Commit Graph
140 Commits
Author SHA1 Message Date
edde746 7f0cad339c fix(startup): report and repair a failed launch instead of showing "Error"
Since 2.10.0 the whole app sits behind one all-or-nothing initialization
gate, and that gate discarded the only evidence of its own failure. It
caught the error, logged nothing but `error.runtimeType`, rendered an
icon plus the word "Error" plus Retry, and never reported the error
because catching it kept the crash reporter from ever seeing it. There
is no log file on any platform, the buffer is in memory only, a
double-clicked Windows release build has no console, and the log viewer
lives in Settings, behind the gate that just failed. #1732 is the result:
a Windows 11 user whose app will not boot and who cannot produce a single
byte of diagnostic detail.

The gate now names its phases. Each step is wrapped so a throw carries
the phase it came from, replacing a `Future.wait` that discarded every
error but the first and could not attribute it to any of four concurrent
steps. The failure screen renders the phase, the exception type, the
message and an expandable stack, plus copy and upload actions that reuse
the existing log-relay flow. The record is persisted next to the database
so the next successful launch can surface it in Settings > Logs, and it
is reported to the crash reporter explicitly.

Only preferences and the database still gate the launch. Window chrome,
locale, crash-reporting init, TV/performance detection, the image-cache
budget and download storage are best-effort and time-bounded, so a
stalled platform thread degrades instead of holding the splash forever.
Sentry no longer receives the startup work as its `appRunner`: that made
a startup failure indistinguishable from a Sentry failure, and the guard
would then have re-run migrations and the database open a second time.

The two remaining fatal steps become recoverable. Preference reads
tolerate a value whose stored type no longer matches, dropping the key
and defaulting instead of failing the boot. A store that cannot be parsed
is detected before either desktop plugin backend can memoise it, which is
what makes an in-process repair possible at all. Repair is never
automatic: it states what it will cost, salvages the credential-vault key
and every tracker and Seerr session it can validate out of the damaged
bytes, reseeds them, and moves the original aside rather than deleting
it. Servers and profiles survive a salvaged key because their tokens are
ciphertext in the database; tracker and Seerr sessions are plaintext
preference entries, so the copy says they may still need reconnecting.

Nothing derived from the store reaches a diagnostic. `FormatException`
prints an excerpt of whatever it failed to parse, and during startup that
document holds the vault key, refresh tokens and session cookies while
the redaction manager still has nothing registered, so the wrapper keeps
only the cause's type and offset and the record is an allowlist of
already-redacted fields. The quarantined copy is labelled as containing
credentials, is never offered for upload, and can be deleted from the
dialog.

Also self-heals orphaned WAL/SHM sidecars on desktop rather than only
tvOS, makes every `createTable` migration step idempotent, keeps MSVC
link by-products out of the Windows bundle, and asserts bundle contents
in CI.

Refs #1732
2026-07-31 21:45:32 +02:00
edde746 944a8d89f5 feat(windows): package for the Microsoft Store as an MSIX bundle
The Store's unpackaged EXE path would require Authenticode-signing the
installer and every PE file inside it. MSIX submissions are re-signed by the
Store instead, so this route needs no code-signing certificate. build-msix.ps1
mirrors build-installer.ps1 and consumes the same per-architecture build
artifacts, leaving the installer, portable archives and WinSparkle appcast
untouched.

One template generates the manifest for both architectures, carrying the
identity reserved in Partner Center. check_windows_msix.py recomputes the
package family name from the publisher DN, so a mistyped identity fails CI
rather than a submission, and it parses the script rather than running it
because root CI is Linux. Qualified logo assets are indexed into
resources.pri; without the altform-unplated variants the shell draws the
taskbar icon on an accent-coloured plate.

PlatformDetector.isPackagedInstall gates the in-app updater and the Liberapay
tile, which the read-only package directory and Store commerce policy
respectively rule out. Gating at runtime keeps one Windows build feeding both
the installer and the Store package.
2026-07-30 20:03:04 +02:00
edde746 8aa836d106 ci(android): gate name-based reachability on an R8-minified variant
R8 only ever ran on `release`, so every automated gate in this repository
exercised code the shipped APK does not contain. Reflective lookups, JNI
callbacks and native library loading can all break under shrinking while
`flutter test`, the Robolectric suites and `connectedDebugAndroidTest`
stay green — which is exactly how #1703 shipped, with the bundled FFmpeg
audio renderer shrunk out of release builds for TrueHD and DTS-HD.

