mirror of
https://github.com/Flowseal/tg-ws-proxy.git
synced 2026-06-23 23:11:08 +03:00
ci: add better view on macos installation (#1019)
This commit is contained in:
+30
-36
@@ -272,30 +272,10 @@ jobs:
|
||||
python3.12 -m pip install .
|
||||
python3.12 -m pip install pyinstaller==6.13.0
|
||||
|
||||
- name: Create macOS icon from ICO
|
||||
- name: Create macOS icon
|
||||
run: |
|
||||
set -euo pipefail
|
||||
python3.12 - <<'PY'
|
||||
from PIL import Image
|
||||
|
||||
image = Image.open('icon.ico')
|
||||
image = image.resize((1024, 1024), Image.LANCZOS)
|
||||
image.save('icon_1024.png', 'PNG')
|
||||
PY
|
||||
|
||||
mkdir -p icon.iconset
|
||||
sips -z 16 16 icon_1024.png --out icon.iconset/icon_16x16.png
|
||||
sips -z 32 32 icon_1024.png --out icon.iconset/icon_16x16@2x.png
|
||||
sips -z 32 32 icon_1024.png --out icon.iconset/icon_32x32.png
|
||||
sips -z 64 64 icon_1024.png --out icon.iconset/icon_32x32@2x.png
|
||||
sips -z 128 128 icon_1024.png --out icon.iconset/icon_128x128.png
|
||||
sips -z 256 256 icon_1024.png --out icon.iconset/icon_128x128@2x.png
|
||||
sips -z 256 256 icon_1024.png --out icon.iconset/icon_256x256.png
|
||||
sips -z 512 512 icon_1024.png --out icon.iconset/icon_256x256@2x.png
|
||||
sips -z 512 512 icon_1024.png --out icon.iconset/icon_512x512.png
|
||||
sips -z 1024 1024 icon_1024.png --out icon.iconset/icon_512x512@2x.png
|
||||
iconutil -c icns icon.iconset -o icon.icns
|
||||
rm -rf icon.iconset icon_1024.png
|
||||
python3.12 macos.py --render-app-icon icon.icns
|
||||
|
||||
- name: Build app with PyInstaller
|
||||
run: python3.12 -m PyInstaller packaging/macos.spec --noconfirm
|
||||
@@ -303,6 +283,11 @@ jobs:
|
||||
- name: Validate universal2 app bundle
|
||||
run: |
|
||||
set -euo pipefail
|
||||
ICON_FILE="$(/usr/libexec/PlistBuddy -c 'Print :CFBundleIconFile' \
|
||||
'dist/TG WS Proxy.app/Contents/Info.plist')"
|
||||
test -n "$ICON_FILE"
|
||||
test -f "dist/TG WS Proxy.app/Contents/Resources/$ICON_FILE"
|
||||
|
||||
found=0
|
||||
while IFS= read -r -d '' file; do
|
||||
if file "$file" | grep -q "Mach-O"; then
|
||||
@@ -326,22 +311,31 @@ jobs:
|
||||
- name: Create DMG
|
||||
run: |
|
||||
set -euo pipefail
|
||||
APP_NAME="TG WS Proxy"
|
||||
DMG_TEMP="dist/dmg_temp"
|
||||
|
||||
rm -rf "$DMG_TEMP"
|
||||
mkdir -p "$DMG_TEMP"
|
||||
cp -R "dist/${APP_NAME}.app" "$DMG_TEMP/"
|
||||
ln -s /Applications "$DMG_TEMP/Applications"
|
||||
|
||||
hdiutil create \
|
||||
-volname "$APP_NAME" \
|
||||
-srcfolder "$DMG_TEMP" \
|
||||
-ov \
|
||||
-format UDZO \
|
||||
packaging/dmg/build_dmg.sh \
|
||||
"dist/TG WS Proxy.app" \
|
||||
"TG WS Proxy" \
|
||||
"dist/TgWsProxy_macos_universal.dmg"
|
||||
|
||||
rm -rf "$DMG_TEMP"
|
||||
- name: Validate DMG
|
||||
run: |
|
||||
set -euo pipefail
|
||||
for DMG in "dist/TgWsProxy_macos_universal.dmg"; do
|
||||
MOUNT_DIR="$(mktemp -d)"
|
||||
DEVICE="$(hdiutil attach \
|
||||
-readonly \
|
||||
-nobrowse \
|
||||
-mountpoint "$MOUNT_DIR" \
|
||||
"$DMG" \
|
||||
| awk '/^\/dev\// { print $1; exit }')"
|
||||
|
||||
test -d "$MOUNT_DIR/TG WS Proxy.app"
|
||||
test -L "$MOUNT_DIR/Applications"
|
||||
test "$(readlink "$MOUNT_DIR/Applications")" = "/Applications"
|
||||
test -f "$MOUNT_DIR/.background/background.tiff"
|
||||
test -f "$MOUNT_DIR/.DS_Store"
|
||||
hdiutil detach "$DEVICE"
|
||||
rmdir "$MOUNT_DIR"
|
||||
done
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v7
|
||||
|
||||
@@ -9,16 +9,53 @@ import webbrowser
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
|
||||
try:
|
||||
import rumps
|
||||
except ImportError:
|
||||
rumps = None
|
||||
|
||||
try:
|
||||
from PIL import Image, ImageDraw, ImageFont
|
||||
except ImportError:
|
||||
Image = ImageDraw = ImageFont = None
|
||||
|
||||
|
||||
def render_app_icon(size: int):
|
||||
scale = size / 1024
|
||||
image = Image.new("RGBA", (size, size), (0, 0, 0, 0))
|
||||
draw = ImageDraw.Draw(image)
|
||||
outer = tuple(round(value * scale) for value in (92, 92, 932, 932))
|
||||
draw.ellipse(outer, fill=(0, 151, 221, 255))
|
||||
try:
|
||||
font = ImageFont.truetype(
|
||||
"/System/Library/Fonts/Helvetica.ttc",
|
||||
round(430 * scale),
|
||||
)
|
||||
except Exception:
|
||||
font = ImageFont.load_default()
|
||||
box = draw.textbbox((0, 0), "T", font=font)
|
||||
width = box[2] - box[0]
|
||||
height = box[3] - box[1]
|
||||
draw.text(
|
||||
(
|
||||
(size - width) / 2 - box[0],
|
||||
(size - height) / 2 - box[1] - round(10 * scale),
|
||||
),
|
||||
"T",
|
||||
font=font,
|
||||
fill=(255, 255, 255, 255),
|
||||
)
|
||||
return image
|
||||
|
||||
|
||||
if __name__ == "__main__" and len(sys.argv) > 1 and sys.argv[1] == "--render-app-icon":
|
||||
if Image is None:
|
||||
raise SystemExit("Pillow is required to render the macOS app icon")
|
||||
output_path = sys.argv[2] if len(sys.argv) > 2 else "icon.icns"
|
||||
render_app_icon(1024).save(output_path, format="ICNS")
|
||||
raise SystemExit(0)
|
||||
|
||||
|
||||
try:
|
||||
import rumps
|
||||
except ImportError:
|
||||
rumps = None
|
||||
|
||||
try:
|
||||
import pyperclip
|
||||
except ImportError:
|
||||
@@ -144,26 +181,10 @@ def _ask_cfworker_domain(default: str) -> Optional[str]:
|
||||
def _make_menubar_icon(size: int = 44):
|
||||
if Image is None:
|
||||
return None
|
||||
img = Image.new("RGBA", (size, size), (0, 0, 0, 0))
|
||||
draw = ImageDraw.Draw(img)
|
||||
margin = size // 11
|
||||
draw.ellipse([margin, margin, size - margin, size - margin], fill=(0, 0, 0, 255))
|
||||
try:
|
||||
font = ImageFont.truetype("/System/Library/Fonts/Helvetica.ttc", size=int(size * 0.55))
|
||||
except Exception:
|
||||
font = ImageFont.load_default()
|
||||
bbox = draw.textbbox((0, 0), "T", font=font)
|
||||
tw, th = bbox[2] - bbox[0], bbox[3] - bbox[1]
|
||||
draw.text(
|
||||
((size - tw) // 2 - bbox[0], (size - th) // 2 - bbox[1]),
|
||||
"T", fill=(255, 255, 255, 255), font=font,
|
||||
)
|
||||
return img
|
||||
return render_app_icon(size)
|
||||
|
||||
|
||||
def _ensure_menubar_icon() -> None:
|
||||
if MENUBAR_ICON_PATH.exists():
|
||||
return
|
||||
ensure_dirs()
|
||||
img = _make_menubar_icon(44)
|
||||
if img:
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 4.6 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 10 KiB |
Executable
+93
@@ -0,0 +1,93 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
APP_PATH="${1:?Usage: build_dmg.sh <App.app> <Volume Name> <output.dmg> [assets_dir]}"
|
||||
VOL_NAME="${2:?missing volume name}"
|
||||
OUT_DMG="${3:?missing output dmg path}"
|
||||
ASSETS_DIR="${4:-$(cd "$(dirname "${BASH_SOURCE[0]}")/assets" && pwd)}"
|
||||
|
||||
WIN_W=660
|
||||
WIN_H=440
|
||||
ICON_SIZE=128
|
||||
APP_X=145
|
||||
APPS_X=515
|
||||
ICON_Y=220
|
||||
|
||||
APP_NAME="$(basename "$APP_PATH")"
|
||||
WORK="$(mktemp -d)"
|
||||
STAGE="$WORK/stage"
|
||||
RW_DMG="$WORK/rw.dmg"
|
||||
MOUNT="/Volumes/$VOL_NAME"
|
||||
DEVICE=""
|
||||
|
||||
cleanup() {
|
||||
if [ -n "$DEVICE" ]; then
|
||||
hdiutil detach "$DEVICE" -force >/dev/null 2>&1 || true
|
||||
fi
|
||||
rm -rf "$WORK"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
mkdir -p "$STAGE/.background"
|
||||
cp -R "$APP_PATH" "$STAGE/"
|
||||
ln -s /Applications "$STAGE/Applications"
|
||||
|
||||
tiffutil -cathidpicheck \
|
||||
"$ASSETS_DIR/background-light.png" \
|
||||
"$ASSETS_DIR/background-light@2x.png" \
|
||||
-out "$STAGE/.background/background.tiff"
|
||||
|
||||
hdiutil create \
|
||||
-volname "$VOL_NAME" \
|
||||
-srcfolder "$STAGE" \
|
||||
-fs HFS+ \
|
||||
-format UDRW \
|
||||
-ov \
|
||||
"$RW_DMG"
|
||||
|
||||
DEVICE="$(hdiutil attach \
|
||||
-readwrite \
|
||||
-noverify \
|
||||
-noautoopen \
|
||||
-mountpoint "$MOUNT" \
|
||||
"$RW_DMG" \
|
||||
| awk '/^\/dev\// { print $1; exit }')"
|
||||
test -n "$DEVICE"
|
||||
test -d "$MOUNT/$APP_NAME"
|
||||
|
||||
sleep 2
|
||||
|
||||
osascript <<APPLESCRIPT
|
||||
tell application "Finder"
|
||||
tell disk "$VOL_NAME"
|
||||
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 the bounds of container window to {200, 140, 200 + $WIN_W, 140 + $WIN_H}
|
||||
set theViewOptions to the icon view options of container window
|
||||
set arrangement of theViewOptions to not arranged
|
||||
set icon size of theViewOptions to $ICON_SIZE
|
||||
set text size of theViewOptions to 13
|
||||
set background picture of theViewOptions to file ".background:background.tiff"
|
||||
set position of item "$APP_NAME" of container window to {$APP_X, $ICON_Y}
|
||||
set position of item "Applications" of container window to {$APPS_X, $ICON_Y}
|
||||
close
|
||||
open
|
||||
update
|
||||
delay 2
|
||||
end tell
|
||||
end tell
|
||||
APPLESCRIPT
|
||||
|
||||
SetFile -a C "$MOUNT" 2>/dev/null || true
|
||||
sync
|
||||
|
||||
hdiutil detach "$DEVICE" -force >/dev/null 2>&1 \
|
||||
|| { sleep 3; hdiutil detach "$DEVICE" -force; }
|
||||
DEVICE=""
|
||||
|
||||
rm -f "$OUT_DMG"
|
||||
hdiutil convert "$RW_DMG" -format UDZO -imagekey zlib-level=9 -ov -o "$OUT_DMG"
|
||||
|
||||
echo "Created $OUT_DMG"
|
||||
Reference in New Issue
Block a user