mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-02 21:33:26 +00:00
Add retry decryption encrypted timeline item debug menu option (#384)
* Fixed a couple of warnings (+2 squashed commits) Squashed commits: [21fbc3b0] Add changelog [abb092c6] Add retry decryption encrypted timeline item debug menu option * Cleanup room list state computations * Bump the RustSDK to v1.0.25-alpha * Fix brew CI errors: remove imagemagick and brew lock file entirely * Fix release script version bumping * Bump ruby dependencies
This commit is contained in:
@@ -32,6 +32,8 @@ extension ElementL10n {
|
||||
public static let roomDetailsTitle = ElementL10n.tr("Untranslated", "room_details_title")
|
||||
/// Failed loading messages
|
||||
public static let roomTimelineBackpaginationFailure = ElementL10n.tr("Untranslated", "room_timeline_backpagination_failure")
|
||||
/// Retry decryption
|
||||
public static let roomTimelineContextMenuRetryDecryption = ElementL10n.tr("Untranslated", "room_timeline_context_menu_retry_decryption")
|
||||
/// Editing
|
||||
public static let roomTimelineEditing = ElementL10n.tr("Untranslated", "room_timeline_editing")
|
||||
/// Failed creating the permalink
|
||||
|
||||
@@ -79,14 +79,13 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol
|
||||
visibleRoomsSummaryProvider.roomListPublisher)
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink { [weak self] state, totalCount, rooms in
|
||||
if state != .live {
|
||||
if totalCount == 0 || rooms.count != totalCount {
|
||||
self?.state.roomListMode = .skeletons
|
||||
} else {
|
||||
self?.state.roomListMode = .rooms
|
||||
}
|
||||
} else if totalCount == 0 {
|
||||
#warning("Empty state but it never happens because SS never goes into live for empty accounts")
|
||||
let isLoadingData = state != .live && (totalCount == 0 || rooms.count != totalCount)
|
||||
let hasNoRooms = state == .live && totalCount == 0
|
||||
|
||||
if isLoadingData {
|
||||
self?.state.roomListMode = .skeletons
|
||||
} else if hasNoRooms {
|
||||
self?.state.roomListMode = .skeletons
|
||||
} else {
|
||||
self?.state.roomListMode = .rooms
|
||||
}
|
||||
|
||||
@@ -193,7 +193,7 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
||||
private func contextMenuActionsForItemId(_ itemId: String) -> TimelineItemContextMenuActions {
|
||||
guard let timelineItem = timelineController.timelineItems.first(where: { $0.id == itemId }),
|
||||
let item = timelineItem as? EventBasedTimelineItemProtocol else {
|
||||
return .init(actions: [])
|
||||
return .init(actions: [], debugActions: [])
|
||||
}
|
||||
|
||||
var actions: [TimelineItemContextMenuAction] = [
|
||||
@@ -208,7 +208,14 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
||||
actions.append(.redact)
|
||||
}
|
||||
|
||||
return .init(actions: actions)
|
||||
var debugActions: [TimelineItemContextMenuAction] = [.viewSource]
|
||||
|
||||
if let item = timelineItem as? EncryptedRoomTimelineItem,
|
||||
case let .megolmV1AesSha2(sessionId) = item.encryptionType {
|
||||
debugActions.append(.retryDecryption(sessionId: sessionId))
|
||||
}
|
||||
|
||||
return .init(actions: actions, debugActions: debugActions)
|
||||
}
|
||||
|
||||
// swiftlint:disable:next cyclomatic_complexity
|
||||
@@ -238,7 +245,9 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
||||
displayError(.alert(ElementL10n.roomTimelinePermalinkCreationFailure))
|
||||
}
|
||||
case .redact:
|
||||
redact(itemId)
|
||||
Task {
|
||||
await timelineController.redact(itemId)
|
||||
}
|
||||
case .reply:
|
||||
state.bindings.composerFocused = true
|
||||
state.composerMode = .reply(id: item.id, displayName: item.senderDisplayName ?? item.senderId)
|
||||
@@ -246,16 +255,14 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
||||
let debugDescription = timelineController.debugDescriptionFor(item.id)
|
||||
MXLog.info(debugDescription)
|
||||
state.bindings.debugInfo = .init(title: "Timeline item", content: debugDescription)
|
||||
case .retryDecryption(let sessionId):
|
||||
Task {
|
||||
await timelineController.retryDecryption(forSessionId: sessionId)
|
||||
}
|
||||
}
|
||||
|
||||
if action.switchToDefaultComposer {
|
||||
state.composerMode = .default
|
||||
}
|
||||
}
|
||||
|
||||
private func redact(_ eventID: String) {
|
||||
Task {
|
||||
await timelineController.redact(eventID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ import SwiftUI
|
||||
|
||||
struct TimelineItemContextMenuActions {
|
||||
let actions: [TimelineItemContextMenuAction]
|
||||
let debugActions: [TimelineItemContextMenuAction] = [.viewSource]
|
||||
let debugActions: [TimelineItemContextMenuAction]
|
||||
}
|
||||
|
||||
enum TimelineItemContextMenuAction: Identifiable, Hashable {
|
||||
@@ -30,6 +30,7 @@ enum TimelineItemContextMenuAction: Identifiable, Hashable {
|
||||
case redact
|
||||
case reply
|
||||
case viewSource
|
||||
case retryDecryption(sessionId: String)
|
||||
|
||||
var id: Self { self }
|
||||
|
||||
@@ -92,6 +93,10 @@ public struct TimelineItemContextMenu: View {
|
||||
Button { callback(item) } label: {
|
||||
Label(ElementL10n.viewSource, systemImage: "doc.text.below.ecg")
|
||||
}
|
||||
case .retryDecryption:
|
||||
Button { callback(item) } label: {
|
||||
Label(ElementL10n.roomTimelineContextMenuRetryDecryption, systemImage: "arrow.down.message")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,4 +81,6 @@ struct MockRoomProxy: RoomProxyProtocol {
|
||||
}
|
||||
return .failure(.failedRetrievingMembers)
|
||||
}
|
||||
|
||||
func retryDecryption(forSessionId sessionId: String) async { }
|
||||
}
|
||||
|
||||
@@ -147,8 +147,6 @@ class RoomProxy: RoomProxyProtocol {
|
||||
return .failure(.noMoreMessagesToBackPaginate)
|
||||
}
|
||||
|
||||
let id = id // Copy the ID due to @Sendable requirement.
|
||||
|
||||
do {
|
||||
let outcome: PaginationOutcome = try await Task.dispatch(on: .global()) {
|
||||
try self.room.paginateBackwards(limit: UInt16(count))
|
||||
@@ -242,19 +240,27 @@ class RoomProxy: RoomProxyProtocol {
|
||||
}
|
||||
}
|
||||
|
||||
func update(avatarURL: String?, forUserId userId: String) {
|
||||
func retryDecryption(forSessionId sessionId: String) async {
|
||||
await Task.dispatch(on: .global()) { [weak self] in
|
||||
self?.room.retryDecryption(sessionIds: [sessionId])
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private func update(avatarURL: String?, forUserId userId: String) {
|
||||
memberAvatars[userId] = avatarURL
|
||||
}
|
||||
|
||||
func update(displayName: String?, forUserId userId: String) {
|
||||
private func update(displayName: String?, forUserId userId: String) {
|
||||
memberDisplayNames[userId] = displayName
|
||||
}
|
||||
|
||||
func update(displayName: String) {
|
||||
private func update(displayName: String) {
|
||||
self.displayName = displayName
|
||||
}
|
||||
|
||||
func update(backPaginationOutcome: PaginationOutcome) {
|
||||
private func update(backPaginationOutcome: PaginationOutcome) {
|
||||
self.backPaginationOutcome = backPaginationOutcome
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,6 +67,8 @@ protocol RoomProxyProtocol {
|
||||
func redact(_ eventID: String) async -> Result<Void, RoomProxyError>
|
||||
|
||||
func members() async -> Result<[RoomMemberProxy], RoomProxyError>
|
||||
|
||||
func retryDecryption(forSessionId sessionId: String) async
|
||||
}
|
||||
|
||||
extension RoomProxyProtocol {
|
||||
|
||||
@@ -62,10 +62,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<RoomSummary>.Change]()
|
||||
for identifier in identifiers {
|
||||
|
||||
@@ -42,4 +42,6 @@ struct MockRoomTimelineProvider: RoomTimelineProviderProtocol {
|
||||
func redact(_ eventID: String) async -> Result<Void, RoomTimelineProviderError> {
|
||||
.failure(.failedRedactingItem)
|
||||
}
|
||||
|
||||
func retryDecryption(forSessionId sessionId: String) async { }
|
||||
}
|
||||
|
||||
@@ -139,6 +139,10 @@ class RoomTimelineProvider: RoomTimelineProviderProtocol {
|
||||
}
|
||||
}
|
||||
|
||||
func retryDecryption(forSessionId sessionId: String) async {
|
||||
await roomProxy.retryDecryption(forSessionId: sessionId)
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private func updateItemsWithDiffs(_ diffs: [TimelineDiff]) {
|
||||
|
||||
@@ -40,6 +40,8 @@ protocol RoomTimelineProviderProtocol {
|
||||
func editMessage(_ newMessage: String, originalItemId: String) async -> Result<Void, RoomTimelineProviderError>
|
||||
|
||||
func redact(_ eventID: String) async -> Result<Void, RoomTimelineProviderError>
|
||||
|
||||
func retryDecryption(forSessionId sessionId: String) async
|
||||
}
|
||||
|
||||
extension RoomTimelineProviderProtocol {
|
||||
|
||||
@@ -87,4 +87,6 @@ class MockRoomTimelineController: RoomTimelineControllerProtocol {
|
||||
func debugDescriptionFor(_ itemId: String) -> String {
|
||||
"Mock debug description"
|
||||
}
|
||||
|
||||
func retryDecryption(forSessionId sessionId: String) async { }
|
||||
}
|
||||
|
||||
@@ -204,6 +204,10 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
|
||||
|
||||
return description
|
||||
}
|
||||
|
||||
func retryDecryption(forSessionId sessionId: String) async {
|
||||
await timelineProvider.retryDecryption(forSessionId: sessionId)
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
|
||||
+2
@@ -61,4 +61,6 @@ protocol RoomTimelineControllerProtocol {
|
||||
func redact(_ eventID: String) async
|
||||
|
||||
func debugDescriptionFor(_ itemId: String) -> String
|
||||
|
||||
func retryDecryption(forSessionId sessionId: String) async
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user