Apply themed icon colors in UI layer, not in icon repository

This commit is contained in:
MM20 2022-04-11 20:04:19 +02:00
parent 8c6b6c5e91
commit 840c7db690
No known key found for this signature in database
GPG Key ID: 0B61A8F2DEAFA389
8 changed files with 65 additions and 81 deletions

View File

@ -8,11 +8,12 @@ import androidx.palette.graphics.Palette
import java.lang.ref.WeakReference import java.lang.ref.WeakReference
open class LauncherIcon( open class LauncherIcon(
foreground: Drawable, foreground: Drawable,
background: Drawable? = null, background: Drawable? = null,
foregroundScale: Float = 1f, foregroundScale: Float = 1f,
backgroundScale: Float = 1f, backgroundScale: Float = 1f,
var autoGenerateBackgroundMode: Int = BACKGROUND_WHITE var autoGenerateBackgroundMode: Int = BACKGROUND_WHITE,
val isThemeable: Boolean = false,
) { ) {
var foreground = foreground var foreground = foreground

View File

@ -15,6 +15,7 @@ class ClockDynamicLauncherIcon(
background: Drawable?, background: Drawable?,
foregroundScale: Float, foregroundScale: Float,
backgroundScale: Float, backgroundScale: Float,
isThemeable: Boolean = false,
val hourLayer: Int, val hourLayer: Int,
val minuteLayer: Int, val minuteLayer: Int,
val secondLayer: Int val secondLayer: Int
@ -22,7 +23,8 @@ class ClockDynamicLauncherIcon(
foreground, foreground,
background, background,
foregroundScale, foregroundScale,
backgroundScale backgroundScale,
isThemeable = isThemeable
) { ) {

View File

@ -7,13 +7,14 @@ abstract class DynamicLauncherIcon(
foreground: Drawable, foreground: Drawable,
background: Drawable?, background: Drawable?,
foregroundScale: Float, foregroundScale: Float,
backgroundScale: Float backgroundScale: Float,
) isThemeable: Boolean = false
: LauncherIcon( ) : LauncherIcon(
foreground, foreground,
background, background,
foregroundScale, foregroundScale,
backgroundScale, backgroundScale,
isThemeable = isThemeable
) { ) {
abstract fun update(context: Context) abstract fun update(context: Context)

View File

@ -4,15 +4,15 @@ import android.content.BroadcastReceiver
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.IntentFilter import android.content.IntentFilter
import android.content.res.Resources
import android.util.LruCache import android.util.LruCache
import android.util.TypedValue
import de.mm20.launcher2.icons.providers.* import de.mm20.launcher2.icons.providers.*
import de.mm20.launcher2.preferences.LauncherDataStore import de.mm20.launcher2.preferences.LauncherDataStore
import de.mm20.launcher2.preferences.Settings
import de.mm20.launcher2.search.data.Searchable import de.mm20.launcher2.search.data.Searchable
import kotlinx.coroutines.* import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.* import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
class IconRepository( class IconRepository(
val context: Context, val context: Context,
@ -31,8 +31,6 @@ class IconRepository(
private val cache = LruCache<String, LauncherIcon>(200) private val cache = LruCache<String, LauncherIcon>(200)
private val themeColors = MutableStateFlow(ThemeColors())
private var iconProviders: MutableStateFlow<List<IconProvider>> = MutableStateFlow(listOf()) private var iconProviders: MutableStateFlow<List<IconProvider>> = MutableStateFlow(listOf())
private lateinit var placeholderProvider: IconProvider private lateinit var placeholderProvider: IconProvider
@ -49,30 +47,34 @@ class IconRepository(
scope.launch { scope.launch {
dataStore.data.map { it.icons }.distinctUntilChanged().collectLatest { settings -> dataStore.data.map { it.icons }.distinctUntilChanged().collectLatest { settings ->
themeColors.collectLatest { colors -> val placeholderProvider = if (settings.themedIcons) {
val placeholderProvider = if (settings.themedIcons) { ThemedPlaceholderIconProvider(context)
ThemedPlaceholderIconProvider(context, colors) } else {
} else { PlaceholderIconProvider(context)
PlaceholderIconProvider(context)
}
val providers = mutableListOf<IconProvider>()
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
} }
val providers = mutableListOf<IconProvider>()
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
} }
} }
} }
@ -120,19 +122,4 @@ class IconRepository(
return iconPackManager.getInstalledIconPacks() return iconPackManager.getInstalledIconPacks()
} }
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)
}
}
internal data class ThemeColors(
val foreground: Int = 0xFFFFFFFF.toInt(),
val background: Int = 0xFF000000.toInt(),
)

View File

@ -2,6 +2,7 @@ package de.mm20.launcher2.icons
import android.content.Context import android.content.Context
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.graphics.Color
import android.graphics.drawable.AdaptiveIconDrawable import android.graphics.drawable.AdaptiveIconDrawable
import android.graphics.drawable.ColorDrawable import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
@ -14,13 +15,13 @@ class ThemedCalendarDynamicLauncherIcon(
foregroundScale: Float, foregroundScale: Float,
val packageName: String, val packageName: String,
val foregroundIds: IntArray, val foregroundIds: IntArray,
val foregroundTint: Int,
background: Drawable, background: Drawable,
) : DynamicLauncherIcon( ) : DynamicLauncherIcon(
foreground = ColorDrawable(0), foreground = ColorDrawable(0),
background = background, background = background,
foregroundScale = foregroundScale, foregroundScale = foregroundScale,
backgroundScale = 1f, backgroundScale = 1f,
isThemeable = true,
) { ) {
var currentDay = 0 var currentDay = 0
@ -36,7 +37,6 @@ class ThemedCalendarDynamicLauncherIcon(
Executors.newSingleThreadExecutor().execute { Executors.newSingleThreadExecutor().execute {
val currentDayDrawable = resources.getDrawableOrNull(foregroundIds[day - 1]) val currentDayDrawable = resources.getDrawableOrNull(foregroundIds[day - 1])
?: return@execute ?: return@execute
currentDayDrawable.setTint(foregroundTint)
foreground = currentDayDrawable foreground = currentDayDrawable
} }
currentDay = day currentDay = day

View File

@ -3,11 +3,10 @@ package de.mm20.launcher2.icons.providers
import android.content.ComponentName import android.content.ComponentName
import android.content.Context import android.content.Context
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.content.res.Configuration
import android.content.res.Resources import android.content.res.Resources
import android.graphics.Color
import android.graphics.drawable.ColorDrawable import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.LayerDrawable import android.graphics.drawable.LayerDrawable
import android.util.TypedValue
import androidx.core.content.res.ResourcesCompat import androidx.core.content.res.ResourcesCompat
import de.mm20.launcher2.crashreporter.CrashReporter import de.mm20.launcher2.crashreporter.CrashReporter
import de.mm20.launcher2.database.AppDatabase import de.mm20.launcher2.database.AppDatabase
@ -18,7 +17,6 @@ import de.mm20.launcher2.search.data.Searchable
internal class ThemedIconProvider( internal class ThemedIconProvider(
private val context: Context, private val context: Context,
private val colors: ThemeColors,
) : IconProvider { ) : IconProvider {
override suspend fun getIcon(searchable: Searchable, size: Int): LauncherIcon? { override suspend fun getIcon(searchable: Searchable, size: Int): LauncherIcon? {
@ -49,11 +47,11 @@ internal class ThemedIconProvider(
private fun getStaticIcon(resources: Resources, resId: Int): LauncherIcon? { private fun getStaticIcon(resources: Resources, resId: Int): LauncherIcon? {
try { try {
val fg = ResourcesCompat.getDrawable(resources, resId, null) ?: return null val fg = ResourcesCompat.getDrawable(resources, resId, null) ?: return null
fg.setTint(colors.foreground)
return LauncherIcon( return LauncherIcon(
foreground = fg, foreground = fg,
foregroundScale = 0.5f, foregroundScale = 0.5f,
background = ColorDrawable(colors.background) background = ColorDrawable(Color.WHITE),
isThemeable = true
) )
} catch (e: Resources.NotFoundException) { } catch (e: Resources.NotFoundException) {
return null return null
@ -85,15 +83,15 @@ internal class ThemedIconProvider(
i++ i++
} }
if (drawable != null && minuteIndex != null && hourIndex != null) { if (drawable != null && minuteIndex != null && hourIndex != null) {
drawable.setTint(colors.foreground)
return ClockDynamicLauncherIcon( return ClockDynamicLauncherIcon(
foreground = drawable, foreground = drawable,
background = ColorDrawable(colors.background), background = ColorDrawable(Color.WHITE),
foregroundScale = 1.5f, foregroundScale = 1.5f,
backgroundScale = 1f, backgroundScale = 1f,
hourLayer = hourIndex, hourLayer = hourIndex,
minuteLayer = minuteIndex, minuteLayer = minuteIndex,
secondLayer = -1, secondLayer = -1,
isThemeable = true,
) )
} }
} catch (e: Resources.NotFoundException) { } catch (e: Resources.NotFoundException) {
@ -111,13 +109,12 @@ internal class ThemedIconProvider(
if (array.length() != 31) return null if (array.length() != 31) return null
return ThemedCalendarDynamicLauncherIcon( return ThemedCalendarDynamicLauncherIcon(
background = ColorDrawable(colors.background), foregroundScale = 0.5f,
packageName = iconProviderPackage, packageName = iconProviderPackage,
foregroundIds = IntArray(31) { foregroundIds = IntArray(31) {
array.getResourceId(it, 0).takeIf { it != 0 } ?: return null array.getResourceId(it, 0).takeIf { it != 0 } ?: return null
}, },
foregroundTint = colors.foreground, background = ColorDrawable(Color.WHITE),
foregroundScale = 0.5f,
) )
} catch (e: Resources.NotFoundException) { } catch (e: Resources.NotFoundException) {

View File

@ -1,24 +1,23 @@
package de.mm20.launcher2.icons.providers package de.mm20.launcher2.icons.providers
import android.content.Context import android.content.Context
import android.content.res.Configuration
import android.util.TypedValue
import de.mm20.launcher2.icons.LauncherIcon 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 import de.mm20.launcher2.search.data.Searchable
internal class ThemedPlaceholderIconProvider( internal class ThemedPlaceholderIconProvider(
private val context: Context, private val context: Context,
private val colors: ThemeColors,
) : IconProvider { ) : IconProvider {
override suspend fun getIcon(searchable: Searchable, size: Int): LauncherIcon { override suspend fun getIcon(searchable: Searchable, size: Int): LauncherIcon {
val icon = searchable.getPlaceholderIcon(context) val icon = searchable.getPlaceholderIcon(context)
icon.foreground.setTint(colors.foreground) return LauncherIcon(
icon.background?.setTint(colors.background) foreground = icon.foreground,
return icon foregroundScale = icon.foregroundScale,
background = icon.background,
backgroundScale = icon.backgroundScale,
isThemeable = true
)
} }
} }

View File

@ -36,9 +36,6 @@ class LauncherActivity : BaseActivity() {
viewModel.setDarkMode(resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES) 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)) binding = ActivityLauncherBinding.inflate(LayoutInflater.from(this))
setContentView(binding.root) setContentView(binding.root)