Merge pull request #906 from vector-im/feature/fga/update-rust-sdk-0.1.34

Feature/fga/update rust sdk 0.1.34
This commit is contained in:
ganfra 2023-07-18 22:52:48 +02:00 committed by GitHub
commit c7d0bbc174
15 changed files with 55 additions and 77 deletions

View file

@ -139,7 +139,9 @@ class LoggedInFlowNode @AssistedInject constructor(
} }
}, },
onResume = { onResume = {
syncService.startSync() lifecycleScope.launch {
syncService.startSync()
}
}, },
onPause = { onPause = {
syncService.stopSync() syncService.stopSync()

View file

@ -139,7 +139,7 @@ class InviteListPresenter @Inject constructor(
private fun CoroutineScope.acceptInvite(roomId: RoomId, acceptedAction: MutableState<Async<RoomId>>) = launch { private fun CoroutineScope.acceptInvite(roomId: RoomId, acceptedAction: MutableState<Async<RoomId>>) = launch {
suspend { suspend {
client.getRoom(roomId)?.use { client.getRoom(roomId)?.use {
it.acceptInvitation().getOrThrow() it.join().getOrThrow()
notificationDrawerManager.clearMembershipNotificationForRoom(client.sessionId, roomId) notificationDrawerManager.clearMembershipNotificationForRoom(client.sessionId, roomId)
analyticsService.capture(it.toAnalyticsJoinedRoom(JoinedRoom.Trigger.Invite)) analyticsService.capture(it.toAnalyticsJoinedRoom(JoinedRoom.Trigger.Invite))
} }
@ -150,7 +150,7 @@ class InviteListPresenter @Inject constructor(
private fun CoroutineScope.declineInvite(roomId: RoomId, declinedAction: MutableState<Async<Unit>>) = launch { private fun CoroutineScope.declineInvite(roomId: RoomId, declinedAction: MutableState<Async<Unit>>) = launch {
suspend { suspend {
client.getRoom(roomId)?.use { client.getRoom(roomId)?.use {
it.rejectInvitation().getOrThrow() it.leave().getOrThrow()
notificationDrawerManager.clearMembershipNotificationForRoom(client.sessionId, roomId) notificationDrawerManager.clearMembershipNotificationForRoom(client.sessionId, roomId)
} }
Unit Unit

View file

@ -211,7 +211,6 @@ class InviteListPresenterTests {
skipItems(2) skipItems(2)
Truth.assertThat(room.isInviteRejected).isTrue()
Truth.assertThat(fakeNotificationDrawerManager.getClearMembershipNotificationForRoomCount(client.sessionId, A_ROOM_ID)).isEqualTo(1) Truth.assertThat(fakeNotificationDrawerManager.getClearMembershipNotificationForRoomCount(client.sessionId, A_ROOM_ID)).isEqualTo(1)
} }
} }
@ -225,7 +224,7 @@ class InviteListPresenterTests {
val room = FakeMatrixRoom() val room = FakeMatrixRoom()
val presenter = createPresenter(client) val presenter = createPresenter(client)
val ex = Throwable("Ruh roh!") val ex = Throwable("Ruh roh!")
room.givenRejectInviteResult(Result.failure(ex)) room.givenLeaveRoomError(ex)
client.givenGetRoomResult(A_ROOM_ID, room) client.givenGetRoomResult(A_ROOM_ID, room)
moleculeFlow(RecompositionClock.Immediate) { moleculeFlow(RecompositionClock.Immediate) {
@ -242,7 +241,6 @@ class InviteListPresenterTests {
val newState = awaitItem() val newState = awaitItem()
Truth.assertThat(room.isInviteRejected).isTrue()
Truth.assertThat(newState.declinedAction).isEqualTo(Async.Failure<Unit>(ex)) Truth.assertThat(newState.declinedAction).isEqualTo(Async.Failure<Unit>(ex))
} }
} }
@ -256,7 +254,7 @@ class InviteListPresenterTests {
val room = FakeMatrixRoom() val room = FakeMatrixRoom()
val presenter = createPresenter(client) val presenter = createPresenter(client)
val ex = Throwable("Ruh roh!") val ex = Throwable("Ruh roh!")
room.givenRejectInviteResult(Result.failure(ex)) room.givenLeaveRoomError(ex)
client.givenGetRoomResult(A_ROOM_ID, room) client.givenGetRoomResult(A_ROOM_ID, room)
moleculeFlow(RecompositionClock.Immediate) { moleculeFlow(RecompositionClock.Immediate) {
@ -298,7 +296,6 @@ class InviteListPresenterTests {
val newState = awaitItem() val newState = awaitItem()
Truth.assertThat(room.isInviteAccepted).isTrue()
Truth.assertThat(newState.acceptedAction).isEqualTo(Async.Success(A_ROOM_ID)) Truth.assertThat(newState.acceptedAction).isEqualTo(Async.Success(A_ROOM_ID))
Truth.assertThat(fakeNotificationDrawerManager.getClearMembershipNotificationForRoomCount(client.sessionId, A_ROOM_ID)).isEqualTo(1) Truth.assertThat(fakeNotificationDrawerManager.getClearMembershipNotificationForRoomCount(client.sessionId, A_ROOM_ID)).isEqualTo(1)
} }
@ -313,7 +310,7 @@ class InviteListPresenterTests {
val room = FakeMatrixRoom() val room = FakeMatrixRoom()
val presenter = createPresenter(client) val presenter = createPresenter(client)
val ex = Throwable("Ruh roh!") val ex = Throwable("Ruh roh!")
room.givenAcceptInviteResult(Result.failure(ex)) room.givenJoinRoomResult(Result.failure(ex))
client.givenGetRoomResult(A_ROOM_ID, room) client.givenGetRoomResult(A_ROOM_ID, room)
moleculeFlow(RecompositionClock.Immediate) { moleculeFlow(RecompositionClock.Immediate) {
@ -322,10 +319,7 @@ class InviteListPresenterTests {
val originalState = awaitItem() val originalState = awaitItem()
originalState.eventSink(InviteListEvents.AcceptInvite(originalState.inviteList[0])) originalState.eventSink(InviteListEvents.AcceptInvite(originalState.inviteList[0]))
val newState = awaitItem() Truth.assertThat(awaitItem().acceptedAction).isEqualTo(Async.Failure<RoomId>(ex))
Truth.assertThat(room.isInviteAccepted).isTrue()
Truth.assertThat(newState.acceptedAction).isEqualTo(Async.Failure<RoomId>(ex))
} }
} }
@ -338,7 +332,7 @@ class InviteListPresenterTests {
val room = FakeMatrixRoom() val room = FakeMatrixRoom()
val presenter = createPresenter(client) val presenter = createPresenter(client)
val ex = Throwable("Ruh roh!") val ex = Throwable("Ruh roh!")
room.givenAcceptInviteResult(Result.failure(ex)) room.givenJoinRoomResult(Result.failure(ex))
client.givenGetRoomResult(A_ROOM_ID, room) client.givenGetRoomResult(A_ROOM_ID, room)
moleculeFlow(RecompositionClock.Immediate) { moleculeFlow(RecompositionClock.Immediate) {

View file

@ -145,7 +145,7 @@ jsoup = { module = "org.jsoup:jsoup", version.ref = "jsoup" }
appyx_core = { module = "com.bumble.appyx:core", version.ref = "appyx" } appyx_core = { module = "com.bumble.appyx:core", version.ref = "appyx" }
molecule-runtime = { module = "app.cash.molecule:molecule-runtime", version.ref = "molecule" } molecule-runtime = { module = "app.cash.molecule:molecule-runtime", version.ref = "molecule" }
timber = "com.jakewharton.timber:timber:5.0.1" timber = "com.jakewharton.timber:timber:5.0.1"
matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.1.31" matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.1.34"
sqldelight-driver-android = { module = "com.squareup.sqldelight:android-driver", version.ref = "sqldelight" } sqldelight-driver-android = { module = "com.squareup.sqldelight:android-driver", version.ref = "sqldelight" }
sqldelight-driver-jvm = { module = "com.squareup.sqldelight:sqlite-driver", version.ref = "sqldelight" } sqldelight-driver-jvm = { module = "com.squareup.sqldelight:sqlite-driver", version.ref = "sqldelight" }
sqldelight-coroutines = { module = "com.squareup.sqldelight:coroutines-extensions", version.ref = "sqldelight" } sqldelight-coroutines = { module = "com.squareup.sqldelight:coroutines-extensions", version.ref = "sqldelight" }

View file

@ -95,9 +95,7 @@ interface MatrixRoom : Closeable {
suspend fun leave(): Result<Unit> suspend fun leave(): Result<Unit>
suspend fun acceptInvitation(): Result<Unit> suspend fun join(): Result<Unit>
suspend fun rejectInvitation(): Result<Unit>
suspend fun inviteUserById(id: UserId): Result<Unit> suspend fun inviteUserById(id: UserId): Result<Unit>

View file

@ -22,7 +22,7 @@ interface SyncService {
/** /**
* Tries to start the sync. If already syncing it has no effect. * Tries to start the sync. If already syncing it has no effect.
*/ */
fun startSync(): Result<Unit> suspend fun startSync(): Result<Unit>
/** /**
* Tries to stop the sync. If service is not syncing it has no effect. * Tries to stop the sync. If service is not syncing it has no effect.

View file

@ -73,10 +73,12 @@ import java.io.File
import org.matrix.rustcomponents.sdk.CreateRoomParameters as RustCreateRoomParameters import org.matrix.rustcomponents.sdk.CreateRoomParameters as RustCreateRoomParameters
import org.matrix.rustcomponents.sdk.RoomPreset as RustRoomPreset import org.matrix.rustcomponents.sdk.RoomPreset as RustRoomPreset
import org.matrix.rustcomponents.sdk.RoomVisibility as RustRoomVisibility import org.matrix.rustcomponents.sdk.RoomVisibility as RustRoomVisibility
import org.matrix.rustcomponents.sdk.SyncService as ClientSyncService
@OptIn(ExperimentalCoroutinesApi::class) @OptIn(ExperimentalCoroutinesApi::class)
class RustMatrixClient constructor( class RustMatrixClient constructor(
private val client: Client, private val client: Client,
private val syncService: ClientSyncService,
private val sessionStore: SessionStore, private val sessionStore: SessionStore,
appCoroutineScope: CoroutineScope, appCoroutineScope: CoroutineScope,
private val dispatchers: CoroutineDispatchers, private val dispatchers: CoroutineDispatchers,
@ -86,14 +88,11 @@ class RustMatrixClient constructor(
) : MatrixClient { ) : MatrixClient {
override val sessionId: UserId = UserId(client.userId()) override val sessionId: UserId = UserId(client.userId())
private val app = client.app().use { builder -> private val roomListService = syncService.roomListService()
builder.finish()
}
private val roomListService = app.roomListService()
private val sessionDispatcher = dispatchers.io.limitedParallelism(64) private val sessionDispatcher = dispatchers.io.limitedParallelism(64)
private val sessionCoroutineScope = appCoroutineScope.childScope(dispatchers.main, "Session-${sessionId}") private val sessionCoroutineScope = appCoroutineScope.childScope(dispatchers.main, "Session-${sessionId}")
private val verificationService = RustSessionVerificationService() private val verificationService = RustSessionVerificationService()
private val syncService = RustSyncService(app, roomListService.stateFlow(), sessionCoroutineScope) private val rustSyncService = RustSyncService(syncService, roomListService.stateFlow(), sessionCoroutineScope)
private val pushersService = RustPushersService( private val pushersService = RustPushersService(
client = client, client = client,
dispatchers = dispatchers, dispatchers = dispatchers,
@ -131,7 +130,7 @@ class RustMatrixClient constructor(
init { init {
client.setDelegate(clientDelegate) client.setDelegate(clientDelegate)
syncService.syncState rustSyncService.syncState
.onEach { syncState -> .onEach { syncState ->
if (syncState == SyncState.Syncing) { if (syncState == SyncState.Syncing) {
onSlidingSyncUpdate() onSlidingSyncUpdate()
@ -247,7 +246,7 @@ class RustMatrixClient constructor(
} }
} }
override fun syncService(): SyncService = syncService override fun syncService(): SyncService = rustSyncService
override fun sessionVerificationService(): SessionVerificationService = verificationService override fun sessionVerificationService(): SessionVerificationService = verificationService
@ -259,7 +258,7 @@ class RustMatrixClient constructor(
sessionCoroutineScope.cancel() sessionCoroutineScope.cancel()
client.setDelegate(null) client.setDelegate(null)
verificationService.destroy() verificationService.destroy()
app.destroy() syncService.destroy()
roomListService.destroy() roomListService.destroy()
notificationClient.destroy() notificationClient.destroy()
client.destroy() client.destroy()

View file

@ -181,9 +181,11 @@ class RustMatrixAuthenticationService @Inject constructor(
*/ */
} }
private fun createMatrixClient(client: Client): MatrixClient { private suspend fun createMatrixClient(client: Client): MatrixClient {
val syncService = client.syncService().finish()
return RustMatrixClient( return RustMatrixClient(
client = client, client = client,
syncService = syncService,
sessionStore = sessionStore, sessionStore = sessionStore,
appCoroutineScope = appCoroutineScope, appCoroutineScope = appCoroutineScope,
dispatchers = coroutineDispatchers, dispatchers = coroutineDispatchers,

View file

@ -43,7 +43,6 @@ import io.element.android.libraries.matrix.impl.timeline.RustMatrixTimeline
import io.element.android.libraries.matrix.impl.timeline.backPaginationStatusFlow import io.element.android.libraries.matrix.impl.timeline.backPaginationStatusFlow
import io.element.android.libraries.matrix.impl.timeline.timelineDiffFlow import io.element.android.libraries.matrix.impl.timeline.timelineDiffFlow
import io.element.android.libraries.sessionstorage.api.SessionData import io.element.android.libraries.sessionstorage.api.SessionData
import io.element.android.libraries.sessionstorage.api.SessionStore
import io.element.android.services.toolbox.api.systemclock.SystemClock import io.element.android.services.toolbox.api.systemclock.SystemClock
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi
@ -82,6 +81,7 @@ class RustMatrixRoom(
// Create a dispatcher for all room methods... // Create a dispatcher for all room methods...
private val roomDispatcher = coroutineDispatchers.io.limitedParallelism(32) private val roomDispatcher = coroutineDispatchers.io.limitedParallelism(32)
//...except getMember methods as it could quickly fill the roomDispatcher... //...except getMember methods as it could quickly fill the roomDispatcher...
private val roomMembersDispatcher = coroutineDispatchers.io.limitedParallelism(8) private val roomMembersDispatcher = coroutineDispatchers.io.limitedParallelism(8)
@ -257,15 +257,9 @@ class RustMatrixRoom(
} }
} }
override suspend fun acceptInvitation(): Result<Unit> = withContext(roomDispatcher) { override suspend fun join(): Result<Unit> = withContext(roomDispatcher) {
runCatching { runCatching {
innerRoom.acceptInvitation() innerRoom.join()
}
}
override suspend fun rejectInvitation(): Result<Unit> = withContext(roomDispatcher) {
runCatching {
innerRoom.rejectInvitation()
} }
} }

View file

@ -17,8 +17,8 @@
package io.element.android.libraries.matrix.impl.sync package io.element.android.libraries.matrix.impl.sync
import io.element.android.libraries.matrix.api.sync.SyncState import io.element.android.libraries.matrix.api.sync.SyncState
import org.matrix.rustcomponents.sdk.AppState
import org.matrix.rustcomponents.sdk.RoomListServiceState import org.matrix.rustcomponents.sdk.RoomListServiceState
import org.matrix.rustcomponents.sdk.SyncServiceState
internal fun RoomListServiceState.toSyncState(): SyncState { internal fun RoomListServiceState.toSyncState(): SyncState {
return when (this) { return when (this) {
@ -30,10 +30,11 @@ internal fun RoomListServiceState.toSyncState(): SyncState {
} }
} }
internal fun AppState.toSyncState(): SyncState { internal fun SyncServiceState.toSyncState(): SyncState {
return when (this) { return when (this) {
AppState.RUNNING -> SyncState.Syncing SyncServiceState.IDLE -> SyncState.Idle
AppState.TERMINATED -> SyncState.Terminated SyncServiceState.RUNNING -> SyncState.Syncing
AppState.ERROR -> SyncState.InError SyncServiceState.TERMINATED -> SyncState.Terminated
SyncServiceState.ERROR -> SyncState.InError
} }
} }

View file

@ -26,24 +26,24 @@ import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.stateIn
import org.matrix.rustcomponents.sdk.App
import org.matrix.rustcomponents.sdk.RoomListServiceState import org.matrix.rustcomponents.sdk.RoomListServiceState
import org.matrix.rustcomponents.sdk.SyncServiceInterface
import timber.log.Timber import timber.log.Timber
class RustSyncService( class RustSyncService(
private val app: App, private val innerSyncService: SyncServiceInterface,
roomListStateFlow: Flow<RoomListServiceState>, roomListStateFlow: Flow<RoomListServiceState>,
sessionCoroutineScope: CoroutineScope sessionCoroutineScope: CoroutineScope
) : SyncService { ) : SyncService {
override fun startSync() = runCatching { override suspend fun startSync() = runCatching {
Timber.v("Start sync") Timber.v("Start sync")
app.start() innerSyncService.start()
} }
override fun stopSync() = runCatching { override fun stopSync() = runCatching {
Timber.v("Stop sync") Timber.v("Stop sync")
app.pause() innerSyncService.pause()
} }
override val syncState: StateFlow<SyncState> = override val syncState: StateFlow<SyncState> =

View file

@ -21,14 +21,14 @@ import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.channels.trySendBlocking import kotlinx.coroutines.channels.trySendBlocking
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.buffer import kotlinx.coroutines.flow.buffer
import org.matrix.rustcomponents.sdk.App import org.matrix.rustcomponents.sdk.SyncService
import org.matrix.rustcomponents.sdk.AppState import org.matrix.rustcomponents.sdk.SyncServiceState
import org.matrix.rustcomponents.sdk.AppStateObserver import org.matrix.rustcomponents.sdk.SyncServiceStateObserver
fun App.stateFlow(): Flow<AppState> = fun SyncService.stateFlow(): Flow<SyncServiceState> =
mxCallbackFlow { mxCallbackFlow {
val listener = object : AppStateObserver { val listener = object : SyncServiceStateObserver {
override fun onUpdate(state: AppState) { override fun onUpdate(state: SyncServiceState) {
trySendBlocking(state) trySendBlocking(state)
} }
} }

View file

@ -63,8 +63,7 @@ class FakeMatrixRoom(
private var userDisplayNameResult = Result.success<String?>(null) private var userDisplayNameResult = Result.success<String?>(null)
private var userAvatarUrlResult = Result.success<String?>(null) private var userAvatarUrlResult = Result.success<String?>(null)
private var updateMembersResult: Result<Unit> = Result.success(Unit) private var updateMembersResult: Result<Unit> = Result.success(Unit)
private var acceptInviteResult = Result.success(Unit) private var joinRoomResult = Result.success(Unit)
private var rejectInviteResult = Result.success(Unit)
private var inviteUserResult = Result.success(Unit) private var inviteUserResult = Result.success(Unit)
private var canInviteResult = Result.success(true) private var canInviteResult = Result.success(true)
private val canSendStateResults = mutableMapOf<StateEventType, Result<Boolean>>() private val canSendStateResults = mutableMapOf<StateEventType, Result<Boolean>>()
@ -101,11 +100,6 @@ class FakeMatrixRoom(
var sendLocationCount: Int = 0 var sendLocationCount: Int = 0
private set private set
var isInviteAccepted: Boolean = false
private set
var isInviteRejected: Boolean = false
private set
var invitedUserId: UserId? = null var invitedUserId: UserId? = null
private set private set
@ -196,16 +190,11 @@ class FakeMatrixRoom(
return Result.success(Unit) return Result.success(Unit)
} }
override suspend fun leave(): Result<Unit> = leaveRoomError?.let { Result.failure(it) } ?: Result.success(Unit) override suspend fun leave(): Result<Unit> =
leaveRoomError?.let { Result.failure(it) } ?: Result.success(Unit)
override suspend fun acceptInvitation(): Result<Unit> { override suspend fun join(): Result<Unit> {
isInviteAccepted = true return joinRoomResult
return acceptInviteResult
}
override suspend fun rejectInvitation(): Result<Unit> {
isInviteRejected = true
return rejectInviteResult
} }
override suspend fun inviteUserById(id: UserId): Result<Unit> = simulateLongTask { override suspend fun inviteUserById(id: UserId): Result<Unit> = simulateLongTask {
@ -316,12 +305,8 @@ class FakeMatrixRoom(
userAvatarUrlResult = avatarUrl userAvatarUrlResult = avatarUrl
} }
fun givenAcceptInviteResult(result: Result<Unit>) { fun givenJoinRoomResult(result: Result<Unit>) {
acceptInviteResult = result joinRoomResult = result
}
fun givenRejectInviteResult(result: Result<Unit>) {
rejectInviteResult = result
} }
fun givenInviteUserResult(result: Result<Unit>) { fun givenInviteUserResult(result: Result<Unit>) {

View file

@ -29,7 +29,7 @@ class FakeSyncService : SyncService {
syncStateFlow.value = SyncState.InError syncStateFlow.value = SyncState.InError
} }
override fun startSync(): Result<Unit> { override suspend fun startSync(): Result<Unit> {
syncStateFlow.value = SyncState.Syncing syncStateFlow.value = SyncState.Syncing
return Result.success(Unit) return Result.success(Unit)
} }

View file

@ -40,6 +40,7 @@ import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.room.RoomMembershipObserver import io.element.android.libraries.matrix.api.room.RoomMembershipObserver
import io.element.android.services.toolbox.impl.strings.AndroidStringProvider import io.element.android.services.toolbox.impl.strings.AndroidStringProvider
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import kotlinx.datetime.Clock import kotlinx.datetime.Clock
import kotlinx.datetime.TimeZone import kotlinx.datetime.TimeZone
@ -103,7 +104,9 @@ class RoomListScreen(
DisposableEffect(Unit) { DisposableEffect(Unit) {
Timber.w("Start sync!") Timber.w("Start sync!")
matrixClient.syncService().startSync() runBlocking {
matrixClient.syncService().startSync()
}
onDispose { onDispose {
Timber.w("Stop sync!") Timber.w("Stop sync!")
matrixClient.syncService().stopSync() matrixClient.syncService().stopSync()