← All repositories

listless

A simple list app for Apple platforms

git clone https://code.inqk.net/listless.git


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

MListlessiOS/Extensions/ItemListView+Undo.swift | 1+
MListlessiOS/Views/ItemListView.swift | 1+
MListlessiOS/Views/ItemRowView.swift | 15++++++++++++---

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),