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