makiolaj f1ded81c03 feat(identity): pure-black (AMOLED) dark theme
ColorScheme.toPureBlack() sets background, surface, surfaceDim and
surfaceContainerLowest to #000 and dims the other containers by scaling
their sRGB channels, so their hue tint carries over and grid tiles drawn
as containers over surface keep visible gaps. FloretExpressiveTheme takes
pureBlack to apply it to the dark scheme, dynamic or app-supplied.

core-prefs gains ThemeMode.BLACK (dark, pure black) and
ThemeMode.isPureBlack, stored under the same theme_mode key.
2026-10-14 17:19:31 +02:00

floret-kit

The shared Material 3 Expressive design system + plumbing for the Floret family of Android apps (Calendula, Agendula, Clockula, and future siblings).

"Floret" is the family's design language: a Calendula flower head is a cluster of many small florets, and each app is one of them. This repo is the bloom they share — so a new app doesn't reinvent a settings screen, an edit form, or a theme; it draws from here.

How it's consumed

Each app embeds this repo as a git submodule and wires it in with a Gradle composite build, so the kit is always built from source (no published artifacts — keeps every app reproducible for F-Droid):

// app's settings.gradle.kts
includeBuild("floret-kit")
// app module's build.gradle.kts
implementation("de.jeanlucmakiola.floret:core-time")

Gradle's dependency substitution maps de.jeanlucmakiola.floret:<module> to the local source module — edit the kit and the app picks it up immediately. Android modules need an SDK location for the included build: set ANDROID_HOME (CI) or add a gitignored <app>/floret-kit/local.properties with sdk.dir (locally). See docs/ARCHITECTURE.md for the full consumption model.

Modules

Module Type What it holds
core-time JVM Date/time helpers: DayWindow local-day windows, locale/zone-aware Instant formatting, TimeBridge (millis ↔ Instant). No Android, no deps.
core-reminders JVM Reminder-lead plumbing: the lead-time unit model (ReminderUnit, decomposeReminderMinutes), the per-target override model (ReminderOverride + reminderLeadFor / applyReminderOverride) and the stored-format codec (ReminderOverrideCodec, separators configurable per app). Each app layers its own DataStore + string labels on top.
core-locale Android Everything "what language are we in". Per-app language plumbing (AppLanguage): read the shipped languages from the app's res/xml/locales_config.xml, get/set the applied language via AppCompatDelegate, render each language's autonym. Plus currentLocale() (observes the applied language from Compose) and localizedDateFormatter(locale, skeleton) (lays a field skeleton out in the locale's own order). The app passes its own locales_config.
core-prefs Android The typed DataStore layer: Pref<T> + PrefStore (typed read/write, distinct-until-changed flows), toEnum() for values that degrade instead of throwing, and the family's shared appearance prefs (ThemeMode, dynamicColor). The store's name and construction stay with the app.
core-di JVM The shared DI vocabulary: @IoDispatcher, @DefaultDispatcher, @ApplicationScope and the Hilt module that provides them.
core-crash Android Privacy-respecting on-device crash capture + report dialog + issue-tracker hand-off. Parameterized per app via CrashConfig.
identity Android The M3 Expressive theme factory FloretExpressiveTheme(…), rememberNavSlideSpec(), the content transitions (expandEnter/collapseExit/itemEnter/…) and the predictiveBack peek. Each app supplies its own seed/palette.
components Android Shared Compose vocabulary + recipes: GroupedSurface/GroupedRow, InlineTextField, OptionCard, CollapsingScaffold, OptionPicker, ReorderableColumn, DebugRibbon, pastelize(), DialogControls, OnboardingScaffold, OptionalFormSection, AboutCard, LanguagePickerRow, SnackChip.
glance Android Home-screen-widget plumbing on Jetpack Glance: FloretGlanceTheme, the rounded WidgetSurface (solid/tinted/transparent backgrounds), WidgetHeader/WidgetActionButton, the position-aware WidgetGroupedRow, WidgetMessage, WidgetRollover (the midnight-rollover alarm) and FloretWidgetUpdateReceiver. App supplies its own colour schemes, data and receiver glue.

The principle: the mechanics are shared, the look stays per-app. See docs/ROADMAP.md for what's extracted, deferred, and deliberately not shared.

Docs

See docs/ — start with docs/README.md (ARCHITECTURE, ROADMAP) and CONTRIBUTING.md to add or change a module. CHANGELOG.md tracks what landed.

Build

./gradlew :core-time:test          # JVM module tests
./gradlew :core-crash:testDebugUnitTest
./gradlew :core-prefs:testDebugUnitTest
./gradlew :core-di:test
./gradlew build                    # everything (Android modules need an SDK; see above)
S
Description
Build infrastructure only — canonical repo: https://codeberg.org/jlmakiola/floret-kit
Readme MIT
497 KiB
Languages
Kotlin 100%