forked from melod1n/fast-messenger
twoFa -> validation naming; fixes for preview for screens (separating view model from ui); some improvements & fixes
This commit is contained in:
+45
-12
@@ -1,9 +1,13 @@
|
||||
package com.meloda.app.fast.languagepicker
|
||||
|
||||
import android.content.res.Resources
|
||||
import androidx.appcompat.app.AppCompatDelegate
|
||||
import androidx.core.os.LocaleListCompat
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.meloda.app.fast.common.UiText
|
||||
import com.meloda.app.fast.common.extensions.setValue
|
||||
import com.meloda.app.fast.common.parseString
|
||||
import com.meloda.app.fast.designsystem.R
|
||||
import com.meloda.app.fast.languagepicker.model.LanguagePickerScreenState
|
||||
import com.meloda.app.fast.languagepicker.model.SelectableLanguage
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
@@ -12,25 +16,54 @@ import kotlinx.coroutines.flow.StateFlow
|
||||
interface LanguagePickerViewModel {
|
||||
val screenState: StateFlow<LanguagePickerScreenState>
|
||||
|
||||
fun setLanguages(languages: List<SelectableLanguage>)
|
||||
|
||||
fun onLanguagePicked(newLanguage: SelectableLanguage)
|
||||
|
||||
fun onApplyButtonClicked()
|
||||
|
||||
fun updateCurrentLocale(locale: String)
|
||||
}
|
||||
|
||||
class LanguagePickerViewModelImpl : LanguagePickerViewModel, ViewModel() {
|
||||
class LanguagePickerViewModelImpl(
|
||||
private val resources: Resources
|
||||
) : LanguagePickerViewModel, ViewModel() {
|
||||
|
||||
override val screenState = MutableStateFlow(
|
||||
LanguagePickerScreenState(
|
||||
languages = emptyList(),
|
||||
currentLanguage = AppCompatDelegate.getApplicationLocales().toLanguageTags()
|
||||
)
|
||||
)
|
||||
override val screenState = MutableStateFlow(LanguagePickerScreenState.EMPTY)
|
||||
|
||||
init {
|
||||
val languages = listOf(
|
||||
Triple(
|
||||
"",
|
||||
UiText.Resource(R.string.language_key_system),
|
||||
UiText.Resource(R.string.language_system)
|
||||
),
|
||||
Triple(
|
||||
"en-US",
|
||||
UiText.Resource(R.string.language_key_english),
|
||||
UiText.Resource(R.string.language_english),
|
||||
),
|
||||
Triple(
|
||||
"ru-RU",
|
||||
UiText.Resource(R.string.language_key_russian),
|
||||
UiText.Resource(R.string.language_russian)
|
||||
),
|
||||
Triple(
|
||||
"uk-UA",
|
||||
UiText.Resource(R.string.language_key_ukrainian),
|
||||
UiText.Resource(R.string.language_ukrainian)
|
||||
)
|
||||
).map { (key, language, local) ->
|
||||
Triple(
|
||||
key,
|
||||
language.parseString(resources).orEmpty(),
|
||||
local.parseString(resources).orEmpty()
|
||||
)
|
||||
}.map { (key, language, local) ->
|
||||
SelectableLanguage(
|
||||
local = local,
|
||||
language = language,
|
||||
key = key,
|
||||
isSelected = key == AppCompatDelegate.getApplicationLocales().toLanguageTags()
|
||||
)
|
||||
}
|
||||
|
||||
override fun setLanguages(languages: List<SelectableLanguage>) {
|
||||
screenState.setValue { old -> old.copy(languages = languages) }
|
||||
}
|
||||
|
||||
|
||||
+9
-1
@@ -6,4 +6,12 @@ import androidx.compose.runtime.Immutable
|
||||
data class LanguagePickerScreenState(
|
||||
val languages: List<SelectableLanguage>,
|
||||
val currentLanguage: String?,
|
||||
)
|
||||
) {
|
||||
|
||||
companion object {
|
||||
val EMPTY: LanguagePickerScreenState = LanguagePickerScreenState(
|
||||
languages = emptyList(),
|
||||
currentLanguage = null
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
package com.meloda.app.fast.languagepicker.navigation
|
||||
|
||||
import androidx.navigation.NavController
|
||||
import androidx.navigation.NavGraphBuilder
|
||||
import androidx.navigation.compose.composable
|
||||
import com.meloda.app.fast.languagepicker.presentation.LanguagePickerRoute
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
object LanguagePicker
|
||||
|
||||
fun NavGraphBuilder.languagePickerScreen(
|
||||
onBack: () -> Unit,
|
||||
) {
|
||||
composable<LanguagePicker> {
|
||||
LanguagePickerRoute(onBack = onBack)
|
||||
}
|
||||
}
|
||||
|
||||
fun NavController.navigateToLanguagePicker() {
|
||||
this.navigate(LanguagePicker)
|
||||
}
|
||||
-78
@@ -1,78 +0,0 @@
|
||||
package com.meloda.app.fast.languagepicker.navigation
|
||||
|
||||
import android.content.res.Resources
|
||||
import androidx.appcompat.app.AppCompatDelegate
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.navigation.NavController
|
||||
import androidx.navigation.NavGraphBuilder
|
||||
import androidx.navigation.compose.composable
|
||||
import com.meloda.app.fast.common.UiText
|
||||
import com.meloda.app.fast.common.parseString
|
||||
import com.meloda.app.fast.designsystem.R
|
||||
import com.meloda.app.fast.languagepicker.LanguagePickerViewModel
|
||||
import com.meloda.app.fast.languagepicker.LanguagePickerViewModelImpl
|
||||
import com.meloda.app.fast.languagepicker.model.SelectableLanguage
|
||||
import com.meloda.app.fast.languagepicker.presentation.LanguagePickerScreen
|
||||
import kotlinx.serialization.Serializable
|
||||
import org.koin.androidx.compose.koinViewModel
|
||||
|
||||
@Serializable
|
||||
object LanguagePicker
|
||||
|
||||
private fun getLanguages(resources: Resources): List<SelectableLanguage> {
|
||||
return listOf(
|
||||
Triple(
|
||||
"",
|
||||
UiText.Resource(R.string.language_key_system),
|
||||
UiText.Resource(R.string.language_system)
|
||||
),
|
||||
Triple(
|
||||
"en-US",
|
||||
UiText.Resource(R.string.language_key_english),
|
||||
UiText.Resource(R.string.language_english),
|
||||
),
|
||||
Triple(
|
||||
"ru-RU",
|
||||
UiText.Resource(R.string.language_key_russian),
|
||||
UiText.Resource(R.string.language_russian)
|
||||
),
|
||||
Triple(
|
||||
"uk-UA",
|
||||
UiText.Resource(R.string.language_key_ukrainian),
|
||||
UiText.Resource(R.string.language_ukrainian)
|
||||
)
|
||||
).map { (key, language, local) ->
|
||||
Triple(
|
||||
key,
|
||||
language.parseString(resources).orEmpty(),
|
||||
local.parseString(resources).orEmpty()
|
||||
)
|
||||
}.map { (key, language, local) ->
|
||||
SelectableLanguage(
|
||||
local = local,
|
||||
language = language,
|
||||
key = key,
|
||||
isSelected = key == AppCompatDelegate.getApplicationLocales().toLanguageTags()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun NavGraphBuilder.languagePickerRoute(
|
||||
onBack: () -> Unit,
|
||||
) {
|
||||
composable<LanguagePicker> {
|
||||
val languages = getLanguages(LocalContext.current.resources)
|
||||
|
||||
val viewModel: LanguagePickerViewModel = koinViewModel<LanguagePickerViewModelImpl>()
|
||||
viewModel.setLanguages(languages)
|
||||
|
||||
LanguagePickerScreen(
|
||||
onBack = onBack,
|
||||
viewModel = viewModel
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun NavController.navigateToLanguagePicker() {
|
||||
this.navigate(LanguagePicker)
|
||||
}
|
||||
+30
-12
@@ -56,31 +56,46 @@ import androidx.lifecycle.compose.LifecycleResumeEffect
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.meloda.app.fast.languagepicker.LanguagePickerViewModel
|
||||
import com.meloda.app.fast.languagepicker.LanguagePickerViewModelImpl
|
||||
import com.meloda.app.fast.languagepicker.model.LanguagePickerScreenState
|
||||
import com.meloda.app.fast.languagepicker.model.SelectableLanguage
|
||||
import org.koin.androidx.compose.koinViewModel
|
||||
import com.meloda.app.fast.designsystem.R as UiR
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun LanguagePickerScreen(
|
||||
fun LanguagePickerRoute(
|
||||
onBack: () -> Unit,
|
||||
viewModel: LanguagePickerViewModel = koinViewModel<LanguagePickerViewModelImpl>()
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
val screenState by viewModel.screenState.collectAsStateWithLifecycle()
|
||||
val languages = screenState.languages
|
||||
|
||||
LifecycleResumeEffect(true) {
|
||||
viewModel.updateCurrentLocale(AppCompatDelegate.getApplicationLocales().toLanguageTags())
|
||||
|
||||
onPauseOrDispose {}
|
||||
}
|
||||
|
||||
val screenState by viewModel.screenState.collectAsStateWithLifecycle()
|
||||
|
||||
LanguagePickerScreen(
|
||||
screenState = screenState,
|
||||
onBack = onBack,
|
||||
onLanguagePicked = viewModel::onLanguagePicked,
|
||||
onApplyButtonClicked = viewModel::onApplyButtonClicked
|
||||
)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun LanguagePickerScreen(
|
||||
screenState: LanguagePickerScreenState = LanguagePickerScreenState.EMPTY,
|
||||
onBack: () -> Unit = {},
|
||||
onLanguagePicked: (SelectableLanguage) -> Unit = {},
|
||||
onApplyButtonClicked: () -> Unit = {}
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
|
||||
val isButtonEnabled by remember(screenState) {
|
||||
derivedStateOf {
|
||||
screenState.currentLanguage != null &&
|
||||
languages.isNotEmpty() &&
|
||||
languages.find(SelectableLanguage::isSelected)?.key != screenState.currentLanguage
|
||||
screenState.languages.isNotEmpty() &&
|
||||
screenState.languages.find(SelectableLanguage::isSelected)?.key != screenState.currentLanguage
|
||||
}
|
||||
}
|
||||
|
||||
@@ -165,10 +180,13 @@ fun LanguagePickerScreen(
|
||||
LazyColumn(
|
||||
modifier = Modifier.fillMaxSize()
|
||||
) {
|
||||
items(screenState.languages.toList()) { item ->
|
||||
items(
|
||||
items = screenState.languages.toList(),
|
||||
key = SelectableLanguage::key
|
||||
) { item ->
|
||||
LanguageItem(
|
||||
item = item,
|
||||
onClick = viewModel::onLanguagePicked
|
||||
onClick = onLanguagePicked
|
||||
)
|
||||
}
|
||||
|
||||
@@ -183,7 +201,7 @@ fun LanguagePickerScreen(
|
||||
}
|
||||
|
||||
Button(
|
||||
onClick = viewModel::onApplyButtonClicked,
|
||||
onClick = onApplyButtonClicked,
|
||||
enabled = isButtonEnabled,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
|
||||
Reference in New Issue
Block a user