Localize ChatViewModel runtime messages
Some checks failed
Android CI / android (push) Failing after 4m52s
Android Release / release (push) Has started running
CI / test (push) Has been cancelled

This commit is contained in:
2026-03-11 06:35:24 +03:00
parent 3f9aa83110
commit 43c3fd0169
3 changed files with 66 additions and 25 deletions

View File

@@ -1,8 +1,10 @@
package ru.daemonlord.messenger.ui.chat
import android.content.Context
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
@@ -16,6 +18,7 @@ import kotlinx.coroutines.launch
import ru.daemonlord.messenger.core.notifications.ActiveChatTracker
import ru.daemonlord.messenger.core.notifications.NotificationDispatcher
import ru.daemonlord.messenger.core.token.TokenRepository
import ru.daemonlord.messenger.R
import ru.daemonlord.messenger.domain.chat.repository.ChatRepository
import ru.daemonlord.messenger.domain.chat.usecase.ObserveChatUseCase
import ru.daemonlord.messenger.domain.chat.usecase.ObserveChatsUseCase
@@ -66,6 +69,7 @@ class ChatViewModel @Inject constructor(
private val activeChatTracker: ActiveChatTracker,
private val notificationDispatcher: NotificationDispatcher,
private val tokenRepository: TokenRepository,
@ApplicationContext private val context: Context,
) : ViewModel() {
private val chatId: Long = checkNotNull(savedStateHandle["chatId"])
@@ -133,7 +137,7 @@ class ChatViewModel @Inject constructor(
isRecordingVoice = true,
isVoiceLocked = false,
voiceRecordingDurationMs = 0L,
voiceRecordingHint = "Slide up to lock, slide left to cancel",
voiceRecordingHint = context.getString(R.string.chat_voice_hint_slide),
errorMessage = null,
)
}
@@ -150,7 +154,7 @@ class ChatViewModel @Inject constructor(
if (!it.isRecordingVoice) it else {
it.copy(
isVoiceLocked = true,
voiceRecordingHint = "Recording locked",
voiceRecordingHint = context.getString(R.string.chat_voice_hint_locked),
)
}
}
@@ -180,7 +184,7 @@ class ChatViewModel @Inject constructor(
isVoiceLocked = false,
voiceRecordingDurationMs = 0L,
voiceRecordingHint = null,
errorMessage = "Voice message is too short.",
errorMessage = context.getString(R.string.chat_error_voice_too_short),
)
}
return
@@ -326,7 +330,7 @@ class ChatViewModel @Inject constructor(
val actionState = uiState.value.actionState
if (actionState.mode == MessageSelectionMode.MULTI) {
if (forAll) {
_uiState.update { it.copy(errorMessage = "Delete for all is available only for single message selection.") }
_uiState.update { it.copy(errorMessage = context.getString(R.string.chat_error_delete_for_all_single)) }
return
}
val selectedIds = actionState.selectedMessageIds.toList().sorted()
@@ -354,7 +358,7 @@ class ChatViewModel @Inject constructor(
}
val selected = getFocusedSelectedMessage() ?: return
if (forAll && !canDeleteForAll(selected)) {
_uiState.update { it.copy(errorMessage = "Delete for all is available only for your own messages.") }
_uiState.update { it.copy(errorMessage = context.getString(R.string.chat_error_delete_for_all_own)) }
return
}
viewModelScope.launch {
@@ -474,7 +478,7 @@ class ChatViewModel @Inject constructor(
selectedCanEdit = false,
selectedCanDeleteForAll = false,
actionState = it.actionState.clearSelection(),
errorMessage = "Chat history cleared.",
errorMessage = context.getString(R.string.chat_info_history_cleared),
)
}
is AppResult.Error -> _uiState.update { it.copy(errorMessage = result.reason.toUiMessage()) }
@@ -560,7 +564,7 @@ class ChatViewModel @Inject constructor(
_uiState.update {
it.copy(
isSending = false,
errorMessage = "This message can no longer be edited.",
errorMessage = context.getString(R.string.chat_error_edit_expired),
)
}
return@launch
@@ -572,7 +576,8 @@ class ChatViewModel @Inject constructor(
_uiState.update {
it.copy(
isSending = false,
errorMessage = uiState.value.sendRestrictionText ?: "Sending is restricted in this chat.",
errorMessage = uiState.value.sendRestrictionText
?: context.getString(R.string.chat_error_send_restricted),
)
}
return@launch
@@ -741,14 +746,18 @@ class ChatViewModel @Inject constructor(
val restriction = if (canSend) {
null
} else {
"Only channel owner/admin can send messages."
context.getString(R.string.chat_restriction_owner_admin)
}
val chatTitle = chat.displayTitle.ifBlank {
context.getString(R.string.chat_title_fallback, chatId)
}
val chatTitle = chat.displayTitle.ifBlank { "Chat #$chatId" }
val chatSubtitle = when {
chat.type.equals("private", ignoreCase = true) && chat.counterpartIsOnline == true -> "online"
chat.type.equals("private", ignoreCase = true) && !chat.counterpartLastSeenAt.isNullOrBlank() -> "last seen recently"
chat.type.equals("group", ignoreCase = true) -> "group"
chat.type.equals("channel", ignoreCase = true) -> "channel"
chat.type.equals("private", ignoreCase = true) && chat.counterpartIsOnline == true ->
context.getString(R.string.chat_status_online)
chat.type.equals("private", ignoreCase = true) && !chat.counterpartLastSeenAt.isNullOrBlank() ->
context.getString(R.string.chat_status_last_seen_recently)
chat.type.equals("group", ignoreCase = true) -> context.getString(R.string.chat_type_group)
chat.type.equals("channel", ignoreCase = true) -> context.getString(R.string.chat_type_channel)
else -> ""
}
_uiState.update {
@@ -932,32 +941,32 @@ class ChatViewModel @Inject constructor(
val state = uiState.value
val selfId = state.selfUserId
if (selfId != null && userId == selfId) {
_uiState.update { it.copy(errorMessage = "You cannot apply this action to yourself.") }
_uiState.update { it.copy(errorMessage = context.getString(R.string.chat_error_action_self)) }
return false
}
val actorRole = state.chatRole?.lowercase()
if (actorRole != "owner" && actorRole != "admin") {
_uiState.update { it.copy(errorMessage = "You don't have enough permissions.") }
_uiState.update { it.copy(errorMessage = context.getString(R.string.chat_error_permissions)) }
return false
}
if (ownerOnly && actorRole != "owner") {
_uiState.update { it.copy(errorMessage = "Only owner can perform this action.") }
_uiState.update { it.copy(errorMessage = context.getString(R.string.chat_error_owner_only)) }
return false
}
val targetRole = state.chatMembers.firstOrNull { it.userId == userId }?.role?.lowercase()
if (targetRole == "owner") {
_uiState.update { it.copy(errorMessage = "You cannot manage owner account.") }
_uiState.update { it.copy(errorMessage = context.getString(R.string.chat_error_manage_owner)) }
return false
}
if (actorRole == "admin" && (targetRole == "admin" || targetRole == "owner")) {
_uiState.update { it.copy(errorMessage = "Admin cannot manage admins or owner.") }
_uiState.update { it.copy(errorMessage = context.getString(R.string.chat_error_admin_manage_admin_owner)) }
return false
}
if (action == "transfer_ownership" && targetRole == "owner") {
_uiState.update { it.copy(errorMessage = "Choose another member for ownership transfer.") }
_uiState.update { it.copy(errorMessage = context.getString(R.string.chat_error_transfer_choose_another)) }
return false
}
return true
@@ -965,11 +974,11 @@ class ChatViewModel @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 -> "Server error."
is AppError.Unknown -> "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 -> context.getString(R.string.error_server)
is AppError.Unknown -> context.getString(R.string.error_unknown)
}
}

View File

@@ -114,6 +114,22 @@
<string name="chat_member_dialog_ban_body">Забанить %1$s?</string>
<string name="chat_member_dialog_kick_title">Исключить участника</string>
<string name="chat_member_dialog_kick_body">Исключить %1$s из чата?</string>
<string name="chat_error_voice_too_short">Голосовое сообщение слишком короткое.</string>
<string name="chat_error_delete_for_all_single">Удаление для всех доступно только при выборе одного сообщения.</string>
<string name="chat_error_delete_for_all_own">Удаление для всех доступно только для ваших сообщений.</string>
<string name="chat_info_history_cleared">История чата очищена.</string>
<string name="chat_error_edit_expired">Это сообщение уже нельзя редактировать.</string>
<string name="chat_error_send_restricted">Отправка сообщений в этом чате ограничена.</string>
<string name="chat_restriction_owner_admin">Только owner/admin канала может отправлять сообщения.</string>
<string name="chat_error_action_self">Это действие нельзя применить к себе.</string>
<string name="chat_error_permissions">Недостаточно прав.</string>
<string name="chat_error_owner_only">Только owner может выполнить это действие.</string>
<string name="chat_error_manage_owner">Нельзя управлять аккаунтом owner.</string>
<string name="chat_error_admin_manage_admin_owner">Админ не может управлять админами и owner.</string>
<string name="chat_error_transfer_choose_another">Выберите другого участника для передачи owner.</string>
<string name="chat_voice_hint_slide">Проведите вверх, чтобы закрепить, и влево, чтобы отменить</string>
<string name="chat_voice_hint_locked">Запись закреплена</string>
<string name="chat_title_fallback">Чат #%1$d</string>
<string name="settings_user_fallback">Пользователь</string>
<string name="settings_accounts_header">АККАУНТЫ</string>

View File

@@ -114,6 +114,22 @@
<string name="chat_member_dialog_ban_body">Ban %1$s?</string>
<string name="chat_member_dialog_kick_title">Kick member</string>
<string name="chat_member_dialog_kick_body">Kick %1$s from chat?</string>
<string name="chat_error_voice_too_short">Voice message is too short.</string>
<string name="chat_error_delete_for_all_single">Delete for all is available only for single message selection.</string>
<string name="chat_error_delete_for_all_own">Delete for all is available only for your own messages.</string>
<string name="chat_info_history_cleared">Chat history cleared.</string>
<string name="chat_error_edit_expired">This message can no longer be edited.</string>
<string name="chat_error_send_restricted">Sending is restricted in this chat.</string>
<string name="chat_restriction_owner_admin">Only channel owner/admin can send messages.</string>
<string name="chat_error_action_self">You cannot apply this action to yourself.</string>
<string name="chat_error_permissions">You don\'t have enough permissions.</string>
<string name="chat_error_owner_only">Only owner can perform this action.</string>
<string name="chat_error_manage_owner">You cannot manage owner account.</string>
<string name="chat_error_admin_manage_admin_owner">Admin cannot manage admins or owner.</string>
<string name="chat_error_transfer_choose_another">Choose another member for ownership transfer.</string>
<string name="chat_voice_hint_slide">Slide up to lock, slide left to cancel</string>
<string name="chat_voice_hint_locked">Recording locked</string>
<string name="chat_title_fallback">Chat #%1$d</string>
<string name="settings_user_fallback">User</string>
<string name="settings_accounts_header">ACCOUNTS</string>