fix: about page version unknown and link crash on Android (#213) #224

Merged
guettlibot merged 5 commits from issue-213-fix into main 2026-05-24 15:20:15 +00:00
5 Commits
Author SHA1 Message Date
Thomas SharedInboxandClaude Sonnet 4.6 bc91c0db52 fix: about page version unknown and link crash on Android (#213)
Bug 1 – "App Version: unknown": PackageInfo.fromPlatform() throws because
plugin registration is aborted mid-way by a Java Error (e.g.
NoClassDefFoundError) that catch (Exception e) does not catch.
Fix: change all 13 catch clauses in GeneratedPluginRegistrant.java to
catch (Throwable e) and commit the file so it is used by release builds.

Bug 2 – crash when tapping sharedinbox.de: url_launcher_android 6.3.25+
migrated to Pigeon 26, which throws a channel-error on some Android
devices (same root cause as path_provider_android, already pinned).
The onTapLink callback called launchUrl via unawaited() with no error
handling, so the PlatformException became an unhandled async error and
crashed the app.
Fix: pin url_launcher_android <6.3.25 in dependency_overrides, and add
a _launchUrl() helper with full try/catch that shows a SnackBar on error
instead of crashing. New widget test verifies the snackbar path.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 17:15:19 +02:00
Thomas SharedInboxandClaude Sonnet 4.6 839a3c63f9 feat: keep secrets in sync via age-encrypted master key (#208)
Store all production secrets encrypted in secrets.age (committed to the
repo) using age. Only one secret needs to be in CI: SECRETS_AGE_KEY.

When a secret changes locally, update secrets.env and re-run
scripts/secrets-encrypt.sh to commit a new secrets.age. CI picks up the
updated secrets automatically on the next push — no manual CI variable
updates required.

Changes:
- scripts/secrets-encrypt.sh: encrypt secrets.env → secrets.age
- scripts/secrets-decrypt.sh: decrypt secrets.age → GITHUB_ENV (CI) or
  eval-safe export block (local)
- scripts/test_secrets.sh: encrypt/decrypt round-trip tests
- secrets.env.example: template documenting all production secret keys
- ci/main.go: add CheckSecrets function (runs test_secrets.sh via Dagger),
  wire into Check(), update Graph(); add age to toolchain apt packages
- .forgejo/Dockerfile: add age package
- .forgejo/workflows/deploy.yml: replace per-secret CI references with a
  single "Decrypt production secrets" step using SECRETS_AGE_KEY
- flake.nix: add age to dev shell
- Taskfile.yml: add check-secrets task, include in check-fast
- .gitignore: ignore plaintext secrets.env
- DAGGER.md: document Option 5 (encrypted secrets file) as active approach

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 16:32:27 +02:00
Thomas SharedInboxandClaude Sonnet 4.6 a167ebd0a3 feat: add build mode, Dart version, timestamp to crash report (#205)
Show app version, build mode, and platform OS in the crash screen UI
so users can report bugs without needing to copy first.  The clipboard
report now also includes Build Mode (debug/release/profile), Dart
runtime version, and a UTC timestamp to aid post-crash diagnosis.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 16:06:32 +02:00
Thomas SharedInboxandClaude Sonnet 4.6 881a240155 fix: probe scanner method channel to detect MissingPluginException (#204)
The previous pre-flight check called ctrl.start() without ctrl.attach(),
causing MobileScannerController to time out after 500 ms with
controllerNotAttached on every device — the scanner never worked even
when the plugin was present.

Replace with a direct invokeMethod('state') probe on the scanner channel.
MissingPluginException (thrown when the plugin is not registered) is the
exact error from the crash report; all other errors are surfaced by the
MobileScanner widget's own error builder.

Also add widget tests for the AccountReceiveScreen step-2 import flow
(text fallback, successful import, invalid-QR error) which were
previously untested.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 15:47:21 +02:00
Thomas SharedInbox 117b546b2c feat: show live countdown with seconds on receive account screen (#203)
Replace the static "expires in 20 minutes" label with a StatefulWidget
that ticks every second and displays the remaining time as MM:SS.
2026-05-24 15:11:56 +02:00