M4: percent-complete, conflict-safe saves & subtask reparent
All checks were successful
CI / ci (push) Successful in 6m49s
All checks were successful
CI / ci (push) Successful in 6m49s
M3 detail/edit polish: - "Progress" slider on the edit form writes Tasks.PERCENT_COMPLETE (clamped 0-100, 5% detents); status stays owned by the complete toggle. - Conflict-safe saves: updateTask re-checks the provider's last_modified against the value captured when the form loaded and throws TaskConflictException; the editor offers overwrite-or-cancel instead of clobbering an external change. M4 subtasks (UI): - Reparent: a "Parent task" picker files a task under any top-level task in its list (or "None" to promote it); candidates stay top-level to keep nesting one level deep. Switching list clears the now-invalid parent. - Tapping a subtask opens its own detail (a new TaskDetail entry, own VM). Tests: percent clamping, parent-id write, populatedFields reveal logic. Docs: ROADMAP M2/M3/M4 reconciled to the codebase; CHANGELOG [Unreleased]. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
100
docs/ROADMAP.md
100
docs/ROADMAP.md
@@ -11,9 +11,12 @@ Status legend: ✅ done · 🚧 in progress · ⬜ not started
|
||||
## Current state (one line)
|
||||
|
||||
The full non-visual stack ("backoffice") over the OpenTasks `TaskContract`
|
||||
provider is **done and unit-tested**; the Material 3 Expressive UI is being
|
||||
built screen by screen on top of it. App builds, gates on provider/permission,
|
||||
and navigates lists → task list → detail / edit through base screen scaffolds.
|
||||
provider is **done and unit-tested**, and the Material 3 Expressive UI is built
|
||||
through **M4**: lists → task list (swipe gestures, inline add, smart-list section
|
||||
headers) → detail / edit with full CRUD, date-time pickers, priority,
|
||||
percent-complete, conflict-safe saves, per-task reminders, and subtask
|
||||
create + reparent. Remaining work is M5 (notification / exact-alarm onboarding,
|
||||
default reminder UI) and M6 (Settings screen, Glance widget, i18n, release).
|
||||
|
||||
---
|
||||
|
||||
@@ -39,38 +42,81 @@ The complete non-visual stack:
|
||||
- JVM unit tests across mappers, filtering, sorting, form, value mapping, and
|
||||
day windows.
|
||||
|
||||
### 🚧 M2 — Screens: lists, task list, complete & CRUD
|
||||
Replace the functional scaffold with the real Material 3 Expressive UI, screen
|
||||
by screen, against the already-built ViewModels.
|
||||
### ✅ M2 — Screens: lists, task list, complete & CRUD
|
||||
The real Material 3 Expressive UI, built screen by screen against the M1
|
||||
ViewModels.
|
||||
- ✅ Provider/permission onboarding gate (`RootScreen`).
|
||||
- ✅ Lists overview (`ListsScreen`) — smart lists + user lists grouped by account.
|
||||
- ✅ Navigation host wiring (`FloretNavHost` + `Dest` route table: lists → task
|
||||
list → detail / edit, each binding its M1 ViewModel from route args).
|
||||
- 🚧 Task list screen — base scaffold lands (checkbox rows, toggle-complete, open
|
||||
/ new-task nav). Remaining: swipe-to-complete / -delete, inline add field,
|
||||
section headers for smart lists.
|
||||
- 🚧 Detail + edit screens — base scaffolds land (detail shows title /
|
||||
description / subtasks with edit+delete; edit has title / description / save).
|
||||
Remaining: full CRUD fields and local-list creation wired to the UI.
|
||||
- ✅ Task list screen — checkbox rows + toggle-complete, swipe-to-complete /
|
||||
-delete (`SwipeToDismissBox`), inline add field (`InlineAdd` → `quickAdd`),
|
||||
smart-list section headers (`TaskSections`).
|
||||
- ✅ Detail + edit screens — detail shows title / description / subtasks with
|
||||
edit+delete; edit has the full CRUD form (title, description, save) wired to a
|
||||
list picker.
|
||||
|
||||
### ⬜ M3 — Detail / edit polish
|
||||
Task detail and edit screens: due/start date-time pickers, priority,
|
||||
percent-complete, conflict-safe saves (re-check before overwrite), smart-list
|
||||
section presentation.
|
||||
### ✅ M3 — Detail / edit polish
|
||||
- ✅ Due / start date-time pickers (`DateTimePickerFlow` in `TaskEditScreen`).
|
||||
- ✅ Priority — coloured by level: green / amber / red pastels (`priorityFill`;
|
||||
M3 has no priority role, only `error`). A shared `ui/common/PriorityChip` on the
|
||||
list and detail screens, and the edit form's M3 segmented selector tints its
|
||||
active segment in the chosen level's hue.
|
||||
- ✅ Smart-list section presentation (`TaskSections` headers on the task list).
|
||||
- ✅ Percent-complete field — optional "Progress" slider (5% detents) on the edit
|
||||
form; writes `Tasks.PERCENT_COMPLETE` (clamped 0–100, status left to the
|
||||
complete toggle).
|
||||
- ✅ Conflict-safe saves — `updateTask` re-checks `last_modified` against the
|
||||
value captured when the form loaded and throws `TaskConflictException`; the
|
||||
editor offers overwrite-or-cancel instead of clobbering an external change.
|
||||
|
||||
### ⬜ M4 — Subtasks (UI)
|
||||
`RELATED-TO` hierarchy in the UI: indentation, create subtask, reparent. The
|
||||
data layer already reads `parentId`; this is the trickiest UI piece.
|
||||
### ✅ M4 — Subtasks (UI)
|
||||
`RELATED-TO` hierarchy in the UI. The data layer already reads `parentId`.
|
||||
- ✅ Create subtask (`AddSubtaskField` → `TaskDetailViewModel.addSubtask` sets
|
||||
`parentId`); subtasks render as a grouped section in the detail screen. Tapping
|
||||
a subtask opens its own detail (a new `TaskDetail` entry, so it can have
|
||||
children too), and the subtask's detail shows a tappable "Part of …" parent
|
||||
card so it never reads as a stray standalone task.
|
||||
- ✅ Inline expansion on the task list — a parent row has a dedicated expand
|
||||
button (trailing chevron, separate from the count chip). Each section flattens
|
||||
into one grouped run (parents + their expanded children) and corners are chosen
|
||||
per-edge (`cornerPosition`): top-level tasks keep their own run, an expanded
|
||||
parent opens its bottom to its children, and the child group rounds off on its
|
||||
last segment while the next top-level task stays mid-run. Children are
|
||||
full-width, set a step down in tone (`surfaceContainer` vs the parents'
|
||||
`surfaceContainerHigh`) and with no colour bar (checkbox stays aligned). An expanded group ends with an inline "add a subtask"
|
||||
row (always on for now; an opt-out toggle lands with the M6 settings screen).
|
||||
Offered only where the list holds all the children (a real list; smart lists
|
||||
that omit off-day children stay collapsed). `TaskDetail.parent` carries the
|
||||
parent for the detail card.
|
||||
- ✅ Reparent — a full-width, searchable "Parent task" sheet on the edit form
|
||||
groups active candidates by due-date section (Overdue / Today / Upcoming / No
|
||||
date) and files a task under any top-level task in its list (or "None" to
|
||||
promote it); switching list clears the now-invalid parent. Candidates stay
|
||||
active + top-level to keep nesting one level deep, matching the detail screen.
|
||||
|
||||
### ⬜ M5 — Reminders onboarding & polish
|
||||
The engine exists (M1). Remaining: the `POST_NOTIFICATIONS` + exact-alarm
|
||||
onboarding flow, per-task / default reminder-offset settings UI, and
|
||||
end-to-end verification on device.
|
||||
### 🚧 M5 — Reminders onboarding & polish
|
||||
The engine exists (M1: `ReminderScheduler` + boot / provider-change re-sync,
|
||||
`DueReminderReceiver`, `TaskNotifier`).
|
||||
- ✅ Per-task reminder-offset UI (`ReminderPickerDialog` → `TaskForm`
|
||||
`reminderMinutesBeforeDue`).
|
||||
- ⬜ `POST_NOTIFICATIONS` + exact-alarm onboarding flow — currently only graceful
|
||||
runtime checks (`TaskNotifier.canPost`, `canScheduleExactAlarms`), no
|
||||
user-facing gate.
|
||||
- ⬜ Default reminder-offset settings UI — `SettingsPrefs`/`SettingsViewModel`
|
||||
back it, but no Composable exposes it.
|
||||
- ⬜ End-to-end verification on device.
|
||||
|
||||
### ⬜ M6 — Settings, widget, i18n, release
|
||||
Settings screen (theme / dynamic-color / language, default list, default
|
||||
reminder), Glance task-list widget, translations, finalize F-Droid metadata,
|
||||
confirm CI release flow.
|
||||
### 🚧 M6 — Settings, widget, i18n, release
|
||||
- ✅ F-Droid metadata scaffolded (`fdroid-metadata/`).
|
||||
- ⬜ Settings screen — `SettingsViewModel` exists but no `SettingsScreen`
|
||||
Composable and it is not in the nav graph (only used by `MainActivity` for
|
||||
app-level theming). Needs theme / dynamic-color / language, default list,
|
||||
default reminder, and the opt-out toggle for the task list's inline
|
||||
add-a-subtask row (on by default since M4).
|
||||
- ⬜ Glance task-list widget — deps present in `build.gradle.kts`, zero impl.
|
||||
- ⬜ Translations — only `res/values/` (English); no `values-XX`.
|
||||
- ⬜ Finalize F-Droid metadata, confirm CI release flow.
|
||||
|
||||
### ⬜ Posture B (separate track, later)
|
||||
Add a `:provider` module bundling the Apache-2.0 `opentasks-provider`;
|
||||
|
||||
Reference in New Issue
Block a user