From 71cd15bbf7cb7a168e37abe3226c9deb112e0f1d Mon Sep 17 00:00:00 2001 From: OxygenCobalt Date: Wed, 16 Dec 2020 16:56:26 -0700 Subject: [PATCH] Fix bugs Fix bugs with playback & edge-to-edge. --- .../java/org/oxycblt/auxio/MainActivity.kt | 2 - .../auxio/playback/PlaybackFragment.kt | 11 ++- .../auxio/playback/queue/QueueAdapter.kt | 14 ++- .../auxio/playback/queue/QueueFragment.kt | 24 +---- .../playback/state/PlaybackStateManager.kt | 10 +- .../java/org/oxycblt/auxio/ui/EdgeUtils.kt | 95 +++++++++++++++++++ .../org/oxycblt/auxio/ui/InterfaceUtils.kt | 87 ----------------- .../res/layout-land/fragment_album_detail.xml | 4 +- .../layout-land/fragment_artist_detail.xml | 2 +- .../res/layout-land/fragment_genre_detail.xml | 2 +- .../res/layout-land/fragment_playback.xml | 40 +++++--- app/src/main/res/layout/fragment_playback.xml | 3 +- app/src/main/res/values/dimens.xml | 2 +- 13 files changed, 156 insertions(+), 140 deletions(-) create mode 100644 app/src/main/java/org/oxycblt/auxio/ui/EdgeUtils.kt diff --git a/app/src/main/java/org/oxycblt/auxio/MainActivity.kt b/app/src/main/java/org/oxycblt/auxio/MainActivity.kt index 0f80f898e..fd4d28bd7 100644 --- a/app/src/main/java/org/oxycblt/auxio/MainActivity.kt +++ b/app/src/main/java/org/oxycblt/auxio/MainActivity.kt @@ -53,8 +53,6 @@ class MainActivity : AppCompatActivity() { @Suppress("DEPRECATION") private fun doEdgeToEdgeSetup(binding: ActivityMainBinding) { - // TODO: Add landscape edge-to-edge support - window?.apply { statusBarColor = Color.TRANSPARENT diff --git a/app/src/main/java/org/oxycblt/auxio/playback/PlaybackFragment.kt b/app/src/main/java/org/oxycblt/auxio/playback/PlaybackFragment.kt index 161e9a68e..45bce8776 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/PlaybackFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/PlaybackFragment.kt @@ -8,6 +8,7 @@ import android.view.MenuItem import android.view.View import android.view.ViewGroup import android.widget.SeekBar +import android.widget.TextView import androidx.core.content.ContextCompat import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels @@ -84,8 +85,7 @@ class PlaybackFragment : Fragment(), SeekBar.OnSeekBarChangeListener { } // Make ellipsizing of song title work - // Disabled until I can figure out why marquee causes a memory leak. - // binding.playbackSong.isSelected = true + binding.playbackSong.isSelected = true binding.playbackSeekBar.setOnSeekBarChangeListener(this) @@ -200,6 +200,13 @@ class PlaybackFragment : Fragment(), SeekBar.OnSeekBarChangeListener { return binding.root } + override fun onStop() { + super.onStop() + + // Stop the marqueeing of the song name to prevent a weird memory leak + requireView().findViewById(R.id.playback_song).isSelected = false + } + // Seeking callbacks override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) { if (fromUser) { diff --git a/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueAdapter.kt b/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueAdapter.kt index 82a69d5d9..190c735a0 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueAdapter.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueAdapter.kt @@ -15,6 +15,7 @@ import org.oxycblt.auxio.logE import org.oxycblt.auxio.music.BaseModel import org.oxycblt.auxio.music.Header import org.oxycblt.auxio.music.Song +import org.oxycblt.auxio.playback.PlaybackViewModel import org.oxycblt.auxio.recycler.DiffCallback import org.oxycblt.auxio.recycler.viewholders.BaseViewHolder import org.oxycblt.auxio.recycler.viewholders.HeaderViewHolder @@ -29,7 +30,7 @@ import org.oxycblt.auxio.recycler.viewholders.HeaderViewHolder */ class QueueAdapter( private val touchHelper: ItemTouchHelper, - private val onHeaderAction: () -> Unit + private val playbackModel: PlaybackViewModel, ) : RecyclerView.Adapter() { private var data = mutableListOf() private var listDiffer = AsyncListDiffer(this, DiffCallback()) @@ -51,12 +52,15 @@ class QueueAdapter( override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { return when (viewType) { HeaderViewHolder.ITEM_TYPE -> HeaderViewHolder.from(parent.context) - QUEUE_ITEM_TYPE -> QueueSongViewHolder( - ItemQueueSongBinding.inflate(LayoutInflater.from(parent.context)) - ) + USER_QUEUE_HEADER_ITEM_TYPE -> UserQueueHeaderViewHolder( parent.context, ItemActionHeaderBinding.inflate(LayoutInflater.from(parent.context)) ) + + QUEUE_ITEM_TYPE -> QueueSongViewHolder( + ItemQueueSongBinding.inflate(LayoutInflater.from(parent.context)) + ) + else -> error("Someone messed with the ViewHolder item types.") } } @@ -159,7 +163,7 @@ class QueueAdapter( setImageResource(R.drawable.ic_clear) setOnClickListener { - onHeaderAction() + playbackModel.clearUserQueue() } } } diff --git a/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueFragment.kt b/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueFragment.kt index bc636235d..0f4f739d3 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueFragment.kt @@ -17,9 +17,7 @@ import org.oxycblt.auxio.music.BaseModel import org.oxycblt.auxio.music.Header import org.oxycblt.auxio.playback.PlaybackViewModel import org.oxycblt.auxio.playback.state.PlaybackMode -import org.oxycblt.auxio.settings.SettingsManager -import org.oxycblt.auxio.ui.isLandscape -import org.oxycblt.auxio.ui.isSystemBarOnBottom +import org.oxycblt.auxio.ui.isInIrregularLandscapeMode /** * A [Fragment] that contains both the user queue and the next queue, with the ability to @@ -38,34 +36,20 @@ class QueueFragment : Fragment() { ): View { val binding = FragmentQueueBinding.inflate(inflater) - val settingsManager = SettingsManager.getInstance() val callback = QueueDragCallback(playbackModel) val helper = ItemTouchHelper(callback) - val queueAdapter = QueueAdapter(helper) { - playbackModel.clearUserQueue() - } + val queueAdapter = QueueAdapter(helper, playbackModel) callback.addQueueAdapter(queueAdapter) // --- UI SETUP --- - // Band-aid that fixes a bug with landscape edge-to-edge where the queue drag buttons - // will be behind the status bar. - if (settingsManager.edgeEnabled) { - if (isLandscape(resources) && !isSystemBarOnBottom(requireActivity())) { - binding.root.rootView.fitsSystemWindows = true - } - } - binding.queueToolbar.apply { setNavigationOnClickListener { findNavController().navigateUp() } - // Since QueueFragment doesn't fit system windows, inset padding needs to be - // artificially applied to the Toolbar so that it fits on the main window AND - // so that the elevation doesn't show on the top. - if (!binding.root.rootView.fitsSystemWindows) { + if (!requireActivity().isInIrregularLandscapeMode()) { setOnApplyWindowInsetsListener @Suppress("DEPRECATION") { _, insets -> val top = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { insets.getInsets(WindowInsets.Type.systemBars()).top @@ -79,6 +63,8 @@ class QueueFragment : Fragment() { insets } + } else { + binding.root.fitsSystemWindows = true } } diff --git a/app/src/main/java/org/oxycblt/auxio/playback/state/PlaybackStateManager.kt b/app/src/main/java/org/oxycblt/auxio/playback/state/PlaybackStateManager.kt index 6d9657b7b..a143690fc 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/state/PlaybackStateManager.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/state/PlaybackStateManager.kt @@ -430,6 +430,8 @@ class PlaybackStateManager private constructor() { logD("Shuffling queue with seed $newSeed") + val lastSong = mQueue[mIndex] + mShuffleSeed = newSeed mQueue.shuffle(Random(newSeed)) @@ -437,9 +439,7 @@ class PlaybackStateManager private constructor() { // If specified, make the current song the first member of the queue. if (keepSong) { - mSong?.let { - moveQueueItems(mQueue.indexOf(it), 0) - } + moveQueueItems(mQueue.indexOf(lastSong), 0) } else { // Otherwise, just start from the zeroth position in the queue. mSong = mQueue[0] @@ -452,9 +452,11 @@ class PlaybackStateManager private constructor() { private fun resetShuffle() { mShuffleSeed = -1L + val lastSong = mQueue[mIndex] + setupOrderedQueue() - mIndex = mQueue.indexOf(mSong) + mIndex = mQueue.indexOf(lastSong) forceQueueUpdate() } diff --git a/app/src/main/java/org/oxycblt/auxio/ui/EdgeUtils.kt b/app/src/main/java/org/oxycblt/auxio/ui/EdgeUtils.kt new file mode 100644 index 000000000..c3ef8ddc8 --- /dev/null +++ b/app/src/main/java/org/oxycblt/auxio/ui/EdgeUtils.kt @@ -0,0 +1,95 @@ +@file:Suppress("DEPRECATION") +@file:TargetApi(Build.VERSION_CODES.O_MR1) + +package org.oxycblt.auxio.ui + +import android.annotation.TargetApi +import android.app.Activity +import android.content.Context +import android.content.res.Configuration +import android.graphics.Point +import android.os.Build +import android.util.DisplayMetrics +import android.view.View +import android.view.Window +import android.view.WindowInsetsController +import android.view.WindowManager +import org.oxycblt.auxio.settings.SettingsManager + +/** + * Check if we are in the "Irregular" landscape mode [e.g landscape, but nav bar is on the sides] + * Used to disable most of edge-to-edge if that's the case, as I cant get it to work on this mode yet. + * TODO: Make edge-to-edge work in irregular mode + * @return True if we are in the irregular landscape mode, false if not. + */ +fun Activity.isInIrregularLandscapeMode(): Boolean { + return SettingsManager.getInstance().edgeEnabled && + isLandscape(resources) && + !isSystemBarOnBottom(this) +} + +/** + * Check if the system bars are on the bottom. + * @return If the system bars are on the bottom, false if no. + */ +private fun isSystemBarOnBottom(activity: Activity): Boolean { + val realPoint = Point() + val metrics = DisplayMetrics() + + var width = 0 + var height = 0 + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + activity.display?.let { display -> + display.getRealSize(realPoint) + + activity.windowManager.currentWindowMetrics.bounds.also { + width = it.width() + height = it.height() + } + } + } else { + (activity.getSystemService(Context.WINDOW_SERVICE) as WindowManager).apply { + defaultDisplay.getRealSize(realPoint) + defaultDisplay.getMetrics(metrics) + + width = metrics.widthPixels + height = metrics.heightPixels + } + } + + val config = activity.resources.configuration + val canMove = (width != height && config.smallestScreenWidthDp < 600) + + return (!canMove || width < height) +} + +/** + * Handle transparent system bars. Adapted from Music Player GO + * (https://github.com/enricocid/Music-Player-GO) + */ +fun Window.handleTransparentSystemBars(config: Configuration) { + fun isNight() = config.uiMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + insetsController?.let { controller -> + val appearance = WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS or + WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS + + val mask = if (isNight()) 0 else appearance + + controller.setSystemBarsAppearance(appearance, mask) + } + } else { + val flags = decorView.systemUiVisibility + + decorView.systemUiVisibility = + if (isNight()) { + flags and View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.inv() and + View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR.inv() + } else { + flags or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR or + View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR + } + } +} diff --git a/app/src/main/java/org/oxycblt/auxio/ui/InterfaceUtils.kt b/app/src/main/java/org/oxycblt/auxio/ui/InterfaceUtils.kt index c1028a744..5e587928a 100644 --- a/app/src/main/java/org/oxycblt/auxio/ui/InterfaceUtils.kt +++ b/app/src/main/java/org/oxycblt/auxio/ui/InterfaceUtils.kt @@ -1,22 +1,13 @@ package org.oxycblt.auxio.ui -import android.annotation.TargetApi -import android.app.Activity import android.content.Context import android.content.res.ColorStateList import android.content.res.Configuration import android.content.res.Resources -import android.graphics.Point -import android.os.Build import android.text.SpannableString import android.text.Spanned import android.text.style.ForegroundColorSpan -import android.util.DisplayMetrics import android.view.MenuItem -import android.view.View -import android.view.Window -import android.view.WindowInsetsController -import android.view.WindowManager import android.widget.ImageButton import android.widget.Toast import androidx.annotation.ColorInt @@ -33,15 +24,6 @@ import org.oxycblt.auxio.playback.PlaybackViewModel import org.oxycblt.auxio.playback.state.PlaybackMode import org.oxycblt.auxio.settings.SettingsManager -// Functions for managing UI elements [Not Colors] - -object InterfaceUtils { - const val NAV_HIDDEN = -1 - const val NAV_ON_LEFT = 0 - const val NAV_ON_RIGHT = 1 - const val NAV_ON_BOTTOM = 2 -} - /** * Apply a text color to a [MenuItem] * @param color The text color that should be applied. @@ -92,75 +74,6 @@ fun Spanned.render(): Spanned { ) } -/** - * Check if the system bars are on the bottom. - * @return If the system bars are on the bottom, false if no. - */ -@Suppress("DEPRECATION") -fun isSystemBarOnBottom(activity: Activity): Boolean { - val realPoint = Point() - val metrics = DisplayMetrics() - - var width = 0 - var height = 0 - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { - activity.display?.let { display -> - display.getRealSize(realPoint) - - activity.windowManager.currentWindowMetrics.bounds.also { - width = it.width() - height = it.height() - } - } - } else { - (activity.getSystemService(Context.WINDOW_SERVICE) as WindowManager).apply { - defaultDisplay.getRealSize(realPoint) - defaultDisplay.getMetrics(metrics) - - width = metrics.widthPixels - height = metrics.heightPixels - } - } - - val config = activity.resources.configuration - val canMove = (width != height && config.smallestScreenWidthDp < 600) - - return (!canMove || width < height) -} - -/** - * Handle transparent system bars. Adapted from Music Player GO - * (https://github.com/enricocid/Music-Player-GO) - */ -@TargetApi(Build.VERSION_CODES.O_MR1) -@Suppress("DEPRECATION") -fun Window.handleTransparentSystemBars(config: Configuration) { - fun isNight() = config.uiMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { - insetsController?.let { controller -> - val appearance = WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS or - WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS - - val mask = if (isNight()) 0 else appearance - - controller.setSystemBarsAppearance(appearance, mask) - } - } else { - val flags = decorView.systemUiVisibility - - decorView.systemUiVisibility = - if (isNight()) { - flags and View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.inv() and - View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR.inv() - } else { - flags or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR or - View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR - } - } -} - /** * Show actions for a song item, such as the ones found in [org.oxycblt.auxio.songs.SongsFragment] */ diff --git a/app/src/main/res/layout-land/fragment_album_detail.xml b/app/src/main/res/layout-land/fragment_album_detail.xml index 149e14053..b1eadc698 100644 --- a/app/src/main/res/layout-land/fragment_album_detail.xml +++ b/app/src/main/res/layout-land/fragment_album_detail.xml @@ -126,11 +126,11 @@ android:nestedScrollingEnabled="false" android:overScrollMode="never" app:layoutManager="androidx.recyclerview.widget.GridLayoutManager" - app:spanCount="2" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/album_song_header" - tools:itemCount="4" + app:spanCount="2" + tools:itemCount="6" tools:listitem="@layout/item_album_song" /> diff --git a/app/src/main/res/layout-land/fragment_artist_detail.xml b/app/src/main/res/layout-land/fragment_artist_detail.xml index 03e1ccefe..f14eb0167 100644 --- a/app/src/main/res/layout-land/fragment_artist_detail.xml +++ b/app/src/main/res/layout-land/fragment_artist_detail.xml @@ -120,10 +120,10 @@ android:nestedScrollingEnabled="false" android:overScrollMode="never" app:layoutManager="androidx.recyclerview.widget.GridLayoutManager" - app:spanCount="2" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/artist_album_header" + app:spanCount="2" tools:itemCount="4" tools:listitem="@layout/item_album" /> diff --git a/app/src/main/res/layout-land/fragment_genre_detail.xml b/app/src/main/res/layout-land/fragment_genre_detail.xml index f872109d4..4b586ecf8 100644 --- a/app/src/main/res/layout-land/fragment_genre_detail.xml +++ b/app/src/main/res/layout-land/fragment_genre_detail.xml @@ -121,10 +121,10 @@ android:nestedScrollingEnabled="false" android:overScrollMode="never" app:layoutManager="androidx.recyclerview.widget.GridLayoutManager" - app:spanCount="2" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/genre_artist_header" + app:spanCount="2" tools:itemCount="4" tools:listitem="@layout/item_artist" /> diff --git a/app/src/main/res/layout-land/fragment_playback.xml b/app/src/main/res/layout-land/fragment_playback.xml index c56da987e..e14f0e309 100644 --- a/app/src/main/res/layout-land/fragment_playback.xml +++ b/app/src/main/res/layout-land/fragment_playback.xml @@ -48,25 +48,35 @@ app:layout_constraintTop_toBottomOf="@+id/playback_toolbar" tools:src="@drawable/ic_song" /> - + + + app:layout_constraintVertical_chainStyle="packed"> + + + + diff --git a/app/src/main/res/layout/fragment_playback.xml b/app/src/main/res/layout/fragment_playback.xml index e337ee528..83069b46a 100644 --- a/app/src/main/res/layout/fragment_playback.xml +++ b/app/src/main/res/layout/fragment_playback.xml @@ -56,8 +56,9 @@ android:layout_height="wrap_content" android:layout_marginStart="@dimen/margin_mid_large" android:layout_marginEnd="@dimen/margin_mid_large" - android:ellipsize="end" + android:ellipsize="marquee" android:fontFamily="@font/inter_semibold" + android:marqueeRepeatLimit="marquee_forever" android:onClick="@{() -> playbackModel.navToItem(playbackModel.song)}" android:singleLine="true" android:text="@{song.name}" diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index f171ea2a3..45e3c9be3 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -28,7 +28,7 @@ 44dp 56dp 68dp - 120dp + 130dp 260dp 70dp