diff --git a/desktop/src/assets/tray-icon.png b/desktop/src/assets/tray-icon.png index 8b84ff0e..78e56673 100644 Binary files a/desktop/src/assets/tray-icon.png and b/desktop/src/assets/tray-icon.png differ diff --git a/desktop/src/build/Taskfile.yml b/desktop/src/build/Taskfile.yml index 7a364e87..dd940c7c 100644 --- a/desktop/src/build/Taskfile.yml +++ b/desktop/src/build/Taskfile.yml @@ -26,20 +26,44 @@ tasks: - echo "skip generate bindings" generate:icons: - summary: Generates .ico from appicon.png and .icns from appicon-macos.png + summary: Generates .ico from appicon.png dir: build sources: - appicon.png - - appicon-macos.png generates: - - darwin/icons.icns - windows/icon.ico cmds: # Windows / Linux keep the full-bleed artwork. - wails3 generate icons -input appicon.png -windowsfilename windows/icon.ico -macfilename "" + + generate:icons:darwin: + summary: Generates .icns from appicon-macos.png via sips + iconutil + dir: build + sources: + - appicon-macos.png + generates: + - darwin/icons.icns + cmds: # macOS expects 824x824 artwork on a 1024x1024 canvas; a full-bleed tile # renders ~24% larger than every other app in the Dock and Launchpad. - - wails3 generate icons -input appicon-macos.png -macfilename darwin/icons.icns -windowsfilename "" + # + # sips downsamples through Core Graphics. wails3's encoder resizes with + # Mitchell-Netravali, which rings on the logo's high-contrast edges and + # leaves stray pixels in the 32/64/128 layers. + - | + set -euo pipefail + work="$(mktemp -d "${TMPDIR:-/tmp}/octop-iconset.XXXXXX")" + trap 'rm -rf "$work"' EXIT + iconset="${work}/AppIcon.iconset" + mkdir -p "$iconset" + for spec in 16:icon_16x16 32:icon_16x16@2x 32:icon_32x32 64:icon_32x32@2x \ + 128:icon_128x128 256:icon_128x128@2x 256:icon_256x256 \ + 512:icon_256x256@2x 512:icon_512x512 1024:icon_512x512@2x; do + px="${spec%%:*}" + sips -s format png -z "$px" "$px" appicon-macos.png \ + --out "${iconset}/${spec#*:}.png" >/dev/null + done + iconutil -c icns "$iconset" -o darwin/icons.icns dev:frontend: summary: Serves the embedded shell assets for Wails dev mode diff --git a/desktop/src/build/appicon-macos.png b/desktop/src/build/appicon-macos.png index c3f8aa59..dba75dcf 100644 Binary files a/desktop/src/build/appicon-macos.png and b/desktop/src/build/appicon-macos.png differ diff --git a/desktop/src/build/appicon.png b/desktop/src/build/appicon.png index 06a52b88..440be2f6 100644 Binary files a/desktop/src/build/appicon.png and b/desktop/src/build/appicon.png differ diff --git a/desktop/src/build/darwin/Taskfile.yml b/desktop/src/build/darwin/Taskfile.yml index a9d69adb..175cd63c 100644 --- a/desktop/src/build/darwin/Taskfile.yml +++ b/desktop/src/build/darwin/Taskfile.yml @@ -9,7 +9,7 @@ tasks: deps: - task: common:go:mod:tidy - task: common:build:frontend - - task: common:generate:icons + - task: common:generate:icons:darwin cmds: - go build {{.BUILD_FLAGS}} -o {{.OUTPUT}} vars: @@ -59,6 +59,23 @@ tasks: done hdiutil detach "$dev" -force -quiet >/dev/null 2>&1 } + # create/convert hit "Resource busy" on CI while background scanners still + # hold the freshly staged bundle. Retry; the last attempt stays unmuted so + # a genuine failure keeps hdiutil's diagnostics. + retry_hdiutil() { + local out="$1" attempt + shift + for attempt in 1 2 3 4; do + sync + if hdiutil "$@" >/dev/null 2>&1; then + return 0 + fi + rm -f "$out" + sleep $((attempt * 5)) + done + sync + hdiutil "$@" + } cleanup() { if [[ -n "$device" ]]; then detach_device "$device" || true @@ -77,13 +94,14 @@ tasks: hdiutil detach "/Volumes/${volname}" -quiet >/dev/null 2>&1 || \ hdiutil detach "/Volumes/${volname}" -force -quiet >/dev/null 2>&1 || true fi - hdiutil create -volname "$volname" -srcfolder "$staging" -ov -format UDRW "$rw_dmg" >/dev/null + retry_hdiutil "$rw_dmg" create -volname "$volname" -srcfolder "$staging" -ov -format UDRW "$rw_dmg" attach_out="$(hdiutil attach -readwrite -noverify -noautoopen "$rw_dmg" || true)" device="$(awk '/^\/dev\// { print $1; exit }' <<<"$attach_out")" mount_point="$(awk -F'\t' '/\/Volumes\// { print $NF; exit }' <<<"$attach_out")" if [[ -z "$device" || ! -d "$mount_point" ]]; then echo "warning: could not mount writable DMG; writing a plain image" >&2 - hdiutil create -volname "$volname" -srcfolder "$staging" -ov -format UDRO "$output" + retry_hdiutil "$output" create -volname "$volname" -srcfolder "$staging" -ov -format UDRO "$output" + test -s "$output" exit 0 fi osascript - "$volname" "$app_name" <<'APPLESCRIPT' || \ @@ -118,13 +136,13 @@ tasks: if ! detach_device "$device"; then echo "warning: could not detach ${device}; writing a plain image" >&2 device="" - hdiutil create -volname "$volname" -srcfolder "$staging" -ov -format UDRO "$output" >/dev/null + retry_hdiutil "$output" create -volname "$volname" -srcfolder "$staging" -ov -format UDRO "$output" test -s "$output" exit 0 fi device="" rm -f "$output" - hdiutil convert "$rw_dmg" -ov -format UDRO -o "$output" >/dev/null + retry_hdiutil "$output" convert "$rw_dmg" -ov -format UDRO -o "$output" test -s "$output" vars: ARCH: "{{.ARCH | default ARCH}}"