Adds components' `scrollable` opt-out on CollapsingScaffold (and its FullScreenPicker passthrough), so a picker with more options than an eagerly composed column can carry can drive its own LazyColumn. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
7.8 KiB
Changelog
All notable changes to floret-kit are documented here. The format follows Keep a Changelog.
floret-kit is consumed from source — each app embeds it as a git submodule
and builds it through a Gradle composite build, pinning a specific commit. There
are no binary releases; "version" tracks the shared version in the root build
(currently 0.2.1). Entries are grouped by module.
[Unreleased]
[0.2.1] - 2026-07-17
Added
components—CollapsingScaffoldtakes ascrollableflag (defaulttrue, so every existing caller is unchanged). Set it tofalsewhen the content brings its own scrolling container: the scaffold's ownverticalScrollcomposes each row up front and can't host aLazyColumn(nesting a same-axis scrollable throws), which ruled out any surface with more options than fit an eager pass. Opting out hands the content a plain column and leaves the insets, IME padding and top-bar collapse as they were.FullScreenPickerforwards the flag. Consumed by Calendula's ~600-entry time-zone picker from 2.16.0.
[0.2.0] - 2026-07-17
Added
components—CustomAmountEditor, the amount + unit editor behind an "Custom…" picker option (Calendula's custom snooze duration). Consumed by Calendula since 2.15.0.core-locale— the locale-aware formatting half of the module, so apps stop hand-rolling"$day. $month $year"templates that bake one language's field order (and its separators, and its ordinal dot) into every language they ship:localizedDateFormatter(locale, skeleton)— aDateTimeFormatterfor a field skeleton ("LLLLy", "dMMMy", "EEEdMMM") laid out in the locale's own order, via Android's best-pattern matching. Drop a field from the skeleton to drop it from the output — the locale still supplies the arrangement.currentLocale()— the display locale, observed fromLocalConfiguration. SinceAppLanguage.apply()changes the language inside a running process, a locale captured once goes stale; this keys recomposition to the change.
Changed
core-localenow carries Compose (runtime + ui only) forcurrentLocale(). The module previously declared itself Compose-free; applying a language mid-process is its own API, so the hook that makes the UI notice belongs beside it rather than in a Compose module depending back on this one.core-crashis the precedent for acore-*module carrying Compose.
Known gaps
core-time'sInstant.formatDate()family now overlapscore-locale. Its privatedateNoYearFormatterstrips the year by regex-ing the pattern string, whichlocalizedDateFormatter(locale, "dMMM")does properly; and its formatters resolveLocale.getDefault()once at class-init ("locale changes within a running process are rare enough to ignore"), whichAppLanguage.apply()makes untrue. Left alone for now — it is unused by Calendula but Agendula-visible. Reconcile when Agendula next re-pins.
[0.1.0] - 2026-07-07
Added
-
core-locale(Android library) — per-app language plumbing (AppLanguage): read the shipped languages from the app'sres/xml/locales_config.xml, get/set the applied language viaAppCompatDelegate, render each language's autonym. The app passes its ownlocales_configresource id; the system-default choice isnull. (Shipped in 0.1.0 but omitted from this changelog at the time; recorded here retroactively.) -
core-time(JVM library) — pure-Kotlin date/time helpers, no Android and no third-party dependencies:DayWindow.today()— local-day boundaries for smart-list logic.Instant.formatDate()/formatTime()/formatDateTime()— locale- and zone-aware display formatting overkotlin.time.Instant.TimeBridge—Longepoch-millis ↔Instant, for content-provider I/O.LocalDate.isoWeekNumber()— ISO-8601 week-of-week-based-year, the calendar-week number for week/month grids (one scheme, shared).
-
core-crash(Android library) — privacy-respecting, on-device crash capture and reporting. Writes an allowlist-only report (app/Android/device version, locale, time, stack trace — nothing else) to private storage and chains to the platform handler; uploads nothing. Includes startup crash-loop detection, a report dialog that shows the full text before it leaves the device, and an issue-tracker hand-off. Per-app specifics (display name, issue URLs) come from aCrashConfigsupplied atinstall(); each app keeps its own thin themedCrashReportActivity. -
identity(Android library) — the family's Material 3 Expressive theme factoryFloretExpressiveTheme(lightScheme, darkScheme, …)(dynamic colour on API 31+, system light/dark fallback, the standard motion scheme) plus the shared motion helpers —rememberNavSlideSpec(), the content transitions,Modifier.predictiveBack()andModifier.animateContentSizeMotion()(eases a block's own height changes, e.g. a text field wrapping to a new line), each reduced-motion-aware. Each app passes its own seed-derived colour schemes and typography — the mechanics are shared, the look is not. -
components(Android library) — the shared Compose component vocabulary:GroupedSurface/GroupedRow+Position/positionOf— the canonical press-morphing tonal grouped-row primitive (the Android-15 settings pattern).InlineTextField— the borderless tonal text input (capitalization is a parameter).OptionCard— the sanctioned selection-dialog pick.CollapsingScaffold— the collapsing settings/sub-screen scaffold; setlargeTopBar = falsefor a pinned single-line bar (the picker variant).FullScreenPicker/OptionPicker— the full-screen single-select picker, now over a pinned single-line bar (a picker is a short list, so no tall collapsing header to scroll past).FullScreenPickertakes an optionalactionsslot (app-bar trailing items) for pickers that carry a commit or extra action — a custom-value Add/OK, a Reset.ReorderableColumn— dependency-free drag-to-reorder for the short, fixed grouped-card Settings lists; pairs withGroupedRow(gapBelow = false), which hands the column uniform control of row spacing.DebugRibbon— a stark, un-themed "DEBUG" corner ribbon; gate onBuildConfig.DEBUGat the call site.InlineTextFieldgainedenabled(a disabled field dims to a locked value).pastelize()— softens a raw provider colour to a theme-fitting pastel.
App-agnostic by design: apps compose their own screens and keep their own identity chips/icons. String resources here (e.g.
back) are fallbacks an app can override. -
core-reminders(JVM library) — the app-agnostic reminder-override model:ReminderOverride(Inherit/None/Minutes), whereMinutescarries a list of lead-times so a target can hold several reminders at once (an app that offers a single reminder just uses a one-element list). Map helpers (reminderOverrideFor,reminderLeadsFor,applyReminderOverride,reminderOverrideForMinutes,normalizeReminders) plusReminderOverrideCodec(three configurable separators; single legacy values round-trip byte-identically) and the lead-time unit model (ReminderUnit,decomposeReminderMinutes). The labels/presets and the alarm scheduler stay per-app.
Conventions
- No
foojaytoolchain resolver anywhere — it can fetch a JDK at build time, which reproducible / official F-Droid builds reject. Modules setjvmTargetdirectly. Seedocs/ARCHITECTURE.md. - AGP 9.x provides built-in Kotlin compilation, so Android modules apply only the
Android library + Compose plugins (no separate
kotlin.android).