The legacy `systray@1.0.5` package (last published 2018) bundles a 2017
x86_64 Go binary whose Mach-O headers are rejected by modern dyld (macOS
14+ / Apple Silicon). The result on affected systems was that
`9router --tray` (and "Hide to Tray" from the interactive menu) printed
"Router is now running in system tray" but no menubar icon appeared —
the failure was silently swallowed by `catch (err) { return null }`.
This swaps the runtime tray library for `systray2@2.1.4`, which embeds
the maintained getlantern/systray-portable binaries that work on macOS
14+ under Rosetta. Changes:
- hooks/trayRuntime.js: install `systray2@2.1.4` (not `systray@1.0.5`)
into ~/.9router/runtime/node_modules. Always purge the legacy systray
package on every run — its binary is broken on macOS and an AV false
positive on Windows. chmod +x the bundled Go binary in case the npm
tarball drops the executable bit (observed on macOS).
- src/cli/tray/tray.js: resolveSystray() now prefers systray2 with a
fallback to legacy systray for safety. initUnixTray() uses the new
.ready() promise API, surfaces failures to stderr instead of silently
returning null, and sets isTemplateIcon:false so the full-color
icon.png renders correctly (template mode would show a solid white
square because only the alpha channel is used). killTray() passes
false to systray2's kill so it doesn't call process.exit(0) before
the rest of cleanup (server SIGKILL, MITM/tunnel) runs.
- package.json: update the `comment_systray` field to describe the new
package choice.
Fixes#1079