Skip to content

Commit

Permalink
Fixes #2808 - Switch the message sending failure options from a dialo…
Browse files Browse the repository at this point in the history
…g to an alert

* Fixes #2808 - Switch the message sending failure options from a dialog to an alert
- this prevents it from showing up as a popup on the room list on an iPad
- it used to be set on the timeline and not on the timeline item because of our use of a UITableView
* Cleanup room screen action names
  • Loading branch information
stefanceriu authored May 9, 2024
1 parent d97f912 commit 905b21e
Show file tree
Hide file tree
Showing 16 changed files with 180 additions and 245 deletions.
58 changes: 42 additions & 16 deletions ElementX.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,19 @@ import UIKit

enum RoomScreenInteractionHandlerAction {
case composer(action: RoomScreenComposerAction)
case displayError(RoomScreenErrorType)

case displayEmojiPicker(itemID: TimelineItemIdentifier, selectedEmojis: Set<String>)
case displayReportContent(itemID: TimelineItemIdentifier, senderID: String)
case displayMessageForwarding(itemID: TimelineItemIdentifier)
case displayMediaUploadPreviewScreen(url: URL)
case displayPollForm(mode: PollFormMode)
case displayRoomMemberDetails(userID: String)

case showActionMenu(TimelineItemActionMenuInfo)
case showDebugInfo(TimelineItemDebugInfo)
case showConfirmationAlert(AlertInfo<UUID>)

case displayAudioRecorderPermissionError
case displayErrorToast(String)
}

