dsh-music-panel 0.3.8 → 0.3.10
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/CHANGELOG.md +14 -0
- package/client.js +110 -90
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.3.10
|
|
4
|
+
|
|
5
|
+
### 变更
|
|
6
|
+
|
|
7
|
+
- 正在播放行改用 DSH 品牌蓝 `--dsw-static-deepseek-450`:歌曲名蓝色加粗、播放均衡器蓝色
|
|
8
|
+
- 高亮改为淡蓝底 + 左侧圆角蓝条 + 10px 圆角,替换原来的灰白块 + 生硬内阴影
|
|
9
|
+
|
|
10
|
+
## 0.3.9
|
|
11
|
+
|
|
12
|
+
### 修复
|
|
13
|
+
|
|
14
|
+
- 播放队列拖拽改为 Pointer Events 实现(参考 DSH 侧栏行拖拽的落点语义 + SortableJS 的 pointer 方案):此前 HTML5 dragstart 在 composer 宿主浮层内不触发,导致松手后顺序不变
|
|
15
|
+
- 按住行左侧 `⋮⋮` 手柄拖动即可;拖拽中目标行显示插入线,松手立即重排;拖拽后不会误触发行的点击跳转
|
|
16
|
+
|
|
3
17
|
## 0.3.8
|
|
4
18
|
|
|
5
19
|
### 修复
|
package/client.js
CHANGED
|
@@ -2124,12 +2124,13 @@ window.__ModuleLoader__.load({
|
|
|
2124
2124
|
function QueueOverlay() {
|
|
2125
2125
|
var [open, setOpen] = useState(queueOverlaySnapshot())
|
|
2126
2126
|
var [snap, setSnap] = useState(player.getSnapshot())
|
|
2127
|
-
|
|
2128
|
-
//
|
|
2129
|
-
// React re-render the dragged node synchronously, which cancels the
|
|
2130
|
-
// browser's drag in Chromium.
|
|
2127
|
+
// Drag state lives entirely in refs/DOM classes so React never
|
|
2128
|
+
// re-renders the dragged row mid-drag (Chromium cancels that).
|
|
2131
2129
|
var dragFromRef = useRef(null)
|
|
2130
|
+
var dragOverRef = useRef(null)
|
|
2131
|
+
var suppressClickRef = useRef(0)
|
|
2132
2132
|
var ref = useRef(null)
|
|
2133
|
+
var listRef = useRef(null)
|
|
2133
2134
|
|
|
2134
2135
|
useEffect(function () {
|
|
2135
2136
|
return subscribeQueueOverlay(function () {
|
|
@@ -2160,6 +2161,90 @@ window.__ModuleLoader__.load({
|
|
|
2160
2161
|
|
|
2161
2162
|
if (!open) return null
|
|
2162
2163
|
var queueView = buildQueueView(snap, player.getPlayOrder())
|
|
2164
|
+
|
|
2165
|
+
function clearDragMarks() {
|
|
2166
|
+
var list = listRef.current
|
|
2167
|
+
if (list === null) return
|
|
2168
|
+
var rowEls = list.querySelectorAll('.mu-queue-row')
|
|
2169
|
+
for (var i = 0; i < rowEls.length; i += 1) {
|
|
2170
|
+
rowEls[i].classList.remove('is-dragging', 'is-drop-target')
|
|
2171
|
+
}
|
|
2172
|
+
}
|
|
2173
|
+
|
|
2174
|
+
function moveRow(from, to) {
|
|
2175
|
+
if (from === null || from === to || from < 0 || to < 0) return
|
|
2176
|
+
if (from >= queueView.length || to >= queueView.length) return
|
|
2177
|
+
var order = queueView.map(function (item) {
|
|
2178
|
+
return item.originalIndex
|
|
2179
|
+
})
|
|
2180
|
+
var moved = order.splice(from, 1)[0]
|
|
2181
|
+
order.splice(to, 0, moved)
|
|
2182
|
+
player.reorderQueue(order)
|
|
2183
|
+
}
|
|
2184
|
+
|
|
2185
|
+
// Pointer-driven reorder (SortableJS' approach). The harness hosts this
|
|
2186
|
+
// overlay inside the composer area, where HTML5 dragstart is unreliable;
|
|
2187
|
+
// DSH's sidebar rows use HTML5 DnD with a custom drag preview, so this
|
|
2188
|
+
// keeps the same before/after marker semantics but with pointer events.
|
|
2189
|
+
var dragMoved = false
|
|
2190
|
+
function startDrag(event, position) {
|
|
2191
|
+
if (event.button !== undefined && event.button !== 0) return
|
|
2192
|
+
event.preventDefault()
|
|
2193
|
+
event.stopPropagation()
|
|
2194
|
+
var list = listRef.current
|
|
2195
|
+
if (list === null) return
|
|
2196
|
+
dragFromRef.current = position
|
|
2197
|
+
dragOverRef.current = position
|
|
2198
|
+
dragMoved = false
|
|
2199
|
+
var sourceRow = event.currentTarget.closest('.mu-queue-row')
|
|
2200
|
+
if (sourceRow !== null) sourceRow.classList.add('is-dragging')
|
|
2201
|
+
document.body.style.userSelect = 'none'
|
|
2202
|
+
|
|
2203
|
+
function mark(target) {
|
|
2204
|
+
dragOverRef.current = target
|
|
2205
|
+
var rowEls = list.querySelectorAll('.mu-queue-row')
|
|
2206
|
+
for (var i = 0; i < rowEls.length; i += 1) {
|
|
2207
|
+
rowEls[i].classList.toggle('is-drop-target', i === target)
|
|
2208
|
+
}
|
|
2209
|
+
}
|
|
2210
|
+
|
|
2211
|
+
function onMove(moveEvent) {
|
|
2212
|
+
dragMoved = true
|
|
2213
|
+
var rowEls = list.querySelectorAll('.mu-queue-row')
|
|
2214
|
+
if (rowEls.length === 0) return
|
|
2215
|
+
var target = rowEls.length - 1
|
|
2216
|
+
for (var i = 0; i < rowEls.length; i += 1) {
|
|
2217
|
+
var rect = rowEls[i].getBoundingClientRect()
|
|
2218
|
+
if (moveEvent.clientY < rect.top + rect.height / 2) {
|
|
2219
|
+
target = i
|
|
2220
|
+
break
|
|
2221
|
+
}
|
|
2222
|
+
target = i
|
|
2223
|
+
}
|
|
2224
|
+
mark(target)
|
|
2225
|
+
}
|
|
2226
|
+
|
|
2227
|
+
function onUp() {
|
|
2228
|
+
document.removeEventListener('pointermove', onMove)
|
|
2229
|
+
document.removeEventListener('pointerup', onUp)
|
|
2230
|
+
document.removeEventListener('pointercancel', onUp)
|
|
2231
|
+
document.body.style.userSelect = ''
|
|
2232
|
+
var from = dragFromRef.current
|
|
2233
|
+
var to = dragOverRef.current
|
|
2234
|
+
dragFromRef.current = null
|
|
2235
|
+
dragOverRef.current = null
|
|
2236
|
+
clearDragMarks()
|
|
2237
|
+
if (dragMoved && from !== null && to !== null) {
|
|
2238
|
+
suppressClickRef.current = Date.now() + 250
|
|
2239
|
+
moveRow(from, to)
|
|
2240
|
+
}
|
|
2241
|
+
}
|
|
2242
|
+
|
|
2243
|
+
document.addEventListener('pointermove', onMove)
|
|
2244
|
+
document.addEventListener('pointerup', onUp)
|
|
2245
|
+
document.addEventListener('pointercancel', onUp)
|
|
2246
|
+
}
|
|
2247
|
+
|
|
2163
2248
|
var rows = queueView.map(function (entry, position) {
|
|
2164
2249
|
var track = entry.track
|
|
2165
2250
|
var originalIndex = entry.originalIndex
|
|
@@ -2168,57 +2253,23 @@ window.__ModuleLoader__.load({
|
|
|
2168
2253
|
'div',
|
|
2169
2254
|
{
|
|
2170
2255
|
key: position + ':' + track.path,
|
|
2171
|
-
className:
|
|
2172
|
-
'mu-queue-row' +
|
|
2173
|
-
(visibleCurrent ? ' is-current' : '') +
|
|
2174
|
-
(dragOver === position ? ' is-drop-target' : ''),
|
|
2175
|
-
draggable: true,
|
|
2256
|
+
className: 'mu-queue-row' + (visibleCurrent ? ' is-current' : ''),
|
|
2176
2257
|
onClick: function () {
|
|
2258
|
+
if (Date.now() < suppressClickRef.current) return
|
|
2177
2259
|
player.select(snap.queue, originalIndex)
|
|
2178
2260
|
},
|
|
2179
|
-
onDragStart: function (event) {
|
|
2180
|
-
dragFromRef.current = position
|
|
2181
|
-
setDragOver(position)
|
|
2182
|
-
if (event.dataTransfer !== null && event.dataTransfer !== undefined) {
|
|
2183
|
-
event.dataTransfer.effectAllowed = 'move'
|
|
2184
|
-
try {
|
|
2185
|
-
event.dataTransfer.setData('text/plain', String(position))
|
|
2186
|
-
} catch (error) {
|
|
2187
|
-
// ignore
|
|
2188
|
-
}
|
|
2189
|
-
}
|
|
2190
|
-
},
|
|
2191
|
-
onDragOver: function (event) {
|
|
2192
|
-
event.preventDefault()
|
|
2193
|
-
if (event.dataTransfer !== null && event.dataTransfer !== undefined) {
|
|
2194
|
-
event.dataTransfer.dropEffect = 'move'
|
|
2195
|
-
}
|
|
2196
|
-
if (dragOver !== position) setDragOver(position)
|
|
2197
|
-
},
|
|
2198
|
-
onDragLeave: function () {
|
|
2199
|
-
if (dragOver === position) setDragOver(null)
|
|
2200
|
-
},
|
|
2201
|
-
onDrop: function (event) {
|
|
2202
|
-
event.preventDefault()
|
|
2203
|
-
event.stopPropagation()
|
|
2204
|
-
var from = dragFromRef.current
|
|
2205
|
-
if (from !== null && from !== position) {
|
|
2206
|
-
var order = queueView.map(function (item) {
|
|
2207
|
-
return item.originalIndex
|
|
2208
|
-
})
|
|
2209
|
-
var moved = order.splice(from, 1)[0]
|
|
2210
|
-
order.splice(position, 0, moved)
|
|
2211
|
-
player.reorderQueue(order)
|
|
2212
|
-
}
|
|
2213
|
-
dragFromRef.current = null
|
|
2214
|
-
setDragOver(null)
|
|
2215
|
-
},
|
|
2216
|
-
onDragEnd: function () {
|
|
2217
|
-
dragFromRef.current = null
|
|
2218
|
-
setDragOver(null)
|
|
2219
|
-
},
|
|
2220
2261
|
},
|
|
2221
|
-
h(
|
|
2262
|
+
h(
|
|
2263
|
+
'span',
|
|
2264
|
+
{
|
|
2265
|
+
className: 'mu-queue-grip',
|
|
2266
|
+
title: t('page.dragSort'),
|
|
2267
|
+
onPointerDown: function (event) {
|
|
2268
|
+
startDrag(event, position)
|
|
2269
|
+
},
|
|
2270
|
+
},
|
|
2271
|
+
'⋮⋮',
|
|
2272
|
+
),
|
|
2222
2273
|
h(
|
|
2223
2274
|
'span',
|
|
2224
2275
|
{ className: 'mu-queue-index' },
|
|
@@ -2265,39 +2316,7 @@ window.__ModuleLoader__.load({
|
|
|
2265
2316
|
'div',
|
|
2266
2317
|
{
|
|
2267
2318
|
className: 'mu-qoverlay-list',
|
|
2268
|
-
|
|
2269
|
-
event.preventDefault()
|
|
2270
|
-
if (event.dataTransfer !== null && event.dataTransfer !== undefined) {
|
|
2271
|
-
event.dataTransfer.dropEffect = 'move'
|
|
2272
|
-
}
|
|
2273
|
-
},
|
|
2274
|
-
// Dropping in the gap between rows (no row handles it) still
|
|
2275
|
-
// reorders: pick the row under the pointer.
|
|
2276
|
-
onDrop: function (event) {
|
|
2277
|
-
event.preventDefault()
|
|
2278
|
-
var from = dragFromRef.current
|
|
2279
|
-
if (from === null) return
|
|
2280
|
-
var rowEls = event.currentTarget.querySelectorAll('.mu-queue-row')
|
|
2281
|
-
var target = queueView.length - 1
|
|
2282
|
-
for (var i = 0; i < rowEls.length; i += 1) {
|
|
2283
|
-
var rect = rowEls[i].getBoundingClientRect()
|
|
2284
|
-
if (event.clientY < rect.top + rect.height / 2) {
|
|
2285
|
-
target = i
|
|
2286
|
-
break
|
|
2287
|
-
}
|
|
2288
|
-
target = i
|
|
2289
|
-
}
|
|
2290
|
-
if (target !== from) {
|
|
2291
|
-
var order = queueView.map(function (item) {
|
|
2292
|
-
return item.originalIndex
|
|
2293
|
-
})
|
|
2294
|
-
var moved = order.splice(from, 1)[0]
|
|
2295
|
-
order.splice(target, 0, moved)
|
|
2296
|
-
player.reorderQueue(order)
|
|
2297
|
-
}
|
|
2298
|
-
dragFromRef.current = null
|
|
2299
|
-
setDragOver(null)
|
|
2300
|
-
},
|
|
2319
|
+
ref: listRef,
|
|
2301
2320
|
},
|
|
2302
2321
|
snap.queue.length === 0 ? h('div', { className: 'mu-state-sub' }, t('page.queueEmpty')) : rows,
|
|
2303
2322
|
),
|
|
@@ -5400,7 +5419,7 @@ window.__ModuleLoader__.load({
|
|
|
5400
5419
|
'.mu-list{flex:1;min-height:0;overflow-y:auto;scrollbar-gutter:stable;padding:0 16px 12px}',
|
|
5401
5420
|
'.mu-vlist-inner{position:relative}',
|
|
5402
5421
|
'.mu-vlist-row{position:absolute;left:0;right:0}',
|
|
5403
|
-
'.mu-row{display:grid;grid-template-columns:calc(var(--mu-row-size,55px) + 4px) minmax(0,1.15fr) minmax(0,.85fr) 56px auto;align-items:center;gap:12px;padding:6px 10px;border-radius:var(--dsw-radius-md,8px);height:67px;box-sizing:border-box}',
|
|
5422
|
+
'.mu-row{display:grid;grid-template-columns:calc(var(--mu-row-size,55px) + 4px) minmax(0,1.15fr) minmax(0,.85fr) 56px auto;align-items:center;gap:12px;padding:6px 10px;border-radius:var(--dsw-radius-md,8px);height:67px;box-sizing:border-box;position:relative}',
|
|
5404
5423
|
'.mu-prefs{min-width:240px;padding:12px}',
|
|
5405
5424
|
'.mu-prefs-panel{position:absolute;top:56px;right:24px;z-index:50;width:360px;max-width:calc(100% - 48px);max-height:70vh;overflow-y:auto;padding:14px;border:1px solid var(--dsw-alias-border-l2,rgba(255,255,255,.12));border-radius:var(--dsw-radius-xl,20px);background:var(--dsw-alias-bg-layer-1,#1a1a1e);box-shadow:var(--dsw-elevation-panel,0 16px 40px rgba(0,0,0,.5))}',
|
|
5406
5425
|
'.mu-prefs-tabs{display:flex;gap:2px;padding:3px;margin-bottom:12px;border-radius:9px;background:var(--dsw-alias-bg-layer-3,rgba(255,255,255,.06))}',
|
|
@@ -5438,16 +5457,17 @@ window.__ModuleLoader__.load({
|
|
|
5438
5457
|
'.mu-btn-danger{background:var(--dsw-alias-state-error-primary,#c0392b);color:var(--dsw-alias-label-primary-foreground,#fff);border-color:transparent}',
|
|
5439
5458
|
'.mu-btn-danger:hover{opacity:.9}',
|
|
5440
5459
|
'.mu-row:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(255,255,255,.05))}',
|
|
5441
|
-
'.mu-row.is-current{background:
|
|
5442
|
-
'.mu-row.is-current
|
|
5443
|
-
'.mu-row.is-current
|
|
5460
|
+
'.mu-row.is-current{background:color-mix(in srgb,var(--dsw-static-deepseek-450,#5686fe) 8%,transparent);border-radius:10px;position:relative}',
|
|
5461
|
+
'.mu-row.is-current::before{content:"";position:absolute;left:3px;top:50%;transform:translateY(-50%);width:3px;height:20px;border-radius:2px;background:var(--dsw-static-deepseek-450,#5686fe)}',
|
|
5462
|
+
'.mu-row.is-current:hover{background:color-mix(in srgb,var(--dsw-static-deepseek-450,#5686fe) 12%,transparent)}',
|
|
5463
|
+
'.mu-row.is-current .mu-row-title{color:var(--dsw-static-deepseek-450,#5686fe);font-weight:600}',
|
|
5444
5464
|
'.mu-row.is-current .mu-row-sub,.mu-row.is-current .mu-row-album,.mu-row.is-current .mu-row-dur{color:var(--dsw-alias-label-secondary,#a1a1aa)}',
|
|
5445
5465
|
'.mu-row-play{position:relative;width:var(--mu-row-size,55px);height:var(--mu-row-size,55px);border:0;padding:0;background:transparent;cursor:pointer;border-radius:var(--dsw-radius-sm,6px);display:flex;align-items:center;justify-content:center}',
|
|
5446
5466
|
'.mu-row-playmask{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;border-radius:var(--dsw-radius-sm,6px);background:rgba(0,0,0,.45);color:#fff;opacity:0;transition:opacity .12s ease}',
|
|
5447
5467
|
'.mu-row-play:hover .mu-row-playmask,.mu-row.is-current .mu-row-playmask{opacity:1}',
|
|
5448
5468
|
'.mu-row.is-current .mu-row-playmask{background:rgba(0,0,0,.35)}',
|
|
5449
5469
|
'.mu-row.is-selected{background:var(--dsw-alias-interactive-bg-hover,rgba(255,255,255,.05))}',
|
|
5450
|
-
'.mu-row.is-current.is-selected{background:
|
|
5470
|
+
'.mu-row.is-current.is-selected{background:color-mix(in srgb,var(--dsw-static-deepseek-450,#5686fe) 8%,transparent)}',
|
|
5451
5471
|
'.mu-row-actions{display:flex;align-items:center;justify-content:flex-end;gap:6px}',
|
|
5452
5472
|
'.mu-check{width:20px;height:20px;margin:0;padding:0;border:1.5px solid var(--dsw-alias-border-l3,rgba(255,255,255,.24));border-radius:50%;background:transparent;color:#fff;cursor:pointer;display:flex;align-items:center;justify-content:center;flex:none;opacity:0;transition:opacity .12s ease}',
|
|
5453
5473
|
'.mu-row:hover .mu-check,.mu-row.is-selected .mu-check,.mu-check:focus-visible{opacity:1}',
|
|
@@ -5458,7 +5478,7 @@ window.__ModuleLoader__.load({
|
|
|
5458
5478
|
'.mu-row-main{min-width:0}',
|
|
5459
5479
|
'.mu-row-title{display:flex;align-items:center;gap:8px;font-size:14px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}',
|
|
5460
5480
|
'.mu-eq{display:inline-flex;align-items:flex-end;gap:2px;height:12px;margin-right:8px;flex:none}',
|
|
5461
|
-
'.mu-eq i{display:block;width:2px;height:4px;border-radius:1px;background:var(--dsw-
|
|
5481
|
+
'.mu-eq i{display:block;width:2px;height:4px;border-radius:1px;background:var(--dsw-static-deepseek-450,#5686fe);opacity:.95}',
|
|
5462
5482
|
'.mu-eq.is-playing i{animation:mu-eq-bounce .9s ease-in-out infinite}',
|
|
5463
5483
|
'.mu-eq.is-playing i:nth-child(2){animation-delay:.15s}',
|
|
5464
5484
|
'.mu-eq.is-playing i:nth-child(3){animation-delay:.3s}',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-music-panel",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.10",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Local music library for DeepSeek Harness: scan a folder, browse tracks with cover art and tags, and play through a sidebar-panel player with loop, shuffle and volume. · DSH 本地音乐插件:扫描音乐目录、读取封面与标签、侧栏入口 + 全屏播放器。",
|
|
6
6
|
"license": "MIT",
|