Both functions lived in Calendula's ui/common/LocaleSupport.kt. Neither is
calendar-specific — "lay this date out the way this language writes dates" is
family plumbing — so they move here, where Agendula can reach them too.
localizedDateFormatter(locale, skeleton) takes a field list ("LLLLy", "dMMMy")
and lets the locale arrange it, which is the only way to render a date correctly
in a language you didn't hand-write a template for. Dropping a field from the
skeleton drops it from the output, so callers ask for "no year" by omitting it
rather than post-processing a longer pattern.
currentLocale() reads the display locale from LocalConfiguration. This module's
own AppLanguage.apply() changes the language inside a running process, so a
locale captured once goes stale; keying on the configuration makes the UI follow
the switch.
core-locale gains Compose (runtime + ui only) for currentLocale(). Its build file
previously declared itself Compose-free, but the alternative — parking the hook
in a Compose module that depends back on this one — splits one concern across two
modules to honour a comment. core-crash is the precedent for a core-* module
carrying Compose.
Leaves core-time's Instant.formatDate() family alone despite the overlap: it is
unused by Calendula but visible to Agendula, so reconciling it is that app's
call, not a drive-by here. Noted in the changelog.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
114 lines
6.5 KiB
Markdown
114 lines
6.5 KiB
Markdown
# Changelog
|
|
|
|
All notable changes to floret-kit are documented here. The format follows
|
|
[Keep a Changelog](https://keepachangelog.com/).
|
|
|
|
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.1.0`). Entries are grouped by module.
|
|
|
|
## [Unreleased]
|
|
|
|
### Added
|
|
|
|
- **`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)` — a `DateTimeFormatter` for 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 from `LocalConfiguration`.
|
|
Since `AppLanguage.apply()` changes the language inside a running process, a
|
|
locale captured once goes stale; this keys recomposition to the change.
|
|
|
|
### Changed
|
|
|
|
- **`core-locale`** now carries Compose (runtime + ui only) for `currentLocale()`.
|
|
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-crash` is
|
|
the precedent for a `core-*` module carrying Compose.
|
|
|
|
### Known gaps
|
|
|
|
- `core-time`'s `Instant.formatDate()` family now overlaps `core-locale`. Its
|
|
private `dateNoYearFormatter` strips the year by regex-ing the pattern string,
|
|
which `localizedDateFormatter(locale, "dMMM")` does properly; and its
|
|
formatters resolve `Locale.getDefault()` once at class-init ("locale changes
|
|
within a running process are rare enough to ignore"), which `AppLanguage.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-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 over `kotlin.time.Instant`.
|
|
- `TimeBridge` — `Long` epoch-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 a `CrashConfig` supplied at `install()`; each app keeps its
|
|
own thin themed `CrashReportActivity`.
|
|
- **`identity`** (Android library) — the family's Material 3 Expressive theme
|
|
factory `FloretExpressiveTheme(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()` and `Modifier.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; set
|
|
`largeTopBar = false` for 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). `FullScreenPicker` takes an optional
|
|
`actions` slot (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 with `GroupedRow(gapBelow = false)`, which
|
|
hands the column uniform control of row spacing.
|
|
- `DebugRibbon` — a stark, un-themed "DEBUG" corner ribbon; gate on
|
|
`BuildConfig.DEBUG` at the call site.
|
|
- `InlineTextField` gained `enabled` (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`), where `Minutes` carries 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`) plus `ReminderOverrideCodec`
|
|
(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 `foojay` toolchain resolver** anywhere — it can fetch a JDK at build time,
|
|
which reproducible / official F-Droid builds reject. Modules set `jvmTarget`
|
|
directly. See [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md).
|
|
- AGP 9.x provides built-in Kotlin compilation, so Android modules apply only the
|
|
Android library + Compose plugins (no separate `kotlin.android`).
|