@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
|
@@ -326,7 +326,7 @@ export function createParticleFieldAdapter({ document, window, emblem = '', embl
|
|
|
326
326
|
const rhodesIndex = Math.max(0, emblemSequence.findIndex(entry => entry.key === 'rhodes-island'))
|
|
327
327
|
const suppliedHeroMask = normalizeEmblemMasks(heroEmblemMask ? [heroEmblemMask] : [], window).get('rhodes-island-hero')
|
|
328
328
|
const empty = { mounted: false, hero: false, side: -1, transition: null, anchor: { horizontalProgress: 0, verticalProgress: 0 }, phase: 'error', error: '徽记资源异常' }
|
|
329
|
-
if (!document || !window) return { update() {}, inspect: () => empty, dispose() {} }
|
|
329
|
+
if (!document || !window) return { update() {}, setSchemeTransitionActive() {}, inspect: () => empty, dispose() {} }
|
|
330
330
|
|
|
331
331
|
let preferences = {}
|
|
332
332
|
let operation
|
|
@@ -378,6 +378,7 @@ export function createParticleFieldAdapter({ document, window, emblem = '', embl
|
|
|
378
378
|
let side = -1
|
|
379
379
|
let segment = 0
|
|
380
380
|
let transition
|
|
381
|
+
let traversalOffset = 0
|
|
381
382
|
let pendingSegment
|
|
382
383
|
let transitionStartedAt
|
|
383
384
|
let densityTransition
|
|
@@ -394,6 +395,7 @@ export function createParticleFieldAdapter({ document, window, emblem = '', embl
|
|
|
394
395
|
let targetPrewarmQueue = []
|
|
395
396
|
let pauseStartedAt
|
|
396
397
|
let hydrationPaused = false
|
|
398
|
+
let schemeTransitionPaused = false
|
|
397
399
|
let hydrationTimer
|
|
398
400
|
let hydrationFrame
|
|
399
401
|
let hydrationStableFrames = 0
|
|
@@ -427,7 +429,7 @@ export function createParticleFieldAdapter({ document, window, emblem = '', embl
|
|
|
427
429
|
: preferences.conversationParticleDensity
|
|
428
430
|
const densityProfile = density => PARTICLE_DENSITY_PROFILES[density] ?? PARTICLE_DENSITY_PROFILES.standard
|
|
429
431
|
const particleRadius = density => densityProfile(density ?? activeDensity()).radius
|
|
430
|
-
const canRenderFrame = () => documentVisible && canvasVisible && !hydrationPaused && !resizing
|
|
432
|
+
const canRenderFrame = () => !disposed && documentVisible && canvasVisible && !hydrationPaused && !schemeTransitionPaused && !resizing
|
|
431
433
|
const layoutWidth = () => width
|
|
432
434
|
const layoutHeight = () => height
|
|
433
435
|
const layoutShiftX = () => 0
|
|
@@ -554,11 +556,51 @@ export function createParticleFieldAdapter({ document, window, emblem = '', embl
|
|
|
554
556
|
}
|
|
555
557
|
|
|
556
558
|
|
|
559
|
+
function particleTraversalSpeed(value = preferences) {
|
|
560
|
+
if (phoneStatic()) return 0
|
|
561
|
+
const numeric = Number(value?.particleTraversalSpeed)
|
|
562
|
+
return Number.isFinite(numeric) ? clamp(numeric, 0, 2) : 1
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
function currentScrollTop() {
|
|
566
|
+
return Number(scroller?.scrollTop) || 0
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
function traversalViewport() {
|
|
570
|
+
return Math.max(1, Number(scroller?.clientHeight) || height)
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
function traversalCoordinate(value = preferences) {
|
|
574
|
+
return traversalOffset + currentScrollTop() * particleTraversalSpeed(value) / traversalViewport()
|
|
575
|
+
}
|
|
576
|
+
|
|
557
577
|
function scrollProgress() {
|
|
558
578
|
if (!scroller) return 0
|
|
559
|
-
const
|
|
560
|
-
|
|
561
|
-
|
|
579
|
+
const coordinate = traversalCoordinate()
|
|
580
|
+
return coordinate - Math.floor(coordinate)
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
function restoreTraversalFromScroll() {
|
|
584
|
+
traversalOffset = 0
|
|
585
|
+
const coordinate = traversalCoordinate()
|
|
586
|
+
segment = Math.floor(coordinate)
|
|
587
|
+
side = sideForSegment(segment)
|
|
588
|
+
pendingSegment = undefined
|
|
589
|
+
transition = undefined
|
|
590
|
+
transitionStartedAt = undefined
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
function reanchorTraversal(coordinate = traversalCoordinate()) {
|
|
594
|
+
if (transition) {
|
|
595
|
+
const targetSegment = transition.targetSegment
|
|
596
|
+
side = sideForSegment(targetSegment)
|
|
597
|
+
transition = undefined
|
|
598
|
+
transitionStartedAt = undefined
|
|
599
|
+
commitTransitionTargets(targetSegment, true)
|
|
600
|
+
}
|
|
601
|
+
pendingSegment = undefined
|
|
602
|
+
traversalOffset = coordinate - currentScrollTop() * particleTraversalSpeed() / traversalViewport()
|
|
603
|
+
if (particles.length) snapParticlesToCurrentLayout()
|
|
562
604
|
}
|
|
563
605
|
|
|
564
606
|
function anchorFor(sideValue, verticalProgress) {
|
|
@@ -1082,6 +1124,19 @@ export function createParticleFieldAdapter({ document, window, emblem = '', embl
|
|
|
1082
1124
|
const entry = entries.find(candidate => candidate.target === operation) ?? entries[0]
|
|
1083
1125
|
const contentRect = entry?.contentRect
|
|
1084
1126
|
pendingResizeSize = contentRect ? sizeFromRect(contentRect) : readOperationSize()
|
|
1127
|
+
if (phoneStatic()) {
|
|
1128
|
+
const nextSize = pendingResizeSize
|
|
1129
|
+
clearResizeState()
|
|
1130
|
+
const changed = applyFieldSize(nextSize)
|
|
1131
|
+
if (changed && particles.length) snapParticlesToCurrentLayout()
|
|
1132
|
+
resizeCommits += changed ? 1 : 0
|
|
1133
|
+
syncCanvasBackingStore()
|
|
1134
|
+
geometryDirty = false
|
|
1135
|
+
cancelFrame()
|
|
1136
|
+
draw(Number(window.performance?.now?.()) || 0)
|
|
1137
|
+
cancelFrame()
|
|
1138
|
+
return
|
|
1139
|
+
}
|
|
1085
1140
|
if (resizeFrame !== undefined) return
|
|
1086
1141
|
resizeFrame = window.requestAnimationFrame?.(() => {
|
|
1087
1142
|
resizeFrame = undefined
|
|
@@ -1373,6 +1428,7 @@ export function createParticleFieldAdapter({ document, window, emblem = '', embl
|
|
|
1373
1428
|
return
|
|
1374
1429
|
}
|
|
1375
1430
|
const targetSide = sideForSegment(targetSegment)
|
|
1431
|
+
const direction = targetSegment > segment ? 1 : -1
|
|
1376
1432
|
if (targetSide === side || motionReduced() || phoneStatic()) {
|
|
1377
1433
|
side = targetSide
|
|
1378
1434
|
transition = undefined
|
|
@@ -1389,7 +1445,7 @@ export function createParticleFieldAdapter({ document, window, emblem = '', embl
|
|
|
1389
1445
|
...population,
|
|
1390
1446
|
fromSide: side,
|
|
1391
1447
|
toSide: targetSide,
|
|
1392
|
-
direction
|
|
1448
|
+
direction,
|
|
1393
1449
|
targetSegment,
|
|
1394
1450
|
progress: 0,
|
|
1395
1451
|
}
|
|
@@ -1398,9 +1454,27 @@ export function createParticleFieldAdapter({ document, window, emblem = '', embl
|
|
|
1398
1454
|
scheduleFrame()
|
|
1399
1455
|
}
|
|
1400
1456
|
|
|
1457
|
+
function retargetTransition(targetSegment) {
|
|
1458
|
+
if (!transition || targetSegment === transition.targetSegment) return
|
|
1459
|
+
const population = prepareTransitionTargets(targetSegment)
|
|
1460
|
+
if (!population.toCount) {
|
|
1461
|
+
reportState({ phase: 'error', error: '徽记资源异常' })
|
|
1462
|
+
return
|
|
1463
|
+
}
|
|
1464
|
+
transition = {
|
|
1465
|
+
...transition,
|
|
1466
|
+
...population,
|
|
1467
|
+
toSide: sideForSegment(targetSegment),
|
|
1468
|
+
direction: targetSegment >= segment ? 1 : -1,
|
|
1469
|
+
targetSegment,
|
|
1470
|
+
}
|
|
1471
|
+
pendingSegment = undefined
|
|
1472
|
+
}
|
|
1473
|
+
|
|
1401
1474
|
function resetTraversal() {
|
|
1402
1475
|
side = -1
|
|
1403
1476
|
segment = 0
|
|
1477
|
+
traversalOffset = -currentScrollTop() * particleTraversalSpeed() / traversalViewport()
|
|
1404
1478
|
pendingSegment = undefined
|
|
1405
1479
|
queuedDensityCount = undefined
|
|
1406
1480
|
queuedTargetRefresh = false
|
|
@@ -1430,6 +1504,9 @@ export function createParticleFieldAdapter({ document, window, emblem = '', embl
|
|
|
1430
1504
|
heroMarker = undefined
|
|
1431
1505
|
heroActive = false
|
|
1432
1506
|
scroller?.removeAttribute('data-prts-hero-active')
|
|
1507
|
+
side = -1
|
|
1508
|
+
segment = 0
|
|
1509
|
+
traversalOffset = -currentScrollTop() * particleTraversalSpeed() / traversalViewport()
|
|
1433
1510
|
pendingSegment = undefined
|
|
1434
1511
|
queuedDensityCount = undefined
|
|
1435
1512
|
queuedTargetRefresh = false
|
|
@@ -1469,14 +1546,13 @@ export function createParticleFieldAdapter({ document, window, emblem = '', embl
|
|
|
1469
1546
|
if (heroActive) leaveHero()
|
|
1470
1547
|
}
|
|
1471
1548
|
function onScroll() {
|
|
1472
|
-
if (!scroller) return
|
|
1549
|
+
if (!scroller || phoneStatic()) return
|
|
1473
1550
|
if (heroActive) {
|
|
1474
1551
|
scheduleFrame()
|
|
1475
1552
|
return
|
|
1476
1553
|
}
|
|
1477
|
-
const
|
|
1478
|
-
|
|
1479
|
-
if (transition) pendingSegment = desiredSegment
|
|
1554
|
+
const desiredSegment = Math.floor(traversalCoordinate())
|
|
1555
|
+
if (transition) retargetTransition(desiredSegment)
|
|
1480
1556
|
else if (desiredSegment !== segment) startTransition(desiredSegment)
|
|
1481
1557
|
scheduleFrame()
|
|
1482
1558
|
}
|
|
@@ -1519,6 +1595,7 @@ export function createParticleFieldAdapter({ document, window, emblem = '', embl
|
|
|
1519
1595
|
}
|
|
1520
1596
|
|
|
1521
1597
|
function registerContentMutations(mutations) {
|
|
1598
|
+
if (phoneStatic()) return
|
|
1522
1599
|
let weight = mutations.length
|
|
1523
1600
|
for (const mutation of mutations) {
|
|
1524
1601
|
for (const node of [...mutation.addedNodes, ...mutation.removedNodes]) {
|
|
@@ -1631,8 +1708,35 @@ export function createParticleFieldAdapter({ document, window, emblem = '', embl
|
|
|
1631
1708
|
cancelFrame()
|
|
1632
1709
|
}
|
|
1633
1710
|
|
|
1711
|
+
function rebindScroller(nextScroller) {
|
|
1712
|
+
scroller?.removeAttribute('data-prts-hero-active')
|
|
1713
|
+
scroller?.removeEventListener('scroll', onScroll)
|
|
1714
|
+
cancelHydrationResume()
|
|
1715
|
+
hydrationPaused = false
|
|
1716
|
+
mutationBurstScore = 0
|
|
1717
|
+
if (mutationBurstTimer !== undefined) window.clearTimeout?.(mutationBurstTimer)
|
|
1718
|
+
mutationBurstTimer = undefined
|
|
1719
|
+
heroMarker = undefined
|
|
1720
|
+
heroActive = false
|
|
1721
|
+
scroller = nextScroller
|
|
1722
|
+
scroller.addEventListener('scroll', onScroll, { passive: true })
|
|
1723
|
+
syncHeroState()
|
|
1724
|
+
if (!heroActive) {
|
|
1725
|
+
resetTraversal()
|
|
1726
|
+
if (!phoneStatic()) restoreTraversalFromScroll()
|
|
1727
|
+
commitTransitionTargets(segment, true)
|
|
1728
|
+
}
|
|
1729
|
+
scheduleFrame()
|
|
1730
|
+
}
|
|
1731
|
+
|
|
1634
1732
|
function mount(nextOperation, nextScroller) {
|
|
1635
|
-
if (operation === nextOperation &&
|
|
1733
|
+
if (operation === nextOperation && ambient?.isConnected && canvas?.isConnected) {
|
|
1734
|
+
if (scroller === nextScroller) return
|
|
1735
|
+
if (nextScroller) {
|
|
1736
|
+
rebindScroller(nextScroller)
|
|
1737
|
+
return
|
|
1738
|
+
}
|
|
1739
|
+
}
|
|
1636
1740
|
unmount()
|
|
1637
1741
|
operation = nextOperation
|
|
1638
1742
|
scroller = nextScroller
|
|
@@ -1643,12 +1747,13 @@ export function createParticleFieldAdapter({ document, window, emblem = '', embl
|
|
|
1643
1747
|
glow = created.glow
|
|
1644
1748
|
canvas = document.createElement('canvas')
|
|
1645
1749
|
canvas.setAttribute('data-prts-particle-layer', '')
|
|
1646
|
-
canvas.setAttribute('aria-label', '随对话滚动轮换阵营标识的粒子画布')
|
|
1750
|
+
canvas.setAttribute('aria-label', phoneStatic() ? '静态阵营标识粒子画布' : '随对话滚动轮换阵营标识的粒子画布')
|
|
1647
1751
|
canvas.style.visibility = 'hidden'
|
|
1648
1752
|
if (typeof window.CanvasRenderingContext2D === 'function') context = canvas.getContext('2d')
|
|
1649
1753
|
targetCache.clear()
|
|
1650
1754
|
initializeFieldSize()
|
|
1651
1755
|
syncHeroState()
|
|
1756
|
+
if (!heroActive) restoreTraversalFromScroll()
|
|
1652
1757
|
if (!particles.length && maskRecords.length) buildParticles()
|
|
1653
1758
|
if (context && particles.length) {
|
|
1654
1759
|
syncCanvasBackingStore()
|
|
@@ -1714,8 +1819,19 @@ export function createParticleFieldAdapter({ document, window, emblem = '', embl
|
|
|
1714
1819
|
if (!mediaQuery?.addEventListener) mediaQuery?.addListener?.(mediaListener)
|
|
1715
1820
|
document.addEventListener?.('visibilitychange', onVisibilityChange)
|
|
1716
1821
|
return {
|
|
1822
|
+
setSchemeTransitionActive(active) {
|
|
1823
|
+
const next = Boolean(active)
|
|
1824
|
+
if (schemeTransitionPaused === next) return
|
|
1825
|
+
schemeTransitionPaused = next
|
|
1826
|
+
updateFrameGate()
|
|
1827
|
+
},
|
|
1717
1828
|
update(nextPreferences = {}) {
|
|
1718
1829
|
const previousPreferences = preferences
|
|
1830
|
+
const traversalSpeedChanged = previousPreferences.particleTraversalSpeed !== undefined
|
|
1831
|
+
&& particleTraversalSpeed(previousPreferences) !== particleTraversalSpeed(nextPreferences)
|
|
1832
|
+
const preservedTraversalCoordinate = traversalSpeedChanged && scroller && !heroActive
|
|
1833
|
+
? traversalCoordinate(previousPreferences)
|
|
1834
|
+
: undefined
|
|
1719
1835
|
preferences = nextPreferences
|
|
1720
1836
|
disposed = false
|
|
1721
1837
|
if (!preferences.enabled) {
|
|
@@ -1734,6 +1850,7 @@ export function createParticleFieldAdapter({ document, window, emblem = '', embl
|
|
|
1734
1850
|
const activeDensityChanged = previousActiveDensity !== undefined && previousActiveDensity !== activeDensity()
|
|
1735
1851
|
reportState({ requestedPattern: 'orthogonal' })
|
|
1736
1852
|
if (particles.length && activeDensityChanged) scheduleDensityReassembly(targetParticleCount(), true)
|
|
1853
|
+
if (preservedTraversalCoordinate !== undefined && scroller && !heroActive) reanchorTraversal(preservedTraversalCoordinate)
|
|
1737
1854
|
if (!mutationObserver && window.MutationObserver && document.body) {
|
|
1738
1855
|
const observationRoot = document.querySelector('[data-slot="root"]')
|
|
1739
1856
|
?? document.querySelector('[data-prts-region="frame"]')
|
|
@@ -1771,6 +1888,10 @@ export function createParticleFieldAdapter({ document, window, emblem = '', embl
|
|
|
1771
1888
|
emblemKey: (heroActive || transition?.fromHero ? heroEmblem() : emblemForSegment(segment))?.key,
|
|
1772
1889
|
nextEmblemKey: transition ? emblemForSegment(transition.targetSegment)?.key : null,
|
|
1773
1890
|
segment,
|
|
1891
|
+
traversalSpeed: particleTraversalSpeed(),
|
|
1892
|
+
traversalOffset,
|
|
1893
|
+
traversalCoordinate: traversalCoordinate(),
|
|
1894
|
+
traversalProgress: scrollProgress(),
|
|
1774
1895
|
transition: transition ? {
|
|
1775
1896
|
fromSide: transition.fromSide,
|
|
1776
1897
|
toSide: transition.toSide,
|
|
@@ -1787,6 +1908,7 @@ export function createParticleFieldAdapter({ document, window, emblem = '', embl
|
|
|
1787
1908
|
firstFrameReady: canvas?.hasAttribute('data-prts-particle-ready') === true,
|
|
1788
1909
|
hydrationPaused,
|
|
1789
1910
|
sleeping: Boolean(context && particles.length && frame === undefined && canRenderFrame() && !motionReduced() && !phoneStatic()),
|
|
1911
|
+
schemeTransitionPaused,
|
|
1790
1912
|
pointer: {
|
|
1791
1913
|
active: pointerActive,
|
|
1792
1914
|
clientX: pointerClientX,
|
|
@@ -10,8 +10,13 @@ export const CONVERSATION_SCALE_FOCUS_CONTRAST_MAX = 100
|
|
|
10
10
|
export const CONVERSATION_SCALE_FOCUS_CONTRAST_STEP = 10
|
|
11
11
|
export const CONVERSATION_SCALE_FOCUS_CONTRAST_DEFAULT = 70
|
|
12
12
|
|
|
13
|
+
export const PARTICLE_TRAVERSAL_SPEED_MIN = 0
|
|
14
|
+
export const PARTICLE_TRAVERSAL_SPEED_MAX = 2
|
|
15
|
+
export const PARTICLE_TRAVERSAL_SPEED_STEP = 0.25
|
|
16
|
+
export const PARTICLE_TRAVERSAL_SPEED_DEFAULT = 1
|
|
17
|
+
|
|
13
18
|
export const DEFAULT_PREFERENCES = Object.freeze({
|
|
14
|
-
version:
|
|
19
|
+
version: 8,
|
|
15
20
|
enabled: false,
|
|
16
21
|
preset: 'standard-tactical',
|
|
17
22
|
texture: 'full',
|
|
@@ -20,7 +25,9 @@ export const DEFAULT_PREFERENCES = Object.freeze({
|
|
|
20
25
|
bootAnimation: true,
|
|
21
26
|
conversationParticleDensity: 'sparse',
|
|
22
27
|
heroParticleDensity: 'light',
|
|
28
|
+
particleTraversalSpeed: PARTICLE_TRAVERSAL_SPEED_DEFAULT,
|
|
23
29
|
particlePattern: 'orthogonal',
|
|
30
|
+
railDefaultHidden: false,
|
|
24
31
|
conversationScaleMaxDistance: CONVERSATION_SCALE_DISTANCE_DEFAULT,
|
|
25
32
|
conversationScaleFocusContrast: CONVERSATION_SCALE_FOCUS_CONTRAST_DEFAULT,
|
|
26
33
|
})
|
|
@@ -60,10 +67,10 @@ export const PARTICLE_DETAIL_LEVELS = Object.freeze({
|
|
|
60
67
|
})
|
|
61
68
|
export const PREFERENCE_GROUPS = Object.freeze({
|
|
62
69
|
background: Object.freeze(['texture']),
|
|
63
|
-
particles: Object.freeze(['conversationParticleDensity', 'heroParticleDensity']),
|
|
70
|
+
particles: Object.freeze(['conversationParticleDensity', 'heroParticleDensity', 'particleTraversalSpeed']),
|
|
64
71
|
material: Object.freeze(['glass']),
|
|
65
72
|
accessibility: Object.freeze(['motion', 'bootAnimation']),
|
|
66
|
-
navigation: Object.freeze(['conversationScaleMaxDistance', 'conversationScaleFocusContrast']),
|
|
73
|
+
navigation: Object.freeze(['railDefaultHidden', 'conversationScaleMaxDistance', 'conversationScaleFocusContrast']),
|
|
67
74
|
})
|
|
68
75
|
|
|
69
76
|
const TEXTURES = new Set(['off', 'restrained', 'full'])
|
|
@@ -114,6 +121,13 @@ function scaleFocusContrastOr(value, fallback) {
|
|
|
114
121
|
return Math.round(clamped / CONVERSATION_SCALE_FOCUS_CONTRAST_STEP) * CONVERSATION_SCALE_FOCUS_CONTRAST_STEP
|
|
115
122
|
}
|
|
116
123
|
|
|
124
|
+
function particleTraversalSpeedOr(value, fallback) {
|
|
125
|
+
const numeric = Number(value)
|
|
126
|
+
if (!Number.isFinite(numeric)) return fallback
|
|
127
|
+
const clamped = Math.min(PARTICLE_TRAVERSAL_SPEED_MAX, Math.max(PARTICLE_TRAVERSAL_SPEED_MIN, numeric))
|
|
128
|
+
return Math.round(clamped / PARTICLE_TRAVERSAL_SPEED_STEP) * PARTICLE_TRAVERSAL_SPEED_STEP
|
|
129
|
+
}
|
|
130
|
+
|
|
117
131
|
function normalizeGlass(input) {
|
|
118
132
|
if (input.glassEnabled === false || input.glass === 'off') return 'off'
|
|
119
133
|
if (input.glass === 'liquid') return 'clear'
|
|
@@ -141,7 +155,7 @@ export function normalizePreferences(value) {
|
|
|
141
155
|
const particlePreset = VISUAL_PRESETS[input.preset] ?? DEFAULT_PREFERENCES
|
|
142
156
|
const legacyDensities = legacyParticleDensities(input)
|
|
143
157
|
const normalized = {
|
|
144
|
-
version:
|
|
158
|
+
version: 8,
|
|
145
159
|
enabled: booleanOr(input.enabled, DEFAULT_PREFERENCES.enabled),
|
|
146
160
|
preset: enumOr(migratedPreset, PRESETS, DEFAULT_PREFERENCES.preset),
|
|
147
161
|
texture: enumOr(input.texture, TEXTURES, DEFAULT_PREFERENCES.texture),
|
|
@@ -150,7 +164,12 @@ export function normalizePreferences(value) {
|
|
|
150
164
|
bootAnimation: booleanOr(input.bootAnimation, DEFAULT_PREFERENCES.bootAnimation),
|
|
151
165
|
conversationParticleDensity: enumOr(legacyDensities.conversation, PARTICLE_DENSITIES, particlePreset.conversationParticleDensity),
|
|
152
166
|
heroParticleDensity: enumOr(legacyDensities.hero, PARTICLE_DENSITIES, particlePreset.heroParticleDensity),
|
|
167
|
+
particleTraversalSpeed: particleTraversalSpeedOr(
|
|
168
|
+
input.particleTraversalSpeed,
|
|
169
|
+
DEFAULT_PREFERENCES.particleTraversalSpeed,
|
|
170
|
+
),
|
|
153
171
|
particlePattern: 'orthogonal',
|
|
172
|
+
railDefaultHidden: booleanOr(input.railDefaultHidden, DEFAULT_PREFERENCES.railDefaultHidden),
|
|
154
173
|
conversationScaleMaxDistance: scaleDistanceOr(
|
|
155
174
|
input.conversationScaleMaxDistance,
|
|
156
175
|
DEFAULT_PREFERENCES.conversationScaleMaxDistance,
|
|
@@ -205,7 +224,7 @@ export function loadPreferences(storage) {
|
|
|
205
224
|
const raw = storage?.getItem(PRTS_STORAGE_KEY)
|
|
206
225
|
if (raw === null || raw === undefined) return { ...DEFAULT_PREFERENCES }
|
|
207
226
|
const parsed = JSON.parse(raw)
|
|
208
|
-
if (![1, 2, 3, 4, 5, 6].includes(parsed?.version)) return { ...DEFAULT_PREFERENCES }
|
|
227
|
+
if (![1, 2, 3, 4, 5, 6, 7, 8].includes(parsed?.version)) return { ...DEFAULT_PREFERENCES }
|
|
209
228
|
return normalizePreferences(parsed)
|
|
210
229
|
} catch {
|
|
211
230
|
return { ...DEFAULT_PREFERENCES }
|
|
@@ -29,6 +29,11 @@ export function createResizeShieldAdapter({
|
|
|
29
29
|
|
|
30
30
|
function onResize() {
|
|
31
31
|
if (!started) return
|
|
32
|
+
if (Number(window?.innerWidth) <= 640) {
|
|
33
|
+
clearTimer()
|
|
34
|
+
setActive(false)
|
|
35
|
+
return
|
|
36
|
+
}
|
|
32
37
|
setActive(true)
|
|
33
38
|
clearTimer()
|
|
34
39
|
settleTimer = window?.setTimeout?.(settle, settleDelay)
|