Merge branch 'develop' into feature/fga/pinned_message_banner_logic
This commit is contained in:
commit
229c02e895
45 changed files with 994 additions and 606 deletions
|
|
@ -45,6 +45,12 @@
|
|||
<string name="state_event_room_name_removed_by_you">"Вы выдалілі назву пакоя"</string>
|
||||
<string name="state_event_room_none">"%1$s не зрабіў(-ла) ніякіх змен"</string>
|
||||
<string name="state_event_room_none_by_you">"Вы не зрабілі ніякіх змен"</string>
|
||||
<string name="state_event_room_pinned_events_changed">"%1$s змяніў(-ла) замацаваныя паведамленні"</string>
|
||||
<string name="state_event_room_pinned_events_changed_by_you">"Вы змянілі замацаваныя паведамленні"</string>
|
||||
<string name="state_event_room_pinned_events_pinned">"%1$s замацаваў(-ла) паведамленне"</string>
|
||||
<string name="state_event_room_pinned_events_pinned_by_you">"Вы замацавалі паведамленне"</string>
|
||||
<string name="state_event_room_pinned_events_unpinned">"%1$s адмацаваў(-ла) паведамленне"</string>
|
||||
<string name="state_event_room_pinned_events_unpinned_by_you">"Вы адмацавалі паведамленне"</string>
|
||||
<string name="state_event_room_reject">"%1$s адхіліў(-ла) запрашэнне"</string>
|
||||
<string name="state_event_room_reject_by_you">"Вы адхілілі запрашэнне"</string>
|
||||
<string name="state_event_room_remove">"%1$s выдаліў(-ла) %2$s"</string>
|
||||
|
|
|
|||
|
|
@ -45,6 +45,12 @@
|
|||
<string name="state_event_room_name_removed_by_you">"Sina eemaldasid jututoa nime"</string>
|
||||
<string name="state_event_room_none">"%1$s ei teinud ühtegi muudatust"</string>
|
||||
<string name="state_event_room_none_by_you">"Sina ei teinud ühtegi muudatust"</string>
|
||||
<string name="state_event_room_pinned_events_changed">"%1$s muutis klammerdatud sõnumeid"</string>
|
||||
<string name="state_event_room_pinned_events_changed_by_you">"Sina muutsid klammerdatud sõnumeid"</string>
|
||||
<string name="state_event_room_pinned_events_pinned">"%1$s klammerdas sõnumi"</string>
|
||||
<string name="state_event_room_pinned_events_pinned_by_you">"Sina klammerdasid sõnumi"</string>
|
||||
<string name="state_event_room_pinned_events_unpinned">"%1$s eemaldas klammerdatud sõnumi"</string>
|
||||
<string name="state_event_room_pinned_events_unpinned_by_you">"Sina eemaldasid klammerdatud sõnumi"</string>
|
||||
<string name="state_event_room_reject">"%1$s lükkas kutse tagasi"</string>
|
||||
<string name="state_event_room_reject_by_you">"Sina lükkasid kutse tagasi"</string>
|
||||
<string name="state_event_room_remove">"%1$s eemaldas jututoast kasutaja %2$s"</string>
|
||||
|
|
|
|||
|
|
@ -45,6 +45,12 @@
|
|||
<string name="state_event_room_name_removed_by_you">"Removeste o nome da sala"</string>
|
||||
<string name="state_event_room_none">"%1$s não fiz nenhuma alteração"</string>
|
||||
<string name="state_event_room_none_by_you">"Não fizeste nenhuma alteração"</string>
|
||||
<string name="state_event_room_pinned_events_changed">"%1$s alterou as mensagens afixadas"</string>
|
||||
<string name="state_event_room_pinned_events_changed_by_you">"Alteraste as mensagens afixadas"</string>
|
||||
<string name="state_event_room_pinned_events_pinned">"%1$s afixou uma mensagem"</string>
|
||||
<string name="state_event_room_pinned_events_pinned_by_you">"Afixaste uma mensagem"</string>
|
||||
<string name="state_event_room_pinned_events_unpinned">"%1$s desafixou uma mensagem"</string>
|
||||
<string name="state_event_room_pinned_events_unpinned_by_you">"Desafixaste uma mensagem"</string>
|
||||
<string name="state_event_room_reject">"%1$s rejeitou o convite"</string>
|
||||
<string name="state_event_room_reject_by_you">"Rejeitaste o convite"</string>
|
||||
<string name="state_event_room_remove">"%1$s removeu %2$s"</string>
|
||||
|
|
|
|||
|
|
@ -45,6 +45,12 @@
|
|||
<string name="state_event_room_name_removed_by_you">"Вы удалили название комнаты"</string>
|
||||
<string name="state_event_room_none">"%1$s ничего не изменил"</string>
|
||||
<string name="state_event_room_none_by_you">"Вы не внесли никаких изменений"</string>
|
||||
<string name="state_event_room_pinned_events_changed">"%1$s изменил закрепленные сообщения"</string>
|
||||
<string name="state_event_room_pinned_events_changed_by_you">"Вы изменили закрепленные сообщения"</string>
|
||||
<string name="state_event_room_pinned_events_pinned">"%1$s закрепил сообщение"</string>
|
||||
<string name="state_event_room_pinned_events_pinned_by_you">"Вы закрепили сообщение"</string>
|
||||
<string name="state_event_room_pinned_events_unpinned">"%1$s открепил сообщение"</string>
|
||||
<string name="state_event_room_pinned_events_unpinned_by_you">"Вы открепили сообщение"</string>
|
||||
<string name="state_event_room_reject">"%1$s отклонил приглашение"</string>
|
||||
<string name="state_event_room_reject_by_you">"Вы отклонили приглашение"</string>
|
||||
<string name="state_event_room_remove">"%1$s удалил %2$s"</string>
|
||||
|
|
|
|||
|
|
@ -45,6 +45,12 @@
|
|||
<string name="state_event_room_name_removed_by_you">"Odstránili ste názov miestnosti"</string>
|
||||
<string name="state_event_room_none">"%1$s nevykonal/a žiadne zmeny"</string>
|
||||
<string name="state_event_room_none_by_you">"Nevykonali ste žiadne zmeny"</string>
|
||||
<string name="state_event_room_pinned_events_changed">"%1$s zmenil/a pripnuté správy"</string>
|
||||
<string name="state_event_room_pinned_events_changed_by_you">"Zmenili ste pripnuté správy"</string>
|
||||
<string name="state_event_room_pinned_events_pinned">"%1$s pripol/la správu"</string>
|
||||
<string name="state_event_room_pinned_events_pinned_by_you">"Pripli ste správu"</string>
|
||||
<string name="state_event_room_pinned_events_unpinned">"%1$s zrušil/a pripnutie správy"</string>
|
||||
<string name="state_event_room_pinned_events_unpinned_by_you">"Zrušili ste pripnutie správy"</string>
|
||||
<string name="state_event_room_reject">"%1$s odmietol/a pozvánku"</string>
|
||||
<string name="state_event_room_reject_by_you">"Odmietli ste pozvánku"</string>
|
||||
<string name="state_event_room_remove">"%1$s odstránil/a %2$s"</string>
|
||||
|
|
|
|||
|
|
@ -45,6 +45,12 @@
|
|||
<string name="state_event_room_name_removed_by_you">"You removed the room name"</string>
|
||||
<string name="state_event_room_none">"%1$s made no changes"</string>
|
||||
<string name="state_event_room_none_by_you">"You made no changes"</string>
|
||||
<string name="state_event_room_pinned_events_changed">"%1$s changed the pinned messages"</string>
|
||||
<string name="state_event_room_pinned_events_changed_by_you">"You changed the pinned messages"</string>
|
||||
<string name="state_event_room_pinned_events_pinned">"%1$s pinned a message"</string>
|
||||
<string name="state_event_room_pinned_events_pinned_by_you">"You pinned a message"</string>
|
||||
<string name="state_event_room_pinned_events_unpinned">"%1$s unpinned a message"</string>
|
||||
<string name="state_event_room_pinned_events_unpinned_by_you">"You unpinned a message"</string>
|
||||
<string name="state_event_room_reject">"%1$s rejected the invitation"</string>
|
||||
<string name="state_event_room_reject_by_you">"You rejected the invitation"</string>
|
||||
<string name="state_event_room_remove">"%1$s removed %2$s"</string>
|
||||
|
|
|
|||
|
|
@ -140,6 +140,7 @@ class FakeMatrixRoom(
|
|||
private val saveComposerDraftLambda: (ComposerDraft) -> Result<Unit> = { _: ComposerDraft -> Result.success(Unit) },
|
||||
private val loadComposerDraftLambda: () -> Result<ComposerDraft?> = { Result.success<ComposerDraft?>(null) },
|
||||
private val clearComposerDraftLambda: () -> Result<Unit> = { Result.success(Unit) },
|
||||
private val subscribeToSyncLambda: () -> Unit = { lambdaError() },
|
||||
) : MatrixRoom {
|
||||
private val _roomInfoFlow: MutableSharedFlow<MatrixRoomInfo> = MutableSharedFlow(replay = 1)
|
||||
override val roomInfoFlow: Flow<MatrixRoomInfo> = _roomInfoFlow
|
||||
|
|
@ -186,7 +187,9 @@ class FakeMatrixRoom(
|
|||
pinnedEventsTimelineResult()
|
||||
}
|
||||
|
||||
override suspend fun subscribeToSync() = Unit
|
||||
override suspend fun subscribeToSync() {
|
||||
subscribeToSyncLambda()
|
||||
}
|
||||
|
||||
override suspend fun powerLevels(): Result<MatrixRoomPowerLevels> {
|
||||
return powerLevelsResult()
|
||||
|
|
|
|||
|
|
@ -22,22 +22,16 @@ import kotlinx.coroutines.flow.MutableStateFlow
|
|||
import kotlinx.coroutines.flow.StateFlow
|
||||
|
||||
class FakeSyncService(
|
||||
initialState: SyncState = SyncState.Idle
|
||||
syncStateFlow: MutableStateFlow<SyncState> = MutableStateFlow(SyncState.Idle)
|
||||
) : SyncService {
|
||||
private val syncStateFlow = MutableStateFlow(initialState)
|
||||
|
||||
fun simulateError() {
|
||||
syncStateFlow.value = SyncState.Error
|
||||
}
|
||||
|
||||
var startSyncLambda: () -> Result<Unit> = { Result.success(Unit) }
|
||||
override suspend fun startSync(): Result<Unit> {
|
||||
syncStateFlow.value = SyncState.Running
|
||||
return Result.success(Unit)
|
||||
return startSyncLambda()
|
||||
}
|
||||
|
||||
var stopSyncLambda: () -> Result<Unit> = { Result.success(Unit) }
|
||||
override suspend fun stopSync(): Result<Unit> {
|
||||
syncStateFlow.value = SyncState.Terminated
|
||||
return Result.success(Unit)
|
||||
return stopSyncLambda()
|
||||
}
|
||||
|
||||
override val syncState: StateFlow<SyncState> = syncStateFlow
|
||||
|
|
|
|||
|
|
@ -82,4 +82,6 @@ dependencies {
|
|||
testImplementation(projects.services.appnavstate.test)
|
||||
testImplementation(projects.services.toolbox.impl)
|
||||
testImplementation(projects.services.toolbox.test)
|
||||
testImplementation(projects.libraries.featureflag.test)
|
||||
testImplementation(libs.kotlinx.collections.immutable)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,9 +18,6 @@ package io.element.android.libraries.push.impl.push
|
|||
|
||||
import com.squareup.anvil.annotations.ContributesBinding
|
||||
import io.element.android.libraries.di.AppScope
|
||||
import io.element.android.libraries.featureflag.api.FeatureFlagService
|
||||
import io.element.android.libraries.featureflag.api.FeatureFlags
|
||||
import io.element.android.libraries.matrix.api.MatrixClientProvider
|
||||
import io.element.android.libraries.push.impl.notifications.DefaultNotificationDrawerManager
|
||||
import io.element.android.libraries.push.impl.notifications.model.NotifiableEvent
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
|
|
@ -35,23 +32,12 @@ interface OnNotifiableEventReceived {
|
|||
class DefaultOnNotifiableEventReceived @Inject constructor(
|
||||
private val defaultNotificationDrawerManager: DefaultNotificationDrawerManager,
|
||||
private val coroutineScope: CoroutineScope,
|
||||
private val matrixClientProvider: MatrixClientProvider,
|
||||
private val featureFlagService: FeatureFlagService,
|
||||
private val syncOnNotifiableEvent: SyncOnNotifiableEvent,
|
||||
) : OnNotifiableEventReceived {
|
||||
override fun onNotifiableEventReceived(notifiableEvent: NotifiableEvent) {
|
||||
coroutineScope.launch {
|
||||
subscribeToRoomIfNeeded(notifiableEvent)
|
||||
launch { syncOnNotifiableEvent(notifiableEvent) }
|
||||
defaultNotificationDrawerManager.onNotifiableEventReceived(notifiableEvent)
|
||||
}
|
||||
}
|
||||
|
||||
private fun CoroutineScope.subscribeToRoomIfNeeded(notifiableEvent: NotifiableEvent) = launch {
|
||||
if (!featureFlagService.isFeatureEnabled(FeatureFlags.SyncOnPush)) {
|
||||
return@launch
|
||||
}
|
||||
val client = matrixClientProvider.getOrRestore(notifiableEvent.sessionId).getOrNull() ?: return@launch
|
||||
client.getRoom(notifiableEvent.roomId)?.use { room ->
|
||||
room.subscribeToSync()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* Copyright (c) 2024 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.push.impl.push
|
||||
|
||||
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
||||
import io.element.android.libraries.featureflag.api.FeatureFlagService
|
||||
import io.element.android.libraries.featureflag.api.FeatureFlags
|
||||
import io.element.android.libraries.matrix.api.MatrixClientProvider
|
||||
import io.element.android.libraries.matrix.api.core.EventId
|
||||
import io.element.android.libraries.matrix.api.room.MatrixRoom
|
||||
import io.element.android.libraries.matrix.api.sync.SyncService
|
||||
import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
|
||||
import io.element.android.libraries.push.impl.notifications.model.NotifiableEvent
|
||||
import io.element.android.services.appnavstate.api.AppForegroundStateService
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlinx.coroutines.withTimeoutOrNull
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
import javax.inject.Inject
|
||||
import kotlin.time.Duration
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
class SyncOnNotifiableEvent @Inject constructor(
|
||||
private val matrixClientProvider: MatrixClientProvider,
|
||||
private val featureFlagService: FeatureFlagService,
|
||||
private val appForegroundStateService: AppForegroundStateService,
|
||||
private val dispatchers: CoroutineDispatchers,
|
||||
) {
|
||||
private var syncCounter = AtomicInteger(0)
|
||||
|
||||
suspend operator fun invoke(notifiableEvent: NotifiableEvent) = withContext(dispatchers.io) {
|
||||
if (!featureFlagService.isFeatureEnabled(FeatureFlags.SyncOnPush)) {
|
||||
return@withContext
|
||||
}
|
||||
val client = matrixClientProvider.getOrRestore(notifiableEvent.sessionId).getOrNull() ?: return@withContext
|
||||
client.getRoom(notifiableEvent.roomId)?.use { room ->
|
||||
room.subscribeToSync()
|
||||
|
||||
// If the app is in foreground, sync is already running, so just add the subscription.
|
||||
if (!appForegroundStateService.isInForeground.value) {
|
||||
val syncService = client.syncService()
|
||||
syncService.startSyncIfNeeded()
|
||||
room.waitsUntilEventIsKnown(eventId = notifiableEvent.eventId, timeout = 10.seconds)
|
||||
syncService.stopSyncIfNeeded()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun MatrixRoom.waitsUntilEventIsKnown(eventId: EventId, timeout: Duration) {
|
||||
withTimeoutOrNull(timeout) {
|
||||
liveTimeline.timelineItems.first { timelineItems ->
|
||||
timelineItems.any { timelineItem ->
|
||||
when (timelineItem) {
|
||||
is MatrixTimelineItem.Event -> timelineItem.eventId == eventId
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun SyncService.startSyncIfNeeded() {
|
||||
if (syncCounter.getAndIncrement() == 0) {
|
||||
startSync()
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun SyncService.stopSyncIfNeeded() {
|
||||
if (syncCounter.decrementAndGet() == 0 && !appForegroundStateService.isInForeground.value) {
|
||||
stopSync()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,151 @@
|
|||
/*
|
||||
* Copyright (c) 2024 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.push.impl.push
|
||||
|
||||
import io.element.android.libraries.featureflag.api.FeatureFlags
|
||||
import io.element.android.libraries.featureflag.test.FakeFeatureFlagService
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.matrix.api.sync.SyncState
|
||||
import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
|
||||
import io.element.android.libraries.matrix.test.A_ROOM_ID
|
||||
import io.element.android.libraries.matrix.test.A_UNIQUE_ID
|
||||
import io.element.android.libraries.matrix.test.FakeMatrixClient
|
||||
import io.element.android.libraries.matrix.test.FakeMatrixClientProvider
|
||||
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
|
||||
import io.element.android.libraries.matrix.test.sync.FakeSyncService
|
||||
import io.element.android.libraries.matrix.test.timeline.FakeTimeline
|
||||
import io.element.android.libraries.matrix.test.timeline.anEventTimelineItem
|
||||
import io.element.android.libraries.push.impl.notifications.fixtures.aNotifiableMessageEvent
|
||||
import io.element.android.services.appnavstate.test.FakeAppForegroundStateService
|
||||
import io.element.android.tests.testutils.lambda.assert
|
||||
import io.element.android.tests.testutils.lambda.lambdaRecorder
|
||||
import io.element.android.tests.testutils.testCoroutineDispatchers
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.test.TestScope
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Test
|
||||
|
||||
class SyncOnNotifiableEventTest {
|
||||
private val timelineItems = MutableStateFlow<List<MatrixTimelineItem>>(emptyList())
|
||||
private val syncStateFlow = MutableStateFlow(SyncState.Idle)
|
||||
private val startSyncLambda = lambdaRecorder<Result<Unit>> { Result.success(Unit) }
|
||||
private val stopSyncLambda = lambdaRecorder<Result<Unit>> { Result.success(Unit) }
|
||||
private val subscribeToSyncLambda = lambdaRecorder<Unit> { }
|
||||
|
||||
private val liveTimeline = FakeTimeline(
|
||||
timelineItems = timelineItems,
|
||||
)
|
||||
private val room = FakeMatrixRoom(
|
||||
roomId = A_ROOM_ID,
|
||||
liveTimeline = liveTimeline,
|
||||
subscribeToSyncLambda = subscribeToSyncLambda
|
||||
)
|
||||
private val syncService = FakeSyncService(syncStateFlow).also {
|
||||
it.startSyncLambda = startSyncLambda
|
||||
it.stopSyncLambda = stopSyncLambda
|
||||
}
|
||||
|
||||
private val client = FakeMatrixClient(
|
||||
syncService = syncService,
|
||||
).apply {
|
||||
givenGetRoomResult(A_ROOM_ID, room)
|
||||
}
|
||||
|
||||
private val notifiableEvent = aNotifiableMessageEvent()
|
||||
|
||||
@Test
|
||||
fun `when feature flag is disabled, nothing happens`() = runTest {
|
||||
val sut = createSyncOnNotifiableEvent(client = client, isSyncOnPushEnabled = false)
|
||||
|
||||
sut(notifiableEvent)
|
||||
|
||||
assert(startSyncLambda).isNeverCalled()
|
||||
assert(stopSyncLambda).isNeverCalled()
|
||||
assert(subscribeToSyncLambda).isNeverCalled()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when feature flag is enabled and app is in foreground, sync is not started`() = runTest {
|
||||
val sut = createSyncOnNotifiableEvent(client = client, isAppInForeground = true, isSyncOnPushEnabled = true)
|
||||
|
||||
sut(notifiableEvent)
|
||||
|
||||
assert(startSyncLambda).isNeverCalled()
|
||||
assert(stopSyncLambda).isNeverCalled()
|
||||
assert(subscribeToSyncLambda).isCalledOnce()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when feature flag is enabled and app is in background, sync is started and stopped`() = runTest {
|
||||
val sut = createSyncOnNotifiableEvent(client = client, isAppInForeground = false, isSyncOnPushEnabled = true)
|
||||
|
||||
timelineItems.emit(
|
||||
listOf(MatrixTimelineItem.Event(A_UNIQUE_ID, anEventTimelineItem()))
|
||||
)
|
||||
syncStateFlow.emit(SyncState.Running)
|
||||
sut(notifiableEvent)
|
||||
|
||||
assert(startSyncLambda).isCalledOnce()
|
||||
assert(stopSyncLambda).isCalledOnce()
|
||||
assert(subscribeToSyncLambda).isCalledOnce()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when feature flag is enabled and app is in background, running multiple time only call once`() = runTest {
|
||||
val sut = createSyncOnNotifiableEvent(client = client, isAppInForeground = false, isSyncOnPushEnabled = true)
|
||||
|
||||
coroutineScope {
|
||||
launch { sut(notifiableEvent) }
|
||||
launch { sut(notifiableEvent) }
|
||||
launch {
|
||||
delay(1)
|
||||
timelineItems.emit(
|
||||
listOf(MatrixTimelineItem.Event(A_UNIQUE_ID, anEventTimelineItem()))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
assert(startSyncLambda).isCalledOnce()
|
||||
assert(stopSyncLambda).isCalledOnce()
|
||||
assert(subscribeToSyncLambda).isCalledExactly(2)
|
||||
}
|
||||
|
||||
private fun TestScope.createSyncOnNotifiableEvent(
|
||||
client: MatrixClient = FakeMatrixClient(),
|
||||
isSyncOnPushEnabled: Boolean = true,
|
||||
isAppInForeground: Boolean = true,
|
||||
): SyncOnNotifiableEvent {
|
||||
val featureFlagService = FakeFeatureFlagService(
|
||||
initialState = mapOf(
|
||||
FeatureFlags.SyncOnPush.key to isSyncOnPushEnabled
|
||||
)
|
||||
)
|
||||
val appForegroundStateService = FakeAppForegroundStateService(
|
||||
initialValue = isAppInForeground
|
||||
)
|
||||
val matrixClientProvider = FakeMatrixClientProvider { Result.success(client) }
|
||||
return SyncOnNotifiableEvent(
|
||||
matrixClientProvider = matrixClientProvider,
|
||||
featureFlagService = featureFlagService,
|
||||
appForegroundStateService = appForegroundStateService,
|
||||
dispatchers = testCoroutineDispatchers(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -91,6 +91,7 @@
|
|||
<string name="action_report_bug">"Teata veast"</string>
|
||||
<string name="action_report_content">"Teata sisust haldurile"</string>
|
||||
<string name="action_reset">"Lähtesta"</string>
|
||||
<string name="action_reset_identity">"Lähtesta on identiteet"</string>
|
||||
<string name="action_retry">"Proovi uuesti"</string>
|
||||
<string name="action_retry_decryption">"Proovi dekrüptimist uuesti"</string>
|
||||
<string name="action_save">"Salvesta"</string>
|
||||
|
|
@ -266,9 +267,21 @@ Põhjus: %1$s."</string>
|
|||
<string name="invite_friends_text">"Hei, suhtle minuga %1$s võrgus: %2$s"</string>
|
||||
<string name="login_initial_device_name_android">"%1$s Android"</string>
|
||||
<string name="preference_rageshake">"Veast teatamiseks raputa nutiseadet ägedalt"</string>
|
||||
<string name="screen_encryption_reset_bullet_1">"Sinu kasutajakonto andmed, kontaktid, eelistused ja vestluste loend säiluvad"</string>
|
||||
<string name="screen_encryption_reset_bullet_2">"Sa kaotad seniste sõnumite ajaloo"</string>
|
||||
<string name="screen_encryption_reset_bullet_3">"Sa pead kõik oma olemasolevad seadmed ja kontaktid uuesti verifitseerima"</string>
|
||||
<string name="screen_encryption_reset_footer">"Lähtesta oma identiteet vaid siis, kui sul pole ligipääsu mitte ühelegi oma seadmele ja sa oled kaotanud oma taastevõtme."</string>
|
||||
<string name="screen_encryption_reset_subtitle">"Kui sa soovid jätkata selle rakenduse kasutamist ja sa pole mitte üheski seadmes sisse logitud ning oled kaotanud oma taastevõtme, siis tõesti pead lähtestama oma identiteedi. "</string>
|
||||
<string name="screen_encryption_reset_title">"Kui sa ühtegi muud võimalust ei leia, siis lähtesta oma identiteet."</string>
|
||||
<string name="screen_media_picker_error_failed_selection">"Meediafaili valimine ei õnnestunud. Palun proovi uuesti."</string>
|
||||
<string name="screen_media_upload_preview_error_failed_processing">"Meediafaili töötlemine enne üleslaadimist ei õnnestunud. Palun proovi uuesti."</string>
|
||||
<string name="screen_media_upload_preview_error_failed_sending">"Meediafaili üleslaadimine ei õnnestunud. Palun proovi uuesti."</string>
|
||||
<string name="screen_reset_encryption_confirmation_alert_action">"Jah, lähtesta nüüd"</string>
|
||||
<string name="screen_reset_encryption_confirmation_alert_subtitle">"See tegevus on tagasipöördumatu."</string>
|
||||
<string name="screen_reset_encryption_confirmation_alert_title">"Kas sa oled kindel, et soovid oma andmete krüptimist lähtestada?"</string>
|
||||
<string name="screen_reset_encryption_password_placeholder">"Sisesta…"</string>
|
||||
<string name="screen_reset_encryption_password_subtitle">"Palun kinnita, et soovid oma andmete krüptimist lähtestada."</string>
|
||||
<string name="screen_reset_encryption_password_title">"Jätkamaks sisesta oma kasutajakonto salasõna"</string>
|
||||
<string name="screen_room_error_failed_processing_media">"Meediafaili töötlemine enne üleslaadimist ei õnnestunud. Palun proovi uuesti."</string>
|
||||
<string name="screen_room_error_failed_retrieving_user_details">"Kasutaja andmete laadimine ei õnnestunud"</string>
|
||||
<string name="screen_room_member_details_block_alert_action">"Blokeeri"</string>
|
||||
|
|
|
|||
|
|
@ -80,6 +80,7 @@
|
|||
<string name="action_ok">"OK"</string>
|
||||
<string name="action_open_settings">"Configurações"</string>
|
||||
<string name="action_open_with">"Abrir com"</string>
|
||||
<string name="action_pin">"Afixar"</string>
|
||||
<string name="action_quick_reply">"Resposta rápida"</string>
|
||||
<string name="action_quote">"Citação"</string>
|
||||
<string name="action_react">"Reagir"</string>
|
||||
|
|
@ -90,6 +91,7 @@
|
|||
<string name="action_report_bug">"Comunicar problema"</string>
|
||||
<string name="action_report_content">"Denunciar conteúdo"</string>
|
||||
<string name="action_reset">"Repor"</string>
|
||||
<string name="action_reset_identity">"Repor identidade"</string>
|
||||
<string name="action_retry">"Tentar novamente"</string>
|
||||
<string name="action_retry_decryption">"Tentar decifragem novamente"</string>
|
||||
<string name="action_save">"Guardar"</string>
|
||||
|
|
@ -109,6 +111,7 @@
|
|||
<string name="action_take_photo">"Tirar foto"</string>
|
||||
<string name="action_tap_for_options">"Toca para ver as opções"</string>
|
||||
<string name="action_try_again">"Tentar novamente"</string>
|
||||
<string name="action_unpin">"Desafixar"</string>
|
||||
<string name="action_view_source">"Ver fonte"</string>
|
||||
<string name="action_yes">"Sim"</string>
|
||||
<string name="common_about">"Sobre"</string>
|
||||
|
|
@ -168,6 +171,7 @@ Razão: %1$s."</string>
|
|||
<string name="common_no_results">"Sem resultados"</string>
|
||||
<string name="common_no_room_name">"Sala sem nome"</string>
|
||||
<string name="common_offline">"Desligado"</string>
|
||||
<string name="common_open_source_licenses">"Licenças de código aberto"</string>
|
||||
<string name="common_or">"ou"</string>
|
||||
<string name="common_password">"Senha"</string>
|
||||
<string name="common_people">"Pessoas"</string>
|
||||
|
|
@ -255,13 +259,29 @@ Razão: %1$s."</string>
|
|||
<string name="error_missing_microphone_voice_rationale_android">"A %1$s não tem permissão para aceder ao teu microfone. Permite o acesso para gravar uma mensagem de voz."</string>
|
||||
<string name="error_some_messages_have_not_been_sent">"Algumas mensagens não foram enviadas"</string>
|
||||
<string name="error_unknown">"Ocorreu um erro, desculpa"</string>
|
||||
<string name="event_shield_reason_authenticity_not_guaranteed">"A autenticidade desta mensagem cifrada não pode ser garantida neste dispositivo."</string>
|
||||
<string name="event_shield_reason_unknown_device">"Cifragem com origem num dispositivo eliminado ou desconhecido."</string>
|
||||
<string name="event_shield_reason_unsigned_device">"Cifragem com origem num dispositivo não verificado pelo seu dono."</string>
|
||||
<string name="event_shield_reason_unverified_identity">"Cifragem com origem num utilizador não verificado."</string>
|
||||
<string name="invite_friends_rich_title">"🔐️ Junta-te a mim na %1$s"</string>
|
||||
<string name="invite_friends_text">"Alô! Fala comigo na %1$s: %2$s"</string>
|
||||
<string name="login_initial_device_name_android">"%1$s Android"</string>
|
||||
<string name="preference_rageshake">"Agita o dispositivo em fúria para comunicar um problema"</string>
|
||||
<string name="screen_encryption_reset_bullet_1">"Os detalhes da tua conta, contactos, preferências e lista de conversas serão mantidos."</string>
|
||||
<string name="screen_encryption_reset_bullet_2">"Perderás o acesso ao teu histórico de mensagens existente"</string>
|
||||
<string name="screen_encryption_reset_bullet_3">"Necessitarás de verificar todos os teus dispositivos e contactos novamente."</string>
|
||||
<string name="screen_encryption_reset_footer">"Repõe a tua identidade apenas se não tiveres acesso a mais nenhum dispositivo com sessão iniciada e se tiveres perdido a tua chave de recuperação."</string>
|
||||
<string name="screen_encryption_reset_subtitle">"Se não tiveres sessão iniciada em nenhum outro dispositivo e perdeste o acesso à tua chave de recuperação, precisarás de repor a tua identidade para continuares a usar a aplicação. "</string>
|
||||
<string name="screen_encryption_reset_title">"Repõe a tua identidade caso não consigas confirmar de outra forma"</string>
|
||||
<string name="screen_media_picker_error_failed_selection">"Falha ao selecionar multimédia, por favor tente novamente."</string>
|
||||
<string name="screen_media_upload_preview_error_failed_processing">"Falha ao processar multimédia para carregamento, por favor tente novamente."</string>
|
||||
<string name="screen_media_upload_preview_error_failed_sending">"Falhar ao carregar multimédia, por favor tente novamente."</string>
|
||||
<string name="screen_reset_encryption_confirmation_alert_action">"Sim, repor agora"</string>
|
||||
<string name="screen_reset_encryption_confirmation_alert_subtitle">"Este processo é irreversível."</string>
|
||||
<string name="screen_reset_encryption_confirmation_alert_title">"Tens a certeza que pretendes repor a tua cifra?"</string>
|
||||
<string name="screen_reset_encryption_password_placeholder">"Inserir…"</string>
|
||||
<string name="screen_reset_encryption_password_subtitle">"Confirma que pretendes realmente repor a tua cifra."</string>
|
||||
<string name="screen_reset_encryption_password_title">"Insere a tua palavra-passe para continuares"</string>
|
||||
<string name="screen_room_error_failed_processing_media">"Falha ao processar multimédia para carregamento, por favor tente novamente."</string>
|
||||
<string name="screen_room_error_failed_retrieving_user_details">"Não foi possível obter os detalhes de utilizador."</string>
|
||||
<string name="screen_room_member_details_block_alert_action">"Bloquear"</string>
|
||||
|
|
@ -271,6 +291,9 @@ Razão: %1$s."</string>
|
|||
<string name="screen_room_member_details_unblock_alert_action">"Desbloquear"</string>
|
||||
<string name="screen_room_member_details_unblock_alert_description">"Poderás voltar a ver todas as suas mensagens."</string>
|
||||
<string name="screen_room_member_details_unblock_user">"Desbloquear utilizador"</string>
|
||||
<string name="screen_room_pinned_banner_indicator">"%1$s de %2$s"</string>
|
||||
<string name="screen_room_pinned_banner_indicator_description">"%1$s mensagens afixadas"</string>
|
||||
<string name="screen_room_pinned_banner_view_all_button_title">"Ver todas"</string>
|
||||
<string name="screen_room_title">"Conversa"</string>
|
||||
<string name="screen_share_location_title">"Partilhar localização"</string>
|
||||
<string name="screen_share_my_location_action">"Partilhar a minha localização"</string>
|
||||
|
|
|
|||
|
|
@ -93,6 +93,7 @@
|
|||
<string name="action_report_bug">"Сообщить об ошибке"</string>
|
||||
<string name="action_report_content">"Пожаловаться на содержание"</string>
|
||||
<string name="action_reset">"Сбросить"</string>
|
||||
<string name="action_reset_identity">"Сбросить идентификацию"</string>
|
||||
<string name="action_retry">"Повторить"</string>
|
||||
<string name="action_retry_decryption">"Повторите расшифровку"</string>
|
||||
<string name="action_save">"Сохранить"</string>
|
||||
|
|
@ -272,9 +273,21 @@
|
|||
<string name="invite_friends_text">"Привет, поговори со мной по %1$s: %2$s"</string>
|
||||
<string name="login_initial_device_name_android">"%1$s Android"</string>
|
||||
<string name="preference_rageshake">"Встряхните устройство, чтобы сообщить об ошибке"</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_subtitle">"Если вы не вошли в систему на других устройствах и потеряли ключ восстановления, вам необходимо сбросить учетные данные, чтобы продолжить использование приложения. "</string>
|
||||
<string name="screen_encryption_reset_title">"Сбросьте ключи подтверждения, если вы не можете подтвердить свою личность другим способом."</string>
|
||||
<string name="screen_media_picker_error_failed_selection">"Не удалось выбрать носитель, попробуйте еще раз."</string>
|
||||
<string name="screen_media_upload_preview_error_failed_processing">"Не удалось обработать медиафайл для загрузки, попробуйте еще раз."</string>
|
||||
<string name="screen_media_upload_preview_error_failed_sending">"Не удалось загрузить медиафайлы, попробуйте еще раз."</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_password_placeholder">"Ввод…"</string>
|
||||
<string name="screen_reset_encryption_password_subtitle">"Подтвердите, что вы хотите сбросить шифрование."</string>
|
||||
<string name="screen_reset_encryption_password_title">"Введите пароль своей учетной записи, чтобы продолжить"</string>
|
||||
<string name="screen_room_error_failed_processing_media">"Не удалось обработать медиафайл для загрузки, попробуйте еще раз."</string>
|
||||
<string name="screen_room_error_failed_retrieving_user_details">"Не удалось получить данные о пользователе"</string>
|
||||
<string name="screen_room_member_details_block_alert_action">"Заблокировать"</string>
|
||||
|
|
|
|||
|
|
@ -93,6 +93,7 @@
|
|||
<string name="action_report_bug">"Nahlásiť chybu"</string>
|
||||
<string name="action_report_content">"Nahlásiť obsah"</string>
|
||||
<string name="action_reset">"Obnoviť"</string>
|
||||
<string name="action_reset_identity">"Obnoviť identitu"</string>
|
||||
<string name="action_retry">"Skúsiť znova"</string>
|
||||
<string name="action_retry_decryption">"Opakovať dešifrovanie"</string>
|
||||
<string name="action_save">"Uložiť"</string>
|
||||
|
|
@ -270,9 +271,21 @@ Dôvod: %1$s."</string>
|
|||
<string name="invite_friends_text">"Ahoj, porozprávajte sa so mnou na %1$s: %2$s"</string>
|
||||
<string name="login_initial_device_name_android">"%1$s Android"</string>
|
||||
<string name="preference_rageshake">"Zúrivo potriasť pre nahlásenie chyby"</string>
|
||||
<string name="screen_encryption_reset_bullet_1">"Údaje o vašom účte, kontakty, predvoľby a zoznam konverzácií budú zachované"</string>
|
||||
<string name="screen_encryption_reset_bullet_2">"Stratíte svoju existujúcu históriu správ"</string>
|
||||
<string name="screen_encryption_reset_bullet_3">"Budete musieť znova overiť všetky existujúce zariadenia a kontakty"</string>
|
||||
<string name="screen_encryption_reset_footer">"Obnovte svoju totožnosť iba vtedy, ak nemáte prístup k inému prihlásenému zariadeniu a stratili ste kľúč na obnovenie."</string>
|
||||
<string name="screen_encryption_reset_subtitle">"Ak nie ste prihlásení do žiadneho iného zariadenia a stratili ste kľúč na obnovenie, budete musieť znovu obnoviť svoju identitu, aby ste mohli pokračovať v používaní aplikácie. "</string>
|
||||
<string name="screen_encryption_reset_title">"Znovu nastavte svoju totožnosť v prípade, že ju nemôžete potvrdiť iným spôsobom"</string>
|
||||
<string name="screen_media_picker_error_failed_selection">"Nepodarilo sa vybrať médium, skúste to prosím znova."</string>
|
||||
<string name="screen_media_upload_preview_error_failed_processing">"Nepodarilo sa spracovať médiá na odoslanie, skúste to prosím znova."</string>
|
||||
<string name="screen_media_upload_preview_error_failed_sending">"Nepodarilo sa nahrať médiá, skúste to prosím znova."</string>
|
||||
<string name="screen_reset_encryption_confirmation_alert_action">"Áno, znovu nastaviť teraz"</string>
|
||||
<string name="screen_reset_encryption_confirmation_alert_subtitle">"Tento proces je nezvratný."</string>
|
||||
<string name="screen_reset_encryption_confirmation_alert_title">"Naozaj chcete obnoviť svoje šifrovanie?"</string>
|
||||
<string name="screen_reset_encryption_password_placeholder">"Zadajte…"</string>
|
||||
<string name="screen_reset_encryption_password_subtitle">"Potvrďte, že chcete obnoviť svoje šifrovanie."</string>
|
||||
<string name="screen_reset_encryption_password_title">"Ak chcete pokračovať, zadajte heslo účtu"</string>
|
||||
<string name="screen_room_error_failed_processing_media">"Nepodarilo sa spracovať médiá na odoslanie, skúste to prosím znova."</string>
|
||||
<string name="screen_room_error_failed_retrieving_user_details">"Nepodarilo sa získať údaje o používateľovi"</string>
|
||||
<string name="screen_room_member_details_block_alert_action">"Zablokovať"</string>
|
||||
|
|
|
|||
|
|
@ -91,6 +91,7 @@
|
|||
<string name="action_report_bug">"Report bug"</string>
|
||||
<string name="action_report_content">"Report content"</string>
|
||||
<string name="action_reset">"Reset"</string>
|
||||
<string name="action_reset_identity">"Reset identity"</string>
|
||||
<string name="action_retry">"Retry"</string>
|
||||
<string name="action_retry_decryption">"Retry decryption"</string>
|
||||
<string name="action_save">"Save"</string>
|
||||
|
|
@ -266,9 +267,21 @@ Reason: %1$s."</string>
|
|||
<string name="invite_friends_text">"Hey, talk to me on %1$s: %2$s"</string>
|
||||
<string name="login_initial_device_name_android">"%1$s Android"</string>
|
||||
<string name="preference_rageshake">"Rageshake to report bug"</string>
|
||||
<string name="screen_encryption_reset_bullet_1">"Your account details, contacts, preferences, and chat list will be kept"</string>
|
||||
<string name="screen_encryption_reset_bullet_2">"You will lose your existing message history"</string>
|
||||
<string name="screen_encryption_reset_bullet_3">"You will need to verify all your existing devices and contacts again"</string>
|
||||
<string name="screen_encryption_reset_footer">"Only reset your identity if you don’t have access to another signed-in device and you’ve lost your recovery key."</string>
|
||||
<string name="screen_encryption_reset_subtitle">"If you’re not signed in to any other devices and you’ve lost your recovery key, then you’ll need to reset your identity to continue using the app. "</string>
|
||||
<string name="screen_encryption_reset_title">"Reset your identity in case you can’t confirm another way"</string>
|
||||
<string name="screen_media_picker_error_failed_selection">"Failed selecting media, please try again."</string>
|
||||
<string name="screen_media_upload_preview_error_failed_processing">"Failed processing media to upload, please try again."</string>
|
||||
<string name="screen_media_upload_preview_error_failed_sending">"Failed uploading media, please try again."</string>
|
||||
<string name="screen_reset_encryption_confirmation_alert_action">"Yes, reset now"</string>
|
||||
<string name="screen_reset_encryption_confirmation_alert_subtitle">"This process is irreversible."</string>
|
||||
<string name="screen_reset_encryption_confirmation_alert_title">"Are you sure you want to reset your encryption?"</string>
|
||||
<string name="screen_reset_encryption_password_placeholder">"Enter…"</string>
|
||||
<string name="screen_reset_encryption_password_subtitle">"Confirm that you want to reset your encryption."</string>
|
||||
<string name="screen_reset_encryption_password_title">"Enter your account password to continue"</string>
|
||||
<string name="screen_room_error_failed_processing_media">"Failed processing media to upload, please try again."</string>
|
||||
<string name="screen_room_error_failed_retrieving_user_details">"Could not retrieve user details"</string>
|
||||
<string name="screen_room_member_details_block_alert_action">"Block"</string>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue