From c254b337531339dd309fcc13538dfb7454a9ddd6 Mon Sep 17 00:00:00 2001 From: Stanislav Dmitrenko <7953703+avently@users.noreply.github.com> Date: Thu, 27 Apr 2023 22:32:40 +0300 Subject: [PATCH] android: blue theme and more options (#2331) * android: blue theme and more options * more color options and better code * more color options and some fixes * removed preferences about non-existent theme * colors * Revert "removed preferences about non-existent theme" This reverts commit cbb38d54a81046211ade7f2ac40e65d95d658007. * colors * update colors * migrations * HighOrLowLight -> secondary * new color * color * update colors, move colors to a separate page --------- Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com> --- apps/android/app/build.gradle | 1 + .../java/chat/simplex/app/MainActivity.kt | 28 +-- .../main/java/chat/simplex/app/SimplexApp.kt | 19 ++ .../java/chat/simplex/app/model/ChatModel.kt | 2 +- .../java/chat/simplex/app/model/SimpleXAPI.kt | 34 ++- .../java/chat/simplex/app/ui/theme/Color.kt | 1 - .../java/chat/simplex/app/ui/theme/Theme.kt | 206 +++++++++++++++++- .../chat/simplex/app/ui/theme/ThemeManager.kt | 119 ++++++++-- .../java/chat/simplex/app/views/SplashView.kt | 5 +- .../chat/simplex/app/views/TerminalView.kt | 2 +- .../chat/simplex/app/views/WelcomeView.kt | 8 +- .../chat/simplex/app/views/call/CallView.kt | 4 +- .../app/views/call/IncomingCallActivity.kt | 6 +- .../app/views/call/IncomingCallAlertView.kt | 4 +- .../simplex/app/views/chat/ChatInfoView.kt | 16 +- .../chat/simplex/app/views/chat/ChatView.kt | 6 +- .../simplex/app/views/chat/ComposeFileView.kt | 5 +- .../app/views/chat/ComposeImageView.kt | 9 +- .../simplex/app/views/chat/ComposeView.kt | 3 +- .../app/views/chat/ComposeVoiceView.kt | 8 +- .../app/views/chat/ContactPreferences.kt | 4 +- .../simplex/app/views/chat/ContextItemView.kt | 10 +- .../simplex/app/views/chat/SendMsgView.kt | 18 +- .../simplex/app/views/chat/VerifyCodeView.kt | 2 +- .../views/chat/group/AddGroupMembersView.kt | 16 +- .../app/views/chat/group/GroupChatInfoView.kt | 16 +- .../app/views/chat/group/GroupLinkView.kt | 5 +- .../views/chat/group/GroupMemberInfoView.kt | 2 +- .../app/views/chat/group/GroupPreferences.kt | 6 +- .../app/views/chat/group/GroupProfileView.kt | 4 +- .../views/chat/group/WelcomeMessageView.kt | 2 +- .../app/views/chat/item/CICallItemView.kt | 11 +- .../app/views/chat/item/CIEventView.kt | 36 ++- .../chat/item/CIFeaturePreferenceView.kt | 5 +- .../simplex/app/views/chat/item/CIFileView.kt | 2 +- .../views/chat/item/CIGroupInvitationView.kt | 7 +- .../simplex/app/views/chat/item/CIMetaView.kt | 6 +- .../app/views/chat/item/CIVoiceView.kt | 8 +- .../app/views/chat/item/ChatItemView.kt | 2 +- .../app/views/chat/item/DeletedItemView.kt | 10 +- .../app/views/chat/item/FramedItemView.kt | 26 ++- .../views/chat/item/IntegrityErrorItemView.kt | 5 +- .../views/chat/item/MarkedDeletedItemView.kt | 10 +- .../app/views/chat/item/TextItemView.kt | 4 +- .../app/views/chatlist/ChatListNavLinkView.kt | 2 +- .../app/views/chatlist/ChatListView.kt | 11 +- .../app/views/chatlist/ChatPreviewView.kt | 26 +-- .../views/chatlist/ContactConnectionView.kt | 4 +- .../app/views/chatlist/ContactRequestView.kt | 2 +- .../app/views/chatlist/ShareListView.kt | 7 +- .../simplex/app/views/chatlist/UserPicker.kt | 8 +- .../views/database/DatabaseEncryptionView.kt | 10 +- .../app/views/database/DatabaseErrorView.kt | 2 +- .../app/views/database/DatabaseView.kt | 8 +- .../simplex/app/views/helpers/AlertManager.kt | 10 +- .../app/views/helpers/ChatInfoImage.kt | 6 +- .../app/views/helpers/CloseSheetBar.kt | 15 +- .../views/helpers/DefaultBasicTextField.kt | 5 +- .../app/views/helpers/DefaultDropdownMenu.kt | 9 +- .../app/views/helpers/DefaultSwitch.kt | 5 +- .../app/views/helpers/DefaultTopAppBar.kt | 2 +- .../helpers/ExposedDropDownSettingRow.kt | 6 +- .../simplex/app/views/helpers/LinkPreviews.kt | 12 +- .../simplex/app/views/helpers/ModalView.kt | 3 +- .../chat/simplex/app/views/helpers/Section.kt | 18 +- .../simplex/app/views/helpers/SimpleButton.kt | 11 +- .../simplex/app/views/helpers/TextEditor.kt | 5 +- .../chat/simplex/app/views/helpers/Util.kt | 21 ++ .../app/views/localauth/PasswordEntry.kt | 5 +- .../app/views/newchat/AddContactView.kt | 4 +- .../simplex/app/views/newchat/AddGroupView.kt | 2 +- .../app/views/newchat/ConnectViaLinkView.kt | 6 +- .../app/views/newchat/CreateLinkView.kt | 6 +- .../simplex/app/views/newchat/NewChatSheet.kt | 6 +- .../views/onboarding/SetNotificationsMode.kt | 4 +- .../app/views/onboarding/WhatsNewView.kt | 21 +- .../views/usersettings/AcceptRequestsView.kt | 4 +- .../usersettings/AdvancedNetworkSettings.kt | 20 +- .../app/views/usersettings/Appearance.kt | 197 ++++++++++++++--- .../app/views/usersettings/CallSettings.kt | 3 +- .../views/usersettings/HiddenProfileView.kt | 2 +- .../views/usersettings/NetworkAndServers.kt | 2 +- .../usersettings/NotificationsSettingsView.kt | 4 +- .../app/views/usersettings/Preferences.kt | 6 +- .../views/usersettings/ProtocolServerView.kt | 8 +- .../views/usersettings/ProtocolServersView.kt | 18 +- .../app/views/usersettings/RTCServers.kt | 2 +- .../app/views/usersettings/SettingsView.kt | 49 +++-- .../app/views/usersettings/UserProfileView.kt | 4 +- .../views/usersettings/UserProfilesView.kt | 2 +- .../app/src/main/res/values/strings.xml | 16 ++ 91 files changed, 896 insertions(+), 406 deletions(-) diff --git a/apps/android/app/build.gradle b/apps/android/app/build.gradle index 0a256bbb99..2291fcd1dd 100644 --- a/apps/android/app/build.gradle +++ b/apps/android/app/build.gradle @@ -119,6 +119,7 @@ dependencies { implementation 'androidx.fragment:fragment:1.4.1' implementation 'org.jetbrains.kotlinx:kotlinx-datetime:0.3.2' implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.2' + implementation 'com.charleskorn.kaml:kaml:0.43.0' //implementation "androidx.compose.material:material-icons-extended:$compose_version" implementation "androidx.compose.ui:ui-util:$compose_version" implementation "androidx.navigation:navigation-compose:2.4.1" diff --git a/apps/android/app/src/main/java/chat/simplex/app/MainActivity.kt b/apps/android/app/src/main/java/chat/simplex/app/MainActivity.kt index 49d3f75c16..029fa52b65 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/MainActivity.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/MainActivity.kt @@ -17,6 +17,7 @@ import androidx.compose.runtime.* import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource @@ -26,8 +27,7 @@ import androidx.lifecycle.* import chat.simplex.app.MainActivity.Companion.enteredBackground import chat.simplex.app.model.* import chat.simplex.app.model.NtfManager.Companion.getUserIdFromIntent -import chat.simplex.app.ui.theme.SimpleButton -import chat.simplex.app.ui.theme.SimpleXTheme +import chat.simplex.app.ui.theme.* import chat.simplex.app.views.SplashView import chat.simplex.app.views.call.ActiveCallView import chat.simplex.app.views.call.IncomingCallAlertView @@ -83,20 +83,14 @@ class MainActivity: FragmentActivity() { } setContent { SimpleXTheme { - Surface( - Modifier - .background(MaterialTheme.colors.background) - .fillMaxSize() - ) { - MainPage( - m, - userAuthorized, - laFailed, - ::runAuthenticate, - ::setPerformLA, - showLANotice = { showLANotice(m.controller.appPrefs.laNoticeShown, this) } - ) - } + MainPage( + m, + userAuthorized, + laFailed, + ::runAuthenticate, + ::setPerformLA, + showLANotice = { showLANotice(m.controller.appPrefs.laNoticeShown, this) } + ) } } SimplexApp.context.schedulePeriodicServiceRestartWorker() @@ -420,7 +414,7 @@ fun MainPage( @Composable fun authView() { Box( - Modifier.fillMaxSize(), + Modifier.fillMaxSize().background(MaterialTheme.colors.background), contentAlignment = Alignment.Center ) { SimpleButton( diff --git a/apps/android/app/src/main/java/chat/simplex/app/SimplexApp.kt b/apps/android/app/src/main/java/chat/simplex/app/SimplexApp.kt index 1559002080..2a6d7587bc 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/SimplexApp.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/SimplexApp.kt @@ -6,6 +6,7 @@ import android.util.Log import androidx.lifecycle.* import androidx.work.* import chat.simplex.app.model.* +import chat.simplex.app.ui.theme.DefaultTheme import chat.simplex.app.views.helpers.* import chat.simplex.app.views.onboarding.OnboardingStage import chat.simplex.app.views.usersettings.NotificationsMode @@ -95,6 +96,7 @@ class SimplexApp: Application(), LifecycleEventObserver { initChatController() ProcessLifecycleOwner.get().lifecycle.addObserver(this) context.getDir("temp", MODE_PRIVATE).deleteRecursively() + runMigrations() } override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) { @@ -184,6 +186,23 @@ class SimplexApp: Application(), LifecycleEventObserver { MessagesFetcherWorker.scheduleWork() } + private fun runMigrations() { + val lastMigration = chatModel.controller.appPrefs.lastMigratedVersionCode + if (lastMigration.get() < BuildConfig.VERSION_CODE) { + while (true) { + if (lastMigration.get() < 117) { + if (chatModel.controller.appPrefs.currentTheme.get() == DefaultTheme.DARK.name) { + chatModel.controller.appPrefs.currentTheme.set(DefaultTheme.SIMPLEX.name) + } + lastMigration.set(117) + } else { + lastMigration.set(BuildConfig.VERSION_CODE) + break + } + } + } + } + companion object { lateinit var context: SimplexApp private set diff --git a/apps/android/app/src/main/java/chat/simplex/app/model/ChatModel.kt b/apps/android/app/src/main/java/chat/simplex/app/model/ChatModel.kt index 0f54b42d8c..8947c782fd 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/model/ChatModel.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/model/ChatModel.kt @@ -1516,7 +1516,7 @@ data class CIMeta ( val isRcvNew: Boolean get() = itemStatus is CIStatus.RcvNew - fun statusIcon(primaryColor: Color, metaColor: Color = HighOrLowlight): Pair? = + fun statusIcon(primaryColor: Color, metaColor: Color = CurrentColors.value.colors.secondary): Pair? = when (itemStatus) { is CIStatus.SndSent -> R.drawable.ic_check_filled to metaColor is CIStatus.SndErrorAuth -> R.drawable.ic_close to Color.Red 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 1fe7e1aa1a..662867f368 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 @@ -14,7 +14,6 @@ import androidx.compose.runtime.* import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.painter.Painter -import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight @@ -26,10 +25,14 @@ import chat.simplex.app.views.call.* import chat.simplex.app.views.newchat.ConnectViaLinkTab import chat.simplex.app.views.onboarding.OnboardingStage import chat.simplex.app.views.usersettings.* +import com.charleskorn.kaml.Yaml +import com.charleskorn.kaml.YamlConfiguration import kotlinx.coroutines.* import kotlinx.datetime.Clock import kotlinx.datetime.Instant import kotlinx.serialization.* +import kotlinx.serialization.builtins.MapSerializer +import kotlinx.serialization.builtins.serializer import kotlinx.serialization.json.* import java.util.Date @@ -57,6 +60,7 @@ enum class SimplexLinkMode { class AppPreferences(val context: Context) { private val sharedPreferences: SharedPreferences = context.getSharedPreferences(SHARED_PREFS_ID, Context.MODE_PRIVATE) + private val sharedPreferencesThemes: SharedPreferences = context.getSharedPreferences(SHARED_PREFS_THEMES_ID, Context.MODE_PRIVATE) // deprecated, remove in 2024 private val runServiceInBackground = mkBoolPreference(SHARED_PREFS_RUN_SERVICE_IN_BACKGROUND, true) @@ -147,9 +151,15 @@ class AppPreferences(val context: Context) { val confirmDBUpgrades = mkBoolPreference(SHARED_PREFS_CONFIRM_DB_UPGRADES, false) val currentTheme = mkStrPreference(SHARED_PREFS_CURRENT_THEME, DefaultTheme.SYSTEM.name) - val primaryColor = mkIntPreference(SHARED_PREFS_PRIMARY_COLOR, LightColorPalette.primary.toArgb()) + val systemDarkTheme = mkStrPreference(SHARED_PREFS_SYSTEM_DARK_THEME, DefaultTheme.SIMPLEX.name) + val themeOverrides = mkMapPreference(SHARED_PREFS_THEMES, mapOf(), encode = { + json.encodeToString(MapSerializer(String.serializer(), ThemeOverrides.serializer()), it) + }, decode = { + json.decodeFromString(MapSerializer(String.serializer(), ThemeOverrides.serializer()), it) + }, sharedPreferencesThemes) val whatsNewVersion = mkStrPreference(SHARED_PREFS_WHATS_NEW_VERSION, null) + val lastMigratedVersionCode = mkIntPreference(SHARED_PREFS_LAST_MIGRATED_VERSION_CODE, 0) private fun mkIntPreference(prefName: String, default: Int) = SharedPreference( @@ -204,8 +214,15 @@ class AppPreferences(val context: Context) { } ) + private fun mkMapPreference(prefName: String, default: Map, encode: (Map) -> String, decode: (String) -> Map, prefs: SharedPreferences = sharedPreferences): SharedPreference> = + SharedPreference( + get = fun() = decode(prefs.getString(prefName, encode(default))!!), + set = fun(value) = prefs.edit().putString(prefName, encode(value)).apply() + ) + companion object { internal const val SHARED_PREFS_ID = "chat.simplex.app.SIMPLEX_APP_PREFS" + internal const val SHARED_PREFS_THEMES_ID = "chat.simplex.app.THEMES" private const val SHARED_PREFS_AUTO_RESTART_WORKER_VERSION = "AutoRestartWorkerVersion" private const val SHARED_PREFS_RUN_SERVICE_IN_BACKGROUND = "RunServiceInBackground" private const val SHARED_PREFS_NOTIFICATIONS_MODE = "NotificationsMode" @@ -258,8 +275,10 @@ class AppPreferences(val context: Context) { private const val SHARED_PREFS_ENCRYPTION_STARTED_AT = "EncryptionStartedAt" private const val SHARED_PREFS_CONFIRM_DB_UPGRADES = "ConfirmDBUpgrades" private const val SHARED_PREFS_CURRENT_THEME = "CurrentTheme" - private const val SHARED_PREFS_PRIMARY_COLOR = "PrimaryColor" + private const val SHARED_PREFS_SYSTEM_DARK_THEME = "SystemDarkTheme" + private const val SHARED_PREFS_THEMES = "Themes" private const val SHARED_PREFS_WHATS_NEW_VERSION = "WhatsNewVersion" + private const val SHARED_PREFS_LAST_MIGRATED_VERSION_CODE = "LastMigratedVersionCode" } } @@ -2581,7 +2600,7 @@ data class FeatureEnabled( } val iconColor: Color - get() = if (forUser) SimplexGreen else if (forContact) WarningYellow else HighOrLowlight + get() = if (forUser) SimplexGreen else if (forContact) WarningYellow else CurrentColors.value.colors.secondary companion object { fun enabled(asymmetric: Boolean, user: ChatPreference, contact: ChatPreference): FeatureEnabled = @@ -2965,7 +2984,7 @@ enum class GroupFeatureEnabled { } val iconColor: Color - get() = if (this == ON) SimplexGreen else HighOrLowlight + get() = if (this == ON) SimplexGreen else CurrentColors.value.colors.secondary } @@ -2976,6 +2995,11 @@ val json = Json { explicitNulls = false } +val yaml = Yaml(configuration = YamlConfiguration( + strictMode = false, + encodeDefaults = false, +)) + @Serializable class APIResponse(val resp: CR, val corr: String? = null) { companion object { diff --git a/apps/android/app/src/main/java/chat/simplex/app/ui/theme/Color.kt b/apps/android/app/src/main/java/chat/simplex/app/ui/theme/Color.kt index e0187c60e4..ee2997b428 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/ui/theme/Color.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/ui/theme/Color.kt @@ -13,7 +13,6 @@ val SimplexGreen = Color(77, 218, 103, 255) val SecretColor = Color(0x40808080) val LightGray = Color(241, 242, 246, 255) val DarkGray = Color(43, 44, 46, 255) -val DarkGrayBackground = Color(38, 38, 38, 255) val HighOrLowlight = Color(139, 135, 134, 255) val MessagePreviewDark = Color(179, 175, 174, 255) val MessagePreviewLight = Color(49, 45, 44, 255) 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 ccd7cce6f2..1f1b4dcdeb 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,16 +2,165 @@ package chat.simplex.app.ui.theme import android.app.UiModeManager import android.content.Context +import androidx.compose.foundation.background import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.material.* import androidx.compose.runtime.* -import androidx.compose.ui.graphics.Color +import androidx.compose.ui.Modifier +import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.graphics.* import androidx.compose.ui.unit.dp +import chat.simplex.app.R import chat.simplex.app.SimplexApp +import chat.simplex.app.views.helpers.* import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable enum class DefaultTheme { - SYSTEM, DARK, LIGHT + SYSTEM, LIGHT, DARK, SIMPLEX; + + // Call it only with base theme, not SYSTEM + fun hasChangedAnyColor(colors: Colors): Boolean { + val palette = when (this) { + SYSTEM -> return false + LIGHT -> LightColorPalette + DARK -> DarkColorPalette + SIMPLEX -> SimplexColorPalette + } + return with(palette) { + colors.primary != primary || + colors.primaryVariant != primaryVariant || + colors.secondary != secondary || + colors.secondaryVariant != secondaryVariant || + colors.background != background || + colors.surface != surface + } + } +} + +data class AppColors( + val title: Color, + val sentMessage: Color, + val receivedMessage: Color +) + +enum class ThemeColor { + PRIMARY, PRIMARY_VARIANT, SECONDARY, SECONDARY_VARIANT, BACKGROUND, SURFACE, TITLE, SENT_MESSAGE, RECEIVED_MESSAGE; + + fun fromColors(colors: Colors, appColors: AppColors): Color { + return when (this) { + PRIMARY -> colors.primary + PRIMARY_VARIANT -> colors.primaryVariant + SECONDARY -> colors.secondary + SECONDARY_VARIANT -> colors.secondaryVariant + BACKGROUND -> colors.background + SURFACE -> colors.surface + TITLE -> appColors.title + SENT_MESSAGE -> appColors.sentMessage + RECEIVED_MESSAGE -> appColors.receivedMessage + } + } + + val text: String + get() = when (this) { + PRIMARY -> generalGetString(R.string.color_primary) + PRIMARY_VARIANT -> generalGetString(R.string.color_primary_variant) + SECONDARY -> generalGetString(R.string.color_secondary) + SECONDARY_VARIANT -> generalGetString(R.string.color_secondary_variant) + BACKGROUND -> generalGetString(R.string.color_background) + SURFACE -> generalGetString(R.string.color_surface) + TITLE -> generalGetString(R.string.color_title) + SENT_MESSAGE -> generalGetString(R.string.color_sent_message) + RECEIVED_MESSAGE -> generalGetString(R.string.color_received_message) + } +} + +@Serializable +data class ThemeColors( + @SerialName("accent") + val primary: String? = null, + @SerialName("accentVariant") + val primaryVariant: String? = null, + val secondary: String? = null, + val secondaryVariant: String? = null, + val background: String? = null, + @SerialName("menus") + val surface: String? = null, + val title: String? = null, + val sentMessage: String? = null, + val receivedMessage: String? = null, +) { + fun toColors(base: DefaultTheme): Colors { + val baseColors = when (base) { + DefaultTheme.LIGHT -> LightColorPalette + DefaultTheme.DARK -> DarkColorPalette + DefaultTheme.SIMPLEX -> SimplexColorPalette + // shouldn't be here + DefaultTheme.SYSTEM -> LightColorPalette + } + return baseColors.copy( + primary = primary?.colorFromReadableHex() ?: baseColors.primary, + primaryVariant = primaryVariant?.colorFromReadableHex() ?: baseColors.primaryVariant, + secondary = secondary?.colorFromReadableHex() ?: baseColors.secondary, + secondaryVariant = secondaryVariant?.colorFromReadableHex() ?: baseColors.secondaryVariant, + background = background?.colorFromReadableHex() ?: baseColors.background, + surface = surface?.colorFromReadableHex() ?: baseColors.surface, + ) + } + + fun toAppColors(base: DefaultTheme): AppColors { + val baseColors = when (base) { + DefaultTheme.LIGHT -> LightColorPaletteApp + DefaultTheme.DARK -> DarkColorPaletteApp + DefaultTheme.SIMPLEX -> SimplexColorPaletteApp + // shouldn't be here + DefaultTheme.SYSTEM -> LightColorPaletteApp + } + return baseColors.copy( + title = title?.colorFromReadableHex() ?: baseColors.title, + sentMessage = sentMessage?.colorFromReadableHex() ?: baseColors.sentMessage, + receivedMessage = receivedMessage?.colorFromReadableHex() ?: baseColors.receivedMessage, + ) + } +} + +private fun String.colorFromReadableHex(): Color = + Color(this.replace("#", "").toLongOrNull(16) ?: Color.White.toArgb().toLong()) + +@Serializable +data class ThemeOverrides ( + val base: DefaultTheme, + val colors: ThemeColors +) { + fun withUpdatedColor(name: ThemeColor, color: String): ThemeOverrides { + return copy(colors = when (name) { + ThemeColor.PRIMARY -> colors.copy(primary = color) + ThemeColor.PRIMARY_VARIANT -> colors.copy(primaryVariant = color) + ThemeColor.SECONDARY -> colors.copy(secondary = color) + ThemeColor.SECONDARY_VARIANT -> colors.copy(secondaryVariant = color) + ThemeColor.BACKGROUND -> colors.copy(background = color) + ThemeColor.SURFACE -> colors.copy(surface = color) + ThemeColor.TITLE -> colors.copy(title = color) + ThemeColor.SENT_MESSAGE -> colors.copy(sentMessage = color) + ThemeColor.RECEIVED_MESSAGE -> colors.copy(receivedMessage = color) + }) + } +} + +fun Modifier.themedBackground(baseTheme: DefaultTheme = CurrentColors.value.base, shape: Shape = RectangleShape): Modifier { + return if (baseTheme == DefaultTheme.SIMPLEX) { + this.background(brush = Brush.linearGradient( + listOf( + CurrentColors.value.colors.background.darker(0.4f), + CurrentColors.value.colors.background.lighter(0.4f) + ), + Offset(0f, Float.POSITIVE_INFINITY), + Offset(Float.POSITIVE_INFINITY, 0f) + ), shape = shape) + } else { + this.background(color = CurrentColors.value.colors.background, shape = shape) + } } val DEFAULT_PADDING = 20.dp @@ -22,10 +171,11 @@ val DEFAULT_BOTTOM_BUTTON_PADDING = 20.dp val DarkColorPalette = darkColors( primary = SimplexBlue, // If this value changes also need to update #0088ff in string resource files - primaryVariant = SimplexGreen, - secondary = DarkGray, + primaryVariant = SimplexBlue, + secondary = HighOrLowlight, + secondaryVariant = DarkGray, // background = Color.Black, -// surface = Color.Black, + surface = Color(0xFF222222), // background = Color(0xFF121212), // surface = Color(0xFF121212), error = Color.Red, @@ -33,27 +183,59 @@ val DarkColorPalette = darkColors( onSurface = Color(0xFFFFFBFA), // onError: Color = Color.Black, ) +val DarkColorPaletteApp = AppColors( + title = SimplexBlue, + sentMessage = Color(0x1E45B8FF), + receivedMessage = Color(0x20B1B0B5) +) + val LightColorPalette = lightColors( primary = SimplexBlue, // If this value changes also need to update #0088ff in string resource files - primaryVariant = SimplexGreen, - secondary = LightGray, + primaryVariant = SimplexBlue, + secondary = HighOrLowlight, + secondaryVariant = LightGray, error = Color.Red, // background = Color.White, -// surface = Color.White + surface = Color.White, // onPrimary = Color.White, // onSecondary = Color.Black, // onBackground = Color.Black, // onSurface = Color.Black, ) +val LightColorPaletteApp = AppColors( + title = SimplexBlue, + sentMessage = Color(0x1E45B8FF), + receivedMessage = Color(0x20B1B0B5) +) -val CurrentColors: MutableStateFlow> = MutableStateFlow(ThemeManager.currentColors(isInNightMode())) +val SimplexColorPalette = darkColors( + primary = Color(0xFF70F0F9), // If this value changes also need to update #0088ff in string resource files + primaryVariant = Color(0xFF1298A5), + secondary = HighOrLowlight, + secondaryVariant = Color(0xFF2C464D), + background = Color(0xFF111528), + // surface = Color.Black, + // background = Color(0xFF121212), + surface = Color(0xFF121C37), + error = Color.Red, +// onBackground = Color(0xFFFFFBFA), +// onSurface = Color(0xFFFFFBFA), + // onError: Color = Color.Black, +) +val SimplexColorPaletteApp = AppColors( + title = Color(0xFF267BE5), + sentMessage = Color(0x1E45B8FF), + receivedMessage = Color(0x20B1B0B5) +) + +val CurrentColors: MutableStateFlow = MutableStateFlow(ThemeManager.currentColors(isInNightMode())) // Non-@Composable implementation private fun isInNightMode() = (SimplexApp.context.getSystemService(Context.UI_MODE_SERVICE) as UiModeManager).nightMode == UiModeManager.MODE_NIGHT_YES @Composable -fun isInDarkTheme(): Boolean = !CurrentColors.collectAsState().value.first.isLight +fun isInDarkTheme(): Boolean = !CurrentColors.collectAsState().value.colors.isLight @Composable fun SimpleXTheme(darkTheme: Boolean? = null, content: @Composable () -> Unit) { @@ -64,14 +246,14 @@ fun SimpleXTheme(darkTheme: Boolean? = null, content: @Composable () -> Unit) { } val systemDark = isSystemInDarkTheme() LaunchedEffect(systemDark) { - if (CurrentColors.value.second == DefaultTheme.SYSTEM && CurrentColors.value.first.isLight == systemDark) { + if (SimplexApp.context.chatModel.controller.appPrefs.currentTheme.get() == DefaultTheme.SYSTEM.name && CurrentColors.value.colors.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 = theme.first, + colors = theme.colors, 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 index a1d5ee4526..e6646c9bc2 100644 --- 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 @@ -7,22 +7,52 @@ import chat.simplex.app.R import chat.simplex.app.SimplexApp import chat.simplex.app.model.AppPreferences import chat.simplex.app.views.helpers.generalGetString +import okhttp3.internal.toHexString object ThemeManager { private val appPrefs: AppPreferences by lazy { - AppPreferences(SimplexApp.context) + SimplexApp.context.chatModel.controller.appPrefs } - 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) + data class ActiveTheme(val name: String, val base: DefaultTheme, val colors: Colors, val appColors: AppColors) + + private fun systemDarkThemeColors(): Pair = when (appPrefs.systemDarkTheme.get()) { + DefaultTheme.DARK.name -> DarkColorPalette to DefaultTheme.DARK + DefaultTheme.SIMPLEX.name -> SimplexColorPalette to DefaultTheme.SIMPLEX + else -> SimplexColorPalette to DefaultTheme.SIMPLEX + } + + fun currentColors(darkForSystemTheme: Boolean): ActiveTheme { + val themeName = appPrefs.currentTheme.get()!! + val themeOverrides = appPrefs.themeOverrides.get() + + val nonSystemThemeName = if (themeName != DefaultTheme.SYSTEM.name) { + themeName + } else { + if (darkForSystemTheme) appPrefs.systemDarkTheme.get()!! else DefaultTheme.LIGHT.name } - return res.copy(first = res.first.copy(primary = Color(appPrefs.primaryColor.get()))) + 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) + else -> Triple(DefaultTheme.LIGHT, LightColorPalette, LightColorPaletteApp) + } + if (theme == null) { + return ActiveTheme(themeName, baseTheme.first, baseTheme.second, baseTheme.third) + } + return ActiveTheme(themeName, baseTheme.first, theme.colors.toColors(theme.base), theme.colors.toAppColors(theme.base)) + } + + fun currentThemeOverrides(darkForSystemTheme: Boolean): ThemeOverrides { + val themeName = appPrefs.currentTheme.get()!! + val nonSystemThemeName = if (themeName != DefaultTheme.SYSTEM.name) { + themeName + } else { + if (darkForSystemTheme) appPrefs.systemDarkTheme.get()!! else DefaultTheme.LIGHT.name + } + val overrides = appPrefs.themeOverrides.get().toMutableMap() + return overrides[nonSystemThemeName] ?: ThemeOverrides(base = CurrentColors.value.base, colors = ThemeColors()) } // colors, default theme enum, localized name of theme @@ -30,7 +60,7 @@ object ThemeManager { val allThemes = ArrayList>() allThemes.add( Triple( - if (darkForSystemTheme) DarkColorPalette else LightColorPalette, + if (darkForSystemTheme) systemDarkThemeColors().first else LightColorPalette, DefaultTheme.SYSTEM, generalGetString(R.string.theme_system) ) @@ -49,16 +79,73 @@ object ThemeManager { generalGetString(R.string.theme_dark) ) ) + allThemes.add( + Triple( + SimplexColorPalette, + DefaultTheme.SIMPLEX, + generalGetString(R.string.theme_simplex) + ) + ) return allThemes } - fun applyTheme(name: String, darkForSystemTheme: Boolean) { - appPrefs.currentTheme.set(name) + fun applyTheme(theme: String, darkForSystemTheme: Boolean) { + appPrefs.currentTheme.set(theme) CurrentColors.value = currentColors(darkForSystemTheme) } - fun saveAndApplyPrimaryColor(color: Color) { - appPrefs.primaryColor.set(color.toArgb()) - CurrentColors.value = currentColors(!CurrentColors.value.first.isLight) + fun changeDarkTheme(theme: String, darkForSystemTheme: Boolean) { + appPrefs.systemDarkTheme.set(theme) + CurrentColors.value = currentColors(darkForSystemTheme) + } + + fun saveAndApplyThemeColor(name: ThemeColor, color: Color? = null, darkForSystemTheme: Boolean) { + val themeName = appPrefs.currentTheme.get()!! + val nonSystemThemeName = if (themeName != DefaultTheme.SYSTEM.name) { + themeName + } else { + if (darkForSystemTheme) appPrefs.systemDarkTheme.get()!! else DefaultTheme.LIGHT.name + } + var colorToSet = color + if (colorToSet == null) { + // Setting default color from a base theme + colorToSet = when(nonSystemThemeName) { + DefaultTheme.LIGHT.name -> name.fromColors(LightColorPalette, LightColorPaletteApp) + DefaultTheme.DARK.name -> name.fromColors(DarkColorPalette, DarkColorPaletteApp) + DefaultTheme.SIMPLEX.name -> name.fromColors(SimplexColorPalette, SimplexColorPaletteApp) + // Will not be here + else -> return + } + } + val overrides = appPrefs.themeOverrides.get().toMutableMap() + val prevValue = overrides[nonSystemThemeName] ?: ThemeOverrides(base = CurrentColors.value.base, colors = ThemeColors()) + overrides[nonSystemThemeName] = prevValue.withUpdatedColor(name, colorToSet.toReadableHex()) + appPrefs.themeOverrides.set(overrides) + CurrentColors.value = currentColors(!CurrentColors.value.colors.isLight) + } + + fun saveAndApplyThemeOverrides(theme: ThemeOverrides, darkForSystemTheme: Boolean) { + val overrides = appPrefs.themeOverrides.get().toMutableMap() + val prevValue = overrides[theme.base.name] ?: ThemeOverrides(base = CurrentColors.value.base, colors = ThemeColors()) + overrides[theme.base.name] = prevValue.copy(colors = theme.colors) + appPrefs.themeOverrides.set(overrides) + appPrefs.currentTheme.set(theme.base.name) + CurrentColors.value = currentColors(!CurrentColors.value.colors.isLight) + } + + fun resetAllThemeColors(darkForSystemTheme: Boolean) { + val themeName = appPrefs.currentTheme.get()!! + val nonSystemThemeName = if (themeName != DefaultTheme.SYSTEM.name) { + themeName + } else { + if (darkForSystemTheme) appPrefs.systemDarkTheme.get()!! else DefaultTheme.LIGHT.name + } + val overrides = appPrefs.themeOverrides.get().toMutableMap() + val prevValue = overrides[nonSystemThemeName] ?: return + overrides[nonSystemThemeName] = prevValue.copy(colors = ThemeColors()) + appPrefs.themeOverrides.set(overrides) + CurrentColors.value = currentColors(!CurrentColors.value.colors.isLight) } } + +private fun Color.toReadableHex(): String = "#" + toArgb().toHexString() diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/SplashView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/SplashView.kt index f37a6fca8e..a831bcc3a9 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/SplashView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/SplashView.kt @@ -1,6 +1,5 @@ package chat.simplex.app.views -import androidx.compose.foundation.background import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material.MaterialTheme import androidx.compose.material.Surface @@ -11,8 +10,8 @@ import androidx.compose.ui.Modifier fun SplashView() { Surface( Modifier - .background(MaterialTheme.colors.background) - .fillMaxSize() + .fillMaxSize(), + color = MaterialTheme.colors.background ) { // Image( // painter = painterResource(R.drawable.logo), diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/TerminalView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/TerminalView.kt index 8641b4a08a..b342cc731d 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/TerminalView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/TerminalView.kt @@ -100,7 +100,7 @@ fun TerminalLayout( modifier = Modifier .padding(contentPadding) .fillMaxWidth() - .background(MaterialTheme.colors.background) + .themedBackground() ) { TerminalLog(terminalItems) } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/WelcomeView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/WelcomeView.kt index cf9084ea1b..0eea155fb2 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/WelcomeView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/WelcomeView.kt @@ -101,7 +101,7 @@ fun CreateProfilePanel(chatModel: ChatModel, close: () -> Unit) { createColor = MaterialTheme.colors.primary } else { createModifier = Modifier.padding(8.dp) - createColor = HighOrLowlight + createColor = MaterialTheme.colors.secondary } Surface(shape = RoundedCornerShape(20.dp)) { Row(verticalAlignment = Alignment.CenterVertically, modifier = createModifier) { @@ -147,9 +147,9 @@ fun ProfileNameField(name: MutableState, placeholder: String = "", isVal derivedStateOf { if (valid) { if (focused) { - HighOrLowlight.copy(alpha = 0.6f) + CurrentColors.value.colors.secondary.copy(alpha = 0.6f) } else { - HighOrLowlight.copy(alpha = 0.3f) + CurrentColors.value.colors.secondary.copy(alpha = 0.3f) } } else Color.Red } @@ -176,7 +176,7 @@ fun ProfileNameField(name: MutableState, placeholder: String = "", isVal autoCorrect = false ), singleLine = true, - cursorBrush = SolidColor(HighOrLowlight) + cursorBrush = SolidColor(MaterialTheme.colors.secondary) ) } LaunchedEffect(Unit) { diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/call/CallView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/call/CallView.kt index 9025ba32db..e7e235c606 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/call/CallView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/call/CallView.kt @@ -316,7 +316,7 @@ private fun ActiveCallOverlayLayout( private fun ControlButton(call: Call, icon: Painter, @StringRes iconText: Int, action: () -> Unit, enabled: Boolean = true) { if (call.hasMedia) { IconButton(onClick = action, enabled = enabled) { - Icon(icon, stringResource(iconText), tint = if (enabled) Color(0xFFFFFFD8) else HighOrLowlight, modifier = Modifier.size(40.dp)) + Icon(icon, stringResource(iconText), tint = if (enabled) Color(0xFFFFFFD8) else MaterialTheme.colors.secondary, modifier = Modifier.size(40.dp)) } } else { Spacer(Modifier.size(40.dp)) @@ -367,7 +367,7 @@ fun CallInfoView(call: Call, alignment: Alignment.Horizontal) { // horizontalAlignment = Alignment.CenterHorizontally, // verticalArrangement = Arrangement.spacedBy(12.dp), // modifier = Modifier -// .background(MaterialTheme.colors.background) +// .themedBackground() // .fillMaxSize() // ) { // WebRTCView(callCommand) { apiMsg -> diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/call/IncomingCallActivity.kt b/apps/android/app/src/main/java/chat/simplex/app/views/call/IncomingCallActivity.kt index 55abc1a941..1f8b0775c5 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/call/IncomingCallActivity.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/call/IncomingCallActivity.kt @@ -97,7 +97,7 @@ fun IncomingCallActivityView(m: ChatModel) { SimpleXTheme { Surface( Modifier - .background(MaterialTheme.colors.background) + .themedBackground() .fillMaxSize()) { if (showCallView) { Box { @@ -212,7 +212,7 @@ private fun LockScreenCallButton(text: String, icon: Painter, color: Color, acti Icon(icon, text, tint = color, modifier = Modifier.scale(1.75f)) } Spacer(Modifier.height(DEFAULT_PADDING)) - Text(text, style = MaterialTheme.typography.body2, color = HighOrLowlight) + Text(text, style = MaterialTheme.typography.body2, color = MaterialTheme.colors.secondary) } } } @@ -226,7 +226,7 @@ fun PreviewIncomingCallLockScreenAlert() { SimpleXTheme(true) { Surface( Modifier - .background(MaterialTheme.colors.background) + .themedBackground() .fillMaxSize()) { IncomingCallLockScreenAlertLayout( invitation = RcvCallInvitation( 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 56d57e1443..c062f6f81b 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 @@ -72,7 +72,7 @@ fun IncomingCallInfo(invitation: RcvCallInvitation, chatModel: ChatModel) { @Composable fun CallIcon(icon: Painter, descr: String) = Icon(icon, descr, tint = SimplexGreen) Row(verticalAlignment = Alignment.CenterVertically) { if (chatModel.users.size > 1) { - ProfileImage(size = 32.dp, image = invitation.user.profile.image, color = MaterialTheme.colors.secondary) + ProfileImage(size = 32.dp, image = invitation.user.profile.image, color = MaterialTheme.colors.secondaryVariant) Spacer(Modifier.width(4.dp)) } if (invitation.callType.media == CallMediaType.Video) CallIcon(painterResource(R.drawable.ic_videocam_filled), stringResource(R.string.icon_descr_video_call)) @@ -96,7 +96,7 @@ private fun CallButton(text: String, icon: Painter, color: Color, action: () -> horizontalAlignment = Alignment.CenterHorizontally ) { Icon(icon, text, tint = color, modifier = Modifier.scale(1.2f)) - Text(text, style = MaterialTheme.typography.body2, color = HighOrLowlight) + Text(text, style = MaterialTheme.typography.body2, color = MaterialTheme.colors.secondary) } } } 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 12b21f9ddc..0474ff71cd 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 @@ -242,7 +242,7 @@ fun ChatInfoHeader(cInfo: ChatInfo, contact: Contact) { ChatInfoImage(cInfo, size = 192.dp, iconColor = if (isInDarkTheme()) GroupDark else SettingsSecondaryLight) Row(Modifier.padding(bottom = 8.dp), verticalAlignment = Alignment.CenterVertically) { if (contact.verified) { - Icon(painterResource(R.drawable.ic_verified_user), null, Modifier.padding(end = 6.dp, top = 4.dp).size(24.dp), tint = HighOrLowlight) + Icon(painterResource(R.drawable.ic_verified_user), null, Modifier.padding(end = 6.dp, top = 4.dp).size(24.dp), tint = MaterialTheme.colors.secondary) } Text( contact.profile.displayName, style = MaterialTheme.typography.h1.copy(fontWeight = FontWeight.Normal), @@ -283,13 +283,13 @@ fun LocalAliasEditor( Text( generalGetString(R.string.text_field_set_contact_placeholder), textAlign = if (center) TextAlign.Center else TextAlign.Start, - color = HighOrLowlight + color = MaterialTheme.colors.secondary ) }, leadingIcon = if (leadingIcon) { { Icon(painterResource(R.drawable.ic_edit_filled), null, Modifier.padding(start = 7.dp)) } } else null, - color = HighOrLowlight, + color = MaterialTheme.colors.secondary, focus = focus, textStyle = TextStyle.Default.copy(textAlign = if (value.isEmpty() || !center) TextAlign.Start else TextAlign.Center), keyboardActions = KeyboardActions(onDone = { updateValue(value) }) @@ -336,7 +336,7 @@ private fun NetworkStatusRow(networkStatus: NetworkStatus) { ) { Text( networkStatus.statusString, - color = HighOrLowlight + color = MaterialTheme.colors.secondary ) ServerImage(networkStatus) } @@ -350,10 +350,10 @@ private fun ServerImage(networkStatus: NetworkStatus) { is NetworkStatus.Connected -> Icon(painterResource(R.drawable.ic_circle_filled), stringResource(R.string.icon_descr_server_status_connected), tint = MaterialTheme.colors.primaryVariant) is NetworkStatus.Disconnected -> - Icon(painterResource(R.drawable.ic_pending_filled), stringResource(R.string.icon_descr_server_status_disconnected), tint = HighOrLowlight) + Icon(painterResource(R.drawable.ic_pending_filled), stringResource(R.string.icon_descr_server_status_disconnected), tint = MaterialTheme.colors.secondary) is NetworkStatus.Error -> - Icon(painterResource(R.drawable.ic_error_filled), stringResource(R.string.icon_descr_server_status_error), tint = HighOrLowlight) - else -> Icon(painterResource(R.drawable.ic_circle), stringResource(R.string.icon_descr_server_status_pending), tint = HighOrLowlight) + Icon(painterResource(R.drawable.ic_error_filled), stringResource(R.string.icon_descr_server_status_error), tint = MaterialTheme.colors.secondary) + else -> Icon(painterResource(R.drawable.ic_circle), stringResource(R.string.icon_descr_server_status_pending), tint = MaterialTheme.colors.secondary) } } } @@ -381,7 +381,7 @@ fun VerifyCodeButton(contactVerified: Boolean, onClick: () -> Unit) { if (contactVerified) painterResource(R.drawable.ic_verified_user) else painterResource(R.drawable.ic_shield), stringResource(if (contactVerified) R.string.view_security_code else R.string.verify_security_code), click = onClick, - iconColor = HighOrLowlight, + iconColor = MaterialTheme.colors.secondary, ) } 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 1731ba49a6..9b2da5a42c 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 @@ -326,7 +326,7 @@ fun ChatLayout( Box( Modifier .fillMaxWidth() - .background(MaterialTheme.colors.background) + .themedBackground() ) { ProvideWindowInsets(windowInsetsAnimationsEnabled = true) { ModalBottomSheetLayout( @@ -462,7 +462,7 @@ fun ChatInfoToolbar( } @Composable -fun ChatInfoToolbarTitle(cInfo: ChatInfo, imageSize: Dp = 40.dp, iconColor: Color = MaterialTheme.colors.secondary) { +fun ChatInfoToolbarTitle(cInfo: ChatInfo, imageSize: Dp = 40.dp, iconColor: Color = MaterialTheme.colors.secondaryVariant) { Row( horizontalArrangement = Arrangement.Center, verticalAlignment = Alignment.CenterVertically @@ -496,7 +496,7 @@ fun ChatInfoToolbarTitle(cInfo: ChatInfo, imageSize: Dp = 40.dp, iconColor: Colo @Composable private fun ContactVerifiedShield() { - Icon(painterResource(R.drawable.ic_verified_user), null, Modifier.size(18.dp).padding(end = 3.dp, top = 1.dp), tint = HighOrLowlight) + Icon(painterResource(R.drawable.ic_verified_user), null, Modifier.size(18.dp).padding(end = 3.dp, top = 1.dp), tint = MaterialTheme.colors.secondary) } data class CIListState(val scrolled: Boolean, val itemCount: Int, val keyboardState: KeyboardState) 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 a36b09a169..d90d2493ba 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 @@ -2,6 +2,7 @@ import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.material.* import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource @@ -10,16 +11,16 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import chat.simplex.app.R import chat.simplex.app.ui.theme.* -import chat.simplex.app.views.chat.item.SentColorLight @Composable fun ComposeFileView(fileName: String, cancelFile: () -> Unit, cancelEnabled: Boolean) { + val sentColor = CurrentColors.collectAsState().value.appColors.sentMessage Row( Modifier .height(60.dp) .fillMaxWidth() .padding(top = 8.dp) - .background(SentColorLight), + .background(sentColor), verticalAlignment = Alignment.CenterVertically ) { Icon( diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ComposeImageView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/ComposeImageView.kt index 6823f29ce8..f84bee44c8 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ComposeImageView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/ComposeImageView.kt @@ -14,21 +14,18 @@ import androidx.compose.ui.graphics.asImageBitmap import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp import chat.simplex.app.R -import chat.simplex.app.model.durationText -import chat.simplex.app.ui.theme.DEFAULT_PADDING_HALF -import chat.simplex.app.ui.theme.HighOrLowlight -import chat.simplex.app.views.chat.item.SentColorLight +import chat.simplex.app.ui.theme.* import chat.simplex.app.views.helpers.UploadContent import chat.simplex.app.views.helpers.base64ToBitmap @Composable fun ComposeImageView(media: ComposePreview.MediaPreview, cancelImages: () -> Unit, cancelEnabled: Boolean) { + val sentColor = CurrentColors.collectAsState().value.appColors.sentMessage Row( Modifier .padding(top = 8.dp) - .background(SentColorLight), + .background(sentColor), verticalAlignment = Alignment.CenterVertically, ) { LazyRow( diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ComposeView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/ComposeView.kt index 1840600666..9284e81c9f 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ComposeView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/ComposeView.kt @@ -33,7 +33,6 @@ import androidx.core.content.ContextCompat import chat.simplex.app.* import chat.simplex.app.R import chat.simplex.app.model.* -import chat.simplex.app.ui.theme.HighOrLowlight import chat.simplex.app.views.chat.item.* import chat.simplex.app.views.helpers.* import kotlinx.coroutines.* @@ -689,7 +688,7 @@ fun ComposeView( Icon( painterResource(R.drawable.ic_attach_file_filled_500), contentDescription = stringResource(R.string.attach), - tint = if (!composeState.value.attachmentDisabled && userCanSend.value) MaterialTheme.colors.primary else HighOrLowlight, + tint = if (!composeState.value.attachmentDisabled && userCanSend.value) MaterialTheme.colors.primary else MaterialTheme.colors.secondary, modifier = Modifier .size(28.dp) .clip(CircleShape) diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ComposeVoiceView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/ComposeVoiceView.kt index f0994b870e..9c6babe65e 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ComposeVoiceView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/ComposeVoiceView.kt @@ -14,7 +14,6 @@ import androidx.compose.ui.unit.sp import chat.simplex.app.R import chat.simplex.app.model.durationText import chat.simplex.app.ui.theme.* -import chat.simplex.app.views.chat.item.SentColorLight import chat.simplex.app.views.helpers.* import kotlinx.coroutines.flow.distinctUntilChanged @@ -57,12 +56,13 @@ fun ComposeVoiceView( .height(3.dp) .background(MaterialTheme.colors.primary) ) + val sentColor = CurrentColors.collectAsState().value.appColors.sentMessage Row( Modifier .height(60.dp) .fillMaxWidth() .padding(top = 8.dp) - .background(SentColorLight), + .background(sentColor), verticalAlignment = Alignment.CenterVertically ) { IconButton( @@ -80,7 +80,7 @@ fun ComposeVoiceView( Modifier .padding(start = 4.dp, end = 2.dp) .size(36.dp), - tint = if (finishedRecording) MaterialTheme.colors.primary else HighOrLowlight + tint = if (finishedRecording) MaterialTheme.colors.primary else MaterialTheme.colors.secondary ) } val numberInText = remember(recordedDurationMs, progress.value) { @@ -95,7 +95,7 @@ fun ComposeVoiceView( Text( durationText(numberInText.value), fontSize = 18.sp, - color = HighOrLowlight, + color = MaterialTheme.colors.secondary, ) Spacer(Modifier.weight(1f)) if (cancelEnabled) { diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ContactPreferences.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/ContactPreferences.kt index 46c96e47af..c5fa9daa57 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ContactPreferences.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/ContactPreferences.kt @@ -194,10 +194,10 @@ private fun TimedMessagesFeatureSection( private fun ResetSaveButtons(reset: () -> Unit, save: () -> Unit, disabled: Boolean) { SectionView { SectionItemView(reset, disabled = disabled) { - Text(stringResource(R.string.reset_verb), color = if (disabled) HighOrLowlight else MaterialTheme.colors.primary) + Text(stringResource(R.string.reset_verb), color = if (disabled) MaterialTheme.colors.secondary else MaterialTheme.colors.primary) } SectionItemView(save, disabled = disabled) { - Text(stringResource(R.string.save_and_notify_contact), color = if (disabled) HighOrLowlight else MaterialTheme.colors.primary) + Text(stringResource(R.string.save_and_notify_contact), color = if (disabled) MaterialTheme.colors.secondary else MaterialTheme.colors.primary) } } } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ContextItemView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/ContextItemView.kt index c030fb86d2..5a24eaf525 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ContextItemView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/ContextItemView.kt @@ -5,6 +5,7 @@ import androidx.compose.foundation.layout.* import androidx.compose.material.* import androidx.compose.ui.graphics.painter.Painter import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource @@ -13,8 +14,7 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import chat.simplex.app.R import chat.simplex.app.model.* -import chat.simplex.app.ui.theme.HighOrLowlight -import chat.simplex.app.ui.theme.SimpleXTheme +import chat.simplex.app.ui.theme.* import chat.simplex.app.views.chat.item.* import kotlinx.datetime.Clock @@ -25,10 +25,12 @@ fun ContextItemView( cancelContextItem: () -> Unit ) { val sent = contextItem.chatDir.sent + val sentColor = CurrentColors.collectAsState().value.appColors.sentMessage + val receivedColor = CurrentColors.collectAsState().value.appColors.receivedMessage Row( Modifier .padding(top = 8.dp) - .background(if (sent) SentColorLight else ReceivedColorLight), + .background(if (sent) sentColor else receivedColor), verticalAlignment = Alignment.CenterVertically ) { Row( @@ -45,7 +47,7 @@ fun ContextItemView( .height(20.dp) .width(20.dp), contentDescription = stringResource(R.string.icon_descr_context), - tint = HighOrLowlight, + tint = MaterialTheme.colors.secondary, ) MarkdownText( contextItem.text, contextItem.formattedText, diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/SendMsgView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/SendMsgView.kt index 7b9b323cb6..d9d67074d3 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/SendMsgView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/SendMsgView.kt @@ -44,7 +44,7 @@ import androidx.core.widget.* import chat.simplex.app.R import chat.simplex.app.SimplexApp import chat.simplex.app.model.* -import chat.simplex.app.ui.theme.HighOrLowlight +import chat.simplex.app.ui.theme.CurrentColors import chat.simplex.app.ui.theme.SimpleXTheme import chat.simplex.app.views.chat.item.ItemAction import chat.simplex.app.views.helpers.* @@ -187,7 +187,7 @@ private fun NativeKeyboard( ) { val cs = composeState.value val textColor = MaterialTheme.colors.onBackground - val tintColor = MaterialTheme.colors.secondary + val tintColor = MaterialTheme.colors.secondaryVariant val padding = PaddingValues(12.dp, 7.dp, 45.dp, 0.dp) val paddingStart = with(LocalDensity.current) { 12.dp.roundToPx() } val paddingTop = with(LocalDensity.current) { 7.dp.roundToPx() } @@ -240,7 +240,7 @@ private fun NativeKeyboard( editText.setPadding(paddingStart, paddingTop, paddingEnd, paddingBottom) editText.setText(cs.message) if (Build.VERSION.SDK_INT >= 29) { - editText.textCursorDrawable?.let { DrawableCompat.setTint(it, HighOrLowlight.toArgb()) } + editText.textCursorDrawable?.let { DrawableCompat.setTint(it, CurrentColors.value.colors.secondary.toArgb()) } } else { try { val f: Field = TextView::class.java.getDeclaredField("mCursorDrawableRes") @@ -284,7 +284,7 @@ private fun ComposeOverlay(textId: Int, textStyle: MutableState, padd Text( generalGetString(textId), Modifier.padding(padding), - color = HighOrLowlight, + color = MaterialTheme.colors.secondary, style = textStyle.value.copy(fontStyle = FontStyle.Italic) ) } @@ -295,7 +295,7 @@ private fun BoxScope.DeleteTextButton(composeState: MutableState) { composeState.value = composeState.value.copy(message = "") }, Modifier.align(Alignment.TopEnd).size(36.dp) ) { - Icon(painterResource(R.drawable.ic_close), null, Modifier.padding(7.dp).size(36.dp), tint = HighOrLowlight) + Icon(painterResource(R.drawable.ic_close), null, Modifier.padding(7.dp).size(36.dp), tint = MaterialTheme.colors.secondary) } } @@ -354,7 +354,7 @@ private fun DisallowedVoiceButton(enabled: Boolean, onClick: () -> Unit) { Icon( painterResource(R.drawable.ic_keyboard_voice), stringResource(R.string.icon_descr_record_voice_message), - tint = HighOrLowlight, + tint = MaterialTheme.colors.secondary, modifier = Modifier .size(36.dp) .padding(4.dp) @@ -424,7 +424,7 @@ private fun RecordVoiceButton(interactionSource: MutableInteractionSource) { @Composable private fun ProgressIndicator() { - CircularProgressIndicator(Modifier.size(36.dp).padding(4.dp), color = HighOrLowlight, strokeWidth = 3.dp) + CircularProgressIndicator(Modifier.size(36.dp).padding(4.dp), color = MaterialTheme.colors.secondary, strokeWidth = 3.dp) } @Composable @@ -474,7 +474,7 @@ private fun SendMsgButton( .padding(4.dp) .alpha(alpha.value) .clip(CircleShape) - .background(if (enabled) MaterialTheme.colors.primary else HighOrLowlight) + .background(if (enabled) MaterialTheme.colors.primary else MaterialTheme.colors.secondary) .padding(3.dp) ) } @@ -497,7 +497,7 @@ private fun StartLiveMessageButton(enabled: Boolean, onClick: () -> Unit) { Icon( BoltFilled, stringResource(R.string.icon_descr_send_message), - tint = if (enabled) MaterialTheme.colors.primary else HighOrLowlight, + tint = if (enabled) MaterialTheme.colors.primary else MaterialTheme.colors.secondary, modifier = Modifier .size(36.dp) .padding(4.dp) diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/VerifyCodeView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/VerifyCodeView.kt index 81d20e8444..12e8ab1aa9 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/VerifyCodeView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/VerifyCodeView.kt @@ -65,7 +65,7 @@ private fun VerifyCodeLayout( val splitCode = splitToParts(connectionCode, 24) Row(Modifier.fillMaxWidth().padding(bottom = DEFAULT_PADDING_HALF), horizontalArrangement = Arrangement.Center) { if (connectionVerified) { - Icon(painterResource(R.drawable.ic_verified_user), null, Modifier.padding(end = 4.dp).size(22.dp), tint = HighOrLowlight) + Icon(painterResource(R.drawable.ic_verified_user), null, Modifier.padding(end = 4.dp).size(22.dp), tint = MaterialTheme.colors.secondary) Text(String.format(stringResource(R.string.is_verified), displayName)) } else { Text(String.format(stringResource(R.string.is_not_verified), displayName)) 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 a57f563250..096b19de0a 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 @@ -133,7 +133,7 @@ fun AddGroupMembersLayout( Text( stringResource(R.string.no_contacts_to_add), Modifier.padding(), - color = HighOrLowlight + color = MaterialTheme.colors.secondary ) } } else { @@ -214,7 +214,7 @@ fun InviteSectionFooter(selectedContactsCount: Int, enabled: Boolean, clearSelec if (selectedContactsCount >= 1) { Text( String.format(generalGetString(R.string.num_contacts_selected), selectedContactsCount), - color = HighOrLowlight, + color = MaterialTheme.colors.secondary, fontSize = 12.sp ) Box( @@ -222,14 +222,14 @@ fun InviteSectionFooter(selectedContactsCount: Int, enabled: Boolean, clearSelec ) { Text( stringResource(R.string.clear_contacts_selection_button), - color = if (enabled) MaterialTheme.colors.primary else HighOrLowlight, + color = if (enabled) MaterialTheme.colors.primary else MaterialTheme.colors.secondary, fontSize = 12.sp ) } } else { Text( stringResource(R.string.no_contacts_selected), - color = HighOrLowlight, + color = MaterialTheme.colors.secondary, fontSize = 12.sp ) } @@ -270,13 +270,13 @@ fun ContactCheckRow( val iconColor: Color if (prohibitedToInviteIncognito) { icon = painterResource(R.drawable.ic_theater_comedy_filled) - iconColor = HighOrLowlight + iconColor = MaterialTheme.colors.secondary } else if (checked) { icon = painterResource(R.drawable.ic_check_circle_filled) - iconColor = if (enabled) MaterialTheme.colors.primary else HighOrLowlight + iconColor = if (enabled) MaterialTheme.colors.primary else MaterialTheme.colors.secondary } else { icon = painterResource(R.drawable.ic_circle) - iconColor = HighOrLowlight + iconColor = MaterialTheme.colors.secondary } SectionItemView( click = if (enabled) { @@ -294,7 +294,7 @@ fun ContactCheckRow( Spacer(Modifier.width(DEFAULT_SPACE_AFTER_ICON)) Text( contact.chatViewName, maxLines = 1, overflow = TextOverflow.Ellipsis, - color = if (prohibitedToInviteIncognito) HighOrLowlight else Color.Unspecified + color = if (prohibitedToInviteIncognito) MaterialTheme.colors.secondary else Color.Unspecified ) Spacer(Modifier.fillMaxWidth().weight(1f)) Icon( 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 7eb93e2d32..728056f1d9 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 @@ -191,7 +191,7 @@ fun GroupChatInfoLayout( } val onAddMembersClick = if (chat.chatInfo.incognito) ::cantInviteIncognitoAlert else addMembers - val tint = if (chat.chatInfo.incognito) HighOrLowlight else MaterialTheme.colors.primary + val tint = if (chat.chatInfo.incognito) MaterialTheme.colors.secondary else MaterialTheme.colors.primary AddMembersButton(tint, onAddMembersClick) } SectionItemView(minHeight = 54.dp) { @@ -305,7 +305,7 @@ private fun MemberRow(member: GroupMember, user: Boolean = false) { val statusDescr = if (user) String.format(generalGetString(R.string.group_info_member_you), s) else s Text( statusDescr, - color = HighOrLowlight, + color = MaterialTheme.colors.secondary, fontSize = 12.sp, maxLines = 1, overflow = TextOverflow.Ellipsis @@ -314,14 +314,14 @@ private fun MemberRow(member: GroupMember, user: Boolean = false) { } val role = member.memberRole if (role == GroupMemberRole.Owner || role == GroupMemberRole.Admin) { - Text(role.text, color = HighOrLowlight) + Text(role.text, color = MaterialTheme.colors.secondary) } } } @Composable private fun MemberVerifiedShield() { - Icon(painterResource(R.drawable.ic_verified_user), null, Modifier.padding(end = 3.dp).size(16.dp), tint = HighOrLowlight) + Icon(painterResource(R.drawable.ic_verified_user), null, Modifier.padding(end = 3.dp).size(16.dp), tint = MaterialTheme.colors.secondary) } @Composable @@ -330,7 +330,7 @@ private fun GroupLinkButton(onClick: () -> Unit) { painterResource(R.drawable.ic_link), stringResource(R.string.group_link), onClick, - iconColor = HighOrLowlight + iconColor = MaterialTheme.colors.secondary ) } @@ -340,7 +340,7 @@ private fun CreateGroupLinkButton(onClick: () -> Unit) { painterResource(R.drawable.ic_add_link), stringResource(R.string.create_group_link), onClick, - iconColor = HighOrLowlight + iconColor = MaterialTheme.colors.secondary ) } @@ -350,7 +350,7 @@ fun EditGroupProfileButton(onClick: () -> Unit) { painterResource(R.drawable.ic_edit), stringResource(R.string.button_edit_group_profile), onClick, - iconColor = HighOrLowlight + iconColor = MaterialTheme.colors.secondary ) } @@ -365,7 +365,7 @@ private fun AddOrEditWelcomeMessage(welcomeMessage: String?, onClick: () -> Unit painterResource(R.drawable.ic_maps_ugc), text, onClick, - iconColor = HighOrLowlight + iconColor = MaterialTheme.colors.secondary ) } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupLinkView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupLinkView.kt index 6fb2eaf9d3..42a893ce99 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupLinkView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupLinkView.kt @@ -4,8 +4,7 @@ import SectionBottomSpacer import androidx.compose.foundation.layout.* import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll -import androidx.compose.material.CircularProgressIndicator -import androidx.compose.material.Text +import androidx.compose.material.* import androidx.compose.runtime.* import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Alignment @@ -177,7 +176,7 @@ fun ProgressIndicator() { Modifier .padding(horizontal = 2.dp) .size(30.dp), - color = HighOrLowlight, + color = MaterialTheme.colors.secondary, strokeWidth = 2.5.dp ) } 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 612b017823..0ba92cc3fc 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 @@ -239,7 +239,7 @@ fun GroupMemberInfoHeader(member: GroupMember) { ProfileImage(size = 192.dp, member.image, color = if (isInDarkTheme()) GroupDark else SettingsSecondaryLight) Row(verticalAlignment = Alignment.CenterVertically) { if (member.verified) { - Icon(painterResource(R.drawable.ic_verified_user), null, Modifier.padding(end = 6.dp, top = 4.dp).size(24.dp), tint = HighOrLowlight) + Icon(painterResource(R.drawable.ic_verified_user), null, Modifier.padding(end = 6.dp, top = 4.dp).size(24.dp), tint = MaterialTheme.colors.secondary) } Text( member.displayName, style = MaterialTheme.typography.h1.copy(fontWeight = FontWeight.Normal), diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupPreferences.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupPreferences.kt index aa9715cf1a..2b2d85e2a3 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupPreferences.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupPreferences.kt @@ -123,7 +123,7 @@ private fun FeatureSection( SectionView { val on = enableFeature.value == GroupFeatureEnabled.ON val icon = if (on) feature.iconFilled() else feature.icon - val iconTint = if (on) SimplexGreen else HighOrLowlight + val iconTint = if (on) SimplexGreen else MaterialTheme.colors.secondary val timedOn = feature == GroupFeature.TimedMessages && enableFeature.value == GroupFeatureEnabled.ON if (groupInfo.canEdit) { PreferenceToggleWithIcon( @@ -157,10 +157,10 @@ private fun FeatureSection( private fun ResetSaveButtons(reset: () -> Unit, save: () -> Unit, disabled: Boolean) { SectionView { SectionItemView(reset, disabled = disabled) { - Text(stringResource(R.string.reset_verb), color = if (disabled) HighOrLowlight else MaterialTheme.colors.primary) + Text(stringResource(R.string.reset_verb), color = if (disabled) MaterialTheme.colors.secondary else MaterialTheme.colors.primary) } SectionItemView(save, disabled = disabled) { - Text(stringResource(R.string.save_and_notify_group_members), color = if (disabled) HighOrLowlight else MaterialTheme.colors.primary) + Text(stringResource(R.string.save_and_notify_group_members), color = if (disabled) MaterialTheme.colors.secondary else MaterialTheme.colors.primary) } } } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupProfileView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupProfileView.kt index 844c0f149e..93e37c9e74 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupProfileView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupProfileView.kt @@ -114,7 +114,7 @@ fun GroupProfileLayout( ) { Box(contentAlignment = Alignment.TopEnd) { Box(contentAlignment = Alignment.Center) { - ProfileImage(108.dp, profileImage.value, color = HighOrLowlight.copy(alpha = 0.1f)) + ProfileImage(108.dp, profileImage.value, color = MaterialTheme.colors.secondary.copy(alpha = 0.1f)) EditImageButton { scope.launch { bottomSheetModalState.show() } } } if (profileImage.value != null) { @@ -163,7 +163,7 @@ fun GroupProfileLayout( } else { Text( stringResource(R.string.save_group_profile), - color = HighOrLowlight + color = MaterialTheme.colors.secondary ) } } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/WelcomeMessageView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/WelcomeMessageView.kt index 906a8815e9..9e9408e993 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/WelcomeMessageView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/WelcomeMessageView.kt @@ -79,7 +79,7 @@ private fun GroupWelcomeLayout( private fun SaveButton(save: () -> Unit, disabled: Boolean) { SectionView { SectionItemView(save, disabled = disabled) { - Text(stringResource(R.string.save_and_update_group_profile), color = if (disabled) HighOrLowlight else MaterialTheme.colors.primary) + Text(stringResource(R.string.save_and_update_group_profile), color = if (disabled) MaterialTheme.colors.secondary else MaterialTheme.colors.primary) } } } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CICallItemView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CICallItemView.kt index 06224d1cc0..378ee4d5b4 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CICallItemView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CICallItemView.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.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -35,15 +34,15 @@ fun CICallItemView(cInfo: ChatInfo, cItem: ChatItem, status: CICallStatus, durat CICallStatus.Negotiated -> ConnectingCallIcon() CICallStatus.Progress -> Icon(painterResource(R.drawable.ic_phone_in_talk_filled), stringResource(R.string.icon_descr_call_progress), tint = SimplexGreen) CICallStatus.Ended -> Row { - Icon(painterResource(R.drawable.ic_call_end), stringResource(R.string.icon_descr_call_ended), tint = HighOrLowlight, modifier = Modifier.padding(end = 4.dp)) - Text(durationText(duration), color = HighOrLowlight) + Icon(painterResource(R.drawable.ic_call_end), stringResource(R.string.icon_descr_call_ended), tint = MaterialTheme.colors.secondary, modifier = Modifier.padding(end = 4.dp)) + Text(durationText(duration), color = MaterialTheme.colors.secondary) } CICallStatus.Error -> {} } Text( cItem.timestampText, - color = HighOrLowlight, + color = MaterialTheme.colors.secondary, fontSize = 14.sp, modifier = Modifier.padding(start = 3.dp) ) @@ -55,7 +54,7 @@ fun AcceptCallButton(cInfo: ChatInfo, acceptCall: (Contact) -> Unit) { if (cInfo is ChatInfo.Direct) { SimpleButton(stringResource(R.string.answer_call), painterResource(R.drawable.ic_ring_volume)) { acceptCall(cInfo.contact) } } else { - Icon(painterResource(R.drawable.ic_ring_volume), stringResource(R.string.answer_call), tint = HighOrLowlight) + Icon(painterResource(R.drawable.ic_ring_volume), stringResource(R.string.answer_call), tint = MaterialTheme.colors.secondary) } // if case let .direct(contact) = chatInfo { // Button { diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIEventView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIEventView.kt index 5b37c402b7..32933a57d7 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIEventView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIEventView.kt @@ -13,8 +13,7 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import chat.simplex.app.model.ChatItem -import chat.simplex.app.ui.theme.HighOrLowlight -import chat.simplex.app.ui.theme.SimpleXTheme +import chat.simplex.app.ui.theme.* @Composable fun CIEventView(ci: ChatItem) { @@ -22,28 +21,25 @@ fun CIEventView(ci: ChatItem) { fun chatEventTextView(text: AnnotatedString) { Text(text, style = MaterialTheme.typography.body1.copy(lineHeight = 22.sp)) } - - Surface { - Row( - Modifier.padding(horizontal = 6.dp, vertical = 6.dp), - verticalAlignment = Alignment.CenterVertically - ) { - val memberDisplayName = ci.memberDisplayName - if (memberDisplayName != null) { - chatEventTextView( - buildAnnotatedString { - withStyle(chatEventStyle) { append(memberDisplayName) } - append(" ") - }.plus(chatEventText(ci)) - ) - } else { - chatEventTextView(chatEventText(ci)) - } + Row( + Modifier.padding(horizontal = 6.dp, vertical = 6.dp), + verticalAlignment = Alignment.CenterVertically + ) { + val memberDisplayName = ci.memberDisplayName + if (memberDisplayName != null) { + chatEventTextView( + buildAnnotatedString { + withStyle(chatEventStyle) { append(memberDisplayName) } + append(" ") + }.plus(chatEventText(ci)) + ) + } else { + chatEventTextView(chatEventText(ci)) } } } -val chatEventStyle = SpanStyle(fontSize = 12.sp, fontWeight = FontWeight.Light, color = HighOrLowlight) +val chatEventStyle = SpanStyle(fontSize = 12.sp, fontWeight = FontWeight.Light, color = CurrentColors.value.colors.secondary) fun chatEventText(ci: ChatItem): AnnotatedString = buildAnnotatedString { diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIFeaturePreferenceView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIFeaturePreferenceView.kt index bb3f400eab..ab9d0896a1 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIFeaturePreferenceView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIFeaturePreferenceView.kt @@ -11,7 +11,6 @@ import androidx.compose.ui.unit.dp 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.views.helpers.generalGetString @Composable @@ -27,7 +26,7 @@ fun CIFeaturePreferenceView( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(4.dp) ) { - Icon(feature.icon, feature.text, Modifier.size(18.dp), tint = HighOrLowlight) + Icon(feature.icon, feature.text, Modifier.size(18.dp), tint = MaterialTheme.colors.secondary) if (contact != null && allowed != FeatureAllowed.NO && contact.allowsFeature(feature) && !contact.userAllowsFeature(feature)) { val acceptStyle = SpanStyle(color = MaterialTheme.colors.primary, fontSize = 12.sp) val setParam = feature == ChatFeature.TimedMessages && contact.mergedPreferences.timedMessages.userPreference.pref.ttl == null @@ -48,7 +47,7 @@ fun CIFeaturePreferenceView( ) } else { Text(chatItem.content.text + " " + chatItem.timestampText, - fontSize = 12.sp, fontWeight = FontWeight.Light, color = HighOrLowlight) + fontSize = 12.sp, fontWeight = FontWeight.Light, color = MaterialTheme.colors.secondary) } } } 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 0194da14d8..39ac18f08a 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 @@ -194,7 +194,7 @@ fun CIFileView( ) Text( formatBytes(file.fileSize) + metaReserve, - color = HighOrLowlight, + color = MaterialTheme.colors.secondary, fontSize = 14.sp, maxLines = 1 ) 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 d55c4ee8ba..e53af51af0 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 @@ -8,7 +8,6 @@ import androidx.compose.material.* import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow @@ -69,12 +68,14 @@ fun CIGroupInvitationView( } } + val sentColor = CurrentColors.collectAsState().value.appColors.sentMessage + val receivedColor = CurrentColors.collectAsState().value.appColors.receivedMessage Surface( modifier = if (action) Modifier.clickable(onClick = { joinGroup(groupInvitation.groupId) }) else Modifier, shape = RoundedCornerShape(18.dp), - color = if (sent) SentColorLight else ReceivedColorLight, + color = if (sent) sentColor else receivedColor, ) { Box( Modifier @@ -105,7 +106,7 @@ fun CIGroupInvitationView( } Text( ci.timestampText, - color = HighOrLowlight, + color = MaterialTheme.colors.secondary, fontSize = 14.sp, modifier = Modifier.padding(start = 3.dp) ) 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 81afbc10e4..23ed293876 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 @@ -14,11 +14,11 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import chat.simplex.app.model.* -import chat.simplex.app.ui.theme.HighOrLowlight +import chat.simplex.app.ui.theme.CurrentColors import kotlinx.datetime.Clock @Composable -fun CIMetaView(chatItem: ChatItem, timedMessagesTTL: Int?, metaColor: Color = HighOrLowlight) { +fun CIMetaView(chatItem: ChatItem, timedMessagesTTL: Int?, metaColor: Color = MaterialTheme.colors.secondary) { Row(Modifier.padding(start = 3.dp), verticalAlignment = Alignment.CenterVertically) { if (chatItem.isDeletedContent) { Text( @@ -72,7 +72,7 @@ fun reserveSpaceForMeta(meta: CIMeta, chatTTL: Int?): String { res += TimedMessagesPreference.shortTtlText(ttl) } } - if (meta.statusIcon(HighOrLowlight) != null || !meta.disappearing) { + if (meta.statusIcon(CurrentColors.value.colors.secondary) != null || !meta.disappearing) { res += iconSpace } return res + meta.timestampText diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIVoiceView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIVoiceView.kt index 8d6bd2c8cc..d8acbe6c49 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIVoiceView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIVoiceView.kt @@ -137,7 +137,7 @@ private fun DurationText(text: State, padding: PaddingValues) { Modifier .padding(padding) .widthIn(min = minWidth), - color = HighOrLowlight, + color = MaterialTheme.colors.secondary, fontSize = 16.sp, maxLines = 1 ) @@ -156,9 +156,11 @@ private fun PlayPauseButton( pause: () -> Unit, longClick: () -> Unit ) { + val sentColor = CurrentColors.collectAsState().value.appColors.sentMessage + val receivedColor = CurrentColors.collectAsState().value.appColors.receivedMessage Surface( Modifier.drawRingModifier(angle, strokeColor, strokeWidth), - color = if (sent) SentColorLight else ReceivedColorLight, + color = if (sent) sentColor else receivedColor, shape = MaterialTheme.shapes.small.copy(CornerSize(percent = 50)) ) { Box( @@ -174,7 +176,7 @@ private fun PlayPauseButton( if (audioPlaying) painterResource(R.drawable.ic_pause_filled) else painterResource(R.drawable.ic_play_arrow_filled), contentDescription = null, Modifier.size(36.dp), - tint = if (error) WarningOrange else if (!enabled) HighOrLowlight else MaterialTheme.colors.primary + tint = if (error) WarningOrange else if (!enabled) MaterialTheme.colors.secondary else MaterialTheme.colors.primary ) } } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/ChatItemView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/ChatItemView.kt index 96c6fbca76..f5376355f4 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/ChatItemView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/ChatItemView.kt @@ -247,7 +247,7 @@ fun ChatItemView( val ct = if (cInfo is ChatInfo.Direct) cInfo.contact else null CIFeaturePreferenceView(cItem, ct, c.feature, c.allowed, acceptFeature) } - is CIContent.SndChatPreference -> CIChatFeatureView(cItem, c.feature, HighOrLowlight, icon = c.feature.icon,) + is CIContent.SndChatPreference -> CIChatFeatureView(cItem, c.feature, MaterialTheme.colors.secondary, icon = c.feature.icon,) is CIContent.RcvGroupFeature -> CIChatFeatureView(cItem, c.groupFeature, c.preference.enable.iconColor) is CIContent.SndGroupFeature -> CIChatFeatureView(cItem, c.groupFeature, c.preference.enable.iconColor) is CIContent.RcvChatFeatureRejected -> CIChatFeatureView(cItem, c.feature, Color.Red) diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/DeletedItemView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/DeletedItemView.kt index 06499418b1..49a9ce28e6 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/DeletedItemView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/DeletedItemView.kt @@ -5,6 +5,7 @@ import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.* import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.text.* @@ -13,15 +14,16 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import chat.simplex.app.model.ChatItem -import chat.simplex.app.ui.theme.HighOrLowlight -import chat.simplex.app.ui.theme.SimpleXTheme +import chat.simplex.app.ui.theme.* @Composable fun DeletedItemView(ci: ChatItem, timedMessagesTTL: Int?, showMember: Boolean = false) { val sent = ci.chatDir.sent + val sentColor = CurrentColors.collectAsState().value.appColors.sentMessage + val receivedColor = CurrentColors.collectAsState().value.appColors.receivedMessage Surface( shape = RoundedCornerShape(18.dp), - color = if (sent) SentColorLight else ReceivedColorLight, + color = if (sent) sentColor else receivedColor, ) { Row( Modifier.padding(horizontal = 12.dp, vertical = 6.dp), @@ -30,7 +32,7 @@ fun DeletedItemView(ci: ChatItem, timedMessagesTTL: Int?, showMember: Boolean = Text( buildAnnotatedString { appendSender(this, if (showMember) ci.memberDisplayName else null, true) - withStyle(SpanStyle(fontStyle = FontStyle.Italic, color = HighOrLowlight)) { append(ci.content.text) } + withStyle(SpanStyle(fontStyle = FontStyle.Italic, color = MaterialTheme.colors.secondary)) { append(ci.content.text) } }, style = MaterialTheme.typography.body1.copy(lineHeight = 22.sp), modifier = Modifier.padding(end = 8.dp) 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 fe80af7bc5..99d6ab7eae 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 @@ -29,11 +29,6 @@ import chat.simplex.app.views.helpers.* import kotlinx.datetime.Clock import kotlin.math.min -val SentColorLight = Color(0x1E45B8FF) -val ReceivedColorLight = Color(0x20B1B0B5) -val SentQuoteColorLight = Color(0x2545B8FF) -val ReceivedQuoteColorLight = Color(0x25B1B0B5) - @Composable fun FramedItemView( chatInfo: ChatInfo, @@ -54,6 +49,9 @@ fun FramedItemView( return if (chatInfo is ChatInfo.Group) chatInfo.groupInfo.membership else null } + @Composable + fun Color.toQuote(): Color = if (isInDarkTheme()) lighter(0.12f) else darker(0.12f) + @Composable fun ciQuotedMsgView(qi: CIQuote) { Box( @@ -70,9 +68,11 @@ fun FramedItemView( @Composable fun FramedItemHeader(caption: String, italic: Boolean, icon: Painter? = null) { + val sentColor = CurrentColors.collectAsState().value.appColors.sentMessage + val receivedColor = CurrentColors.collectAsState().value.appColors.receivedMessage Row( Modifier - .background(if (sent) SentQuoteColorLight else ReceivedQuoteColorLight) + .background(if (sent) sentColor.toQuote() else receivedColor.toQuote()) .fillMaxWidth() .padding(start = 8.dp, top = 6.dp, end = 12.dp, bottom = if (ci.quotedItem == null) 6.dp else 0.dp), horizontalArrangement = Arrangement.spacedBy(4.dp), @@ -87,7 +87,7 @@ fun FramedItemView( } Text( buildAnnotatedString { - withStyle(SpanStyle(fontSize = 12.sp, fontStyle = if (italic) FontStyle.Italic else FontStyle.Normal, color = HighOrLowlight)) { + withStyle(SpanStyle(fontSize = 12.sp, fontStyle = if (italic) FontStyle.Italic else FontStyle.Normal, color = MaterialTheme.colors.secondary)) { append(caption) } }, @@ -100,9 +100,11 @@ fun FramedItemView( @Composable fun ciQuoteView(qi: CIQuote) { + val sentColor = CurrentColors.collectAsState().value.appColors.sentMessage + val receivedColor = CurrentColors.collectAsState().value.appColors.receivedMessage Row( Modifier - .background(if (sent) SentQuoteColorLight else ReceivedQuoteColorLight) + .background(if (sent) sentColor.toQuote() else receivedColor.toQuote()) .fillMaxWidth() .combinedClickable( onLongClick = { showMenu.value = true }, @@ -163,16 +165,18 @@ fun FramedItemView( val transparentBackground = (ci.content.msgContent is MsgContent.MCImage || ci.content.msgContent is MsgContent.MCVideo) && !ci.meta.isLive && ci.content.text.isEmpty() && ci.quotedItem == null + val sentColor = CurrentColors.collectAsState().value.appColors.sentMessage + val receivedColor = CurrentColors.collectAsState().value.appColors.receivedMessage Box(Modifier .clip(RoundedCornerShape(18.dp)) .background( when { transparentBackground -> Color.Transparent - sent -> SentColorLight - else -> ReceivedColorLight + sent -> sentColor + else -> receivedColor } )) { - var metaColor = HighOrLowlight + var metaColor = MaterialTheme.colors.secondary Box(contentAlignment = Alignment.BottomEnd) { Column(Modifier.width(IntrinsicSize.Max)) { PriorityLayout(Modifier, CHAT_IMAGE_LAYOUT_ID) { diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/IntegrityErrorItemView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/IntegrityErrorItemView.kt index fa25e0f88a..e1ddd3b3e7 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/IntegrityErrorItemView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/IntegrityErrorItemView.kt @@ -7,6 +7,7 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.* import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color @@ -18,6 +19,7 @@ import androidx.compose.ui.unit.sp import chat.simplex.app.R import chat.simplex.app.model.ChatItem import chat.simplex.app.model.MsgErrorType +import chat.simplex.app.ui.theme.CurrentColors import chat.simplex.app.ui.theme.SimpleXTheme import chat.simplex.app.views.helpers.AlertManager import chat.simplex.app.views.helpers.generalGetString @@ -50,10 +52,11 @@ fun IntegrityErrorItemView(msgError: MsgErrorType, ci: ChatItem, timedMessagesTT @Composable fun CIMsgError(ci: ChatItem, timedMessagesTTL: Int?, showMember: Boolean = false, onClick: () -> Unit) { + val receivedColor = CurrentColors.collectAsState().value.appColors.receivedMessage Surface( Modifier.clickable(onClick = onClick), shape = RoundedCornerShape(18.dp), - color = ReceivedColorLight, + color = receivedColor, ) { Row( Modifier.padding(horizontal = 12.dp, vertical = 6.dp), diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/MarkedDeletedItemView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/MarkedDeletedItemView.kt index a63a232939..4bb56b60fa 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/MarkedDeletedItemView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/MarkedDeletedItemView.kt @@ -5,6 +5,7 @@ import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.* import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.text.* @@ -16,15 +17,16 @@ import androidx.compose.ui.unit.sp import chat.simplex.app.R import chat.simplex.app.model.CIDeleted import chat.simplex.app.model.ChatItem -import chat.simplex.app.ui.theme.HighOrLowlight -import chat.simplex.app.ui.theme.SimpleXTheme +import chat.simplex.app.ui.theme.* import chat.simplex.app.views.helpers.generalGetString @Composable fun MarkedDeletedItemView(ci: ChatItem, timedMessagesTTL: Int?, showMember: Boolean = false) { + val sentColor = CurrentColors.collectAsState().value.appColors.sentMessage + val receivedColor = CurrentColors.collectAsState().value.appColors.receivedMessage Surface( shape = RoundedCornerShape(18.dp), - color = if (ci.chatDir.sent) SentColorLight else ReceivedColorLight, + color = if (ci.chatDir.sent) sentColor else receivedColor, ) { Row( Modifier.padding(horizontal = 12.dp, vertical = 6.dp), @@ -47,7 +49,7 @@ private fun MarkedDeletedText(text: String) { Text( buildAnnotatedString { // appendSender(this, if (showMember) ci.memberDisplayName else null, true) // TODO font size - withStyle(SpanStyle(fontSize = 12.sp, fontStyle = FontStyle.Italic, color = HighOrLowlight)) { append(text) } + withStyle(SpanStyle(fontSize = 12.sp, fontStyle = FontStyle.Italic, color = MaterialTheme.colors.secondary)) { append(text) } }, style = MaterialTheme.typography.body1.copy(lineHeight = 22.sp), modifier = Modifier.padding(end = 8.dp), diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/TextItemView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/TextItemView.kt index d6fe1b2f4c..de5fd1594e 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/TextItemView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/TextItemView.kt @@ -22,7 +22,7 @@ import androidx.compose.ui.unit.* import androidx.core.text.BidiFormatter import chat.simplex.app.TAG import chat.simplex.app.model.* -import chat.simplex.app.ui.theme.HighOrLowlight +import chat.simplex.app.ui.theme.CurrentColors import chat.simplex.app.views.helpers.detectGesture import kotlinx.coroutines.* @@ -57,7 +57,7 @@ private val typingIndicators: List = listOf( private fun typingIndicator(recent: Boolean, @IntRange (from = 0, to = 4) typingIdx: Int): AnnotatedString = buildAnnotatedString { - pushStyle(SpanStyle(color = HighOrLowlight, fontFamily = FontFamily.Monospace, letterSpacing = (-1).sp)) + pushStyle(SpanStyle(color = CurrentColors.value.colors.secondary, fontFamily = FontFamily.Monospace, letterSpacing = (-1).sp)) append(if (recent) typingIndicators[typingIdx] else noTyping) } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatListNavLinkView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatListNavLinkView.kt index fa8b639b96..e005ae0c3d 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatListNavLinkView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatListNavLinkView.kt @@ -328,7 +328,7 @@ fun ContactConnectionMenuItems(chatInfo: ChatInfo.ContactConnection, chatModel: @Composable private fun InvalidDataView() { Row { - ProfileImage(72.dp, null, R.drawable.ic_account_circle_filled, HighOrLowlight) + ProfileImage(72.dp, null, R.drawable.ic_account_circle_filled, MaterialTheme.colors.secondary) Column( modifier = Modifier .padding(horizontal = 8.dp) diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatListView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatListView.kt index 1580a265d2..6104f7e6b0 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatListView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatListView.kt @@ -84,7 +84,7 @@ fun ChatListView(chatModel: ChatModel, setPerformLA: (Boolean, FragmentActivity) hoveredElevation = 0.dp, focusedElevation = 0.dp, ), - backgroundColor = if (!stopped) MaterialTheme.colors.primary else HighOrLowlight, + backgroundColor = if (!stopped) MaterialTheme.colors.primary else MaterialTheme.colors.secondary, contentColor = Color.White ) { Icon(if (!newChatSheetState.collectAsState().value.isVisible()) painterResource(R.drawable.ic_edit_filled) else painterResource(R.drawable.ic_close), stringResource(R.string.add_contact_or_create_group)) @@ -96,7 +96,6 @@ fun ChatListView(chatModel: ChatModel, setPerformLA: (Boolean, FragmentActivity) Column( modifier = Modifier .fillMaxSize() - .background(MaterialTheme.colors.background) ) { if (chatModel.chats.isNotEmpty()) { ChatList(chatModel, search = searchInList) @@ -105,7 +104,7 @@ fun ChatListView(chatModel: ChatModel, setPerformLA: (Boolean, FragmentActivity) if (!stopped && !newChatSheetState.collectAsState().value.isVisible()) { OnboardingButtons(showNewChatSheet) } - Text(stringResource(R.string.you_have_no_chats), Modifier.align(Alignment.Center), color = HighOrLowlight) + Text(stringResource(R.string.you_have_no_chats), Modifier.align(Alignment.Center), color = MaterialTheme.colors.secondary) } } } @@ -136,7 +135,7 @@ private fun OnboardingButtons(openNewChatSheet: () -> Unit) { } Spacer(Modifier.height(DEFAULT_PADDING)) ConnectButton(generalGetString(R.string.tap_to_start_new_chat), openNewChatSheet) - val color = MaterialTheme.colors.primary + val color = MaterialTheme.colors.primaryVariant Canvas(modifier = Modifier.width(40.dp).height(10.dp), onDraw = { val trianglePath = Path().apply { moveTo(0.dp.toPx(), 0f) @@ -159,7 +158,7 @@ private fun ConnectButton(text: String, onClick: () -> Unit) { onClick, shape = RoundedCornerShape(21.dp), colors = ButtonDefaults.textButtonColors( - backgroundColor = MaterialTheme.colors.primary + backgroundColor = MaterialTheme.colors.primaryVariant ), elevation = null, contentPadding = PaddingValues(horizontal = DEFAULT_PADDING, vertical = DEFAULT_PADDING_HALF), @@ -282,7 +281,7 @@ private fun ProgressIndicator() { Modifier .padding(horizontal = 2.dp) .size(30.dp), - color = HighOrLowlight, + color = MaterialTheme.colors.secondary, strokeWidth = 2.5.dp ) } 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 1c641f696a..5a4745ced8 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 @@ -46,7 +46,7 @@ fun ChatPreviewView( painterResource(R.drawable.ic_cancel_filled), stringResource(R.string.icon_descr_group_inactive), Modifier.size(18.dp).background(MaterialTheme.colors.background, CircleShape), - tint = HighOrLowlight + tint = MaterialTheme.colors.secondary ) } @@ -76,7 +76,7 @@ fun ChatPreviewView( @Composable fun VerifiedIcon() { - Icon(painterResource(R.drawable.ic_verified_user), null, Modifier.size(19.dp).padding(end = 3.dp, top = 1.dp), tint = HighOrLowlight) + Icon(painterResource(R.drawable.ic_verified_user), null, Modifier.size(19.dp).padding(end = 3.dp, top = 1.dp), tint = MaterialTheme.colors.secondary) } fun messageDraft(draft: ComposeState): Pair> { @@ -110,7 +110,7 @@ fun ChatPreviewView( "attachmentIcon" to InlineTextContent( Placeholder(20.sp, 20.sp, PlaceholderVerticalAlign.TextCenter) ) { - Icon(if (attachment?.first != null) painterResource(attachment.first) else painterResource(R.drawable.ic_edit_note), null, tint = HighOrLowlight) + Icon(if (attachment?.first != null) painterResource(attachment.first) else painterResource(R.drawable.ic_edit_note), null, tint = MaterialTheme.colors.secondary) } ) return text to inlineContent @@ -124,12 +124,12 @@ fun ChatPreviewView( if (cInfo.contact.verified) { VerifiedIcon() } - chatPreviewTitleText(if (cInfo.ready) Color.Unspecified else HighOrLowlight) + chatPreviewTitleText(if (cInfo.ready) Color.Unspecified else MaterialTheme.colors.secondary) } is ChatInfo.Group -> when (cInfo.groupInfo.membership.memberStatus) { GroupMemberStatus.MemInvited -> chatPreviewTitleText(if (chat.chatInfo.incognito) Indigo else MaterialTheme.colors.primary) - GroupMemberStatus.MemAccepted -> chatPreviewTitleText(HighOrLowlight) + GroupMemberStatus.MemAccepted -> chatPreviewTitleText(MaterialTheme.colors.secondary) else -> chatPreviewTitleText() } else -> chatPreviewTitleText() @@ -170,12 +170,12 @@ fun ChatPreviewView( when (cInfo) { is ChatInfo.Direct -> if (!cInfo.ready) { - Text(stringResource(R.string.contact_connection_pending), color = HighOrLowlight) + Text(stringResource(R.string.contact_connection_pending), color = MaterialTheme.colors.secondary) } is ChatInfo.Group -> when (cInfo.groupInfo.membership.memberStatus) { GroupMemberStatus.MemInvited -> Text(groupInvitationPreviewText(chatModelIncognito, currentUserProfileDisplayName, cInfo.groupInfo)) - GroupMemberStatus.MemAccepted -> Text(stringResource(R.string.group_connection_pending), color = HighOrLowlight) + GroupMemberStatus.MemAccepted -> Text(stringResource(R.string.group_connection_pending), color = MaterialTheme.colors.secondary) else -> {} } else -> {} @@ -208,7 +208,7 @@ fun ChatPreviewView( ) { Text( ts, - color = HighOrLowlight, + color = MaterialTheme.colors.secondary, style = MaterialTheme.typography.body2, modifier = Modifier.padding(bottom = 5.dp) ) @@ -221,10 +221,10 @@ fun ChatPreviewView( ) { Text( if (n > 0) unreadCountStr(n) else "", - color = MaterialTheme.colors.onPrimary, + color = Color.White, fontSize = 11.sp, modifier = Modifier - .background(if (stopped || showNtfsIcon) HighOrLowlight else MaterialTheme.colors.primary, shape = CircleShape) + .background(if (stopped || showNtfsIcon) MaterialTheme.colors.secondary else MaterialTheme.colors.primaryVariant, shape = CircleShape) .badgeLayout() .padding(horizontal = 3.dp) .padding(vertical = 1.dp) @@ -238,7 +238,7 @@ fun ChatPreviewView( Icon( painterResource(R.drawable.ic_notifications_off_filled), contentDescription = generalGetString(R.string.notifications), - tint = HighOrLowlight, + tint = MaterialTheme.colors.secondary, modifier = Modifier .padding(horizontal = 3.dp) .padding(vertical = 1.dp) @@ -280,7 +280,7 @@ fun ChatStatusImage(s: NetworkStatus?) { Icon( painterResource(R.drawable.ic_error), contentDescription = descr, - tint = HighOrLowlight, + tint = MaterialTheme.colors.secondary, modifier = Modifier .size(19.dp) ) @@ -289,7 +289,7 @@ fun ChatStatusImage(s: NetworkStatus?) { Modifier .padding(horizontal = 2.dp) .size(15.dp), - color = HighOrLowlight, + color = MaterialTheme.colors.secondary, strokeWidth = 1.5.dp ) } 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 9e4cd20cad..de6fe43d50 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 @@ -34,7 +34,7 @@ fun ContactConnectionView(contactConnection: PendingContactConnection) { overflow = TextOverflow.Ellipsis, style = MaterialTheme.typography.h3, fontWeight = FontWeight.Bold, - color = HighOrLowlight + color = MaterialTheme.colors.secondary ) val height = with(LocalDensity.current) { 46.sp.toDp() } Text(contactConnection.description, Modifier.heightIn(min = height), maxLines = 2, color = if (isInDarkTheme()) MessagePreviewDark else MessagePreviewLight) @@ -45,7 +45,7 @@ fun ContactConnectionView(contactConnection: PendingContactConnection) { ) { Text( ts, - color = HighOrLowlight, + color = MaterialTheme.colors.secondary, style = MaterialTheme.typography.body2, modifier = Modifier.padding(bottom = 5.dp) ) 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 064cb4a66a..936d3d2590 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 @@ -42,7 +42,7 @@ fun ContactRequestView(chatModelIncognito: Boolean, contactRequest: ChatInfo.Con ) { Text( ts, - color = HighOrLowlight, + color = MaterialTheme.colors.secondary, style = MaterialTheme.typography.body2, modifier = Modifier.padding(bottom = 5.dp) ) diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ShareListView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ShareListView.kt index f601e65378..0be8f9b531 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ShareListView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ShareListView.kt @@ -19,8 +19,7 @@ import androidx.compose.ui.text.intl.Locale import androidx.compose.ui.unit.dp import chat.simplex.app.R import chat.simplex.app.model.* -import chat.simplex.app.ui.theme.HighOrLowlight -import chat.simplex.app.ui.theme.Indigo +import chat.simplex.app.ui.theme.* import chat.simplex.app.views.helpers.* import kotlinx.coroutines.flow.MutableStateFlow @@ -36,7 +35,7 @@ fun ShareListView(chatModel: ChatModel, stopped: Boolean) { Column( modifier = Modifier .fillMaxSize() - .background(MaterialTheme.colors.background) + .themedBackground() ) { if (chatModel.chats.isNotEmpty()) { ShareList(chatModel, search = searchInList) @@ -54,7 +53,7 @@ fun ShareListView(chatModel: ChatModel, stopped: Boolean) { @Composable private fun EmptyList() { Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { - Text(stringResource(R.string.you_have_no_chats), color = HighOrLowlight) + Text(stringResource(R.string.you_have_no_chats), color = MaterialTheme.colors.secondary) } } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/UserPicker.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/UserPicker.kt index d073d2d2de..31d6e96efa 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/UserPicker.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/UserPicker.kt @@ -107,7 +107,7 @@ fun UserPicker( .width(IntrinsicSize.Min) .height(IntrinsicSize.Min) .shadow(8.dp, RoundedCornerShape(corner = CornerSize(25.dp)), clip = true) - .background(if (isInDarkTheme()) DarkGrayBackground else MaterialTheme.colors.background, RoundedCornerShape(corner = CornerSize(25.dp))) + .background(MaterialTheme.colors.surface, RoundedCornerShape(corner = CornerSize(25.dp))) .clip(RoundedCornerShape(corner = CornerSize(25.dp))) ) { Column(Modifier.weight(1f).verticalScroll(rememberScrollState())) { @@ -169,7 +169,7 @@ fun UserProfilePickerItem(u: User, unreadCount: Int = 0, padding: PaddingValues if (u.activeUser) { Icon(painterResource(R.drawable.ic_done_filled), null, Modifier.size(20.dp), tint = MaterialTheme.colors.onBackground) } else if (u.hidden) { - Icon(painterResource(R.drawable.ic_lock), null, Modifier.size(20.dp), tint = HighOrLowlight) + Icon(painterResource(R.drawable.ic_lock), null, Modifier.size(20.dp), tint = MaterialTheme.colors.secondary) } else if (unreadCount > 0) { Box( contentAlignment = Alignment.Center @@ -179,13 +179,13 @@ fun UserProfilePickerItem(u: User, unreadCount: Int = 0, padding: PaddingValues color = Color.White, fontSize = 11.sp, modifier = Modifier - .background(if (u.showNtfs) MaterialTheme.colors.primary else HighOrLowlight, shape = CircleShape) + .background(MaterialTheme.colors.primaryVariant, shape = CircleShape) .padding(2.dp) .badgeLayout() ) } } else if (!u.showNtfs) { - Icon(painterResource(R.drawable.ic_notifications_off), null, Modifier.size(20.dp), tint = HighOrLowlight) + Icon(painterResource(R.drawable.ic_notifications_off), null, Modifier.size(20.dp), tint = MaterialTheme.colors.secondary) } else { Box(Modifier.size(20.dp)) } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/database/DatabaseEncryptionView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/database/DatabaseEncryptionView.kt index 5c24e59bd4..8923962bcd 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/database/DatabaseEncryptionView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/database/DatabaseEncryptionView.kt @@ -112,7 +112,7 @@ fun DatabaseEncryptionView(m: ChatModel) { Modifier .padding(horizontal = 2.dp) .size(30.dp), - color = HighOrLowlight, + color = MaterialTheme.colors.secondary, strokeWidth = 2.5.dp ) } @@ -211,7 +211,7 @@ fun DatabaseEncryptionLayout( ) SectionItemViewSpaceBetween(onClickUpdate, disabled = disabled, minHeight = TextFieldDefaults.MinHeight) { - Text(generalGetString(R.string.update_database_passphrase), color = if (disabled) HighOrLowlight else MaterialTheme.colors.primary) + Text(generalGetString(R.string.update_database_passphrase), color = if (disabled) MaterialTheme.colors.secondary else MaterialTheme.colors.primary) } } @@ -292,7 +292,7 @@ fun SavePassphraseSetting( Icon( if (storedKey) painterResource(R.drawable.ic_vpn_key_filled) else painterResource(R.drawable.ic_vpn_key_off_filled), stringResource(R.string.save_passphrase_in_keychain), - tint = if (storedKey) SimplexGreen else HighOrLowlight + tint = if (storedKey) SimplexGreen else MaterialTheme.colors.secondary ) Spacer(Modifier.padding(horizontal = 4.dp)) Text( @@ -360,7 +360,7 @@ fun PassphraseField( if (showKey) painterResource(R.drawable.ic_visibility_off_filled) else painterResource(R.drawable.ic_visibility_filled) } else painterResource(R.drawable.ic_error) val iconColor = if (valid) { - if (showStrength && key.value.isNotEmpty()) PassphraseStrength.check(key.value).color else HighOrLowlight + if (showStrength && key.value.isNotEmpty()) PassphraseStrength.check(key.value).color else MaterialTheme.colors.secondary } else Color.Red val keyboard = LocalSoftwareKeyboardController.current val keyboardOptions = KeyboardOptions( @@ -417,7 +417,7 @@ fun PassphraseField( TextFieldDefaults.TextFieldDecorationBox( value = state.value.text, innerTextField = innerTextField, - placeholder = { Text(placeholder, color = HighOrLowlight) }, + placeholder = { Text(placeholder, color = MaterialTheme.colors.secondary) }, singleLine = true, enabled = enabled, isError = !valid, diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/database/DatabaseErrorView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/database/DatabaseErrorView.kt index 410bdea630..c1aa1fe5a6 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/database/DatabaseErrorView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/database/DatabaseErrorView.kt @@ -180,7 +180,7 @@ fun DatabaseErrorView( Modifier .padding(horizontal = 2.dp) .size(30.dp), - color = HighOrLowlight, + color = MaterialTheme.colors.secondary, strokeWidth = 2.5.dp ) } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/database/DatabaseView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/database/DatabaseView.kt index 5feaa4bdff..2a74524b3c 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/database/DatabaseView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/database/DatabaseView.kt @@ -114,7 +114,7 @@ fun DatabaseView( Modifier .padding(horizontal = 2.dp) .size(30.dp), - color = HighOrLowlight, + color = MaterialTheme.colors.secondary, strokeWidth = 2.5.dp ) } @@ -185,7 +185,7 @@ fun DatabaseLayout( .drawable.ic_lock), stringResource(R.string.database_passphrase), click = showSettingsModal() { DatabaseEncryptionView(it) }, - iconColor = if (unencrypted) WarningOrange else HighOrLowlight, + iconColor = if (unencrypted) WarningOrange else MaterialTheme.colors.secondary, disabled = operationsDisabled ) AppDataBackupPreference(privacyFullBackup, initialRandomDBPassphrase) @@ -250,7 +250,7 @@ fun DatabaseLayout( ) { Text( stringResource(if (users.size > 1) R.string.delete_files_and_media_for_all_users else R.string.delete_files_and_media_all), - color = if (deleteFilesDisabled) HighOrLowlight else Color.Red + color = if (deleteFilesDisabled) MaterialTheme.colors.secondary else Color.Red ) } } @@ -270,7 +270,7 @@ fun DatabaseLayout( private fun AppDataBackupPreference(privacyFullBackup: SharedPreference, initialRandomDBPassphrase: SharedPreference) { SettingsPreferenceItem( painterResource(R.drawable.ic_backup), - iconColor = HighOrLowlight, + iconColor = MaterialTheme.colors.secondary, pref = privacyFullBackup, text = stringResource(R.string.full_backup) ) { 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 b12957f8d1..f4895c22ce 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 @@ -37,7 +37,6 @@ class AlertManager { ) { showAlert { AlertDialog( - backgroundColor = if (isInDarkTheme()) DarkGrayBackground else MaterialTheme.colors.background, onDismissRequest = this::hideAlert, title = alertTitle(title), text = alertText(text), @@ -56,7 +55,7 @@ class AlertManager { Dialog(onDismissRequest = this::hideAlert) { Column( Modifier - .background(if (isInDarkTheme()) DarkGrayBackground else MaterialTheme.colors.background, RoundedCornerShape(corner = CornerSize(25.dp))) + .background(MaterialTheme.colors.surface, RoundedCornerShape(corner = CornerSize(25.dp))) .padding(bottom = DEFAULT_PADDING) ) { Text( @@ -67,7 +66,7 @@ class AlertManager { ) CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.high) { if (text != null) { - Text(text, Modifier.fillMaxWidth().padding(start = DEFAULT_PADDING, end = DEFAULT_PADDING, bottom = DEFAULT_PADDING * 1.5f), fontSize = 16.sp, textAlign = TextAlign.Center, color = HighOrLowlight) + Text(text, Modifier.fillMaxWidth().padding(start = DEFAULT_PADDING, end = DEFAULT_PADDING, bottom = DEFAULT_PADDING * 1.5f), fontSize = 16.sp, textAlign = TextAlign.Center, color = MaterialTheme.colors.secondary) } buttons() } @@ -106,7 +105,6 @@ class AlertManager { }) { Text(confirmText, color = if (destructive) MaterialTheme.colors.error else Color.Unspecified) } } }, - backgroundColor = if (isInDarkTheme()) DarkGrayBackground else MaterialTheme.colors.background, shape = RoundedCornerShape(corner = CornerSize(25.dp)) ) } @@ -142,7 +140,6 @@ class AlertManager { }) { Text(confirmText, color = if (destructive) Color.Red else Color.Unspecified, textAlign = TextAlign.End) } } }, - backgroundColor = if (isInDarkTheme()) DarkGrayBackground else MaterialTheme.colors.background, shape = RoundedCornerShape(corner = CornerSize(25.dp)) ) } @@ -167,7 +164,6 @@ class AlertManager { }) { Text(confirmText, color = Color.Unspecified) } } }, - backgroundColor = if (isInDarkTheme()) DarkGrayBackground else MaterialTheme.colors.background, shape = RoundedCornerShape(corner = CornerSize(25.dp)) ) } @@ -209,7 +205,7 @@ private fun alertText(text: String?): (@Composable () -> Unit)? { Modifier.fillMaxWidth(), textAlign = TextAlign.Center, fontSize = 16.sp, - color = HighOrLowlight + color = MaterialTheme.colors.secondary ) }) } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/ChatInfoImage.kt b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/ChatInfoImage.kt index 04d2744484..d8463d94a7 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/ChatInfoImage.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/ChatInfoImage.kt @@ -20,7 +20,7 @@ import chat.simplex.app.model.ChatInfo import chat.simplex.app.ui.theme.SimpleXTheme @Composable -fun ChatInfoImage(chatInfo: ChatInfo, size: Dp, iconColor: Color = MaterialTheme.colors.secondary) { +fun ChatInfoImage(chatInfo: ChatInfo, size: Dp, iconColor: Color = MaterialTheme.colors.secondaryVariant) { val icon = if (chatInfo is ChatInfo.Group) R.drawable.ic_supervised_user_circle_filled else R.drawable.ic_account_circle_filled @@ -28,7 +28,7 @@ fun ChatInfoImage(chatInfo: ChatInfo, size: Dp, iconColor: Color = MaterialTheme } @Composable -fun IncognitoImage(size: Dp, iconColor: Color = MaterialTheme.colors.secondary) { +fun IncognitoImage(size: Dp, iconColor: Color = MaterialTheme.colors.secondaryVariant) { Box(Modifier.size(size)) { Icon( painterResource(R.drawable.ic_theater_comedy_filled), stringResource(R.string.incognito), @@ -43,7 +43,7 @@ fun ProfileImage( size: Dp, image: String? = null, icon: Int = R.drawable.ic_account_circle_filled, - color: Color = MaterialTheme.colors.secondary + color: Color = MaterialTheme.colors.secondaryVariant ) { Box(Modifier.size(size)) { if (image == null) { diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/CloseSheetBar.kt b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/CloseSheetBar.kt index 1c9cb170d0..6ee9b62a05 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/CloseSheetBar.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/CloseSheetBar.kt @@ -3,9 +3,12 @@ package chat.simplex.app.views.helpers import android.content.res.Configuration import androidx.compose.foundation.layout.* import androidx.compose.material.* -import androidx.compose.runtime.Composable +import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview @@ -41,14 +44,20 @@ fun CloseSheetBar(close: (() -> Unit)?, endButtons: @Composable RowScope.() -> U @Composable fun AppBarTitle(title: String, withPadding: Boolean = true) { + val theme = CurrentColors.collectAsState() + val titleColor = CurrentColors.collectAsState().value.appColors.title + val brush = if (theme.value.base == DefaultTheme.SIMPLEX) + Brush.linearGradient(listOf(titleColor.darker(0.2f), titleColor.lighter(0.35f)), Offset(0f, Float.POSITIVE_INFINITY), Offset(Float.POSITIVE_INFINITY, 0f)) + else // color is not updated when changing themes if I pass null here + Brush.linearGradient(listOf(titleColor, titleColor), Offset(0f, Float.POSITIVE_INFINITY), Offset(Float.POSITIVE_INFINITY, 0f)) Text( title, Modifier .fillMaxWidth() .padding(bottom = DEFAULT_PADDING * 1.5f, start = if (withPadding) DEFAULT_PADDING else 0.dp, end = if (withPadding) DEFAULT_PADDING else 0.dp,), overflow = TextOverflow.Ellipsis, - style = MaterialTheme.typography.h1, - color = MaterialTheme.colors.primary, + style = MaterialTheme.typography.h1.copy(brush = brush), + color = MaterialTheme.colors.primaryVariant, textAlign = TextAlign.Center ) } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/DefaultBasicTextField.kt b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/DefaultBasicTextField.kt index e3d4048cfa..2ea147014f 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/DefaultBasicTextField.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/DefaultBasicTextField.kt @@ -22,7 +22,6 @@ import androidx.compose.ui.text.input.* import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import chat.simplex.app.R -import chat.simplex.app.ui.theme.HighOrLowlight import chat.simplex.app.views.database.PassphraseStrength import chat.simplex.app.views.database.validKey import kotlinx.coroutines.delay @@ -137,7 +136,7 @@ fun DefaultConfigurableTextField( if (showKey) painterResource(R.drawable.ic_visibility_off_filled) else painterResource(R.drawable.ic_visibility_filled) } else painterResource(R.drawable.ic_error) val iconColor = if (valid) { - if (showPasswordStrength && state.value.text.isNotEmpty()) PassphraseStrength.check(state.value.text).color else HighOrLowlight + if (showPasswordStrength && state.value.text.isNotEmpty()) PassphraseStrength.check(state.value.text).color else MaterialTheme.colors.secondary } else Color.Red val keyboard = LocalSoftwareKeyboardController.current val keyboardOptions = KeyboardOptions( @@ -189,7 +188,7 @@ fun DefaultConfigurableTextField( TextFieldDefaults.TextFieldDecorationBox( value = state.value.text, innerTextField = innerTextField, - placeholder = { Text(placeholder, color = HighOrLowlight) }, + placeholder = { Text(placeholder, color = MaterialTheme.colors.secondary) }, singleLine = true, enabled = enabled, isError = !valid, diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/DefaultDropdownMenu.kt b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/DefaultDropdownMenu.kt index e6ec87e14d..71af738bda 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/DefaultDropdownMenu.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/DefaultDropdownMenu.kt @@ -1,5 +1,6 @@ package chat.simplex.app.views.helpers +import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.CornerSize import androidx.compose.foundation.shape.RoundedCornerShape @@ -19,7 +20,6 @@ fun DefaultDropdownMenu( dropdownMenuItems: (@Composable () -> Unit)? ) { MaterialTheme( - colors = MaterialTheme.colors.copy(surface = if (isInDarkTheme()) Color(0xFF0B0B0B) else MaterialTheme.colors.background), shapes = MaterialTheme.shapes.copy(medium = RoundedCornerShape(corner = CornerSize(25.dp))) ) { DropdownMenu( @@ -27,6 +27,7 @@ fun DefaultDropdownMenu( onDismissRequest = { showMenu.value = false }, Modifier .widthIn(min = 250.dp) + .background(MaterialTheme.colors.surface) .padding(vertical = 4.dp), offset = offset, ) { @@ -42,11 +43,13 @@ fun ExposedDropdownMenuBoxScope.DefaultExposedDropdownMenu( dropdownMenuItems: (@Composable () -> Unit)? ) { MaterialTheme( - colors = MaterialTheme.colors.copy(surface = if (isInDarkTheme()) Color(0xFF080808) else MaterialTheme.colors.background), shapes = MaterialTheme.shapes.copy(medium = RoundedCornerShape(corner = CornerSize(25.dp))) ) { ExposedDropdownMenu( - modifier = Modifier.widthIn(min = 200.dp).then(modifier), + modifier = Modifier + .widthIn(min = 200.dp) + .background(MaterialTheme.colors.surface) + .then(modifier), expanded = expanded.value, onDismissRequest = { expanded.value = false diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/DefaultSwitch.kt b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/DefaultSwitch.kt index 251cb8df30..613caed54d 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/DefaultSwitch.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/DefaultSwitch.kt @@ -9,7 +9,6 @@ import androidx.compose.ui.draw.drawBehind import androidx.compose.ui.geometry.* import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.unit.dp -import chat.simplex.app.ui.theme.HighOrLowlight @Composable fun DefaultSwitch( @@ -20,12 +19,12 @@ fun DefaultSwitch( interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, colors: SwitchColors = SwitchDefaults.colors( checkedThumbColor = MaterialTheme.colors.primary, - uncheckedThumbColor = HighOrLowlight, + uncheckedThumbColor = MaterialTheme.colors.secondary, checkedTrackAlpha = 0.0f, uncheckedTrackAlpha = 0.0f, ) ) { - val color = if (checked) MaterialTheme.colors.primary.copy(alpha = 0.3f) else HighOrLowlight.copy(alpha = 0.3f) + val color = if (checked) MaterialTheme.colors.primary.copy(alpha = 0.3f) else MaterialTheme.colors.secondary.copy(alpha = 0.3f) val size = with(LocalDensity.current) { Size(46.dp.toPx(), 28.dp.toPx()) } val offset = with(LocalDensity.current) { Offset(1.dp.toPx(), 10.dp.toPx()) } val radius = with(LocalDensity.current) { 28.dp.toPx() } 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 225dd393ba..9896b0302e 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 @@ -47,7 +47,7 @@ fun DefaultTopAppBar( fun NavigationButtonBack(onButtonClicked: (() -> Unit)?) { IconButton(onButtonClicked ?: {}, enabled = onButtonClicked != null) { Icon( - painterResource(R.drawable.ic_arrow_back_ios_new), stringResource(R.string.back), tint = if (onButtonClicked != null) MaterialTheme.colors.primary else HighOrLowlight + painterResource(R.drawable.ic_arrow_back_ios_new), stringResource(R.string.back), tint = if (onButtonClicked != null) MaterialTheme.colors.primary else MaterialTheme.colors.secondary ) } } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/ExposedDropDownSettingRow.kt b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/ExposedDropDownSettingRow.kt index 7fa87a482c..b39b36e365 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/ExposedDropDownSettingRow.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/ExposedDropDownSettingRow.kt @@ -23,7 +23,7 @@ fun ExposedDropDownSettingRow( selection: State, label: String? = null, icon: Painter? = null, - iconTint: Color = HighOrLowlight, + iconTint: Color = MaterialTheme.colors.secondary, enabled: State = mutableStateOf(true), onSelected: (T) -> Unit ) { @@ -46,13 +46,13 @@ fun ExposedDropDownSettingRow( Modifier.widthIn(max = maxWidth), maxLines = 1, overflow = TextOverflow.Ellipsis, - color = HighOrLowlight + color = MaterialTheme.colors.secondary ) Spacer(Modifier.size(12.dp)) Icon( if (!expanded.value) painterResource(R.drawable.ic_expand_more) else painterResource(R.drawable.ic_expand_less), generalGetString(R.string.icon_descr_more_button), - tint = HighOrLowlight + tint = MaterialTheme.colors.secondary ) } DefaultExposedDropdownMenu( diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/LinkPreviews.kt b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/LinkPreviews.kt index 7624665036..f6c749b554 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/LinkPreviews.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/LinkPreviews.kt @@ -7,6 +7,7 @@ import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.material.* import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.asImageBitmap @@ -19,9 +20,7 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import chat.simplex.app.R import chat.simplex.app.model.LinkPreview -import chat.simplex.app.ui.theme.HighOrLowlight -import chat.simplex.app.ui.theme.SimpleXTheme -import chat.simplex.app.views.chat.item.SentColorLight +import chat.simplex.app.ui.theme.* import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import org.jsoup.Jsoup @@ -79,8 +78,9 @@ suspend fun getLinkPreview(url: String): LinkPreview? { @Composable fun ComposeLinkView(linkPreview: LinkPreview?, cancelPreview: () -> Unit) { + val sentColor = CurrentColors.collectAsState().value.appColors.sentMessage Row( - Modifier.fillMaxWidth().padding(top = 8.dp).background(SentColorLight), + Modifier.fillMaxWidth().padding(top = 8.dp).background(sentColor), verticalAlignment = Alignment.CenterVertically ) { if (linkPreview == null) { @@ -90,7 +90,7 @@ fun ComposeLinkView(linkPreview: LinkPreview?, cancelPreview: () -> Unit) { ) { CircularProgressIndicator( Modifier.size(16.dp), - color = HighOrLowlight, + color = MaterialTheme.colors.secondary, strokeWidth = 2.dp ) } @@ -134,7 +134,7 @@ fun ChatItemLinkView(linkPreview: LinkPreview) { if (linkPreview.description != "") { Text(linkPreview.description, maxLines = 12, overflow = TextOverflow.Ellipsis, fontSize = 14.sp, lineHeight = 20.sp) } - Text(linkPreview.uri, maxLines = 1, overflow = TextOverflow.Ellipsis, fontSize = 12.sp, color = HighOrLowlight) + Text(linkPreview.uri, maxLines = 1, overflow = TextOverflow.Ellipsis, fontSize = 12.sp, color = MaterialTheme.colors.secondary) } } } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/ModalView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/ModalView.kt index 7e834806a1..3ba958a540 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/ModalView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/ModalView.kt @@ -12,6 +12,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import chat.simplex.app.TAG import chat.simplex.app.ui.theme.isInDarkTheme +import chat.simplex.app.ui.theme.themedBackground import java.util.concurrent.atomic.AtomicBoolean @Composable @@ -24,7 +25,7 @@ fun ModalView( ) { BackHandler(onBack = close) Surface(Modifier.fillMaxSize()) { - Column(Modifier.background(background)) { + Column(if (background != MaterialTheme.colors.background) Modifier.background(background) else Modifier.themedBackground()) { CloseSheetBar(close, endButtons) Box(modifier) { content() } } 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 2a50888e8e..38b00dadee 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 @@ -25,7 +25,7 @@ fun SectionView(title: String? = null, padding: PaddingValues = PaddingValues(), Column { if (title != null) { Text( - title, color = HighOrLowlight, style = MaterialTheme.typography.body2, + title, color = MaterialTheme.colors.secondary, style = MaterialTheme.typography.body2, modifier = Modifier.padding(start = DEFAULT_PADDING, bottom = 5.dp), fontSize = 12.sp ) } @@ -37,7 +37,7 @@ fun SectionView(title: String? = null, padding: PaddingValues = PaddingValues(), fun SectionView( title: String, icon: Painter, - iconTint: Color = HighOrLowlight, + iconTint: Color = MaterialTheme.colors.secondary, leadingIcon: Boolean = false, padding: PaddingValues = PaddingValues(), content: (@Composable ColumnScope.() -> Unit) @@ -46,7 +46,7 @@ fun SectionView( val iconSize = with(LocalDensity.current) { 21.sp.toDp() } Row(Modifier.padding(start = DEFAULT_PADDING, bottom = 5.dp), verticalAlignment = Alignment.CenterVertically) { if (leadingIcon) Icon(icon, null, Modifier.padding(end = DEFAULT_PADDING_HALF).size(iconSize), tint = iconTint) - Text(title, color = HighOrLowlight, style = MaterialTheme.typography.body2, fontSize = 12.sp) + Text(title, color = MaterialTheme.colors.secondary, style = MaterialTheme.typography.body2, fontSize = 12.sp) if (!leadingIcon) Icon(icon, null, Modifier.padding(start = DEFAULT_PADDING_HALF).size(iconSize), tint = iconTint) } Column(Modifier.padding(padding).fillMaxWidth()) { content() } @@ -147,7 +147,7 @@ fun SectionItemWithValue( values: List>, label: String? = null, icon: Painter? = null, - iconTint: Color = HighOrLowlight, + iconTint: Color = MaterialTheme.colors.secondary, enabled: State = mutableStateOf(true), onSelected: () -> Unit ) { @@ -161,7 +161,7 @@ fun SectionItemWithValue( values.first { it.value == currentValue.value }.title + (if (label != null) " $label" else ""), maxLines = 1, overflow = TextOverflow.Ellipsis, - color = HighOrLowlight + color = MaterialTheme.colors.secondary ) } } @@ -177,7 +177,7 @@ fun SectionTextFooter(text: AnnotatedString) { Text( text, Modifier.padding(start = DEFAULT_PADDING, end = DEFAULT_PADDING, top = DEFAULT_PADDING_HALF).fillMaxWidth(0.9F), - color = HighOrLowlight, + color = MaterialTheme.colors.secondary, lineHeight = 18.sp, fontSize = 14.sp ) @@ -228,10 +228,10 @@ fun InfoRow(title: String, value: String, icon: Painter? = null, iconTint: Color SectionItemViewSpaceBetween { Row { val iconSize = with(LocalDensity.current) { 21.sp.toDp() } - if (icon != null) Icon(icon, title, Modifier.padding(end = 8.dp).size(iconSize), tint = iconTint ?: HighOrLowlight) + if (icon != null) Icon(icon, title, Modifier.padding(end = 8.dp).size(iconSize), tint = iconTint ?: MaterialTheme.colors.secondary) Text(title) } - Text(value, color = HighOrLowlight) + Text(value, color = MaterialTheme.colors.secondary) } } @@ -247,7 +247,7 @@ fun InfoRowEllipsis(title: String, value: String, onClick: () -> Unit) { .widthIn(max = (configuration.screenWidthDp / 2).dp), maxLines = 1, overflow = TextOverflow.Ellipsis, - color = HighOrLowlight + color = MaterialTheme.colors.secondary ) } } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/SimpleButton.kt b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/SimpleButton.kt index 9f32850e95..779f51d9e3 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/SimpleButton.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/SimpleButton.kt @@ -1,14 +1,15 @@ package chat.simplex.app.ui.theme +import androidx.compose.foundation.background import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.* import androidx.compose.ui.res.painterResource import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.text.font.FontWeight @@ -54,10 +55,10 @@ fun SimpleButton( ) { SimpleButtonFrame(click, disabled = disabled) { Icon( - icon, text, tint = if (disabled) HighOrLowlight else color, + icon, text, tint = if (disabled) MaterialTheme.colors.secondary else color, modifier = Modifier.padding(end = 8.dp) ) - Text(text, style = MaterialTheme.typography.caption, color = if (disabled) HighOrLowlight else color) + Text(text, style = MaterialTheme.typography.caption, color = if (disabled) MaterialTheme.colors.secondary else color) } } @@ -79,7 +80,7 @@ fun SimpleButtonIconEnded( @Composable fun SimpleButtonFrame(click: () -> Unit, modifier: Modifier = Modifier, disabled: Boolean = false, content: @Composable () -> Unit) { - Surface(shape = RoundedCornerShape(20.dp)) { + Box(Modifier.clip(RoundedCornerShape(20.dp))) { val modifier = if (disabled) modifier else modifier.clickable { click() } Row( verticalAlignment = Alignment.CenterVertically, diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/TextEditor.kt b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/TextEditor.kt index 71f9874eed..e00f9ba454 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/TextEditor.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/TextEditor.kt @@ -18,7 +18,6 @@ import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.input.KeyboardCapitalization import androidx.compose.ui.unit.* import chat.simplex.app.ui.theme.DEFAULT_PADDING -import chat.simplex.app.ui.theme.HighOrLowlight @Composable fun TextEditor( @@ -41,11 +40,11 @@ fun TextEditor( autoCorrect = false ), modifier = modifier, - cursorBrush = SolidColor(HighOrLowlight), + cursorBrush = SolidColor(MaterialTheme.colors.secondary), decorationBox = { innerTextField -> Surface( shape = if (border) RoundedCornerShape(10.dp) else RectangleShape, - border = if (border) BorderStroke(1.dp, MaterialTheme.colors.secondary) else null + border = if (border) BorderStroke(1.dp, MaterialTheme.colors.secondaryVariant) else null ) { Row( Modifier.background(background), diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/Util.kt b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/Util.kt index 0a274d20b9..39f7d88932 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/Util.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/Util.kt @@ -37,6 +37,8 @@ import androidx.core.text.HtmlCompat import chat.simplex.app.* import chat.simplex.app.R import chat.simplex.app.model.* +import chat.simplex.app.ui.theme.ThemeOverrides +import com.charleskorn.kaml.decodeFromStream import kotlinx.coroutines.* import kotlinx.serialization.decodeFromString import kotlinx.serialization.encodeToString @@ -388,6 +390,22 @@ fun getDrawableFromUri(uri: Uri, withAlertOnException: Boolean = true): Drawable } } +fun getThemeFromUri(uri: Uri, withAlertOnException: Boolean = true): ThemeOverrides? { + SimplexApp.context.contentResolver.openInputStream(uri).use { + runCatching { + return yaml.decodeFromStream(it!!) + }.onFailure { + if (withAlertOnException) { + AlertManager.shared.showAlertMsg( + title = generalGetString(R.string.import_theme_error), + text = generalGetString(R.string.import_theme_error_desc), + ) + } + } + } + return null +} + fun saveImage(context: Context, uri: Uri): String? { val bitmap = getBitmapFromUri(uri) ?: return null return saveImage(context, bitmap) @@ -566,6 +584,9 @@ fun getBitmapFromVideo(uri: Uri, timestamp: Long? = null, random: Boolean = true fun Color.darker(factor: Float = 0.1f): Color = Color(max(red * (1 - factor), 0f), max(green * (1 - factor), 0f), max(blue * (1 - factor), 0f), alpha) +fun Color.lighter(factor: Float = 0.1f): Color = + Color(min(red * (1 + factor), 1f), min(green * (1 + factor), 1f), min(blue * (1 + factor), 1f), alpha) + fun ByteArray.toBase64String() = Base64.encodeToString(this, Base64.DEFAULT) fun String.toByteArrayFromBase64() = Base64.decode(this, Base64.DEFAULT) diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/localauth/PasswordEntry.kt b/apps/android/app/src/main/java/chat/simplex/app/views/localauth/PasswordEntry.kt index 20ee2fbcde..0f6f063082 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/localauth/PasswordEntry.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/localauth/PasswordEntry.kt @@ -17,7 +17,6 @@ import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.* -import chat.simplex.app.ui.theme.HighOrLowlight @Composable fun PasscodeEntry( @@ -129,7 +128,7 @@ private fun PasswordDigit(size: Dp, d: Int, password: MutableState) { fontSize = 30.sp, letterSpacing = (-0.5).sp ), - color = HighOrLowlight + color = MaterialTheme.colors.secondary ) } } @@ -137,7 +136,7 @@ private fun PasswordDigit(size: Dp, d: Int, password: MutableState) { @Composable private fun PasswordEdit(size: Dp, image: Painter, action: () -> Unit) { PasswordButton(size, action) { - Icon(image, null, tint = HighOrLowlight) + Icon(image, null, tint = MaterialTheme.colors.secondary) } } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/newchat/AddContactView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/newchat/AddContactView.kt index b307ea62d9..5ad769adb6 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/newchat/AddContactView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/newchat/AddContactView.kt @@ -63,7 +63,7 @@ fun AddContactLayout(connReq: String, connIncognito: Boolean, share: () -> Unit) .size(36.dp) .padding(4.dp) .align(Alignment.CenterHorizontally), - color = HighOrLowlight, + color = MaterialTheme.colors.secondary, strokeWidth = 3.dp ) } @@ -113,7 +113,7 @@ fun InfoAboutIncognito(chatModelIncognito: Boolean, supportedIncognito: Boolean Icon( painterResource(R.drawable.ic_info), stringResource(R.string.incognito), - tint = HighOrLowlight, + tint = MaterialTheme.colors.secondary, modifier = Modifier.padding(end = 10.dp).size(20.dp) ) Text(offText, textAlign = if (centered) TextAlign.Center else TextAlign.Left, style = MaterialTheme.typography.body2) 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 d8acc440bf..a570ca3411 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 @@ -141,7 +141,7 @@ fun AddGroupLayout(createGroup: (GroupProfile) -> Unit, close: () -> Unit) { } .padding(8.dp)) } else { - CreateGroupButton(HighOrLowlight, Modifier.padding(8.dp)) + CreateGroupButton(MaterialTheme.colors.secondary, Modifier.padding(8.dp)) } LaunchedEffect(Unit) { delay(300) diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/newchat/ConnectViaLinkView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/newchat/ConnectViaLinkView.kt index ba9c8fc25d..18a149eb52 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/newchat/ConnectViaLinkView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/newchat/ConnectViaLinkView.kt @@ -4,12 +4,12 @@ import androidx.compose.foundation.layout.* import androidx.compose.material.* import androidx.compose.runtime.* import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.sp import chat.simplex.app.R import chat.simplex.app.model.ChatModel -import chat.simplex.app.ui.theme.HighOrLowlight enum class ConnectViaLinkTab { SCAN, PASTE @@ -44,7 +44,7 @@ fun ConnectViaLinkView(m: ChatModel, close: () -> Unit) { } TabRow( selectedTabIndex = selection.value.ordinal, - backgroundColor = MaterialTheme.colors.background, + backgroundColor = Color.Transparent, contentColor = MaterialTheme.colors.primary, ) { tabTitles.forEachIndexed { index, it -> @@ -62,7 +62,7 @@ fun ConnectViaLinkView(m: ChatModel, close: () -> Unit) { ) }, selectedContentColor = MaterialTheme.colors.primary, - unselectedContentColor = HighOrLowlight, + unselectedContentColor = MaterialTheme.colors.secondary, ) } } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/newchat/CreateLinkView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/newchat/CreateLinkView.kt index 6e4c6849d4..90e58a6986 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/newchat/CreateLinkView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/newchat/CreateLinkView.kt @@ -5,13 +5,13 @@ import androidx.compose.material.* import androidx.compose.runtime.* import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.sp import chat.simplex.app.R import chat.simplex.app.model.ChatModel import chat.simplex.app.ui.theme.DEFAULT_PADDING -import chat.simplex.app.ui.theme.HighOrLowlight import chat.simplex.app.views.helpers.ModalManager import chat.simplex.app.views.helpers.withApi import chat.simplex.app.views.usersettings.UserAddressView @@ -67,7 +67,7 @@ fun CreateLinkView(m: ChatModel, initialSelection: CreateLinkTab) { } TabRow( selectedTabIndex = selection.value.ordinal, - backgroundColor = MaterialTheme.colors.background, + backgroundColor = Color.Transparent, contentColor = MaterialTheme.colors.primary, ) { tabTitles.forEachIndexed { index, it -> @@ -84,7 +84,7 @@ fun CreateLinkView(m: ChatModel, initialSelection: CreateLinkTab) { ) }, selectedContentColor = MaterialTheme.colors.primary, - unselectedContentColor = HighOrLowlight, + unselectedContentColor = MaterialTheme.colors.secondary, ) } } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/newchat/NewChatSheet.kt b/apps/android/app/src/main/java/chat/simplex/app/views/newchat/NewChatSheet.kt index c0214eb3cb..5224a3ab40 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/newchat/NewChatSheet.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/newchat/NewChatSheet.kt @@ -150,7 +150,7 @@ private fun NewChatSheetLayout( hoveredElevation = 0.dp, focusedElevation = 0.dp, ), - backgroundColor = if (!stopped) MaterialTheme.colors.primary else HighOrLowlight, + backgroundColor = if (!stopped) MaterialTheme.colors.primary else MaterialTheme.colors.secondary, contentColor = Color.White ) { Icon( @@ -180,7 +180,7 @@ fun ActionButton( .padding(8.dp), horizontalAlignment = Alignment.CenterHorizontally ) { - val tint = if (disabled) HighOrLowlight else MaterialTheme.colors.primary + val tint = if (disabled) MaterialTheme.colors.secondary else MaterialTheme.colors.primary Icon( icon, text, tint = tint, @@ -226,7 +226,7 @@ fun ActionButton( .padding(8.dp), horizontalAlignment = Alignment.CenterHorizontally ) { - val tint = if (disabled) HighOrLowlight else tint + val tint = if (disabled) MaterialTheme.colors.secondary else tint Icon( icon, text, tint = tint, diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/onboarding/SetNotificationsMode.kt b/apps/android/app/src/main/java/chat/simplex/app/views/onboarding/SetNotificationsMode.kt index 774a962c42..a0d2c66b11 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/onboarding/SetNotificationsMode.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/onboarding/SetNotificationsMode.kt @@ -53,7 +53,7 @@ fun SetNotificationsMode(m: ChatModel) { private fun NotificationButton(currentMode: MutableState, mode: NotificationsMode, @StringRes title: Int, @StringRes description: Int) { TextButton( onClick = { currentMode.value = mode }, - border = BorderStroke(1.dp, color = if (currentMode.value == mode) MaterialTheme.colors.primary else HighOrLowlight.copy(alpha = 0.5f)), + border = BorderStroke(1.dp, color = if (currentMode.value == mode) MaterialTheme.colors.primary else MaterialTheme.colors.secondary.copy(alpha = 0.5f)), shape = RoundedCornerShape(35.dp), ) { Column(Modifier.padding(horizontal = 14.dp).padding(top = 4.dp, bottom = 8.dp)) { @@ -61,7 +61,7 @@ private fun NotificationButton(currentMode: MutableState, mod stringResource(title), style = MaterialTheme.typography.h2, fontWeight = FontWeight.Medium, - color = if (currentMode.value == mode) MaterialTheme.colors.primary else HighOrLowlight, + color = if (currentMode.value == mode) MaterialTheme.colors.primary else MaterialTheme.colors.secondary, modifier = Modifier.padding(bottom = 8.dp).align(Alignment.CenterHorizontally), textAlign = TextAlign.Center ) diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/onboarding/WhatsNewView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/onboarding/WhatsNewView.kt index a3acb2e34b..1e7c8d6b22 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/onboarding/WhatsNewView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/onboarding/WhatsNewView.kt @@ -1,6 +1,7 @@ package chat.simplex.app.views.onboarding import android.content.res.Configuration +import android.os.Build import androidx.annotation.IntegerRes import androidx.compose.foundation.* import androidx.compose.foundation.layout.* @@ -9,6 +10,7 @@ import androidx.compose.material.* import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.platform.LocalUriHandler import androidx.compose.ui.res.painterResource @@ -18,6 +20,7 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import chat.simplex.app.BuildConfig import chat.simplex.app.R import chat.simplex.app.model.ChatModel import chat.simplex.app.ui.theme.* @@ -47,7 +50,7 @@ fun WhatsNewView(viaSettings: Boolean = false, close: () -> Unit) { horizontalArrangement = Arrangement.spacedBy(8.dp), modifier = Modifier.padding(bottom = 4.dp) ) { - Icon(icon, stringResource(titleId), tint = HighOrLowlight) + Icon(icon, stringResource(titleId), tint = MaterialTheme.colors.secondary) Text( generalGetString(titleId), maxLines = 1, @@ -71,7 +74,7 @@ fun WhatsNewView(viaSettings: Boolean = false, close: () -> Unit) { ) { if (currentVersion.value > 0) { val prev = currentVersion.value - 1 - Surface(shape = RoundedCornerShape(20.dp)) { + Box(Modifier.clip(RoundedCornerShape(20.dp))) { Row( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(8.dp), @@ -87,7 +90,7 @@ fun WhatsNewView(viaSettings: Boolean = false, close: () -> Unit) { Spacer(Modifier.fillMaxWidth().weight(1f)) if (currentVersion.value < versionDescriptions.lastIndex) { val next = currentVersion.value + 1 - Surface(shape = RoundedCornerShape(20.dp)) { + Box(Modifier.clip(RoundedCornerShape(20.dp))) { Row( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(8.dp), @@ -113,17 +116,7 @@ fun WhatsNewView(viaSettings: Boolean = false, close: () -> Unit) { .verticalScroll(rememberScrollState()), verticalArrangement = Arrangement.spacedBy(DEFAULT_PADDING) ) { - Text( - String.format(generalGetString(R.string.new_in_version), v.version), - Modifier - .fillMaxWidth() - .padding(DEFAULT_PADDING), - textAlign = TextAlign.Center, - overflow = TextOverflow.Ellipsis, - style = MaterialTheme.typography.h1, - fontWeight = FontWeight.Normal, - color = HighOrLowlight - ) + AppBarTitle(String.format(generalGetString(R.string.new_in_version), v.version)) v.features.forEach { feature -> featureDescription(painterResource(feature.icon), feature.titleId, feature.descrId, feature.link) diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/AcceptRequestsView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/AcceptRequestsView.kt index 4c5ff2fd85..c383370042 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/AcceptRequestsView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/AcceptRequestsView.kt @@ -60,7 +60,7 @@ private fun AcceptRequestsLayout( PreferenceToggleWithIcon( stringResource(R.string.incognito), if (autoAcceptState.value.incognito) painterResource(R.drawable.ic_theater_comedy_filled) else painterResource(R.drawable.ic_theater_comedy), - if (autoAcceptState.value.incognito) Indigo else HighOrLowlight, + if (autoAcceptState.value.incognito) Indigo else MaterialTheme.colors.secondary, autoAcceptState.value.incognito, ) { autoAcceptState.value = AutoAcceptState(autoAcceptState.value.enable, it, autoAcceptState.value.welcomeText) @@ -81,7 +81,7 @@ private fun AcceptRequestsLayout( Spacer(Modifier.height(DEFAULT_PADDING)) if (autoAcceptState.value.enable) { Text( - stringResource(R.string.section_title_welcome_message), color = HighOrLowlight, style = MaterialTheme.typography.body2, + stringResource(R.string.section_title_welcome_message), color = MaterialTheme.colors.secondary, style = MaterialTheme.typography.body2, modifier = Modifier.padding(start = DEFAULT_PADDING, bottom = 5.dp), fontSize = 12.sp ) TextEditor(Modifier.padding(horizontal = DEFAULT_PADDING).height(160.dp), text = welcomeText) diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/AdvancedNetworkSettings.kt b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/AdvancedNetworkSettings.kt index fe1f29802d..044260ac83 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/AdvancedNetworkSettings.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/AdvancedNetworkSettings.kt @@ -184,13 +184,13 @@ fun AdvancedNetworkSettingsView(chatModel: ChatModel) { } } else { SectionItemView { - Text("TCP_KEEPIDLE", color = HighOrLowlight) + Text("TCP_KEEPIDLE", color = MaterialTheme.colors.secondary) } SectionItemView { - Text("TCP_KEEPINTVL", color = HighOrLowlight) + Text("TCP_KEEPINTVL", color = MaterialTheme.colors.secondary) } SectionItemView { - Text("TCP_KEEPCNT", color = HighOrLowlight) + Text("TCP_KEEPCNT", color = MaterialTheme.colors.secondary) } } } @@ -208,7 +208,7 @@ fun ResetToDefaultsButton(reset: () -> Unit, disabled: Boolean) { modifier.fillMaxSize(), verticalAlignment = Alignment.CenterVertically ) { - val color = if (disabled) HighOrLowlight else MaterialTheme.colors.primary + val color = if (disabled) MaterialTheme.colors.secondary else MaterialTheme.colors.primary Text(stringResource(R.string.network_options_reset_to_defaults), color = color) } } @@ -256,14 +256,14 @@ fun IntSettingRow(title: String, selection: MutableState, values: List "${selection.value} $label", maxLines = 1, overflow = TextOverflow.Ellipsis, - color = HighOrLowlight + color = MaterialTheme.colors.secondary ) Spacer(Modifier.size(4.dp)) Icon( if (!expanded.value) painterResource(R.drawable.ic_expand_more) else painterResource(R.drawable.ic_expand_less), generalGetString(R.string.invite_to_group_button), modifier = Modifier.padding(start = 8.dp), - tint = HighOrLowlight + tint = MaterialTheme.colors.secondary ) } DefaultExposedDropdownMenu( @@ -317,14 +317,14 @@ fun TimeoutSettingRow(title: String, selection: MutableState, values: List "${df.format(selection.value / 1_000_000.toDouble())} $label", maxLines = 1, overflow = TextOverflow.Ellipsis, - color = HighOrLowlight + color = MaterialTheme.colors.secondary ) Spacer(Modifier.size(4.dp)) Icon( if (!expanded.value) painterResource(R.drawable.ic_expand_more) else painterResource(R.drawable.ic_expand_less), generalGetString(R.string.invite_to_group_button), modifier = Modifier.padding(start = 8.dp), - tint = HighOrLowlight + tint = MaterialTheme.colors.secondary ) } DefaultExposedDropdownMenu( @@ -376,11 +376,11 @@ fun FooterButton(icon: Painter, title: String, action: () -> Unit, disabled: Boo Icon( icon, title, - tint = if (disabled) HighOrLowlight else MaterialTheme.colors.primary + tint = if (disabled) MaterialTheme.colors.secondary else MaterialTheme.colors.primary ) Text( title, - color = if (disabled) HighOrLowlight else MaterialTheme.colors.primary + color = if (disabled) MaterialTheme.colors.secondary else MaterialTheme.colors.primary ) } } 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 ae84518bfd..1f04dcd4f4 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,16 +1,23 @@ package chat.simplex.app.views.usersettings import SectionBottomSpacer -import SectionCustomFooter import SectionDividerSpaced +import SectionItemView import SectionItemViewSpaceBetween import SectionSpacer import SectionView import android.app.Activity import android.content.ComponentName +import android.content.Context import android.content.pm.PackageManager import android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT import android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED +import android.net.Uri +import android.util.Log +import android.widget.Toast +import androidx.activity.compose.ManagedActivityResultLauncher +import androidx.activity.compose.rememberLauncherForActivityResult +import androidx.activity.result.contract.ActivityResultContracts import androidx.compose.foundation.* import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyRow @@ -32,13 +39,15 @@ 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.model.SharedPreference +import chat.simplex.app.model.* import chat.simplex.app.ui.theme.* import chat.simplex.app.views.helpers.* import com.godaddy.android.colorpicker.* import kotlinx.coroutines.delay +import kotlinx.serialization.encodeToString +import java.io.BufferedOutputStream import java.util.* +import kotlin.collections.ArrayList enum class AppIcon(val resId: Int) { DEFAULT(R.mipmap.icon), @@ -46,7 +55,7 @@ enum class AppIcon(val resId: Int) { } @Composable -fun AppearanceView(m: ChatModel) { +fun AppearanceView(m: ChatModel, showSettingsModal: (@Composable (ChatModel) -> Unit) -> (() -> Unit)) { val appIcon = remember { mutableStateOf(findEnabledIcon()) } fun setAppIcon(newIcon: AppIcon) { @@ -69,10 +78,12 @@ fun AppearanceView(m: ChatModel) { AppearanceLayout( appIcon, m.controller.appPrefs.appLanguage, + m.controller.appPrefs.systemDarkTheme, changeIcon = ::setAppIcon, - editPrimaryColor = { primary -> + showSettingsModal = showSettingsModal, + editColor = { name, initialColor -> ModalManager.shared.showModalCloseable { close -> - ColorEditor(primary, close) + ColorEditor(name, initialColor, close) } }, ) @@ -81,8 +92,10 @@ fun AppearanceView(m: ChatModel) { @Composable fun AppearanceLayout( icon: MutableState, languagePref: SharedPreference, + systemDarkTheme: SharedPreference, changeIcon: (AppIcon) -> Unit, - editPrimaryColor: (Color) -> Unit, + showSettingsModal: (@Composable (ChatModel) -> Unit) -> (() -> Unit), + editColor: (ThemeColor, Color) -> Unit, ) { Column( Modifier.fillMaxWidth().verticalScroll(rememberScrollState()), @@ -127,7 +140,7 @@ fun AppearanceView(m: ChatModel) { contentDescription = "", contentScale = ContentScale.Fit, modifier = Modifier - .shadow(if (item == icon.value) 1.dp else 0.dp, ambientColor = colors.secondary) + .shadow(if (item == icon.value) 1.dp else 0.dp, ambientColor = colors.secondaryVariant) .size(70.dp) .clickable { changeIcon(item) } .padding(10.dp) @@ -144,26 +157,110 @@ fun AppearanceView(m: ChatModel) { val currentTheme by CurrentColors.collectAsState() SectionView(stringResource(R.string.settings_section_title_themes)) { val darkTheme = isSystemInDarkTheme() - val state = remember { derivedStateOf { currentTheme.second } } + val state = remember { derivedStateOf { currentTheme.name } } ThemeSelector(state) { - ThemeManager.applyTheme(it.name, darkTheme) + ThemeManager.applyTheme(it, darkTheme) } - SectionItemViewSpaceBetween({ editPrimaryColor(currentTheme.first.primary) }) { + if (state.value == DefaultTheme.SYSTEM.name) { + DarkThemeSelector(remember { systemDarkTheme.state }) { + ThemeManager.changeDarkTheme(it, darkTheme) + } + } + } + SectionItemView(showSettingsModal { _ -> CustomizeThemeView(editColor) }) { Text(stringResource(R.string.customize_theme_title)) } + SectionBottomSpacer() + } +} + +@Composable +fun CustomizeThemeView(editColor: (ThemeColor, Color) -> Unit) { + Column( + Modifier.fillMaxWidth().verticalScroll(rememberScrollState()), + ) { + val currentTheme by CurrentColors.collectAsState() + + AppBarTitle(stringResource(R.string.customize_theme_title)) + + SectionView(stringResource(R.string.theme_colors_section_title)) { + SectionItemViewSpaceBetween({ editColor(ThemeColor.PRIMARY, currentTheme.colors.primary) }) { val title = generalGetString(R.string.color_primary) Text(title) Icon(painterResource(R.drawable.ic_circle_filled), title, tint = colors.primary) } + SectionItemViewSpaceBetween({ editColor(ThemeColor.PRIMARY_VARIANT, currentTheme.colors.primaryVariant) }) { + val title = generalGetString(R.string.color_primary_variant) + Text(title) + Icon(painterResource(R.drawable.ic_circle_filled), title, tint = colors.primaryVariant) + } + SectionItemViewSpaceBetween({ editColor(ThemeColor.SECONDARY, currentTheme.colors.secondary) }) { + val title = generalGetString(R.string.color_secondary) + Text(title) + Icon(painterResource(R.drawable.ic_circle_filled), title, tint = colors.secondary) + } + SectionItemViewSpaceBetween({ editColor(ThemeColor.SECONDARY_VARIANT, currentTheme.colors.secondaryVariant) }) { + val title = generalGetString(R.string.color_secondary_variant) + Text(title) + Icon(painterResource(R.drawable.ic_circle_filled), title, tint = colors.secondaryVariant) + } + SectionItemViewSpaceBetween({ editColor(ThemeColor.BACKGROUND, currentTheme.colors.background) }) { + val title = generalGetString(R.string.color_background) + Text(title) + Icon(painterResource(R.drawable.ic_circle_filled), title, tint = colors.background) + } + SectionItemViewSpaceBetween({ editColor(ThemeColor.SURFACE, currentTheme.colors.surface) }) { + val title = generalGetString(R.string.color_surface) + Text(title) + Icon(painterResource(R.drawable.ic_circle_filled), title, tint = colors.surface) + } + SectionItemViewSpaceBetween({ editColor(ThemeColor.TITLE, currentTheme.appColors.title) }) { + val title = generalGetString(R.string.color_title) + Text(title) + Icon(painterResource(R.drawable.ic_circle_filled), title, tint = currentTheme.appColors.title) + } + SectionItemViewSpaceBetween({ editColor(ThemeColor.SENT_MESSAGE, currentTheme.appColors.sentMessage) }) { + val title = generalGetString(R.string.color_sent_message) + Text(title) + Icon(painterResource(R.drawable.ic_circle_filled), title, tint = currentTheme.appColors.sentMessage) + } + SectionItemViewSpaceBetween({ editColor(ThemeColor.RECEIVED_MESSAGE, currentTheme.appColors.receivedMessage) }) { + val title = generalGetString(R.string.color_received_message) + Text(title) + Icon(painterResource(R.drawable.ic_circle_filled), title, tint = currentTheme.appColors.receivedMessage) + } } - 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)) + val isInDarkTheme = isInDarkTheme() + if (currentTheme.base.hasChangedAnyColor(currentTheme.colors)) { + SectionItemView({ ThemeManager.resetAllThemeColors(darkForSystemTheme = isInDarkTheme) }) { + Text(generalGetString(R.string.reset_color), color = colors.primary) + } + } + SectionSpacer() + SectionView { + if (currentTheme.base.hasChangedAnyColor(currentTheme.colors)) { + val context = LocalContext.current + val theme = remember { mutableStateOf(null as String?) } + val exportThemeLauncher = rememberSaveThemeLauncher(context, theme) + SectionItemView({ + val overrides = ThemeManager.currentThemeOverrides(isInDarkTheme) + theme.value = yaml.encodeToString(overrides) + exportThemeLauncher.launch("simplex.theme") + }) { + Text(generalGetString(R.string.export_theme), color = colors.primary) } } + + val importThemeLauncher = rememberGetContentLauncher { uri: Uri? -> + if (uri != null) { + val theme = getThemeFromUri(uri) + if (theme != null) { + ThemeManager.saveAndApplyThemeOverrides(theme, isInDarkTheme) + } + } + } + // Can not limit to YAML mime type since it's unsupported by Android + SectionItemView({ importThemeLauncher.launch("*/*") }) { + Text(generalGetString(R.string.import_theme), color = colors.primary) + } } SectionBottomSpacer() } @@ -171,6 +268,7 @@ fun AppearanceView(m: ChatModel) { @Composable fun ColorEditor( + name: ThemeColor, initialColor: Color, close: () -> Unit, ) { @@ -178,17 +276,17 @@ fun ColorEditor( Modifier .fillMaxWidth() ) { - AppBarTitle(stringResource(R.string.color_primary)) + AppBarTitle(name.text) var currentColor by remember { mutableStateOf(initialColor) } ColorPicker(initialColor) { currentColor = it } SectionSpacer() - + val isInDarkTheme = isInDarkTheme() TextButton( onClick = { - ThemeManager.saveAndApplyPrimaryColor(currentColor) + ThemeManager.saveAndApplyThemeColor(name, currentColor, isInDarkTheme) close() }, Modifier.align(Alignment.CenterHorizontally), @@ -206,7 +304,7 @@ fun ColorPicker(initialColor: Color, onColorChanged: (Color) -> Unit) { modifier = Modifier .fillMaxWidth() .height(300.dp), - showAlphaBar = false, + showAlphaBar = true, onColorChanged = { color: HsvColor -> onColorChanged(color.toColor()) } @@ -241,9 +339,9 @@ private fun LangSelector(state: State, onSelected: (String) -> Unit) { } @Composable -private fun ThemeSelector(state: State, onSelected: (DefaultTheme) -> Unit) { +private fun ThemeSelector(state: State, onSelected: (String) -> Unit) { val darkTheme = isSystemInDarkTheme() - val values by remember { mutableStateOf(ThemeManager.allThemes(darkTheme).map { it.second to it.third }) } + val values by remember { mutableStateOf(ThemeManager.allThemes(darkTheme).map { it.second.name to it.third }) } ExposedDropDownSettingRow( generalGetString(R.string.theme), values, @@ -254,10 +352,55 @@ private fun ThemeSelector(state: State, onSelected: (DefaultTheme) ) } +@Composable +private fun DarkThemeSelector(state: State, onSelected: (String) -> Unit) { + val values by remember { + val darkThemes = ArrayList>() + darkThemes.add(DefaultTheme.DARK.name to generalGetString(R.string.theme_dark)) + darkThemes.add(DefaultTheme.SIMPLEX.name to generalGetString(R.string.theme_simplex)) + mutableStateOf(darkThemes.toList()) + } + ExposedDropDownSettingRow( + generalGetString(R.string.dark_theme), + values, + state, + icon = null, + enabled = remember { mutableStateOf(true) }, + onSelected = { if (it != null) onSelected(it) } + ) +} + //private fun openSystemLangPicker(activity: Activity) { // activity.startActivity(Intent(Settings.ACTION_APP_LOCALE_SETTINGS, Uri.parse("package:" + SimplexApp.context.packageName))) //} +@Composable +private fun rememberSaveThemeLauncher(cxt: Context, theme: MutableState): ManagedActivityResultLauncher = + rememberLauncherForActivityResult( + contract = ActivityResultContracts.CreateDocument(), + onResult = { destination -> + try { + destination?.let { + val theme = theme.value + if (theme != null) { + val contentResolver = cxt.contentResolver + contentResolver.openOutputStream(destination)?.let { stream -> + BufferedOutputStream(stream).use { outputStream -> + theme.byteInputStream().use { it.copyTo(outputStream) } + } + Toast.makeText(cxt, generalGetString(R.string.file_saved), Toast.LENGTH_SHORT).show() + } + } + } + } catch (e: Error) { + Toast.makeText(cxt, generalGetString(R.string.error_saving_file), Toast.LENGTH_SHORT).show() + Log.e(TAG, "rememberSaveThemeLauncher error saving theme $e") + } finally { + theme.value = null + } + } + ) + private fun findEnabledIcon(): AppIcon = AppIcon.values().first { icon -> SimplexApp.context.packageManager.getComponentEnabledSetting( ComponentName(BuildConfig.APPLICATION_ID, "chat.simplex.app.MainActivity_${icon.name.lowercase()}") @@ -271,8 +414,10 @@ fun PreviewAppearanceSettings() { AppearanceLayout( icon = remember { mutableStateOf(AppIcon.DARK_BLUE) }, languagePref = SharedPreference({ null }, {}), + systemDarkTheme = SharedPreference({ null }, {}), changeIcon = {}, - editPrimaryColor = {}, + showSettingsModal = { {} }, + editColor = { _, _ -> }, ) } } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/CallSettings.kt b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/CallSettings.kt index e487276231..997a9f9e54 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/CallSettings.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/CallSettings.kt @@ -16,7 +16,6 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import chat.simplex.app.R import chat.simplex.app.model.* -import chat.simplex.app.ui.theme.HighOrLowlight import chat.simplex.app.views.helpers.* @Composable @@ -108,7 +107,7 @@ fun SharedPreferenceToggleWithIcon( ) { val prefState = preferenceState ?: remember { mutableStateOf(preference.get()) } Row(Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) { - Text(text, Modifier.padding(end = 4.dp), color = if (stopped) HighOrLowlight else Color.Unspecified) + Text(text, Modifier.padding(end = 4.dp), color = if (stopped) MaterialTheme.colors.secondary else Color.Unspecified) Icon( icon, null, diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/HiddenProfileView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/HiddenProfileView.kt index 75017d8478..676cbd3600 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/HiddenProfileView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/HiddenProfileView.kt @@ -77,7 +77,7 @@ private fun HiddenProfileLayout( PassphraseField(confirmHidePassword, stringResource(R.string.confirm_password), isValid = { confirmValid }, dependsOn = hidePassword) } SectionItemViewSpaceBetween({ saveProfilePassword(hidePassword.value) }, disabled = saveDisabled, minHeight = TextFieldDefaults.MinHeight) { - Text(generalGetString(R.string.save_profile_password), color = if (saveDisabled) HighOrLowlight else MaterialTheme.colors.primary) + Text(generalGetString(R.string.save_profile_password), color = if (saveDisabled) MaterialTheme.colors.secondary else MaterialTheme.colors.primary) } } SectionTextFooter(stringResource(R.string.to_reveal_profile_enter_password)) diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/NetworkAndServers.kt b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/NetworkAndServers.kt index dcaad615cf..c20e4eb0be 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/NetworkAndServers.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/NetworkAndServers.kt @@ -207,7 +207,7 @@ fun UseSocksProxySwitch( Icon( painterResource(R.drawable.ic_settings_ethernet), stringResource(R.string.network_socks_toggle), - tint = HighOrLowlight + tint = MaterialTheme.colors.secondary ) TextIconSpaced(false) if (networkUseSocksProxy.value) { diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/NotificationsSettingsView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/NotificationsSettingsView.kt index 6d3190ab53..e80283ecba 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/NotificationsSettingsView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/NotificationsSettingsView.kt @@ -88,7 +88,7 @@ fun NotificationsSettingsLayout( modes.first { it.value == notificationsMode.value }.title, maxLines = 1, overflow = TextOverflow.Ellipsis, - color = HighOrLowlight + color = MaterialTheme.colors.secondary ) } SettingsActionItemWithContent(null, stringResource(R.string.settings_notification_preview_mode_title), { showPage(CurrentPage.NOTIFICATION_PREVIEW_MODE) }) { @@ -96,7 +96,7 @@ fun NotificationsSettingsLayout( previewModes.first { it.value == notificationPreviewMode.value }.title, maxLines = 1, overflow = TextOverflow.Ellipsis, - color = HighOrLowlight + color = MaterialTheme.colors.secondary ) } } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/Preferences.kt b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/Preferences.kt index a8fe451c5e..ad0537331b 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/Preferences.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/Preferences.kt @@ -112,7 +112,7 @@ private fun TimedMessagesFeatureSection(allowFeature: State, onS PreferenceToggleWithIcon( ChatFeature.TimedMessages.text, ChatFeature.TimedMessages.icon, - HighOrLowlight, + MaterialTheme.colors.secondary, allowFeature.value == FeatureAllowed.ALWAYS || allowFeature.value == FeatureAllowed.YES, extraPadding = false, onSelected @@ -125,10 +125,10 @@ private fun TimedMessagesFeatureSection(allowFeature: State, onS private fun ResetSaveButtons(reset: () -> Unit, save: () -> Unit, disabled: Boolean) { SectionView { SectionItemView(reset, disabled = disabled) { - Text(stringResource(R.string.reset_verb), color = if (disabled) HighOrLowlight else MaterialTheme.colors.primary) + Text(stringResource(R.string.reset_verb), color = if (disabled) MaterialTheme.colors.secondary else MaterialTheme.colors.primary) } SectionItemView(save, disabled = disabled) { - Text(stringResource(R.string.save_and_notify_contacts), color = if (disabled) HighOrLowlight else MaterialTheme.colors.primary) + Text(stringResource(R.string.save_and_notify_contacts), color = if (disabled) MaterialTheme.colors.secondary else MaterialTheme.colors.primary) } } } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/ProtocolServerView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/ProtocolServerView.kt index 9611e6d900..dc960dfd8b 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/ProtocolServerView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/ProtocolServerView.kt @@ -60,7 +60,7 @@ fun ProtocolServerView(m: ChatModel, server: ServerCfg, serverProtocol: ServerPr Modifier .padding(horizontal = 2.dp) .size(30.dp), - color = HighOrLowlight, + color = MaterialTheme.colors.secondary, strokeWidth = 2.5.dp ) } @@ -107,7 +107,7 @@ private fun PresetServer( Modifier.padding(start = DEFAULT_PADDING, top = 5.dp, end = DEFAULT_PADDING, bottom = 10.dp), style = TextStyle( fontFamily = FontFamily.Monospace, fontSize = 16.sp, - color = HighOrLowlight + color = MaterialTheme.colors.secondary ) ) } @@ -172,13 +172,13 @@ private fun UseServerSection( ) { SectionView(stringResource(R.string.smp_servers_use_server).uppercase()) { SectionItemViewSpaceBetween(testServer, disabled = !valid || testing) { - Text(stringResource(R.string.smp_servers_test_server), color = if (valid && !testing) MaterialTheme.colors.onBackground else HighOrLowlight) + Text(stringResource(R.string.smp_servers_test_server), color = if (valid && !testing) MaterialTheme.colors.onBackground else MaterialTheme.colors.secondary) ShowTestStatus(server) } val enabled = rememberUpdatedState(server.enabled) PreferenceToggle(stringResource(R.string.smp_servers_use_server_for_new_conn), enabled.value) { onUpdate(server.copy(enabled = it)) } SectionItemView(onDelete, disabled = testing) { - Text(stringResource(R.string.smp_servers_delete_server), color = if (testing) HighOrLowlight else MaterialTheme.colors.error) + Text(stringResource(R.string.smp_servers_delete_server), color = if (testing) MaterialTheme.colors.secondary else MaterialTheme.colors.error) } } } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/ProtocolServersView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/ProtocolServersView.kt index 173f25c5c0..5e07e6fdba 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/ProtocolServersView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/ProtocolServersView.kt @@ -166,7 +166,7 @@ fun ProtocolServersView(m: ChatModel, serverProtocol: ServerProtocol, close: () Modifier .padding(horizontal = 2.dp) .size(30.dp), - color = HighOrLowlight, + color = MaterialTheme.colors.secondary, strokeWidth = 2.5.dp ) } @@ -207,8 +207,8 @@ private fun ProtocolServersLayout( stringResource(R.string.smp_servers_add), addServer, disabled = testing, - textColor = if (testing) HighOrLowlight else MaterialTheme.colors.primary, - iconColor = if (testing) HighOrLowlight else MaterialTheme.colors.primary + textColor = if (testing) MaterialTheme.colors.secondary else MaterialTheme.colors.primary, + iconColor = if (testing) MaterialTheme.colors.secondary else MaterialTheme.colors.primary ) } SectionTextFooter( @@ -225,14 +225,14 @@ private fun ProtocolServersLayout( SectionDividerSpaced(maxTopPadding = true, maxBottomPadding = false) SectionView { SectionItemView(resetServers, disabled = serversUnchanged) { - Text(stringResource(R.string.reset_verb), color = if (!serversUnchanged) MaterialTheme.colors.onBackground else HighOrLowlight) + Text(stringResource(R.string.reset_verb), color = if (!serversUnchanged) MaterialTheme.colors.onBackground else MaterialTheme.colors.secondary) } val testServersDisabled = testing || allServersDisabled SectionItemView(testServers, disabled = testServersDisabled) { - Text(stringResource(R.string.smp_servers_test_servers), color = if (!testServersDisabled) MaterialTheme.colors.onBackground else HighOrLowlight) + Text(stringResource(R.string.smp_servers_test_servers), color = if (!testServersDisabled) MaterialTheme.colors.onBackground else MaterialTheme.colors.secondary) } SectionItemView(saveSMPServers, disabled = saveDisabled) { - Text(stringResource(R.string.smp_servers_save), color = if (!saveDisabled) MaterialTheme.colors.onBackground else HighOrLowlight) + Text(stringResource(R.string.smp_servers_save), color = if (!saveDisabled) MaterialTheme.colors.onBackground else MaterialTheme.colors.secondary) } } SectionDividerSpaced(maxBottomPadding = false) @@ -248,15 +248,15 @@ private fun ProtocolServerView(serverProtocol: ServerProtocol, srv: ServerCfg, s val address = parseServerAddress(srv.server) when { address == null || !address.valid || address.serverProtocol != serverProtocol || !uniqueAddress(srv, address, servers) -> InvalidServer() - !srv.enabled -> Icon(painterResource(R.drawable.ic_do_not_disturb_on), null, tint = HighOrLowlight) + !srv.enabled -> Icon(painterResource(R.drawable.ic_do_not_disturb_on), null, tint = MaterialTheme.colors.secondary) else -> ShowTestStatus(srv) } Spacer(Modifier.padding(horizontal = 4.dp)) val text = address?.hostnames?.firstOrNull() ?: srv.server if (srv.enabled) { - Text(text, color = if (disabled) HighOrLowlight else MaterialTheme.colors.onBackground, maxLines = 1) + Text(text, color = if (disabled) MaterialTheme.colors.secondary else MaterialTheme.colors.onBackground, maxLines = 1) } else { - Text(text, maxLines = 1, color = HighOrLowlight) + Text(text, maxLines = 1, color = MaterialTheme.colors.secondary) } } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/RTCServers.kt b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/RTCServers.kt index fde4082739..bfecd10027 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/RTCServers.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/RTCServers.kt @@ -155,7 +155,7 @@ fun RTCServersLayout( .height(160.dp) .fillMaxWidth(), shape = RoundedCornerShape(10.dp), - border = BorderStroke(1.dp, MaterialTheme.colors.secondary) + border = BorderStroke(1.dp, MaterialTheme.colors.secondaryVariant) ) { SelectionContainer( Modifier.verticalScroll(rememberScrollState()) 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 c28aa38f5a..2c90600077 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 @@ -97,7 +97,7 @@ fun SettingsView(chatModel: ChatModel, setPerformLA: (Boolean, FragmentActivity) } } Box( - Modifier.fillMaxSize(), + Modifier.fillMaxSize().background(MaterialTheme.colors.background), contentAlignment = Alignment.Center ) { SimpleButton( @@ -134,8 +134,9 @@ fun SettingsLayout( showVersion: () -> Unit, withAuth: (title: String, desc: String, block: () -> Unit) -> Unit ) { + val theme = CurrentColors.collectAsState() val uriHandler = LocalUriHandler.current - Box(Modifier.fillMaxSize().verticalScroll(rememberScrollState()).background(MaterialTheme.colors.background)) { + Box(Modifier.fillMaxSize().verticalScroll(rememberScrollState()).themedBackground(theme.value.base)) { Column( Modifier .fillMaxSize() @@ -160,7 +161,7 @@ fun SettingsLayout( SettingsActionItem(painterResource(R.drawable.ic_wifi_tethering), stringResource(R.string.network_and_servers), showSettingsModal { NetworkAndServersView(it, showModal, showSettingsModal, showCustomModal) }, disabled = stopped, extraPadding = true) SettingsActionItem(painterResource(R.drawable.ic_videocam), stringResource(R.string.settings_audio_video_calls), showSettingsModal { CallSettingsView(it, showModal) }, disabled = stopped, extraPadding = true) SettingsActionItem(painterResource(R.drawable.ic_lock), stringResource(R.string.privacy_and_security), showSettingsModal { PrivacySettingsView(it, showSettingsModal, setPerformLA) }, disabled = stopped, extraPadding = true) - SettingsActionItem(painterResource(R.drawable.ic_light_mode), stringResource(R.string.appearance_settings), showSettingsModal { AppearanceView(it) }, disabled = stopped, extraPadding = true) + SettingsActionItem(painterResource(R.drawable.ic_light_mode), stringResource(R.string.appearance_settings), showSettingsModal { AppearanceView(it, showSettingsModal) }, extraPadding = true) DatabaseItem(encrypted, showSettingsModal { DatabaseView(it, showSettingsModal) }, stopped) } SectionDividerSpaced() @@ -199,7 +200,7 @@ fun SettingsIncognitoActionItem( ) { SettingsPreferenceItemWithInfo( if (incognito.value) painterResource(R.drawable.ic_theater_comedy_filled) else painterResource(R.drawable.ic_theater_comedy), - if (incognito.value) Indigo else HighOrLowlight, + if (incognito.value) Indigo else MaterialTheme.colors.secondary, stringResource(R.string.incognito), stopped, onClickInfo, @@ -237,7 +238,7 @@ fun MaintainIncognitoState(chatModel: ChatModel) { Icon( painterResource(R.drawable.ic_database), contentDescription = stringResource(R.string.database_passphrase_and_export), - tint = if (encrypted) HighOrLowlight else WarningOrange, + tint = if (encrypted) MaterialTheme.colors.secondary else WarningOrange, ) TextIconSpaced(true) Text(stringResource(R.string.database_passphrase_and_export)) @@ -282,10 +283,10 @@ fun ChatLockItem( click = showSettingsModal { SimplexLockView(chatModel, currentLAMode, setPerformLA) }, icon = if (performLA.value) painterResource(R.drawable.ic_lock_filled) else painterResource(R.drawable.ic_lock), text = stringResource(R.string.chat_lock), - iconColor = if (performLA.value) SimplexGreen else HighOrLowlight, + iconColor = if (performLA.value) SimplexGreen else MaterialTheme.colors.secondary, extraPadding = false, ) { - Text(if (performLA.value) remember { currentLAMode.state }.value.text else generalGetString(androidx.compose.ui.R.string.off), color = HighOrLowlight) + Text(if (performLA.value) remember { currentLAMode.state }.value.text else generalGetString(androidx.compose.ui.R.string.off), color = MaterialTheme.colors.secondary) } } @@ -294,7 +295,7 @@ fun ChatLockItem( Icon( painterResource(R.drawable.ic_keyboard), contentDescription = "GitHub", - tint = HighOrLowlight, + tint = MaterialTheme.colors.secondary, ) TextIconSpaced(extraPadding = true) Text(generalGetString(R.string.contribute), color = MaterialTheme.colors.primary) @@ -310,7 +311,7 @@ fun ChatLockItem( Icon( painterResource(R.drawable.ic_star), contentDescription = "Google Play", - tint = HighOrLowlight, + tint = MaterialTheme.colors.secondary, ) TextIconSpaced(extraPadding = true) Text(generalGetString(R.string.rate_the_app), color = MaterialTheme.colors.primary) @@ -322,7 +323,7 @@ fun ChatLockItem( Icon( painter = painterResource(id = R.drawable.ic_github), contentDescription = "GitHub", - tint = HighOrLowlight, + tint = MaterialTheme.colors.secondary, ) TextIconSpaced(extraPadding = true) Text(generalGetString(R.string.star_on_github), color = MaterialTheme.colors.primary) @@ -334,7 +335,7 @@ fun ChatLockItem( Icon( painter = painterResource(id = R.drawable.ic_outline_terminal), contentDescription = stringResource(R.string.chat_console), - tint = HighOrLowlight, + tint = MaterialTheme.colors.secondary, ) TextIconSpaced() Text(stringResource(R.string.chat_console)) @@ -346,7 +347,7 @@ fun ChatLockItem( Icon( painter = painterResource(id = R.drawable.ic_github), contentDescription = "GitHub", - tint = HighOrLowlight, + tint = MaterialTheme.colors.secondary, ) TextIconSpaced() Text(generalGetString(R.string.install_simplex_chat_for_terminal), color = MaterialTheme.colors.primary) @@ -361,7 +362,7 @@ fun ChatLockItem( Text("v${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})") } -@Composable fun ProfilePreview(profileOf: NamedChat, size: Dp = 60.dp, color: Color = MaterialTheme.colors.secondary, stopped: Boolean = false) { +@Composable fun ProfilePreview(profileOf: NamedChat, size: Dp = 60.dp, color: Color = MaterialTheme.colors.secondaryVariant, stopped: Boolean = false) { ProfileImage(size = size, image = profileOf.image, color = color) Spacer(Modifier.padding(horizontal = 8.dp)) Column(Modifier.height(size), verticalArrangement = Arrangement.Center) { @@ -369,7 +370,7 @@ fun ChatLockItem( profileOf.displayName, style = MaterialTheme.typography.caption, fontWeight = FontWeight.Bold, - color = if (stopped) HighOrLowlight else Color.Unspecified, + color = if (stopped) MaterialTheme.colors.secondary else Color.Unspecified, maxLines = 1, overflow = TextOverflow.Ellipsis ) @@ -377,7 +378,7 @@ fun ChatLockItem( Text( profileOf.fullName, Modifier.padding(vertical = 5.dp), - color = if (stopped) HighOrLowlight else Color.Unspecified, + color = if (stopped) MaterialTheme.colors.secondary else Color.Unspecified, maxLines = 1, overflow = TextOverflow.Ellipsis ) @@ -386,16 +387,16 @@ fun ChatLockItem( } @Composable -fun SettingsActionItem(icon: Painter, text: String, click: (() -> Unit)? = null, textColor: Color = Color.Unspecified, iconColor: Color = HighOrLowlight, disabled: Boolean = false, extraPadding: Boolean = false) { +fun SettingsActionItem(icon: Painter, text: String, click: (() -> Unit)? = null, textColor: Color = Color.Unspecified, iconColor: Color = MaterialTheme.colors.secondary, disabled: Boolean = false, extraPadding: Boolean = false) { SectionItemView(click, disabled = disabled, extraPadding = extraPadding) { - Icon(icon, text, tint = if (disabled) HighOrLowlight else iconColor) + Icon(icon, text, tint = if (disabled) MaterialTheme.colors.secondary else iconColor) TextIconSpaced(extraPadding) - Text(text, color = if (disabled) HighOrLowlight else textColor) + Text(text, color = if (disabled) MaterialTheme.colors.secondary else textColor) } } @Composable -fun SettingsActionItemWithContent(icon: Painter?, text: String? = null, click: (() -> Unit)? = null, iconColor: Color = HighOrLowlight, disabled: Boolean = false, extraPadding: Boolean = false, content: @Composable RowScope.() -> Unit) { +fun SettingsActionItemWithContent(icon: Painter?, text: String? = null, click: (() -> Unit)? = null, iconColor: Color = MaterialTheme.colors.secondary, disabled: Boolean = false, extraPadding: Boolean = false, content: @Composable RowScope.() -> Unit) { SectionItemView( click, extraPadding = extraPadding, @@ -406,11 +407,11 @@ fun SettingsActionItemWithContent(icon: Painter?, text: String? = null, click: ( disabled = disabled ) { if (icon != null) { - Icon(icon, text, Modifier, tint = if (disabled) HighOrLowlight else iconColor) + Icon(icon, text, Modifier, tint = if (disabled) MaterialTheme.colors.secondary else iconColor) TextIconSpaced(extraPadding) } if (text != null) { - Text(text, Modifier.weight(1f), color = if (disabled) HighOrLowlight else MaterialTheme.colors.onBackground) + Text(text, Modifier.weight(1f), color = if (disabled) MaterialTheme.colors.secondary else MaterialTheme.colors.onBackground) Spacer(Modifier.width(DEFAULT_PADDING)) } content() @@ -422,7 +423,7 @@ fun SettingsPreferenceItem( icon: Painter?, text: String, pref: SharedPreference, - iconColor: Color = HighOrLowlight, + iconColor: Color = MaterialTheme.colors.secondary, enabled: Boolean = true, onChange: ((Boolean) -> Unit)? = null, ) { @@ -464,12 +465,12 @@ fun PreferenceToggle( fun PreferenceToggleWithIcon( text: String, icon: Painter? = null, - iconColor: Color? = HighOrLowlight, + iconColor: Color? = MaterialTheme.colors.secondary, checked: Boolean, extraPadding: Boolean = false, onChange: (Boolean) -> Unit = {}, ) { - SettingsActionItemWithContent(icon, text, iconColor = iconColor ?: HighOrLowlight, extraPadding = extraPadding) { + SettingsActionItemWithContent(icon, text, iconColor = iconColor ?: MaterialTheme.colors.secondary, extraPadding = extraPadding) { DefaultSwitch( checked = checked, onCheckedChange = { diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/UserProfileView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/UserProfileView.kt index 5e70e268db..e0d7926486 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/UserProfileView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/UserProfileView.kt @@ -115,7 +115,7 @@ fun UserProfileLayout( ) { Box(contentAlignment = Alignment.TopEnd) { Box(contentAlignment = Alignment.Center) { - ProfileImage(108.dp, profileImage.value, color = HighOrLowlight.copy(alpha = 0.1f)) + ProfileImage(108.dp, profileImage.value, color = MaterialTheme.colors.secondary.copy(alpha = 0.1f)) EditImageButton { scope.launch { bottomSheetModalState.show() } } } if (profileImage.value != null) { @@ -156,7 +156,7 @@ fun UserProfileLayout( saveColor = MaterialTheme.colors.primary } else { saveModifier = Modifier - saveColor = HighOrLowlight + saveColor = MaterialTheme.colors.secondary } Text( stringResource(R.string.save_and_notify_contacts), diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/UserProfilesView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/UserProfilesView.kt index 780d9292f9..98c1519320 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/UserProfilesView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/UserProfilesView.kt @@ -281,7 +281,7 @@ private fun ProfileActionView(action: UserProfileAction, user: User, doAction: ( PassphraseField(actionPassword, generalGetString(R.string.profile_password), isValid = { passwordValid }, showStrength = true) } SectionItemViewSpaceBetween({ doAction(actionPassword.value) }, disabled = !actionEnabled, minHeight = TextFieldDefaults.MinHeight) { - Text(generalGetString(label), color = if (actionEnabled) color else HighOrLowlight) + Text(generalGetString(label), color = if (actionEnabled) color else MaterialTheme.colors.secondary) } } } diff --git a/apps/android/app/src/main/res/values/strings.xml b/apps/android/app/src/main/res/values/strings.xml index 578c14a298..ea69b48417 100644 --- a/apps/android/app/src/main/res/values/strings.xml +++ b/apps/android/app/src/main/res/values/strings.xml @@ -564,6 +564,8 @@ Update transport isolation mode? Set Use .onion hosts to No if SOCKS proxy does not support them. Appearance + Customize theme + THEME COLORS App version App version: v%s App build: %s @@ -1156,15 +1158,29 @@ System Light Dark + SimpleX System Theme + Dark theme Save color + Import theme + Import theme error + Make sure the file has correct YAML syntax. Export theme to have an example of the theme file structure. + Export theme Reset colors Accent + Additional accent + Secondary + Additional secondary + Background + Menus & alerts + Title + Sent message + Received message You allow