dsh-music-player 0.5.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -23,9 +23,11 @@ DeepSeek Harness 本地音乐/小说播放插件。
23
23
 
24
24
  ## 截图
25
25
 
26
- ![播放条](assets/screenshot-bar.png)
26
+ ![播放本地音乐](assets/screenshot-bar.png)
27
27
 
28
- ![实时频谱](assets/screenshot-spectrum.png)
28
+ ![播放QQ音乐](assets/screenshot-qq.png)
29
+
30
+ ![播放AI讲书](assets/screenshot-spectrum.png)
29
31
 
30
32
  ![播放面板](assets/screenshot-panel.png)
31
33
 
@@ -117,17 +119,17 @@ dsh plugin --profile <profile> add ./dsh-music-player-0.1.0.tgz
117
119
  - 新歌:新歌速递(最新/内地/港台/欧美/韩国等)。
118
120
  - 搜索:搜歌曲与歌单,带搜索历史(localStorage,最近 10 条)。
119
121
  - **播放**:点击任意歌曲即可播放(同一播放条 + 频谱);VIP 标识显示在歌名后,行尾显示歌手名。
120
- - **收藏**:播放条爱心按钮把当前在线曲目收藏到 QQ 音乐「我喜欢」(dirId 201);已收藏歌曲爱心实时点亮。
122
+ - **收藏**:播放条爱心按钮把当前在线曲目收藏到 QQ 音乐「我喜欢」,已收藏歌曲爱心实时点亮。
121
123
  - **续播**:在线播放进度(当前曲目 + 队列)刷新后自动恢复,点 ▶ 续播。
122
124
  - 在线曲目不占本地曲库的 500 首上限,与本地/讲书完全隔离。
123
125
 
124
126
  ## AI 讲书
125
127
 
126
- 把本地 `.txt` 小说交给 AI 朗读(复用 DSH 已配置的 xiaomi/MiMo TTS)。**AI 语音目前仅支持 xiaomi 提供方(限时免费),请在设置中配置好再使用此功能。**
128
+ 把本地 `.txt` 小说交给 AI 朗读。**AI 语音目前仅支持xiaomi提供方(限时免费),请在设置中配置好再使用此功能。**
127
129
 
128
130
  ### 前置
129
131
 
130
- 在 DSH 的模型设置里配置一个 xiaomi/MiMo TTS provider(含 api key)。未配置时,小说列表会提示"未配置 xiaomi/MiMo TTS 模型"。
132
+ 在 DSH 的模型设置里配置一个xiaomi提供方(含 api key)。未配置时,小说列表会提示"未配置xiaomi提供方"。
131
133
 
132
134
  ### 使用
133
135
 
