Updated the TaskListItem view in the app target to use the new view modifiers.
This commit is contained in:
@@ -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<String> {
|
||||
.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"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user