diff --git a/android/app/src/main/java/ru/daemonlord/messenger/ui/contacts/ContactsScreen.kt b/android/app/src/main/java/ru/daemonlord/messenger/ui/contacts/ContactsScreen.kt index b121d29..375a9ed 100644 --- a/android/app/src/main/java/ru/daemonlord/messenger/ui/contacts/ContactsScreen.kt +++ b/android/app/src/main/java/ru/daemonlord/messenger/ui/contacts/ContactsScreen.kt @@ -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, ) diff --git a/android/app/src/main/java/ru/daemonlord/messenger/ui/contacts/ContactsViewModel.kt b/android/app/src/main/java/ru/daemonlord/messenger/ui/contacts/ContactsViewModel.kt index 8d1d4fc..f590d51 100644 --- a/android/app/src/main/java/ru/daemonlord/messenger/ui/contacts/ContactsViewModel.kt +++ b/android/app/src/main/java/ru/daemonlord/messenger/ui/contacts/ContactsViewModel.kt @@ -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) } } } diff --git a/android/app/src/main/res/values-ru/strings.xml b/android/app/src/main/res/values-ru/strings.xml index 883b8ed..40f0037 100644 --- a/android/app/src/main/res/values-ru/strings.xml +++ b/android/app/src/main/res/values-ru/strings.xml @@ -208,4 +208,22 @@ Отправить ссылку сброса Новый пароль Сбросить по токену + + Контакты + Поиск контактов/пользователей + Добавить по email + Результаты поиска + Мои контакты + был(а) недавно + Удалить + Контактов пока нет. + Контакт добавлен. + Контакт добавлен по email. + Контакт удален. + Требуется email. + Ошибка сети. + Сессия истекла. + Ошибка авторизации. + Ошибка сервера. + Неизвестная ошибка. diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml index 67224a5..f1ee1d0 100644 --- a/android/app/src/main/res/values/strings.xml +++ b/android/app/src/main/res/values/strings.xml @@ -208,4 +208,22 @@ Send reset link New password Reset with token + + Contacts + Search contacts/users + Add by email + Search results + My contacts + last seen recently + Remove + No contacts yet. + Contact added. + Contact added by email. + Contact removed. + Email is required. + Network error. + Session expired. + Authorization error. + Server error. + Unknown error.