Skip to content

✨feat(mac/tray/lyric): 新增 macOS 状态栏歌词与托盘图标适配#843

Draft
Pissofdvpe wants to merge 2 commits intoimsyy:devfrom
Pissofdvpe:dev
Draft

✨feat(mac/tray/lyric): 新增 macOS 状态栏歌词与托盘图标适配#843
Pissofdvpe wants to merge 2 commits intoimsyy:devfrom
Pissofdvpe:dev

Conversation

@Pissofdvpe
Copy link
Contributor

  • 新增 macOS 状态栏歌词功能:

    • 在 macOS 平台,歌词将显示在系统状态栏区域。
    • ipc-taskbar.ts 新增 macOS 歌词处理逻辑,包括查找当前歌词、更新进度和播放状态,并通过 IPC 发送至主进程。
    • ipc-tray.ts 新增 mac-toggle-statusbar-lyricmac-update-statusbar-lyric IPC
      处理器,用于控制状态栏歌词的显示与内容更新。
    • 实现了歌词更新防抖机制,优化显示效果。
  • 实现 macOS 风格托盘图标与菜单图标适配:

    • tray/index.ts 引入 getTrayIcon() 方法,用于为 macOS
      创建符合系统风格的模板图像托盘图标,使其能自适应亮/暗模式。
    • getMenuIcon() 方法现在处理 macOS 菜单项图标的加载和尺寸调整,同样适应系统主题。
    • 调整了 CreateTray 构造函数中的托盘图标加载逻辑,实现平台差异化。
    • 优化了托盘标题的更新时机,以避免与 macOS 状态栏歌词冲突。
  • 维护跨平台兼容性:

    • 确保 Windows 及其他平台原有的任务栏歌词窗口功能不受影响,通过 isMac 判断进行逻辑隔离。
  • 先前Mac菜单栏(状态栏)效果:
    截屏2026-02-06 22.30.46.png

  • 新增特性效果:
    截屏2026-02-07 22.02.10.png
    截屏2026-02-07 22.01.10.png

Pissofdvpe and others added 2 commits February 7, 2026 22:30
- 新增 macOS 状态栏歌词功能:在 macOS 平台,歌词将显示在系统状态栏区域,并根据播放进度实时更新,同时通过 IPC 消息进>行控制和同步。
- 实现 macOS 风格托盘图标适配:引入 `getTrayIcon()` 和 `getMenuIcon()` 方法,支持 macOS 模板图像,实现托盘和菜单图标
随系统亮/暗模式自动切换,提供更好的视觉集成。
- 维护跨平台兼容性:通过 `isMac` 判断进行逻辑隔离,确保 Windows 及其他平台原有的任务栏歌词窗口功能不受影响。
~
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @Pissofdvpe, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

此拉取请求的核心目标是增强应用程序在 macOS 平台的用户体验,通过引入原生的状态栏歌词显示功能,并优化托盘图标和菜单图标的视觉风格,使其更好地融入 macOS 生态系统。同时,所有这些改进都经过精心设计,以确保不会影响现有 Windows 用户的任务栏歌词功能,从而保持了良好的跨平台兼容性。

Highlights

  • 新增 macOS 状态栏歌词功能: 在 macOS 平台上,歌词现在可以直接显示在系统状态栏区域。此功能包括查找当前歌词、更新播放进度和状态,并通过 IPC 机制发送至主进程进行显示。为优化显示效果,还实现了歌词更新的防抖机制。
  • 适配 macOS 风格托盘图标与菜单图标: 托盘图标现在使用 macOS 风格的模板图像,能够自适应系统的亮/暗模式。菜单项图标也进行了调整,以适应系统主题并优化尺寸,提升了整体视觉一致性。
  • 维护跨平台兼容性: 确保了 Windows 及其他平台原有的任务栏歌词窗口功能不受影响,通过平台判断逻辑(isMac)实现了功能隔离,保证了不同操作系统的用户体验。
