← All repositories

listless

A simple list app for Apple platforms

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


commit 26aac929f3138d295e4d057e7e4f7bbc022ff7b2
parent e15625be11894c079eec2e10f477691308327c03
Author: Michael Camilleri <[email protected]>
Date:   Wed, 11 Mar 2026 15:43:40 +0900

Tidy up pull-to-create code

This commit tidies up the code that was added as part of changing the
visual effect for the pull-to-create gesture.

Co-Authored-By: Codex GPT 5.4 <[email protected]>

Diffstat

MListlessiOS/Extensions/TaskListView+PullGestures.swift | 27+--------------------------
MListlessiOS/Extensions/TaskListView+PullToCreate.swift | 1-
MListlessiOS/Views/PullToCreate.swift | 3+--
MListlessiOS/Views/TaskListView.swift | 19++++++++++++-------
MListlessiOS/Views/TaskRowView.swift | 7-------

5 files changed, 14 insertions(+), 43 deletions(-)

diff --git a/ListlessiOS/Extensions/TaskListView+PullGestures.swift b/ListlessiOS/Extensions/TaskListView+PullGestures.swift

@@ -11,7 +11,6 @@ extension TaskListView {
         var pullOffset: CGFloat = 0
         var indicatorOffset: CGFloat = 0
         var isInsertionPending: Bool = false
-        var pendingTaskID: UUID?
         var isScrollInteracting: Bool = false
 
         private var pullStartTime: CFTimeInterval = 0
@@ -54,22 +53,12 @@ extension TaskListView {
 
             if pullOffset >= pullThreshold || isFlick {
                 isInsertionPending = true
-                pendingTaskID = nil
                 return .createTask
             }
 
             isInsertionPending = false
-            pendingTaskID = nil
             return .collapseIndicator
         }
-
-        mutating func resolvePendingInsertion(activeTaskIDs: [UUID]) {
-            guard isInsertionPending, let pendingTaskID else { return }
-            guard activeTaskIDs.contains(pendingTaskID) else { return }
-            isInsertionPending = false
-            self.pendingTaskID = nil
-            indicatorOffset = 0
-        }
     }
 }
 