package/lib/client.js CHANGED
@@ -778,7 +778,7 @@ window.__ModuleLoader__.load({
778
778
  bookRestorePos = -1;
779
779
  audio.src = track.url;
780
780
  audio.load();
781
- set({ currentId: id, currentName: track.name, currentArtists: track.artists || store.currentArtists || [], pendingId: null, pendingName: null, error: null, tocOpen: false, currentSection: '', qqFaved: false });
781
+ set({ currentId: id, currentName: track.name, currentArtists: track.artists || [], pendingId: null, pendingName: null, error: null, tocOpen: false, currentSection: '', qqFaved: false });
782
782
  syncShufflePos();
783
783
  loadEnvelope(id, track.url);
784
784
  prefetchNext();
@@ -947,7 +947,7 @@ window.__ModuleLoader__.load({
947
947
  // near-instant (server-side synthesis cache) so we don't flash a spinner
948
948
  // at every chunk boundary. Only user-initiated plays show it.
949
949
  const showBuffer = !silent;
950
- set({ currentId: 'book:' + id, currentName: book.name, pendingId: null, pendingName: null, error: null, vizState: 'ok' });
950
+ set({ currentId: 'book:' + id, currentName: book.name, currentArtists: [], pendingId: null, pendingName: null, error: null, vizState: 'ok' });
951
951
  // Load the chapter structure for the toc + the current-section label (the
952
952
  // current section is derived from the chunk index once the meta arrives).
953
953
  const startFrom = from;
@@ -1432,6 +1432,7 @@ window.__ModuleLoader__.load({
1432
1432
  // (togglePlay), and the readout is pinned to the restored values.
1433
1433
  set({
1434
1434
  currentId: track.id, currentName: track.name,
1435
+ currentArtists: track.artists || [],
1435
1436
  position: pos, duration: savedDur,
1436
1437
  pendingId: null, pendingName: null, error: null, scope,
1437
1438
  });
@@ -1475,7 +1476,7 @@ window.__ModuleLoader__.load({
1475
1476
  // <audio> element here (avoiding the Chromium 'getTopURL' quirk on
1476
1477
  // refresh); togglePlay loads + seeks the chunk when the user resumes.
1477
1478
  set({
1478
- currentId: 'book:' + book.id, currentName: book.name,
1479
+ currentId: 'book:' + book.id, currentName: book.name, currentArtists: [],
1479
1480
  position: base + pos, duration: base + (Number.isFinite(audio.duration) ? audio.duration : 0),
1480
1481
  pendingId: null, pendingName: null, error: null, playing: false,
1481
1482
  bookBuffering: false, bookBufferingSilent: false, bookError: '', bookBufferingSince: 0,
@@ -1563,7 +1564,8 @@ window.__ModuleLoader__.load({
1563
1564
  tracks: result.tracks || [], books: result.books || [],
1564
1565
  count: result.count || 0, loading: false, error: null,
1565
1566
  });
1566
- restoreLatest(result.tracks || []);
1567
+ // 换目录只刷新列表,不调用 restoreLatest:否则播放中的在线 QQ 曲目会
1568
+ // 触发 restorePlayback 把 tab 强制切回「QQ音乐」(选完目录被跳回的问题)。
1567
1569
  } else {
1568
1570
  set({ loading: false, error: (result && result.error) || '设置目录失败' });
1569
1571
  }
@@ -1975,6 +1977,9 @@ window.__ModuleLoader__.load({
1975
1977
  }
1976
1978
  }
1977
1979
 
1980
+ // 在线 QQ 面板的「上次所在层」只在本次会话首次挂载时恢复一次,避免切 tab
1981
+ // (QQ 音乐 ↔ 本地音乐/AI讲书)重新挂载时又被 localStorage 里的旧层拉回播放列表页。
1982
+ let qqUiRestored = false;
1978
1983
  function QQOnlinePanel() {
1979
1984
  const s = useStore();
1980
1985
  const [loggedIn, setLoggedIn] = useState(s.qqLoggedIn || false);
@@ -2066,7 +2071,8 @@ window.__ModuleLoader__.load({
2066
2071
  // 默认落在「我的歌单」tab:登录态下加载我的歌单;未登录时主 UI 不显示。
2067
2072
  loadMine();
2068
2073
  loadRecommended();
2069
- restoreUi(loadUi());
2074
+ // 仅本次会话首次挂载时恢复上次所在层;之后切 tab 重挂不再拉回旧层。
2075
+ if (!qqUiRestored) { qqUiRestored = true; restoreUi(loadUi()); }
2070
2076
  // 点击搜索框外时关闭历史下拉。
2071
2077
  const onDocClick = (e) => { if (histRef.current !== null && !histRef.current.contains(e.target)) setHistOpen(false); };
2072
2078
  document.addEventListener('mousedown', onDocClick);
@@ -3034,7 +3040,7 @@ window.__ModuleLoader__.load({
3034
3040
  if (track !== null) {
3035
3041
  audio.src = track.url;
3036
3042
  audio.load();
3037
- set({ currentId: intent.id, currentName: track.name, error: null, scope: { kind: 'library' } });
3043
+ set({ currentId: intent.id, currentName: track.name, currentArtists: track.artists || [], error: null, scope: { kind: 'library' } });
3038
3044
  loadEnvelope(intent.id, track.url);
3039
3045
  prefetchNext();
3040
3046
  savePlayback();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-music-player",
3
- "version": "0.5.0",
3
+ "version": "0.5.1",
4
4
  "description": "DeepSeek Harness 本地音乐 + AI 讲书插件:Host 扫描音乐目录并以 HTTP 流式提供音频、解析 .txt 小说结构并经 MiMo TTS 合成朗读,浏览器侧提供播放条/播放面板/章节目录跳转/多声音选择/实时频谱,并注册 music_play 模型工具",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",