Commit graph

331 commits

Author SHA1 Message Date
facd72db16 ci(release): apksigner --alignment-preserved true (reproducibility, final layer)
All checks were successful
ci / analyze (push) Successful in 1m29s
ci / test-commons-core (push) Successful in 55s
ci / test-app-seeds (push) Successful in 9m51s
Even with the /home/vagrant path fix and v2/v3-only signing, the verify
still failed on a v3 CHUNKED_SHA512 mismatch with an EMPTY file diff. Cause
found by byte-level compare: apksigner (build-tools 35+) re-aligns native
libs to 16KB pages by default (--alignment-preserved defaults to false),
rewriting each .so's ZIP local-header extra field from gradle's 0x0 padding
to the 0xd935 alignment marker. F-Droid's reproducibility check compares
against the raw gradle output (0x0), so our re-aligned reference (0xd935)
differed in the signed bytes though every file was identical. Proven: 273
entries differed only in the extra field, 0 in compressed data. Signing
F-Droid's own unsigned build with --alignment-preserved true yields content
byte-identical to it (0 extra-field diffs, 0 data diffs). So preserve the
build's alignment when signing the reference.
2026-07-22 22:57:51 +02:00
6c9de115e9 ci(release): sign fdroid references v2/v3 only (no v1) for reproducibility
All checks were successful
ci / analyze (push) Successful in 1m14s
ci / test-commons-core (push) Successful in 45s
ci / test-app-seeds (push) Successful in 6m28s
The reproducible-build verify failed even after the /home/vagrant path fix
made every file identical: our reference APK carried a v1 (JAR) signature,
which adds META-INF/{MANIFEST.MF,*.SF,*.RSA} as three extra ZIP ENTRIES.
F-Droid's apksigcopier transplants only the v2/v3 signing block onto its
rebuild, so those 3 v1 entries make the reference's signed content differ
from F-Droid's build — apksigner then reports a v3 CHUNKED_SHA512 digest
mismatch though 'diff -r' shows no file differences. Proven by zipinfo: our
ref had 486 entries vs F-Droid's 483, the delta being exactly the v1 files;
the shared 483 are byte-identical. minSdk is 24 so v1 is never needed.
Sign v2/v3 only so the reference byte-matches F-Droid's rebuild.
2026-07-22 20:37:38 +02:00
8818576ee8 fix(android): declare INTERNET permission in the main manifest (release had none)
Some checks failed
ci / analyze (push) Successful in 1m25s
ci / test-commons-core (push) Successful in 50s
site / deploy (push) Successful in 30s
release / play (push) Successful in 36m40s
ci / test-app-seeds (push) Failing after 17m37s
release / fdroid_reference_armeabi_v7a (push) Successful in 24m4s
release / fdroid_reference_arm64_v8a (push) Successful in 25m5s
release / fdroid_reference_x86_64 (push) Successful in 25m14s
Flutter auto-adds android.permission.INTERNET only to the debug/profile
manifests, so every RELEASE build (Play + F-Droid) shipped with no network
permission at all — the whole social layer (market, messaging, trust, sync)
was dead on Android release, while desktop (no permission model) worked. The
market's 'can't reach the servers' was the visible symptom. Adds it to
android/app/src/main/AndroidManifest.xml.

Release prep v0.1.14: pubspec 0.1.13+15 -> 0.1.14+16; fdroid recipe
versionCodes 161/162/163, commit v0.1.14, CurrentVersionCode 163.
2026-07-22 17:11:12 +02:00
3d042c673e chore(release): prep v0.1.13 — point fdroid recipe at v0.1.13 so references build
Some checks failed
ci / analyze (push) Successful in 1m22s
ci / test-commons-core (push) Successful in 45s
ci / test-app-seeds (push) Successful in 16m43s
site / deploy (push) Successful in 31s
release / play (push) Successful in 16m54s
release / fdroid_reference_arm64_v8a (push) Has been cancelled
release / fdroid_reference_x86_64 (push) Has been cancelled
release / fdroid_reference_armeabi_v7a (push) Has been cancelled
v0.1.11 and v0.1.12 bumped pubspec without advancing the fdroid recipe, so the
fdroid_reference job computed versionCodes 131/141 that the recipe (still
121/122/123) didn't define — 'fdroid build' found no such versionCode and the
job failed. The Play deploys were unaffected.

