Localize contacts screen and contact errors/messages (EN/RU)
This commit is contained in:
@@ -30,12 +30,14 @@ import androidx.compose.runtime.snapshotFlow
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalConfiguration
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import ru.daemonlord.messenger.R
|
||||
|
||||
@Composable
|
||||
fun ContactsRoute(
|
||||
@@ -104,7 +106,7 @@ private fun ContactsScreen(
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp),
|
||||
) {
|
||||
TopAppBar(
|
||||
title = { Text("Contacts") },
|
||||
title = { Text(stringResource(id = R.string.contacts_title)) },
|
||||
)
|
||||
PullToRefreshBox(
|
||||
isRefreshing = state.isRefreshing,
|
||||
@@ -122,7 +124,7 @@ private fun ContactsScreen(
|
||||
onValueChange = onQueryChanged,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
singleLine = true,
|
||||
label = { Text("Search contacts/users") },
|
||||
label = { Text(stringResource(id = R.string.contacts_search_label)) },
|
||||
)
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
@@ -134,10 +136,10 @@ private fun ContactsScreen(
|
||||
onValueChange = onAddByEmailChanged,
|
||||
modifier = Modifier.weight(1f),
|
||||
singleLine = true,
|
||||
label = { Text("Add by email") },
|
||||
label = { Text(stringResource(id = R.string.contacts_add_by_email_label)) },
|
||||
)
|
||||
Button(onClick = onAddContactByEmail) {
|
||||
Text("Add")
|
||||
Text(stringResource(id = R.string.common_create))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,7 +174,7 @@ private fun ContactsScreen(
|
||||
if (state.isSearchingUsers || state.query.trim().length >= 2) {
|
||||
item(key = "search_header") {
|
||||
Text(
|
||||
text = "Search results",
|
||||
text = stringResource(id = R.string.contacts_search_results),
|
||||
style = MaterialTheme.typography.titleSmall,
|
||||
fontWeight = FontWeight.SemiBold,
|
||||
)
|
||||
@@ -197,7 +199,7 @@ private fun ContactsScreen(
|
||||
)
|
||||
}
|
||||
OutlinedButton(onClick = { onAddContact(user.id) }) {
|
||||
Text("Add")
|
||||
Text(stringResource(id = R.string.common_create))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -205,7 +207,7 @@ private fun ContactsScreen(
|
||||
|
||||
item(key = "contacts_header") {
|
||||
Text(
|
||||
text = "My contacts",
|
||||
text = stringResource(id = R.string.contacts_my_contacts),
|
||||
style = MaterialTheme.typography.titleSmall,
|
||||
fontWeight = FontWeight.SemiBold,
|
||||
modifier = Modifier.padding(top = 4.dp),
|
||||
@@ -226,13 +228,13 @@ private fun ContactsScreen(
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
Text(
|
||||
text = contact.username?.let { "@$it" } ?: "last seen recently",
|
||||
text = contact.username?.let { "@$it" } ?: stringResource(id = R.string.contacts_last_seen_recently),
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
}
|
||||
OutlinedButton(onClick = { onRemoveContact(contact.id) }) {
|
||||
Text("Remove")
|
||||
Text(stringResource(id = R.string.contacts_remove))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -240,7 +242,7 @@ private fun ContactsScreen(
|
||||
if (state.contacts.isEmpty()) {
|
||||
item(key = "empty_contacts") {
|
||||
Text(
|
||||
text = "No contacts yet.",
|
||||
text = stringResource(id = R.string.contacts_empty),
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
|
||||
@@ -2,7 +2,9 @@ package ru.daemonlord.messenger.ui.contacts
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import android.content.Context
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
@@ -10,6 +12,7 @@ import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
import ru.daemonlord.messenger.R
|
||||
import ru.daemonlord.messenger.domain.account.repository.AccountRepository
|
||||
import ru.daemonlord.messenger.domain.common.AppError
|
||||
import ru.daemonlord.messenger.domain.common.AppResult
|
||||
@@ -18,6 +21,7 @@ import javax.inject.Inject
|
||||
@HiltViewModel
|
||||
class ContactsViewModel @Inject constructor(
|
||||
private val accountRepository: AccountRepository,
|
||||
@ApplicationContext private val context: Context,
|
||||
) : ViewModel() {
|
||||
|
||||
private val _uiState = MutableStateFlow(ContactsUiState())
|
||||
@@ -76,7 +80,7 @@ class ContactsViewModel @Inject constructor(
|
||||
viewModelScope.launch {
|
||||
when (val result = accountRepository.addContact(userId = userId)) {
|
||||
is AppResult.Success -> {
|
||||
_uiState.update { it.copy(infoMessage = "Contact added.") }
|
||||
_uiState.update { it.copy(infoMessage = context.getString(R.string.contacts_info_added)) }
|
||||
loadContacts(forceRefresh = true)
|
||||
}
|
||||
is AppResult.Error -> _uiState.update { it.copy(errorMessage = result.reason.toUiMessage()) }
|
||||
@@ -87,7 +91,7 @@ class ContactsViewModel @Inject constructor(
|
||||
fun addContactByEmail() {
|
||||
val email = uiState.value.addByEmail.trim()
|
||||
if (email.isBlank()) {
|
||||
_uiState.update { it.copy(errorMessage = "Email is required.") }
|
||||
_uiState.update { it.copy(errorMessage = context.getString(R.string.contacts_error_email_required)) }
|
||||
return
|
||||
}
|
||||
viewModelScope.launch {
|
||||
@@ -96,7 +100,7 @@ class ContactsViewModel @Inject constructor(
|
||||
_uiState.update {
|
||||
it.copy(
|
||||
addByEmail = "",
|
||||
infoMessage = "Contact added by email.",
|
||||
infoMessage = context.getString(R.string.contacts_info_added_by_email),
|
||||
)
|
||||
}
|
||||
loadContacts(forceRefresh = true)
|
||||
@@ -110,7 +114,7 @@ class ContactsViewModel @Inject constructor(
|
||||
viewModelScope.launch {
|
||||
when (val result = accountRepository.removeContact(userId = userId)) {
|
||||
is AppResult.Success -> {
|
||||
_uiState.update { it.copy(infoMessage = "Contact removed.") }
|
||||
_uiState.update { it.copy(infoMessage = context.getString(R.string.contacts_info_removed)) }
|
||||
loadContacts(forceRefresh = true)
|
||||
}
|
||||
is AppResult.Error -> _uiState.update { it.copy(errorMessage = result.reason.toUiMessage()) }
|
||||
@@ -148,11 +152,11 @@ class ContactsViewModel @Inject constructor(
|
||||
|
||||
private fun AppError.toUiMessage(): String {
|
||||
return when (this) {
|
||||
AppError.Network -> "Network error."
|
||||
AppError.Unauthorized -> "Session expired."
|
||||
AppError.InvalidCredentials -> "Authorization error."
|
||||
is AppError.Server -> this.message ?: "Server error."
|
||||
is AppError.Unknown -> this.cause?.message ?: "Unknown error."
|
||||
AppError.Network -> context.getString(R.string.error_network)
|
||||
AppError.Unauthorized -> context.getString(R.string.error_session_expired)
|
||||
AppError.InvalidCredentials -> context.getString(R.string.error_authorization)
|
||||
is AppError.Server -> this.message ?: context.getString(R.string.error_server)
|
||||
is AppError.Unknown -> this.cause?.message ?: context.getString(R.string.error_unknown)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,4 +208,22 @@
|
||||
<string name="auth_send_reset_link">Отправить ссылку сброса</string>
|
||||
<string name="auth_new_password">Новый пароль</string>
|
||||
<string name="auth_reset_with_token">Сбросить по токену</string>
|
||||
|
||||
<string name="contacts_title">Контакты</string>
|
||||
<string name="contacts_search_label">Поиск контактов/пользователей</string>
|
||||
<string name="contacts_add_by_email_label">Добавить по email</string>
|
||||
<string name="contacts_search_results">Результаты поиска</string>
|
||||
<string name="contacts_my_contacts">Мои контакты</string>
|
||||
<string name="contacts_last_seen_recently">был(а) недавно</string>
|
||||
<string name="contacts_remove">Удалить</string>
|
||||
<string name="contacts_empty">Контактов пока нет.</string>
|
||||
<string name="contacts_info_added">Контакт добавлен.</string>
|
||||
<string name="contacts_info_added_by_email">Контакт добавлен по email.</string>
|
||||
<string name="contacts_info_removed">Контакт удален.</string>
|
||||
<string name="contacts_error_email_required">Требуется email.</string>
|
||||
<string name="error_network">Ошибка сети.</string>
|
||||
<string name="error_session_expired">Сессия истекла.</string>
|
||||
<string name="error_authorization">Ошибка авторизации.</string>
|
||||
<string name="error_server">Ошибка сервера.</string>
|
||||
<string name="error_unknown">Неизвестная ошибка.</string>
|
||||
</resources>
|
||||
|
||||
@@ -208,4 +208,22 @@
|
||||
<string name="auth_send_reset_link">Send reset link</string>
|
||||
<string name="auth_new_password">New password</string>
|
||||
<string name="auth_reset_with_token">Reset with token</string>
|
||||
|
||||
<string name="contacts_title">Contacts</string>
|
||||
<string name="contacts_search_label">Search contacts/users</string>
|
||||
<string name="contacts_add_by_email_label">Add by email</string>
|
||||
<string name="contacts_search_results">Search results</string>
|
||||
<string name="contacts_my_contacts">My contacts</string>
|
||||
<string name="contacts_last_seen_recently">last seen recently</string>
|
||||
<string name="contacts_remove">Remove</string>
|
||||
<string name="contacts_empty">No contacts yet.</string>
|
||||
<string name="contacts_info_added">Contact added.</string>
|
||||
<string name="contacts_info_added_by_email">Contact added by email.</string>
|
||||
<string name="contacts_info_removed">Contact removed.</string>
|
||||
<string name="contacts_error_email_required">Email is required.</string>
|
||||
<string name="error_network">Network error.</string>
|
||||
<string name="error_session_expired">Session expired.</string>
|
||||
<string name="error_authorization">Authorization error.</string>
|
||||
<string name="error_server">Server error.</string>
|
||||
<string name="error_unknown">Unknown error.</string>
|
||||
</resources>
|
||||
|
||||
Reference in New Issue
Block a user