From e1e032d254806940f843694dcda04754419893d6 Mon Sep 17 00:00:00 2001 From: OxygenCobalt Date: Tue, 24 May 2022 12:50:18 -0600 Subject: [PATCH] ui: re-add accent customization >api 31 Re-add accent customization on Android 12 and above. Previously, I disabled accent customization since I thought they were more or less useless with the new Material You dynamic colors system. Turns out I severely underestimated how horribly OEMs would botch the dynamic colors system. Guess I was blinded by my adherence to the pixel line. Re-add the accent customization for those who do not have a good dynamic color palette at all. Resolves #131. --- CHANGELOG.md | 4 +- .../java/org/oxycblt/auxio/MainActivity.kt | 34 ++++++++-------- .../oxycblt/auxio/settings/SettingsCompat.kt | 20 +++++++++- .../oxycblt/auxio/settings/SettingsManager.kt | 2 +- .../org/oxycblt/auxio/ui/accent/Accent.kt | 29 ++++++++++---- .../oxycblt/auxio/ui/accent/AccentAdapter.kt | 2 +- .../java/org/oxycblt/auxio/widgets/Forms.kt | 40 ++++++------------- app/src/main/res/layout/widget_tiny.xml | 4 +- app/src/main/res/values-night/colors.xml | 8 ++-- app/src/main/res/values/colors.xml | 8 ++-- app/src/main/res/values/dimens.xml | 1 + app/src/main/res/xml/prefs_main.xml | 3 +- 12 files changed, 87 insertions(+), 68 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 171079194..be7d57f16 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,8 +9,10 @@ - About screen now shows counts for multiple types of library items, alongside a total duration - New disc, track, song count, and duration sorting modes -### What's Improved +#### What's Improved +- Re-enabled theme customization on Android 12 - The tab selector now hides itself when there is only one tab +- Added more buttons to the smallest widget form #### What's Fixed - Fixed incorrect ellipsizing on song items diff --git a/app/src/main/java/org/oxycblt/auxio/MainActivity.kt b/app/src/main/java/org/oxycblt/auxio/MainActivity.kt index df2ccc292..c70033f28 100644 --- a/app/src/main/java/org/oxycblt/auxio/MainActivity.kt +++ b/app/src/main/java/org/oxycblt/auxio/MainActivity.kt @@ -108,26 +108,24 @@ class MainActivity : AppCompatActivity() { private fun setupTheme() { val settingsManager = SettingsManager.getInstance() - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { - // Android 12, let dynamic colors be our accent and only enable the black theme option - if (isNight && settingsManager.useBlackTheme) { - logD("Applying black theme [dynamic colors]") - setTheme(R.style.Theme_Auxio_Black) - } - } else { - // Below android 12, load the accent and enable theme customization + // Disable theme customization above Android 12, as it's far enough in as a version to + // the point where most phones should have an automatic option for light/dark theming. + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) { AppCompatDelegate.setDefaultNightMode(settingsManager.theme) - val accent = settingsManager.accent + } else { + AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM) + } - // The black theme has a completely separate set of styles since style attributes cannot - // be modified at runtime. - if (isNight && settingsManager.useBlackTheme) { - logD("Applying black theme [accent $accent]") - setTheme(accent.blackTheme) - } else { - logD("Applying normal theme [accent $accent]") - setTheme(accent.theme) - } + val accent = settingsManager.accent + + // The black theme has a completely separate set of styles since style attributes cannot + // be modified at runtime. + if (isNight && settingsManager.useBlackTheme) { + logD("Applying black theme [accent $accent]") + setTheme(accent.blackTheme) + } else { + logD("Applying normal theme [accent $accent]") + setTheme(accent.theme) } } diff --git a/app/src/main/java/org/oxycblt/auxio/settings/SettingsCompat.kt b/app/src/main/java/org/oxycblt/auxio/settings/SettingsCompat.kt index 5237729ef..38d652046 100644 --- a/app/src/main/java/org/oxycblt/auxio/settings/SettingsCompat.kt +++ b/app/src/main/java/org/oxycblt/auxio/settings/SettingsCompat.kt @@ -18,6 +18,7 @@ package org.oxycblt.auxio.settings import android.content.SharedPreferences +import android.os.Build import androidx.core.content.edit import org.oxycblt.auxio.ui.accent.Accent @@ -43,16 +44,33 @@ fun handleAccentCompat(prefs: SharedPreferences): Accent { } prefs.edit { - putInt(SettingsManager.KEY_ACCENT, accent) + putInt(OldKeys.KEY_ACCENT3, accent) remove(OldKeys.KEY_ACCENT2) apply() } } + if (prefs.contains(OldKeys.KEY_ACCENT3)) { + var accent = prefs.getInt(OldKeys.KEY_ACCENT3, 5) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + // Accents were previously frozen as soon as the OS was updated to android twelve, + // as dynamic colors were enabled by default. This is no longer the case, so we need + // to re-update the setting to dynamic colors here. + accent = 16 + } + + prefs.edit { + putInt(SettingsManager.KEY_ACCENT, accent) + remove(OldKeys.KEY_ACCENT3) + apply() + } + } + return Accent(prefs.getInt(SettingsManager.KEY_ACCENT, 5)) } /** Cache of the old keys used in Auxio. */ private object OldKeys { const val KEY_ACCENT2 = "KEY_ACCENT2" + const val KEY_ACCENT3 = "auxio_accent" } diff --git a/app/src/main/java/org/oxycblt/auxio/settings/SettingsManager.kt b/app/src/main/java/org/oxycblt/auxio/settings/SettingsManager.kt index 11ed1ae4e..ac8251a10 100644 --- a/app/src/main/java/org/oxycblt/auxio/settings/SettingsManager.kt +++ b/app/src/main/java/org/oxycblt/auxio/settings/SettingsManager.kt @@ -279,7 +279,7 @@ class SettingsManager private constructor(context: Context) : // with auxio_. const val KEY_THEME = "KEY_THEME2" const val KEY_BLACK_THEME = "KEY_BLACK_THEME" - const val KEY_ACCENT = "auxio_accent" + const val KEY_ACCENT = "auxio_accent2" const val KEY_LIB_TABS = "auxio_lib_tabs" const val KEY_SHOW_COVERS = "KEY_SHOW_COVERS" diff --git a/app/src/main/java/org/oxycblt/auxio/ui/accent/Accent.kt b/app/src/main/java/org/oxycblt/auxio/ui/accent/Accent.kt index 3938b8745..ac44ebe0f 100644 --- a/app/src/main/java/org/oxycblt/auxio/ui/accent/Accent.kt +++ b/app/src/main/java/org/oxycblt/auxio/ui/accent/Accent.kt @@ -17,13 +17,14 @@ package org.oxycblt.auxio.ui.accent +import android.os.Build import org.oxycblt.auxio.R val ACCENT_COUNT: Int get() = ACCENT_NAMES.size private val ACCENT_NAMES = - arrayOf( + intArrayOf( R.string.clr_red, R.string.clr_pink, R.string.clr_purple, @@ -40,10 +41,10 @@ private val ACCENT_NAMES = R.string.clr_orange, R.string.clr_brown, R.string.clr_grey, - ) + R.string.clr_dynamic) private val ACCENT_THEMES = - arrayOf( + intArrayOf( R.style.Theme_Auxio_Red, R.style.Theme_Auxio_Pink, R.style.Theme_Auxio_Purple, @@ -60,10 +61,11 @@ private val ACCENT_THEMES = R.style.Theme_Auxio_Orange, R.style.Theme_Auxio_Brown, R.style.Theme_Auxio_Grey, - ) + R.style.Theme_Auxio_App // Dynamic colors are on the base theme + ) private val ACCENT_BLACK_THEMES = - arrayOf( + intArrayOf( R.style.Theme_Auxio_Black_Red, R.style.Theme_Auxio_Black_Pink, R.style.Theme_Auxio_Black_Purple, @@ -80,10 +82,11 @@ private val ACCENT_BLACK_THEMES = R.style.Theme_Auxio_Black_Orange, R.style.Theme_Auxio_Black_Brown, R.style.Theme_Auxio_Black_Grey, - ) + R.style.Theme_Auxio_Black // Dynamic colors are on the base theme + ) private val ACCENT_PRIMARY_COLORS = - arrayOf( + intArrayOf( R.color.red_primary, R.color.pink_primary, R.color.purple_primary, @@ -100,7 +103,7 @@ private val ACCENT_PRIMARY_COLORS = R.color.orange_primary, R.color.brown_primary, R.color.grey_primary, - ) + R.color.dynamic_primary) /** * The data object for an accent. In the UI this is known as a "Color Scheme." This can be nominally @@ -122,4 +125,14 @@ data class Accent(val index: Int) { get() = ACCENT_BLACK_THEMES[index] val primary: Int get() = ACCENT_PRIMARY_COLORS[index] + + companion object { + val MAX = + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + ACCENT_THEMES.size + } else { + // Disable the option for a dynamic accent + ACCENT_THEMES.size - 1 + } + } } diff --git a/app/src/main/java/org/oxycblt/auxio/ui/accent/AccentAdapter.kt b/app/src/main/java/org/oxycblt/auxio/ui/accent/AccentAdapter.kt index 0243fd0c9..684928e37 100644 --- a/app/src/main/java/org/oxycblt/auxio/ui/accent/AccentAdapter.kt +++ b/app/src/main/java/org/oxycblt/auxio/ui/accent/AccentAdapter.kt @@ -65,7 +65,7 @@ class AccentAdapter(listener: Listener) : class AccentData : BackingData() { override fun getItem(position: Int) = Accent(position) - override fun getItemCount() = ACCENT_COUNT + override fun getItemCount() = Accent.MAX } } diff --git a/app/src/main/java/org/oxycblt/auxio/widgets/Forms.kt b/app/src/main/java/org/oxycblt/auxio/widgets/Forms.kt index 9f11ad3ca..20c5321ea 100644 --- a/app/src/main/java/org/oxycblt/auxio/widgets/Forms.kt +++ b/app/src/main/java/org/oxycblt/auxio/widgets/Forms.kt @@ -30,54 +30,47 @@ import org.oxycblt.auxio.util.newMainIntent * The default widget is displayed whenever there is no music playing. It just shows the message "No * music playing". */ -fun createDefaultWidget(context: Context): RemoteViews { - return createViews(context, R.layout.widget_default) -} +fun createDefaultWidget(context: Context) = createViews(context, R.layout.widget_default) /** * The tiny widget is for an edge-case situation where a widget falls under the size class of the * small widget, either via landscape mode or exceptionally small screens. */ -fun createTinyWidget(context: Context, state: WidgetComponent.WidgetState): RemoteViews { - return createViews(context, R.layout.widget_tiny) +fun createTinyWidget(context: Context, state: WidgetComponent.WidgetState) = + createViews(context, R.layout.widget_tiny) .applyMeta(context, state) .applyBasicControls(context, state) -} /** * The small widget is for 2x2 widgets and just shows the cover art and playback controls. This is * generally because a Medium widget is too large for this widget size and a text-only widget is too * small for this widget size. */ -fun createSmallWidget(context: Context, state: WidgetComponent.WidgetState): RemoteViews { - return createViews(context, R.layout.widget_small) +fun createSmallWidget(context: Context, state: WidgetComponent.WidgetState) = + createViews(context, R.layout.widget_small) .applyCover(context, state) .applyBasicControls(context, state) -} /** * The medium widget is for 2x3 widgets and shows the cover art, title/artist, and three controls. * This is the default widget configuration. */ -fun createMediumWidget(context: Context, state: WidgetComponent.WidgetState): RemoteViews { - return createViews(context, R.layout.widget_medium) +fun createMediumWidget(context: Context, state: WidgetComponent.WidgetState) = + createViews(context, R.layout.widget_medium) .applyMeta(context, state) .applyBasicControls(context, state) -} /** The wide widget is for Nx2 widgets and is like the small widget but with more controls. */ -fun createWideWidget(context: Context, state: WidgetComponent.WidgetState): RemoteViews { - return createViews(context, R.layout.widget_wide) +fun createWideWidget(context: Context, state: WidgetComponent.WidgetState) = + createViews(context, R.layout.widget_wide) .applyCover(context, state) .applyFullControls(context, state) -} /** The large widget is for 3x4 widgets and shows all metadata and controls. */ -fun createLargeWidget(context: Context, state: WidgetComponent.WidgetState): RemoteViews { - return createViews(context, R.layout.widget_large) +fun createLargeWidget(context: Context, state: WidgetComponent.WidgetState): RemoteViews = + createViews(context, R.layout.widget_large) .applyMeta(context, state) .applyFullControls(context, state) -} private fun createViews(context: Context, @LayoutRes layout: Int): RemoteViews { val views = RemoteViews(context.packageName, layout) @@ -114,7 +107,7 @@ private fun RemoteViews.applyCover( return this } -private fun RemoteViews.applyPlayControls( +private fun RemoteViews.applyBasicControls( context: Context, state: WidgetComponent.WidgetState ): RemoteViews { @@ -129,15 +122,6 @@ private fun RemoteViews.applyPlayControls( R.drawable.ic_play }) - return this -} - -private fun RemoteViews.applyBasicControls( - context: Context, - state: WidgetComponent.WidgetState -): RemoteViews { - applyPlayControls(context, state) - setOnClickPendingIntent( R.id.widget_skip_prev, context.newBroadcastIntent(PlaybackService.ACTION_SKIP_PREV)) diff --git a/app/src/main/res/layout/widget_tiny.xml b/app/src/main/res/layout/widget_tiny.xml index 5b1cc15ff..2aa3a0b35 100644 --- a/app/src/main/res/layout/widget_tiny.xml +++ b/app/src/main/res/layout/widget_tiny.xml @@ -17,8 +17,8 @@ #01151515 + @color/material_dynamic_secondary20 + @color/material_dynamic_neutral90 + @color/material_dynamic_neutral20 + #FFB4A8 #680001 #940002 @@ -387,7 +391,5 @@ #fafafa #2D3132 - @color/material_dynamic_secondary20 - @color/material_dynamic_neutral90 - @color/material_dynamic_neutral20 + @color/m3_ref_palette_dynamic_primary80 \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 63835acba..2c5ab5d8b 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -5,6 +5,10 @@ #80000000 #80ffffff + @color/material_dynamic_primary95 + @color/material_dynamic_neutral80 + @color/material_dynamic_neutral95 + #BC1714 #FFFFFF #FFDAD3 @@ -389,7 +393,5 @@ #1f1f1f #F0F0F0 - @color/material_dynamic_primary95 - @color/material_dynamic_neutral80 - @color/material_dynamic_neutral95 + @color/m3_ref_palette_dynamic_primary40 \ No newline at end of file diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 0db474ae6..883792cd1 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -14,6 +14,7 @@ 48dp 56dp + 88dp 128dp 192dp 256dp diff --git a/app/src/main/res/xml/prefs_main.xml b/app/src/main/res/xml/prefs_main.xml index e7318e88f..28cdee259 100644 --- a/app/src/main/res/xml/prefs_main.xml +++ b/app/src/main/res/xml/prefs_main.xml @@ -16,8 +16,7 @@