@ash-qw/dsh-theme-prts 0.1.99 → 0.1.101
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 +12 -0
- package/lib/client.js +553 -35
- package/package.json +2 -2
- package/src/client/composer-glass-adapter.js +13 -3
- package/src/client/facility-geometry.js +12 -6
- package/src/client/facility-vector.js +44 -7
- package/src/client/index.js +24 -3
- package/src/client/preferences.js +68 -4
- package/src/client/session-lifeline.js +19 -4
- package/src/client/sidebar-control-adapter.js +201 -4
- package/src/client/theme-controller-v2.js +13 -0
- package/src/client/theme-controller.js +13 -0
- package/src/client/theme-settings-workbench.js +193 -6
- package/src/styles/facility-vector.css +320 -18
- package/src/styles/theme-settings-workbench.css +83 -4
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { PARTICLE_TRAVERSAL_SPEED_DEFAULT, PARTICLE_TRAVERSAL_SPEED_MAX, PARTICLE_TRAVERSAL_SPEED_MIN, PARTICLE_TRAVERSAL_SPEED_STEP, resolveParticleDetail } from './preferences.js'
|
|
1
|
+
import { PARTICLE_TRAVERSAL_SPEED_DEFAULT, PARTICLE_TRAVERSAL_SPEED_MAX, PARTICLE_TRAVERSAL_SPEED_MIN, PARTICLE_TRAVERSAL_SPEED_STEP, SESSION_FLOW_SPEED_DEFAULT, SESSION_FLOW_SPEED_MAX, SESSION_FLOW_SPEED_MIN, SESSION_FLOW_SPEED_STEP, resolveParticleDetail } from './preferences.js'
|
|
2
2
|
|
|
3
3
|
const SETTINGS_FOCUSABLE = [
|
|
4
4
|
'button:not([disabled])',
|
|
@@ -20,7 +20,14 @@ const COMMON_CONTROLS = [
|
|
|
20
20
|
['glass', '玻璃材质', [['off', '关闭'], ['soft', '柔和'], ['standard', '标准'], ['clear', '清晰']]],
|
|
21
21
|
['motion', '动态效果', [['system', '跟随系统'], ['reduced', '减少']]],
|
|
22
22
|
['sessionFlow', '当前会话流线', [['false', '关闭'], ['true', '开启']]],
|
|
23
|
-
['
|
|
23
|
+
['sessionGlow', '流线光效', [['false', '关闭'], ['true', '开启']]],
|
|
24
|
+
['sessionFlowPalette', '流线色调', [['triad', '三色'], ['rhodes', '青蓝'], ['amber', '金黄'], ['alert', '赤红'], ['custom', '自定义']]],
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
const SESSION_FLOW_COLOR_CONTROLS = [
|
|
28
|
+
['sessionFlowColorBack', '后层'],
|
|
29
|
+
['sessionFlowColorCore', '中层'],
|
|
30
|
+
['sessionFlowColorFront', '前层'],
|
|
24
31
|
]
|
|
25
32
|
|
|
26
33
|
const PARTICLE_OPTIONS = [
|
|
@@ -40,8 +47,12 @@ function settingButtons(key, label, options) {
|
|
|
40
47
|
? '<small data-prts-setting-note>立即切换会话背景、头像与消息气泡</small>'
|
|
41
48
|
: key === 'sessionFlow'
|
|
42
49
|
? '<small data-prts-setting-note>仅控制当前会话卡片的三色流线</small>'
|
|
50
|
+
: key === 'sessionGlow'
|
|
51
|
+
? '<small data-prts-setting-note>为流线添加柔和的同色辉光</small>'
|
|
52
|
+
: key === 'sessionFlowPalette'
|
|
53
|
+
? '<small data-prts-setting-note>同时适配日间与夜间模式</small>'
|
|
43
54
|
: ''
|
|
44
|
-
const sample = value => key === 'texture' || key === 'glass'
|
|
55
|
+
const sample = value => key === 'texture' || key === 'glass' || key === 'sessionFlowPalette'
|
|
45
56
|
? `<i data-prts-option-sample="${key}" data-prts-option-sample-value="${value}" aria-hidden="true"></i>`
|
|
46
57
|
: ''
|
|
47
58
|
return `<div data-prts-setting-row="${key}">
|
|
@@ -62,6 +73,33 @@ function particleMarkup() {
|
|
|
62
73
|
</button>`).join('')
|
|
63
74
|
}
|
|
64
75
|
|
|
76
|
+
function sessionFlowPreviewMarkup() {
|
|
77
|
+
const filaments = [
|
|
78
|
+
['back', 'M 3 29 C 34 8 66 36 101 17 C 126 5 151 27 177 13'],
|
|
79
|
+
['core', 'M 3 24 C 30 35 61 7 94 23 C 124 37 148 7 177 20'],
|
|
80
|
+
['front', 'M 3 18 C 34 4 66 30 96 12 C 125 -1 148 30 177 24'],
|
|
81
|
+
]
|
|
82
|
+
return `<svg data-prts-session-flow-preview viewBox="0 0 180 42" aria-label="三色流线预览" role="img">
|
|
83
|
+
${filaments.map(([strand, path]) => `<g data-prts-session-flow-preview-filament="${strand}">
|
|
84
|
+
<path data-prts-session-flow-preview-layer="halo" d="${path}"></path>
|
|
85
|
+
<path data-prts-session-flow-preview-layer="body" d="${path}"></path>
|
|
86
|
+
<path data-prts-session-flow-preview-layer="core" d="${path}"></path>
|
|
87
|
+
</g>`).join('')}
|
|
88
|
+
</svg>`
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function sessionFlowColorMarkup() {
|
|
92
|
+
return `<div data-prts-setting-row="sessionFlowColors" data-prts-session-flow-colors>
|
|
93
|
+
<span><strong>三色调色盘</strong><small data-prts-setting-note>任意修改后切换为自定义,日夜模式均保持原色</small></span>
|
|
94
|
+
<div data-prts-session-flow-color-workbench>
|
|
95
|
+
${sessionFlowPreviewMarkup()}
|
|
96
|
+
<div data-prts-session-flow-color-inputs role="group" aria-label="三色流线调色盘">
|
|
97
|
+
${SESSION_FLOW_COLOR_CONTROLS.map(([key, label]) => `<label><span>${label}</span><input type="color" value="#ffffff" data-prts-setting-color data-prts-setting-key="${key}" aria-label="${label}流线颜色"><output data-prts-setting-color-output="${key}">#ffffff</output></label>`).join('')}
|
|
98
|
+
</div>
|
|
99
|
+
</div>
|
|
100
|
+
</div>`
|
|
101
|
+
}
|
|
102
|
+
|
|
65
103
|
export function themeSettingsMarkup() {
|
|
66
104
|
return `<div data-prts-settings-backdrop hidden aria-hidden="true"></div>
|
|
67
105
|
<dialog id="prts-theme-settings" data-prts-theme-settings aria-label="P.R.T.S. 主题设置" aria-hidden="true">
|
|
@@ -83,7 +121,14 @@ export function themeSettingsMarkup() {
|
|
|
83
121
|
|
|
84
122
|
<section data-prts-settings-common>
|
|
85
123
|
<header><span><small>常用设置</small><strong>主题表现</strong></span></header>
|
|
86
|
-
<div data-prts-settings-common-grid>${COMMON_CONTROLS.map(([key, label, options]) => settingButtons(key, label, options)).join('')}
|
|
124
|
+
<div data-prts-settings-common-grid>${COMMON_CONTROLS.map(([key, label, options]) => settingButtons(key, label, options)).join('')}
|
|
125
|
+
${sessionFlowColorMarkup()}
|
|
126
|
+
<label data-prts-setting-row="sessionFlowSpeed" data-prts-setting-range-row data-prts-session-flow-speed>
|
|
127
|
+
<span><strong>流线速度</strong><small data-prts-setting-note>控制当前会话流线的形变速度</small></span>
|
|
128
|
+
<div><input type="range" min="0.25" max="2" step="0.25" value="1" data-prts-setting-range data-prts-setting-key="sessionFlowSpeed" aria-label="当前会话流线速度"><output data-prts-session-flow-speed-output>1× · 标准</output></div>
|
|
129
|
+
</label>
|
|
130
|
+
${settingButtons('conversationStyle', '会话主题', [['native', '原有'], ['deck-chat', '通讯链路']])}
|
|
131
|
+
</div>
|
|
87
132
|
</section>
|
|
88
133
|
|
|
89
134
|
<details data-prts-settings-advanced>
|
|
@@ -143,6 +188,10 @@ export function createThemeSettingsOverlay({
|
|
|
143
188
|
let currentPersistence = { phase: 'idle', revision: 0 }
|
|
144
189
|
let particleTraversalSpeedDraft
|
|
145
190
|
let particleTraversalSpeedDirty = false
|
|
191
|
+
let sessionFlowSpeedDraft
|
|
192
|
+
let sessionFlowSpeedDirty = false
|
|
193
|
+
let sessionFlowColorDrafts = {}
|
|
194
|
+
const sessionFlowColorDirty = new Set()
|
|
146
195
|
let savedTimer
|
|
147
196
|
let feedbackTimer
|
|
148
197
|
let feedbackTarget
|
|
@@ -192,6 +241,8 @@ export function createThemeSettingsOverlay({
|
|
|
192
241
|
if (value === isOpen) return isOpen
|
|
193
242
|
if (!value) {
|
|
194
243
|
commitParticleTraversalSpeed()
|
|
244
|
+
commitSessionFlowSpeed()
|
|
245
|
+
commitSessionFlowColors()
|
|
195
246
|
}
|
|
196
247
|
isOpen = value
|
|
197
248
|
trigger.setAttribute('aria-expanded', String(isOpen))
|
|
@@ -225,6 +276,34 @@ export function createThemeSettingsOverlay({
|
|
|
225
276
|
)
|
|
226
277
|
}
|
|
227
278
|
|
|
279
|
+
function normalizeSessionFlowSpeed(value) {
|
|
280
|
+
const numeric = Number(value)
|
|
281
|
+
if (!Number.isFinite(numeric)) return SESSION_FLOW_SPEED_DEFAULT
|
|
282
|
+
const clamped = Math.min(SESSION_FLOW_SPEED_MAX, Math.max(SESSION_FLOW_SPEED_MIN, numeric))
|
|
283
|
+
return Math.round(clamped / SESSION_FLOW_SPEED_STEP) * SESSION_FLOW_SPEED_STEP
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
function currentSessionFlowSpeed() {
|
|
287
|
+
return normalizeSessionFlowSpeed(
|
|
288
|
+
sessionFlowSpeedDirty ? sessionFlowSpeedDraft : currentPreferences?.sessionFlowSpeed,
|
|
289
|
+
)
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
function normalizeSessionFlowColor(value, fallback = '#ffffff') {
|
|
293
|
+
return typeof value === 'string' && /^#[\da-f]{6}$/i.test(value) ? value.toLowerCase() : fallback
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
function currentSessionFlowColor(key) {
|
|
297
|
+
return normalizeSessionFlowColor(
|
|
298
|
+
sessionFlowColorDirty.has(key) ? sessionFlowColorDrafts[key] : currentPreferences?.[key],
|
|
299
|
+
'#ffffff',
|
|
300
|
+
)
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
function activeSessionFlowPalette() {
|
|
304
|
+
return sessionFlowColorDirty.size > 0 ? 'custom' : currentPreferences?.sessionFlowPalette
|
|
305
|
+
}
|
|
306
|
+
|
|
228
307
|
function conciseNumber(value) {
|
|
229
308
|
return String(Number(Number(value).toFixed(2)))
|
|
230
309
|
}
|
|
@@ -243,6 +322,42 @@ export function createThemeSettingsOverlay({
|
|
|
243
322
|
setText(panel.querySelector('[data-prts-particle-traversal-output]'), particleTraversalLabel(value))
|
|
244
323
|
}
|
|
245
324
|
|
|
325
|
+
function sessionFlowSpeedLabel(value) {
|
|
326
|
+
const speed = normalizeSessionFlowSpeed(value)
|
|
327
|
+
const description = speed < 1 ? '缓慢' : speed === 1 ? '标准' : speed <= 1.5 ? '快速' : '高速'
|
|
328
|
+
return `${conciseNumber(speed)}× · ${description}`
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
function renderSessionFlowSpeed() {
|
|
332
|
+
if (!panel || !currentPreferences) return
|
|
333
|
+
const value = currentSessionFlowSpeed()
|
|
334
|
+
const range = panel.querySelector('input[data-prts-setting-range][data-prts-setting-key="sessionFlowSpeed"]')
|
|
335
|
+
if (range && range.value !== String(value)) range.value = String(value)
|
|
336
|
+
setText(panel.querySelector('[data-prts-session-flow-speed-output]'), sessionFlowSpeedLabel(value))
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
function renderSessionFlowColors() {
|
|
340
|
+
if (!panel || !currentPreferences) return
|
|
341
|
+
for (const [key] of SESSION_FLOW_COLOR_CONTROLS) {
|
|
342
|
+
const value = currentSessionFlowColor(key)
|
|
343
|
+
const input = panel.querySelector(`input[data-prts-setting-color][data-prts-setting-key="${key}"]`)
|
|
344
|
+
if (input && input.value !== value) input.value = value
|
|
345
|
+
setText(panel.querySelector(`[data-prts-setting-color-output="${key}"]`), value)
|
|
346
|
+
}
|
|
347
|
+
const preview = panel.querySelector('[data-prts-session-flow-preview]')
|
|
348
|
+
if (preview) {
|
|
349
|
+
preview.dataset.prtsSessionFlowPreviewPalette = activeSessionFlowPalette() || 'triad'
|
|
350
|
+
preview.style.setProperty('--prts-session-flow-back', currentSessionFlowColor('sessionFlowColorBack'))
|
|
351
|
+
preview.style.setProperty('--prts-session-flow-core', currentSessionFlowColor('sessionFlowColorCore'))
|
|
352
|
+
preview.style.setProperty('--prts-session-flow-front', currentSessionFlowColor('sessionFlowColorFront'))
|
|
353
|
+
}
|
|
354
|
+
for (const button of panel.querySelectorAll('button[data-prts-setting-key="sessionFlowPalette"]')) {
|
|
355
|
+
const selected = button.dataset.prtsSettingValue === activeSessionFlowPalette()
|
|
356
|
+
button.classList.toggle('is-selected', selected)
|
|
357
|
+
button.setAttribute('aria-pressed', String(selected))
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
|
|
246
361
|
function setText(node, value) {
|
|
247
362
|
if (node && node.textContent !== value) node.textContent = value
|
|
248
363
|
}
|
|
@@ -260,6 +375,38 @@ export function createThemeSettingsOverlay({
|
|
|
260
375
|
return true
|
|
261
376
|
}
|
|
262
377
|
|
|
378
|
+
function commitSessionFlowSpeed() {
|
|
379
|
+
if (!sessionFlowSpeedDirty || !currentPreferences) return false
|
|
380
|
+
const value = currentSessionFlowSpeed()
|
|
381
|
+
sessionFlowSpeedDirty = false
|
|
382
|
+
sessionFlowSpeedDraft = value
|
|
383
|
+
if (value !== normalizeSessionFlowSpeed(currentPreferences.sessionFlowSpeed)) {
|
|
384
|
+
onPreferenceChange('sessionFlowSpeed', value)
|
|
385
|
+
} else {
|
|
386
|
+
renderSessionFlowSpeed()
|
|
387
|
+
}
|
|
388
|
+
return true
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
function commitSessionFlowColor(key) {
|
|
392
|
+
if (!sessionFlowColorDirty.has(key) || !currentPreferences) return false
|
|
393
|
+
const value = currentSessionFlowColor(key)
|
|
394
|
+
sessionFlowColorDirty.delete(key)
|
|
395
|
+
sessionFlowColorDrafts[key] = value
|
|
396
|
+
if (value !== normalizeSessionFlowColor(currentPreferences[key]) || currentPreferences.sessionFlowPalette !== 'custom') {
|
|
397
|
+
onPreferenceChange(key, value)
|
|
398
|
+
} else {
|
|
399
|
+
renderSessionFlowColors()
|
|
400
|
+
}
|
|
401
|
+
return true
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
function commitSessionFlowColors() {
|
|
405
|
+
let committed = false
|
|
406
|
+
for (const key of [...sessionFlowColorDirty]) committed = commitSessionFlowColor(key) || committed
|
|
407
|
+
return committed
|
|
408
|
+
}
|
|
409
|
+
|
|
263
410
|
function renderPersistence() {
|
|
264
411
|
const status = panel?.querySelector?.('[data-prts-persistence-status]')
|
|
265
412
|
const error = panel?.querySelector?.('[data-prts-persistence-error]')
|
|
@@ -286,8 +433,10 @@ export function createThemeSettingsOverlay({
|
|
|
286
433
|
const key = button.dataset.prtsSettingKey
|
|
287
434
|
const actual = key === 'particleDetail'
|
|
288
435
|
? particleDetail
|
|
289
|
-
: key === '
|
|
290
|
-
?
|
|
436
|
+
: key === 'sessionFlowPalette'
|
|
437
|
+
? activeSessionFlowPalette()
|
|
438
|
+
: key === 'sessionFlow' || key === 'sessionGlow'
|
|
439
|
+
? currentPreferences[key] !== false
|
|
291
440
|
: currentPreferences[key]
|
|
292
441
|
const selected = String(actual) === button.dataset.prtsSettingValue
|
|
293
442
|
button.classList.toggle('is-selected', selected)
|
|
@@ -305,7 +454,13 @@ export function createThemeSettingsOverlay({
|
|
|
305
454
|
const particleError = panel.querySelector('[data-prts-particle-error]')
|
|
306
455
|
if (particleError) particleError.hidden = currentStatus?.particle?.phase !== 'error'
|
|
307
456
|
if (!particleTraversalSpeedDirty) particleTraversalSpeedDraft = normalizeParticleTraversalSpeed(currentPreferences.particleTraversalSpeed)
|
|
457
|
+
if (!sessionFlowSpeedDirty) sessionFlowSpeedDraft = normalizeSessionFlowSpeed(currentPreferences.sessionFlowSpeed)
|
|
458
|
+
for (const [key] of SESSION_FLOW_COLOR_CONTROLS) {
|
|
459
|
+
if (!sessionFlowColorDirty.has(key)) sessionFlowColorDrafts[key] = normalizeSessionFlowColor(currentPreferences[key])
|
|
460
|
+
}
|
|
308
461
|
renderParticleTraversal()
|
|
462
|
+
renderSessionFlowSpeed()
|
|
463
|
+
renderSessionFlowColors()
|
|
309
464
|
renderPersistence()
|
|
310
465
|
}
|
|
311
466
|
|
|
@@ -329,6 +484,10 @@ export function createThemeSettingsOverlay({
|
|
|
329
484
|
if (target.hasAttribute('data-prts-theme-settings-close')) { setOpen(false); return }
|
|
330
485
|
if (target.hasAttribute('data-prts-setting-key')) {
|
|
331
486
|
const raw = target.dataset.prtsSettingValue
|
|
487
|
+
if (target.dataset.prtsSettingKey === 'sessionFlowPalette') {
|
|
488
|
+
sessionFlowColorDirty.clear()
|
|
489
|
+
sessionFlowColorDrafts = {}
|
|
490
|
+
}
|
|
332
491
|
markFeedback(target)
|
|
333
492
|
onPreferenceChange(target.dataset.prtsSettingKey, raw === 'true' ? true : raw === 'false' ? false : raw)
|
|
334
493
|
return
|
|
@@ -339,6 +498,10 @@ export function createThemeSettingsOverlay({
|
|
|
339
498
|
if (target.hasAttribute('data-prts-reset-confirm-action')) {
|
|
340
499
|
particleTraversalSpeedDirty = false
|
|
341
500
|
particleTraversalSpeedDraft = undefined
|
|
501
|
+
sessionFlowSpeedDirty = false
|
|
502
|
+
sessionFlowSpeedDraft = undefined
|
|
503
|
+
sessionFlowColorDirty.clear()
|
|
504
|
+
sessionFlowColorDrafts = {}
|
|
342
505
|
setResetConfirmation(false)
|
|
343
506
|
onResetVisual()
|
|
344
507
|
}
|
|
@@ -346,6 +509,15 @@ export function createThemeSettingsOverlay({
|
|
|
346
509
|
|
|
347
510
|
function onPanelInput(event) {
|
|
348
511
|
const target = event.target
|
|
512
|
+
if (target?.matches?.('input[data-prts-setting-color]')) {
|
|
513
|
+
const key = target.dataset.prtsSettingKey
|
|
514
|
+
const value = normalizeSessionFlowColor(target.value, currentSessionFlowColor(key))
|
|
515
|
+
sessionFlowColorDrafts[key] = value
|
|
516
|
+
sessionFlowColorDirty.add(key)
|
|
517
|
+
renderSessionFlowColors()
|
|
518
|
+
onPreferencePreview(key, value)
|
|
519
|
+
return
|
|
520
|
+
}
|
|
349
521
|
if (!target?.matches?.('input[data-prts-setting-range]')) return
|
|
350
522
|
const value = Number(target.value)
|
|
351
523
|
if (!Number.isFinite(value)) return
|
|
@@ -355,6 +527,12 @@ export function createThemeSettingsOverlay({
|
|
|
355
527
|
renderParticleTraversal()
|
|
356
528
|
onPreferencePreview('particleTraversalSpeed', particleTraversalSpeedDraft)
|
|
357
529
|
return
|
|
530
|
+
} else if (target.dataset.prtsSettingKey === 'sessionFlowSpeed') {
|
|
531
|
+
sessionFlowSpeedDraft = normalizeSessionFlowSpeed(value)
|
|
532
|
+
sessionFlowSpeedDirty = true
|
|
533
|
+
renderSessionFlowSpeed()
|
|
534
|
+
onPreferencePreview('sessionFlowSpeed', sessionFlowSpeedDraft)
|
|
535
|
+
return
|
|
358
536
|
} else {
|
|
359
537
|
return
|
|
360
538
|
}
|
|
@@ -378,8 +556,13 @@ export function createThemeSettingsOverlay({
|
|
|
378
556
|
const renderMediaState = () => renderState()
|
|
379
557
|
const commitFromControl = event => {
|
|
380
558
|
const target = event.target
|
|
559
|
+
if (target?.matches?.('input[data-prts-setting-color]')) {
|
|
560
|
+
if (event.type === 'change' || event.type === 'focusout') commitSessionFlowColor(target.dataset.prtsSettingKey)
|
|
561
|
+
return
|
|
562
|
+
}
|
|
381
563
|
if (!target?.matches?.('input[data-prts-setting-range]')) return
|
|
382
564
|
if (target.dataset.prtsSettingKey === 'particleTraversalSpeed') commitParticleTraversalSpeed()
|
|
565
|
+
if (target.dataset.prtsSettingKey === 'sessionFlowSpeed') commitSessionFlowSpeed()
|
|
383
566
|
}
|
|
384
567
|
|
|
385
568
|
trigger?.addEventListener('click', toggle)
|
|
@@ -400,6 +583,10 @@ export function createThemeSettingsOverlay({
|
|
|
400
583
|
currentStatus = status
|
|
401
584
|
currentPersistence = persistenceState ?? { phase: 'idle', revision: 0 }
|
|
402
585
|
if (!particleTraversalSpeedDirty) particleTraversalSpeedDraft = normalizeParticleTraversalSpeed(preferences?.particleTraversalSpeed)
|
|
586
|
+
if (!sessionFlowSpeedDirty) sessionFlowSpeedDraft = normalizeSessionFlowSpeed(preferences?.sessionFlowSpeed)
|
|
587
|
+
for (const [key] of SESSION_FLOW_COLOR_CONTROLS) {
|
|
588
|
+
if (!sessionFlowColorDirty.has(key)) sessionFlowColorDrafts[key] = normalizeSessionFlowColor(preferences?.[key])
|
|
589
|
+
}
|
|
403
590
|
renderState()
|
|
404
591
|
},
|
|
405
592
|
open: () => setOpen(true),
|