MiniPlayer/scripts/build-macos.sh
yumoqing dd64a21404 feat: QR code for current media with channel info, cross-platform
- 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
2026-10-04 12:07:00 +08:00

171 lines
5.8 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/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)"