Localize AccountViewModel status and error messages
Some checks failed
Android CI / android (push) Failing after 5m31s
Android Release / release (push) Has started running
CI / test (push) Has been cancelled

This commit is contained in:
2026-03-11 20:46:36 +03:00
parent d54dc9fe8b
commit 27f2ad8001
3 changed files with 45 additions and 16 deletions

View File

@@ -1,9 +1,11 @@
package ru.daemonlord.messenger.ui.account
import android.content.Context
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.appcompat.app.AppCompatDelegate
import androidx.core.os.LocaleListCompat
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
@@ -23,6 +25,7 @@ import ru.daemonlord.messenger.domain.settings.model.AppLanguage
import ru.daemonlord.messenger.domain.settings.model.AppThemeMode
import ru.daemonlord.messenger.domain.settings.repository.LanguageRepository
import ru.daemonlord.messenger.domain.settings.repository.ThemeRepository
import ru.daemonlord.messenger.R
import javax.inject.Inject
@HiltViewModel
@@ -36,6 +39,7 @@ class AccountViewModel @Inject constructor(
private val languageRepository: LanguageRepository,
private val themeRepository: ThemeRepository,
private val pushTokenSyncManager: PushTokenSyncManager,
@ApplicationContext private val context: Context,
) : ViewModel() {
private val _uiState = MutableStateFlow(AccountUiState())
val uiState: StateFlow<AccountUiState> = _uiState.asStateFlow()
@@ -65,13 +69,14 @@ class AccountViewModel @Inject constructor(
notificationsHistory = (notifications as? AppResult.Success)?.data ?: state.notificationsHistory,
activeUserId = activeUserId,
storedAccounts = storedAccounts.map { account ->
val fallbackUser = context.getString(R.string.account_user_fallback, account.userId)
StoredAccountUi(
userId = account.userId,
title = account.name.ifBlank { "User #${account.userId}" },
title = account.name.ifBlank { fallbackUser },
subtitle = listOfNotNull(
account.username?.takeIf { it.isNotBlank() }?.let { "@$it" },
account.email?.takeIf { it.isNotBlank() },
).joinToString("").ifBlank { "User #${account.userId}" },
).joinToString("").ifBlank { fallbackUser },
avatarUrl = account.avatarUrl,
isActive = activeUserId == account.userId,
)
@@ -131,7 +136,7 @@ class AccountViewModel @Inject constructor(
fun addAccount(email: String, password: String, onDone: (Boolean) -> Unit = {}) {
val normalizedEmail = email.trim()
if (normalizedEmail.isBlank() || password.isBlank()) {
_uiState.update { it.copy(errorMessage = "Email and password are required.") }
_uiState.update { it.copy(errorMessage = context.getString(R.string.account_error_email_password_required)) }
onDone(false)
return
}
@@ -142,7 +147,7 @@ class AccountViewModel @Inject constructor(
_uiState.update {
it.copy(
isAddingAccount = false,
message = "Account added.",
message = context.getString(R.string.account_info_added),
)
}
refresh()
@@ -165,7 +170,7 @@ class AccountViewModel @Inject constructor(
viewModelScope.launch {
val switched = tokenRepository.switchAccount(userId)
if (!switched) {
_uiState.update { it.copy(errorMessage = "No saved session for this account.") }
_uiState.update { it.copy(errorMessage = context.getString(R.string.account_error_no_saved_session)) }
onSwitched(false)
return@launch
}
@@ -180,7 +185,7 @@ class AccountViewModel @Inject constructor(
if (syncFailed) {
_uiState.update {
it.copy(
errorMessage = "Account switched, but chats sync failed. Pull to refresh.",
errorMessage = context.getString(R.string.account_error_switch_sync_failed),
)
}
}
@@ -208,7 +213,7 @@ class AccountViewModel @Inject constructor(
it.copy(
isSaving = false,
profile = result.data,
message = "Profile updated.",
message = context.getString(R.string.account_info_profile_updated),
)
}
is AppResult.Error -> _uiState.update {
@@ -231,7 +236,7 @@ class AccountViewModel @Inject constructor(
_uiState.update { it.copy(isSaving = true, errorMessage = null, message = null) }
when (val result = accountRepository.uploadAvatar(fileName, mimeType, bytes)) {
is AppResult.Success -> {
_uiState.update { it.copy(isSaving = false, message = "Avatar uploaded.") }
_uiState.update { it.copy(isSaving = false, message = context.getString(R.string.account_info_avatar_uploaded)) }
onUploaded(result.data)
}
is AppResult.Error -> _uiState.update {
@@ -264,7 +269,7 @@ class AccountViewModel @Inject constructor(
it.copy(
isSaving = false,
profile = result.data,
message = "Privacy settings updated.",
message = context.getString(R.string.account_info_privacy_updated),
)
}
is AppResult.Error -> _uiState.update {
@@ -317,7 +322,7 @@ class AccountViewModel @Inject constructor(
it.copy(
twoFactorSecret = result.data.first,
twoFactorOtpAuthUrl = result.data.second,
message = "2FA secret generated. Enter code to enable.",
message = context.getString(R.string.account_info_2fa_secret_generated),
errorMessage = null,
)
}
@@ -366,7 +371,7 @@ class AccountViewModel @Inject constructor(
is AppResult.Success -> _uiState.update {
it.copy(
recoveryCodes = result.data,
message = "Recovery codes regenerated.",
message = context.getString(R.string.account_info_recovery_codes_regenerated),
errorMessage = null,
)
}
@@ -461,11 +466,11 @@ class AccountViewModel @Inject constructor(
private fun AppError.toUiMessage(): String {
return when (this) {
AppError.InvalidCredentials -> "Invalid credentials."
AppError.Unauthorized -> "Unauthorized."
AppError.Network -> "Network error."
is AppError.Server -> message ?: "Server error."
is AppError.Unknown -> cause?.message ?: "Unknown error."
AppError.InvalidCredentials -> context.getString(R.string.account_error_invalid_credentials)
AppError.Unauthorized -> context.getString(R.string.account_error_unauthorized)
AppError.Network -> context.getString(R.string.error_network)
is AppError.Server -> message ?: context.getString(R.string.error_server)
is AppError.Unknown -> cause?.message ?: context.getString(R.string.error_unknown)
}
}
}

View File

@@ -263,4 +263,16 @@
<string name="error_authorization">Ошибка авторизации.</string>
<string name="error_server">Ошибка сервера.</string>
<string name="error_unknown">Неизвестная ошибка.</string>
<string name="account_user_fallback">Пользователь #%1$d</string>
<string name="account_error_email_password_required">Нужны email и пароль.</string>
<string name="account_info_added">Аккаунт добавлен.</string>
<string name="account_error_no_saved_session">Для этого аккаунта нет сохраненной сессии.</string>
<string name="account_error_switch_sync_failed">Аккаунт переключен, но синхронизация чатов не удалась. Потяните вниз для обновления.</string>
<string name="account_info_profile_updated">Профиль обновлен.</string>
<string name="account_info_avatar_uploaded">Аватар загружен.</string>
<string name="account_info_privacy_updated">Настройки приватности обновлены.</string>
<string name="account_info_2fa_secret_generated">Секрет 2FA сгенерирован. Введите код для включения.</string>
<string name="account_info_recovery_codes_regenerated">Коды восстановления перегенерированы.</string>
<string name="account_error_invalid_credentials">Неверные учетные данные.</string>
<string name="account_error_unauthorized">Не авторизовано.</string>
</resources>

View File

@@ -263,4 +263,16 @@
<string name="error_authorization">Authorization error.</string>
<string name="error_server">Server error.</string>
<string name="error_unknown">Unknown error.</string>
<string name="account_user_fallback">User #%1$d</string>
<string name="account_error_email_password_required">Email and password are required.</string>
<string name="account_info_added">Account added.</string>
<string name="account_error_no_saved_session">No saved session for this account.</string>
<string name="account_error_switch_sync_failed">Account switched, but chats sync failed. Pull to refresh.</string>
<string name="account_info_profile_updated">Profile updated.</string>
<string name="account_info_avatar_uploaded">Avatar uploaded.</string>
<string name="account_info_privacy_updated">Privacy settings updated.</string>
<string name="account_info_2fa_secret_generated">2FA secret generated. Enter code to enable.</string>
<string name="account_info_recovery_codes_regenerated">Recovery codes regenerated.</string>
<string name="account_error_invalid_credentials">Invalid credentials.</string>
<string name="account_error_unauthorized">Unauthorized.</string>
</resources>