- pubspec: 0.1.12+14 -> 0.1.13+15.
- fdroid recipe: Builds versionName 0.1.13, versionCodes 151/152/153,
  commit v0.1.13; CurrentVersion 0.1.13, CurrentVersionCode 153.

Play accepts versionCode 15 (new); fdroid_reference now builds 151/152/153.
2026-07-22 16:49:55 +02:00
05e4689339 chore(release): v0.1.12 — fresh-install market connectivity + honest server copy
Some checks failed
ci / analyze (push) Successful in 1m13s
ci / test-commons-core (push) Successful in 38s
ci / test-app-seeds (push) Successful in 7m19s
site / deploy (push) Successful in 34s
release / play (push) Successful in 14m52s
release / fdroid_reference_armeabi_v7a (push) Failing after 11s
release / fdroid_reference_arm64_v8a (push) Has been skipped
release / fdroid_reference_x86_64 (push) Has been skipped
Bumps 0.1.11+13 -> 0.1.12+14. Ships the market fixes: auto-recovery when the
shared relay connection comes up (no more stuck 'can't reach the servers' on a
fresh install), per-relay connect timeout, zone prompt before the connection
error, un-clipped Save button, and honest 'community servers' copy in app + site.

fdroid recipe intentionally not bumped here (as with v0.1.11); F-Droid is tracked
in its own reproducible-build MR.
2026-07-22 16:08:34 +02:00
2c04f4bfb6 fix(site): honest decentralization copy — community servers, not 'no server'
The landing claimed seeds spread 'with no server in the middle' and the About
page said people communicate 'directly with each other', while sharing in fact
travels through community relays. Reworded (en/es/pt, docs sources + generated
about pages via build-legal.sh): what you share travels through community
servers run by people and collectives — many of them, anyone can add one, none
a controllable center.
2026-07-22 16:08:34 +02:00
1a946d5c26 fix(i18n): honest sharing intro — community servers exist, no company runs them
The setup intro claimed sharing happened 'with no company in the middle'
while the sheet itself lists community servers. Reworded in all repo-authored
locales (en/es/fr/de/pt/pt_BR/ast): what you offer travels through community
servers run by people and collectives rather than a company.
2026-07-22 16:08:34 +02:00
13b6b4bfce fix(market): zone prompt before connection error; keep Save above the nav bar
- A new user's first step (set your area) works offline, so that empty state
  now wins over 'can't reach the servers'
- The sharing-setup sheet wraps in SafeArea(top: false) so the Save button
  isn't clipped by the system navigation bar on edge-to-edge devices
2026-07-22 16:08:34 +02:00
8a7dc8d3dc fix(market): recover by itself when the shared connection comes up
Fresh installs could sit on 'can't reach the servers' forever: the offers
cubit captured the transport once at build time, the shared connection only
retried on a connectivity CHANGE, and a silently-filtered relay could stall
the pool for minutes.

- SocialConnection: retry with backoff after a failed attempt while started
  and not knowingly offline (injectable schedule for tests)
- OffersCubit: follow connection.sessions, re-attach the transport and re-run
  the last discovery on (re)connect; announce drops via connectionEpoch
- market _init: record the wanted area on the cubit even while offline
- NostrOfferTransport.discoverPage: sort a copy (channel lists may be
  unmodifiable)
