Skip to content

Commit 2ba97fe

Browse files
sang765rukamori
andcommitted
feat(theme): backport wallpaper color extraction to API < 31 (rukamori#1219)
Co-authored-by: morieeattonkatsu <107134739+rukamori@users.noreply.github.com>
1 parent 8b90e35 commit 2ba97fe

5 files changed

Lines changed: 61 additions & 2 deletions

File tree

‎app/src/main/kotlin/moe/rukamori/archivetune/MainActivity.kt‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,7 @@ import moe.rukamori.archivetune.constants.AppLanguageKey
192192
import moe.rukamori.archivetune.constants.UseSystemLanguageKey
193193
import moe.rukamori.archivetune.constants.CustomFontUriKey
194194
import moe.rukamori.archivetune.constants.CustomThemeColorKey
195+
import moe.rukamori.archivetune.constants.WallpaperExtractionFailedKey
195196
import moe.rukamori.archivetune.constants.DarkModeKey
196197
import moe.rukamori.archivetune.constants.DefaultOpenTabKey
197198
import moe.rukamori.archivetune.constants.DisableAnimationsKey
@@ -286,6 +287,7 @@ import moe.rukamori.archivetune.ui.theme.ArchiveTuneTheme
286287
import moe.rukamori.archivetune.ui.theme.ColorSaver
287288
import moe.rukamori.archivetune.ui.theme.DefaultThemeColor
288289
import moe.rukamori.archivetune.ui.theme.extractThemeColor
290+
import moe.rukamori.archivetune.ui.theme.extractWallpaperThemeColor
289291
import moe.rukamori.archivetune.ui.utils.appBarScrollBehavior
290292
import moe.rukamori.archivetune.ui.utils.backToMain
291293
import moe.rukamori.archivetune.ui.utils.resetHeightOffset
@@ -833,7 +835,11 @@ class MainActivity : ComponentActivity() {
833835
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
834836
themeColor = DefaultThemeColor
835837
} else {
836-
themeColor = customThemeColor
838+
val wallpaperColor = extractWallpaperThemeColor(this@MainActivity)
839+
themeColor = wallpaperColor ?: customThemeColor
840+
dataStore.edit { prefs ->
841+
prefs[WallpaperExtractionFailedKey] = wallpaperColor == null
842+
}
837843
}
838844
}
839845
}

‎app/src/main/kotlin/moe/rukamori/archivetune/constants/PreferenceKeys.kt‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ val DarkModeKey = stringPreferencesKey("darkMode")
2323
val PureBlackKey = booleanPreferencesKey("pureBlack")
2424
val DisableAnimationsKey = booleanPreferencesKey("disableAnimations")
2525
val ForceHighRefreshRateKey = booleanPreferencesKey("forceHighRefreshRate")
26+
val WallpaperExtractionFailedKey = booleanPreferencesKey("wallpaperExtractionFailed")
2627
val EnableHapticFeedbackKey = booleanPreferencesKey("enableHapticFeedback")
2728
val UseSystemFontKey = booleanPreferencesKey("useSystemFont")
2829
val FontPreferenceKey = stringPreferencesKey("fontPreference")

‎app/src/main/kotlin/moe/rukamori/archivetune/ui/screens/settings/AppearanceSettings.kt‎

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ import moe.rukamori.archivetune.constants.SwipeSensitivityKey
116116
import moe.rukamori.archivetune.constants.SwipeThumbnailKey
117117
import moe.rukamori.archivetune.constants.SwipeToSongKey
118118
import moe.rukamori.archivetune.constants.ThumbnailCornerRadiusKey
119+
import moe.rukamori.archivetune.constants.WallpaperExtractionFailedKey
119120
import moe.rukamori.archivetune.constants.toLibraryFilterOrder
120121
import moe.rukamori.archivetune.constants.toLibraryFilterPreference
121122
import moe.rukamori.archivetune.constants.toPlaylistTagOrder
@@ -154,6 +155,11 @@ fun AppearanceSettings(navController: NavController) {
154155
DynamicThemeKey,
155156
defaultValue = true,
156157
)
158+
val (wallpaperExtractionFailed) =
159+
rememberPreference(
160+
WallpaperExtractionFailedKey,
161+
defaultValue = false,
162+
)
157163
val (randomThemeOnStartup, onRandomThemeOnStartupChange) =
158164
rememberPreference(
159165
RandomThemeOnStartupKey,
@@ -540,7 +546,23 @@ fun AppearanceSettings(navController: NavController) {
540546
)
541547
}
542548

