From 522fbcb08454a1c6611bce0c69a341b79f6992dd Mon Sep 17 00:00:00 2001 From: Doug Date: Thu, 25 Apr 2024 18:32:09 +0100 Subject: [PATCH] Update the SDK and enable event permalinks. --- ElementX.xcodeproj/project.pbxproj | 2 +- .../xcshareddata/swiftpm/Package.resolved | 4 +- .../Application/Navigation/AppRoutes.swift | 6 +- ElementX/Sources/Mocks/RoomProxyMock.swift | 2 +- .../RoomPollsHistoryScreenViewModel.swift | 2 +- .../RoomScreenInteractionHandler.swift | 2 +- .../RoomScreen/RoomScreenViewModel.swift | 4 +- .../HighlightedTimelineItemModifier.swift | 3 + .../Sources/Services/Client/ClientProxy.swift | 2 +- .../Sources/Services/Room/RoomProxy.swift | 15 +++-- .../RoomTimelineProviderProtocol.swift | 6 +- .../MockRoomTimelineController.swift | 8 +-- .../RoomTimelineController.swift | 4 +- .../Other/EncryptedRoomTimelineItem.swift | 7 ++- .../RoomTimelineItemFactory.swift | 10 +++- .../Services/Timeline/TimelineProxy.swift | 55 +++++++++---------- project.yml | 2 +- 17 files changed, 71 insertions(+), 63 deletions(-) diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index 550670d454..452690d998 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -7332,7 +7332,7 @@ repositoryURL = "https://github.com/matrix-org/matrix-rust-components-swift"; requirement = { kind = exactVersion; - version = 1.1.60; + version = 1.1.61; }; }; 821C67C9A7F8CC3FD41B28B4 /* XCRemoteSwiftPackageReference "emojibase-bindings" */ = { diff --git a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 5ef386cddb..38e7585201 100644 --- a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -139,8 +139,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/matrix-org/matrix-rust-components-swift", "state" : { - "revision" : "33cad4cb0c95a39bacdd8845d81da17e8a221481", - "version" : "1.1.60" + "revision" : "8def4c4c5cc5a95699431a509f1dcd55ec9b59d2", + "version" : "1.1.61" } }, { diff --git a/ElementX/Sources/Application/Navigation/AppRoutes.swift b/ElementX/Sources/Application/Navigation/AppRoutes.swift index 4dc1c729e4..abffb1f22c 100644 --- a/ElementX/Sources/Application/Navigation/AppRoutes.swift +++ b/ElementX/Sources/Application/Navigation/AppRoutes.swift @@ -142,11 +142,9 @@ struct MatrixPermalinkParser: URLParser { case .user(let id): return .userProfile(userID: id) case .eventOnRoomId(let roomID, let eventID): - // return .event(roomID: roomID, eventID: eventID) - return nil + return .event(roomID: roomID, eventID: eventID) case .eventOnRoomAlias(let alias, let eventID): - // return .eventOnRoomAlias(alias: alias, eventID: eventID) - return nil + return .eventOnRoomAlias(alias: alias, eventID: eventID) default: return nil } diff --git a/ElementX/Sources/Mocks/RoomProxyMock.swift b/ElementX/Sources/Mocks/RoomProxyMock.swift index 9974bb8fce..9de3957f48 100644 --- a/ElementX/Sources/Mocks/RoomProxyMock.swift +++ b/ElementX/Sources/Mocks/RoomProxyMock.swift @@ -44,7 +44,7 @@ struct RoomProxyMockConfiguration { mock.underlyingActions = Empty(completeImmediately: false).eraseToAnyPublisher() let timelineProvider = RoomTimelineProviderMock() - timelineProvider.paginationState = .init(backward: timelineStartReached ? .timelineStartReached : .idle, forward: .timelineStartReached) + timelineProvider.paginationState = .init(backward: timelineStartReached ? .timelineEndReached : .idle, forward: .timelineEndReached) timelineProvider.underlyingMembershipChangePublisher = PassthroughSubject().eraseToAnyPublisher() mock.underlyingTimelineProvider = timelineProvider return mock diff --git a/ElementX/Sources/Screens/RoomPollsHistoryScreen/RoomPollsHistoryScreenViewModel.swift b/ElementX/Sources/Screens/RoomPollsHistoryScreen/RoomPollsHistoryScreenViewModel.swift index 2e5cadc8a4..1fabb99391 100644 --- a/ElementX/Sources/Screens/RoomPollsHistoryScreen/RoomPollsHistoryScreenViewModel.swift +++ b/ElementX/Sources/Screens/RoomPollsHistoryScreen/RoomPollsHistoryScreenViewModel.swift @@ -83,7 +83,7 @@ class RoomPollsHistoryScreenViewModel: RoomPollsHistoryScreenViewModelType, Room case .updatedTimelineItems: self.updatePollsList(filter: state.bindings.filter) case .paginationState(let paginationState): - let canBackPaginate = paginationState.backward != .timelineStartReached + let canBackPaginate = paginationState.backward != .timelineEndReached if self.state.canBackPaginate != canBackPaginate { self.state.canBackPaginate = canBackPaginate } diff --git a/ElementX/Sources/Screens/RoomScreen/RoomScreenInteractionHandler.swift b/ElementX/Sources/Screens/RoomScreen/RoomScreenInteractionHandler.swift index 74c460f3f8..e9dd8cbc1d 100644 --- a/ElementX/Sources/Screens/RoomScreen/RoomScreenInteractionHandler.swift +++ b/ElementX/Sources/Screens/RoomScreen/RoomScreenInteractionHandler.swift @@ -130,7 +130,7 @@ class RoomScreenInteractionHandler { if let encryptedItem = timelineItem as? EncryptedRoomTimelineItem { switch encryptedItem.encryptionType { - case .megolmV1AesSha2(let sessionID): + case .megolmV1AesSha2(let sessionID, _): debugActions.append(.retryDecryption(sessionID: sessionID)) default: break diff --git a/ElementX/Sources/Screens/RoomScreen/RoomScreenViewModel.swift b/ElementX/Sources/Screens/RoomScreen/RoomScreenViewModel.swift index 4a408b0ccd..ebad853d1c 100644 --- a/ElementX/Sources/Screens/RoomScreen/RoomScreenViewModel.swift +++ b/ElementX/Sources/Screens/RoomScreen/RoomScreenViewModel.swift @@ -234,7 +234,7 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol switch await timelineController.focusOnEvent(eventID, timelineSize: Constants.detachedTimelineSize) { case .success: state.timelineViewState.focussedEventID = eventID - case .failure(let error): + case .failure: MXLog.error("Failed to focus on event \(eventID)") displayError(.toast(L10n.commonFailed)) } @@ -475,7 +475,7 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol break } - if state.timelineViewState.paginationState.forward == .timelineStartReached { + if state.timelineViewState.paginationState.forward == .timelineEndReached { focusLive() } diff --git a/ElementX/Sources/Screens/RoomScreen/View/Timeline/HighlightedTimelineItemModifier.swift b/ElementX/Sources/Screens/RoomScreen/View/Timeline/HighlightedTimelineItemModifier.swift index a8a3da22f6..e393883ca3 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/Timeline/HighlightedTimelineItemModifier.swift +++ b/ElementX/Sources/Screens/RoomScreen/View/Timeline/HighlightedTimelineItemModifier.swift @@ -47,6 +47,7 @@ private struct HighlightedTimelineItemModifier: ViewModifier { } } +// swiftlint:disable line_length struct HighlightedTimelineItemModifier_Previews: PreviewProvider, TestablePreview { static var previews: some View { ScrollView { @@ -83,3 +84,5 @@ struct HighlightedTimelineItemModifier_Previews: PreviewProvider, TestablePrevie } } } + +// swiftlint:enable line_length diff --git a/ElementX/Sources/Services/Client/ClientProxy.swift b/ElementX/Sources/Services/Client/ClientProxy.swift index c5c93263c6..82beba59aa 100644 --- a/ElementX/Sources/Services/Client/ClientProxy.swift +++ b/ElementX/Sources/Services/Client/ClientProxy.swift @@ -817,7 +817,7 @@ class ClientProxy: ClientProxyProtocol { do { let roomListItem = try roomListService?.room(roomId: identifier) if roomListItem?.isTimelineInitialized() == false { - try await roomListItem?.initTimeline(eventTypeFilter: eventFilters) + try await roomListItem?.initTimeline(eventTypeFilter: eventFilters, internalIdPrefix: nil) } let fullRoom = try await roomListItem?.fullRoom() diff --git a/ElementX/Sources/Services/Room/RoomProxy.swift b/ElementX/Sources/Services/Room/RoomProxy.swift index 93894273ed..848550ca6e 100644 --- a/ElementX/Sources/Services/Room/RoomProxy.swift +++ b/ElementX/Sources/Services/Room/RoomProxy.swift @@ -160,14 +160,13 @@ class RoomProxy: RoomProxyProtocol { } func timelineFocusedOnEvent(eventID: String, numberOfEvents: UInt16) async -> Result { - .failure(.sdkError(RoomProxyMockError.generic)) -// do { -// let timeline = try await room.timelineFocusedOnEvent(eventId: eventID, numContextEvents: numberOfEvents, internalIdPrefix: UUID().uuidString) -// return .success(TimelineProxy(timeline: timeline, isLive: false)) -// } catch { -// MXLog.error("Failed to create a timeline focussed on: \(eventID) with error: \(error)") -// return .failure(.sdkError(error)) -// } + do { + let timeline = try await room.timelineFocusedOnEvent(eventId: eventID, numContextEvents: numberOfEvents, internalIdPrefix: UUID().uuidString) + return .success(TimelineProxy(timeline: timeline, isLive: false)) + } catch { + MXLog.error("Failed to create a timeline focussed on: \(eventID) with error: \(error)") + return .failure(.sdkError(error)) + } } func redact(_ eventID: String) async -> Result { diff --git a/ElementX/Sources/Services/Timeline/RoomTimelineProviderProtocol.swift b/ElementX/Sources/Services/Timeline/RoomTimelineProviderProtocol.swift index 896b709c65..6a53721c76 100644 --- a/ElementX/Sources/Services/Timeline/RoomTimelineProviderProtocol.swift +++ b/ElementX/Sources/Services/Timeline/RoomTimelineProviderProtocol.swift @@ -19,9 +19,9 @@ import Foundation import MatrixRustSDK struct PaginationState: Equatable { - static var `default` = PaginationState(backward: .idle, forward: .timelineStartReached) - let backward: BackPaginationStatus - let forward: BackPaginationStatus + static var `default` = PaginationState(backward: .idle, forward: .timelineEndReached) + let backward: PaginationStatus + let forward: PaginationStatus } @MainActor diff --git a/ElementX/Sources/Services/Timeline/TimelineController/MockRoomTimelineController.swift b/ElementX/Sources/Services/Timeline/TimelineController/MockRoomTimelineController.swift index 9020884490..66df8f70bd 100644 --- a/ElementX/Sources/Services/Timeline/TimelineController/MockRoomTimelineController.swift +++ b/ElementX/Sources/Services/Timeline/TimelineController/MockRoomTimelineController.swift @@ -36,7 +36,7 @@ class MockRoomTimelineController: RoomTimelineControllerProtocol { private var client: UITestsSignalling.Client? init(listenForSignals: Bool = false) { - callbacks.send(.paginationState(PaginationState(backward: .idle, forward: .timelineStartReached))) + callbacks.send(.paginationState(PaginationState(backward: .idle, forward: .timelineEndReached))) callbacks.send(.isLive(true)) guard listenForSignals else { return } @@ -62,7 +62,7 @@ class MockRoomTimelineController: RoomTimelineControllerProtocol { } func paginateBackwards(requestSize: UInt16) async -> Result { - callbacks.send(.paginationState(PaginationState(backward: .paginating, forward: .timelineStartReached))) + callbacks.send(.paginationState(PaginationState(backward: .paginating, forward: .timelineEndReached))) if client == nil { try? await simulateBackPagination() @@ -173,8 +173,8 @@ class MockRoomTimelineController: RoomTimelineControllerProtocol { /// Prepends the next chunk of items to the `timelineItems` array. private func simulateBackPagination() async throws { defer { - callbacks.send(.paginationState(PaginationState(backward: backPaginationResponses.isEmpty ? .timelineStartReached : .idle, - forward: .timelineStartReached))) + callbacks.send(.paginationState(PaginationState(backward: backPaginationResponses.isEmpty ? .timelineEndReached : .idle, + forward: .timelineEndReached))) } guard !backPaginationResponses.isEmpty else { return } diff --git a/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineController.swift b/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineController.swift index 93deae4d69..c9d5f6dd10 100644 --- a/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineController.swift +++ b/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineController.swift @@ -321,7 +321,7 @@ class RoomTimelineController: RoomTimelineControllerProtocol { // Check if we need to add anything to the top of the timeline. switch paginationState.backward { - case .timelineStartReached: + case .timelineEndReached: if !roomProxy.isEncryptedOneToOneRoom { let timelineStart = TimelineStartRoomTimelineItem(name: roomProxy.name) newTimelineItems.insert(timelineStart, at: 0) @@ -335,7 +335,7 @@ class RoomTimelineController: RoomTimelineControllerProtocol { switch paginationState.forward { case .paginating: newTimelineItems.insert(PaginationIndicatorRoomTimelineItem(position: .end), at: newTimelineItems.count) - case .idle, .timelineStartReached: + case .idle, .timelineEndReached: break } diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/EncryptedRoomTimelineItem.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/EncryptedRoomTimelineItem.swift index a253acf408..fd545c9c18 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/EncryptedRoomTimelineItem.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/EncryptedRoomTimelineItem.swift @@ -18,11 +18,16 @@ import UIKit struct EncryptedRoomTimelineItem: EventBasedTimelineItemProtocol, Equatable { enum EncryptionType: Hashable { - case megolmV1AesSha2(sessionId: String) + case megolmV1AesSha2(sessionID: String, cause: UTDCause) case olmV1Curve25519AesSha2(senderKey: String) case unknown } + enum UTDCause: Hashable { + case membership + case unknown + } + let id: TimelineItemIdentifier let body: String let encryptionType: EncryptionType diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemFactory.swift b/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemFactory.swift index 893000b44a..3faca14c29 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemFactory.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemFactory.swift @@ -162,11 +162,15 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol { _ isOutgoing: Bool) -> RoomTimelineItemProtocol { var encryptionType = EncryptedRoomTimelineItem.EncryptionType.unknown switch encryptedMessage { - case .megolmV1AesSha2(let sessionId): - encryptionType = .megolmV1AesSha2(sessionId: sessionId) + case .megolmV1AesSha2(let sessionID, let cause): + let cause: EncryptedRoomTimelineItem.UTDCause = switch cause { + case .unknown: .unknown + case .membership: .membership + } + encryptionType = .megolmV1AesSha2(sessionID: sessionID, cause: cause) case .olmV1Curve25519AesSha2(let senderKey): encryptionType = .olmV1Curve25519AesSha2(senderKey: senderKey) - default: + case .unknown: break } diff --git a/ElementX/Sources/Services/Timeline/TimelineProxy.swift b/ElementX/Sources/Services/Timeline/TimelineProxy.swift index e43e72414e..a1bdf5544c 100644 --- a/ElementX/Sources/Services/Timeline/TimelineProxy.swift +++ b/ElementX/Sources/Services/Timeline/TimelineProxy.swift @@ -31,8 +31,8 @@ final class TimelineProxy: TimelineProxyProtocol { // periphery:ignore - retaining purpose private var timelineListener: RoomTimelineListener? - private let backPaginationStatusSubject = CurrentValueSubject(.idle) - private let forwardPaginationStatusSubject = CurrentValueSubject(.timelineStartReached) + private let backPaginationStatusSubject = CurrentValueSubject(.idle) + private let forwardPaginationStatusSubject = CurrentValueSubject(.timelineEndReached) private let timelineUpdatesSubject = PassthroughSubject<[TimelineDiff], Never>() private let actionsSubject = PassthroughSubject() @@ -150,7 +150,7 @@ final class TimelineProxy: TimelineProxyProtocol { MXLog.info("Paginating backwards") do { - _ = try timeline.paginateBackwards(opts: .simpleRequest(eventLimit: requestSize, waitForToken: true)) + _ = try await timeline.paginateBackwards(numEvents: requestSize) MXLog.info("Finished paginating backwards") return .success(()) @@ -161,28 +161,27 @@ final class TimelineProxy: TimelineProxyProtocol { } func paginateForwards(requestSize: UInt16) async -> Result { - .failure(.failedPaginatingBackwards) // This extra check is necessary as forwards pagination status doesn't support subscribing. // We need it to make sure we send a valid status after a failure. -// guard forwardPaginationStatusSubject.value == .idle else { -// MXLog.error("Attempting to paginate forwards when already at the end.") -// return .failure(.failedPaginatingBackwards) -// } -// -// MXLog.info("Paginating forwards") -// forwardPaginationStatusSubject.send(.paginating) -// -// do { -// let timelineEndReached = try await timeline.paginateForwards(numEvents: requestSize) -// MXLog.info("Finished paginating forwards") -// -// forwardPaginationStatusSubject.send(timelineEndReached ? .timelineEndReached : .idle) -// return .success(()) -// } catch { -// MXLog.error("Failed paginating forwards with error: \(error)") -// forwardPaginationStatusSubject.send(.idle) -// return .failure(.failedPaginatingBackwards) -// } + guard forwardPaginationStatusSubject.value == .idle else { + MXLog.error("Attempting to paginate forwards when already at the end.") + return .failure(.failedPaginatingBackwards) + } + + MXLog.info("Paginating forwards") + forwardPaginationStatusSubject.send(.paginating) + + do { + let timelineEndReached = try await timeline.focusedPaginateForwards(numEvents: 16) + MXLog.info("Finished paginating forwards") + + forwardPaginationStatusSubject.send(timelineEndReached ? .timelineEndReached : .idle) + return .success(()) + } catch { + MXLog.error("Failed paginating forwards with error: \(error)") + forwardPaginationStatusSubject.send(.idle) + return .failure(.failedPaginatingBackwards) + } } func retryDecryption(for sessionID: String) async { @@ -560,7 +559,7 @@ final class TimelineProxy: TimelineProxyProtocol { } // Forward pagination doesn't support observation, set the initial state ourself. - forwardPaginationStatusSubject.send(isLive ? .timelineStartReached : .idle) + forwardPaginationStatusSubject.send(isLive ? .timelineEndReached : .idle) } } @@ -576,14 +575,14 @@ private final class RoomTimelineListener: TimelineListener { } } -private final class RoomPaginationStatusListener: BackPaginationStatusListener { - private let onUpdateClosure: (BackPaginationStatus) -> Void +private final class RoomPaginationStatusListener: PaginationStatusListener { + private let onUpdateClosure: (PaginationStatus) -> Void - init(_ onUpdateClosure: @escaping (BackPaginationStatus) -> Void) { + init(_ onUpdateClosure: @escaping (PaginationStatus) -> Void) { self.onUpdateClosure = onUpdateClosure } - func onUpdate(status: BackPaginationStatus) { + func onUpdate(status: PaginationStatus) { onUpdateClosure(status) } } diff --git a/project.yml b/project.yml index 4e0dba58da..c3694145cf 100644 --- a/project.yml +++ b/project.yml @@ -49,7 +49,7 @@ packages: # Element/Matrix dependencies MatrixRustSDK: url: https://github.com/matrix-org/matrix-rust-components-swift - exactVersion: 1.1.60 + exactVersion: 1.1.61 # path: ../matrix-rust-sdk Compound: url: https://github.com/element-hq/compound-ios