diff --git a/app/src/main/java/com/nextcloud/talk/chat/data/network/OfflineFirstChatRepository.kt b/app/src/main/java/com/nextcloud/talk/chat/data/network/OfflineFirstChatRepository.kt index b72ff8968a1..9569d65d49e 100644 --- a/app/src/main/java/com/nextcloud/talk/chat/data/network/OfflineFirstChatRepository.kt +++ b/app/src/main/java/com/nextcloud/talk/chat/data/network/OfflineFirstChatRepository.kt @@ -367,6 +367,11 @@ class OfflineFirstChatRepository @Inject constructor( while (true) { delay(INSURANCE_REQUEST_DELAY) + if (itIsPaused) { + // ChatViewModel.onResume fetches right away when the chat comes back to the foreground + Log.d(TAG, "skip insurance request while paused") + continue + } Log.d(TAG, "execute insurance request") fetchNewMessages() diff --git a/app/src/test/java/com/nextcloud/talk/chat/data/network/OfflineFirstChatRepositoryTest.kt b/app/src/test/java/com/nextcloud/talk/chat/data/network/OfflineFirstChatRepositoryTest.kt index 1496841e6a3..e9078eb57e5 100644 --- a/app/src/test/java/com/nextcloud/talk/chat/data/network/OfflineFirstChatRepositoryTest.kt +++ b/app/src/test/java/com/nextcloud/talk/chat/data/network/OfflineFirstChatRepositoryTest.kt @@ -43,6 +43,8 @@ import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking import kotlinx.coroutines.flow.toList +import kotlinx.coroutines.test.advanceTimeBy +import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import kotlinx.coroutines.withTimeout import okhttp3.MediaType.Companion.toMediaType @@ -56,6 +58,7 @@ import org.junit.Test import org.mockito.kotlin.any import org.mockito.kotlin.argumentCaptor import org.mockito.kotlin.atLeastOnce +import org.mockito.kotlin.clearInvocations import org.mockito.kotlin.eq import org.mockito.kotlin.doSuspendableAnswer import org.mockito.kotlin.mock @@ -76,7 +79,7 @@ import java.io.IOException * last read message, otherwise the initial window is re-fetched — anchored at the boundary when * the unread backlog calls for it. */ -@Suppress("TooManyFunctions") +@Suppress("TooManyFunctions", "LargeClass") class OfflineFirstChatRepositoryTest { private val logger: Logger = mock() @@ -245,6 +248,45 @@ class OfflineFirstChatRepositoryTest { assertFalse(fieldMap.containsKey("lastKnownMessageId")) } + @Test + fun `insurance requests are skipped while the chat is paused`() = + runTest { + givenHttpSyncedAnchor() + clearInvocations(network) + repository.handleOnPause() + val polling = launch { repository.initInsuranceRequests() } + + advanceTimeBy(INSURANCE_DELAY_MS * 5 + 1) + runCurrent() + + verifyBlocking(network, never()) { pullChatMessages(any(), any(), any()) } + polling.cancelAndJoin() + } + + @Test + fun `insurance requests resume with the next tick after the chat is resumed`() = + runTest { + givenHttpSyncedAnchor() + clearInvocations(network) + repository.handleOnPause() + val polling = launch { repository.initInsuranceRequests() } + advanceTimeBy(INSURANCE_DELAY_MS * 3 + 1) + runCurrent() + verifyBlocking(network, never()) { pullChatMessages(any(), any(), any()) } + + repository.handleOnResume() + // the loop keeps its normal step: nothing is sent before the next tick ... + advanceTimeBy(INSURANCE_DELAY_MS / 2) + runCurrent() + verifyBlocking(network, never()) { pullChatMessages(any(), any(), any()) } + + // ... and the request is sent on it + advanceTimeBy(INSURANCE_DELAY_MS / 2) + runCurrent() + verifyBlocking(network, times(1)) { pullChatMessages(eq(CREDENTIALS), eq(CHAT_URL), any()) } + polling.cancelAndJoin() + } + @Test fun `fetchNewMessages skips the request when no HTTP-synced anchor exists yet`() = runTest { @@ -862,6 +904,7 @@ class OfflineFirstChatRepositoryTest { private const val LONG_POLLING_OBSERVATION_MILLIS = 200L private const val AWAIT_TIMEOUT_MILLIS = 2000L private const val CHAT_URL = "https://server.example.com/ocs/v2.php/apps/spreed/api/v1/chat/$ROOM_TOKEN" + private const val INSURANCE_DELAY_MS = 2 * 60 * 1000L private const val MESSAGE_ID = 42L private const val SYSTEM_MESSAGE_ID = 43L private const val MESSAGE_URL = "$CHAT_URL/42"