- Add QR generation of the currently playing URL (macOS window / iOS sheet) - Encode channel metadata (name/type/group/logo) in the QR payload as compact JSON; fall back to a plain URL when the payload is too long for a reliably scannable QR - Scanning saves the entry into the local library with its channel metadata and starts playback; legacy plain-URL QR codes still work - Add iOS QR scanner sheet (AVCaptureMetadataOutput) so scanning is no longer macOS-only; both scanners share handleScannedCode - Add optional channel name / group fields to the Add URL dialog and thread group/logo through addURL/addItem into the library - Restore session (queue + position) on launch and save on quit for macOS, not just iOS - Bundle app icons: generate AppIcon.icns from the macOS iconset when missing, and compile Assets.xcassets into the iOS app
171 lines
5.8 KiB
Bash
Executable File
171 lines
5.8 KiB
Bash
Executable File
#!/bin/bash
|
||
# ========================================
|
||
# MiniPlayer macOS 打包脚本
|
||
# 生成 .app bundle + .dmg 安装包
|
||
# ========================================
|
||
set -e
|
||
|
||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||
PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||
BUILD_DIR="$PROJECT_DIR/.build/release"
|
||
APP_NAME="MiniPlayer"
|
||
BUNDLE_ID="com.miniplayer.app"
|
||
VERSION=$(date +%Y.%m.%d)
|
||
|
||
APP_BUNDLE="$PROJECT_DIR/$APP_NAME.app"
|
||
DMG_OUTPUT="$PROJECT_DIR/$APP_NAME-$VERSION.dmg"
|
||
|
||
echo "=== MiniPlayer macOS 打包 ==="
|
||
echo "项目目录: $PROJECT_DIR"
|
||
echo "版本: $VERSION"
|
||
echo ""
|
||
|
||
# 1. 清理旧构建
|
||
echo "[1/6] 清理旧构建..."
|
||
rm -rf "$APP_BUNDLE"
|
||
rm -f "$DMG_OUTPUT"
|
||
|
||
# 2. 编译 Release
|
||
echo "[2/6] 编译 Release 版本..."
|
||
cd "$PROJECT_DIR"
|
||
swift build -c release
|
||
echo " ✓ 编译完成"
|
||
|
||
# 3. 创建 .app bundle 结构
|
||
echo "[3/6] 创建 .app bundle..."
|
||
mkdir -p "$APP_BUNDLE/Contents/MacOS"
|
||
mkdir -p "$APP_BUNDLE/Contents/Resources/i18n"
|
||
mkdir -p "$APP_BUNDLE/Contents/Resources/zh-Hans.lproj"
|
||
mkdir -p "$APP_BUNDLE/Contents/Resources/en.lproj"
|
||
|
||
# 4. 拷贝文件
|
||
echo "[4/6] 拷贝文件..."
|
||
# 可执行文件
|
||
cp "$BUILD_DIR/$APP_NAME" "$APP_BUNDLE/Contents/MacOS/"
|
||
|
||
# 资源文件
|
||
cp "$PROJECT_DIR/Sources/Resources/miniplayer.ui" "$APP_BUNDLE/Contents/Resources/"
|
||
cp "$PROJECT_DIR/Sources/Resources/i18n/en.json" "$APP_BUNDLE/Contents/Resources/i18n/"
|
||
cp "$PROJECT_DIR/Sources/Resources/i18n/zh.json" "$APP_BUNDLE/Contents/Resources/i18n/"
|
||
cp "$PROJECT_DIR/Sources/Resources/zh-Hans.lproj/Localizable.strings" "$APP_BUNDLE/Contents/Resources/zh-Hans.lproj/"
|
||
cp "$PROJECT_DIR/Sources/Resources/en.lproj/Localizable.strings" "$APP_BUNDLE/Contents/Resources/en.lproj/"
|
||
|
||
# App 图标:若缺 .icns 则从 iconset 自动生成
|
||
if [ ! -f "$PROJECT_DIR/Resources/AppIcon.icns" ] && [ -d "$PROJECT_DIR/Icons_macOS/MiniPlayer.appiconset" ]; then
|
||
echo " → 生成 AppIcon.icns..."
|
||
ICONSET_SRC="$PROJECT_DIR/Icons_macOS/MiniPlayer.appiconset"
|
||
ICONSET_TMP="$(mktemp -d)/AppIcon.iconset"
|
||
mkdir -p "$ICONSET_TMP"
|
||
cp "$ICONSET_SRC/icon_16.png" "$ICONSET_TMP/icon_16x16.png"
|
||
cp "$ICONSET_SRC/icon_16@2x.png" "$ICONSET_TMP/icon_16x16@2x.png"
|
||
cp "$ICONSET_SRC/icon_32.png" "$ICONSET_TMP/icon_32x32.png"
|
||
cp "$ICONSET_SRC/icon_32@2x.png" "$ICONSET_TMP/icon_32x32@2x.png"
|
||
cp "$ICONSET_SRC/icon_128.png" "$ICONSET_TMP/icon_128x128.png"
|
||
cp "$ICONSET_SRC/icon_128@2x.png" "$ICONSET_TMP/icon_128x128@2x.png"
|
||
cp "$ICONSET_SRC/icon_256.png" "$ICONSET_TMP/icon_256x256.png"
|
||
cp "$ICONSET_SRC/icon_256@2x.png" "$ICONSET_TMP/icon_256x256@2x.png"
|
||
cp "$ICONSET_SRC/icon_512.png" "$ICONSET_TMP/icon_512x512.png"
|
||
cp "$ICONSET_SRC/icon_512@2x.png" "$ICONSET_TMP/icon_512x512@2x.png"
|
||
mkdir -p "$PROJECT_DIR/Resources"
|
||
iconutil -c icns "$ICONSET_TMP" -o "$PROJECT_DIR/Resources/AppIcon.icns" 2>/dev/null || true
|
||
rm -rf "$(dirname "$ICONSET_TMP")"
|
||
fi
|
||
|
||
if [ -f "$PROJECT_DIR/Resources/AppIcon.icns" ]; then
|
||
cp "$PROJECT_DIR/Resources/AppIcon.icns" "$APP_BUNDLE/Contents/Resources/"
|
||
ICON_FILE="AppIcon.icns"
|
||
else
|
||
echo " ⚠ 未找到/无法生成 AppIcon.icns,应用将没有图标"
|
||
ICON_FILE=""
|
||
fi
|
||
|
||
# 5. 生成 Info.plist
|
||
echo "[5/6] 生成 Info.plist..."
|
||
cat > "$APP_BUNDLE/Contents/Info.plist" <<PLIST
|
||
<?xml version="1.0" encoding="UTF-8"?>
|
||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||
<plist version="1.0">
|
||
<dict>
|
||
<key>CFBundleExecutable</key>
|
||
<string>$APP_NAME</string>
|
||
<key>CFBundleIdentifier</key>
|
||
<string>$BUNDLE_ID</string>
|
||
<key>CFBundleName</key>
|
||
<string>$APP_NAME</string>
|
||
<key>CFBundleDisplayName</key>
|
||
<string>MiniPlayer</string>
|
||
<key>CFBundleVersion</key>
|
||
<string>$VERSION</string>
|
||
<key>CFBundleShortVersionString</key>
|
||
<string>$VERSION</string>
|
||
<key>CFBundlePackageType</key>
|
||
<string>APPL</string>
|
||
<key>CFBundleInfoDictionaryVersion</key>
|
||
<string>6.0</string>
|
||
<key>LSMinimumSystemVersion</key>
|
||
<string>14.0</string>
|
||
<key>NSHighResolutionCapable</key>
|
||
<true/>
|
||
<key>LSApplicationCategoryType</key>
|
||
<string>public.app-category.entertainment</string>
|
||
<key>NSHumanReadableCopyright</key>
|
||
<string>Copyright © $(date +%Y) MiniPlayer. All rights reserved.</string>
|
||
<key>CFBundleIconFile</key>
|
||
<string>${ICON_FILE:-}</string>
|
||
<key>CFBundleResourceSpecification</key>
|
||
<string></string>
|
||
<key>NSSupportsAutomaticTermination</key>
|
||
<true/>
|
||
<key>NSSupportsSuddenTermination</key>
|
||
<false/>
|
||
<key>NSCameraUsageDescription</key>
|
||
<string>MiniPlayer 需要摄像头权限来扫描二维码添加播放地址。</string>
|
||
<key>NSMicrophoneUsageDescription</key>
|
||
<string>MiniPlayer 需要麦克风权限来录制音频。</string>
|
||
</dict>
|
||
</plist>
|
||
PLIST
|
||
|
||
echo " ✓ .app bundle 创建完成: $APP_BUNDLE"
|
||
|
||
# 6. 创建 DMG
|
||
echo "[6/6] 创建 DMG 安装包..."
|
||
DMG_TEMP="$PROJECT_DIR/.dmg_temp"
|
||
DMG_RW="$PROJECT_DIR/.dmg_rw.dmg"
|
||
DMG_SIZE="200m"
|
||
|
||
mkdir -p "$DMG_TEMP"
|
||
cp -R "$APP_BUNDLE" "$DMG_TEMP/"
|
||
|
||
# 创建 Applications 快捷方式
|
||
ln -s /Applications "$DMG_TEMP/Applications"
|
||
|
||
# 创建临时 DMG
|
||
hdiutil create -srcfolder "$DMG_TEMP" -volname "$APP_NAME" \
|
||
-fs HFS+ -fsargs "-c c=64,a=16,e=16" \
|
||
-format UDRW -size "$DMG_SIZE" "$DMG_RW" 2>/dev/null
|
||
|
||
# 转换为压缩 DMG
|
||
hdiutil convert "$DMG_RW" -format UDZO -imagekey zlib-level=9 -o "$DMG_OUTPUT" 2>/dev/null
|
||
|
||
# 清理临时文件
|
||
rm -rf "$DMG_TEMP"
|
||
rm -f "$DMG_RW"
|
||
|
||
echo " ✓ DMG 创建完成: $DMG_OUTPUT"
|
||
|
||
# 显示结果
|
||
echo ""
|
||
echo "=============================="
|
||
echo " 打包完成!"
|
||
echo "=============================="
|
||
echo " .app: $APP_BUNDLE"
|
||
echo " .dmg: $DMG_OUTPUT"
|
||
APP_SIZE=$(du -sh "$APP_BUNDLE" | cut -f1)
|
||
DMG_SIZE=$(du -sh "$DMG_OUTPUT" | cut -f1)
|
||
echo " .app 大小: $APP_SIZE"
|
||
echo " .dmg 大小: $DMG_SIZE"
|
||
echo ""
|
||
echo " 双击 .app 直接运行"
|
||
echo " 双击 .dmg 安装(拖入 Applications)"
|