543-
item(visible = !dynamicTheme || Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
549+
item(visible = dynamicTheme && Build.VERSION.SDK_INT < Build.VERSION_CODES.S && wallpaperExtractionFailed) {
550+
PreferenceEntry(
551+
title = { Text(stringResource(R.string.wallpaper_permission)) },
552+
description = stringResource(R.string.wallpaper_permission_desc),
553+
icon = { Icon(painterResource(R.drawable.storage), null) },
554+
onClick = {
555+
val intent =
556+
android.content.Intent(
557+
android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
558+
android.net.Uri.fromParts("package", context.packageName, null),
559+
)
560+
context.startActivity(intent)
561+
},
562+
)
563+
}
564+
565+
item(visible = !dynamicTheme) {
544566
SwitchPreference(
545567
title = { Text(stringResource(R.string.random_theme_on_startup)) },
546568
description = stringResource(R.string.random_theme_on_startup_desc),

‎app/src/main/kotlin/moe/rukamori/archivetune/ui/theme/Theme.kt‎

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@
77

88
package moe.rukamori.archivetune.ui.theme
99

10+
import android.app.WallpaperManager
11+
import android.content.Context
1012
import android.graphics.Bitmap
13+
import android.graphics.drawable.BitmapDrawable
1114
import android.os.Build
1215
import android.util.Base64
1316
import androidx.compose.animation.animateColorAsState
@@ -450,6 +453,31 @@ fun Bitmap.extractGradientColors(): List<Color> {
450453
.sortedByDescending { it.luminance() }
451454
}
452455

456+
fun extractWallpaperThemeColor(context: Context): Color? {
457+
return try {
458+
val wallpaperManager = WallpaperManager.getInstance(context)
459+
val drawable = wallpaperManager.drawable ?: return null
460+
val bitmap =
461+
if (drawable is BitmapDrawable) {
462+
drawable.bitmap
463+
} else {
464+
val bmp =
465+
Bitmap.createBitmap(
466+
drawable.intrinsicWidth.coerceAtLeast(1),
467+
drawable.intrinsicHeight.coerceAtLeast(1),
468+
Bitmap.Config.ARGB_8888,
469+
)
470+
val canvas = android.graphics.Canvas(bmp)
471+
drawable.setBounds(0, 0, canvas.width, canvas.height)
472+
drawable.draw(canvas)
473+
bmp
474+
}
475+
bitmap.extractThemeColor()
476+
} catch (e: Exception) {
477+
null
478+
}
479+
}
480+
453481
fun ColorScheme.pureBlack(apply: Boolean) =
454482
if (apply) {
455483
copy(

‎app/src/main/res/values/strings.xml‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,8 @@
339339
<string name="app_icon_change_failed">Couldn\'t change the app icon</string>
340340
<string name="theme">Theme</string>
341341
<string name="enable_dynamic_theme">Enable dynamic theme</string>
342+
<string name="wallpaper_permission">Wallpaper color permission</string>
343+
<string name="wallpaper_permission_desc">Grant storage permission to extract colors from your wallpaper on older devices</string>
342344
<string name="random_theme_on_startup">Random theme on startup</string>
343345
<string name="random_theme_on_startup_desc">Apply a random color palette every time the app starts</string>
344346
<string name="font_preference">Font</string>

0 commit comments

Comments
 (0)