From a5e74ea2f0545e201af1a24a832eecfd08caef2b Mon Sep 17 00:00:00 2001 From: Stanislav Dmitrenko <7953703+avently@users.noreply.github.com> Date: Wed, 24 Aug 2022 23:15:26 +0300 Subject: [PATCH] android: choosing theme and accent color (#967) * Theme selector - ability to select from three default choices: system theme, light, dark - ability to choose color accent (primary color) * Removed unused code and made small changes to colors and buttons --- apps/android/app/build.gradle | 1 + .../java/chat/simplex/app/model/SimpleXAPI.kt | 8 +- .../java/chat/simplex/app/ui/theme/Theme.kt | 39 ++++-- .../chat/simplex/app/ui/theme/ThemeManager.kt | 64 ++++++++++ .../app/views/call/IncomingCallAlertView.kt | 2 +- .../simplex/app/views/chat/ChatInfoView.kt | 2 +- .../chat/simplex/app/views/chat/ChatView.kt | 6 +- .../simplex/app/views/chat/ComposeFileView.kt | 3 +- .../views/chat/group/AddGroupMembersView.kt | 2 +- .../app/views/chat/group/GroupChatInfoView.kt | 4 +- .../views/chat/group/GroupMemberInfoView.kt | 2 +- .../simplex/app/views/chat/item/CIFileView.kt | 5 +- .../views/chat/item/CIGroupInvitationView.kt | 3 +- .../simplex/app/views/chat/item/CIMetaView.kt | 6 +- .../app/views/chat/item/FramedItemView.kt | 2 +- .../app/views/chatlist/ChatPreviewView.kt | 3 +- .../views/chatlist/ContactConnectionView.kt | 3 +- .../app/views/chatlist/ContactRequestView.kt | 3 +- .../simplex/app/views/helpers/AlertManager.kt | 5 +- .../app/views/helpers/DefaultTopAppBar.kt | 5 +- .../chat/simplex/app/views/helpers/Section.kt | 31 ++++- .../simplex/app/views/newchat/AddGroupView.kt | 2 +- .../app/views/onboarding/SimpleXInfo.kt | 3 +- .../app/views/usersettings/Appearance.kt | 117 ++++++++++++++++-- .../app/views/usersettings/SettingsView.kt | 24 +--- .../app/views/usersettings/ThemeSelector.kt | 69 +++++++++++ .../app/src/main/res/values-ru/strings.xml | 14 ++- .../app/src/main/res/values/strings.xml | 14 ++- 28 files changed, 358 insertions(+), 84 deletions(-) create mode 100644 apps/android/app/src/main/java/chat/simplex/app/ui/theme/ThemeManager.kt create mode 100644 apps/android/app/src/main/java/chat/simplex/app/views/usersettings/ThemeSelector.kt diff --git a/apps/android/app/build.gradle b/apps/android/app/build.gradle index 4765f58c5e..4fc7791a26 100644 --- a/apps/android/app/build.gradle +++ b/apps/android/app/build.gradle @@ -94,6 +94,7 @@ dependencies { implementation "androidx.navigation:navigation-compose:2.4.1" implementation "com.google.accompanist:accompanist-insets:0.23.0" implementation 'androidx.webkit:webkit:1.4.0' + implementation "com.godaddy.android.colorpicker:compose-color-picker:0.4.2" def work_version = "2.7.1" implementation "androidx.work:work-runtime-ktx:$work_version" diff --git a/apps/android/app/src/main/java/chat/simplex/app/model/SimpleXAPI.kt b/apps/android/app/src/main/java/chat/simplex/app/model/SimpleXAPI.kt index 2166882959..44f4e7f7c6 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/model/SimpleXAPI.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/model/SimpleXAPI.kt @@ -5,7 +5,6 @@ import android.app.ActivityManager import android.app.ActivityManager.RunningAppProcessInfo import android.app.Application import android.content.* -import android.content.pm.PackageManager import android.net.Uri import android.os.Build import android.os.PowerManager @@ -16,12 +15,14 @@ import androidx.compose.material.* import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.Bolt import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.fragment.app.FragmentActivity import chat.simplex.app.* import chat.simplex.app.R +import chat.simplex.app.ui.theme.* import chat.simplex.app.views.call.* import chat.simplex.app.views.helpers.* import chat.simplex.app.views.onboarding.OnboardingStage @@ -95,6 +96,9 @@ class AppPreferences(val context: Context) { val networkTCPKeepIntvl = mkIntPreference(SHARED_PREFS_NETWORK_TCP_KEEP_INTVL, KeepAliveOpts.defaults.keepIntvl) val networkTCPKeepCnt = mkIntPreference(SHARED_PREFS_NETWORK_TCP_KEEP_CNT, KeepAliveOpts.defaults.keepCnt) + val currentTheme = mkStrPreference(SHARED_PREFS_CURRENT_THEME, DefaultTheme.SYSTEM.name) + val primaryColor = mkIntPreference(SHARED_PREFS_PRIMARY_COLOR, LightColorPalette.primary.toArgb()) + private fun mkIntPreference(prefName: String, default: Int) = Preference( get = fun() = sharedPreferences.getInt(prefName, default), @@ -161,6 +165,8 @@ class AppPreferences(val context: Context) { private const val SHARED_PREFS_NETWORK_TCP_KEEP_IDLE = "NetworkTCPKeepIdle" private const val SHARED_PREFS_NETWORK_TCP_KEEP_INTVL = "NetworkTCPKeepIntvl" private const val SHARED_PREFS_NETWORK_TCP_KEEP_CNT = "NetworkTCPKeepCnt" + private const val SHARED_PREFS_CURRENT_THEME = "CurrentTheme" + private const val SHARED_PREFS_PRIMARY_COLOR = "PrimaryColor" } } diff --git a/apps/android/app/src/main/java/chat/simplex/app/ui/theme/Theme.kt b/apps/android/app/src/main/java/chat/simplex/app/ui/theme/Theme.kt index a7ee4c9fb7..a475beed7c 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/ui/theme/Theme.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/ui/theme/Theme.kt @@ -2,10 +2,15 @@ package chat.simplex.app.ui.theme import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.material.* -import androidx.compose.runtime.Composable +import androidx.compose.runtime.* import androidx.compose.ui.graphics.Color +import kotlinx.coroutines.flow.MutableStateFlow -private val DarkColorPalette = darkColors( +enum class DefaultTheme { + SYSTEM, DARK, LIGHT +} + +val DarkColorPalette = darkColors( primary = SimplexBlue, // If this value changes also need to update #0088ff in string resource files primaryVariant = SimplexGreen, secondary = DarkGray, @@ -18,7 +23,7 @@ private val DarkColorPalette = darkColors( onSurface = Color(0xFFFFFBFA), // onError: Color = Color.Black, ) -private val LightColorPalette = lightColors( +val LightColorPalette = lightColors( primary = SimplexBlue, // If this value changes also need to update #0088ff in string resource files primaryVariant = SimplexGreen, secondary = LightGray, @@ -30,16 +35,28 @@ private val LightColorPalette = lightColors( // onSurface = Color.Black, ) -@Composable -fun SimpleXTheme(darkTheme: Boolean = isSystemInDarkTheme(), content: @Composable () -> Unit) { - val colors = if (darkTheme) { - DarkColorPalette - } else { - LightColorPalette - } +val CurrentColors: MutableStateFlow> = MutableStateFlow(ThemeManager.currentColors(true)) +@Composable +fun isInDarkTheme(): Boolean = !CurrentColors.collectAsState().value.first.isLight + +@Composable +fun SimpleXTheme(darkTheme: Boolean? = null, content: @Composable () -> Unit) { + LaunchedEffect(darkTheme) { + // For preview + if (darkTheme != null) + CurrentColors.value = ThemeManager.currentColors(darkTheme) + } + val systemDark = isSystemInDarkTheme() + LaunchedEffect(systemDark) { + if (CurrentColors.value.second == DefaultTheme.SYSTEM && CurrentColors.value.first.isLight == systemDark) { + // Change active colors from light to dark and back based on system theme + ThemeManager.applyTheme(DefaultTheme.SYSTEM.name, systemDark) + } + } + val theme by CurrentColors.collectAsState() MaterialTheme( - colors = colors, + colors = theme.first, typography = Typography, shapes = Shapes, content = content diff --git a/apps/android/app/src/main/java/chat/simplex/app/ui/theme/ThemeManager.kt b/apps/android/app/src/main/java/chat/simplex/app/ui/theme/ThemeManager.kt new file mode 100644 index 0000000000..a1d5ee4526 --- /dev/null +++ b/apps/android/app/src/main/java/chat/simplex/app/ui/theme/ThemeManager.kt @@ -0,0 +1,64 @@ +package chat.simplex.app.ui.theme + +import androidx.compose.material.Colors +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.toArgb +import chat.simplex.app.R +import chat.simplex.app.SimplexApp +import chat.simplex.app.model.AppPreferences +import chat.simplex.app.views.helpers.generalGetString + +object ThemeManager { + private val appPrefs: AppPreferences by lazy { + AppPreferences(SimplexApp.context) + } + + fun currentColors(darkForSystemTheme: Boolean): Pair { + val theme = appPrefs.currentTheme.get()!! + val systemThemeColors = if (darkForSystemTheme) DarkColorPalette else LightColorPalette + val res = when (theme) { + DefaultTheme.SYSTEM.name -> Pair(systemThemeColors, DefaultTheme.SYSTEM) + DefaultTheme.DARK.name -> Pair(DarkColorPalette, DefaultTheme.DARK) + DefaultTheme.LIGHT.name -> Pair(LightColorPalette, DefaultTheme.LIGHT) + else -> Pair(systemThemeColors, DefaultTheme.SYSTEM) + } + return res.copy(first = res.first.copy(primary = Color(appPrefs.primaryColor.get()))) + } + + // colors, default theme enum, localized name of theme + fun allThemes(darkForSystemTheme: Boolean): List> { + val allThemes = ArrayList>() + allThemes.add( + Triple( + if (darkForSystemTheme) DarkColorPalette else LightColorPalette, + DefaultTheme.SYSTEM, + generalGetString(R.string.theme_system) + ) + ) + allThemes.add( + Triple( + LightColorPalette, + DefaultTheme.LIGHT, + generalGetString(R.string.theme_light) + ) + ) + allThemes.add( + Triple( + DarkColorPalette, + DefaultTheme.DARK, + generalGetString(R.string.theme_dark) + ) + ) + return allThemes + } + + fun applyTheme(name: String, darkForSystemTheme: Boolean) { + appPrefs.currentTheme.set(name) + CurrentColors.value = currentColors(darkForSystemTheme) + } + + fun saveAndApplyPrimaryColor(color: Color) { + appPrefs.primaryColor.set(color.toArgb()) + CurrentColors.value = currentColors(!CurrentColors.value.first.isLight) + } +} diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/call/IncomingCallAlertView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/call/IncomingCallAlertView.kt index 631649211c..31e99eda96 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/call/IncomingCallAlertView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/call/IncomingCallAlertView.kt @@ -45,7 +45,7 @@ fun IncomingCallAlertLayout( ignoreCall: () -> Unit, acceptCall: () -> Unit ) { - val color = if (isSystemInDarkTheme()) IncomingCallDark else IncomingCallLight + val color = if (isInDarkTheme()) IncomingCallDark else IncomingCallLight Column(Modifier.background(color).padding(top = 16.dp, bottom = 16.dp, start = 16.dp, end = 8.dp)) { IncomingCallInfo(invitation) Spacer(Modifier.height(8.dp)) diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatInfoView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatInfoView.kt index 72c656261c..1734a3f1b5 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatInfoView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatInfoView.kt @@ -198,7 +198,7 @@ fun ChatInfoHeader(cInfo: ChatInfo) { Modifier.padding(horizontal = 8.dp), horizontalAlignment = Alignment.CenterHorizontally ) { - ChatInfoImage(cInfo, size = 192.dp, iconColor = if (isSystemInDarkTheme()) GroupDark else SettingsSecondaryLight) + ChatInfoImage(cInfo, size = 192.dp, iconColor = if (isInDarkTheme()) GroupDark else SettingsSecondaryLight) Text( cInfo.displayName, style = MaterialTheme.typography.h1.copy(fontWeight = FontWeight.Normal), color = MaterialTheme.colors.onBackground, diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatView.kt index 095f3aec15..f56e5e90f5 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatView.kt @@ -114,7 +114,7 @@ fun ChatView(chatModel: ChatModel) { ModalManager.shared.showCustomModal { close -> ModalView( close = close, modifier = Modifier, - background = if (isSystemInDarkTheme()) MaterialTheme.colors.background else SettingsBackgroundLight + background = if (isInDarkTheme()) MaterialTheme.colors.background else SettingsBackgroundLight ) { ChatInfoView(chatModel, connStats, close) } @@ -124,7 +124,7 @@ fun ChatView(chatModel: ChatModel) { ModalManager.shared.showCustomModal { close -> ModalView( close = close, modifier = Modifier, - background = if (isSystemInDarkTheme()) MaterialTheme.colors.background else SettingsBackgroundLight + background = if (isInDarkTheme()) MaterialTheme.colors.background else SettingsBackgroundLight ) { GroupChatInfoView(chatModel, close) } @@ -189,7 +189,7 @@ fun ChatView(chatModel: ChatModel) { ModalManager.shared.showCustomModal { close -> ModalView( close = close, modifier = Modifier, - background = if (isSystemInDarkTheme()) MaterialTheme.colors.background else SettingsBackgroundLight + background = if (isInDarkTheme()) MaterialTheme.colors.background else SettingsBackgroundLight ) { AddGroupMembersView(groupInfo, chatModel, close) } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ComposeFileView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/ComposeFileView.kt index 48917ec05e..dd7b628e1e 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ComposeFileView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/ComposeFileView.kt @@ -1,5 +1,4 @@ import androidx.compose.foundation.background -import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.* import androidx.compose.material.* import androidx.compose.material.icons.Icons @@ -31,7 +30,7 @@ fun ComposeFileView(fileName: String, cancelFile: () -> Unit, cancelEnabled: Boo Modifier .padding(start = 4.dp, end = 2.dp) .size(36.dp), - tint = if (isSystemInDarkTheme()) FileDark else FileLight + tint = if (isInDarkTheme()) FileDark else FileLight ) Text(fileName) Spacer(Modifier.weight(1f)) diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/AddGroupMembersView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/AddGroupMembersView.kt index b88c0b5470..6730da6fb3 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/AddGroupMembersView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/AddGroupMembersView.kt @@ -93,7 +93,7 @@ fun AddGroupMembersLayout( ChatInfoToolbarTitle( ChatInfo.Group(groupInfo), imageSize = 60.dp, - iconColor = if (isSystemInDarkTheme()) GroupDark else SettingsSecondaryLight + iconColor = if (isInDarkTheme()) GroupDark else SettingsSecondaryLight ) } SectionSpacer() diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupChatInfoView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupChatInfoView.kt index d2d7787718..3c827752c5 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupChatInfoView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupChatInfoView.kt @@ -47,7 +47,7 @@ fun GroupChatInfoView(chatModel: ChatModel, close: () -> Unit) { ModalManager.shared.showCustomModal { close -> ModalView( close = close, modifier = Modifier, - background = if (isSystemInDarkTheme()) MaterialTheme.colors.background else SettingsBackgroundLight + background = if (isInDarkTheme()) MaterialTheme.colors.background else SettingsBackgroundLight ) { AddGroupMembersView(groupInfo, chatModel, close) } @@ -60,7 +60,7 @@ fun GroupChatInfoView(chatModel: ChatModel, close: () -> Unit) { ModalManager.shared.showCustomModal { close -> ModalView( close = close, modifier = Modifier, - background = if (isSystemInDarkTheme()) MaterialTheme.colors.background else SettingsBackgroundLight + background = if (isInDarkTheme()) MaterialTheme.colors.background else SettingsBackgroundLight ) { GroupMemberInfoView(groupInfo, member, connStats, chatModel, close) } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupMemberInfoView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupMemberInfoView.kt index 6a0209cc1e..ba0a39bd3f 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupMemberInfoView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupMemberInfoView.kt @@ -139,7 +139,7 @@ fun GroupMemberInfoHeader(member: GroupMember) { Modifier.padding(horizontal = 8.dp), horizontalAlignment = Alignment.CenterHorizontally ) { - ProfileImage(size = 192.dp, member.image, color = if (isSystemInDarkTheme()) GroupDark else SettingsSecondaryLight) + ProfileImage(size = 192.dp, member.image, color = if (isInDarkTheme()) GroupDark else SettingsSecondaryLight) Text( member.displayName, style = MaterialTheme.typography.h1.copy(fontWeight = FontWeight.Normal), color = MaterialTheme.colors.onBackground, diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIFileView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIFileView.kt index fdf25baba9..dd5992600d 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIFileView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIFileView.kt @@ -2,7 +2,6 @@ package chat.simplex.app.views.chat.item import android.widget.Toast import androidx.compose.foundation.clickable -import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.* @@ -39,7 +38,7 @@ fun CIFileView( @Composable fun fileIcon( innerIcon: ImageVector? = null, - color: Color = if (isSystemInDarkTheme()) FileDark else FileLight + color: Color = if (isInDarkTheme()) FileDark else FileLight ) { Box( contentAlignment = Alignment.Center @@ -105,7 +104,7 @@ fun CIFileView( fun progressIndicator() { CircularProgressIndicator( Modifier.size(32.dp), - color = if (isSystemInDarkTheme()) FileDark else FileLight, + color = if (isInDarkTheme()) FileDark else FileLight, strokeWidth = 4.dp ) } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIGroupInvitationView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIGroupInvitationView.kt index 03db38ba4b..73e7608d2b 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIGroupInvitationView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIGroupInvitationView.kt @@ -3,7 +3,6 @@ package chat.simplex.app.views.chat.item import android.content.res.Configuration import android.util.Log import androidx.compose.foundation.clickable -import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.* @@ -39,7 +38,7 @@ fun CIGroupInvitationView( val p = groupInvitation.groupProfile val iconColor = if (action) MaterialTheme.colors.primary - else if (isSystemInDarkTheme()) FileDark else FileLight + else if (isInDarkTheme()) FileDark else FileLight Row( Modifier diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIMetaView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIMetaView.kt index 126b477e80..f5566b6f19 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIMetaView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIMetaView.kt @@ -1,8 +1,7 @@ package chat.simplex.app.views.chat.item import androidx.compose.foundation.layout.* -import androidx.compose.material.Icon -import androidx.compose.material.Text +import androidx.compose.material.* import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.* import androidx.compose.runtime.Composable @@ -16,7 +15,6 @@ import androidx.compose.ui.unit.sp import chat.simplex.app.R import chat.simplex.app.model.* import chat.simplex.app.ui.theme.HighOrLowlight -import chat.simplex.app.ui.theme.SimplexBlue import kotlinx.datetime.Clock @Composable @@ -56,7 +54,7 @@ fun CIStatusView(status: CIStatus, metaColor: Color = HighOrLowlight) { Icon(Icons.Filled.WarningAmber, stringResource(R.string.icon_descr_sent_msg_status_send_failed), Modifier.height(12.dp), tint = Color.Yellow) } is CIStatus.RcvNew -> { - Icon(Icons.Filled.Circle, stringResource(R.string.icon_descr_received_msg_status_unread), Modifier.height(12.dp), tint = SimplexBlue) + Icon(Icons.Filled.Circle, stringResource(R.string.icon_descr_received_msg_status_unread), Modifier.height(12.dp), tint = MaterialTheme.colors.primary) } else -> {} } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/FramedItemView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/FramedItemView.kt index ff69501d0c..d74392946d 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/FramedItemView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/FramedItemView.kt @@ -87,7 +87,7 @@ fun FramedItemView( Modifier .padding(top = 6.dp, end = 4.dp) .size(22.dp), - tint = if (isSystemInDarkTheme()) FileDark else FileLight + tint = if (isInDarkTheme()) FileDark else FileLight ) } else -> ciQuotedMsgView(qi) diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatPreviewView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatPreviewView.kt index 5bb8e8526f..dc71336cef 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatPreviewView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatPreviewView.kt @@ -2,7 +2,6 @@ package chat.simplex.app.views.chatlist import android.content.res.Configuration import androidx.compose.foundation.background -import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.CircleShape import androidx.compose.material.* @@ -88,7 +87,7 @@ fun ChatPreviewView(chat: Chat, stopped: Boolean) { metaText = ci.timestampText, maxLines = 2, overflow = TextOverflow.Ellipsis, - style = MaterialTheme.typography.body1.copy(color = if (isSystemInDarkTheme()) MessagePreviewDark else MessagePreviewLight, lineHeight = 22.sp), + style = MaterialTheme.typography.body1.copy(color = if (isInDarkTheme()) MessagePreviewDark else MessagePreviewLight, lineHeight = 22.sp), ) } else { when (cInfo) { diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ContactConnectionView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ContactConnectionView.kt index 318f1a0093..2ee852aeb3 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ContactConnectionView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ContactConnectionView.kt @@ -1,6 +1,5 @@ package chat.simplex.app.views.chatlist -import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.* import androidx.compose.material.MaterialTheme import androidx.compose.material.Text @@ -37,7 +36,7 @@ fun ContactConnectionView(contactConnection: PendingContactConnection) { fontWeight = FontWeight.Bold, color = HighOrLowlight ) - Text(contactConnection.description, maxLines = 2, color = if (isSystemInDarkTheme()) MessagePreviewDark else MessagePreviewLight) + Text(contactConnection.description, maxLines = 2, color = if (isInDarkTheme()) MessagePreviewDark else MessagePreviewLight) } val ts = getTimestampText(contactConnection.updatedAt) Column( diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ContactRequestView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ContactRequestView.kt index 3b90163243..6ec6263f26 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ContactRequestView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ContactRequestView.kt @@ -1,6 +1,5 @@ package chat.simplex.app.views.chatlist -import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.* import androidx.compose.material.MaterialTheme import androidx.compose.material.Text @@ -33,7 +32,7 @@ fun ContactRequestView(contactRequest: ChatInfo.ContactRequest) { fontWeight = FontWeight.Bold, color = MaterialTheme.colors.primary ) - Text(stringResource(R.string.contact_wants_to_connect_with_you), maxLines = 2, color = if (isSystemInDarkTheme()) MessagePreviewDark else MessagePreviewLight) + Text(stringResource(R.string.contact_wants_to_connect_with_you), maxLines = 2, color = if (isInDarkTheme()) MessagePreviewDark else MessagePreviewLight) } val ts = getTimestampText(contactRequest.contactRequest.updatedAt) Column( diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/AlertManager.kt b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/AlertManager.kt index 55715f8e84..f4a6595798 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/AlertManager.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/AlertManager.kt @@ -2,8 +2,9 @@ package chat.simplex.app.views.helpers import android.util.Log import androidx.compose.material.* -import androidx.compose.runtime.Composable -import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.* +import androidx.compose.ui.ExperimentalComposeUiApi +import androidx.compose.ui.Modifier import chat.simplex.app.R import chat.simplex.app.TAG diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/DefaultTopAppBar.kt b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/DefaultTopAppBar.kt index 1e6c37902a..a4962dc7a8 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/DefaultTopAppBar.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/DefaultTopAppBar.kt @@ -13,8 +13,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.* import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import chat.simplex.app.ui.theme.ToolbarDark -import chat.simplex.app.ui.theme.ToolbarLight +import chat.simplex.app.ui.theme.* @Composable fun DefaultTopAppBar( @@ -39,7 +38,7 @@ fun DefaultTopAppBar( SearchTextField(Modifier.fillMaxWidth(), stringResource(android.R.string.search_go), onSearchValueChanged) } }, - backgroundColor = if (isSystemInDarkTheme()) ToolbarDark else ToolbarLight, + backgroundColor = if (isInDarkTheme()) ToolbarDark else ToolbarLight, navigationIcon = navigationButton, buttons = if (!showSearch) buttons else emptyList(), centered = !showSearch diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/Section.kt b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/Section.kt index 6a04db96e3..9ec912abcb 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/Section.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/Section.kt @@ -1,5 +1,4 @@ import androidx.compose.foundation.clickable -import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.* import androidx.compose.material.* import androidx.compose.runtime.Composable @@ -8,8 +7,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.* -import chat.simplex.app.ui.theme.GroupDark -import chat.simplex.app.ui.theme.HighOrLowlight +import chat.simplex.app.ui.theme.* @Composable fun SectionView(title: String? = null, content: (@Composable () -> Unit)) { @@ -20,7 +18,7 @@ fun SectionView(title: String? = null, content: (@Composable () -> Unit)) { modifier = Modifier.padding(start = 16.dp, bottom = 5.dp), fontSize = 12.sp ) } - Surface(color = if (isSystemInDarkTheme()) GroupDark else MaterialTheme.colors.background) { + Surface(color = if (isInDarkTheme()) GroupDark else MaterialTheme.colors.background) { Column(Modifier.padding(horizontal = 6.dp).fillMaxWidth()) { content() } } } @@ -40,6 +38,27 @@ fun SectionItemView(click: (() -> Unit)? = null, height: Dp = 46.dp, disabled: B } } +@Composable +fun SectionItemViewSpaceBetween( + click: (() -> Unit)? = null, + height: Dp = 46.dp, + padding: PaddingValues = PaddingValues(horizontal = 8.dp), + disabled: Boolean = false, + content: (@Composable () -> Unit) +) { + val modifier = Modifier + .padding(padding) + .fillMaxWidth() + .height(height) + Row( + if (click == null || disabled) modifier else modifier.clickable(onClick = click), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + content() + } +} + @Composable fun SectionTextFooter(text: String) { Text( @@ -51,9 +70,9 @@ fun SectionTextFooter(text: String) { } @Composable -fun SectionCustomFooter(content: (@Composable () -> Unit)) { +fun SectionCustomFooter(padding: PaddingValues = PaddingValues(start = 16.dp, end = 16.dp, top = 5.dp), content: (@Composable () -> Unit)) { Row( - Modifier.padding(horizontal = 16.dp).padding(top = 5.dp) + Modifier.padding(padding) ) { content() } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/newchat/AddGroupView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/newchat/AddGroupView.kt index c4c56d65a8..d4d03bfbc3 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/newchat/AddGroupView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/newchat/AddGroupView.kt @@ -46,7 +46,7 @@ fun AddGroupView(chatModel: ChatModel, close: () -> Unit) { ModalManager.shared.showCustomModal { close -> ModalView( close = close, modifier = Modifier, - background = if (isSystemInDarkTheme()) MaterialTheme.colors.background else SettingsBackgroundLight + background = if (isInDarkTheme()) MaterialTheme.colors.background else SettingsBackgroundLight ) { AddGroupMembersView(groupInfo, chatModel, close) } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/onboarding/SimpleXInfo.kt b/apps/android/app/src/main/java/chat/simplex/app/views/onboarding/SimpleXInfo.kt index 9b66a14af8..5c95b8a727 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/onboarding/SimpleXInfo.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/onboarding/SimpleXInfo.kt @@ -3,7 +3,6 @@ package chat.simplex.app.views.onboarding import android.content.res.Configuration import androidx.annotation.StringRes import androidx.compose.foundation.Image -import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.* import androidx.compose.material.* import androidx.compose.material.icons.Icons @@ -77,7 +76,7 @@ fun SimpleXInfoLayout( @Composable fun SimpleXLogo() { Image( - painter = painterResource(if (isSystemInDarkTheme()) R.drawable.logo_light else R.drawable.logo), + painter = painterResource(if (isInDarkTheme()) R.drawable.logo_light else R.drawable.logo), contentDescription = stringResource(R.string.image_descr_simplex_logo), modifier = Modifier .padding(vertical = 20.dp) diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/Appearance.kt b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/Appearance.kt index 8a35d64916..3ab5ac25ab 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/Appearance.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/Appearance.kt @@ -1,5 +1,8 @@ package chat.simplex.app.views.usersettings +import SectionCustomFooter +import SectionItemViewSpaceBetween +import SectionSpacer import SectionView import android.content.ComponentName import android.content.pm.PackageManager @@ -10,11 +13,13 @@ import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyRow import androidx.compose.material.* import androidx.compose.material.MaterialTheme.colors +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Circle import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.shadow -import androidx.compose.ui.graphics.asImageBitmap +import androidx.compose.ui.graphics.* import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource @@ -24,7 +29,10 @@ import androidx.core.content.ContextCompat import androidx.core.graphics.drawable.toBitmap import chat.simplex.app.* import chat.simplex.app.R +import chat.simplex.app.model.ChatModel import chat.simplex.app.ui.theme.* +import chat.simplex.app.views.helpers.* +import com.godaddy.android.colorpicker.* enum class AppIcon(val resId: Int) { DEFAULT(R.mipmap.icon), @@ -32,7 +40,9 @@ enum class AppIcon(val resId: Int) { } @Composable -fun AppearanceView() { +fun AppearanceView( + showCustomModal: (@Composable (ChatModel, () -> Unit) -> Unit) -> (() -> Unit), +) { val appIcon = remember { mutableStateOf(findEnabledIcon()) } fun setAppIcon(newIcon: AppIcon) { @@ -54,18 +64,33 @@ fun AppearanceView() { AppearanceLayout( appIcon, - changeIcon = ::setAppIcon + changeIcon = ::setAppIcon, + showThemeSelector = showCustomModal { _, close -> + ModalView( + close = close, modifier = Modifier, + background = if (isInDarkTheme()) colors.background else SettingsBackgroundLight + ) { ThemeSelectorView() } + }, + editPrimaryColor = { primary -> + showCustomModal { _, close -> + ModalView( + close = close, modifier = Modifier, + background = if (isInDarkTheme()) colors.background else SettingsBackgroundLight + ) { ColorEditor(primary, close) } + }() + }, ) } @Composable fun AppearanceLayout( icon: MutableState, - changeIcon: (AppIcon) -> Unit + changeIcon: (AppIcon) -> Unit, + showThemeSelector: () -> Unit, + editPrimaryColor: (Color) -> Unit, ) { Column( Modifier.fillMaxWidth(), horizontalAlignment = Alignment.Start, - verticalArrangement = Arrangement.spacedBy(8.dp) ) { Text( stringResource(R.string.appearance_settings), @@ -73,10 +98,7 @@ fun AppearanceView() { style = MaterialTheme.typography.h1 ) SectionView(stringResource(R.string.settings_section_title_icon)) { - LazyRow( - Modifier - .padding(horizontal = 8.dp) - ) { + LazyRow { items(AppIcon.values().size, { index -> AppIcon.values()[index] }) { index -> val item = AppIcon.values()[index] val mipmap = ContextCompat.getDrawable(LocalContext.current, item.resId)!! @@ -97,9 +119,82 @@ fun AppearanceView() { } } } + + SectionSpacer() + val currentTheme by CurrentColors.collectAsState() + SectionView(stringResource(R.string.settings_section_title_themes)) { + Column( + Modifier.padding(horizontal = 8.dp) + ) { + SectionItemViewSpaceBetween(showThemeSelector, padding = PaddingValues()) { + Text(generalGetString(R.string.theme)) + } + Spacer(Modifier.padding(horizontal = 4.dp)) + + SectionItemViewSpaceBetween({ editPrimaryColor(currentTheme.first.primary) }, padding = PaddingValues()) { + val title = generalGetString(R.string.color_primary) + Text(title) + Icon(Icons.Filled.Circle, title, tint = colors.primary) + } + } + } + if (currentTheme.first.primary != LightColorPalette.primary) { + SectionCustomFooter(PaddingValues(start = 7.dp, end = 7.dp, top = 5.dp)) { + TextButton( + onClick = { + ThemeManager.saveAndApplyPrimaryColor(LightColorPalette.primary) + }, + ) { + Text(generalGetString(R.string.reset_color)) + } + } + } } } +@Composable +fun ColorEditor( + initialColor: Color, + close: () -> Unit, +) { + Column( + Modifier + .fillMaxWidth() + ) { + var currentColor by remember { mutableStateOf(initialColor) } + ColorPicker(initialColor) { + currentColor = it + } + + SectionSpacer() + + TextButton( + onClick = { + ThemeManager.saveAndApplyPrimaryColor(currentColor) + close() + }, + Modifier.align(Alignment.CenterHorizontally), + colors = ButtonDefaults.textButtonColors(contentColor = currentColor) + ) { + Text(generalGetString(R.string.save_color)) + } + } +} + +@Composable +fun ColorPicker(initialColor: Color, onColorChanged: (Color) -> Unit) { + ClassicColorPicker( + color = initialColor, + modifier = Modifier + .fillMaxWidth() + .height(300.dp), + showAlphaBar = false, + onColorChanged = { color: HsvColor -> + onColorChanged(color.toColor()) + } + ) +} + private fun findEnabledIcon(): AppIcon = AppIcon.values().first { icon -> SimplexApp.context.packageManager.getComponentEnabledSetting( ComponentName(BuildConfig.APPLICATION_ID, "chat.simplex.app.MainActivity_${icon.name.lowercase()}") @@ -112,7 +207,9 @@ fun PreviewAppearanceSettings() { SimpleXTheme { AppearanceLayout( icon = remember { mutableStateOf(AppIcon.DARK_BLUE) }, - changeIcon = {} + changeIcon = {}, + showThemeSelector = {}, + editPrimaryColor = {}, ) } } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/SettingsView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/SettingsView.kt index 8d5358c52b..9061369acc 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/SettingsView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/SettingsView.kt @@ -58,24 +58,12 @@ fun SettingsView(chatModel: ChatModel, setPerformLA: (Boolean) -> Unit) { showModal = { modalView -> { ModalManager.shared.showModal { modalView(chatModel) } } }, showSettingsModal = { modalView -> { ModalManager.shared.showCustomModal { close -> ModalView(close = close, modifier = Modifier, - background = if (isSystemInDarkTheme()) MaterialTheme.colors.background else SettingsBackgroundLight) { + background = if (isInDarkTheme()) MaterialTheme.colors.background else SettingsBackgroundLight) { modalView(chatModel) } } } }, showCustomModal = { modalView -> { ModalManager.shared.showCustomModal { close -> modalView(chatModel, close) } } }, showTerminal = { ModalManager.shared.showCustomModal { close -> TerminalView(chatModel, close) } }, - showAppearance = { - withApi { - ModalManager.shared.showCustomModal { close -> - ModalView( - close = close, modifier = Modifier, - background = if (isSystemInDarkTheme()) MaterialTheme.colors.background else SettingsBackgroundLight - ) { - AppearanceView() - } - } - } - } // showVideoChatPrototype = { ModalManager.shared.showCustomModal { close -> CallViewDebug(close) } }, ) } @@ -88,7 +76,7 @@ val simplexTeamUri = //fun showSectionedModal(chatModel: ChatModel, modalView: (@Composable (ChatModel) -> Unit)) { // ModalManager.shared.showCustomModal { close -> // ModalView(close = close, modifier = Modifier, -// background = if (isSystemInDarkTheme()) MaterialTheme.colors.background else SettingsBackgroundLight) { +// background = if (isInDarkTheme()) MaterialTheme.colors.background else SettingsBackgroundLight) { // modalView(chatModel) // } // } @@ -106,7 +94,6 @@ fun SettingsLayout( showSettingsModal: (@Composable (ChatModel) -> Unit) -> (() -> Unit), showCustomModal: (@Composable (ChatModel, () -> Unit) -> Unit) -> (() -> Unit), showTerminal: () -> Unit, - showAppearance: () -> Unit // showVideoChatPrototype: () -> Unit ) { val uriHandler = LocalUriHandler.current @@ -114,7 +101,7 @@ fun SettingsLayout( Column( Modifier .fillMaxSize() - .background(if (isSystemInDarkTheme()) MaterialTheme.colors.background else SettingsBackgroundLight) + .background(if (isInDarkTheme()) MaterialTheme.colors.background else SettingsBackgroundLight) .padding(top = 16.dp) ) { Text( @@ -142,7 +129,7 @@ fun SettingsLayout( SectionDivider() SettingsActionItem(Icons.Outlined.Lock, stringResource(R.string.privacy_and_security), showSettingsModal { PrivacySettingsView(it, setPerformLA) }, disabled = stopped) SectionDivider() - SettingsActionItem(Icons.Outlined.LightMode, stringResource(R.string.appearance_settings), showAppearance, disabled = stopped) + SettingsActionItem(Icons.Outlined.LightMode, stringResource(R.string.appearance_settings), showSettingsModal { AppearanceView(showCustomModal) }, disabled = stopped) SectionDivider() SettingsActionItem(Icons.Outlined.WifiTethering, stringResource(R.string.network_and_servers), showSettingsModal { NetworkAndServersView(it, showModal, showSettingsModal) }, disabled = stopped) } @@ -288,7 +275,7 @@ fun SettingsLayout( tint = HighOrLowlight, ) Spacer(Modifier.padding(horizontal = 4.dp)) - Text(annotatedStringResource(R.string.install_simplex_chat_for_terminal)) + Text(generalGetString(R.string.install_simplex_chat_for_terminal), color = MaterialTheme.colors.primary) } } @@ -355,7 +342,6 @@ fun PreviewSettingsLayout() { showSettingsModal = { {} }, showCustomModal = { {} }, showTerminal = {}, - showAppearance = {}, // showVideoChatPrototype = {} ) } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/ThemeSelector.kt b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/ThemeSelector.kt new file mode 100644 index 0000000000..9f410a1bc9 --- /dev/null +++ b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/ThemeSelector.kt @@ -0,0 +1,69 @@ +package chat.simplex.app.views.usersettings + +import SectionItemViewSpaceBetween +import SectionView +import androidx.compose.foundation.* +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.material.* +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.* +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.capitalize +import androidx.compose.ui.text.intl.Locale +import androidx.compose.ui.unit.dp +import chat.simplex.app.R +import chat.simplex.app.ui.theme.* + +@Composable +fun ThemeSelectorView() { + val darkTheme = isSystemInDarkTheme() + val allThemes by remember { mutableStateOf(ThemeManager.allThemes(darkTheme)) } + + ThemeSelectorLayout( + allThemes, + onSelectTheme = { + ThemeManager.applyTheme(it, darkTheme) + }, + ) +} + +@Composable fun ThemeSelectorLayout( + allThemes: List>, + onSelectTheme: (String) -> Unit, +) { + Column( + Modifier.fillMaxWidth(), + horizontalAlignment = Alignment.Start, + ) { + Text( + stringResource(R.string.settings_section_title_themes).lowercase().capitalize(Locale.current), + Modifier.padding(start = 16.dp, bottom = 24.dp), + style = MaterialTheme.typography.h1 + ) + val currentTheme by CurrentColors.collectAsState() + SectionView(null) { + LazyColumn( + Modifier.padding(horizontal = 8.dp) + ) { + items(allThemes.size) { index -> + val item = allThemes[index] + val onClick = { + onSelectTheme(item.second.name) + } + SectionItemViewSpaceBetween(onClick, padding = PaddingValues()) { + Text(item.third) + if (currentTheme.second == item.second) { + Icon(Icons.Outlined.Check, item.third, tint = HighOrLowlight) + } + } + Spacer(Modifier.padding(horizontal = 4.dp)) + } + } + } + } +} + diff --git a/apps/android/app/src/main/res/values-ru/strings.xml b/apps/android/app/src/main/res/values-ru/strings.xml index b8246adb74..994672296a 100644 --- a/apps/android/app/src/main/res/values-ru/strings.xml +++ b/apps/android/app/src/main/res/values-ru/strings.xml @@ -272,7 +272,7 @@ Блокировка SimpleX Консоль SMP серверы - SimpleX Chat для терминала + SimpleX Chat для терминала Использовать серверы предосталенные SimpleX Chat? Сохраненные SMP серверы будут удалены. Ваши SMP серверы @@ -468,6 +468,7 @@ Экспериментальные функции SOCKS ПРОКСИ ИКОНКА + ТЕМЫ Данные чата @@ -635,4 +636,15 @@ Обновить настройки сети? Обновление настроек приведет к переподключению клиента ко всем серверам. Обновить + + + Системная + Светлая + Темная + + + Тема + Сохранить цвет + Сбросить цвета + Акцент diff --git a/apps/android/app/src/main/res/values/strings.xml b/apps/android/app/src/main/res/values/strings.xml index ca4aeb42e9..8019e862ab 100644 --- a/apps/android/app/src/main/res/values/strings.xml +++ b/apps/android/app/src/main/res/values/strings.xml @@ -277,7 +277,7 @@ SimpleX Lock Chat console SMP servers - Install SimpleX Chat for terminal + Install SimpleX Chat for terminal Use SimpleX Chat servers? Saved SMP servers will be removed. Your SMP servers @@ -470,6 +470,7 @@ Experimental features SOCKS PROXY APP ICON + THEMES Your chat database @@ -637,4 +638,15 @@ Update network settings? Updating settings will re-connect the client to all servers. Update + + + System + Light + Dark + + + Theme + Save color + Reset colors + Accent