From 33cc261b6270a3ea78ec9dcc414d3a5b58ec81fb Mon Sep 17 00:00:00 2001 From: greenart7c3 <115044884+greenart7c3@users.noreply.github.com> Date: Wed, 5 Jul 2023 11:30:18 -0300 Subject: [PATCH] add settings to change theme --- .../amethyst/LocalPreferences.kt | 15 ++++++++++++++ .../vitorpamplona/amethyst/ui/MainActivity.kt | 7 +++++-- .../amethyst/ui/screen/AccountScreen.kt | 6 +++--- .../amethyst/ui/screen/ThemeViewModel.kt | 14 +++++++++++++ .../ui/screen/loggedIn/AccountViewModel.kt | 15 +++++++++++--- .../ui/screen/loggedIn/SettingsScreen.kt | 20 +++++++++++++++++++ .../vitorpamplona/amethyst/ui/theme/Theme.kt | 14 ++++++++----- 7 files changed, 78 insertions(+), 13 deletions(-) create mode 100644 app/src/main/java/com/vitorpamplona/amethyst/ui/screen/ThemeViewModel.kt diff --git a/app/src/main/java/com/vitorpamplona/amethyst/LocalPreferences.kt b/app/src/main/java/com/vitorpamplona/amethyst/LocalPreferences.kt index baa47ed90..2b3b08e66 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/LocalPreferences.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/LocalPreferences.kt @@ -70,6 +70,7 @@ private object PrefKeys { const val LAST_READ_PER_ROUTE = "last_read_route_per_route" const val AUTOMATICALLY_SHOW_IMAGES = "automatically_show_images" const val AUTOMATICALLY_START_PLAYBACK = "automatically_start_playback" + const val THEME = "theme" val LAST_READ: (String) -> String = { route -> "last_read_route_$route" } } @@ -256,6 +257,20 @@ object LocalPreferences { }.apply() } + fun updateTheme(theme: String) { + encryptedPreferences().edit().apply { + putString(PrefKeys.THEME, theme) + }.apply() + } + + fun getTheme(): String { + var theme = "System" + encryptedPreferences().apply { + theme = getString(PrefKeys.THEME, "System") ?: "System" + } + return theme + } + fun loadFromEncryptedStorage(): Account? { val acc = loadFromEncryptedStorage(currentAccount()) acc?.registerObservers() diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/MainActivity.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/MainActivity.kt index 6f299b350..1e5f10444 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/MainActivity.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/MainActivity.kt @@ -33,6 +33,7 @@ import com.vitorpamplona.amethyst.ui.navigation.debugState import com.vitorpamplona.amethyst.ui.note.Nip47 import com.vitorpamplona.amethyst.ui.screen.AccountScreen import com.vitorpamplona.amethyst.ui.screen.AccountStateViewModel +import com.vitorpamplona.amethyst.ui.screen.ThemeViewModel import com.vitorpamplona.amethyst.ui.theme.AmethystTheme import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.Dispatchers @@ -50,16 +51,18 @@ class MainActivity : FragmentActivity() { val startingPage = uriToRoute(uri) LocalPreferences.migrateSingleUserPrefs() + val themeViewModel = ThemeViewModel() + themeViewModel.onChange(LocalPreferences.getTheme()) setContent { - AmethystTheme { + AmethystTheme(themeViewModel) { // A surface container using the 'background' color from the theme Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colors.background) { val accountStateViewModel: AccountStateViewModel = viewModel { AccountStateViewModel(this@MainActivity) } - AccountScreen(accountStateViewModel, startingPage) + AccountScreen(accountStateViewModel, themeViewModel, startingPage) } } } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/AccountScreen.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/AccountScreen.kt index f3c923a68..6ac35a240 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/AccountScreen.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/AccountScreen.kt @@ -12,7 +12,7 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.MainScreen import com.vitorpamplona.amethyst.ui.screen.loggedOff.LoginPage @Composable -fun AccountScreen(accountStateViewModel: AccountStateViewModel, startingPage: String?) { +fun AccountScreen(accountStateViewModel: AccountStateViewModel, themeViewModel: ThemeViewModel, startingPage: String?) { val accountState by accountStateViewModel.accountContent.collectAsState() Column() { @@ -24,7 +24,7 @@ fun AccountScreen(accountStateViewModel: AccountStateViewModel, startingPage: St is AccountState.LoggedIn -> { val accountViewModel: AccountViewModel = viewModel( key = state.account.userProfile().pubkeyHex, - factory = AccountViewModel.Factory(state.account) + factory = AccountViewModel.Factory(state.account, themeViewModel) ) MainScreen(accountViewModel, accountStateViewModel, startingPage) @@ -32,7 +32,7 @@ fun AccountScreen(accountStateViewModel: AccountStateViewModel, startingPage: St is AccountState.LoggedInViewOnly -> { val accountViewModel: AccountViewModel = viewModel( key = state.account.userProfile().pubkeyHex, - factory = AccountViewModel.Factory(state.account) + factory = AccountViewModel.Factory(state.account, themeViewModel) ) MainScreen(accountViewModel, accountStateViewModel, startingPage) diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/ThemeViewModel.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/ThemeViewModel.kt new file mode 100644 index 000000000..c64cca42d --- /dev/null +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/ThemeViewModel.kt @@ -0,0 +1,14 @@ +package com.vitorpamplona.amethyst.ui.screen + +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel + +class ThemeViewModel : ViewModel() { + private val _theme = MutableLiveData("System") + val theme: LiveData = _theme + + fun onChange(newValue: String) { + _theme.value = newValue + } +} diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt index 91082ac97..f55bca325 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt @@ -22,6 +22,7 @@ import com.vitorpamplona.amethyst.service.model.Event import com.vitorpamplona.amethyst.service.model.LnZapEvent import com.vitorpamplona.amethyst.service.model.PayInvoiceErrorResponse import com.vitorpamplona.amethyst.service.model.ReportEvent +import com.vitorpamplona.amethyst.ui.screen.ThemeViewModel import kotlinx.collections.immutable.ImmutableSet import kotlinx.collections.immutable.persistentSetOf import kotlinx.collections.immutable.toImmutableSet @@ -32,7 +33,7 @@ import java.math.BigDecimal import java.util.Locale @Stable -class AccountViewModel(val account: Account) : ViewModel() { +class AccountViewModel(val account: Account, private val themeViewModel: ThemeViewModel) : ViewModel() { val accountLiveData: LiveData = account.live.map { it } val accountLanguagesLiveData: LiveData = account.liveLanguages.map { it } val accountLastReadLiveData: LiveData = account.liveLastRead.map { it } @@ -40,6 +41,14 @@ class AccountViewModel(val account: Account) : ViewModel() { val userFollows: LiveData = account.userProfile().live().follows.map { it } val userRelays: LiveData = account.userProfile().live().relays.map { it } + fun changeTheme(newValue: String) { + themeViewModel.onChange(newValue) + } + + fun currentTheme(): String { + return themeViewModel.theme.value ?: "System" + } + fun updateGlobalSettings(automaticallyShowImages: Boolean?, automaticallyStartPlayback: Boolean?) { account.updateGlobalSettings(automaticallyShowImages, automaticallyStartPlayback) } @@ -303,9 +312,9 @@ class AccountViewModel(val account: Account) : ViewModel() { } } - class Factory(val account: Account) : ViewModelProvider.Factory { + class Factory(val account: Account, private val themeViewModel: ThemeViewModel) : ViewModelProvider.Factory { override fun create(modelClass: Class): AccountViewModel { - return AccountViewModel(account) as AccountViewModel + return AccountViewModel(account, themeViewModel) as AccountViewModel } } } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/SettingsScreen.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/SettingsScreen.kt index a0d937843..854a16221 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/SettingsScreen.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/SettingsScreen.kt @@ -51,6 +51,13 @@ fun SettingsScreen( val selectedVideoItem = remember { mutableStateOf(selectedItens[videoIndex]) } + + val themeItens = arrayOf("System", "Light", "Dark") + val themeIndex = themeItens.indexOf(accountViewModel.currentTheme()) + val selectedTheme = remember { + mutableStateOf(themeItens[themeIndex]) + } + val context = LocalContext.current Column( StdPadding, @@ -60,6 +67,17 @@ fun SettingsScreen( Section("Application preferences") + Text( + "Theme", + fontWeight = FontWeight.Bold + ) + + DropDownSettings( + selectedItem = selectedTheme, + listItems = themeItens, + title = "Theme" + ) + Text( "Media", fontWeight = FontWeight.Bold @@ -95,9 +113,11 @@ fun SettingsScreen( 2 -> false else -> null } + accountViewModel.changeTheme(selectedTheme.value) scope.launch(Dispatchers.IO) { accountViewModel.updateGlobalSettings(automaticallyShowImages, automaticallyStartPlayback) LocalPreferences.saveToEncryptedStorage(accountViewModel.account) + LocalPreferences.updateTheme(selectedTheme.value) ServiceManager.pause() ServiceManager.start(context) } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/theme/Theme.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/theme/Theme.kt index 46471728e..88cf6fec2 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/theme/Theme.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/theme/Theme.kt @@ -14,6 +14,7 @@ import androidx.compose.material.darkColors import androidx.compose.material.lightColors import androidx.compose.runtime.Composable import androidx.compose.runtime.SideEffect +import androidx.compose.runtime.livedata.observeAsState import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color @@ -27,6 +28,7 @@ import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.unit.dp import com.halilibo.richtext.ui.RichTextStyle import com.halilibo.richtext.ui.resolveDefaults +import com.vitorpamplona.amethyst.ui.screen.ThemeViewModel private val DarkColorPalette = darkColors( primary = Purple200, @@ -304,12 +306,14 @@ val Colors.innerPostModifier: Modifier get() = if (isLight) LightInnerPostBorderModifier else DarkInnerPostBorderModifier @Composable -fun AmethystTheme(darkTheme: Boolean = isSystemInDarkTheme(), content: @Composable () -> Unit) { - val colors = if (darkTheme) { - DarkColorPalette - } else { - LightColorPalette +fun AmethystTheme(themeViewModel: ThemeViewModel, content: @Composable () -> Unit) { + val theme = themeViewModel.theme.observeAsState() + val darkTheme = when (theme.value) { + "Dark" -> true + "Light" -> false + else -> if (isSystemInDarkTheme()) true else false } + val colors = if (darkTheme) DarkColorPalette else LightColorPalette MaterialTheme( colors = colors,