From b49a8af83de16594b29542916a247fac0bdc42ed Mon Sep 17 00:00:00 2001 From: Jean-Luc Makiola Date: Mon, 21 Sep 2026 13:37:49 +0200 Subject: [PATCH] chore: clear out what the own-store branch left behind, and refresh deps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Dead weight, found by reading `lintDebug` rather than by anything breaking. Gone with the deleted `:provider` module: its entire dependency block in the version catalog — jems, rfc5545-datetime, Robolectric, JUnit 4, Hamcrest, Mockito — plus the comments explaining a `provider/PROVENANCE.md` that is not there any more. Only lib-recur survived the deletion and it is now documented where it lives. That block was also the source of most of the catalog's "newer version available" noise. Gone outright: `glance-appwidget` and `glance-material3`, declared but not referenced by a single line, so they were shipping in the APK for nothing. The WorkManager `ListenableWorker` keep rule went with them, since Glance was what dragged WorkManager in; the RoomDatabase keep rule stays and its comment now says why it matters *more* than it did — Room used to arrive transitively through that chain, and is now our own task store. Also gone: thirteen unused resources (twelve strings and a colour), which volunteers on Weblate were translating for nothing; a `SDK_INT < O` branch that cannot be false at minSdk 29; and the `-v26` qualifier on the mipmap folder, unnecessary at the same minSdk. `DemoSeeder` is injected as a `Provider` now. Its call site is `BuildConfig.DEBUG`-gated, i.e. compile-time dead in a release build, but injecting the instance still constructed one on every launch of the shipped app. `ProviderChangeReceiver` gets one intent-filter per authority rather than two `` tags in one filter. Identical behaviour — Android takes the cross product of every data attribute in a filter — but it no longer reads as if it might not, which is what lint's IntentFilterUniqueDataAttributes warns about. Dependency refresh, app-level only: KSP 2.3.11, Hilt 2.60.1, lifecycle 2.11.0, material3 1.5.0-alpha26, JUnit 6.1.3, hilt-navigation-compose 1.4.0. That last one moved `hiltViewModel` into `androidx.hilt.lifecycle.viewmodel.compose`, so nine call sites follow it and the artifact it now lives in is declared rather than inherited. The floret-kit coordinates move into the catalog, version-less, since the composite build substitutes them. Deliberately not touched: AGP, Gradle, Kotlin, the Compose BOM and kotlinx-* — toolchain moves that want their own change and a reproducible-build check, not a release cut. lib-recur stays pinned at 0.12.2 (0.16.0 removed `RecurrenceSet`). --- app/build.gradle.kts | 20 +++--- app/proguard-rules.pro | 14 ++-- app/src/main/AndroidManifest.xml | 14 +++- .../jeanlucmakiola/agendula/MainActivity.kt | 10 ++- .../agendula/data/reminders/TaskNotifier.kt | 1 - .../agendula/data/tasks/TasksContract.kt | 15 +++-- .../jeanlucmakiola/agendula/ui/RootScreen.kt | 2 +- .../agendula/ui/detail/TaskDetailScreen.kt | 2 +- .../agendula/ui/edit/TaskEditScreen.kt | 2 +- .../agendula/ui/export/ExportScreen.kt | 2 +- .../agendula/ui/lists/ListsScreen.kt | 2 +- .../agendula/ui/navigation/AgendulaNavHost.kt | 2 +- .../agendula/ui/settings/SettingsScreen.kt | 2 +- .../agendula/ui/tasklist/TaskListScreen.kt | 4 +- .../ic_launcher.xml | 0 .../ic_launcher_round.xml | 0 app/src/main/res/values-de/strings.xml | 11 ---- app/src/main/res/values-pt-rBR/strings.xml | 12 ---- app/src/main/res/values/colors.xml | 1 - app/src/main/res/values/strings.xml | 12 ---- gradle/libs.versions.toml | 65 ++++++++----------- 21 files changed, 75 insertions(+), 118 deletions(-) rename app/src/main/res/{mipmap-anydpi-v26 => mipmap-anydpi}/ic_launcher.xml (100%) rename app/src/main/res/{mipmap-anydpi-v26 => mipmap-anydpi}/ic_launcher_round.xml (100%) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 1639fed..b167842 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -174,12 +174,11 @@ dependencies { implementation(libs.hilt.android) implementation(libs.androidx.hilt.navigation.compose) + implementation(libs.androidx.hilt.lifecycle.viewmodel.compose) implementation(libs.androidx.navigation.compose) ksp(libs.hilt.compiler) - // RFC 5545 recurrence expansion, in-process. Pinned at 0.12.2 — 0.16.0 - // removed RecurrenceSet. rfc5545-datetime comes with it and is part of its - // API surface, so it isn't declared separately. + // RFC 5545 recurrence expansion, in-process; see the catalog for the pin. implementation(libs.dmfs.lib.recur) implementation(libs.androidx.room.runtime) @@ -189,17 +188,14 @@ dependencies { implementation(libs.androidx.datastore.preferences) implementation(libs.androidx.documentfile) - implementation(libs.androidx.glance.appwidget) - implementation(libs.androidx.glance.material3) - implementation(libs.kotlinx.datetime) implementation(libs.kotlinx.coroutines.core) - implementation("de.jeanlucmakiola.floret:core-time") - implementation("de.jeanlucmakiola.floret:core-reminders") - implementation("de.jeanlucmakiola.floret:core-locale") - implementation("de.jeanlucmakiola.floret:core-crash") - implementation("de.jeanlucmakiola.floret:identity") - implementation("de.jeanlucmakiola.floret:components") + implementation(libs.floret.core.time) + implementation(libs.floret.core.reminders) + implementation(libs.floret.core.locale) + implementation(libs.floret.core.crash) + implementation(libs.floret.identity) + implementation(libs.floret.components) debugImplementation(libs.androidx.ui.tooling) debugImplementation(libs.androidx.ui.test.manifest) diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index d4314e3..4b96679 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -5,17 +5,11 @@ # Room instantiates its generated _Impl reflectively through a no-arg # constructor. R8 under AGP 9 keeps the class but prunes that constructor, since # nothing calls it directly — Room then throws InstantiationException, reported -# as "Failed to create an instance of ...". We pull Room in transitively via -# Glance -> WorkManager, whose WorkDatabase is built by WorkManagerInitializer -# at startup, so the app died on launch in every minified build (issue #1). +# as "Failed to create an instance of ...". This first bit us through a +# transitive Room (Glance -> WorkManager -> WorkDatabase, built at startup: +# issue #1); Glance is gone and Room is now our own task store, so the rule +# matters more, not less — TasksDatabase is built on the first store read. -keep class * extends androidx.room.RoomDatabase { (); } -# WorkManager likewise looks its workers up by name and calls this constructor -# reflectively — same pruning, but it only bites once a worker actually runs -# (Glance's widget updates), so keep it explicitly rather than wait for it. --keep class * extends androidx.work.ListenableWorker { - (android.content.Context, androidx.work.WorkerParameters); -} - # Compose Compiler may keep its own; defaults are fine -dontwarn org.jetbrains.annotations.** diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a50a376..8d39dc2 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -83,16 +83,24 @@ + InvalidationTracker covers our own writes. + + An intent-filter host must be a literal, so both external authorities + are listed — one filter each. Two tags in a single filter would + mean the same thing (Android takes the cross product of every data + attribute in a filter), but reads as if it might not, which is what + lint's IntentFilterUniqueDataAttributes warns about. --> - + + + + - #FF7A5C6B #FF7A5C6B diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 178c689..dfc935a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,6 +1,5 @@ Agendula - A modern Material 3 Expressive task app.\nComing into bloom. Untitled task @@ -21,9 +20,6 @@ Edit - Edit task - New task - Title Description Could not save. Try again. @@ -52,11 +48,8 @@ High - Mark complete - Mark not complete List Due - Starts Priority Progress Subtasks @@ -152,7 +145,6 @@ Overdue Upcoming All - %1$d open %1$d of %2$d done @@ -168,7 +160,6 @@ Search tasks Clear search - Close search No tasks match “%1$s” @@ -182,8 +173,6 @@ Allow access to your tasks Agendula needs permission to read and write your tasks. That\'s the only thing it ever asks for. Grant task access - Install OpenTasks - Install tasks.org Never miss what\'s due @@ -238,7 +227,6 @@ Exact timing Reminders fire at the exact time Blocked — tap to allow exact reminders - Tasks Default list First available list Show \"add a subtask\" row diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index c57fbae..9dd1c71 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,53 +1,42 @@ [versions] agp = "9.2.1" kotlin = "2.3.21" -ksp = "2.3.9" -hilt = "2.59.2" +ksp = "2.3.11" +hilt = "2.60.1" coreKtx = "1.19.0" appcompat = "1.7.1" -lifecycleRuntime = "2.10.0" +lifecycleRuntime = "2.11.0" activityCompose = "1.13.0" composeBom = "2026.05.01" # Material 3 Expressive APIs currently live only in the 1.5 alpha line. # Pin explicitly to override the BOM (which ships stable 1.4.0). # Re-evaluate when 1.5.0 stable lands. -material3 = "1.5.0-alpha21" +material3 = "1.5.0-alpha26" datastore = "1.2.1" # Room — Agendula's own task store (docs/OWN-STORE.md). room = "2.8.4" kotlinxSerialization = "1.8.1" # SAF directory writing for export/backup (DocumentFile). documentfile = "1.1.0" -junit = "6.1.0" -junitPlatform = "6.1.0" +junit = "6.1.3" +junitPlatform = "6.1.3" truth = "1.4.5" androidxJunit = "1.3.0" espressoCore = "3.7.0" kotlinxDatetime = "0.7.0" kotlinxCoroutines = "1.10.2" turbine = "1.2.0" -hiltNavigationCompose = "1.3.0" +hiltNavigationCompose = "1.4.0" navigationCompose = "2.9.0" -lifecycleCompose = "2.10.0" +lifecycleCompose = "2.11.0" androidxTestRules = "1.7.0" -# Glance: 1.1.1 is the latest stable (1.2.0 is still rc, 1.3.0 alpha). -glance = "1.1.1" -# --- :provider (vendored dmfs task provider) --------------------------------- -# Versions the upstream 1.4.2 source was written against. These are its runtime -# dependencies, not ours — nothing above the data layer touches them, and they -# only move when we deliberately resync the fork. See provider/PROVENANCE.md. -dmfsJems = "1.43" -dmfsRfc5545Datetime = "0.2.4" +# RFC 5545 recurrence expansion. The last of the dmfs dependencies: the vendored +# `:provider` module that needed the rest was deleted (docs/STORAGE-DECISION.md), +# and lib-recur stayed because our own store expands a series in process. +# Pinned at 0.12.2 — 0.16.0 removed RecurrenceSet. rfc5545-datetime arrives with +# it as part of its API surface, so it is not declared separately. dmfsLibRecur = "0.12.2" -# The provider's own test suite is JUnit 4 + Robolectric, unlike the app's -# JUnit 5. Kept as upstream wrote it (rewriting ~13 test classes would forfeit -# the regression coverage that makes vendoring safe), but on current versions: -# upstream pins Robolectric 3.5.1, which predates AGP's resource handling. -robolectric = "4.16" -junit4 = "4.13.2" -hamcrest = "3.0" -mockito = "5.20.0" [libraries] # AndroidX core @@ -107,8 +96,11 @@ kotlinx-coroutines-test = { group = "org.jetbrains.kotlinx", name = "kotlinx-cor # Test - Flow assertions turbine = { group = "app.cash.turbine", name = "turbine", version.ref = "turbine" } -# Hilt navigation-compose (for hiltViewModel() in Composables) +# Hilt navigation-compose (hiltViewModel() moved out of it in 1.4.0, into +# hilt-lifecycle-viewmodel-compose — which it still brings in transitively, but +# we call that API directly, so it is declared here rather than inherited) androidx-hilt-navigation-compose = { group = "androidx.hilt", name = "hilt-navigation-compose", version.ref = "hiltNavigationCompose" } +androidx-hilt-lifecycle-viewmodel-compose = { group = "androidx.hilt", name = "hilt-lifecycle-viewmodel-compose", version.ref = "hiltNavigationCompose" } # Navigation-compose (the NavHost / back stack) androidx-navigation-compose = { group = "androidx.navigation", name = "navigation-compose", version.ref = "navigationCompose" } @@ -118,22 +110,21 @@ androidx-lifecycle-runtime-compose = { group = "androidx.lifecycle", name = "lif # ProcessLifecycleOwner — the WAL checkpoint hangs off ON_STOP. androidx-lifecycle-process = { group = "androidx.lifecycle", name = "lifecycle-process", version.ref = "lifecycleRuntime" } -# Glance — Jetpack home-screen widgets (Compose-like RemoteViews) -androidx-glance-appwidget = { group = "androidx.glance", name = "glance-appwidget", version.ref = "glance" } -androidx-glance-material3 = { group = "androidx.glance", name = "glance-material3", version.ref = "glance" } - # Android tests - GrantPermissionRule androidx-test-rules = { group = "androidx.test", name = "rules", version.ref = "androidxTestRules" } -# :provider — vendored dmfs task provider (see provider/PROVENANCE.md) -dmfs-jems = { group = "org.dmfs", name = "jems", version.ref = "dmfsJems" } -dmfs-jems-testing = { group = "org.dmfs", name = "jems-testing", version.ref = "dmfsJems" } -dmfs-rfc5545-datetime = { group = "org.dmfs", name = "rfc5545-datetime", version.ref = "dmfsRfc5545Datetime" } +# Recurrence expansion for our own store dmfs-lib-recur = { group = "org.dmfs", name = "lib-recur", version.ref = "dmfsLibRecur" } -robolectric = { group = "org.robolectric", name = "robolectric", version.ref = "robolectric" } -junit4 = { group = "junit", name = "junit", version.ref = "junit4" } -hamcrest = { group = "org.hamcrest", name = "hamcrest", version.ref = "hamcrest" } -mockito-core = { group = "org.mockito", name = "mockito-core", version.ref = "mockito" } + +# floret-kit — the shared house library, an included build (see settings.gradle.kts). +# Deliberately version-less: the composite build substitutes these coordinates +# with the submodule's own projects, so a version here would be fiction. +floret-core-time = { group = "de.jeanlucmakiola.floret", name = "core-time" } +floret-core-reminders = { group = "de.jeanlucmakiola.floret", name = "core-reminders" } +floret-core-locale = { group = "de.jeanlucmakiola.floret", name = "core-locale" } +floret-core-crash = { group = "de.jeanlucmakiola.floret", name = "core-crash" } +floret-identity = { group = "de.jeanlucmakiola.floret", name = "identity" } +floret-components = { group = "de.jeanlucmakiola.floret", name = "components" } [plugins] android-application = { id = "com.android.application", version.ref = "agp" }