From 994dbb884c509e34526af163d356a79fbc4bdc45 Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Tue, 17 Dec 2024 11:36:52 +0200 Subject: [PATCH 1/2] Automatically retry decryptions in the active room when the app becomes active again just in case the NSE received keys we're not aware of. --- .../Mocks/Generated/GeneratedMocks.swift | 32 +++++++++---------- .../RoomScreen/RoomScreenViewModel.swift | 8 +++++ .../Timeline/TimelineInteractionHandler.swift | 2 +- .../MockRoomTimelineController.swift | 2 +- .../RoomTimelineController.swift | 4 +-- .../RoomTimelineControllerProtocol.swift | 2 +- .../Services/Timeline/TimelineProxy.swift | 10 +++--- .../Timeline/TimelineProxyProtocol.swift | 8 ++++- 8 files changed, 42 insertions(+), 26 deletions(-) diff --git a/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift b/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift index 1a8aa5b5ab..8ecff22364 100644 --- a/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift +++ b/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift @@ -14076,15 +14076,15 @@ class TimelineProxyMock: TimelineProxyProtocol { } //MARK: - retryDecryption - var retryDecryptionForUnderlyingCallsCount = 0 - var retryDecryptionForCallsCount: Int { + var retryDecryptionSessionIDsUnderlyingCallsCount = 0 + var retryDecryptionSessionIDsCallsCount: Int { get { if Thread.isMainThread { - return retryDecryptionForUnderlyingCallsCount + return retryDecryptionSessionIDsUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = retryDecryptionForUnderlyingCallsCount + returnValue = retryDecryptionSessionIDsUnderlyingCallsCount } return returnValue! @@ -14092,28 +14092,28 @@ class TimelineProxyMock: TimelineProxyProtocol { } set { if Thread.isMainThread { - retryDecryptionForUnderlyingCallsCount = newValue + retryDecryptionSessionIDsUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - retryDecryptionForUnderlyingCallsCount = newValue + retryDecryptionSessionIDsUnderlyingCallsCount = newValue } } } } - var retryDecryptionForCalled: Bool { - return retryDecryptionForCallsCount > 0 + var retryDecryptionSessionIDsCalled: Bool { + return retryDecryptionSessionIDsCallsCount > 0 } - var retryDecryptionForReceivedSessionID: String? - var retryDecryptionForReceivedInvocations: [String] = [] - var retryDecryptionForClosure: ((String) async -> Void)? + var retryDecryptionSessionIDsReceivedSessionIDs: [String]? + var retryDecryptionSessionIDsReceivedInvocations: [[String]?] = [] + var retryDecryptionSessionIDsClosure: (([String]?) async -> Void)? - func retryDecryption(for sessionID: String) async { - retryDecryptionForCallsCount += 1 - retryDecryptionForReceivedSessionID = sessionID + func retryDecryption(sessionIDs: [String]?) async { + retryDecryptionSessionIDsCallsCount += 1 + retryDecryptionSessionIDsReceivedSessionIDs = sessionIDs DispatchQueue.main.async { - self.retryDecryptionForReceivedInvocations.append(sessionID) + self.retryDecryptionSessionIDsReceivedInvocations.append(sessionIDs) } - await retryDecryptionForClosure?(sessionID) + await retryDecryptionSessionIDsClosure?(sessionIDs) } //MARK: - paginateBackwards diff --git a/ElementX/Sources/Screens/RoomScreen/RoomScreenViewModel.swift b/ElementX/Sources/Screens/RoomScreen/RoomScreenViewModel.swift index e81eed4057..93f9422f8d 100644 --- a/ElementX/Sources/Screens/RoomScreen/RoomScreenViewModel.swift +++ b/ElementX/Sources/Screens/RoomScreen/RoomScreenViewModel.swift @@ -196,6 +196,14 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol .throttle(for: .milliseconds(100), scheduler: DispatchQueue.main, latest: true) .weakAssign(to: \.state.unseenKnockRequests, on: self) .store(in: &cancellables) + + NotificationCenter.default.publisher(for: UIApplication.didBecomeActiveNotification) + .sink { [weak self] _ in + Task { + await self?.roomProxy.timeline.retryDecryption() + } + } + .store(in: &cancellables) } private func processIdentityStatusChanges(_ changes: [IdentityStatusChange]) async { diff --git a/ElementX/Sources/Screens/Timeline/TimelineInteractionHandler.swift b/ElementX/Sources/Screens/Timeline/TimelineInteractionHandler.swift index 0dfd0d328f..87cd6be5a6 100644 --- a/ElementX/Sources/Screens/Timeline/TimelineInteractionHandler.swift +++ b/ElementX/Sources/Screens/Timeline/TimelineInteractionHandler.swift @@ -158,7 +158,7 @@ class TimelineInteractionHandler { MXLog.info("Showing debug info for \(eventTimelineItem.id)") actionsSubject.send(.showDebugInfo(debugInfo)) case .retryDecryption(let sessionID): - Task { await timelineController.retryDecryption(for: sessionID) } + Task { await timelineController.retryDecryption(sessionIDs: [sessionID]) } case .report: actionsSubject.send(.displayReportContent(itemID: itemID, senderID: eventTimelineItem.sender.id)) case .react: diff --git a/ElementX/Sources/Services/Timeline/TimelineController/MockRoomTimelineController.swift b/ElementX/Sources/Services/Timeline/TimelineController/MockRoomTimelineController.swift index eb34a23545..9c039f9656 100644 --- a/ElementX/Sources/Services/Timeline/TimelineController/MockRoomTimelineController.swift +++ b/ElementX/Sources/Services/Timeline/TimelineController/MockRoomTimelineController.swift @@ -139,7 +139,7 @@ class MockRoomTimelineController: RoomTimelineControllerProtocol { nil } - func retryDecryption(for sessionID: String) async { } + func retryDecryption(sessionIDs: [String]?) async { } func eventTimestamp(for itemID: TimelineItemIdentifier) -> Date? { timelineItemsTimestamp[itemID] ?? .now diff --git a/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineController.swift b/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineController.swift index 218cfb198a..098d481a7c 100644 --- a/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineController.swift +++ b/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineController.swift @@ -356,8 +356,8 @@ class RoomTimelineController: RoomTimelineControllerProtocol { return nil } - func retryDecryption(for sessionID: String) async { - await activeTimeline.retryDecryption(for: sessionID) + func retryDecryption(sessionIDs: [String]?) async { + await activeTimeline.retryDecryption(sessionIDs: sessionIDs) } // MARK: - Private diff --git a/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineControllerProtocol.swift b/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineControllerProtocol.swift index 1aa9e0a063..5851cafb39 100644 --- a/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineControllerProtocol.swift +++ b/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineControllerProtocol.swift @@ -82,7 +82,7 @@ protocol RoomTimelineControllerProtocol { func sendHandle(for itemID: TimelineItemIdentifier) -> SendHandleProxy? - func retryDecryption(for sessionID: String) async + func retryDecryption(sessionIDs: [String]?) async func eventTimestamp(for itemID: TimelineItemIdentifier) -> Date? } diff --git a/ElementX/Sources/Services/Timeline/TimelineProxy.swift b/ElementX/Sources/Services/Timeline/TimelineProxy.swift index 6b662f8ca9..92ff156c7c 100644 --- a/ElementX/Sources/Services/Timeline/TimelineProxy.swift +++ b/ElementX/Sources/Services/Timeline/TimelineProxy.swift @@ -155,12 +155,14 @@ final class TimelineProxy: TimelineProxyProtocol { } } - func retryDecryption(for sessionID: String) async { - MXLog.info("Retrying decryption for sessionID: \(sessionID)") + func retryDecryption(sessionIDs: [String]?) async { + let sessionIDs = sessionIDs ?? [] + + MXLog.info("Retrying decryption for sessionIDs: \(sessionIDs)") await Task.dispatch(on: .global()) { [weak self] in - self?.timeline.retryDecryption(sessionIds: [sessionID]) - MXLog.info("Finished retrying decryption for sessionID: \(sessionID)") + self?.timeline.retryDecryption(sessionIds: sessionIDs) + MXLog.info("Finished retrying decryption for sessionID: \(sessionIDs)") } } diff --git a/ElementX/Sources/Services/Timeline/TimelineProxyProtocol.swift b/ElementX/Sources/Services/Timeline/TimelineProxyProtocol.swift index 9620445e52..8c6dc6b817 100644 --- a/ElementX/Sources/Services/Timeline/TimelineProxyProtocol.swift +++ b/ElementX/Sources/Services/Timeline/TimelineProxyProtocol.swift @@ -35,7 +35,7 @@ protocol TimelineProxyProtocol { func messageEventContent(for timelineItemID: TimelineItemIdentifier) async -> RoomMessageEventContentWithoutRelation? - func retryDecryption(for sessionID: String) async + func retryDecryption(sessionIDs: [String]?) async func paginateBackwards(requestSize: UInt16) async -> Result func paginateForwards(requestSize: UInt16) async -> Result @@ -113,3 +113,9 @@ protocol TimelineProxyProtocol { html: String?, intentionalMentions: Mentions) -> RoomMessageEventContentWithoutRelation } + +extension TimelineProxyProtocol { + func retryDecryption() async { + await retryDecryption(sessionIDs: nil) + } +} From 7f3cdd8530afd8fd34fd60d116e8006c727ad30b Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Wed, 18 Dec 2024 08:40:25 +0200 Subject: [PATCH 2/2] Get rid of method @pixlwave doesn't like ;) --- .../Screens/Timeline/TimelineInteractionHandler.swift | 2 -- .../Timeline/View/ItemMenu/TimelineItemMenuAction.swift | 3 --- .../View/ItemMenu/TimelineItemMenuActionProvider.swift | 9 +-------- .../TimelineController/MockRoomTimelineController.swift | 2 -- .../TimelineController/RoomTimelineController.swift | 4 ---- .../RoomTimelineControllerProtocol.swift | 2 -- 6 files changed, 1 insertion(+), 21 deletions(-) diff --git a/ElementX/Sources/Screens/Timeline/TimelineInteractionHandler.swift b/ElementX/Sources/Screens/Timeline/TimelineInteractionHandler.swift index 87cd6be5a6..3231c0769d 100644 --- a/ElementX/Sources/Screens/Timeline/TimelineInteractionHandler.swift +++ b/ElementX/Sources/Screens/Timeline/TimelineInteractionHandler.swift @@ -157,8 +157,6 @@ class TimelineInteractionHandler { let debugInfo = timelineController.debugInfo(for: eventTimelineItem.id) MXLog.info("Showing debug info for \(eventTimelineItem.id)") actionsSubject.send(.showDebugInfo(debugInfo)) - case .retryDecryption(let sessionID): - Task { await timelineController.retryDecryption(sessionIDs: [sessionID]) } case .report: actionsSubject.send(.displayReportContent(itemID: itemID, senderID: eventTimelineItem.sender.id)) case .react: diff --git a/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenuAction.swift b/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenuAction.swift index 859b6f9bbb..6e6728d540 100644 --- a/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenuAction.swift +++ b/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenuAction.swift @@ -67,7 +67,6 @@ enum TimelineItemMenuAction: Identifiable, Hashable { case reply(isThread: Bool) case forward(itemID: TimelineItemIdentifier) case viewSource - case retryDecryption(sessionID: String) case report case react case toggleReaction(key: String) @@ -164,8 +163,6 @@ enum TimelineItemMenuAction: Identifiable, Hashable { Label(L10n.actionRemoveMessage, icon: \.delete) case .viewSource: Label(L10n.actionViewSource, icon: \.code) - case .retryDecryption: - Label(L10n.actionRetryDecryption, systemImage: "arrow.down.message") case .report: Label(L10n.actionReportContent, icon: \.chatProblem) case .react: diff --git a/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenuActionProvider.swift b/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenuActionProvider.swift index 63f6f41025..33c1f322ce 100644 --- a/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenuActionProvider.swift +++ b/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenuActionProvider.swift @@ -136,14 +136,7 @@ struct TimelineItemMenuActionProvider { if isViewSourceEnabled { actions.append(.viewSource) } - - switch encryptedItem.encryptionType { - case .megolmV1AesSha2(let sessionID, _): - secondaryActions.append(.retryDecryption(sessionID: sessionID)) - default: - break - } - + return .init(isReactable: false, actions: actions, secondaryActions: secondaryActions, diff --git a/ElementX/Sources/Services/Timeline/TimelineController/MockRoomTimelineController.swift b/ElementX/Sources/Services/Timeline/TimelineController/MockRoomTimelineController.swift index 9c039f9656..6674cdaef8 100644 --- a/ElementX/Sources/Services/Timeline/TimelineController/MockRoomTimelineController.swift +++ b/ElementX/Sources/Services/Timeline/TimelineController/MockRoomTimelineController.swift @@ -139,8 +139,6 @@ class MockRoomTimelineController: RoomTimelineControllerProtocol { nil } - func retryDecryption(sessionIDs: [String]?) async { } - func eventTimestamp(for itemID: TimelineItemIdentifier) -> Date? { timelineItemsTimestamp[itemID] ?? .now } diff --git a/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineController.swift b/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineController.swift index 098d481a7c..8f9292a4d0 100644 --- a/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineController.swift +++ b/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineController.swift @@ -356,10 +356,6 @@ class RoomTimelineController: RoomTimelineControllerProtocol { return nil } - func retryDecryption(sessionIDs: [String]?) async { - await activeTimeline.retryDecryption(sessionIDs: sessionIDs) - } - // MARK: - Private /// The cancellable used to update the timeline items. diff --git a/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineControllerProtocol.swift b/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineControllerProtocol.swift index 5851cafb39..67a076ce55 100644 --- a/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineControllerProtocol.swift +++ b/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineControllerProtocol.swift @@ -82,7 +82,5 @@ protocol RoomTimelineControllerProtocol { func sendHandle(for itemID: TimelineItemIdentifier) -> SendHandleProxy? - func retryDecryption(sessionIDs: [String]?) async - func eventTimestamp(for itemID: TimelineItemIdentifier) -> Date? }