## 当前状态 - 插件界面已完成重命名 (cursorpro → hummingbird) - 双账号池 UI 已实现 (Auto/Pro 卡片) - 后端已切换到 MySQL 数据库 - 添加了 Cursor 官方用量 API 文档 ## 已知问题 (待修复) 1. 激活时检查账号导致无账号时激活失败 2. 未启用无感换号时不应获取账号 3. 账号用量模块不显示 (seamless 未启用时应隐藏) 4. 积分显示为 0 (后端未正确返回) 5. Auto/Pro 双密钥逻辑混乱,状态不同步 6. 账号添加后无自动分析功能 ## 下一版本计划 - 重构数据模型,优化账号状态管理 - 实现 Cursor API 自动分析账号 - 修复激活流程,不依赖账号 - 启用无感时才分配账号 - 完善账号用量实时显示 ## 文件说明 - docs/系统设计文档.md - 完整架构设计 - cursor 官方用量接口.md - Cursor API 文档 - 参考计费/ - Vibeviewer 开源项目参考 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
190 lines
6.3 KiB
Bash
190 lines
6.3 KiB
Bash
#!/bin/bash
|
|
set -e
|
|
|
|
# Configuration
|
|
APP_NAME="Vibeviewer"
|
|
CONFIGURATION="Release"
|
|
SCHEME="Vibeviewer"
|
|
WORKSPACE="Vibeviewer.xcworkspace"
|
|
BUILD_DIR="build"
|
|
TEMP_DIR="temp_dmg"
|
|
BACKGROUND_IMAGE_NAME="dmg_background.png"
|
|
|
|
# Script directory
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
|
|
# Parse command line arguments
|
|
VERSION=""
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case $1 in
|
|
--version|-v)
|
|
VERSION="$2"
|
|
shift 2
|
|
;;
|
|
--help|-h)
|
|
echo "用法: $0 [选项]"
|
|
echo ""
|
|
echo "选项:"
|
|
echo " --version, -v <版本> 指定版本号(默认从应用 Info.plist 读取)"
|
|
echo " --help, -h 显示此帮助信息"
|
|
echo ""
|
|
echo "示例:"
|
|
echo " $0 # 仅创建 DMG"
|
|
echo " $0 -v 1.1.9 # 指定版本创建 DMG"
|
|
exit 0
|
|
;;
|
|
*)
|
|
echo "未知选项: $1"
|
|
echo "使用 --help 查看帮助信息"
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# Colors
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[0;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m' # No Color
|
|
|
|
echo -e "${BLUE}🚀 Starting DMG creation process for ${APP_NAME}...${NC}"
|
|
|
|
# Clean up previous builds
|
|
echo -e "${YELLOW}📦 Cleaning up previous builds...${NC}"
|
|
rm -rf "${BUILD_DIR}"
|
|
rm -rf "${TEMP_DIR}"
|
|
# Note: DMG_NAME will be set after version detection, so we clean up old DMGs separately
|
|
rm -f "${APP_NAME}"-*.dmg
|
|
|
|
# Build the app
|
|
echo -e "${BLUE}🔨 Building ${APP_NAME} in ${CONFIGURATION} configuration...${NC}"
|
|
xcodebuild -workspace "${WORKSPACE}" \
|
|
-scheme "${SCHEME}" \
|
|
-configuration "${CONFIGURATION}" \
|
|
-derivedDataPath "${BUILD_DIR}" \
|
|
-destination "platform=macOS" \
|
|
-skipMacroValidation \
|
|
clean build
|
|
|
|
# Find the built app
|
|
APP_PATH=$(find "${BUILD_DIR}" -name "${APP_NAME}.app" -type d | head -1)
|
|
if [ -z "$APP_PATH" ]; then
|
|
echo -e "${RED}❌ Error: Could not find ${APP_NAME}.app in build output${NC}"
|
|
exit 1
|
|
fi
|
|
|
|
echo -e "${GREEN}✅ Found app at: ${APP_PATH}${NC}"
|
|
|
|
# 验证 app 的版本信息和代码签名
|
|
echo -e "${BLUE}🔍 验证 app 信息...${NC}"
|
|
INFO_PLIST="${APP_PATH}/Contents/Info.plist"
|
|
if [ -f "$INFO_PLIST" ]; then
|
|
APP_VERSION=$(/usr/libexec/PlistBuddy -c "Print :CFBundleShortVersionString" "$INFO_PLIST" 2>/dev/null || echo "")
|
|
APP_BUILD=$(/usr/libexec/PlistBuddy -c "Print :CFBundleVersion" "$INFO_PLIST" 2>/dev/null || echo "")
|
|
echo -e " 版本: ${APP_VERSION}"
|
|
echo -e " Build: ${APP_BUILD}"
|
|
|
|
# 检查代码签名
|
|
if codesign -dv "${APP_PATH}" 2>&1 | grep -q "code object is not signed"; then
|
|
echo -e "${YELLOW}⚠️ 警告: App 未签名或签名无效${NC}"
|
|
else
|
|
SIGNING_IDENTITY=$(codesign -dv "${APP_PATH}" 2>&1 | grep "Authority=" | head -1 | sed 's/.*Authority=\(.*\)/\1/' || echo "未知")
|
|
echo -e " 签名: ${SIGNING_IDENTITY}"
|
|
|
|
# 检查签名是否有效
|
|
if ! codesign --verify --verbose "${APP_PATH}" 2>&1 | grep -q "valid on disk"; then
|
|
echo -e "${YELLOW}⚠️ 警告: 代码签名验证失败${NC}"
|
|
fi
|
|
fi
|
|
else
|
|
echo -e "${YELLOW}⚠️ 警告: 找不到 Info.plist${NC}"
|
|
fi
|
|
|
|
# Get version from Project.swift first (single source of truth), then from built app
|
|
if [ -z "$VERSION" ]; then
|
|
# 优先从 Project.swift 读取版本号(统一版本号配置)
|
|
if [ -f "${PROJECT_ROOT}/Project.swift" ]; then
|
|
VERSION=$(grep -E '^let appVersion\s*=' "${PROJECT_ROOT}/Project.swift" | sed -E 's/.*"([0-9]+\.[0-9]+\.[0-9]+)".*/\1/' | head -1)
|
|
fi
|
|
|
|
# Fallback: 从构建后的应用读取版本号
|
|
if [ -z "$VERSION" ]; then
|
|
INFO_PLIST="${APP_PATH}/Contents/Info.plist"
|
|
if [ -f "$INFO_PLIST" ]; then
|
|
VERSION=$(/usr/libexec/PlistBuddy -c "Print :CFBundleShortVersionString" "$INFO_PLIST" 2>/dev/null || echo "")
|
|
fi
|
|
fi
|
|
|
|
# Final fallback
|
|
if [ -z "$VERSION" ]; then
|
|
echo -e "${YELLOW}⚠️ 无法自动获取版本号,使用默认值 1.1.8${NC}"
|
|
echo -e "${YELLOW} 提示: 使用 --version 参数指定版本号${NC}"
|
|
VERSION="1.1.8"
|
|
fi
|
|
fi
|
|
|
|
DMG_NAME="${APP_NAME}-${VERSION}.dmg"
|
|
echo -e "${BLUE}📦 版本: ${VERSION}${NC}"
|
|
echo -e "${BLUE}📦 DMG 文件名: ${DMG_NAME}${NC}"
|
|
|
|
# Create temporary directory for DMG contents
|
|
echo -e "${YELLOW}📁 Creating DMG contents...${NC}"
|
|
mkdir -p "${TEMP_DIR}"
|
|
cp -R "${APP_PATH}" "${TEMP_DIR}/"
|
|
|
|
# Create Applications symlink
|
|
ln -s /Applications "${TEMP_DIR}/Applications"
|
|
|
|
# Create a simple background image if it doesn't exist
|
|
if [ ! -f "${BACKGROUND_IMAGE_NAME}" ]; then
|
|
echo -e "${YELLOW}🎨 Creating background image...${NC}"
|
|
# Create a simple background using ImageMagick if available, otherwise skip
|
|
if command -v convert >/dev/null 2>&1; then
|
|
convert -size 600x400 xc:white \
|
|
-fill '#f0f0f0' -draw 'rectangle 0,0 600,400' \
|
|
-fill black -pointsize 20 -gravity center \
|
|
-annotate +0-100 "Drag ${APP_NAME} to Applications" \
|
|
"${BACKGROUND_IMAGE_NAME}"
|
|
fi
|
|
fi
|
|
|
|
# Copy background image if it exists
|
|
if [ -f "${BACKGROUND_IMAGE_NAME}" ]; then
|
|
cp "${BACKGROUND_IMAGE_NAME}" "${TEMP_DIR}/.background.png"
|
|
fi
|
|
|
|
# Create DMG
|
|
echo -e "${BLUE}💽 Creating DMG file...${NC}"
|
|
hdiutil create -volname "${APP_NAME}" \
|
|
-srcfolder "${TEMP_DIR}" \
|
|
-ov \
|
|
-format UDZO \
|
|
-imagekey zlib-level=9 \
|
|
"${DMG_NAME}"
|
|
|
|
# Clean up temporary files
|
|
echo -e "${YELLOW}🧹 Cleaning up temporary files...${NC}"
|
|
rm -rf "${TEMP_DIR}"
|
|
rm -rf "${BUILD_DIR}"
|
|
|
|
# Get DMG size
|
|
DMG_SIZE=$(du -h "${DMG_NAME}" | cut -f1)
|
|
|
|
echo -e "${GREEN}🎉 DMG creation completed successfully!${NC}"
|
|
echo -e "${GREEN}📦 Output: ${DMG_NAME} (${DMG_SIZE})${NC}"
|
|
echo -e "${GREEN}📍 Location: $(pwd)/${DMG_NAME}${NC}"
|
|
echo ""
|
|
echo -e "${BLUE}📋 下一步:${NC}"
|
|
echo -e "1. 在 GitHub 上创建 Release (tag: v${VERSION})"
|
|
echo -e "2. 上传 DMG 文件: ${DMG_NAME}"
|
|
echo -e "3. 填写 Release Notes"
|
|
|
|
# Optional: Open the directory containing the DMG
|
|
if command -v open >/dev/null 2>&1; then
|
|
echo ""
|
|
echo -e "${BLUE}📂 Opening directory...${NC}"
|
|
open .
|
|
fi |