Skip to content

Commit

Permalink
Artificial delay when a message fails to send (#2091)
Browse files Browse the repository at this point in the history
  • Loading branch information
Velin92 authored Nov 16, 2023
1 parent 9f1092b commit 003b494
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -36,7 +37,7 @@ struct TimelineItemPlainStylerView<Content: View>: View {
supplementaryViews
}
}
TimelineItemStatusView(timelineItem: timelineItem)
TimelineItemStatusView(timelineItem: timelineItem, adjustedDeliveryStatus: adjustedDeliveryStatus)
.environmentObject(context)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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:
Expand Down
1 change: 1 addition & 0 deletions changelog.d/1352.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Added a small artificial delay when resending a failed message if it fails instantly, for better UX.
1 change: 1 addition & 0 deletions changelog.d/2078.feature
Original file line number Diff line number Diff line change
@@ -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.

0 comments on commit 003b494

Please sign in to comment.