listless

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

commit 54fe3702c4345b6ff5ac14d306f56e484b0e99f2
parent 70be346be50f71014b8f4567f5df75d2c63e1bc1
Author: Michael Camilleri <[email protected]>
Date:   Fri, 27 Feb 2026 07:59:07 +0900

Improve semantics of return key on iOS keyboard

Co-Authored-By: Codex GPT 5.3 <[email protected]>

Diffstat:
MListlessiOS/Helpers/TappableTextField.swift | 7++++++-
MListlessiOS/Views/TaskListView.swift | 1+
MListlessiOS/Views/TaskRowView.swift | 4++++
3 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/ListlessiOS/Helpers/TappableTextField.swift b/ListlessiOS/Helpers/TappableTextField.swift @@ -8,6 +8,7 @@ struct TappableTextField: UIViewRepresentable { @Binding var text: String let isCompleted: Bool let onEditingChanged: (Bool, _ shouldCreateNewTask: Bool) -> Void + var returnKeyType: UIReturnKeyType = .done var onContentChange: ((String) -> Void)? = nil func makeUIView(context: Context) -> UITextView { @@ -20,7 +21,7 @@ struct TappableTextField: UIViewRepresentable { textView.isScrollEnabled = false textView.autocorrectionType = .default textView.autocapitalizationType = .sentences - textView.returnKeyType = .done + textView.returnKeyType = returnKeyType let placeholder = UILabel() placeholder.text = "Enter task" @@ -41,6 +42,10 @@ struct TappableTextField: UIViewRepresentable { if !textView.isFirstResponder { applyStyle(to: textView, text: text, isCompleted: isCompleted) } + if textView.returnKeyType != returnKeyType { + textView.returnKeyType = returnKeyType + textView.reloadInputViews() + } textView.isEditable = !isCompleted textView.isSelectable = !isCompleted if let placeholder = textView.viewWithTag(100) as? UILabel { diff --git a/ListlessiOS/Views/TaskListView.swift b/ListlessiOS/Views/TaskListView.swift @@ -211,6 +211,7 @@ struct TaskListView: View, TaskListViewProtocol { totalTasks: displayActiveTasks.count, isSelected: selectedTaskID == taskID, isDragging: isDraggingStateBinding, + isLastActiveTask: index == displayActiveTasks.count - 1, focusedField: $focusedFieldBinding, onToggle: { toggleCompletion($0) }, onTitleChange: { updateTitle($0, $1) }, diff --git a/ListlessiOS/Views/TaskRowView.swift b/ListlessiOS/Views/TaskRowView.swift @@ -11,6 +11,7 @@ struct TaskRowView: View { let onTitleChange: (TaskItem, String) -> Void let onDelete: (TaskItem) -> Void let onSelect: (UUID) -> Void + let isLastActiveTask: Bool let onStartEdit: (UUID) -> Void let onEndEdit: (UUID, _ shouldCreateNewTask: Bool) -> Void @FocusState.Binding var focusedField: FocusField? @@ -29,6 +30,7 @@ struct TaskRowView: View { totalTasks: Int = 1, isSelected: Bool, isDragging: Binding<Bool> = .constant(false), + isLastActiveTask: Bool = false, focusedField: FocusState<FocusField?>.Binding, onToggle: @escaping (TaskItem) -> Void, onTitleChange: @escaping (TaskItem, String) -> Void, @@ -43,6 +45,7 @@ struct TaskRowView: View { self.totalTasks = totalTasks self.isSelected = isSelected _isDragging = isDragging + self.isLastActiveTask = isLastActiveTask self.onToggle = onToggle self.onTitleChange = onTitleChange self.onDelete = onDelete @@ -80,6 +83,7 @@ struct TaskRowView: View { else { onEndEdit(taskID, shouldCreateNewTask) } } }, + returnKeyType: isLastActiveTask ? .next : .done, onContentChange: { newTitle in guard !task.isCompleted else { return } onTitleChange(task, newTitle)