Add a `minified` build type that inherits release's shrinker
configuration but stays debuggable and debug-signed, so it is an ordinary
test artifact and never a publishable one. Three integration details
took a run each to find: the Flutter plugin copies app build types into
every plugin module, so library-level shrinking deleted the plugin entry
points that only GeneratedPluginRegistrant references; the harness must
not be shrunk or the runner disappears; and androidx.test has to survive
in the app under test, or the runner cannot link its own supertype and
the run reports zero tests instead of failing.

Instrumentation still defaults to `debug`, because only one build type
can host androidTest and the existing playback suites drive media3
builder APIs the app never calls, which R8 shrinks legitimately. The new
reachability test opts into the minified variant instead and touches no
builder API, so the only keeps it depends on are the ones under test.
Emptying proguard-rules.pro was verified to fail it.
2026-07-28 20:13:40 +02:00
edde746 41a2e996e1 perf(test): scale test concurrency and stop re-onboarding every Maestro flow
The Dart suite spent 77% of its cost compiling one isolate per test file
while `flutter test` used half the cores, and every Maestro flow replayed
a full Jellyfin onboarding before its first real assertion.

- Add scripts/run_tests.sh, which runs `flutter test` with -j set to the
  cores the process may actually use instead of the ncpu/2 default.
  Measured on 8 cores: 190s -> 136s; -j 12 regresses to 165s, so it scales
  to the core count rather than hard-coding one. CI and CONTRIBUTING use it.
  A cgroup v2 quota, a cgroup v1 quota, and the cpuset/affinity nproc
  reports can each be the binding limit independently, so the detector
  takes the smallest; trusting whichever it found first would oversubscribe
  4x on a container holding an 8-CPU quota while pinned to 2. Covered by
  scripts/test_run_tests.py, which the ci_guard_checks.sh glob picks up.
- Add .maestro/subflows/ensure_onboarded.yaml: cold-start the app and only
  onboard when no session is stored. Flows that just need a signed-in Home
  use it; 02_onboarding_home, 08_logout, 09_download_offline_playback and
  the profile regressions keep clearing state. 59s -> 16s per flow.
- Guard onboarding's two optional taps behind visibility checks. A missed
  `optional: true` tap still runs the full element search, costing 3.0s
  and 7.8s per onboarding to find nothing.
- Disable device animation scales in run_maestro.py, restored by the
  existing cleanup path. CI's emulator got this from the runner flag;
  physical devices never did.
- Shorten the watch_together setup-timeout replacement from 500ms to the
  10ms the same file already proves sufficient, and shorten the retry
  backoff at the one site that missed it: 8.04s -> 1.59s of execution.
- Make the LAN discovery waits deadline-based and resend the beacon while
  polling. Loopback UDP drops datagrams under load, which timed out a
  wait that could never be satisfied; this was the suite's one flaky test.
- Fix 08_logout, which searched for "Logout" and "Are you sure you want to
  logout?" after both strings became "Log out". The flow had been failing
  and aborting the suite before 09 ever ran.

flutter test 190s -> 131s. Maestro's Android suite 621s -> 385s across the
eight flows the baseline reached, and now runs all nine green.
2026-07-27 03:59:27 +02:00
edde746 a56b9a3dfb Merge the deduplication and dead-code removal pass
Consolidates duplicated logic behind shared implementations — paginated
grid tabs, focus chrome, cached remote stores, sheet selection columns,
the server artifact store and a test fixture layer — and removes code
that had become unreachable. Net reduction of about 5,500 lines with no
behaviour change.

Where a fix had landed separately in code that moved into a shared
helper, the fix was re-applied inside the helper rather than left behind
in the copy that went away.
2026-07-26 19:41:23 +02:00
edde746 7e05686a7c fix(windows): restore x64 and arm64 builds 2026-07-26 15:32:02 +02:00
edde746 352b88109b refactor: extract shared mixins and helpers, drop dead abstractions
Introduces shared seams for paginated views, D-pad reorder, media control
routing, async singletons and the device method channel, then points the
open-coded copies at them.

