diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index 47d5231db..0f17ccd44 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -3759,7 +3759,7 @@ repositoryURL = "https://github.com/matrix-org/matrix-rust-components-swift"; requirement = { kind = exactVersion; - version = "0.0.9-demo"; + version = "1.0.22-alpha"; }; }; 96495DD8554E2F39D3954354 /* XCRemoteSwiftPackageReference "posthog-ios" */ = { diff --git a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index c6b4d6dba..f1ddcafd1 100644 --- a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -86,8 +86,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/matrix-org/matrix-rust-components-swift", "state" : { - "revision" : "2645cfb64f3255f299a63af280b5172a6dd6602c", - "version" : "0.0.9-demo" + "revision" : "65d6f8a51367d5c411c1fec39402907f588fcd67", + "version" : "1.0.22-alpha" } }, { diff --git a/ElementX/Sources/Screens/HomeScreen/HomeScreenViewModel.swift b/ElementX/Sources/Screens/HomeScreen/HomeScreenViewModel.swift index b5752e769..b4034a34c 100644 --- a/ElementX/Sources/Screens/HomeScreen/HomeScreenViewModel.swift +++ b/ElementX/Sources/Screens/HomeScreen/HomeScreenViewModel.swift @@ -21,7 +21,8 @@ typealias HomeScreenViewModelType = StateStoreViewModel 0, - timestamp: timestamp ?? oldRoom?.timestamp, - lastMessage: summary.lastMessage ?? oldRoom?.lastMessage, - avatar: avatarImage ?? oldRoom?.avatar) - + let room = buildRoomForSummary(summary) + rooms.append(room) + newRoomsForIdentifiers[summary.id] = room + case .filled(let summary): + let room = buildRoomForSummary(summary) rooms.append(room) newRoomsForIdentifiers[summary.id] = room } @@ -192,6 +200,24 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol roomsForIdentifiers = newRoomsForIdentifiers } + private func buildRoomForSummary(_ summary: RoomSummaryDetails) -> HomeScreenRoom { + let oldRoom = roomsForIdentifiers[summary.id] + + let avatarImage = userSession.mediaProvider.imageFromURLString(summary.avatarURLString, avatarSize: .room(on: .home)) + + var timestamp: String? + if let lastMessageTimestamp = summary.lastMessageTimestamp { + timestamp = lastMessageTimestamp.formatted(date: .omitted, time: .shortened) + } + + return HomeScreenRoom(id: summary.id, + name: summary.name, + hasUnreads: summary.unreadNotificationCount > 0, + timestamp: timestamp ?? oldRoom?.timestamp, + lastMessage: summary.lastMessage ?? oldRoom?.lastMessage, + avatar: avatarImage ?? oldRoom?.avatar) + } + private func updateVisibleRange(visibleItemIdentifiers items: Set) { let result = items.compactMap { itemIdentifier in state.rooms.firstIndex { $0.id == itemIdentifier } @@ -205,6 +231,6 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol return } - userSession.clientProxy.roomSummaryProvider?.updateVisibleRange(lowerBound...upperBound) + visibleRoomsSummaryProvider?.updateVisibleRange(lowerBound...upperBound) } } diff --git a/ElementX/Sources/Services/Client/ClientProxy.swift b/ElementX/Sources/Services/Client/ClientProxy.swift index 6ce80c899..91159a93b 100644 --- a/ElementX/Sources/Services/Client/ClientProxy.swift +++ b/ElementX/Sources/Services/Client/ClientProxy.swift @@ -58,7 +58,9 @@ class ClientProxy: ClientProxyProtocol { private var slidingSyncObserverToken: StoppableSpawn? private var slidingSync: SlidingSync? - var roomSummaryProvider: RoomSummaryProviderProtocol? + var visibleRoomsSummaryProvider: RoomSummaryProviderProtocol? + + var allRoomsSummaryProvider: RoomSummaryProviderProtocol? deinit { // These need to be inlined instead of using stopSync() @@ -83,25 +85,40 @@ class ClientProxy: ClientProxyProtocol { do { let slidingSyncBuilder = try client.slidingSync().homeserver(url: ServiceLocator.shared.settings.slidingSyncProxyBaseURLString) - let slidingSyncView = try SlidingSyncViewBuilder() + let visibleRoomsView = try SlidingSyncViewBuilder() .timelineLimit(limit: 10) .requiredState(requiredState: [RequiredState(key: "m.room.avatar", value: ""), RequiredState(key: "m.room.encryption", value: "")]) - .name(name: "HomeScreenView") + .name(name: "CurrentlyVisibleRooms") .syncMode(mode: .selective) .addRange(from: 0, to: 20) .build() + + let allRoomsView = try SlidingSyncViewBuilder() + .noTimelineLimit() + .requiredState(requiredState: [RequiredState(key: "m.room.avatar", value: ""), + RequiredState(key: "m.room.encryption", value: "")]) + .name(name: "AllRooms") + .syncMode(mode: .growingFullSync) + .batchSize(batchSize: 20) + .build() let slidingSync = try slidingSyncBuilder - .addView(v: slidingSyncView) + .addView(v: visibleRoomsView) + // .addView(v: allRoomsView) // FIXME: Intentionally disabled as it doesn't work properly .withCommonExtensions() .coldCache(name: "ElementX") .build() - let slidingSyncViewProxy = SlidingSyncViewProxy(clientProxy: self, slidingSync: slidingSync, slidingSyncView: slidingSyncView) + let visibleRoomsViewProxy = SlidingSyncViewProxy(clientProxy: self, slidingSync: slidingSync, slidingSyncView: visibleRoomsView) - self.roomSummaryProvider = RoomSummaryProvider(slidingSyncViewProxy: slidingSyncViewProxy, - roomMessageFactory: RoomMessageFactory()) + 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 { @@ -286,7 +303,8 @@ class ClientProxy: ClientProxyProtocol { } fileprivate func didReceiveSlidingSyncUpdate(summary: UpdateSummary) { - roomSummaryProvider?.updateRoomsWithIdentifiers(summary.rooms) + visibleRoomsSummaryProvider?.updateRoomsWithIdentifiers(summary.rooms) + allRoomsSummaryProvider?.updateRoomsWithIdentifiers(summary.rooms) callbacks.send(.receivedSyncUpdate) } diff --git a/ElementX/Sources/Services/Client/ClientProxyProtocol.swift b/ElementX/Sources/Services/Client/ClientProxyProtocol.swift index fdf0769a4..a105d1145 100644 --- a/ElementX/Sources/Services/Client/ClientProxyProtocol.swift +++ b/ElementX/Sources/Services/Client/ClientProxyProtocol.swift @@ -71,7 +71,9 @@ protocol ClientProxyProtocol: AnyObject, MediaProxyProtocol { var restorationToken: RestorationToken? { get } - var roomSummaryProvider: RoomSummaryProviderProtocol? { get } + var visibleRoomsSummaryProvider: RoomSummaryProviderProtocol? { get } + + var allRoomsSummaryProvider: RoomSummaryProviderProtocol? { get } func startSync() diff --git a/ElementX/Sources/Services/Client/MockClientProxy.swift b/ElementX/Sources/Services/Client/MockClientProxy.swift index ae14c146d..0651b778c 100644 --- a/ElementX/Sources/Services/Client/MockClientProxy.swift +++ b/ElementX/Sources/Services/Client/MockClientProxy.swift @@ -27,11 +27,13 @@ class MockClientProxy: ClientProxyProtocol { let homeserver = "" let restorationToken: RestorationToken? = nil - var roomSummaryProvider: RoomSummaryProviderProtocol? = MockRoomSummaryProvider() + var visibleRoomsSummaryProvider: RoomSummaryProviderProtocol? = MockRoomSummaryProvider() + + var allRoomsSummaryProvider: RoomSummaryProviderProtocol? = MockRoomSummaryProvider() internal init(userIdentifier: String, roomSummaryProvider: RoomSummaryProviderProtocol? = MockRoomSummaryProvider()) { self.userIdentifier = userIdentifier - self.roomSummaryProvider = roomSummaryProvider + visibleRoomsSummaryProvider = roomSummaryProvider } func startSync() { } diff --git a/ElementX/Sources/Services/Room/Messages/RoomMessageProtocol.swift b/ElementX/Sources/Services/Room/Messages/RoomMessageProtocol.swift index 7a70fe473..362b96f42 100644 --- a/ElementX/Sources/Services/Room/Messages/RoomMessageProtocol.swift +++ b/ElementX/Sources/Services/Room/Messages/RoomMessageProtocol.swift @@ -20,5 +20,5 @@ protocol RoomMessageProtocol { var id: String { get } var body: String { get } var sender: String { get } - var originServerTs: Date { get } + var timestamp: Date { get } } diff --git a/ElementX/Sources/Services/Room/RoomMessageFactory.swift b/ElementX/Sources/Services/Room/RoomMessageFactory.swift index 2d6d8f9e7..ca9d3c0df 100644 --- a/ElementX/Sources/Services/Room/RoomMessageFactory.swift +++ b/ElementX/Sources/Services/Room/RoomMessageFactory.swift @@ -21,7 +21,7 @@ struct SomeRoomMessage: RoomMessageProtocol { let id: String let body: String let sender: String - let originServerTs: Date + let timestamp: Date } struct RoomMessageFactory: RoomMessageFactoryProtocol { @@ -29,6 +29,6 @@ struct RoomMessageFactory: RoomMessageFactoryProtocol { SomeRoomMessage(id: eventItemProxy.id, body: eventItemProxy.body ?? "", sender: eventItemProxy.sender, - originServerTs: eventItemProxy.originServerTs) + timestamp: eventItemProxy.timestamp) } } diff --git a/ElementX/Sources/Services/Room/RoomSummary/RoomSummaryProvider.swift b/ElementX/Sources/Services/Room/RoomSummary/RoomSummaryProvider.swift index 1416cb520..24f89491c 100644 --- a/ElementX/Sources/Services/Room/RoomSummary/RoomSummaryProvider.swift +++ b/ElementX/Sources/Services/Room/RoomSummary/RoomSummaryProvider.swift @@ -63,9 +63,9 @@ class RoomSummaryProvider: RoomSummaryProviderProtocol { func updateRoomsWithIdentifiers(_ identifiers: [String]) { #warning("This is a valid check but Rust doesn't set it correctly for selective ranged syncs") -// guard statePublisher.value == .live else { -// return -// } + // guard statePublisher.value == .live else { + // return + // } var changes = [CollectionDifference.Change]() for identifier in identifiers { @@ -136,11 +136,14 @@ class RoomSummaryProvider: RoomSummaryProviderProtocol { var lastMessageTimestamp: Date? if let latestRoomMessage = room.latestRoomMessage() { let lastMessage = roomMessageFactory.buildRoomMessageFrom(EventTimelineItemProxy(item: latestRoomMessage)) - if let lastMessageSender = try? AttributedString(markdown: "**\(lastMessage.sender)**") { - // Don't include the message body in the markdown otherwise it makes tappable links. - attributedLastMessage = lastMessageSender + ": " + AttributedString(lastMessage.body) - } - lastMessageTimestamp = lastMessage.originServerTs + + #warning("Intentionally remove the sender mxid from the room list for now") + // if let lastMessageSender = try? AttributedString(markdown: "**\(lastMessage.sender)**") { + // // Don't include the message body in the markdown otherwise it makes tappable links. + // attributedLastMessage = lastMessageSender + ": " + AttributedString(lastMessage.body) + // } + attributedLastMessage = AttributedString(lastMessage.body) + lastMessageTimestamp = lastMessage.timestamp } return .filled(details: RoomSummaryDetails(id: room.roomId(), diff --git a/ElementX/Sources/Services/Timeline/TimeLineItemContent/MessageTimelineItem.swift b/ElementX/Sources/Services/Timeline/TimeLineItemContent/MessageTimelineItem.swift index 032dae273..2f2334329 100644 --- a/ElementX/Sources/Services/Timeline/TimeLineItemContent/MessageTimelineItem.swift +++ b/ElementX/Sources/Services/Timeline/TimeLineItemContent/MessageTimelineItem.swift @@ -49,7 +49,7 @@ struct MessageTimelineItem { case .transactionId: return .sending case .eventId: - return .sent(elapsedTime: Date().timeIntervalSince1970 - originServerTs.timeIntervalSince1970) + return .sent(elapsedTime: Date().timeIntervalSince1970 - timestamp.timeIntervalSince1970) } } @@ -77,12 +77,8 @@ struct MessageTimelineItem { item.sender() } - var originServerTs: Date { - if let timestamp = item.originServerTs() { - return Date(timeIntervalSince1970: TimeInterval(timestamp / 1000)) - } else { - return .now - } + var timestamp: Date { + Date(timeIntervalSince1970: TimeInterval(item.timestamp() / 1000)) } } diff --git a/ElementX/Sources/Services/Timeline/TimelineItemProxy.swift b/ElementX/Sources/Services/Timeline/TimelineItemProxy.swift index 508e7f689..edcc842e6 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItemProxy.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItemProxy.swift @@ -91,12 +91,8 @@ struct EventTimelineItemProxy: CustomDebugStringConvertible { item.reactions() } - var originServerTs: Date { - if let timestamp = item.originServerTs() { - return Date(timeIntervalSince1970: TimeInterval(timestamp / 1000)) - } else { - return .now - } + var timestamp: Date { + Date(timeIntervalSince1970: TimeInterval(item.timestamp() / 1000)) } // MARK: - CustomDebugStringConvertible diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemFactory.swift b/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemFactory.swift index 9af3aa977..84a9152ef 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemFactory.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemFactory.swift @@ -98,7 +98,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol { return EncryptedRoomTimelineItem(id: eventItemProxy.id, text: ElementL10n.encryptionInformationDecryptionError, encryptionType: encryptionType, - timestamp: eventItemProxy.originServerTs.formatted(date: .omitted, time: .shortened), + timestamp: eventItemProxy.timestamp.formatted(date: .omitted, time: .shortened), inGroupState: inGroupState, isOutgoing: isOutgoing, isEditable: eventItemProxy.isEditable, @@ -115,7 +115,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol { _ avatarImage: UIImage?) -> RoomTimelineItemProtocol { RedactedRoomTimelineItem(id: eventItemProxy.id, text: ElementL10n.eventRedacted, - timestamp: eventItemProxy.originServerTs.formatted(date: .omitted, time: .shortened), + timestamp: eventItemProxy.timestamp.formatted(date: .omitted, time: .shortened), inGroupState: inGroupState, isOutgoing: isOutgoing, isEditable: eventItemProxy.isEditable, @@ -136,7 +136,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol { return TextRoomTimelineItem(id: eventItemProxy.id, text: eventItemProxy.body ?? "", attributedComponents: attributedComponents, - timestamp: eventItemProxy.originServerTs.formatted(date: .omitted, time: .shortened), + timestamp: eventItemProxy.timestamp.formatted(date: .omitted, time: .shortened), inGroupState: inGroupState, isOutgoing: isOutgoing, isEditable: eventItemProxy.isEditable, @@ -158,7 +158,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol { return TextRoomTimelineItem(id: message.id, text: message.body, attributedComponents: attributedComponents, - timestamp: message.originServerTs.formatted(date: .omitted, time: .shortened), + timestamp: message.timestamp.formatted(date: .omitted, time: .shortened), inGroupState: inGroupState, isOutgoing: isOutgoing, isEditable: message.isEditable, @@ -183,7 +183,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol { return ImageRoomTimelineItem(id: message.id, text: message.body, - timestamp: message.originServerTs.formatted(date: .omitted, time: .shortened), + timestamp: message.timestamp.formatted(date: .omitted, time: .shortened), inGroupState: inGroupState, isOutgoing: isOutgoing, isEditable: message.isEditable, @@ -214,7 +214,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol { return VideoRoomTimelineItem(id: message.id, text: message.body, - timestamp: message.originServerTs.formatted(date: .omitted, time: .shortened), + timestamp: message.timestamp.formatted(date: .omitted, time: .shortened), inGroupState: inGroupState, isOutgoing: isOutgoing, isEditable: message.isEditable, @@ -241,7 +241,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol { _ avatarImage: UIImage?) -> RoomTimelineItemProtocol { FileRoomTimelineItem(id: message.id, text: message.body, - timestamp: message.originServerTs.formatted(date: .omitted, time: .shortened), + timestamp: message.timestamp.formatted(date: .omitted, time: .shortened), inGroupState: inGroupState, isOutgoing: isOutgoing, isEditable: message.isEditable, @@ -266,7 +266,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol { return NoticeRoomTimelineItem(id: message.id, text: message.body, attributedComponents: attributedComponents, - timestamp: message.originServerTs.formatted(date: .omitted, time: .shortened), + timestamp: message.timestamp.formatted(date: .omitted, time: .shortened), inGroupState: inGroupState, isOutgoing: isOutgoing, isEditable: message.isEditable, @@ -289,7 +289,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol { return EmoteRoomTimelineItem(id: message.id, text: message.body, attributedComponents: attributedComponents, - timestamp: message.originServerTs.formatted(date: .omitted, time: .shortened), + timestamp: message.timestamp.formatted(date: .omitted, time: .shortened), inGroupState: inGroupState, isOutgoing: isOutgoing, isEditable: message.isEditable, diff --git a/project.yml b/project.yml index 5f6132c5f..7fd736196 100644 --- a/project.yml +++ b/project.yml @@ -40,7 +40,7 @@ include: packages: MatrixRustSDK: url: https://github.com/matrix-org/matrix-rust-components-swift - exactVersion: 0.0.9-demo + exactVersion: 1.0.22-alpha # path: ../matrix-rust-components-swift DesignKit: path: ./