Skip to content

v1.0.0#362

Draft
maotoumao[bot] wants to merge 74 commits into
masterfrom
dev
Draft

v1.0.0#362
maotoumao[bot] wants to merge 74 commits into
masterfrom
dev

Conversation

@maotoumao

@maotoumao maotoumao Bot commented Mar 14, 2026

Copy link
Copy Markdown

Draft PR for v1.0.0 release

maotoumao and others added 30 commits March 25, 2026 00:03
> [!CAUTION]
> PR 请提交到 dev 分支 (Please submit PR to dev branch)
> 提到其他分支将会直接关闭 PR

## PR 解决的问题 (PR Summary)

旧版数据迁移流程虽然能够恢复歌单和歌曲数据,但没有把已下载歌曲对应的下载元数据一并迁移,导致升级后这部分歌曲会丢失本地下载状态。

这个 PR 在执行旧版 IndexedDB 数据迁移时,额外恢复已下载歌曲的 downloadData
信息,并将这些歌曲重新加入“已下载”歌单,确保迁移完成后仍能正确识别本地下载文件路径和音质信息。

## 影响范围 (Impact Scope)

影响旧版本用户升级到当前版本时的数据迁移流程,主要包括:

1. 从旧版歌曲记录中提取已下载歌曲的下载信息。
2. 将下载信息写回新的 mediaMeta 存储。
3. 将对应歌曲补入“已下载”歌单。

不影响新安装用户,也不影响已经完成迁移的用户日常使用流程。
…Migration

- Wrap musicDB usage in try/finally to guarantee close() on IDB read errors
- Wrap download data restoration in try/catch to prevent blocking subsequent migration steps
- Simplify downloadedItems from Map to Array (source musicPool already deduplicated)
- Fix duplicate comment numbering (step 3 → 3 and 4)
- Add console.warn for songs not found in pool during sheet assembly
…ndows

On Windows, calling hide() on an already-minimized window causes Chromium to release the GPU compositor surface. Subsequent restore() then leaves the client area blank (window frame restores, content stays white) with no error logs. Typical repro: minimize main window -> click X on the taskbar thumbnail preview -> reopen from tray icon.

Switch to minimize()+setSkipTaskbar(true) on Windows so the window keeps WS_VISIBLE and Chromium never tears down the compositor. Other platforms keep hide().

Fixes #412
## 问题

在歌曲右键菜单中,当一首歌同时满足以下两个条件时,会出现两个「删除本地文件」菜单项:

1. 歌曲被 `downloadManager.isDownloaded()` 标记为已下载
2. 歌曲的 `platform === LOCAL_PLUGIN_NAME`(纯本地歌曲)

### 根因

`MusicItemMenu.tsx` 中有两个独立的删除逻辑分支:

- **`downloaded` 路径(第 237 行)**:删除已下载的本地文件,条件是歌曲已下载
- **`allLocal` 路径(第 279 行)**:删除纯本地文件(移至回收站 + 从所有歌单移除 +
从播放队列移除),条件是选中项全是本地歌曲

当一首歌同时满足两者时,两个分支都添加了删除项,导致重复。

## 修复

在 `downloaded` 路径增加 `singleItem.platform !== LOCAL_PLUGIN_NAME`
排除条件,本地歌曲的删除由 `allLocal` 路径统一处理(它的逻辑更完整)。

## 相关

- 这是已有 bug,并非本次新引入

### 相关截图
<img width="1730" height="974" alt="PixPin_2026-06-03_20-25-29"
src="https://github.com/user-attachments/assets/31335b28-2c52-4c3b-86a0-9c64e7ac7bfe"
/>
Tier1 patch/minor: axios 1.17, better-sqlite3 12.10, dayjs, dompurify, framer-motion, hls.js, jotai, music-metadata, nanoid, p-queue, qs, react/react-dom 19.2.7, react-router, react-virtuoso, webdav, yauzl.

Tier2: i18next 26.3.1 + react-i18next 17.0.8 (paired major).

Tier3: marked 18.0.5.

downloadTask: coerce axios header values to string for tightened AxiosHeaderValue type.

