listless

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

commit 7cba48e134ed7925eff330ca039434dc89e73740
parent f7fd505561ba27161bed9b87b0021ec7ae1199c7
Author: Michael Camilleri <[email protected]>
Date:   Fri, 13 Mar 2026 10:10:56 +0900

Simplify draft row-related variable names

Diffstat:
MListless/Extensions/TaskListView+Logic.swift | 28++++++++++++++--------------
MListless/Helpers/TaskListViewProtocol.swift | 4++--
MListlessMac/Helpers/ClickableTextField.swift | 23++++++++---------------
MListlessMac/Views/TaskListView.swift | 30+++++++++++++++---------------
MListlessiOS/Views/TaskListView.swift | 40++++++++++++++++++++--------------------
5 files changed, 59 insertions(+), 66 deletions(-)

diff --git a/Listless/Extensions/TaskListView+Logic.swift b/Listless/Extensions/TaskListView+Logic.swift @@ -58,7 +58,7 @@ extension TaskListViewProtocol { return lastTask.id == taskID } - func draftTaskID(for placement: DraftTaskPlacement) -> UUID { + func draftID(for placement: DraftTaskPlacement) -> UUID { switch placement { case .prepend: draftPrependRowID @@ -67,7 +67,7 @@ extension TaskListViewProtocol { } } - func draftTaskPlacement(for taskID: UUID) -> DraftTaskPlacement? { + func draftPlacement(for taskID: UUID) -> DraftTaskPlacement? { switch taskID { case draftPrependRowID: .prepend @@ -90,22 +90,22 @@ extension TaskListViewProtocol { } func revealDraftTask(at placement: DraftTaskPlacement) { - if draftTaskPlacement != placement, draftTaskPlacement != nil { + if draftPlacement != placement, draftPlacement != nil { commitDraftTask() } clearDragState() - let taskID = draftTaskID(for: placement) - draftTaskTitle = "" - draftTaskPlacement = placement + let taskID = draftID(for: placement) + draftTitle = "" + draftPlacement = placement fState.pendingFocus = .task(taskID) focusedField = .task(taskID) fState.selectedTaskID = taskID } func beginDraftTaskEditing(_ placement: DraftTaskPlacement) { - guard draftTaskPlacement == placement else { return } - let taskID = draftTaskID(for: placement) + guard draftPlacement == placement else { return } + let taskID = draftID(for: placement) fState.selectedTaskID = taskID if case .task(let id) = fState.pendingFocus, id == taskID { fState.pendingFocus = nil @@ -113,9 +113,9 @@ extension TaskListViewProtocol { } func commitDraftTask(shouldCreateNewTask: Bool = false) { - guard let placement = draftTaskPlacement else { return } - let taskID = draftTaskID(for: placement) - let title = draftTaskTitle.trimmingCharacters(in: .whitespacesAndNewlines) + guard let placement = draftPlacement else { return } + let taskID = draftID(for: placement) + let title = draftTitle.trimmingCharacters(in: .whitespacesAndNewlines) // Clear fState.pendingFocus before clearDraftTaskUI so that the iOS // onChange(of: focusedFieldBinding) nil-redirect doesn't re-focus @@ -193,7 +193,7 @@ extension TaskListViewProtocol { if isTaskFocused || fState.selectedTaskID != nil { fState.pendingFocus = nil - if draftTaskPlacement != nil { + if draftPlacement != nil { commitDraftTask() } fState.selectedTaskID = nil @@ -211,7 +211,7 @@ extension TaskListViewProtocol { return } - if draftTaskPlacement(for: oldID) != nil { + if draftPlacement(for: oldID) != nil { return } @@ -422,7 +422,7 @@ extension TaskListViewProtocol { } func endEditing(_ taskID: UUID, shouldCreateNewTask: Bool) { - if draftTaskPlacement(for: taskID) != nil { + if draftPlacement(for: taskID) != nil { commitDraftTask(shouldCreateNewTask: shouldCreateNewTask) return } diff --git a/Listless/Helpers/TaskListViewProtocol.swift b/Listless/Helpers/TaskListViewProtocol.swift @@ -10,8 +10,8 @@ protocol TaskListViewProtocol { var focusedField: FocusField? { get nonmutating set } var fState: FocusStateData { get nonmutating set } var dragState: DragState { get nonmutating set } - var draftTaskPlacement: DraftTaskPlacement? { get nonmutating set } - var draftTaskTitle: String { get nonmutating set } + var draftPlacement: DraftTaskPlacement? { get nonmutating set } + var draftTitle: String { get nonmutating set } func didStartDrag() func clearDraftTaskUI(at placement: DraftTaskPlacement, hasTitle: Bool) } diff --git a/ListlessMac/Helpers/ClickableTextField.swift b/ListlessMac/Helpers/ClickableTextField.swift @@ -115,25 +115,16 @@ struct ClickableTextField: NSViewRepresentable { // Calculate text height with wrapping private func calculateHeight(for text: String, width: CGFloat, font: NSFont) -> CGFloat { - let attributedString = NSAttributedString( - string: text.isEmpty ? "Enter text" : text, + let displayText = text.isEmpty ? "Enter text" : text + let rect = (displayText as NSString).boundingRect( + with: CGSize(width: width, height: .greatestFiniteMagnitude), + options: [.usesLineFragmentOrigin, .usesFontLeading], attributes: [.font: font] ) - let textStorage = NSTextStorage(attributedString: attributedString) - let layoutManager = NSLayoutManager() - let textContainer = NSTextContainer( - size: CGSize(width: width, height: .greatestFiniteMagnitude)) - textContainer.lineFragmentPadding = 0 - - layoutManager.addTextContainer(textContainer) - textStorage.addLayoutManager(layoutManager) - - layoutManager.ensureLayout(for: textContainer) - let rect = layoutManager.usedRect(for: textContainer) - return ceil(rect.height) + 4 } + @MainActor final class Coordinator: NSObject, NSTextFieldDelegate { @Binding var text: String let onEditingChanged: (Bool, _ shouldCreateNewTask: Bool) -> Void @@ -150,7 +141,6 @@ struct ClickableTextField: NSViewRepresentable { self.onContentChange = onContentChange } - @MainActor func applyStyle(to textField: NSTextField, text: String, isCompleted: Bool) { guard !text.isEmpty else { textField.stringValue = "" @@ -197,6 +187,9 @@ struct ClickableTextField: NSViewRepresentable { ) -> Bool { + // Note: makeFirstResponder(nil) can trigger a Thread Performance + // Checker priority inversion warning. This is internal to AppKit's + // first responder machinery, not caused by our callback chain. if commandSelector == #selector(NSResponder.insertNewline(_:)) { // Return key pressed editEndReason = .returnKey diff --git a/ListlessMac/Views/TaskListView.swift b/ListlessMac/Views/TaskListView.swift @@ -5,8 +5,8 @@ struct TaskListView: View, TaskListViewProtocol { struct InteractionStateData { var dragState: DragState = .idle var liftedTaskID: UUID? - var draftTaskPlacement: DraftTaskPlacement? - var draftTaskTitle: String = "" + var draftPlacement: DraftTaskPlacement? + var draftTitle: String = "" } @Environment(\.undoManager) var undoManager @@ -37,14 +37,14 @@ struct TaskListView: View, TaskListViewProtocol { nonmutating set { iState.dragState = newValue } } - var draftTaskPlacement: DraftTaskPlacement? { - get { iState.draftTaskPlacement } - nonmutating set { iState.draftTaskPlacement = newValue } + var draftPlacement: DraftTaskPlacement? { + get { iState.draftPlacement } + nonmutating set { iState.draftPlacement = newValue } } - var draftTaskTitle: String { - get { iState.draftTaskTitle } - nonmutating set { iState.draftTaskTitle = newValue } + var draftTitle: String { + get { iState.draftTitle } + nonmutating set { iState.draftTitle = newValue } } var vStackSpacing: CGFloat { 0 } @@ -150,11 +150,11 @@ struct TaskListView: View, TaskListViewProtocol { } func clearDraftTaskUI(at placement: DraftTaskPlacement, hasTitle _: Bool) { - if draftTaskPlacement == placement { - draftTaskPlacement = nil + if draftPlacement == placement { + draftPlacement = nil } - draftTaskTitle = "" - if fState.selectedTaskID == draftTaskID(for: placement) { + draftTitle = "" + if fState.selectedTaskID == draftID(for: placement) { fState.selectedTaskID = nil } focusedField = nil @@ -242,7 +242,7 @@ struct TaskListView: View, TaskListViewProtocol { } } - if draftTaskPlacement == .append { + if draftPlacement == .append { let total = max(1, displayActiveTasks.count + 1) let index = displayActiveTasks.count let accentColor = cachedTaskColor( @@ -260,8 +260,8 @@ struct TaskListView: View, TaskListViewProtocol { ClickableTextField( text: Binding( - get: { iState.draftTaskTitle }, - set: { iState.draftTaskTitle = $0 } + get: { iState.draftTitle }, + set: { iState.draftTitle = $0 } ), isCompleted: false, onEditingChanged: { editing, shouldCreateNewTask in diff --git a/ListlessiOS/Views/TaskListView.swift b/ListlessiOS/Views/TaskListView.swift @@ -12,8 +12,8 @@ struct TaskListView: View, TaskListViewProtocol { var clearingTaskIDs: Set<UUID> = [] var rowFrames: [UUID: CGRect] = [:] var undoToast: UndoToastData? = nil - var draftTaskPlacement: DraftTaskPlacement? - var draftTaskTitle: String = "" + var draftPlacement: DraftTaskPlacement? + var draftTitle: String = "" } @AppStorage("headingText") var headingText = "Items" @@ -44,28 +44,28 @@ struct TaskListView: View, TaskListViewProtocol { nonmutating set { iState.dragState = newValue } } - var draftTaskPlacement: DraftTaskPlacement? { - get { iState.draftTaskPlacement } - nonmutating set { iState.draftTaskPlacement = newValue } + var draftPlacement: DraftTaskPlacement? { + get { iState.draftPlacement } + nonmutating set { iState.draftPlacement = newValue } } - var draftTaskTitle: String { - get { iState.draftTaskTitle } - nonmutating set { iState.draftTaskTitle = newValue } + var draftTitle: String { + get { iState.draftTitle } + nonmutating set { iState.draftTitle = newValue } } private var isPrependDraftVisible: Bool { - draftTaskPlacement == .prepend + draftPlacement == .prepend } private var isAppendDraftVisible: Bool { - draftTaskPlacement == .append + draftPlacement == .append } - var draftTaskTitleBinding: Binding<String> { + var draftTitleBinding: Binding<String> { Binding( - get: { iState.draftTaskTitle }, - set: { iState.draftTaskTitle = $0 } + get: { iState.draftTitle }, + set: { iState.draftTitle = $0 } ) } @@ -160,11 +160,11 @@ struct TaskListView: View, TaskListViewProtocol { func clearDraftTaskUI(at placement: DraftTaskPlacement, hasTitle: Bool) { let clear: () -> Void = { - if draftTaskPlacement == placement { - draftTaskPlacement = nil + if draftPlacement == placement { + draftPlacement = nil } - draftTaskTitle = "" - if fState.selectedTaskID == draftTaskID(for: placement) { + draftTitle = "" + if fState.selectedTaskID == draftID(for: placement) { fState.selectedTaskID = nil } @@ -283,7 +283,7 @@ struct TaskListView: View, TaskListViewProtocol { .font(.system(size: 17)) TappableTextField( - text: draftTaskTitleBinding, + text: draftTitleBinding, isCompleted: false, isDragging: false, onEditingChanged: { editing, _ in @@ -345,7 +345,7 @@ struct TaskListView: View, TaskListViewProtocol { .font(.system(size: 17)) TappableTextField( - text: draftTaskTitleBinding, + text: draftTitleBinding, isCompleted: false, isDragging: false, onEditingChanged: { editing, shouldCreateNewTask in @@ -359,7 +359,7 @@ struct TaskListView: View, TaskListViewProtocol { } } }, - returnKeyType: draftTaskTitle.trimmingCharacters( + returnKeyType: draftTitle.trimmingCharacters( in: .whitespacesAndNewlines ).isEmpty ? .done : .next )