Skip to content

🦄 refactor: 下载管理接入 Rust 目录扫描 & 任务栏歌词跟随歌曲封面颜色#864

Merged
imsyy merged 4 commits into
devfrom
dev-dl-rust
Feb 11, 2026
Merged

🦄 refactor: 下载管理接入 Rust 目录扫描 & 任务栏歌词跟随歌曲封面颜色#864
imsyy merged 4 commits into
devfrom
dev-dl-rust

Conversation

@imsyy
Copy link
Copy Markdown
Member

@imsyy imsyy commented Feb 10, 2026

No description provided.

@imsyy
Copy link
Copy Markdown
Member Author

imsyy commented Feb 10, 2026

/gemini review

Copy link
Copy Markdown
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

本次重构将下载管理的目录扫描功能接入了 Rust 实现,这是一个很好的性能优化。代码结构也通过提取 _scan 私有方法和 processMusicList 辅助函数得到了改善,提高了模块化和代码复用性。

我发现了一些可以改进的地方:

  1. 数据库查询逻辑中存在一个关于路径匹配的潜在 bug,可能导致查询结果不精确。
  2. IPC 处理函数中存在少量重复代码,可以进行提取以提高可维护性。

具体的修改建议请见我的评论。

Comment thread electron/main/database/LocalMusicDB.ts Outdated
Comment thread electron/main/ipc/ipc-file.ts Outdated
@imsyy imsyy changed the title 🦄 refactor: 下载管理接入 Rust 目录扫描 🦄 refactor: 下载管理接入 Rust 目录扫描 & 任务栏歌词跟随歌曲封面颜色 Feb 10, 2026
@imsyy
Copy link
Copy Markdown
Member Author

imsyy commented Feb 10, 2026

/gemini review

Copy link
Copy Markdown
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 是一次不错的重构,将下载管理接入了 Rust 目录扫描,并实现了任务栏歌词颜色跟随歌曲封面。代码结构和类型安全方面都有所改进。我发现了一个高危问题,即后端 MusicTrack 对象到前端 SongType 对象的映射不正确,这可能导致前端功能异常。我已经为此提供了一个修复建议。除此之外,其他的重构,如服务和工具函数的提取,都做得很好。

Comment thread electron/main/utils/format.ts
@imsyy
Copy link
Copy Markdown
Member Author

imsyy commented Feb 11, 2026

/gemini review

Copy link
Copy Markdown
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 包含两项主要变更:为下载管理接入了基于 Rust 的目录扫描功能,以及实现了任务栏歌词颜色跟随歌曲封面颜色的功能。代码重构做得很好,特别是 LocalMusicService 中扫描逻辑的拆分和数据格式化的集中处理,使得代码更清晰、更模块化。

我的主要反馈是关于类型安全性的一个退步。在几处代码中,用于 IPC 传输的歌曲数据的特定类型被替换为了 Record<string, unknown>[]。虽然这可能解决了眼前的类型不匹配问题,但从长远来看,这会降低代码的安全性和可维护性。我建议为这些数据重新引入 DTO。此外,我还发现了一个在 IPC handler 中可以提升类型安全的小机会。

总的来说,这是一次很棒的 PR,带来了显著的改进。

Comment thread electron/main/ipc/ipc-file.ts
Comment thread src/core/resource/DownloadManager.ts
Comment thread src/views/Local/layout.vue
@imsyy imsyy marked this pull request as ready for review February 11, 2026 05:41
@imsyy imsyy requested a review from Copilot February 11, 2026 06:19
@imsyy
Copy link
Copy Markdown
Member Author

imsyy commented Feb 11, 2026

@copilot 看看💩代码

Copy link
Copy Markdown

Copilot AI commented Feb 11, 2026

@imsyy I've opened a new pull request, #866, to work on those changes. Once the pull request is ready, I'll request review from you.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

该 PR 主要将下载管理与本地音乐扫描逻辑接入 Rust 扫描/本地库 DB,并让任务栏歌词颜色跟随歌曲封面主色;同时统一了歌曲 size 字段为字节并改进前端展示。

Changes:

  • 下载目录/本地库扫描改为通过主进程 LocalMusicService + Rust 扫描结果回传,并复用 DB 查询。
  • 任务栏歌词主题色逻辑调整为读取封面主题色并发送到任务栏侧。
  • 统一 size 为字节:后端/接口不再提前换算 MB,前端使用 formatFileSize 统一展示。

Reviewed changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/views/Local/layout.vue 本地库同步接收数据直接交给 formatSongsList,并调整总容量计算口径/单位。
src/views/Download/layout.vue 下载管理页面模板格式调整(无核心逻辑变化)。
src/views/Download/downloaded.vue 下载完成列表不再强制隐藏封面。
src/utils/initIpc.ts 任务栏请求数据时补发封面主色。
src/utils/helper.ts handleSongQuality 增加提前返回逻辑(当前实现存在潜在行为回退问题)。
src/utils/color.ts 将“任务栏主题色”改为“封面颜色”发送逻辑,并从 statusStore.songCoverTheme 读取。
src/core/resource/DownloadManager.ts 下载完成列表改用新 IPC get-downloaded-songs 获取并交给 formatSongsList
src/components/Setting/config/lyric.ts 设置文案从“跟随主题色”改为“跟随封面颜色”。
src/components/Player/FullPlayer.vue 增加 mousemove/click 触发 playerMove,改善自动隐藏交互。
src/components/Card/SongCard.vue 歌曲大小展示改为 formatFileSize(字节制)。
src/api/streaming/subsonic.ts Subsonic 歌曲 size 不再转换为 MB,保持字节。
electron/main/utils/format.ts 新增 processMusicList:统一补齐 name/cover/quality 等字段供渲染进程使用。
electron/main/services/MusicMetadataService.ts setMetadata 引入明确的输入类型 MusicMetadataInput
electron/main/services/LocalMusicService.ts 将扫描逻辑抽到私有 _scan,新增 scanDirectory 支持下载目录扫描。
electron/main/ipc/ipc-file.ts 新增 get-downloaded-songs IPC,并复用 processMusicList;封面目录路径提取为函数。
electron/main/database/LocalMusicDB.ts 新增按目录前缀查询 getTracksInPath,用于下载目录扫描后查询。

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/utils/helper.ts
const settingStore = useSettingStore();
const { disableAiAudio } = settingStore;

