diff --git a/apps/studio/assets/dmg-background.svg b/apps/studio/assets/dmg-background.svg new file mode 100644 index 0000000..8ceefd0 --- /dev/null +++ b/apps/studio/assets/dmg-background.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + Install ScreenForge + Drag the app into your Applications folder + + + screenforge.studio + diff --git a/apps/studio/assets/dmg-background.tiff b/apps/studio/assets/dmg-background.tiff new file mode 100644 index 0000000..182a97a Binary files /dev/null and b/apps/studio/assets/dmg-background.tiff differ diff --git a/apps/studio/assets/icon-1024.png b/apps/studio/assets/icon-1024.png index c46a8df..35acec5 100644 Binary files a/apps/studio/assets/icon-1024.png and b/apps/studio/assets/icon-1024.png differ diff --git a/apps/studio/assets/icon-256.png b/apps/studio/assets/icon-256.png index b243609..a68b111 100644 Binary files a/apps/studio/assets/icon-256.png and b/apps/studio/assets/icon-256.png differ diff --git a/apps/studio/assets/icon-512.png b/apps/studio/assets/icon-512.png index 75256f7..bf80225 100644 Binary files a/apps/studio/assets/icon-512.png and b/apps/studio/assets/icon-512.png differ diff --git a/apps/studio/assets/icon-tile-256.png b/apps/studio/assets/icon-tile-256.png new file mode 100644 index 0000000..c046985 Binary files /dev/null and b/apps/studio/assets/icon-tile-256.png differ diff --git a/apps/studio/assets/icon.icns b/apps/studio/assets/icon.icns index 6cb926e..c0f7407 100644 Binary files a/apps/studio/assets/icon.icns and b/apps/studio/assets/icon.icns differ diff --git a/apps/studio/assets/icon.ico b/apps/studio/assets/icon.ico index 7a5adf8..b9af402 100644 Binary files a/apps/studio/assets/icon.ico and b/apps/studio/assets/icon.ico differ diff --git a/apps/studio/assets/icon.svg b/apps/studio/assets/icon.svg index 26d4625..fab7b73 100644 --- a/apps/studio/assets/icon.svg +++ b/apps/studio/assets/icon.svg @@ -23,8 +23,9 @@ - - + + + diff --git a/apps/studio/assets/installer/small-110.bmp b/apps/studio/assets/installer/small-110.bmp index 0fc59a4..db3bfea 100644 Binary files a/apps/studio/assets/installer/small-110.bmp and b/apps/studio/assets/installer/small-110.bmp differ diff --git a/apps/studio/assets/installer/small-55.bmp b/apps/studio/assets/installer/small-55.bmp index c54d2ec..2cd04b6 100644 Binary files a/apps/studio/assets/installer/small-55.bmp and b/apps/studio/assets/installer/small-55.bmp differ diff --git a/apps/studio/assets/installer/small-83.bmp b/apps/studio/assets/installer/small-83.bmp index 7c6f1ca..61fa09d 100644 Binary files a/apps/studio/assets/installer/small-83.bmp and b/apps/studio/assets/installer/small-83.bmp differ diff --git a/apps/studio/assets/installer/wizard-164.bmp b/apps/studio/assets/installer/wizard-164.bmp index 37f0dcc..a3a7687 100644 Binary files a/apps/studio/assets/installer/wizard-164.bmp and b/apps/studio/assets/installer/wizard-164.bmp differ diff --git a/apps/studio/assets/installer/wizard-246.bmp b/apps/studio/assets/installer/wizard-246.bmp index e2ae8d6..9dcb450 100644 Binary files a/apps/studio/assets/installer/wizard-246.bmp and b/apps/studio/assets/installer/wizard-246.bmp differ diff --git a/apps/studio/assets/installer/wizard-328.bmp b/apps/studio/assets/installer/wizard-328.bmp index 0528f26..c68e9c0 100644 Binary files a/apps/studio/assets/installer/wizard-328.bmp and b/apps/studio/assets/installer/wizard-328.bmp differ diff --git a/apps/studio/src/main.rs b/apps/studio/src/main.rs index b747145..abe6972 100644 --- a/apps/studio/src/main.rs +++ b/apps/studio/src/main.rs @@ -52,6 +52,13 @@ fn main() -> eframe::Result { sf_recording::clock::init(); tracing_subscriber::fmt().with_env_filter(tracing_subscriber::EnvFilter::from_default_env()).init(); open_docs::install(); + // macOS: an empty icon keeps the bundle's icon.icns in the Dock; setting one would swap it for a + // single 256 px raster. Windows uses the shadowless tile that icon.ico is built from. + #[cfg(target_os = "macos")] + let icon = egui::IconData::default(); + #[cfg(target_os = "windows")] + let icon = eframe::icon_data::from_png_bytes(include_bytes!("../assets/icon-tile-256.png")).expect("app icon"); + #[cfg(not(any(target_os = "macos", target_os = "windows")))] let icon = eframe::icon_data::from_png_bytes(include_bytes!("../assets/icon-256.png")).expect("app icon"); let options = eframe::NativeOptions { viewport: egui::ViewportBuilder::default() diff --git a/apps/studio/src/tray.rs b/apps/studio/src/tray.rs index 51e4d2c..6fe4fdf 100644 --- a/apps/studio/src/tray.rs +++ b/apps/studio/src/tray.rs @@ -83,7 +83,7 @@ mod windows_tray { use tray_icon::{Icon, TrayIcon, TrayIconBuilder}; pub fn create(menu: &muda::Menu) -> Option { - let img = image::load_from_memory(include_bytes!("../assets/icon-256.png")).ok()?.resize_exact(32, 32, image::imageops::FilterType::Lanczos3).to_rgba8(); + let img = image::load_from_memory(include_bytes!("../assets/icon-tile-256.png")).ok()?.resize_exact(32, 32, image::imageops::FilterType::Lanczos3).to_rgba8(); let (w, h) = img.dimensions(); let icon = Icon::from_rgba(img.into_raw(), w, h).ok()?; TrayIconBuilder::new().with_menu(Box::new(menu.clone())).with_tooltip("ScreenForge").with_icon(icon).build().ok() diff --git a/scripts/dmg.sh b/scripts/dmg.sh index 50d2463..5dc5878 100755 --- a/scripts/dmg.sh +++ b/scripts/dmg.sh @@ -8,6 +8,54 @@ STAGE=target/dmg-stage rm -rf "$STAGE" "$OUT"; mkdir -p "$STAGE" cp -R target/ScreenForge.app "$STAGE/" ln -s /Applications "$STAGE/Applications" -hdiutil create -volname "ScreenForge" -srcfolder "$STAGE" -ov -format UDZO "$OUT" >/dev/null +RW=target/dmg-rw.dmg +rm -f "$RW" +hdiutil create -volname "ScreenForge" -srcfolder "$STAGE" -ov -format UDRW "$RW" >/dev/null + +# window layout (background, icon positions) is stored in the volume's .DS_Store, which only Finder +# writes, so mount where Finder can see it and script it. A failure here (no Finder session) leaves +# a plain but working DMG. +VOL=/Volumes/ScreenForge +[ -d "$VOL" ] && hdiutil detach "$VOL" -force >/dev/null 2>&1 || true +hdiutil attach "$RW" -noautoopen >/dev/null +mkdir "$VOL/.background" && cp apps/studio/assets/dmg-background.tiff "$VOL/.background/background.tiff" +# Finder needs a moment to see a freshly attached disk +LAYOUT=$(cat <<'OSA' +tell application "Finder" + tell disk "ScreenForge" + open + set current view of container window to icon view + set toolbar visible of container window to false + set statusbar visible of container window to false + set bounds of container window to {200, 120, 760, 508} + set opts to icon view options of container window + set arrangement of opts to not arranged + set icon size of opts to 112 + set text size of opts to 12 + set background picture of opts to file ".background:background.tiff" + set position of item "ScreenForge.app" to {150, 190} + set position of item "Applications" to {410, 190} + close + open + update without registering applications + delay 1 + close + end tell +end tell +OSA +) +for try in 1 2 3 4 5; do + if osascript -e "$LAYOUT" >/dev/null 2>&1; then break; fi + [ $try = 5 ] && echo "warning: could not lay out the DMG window" >&2 || sleep 2 +done +# volume icon: .VolumeIcon.icns plus the custom-icon flag on the root. Done after the Finder step, +# because Finder removes both when it saves the window layout. +cp apps/studio/assets/icon.icns "$VOL/.VolumeIcon.icns" +SetFile -a V "$VOL/.VolumeIcon.icns" +SetFile -a C "$VOL" +sync +hdiutil detach "$VOL" >/dev/null || { sleep 2; hdiutil detach "$VOL" -force >/dev/null; } +hdiutil convert "$RW" -format UDZO -o "$OUT" >/dev/null +rm -f "$RW" if [ -n "$CODESIGN_IDENTITY" ]; then codesign --force --timestamp --sign "$CODESIGN_IDENTITY" "$OUT"; fi echo "$OUT" diff --git a/scripts/gen-icons.sh b/scripts/gen-icons.sh new file mode 100755 index 0000000..1bdf3f3 --- /dev/null +++ b/scripts/gen-icons.sh @@ -0,0 +1,48 @@ +#!/bin/sh +# Render every app icon asset from apps/studio/assets/icon.svg (needs rsvg-convert and ImageMagick). +# icon-{256,512,1024}.png macOS-style tile with margin and drop shadow +# icon.icns each size rendered from the vector, not downscaled from 1024 +# icon-tile-256.png Windows window/tray icon (same tile as icon.ico) +# icon.ico Windows: no drop shadow, tile fills the frame, 16..256 px frames +# installer/*.bmp Inno Setup wizard panel and header images +# dmg-background.tiff DMG window background, 1x + 2x (from dmg-background.svg) +set -e +cd "$(dirname "$0")/../apps/studio/assets" +TMP=$(mktemp -d); trap 'rm -rf "$TMP"' EXIT + +render() { rsvg-convert -w "$2" -h "$2" "$1" -o "$3"; } + +# Windows/installer variant: drop the shadow and crop to the tile (small margin for antialiasing) +sed -e '/filter="url(#shadow)"/d' -e 's/viewBox="0 0 1024 1024"/viewBox="88 88 848 848"/' icon.svg > "$TMP/tile.svg" + +for s in 256 512 1024; do render icon.svg $s icon-$s.png; done + +mkdir "$TMP/icon.iconset" +for s in 16 32 128 256 512; do + render icon.svg $s "$TMP/icon.iconset/icon_${s}x${s}.png" + render icon.svg $((s * 2)) "$TMP/icon.iconset/icon_${s}x${s}@2x.png" +done +iconutil -c icns "$TMP/icon.iconset" -o icon.icns + +ICO="" +for s in 16 20 24 32 40 48 64 96 128 256; do render "$TMP/tile.svg" $s "$TMP/ico-$s.png"; ICO="$ICO $TMP/ico-$s.png"; done +# shellcheck disable=SC2086 +magick $ICO icon.ico +cp "$TMP/ico-256.png" icon-tile-256.png + +# Inno Setup: 24-bit BMPs. Wizard panel = dark backdrop with the tile; header = tile on white. +render "$TMP/tile.svg" 1024 "$TMP/tile-1024.png" +for wh in 164x314 246x459 328x628; do + w=${wh%x*}; h=${wh#*x}; t=$((w * 46 / 100)) + magick -size ${w}x${h} 'xc:rgb(23,22,37)' \( "$TMP/tile-1024.png" -resize ${t}x${t} \) -gravity center -composite \ + -type TrueColor BMP3:installer/wizard-$w.bmp +done +for w in 55 83 110; do + t=$((w * 84 / 100)) + magick -size ${w}x${w} xc:white \( "$TMP/tile-1024.png" -resize ${t}x${t} \) -gravity center -composite \ + -type TrueColor BMP3:installer/small-$w.bmp +done +rsvg-convert -w 560 -h 360 dmg-background.svg -o "$TMP/bg.png" +rsvg-convert -w 1120 -h 720 dmg-background.svg -o "$TMP/bg@2x.png" +tiffutil -cathidpicheck "$TMP/bg.png" "$TMP/bg@2x.png" -out dmg-background.tiff >/dev/null 2>&1 +echo "icons regenerated in $(pwd)"