Held back: lucide-react (v1 dropped brand icons), http/https-proxy-agent (v8+ ESM-only, incompatible with moduleResolution:node), tinykeys.
Switch tsconfig module/moduleResolution from commonjs/node to esnext/bundler so TS reads package.json exports types (matches webpack's conditionNames-based resolution).

Remove legacy wildcard paths mapping '*' -> node_modules/* which hijacked @types auto-discovery under bundler (was the cause of 542 spurious TS7016/7026 errors).

Unblocked by the migration: upgrade tinykeys 3->4 (v3 exports lacked a types condition; API identical) and http/https-proxy-agent 7->9 (ESM-only, types only via exports).

Verified: tsc 0 errors, eslint clean, app launches (ProxyManager + 36 plugins OK).
## 影响范围

- 新增 `@infra/local-music/update-music-item` IPC 通道
- 新增 `node-id3` 依赖(纯 JS,无需编译)
- 新增 `metadataWriter.ts` — 文件标签写入模块
- 新增 `EditMusicMetaModal` 弹窗组件
- 本地歌曲右键菜单新增「编辑元数据」入口

## 功能说明

对纯本地歌曲右键 → 「编辑元数据」,可修改标题/歌手/专辑。

写入策略:
- `.mp3` 文件 → 使用 node-id3 写入 ID3v2 标签 + 更新数据库
- `.flac`/`.m4a`/`.ogg` 等 → 仅更新数据库,弹窗显示格式提示
- `.m4s`/`.wav` → 显示不支持提示,仅更新数据库

## 截屏

| 改动前 (Before) | 改动后 (After) |
| ------ | ------ |
| 本地歌曲右键无编辑选项 | 右键出现「编辑元数据」|
| 歌曲元数据无法修改 | 弹窗可编辑标题/歌手/专辑,MP3 文件标签同步写入 |

<img width="1730" height="974" alt="PixPin_2026-06-03_19-36-44"
src="https://github.com/user-attachments/assets/46c7a306-e03b-4c4d-baf2-984e304bcf74"
/>
<img width="1730" height="974" alt="PixPin_2026-06-03_19-36-58"
src="https://github.com/user-attachments/assets/d840648d-4c78-4de8-b3e1-a1749c490cf0"
/>
Remove deprecated stub types @types/big-integer, @types/sharp.

Bump @types/yauzl 2->3 to match runtime yauzl v3.

axios 1.18, better-sqlite3 12.11.1, dompurify 3.4.11, jotai 2.20.1, nanoid 5.1.14.

react-router 7->8 (declarative-mode hooks unchanged; framework-mode/react-router-dom breaks not used).

Held back: sharp 0.35 (removes ./package.json from exports, breaks @timfish/forge-externals-plugin's require.resolve).

Verified: tsc 0 errors, eslint clean, app launches.
@electron-forge/* 7.11.2, @types/react 19.2.17, @types/qs 6.15.1, eslint-import-resolver-typescript 4.4.5, prettier 3.8.4, globals 17.6.0, sass 1.101.0, ts-loader 9.6.1, typescript-eslint 8.61.1, @vercel/webpack-asset-relocator-loader 1.10.0.

Verified: tsc 0 errors, eslint clean, app launches.
lucide v1 removed brand icons (Github/Twitter) for trademark reasons; per lucide's guidance use Simple Icons (CC0). Inline GitHub + X logos as local BrandIcons components matching lucide's size/className API — no new dependency, no webpack/SVGR changes.

AboutSection now imports GithubIcon/XIcon locally; SocialIcon type covers both lucide and brand icons.

Verified: tsc 0 errors, eslint clean, app launches.
Forge 7.x monkeypatches this loader and only supports the 1.7.x line; 1.10.0 (bumped in the previous dev-tooling round) injects a renderer runtime that references __dirname, which breaks under newer Electron (electron/forge#3964). Revert to the Forge-compatible 1.7.3 to remove the latent breakage.

Note: Electron stays at 40.4.0 — Electron 42 requires Forge 8 (still pre-release) for proper native/renderer handling; deferring that upgrade.
- stale: mark+close inactive issues/PRs (60d/14d), exempt accepted/pinned/roadmap/security
- maintainer-commands: /accept labels issues, clears stale, reopens if needed
- pr-branch-guard: close PRs not targeting dev
- pr-approved-gate: close PRs not linked to a maintainer-applied accepted issue
- templates: document accepted-based workflow and PR linkage requirement
新增 download.interval 与 download.intervalJitter 配置,限制相邻两次下载任务启动之间的最小间隔并叠加随机抖动,覆盖 add/resume/retry 全部入口,默认关闭。
代理 worker 用 stream.pipeline 替代裸 pipe 并过滤逐跳头,客户端断连时中止上游请求,新增 30s 上游空闲超时,消除流中途出错导致的 worker 崩溃与 socket 泄漏。

播放器以 2s 容差区分自然播完与流截断,截断时从断点重新拉源续播,按断点是否前进防止死循环,切歌时按 isSameMedia 重置续播状态。VBR/元数据时长虚高导致的误判统一按自然播完前进,保证播放永不卡死;ended 处理整体捕获异常杜绝未处理 rejection。抽取 resolveSource 与 IResolveSourceOptions 收敛重复音源解析逻辑。
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.

4 participants