mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-03 06:55:59 +00:00
Various sliding sync tweaks (#446)
* Refactor SS configuration and add (unfinished) support for adding views dynamically. * Implement pop and clear support on the room summary provider * Register views against sliding sync * Read invalidated vislbeRoomsSummaryProvider from the allRoomSummaryProvider * Switch SS window range setting from the ScrollViewAdapter to a publisher debounce * Tweak allRoomsView addition: switch from listening the visibleRoomsView's state to when it publishes the first diff update * Cleanup client delegate and sliding sync observers and lifecycle * Bump the RustSDK to 1.0.30-alpha * Reuse startSync within restartSync
This commit is contained in:
@@ -39,7 +39,7 @@ enum HomeScreenViewAction {
|
||||
case userMenu(action: HomeScreenViewUserMenuAction)
|
||||
case verifySession
|
||||
case skipSessionVerification
|
||||
case updatedVisibleItemIdentifiers(Set<String>)
|
||||
case updatedVisibleItemRange(Range<Int>)
|
||||
}
|
||||
|
||||
enum HomeScreenRoomListMode {
|
||||
|
||||
@@ -20,11 +20,17 @@ import SwiftUI
|
||||
typealias HomeScreenViewModelType = StateStoreViewModel<HomeScreenViewState, HomeScreenViewAction>
|
||||
|
||||
class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol {
|
||||
enum Constants {
|
||||
static let slidingWindowBoundsPadding = 5
|
||||
}
|
||||
|
||||
private let userSession: UserSessionProtocol
|
||||
private let visibleRoomsSummaryProvider: RoomSummaryProviderProtocol?
|
||||
private let allRoomsSummaryProvider: RoomSummaryProviderProtocol?
|
||||
private let attributedStringBuilder: AttributedStringBuilderProtocol
|
||||
|
||||
private let visibleItemRangePublisher = CurrentValueSubject<Range<Int>, Never>(0..<0)
|
||||
|
||||
var callback: ((HomeScreenViewModelAction) -> Void)?
|
||||
|
||||
// MARK: - Setup
|
||||
@@ -53,6 +59,14 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
visibleItemRangePublisher
|
||||
.debounce(for: 0.1, scheduler: RunLoop.main)
|
||||
.removeDuplicates()
|
||||
.sink { range in
|
||||
self.updateVisibleRange(range)
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
Task {
|
||||
if case let .success(userAvatarURLString) = await userSession.clientProxy.loadUserAvatarURLString() {
|
||||
if case let .success(avatar) = await userSession.mediaProvider.loadImageFromURLString(userAvatarURLString, avatarSize: .user(on: .home)) {
|
||||
@@ -136,8 +150,8 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol
|
||||
callback?(.presentSessionVerificationScreen)
|
||||
case .skipSessionVerification:
|
||||
state.showSessionVerificationBanner = false
|
||||
case .updatedVisibleItemIdentifiers(let identifiers):
|
||||
updateVisibleRange(visibleItemIdentifiers: identifiers)
|
||||
case .updatedVisibleItemRange(let range):
|
||||
visibleItemRangePublisher.send(range)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -185,7 +199,7 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol
|
||||
|
||||
for (index, summary) in visibleRoomsSummaryProvider.roomListPublisher.value.enumerated() {
|
||||
switch summary {
|
||||
case .empty:
|
||||
case .empty, .invalidated:
|
||||
guard let allRoomsRoomSummary = allRoomsSummaryProvider?.roomListPublisher.value[safe: index] else {
|
||||
rooms.append(HomeScreenRoom.placeholder())
|
||||
continue
|
||||
@@ -201,9 +215,6 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol
|
||||
case .filled(let details):
|
||||
let room = buildRoom(with: details, invalidated: false)
|
||||
rooms.append(room)
|
||||
case .invalidated(let details):
|
||||
let room = buildRoom(with: details, invalidated: true)
|
||||
rooms.append(room)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,19 +240,17 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol
|
||||
avatar: avatarImage)
|
||||
}
|
||||
|
||||
private func updateVisibleRange(visibleItemIdentifiers items: Set<String>) {
|
||||
let result = items.compactMap { itemIdentifier in
|
||||
state.rooms.firstIndex { $0.id == itemIdentifier }
|
||||
}.sorted()
|
||||
private func updateVisibleRange(_ range: Range<Int>) {
|
||||
guard !range.isEmpty else { return }
|
||||
|
||||
guard !result.isEmpty else {
|
||||
guard let visibleRoomsSummaryProvider else {
|
||||
MXLog.error("Visible rooms summary provider unavailable")
|
||||
return
|
||||
}
|
||||
|
||||
guard let lowerBound = result.first, let upperBound = result.last else {
|
||||
return
|
||||
}
|
||||
let lowerBound = max(0, range.lowerBound - Constants.slidingWindowBoundsPadding)
|
||||
let upperBound = min(Int(visibleRoomsSummaryProvider.countPublisher.value), range.upperBound + Constants.slidingWindowBoundsPadding)
|
||||
|
||||
visibleRoomsSummaryProvider?.updateVisibleRange(lowerBound...upperBound)
|
||||
visibleRoomsSummaryProvider.updateVisibleRange(lowerBound..<upperBound)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,12 +17,17 @@
|
||||
import SwiftUI
|
||||
|
||||
struct HomeScreen: View {
|
||||
@State private var showingLogoutConfirmation = false
|
||||
@State private var visibleItemIdentifiers = Set<String>()
|
||||
@State private var scrollViewAdapter = ScrollViewAdapter()
|
||||
|
||||
@ObservedObject var context: HomeScreenViewModel.Context
|
||||
|
||||
@State private var showingLogoutConfirmation = false
|
||||
@State private var visibleItemIdentifiers = Set<String>() {
|
||||
didSet {
|
||||
if visibleItemIdentifiers != oldValue {
|
||||
updateVisibleRange()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
ScrollView {
|
||||
if context.viewState.showSessionVerificationBanner {
|
||||
@@ -62,10 +67,6 @@ struct HomeScreen: View {
|
||||
.disableAutocorrection(true)
|
||||
}
|
||||
}
|
||||
.introspectScrollView { scrollView in
|
||||
guard scrollView != scrollViewAdapter.scrollView else { return }
|
||||
scrollViewAdapter.scrollView = scrollView
|
||||
}
|
||||
.disabled(context.viewState.roomListMode == .skeletons)
|
||||
.animation(.elementDefault, value: context.viewState.showSessionVerificationBanner)
|
||||
.animation(.elementDefault, value: context.viewState.roomListMode)
|
||||
@@ -76,14 +77,6 @@ struct HomeScreen: View {
|
||||
userMenuButton
|
||||
}
|
||||
}
|
||||
.onReceive(scrollViewAdapter.isScrolling) { isScrolling in
|
||||
guard context.viewState.bindings.searchQuery.isEmpty,
|
||||
!isScrolling else {
|
||||
return
|
||||
}
|
||||
|
||||
context.send(viewAction: .updatedVisibleItemIdentifiers(visibleItemIdentifiers))
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
@@ -191,6 +184,22 @@ struct HomeScreen: View {
|
||||
private func signOut() {
|
||||
context.send(viewAction: .userMenu(action: .signOut))
|
||||
}
|
||||
|
||||
private func updateVisibleRange() {
|
||||
let result = visibleItemIdentifiers.compactMap { itemIdentifier in
|
||||
context.viewState.rooms.firstIndex { $0.id == itemIdentifier }
|
||||
}.sorted()
|
||||
|
||||
guard !result.isEmpty else {
|
||||
return
|
||||
}
|
||||
|
||||
guard let firstIndex = result.first, let lastIndex = result.last else {
|
||||
return
|
||||
}
|
||||
|
||||
context.send(viewAction: .updatedVisibleItemRange(firstIndex..<lastIndex))
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Previews
|
||||
|
||||
@@ -46,9 +46,6 @@ private class WeakClientProxyWrapper: ClientDelegate, SlidingSyncObserver {
|
||||
}
|
||||
|
||||
class ClientProxy: ClientProxyProtocol {
|
||||
/// The maximum number of timeline events required during a sync request.
|
||||
static let syncLimit: UInt16 = 50
|
||||
|
||||
private let client: ClientProtocol
|
||||
private let backgroundTaskService: BackgroundTaskServiceProtocol
|
||||
private var sessionVerificationControllerProxy: SessionVerificationControllerProxy?
|
||||
@@ -58,10 +55,15 @@ class ClientProxy: ClientProxyProtocol {
|
||||
private var slidingSyncObserverToken: StoppableSpawn?
|
||||
private var slidingSync: SlidingSync?
|
||||
|
||||
var visibleRoomsSlidingSyncView: SlidingSyncView?
|
||||
var visibleRoomsSummaryProvider: RoomSummaryProviderProtocol?
|
||||
|
||||
var allRoomsSlidingSyncView: SlidingSyncView?
|
||||
var allRoomsSummaryProvider: RoomSummaryProviderProtocol?
|
||||
|
||||
private var cancellables = Set<AnyCancellable>()
|
||||
private var visibleRoomsViewProxyStateObservationToken: AnyCancellable?
|
||||
|
||||
deinit {
|
||||
// These need to be inlined instead of using stopSync()
|
||||
// as we can't call async methods safely from deinit
|
||||
@@ -72,77 +74,16 @@ class ClientProxy: ClientProxyProtocol {
|
||||
|
||||
let callbacks = PassthroughSubject<ClientProxyCallback, Never>()
|
||||
|
||||
// swiftlint:disable:next function_body_length
|
||||
init(client: ClientProtocol,
|
||||
backgroundTaskService: BackgroundTaskServiceProtocol) async {
|
||||
init(client: ClientProtocol, backgroundTaskService: BackgroundTaskServiceProtocol) async {
|
||||
self.client = client
|
||||
self.backgroundTaskService = backgroundTaskService
|
||||
clientQueue = .init(label: "ClientProxyQueue",
|
||||
attributes: .concurrent)
|
||||
mediaProxy = MediaProxy(client: client,
|
||||
clientQueue: clientQueue)
|
||||
clientQueue = .init(label: "ClientProxyQueue", attributes: .concurrent)
|
||||
|
||||
mediaProxy = MediaProxy(client: client, clientQueue: clientQueue)
|
||||
|
||||
await Task.dispatch(on: clientQueue) {
|
||||
do {
|
||||
let slidingSyncBuilder = try client.slidingSync().homeserver(url: ServiceLocator.shared.settings.slidingSyncProxyBaseURLString)
|
||||
|
||||
let requiredState = [RequiredState(key: "m.room.avatar", value: ""),
|
||||
RequiredState(key: "m.room.encryption", value: "")]
|
||||
|
||||
let filters = SlidingSyncRequestListFilters(isDm: nil,
|
||||
spaces: [],
|
||||
isEncrypted: nil,
|
||||
isInvite: false,
|
||||
isTombstoned: false,
|
||||
roomTypes: [],
|
||||
notRoomTypes: ["m.space"],
|
||||
roomNameLike: nil,
|
||||
tags: [],
|
||||
notTags: [])
|
||||
|
||||
let visibleRoomsView = try SlidingSyncViewBuilder()
|
||||
.timelineLimit(limit: 20)
|
||||
.requiredState(requiredState: requiredState)
|
||||
.filters(filters: filters)
|
||||
.name(name: "CurrentlyVisibleRooms")
|
||||
.syncMode(mode: .selective)
|
||||
.addRange(from: 0, to: 20)
|
||||
.build()
|
||||
|
||||
let allRoomsView = try SlidingSyncViewBuilder()
|
||||
.noTimelineLimit()
|
||||
.requiredState(requiredState: requiredState)
|
||||
.filters(filters: filters)
|
||||
.name(name: "AllRooms")
|
||||
.syncMode(mode: .growingFullSync)
|
||||
.batchSize(batchSize: 100)
|
||||
.roomLimit(limit: 500)
|
||||
.build()
|
||||
|
||||
let slidingSync = try slidingSyncBuilder
|
||||
.addView(v: visibleRoomsView)
|
||||
.addView(v: allRoomsView)
|
||||
.withCommonExtensions()
|
||||
.coldCache(name: "ElementX")
|
||||
.build()
|
||||
|
||||
let visibleRoomsViewProxy = SlidingSyncViewProxy(clientProxy: self, slidingSync: slidingSync, slidingSyncView: visibleRoomsView)
|
||||
|
||||
let allRoomsViewProxy = SlidingSyncViewProxy(clientProxy: self, slidingSync: slidingSync, slidingSyncView: allRoomsView)
|
||||
|
||||
self.visibleRoomsSummaryProvider = RoomSummaryProvider(slidingSyncViewProxy: visibleRoomsViewProxy,
|
||||
roomMessageFactory: RoomMessageFactory())
|
||||
|
||||
self.allRoomsSummaryProvider = RoomSummaryProvider(slidingSyncViewProxy: allRoomsViewProxy,
|
||||
roomMessageFactory: RoomMessageFactory())
|
||||
|
||||
self.slidingSync = slidingSync
|
||||
} catch {
|
||||
MXLog.error("Failed configuring sliding sync with error: \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
client.setDelegate(delegate: WeakClientProxyWrapper(clientProxy: self))
|
||||
|
||||
configureSlidingSync()
|
||||
}
|
||||
|
||||
var userIdentifier: String {
|
||||
@@ -181,24 +122,16 @@ class ClientProxy: ClientProxyProtocol {
|
||||
}
|
||||
|
||||
func startSync() {
|
||||
guard !client.isSoftLogout() else {
|
||||
guard !client.isSoftLogout(), slidingSyncObserverToken == nil else {
|
||||
return
|
||||
}
|
||||
|
||||
slidingSync?.setObserver(observer: WeakClientProxyWrapper(clientProxy: self))
|
||||
slidingSyncObserverToken = slidingSync?.sync()
|
||||
}
|
||||
|
||||
func stopSync() {
|
||||
client.setDelegate(delegate: nil)
|
||||
|
||||
slidingSyncObserverToken?.cancel()
|
||||
slidingSync?.setObserver(observer: nil)
|
||||
}
|
||||
|
||||
func restartSync() {
|
||||
slidingSyncObserverToken?.cancel()
|
||||
slidingSyncObserverToken = slidingSync?.sync()
|
||||
slidingSyncObserverToken = nil
|
||||
}
|
||||
|
||||
func roomForIdentifier(_ identifier: String) async -> RoomProxyProtocol? {
|
||||
@@ -297,6 +230,125 @@ class ClientProxy: ClientProxyProtocol {
|
||||
}
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private func restartSync() {
|
||||
stopSync()
|
||||
startSync()
|
||||
}
|
||||
|
||||
private func configureSlidingSync() {
|
||||
guard slidingSync == nil else {
|
||||
fatalError("This shouldn't be called more than once")
|
||||
}
|
||||
|
||||
do {
|
||||
let slidingSyncBuilder = try client.slidingSync().homeserver(url: ServiceLocator.shared.settings.slidingSyncProxyBaseURLString)
|
||||
|
||||
let slidingSync = try slidingSyncBuilder
|
||||
.withCommonExtensions()
|
||||
.coldCache(name: "ElementX")
|
||||
.build()
|
||||
|
||||
slidingSync.setObserver(observer: WeakClientProxyWrapper(clientProxy: self))
|
||||
|
||||
self.slidingSync = slidingSync
|
||||
|
||||
configureSlidingSyncViews(slidingSync: slidingSync)
|
||||
|
||||
guard let visibleRoomsSlidingSyncView else {
|
||||
MXLog.error("Visible rooms sliding sync view unavailable")
|
||||
return
|
||||
}
|
||||
|
||||
registerSlidingSyncView(visibleRoomsSlidingSyncView)
|
||||
|
||||
} catch {
|
||||
MXLog.error("Failed building sliding sync with error: \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
// swiftlint:disable:next function_body_length
|
||||
private func configureSlidingSyncViews(slidingSync: SlidingSyncProtocol) {
|
||||
guard visibleRoomsSlidingSyncView == nil,
|
||||
allRoomsSlidingSyncView == nil else {
|
||||
fatalError("This shouldn't be called more than once")
|
||||
}
|
||||
|
||||
let requiredState = [RequiredState(key: "m.room.avatar", value: ""),
|
||||
RequiredState(key: "m.room.encryption", value: "")]
|
||||
|
||||
let filters = SlidingSyncRequestListFilters(isDm: nil,
|
||||
spaces: [],
|
||||
isEncrypted: nil,
|
||||
isInvite: false,
|
||||
isTombstoned: false,
|
||||
roomTypes: [],
|
||||
notRoomTypes: ["m.space"],
|
||||
roomNameLike: nil,
|
||||
tags: [],
|
||||
notTags: [])
|
||||
|
||||
do {
|
||||
let visibleRoomsView = try SlidingSyncViewBuilder()
|
||||
.timelineLimit(limit: 20)
|
||||
.requiredState(requiredState: requiredState)
|
||||
.filters(filters: filters)
|
||||
.name(name: "CurrentlyVisibleRooms")
|
||||
.syncMode(mode: .selective)
|
||||
.addRange(from: 0, to: 20)
|
||||
.build()
|
||||
|
||||
let allRoomsView = try SlidingSyncViewBuilder()
|
||||
.noTimelineLimit()
|
||||
.requiredState(requiredState: requiredState)
|
||||
.filters(filters: filters)
|
||||
.name(name: "AllRooms")
|
||||
.syncMode(mode: .growingFullSync)
|
||||
.batchSize(batchSize: 100)
|
||||
.roomLimit(limit: 500)
|
||||
.build()
|
||||
|
||||
let visibleRoomsViewProxy = SlidingSyncViewProxy(slidingSync: slidingSync, slidingSyncView: visibleRoomsView)
|
||||
|
||||
let allRoomsViewProxy = SlidingSyncViewProxy(slidingSync: slidingSync, slidingSyncView: allRoomsView)
|
||||
|
||||
visibleRoomsSummaryProvider = RoomSummaryProvider(slidingSyncViewProxy: visibleRoomsViewProxy,
|
||||
roomMessageFactory: RoomMessageFactory())
|
||||
|
||||
allRoomsSummaryProvider = RoomSummaryProvider(slidingSyncViewProxy: allRoomsViewProxy,
|
||||
roomMessageFactory: RoomMessageFactory())
|
||||
|
||||
visibleRoomsViewProxy.visibleRangeUpdatePublisher.sink { [weak self] in
|
||||
self?.restartSync()
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
visibleRoomsViewProxyStateObservationToken = visibleRoomsViewProxy.diffPublisher.sink { [weak self] _ in
|
||||
self?.registerAllRoomSlidingSyncView()
|
||||
self?.visibleRoomsViewProxyStateObservationToken = nil
|
||||
}
|
||||
|
||||
visibleRoomsSlidingSyncView = visibleRoomsView
|
||||
allRoomsSlidingSyncView = allRoomsView
|
||||
|
||||
} catch {
|
||||
MXLog.error("Failed building sliding sync views with error: \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
private func registerAllRoomSlidingSyncView() {
|
||||
guard let allRoomsSlidingSyncView else {
|
||||
MXLog.error("All rooms sliding sync view unavailable")
|
||||
return
|
||||
}
|
||||
|
||||
registerSlidingSyncView(allRoomsSlidingSyncView)
|
||||
}
|
||||
|
||||
private func registerSlidingSyncView(_ view: SlidingSyncView) {
|
||||
_ = slidingSync?.addView(view: view)
|
||||
restartSync()
|
||||
}
|
||||
|
||||
private func roomTupleForIdentifier(_ identifier: String) -> (SlidingSyncRoom?, Room?) {
|
||||
do {
|
||||
|
||||
@@ -79,8 +79,6 @@ protocol ClientProxyProtocol: AnyObject, MediaProxyProtocol {
|
||||
|
||||
func stopSync()
|
||||
|
||||
func restartSync()
|
||||
|
||||
func roomForIdentifier(_ identifier: String) async -> RoomProxyProtocol?
|
||||
|
||||
func loadUserDisplayName() async -> Result<String, ClientProxyError>
|
||||
|
||||
@@ -40,8 +40,6 @@ class MockClientProxy: ClientProxyProtocol {
|
||||
|
||||
func stopSync() { }
|
||||
|
||||
func restartSync() { }
|
||||
|
||||
func roomForIdentifier(_ identifier: String) async -> RoomProxyProtocol? {
|
||||
guard let room = visibleRoomsSummaryProvider?.roomListPublisher.value.first(where: { $0.id == identifier }) else {
|
||||
return nil
|
||||
|
||||
@@ -51,7 +51,6 @@ private class SlidingSyncViewObserver: SlidingSyncViewRoomListObserver, SlidingS
|
||||
}
|
||||
|
||||
class SlidingSyncViewProxy {
|
||||
private weak var clientProxy: ClientProxyProtocol?
|
||||
private let slidingSync: SlidingSyncProtocol
|
||||
private let slidingSyncView: SlidingSyncViewProtocol
|
||||
|
||||
@@ -64,6 +63,7 @@ class SlidingSyncViewProxy {
|
||||
let diffPublisher = PassthroughSubject<SlidingSyncViewRoomsListDiff, Never>()
|
||||
let statePublisher = PassthroughSubject<SlidingSyncState, Never>()
|
||||
let countPublisher = PassthroughSubject<UInt, Never>()
|
||||
let visibleRangeUpdatePublisher = PassthroughSubject<Void, Never>()
|
||||
|
||||
deinit {
|
||||
listUpdateObserverToken?.cancel()
|
||||
@@ -71,8 +71,7 @@ class SlidingSyncViewProxy {
|
||||
countUpdateObserverToken?.cancel()
|
||||
}
|
||||
|
||||
init(clientProxy: ClientProxyProtocol, slidingSync: SlidingSyncProtocol, slidingSyncView: SlidingSyncViewProtocol) {
|
||||
self.clientProxy = clientProxy
|
||||
init(slidingSync: SlidingSyncProtocol, slidingSyncView: SlidingSyncViewProtocol) {
|
||||
self.slidingSync = slidingSync
|
||||
self.slidingSyncView = slidingSyncView
|
||||
|
||||
@@ -103,11 +102,11 @@ class SlidingSyncViewProxy {
|
||||
try slidingSync.getRoom(roomId: identifier)
|
||||
}
|
||||
|
||||
func updateVisibleRange(_ range: ClosedRange<Int>) {
|
||||
func updateVisibleRange(_ range: Range<Int>) {
|
||||
MXLog.info("Setting sliding sync view range to \(range)")
|
||||
|
||||
slidingSyncView.setRange(start: UInt32(range.lowerBound), end: UInt32(range.upperBound))
|
||||
|
||||
clientProxy?.restartSync()
|
||||
visibleRangeUpdatePublisher.send(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ class MockRoomSummaryProvider: RoomSummaryProviderProtocol {
|
||||
|
||||
func updateRoomsWithIdentifiers(_ identifiers: [String]) { }
|
||||
|
||||
func updateVisibleRange(_ range: ClosedRange<Int>) { }
|
||||
func updateVisibleRange(_ range: Range<Int>) { }
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ class RoomSummaryProvider: RoomSummaryProviderProtocol {
|
||||
}
|
||||
}
|
||||
|
||||
func updateVisibleRange(_ range: ClosedRange<Int>) {
|
||||
func updateVisibleRange(_ range: Range<Int>) {
|
||||
slidingSyncViewProxy.updateVisibleRange(range)
|
||||
}
|
||||
|
||||
@@ -181,6 +181,7 @@ class RoomSummaryProvider: RoomSummaryProviderProtocol {
|
||||
}
|
||||
}
|
||||
|
||||
// swiftlint:disable:next cyclomatic_complexity
|
||||
private func buildDiff(from diff: SlidingSyncViewRoomsListDiff, on rooms: [RoomSummary]) -> CollectionDifference<RoomSummary>? {
|
||||
var changes = [CollectionDifference<RoomSummary>.Change]()
|
||||
|
||||
@@ -216,6 +217,18 @@ class RoomSummaryProvider: RoomSummaryProviderProtocol {
|
||||
for (index, value) in values.enumerated() {
|
||||
changes.append(.insert(offset: index, element: buildSummaryForRoomListEntry(value), associatedWith: nil))
|
||||
}
|
||||
case .clear:
|
||||
MXLog.verbose("Clear all items, current total count: \(rooms.count)")
|
||||
for (index, value) in rooms.enumerated() {
|
||||
changes.append(.remove(offset: index, element: value, associatedWith: nil))
|
||||
}
|
||||
case .pop:
|
||||
MXLog.verbose("Pop, current total count: \(rooms.count)")
|
||||
guard let value = rooms.last else {
|
||||
fatalError()
|
||||
}
|
||||
|
||||
changes.append(.remove(offset: rooms.count - 1, element: value, associatedWith: nil))
|
||||
}
|
||||
|
||||
return CollectionDifference(changes)
|
||||
|
||||
@@ -55,5 +55,5 @@ protocol RoomSummaryProviderProtocol {
|
||||
/// - Parameter identifiers: the identifiers for the rooms that have changed
|
||||
func updateRoomsWithIdentifiers(_ identifiers: [String])
|
||||
|
||||
func updateVisibleRange(_ range: ClosedRange<Int>)
|
||||
func updateVisibleRange(_ range: Range<Int>)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user