2026-07-22 16:08:34 +02:00
981cf10048 fix(social): cap relay connect with a timeout so one hung relay can't stall the pool 2026-07-22 16:08:34 +02:00
3ec6ed2329 v0.1.11 2026-07-22 16:08:34 +02:00
4963282620 fix(site): only wrap header nav on small screens if it overflows
The forced width:100% on .site-nav below 560px was written back when
the language switcher spelled out every language name and needed the
room. Now that it's a compact pill, the header fits on one line down
to ~360px; let flex-wrap handle the actual overflow case instead of
always forcing a second row.
2026-07-22 16:08:34 +02:00
8aa37bde34 ci(release): retry network-fragile steps (fdroidserver download + fdroid build)
All checks were successful
ci / analyze (push) Successful in 1m22s
ci / test-commons-core (push) Successful in 46s
ci / test-app-seeds (push) Successful in 7m7s
Even after the dnsmasq DNS cache, the Hetzner vSwitch still blips
mid-transfer. Two spots kept killing ~25min builds: the fdroidserver
tarball 'curl -sL | tar' (an empty stream -> 'gzip: unexpected end of
file') and maven/pub fetches mid-Gradle ('Network is unreachable').
Download fdroidserver to a file with curl --retry (+ -f + validate the
gzip before extract), and wrap fdroid build in a 3-attempt loop gated on
the APK actually appearing (fdroid build exits 0 even on failure).
2026-07-22 12:17:11 +02:00
92cc2e6232 ci(release): build fdroid references under /home/vagrant to match F-Droid (reproducibility)
All checks were successful
ci / analyze (push) Successful in 1m12s
ci / test-commons-core (push) Successful in 39s
ci / test-app-seeds (push) Successful in 6m30s
F-Droid's reproducible-build verification failed: the native .so
(Flutter libapp/libdartjni + tesseract4android libjpeg/leptonica/pngx/
libtesseract) differed byte-for-byte. Root cause: F-Droid builds under
/home/vagrant/build/<appid> (its buildserver path) while our reference
built under /tmp/fdroiddata/build/<appid> — the differing absolute build
path leaks into the native libs (debug info / embedded paths). Build the
reference under /home/vagrant so app + srclib paths match F-Droid's.

Also: add a workflow_dispatch ref_tag input to rebuild+re-upload an
existing release's reference APKs (idempotent asset replace) without
cutting a new tag or re-deploying to Play — so reproducibility fixes can
be iterated on the same v* release.
2026-07-22 09:56:59 +02:00
841cb9aaec ci(release): serialize play before the fdroid_reference chain
All checks were successful
ci / analyze (push) Successful in 3m17s
ci / test-commons-core (push) Successful in 1m26s
ci / test-app-seeds (push) Successful in 11m1s
A tag push started play (AAB → Play) and fdroid_reference_armeabi_v7a at
the same instant; two heavy Android builds on the shared runner
(capacity:2) OOM-killed play's Gradle daemon ('daemon disappeared') deep
in bundleRelease. Chain the fdroid references after play with needs:play
+ if:always() so only one Android build runs at a time. if:always() keeps
the fdroid chain independent of play's result (still runs when play fails
or, on workflow_dispatch, is skipped).
2026-07-21 23:57:38 +02:00
538b28e5d2 Lang menu and autodetect
All checks were successful
ci / test-commons-core (push) Successful in 56s
ci / analyze (push) Successful in 1m39s
site / deploy (push) Successful in 44s
ci / test-app-seeds (push) Successful in 7m29s
release / fdroid_reference_armeabi_v7a (push) Successful in 42m36s
release / fdroid_reference_arm64_v8a (push) Successful in 33m58s
release / fdroid_reference_x86_64 (push) Successful in 26m15s
release / play (push) Successful in 12m49s
2026-07-21 19:15:42 +02:00
1b439e9499 chore(release): prep v0.1.10 — harden play vs jcenter/OOM, point recipe at v0.1.10
Some checks failed
ci / test-commons-core (push) Successful in 56s
ci / analyze (push) Successful in 1m47s
site / deploy (push) Successful in 34s
ci / test-app-seeds (push) Has been cancelled
- play job: apply the same two fixes the fdroid recipe uses (strip
  flutter_tesseract_ocr's dead-jcenter buildscript; cap Gradle heap to
  -Xmx4g + no daemon) so a cold-cache production AAB build can't hit
  either blocker. play builds the AAB directly, not via the recipe, so
  it was still exposed.
- pubspec: 0.1.9+11 -> 0.1.10+12.
- fdroid recipe: versionName 0.1.10, versionCodes 121/122/123,
  commit v0.1.10, CurrentVersion(Code) 0.1.10/123. binary: uses %v so
  it resolves to the v0.1.10 release assets the tag build will upload.

