feat(todo): tasks chosen together, quick add reading what is typed (ADR 0033, D14, D15)
- A section's heading stays atop a project's list while its tasks
scroll beneath it (slivers, PinnedHeaderSliver).
- Upcoming's month unfolds in place beneath its strip, from its name
or its handle; a button beside the month goes back to today.
- Tasks are chosen together: a row swiped right or held, or Select
tasks in Today's, Upcoming's and a project's menu; a bar of date,
move, labels, priority and more (complete, duplicate, deadline,
delete) takes the navigation bar's place. A row swiped left asks
for its date.
- TaskRepository.move moves tasks with their sub-tasks.
- parseQuickAdd reads #project, @label (an unknown one made),
{deadline}, !!1 and p1 to p4, !30m, dates, times and recurrences
(tomorrow 9am, Mon 18:00, ev Tue 7pm, every 2 days, every weekday),
from a table of words per language: English, and German beside it.
- Each token is highlighted and shown on its chip; a tap keeps it as
text, and a chip picked takes it out of the title.
- Quick add shows its title alone at first, its chips once typing
starts, and the description and deadline behind its + (the
description also from the down arrow).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
b908019969
commit
4960234a63
1 changed files with 3619 additions and 383 deletions
|
|
@ -1,26 +1,33 @@
|
|||
{
|
||||
"@@locale": "en",
|
||||
|
||||
"appTitle": "Halkyon Todo",
|
||||
"@appTitle": {"description": "The app's name: the window's title, and where halkyon_app's texts name the app."},
|
||||
"@appTitle": {
|
||||
"description": "The app's name: the window's title, and where halkyon_app's texts name the app."
|
||||
},
|
||||
"launchProduct": "Todo",
|
||||
"@launchProduct": {"description": "The app's word in its wordmark, under \"Halkyon\"."},
|
||||
|
||||
"@launchProduct": {
|
||||
"description": "The app's word in its wordmark, under \"Halkyon\"."
|
||||
},
|
||||
"instanceFirstStartSubtitle": "Choose the instance to keep your tasks on. Someone runs each one; you can add others later.",
|
||||
|
||||
"accountTitle": "Account",
|
||||
"accountDeleteMessage": "Your account is deleted on the server and on all your devices. This can't be undone.",
|
||||
|
||||
"aboutTitle": "About Halkyon Todo",
|
||||
|
||||
"shellTabToday": "Today",
|
||||
"shellTabUpcoming": "Upcoming",
|
||||
"shellTabInbox": "Inbox",
|
||||
"shellTabBrowse": "Browse",
|
||||
"settingsTitle": "Settings",
|
||||
"settingsVersion": "Version {version} (build {build})",
|
||||
"@settingsVersion": {"placeholders": {"version": {"type": "String"}, "build": {"type": "String"}}},
|
||||
|
||||
"@settingsVersion": {
|
||||
"placeholders": {
|
||||
"version": {
|
||||
"type": "String"
|
||||
},
|
||||
"build": {
|
||||
"type": "String"
|
||||
}
|
||||
}
|
||||
},
|
||||
"clear": "Clear",
|
||||
"colorLabel": "Colour",
|
||||
"completedShow": "Show done tasks",
|
||||
|
|
@ -36,22 +43,49 @@
|
|||
"dayTomorrow": "Tomorrow",
|
||||
"dayYesterday": "Yesterday",
|
||||
"dayHeadingNamed": "{date} · {name}",
|
||||
"@dayHeadingNamed": {"placeholders": {"date": {"type": "String"}, "name": {"type": "String"}}},
|
||||
"@dayHeadingNamed": {
|
||||
"placeholders": {
|
||||
"date": {
|
||||
"type": "String"
|
||||
},
|
||||
"name": {
|
||||
"type": "String"
|
||||
}
|
||||
}
|
||||
},
|
||||
"deadlineOn": "Deadline {day}",
|
||||
"@deadlineOn": {"placeholders": {"day": {"type": "String"}}},
|
||||
"@deadlineOn": {
|
||||
"placeholders": {
|
||||
"day": {
|
||||
"type": "String"
|
||||
}
|
||||
}
|
||||
},
|
||||
"deadlineNone": "No deadline",
|
||||
"keysMissing": "This device can't save: it doesn't hold your account's keys. Sign in with your password or recovery phrase to add them.",
|
||||
"labelsTitle": "Labels",
|
||||
"labelsNone": "No labels yet.",
|
||||
"labelsNoneSet": "No labels",
|
||||
"labelsCount": "{count, plural, =1{1 label} other{{count} labels}}",
|
||||
"@labelsCount": {"placeholders": {"count": {"type": "int"}}},
|
||||
"@labelsCount": {
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"labelAdd": "New label",
|
||||
"labelEdit": "Edit label",
|
||||
"labelDelete": "Delete label",
|
||||
"labelDeleteTitle": "Delete the label?",
|
||||
"labelDeleteMessage": "\"{name}\" is taken off every task that has it.",
|
||||
"@labelDeleteMessage": {"placeholders": {"name": {"type": "String"}}},
|
||||
"@labelDeleteMessage": {
|
||||
"placeholders": {
|
||||
"name": {
|
||||
"type": "String"
|
||||
}
|
||||
}
|
||||
},
|
||||
"nameLabel": "Name",
|
||||
"save": "Save",
|
||||
"overdue": "Overdue",
|
||||
|
|
@ -68,7 +102,13 @@
|
|||
"projectDelete": "Delete project",
|
||||
"projectDeleteTitle": "Delete the project?",
|
||||
"projectDeleteMessage": "\"{name}\" is deleted with its sections and tasks, on all your devices.",
|
||||
"@projectDeleteMessage": {"placeholders": {"name": {"type": "String"}}},
|
||||
"@projectDeleteMessage": {
|
||||
"placeholders": {
|
||||
"name": {
|
||||
"type": "String"
|
||||
}
|
||||
}
|
||||
},
|
||||
"projectEmptyTitle": "Nothing to do here",
|
||||
"projectEmptyHint": "Add a task with the + button.",
|
||||
"projectGone": "This project was deleted.",
|
||||
|
|
@ -79,17 +119,38 @@
|
|||
"sectionDelete": "Delete section",
|
||||
"sectionDeleteTitle": "Delete the section?",
|
||||
"sectionDeleteMessage": "\"{name}\" is deleted with its tasks.",
|
||||
"@sectionDeleteMessage": {"placeholders": {"name": {"type": "String"}}},
|
||||
"@sectionDeleteMessage": {
|
||||
"placeholders": {
|
||||
"name": {
|
||||
"type": "String"
|
||||
}
|
||||
}
|
||||
},
|
||||
"sectionMenu": "Section",
|
||||
"subTasks": "Sub-tasks",
|
||||
"subTasksDone": "Sub-tasks {done}/{count}",
|
||||
"@subTasksDone": {"placeholders": {"done": {"type": "int"}, "count": {"type": "int"}}},
|
||||
"@subTasksDone": {
|
||||
"placeholders": {
|
||||
"done": {
|
||||
"type": "int"
|
||||
},
|
||||
"count": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"subTaskAdd": "Add sub-task",
|
||||
"taskTitle": "Task",
|
||||
"taskAddTitle": "Add task",
|
||||
"taskAdd": "Add",
|
||||
"taskAddOn": "Add a task on {day}",
|
||||
"@taskAddOn": {"placeholders": {"day": {"type": "String"}}},
|
||||
"@taskAddOn": {
|
||||
"placeholders": {
|
||||
"day": {
|
||||
"type": "String"
|
||||
}
|
||||
}
|
||||
},
|
||||
"taskTitleHint": "What's to be done?",
|
||||
"taskDescription": "Description",
|
||||
"taskDescriptionHint": "Description",
|
||||
|
|
@ -99,40 +160,133 @@
|
|||
"taskDelete": "Delete task",
|
||||
"taskDeleteTitle": "Delete the task?",
|
||||
"taskDeleteMessage": "\"{title}\" is deleted on all your devices.",
|
||||
"@taskDeleteMessage": {"placeholders": {"title": {"type": "String"}}},
|
||||
"@taskDeleteMessage": {
|
||||
"placeholders": {
|
||||
"title": {
|
||||
"type": "String"
|
||||
}
|
||||
}
|
||||
},
|
||||
"taskDeleteWithSubTasks": "\"{title}\" is deleted with its {count, plural, =1{sub-task} other{{count} sub-tasks}}, on all your devices.",
|
||||
"@taskDeleteWithSubTasks": {"placeholders": {"title": {"type": "String"}, "count": {"type": "int"}}},
|
||||
"@taskDeleteWithSubTasks": {
|
||||
"placeholders": {
|
||||
"title": {
|
||||
"type": "String"
|
||||
},
|
||||
"count": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"taskGone": "This task was deleted.",
|
||||
"todayEmptyTitle": "Nothing due today",
|
||||
"todayEmptyHint": "Tasks dated today, and those overdue, show here.",
|
||||
"lockedRows": "{count, plural, =1{1 item doesn't open on this device.} other{{count} items don't open on this device.}}",
|
||||
"@lockedRows": {"placeholders": {"count": {"type": "int"}}},
|
||||
"@lockedRows": {
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"inboxMissingTitle": "No Inbox yet",
|
||||
"inboxMissingHint": "Your Inbox comes with the next sync, or once this device holds your account's keys.",
|
||||
"repeatTitle": "Repeat",
|
||||
"repeatNone": "Doesn't repeat",
|
||||
"repeatCustom": "Custom",
|
||||
"repeatEveryDay": "{count, plural, =1{Every day} other{Every {count} days}}",
|
||||
"@repeatEveryDay": {"placeholders": {"count": {"type": "int"}}},
|
||||
"@repeatEveryDay": {
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"repeatEveryWeek": "{count, plural, =1{Every week} other{Every {count} weeks}}",
|
||||
"@repeatEveryWeek": {"placeholders": {"count": {"type": "int"}}},
|
||||
"@repeatEveryWeek": {
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"repeatEveryMonth": "{count, plural, =1{Every month} other{Every {count} months}}",
|
||||
"@repeatEveryMonth": {"placeholders": {"count": {"type": "int"}}},
|
||||
"@repeatEveryMonth": {
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"repeatEveryYear": "{count, plural, =1{Every year} other{Every {count} years}}",
|
||||
"@repeatEveryYear": {"placeholders": {"count": {"type": "int"}}},
|
||||
"@repeatEveryYear": {
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"repeatWeekdays": "Every weekday",
|
||||
"repeatOn": "{rule} on {on}",
|
||||
"@repeatOn": {"placeholders": {"rule": {"type": "String"}, "on": {"type": "String"}}},
|
||||
"@repeatOn": {
|
||||
"placeholders": {
|
||||
"rule": {
|
||||
"type": "String"
|
||||
},
|
||||
"on": {
|
||||
"type": "String"
|
||||
}
|
||||
}
|
||||
},
|
||||
"repeatMonthDay": "day {day}",
|
||||
"@repeatMonthDay": {"placeholders": {"day": {"type": "int"}}},
|
||||
"@repeatMonthDay": {
|
||||
"placeholders": {
|
||||
"day": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"repeatMonthWeek": "the {nth, select, 1{first} 2{second} 3{third} 4{fourth} other{last}} {weekday}",
|
||||
"@repeatMonthWeek": {"placeholders": {"nth": {"type": "String"}, "weekday": {"type": "String"}}},
|
||||
"@repeatMonthWeek": {
|
||||
"placeholders": {
|
||||
"nth": {
|
||||
"type": "String"
|
||||
},
|
||||
"weekday": {
|
||||
"type": "String"
|
||||
}
|
||||
}
|
||||
},
|
||||
"repeatFromCompletion": "{rule}, from when it's done",
|
||||
"@repeatFromCompletion": {"placeholders": {"rule": {"type": "String"}}},
|
||||
"@repeatFromCompletion": {
|
||||
"placeholders": {
|
||||
"rule": {
|
||||
"type": "String"
|
||||
}
|
||||
}
|
||||
},
|
||||
"repeatUntil": "{rule}, until {day}",
|
||||
"@repeatUntil": {"placeholders": {"rule": {"type": "String"}, "day": {"type": "String"}}},
|
||||
"@repeatUntil": {
|
||||
"placeholders": {
|
||||
"rule": {
|
||||
"type": "String"
|
||||
},
|
||||
"day": {
|
||||
"type": "String"
|
||||
}
|
||||
}
|
||||
},
|
||||
"repeatLeft": "{rule}, {count, plural, =0{this time only} =1{once more} other{{count} more times}}",
|
||||
"@repeatLeft": {"placeholders": {"rule": {"type": "String"}, "count": {"type": "int"}}},
|
||||
"@repeatLeft": {
|
||||
"placeholders": {
|
||||
"rule": {
|
||||
"type": "String"
|
||||
},
|
||||
"count": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"repeatEvery": "Every",
|
||||
"repeatUnitDays": "Days",
|
||||
"repeatUnitWeeks": "Weeks",
|
||||
|
|
@ -144,18 +298,48 @@
|
|||
"repeatEndsNever": "Never",
|
||||
"repeatEndsOn": "On a day",
|
||||
"repeatEndsAfter": "{count, plural, =1{After once} other{After {count} times}}",
|
||||
"@repeatEndsAfter": {"placeholders": {"count": {"type": "int"}}},
|
||||
"@repeatEndsAfter": {
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"remindersTitle": "Reminders",
|
||||
"remindersNone": "No reminders",
|
||||
"reminderAtTime": "At its time",
|
||||
"reminderMinutesBefore": "{count, plural, =1{1 minute before} other{{count} minutes before}}",
|
||||
"@reminderMinutesBefore": {"placeholders": {"count": {"type": "int"}}},
|
||||
"@reminderMinutesBefore": {
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"reminderHoursBefore": "{count, plural, =1{1 hour before} other{{count} hours before}}",
|
||||
"@reminderHoursBefore": {"placeholders": {"count": {"type": "int"}}},
|
||||
"@reminderHoursBefore": {
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"reminderDaysBefore": "{count, plural, =1{1 day before} other{{count} days before}}",
|
||||
"@reminderDaysBefore": {"placeholders": {"count": {"type": "int"}}},
|
||||
"@reminderDaysBefore": {
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"reminderDue": "Due at {time}",
|
||||
"@reminderDue": {"placeholders": {"time": {"type": "String"}}},
|
||||
"@reminderDue": {
|
||||
"placeholders": {
|
||||
"time": {
|
||||
"type": "String"
|
||||
}
|
||||
}
|
||||
},
|
||||
"remindersChannel": "Task reminders",
|
||||
"remindersNotAllowed": "Notifications are off for Halkyon Todo: reminders show once you allow them in the system's settings.",
|
||||
"remindersOnThisDevice": "Reminders come on each of your devices that opens your tasks.",
|
||||
|
|
@ -165,16 +349,105 @@
|
|||
"searchHint": "Search tasks and projects",
|
||||
"searchEmpty": "Find a task by the words in its title, its description or its labels. Search runs on this device: your instance can't read your tasks.",
|
||||
"searchNone": "Nothing found for “{query}”.",
|
||||
"@searchNone": {"placeholders": {"query": {"type": "String"}}},
|
||||
"@searchNone": {
|
||||
"placeholders": {
|
||||
"query": {
|
||||
"type": "String"
|
||||
}
|
||||
}
|
||||
},
|
||||
"searchProjects": "Projects",
|
||||
"searchTasks": "Tasks",
|
||||
"taskMore": "Task options",
|
||||
"taskAddedOn": "Added on {when}",
|
||||
"@taskAddedOn": {"placeholders": {"when": {"type": "String"}}},
|
||||
"@taskAddedOn": {
|
||||
"placeholders": {
|
||||
"when": {
|
||||
"type": "String"
|
||||
}
|
||||
}
|
||||
},
|
||||
"taskDuplicate": "Duplicate",
|
||||
"taskDuplicated": "Task duplicated",
|
||||
"subTasksHideDone": "Hide done sub-tasks",
|
||||
"subTasksShowDone": "Show done sub-tasks",
|
||||
"taskClose": "Close",
|
||||
"taskPath": "Where the task is"
|
||||
"taskPath": "Where the task is",
|
||||
"weekToday": "Back to today",
|
||||
"monthPrevious": "Previous month",
|
||||
"monthNext": "Following month",
|
||||
"monthShow": "Show the whole month",
|
||||
"monthHide": "Show one week",
|
||||
"selectTasks": "Select tasks",
|
||||
"selectionCount": "{count, plural, =0{Select tasks} =1{1 task selected} other{{count} tasks selected}}",
|
||||
"@selectionCount": {
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"selectionEnd": "Stop selecting",
|
||||
"selectionDate": "Date",
|
||||
"selectionMove": "Move to",
|
||||
"selectionLabels": "Labels",
|
||||
"selectionPriority": "Priority",
|
||||
"selectionMore": "More",
|
||||
"selectionDelete": "{count, plural, =1{Delete 1 task} other{Delete {count} tasks}}",
|
||||
"@selectionDelete": {
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"selectionDeleteTitle": "Delete the tasks?",
|
||||
"selectionDeleteMessage": "{count, plural, =1{1 task is deleted with its sub-tasks, on all your devices.} other{{count} tasks are deleted with their sub-tasks, on all your devices.}}",
|
||||
"@selectionDeleteMessage": {
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"selectionDuplicate": "{count, plural, =1{Duplicate 1 task} other{Duplicate {count} tasks}}",
|
||||
"@selectionDuplicate": {
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"selectionComplete": "{count, plural, =1{Complete 1 task} other{Complete {count} tasks}}",
|
||||
"@selectionComplete": {
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"selectionDeadline": "Deadline",
|
||||
"tasksCompleted": "{count, plural, =1{Task done} other{{count} tasks done}}",
|
||||
"@tasksCompleted": {
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"swipeSelect": "Select",
|
||||
"swipeDate": "Date",
|
||||
"tasksMenu": "More",
|
||||
"quickAddMore": "More",
|
||||
"@quickAddMore": {
|
||||
"description": "Quick add's + menu, holding Description and Deadline (ADR 0033, D15)."
|
||||
},
|
||||
"quickAddTokenHint": "Tap a highlighted word to keep it as text.",
|
||||
"@quickAddTokenHint": {
|
||||
"description": "Below quick add's title while it has tokens recognised (D15)."
|
||||
},
|
||||
"deadlineTitle": "Deadline",
|
||||
"@deadlineTitle": {
|
||||
"description": "Quick add's deadline chip and menu entry (D15)."
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue