The release/* branch protection requires the "Translations / check" status,
but the workflow was path-filtered to translation resources. A code-only PR
targeting a release branch never touches those, so the workflow never ran,
never posted its status, and the required check stayed pending forever —
permanently blocking the merge (only PRs that happened to change strings could
satisfy it).
Drop the path filter so it runs on every PR, mirroring the always-on `ci` job.
The parity check is SDK-free and passes when the committed translations are
consistent, so running it on unrelated PRs is effectively free.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The calendar row in the editor is now tappable when editing an existing
event: picking a different calendar moves the event there on save, rather
than forcing a delete-and-recreate.
CALENDAR_ID is sync-adapter-owned and can't be updated in place, so the
move is copy+delete: the master row is re-inserted on the target calendar
(preserving UID_2445 so backup dedup and sync identity survive), its
reminders and editable guests are copied, and — for a recurring series —
every exception is replayed against the new master (modified occurrences
via CONTENT_EXCEPTION_URI, cancellations as STATUS_CANCELED). The user's
field edits are then applied with the normal series update. Everything on
the new side is built before the source is deleted (post-before-delete),
with a rollback of the copy on any failure, so a move is all-or-nothing.
A calendar change forces whole-series scope, so it skips the recurring
scope dialog. Managed special-dates calendars stay locked. Colour is not
carried across (a raw/keyed colour may be invalid on the target account),
matching the existing calendar-switch behaviour.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The Snooze-duration setting gains a Custom… option: a new single-select
SnoozeDurationPicker keeps the minute presets and adds a Custom row that
expands an amount field with a Minutes/Hours toggle, so any delay is settable
(not just the fixed presets). Closes the settings half of the snooze request.
The three presets-plus-custom editors (reminder default, agenda range, snooze)
now delegate to floret-kit's new CustomAmountEditor instead of each duplicating
the tonal editor card — the app keeps its domain math, strings and labels.
Re-pin the floret-kit submodule to the branch commit carrying CustomAmountEditor.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Move the submodule pin from a loose main commit to the tagged v0.1.0
release (same tree content), so the from-source F-Droid build tracks a
stable, traceable kit version instead of a rolling commit.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Recapture all phone screenshots on the Pixel 10 Pro (Android 16) at a
uniform 1280x2856 across every locale, showing the current UI with sample
events: week, month, day, event detail, agenda, and the calendar-access
onboarding. Replaces the old 05-edit shot with 05-agenda (the light theme
has no standalone edit screen) for en-US and de-DE.
Add fully localized store metadata (title, summary, full description) and
per-locale icon for Italian (it-IT) and Spanish (es-ES), matching the
existing en-US/de-DE listings; the app UI is already translated for both.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Unify the app's "choose one" surfaces on the full-screen picker style
(floret-kit FullScreenPicker/OptionPicker) instead of the OptionCard modal
dialogs, for consistency across the app:
- Event editor: visibility + add-field -> OptionPicker; reminder, recurrence
rule, and colour -> FullScreenPicker, with the custom-value Add / OK and the
colour Reset carried in the app-bar via the picker's new `actions` slot; the
save-conflict chooser -> full-screen.
- The recurring scope choosers stay compact OptionCard popups — saving an edit
to, or deleting, a recurring event — since a quick 2-3 option decision reads
better as a popup than a near-empty full screen.
Bumps the floret-kit pin (55ad536 -> e1919ca) for the FullScreenPicker
`actions` passthrough.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Brings the floret-kit migration onto the 2.14.0 release line: Calendula now
draws its shared UI/crash/locale/reminder/time code from the floret-kit
submodule (Gradle composite build) instead of inline copies, plus the
week-number isoWeekNumber extraction and the wrapped-title height animation.
Pins floret-kit at 55ad536 (origin/main). Integrated for a full pre-release
verification sweep; on-device review still owed before cutting the release.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Long titles wrap to a second line (#33); the field's height — and the
accent bar and cards below it — snapped to the new height. Apply the new
floret-kit Modifier.animateContentSizeMotion() to the title field so the
height eases on the M3 Expressive motion scheme (snapping under reduced
motion), and bump the kit pin (cded442 -> 55ad536) to the commit adding it.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The Week and Month grid headers each inlined the same ISO-week-number
computation. Replace both with the new shared
core-time LocalDate.isoWeekNumber(), and bump the floret-kit submodule
pin (5a576c4 -> cded442) to the commit that adds it.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Brings the 2.14.0 feature set (Month week numbers, .ics restore +
per-calendar export picker, Day view on date-header tap, wrapped long
titles, Simplified Chinese) onto the floret-kit migration without
resurrecting the inline component copies the kit now owns.
Conflict resolutions (both were import-block collisions where the
migration repointed to de.jeanlucmakiola.floret.* while release kept the
old app-local imports):
- CalendarsScreen.kt: keep the kit imports (CollapsingScaffold,
DialogAmountField/DialogUnitDropdown, collapseExit/expandEnter,
predictiveBack) and repoint FullScreenPicker + positionOf to the kit
(both moved out of ui.common). Keep the genuinely app-local
LeadingAvatar/SourceLogo/curatedSourcePackage; drop the renamed
calendarCollapseExit/calendarExpandEnter (0 uses).
- ImportScreen.kt: keep the app-local CalendarPickerGroups, use the kit's
predictiveBack, drop the now-unused OptionCard import.
Semantic fixup: CalendarPickerGroups.kt (new in 2.14.0) relied on
same-package resolution of GroupedRow/Position, which the migration moved
to the kit — added the explicit floret.components imports.
Verified: :app:compileDebugKotlin, ./gradlew test (app + kit), and
scripts/check_translations.py all green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Supersedes the stale chore/floret-kit-core-time branch: re-applies the
floret-kit migration on top of current main (122 commits ahead of the old
branch's base), pinning the kit at the multi-value-reminders + pinned-picker HEAD.
- Submodule + composite build (includeBuild), 6 module deps, CI submodules:
recursive, reproducible-release scan extended to the kit, F-Droid recipe.
- Deletes the inline copies now owned by the kit (GroupedList, Picker scaffolds,
InlineTextField, OptionCard, DialogControls, CrashReporter + dialog/submit,
OnboardingScaffold, AppLanguage, TimeBridge, ReorderableColumn, DebugRibbon)
and redraws them from components/identity/core-crash/core-locale/core-time.
- Reminder overrides drawn from core-reminders (multi-value ReminderOverride +
codec); Calendula keeps its app-specific bits (all-day resolution, labels,
presets, the multi-select ReminderDefaultPicker, its own CrashReportActivity).
- Theme draws FloretExpressiveTheme while keeping the user-typography param.
Build pending (deferred): run ./gradlew :app:compileDebugKotlin with ANDROID_HOME
(or floret-kit/local.properties) set.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add zh-CN to locales_config.xml so the community Simplified Chinese
translation (values-zh-rCN, already committed via Weblate, ~27%) is
selectable in the in-app language picker and Android's per-app-language
settings. Untranslated strings fall back to English.
Fill in the 2.14.0 changelog, which only documented #37: add the three
feature PRs that also landed on this branch — .ics restore + per-calendar
export (#32), Month week numbers (#25), edit-screen title wrapping (#33) —
plus a note for the new Chinese translation, the missing [#N] link refs,
and the re-synced fastlane en-US changelog.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The edit-screen title field was single-line, so long titles scrolled off
one line instead of wrapping. Make it multi-line so it wraps and grows
vertically, matching the detail screen and Google Calendar.
A title is still one logical line: strip any newline the IME's Enter key
or a paste would introduce in setTitle, so no line break reaches the
provider's TITLE column.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Per on-device review, render the week number as a full-height tonal pill
mirroring the day cells' geometry (secondaryContainer tint, same rounded
shape and gap), with the number centred — so the gutter reads as part of the
grid rather than a floating chip. This diverges from the Week view's small
header chip, so revert the shared-badge extraction: restore WeekScreen's
private badge and drop ui/common/WeekNumberBadge.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Extract the Week view's calendar-week badge into a shared ui/common
component and reuse it for the Month grid's week-number gutter, so the two
views show week numbers in the exact same format. The gutter now centres the
badge vertically in each row (was pinned to the day-number band) and is
widened to seat the badge.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add an opt-in left gutter to the Month grid showing the ISO calendar-week
number, gated by a new "Week numbers" display setting (default off). The
number is computed on each row's first day — the same basis as the Week
view's badge — so the two views agree, and rendered as a low-emphasis
onSurfaceVariant label so it recedes across all six rows rather than
competing with the event bars. The weekday header reserves a matching
gutter so the day columns stay aligned.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Bump versionName to 2.14.0 (versionCode 21400) and cut the changelog for
the day-view-on-date-header-tap feature (#37). Merging this to main
triggers the release pipeline.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The fake now records the calendarIds it receives; two repository tests
assert exportEvents forwards a chosen subset and defaults to null (all
eligible calendars), closing the coverage gap for the per-calendar
export selector.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Restore is import, not export: offer it whenever any writable, non-
managed calendar exists (local or synced), not only when there is a
local calendar to back up. Previously the row lived inside the
export-gated block and vanished for users with only a writable synced
calendar, despite import supporting that target.
- Export-picker selection now uses rememberSaveable and is no longer
keyed on the observer-driven calendars list, so a background provider
re-emit (sync/recolor) can't silently reset the user's de-selections,
and the choice survives rotation.
- Shared calendar picker: restore the displayName fallback for a synced
calendar whose account name and type are both blank (was grouping them
under an empty header).
- Drop imports left dead by the CalendarPickerGroups extraction.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ImportScreen has no nav backstack, so an unkeyed hiltViewModel() resolved
to the Activity's ViewModelStore and was retained across imports. Its
one-shot `load` guard then showed the *previous* file's parsed state on
the next import — trivially reachable now that the in-app Restore button
lets you export→restore or restore twice in one session (worst case: the
picker still holds file A, so tapping Import writes A's events after you
picked B). Keying the VM by the file uri hands each distinct file a fresh
VM (fresh Loading state); the same uri (rotation) reuses it and holds the
result.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Tapping a date header in the Week (day-of-week column) and Agenda
(sticky section) views now drills into that date in Day view, mirroring
the Agenda widget's header behaviour. Both reuse the existing onOpenDay
callback (pendingDayIso + drillToDay) that Month already used, so the
back stack lands on Day with the tapped view as its parent.
Month already navigated on any cell tap (the transparent tap layer sits
above the day number), so no change was needed there — all four views
now behave consistently.
Closes #37
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The pre-selected target was calendars.first() (raw provider order), which
could land on a synced calendar mid-list while the picker shows local
calendars first. Default to the first local calendar so the checkmark lines
up with the top row; fall back to the first calendar when none are local.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Move the multi-event import's confirm button into the app-bar actions so
it's reachable without scrolling past a long calendar list, and put the
count in the title ('Importing 5 events') instead of a separate 'N events
in this file' line. Hoists the selected target calendar to the screen so
the top-bar action can read it.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Route by entry point, not just event count. Opening a .ics from outside
still sends a single event straight to the prefilled create form (add one
event, e.g. a ticket). The in-app 'Restore from .ics' button passes
forceMany so even a single-event backup goes through the calendar picker +
summary — its intent is 'restore a backup', not 'add this event'.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The import de-dups by UID against the target calendar (idempotent restore),
so re-importing events already present shows a low 'Added' count. Add a note
under the title when any were skipped so the outcome doesn't read as broken.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Tapping Export with more than one exportable calendar now opens a picker
to choose which local calendars to include (all selected by default); a
single calendar exports straight through as before. Threads an optional
calendarIds filter through exportEvents/exportableEvents (null = all
eligible), so the auto-backup path is unaffected. The backup section is
now gated on there being at least one exportable (non-managed) calendar.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Symmetric with the export change: the contact-derived, editor-locked
special-dates mirror calendars aren't a valid import destination, so drop
them from the target-calendar picker.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The contact special-dates mirror calendars (birthdays/anniversaries) are
derived from contacts and re-materialise from the contact sync, so backing
them up only duplicates events on restore. Skip managed calendars in
exportableEvents — covers both the manual export and the auto-backup, which
share this path.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace the plain centered text list with an M3 Expressive success state:
a tonal check badge that springs in, the headline, and big-number tonal
stat tiles for added / duplicate-skipped counts, with a full-width Done
button. Stat tiles carry the full-sentence plurals as accessibility
labels so TalkBack still reads 'Imported N events'.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Extract CalendarPickerGroups into ui/common: the calendar-manager screen's
grouped-card system (device chip for local calendars, the owning app's
launcher icon per synced account, colour chip + check per calendar) as a
single reusable picker. Use it in both the event editor and the .ics import
screen so all 'which calendar' lists match.
Moves LeadingAvatar/SourceLogo/curatedSourcePackage out of CalendarsScreen
into common as the shared source of truth. Drops the redundant 'Add to
calendar' caption from the import picker.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The 'Add to calendar' picker rendered bare OptionCards with no calendar
colour and no account grouping. Reuse the same account-grouped GroupedRow
layout as the event editor's calendar picker — coloured chip per calendar,
account sub-headers, a check on the selected row — so it matches the rest
of the app.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add a 'Restore from .ics file' row to the Calendars backup section, next
to Export. It opens a SAF document picker and routes the picked Uri into
the existing import flow (parse, dedup by UID, target-calendar picker,
summary) via CalendarHost's importUri — the same path an externally
opened .ics already takes, so no new import machinery is needed.
Closes #32.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Patch release bundling the fixes for #34 (pre-1970 recurring events could
not be opened) and #27 (time-picker dial ignored the 24h setting), plus
#30 (create events from external ACTION_INSERT launches). Bumps
versionName to 2.13.1 (versionCode 21301) and cuts the changelog.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>