From 8ee2b928f92c33eed0dea1f38d03d08d86c0ceb9 Mon Sep 17 00:00:00 2001 From: Astrian Zheng Date: Wed, 4 Jun 2025 22:23:34 +1000 Subject: [PATCH 01/10] =?UTF-8?q?fix:=20=E8=A7=A3=E5=86=B3=20Safari=20?= =?UTF-8?q?=E6=B5=8F=E8=A7=88=E5=99=A8=E9=9F=B3=E9=A2=91=E6=92=AD=E6=94=BE?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 创建浏览器检测工具,专门检测 Safari 和音频可视化支持 - 在 Safari 浏览器上禁用 AudioContext 连接,避免播放问题 - 保持其他浏览器的音频可视化功能正常工作 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- src/components/Player.vue | 69 ++++++++++++++++-------- src/utils/browserDetection.ts | 98 +++++++++++++++++++++++++++++++++++ src/utils/index.ts | 13 ++++- 3 files changed, 156 insertions(+), 24 deletions(-) create mode 100644 src/utils/browserDetection.ts diff --git a/src/components/Player.vue b/src/components/Player.vue index 605fd04..55bf6cc 100644 --- a/src/components/Player.vue +++ b/src/components/Player.vue @@ -7,7 +7,7 @@ import { usePlayQueueStore } from '../stores/usePlayQueueStore' import LoadingIndicator from '../assets/icons/loadingindicator.vue' import PlayIcon from '../assets/icons/play.vue' -import { audioVisualizer, checkAndRefreshSongResource } from '../utils' +import { audioVisualizer, checkAndRefreshSongResource, supportsWebAudioVisualization } from '../utils' const playQueueStore = usePlayQueueStore() const favourites = useFavourites() @@ -263,21 +263,40 @@ function updateCurrentTime() { } } -console.log('[Player] 初始化 audioVisualizer') -const { barHeights, connectAudio, isAnalyzing, error } = audioVisualizer({ - sensitivity: 1.5, - barCount: 6, - maxDecibels: -10, - bassBoost: 0.8, - midBoost: 1.2, - trebleBoost: 1.4, - threshold: 0, -}) +// 检查浏览器是否支持音频可视化 +const isAudioVisualizationSupported = supportsWebAudioVisualization() +console.log('[Player] 音频可视化支持状态:', isAudioVisualizationSupported) -console.log('[Player] audioVisualizer 返回值:', { - barHeights: barHeights.value, - isAnalyzing: isAnalyzing.value, -}) +// 只在支持的浏览器上初始化音频可视化 +let barHeights = ref([0, 0, 0, 0, 0, 0]) +let connectAudio = (_audio: HTMLAudioElement) => {} +let isAnalyzing = ref(false) +let error = ref(null) + +if (isAudioVisualizationSupported) { + console.log('[Player] 初始化 audioVisualizer') + const visualizer = audioVisualizer({ + sensitivity: 1.5, + barCount: 6, + maxDecibels: -10, + bassBoost: 0.8, + midBoost: 1.2, + trebleBoost: 1.4, + threshold: 0, + }) + + barHeights = visualizer.barHeights + connectAudio = visualizer.connectAudio + isAnalyzing = visualizer.isAnalyzing + error = visualizer.error + + console.log('[Player] audioVisualizer 返回值:', { + barHeights: barHeights.value, + isAnalyzing: isAnalyzing.value, + }) +} else { + console.log('[Player] 音频可视化被禁用(Safari 或不支持的浏览器)') +} // 监听播放列表变化 watch( @@ -293,13 +312,17 @@ watch( await nextTick() if (player.value) { - console.log('[Player] 连接音频元素到可视化器') - console.log('[Player] 音频元素状态:', { - src: player.value.src?.substring(0, 50) + '...', - readyState: player.value.readyState, - paused: player.value.paused, - }) - connectAudio(player.value) + if (isAudioVisualizationSupported) { + console.log('[Player] 连接音频元素到可视化器') + console.log('[Player] 音频元素状态:', { + src: player.value.src?.substring(0, 50) + '...', + readyState: player.value.readyState, + paused: player.value.paused, + }) + connectAudio(player.value) + } else { + console.log('[Player] 跳过音频可视化连接(不支持的浏览器)') + } } else { console.log('[Player] ❌ 音频元素不存在') } @@ -322,7 +345,7 @@ watch( watch( () => player.value, (audioElement) => { - if (audioElement && playQueueStore.list.length > 0) { + if (audioElement && playQueueStore.list.length > 0 && isAudioVisualizationSupported) { connectAudio(audioElement) } }, diff --git a/src/utils/browserDetection.ts b/src/utils/browserDetection.ts new file mode 100644 index 0000000..28ba2e9 --- /dev/null +++ b/src/utils/browserDetection.ts @@ -0,0 +1,98 @@ +/** + * 浏览器检测工具 + */ + +/** + * 检测是否为 Safari 浏览器 + * @returns {boolean} 如果是 Safari 返回 true,否则返回 false + */ +export function isSafari(): boolean { + const ua = navigator.userAgent.toLowerCase() + + // 检测 Safari 浏览器(包括 iOS 和 macOS) + // Safari 的 User Agent 包含 'safari' 但不包含 'chrome' 或 'chromium' + const isSafariBrowser = ua.includes('safari') && + !ua.includes('chrome') && + !ua.includes('chromium') && + !ua.includes('android') + + // 额外检查:使用 Safari 特有的 API + const isSafariByFeature = 'safari' in window || + /^((?!chrome|android).)*safari/i.test(navigator.userAgent) + + return isSafariBrowser || isSafariByFeature +} + +/** + * 检测是否为移动版 Safari + * @returns {boolean} 如果是移动版 Safari 返回 true,否则返回 false + */ +export function isMobileSafari(): boolean { + return /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream +} + +/** + * 检测是否支持 Web Audio API 的完整功能 + * @returns {boolean} 如果支持返回 true,否则返回 false + */ +export function supportsWebAudioVisualization(): boolean { + // Safari 在某些情况下对 AudioContext 的支持有限制 + // 特别是在处理跨域音频资源时 + if (isSafari()) { + console.log('[BrowserDetection] Safari detected, audio visualization disabled') + return false + } + + // 检查基本的 Web Audio API 支持 + const hasAudioContext = 'AudioContext' in window || 'webkitAudioContext' in window + const hasAnalyserNode = hasAudioContext && ( + 'AnalyserNode' in window || + (window.AudioContext && 'createAnalyser' in AudioContext.prototype) + ) + + return hasAudioContext && hasAnalyserNode +} + +/** + * 获取浏览器信息 + * @returns {object} 包含浏览器类型和版本信息的对象 + */ +export function getBrowserInfo() { + const ua = navigator.userAgent + let browserName = 'Unknown' + let browserVersion = 'Unknown' + + if (isSafari()) { + browserName = 'Safari' + const versionMatch = ua.match(/Version\/(\d+\.\d+)/) + if (versionMatch) { + browserVersion = versionMatch[1] + } + } else if (ua.includes('Chrome')) { + browserName = 'Chrome' + const versionMatch = ua.match(/Chrome\/(\d+\.\d+)/) + if (versionMatch) { + browserVersion = versionMatch[1] + } + } else if (ua.includes('Firefox')) { + browserName = 'Firefox' + const versionMatch = ua.match(/Firefox\/(\d+\.\d+)/) + if (versionMatch) { + browserVersion = versionMatch[1] + } + } else if (ua.includes('Edge')) { + browserName = 'Edge' + const versionMatch = ua.match(/Edge\/(\d+\.\d+)/) + if (versionMatch) { + browserVersion = versionMatch[1] + } + } + + return { + name: browserName, + version: browserVersion, + isSafari: isSafari(), + isMobileSafari: isMobileSafari(), + supportsAudioVisualization: supportsWebAudioVisualization() + } +} \ No newline at end of file diff --git a/src/utils/index.ts b/src/utils/index.ts index 5f850e4..67aee1a 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -2,5 +2,16 @@ import artistsOrganize from "./artistsOrganize" import { audioVisualizer } from "./audioVisualizer" import cicdInfo from "./cicdInfo" import { checkAndRefreshSongResource, checkAndRefreshMultipleSongs } from "./songResourceChecker" +import { isSafari, isMobileSafari, supportsWebAudioVisualization, getBrowserInfo } from "./browserDetection" -export { artistsOrganize, audioVisualizer, cicdInfo, checkAndRefreshSongResource, checkAndRefreshMultipleSongs } +export { + artistsOrganize, + audioVisualizer, + cicdInfo, + checkAndRefreshSongResource, + checkAndRefreshMultipleSongs, + isSafari, + isMobileSafari, + supportsWebAudioVisualization, + getBrowserInfo +} From b0743178ed132c41725d2b61b8eebc1f84cc0e81 Mon Sep 17 00:00:00 2001 From: Astrian Zheng Date: Wed, 4 Jun 2025 22:25:24 +1000 Subject: [PATCH 02/10] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=20ref=20?= =?UTF-8?q?=E6=9C=AA=E5=AF=BC=E5=85=A5=E7=9A=84=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在 Player.vue 中添加缺失的 ref 导入 - 解决 "ReferenceError: Can't find variable: ref" 错误 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- src/components/Player.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Player.vue b/src/components/Player.vue index 55bf6cc..3ecfeec 100644 --- a/src/components/Player.vue +++ b/src/components/Player.vue @@ -1,6 +1,6 @@ + + \ No newline at end of file diff --git a/src/components/PlayQueueItem.vue b/src/components/PlayQueueItem.vue index c15bf70..85ee912 100644 --- a/src/components/PlayQueueItem.vue +++ b/src/components/PlayQueueItem.vue @@ -5,6 +5,7 @@ import { artistsOrganize } from '../utils' import XIcon from '../assets/icons/x.vue' import UpHyphenIcon from '../assets/icons/uphypen.vue' import DownHyphenIcon from '../assets/icons/downhyphen.vue' +import SoundwaveIcon from '../assets/icons/soundwave.vue' import { ref } from 'vue' @@ -156,12 +157,7 @@ function removeItem() {
-
-
-
+
diff --git a/src/components/Player.vue b/src/components/Player.vue index 3ecfeec..ce7c178 100644 --- a/src/components/Player.vue +++ b/src/components/Player.vue @@ -7,6 +7,7 @@ import { usePlayQueueStore } from '../stores/usePlayQueueStore' import LoadingIndicator from '../assets/icons/loadingindicator.vue' import PlayIcon from '../assets/icons/play.vue' +import PauseIcon from '../assets/icons/pause.vue' import { audioVisualizer, checkAndRefreshSongResource, supportsWebAudioVisualization } from '../utils' const playQueueStore = usePlayQueueStore() @@ -518,12 +519,7 @@ setInterval(syncVolumeFromStorage, 100) }">
-
-
-
+
From be15a89ad6dc630ebc68611706e855c002defa51 Mon Sep 17 00:00:00 2001 From: Astrian Zheng Date: Wed, 4 Jun 2025 22:31:16 +1000 Subject: [PATCH 04/10] =?UTF-8?q?fix:=20=E6=81=A2=E5=A4=8D=E9=9D=9E=20Safa?= =?UTF-8?q?ri=20=E6=B5=8F=E8=A7=88=E5=99=A8=E7=9A=84=E9=9F=B3=E9=A2=91?= =?UTF-8?q?=E5=8F=AF=E8=A7=86=E5=8C=96=E6=95=88=E6=9E=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 只在 Safari 浏览器上使用静态图标替代可视化 - Chrome、Firefox 等浏览器保留原有的动态可视化效果 - Player.vue 和 PlayQueueItem.vue 现在都会检测浏览器支持情况 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- src/components/PlayQueueItem.vue | 14 ++++++++++++-- src/components/Player.vue | 7 +++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/components/PlayQueueItem.vue b/src/components/PlayQueueItem.vue index 85ee912..eb3d284 100644 --- a/src/components/PlayQueueItem.vue +++ b/src/components/PlayQueueItem.vue @@ -1,6 +1,6 @@ + + + +`; + fs.writeFileSync(backgroundHtmlPath, backgroundHtmlContent); + + // 创建 Safari 兼容的 background.js + const backgroundJsPath = path.join(__dirname, '../public/background.js'); + let backgroundJsContent = fs.readFileSync(backgroundJsPath, 'utf8'); + + // 检查是否已经添加过 Safari 代码,避免重复 + if (backgroundJsContent.includes('=== Safari background.js starting ===')) { + console.log('Safari background.js already processed, skipping...'); + } else { + // 在开头添加 Safari 调试信息(只添加一次) + const safariDebugCode = ` +console.log("=== Safari background.js starting ==="); +console.log("Available APIs:", { + chrome: typeof chrome, + browser: typeof browser, + safari: typeof safari +}); + +// Safari 特殊处理 +if (typeof chrome === 'undefined' && typeof browser === 'undefined') { + console.log("No extension APIs available in Safari"); + // 如果没有扩展 API,创建一个空的对象避免错误 + window.chrome = { + webRequest: { onBeforeRequest: { addListener: () => {} } }, + storage: { sync: { get: () => Promise.resolve({}) } }, + tabs: { create: () => {}, remove: () => {}, update: () => {} }, + runtime: { + getURL: (path) => path, + onMessage: { addListener: () => {} } + } + }; +} + +// Safari 消息监听器:处理来自 content script 的重定向请求 +if (typeof chrome !== 'undefined' && chrome.runtime && chrome.runtime.onMessage) { + chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { + console.log('Background received message:', message); + + if (message.action === 'redirect_to_extension') { + console.log('Processing redirect request from content script'); + + try { + // 创建新标签页并打开扩展 + const extensionUrl = chrome.runtime.getURL('index.html'); + chrome.tabs.create({ url: extensionUrl }, (newTab) => { + console.log('New extension tab created:', newTab.id); + + // 关闭原始标签页 + if (sender.tab && sender.tab.id) { + chrome.tabs.remove(sender.tab.id); + } + + sendResponse({ success: true, url: extensionUrl }); + }); + } catch (error) { + console.error('Failed to redirect:', error); + sendResponse({ success: false, error: error.message }); + } + + return true; // 保持消息通道开放 + } + }); +} + +`; + + // 替换 Safari 的重定向 URL 监听 + backgroundJsContent = backgroundJsContent.replace( + /{ urls: \['https:\/\/monster-siren\.hypergryph\.com\/api\/fontset', 'https:\/\/monster-siren\.hypergryph\.com\/manifest\.json'\] }/g, + "{ urls: ['https://monster-siren.hypergryph.com/api/fontset', 'https://monster-siren.hypergryph.com/manifest.json', 'https://monster-siren.hypergryph.com/'] }" + ); + + // 替换 Safari 的重定向判断逻辑 + backgroundJsContent = backgroundJsContent.replace( + /details\.url === 'https:\/\/monster-siren\.hypergryph\.com\/manifest\.json'/g, + "(details.url === 'https://monster-siren.hypergryph.com/manifest.json' || details.url === 'https://monster-siren.hypergryph.com/')" + ); + + // 清理可能的重复条件 + backgroundJsContent = backgroundJsContent.replace( + /\(\(details\.url === 'https:\/\/monster-siren\.hypergryph\.com\/manifest\.json' \|\| details\.url === 'https:\/\/monster-siren\.hypergryph\.com\/'\) \|\| details\.url === 'https:\/\/monster-siren\.hypergryph\.com\/'\)/g, + "(details.url === 'https://monster-siren.hypergryph.com/manifest.json' || details.url === 'https://monster-siren.hypergryph.com/')" + ); + + backgroundJsContent = safariDebugCode + backgroundJsContent; + } + fs.writeFileSync(backgroundJsPath, backgroundJsContent); + console.log('✅ Safari-compatible background.js created'); + + // 创建 Safari 专用的 content.js + const contentJsPath = path.join(__dirname, '../public/content.js'); + + // 检查是否已经处理过 content.js + const existingContentJs = fs.existsSync(contentJsPath) ? fs.readFileSync(contentJsPath, 'utf8') : ''; + if (existingContentJs.includes('checkRedirectPreference')) { + console.log('Safari content.js already processed, skipping...'); + } else { + const contentJsContent = ` +// Safari 扩展 content script for redirect +console.log('MSR Mod content script loaded on:', window.location.href); + +// 兼容 Safari 的浏览器 API +const browserAPI = typeof browser !== 'undefined' ? browser : chrome; + +// 异步函数:检查重定向偏好设置 +async function checkRedirectPreference() { + try { + console.log('Checking redirect preferences...'); + + // 读取偏好设置 + const pref = await browserAPI.storage.sync.get('preferences'); + console.log('Retrieved preferences:', pref); + + // 检查自动重定向设置(默认为 true) + const shouldRedirect = pref === undefined || + pref.preferences === undefined || + pref.preferences.autoRedirect === undefined || + pref.preferences.autoRedirect === true; + + console.log('Should redirect:', shouldRedirect); + return shouldRedirect; + } catch (error) { + console.error('Error reading preferences:', error); + // 如果读取偏好设置失败,默认重定向 + return true; + } +} + +// 执行重定向的函数 +function performRedirect() { + console.log('Performing redirect to extension...'); + + try { + // 对于 Safari,我们需要使用消息传递来请求重定向 + // 因为 content script 无法直接访问 chrome.runtime.getURL + + // 方案1:尝试通过消息传递 + if (typeof chrome !== 'undefined' && chrome.runtime) { + chrome.runtime.sendMessage({action: 'redirect_to_extension'}, (response) => { + if (chrome.runtime.lastError) { + console.log('Message sending failed, trying direct redirect...'); + // 方案2:尝试直接重定向(可能在某些情况下有效) + window.location.href = 'safari-web-extension://[extension-id]/index.html'; + } + }); + } else { + console.log('Chrome runtime not available, trying alternative redirect...'); + // 方案3:显示提示让用户手动打开扩展 + document.body.innerHTML = \` +
+

