mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-06 12:28:29 +00:00
Move the pinned timeline in line with the other timeline creation methods and have it report errors just like the others
This commit is contained in:
committed by
Stefan Ceriu
parent
909aa086f2
commit
250a7ed451
@@ -67,10 +67,10 @@ class PinnedEventsTimelineFlowCoordinator: FlowCoordinatorProtocol {
|
|||||||
let timelineItemFactory = RoomTimelineItemFactory(userID: userID,
|
let timelineItemFactory = RoomTimelineItemFactory(userID: userID,
|
||||||
attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()),
|
attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()),
|
||||||
stateEventStringBuilder: RoomStateEventStringBuilder(userID: userID))
|
stateEventStringBuilder: RoomStateEventStringBuilder(userID: userID))
|
||||||
|
|
||||||
guard let timelineController = await timelineControllerFactory.buildPinnedEventsTimelineController(roomProxy: roomProxy,
|
guard case let .success(timelineController) = await timelineControllerFactory.buildPinnedEventsTimelineController(roomProxy: roomProxy,
|
||||||
timelineItemFactory: timelineItemFactory,
|
timelineItemFactory: timelineItemFactory,
|
||||||
mediaProvider: userSession.mediaProvider) else {
|
mediaProvider: userSession.mediaProvider) else {
|
||||||
fatalError("This can never fail because we allow this view to be presented only when the timeline is fully loaded and not nil")
|
fatalError("This can never fail because we allow this view to be presented only when the timeline is fully loaded and not nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6270,23 +6270,6 @@ class JoinedRoomProxyMock: JoinedRoomProxyProtocol, @unchecked Sendable {
|
|||||||
set(value) { underlyingTimeline = value }
|
set(value) { underlyingTimeline = value }
|
||||||
}
|
}
|
||||||
var underlyingTimeline: TimelineProxyProtocol!
|
var underlyingTimeline: TimelineProxyProtocol!
|
||||||
var pinnedEventsTimelineCallsCount = 0
|
|
||||||
var pinnedEventsTimelineCalled: Bool {
|
|
||||||
return pinnedEventsTimelineCallsCount > 0
|
|
||||||
}
|
|
||||||
|
|
||||||
var pinnedEventsTimeline: TimelineProxyProtocol? {
|
|
||||||
get async {
|
|
||||||
pinnedEventsTimelineCallsCount += 1
|
|
||||||
if let pinnedEventsTimelineClosure = pinnedEventsTimelineClosure {
|
|
||||||
return await pinnedEventsTimelineClosure()
|
|
||||||
} else {
|
|
||||||
return underlyingPinnedEventsTimeline
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var underlyingPinnedEventsTimeline: TimelineProxyProtocol?
|
|
||||||
var pinnedEventsTimelineClosure: (() async -> TimelineProxyProtocol?)?
|
|
||||||
var id: String {
|
var id: String {
|
||||||
get { return underlyingId }
|
get { return underlyingId }
|
||||||
set(value) { underlyingId = value }
|
set(value) { underlyingId = value }
|
||||||
@@ -6578,6 +6561,70 @@ class JoinedRoomProxyMock: JoinedRoomProxyProtocol, @unchecked Sendable {
|
|||||||
return messageFilteredTimelineFocusAllowedMessageTypesPresentationReturnValue
|
return messageFilteredTimelineFocusAllowedMessageTypesPresentationReturnValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//MARK: - pinnedEventsTimeline
|
||||||
|
|
||||||
|
var pinnedEventsTimelineUnderlyingCallsCount = 0
|
||||||
|
var pinnedEventsTimelineCallsCount: Int {
|
||||||
|
get {
|
||||||
|
if Thread.isMainThread {
|
||||||
|
return pinnedEventsTimelineUnderlyingCallsCount
|
||||||
|
} else {
|
||||||
|
var returnValue: Int? = nil
|
||||||
|
DispatchQueue.main.sync {
|
||||||
|
returnValue = pinnedEventsTimelineUnderlyingCallsCount
|
||||||
|
}
|
||||||
|
|
||||||
|
return returnValue!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
if Thread.isMainThread {
|
||||||
|
pinnedEventsTimelineUnderlyingCallsCount = newValue
|
||||||
|
} else {
|
||||||
|
DispatchQueue.main.sync {
|
||||||
|
pinnedEventsTimelineUnderlyingCallsCount = newValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var pinnedEventsTimelineCalled: Bool {
|
||||||
|
return pinnedEventsTimelineCallsCount > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
var pinnedEventsTimelineUnderlyingReturnValue: Result<TimelineProxyProtocol, RoomProxyError>!
|
||||||
|
var pinnedEventsTimelineReturnValue: Result<TimelineProxyProtocol, RoomProxyError>! {
|
||||||
|
get {
|
||||||
|
if Thread.isMainThread {
|
||||||
|
return pinnedEventsTimelineUnderlyingReturnValue
|
||||||
|
} else {
|
||||||
|
var returnValue: Result<TimelineProxyProtocol, RoomProxyError>? = nil
|
||||||
|
DispatchQueue.main.sync {
|
||||||
|
returnValue = pinnedEventsTimelineUnderlyingReturnValue
|
||||||
|
}
|
||||||
|
|
||||||
|
return returnValue!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
if Thread.isMainThread {
|
||||||
|
pinnedEventsTimelineUnderlyingReturnValue = newValue
|
||||||
|
} else {
|
||||||
|
DispatchQueue.main.sync {
|
||||||
|
pinnedEventsTimelineUnderlyingReturnValue = newValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var pinnedEventsTimelineClosure: (() async -> Result<TimelineProxyProtocol, RoomProxyError>)?
|
||||||
|
|
||||||
|
func pinnedEventsTimeline() async -> Result<TimelineProxyProtocol, RoomProxyError> {
|
||||||
|
pinnedEventsTimelineCallsCount += 1
|
||||||
|
if let pinnedEventsTimelineClosure = pinnedEventsTimelineClosure {
|
||||||
|
return await pinnedEventsTimelineClosure()
|
||||||
|
} else {
|
||||||
|
return pinnedEventsTimelineReturnValue
|
||||||
|
}
|
||||||
|
}
|
||||||
//MARK: - enableEncryption
|
//MARK: - enableEncryption
|
||||||
|
|
||||||
var enableEncryptionUnderlyingCallsCount = 0
|
var enableEncryptionUnderlyingCallsCount = 0
|
||||||
@@ -15141,13 +15188,13 @@ class TimelineControllerFactoryMock: TimelineControllerFactoryProtocol, @uncheck
|
|||||||
var buildPinnedEventsTimelineControllerRoomProxyTimelineItemFactoryMediaProviderReceivedArguments: (roomProxy: JoinedRoomProxyProtocol, timelineItemFactory: RoomTimelineItemFactoryProtocol, mediaProvider: MediaProviderProtocol)?
|
var buildPinnedEventsTimelineControllerRoomProxyTimelineItemFactoryMediaProviderReceivedArguments: (roomProxy: JoinedRoomProxyProtocol, timelineItemFactory: RoomTimelineItemFactoryProtocol, mediaProvider: MediaProviderProtocol)?
|
||||||
var buildPinnedEventsTimelineControllerRoomProxyTimelineItemFactoryMediaProviderReceivedInvocations: [(roomProxy: JoinedRoomProxyProtocol, timelineItemFactory: RoomTimelineItemFactoryProtocol, mediaProvider: MediaProviderProtocol)] = []
|
var buildPinnedEventsTimelineControllerRoomProxyTimelineItemFactoryMediaProviderReceivedInvocations: [(roomProxy: JoinedRoomProxyProtocol, timelineItemFactory: RoomTimelineItemFactoryProtocol, mediaProvider: MediaProviderProtocol)] = []
|
||||||
|
|
||||||
var buildPinnedEventsTimelineControllerRoomProxyTimelineItemFactoryMediaProviderUnderlyingReturnValue: TimelineControllerProtocol?
|
var buildPinnedEventsTimelineControllerRoomProxyTimelineItemFactoryMediaProviderUnderlyingReturnValue: Result<TimelineControllerProtocol, TimelineFactoryControllerError>!
|
||||||
var buildPinnedEventsTimelineControllerRoomProxyTimelineItemFactoryMediaProviderReturnValue: TimelineControllerProtocol? {
|
var buildPinnedEventsTimelineControllerRoomProxyTimelineItemFactoryMediaProviderReturnValue: Result<TimelineControllerProtocol, TimelineFactoryControllerError>! {
|
||||||
get {
|
get {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
return buildPinnedEventsTimelineControllerRoomProxyTimelineItemFactoryMediaProviderUnderlyingReturnValue
|
return buildPinnedEventsTimelineControllerRoomProxyTimelineItemFactoryMediaProviderUnderlyingReturnValue
|
||||||
} else {
|
} else {
|
||||||
var returnValue: TimelineControllerProtocol?? = nil
|
var returnValue: Result<TimelineControllerProtocol, TimelineFactoryControllerError>? = nil
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
returnValue = buildPinnedEventsTimelineControllerRoomProxyTimelineItemFactoryMediaProviderUnderlyingReturnValue
|
returnValue = buildPinnedEventsTimelineControllerRoomProxyTimelineItemFactoryMediaProviderUnderlyingReturnValue
|
||||||
}
|
}
|
||||||
@@ -15165,9 +15212,9 @@ class TimelineControllerFactoryMock: TimelineControllerFactoryProtocol, @uncheck
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var buildPinnedEventsTimelineControllerRoomProxyTimelineItemFactoryMediaProviderClosure: ((JoinedRoomProxyProtocol, RoomTimelineItemFactoryProtocol, MediaProviderProtocol) async -> TimelineControllerProtocol?)?
|
var buildPinnedEventsTimelineControllerRoomProxyTimelineItemFactoryMediaProviderClosure: ((JoinedRoomProxyProtocol, RoomTimelineItemFactoryProtocol, MediaProviderProtocol) async -> Result<TimelineControllerProtocol, TimelineFactoryControllerError>)?
|
||||||
|
|
||||||
func buildPinnedEventsTimelineController(roomProxy: JoinedRoomProxyProtocol, timelineItemFactory: RoomTimelineItemFactoryProtocol, mediaProvider: MediaProviderProtocol) async -> TimelineControllerProtocol? {
|
func buildPinnedEventsTimelineController(roomProxy: JoinedRoomProxyProtocol, timelineItemFactory: RoomTimelineItemFactoryProtocol, mediaProvider: MediaProviderProtocol) async -> Result<TimelineControllerProtocol, TimelineFactoryControllerError> {
|
||||||
buildPinnedEventsTimelineControllerRoomProxyTimelineItemFactoryMediaProviderCallsCount += 1
|
buildPinnedEventsTimelineControllerRoomProxyTimelineItemFactoryMediaProviderCallsCount += 1
|
||||||
buildPinnedEventsTimelineControllerRoomProxyTimelineItemFactoryMediaProviderReceivedArguments = (roomProxy: roomProxy, timelineItemFactory: timelineItemFactory, mediaProvider: mediaProvider)
|
buildPinnedEventsTimelineControllerRoomProxyTimelineItemFactoryMediaProviderReceivedArguments = (roomProxy: roomProxy, timelineItemFactory: timelineItemFactory, mediaProvider: mediaProvider)
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
|
|||||||
@@ -59,6 +59,8 @@ extension JoinedRoomProxyMock {
|
|||||||
|
|
||||||
timeline = TimelineProxyMock(.init(isAutoUpdating: configuration.shouldUseAutoUpdatingTimeline,
|
timeline = TimelineProxyMock(.init(isAutoUpdating: configuration.shouldUseAutoUpdatingTimeline,
|
||||||
timelineStartReached: configuration.timelineStartReached))
|
timelineStartReached: configuration.timelineStartReached))
|
||||||
|
|
||||||
|
pinnedEventsTimelineReturnValue = .failure(.failedCreatingPinnedTimeline)
|
||||||
|
|
||||||
ownUserID = configuration.ownUserID
|
ownUserID = configuration.ownUserID
|
||||||
|
|
||||||
|
|||||||
@@ -445,12 +445,12 @@ class RoomDetailsScreenViewModel: RoomDetailsScreenViewModelType, RoomDetailsScr
|
|||||||
}
|
}
|
||||||
|
|
||||||
Task {
|
Task {
|
||||||
guard let timelineProvider = await roomProxy.pinnedEventsTimeline?.timelineProvider else {
|
guard case let .success(pinnedEventsTimeline) = await roomProxy.pinnedEventsTimeline() else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if pinnedEventsTimelineProvider == nil {
|
if pinnedEventsTimelineProvider == nil {
|
||||||
pinnedEventsTimelineProvider = timelineProvider
|
pinnedEventsTimelineProvider = pinnedEventsTimeline.timelineProvider
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -353,12 +353,12 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
|||||||
}
|
}
|
||||||
|
|
||||||
Task {
|
Task {
|
||||||
guard let timelineProvider = await roomProxy.pinnedEventsTimeline?.timelineProvider else {
|
guard case let .success(pinnedEventsTimeline) = await roomProxy.pinnedEventsTimeline() else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if pinnedEventsTimelineProvider == nil {
|
if pinnedEventsTimelineProvider == nil {
|
||||||
pinnedEventsTimelineProvider = timelineProvider
|
pinnedEventsTimelineProvider = pinnedEventsTimeline.timelineProvider
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,12 +11,14 @@ import MatrixRustSDK
|
|||||||
class BannedRoomProxy: BannedRoomProxyProtocol {
|
class BannedRoomProxy: BannedRoomProxyProtocol {
|
||||||
private let roomListItem: RoomListItemProtocol
|
private let roomListItem: RoomListItemProtocol
|
||||||
private let roomPreview: RoomPreviewProtocol
|
private let roomPreview: RoomPreviewProtocol
|
||||||
let info: BaseRoomInfoProxyProtocol
|
|
||||||
let ownUserID: String
|
|
||||||
|
|
||||||
// A room identifier is constant and lazy stops it from being fetched
|
// A room identifier is constant and lazy stops it from being fetched
|
||||||
// multiple times over FFI
|
// multiple times over FFI
|
||||||
lazy var id = info.id
|
lazy var id = info.id
|
||||||
|
|
||||||
|
let ownUserID: String
|
||||||
|
|
||||||
|
let info: BaseRoomInfoProxyProtocol
|
||||||
|
|
||||||
init(roomListItem: RoomListItemProtocol,
|
init(roomListItem: RoomListItemProtocol,
|
||||||
roomPreview: RoomPreviewProtocol,
|
roomPreview: RoomPreviewProtocol,
|
||||||
|
|||||||
@@ -12,13 +12,15 @@ import UIKit
|
|||||||
class InvitedRoomProxy: InvitedRoomProxyProtocol {
|
class InvitedRoomProxy: InvitedRoomProxyProtocol {
|
||||||
private let roomListItem: RoomListItemProtocol
|
private let roomListItem: RoomListItemProtocol
|
||||||
private let roomPreview: RoomPreviewProtocol
|
private let roomPreview: RoomPreviewProtocol
|
||||||
let info: BaseRoomInfoProxyProtocol
|
|
||||||
let ownUserID: String
|
|
||||||
let inviter: RoomMemberProxyProtocol?
|
|
||||||
|
|
||||||
// A room identifier is constant and lazy stops it from being fetched
|
// A room identifier is constant and lazy stops it from being fetched
|
||||||
// multiple times over FFI
|
// multiple times over FFI
|
||||||
lazy var id: String = info.id
|
lazy var id: String = info.id
|
||||||
|
|
||||||
|
let ownUserID: String
|
||||||
|
|
||||||
|
let info: BaseRoomInfoProxyProtocol
|
||||||
|
let inviter: RoomMemberProxyProtocol?
|
||||||
|
|
||||||
init(roomListItem: RoomListItemProtocol,
|
init(roomListItem: RoomListItemProtocol,
|
||||||
roomPreview: RoomPreviewProtocol,
|
roomPreview: RoomPreviewProtocol,
|
||||||
|
|||||||
@@ -14,50 +14,6 @@ class JoinedRoomProxy: JoinedRoomProxyProtocol {
|
|||||||
private let roomListService: RoomListServiceProtocol
|
private let roomListService: RoomListServiceProtocol
|
||||||
private let roomListItem: RoomListItemProtocol
|
private let roomListItem: RoomListItemProtocol
|
||||||
private let room: RoomProtocol
|
private let room: RoomProtocol
|
||||||
let timeline: TimelineProxyProtocol
|
|
||||||
|
|
||||||
private var innerPinnedEventsTimeline: TimelineProxyProtocol?
|
|
||||||
private var innerPinnedEventsTimelineTask: Task<TimelineProxyProtocol?, Never>?
|
|
||||||
var pinnedEventsTimeline: TimelineProxyProtocol? {
|
|
||||||
get async {
|
|
||||||
// Check if is already available.
|
|
||||||
if let innerPinnedEventsTimeline {
|
|
||||||
return innerPinnedEventsTimeline
|
|
||||||
// Otherwise check if there is already a task loading it, and wait for it.
|
|
||||||
} else if let innerPinnedEventsTimelineTask,
|
|
||||||
let value = await innerPinnedEventsTimelineTask.value {
|
|
||||||
return value
|
|
||||||
// Else create and store a new task to load it and wait for it.
|
|
||||||
} else {
|
|
||||||
let task = Task<TimelineProxyProtocol?, Never> { [weak self] in
|
|
||||||
guard let self else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
do {
|
|
||||||
let sdkTimeline = try await room.timelineWithConfiguration(configuration: .init(focus: .pinnedEvents(maxEventsToLoad: 100, maxConcurrentRequests: 10),
|
|
||||||
filter: .all,
|
|
||||||
internalIdPrefix: nil,
|
|
||||||
dateDividerMode: .daily,
|
|
||||||
trackReadReceipts: false,
|
|
||||||
reportUtds: true))
|
|
||||||
|
|
||||||
let timeline = TimelineProxy(timeline: sdkTimeline, kind: .pinned)
|
|
||||||
|
|
||||||
await timeline.subscribeForUpdates()
|
|
||||||
innerPinnedEventsTimeline = timeline
|
|
||||||
return timeline
|
|
||||||
} catch {
|
|
||||||
MXLog.error("Failed creating pinned events timeline with error: \(error)")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
innerPinnedEventsTimelineTask = task
|
|
||||||
return await task.value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// periphery:ignore - required for instance retention in the rust codebase
|
// periphery:ignore - required for instance retention in the rust codebase
|
||||||
private var roomInfoObservationToken: TaskHandle?
|
private var roomInfoObservationToken: TaskHandle?
|
||||||
@@ -68,8 +24,19 @@ class JoinedRoomProxy: JoinedRoomProxyProtocol {
|
|||||||
// periphery:ignore - required for instance retention in the rust codebase
|
// periphery:ignore - required for instance retention in the rust codebase
|
||||||
private var knockRequestsChangesObservationToken: TaskHandle?
|
private var knockRequestsChangesObservationToken: TaskHandle?
|
||||||
|
|
||||||
|
private var innerPinnedEventsTimeline: TimelineProxyProtocol?
|
||||||
|
private var innerPinnedEventsTimelineTask: Task<Result<TimelineProxyProtocol, RoomProxyError>, Never>?
|
||||||
|
|
||||||
private var subscribedForUpdates = false
|
private var subscribedForUpdates = false
|
||||||
|
|
||||||
|
// A room identifier is constant and lazy stops it from being fetched
|
||||||
|
// multiple times over FFI
|
||||||
|
lazy var id: String = room.id()
|
||||||
|
|
||||||
|
var ownUserID: String { room.ownUserId() }
|
||||||
|
|
||||||
|
let timeline: TimelineProxyProtocol
|
||||||
|
|
||||||
private let infoSubject: CurrentValueSubject<RoomInfoProxy, Never>
|
private let infoSubject: CurrentValueSubject<RoomInfoProxy, Never>
|
||||||
var infoPublisher: CurrentValuePublisher<RoomInfoProxy, Never> {
|
var infoPublisher: CurrentValuePublisher<RoomInfoProxy, Never> {
|
||||||
infoSubject.asCurrentValuePublisher()
|
infoSubject.asCurrentValuePublisher()
|
||||||
@@ -95,12 +62,6 @@ class JoinedRoomProxy: JoinedRoomProxyProtocol {
|
|||||||
knockRequestsStateSubject.asCurrentValuePublisher()
|
knockRequestsStateSubject.asCurrentValuePublisher()
|
||||||
}
|
}
|
||||||
|
|
||||||
// A room identifier is constant and lazy stops it from being fetched
|
|
||||||
// multiple times over FFI
|
|
||||||
lazy var id: String = room.id()
|
|
||||||
var ownUserID: String { room.ownUserId() }
|
|
||||||
var info: RoomInfoProxy { infoSubject.value }
|
|
||||||
|
|
||||||
init(roomListService: RoomListServiceProtocol,
|
init(roomListService: RoomListServiceProtocol,
|
||||||
roomListItem: RoomListItemProtocol,
|
roomListItem: RoomListItemProtocol,
|
||||||
room: RoomProtocol) async throws {
|
room: RoomProtocol) async throws {
|
||||||
@@ -111,7 +72,7 @@ class JoinedRoomProxy: JoinedRoomProxyProtocol {
|
|||||||
infoSubject = try await .init(RoomInfoProxy(roomInfo: room.roomInfo()))
|
infoSubject = try await .init(RoomInfoProxy(roomInfo: room.roomInfo()))
|
||||||
|
|
||||||
timeline = try await TimelineProxy(timeline: room.timelineWithConfiguration(configuration: .init(focus: .live,
|
timeline = try await TimelineProxy(timeline: room.timelineWithConfiguration(configuration: .init(focus: .live,
|
||||||
filter: .eventTypeFilter(filter: eventFilters),
|
filter: .eventTypeFilter(filter: excludedEventsFilter),
|
||||||
internalIdPrefix: nil,
|
internalIdPrefix: nil,
|
||||||
dateDividerMode: .daily,
|
dateDividerMode: .daily,
|
||||||
trackReadReceipts: true,
|
trackReadReceipts: true,
|
||||||
@@ -131,24 +92,6 @@ class JoinedRoomProxy: JoinedRoomProxyProtocol {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private let eventFilters: TimelineEventTypeFilter = {
|
|
||||||
var stateEventFilters: [StateEventType] = [.roomAliases,
|
|
||||||
.roomCanonicalAlias,
|
|
||||||
.roomGuestAccess,
|
|
||||||
.roomHistoryVisibility,
|
|
||||||
.roomJoinRules,
|
|
||||||
.roomPinnedEvents,
|
|
||||||
.roomPowerLevels,
|
|
||||||
.roomServerAcl,
|
|
||||||
.roomTombstone,
|
|
||||||
.spaceChild,
|
|
||||||
.spaceParent,
|
|
||||||
.policyRuleRoom,
|
|
||||||
.policyRuleServer,
|
|
||||||
.policyRuleUser]
|
|
||||||
return .exclude(eventTypes: stateEventFilters.map { FilterTimelineEventType.state(eventType: $0) })
|
|
||||||
}()
|
|
||||||
|
|
||||||
func subscribeForUpdates() async {
|
func subscribeForUpdates() async {
|
||||||
guard !subscribedForUpdates else {
|
guard !subscribedForUpdates else {
|
||||||
MXLog.warning("Room already subscribed for updates")
|
MXLog.warning("Room already subscribed for updates")
|
||||||
@@ -273,6 +216,43 @@ class JoinedRoomProxy: JoinedRoomProxyProtocol {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func pinnedEventsTimeline() async -> Result<TimelineProxyProtocol, RoomProxyError> {
|
||||||
|
// Check if is already available.
|
||||||
|
if let innerPinnedEventsTimeline {
|
||||||
|
return .success(innerPinnedEventsTimeline)
|
||||||
|
// Otherwise check if there is already a task loading it, and wait for it.
|
||||||
|
} else if let innerPinnedEventsTimelineTask {
|
||||||
|
return await innerPinnedEventsTimelineTask.value
|
||||||
|
} else { // Else create and store a new task to load it and wait for it.
|
||||||
|
let task = Task<Result<TimelineProxyProtocol, RoomProxyError>, Never> { [weak self] in
|
||||||
|
guard let self else {
|
||||||
|
return .failure(.failedCreatingPinnedTimeline)
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
let sdkTimeline = try await room.timelineWithConfiguration(configuration: .init(focus: .pinnedEvents(maxEventsToLoad: 100, maxConcurrentRequests: 10),
|
||||||
|
filter: .all,
|
||||||
|
internalIdPrefix: nil,
|
||||||
|
dateDividerMode: .daily,
|
||||||
|
trackReadReceipts: false,
|
||||||
|
reportUtds: true))
|
||||||
|
|
||||||
|
let timeline = TimelineProxy(timeline: sdkTimeline, kind: .pinned)
|
||||||
|
|
||||||
|
await timeline.subscribeForUpdates()
|
||||||
|
innerPinnedEventsTimeline = timeline
|
||||||
|
return .success(timeline)
|
||||||
|
} catch {
|
||||||
|
MXLog.error("Failed creating pinned events timeline with error: \(error)")
|
||||||
|
return .failure(.sdkError(error))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
innerPinnedEventsTimelineTask = task
|
||||||
|
return await task.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func enableEncryption() async -> Result<Void, RoomProxyError> {
|
func enableEncryption() async -> Result<Void, RoomProxyError> {
|
||||||
do {
|
do {
|
||||||
try await room.enableEncryption()
|
try await room.enableEncryption()
|
||||||
@@ -856,6 +836,24 @@ class JoinedRoomProxy: JoinedRoomProxyProtocol {
|
|||||||
MXLog.error("Failed observing requests to join with error: \(error)")
|
MXLog.error("Failed observing requests to join with error: \(error)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private let excludedEventsFilter: TimelineEventTypeFilter = {
|
||||||
|
var stateEventFilters: [StateEventType] = [.roomAliases,
|
||||||
|
.roomCanonicalAlias,
|
||||||
|
.roomGuestAccess,
|
||||||
|
.roomHistoryVisibility,
|
||||||
|
.roomJoinRules,
|
||||||
|
.roomPinnedEvents,
|
||||||
|
.roomPowerLevels,
|
||||||
|
.roomServerAcl,
|
||||||
|
.roomTombstone,
|
||||||
|
.spaceChild,
|
||||||
|
.spaceParent,
|
||||||
|
.policyRuleRoom,
|
||||||
|
.policyRuleServer,
|
||||||
|
.policyRuleUser]
|
||||||
|
return .exclude(eventTypes: stateEventFilters.map { FilterTimelineEventType.state(eventType: $0) })
|
||||||
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
private final class RoomTypingNotificationUpdateListener: TypingNotificationsListener {
|
private final class RoomTypingNotificationUpdateListener: TypingNotificationsListener {
|
||||||
|
|||||||
@@ -11,12 +11,14 @@ import MatrixRustSDK
|
|||||||
class KnockedRoomProxy: KnockedRoomProxyProtocol {
|
class KnockedRoomProxy: KnockedRoomProxyProtocol {
|
||||||
private let roomListItem: RoomListItemProtocol
|
private let roomListItem: RoomListItemProtocol
|
||||||
private let roomPreview: RoomPreviewProtocol
|
private let roomPreview: RoomPreviewProtocol
|
||||||
let info: BaseRoomInfoProxyProtocol
|
|
||||||
let ownUserID: String
|
|
||||||
|
|
||||||
// A room identifier is constant and lazy stops it from being fetched
|
// A room identifier is constant and lazy stops it from being fetched
|
||||||
// multiple times over FFI
|
// multiple times over FFI
|
||||||
lazy var id = info.id
|
lazy var id = info.id
|
||||||
|
|
||||||
|
let ownUserID: String
|
||||||
|
|
||||||
|
let info: BaseRoomInfoProxyProtocol
|
||||||
|
|
||||||
init(roomListItem: RoomListItemProtocol,
|
init(roomListItem: RoomListItemProtocol,
|
||||||
roomPreview: RoomPreviewProtocol,
|
roomPreview: RoomPreviewProtocol,
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ enum RoomProxyError: Error {
|
|||||||
case invalidMedia
|
case invalidMedia
|
||||||
case eventNotFound
|
case eventNotFound
|
||||||
case missingTransactionID
|
case missingTransactionID
|
||||||
|
case failedCreatingPinnedTimeline
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An enum that describes the relationship between the current user and the room, and contains a reference to the specific implementation of the `RoomProxy`.
|
/// An enum that describes the relationship between the current user and the room, and contains a reference to the specific implementation of the `RoomProxy`.
|
||||||
@@ -75,8 +76,6 @@ protocol JoinedRoomProxyProtocol: RoomProxyProtocol {
|
|||||||
|
|
||||||
var timeline: TimelineProxyProtocol { get }
|
var timeline: TimelineProxyProtocol { get }
|
||||||
|
|
||||||
var pinnedEventsTimeline: TimelineProxyProtocol? { get async }
|
|
||||||
|
|
||||||
func subscribeForUpdates() async
|
func subscribeForUpdates() async
|
||||||
|
|
||||||
func subscribeToRoomInfoUpdates()
|
func subscribeToRoomInfoUpdates()
|
||||||
@@ -89,6 +88,8 @@ protocol JoinedRoomProxyProtocol: RoomProxyProtocol {
|
|||||||
allowedMessageTypes: [TimelineAllowedMessageType],
|
allowedMessageTypes: [TimelineAllowedMessageType],
|
||||||
presentation: TimelineKind.MediaPresentation) async -> Result<TimelineProxyProtocol, RoomProxyError>
|
presentation: TimelineKind.MediaPresentation) async -> Result<TimelineProxyProtocol, RoomProxyError>
|
||||||
|
|
||||||
|
func pinnedEventsTimeline() async -> Result<TimelineProxyProtocol, RoomProxyError>
|
||||||
|
|
||||||
func enableEncryption() async -> Result<Void, RoomProxyError>
|
func enableEncryption() async -> Result<Void, RoomProxyError>
|
||||||
|
|
||||||
func redact(_ eventID: String) async -> Result<Void, RoomProxyError>
|
func redact(_ eventID: String) async -> Result<Void, RoomProxyError>
|
||||||
|
|||||||
+11
-10
@@ -40,17 +40,18 @@ struct TimelineControllerFactory: TimelineControllerFactoryProtocol {
|
|||||||
|
|
||||||
func buildPinnedEventsTimelineController(roomProxy: JoinedRoomProxyProtocol,
|
func buildPinnedEventsTimelineController(roomProxy: JoinedRoomProxyProtocol,
|
||||||
timelineItemFactory: RoomTimelineItemFactoryProtocol,
|
timelineItemFactory: RoomTimelineItemFactoryProtocol,
|
||||||
mediaProvider: MediaProviderProtocol) async -> TimelineControllerProtocol? {
|
mediaProvider: MediaProviderProtocol) async -> Result<TimelineControllerProtocol, TimelineFactoryControllerError> {
|
||||||
guard let pinnedEventsTimeline = await roomProxy.pinnedEventsTimeline else {
|
switch await roomProxy.pinnedEventsTimeline() {
|
||||||
return nil
|
case .success(let timelineProxy):
|
||||||
|
return .success(TimelineController(roomProxy: roomProxy,
|
||||||
|
timelineProxy: timelineProxy,
|
||||||
|
initialFocussedEventID: nil,
|
||||||
|
timelineItemFactory: timelineItemFactory,
|
||||||
|
mediaProvider: mediaProvider,
|
||||||
|
appSettings: ServiceLocator.shared.settings))
|
||||||
|
case .failure(let error):
|
||||||
|
return .failure(.roomProxyError(error))
|
||||||
}
|
}
|
||||||
|
|
||||||
return TimelineController(roomProxy: roomProxy,
|
|
||||||
timelineProxy: pinnedEventsTimeline,
|
|
||||||
initialFocussedEventID: nil,
|
|
||||||
timelineItemFactory: timelineItemFactory,
|
|
||||||
mediaProvider: mediaProvider,
|
|
||||||
appSettings: ServiceLocator.shared.settings)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildMessageFilteredTimelineController(focus: TimelineFocus,
|
func buildMessageFilteredTimelineController(focus: TimelineFocus,
|
||||||
|
|||||||
+1
-1
@@ -26,7 +26,7 @@ protocol TimelineControllerFactoryProtocol {
|
|||||||
|
|
||||||
func buildPinnedEventsTimelineController(roomProxy: JoinedRoomProxyProtocol,
|
func buildPinnedEventsTimelineController(roomProxy: JoinedRoomProxyProtocol,
|
||||||
timelineItemFactory: RoomTimelineItemFactoryProtocol,
|
timelineItemFactory: RoomTimelineItemFactoryProtocol,
|
||||||
mediaProvider: MediaProviderProtocol) async -> TimelineControllerProtocol?
|
mediaProvider: MediaProviderProtocol) async -> Result<TimelineControllerProtocol, TimelineFactoryControllerError>
|
||||||
|
|
||||||
func buildMessageFilteredTimelineController(focus: TimelineFocus,
|
func buildMessageFilteredTimelineController(focus: TimelineFocus,
|
||||||
allowedMessageTypes: [TimelineAllowedMessageType],
|
allowedMessageTypes: [TimelineAllowedMessageType],
|
||||||
|
|||||||
@@ -30,7 +30,11 @@ class RoomScreenViewModelTests: XCTestCase {
|
|||||||
let roomProxyMock = JoinedRoomProxyMock(configuration)
|
let roomProxyMock = JoinedRoomProxyMock(configuration)
|
||||||
// setup a way to inject the mock of the pinned events timeline
|
// setup a way to inject the mock of the pinned events timeline
|
||||||
roomProxyMock.pinnedEventsTimelineClosure = {
|
roomProxyMock.pinnedEventsTimelineClosure = {
|
||||||
await timelineSubject.values.first()
|
guard let timeline = await timelineSubject.values.first() else {
|
||||||
|
fatalError()
|
||||||
|
}
|
||||||
|
|
||||||
|
return .success(timeline)
|
||||||
}
|
}
|
||||||
// setup the room proxy actions publisher
|
// setup the room proxy actions publisher
|
||||||
roomProxyMock.underlyingInfoPublisher = infoSubject.asCurrentValuePublisher()
|
roomProxyMock.underlyingInfoPublisher = infoSubject.asCurrentValuePublisher()
|
||||||
@@ -113,7 +117,7 @@ class RoomScreenViewModelTests: XCTestCase {
|
|||||||
pinnedTimelineProviderMock.itemProxies = [.event(.init(item: EventTimelineItem(configuration: .init(eventID: "test1")), uniqueID: .init("1"))),
|
pinnedTimelineProviderMock.itemProxies = [.event(.init(item: EventTimelineItem(configuration: .init(eventID: "test1")), uniqueID: .init("1"))),
|
||||||
.event(.init(item: EventTimelineItem(configuration: .init(eventID: "test2")), uniqueID: .init("2"))),
|
.event(.init(item: EventTimelineItem(configuration: .init(eventID: "test2")), uniqueID: .init("2"))),
|
||||||
.event(.init(item: EventTimelineItem(configuration: .init(eventID: "test3")), uniqueID: .init("3")))]
|
.event(.init(item: EventTimelineItem(configuration: .init(eventID: "test3")), uniqueID: .init("3")))]
|
||||||
roomProxyMock.underlyingPinnedEventsTimeline = pinnedTimelineMock
|
roomProxyMock.pinnedEventsTimelineReturnValue = .success(pinnedTimelineMock)
|
||||||
let viewModel = RoomScreenViewModel(clientProxy: ClientProxyMock(),
|
let viewModel = RoomScreenViewModel(clientProxy: ClientProxyMock(),
|
||||||
roomProxy: roomProxyMock,
|
roomProxy: roomProxyMock,
|
||||||
initialSelectedPinnedEventID: "test1",
|
initialSelectedPinnedEventID: "test1",
|
||||||
|
|||||||
Reference in New Issue
Block a user