The v0.1.10 tag is intentionally NOT cut here: cutting it deploys to
Google Play PRODUCTION (100%) and uploads the 3 signed reference APKs.
2026-07-21 19:12:11 +02:00
e4c62f2b56 fix(fdroid): cap Gradle heap + drop daemons so the build survives host RAM pressure
All checks were successful
ci / test-commons-core (push) Successful in 54s
ci / analyze (push) Successful in 1m51s
site / deploy (push) Successful in 40s
ci / test-app-seeds (push) Successful in 9m28s
The reproducible build OOM-killed the Gradle daemon ('daemon disappeared
unexpectedly') mid flutter-build-apk on the shared runner. The app's
gradle.properties reserves -Xmx8G+4G metaspace (~12G), and the fdroid
build also compiles tesseract4android from source first (its daemon
lingers), so combined peak RAM trips the OS OOM-killer under contention
(the same build succeeded on a quieter host earlier). Scope the fix to
the fdroid build (don't touch the committed 8G the play/local builds
rely on): run tesseract's gradle with --no-daemon so it frees memory
before the app build, and append a lower -Xmx4g + org.gradle.daemon=false
override to gradle.properties in prebuild (last-key-wins; F-Droid runs
the same steps and memory settings don't change output bytes, so it stays
reproducible).
2026-07-21 17:43:37 +02:00
08459ad29d fix(fdroid): strip flutter_tesseract_ocr's stale jcenter buildscript
All checks were successful
ci / test-commons-core (push) Successful in 45s
ci / analyze (push) Successful in 1m30s
site / deploy (push) Successful in 34s
ci / test-app-seeds (push) Successful in 8m8s
The plugin's android/build.gradle pins its own AGP 7.1.2 and resolves it
via jcenter() (dead since 2021). On a cold Gradle cache the AGP-7.1.2
transitives (apkzlib -> fastutil/json-simple/javawriter) only resolve
from jcenter and fail hard, breaking the reproducible fdroid build.
Warm-cache runs masked it (the one green armeabi-v7a run never hit
jcenter). Strip that buildscript block in prebuild so the plugin
inherits the app's AGP 8.11.1 (settings.gradle.kts) and never touches
jcenter or old AGP at all.
2026-07-21 16:50:11 +02:00
64b974a7a6 ci(release): chain fdroid_reference ABIs with needs: (matrix max-parallel not honored by this runner)
All checks were successful
ci / analyze (push) Successful in 2m27s
ci / test-commons-core (push) Successful in 1m16s
ci / test-app-seeds (push) Successful in 12m7s
2026-07-21 13:11:08 +02:00
6a65175154 ci(release): serialize fdroid_reference matrix (max-parallel:1) to avoid OOM contention
All checks were successful
ci / test-commons-core (push) Successful in 45s
ci / analyze (push) Successful in 1m33s
ci / test-app-seeds (push) Successful in 9m9s
2026-07-21 12:31:07 +02:00
fa768ef17f feat(site): add Portuguese to the landing site
All checks were successful
ci / analyze (push) Successful in 2m43s
ci / test-commons-core (push) Successful in 1m32s
site / deploy (push) Successful in 1m23s
ci / test-app-seeds (push) Successful in 12m26s
Mirror the es/ pattern: docs/legal/pt/ + docs/o-que-e-tane.md as the
Portuguese source of truth, build-legal.sh extended to generate the
Hugo pt.* pages from them, config.toml gets a [languages.pt] entry,
i18n/pt.json translates the UI chrome. og-pt.png is a placeholder copy
of og-en.png until a proper Portuguese social card is made by hand
(same as the other og-*.png, per DEPLOY.md). Verified locally with the
Docker build: /pt/, /pt/about/, all four /pt/legal/ pages and the
lang-switch link all resolve correctly.
2026-07-20 23:35:26 +02:00
a47bd6badd docs(claude): point git note at git.comunes.org origin; note pre-split backup
Some checks failed
ci / analyze (push) Successful in 2m1s
ci / test-commons-core (push) Successful in 1m35s
ci / test-app-seeds (push) Has been cancelled
The bare ~/repos/tane.git was renamed to ~/repos/tane-pre-split-2026-07-15.git
(archived pre-filter-repo history) and detached as a remote; origin is now the
forge at git.comunes.org.
2026-07-20 23:16:14 +02:00
d80f6d50fa feat(i18n): complete Portuguese, add Brazilian Portuguese (pt_BR)
Some checks are pending
ci / analyze (push) Waiting to run
ci / test-commons-core (push) Waiting to run
ci / test-app-seeds (push) Waiting to run
Fill the ~74 UI strings pt.i18n.json was missing (saved searches, label
scanning, Plantaré, lot history), then add pt_BR as a proper Brazilian
variant rather than a copy of European Portuguese: tu/teu/tua -> você/
seu/sua with matching verb conjugation, partilhar -> compartilhar, and
Guardar -> Salvar for UI actions (seed-saving keeps "guardar", the
correct term in both variants). Wires AppLocale.ptBr into the language
picker and regenerates slang output.
2026-07-20 23:11:01 +02:00
071be44851 perf(android): R8, bitmap downscaling, edge-to-edge; recover device compat; publish to production
Some checks are pending
ci / analyze (push) Waiting to run
ci / test-commons-core (push) Waiting to run
ci / test-app-seeds (push) Waiting to run
site / deploy (push) Successful in 1m8s
Device compatibility (regression fix):
- The CAMERA permission (from zxing_barcode_scanner / image_picker) implicitly
  required android.hardware.camera, excluding camera-less devices — Play showed
  Automotive -96%, Chromebook -86%, TV -25%. Declare camera & location
  uses-feature required="false" to keep those devices supported.
- Detect a real camera at runtime (PackageManager.FEATURE_CAMERA_ANY via the
  existing MethodChannel), cache it at bootstrap, and hide the QR scan button and
  the camera photo-source option when absent, so no broken actions are offered.

Play "app optimization" recommendations:
- Enable R8 (isMinifyEnabled + isShrinkResources) with keep rules for the
  OCR (tesseract4android), SQLCipher and notifications JNI/reflection code.
- Bitmap downscaling: cacheWidth/cacheHeight (and ResizeImage for avatars) on
  list thumbnails and avatars so photos decode to on-screen size, not full res.
- Edge-to-edge: opt in with transparent system bars in main().

Release flow:
- Tagged builds now publish to the production track at 100% (was internal);
  add a manual deploy_internal lane as a QA safety net.
- Document country/region availability as a Play Console setting (not in-repo).
2026-07-20 22:53:48 +02:00
f17ae7751c perf(market): paginate Nostr offer discovery, infinite scroll, memory cap
Bound market memory and let large areas page instead of loading everything:
- DiscoveryQuery gains an until cursor; OfferTransport gains discoverPage()
  (one-shot, EOSE-bounded, newest-first) alongside the existing live discover()
  stream, which now accepts since so it only carries NEW offers going forward.
- NostrOfferTransport.discoverPage sorts by created_at desc and derives the
  next cursor from the oldest event seen (not the oldest type-matched one, so
  filtering never skips a page).
- OffersCubit: discover() fetches the first page + opens a since=now live sub;
  loadNextPage() pages further back; the in-memory list is capped at 400
  offers (each can carry a ~40KB inline photo thumbnail, so unbounded growth in
  a busy area was a real OOM risk).
- market_screen: infinite scroll via a scroll-position trigger + footer
  spinner, instead of a single unbounded ListView.
- Added discoverPage unit tests (commons_core) and cubit pagination tests
  (first page/cursor, accumulation, cap, cross-page dedup).
2026-07-20 22:53:48 +02:00
3de01bd948 perf(inventory): lazy list, photo thumbnails, indexes, debounced reload
Scale the local inventory to 10k+ varieties:
- Render the list with ListView.builder over a flattened header/item model
  instead of building every tile upfront.
- Store a small regenerable JPEG thumbnail per photo (schema v14) and use it
  for the 48px list avatar; full bytes stay for offer image hosting. Existing
  photos are backfilled lazily at startup. Thumbnail is local-only (excluded
  from CRDT sync and backups by the JSON codec).
- Add indexes on varieties(is_deleted,is_draft), attachments(parent_type,
  parent_id,kind), lots(variety_id) via @TableIndex.
- Debounce watchInventoryView (~250ms) so a burst of table writes triggers one
  reload, not seven.
- cacheWidth/cacheHeight on the list avatar decode.
- Scale test raised 3k -> 10k; migration test v13 -> v14.
2026-07-20 22:53:48 +02:00
2884ddd3c7 ci(release): split fdroid_reference into a 3-way ABI matrix to fit the runner's max job time
All checks were successful
ci / test-commons-core (push) Successful in 1m4s
ci / analyze (push) Successful in 2m5s
ci / test-app-seeds (push) Successful in 8m44s
2026-07-20 22:37:42 +02:00
0763047d02 ci(release): pre-clone app into fdroid build dir so SOURCE_DATE_EPOCH resolves; fail fast unless 3 APKs
All checks were successful
ci / test-commons-core (push) Successful in 59s
ci / analyze (push) Successful in 2m1s
ci / test-app-seeds (push) Successful in 10m58s
2026-07-20 21:39:56 +02:00
06e2ad29c9 chore(release): v0.1.9 (+11) — single-run reproducible developer-signed (SOURCE_DATE_EPOCH comes from the app commit, not fdroiddata)
Some checks failed
ci / test-commons-core (push) Successful in 43s
ci / analyze (push) Successful in 1m24s
site / deploy (push) Successful in 28s
ci / test-app-seeds (push) Successful in 9m35s
release / fdroid_reference (push) Failing after 21s
release / play (push) Successful in 18m50s
2026-07-20 17:24:28 +02:00
bec3493e37 Revert "ci(release): revert to F-Droid-signed recipe; drop pre-merge reference build"
This reverts commit 4d99e1a840.
2026-07-20 17:13:46 +02:00
e054e280dc Revert "docs(fdroid): post-merge runbook for reproducible developer-signed builds"
This reverts commit 85a75ac3b7.
2026-07-20 17:13:46 +02:00
85a75ac3b7 docs(fdroid): post-merge runbook for reproducible developer-signed builds
All checks were successful
ci / test-commons-core (push) Successful in 51s
ci / analyze (push) Successful in 1m35s
site / deploy (push) Successful in 34s
ci / test-app-seeds (push) Successful in 6m40s
2026-07-19 11:36:15 +02:00
4d99e1a840 ci(release): revert to F-Droid-signed recipe; drop pre-merge reference build
All checks were successful
ci / test-commons-core (push) Successful in 44s
ci / analyze (push) Successful in 1m26s
site / deploy (push) Successful in 30s
ci / test-app-seeds (push) Successful in 6m8s
2026-07-19 11:19:46 +02:00
831730e308 ci(release): redirect app clone to internal Forgejo; robust apksigner; manual dispatch (play=tags only)
All checks were successful
ci / test-commons-core (push) Successful in 54s
ci / analyze (push) Successful in 1m48s
ci / test-app-seeds (push) Successful in 6m44s
2026-07-19 10:31:36 +02:00
50edb5ff75 ci(release): vendor fdroid config+srclibs in-repo (no gitlab clone); v0.1.8 (+10)
Some checks failed
ci / test-commons-core (push) Successful in 59s
ci / analyze (push) Successful in 1m53s
site / deploy (push) Successful in 33s
ci / test-app-seeds (push) Successful in 9m52s
release / fdroid_reference (push) Failing after 13s
release / play (push) Successful in 19m22s
2026-07-19 09:54:31 +02:00
9b0ef1fc40 chore(release): v0.1.7 (+9) — reference APKs via fdroid buildserver
Some checks failed
ci / test-commons-core (push) Successful in 44s
ci / analyze (push) Successful in 1m27s
site / deploy (push) Successful in 29s
ci / test-app-seeds (push) Successful in 8m51s
release / fdroid_reference (push) Failing after 1m32s
release / play (push) Successful in 17m48s
2026-07-19 09:32:39 +02:00
b906161d70 ci(release): produce F-Droid reference APKs via fdroid build in buildserver image, then sign 2026-07-19 08:56:54 +02:00
654ed1fe68 ci(release): route dead jcenter deps to mavenCentral; v0.1.6 (+8)
Some checks failed
ci / test-commons-core (push) Successful in 1m3s
ci / analyze (push) Successful in 2m2s
ci / test-app-seeds (push) Successful in 10m51s
release / android (push) Failing after 17m23s
2026-07-19 07:09:07 +02:00
bbd8d3580f chore(release): v0.1.5 (+7) — retag with tesseract build fix
Some checks failed
ci / test-commons-core (push) Successful in 50s
ci / analyze (push) Successful in 1m39s
ci / test-app-seeds (push) Successful in 10m14s
release / android (push) Failing after 20m15s
2026-07-19 06:38:21 +02:00
f968f64de8 ci(release): fix tesseract build — use root gradlew with :tesseract4android task 2026-07-19 06:36:25 +02:00
a575f01207 ci(release): build tesseract4android from source for F-Droid reproducibility; v0.1.4 (+6)
Some checks failed
ci / test-commons-core (push) Successful in 1m27s
ci / analyze (push) Successful in 2m17s
release / android (push) Failing after 4m50s
ci / test-app-seeds (push) Successful in 10m40s
2026-07-19 06:18:04 +02:00
b76083be57 chore(release): v0.1.3 (+5) — reproducible developer-signed F-Droid
All checks were successful
ci / test-commons-core (push) Successful in 1m0s
ci / analyze (push) Successful in 1m55s
site / deploy (push) Successful in 34s
ci / test-app-seeds (push) Successful in 11m39s
release / android (push) Successful in 24m33s
2026-07-19 00:03:53 +02:00
1a826477f2 feat(app): hint isolation distance when sowing a cross-pollinating crop
Some checks failed
ci / test-commons-core (push) Successful in 58s
ci / analyze (push) Successful in 1m49s
site / deploy (push) Successful in 38s
ci / test-app-seeds (push) Has been cancelled
One passive line in the batch story after a 'sown today' tap — 'this
species crosses, grow it ~400 m from others' — sourced from the bundled
seed-saving guidance (family default + species override). Selfers get
nothing: the trap is recording isolation religiously for beans where it
never mattered. No input fields, no schema change.
2026-07-18 12:31:42 +02:00
f1aa8f8e66 feat(app): scan a printed seed label back into its record
Closes the physical↔digital loop the labels opened: the QR on a printed
envelope (tane://seed, already encoded by seed_label_codec) can now be
scanned from the inventory bar. A known label opens its variety; an
unknown one asks before adding anything, then creates the variety (species
linked by exact scientific name when bundled) with a lot carrying the
label's year and origin. Scanner is pure ZXing (zxing_barcode_scanner,
MIT) — no ML Kit, no Play Services, F-Droid-safe, the stack Ğ1nkgo ships.
Mobile-only; other platforms don't show the button (OCR precedent).
The post-scan flow is a plain function (handleScannedPayload) so it's
widget-tested without a camera.
2026-07-18 12:26:27 +02:00
bb5b3d4a43 feat(app): ask 'how did it do?' when a harvest is noted (schema v13)
The note growers most wish they had two seasons later — did it do well,
was it worth keeping — never had a home. New append-only GardenOutcomes
table (lotId, season year, three-face rating, free note); the question
appears ONCE, inline, right after recording a harvest in the batch story,
and is skippable without a trace. The answer shows as one more story
line. Rides backups/sync like every mutable table (JSON codec, LWW
import, HLC clock absorb). Migration v12→v13 guarded + verified from
every historical version.
2026-07-18 12:18:25 +02:00
92fd84590b feat(app): show each batch's story as a composite timeline
The Movement log (history + provenance DAG) was recorded but invisible.
A new history sheet on every lot tile narrates the batch: movements,
germination tests, storage checks and how it entered the collection
(origin attached), most-recent first. Two one-tap chips record 'sown
today' / 'harvested today' — the first UI door to the sown/harvested
movement types. No schema change; one-shot reads only (no live
subscriptions in a transient sheet).
2026-07-18 06:25:55 +02:00
11cbdf3022 docs(site): document the automatic Forgejo Actions deploy
All checks were successful
ci / test-commons-core (push) Successful in 56s
ci / analyze (push) Successful in 1m51s
site / deploy (push) Successful in 36s
ci / test-app-seeds (push) Successful in 7m10s
The manual Ansible playbook was superseded by the site.yml workflow,
which deploys on every push to main touching site/** or docs/**.
Keep Ansible documented only as the manual fallback.
2026-07-18 00:30:05 +02:00
0aa8dd91ab feat(site): show discreet # permalinks on landing section titles
All checks were successful
ci / test-commons-core (push) Successful in 49s
ci / analyze (push) Successful in 1m34s
site / deploy (push) Successful in 36s
ci / test-app-seeds (push) Successful in 6m19s
The landing sections had ids but no visible anchor, unlike About/Legal.
Add a hover-revealed # link on each section title (Status, Features,
Screenshots, Values, FAQ, Collaborate, Get it) and widen the reveal rule
beyond .doc so it applies to the home too.
2026-07-17 17:36:32 +02:00
8bec7dcde2 feat(android): split release APK per ABI for F-Droid
All checks were successful
release / android (push) Successful in 13m47s
Adds a versionCodeOverride to build.gradle.kts (F-Droid requires distinct
versionCodes per split APK; Google Play's App Bundle is unaffected since
this only touches the application-variant/APK output). Bumps to 0.1.2+4.

Verified locally: flutter build apk --release --split-per-abi produces
app-{armeabi-v7a,arm64-v8a,x86_64}-release.apk with versionCode 31/32/33.
2026-07-17 17:36:18 +02:00