diff --git a/app/src/main/java/org/oxycblt/auxio/library/LibraryFragment.kt b/app/src/main/java/org/oxycblt/auxio/library/LibraryFragment.kt index dc638c079..61a9dd550 100644 --- a/app/src/main/java/org/oxycblt/auxio/library/LibraryFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/library/LibraryFragment.kt @@ -4,7 +4,6 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import androidx.core.view.forEach import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels import androidx.navigation.fragment.findNavController @@ -20,13 +19,9 @@ import org.oxycblt.auxio.music.BaseModel import org.oxycblt.auxio.music.Genre import org.oxycblt.auxio.music.Song import org.oxycblt.auxio.ui.ActionMenu -import org.oxycblt.auxio.ui.accent -import org.oxycblt.auxio.ui.applyColor import org.oxycblt.auxio.ui.getLandscapeSpans import org.oxycblt.auxio.ui.isLandscape import org.oxycblt.auxio.ui.requireCompatActivity -import org.oxycblt.auxio.ui.resolveAttr -import org.oxycblt.auxio.ui.toColor /** * A [Fragment] that shows a custom list of [Genre], [Artist], or [Album] data. Also allows for @@ -47,16 +42,17 @@ class LibraryFragment : Fragment() { ActionMenu(requireCompatActivity(), view, data, ActionMenu.FLAG_NONE) } - val sortAction = binding.libraryToolbar.menu.findItem(R.id.submenu_sorting) - // --- UI SETUP --- binding.libraryToolbar.apply { + menu.findItem(libraryModel.sortMode.toMenuId()).isChecked = true + setOnMenuItemClickListener { when (it.itemId) { R.id.submenu_sorting -> {} else -> { + it.isChecked = true libraryModel.updateSortMode(it.itemId) } } @@ -80,22 +76,6 @@ class LibraryFragment : Fragment() { libraryAdapter.updateData(it) } - libraryModel.sortMode.observe(viewLifecycleOwner) { mode -> - logD("Updating sort mode to $mode") - - val modeId = mode.toMenuId() - - // Highlight the item instead of using a checkable since the checkables just...wont - // respond to any attempts to make them checked or not. - sortAction.subMenu.forEach { - if (it.itemId == modeId) { - it.applyColor(accent.first.toColor(requireContext())) - } else { - it.applyColor(resolveAttr(requireContext(), android.R.attr.textColorPrimary)) - } - } - } - detailModel.navToItem.observe(viewLifecycleOwner) { if (it != null) { libraryModel.updateNavigationStatus(false) diff --git a/app/src/main/java/org/oxycblt/auxio/library/LibraryViewModel.kt b/app/src/main/java/org/oxycblt/auxio/library/LibraryViewModel.kt index 6cac73585..45a1a836f 100644 --- a/app/src/main/java/org/oxycblt/auxio/library/LibraryViewModel.kt +++ b/app/src/main/java/org/oxycblt/auxio/library/LibraryViewModel.kt @@ -17,15 +17,15 @@ import org.oxycblt.auxio.settings.SettingsManager * @author OxygenCobalt */ class LibraryViewModel : ViewModel(), SettingsManager.Callback { - private val mSortMode = MutableLiveData(SortMode.ALPHA_DOWN) - val sortMode: LiveData get() = mSortMode - private val mLibraryData = MutableLiveData(listOf()) val libraryData: LiveData> get() = mLibraryData private var mIsNavigating = false val isNavigating: Boolean get() = mIsNavigating + private var mSortMode = SortMode.ALPHA_DOWN + val sortMode: SortMode get() = mSortMode + private var mDisplayMode = DisplayMode.SHOW_ARTISTS private val settingsManager = SettingsManager.getInstance() @@ -36,7 +36,7 @@ class LibraryViewModel : ViewModel(), SettingsManager.Callback { // Set up the display/sort modes mDisplayMode = settingsManager.libraryDisplayMode - mSortMode.value = settingsManager.librarySortMode + mSortMode = settingsManager.librarySortMode updateLibraryData() } @@ -54,8 +54,8 @@ class LibraryViewModel : ViewModel(), SettingsManager.Callback { else -> SortMode.NONE } - if (mode != mSortMode.value) { - mSortMode.value = mode + if (mode != mSortMode) { + mSortMode = mode settingsManager.librarySortMode = mode updateLibraryData() @@ -92,15 +92,15 @@ class LibraryViewModel : ViewModel(), SettingsManager.Callback { private fun updateLibraryData() { mLibraryData.value = when (mDisplayMode) { DisplayMode.SHOW_GENRES -> { - mSortMode.value!!.getSortedGenreList(musicStore.genres) + mSortMode.getSortedGenreList(musicStore.genres) } DisplayMode.SHOW_ARTISTS -> { - mSortMode.value!!.getSortedBaseModelList(musicStore.artists) + mSortMode.getSortedBaseModelList(musicStore.artists) } DisplayMode.SHOW_ALBUMS -> { - mSortMode.value!!.getSortedAlbumList(musicStore.albums) + mSortMode.getSortedAlbumList(musicStore.albums) } else -> error("DisplayMode $mDisplayMode is unsupported.") diff --git a/app/src/main/java/org/oxycblt/auxio/search/SearchFragment.kt b/app/src/main/java/org/oxycblt/auxio/search/SearchFragment.kt index d466aae8d..5a69bcb1b 100644 --- a/app/src/main/java/org/oxycblt/auxio/search/SearchFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/search/SearchFragment.kt @@ -34,7 +34,6 @@ import org.oxycblt.auxio.ui.toColor /** * A [Fragment] that allows for the searching of the entire music library. * TODO: Add "Recent Searches" & No Results indicator - * TODO: Filtering * @author OxygenCobalt */ class SearchFragment : Fragment() { diff --git a/app/src/main/java/org/oxycblt/auxio/ui/EdgeUtils.kt b/app/src/main/java/org/oxycblt/auxio/ui/EdgeUtils.kt deleted file mode 100644 index 395499050..000000000 --- a/app/src/main/java/org/oxycblt/auxio/ui/EdgeUtils.kt +++ /dev/null @@ -1,64 +0,0 @@ -@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.graphics.Point -import android.os.Build -import android.util.DisplayMetrics -import android.view.WindowManager - -/** - * 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. - * @return True if we are in the irregular landscape mode, false if not. - */ -fun Activity.isIrregularLandscape(): Boolean { - return isLandscape(resources) && - !isSystemBarOnBottom(this) -} - -/** - * Check if edge is on. Really a glorified version check. - * @return Whether edge is on. - */ -fun isEdgeOn(): Boolean = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1 - -/** - * 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) -} 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 734277ecb..7aadd90ec 100644 --- a/app/src/main/java/org/oxycblt/auxio/ui/InterfaceUtils.kt +++ b/app/src/main/java/org/oxycblt/auxio/ui/InterfaceUtils.kt @@ -1,13 +1,18 @@ package org.oxycblt.auxio.ui +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.WindowManager import android.widget.ImageButton import android.widget.TextView import android.widget.Toast @@ -20,16 +25,7 @@ import androidx.fragment.app.Fragment import com.google.android.material.button.MaterialButton import org.oxycblt.auxio.R -/** - * Apply a text color to a [MenuItem] - * @param color The text color that should be applied. - */ -fun MenuItem.applyColor(@ColorInt color: Int) { - SpannableString(title).apply { - setSpan(ForegroundColorSpan(color), 0, length, SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE) - title = this - } -} +// --- VIEW CONFIGURATION --- /** * Disable an image button. @@ -44,40 +40,6 @@ fun ImageButton.disable() { } } -/** - * Determine if the device is currently in landscape. - * @param resources [Resources] required - */ -fun isLandscape(resources: Resources): Boolean { - return resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE -} - -/** - * Get the span count for most RecyclerViews when in landscape mode. - * @return 3 if landscape mode is tablet, 2 if landscape mode is phone - */ -fun getLandscapeSpans(resources: Resources): Int { - return if (resources.configuration.screenLayout == Configuration.SCREENLAYOUT_SIZE_LARGE) 3 else 2 -} - -/** - * Create a [Toast] from a [String] - * @param context [Context] required to create the toast - */ -fun String.createToast(context: Context) { - Toast.makeText(context.applicationContext, this, Toast.LENGTH_SHORT).show() -} - -/** - * "Render" a [Spanned] using [HtmlCompat]. - * @return A [Spanned] that actually works. - */ -fun Spanned.render(): Spanned { - return HtmlCompat.fromHtml( - this.toString(), HtmlCompat.FROM_HTML_OPTION_USE_CSS_COLORS - ) -} - /** * Set a [TextView] text color, without having to resolve the resource. */ @@ -100,6 +62,26 @@ fun MaterialButton.applyAccents(highlighted: Boolean) { } } +// --- CONVENIENCE --- + +/** + * Convenience method for getting a plural. + * @param pluralsRes Resource for the plural + * @param value Int value for the plural. + * @return The formatted string requested + */ +fun Context.getPlural(@PluralsRes pluralsRes: Int, value: Int): String { + return resources.getQuantityString(pluralsRes, value, value) +} + +/** + * Create a [Toast] from a [String] + * @param context [Context] required to create the toast + */ +fun String.createToast(context: Context) { + Toast.makeText(context.applicationContext, this, Toast.LENGTH_SHORT).show() +} + /** * Require an [AppCompatActivity] */ @@ -114,11 +96,81 @@ fun Fragment.requireCompatActivity(): AppCompatActivity { } /** - * Convenience method for getting a plural. - * @param pluralsRes Resource for the plural - * @param value Int value for the plural. - * @return The formatted string requested + * "Render" a [Spanned] using [HtmlCompat]. + * @return A [Spanned] that actually works. */ -fun Context.getPlural(@PluralsRes pluralsRes: Int, value: Int): String { - return resources.getQuantityString(pluralsRes, value, value) +fun Spanned.render(): Spanned { + return HtmlCompat.fromHtml( + this.toString(), HtmlCompat.FROM_HTML_OPTION_USE_CSS_COLORS + ) +} + +// --- CONFIGURATION --- + +/** + * Check if edge is on. Really a glorified version check. + * @return Whether edge is on. + */ +fun isEdgeOn(): Boolean = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1 + +/** + * Determine if the device is currently in landscape. + * @param resources [Resources] required + */ +fun isLandscape(resources: Resources): Boolean { + return resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE +} + +/** + * Get the span count for most RecyclerViews when in landscape mode. + * @return 3 if landscape mode is tablet, 2 if landscape mode is phone + */ +fun getLandscapeSpans(resources: Resources): Int { + return if (resources.configuration.screenLayout == Configuration.SCREENLAYOUT_SIZE_LARGE) 3 else 2 +} + +/** + * 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. + * @return True if we are in the irregular landscape mode, false if not. + */ +fun Activity.isIrregularLandscape(): Boolean { + return 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) } diff --git a/app/src/main/res/menu/menu_library.xml b/app/src/main/res/menu/menu_library.xml index 66db7ebd9..02e6f3eb0 100644 --- a/app/src/main/res/menu/menu_library.xml +++ b/app/src/main/res/menu/menu_library.xml @@ -13,7 +13,8 @@ android:title="@string/label_sort" app:showAsAction="always"> - +