Rename the TimelineProvider to TimelineItemProvider

This commit is contained in:
Stefan Ceriu
2025-05-23 07:21:25 +03:00
committed by Stefan Ceriu
parent d058e7cd25
commit 972084aaf7
18 changed files with 102 additions and 119 deletions
@@ -13,19 +13,17 @@ import UIKit
class TimelineController: TimelineControllerProtocol {
private let roomProxy: JoinedRoomProxyProtocol
private let liveTimelineProvider: TimelineProviderProtocol
private let liveTimelineItemProvider: TimelineItemProviderProtocol
private let timelineItemFactory: RoomTimelineItemFactoryProtocol
private let mediaProvider: MediaProviderProtocol
private let appSettings: AppSettings
private let serialDispatchQueue: DispatchQueue
let callbacks = PassthroughSubject<TimelineControllerCallback, Never>()
private var activeTimeline: TimelineProxyProtocol
private var activeTimelineProvider: TimelineProviderProtocol {
private var activeTimelineItemProvider: TimelineItemProviderProtocol {
didSet {
configureActiveTimelineProvider()
configureActiveTimelineItemProvider()
}
}
@@ -42,7 +40,7 @@ class TimelineController: TimelineControllerProtocol {
}
var timelineKind: TimelineKind {
activeTimelineProvider.kind
activeTimelineItemProvider.kind
}
init(roomProxy: JoinedRoomProxyProtocol,
@@ -52,18 +50,16 @@ class TimelineController: TimelineControllerProtocol {
mediaProvider: MediaProviderProtocol,
appSettings: AppSettings) {
self.roomProxy = roomProxy
liveTimelineProvider = timelineProxy.timelineProvider
liveTimelineItemProvider = timelineProxy.timelineItemProvider
self.timelineItemFactory = timelineItemFactory
self.mediaProvider = mediaProvider
self.appSettings = appSettings
serialDispatchQueue = DispatchQueue(label: "io.element.elementx.timelineprovider", qos: .utility)
activeTimeline = timelineProxy
activeTimelineProvider = liveTimelineProvider
activeTimelineItemProvider = liveTimelineItemProvider
guard let initialFocussedEventID else {
configureActiveTimelineProvider()
configureActiveTimelineItemProvider()
return
}
@@ -75,7 +71,7 @@ class TimelineController: TimelineControllerProtocol {
break
case .failure:
// Setup the live timeline as a fallback.
configureActiveTimelineProvider()
configureActiveTimelineItemProvider()
}
}
}
@@ -85,7 +81,7 @@ class TimelineController: TimelineControllerProtocol {
case .success(let timeline):
await timeline.subscribeForUpdates()
activeTimeline = timeline
activeTimelineProvider = timeline.timelineProvider
activeTimelineItemProvider = timeline.timelineItemProvider
return .success(())
case .failure(let error):
if case .eventNotFound = error {
@@ -98,7 +94,7 @@ class TimelineController: TimelineControllerProtocol {
func focusLive() {
activeTimeline = roomProxy.timeline
activeTimelineProvider = liveTimelineProvider
activeTimelineItemProvider = liveTimelineItemProvider
}
func paginateBackwards(requestSize: UInt16) async -> Result<Void, TimelineControllerError> {
@@ -328,7 +324,7 @@ class TimelineController: TimelineControllerProtocol {
// Handle this parallel to the timeline items so we're not forced
// to bundle the Rust side objects within them
func debugInfo(for itemID: TimelineItemIdentifier) -> TimelineItemDebugInfo {
for timelineItemProxy in activeTimelineProvider.itemProxies {
for timelineItemProxy in activeTimelineItemProvider.itemProxies {
switch timelineItemProxy {
case .event(let item):
if item.id == itemID {
@@ -343,7 +339,7 @@ class TimelineController: TimelineControllerProtocol {
}
func sendHandle(for itemID: TimelineItemIdentifier) -> SendHandleProxy? {
for timelineItemProxy in activeTimelineProvider.itemProxies {
for timelineItemProxy in activeTimelineItemProvider.itemProxies {
switch timelineItemProxy {
case .event(let item):
if item.id == itemID {
@@ -361,24 +357,24 @@ class TimelineController: TimelineControllerProtocol {
/// The cancellable used to update the timeline items.
private var updateTimelineItemsCancellable: AnyCancellable?
/// The controller is switching the `activeTimelineProvider`.
/// The controller is switching the `activeTimelineItemProvider`.
private var isSwitchingTimelines = false
/// Configures the controller to listen to `activeTimeline` for events.
/// - Parameter clearExistingItems: Whether or not to clear any existing items before loading the timeline's contents.
private func configureActiveTimelineProvider() {
private func configureActiveTimelineItemProvider() {
updateTimelineItemsCancellable = nil
isSwitchingTimelines = true
// Inform the world that the initial items are loading from the store
paginationState = PaginationState(backward: .paginating, forward: .paginating)
callbacks.send(.isLive(activeTimelineProvider.kind == .live))
callbacks.send(.isLive(activeTimelineItemProvider.kind == .live))
updateTimelineItemsCancellable = Task { [weak self, activeTimelineProvider] in
updateTimelineItemsCancellable = Task { [weak self, activeTimelineItemProvider] in
let contentSizeChangePublisher = NotificationCenter.default.publisher(for: UIContentSizeCategory.didChangeNotification)
let timelineUpdates = activeTimelineProvider.updatePublisher.merge(with: contentSizeChangePublisher.map { _ in
(activeTimelineProvider.itemProxies, activeTimelineProvider.paginationState)
let timelineUpdates = activeTimelineItemProvider.updatePublisher.merge(with: contentSizeChangePublisher.map { _ in
(activeTimelineItemProvider.itemProxies, activeTimelineItemProvider.paginationState)
})
for await (items, paginationState) in timelineUpdates.values {
@@ -506,7 +502,7 @@ class TimelineController: TimelineControllerProtocol {
}
func eventTimestamp(for itemID: TimelineItemIdentifier) -> Date? {
for itemProxy in activeTimelineProvider.itemProxies {
for itemProxy in activeTimelineItemProvider.itemProxies {
switch itemProxy {
case .event(let eventTimelineItemProxy):
if eventTimelineItemProxy.id == itemID {
@@ -9,7 +9,7 @@ import Combine
import Foundation
import MatrixRustSDK
class TimelineProvider: TimelineProviderProtocol {
class TimelineItemProvider: TimelineItemProviderProtocol {
private var cancellables = Set<AnyCancellable>()
private let serialDispatchQueue: DispatchQueue
@@ -46,7 +46,7 @@ class TimelineProvider: TimelineProviderProtocol {
}
init(timeline: Timeline, kind: TimelineKind, paginationStatePublisher: AnyPublisher<PaginationState, Never>) {
serialDispatchQueue = DispatchQueue(label: "io.element.elementx.timelineprovider", qos: .utility)
serialDispatchQueue = DispatchQueue(label: "io.element.elementx.timeline_item_provider", qos: .utility)
itemProxiesSubject = CurrentValueSubject<[TimelineItemProxy], Never>([])
self.kind = kind
@@ -29,7 +29,7 @@ struct PaginationState: Equatable {
@MainActor
// sourcery: AutoMockable
protocol TimelineProviderProtocol {
protocol TimelineItemProviderProtocol {
/// A publisher that signals when ``itemProxies`` or ``paginationState`` are changed.
var updatePublisher: AnyPublisher<([TimelineItemProxy], PaginationState), Never> { get }
/// The current set of items in the timeline.
@@ -24,9 +24,9 @@ final class TimelineProxy: TimelineProxyProtocol {
private let kind: TimelineKind
private var innerTimelineProvider: TimelineProviderProtocol!
var timelineProvider: TimelineProviderProtocol {
innerTimelineProvider
private var innerTimelineItemProvider: TimelineItemProviderProtocol!
var timelineItemProvider: TimelineItemProviderProtocol {
innerTimelineItemProvider
}
deinit {
@@ -39,7 +39,7 @@ final class TimelineProxy: TimelineProxyProtocol {
}
func subscribeForUpdates() async {
guard innerTimelineProvider == nil else {
guard innerTimelineItemProvider == nil else {
MXLog.warning("Timeline already subscribed for updates")
return
}
@@ -51,12 +51,12 @@ final class TimelineProxy: TimelineProxyProtocol {
await subscribeToPagination()
let provider = await TimelineProvider(timeline: timeline, kind: kind, paginationStatePublisher: paginationStatePublisher)
let provider = await TimelineItemProvider(timeline: timeline, kind: kind, paginationStatePublisher: paginationStatePublisher)
// Make sure the existing items are built so that we have content in the timeline before
// determining whether or not the timeline should paginate to load more items.
await provider.waitForInitialItems()
innerTimelineProvider = provider
innerTimelineItemProvider = provider
Task {
await timeline.fetchMembers()
@@ -76,7 +76,7 @@ final class TimelineProxy: TimelineProxyProtocol {
}
func messageEventContent(for timelineItemID: TimelineItemIdentifier) async -> RoomMessageEventContentWithoutRelation? {
guard let content = await timelineProvider.itemProxies.firstEventTimelineItemUsingStableID(timelineItemID)?.content,
guard let content = await timelineItemProvider.itemProxies.firstEventTimelineItemUsingStableID(timelineItemID)?.content,
case let .msgLike(messageLikeContent) = content,
case let .message(messageContent) = messageLikeContent.kind else {
return nil
@@ -39,7 +39,7 @@ enum TimelineProxyError: Error {
// sourcery: AutoMockable
protocol TimelineProxyProtocol {
var timelineProvider: TimelineProviderProtocol { get }
var timelineItemProvider: TimelineItemProviderProtocol { get }
func subscribeForUpdates() async