mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-04 01:20:12 +00:00
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:
@@ -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 {
|
||||||
|
|||||||
@@ -28,24 +28,30 @@ 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
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user