diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ce00e92..01011c9 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -53,7 +53,31 @@ jobs: CGO_ENABLED=1 GOARCH=$arch go build -o "$dir/bpm-tray" ./cmd/bpm-tray tar -C "$dir" -czf "dist-tray/bpm-tray_${{ github.ref_name }}_darwin_${arch}.tar.gz" bpm-tray done + - name: Build AppIcon.icns from the embedded logo + run: | + mkdir -p /tmp/icon.iconset + for size in 16 32 128 256 512; do + sips -z $size $size internal/webui/assets/logo.png --out /tmp/icon.iconset/icon_${size}x${size}.png >/dev/null + double=$((size*2)) + sips -z $double $double internal/webui/assets/logo.png --out /tmp/icon.iconset/icon_${size}x${size}@2x.png >/dev/null + done + iconutil -c icns /tmp/icon.iconset -o /tmp/AppIcon.icns + - name: Assemble BpmTray.app for both architectures + run: | + version="${{ github.ref_name }}" + version="${version#v}" + for arch in arm64 amd64; do + app="dist-tray/darwin_${arch}/BpmTray.app" + mkdir -p "$app/Contents/MacOS" "$app/Contents/Resources" + sed "s/VERSION_PLACEHOLDER/${version}/" packaging/macos/Info.plist.template > "$app/Contents/Info.plist" + cp "dist-tray/darwin_${arch}/bpm-tray" "$app/Contents/MacOS/bpm-tray" + cp /tmp/AppIcon.icns "$app/Contents/Resources/AppIcon.icns" + plutil -lint "$app/Contents/Info.plist" + ditto -c -k --sequesterRsrc --keepParent "$app" "dist-tray/BpmTray_${{ github.ref_name }}_darwin_${arch}.zip" + done - name: Attach to the release env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: gh release upload ${{ github.ref_name }} dist-tray/*.tar.gz --clobber + run: | + gh release upload ${{ github.ref_name }} dist-tray/*.tar.gz --clobber + gh release upload ${{ github.ref_name }} dist-tray/*.zip --clobber diff --git a/cmd/bpm-tray/main.go b/cmd/bpm-tray/main.go index 86f33ad..fa950e8 100644 --- a/cmd/bpm-tray/main.go +++ b/cmd/bpm-tray/main.go @@ -30,9 +30,20 @@ func main() { } func onReady() { - systray.SetIcon(webui.LogoPNG) + // Template icon: a flat black silhouette with real alpha, so macOS tints + // it correctly for the light/dark menu bar - the full-colour app icon + // (via plain SetIcon) rendered as an illegible colour blob at actual + // menu bar size. regularIconBytes (LogoPNG) is only a fallback for + // platforms without template-icon support; bpm-tray only ships for + // macOS, so it's never actually shown. + systray.SetTemplateIcon(webui.LogoTemplatePNG, webui.LogoPNG) systray.SetTooltip("Bambu Profile Manager") + // A single click opens the web UI directly - no menu to navigate first. + // Right-click (the systray default when SetOnTapped is set) still shows + // the menu below, so Quit stays reachable. + systray.SetOnTapped(openBrowser) + mOpen := systray.AddMenuItem("Open bpm", "Open the web UI in your browser") mStatus := systray.AddMenuItem("Starting…", "") mStatus.Disable() @@ -51,7 +62,7 @@ func onReady() { for { select { case <-mOpen.ClickedCh: - exec.Command("open", "http://localhost"+addr).Start() + openBrowser() case <-mQuit.ClickedCh: systray.Quit() return @@ -60,6 +71,10 @@ func onReady() { }() } +func openBrowser() { + exec.Command("open", "http://localhost"+addr).Start() +} + // startServer wires up the same server cmd/bpm's `serve` builds, but with // zero flags: db and backups live under ~/Library/Application Support/bpm, // and Bambu Studio's real directories are auto-discovered rather than diff --git a/internal/webui/assets.go b/internal/webui/assets.go index 5cc4340..ebf3177 100644 --- a/internal/webui/assets.go +++ b/internal/webui/assets.go @@ -14,6 +14,16 @@ import ( //go:embed assets/logo.png var LogoPNG []byte +// LogoTemplatePNG is a monochrome (black-on-transparent) silhouette derived +// from LogoPNG, cropped and downsized for use as a macOS menu bar "template" +// image — those get tinted/inverted automatically for the light/dark menu +// bar, but only if they're a flat black shape with real alpha, not a full +// colour icon (real gap found live: SetIcon with the full-colour app icon +// rendered as a tiny, illegible blob at menu bar size). +// +//go:embed assets/logo-template.png +var LogoTemplatePNG []byte + // handleLogo serves LogoPNG over HTTP. Aggressively cacheable: the file // only changes on a new build, and go:embed gives every build a fresh byte // slice anyway. diff --git a/internal/webui/assets/logo-template.png b/internal/webui/assets/logo-template.png new file mode 100644 index 0000000..c8c0907 Binary files /dev/null and b/internal/webui/assets/logo-template.png differ diff --git a/packaging/macos/Info.plist.template b/packaging/macos/Info.plist.template new file mode 100644 index 0000000..99722bd --- /dev/null +++ b/packaging/macos/Info.plist.template @@ -0,0 +1,28 @@ + + + + + CFBundleName + Bpm Tray + CFBundleDisplayName + Bpm Tray + CFBundleIdentifier + uk.syscode-labs.bpm-tray + CFBundleExecutable + bpm-tray + CFBundleIconFile + AppIcon + CFBundlePackageType + APPL + CFBundleShortVersionString + VERSION_PLACEHOLDER + CFBundleVersion + VERSION_PLACEHOLDER + LSMinimumSystemVersion + 11.0 + LSUIElement + + NSHighResolutionCapable + + +