The create form (v1.2) now edits: a pencil on the detail screen (writable calendars only, contextual WRITE upgrade like delete) opens it prefilled via EventDetail.toEditForm; populated sections always show, the calendar is fixed, and a dirty-check writes only changed columns (pristine saves are no-ops). Saving a dirty recurring event parks in SaveUiState.AwaitingScope and asks how far the change reaches (Google model): "only this event" = modified-occurrence exception via CONTENT_EXCEPTION_URI (empty optionals as explicit NULLs since the provider clones the parent row), "this and all following" = series split (insert new event first, then truncate), "all events" = series-row update with the time delta applied to the series DTSTART. A changed rule drops the exception option. Delete gained the same middle scope. Recurrence: EventForm.rrule + SimpleRecurrence (FREQ/INTERVAL/UNTIL/COUNT + weekly BYDAY with locale-ordered weekday toggles) behind a picker on create and edit; unrepresentable rules render humanized (shared ui/common RecurrenceText) and survive verbatim. UNTIL validation flags rules ending before the event starts. Provider lessons baked in (verified on-device via adb probes): instance caches regenerate only from an update's own values, so truncation sends the full time-column set (truncateSeries) — RRULE-only updates left a stale duplicate occurrence on the split day; UNTIL is written as the local end of day in UTC (toRRule(zone), previousLocalDayEndUtcMillis) so UTC+x zones can't leak an extra day. Reminder edits reconcile against actual provider rows, keeping untouched rows' methods. Tests: RecurrenceTest (parse/render/round-trip, truncation), update/exception mapper paths, repository pass-throughs, prefill + populatedFields, raw-title mapper. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
72 lines
4.2 KiB
Markdown
72 lines
4.2 KiB
Markdown
# Calendula — Current State
|
||
|
||
*Last updated: 2026-06-11*
|
||
|
||
## Status
|
||
|
||
**Milestone:** v2.0 — Write support (milestone 2, in progress)
|
||
**Phase:** v1.3.0 (edit event) shipped 2026-06-11 after four on-device
|
||
review rounds (BYDAY toggles, scoped recurring writes, scope-at-save flip,
|
||
stale-instances split bugfix). Milestone 2 runs in four slices
|
||
(`docs/superpowers/plans/2026-06-11-03-write-support.md`); v2.0 (quick-add,
|
||
conflict dialog, polish) is the remaining slice, v1.4 (reminder
|
||
notifications) comes first.
|
||
|
||
## Progress
|
||
|
||
- [x] Design spec written and committed (`docs/superpowers/specs/2026-06-08-calendar-app-design.md`)
|
||
- [x] V1 design decisions resolved (App name "Calendula", icon, seed color)
|
||
- [x] Plan 01 written and executed — foundation lands (theme, icon, i18n, Hilt, DataStore, CI green)
|
||
- [x] Plan 02 written and executed — data layer + permission flow + debug screen
|
||
- [x] Month view (S1) — 6-week grid, event dots, today marker, swipe nav, three states (replaces debug screen)
|
||
- [x] Week view (S2) — time schedule with overlap-resolved lanes, all-day strip, swipe nav, three states
|
||
- [x] Day view (S3) — single-column slice reusing the week layout
|
||
- [x] View-switcher (M1) wired — cycles Month ↔ Week ↔ Day
|
||
- [x] Event-detail screen (S4) — full-screen, humanized recurrence
|
||
- [x] Filter sheet (M3) — per-calendar visibility, grouped by account, persisted, applied centrally in the repository
|
||
- [x] Settings (M4) — appearance (theme, dynamic colour, week start), language (per-app locales), about
|
||
- [~] Jump-to-date (M2) — **cut from scope**; "Today" half shipped in v0.5, date-picker dropped
|
||
- [x] Full event read (v0.6) — reminders, status, availability, access level,
|
||
attendee role + self-response, foreign timezone, and linkified description
|
||
URLs in the detail view; new domain enums + mapper unit tests. (A dedicated
|
||
URL field was cut — no `CalendarContract` column backs it.)
|
||
|
||
- [x] v1.1 write foundation — `WRITE_CALENDAR` (onboarding asks READ+WRITE,
|
||
only READ gates; contextual upgrade for v1.0 installs), read-only-calendar
|
||
detection (`CALENDAR_ACCESS_LEVEL` → `canModifyContents`, actions hidden for
|
||
WebCal/birthday calendars), delete from the detail screen (recurring:
|
||
"only this event" via cancelled exception / "all events in the series"),
|
||
repository + mapper tests
|
||
|
||
- [x] v1.2 create event — full-screen `EventEditScreen` (title, all-day,
|
||
M3 date/time pickers with duration-preserving start moves, writable-only
|
||
calendar picker preselecting the last-used calendar, location, description),
|
||
"+" FAB on all three views prefilled with the visible day, `insertEvent`
|
||
with provider-correct all-day normalisation (UTC midnights, exclusive end),
|
||
domain/mapper/repository tests
|
||
|
||
- [x] v1.3 edit event (shipped 2026-06-11) — `EventEditScreen` reused for
|
||
edit (detail-screen Edit action, `canModify`-gated, contextual WRITE
|
||
upgrade), dirty-checked partial `update` on the Events row (recurring:
|
||
series DTSTART moves by the user's delta, DURATION instead of DTEND),
|
||
reminder diff by minutes (kept rows keep their method), simple recurrence
|
||
picker (FREQ/INTERVAL/UNTIL/COUNT; complex RRULEs preserved verbatim and
|
||
shown humanized), `EventFormField.Recurrence` incl. settings default,
|
||
recurrence also available on create; domain/mapper/repository tests.
|
||
Review round 1: weekly BYDAY day-toggles in the custom picker ("every week
|
||
on Mon+Fri"). Review rounds 2–4: occurrence edit pulled forward from v2.0
|
||
and made three-way like delete ("this" = exception row via
|
||
`CONTENT_EXCEPTION_URI`, "this and following" = series split, "all" =
|
||
series update); delete equally three-way (truncation via RRULE UNTIL);
|
||
the edit-scope question moved to save time (Google model) — dirty
|
||
recurring saves park in `SaveUiState.AwaitingScope`, a changed rule drops
|
||
the "only this event" option
|
||
|
||
## Next
|
||
|
||
1. v1.4 — reminder notifications (essential for sole-app use): `EVENT_REMINDER`
|
||
receiver + notification channel, `POST_NOTIFICATIONS`, onboarding step with
|
||
default-on toggle + duplicate-reminder warning (Etar model)
|
||
2. v2.0 — quick-add sheet, conflict dialog, polish pass, milestone release
|
||
3. Monitor the F-Droid build/publish for v1.1.0 – v1.3.0
|