Migrate icon settings

This commit is contained in:
MM20
2022-01-28 23:15:27 +01:00
parent 75529b8f42
commit f72e7a1993
28 changed files with 344 additions and 187 deletions
@@ -23,6 +23,8 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import de.mm20.launcher2.icons.LauncherIcon
import de.mm20.launcher2.preferences.Settings
import de.mm20.launcher2.preferences.Settings.IconSettings.LegacyIconBackground
import de.mm20.launcher2.search.data.Searchable
import de.mm20.launcher2.ui.icons.PlaceholderIcon
import de.mm20.launcher2.ui.icons.getPlaceholderIcon
@@ -48,7 +50,7 @@ fun ShapedLauncherIcon(
LaunchedEffect(item) {
icon = withContext(Dispatchers.IO) {
item.loadIcon(context, iconSize)
item.loadIcon(context, iconSize, LegacyIconBackground.Dynamic)
}
}
@@ -35,8 +35,6 @@ class LauncherActivity : BaseActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val iconRepository: IconRepository by inject()
iconRepository.recreate()
WindowCompat.setDecorFitsSystemWindows(window, false)
@@ -1,13 +1,15 @@
package de.mm20.launcher2.ui.settings.appearance
import android.content.Context
import android.graphics.drawable.ColorDrawable
import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.content.res.AppCompatResources
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.GridCells
import androidx.compose.foundation.lazy.LazyVerticalGrid
import androidx.compose.foundation.lazy.items
@@ -30,7 +32,6 @@ import com.google.accompanist.pager.HorizontalPagerIndicator
import com.google.accompanist.pager.rememberPagerState
import de.mm20.launcher2.icons.LauncherIcon
import de.mm20.launcher2.ktx.dp
import de.mm20.launcher2.preferences.IconShape
import de.mm20.launcher2.preferences.Settings.AppearanceSettings.ColorScheme
import de.mm20.launcher2.preferences.Settings.AppearanceSettings.Theme
import de.mm20.launcher2.preferences.Settings.IconSettings
@@ -111,7 +112,7 @@ fun AppearanceSettingsScreen() {
)
}
PreferenceCategory(stringResource(R.string.preference_category_icons)) {
val iconShape by viewModel.iconShape.observeAsState()
val iconShape by viewModel.iconShape.observeAsState(IconSettings.IconShape.PlatformDefault)
IconShapePreference(
title = stringResource(R.string.preference_icon_shape),
summary = getShapeName(iconShape),
@@ -120,6 +121,46 @@ fun AppearanceSettingsScreen() {
viewModel.setIconShape(it)
}
)
val themedIcons by viewModel.themedIcons.observeAsState()
SwitchPreference(
title = stringResource(R.string.preference_themed_icons),
summary = stringResource(R.string.preference_themed_icons_summary),
value = themedIcons == true,
onValueChanged = {
viewModel.setThemedIcons(it)
}
)
val iconPack by viewModel.iconPack.observeAsState()
val installedIconPacks by viewModel.installedIconPacks.observeAsState(emptyList())
val items = installedIconPacks.map {
it.name to it.packageName
}
ListPreference(
title = stringResource(R.string.preference_icon_pack),
items = items,
summary = if (items.size <= 1) {
stringResource(R.string.preference_icon_pack_summary_empty)
} else {
items.firstOrNull { iconPack == it.value }?.label ?: "System"
},
enabled = installedIconPacks.size > 1,
value = iconPack,
onValueChanged = {
if (it != null) viewModel.setIconPack(it)
}
)
val legacyIconBackground by viewModel.legacyIconBackground.observeAsState()
LegacyIconBackgroundPreference(
title = stringResource(R.string.preference_legacy_icon_bg),
summary = stringResource(R.string.preference_legacy_icon_bg_summary),
value = legacyIconBackground,
onValueChanged = {
viewModel.setLegacyIconBackground(it)
},
iconShape = iconShape
)
}
PreferenceCategory(stringResource(R.string.preference_category_searchbar)) {
val searchBarStyle by viewModel.searchBarStyle.observeAsState()
@@ -263,14 +304,19 @@ fun IconShapePreference(
.padding(bottom = 16.dp, start = 16.dp, end = 16.dp)
) {
items(shapes) {
Column(modifier = Modifier
.padding(8.dp),
horizontalAlignment = Alignment.CenterHorizontally) {
Column(
modifier = Modifier
.padding(8.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
AndroidView(factory = { context ->
LauncherIconView(context).apply {
shape = it
icon = LauncherIcon(
foreground = AppCompatResources.getDrawable(context, R.mipmap.ic_launcher_foreground)!!,
foreground = AppCompatResources.getDrawable(
context,
R.mipmap.ic_launcher_foreground
)!!,
background = ColorDrawable(context.getColor(R.color.ic_launcher_background))
)
setOnClickListener { _ ->
@@ -287,7 +333,90 @@ fun IconShapePreference(
getShapeName(it) ?: "",
textAlign = TextAlign.Center,
style = MaterialTheme.typography.labelMedium,
modifier = Modifier.padding(top = 4.dp))
modifier = Modifier.padding(top = 4.dp)
)
}
}
}
}
}
}
}
}
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun LegacyIconBackgroundPreference(
title: String,
summary: String? = null,
value: IconSettings.LegacyIconBackground?,
onValueChanged: (IconSettings.LegacyIconBackground) -> Unit,
iconShape: IconSettings.IconShape
) {
var showDialog by remember { mutableStateOf(false) }
Preference(title = title, summary = summary, onClick = { showDialog = true })
if (showDialog && value != null) {
val colors = remember {
IconSettings.LegacyIconBackground.values()
.filter { it != IconSettings.LegacyIconBackground.UNRECOGNIZED }
}
Dialog(onDismissRequest = { showDialog = false }) {
Surface(
tonalElevation = 16.dp,
shadowElevation = 16.dp,
shape = RoundedCornerShape(16.dp),
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 16.dp),
) {
Column(
modifier = Modifier.fillMaxWidth()
) {
Text(
text = title,
style = MaterialTheme.typography.titleLarge,
modifier = Modifier.padding(
start = 24.dp, end = 24.dp, top = 16.dp, bottom = 8.dp
)
)
LazyVerticalGrid(
cells = GridCells.Adaptive(96.dp),
modifier = Modifier
.fillMaxWidth()
.padding(bottom = 16.dp, start = 16.dp, end = 16.dp)
) {
items(colors) {
Column(
modifier = Modifier
.padding(8.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
AndroidView(factory = { context ->
LauncherIconView(context).apply {
shape = iconShape
icon = LauncherIcon(
foreground = AppCompatResources.getDrawable(
context,
R.mipmap.ic_launcher_foreground
)!!,
background = null,
autoGenerateBackgroundMode = when (it) {
IconSettings.LegacyIconBackground.Dynamic -> LauncherIcon.BACKGROUND_DYNAMIC
IconSettings.LegacyIconBackground.None -> LauncherIcon.BACKGROUND_NONE
else -> LauncherIcon.BACKGROUND_WHITE
}
)
setOnClickListener { _ ->
onValueChanged(it)
showDialog = false
}
layoutParams = ViewGroup.LayoutParams(
(48 * context.dp).toInt(),
(48 * context.dp).toInt(),
)
}
})
}
}
}
@@ -300,15 +429,17 @@ fun IconShapePreference(
@Composable
private fun getShapeName(shape: IconSettings.IconShape?): String? {
return stringResource(when (shape) {
IconSettings.IconShape.Triangle -> R.string.preference_icon_shape_triangle
IconSettings.IconShape.Hexagon -> R.string.preference_icon_shape_hexagon
IconSettings.IconShape.RoundedSquare -> R.string.preference_icon_shape_rounded_square
IconSettings.IconShape.Squircle -> R.string.preference_icon_shape_squircle
IconSettings.IconShape.Square -> R.string.preference_icon_shape_square
IconSettings.IconShape.Pentagon -> R.string.preference_icon_shape_pentagon
IconSettings.IconShape.PlatformDefault -> R.string.preference_icon_shape_platform
IconSettings.IconShape.Circle -> R.string.preference_icon_shape_circle
else -> return null
})
return stringResource(
when (shape) {
IconSettings.IconShape.Triangle -> R.string.preference_icon_shape_triangle
IconSettings.IconShape.Hexagon -> R.string.preference_icon_shape_hexagon
IconSettings.IconShape.RoundedSquare -> R.string.preference_icon_shape_rounded_square
IconSettings.IconShape.Squircle -> R.string.preference_icon_shape_squircle
IconSettings.IconShape.Square -> R.string.preference_icon_shape_square
IconSettings.IconShape.Pentagon -> R.string.preference_icon_shape_pentagon
IconSettings.IconShape.PlatformDefault -> R.string.preference_icon_shape_platform
IconSettings.IconShape.Circle -> R.string.preference_icon_shape_circle
else -> return null
}
)
}
@@ -2,13 +2,14 @@ package de.mm20.launcher2.ui.settings.appearance
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.ViewModel
import androidx.lifecycle.asLiveData
import androidx.lifecycle.viewModelScope
import androidx.lifecycle.*
import de.mm20.launcher2.icons.IconPack
import de.mm20.launcher2.icons.IconRepository
import de.mm20.launcher2.preferences.LauncherDataStore
import de.mm20.launcher2.preferences.Settings
import de.mm20.launcher2.preferences.Settings.AppearanceSettings.ColorScheme
import de.mm20.launcher2.preferences.Settings.AppearanceSettings.Theme
import de.mm20.launcher2.preferences.Settings.IconSettings.LegacyIconBackground
import de.mm20.launcher2.preferences.Settings.SearchBarSettings
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
@@ -18,6 +19,8 @@ import org.koin.core.component.inject
class AppearanceSettingsScreenVM : ViewModel(), KoinComponent {
private val dataStore: LauncherDataStore by inject()
private val iconRepository: IconRepository by inject()
val theme = dataStore.data.map { it.appearance.theme }.asLiveData()
fun setTheme(theme: Theme) {
viewModelScope.launch {
@@ -93,4 +96,56 @@ class AppearanceSettingsScreenVM : ViewModel(), KoinComponent {
}
}
}
val legacyIconBackground = dataStore.data.map { it.icons.legacyIconBg }.asLiveData()
fun setLegacyIconBackground(legacyIconBackground: LegacyIconBackground) {
viewModelScope.launch {
dataStore.updateData {
it.toBuilder()
.setIcons(
it.icons.toBuilder()
.setLegacyIconBg(legacyIconBackground)
)
.build()
}
}
}
val themedIcons = dataStore.data.map { it.icons.themedIcons }.asLiveData()
fun setThemedIcons(themedIcons: Boolean) {
viewModelScope.launch {
dataStore.updateData {
it.toBuilder()
.setIcons(
it.icons.toBuilder()
.setThemedIcons(themedIcons)
)
.build()
}
}
}
val installedIconPacks: LiveData<List<IconPack>> = liveData {
emit(
listOf(IconPack(
name = "System",
packageName = "",
version = "",
)) +
iconRepository.getInstalledIconPacks()
)
}
val iconPack = dataStore.data.map { it.icons.iconPack }.asLiveData()
fun setIconPack(iconPack: String) {
viewModelScope.launch {
dataStore.updateData {
it.toBuilder()
.setIcons(
it.icons.toBuilder()
.setIconPack(iconPack)
)
.build()
}
}
}
}