From 435dfb8e46ab3e255576d236515ec8772930992c Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Wed, 18 Dec 2024 11:10:56 +0200 Subject: [PATCH] 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 (#3628) --- .../Mocks/Generated/GeneratedMocks.swift | 32 +++++++++---------- .../RoomScreen/RoomScreenViewModel.swift | 8 +++++ .../Timeline/TimelineInteractionHandler.swift | 2 -- .../ItemMenu/TimelineItemMenuAction.swift | 3 -- .../TimelineItemMenuActionProvider.swift | 9 +----- .../MockRoomTimelineController.swift | 2 -- .../RoomTimelineController.swift | 4 --- .../RoomTimelineControllerProtocol.swift | 2 -- .../Services/Timeline/TimelineProxy.swift | 10 +++--- .../Timeline/TimelineProxyProtocol.swift | 8 ++++- 10 files changed, 38 insertions(+), 42 deletions(-) diff --git a/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift b/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift index 46b42ecb7..1857b7f4a 100644 --- a/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift +++ b/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift @@ -14150,15 +14150,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! @@ -14166,28 +14166,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 e81eed405..93f9422f8 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 0dfd0d328..3231c0769 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(for: 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 859b6f9bb..6e6728d54 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 63f6f4102..33c1f322c 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 eb34a2354..6674cdaef 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(for sessionID: 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 218cfb198..8f9292a4d 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(for sessionID: String) async { - await activeTimeline.retryDecryption(for: sessionID) - } - // 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 1aa9e0a06..67a076ce5 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(for sessionID: 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 6b662f8ca..92ff156c7 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 9620445e5..8c6dc6b81 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) + } +}