Also removes unused models and duplicated provider/server plumbing, folds
the twice-implemented artifact store in the server, and factors the
repeated Flutter toolchain prologue in CI into a composite action.
2026-07-26 06:09:48 +02:00
edde746 77da82b648 fix(ci): make cross-platform checks deterministic 2026-07-25 16:17:25 +02:00
edde746 b7d5922b0a fix(ci): repair Windows native checks 2026-07-25 00:22:23 +02:00
edde746 d1cec00b51 fix(ci): repair native and Maestro checks 2026-07-24 20:30:45 +02:00
edde746 40833e65ec fix(ci): align toolchains and isolate platform tests 2026-07-24 10:06:50 +02:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> ef0524485a build(deps): bump softprops/action-gh-release (#1665)
Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from c12583777ecdfd3be55c69cf75464299dc01057e to 3d0d9888cb7fd7b750713d6e236d1fcb99157228.
- [Release notes](https://github.com/softprops/action-gh-release/releases)
- [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md)
- [Commits](https://github.com/softprops/action-gh-release/compare/c12583777ecdfd3be55c69cf75464299dc01057e...3d0d9888cb7fd7b750713d6e236d1fcb99157228)

---
updated-dependencies:
- dependency-name: softprops/action-gh-release
  dependency-version: 3d0d9888cb7fd7b750713d6e236d1fcb99157228
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-24 07:38:40 +02:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 071b632c93 build(deps): bump awalsh128/cache-apt-pkgs-action (#1664)
Bumps [awalsh128/cache-apt-pkgs-action](https://github.com/awalsh128/cache-apt-pkgs-action) from 2153a1bf62a0ad7830c24ccdf1d588bedc2834a7 to 553a35bb8ebd9fcabcb1c9451aa4c98e1b4ca8a9.
- [Release notes](https://github.com/awalsh128/cache-apt-pkgs-action/releases)
- [Commits](https://github.com/awalsh128/cache-apt-pkgs-action/compare/2153a1bf62a0ad7830c24ccdf1d588bedc2834a7...553a35bb8ebd9fcabcb1c9451aa4c98e1b4ca8a9)

---
updated-dependencies:
- dependency-name: awalsh128/cache-apt-pkgs-action
  dependency-version: 553a35bb8ebd9fcabcb1c9451aa4c98e1b4ca8a9
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-24 07:38:38 +02:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 62330413ee build(deps): bump actions/attest-build-provenance (#1663)
Bumps [actions/attest-build-provenance](https://github.com/actions/attest-build-provenance) from 78e6cbd37d0ac1a40113c04f2037dacf1ea3f12e to 0f67c3f4856b2e3261c31976d6725780e5e4c373.
- [Release notes](https://github.com/actions/attest-build-provenance/releases)
- [Changelog](https://github.com/actions/attest-build-provenance/blob/main/RELEASE.md)
- [Commits](https://github.com/actions/attest-build-provenance/compare/78e6cbd37d0ac1a40113c04f2037dacf1ea3f12e...0f67c3f4856b2e3261c31976d6725780e5e4c373)

---
updated-dependencies:
- dependency-name: actions/attest-build-provenance
  dependency-version: 0f67c3f4856b2e3261c31976d6725780e5e4c373
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-24 07:38:34 +02:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> aa66f9a15d build(deps): bump actions/checkout from 7.0.0 to 7.0.1 (#1662)
Bumps [actions/checkout](https://github.com/actions/checkout) from 7.0.0 to 7.0.1.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0...3d3c42e5aac5ba805825da76410c181273ba90b1)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 7.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-24 07:38:31 +02:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 7ed2049a01 build(deps): bump actions/setup-java from 5.5.0 to 5.6.0 (#1661)
Bumps [actions/setup-java](https://github.com/actions/setup-java) from 5.5.0 to 5.6.0.
- [Release notes](https://github.com/actions/setup-java/releases)
- [Commits](https://github.com/actions/setup-java/compare/0f481fcb613427c0f801b606911222b5b6f3083a...03ad4de0992f5dab5e18fcb136590ce7c4a0ac95)

---
updated-dependencies:
- dependency-name: actions/setup-java
  dependency-version: 5.6.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-24 07:38:29 +02:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> a961a5a997 build(deps): bump reactivecircus/android-emulator-runner (#1660)
Bumps [reactivecircus/android-emulator-runner](https://github.com/reactivecircus/android-emulator-runner) from 4c44018e59b437e86cdfc41da381398f93ed8808 to a421e43855164a8197daf9d8d40fe71c6996bb0d.
- [Release notes](https://github.com/reactivecircus/android-emulator-runner/releases)
- [Changelog](https://github.com/ReactiveCircus/android-emulator-runner/blob/main/CHANGELOG.md)
- [Commits](https://github.com/reactivecircus/android-emulator-runner/compare/4c44018e59b437e86cdfc41da381398f93ed8808...a421e43855164a8197daf9d8d40fe71c6996bb0d)

---
updated-dependencies:
- dependency-name: reactivecircus/android-emulator-runner
  dependency-version: a421e43855164a8197daf9d8d40fe71c6996bb0d
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-24 07:38:26 +02:00
edde746 09656fa4d3 fix(supply-chain): verify CI and production inputs
Pin external actions, images, toolchains, native archives, and tvOS engine artifacts; enforce fail-closed CI checks and keep website privacy disclosures aligned with shipped behavior.
2026-07-24 03:56:40 +02:00
edde746 43a8fe020d fix(relay): secure reconnect and room ownership 2026-07-24 03:46:50 +02:00
edde746 658da37b48 build: make toolchain inputs reproducible 2026-07-24 03:40:06 +02:00
edde746 1d1c301f61 test: stabilize deterministic integration coverage 2026-07-24 03:40:06 +02:00
edde746 fa901be328 fix(e2e): run emulator suites through Python 2026-07-15 08:25:55 +02:00
edde746 0bcd00bcb6 ci: harden privileged workflow trust boundaries 2026-07-15 07:57:42 +02:00
edde746 87c0547090 ci: harden pull request workflows 2026-07-15 07:15:34 +02:00
edde746 9471e30585 ci(test): consolidate Maestro workflow setup 2026-07-15 06:58:22 +02:00
edde746 139cf83507 feat(test): add Maestro end-to-end coverage 2026-07-15 06:40:35 +02:00
edde746 30c978719b fix(ci): update actions for Node 24 2026-07-14 07:23:16 +02:00
edde746 cbb0a01c5f fix(release): create untagged build drafts 2026-07-14 00:33:12 +02:00
edde746 a0013323f2 chore(ui): enforce icon consistency 2026-07-13 23:13:53 +02:00
edde746 7400a10c59 fix(release): prevent published asset replacement 2026-07-13 21:48:44 +02:00
edde746 822657972d fix(android): enforce minSdk compatibility 2026-07-13 17:00:50 +02:00
edde746 8210b23d31 fix(ci): set explicit release tag 2026-07-13 01:42:41 +02:00
edde746 e03edad824 fix: prevent async state and platform regressions 2026-07-13 00:03:52 +02:00
edde746 780a1ea180 fix(ci): restore analyzer and unit checks 2026-07-12 19:55:24 +02:00
edde746 fe8d405a56 fix(i18n): enforce complete localized coverage 2026-07-12 17:31:14 +02:00
edde746 a5449a1430 refactor(ci): matrix architecture builds 2026-07-12 08:42:25 +02:00
edde746 c0d8951677 fix(release): centralize pubspec version parsing 2026-07-12 08:42:24 +02:00
edde746 eaa60cc2b5 fix(release): resolve package tags once 2026-07-12 08:42:23 +02:00
edde746 5f8d263d63 fix(ci): fail closed on analyzer errors 2026-07-12 08:42:22 +02:00
edde746 d1a67828b6 fix(ci): detect silent tool failures 2026-07-12 08:42:19 +02:00
edde746 e4b0680158 fix(ci): enforce automation checks 2026-07-12 08:42:18 +02:00
edde746 5867809560 fix: resolve Jellyfin, logout, playback, and Android regressions 2026-07-09 17:14:45 +02:00
edde746 1d2dea214c ci(windows): set up arm64 Flutter 3.44.0 from git tag 2026-07-01 07:10:24 +02:00
edde746 e07f54921c ci(windows): install patched DComp engine for x64 and arm64 2026-07-01 06:37:51 +02:00
edde746 eba553413c fix(macos): allow LuaJIT under hardened runtime
close #1214
2026-06-01 02:46:37 +02:00
edde746 656d512858 ci: add build platform toggles 2026-05-31 09:26:55 +02:00
edde746 4f636dfffd fix(ci): install libmpv scripting deps 2026-05-31 07:54:37 +02:00
edde746 139eed9ca9 fix(templates): require substantive issue-form fields 2026-05-30 07:33:06 +02:00
edde746 f565684842 fix(ci): stabilize analyzer and linux builds 2026-05-20 19:10:46 +02:00
edde746 1978d710da fix(ci): unblock Flutter 3.44 checks 2026-05-19 12:38:43 +02:00