Merge pull request #5469 from element-hq/feature/bma/newSound
Set a notification sound
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_space_announcement_item1">"Se klynger, du har oprettet eller tilmeldt dig"</string>
|
||||
<string name="screen_space_announcement_item2">"Acceptere eller afvise invitationer til klynger"</string>
|
||||
<string name="screen_space_announcement_item3">"Finde alle rum, du kan deltage i, i dine klynger"</string>
|
||||
<string name="screen_space_announcement_item4">"Deltage i offentlige klynger"</string>
|
||||
<string name="screen_space_announcement_item5">"Forlade de klynger, du har tilsluttet dig"</string>
|
||||
<string name="screen_space_announcement_notice">"Oprettelse og administration af klynger kommer snart."</string>
|
||||
<string name="screen_space_announcement_subtitle">"Velkommen til betaversionen af Klynger! Med denne første version kan du:"</string>
|
||||
<string name="screen_space_announcement_title">"Introduktion til Klynger"</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_space_announcement_item1">"Von dir erstellte oder beigetretene Spaces anzeigen"</string>
|
||||
<string name="screen_space_announcement_item2">"Einladungen zu Spaces annehmen oder ablehnen"</string>
|
||||
<string name="screen_space_announcement_item3">"Chats innerhalb deiner Spaces entdecken, um ihnen beizutreten"</string>
|
||||
<string name="screen_space_announcement_item4">"Öffentlichen Spaces beitreten"</string>
|
||||
<string name="screen_space_announcement_item5">"Spaces verlassen, bei denen du Mitglied bist"</string>
|
||||
<string name="screen_space_announcement_notice">"Das Erstellen und Verwalten von Spaces ist bald verfügbar."</string>
|
||||
<string name="screen_space_announcement_subtitle">"Willkommen bei der Beta-Version von Spaces! Mit dieser ersten Version kannst du:"</string>
|
||||
<string name="screen_space_announcement_title">"Einführung in Spaces"</string>
|
||||
</resources>
|
||||
@@ -2,9 +2,9 @@
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_space_announcement_item1">"Voir les espaces que vous avez créés ou rejoints"</string>
|
||||
<string name="screen_space_announcement_item2">"Accepter ou refuser les invitations aux espaces"</string>
|
||||
<string name="screen_space_announcement_item3">"Découvrez les salons que vous pouvez joindre depuis vos espaces"</string>
|
||||
<string name="screen_space_announcement_item3">"Découvrir les salons que vous pouvez joindre depuis vos espaces"</string>
|
||||
<string name="screen_space_announcement_item4">"Rejoindre les espaces publics"</string>
|
||||
<string name="screen_space_announcement_item5">"Quittez les espaces dont vous êtes membre."</string>
|
||||
<string name="screen_space_announcement_item5">"Quitter les espaces dont vous êtes membre."</string>
|
||||
<string name="screen_space_announcement_notice">"La création et la gestion des espaces seront bientôt disponibles."</string>
|
||||
<string name="screen_space_announcement_subtitle">"Bienvenue dans la version bêta des espaces! Avec cette première version, vous pourrez :"</string>
|
||||
<string name="screen_space_announcement_title">"Ajout des espaces"</string>
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_space_announcement_item1">"Se områder du har opprettet eller blitt med i"</string>
|
||||
<string name="screen_space_announcement_item2">"Godta eller avslå invitasjoner til områder"</string>
|
||||
<string name="screen_space_announcement_item3">"Oppdag alle rom du kan bli med i i dine områder"</string>
|
||||
<string name="screen_space_announcement_item4">"Bli med i offentlige områder"</string>
|
||||
<string name="screen_space_announcement_item5">"Forlat områder du har blitt med i"</string>
|
||||
<string name="screen_space_announcement_notice">"Oppretting og administrasjon av områder kommer snart."</string>
|
||||
<string name="screen_space_announcement_subtitle">"Velkommen til betaversjonen av Områder! Med denne første versjonen kan du:"</string>
|
||||
<string name="screen_space_announcement_title">"Vi introduserer Områder"</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_space_announcement_item1">"Vizualizați spațiile pe care le-ați creat sau la care v-ați alăturat"</string>
|
||||
<string name="screen_space_announcement_item2">"Acceptați sau refuzați invitațiile la spații"</string>
|
||||
<string name="screen_space_announcement_item3">"Descoperiți toate camerele la care vă puteți alătura în spațiile dumneavoastră."</string>
|
||||
<string name="screen_space_announcement_item4">"Alăturați-vă spațiilor publice"</string>
|
||||
<string name="screen_space_announcement_item5">"Părăsiți spațiile la care v-ați alăturat."</string>
|
||||
<string name="screen_space_announcement_notice">"Crearea și gestionarea spațiilor vor fi disponibile în curând."</string>
|
||||
<string name="screen_space_announcement_subtitle">"Bun venit la versiunea beta a Spațiilor! Cu această primă versiune puteți:"</string>
|
||||
<string name="screen_space_announcement_title">"Vă prezentăm Spații"</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2025 New Vector 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.components
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import io.element.android.features.home.impl.R
|
||||
import io.element.android.libraries.designsystem.components.Announcement
|
||||
import io.element.android.libraries.designsystem.components.AnnouncementType
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
|
||||
@Composable
|
||||
internal fun NewNotificationSoundBanner(
|
||||
onDismissClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Announcement(
|
||||
modifier = modifier.roomListBannerPadding(),
|
||||
title = stringResource(R.string.banner_new_sound_title),
|
||||
description = stringResource(R.string.banner_new_sound_message),
|
||||
type = AnnouncementType.Actionable(
|
||||
actionText = stringResource(CommonStrings.action_ok),
|
||||
onActionClick = onDismissClick,
|
||||
onDismissClick = onDismissClick,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@PreviewsDayNight
|
||||
@Composable
|
||||
internal fun NewNotificationSoundBannerPreview() = ElementPreview {
|
||||
NewNotificationSoundBanner(
|
||||
onDismissClick = {},
|
||||
)
|
||||
}
|
||||
@@ -251,6 +251,12 @@ private fun RoomsViewList(
|
||||
item {
|
||||
BatteryOptimizationBanner(state = state.batteryOptimizationState)
|
||||
}
|
||||
} else if (state.showNewNotificationSoundBanner) {
|
||||
item {
|
||||
NewNotificationSoundBanner(
|
||||
onDismissClick = { updatedEventSink(RoomListEvents.DismissNewNotificationSoundBanner) },
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,17 +26,22 @@ open class RoomListContentStateProvider : PreviewParameterProvider<RoomListConte
|
||||
aSkeletonContentState(),
|
||||
anEmptyContentState(),
|
||||
anEmptyContentState(securityBannerState = SecurityBannerState.SetUpRecovery),
|
||||
aRoomsContentState(
|
||||
showNewNotificationSoundBanner = true,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
internal fun aRoomsContentState(
|
||||
securityBannerState: SecurityBannerState = SecurityBannerState.None,
|
||||
showNewNotificationSoundBanner: Boolean = false,
|
||||
summaries: ImmutableList<RoomListRoomSummary> = aRoomListRoomSummaryList(),
|
||||
fullScreenIntentPermissionsState: FullScreenIntentPermissionsState = aFullScreenIntentPermissionsState(),
|
||||
batteryOptimizationState: BatteryOptimizationState = aBatteryOptimizationState(),
|
||||
seenRoomInvites: Set<RoomId> = emptySet(),
|
||||
) = RoomListContentState.Rooms(
|
||||
securityBannerState = securityBannerState,
|
||||
showNewNotificationSoundBanner = showNewNotificationSoundBanner,
|
||||
fullScreenIntentPermissionsState = fullScreenIntentPermissionsState,
|
||||
batteryOptimizationState = batteryOptimizationState,
|
||||
summaries = summaries,
|
||||
|
||||
@@ -14,6 +14,7 @@ sealed interface RoomListEvents {
|
||||
data class UpdateVisibleRange(val range: IntRange) : RoomListEvents
|
||||
data object DismissRequestVerificationPrompt : RoomListEvents
|
||||
data object DismissBanner : RoomListEvents
|
||||
data object DismissNewNotificationSoundBanner : RoomListEvents
|
||||
data object ToggleSearchResults : RoomListEvents
|
||||
data class ShowContextMenu(val roomSummary: RoomListRoomSummary) : RoomListEvents
|
||||
|
||||
|
||||
@@ -98,6 +98,7 @@ class RoomListPresenter(
|
||||
}
|
||||
|
||||
var securityBannerDismissed by rememberSaveable { mutableStateOf(false) }
|
||||
val showNewNotificationSoundBanner by appPreferencesStore.showNewNotificationSoundBanner().collectAsState(false)
|
||||
|
||||
// Avatar indicator
|
||||
val hideInvitesAvatar by client.rememberHideInvitesAvatar()
|
||||
@@ -112,6 +113,9 @@ class RoomListPresenter(
|
||||
}
|
||||
RoomListEvents.DismissRequestVerificationPrompt -> securityBannerDismissed = true
|
||||
RoomListEvents.DismissBanner -> securityBannerDismissed = true
|
||||
RoomListEvents.DismissNewNotificationSoundBanner -> coroutineScope.launch {
|
||||
appPreferencesStore.setShowNewNotificationSoundBanner(false)
|
||||
}
|
||||
RoomListEvents.ToggleSearchResults -> searchState.eventSink(RoomListSearchEvents.ToggleSearchVisibility)
|
||||
is RoomListEvents.ShowContextMenu -> {
|
||||
coroutineScope.showContextMenu(event, contextMenu)
|
||||
@@ -141,7 +145,10 @@ class RoomListPresenter(
|
||||
}
|
||||
}
|
||||
|
||||
val contentState = roomListContentState(securityBannerDismissed)
|
||||
val contentState = roomListContentState(
|
||||
securityBannerDismissed,
|
||||
showNewNotificationSoundBanner,
|
||||
)
|
||||
|
||||
val canReportRoom by produceState(false) { value = client.canReportRoom() }
|
||||
|
||||
@@ -197,6 +204,7 @@ class RoomListPresenter(
|
||||
@Composable
|
||||
private fun roomListContentState(
|
||||
securityBannerDismissed: Boolean,
|
||||
showNewNotificationSoundBanner: Boolean,
|
||||
): RoomListContentState {
|
||||
val roomSummaries by produceState(initialValue = AsyncData.Loading()) {
|
||||
roomListDataSource.allRooms.collect { value = AsyncData.Success(it) }
|
||||
@@ -215,11 +223,14 @@ class RoomListPresenter(
|
||||
val seenRoomInvites by remember { seenInvitesStore.seenRoomIds() }.collectAsState(emptySet())
|
||||
val securityBannerState by rememberSecurityBannerState(securityBannerDismissed)
|
||||
return when {
|
||||
showEmpty -> RoomListContentState.Empty(securityBannerState = securityBannerState)
|
||||
showEmpty -> RoomListContentState.Empty(
|
||||
securityBannerState = securityBannerState,
|
||||
)
|
||||
showSkeleton -> RoomListContentState.Skeleton(count = 16)
|
||||
else -> {
|
||||
RoomListContentState.Rooms(
|
||||
securityBannerState = securityBannerState,
|
||||
showNewNotificationSoundBanner = showNewNotificationSoundBanner,
|
||||
fullScreenIntentPermissionsState = fullScreenIntentPermissionsPresenter.present(),
|
||||
batteryOptimizationState = batteryOptimizationPresenter.present(),
|
||||
summaries = roomSummaries.dataOrNull().orEmpty().toPersistentList(),
|
||||
|
||||
@@ -69,6 +69,7 @@ sealed interface RoomListContentState {
|
||||
val securityBannerState: SecurityBannerState,
|
||||
val fullScreenIntentPermissionsState: FullScreenIntentPermissionsState,
|
||||
val batteryOptimizationState: BatteryOptimizationState,
|
||||
val showNewNotificationSoundBanner: Boolean,
|
||||
val summaries: ImmutableList<RoomListRoomSummary>,
|
||||
val seenRoomInvites: ImmutableSet<RoomId>,
|
||||
) : RoomListContentState
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
<string name="banner_battery_optimization_content_android">"Deaktiver batterioptimering for denne app for at sikre, at alle notifikationer dukker op."</string>
|
||||
<string name="banner_battery_optimization_submit_android">"Deaktivér optimering"</string>
|
||||
<string name="banner_battery_optimization_title_android">"Modtager du ikke notifikationer?"</string>
|
||||
<string name="banner_new_sound_message">"Dit notifikationsping er blevet opdateret – tydeligere, hurtigere og mindre forstyrrende."</string>
|
||||
<string name="banner_new_sound_title">"Vi har opdateret dine lyde"</string>
|
||||
<string name="banner_set_up_recovery_content">"Gendan din kryptografiske identitet og meddelelseshistorik med en gendannelsesnøgle, hvis du har mistet alle dine eksisterende enheder."</string>
|
||||
<string name="banner_set_up_recovery_submit">"Opsæt gendannelse"</string>
|
||||
<string name="banner_set_up_recovery_title">"Konfigurer gendannelse for at beskytte din konto"</string>
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
<string name="banner_battery_optimization_content_android">"Deaktiviere die Batterieoptimierung für diese App, um sicherzustellen, dass alle Benachrichtigungen empfangen werden."</string>
|
||||
<string name="banner_battery_optimization_submit_android">"Optimierung deaktivieren"</string>
|
||||
<string name="banner_battery_optimization_title_android">"Kommen die Benachrichtigungen nicht an?"</string>
|
||||
<string name="banner_new_sound_message">"Dein Benachrichtigungs-Ping wurde aktualisiert – klarer, schneller und weniger störend."</string>
|
||||
<string name="banner_new_sound_title">"Wir haben deine Sounds aktualisiert"</string>
|
||||
<string name="banner_set_up_recovery_content">"Stelle Deine kryptographische Identität und Deinen Nachrichtenverlauf mit Hilfe eines Wiederherstellungsschlüssels wieder her, falls du alle deine Geräte verloren haben solltest"</string>
|
||||
<string name="banner_set_up_recovery_submit">"Wiederherstellung einrichten"</string>
|
||||
<string name="banner_set_up_recovery_title">"Wiederherstellung einrichten"</string>
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
<string name="banner_battery_optimization_content_android">"Désactivez l’optimisation de la batterie pour cette application afin de vous assurer que toutes les notifications sont reçues."</string>
|
||||
<string name="banner_battery_optimization_submit_android">"Désactiver l’optimisation"</string>
|
||||
<string name="banner_battery_optimization_title_android">"Ils vous manque des notifications?"</string>
|
||||
<string name="banner_new_sound_message">"Le son des notifications a été modifié: plus clair, plus court et moins perturbateur."</string>
|
||||
<string name="banner_new_sound_title">"Nous avons rafraîchi les sons"</string>
|
||||
<string name="banner_set_up_recovery_content">"Générez une nouvelle clé de récupération qui peut être utilisée pour restaurer l’historique de vos messages chiffrés au cas où vous perdriez l’accès à vos appareils."</string>
|
||||
<string name="banner_set_up_recovery_submit">"Configurer la sauvegarde"</string>
|
||||
<string name="banner_set_up_recovery_title">"Configurer la récupération"</string>
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
<string name="banner_battery_optimization_content_android">"Deaktiver batterioptimalisering for denne appen for å sikre at alle varsler mottas."</string>
|
||||
<string name="banner_battery_optimization_submit_android">"Deaktiver optimalisering"</string>
|
||||
<string name="banner_battery_optimization_title_android">"Kommer ikke varslene frem?"</string>
|
||||
<string name="banner_new_sound_message">"Varslingssignalet ditt er oppdatert – tydeligere, raskere og mindre forstyrrende."</string>
|
||||
<string name="banner_new_sound_title">"Vi har oppdatert lydene dine"</string>
|
||||
<string name="banner_set_up_recovery_content">"Gjenopprett din kryptografiske identitet og meldingshistorikk med en gjenopprettingsnøkkel hvis du har mistet alle dine brukte enheter."</string>
|
||||
<string name="banner_set_up_recovery_submit">"Konfigurer gjenoppretting"</string>
|
||||
<string name="banner_set_up_recovery_title">"Konfigurer gjenoppretting for å beskytte kontoen din"</string>
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
<string name="banner_battery_optimization_content_android">"Dezactivați optimizarea bateriei pentru această aplicație, pentru a vă asigura că toate notificările sunt primite."</string>
|
||||
<string name="banner_battery_optimization_submit_android">"Dezactivați optimizarea"</string>
|
||||
<string name="banner_battery_optimization_title_android">"Nu primiți notificări?"</string>
|
||||
<string name="banner_new_sound_message">"Sunetul pentru notificări a fost actualizat — mai clar, mai rapid și mai puțin perturbatoar."</string>
|
||||
<string name="banner_new_sound_title">"Am reîmprospătat sunetele"</string>
|
||||
<string name="banner_set_up_recovery_content">"Recuperați-vă identitatea criptografică și mesajele anterioare cu o cheie de recuperare dacă ați pierdut toate dispozitivele existente."</string>
|
||||
<string name="banner_set_up_recovery_submit">"Configurați recuperarea"</string>
|
||||
<string name="banner_set_up_recovery_title">"Configurați recuperarea pentru a vă proteja contul"</string>
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
<string name="banner_battery_optimization_content_android">"Выключите оптимизацию расхода батареи, чтобы убедиться, что все уведомления будут поступать."</string>
|
||||
<string name="banner_battery_optimization_submit_android">"Выключить оптимизацию"</string>
|
||||
<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>
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
<string name="banner_battery_optimization_content_android">"Disable battery optimisation for this app, to make sure all notifications are received."</string>
|
||||
<string name="banner_battery_optimization_submit_android">"Disable optimisation"</string>
|
||||
<string name="banner_battery_optimization_title_android">"Notifications not arriving?"</string>
|
||||
<string name="banner_new_sound_message">"Your notification ping has been updated—clearer, quicker, and less disruptive."</string>
|
||||
<string name="banner_new_sound_title">"We’ve refreshed your sounds"</string>
|
||||
<string name="banner_set_up_recovery_content">"Recover your cryptographic identity and message history with a recovery key if you have lost all your existing devices."</string>
|
||||
<string name="banner_set_up_recovery_submit">"Set up recovery"</string>
|
||||
<string name="banner_set_up_recovery_title">"Set up recovery to protect your account"</string>
|
||||
|
||||
@@ -75,6 +75,7 @@ import io.element.android.tests.testutils.lambda.value
|
||||
import io.element.android.tests.testutils.test
|
||||
import io.element.android.tests.testutils.testCoroutineDispatchers
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.test.TestScope
|
||||
import kotlinx.coroutines.test.advanceTimeBy
|
||||
import kotlinx.coroutines.test.runTest
|
||||
@@ -593,6 +594,38 @@ class RoomListPresenterTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - notification sound banner`() = runTest {
|
||||
val subscribeToVisibleRoomsLambda = lambdaRecorder { _: List<RoomId> -> }
|
||||
val roomListService = FakeRoomListService(subscribeToVisibleRoomsLambda = subscribeToVisibleRoomsLambda)
|
||||
val matrixClient = FakeMatrixClient(
|
||||
roomListService = roomListService,
|
||||
)
|
||||
val roomSummary = aRoomSummary(
|
||||
currentUserMembership = CurrentUserMembership.INVITED
|
||||
)
|
||||
roomListService.postAllRoomsLoadingState(RoomList.LoadingState.Loaded(1))
|
||||
roomListService.postAllRooms(listOf(roomSummary))
|
||||
val store = InMemoryAppPreferencesStore()
|
||||
val presenter = createRoomListPresenter(
|
||||
client = matrixClient,
|
||||
appPreferencesStore = store,
|
||||
)
|
||||
presenter.test {
|
||||
assertThat(store.showNewNotificationSoundBanner().first()).isFalse()
|
||||
skipItems(1)
|
||||
val state = awaitItem()
|
||||
assertThat(state.contentAsRooms().showNewNotificationSoundBanner).isFalse()
|
||||
store.setShowNewNotificationSoundBanner(true)
|
||||
assertThat(store.showNewNotificationSoundBanner().first()).isTrue()
|
||||
assertThat(awaitItem().contentAsRooms().showNewNotificationSoundBanner).isTrue()
|
||||
state.eventSink(RoomListEvents.DismissNewNotificationSoundBanner)
|
||||
assertThat(awaitItem().contentAsRooms().showNewNotificationSoundBanner).isFalse()
|
||||
// Ensure store has been updated
|
||||
assertThat(store.showNewNotificationSoundBanner().first()).isFalse()
|
||||
}
|
||||
}
|
||||
|
||||
private fun TestScope.createRoomListPresenter(
|
||||
client: MatrixClient = FakeMatrixClient(),
|
||||
leaveRoomState: LeaveRoomState = aLeaveRoomState(),
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_join_room_ban_by_message">"Du blev spærret fra dette rum af %1$s."</string>
|
||||
<string name="screen_join_room_ban_message">"Du blev spærret fra dette rum"</string>
|
||||
<string name="screen_join_room_ban_by_message">"Du blev spærret af %1$s."</string>
|
||||
<string name="screen_join_room_ban_message">"Du blev spærret"</string>
|
||||
<string name="screen_join_room_ban_reason">"Årsag: %1$s."</string>
|
||||
<string name="screen_join_room_cancel_knock_action">"Annuller anmodning"</string>
|
||||
<string name="screen_join_room_cancel_knock_alert_confirmation">"Ja, annullér"</string>
|
||||
@@ -11,12 +11,12 @@
|
||||
<string name="screen_join_room_decline_and_block_alert_message">"Er du sikker på, at du vil afvise invitationen til at deltage i dette rum? Dette forhindrer også %1$s i at kontakte dig eller invitere dig til andre rum."</string>
|
||||
<string name="screen_join_room_decline_and_block_alert_title">"Afvis invitation og blokér"</string>
|
||||
<string name="screen_join_room_decline_and_block_button_title">"Afvis og blokér"</string>
|
||||
<string name="screen_join_room_fail_message">"Deltagelse i rummet fejlede."</string>
|
||||
<string name="screen_join_room_fail_reason">"Dette rum er enten kun for gæster, eller der kan være sat begrænsninger for adgangen på klyngeniveau."</string>
|
||||
<string name="screen_join_room_forget_action">"Glem dette rum"</string>
|
||||
<string name="screen_join_room_invite_required_message">"Du har brug for en invitation for at deltage i dette rum"</string>
|
||||
<string name="screen_join_room_fail_message">"Deltagelse fejlede."</string>
|
||||
<string name="screen_join_room_fail_reason">"Du skal enten inviteres til at deltage, eller der kan være adgangsbegrænsninger."</string>
|
||||
<string name="screen_join_room_forget_action">"Glem"</string>
|
||||
<string name="screen_join_room_invite_required_message">"Du har brug for en invitation for at deltage"</string>
|
||||
<string name="screen_join_room_invited_by">"Inviteret af"</string>
|
||||
<string name="screen_join_room_join_action">"Deltag i rummet"</string>
|
||||
<string name="screen_join_room_join_action">"Deltag"</string>
|
||||
<string name="screen_join_room_join_restricted_message">"Du skal muligvis være inviteret eller være medlem af en klynge for at deltage."</string>
|
||||
<string name="screen_join_room_knock_action">"Send anmodning om at deltage"</string>
|
||||
<string name="screen_join_room_knock_message_characters_count">"Tilladte tegn %1$d af %2$d"</string>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_join_room_ban_by_message">"Du wurdest von %1$s für diesen Chat gesperrt."</string>
|
||||
<string name="screen_join_room_ban_message">"Du wurdest für diesen Chat gesperrt"</string>
|
||||
<string name="screen_join_room_ban_by_message">"Du wurdest von %1$s gesperrt."</string>
|
||||
<string name="screen_join_room_ban_message">"Du wurdest gesperrt"</string>
|
||||
<string name="screen_join_room_ban_reason">"Grund:%1$s."</string>
|
||||
<string name="screen_join_room_cancel_knock_action">"Anfrage abbrechen"</string>
|
||||
<string name="screen_join_room_cancel_knock_alert_confirmation">"Ja, abbrechen"</string>
|
||||
@@ -11,12 +11,12 @@
|
||||
<string name="screen_join_room_decline_and_block_alert_message">"Bist du sicher, dass du die Einladung zu diesem Chat ablehnen möchtest? Dadurch wird auch jede weitere Kontaktaufnahme oder Chat Einladung von %1$s blockiert."</string>
|
||||
<string name="screen_join_room_decline_and_block_alert_title">"Einladung ablehnen & Nutzer blockieren"</string>
|
||||
<string name="screen_join_room_decline_and_block_button_title">"Ablehnen und blockieren"</string>
|
||||
<string name="screen_join_room_fail_message">"Der Beitritt zum Chat schlug fehl."</string>
|
||||
<string name="screen_join_room_fail_reason">"Dieser Chat ist entweder nur auf Einladung zugänglich oder es gibt andere Zugangsbeschränkungen durch Spaces."</string>
|
||||
<string name="screen_join_room_forget_action">"Vergiss diesen Chat"</string>
|
||||
<string name="screen_join_room_invite_required_message">"Du benötigst eine Einladung, um diesem Chat beizutreten"</string>
|
||||
<string name="screen_join_room_fail_message">"Beitritt fehlgeschlagen"</string>
|
||||
<string name="screen_join_room_fail_reason">"Du musst entweder eingeladen werden, um beizutreten, oder es gibt möglicherweise Zugriffsbeschränkungen."</string>
|
||||
<string name="screen_join_room_forget_action">"Vergessen"</string>
|
||||
<string name="screen_join_room_invite_required_message">"Du benötigst eine Einladung, um beizutreten"</string>
|
||||
<string name="screen_join_room_invited_by">"Eingeladen von"</string>
|
||||
<string name="screen_join_room_join_action">"Chat beitreten"</string>
|
||||
<string name="screen_join_room_join_action">"Beitreten"</string>
|
||||
<string name="screen_join_room_join_restricted_message">"Möglicherweise musst du eingeladen werden oder ein Mitglied eines Spaces sein, um beitreten zu können."</string>
|
||||
<string name="screen_join_room_knock_action">"Anklopfen"</string>
|
||||
<string name="screen_join_room_knock_message_characters_count">"%1$d von %2$d erlaubte Zeichen"</string>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_join_room_ban_by_message">"Du ble utestengt fra dette rommet av %1$s."</string>
|
||||
<string name="screen_join_room_ban_message">"Du ble utestengt fra dette rommet"</string>
|
||||
<string name="screen_join_room_ban_by_message">"Du ble utestengt av %1$s."</string>
|
||||
<string name="screen_join_room_ban_message">"Du ble utestengt"</string>
|
||||
<string name="screen_join_room_ban_reason">"Årsak: %1$s."</string>
|
||||
<string name="screen_join_room_cancel_knock_action">"Avbryt forespørsel"</string>
|
||||
<string name="screen_join_room_cancel_knock_alert_confirmation">"Ja, avbryt"</string>
|
||||
@@ -11,12 +11,12 @@
|
||||
<string name="screen_join_room_decline_and_block_alert_message">"Er du sikker på at du vil avslå invitasjonen til å bli med i dette rommet? Dette vil også forhindre %1$s fra å kontakte deg eller invitere deg til rom."</string>
|
||||
<string name="screen_join_room_decline_and_block_alert_title">"Avslå invitasjon og blokker"</string>
|
||||
<string name="screen_join_room_decline_and_block_button_title">"Avslå og blokker"</string>
|
||||
<string name="screen_join_room_fail_message">"Å bli med i rommet mislyktes."</string>
|
||||
<string name="screen_join_room_fail_reason">"Dette rommet er enten kun for inviterte, eller det kan være begrensninger for tilgang på områdenivå."</string>
|
||||
<string name="screen_join_room_forget_action">"Glem dette rommet"</string>
|
||||
<string name="screen_join_room_invite_required_message">"Du trenger en invitasjon for å bli med i dette rommet"</string>
|
||||
<string name="screen_join_room_fail_message">"Kunne ikke bli med"</string>
|
||||
<string name="screen_join_room_fail_reason">"Du må enten bli invitert til å bli med, eller så kan det være begrensninger på tilgangen."</string>
|
||||
<string name="screen_join_room_forget_action">"Glem"</string>
|
||||
<string name="screen_join_room_invite_required_message">"Du trenger en invitasjon for å bli med"</string>
|
||||
<string name="screen_join_room_invited_by">"Invitert av"</string>
|
||||
<string name="screen_join_room_join_action">"Bli med i rommet"</string>
|
||||
<string name="screen_join_room_join_action">"Bli med"</string>
|
||||
<string name="screen_join_room_join_restricted_message">"Du må kanskje bli invitert eller være medlem av et område for å bli med."</string>
|
||||
<string name="screen_join_room_knock_action">"Send forespørsel om å bli med"</string>
|
||||
<string name="screen_join_room_knock_message_characters_count">"Tillatte tegn %1$d av %2$d"</string>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_join_room_ban_by_message">"Ai fost exclus din această cameră de către %1$s."</string>
|
||||
<string name="screen_join_room_ban_by_message">"Ați fost exclus din această cameră de către %1$s."</string>
|
||||
<string name="screen_join_room_ban_message">"Ați fost exclus din această cameră."</string>
|
||||
<string name="screen_join_room_ban_reason">"Motiv: %1$s."</string>
|
||||
<string name="screen_join_room_cancel_knock_action">"Anulați cererea"</string>
|
||||
@@ -16,7 +16,7 @@
|
||||
<string name="screen_join_room_forget_action">"Uitați această cameră"</string>
|
||||
<string name="screen_join_room_invite_required_message">"Aveți nevoie de o invitație pentru a vă alătura acestei camere."</string>
|
||||
<string name="screen_join_room_invited_by">"Invitat de"</string>
|
||||
<string name="screen_join_room_join_action">"Alăturați-vă camerei"</string>
|
||||
<string name="screen_join_room_join_action">"Alăturați-vă"</string>
|
||||
<string name="screen_join_room_join_restricted_message">"Este posibil să fie necesar să fiți invitat sau să fiți membru al unui spațiu pentru a vă alătura."</string>
|
||||
<string name="screen_join_room_knock_action">"Trimiteți o cerere de alăturare"</string>
|
||||
<string name="screen_join_room_knock_message_characters_count">"Caractere permise %1$d din %2$d"</string>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_join_room_ban_by_message">"You were banned from this room by %1$s."</string>
|
||||
<string name="screen_join_room_ban_message">"You were banned from this room"</string>
|
||||
<string name="screen_join_room_ban_by_message">"You were banned by %1$s."</string>
|
||||
<string name="screen_join_room_ban_message">"You were banned"</string>
|
||||
<string name="screen_join_room_ban_reason">"Reason: %1$s."</string>
|
||||
<string name="screen_join_room_cancel_knock_action">"Cancel request"</string>
|
||||
<string name="screen_join_room_cancel_knock_alert_confirmation">"Yes, cancel"</string>
|
||||
@@ -11,12 +11,12 @@
|
||||
<string name="screen_join_room_decline_and_block_alert_message">"Are you sure you want to decline the invite to join this room? This will also prevent %1$s from contacting you or inviting you to rooms."</string>
|
||||
<string name="screen_join_room_decline_and_block_alert_title">"Decline invite & block"</string>
|
||||
<string name="screen_join_room_decline_and_block_button_title">"Decline and block"</string>
|
||||
<string name="screen_join_room_fail_message">"Joining the room failed."</string>
|
||||
<string name="screen_join_room_fail_reason">"This room is either invite-only or there might be restrictions to access at space level."</string>
|
||||
<string name="screen_join_room_forget_action">"Forget this room"</string>
|
||||
<string name="screen_join_room_invite_required_message">"You need an invite in order to join this room"</string>
|
||||
<string name="screen_join_room_fail_message">"Joining failed"</string>
|
||||
<string name="screen_join_room_fail_reason">"You either need to be invited to join or there might be restrictions to access."</string>
|
||||
<string name="screen_join_room_forget_action">"Forget"</string>
|
||||
<string name="screen_join_room_invite_required_message">"You need an invite in order to join"</string>
|
||||
<string name="screen_join_room_invited_by">"Invited by"</string>
|
||||
<string name="screen_join_room_join_action">"Join room"</string>
|
||||
<string name="screen_join_room_join_action">"Join"</string>
|
||||
<string name="screen_join_room_join_restricted_message">"You may need to be invited or be a member of a space in order to join."</string>
|
||||
<string name="screen_join_room_knock_action">"Send request to join"</string>
|
||||
<string name="screen_join_room_knock_message_characters_count">"Allowed characters %1$d of %2$d"</string>
|
||||
|
||||
@@ -31,6 +31,7 @@ class MigrationPresenter(
|
||||
) : Presenter<MigrationState> {
|
||||
private val orderedMigrations = migrations.sortedBy { it.order }
|
||||
private val lastMigration: Int = orderedMigrations.lastOrNull()?.order ?: 0
|
||||
private var isFreshInstall = false
|
||||
|
||||
@Composable
|
||||
override fun present(): MigrationState {
|
||||
@@ -49,6 +50,7 @@ class MigrationPresenter(
|
||||
val migrationValue = migrationStoreVersion ?: return@LaunchedEffect
|
||||
if (migrationValue == -1) {
|
||||
Timber.d("Fresh install, or previous installed application did not have the migration mechanism.")
|
||||
isFreshInstall = true
|
||||
}
|
||||
if (migrationValue == lastMigration) {
|
||||
Timber.d("Current app migration version: $migrationValue. No migration needed.")
|
||||
@@ -59,7 +61,7 @@ class MigrationPresenter(
|
||||
val nextMigration = orderedMigrations.firstOrNull { it.order > migrationValue }
|
||||
if (nextMigration != null) {
|
||||
Timber.d("Current app migration version: $migrationValue. Applying migration: ${nextMigration.order}")
|
||||
nextMigration.migrate()
|
||||
nextMigration.migrate(isFreshInstall)
|
||||
migrationStore.setApplicationMigrationVersion(nextMigration.order)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,5 +9,5 @@ package io.element.android.features.migration.impl.migrations
|
||||
|
||||
interface AppMigration {
|
||||
val order: Int
|
||||
suspend fun migrate()
|
||||
suspend fun migrate(isFreshInstall: Boolean)
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ class AppMigration01(
|
||||
) : AppMigration {
|
||||
override val order: Int = 1
|
||||
|
||||
override suspend fun migrate() {
|
||||
override suspend fun migrate(isFreshInstall: Boolean) {
|
||||
logFilesRemover.perform()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ class AppMigration02(
|
||||
) : AppMigration {
|
||||
override val order: Int = 2
|
||||
|
||||
override suspend fun migrate() {
|
||||
override suspend fun migrate(isFreshInstall: Boolean) {
|
||||
coroutineScope {
|
||||
for (session in sessionStore.getAllSessions()) {
|
||||
val sessionId = SessionId(session.userId)
|
||||
|
||||
@@ -21,7 +21,7 @@ class AppMigration03(
|
||||
) : AppMigration {
|
||||
override val order: Int = 3
|
||||
|
||||
override suspend fun migrate() {
|
||||
migration01.migrate()
|
||||
override suspend fun migrate(isFreshInstall: Boolean) {
|
||||
migration01.migrate(isFreshInstall)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ class AppMigration04(
|
||||
}
|
||||
override val order: Int = 4
|
||||
|
||||
override suspend fun migrate() {
|
||||
override suspend fun migrate(isFreshInstall: Boolean) {
|
||||
runCatchingExceptions { context.getDatabasePath(NOTIFICATION_FILE_NAME).delete() }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ class AppMigration05(
|
||||
) : AppMigration {
|
||||
override val order: Int = 5
|
||||
|
||||
override suspend fun migrate() {
|
||||
override suspend fun migrate(isFreshInstall: Boolean) {
|
||||
val allSessions = sessionStore.getAllSessions()
|
||||
for (session in allSessions) {
|
||||
if (session.sessionPath.isEmpty()) {
|
||||
|
||||
@@ -25,7 +25,7 @@ class AppMigration06(
|
||||
) : AppMigration {
|
||||
override val order: Int = 6
|
||||
|
||||
override suspend fun migrate() {
|
||||
override suspend fun migrate(isFreshInstall: Boolean) {
|
||||
val allSessions = sessionStore.getAllSessions()
|
||||
for (session in allSessions) {
|
||||
if (session.cachePath.isEmpty()) {
|
||||
|
||||
@@ -22,7 +22,7 @@ class AppMigration07(
|
||||
) : AppMigration {
|
||||
override val order: Int = 7
|
||||
|
||||
override suspend fun migrate() {
|
||||
override suspend fun migrate(isFreshInstall: Boolean) {
|
||||
logFilesRemover.perform { file ->
|
||||
file.name.startsWith("logs-")
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2025 New Vector 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.migration.impl.migrations
|
||||
|
||||
import dev.zacsweers.metro.AppScope
|
||||
import dev.zacsweers.metro.ContributesIntoSet
|
||||
import dev.zacsweers.metro.Inject
|
||||
import io.element.android.libraries.preferences.api.store.AppPreferencesStore
|
||||
|
||||
/**
|
||||
* Ensure the new notification sound banner is displayed, but only on application upgrade.
|
||||
*/
|
||||
@ContributesIntoSet(AppScope::class)
|
||||
@Inject
|
||||
class AppMigration08(
|
||||
private val appPreferencesStore: AppPreferencesStore,
|
||||
) : AppMigration {
|
||||
override val order: Int = 8
|
||||
|
||||
override suspend fun migrate(isFreshInstall: Boolean) {
|
||||
if (!isFreshInstall) {
|
||||
appPreferencesStore.setShowNewNotificationSoundBanner(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,8 +15,10 @@ import io.element.android.features.migration.impl.migrations.AppMigration
|
||||
import io.element.android.libraries.architecture.AsyncData
|
||||
import io.element.android.tests.testutils.WarmUpRule
|
||||
import io.element.android.tests.testutils.consumeItemsUntilPredicate
|
||||
import io.element.android.tests.testutils.lambda.LambdaNoParamRecorder
|
||||
import io.element.android.tests.testutils.lambda.LambdaOneParamRecorder
|
||||
import io.element.android.tests.testutils.lambda.lambdaError
|
||||
import io.element.android.tests.testutils.lambda.lambdaRecorder
|
||||
import io.element.android.tests.testutils.lambda.value
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Rule
|
||||
@@ -48,13 +50,18 @@ class MigrationPresenterTest {
|
||||
assertThat(store.applicationMigrationVersion().first()).isEqualTo(migrations.maxOf { it.order })
|
||||
}
|
||||
for (migration in migrations) {
|
||||
migration.migrateLambda.assertions().isCalledOnce()
|
||||
migration.migrateLambda.assertions().isCalledOnce().with(value(true))
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - no migration should occurs if ApplicationMigrationVersion is the last one`() = runTest {
|
||||
val migrations = (1..10).map { FakeAppMigration(it) }
|
||||
val migrations = (1..10).map {
|
||||
FakeAppMigration(
|
||||
order = it,
|
||||
migrateLambda = lambdaRecorder<Boolean, Unit> { lambdaError() },
|
||||
)
|
||||
}
|
||||
val store = InMemoryMigrationStore(migrations.maxOf { it.order })
|
||||
val presenter = createPresenter(
|
||||
migrationStore = store,
|
||||
@@ -90,7 +97,7 @@ class MigrationPresenterTest {
|
||||
consumeItemsUntilPredicate { it.migrationAction is AsyncData.Success }
|
||||
assertThat(store.applicationMigrationVersion().first()).isEqualTo(migrations.maxOf { it.order })
|
||||
for (migration in migrations) {
|
||||
migration.migrateLambda.assertions().isCalledOnce()
|
||||
migration.migrateLambda.assertions().isCalledOnce().with(value(false))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -106,9 +113,9 @@ private fun createPresenter(
|
||||
|
||||
private class FakeAppMigration(
|
||||
override val order: Int,
|
||||
val migrateLambda: LambdaNoParamRecorder<Unit> = lambdaRecorder { -> },
|
||||
val migrateLambda: LambdaOneParamRecorder<Boolean, Unit> = lambdaRecorder<Boolean, Unit> { },
|
||||
) : AppMigration {
|
||||
override suspend fun migrate() {
|
||||
migrateLambda()
|
||||
override suspend fun migrate(isFreshInstall: Boolean) {
|
||||
migrateLambda(isFreshInstall)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ class AppMigration01Test {
|
||||
val logsFileRemover = FakeLogFilesRemover()
|
||||
val migration = AppMigration01(logsFileRemover)
|
||||
|
||||
migration.migrate()
|
||||
migration.migrate(true)
|
||||
|
||||
logsFileRemover.performLambda.assertions().isCalledOnce()
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ class AppMigration02Test {
|
||||
)
|
||||
val migration = AppMigration02(sessionStore = sessionStore, sessionPreferenceStoreFactory = sessionPreferencesStoreFactory)
|
||||
|
||||
migration.migrate()
|
||||
migration.migrate(true)
|
||||
|
||||
// We got the session preferences store
|
||||
sessionPreferencesStoreFactory.getLambda.assertions().isCalledOnce()
|
||||
|
||||
@@ -17,7 +17,7 @@ class AppMigration03Test {
|
||||
val logsFileRemover = FakeLogFilesRemover()
|
||||
val migration = AppMigration03(migration01 = AppMigration01(logsFileRemover))
|
||||
|
||||
migration.migrate()
|
||||
migration.migrate(true)
|
||||
|
||||
logsFileRemover.performLambda.assertions().isCalledOnce()
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ class AppMigration04Test {
|
||||
|
||||
val migration = AppMigration04(context)
|
||||
|
||||
migration.migrate()
|
||||
migration.migrate(true)
|
||||
|
||||
// Check that the file has been deleted
|
||||
assertThat(file.exists()).isFalse()
|
||||
|
||||
@@ -27,7 +27,7 @@ class AppMigration05Test {
|
||||
)
|
||||
)
|
||||
val migration = AppMigration05(sessionStore = sessionStore, baseDirectory = File("/a/path"))
|
||||
migration.migrate()
|
||||
migration.migrate(true)
|
||||
val storedData = sessionStore.getSession(A_SESSION_ID.value)!!
|
||||
assertThat(storedData.sessionPath).isEqualTo("/a/path/${A_SESSION_ID.value.replace(':', '_')}")
|
||||
}
|
||||
@@ -43,7 +43,7 @@ class AppMigration05Test {
|
||||
)
|
||||
)
|
||||
val migration = AppMigration05(sessionStore = sessionStore, baseDirectory = File("/a/path"))
|
||||
migration.migrate()
|
||||
migration.migrate(true)
|
||||
val storedData = sessionStore.getSession(A_SESSION_ID.value)!!
|
||||
assertThat(storedData.sessionPath).isEqualTo("/a/path/existing")
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ class AppMigration06Test {
|
||||
)
|
||||
)
|
||||
val migration = AppMigration06(sessionStore = sessionStore, cacheDirectory = File("/a/path/cache"))
|
||||
migration.migrate()
|
||||
migration.migrate(true)
|
||||
val storedData = sessionStore.getSession(A_SESSION_ID.value)!!
|
||||
assertThat(storedData.cachePath).isEqualTo("/a/path/cache/AN_ID")
|
||||
}
|
||||
@@ -44,7 +44,7 @@ class AppMigration06Test {
|
||||
)
|
||||
)
|
||||
val migration = AppMigration05(sessionStore = sessionStore, baseDirectory = File("/a/path/cache"))
|
||||
migration.migrate()
|
||||
migration.migrate(true)
|
||||
val storedData = sessionStore.getSession(A_SESSION_ID.value)!!
|
||||
assertThat(storedData.cachePath).isEqualTo("/a/path/existing")
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ class AppMigration07Test {
|
||||
}
|
||||
val logsFileRemover = FakeLogFilesRemover(performLambda = performLambda)
|
||||
val migration = AppMigration07(logsFileRemover)
|
||||
migration.migrate()
|
||||
migration.migrate(true)
|
||||
performLambda.assertions().isCalledOnce()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2024 New Vector 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.migration.impl.migrations
|
||||
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import io.element.android.libraries.preferences.test.InMemoryAppPreferencesStore
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Test
|
||||
|
||||
class AppMigration08Test {
|
||||
@Test
|
||||
fun `migration on fresh install should not modify the store`() = runTest {
|
||||
val store = InMemoryAppPreferencesStore()
|
||||
assertThat(store.showNewNotificationSoundBanner().first()).isFalse()
|
||||
val migration = AppMigration08(store)
|
||||
migration.migrate(isFreshInstall = true)
|
||||
assertThat(store.showNewNotificationSoundBanner().first()).isFalse()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `migration on upgrade should modify the store`() = runTest {
|
||||
val store = InMemoryAppPreferencesStore()
|
||||
assertThat(store.showNewNotificationSoundBanner().first()).isFalse()
|
||||
val migration = AppMigration08(store)
|
||||
migration.migrate(isFreshInstall = false)
|
||||
assertThat(store.showNewNotificationSoundBanner().first()).isTrue()
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@
|
||||
<string name="screen_advanced_settings_element_call_base_url_validation_error">"Ugyldig URL, sørg for at inkludere protokollen (http/https) og den korrekte adresse."</string>
|
||||
<string name="screen_advanced_settings_hide_invite_avatars_toggle_title">"Skjul avatarer i anmodninger om invitation til rum"</string>
|
||||
<string name="screen_advanced_settings_hide_timeline_media_toggle_title">"Skjul forhåndsvisning af medier i tidslinjen"</string>
|
||||
<string name="screen_advanced_settings_labs">"Laboratorier"</string>
|
||||
<string name="screen_advanced_settings_media_compression_description">"Upload fotos og videoer hurtigere, og reducér dataforbrug"</string>
|
||||
<string name="screen_advanced_settings_media_compression_title">"Optimér mediekvaliteten"</string>
|
||||
<string name="screen_advanced_settings_moderation_and_safety_section_title">"Moderation og sikkerhed"</string>
|
||||
@@ -43,6 +44,11 @@
|
||||
<string name="screen_edit_profile_error_title">"Kan ikke opdatere profilen"</string>
|
||||
<string name="screen_edit_profile_title">"Redigér profil"</string>
|
||||
<string name="screen_edit_profile_updating_details">"Opdaterer profil…"</string>
|
||||
<string name="screen_labs_enable_threads">"Aktivér svar-tråde"</string>
|
||||
<string name="screen_labs_enable_threads_description">"Appen genstarter for at anvende denne ændring."</string>
|
||||
<string name="screen_labs_header_description">"Prøv vores nyeste idéer under udvikling. Disse funktioner er ikke færdige; de kan være ustabile og kan ændre sig."</string>
|
||||
<string name="screen_labs_header_title">"Er du i humør til at eksperimentere?"</string>
|
||||
<string name="screen_labs_title">"Laboratorier"</string>
|
||||
<string name="screen_notification_settings_additional_settings_section_title">"Yderligere indstillinger"</string>
|
||||
<string name="screen_notification_settings_calls_label">"Lyd- og videoopkald"</string>
|
||||
<string name="screen_notification_settings_configuration_mismatch">"Uoverensstemmelse i konfigurationen"</string>
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
<string name="screen_advanced_settings_element_call_base_url_validation_error">"Ungültige URL, bitte gib das Protokoll (http/https) und die richtige Adresse an."</string>
|
||||
<string name="screen_advanced_settings_hide_invite_avatars_toggle_title">"Avatare in Chateinladungen ausblenden"</string>
|
||||
<string name="screen_advanced_settings_hide_timeline_media_toggle_title">"Medienvorschau im Nachrichtenverlauf ausblenden"</string>
|
||||
<string name="screen_advanced_settings_labs">"Labs"</string>
|
||||
<string name="screen_advanced_settings_media_compression_description">"Lade Fotos und Videos schneller hoch und reduziere den Datenverbrauch"</string>
|
||||
<string name="screen_advanced_settings_media_compression_title">"Optimiere die Medienqualität"</string>
|
||||
<string name="screen_advanced_settings_moderation_and_safety_section_title">"Moderation und Sicherheit"</string>
|
||||
@@ -43,6 +44,11 @@
|
||||
<string name="screen_edit_profile_error_title">"Profil kann nicht aktualisiert werden"</string>
|
||||
<string name="screen_edit_profile_title">"Profil bearbeiten"</string>
|
||||
<string name="screen_edit_profile_updating_details">"Profil wird aktualisiert…"</string>
|
||||
<string name="screen_labs_enable_threads">"Thread-Antworten aktivieren"</string>
|
||||
<string name="screen_labs_enable_threads_description">"Die App wird neu gestartet, um diese Änderung zu übernehmen."</string>
|
||||
<string name="screen_labs_header_description">"Probier unsere neuesten Ideen in der Entwicklung aus. Diese Funktionen sind noch nicht fertiggestellt; sie können instabil sein und sich noch ändern."</string>
|
||||
<string name="screen_labs_header_title">"Entdeckungsfreudig?"</string>
|
||||
<string name="screen_labs_title">"Labs"</string>
|
||||
<string name="screen_notification_settings_additional_settings_section_title">"Zusätzliche Einstellungen"</string>
|
||||
<string name="screen_notification_settings_calls_label">"Audio- und Videoanrufe"</string>
|
||||
<string name="screen_notification_settings_configuration_mismatch">"Konfiguration stimmt nicht überein"</string>
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
<string name="screen_advanced_settings_element_call_base_url_validation_error">"URL invalide, assurez-vous d’inclure le protocol (http/https) et l’adresse correcte."</string>
|
||||
<string name="screen_advanced_settings_hide_invite_avatars_toggle_title">"Masquer les avatars des salons dans les invitations"</string>
|
||||
<string name="screen_advanced_settings_hide_timeline_media_toggle_title">"Masquer les aperçus des médias dans les discussions"</string>
|
||||
<string name="screen_advanced_settings_labs">"Expérimental"</string>
|
||||
<string name="screen_advanced_settings_media_compression_description">"Téléchargez des photos et des vidéos plus rapidement et réduisez la consommation de données"</string>
|
||||
<string name="screen_advanced_settings_media_compression_title">"Optimisez la qualité des médias"</string>
|
||||
<string name="screen_advanced_settings_moderation_and_safety_section_title">"Modération et sécurité"</string>
|
||||
@@ -43,6 +44,10 @@
|
||||
<string name="screen_edit_profile_error_title">"Impossible de mettre à jour le profil"</string>
|
||||
<string name="screen_edit_profile_title">"Modifier le profil"</string>
|
||||
<string name="screen_edit_profile_updating_details">"Mise à jour du profil…"</string>
|
||||
<string name="screen_labs_enable_threads">"Activez les fils de discussion."</string>
|
||||
<string name="screen_labs_header_description">"Découvrez nos dernières idées en cours de développement. Ces fonctionnalités ne sont pas encore finalisées; elles peuvent être instables et évoluer."</string>
|
||||
<string name="screen_labs_header_title">"Envie d’expérimenter?"</string>
|
||||
<string name="screen_labs_title">"Expérimental"</string>
|
||||
<string name="screen_notification_settings_additional_settings_section_title">"Réglages supplémentaires"</string>
|
||||
<string name="screen_notification_settings_calls_label">"Appels audio et vidéo"</string>
|
||||
<string name="screen_notification_settings_configuration_mismatch">"Incompatibilité de configuration"</string>
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
<string name="screen_advanced_settings_element_call_base_url_validation_error">"Ugyldig URL. Pass på at du inkluderer protokollen (http/https) og riktig adresse."</string>
|
||||
<string name="screen_advanced_settings_hide_invite_avatars_toggle_title">"Skjul avatarer i invitasjonsforespørsler til rom"</string>
|
||||
<string name="screen_advanced_settings_hide_timeline_media_toggle_title">"Skjul forhåndsvisninger av medier på tidslinjen"</string>
|
||||
<string name="screen_advanced_settings_labs">"Prøvefunksjoner"</string>
|
||||
<string name="screen_advanced_settings_media_compression_description">"Last opp bilder og videoer raskere og reduser databruken"</string>
|
||||
<string name="screen_advanced_settings_media_compression_title">"Optimaliser mediekvaliteten"</string>
|
||||
<string name="screen_advanced_settings_moderation_and_safety_section_title">"Moderasjon og sikkerhet"</string>
|
||||
@@ -43,6 +44,11 @@
|
||||
<string name="screen_edit_profile_error_title">"Kan ikke oppdatere profilen"</string>
|
||||
<string name="screen_edit_profile_title">"Rediger profil"</string>
|
||||
<string name="screen_edit_profile_updating_details">"Oppdaterer profilen…"</string>
|
||||
<string name="screen_labs_enable_threads">"Aktiver trådsvar"</string>
|
||||
<string name="screen_labs_enable_threads_description">"Appen vil starte på nytt for å implementere denne endringen."</string>
|
||||
<string name="screen_labs_header_description">"Prøv ut våre nyeste ideer under utvikling. Disse funksjonene er ikke ferdig utviklet; de kan være ustabile og kan endres."</string>
|
||||
<string name="screen_labs_header_title">"Lyst til å prøve noe nytt?"</string>
|
||||
<string name="screen_labs_title">"Prøvefunksjoner"</string>
|
||||
<string name="screen_notification_settings_additional_settings_section_title">"Ytterligere innstillinger"</string>
|
||||
<string name="screen_notification_settings_calls_label">"Lyd- og videosamtaler"</string>
|
||||
<string name="screen_notification_settings_configuration_mismatch">"Uoverensstemmelse i konfigurasjonen"</string>
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
<string name="screen_advanced_settings_element_call_base_url_validation_error">"URL invalid, vă rugăm să vă asigurați că includeți protocolul (http/https) și adresa corectă."</string>
|
||||
<string name="screen_advanced_settings_hide_invite_avatars_toggle_title">"Ascundeți avatarele din invitațiile pentru camere"</string>
|
||||
<string name="screen_advanced_settings_hide_timeline_media_toggle_title">"Ascundeți previzualizările media în lista de mesaje"</string>
|
||||
<string name="screen_advanced_settings_labs">"Laboratoare"</string>
|
||||
<string name="screen_advanced_settings_media_compression_description">"Încărcați fotografii și videoclipuri mai rapid și reduceți consumul de date"</string>
|
||||
<string name="screen_advanced_settings_media_compression_title">"Optimizați calitatea media"</string>
|
||||
<string name="screen_advanced_settings_moderation_and_safety_section_title">"Moderare și siguranță"</string>
|
||||
@@ -43,6 +44,11 @@
|
||||
<string name="screen_edit_profile_error_title">"Nu s-a putut actualiza profilul"</string>
|
||||
<string name="screen_edit_profile_title">"Editați profilul"</string>
|
||||
<string name="screen_edit_profile_updating_details">"Se actualizează profilul…"</string>
|
||||
<string name="screen_labs_enable_threads">"Activați răspunsurile în fir"</string>
|
||||
<string name="screen_labs_enable_threads_description">"Aplicația va reporni pentru a aplica această modificare."</string>
|
||||
<string name="screen_labs_header_description">"Încercați cele mai noi idei în curs de dezvoltare. Aceste funcții nu sunt finalizate; pot fi instabile și pot suferi modificări."</string>
|
||||
<string name="screen_labs_header_title">"Doriți experiențe noi?"</string>
|
||||
<string name="screen_labs_title">"Laboratoare"</string>
|
||||
<string name="screen_notification_settings_additional_settings_section_title">"Setări adiționale"</string>
|
||||
<string name="screen_notification_settings_calls_label">"Apeluri audio și video"</string>
|
||||
<string name="screen_notification_settings_configuration_mismatch">"Nepotrivire de configurație"</string>
|
||||
|
||||
@@ -44,6 +44,10 @@
|
||||
<string name="screen_edit_profile_error_title">"Невозможно обновить профиль"</string>
|
||||
<string name="screen_edit_profile_title">"Редактировать профиль"</string>
|
||||
<string name="screen_edit_profile_updating_details">"Обновление профиля…"</string>
|
||||
<string name="screen_labs_enable_threads">"Включить ответы в топике"</string>
|
||||
<string name="screen_labs_header_description">"Попробуйте наши последние идеи в разработке. Эти функции ещё не завершены, они могут быть нестабильны и могут измениться."</string>
|
||||
<string name="screen_labs_header_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_configuration_mismatch">"Несоответствие конфигурации"</string>
|
||||
|
||||
@@ -14,5 +14,6 @@
|
||||
<string name="screen_bug_report_include_screenshot">"Send skjermbilde"</string>
|
||||
<string name="screen_bug_report_logs_description">"Logger vil bli inkludert i meldingen din, for å sikre at alt fungerer som det skal. For å sende meldingen uten logger, slå av denne innstillingen."</string>
|
||||
<string name="screen_bug_report_rash_logs_alert_title">"%1$s krasjet sist gang den ble brukt. Vil du dele en krasjrapport med oss?"</string>
|
||||
<string name="screen_bug_report_send_notification_settings_description">"Hvis du har problemer med varsler, kan det å laste opp varslingsinnstillingene hjelpe oss med å finne den underliggende årsaken."</string>
|
||||
<string name="screen_bug_report_view_logs">"Vis logger"</string>
|
||||
</resources>
|
||||
|
||||
@@ -6,5 +6,8 @@
|
||||
<item quantity="other">"Forlad %1$d rum og klynger"</item>
|
||||
</plurals>
|
||||
<string name="screen_leave_space_subtitle">"Vælg de rum, du vil forlade, som du ikke er den eneste administrator for:"</string>
|
||||
<string name="screen_leave_space_subtitle_last_admin">"Du skal tildele en anden administrator til denne klynge, før du kan forlade den."</string>
|
||||
<string name="screen_leave_space_subtitle_only_last_admin">"Du vil ikke blive fjernet fra følgende rum, fordi du er den eneste administrator:"</string>
|
||||
<string name="screen_leave_space_title">"Forlad %1$s?"</string>
|
||||
<string name="screen_leave_space_title_last_admin">"Du er den eneste administrator for %1$s"</string>
|
||||
</resources>
|
||||
|
||||
@@ -6,5 +6,8 @@
|
||||
<item quantity="other">"%1$d Chats und Space verlassen"</item>
|
||||
</plurals>
|
||||
<string name="screen_leave_space_subtitle">"Dadurch wirst du auch aus allen Chats in diesem Space entfernt."</string>
|
||||
<string name="screen_leave_space_subtitle_last_admin">"Du musst einen anderen Admin für diesen Space zuweisen, bevor du ihn verlassen kannst."</string>
|
||||
<string name="screen_leave_space_subtitle_only_last_admin">"Du wirst aus den folgenden Chats nicht entfernt, weil du der einzige Admin bist:"</string>
|
||||
<string name="screen_leave_space_title">"%1$s verlassen?"</string>
|
||||
<string name="screen_leave_space_title_last_admin">"Du bist der einzige Administrator für %1$s"</string>
|
||||
</resources>
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_leave_space_last_admin_info">"%1$s (Admin)"</string>
|
||||
<string name="screen_leave_space_subtitle">"Velg rommene du vil forlate, som du ikke er den eneste administratoren for:"</string>
|
||||
<string name="screen_leave_space_subtitle_last_admin">"Du må tildele en annen administrator for dette området før du kan forlate det."</string>
|
||||
<string name="screen_leave_space_subtitle_only_last_admin">"Du vil ikke bli fjernet fra følgende rom fordi du er den eneste administratoren:"</string>
|
||||
<string name="screen_leave_space_title">"Forlat %1$s?"</string>
|
||||
<string name="screen_leave_space_title_last_admin">"Du er den eneste administratoren for %1$s"</string>
|
||||
</resources>
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
<string name="screen_session_verification_compare_numbers_title">"Sammenlign tallene"</string>
|
||||
<string name="screen_session_verification_complete_subtitle">"Nå kan du lese eller sende meldinger sikkert på den andre enheten din."</string>
|
||||
<string name="screen_session_verification_complete_user_subtitle">"Nå kan du stole på identiteten til denne brukeren når du sender eller mottar meldinger."</string>
|
||||
<string name="screen_session_verification_device_verified">"Enheten er verifisert"</string>
|
||||
<string name="screen_session_verification_enter_recovery_key">"Skriv inn gjenopprettingsnøkkel"</string>
|
||||
<string name="screen_session_verification_failed_subtitle">"Enten ble forespørselen tidsavbrutt, forespørselen ble avslått eller det var en feil i verifiseringen."</string>
|
||||
<string name="screen_session_verification_open_existing_session_subtitle">"Bevis at det er deg for å få tilgang til den krypterte meldingshistorikken din."</string>
|
||||
|
||||
@@ -37,5 +37,8 @@ interface AppPreferencesStore {
|
||||
suspend fun setTracingLogPacks(targets: Set<TraceLogPack>)
|
||||
fun getTracingLogPacksFlow(): Flow<Set<TraceLogPack>>
|
||||
|
||||
suspend fun setShowNewNotificationSoundBanner(show: Boolean)
|
||||
fun showNewNotificationSoundBanner(): Flow<Boolean>
|
||||
|
||||
suspend fun reset()
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ private val hideInviteAvatarsKey = booleanPreferencesKey("hideInviteAvatars")
|
||||
private val timelineMediaPreviewValueKey = stringPreferencesKey("timelineMediaPreviewValue")
|
||||
private val logLevelKey = stringPreferencesKey("logLevel")
|
||||
private val traceLogPacksKey = stringPreferencesKey("traceLogPacks")
|
||||
private val showNewNotificationSoundBannerKey = booleanPreferencesKey("showNewNotificationSoundBanner")
|
||||
|
||||
@ContributesBinding(AppScope::class)
|
||||
@Inject
|
||||
@@ -145,6 +146,19 @@ class DefaultAppPreferencesStore(
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun setShowNewNotificationSoundBanner(show: Boolean) {
|
||||
store.edit { prefs ->
|
||||
prefs[showNewNotificationSoundBannerKey] = show
|
||||
}
|
||||
}
|
||||
|
||||
override fun showNewNotificationSoundBanner(): Flow<Boolean> {
|
||||
return store.data.map { prefs ->
|
||||
// Default is false, but a migration will set it to true on application upgrade (see AppMigration08)
|
||||
prefs[showNewNotificationSoundBannerKey] ?: false
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun reset() {
|
||||
store.edit { it.clear() }
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ class InMemoryAppPreferencesStore(
|
||||
theme: String? = null,
|
||||
logLevel: LogLevel = LogLevel.INFO,
|
||||
traceLockPacks: Set<TraceLogPack> = emptySet(),
|
||||
showNewNotificationSoundBanner: Boolean = false,
|
||||
) : AppPreferencesStore {
|
||||
private val isDeveloperModeEnabled = MutableStateFlow(isDeveloperModeEnabled)
|
||||
private val customElementCallBaseUrl = MutableStateFlow(customElementCallBaseUrl)
|
||||
@@ -30,6 +31,7 @@ class InMemoryAppPreferencesStore(
|
||||
private val tracingLogPacks = MutableStateFlow(traceLockPacks)
|
||||
private val hideInviteAvatars = MutableStateFlow(hideInviteAvatars)
|
||||
private val timelineMediaPreviewValue = MutableStateFlow(timelineMediaPreviewValue)
|
||||
private val showNewNotificationSoundBanner = MutableStateFlow(showNewNotificationSoundBanner)
|
||||
|
||||
override suspend fun setDeveloperModeEnabled(enabled: Boolean) {
|
||||
isDeveloperModeEnabled.value = enabled
|
||||
@@ -91,6 +93,14 @@ class InMemoryAppPreferencesStore(
|
||||
return tracingLogPacks
|
||||
}
|
||||
|
||||
override suspend fun setShowNewNotificationSoundBanner(show: Boolean) {
|
||||
showNewNotificationSoundBanner.value = show
|
||||
}
|
||||
|
||||
override fun showNewNotificationSoundBanner(): Flow<Boolean> {
|
||||
return showNewNotificationSoundBanner
|
||||
}
|
||||
|
||||
override suspend fun reset() {
|
||||
// No op
|
||||
}
|
||||
|
||||
@@ -7,8 +7,12 @@
|
||||
|
||||
package io.element.android.libraries.push.impl.notifications.channels
|
||||
|
||||
import android.content.ContentResolver
|
||||
import android.content.Context
|
||||
import android.media.AudioAttributes
|
||||
import android.media.AudioAttributes.USAGE_NOTIFICATION
|
||||
import android.media.AudioManager
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.provider.Settings
|
||||
import androidx.annotation.ChecksSdkIntAtLeast
|
||||
@@ -19,6 +23,7 @@ import dev.zacsweers.metro.ContributesBinding
|
||||
import dev.zacsweers.metro.Inject
|
||||
import dev.zacsweers.metro.SingleIn
|
||||
import io.element.android.appconfig.NotificationConfig
|
||||
import io.element.android.libraries.di.annotations.ApplicationContext
|
||||
import io.element.android.libraries.push.impl.R
|
||||
import io.element.android.services.toolbox.api.strings.StringProvider
|
||||
|
||||
@@ -26,7 +31,7 @@ import io.element.android.services.toolbox.api.strings.StringProvider
|
||||
* IDs for channels
|
||||
* ========================================================================================== */
|
||||
internal const val SILENT_NOTIFICATION_CHANNEL_ID = "DEFAULT_SILENT_NOTIFICATION_CHANNEL_ID_V2"
|
||||
internal const val NOISY_NOTIFICATION_CHANNEL_ID = "DEFAULT_NOISY_NOTIFICATION_CHANNEL_ID"
|
||||
internal const val NOISY_NOTIFICATION_CHANNEL_ID = "DEFAULT_NOISY_NOTIFICATION_CHANNEL_ID_V2"
|
||||
internal const val CALL_NOTIFICATION_CHANNEL_ID = "CALL_NOTIFICATION_CHANNEL_ID_V3"
|
||||
internal const val RINGING_CALL_NOTIFICATION_CHANNEL_ID = "RINGING_CALL_NOTIFICATION_CHANNEL_ID"
|
||||
|
||||
@@ -61,6 +66,8 @@ private fun supportNotificationChannels() = Build.VERSION.SDK_INT >= Build.VERSI
|
||||
class DefaultNotificationChannels(
|
||||
private val notificationManager: NotificationManagerCompat,
|
||||
private val stringProvider: StringProvider,
|
||||
@ApplicationContext
|
||||
private val context: Context,
|
||||
) : NotificationChannels {
|
||||
init {
|
||||
createNotificationChannels()
|
||||
@@ -94,6 +101,7 @@ class DefaultNotificationChannels(
|
||||
// Migration - Remove deprecated channels
|
||||
for (channelId in listOf(
|
||||
"DEFAULT_SILENT_NOTIFICATION_CHANNEL_ID",
|
||||
"DEFAULT_NOISY_NOTIFICATION_CHANNEL_ID",
|
||||
"CALL_NOTIFICATION_CHANNEL_ID",
|
||||
"CALL_NOTIFICATION_CHANNEL_ID_V2",
|
||||
"LISTEN_FOR_EVENTS_NOTIFICATION_CHANNEL_ID",
|
||||
@@ -112,6 +120,17 @@ class DefaultNotificationChannels(
|
||||
NOISY_NOTIFICATION_CHANNEL_ID,
|
||||
NotificationManagerCompat.IMPORTANCE_DEFAULT
|
||||
)
|
||||
.setSound(
|
||||
Uri.Builder()
|
||||
.scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
|
||||
// Strangely wwe have to provide a "//" before the package name
|
||||
.path("//" + context.packageName + "/" + R.raw.message)
|
||||
.build(),
|
||||
AudioAttributes.Builder()
|
||||
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
|
||||
.setUsage(USAGE_NOTIFICATION)
|
||||
.build(),
|
||||
)
|
||||
.setName(stringProvider.getString(R.string.notification_channel_noisy).ifEmpty { "Noisy notifications" })
|
||||
.setDescription(stringProvider.getString(R.string.notification_channel_noisy))
|
||||
.setVibrationEnabled(true)
|
||||
|
||||
BIN
libraries/push/impl/src/main/res/raw/message.mp3
Normal file
BIN
libraries/push/impl/src/main/res/raw/message.mp3
Normal file
Binary file not shown.
@@ -64,7 +64,10 @@
|
||||
<string name="troubleshoot_notifications_test_blocked_users_title">"Blokerede brugere"</string>
|
||||
<string name="troubleshoot_notifications_test_current_push_provider_description">"Få navnet på den aktuelle udbyder."</string>
|
||||
<string name="troubleshoot_notifications_test_current_push_provider_failure">"Ingen push-udbydere valgt."</string>
|
||||
<string name="troubleshoot_notifications_test_current_push_provider_failure_distributor_not_found">"Nuværende push-udbyder: %1$s og nuværende distributør: %2$s. Men distributøren %3$s kan ikke findes. Måske er applikationen blevet afinstalleret?"</string>
|
||||
<string name="troubleshoot_notifications_test_current_push_provider_failure_no_distributor">"Nuværende push-udbyder: %1$s, men der er ikke konfigureret nogen distributører."</string>
|
||||
<string name="troubleshoot_notifications_test_current_push_provider_success">"Nuværende push-udbyder: %1$s."</string>
|
||||
<string name="troubleshoot_notifications_test_current_push_provider_success_with_distributor">"Nuværende push-udbyder: %1$s (%2$s)"</string>
|
||||
<string name="troubleshoot_notifications_test_current_push_provider_title">"Nuværende push-udbyder"</string>
|
||||
<string name="troubleshoot_notifications_test_detect_push_provider_description">"Sørg for, at programmet understøtter mindst én push-udbyder."</string>
|
||||
<string name="troubleshoot_notifications_test_detect_push_provider_failure">"Ingen push-udbyder understøttelse fundet."</string>
|
||||
|
||||
@@ -65,6 +65,7 @@
|
||||
<string name="troubleshoot_notifications_test_current_push_provider_description">"Ermittele den Namen des aktuellen Anbieters."</string>
|
||||
<string name="troubleshoot_notifications_test_current_push_provider_failure">"Kein Dienst für Push-Benachrichtigungen ausgewählt."</string>
|
||||
<string name="troubleshoot_notifications_test_current_push_provider_success">"Aktueller Push-Dienst: %1$s."</string>
|
||||
<string name="troubleshoot_notifications_test_current_push_provider_success_with_distributor">"Aktueller Push-Dienst: %1$s (%2$s)"</string>
|
||||
<string name="troubleshoot_notifications_test_current_push_provider_title">"Aktueller Push-Dienst"</string>
|
||||
<string name="troubleshoot_notifications_test_detect_push_provider_description">"Stelle sicher, dass die Anwendung mindestens einen Push-Dienst hat."</string>
|
||||
<string name="troubleshoot_notifications_test_detect_push_provider_failure">"Keine Unterstützung für Push-Dienst gefunden."</string>
|
||||
|
||||
@@ -55,11 +55,18 @@
|
||||
<string name="push_distributor_firebase_android">"Google Services"</string>
|
||||
<string name="push_no_valid_google_play_services_apk_android">"Ingen gyldige Google Play-tjenester funnet. Det kan hende at varsler ikke fungerer som de skal."</string>
|
||||
<string name="troubleshoot_notifications_test_blocked_users_description">"Sjekker blokkerte brukere"</string>
|
||||
<string name="troubleshoot_notifications_test_blocked_users_quick_fix">"Vis blokkerte brukere"</string>
|
||||
<string name="troubleshoot_notifications_test_blocked_users_result_none">"Ingen brukere er blokkert."</string>
|
||||
<plurals name="troubleshoot_notifications_test_blocked_users_result_some">
|
||||
<item quantity="one">"Du blokkerte%1$d bruker. Du vil ikke motta varsler for denne brukeren."</item>
|
||||
<item quantity="other">"Du blokkerte%1$d brukere. Du vil ikke motta varsler for disse brukerne."</item>
|
||||
</plurals>
|
||||
<string name="troubleshoot_notifications_test_blocked_users_title">"Blokkerte brukere"</string>
|
||||
<string name="troubleshoot_notifications_test_current_push_provider_description">"Få navnet på den nåværende tilbyderen."</string>
|
||||
<string name="troubleshoot_notifications_test_current_push_provider_failure">"Ingen push-leverandører er valgt."</string>
|
||||
<string name="troubleshoot_notifications_test_current_push_provider_failure_no_distributor">"Nåværende push-leverandør: %1$s, men ingen distributører er konfigurert."</string>
|
||||
<string name="troubleshoot_notifications_test_current_push_provider_success">"Gjeldende push-leverandør: %1$s."</string>
|
||||
<string name="troubleshoot_notifications_test_current_push_provider_success_with_distributor">"Nåværende push-leverandør: %1$s (%2$s)"</string>
|
||||
<string name="troubleshoot_notifications_test_current_push_provider_title">"Nåværende push-leverandør"</string>
|
||||
<string name="troubleshoot_notifications_test_detect_push_provider_description">"Påse at applikasjonen har minst én push-leverandør."</string>
|
||||
<string name="troubleshoot_notifications_test_detect_push_provider_failure">"Ingen push-leverandører funnet."</string>
|
||||
|
||||
@@ -18,6 +18,7 @@ import io.mockk.verify
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.robolectric.RobolectricTestRunner
|
||||
import org.robolectric.RuntimeEnvironment
|
||||
import org.robolectric.annotation.Config
|
||||
|
||||
@RunWith(RobolectricTestRunner::class)
|
||||
@@ -66,5 +67,6 @@ class NotificationChannelsTest {
|
||||
) = DefaultNotificationChannels(
|
||||
notificationManager = notificationManager,
|
||||
stringProvider = FakeStringProvider(),
|
||||
context = RuntimeEnvironment.getApplication(),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -332,5 +332,9 @@ fun createNotificationCreator(
|
||||
|
||||
fun createNotificationChannels(): NotificationChannels {
|
||||
val context = RuntimeEnvironment.getApplication()
|
||||
return DefaultNotificationChannels(NotificationManagerCompat.from(context), FakeStringProvider(""))
|
||||
return DefaultNotificationChannels(
|
||||
notificationManager = NotificationManagerCompat.from(context),
|
||||
stringProvider = FakeStringProvider(""),
|
||||
context = context,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -94,6 +94,7 @@
|
||||
<string name="action_forgot_password">"Har du glemt din adgangskode?"</string>
|
||||
<string name="action_forward">"Videresend"</string>
|
||||
<string name="action_go_back">"Gå tilbage"</string>
|
||||
<string name="action_go_to_settings">"Gå til indstillinger"</string>
|
||||
<string name="action_ignore">"Ignorér"</string>
|
||||
<string name="action_invite">"Invitér"</string>
|
||||
<string name="action_invite_friends">"Invitér andre"</string>
|
||||
@@ -110,6 +111,7 @@
|
||||
<string name="action_manage_account">"Administrer konto"</string>
|
||||
<string name="action_manage_devices">"Administrer enheder"</string>
|
||||
<string name="action_message">"Besked"</string>
|
||||
<string name="action_minimize">"Minimér"</string>
|
||||
<string name="action_next">"Næste"</string>
|
||||
<string name="action_no">"Nej"</string>
|
||||
<string name="action_not_now">"Ikke nu"</string>
|
||||
@@ -176,6 +178,7 @@
|
||||
<string name="common_android_shortcuts_remove_reason_session_logged_out">"Du blev logget ud af sessionen"</string>
|
||||
<string name="common_appearance">"Udseende"</string>
|
||||
<string name="common_audio">"Lyd"</string>
|
||||
<string name="common_beta">"Beta"</string>
|
||||
<string name="common_blocked_users">"Blokerede brugere"</string>
|
||||
<string name="common_bubbles">"Bobler"</string>
|
||||
<string name="common_call_started">"Opkald startet"</string>
|
||||
@@ -225,6 +228,7 @@
|
||||
<string name="common_install_apk_android">"Installer APK"</string>
|
||||
<string name="common_invite_unknown_profile">"Dette Matrix-ID kan ikke findes, så invitationen modtages muligvis ikke."</string>
|
||||
<string name="common_leaving_room">"Forlader rummet"</string>
|
||||
<string name="common_leaving_space">"Forlader klynge"</string>
|
||||
<string name="common_light">"Lyst tema"</string>
|
||||
<string name="common_line_copied_to_clipboard">"Linje kopieret til udklipsholder"</string>
|
||||
<string name="common_link_copied_to_clipboard">"Linket er kopieret til udklipsholderen"</string>
|
||||
@@ -313,6 +317,7 @@
|
||||
<string name="common_settings">"Indstillinger"</string>
|
||||
<string name="common_share_space">"Del klynge"</string>
|
||||
<string name="common_shared_location">"Delt placering"</string>
|
||||
<string name="common_shared_space">"Delt klynge"</string>
|
||||
<string name="common_signing_out">"Logger ud"</string>
|
||||
<string name="common_something_went_wrong">"Noget gik galt"</string>
|
||||
<string name="common_something_went_wrong_message">"Vi stødte på et problem. Prøv venligst igen."</string>
|
||||
|
||||
@@ -94,6 +94,7 @@
|
||||
<string name="action_forgot_password">"Passwort vergessen?"</string>
|
||||
<string name="action_forward">"Weiterleiten"</string>
|
||||
<string name="action_go_back">"Zurück"</string>
|
||||
<string name="action_go_to_settings">"Zu den Einstellungen"</string>
|
||||
<string name="action_ignore">"Ignorieren"</string>
|
||||
<string name="action_invite">"Einladen"</string>
|
||||
<string name="action_invite_friends">"Nutzer einladen"</string>
|
||||
@@ -110,6 +111,7 @@
|
||||
<string name="action_manage_account">"Konto verwalten"</string>
|
||||
<string name="action_manage_devices">"Geräte verwalten"</string>
|
||||
<string name="action_message">"Nachricht"</string>
|
||||
<string name="action_minimize">"Minimieren"</string>
|
||||
<string name="action_next">"Weiter"</string>
|
||||
<string name="action_no">"Nein"</string>
|
||||
<string name="action_not_now">"Später"</string>
|
||||
@@ -176,6 +178,7 @@
|
||||
<string name="common_android_shortcuts_remove_reason_session_logged_out">"Du wurdest aus der Sitzung abgemeldet."</string>
|
||||
<string name="common_appearance">"Erscheinungsbild"</string>
|
||||
<string name="common_audio">"Audio"</string>
|
||||
<string name="common_beta">"Beta"</string>
|
||||
<string name="common_blocked_users">"Blockierte Nutzer"</string>
|
||||
<string name="common_bubbles">"Sprechblasen"</string>
|
||||
<string name="common_call_started">"Anruf gestartet"</string>
|
||||
@@ -314,6 +317,7 @@ Grund: %1$s."</string>
|
||||
<string name="common_settings">"Einstellungen"</string>
|
||||
<string name="common_share_space">"Space teilen"</string>
|
||||
<string name="common_shared_location">"Geteilter Standort"</string>
|
||||
<string name="common_shared_space">"Gemeinsamer Space"</string>
|
||||
<string name="common_signing_out">"Abmelden"</string>
|
||||
<string name="common_something_went_wrong">"Es ist ein Fehler aufgetreten."</string>
|
||||
<string name="common_something_went_wrong_message">"Wir haben ein Problem festgestellt. Bitte versuch es erneut."</string>
|
||||
|
||||
@@ -94,6 +94,7 @@
|
||||
<string name="action_forgot_password">"Mot de passe oublié ?"</string>
|
||||
<string name="action_forward">"Transférer"</string>
|
||||
<string name="action_go_back">"Retour"</string>
|
||||
<string name="action_go_to_settings">"Ouvrir les paramètres"</string>
|
||||
<string name="action_ignore">"Ignorer"</string>
|
||||
<string name="action_invite">"Inviter"</string>
|
||||
<string name="action_invite_friends">"Inviter des amis"</string>
|
||||
@@ -177,6 +178,7 @@
|
||||
<string name="common_android_shortcuts_remove_reason_session_logged_out">"Vous avez été déconnecté de la session"</string>
|
||||
<string name="common_appearance">"Apparence"</string>
|
||||
<string name="common_audio">"Audio"</string>
|
||||
<string name="common_beta">"Bêta"</string>
|
||||
<string name="common_blocked_users">"Utilisateurs bloqués"</string>
|
||||
<string name="common_bubbles">"Bulles"</string>
|
||||
<string name="common_call_started">"Appel démarré"</string>
|
||||
|
||||
@@ -93,6 +93,7 @@
|
||||
<string name="action_forgot_password">"Glemt passordet?"</string>
|
||||
<string name="action_forward">"Videresend"</string>
|
||||
<string name="action_go_back">"Gå tilbake"</string>
|
||||
<string name="action_go_to_settings">"Gå til innstillinger"</string>
|
||||
<string name="action_ignore">"Ignorer"</string>
|
||||
<string name="action_invite">"Inviter"</string>
|
||||
<string name="action_invite_friends">"Inviter folk"</string>
|
||||
@@ -109,6 +110,7 @@
|
||||
<string name="action_manage_account">"Administrer konto"</string>
|
||||
<string name="action_manage_devices">"Administrer enheter"</string>
|
||||
<string name="action_message">"Melding"</string>
|
||||
<string name="action_minimize">"Minimer"</string>
|
||||
<string name="action_next">"Neste"</string>
|
||||
<string name="action_no">"Nei"</string>
|
||||
<string name="action_not_now">"Ikke nå"</string>
|
||||
@@ -175,6 +177,7 @@
|
||||
<string name="common_android_shortcuts_remove_reason_session_logged_out">"Du ble logget ut av økten"</string>
|
||||
<string name="common_appearance">"Utseende"</string>
|
||||
<string name="common_audio">"Lyd"</string>
|
||||
<string name="common_beta">"Beta"</string>
|
||||
<string name="common_blocked_users">"Blokkerte brukere"</string>
|
||||
<string name="common_bubbles">"Bobler"</string>
|
||||
<string name="common_call_started">"Samtale startet"</string>
|
||||
@@ -189,6 +192,7 @@
|
||||
<string name="common_dark">"Mørk"</string>
|
||||
<string name="common_decryption_error">"Dekrypteringsfeil"</string>
|
||||
<string name="common_description">"Beskrivelse"</string>
|
||||
<string name="common_deselect_all">"Velg bort alle"</string>
|
||||
<string name="common_developer_options">"Alternativer for utviklere"</string>
|
||||
<string name="common_device_id">"Enhets-ID"</string>
|
||||
<string name="common_direct_chat">"Direkte chat"</string>
|
||||
@@ -223,6 +227,7 @@
|
||||
<string name="common_install_apk_android">"Installer APK"</string>
|
||||
<string name="common_invite_unknown_profile">"Finner ikke denne Matrix-IDen, så invitasjonen blir kanskje ikke mottatt."</string>
|
||||
<string name="common_leaving_room">"Forlater rommet"</string>
|
||||
<string name="common_leaving_space">"Forlater området"</string>
|
||||
<string name="common_light">"Lys"</string>
|
||||
<string name="common_line_copied_to_clipboard">"Linje kopiert til utklippstavlen"</string>
|
||||
<string name="common_link_copied_to_clipboard">"Lenke kopiert til utklippstavlen"</string>
|
||||
@@ -298,6 +303,7 @@
|
||||
<string name="common_security">"Sikkerhet"</string>
|
||||
<string name="common_seen_by">"Sett av"</string>
|
||||
<string name="common_select_account">"Velg en konto"</string>
|
||||
<string name="common_select_all">"Velg alle"</string>
|
||||
<string name="common_send_to">"Sendt til"</string>
|
||||
<string name="common_sending">"Sender…"</string>
|
||||
<string name="common_sending_failed">"Kunne ikke sende"</string>
|
||||
@@ -308,6 +314,7 @@
|
||||
<string name="common_settings">"Innstillinger"</string>
|
||||
<string name="common_share_space">"Del område"</string>
|
||||
<string name="common_shared_location">"Delt posisjon"</string>
|
||||
<string name="common_shared_space">"Delt område"</string>
|
||||
<string name="common_signing_out">"Logger av"</string>
|
||||
<string name="common_something_went_wrong">"Noe gikk galt"</string>
|
||||
<string name="common_something_went_wrong_message">"Vi har støtt på et problem. Vennligst prøv igjen."</string>
|
||||
@@ -453,6 +460,7 @@ Er du sikker på at du vil fortsette?"</string>
|
||||
<string name="screen_share_this_location_action">"Del denne lokasjonen"</string>
|
||||
<string name="screen_space_list_description">"Områder du har opprettet eller blitt med i."</string>
|
||||
<string name="screen_space_list_details">"%1$s • %2$s"</string>
|
||||
<string name="screen_space_list_parent_space">"%1$s område"</string>
|
||||
<string name="screen_space_list_title">"Områder"</string>
|
||||
<string name="screen_timeline_item_menu_send_failure_changed_identity">"Meldingen ble ikke sendt fordi %1$ss verifiserte identitet er tilbakestilt."</string>
|
||||
<string name="screen_timeline_item_menu_send_failure_unsigned_device">"Meldingen ble ikke sendt fordi %1$s ikke har verifisert alle enheter."</string>
|
||||
|
||||
@@ -96,6 +96,7 @@
|
||||
<string name="action_forgot_password">"Ați uitat parola?"</string>
|
||||
<string name="action_forward">"Redirecționați"</string>
|
||||
<string name="action_go_back">"Înapoi"</string>
|
||||
<string name="action_go_to_settings">"Mergeți la setări"</string>
|
||||
<string name="action_ignore">"Ignorați"</string>
|
||||
<string name="action_invite">"Invitați"</string>
|
||||
<string name="action_invite_friends">"Invitați prieteni"</string>
|
||||
@@ -179,6 +180,7 @@
|
||||
<string name="common_android_shortcuts_remove_reason_session_logged_out">"Ați fost deconectat din sesiune."</string>
|
||||
<string name="common_appearance">"Aspect"</string>
|
||||
<string name="common_audio">"Audio"</string>
|
||||
<string name="common_beta">"Beta"</string>
|
||||
<string name="common_blocked_users">"Utilizatori blocați"</string>
|
||||
<string name="common_bubbles">"Baloane"</string>
|
||||
<string name="common_call_started">"A început un apel"</string>
|
||||
@@ -323,6 +325,7 @@ Motiv:%1$s."</string>
|
||||
<string name="common_settings">"Setări"</string>
|
||||
<string name="common_share_space">"Partajați spațiul"</string>
|
||||
<string name="common_shared_location">"Locație partajată"</string>
|
||||
<string name="common_shared_space">"Spațiu comun"</string>
|
||||
<string name="common_signing_out">"Deconectare în curs"</string>
|
||||
<string name="common_something_went_wrong">"Ceva nu a mers bine"</string>
|
||||
<string name="common_something_went_wrong_message">"Am întâmpinat o problemă. Vă rugăm să încercați din nou."</string>
|
||||
|
||||
@@ -166,8 +166,6 @@
|
||||
<string name="action_yes_try_again">"Да, попробуйте еще раз"</string>
|
||||
<string name="banner_migrate_to_native_sliding_sync_description">"Теперь ваш сервер поддерживает новый, более быстрый протокол. Чтобы обновить его прямо сейчас, выйдите и войдите в свою учётную запись снова. Сделав это сейчас, вы сможете избежать принудительного выхода из системы при последующем удалении старого протокола."</string>
|
||||
<string name="banner_migrate_to_native_sliding_sync_title">"Доступно обновление"</string>
|
||||
<string name="banner_new_sound_message">"Ваши уведомления были обновлены — теперь они понятнее, быстрее и менее отвлекающие."</string>
|
||||
<string name="banner_new_sound_title">"Мы обновили ваши звуки"</string>
|
||||
<string name="common_about">"О приложении"</string>
|
||||
<string name="common_acceptable_use_policy">"Политика допустимого использования"</string>
|
||||
<string name="common_add_account">"Добавить аккаунт"</string>
|
||||
@@ -433,10 +431,6 @@
|
||||
<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_labs_enable_threads">"Включить ответы в топике"</string>
|
||||
<string name="screen_labs_header_description">"Попробуйте наши последние идеи в разработке. Эти функции ещё не завершены, они могут быть нестабильны и могут измениться."</string>
|
||||
<string name="screen_labs_header_title">"Хотите попробовать?"</string>
|
||||
<string name="screen_labs_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>
|
||||
|
||||
@@ -166,8 +166,6 @@
|
||||
<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>
|
||||
<string name="banner_migrate_to_native_sliding_sync_title">"Upgrade available"</string>
|
||||
<string name="banner_new_sound_message">"Your notification ping has been updated—clearer, quicker, and less disruptive."</string>
|
||||
<string name="banner_new_sound_title">"We’ve refreshed your sounds"</string>
|
||||
<string name="common_about">"About"</string>
|
||||
<string name="common_acceptable_use_policy">"Acceptable use policy"</string>
|
||||
<string name="common_add_account">"Add an account"</string>
|
||||
@@ -428,11 +426,6 @@ 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_labs_enable_threads">"Enable thread replies"</string>
|
||||
<string name="screen_labs_enable_threads_description">"Restarting the app is required to apply changes"</string>
|
||||
<string name="screen_labs_header_description">"Try out our latest ideas in development. These features are not finalised; they may be unstable, may change."</string>
|
||||
<string name="screen_labs_header_title">"Feeling experimental?"</string>
|
||||
<string name="screen_labs_title">"Labs"</string>
|
||||
<string name="screen_media_picker_error_failed_selection">"Failed selecting media, please try again."</string>
|
||||
<string name="screen_pinned_timeline_empty_state_description">"Press on a message and choose “%1$s” to include here."</string>
|
||||
<string name="screen_pinned_timeline_empty_state_headline">"Pin important messages so that they can be easily discovered"</string>
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -185,6 +185,7 @@
|
||||
"confirm_recovery_key_banner_.*",
|
||||
"banner\\.set_up_recovery\\..*",
|
||||
"banner\\.battery_optimization\\..*",
|
||||
"banner\\.new_sound\\..*",
|
||||
"full_screen_intent_banner_.*",
|
||||
"screen_migration_.*",
|
||||
"screen_invites_.*"
|
||||
|
||||
Reference in New Issue
Block a user