mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-04 19:44:05 +00:00
Retry send and cancel send for failed to send messages (#1088)
* is now possible to open the confirmation dialog and pass the transaction id * task completed added some tests * changelog * title visibility set to .visible
This commit is contained in:
@@ -70,6 +70,9 @@ enum RoomScreenViewAction {
|
||||
|
||||
case handlePasteOrDrop(provider: NSItemProvider)
|
||||
case tappedOnUser(userID: String)
|
||||
|
||||
case retrySend(transactionID: String?)
|
||||
case cancelSend(transactionID: String?)
|
||||
}
|
||||
|
||||
struct RoomScreenViewState: BindableState {
|
||||
@@ -109,6 +112,8 @@ struct RoomScreenViewStateBindings {
|
||||
var debugInfo: TimelineItemDebugInfo?
|
||||
|
||||
var actionMenuInfo: TimelineItemActionMenuInfo?
|
||||
|
||||
var sendFailedConfirmationDialogInfo: SendFailedConfirmationDialogInfo?
|
||||
}
|
||||
|
||||
struct TimelineItemActionMenuInfo: Identifiable {
|
||||
@@ -119,6 +124,12 @@ struct TimelineItemActionMenuInfo: Identifiable {
|
||||
}
|
||||
}
|
||||
|
||||
struct SendFailedConfirmationDialogInfo: ConfirmationDialogProtocol {
|
||||
let title = L10n.screenRoomRetrySendMenuTitle
|
||||
|
||||
let transactionID: String?
|
||||
}
|
||||
|
||||
enum RoomScreenErrorType: Hashable {
|
||||
/// A specific error message shown in an alert.
|
||||
case alert(String)
|
||||
|
||||
@@ -105,10 +105,13 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
||||
handlePasteOrDrop(provider)
|
||||
case .tappedOnUser(userID: let userID):
|
||||
Task { await handleTappedUser(userID: userID) }
|
||||
|
||||
case .displayEmojiPicker(let itemID):
|
||||
guard let item = state.items.first(where: { $0.id == itemID }), item.isReactable else { return }
|
||||
callback?(.displayEmojiPicker(itemID: itemID))
|
||||
case .retrySend(let transactionID):
|
||||
Task { await handleRetrySend(transactionID: transactionID) }
|
||||
case .cancelSend(let transactionID):
|
||||
Task { await handleCancelSend(transactionID: transactionID) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -470,6 +473,22 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
||||
}
|
||||
}
|
||||
|
||||
private func handleRetrySend(transactionID: String?) async {
|
||||
guard let transactionID else {
|
||||
return
|
||||
}
|
||||
|
||||
await roomProxy.retrySend(transactionID: transactionID)
|
||||
}
|
||||
|
||||
private func handleCancelSend(transactionID: String?) async {
|
||||
guard let transactionID else {
|
||||
return
|
||||
}
|
||||
|
||||
await roomProxy.cancelSend(transactionID: transactionID)
|
||||
}
|
||||
|
||||
private static let loadingIndicatorIdentifier = "RoomScreenLoadingIndicator"
|
||||
|
||||
private func showLoadingIndicator(with delay: Duration) -> Task<Void, Never> {
|
||||
|
||||
@@ -62,6 +62,14 @@ struct RoomScreen: View {
|
||||
context.send(viewAction: .handlePasteOrDrop(provider: provider))
|
||||
return true
|
||||
}
|
||||
.confirmationDialog(item: $context.sendFailedConfirmationDialogInfo, titleVisibility: .visible) { item in
|
||||
Button(L10n.screenRoomRetrySendMenuSendAgainAction) {
|
||||
context.send(viewAction: .retrySend(transactionID: item.transactionID))
|
||||
}
|
||||
Button(L10n.screenRoomRetrySendMenuRemoveAction, role: .destructive) {
|
||||
context.send(viewAction: .cancelSend(transactionID: item.transactionID))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var timeline: some View {
|
||||
|
||||
+31
-14
@@ -146,30 +146,47 @@ struct TimelineItemBubbledStylerView<Content: View>: View {
|
||||
|
||||
@ViewBuilder
|
||||
var contentWithTimestamp: some View {
|
||||
if isTextItem {
|
||||
if isTextItem || isMediaType {
|
||||
ZStack(alignment: .bottomTrailing) {
|
||||
contentWithReply
|
||||
localizedSendInfo
|
||||
}
|
||||
} else if isMediaType {
|
||||
ZStack(alignment: .bottomTrailing) {
|
||||
contentWithReply
|
||||
localizedSendInfo
|
||||
.padding(.horizontal, 4)
|
||||
.padding(.vertical, 2)
|
||||
.background(Color.element.system)
|
||||
.cornerRadius(10)
|
||||
.padding(.trailing, 4)
|
||||
.padding(.bottom, 4)
|
||||
interactiveLocalizedSendInfo
|
||||
}
|
||||
} else {
|
||||
HStack(alignment: .bottom, spacing: 4) {
|
||||
contentWithReply
|
||||
localizedSendInfo
|
||||
interactiveLocalizedSendInfo
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
var interactiveLocalizedSendInfo: some View {
|
||||
if timelineItem.properties.deliveryStatus == .sendingFailed {
|
||||
backgroundedLocalizedSendInfo
|
||||
.onTapGesture {
|
||||
context.sendFailedConfirmationDialogInfo = .init(transactionID: timelineItem.properties.transactionID)
|
||||
}
|
||||
} else {
|
||||
backgroundedLocalizedSendInfo
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
var backgroundedLocalizedSendInfo: some View {
|
||||
if isMediaType {
|
||||
localizedSendInfo
|
||||
.padding(.horizontal, 4)
|
||||
.padding(.vertical, 2)
|
||||
.background(Color.element.system)
|
||||
.cornerRadius(10)
|
||||
.padding(.trailing, 4)
|
||||
.padding(.bottom, 4)
|
||||
|
||||
} else {
|
||||
localizedSendInfo
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
var localizedSendInfo: some View {
|
||||
HStack(spacing: 4) {
|
||||
|
||||
@@ -69,6 +69,9 @@ struct TimelineItemStatusView: View {
|
||||
.resizable()
|
||||
.foregroundColor(.element.alert)
|
||||
.frame(width: 16, height: 16)
|
||||
.onTapGesture {
|
||||
context.sendFailedConfirmationDialogInfo = .init(transactionID: timelineItem.properties.transactionID)
|
||||
}
|
||||
}
|
||||
// The bubbles handle the failure internally
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user