Files
agendula/CLAUDE.md

6.5 KiB
Raw Blame History

Build host (ARM64)

The primary dev machine is ARM64 (aarch64) Linux, and Google ships no linux-aarch64 aapt/aapt2 — both run under box64 via wrappers that live outside the repo (~/.gradle/box64-aapt2/aapt2 behind android.aapt2FromMavenOverride, and an aapt wrapper installed straight into ~/Android/Sdk/build-tools/*/ because AGP's test-APK installer hardcodes that path). Nothing in the project tree depends on this; x86-64 machines and CI are unaffected.

The trap: without the aapt wrapper, connectedDebugAndroidTest exits non-zero even when every test passes — teardown fails, and Gradle reports it as "There were failing tests". If that shows up, read app/build/outputs/androidTest-results/connected/debug/*.xml for the real result before believing the exit code.

On-device work (USB-connected phone)

A physical phone is connected over USB. Rules:

  • Install when asked — if the user says to install/deploy on device, do it (build + adb install). That's the one action you may take on your own.
  • Do nothing else on the device unprompted. Do not launch the app, take screenshots, dump/read logcat, poke UI, or otherwise "test" or verify on the device on your own initiative — even to confirm a change works.
  • Read logs, capture screenshots, and inspect on-device behaviour only when the user explicitly asks for it, each time. The user drives when it's time to look; wait for that instruction.

UI / design conventions

  • Material 3 Expressive throughout. Consult the material-3 skill before designing anything new; prefer M3 tokens/components over hardcoded colours.
  • Selection pickers are full-screen — browse-style "choose one" surfaces (visibility, reminder, recurrence rule, colour, calendar, add-field, plus the Settings pickers) use floret-kit's FullScreenPicker / OptionPicker (a full-bleed sheet with a pinned title bar and connected grouped rows); a picker that needs a commit/extra action passes it via the picker's actions slot. The exception is the recurring scope choosers — the "this / this & following / all" prompts shown when you save an edit to, drag or delete a recurring event — which stay compact OptionCard-in-AlertDialog popups (a quick 23 option decision reads better as a popup than a near-empty full screen). AlertDialog is otherwise only for plain confirmations. Radio/text-list dialogs are banned.

Releases

The committed versionCode / versionName in app/build.gradle.kts are the release trigger: merging a bumped versionName into main runs .gitea/workflows/release.yaml, which builds, signs, publishes to the self-hosted F-Droid repo, then mints the vX.Y.Z tag + release. versionCode is pinned to MAJOR*10000 + MINOR*100 + PATCH (e.g. 2.13.0 → 21300). Full process in docs/RELEASING.md. Never tag/release UI changes before on-device review and explicit go-ahead.

Release builds are kept F-Droid reproduciblevcsInfo, dependenciesInfo, and the AGP metadata block are deliberately disabled in build.gradle.kts; don't re-enable them. Use the releaseTest build type (R8-shrunk twin, debug-signed, own applicationId suffix) to smoke-test a release candidate on-device.

Per-version changelogs are written by hand, in every locale

fastlane/metadata/android/<locale>/changelogs/<versionCode>.txt is the "What's New" both F-Droid and Play publish. There is no auto-translation layer — Weblate owns values-*/strings.xml only, not the fastlane tree — so when cutting a release you write these files yourself, one per locale, each a short summary under 500 characters (Play's hard cap, applied per locale; F-Droid truncates in-client).

Write one for every language the app ships (app/src/main/res/values-*), using store locale codes: en-US, en-GB, de-DE, es-ES, fr-FR, it-IT, pl-PL, pt-PT, ru-RU, zh-CN, ar. Missing locales aren't fatal — both stores fall back — but see the en-GB trap below.

en-GB is the Play Console's default language. Play's fallback is the default locale, not en-US, so a release with only an en-US changelog ships with no "What's New" at all — this is why the latest release had none. en-GB must exist.

The rest of the plumbing is already locale-agnostic: sync_changelog_to_fastlane.sh seeds en-US only and never overwrites a committed file, while fastlane_to_fdroid_localized.sh and supply pick up every locale that has a changelogs/ dir. So the files are the whole job.

Forge / tea CLI

Codeberg is canonical (codeberg.org/jlmakiola/calendula) for git, issues, PRs, tags and releases — including the floret-kit submodule. The self-hosted Gitea instance is build infrastructure only: signing key, F-Droid publishing, release pipeline.

Use the tea CLI for forge interaction — not raw API calls. Note the flag is a subcommand flag, not global: tea pulls list --login codeberg, never tea --login codeberg pulls list. Two accounts, neither default:

  • Everything → codeberg (user jlmakiola). PRs, issues, releases, repo settings. tea pulls create --login codeberg ...
  • Build infra only → jeanluc (gitea.jeanlucmakiola.de, user makiolaj). Release-pipeline runs, Actions secrets. tea ... --login jeanluc

Workflows are split by directory and this is load-bearing — Forgejo's lookup is first-match-wins across .forgejo/.gitea/.github/:

  • .forgejo/workflows/ runs on Codeberg (ci.yaml, translations.yaml) and must reference no secrets — that's what makes fork PRs safe.
  • .gitea/workflows/ runs on Gitea (release.yaml, renovate.yml) and is where every secret lives.

Don't add a workflow without deciding which side it belongs on.

Translations

Community translations are managed on a self-hosted Weblate, which owns all values-* files (including German — API only, never hand-edit). Partial translations are expected (MissingTranslation is informational, not fatal); extra/stale keys stay fatal.

Git Operations

Use a commit format which references the issues, dont add any Co-Authered by Claude lines, and don't write extensive commit and merge messages, simple human ones suffice, for prs, stuff like testing etc, isnt interesting write what has chnaged, and if deviated from the underling issues pls explain why, add a closes issue line at the end of all prs.

Comments

Don't add extensive code comments, methode discription, so as a Java Doc is fine, but no extensive explanbanitory conmments