listless

A simple list app for Apple platforms
Log | Files | Refs | README | LICENSE

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