commit 79287d36d80f9fc71e7e950d8cc439b034eaf7bc
parent 5373c36ceee1b853e64962aa2f0ebb0031352296
Author: Michael Camilleri <[email protected]>
Date: Sun, 8 Feb 2026 14:14:45 +0900
Use swift-format to format code
Co-Authored-By: Claude 4.5 Sonnet <[email protected]>
Diffstat:
14 files changed, 196 insertions(+), 76 deletions(-)
diff --git a/.swift-format b/.swift-format
@@ -0,0 +1,75 @@
+{
+ "fileScopedDeclarationPrivacy" : {
+ "accessLevel" : "private"
+ },
+ "indentConditionalCompilationBlocks" : true,
+ "indentSwitchCaseLabels" : false,
+ "indentation" : {
+ "spaces" : 4
+ },
+ "lineBreakAroundMultilineExpressionChainComponents" : false,
+ "lineBreakBeforeControlFlowKeywords" : false,
+ "lineBreakBeforeEachArgument" : false,
+ "lineBreakBeforeEachGenericRequirement" : false,
+ "lineBreakBetweenDeclarationAttributes" : false,
+ "lineLength" : 100,
+ "maximumBlankLines" : 1,
+ "multiElementCollectionTrailingCommas" : true,
+ "noAssignmentInExpressions" : {
+ "allowedFunctions" : [
+ "XCTAssertNoThrow"
+ ]
+ },
+ "prioritizeKeepingFunctionOutputTogether" : false,
+ "reflowMultilineStringLiterals" : "never",
+ "respectsExistingLineBreaks" : true,
+ "rules" : {
+ "AllPublicDeclarationsHaveDocumentation" : false,
+ "AlwaysUseLiteralForEmptyCollectionInit" : false,
+ "AlwaysUseLowerCamelCase" : true,
+ "AmbiguousTrailingClosureOverload" : true,
+ "AvoidRetroactiveConformances" : true,
+ "BeginDocumentationCommentWithOneLineSummary" : false,
+ "DoNotUseSemicolons" : true,
+ "DontRepeatTypeInStaticProperties" : true,
+ "FileScopedDeclarationPrivacy" : true,
+ "FullyIndirectEnum" : true,
+ "GroupNumericLiterals" : true,
+ "IdentifiersMustBeASCII" : true,
+ "NeverForceUnwrap" : false,
+ "NeverUseForceTry" : false,
+ "NeverUseImplicitlyUnwrappedOptionals" : false,
+ "NoAccessLevelOnExtensionDeclaration" : true,
+ "NoAssignmentInExpressions" : true,
+ "NoBlockComments" : true,
+ "NoCasesWithOnlyFallthrough" : true,
+ "NoEmptyLinesOpeningClosingBraces" : false,
+ "NoEmptyTrailingClosureParentheses" : true,
+ "NoLabelsInCasePatterns" : true,
+ "NoLeadingUnderscores" : false,
+ "NoParensAroundConditions" : true,
+ "NoPlaygroundLiterals" : true,
+ "NoVoidReturnOnFunctionSignature" : true,
+ "OmitExplicitReturns" : false,
+ "OneCasePerLine" : true,
+ "OneVariableDeclarationPerLine" : true,
+ "OnlyOneTrailingClosureArgument" : true,
+ "OrderedImports" : true,
+ "ReplaceForEachWithForLoop" : true,
+ "ReturnVoidInsteadOfEmptyTuple" : true,
+ "TypeNamesShouldBeCapitalized" : true,
+ "UseEarlyExits" : false,
+ "UseExplicitNilCheckInConditions" : true,
+ "UseLetInEveryBoundCaseVariable" : true,
+ "UseShorthandTypeNames" : true,
+ "UseSingleLinePropertyGetter" : true,
+ "UseSynthesizedInitializer" : true,
+ "UseTripleSlashForDocumentationComments" : true,
+ "UseWhereClausesInForLoops" : false,
+ "ValidateDocumentationComments" : false
+ },
+ "spacesAroundRangeFormationOperators" : false,
+ "spacesBeforeEndOfLineComments" : 2,
+ "tabWidth" : 8,
+ "version" : 1
+}
diff --git a/Listless/Models/TaskItem.swift b/Listless/Models/TaskItem.swift
@@ -1,5 +1,5 @@
-import Foundation
import CoreData
+import Foundation
@objc(TaskItem)
public class TaskItem: NSManagedObject, Identifiable {
diff --git a/Listless/Models/TaskStore.swift b/Listless/Models/TaskStore.swift
@@ -1,5 +1,5 @@
-import Foundation
import CoreData
+import Foundation
import Observation
@MainActor
diff --git a/Listless/Sync/PersistenceController.swift b/Listless/Sync/PersistenceController.swift
@@ -27,7 +27,8 @@ final class PersistenceController {
)
description.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey)
- description.setOption(true as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey)
+ description.setOption(
+ true as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey)
}
container.loadPersistentStores { storeDescription, error in
@@ -37,7 +38,8 @@ final class PersistenceController {
}
container.viewContext.automaticallyMergesChangesFromParent = true
- container.viewContext.mergePolicy = NSMergePolicy(merge: .mergeByPropertyObjectTrumpMergePolicyType)
+ container.viewContext.mergePolicy = NSMergePolicy(
+ merge: .mergeByPropertyObjectTrumpMergePolicyType)
performDataMigrationIfNeeded()
}
diff --git a/Listless/Views/TaskListView.swift b/Listless/Views/TaskListView.swift
@@ -61,31 +61,37 @@ struct TaskListView: View {
Color.clear
.frame(maxHeight: .infinity)
.layoutPriority(1)
- .dropDestination(for: String.self, action: { _, _ in false }, isTargeted: { isTargeted in
- if isTargeted {
- updateVisualOrder(insertBefore: task.id)
- }
- })
+ .dropDestination(
+ for: String.self, action: { _, _ in false },
+ isTargeted: { isTargeted in
+ if isTargeted {
+ updateVisualOrder(insertBefore: task.id)
+ }
+ })
// Middle 2/3 - insert based on direction
Color.clear
.frame(maxHeight: .infinity)
.layoutPriority(4)
- .dropDestination(for: String.self, action: { _, _ in false }, isTargeted: { isTargeted in
- if isTargeted {
- updateVisualOrderSmart(relativeTo: task.id)
- }
- })
+ .dropDestination(
+ for: String.self, action: { _, _ in false },
+ isTargeted: { isTargeted in
+ if isTargeted {
+ updateVisualOrderSmart(relativeTo: task.id)
+ }
+ })
// Bottom 1/6 - insert AFTER
Color.clear
.frame(maxHeight: .infinity)
.layoutPriority(1)
- .dropDestination(for: String.self, action: { _, _ in false }, isTargeted: { isTargeted in
- if isTargeted {
- updateVisualOrder(insertAfter: task.id)
- }
- })
+ .dropDestination(
+ for: String.self, action: { _, _ in false },
+ isTargeted: { isTargeted in
+ if isTargeted {
+ updateVisualOrder(insertAfter: task.id)
+ }
+ })
}
}
}
@@ -95,11 +101,13 @@ struct TaskListView: View {
if !activeTasks.isEmpty && draggedTaskID != nil {
Color.clear
.frame(height: 44)
- .dropDestination(for: String.self, action: { _, _ in false }, isTargeted: { isTargeted in
- if isTargeted {
- updateVisualOrder(insertAtEnd: true)
- }
- })
+ .dropDestination(
+ for: String.self, action: { _, _ in false },
+ isTargeted: { isTargeted in
+ if isTargeted {
+ updateVisualOrder(insertAtEnd: true)
+ }
+ })
}
ForEach(completedTasks) { task in
@@ -235,7 +243,9 @@ struct TaskListView: View {
}
private func handleFocusChange(from oldValue: FocusField?, to newValue: FocusField?) {
- print("🟣 handleFocusChange() from: \(String(describing: oldValue)) to: \(String(describing: newValue))")
+ print(
+ "🟣 handleFocusChange() from: \(String(describing: oldValue)) to: \(String(describing: newValue))"
+ )
let oldID = taskID(from: oldValue)
let newID = taskID(from: newValue)
@@ -248,7 +258,7 @@ struct TaskListView: View {
}
private func taskID(from field: FocusField?) -> UUID? {
- guard case let .task(id) = field else { return nil }
+ guard case .task(let id) = field else { return nil }
return id
}
@@ -274,7 +284,6 @@ struct TaskListView: View {
managedObjectContext.undoManager?.enableUndoRegistration()
}
-
private func updateTitle(_ task: TaskItem, _ title: String) {
guard task.title != title else { return }
store.updateWithoutSaving(taskID: task.id, title: title)
@@ -362,7 +371,9 @@ struct TaskListView: View {
private func toggleSelectedTask() -> KeyPress.Result {
guard focusedField == .scrollView else { return .ignored }
guard let currentID = selectedTaskID else { return .handled }
- guard let task = allTasksInDisplayOrder.first(where: { $0.id == currentID }) else { return .handled }
+ guard let task = allTasksInDisplayOrder.first(where: { $0.id == currentID }) else {
+ return .handled
+ }
toggleCompletion(task)
return .handled
}
@@ -370,7 +381,9 @@ struct TaskListView: View {
private func focusSelectedTask() -> KeyPress.Result {
guard focusedField == .scrollView else { return .ignored }
guard let currentID = selectedTaskID else { return .handled }
- guard let task = allTasksInDisplayOrder.first(where: { $0.id == currentID }) else { return .handled }
+ guard let task = allTasksInDisplayOrder.first(where: { $0.id == currentID }) else {
+ return .handled
+ }
guard !task.isCompleted else { return .handled }
startEditing(currentID)
return .handled
@@ -395,7 +408,6 @@ struct TaskListView: View {
return .handled
}
-
// MARK: - Focus Management
private func focusTextField(_ taskID: UUID) {
@@ -410,14 +422,17 @@ struct TaskListView: View {
}
private func endEditing(_ taskID: UUID, shouldCreateNewTask: Bool) {
- print("🟢 endEditing() called for task \(taskID), shouldCreateNewTask: \(shouldCreateNewTask)")
+ print(
+ "🟢 endEditing() called for task \(taskID), shouldCreateNewTask: \(shouldCreateNewTask)")
// Save any pending changes
store.save()
// Check conditions BEFORE deleting the task
let wasLastActiveTask = isLastActiveTask(taskID)
let willBeDeleted = shouldDeleteIfEmpty(taskID: taskID)
- print("🟢 endEditing() wasLastActiveTask: \(wasLastActiveTask), willBeDeleted: \(willBeDeleted)")
+ print(
+ "🟢 endEditing() wasLastActiveTask: \(wasLastActiveTask), willBeDeleted: \(willBeDeleted)"
+ )
if willBeDeleted {
print("🟢 endEditing() deleting task - focus will be repaired automatically by onChange")
@@ -453,7 +468,8 @@ struct TaskListView: View {
private func updateVisualOrder(insertBefore targetID: UUID) {
guard let draggedID = draggedTaskID,
- let order = visualOrder else { return }
+ let order = visualOrder
+ else { return }
var newOrder = order.filter { $0 != draggedID }
if let targetIndex = newOrder.firstIndex(of: targetID) {
@@ -469,7 +485,8 @@ struct TaskListView: View {
private func updateVisualOrder(insertAfter targetID: UUID) {
guard let draggedID = draggedTaskID,
- let order = visualOrder else { return }
+ let order = visualOrder
+ else { return }
var newOrder = order.filter { $0 != draggedID }
if let targetIndex = newOrder.firstIndex(of: targetID) {
@@ -485,11 +502,13 @@ struct TaskListView: View {
private func updateVisualOrderSmart(relativeTo targetID: UUID) {
guard let draggedID = draggedTaskID,
- let order = visualOrder else { return }
+ let order = visualOrder
+ else { return }
// Determine if dragged item is currently above or below target
guard let draggedIndex = order.firstIndex(of: draggedID),
- let targetIndex = order.firstIndex(of: targetID) else { return }
+ let targetIndex = order.firstIndex(of: targetID)
+ else { return }
if draggedIndex < targetIndex {
// Dragging from above → insert after target
@@ -502,7 +521,8 @@ struct TaskListView: View {
private func updateVisualOrder(insertAtEnd: Bool) {
guard let draggedID = draggedTaskID,
- let order = visualOrder else { return }
+ let order = visualOrder
+ else { return }
var newOrder = order.filter { $0 != draggedID }
newOrder.append(draggedID)
@@ -516,9 +536,10 @@ struct TaskListView: View {
private func handleDrop(items: [String]) -> Bool {
guard let droppedUUIDString = items.first,
- let droppedUUID = UUID(uuidString: droppedUUIDString),
- let order = visualOrder,
- let finalIndex = order.firstIndex(of: droppedUUID) else {
+ let droppedUUID = UUID(uuidString: droppedUUIDString),
+ let order = visualOrder,
+ let finalIndex = order.firstIndex(of: droppedUUID)
+ else {
draggedTaskID = nil
visualOrder = nil
return false
diff --git a/Listless/Views/TaskRowView.swift b/Listless/Views/TaskRowView.swift
@@ -34,9 +34,9 @@ struct TaskRowView: View {
let progress = Double(index) / Double(totalTasks - 1)
// Define color stops based on the gradient image
- let topColor = Color(hue: 0.98, saturation: 0.85, brightness: 1.0) // Coral/red
- let midColor = Color(hue: 0.88, saturation: 0.75, brightness: 0.95) // Pink/magenta
- let bottomColor = Color(hue: 0.72, saturation: 0.65, brightness: 0.85) // Purple/blue
+ let topColor = Color(hue: 0.98, saturation: 0.85, brightness: 1.0) // Coral/red
+ let midColor = Color(hue: 0.88, saturation: 0.75, brightness: 0.95) // Pink/magenta
+ let bottomColor = Color(hue: 0.72, saturation: 0.65, brightness: 0.85) // Purple/blue
// Interpolate between colors
if progress < 0.5 {
@@ -123,7 +123,8 @@ struct TaskRowView: View {
)
.focused($focusedField, equals: .task(taskID))
.frame(maxWidth: .infinity, alignment: .leading)
- .accessibilityIdentifier(isCurrentlyEditing ? "task-textfield" : "task-text-\(task.title)")
+ .accessibilityIdentifier(
+ isCurrentlyEditing ? "task-textfield" : "task-text-\(task.title)")
}
.padding(.vertical, 8)
.padding(.horizontal, 16)
@@ -209,19 +210,19 @@ struct TaskRowView: View {
let text = isEditing ? editingTitle : task.title
guard !text.isEmpty else { return }
#if os(macOS)
- let pasteboard = NSPasteboard.general
- pasteboard.clearContents()
- pasteboard.setString(text, forType: .string)
+ let pasteboard = NSPasteboard.general
+ pasteboard.clearContents()
+ pasteboard.setString(text, forType: .string)
#else
- UIPasteboard.general.string = text
+ UIPasteboard.general.string = text
#endif
}
private func pasteFromPasteboard() {
#if os(macOS)
- guard let string = NSPasteboard.general.string(forType: .string) else { return }
+ guard let string = NSPasteboard.general.string(forType: .string) else { return }
#else
- guard let string = UIPasteboard.general.string else { return }
+ guard let string = UIPasteboard.general.string else { return }
#endif
if isEditing {
editingTitle = string
diff --git a/ListlessMac/Views/ClickableTextField.swift b/ListlessMac/Views/ClickableTextField.swift
@@ -1,5 +1,5 @@
-import SwiftUI
import AppKit
+import SwiftUI
/// Custom NSTextField that notifies when clicked (becomes first responder)
class ClickableNSTextField: NSTextField {
@@ -33,7 +33,7 @@ struct ClickableTextField: NSViewRepresentable {
textField.cell?.wraps = true
textField.cell?.isScrollable = false
textField.isSelectable = true // Shows I-beam cursor on hover
- textField.isEditable = true // Always editable, becomes first responder on click
+ textField.isEditable = true // Always editable, becomes first responder on click
// Notify when field is clicked (becomes first responder)
textField.onBecomeFirstResponder = {
@@ -62,19 +62,24 @@ struct ClickableTextField: NSViewRepresentable {
textField.isSelectable = !isCompleted
}
- func sizeThatFits(_ proposal: ProposedViewSize, nsView: ClickableNSTextField, context: Context) -> CGSize? {
+ func sizeThatFits(_ proposal: ProposedViewSize, nsView: ClickableNSTextField, context: Context)
+ -> CGSize?
+ {
let maxWidth = proposal.width ?? 300
let isEditing = nsView.currentEditor() != nil
// Always calculate height based on maxWidth to preserve multiline wrapping
- let height = calculateHeight(for: text, width: maxWidth, font: nsView.font ?? .systemFont(ofSize: NSFont.systemFontSize))
+ let height = calculateHeight(
+ for: text, width: maxWidth,
+ font: nsView.font ?? .systemFont(ofSize: NSFont.systemFontSize))
if isEditing {
// When editing, take full width
return CGSize(width: maxWidth, height: max(height, 22))
} else {
// When not editing, size width to content but maintain multiline height
- let width = calculateWidth(for: text, font: nsView.font ?? .systemFont(ofSize: NSFont.systemFontSize))
+ let width = calculateWidth(
+ for: text, font: nsView.font ?? .systemFont(ofSize: NSFont.systemFontSize))
return CGSize(width: min(width, maxWidth), height: max(height, 22))
}
}
@@ -107,7 +112,8 @@ struct ClickableTextField: NSViewRepresentable {
)
let textStorage = NSTextStorage(attributedString: attributedString)
let layoutManager = NSLayoutManager()
- let textContainer = NSTextContainer(size: CGSize(width: width, height: .greatestFiniteMagnitude))
+ let textContainer = NSTextContainer(
+ size: CGSize(width: width, height: .greatestFiniteMagnitude))
textContainer.lineFragmentPadding = 0
layoutManager.addTextContainer(textContainer)
@@ -124,7 +130,10 @@ struct ClickableTextField: NSViewRepresentable {
let onEditingChanged: (Bool, _ shouldCreateNewTask: Bool) -> Void
var editEndReason: EditEndReason = .focusLost
- init(text: Binding<String>, onEditingChanged: @escaping (Bool, _ shouldCreateNewTask: Bool) -> Void) {
+ init(
+ text: Binding<String>,
+ onEditingChanged: @escaping (Bool, _ shouldCreateNewTask: Bool) -> Void
+ ) {
_text = text
self.onEditingChanged = onEditingChanged
}
@@ -134,11 +143,14 @@ struct ClickableTextField: NSViewRepresentable {
let displayText = text.isEmpty ? "New task" : text
let attributes: [NSAttributedString.Key: Any] = [
.font: NSFont.systemFont(ofSize: NSFont.systemFontSize),
- .foregroundColor: text.isEmpty ? NSColor.secondaryLabelColor : (isCompleted ? NSColor.secondaryLabelColor : NSColor.labelColor),
+ .foregroundColor: text.isEmpty
+ ? NSColor.secondaryLabelColor
+ : (isCompleted ? NSColor.secondaryLabelColor : NSColor.labelColor),
.strikethroughStyle: isCompleted ? NSUnderlineStyle.single.rawValue : 0,
- .strikethroughColor: NSColor.secondaryLabelColor
+ .strikethroughColor: NSColor.secondaryLabelColor,
]
- textField.attributedStringValue = NSAttributedString(string: displayText, attributes: attributes)
+ textField.attributedStringValue = NSAttributedString(
+ string: displayText, attributes: attributes)
}
func handleBecomeFirstResponder() {
@@ -158,7 +170,11 @@ struct ClickableTextField: NSViewRepresentable {
text = textField.stringValue
}
- func control(_ control: NSControl, textView: NSTextView, doCommandBy commandSelector: Selector) -> Bool {
+ func control(
+ _ control: NSControl, textView: NSTextView, doCommandBy commandSelector: Selector
+ )
+ -> Bool
+ {
print("🟡 ClickableTextField.doCommandBy selector: \(commandSelector)")
if commandSelector == #selector(NSResponder.insertNewline(_:)) {
// Return key pressed
diff --git a/ListlessMac/Views/HoverCursorModifier.swift b/ListlessMac/Views/HoverCursorModifier.swift
@@ -1,5 +1,5 @@
-import SwiftUI
import AppKit
+import SwiftUI
struct TextHoverModifier: ViewModifier {
let isCompleted: Bool
diff --git a/ListlessMac/Views/PlatformScrollIndicatorsModifier.swift b/ListlessMac/Views/PlatformScrollIndicatorsModifier.swift
@@ -18,7 +18,8 @@ private struct PlatformScrollIndicatorsModifier: ViewModifier {
content
.background(
GeometryReader { contentProxy in
- Color.clear.preference(key: ContentHeightKey.self, value: contentProxy.size.height)
+ Color.clear.preference(
+ key: ContentHeightKey.self, value: contentProxy.size.height)
}
)
.scrollIndicators(effectiveContentHeight > proxy.size.height ? .visible : .hidden)
diff --git a/ListlessMac/Views/PlatformTextFieldWidthModifier.swift b/ListlessMac/Views/PlatformTextFieldWidthModifier.swift
@@ -32,7 +32,8 @@ private struct MacTextFieldWidthModifier: ViewModifier {
.fixedSize()
.background(
GeometryReader { proxy in
- Color.clear.preference(key: TextFieldWidthPreferenceKey.self, value: proxy.size.width)
+ Color.clear.preference(
+ key: TextFieldWidthPreferenceKey.self, value: proxy.size.width)
}
)
.hidden()
diff --git a/ListlessMac/Views/TaskListView+Toolbar.swift b/ListlessMac/Views/TaskListView+Toolbar.swift
@@ -20,7 +20,8 @@ extension TaskListView {
Button {
if let currentID = selectedTaskID,
- let task = allTasksInDisplayOrder.first(where: { $0.id == currentID }) {
+ let task = allTasksInDisplayOrder.first(where: { $0.id == currentID })
+ {
deleteTask(task)
}
} label: {
diff --git a/ListlessMac/Views/TaskRowDragGesture.swift b/ListlessMac/Views/TaskRowDragGesture.swift
@@ -7,11 +7,12 @@ extension View {
taskID: UUID,
onDragStart: @escaping () -> Void
) -> some View {
- self.modifier(TaskRowDragGesture(
- isActive: isActive,
- taskID: taskID,
- onDragStart: onDragStart
- ))
+ self.modifier(
+ TaskRowDragGesture(
+ isActive: isActive,
+ taskID: taskID,
+ onDragStart: onDragStart
+ ))
}
}
diff --git a/ListlessiOS/ColorExtensions.swift b/ListlessiOS/ColorExtensions.swift
@@ -1,5 +1,5 @@
-import UIKit
import SwiftUI
+import UIKit
typealias PlatformColor = UIColor
diff --git a/ListlessiOS/Views/TaskRowDragGesture.swift b/ListlessiOS/Views/TaskRowDragGesture.swift
@@ -7,11 +7,12 @@ extension View {
taskID: UUID,
onDragStart: @escaping () -> Void
) -> some View {
- self.modifier(TaskRowDragGesture(
- isActive: isActive,
- taskID: taskID,
- onDragStart: onDragStart
- ))
+ self.modifier(
+ TaskRowDragGesture(
+ isActive: isActive,
+ taskID: taskID,
+ onDragStart: onDragStart
+ ))
}
}