A task with a time takes reminders, minutes before it, in its sealed payload; each device plans the coming ones whenever the tasks change and schedules them with the system through flutter_local_notifications (Android, iOS, macOS, Windows; on Linux the running app shows them), at the minute where Android allows exact alarms. Notifying is asked for when a task first gets a reminder; signing out or switching person cancels them. Upcoming gets its week strip: the month opening Material's calendar, the weeks before and after, a dot under each day with tasks; a day picked scrolls the agenda to it, and scrolling moves the strip along. From expanded windows on, a task opens in a pane beside the list rather than in a dialog. Search, from every tab's app bar, finds projects by name and tasks by every word typed, in their title, description or labels, whatever the case and accents, on the device alone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
8.2 KiB
8.2 KiB
Halkyon Todo
What holds for every app and package of this repository is in the root AGENTS.md; it applies here in full, and Learn's patterns (apps/learn/AGENTS.md) wherever Todo needs the same thing.
- A shell on the shared packages (decided 2026-10-19; what Todo is to do and how it looks: ADR 0033, decided 2026-11-01): signing in, the instances, the account and the look work; since 1 Nov 2026 a person's projects are kept and synced with
serverpod_offline_sync, every row sealed (ADR 0033, D5, D6):content_keyandprojecton the server (deleteTodoDatadeletes a person's space with them), and on the deviceTodoKeys(Train'sTrainKeyscopied with Todo's own key IDs,todo1.…; to be shared in halkyon_app once Train's 0.1.1 is out),SealedRows(lib/src/core/sealed/: a table's rows sealed for their table and row, under whichProjectRepository, the Inbox under a row ID keyed by the account, made once as the person's data opens, never deleted,SectionRepository,TaskRepository, a task deleted with its sub-tasks, andLabelRepository), one sync gateway per table, andTodoPersonopening the person's sync database, itsSyncServiceand all of them, as Train's; a project or a section is deleted with its tasks (TodoPerson.deleteProject,deleteSection). A task's date is a day with an optional wall-clock time and duration, no time zone (TaskDate), and its recurrence (Repeat, ADR 0033, D7:TaskRepository.completemoves a recurring task on, reopens its sub-tasks and returns what it changed forrestoreto undo; picked throughpickRepeat) and its reminders, minutes before its time (D5:planRemindersplans them,ReminderSchedulerunder the person's app hands them toReminderGateway,SystemReminderGatewayonflutter_local_notifications, the system scheduling them but on Linux, where the running app shows them;TodoPerson.disposecancels them; Android's manifest declares the boot receiver and exact alarms, the build desugars). Packages:halkyon_todo_server,halkyon_todo_client(generated, never edited),halkyon_todo_flutter; app IDapp.halkyon.todoon every platform; no web build. Licences as Learn's (server SSPL, client and app AGPL;LICENSE.md). - The server includes
halkyon_base(ADR 0014) and configures it inserver.dart(todoBase(),lib/src/todo_base.dart): its basics say it servestodo(never change it once apps use it), sign-in mails name Halkyon Todo, the source is this repository,minimumAppBuild1, a person's space deleted with them (deletePersonData: [deleteTodoData],lib/src/todo_data.dart). Authentication through the module's builders: a password, SimpleLogin on the register, email codes proving an address, server-side sessions; no anonymous accounts (ADR 0020, D25), nor GitHub (D36). Accounts (ADR 0016): Todo holds its own register when it runs alone, and is a member of the instance's register (Learn's server on learn.halkyon.eu) where the operator setsACCOUNT_REGISTER_URL(todoBase(accounts: AccountsMode.fromEnvironment())) with the instance's sharedINSTANCE_SECRET(instanceSecret); then sign-in, handles and profiles are the register's, the email settings are the register's alone, and an identified person's deletion goes to the register first.addInstanceRoutesserves the calls between the services on its web server, and the server doesn't start without the secret where it needs it.schedulePruning(lib/src/pruning.dart) keeps the module's pruning scheduled, one entry each however often the server starts (and cancels the one under the pruning's name before ADR 0020, D25): the anonymous accounts left from before daily, sign-up attempts and codes hourly, as the register the deletions its members haven't confirmed hourly, as a member the people the register no longer knows daily (each a no-op in the other mode). Session logs are never persisted, in any run mode. Migrations (2026-10-19): the initial one (Serverpod's tables, its auth modules' and the module'semail_identity,email_code_request),profiles(public_profile),deletion-notices(account_deletion_notice), and since 1 Nov 2026projects(content_key,projectand the sync engine's tables) andtasks(section,task,label). Tests (test/integration/todo_server_test.dart) call the module's endpoints through the server's own dispatch (halkyon_base.<endpoint>), since the generated test tools expose the project's endpoints alone. - The app is halkyon_app's
InstanceGateandSessionGatewith Todo's frame (todoFrame: "Todo" under "Halkyon", its icon,todo.example.org, its own sentence) andServerpodInstanceChecker(app: 'todo');TodoDependencies(AppDependencies<TodoPerson>) on one instance,TodoPerson(empty) per person; a person's app in Todo's frame (ADR 0033, D1 to D4, since 1 Nov 2026), as Train's: go_router (buildTodoRouter,TodoPaths) with aStatefulShellRoute, halkyon_ui'sNavigationFrame(TodoShell) with the tabs Today (where it opens), Upcoming, Inbox and Browse, (lib/src/tabs/; ADR 0033, D8, since 1 Nov 2026): Today (overdue first with Reschedule, then today's), Upcoming (overdue, then the next 28 days, empty ones muted), Inbox and a project's screen (ProjectScreen, from Browse: its tasks above and in its sections, done ones shown on asking, sections added, renamed and deleted, the project edited and deleted), Browse (projects with their open counts, labels, what doesn't open counted); a task's row (TaskTile: its check in its priority's colour, its date in the colour of how near it is, deadline, sub-tasks done, labels), quick add (showQuickAdd: title, date, priority, project, labels, description) and its sheet (openTaskSheet; from expanded windows on the pane beside the tabs instead,TaskPane, D2), Upcoming's week strip (WeekStrip, a day picked scrolling the agenda to it), search from every tab's app bar (SearchButtoninTabScreen,SearchScreenon the tab's stack,searchTasksmatching words folded to lower case without accents), all overTodoCubit, which reads everything again on any change; colours from halkyon_ui's palette (task_texts.dart, D9), every screen washing down in strawberry (ScreenColor,TabScreen); Settings (lib/src/settings/) over the tabs from Browse's cog (its dot while sync fails), grouped inSectionCards: Sync's card, the operator's card, the account (halkyon_app'sAccountTiles, whose account on which instance, Switch account, Sign out, Delete account, which asks first, with SimpleLogin and the account's security) in Todo's words, What's new and halkyon_app's About (showAppAbout: the source of what the instance runs, fromTodoDependencies.sourceCodeUrl, and the licence list), the version below (TodoDependencies.appVersion). What's new shows nothing yet:main.dartgives noWhatsNewScopeuntil Todo's first release bringsassets/whats_new/. Texts through gen-l10n in British English (the template), German (informal du), an emptyen_USanden_GB(test/l10n/arb_files_test.dartkeeps them in step). The look follows the system's theme mode and language until Todo has settings. Countries in where an instance keeps its data are named by halkyon_app's CLDR names (AssetCountryNames), its language picked by halkyon_app'sresolveAppLocale. Widget tests start Todo's whole tree with halkyon_app's fakes (test/app/todo_app_test.dart). - The icon is Lucide's
list-todofading from cobalt through pacific into fern (ADR 0031), drawn with the other apps' by the repository'stool/app_icons.py(python3 -I tool/app_icons.py todofrom the root):assets/icon/halkyon_todo_icon.png, Lucide's ISC licence beside it, and every platform's launcher icon through flutter_launcher_icons.registerLucideLicenseputs the notice in the licence list. serverpod startruns inapps/todo/halkyon_todo_server(it launches the app fromlib/driver.dart);.mcp.json's--server-dirnames it when a session works on Todo. Its tests need throwaway passwords in its git-ignoredconfig/passwords.yaml(database,serviceSecret,serverSideSessionKeyHashPepper,emailSignInPepper) or from the environment, as CI gives them. Learn's and Todo's development servers use the same ports: run one at a time.