Changelog
  • electron/main/ipc/ipc-taskbar.ts
    • 引入 isMac 工具函数,用于区分 macOS 和其他平台的逻辑。
    • 新增 MacLyricLine 接口及相关状态变量(macLyricLines, macCurrentTime, macOffset, macIsPlaying, macLastLyricIndex, macUpdateTimer),用于管理 macOS 状态栏歌词数据和状态。
    • 添加 findCurrentLyricIndexfindCurrentLyric 函数,用于根据时间查找当前歌词。
    • 实现 updateMacStatusBarLyric 函数,负责更新 macOS 状态栏歌词,并加入了 200ms 的防抖机制以避免频繁更新导致的闪烁。
    • 修改 initTaskbarIpc 函数,在 macOS 上启用状态栏歌词时,通过 ipcMain.emit 触发 mac-toggle-statusbar-lyric 事件,并向渲染进程请求当前歌词数据。
    • taskbar:update-lyrics, taskbar:update-progress, taskbar:update-statetaskbar:request-data 等 IPC 消息添加了 macOS 专属处理逻辑,确保状态栏歌词能正确接收和显示数据。
  • electron/main/ipc/ipc-tray.ts
    • 新增 macStatusBarLyricEnabled 变量来跟踪 macOS 状态栏歌词的启用状态,以及 currentSongTitle 来保存当前歌曲标题。
    • 修改 play-song-change IPC 处理器,在 macOS 状态栏歌词启用时,阻止托盘标题被歌曲名称覆盖,以避免冲突。
    • 新增 mac-toggle-statusbar-lyric IPC 处理器,用于控制 macOS 状态栏歌词的显示/隐藏,并在关闭时恢复显示歌曲标题。
    • 新增 mac-update-statusbar-lyric IPC 处理器,用于更新 macOS 状态栏歌词的具体内容。
  • electron/main/tray/index.ts
    • 引入 NativeImage 类型和 isMac 变量。
    • MainTray 接口中新增 setMacStatusBarLyricShowsetMacStatusBarLyricTitle 方法。
    • 新增 getTrayIcon() 函数,专门为 macOS 创建自适应亮/暗模式的模板图像托盘图标,并处理图标加载失败的备用方案。
    • 新增 getMenuIcon() 函数,用于为 macOS 菜单项加载并调整图标尺寸,使其适应系统主题。
    • createTrayMenu 函数中所有菜单项的图标加载逻辑从 showIcon 替换为 getMenuIcon
    • 修改 'toggle-taskbar-lyric' 菜单项的标签和可见性,使其在 macOS 上显示为 '状态栏歌词' 并可见。
    • 修改 CreateTray 构造函数,根据操作系统类型(isWin, isMac)选择不同的托盘图标加载方式,macOS 使用 getTrayIcon()
    • 实现 setMacStatusBarLyricShow 方法,用于控制 macOS 状态栏歌词的显示状态,并根据需要更新托盘标题。
    • 实现 setMacStatusBarLyricTitle 方法,用于设置 macOS 状态栏歌词的文本内容。
    • destroyTray 方法中添加了清除 _checkInterval 的逻辑,以防止内存泄漏。
Activity
  • 此拉取请求由 Pissofdvpe 创建,旨在为 macOS 用户提供更好的歌词显示和托盘体验。
  • 目前没有额外的评论或审查活动。
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

本次 PR 主要为 macOS 平台增加了状态栏歌词功能,并对托盘图标进行了适配,使其风格与系统更加统一。代码实现考虑了平台差异性,保证了 Windows 等其他平台原有功能不受影响,整体改动清晰。

我在代码中发现了一些可以优化的地方:

  • ipc-taskbar.ts 中,存在几处代码重复和一处性能问题,可以通过重构来提升代码质量和运行效率。
  • ipc-tray.ts 中,一处逻辑可以简化,避免冗余的函数调用。
  • tray/index.ts 中,有一处未使用的变量和相关的死代码逻辑。

具体的修改建议请见各文件的评论。这些修改将有助于提升代码的可维护性和性能。

if (currentLyricIndex === macLastLyricIndex) return;
macLastLyricIndex = currentLyricIndex;

const currentLyric = findCurrentLyric(macCurrentTime, macLyricLines, macOffset);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

