refactor: create language model
This commit is contained in:
parent
0fa8041d5c
commit
96c3917169
11 changed files with 109 additions and 52 deletions
|
|
@ -6,28 +6,29 @@
|
||||||
|
|
||||||
package ua.acclorite.book_story.core.data
|
package ua.acclorite.book_story.core.data
|
||||||
|
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
import kotlinx.collections.immutable.toPersistentList
|
||||||
|
import ua.acclorite.book_story.core.model.Language
|
||||||
|
|
||||||
object CoreData {
|
object CoreData {
|
||||||
val languages = persistentListOf(
|
val defaultLanguage = Language.fromCode(code = "en")
|
||||||
Pair("en", "English"),
|
val languages = listOf(
|
||||||
Pair("uk", "Українська"),
|
Language.fromCode(code = "en"),
|
||||||
Pair("de", "Deutsch"),
|
Language.fromCode(code = "uk"),
|
||||||
Pair("ar", "اَلْعَرَبِيَّةُ"),
|
Language.fromCode(code = "de"),
|
||||||
Pair("es", "Español"),
|
Language.fromCode(code = "ar"),
|
||||||
Pair("tr", "Türkçe"),
|
Language.fromCode(code = "es"),
|
||||||
Pair("fr", "Français"),
|
Language.fromCode(code = "tr"),
|
||||||
Pair("pl", "Polski"),
|
Language.fromCode(code = "fr"),
|
||||||
Pair("it", "Italiano"),
|
Language.fromCode(code = "pl"),
|
||||||
Pair("zh", "汉语"),
|
Language.fromCode(code = "it"),
|
||||||
Pair("hi", "हिन्दी"),
|
Language.fromCode(code = "zh"),
|
||||||
// Currently as "pt" (which is Portuguese) instead of "pt-BR"
|
Language.fromCode(code = "hi"),
|
||||||
Pair("pt", "Português (Brasil)"),
|
Language.fromCode(code = "pt", displayName = "pt-BR"),
|
||||||
Pair("ta", "தமிழ்"),
|
Language.fromCode(code = "ta"),
|
||||||
Pair("ml", "മലയാളം"),
|
Language.fromCode(code = "ml"),
|
||||||
Pair("cs", "Čeština"),
|
Language.fromCode(code = "cs"),
|
||||||
Pair("ro", "Română"),
|
Language.fromCode(code = "ro"),
|
||||||
Pair("be", "Беларуская"),
|
Language.fromCode(code = "be"),
|
||||||
Pair("ja", "日本語")
|
Language.fromCode(code = "ja"),
|
||||||
)
|
).sortedBy { it.displayName }.toPersistentList()
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
/*
|
||||||
|
* Book's Story — free and open-source Material You eBook reader.
|
||||||
|
* Copyright (C) 2024-2025 Acclorite
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
package ua.acclorite.book_story.core.model
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Immutable
|
||||||
|
|
||||||
|
@Immutable
|
||||||
|
data class Language(
|
||||||
|
val languageCode: LanguageCode,
|
||||||
|
val displayName: String
|
||||||
|
) {
|
||||||
|
companion object {
|
||||||
|
fun fromCode(code: String, displayName: String = code): Language {
|
||||||
|
return Language(
|
||||||
|
languageCode = LanguageCode(code = code),
|
||||||
|
displayName = LanguageCode.getDisplayName(code = displayName)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
/*
|
||||||
|
* Book's Story — free and open-source Material You eBook reader.
|
||||||
|
* Copyright (C) 2024-2025 Acclorite
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
package ua.acclorite.book_story.core.model
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Immutable
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
|
@Immutable
|
||||||
|
@JvmInline
|
||||||
|
value class LanguageCode(val code: String) {
|
||||||
|
companion object {
|
||||||
|
fun getDisplayName(code: String): String {
|
||||||
|
val target = Locale.forLanguageTag(code)
|
||||||
|
val displayName = target.getDisplayName(target)
|
||||||
|
return displayName.replaceFirstChar { it.uppercaseChar() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -21,6 +21,7 @@ import kotlinx.coroutines.flow.update
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import ua.acclorite.book_story.core.data.CoreData
|
import ua.acclorite.book_story.core.data.CoreData
|
||||||
import ua.acclorite.book_story.core.log.logI
|
import ua.acclorite.book_story.core.log.logI
|
||||||
|
import ua.acclorite.book_story.core.model.Language
|
||||||
import ua.acclorite.book_story.data.local.data_store.DataStore
|
import ua.acclorite.book_story.data.local.data_store.DataStore
|
||||||
import ua.acclorite.book_story.data.settings.model.Setting
|
import ua.acclorite.book_story.data.settings.model.Setting
|
||||||
import ua.acclorite.book_story.presentation.browse.model.BrowseLayout
|
import ua.acclorite.book_story.presentation.browse.model.BrowseLayout
|
||||||
|
|
@ -62,15 +63,19 @@ class SettingsManager @Inject constructor(
|
||||||
|
|
||||||
/* ------ Settings --------------------------- */
|
/* ------ Settings --------------------------- */
|
||||||
/* ------ General ---------------------------- */
|
/* ------ General ---------------------------- */
|
||||||
val language = setting<String, String>(
|
val language =
|
||||||
key = stringPreferencesKey("language"),
|
setting<Language, String>(
|
||||||
default = Locale.getDefault().language.take(2).let { locale ->
|
key = stringPreferencesKey("language"),
|
||||||
CoreData.languages.any { locale == it.first }.run {
|
default = Locale.getDefault().language.take(2).let { defaultLocale ->
|
||||||
if (this) locale
|
CoreData.languages.find { locale -> locale.languageCode.code == defaultLocale }
|
||||||
else "en"// Default language (English)
|
?: CoreData.defaultLanguage
|
||||||
|
},
|
||||||
|
serialize = { it.languageCode.code },
|
||||||
|
deserialize = { code ->
|
||||||
|
CoreData.languages.find { locale -> locale.languageCode.code == code }
|
||||||
|
?: CoreData.defaultLanguage
|
||||||
}
|
}
|
||||||
}
|
)
|
||||||
)
|
|
||||||
val theme = setting<Theme, String>(
|
val theme = setting<Theme, String>(
|
||||||
key = stringPreferencesKey("theme"), default = Theme.Companion.entries().first(),
|
key = stringPreferencesKey("theme"), default = Theme.Companion.entries().first(),
|
||||||
serialize = { it.name }, deserialize = { Theme.valueOf(it) }
|
serialize = { it.name }, deserialize = { Theme.valueOf(it) }
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ package ua.acclorite.book_story.domain.use_case.settings
|
||||||
|
|
||||||
import androidx.appcompat.app.AppCompatDelegate
|
import androidx.appcompat.app.AppCompatDelegate
|
||||||
import androidx.core.os.LocaleListCompat
|
import androidx.core.os.LocaleListCompat
|
||||||
|
import ua.acclorite.book_story.core.model.Language
|
||||||
import ua.acclorite.book_story.data.settings.SettingsManager
|
import ua.acclorite.book_story.data.settings.SettingsManager
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
|
@ -15,8 +16,8 @@ class UpdateLanguageUseCase @Inject constructor(
|
||||||
private val settings: SettingsManager
|
private val settings: SettingsManager
|
||||||
) {
|
) {
|
||||||
|
|
||||||
operator fun invoke(language: String) {
|
operator fun invoke(language: Language) {
|
||||||
val appLocale = LocaleListCompat.forLanguageTags(language)
|
val appLocale = LocaleListCompat.forLanguageTags(language.languageCode.code)
|
||||||
AppCompatDelegate.setApplicationLocales(appLocale)
|
AppCompatDelegate.setApplicationLocales(appLocale)
|
||||||
settings.language.update(language)
|
settings.language.update(language)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,13 +11,14 @@ import android.net.Uri
|
||||||
import androidx.compose.runtime.Immutable
|
import androidx.compose.runtime.Immutable
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import ua.acclorite.book_story.core.ID
|
import ua.acclorite.book_story.core.ID
|
||||||
|
import ua.acclorite.book_story.core.model.Language
|
||||||
import ua.acclorite.book_story.domain.model.library.Category
|
import ua.acclorite.book_story.domain.model.library.Category
|
||||||
import ua.acclorite.book_story.presentation.library.model.LibrarySortOrder
|
import ua.acclorite.book_story.presentation.library.model.LibrarySortOrder
|
||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
sealed class SettingsEvent {
|
sealed class SettingsEvent {
|
||||||
data class OnUpdateLanguage(
|
data class OnUpdateLanguage(
|
||||||
val language: String
|
val language: Language
|
||||||
) : SettingsEvent()
|
) : SettingsEvent()
|
||||||
|
|
||||||
data class OnGrantPersistableUriPermission(
|
data class OnGrantPersistableUriPermission(
|
||||||
|
|
|
||||||
|
|
@ -58,13 +58,13 @@ object StartScreen : Screen, Parcelable {
|
||||||
val stackEvent = remember { mutableStateOf(StackEvent.DEFAULT) }
|
val stackEvent = remember { mutableStateOf(StackEvent.DEFAULT) }
|
||||||
|
|
||||||
val languages = remember(settings.language.value) {
|
val languages = remember(settings.language.value) {
|
||||||
CoreData.languages.sortedBy { it.second }.map {
|
CoreData.languages.map { item ->
|
||||||
ListItem(
|
ListItem(
|
||||||
item = it.first,
|
item = item,
|
||||||
title = it.second,
|
title = item.displayName,
|
||||||
selected = it.first == settings.language.lastValue
|
selected = item == settings.language.lastValue
|
||||||
)
|
)
|
||||||
}.sortedBy { it.title }
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
StartContent(
|
StartContent(
|
||||||
|
|
|
||||||
|
|
@ -24,11 +24,11 @@ fun AppLanguageOption() {
|
||||||
|
|
||||||
ChipsWithTitle(
|
ChipsWithTitle(
|
||||||
title = stringResource(id = R.string.language_option),
|
title = stringResource(id = R.string.language_option),
|
||||||
chips = CoreData.languages.sortedBy { it.second }.map { item ->
|
chips = CoreData.languages.map { item ->
|
||||||
ListItem(
|
ListItem(
|
||||||
item = item.first,
|
item = item,
|
||||||
title = item.second,
|
title = item.displayName,
|
||||||
selected = item.first == settings.language.value
|
selected = item == settings.language.value
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
onClick = { item ->
|
onClick = { item ->
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import androidx.compose.foundation.background
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import ua.acclorite.book_story.core.model.Language
|
||||||
import ua.acclorite.book_story.presentation.navigator.StackEvent
|
import ua.acclorite.book_story.presentation.navigator.StackEvent
|
||||||
import ua.acclorite.book_story.presentation.start.StartScreen
|
import ua.acclorite.book_story.presentation.start.StartScreen
|
||||||
import ua.acclorite.book_story.ui.common.model.ListItem
|
import ua.acclorite.book_story.ui.common.model.ListItem
|
||||||
|
|
@ -18,8 +19,8 @@ import ua.acclorite.book_story.ui.common.model.ListItem
|
||||||
fun StartContent(
|
fun StartContent(
|
||||||
currentPage: Int,
|
currentPage: Int,
|
||||||
stackEvent: StackEvent,
|
stackEvent: StackEvent,
|
||||||
languages: List<ListItem<String>>,
|
languages: List<ListItem<Language>>,
|
||||||
updateLanguage: (String) -> Unit,
|
updateLanguage: (Language) -> Unit,
|
||||||
navigateForward: () -> Unit,
|
navigateForward: () -> Unit,
|
||||||
navigateBack: () -> Unit,
|
navigateBack: () -> Unit,
|
||||||
navigateToBrowse: () -> Unit,
|
navigateToBrowse: () -> Unit,
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
package ua.acclorite.book_story.ui.start
|
package ua.acclorite.book_story.ui.start
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import ua.acclorite.book_story.core.model.Language
|
||||||
import ua.acclorite.book_story.presentation.navigator.StackEvent
|
import ua.acclorite.book_story.presentation.navigator.StackEvent
|
||||||
import ua.acclorite.book_story.presentation.start.StartScreen
|
import ua.acclorite.book_story.presentation.start.StartScreen
|
||||||
import ua.acclorite.book_story.ui.common.model.ListItem
|
import ua.acclorite.book_story.ui.common.model.ListItem
|
||||||
|
|
@ -15,8 +16,8 @@ import ua.acclorite.book_story.ui.common.model.ListItem
|
||||||
fun StartSettings(
|
fun StartSettings(
|
||||||
currentPage: Int,
|
currentPage: Int,
|
||||||
stackEvent: StackEvent,
|
stackEvent: StackEvent,
|
||||||
languages: List<ListItem<String>>,
|
languages: List<ListItem<Language>>,
|
||||||
updateLanguage: (String) -> Unit,
|
updateLanguage: (Language) -> Unit,
|
||||||
navigateForward: () -> Unit
|
navigateForward: () -> Unit
|
||||||
) {
|
) {
|
||||||
StartSettingsScaffold(
|
StartSettingsScaffold(
|
||||||
|
|
|
||||||
|
|
@ -17,13 +17,14 @@ import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import ua.acclorite.book_story.R
|
import ua.acclorite.book_story.R
|
||||||
|
import ua.acclorite.book_story.core.model.Language
|
||||||
import ua.acclorite.book_story.ui.common.components.dialog.SelectableDialogItem
|
import ua.acclorite.book_story.ui.common.components.dialog.SelectableDialogItem
|
||||||
import ua.acclorite.book_story.ui.common.model.ListItem
|
import ua.acclorite.book_story.ui.common.model.ListItem
|
||||||
import ua.acclorite.book_story.ui.settings.components.SettingsSubcategoryTitle
|
import ua.acclorite.book_story.ui.settings.components.SettingsSubcategoryTitle
|
||||||
|
|
||||||
fun LazyListScope.StartSettingsLayoutGeneral(
|
fun LazyListScope.StartSettingsLayoutGeneral(
|
||||||
languages: List<ListItem<String>>,
|
languages: List<ListItem<Language>>,
|
||||||
updateLanguage: (String) -> Unit,
|
updateLanguage: (Language) -> Unit,
|
||||||
) {
|
) {
|
||||||
item {
|
item {
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
|
@ -34,13 +35,13 @@ fun LazyListScope.StartSettingsLayoutGeneral(
|
||||||
Spacer(modifier = Modifier.height(12.dp))
|
Spacer(modifier = Modifier.height(12.dp))
|
||||||
}
|
}
|
||||||
|
|
||||||
items(languages, key = { it.item }) {
|
items(languages, key = { it.item }) { item ->
|
||||||
SelectableDialogItem(
|
SelectableDialogItem(
|
||||||
selected = it.selected,
|
selected = item.selected,
|
||||||
title = it.title,
|
title = item.title,
|
||||||
horizontalPadding = 18.dp
|
horizontalPadding = 18.dp
|
||||||
) {
|
) {
|
||||||
updateLanguage(it.item)
|
updateLanguage(item.item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue