Revert decryption banner & try fix context menu crash. (#525)
This commit is contained in:
@@ -26,6 +26,8 @@
|
||||
"room_timeline_syncing" = "Syncing";
|
||||
"room_timeline_unable_to_decrypt" = "Unable to decrypt";
|
||||
|
||||
"room_timeline_context_menu_retry_decryption" = "Retry decryption";
|
||||
|
||||
"room_timeline_item_unsupported" = "Unsupported event";
|
||||
"room_timeline_image_gif" = "GIF";
|
||||
"room_timeline_read_marker_title" = "New";
|
||||
|
||||
@@ -98,6 +98,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")
|
||||
/// GIF
|
||||
|
||||
@@ -53,7 +53,6 @@ enum RoomScreenViewAction {
|
||||
case cancelEdit
|
||||
/// Mark the entire room as read - this is heavy handed as a starting point for now.
|
||||
case markRoomAsRead
|
||||
case retryDecryption
|
||||
case contextMenuAction(itemID: String, action: TimelineItemContextMenuAction)
|
||||
}
|
||||
|
||||
@@ -64,7 +63,6 @@ struct RoomScreenViewState: BindableState {
|
||||
var items: [RoomTimelineViewProvider] = []
|
||||
var canBackPaginate = true
|
||||
var isBackPaginating = false
|
||||
var showEncryptionBanner = false
|
||||
var showLoading = false
|
||||
var bindings: RoomScreenViewStateBindings
|
||||
|
||||
|
||||
@@ -29,7 +29,6 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
||||
private let timelineController: RoomTimelineControllerProtocol
|
||||
private let timelineViewFactory: RoomTimelineViewFactoryProtocol
|
||||
|
||||
// swiftlint:disable:next cyclomatic_complexity
|
||||
init(timelineController: RoomTimelineControllerProtocol,
|
||||
timelineViewFactory: RoomTimelineViewFactoryProtocol,
|
||||
mediaProvider: MediaProviderProtocol,
|
||||
@@ -67,10 +66,6 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
||||
if self.state.isBackPaginating != isBackPaginating {
|
||||
self.state.isBackPaginating = isBackPaginating
|
||||
}
|
||||
case .hasEncryptedItems(let hasEncryptedItems):
|
||||
if self.state.showEncryptionBanner != hasEncryptedItems {
|
||||
self.state.showEncryptionBanner = hasEncryptedItems
|
||||
}
|
||||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
@@ -118,8 +113,6 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
||||
state.bindings.composerText = ""
|
||||
case .markRoomAsRead:
|
||||
await markRoomAsRead()
|
||||
case .retryDecryption:
|
||||
retryDecryption()
|
||||
case .contextMenuAction(let itemID, let action):
|
||||
processContentMenuAction(action, itemID: itemID)
|
||||
}
|
||||
@@ -189,19 +182,6 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
||||
}
|
||||
}
|
||||
|
||||
/// Retry decrypting any encrypted items in the timeline.
|
||||
private func retryDecryption() {
|
||||
Task {
|
||||
let firstEncryptedItem = state.items.first { $0.sessionID != nil }
|
||||
|
||||
if let sessionID = firstEncryptedItem?.sessionID {
|
||||
// Request for the first encrypted item to be decrypted as the SDK
|
||||
// will continue to decrypt any following items automatically.
|
||||
await timelineController.retryDecryption(for: sessionID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func displayError(_ type: RoomScreenErrorType) {
|
||||
switch type {
|
||||
case .alert(let message):
|
||||
@@ -244,7 +224,12 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
||||
actions.append(.redact)
|
||||
}
|
||||
|
||||
let debugActions: [TimelineItemContextMenuAction] = [.viewSource]
|
||||
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)
|
||||
}
|
||||
@@ -286,6 +271,10 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
||||
let debugDescription = timelineController.debugDescription(for: item.id)
|
||||
MXLog.info(debugDescription)
|
||||
state.bindings.debugInfo = .init(title: "Timeline item", content: debugDescription)
|
||||
case .retryDecryption(let sessionID):
|
||||
Task {
|
||||
await timelineController.retryDecryption(for: sessionID)
|
||||
}
|
||||
}
|
||||
|
||||
if action.switchToDefaultComposer {
|
||||
@@ -302,14 +291,3 @@ extension RoomScreenViewModel {
|
||||
mediaProvider: MockMediaProvider(),
|
||||
roomName: "Preview room")
|
||||
}
|
||||
|
||||
private extension RoomTimelineViewProvider {
|
||||
/// The item's session ID if it was unable to decrypt and uses megolm.
|
||||
/// This will be nil for items that have already been decrypted.
|
||||
var sessionID: String? {
|
||||
guard case let .encrypted(item) = self,
|
||||
case let .megolmV1AesSha2(sessionID) = item.encryptionType
|
||||
else { return nil }
|
||||
return sessionID
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,8 +24,6 @@ struct RoomScreen: View {
|
||||
var body: some View {
|
||||
timeline
|
||||
.background(Color.element.background.ignoresSafeArea()) // Kills the toolbar translucency.
|
||||
.overlay(alignment: .top) { encryptionBanner } // Overlay for now, safeAreaInset breaks timeline scroll offset.
|
||||
.animation(.spring(), value: context.viewState.showEncryptionBanner)
|
||||
.safeAreaInset(edge: .bottom, spacing: 0) { messageComposer }
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.toolbar { toolbar }
|
||||
@@ -51,44 +49,6 @@ struct RoomScreen: View {
|
||||
.overlay(alignment: .bottomTrailing) { scrollToBottomButton }
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
var encryptionBanner: some View {
|
||||
if context.viewState.showEncryptionBanner {
|
||||
VStack(alignment: .leading, spacing: 4) {
|
||||
Label {
|
||||
Text("Unable to decrypt all messages")
|
||||
.foregroundColor(.element.primaryContent)
|
||||
} icon: {
|
||||
Image(systemName: "lock.shield")
|
||||
.foregroundColor(.element.background)
|
||||
.padding(4)
|
||||
.background(Color.element.tertiaryContent)
|
||||
.cornerRadius(5)
|
||||
}
|
||||
.font(.element.bodyBold)
|
||||
|
||||
Text("Accessing your encrypted message history is not fully supported yet.")
|
||||
.font(.element.subheadline)
|
||||
.foregroundColor(.element.secondaryContent)
|
||||
.padding(.bottom, 8)
|
||||
|
||||
Button(ElementL10n.globalRetry) {
|
||||
context.send(viewAction: .retryDecryption)
|
||||
}
|
||||
.buttonStyle(.elementCapsuleProminent)
|
||||
}
|
||||
.padding(.horizontal, 16)
|
||||
.padding(.vertical, 12)
|
||||
.background {
|
||||
RoundedRectangle(cornerRadius: 8)
|
||||
.fill(Color.element.system)
|
||||
}
|
||||
.padding([.horizontal, .top], 16)
|
||||
.background(Color.element.background)
|
||||
.transition(.move(edge: .top).combined(with: .opacity))
|
||||
}
|
||||
}
|
||||
|
||||
var messageComposer: some View {
|
||||
MessageComposer(text: $context.composerText,
|
||||
focused: $context.composerFocused,
|
||||
@@ -150,8 +110,7 @@ struct RoomScreen_Previews: PreviewProvider {
|
||||
roomName: "Preview room")
|
||||
|
||||
NavigationView {
|
||||
RoomScreen(context: viewModel.context).encryptionBanner
|
||||
.padding()
|
||||
RoomScreen(context: viewModel.context)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,8 +91,8 @@ struct TimelineItemBubbledStylerView<Content: View>: View {
|
||||
var messageBubble: some View {
|
||||
styledContent
|
||||
.contentShape(.contextMenuPreview, RoundedCornerShape(radius: cornerRadius, corners: timelineItem.roundedCorners)) // Rounded corners for the context menu animation.
|
||||
.contextMenu { [weak context] in
|
||||
context?.viewState.contextMenuActionProvider?(timelineItem.id).map { actions in
|
||||
.contextMenu {
|
||||
context.viewState.contextMenuActionProvider?(timelineItem.id).map { actions in
|
||||
TimelineItemContextMenu(itemID: timelineItem.id, contextMenuActions: actions)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ enum TimelineItemContextMenuAction: Identifiable, Hashable {
|
||||
case redact
|
||||
case reply
|
||||
case viewSource
|
||||
case retryDecryption(sessionID: String)
|
||||
|
||||
var id: Self { self }
|
||||
|
||||
@@ -102,6 +103,10 @@ public struct TimelineItemContextMenu: View {
|
||||
Button { send(action) } label: {
|
||||
Label(ElementL10n.viewSource, systemImage: "doc.text.below.ecg")
|
||||
}
|
||||
case .retryDecryption:
|
||||
Button { send(action) } label: {
|
||||
Label(ElementL10n.roomTimelineContextMenuRetryDecryption, systemImage: "arrow.down.message")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -218,12 +218,11 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
|
||||
updateTimelineItems()
|
||||
}
|
||||
|
||||
// swiftlint:disable:next cyclomatic_complexity function_body_length
|
||||
// swiftlint:disable:next cyclomatic_complexity
|
||||
private func updateTimelineItems() {
|
||||
var newTimelineItems = [RoomTimelineItemProtocol]()
|
||||
var canBackPaginate = true
|
||||
var isBackPaginating = false
|
||||
var hasEncryptedItems = false
|
||||
|
||||
var createdIdentifiers = [String: Bool]()
|
||||
|
||||
@@ -244,9 +243,6 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
|
||||
if createdIdentifiers[timelineItem.id] == nil {
|
||||
newTimelineItems.append(timelineItem)
|
||||
createdIdentifiers[timelineItem.id] = true
|
||||
if timelineItem is EncryptedRoomTimelineItem {
|
||||
hasEncryptedItems = true
|
||||
}
|
||||
} else {
|
||||
MXLog.error("Found duplicated timeline item, ignoring")
|
||||
}
|
||||
@@ -284,7 +280,6 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
|
||||
callbacks.send(.updatedTimelineItems)
|
||||
callbacks.send(.canBackPaginate(canBackPaginate))
|
||||
callbacks.send(.isBackPaginating(isBackPaginating))
|
||||
callbacks.send(.hasEncryptedItems(hasEncryptedItems))
|
||||
}
|
||||
|
||||
private func computeGroupState(for itemProxy: TimelineItemProxy,
|
||||
|
||||
@@ -23,7 +23,6 @@ enum RoomTimelineControllerCallback {
|
||||
case updatedTimelineItem(_ itemId: String)
|
||||
case canBackPaginate(Bool)
|
||||
case isBackPaginating(Bool)
|
||||
case hasEncryptedItems(Bool)
|
||||
}
|
||||
|
||||
enum RoomTimelineControllerAction {
|
||||
|
||||
Reference in New Issue
Block a user