alger
837f0268d5
fix(player): 合并外部贡献后的集成修复
...
- PlayBar 下载按钮补 isElectron 守卫,Web 端不再显示无效按钮(#708 评审意见)
- preloadNextSongs 恢复 800ms 短去抖,避免快速切歌时音源请求风暴(#712 评审意见)
- 清理合并后未使用的导入
2026-07-05 14:00:07 +08:00
alger
8ea13e04f0
Merge pull request #712 from daili115/trae/agent-m1V9o5
...
feat: 优化音乐播放性能,实现异步加载和即时预加载
2026-07-05 13:55:34 +08:00
alger
91a3259e27
Merge pull request #708 from jiang-LJ/main
...
feat(player): 在播放栏添加下载当前歌曲按钮
2026-07-05 13:55:34 +08:00
alger
ecb85f0146
Merge pull request #676 from chengww5217/refactor/persisted-storage
...
refactor(persist): localStorage 配额防护与历史持久化重写
2026-07-05 13:55:20 +08:00
alger
6bea735aef
Merge pull request #675 from chengww5217/fix/local-music-playback
...
fix(local-music): 修复本地音乐播放失败、进度异常与切歌失效
2026-07-05 13:55:20 +08:00
alger
d9b102879f
Merge pull request #677 from chengww5217/chore/fix-existing-lint
...
ci: 修复 PR Code Quality job 失败(存量 lint + typecheck 拿不到 unplugin d.ts)
2026-07-05 13:55:09 +08:00
daili115
c5035b0583
feat: 修复软件切歌慢问题
...
Co-authored-by: traeagent <traeagent@users.noreply.github.com >
2026-06-25 07:41:15 +00:00
jiang-LJ
7792eeac2e
feat(player): 在播放栏添加下载当前歌曲按钮
2026-06-17 21:57:01 +08:00
chengww
1a8b5f4977
ci: 加 setup-bun 让 lint:i18n 步骤能跑
...
package.json 里 lint:i18n = "bun scripts/check_i18n.ts",但 pr-check.yml
只装了 Node 没装 bun,I18n check 步骤报 sh: bun: not found。
之前这个错误被前两步(lint / typecheck)的失败遮住,前两步修了之后才暴露。
用官方 oven-sh/setup-bun 一步搞定,放在 setup-node 之后、install 之前。
2026-05-18 00:07:05 +08:00
chengww
95694057ec
ci: typecheck 前先跑 build 让 unplugin 生成自动 import d.ts
...
tsconfig.web.json 的 compilerOptions.types 显式 require
src/renderer/{auto-imports,components}.d.ts,这两个文件由
unplugin-auto-import / unplugin-vue-components 在 vite 启动时生成,
且被 .gitignore 排除(58922dc 维护者主动设置)。
CI 直接跑 typecheck 拿不到 d.ts 会报 TS2688,导致所有 PR 都过不了
Code Quality job。在 Type check 步骤前插入一次 npm run build 触发
unplugin 生成 d.ts,同时顺带验证 build 链路(一次到位,不增加额外
专用脚本,CI 多 30-60s 但能拦下 build 阶段的回归)。
本地验证:删除两个 d.ts 后跑 npm run build 重新生成,typecheck 通过。
2026-05-18 00:01:19 +08:00
chengww
938c497ca3
chore: 修复 main 上的存量 lint 错误
...
pr-check.yml 只在 PR 触发,main push 不跑 lint,导致存量错误一直未被发现,
PR #675 / #676 都被 Code Quality job 拦下。
- 9 处 prettier/prettier 格式错误:StickyTabPage.vue / RadioCard.vue /
list/index.vue / mv/index.vue / podcast/index.vue 的属性换行与 import
排序,全部 eslint --fix 自动修复
- 1 处 no-undef ScrollToOptions(StickyTabPage.vue:79):在 eslint.config.mjs
的 .ts 与 .vue 配置块同时补 ScrollToOptions 到 globals,与既有的
ScrollBehavior 同级;TypeScript DOM lib 类型不在 globals.browser 里,
需手动声明
2026-05-17 23:54:28 +08:00
chengww
a078e37e2c
fix(build): renderer 单 chunk 打包,规避 chunk 间循环依赖 TDZ 白屏
...
store/index.ts 用 `export *` 聚合所有 store + 抽出的共享工具(如
debouncedStorage)被多 store 引用,Vite 6 默认拆分会让 utils 合并到
entry chunk,再与 store chunk 形成 index ↔ store 循环;当循环 chunk
顶层同步访问对方导出的 const(如 `persist: { storage: debouncedLocalStorage }`),
生产构建会触发 TDZ 报错 `Cannot access 'debouncedLocalStorage' before
initialization`,表现为打包后白屏(dev 不分包不暴露)。
Electron 桌面端无 CDN/首屏体积顾虑,单 chunk 是最简洁的兜底。
2026-05-17 23:38:33 +08:00
chengww
405b144e66
refactor(playHistory): v1 旧 localStorage key 清理与调用方对齐
...
老用户升级后清掉 v1 时代独立 key 释放配额,调用方切到 store API。
- player.ts initializePlayState 调用从 migrateFromLocalStorage 切到
cleanupLegacyPlayHistoryStorage:不再做数据迁移(历史是低关键性
衍生数据,老用户重新听几次即可),仅清掉旧 musicHistory/podcastHistory/
playlistHistory/albumHistory/podcastRadioHistory/playHistory-migrated/
playMode 这 7 个旧 key,避免和新 play-history-store key 双倍占用
- SystemTab.vue 清缓存的 case 'history' 改走 usePlayHistoryStore().
clearMusicHistory(),与 v1 时代行为对齐(只清音乐历史,不动 podcast/
playlist/album/podcastRadio);移除 case 'settings' 里的
removeItem('playMode')——已并入 player-core-store
2026-05-17 23:08:52 +08:00
chengww
761884f23a
refactor(playHistory): 持久化重写,统一防抖落盘与序列化兜底
...
把 playHistory 接入 utils/debouncedStorage 与 utils/persistedSong,
配合 add* 方法重构与 clearAll 同步落盘,闭合 localStorage 配额防护。
- musicHistory 类型从 SongResult 收敛到 MusicHistoryItem(精简子集),
导出 MinifiedDjProgram、stripBase64Covers,给 podcast/playlist/album/
podcastRadio 历史也做顶层 picUrl/coverImgUrl/coverUrl 的 base64 兜底
- serializePlayHistoryState 提取为模块级函数,给 persistedstate.serializer
与 clearAll 同步落盘共用,避免格式漂移;isPodcast/program 字段必须
保留——playbackController.playTrack 用 isPodcast 决定写哪条历史
- 5 个 add* 全部重写成单步 ref 重赋值,避免 splice/pop/unshift 多次
触发 watch 与持久化;命中已有条目时累加 count + 刷新 lastPlayTime,
picUrl/al 用新数据覆盖(封面可能换了短引用)
- clearAll 增加 flushDebouncedStorage + 同步 setItem 空状态,防止
kill -9 落在 2s 防抖窗口里导致旧历史残留
- heatmap/index.vue 类型切到 MusicHistoryItem,移除 music.artists
兜底(minifySong 已合并 ar/artists,只剩 ar)
2026-05-17 23:08:22 +08:00
chengww
537e280fdd
refactor(persist): 抽公共防抖 storage 与 minifySong 工具,playlist/playerCore 接入
...
把 9caaec3 在 playlist 内联的 minifySong + debouncedLocalStorage 抽到
utils 共用,playerCore 同步接入,为后续推广到 playHistory 做准备。
- 新增 utils/debouncedStorage.ts:高频状态变更(volume 拖动、isPlay
切换)2s 防抖落盘,beforeunload 钩子兜底刷盘;多 store 共用同一
pendingWrites map,flush 时一次写完所有 pending key
- 新增 utils/persistedSong.ts:minifySong 剥离 base64 picUrl、仅保留
local:// 永不过期的 playMusicUrl;ar.length 守卫避免空数组吞掉
s.artists 兜底;al.id 守卫避免序列化出无 id 空壳
- playlist.ts 删除内联实现改用 import,行为不变
- playerCore.ts 切到防抖落盘并 minify playMusic;id 守卫避免空
playMusic 走 minify 后失去 Object.keys().length===0 判空能力,
下次启动会误恢复一首无 id 的空歌
Trade-off:极端非正常退出(kill -9 / 断电)下最近 2s 的 volume /
isPlay / playMusic 变更会丢——这些状态丢一次无大碍,可接受
2026-05-17 23:07:58 +08:00
chengww
15258f28fd
fix(local-music): 封面落盘 + URL 编码统一,修复持久化配额与编码边界
...
- 新增 src/shared/localUrl.ts 共用 local:// 编码:按路径段 encodeURIComponent,
避免整体编码把 / 转成 %2F 引发 Chromium 解析边界差异,同时正确处理
空格/中文/# 等特殊字符(封面落到含空格目录时 Image loader 会加载失败)
- 封面从内嵌 base64 Data URL 改为 userData/AudioCovers/<sha256>.<ext> 落盘,
MAX_COVER_BYTES 1MB→8MB;老条目(无 coverPath 字段)扫描时一次性自愈
- playlist minify 剥离 base64 picUrl 并仅持久化 local:// 永不过期的 playMusicUrl,
防止单张 base64 封面撑爆 localStorage 5MB 配额导致整个 playList 写入失败;
localStorage 写入加 try/catch 兜底,避免配额超限时直接抛异常
2026-05-17 23:07:17 +08:00
chengww
fa818a020f
fix(player): 双击歌曲时同步设置播放列表上下文
...
BaseSongItem 双击和右键菜单"播放"只调了 setPlay,未 emit 'play',
导致父组件 setPlayList 不会执行,上下一首切换失效。抽出统一入口
先 emit 再触发播放,与点击播放按钮行为对齐。
2026-05-17 23:07:01 +08:00
chengww
c15a10c098
fix(local-music): 主进程实现 Range/206 让本地音乐 seek/快进恢复
...
切到 protocol.handle 后,audio 元素发的 Range 请求会带 HTTP 头到达
主进程;net.fetch(file://) 既不识别 Range 也不带 Accept-Ranges,导致
浏览器认为 local:// 不支持随机访问,seek 时只能从头加载,表现为
快进失效、退出后恢复播放从 0 开始。
新增 buildLocalFileResponse:
- 无 Range:200 + Accept-Ranges: bytes,让 audio 知道支持随机访问
- 有 Range:206 + Content-Range,用 fs.createReadStream 切片返回
- 非法 Range:416 + Content-Range: bytes */total
顺手把 fs.existsSync 换成 stat,一次拿文件大小且过滤掉目录。
2026-05-17 23:07:01 +08:00
chengww
51f1aaba55
chore: 忽略 *.tsbuildinfo 编译缓存
2026-05-17 23:07:01 +08:00
chengww
0c0189bcef
fix(local-music): 注册 local 协议为特权 scheme 修复本地音乐 CORS 报错
...
- main/index.ts 在 app.whenReady 之前调用 registerSchemesAsPrivileged,
把 local 标记为 standard/secure/supportFetchAPI/stream/corsEnabled/bypassCSP,
让 http 页面(dev server / 生产)可跨协议加载本地音频
- fileManager.ts 用 Electron 25 起推荐的 protocol.handle 替代已弃用的
registerFileProtocol,内部转发到 file:// 自动支持 Range / 流式播放
- 修复 macOS/Linux 上去掉前导斜杠后丢失绝对路径前缀的问题
2026-05-17 23:07:01 +08:00
alger
ee98eb0266
fix(player): 私人 FM 模式下点击下一首按钮可正常切歌
...
FM 播放列表只保留 1 首,原 _nextPlay 走到"顺序模式 + 最后一首"
分支只弹"列表已播完"提示,仅 audioService end 事件中拉取下一首
FM 的逻辑生效,导致用户手动点击下一首无效(issue #666)。
抽出 _nextFmPlay,_nextPlay 入口检测 isFmPlaying 直接路由到 FM
分支;MusicHook end 事件去掉重复的 FM 处理,统一走 nextPlayOnEnd。
2026-05-10 13:00:55 +08:00
alger
d722728ee0
chore(scripts): 移动 fix-sandbox.js 到 scripts 目录
...
将根目录的运维脚本统一收纳到 scripts/,并把脚本内的相对路径
改为基于 __dirname,避免在仓库子目录执行时找不到 node_modules。
2026-05-10 12:34:53 +08:00
alger
5ba9e6591a
refactor(lyric): 抽取全屏背景/文字颜色逻辑为 useLyricBackground composable
...
MusicFull.vue 与 MusicFullMobile.vue 各自持有的 setTextColors /
currentBackground / animationFrame / isDark 合并到共享 composable,
消除两份几乎一致的包装逻辑。Mobile 的 --bg-color 差异通过 writeBgColor
option 注入,行为等价。
2026-05-10 12:34:53 +08:00
Alger
7e95ab69be
Merge pull request #654 from chengww5217/fix/unmute-restore-volume
...
fix(player): 静音保留原音量,解除后可恢复
2026-05-10 12:23:34 +08:00
Alger
7c6448733d
Merge pull request #653 from chengww5217/fix/download-config
...
fix(download): 下载设置抽屉打开时路径显示为空
2026-05-10 12:23:31 +08:00
chengww
2b1024ca24
fix(player): 静音保留原音量,解除后可恢复
...
- playerCore 新增持久化 isMuted 状态及 setMuted/toggleMute,静音时音频输出置 0 但 volume 保持不变
- 音量 > 0 时自动解除静音
- useVolumeControl 移除原 0↔30 切换;滑块/百分比展示真实音量,图标反映静音态
- 三个播放栏的音量滑块在静音时 disabled;PlayBar 百分比文字同步置灰(仅文字颜色)
2026-04-26 21:47:11 +08:00
chengww
a62f525840
fix(download): 下载设置抽屉打开时路径显示为空
...
get-store-value 主进程用 ipcMain.on 同步返回,renderer 却用 invoke 读取会直接
reject,导致 initDownloadSettings 中断、已保存的下载路径等配置回读失败。改为
sendSync,与项目其它调用点保持一致。
contentLength 类型错误非本次提交引入,因无法通过 precommit 检查,故一并修复。
2026-04-26 21:05:59 +08:00
alger
97220761cf
fix(lyric): 重启后桌面歌词显示无歌词
...
playerCore.playMusic 整体替换 (id 不变) 时, lyric watcher 的响应式追踪不可靠
点击播放走 playTrack 流程也未必能可靠触发解析
- 提取 ensureLyricsLoaded 到 module 级别, 直接读 playMusic.value 解析
- openLyric 入口主动调用 (重启首次打开桌面歌词场景)
- onLyricWindowReady 兜底 (窗口异步就绪时 lyric 字段可能刚到位)
- audioService.on('play') 兜底 (重启后首次点击播放场景)
- 在线歌曲 lyric 字段缺失时, 主动调 getMusicLrc API 兜底
2026-04-19 16:15:09 +08:00
alger
7282e876f4
fix(lyric-window): 锁定状态启动时同步穿透并禁用 resize
...
- 重启应用恢复锁定时, 主进程主动 setIgnoreMouseEvents(true), 修复鼠标无法穿透
- 锁定时 setResizable(false), 隐藏窗口边缘 resize 光标
- 由 set-lyric-lock-state IPC 统一驱动, 后续 polling 按位置精细纠正
2026-04-19 15:44:28 +08:00
alger
6b22713854
perf(lyric-window): 仅在锁定+可见时启用鼠标位置轮询
...
- 新增 set-lyric-lock-state IPC, 渲染端 watch isLock 同步到主进程
- 主进程通过 isLyricLocked + isLyricWindowVisible 控制轮询启停
- 监听窗口 show/hide/minimize/restore, 隐藏时停止 50ms 轮询
- 解锁状态下 DOM mouseenter/mouseleave 已足够, 无需轮询兜底
2026-04-19 15:31:23 +08:00
alger
0d960aa8d5
Merge pull request #645 from geewon1i/Lyric-lock-icon
...
fix(歌词悬窗): 通过主进程周期检测鼠标位置纠正悬停状态,修复鼠标快速移出时锁图标残留问题
Closes #606
2026-04-19 15:29:06 +08:00
kimjiwon
e066efb373
add main-process cursor presence sync for locked lyric window
2026-04-12 13:29:02 +08:00
alger
b0b3eb3326
ci: 移除 PR 检查中已删除的 dev_electron 分支
2026-04-11 22:53:17 +08:00
alger
4a50886a68
ci: 添加 PR 提交规范检查和 commitlint
...
- 添加 commitlint 及 Conventional Commits 规范配置
- 添加 commit-msg husky hook 本地校验提交信息
- 添加 GitHub Actions PR 检查 workflow:
- PR 标题符合 Conventional Commits
- 所有 commit message 符合规范
- ESLint + TypeScript 类型检查 + i18n 检查
2026-04-11 22:50:20 +08:00
Alger
f9222b699d
Merge pull request #644 from algerkong/fix/mpris-review-643
...
fix(mpris): 修复 MPRIS 模块多项安全和性能问题
2026-04-11 22:44:38 +08:00
alger
030a1f1c85
fix(mpris): 修复 MPRIS 模块多项安全和性能问题
...
- 将 fix-sandbox.js 从 postinstall 移除,避免 npm install 时执行 sudo
- 修复 play/pause/stop 事件语义错误,不再全部映射到 togglePlay
- 缓存平台信息避免 sendSync 阻塞渲染进程
- 修复 cleanupAppShortcuts 中缺少 MPRIS 监听器清理导致的事件泄漏
- destroyMpris 中添加 IPC 监听器清理
- 清理冗余调试日志,安全加载 dbus-native 模块
- 添加 mpris-service 类型声明解决跨平台类型检查问题
2026-04-11 22:37:26 +08:00
stark81
3f31278131
fix-sandbox
2026-04-11 16:01:06 +08:00
alger
33fc4f768c
1. 实现linux下的mpris和gnome状态栏歌词功能
2026-04-11 15:45:14 +08:00
alger
8e3e4e610c
fix(pwa): 修复 manifest.json 未被引用导致浏览器无法识别 PWA ( #640 )
...
在 index.html 中添加 manifest 引用,并补全 PWA 必需字段
2026-04-10 23:27:19 +08:00
alger
03b52cd6e2
fix(audio): 移除不必要的麦克风权限请求 ( #639 )
...
枚举音频输出设备时不再调用 getUserMedia,避免安全软件误报
2026-04-10 23:27:12 +08:00
4everWZ
8726af556a
perf: 长列表渐进式渲染优化与播放栏遮挡修复 ( #589 )
...
- 新增 useProgressiveRender composable,提取手工虚拟化逻辑(renderLimit + placeholderHeight)
- FavoritePage/DownloadPage 使用 composable 实现渐进式渲染,避免大量 DOM 一次性渲染
- MusicListPage 初始加载扩大至 200 首,工具栏按钮添加 n-tooltip,新增回到顶部按钮
- 播放栏动态底部间距替代 PlayBottom 组件,修复播放时列表底部被遮挡
- 下载页无下载任务时自动切换到已下载 tab
- i18n: 添加 scrollToTop/compactLayout/normalLayout 翻译(5 种语言)
Inspired-By: https://github.com/algerkong/AlgerMusicPlayer/pull/589
2026-04-10 23:26:34 +08:00
Vanilla-puree
0ab784024c
feat(download): 新增未保存下载设置时的确认对话框 ( #507 )
...
- feat(download): 关闭下载设置抽屉时检测未保存更改,提供取消/放弃/保存选项
- fix: 自动播放首次暂停无法暂停,移除不必要的 isFirstPlay 检查
- fix: 歌手详情路由添加 props key,修复跳转歌手详情不生效问题
- i18n: 添加 download.save.* 翻译(5 种语言)
Co-Authored-By: 心妄 <1661272893@qq.com >
2026-04-10 23:26:33 +08:00
alger
ad2df12957
fix(core): 修复事件监听器泄漏
...
- App.vue: offline 监听器添加 onUnmounted 清理,移除冗余 console.log
- MusicHook.ts: document.onkeyup 直接赋值改为 addEventListener + 防重复
- MusicHook.ts: audio-ready 监听器提取为命名函数,先移除再注册防堆叠
2026-04-10 23:26:33 +08:00
alger
a407045527
fix(player): 修复迷你模式恢复后歌词页面空白偏移
...
迷你播放栏的 togglePlaylist 设置 document.body.style.height='64px'
和 overflow='hidden',恢复主窗口时未清理,导致歌词 drawer 高度被限制。
在 mini-mode 事件处理中添加 body 样式重置。
2026-04-10 23:26:33 +08:00
alger
38723165a0
refactor(player): 提取播放栏共享逻辑为 composable
...
- 新增 useVolumeControl:统一音量管理(volumeSlider、mute、滚轮调节)
- 新增 useFavorite:收藏状态与切换
- 新增 usePlaybackControl:播放/暂停、上/下一首
- PlayBar、MiniPlayBar、SimplePlayBar、MobilePlayBar 使用新 composable
- 修复音量存储不一致:MiniPlayBar/SimplePlayBar 原先绕过 playerStore 直接操作 localStorage
2026-04-10 23:26:33 +08:00
alger
042b8ba6f8
fix(i18n): 补充 player.autoResumed/resumeFailed 翻译(5 种语言)
2026-03-29 13:20:45 +08:00
alger
eb801cfbfd
style(ui): 桌面端 message 毛玻璃样式,本地音乐页面全页滚动优化
...
- message 提示适配项目设计:全圆角、backdrop-blur、半透明背景、深色/浅色模式
- 本地音乐页面:hero 缩小可滚出、action bar 吸顶、歌曲列表跟随全页滚动
- 顺序播放到最后一首:用户点下一首保持播放仅提示,自然播完才停止
- i18n 新增 playListEnded(5 种语言)
2026-03-29 13:18:56 +08:00
alger
0cfec3dd82
refactor(player): 重构播放控制系统,移除 Howler.js 改用原生 HTMLAudioElement
...
- 新建 playbackController.ts,使用 generation-based 取消替代 playbackRequestManager 状态机
- audioService 重写:单一持久 HTMLAudioElement + Web Audio API,createMediaElementSource 只调一次
- playerCore 瘦身为纯状态管理,移除 handlePlayMusic/playAudio/checkPlaybackState
- playlist next/prev 简化,区分用户手动切歌和歌曲自然播完
- MusicHook 适配 HTMLAudioElement API(.currentTime/.duration/.paused)
- preloadService 从 Howl 实例缓存改为 URL 可用性验证
- 所有 view/component 调用者迁移到 playbackController.playTrack()
修复:快速切歌竞态、seek 到未缓冲位置失败、重启后自动播放循环提示、EQ 重建崩溃
2026-03-29 13:18:05 +08:00
alger
167f081ee6
fix(download): 下载中列表封面使用缩略图加速加载
2026-03-27 23:06:38 +08:00
alger
c28368f783
fix(local-music): 扫描自动清理已删除文件,修复双滚动条
...
- scanFolders() 扫描时收集磁盘文件路径,完成后自动移除 IndexedDB 中已删除的条目
- 移除外层 n-scrollbar,改用 flex 布局,n-virtual-list 作为唯一滚动容器
2026-03-27 23:02:09 +08:00