docs(todo): ADR 0033, D32: a task's locations

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
Tizian 「ティツィアーン」 2026-11-05 15:24:13 +01:00
commit 0a9facc3a2
Signed by: raisondetredev
GPG key ID: 07F6FCF405488B64

View file

@ -175,7 +175,7 @@ the rail, a wash of strawberry, settings grouped as theirs. What the screenshots
or hidden per view; reminders on the device. **Later**, each put to the developer when
its turn comes: the board and calendar layouts, Upcoming's 3-day grid, each view's
Display sheet (grouping, sorting, filters), saved filters, Reporting and goals (karma
not before the developer asks for it), location reminders, comments and attachments,
not before the developer asks for it), location reminders (come with D32), comments and attachments,
typed dates, sharing.
- **D9 Colours that mean something come from halkyon_ui's palette** (recommended): a
project's colour is picked from `PaletteColor`, with its localised name, as Learn's
@ -602,6 +602,57 @@ The developer's review of 4 Nov 2026, again beside Todoist's screens.
time can't be). Google Play reviews `USE_EXACT_ALARM` against that purpose; Todo is
one, and F-Droid asks nothing of it.
- **D32 A task's locations, with reminders on arriving or leaving** (the developer's, 5
Nov 2026): a location says where a task happens; a task may have several, which count
as alternatives, each with its own reminder: none, on arriving, or on leaving.
`TaskLocation` (name, address text, position, optional OSM type and ID, trigger) goes
in the task's sealed payload as `locations`, schema still 1 (D18's unknown fields stay);
recent places are derived from the tasks (`recentLocations`), not kept.
- *Finding a place.* People don't know addresses, so a search starts from a city or
district and a name (`Lindau EDEKA`, `Aeschach EDEKA`), and the map is part of
picking, not an extra (the developer's): results list name, then street, district
and city, so that two EDEKAs differ, and show as pins; a pin or a row chooses, and a
tap on the map places a pin by hand. The phone's last known position centres the map
and biases the search, where it may be read. `PlaceSearchGateway` is the seam:
`TodoDependencies.places` is the instance's search once wired, and until then
`PublicPhotonGateway` to komoot's public Photon, in a debug build asked for it alone
(`--dart-define=TODO_PUBLIC_PHOTON=true`), with a generic User-Agent and no personal
data; without either the picker says search isn't available. Car parks and charging
stations named after a place are left out (seen on `Lindau EDEKA`). The map is Train's
(`flutter_map`, `vector_map_tiles`, OpenFreeMap's Liberty and Dark), a small copy of
`vectorTiles`, no tile layer in widget tests. Alternatives named: a street-address
form (refused: nobody knows them), the picker without a map (refused by the developer).
- *Quick add.* `+` is a keyword as `#` and `@`: recent places suggested as it is typed,
below them the way into the search with what was typed; a place named before becomes
a token (`parseQuickAdd`'s `locations`), kept as text by a tap or Backspace as any
other (D29); an unknown `+word`, or a `+` a space follows, stays text. A + menu entry
and a pin button with the name or a count do the same by hand. The task sheet has a
Where box, each place with its ⋮; a task's row shows the name and how many more.
- *Reminders* are on the device, Android alone (`LocationReminderGateway`, a no-op
elsewhere, which offers none), as the instance reads no task: the system's
`LocationManager.addProximityAlert`, 150 m, no Google services, which GrapheneOS
lacks. Planned from the open tasks as `ReminderScheduler` plans reminders
(`planLocationWatches`), cancelled in `TodoPerson.dispose`, kept in the app's private
preferences (titles unsealed there, as reminders' are; `allowBackup` is off),
registered anew after a restart or an update and on the process's first plan, as a
force stop drops them unseen. Fused-provider geofencing was refused: it is Google's.
- *Dwell*, so that driving past an EDEKA on the way to the next doesn't remind (the
developer's question): crossing the circle schedules a check two minutes later, a
crossing back cancels it, and the check notifies only if the phone is still on that
side (`LocationDwell`, pure, with JUnit tests CI doesn't run yet), by a fix at most
90 s old where there is one, else by the system's last event. A red light of over
two minutes beside the shop still reminds; that is accepted for now.
- *Once*: a task reminds once until it changes (title, day, places: `stamp`), and an
alternative that reminded stops the task's others. The notification goes on the
reminders' channel and opens the app.
- *Permission*: the position first, then, told why, *Allow all the time* in the
system's settings, asked as a person chooses such a reminder and never by planning
(a task may sync in); Settings' Reminders says while it is off, with Turn on, as D31.
- *A debug build installs beside the release* (`.debug`, *Todo Debug*), the keys
differing; SimpleLogin's way back keeps the scheme the instance allows, so with both
installed Android asks which app answers it. Debug builds log to
`adb logcat -s HalkyonLocation`.
## Steps
1. **The frame**: go_router and `NavigationFrame` with the four tabs (empty screens that