From 667ec0f9324c03df115ec76c96052b8d4f0d7b44 Mon Sep 17 00:00:00 2001 From: MM20 <15646950+MM2-0@users.noreply.github.com> Date: Sat, 5 Mar 2022 16:49:53 +0100 Subject: [PATCH] Themed icons: correctly apply application theme colors --- .../de/mm20/launcher2/icons/IconRepository.kt | 79 ++++++++++--------- .../icons/providers/ThemedIconProvider.kt | 36 +++------ .../ThemedPlaceholderIconProvider.kt | 33 ++------ .../launcher2/ui/launcher/LauncherActivity.kt | 6 +- 4 files changed, 60 insertions(+), 94 deletions(-) diff --git a/icons/src/main/java/de/mm20/launcher2/icons/IconRepository.kt b/icons/src/main/java/de/mm20/launcher2/icons/IconRepository.kt index 99bd18d7..de731226 100644 --- a/icons/src/main/java/de/mm20/launcher2/icons/IconRepository.kt +++ b/icons/src/main/java/de/mm20/launcher2/icons/IconRepository.kt @@ -4,7 +4,9 @@ import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import android.content.IntentFilter +import android.content.res.Resources import android.util.LruCache +import android.util.TypedValue import de.mm20.launcher2.icons.providers.* import de.mm20.launcher2.preferences.LauncherDataStore import de.mm20.launcher2.preferences.Settings @@ -29,6 +31,8 @@ class IconRepository( private val cache = LruCache(200) + private val themeColors = MutableStateFlow(ThemeColors()) + private var iconProviders: MutableStateFlow> = MutableStateFlow(listOf()) private lateinit var placeholderProvider: IconProvider @@ -44,8 +48,31 @@ class IconRepository( }) scope.launch { - dataStore.data.map { it.icons }.distinctUntilChanged().collectLatest { - recreate(it) + dataStore.data.map { it.icons }.distinctUntilChanged().collectLatest { settings -> + themeColors.collectLatest { colors -> + val placeholderProvider = if (settings.themedIcons) { + ThemedPlaceholderIconProvider(context, colors) + } else { + PlaceholderIconProvider(context) + } + val providers = mutableListOf() + + if (settings.themedIcons) { + providers.add(ThemedIconProvider(context, colors)) + } + + if (settings.iconPack.isNotBlank()) { + providers.add(IconPackIconProvider(context, settings.iconPack, settings.legacyIconBg)) + } + providers.add(GoogleClockIconProvider(context)) + providers.add(CalendarIconProvider(context)) + providers.add(SystemIconProvider(context, settings.legacyIconBg)) + providers.add(placeholderProvider) + cache.evictAll() + + this@IconRepository.placeholderProvider = placeholderProvider + iconProviders.value = providers + } } } } @@ -82,13 +109,6 @@ class IconRepository( } } - /** - * Returns the icon for the given Searchable if it was requested earlier and is still in cache. - * Returns `null` otherwise. - */ - fun getIconIfCached(searchable: Searchable): LauncherIcon? { - return cache[searchable.key] - } fun requestIconPackListUpdate() { scope.launch { @@ -100,34 +120,19 @@ class IconRepository( return iconPackManager.getInstalledIconPacks() } - fun recreate() { - scope.launch { - recreate(dataStore.data.map { it.icons }.first()) + fun applyTheme(theme: Resources.Theme) { + val typedValue = TypedValue() + val bgColor = theme.resolveAttribute(R.attr.colorPrimaryContainer, typedValue, true).let { + typedValue.data } + val fgColor = theme.resolveAttribute(R.attr.colorOnPrimaryContainer, typedValue, true).let { + typedValue.data + } + themeColors.value = ThemeColors(foreground = fgColor, background = bgColor) } +} - private fun recreate(settings: Settings.IconSettings) { - val placeholderProvider = if (settings.themedIcons) { - ThemedPlaceholderIconProvider(context) - } else { - PlaceholderIconProvider(context) - } - val providers = mutableListOf() - - if (settings.themedIcons) { - providers.add(ThemedIconProvider(context)) - } - - if (settings.iconPack.isNotBlank()) { - providers.add(IconPackIconProvider(context, settings.iconPack, settings.legacyIconBg)) - } - providers.add(GoogleClockIconProvider(context)) - providers.add(CalendarIconProvider(context)) - providers.add(SystemIconProvider(context, settings.legacyIconBg)) - providers.add(placeholderProvider) - cache.evictAll() - - this@IconRepository.placeholderProvider = placeholderProvider - iconProviders.value = providers - } -} \ No newline at end of file +internal data class ThemeColors( + val foreground: Int = 0xFFFFFFFF.toInt(), + val background: Int = 0xFF000000.toInt(), +) \ No newline at end of file diff --git a/icons/src/main/java/de/mm20/launcher2/icons/providers/ThemedIconProvider.kt b/icons/src/main/java/de/mm20/launcher2/icons/providers/ThemedIconProvider.kt index bdb1f551..4932f80f 100644 --- a/icons/src/main/java/de/mm20/launcher2/icons/providers/ThemedIconProvider.kt +++ b/icons/src/main/java/de/mm20/launcher2/icons/providers/ThemedIconProvider.kt @@ -16,28 +16,10 @@ import de.mm20.launcher2.ktx.obtainTypedArrayOrNull import de.mm20.launcher2.search.data.Application import de.mm20.launcher2.search.data.Searchable -class ThemedIconProvider( - private val context: Context +internal class ThemedIconProvider( + private val context: Context, + private val colors: ThemeColors, ) : IconProvider { - private val fgColor: Int - private val bgColor: Int - - init { - val theme = context.resources.newTheme() - theme.applyStyle(R.style.DefaultColors, true) - val typedValue = TypedValue() - val isDarkMode = - context.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_YES != 0 - - val bgAttr = R.attr.colorPrimaryContainer - val fgAttr = R.attr.colorOnPrimaryContainer - bgColor = theme.resolveAttribute(bgAttr, typedValue, true).let { - typedValue.data - } - fgColor = theme.resolveAttribute(fgAttr, typedValue, true).let { - typedValue.data - } - } override suspend fun getIcon(searchable: Searchable, size: Int): LauncherIcon? { if (searchable !is Application) return null @@ -67,11 +49,11 @@ class ThemedIconProvider( private fun getStaticIcon(resources: Resources, resId: Int): LauncherIcon? { try { val fg = ResourcesCompat.getDrawable(resources, resId, null) ?: return null - fg.setTint(fgColor) + fg.setTint(colors.foreground) return LauncherIcon( foreground = fg, foregroundScale = 0.5f, - background = ColorDrawable(bgColor) + background = ColorDrawable(colors.background) ) } catch (e: Resources.NotFoundException) { return null @@ -103,10 +85,10 @@ class ThemedIconProvider( i++ } if (drawable != null && minuteIndex != null && hourIndex != null) { - drawable.setTint(fgColor) + drawable.setTint(colors.foreground) return ClockDynamicLauncherIcon( foreground = drawable, - background = ColorDrawable(bgColor), + background = ColorDrawable(colors.background), foregroundScale = 1.5f, backgroundScale = 1f, hourLayer = hourIndex, @@ -129,12 +111,12 @@ class ThemedIconProvider( if (array.length() != 31) return null return ThemedCalendarDynamicLauncherIcon( - background = ColorDrawable(bgColor), + background = ColorDrawable(colors.foreground), packageName = iconProviderPackage, foregroundIds = IntArray(31) { array.getResourceId(it, 0).takeIf { it != 0 } ?: return null }, - foregroundTint = fgColor, + foregroundTint = colors.background, foregroundScale = 0.5f, ) diff --git a/icons/src/main/java/de/mm20/launcher2/icons/providers/ThemedPlaceholderIconProvider.kt b/icons/src/main/java/de/mm20/launcher2/icons/providers/ThemedPlaceholderIconProvider.kt index eed0f610..525a5dd6 100644 --- a/icons/src/main/java/de/mm20/launcher2/icons/providers/ThemedPlaceholderIconProvider.kt +++ b/icons/src/main/java/de/mm20/launcher2/icons/providers/ThemedPlaceholderIconProvider.kt @@ -5,40 +5,19 @@ import android.content.res.Configuration import android.util.TypedValue import de.mm20.launcher2.icons.LauncherIcon import de.mm20.launcher2.icons.R +import de.mm20.launcher2.icons.ThemeColors import de.mm20.launcher2.search.data.Searchable -class ThemedPlaceholderIconProvider( - val context: Context +internal class ThemedPlaceholderIconProvider( + private val context: Context, + private val colors: ThemeColors, ) : IconProvider { - private val fgColor: Int - private val bgColor: Int - - init { - val theme = context.resources.newTheme() - theme.applyStyle(R.style.DefaultColors, true) - val typedValue = TypedValue() - val isDarkMode = - context.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_YES != 0 - - val bgAttr = R.attr.colorPrimaryContainer - val fgAttr = R.attr.colorOnPrimaryContainer - - bgColor = theme.resolveAttribute(bgAttr, typedValue, true).let { - typedValue.data - } - fgColor = theme.resolveAttribute(fgAttr, typedValue, true).let { - typedValue.data - } - } - override suspend fun getIcon(searchable: Searchable, size: Int): LauncherIcon { - - val icon = searchable.getPlaceholderIcon(context) - icon.foreground.setTint(fgColor) - icon.background?.setTint(bgColor) + icon.foreground.setTint(colors.foreground) + icon.background?.setTint(colors.background) return icon } diff --git a/ui/src/main/java/de/mm20/launcher2/ui/launcher/LauncherActivity.kt b/ui/src/main/java/de/mm20/launcher2/ui/launcher/LauncherActivity.kt index 27267b47..91212348 100644 --- a/ui/src/main/java/de/mm20/launcher2/ui/launcher/LauncherActivity.kt +++ b/ui/src/main/java/de/mm20/launcher2/ui/launcher/LauncherActivity.kt @@ -32,13 +32,13 @@ class LauncherActivity : BaseActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - val iconRepository: IconRepository by inject() - iconRepository.recreate() - WindowCompat.setDecorFitsSystemWindows(window, false) viewModel.setDarkMode(resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES) + val iconRepository: IconRepository by inject() + iconRepository.applyTheme(theme) + binding = ActivityLauncherBinding.inflate(LayoutInflater.from(this)) setContentView(binding.root)