From 81859cf841d63a5e2af7ebad777b5901908dda34 Mon Sep 17 00:00:00 2001 From: Javier Cicchelli Date: Thu, 12 Feb 2026 01:52:45 +0100 Subject: [PATCH] Updated the TaskListItem view in the app target to use the new view modifiers. --- App/Sources/Views/TaskList/TaskListItem.swift | 108 +++--------------- 1 file changed, 17 insertions(+), 91 deletions(-) diff --git a/App/Sources/Views/TaskList/TaskListItem.swift b/App/Sources/Views/TaskList/TaskListItem.swift index 392b96a..e04eb63 100644 --- a/App/Sources/Views/TaskList/TaskListItem.swift +++ b/App/Sources/Views/TaskList/TaskListItem.swift @@ -20,7 +20,7 @@ extension TaskListView { /// Tracks which text field currently has keyboard focus. @FocusState - private var focusOnField: FieldFocus? + private var inputFocus: InputFieldFocus? /// The todo task to display. @Bindable @@ -35,7 +35,7 @@ extension TaskListView { /// /// - Parameter item: The todo task to display and edit. init(_ item: Todo) { - _item = Bindable(item) + self._item = Bindable(item) } // MARK: Body @@ -65,14 +65,19 @@ extension TaskListView { ) { TextField( "view.task-list-item.placeholder.title", - text: title, + text: $item.title, axis: .vertical ) .font(.headline) .focused( - $focusOnField, + $inputFocus, equals: .title ) + .onNewlineFocus( + $item.title, + to: .note, + on: $inputFocus + ) if isNoteShown { TextField( @@ -82,9 +87,13 @@ extension TaskListView { ) .font(.subheadline) .focused( - $focusOnField, + $inputFocus, equals: .note ) + .onEmptyNewlineResignFocus( + text: note, + from: $inputFocus + ) } DatePicker( @@ -99,7 +108,7 @@ extension TaskListView { .autocapitalization(.sentences) .autocorrectionDisabled(false) .foregroundStyle(foregroundStyleView) - .keyboardType(.asciiCapable) + .keyboardType(.default) } .animation( .easeInOut, @@ -110,20 +119,6 @@ extension TaskListView { } -// MARK: - Enumerations - -private extension TaskListView.Item { - - /// Identifies which text field should receive keyboard focus. - enum FieldFocus { - /// The note text field has focus. - case note - /// The title text field has focus. - case title - } - -} - // MARK: - Helpers private extension TaskListView.Item { @@ -151,19 +146,7 @@ private extension TaskListView.Item { .init { item.note ?? "" } set: { - setNote(with: $0) - } - } - - /// A binding to the title text of a todo task. - /// - /// This computed binding provides access to the title of a todo task with special handling - /// for newline characters. - var title: Binding { - .init { - item.title - } set: { - setTitle(with: $0) + item.note = $0.isEmpty ? nil : $0 } } @@ -184,7 +167,7 @@ private extension TaskListView.Item { /// - Any text field has focus (allowing users to add a note even if one doesn't exist yet) /// - The todo task has a note with non-whitespace content var isNoteShown: Bool { - guard focusOnField != nil else { + guard inputFocus != nil else { guard let note = item.note else { return false } @@ -195,57 +178,6 @@ private extension TaskListView.Item { return true } - // MARK: Functions - - /// Updates the note of a todo task with special handling for newlines and empty content. - /// - /// This method provides intelligent note field behavior: - /// - Empty text immediately clears the note - /// - Newlines at the end of the text trigger special handling: - /// - If the text is only whitespace/newlines, the note is cleared and focus is removed - /// - Otherwise, the text (including newlines) is saved normally - /// - All other text is saved as-is - /// - /// This allows users to press return on an empty note field to dismiss it, - /// while still supporting multi-line notes. - /// - /// - Parameter text: The new note text to set. - func setNote(with text: String) { - guard text.isEmpty == false else { - item.note = text - return - } - - if text.last == .newLine { - guard text.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty == true else { - item.note = text - return - } - - item.note = nil - focusOnField = nil - } - else { - item.note = text - } - } - - /// Updates the title of a todo task with special handling for newline characters. - /// - /// When the user presses return in the title field (adding a newline), this function - /// prevents the newline from being added to the title and instead moves keyboard - /// focus to the note field. If no newline is present, the title is updated normally. - /// - /// - Parameter text: The new title text to set. - func setTitle(with text: String) { - guard text.lastIndex(of: .newLine) == nil else { - focusOnField = .note - return - } - - item.title = text - } - } // MARK: - Previews @@ -264,9 +196,3 @@ private extension TaskListView.Item { } .listStyle(.grouped) } - -// MARK: - Character+Constants - -private extension Character { - static let newLine: Self = "\n" -}