Artificial delay when a message fails to send (#2091)

This commit is contained in:
Mauro
2023-11-16 10:09:29 +01:00
committed by GitHub
parent 9f1092b0b6
commit 003b494c90
6 changed files with 48 additions and 10 deletions
@@ -24,6 +24,7 @@ struct TimelineItemBubbledStylerView<Content: View>: View {
@Environment(\.timelineGroupStyle) private var timelineGroupStyle
let timelineItem: EventBasedTimelineItemProtocol
let adjustedDeliveryStatus: TimelineItemDeliveryStatus?
@ViewBuilder let content: () -> Content
@State private var showItemActionMenu = false
@@ -62,7 +63,7 @@ struct TimelineItemBubbledStylerView<Content: View>: View {
if !timelineItem.isOutgoing {
Spacer()
}
TimelineItemStatusView(timelineItem: timelineItem)
TimelineItemStatusView(timelineItem: timelineItem, adjustedDeliveryStatus: adjustedDeliveryStatus)
.environmentObject(context)
.padding(.top, 8)
.padding(.bottom, 3)
@@ -162,7 +163,7 @@ struct TimelineItemBubbledStylerView<Content: View>: View {
@ViewBuilder
var interactiveLocalizedSendInfo: some View {
if timelineItem.hasFailedToSend {
if adjustedDeliveryStatus == .sendingFailed {
layoutedLocalizedSendInfo
.onTapGesture {
context.sendFailedConfirmationDialogInfo = .init(itemID: timelineItem.id)
@@ -203,12 +204,12 @@ struct TimelineItemBubbledStylerView<Content: View>: View {
Text(timelineItem.timestamp)
}
if timelineItem.hasFailedToSend {
if adjustedDeliveryStatus == .sendingFailed {
CompoundIcon(\.error, size: .xSmall, relativeTo: .compound.bodyXS)
}
}
.font(.compound.bodyXS)
.foregroundColor(timelineItem.hasFailedToSend ? .compound.textCriticalPrimary : .compound.textSecondary)
.foregroundColor(adjustedDeliveryStatus == .sendingFailed ? .compound.textCriticalPrimary : .compound.textSecondary)
}
@ViewBuilder
@@ -22,6 +22,7 @@ struct TimelineItemPlainStylerView<Content: View>: View {
@Environment(\.timelineGroupStyle) private var timelineGroupStyle
let timelineItem: EventBasedTimelineItemProtocol
let adjustedDeliveryStatus: TimelineItemDeliveryStatus?
@ViewBuilder let content: () -> Content
@State private var showItemActionMenu = false
@@ -36,7 +37,7 @@ struct TimelineItemPlainStylerView<Content: View>: View {
supplementaryViews
}
}
TimelineItemStatusView(timelineItem: timelineItem)
TimelineItemStatusView(timelineItem: timelineItem, adjustedDeliveryStatus: adjustedDeliveryStatus)
.environmentObject(context)
}
}
@@ -24,13 +24,46 @@ struct TimelineStyler<Content: View>: View {
let timelineItem: EventBasedTimelineItemProtocol
@ViewBuilder let content: () -> Content
@State private var adjustedDeliveryStatus: TimelineItemDeliveryStatus?
@State private var task: Task<Void, Never>?
init(timelineItem: EventBasedTimelineItemProtocol, @ViewBuilder content: @escaping () -> Content) {
self.timelineItem = timelineItem
self.content = content
_adjustedDeliveryStatus = State(initialValue: timelineItem.properties.deliveryStatus)
}
var body: some View {
mainContent
.onChange(of: timelineItem.properties.deliveryStatus) { newStatus in
if newStatus == .sendingFailed {
guard task == nil else {
return
}
task = Task {
try? await Task.sleep(for: .milliseconds(700))
if !Task.isCancelled {
adjustedDeliveryStatus = newStatus
}
task = nil
}
} else {
task?.cancel()
task = nil
adjustedDeliveryStatus = newStatus
}
}
.animation(.elementDefault, value: adjustedDeliveryStatus)
}
@ViewBuilder
var mainContent: some View {
switch style {
case .plain:
TimelineItemPlainStylerView(timelineItem: timelineItem, content: content)
TimelineItemPlainStylerView(timelineItem: timelineItem, adjustedDeliveryStatus: adjustedDeliveryStatus, content: content)
case .bubbles:
TimelineItemBubbledStylerView(timelineItem: timelineItem, content: content)
TimelineItemBubbledStylerView(timelineItem: timelineItem, adjustedDeliveryStatus: adjustedDeliveryStatus, content: content)
}
}
}
@@ -19,6 +19,7 @@ import SwiftUI
struct TimelineItemStatusView: View {
let timelineItem: EventBasedTimelineItemProtocol
let adjustedDeliveryStatus: TimelineItemDeliveryStatus?
@Environment(\.timelineStyle) private var style
@Environment(\.readReceiptsEnabled) private var readReceiptsEnabled
@EnvironmentObject private var context: RoomScreenViewModel.Context
@@ -36,13 +37,13 @@ struct TimelineItemStatusView: View {
if !timelineItem.properties.orderedReadReceipts.isEmpty, readReceiptsEnabled {
readReceipts
} else {
deliveryStatus
deliveryStatusBadge
}
}
@ViewBuilder
var deliveryStatus: some View {
switch timelineItem.properties.deliveryStatus {
var deliveryStatusBadge: some View {
switch adjustedDeliveryStatus {
case .sending:
TimelineDeliveryStatusView(deliveryStatus: .sending)
case .sent, .none:
+1
View File
@@ -0,0 +1 @@
Added a small artificial delay when resending a failed message if it fails instantly, for better UX.
+1
View File
@@ -0,0 +1 @@
Added a disclaimer on the Mentions Only option for notifications, so that the user will know if it will work properly or not on their home server.