4 Commits

Author SHA1 Message Date
cfa25b9730 release: cut 0.3.1 — fix the launch crash in minified builds (#1)
All checks were successful
Release — F-Droid repo + Gitea/Codeberg release / detect (push) Successful in 7s
Release — F-Droid repo + Gitea/Codeberg release / release (push) Successful in 11m31s
2026-07-20 18:36:47 +02:00
9d7fc64b0b release: cut 0.3.1 — fix the launch crash in minified builds
R8 kept androidx.work.impl.WorkDatabase_Impl but pruned its no-arg
constructor: nothing calls it directly, Room only reaches it reflectively.
Room then threw InstantiationException, surfacing as "Failed to create an
instance of androidx.work.impl.WorkDatabase". WorkManager builds that
database from a startup ContentProvider, so 0.3.0 died before any of our
code ran — every install, every launch.

We don't depend on WorkManager directly; it arrives via Glance. AGP 9's
stricter R8 is what tipped this over, which is why 0.3.0 was the first
release to hit it.

Keep the Room no-arg constructor, and the ListenableWorker constructor
alongside it — same pruning hazard on the path WorkManager uses to
instantiate workers by name, which would have bitten once a Glance widget
update actually ran.

Reproduced the reporter's stack trace frame-for-frame on a releaseTest
build, then confirmed it launches clean afterwards. Fixes #1.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-20 18:35:41 +02:00
4aa65edb45 ci(release): push tag to Codeberg before creating the release
All checks were successful
Release — F-Droid repo + Gitea/Codeberg release / detect (push) Successful in 6s
Release — F-Droid repo + Gitea/Codeberg release / release (push) Has been skipped
The first fix didn't help: the pipeline creates the tag via the Gitea
API, and the push mirror (sync_on_commit only fires on real git pushes)
doesn't propagate an API-created tag promptly. So the Codeberg release
POST still raced the mirror and 500'd on a commit/tag Codeberg hadn't
received (0.2.1 and 0.3.0 both shipped everywhere but Codeberg).

Push the tag straight to Codeberg from the runner (guaranteed present),
then attach the release to that existing tag with no target_commitish —
which is what Forgejo 500s on. Race-free.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-19 22:48:29 +02:00
a9843e25b7 release: cut 0.3.0
All checks were successful
Release — F-Droid repo + Gitea/Codeberg release / detect (push) Successful in 7s
Release — F-Droid repo + Gitea/Codeberg release / release (push) Successful in 12m27s
Ships the M5 reminders onboarding + Settings screen alongside the reworked
overview (Today progress ring, live Upcoming preview, unfurling search) and
the real launcher mark.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-19 22:25:14 +02:00
6 changed files with 71 additions and 32 deletions

View File

@@ -399,27 +399,27 @@ jobs:
sed -i -e '/./,$!d' release-notes.md
fi
[ -s release-notes.md ] || echo "_See CHANGELOG.md for ${VERSION}._" > release-notes.md
# The push mirror (sync_on_commit) usually syncs the tag to Codeberg
# before this step runs. Forgejo 500s on POST /releases with a
# target_commitish when the tag already exists — so only pass
# target_commitish when we actually need the API to create the tag.
TAG_CODE=$(curl -s -o /dev/null -w '%{http_code}' \
-H "Authorization: token $TOKEN" "$API/git/refs/tags/$TAG")
python3 - "$TAG" "$SHA" "$PRERELEASE" "$TAG_CODE" <<'PY' > cb-payload.json
# The pipeline creates the tag via the Gitea API, which the push mirror
# (sync_on_commit only fires on real git pushes) doesn't propagate
# promptly — so a release POST that carries a target_commitish can
# outrun the mirror and 500 on a commit/tag Codeberg hasn't received.
# Push the tag straight to Codeberg so it's guaranteed present, then
# attach the release to that existing tag with NO target_commitish
# (which is what triggered the 500).
git tag -f "$TAG" "$SHA"
git push -f "https://jlmakiola:${TOKEN}@codeberg.org/jlmakiola/agendula.git" \
"refs/tags/$TAG"
python3 - "$TAG" "$PRERELEASE" <<'PY' > cb-payload.json
import json, sys
tag, sha, pre, tag_code = sys.argv[1:5]
payload = {
tag, pre = sys.argv[1:3]
print(json.dumps({
"tag_name": tag,
"name": tag,
"body": open("release-notes.md").read(),
"draft": False,
# Pre-1.0 releases are flagged as pre-releases (see detect job).
"prerelease": pre == "true",
}
# Only create the tag via the release when it isn't mirrored yet.
if tag_code != "200":
payload["target_commitish"] = sha
print(json.dumps(payload))
}))
PY
# Upsert (re-run safe).
ID=$(curl -s -H "Authorization: token $TOKEN" "$API/releases/tags/$TAG" | jq -r '.id // empty')

View File

@@ -7,23 +7,28 @@ All notable changes to this project are documented here. The format follows
## [Unreleased]
## [0.3.1] - 2026-07-20
### Fixed
- Agendula no longer crashes on launch. Every 0.3.0 install was affected: the
release build stripped a constructor that the background-work scheduler needs
to open its database, and that happens before the app draws anything.
## [0.3.0] - 2026-07-19
### Added
- M5 reminders onboarding & polish: a one-time reminder onboarding step after the
provider grant explains that Agendula delivers due reminders itself and requests
`POST_NOTIFICATIONS` (API 33+). A new **Settings** screen (gear on the lists
overview), structured after Calendula as a category hub with sliding sub-screens
(`CollapsingScaffold` + grouped category rows + full-screen `OptionPicker`):
an About card, **Appearance** (theme, dynamic colour), **Task form** (which
optional edit-form fields show by default, default list, the add-a-subtask-row
opt-out), and **Reminders** (a master enable switch that re-requests the
notification permission, a "when to remind" default offset, and — on Android 12
only — an exact-alarm status row that deep-links to system settings).
- The reminders master switch gates the whole engine: turning it off clears every
scheduled alarm and suppresses any that fire.
- Expressive top-bar actions: a reusable `ShapedActionButton` wraps an action icon
in a tonal M3 Expressive `MaterialShapes` container (the settings entry uses the
faceted Gem shape, tertiary tones), with a small press scale/rotate flourish.
Future top-bar actions pick their own shape from the `ActionShapes` registry.
- Reminders: Agendula now delivers your due reminders itself. A one-time setup
step explains this and asks for notification access, and a master switch in
Settings turns the whole thing off again.
- A Settings screen, from the gear on the overview: appearance and theme, which
fields the task form shows, your default list, and reminder defaults.
- The overview leads with Today — a progress ring showing how much of today
you've finished — followed by a live preview of what's coming up next.
- Search across every task, open or completed, from the top bar.
- A proper app icon.
### Changed
- A tidier top bar: no app title, with search and settings pinned to the right.
## [0.2.2] - 2026-07-19

View File

@@ -29,8 +29,8 @@ android {
// release itself (versionCode is pinned to MAJOR*10000 + MINOR*100 +
// PATCH from versionName, e.g. 0.2.0 -> 200). The Gitea release is marked
// as a pre-release while MAJOR is 0. See docs/RELEASING.md.
versionCode = 202
versionName = "0.2.2"
versionCode = 301
versionName = "0.3.1"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}

View File

@@ -2,5 +2,20 @@
-keep class dagger.hilt.** { *; }
-keep @dagger.hilt.android.HiltAndroidApp class *
# Room instantiates its generated <Database>_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).
-keep class * extends androidx.room.RoomDatabase { <init>(); }
# 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 {
<init>(android.content.Context, androidx.work.WorkerParameters);
}
# Compose Compiler may keep its own; defaults are fine
-dontwarn org.jetbrains.annotations.**

View File

@@ -0,0 +1,14 @@
### Added
- Reminders: Agendula now delivers your due reminders itself. A one-time setup
step explains this and asks for notification access, and a master switch in
Settings turns the whole thing off again.
- A Settings screen, from the gear on the overview: appearance and theme, which
fields the task form shows, your default list, and reminder defaults.
- The overview leads with Today — a progress ring showing how much of today
you've finished — followed by a live preview of what's coming up next.
- Search across every task, open or completed, from the top bar.
- A proper app icon.
### Changed
- A tidier top bar: no app title, with search and settings pinned to the right.

View File

@@ -0,0 +1,5 @@
### Fixed
- Agendula no longer crashes on launch. Every 0.3.0 install was affected: the
release build stripped a constructor that the background-work scheduler needs
to open its database, and that happens before the app draws anything.