From 5ba86ed4977f9c9f74843ceb39c2e5672c83c7bf Mon Sep 17 00:00:00 2001 From: Avently <7953703+avently@users.noreply.github.com> Date: Wed, 8 May 2024 13:15:03 +0700 Subject: [PATCH] changes --- .../main/java/chat/simplex/app/SimplexApp.kt | 3 +- .../chat/simplex/common/model/ChatModel.kt | 8 ++-- .../chat/simplex/common/model/SimpleXAPI.kt | 38 +++++++-------- .../chat/simplex/common/platform/AppCommon.kt | 6 +++ .../chat/simplex/common/platform/Core.kt | 1 - .../chat/simplex/common/ui/theme/Theme.kt | 22 ++++++++- .../simplex/common/ui/theme/ThemeManager.kt | 48 +++++++++---------- .../simplex/common/views/chat/ChatInfoView.kt | 16 +++++-- .../simplex/common/views/chat/ChatView.kt | 2 +- .../views/chat/group/GroupChatInfoView.kt | 15 ++++-- .../common/views/usersettings/Appearance.kt | 6 +-- .../kotlin/chat/simplex/desktop/Main.kt | 1 + 12 files changed, 103 insertions(+), 63 deletions(-) diff --git a/apps/multiplatform/android/src/main/java/chat/simplex/app/SimplexApp.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/SimplexApp.kt index 83105c678a..a0071b1c0f 100644 --- a/apps/multiplatform/android/src/main/java/chat/simplex/app/SimplexApp.kt +++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/SimplexApp.kt @@ -64,6 +64,7 @@ class SimplexApp: Application(), LifecycleEventObserver { } } context = this + runMigrations() initHaskell() initMultiplatform() tmpDir.deleteRecursively() @@ -254,7 +255,7 @@ class SimplexApp: Application(), LifecycleEventObserver { override fun androidSetNightModeIfSupported() { if (Build.VERSION.SDK_INT < 31) return - val light = if (CurrentColors.value.name == DefaultTheme.SYSTEM.name) { + val light = if (CurrentColors.value.name == DefaultTheme.SYSTEM.themeName) { null } else { CurrentColors.value.colors.isLight diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/ChatModel.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/ChatModel.kt index 9608bfbe7c..c480d8fd86 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/ChatModel.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/ChatModel.kt @@ -1042,7 +1042,7 @@ data class Contact( val chatTs: Instant?, val contactGroupMemberId: Long? = null, val contactGrpInvSent: Boolean, - val uiTheme: ThemeOverrides? = null, + val uiThemes: Map? = null, ): SomeChat, NamedChat { override val chatType get() = ChatType.Direct override val id get() = "@$contactId" @@ -1111,7 +1111,7 @@ data class Contact( updatedAt = Clock.System.now(), chatTs = Clock.System.now(), contactGrpInvSent = false, - uiTheme = null, + uiThemes = null, ) } } @@ -1248,7 +1248,7 @@ data class GroupInfo ( override val createdAt: Instant, override val updatedAt: Instant, val chatTs: Instant?, - val uiTheme: ThemeOverrides? = null, + val uiThemes: Map? = null, ): SomeChat, NamedChat { override val chatType get() = ChatType.Group override val id get() = "#$groupId" @@ -1291,7 +1291,7 @@ data class GroupInfo ( createdAt = Clock.System.now(), updatedAt = Clock.System.now(), chatTs = Clock.System.now(), - uiTheme = null, + uiThemes = null, ) } } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt index 556907a42d..31af6f6997 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt @@ -164,8 +164,8 @@ class AppPreferences { val selfDestruct = mkBoolPreference(SHARED_PREFS_SELF_DESTRUCT, false) val selfDestructDisplayName = mkStrPreference(SHARED_PREFS_SELF_DESTRUCT_DISPLAY_NAME, null) - val currentTheme = mkStrPreference(SHARED_PREFS_CURRENT_THEME, DefaultTheme.SYSTEM.name) - val systemDarkTheme = mkStrPreference(SHARED_PREFS_SYSTEM_DARK_THEME, DefaultTheme.SIMPLEX.name) + val currentTheme = mkStrPreference(SHARED_PREFS_CURRENT_THEME, DefaultTheme.SYSTEM.themeName) + val systemDarkTheme = mkStrPreference(SHARED_PREFS_SYSTEM_DARK_THEME, DefaultTheme.SIMPLEX.themeName) val themeOverrides = mkMapPreference(SHARED_PREFS_THEMES, mapOf(), encode = { json.encodeToString(MapSerializer(String.serializer(), ThemeOverrides.serializer()), it) }, decode = { @@ -1149,17 +1149,17 @@ object ChatController { return null } - suspend fun apiSetUserUITheme(rh: Long?, userId: Long, theme: ThemeOverrides): Boolean { - val r = sendCmd(rh, CC.ApiSetUserUITheme(userId, theme)) + suspend fun apiSetUserUIThemes(rh: Long?, userId: Long, themes: Map?): Boolean { + val r = sendCmd(rh, CC.ApiSetUserUIThemes(userId, themes)) if (r is CR.CmdOk) return true - Log.e(TAG, "apiSetUserUITheme bad response: ${r.responseType} ${r.details}") + Log.e(TAG, "apiSetUserUIThemes bad response: ${r.responseType} ${r.details}") return false } - suspend fun apiSetChatUITheme(rh: Long?, chatId: ChatId, theme: ThemeOverrides): Boolean { - val r = sendCmd(rh, CC.ApiSetChatUITheme(chatId, theme)) + suspend fun apiSetChatUIThemes(rh: Long?, chatId: ChatId, themes: Map?): Boolean { + val r = sendCmd(rh, CC.ApiSetChatUIThemes(chatId, themes)) if (r is CR.CmdOk) return true - Log.e(TAG, "apiSetChatUITheme bad response: ${r.responseType} ${r.details}") + Log.e(TAG, "apiSetChatUIThemes bad response: ${r.responseType} ${r.details}") return false } @@ -2463,8 +2463,8 @@ sealed class CC { class ApiSetContactPrefs(val contactId: Long, val prefs: ChatPreferences): CC() class ApiSetContactAlias(val contactId: Long, val localAlias: String): CC() class ApiSetConnectionAlias(val connId: Long, val localAlias: String): CC() - class ApiSetUserUITheme(val userId: Long, val theme: ThemeOverrides): CC() - class ApiSetChatUITheme(val chatId: String, val theme: ThemeOverrides): CC() + class ApiSetUserUIThemes(val userId: Long, val themes: Map?): CC() + class ApiSetChatUIThemes(val chatId: String, val themes: Map?): CC() class ApiCreateMyAddress(val userId: Long): CC() class ApiDeleteMyAddress(val userId: Long): CC() class ApiShowMyAddress(val userId: Long): CC() @@ -2609,8 +2609,8 @@ sealed class CC { is ApiSetContactPrefs -> "/_set prefs @$contactId ${json.encodeToString(prefs)}" is ApiSetContactAlias -> "/_set alias @$contactId ${localAlias.trim()}" is ApiSetConnectionAlias -> "/_set alias :$connId ${localAlias.trim()}" - is ApiSetUserUITheme -> "/_set theme user $userId ${json.encodeToString(theme)}" - is ApiSetChatUITheme -> "/_set theme $chatId ${json.encodeToString(theme)}" + is ApiSetUserUIThemes -> "/_set theme user $userId ${json.encodeToString(themes)}" + is ApiSetChatUIThemes -> "/_set theme $chatId ${json.encodeToString(themes)}" is ApiCreateMyAddress -> "/_address $userId" is ApiDeleteMyAddress -> "/_delete_address $userId" is ApiShowMyAddress -> "/_show_address $userId" @@ -2742,8 +2742,8 @@ sealed class CC { is ApiSetContactPrefs -> "apiSetContactPrefs" is ApiSetContactAlias -> "apiSetContactAlias" is ApiSetConnectionAlias -> "apiSetConnectionAlias" - is ApiSetUserUITheme -> "apiSetUserUITheme" - is ApiSetChatUITheme -> "apiSetChatUITheme" + is ApiSetUserUIThemes -> "apiSetUserUIThemes" + is ApiSetChatUIThemes -> "apiSetChatUIThemes" is ApiCreateMyAddress -> "apiCreateMyAddress" is ApiDeleteMyAddress -> "apiDeleteMyAddress" is ApiShowMyAddress -> "apiShowMyAddress" @@ -5434,7 +5434,7 @@ data class AppSettings( var iosCallKitEnabled: Boolean? = null, var iosCallKitCallsInRecents: Boolean? = null, var uiColorScheme: String? = null, - var uiThemes: List? = null, + var uiThemes: Map? = null, ) { fun prepareForExport(): AppSettings { val empty = AppSettings() @@ -5492,7 +5492,7 @@ data class AppSettings( iosCallKitEnabled?.let { def.iosCallKitEnabled.set(it) } iosCallKitCallsInRecents?.let { def.iosCallKitCallsInRecents.set(it) } uiColorScheme?.let { def.currentTheme.set(it) } - uiThemes?.let { def.themeOverrides.set(it.map { theme -> theme.base.name to theme }.toMap()) } + uiThemes?.let { def.themeOverrides.set(it) } } companion object { @@ -5517,7 +5517,7 @@ data class AppSettings( androidCallOnLockScreen = AppSettingsLockScreenCalls.SHOW, iosCallKitEnabled = true, iosCallKitCallsInRecents = false, - uiColorScheme = DefaultTheme.SYSTEM.name, + uiColorScheme = DefaultTheme.SYSTEM.themeName, uiThemes = null, ) @@ -5544,8 +5544,8 @@ data class AppSettings( androidCallOnLockScreen = AppSettingsLockScreenCalls.from(def.callOnLockScreen.get()), iosCallKitEnabled = def.iosCallKitEnabled.get(), iosCallKitCallsInRecents = def.iosCallKitCallsInRecents.get(), - uiColorScheme = def.currentTheme.get() ?: DefaultTheme.SYSTEM.name, - uiThemes = def.themeOverrides.get().values.toList(), + uiColorScheme = def.currentTheme.get() ?: DefaultTheme.SYSTEM.themeName, + uiThemes = def.themeOverrides.get(), ) } } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/platform/AppCommon.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/platform/AppCommon.kt index 7d5b1b0196..bb0a090b94 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/platform/AppCommon.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/platform/AppCommon.kt @@ -42,6 +42,12 @@ fun runMigrations() { ChatController.appPrefs.currentTheme.set(DefaultTheme.SIMPLEX.name) } lastMigration.set(117) + } else if (lastMigration.get() < 201) { + // Making theme keys lowercase as API expects + ChatController.appPrefs.themeOverrides.set(ChatController.appPrefs.themeOverrides.get().map { it.key.lowercase() to it.value }.toMap()) + ChatController.appPrefs.currentTheme.set(ChatController.appPrefs.currentTheme.get()?.lowercase()) + ChatController.appPrefs.systemDarkTheme.set(ChatController.appPrefs.systemDarkTheme.get()?.lowercase()) + lastMigration.set(201) } else { lastMigration.set(BuildConfigCommon.ANDROID_VERSION_CODE) break diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/platform/Core.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/platform/Core.kt index efc817371e..b34160817e 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/platform/Core.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/platform/Core.kt @@ -50,7 +50,6 @@ fun initChatControllerAndRunMigrations() { } else { initChatController() } - runMigrations() } } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/ui/theme/Theme.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/ui/theme/Theme.kt index 238c91cafc..85ae6b8176 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/ui/theme/Theme.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/ui/theme/Theme.kt @@ -20,6 +20,9 @@ import chat.simplex.res.MR enum class DefaultTheme { SYSTEM, LIGHT, DARK, SIMPLEX; + val themeName: String + get() = name.lowercase() + // Call it only with base theme, not SYSTEM fun hasChangedAnyColor(colors: Colors, appColors: AppColors, appWallpaper: AppWallpaper): Boolean { val palette = when (this) { @@ -324,6 +327,21 @@ data class ThemeOverrides ( } } +fun Map.preferredTheme(baseTheme: DefaultTheme = CurrentColors.value.base): ThemeOverrides? { + val idealTheme = get(baseTheme.themeName) + if (idealTheme != null) return idealTheme + + val light = get(DefaultTheme.LIGHT.themeName) + val dark = get(DefaultTheme.DARK.themeName) + val simplex = get(DefaultTheme.SIMPLEX.themeName) + return when (baseTheme.themeName) { + DefaultTheme.LIGHT.themeName -> dark ?: simplex + DefaultTheme.DARK.themeName -> simplex ?: light + DefaultTheme.SIMPLEX.themeName -> dark ?: light + else -> null + } +} + fun Modifier.themedBackground(baseTheme: DefaultTheme = CurrentColors.value.base, shape: Shape = RectangleShape): Modifier { return if (baseTheme == DefaultTheme.SIMPLEX) { this.background(brush = Brush.linearGradient( @@ -437,9 +455,9 @@ val MaterialTheme.wallpaper: AppWallpaper get() = LocalAppWallpaper.current fun reactOnDarkThemeChanges(isDark: Boolean) { - if (ChatController.appPrefs.currentTheme.get() == DefaultTheme.SYSTEM.name && CurrentColors.value.colors.isLight == isDark) { + if (ChatController.appPrefs.currentTheme.get() == DefaultTheme.SYSTEM.themeName && CurrentColors.value.colors.isLight == isDark) { // Change active colors from light to dark and back based on system theme - ThemeManager.applyTheme(DefaultTheme.SYSTEM.name, isDark) + ThemeManager.applyTheme(DefaultTheme.SYSTEM.themeName, isDark) } } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/ui/theme/ThemeManager.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/ui/theme/ThemeManager.kt index 434c316407..66792ab5ad 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/ui/theme/ThemeManager.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/ui/theme/ThemeManager.kt @@ -20,23 +20,23 @@ object ThemeManager { data class ActiveTheme(val name: String, val base: DefaultTheme, val colors: Colors, val appColors: AppColors, val wallpaper: AppWallpaper) private fun systemDarkThemeColors(): Pair = when (appPrefs.systemDarkTheme.get()) { - DefaultTheme.DARK.name -> DarkColorPalette to DefaultTheme.DARK - DefaultTheme.SIMPLEX.name -> SimplexColorPalette to DefaultTheme.SIMPLEX + DefaultTheme.DARK.themeName -> DarkColorPalette to DefaultTheme.DARK + DefaultTheme.SIMPLEX.themeName -> SimplexColorPalette to DefaultTheme.SIMPLEX else -> SimplexColorPalette to DefaultTheme.SIMPLEX } fun currentColors(darkForSystemTheme: Boolean, themeOverrides: Map = appPrefs.themeOverrides.get()): ActiveTheme { val themeName = appPrefs.currentTheme.get()!! - val nonSystemThemeName = if (themeName != DefaultTheme.SYSTEM.name) { + val nonSystemThemeName = if (themeName != DefaultTheme.SYSTEM.themeName) { themeName } else { - if (darkForSystemTheme) appPrefs.systemDarkTheme.get()!! else DefaultTheme.LIGHT.name + if (darkForSystemTheme) appPrefs.systemDarkTheme.get()!! else DefaultTheme.LIGHT.themeName } val theme = themeOverrides[nonSystemThemeName] val baseTheme = when (nonSystemThemeName) { - DefaultTheme.LIGHT.name -> Triple(DefaultTheme.LIGHT, LightColorPalette, LightColorPaletteApp) - DefaultTheme.DARK.name -> Triple(DefaultTheme.DARK, DarkColorPalette, DarkColorPaletteApp) - DefaultTheme.SIMPLEX.name -> Triple(DefaultTheme.SIMPLEX, SimplexColorPalette, SimplexColorPaletteApp) + DefaultTheme.LIGHT.themeName -> Triple(DefaultTheme.LIGHT, LightColorPalette, LightColorPaletteApp) + DefaultTheme.DARK.themeName -> Triple(DefaultTheme.DARK, DarkColorPalette, DarkColorPaletteApp) + DefaultTheme.SIMPLEX.themeName -> Triple(DefaultTheme.SIMPLEX, SimplexColorPalette, SimplexColorPaletteApp) else -> Triple(DefaultTheme.LIGHT, LightColorPalette, LightColorPaletteApp) } if (theme == null) { @@ -47,22 +47,22 @@ object ThemeManager { } fun overriddenColors(theme: ThemeOverrides): ActiveTheme { - val baseTheme = when (theme.base.name) { - DefaultTheme.LIGHT.name -> Triple(DefaultTheme.LIGHT, LightColorPalette, LightColorPaletteApp) - DefaultTheme.DARK.name -> Triple(DefaultTheme.DARK, DarkColorPalette, DarkColorPaletteApp) - DefaultTheme.SIMPLEX.name -> Triple(DefaultTheme.SIMPLEX, SimplexColorPalette, SimplexColorPaletteApp) + val baseTheme = when (theme.base.themeName) { + DefaultTheme.LIGHT.themeName -> Triple(DefaultTheme.LIGHT, LightColorPalette, LightColorPaletteApp) + DefaultTheme.DARK.themeName -> Triple(DefaultTheme.DARK, DarkColorPalette, DarkColorPaletteApp) + DefaultTheme.SIMPLEX.themeName -> Triple(DefaultTheme.SIMPLEX, SimplexColorPalette, SimplexColorPaletteApp) else -> Triple(DefaultTheme.LIGHT, LightColorPalette, LightColorPaletteApp) } val backgroundTheme = if (theme.wallpaper.preset != null) PredefinedBackgroundImage.from(theme.wallpaper.preset)?.colors?.get(theme.base) else null - return ActiveTheme(theme.base.name, baseTheme.first, theme.colors.toColors(theme.base, backgroundTheme), theme.colors.toAppColors(theme.base, backgroundTheme), theme.wallpaper.toAppWallpaper()) + return ActiveTheme(theme.base.themeName, baseTheme.first, theme.colors.toColors(theme.base, backgroundTheme), theme.colors.toAppColors(theme.base, backgroundTheme), theme.wallpaper.toAppWallpaper()) } fun currentThemeOverridesForExport(darkForSystemTheme: Boolean): ThemeOverrides { val themeName = appPrefs.currentTheme.get()!! - val nonSystemThemeName = if (themeName != DefaultTheme.SYSTEM.name) { + val nonSystemThemeName = if (themeName != DefaultTheme.SYSTEM.themeName) { themeName } else { - if (darkForSystemTheme) appPrefs.systemDarkTheme.get()!! else DefaultTheme.LIGHT.name + if (darkForSystemTheme) appPrefs.systemDarkTheme.get()!! else DefaultTheme.LIGHT.themeName } val overrides = appPrefs.themeOverrides.get().toMutableMap() val nonFilledTheme = overrides.getOrDefault(nonSystemThemeName, ThemeOverrides()) @@ -116,14 +116,14 @@ object ThemeManager { } fun saveAndApplyThemeColor(baseTheme: DefaultTheme, name: ThemeColor, color: Color? = null, pref: SharedPreference> = appPrefs.themeOverrides) { - val nonSystemThemeName = baseTheme.name + val nonSystemThemeName = baseTheme.themeName var colorToSet = color if (colorToSet == null) { // Setting default color from a base theme colorToSet = when(nonSystemThemeName) { - DefaultTheme.LIGHT.name -> name.fromColors(LightColorPalette, LightColorPaletteApp, AppWallpaper()) - DefaultTheme.DARK.name -> name.fromColors(DarkColorPalette, DarkColorPaletteApp, AppWallpaper()) - DefaultTheme.SIMPLEX.name -> name.fromColors(SimplexColorPalette, SimplexColorPaletteApp, AppWallpaper()) + DefaultTheme.LIGHT.themeName -> name.fromColors(LightColorPalette, LightColorPaletteApp, AppWallpaper()) + DefaultTheme.DARK.themeName -> name.fromColors(DarkColorPalette, DarkColorPaletteApp, AppWallpaper()) + DefaultTheme.SIMPLEX.themeName -> name.fromColors(SimplexColorPalette, SimplexColorPaletteApp, AppWallpaper()) // Will not be here else -> return } @@ -136,7 +136,7 @@ object ThemeManager { } fun saveAndApplyBackgroundImage(baseTheme: DefaultTheme, type: BackgroundImageType?, pref: SharedPreference> = appPrefs.themeOverrides) { - val nonSystemThemeName = baseTheme.name + val nonSystemThemeName = baseTheme.themeName val overrides = pref.get().toMutableMap() var prevValue = overrides.getOrDefault(nonSystemThemeName, ThemeOverrides()) // Overriding the whole theme on type change @@ -150,19 +150,19 @@ object ThemeManager { fun saveAndApplyThemeOverrides(theme: ThemeOverrides, pref: SharedPreference> = appPrefs.themeOverrides) { val overrides = pref.get().toMutableMap() - val prevValue = overrides.getOrDefault(theme.base.name, ThemeOverrides()) - overrides[theme.base.name] = prevValue.copy(colors = theme.colors, wallpaper = theme.wallpaper.importFromString()) + val prevValue = overrides.getOrDefault(theme.base.themeName, ThemeOverrides()) + overrides[theme.base.themeName] = prevValue.copy(colors = theme.colors, wallpaper = theme.wallpaper.importFromString()) pref.set(overrides) - appPrefs.currentTheme.set(theme.base.name) + appPrefs.currentTheme.set(theme.base.themeName) CurrentColors.value = currentColors(!CurrentColors.value.colors.isLight, appPrefs.themeOverrides.get()) } fun resetAllThemeColors(darkForSystemTheme: Boolean, pref: SharedPreference> = appPrefs.themeOverrides) { val themeName = appPrefs.currentTheme.get()!! - val nonSystemThemeName = if (themeName != DefaultTheme.SYSTEM.name) { + val nonSystemThemeName = if (themeName != DefaultTheme.SYSTEM.themeName) { themeName } else { - if (darkForSystemTheme) appPrefs.systemDarkTheme.get()!! else DefaultTheme.LIGHT.name + if (darkForSystemTheme) appPrefs.systemDarkTheme.get()!! else DefaultTheme.LIGHT.themeName } val overrides = pref.get().toMutableMap() val prevValue = overrides[nonSystemThemeName] ?: return diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatInfoView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatInfoView.kt index 7bc8c4c154..3a097df10c 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatInfoView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatInfoView.kt @@ -339,15 +339,21 @@ fun ChatInfoLayout( SynchronizeConnectionButton(syncContactConnection) } - val theme = remember { (chat.chatInfo as ChatInfo.Direct).contact.uiTheme ?: ThemeOverrides() } + val theme = remember { + // Using existing theme overrides as an overrides for a new theme if the same BASE theme is not found in already configured map + (chat.chatInfo as ChatInfo.Direct).contact.uiThemes?.preferredTheme()?.copy(base = CurrentColors.value.base) ?: ThemeOverrides() + } + WallpaperButton { ModalManager.end.showModal { WallpaperEditor(theme) { type, theme -> withBGApi { - if (controller.apiSetChatUITheme(chat.remoteHostId, chat.id, theme.copy(wallpaper = theme.wallpaper.withFilledWallpaperPath()))) { + val changedThemes = ((chat.chatInfo as ChatInfo.Direct).contact.uiThemes ?: mapOf()).toMutableMap() + changedThemes[theme.base.themeName] = theme.copy(wallpaper = theme.wallpaper.withFilledWallpaperPath()) + if (controller.apiSetChatUIThemes(chat.remoteHostId, chat.id, changedThemes)) { // Remove previous image only after saving removeBackgroundImage(theme.wallpaper.imageFile) - chatModel.updateChatInfo(chat.remoteHostId, (chat.chatInfo as ChatInfo.Direct).copy(contact = chat.chatInfo.contact.copy(uiTheme = theme.copy(wallpaper = theme.wallpaper.withFilledWallpaperPath())))) + chatModel.updateChatInfo(chat.remoteHostId, chat.chatInfo.copy(contact = chat.chatInfo.contact.copy(uiThemes = changedThemes))) } } } @@ -712,10 +718,10 @@ fun ModalData.WallpaperEditor(theme: ThemeOverrides, save: (BackgroundImageType? val pref = remember { SharedPreference>( get = { - mapOf(baseTheme.name to themeOverrides.value) + mapOf(baseTheme.themeName to themeOverrides.value) }, set = { value -> - themeOverrides.value = value[baseTheme.name]!! + themeOverrides.value = value[baseTheme.themeName]!! } ) } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatView.kt index 75db512dcd..c5085ca3ee 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatView.kt @@ -117,7 +117,7 @@ fun ChatView(chatId: String, chatModel: ChatModel, onComposed: suspend (chatId: val clipboard = LocalClipboardManager.current when (chat.chatInfo) { is ChatInfo.Direct, is ChatInfo.Group, is ChatInfo.Local -> { - val themeOverrides = remember(chat.chatInfo) { if (chat.chatInfo is ChatInfo.Direct) chat.chatInfo.contact.uiTheme else if (chat.chatInfo is ChatInfo.Group) chat.chatInfo.groupInfo.uiTheme else null } + val themeOverrides = remember(chat.chatInfo) { if (chat.chatInfo is ChatInfo.Direct) chat.chatInfo.contact.uiThemes?.preferredTheme() else if (chat.chatInfo is ChatInfo.Group) chat.chatInfo.groupInfo.uiThemes?.preferredTheme() else null } val overrides = if (themeOverrides != null) ThemeManager.overriddenColors(themeOverrides) else null SimpleXThemeOverride(overrides ?: CurrentColors.collectAsState().value) { ChatLayout( diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupChatInfoView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupChatInfoView.kt index 76308d22dc..9a4b7b0323 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupChatInfoView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupChatInfoView.kt @@ -235,13 +235,22 @@ fun GroupChatInfoLayout( SendReceiptsOptionDisabled() } - val theme = remember { (chat.chatInfo as ChatInfo.Group).groupInfo.uiTheme ?: ThemeOverrides() } + val theme = remember { + // Using existing theme overrides as an overrides for a new theme if the same BASE theme is not found in already configured map + (chat.chatInfo as ChatInfo.Group).groupInfo.uiThemes?.preferredTheme()?.copy(base = CurrentColors.value.base) ?: ThemeOverrides() + } WallpaperButton { ModalManager.end.showModal { WallpaperEditor(theme) { type, theme -> withBGApi { - controller.apiSetChatUITheme(chat.remoteHostId, chat.id, theme.copy(wallpaper = theme.wallpaper.withFilledWallpaperPath())) - chatModel.updateChatInfo(chat.remoteHostId, (chat.chatInfo as ChatInfo.Group).copy(groupInfo = chat.chatInfo.groupInfo.copy(uiTheme = theme.copy(wallpaper = theme.wallpaper.withFilledWallpaperPath())))) + val changedThemes = ((chat.chatInfo as ChatInfo.Direct).contact.uiThemes ?: mapOf()).toMutableMap() + changedThemes[theme.base.themeName] = theme.copy(wallpaper = theme.wallpaper.withFilledWallpaperPath()) + if (controller.apiSetChatUIThemes(chat.remoteHostId, chat.id, changedThemes)) { + // Remove previous image only after saving + removeBackgroundImage(theme.wallpaper.imageFile) + chatModel.updateChatInfo(chat.remoteHostId, chat.chatInfo.copy(contact = chat.chatInfo.contact.copy(uiThemes = changedThemes))) + } + } } } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/Appearance.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/Appearance.kt index 89ee351ebe..4d2e910cde 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/Appearance.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/Appearance.kt @@ -244,7 +244,7 @@ object AppearanceScope { ThemeSelector(state) { ThemeManager.applyTheme(it, darkTheme) } - if (state.value == DefaultTheme.SYSTEM.name) { + if (state.value == DefaultTheme.SYSTEM.themeName) { DarkThemeSelector(remember { systemDarkTheme.state }) { ThemeManager.changeDarkTheme(it, darkTheme) } @@ -505,8 +505,8 @@ object AppearanceScope { private fun DarkThemeSelector(state: State, onSelected: (String) -> Unit) { val values by remember { val darkThemes = ArrayList>() - darkThemes.add(DefaultTheme.DARK.name to generalGetString(MR.strings.theme_dark)) - darkThemes.add(DefaultTheme.SIMPLEX.name to generalGetString(MR.strings.theme_simplex)) + darkThemes.add(DefaultTheme.DARK.themeName to generalGetString(MR.strings.theme_dark)) + darkThemes.add(DefaultTheme.SIMPLEX.themeName to generalGetString(MR.strings.theme_simplex)) mutableStateOf(darkThemes.toList()) } ExposedDropDownSettingRow( diff --git a/apps/multiplatform/desktop/src/jvmMain/kotlin/chat/simplex/desktop/Main.kt b/apps/multiplatform/desktop/src/jvmMain/kotlin/chat/simplex/desktop/Main.kt index 7171f17991..76850b0d4d 100644 --- a/apps/multiplatform/desktop/src/jvmMain/kotlin/chat/simplex/desktop/Main.kt +++ b/apps/multiplatform/desktop/src/jvmMain/kotlin/chat/simplex/desktop/Main.kt @@ -17,6 +17,7 @@ import kotlinx.coroutines.* import java.io.File fun main() { + runMigrations() initHaskell() initApp() tmpDir.deleteRecursively()