Add preference to disable themed icons for themed icon packs

This commit is contained in:
MM20 2023-03-15 17:02:16 +01:00
parent 6f6d6451a9
commit 70b406eb5c
No known key found for this signature in database
GPG Key ID: 0B61A8F2DEAFA389
9 changed files with 139 additions and 58 deletions

View File

@ -4,21 +4,24 @@ import android.graphics.drawable.ColorDrawable
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.basicMarquee
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.grid.GridCells import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.lazy.grid.items import androidx.compose.foundation.lazy.grid.items
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.FormatPaint import androidx.compose.material.icons.rounded.FormatPaint
import androidx.compose.material3.AlertDialog import androidx.compose.material3.AlertDialog
import androidx.compose.material3.FilledIconToggleButton
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.LocalContentColor
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface import androidx.compose.material3.Surface
import androidx.compose.material3.Text import androidx.compose.material3.Text
@ -34,6 +37,7 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
@ -249,6 +253,7 @@ fun AppearanceSettingsScreen() {
) )
val iconPackPackage by viewModel.iconPack.observeAsState() val iconPackPackage by viewModel.iconPack.observeAsState()
val iconPackThemed by viewModel.iconPackThemed.collectAsState(true)
val installedIconPacks by viewModel.installedIconPacks.collectAsState(emptyList()) val installedIconPacks by viewModel.installedIconPacks.collectAsState(emptyList())
val iconPack by remember { val iconPack by remember {
derivedStateOf { installedIconPacks.firstOrNull { it.packageName == iconPackPackage } } derivedStateOf { installedIconPacks.firstOrNull { it.packageName == iconPackPackage } }
@ -256,56 +261,88 @@ fun AppearanceSettingsScreen() {
val items = installedIconPacks.map { val items = installedIconPacks.map {
it.name to it it.name to it
} }
ListPreference( Row(
title = stringResource(R.string.preference_icon_pack), verticalAlignment = (Alignment.CenterVertically)
items = items, ) {
summary = if (items.size <= 1) { Box(
stringResource(R.string.preference_icon_pack_summary_empty) modifier = Modifier.weight(1f)
} else { ) {
iconPack?.name ?: "System" ListPreference(
}, title = stringResource(R.string.preference_icon_pack),
enabled = installedIconPacks.size > 1, items = items,
value = iconPack, summary = if (items.size <= 1) {
onValueChanged = { stringResource(R.string.preference_icon_pack_summary_empty)
if (it != null) viewModel.setIconPack(it.packageName) } else {
}, iconPack?.name ?: "System"
itemLabel = { },
Column( enabled = installedIconPacks.size > 1,
verticalArrangement = Arrangement.Center, value = iconPack,
) { onValueChanged = {
Text( if (it != null) viewModel.setIconPack(it.packageName)
text = it.label, },
maxLines = 1, itemLabel = {
overflow = TextOverflow.Ellipsis, Column(
) verticalArrangement = Arrangement.Center,
if (it.value?.themed == true) {
Surface(
shape = MaterialTheme.shapes.extraSmall,
color = MaterialTheme.colorScheme.tertiary,
modifier = Modifier.padding(top = 4.dp)
) { ) {
Row( Text(
modifier = Modifier.padding(horizontal = 4.dp), text = it.label,
verticalAlignment = Alignment.CenterVertically, maxLines = 1,
) { overflow = TextOverflow.Ellipsis,
Icon( )
modifier = Modifier if (it.value?.themed == true) {
.size(20.dp) Surface(
.padding(end = 4.dp), shape = MaterialTheme.shapes.extraSmall,
imageVector = Icons.Rounded.FormatPaint, color = MaterialTheme.colorScheme.tertiary,
contentDescription = null, modifier = Modifier.padding(top = 4.dp)
) ) {
Text( Row(
text = stringResource(R.string.icon_pack_dynamic_colors), modifier = Modifier.padding(horizontal = 4.dp),
style = MaterialTheme.typography.labelSmall verticalAlignment = Alignment.CenterVertically,
) ) {
Icon(
modifier = Modifier
.size(20.dp)
.padding(end = 4.dp),
imageVector = Icons.Rounded.FormatPaint,
contentDescription = null,
)
Text(
text = stringResource(R.string.icon_pack_dynamic_colors),
style = MaterialTheme.typography.labelSmall
)
}
}
} }
} }
} }
)
}
if (iconPack?.themed == true) {
Box(
modifier = Modifier
.height(36.dp)
.width(1.dp)
.alpha(0.38f)
.background(LocalContentColor.current)
)
Box(
modifier = Modifier
.padding(12.dp)
) {
FilledIconToggleButton(
checked = iconPackThemed,
onCheckedChange = {
viewModel.setIconPackThemed(it)
}) {
Icon(
Icons.Rounded.FormatPaint,
stringResource(R.string.icon_pack_dynamic_colors)
)
}
} }
} }
) }
} }
PreferenceCategory(stringResource(R.string.preference_category_searchbar)) { PreferenceCategory(stringResource(R.string.preference_category_searchbar)) {
val searchBarStyle by viewModel.searchBarStyle.observeAsState() val searchBarStyle by viewModel.searchBarStyle.observeAsState()

View File

@ -20,7 +20,9 @@ import de.mm20.launcher2.preferences.Settings.SearchBarSettings
import de.mm20.launcher2.preferences.Settings.SearchBarSettings.SearchBarColors import de.mm20.launcher2.preferences.Settings.SearchBarSettings.SearchBarColors
import de.mm20.launcher2.preferences.Settings.SystemBarsSettings import de.mm20.launcher2.preferences.Settings.SystemBarsSettings
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.shareIn
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.koin.core.component.KoinComponent import org.koin.core.component.KoinComponent
import org.koin.core.component.inject import org.koin.core.component.inject
@ -199,12 +201,29 @@ class AppearanceSettingsScreenVM : ViewModel(), KoinComponent {
} }
val installedIconPacks: Flow<List<IconPack>> = iconRepository.getInstalledIconPacks().map { val installedIconPacks: Flow<List<IconPack>> = iconRepository.getInstalledIconPacks().map {
listOf(IconPack( listOf(
IconPack(
name = "System", name = "System",
packageName = "", packageName = "",
version = "", version = "",
)) + it )
) + it
}
val iconPackThemed = dataStore.data.map { it.icons.iconPackThemed }
fun setIconPackThemed(iconPackThemed: Boolean) {
viewModelScope.launch {
dataStore.updateData {
it.toBuilder()
.setIcons(
it.icons
.toBuilder()
.setIconPackThemed(iconPackThemed)
)
.build()
}
} }
}
val iconPack = dataStore.data.map { it.icons.iconPack }.asLiveData() val iconPack = dataStore.data.map { it.icons.iconPack }.asLiveData()
fun setIconPack(iconPack: String) { fun setIconPack(iconPack: String) {

View File

@ -22,7 +22,7 @@ internal val Context.dataStore: LauncherDataStore by dataStore(
} }
) )
internal const val SchemaVersion = 13 internal const val SchemaVersion = 14
internal fun getMigrations(context: Context): List<DataMigration<Settings>> { internal fun getMigrations(context: Context): List<DataMigration<Settings>> {
return listOf( return listOf(
@ -39,5 +39,6 @@ internal fun getMigrations(context: Context): List<DataMigration<Settings>> {
Migration_10_11(), Migration_10_11(),
Migration_11_12(), Migration_11_12(),
Migration_12_13(), Migration_12_13(),
Migration_13_14(),
) )
} }

View File

@ -145,6 +145,7 @@ fun createFactorySettings(context: Context): Settings {
.setShape(Settings.IconSettings.IconShape.PlatformDefault) .setShape(Settings.IconSettings.IconShape.PlatformDefault)
.setThemedIcons(false) .setThemedIcons(false)
.setIconPack("") .setIconPack("")
.setIconPackThemed(true)
) )
.setEasterEgg(false) .setEasterEgg(false)
.setSystemBars( .setSystemBars(

View File

@ -0,0 +1,13 @@
package de.mm20.launcher2.preferences.migrations
import de.mm20.launcher2.preferences.Settings
class Migration_13_14 : VersionedMigration(13, 14) {
override suspend fun applyMigrations(builder: Settings.Builder): Settings.Builder {
return builder
.setIcons(
builder.icons.toBuilder()
.setIconPackThemed(true)
)
}
}

View File

@ -246,6 +246,7 @@ message Settings {
reserved 4; reserved 4;
bool adaptify = 5; bool adaptify = 5;
bool force_themed = 6; bool force_themed = 6;
bool icon_pack_themed = 7;
} }
IconSettings icons = 21; IconSettings icons = 21;

View File

@ -87,6 +87,7 @@ class IconPackManager(
iconPack: String, iconPack: String,
packageName: String, packageName: String,
activityName: String?, activityName: String?,
allowThemed: Boolean = true
): LauncherIcon? { ): LauncherIcon? {
val res = try { val res = try {
context.packageManager.getResourcesForApplication(iconPack) context.packageManager.getResourcesForApplication(iconPack)
@ -100,11 +101,11 @@ class IconPackManager(
?: return null ?: return null
if (icon is CalendarIcon) { if (icon is CalendarIcon) {
return getIconPackCalendarIcon(icon, res) return getIconPackCalendarIcon(icon, res, allowThemed)
} else if (icon is AppIcon) { } else if (icon is AppIcon) {
return getIconPackStaticIcon(icon, res) return getIconPackStaticIcon(icon, res, allowThemed)
} else if (icon is ClockIcon) { } else if (icon is ClockIcon) {
return getIconPackClockIcon(icon, res) return getIconPackClockIcon(icon, res, allowThemed)
} }
return null return null
} }
@ -241,6 +242,7 @@ class IconPackManager(
private fun getIconPackStaticIcon( private fun getIconPackStaticIcon(
icon: AppIcon, icon: AppIcon,
resources: Resources, resources: Resources,
allowThemed: Boolean,
): LauncherIcon? { ): LauncherIcon? {
val resId = val resId =
resources.getIdentifier(icon.drawable, "drawable", icon.iconPack).takeIf { it != 0 } resources.getIdentifier(icon.drawable, "drawable", icon.iconPack).takeIf { it != 0 }
@ -250,8 +252,9 @@ class IconPackManager(
} catch (e: Resources.NotFoundException) { } catch (e: Resources.NotFoundException) {
return null return null
} }
val themed = icon.themed && allowThemed
return when { return when {
icon.themed && drawable is AdaptiveIconDrawable -> { themed && drawable is AdaptiveIconDrawable -> {
if (isAtLeastApiLevel(33) && drawable.monochrome != null) { if (isAtLeastApiLevel(33) && drawable.monochrome != null) {
return StaticLauncherIcon( return StaticLauncherIcon(
foregroundLayer = TintedIconLayer( foregroundLayer = TintedIconLayer(
@ -271,7 +274,7 @@ class IconPackManager(
} }
} }
icon.themed -> { themed -> {
return StaticLauncherIcon( return StaticLauncherIcon(
foregroundLayer = TintedIconLayer( foregroundLayer = TintedIconLayer(
icon = drawable, icon = drawable,
@ -313,6 +316,7 @@ class IconPackManager(
private fun getIconPackCalendarIcon( private fun getIconPackCalendarIcon(
icon: CalendarIcon, icon: CalendarIcon,
resources: Resources, resources: Resources,
allowThemed: Boolean,
): LauncherIcon? { ): LauncherIcon? {
val drawableIds = icon.drawables.map { val drawableIds = icon.drawables.map {
val id = resources.getIdentifier(it, "drawable", icon.iconPack) val id = resources.getIdentifier(it, "drawable", icon.iconPack)
@ -321,7 +325,7 @@ class IconPackManager(
}.toIntArray() }.toIntArray()
if (icon.themed) { if (icon.themed && allowThemed) {
return ThemedDynamicCalendarIcon( return ThemedDynamicCalendarIcon(
resources = resources, resources = resources,
resourceIds = drawableIds, resourceIds = drawableIds,
@ -336,6 +340,7 @@ class IconPackManager(
private fun getIconPackClockIcon( private fun getIconPackClockIcon(
icon: ClockIcon, icon: ClockIcon,
resources: Resources, resources: Resources,
allowThemed: Boolean,
): LauncherIcon? { ): LauncherIcon? {
var drawable = try { var drawable = try {
resources.getIdentifier(icon.drawable, "drawable", icon.iconPack).takeIf { it != 0 } resources.getIdentifier(icon.drawable, "drawable", icon.iconPack).takeIf { it != 0 }
@ -362,8 +367,10 @@ class IconPackManager(
) )
} }
val themed = icon.themed && allowThemed
return when { return when {
icon.themed && drawable is AdaptiveIconDrawable -> { themed && drawable is AdaptiveIconDrawable -> {
StaticLauncherIcon( StaticLauncherIcon(
foregroundLayer = TintedClockLayer( foregroundLayer = TintedClockLayer(
defaultHour = icon.config.defaultHour, defaultHour = icon.config.defaultHour,
@ -376,7 +383,7 @@ class IconPackManager(
) )
} }
icon.themed -> { themed -> {
StaticLauncherIcon( StaticLauncherIcon(
foregroundLayer = TintedClockLayer( foregroundLayer = TintedClockLayer(
defaultHour = icon.config.defaultHour, defaultHour = icon.config.defaultHour,

View File

@ -109,7 +109,8 @@ class IconRepository(
IconPackIconProvider( IconPackIconProvider(
context, context,
pack, pack,
iconPackManager iconPackManager,
settings.iconPackThemed,
) )
) )
} else { } else {

View File

@ -12,11 +12,12 @@ class IconPackIconProvider(
private val context: Context, private val context: Context,
private val iconPack: IconPack, private val iconPack: IconPack,
private val iconPackManager: IconPackManager, private val iconPackManager: IconPackManager,
private val allowThemed: Boolean,
): IconProvider { ): IconProvider {
override suspend fun getIcon(searchable: SavableSearchable, size: Int): LauncherIcon? { override suspend fun getIcon(searchable: SavableSearchable, size: Int): LauncherIcon? {
if (searchable !is LauncherApp) return null if (searchable !is LauncherApp) return null
return iconPackManager.getIcon(iconPack.packageName, searchable.`package`, searchable.activity) return iconPackManager.getIcon(iconPack.packageName, searchable.`package`, searchable.activity, allowThemed)
?: iconPackManager.generateIcon( ?: iconPackManager.generateIcon(
context, context,
iconPack.packageName, iconPack.packageName,