Commit Graph
36 Commits
Author SHA1 Message Date
makiolajandClaude Opus 4.8 c0d413ba11 docs: backlog the initial grant-access screen redesign (pre-1.0 polish)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 09:08:21 +02:00
makiolajandClaude Opus 4.8 dca0245a42 refactor(detail): show availability only when Free, pin it by the title
The Busy availability value is the default for nearly every event, so a
"Busy" chip on every detail screen was noise. Show the pill only for Free
(the noteworthy case) and move it to the top-right of the title row instead
of the under-title chip strip. That strip now carries only status/access and
hides entirely when there's nothing noteworthy. Drops the now-unused
event_availability_busy string from both locales.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 09:08:21 +02:00
makiolajandClaude Opus 4.8 024512959f feat(detail): full event read — surface every readable field (v0.6.0)
Round out the read-only model so the detail view shows everything
CalendarContract actually stores, ahead of write support.

Data layer:
- New domain types: Reminder, EventStatus, Availability, AccessLevel,
  AttendeeRelationship, AttendeeType; EventDetail gains reminders, status,
  availability, accessLevel, eventTimezone, selfStatus and Attendee gains
  relationship + type (all defaulted so existing callers compile)
- EventDetailProjection reads STATUS / AVAILABILITY / ACCESS_LEVEL /
  EVENT_TIMEZONE / SELF_ATTENDEE_STATUS; AttendeeProjection reads
  RELATIONSHIP + TYPE; new ReminderProjection queries CalendarContract.Reminders
- Mappers translate each provider integer code, guarding STATUS's null-vs-0
  ambiguity (0 == TENTATIVE) so an absent status reads as Confirmed
- Mapper unit tests cover every new column's codes

Detail UI:
- Status / availability / access chips under the title; cancelled also strikes
  the title through
- Reminders card with humanised lead times (plurals, DE + EN)
- Foreign-timezone card, shown only for timed events in a non-device zone
- Attendee role badges + the user's own "Your response: …" line
- http(s) URLs in the description are now tappable

URL field cut: CalendarContract exposes no Events.URL column (only the
CUSTOM_APP_URI app deep-link), so URLs are surfaced by linkifying the
description instead. Recorded in ROADMAP/CHANGELOG.

Version bumped to 0.6.0 / 6.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 08:56:40 +02:00
makiolajandClaude Opus 4.8 e78da3d7c1 docs: add v0.6 "full event read" milestone before v1.0
CI / ci (push) Successful in 12m21s
Plan to surface every readable CalendarContract field (reminders, status,
availability, attendee role + self-status, timezone, URL, access level) in
the detail view before write support. Recurrence-override badges and
CATEGORIES/ATTACH stay out (the former folds into v2, the latter is a
provider limitation). Noted only — implementation comes later.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-10 23:35:02 +02:00
makiolajandClaude Opus 4.8 2cb8b59fb7 docs: cut jump-to-date (M2) from V1 scope
The date-picker half of M2 is dropped entirely; the "Today" half already
shipped in v0.5. V1 is now feature-complete and only a polish/QA pass
remains before v1.0.