@MainActor
Expand Down Expand Up @@ -85,7 +88,7 @@ class RoomScreenInteractionHandler {

// MARK: Timeline Item Action Menu

func showTimelineItemActionMenu(for itemID: TimelineItemIdentifier) {
func displayTimelineItemActionMenu(for itemID: TimelineItemIdentifier) {
Task {
if case let .success(value) = await roomProxy.canUserRedactOther(userID: roomProxy.ownUserID) {
canCurrentUserRedactOthers = value
Expand Down Expand Up @@ -186,7 +189,7 @@ class RoomScreenInteractionHandler {
return .init(actions: actions, debugActions: debugActions)
}

func processTimelineItemMenuAction(_ action: TimelineItemMenuAction, itemID: TimelineItemIdentifier) {
func handleTimelineItemMenuAction(_ action: TimelineItemMenuAction, itemID: TimelineItemIdentifier) {
guard let timelineItem = timelineController.timelineItems.firstUsingStableID(itemID),
let eventTimelineItem = timelineItem as? EventBasedTimelineItemProtocol else {
return
Expand Down Expand Up @@ -214,13 +217,13 @@ class RoomScreenInteractionHandler {
}
case .copyPermalink:
guard let eventID = eventTimelineItem.id.eventID else {
actionsSubject.send(.displayError(.alert(L10n.errorFailedCreatingThePermalink)))
actionsSubject.send(.displayErrorToast(L10n.errorFailedCreatingThePermalink))
return
}

Task {
guard case let .success(permalinkURL) = await roomProxy.matrixToEventPermalink(eventID) else {
actionsSubject.send(.displayError(.alert(L10n.errorFailedCreatingThePermalink)))
actionsSubject.send(.displayErrorToast(L10n.errorFailedCreatingThePermalink))
return
}

Expand Down Expand Up @@ -256,7 +259,7 @@ class RoomScreenInteractionHandler {
case .report:
actionsSubject.send(.displayReportContent(itemID: itemID, senderID: eventTimelineItem.sender.id))
case .react:
showEmojiPicker(for: itemID)
displayEmojiPicker(for: itemID)
case .toggleReaction(let key):
guard let eventID = itemID.eventID else { return }
Task { await roomProxy.timeline.toggleReaction(key, to: eventID) }
Expand Down Expand Up @@ -294,7 +297,7 @@ class RoomScreenInteractionHandler {
case .success:
break
case .failure:
actionsSubject.send(.displayError(.toast(L10n.errorUnknown)))
actionsSubject.send(.displayErrorToast(L10n.errorUnknown))
}
}
}
Expand All @@ -307,7 +310,7 @@ class RoomScreenInteractionHandler {
case .success:
break
case .failure:
actionsSubject.send(.displayError(.toast(L10n.errorUnknown)))
actionsSubject.send(.displayErrorToast(L10n.errorUnknown))
}
}
}
Expand All @@ -318,7 +321,7 @@ class RoomScreenInteractionHandler {
guard let contentType = provider.preferredContentType,
let preferredExtension = contentType.preferredFilenameExtension else {
MXLog.error("Invalid NSItemProvider: \(provider)")
actionsSubject.send(.displayError(.toast(L10n.screenRoomErrorFailedProcessingMedia)))
actionsSubject.send(.displayErrorToast(L10n.screenRoomErrorFailedProcessingMedia))
return
}

Expand All @@ -334,13 +337,13 @@ class RoomScreenInteractionHandler {
}

if let error {
self.actionsSubject.send(.displayError(.toast(L10n.screenRoomErrorFailedProcessingMedia)))
self.actionsSubject.send(.displayErrorToast(L10n.screenRoomErrorFailedProcessingMedia))
MXLog.error("Failed processing NSItemProvider: \(providerDescription) with error: \(error)")
return
}

guard let data else {
self.actionsSubject.send(.displayError(.toast(L10n.screenRoomErrorFailedProcessingMedia)))
self.actionsSubject.send(.displayErrorToast(L10n.screenRoomErrorFailedProcessingMedia))
MXLog.error("Invalid NSItemProvider data: \(providerDescription)")
return
}
Expand All @@ -359,7 +362,7 @@ class RoomScreenInteractionHandler {

self.actionsSubject.send(.displayMediaUploadPreviewScreen(url: url))
} catch {
self.actionsSubject.send(.displayError(.toast(L10n.screenRoomErrorFailedProcessingMedia)))
self.actionsSubject.send(.displayErrorToast(L10n.screenRoomErrorFailedProcessingMedia))
MXLog.error("Failed storing NSItemProvider data \(providerDescription) with error: \(error)")
}
}
Expand All @@ -381,11 +384,7 @@ class RoomScreenInteractionHandler {
switch error {
case .audioRecorderError(.recordPermissionNotGranted):
MXLog.info("permission to record audio has not been granted.")
actionsSubject.send(.showConfirmationAlert(.init(id: .init(),
title: L10n.dialogPermissionMicrophoneTitleIos(InfoPlistReader.main.bundleDisplayName),
message: L10n.dialogPermissionMicrophoneDescriptionIos,
primaryButton: .init(title: L10n.commonSettings, action: { [weak self] in self?.openSystemSettings() }),
secondaryButton: .init(title: L10n.actionNotNow, role: .cancel, action: nil))))
actionsSubject.send(.displayAudioRecorderPermissionError)
default:
MXLog.error("failed to start voice message recording. \(error)")
actionsSubject.send(.composer(action: .setMode(mode: .default)))
Expand Down Expand Up @@ -427,7 +426,7 @@ class RoomScreenInteractionHandler {

func sendCurrentVoiceMessage() async {
guard let audioPlayerState = voiceMessageRecorder.previewAudioPlayerState, let recordingURL = voiceMessageRecorder.recordingURL else {
actionsSubject.send(.displayError(.alert(L10n.errorFailedUploadingVoiceMessage)))
actionsSubject.send(.displayErrorToast(L10n.errorFailedUploadingVoiceMessage))
return
}

Expand All @@ -445,7 +444,7 @@ class RoomScreenInteractionHandler {
case .failure(let error):
MXLog.error("failed to send the voice message. \(error)")
actionsSubject.send(.composer(action: .setMode(mode: .previewVoiceMessage(state: audioPlayerState, waveform: .url(recordingURL), isUploading: false))))
actionsSubject.send(.displayError(.alert(L10n.errorFailedUploadingVoiceMessage)))
actionsSubject.send(.displayErrorToast(L10n.errorFailedUploadingVoiceMessage))
}
}

Expand Down Expand Up @@ -578,7 +577,7 @@ class RoomScreenInteractionHandler {

// MARK: Other

func showEmojiPicker(for itemID: TimelineItemIdentifier) {
func displayEmojiPicker(for itemID: TimelineItemIdentifier) {
guard let timelineItem = timelineController.timelineItems.firstUsingStableID(itemID),
timelineItem.isReactable,
let eventTimelineItem = timelineItem as? EventBasedTimelineItemProtocol else {
Expand All @@ -588,7 +587,7 @@ class RoomScreenInteractionHandler {
actionsSubject.send(.displayEmojiPicker(itemID: itemID, selectedEmojis: selectedEmojis))
}

func handleTappedUser(userID: String) async {
func displayRoomMemberDetails(userID: String) async {
actionsSubject.send(.displayRoomMemberDetails(userID: userID))
}

Expand Down Expand Up @@ -623,10 +622,6 @@ class RoomScreenInteractionHandler {
}
}

private func openSystemSettings() {
appMediator.openAppSettings()
}

private func displayMediaActionIfPossible(timelineItem: RoomTimelineItemProtocol) async -> RoomTimelineControllerAction {
var source: MediaSourceProxy?
var body: String
Expand Down
52 changes: 17 additions & 35 deletions ElementX/Sources/Screens/RoomScreen/RoomScreenModels.swift
Original file line number Diff line number Diff line change
Expand Up @@ -68,14 +68,12 @@ enum RoomScreenViewPollAction {
case edit(pollStartID: String, poll: Poll)
}

enum RoomScreenViewAudioAction {
enum RoomScreenAudioPlayerAction {
case playPause(itemID: TimelineItemIdentifier)
case seek(itemID: TimelineItemIdentifier, progress: Double)
}

enum RoomScreenViewAction {
case displayRoomDetails

case itemAppeared(itemID: TimelineItemIdentifier)
case itemDisappeared(itemID: TimelineItemIdentifier)

Expand All @@ -86,27 +84,20 @@ enum RoomScreenViewAction {
case paginateForwards
case scrollToBottom

case timelineItemMenu(itemID: TimelineItemIdentifier)
case timelineItemMenuAction(itemID: TimelineItemIdentifier, action: TimelineItemMenuAction)
case displayTimelineItemMenu(itemID: TimelineItemIdentifier)
case handleTimelineItemMenuAction(itemID: TimelineItemIdentifier, action: TimelineItemMenuAction)

case displayRoomDetails
case displayRoomMemberDetails(userID: String)
case displayReactionSummary(itemID: TimelineItemIdentifier, key: String)
case displayEmojiPicker(itemID: TimelineItemIdentifier)
case displayMessageSendingFailureAlert(itemID: TimelineItemIdentifier)
case displayReadReceipts(itemID: TimelineItemIdentifier)
case displayCall

case handlePasteOrDrop(provider: NSItemProvider)

case tappedOnUser(userID: String)

case reactionSummary(itemID: TimelineItemIdentifier, key: String)

case retrySend(itemID: TimelineItemIdentifier)
case cancelSend(itemID: TimelineItemIdentifier)

case showReadReceipts(itemID: TimelineItemIdentifier)

case poll(RoomScreenViewPollAction)

case audio(RoomScreenViewAudioAction)

case presentCall
case handlePollAction(RoomScreenViewPollAction)
case handleAudioPlayerAction(RoomScreenAudioPlayerAction)

/// Focus the timeline onto the specified event ID (switching to a detached timeline if needed).
case focusOnEventID(String)
Expand Down Expand Up @@ -161,18 +152,12 @@ struct RoomScreenViewStateBindings {
/// A media item that will be previewed with QuickLook.
var mediaPreviewItem: MediaPreviewItem?

/// Information describing the currently displayed alert.
var alertInfo: AlertInfo<RoomScreenErrorType>?

/// An alert info for confirmation actions (e.g. ending a poll)
var confirmationAlertInfo: AlertInfo<UUID>?
var alertInfo: AlertInfo<RoomScreenAlertInfoType>?

var debugInfo: TimelineItemDebugInfo?

var actionMenuInfo: TimelineItemActionMenuInfo?

var sendFailedConfirmationDialogInfo: SendFailedConfirmationDialogInfo?

var reactionSummaryInfo: ReactionSummaryInfo?

var readReceiptsSummaryInfo: ReadReceiptSummaryInfo?
Expand All @@ -190,9 +175,7 @@ struct TimelineItemActionMenuInfo: Equatable, Identifiable {
}
}

struct SendFailedConfirmationDialogInfo: ConfirmationDialogProtocol {
let title = L10n.screenRoomRetrySendMenuTitle

struct MessageSendingFailureInfo: Hashable {
let itemID: TimelineItemIdentifier
}

Expand All @@ -210,11 +193,10 @@ struct ReadReceiptSummaryInfo: Identifiable {
let id: TimelineItemIdentifier
}

enum RoomScreenErrorType: Hashable {
/// A specific error message shown in an alert.
case alert(String)
/// A specific error message shown in a toast.
case toast(String)
enum RoomScreenAlertInfoType: Hashable {
case audioRecodingPermissionError
case pollEndConfirmation(String)
case messageSendingFailure(TimelineItemIdentifier)
}

struct RoomMemberState {
Expand Down
Loading

0 comments on commit 905b21e

Please sign in to comment.