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