diff --git a/electron/main/ipc/ipc-mac-statusbar.ts b/electron/main/ipc/ipc-mac-statusbar.ts index 513553708..616881bd1 100644 --- a/electron/main/ipc/ipc-mac-statusbar.ts +++ b/electron/main/ipc/ipc-mac-statusbar.ts @@ -4,6 +4,7 @@ import { ipcMain } from "electron"; import { useStore } from "../store"; import { getMainTray } from "../tray"; import mainWindow from "../windows/main-window"; +import { getCurrentSongTitle } from "./ipc-tray"; let macLyricLines: LyricLine[] = []; let macCurrentTime = 0; @@ -29,7 +30,7 @@ const stopInterpolation = () => { /** * 启动插值计时器 */ -const startInterpolation = (store: ReturnType) => { +const startInterpolation = () => { stopInterpolation(); // 先停止任何已存在的计时器 macLastUpdateTime = Date.now(); // 在启动新的插值计时器时,重置 macLastUpdateTime interpolationTimer = setInterval(() => { @@ -37,7 +38,7 @@ const startInterpolation = (store: ReturnType) => { const elapsedTime = now - macLastUpdateTime; macCurrentTime += elapsedTime; macLastUpdateTime = now; - updateMacStatusBarLyric(store); + updateMacStatusBarLyric(); }, LYRIC_UPDATE_INTERVAL); }; @@ -65,28 +66,41 @@ const findCurrentLyricIndex = ( /** * 更新 macOS 状态栏歌词(只在新行时才更新) + * @param forceUpdate 是否强制更新,即便歌词行索引未变化 */ -const updateMacStatusBarLyric = (store: ReturnType) => { +const updateMacStatusBarLyric = ( + forceUpdate: boolean = false, +) => { + const store = useStore(); const tray = getMainTray(); if (!tray) return; + // 检查 macOS 状态栏歌词功能是否启用 + const isMacosLyricEnabled = store.get("macos.statusBarLyric.enabled") ?? false; + if (!isMacosLyricEnabled) { + // 如果功能被禁用,则确保托盘标题显示为当前歌曲名,并立即返回 + tray.setTitle(getCurrentSongTitle()); + return; + } + const showWhenPaused = store.get("taskbar.showWhenPaused") ?? true; if (!macIsPlaying && !showWhenPaused) { - // 如果不显示,则清空标题 - tray.setMacStatusBarLyricTitle(""); + // 如果当前未播放且设置不允许暂停时显示歌词,则清空标题 + tray.setTitle(""); return; } - // 如果歌词为空,则清空标题并返回 + // 如果歌词数据为空,则清空标题并返回 if (macLyricLines.length === 0) { - tray.setMacStatusBarLyricTitle(""); + tray.setTitle(""); return; } const currentLyricIndex = findCurrentLyricIndex(macCurrentTime, macLyricLines, macOffset); - // 如果行索引没有变化,不更新 - if (currentLyricIndex === macLastLyricIndex) return; + // 如果不是强制更新模式,并且歌词行索引没有变化,则跳过更新 + // `forceUpdate` 用于在启动时或拖动进度条时,即使行索引未变,也强制更新 + if (!forceUpdate && currentLyricIndex === macLastLyricIndex) return; macLastLyricIndex = currentLyricIndex; const currentLyric = @@ -97,64 +111,68 @@ const updateMacStatusBarLyric = (store: ReturnType) => { .trim() : ""; - tray.setMacStatusBarLyricTitle(currentLyric); + tray.setTitle(currentLyric); }; export const initMacStatusBarIpc = () => { const store = useStore(); - // 初始化时读取新的 macOS 专属设置 + // 初始化时读取 macOS 专属设置 const isMacosLyricEnabled = store.get("macos.statusBarLyric.enabled") ?? false; const tray = getMainTray(); - tray?.setMacStatusBarLyricShow(isMacosLyricEnabled); // 根据新设置初始化显示状态 + + // 根据初始设置状态更新托盘显示 + // 如果禁用,设置回歌曲标题 + if (!isMacosLyricEnabled) { + tray?.setTitle(getCurrentSongTitle()); + } // 新增 macOS 专属设置切换监听 ipcMain.on("macos-lyric:toggle", (_event, show: boolean) => { - store.set("macos.statusBarLyric.enabled", show); // 更新 store + store.set("macos.statusBarLyric.enabled", show); const tray = getMainTray(); + const mainWin = mainWindow.getWin(); - // 触发 "mac-toggle-statusbar-lyric" 事件,让 ipc-tray 响应 - ipcMain.emit("mac-toggle-statusbar-lyric", null, show); + // 强制更新托盘菜单,以响应新的开启/关闭状态 + tray?.initTrayMenu(); - const mainWin = mainWindow.getWin(); // 获取主窗口实例 if (mainWin && !mainWin.isDestroyed()) { // 发送更新给渲染进程,同步 Pinia store mainWin.webContents.send("setting:update-macos-lyric-enabled", show); if (show) { - mainWin.webContents.send(TASKBAR_IPC_CHANNELS.REQUEST_DATA); // 请求新数据 + mainWin.webContents.send(TASKBAR_IPC_CHANNELS.REQUEST_DATA); } else { - tray?.setMacStatusBarLyricTitle(""); // 关闭时清空歌词 - stopInterpolation(); // 关闭时停止计时器 + // 关闭时,将标题恢复为歌曲名,并停止歌词插值计时器 + tray?.setTitle(getCurrentSongTitle()); + stopInterpolation(); } } else if (!show) { - // 如果主窗口不可用且正在关闭,也清空歌词 - tray?.setMacStatusBarLyricTitle(""); - stopInterpolation(); // 关闭时停止计时器 + // 如果主窗口不可用且正在关闭,也恢复标题并停止计时器 + tray?.setTitle(getCurrentSongTitle()); + stopInterpolation(); } }); ipcMain.on(TASKBAR_IPC_CHANNELS.SYNC_STATE, (_event, payload: SyncStatePayload) => { switch (payload.type) { case "lyrics-loaded": { + // 仅更新歌词数据,不立即更新状态栏显示 macLyricLines = payload.data.lines; macLastLyricIndex = -1; - // 确保新歌词到达后立即更新状态栏显示 - const mainWin = mainWindow.getWin(); - if (mainWin && !mainWin.isDestroyed()) { - updateMacStatusBarLyric(useStore()); - } break; } case "playback-state": macIsPlaying = payload.data.isPlaying; - if (!macIsPlaying) { + // 不在这里直接更新歌词,依赖 SYNC_TICK 来驱动 + if (!macIsPlaying) { // 如果是暂停状态,则停止插值器并进行一次最终更新 stopInterpolation(); - updateMacStatusBarLyric(store); + updateMacStatusBarLyric(); } break; case "full-hydration": + // 接收完整的状态,但歌词更新仍然依赖 SYNC_TICK if (payload.data.lyrics) { macLyricLines = payload.data.lyrics.lines; macLastLyricIndex = -1; @@ -167,14 +185,11 @@ export const initMacStatusBarIpc = () => { macOffset = offset; } } - updateMacStatusBarLyric(store); - if (macIsPlaying) { - startInterpolation(store); - } break; } }); + // macOS 状态栏歌词专用进度更新 ipcMain.on(TASKBAR_IPC_CHANNELS.SYNC_TICK, (_, payload: SyncTickPayload) => { const [currentTime, _duration, offset] = payload; @@ -193,10 +208,10 @@ export const initMacStatusBarIpc = () => { macOffset = offset; } // 收到精确进度或误差较大同步后,立即更新一次歌词显示 - updateMacStatusBarLyric(store); // 如果此时是播放状态,确保插值器运行 + updateMacStatusBarLyric(true); if (macIsPlaying) { - startInterpolation(store); + startInterpolation(); } }); @@ -207,4 +222,4 @@ export const initMacStatusBarIpc = () => { mainWin.webContents.send(TASKBAR_IPC_CHANNELS.REQUEST_DATA); } }); -}; +}; \ No newline at end of file diff --git a/electron/main/ipc/ipc-tray.ts b/electron/main/ipc/ipc-tray.ts index ea8c593c0..0d5a8ee01 100644 --- a/electron/main/ipc/ipc-tray.ts +++ b/electron/main/ipc/ipc-tray.ts @@ -3,12 +3,17 @@ import { ipcMain } from "electron"; import { getMainTray } from "../tray"; import { appName, isMac } from "../utils/config"; import lyricWindow from "../windows/lyric-window"; +import { useStore } from "../store"; -// macOS 状态栏歌词开关状态 -let macStatusBarLyricEnabled = false; // 当前歌曲标题 let currentSongTitle = appName; +/** + * 获取当前歌曲标题 + * @returns 当前歌曲标题 + */ +export const getCurrentSongTitle = () => currentSongTitle; + /** * 托盘 IPC */ @@ -25,11 +30,14 @@ const initTrayIpc = (): void => { // 音乐名称更改 ipcMain.on("play-song-change", (_, options) => { + const store = useStore(); + // 从 Store 获取 macOS 状态栏歌词的启用状态 + const isMacLyricEnabled = store.get("macos.statusBarLyric.enabled") ?? false; let title = options?.title; if (!title) title = appName; currentSongTitle = title; - // 更改标题(仅在非 macOS 状态栏歌词模式下更新托盘标题) - if (!isMac || !macStatusBarLyricEnabled) { + // 更改托盘标题:仅在非 macOS 状态栏歌词模式下,或 macOS 歌词未启用时,才更新托盘标题为歌曲名 + if (!isMac || !isMacLyricEnabled) { tray?.setTitle(title); } tray?.setPlayName(title); @@ -54,17 +62,6 @@ const initTrayIpc = (): void => { ipcMain.on("desktop-lyric:toggle-lock", (_, { lock }: { lock: boolean }) => { tray?.setDesktopLyricLock(lock); }); - - // macOS 状态栏歌词开关 - ipcMain.on("mac-toggle-statusbar-lyric", (_, show: boolean) => { - if (!isMac) return; - macStatusBarLyricEnabled = show; - tray?.setMacStatusBarLyricShow(show); - // 如果关闭,恢复显示歌曲标题 - if (!show) { - tray?.setTitle(currentSongTitle); - } - }); }; export default initTrayIpc; diff --git a/electron/main/tray/index.ts b/electron/main/tray/index.ts index efa95860c..e874c1c2d 100644 --- a/electron/main/tray/index.ts +++ b/electron/main/tray/index.ts @@ -28,9 +28,6 @@ let likeSong: boolean = false; let desktopLyricShow: boolean = false; let desktopLyricLock: boolean = false; let taskbarLyricShow: boolean = false; -// macOS 状态栏歌词 -let macStatusBarLyricShow: boolean = false; -let macStatusBarLyricTitle: string = ""; export interface MainTray { setTitle(title: string): void; @@ -41,8 +38,7 @@ export interface MainTray { setDesktopLyricShow(show: boolean): void; setDesktopLyricLock(lock: boolean): void; setTaskbarLyricShow(show: boolean): void; - setMacStatusBarLyricShow(show: boolean, songTitle?: string): void; - setMacStatusBarLyricTitle(title: string): void; + initTrayMenu(): void; destroyTray(): void; } @@ -108,6 +104,7 @@ const getMenuIcon = (iconName: string): NativeImage | undefined => { // 托盘菜单 const createTrayMenu = (win: BrowserWindow): MenuItemConstructorOptions[] => { + const store = useStore(); /** * 获取 {@linkcode RepeatModeType} 对应的显示字符串 * @param mode 重复模式 @@ -124,6 +121,9 @@ const createTrayMenu = (win: BrowserWindow): MenuItemConstructorOptions[] => { return "列表循环"; } }; + + const isMacosLyricEnabled = store.get("macos.statusBarLyric.enabled") ?? false; + // 菜单 const menu: MenuItemConstructorOptions[] = [ { @@ -226,7 +226,7 @@ const createTrayMenu = (win: BrowserWindow): MenuItemConstructorOptions[] => { }, { id: "toggle-taskbar-lyric", - label: `${(isMac ? macStatusBarLyricShow : taskbarLyricShow) ? "关闭" : "开启"}${isMac ? "状态栏" : "任务栏"}歌词`, + label: `${(isMac ? isMacosLyricEnabled : taskbarLyricShow) ? "关闭" : "开启"}${isMac ? "状态栏" : "任务栏"}歌词`, icon: getMenuIcon("lyric"), visible: isWin || isMac, click: () => win.webContents.send("toggle-taskbar-lyric"), @@ -293,10 +293,10 @@ class CreateTray implements MainTray { this._contextMenu = Menu.buildFromTemplate(this._menu); this.initTrayMenu(); this.initEvents(); - this.setTitle(appName); + this._tray.setTitle(appName); // 仅设置托盘标题,不设置窗口标题 } // 托盘菜单 - private initTrayMenu() { + public initTrayMenu() { this._menu = createTrayMenu(this._win); this._contextMenu = Menu.buildFromTemplate(this._menu); this._tray.setContextMenu(this._contextMenu); @@ -318,7 +318,6 @@ class CreateTray implements MainTray { * @param title 标题 */ setTitle(title: string) { - this._win.setTitle(title); this._tray.setTitle(title); this._tray.setToolTip(title); } @@ -383,25 +382,10 @@ class CreateTray implements MainTray { setTaskbarLyricShow(show: boolean) { taskbarLyricShow = show; + // 更新菜单 this.initTrayMenu(); } - setMacStatusBarLyricShow(show: boolean, songTitle?: string) { - macStatusBarLyricShow = show; - this.initTrayMenu(); - if (show && macStatusBarLyricTitle) { - this._tray.setTitle(macStatusBarLyricTitle); - } else if (!show) { - this._tray.setTitle(songTitle ?? appName); - } - } - - setMacStatusBarLyricTitle(title: string) { - macStatusBarLyricTitle = title; - if (macStatusBarLyricShow) { - this._tray.setTitle(title); - } - } /** * 销毁托盘 */