mirror of
https://github.com/Novaloop-AG/element-x-android.git
synced 2026-10-31 16:22:49 +00:00
Merge branch 'develop' into renovate/zizmorcore-zizmor-action-0.x
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="call_foreground_service_channel_title_android">"通话进行中"</string>
|
||||
<string name="call_foreground_service_channel_title_android">"正在进行的通话"</string>
|
||||
<string name="call_foreground_service_message_android">"点击以返回通话"</string>
|
||||
<string name="call_foreground_service_title_android">"☎️ 通话中"</string>
|
||||
<string name="call_invalid_audio_device_bluetooth_devices_disabled">"Element Call 不支持在此 Android 版本中使用蓝牙音频设备。请选择其它音频设备。"</string>
|
||||
|
||||
@@ -31,6 +31,6 @@
|
||||
<string name="screen_create_room_space_selection_no_space_option">"Не додавати до простору"</string>
|
||||
<string name="screen_create_room_space_selection_no_space_title">"Головна"</string>
|
||||
<string name="screen_create_room_space_selection_sheet_title">"Додати до простору"</string>
|
||||
<string name="screen_create_room_topic_label">"Тема (необов\'язково)"</string>
|
||||
<string name="screen_create_room_topic_label">"Тематика обговорень (необов’язково)"</string>
|
||||
<string name="screen_create_room_topic_placeholder">"Додати опис…"</string>
|
||||
</resources>
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_deactivate_account_confirmation_dialog_content">"Будь ласка, підтвердіть, що ви хочете деактивувати свій обліковий запис. Ця дія не може бути скасована."</string>
|
||||
<string name="screen_deactivate_account_confirmation_dialog_content">"Підтвердьте, що хочете видалити свій обліковий запис. Цю дію неможливо скасувати."</string>
|
||||
<string name="screen_deactivate_account_delete_all_messages">"Видалити всі мої повідомлення"</string>
|
||||
<string name="screen_deactivate_account_delete_all_messages_notice">"Попередження: майбутні користувачі можуть бачити неповні розмови."</string>
|
||||
<string name="screen_deactivate_account_description">"Деактивація вашого облікового запису%1$s , це буде:"</string>
|
||||
<string name="screen_deactivate_account_description">"Видалення вашого облікового запису %1$s призведе до:"</string>
|
||||
<string name="screen_deactivate_account_description_bold_part">"незворотні"</string>
|
||||
<string name="screen_deactivate_account_list_item_1">"%1$sваш обліковий запис (ви не можете знову увійти, а ваш ідентифікатор не може бути використаний повторно)."</string>
|
||||
<string name="screen_deactivate_account_list_item_1_bold_part">"Назавжди відключити"</string>
|
||||
<string name="screen_deactivate_account_list_item_2">"Видалити вас з усіх чатів."</string>
|
||||
<string name="screen_deactivate_account_list_item_2">"Вилучити вас з усіх бесід."</string>
|
||||
<string name="screen_deactivate_account_list_item_3">"Видаліть інформацію свого облікового запису з нашого сервера ідентифікації."</string>
|
||||
<string name="screen_deactivate_account_list_item_4">"Ваші повідомлення залишатимуться видимими для зареєстрованих користувачів, але недоступними для нових або незареєстрованих користувачів, якщо ви вирішите їх видалити."</string>
|
||||
<string name="screen_deactivate_account_title">"Відключити обліковий запис"</string>
|
||||
<string name="screen_deactivate_account_title">"Видалити обліковий запис"</string>
|
||||
</resources>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_identity_confirmation_cannot_confirm">"Tidak dapat mengonfirmasi?"</string>
|
||||
<string name="screen_identity_confirmation_create_new_recovery_key">"Buat kunci pemulihan baru"</string>
|
||||
<string name="screen_identity_confirmation_subtitle">"Verifikasi perangkat ini untuk menyiapkan perpesanan aman."</string>
|
||||
<string name="screen_identity_confirmation_subtitle">"Pilih cara verifikasi untuk mengatur pengiriman pesan yang aman."</string>
|
||||
<string name="screen_identity_confirmation_title">"Konfirmasi bahwa ini Anda"</string>
|
||||
<string name="screen_identity_confirmation_use_another_device">"Gunakan perangkat lain"</string>
|
||||
<string name="screen_identity_confirmation_use_recovery_key">"Gunakan kunci pemulihan"</string>
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_identity_confirmation_cannot_confirm">"Не можете підтвердити?"</string>
|
||||
<string name="screen_identity_confirmation_create_new_recovery_key">"Створити новий ключ відновлення"</string>
|
||||
<string name="screen_identity_confirmation_subtitle">"Верифікуйте цей пристрій, щоб налаштувати безпечний обмін повідомленнями."</string>
|
||||
<string name="screen_identity_confirmation_title">"Підтвердьте, що це ви"</string>
|
||||
<string name="screen_identity_confirmation_subtitle">"Виберіть спосіб звіряння, щоб налаштувати безпечний обмін повідомленнями."</string>
|
||||
<string name="screen_identity_confirmation_title">"Підтвердьте свою цифрову ідентичність"</string>
|
||||
<string name="screen_identity_confirmation_use_another_device">"Використовуйте інший пристрій"</string>
|
||||
<string name="screen_identity_confirmation_use_recovery_key">"Використовуйте ключ відновлення"</string>
|
||||
<string name="screen_identity_confirmed_subtitle">"Тепер ви можете безпечно читати або надсилати повідомлення, і кожен, з ким ви спілкуєтесь, також може довіряти цьому пристрою."</string>
|
||||
<string name="screen_identity_confirmed_title">"Пристрій перевірено"</string>
|
||||
<string name="screen_identity_confirmed_title">"Пристрій звірено"</string>
|
||||
<string name="screen_identity_use_another_device">"Використовуйте інший пристрій"</string>
|
||||
<string name="screen_identity_waiting_on_other_device">"Чекає на інше пристрій…"</string>
|
||||
<string name="screen_notification_optin_subtitle">"Ви можете змінити свої налаштування пізніше."</string>
|
||||
|
||||
@@ -57,6 +57,7 @@ dependencies {
|
||||
implementation(libs.androidx.datastore.preferences)
|
||||
implementation(libs.haze)
|
||||
implementation(libs.haze.materials)
|
||||
implementation(projects.features.preferences.impl)
|
||||
implementation(projects.features.reportroom.api)
|
||||
implementation(projects.features.rolesandpermissions.api)
|
||||
implementation(projects.libraries.previewutils)
|
||||
|
||||
+5
-18
@@ -41,6 +41,7 @@ import io.element.android.features.invite.api.acceptdecline.AcceptDeclineInviteE
|
||||
import io.element.android.features.invite.api.acceptdecline.AcceptDeclineInviteState
|
||||
import io.element.android.features.leaveroom.api.LeaveRoomEvent
|
||||
import io.element.android.features.leaveroom.api.LeaveRoomState
|
||||
import io.element.android.features.preferences.impl.tasks.MarkRoomAsRead
|
||||
import io.element.android.libraries.architecture.AsyncData
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.featureflag.api.FeatureFlagService
|
||||
@@ -51,11 +52,8 @@ import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.encryption.RecoveryState
|
||||
import io.element.android.libraries.matrix.api.roomlist.RoomList
|
||||
import io.element.android.libraries.matrix.api.roomlist.RoomListFilter
|
||||
import io.element.android.libraries.matrix.api.timeline.ReceiptType
|
||||
import io.element.android.libraries.matrix.ui.safety.rememberHideInvitesAvatar
|
||||
import io.element.android.libraries.preferences.api.store.SessionPreferencesStore
|
||||
import io.element.android.libraries.push.api.battery.BatteryOptimizationState
|
||||
import io.element.android.libraries.push.api.notifications.NotificationCleaner
|
||||
import io.element.android.services.analytics.api.AnalyticsService
|
||||
import io.element.android.services.analytics.api.watchers.AnalyticsColdStartWatcher
|
||||
import io.element.android.services.analyticsproviders.api.trackers.captureInteraction
|
||||
@@ -65,7 +63,6 @@ import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
@@ -79,12 +76,11 @@ class RoomListPresenter(
|
||||
private val roomListDataSource: RoomListDataSource,
|
||||
private val filtersPresenter: Presenter<RoomListFiltersState>,
|
||||
private val searchPresenter: Presenter<RoomListSearchState>,
|
||||
private val sessionPreferencesStore: SessionPreferencesStore,
|
||||
private val analyticsService: AnalyticsService,
|
||||
private val acceptDeclineInvitePresenter: Presenter<AcceptDeclineInviteState>,
|
||||
private val fullScreenIntentPermissionsPresenter: Presenter<FullScreenIntentPermissionsState>,
|
||||
private val batteryOptimizationPresenter: Presenter<BatteryOptimizationState>,
|
||||
private val notificationCleaner: NotificationCleaner,
|
||||
private val markRoomAsRead: MarkRoomAsRead,
|
||||
private val seenInvitesStore: SeenInvitesStore,
|
||||
private val announcementService: AnnouncementService,
|
||||
private val coldStartWatcher: AnalyticsColdStartWatcher,
|
||||
@@ -308,19 +304,10 @@ class RoomListPresenter(
|
||||
}
|
||||
|
||||
private fun CoroutineScope.markAsRead(roomId: RoomId) = launch {
|
||||
notificationCleaner.clearMessagesForRoom(client.sessionId, roomId)
|
||||
client.getRoom(roomId)?.use { room ->
|
||||
room.setUnreadFlag(isUnread = false)
|
||||
val receiptType = if (sessionPreferencesStore.isSendPublicReadReceiptsEnabled().first()) {
|
||||
ReceiptType.READ
|
||||
} else {
|
||||
ReceiptType.READ_PRIVATE
|
||||
markRoomAsRead(roomId)
|
||||
.onSuccess {
|
||||
analyticsService.captureInteraction(name = Interaction.Name.MobileRoomListRoomContextMenuUnreadToggle)
|
||||
}
|
||||
room.markAsRead(receiptType)
|
||||
.onSuccess {
|
||||
analyticsService.captureInteraction(name = Interaction.Name.MobileRoomListRoomContextMenuUnreadToggle)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun CoroutineScope.markAsUnread(roomId: RoomId) = launch {
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
<string name="banner_battery_optimization_submit_android">"Nonaktifkan optimasi"</string>
|
||||
<string name="banner_battery_optimization_title_android">"Notifikasi tidak masuk?"</string>
|
||||
<string name="banner_set_up_recovery_content">"Buat kunci pemulihan baru yang dapat digunakan untuk memulihkan riwayat pesan terenkripsi Anda jika Anda kehilangan akses ke perangkat Anda."</string>
|
||||
<string name="banner_set_up_recovery_submit">"Siapkan pemulihan"</string>
|
||||
<string name="banner_set_up_recovery_title">"Siapkan pemulihan"</string>
|
||||
<string name="banner_set_up_recovery_submit">"Siapkan Kunci pemulihan"</string>
|
||||
<string name="banner_set_up_recovery_title">"Cadangkan obrolan Anda"</string>
|
||||
<string name="confirm_recovery_key_banner_message">"Konfirmasikan kunci pemulihan Anda untuk mempertahankan akses ke penyimpanan kunci dan riwayat pesan Anda."</string>
|
||||
<string name="confirm_recovery_key_banner_primary_button_title">"Masukkan kunci pemulihan Anda"</string>
|
||||
<string name="confirm_recovery_key_banner_secondary_button_title">"Lupa kunci pemulihan Anda?"</string>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<string name="banner_new_sound_message">"O seu ping de notificação foi atualizado—mais suave, mais rápido, e menos disruptivo."</string>
|
||||
<string name="banner_new_sound_title">"Recarregamos seus sons"</string>
|
||||
<string name="banner_set_up_recovery_content">"Recupere sua identidade criptográfica e o histórico de mensagens com uma chave de recuperação caso você perda todos os dispositivos existentes."</string>
|
||||
<string name="banner_set_up_recovery_submit">"Configurar a recuperação"</string>
|
||||
<string name="banner_set_up_recovery_submit">"Receber chave de recuperação"</string>
|
||||
<string name="banner_set_up_recovery_title">"Configure a recuperação para proteger sua conta"</string>
|
||||
<string name="confirm_recovery_key_banner_message">"Confirme sua chave de recuperação para manter o acesso ao seu armazenamento de chaves e histórico de mensagens."</string>
|
||||
<string name="confirm_recovery_key_banner_primary_button_title">"Digite sua chave de recuperação"</string>
|
||||
|
||||
@@ -5,15 +5,15 @@
|
||||
<string name="banner_battery_optimization_title_android">"Не надходять сповіщення?"</string>
|
||||
<string name="banner_new_sound_message">"Ваш сигнал сповіщень оновлено — він став чіткішим, швидшим і не таким надокучливим."</string>
|
||||
<string name="banner_new_sound_title">"Ми оновили ваші звуки"</string>
|
||||
<string name="banner_set_up_recovery_content">"Відновіть свою криптографічну ідентичність та історію повідомлень за допомогою ключа відновлення, якщо ви втратили всі наявні пристрої."</string>
|
||||
<string name="banner_set_up_recovery_submit">"Налаштувати відновлення"</string>
|
||||
<string name="banner_set_up_recovery_title">"Налаштуйте відновлення для захисту свого облікового запису"</string>
|
||||
<string name="banner_set_up_recovery_content">"Ваші бесіди автоматично резервуються з використанням наскрізного шифрування. Щоб відновити цю резервну копію та зберегти свою цифрову ідентичність у разі втрати доступу до всіх своїх пристроїв, вам знадобиться ключ відновлення."</string>
|
||||
<string name="banner_set_up_recovery_submit">"Отримати ключ відновлення"</string>
|
||||
<string name="banner_set_up_recovery_title">"Створити резервну копію своїх бесід"</string>
|
||||
<string name="confirm_recovery_key_banner_message">"Підтвердіть свій ключ відновлення, щоб мати доступ до сховища ключів та історії повідомлень."</string>
|
||||
<string name="confirm_recovery_key_banner_primary_button_title">"Введіть ключ відновлення"</string>
|
||||
<string name="confirm_recovery_key_banner_secondary_button_title">"Забули ключ відновлення?"</string>
|
||||
<string name="confirm_recovery_key_banner_title">"Ваше сховище ключів не синхронізовано"</string>
|
||||
<string name="full_screen_intent_banner_message">"Щоб ніколи не пропустити важливий виклик, змініть налаштування, щоб увімкнути повноекранні сповіщення, коли телефон заблоковано."</string>
|
||||
<string name="full_screen_intent_banner_title">"Покращуйте досвід дзвінків"</string>
|
||||
<string name="full_screen_intent_banner_title">"Покращуйте якість викликів"</string>
|
||||
<string name="screen_home_tab_chats">"Бесіди"</string>
|
||||
<string name="screen_home_tab_spaces">"Простори"</string>
|
||||
<string name="screen_invites_decline_chat_message">"Ви впевнені, що хочете відхилити запрошення приєднатися до %1$s?"</string>
|
||||
@@ -51,6 +51,6 @@
|
||||
<string name="screen_roomlist_mark_as_unread">"Позначити непрочитаним"</string>
|
||||
<string name="screen_roomlist_tombstoned_room_description">"Цю кімнату оновлено"</string>
|
||||
<string name="screen_roomlist_your_spaces">"Ваші простори"</string>
|
||||
<string name="session_verification_banner_message">"Схоже, ви використовуєте новий пристрій. Щоб отримати доступ до зашифрованих повідомлень, підтвердьте особу за допомогою іншого пристрою."</string>
|
||||
<string name="session_verification_banner_message">"Здається, ви використовуєте новий пристрій. Звірте його за допомогою іншого пристрою, щоб отримати доступ до своїх зашифрованих повідомлень."</string>
|
||||
<string name="session_verification_banner_title">"Підтвердьте, що це ви"</string>
|
||||
</resources>
|
||||
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (c) 2026 Element Creations Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.features.home.impl.roomlist
|
||||
|
||||
import io.element.android.features.preferences.impl.tasks.MarkRoomAsRead
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
|
||||
class FakeMarkRoomAsRead(
|
||||
private val invokeLambda: suspend (RoomId) -> Result<Unit> = { Result.success(Unit) },
|
||||
) : MarkRoomAsRead {
|
||||
val invokedRoomIds = mutableListOf<RoomId>()
|
||||
|
||||
override suspend fun invoke(roomId: RoomId): Result<Unit> {
|
||||
invokedRoomIds.add(roomId)
|
||||
return invokeLambda(roomId)
|
||||
}
|
||||
}
|
||||
+31
-2
@@ -30,6 +30,7 @@ import io.element.android.features.invite.api.acceptdecline.anAcceptDeclineInvit
|
||||
import io.element.android.features.invite.test.InMemorySeenInvitesStore
|
||||
import io.element.android.features.leaveroom.api.LeaveRoomEvent
|
||||
import io.element.android.features.leaveroom.api.LeaveRoomState
|
||||
import io.element.android.features.preferences.impl.tasks.MarkRoomAsRead
|
||||
import io.element.android.features.rageshake.test.logs.FakeAnnouncementService
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.dateformatter.api.DateFormatter
|
||||
@@ -427,11 +428,17 @@ class RoomListPresenterTest {
|
||||
val notificationCleaner = FakeNotificationCleaner(
|
||||
clearMessagesForRoomLambda = clearMessagesForRoomLambda,
|
||||
)
|
||||
val markRoomAsRead = createTestMarkRoomAsRead(
|
||||
client = matrixClient,
|
||||
notificationCleaner = notificationCleaner,
|
||||
sessionPreferencesStore = sessionPreferencesStore,
|
||||
)
|
||||
val presenter = createRoomListPresenter(
|
||||
client = matrixClient,
|
||||
sessionPreferencesStore = sessionPreferencesStore,
|
||||
analyticsService = analyticsService,
|
||||
notificationCleaner = notificationCleaner,
|
||||
markRoomAsRead = markRoomAsRead,
|
||||
)
|
||||
presenter.test {
|
||||
val initialState = awaitItem()
|
||||
@@ -623,6 +630,24 @@ class RoomListPresenterTest {
|
||||
}
|
||||
}
|
||||
|
||||
private fun createTestMarkRoomAsRead(
|
||||
client: MatrixClient,
|
||||
notificationCleaner: NotificationCleaner,
|
||||
sessionPreferencesStore: SessionPreferencesStore,
|
||||
): MarkRoomAsRead = FakeMarkRoomAsRead { roomId ->
|
||||
notificationCleaner.clearMessagesForRoom(client.sessionId, roomId)
|
||||
val room = client.getRoom(roomId) ?: return@FakeMarkRoomAsRead Result.failure(IllegalStateException("Room not found"))
|
||||
room.use {
|
||||
it.setUnreadFlag(isUnread = false)
|
||||
val receiptType = if (sessionPreferencesStore.isSendPublicReadReceiptsEnabled().first()) {
|
||||
ReceiptType.READ
|
||||
} else {
|
||||
ReceiptType.READ_PRIVATE
|
||||
}
|
||||
it.markAsRead(receiptType)
|
||||
}
|
||||
}
|
||||
|
||||
private fun TestScope.createRoomListPresenter(
|
||||
client: MatrixClient = FakeMatrixClient(),
|
||||
leaveRoomState: LeaveRoomState = aLeaveRoomState(),
|
||||
@@ -638,6 +663,7 @@ class RoomListPresenterTest {
|
||||
seenInvitesStore: SeenInvitesStore = InMemorySeenInvitesStore(),
|
||||
announcementService: AnnouncementService = FakeAnnouncementService(),
|
||||
featureFlagService: FeatureFlagService = FakeFeatureFlagService(),
|
||||
markRoomAsRead: MarkRoomAsRead? = null,
|
||||
) = RoomListPresenter(
|
||||
client = client,
|
||||
leaveRoomPresenter = { leaveRoomState },
|
||||
@@ -654,14 +680,17 @@ class RoomListPresenterTest {
|
||||
analyticsService = FakeAnalyticsService(),
|
||||
),
|
||||
searchPresenter = searchPresenter,
|
||||
sessionPreferencesStore = sessionPreferencesStore,
|
||||
filtersPresenter = filtersPresenter,
|
||||
spaceFiltersPresenter = spaceFiltersPresenter,
|
||||
analyticsService = analyticsService,
|
||||
acceptDeclineInvitePresenter = acceptDeclineInvitePresenter,
|
||||
fullScreenIntentPermissionsPresenter = { aFullScreenIntentPermissionsState() },
|
||||
batteryOptimizationPresenter = { aBatteryOptimizationState() },
|
||||
notificationCleaner = notificationCleaner,
|
||||
markRoomAsRead = markRoomAsRead ?: createTestMarkRoomAsRead(
|
||||
client = client,
|
||||
notificationCleaner = notificationCleaner,
|
||||
sessionPreferencesStore = sessionPreferencesStore,
|
||||
),
|
||||
seenInvitesStore = seenInvitesStore,
|
||||
announcementService = announcementService,
|
||||
coldStartWatcher = FakeAnalyticsColdStartWatcher(),
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_invite_users_already_a_member">"Уже учасник"</string>
|
||||
<string name="screen_invite_users_already_invited">"Уже запрошені"</string>
|
||||
<string name="screen_invite_users_confirm_dialog_subtitle_multiple_users">"Наразі у вас немає чатів із цими контактами. Підтвердьте запрошення їх до цієї кімнати, перш ніж продовжувати."</string>
|
||||
<string name="screen_invite_users_confirm_dialog_subtitle_one_user">"Наразі у вас немає чатів із цим контактом. Підтвердьте запрошення до цієї кімнати, перш ніж продовжувати."</string>
|
||||
<string name="screen_invite_users_confirm_dialog_subtitle_multiple_users">"Наразі у вас немає бесід з цими контактами. Підтвердьте запрошення їх до цієї кімнати, перш ніж продовжувати."</string>
|
||||
<string name="screen_invite_users_confirm_dialog_subtitle_one_user">"Наразі у вас немає бесід із цим контактом. Підтвердьте запрошення до цієї кімнати, перш ніж продовжувати."</string>
|
||||
<string name="screen_invite_users_confirm_dialog_title_mutiple_users">"Запросити нових контактів до цієї кімнати?"</string>
|
||||
<string name="screen_invite_users_confirm_dialog_title_one_user">"Запросити нового контакта до цієї кімнати?"</string>
|
||||
</resources>
|
||||
|
||||
@@ -15,6 +15,10 @@
|
||||
<string name="screen_join_room_fail_reason">"Ruangan ini hanya untuk undangan atau mungkin ada pembatasan akses pada tingkat space."</string>
|
||||
<string name="screen_join_room_forget_action">"Lupa"</string>
|
||||
<string name="screen_join_room_invite_required_message">"Anda memerlukan undangan untuk bergabung dalam ruangan ini"</string>
|
||||
<string name="screen_join_room_invited_by">
|
||||
"Diundang oleh "
|
||||
<userName/>
|
||||
</string>
|
||||
<string name="screen_join_room_join_action">"Gabung"</string>
|
||||
<string name="screen_join_room_join_restricted_message">"Anda mungkin perlu diundang atau menjadi anggota space untuk bergabung."</string>
|
||||
<string name="screen_join_room_knock_action">"Ketuk untuk bergabung"</string>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="leave_conversation_alert_subtitle">"Czy na pewno chcesz opuścić tę konwersację? Konwersacja nie jest publiczna i nie będziesz mógł dołączyć ponownie bez zaproszenia."</string>
|
||||
<string name="leave_room_alert_empty_subtitle">"Jesteś pewien, że chcesz opuścić ten pokój? Jesteś tu jedyną osobą. Jeśli wyjdziesz, nikt nie będzie mógł dołączyć, w tym Ty."</string>
|
||||
<string name="leave_room_alert_empty_subtitle">"Czy na pewno chcesz opuścić ten pokój? Jesteś tu jedyną osobą. Jeśli wyjdziesz, nikt nie będzie mógł dołączyć, w tym Ty."</string>
|
||||
<string name="leave_room_alert_private_subtitle">"Czy na pewno chcesz opuścić ten pokój? Ten pokój nie jest publiczny i nie będziesz mógł do niego wrócić bez zaproszenia."</string>
|
||||
<string name="leave_room_alert_select_new_owner_action">"Wybierz właścicieli"</string>
|
||||
<string name="leave_room_alert_select_new_owner_subtitle">"Jesteś jedynym właścicielem tego pokoju. Musisz przenieść własność na kogoś innego, zanim go opuścisz."</string>
|
||||
<string name="leave_room_alert_select_new_owner_title">"Przenieś własność"</string>
|
||||
<string name="leave_room_alert_subtitle">"Jesteś pewien, że chcesz wyjść z tego pokoju?"</string>
|
||||
<string name="leave_room_alert_subtitle">"Czy na pewno chcesz wyjść z tego pokoju?"</string>
|
||||
</resources>
|
||||
|
||||
+4
@@ -9,6 +9,7 @@
|
||||
|
||||
package io.element.android.features.linknewdevice.impl.screens.scan
|
||||
|
||||
import android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.ui.platform.LocalInspectionMode
|
||||
@@ -25,9 +26,11 @@ import io.element.android.tests.testutils.ensureCalledOnce
|
||||
import io.element.android.tests.testutils.pressBackKey
|
||||
import io.element.android.tests.testutils.robolectric.RobolectricTest
|
||||
import org.junit.Test
|
||||
import org.robolectric.annotation.Config
|
||||
|
||||
class ScanQrCodeViewTest : RobolectricTest() {
|
||||
@Test
|
||||
@Config(sdk = [UPSIDE_DOWN_CAKE])
|
||||
fun `on back pressed - calls the expected callback`() = runAndroidComposeUiTest {
|
||||
val eventRecorder = EventsRecorder<ScanQrCodeEvent>(expectEvents = false)
|
||||
ensureCalledOnce { callback ->
|
||||
@@ -42,6 +45,7 @@ class ScanQrCodeViewTest : RobolectricTest() {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Config(sdk = [UPSIDE_DOWN_CAKE])
|
||||
fun `try again button clicked - emits the expected event`() = runAndroidComposeUiTest {
|
||||
val eventRecorder = EventsRecorder<ScanQrCodeEvent>()
|
||||
setView(
|
||||
|
||||
@@ -23,7 +23,7 @@ Pilih sesuatu yang mudah untuk diingat. Jika Anda lupa PIN ini, Anda akan dikelu
|
||||
<string name="screen_app_lock_setup_pin_mismatch_dialog_content">"Silakan masukkan PIN yang sama dua kali"</string>
|
||||
<string name="screen_app_lock_setup_pin_mismatch_dialog_title">"PIN tidak cocok"</string>
|
||||
<string name="screen_app_lock_signout_alert_message">"Anda harus masuk ulang dan membuat PIN baru untuk melanjutkan"</string>
|
||||
<string name="screen_app_lock_signout_alert_title">"Anda sedang dikeluarkan"</string>
|
||||
<string name="screen_app_lock_signout_alert_title">"Perangkat ini sedang dilepas"</string>
|
||||
<plurals name="screen_app_lock_subtitle">
|
||||
<item quantity="other">"Anda memiliki %1$d percobaan lagi untuk membuka kunci"</item>
|
||||
</plurals>
|
||||
|
||||
@@ -23,7 +23,7 @@ Escolha algo memorável. Se você esquecer este PIN, você será desconectado do
|
||||
<string name="screen_app_lock_setup_pin_mismatch_dialog_content">"Por favor, digite o mesmo PIN duas vezes"</string>
|
||||
<string name="screen_app_lock_setup_pin_mismatch_dialog_title">"Os PINs não correspondem"</string>
|
||||
<string name="screen_app_lock_signout_alert_message">"Você terá que entrar novamente e criar um PIN novo para continuar"</string>
|
||||
<string name="screen_app_lock_signout_alert_title">"Você está sendo desconectado"</string>
|
||||
<string name="screen_app_lock_signout_alert_title">"Este dispositivo está sendo removido"</string>
|
||||
<plurals name="screen_app_lock_subtitle">
|
||||
<item quantity="one">"Você tem %1$d tentativa de desbloqueio"</item>
|
||||
<item quantity="other">"Você tem %1$d tentativas de desbloqueio"</item>
|
||||
@@ -34,5 +34,5 @@ Escolha algo memorável. Se você esquecer este PIN, você será desconectado do
|
||||
</plurals>
|
||||
<string name="screen_app_lock_use_biometric_android">"Usar biometria"</string>
|
||||
<string name="screen_app_lock_use_pin_android">"Usar PIN"</string>
|
||||
<string name="screen_signout_in_progress_dialog_content">"Saindo…"</string>
|
||||
<string name="screen_signout_in_progress_dialog_content">"Removendo dispositivo…"</string>
|
||||
</resources>
|
||||
|
||||
@@ -15,15 +15,15 @@
|
||||
<string name="screen_app_lock_setup_biometric_unlock_subtitle">"Заощаджуйте час і використовуйте %1$s для розблокування застосунку щоразу"</string>
|
||||
<string name="screen_app_lock_setup_choose_pin">"Виберіть PIN-код"</string>
|
||||
<string name="screen_app_lock_setup_confirm_pin">"Підтвердити PIN-код"</string>
|
||||
<string name="screen_app_lock_setup_pin_context">"Заблокуйте %1$s, щоб додати додаткову безпеку вашим чатам.
|
||||
<string name="screen_app_lock_setup_pin_context">"Додаткове блокування %1$s поліпшить захист ваших бесід.
|
||||
|
||||
Виберіть щось, що запам\'ятовується. Але якщо ви забудете PIN-код, ви вийдете з застосунку."</string>
|
||||
Виберіть щось, що запам’ятовується. Але якщо ви забудете PIN-код, ви вийдете із застосунку."</string>
|
||||
<string name="screen_app_lock_setup_pin_forbidden_dialog_content">"Ви не можете вибрати його своїм PIN-кодом з міркувань безпеки"</string>
|
||||
<string name="screen_app_lock_setup_pin_forbidden_dialog_title">"Виберіть інший PIN-код"</string>
|
||||
<string name="screen_app_lock_setup_pin_mismatch_dialog_content">"Будь ласка, введіть один і той самий PIN-код двічі"</string>
|
||||
<string name="screen_app_lock_setup_pin_mismatch_dialog_title">"PIN-коди не збігаються"</string>
|
||||
<string name="screen_app_lock_signout_alert_message">"Щоб продовжити, вам потрібно повторно ввійти та створити новий PIN-код"</string>
|
||||
<string name="screen_app_lock_signout_alert_title">"Ви виходите з системи"</string>
|
||||
<string name="screen_app_lock_signout_alert_title">"Цей пристрій вилучається"</string>
|
||||
<plurals name="screen_app_lock_subtitle">
|
||||
<item quantity="one">"Ви маєте %1$d спробу"</item>
|
||||
<item quantity="few">"Ви маєте %1$d спроби"</item>
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
<string name="screen_missing_key_backup_step_5">"Επιστρέψτε στο %1$s"</string>
|
||||
<string name="screen_missing_key_backup_title">"Ενεργοποιήστε την αποθήκευση κλειδιών σας πριν προχωρήσετε στο %1$s"</string>
|
||||
<string name="screen_onboarding_app_version">"Έκδοση %1$s"</string>
|
||||
<string name="screen_onboarding_checking_account">"Έλεγχος λογαριασμού"</string>
|
||||
<string name="screen_onboarding_sign_in_manually">"Σύνδεση χειροκίνητα"</string>
|
||||
<string name="screen_onboarding_sign_in_to">"Συνδέσου στο %1$s"</string>
|
||||
<string name="screen_onboarding_sign_in_with_qr_code">"Συνδέσου με κωδικό QR"</string>
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
<string name="screen_change_server_subtitle">"Qual é o endereço do seu servidor?"</string>
|
||||
<string name="screen_change_server_title">"Selecione seu servidor"</string>
|
||||
<string name="screen_create_account_title">"Criar conta"</string>
|
||||
<string name="screen_login_error_deactivated_account">"Essa conta foi desativada."</string>
|
||||
<string name="screen_login_error_deactivated_account">"Essa conta foi apagada."</string>
|
||||
<string name="screen_login_error_invalid_credentials">"Nome de usuário e/ou senha incorretos"</string>
|
||||
<string name="screen_login_error_invalid_user_id">"Esse não é um identificador de usuário válido. Formato esperado: \'@usuário:servidor.org\'"</string>
|
||||
<string name="screen_login_error_refresh_tokens">"Este servidor está configurado para usar tokens recarregados. Não há suporte a eles ao entrar por uma senha."</string>
|
||||
|
||||
@@ -51,9 +51,9 @@
|
||||
<string name="screen_onboarding_sign_in_with_qr_code">"Увійти за допомогою QR-коду"</string>
|
||||
<string name="screen_onboarding_sign_up">"Створити обліковий запис"</string>
|
||||
<string name="screen_onboarding_welcome_back">"З поверненням!"</string>
|
||||
<string name="screen_onboarding_welcome_message">"Ласкаво просимо до найшвидшого %1$s. Заряджений для швидкості та простоти."</string>
|
||||
<string name="screen_onboarding_welcome_subtitle">"Ласкаво просимо до %1$s. Заряджений, для швидкості та простоти."</string>
|
||||
<string name="screen_onboarding_welcome_title">"Будьте у своєму element"</string>
|
||||
<string name="screen_onboarding_welcome_message">"Вітаємо в %1$s. Сфокусованому на швидкості та простоті."</string>
|
||||
<string name="screen_onboarding_welcome_subtitle">"Вітаємо у %1$s. Сфокусованому на швидкості та простоті."</string>
|
||||
<string name="screen_onboarding_welcome_title">"Спілкуйтесь елементарно"</string>
|
||||
<string name="screen_qr_code_login_connecting_subtitle">"Встановлення безпечного з\'єднання"</string>
|
||||
<string name="screen_qr_code_login_connection_note_secure_state_description">"Не вдалося встановити безпечне з\'єднання з новим пристроєм. Ваші наявні пристрої досі в безпеці, і вам не потрібно про них турбуватися."</string>
|
||||
<string name="screen_qr_code_login_connection_note_secure_state_list_header">"Що тепер?"</string>
|
||||
|
||||
@@ -5,14 +5,14 @@
|
||||
<string name="screen_signout_confirmation_dialog_title">"Hapus device dari akun"</string>
|
||||
<string name="screen_signout_in_progress_dialog_content">"Mengeluarkan device dari akun…"</string>
|
||||
<string name="screen_signout_key_backup_disabled_subtitle">"Anda akan keluar dari sesi terakhir Anda. Jika Anda keluar sekarang, Anda akan kehilangan akses ke pesan terenkripsi Anda."</string>
|
||||
<string name="screen_signout_key_backup_disabled_title">"Anda telah menonaktifkan pencadangan"</string>
|
||||
<string name="screen_signout_key_backup_offline_subtitle">"Kunci Anda masih dicadangkan saat Anda luring. Sambungkan kembali sehingga kunci Anda dapat dicadangkan sebelum keluar."</string>
|
||||
<string name="screen_signout_key_backup_disabled_title">"Anda akan segera kehilangan akses ke obrolan terenkripsi Anda."</string>
|
||||
<string name="screen_signout_key_backup_offline_subtitle">"Kunci Anda masih dalam proses pencadangan saat Anda offline. Sambungkan kembali agar kunci Anda dapat dicadangkan sebelum Anda menghapus perangkat ini."</string>
|
||||
<string name="screen_signout_key_backup_offline_title">"Kunci Anda masih dicadangkan"</string>
|
||||
<string name="screen_signout_key_backup_ongoing_subtitle">"Mohon tunggu hingga proses ini selesai sebelum keluar."</string>
|
||||
<string name="screen_signout_key_backup_ongoing_subtitle">"Harap tunggu hingga proses ini selesai sebelum melepas perangkat ini."</string>
|
||||
<string name="screen_signout_key_backup_ongoing_title">"Kunci Anda masih dicadangkan"</string>
|
||||
<string name="screen_signout_preference_item">"Hapus device dari akun"</string>
|
||||
<string name="screen_signout_recovery_disabled_subtitle">"Anda akan keluar dari sesi Anda yang terakhir. Jika Anda keluar sekarang, Anda akan kehilangan akses ke pesan terenkripsi Anda."</string>
|
||||
<string name="screen_signout_recovery_disabled_title">"Pemulihan belum disiapkan"</string>
|
||||
<string name="screen_signout_recovery_disabled_title">"Anda akan segera kehilangan akses ke obrolan terenkripsi Anda."</string>
|
||||
<string name="screen_signout_save_recovery_key_subtitle">"Anda akan keluar dari sesi terakhir Anda. Jika Anda keluar sekarang, Anda mungkin kehilangan akses ke pesan terenkripsi Anda."</string>
|
||||
<string name="screen_signout_save_recovery_key_title">"Apakah Anda sudah menyimpan kunci pemulihan Anda?"</string>
|
||||
<string name="screen_signout_save_recovery_key_title">"Pastikan Anda memiliki akses ke kunci pemulihan sebelum mencabut perangkat ini."</string>
|
||||
</resources>
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_signout_confirmation_dialog_content">"Você tem certeza que deseja sair?"</string>
|
||||
<string name="screen_signout_confirmation_dialog_submit">"Sair"</string>
|
||||
<string name="screen_signout_confirmation_dialog_title">"Sair"</string>
|
||||
<string name="screen_signout_in_progress_dialog_content">"Saindo…"</string>
|
||||
<string name="screen_signout_confirmation_dialog_content">"Você tem certeza que deseja remover este dispositivo?"</string>
|
||||
<string name="screen_signout_confirmation_dialog_submit">"Remover este dispositivo"</string>
|
||||
<string name="screen_signout_confirmation_dialog_title">"Remover este dispositivo"</string>
|
||||
<string name="screen_signout_in_progress_dialog_content">"Removendo dispositivo…"</string>
|
||||
<string name="screen_signout_key_backup_disabled_subtitle">"Você está prestes a sair da sua última sessão. Se você sair agora, perderá o acesso às suas mensagens criptografadas."</string>
|
||||
<string name="screen_signout_key_backup_disabled_title">"Você desativou o backup"</string>
|
||||
<string name="screen_signout_key_backup_offline_subtitle">"O backup das suas chaves ainda estava sendo feito quando você ficou off-line. Reconecte-se para que você possa fazer o backup de suas chaves antes de sair."</string>
|
||||
<string name="screen_signout_key_backup_offline_title">"O backup das suas chaves ainda está em andamento"</string>
|
||||
<string name="screen_signout_key_backup_ongoing_subtitle">"Aguarde até que isso seja concluído antes de sair."</string>
|
||||
<string name="screen_signout_key_backup_ongoing_title">"O backup das suas chaves ainda está em andamento"</string>
|
||||
<string name="screen_signout_preference_item">"Sair"</string>
|
||||
<string name="screen_signout_preference_item">"Remover este dispositivo"</string>
|
||||
<string name="screen_signout_recovery_disabled_subtitle">"Você está prestes a sair da sua última sessão. Se você sair agora, perderá o acesso às suas mensagens criptografadas."</string>
|
||||
<string name="screen_signout_recovery_disabled_title">"A recuperação não está configurada"</string>
|
||||
<string name="screen_signout_recovery_disabled_title">"Você está prestes a perder o acesso às suas conversas criptografadas"</string>
|
||||
<string name="screen_signout_save_recovery_key_subtitle">"Você está prestes a sair da sua última sessão. Se você sair agora, poderá perder o acesso às suas mensagens criptografadas."</string>
|
||||
<string name="screen_signout_save_recovery_key_title">"Você salvou sua chave de recuperação?"</string>
|
||||
</resources>
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_signout_confirmation_dialog_content">"Ви впевнені, що хочете видалити цей пристрій?"</string>
|
||||
<string name="screen_signout_confirmation_dialog_submit">"Вийти"</string>
|
||||
<string name="screen_signout_confirmation_dialog_title">"Вийти"</string>
|
||||
<string name="screen_signout_confirmation_dialog_submit">"Вилучити цей пристрій"</string>
|
||||
<string name="screen_signout_confirmation_dialog_title">"Вилучити цей пристрій"</string>
|
||||
<string name="screen_signout_in_progress_dialog_content">"Видалення пристрою…"</string>
|
||||
<string name="screen_signout_key_backup_disabled_subtitle">"Ви збираєтеся вийти зі свого останнього сеансу. Якщо ви вийдете зараз, ви втратите доступ до своїх зашифрованих повідомлень."</string>
|
||||
<string name="screen_signout_key_backup_disabled_title">"Ви вимкнули резервне копіювання"</string>
|
||||
<string name="screen_signout_key_backup_offline_subtitle">"Коли ви вийшли з мережі, резервна копія ваших ключів все ще створювалася. Повторно під\'єднайтеся, щоб зберегти резервну копію ключів перед виходом."</string>
|
||||
<string name="screen_signout_key_backup_disabled_subtitle">"Це ваш єдиний пристрій. Якщо ви його вилучите, вам знадобиться ключ відновлення, щоб підтвердити свою цифрову ідентичність і відновити зашифровані бесіди під час наступного входу."</string>
|
||||
<string name="screen_signout_key_backup_disabled_title">"Ви втратите доступ до своїх зашифрованих бесід"</string>
|
||||
<string name="screen_signout_key_backup_offline_subtitle">"Резервні копії ваших ключів продовжували створюватися після вашого виходу з мережі. Під\'єднайтеся знову, щоб створити резервні копії ключів, перш ніж вилучати цей пристрій."</string>
|
||||
<string name="screen_signout_key_backup_offline_title">"Резервне копіювання ваших ключів ще триває"</string>
|
||||
<string name="screen_signout_key_backup_ongoing_subtitle">"Дочекайтеся завершення процесу, перш ніж вийти."</string>
|
||||
<string name="screen_signout_key_backup_ongoing_subtitle">"Дочекайтесь завершення, перш ніж вилучити цей пристрій."</string>
|
||||
<string name="screen_signout_key_backup_ongoing_title">"Резервне копіювання ваших ключів ще триває"</string>
|
||||
<string name="screen_signout_preference_item">"Вийти"</string>
|
||||
<string name="screen_signout_recovery_disabled_subtitle">"Ви збираєтеся вийти зі свого останнього сеансу. Якщо ви вийдете зараз, ви втратите доступ до своїх зашифрованих повідомлень."</string>
|
||||
<string name="screen_signout_recovery_disabled_title">"Відновлення не налаштовано"</string>
|
||||
<string name="screen_signout_save_recovery_key_subtitle">"Ви збираєтеся вийти зі свого останнього сеансу. Якщо вийти зараз, ви можете втратити доступ до зашифрованих повідомлень."</string>
|
||||
<string name="screen_signout_save_recovery_key_title">"Ви зберегли ключ відновлення?"</string>
|
||||
<string name="screen_signout_preference_item">"Вилучити цей пристрій"</string>
|
||||
<string name="screen_signout_recovery_disabled_subtitle">"Це ваш єдиний пристрій. Якщо ви вилучите його, вам знадобиться ключ відновлення, щоб підтвердити свою цифрову ідентичність і відновити зашифровані бесіди під час наступного входу."</string>
|
||||
<string name="screen_signout_recovery_disabled_title">"Ви втратите доступ до своїх зашифрованих бесід"</string>
|
||||
<string name="screen_signout_save_recovery_key_subtitle">"Це ваш єдиний пристрій. Якщо ви його вилучите, вам знадобиться ключ відновлення, щоб підтвердити свою цифрову ідентичність і відновити зашифровані бесіди під час наступного входу."</string>
|
||||
<string name="screen_signout_save_recovery_key_title">"Переконайтеся, що у вас є доступ до ключа відновлення, перш ніж вилучити цей пристрій"</string>
|
||||
</resources>
|
||||
|
||||
+9
-1
@@ -43,6 +43,7 @@ fun TimelineEventTimestampView(
|
||||
event: TimelineItem.Event,
|
||||
eventSink: (TimelineEvent.TimelineItemEvent) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
isLayoutDirectionMismatched: Boolean = false,
|
||||
) {
|
||||
val formattedTime = event.sentTime
|
||||
val hasError = event.failedToSend
|
||||
@@ -77,9 +78,16 @@ fun TimelineEventTimestampView(
|
||||
else -> Modifier
|
||||
}
|
||||
}
|
||||
|
||||
val padding = if (!isLayoutDirectionMismatched) {
|
||||
PaddingValues(start = TimelineEventTimestampViewDefaults.spacing)
|
||||
} else {
|
||||
PaddingValues(end = TimelineEventTimestampViewDefaults.spacing)
|
||||
}
|
||||
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.padding(PaddingValues(start = TimelineEventTimestampViewDefaults.spacing))
|
||||
.padding(padding)
|
||||
// For a better click target, make the corners rounded
|
||||
.clip(RoundedCornerShape(8.dp))
|
||||
.then(clickableModifier)
|
||||
|
||||
+191
-16
@@ -39,7 +39,9 @@ import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.graphicsLayer
|
||||
import androidx.compose.ui.platform.LocalLayoutDirection
|
||||
import androidx.compose.ui.platform.LocalViewConfiguration
|
||||
import androidx.compose.ui.platform.ViewConfiguration
|
||||
import androidx.compose.ui.res.pluralStringResource
|
||||
@@ -49,9 +51,12 @@ import androidx.compose.ui.semantics.hideFromAccessibility
|
||||
import androidx.compose.ui.semantics.isTraversalGroup
|
||||
import androidx.compose.ui.semantics.semantics
|
||||
import androidx.compose.ui.semantics.traversalIndex
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextDirection
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.DpOffset
|
||||
import androidx.compose.ui.unit.IntOffset
|
||||
import androidx.compose.ui.unit.LayoutDirection
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.zIndex
|
||||
import androidx.constraintlayout.compose.ConstrainScope
|
||||
@@ -68,12 +73,14 @@ import io.element.android.features.messages.impl.timeline.components.receipt.Rea
|
||||
import io.element.android.features.messages.impl.timeline.components.receipt.TimelineItemReadReceiptView
|
||||
import io.element.android.features.messages.impl.timeline.model.TimelineItem
|
||||
import io.element.android.features.messages.impl.timeline.model.TimelineItemGroupPosition
|
||||
import io.element.android.features.messages.impl.timeline.model.TimelineItemReactions
|
||||
import io.element.android.features.messages.impl.timeline.model.TimelineItemThreadInfo
|
||||
import io.element.android.features.messages.impl.timeline.model.bubble.BubbleState
|
||||
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemImageContent
|
||||
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemLocationContent
|
||||
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemPollContent
|
||||
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemStickerContent
|
||||
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemTextContent
|
||||
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemVideoContent
|
||||
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemVoiceContent
|
||||
import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemImageContent
|
||||
@@ -91,6 +98,7 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarSize
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarType
|
||||
import io.element.android.libraries.designsystem.modifiers.niceClickable
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||
import io.element.android.libraries.designsystem.preview.PreviewWithExtraLargeHeight
|
||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||
import io.element.android.libraries.designsystem.preview.USER_NAME_ALICE
|
||||
import io.element.android.libraries.designsystem.swipe.SwipeableActionsState
|
||||
@@ -106,6 +114,7 @@ import io.element.android.libraries.matrix.api.timeline.item.EmbeddedEventInfo
|
||||
import io.element.android.libraries.matrix.api.timeline.item.ThreadSummary
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.EventOrTransactionId
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.MessageContent
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.MessageShield
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.ProfileDetails
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.TextMessageType
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.getAvatarUrl
|
||||
@@ -122,7 +131,9 @@ import io.element.android.libraries.testtags.testTag
|
||||
import io.element.android.libraries.ui.strings.CommonPlurals
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
import io.element.android.libraries.ui.utils.a11y.isTalkbackActive
|
||||
import io.element.android.libraries.ui.utils.text.detect
|
||||
import io.element.android.wysiwyg.link.Link
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.roundToInt
|
||||
@@ -649,23 +660,44 @@ private fun MessageEventBubbleContent(
|
||||
.padding(horizontal = 4.dp, vertical = 2.dp)
|
||||
)
|
||||
}
|
||||
TimestampPosition.Aligned ->
|
||||
ContentAvoidingLayout(
|
||||
modifier = modifier,
|
||||
// The spacing is negative to make the content overlap the empty space at the start of the timestamp
|
||||
spacing = (-4).dp,
|
||||
overlayOffset = DpOffset(0.dp, -1.dp),
|
||||
shrinkContent = canShrinkContent,
|
||||
content = { content(this::onContentLayoutChange) },
|
||||
overlay = {
|
||||
TimelineEventTimestampView(
|
||||
event = event,
|
||||
eventSink = eventSink,
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 8.dp, vertical = 4.dp)
|
||||
)
|
||||
TimestampPosition.Aligned -> @Composable {
|
||||
val originalLayoutDirection = LocalLayoutDirection.current
|
||||
// Detect if the direction of the text content (if any) does not match the layout direction, to place the content and timestamp correctly
|
||||
val contentDirection = if (event.content is TimelineItemTextContent) {
|
||||
remember(event.content.body) {
|
||||
when (TextDirection.detect(event.content.body)) {
|
||||
TextDirection.Ltr, TextDirection.ContentOrLtr -> LayoutDirection.Ltr
|
||||
TextDirection.Rtl, TextDirection.ContentOrRtl -> LayoutDirection.Rtl
|
||||
else -> originalLayoutDirection
|
||||
}
|
||||
}
|
||||
)
|
||||
} else {
|
||||
originalLayoutDirection
|
||||
}
|
||||
|
||||
CompositionLocalProvider(LocalLayoutDirection provides contentDirection) {
|
||||
ContentAvoidingLayout(
|
||||
modifier = modifier,
|
||||
// The spacing is negative to make the content overlap the empty space at the start of the timestamp
|
||||
spacing = (-4).dp,
|
||||
overlayOffset = DpOffset(0.dp, -1.dp),
|
||||
shrinkContent = canShrinkContent,
|
||||
content = { content(this::onContentLayoutChange) },
|
||||
overlay = {
|
||||
// Use the original layout direction for the timestamp
|
||||
CompositionLocalProvider(LocalLayoutDirection provides originalLayoutDirection) {
|
||||
TimelineEventTimestampView(
|
||||
event = event,
|
||||
eventSink = eventSink,
|
||||
isLayoutDirectionMismatched = originalLayoutDirection != contentDirection,
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 8.dp, vertical = 4.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
TimestampPosition.Below ->
|
||||
Column(modifier) {
|
||||
content {}
|
||||
@@ -879,6 +911,149 @@ internal fun TimelineItemEventRowWithThreadSummaryPreview() = ElementPreview {
|
||||
}
|
||||
}
|
||||
|
||||
@PreviewWithExtraLargeHeight
|
||||
@Composable
|
||||
internal fun TimelineItemEventRowRtlContentPreview() = ElementPreview {
|
||||
Column {
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.background(Color.LightGray)
|
||||
.padding(8.dp),
|
||||
text = "LTR layout direction",
|
||||
textAlign = TextAlign.Center,
|
||||
style = ElementTheme.typography.fontHeadingMdBold,
|
||||
)
|
||||
CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Ltr) {
|
||||
sequenceOf(false, true).forEach { isMine ->
|
||||
ATimelineItemEventRow(
|
||||
event = aTimelineItemEvent(
|
||||
senderDisplayName = "Sender with a super long name that should ellipsize",
|
||||
isMine = isMine,
|
||||
content = aTimelineItemTextContent(
|
||||
body = "ظَة وَدَاع يَسْتَغْرِب فِيهَ"
|
||||
),
|
||||
timelineItemReactions = TimelineItemReactions(persistentListOf()),
|
||||
groupPosition = TimelineItemGroupPosition.First,
|
||||
)
|
||||
)
|
||||
ATimelineItemEventRow(
|
||||
event = aTimelineItemEvent(
|
||||
senderDisplayName = "Sender with a super long name that should ellipsize",
|
||||
isMine = isMine,
|
||||
content = aTimelineItemTextContent(
|
||||
body = "ظَة وَدَاع يَسْتَغْرِب فِيهَ",
|
||||
isEdited = true,
|
||||
),
|
||||
timelineItemReactions = TimelineItemReactions(persistentListOf()),
|
||||
groupPosition = TimelineItemGroupPosition.Middle,
|
||||
messageShield = MessageShield.UnknownDevice(isCritical = true),
|
||||
)
|
||||
)
|
||||
ATimelineItemEventRow(
|
||||
event = aTimelineItemEvent(
|
||||
senderDisplayName = "Sender with a super long name that should ellipsize",
|
||||
isMine = isMine,
|
||||
content = aTimelineItemTextContent(
|
||||
body = "ظَة وَدَاع \nيَسْتَغْرِب فِيهَ"
|
||||
),
|
||||
timelineItemReactions = TimelineItemReactions(persistentListOf()),
|
||||
groupPosition = TimelineItemGroupPosition.Middle,
|
||||
)
|
||||
)
|
||||
ATimelineItemEventRow(
|
||||
event = aTimelineItemEvent(
|
||||
senderDisplayName = "Sender with a super long name that should ellipsize",
|
||||
isMine = isMine,
|
||||
content = aTimelineItemTextContent(
|
||||
body = "ظَة وَدَاع يَسْتَغْرِب فِيهَا اَلشَّاعِر أَنْ لَا يَبْكِي مِنْ أَلَم اَلْفِرَاق،" +
|
||||
" وَيَصِف حَالَة اَلْمُودِعِينَ"
|
||||
),
|
||||
timelineItemReactions = TimelineItemReactions(persistentListOf()),
|
||||
groupPosition = TimelineItemGroupPosition.Last,
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.background(Color.LightGray)
|
||||
.padding(8.dp),
|
||||
text = "RTL layout direction",
|
||||
textAlign = TextAlign.Center,
|
||||
style = ElementTheme.typography.fontHeadingMdBold,
|
||||
)
|
||||
|
||||
CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) {
|
||||
sequenceOf(false, true).forEach { isMine ->
|
||||
ATimelineItemEventRow(
|
||||
event = aTimelineItemEvent(
|
||||
senderDisplayName = "Sender with a super long name that should ellipsize",
|
||||
isMine = isMine,
|
||||
content = aTimelineItemTextContent(
|
||||
body = "ظَة وَدَاع يَسْتَغْرِب فِيهَا اَلشَّاعِر أَنْ لَا يَبْكِي مِنْ أَلَم اَلْفِرَاق،" +
|
||||
" وَيَصِف حَالَة اَلْمُودِعِينَ",
|
||||
),
|
||||
timelineItemReactions = TimelineItemReactions(persistentListOf()),
|
||||
groupPosition = TimelineItemGroupPosition.First,
|
||||
)
|
||||
)
|
||||
ATimelineItemEventRow(
|
||||
event = aTimelineItemEvent(
|
||||
senderDisplayName = "Sender with a super long name that should ellipsize",
|
||||
isMine = isMine,
|
||||
content = aTimelineItemTextContent(
|
||||
body = "Testing\nLTR Line\nBreaks.",
|
||||
),
|
||||
timelineItemReactions = TimelineItemReactions(persistentListOf()),
|
||||
groupPosition = TimelineItemGroupPosition.Middle,
|
||||
)
|
||||
)
|
||||
ATimelineItemEventRow(
|
||||
event = aTimelineItemEvent(
|
||||
senderDisplayName = "Sender with a super long name that should ellipsize",
|
||||
isMine = isMine,
|
||||
content = aTimelineItemTextContent(
|
||||
body = "Testing a very long LTR text in an RTL layout."
|
||||
),
|
||||
timelineItemReactions = TimelineItemReactions(persistentListOf()),
|
||||
groupPosition = TimelineItemGroupPosition.Middle,
|
||||
)
|
||||
)
|
||||
ATimelineItemEventRow(
|
||||
event = aTimelineItemEvent(
|
||||
senderDisplayName = "Sender with a super long name that should ellipsize",
|
||||
isMine = isMine,
|
||||
content = aTimelineItemTextContent(
|
||||
body = "Testing LTR in RTL layout.",
|
||||
),
|
||||
timelineItemReactions = TimelineItemReactions(persistentListOf()),
|
||||
groupPosition = TimelineItemGroupPosition.Last,
|
||||
messageShield = MessageShield.UnknownDevice(isCritical = true),
|
||||
)
|
||||
)
|
||||
ATimelineItemEventRow(
|
||||
event = aTimelineItemEvent(
|
||||
senderDisplayName = "Sender with a super long name that should ellipsize",
|
||||
isMine = isMine,
|
||||
content = aTimelineItemTextContent(
|
||||
body = "Testing LTR in RTL layout.",
|
||||
isEdited = true,
|
||||
),
|
||||
timelineItemReactions = TimelineItemReactions(persistentListOf()),
|
||||
groupPosition = TimelineItemGroupPosition.Last,
|
||||
messageShield = MessageShield.UnknownDevice(isCritical = true),
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@PreviewsDayNight
|
||||
@Composable
|
||||
internal fun ThreadSummaryViewPreview() {
|
||||
|
||||
+6
-6
@@ -15,13 +15,13 @@ import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.layout.Layout
|
||||
import androidx.compose.ui.platform.LocalLayoutDirection
|
||||
import androidx.compose.ui.text.TextLayoutResult
|
||||
import androidx.compose.ui.text.style.ResolvedTextDirection
|
||||
import androidx.compose.ui.unit.Constraints
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.DpOffset
|
||||
import androidx.compose.ui.unit.LayoutDirection
|
||||
import androidx.compose.ui.unit.dp
|
||||
import io.element.android.libraries.core.data.tryOrNull
|
||||
import io.element.android.libraries.designsystem.text.roundToPx
|
||||
import io.element.android.wysiwyg.compose.EditorStyledText
|
||||
import kotlin.math.max
|
||||
@@ -149,13 +149,13 @@ object ContentAvoidingLayout {
|
||||
onContentLayoutChange: (ContentAvoidingLayoutData) -> Unit,
|
||||
extraWidth: Dp = 0.dp,
|
||||
): ((TextLayoutResult) -> Unit) {
|
||||
val layoutDirection = LocalLayoutDirection.current
|
||||
val extraWidthPx = extraWidth.roundToPx()
|
||||
return { textLayout: TextLayoutResult ->
|
||||
// We need to add the external extra width so it's not taken into account as 'free space'
|
||||
val lastLineWidth = when (layoutDirection) {
|
||||
LayoutDirection.Ltr -> textLayout.getLineRight(textLayout.lineCount - 1).roundToInt()
|
||||
LayoutDirection.Rtl -> textLayout.getLineLeft(textLayout.lineCount - 1).roundToInt()
|
||||
val textDirection = tryOrNull { textLayout.getParagraphDirection(0) }
|
||||
val lastLineWidth = when (textDirection) {
|
||||
ResolvedTextDirection.Rtl -> textLayout.getLineLeft(textLayout.lineCount - 1).roundToInt()
|
||||
else -> textLayout.getLineRight(textLayout.lineCount - 1).roundToInt()
|
||||
}
|
||||
val lastLineHeight = textLayout.getLineBottom(textLayout.lineCount - 1).roundToInt()
|
||||
onContentLayoutChange(
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
<string name="screen_media_upload_preview_error_failed_sending">"Gagal mengunggah media, silakan coba lagi."</string>
|
||||
<string name="screen_media_upload_preview_error_too_large_message">"Ukuran file maksimum yang diizinkan adalah%1$s ."</string>
|
||||
<string name="screen_media_upload_preview_error_too_large_title">"Ukuran file terlalu besar untuk diunggah."</string>
|
||||
<string name="screen_media_upload_preview_item_count">"Item %1$d dari %2$d"</string>
|
||||
<string name="screen_media_upload_preview_optimize_image_quality_title">"Optimalkan kualitas gambar"</string>
|
||||
<string name="screen_media_upload_preview_processing">"Memproses…"</string>
|
||||
<string name="screen_report_content_block_user">"Blokir pengguna"</string>
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
<string name="screen_room_attachment_source_camera_video">"Gravar vídeo"</string>
|
||||
<string name="screen_room_attachment_source_files">"Anexo"</string>
|
||||
<string name="screen_room_attachment_source_gallery">"Biblioteca de fotos e vídeos"</string>
|
||||
<string name="screen_room_attachment_source_location">"Localização"</string>
|
||||
<string name="screen_room_attachment_source_location">"Compartilhar localização"</string>
|
||||
<string name="screen_room_attachment_source_poll">"Enquete"</string>
|
||||
<string name="screen_room_attachment_text_formatting">"Formatação de texto"</string>
|
||||
<string name="screen_room_encrypted_history_banner">"O histórico de mensagens não está disponível no momento."</string>
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="crypto_event_authenticity_mismatched_sender">"Відправник події не збігається з власником пристрою, який його надіслав."</string>
|
||||
<string name="crypto_event_authenticity_not_guaranteed">"Автентичність цього зашифрованого повідомлення не може бути гарантована на цьому пристрої."</string>
|
||||
<string name="crypto_event_authenticity_previously_verified">"Зашифровано попередньо перевіреним користувачем."</string>
|
||||
<string name="crypto_event_authenticity_previously_verified">"Зашифровано звіреним раніше користувачем."</string>
|
||||
<string name="crypto_event_authenticity_sent_in_clear">"Не зашифровано."</string>
|
||||
<string name="crypto_event_authenticity_unknown_device">"Зашифровано невідомим або видаленим пристроєм."</string>
|
||||
<string name="crypto_event_authenticity_unsigned_device">"Зашифровано пристроєм, який не верифіковано його власником."</string>
|
||||
<string name="crypto_event_authenticity_unverified_identity">"Зашифровано неверифікованим користувачем."</string>
|
||||
<string name="crypto_event_authenticity_unsigned_device">"Зашифровано пристроєм, який не звірено його власником."</string>
|
||||
<string name="crypto_event_authenticity_unverified_identity">"Зашифровано не звіреним користувачем."</string>
|
||||
<string name="emoji_picker_category_activity">"Дії"</string>
|
||||
<string name="emoji_picker_category_flags">"Прапори"</string>
|
||||
<string name="emoji_picker_category_foods">"Їжа та напої"</string>
|
||||
@@ -16,6 +16,12 @@
|
||||
<string name="emoji_picker_category_places">"Подорожі та місця"</string>
|
||||
<string name="emoji_picker_category_recent">"Нещодавні емодзі"</string>
|
||||
<string name="emoji_picker_category_symbols">"Символи"</string>
|
||||
<string name="screen_image_edition_a11y_flip_image_horizontally">"Повернути зображення по горизонталі"</string>
|
||||
<string name="screen_image_edition_a11y_flip_image_horizontally_state_flipped">"Перевернуто по горизонталі"</string>
|
||||
<string name="screen_image_edition_a11y_flip_image_horizontally_state_original">"Оригінал"</string>
|
||||
<string name="screen_image_edition_a11y_flip_image_vertically">"Повернути зображення по вертикалі"</string>
|
||||
<string name="screen_image_edition_a11y_flip_image_vertically_state_flipped">"Перевернуто по вертикалі"</string>
|
||||
<string name="screen_image_edition_a11y_flip_image_vertically_state_original">"Оригінал"</string>
|
||||
<string name="screen_image_edition_a11y_rotate_to_the_left">"Повернути зображення вліво"</string>
|
||||
<plurals name="screen_image_edition_a11y_rotation_state">
|
||||
<item quantity="one">"%1$d градус"</item>
|
||||
@@ -47,7 +53,7 @@
|
||||
<string name="screen_room_attachment_source_poll">"Опитування"</string>
|
||||
<string name="screen_room_attachment_text_formatting">"Форматування тексту"</string>
|
||||
<string name="screen_room_encrypted_history_banner">"Історія повідомлень наразі недоступна."</string>
|
||||
<string name="screen_room_encrypted_history_banner_unverified">"Історія повідомлень недоступна в цій кімнаті. Перевірте цей пристрій, щоб побачити історію повідомлень."</string>
|
||||
<string name="screen_room_encrypted_history_banner_unverified">"Історія повідомлень недоступна в цій кімнаті. Звірте цей пристрій, щоб побачити історію повідомлень."</string>
|
||||
<string name="screen_room_invite_again_alert_message">"Чи хотіли б ви запросити їх знову?"</string>
|
||||
<string name="screen_room_invite_again_alert_title">"Ви одні в цій бесіді"</string>
|
||||
<string name="screen_room_mentions_at_room_subtitle">"Сповістити всю кімнату"</string>
|
||||
|
||||
+2
@@ -15,4 +15,6 @@ sealed interface DeveloperSettingsEvents {
|
||||
data class ChangeBrandColor(val color: Color?) : DeveloperSettingsEvents
|
||||
data object ClearCache : DeveloperSettingsEvents
|
||||
data object VacuumStores : DeveloperSettingsEvents
|
||||
data class MarkAllRoomsAsRead(val needsConfirmation: Boolean) : DeveloperSettingsEvents
|
||||
data object DismissMarkAllRoomsAsReadConfirmation : DeveloperSettingsEvents
|
||||
}
|
||||
|
||||
+26
-2
@@ -22,6 +22,7 @@ import io.element.android.features.enterprise.api.EnterpriseService
|
||||
import io.element.android.features.preferences.impl.developer.appsettings.AppDeveloperSettingsState
|
||||
import io.element.android.features.preferences.impl.tasks.ClearCacheUseCase
|
||||
import io.element.android.features.preferences.impl.tasks.ComputeCacheSizeUseCase
|
||||
import io.element.android.features.preferences.impl.tasks.MarkAllRoomsAsRead
|
||||
import io.element.android.features.preferences.impl.tasks.VacuumStoresUseCase
|
||||
import io.element.android.libraries.androidutils.filesize.FileSizeFormatter
|
||||
import io.element.android.libraries.architecture.AsyncAction
|
||||
@@ -46,6 +47,7 @@ class DeveloperSettingsPresenter(
|
||||
private val vacuumStoresUseCase: VacuumStoresUseCase,
|
||||
private val databaseSizesUseCase: GetDatabaseSizesUseCase,
|
||||
private val fileSizeFormatter: FileSizeFormatter,
|
||||
private val markAllRoomsAsRead: MarkAllRoomsAsRead,
|
||||
) : Presenter<DeveloperSettingsState> {
|
||||
@Composable
|
||||
override fun present(): DeveloperSettingsState {
|
||||
@@ -58,6 +60,9 @@ class DeveloperSettingsPresenter(
|
||||
val clearCacheAction = remember {
|
||||
mutableStateOf<AsyncAction<Unit>>(AsyncAction.Uninitialized)
|
||||
}
|
||||
val markAllRoomsAsReadAction = remember {
|
||||
mutableStateOf<AsyncAction<Unit>>(AsyncAction.Uninitialized)
|
||||
}
|
||||
var showColorPicker by remember {
|
||||
mutableStateOf(false)
|
||||
}
|
||||
@@ -88,6 +93,18 @@ class DeveloperSettingsPresenter(
|
||||
DeveloperSettingsEvents.VacuumStores -> coroutineScope.launch {
|
||||
vacuumStoresUseCase()
|
||||
}
|
||||
is DeveloperSettingsEvents.MarkAllRoomsAsRead -> {
|
||||
if (event.needsConfirmation) {
|
||||
markAllRoomsAsReadAction.value = AsyncAction.ConfirmingNoParams
|
||||
} else {
|
||||
coroutineScope.markAllRoomsAsRead(
|
||||
markAllRoomsAsReadAction = markAllRoomsAsReadAction,
|
||||
)
|
||||
}
|
||||
}
|
||||
DeveloperSettingsEvents.DismissMarkAllRoomsAsReadConfirmation -> {
|
||||
markAllRoomsAsReadAction.value = AsyncAction.Uninitialized
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,6 +114,7 @@ class DeveloperSettingsPresenter(
|
||||
cacheSize = cacheSize.value,
|
||||
databaseSizes = databaseSizes.value,
|
||||
clearCacheAction = clearCacheAction.value,
|
||||
markAllRoomsAsReadAction = markAllRoomsAsReadAction.value,
|
||||
isEnterpriseBuild = enterpriseService.isEnterpriseBuild,
|
||||
showColorPicker = showColorPicker,
|
||||
eventSink = ::handleEvent,
|
||||
@@ -131,8 +149,14 @@ class DeveloperSettingsPresenter(
|
||||
}
|
||||
|
||||
private fun CoroutineScope.clearCache(clearCacheAction: MutableState<AsyncAction<Unit>>) = launch {
|
||||
suspend { clearCacheUseCase() }.runCatchingUpdatingState(state = clearCacheAction)
|
||||
}
|
||||
|
||||
private fun CoroutineScope.markAllRoomsAsRead(
|
||||
markAllRoomsAsReadAction: MutableState<AsyncAction<Unit>>,
|
||||
) = launch {
|
||||
suspend {
|
||||
clearCacheUseCase()
|
||||
}.runCatchingUpdatingState(clearCacheAction)
|
||||
markAllRoomsAsRead().getOrThrow()
|
||||
}.runCatchingUpdatingState(state = markAllRoomsAsReadAction)
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -18,9 +18,10 @@ data class DeveloperSettingsState(
|
||||
val cacheSize: AsyncData<String>,
|
||||
val databaseSizes: AsyncData<ImmutableMap<String, String>>,
|
||||
val clearCacheAction: AsyncAction<Unit>,
|
||||
val markAllRoomsAsReadAction: AsyncAction<Unit>,
|
||||
val isEnterpriseBuild: Boolean,
|
||||
val showColorPicker: Boolean,
|
||||
val eventSink: (DeveloperSettingsEvents) -> Unit
|
||||
) {
|
||||
val showLoader = clearCacheAction is AsyncAction.Loading
|
||||
val showLoader = clearCacheAction is AsyncAction.Loading || markAllRoomsAsReadAction is AsyncAction.Loading
|
||||
}
|
||||
|
||||
+2
@@ -37,6 +37,7 @@ open class DeveloperSettingsStateProvider : PreviewParameterProvider<DeveloperSe
|
||||
fun aDeveloperSettingsState(
|
||||
appDeveloperSettingsState: AppDeveloperSettingsState = anAppDeveloperSettingsState(),
|
||||
clearCacheAction: AsyncAction<Unit> = AsyncAction.Uninitialized,
|
||||
markAllRoomsAsReadAction: AsyncAction<Unit> = AsyncAction.Uninitialized,
|
||||
isEnterpriseBuild: Boolean = false,
|
||||
showColorPicker: Boolean = false,
|
||||
eventSink: (DeveloperSettingsEvents) -> Unit = {},
|
||||
@@ -45,6 +46,7 @@ fun aDeveloperSettingsState(
|
||||
cacheSize = AsyncData.Success("1.2 MB"),
|
||||
databaseSizes = AsyncData.Success(persistentMapOf("state_store" to "1.2MB")),
|
||||
clearCacheAction = clearCacheAction,
|
||||
markAllRoomsAsReadAction = markAllRoomsAsReadAction,
|
||||
isEnterpriseBuild = isEnterpriseBuild,
|
||||
showColorPicker = showColorPicker,
|
||||
eventSink = eventSink,
|
||||
|
||||
+38
@@ -18,9 +18,11 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.unit.dp
|
||||
import io.element.android.compound.theme.ElementTheme
|
||||
import io.element.android.features.preferences.impl.R
|
||||
import io.element.android.features.preferences.impl.developer.appsettings.AppDeveloperSettingsView
|
||||
import io.element.android.libraries.designsystem.components.ProgressDialog
|
||||
import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog
|
||||
import io.element.android.libraries.designsystem.components.list.ListItemContent
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceCategory
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferencePage
|
||||
@@ -45,6 +47,15 @@ fun DeveloperSettingsView(
|
||||
if (state.showLoader) {
|
||||
ProgressDialog()
|
||||
}
|
||||
if (state.markAllRoomsAsReadAction.isConfirming()) {
|
||||
ConfirmationDialog(
|
||||
title = "Are you sure you want to mark all the rooms as read?",
|
||||
content = "",
|
||||
submitText = stringResource(CommonStrings.action_yes),
|
||||
onSubmitClick = { state.eventSink(DeveloperSettingsEvents.MarkAllRoomsAsRead(needsConfirmation = false)) },
|
||||
onDismiss = { state.eventSink(DeveloperSettingsEvents.DismissMarkAllRoomsAsReadConfirmation) },
|
||||
)
|
||||
}
|
||||
BackHandler(
|
||||
enabled = !state.showLoader,
|
||||
onBack = onBackClick,
|
||||
@@ -64,6 +75,7 @@ fun DeveloperSettingsView(
|
||||
onOpenShowkase = onOpenShowkase,
|
||||
)
|
||||
NotificationCategory(onPushHistoryClick)
|
||||
MarkAllRoomsAsReadCategory(state)
|
||||
|
||||
if (state.isEnterpriseBuild) {
|
||||
PreferenceCategory(title = "Theme") {
|
||||
@@ -152,6 +164,32 @@ fun DeveloperSettingsView(
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun MarkAllRoomsAsReadCategory(state: DeveloperSettingsState) {
|
||||
PreferenceCategory(title = "Room list") {
|
||||
ListItem(
|
||||
headlineContent = {
|
||||
Text("Mark all rooms as read")
|
||||
},
|
||||
supportingContent = {
|
||||
Text(
|
||||
text = """
|
||||
This will send a private read receipt and a read marker in every room you are part of.
|
||||
It's a long running operation that might get rate limited.
|
||||
It will run in the background but the app must be alive for it to finish.
|
||||
""".trimIndent(),
|
||||
style = ElementTheme.typography.fontBodySmRegular,
|
||||
color = ElementTheme.colors.textSecondary,
|
||||
)
|
||||
},
|
||||
enabled = !state.showLoader,
|
||||
onClick = {
|
||||
state.eventSink(DeveloperSettingsEvents.MarkAllRoomsAsRead(needsConfirmation = true))
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun NotificationCategory(onPushHistoryClick: () -> Unit) {
|
||||
PreferenceCategory(title = stringResource(id = R.string.screen_notification_settings_title)) {
|
||||
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2026 Element Creations Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.features.preferences.impl.tasks
|
||||
|
||||
import dev.zacsweers.metro.ContributesBinding
|
||||
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
||||
import io.element.android.libraries.di.SessionScope
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.push.api.notifications.NotificationCleaner
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
interface MarkAllRoomsAsRead {
|
||||
suspend operator fun invoke(): Result<Unit>
|
||||
}
|
||||
|
||||
@ContributesBinding(SessionScope::class)
|
||||
class DefaultMarkAllRoomsAsRead(
|
||||
private val client: MatrixClient,
|
||||
private val notificationCleaner: NotificationCleaner,
|
||||
private val coroutineDispatchers: CoroutineDispatchers,
|
||||
) : MarkAllRoomsAsRead {
|
||||
override suspend fun invoke(): Result<Unit> = withContext(coroutineDispatchers.io) {
|
||||
client.markAllRoomsAsRead()
|
||||
.onSuccess {
|
||||
notificationCleaner.clearAllMessagesEvents(client.sessionId)
|
||||
}
|
||||
}
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2026 Element Creations Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.features.preferences.impl.tasks
|
||||
|
||||
import dev.zacsweers.metro.ContributesBinding
|
||||
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
||||
import io.element.android.libraries.di.SessionScope
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.timeline.ReceiptType
|
||||
import io.element.android.libraries.preferences.api.store.SessionPreferencesStore
|
||||
import io.element.android.libraries.push.api.notifications.NotificationCleaner
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
interface MarkRoomAsRead {
|
||||
suspend operator fun invoke(roomId: RoomId): Result<Unit>
|
||||
}
|
||||
|
||||
@ContributesBinding(SessionScope::class)
|
||||
class DefaultMarkRoomAsRead(
|
||||
private val client: MatrixClient,
|
||||
private val notificationCleaner: NotificationCleaner,
|
||||
private val sessionPreferencesStore: SessionPreferencesStore,
|
||||
private val coroutineDispatchers: CoroutineDispatchers,
|
||||
) : MarkRoomAsRead {
|
||||
override suspend fun invoke(roomId: RoomId): Result<Unit> = withContext(coroutineDispatchers.io) {
|
||||
notificationCleaner.clearMessagesForRoom(client.sessionId, roomId)
|
||||
val room = client.getRoom(roomId) ?: return@withContext Result.failure(IllegalStateException("Room not found"))
|
||||
room.use {
|
||||
it.setUnreadFlag(isUnread = false)
|
||||
val receiptType = if (sessionPreferencesStore.isSendPublicReadReceiptsEnabled().first()) {
|
||||
ReceiptType.READ
|
||||
} else {
|
||||
ReceiptType.READ_PRIVATE
|
||||
}
|
||||
it.markAsRead(receiptType)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="full_screen_intent_banner_message">"Щоб ніколи не пропустити важливий виклик, змініть налаштування, щоб увімкнути повноекранні сповіщення, коли телефон заблоковано."</string>
|
||||
<string name="full_screen_intent_banner_title">"Покращуйте досвід дзвінків"</string>
|
||||
<string name="full_screen_intent_banner_title">"Покращуйте якість викликів"</string>
|
||||
<string name="screen_advanced_settings_choose_distributor_dialog_title_android">"Виберіть спосіб отримання сповіщень"</string>
|
||||
<string name="screen_advanced_settings_developer_mode">"Режим розробника"</string>
|
||||
<string name="screen_advanced_settings_developer_mode_description">"Увімкніть доступ до функцій і можливостей для розробників."</string>
|
||||
@@ -10,18 +10,18 @@
|
||||
<string name="screen_advanced_settings_element_call_base_url_validation_error">"Неправильна URL-адреса. Переконайтеся, що ви вказали протокол (http/https) та правильну адресу."</string>
|
||||
<string name="screen_advanced_settings_hide_invite_avatars_toggle_title">"Сховати аватари у запитах на запрошення до кімнат"</string>
|
||||
<string name="screen_advanced_settings_hide_timeline_media_toggle_title">"Сховати попередній перегляд медіа у стрічці"</string>
|
||||
<string name="screen_advanced_settings_labs">"Лабораторії"</string>
|
||||
<string name="screen_advanced_settings_labs">"Лабораторія"</string>
|
||||
<string name="screen_advanced_settings_live_location_section_description">"Відстань, яку потрібно пройти, щоб ініціювати оновлення."</string>
|
||||
<string name="screen_advanced_settings_live_location_section_footer">"Переконайтеся, що для цього додатка увімкнено функцію «Точна геолокація». Щоб змінити дозвіл, перейдіть на сторінку %1$s."</string>
|
||||
<string name="screen_advanced_settings_live_location_section_footer_link">"Налаштування додатка"</string>
|
||||
<string name="screen_advanced_settings_live_location_section_footer">"Переконайтеся, що для цього застосунку ввімкнено функцію «Точна геолокація». Щоб змінити дозвіл, перейдіть на сторінку %1$s."</string>
|
||||
<string name="screen_advanced_settings_live_location_section_footer_link">"Налаштування застосунку"</string>
|
||||
<string name="screen_advanced_settings_live_location_section_title">"Оновлення місцезнаходження в реальному часі"</string>
|
||||
<plurals name="screen_advanced_settings_live_location_update_distance">
|
||||
<item quantity="one">"Кожен %1$d метр"</item>
|
||||
<item quantity="few">"Кожні %1$d метри"</item>
|
||||
<item quantity="many">"Кожні %1$d метрів"</item>
|
||||
</plurals>
|
||||
<string name="screen_advanced_settings_media_compression_description">"Швидше завантажуйте фотографії та відео та зменшуйте використання даних"</string>
|
||||
<string name="screen_advanced_settings_media_compression_title">"Оптимізуйте медіаякість"</string>
|
||||
<string name="screen_advanced_settings_media_compression_description">"Швидше завантаження світлин і відео та зменшення обсягу трафіку"</string>
|
||||
<string name="screen_advanced_settings_media_compression_title">"Оптимізація якості медіа"</string>
|
||||
<string name="screen_advanced_settings_moderation_and_safety_section_title">"Модерування й безпека"</string>
|
||||
<string name="screen_advanced_settings_optimise_image_upload_quality_description">"Автоматична оптимізація зображень для швидшого вивантаження та зменшення розміру файлів."</string>
|
||||
<string name="screen_advanced_settings_optimise_image_upload_quality_title">"Оптимізація якості вивантажуваних зображень"</string>
|
||||
@@ -34,14 +34,14 @@
|
||||
<string name="screen_advanced_settings_rich_text_editor_description">"Вимкніть редактор розширеного тексту, щоб вводити Markdown вручну."</string>
|
||||
<string name="screen_advanced_settings_send_read_receipts">"Читати журнали"</string>
|
||||
<string name="screen_advanced_settings_send_read_receipts_description">"Якщо вимкнено, ваші сповіщення про прочитання нікому не надсилатимуться. Ви все одно отримуватимете сповіщення про прочитання від інших користувачів."</string>
|
||||
<string name="screen_advanced_settings_share_presence">"Поділіться присутністю"</string>
|
||||
<string name="screen_advanced_settings_share_presence_description">"Якщо цей параметр вимкнено, ви не зможете надсилати й отримувати звіти про прочитання чи сповіщення про введення тексту."</string>
|
||||
<string name="screen_advanced_settings_share_presence">"Ділитися присутністю"</string>
|
||||
<string name="screen_advanced_settings_share_presence_description">"Якщо вимкнути цю функцію, ви не зможете надсилати чи отримувати підтвердження прочитання або сповіщення про набір тексту."</string>
|
||||
<string name="screen_advanced_settings_show_media_timeline_always_hide">"Завжди ховати"</string>
|
||||
<string name="screen_advanced_settings_show_media_timeline_always_show">"Завжди показувати"</string>
|
||||
<string name="screen_advanced_settings_show_media_timeline_private_rooms">"У приватних кімнатах"</string>
|
||||
<string name="screen_advanced_settings_show_media_timeline_subtitle">"Сховані медіа завжди можна переглянути, натиснувши на нього"</string>
|
||||
<string name="screen_advanced_settings_show_media_timeline_title">"Показувати медіа у стрічці"</string>
|
||||
<string name="screen_advanced_settings_view_source_description">"Увімкнути опцію для перегляду коду повідомлення в стрічці"</string>
|
||||
<string name="screen_advanced_settings_view_source_description">"Увімкнення цього параметра уможливить перегляд джерела повідомлень зі стрічки."</string>
|
||||
<string name="screen_blocked_users_empty">"У вас немає заблокованих користувачів."</string>
|
||||
<string name="screen_blocked_users_unblock_alert_action">"Розблокувати"</string>
|
||||
<string name="screen_blocked_users_unblock_alert_description">"Ви знову зможете бачити всі повідомлення від них."</string>
|
||||
@@ -55,11 +55,12 @@
|
||||
<string name="screen_edit_profile_updating_details">"Оновлення профілю…"</string>
|
||||
<string name="screen_labs_enable_threads">"Увімкнути відповіді в гілках"</string>
|
||||
<string name="screen_labs_enable_threads_description">"Застосунок перезапуститься, щоб застосувати цю зміну."</string>
|
||||
<string name="screen_labs_header_description">"Випробуйте наші останні ідеї, що перебувають на стадії розробки. Ці функції ще не остаточні; вони можуть бути нестабільними та змінюватися."</string>
|
||||
<string name="screen_labs_header_description">"Випробуйте найновіші ідеї наших розробників. Ці функції ще не завершені, вони можуть бути нестабільними та змінюватись."</string>
|
||||
<string name="screen_labs_header_title">"Хочете поекспериментувати?"</string>
|
||||
<string name="screen_labs_title">"Лабораторії"</string>
|
||||
<string name="screen_labs_title">"Лабораторія"</string>
|
||||
<string name="screen_notification_settings_additional_settings_section_title">"Додаткові налаштування"</string>
|
||||
<string name="screen_notification_settings_calls_label">"Аудіо та відеодзвінки"</string>
|
||||
<string name="screen_notification_settings_call_ringtone_label">"Мелодія виклику"</string>
|
||||
<string name="screen_notification_settings_calls_label">"Аудіо та відеовиклики"</string>
|
||||
<string name="screen_notification_settings_configuration_mismatch">"Невідповідність конфігурації"</string>
|
||||
<string name="screen_notification_settings_configuration_mismatch_description">"Ми спростили налаштування сповіщень, щоб полегшити пошук параметрів. Деякі користувацькі налаштування, які ви вибрали раніше, тут не відображаються, але вони все ще активні.
|
||||
|
||||
@@ -77,18 +78,25 @@
|
||||
<string name="screen_notification_settings_invite_for_me_label">"Запрошення"</string>
|
||||
<string name="screen_notification_settings_mentions_only_disclaimer">"Ваш домашній сервер не підтримує цю опцію в зашифрованих кімнатах, ви можете не отримати сповіщення в деяких кімнатах."</string>
|
||||
<string name="screen_notification_settings_mentions_section_title">"Згадки"</string>
|
||||
<string name="screen_notification_settings_message_sound_dialog_choose_other">"Обрати інший звук…"</string>
|
||||
<string name="screen_notification_settings_message_sound_dialog_current_subtitle">"Наразі використовується %1$s"</string>
|
||||
<string name="screen_notification_settings_message_sound_dialog_title">"Звук повідомлення"</string>
|
||||
<string name="screen_notification_settings_message_sound_label">"Звук повідомлення"</string>
|
||||
<string name="screen_notification_settings_mode_all">"Усі"</string>
|
||||
<string name="screen_notification_settings_mode_mentions">"Згадки"</string>
|
||||
<string name="screen_notification_settings_notification_section_title">"Сповіщати мене про"</string>
|
||||
<string name="screen_notification_settings_room_mention_label">"Сповіщати про @room"</string>
|
||||
<string name="screen_notification_settings_sound_custom_fallback">"Власний"</string>
|
||||
<string name="screen_notification_settings_sound_custom_sound_button_title">"Користувацький звук…"</string>
|
||||
<string name="screen_notification_settings_sound_delete_sound_error_title">"Помилка видалення файлу"</string>
|
||||
<string name="screen_notification_settings_sound_element_default">"За замовчуванням Element"</string>
|
||||
<string name="screen_notification_settings_sound_element_default">"Типово Element"</string>
|
||||
<string name="screen_notification_settings_sound_element_fade">"Згасання Element"</string>
|
||||
<string name="screen_notification_settings_sound_import_sound_error_title">"Помилка імпорту файлу"</string>
|
||||
<string name="screen_notification_settings_sound_preview_sound_error_title">"Проблема з попереднім прослуховуванням звуку сповіщення"</string>
|
||||
<string name="screen_notification_settings_sound_section_title">"Звук"</string>
|
||||
<string name="screen_notification_settings_sound_set_sound_error_title">"Проблема налаштовування звуку сповіщення"</string>
|
||||
<string name="screen_notification_settings_sound_silent">"Без звуку"</string>
|
||||
<string name="screen_notification_settings_sound_system_default">"Як у системі"</string>
|
||||
<string name="screen_notification_settings_system_notifications_action_required">"Щоб отримувати сповіщення змініть свої %1$s."</string>
|
||||
<string name="screen_notification_settings_system_notifications_action_required_content_link">"системні налаштування"</string>
|
||||
<string name="screen_notification_settings_system_notifications_turned_off">"Системні сповіщення вимкнені"</string>
|
||||
|
||||
+25
@@ -17,6 +17,7 @@ import io.element.android.features.enterprise.test.FakeEnterpriseService
|
||||
import io.element.android.features.preferences.impl.developer.appsettings.anAppDeveloperSettingsState
|
||||
import io.element.android.features.preferences.impl.tasks.FakeClearCacheUseCase
|
||||
import io.element.android.features.preferences.impl.tasks.FakeComputeCacheSizeUseCase
|
||||
import io.element.android.features.preferences.impl.tasks.FakeMarkAllRoomsAsRead
|
||||
import io.element.android.features.preferences.impl.tasks.VacuumStoresUseCase
|
||||
import io.element.android.libraries.androidutils.filesize.FakeFileSizeFormatter
|
||||
import io.element.android.libraries.architecture.AsyncAction
|
||||
@@ -127,6 +128,28 @@ class DeveloperSettingsPresenterTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - confirm mark all rooms as read`() = runTest {
|
||||
val markAllRoomsAsRead = FakeMarkAllRoomsAsRead()
|
||||
val presenter = createDeveloperSettingsPresenter(markAllRoomsAsRead = markAllRoomsAsRead)
|
||||
presenter.test {
|
||||
skipItems(2)
|
||||
val initialState = awaitItem()
|
||||
initialState.eventSink(DeveloperSettingsEvents.MarkAllRoomsAsRead(needsConfirmation = true))
|
||||
val stateWithConfirmation = awaitItem()
|
||||
assertThat(stateWithConfirmation.markAllRoomsAsReadAction.isConfirming()).isTrue()
|
||||
stateWithConfirmation.eventSink(DeveloperSettingsEvents.MarkAllRoomsAsRead(needsConfirmation = false))
|
||||
awaitItem().also { state ->
|
||||
assertThat(state.markAllRoomsAsReadAction.isConfirming()).isFalse()
|
||||
assertThat(state.markAllRoomsAsReadAction).isInstanceOf(AsyncAction.Loading::class.java)
|
||||
}
|
||||
awaitItem().also { state ->
|
||||
assertThat(state.markAllRoomsAsReadAction).isInstanceOf(AsyncAction.Success::class.java)
|
||||
assertThat(markAllRoomsAsRead.invokeCallCount).isEqualTo(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - VacuumStores action invokes the VacuumStoresUseCase`() = runTest {
|
||||
var vacuumCalled = false
|
||||
@@ -151,6 +174,7 @@ class DeveloperSettingsPresenterTest {
|
||||
enterpriseService: EnterpriseService = FakeEnterpriseService(),
|
||||
vacuumStoresUseCase: VacuumStoresUseCase = VacuumStoresUseCase {},
|
||||
databaseSizesUseCase: GetDatabaseSizesUseCase = GetDatabaseSizesUseCase { Result.success(SdkStoreSizes(null, null, null, null)) },
|
||||
markAllRoomsAsRead: FakeMarkAllRoomsAsRead = FakeMarkAllRoomsAsRead(),
|
||||
): DeveloperSettingsPresenter {
|
||||
return DeveloperSettingsPresenter(
|
||||
appDeveloperSettingsPresenter = { anAppDeveloperSettingsState() },
|
||||
@@ -161,6 +185,7 @@ class DeveloperSettingsPresenterTest {
|
||||
vacuumStoresUseCase = vacuumStoresUseCase,
|
||||
databaseSizesUseCase = databaseSizesUseCase,
|
||||
fileSizeFormatter = FakeFileSizeFormatter(),
|
||||
markAllRoomsAsRead = markAllRoomsAsRead,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -71,7 +71,7 @@ class DeveloperSettingsViewTest : RobolectricTest() {
|
||||
}
|
||||
}
|
||||
|
||||
@Config(qualifiers = "h2200dp")
|
||||
@Config(qualifiers = "h2400dp")
|
||||
@Test
|
||||
fun `clicking on clear cache emits the expected event`() = runAndroidComposeUiTest {
|
||||
val eventsRecorder = EventsRecorder<DeveloperSettingsEvents>()
|
||||
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (c) 2026 Element Creations Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.features.preferences.impl.tasks
|
||||
|
||||
import io.element.android.tests.testutils.simulateLongTask
|
||||
|
||||
class FakeMarkAllRoomsAsRead(
|
||||
private val invokeLambda: suspend () -> Result<Unit> = { Result.success(Unit) },
|
||||
) : MarkAllRoomsAsRead {
|
||||
var invokeCallCount = 0
|
||||
private set
|
||||
|
||||
override suspend fun invoke(): Result<Unit> = simulateLongTask {
|
||||
invokeCallCount++
|
||||
invokeLambda()
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (c) 2026 Element Creations Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.features.preferences.impl.tasks
|
||||
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
|
||||
class FakeMarkRoomAsRead(
|
||||
private val invokeLambda: suspend (RoomId) -> Result<Unit> = { Result.success(Unit) },
|
||||
) : MarkRoomAsRead {
|
||||
val invokedRoomIds = mutableListOf<RoomId>()
|
||||
|
||||
override suspend fun invoke(roomId: RoomId): Result<Unit> {
|
||||
invokedRoomIds.add(roomId)
|
||||
return invokeLambda(roomId)
|
||||
}
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (c) 2026 Element Creations Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.features.preferences.impl.tasks
|
||||
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import io.element.android.libraries.matrix.api.core.SessionId
|
||||
import io.element.android.libraries.matrix.test.A_SESSION_ID
|
||||
import io.element.android.libraries.matrix.test.FakeMatrixClient
|
||||
import io.element.android.libraries.push.test.notifications.FakeNotificationCleaner
|
||||
import io.element.android.tests.testutils.lambda.lambdaRecorder
|
||||
import io.element.android.tests.testutils.lambda.value
|
||||
import io.element.android.tests.testutils.testCoroutineDispatchers
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Test
|
||||
|
||||
class MarkAllRoomsAsReadTest {
|
||||
@Test
|
||||
fun `invoke - delegates to client and clears all notifications`() = runTest {
|
||||
val markAllRoomsAsReadLambda = lambdaRecorder<Result<Unit>> { Result.success(Unit) }
|
||||
val clearAllMessagesEventsLambda = lambdaRecorder<SessionId, Unit> { }
|
||||
val markAllRoomsAsRead = DefaultMarkAllRoomsAsRead(
|
||||
client = FakeMatrixClient(
|
||||
markAllRoomsAsReadResult = markAllRoomsAsReadLambda,
|
||||
),
|
||||
notificationCleaner = FakeNotificationCleaner(
|
||||
clearAllMessagesEventsLambda = clearAllMessagesEventsLambda,
|
||||
),
|
||||
coroutineDispatchers = testCoroutineDispatchers(),
|
||||
)
|
||||
|
||||
val result = markAllRoomsAsRead()
|
||||
|
||||
assertThat(result.isSuccess).isTrue()
|
||||
markAllRoomsAsReadLambda.assertions().isCalledOnce()
|
||||
clearAllMessagesEventsLambda.assertions().isCalledOnce().with(value(A_SESSION_ID))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `invoke - does not clear notifications when client fails`() = runTest {
|
||||
val clearAllMessagesEventsLambda = lambdaRecorder<SessionId, Unit> { }
|
||||
val markAllRoomsAsRead = DefaultMarkAllRoomsAsRead(
|
||||
client = FakeMatrixClient(
|
||||
markAllRoomsAsReadResult = { Result.failure(IllegalStateException("Failed")) },
|
||||
),
|
||||
notificationCleaner = FakeNotificationCleaner(
|
||||
clearAllMessagesEventsLambda = clearAllMessagesEventsLambda,
|
||||
),
|
||||
coroutineDispatchers = testCoroutineDispatchers(),
|
||||
)
|
||||
|
||||
val result = markAllRoomsAsRead()
|
||||
|
||||
assertThat(result.isFailure).isTrue()
|
||||
clearAllMessagesEventsLambda.assertions().isNeverCalled()
|
||||
}
|
||||
}
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (c) 2026 Element Creations Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
@file:OptIn(ExperimentalCoroutinesApi::class)
|
||||
|
||||
package io.element.android.features.preferences.impl.tasks
|
||||
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.core.SessionId
|
||||
import io.element.android.libraries.matrix.api.timeline.ReceiptType
|
||||
import io.element.android.libraries.matrix.test.A_ROOM_ID
|
||||
import io.element.android.libraries.matrix.test.A_SESSION_ID
|
||||
import io.element.android.libraries.matrix.test.FakeMatrixClient
|
||||
import io.element.android.libraries.matrix.test.room.FakeBaseRoom
|
||||
import io.element.android.libraries.preferences.test.InMemorySessionPreferencesStore
|
||||
import io.element.android.libraries.push.test.notifications.FakeNotificationCleaner
|
||||
import io.element.android.tests.testutils.lambda.lambdaRecorder
|
||||
import io.element.android.tests.testutils.lambda.value
|
||||
import io.element.android.tests.testutils.testCoroutineDispatchers
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.test.runCurrent
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Test
|
||||
|
||||
class MarkRoomAsReadTest {
|
||||
@Test
|
||||
fun `invoke - clears notifications, clears unread flag and sends public read receipt`() = runTest {
|
||||
val markAsReadResult = lambdaRecorder<ReceiptType, Result<Unit>> { Result.success(Unit) }
|
||||
val room = FakeBaseRoom(markAsReadResult = markAsReadResult)
|
||||
val matrixClient = FakeMatrixClient().apply {
|
||||
givenGetRoomResult(A_ROOM_ID, room)
|
||||
}
|
||||
val clearMessagesForRoomLambda = lambdaRecorder { _: SessionId, _: RoomId -> }
|
||||
val notificationCleaner = FakeNotificationCleaner(clearMessagesForRoomLambda = clearMessagesForRoomLambda)
|
||||
val sessionPreferencesStore = InMemorySessionPreferencesStore()
|
||||
val markRoomAsRead = DefaultMarkRoomAsRead(
|
||||
client = matrixClient,
|
||||
notificationCleaner = notificationCleaner,
|
||||
sessionPreferencesStore = sessionPreferencesStore,
|
||||
coroutineDispatchers = testCoroutineDispatchers(),
|
||||
)
|
||||
|
||||
val result = markRoomAsRead(A_ROOM_ID)
|
||||
runCurrent()
|
||||
|
||||
assertThat(result.isSuccess).isTrue()
|
||||
clearMessagesForRoomLambda.assertions().isCalledOnce()
|
||||
.with(value(A_SESSION_ID), value(A_ROOM_ID))
|
||||
assertThat(room.setUnreadFlagCalls).isEqualTo(listOf(false))
|
||||
markAsReadResult.assertions().isCalledOnce().with(value(ReceiptType.READ))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `invoke - sends private read receipt when public receipts are disabled`() = runTest {
|
||||
val markAsReadResult = lambdaRecorder<ReceiptType, Result<Unit>> { Result.success(Unit) }
|
||||
val room = FakeBaseRoom(markAsReadResult = markAsReadResult)
|
||||
val matrixClient = FakeMatrixClient().apply {
|
||||
givenGetRoomResult(A_ROOM_ID, room)
|
||||
}
|
||||
val sessionPreferencesStore = InMemorySessionPreferencesStore(isSendPublicReadReceiptsEnabled = false)
|
||||
val markRoomAsRead = DefaultMarkRoomAsRead(
|
||||
client = matrixClient,
|
||||
notificationCleaner = FakeNotificationCleaner(clearMessagesForRoomLambda = { _, _ -> }),
|
||||
sessionPreferencesStore = sessionPreferencesStore,
|
||||
coroutineDispatchers = testCoroutineDispatchers(),
|
||||
)
|
||||
|
||||
val result = markRoomAsRead(A_ROOM_ID)
|
||||
runCurrent()
|
||||
|
||||
assertThat(result.isSuccess).isTrue()
|
||||
markAsReadResult.assertions().isCalledOnce().with(value(ReceiptType.READ_PRIVATE))
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@
|
||||
<string name="screen_bug_report_editor_supporting">"请尽可能用英文描述。"</string>
|
||||
<string name="screen_bug_report_error_description_too_short">"描述太短,请提供详细情况。谢谢!"</string>
|
||||
<string name="screen_bug_report_github_issue_description">"你可以输入与之相关的 GitHub issue 编号(如果有)。"</string>
|
||||
<string name="screen_bug_report_github_issue_label">"GitHub issue"</string>
|
||||
<string name="screen_bug_report_include_crash_logs">"发送崩溃日志"</string>
|
||||
<string name="screen_bug_report_include_logs">"允许日志"</string>
|
||||
<string name="screen_bug_report_include_logs_error">"日志文件过大,无法包含在本次报告中,请通过其它方式发送给我们。"</string>
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
<string name="screen_room_details_edit_room_title">"Edytuj szczegóły"</string>
|
||||
<string name="screen_room_details_edition_error">"Wystąpił nieznany błąd i nie można było zmienić informacji."</string>
|
||||
<string name="screen_room_details_edition_error_title">"Nie można zaktualizować pokoju"</string>
|
||||
<string name="screen_room_details_encryption_enabled_subtitle">"Wiadomości są zabezpieczone kłódkami. Tylko Ty i odbiorcy macie unikalne klucze do ich odblokowania."</string>
|
||||
<string name="screen_room_details_encryption_enabled_subtitle">"Wiadomości są zabezpieczone kłódkami. Tylko Ty i Twoi odbiorcy posiadacie klucze do ich otwarcia."</string>
|
||||
<string name="screen_room_details_encryption_enabled_title">"Szyfrowanie wiadomości włączone"</string>
|
||||
<string name="screen_room_details_error_loading_notification_settings">"Wystąpił błąd podczas ładowania ustawień powiadomień."</string>
|
||||
<string name="screen_room_details_error_muting">"Wyciszenie tego pokoju nie powiodło się, spróbuj ponownie."</string>
|
||||
|
||||
@@ -25,7 +25,8 @@
|
||||
<string name="screen_custom_recovery_key_confirm_subtitle">"Sisesta oma taastevõti uuesti."</string>
|
||||
<string name="screen_custom_recovery_key_confirm_title">"Korda oma taastevõtit"</string>
|
||||
<plurals name="screen_custom_recovery_key_input_notice">
|
||||
<item quantity="other">"Vähemalt %1$s tähemärki. Ära kasuta oma konto salasõna."</item>
|
||||
<item quantity="one">"Vähemalt %1$d tähemärk. Ära pruugi kasutajakonto salasõna."</item>
|
||||
<item quantity="other">"Vähemalt %1$d tähemärki. Ära pruugi kasutajakonto salasõna."</item>
|
||||
</plurals>
|
||||
<string name="screen_custom_recovery_key_input_strength">"Tugevus"</string>
|
||||
<string name="screen_custom_recovery_key_input_strength_a11y">"Salafraasi tugevus: %1$s"</string>
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<string name="screen_chat_backup_recovery_action_change_description">"Pulihkan identitas kriptografi dan riwayat pesan Anda dengan kunci pemulihan jika Anda kehilangan semua perangkat yang ada."</string>
|
||||
<string name="screen_chat_backup_recovery_action_confirm">"Masukkan kunci pemulihan"</string>
|
||||
<string name="screen_chat_backup_recovery_action_confirm_description">"Penyimpanan kunci Anda saat ini tidak sinkron."</string>
|
||||
<string name="screen_chat_backup_recovery_action_setup">"Siapkan pemulihan"</string>
|
||||
<string name="screen_chat_backup_recovery_action_setup">"Siapkan Kunci pemulihan"</string>
|
||||
<string name="screen_create_new_recovery_key_list_item_1">"Buka %1$s di perangkat desktop"</string>
|
||||
<string name="screen_create_new_recovery_key_list_item_2">"Masuk ke akun Anda lagi"</string>
|
||||
<string name="screen_create_new_recovery_key_list_item_3">"Saat diminta untuk memverifikasi perangkat Anda, pilih %1$s"</string>
|
||||
@@ -25,8 +25,8 @@
|
||||
<string name="screen_encryption_reset_bullet_3">"Anda perlu memverifikasi semua perangkat dan kontak yang ada lagi"</string>
|
||||
<string name="screen_encryption_reset_footer">"Hanya atur ulang identitas Anda jika Anda tidak memiliki akses ke perangkat lain yang masuk dan Anda kehilangan kunci pemulihan."</string>
|
||||
<string name="screen_encryption_reset_title">"Tidak dapat mengonfirmasi? Anda perlu mengatur ulang identitas Anda."</string>
|
||||
<string name="screen_key_backup_disable_confirmation_action_turn_off">"Matikan"</string>
|
||||
<string name="screen_key_backup_disable_confirmation_description">"Anda akan kehilangan pesan terenkripsi jika Anda keluar dari semua perangkat."</string>
|
||||
<string name="screen_key_backup_disable_confirmation_action_turn_off">"Hapus"</string>
|
||||
<string name="screen_key_backup_disable_confirmation_description">"Anda akan kehilangan pesan terenkripsi jika Anda menghapusnya dari semua perangkat."</string>
|
||||
<string name="screen_key_backup_disable_confirmation_title">"Apakah Anda yakin ingin mematikan pencadangan?"</string>
|
||||
<string name="screen_key_backup_disable_description">"Mematikan pencadangan akan menghapus pencadangan kunci terenkripsi saat ini dan mematikan fitur keamanan lainnya. Dalam hal ini, Anda akan:"</string>
|
||||
<string name="screen_key_backup_disable_description_point_1">"Tidak memiliki riwayat pesan terenkripsi di perangkat baru"</string>
|
||||
@@ -58,7 +58,7 @@
|
||||
<string name="screen_recovery_key_setup_generate_key">"Buat kunci pemulihan Anda"</string>
|
||||
<string name="screen_recovery_key_setup_generate_key_description">"Jangan bagikan ini kepada siapa pun!"</string>
|
||||
<string name="screen_recovery_key_setup_success">"Penyiapan pemulihan berhasil"</string>
|
||||
<string name="screen_recovery_key_setup_title">"Siapkan pemulihan"</string>
|
||||
<string name="screen_recovery_key_setup_title">"Siapkan Kunci pemulihan"</string>
|
||||
<string name="screen_reset_encryption_confirmation_alert_action">"Ya, atur ulang sekarang"</string>
|
||||
<string name="screen_reset_encryption_confirmation_alert_subtitle">"Proses ini tidak dapat diurungkan."</string>
|
||||
<string name="screen_reset_encryption_confirmation_alert_title">"Apakah Anda yakin ingin mengatur ulang identitas Anda?"</string>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_chat_backup_key_backup_action_disable">"Apagar o armazenamento de chaves"</string>
|
||||
<string name="screen_chat_backup_key_backup_action_enable">"Ativar o backup"</string>
|
||||
<string name="screen_chat_backup_key_backup_description">"Armazene sua identidade criptográfica e chaves de mensagem com segurança no servidor. Isso permitirá que você visualize seu histórico de mensagens em dispositivos futuros. %1$s."</string>
|
||||
<string name="screen_chat_backup_key_backup_description">"Isso te permite ver seu histórico de conversas em dispositivos novos, e é necessário para o backup de conversas e identidade digital. %1$s"</string>
|
||||
<string name="screen_chat_backup_key_backup_title">"Armazenamento de chaves"</string>
|
||||
<string name="screen_chat_backup_key_storage_disabled_error">"O armazenamento de chaves deve ser ativado para configurar a recuperação."</string>
|
||||
<string name="screen_chat_backup_key_storage_toggle_description">"Enviar chaves a partir deste dispositivo"</string>
|
||||
@@ -11,7 +11,7 @@
|
||||
<string name="screen_chat_backup_recovery_action_change_description">"Recupere sua identidade criptográfica e o histórico de mensagens com uma chave de recuperação, caso você tenha perdido todos os dispositivos existentes."</string>
|
||||
<string name="screen_chat_backup_recovery_action_confirm">"Digitar chave de recuperação"</string>
|
||||
<string name="screen_chat_backup_recovery_action_confirm_description">"Seu armazenamento de chaves está fora de sincronia no momento."</string>
|
||||
<string name="screen_chat_backup_recovery_action_setup">"Configurar a recuperação"</string>
|
||||
<string name="screen_chat_backup_recovery_action_setup">"Receber chave de recuperação"</string>
|
||||
<string name="screen_create_new_recovery_key_list_item_1">"Abra o %1$s em um computador"</string>
|
||||
<string name="screen_create_new_recovery_key_list_item_2">"Entre na sua conta novamente"</string>
|
||||
<string name="screen_create_new_recovery_key_list_item_3">"Ao ser solicitado para verificar o seu dispositivo, selecione %1$s"</string>
|
||||
@@ -25,10 +25,10 @@
|
||||
<string name="screen_encryption_reset_bullet_3">"Você precisará verificar todos os seus dispositivos e contatos existentes novamente."</string>
|
||||
<string name="screen_encryption_reset_footer">"Redefina sua identidade somente se você não tiver acesso a outro dispositivo conectado e se tiver perdido sua chave de recuperação."</string>
|
||||
<string name="screen_encryption_reset_title">"Não consegue confirmar? Você precisará redefinir sua identidade."</string>
|
||||
<string name="screen_key_backup_disable_confirmation_action_turn_off">"Desativar"</string>
|
||||
<string name="screen_key_backup_disable_confirmation_description">"Você perderá suas mensagens criptografadas se for desconectado de todos os dispositivos."</string>
|
||||
<string name="screen_key_backup_disable_confirmation_title">"Tem certeza de que deseja desativar o backup?"</string>
|
||||
<string name="screen_key_backup_disable_description">"Ao apagar o armazenamento de chaves, a sua identidade criptográfica e as chaves das mensagens serão apagadas do servidor e os seguintes recursos de segurança serão desativados:"</string>
|
||||
<string name="screen_key_backup_disable_confirmation_action_turn_off">"Apagar"</string>
|
||||
<string name="screen_key_backup_disable_confirmation_description">"Você perderá o seu histórico de mensagens criptografadas e precisará reconfigurar sua identidade digital se remover todos os dispositivos."</string>
|
||||
<string name="screen_key_backup_disable_confirmation_title">"Tem certeza de que deseja apagar o armazenamento de chaves?"</string>
|
||||
<string name="screen_key_backup_disable_description">"Ao apagar o armazenamento de chaves, a sua identidade digital e as chaves das mensagens serão apagadas do servidor e os seguintes recursos de segurança serão desativados:"</string>
|
||||
<string name="screen_key_backup_disable_description_point_1">"Você não terá o histórico de mensagens criptografadas em dispositivos novos"</string>
|
||||
<string name="screen_key_backup_disable_description_point_2">"Você perderá o acesso às suas mensagens criptografadas se for desconectado de %1$s em todos os dispositivos"</string>
|
||||
<string name="screen_key_backup_disable_title">"Tem certeza de que deseja desativar o armazenamento de chaves e apagá-lo?"</string>
|
||||
@@ -58,7 +58,7 @@
|
||||
<string name="screen_recovery_key_setup_generate_key">"Gere sua chave de recuperação"</string>
|
||||
<string name="screen_recovery_key_setup_generate_key_description">"Não compartilhe isso com ninguém!"</string>
|
||||
<string name="screen_recovery_key_setup_success">"Configuração de recuperação bem-sucedida"</string>
|
||||
<string name="screen_recovery_key_setup_title">"Configurar a recuperação"</string>
|
||||
<string name="screen_recovery_key_setup_title">"Receber chave de recuperação"</string>
|
||||
<string name="screen_reset_encryption_confirmation_alert_action">"Sim, redefinir agora"</string>
|
||||
<string name="screen_reset_encryption_confirmation_alert_subtitle">"Esse processo é irreversível."</string>
|
||||
<string name="screen_reset_encryption_confirmation_alert_title">"Você tem certeza de que deseja redefinir sua identidade?"</string>
|
||||
|
||||
@@ -2,34 +2,56 @@
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_chat_backup_key_backup_action_disable">"Вимкнути резервне копіювання"</string>
|
||||
<string name="screen_chat_backup_key_backup_action_enable">"Увімкнути резервне копіювання"</string>
|
||||
<string name="screen_chat_backup_key_backup_description">"Зберігайте свій криптографічний ідентифікатор і ключі повідомлень на сервері. Це дозволить вам переглядати історію повідомлень на будь-яких нових пристроях. %1$s."</string>
|
||||
<string name="screen_chat_backup_key_backup_description">"Це дозволить вам переглядати історію бесід на нових пристроях і необхідно для резервного копіювання бесід і цифрової ідентичності. %1$s."</string>
|
||||
<string name="screen_chat_backup_key_backup_title">"Резервне копіювання"</string>
|
||||
<string name="screen_chat_backup_key_storage_disabled_error">"Щоб налаштувати відновлення, потрібно ввімкнути зберігання ключів."</string>
|
||||
<string name="screen_chat_backup_key_storage_disabled_error">"Для створення резервної копії ваших бесід необхідно ввімкнути функцію зберігання ключів."</string>
|
||||
<string name="screen_chat_backup_key_storage_toggle_description">"Завантажте ключі з цього пристрою"</string>
|
||||
<string name="screen_chat_backup_key_storage_toggle_title">"Дозволити зберігання ключів"</string>
|
||||
<string name="screen_chat_backup_recovery_action_change">"Змінити ключ відновлення"</string>
|
||||
<string name="screen_chat_backup_recovery_action_change_description">"Відновіть криптографічну ідентичність та історію повідомлень за допомогою ключа відновлення, якщо ви втратили всі наявні пристрої."</string>
|
||||
<string name="screen_chat_backup_recovery_action_change_description">"Ваші бесіди автоматично резервуються з використанням наскрізного шифрування. Щоб відновити цю резервну копію та зберегти свою цифрову ідентичність у разі втрати доступу до всіх своїх пристроїв, вам знадобиться ключ відновлення."</string>
|
||||
<string name="screen_chat_backup_recovery_action_confirm">"Введіть ключ відновлення"</string>
|
||||
<string name="screen_chat_backup_recovery_action_confirm_description">"Сховище ключів наразі не синхронізовано."</string>
|
||||
<string name="screen_chat_backup_recovery_action_setup">"Налаштувати відновлення"</string>
|
||||
<string name="screen_chat_backup_recovery_action_setup_description">"Ваші чати автоматично резервуються з використанням наскрізного шифрування. Щоб відновити цю резервну копію та зберегти свою цифрову ідентичність у разі втрати доступу до всіх своїх пристроїв, вам знадобиться ключ відновлення."</string>
|
||||
<string name="screen_chat_backup_recovery_action_setup">"Отримати ключ відновлення"</string>
|
||||
<string name="screen_chat_backup_recovery_action_setup_description">"Ваші бесіди автоматично резервуються з використанням наскрізного шифрування. Щоб відновити цю резервну копію та зберегти свою цифрову ідентичність у разі втрати доступу до всіх своїх пристроїв, вам знадобиться ключ відновлення."</string>
|
||||
<string name="screen_create_new_recovery_key_list_item_1">"Відкрийте %1$s на комп\'ютері"</string>
|
||||
<string name="screen_create_new_recovery_key_list_item_2">"Увійдіть до вашого облікового запису знову"</string>
|
||||
<string name="screen_create_new_recovery_key_list_item_3">"Коли вас попросять підтвердити пристрій, виберіть %1$s"</string>
|
||||
<string name="screen_create_new_recovery_key_list_item_3">"Коли вас попросять звірити пристрій, виберіть %1$s"</string>
|
||||
<string name="screen_create_new_recovery_key_list_item_3_reset_all">"“Скинути все”"</string>
|
||||
<string name="screen_create_new_recovery_key_list_item_4">"Дотримуйтесь інструкцій, щоб створити новий ключ відновлення"</string>
|
||||
<string name="screen_create_new_recovery_key_list_item_5">"Збережіть новий ключ відновлення у менеджері паролів або зашифрованій нотатці"</string>
|
||||
<string name="screen_create_new_recovery_key_title">"Скинути шифрування облікового запису за допомогою іншого пристрою"</string>
|
||||
<string name="screen_custom_recovery_key_confirm_error_mismatch">"Введений ключ відновлення не збігається"</string>
|
||||
<string name="screen_custom_recovery_key_confirm_submit">"Завершити налаштування"</string>
|
||||
<string name="screen_custom_recovery_key_confirm_subtitle">"Повторно введіть свій ключ відновлення."</string>
|
||||
<string name="screen_custom_recovery_key_confirm_title">"Підтвердьте свій ключ відновлення"</string>
|
||||
<plurals name="screen_custom_recovery_key_input_notice">
|
||||
<item quantity="one">"Щонайменше %1$d символ. Не використовуйте пароль облікового запису."</item>
|
||||
<item quantity="few">"Щонайменше %1$d символи. Не використовуйте пароль облікового запису."</item>
|
||||
<item quantity="many">"Щонайменше %1$d символів. Не використовуйте пароль облікового запису."</item>
|
||||
</plurals>
|
||||
<string name="screen_custom_recovery_key_input_strength">"Надійність"</string>
|
||||
<string name="screen_custom_recovery_key_input_strength_a11y">"Надійність парольної фрази: %1$s"</string>
|
||||
<string name="screen_custom_recovery_key_input_strength_moderate">"Посередня"</string>
|
||||
<string name="screen_custom_recovery_key_input_strength_strong">"Надійна"</string>
|
||||
<string name="screen_custom_recovery_key_input_strength_very_strong">"Дуже надійна"</string>
|
||||
<string name="screen_custom_recovery_key_input_strength_very_weak">"Дуже ненадійна"</string>
|
||||
<string name="screen_custom_recovery_key_input_strength_weak">"Ненадійна"</string>
|
||||
<string name="screen_custom_recovery_key_input_subtitle">"Оберіть ключ відновлення, який ви зможете запам\'ятати."</string>
|
||||
<string name="screen_custom_recovery_key_input_title">"Введіть ключ відновлення"</string>
|
||||
<string name="screen_custom_recovery_key_loading_a11y">"Завантаження вимог до ключа відновлення"</string>
|
||||
<string name="screen_custom_recovery_key_success_notice">"Щоб змінити ключ відновлення, перейдіть до Налаштування → Шифрування → Резервне копіювання"</string>
|
||||
<string name="screen_custom_recovery_key_success_subtitle">"Ви можете використовувати свій ключ відновлення для підтвердження нових пристроїв або відновлення зашифрованих бесід, якщо втратите доступ до всіх своїх пристроїв."</string>
|
||||
<string name="screen_custom_recovery_key_success_title">"Налаштування резервного копіювання завершено"</string>
|
||||
<string name="screen_encryption_reset_action_continue_reset">"Продовжити скидання налаштувань"</string>
|
||||
<string name="screen_encryption_reset_bullet_1">"Дані вашого облікового запису, контакти, налаштування й бесіди будуть збережені"</string>
|
||||
<string name="screen_encryption_reset_bullet_2">"Ви втратите свою наявну історію повідомлень"</string>
|
||||
<string name="screen_encryption_reset_bullet_3">"Вам доведеться верифікувати всі наявні пристрої та контакти повторно"</string>
|
||||
<string name="screen_encryption_reset_footer">"Скидайте ідентичність тільки якщо ви не маєте доступу до інших пристроїв в обліковому записі та втратили свій ключ відновлення."</string>
|
||||
<string name="screen_encryption_reset_title">"Не можете підтвердити? Вам доведеться скинути свою ідентичність."</string>
|
||||
<string name="screen_key_backup_disable_confirmation_action_turn_off">"Вимкнути"</string>
|
||||
<string name="screen_key_backup_disable_confirmation_description">"Ви втратите зашифровані повідомлення, якщо вийдете з усіх пристроїв."</string>
|
||||
<string name="screen_key_backup_disable_confirmation_title">"Ви впевнені, що хочете вимкнути резервне копіювання?"</string>
|
||||
<string name="screen_key_backup_disable_description">"Вимкнення резервного копіювання призведе до видалення поточної резервної копії ключа шифрування та вимкнення інших функцій безпеки. В такому разі ви:"</string>
|
||||
<string name="screen_encryption_reset_bullet_3">"Вам потрібно буде повторно звірити всі наявні пристрої та контакти"</string>
|
||||
<string name="screen_encryption_reset_footer">"Скидайте свою цифрову ідентичність лише якщо у вас немає доступу до іншого звіреного пристрою та ключа відновлення."</string>
|
||||
<string name="screen_encryption_reset_title">"Не можете підтвердити? Вам доведеться скинути свою цифрову ідентичність."</string>
|
||||
<string name="screen_key_backup_disable_confirmation_action_turn_off">"Видалити"</string>
|
||||
<string name="screen_key_backup_disable_confirmation_description">"Якщо ви вилучите всі свої пристрої, ви втратите історію зашифрованих бесід і вам доведеться скинути свою цифрову ідентичність."</string>
|
||||
<string name="screen_key_backup_disable_confirmation_title">"Ви впевнені, що хочете видалити сховище ключів?"</string>
|
||||
<string name="screen_key_backup_disable_description">"Видалення сховища ключів призведе до видалення вашої цифрової ідентичності та ключів повідомлень із сервера, а також вимкне ці функції безпеки:"</string>
|
||||
<string name="screen_key_backup_disable_description_point_1">"Не матимете історії зашифрованих повідомлень на нових пристроях"</string>
|
||||
<string name="screen_key_backup_disable_description_point_2">"Втратите доступ до зашифрованих повідомлень, якщо вийдете з усіх сеансів %1$s"</string>
|
||||
<string name="screen_key_backup_disable_title">"Ви впевнені, що хочете вимкнути резервне копіювання?"</string>
|
||||
@@ -55,16 +77,16 @@
|
||||
<string name="screen_recovery_key_save_title">"Збережіть ключ відновлення"</string>
|
||||
<string name="screen_recovery_key_setup_confirmation_description">"Після цього кроку ви не зможете отримати доступ до нового ключа відновлення."</string>
|
||||
<string name="screen_recovery_key_setup_confirmation_title">"Ви зберегли ключ відновлення?"</string>
|
||||
<string name="screen_recovery_key_setup_description">"Ваша резервна копія чату захищена ключем відновлення. Якщо вам потрібен новий ключ відновлення після налаштування, ви можете відтворити, вибравши «Змінити ключ відновлення»."</string>
|
||||
<string name="screen_recovery_key_setup_description">"Ваше сховище ключів захищено ключем відновлення. Якщо вам знадобиться новий ключ відновлення після налаштування, ви можете створити його повторно, вибравши «Змінити ключ відновлення»."</string>
|
||||
<string name="screen_recovery_key_setup_generate_key">"Згенеруйте ключ відновлення"</string>
|
||||
<string name="screen_recovery_key_setup_generate_key_description">"Не діліться цим ні з ким!"</string>
|
||||
<string name="screen_recovery_key_setup_success">"Налаштування відновлення виконано успішно"</string>
|
||||
<string name="screen_recovery_key_setup_title">"Налаштувати відновлення"</string>
|
||||
<string name="screen_recovery_key_setup_title">"Отримати ключ відновлення"</string>
|
||||
<string name="screen_reset_encryption_confirmation_alert_action">"Так, скинути зараз"</string>
|
||||
<string name="screen_reset_encryption_confirmation_alert_subtitle">"Цей процес незворотний."</string>
|
||||
<string name="screen_reset_encryption_confirmation_alert_title">"Ви впевнені, що хочете скинути шифрування?"</string>
|
||||
<string name="screen_reset_encryption_confirmation_alert_title">"Ви впевнені, що хочете скинути свою цифрову ідентичність?"</string>
|
||||
<string name="screen_reset_encryption_password_error">"Сталася невідома помилка. Будь ласка, перевірте правильність пароля свого облікового запису та повторіть спробу."</string>
|
||||
<string name="screen_reset_encryption_password_placeholder">"Входимо…"</string>
|
||||
<string name="screen_reset_encryption_password_subtitle">"Підтвердьте, що ви хочете скинути шифрування."</string>
|
||||
<string name="screen_reset_encryption_password_subtitle">"Підтвердьте, що ви хочете скинути свою цифрову ідентичність."</string>
|
||||
<string name="screen_reset_encryption_password_title">"Введіть пароль облікового запису, щоб продовжити"</string>
|
||||
</resources>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<string name="screen_start_chat_error_starting_chat">"Παρουσιάστηκε σφάλμα κατά την προσπάθεια έναρξης μιας συνομιλίας"</string>
|
||||
<string name="screen_start_chat_join_room_by_address_action">"Συμμετοχή σε αίθουσα μέσω διεύθυνσης"</string>
|
||||
<string name="screen_start_chat_join_room_by_address_invalid_address">"Μη έγκυρη διεύθυνση"</string>
|
||||
<string name="screen_start_chat_join_room_by_address_placeholder">"Εισάγετε…"</string>
|
||||
<string name="screen_start_chat_join_room_by_address_placeholder">"Εισαγάγετε διεύθυνση…"</string>
|
||||
<string name="screen_start_chat_join_room_by_address_room_found">"Βρέθηκε η αντίστοιχη αίθουσα"</string>
|
||||
<string name="screen_start_chat_join_room_by_address_room_not_found">"Η αίθουσα δεν βρέθηκε"</string>
|
||||
<string name="screen_start_chat_join_room_by_address_supporting_text">"π.χ. #όνομα-αίθουσας:matrix.org"</string>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<string name="screen_start_chat_error_starting_chat">"Vestluse alustamisel tekkis viga"</string>
|
||||
<string name="screen_start_chat_join_room_by_address_action">"Liitu jututoaga aadressi alusel"</string>
|
||||
<string name="screen_start_chat_join_room_by_address_invalid_address">"See pole kehtiv aadress"</string>
|
||||
<string name="screen_start_chat_join_room_by_address_placeholder">"Sisene…"</string>
|
||||
<string name="screen_start_chat_join_room_by_address_placeholder">"Sisesta aadress…"</string>
|
||||
<string name="screen_start_chat_join_room_by_address_room_found">"Leidsime vastava jututoa"</string>
|
||||
<string name="screen_start_chat_join_room_by_address_room_not_found">"Jututuba ei leidu"</string>
|
||||
<string name="screen_start_chat_join_room_by_address_supporting_text">"nt. #jututoa-nimi:matrix.org"</string>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<string name="screen_start_chat_error_starting_chat">"Terjadi kesalahan saat mencoba memulai obrolan"</string>
|
||||
<string name="screen_start_chat_join_room_by_address_action">"Bergabung dalam ruangan berdasarkan alamat"</string>
|
||||
<string name="screen_start_chat_join_room_by_address_invalid_address">"Bukan alamat yang valid"</string>
|
||||
<string name="screen_start_chat_join_room_by_address_placeholder">"Masuk…"</string>
|
||||
<string name="screen_start_chat_join_room_by_address_placeholder">"Masukkan alamat…"</string>
|
||||
<string name="screen_start_chat_join_room_by_address_room_found">"Ruangan yang cocok ditemukan"</string>
|
||||
<string name="screen_start_chat_join_room_by_address_room_not_found">"Ruangan tidak ditemukan"</string>
|
||||
<string name="screen_start_chat_join_room_by_address_supporting_text">"mis. #nama-ruangan:matrix.org"</string>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<string name="screen_start_chat_error_starting_chat">"Wystąpił błąd podczas próby rozpoczęcia czatu"</string>
|
||||
<string name="screen_start_chat_join_room_by_address_action">"Dołącz do pokoju za pomocą adresu"</string>
|
||||
<string name="screen_start_chat_join_room_by_address_invalid_address">"Nieprawidłowy adres"</string>
|
||||
<string name="screen_start_chat_join_room_by_address_placeholder">"Wprowadź…"</string>
|
||||
<string name="screen_start_chat_join_room_by_address_placeholder">"Wprowadź adres…"</string>
|
||||
<string name="screen_start_chat_join_room_by_address_room_found">"Znaleziono pasujący pokój"</string>
|
||||
<string name="screen_start_chat_join_room_by_address_room_not_found">"Nie znaleziono pokoju"</string>
|
||||
<string name="screen_start_chat_join_room_by_address_supporting_text">"np. #room-name:matrix.org"</string>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<string name="screen_start_chat_error_starting_chat">"Під час спроби почати бесіду сталася помилка"</string>
|
||||
<string name="screen_start_chat_join_room_by_address_action">"Приєднатися до кімнати за адресою"</string>
|
||||
<string name="screen_start_chat_join_room_by_address_invalid_address">"Недійсна адреса"</string>
|
||||
<string name="screen_start_chat_join_room_by_address_placeholder">"Введіть…"</string>
|
||||
<string name="screen_start_chat_join_room_by_address_placeholder">"Увести адресу…"</string>
|
||||
<string name="screen_start_chat_join_room_by_address_room_found">"Знайдено відповідну кімнату"</string>
|
||||
<string name="screen_start_chat_join_room_by_address_room_not_found">"Кімната не знайдена"</string>
|
||||
<string name="screen_start_chat_join_room_by_address_supporting_text">"наприклад, #room-name:matrix.org"</string>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<string name="screen_start_chat_error_starting_chat">"在开始聊天时发生了错误"</string>
|
||||
<string name="screen_start_chat_join_room_by_address_action">"输入地址加入房间"</string>
|
||||
<string name="screen_start_chat_join_room_by_address_invalid_address">"地址无效"</string>
|
||||
<string name="screen_start_chat_join_room_by_address_placeholder">"输入…"</string>
|
||||
<string name="screen_start_chat_join_room_by_address_placeholder">"输入地址…"</string>
|
||||
<string name="screen_start_chat_join_room_by_address_room_found">"找到匹配的房间"</string>
|
||||
<string name="screen_start_chat_join_room_by_address_room_not_found">"未找到房间"</string>
|
||||
<string name="screen_start_chat_join_room_by_address_supporting_text">"例如 #room-name:matrix.org"</string>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<string name="screen_start_chat_error_starting_chat">"An error occurred when trying to start a chat"</string>
|
||||
<string name="screen_start_chat_join_room_by_address_action">"Join room by address"</string>
|
||||
<string name="screen_start_chat_join_room_by_address_invalid_address">"Not a valid address"</string>
|
||||
<string name="screen_start_chat_join_room_by_address_placeholder">"Enter…"</string>
|
||||
<string name="screen_start_chat_join_room_by_address_placeholder">"Enter address…"</string>
|
||||
<string name="screen_start_chat_join_room_by_address_room_found">"Matching room found"</string>
|
||||
<string name="screen_start_chat_join_room_by_address_room_not_found">"Room not found"</string>
|
||||
<string name="screen_start_chat_join_room_by_address_supporting_text">"e.g. #room-name:matrix.org"</string>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<string name="screen_room_member_details_unblock_alert_action">"Розблокувати"</string>
|
||||
<string name="screen_room_member_details_unblock_alert_description">"Ви знову зможете бачити всі повідомлення від них."</string>
|
||||
<string name="screen_room_member_details_unblock_user">"Розблокувати користувача"</string>
|
||||
<string name="screen_room_member_details_verify_button_subtitle">"Використовуйте веб-додаток, щоб верифікувати цього користувача."</string>
|
||||
<string name="screen_room_member_details_verify_button_title">"Перевірте %1$s"</string>
|
||||
<string name="screen_room_member_details_verify_button_subtitle">"Використовуйте вебзастосунок, щоб звірити цього користувача."</string>
|
||||
<string name="screen_room_member_details_verify_button_title">"Звірити %1$s"</string>
|
||||
<string name="screen_start_chat_error_starting_chat">"Під час спроби почати бесіду сталася помилка"</string>
|
||||
</resources>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_identity_confirmation_cannot_confirm">"Tidak dapat mengonfirmasi?"</string>
|
||||
<string name="screen_identity_confirmation_create_new_recovery_key">"Buat kunci pemulihan baru"</string>
|
||||
<string name="screen_identity_confirmation_subtitle">"Verifikasi perangkat ini untuk menyiapkan perpesanan aman."</string>
|
||||
<string name="screen_identity_confirmation_subtitle">"Pilih cara verifikasi untuk mengatur pengiriman pesan yang aman."</string>
|
||||
<string name="screen_identity_confirmation_title">"Konfirmasi bahwa ini Anda"</string>
|
||||
<string name="screen_identity_confirmation_use_another_device">"Gunakan perangkat lain"</string>
|
||||
<string name="screen_identity_confirmation_use_recovery_key">"Gunakan kunci pemulihan"</string>
|
||||
|
||||
@@ -50,5 +50,5 @@
|
||||
<string name="screen_session_verification_waiting_subtitle">"Depois de aceito, você poderá continuar com a verificação."</string>
|
||||
<string name="screen_session_verification_waiting_to_accept_subtitle">"Aceite a solicitação para iniciar o processo de verificação na sua outra sessão para continuar."</string>
|
||||
<string name="screen_session_verification_waiting_to_accept_title">"Aguardando para aceitar a solicitação"</string>
|
||||
<string name="screen_signout_in_progress_dialog_content">"Saindo…"</string>
|
||||
<string name="screen_signout_in_progress_dialog_content">"Removendo dispositivo…"</string>
|
||||
</resources>
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_identity_confirmation_cannot_confirm">"Не можете підтвердити?"</string>
|
||||
<string name="screen_identity_confirmation_create_new_recovery_key">"Створити новий ключ відновлення"</string>
|
||||
<string name="screen_identity_confirmation_subtitle">"Верифікуйте цей пристрій, щоб налаштувати безпечний обмін повідомленнями."</string>
|
||||
<string name="screen_identity_confirmation_title">"Підтвердьте, що це ви"</string>
|
||||
<string name="screen_identity_confirmation_subtitle">"Виберіть спосіб звіряння, щоб налаштувати безпечний обмін повідомленнями."</string>
|
||||
<string name="screen_identity_confirmation_title">"Підтвердьте свою цифрову ідентичність"</string>
|
||||
<string name="screen_identity_confirmation_use_another_device">"Використовуйте інший пристрій"</string>
|
||||
<string name="screen_identity_confirmation_use_recovery_key">"Використовуйте ключ відновлення"</string>
|
||||
<string name="screen_identity_confirmed_subtitle">"Тепер ви можете безпечно читати або надсилати повідомлення, і кожен, з ким ви спілкуєтесь, також може довіряти цьому пристрою."</string>
|
||||
<string name="screen_identity_confirmed_title">"Пристрій перевірено"</string>
|
||||
<string name="screen_identity_confirmed_title">"Пристрій звірено"</string>
|
||||
<string name="screen_identity_use_another_device">"Використовуйте інший пристрій"</string>
|
||||
<string name="screen_identity_waiting_on_other_device">"Чекає на інше пристрій…"</string>
|
||||
<string name="screen_session_verification_cancelled_subtitle">"Щось не так. Або час очікування запиту минув, або в запиті було відмовлено."</string>
|
||||
@@ -17,38 +17,38 @@
|
||||
<string name="screen_session_verification_compare_numbers_subtitle">"Переконайтеся, що наведені нижче цифри збігаються з тими, що показані під час вашого іншого сеансу."</string>
|
||||
<string name="screen_session_verification_compare_numbers_title">"Порівняйте цифри"</string>
|
||||
<string name="screen_session_verification_complete_subtitle">"Тепер ви можете безпечно читати або надсилати повідомлення на іншому пристрої."</string>
|
||||
<string name="screen_session_verification_complete_user_subtitle">"Тепер ви можете довіряти особистості цього користувача під час надсилання або отримання повідомлень."</string>
|
||||
<string name="screen_session_verification_device_verified">"Пристрій перевірено"</string>
|
||||
<string name="screen_session_verification_complete_user_subtitle">"Відтепер ви можете довіряти цифровій ідентичності цього користувача під час надсилання або отримання повідомлень"</string>
|
||||
<string name="screen_session_verification_device_verified">"Пристрій звірено"</string>
|
||||
<string name="screen_session_verification_enter_recovery_key">"Введіть ключ відновлення"</string>
|
||||
<string name="screen_session_verification_failed_subtitle">"Або час очікування запиту минув, або запит було відхилено, або виникла розбіжність у верифікації."</string>
|
||||
<string name="screen_session_verification_failed_subtitle">"Або час очікування запиту минув, або запит було відхилено, або виникла розбіжність у звірянні."</string>
|
||||
<string name="screen_session_verification_open_existing_session_subtitle">"Доведіть, що це ви, щоб отримати доступ до історії зашифрованих повідомлень."</string>
|
||||
<string name="screen_session_verification_open_existing_session_title">"Відкрийте активний сеанс"</string>
|
||||
<string name="screen_session_verification_positive_button_canceled">"Повторити верифікацію"</string>
|
||||
<string name="screen_session_verification_positive_button_canceled">"Повторити звіряння"</string>
|
||||
<string name="screen_session_verification_positive_button_initial">"У мене все готово"</string>
|
||||
<string name="screen_session_verification_positive_button_verifying_ongoing">"Очікування збігу"</string>
|
||||
<string name="screen_session_verification_ready_subtitle">"Порівняйте унікальний набір емоджі."</string>
|
||||
<string name="screen_session_verification_request_accepted_subtitle">"Порівняйте унікальні емоджі, переконавшись, що вони показані в однаковому порядку."</string>
|
||||
<string name="screen_session_verification_request_details_timestamp">"Увійшов"</string>
|
||||
<string name="screen_session_verification_request_failure_subtitle">"Або час очікування запиту минув, або запит було відхилено, або виникла розбіжність у верифікації."</string>
|
||||
<string name="screen_session_verification_request_failure_title">"Перевірка не вдалася"</string>
|
||||
<string name="screen_session_verification_request_footer">"Продовжуйте, лише якщо ви ініціювали цю перевірку."</string>
|
||||
<string name="screen_session_verification_request_subtitle">"Перевірте інший пристрій, щоб захистити історію повідомлень."</string>
|
||||
<string name="screen_session_verification_request_failure_subtitle">"Або час очікування запиту минув, або запит було відхилено, або виникла розбіжність у звірянні."</string>
|
||||
<string name="screen_session_verification_request_failure_title">"Не вдалося звірити"</string>
|
||||
<string name="screen_session_verification_request_footer">"Продовжуйте, лише якщо ви ініціювали це звіряння."</string>
|
||||
<string name="screen_session_verification_request_subtitle">"Звірте інший пристрій, щоб захистити історію повідомлень."</string>
|
||||
<string name="screen_session_verification_request_success_subtitle">"Тепер ви можете безпечно читати або надсилати повідомлення на іншому пристрої."</string>
|
||||
<string name="screen_session_verification_request_success_title">"Пристрій перевірено"</string>
|
||||
<string name="screen_session_verification_request_title">"Запитано на верифікацію"</string>
|
||||
<string name="screen_session_verification_request_success_title">"Пристрій звірено"</string>
|
||||
<string name="screen_session_verification_request_title">"Запит на звіряння"</string>
|
||||
<string name="screen_session_verification_they_dont_match">"Вони не збігаються"</string>
|
||||
<string name="screen_session_verification_they_match">"Вони збігаються"</string>
|
||||
<string name="screen_session_verification_use_another_device_subtitle">"Перш ніж починати перевірку звідси, переконайтеся, що програму відкрито на іншому пристрої."</string>
|
||||
<string name="screen_session_verification_use_another_device_title">"Відкрийте додаток на іншому перевіреному пристрої"</string>
|
||||
<string name="screen_session_verification_user_initiator_subtitle">"Для додаткової безпеки верифікуйте цього користувача, порівнявши набір емоджі на ваших пристроях. Зробіть це, використовуючи надійний спосіб спілкування."</string>
|
||||
<string name="screen_session_verification_user_initiator_title">"Верифікувати цього користувача?"</string>
|
||||
<string name="screen_session_verification_user_responder_subtitle">"Для додаткової безпеки інший користувач хоче верифікувати вашу особистість. Вам буде показано набір емоджі для порівняння."</string>
|
||||
<string name="screen_session_verification_waiting_another_device_subtitle">"Ви повинні побачити спливаюче вікно на іншому пристрої. Почніть перевірку звідти."</string>
|
||||
<string name="screen_session_verification_waiting_another_device_title">"Почніть перевірку на іншому пристрої"</string>
|
||||
<string name="screen_session_verification_waiting_other_device_title">"Почніть перевірку на іншому пристрої"</string>
|
||||
<string name="screen_session_verification_use_another_device_subtitle">"Перш ніж розпочати звіряння звідси, переконайтеся, що ви відкрили застосунок на іншому пристрої."</string>
|
||||
<string name="screen_session_verification_use_another_device_title">"Відкрийте застосунок на іншому звіреному пристрої"</string>
|
||||
<string name="screen_session_verification_user_initiator_subtitle">"Для додаткової безпеки звірте цього користувача, порівнявши набір емоджі на ваших пристроях. Зробіть це, використовуючи надійний спосіб спілкування."</string>
|
||||
<string name="screen_session_verification_user_initiator_title">"Звірити цього користувача?"</string>
|
||||
<string name="screen_session_verification_user_responder_subtitle">"Для додаткової безпеки інший користувач хоче звірити вашу цифрову ідентичність. Вам буде показано набір емодзі для порівняння."</string>
|
||||
<string name="screen_session_verification_waiting_another_device_subtitle">"На іншому пристрої має з’явитися спливне вікно. Розпочніть звіряння звідти."</string>
|
||||
<string name="screen_session_verification_waiting_another_device_title">"Розпочати звіряння на іншому пристрої"</string>
|
||||
<string name="screen_session_verification_waiting_other_device_title">"Розпочати звіряння на іншому пристрої"</string>
|
||||
<string name="screen_session_verification_waiting_other_user_title">"Очікування іншого користувача"</string>
|
||||
<string name="screen_session_verification_waiting_subtitle">"Після погодження ви зможете продовжити верифікацію."</string>
|
||||
<string name="screen_session_verification_waiting_to_accept_subtitle">"Щоб продовжити, прийміть запит на початок процесу верифікації в іншому сеансі."</string>
|
||||
<string name="screen_session_verification_waiting_subtitle">"Після схвалення ви зможете продовжити звіряння."</string>
|
||||
<string name="screen_session_verification_waiting_to_accept_subtitle">"Прийміть запит, щоб розпочати процес звіряння в іншому сеансі та продовжити роботу."</string>
|
||||
<string name="screen_session_verification_waiting_to_accept_title">"Очікування на прийняття запиту"</string>
|
||||
<string name="screen_signout_in_progress_dialog_content">"Видалення пристрою…"</string>
|
||||
</resources>
|
||||
|
||||
@@ -22,7 +22,7 @@ camera = "1.6.1"
|
||||
work = "2.11.2"
|
||||
|
||||
# Compose
|
||||
compose_bom = "2026.05.01"
|
||||
compose_bom = "2026.06.00"
|
||||
|
||||
# Coroutines
|
||||
coroutines = "1.11.0"
|
||||
@@ -130,6 +130,7 @@ androidx_compose_material3 = { module = "androidx.compose.material3:material3",
|
||||
androidx_compose_material3_windowsizeclass = { module = "androidx.compose.material3:material3-window-size-class" }
|
||||
androidx_compose_material3_adaptive = "androidx.compose.material3:material3-adaptive-android:1.0.0-alpha06"
|
||||
androidx_compose_ui = { module = "androidx.compose.ui:ui" }
|
||||
androidx_compose_ui_text = { module = "androidx.compose.ui:ui-text" }
|
||||
androidx_compose_ui_tooling = { module = "androidx.compose.ui:ui-tooling" }
|
||||
androidx_compose_ui_tooling_preview = { module = "androidx.compose.ui:ui-tooling-preview" }
|
||||
androidx_compose_ui_test_manifest = { module = "androidx.compose.ui:ui-test-manifest" }
|
||||
@@ -240,7 +241,7 @@ sigpwned_emoji4j = "com.sigpwned:emoji4j-core:16.0.0"
|
||||
metro_runtime = { module = "dev.zacsweers.metro:runtime", version.ref = "metro" }
|
||||
|
||||
# Element Call
|
||||
element_call_embedded = "io.element.android:element-call-embedded:0.20.2"
|
||||
element_call_embedded = "io.element.android:element-call-embedded:0.20.3"
|
||||
|
||||
# Auto services
|
||||
google_autoservice = { module = "com.google.auto.service:auto-service", version.ref = "autoservice" }
|
||||
|
||||
+6
@@ -203,6 +203,12 @@ interface MatrixClient {
|
||||
*/
|
||||
suspend fun markRoomAsFullyRead(roomId: RoomId, eventId: EventId): Result<Unit>
|
||||
|
||||
/**
|
||||
* Mark all joined rooms as read by sending public, private and fully-read receipts
|
||||
* on each room's latest event. Per-room errors are logged and skipped by the SDK.
|
||||
*/
|
||||
suspend fun markAllRoomsAsRead(): Result<Unit>
|
||||
|
||||
/**
|
||||
* Check if linking a new device using QrCode is supported by the server.
|
||||
*/
|
||||
|
||||
+6
@@ -800,6 +800,12 @@ class RustMatrixClient(
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun markAllRoomsAsRead(): Result<Unit> = withContext(sessionDispatcher) {
|
||||
runCatchingExceptions {
|
||||
innerClient.markAllRoomsAsRead()
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun performDatabaseVacuum(): Result<Unit> = withContext(sessionDispatcher) {
|
||||
runCatchingExceptions {
|
||||
Timber.d("Performing database vacuuming for session $sessionId...")
|
||||
|
||||
+5
@@ -117,6 +117,7 @@ class FakeMatrixClient(
|
||||
private val getRecentEmojisLambda: () -> Result<List<String>> = { Result.success(emptyList()) },
|
||||
private val addRecentEmojiLambda: (String) -> Result<Unit> = { Result.success(Unit) },
|
||||
private val markRoomAsFullyReadResult: (RoomId, EventId) -> Result<Unit> = { _, _ -> lambdaError() },
|
||||
private val markAllRoomsAsReadResult: () -> Result<Unit> = { Result.success(Unit) },
|
||||
private val performDatabaseVacuumLambda: () -> Result<Unit> = { lambdaError() },
|
||||
private val getMapStyleUrlResult: () -> Result<String?> = { lambdaError() },
|
||||
private val getDatabaseSizesLambda: () -> Result<SdkStoreSizes> = { lambdaError() },
|
||||
@@ -373,6 +374,10 @@ class FakeMatrixClient(
|
||||
return markRoomAsFullyReadResult(roomId, eventId)
|
||||
}
|
||||
|
||||
override suspend fun markAllRoomsAsRead(): Result<Unit> {
|
||||
return markAllRoomsAsReadResult()
|
||||
}
|
||||
|
||||
override suspend fun performDatabaseVacuum(): Result<Unit> {
|
||||
return performDatabaseVacuumLambda()
|
||||
}
|
||||
|
||||
@@ -3,5 +3,7 @@
|
||||
<string name="screen_bottom_sheet_create_dm_confirmation_button_title">"Αποστολή πρόσκλησης"</string>
|
||||
<string name="screen_bottom_sheet_create_dm_message">"Θα θέλατε να ξεκινήσετε μια συνομιλία με τον χρήστη %1$s;"</string>
|
||||
<string name="screen_bottom_sheet_create_dm_title">"Αποστολή πρόσκλησης;"</string>
|
||||
<string name="screen_bottom_sheet_create_dm_unknown_user_content">"Προς το παρόν δεν έχετε καμία συνομιλία με αυτό το άτομο. Επιβεβαιώστε την πρόσκλησή του πριν συνεχίσετε."</string>
|
||||
<string name="screen_bottom_sheet_create_dm_unknown_user_title">"Έναρξη συνομιλίας με αυτήν τη νέα επαφή;"</string>
|
||||
<string name="screen_invites_invited_you">"%1$s (%2$s) σέ προσκάλεσε"</string>
|
||||
</resources>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<string name="screen_bottom_sheet_create_dm_confirmation_button_title">"Надіслати запрошення"</string>
|
||||
<string name="screen_bottom_sheet_create_dm_message">"Хочете розпочати бесіду з %1$s?"</string>
|
||||
<string name="screen_bottom_sheet_create_dm_title">"Надіслати запрошення?"</string>
|
||||
<string name="screen_bottom_sheet_create_dm_unknown_user_content">"Наразі у вас немає чатів із цим користувачем. Підтвердьте запрошення, перш ніж продовжити."</string>
|
||||
<string name="screen_bottom_sheet_create_dm_unknown_user_title">"Розпочати чат із цим новим контактом?"</string>
|
||||
<string name="screen_bottom_sheet_create_dm_unknown_user_content">"Наразі у вас немає бесід з цим користувачем. Підтвердьте запрошення, перш ніж продовжити."</string>
|
||||
<string name="screen_bottom_sheet_create_dm_unknown_user_title">"Розпочати бесіду з цим новим контактом?"</string>
|
||||
<string name="screen_invites_invited_you">"%1$s (%2$s) запрошує вас"</string>
|
||||
</resources>
|
||||
|
||||
@@ -48,6 +48,8 @@
|
||||
<string name="push_distributor_background_sync_android">"Sinkronisasi latar belakang"</string>
|
||||
<string name="push_distributor_firebase_android">"Layanan Google"</string>
|
||||
<string name="push_no_valid_google_play_services_apk_android">"Tidak ditemukan Layanan Google Play yang valid. Pemberitahuan mungkin tidak berfungsi dengan baik."</string>
|
||||
<string name="troubleshoot_notifications_test_blocked_users_description">"Memeriksa pengguna yang diblokir"</string>
|
||||
<string name="troubleshoot_notifications_test_blocked_users_result_none">"Tidak ada pengguna yang diblokir."</string>
|
||||
<string name="troubleshoot_notifications_test_blocked_users_title">"Pengguna yang diblokir"</string>
|
||||
<string name="troubleshoot_notifications_test_current_push_provider_description">"Dapatkan nama penyedia saat ini."</string>
|
||||
<string name="troubleshoot_notifications_test_current_push_provider_failure">"Tidak ada penyedia notifikasi dorongan yang dipilih."</string>
|
||||
|
||||
@@ -15,14 +15,14 @@
|
||||
<item quantity="few">"%d сповіщення"</item>
|
||||
<item quantity="many">"%d сповіщень"</item>
|
||||
</plurals>
|
||||
<string name="notification_error_unified_push_unregistered_android">"Розподільник сповіщень UnifiedPush не вдалося зареєструвати, тому ви більше не отримуватимете сповіщень. Перевірте налаштування сповіщень у додатку та статус розподільника push-сповіщень."</string>
|
||||
<string name="notification_error_unified_push_unregistered_android">"Розподільник сповіщень UnifiedPush не вдалося зареєструвати, тому ви більше не отримуватимете сповіщень. Перевірте налаштування сповіщень у застосунку та стан розподільника push-сповіщень."</string>
|
||||
<string name="notification_fallback_content">"У вас є нові повідомлення."</string>
|
||||
<plurals name="notification_fallback_n_content">
|
||||
<item quantity="one">"У вас %d нове повідомлення."</item>
|
||||
<item quantity="few">"У вас %d нових повідомлення."</item>
|
||||
<item quantity="many">"У вас %d нових повідомлень."</item>
|
||||
</plurals>
|
||||
<string name="notification_incoming_audio_call">"📞 Вхідний дзвінок"</string>
|
||||
<string name="notification_incoming_audio_call">"📞 Вхідний виклик"</string>
|
||||
<string name="notification_incoming_call">"📹 Вхідний виклик"</string>
|
||||
<string name="notification_inline_reply_failed">"** Не вдалося надіслати - відкрийте кімнату"</string>
|
||||
<string name="notification_invitation_action_join">"Доєднатися"</string>
|
||||
@@ -33,7 +33,7 @@
|
||||
<item quantity="many">"%d запрошень"</item>
|
||||
</plurals>
|
||||
<string name="notification_invite_body">"Запрошує вас до бесіди"</string>
|
||||
<string name="notification_invite_body_with_sender">"%1$s запросив вас до чату"</string>
|
||||
<string name="notification_invite_body_with_sender">"%1$s запрошує вас до бесіди"</string>
|
||||
<string name="notification_mentioned_you_body">"Вас згадує: %1$s"</string>
|
||||
<string name="notification_new_messages">"Нові повідомлення"</string>
|
||||
<plurals name="notification_new_messages_for_room">
|
||||
@@ -81,7 +81,7 @@
|
||||
<string name="troubleshoot_notifications_test_blocked_users_title">"Заблоковані користувачі"</string>
|
||||
<string name="troubleshoot_notifications_test_current_push_provider_description">"Отримує назву поточного постачальника."</string>
|
||||
<string name="troubleshoot_notifications_test_current_push_provider_failure">"Постачальників push-сповіщень не вибрано."</string>
|
||||
<string name="troubleshoot_notifications_test_current_push_provider_failure_distributor_not_found">"Поточний провайдер push-повідомлень: %1$s та поточний дистриб\'ютор: %2$s. Але дистриб\'ютор %3$s не знайдено. Можливо, додаток було видалено?"</string>
|
||||
<string name="troubleshoot_notifications_test_current_push_provider_failure_distributor_not_found">"Поточний провайдер push-повідомлень: %1$s та поточний дистриб\'ютор: %2$s. Але дистриб\'ютора %3$s не знайдено. Можливо, застосунок було видалено?"</string>
|
||||
<string name="troubleshoot_notifications_test_current_push_provider_failure_no_distributor">"Поточний постачальник push-сповіщень: %1$s, але дистриб\'юторів не налаштовано."</string>
|
||||
<string name="troubleshoot_notifications_test_current_push_provider_success">"Поточний постачальник: %1$s."</string>
|
||||
<string name="troubleshoot_notifications_test_current_push_provider_success_with_distributor">"Поточний постачальник push-сповіщень: %1$s (%2$s)"</string>
|
||||
|
||||
@@ -463,6 +463,13 @@
|
||||
<string name="screen_create_poll_options_section_title">"Επιλογές"</string>
|
||||
<string name="screen_create_poll_remove_accessibility_label">"Αφαίρεση %1$s"</string>
|
||||
<string name="screen_create_poll_settings_section_title">"Ρυθμίσεις"</string>
|
||||
<string name="screen_live_location_sheet_nobody_sharing">"Κανείς δεν μοιράζεται την τοποθεσία του"</string>
|
||||
<string name="screen_live_location_sheet_sharing_live_location">"Κοινοποιείς την τοποθεσία σε πραγματικό χρόνο"</string>
|
||||
<plurals name="screen_live_location_sheet_subtitle">
|
||||
<item quantity="one">"%1$d άτομο"</item>
|
||||
<item quantity="other">"%1$d άτομα"</item>
|
||||
</plurals>
|
||||
<string name="screen_live_location_sheet_title">"Στον χάρτη"</string>
|
||||
<string name="screen_media_picker_error_failed_selection">"Αποτυχία επιλογής πολυμέσου, δοκίμασε ξανά."</string>
|
||||
<string name="screen_pinned_timeline_empty_state_description">"Πάτα σε ένα μήνυμα και επέλεξε «%1$s» για να συμπεριληφθεί εδώ."</string>
|
||||
<string name="screen_pinned_timeline_empty_state_headline">"Καρφίτσωσε σημαντικά μηνύματα, ώστε να μπορούν να εντοπιστούν εύκολα"</string>
|
||||
@@ -487,6 +494,7 @@
|
||||
<string name="screen_room_event_pill">"Μήνυμα στο %1$s"</string>
|
||||
<string name="screen_room_grouped_state_events_expand">"Επέκταση"</string>
|
||||
<string name="screen_room_grouped_state_events_reduce">"Μείωση"</string>
|
||||
<string name="screen_room_live_location_banner">"Κοινοποιείς την τοποθεσία σε πραγματικό χρόνο"</string>
|
||||
<string name="screen_room_permalink_same_room_android">"Βλέπετε ήδη αυτήν την αίθουσα!"</string>
|
||||
<string name="screen_room_pinned_banner_indicator">"%1$s από %2$s"</string>
|
||||
<string name="screen_room_pinned_banner_indicator_description">"%1$s Καρφιτσωμένα μηνύματα"</string>
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
<string name="a11y_address">"Aadress"</string>
|
||||
<string name="a11y_avatar">"Tunnuspilt"</string>
|
||||
<string name="a11y_collapse_message_text_field">"Vähenda tekstivälja"</string>
|
||||
<string name="a11y_create_poll_votes_allowed_decrease">"Vähenda kasutaja kohta lubatud hääletuskordi"</string>
|
||||
<string name="a11y_create_poll_votes_allowed_increase">"Suurenda kasutaja kohta lubatud hääletuskordi"</string>
|
||||
<string name="a11y_delete">"Kustuta"</string>
|
||||
<plurals name="a11y_digits_entered">
|
||||
<item quantity="one">"%1$d number sisestatud"</item>
|
||||
@@ -30,6 +32,7 @@
|
||||
<string name="a11y_page_n">"%1$d. lehekülg"</string>
|
||||
<string name="a11y_pause">"Peata"</string>
|
||||
<string name="a11y_paused_voice_message">"Häälsõnum, kestus:%1$s, praegune asukoht: %2$s"</string>
|
||||
<string name="a11y_photo_preview">"Foto eelvaade"</string>
|
||||
<string name="a11y_pin_field">"PIN-koodi väli"</string>
|
||||
<string name="a11y_pinned_location">"Esiletõstetud asukoht"</string>
|
||||
<string name="a11y_play">"Esita"</string>
|
||||
@@ -64,6 +67,7 @@
|
||||
<string name="a11y_tombstoned_room">"Lõpetatuks märgitud jututuba"</string>
|
||||
<string name="a11y_user_avatar">"Kasutaja tunnuspilt"</string>
|
||||
<string name="a11y_user_menu">"Kasutajamenüü"</string>
|
||||
<string name="a11y_video_preview">"Video eelvaade"</string>
|
||||
<string name="a11y_view_avatar">"Vaata tunnuspilti"</string>
|
||||
<string name="a11y_view_details">"Vaata üksikasju"</string>
|
||||
<string name="a11y_voice_message">"Häälsõnum, kestus:%1$s"</string>
|
||||
@@ -192,9 +196,11 @@
|
||||
<string name="action_translate">"Tõlgi"</string>
|
||||
<string name="action_try_again">"Proovi uuesti"</string>
|
||||
<string name="action_unpin">"Eemalda esiletõstmine"</string>
|
||||
<string name="action_video_call">"Videokõne"</string>
|
||||
<string name="action_view">"Vaata"</string>
|
||||
<string name="action_view_in_timeline">"Vaata ajajoonel"</string>
|
||||
<string name="action_view_source">"Vaata lähtekoodi"</string>
|
||||
<string name="action_voice_call">"Häälkõne"</string>
|
||||
<string name="action_yes">"Jah"</string>
|
||||
<string name="action_yes_try_again">"Jah, proovi uuesti"</string>
|
||||
<string name="banner_migrate_to_native_sliding_sync_description">"Sinu koduserver toetab uut ja kiiremat protokolli. Uuendamiseks logi korraks rakendusest välja ja siis tagasi. Mingil hetkel tulevikus vana protokoll eemaldatakse kasutusest ja tehes uuenduse nüüd, väldid hilisemat sundkorras uuendust."</string>
|
||||
@@ -259,6 +265,7 @@ Põhjus: %1$s."</string>
|
||||
<string name="common_file_saved_on_disk_android">"Fail on salvestatud kausta Allalaadimised"</string>
|
||||
<string name="common_forward_message">"Edasta sõnum"</string>
|
||||
<string name="common_frequently_used">"Sagedasti kasutatud"</string>
|
||||
<string name="common_gallery">"Galerii"</string>
|
||||
<string name="common_gif">"GIF"</string>
|
||||
<string name="common_group_call_in_progress">"Rühmakõne on pooleli"</string>
|
||||
<string name="common_image">"Pilt"</string>
|
||||
@@ -486,6 +493,7 @@ Kas sa oled kindel, et soovid jätkata?"</string>
|
||||
<string name="screen_create_poll_options_section_title">"Valikud"</string>
|
||||
<string name="screen_create_poll_remove_accessibility_label">"Kustuta: %1$s"</string>
|
||||
<string name="screen_create_poll_settings_section_title">"Seadistused"</string>
|
||||
<string name="screen_create_poll_votes_allowed_per_person">"Hääletuskordi kasutaja kohta"</string>
|
||||
<string name="screen_live_location_sheet_nobody_sharing">"Mitte keegi ei jaga oma asukohta"</string>
|
||||
<string name="screen_live_location_sheet_sharing_live_location">"Asukoht on jagamisel reaalajas"</string>
|
||||
<plurals name="screen_live_location_sheet_subtitle">
|
||||
|
||||
@@ -145,7 +145,7 @@
|
||||
<string name="action_show">"Tampilkan"</string>
|
||||
<string name="action_sign_in_again">"Masuk lagi"</string>
|
||||
<string name="action_signout">"Hapus device dari akun"</string>
|
||||
<string name="action_signout_anyway">"Keluar saja"</string>
|
||||
<string name="action_signout_anyway">"Hapus Perangkat ini"</string>
|
||||
<string name="action_skip">"Lewati"</string>
|
||||
<string name="action_start">"Mulai"</string>
|
||||
<string name="action_start_chat">"Mulai obrolan"</string>
|
||||
@@ -184,6 +184,7 @@
|
||||
<string name="common_creating_room">"Membuat ruangan…"</string>
|
||||
<string name="common_current_user_canceled_knock">"Permintaan dibatalkan"</string>
|
||||
<string name="common_current_user_left_room">"Keluar dari ruangan"</string>
|
||||
<string name="common_current_user_left_space">"Ruang tersisa"</string>
|
||||
<string name="common_current_user_rejected_invite">"Undangan ditolak"</string>
|
||||
<string name="common_decryption_error">"Kesalahan dekripsi"</string>
|
||||
<string name="common_description">"Deskripsi"</string>
|
||||
@@ -296,8 +297,9 @@ Alasan: %1$s."</string>
|
||||
<string name="common_server_unreachable">"Server tidak dapat dijangkau"</string>
|
||||
<string name="common_server_url">"URL Server"</string>
|
||||
<string name="common_settings">"Pengaturan"</string>
|
||||
<string name="common_share_space">"Berbagi ruang"</string>
|
||||
<string name="common_shared_location">"Lokasi terbagi"</string>
|
||||
<string name="common_signing_out">"Mengeluarkan dari akun"</string>
|
||||
<string name="common_signing_out">"Melepaskan perangkat"</string>
|
||||
<string name="common_something_went_wrong">"Ada yang salah"</string>
|
||||
<string name="common_something_went_wrong_message">"Kami mengalami masalah. Silakan coba lagi."</string>
|
||||
<string name="common_space">"Space"</string>
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
<string name="a11y_address">"Adres"</string>
|
||||
<string name="a11y_avatar">"Awatar"</string>
|
||||
<string name="a11y_collapse_message_text_field">"Zmniejsz pole tekstowe wiadomości"</string>
|
||||
<string name="a11y_create_poll_votes_allowed_decrease">"Zmniejsz liczbę głosów dozwolonych na osobę"</string>
|
||||
<string name="a11y_create_poll_votes_allowed_increase">"Zwiększ liczbę głosów dozwolonych na osobę"</string>
|
||||
<string name="a11y_delete">"Usuń"</string>
|
||||
<plurals name="a11y_digits_entered">
|
||||
<item quantity="one">"Wprowadzono %1$d cyfrę"</item>
|
||||
@@ -196,9 +198,11 @@
|
||||
<string name="action_translate">"Przetłumacz"</string>
|
||||
<string name="action_try_again">"Spróbuj ponownie"</string>
|
||||
<string name="action_unpin">"Odepnij"</string>
|
||||
<string name="action_video_call">"Rozmowa wideo"</string>
|
||||
<string name="action_view">"Wyświetl"</string>
|
||||
<string name="action_view_in_timeline">"Wyświetl na osi czasu"</string>
|
||||
<string name="action_view_source">"Wyświetl źródło"</string>
|
||||
<string name="action_voice_call">"Rozmowa głosowa"</string>
|
||||
<string name="action_yes">"Tak"</string>
|
||||
<string name="action_yes_try_again">"Tak, spróbuj ponownie"</string>
|
||||
<string name="banner_migrate_to_native_sliding_sync_description">"Twój serwer wspiera teraz nowy, szybszy protokół. Zaloguj się ponownie, aby zaktualizować. Dzięki temu unikniesz wymuszonego wylogowania, gdy stary protokół zostanie usunięty."</string>
|
||||
@@ -263,6 +267,7 @@ Powód: %1$s."</string>
|
||||
<string name="common_file_saved_on_disk_android">"Plik zapisany do folderu Pobrane"</string>
|
||||
<string name="common_forward_message">"Przekaż wiadomość"</string>
|
||||
<string name="common_frequently_used">"Często używane"</string>
|
||||
<string name="common_gallery">"Galeria"</string>
|
||||
<string name="common_gif">"GIF"</string>
|
||||
<string name="common_group_call_in_progress">"Trwa połączenie grupowe"</string>
|
||||
<string name="common_image">"Zdjęcie"</string>
|
||||
@@ -312,7 +317,7 @@ Powód: %1$s."</string>
|
||||
<string name="common_pinned">"Przypięte"</string>
|
||||
<string name="common_please_check_internet_connection">"Sprawdź swoje połączenie internetowe"</string>
|
||||
<string name="common_please_wait">"Proszę czekać…"</string>
|
||||
<string name="common_poll_end_confirmation">"Jesteś pewien, że chcesz zakończyć tę ankietę?"</string>
|
||||
<string name="common_poll_end_confirmation">"Czy na pewno chcesz zakończyć tę ankietę?"</string>
|
||||
<string name="common_poll_summary">"Ankieta: %1$s"</string>
|
||||
<string name="common_poll_summary_prefix">"Ankieta"</string>
|
||||
<string name="common_poll_total_votes">"Łączna liczba głosów: %1$s"</string>
|
||||
@@ -497,6 +502,7 @@ Czy na pewno chcesz kontynuować?"</string>
|
||||
<string name="screen_create_poll_options_section_title">"Opcje"</string>
|
||||
<string name="screen_create_poll_remove_accessibility_label">"Usuń %1$s"</string>
|
||||
<string name="screen_create_poll_settings_section_title">"Ustawienia"</string>
|
||||
<string name="screen_create_poll_votes_allowed_per_person">"Liczba głosów na osobę"</string>
|
||||
<string name="screen_live_location_sheet_nobody_sharing">"Nikt nie udostępnia swojej lokalizacji"</string>
|
||||
<string name="screen_live_location_sheet_sharing_live_location">"Udostępnianie lokalizacji na żywo"</string>
|
||||
<plurals name="screen_live_location_sheet_subtitle">
|
||||
@@ -506,8 +512,8 @@ Czy na pewno chcesz kontynuować?"</string>
|
||||
</plurals>
|
||||
<string name="screen_live_location_sheet_title">"Na mapie"</string>
|
||||
<string name="screen_media_picker_error_failed_selection">"Nie udało się wybrać multimediów. Spróbuj ponownie."</string>
|
||||
<string name="screen_pinned_timeline_empty_state_description">"Naciśnij wiadomość i wybierz “%1$s”, aby dołączyć tutaj."</string>
|
||||
<string name="screen_pinned_timeline_empty_state_headline">"Przypinaj ważne wiadomości, aby można było je łatwo znaleźć"</string>
|
||||
<string name="screen_pinned_timeline_empty_state_description">"Przytrzymaj wiadomość i wybierz “%1$s”, aby umieścić ją tutaj."</string>
|
||||
<string name="screen_pinned_timeline_empty_state_headline">"Przypinaj ważne wiadomości, by łatwo je później odnaleźć"</string>
|
||||
<plurals name="screen_pinned_timeline_screen_title">
|
||||
<item quantity="one">"%1$d przypięta wiadomość"</item>
|
||||
<item quantity="few">"%1$d przypięte wiadomości"</item>
|
||||
|
||||
@@ -155,8 +155,8 @@
|
||||
<string name="action_share_link">"Compartilhar link"</string>
|
||||
<string name="action_show">"Mostrar"</string>
|
||||
<string name="action_sign_in_again">"Entrar novamente"</string>
|
||||
<string name="action_signout">"Sair"</string>
|
||||
<string name="action_signout_anyway">"Sair mesmo assim"</string>
|
||||
<string name="action_signout">"Remover este dispositivo"</string>
|
||||
<string name="action_signout_anyway">"Remover este dispositivo mesmo assim"</string>
|
||||
<string name="action_skip">"Pular"</string>
|
||||
<string name="action_start">"Iniciar"</string>
|
||||
<string name="action_start_chat">"Iniciar conversa"</string>
|
||||
@@ -473,7 +473,7 @@ Você tem certeza de que deseja continuar?"</string>
|
||||
<string name="screen_share_open_apple_maps">"Abrir no Apple Maps"</string>
|
||||
<string name="screen_share_open_google_maps">"Abrir no Google Maps"</string>
|
||||
<string name="screen_share_open_osm_maps">"Abrir no OpenStreetMap"</string>
|
||||
<string name="screen_share_this_location_action">"Compartilhar esta localização"</string>
|
||||
<string name="screen_share_this_location_action">"Compartilhar localização selecionada"</string>
|
||||
<string name="screen_space_list_description">"Os espaços que você criou ou entrou."</string>
|
||||
<string name="screen_space_list_details">"%1$s • %2$s"</string>
|
||||
<string name="screen_space_list_empty_state_title">"Crie espaços para organizar salas"</string>
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="a11y_add_avatar">"Додати аватар"</string>
|
||||
<string name="a11y_add_reaction">"Додати реакцію: %1$s"</string>
|
||||
<string name="a11y_address">"Адреса"</string>
|
||||
<string name="a11y_avatar">"Аватар"</string>
|
||||
<string name="a11y_collapse_message_text_field">"Згорнути поле тексту повідомлення"</string>
|
||||
<string name="a11y_create_poll_votes_allowed_decrease">"Зменшити кількість голосів, дозволених на одну особу"</string>
|
||||
<string name="a11y_create_poll_votes_allowed_increase">"Збільшити кількість голосів, дозволених на одну особу"</string>
|
||||
<string name="a11y_delete">"Видалити"</string>
|
||||
<plurals name="a11y_digits_entered">
|
||||
<item quantity="one">"Введена %1$d цифра"</item>
|
||||
@@ -30,6 +33,7 @@
|
||||
<string name="a11y_page_n">"Сторінка %1$d"</string>
|
||||
<string name="a11y_pause">"Пауза"</string>
|
||||
<string name="a11y_paused_voice_message">"Голосове повідомлення, тривалість: %1$s, поточна позиція: %2$s"</string>
|
||||
<string name="a11y_photo_preview">"Попередній перегляд світлин"</string>
|
||||
<string name="a11y_pin_field">"Поле PIN-коду"</string>
|
||||
<string name="a11y_pinned_location">"Закріплена локація"</string>
|
||||
<string name="a11y_play">"Відтворити"</string>
|
||||
@@ -54,17 +58,18 @@
|
||||
<string name="a11y_send_files">"Надіслати файли"</string>
|
||||
<string name="a11y_sender_location">"Локація відправника"</string>
|
||||
<string name="a11y_sent_by_sender_at_date">"Надіслано %1$s о %2$s"</string>
|
||||
<string name="a11y_session_verification_time_limited_action_required">"Необхідно виконати дію, обмежену в часі, у вас є одна хвилина для верифікації"</string>
|
||||
<string name="a11y_session_verification_time_limited_action_required">"Необхідно виконати дію, обмежену в часі, ви маєте одну хвилину, щоб звіритись"</string>
|
||||
<string name="a11y_settings_with_required_action">"Налаштування, потрібні дії"</string>
|
||||
<string name="a11y_show_password">"Показати пароль"</string>
|
||||
<string name="a11y_start_call">"Розпочати виклик"</string>
|
||||
<string name="a11y_start_video_call">"Розпочати відеодзвінок"</string>
|
||||
<string name="a11y_start_voice_call">"Розпочати голосовий дзвінок"</string>
|
||||
<string name="a11y_start_video_call">"Розпочати відеовиклик"</string>
|
||||
<string name="a11y_start_voice_call">"Розпочати голосовий виклик"</string>
|
||||
<string name="a11y_thread_in_room">"Гілка в %1$s"</string>
|
||||
<string name="a11y_threads_in_room">"Гілки в %1$s"</string>
|
||||
<string name="a11y_tombstoned_room">"Кімната більше не використовується"</string>
|
||||
<string name="a11y_user_avatar">"Аватар користувача"</string>
|
||||
<string name="a11y_user_menu">"Меню користувача"</string>
|
||||
<string name="a11y_video_preview">"Попередній перегляд відео"</string>
|
||||
<string name="a11y_view_avatar">"Переглянути аватар"</string>
|
||||
<string name="a11y_view_details">"Переглянути подробиці"</string>
|
||||
<string name="a11y_voice_message">"Голосове повідомлення, тривалість: %1$s"</string>
|
||||
@@ -83,7 +88,7 @@
|
||||
<string name="action_choose_photo">"Вибрати фото"</string>
|
||||
<string name="action_clear">"Очистити"</string>
|
||||
<string name="action_close">"Закрити"</string>
|
||||
<string name="action_complete_verification">"Верифікація завершена"</string>
|
||||
<string name="action_complete_verification">"Завершити звіряння"</string>
|
||||
<string name="action_confirm">"Підтвердити"</string>
|
||||
<string name="action_confirm_password">"Підтвердіть пароль"</string>
|
||||
<string name="action_continue">"Продовжити"</string>
|
||||
@@ -179,13 +184,13 @@
|
||||
<string name="action_share_live_location">"Ділитися місцезнаходженням у реальному часі"</string>
|
||||
<string name="action_show">"Показати"</string>
|
||||
<string name="action_sign_in_again">"Увійдіть знову"</string>
|
||||
<string name="action_signout">"Вийти"</string>
|
||||
<string name="action_signout_anyway">"Все одно вийти"</string>
|
||||
<string name="action_signout">"Вилучити цей пристрій"</string>
|
||||
<string name="action_signout_anyway">"Усе одно вилучити цей пристрій"</string>
|
||||
<string name="action_skip">"Пропустити"</string>
|
||||
<string name="action_start">"Розпочати"</string>
|
||||
<string name="action_start_chat">"Розпочати бесіду"</string>
|
||||
<string name="action_start_over">"Почати спочатку"</string>
|
||||
<string name="action_start_verification">"Почати верифікацію"</string>
|
||||
<string name="action_start_verification">"Розпочати звіряння"</string>
|
||||
<string name="action_static_map_load">"Натисніть, щоб завантажити мапу"</string>
|
||||
<string name="action_stop">"Зупинити"</string>
|
||||
<string name="action_take_photo">"Зробити фото"</string>
|
||||
@@ -193,9 +198,11 @@
|
||||
<string name="action_translate">"Перекласти"</string>
|
||||
<string name="action_try_again">"Спробуйте ще раз"</string>
|
||||
<string name="action_unpin">"Відкріпити"</string>
|
||||
<string name="action_video_call">"Відеовиклик"</string>
|
||||
<string name="action_view">"Переглянути"</string>
|
||||
<string name="action_view_in_timeline">"Переглянути на шкалі часу"</string>
|
||||
<string name="action_view_source">"Переглянути джерело"</string>
|
||||
<string name="action_voice_call">"Голосовий виклик"</string>
|
||||
<string name="action_yes">"Так"</string>
|
||||
<string name="action_yes_try_again">"Так, повторити спробу"</string>
|
||||
<string name="banner_migrate_to_native_sliding_sync_description">"Ваш сервер тепер підтримує новий, швидший протокол. Вийдіть із системи та увійдіть знову, щоб оновити систему зараз. Якщо ви зробите це зараз, це допоможе вам уникнути примусового виходу з системи, коли старий протокол буде видалено пізніше."</string>
|
||||
@@ -210,14 +217,15 @@
|
||||
<string name="common_analytics">"Аналітика"</string>
|
||||
<string name="common_android_shortcuts_remove_reason_left_room">"Ви вийшли з кімнати"</string>
|
||||
<string name="common_android_shortcuts_remove_reason_session_logged_out">"Ви вийшли з сеансу"</string>
|
||||
<string name="common_appearance">"Тема"</string>
|
||||
<string name="common_appearance">"Вигляд"</string>
|
||||
<string name="common_audio">"Аудіо"</string>
|
||||
<string name="common_beta">"Бета-версія"</string>
|
||||
<string name="common_blocked_users">"Заблоковані користувачі"</string>
|
||||
<string name="common_bubbles">"Бульбашки"</string>
|
||||
<string name="common_call_declined">"Дзвінок відхилено"</string>
|
||||
<string name="common_call_declined">"Виклик відхилено"</string>
|
||||
<string name="common_call_in_progress">"Виклик триває"</string>
|
||||
<string name="common_call_started">"Виклик розпочато"</string>
|
||||
<string name="common_call_you_declined">"Ви відхилили дзвінок"</string>
|
||||
<string name="common_call_you_declined">"Ви відхилили виклик"</string>
|
||||
<string name="common_chat_backup">"Резервне копіювання бесіди"</string>
|
||||
<string name="common_copied_to_clipboard">"Скопійовано до буферу обміну"</string>
|
||||
<string name="common_copyright">"Авторське право"</string>
|
||||
@@ -259,7 +267,9 @@
|
||||
<string name="common_file_saved_on_disk_android">"Файл збережений у Завантаження"</string>
|
||||
<string name="common_forward_message">"Переслати повідомлення"</string>
|
||||
<string name="common_frequently_used">"Частовживані"</string>
|
||||
<string name="common_gallery">"Галерея"</string>
|
||||
<string name="common_gif">"GIF"</string>
|
||||
<string name="common_group_call_in_progress">"Триває груповий виклик"</string>
|
||||
<string name="common_image">"Зображення"</string>
|
||||
<string name="common_in_reply_to">"У відповідь на %1$s"</string>
|
||||
<string name="common_install_apk_android">"Встановити APK"</string>
|
||||
@@ -351,7 +361,7 @@
|
||||
</plurals>
|
||||
<string name="common_saved_changes">"Збережені зміни"</string>
|
||||
<string name="common_saving">"Збереження"</string>
|
||||
<string name="common_screen_lock">"Блокування екрану"</string>
|
||||
<string name="common_screen_lock">"Блокування екрана"</string>
|
||||
<string name="common_search_for_someone">"Шукати когось"</string>
|
||||
<string name="common_search_results">"Результати пошуку"</string>
|
||||
<string name="common_security">"Безпека"</string>
|
||||
@@ -376,7 +386,7 @@
|
||||
<string name="common_shared_live_location">"Поділитися місцезнаходженням в реальному часі"</string>
|
||||
<string name="common_shared_location">"Поширене розташування"</string>
|
||||
<string name="common_shared_space">"Простір спільного користування"</string>
|
||||
<string name="common_signing_out">"Вихід"</string>
|
||||
<string name="common_signing_out">"Вилучення пристрою"</string>
|
||||
<string name="common_something_went_wrong">"Щось пішло не так"</string>
|
||||
<string name="common_something_went_wrong_message">"Ми зіткнулися з проблемою. Будь ласка, повторіть спробу."</string>
|
||||
<string name="common_space">"Простір"</string>
|
||||
@@ -402,21 +412,22 @@
|
||||
<string name="common_unable_to_decrypt">"Неможливо розшифрувати"</string>
|
||||
<string name="common_unable_to_decrypt_insecure_device">"Надіслано з незахищеного пристрою"</string>
|
||||
<string name="common_unable_to_decrypt_no_access">"Ви не маєте доступу до цього повідомлення"</string>
|
||||
<string name="common_unable_to_decrypt_verification_violation">"Ідентичність відправника скинуто"</string>
|
||||
<string name="common_unable_to_decrypt_verification_violation">"Звірена цифрова ідентичність відправника була скинута"</string>
|
||||
<string name="common_unable_to_invite_message">"Не вдалося надіслати запрошення одному чи кільком користувачам."</string>
|
||||
<string name="common_unable_to_invite_title">"Не вдалося надіслати запрошення"</string>
|
||||
<string name="common_unlock">"Розблокувати"</string>
|
||||
<string name="common_unmute">"Увімкнути звук"</string>
|
||||
<string name="common_unsupported_call">"Непідтриманий виклик"</string>
|
||||
<string name="common_unsupported_event">"Непідтримувана подія"</string>
|
||||
<string name="common_user_started_a_call">"%1$s розпочинає виклик"</string>
|
||||
<string name="common_username">"Ім\'я користувача"</string>
|
||||
<string name="common_verification_cancelled">"Верифікацію скасовано"</string>
|
||||
<string name="common_verification_complete">"Верифікацію завершено"</string>
|
||||
<string name="common_verification_failed">"Перевірка не вдалася"</string>
|
||||
<string name="common_verified">"Перевірено"</string>
|
||||
<string name="common_verify_device">"Верифікувати пристрій"</string>
|
||||
<string name="common_verify_identity">"Підтвердити особу"</string>
|
||||
<string name="common_verify_user">"Верифікувати користувача"</string>
|
||||
<string name="common_verification_cancelled">"Звіряння скасовано"</string>
|
||||
<string name="common_verification_complete">"Звіряння завершено"</string>
|
||||
<string name="common_verification_failed">"Не вдалося звірити"</string>
|
||||
<string name="common_verified">"Звірено"</string>
|
||||
<string name="common_verify_device">"Звірити пристрій"</string>
|
||||
<string name="common_verify_identity">"Підтвердити ідентичність"</string>
|
||||
<string name="common_verify_user">"Звірити користувача"</string>
|
||||
<string name="common_video">"Відео"</string>
|
||||
<string name="common_video_quality_high">"Висока якість"</string>
|
||||
<string name="common_video_quality_high_description">"Найкраща якість, але більший розмір файлу"</string>
|
||||
@@ -433,11 +444,11 @@
|
||||
<string name="crypto_event_key_forwarded_known_profile_dialog_content">"%1$s (%2$s) поділився цим повідомленням, оскільки вас не було в кімнаті, коли його надіслали."</string>
|
||||
<string name="crypto_event_key_forwarded_unknown_profile_dialog_content">"%1$s поділився цим повідомленням, оскільки вас не було в кімнаті, коли його надіслали."</string>
|
||||
<string name="crypto_history_visible">"Згідно із налаштувань цієї кімнати, нові учасники можуть переглядати історію. %1$s"</string>
|
||||
<string name="crypto_identity_change_pin_violation">"Ідентичність %1$s скинуто. %2$s"</string>
|
||||
<string name="crypto_identity_change_pin_violation_new">"Ідентичність %1$s %2$s скинуто. %3$s"</string>
|
||||
<string name="crypto_identity_change_pin_violation">"Цифрову ідентичність %1$s скинуто. %2$s"</string>
|
||||
<string name="crypto_identity_change_pin_violation_new">"Цифрову ідентичність %1$s %2$s скинуто. %3$s"</string>
|
||||
<string name="crypto_identity_change_pin_violation_new_user_id">"(%1$s)"</string>
|
||||
<string name="crypto_identity_change_profile_pin_violation">"Ідентичність %1$s скинуто."</string>
|
||||
<string name="crypto_identity_change_verification_violation_new">"Ідентичність %1$s %2$s скинуто. %3$s"</string>
|
||||
<string name="crypto_identity_change_profile_pin_violation">"Цифрову ідентичність %1$s скинуто."</string>
|
||||
<string name="crypto_identity_change_verification_violation_new">"Цифрову ідентичність %1$s %2$s скинуто. %3$s"</string>
|
||||
<string name="crypto_identity_change_withdraw_verification_action">"Відкликати верифікацію"</string>
|
||||
<string name="dialog_allow_access">"Надати доступ"</string>
|
||||
<string name="dialog_confirm_link_message">"Посилання %1$s спрямовує вас на інший сайт %2$s
|
||||
@@ -485,12 +496,13 @@
|
||||
<string name="live_location_sharing_foreground_service_message_android">"Триває обмін місцезнаходженням"</string>
|
||||
<string name="live_location_sharing_foreground_service_title_android">"%1$s Місцезнаходження в реальному часі"</string>
|
||||
<string name="login_initial_device_name_android">"%1$s Android"</string>
|
||||
<string name="preference_rageshake">"Повідомити про ваду за допомогою Rageshake"</string>
|
||||
<string name="preference_rageshake">"Повідомляти про помилку потрусивши телефон"</string>
|
||||
<string name="screen_bug_report_a11y_screenshot">"Знімок екрана"</string>
|
||||
<string name="screen_create_poll_option_accessibility_label">"%1$s: %2$s"</string>
|
||||
<string name="screen_create_poll_options_section_title">"Варіанти"</string>
|
||||
<string name="screen_create_poll_remove_accessibility_label">"Вилучити %1$s"</string>
|
||||
<string name="screen_create_poll_settings_section_title">"Налаштування"</string>
|
||||
<string name="screen_create_poll_votes_allowed_per_person">"Кількість голосів, дозволених на одну особу"</string>
|
||||
<string name="screen_live_location_sheet_nobody_sharing">"Ніхто не ділиться своєю геопозицією"</string>
|
||||
<string name="screen_live_location_sheet_sharing_live_location">"Обмін геопозицією"</string>
|
||||
<plurals name="screen_live_location_sheet_subtitle">
|
||||
@@ -508,11 +520,11 @@
|
||||
<item quantity="many">"%1$d Закріплених повідомлення"</item>
|
||||
</plurals>
|
||||
<string name="screen_pinned_timeline_screen_title_empty">"Закріплені повідомлення"</string>
|
||||
<string name="screen_reset_identity_confirmation_subtitle">"Ви збираєтеся перейти до свого облікового запису %1$s, щоб скинути свій обліковий запис. Після цього ви повернетесь до програми."</string>
|
||||
<string name="screen_reset_identity_confirmation_title">"Не можете підтвердити? Перейдіть до свого облікового запису, щоб скинути облікові дані."</string>
|
||||
<string name="screen_reset_identity_confirmation_subtitle">"Ви збираєтеся перейти до свого облікового запису %1$s, щоб скинути свою цифрову ідентичність. Після цього ви повернетеся до застосунку."</string>
|
||||
<string name="screen_reset_identity_confirmation_title">"Не можете підтвердити? Перейдіть до свого облікового запису, щоб скинути цифрову ідентичність."</string>
|
||||
<string name="screen_resolve_send_failure_changed_identity_primary_button_title">"Відкликати верифікацію та відправити"</string>
|
||||
<string name="screen_resolve_send_failure_changed_identity_subtitle">"Ви все одно можете відкликати підтвердження та надіслати це повідомлення, або ви можете скасувати підписку на даний момент і спробувати пізніше після повторної перевірки %1$s."</string>
|
||||
<string name="screen_resolve_send_failure_changed_identity_title">"Ваше повідомлення не надіслано, оскільки підтверджену особистість %1$s скинуто"</string>
|
||||
<string name="screen_resolve_send_failure_changed_identity_title">"Ваше повідомлення не надіслано, оскільки звірена цифрова ідентичність %1$s була скинута"</string>
|
||||
<string name="screen_resolve_send_failure_unsigned_device_primary_button_title">"Надіслати повідомлення в будь-якому випадку"</string>
|
||||
<string name="screen_resolve_send_failure_unsigned_device_subtitle">"%1$s використовує один або кілька неперевірених пристроїв. Ви можете відправити повідомлення в будь-якому випадку, або ж скасувати відправку і спробувати пізніше, коли %2$s перевірить всі пристрої."</string>
|
||||
<string name="screen_resolve_send_failure_unsigned_device_title">"Ваше повідомлення не було надіслано, тому що %1$s не перевірив усі пристрої"</string>
|
||||
@@ -545,15 +557,22 @@
|
||||
<string name="screen_space_list_title">"Простори"</string>
|
||||
<string name="screen_static_location_sheet_timestamp_description">"Надано доступ %1$s"</string>
|
||||
<string name="screen_static_location_sheet_title">"На карті"</string>
|
||||
<string name="screen_timeline_item_menu_send_failure_changed_identity">"Повідомлення не надіслано, оскільки підтверджену особистість %1$s скинуто."</string>
|
||||
<plurals name="screen_timeline_active_call_extra_joined_count">
|
||||
<item quantity="one">"+ %1$d приєднується"</item>
|
||||
<item quantity="few">"+ %1$d приєднуються"</item>
|
||||
<item quantity="many">"+ %1$d приєднуються"</item>
|
||||
</plurals>
|
||||
<string name="screen_timeline_item_menu_send_failure_changed_identity">"Повідомлення не надіслано, оскільки звірена цифрова ідентичність %1$s була скинута."</string>
|
||||
<string name="screen_timeline_item_menu_send_failure_unsigned_device">"Повідомлення не надіслано, оскільки %1$s перевірив не всі пристрої."</string>
|
||||
<string name="screen_timeline_item_menu_send_failure_you_unsigned_device">"Повідомлення не надіслано, оскільки ви не підтвердили один або кілька своїх пристроїв."</string>
|
||||
<string name="screen_timeline_item_menu_send_failure_you_unsigned_device">"Повідомлення не надіслано, оскільки ви не звірили один або кілька своїх пристроїв."</string>
|
||||
<string name="screen_view_location_title">"Розташування"</string>
|
||||
<string name="settings_version_number">"Версія: %1$s (%2$s)"</string>
|
||||
<string name="test_language_identifier">"uk"</string>
|
||||
<string name="timeline_decryption_failure_historical_event_no_key_backup">"Історичні повідомлення недоступні на цьому пристрої"</string>
|
||||
<string name="timeline_decryption_failure_historical_event_unverified_device">"Щоб отримати доступ до історичних повідомлень, потрібно верифікувати цей пристрій"</string>
|
||||
<string name="timeline_decryption_failure_historical_event_unverified_device">"Щоб отримати доступ до історії повідомлень, потрібно звірити цей пристрій"</string>
|
||||
<string name="timeline_decryption_failure_historical_event_user_not_joined">"Ви не маєте доступу до цього повідомлення"</string>
|
||||
<string name="timeline_decryption_failure_unable_to_decrypt">"Неможливо розшифрувати повідомлення"</string>
|
||||
<string name="timeline_decryption_failure_withheld_unverified">"Це повідомлення заблоковано оскільки ви не верифікували свій пристрій, або тому, що відправнику потрібно верифікувати вашу особистість."</string>
|
||||
<string name="timeline_decryption_failure_withheld_unverified">"Це повідомлення заблоковано, оскільки ви не звірили свій пристрій або відправник повинен звірити вашу цифрову ідентичність."</string>
|
||||
<string name="vulkan_not_supported_dialog_content_android">"Ваш пристрій занадто старий, потрібен пристрій з Android 8 або новіший."</string>
|
||||
<string name="vulkan_not_supported_dialog_title_android">"Відтворення карт не підтримується"</string>
|
||||
</resources>
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
<string name="a11y_address">"地址"</string>
|
||||
<string name="a11y_avatar">"头像"</string>
|
||||
<string name="a11y_collapse_message_text_field">"最小化消息文本框"</string>
|
||||
<string name="a11y_create_poll_votes_allowed_decrease">"减少每人允许的投票数"</string>
|
||||
<string name="a11y_create_poll_votes_allowed_increase">"增加每人允许的投票数"</string>
|
||||
<string name="a11y_delete">"删除"</string>
|
||||
<plurals name="a11y_digits_entered">
|
||||
<item quantity="other">"已输入 %1$d 个数字"</item>
|
||||
@@ -191,9 +193,11 @@
|
||||
<string name="action_translate">"翻译"</string>
|
||||
<string name="action_try_again">"重试"</string>
|
||||
<string name="action_unpin">"取消置顶"</string>
|
||||
<string name="action_video_call">"视频通话"</string>
|
||||
<string name="action_view">"查看"</string>
|
||||
<string name="action_view_in_timeline">"在时间线上查看"</string>
|
||||
<string name="action_view_source">"查看源码"</string>
|
||||
<string name="action_voice_call">"语音通话"</string>
|
||||
<string name="action_yes">"是"</string>
|
||||
<string name="action_yes_try_again">"是,重试"</string>
|
||||
<string name="banner_migrate_to_native_sliding_sync_description">"你的服务器现在支持更快的新协议。现在注销并重新登录以升级。立即这样做可以避免你在以后删除旧协议时被强制注销。"</string>
|
||||
@@ -258,6 +262,7 @@
|
||||
<string name="common_file_saved_on_disk_android">"文件已保存到“下载”"</string>
|
||||
<string name="common_forward_message">"转发消息"</string>
|
||||
<string name="common_frequently_used">"常用"</string>
|
||||
<string name="common_gallery">"图库"</string>
|
||||
<string name="common_gif">"GIF"</string>
|
||||
<string name="common_group_call_in_progress">"群组通话进行中"</string>
|
||||
<string name="common_image">"图片"</string>
|
||||
@@ -395,7 +400,7 @@
|
||||
<string name="common_unmute">"解除静音"</string>
|
||||
<string name="common_unsupported_call">"不受支持的通话"</string>
|
||||
<string name="common_unsupported_event">"不支持的事件"</string>
|
||||
<string name="common_user_started_a_call">"%1$s 开始了通话"</string>
|
||||
<string name="common_user_started_a_call">"%1$s 已开始通话"</string>
|
||||
<string name="common_username">"用户名"</string>
|
||||
<string name="common_verification_cancelled">"验证已取消"</string>
|
||||
<string name="common_verification_complete">"验证完成"</string>
|
||||
@@ -478,6 +483,7 @@
|
||||
<string name="screen_create_poll_options_section_title">"选项"</string>
|
||||
<string name="screen_create_poll_remove_accessibility_label">"移除 %1$s"</string>
|
||||
<string name="screen_create_poll_settings_section_title">"设置"</string>
|
||||
<string name="screen_create_poll_votes_allowed_per_person">"每人允许的投票数"</string>
|
||||
<string name="screen_live_location_sheet_nobody_sharing">"目前无人分享其位置"</string>
|
||||
<string name="screen_live_location_sheet_sharing_live_location">"共享实时位置"</string>
|
||||
<plurals name="screen_live_location_sheet_subtitle">
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
<string name="a11y_address">"Address"</string>
|
||||
<string name="a11y_avatar">"Avatar"</string>
|
||||
<string name="a11y_collapse_message_text_field">"Minimise message text field"</string>
|
||||
<string name="a11y_create_poll_votes_allowed_decrease">"Decrease votes allowed per person"</string>
|
||||
<string name="a11y_create_poll_votes_allowed_increase">"Increase votes allowed per person"</string>
|
||||
<string name="a11y_delete">"Delete"</string>
|
||||
<plurals name="a11y_digits_entered">
|
||||
<item quantity="one">"%1$d digit entered"</item>
|
||||
@@ -194,9 +196,11 @@
|
||||
<string name="action_translate">"Translate"</string>
|
||||
<string name="action_try_again">"Try again"</string>
|
||||
<string name="action_unpin">"Unpin"</string>
|
||||
<string name="action_video_call">"Video call"</string>
|
||||
<string name="action_view">"View"</string>
|
||||
<string name="action_view_in_timeline">"View in timeline"</string>
|
||||
<string name="action_view_source">"View source"</string>
|
||||
<string name="action_voice_call">"Voice call"</string>
|
||||
<string name="action_yes">"Yes"</string>
|
||||
<string name="action_yes_try_again">"Yes, try again"</string>
|
||||
<string name="banner_migrate_to_native_sliding_sync_description">"Your server now supports a new, faster protocol. Log out and log back in to upgrade now. Doing this now will help you avoid a forced logout when the old protocol is removed later."</string>
|
||||
@@ -261,6 +265,7 @@ Reason: %1$s."</string>
|
||||
<string name="common_file_saved_on_disk_android">"File saved to Downloads"</string>
|
||||
<string name="common_forward_message">"Forward message"</string>
|
||||
<string name="common_frequently_used">"Frequently used"</string>
|
||||
<string name="common_gallery">"Gallery"</string>
|
||||
<string name="common_gif">"GIF"</string>
|
||||
<string name="common_group_call_in_progress">"Group call in progress"</string>
|
||||
<string name="common_image">"Image"</string>
|
||||
@@ -488,6 +493,7 @@ Are you sure you want to continue?"</string>
|
||||
<string name="screen_create_poll_options_section_title">"Options"</string>
|
||||
<string name="screen_create_poll_remove_accessibility_label">"Remove %1$s"</string>
|
||||
<string name="screen_create_poll_settings_section_title">"Settings"</string>
|
||||
<string name="screen_create_poll_votes_allowed_per_person">"Votes allowed per person"</string>
|
||||
<string name="screen_live_location_sheet_nobody_sharing">"Nobody is sharing their location"</string>
|
||||
<string name="screen_live_location_sheet_sharing_live_location">"Sharing live location"</string>
|
||||
<plurals name="screen_live_location_sheet_subtitle">
|
||||
|
||||
@@ -19,6 +19,7 @@ android {
|
||||
dependencies {
|
||||
implementation(projects.libraries.androidutils)
|
||||
implementation(projects.services.toolbox.impl)
|
||||
implementation(libs.androidx.compose.ui.text)
|
||||
|
||||
testCommonDependencies(libs)
|
||||
}
|
||||
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) 2026 Element Creations Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.ui.utils.text
|
||||
|
||||
import androidx.compose.ui.text.style.TextDirection
|
||||
|
||||
/**
|
||||
* Detect if a text is RTL or not, based on its content.
|
||||
*/
|
||||
fun TextDirection.Companion.detect(text: String): TextDirection {
|
||||
return if (text.any(::isRtlChar)) TextDirection.Rtl else TextDirection.Ltr
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect if a character is an RTL character or not, based on its Unicode directionality.
|
||||
*/
|
||||
fun isRtlChar(char: Char): Boolean = when (Character.getDirectionality(char)) {
|
||||
Character.DIRECTIONALITY_RIGHT_TO_LEFT,
|
||||
Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC,
|
||||
Character.DIRECTIONALITY_RIGHT_TO_LEFT_EMBEDDING,
|
||||
Character.DIRECTIONALITY_RIGHT_TO_LEFT_OVERRIDE -> true
|
||||
else -> false
|
||||
}
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user