@ash-qw/dsh-theme-prts 0.1.92 → 0.1.94
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 +36 -0
- package/README.en.md +25 -65
- package/README.md +26 -68
- package/lib/client.js +1211 -63
- package/package.json +12 -2
- package/src/client/conversation-scale-adapter.js +110 -6
- package/src/client/index.js +18 -3
- package/src/client/operations-shell-v2.js +334 -20
- package/src/client/particle-field-adapter.js +134 -12
- package/src/client/preferences.js +24 -5
- package/src/client/resize-shield-adapter.js +5 -0
- package/src/client/theme-controller-v2.js +609 -16
- package/src/client/theme-settings-workbench.js +69 -2
- package/src/styles/prts.css +402 -16
- package/src/styles/theme-settings-workbench.css +17 -0
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { createThemeSettingsOverlay, themeSettingsMarkup } from './theme-settings-workbench.js'
|
|
2
2
|
import { createResizeShieldAdapter } from './resize-shield-adapter.js'
|
|
3
3
|
|
|
4
|
+
const PHONE_RAIL_BREAKPOINT = 640
|
|
5
|
+
const RAIL_HOLD_DELAY_MS = 350
|
|
6
|
+
const RAIL_HOLD_MOVE_TOLERANCE = 8
|
|
7
|
+
const RAIL_SWIPE_THRESHOLD = 32
|
|
8
|
+
const RAIL_SWIPE_AXIS_RATIO = 1.25
|
|
9
|
+
|
|
4
10
|
function setText(root, selector, value) {
|
|
5
11
|
const node = root?.querySelector(selector)
|
|
6
12
|
const next = String(value ?? '')
|
|
@@ -9,7 +15,7 @@ function setText(root, selector, value) {
|
|
|
9
15
|
|
|
10
16
|
function markup(emblem) {
|
|
11
17
|
return `<div data-prts-shell data-plugin="dsh-theme-prts">
|
|
12
|
-
<button type="button" data-prts-rail-launcher aria-label="打开 P.R.T.S. 导航" aria-controls="prts-nav-rail" aria-expanded="false"><span aria-hidden="true">P.R.T.S.</span></button>
|
|
18
|
+
<button type="button" data-prts-rail-launcher aria-label="打开 P.R.T.S. 导航" aria-controls="prts-nav-rail" aria-expanded="false"><span aria-hidden="true">P.R.T.S.</span><i data-prts-rail-gesture-cue aria-hidden="true">⌄<br>⌄</i></button>
|
|
13
19
|
<nav id="prts-nav-rail" data-prts-nav-rail aria-label="P.R.T.S. 导航">
|
|
14
20
|
<button type="button" data-prts-rail-brand aria-label="P.R.T.S. 终端设置" aria-controls="prts-theme-settings" aria-expanded="false">${emblem || ''}<span>P.R.T.S.</span></button>
|
|
15
21
|
<div data-prts-nav-bottom>
|
|
@@ -35,8 +41,10 @@ export function createOperationsShell({
|
|
|
35
41
|
adapter,
|
|
36
42
|
hostGeometry,
|
|
37
43
|
onSchemeToggle = () => {},
|
|
44
|
+
onSchemeDragStart = () => undefined,
|
|
38
45
|
onThemeDisable = () => {},
|
|
39
46
|
onPreferenceChange = () => {},
|
|
47
|
+
onPreferencePreview = () => {},
|
|
40
48
|
onVisualReset = () => {},
|
|
41
49
|
getConversationScalePreview = () => ({ visible: false, reason: 'unmeasured', mode: 'hidden' }),
|
|
42
50
|
onRetrySave = () => {},
|
|
@@ -47,14 +55,166 @@ export function createOperationsShell({
|
|
|
47
55
|
let navRail
|
|
48
56
|
let railLauncher
|
|
49
57
|
let railMode
|
|
58
|
+
let railViewport
|
|
59
|
+
let railDefaultHidden = false
|
|
50
60
|
let railViewportQuery
|
|
61
|
+
let railPointerQuery
|
|
62
|
+
let railHoverQuery
|
|
63
|
+
let railPointer
|
|
64
|
+
let railHoldTimer
|
|
51
65
|
let settingsOverlay
|
|
52
66
|
let schemeToggle
|
|
67
|
+
let schemeIntent
|
|
68
|
+
let schemePressRevision = 0
|
|
69
|
+
let schemePressAnimation
|
|
70
|
+
let schemePointer
|
|
71
|
+
let suppressSchemeClick = false
|
|
72
|
+
let suppressSchemeClickTimer
|
|
53
73
|
let themeDisable
|
|
54
74
|
let connectionIndicator
|
|
55
75
|
let conversationObserver
|
|
56
76
|
let schemeObserver
|
|
57
77
|
let operationRegion
|
|
78
|
+
const schemePressDelays = new Set()
|
|
79
|
+
|
|
80
|
+
function reducedMotion() {
|
|
81
|
+
if (root.dataset.prtsMotion === 'reduced') return true
|
|
82
|
+
try { return window.matchMedia?.('(prefers-reduced-motion: reduce)')?.matches === true } catch { return false }
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function phoneRailGesture() {
|
|
86
|
+
if (railMode !== 'overlay' || Number(window.innerWidth) > PHONE_RAIL_BREAKPOINT) return false
|
|
87
|
+
return railPointerQuery?.matches === true
|
|
88
|
+
|| railHoverQuery?.matches === true
|
|
89
|
+
|| Number(window.navigator?.maxTouchPoints) > 0
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function clearRailGesture({ release = true } = {}) {
|
|
93
|
+
if (railHoldTimer !== undefined) window.clearTimeout(railHoldTimer)
|
|
94
|
+
railHoldTimer = undefined
|
|
95
|
+
const pointer = railPointer
|
|
96
|
+
railPointer = undefined
|
|
97
|
+
if (release && pointer) {
|
|
98
|
+
try { railLauncher?.releasePointerCapture?.(pointer.pointerId) } catch {}
|
|
99
|
+
}
|
|
100
|
+
railLauncher?.removeAttribute('data-prts-rail-gesture-active')
|
|
101
|
+
railLauncher?.removeAttribute('data-prts-rail-gesture-ready')
|
|
102
|
+
railLauncher?.style?.removeProperty('--prts-rail-gesture-progress')
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function armRailGesture() {
|
|
106
|
+
railHoldTimer = undefined
|
|
107
|
+
if (!railPointer || !phoneRailGesture()) return
|
|
108
|
+
railPointer.armed = true
|
|
109
|
+
railLauncher?.setAttribute('data-prts-rail-gesture-active', '')
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function onRailPointerDown(event) {
|
|
113
|
+
if (!phoneRailGesture() || railPointer || (event.button ?? 0) !== 0) return
|
|
114
|
+
const pointerId = event.pointerId ?? 1
|
|
115
|
+
railPointer = {
|
|
116
|
+
pointerId,
|
|
117
|
+
startX: Number(event.clientX) || 0,
|
|
118
|
+
startY: Number(event.clientY) || 0,
|
|
119
|
+
armed: false,
|
|
120
|
+
ready: false,
|
|
121
|
+
}
|
|
122
|
+
try { railLauncher?.setPointerCapture?.(pointerId) } catch {}
|
|
123
|
+
railHoldTimer = window.setTimeout(armRailGesture, RAIL_HOLD_DELAY_MS)
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function onRailPointerMove(event) {
|
|
127
|
+
const pointer = railPointer
|
|
128
|
+
if (!pointer || (event.pointerId ?? 1) !== pointer.pointerId) return
|
|
129
|
+
const deltaX = (Number(event.clientX) || 0) - pointer.startX
|
|
130
|
+
const deltaY = (Number(event.clientY) || 0) - pointer.startY
|
|
131
|
+
if (!pointer.armed) {
|
|
132
|
+
if (Math.hypot(deltaX, deltaY) > RAIL_HOLD_MOVE_TOLERANCE) clearRailGesture()
|
|
133
|
+
return
|
|
134
|
+
}
|
|
135
|
+
event.preventDefault?.()
|
|
136
|
+
if (Math.abs(deltaX) > Math.max(RAIL_HOLD_MOVE_TOLERANCE, Math.max(0, deltaY) / RAIL_SWIPE_AXIS_RATIO)) {
|
|
137
|
+
clearRailGesture()
|
|
138
|
+
return
|
|
139
|
+
}
|
|
140
|
+
const progress = Math.min(1, Math.max(0, deltaY) / RAIL_SWIPE_THRESHOLD)
|
|
141
|
+
pointer.ready = deltaY >= RAIL_SWIPE_THRESHOLD
|
|
142
|
+
&& deltaY >= Math.abs(deltaX) * RAIL_SWIPE_AXIS_RATIO
|
|
143
|
+
railLauncher?.style?.setProperty('--prts-rail-gesture-progress', Math.round(progress * 12) + 'px')
|
|
144
|
+
railLauncher?.toggleAttribute('data-prts-rail-gesture-ready', pointer.ready)
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function onRailPointerUp(event) {
|
|
148
|
+
const pointer = railPointer
|
|
149
|
+
if (!pointer || (event.pointerId ?? 1) !== pointer.pointerId) return
|
|
150
|
+
const shouldOpen = pointer.armed && pointer.ready
|
|
151
|
+
clearRailGesture()
|
|
152
|
+
if (shouldOpen) openRail()
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function onRailLostPointerCapture(event) {
|
|
156
|
+
if (!railPointer || (event.pointerId ?? 1) !== railPointer.pointerId) return
|
|
157
|
+
clearRailGesture({ release: false })
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function onRailClick(event) {
|
|
161
|
+
if (phoneRailGesture() && Number(event?.detail) > 0) {
|
|
162
|
+
event.preventDefault?.()
|
|
163
|
+
return
|
|
164
|
+
}
|
|
165
|
+
toggleRail()
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function playSchemePress() {
|
|
169
|
+
if (!schemeToggle || reducedMotion()) return
|
|
170
|
+
const revision = ++schemePressRevision
|
|
171
|
+
schemePressAnimation?.cancel?.()
|
|
172
|
+
schemePressAnimation = undefined
|
|
173
|
+
schemeToggle.removeAttribute('data-prts-scheme-press')
|
|
174
|
+
|
|
175
|
+
if (typeof schemeToggle.animate === 'function') {
|
|
176
|
+
const animation = schemeToggle.animate([
|
|
177
|
+
{ transform: 'translateY(0) scale(1)' },
|
|
178
|
+
{ transform: 'translateY(0) scale(.96)', offset: 0.5 },
|
|
179
|
+
{ transform: 'translateY(0) scale(1)' },
|
|
180
|
+
], { duration: 100, easing: 'cubic-bezier(.22, 1, .36, 1)' })
|
|
181
|
+
schemePressAnimation = animation
|
|
182
|
+
Promise.resolve(animation.finished).catch(() => {}).finally(() => {
|
|
183
|
+
if (revision === schemePressRevision && schemePressAnimation === animation) schemePressAnimation = undefined
|
|
184
|
+
})
|
|
185
|
+
return
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
schemeToggle.setAttribute('data-prts-scheme-press', '')
|
|
189
|
+
const entry = { timer: undefined }
|
|
190
|
+
entry.timer = window.setTimeout(() => {
|
|
191
|
+
schemePressDelays.delete(entry)
|
|
192
|
+
if (revision === schemePressRevision) schemeToggle?.removeAttribute('data-prts-scheme-press')
|
|
193
|
+
}, 100)
|
|
194
|
+
schemePressDelays.add(entry)
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
function clearSchemePressDelays() {
|
|
198
|
+
schemePressRevision += 1
|
|
199
|
+
schemePressAnimation?.cancel?.()
|
|
200
|
+
schemePressAnimation = undefined
|
|
201
|
+
schemeToggle?.removeAttribute('data-prts-scheme-press')
|
|
202
|
+
for (const entry of schemePressDelays) {
|
|
203
|
+
window.clearTimeout(entry.timer)
|
|
204
|
+
}
|
|
205
|
+
schemePressDelays.clear()
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function schemeTarget() {
|
|
209
|
+
const current = schemeIntent ?? (root.dataset.prtsScheme === 'dark' ? 'dark' : 'light')
|
|
210
|
+
return current === 'dark' ? 'light' : 'dark'
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
function schemeOrigin() {
|
|
214
|
+
const rect = schemeToggle?.getBoundingClientRect?.()
|
|
215
|
+
return rect ? { x: rect.left + rect.width / 2, y: rect.top + rect.height / 2 } : undefined
|
|
216
|
+
}
|
|
217
|
+
|
|
58
218
|
function syncConversationState() {
|
|
59
219
|
if (!operationRegion) return
|
|
60
220
|
const candidate = operationRegion.querySelector(
|
|
@@ -65,13 +225,122 @@ export function createOperationsShell({
|
|
|
65
225
|
settingsOverlay?.refreshScalePreview()
|
|
66
226
|
}
|
|
67
227
|
|
|
68
|
-
function toggleScheme() {
|
|
69
|
-
|
|
228
|
+
function toggleScheme(event) {
|
|
229
|
+
if (suppressSchemeClick) {
|
|
230
|
+
event?.preventDefault?.()
|
|
231
|
+
return
|
|
232
|
+
}
|
|
233
|
+
const next = schemeTarget()
|
|
234
|
+
schemeIntent = next
|
|
235
|
+
playSchemePress()
|
|
236
|
+
let request
|
|
237
|
+
try { request = onSchemeToggle(next, { origin: schemeOrigin() }) } catch { request = undefined }
|
|
238
|
+
Promise.resolve(request).catch(() => {}).finally(() => {
|
|
239
|
+
if (schemeIntent === next) schemeIntent = undefined
|
|
240
|
+
})
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
function schemePointerProgress(event) {
|
|
244
|
+
const width = Math.max(1, Number(window.innerWidth) || Number(root.clientWidth) || 1)
|
|
245
|
+
return Math.min(1, Math.max(0, Number(event?.clientX) / width || 0))
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
function clearSchemeClickSuppression() {
|
|
249
|
+
if (suppressSchemeClickTimer !== undefined) window.clearTimeout(suppressSchemeClickTimer)
|
|
250
|
+
suppressSchemeClickTimer = undefined
|
|
251
|
+
suppressSchemeClick = false
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
function suppressNextSchemeClick() {
|
|
255
|
+
clearSchemeClickSuppression()
|
|
256
|
+
suppressSchemeClick = true
|
|
257
|
+
suppressSchemeClickTimer = window.setTimeout(() => {
|
|
258
|
+
suppressSchemeClickTimer = undefined
|
|
259
|
+
suppressSchemeClick = false
|
|
260
|
+
}, 0)
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
function settleSchemePointer({ commit = false } = {}) {
|
|
264
|
+
const pointer = schemePointer
|
|
265
|
+
if (!pointer) return
|
|
266
|
+
schemePointer = undefined
|
|
267
|
+
try { schemeToggle?.releasePointerCapture?.(pointer.pointerId) } catch {}
|
|
268
|
+
if (!pointer.dragging) return
|
|
269
|
+
suppressNextSchemeClick()
|
|
270
|
+
let result
|
|
271
|
+
try { result = pointer.gesture?.finish?.(commit) } catch { result = undefined }
|
|
272
|
+
Promise.resolve(result).catch(() => {}).finally(() => {
|
|
273
|
+
if (schemeIntent === pointer.target) schemeIntent = undefined
|
|
274
|
+
})
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
function onSchemePointerDown(event) {
|
|
278
|
+
if ((event.button ?? 0) !== 0 || schemePointer) return
|
|
279
|
+
const pointerId = event.pointerId ?? 1
|
|
280
|
+
schemePointer = {
|
|
281
|
+
pointerId,
|
|
282
|
+
startX: Number(event.clientX) || 0,
|
|
283
|
+
startY: Number(event.clientY) || 0,
|
|
284
|
+
target: schemeTarget(),
|
|
285
|
+
origin: schemeOrigin(),
|
|
286
|
+
dragging: false,
|
|
287
|
+
gesture: undefined,
|
|
288
|
+
}
|
|
289
|
+
try { schemeToggle?.setPointerCapture?.(pointerId) } catch {}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
function onSchemePointerMove(event) {
|
|
293
|
+
const pointer = schemePointer
|
|
294
|
+
if (!pointer || (event.pointerId ?? 1) !== pointer.pointerId) return
|
|
295
|
+
const deltaX = (Number(event.clientX) || 0) - pointer.startX
|
|
296
|
+
if (!pointer.dragging) {
|
|
297
|
+
if (deltaX < 8) return
|
|
298
|
+
pointer.dragging = true
|
|
299
|
+
schemeIntent = pointer.target
|
|
300
|
+
playSchemePress()
|
|
301
|
+
const progress = schemePointerProgress(event)
|
|
302
|
+
try {
|
|
303
|
+
pointer.gesture = onSchemeDragStart(pointer.target, {
|
|
304
|
+
origin: pointer.origin,
|
|
305
|
+
progress,
|
|
306
|
+
clientX: Number(event.clientX) || 0,
|
|
307
|
+
})
|
|
308
|
+
} catch {
|
|
309
|
+
pointer.gesture = undefined
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
event.preventDefault?.()
|
|
313
|
+
pointer.gesture?.update?.(schemePointerProgress(event))
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
function onSchemePointerUp(event) {
|
|
317
|
+
const pointer = schemePointer
|
|
318
|
+
if (!pointer || (event.pointerId ?? 1) !== pointer.pointerId) return
|
|
319
|
+
const commit = pointer.dragging && schemePointerProgress(event) >= .5
|
|
320
|
+
settleSchemePointer({ commit })
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
function cancelSchemePointer() {
|
|
324
|
+
const pointer = schemePointer
|
|
325
|
+
if (!pointer) return
|
|
326
|
+
if (pointer.dragging) {
|
|
327
|
+
try { pointer.gesture?.cancel?.() } catch {}
|
|
328
|
+
}
|
|
329
|
+
schemePointer = undefined
|
|
330
|
+
try { schemeToggle?.releasePointerCapture?.(pointer.pointerId) } catch {}
|
|
331
|
+
if (pointer.dragging) suppressNextSchemeClick()
|
|
332
|
+
if (schemeIntent === pointer.target) schemeIntent = undefined
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
function onSchemeLostPointerCapture(event) {
|
|
336
|
+
if (!schemePointer || (event.pointerId ?? 1) !== schemePointer.pointerId) return
|
|
337
|
+
cancelSchemePointer()
|
|
70
338
|
}
|
|
71
339
|
|
|
72
340
|
function syncSchemeToggle() {
|
|
73
341
|
if (!schemeToggle) return
|
|
74
342
|
const current = root.dataset.prtsScheme === 'dark' ? 'dark' : 'light'
|
|
343
|
+
if (schemeIntent === current) schemeIntent = undefined
|
|
75
344
|
schemeToggle.dataset.prtsSchemeCurrent = current
|
|
76
345
|
schemeToggle.setAttribute('aria-label', current === 'dark' ? '切换到日间模式' : '切换到夜间模式')
|
|
77
346
|
}
|
|
@@ -81,7 +350,8 @@ export function createOperationsShell({
|
|
|
81
350
|
const overlay = railMode === 'overlay'
|
|
82
351
|
const open = overlay && root.hasAttribute('data-prts-rail-open')
|
|
83
352
|
railLauncher.setAttribute('aria-expanded', String(open))
|
|
84
|
-
|
|
353
|
+
const closedLabel = phoneRailGesture() ? '长按并向下滑动打开 P.R.T.S. 导航' : '打开 P.R.T.S. 导航'
|
|
354
|
+
railLauncher.setAttribute('aria-label', open ? '关闭 P.R.T.S. 导航' : closedLabel)
|
|
85
355
|
if (overlay && !open) {
|
|
86
356
|
navRail.setAttribute('aria-hidden', 'true')
|
|
87
357
|
navRail.setAttribute('inert', '')
|
|
@@ -110,13 +380,17 @@ export function createOperationsShell({
|
|
|
110
380
|
else window?.setTimeout?.(focusFirst, 0)
|
|
111
381
|
}
|
|
112
382
|
|
|
113
|
-
function setRailViewport(width = window.innerWidth) {
|
|
114
|
-
const
|
|
115
|
-
|
|
383
|
+
function setRailViewport(width = window.innerWidth, { forceClose = false } = {}) {
|
|
384
|
+
const nextViewport = Number(width) >= 1180 ? 'wide' : 'narrow'
|
|
385
|
+
const viewportChanged = nextViewport !== railViewport
|
|
386
|
+
const nextMode = railDefaultHidden || nextViewport === 'narrow' ? 'overlay' : 'docked'
|
|
387
|
+
const modeChanged = nextMode !== railMode
|
|
388
|
+
if (!viewportChanged && !modeChanged && !forceClose) return railMode
|
|
389
|
+
railViewport = nextViewport
|
|
116
390
|
railMode = nextMode
|
|
391
|
+
clearRailGesture()
|
|
117
392
|
root.dataset.prtsRailMode = nextMode
|
|
118
|
-
|
|
119
|
-
else root.removeAttribute('data-prts-rail-open')
|
|
393
|
+
root.removeAttribute('data-prts-rail-open')
|
|
120
394
|
syncRailState()
|
|
121
395
|
return nextMode
|
|
122
396
|
}
|
|
@@ -134,23 +408,26 @@ export function createOperationsShell({
|
|
|
134
408
|
|
|
135
409
|
function onDocumentClick(event) {
|
|
136
410
|
if (railMode !== 'overlay' || !root.hasAttribute('data-prts-rail-open')) return
|
|
137
|
-
|
|
411
|
+
const settingsPanel = shell?.querySelector?.('[data-prts-theme-settings]')
|
|
412
|
+
const insideSettingsContent = settingsPanel?.contains?.(event.target) && event.target !== settingsPanel
|
|
413
|
+
if (navRail?.contains?.(event.target) || railLauncher?.contains?.(event.target) || insideSettingsContent) return
|
|
138
414
|
closeRail()
|
|
139
415
|
}
|
|
140
416
|
|
|
141
|
-
function onRailAction(event) {
|
|
142
|
-
const action = event.target?.closest?.('[data-prts-rail-brand], [data-prts-scheme-toggle]')
|
|
143
|
-
if (action && navRail?.contains?.(action)) closeRail()
|
|
144
|
-
}
|
|
145
|
-
|
|
146
417
|
function onResponsiveChange() {
|
|
418
|
+
clearRailGesture()
|
|
147
419
|
setRailViewport(window.innerWidth)
|
|
420
|
+
syncRailState()
|
|
148
421
|
settingsOverlay?.scheduleScalePreviewRefresh?.()
|
|
149
422
|
}
|
|
150
423
|
|
|
151
424
|
function bindResponsiveQueries() {
|
|
152
425
|
railViewportQuery = window.matchMedia?.('(min-width: 1180px)')
|
|
426
|
+
railPointerQuery = window.matchMedia?.('(pointer: coarse)')
|
|
427
|
+
railHoverQuery = window.matchMedia?.('(hover: none)')
|
|
153
428
|
railViewportQuery?.addEventListener?.('change', onResponsiveChange)
|
|
429
|
+
railPointerQuery?.addEventListener?.('change', onResponsiveChange)
|
|
430
|
+
railHoverQuery?.addEventListener?.('change', onResponsiveChange)
|
|
154
431
|
}
|
|
155
432
|
function disableTheme() { onThemeDisable() }
|
|
156
433
|
|
|
@@ -177,6 +454,7 @@ export function createOperationsShell({
|
|
|
177
454
|
panel: shell.querySelector('[data-prts-theme-settings]'),
|
|
178
455
|
backdrop: shell.querySelector('[data-prts-settings-backdrop]'),
|
|
179
456
|
onPreferenceChange,
|
|
457
|
+
onPreferencePreview,
|
|
180
458
|
onResetVisual: onVisualReset,
|
|
181
459
|
onRetrySave,
|
|
182
460
|
getConversationScalePreview,
|
|
@@ -190,11 +468,21 @@ export function createOperationsShell({
|
|
|
190
468
|
conversationObserver.observe(operationRegion, { childList: true, subtree: true, attributes: true, attributeFilter: ['hidden', 'data-chat-flow-kind', 'data-message-role'] })
|
|
191
469
|
schemeObserver = new window.MutationObserver(syncSchemeToggle)
|
|
192
470
|
schemeObserver.observe(root, { attributes: true, attributeFilter: ['data-prts-scheme'] })
|
|
193
|
-
railLauncher.addEventListener('click',
|
|
194
|
-
|
|
471
|
+
railLauncher.addEventListener('click', onRailClick)
|
|
472
|
+
railLauncher.addEventListener('pointerdown', onRailPointerDown)
|
|
473
|
+
railLauncher.addEventListener('pointermove', onRailPointerMove)
|
|
474
|
+
railLauncher.addEventListener('pointerup', onRailPointerUp)
|
|
475
|
+
railLauncher.addEventListener('pointercancel', clearRailGesture)
|
|
476
|
+
railLauncher.addEventListener('lostpointercapture', onRailLostPointerCapture)
|
|
195
477
|
document.addEventListener('keydown', onRailKeydown)
|
|
196
478
|
document.addEventListener('click', onDocumentClick)
|
|
197
479
|
schemeToggle.addEventListener('click', toggleScheme)
|
|
480
|
+
schemeToggle.addEventListener('pointerdown', onSchemePointerDown)
|
|
481
|
+
schemeToggle.addEventListener('pointermove', onSchemePointerMove)
|
|
482
|
+
schemeToggle.addEventListener('pointerup', onSchemePointerUp)
|
|
483
|
+
schemeToggle.addEventListener('pointercancel', cancelSchemePointer)
|
|
484
|
+
schemeToggle.addEventListener('lostpointercapture', onSchemeLostPointerCapture)
|
|
485
|
+
window.addEventListener?.('blur', cancelSchemePointer)
|
|
198
486
|
themeDisable.addEventListener('click', disableTheme)
|
|
199
487
|
syncConversationState()
|
|
200
488
|
syncSchemeToggle()
|
|
@@ -202,14 +490,32 @@ export function createOperationsShell({
|
|
|
202
490
|
}
|
|
203
491
|
|
|
204
492
|
function dispose() {
|
|
205
|
-
|
|
206
|
-
|
|
493
|
+
clearRailGesture()
|
|
494
|
+
cancelSchemePointer()
|
|
495
|
+
clearSchemeClickSuppression()
|
|
496
|
+
clearSchemePressDelays()
|
|
497
|
+
railLauncher?.removeEventListener('click', onRailClick)
|
|
498
|
+
railLauncher?.removeEventListener('pointerdown', onRailPointerDown)
|
|
499
|
+
railLauncher?.removeEventListener('pointermove', onRailPointerMove)
|
|
500
|
+
railLauncher?.removeEventListener('pointerup', onRailPointerUp)
|
|
501
|
+
railLauncher?.removeEventListener('pointercancel', clearRailGesture)
|
|
502
|
+
railLauncher?.removeEventListener('lostpointercapture', onRailLostPointerCapture)
|
|
207
503
|
document.removeEventListener('keydown', onRailKeydown)
|
|
208
504
|
document.removeEventListener('click', onDocumentClick)
|
|
209
505
|
schemeToggle?.removeEventListener('click', toggleScheme)
|
|
506
|
+
schemeToggle?.removeEventListener('pointerdown', onSchemePointerDown)
|
|
507
|
+
schemeToggle?.removeEventListener('pointermove', onSchemePointerMove)
|
|
508
|
+
schemeToggle?.removeEventListener('pointerup', onSchemePointerUp)
|
|
509
|
+
schemeToggle?.removeEventListener('pointercancel', cancelSchemePointer)
|
|
510
|
+
schemeToggle?.removeEventListener('lostpointercapture', onSchemeLostPointerCapture)
|
|
511
|
+
window.removeEventListener?.('blur', cancelSchemePointer)
|
|
210
512
|
themeDisable?.removeEventListener('click', disableTheme)
|
|
211
513
|
railViewportQuery?.removeEventListener?.('change', onResponsiveChange)
|
|
514
|
+
railPointerQuery?.removeEventListener?.('change', onResponsiveChange)
|
|
515
|
+
railHoverQuery?.removeEventListener?.('change', onResponsiveChange)
|
|
212
516
|
railViewportQuery = undefined
|
|
517
|
+
railPointerQuery = undefined
|
|
518
|
+
railHoverQuery = undefined
|
|
213
519
|
resizeShield.dispose()
|
|
214
520
|
settingsOverlay?.dispose()
|
|
215
521
|
conversationObserver?.disconnect()
|
|
@@ -218,7 +524,10 @@ export function createOperationsShell({
|
|
|
218
524
|
root.removeAttribute('data-prts-conversation-state')
|
|
219
525
|
root.removeAttribute('data-prts-rail-mode')
|
|
220
526
|
root.removeAttribute('data-prts-rail-open')
|
|
221
|
-
|
|
527
|
+
root.removeAttribute('data-prts-rail-default-hidden')
|
|
528
|
+
navRail = railLauncher = railMode = railViewport = undefined
|
|
529
|
+
railDefaultHidden = false
|
|
530
|
+
schemeIntent = undefined
|
|
222
531
|
shell = settingsOverlay = schemeToggle = themeDisable = connectionIndicator = undefined
|
|
223
532
|
conversationObserver = schemeObserver = undefined
|
|
224
533
|
operationRegion = undefined
|
|
@@ -232,7 +541,12 @@ export function createOperationsShell({
|
|
|
232
541
|
dispose()
|
|
233
542
|
return false
|
|
234
543
|
}
|
|
544
|
+
const nextRailDefaultHidden = Boolean(preferences.railDefaultHidden)
|
|
545
|
+
const railPreferenceChanged = nextRailDefaultHidden !== railDefaultHidden
|
|
546
|
+
railDefaultHidden = nextRailDefaultHidden
|
|
235
547
|
if (!mount()) return false
|
|
548
|
+
root.toggleAttribute('data-prts-rail-default-hidden', railDefaultHidden)
|
|
549
|
+
setRailViewport(window.innerWidth, { forceClose: railPreferenceChanged })
|
|
236
550
|
const connection = status?.connection || 'unknown'
|
|
237
551
|
const connectionLabel = status?.connectionLabel || '未知'
|
|
238
552
|
connectionIndicator.dataset.state = connection
|