这里存在性能可以优化的点。findCurrentLyricIndex 已经找到了当前歌词的索引,但随后调用的 findCurrentLyric 又重复遍历了一遍歌词数组来获取歌词内容。这造成了不必要的性能开销。

建议直接使用 currentLyricIndex 来获取歌词,这样可以避免重复遍历,提高效率。修改后,findCurrentLyric 函数(40-56行)将不再被需要,可以一并移除。

Suggested change
const currentLyric = findCurrentLyric(macCurrentTime, macLyricLines, macOffset);
const currentLyric = currentLyricIndex > -1 ? macLyricLines[currentLyricIndex].words.map((w) => w.word ?? "").join("").trim() : "";

Comment on lines +96 to 110
// macOS 使用状态栏歌词,不使用任务栏歌词窗口
if (isMac) {
const envEnabled = store.get("taskbar.enabled");
const tray = getMainTray();
tray?.setMacStatusBarLyricShow(envEnabled);
} else {
const envEnabled = store.get("taskbar.enabled");

const tray = getMainTray();
tray?.setTaskbarLyricShow(envEnabled);
const tray = getMainTray();
tray?.setTaskbarLyricShow(envEnabled);

if (envEnabled) {
taskbarLyricWindow.create();
if (envEnabled) {
taskbarLyricWindow.create();
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

if (isMac)else 两个分支中都重复获取了 envEnabledtray 实例。可以将这些通用操作提取到 if 语句之前,以减少代码重复,使逻辑更清晰。

  const envEnabled = store.get("taskbar.enabled");
  const tray = getMainTray();

  // macOS 使用状态栏歌词,不使用任务栏歌词窗口
  if (isMac) {
    tray?.setMacStatusBarLyricShow(envEnabled);
  } else {
    tray?.setTaskbarLyricShow(envEnabled);

    if (envEnabled) {
      taskbarLyricWindow.create();
    }
  }

Comment on lines +59 to +67
ipcMain.on("mac-toggle-statusbar-lyric", (_, show: boolean) => {
if (!isMac) return;
macStatusBarLyricEnabled = show;
tray?.setMacStatusBarLyricShow(show);
// 如果关闭,恢复显示歌曲标题
if (!show) {
tray?.setTitle(currentSongTitle);
}
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

mac-toggle-statusbar-lyric 事件处理器中,当关闭状态栏歌词时 (showfalse),会先调用 tray?.setMacStatusBarLyricShow(show),该函数内部会将托盘标题设置为 appName,然后又会调用 tray?.setTitle(currentSongTitle)。这会导致一次不必要的标题设置和潜在的界面闪烁。

建议将 currentSongTitle 作为参数传递给 setMacStatusBarLyricShow,由其内部统一处理标题恢复逻辑,从而简化代码并避免冗余调用。

  ipcMain.on("mac-toggle-statusbar-lyric", (_, show: boolean) => {
    if (!isMac) return;
    macStatusBarLyricEnabled = show;
    tray?.setMacStatusBarLyricShow(show, currentSongTitle);
  });

Comment on lines +374 to +376
if (this._checkInterval) {
clearInterval(this._checkInterval);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

类成员 _checkInterval 被声明但从未被赋值,其初始值为 null。因此,这里的 if (this._checkInterval) 判断条件永远为假,这块代码是无法访问的死代码。如果这个变量未来没有计划使用,建议移除这部分检查逻辑,以保持代码整洁。同时也可以移除在第 269 行的 _checkInterval 声明。

@Pissofdvpe Pissofdvpe marked this pull request as draft February 7, 2026 14:45
@apoint123
Copy link
Collaborator

这个 “状态栏歌词” 和现有的任务栏歌词实现看起来并没有什么关联,只是将托盘上应用图标旁边的名称换成了元数据和歌词。这个实现无法拥有任何动画效果或者自定义功能,也无法使用设置中的任务栏歌词选项。

建议改名并在设置里面添加一个 MacOS 专属的选项,比如 “在托盘上显示歌词” 之类的,或者至少让它和现有的任务栏歌词解耦

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants