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
|
||||
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
import ua.acclorite.book_story.core.model.Language
|
||||
|
||||
object CoreData {
|
||||
val languages = persistentListOf(
|
||||
Pair("en", "English"),
|
||||
Pair("uk", "Українська"),
|
||||
Pair("de", "Deutsch"),
|
||||
Pair("ar", "اَلْعَرَبِيَّةُ"),
|
||||
Pair("es", "Español"),
|
||||
Pair("tr", "Türkçe"),
|
||||
Pair("fr", "Français"),
|
||||
Pair("pl", "Polski"),
|
||||
Pair("it", "Italiano"),
|
||||
Pair("zh", "汉语"),
|
||||
Pair("hi", "हिन्दी"),
|
||||
// Currently as "pt" (which is Portuguese) instead of "pt-BR"
|
||||
Pair("pt", "Português (Brasil)"),
|
||||
Pair("ta", "தமிழ்"),
|
||||
Pair("ml", "മലയാളം"),
|
||||
Pair("cs", "Čeština"),
|
||||
Pair("ro", "Română"),
|
||||
Pair("be", "Беларуская"),
|
||||
Pair("ja", "日本語")
|
||||
)
|
||||
val defaultLanguage = Language.fromCode(code = "en")
|
||||
val languages = listOf(
|
||||
Language.fromCode(code = "en"),
|
||||
Language.fromCode(code = "uk"),
|
||||
Language.fromCode(code = "de"),
|
||||
Language.fromCode(code = "ar"),
|
||||
Language.fromCode(code = "es"),
|
||||
Language.fromCode(code = "tr"),
|
||||
Language.fromCode(code = "fr"),
|
||||
Language.fromCode(code = "pl"),
|
||||
Language.fromCode(code = "it"),
|
||||
Language.fromCode(code = "zh"),
|
||||
Language.fromCode(code = "hi"),
|
||||
Language.fromCode(code = "pt", displayName = "pt-BR"),
|
||||
Language.fromCode(code = "ta"),
|
||||
Language.fromCode(code = "ml"),
|
||||
Language.fromCode(code = "cs"),
|
||||
Language.fromCode(code = "ro"),
|
||||
Language.fromCode(code = "be"),
|
||||
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 ua.acclorite.book_story.core.data.CoreData
|
||||
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.settings.model.Setting
|
||||
import ua.acclorite.book_story.presentation.browse.model.BrowseLayout
|
||||
|
|
@ -62,13 +63,17 @@ class SettingsManager @Inject constructor(
|
|||
|
||||
/* ------ Settings --------------------------- */
|
||||
/* ------ General ---------------------------- */
|
||||
val language = setting<String, String>(
|
||||
val language =
|
||||
setting<Language, String>(
|
||||
key = stringPreferencesKey("language"),
|
||||
default = Locale.getDefault().language.take(2).let { locale ->
|
||||
CoreData.languages.any { locale == it.first }.run {
|
||||
if (this) locale
|
||||
else "en"// Default language (English)
|
||||
}
|
||||
default = Locale.getDefault().language.take(2).let { defaultLocale ->
|
||||
CoreData.languages.find { locale -> locale.languageCode.code == defaultLocale }
|
||||
?: CoreData.defaultLanguage
|
||||
},
|
||||
serialize = { it.languageCode.code },
|
||||
deserialize = { code ->
|
||||
CoreData.languages.find { locale -> locale.languageCode.code == code }
|
||||
?: CoreData.defaultLanguage
|
||||
}
|
||||
)
|
||||
val theme = setting<Theme, String>(
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ package ua.acclorite.book_story.domain.use_case.settings
|
|||
|
||||
import androidx.appcompat.app.AppCompatDelegate
|
||||
import androidx.core.os.LocaleListCompat
|
||||
import ua.acclorite.book_story.core.model.Language
|
||||
import ua.acclorite.book_story.data.settings.SettingsManager
|
||||
import javax.inject.Inject
|
||||
|
||||
|
|
@ -15,8 +16,8 @@ class UpdateLanguageUseCase @Inject constructor(
|
|||
private val settings: SettingsManager
|
||||
) {
|
||||
|
||||
operator fun invoke(language: String) {
|
||||
val appLocale = LocaleListCompat.forLanguageTags(language)
|
||||
operator fun invoke(language: Language) {
|
||||
val appLocale = LocaleListCompat.forLanguageTags(language.languageCode.code)
|
||||
AppCompatDelegate.setApplicationLocales(appLocale)
|
||||
settings.language.update(language)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,13 +11,14 @@ import android.net.Uri
|
|||
import androidx.compose.runtime.Immutable
|
||||
import androidx.compose.ui.graphics.Color
|
||||
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.presentation.library.model.LibrarySortOrder
|
||||
|
||||
@Immutable
|
||||
sealed class SettingsEvent {
|
||||
data class OnUpdateLanguage(
|
||||
val language: String
|
||||
val language: Language
|
||||
) : SettingsEvent()
|
||||
|
||||
data class OnGrantPersistableUriPermission(
|
||||
|
|
|
|||
|
|
@ -58,13 +58,13 @@ object StartScreen : Screen, Parcelable {
|
|||
val stackEvent = remember { mutableStateOf(StackEvent.DEFAULT) }
|
||||
|
||||
val languages = remember(settings.language.value) {
|
||||
CoreData.languages.sortedBy { it.second }.map {
|
||||
CoreData.languages.map { item ->
|
||||
ListItem(
|
||||
item = it.first,
|
||||
title = it.second,
|
||||
selected = it.first == settings.language.lastValue
|
||||
item = item,
|
||||
title = item.displayName,
|
||||
selected = item == settings.language.lastValue
|
||||
)
|
||||
}.sortedBy { it.title }
|
||||
}
|
||||
}
|
||||
|
||||
StartContent(
|
||||
|
|
|
|||
|
|
@ -24,11 +24,11 @@ fun AppLanguageOption() {
|
|||
|
||||
ChipsWithTitle(
|
||||
title = stringResource(id = R.string.language_option),
|
||||
chips = CoreData.languages.sortedBy { it.second }.map { item ->
|
||||
chips = CoreData.languages.map { item ->
|
||||
ListItem(
|
||||
item = item.first,
|
||||
title = item.second,
|
||||
selected = item.first == settings.language.value
|
||||
item = item,
|
||||
title = item.displayName,
|
||||
selected = item == settings.language.value
|
||||
)
|
||||
},
|
||||
onClick = { item ->
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import androidx.compose.foundation.background
|
|||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
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.start.StartScreen
|
||||
import ua.acclorite.book_story.ui.common.model.ListItem
|
||||
|
|
@ -18,8 +19,8 @@ import ua.acclorite.book_story.ui.common.model.ListItem
|
|||
fun StartContent(
|
||||
currentPage: Int,
|
||||
stackEvent: StackEvent,
|
||||
languages: List<ListItem<String>>,
|
||||
updateLanguage: (String) -> Unit,
|
||||
languages: List<ListItem<Language>>,
|
||||
updateLanguage: (Language) -> Unit,
|
||||
navigateForward: () -> Unit,
|
||||
navigateBack: () -> Unit,
|
||||
navigateToBrowse: () -> Unit,
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
package ua.acclorite.book_story.ui.start
|
||||
|
||||
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.start.StartScreen
|
||||
import ua.acclorite.book_story.ui.common.model.ListItem
|
||||
|
|
@ -15,8 +16,8 @@ import ua.acclorite.book_story.ui.common.model.ListItem
|
|||
fun StartSettings(
|
||||
currentPage: Int,
|
||||
stackEvent: StackEvent,
|
||||
languages: List<ListItem<String>>,
|
||||
updateLanguage: (String) -> Unit,
|
||||
languages: List<ListItem<Language>>,
|
||||
updateLanguage: (Language) -> Unit,
|
||||
navigateForward: () -> Unit
|
||||
) {
|
||||
StartSettingsScaffold(
|
||||
|
|
|
|||
|
|
@ -17,13 +17,14 @@ import androidx.compose.ui.Modifier
|
|||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
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.model.ListItem
|
||||
import ua.acclorite.book_story.ui.settings.components.SettingsSubcategoryTitle
|
||||
|
||||
fun LazyListScope.StartSettingsLayoutGeneral(
|
||||
languages: List<ListItem<String>>,
|
||||
updateLanguage: (String) -> Unit,
|
||||
languages: List<ListItem<Language>>,
|
||||
updateLanguage: (Language) -> Unit,
|
||||
) {
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
|
@ -34,13 +35,13 @@ fun LazyListScope.StartSettingsLayoutGeneral(
|
|||
Spacer(modifier = Modifier.height(12.dp))
|
||||
}
|
||||
|
||||
items(languages, key = { it.item }) {
|
||||
items(languages, key = { it.item }) { item ->
|
||||
SelectableDialogItem(
|
||||
selected = it.selected,
|
||||
title = it.title,
|
||||
selected = item.selected,
|
||||
title = item.title,
|
||||
horizontalPadding = 18.dp
|
||||
) {
|
||||
updateLanguage(it.item)
|
||||
updateLanguage(item.item)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue