Add a "Soften calendar colours" setting (Settings → Design, default on).
Turning it off paints calendar and event colours raw, exactly as the sync
source (DAVx5/CalDAV) publishes them, instead of the theme-fitting pastels
(#36).
Event/calendar colours now flow through shared eventFill()/eventInk()
helpers gated by a LocalSoftenColors composition local (widgets read the
pref directly). Event titles pick black or white text by the fill's WCAG
relative luminance, so a dark colour stays legible whether softened or raw
(#21) — previously always near-black.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Both landed as community translations through Weblate (French ~33%, Polish
~57%), above the bar already shipped for zh-CN. Add them to locales_config.xml —
the single source of truth for the in-app language picker and Android's per-app
language settings.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add a Duplicate action to the event detail top bar that opens the shared
event form seeded with a copy of the event as a new, unsaved event, so a
non-recurring event can be re-created with just the day and time changed
instead of re-entering every field.
The copy reuses the existing prefilled-create overlay (createEvent), so it
becomes an independent event with the default reminder applied. Recurrence
is dropped — a duplicate is a single event; the edit form still exposes a
recurrence picker for anyone who wants a series. The occurrence's own times
carry over unchanged. Duplicate is offered for any loaded event, including
read-only ones (WebCal, birthdays): the source calendar is kept only when
it's writable, otherwise the copy resolves to the first writable calendar.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add an "Always show today" setting (Settings → Agenda, on by default) that
keeps today as the first entry in both the Agenda screen and its home-screen
widget even once nothing is left today. Under today's normal header a small
"No more events today" card appears — the coffee-cup empty-state motif in the
app, a rounded surface in the widget — so the first rows you see are clearly
today's rather than a future day's.
The anchor is a pure, JVM-tested helper (anchorTodayIfMissing) applied after
past-event filtering; in-app it only kicks in when the window starts on today,
never on a jumped-to date. The widget reads the pref reactively via per-instance
Glance state, mirroring the range/past-event settings.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A reminder fired ahead of an event on a different day showed only the
event's time (e.g. "09:30 – 10:00"), making it look like it was
happening today. reminderTimeText now prefixes timed events with a
relative day: "Tomorrow"/"Yesterday", the short weekday for another day
this week, or the exact date for anything further out.
The this-week boundary honours the user's "week starts on" setting: the
resolved first day of week is threaded through from ReminderNotifier, so
e.g. a Sunday reads as next week under a Sunday-start locale. All-day
events keep their explicit date (never ambiguous), and cross-midnight
timed events keep both explicit dates.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Split the two prefill paths that share openImported(): an ACTION_INSERT
intent still auto-applies the settings default (it carries no reminder
semantics), but a .ics file — which owns its reminders — no longer silently
decides. It keeps the file's reminders and raises a one-time prompt
("This event was imported with N reminder(s) — apply your default?") so the
user chooses. The prompt is skipped when there's no real choice: no default
configured, or the file already carries exactly it.
openImported() now takes an ImportSource; CalendarHost tags the overlay
Insert vs File. Accepting swaps in the default and reveals the section;
declining (or dismissing) keeps the file's own reminders.
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>
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>
- 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>
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>
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>
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>
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>
The source key was removed on this branch; the Weblate translations
merged from main still carried it, tripping check_translations.py and
fatal ExtraTranslation lint.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Community translations for es and it reached ~85% coverage (Weblate
PR #52 into main). Adding their locale entries makes them selectable in
the in-app picker and Android 13+ per-app language settings once that
PR is merged.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Weblate owns all translation files including values-de; devs only touch
the English base. Reverts the hand-added special-dates strings and the
permission_rationale_body rewording to main's version (texts recoverable
from 1ff4115, to be re-added through the Weblate API). Keeps the removal
of the stale reminder_custom_with_value key, whose source string was
deleted on this branch (ExtraTranslation is fatal).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
German translations must flow through Weblate; strings committed from
code conflict with Weblate's repo state on its next merge. The nine
font-picker strings from the custom-fonts feature fall back to English
until translated in Weblate (MissingTranslation is informational).
The stale-key removal (reminder_custom_with_value) stays: ExtraTranslation
is a fatal lint error, so deletions of retired source strings must
accompany the code change.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>