MSR Mod Extension Detected

+

Please click the MSR Mod extension icon in your Safari toolbar to open the app.

+ +
+ \`; + } + } catch (error) { + console.error('Redirect failed:', error); + } +} + +// 主逻辑:检查页面并根据偏好设置决定是否重定向 +async function main() { + // 检查是否是目标页面 + if (window.location.pathname === '/' || window.location.href.includes('appShell.html')) { + console.log('Detected target page, checking preferences...'); + + // 检查偏好设置 + const shouldRedirect = await checkRedirectPreference(); + + if (shouldRedirect) { + console.log('Auto-redirect is enabled, proceeding with redirect...'); + performRedirect(); + } else { + console.log('Auto-redirect is disabled, skipping redirect.'); + } + } +} + +// 执行主逻辑 +main().catch(error => { + console.error('Error in main function:', error); +}); +`; + + fs.writeFileSync(contentJsPath, contentJsContent); + } + console.log('✅ Safari-compatible content.js created'); + + // Safari 可能需要额外的权限 + if (!manifest.permissions.includes('activeTab')) { + manifest.permissions.push('activeTab'); + } + + // 添加 Safari 特有配置 + manifest.browser_specific_settings = { + safari: { + minimum_version: "14.0" + } + }; + + fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2)); + console.log('✅ Safari Manifest.json processed'); + console.log('✅ Background.html created for Safari'); +} + +// 处理 index.html +function processIndexHtml() { + const indexPath = path.join(__dirname, '../index.html'); + let content = fs.readFileSync(indexPath, 'utf8'); + + // 替换脚本地址 + content = content.replace( + /src="[^"]*\/src\/main\.ts"/g, + 'src="./src/main.ts"' + ); + + // 移除 crossorigin 属性 + content = content.replace(/\s+crossorigin/g, ''); + + fs.writeFileSync(indexPath, content); + console.log('✅ Index.html processed for Safari'); +} + +// 执行处理 +try { + processManifest(); + processIndexHtml(); + console.log('🎉 Safari build preparation completed!'); +} catch (error) { + console.error('❌ Error during Safari build preparation:', error); + process.exit(1); +} diff --git a/src/components/PlayListItem.vue b/src/components/PlayListItem.vue index f526b15..6090b0e 100644 --- a/src/components/PlayListItem.vue +++ b/src/components/PlayListItem.vue @@ -9,7 +9,7 @@ const favourites = useFavourites() const hover = ref(false) -const props = defineProps<{ +defineProps<{ item: QueueItem index: number }>() diff --git a/src/utils/browserDetection.ts b/src/utils/browserDetection.ts index 28ba2e9..f1c80ef 100644 --- a/src/utils/browserDetection.ts +++ b/src/utils/browserDetection.ts @@ -28,7 +28,7 @@ export function isSafari(): boolean { * @returns {boolean} 如果是移动版 Safari 返回 true,否则返回 false */ export function isMobileSafari(): boolean { - return /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream + return /iPad|iPhone|iPod/.test(navigator.userAgent) && !(window as any).MSStream } /** @@ -47,7 +47,7 @@ export function supportsWebAudioVisualization(): boolean { const hasAudioContext = 'AudioContext' in window || 'webkitAudioContext' in window const hasAnalyserNode = hasAudioContext && ( 'AnalyserNode' in window || - (window.AudioContext && 'createAnalyser' in AudioContext.prototype) + ((window as any).AudioContext && 'createAnalyser' in (window as any).AudioContext.prototype) ) return hasAudioContext && hasAnalyserNode From acc3af1214aa853525c3366d71b4d48044a725ad Mon Sep 17 00:00:00 2001 From: Astrian Zheng Date: Thu, 5 Jun 2025 10:54:13 +1000 Subject: [PATCH 06/10] feat: add Safari extension build workflow for CI/CD MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add macOS runner support for building Safari extensions including: - Safari-specific build process with npm run build:safari - Xcode setup and safari-web-extension-converter integration - Native Safari extension compilation with xcodebuild - Artifact upload for Safari extension builds 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- .gitea/workflows/workflow.yaml | 42 ++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/.gitea/workflows/workflow.yaml b/.gitea/workflows/workflow.yaml index eaea6fc..36cd640 100644 --- a/.gitea/workflows/workflow.yaml +++ b/.gitea/workflows/workflow.yaml @@ -61,6 +61,48 @@ jobs: name: firefox-addon path: dist/ + build-for-safari: + name: 构建 Safari 扩展程序 + runs-on: macos + env: + VITE_RUN_ID: ${{ gitea.run_number }} + VITE_HASH_ID: ${{ gitea.sha }} + + steps: + - uses: actions/checkout@v3 + name: 检出代码 + + - name: 设置 Node.js + uses: actions/setup-node@v3 + with: + node-version: '22' + + - name: 安装依赖 + run: npm install + + - name: 构建扩展程序 + run: npm run build:safari + + - name: 设置 Xcode + uses: maxim-lobanov/setup-xcode@v1 + with: + xcode-version: latest-stable + + - name: 创建 Safari 扩展项目 + run: | + xcrun safari-web-extension-converter dist --project-location safari-extension --app-name "MSR Mod" --bundle-identifier "com.astrian.msrmod" --swift --no-open + + - name: 构建 Safari 扩展 + run: | + cd safari-extension + xcodebuild -project "MSR Mod.xcodeproj" -scheme "MSR Mod" -configuration Release -destination "generic/platform=macOS" build + + - name: 上传构建工件 + uses: actions/upload-artifact@v3 + with: + name: safari-extension + path: safari-extension/ + publish-to-chrome-webstore: name: 发布至 Chrome 应用商店 runs-on: ubuntu-latest From e54361fb14d54cc7f21cea9b89438b52be75e92e Mon Sep 17 00:00:00 2001 From: Astrian Zheng Date: Thu, 5 Jun 2025 12:05:40 +1000 Subject: [PATCH 07/10] trigger CI rebuild From e62ef27a104e748cd2990211b03bb97aaef3a6c3 Mon Sep 17 00:00:00 2001 From: Astrian Zheng Date: Thu, 5 Jun 2025 15:42:26 +1000 Subject: [PATCH 08/10] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=20Safari=20?= =?UTF-8?q?=E6=89=A9=E5=B1=95=E6=9E=84=E5=BB=BA=E8=B7=AF=E5=BE=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修正 xcodebuild 命令的工作目录 - safari-web-extension-converter 会在指定目录下创建以应用名命名的子目录 --- .gitea/workflows/workflow.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitea/workflows/workflow.yaml b/.gitea/workflows/workflow.yaml index 36cd640..8153f89 100644 --- a/.gitea/workflows/workflow.yaml +++ b/.gitea/workflows/workflow.yaml @@ -94,7 +94,7 @@ jobs: - name: 构建 Safari 扩展 run: | - cd safari-extension + cd "safari-extension/MSR Mod" xcodebuild -project "MSR Mod.xcodeproj" -scheme "MSR Mod" -configuration Release -destination "generic/platform=macOS" build - name: 上传构建工件 From 9852d7bef4752ff01d4300015946a3e964ab90ba Mon Sep 17 00:00:00 2001 From: Astrian Zheng Date: Thu, 5 Jun 2025 15:43:56 +1000 Subject: [PATCH 09/10] =?UTF-8?q?chore:=20=E6=9B=B4=E6=96=B0=20Safari=20?= =?UTF-8?q?=E6=89=A9=E5=B1=95=E7=9A=84=20bundle=20ID?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 bundle ID 从 com.astrian.msrmod 改为 moe.astrian.ext-msrmod - 使用反向域名规范,更符合项目命名规范 --- .gitea/workflows/workflow.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitea/workflows/workflow.yaml b/.gitea/workflows/workflow.yaml index 8153f89..bb7070b 100644 --- a/.gitea/workflows/workflow.yaml +++ b/.gitea/workflows/workflow.yaml @@ -90,7 +90,7 @@ jobs: - name: 创建 Safari 扩展项目 run: | - xcrun safari-web-extension-converter dist --project-location safari-extension --app-name "MSR Mod" --bundle-identifier "com.astrian.msrmod" --swift --no-open + xcrun safari-web-extension-converter dist --project-location safari-extension --app-name "MSR Mod" --bundle-identifier "moe.astrian.ext-msrmod" --swift --no-open - name: 构建 Safari 扩展 run: | From fa8bd3d2af501342cac2769402f7c1517e692daf Mon Sep 17 00:00:00 2001 From: Astrian Zheng Date: Thu, 5 Jun 2025 16:12:43 +1000 Subject: [PATCH 10/10] =?UTF-8?q?fix:=20=E4=BF=AE=E6=AD=A3=20Safari=20?= =?UTF-8?q?=E6=89=A9=E5=B1=95=E6=9E=84=E5=BB=BA=E7=9A=84=20scheme=20?= =?UTF-8?q?=E5=90=8D=E7=A7=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 使用正确的 scheme 名称 'MSR Mod (macOS)' 而不是 'MSR Mod' - safari-web-extension-converter 生成的 scheme 包含平台标识符 --- .gitea/workflows/workflow.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitea/workflows/workflow.yaml b/.gitea/workflows/workflow.yaml index bb7070b..041a02c 100644 --- a/.gitea/workflows/workflow.yaml +++ b/.gitea/workflows/workflow.yaml @@ -95,7 +95,7 @@ jobs: - name: 构建 Safari 扩展 run: | cd "safari-extension/MSR Mod" - xcodebuild -project "MSR Mod.xcodeproj" -scheme "MSR Mod" -configuration Release -destination "generic/platform=macOS" build + xcodebuild -project "MSR Mod.xcodeproj" -scheme "MSR Mod (macOS)" -configuration Release -destination "generic/platform=macOS" build - name: 上传构建工件 uses: actions/upload-artifact@v3