add settings to change theme
This commit is contained in:
@@ -70,6 +70,7 @@ private object PrefKeys {
|
|||||||
const val LAST_READ_PER_ROUTE = "last_read_route_per_route"
|
const val LAST_READ_PER_ROUTE = "last_read_route_per_route"
|
||||||
const val AUTOMATICALLY_SHOW_IMAGES = "automatically_show_images"
|
const val AUTOMATICALLY_SHOW_IMAGES = "automatically_show_images"
|
||||||
const val AUTOMATICALLY_START_PLAYBACK = "automatically_start_playback"
|
const val AUTOMATICALLY_START_PLAYBACK = "automatically_start_playback"
|
||||||
|
const val THEME = "theme"
|
||||||
val LAST_READ: (String) -> String = { route -> "last_read_route_$route" }
|
val LAST_READ: (String) -> String = { route -> "last_read_route_$route" }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,6 +257,20 @@ object LocalPreferences {
|
|||||||
}.apply()
|
}.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? {
|
fun loadFromEncryptedStorage(): Account? {
|
||||||
val acc = loadFromEncryptedStorage(currentAccount())
|
val acc = loadFromEncryptedStorage(currentAccount())
|
||||||
acc?.registerObservers()
|
acc?.registerObservers()
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import com.vitorpamplona.amethyst.ui.navigation.debugState
|
|||||||
import com.vitorpamplona.amethyst.ui.note.Nip47
|
import com.vitorpamplona.amethyst.ui.note.Nip47
|
||||||
import com.vitorpamplona.amethyst.ui.screen.AccountScreen
|
import com.vitorpamplona.amethyst.ui.screen.AccountScreen
|
||||||
import com.vitorpamplona.amethyst.ui.screen.AccountStateViewModel
|
import com.vitorpamplona.amethyst.ui.screen.AccountStateViewModel
|
||||||
|
import com.vitorpamplona.amethyst.ui.screen.ThemeViewModel
|
||||||
import com.vitorpamplona.amethyst.ui.theme.AmethystTheme
|
import com.vitorpamplona.amethyst.ui.theme.AmethystTheme
|
||||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@@ -50,16 +51,18 @@ class MainActivity : FragmentActivity() {
|
|||||||
val startingPage = uriToRoute(uri)
|
val startingPage = uriToRoute(uri)
|
||||||
|
|
||||||
LocalPreferences.migrateSingleUserPrefs()
|
LocalPreferences.migrateSingleUserPrefs()
|
||||||
|
val themeViewModel = ThemeViewModel()
|
||||||
|
themeViewModel.onChange(LocalPreferences.getTheme())
|
||||||
|
|
||||||
setContent {
|
setContent {
|
||||||
AmethystTheme {
|
AmethystTheme(themeViewModel) {
|
||||||
// A surface container using the 'background' color from the theme
|
// A surface container using the 'background' color from the theme
|
||||||
Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colors.background) {
|
Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colors.background) {
|
||||||
val accountStateViewModel: AccountStateViewModel = viewModel {
|
val accountStateViewModel: AccountStateViewModel = viewModel {
|
||||||
AccountStateViewModel(this@MainActivity)
|
AccountStateViewModel(this@MainActivity)
|
||||||
}
|
}
|
||||||
|
|
||||||
AccountScreen(accountStateViewModel, startingPage)
|
AccountScreen(accountStateViewModel, themeViewModel, startingPage)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.MainScreen
|
|||||||
import com.vitorpamplona.amethyst.ui.screen.loggedOff.LoginPage
|
import com.vitorpamplona.amethyst.ui.screen.loggedOff.LoginPage
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun AccountScreen(accountStateViewModel: AccountStateViewModel, startingPage: String?) {
|
fun AccountScreen(accountStateViewModel: AccountStateViewModel, themeViewModel: ThemeViewModel, startingPage: String?) {
|
||||||
val accountState by accountStateViewModel.accountContent.collectAsState()
|
val accountState by accountStateViewModel.accountContent.collectAsState()
|
||||||
|
|
||||||
Column() {
|
Column() {
|
||||||
@@ -24,7 +24,7 @@ fun AccountScreen(accountStateViewModel: AccountStateViewModel, startingPage: St
|
|||||||
is AccountState.LoggedIn -> {
|
is AccountState.LoggedIn -> {
|
||||||
val accountViewModel: AccountViewModel = viewModel(
|
val accountViewModel: AccountViewModel = viewModel(
|
||||||
key = state.account.userProfile().pubkeyHex,
|
key = state.account.userProfile().pubkeyHex,
|
||||||
factory = AccountViewModel.Factory(state.account)
|
factory = AccountViewModel.Factory(state.account, themeViewModel)
|
||||||
)
|
)
|
||||||
|
|
||||||
MainScreen(accountViewModel, accountStateViewModel, startingPage)
|
MainScreen(accountViewModel, accountStateViewModel, startingPage)
|
||||||
@@ -32,7 +32,7 @@ fun AccountScreen(accountStateViewModel: AccountStateViewModel, startingPage: St
|
|||||||
is AccountState.LoggedInViewOnly -> {
|
is AccountState.LoggedInViewOnly -> {
|
||||||
val accountViewModel: AccountViewModel = viewModel(
|
val accountViewModel: AccountViewModel = viewModel(
|
||||||
key = state.account.userProfile().pubkeyHex,
|
key = state.account.userProfile().pubkeyHex,
|
||||||
factory = AccountViewModel.Factory(state.account)
|
factory = AccountViewModel.Factory(state.account, themeViewModel)
|
||||||
)
|
)
|
||||||
|
|
||||||
MainScreen(accountViewModel, accountStateViewModel, startingPage)
|
MainScreen(accountViewModel, accountStateViewModel, startingPage)
|
||||||
|
|||||||
@@ -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<String> = _theme
|
||||||
|
|
||||||
|
fun onChange(newValue: String) {
|
||||||
|
_theme.value = newValue
|
||||||
|
}
|
||||||
|
}
|
||||||
+12
-3
@@ -22,6 +22,7 @@ import com.vitorpamplona.amethyst.service.model.Event
|
|||||||
import com.vitorpamplona.amethyst.service.model.LnZapEvent
|
import com.vitorpamplona.amethyst.service.model.LnZapEvent
|
||||||
import com.vitorpamplona.amethyst.service.model.PayInvoiceErrorResponse
|
import com.vitorpamplona.amethyst.service.model.PayInvoiceErrorResponse
|
||||||
import com.vitorpamplona.amethyst.service.model.ReportEvent
|
import com.vitorpamplona.amethyst.service.model.ReportEvent
|
||||||
|
import com.vitorpamplona.amethyst.ui.screen.ThemeViewModel
|
||||||
import kotlinx.collections.immutable.ImmutableSet
|
import kotlinx.collections.immutable.ImmutableSet
|
||||||
import kotlinx.collections.immutable.persistentSetOf
|
import kotlinx.collections.immutable.persistentSetOf
|
||||||
import kotlinx.collections.immutable.toImmutableSet
|
import kotlinx.collections.immutable.toImmutableSet
|
||||||
@@ -32,7 +33,7 @@ import java.math.BigDecimal
|
|||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
|
||||||
@Stable
|
@Stable
|
||||||
class AccountViewModel(val account: Account) : ViewModel() {
|
class AccountViewModel(val account: Account, private val themeViewModel: ThemeViewModel) : ViewModel() {
|
||||||
val accountLiveData: LiveData<AccountState> = account.live.map { it }
|
val accountLiveData: LiveData<AccountState> = account.live.map { it }
|
||||||
val accountLanguagesLiveData: LiveData<AccountState> = account.liveLanguages.map { it }
|
val accountLanguagesLiveData: LiveData<AccountState> = account.liveLanguages.map { it }
|
||||||
val accountLastReadLiveData: LiveData<AccountState> = account.liveLastRead.map { it }
|
val accountLastReadLiveData: LiveData<AccountState> = account.liveLastRead.map { it }
|
||||||
@@ -40,6 +41,14 @@ class AccountViewModel(val account: Account) : ViewModel() {
|
|||||||
val userFollows: LiveData<UserState> = account.userProfile().live().follows.map { it }
|
val userFollows: LiveData<UserState> = account.userProfile().live().follows.map { it }
|
||||||
val userRelays: LiveData<UserState> = account.userProfile().live().relays.map { it }
|
val userRelays: LiveData<UserState> = 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?) {
|
fun updateGlobalSettings(automaticallyShowImages: Boolean?, automaticallyStartPlayback: Boolean?) {
|
||||||
account.updateGlobalSettings(automaticallyShowImages, automaticallyStartPlayback)
|
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 <AccountViewModel : ViewModel> create(modelClass: Class<AccountViewModel>): AccountViewModel {
|
override fun <AccountViewModel : ViewModel> create(modelClass: Class<AccountViewModel>): AccountViewModel {
|
||||||
return AccountViewModel(account) as AccountViewModel
|
return AccountViewModel(account, themeViewModel) as AccountViewModel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,6 +51,13 @@ fun SettingsScreen(
|
|||||||
val selectedVideoItem = remember {
|
val selectedVideoItem = remember {
|
||||||
mutableStateOf(selectedItens[videoIndex])
|
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
|
val context = LocalContext.current
|
||||||
Column(
|
Column(
|
||||||
StdPadding,
|
StdPadding,
|
||||||
@@ -60,6 +67,17 @@ fun SettingsScreen(
|
|||||||
|
|
||||||
Section("Application preferences")
|
Section("Application preferences")
|
||||||
|
|
||||||
|
Text(
|
||||||
|
"Theme",
|
||||||
|
fontWeight = FontWeight.Bold
|
||||||
|
)
|
||||||
|
|
||||||
|
DropDownSettings(
|
||||||
|
selectedItem = selectedTheme,
|
||||||
|
listItems = themeItens,
|
||||||
|
title = "Theme"
|
||||||
|
)
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
"Media",
|
"Media",
|
||||||
fontWeight = FontWeight.Bold
|
fontWeight = FontWeight.Bold
|
||||||
@@ -95,9 +113,11 @@ fun SettingsScreen(
|
|||||||
2 -> false
|
2 -> false
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
|
accountViewModel.changeTheme(selectedTheme.value)
|
||||||
scope.launch(Dispatchers.IO) {
|
scope.launch(Dispatchers.IO) {
|
||||||
accountViewModel.updateGlobalSettings(automaticallyShowImages, automaticallyStartPlayback)
|
accountViewModel.updateGlobalSettings(automaticallyShowImages, automaticallyStartPlayback)
|
||||||
LocalPreferences.saveToEncryptedStorage(accountViewModel.account)
|
LocalPreferences.saveToEncryptedStorage(accountViewModel.account)
|
||||||
|
LocalPreferences.updateTheme(selectedTheme.value)
|
||||||
ServiceManager.pause()
|
ServiceManager.pause()
|
||||||
ServiceManager.start(context)
|
ServiceManager.start(context)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import androidx.compose.material.darkColors
|
|||||||
import androidx.compose.material.lightColors
|
import androidx.compose.material.lightColors
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.SideEffect
|
import androidx.compose.runtime.SideEffect
|
||||||
|
import androidx.compose.runtime.livedata.observeAsState
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
@@ -27,6 +28,7 @@ import androidx.compose.ui.text.font.FontFamily
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import com.halilibo.richtext.ui.RichTextStyle
|
import com.halilibo.richtext.ui.RichTextStyle
|
||||||
import com.halilibo.richtext.ui.resolveDefaults
|
import com.halilibo.richtext.ui.resolveDefaults
|
||||||
|
import com.vitorpamplona.amethyst.ui.screen.ThemeViewModel
|
||||||
|
|
||||||
private val DarkColorPalette = darkColors(
|
private val DarkColorPalette = darkColors(
|
||||||
primary = Purple200,
|
primary = Purple200,
|
||||||
@@ -304,12 +306,14 @@ val Colors.innerPostModifier: Modifier
|
|||||||
get() = if (isLight) LightInnerPostBorderModifier else DarkInnerPostBorderModifier
|
get() = if (isLight) LightInnerPostBorderModifier else DarkInnerPostBorderModifier
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun AmethystTheme(darkTheme: Boolean = isSystemInDarkTheme(), content: @Composable () -> Unit) {
|
fun AmethystTheme(themeViewModel: ThemeViewModel, content: @Composable () -> Unit) {
|
||||||
val colors = if (darkTheme) {
|
val theme = themeViewModel.theme.observeAsState()
|
||||||
DarkColorPalette
|
val darkTheme = when (theme.value) {
|
||||||
} else {
|
"Dark" -> true
|
||||||
LightColorPalette
|
"Light" -> false
|
||||||
|
else -> if (isSystemInDarkTheme()) true else false
|
||||||
}
|
}
|
||||||
|
val colors = if (darkTheme) DarkColorPalette else LightColorPalette
|
||||||
|
|
||||||
MaterialTheme(
|
MaterialTheme(
|
||||||
colors = colors,
|
colors = colors,
|
||||||
|
|||||||
Reference in New Issue
Block a user