diff --git a/nix/modules/hive-matrix.nix b/nix/modules/hive-matrix.nix index c1575d9e..f748fa28 100644 --- a/nix/modules/hive-matrix.nix +++ b/nix/modules/hive-matrix.nix @@ -8,6 +8,82 @@ let cfg = config.services.hyperhive.matrix; hyperhiveDomain = config.services.hyperhive.domain; effectiveServerName = if cfg.serverName != null then cfg.serverName else hyperhiveDomain; + + # Two files are missing from nixpkgs's `pkgs.fluffychat-web` dist + # because `flutter341.buildFlutterApplication` doesn't run the + # native_imaging package's emscripten build (#685): + # + # - Imaging.js / Imaging.wasm ← emscripten-compiled C library + # from the native_imaging dart package (vendored by Famedly). + # The package ships only C source + a Makefile that builds + # them via emcc; pulling in `pkgs.emscripten` to run that + # mid-build adds ~600 MB of closure for two files we can pin + # to the upstream release tarball's prebuilt copies (same + # fluffychat release version → byte-identical output). + # + # `native_executor.js` is the other missing file (web worker entry + # point), but that one compiles cleanly from source via + # `dart compile js` — handled in `fluffychat-web-fixed` below + # rather than vendored, since the dart SDK is already in the + # flutter341 closure. + fluffychat-web-imaging-prebuilt = + pkgs.runCommandLocal "fluffychat-web-imaging-prebuilt-${pkgs.fluffychat-web.version}" + { + src = pkgs.fetchurl { + url = "https://github.com/krille-chan/fluffychat/releases/download/v${pkgs.fluffychat-web.version}/fluffychat-web.tar.gz"; + # v2.6.0 prebuilt tarball; bump in lockstep with + # `pkgs.fluffychat-web.version` on any flutter upgrade. + hash = "sha256-P3Bt5FZ5TPeE0k05gYxLw7FdEyyi8g5A/r7tGZMezQk="; + }; + } + '' + mkdir -p $out + tar -xzf $src --strip-components=2 -C $out \ + build/web/Imaging.js build/web/Imaging.wasm + ''; + + # `pkgs.fluffychat-web` with #685's three missing files patched + # in via postInstall, plus the existing `--base-href "/matrix/"` + # override (#634) for the sub-path mount. The patches sit in our + # tree rather than as a nixpkgs upstream PR because: + # - `dart compile js` for web workers is a `buildFlutterApplication` + # gap that needs an upstream patch, not a per-package one + # - vendoring emscripten output for `native_imaging` is a + # workaround for the same builder gap + # When `flutter341.buildFlutterApplication` grows worker / emcc + # support, drop the postInstall entirely. + fluffychat-web-fixed = pkgs.fluffychat-web.overrideAttrs (old: { + # `--base-href "/matrix/"` so relative asset paths resolve + # under the sub-path mount (#634). Upstream default is `/`, + # wrong for hyperhive's `/matrix/` location. + flutterBuildFlags = (old.flutterBuildFlags or [ ]) ++ [ + "--base-href" + "/matrix/" + ]; + + # `dart` from the flutter341 closure (already pulled, no + # incremental closure cost) so we can compile the web-worker + # entry point that buildFlutterApplication skips. + nativeBuildInputs = (old.nativeBuildInputs or [ ]) ++ [ pkgs.flutter341.dart ]; + + postInstall = + (old.postInstall or "") + + '' + # #685: compile web/native_executor.dart → native_executor.js. + # The flutter web bootstrap loads this from /matrix/native_executor.js + # at startup; without it, main.dart.js logs a network-error and + # the SPA renders blank (see #643 for the symptom). + ${pkgs.flutter341.dart}/bin/dart compile js \ + -o $out/native_executor.js \ + $src/web/native_executor.dart + + # #685: vendor Imaging.{js,wasm} from upstream prebuilt — see + # comment on `fluffychat-web-imaging-prebuilt` above for the + # closure-size rationale vs running emcc here. + install -m 644 ${fluffychat-web-imaging-prebuilt}/Imaging.js $out/Imaging.js + install -m 644 ${fluffychat-web-imaging-prebuilt}/Imaging.wasm $out/Imaging.wasm + ''; + }); in { # Private Matrix homeserver (matrix-tuwunel — the official conduwuit @@ -202,32 +278,24 @@ in package = lib.mkOption { type = lib.types.package; - default = pkgs.fluffychat-web.overrideAttrs (old: { - # fluffychat-web ships with `` baked into its - # index.html — flutter's `--base-href` build flag replaces - # that placeholder. Default upstream build is `--base-href "/"` - # which is wrong for hyperhive's `/matrix/` sub-path mount: - # the browser resolves relative asset paths (`Imaging.js`, - # `flutter.js`, `splash/*`) against the document ROOT, - # producing 404s for every asset (#634). Inject the right - # base-href into the actual `flutter build web` invocation - # via the upstream derivation's `flutterBuildFlags` string - # (the buildPhase is literally - # `flutter build web -v $flutterBuildFlags`). When subdomain - # routing lands (#609 — `matrix.${hyperhiveDomain}`), drop - # this override; upstream's `/` base-href is correct at the - # root of a dedicated subdomain. - flutterBuildFlags = (old.flutterBuildFlags or [ ]) ++ [ - "--base-href" - "/matrix/" - ]; - }); - defaultText = lib.literalMD "`pkgs.fluffychat-web` rebuilt with `--base-href /matrix/` via `flutterBuildFlags`."; + default = fluffychat-web-fixed; + defaultText = lib.literalMD '' + `pkgs.fluffychat-web` rebuilt with `--base-href /matrix/` (#634) + and patched via `postInstall` to add the three files + `flutter341.buildFlutterApplication` skips: `native_executor.js` + (compiled via `dart compile js`), plus `Imaging.js` and + `Imaging.wasm` (vendored from the upstream release tarball; + they're emscripten output from the `native_imaging` dart + package and the alternative is +~600 MB of `pkgs.emscripten` in + the build closure for two files). See the `let` block in + `nix/modules/hive-matrix.nix` for the full rationale (#685). + ''; description = '' Static web client dist to serve at `/matrix/`. Defaults to `pkgs.fluffychat-web` rebuilt with `--base-href "/matrix/"` so relative asset paths resolve under the sub-path mount - (#634). Override to swap for `hydrogen-web` (lightest), + (#634), plus a `postInstall` patch for #685's three missing + files. Override to swap for `hydrogen-web` (lightest), `cinny` (no threads), `element-web` (heaviest, full features), or an out-of-tree client dist — any replacement also needs its `` aligned with the mount path.