Merge branch 'develop' into valere/rtc/voice_call
This commit is contained in:
commit
04a9c677fb
187 changed files with 2612 additions and 2314 deletions
|
|
@ -9,6 +9,7 @@
|
|||
package io.element.android.libraries.matrix.api.media
|
||||
|
||||
import android.os.Parcelable
|
||||
import kotlinx.parcelize.IgnoredOnParcel
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
@Parcelize
|
||||
|
|
@ -16,9 +17,20 @@ data class MediaSource(
|
|||
/**
|
||||
* Url of the media.
|
||||
*/
|
||||
val url: String,
|
||||
private val url: String,
|
||||
/**
|
||||
* This is used to hold data for encrypted media.
|
||||
*/
|
||||
val json: String? = null,
|
||||
) : Parcelable
|
||||
) : Parcelable {
|
||||
/**
|
||||
* A URL with invalid parts (like `#fragment`, if it's an MXC url) removed.
|
||||
*/
|
||||
@IgnoredOnParcel
|
||||
val safeUrl = if (url.startsWith("mxc")) {
|
||||
// We've seen some MXC urls in the wild having some `mxc://foo/bar#auto` fragment suffix, which is invalid
|
||||
url.substringBefore("#")
|
||||
} else {
|
||||
url
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,6 +35,11 @@ interface RoomListService {
|
|||
data object Hide : SyncIndicator
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether the initial sliding sync request is done or not.
|
||||
*/
|
||||
val isInitialSyncDone: Boolean
|
||||
|
||||
/**
|
||||
* Creates a room list that can be used to load more rooms and filter them dynamically.
|
||||
* @param pageSize the number of rooms to load at once.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright (c) 2026 Element Creations Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.matrix.api.media
|
||||
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import io.element.android.libraries.matrix.test.media.aMediaSource
|
||||
import org.junit.Test
|
||||
|
||||
class MediaSourceTest {
|
||||
@Test
|
||||
fun `safeUrl removes the fragment part in MXC urls`() {
|
||||
val mediaSource = aMediaSource(url = "mxc://matrix.org/url#fragment")
|
||||
assertThat(mediaSource.safeUrl).isEqualTo("mxc://matrix.org/url")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `safeUrl keeps the fragment part in a non-MXC url`() {
|
||||
val mediaSource = aMediaSource(url = "https://matrix.org/url#fragment")
|
||||
assertThat(mediaSource.safeUrl).isEqualTo("https://matrix.org/url#fragment")
|
||||
}
|
||||
}
|
||||
|
|
@ -83,7 +83,7 @@ import io.element.android.libraries.matrix.impl.util.SessionPathsProvider
|
|||
import io.element.android.libraries.matrix.impl.util.cancelAndDestroy
|
||||
import io.element.android.libraries.matrix.impl.util.mxCallbackFlow
|
||||
import io.element.android.libraries.matrix.impl.verification.RustSessionVerificationService
|
||||
import io.element.android.libraries.matrix.impl.workmanager.PerformDatabaseVacuumWorkManagerRequest
|
||||
import io.element.android.libraries.matrix.impl.workmanager.PerformDatabaseVacuumRequestBuilder
|
||||
import io.element.android.libraries.sessionstorage.api.SessionStore
|
||||
import io.element.android.libraries.workmanager.api.WorkManagerRequestType
|
||||
import io.element.android.libraries.workmanager.api.WorkManagerScheduler
|
||||
|
|
@ -832,8 +832,8 @@ class RustMatrixClient(
|
|||
if (workManagerScheduler.hasPendingWork(sessionId, WorkManagerRequestType.DB_VACUUM)) return
|
||||
|
||||
Timber.i("Scheduling periodic database vacuuming for session $sessionId")
|
||||
val request = PerformDatabaseVacuumWorkManagerRequest(sessionId)
|
||||
workManagerScheduler.submit(request)
|
||||
val request = PerformDatabaseVacuumRequestBuilder(sessionId)
|
||||
sessionCoroutineScope.launch { workManagerScheduler.submit(request) }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ class RustMediaLoader(
|
|||
return if (json != null) {
|
||||
RustMediaSource.fromJson(json)
|
||||
} else {
|
||||
RustMediaSource.fromUrl(url)
|
||||
RustMediaSource.fromUrl(safeUrl)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import kotlinx.coroutines.flow.stateIn
|
|||
import org.matrix.rustcomponents.sdk.RoomListServiceState
|
||||
import org.matrix.rustcomponents.sdk.RoomListServiceSyncIndicator
|
||||
import timber.log.Timber
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
import org.matrix.rustcomponents.sdk.RoomListService as InnerRustRoomListService
|
||||
|
||||
internal class RustRoomListService(
|
||||
|
|
@ -33,6 +34,9 @@ internal class RustRoomListService(
|
|||
private val roomSyncSubscriber: RoomSyncSubscriber,
|
||||
private val sessionCoroutineScope: CoroutineScope,
|
||||
) : RoomListService {
|
||||
private val _isInitialSyncDone = AtomicBoolean(false)
|
||||
override val isInitialSyncDone: Boolean get() = _isInitialSyncDone.get()
|
||||
|
||||
override fun createRoomList(
|
||||
pageSize: Int,
|
||||
source: RoomList.Source,
|
||||
|
|
@ -75,6 +79,9 @@ internal class RustRoomListService(
|
|||
.map { it.toRoomListState() }
|
||||
.onEach { state ->
|
||||
Timber.d("RoomList state=$state")
|
||||
if (state == RoomListService.State.Running) {
|
||||
_isInitialSyncDone.set(true)
|
||||
}
|
||||
}
|
||||
.distinctUntilChanged()
|
||||
.stateIn(sessionCoroutineScope, SharingStarted.Eagerly, RoomListService.State.Idle)
|
||||
|
|
|
|||
|
|
@ -10,18 +10,18 @@ package io.element.android.libraries.matrix.impl.workmanager
|
|||
import androidx.work.Constraints
|
||||
import androidx.work.Data
|
||||
import androidx.work.PeriodicWorkRequest
|
||||
import androidx.work.WorkRequest
|
||||
import io.element.android.libraries.matrix.api.core.SessionId
|
||||
import io.element.android.libraries.matrix.impl.workmanager.VacuumDatabaseWorker.Companion.SESSION_ID_PARAM
|
||||
import io.element.android.libraries.workmanager.api.WorkManagerRequest
|
||||
import io.element.android.libraries.workmanager.api.WorkManagerRequestBuilder
|
||||
import io.element.android.libraries.workmanager.api.WorkManagerRequestType
|
||||
import io.element.android.libraries.workmanager.api.WorkManagerRequestWrapper
|
||||
import io.element.android.libraries.workmanager.api.workManagerTag
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class PerformDatabaseVacuumWorkManagerRequest(
|
||||
class PerformDatabaseVacuumRequestBuilder(
|
||||
private val sessionId: SessionId,
|
||||
) : WorkManagerRequest {
|
||||
override fun build(): Result<List<WorkRequest>> {
|
||||
) : WorkManagerRequestBuilder {
|
||||
override suspend fun build(): Result<List<WorkManagerRequestWrapper>> {
|
||||
val data = Data.Builder().putString(SESSION_ID_PARAM, sessionId.value).build()
|
||||
val workRequest = PeriodicWorkRequest.Builder(
|
||||
workerClass = VacuumDatabaseWorker::class,
|
||||
|
|
@ -41,6 +41,6 @@ class PerformDatabaseVacuumWorkManagerRequest(
|
|||
)
|
||||
.build()
|
||||
|
||||
return Result.success(listOf(workRequest))
|
||||
return Result.success(listOf(WorkManagerRequestWrapper(workRequest)))
|
||||
}
|
||||
}
|
||||
|
|
@ -19,7 +19,7 @@ import io.element.android.libraries.network.useragent.SimpleUserAgentProvider
|
|||
import io.element.android.libraries.sessionstorage.api.SessionStore
|
||||
import io.element.android.libraries.sessionstorage.test.InMemorySessionStore
|
||||
import io.element.android.libraries.sessionstorage.test.aSessionData
|
||||
import io.element.android.libraries.workmanager.api.WorkManagerRequest
|
||||
import io.element.android.libraries.workmanager.api.WorkManagerRequestBuilder
|
||||
import io.element.android.libraries.workmanager.test.FakeWorkManagerScheduler
|
||||
import io.element.android.services.analytics.test.FakeAnalyticsService
|
||||
import io.element.android.services.toolbox.test.systemclock.FakeSystemClock
|
||||
|
|
@ -33,7 +33,7 @@ import java.io.File
|
|||
class RustMatrixClientFactoryTest {
|
||||
@Test
|
||||
fun test() = runTest {
|
||||
val scheduleVacuumLambda = lambdaRecorder<WorkManagerRequest, Unit> {}
|
||||
val scheduleVacuumLambda = lambdaRecorder<WorkManagerRequestBuilder, Unit> {}
|
||||
val workManagerScheduler = FakeWorkManagerScheduler(submitLambda = scheduleVacuumLambda)
|
||||
val sut = createRustMatrixClientFactory(workManagerScheduler = workManagerScheduler)
|
||||
|
||||
|
|
|
|||
|
|
@ -20,10 +20,14 @@ class FakeRoomListService(
|
|||
private val subscribeToVisibleRoomsLambda: (List<RoomId>) -> Unit = {},
|
||||
private val createRoomListLambda: (pageSize: Int) -> DynamicRoomList = { pageSize -> FakeDynamicRoomList(pageSize = pageSize) },
|
||||
override val allRooms: RoomList = createRoomListLambda(Int.MAX_VALUE),
|
||||
private val isInitialSyncLambda: () -> Boolean = { true },
|
||||
) : RoomListService {
|
||||
private val roomListStateFlow = MutableStateFlow<RoomListService.State>(RoomListService.State.Idle)
|
||||
private val syncIndicatorStateFlow = MutableStateFlow<RoomListService.SyncIndicator>(RoomListService.SyncIndicator.Hide)
|
||||
|
||||
override val isInitialSyncDone: Boolean
|
||||
get() = isInitialSyncLambda()
|
||||
|
||||
suspend fun postState(state: RoomListService.State) {
|
||||
roomListStateFlow.emit(state)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue