Skip to content

Commit

Permalink
Update sort order in the SDK without recreating duplicate room lists
Browse files Browse the repository at this point in the history
Change-Id: Ieffbfc5199d8c9c2d06d32b52993497f17aac339
  • Loading branch information
SpiritCroc committed Oct 3, 2024
1 parent 929f529 commit c48cab9
Show file tree
Hide file tree
Showing 21 changed files with 141 additions and 129 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class ElementXApplication : Application(), DaggerComponentOwner {
initializeComponent(CrashInitializer::class.java)
initializeComponent(TracingInitializer::class.java)
initializeComponent(CacheCleanerInitializer::class.java)
initializeComponent(ScInitializer::class.java) // SC
}
EmojiCompat.init(BundledEmojiCompatConfig(this)) // SC
logApplicationInfo(this)
Expand Down
2 changes: 0 additions & 2 deletions app/src/main/kotlin/io/element/android/x/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalUriHandler
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
Expand Down Expand Up @@ -68,7 +67,6 @@ class MainActivity : NodeActivity() {
LocalUriHandler provides SafeUriHandler(this),
LocalAnalyticsService provides appBindings.analyticsService(),
) {
LaunchedEffect(Unit) { appBindings.scPreferencesStore().prefetch() }
Box(
modifier = Modifier
.fillMaxSize()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package io.element.android.x

import android.content.Context
import androidx.startup.Initializer
import io.element.android.libraries.architecture.bindings
import io.element.android.x.di.AppBindings
import kotlinx.coroutines.runBlocking
import timber.log.Timber

class ScInitializer : Initializer<Unit> {
override fun create(context: Context) {
val ts = System.currentTimeMillis()
val appBindings = context.bindings<AppBindings>()
// runBlocking is not nice, but we want to make sure that preferences are ready before creating room list service
runBlocking {
appBindings.scPreferencesStore().prefetch()
}
Timber.d("Initialized SC dependencies in ${System.currentTimeMillis() - ts} ms")
}

override fun dependencies(): List<Class<out Initializer<*>>> = emptyList()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package chat.schildi.features.roomlist

import chat.schildi.lib.preferences.ScPreferencesStore
import chat.schildi.lib.preferences.ScPrefs
import io.element.android.libraries.matrix.api.roomlist.RoomListService
import io.element.android.libraries.matrix.api.roomlist.ScSdkInboxSettings
import io.element.android.libraries.matrix.api.roomlist.ScSdkRoomSortOrder
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import javax.inject.Inject

class ScInboxSettingsSource @Inject constructor(
private val scPreferencesStore: ScPreferencesStore,
private val roomListService: RoomListService,
) {
fun launchIn(scope: CoroutineScope) {
scPreferencesStore.combinedSettingFlow { lookup ->
ScSdkInboxSettings(
sortOrder = ScSdkRoomSortOrder(
byUnread = ScPrefs.SORT_BY_UNREAD.let { it.ensureType(lookup(it)) ?: it.defaultValue },
pinFavourites = ScPrefs.PIN_FAVORITES.let { it.ensureType(lookup(it)) ?: it.defaultValue },
buryLowPriority = ScPrefs.BURY_LOW_PRIORITY.let { it.ensureType(lookup(it)) ?: it.defaultValue },
clientSideUnreadCounts = ScPrefs.CLIENT_GENERATED_UNREAD_COUNTS.let { it.ensureType(lookup(it)) ?: it.defaultValue },
withSilentUnread = ScPrefs.SORT_WITH_SILENT_UNREAD.let { it.ensureType(lookup(it)) ?: it.defaultValue },
)
)
}.onEach { inboxSettings ->
roomListService.allRooms.updateSettings(inboxSettings)
}.launchIn(scope)
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

package io.element.android.features.roomlist.impl.datasource

import chat.schildi.features.roomlist.ScRoomSortOrderSource
import chat.schildi.features.roomlist.ScInboxSettingsSource
import io.element.android.features.roomlist.impl.model.RoomListRoomSummary
import io.element.android.libraries.androidutils.diff.DiffCacheUpdater
import io.element.android.libraries.androidutils.diff.MutableListDiffCache
Expand Down Expand Up @@ -36,7 +36,7 @@ class RoomListDataSource @Inject constructor(
private val roomListRoomSummaryFactory: RoomListRoomSummaryFactory,
private val coroutineDispatchers: CoroutineDispatchers,
private val notificationSettingsService: NotificationSettingsService,
private val scRoomSortOrderSource: ScRoomSortOrderSource,
private val scInboxSettingsSource: ScInboxSettingsSource,
private val appScope: CoroutineScope,
) {
init {
Expand All @@ -56,12 +56,10 @@ class RoomListDataSource @Inject constructor(
val loadingState = roomListService.allRooms.loadingState

fun launchIn(coroutineScope: CoroutineScope) {
/*
scInboxSettingsSource.launchIn(coroutineScope)
roomListService
.allRooms
.filteredSummaries
*/
scRoomSortOrderSource.filteredSummaries()
.onEach { roomSummaries ->
replaceWith(roomSummaries)
}
Expand All @@ -78,7 +76,6 @@ class RoomListDataSource @Inject constructor(
.debounce(0.5.seconds)
.onEach {
roomListService.allRooms.rebuildSummaries()
roomListService.sortedRooms.rebuildSummaries()
}
.launchIn(appScope)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,7 @@ class RoomListFiltersPresenter @Inject constructor(
}
.collect { filters ->
val result = MatrixRoomListFilter.All(filters)
//roomListService.allRooms.updateFilter(result)
roomListService.sortedRooms.updateFilter(result)
roomListService.allRooms.updateFilter(result)
}
}

Expand Down
2 changes: 1 addition & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ jsoup = "org.jsoup:jsoup:1.18.1"
appyx_core = { module = "com.bumble.appyx:core", version.ref = "appyx" }
molecule-runtime = "app.cash.molecule:molecule-runtime:2.0.0"
timber = "com.jakewharton.timber:timber:5.0.1"
matrix_sdk = "chat.schildi.rustcomponents:sdk-android:0.2.32"
matrix_sdk = "chat.schildi.rustcomponents:sdk-android:0.2.33"
matrix_richtexteditor = { module = "chat.schildi:wysiwyg", version.ref = "wysiwyg" }
matrix_richtexteditor_compose = { module = "chat.schildi:wysiwyg-compose", version.ref = "wysiwyg" }
sqldelight-driver-android = { module = "app.cash.sqldelight:android-driver", version.ref = "sqldelight" }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ interface DynamicRoomList : RoomList {
* @param filter the filter to apply.
*/
suspend fun updateFilter(filter: RoomListFilter)

suspend fun updateSettings(settings: ScSdkInboxSettings)
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,6 @@ interface RoomListService {
source: RoomList.Source,
): DynamicRoomList

fun getOrReplaceRoomListWithSortOrder(
pageSize: Int,
initialFilter: RoomListFilter,
sortOrder: ScRoomSortOrder = ScRoomSortOrder(),
): DynamicRoomList

/**
* Subscribes to sync requests for the visible rooms.
* @param roomIds the list of visible room ids to subscribe to.
Expand All @@ -63,12 +57,6 @@ interface RoomListService {
*/
val allRooms: DynamicRoomList

/**
* SC: don't use allRooms, sorted rooms unfortunately needs recreation when changing sort order which could break some flows,
* so only use it if we're sure we cover that
*/
val sortedRooms: DynamicRoomList

/**
* Root spaces.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package io.element.android.libraries.matrix.api.roomlist

data class ScSdkInboxSettings(
val sortOrder: ScSdkRoomSortOrder = ScSdkRoomSortOrder(),
)

data class ScRoomSortOrder(
data class ScSdkRoomSortOrder(
val byUnread: Boolean = false,
val pinFavourites: Boolean = false,
val buryLowPriority: Boolean = false,
Expand Down
1 change: 1 addition & 0 deletions libraries/matrix/impl/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ anvil {

dependencies {
implementation(projects.schildi.matrixsdk)
implementation(projects.schildi.lib)
releaseImplementation(libs.matrix.sdk)
if (file("${rootDir.path}/libraries/rustsdk/matrix-rust-sdk.aar").exists()) {
println("\nNote: Using local binary of the Rust SDK.\n")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

package io.element.android.libraries.matrix.impl

import chat.schildi.lib.preferences.ScPreferencesStore
import io.element.android.libraries.androidutils.file.getSizeOfFiles
import io.element.android.libraries.androidutils.file.safeDelete
import io.element.android.libraries.core.bool.orFalse
Expand Down Expand Up @@ -120,6 +121,7 @@ class RustMatrixClient(
private val sessionStore: SessionStore,
private val appCoroutineScope: CoroutineScope,
private val sessionDelegate: RustClientSessionDelegate,
private val scPreferencesStore: ScPreferencesStore,
syncService: ClientSyncService,
dispatchers: CoroutineDispatchers,
baseCacheDirectory: File,
Expand Down Expand Up @@ -168,6 +170,7 @@ class RustMatrixClient(
sessionCoroutineScope = sessionCoroutineScope,
),
roomSyncSubscriber = roomSyncSubscriber,
scPreferencesStore = scPreferencesStore,
)

private val verificationService = RustSessionVerificationService(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

package io.element.android.libraries.matrix.impl

import chat.schildi.lib.preferences.ScPreferencesStore
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
import io.element.android.libraries.di.CacheDirectory
import io.element.android.libraries.featureflag.api.FeatureFlagService
Expand Down Expand Up @@ -40,6 +41,7 @@ class RustMatrixClientFactory @Inject constructor(
private val appCoroutineScope: CoroutineScope,
private val coroutineDispatchers: CoroutineDispatchers,
private val sessionStore: SessionStore,
private val scPreferencesStore: ScPreferencesStore,
private val userAgentProvider: UserAgentProvider,
private val userCertificatesProvider: UserCertificatesProvider,
private val proxyProvider: ProxyProvider,
Expand Down Expand Up @@ -80,6 +82,7 @@ class RustMatrixClientFactory @Inject constructor(
baseCacheDirectory = cacheDirectory,
clock = clock,
timelineEventTypeFilterFactory = timelineEventTypeFilterFactory,
scPreferencesStore = scPreferencesStore,
).also {
Timber.tag(it.toString()).d("Creating Client with access token '$anonymizedAccessToken' and refresh token '$anonymizedRefreshToken'")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@

package io.element.android.libraries.matrix.impl.roomlist

import io.element.android.libraries.matrix.api.roomlist.ScSdkInboxSettings
import org.matrix.rustcomponents.sdk.RoomListEntriesDynamicFilterKind

internal sealed interface RoomListDynamicEvents {
data object Reset : RoomListDynamicEvents
data object LoadMore : RoomListDynamicEvents
data class SetFilter(val filter: RoomListEntriesDynamicFilterKind) : RoomListDynamicEvents
data class SetScInboxSettings(val settings: ScSdkInboxSettings) : RoomListDynamicEvents
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
package io.element.android.libraries.matrix.impl.roomlist

import io.element.android.libraries.core.data.tryOrNull
import io.element.android.libraries.matrix.api.roomlist.ScRoomSortOrder
import io.element.android.libraries.matrix.api.roomlist.ScSdkInboxSettings
import io.element.android.libraries.matrix.impl.util.cancelAndDestroy
import io.element.android.libraries.matrix.impl.util.mxCallbackFlow
import kotlinx.coroutines.channels.Channel
Expand Down Expand Up @@ -59,7 +59,7 @@ internal fun RoomListInterface.entriesFlow(
pageSize: Int,
roomListDynamicEvents: Flow<RoomListDynamicEvents>,
initialFilterKind: RoomListEntriesDynamicFilterKind,
sortOrder: ScRoomSortOrder,
initialInboxSettings: ScSdkInboxSettings? = null,
): Flow<List<RoomListEntriesUpdate>> =
callbackFlow {
val listener = object : RoomListEntriesListener {
Expand All @@ -69,11 +69,19 @@ internal fun RoomListInterface.entriesFlow(
}
val result = entriesWithDynamicAdapters(pageSize.toUInt(), listener)
val controller = result.controller()
controller.setFilter(initialFilterKind)
controller.setSortOrder(sortOrder.toSdkSortOrder())
if (initialInboxSettings == null) {
controller.setFilter(initialFilterKind)
} else {
controller.setScInboxSettings(initialFilterKind, initialInboxSettings.toSdkSettings())
}
var previousScInboxSettings = initialInboxSettings
roomListDynamicEvents.onEach { controllerEvents ->
when (controllerEvents) {
is RoomListDynamicEvents.SetFilter -> {
if (initialInboxSettings != null) {
Timber.e("Setting filter while using SC inbox settings not supported")
return@onEach
}
controller.setFilter(controllerEvents.filter)
}
is RoomListDynamicEvents.LoadMore -> {
Expand All @@ -82,6 +90,20 @@ internal fun RoomListInterface.entriesFlow(
is RoomListDynamicEvents.Reset -> {
controller.resetToOnePage()
}
is RoomListDynamicEvents.SetScInboxSettings -> {
if (initialInboxSettings == null) {
Timber.w("Setting SC inbox settings after initializing without")
}
if (controllerEvents.settings == previousScInboxSettings) {
Timber.i("Ignore inbox settings update without change")
return@onEach
}
previousScInboxSettings = controllerEvents.settings
controller.setScInboxSettings(
initialFilterKind,
controllerEvents.settings.toSdkSettings()
)
}
}
}.launchIn(this)
awaitClose {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ import io.element.android.libraries.matrix.api.roomlist.DynamicRoomList
import io.element.android.libraries.matrix.api.roomlist.RoomList
import io.element.android.libraries.matrix.api.roomlist.RoomListFilter
import io.element.android.libraries.matrix.api.roomlist.RoomSummary
import io.element.android.libraries.matrix.api.roomlist.ScRoomSortOrder
import io.element.android.libraries.matrix.api.roomlist.ScSdkInboxSettings
import io.element.android.libraries.matrix.api.roomlist.ScSdkRoomSortOrder
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
Expand Down Expand Up @@ -42,7 +43,7 @@ internal class RoomListFactory(
coroutineContext: CoroutineContext,
coroutineScope: CoroutineScope = sessionCoroutineScope,
initialFilter: RoomListFilter = RoomListFilter.all(),
sortOrder: ScRoomSortOrder = ScRoomSortOrder(),
initialInboxSettings: ScSdkInboxSettings? = null,
innerProvider: suspend () -> InnerRoomList
): DynamicRoomList {
val loadingStateFlow: MutableStateFlow<RoomList.LoadingState> = MutableStateFlow(RoomList.LoadingState.NotLoaded)
Expand All @@ -62,7 +63,7 @@ internal class RoomListFactory(
pageSize = pageSize,
roomListDynamicEvents = dynamicEvents,
initialFilterKind = RoomListEntriesDynamicFilterKind.NonLeft,
sortOrder = sortOrder,
initialInboxSettings = initialInboxSettings,
).onEach { update ->
processor.postUpdate(update)
}.launchIn(this)
Expand Down Expand Up @@ -117,6 +118,10 @@ private class RustDynamicRoomList(
currentFilter.emit(filter)
}

override suspend fun updateSettings(settings: ScSdkInboxSettings) {
dynamicEvents.emit(RoomListDynamicEvents.SetScInboxSettings(settings))
}

override suspend fun loadMore() {
dynamicEvents.emit(RoomListDynamicEvents.LoadMore)
loadedPages.getAndUpdate { it + 1 }
Expand Down
Loading

0 comments on commit c48cab9

Please sign in to comment.