if (!song) return undefined;
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

handleSongQuality 里用 if (!song) return undefined; 会把 0(例如本地 bitrate 为空时用 0 兜底)也当成无效输入,导致本地歌曲音质从原本的 LQ 变成 undefined,从而不显示音质标签/影响逻辑。建议改为仅对 null/undefined 做提前返回(例如 song == null),保留数字 0 的正常分支处理。

Suggested change
if (!song) return undefined;
if (song == null) return undefined;

Copilot uses AI. Check for mistakes.
Comment on lines +131 to 133
ipcMain.handle("set-music-metadata", async (_, path: string, metadata) => {
return musicMetadataService.setMetadata(path, metadata);
});
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

这里 metadata 参数没有类型注解,会在开启 noImplicitAny/strict 时变成隐式 any,导致 node 端 typecheck 失败。建议把参数类型显式标注为 MusicMetadataInput(可从 MusicMetadataService 导出/引入),或至少标注为 unknown 并在 setMetadata 内做校验/转换。

Suggested change
ipcMain.handle("set-music-metadata", async (_, path: string, metadata) => {
return musicMetadataService.setMetadata(path, metadata);
});
ipcMain.handle(
"set-music-metadata",
async (_, path: string, metadata: Parameters<MusicMetadataService["setMetadata"]>[1]) => {
return musicMetadataService.setMetadata(path, metadata);
},
);

Copilot uses AI. Check for mistakes.
Comment on lines 116 to 120
case "end":
if (event.deletedPaths && event.deletedPaths.length > 0) {
if (!ignoreDelete && event.deletedPaths && event.deletedPaths.length > 0) {
this.db?.deleteTracks(event.deletedPaths);
}
resolve();
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

scanDirectory() 通过 ignoreDelete=true 完全跳过了 deletedPaths 的处理,这会导致扫描目录内被删除/移动的文件仍然残留在 DB 中,getTracksInPath() 也会继续返回这些陈旧记录(例如下载目录里手动删歌后列表仍显示)。建议在 ignoreDelete 场景下仅过滤并删除属于本次扫描目录前缀的 deletedPaths(避免误删其它库目录),而不是全部忽略。

Copilot uses AI. Check for mistakes.
Comment on lines +308 to 312
// 全部音乐大小
const allMusicSize = computed<number>(() => {
const total = listData.value.reduce((total, song) => (total += song?.size || 0), 0);
return Number((total / 1024).toFixed(2));
const totalBytes = listData.value.reduce((total, song) => (total += song?.size || 0), 0);
return Number((totalBytes / (1024 * 1024 * 1024)).toFixed(2));
});
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

allMusicSize 实际上是基于 listData 计算的(会受搜索/文件夹筛选影响),但注释现在写成“全部音乐大小”,容易误导后续维护。建议把注释改回“基于当前筛选结果的大小”,或改为使用 localStore.localSongs/未筛选数据来真正表示“全部”。

Copilot uses AI. Check for mistakes.
Comment on lines 355 to 396
@@ -400,13 +386,13 @@ const getAllLocalMusic = debounce(
// 记录初始歌曲数量,用于计算新增数量
const initialSongCount = localStore.localSongs.length;
// 累积接收到的tracks
const receivedTracks: MusicTrackData[] = [];
const receivedTracks: Record<string, unknown>[] = [];
let isCompleted = false;
// 清理之前的监听器
window.electron.ipcRenderer.removeAllListeners("music-sync-tracks-batch");
window.electron.ipcRenderer.removeAllListeners("music-sync-complete");
// 监听批量track数据
const tracksBatchHandler = (_event: unknown, tracks: MusicTrackData[]) => {
const tracksBatchHandler = (_event: unknown, tracks: Record<string, unknown>[]) => {
if (!loading.value || isCompleted) return;
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

本地同步的 tracks/receivedTracks 改成了 Record<string, unknown>[],会让 formatSongsList(sourceTracks) 依赖的字段(如 id/name/artist/album/path/size/quality)完全失去编译期约束,后续 IPC 结构一变更就只能在运行时爆雷。建议定义一个明确的 IPC Track 类型(可复用 native/tools 的 MusicTrack 字段并补充 name/quality/cover 等映射字段),并在这里使用该类型而不是 Record<string, unknown>

Copilot uses AI. Check for mistakes.
@imsyy imsyy merged commit 4c10224 into dev Feb 11, 2026
10 checks passed
@imsyy imsyy deleted the dev-dl-rust branch February 11, 2026 06:55
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.

3 participants