commit cfeed7a5f1aa2c64e5b8382009d5ab76eb3c9f6f
parent 073bb63d24395b47ba5e4230506ef4c7fb766c8e
Author: Michael Camilleri <[email protected]>
Date: Wed, 1 Apr 2026 15:49:59 +0900
Implement more robust reset after undoing
Prior to this commit, it is possible to trigger an animation bug where a
swipe-to-delete animation is 'preserved' after a user presses undo. This
change addresses this using a state value that all rows observe (which
is a little inelegant but has a simpler implementation).
Co-Authored-By: Claude 4.6 Opus <[email protected]>
Diffstat:
3 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/ListlessiOS/Extensions/ItemListView+Undo.swift b/ListlessiOS/Extensions/ItemListView+Undo.swift
@@ -68,6 +68,7 @@ extension ItemListView {
} catch {
presentStoreError(error)
}
+ iState.undoGeneration &+= 1
dismissUndoToast()
}
diff --git a/ListlessiOS/Views/ItemListView.swift b/ListlessiOS/Views/ItemListView.swift
@@ -23,6 +23,7 @@ struct ItemListView: View, ItemListViewProtocol {
var draftPlacement: DraftItemPlacement?
var draftTitle: String = ""
var fetchWorkaround: Int = 0
+ var undoGeneration: Int = 0
var isShowingOverlay: Bool {
isShowingSettings || isShowingSyncDiagnostics || isShowingRenameAlert
diff --git a/ListlessiOS/Views/ItemRowView.swift b/ListlessiOS/Views/ItemRowView.swift
@@ -15,6 +15,7 @@ struct ItemRowView: View {
let isLastActiveItem: Bool
let onStartEdit: (UUID) -> Void
let onEndEdit: (UUID, _ shouldCreateNewItem: Bool) -> Void
+ let undoGeneration: Int
@FocusState.Binding var focusedField: FocusField?
@AppStorage("colorTheme") private var colorThemeRaw = 0
@@ -36,6 +37,7 @@ struct ItemRowView: View {
isDragging: Binding<Bool> = .constant(false),
isSwiping: Binding<Bool> = .constant(false),
isLastActiveItem: Bool = false,
+ undoGeneration: Int = 0,
focusedField: FocusState<FocusField?>.Binding,
onToggle: @escaping (UUID) -> Void,
onTitleChange: @escaping (UUID, String) -> Void,
@@ -52,6 +54,7 @@ struct ItemRowView: View {
_isDragging = isDragging
_isSwiping = isSwiping
self.isLastActiveItem = isLastActiveItem
+ self.undoGeneration = undoGeneration
self.onToggle = onToggle
self.onTitleChange = onTitleChange
self.onDelete = onDelete
@@ -158,9 +161,6 @@ struct ItemRowView: View {
.onAppear {
editingTitle = item.title
cachedAccentColor = computeAccentColor()
- swipeOffset = 0
- swipeDirection = .none
- isSwipeTriggered = false
}
.onChange(of: item.title) { _, newValue in
if !isCurrentlyEditing {
@@ -176,6 +176,15 @@ struct ItemRowView: View {
.onChange(of: colorThemeRaw) { _, _ in
cachedAccentColor = computeAccentColor()
}
+ .onChange(of: undoGeneration) { _, _ in
+ var transaction = Transaction(animation: nil)
+ transaction.disablesAnimations = true
+ withTransaction(transaction) {
+ swipeOffset = 0
+ swipeDirection = .none
+ isSwipeTriggered = false
+ }
+ }
.itemSwipeGesture(
isDragging: $isDragging,
isEditing: focusedField == .item(itemID),