Sliding sync v2 (#775)

* Adopt latest rust Sliding Sync changes

* Bump SDK, converge on similar to configure both sliding sync lists

* Adopt latest SDK version, fix breaking changes

* Fix unit tests
This commit is contained in:
Stefan Ceriu
2023-04-06 18:43:08 +03:00
committed by GitHub
parent f368da3485
commit cabb8e5442
8 changed files with 95 additions and 63 deletions
@@ -111,8 +111,8 @@
"kind" : "remoteSourceControl", "kind" : "remoteSourceControl",
"location" : "https://github.com/matrix-org/matrix-rust-components-swift", "location" : "https://github.com/matrix-org/matrix-rust-components-swift",
"state" : { "state" : {
"revision" : "3d377773dc09104af8a38cf641860aa21f33f2c6", "revision" : "c4185fb641cd5eb312c64b2b70ec2241ade3e309",
"version" : "1.0.51-alpha" "version" : "1.0.53-alpha"
} }
}, },
{ {
@@ -163,7 +163,7 @@
{ {
"identity" : "swift-snapshot-testing", "identity" : "swift-snapshot-testing",
"kind" : "remoteSourceControl", "kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swift-snapshot-testing.git", "location" : "https://github.com/pointfreeco/swift-snapshot-testing",
"state" : { "state" : {
"revision" : "cef5b3f6f11781dd4591bdd1dd0a3d22bd609334", "revision" : "cef5b3f6f11781dd4591bdd1dd0a3d22bd609334",
"version" : "1.11.0" "version" : "1.11.0"
@@ -268,8 +268,9 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol
} }
private func updateVisibleRange(_ range: Range<Int>, timelineLimit: UInt) { private func updateVisibleRange(_ range: Range<Int>, timelineLimit: UInt) {
guard visibleRoomsSummaryProvider?.statePublisher.value == .fullyLoaded, guard !range.isEmpty else {
!range.isEmpty else { return } return
}
guard let visibleRoomsSummaryProvider else { guard let visibleRoomsSummaryProvider else {
MXLog.error("Visible rooms summary provider unavailable") MXLog.error("Visible rooms summary provider unavailable")
@@ -299,25 +299,20 @@ class ClientProxy: ClientProxyProtocol {
do { do {
let slidingSyncBuilder = client.slidingSync() let slidingSyncBuilder = client.slidingSync()
// Build the visibleRoomsSlidingSyncView here so that it can take advantage of the SS builder cold cache
// We will still register the allRoomsSlidingSyncView later, and than will have no cache
let visibleRoomsView = try SlidingSyncListBuilder()
.timelineLimit(limit: UInt32(SlidingSyncConstants.initialTimelineLimit)) // Starts off with zero to quickly load rooms, then goes to 1 while scrolling to quickly load last messages and 20 when the scrolling stops to load room history
.requiredState(requiredState: slidingSyncRequiredState)
.filters(filters: slidingSyncFilters)
.name(name: "CurrentlyVisibleRooms")
.syncMode(mode: .selective)
.addRange(from: 0, to: 20)
.sendUpdatesForItems(enable: true)
.build()
// List observers need to be setup before calling build() on the SlidingSyncBuilder otherwise // List observers need to be setup before calling build() on the SlidingSyncBuilder otherwise
// cold cache state and count updates will be lost // cold cache state and count updates will be lost
buildAndConfigureVisibleRoomsSlidingSyncView(visibleRoomsView: visibleRoomsView) buildAndConfigureVisibleRoomsSlidingSyncView()
buildAndConfigureAllRoomsSlidingSyncView() buildAndConfigureAllRoomsSlidingSyncView()
guard let visibleRoomsSlidingSyncView else {
MXLog.error("Visible rooms sliding sync view unavailable")
return
}
// Add the visibleRoomsSlidingSyncView here so that it can take advantage of the SS builder cold cache
// We will still register the allRoomsSlidingSyncView later, and than will have no cache
let slidingSync = try slidingSyncBuilder let slidingSync = try slidingSyncBuilder
.addList(v: visibleRoomsView) .addList(v: visibleRoomsSlidingSyncView)
.withCommonExtensions() .withCommonExtensions()
.coldCache(name: "ElementX") .coldCache(name: "ElementX")
.build() .build()
@@ -334,28 +329,48 @@ class ClientProxy: ClientProxyProtocol {
} }
} }
private func buildAndConfigureVisibleRoomsSlidingSyncView(visibleRoomsView: SlidingSyncList) { private func buildAndConfigureVisibleRoomsSlidingSyncView() {
let visibleRoomsViewProxy = SlidingSyncViewProxy(slidingSyncView: visibleRoomsView) guard visibleRoomsSlidingSyncView == nil else {
fatalError("This shouldn't be called more than once")
visibleRoomsSummaryProvider = RoomSummaryProvider(slidingSyncViewProxy: visibleRoomsViewProxy,
eventStringBuilder: RoomEventStringBuilder(stateEventStringBuilder: RoomStateEventStringBuilder(userID: userID)))
visibleRoomsSlidingSyncView = visibleRoomsView
// Changes to the visibleRoomsSlidingSyncView range need to restart the connection to be applied
visibleRoomsViewProxy.visibleRangeUpdatePublisher.sink { [weak self] in
self?.restartSync()
}
.store(in: &cancellables)
// The allRoomsSlidingSyncView will be registered as soon as the visibleRoomsSlidingSyncView receives its first update
visibleRoomsViewProxyStateObservationToken = visibleRoomsViewProxy.diffPublisher.sink { [weak self] _ in
MXLog.info("Visible rooms view received first update, configuring views post initial sync")
self?.configureViewsPostInitialSync()
self?.visibleRoomsViewProxyStateObservationToken = nil
} }
self.visibleRoomsViewProxy = visibleRoomsViewProxy do {
let visibleRoomsSlidingSyncView = try SlidingSyncListBuilder()
.timelineLimit(limit: UInt32(SlidingSyncConstants.initialTimelineLimit)) // Starts off with zero to quickly load rooms, then goes to 1 while scrolling to quickly load last messages and 20 when the scrolling stops to load room history
.requiredState(requiredState: slidingSyncRequiredState)
.filters(filters: slidingSyncFilters)
.name(name: "CurrentlyVisibleRooms")
.syncMode(mode: .selective)
.addRange(from: 0, to: 20)
.build()
let visibleRoomsViewProxy = SlidingSyncViewProxy(slidingSyncView: visibleRoomsSlidingSyncView, name: "Visible rooms")
visibleRoomsSummaryProvider = RoomSummaryProvider(slidingSyncViewProxy: visibleRoomsViewProxy,
eventStringBuilder: RoomEventStringBuilder(stateEventStringBuilder: RoomStateEventStringBuilder(userID: userID)))
self.visibleRoomsSlidingSyncView = visibleRoomsSlidingSyncView
self.visibleRoomsViewProxy = visibleRoomsViewProxy
// Changes to the visibleRoomsSlidingSyncView range need to restart the connection to be applied
visibleRoomsViewProxy.visibleRangeUpdatePublisher.sink { [weak self] in
self?.restartSync()
}
.store(in: &cancellables)
// The allRoomsSlidingSyncView will be registered as soon as the visibleRoomsSlidingSyncView receives its first update
visibleRoomsViewProxyStateObservationToken = visibleRoomsViewProxy.statePublisher.sink { [weak self] state in
guard state == .fullyLoaded else {
return
}
MXLog.info("Visible rooms view received first update, configuring views post initial sync")
self?.configureViewsPostInitialSync()
self?.visibleRoomsViewProxyStateObservationToken = nil
}
} catch {
MXLog.error("Failed building the visible rooms sliding sync view with error: \(error)")
}
} }
private func buildAndConfigureAllRoomsSlidingSyncView() { private func buildAndConfigureAllRoomsSlidingSyncView() {
@@ -364,23 +379,21 @@ class ClientProxy: ClientProxyProtocol {
} }
do { do {
let allRoomsView = try SlidingSyncListBuilder() let allRoomsSlidingSyncView = try SlidingSyncListBuilder()
.noTimelineLimit() .noTimelineLimit()
.requiredState(requiredState: slidingSyncRequiredState) .requiredState(requiredState: slidingSyncRequiredState)
.filters(filters: slidingSyncFilters) .filters(filters: slidingSyncFilters)
.name(name: "AllRooms") .name(name: "AllRooms")
.syncMode(mode: .growingFullSync) .syncMode(mode: .growing)
.batchSize(batchSize: 100) .batchSize(batchSize: 100)
.sendUpdatesForItems(enable: true)
.build() .build()
let allRoomsViewProxy = SlidingSyncViewProxy(slidingSyncView: allRoomsView) let allRoomsViewProxy = SlidingSyncViewProxy(slidingSyncView: allRoomsSlidingSyncView, name: "All rooms")
allRoomsSummaryProvider = RoomSummaryProvider(slidingSyncViewProxy: allRoomsViewProxy, allRoomsSummaryProvider = RoomSummaryProvider(slidingSyncViewProxy: allRoomsViewProxy,
eventStringBuilder: RoomEventStringBuilder(stateEventStringBuilder: RoomStateEventStringBuilder(userID: userID))) eventStringBuilder: RoomEventStringBuilder(stateEventStringBuilder: RoomStateEventStringBuilder(userID: userID)))
allRoomsSlidingSyncView = allRoomsView self.allRoomsSlidingSyncView = allRoomsSlidingSyncView
self.allRoomsViewProxy = allRoomsViewProxy self.allRoomsViewProxy = allRoomsViewProxy
} catch { } catch {
@@ -27,25 +27,31 @@ private class SlidingSyncViewObserver: SlidingSyncListRoomListObserver, SlidingS
/// Publishes the number of available rooms /// Publishes the number of available rooms
let countUpdatePublisher = CurrentValueSubject<UInt, Never>(0) let countUpdatePublisher = CurrentValueSubject<UInt, Never>(0)
private let name: String
init(name: String) {
self.name = name
}
// MARK: - SlidingSyncListRoomListObserver // MARK: - SlidingSyncListRoomListObserver
func didReceiveUpdate(diff: SlidingSyncListRoomsListDiff) { func didReceiveUpdate(diff: SlidingSyncListRoomsListDiff) {
MXLog.verbose("Received room diff") MXLog.verbose("\(name): Received room diff")
roomListDiffPublisher.send(diff) roomListDiffPublisher.send(diff)
} }
// MARK: - SlidingSyncListStateObserver // MARK: - SlidingSyncListStateObserver
func didReceiveUpdate(newState: SlidingSyncState) { func didReceiveUpdate(newState: SlidingSyncState) {
MXLog.info("Updated state: \(newState)") MXLog.info("\(name): Updated state: \(newState)")
stateUpdatePublisher.send(newState) stateUpdatePublisher.send(newState)
} }
// MARK: - SlidingSyncListRoomsCountObserver // MARK: - SlidingSyncListRoomsCountObserver
func didReceiveUpdate(count: UInt32) { func didReceiveUpdate(count: UInt32) {
MXLog.info("Updated room count: \(count)") MXLog.info("\(name): Updated room count: \(count)")
countUpdatePublisher.send(UInt(count)) countUpdatePublisher.send(UInt(count))
} }
} }
@@ -71,10 +77,10 @@ class SlidingSyncViewProxy {
countUpdateObserverToken?.cancel() countUpdateObserverToken?.cancel()
} }
init(slidingSyncView: SlidingSyncListProtocol) { init(slidingSyncView: SlidingSyncListProtocol, name: String) {
self.slidingSyncView = slidingSyncView self.slidingSyncView = slidingSyncView
let slidingSyncViewObserver = SlidingSyncViewObserver() let slidingSyncViewObserver = SlidingSyncViewObserver(name: name)
slidingSyncViewObserver.stateUpdatePublisher slidingSyncViewObserver.stateUpdatePublisher
.subscribe(statePublisher) .subscribe(statePublisher)
@@ -98,7 +104,7 @@ class SlidingSyncViewProxy {
} }
func currentRoomsList() -> [RoomListEntry] { func currentRoomsList() -> [RoomListEntry] {
slidingSyncView.currentRoomsList() slidingSyncView.currentRoomList()
} }
func roomForIdentifier(_ identifier: String) throws -> SlidingSyncRoomProtocol? { func roomForIdentifier(_ identifier: String) throws -> SlidingSyncRoomProtocol? {
@@ -108,9 +114,13 @@ class SlidingSyncViewProxy {
func updateVisibleRange(_ range: Range<Int>, timelineLimit: UInt) { func updateVisibleRange(_ range: Range<Int>, timelineLimit: UInt) {
MXLog.info("Setting sliding sync view range to \(range), timeline limit: \(timelineLimit)") MXLog.info("Setting sliding sync view range to \(range), timeline limit: \(timelineLimit)")
slidingSyncView.setRange(start: UInt32(range.lowerBound), end: UInt32(range.upperBound)) do {
slidingSyncView.setTimelineLimit(value: UInt32(timelineLimit)) try slidingSyncView.setRange(start: UInt32(range.lowerBound), end: UInt32(range.upperBound))
slidingSyncView.setTimelineLimit(value: UInt32(timelineLimit))
visibleRangeUpdatePublisher.send(())
visibleRangeUpdatePublisher.send(())
} catch {
MXLog.error("Failed setting sliding sync list range with error: \(error)")
}
} }
} }
@@ -42,10 +42,6 @@ struct MessageTimelineItem<Content: MessageContentProtocol> {
item.content().asMessage()?.isEdited() == true item.content().asMessage()?.isEdited() == true
} }
var inReplyTo: String? {
item.content().asMessage()?.inReplyTo()
}
var sender: String { var sender: String {
item.sender() item.sender()
} }
@@ -116,7 +116,19 @@ struct EventTimelineItemProxy: CustomDebugStringConvertible {
// MARK: - CustomDebugStringConvertible // MARK: - CustomDebugStringConvertible
var debugDescription: String { var debugDescription: String {
item.fmtDebug() let debugInfo = item.debugInfo()
var debugDescription = debugInfo.model
if let originalJson = debugInfo.originalJson {
debugDescription += "\n\n\(originalJson)"
}
if let latestEditJson = debugInfo.latestEditJson {
debugDescription += "\n\n\(latestEditJson)"
}
return debugDescription
} }
} }
@@ -141,7 +141,7 @@ private struct MockEventTimelineItem: EventTimelineItemProtocol {
func eventId() -> String? { UUID().uuidString } func eventId() -> String? { UUID().uuidString }
func fmtDebug() -> String { "MockEvent" } func debugInfo() -> MatrixRustSDK.EventTimelineItemDebugInfo { .init(model: "MockEvent", originalJson: nil, latestEditJson: nil) }
func isEditable() -> Bool { false } func isEditable() -> Bool { false }
@@ -159,7 +159,7 @@ private struct MockEventTimelineItem: EventTimelineItemProtocol {
func sender() -> String { "@user:server.com" } func sender() -> String { "@user:server.com" }
func senderProfile() -> MatrixRustSDK.ProfileTimelineDetails { .unavailable } func senderProfile() -> MatrixRustSDK.ProfileDetails { .unavailable }
func timestamp() -> UInt64 { 0 } func timestamp() -> UInt64 { 0 }
+1 -1
View File
@@ -42,7 +42,7 @@ include:
packages: packages:
MatrixRustSDK: MatrixRustSDK:
url: https://github.com/matrix-org/matrix-rust-components-swift url: https://github.com/matrix-org/matrix-rust-components-swift
exactVersion: 1.0.51-alpha exactVersion: 1.0.53-alpha
# path: ../matrix-rust-sdk # path: ../matrix-rust-sdk
DesignKit: DesignKit:
path: DesignKit path: DesignKit