Updated the living planning docs (ROADMAP, STATE, REQUIREMENTS) and the
design spec; corrected the v0.5.0 CHANGELOG note that promised M2 would
return in v1.0.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-10 23:27:21 +02:00
makiolaj 7d36d22fd5 Merge pull request 'feat: calendar filter in drawer + settings (v0.5.0)' (#1) from feat/filter-settings-v0.5.0 into main
CI / ci (push) Has been cancelled
Build and Release to F-Droid / ci (push) Successful in 7m48s
Build and Release to F-Droid / build-and-deploy (push) Successful in 9m50s
2026-06-10 20:57:57 +00:00
makiolajandClaude Opus 4.8 adcbed6e02 feat(filter,settings): calendar filter in drawer + settings (v0.5.0)
CI / ci (push) Successful in 12m42s
CI / ci (pull_request) Successful in 12m23s
M3 — calendar filter: the navigation drawer now hosts the calendar list
inline (grouped by account, colour swatch + checkbox per calendar). Hidden
calendars are persisted app-side and filtered centrally in the repository,
so month/week/day re-filter live the moment a checkbox flips. Drawer trimmed
to Today, the calendar filter, and Settings, with leading icons and a clear
title/section type scale; the stubbed jump-to-date entry (M2) was removed.

M4 — settings: full-screen destination with appearance (theme System/Light/
Dark, Material You dynamic colour auto-disabled < API 31, week start Auto/Mon/
Sun), language (per-app locales via AppCompat, persisted to API 29), and an
about section (version, licence, source link). Theme is driven by one
activity-scoped settings source so changes apply app-wide at once. Week start
now drives the month grid and week view; Auto follows the locale.

Also:
- default view switched from month to week
- Settings screen handles system back (was closing the app)
- fix pre-existing NonObservableLocale/LocalContextConfigurationRead lint
  errors in EventDetailScreen so CI lint is green again
- versionName/versionCode bumped to 0.5.0 / 5

Tests: repository hidden-filter (incl. live re-emit), SettingsPrefs round-trip
+ week-start resolution, filter grouping. lint + unit tests + assembleDebug green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-10 22:55:33 +02:00
makiolajandClaude Opus 4.8 efa0abbaed feat(detail): full-screen event detail (S4) with humanized recurrence
CI / ci (push) Failing after 6m55s
Build and Release to F-Droid / ci (push) Successful in 7m48s
Build and Release to F-Droid / build-and-deploy (push) Successful in 9m40s
Tapping an event in the week/day timeline opens a full-screen detail
destination (MD3 list→detail, not a bottom sheet) overlaying the calendar
with a slide transition. One card per field (when, calendar, location,
description, attendees, recurrence) with leading icons; location taps open
a maps intent. Loading/Failure/Success throughout.

Recurrence is humanized from the RRULE — e.g. "Every week on Tue and Thu
until 31 Dec 2026" — covering FREQ/INTERVAL/BYDAY/UNTIL/COUNT with
abbreviated, italicised day names and localized list formatting, falling
back to a generic label for rules it can't render.

Also:
- fix: recurring events failed to open (series row stores DURATION, not
  DTEND, so the mapper dropped them as EventNotFound). The detail keeps
  them and shows the tapped occurrence's own times from Instances.
- feat: month day cell → opens the day view anchored to that date.
- build: add material-icons-extended (R8 strips unused icons in release).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-10 21:52:35 +02:00
makiolajandClaude Opus 4.8 d3fbe28843 docs: record v0.3.0 (month/week/day views, view switcher) in CHANGELOG
Build and Release to F-Droid / build-and-deploy (push) Successful in 8m43s
CI / ci (push) Successful in 10m49s
Build and Release to F-Droid / ci (push) Successful in 6m16s
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-10 20:44:22 +02:00
makiolajandClaude Opus 4.8 951fb640a6 feat(day): single-column day view, wire into view switcher
Day view as a one-column slice of the week view: shared TimedBlock/
AllDaySpan layout, per-day swipe navigation, hoisted noon-centred scroll,
animated all-day strip, and a compact top bar showing the full date.

- DayUiState / DayViewModel / DayScreen under ui/day
- reuse layoutDay/layoutAllDay/coversDay from the week package
- add Day to IMPLEMENTED_VIEWS; CalendarHost routes it explicitly
- day_today_action strings (en/de)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-10 20:40:02 +02:00
makiolajandClaude Opus 4.8 94fa206e2e refactor(week): polish timeline — rounded viewport, scroll persistence, week badge
CI / ci (push) Successful in 11m40s
- Rounded, permanently-soft day-column scroll viewport via two viewports
  sharing one scroll state (gutter + columns stay aligned); plain
  rectangular column cards inside
- Vertical scroll position now persists across week swipes; noon-centring
  only runs on first entry into the week view (from month/day)
- All-day strip height is hoisted + animated, shared by both swipe pages,
  so it slides along and resizes smoothly instead of jumping
- Multi-line event time label so the end time isn't clipped in narrow
  columns; hour labels centred in the gutter
- Calendar-week (ISO) badge in the header gutter, aligned with the date
  numbers; dropped the redundant "All-day" gutter label
- Small breathing room between the top section and the timeline

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-10 20:05:40 +02:00
makiolajandClaude Opus 4.8 6a90bade8a feat(ui): month card grid + week timeline, wire view switcher
Replace the throwaway debug screen with the first real calendar UI and a
functional Month <-> Week switcher, on Material 3 Expressive.

Month view (S1):
- Material 3 Expressive card-per-day grid; only the current month's weeks
  render (neighbouring days left blank)
- per-day event dots with "+N" overflow, today via primaryContainer
- spring-based press feedback from the active motion scheme
- swipe + drawer navigation, Loading/Failure/Success states

Week view (S2):
- vertical time schedule with overlap-resolved lanes (per-day clipping,
  midnight spanning, instant events)
- all-day / multi-day events as connected horizontal spans
- single scroll container (gutter + day columns stay aligned), columns
  bundled in a rounded container, noon-centred on load
- top section colour-shifts with the app bar on scroll; swipe navigation,
  three states

Shared / infra:
- CalendarHost holds the active view; RootScreen renders it post-permission
- ui/common building blocks: CalendarDrawer, CalendarFailure,
  ViewSwitcherPill, pastelize, observable locale, M3 Expressive slide
  transition (motionScheme fastSpatialSpec)
- unit tests for the week layout (lanes, clipping, all-day spans)
- build: compileSdk 37, material3 pinned to 1.5.0-alpha21 for Expressive

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-10 20:05:40 +02:00
makiolajandClaude Opus 4.8 0132201cf9 style(icon): regenerate F-Droid icon.png to match launcher exactly
CI / ci (push) Successful in 10m41s
Build and Release to F-Droid / ci (push) Successful in 5m59s
Build and Release to F-Droid / build-and-deploy (push) Successful in 8m27s
Re-render both locale catalog icons (512x512) from the same logo as the
Android adaptive launcher icon, baking in the foreground group transform
(scale 0.5, pivot 114,108, translate 2,8) over the slate background so the
F-Droid render is pixel-faithful to the on-device icon.

Add design/icon/calendula_launcher.svg as the composed full-bleed source
of truth for store/F-Droid renders.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-09 10:38:08 +02:00
makiolaj b792ddc2f0 style: fix launcher icon scaling and centering, update AGP
CI / ci (push) Successful in 9m58s
2026-06-08 20:30:40 +02:00
makiolaj 440fa57161 fix(debug): use prefixed composite keys in LazyColumn
CI / ci (push) Successful in 9m35s
Cal.id and Event.instanceId share a numeric range, and the LazyColumn
keys both sections — colliding values (e.g. cal-id=4 + event-instance-id=4)
crashed with "Key '4' was already used". Additionally, Instances._ID is
inherited from the parent Event, so recurring events produce multiple
rows with the same instanceId; the start instant disambiguates them.
2026-06-08 20:19:58 +02:00
makiolaj 2a2b919041 docs: record v0.2.0 data-layer + permission flow in CHANGELOG, planning
CI / ci (push) Successful in 9m53s
Build and Release to F-Droid / ci (push) Successful in 5m58s
Build and Release to F-Droid / build-and-deploy (push) Successful in 8m7s
2026-06-08 17:58:02 +02:00
makiolaj 3ced240e23 test: instrumented repository smoke against real CalendarContract 2026-06-08 17:57:12 +02:00
makiolaj 035ac9b003 test: replace placeholder smoke with permission-rationale assert 2026-06-08 17:56:03 +02:00
makiolaj c03389abe0 ui: replace placeholder with RootScreen routing permission ↔ debug 2026-06-08 17:55:34 +02:00
makiolaj 98f8433156 ui: add DebugScreen showing calendars + next 50 instances 2026-06-08 17:54:23 +02:00
makiolaj 8fbbab30e2 ui: add DebugViewModel combining calendars + next 30d instances 2026-06-08 17:52:50 +02:00
makiolaj ef0a4b0568 ui: add PermissionScreen with rationale and denied recovery 2026-06-08 17:50:33 +02:00
makiolaj 43f12812b6 ui: add PermissionViewModel with three-state machine 2026-06-08 17:49:39 +02:00
makiolaj 2400d5482c i18n: add permission + debug screen strings (en, de) 2026-06-08 17:49:06 +02:00
makiolaj 4d54501ed4 di: wire CalendarRepository, DataSource, DataStore, IoDispatcher 2026-06-08 17:48:34 +02:00
makiolaj 748df761bf data: add CalendarPrefs (hidden calendar ids in DataStore) 2026-06-08 17:47:55 +02:00
makiolaj d13f2f07a5 data: add CalendarRepository + Impl with SharedFlow re-emit on data-source ticks 2026-06-08 17:47:13 +02:00
makiolaj 7abb2e6ab4 data: add CalendarDataSource seam returning domain lists (not Cursors)
Deviation from Plan 02: changing from Cursor-returning interface to
domain-returning interface so the repository unit tests can use a simple
fake without constructing ContentObserver/Handler/Looper on the JVM
(which would either crash or no-op via the mockable.jar stubs).
2026-06-08 17:44:19 +02:00
makiolaj fb003d8806 data: add ColumnReader.toEventDetailCore() and toAttendee() mappers 2026-06-08 17:42:42 +02:00
makiolaj 40b531fa52 data: add ColumnReader.toEventInstance() with defensive validation (§8) 2026-06-08 17:41:29 +02:00
makiolaj 0e4c47febe data: add ColumnReader abstraction + Cursor.toCalendarSource mapper
Deviation from Plan 02: the JVM mockable-android.jar stubs every Cursor
method even with isReturnDefaultValues=true (returns null/0 regardless of
the underlying MatrixCursor backing). Introduce an internal ColumnReader
interface so mappers stay pure-Kotlin and JVM-testable via MapColumnReader,
while production reads through CursorColumnReader.
2026-06-08 17:40:37 +02:00
makiolaj fb723fba68 data: add CalendarContract column projections + indices
Build and Release to F-Droid / ci (push) Has been cancelled
Build and Release to F-Droid / build-and-deploy (push) Has been cancelled
2026-06-08 17:37:23 +02:00
makiolaj af75965a31 domain: add pure-Kotlin models (CalendarSource, EventInstance, EventDetail, …) 2026-06-08 17:36:39 +02:00
makiolaj 1b456d2133 data: add TimeBridge helpers for epoch-millis ↔ kotlin.time.Instant 2026-06-08 17:35:49 +02:00
makiolaj a826e82bdc build: add kotlinx-datetime, coroutines, turbine, hilt-nav-compose, lifecycle-compose 2026-06-08 17:32:45 +02:00
makiolaj ed680b4482 docs: add Plan 02 - Data Layer & Permission Flow implementation plan
21 bite-sized tasks covering domain models, CalendarContract data layer
(Cursor mappers with §8 defensive validation, ContentObserver-backed
SharedFlow repository), DataStore-persisted hidden-calendar set, Hilt
wiring, READ_CALENDAR permission flow (rationale + denied recovery), and
a wegwerfbarer Debug screen that visually validates data is flowing.

Out of scope: Month/Week/Day views (Plans 03-05), Event Detail Sheet
(Plan 06), Filter/Settings (Plan 07).
2026-06-08 17:30:41 +02:00