From c672e0826a35d16f25f44b9c49b22a257d33d560 Mon Sep 17 00:00:00 2001 From: MM20 <15646950+MM2-0@users.noreply.github.com> Date: Wed, 18 Jun 2025 22:46:54 +0200 Subject: [PATCH] implement import/export for typographie --- .../appearance/ExportThemeSettingsScreen.kt | 15 ++++++++++++++- .../appearance/ExportThemeSettingsScreenVM.kt | 11 +++++++++++ .../appearance/ImportThemeSettingsScreen.kt | 18 ++++++++++++++++++ .../appearance/ImportThemeSettingsScreenVM.kt | 17 +++++++++++++++++ .../de/mm20/launcher2/themes/ThemeBundle.kt | 2 ++ .../launcher2/themes/typography/Typography.kt | 2 ++ 6 files changed, 64 insertions(+), 1 deletion(-) diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/appearance/ExportThemeSettingsScreen.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/appearance/ExportThemeSettingsScreen.kt index 41f4da50..13b036da 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/appearance/ExportThemeSettingsScreen.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/appearance/ExportThemeSettingsScreen.kt @@ -16,6 +16,7 @@ import androidx.compose.material.icons.rounded.Opacity import androidx.compose.material.icons.rounded.Palette import androidx.compose.material.icons.rounded.Save import androidx.compose.material.icons.rounded.Share +import androidx.compose.material.icons.rounded.TextFields import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.DropdownMenu import androidx.compose.material3.DropdownMenuItem @@ -50,12 +51,13 @@ fun ExportThemeSettingsScreen() { val context = LocalContext.current val colorSchemes by viewModel.colorSchemes.collectAsState(emptyList()) + val typographyThemes by viewModel.typographySchemes.collectAsState(emptyList()) val shapeThemes by viewModel.shapeSchemes.collectAsState(emptyList()) val transparencySchemes by viewModel.transparencySchemes.collectAsState(emptyList()) val isValidSelection by remember { derivedStateOf { - viewModel.colorScheme != null || viewModel.shapeScheme != null || viewModel.transparencyScheme != null + viewModel.colorScheme != null || viewModel.typographyScheme != null || viewModel.shapeScheme != null || viewModel.transparencyScheme != null } } @@ -102,6 +104,17 @@ fun ExportThemeSettingsScreen() { viewModel.setColorScheme(newValue) } ) + ListPreference( + stringResource(R.string.preference_screen_typography), + icon = Icons.Rounded.TextFields, + value = viewModel.typographyScheme, + items = listOf(stringResource(R.string.no_selection) to null) + typographyThemes.map { + it.name to it + }, + onValueChanged = { newValue -> + viewModel.setTypographyScheme(newValue) + } + ) ListPreference( stringResource(R.string.preference_screen_shapes), icon = Icons.Rounded.CropSquare, diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/appearance/ExportThemeSettingsScreenVM.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/appearance/ExportThemeSettingsScreenVM.kt index ec09e069..64d1b271 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/appearance/ExportThemeSettingsScreenVM.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/appearance/ExportThemeSettingsScreenVM.kt @@ -15,6 +15,7 @@ import de.mm20.launcher2.themes.shapes.Shapes import de.mm20.launcher2.themes.ThemeBundle import de.mm20.launcher2.themes.ThemeRepository import de.mm20.launcher2.themes.transparencies.Transparencies +import de.mm20.launcher2.themes.typography.Typography import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch @@ -28,6 +29,7 @@ class ExportThemeSettingsScreenVM: ViewModel(), KoinComponent { private val themeRepository: ThemeRepository by inject() val colorSchemes = themeRepository.colors.getAll().map { it.filter { !it.builtIn } } + val typographySchemes = themeRepository.typographies.getAll().map { it.filter { !it.builtIn } } val shapeSchemes = themeRepository.shapes.getAll().map { it.filter { !it.builtIn } } val transparencySchemes = themeRepository.transparencies.getAll().map { it.filter { !it.builtIn } } @@ -47,6 +49,14 @@ class ExportThemeSettingsScreenVM: ViewModel(), KoinComponent { colorScheme = scheme } + var typographyScheme by mutableStateOf(null) + @JvmName("_setTypographyScheme") + private set + fun setTypographyScheme(scheme: Typography?) { + if (themeName.isBlank() && scheme != null) themeName = scheme.name + typographyScheme = scheme + } + var shapeScheme by mutableStateOf(null) @JvmName("_setShapeScheme") private set @@ -69,6 +79,7 @@ class ExportThemeSettingsScreenVM: ViewModel(), KoinComponent { author = themeAuthor.takeIf { it.isNotBlank() }, colors = colorScheme, shapes = shapeScheme, + typography = typographyScheme, transparencies = transparencyScheme, ) } diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/appearance/ImportThemeSettingsScreen.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/appearance/ImportThemeSettingsScreen.kt index 6c6d5796..242e5c5b 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/appearance/ImportThemeSettingsScreen.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/appearance/ImportThemeSettingsScreen.kt @@ -22,6 +22,7 @@ import androidx.compose.material.icons.rounded.MoreVert import androidx.compose.material.icons.rounded.Opacity import androidx.compose.material.icons.rounded.Palette import androidx.compose.material.icons.rounded.Star +import androidx.compose.material.icons.rounded.TextFields import androidx.compose.material3.Button import androidx.compose.material3.FilledTonalIconButton import androidx.compose.material3.FilterChip @@ -72,6 +73,7 @@ import de.mm20.launcher2.ui.theme.shapes.shapesOf import de.mm20.launcher2.ui.theme.transparency.LocalTransparencyScheme import de.mm20.launcher2.ui.theme.transparency.transparency import de.mm20.launcher2.ui.theme.transparency.transparencySchemeOf +import de.mm20.launcher2.ui.theme.typography.typographyOf import kotlinx.coroutines.launch import kotlinx.serialization.Serializable @@ -124,6 +126,7 @@ fun ImportThemeSettingsScreen( if (darkModePreview) darkColorSchemeOf(it) else lightColorSchemeOf(it) } ?: MaterialTheme.colorScheme, shapes = themeBundle.shapes?.let { shapesOf(it) } ?: MaterialTheme.shapes, + typography = themeBundle.typography?.let { typographyOf(it) } ?: MaterialTheme.typography, ) { val transparencies = themeBundle.transparencies?.let { transparencySchemeOf(it) } ?: MaterialTheme.transparency CompositionLocalProvider( @@ -153,6 +156,21 @@ fun ImportThemeSettingsScreen( } else null, ) } + if (themeBundle.typography != null) { + Preference( + icon = Icons.Rounded.TextFields, + title = stringResource(R.string.preference_screen_typography), + summary = themeBundle.typography?.name, + controls = if (viewModel.typographyExists) { + { + Icon( + Icons.Rounded.ChangeCircle, + stringResource(R.string.import_theme_exists) + ) + } + } else null, + ) + } if (themeBundle.shapes != null) { Preference( icon = Icons.Rounded.CropSquare, diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/appearance/ImportThemeSettingsScreenVM.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/appearance/ImportThemeSettingsScreenVM.kt index 2c33cfbc..3a4360df 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/appearance/ImportThemeSettingsScreenVM.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/appearance/ImportThemeSettingsScreenVM.kt @@ -29,6 +29,9 @@ class ImportThemeSettingsScreenVM : ViewModel(), KoinComponent { var colorsExists by mutableStateOf(false) private set + var typographyExists by mutableStateOf(false) + private set + var shapesExists by mutableStateOf(false) private set @@ -56,12 +59,15 @@ class ImportThemeSettingsScreenVM : ViewModel(), KoinComponent { if (theme != null) { val colors = theme.colors?.id?.let { themeRepository.colors.get(it) }?.first() + val typography = + theme.typography?.id?.let { themeRepository.typographies.get(it) }?.first() val shapes = theme.shapes?.id?.let { themeRepository.shapes.get(it) }?.first() val transparencies = theme.transparencies?.id?.let { themeRepository.transparencies.get(it) }?.first() colorsExists = colors != null + typographyExists = typography != null shapesExists = shapes != null transparenciesExists = transparencies != null themeBundle = theme @@ -81,6 +87,7 @@ class ImportThemeSettingsScreenVM : ViewModel(), KoinComponent { val themeBundle = this.themeBundle ?: return null val colors = themeBundle.colors + val typography = themeBundle.typography val shapes = themeBundle.shapes val transparencies = themeBundle.transparencies @@ -100,6 +107,16 @@ class ImportThemeSettingsScreenVM : ViewModel(), KoinComponent { uiSettings.setColorsId(colors.id) } } + if (typography != null) { + if (typographyExists) { + themeRepository.typographies.update(typography) + } else { + themeRepository.typographies.create(typography) + } + if (applyTheme) { + uiSettings.setTypographyId(typography.id) + } + } if (shapes != null) { if (shapesExist) { themeRepository.shapes.update(shapes) diff --git a/data/themes/src/main/java/de/mm20/launcher2/themes/ThemeBundle.kt b/data/themes/src/main/java/de/mm20/launcher2/themes/ThemeBundle.kt index 89555d55..1a9003ab 100644 --- a/data/themes/src/main/java/de/mm20/launcher2/themes/ThemeBundle.kt +++ b/data/themes/src/main/java/de/mm20/launcher2/themes/ThemeBundle.kt @@ -11,6 +11,7 @@ import de.mm20.launcher2.themes.colors.DefaultLightColorScheme import de.mm20.launcher2.themes.colors.EmptyCorePalette import de.mm20.launcher2.themes.shapes.Shapes import de.mm20.launcher2.themes.transparencies.Transparencies +import de.mm20.launcher2.themes.typography.Typography import kotlinx.serialization.Serializable import kotlinx.serialization.SerializationException import kotlinx.serialization.json.JsonObject @@ -26,6 +27,7 @@ data class ThemeBundle( val name: String, val author: String? = null, val colors: Colors? = null, + val typography: Typography? = null, val shapes: Shapes? = null, val transparencies: Transparencies? = null, /** diff --git a/data/themes/src/main/java/de/mm20/launcher2/themes/typography/Typography.kt b/data/themes/src/main/java/de/mm20/launcher2/themes/typography/Typography.kt index 6312a67f..6ce88f76 100644 --- a/data/themes/src/main/java/de/mm20/launcher2/themes/typography/Typography.kt +++ b/data/themes/src/main/java/de/mm20/launcher2/themes/typography/Typography.kt @@ -216,6 +216,7 @@ sealed interface FontWeight { * Absolute font weight, e.g. 400 for normal, 700 for bold. */ @JvmInline + @Serializable value class Absolute(val weight: Int) : FontWeight /** @@ -224,5 +225,6 @@ sealed interface FontWeight { * the emphasized style with a relative weight of 100 will have a weight of 500, */ @JvmInline + @Serializable value class Relative(val relativeWeight: Int) : FontWeight } \ No newline at end of file