@@ -81,7 +70,6 @@ private struct PullGesturesModifier: ViewModifier {
     @State private var isAtBottom = false
     @State private var clearPullStartedAtBottom = false
 
-    let activeTaskIDs: [UUID]
     let hasCompletedTasks: Bool
     let pullCreateThreshold: CGFloat
     let flickThreshold: CGFloat
@@ -110,13 +98,6 @@ private struct PullGesturesModifier: ViewModifier {
             .onScrollPhaseChange { oldPhase, newPhase in
                 handlePullToCreateScrollPhaseChange(from: oldPhase, to: newPhase)
             }
-            .onChange(of: activeTaskIDs) { _, newIDs in
-                var transaction = Transaction(animation: nil)
-                transaction.disablesAnimations = true
-                withTransaction(transaction) {
-                    pullToCreate.resolvePendingInsertion(activeTaskIDs: newIDs)
-                }
-            }
             .sensoryFeedback(
                 .impact(weight: .medium),
                 trigger: pullToCreate.pullOffset >= pullCreateThreshold
@@ -143,12 +124,8 @@ private struct PullGesturesModifier: ViewModifier {
         case .createTask:
             var transaction = Transaction(animation: .spring(response: 0.28, dampingFraction: 0.9))
             transaction.disablesAnimations = false
-            var createdTaskID: UUID?
             withTransaction(transaction) {
-                createdTaskID = onCreateTaskAtTop()
-            }
-            if let createdTaskID {
-                pullToCreate.pendingTaskID = createdTaskID
+                _ = onCreateTaskAtTop()
             }
         case .collapseIndicator:
             withAnimation(.spring(response: 0.22, dampingFraction: 0.95)) {
@@ -192,7 +169,6 @@ extension View {
         pullToCreate: Binding<TaskListView.PullToCreateState>,
         pullUpOffset: Binding<CGFloat>,
         isDragging: Binding<Bool>,
-        activeTaskIDs: [UUID],
         hasCompletedTasks: Bool,
         pullCreateThreshold: CGFloat,
         flickThreshold: CGFloat,
@@ -205,7 +181,6 @@ extension View {
                 pullToCreate: pullToCreate,
                 pullUpOffset: pullUpOffset,
                 isDragging: isDragging,
-                activeTaskIDs: activeTaskIDs,
                 hasCompletedTasks: hasCompletedTasks,
                 pullCreateThreshold: pullCreateThreshold,
                 flickThreshold: flickThreshold,

diff --git a/ListlessiOS/Extensions/TaskListView+PullToCreate.swift b/ListlessiOS/Extensions/TaskListView+PullToCreate.swift

@@ -25,7 +25,6 @@ extension TaskListView {
             selectedTaskID = nil
             var state = pullToCreate
             state.isInsertionPending = false
-            state.pendingTaskID = nil
             state.indicatorOffset = 0
             pullToCreate = state
         }

diff --git a/ListlessiOS/Views/PullToCreate.swift b/ListlessiOS/Views/PullToCreate.swift

@@ -3,7 +3,6 @@ import SwiftUI
 struct PullToCreateIndicator: View {
     let pullOffset: CGFloat
     let threshold: CGFloat
-    let topTrailingRadius: CGFloat
 
     static let indicatorHeight: CGFloat = 50
 
@@ -40,7 +39,7 @@ struct PullToCreateIndicator: View {
             UnevenRoundedRectangle(
                 topLeadingRadius: 0, bottomLeadingRadius: 0,
                 bottomTrailingRadius: TaskRowMetrics.trailingCornerRadius,
-                topTrailingRadius: topTrailingRadius
+                topTrailingRadius: TaskRowMetrics.trailingCornerRadius
             )
         )
         .overlay(alignment: .leading) {

diff --git a/ListlessiOS/Views/TaskListView.swift b/ListlessiOS/Views/TaskListView.swift

@@ -246,10 +246,6 @@ struct TaskListView: View, TaskListViewProtocol {
         return PullToCreateIndicator.indicatorHeight - pullToCreateRevealHeight
     }
 
-    private var pullToCreateIndicatorTopCornerRadius: CGFloat {
-        TaskRowMetrics.trailingCornerRadius
-    }
-
     /// Combined indicator and phantom entry row sharing the same VStack slot.
     /// The phantom's UITextView is created while the indicator is visible
     /// (during the pull), so it's ready when the user releases.
@@ -262,8 +258,7 @@ struct TaskListView: View, TaskListViewProtocol {
                     pullOffset: pullToCreate.indicatorDisplayOffset(
                         threshold: pullCreateThreshold
                     ),
-                    threshold: pullCreateThreshold,
-                    topTrailingRadius: pullToCreateIndicatorTopCornerRadius
+                    threshold: pullCreateThreshold
                 )
                 .opacity(showPhantom ? 0 : 1)
 
@@ -287,6 +282,7 @@ struct TaskListView: View, TaskListViewProtocol {
         let accentColor = taskColor(
             forIndex: 0, total: max(1, displayActiveTasks.count + 1)
         )
+        let isSelected = selectedTaskID == Self.phantomRowID
         HStack(alignment: .center, spacing: TaskRowMetrics.contentSpacing) {
             Image(systemName: "circle")
                 .frame(width: 22, height: 22)
@@ -329,6 +325,16 @@ struct TaskListView: View, TaskListViewProtocol {
                 .fill(accentColor)
                 .frame(width: TaskRowMetrics.accentBarWidth)
         }
+        .overlay(
+            isSelected
+                ? UnevenRoundedRectangle(
+                    topLeadingRadius: 0, bottomLeadingRadius: 0,
+                    bottomTrailingRadius: TaskRowMetrics.trailingCornerRadius,
+                    topTrailingRadius: TaskRowMetrics.trailingCornerRadius
+                )
+                .stroke(accentColor.opacity(0.40), lineWidth: 2)
+                : nil
+        )
     }
 
     @ViewBuilder private var taskRows: some View {
@@ -540,7 +546,6 @@ struct TaskListView: View, TaskListViewProtocol {
                 pullToCreate: pullToCreateStateBinding,
                 pullUpOffset: pullUpOffsetStateBinding,
                 isDragging: isDraggingStateBinding,
-                activeTaskIDs: activeTasks.map(\.id),
                 hasCompletedTasks: !completedTasks.isEmpty,
             pullCreateThreshold: pullCreateThreshold,
             flickThreshold: flickThreshold,

diff --git a/ListlessiOS/Views/TaskRowView.swift b/ListlessiOS/Views/TaskRowView.swift

@@ -120,13 +120,6 @@ struct TaskRowView: View {
             }
         }
         .background(cardBackground)
-        .clipShape(
-            UnevenRoundedRectangle(
-                topLeadingRadius: 0, bottomLeadingRadius: 0,
-                bottomTrailingRadius: TaskRowMetrics.trailingCornerRadius,
-                topTrailingRadius: TaskRowMetrics.trailingCornerRadius
-            )
-        )
         .overlay(alignment: .leading) {
             if !task.isCompleted {
                 Rectangle()