desktop: changing language without reload (#2896)

* desktop: changing language without reload

* comment

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
This commit is contained in:
Stanislav Dmitrenko 2023-08-11 13:00:48 +03:00 committed by GitHub
parent 7a41957d7b
commit 1bc880877d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 80 additions and 74 deletions

View File

@ -214,7 +214,7 @@ object AppearanceScope {
"ru" to "Русский", "ru" to "Русский",
"zh-CN" to "简体中文" "zh-CN" to "简体中文"
) )
val values by remember { mutableStateOf(supportedLanguages.map { it.key to it.value }) } val values by remember(ChatController.appPrefs.appLanguage.state.value) { mutableStateOf(supportedLanguages.map { it.key to it.value }) }
ExposedDropDownSettingRow( ExposedDropDownSettingRow(
generalGetString(MR.strings.settings_section_title_language).lowercase().replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.US) else it.toString() }, generalGetString(MR.strings.settings_section_title_language).lowercase().replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.US) else it.toString() },
values, values,
@ -228,7 +228,9 @@ object AppearanceScope {
@Composable @Composable
private fun ThemeSelector(state: State<String>, onSelected: (String) -> Unit) { private fun ThemeSelector(state: State<String>, onSelected: (String) -> Unit) {
val darkTheme = chat.simplex.common.ui.theme.isSystemInDarkTheme() val darkTheme = chat.simplex.common.ui.theme.isSystemInDarkTheme()
val values by remember { mutableStateOf(ThemeManager.allThemes(darkTheme).map { it.second.name to it.third }) } val values by remember(ChatController.appPrefs.appLanguage.state.value) {
mutableStateOf(ThemeManager.allThemes(darkTheme).map { it.second.name to it.third })
}
ExposedDropDownSettingRow( ExposedDropDownSettingRow(
generalGetString(MR.strings.theme), generalGetString(MR.strings.theme),
values, values,

View File

@ -14,6 +14,7 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.* import androidx.compose.ui.window.*
import chat.simplex.common.model.ChatController import chat.simplex.common.model.ChatController
import chat.simplex.common.model.ChatModel import chat.simplex.common.model.ChatModel
import chat.simplex.common.platform.defaultLocale
import chat.simplex.common.platform.desktopPlatform import chat.simplex.common.platform.desktopPlatform
import chat.simplex.common.ui.theme.SimpleXTheme import chat.simplex.common.ui.theme.SimpleXTheme
import chat.simplex.common.views.helpers.FileDialogChooser import chat.simplex.common.views.helpers.FileDialogChooser
@ -34,84 +35,87 @@ fun showApp() = application {
val width = if (desktopPlatform.isLinux()) 1376.dp else 1366.dp val width = if (desktopPlatform.isLinux()) 1376.dp else 1366.dp
val windowState = rememberWindowState(placement = WindowPlacement.Floating, width = width, height = 768.dp) val windowState = rememberWindowState(placement = WindowPlacement.Floating, width = width, height = 768.dp)
simplexWindowState.windowState = windowState simplexWindowState.windowState = windowState
Window(state = windowState, onCloseRequest = ::exitApplication, onKeyEvent = { // Reload all strings in all @Composable's after language change at runtime
if (it.key == Key.Escape && it.type == KeyEventType.KeyUp) { if (remember { ChatController.appPrefs.appLanguage.state }.value != "") {
simplexWindowState.backstack.lastOrNull()?.invoke() != null Window(state = windowState, onCloseRequest = ::exitApplication, onKeyEvent = {
} else { if (it.key == Key.Escape && it.type == KeyEventType.KeyUp) {
false simplexWindowState.backstack.lastOrNull()?.invoke() != null
} } else {
}, title = "SimpleX") { false
SimpleXTheme {
AppScreen()
if (simplexWindowState.openDialog.isAwaiting) {
FileDialogChooser(
title = "SimpleX",
isLoad = true,
params = simplexWindowState.openDialog.params,
onResult = {
simplexWindowState.openDialog.onResult(it.firstOrNull())
}
)
} }
}, title = "SimpleX") {
if (simplexWindowState.openMultipleDialog.isAwaiting) { SimpleXTheme {
FileDialogChooser( AppScreen()
title = "SimpleX", if (simplexWindowState.openDialog.isAwaiting) {
isLoad = true, FileDialogChooser(
params = simplexWindowState.openMultipleDialog.params, title = "SimpleX",
onResult = { isLoad = true,
simplexWindowState.openMultipleDialog.onResult(it) params = simplexWindowState.openDialog.params,
} onResult = {
) simplexWindowState.openDialog.onResult(it.firstOrNull())
} }
if (simplexWindowState.saveDialog.isAwaiting) {
FileDialogChooser(
title = "SimpleX",
isLoad = false,
params = simplexWindowState.saveDialog.params,
onResult = { simplexWindowState.saveDialog.onResult(it.firstOrNull()) }
)
}
val toasts = remember { simplexWindowState.toasts }
val toast = toasts.firstOrNull()
if (toast != null) {
Box(Modifier.fillMaxSize().padding(bottom = 20.dp), contentAlignment = Alignment.BottomCenter) {
Text(
toast.first,
Modifier.background(MaterialTheme.colors.primary, RoundedCornerShape(100)).padding(vertical = 5.dp, horizontal = 10.dp),
color = MaterialTheme.colors.onPrimary,
style = MaterialTheme.typography.body1
) )
} }
// Shows toast in insertion order with preferred delay per toast. New one will be shown once previous one expires
LaunchedEffect(toast, toasts.size) { if (simplexWindowState.openMultipleDialog.isAwaiting) {
delay(toast.second) FileDialogChooser(
simplexWindowState.toasts.removeFirst() title = "SimpleX",
} isLoad = true,
} params = simplexWindowState.openMultipleDialog.params,
} onResult = {
var windowFocused by remember { simplexWindowState.windowFocused } simplexWindowState.openMultipleDialog.onResult(it)
LaunchedEffect(windowFocused) { }
val delay = ChatController.appPrefs.laLockDelay.get() )
if (!windowFocused && ChatModel.performLA.value && delay > 0) {
delay(delay * 1000L)
// Trigger auth state check when delay ends (and if it ends)
AppLock.recheckAuthState()
}
}
LaunchedEffect(Unit) {
window.addWindowFocusListener(object : WindowFocusListener {
override fun windowGainedFocus(p0: WindowEvent?) {
windowFocused = true
AppLock.recheckAuthState()
} }
override fun windowLostFocus(p0: WindowEvent?) { if (simplexWindowState.saveDialog.isAwaiting) {
windowFocused = false FileDialogChooser(
AppLock.appWasHidden() title = "SimpleX",
isLoad = false,
params = simplexWindowState.saveDialog.params,
onResult = { simplexWindowState.saveDialog.onResult(it.firstOrNull()) }
)
} }
}) val toasts = remember { simplexWindowState.toasts }
val toast = toasts.firstOrNull()
if (toast != null) {
Box(Modifier.fillMaxSize().padding(bottom = 20.dp), contentAlignment = Alignment.BottomCenter) {
Text(
toast.first,
Modifier.background(MaterialTheme.colors.primary, RoundedCornerShape(100)).padding(vertical = 5.dp, horizontal = 10.dp),
color = MaterialTheme.colors.onPrimary,
style = MaterialTheme.typography.body1
)
}
// Shows toast in insertion order with preferred delay per toast. New one will be shown once previous one expires
LaunchedEffect(toast, toasts.size) {
delay(toast.second)
simplexWindowState.toasts.removeFirst()
}
}
}
var windowFocused by remember { simplexWindowState.windowFocused }
LaunchedEffect(windowFocused) {
val delay = ChatController.appPrefs.laLockDelay.get()
if (!windowFocused && ChatModel.performLA.value && delay > 0) {
delay(delay * 1000L)
// Trigger auth state check when delay ends (and if it ends)
AppLock.recheckAuthState()
}
}
LaunchedEffect(Unit) {
window.addWindowFocusListener(object: WindowFocusListener {
override fun windowGainedFocus(p0: WindowEvent?) {
windowFocused = true
AppLock.recheckAuthState()
}
override fun windowLostFocus(p0: WindowEvent?) {
windowFocused = false
AppLock.appWasHidden()
}
})
}
} }
} }
} }