@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/package.json CHANGED
@@ -1,9 +1,18 @@
1
1
  {
2
2
  "name": "@ash-qw/dsh-theme-prts",
3
- "version": "0.1.92",
3
+ "version": "0.1.94",
4
4
  "private": false,
5
5
  "type": "module",
6
- "description": "Unofficial personal non-commercial Arknights P.R.T.S. fan UI for DeepSeek Harness",
6
+ "description": "Unofficial Arknights P.R.T.S.-inspired UI theme for DeepSeek Harness Web",
7
+ "keywords": [
8
+ "deepseek-harness",
9
+ "dsh",
10
+ "dsh-plugin",
11
+ "theme",
12
+ "ui",
13
+ "arknights",
14
+ "prts"
15
+ ],
7
16
  "license": "SEE LICENSE IN LICENSE",
8
17
  "repository": {
9
18
  "type": "git",
@@ -44,6 +53,7 @@
44
53
  "cordis.patch.yml",
45
54
  "README.md",
46
55
  "README.en.md",
56
+ "CHANGELOG.md",
47
57
  "LICENSE",
48
58
  "THIRD_PARTY_NOTICES.md"
49
59
  ],
@@ -107,6 +107,8 @@ const PREVIEW_TOUCH_DURATION = 1200
107
107
  const SNAP_DELAY = 110
108
108
  const TOUCH_WAVE_DURATION = 620
109
109
  const HISTORY_PAGE_SETTLE_LIMIT = 4000
110
+ const GEOMETRY_SETTLE_FRAME_LIMIT = 8
111
+ const GEOMETRY_SETTLE_STABLE_FRAMES = 2
110
112
  let scaleInstanceSeed = 0
111
113
 
112
114
  function clamp(value, minimum, maximum) {
@@ -764,6 +766,10 @@ export function createConversationScaleAdapter({ document, window, sessions }) {
764
766
  let scaleLengths = resolveConversationScaleLengths(focusContrast)
765
767
  let contentLeft
766
768
  let geometryDirty = true
769
+ let geometrySettleFrame
770
+ let geometrySettleFramesRemaining = 0
771
+ let geometrySettleStableFrames = 0
772
+ let geometrySettleSignature
767
773
  let observedOperationWidth
768
774
  let observedOperationHeight
769
775
  let started = false
@@ -785,6 +791,80 @@ export function createConversationScaleAdapter({ document, window, sessions }) {
785
791
  const currentTime = timestamp => Number.isFinite(timestamp)
786
792
  ? timestamp
787
793
  : window?.performance?.now?.() ?? Date.now()
794
+ const phoneScaleHidden = () => Number(window?.innerWidth) <= 640
795
+
796
+ function currentGeometrySignature() {
797
+ if (!operation || !scroller) return undefined
798
+ const operationBox = operation.getBoundingClientRect?.()
799
+ const scrollerBox = scroller.getBoundingClientRect?.()
800
+ const composerBox = composer?.getBoundingClientRect?.()
801
+ if (!operationBox || !scrollerBox) return undefined
802
+ const values = [
803
+ operationBox.width,
804
+ operationBox.height,
805
+ scrollerBox.top - operationBox.top,
806
+ scrollerBox.bottom - operationBox.top,
807
+ scrollerBox.left - operationBox.left,
808
+ scrollerBox.right - operationBox.left,
809
+ composerBox ? composerBox.top - operationBox.top : -1,
810
+ composerBox ? composerBox.bottom - operationBox.top : -1,
811
+ composerBox ? composerBox.left - operationBox.left : -1,
812
+ composerBox ? composerBox.right - operationBox.left : -1,
813
+ ]
814
+ if (!values.every(Number.isFinite)) return undefined
815
+ return values.map(value => Number(value.toFixed(2))).join(':')
816
+ }
817
+
818
+ function sampleGeometryStabilization() {
819
+ geometrySettleFrame = undefined
820
+ if (!started || failed || geometrySettleFramesRemaining <= 0) return
821
+ geometrySettleFramesRemaining -= 1
822
+ const signature = currentGeometrySignature()
823
+ if (signature === undefined) {
824
+ geometrySettleStableFrames = 0
825
+ } else if (signature !== geometrySettleSignature) {
826
+ geometrySettleSignature = signature
827
+ geometrySettleStableFrames = 1
828
+ geometryDirty = true
829
+ obstructionDirty = true
830
+ schedule()
831
+ } else {
832
+ geometrySettleStableFrames += 1
833
+ }
834
+ if (geometrySettleStableFrames >= GEOMETRY_SETTLE_STABLE_FRAMES) {
835
+ geometrySettleFramesRemaining = 0
836
+ return
837
+ }
838
+ if (geometrySettleFramesRemaining > 0) {
839
+ geometrySettleFrame = requestFrame(sampleGeometryStabilization)
840
+ }
841
+ }
842
+
843
+ function requestGeometryStabilization() {
844
+ if (!started || failed || phoneScaleHidden()) return
845
+ geometrySettleFramesRemaining = GEOMETRY_SETTLE_FRAME_LIMIT
846
+ geometrySettleStableFrames = 0
847
+ if (geometrySettleFrame === undefined) {
848
+ geometrySettleFrame = requestFrame(sampleGeometryStabilization)
849
+ }
850
+ }
851
+
852
+ function stopGeometryStabilization() {
853
+ cancelFrame(geometrySettleFrame)
854
+ geometrySettleFrame = undefined
855
+ geometrySettleFramesRemaining = 0
856
+ geometrySettleStableFrames = 0
857
+ geometrySettleSignature = undefined
858
+ }
859
+
860
+ function onHostGeometryChange() {
861
+ if (phoneScaleHidden()) {
862
+ stopGeometryStabilization()
863
+ return
864
+ }
865
+ requestGeometryStabilization()
866
+ schedule(true)
867
+ }
788
868
 
789
869
  function reducedMotion() {
790
870
  return window?.matchMedia?.('(prefers-reduced-motion: reduce)')?.matches
@@ -997,7 +1077,6 @@ export function createConversationScaleAdapter({ document, window, sessions }) {
997
1077
  scanPending = true
998
1078
  fullScanPending = true
999
1079
  }
1000
- if (resizeActive) return
1001
1080
  if (frame !== undefined || failed) return
1002
1081
  frame = requestFrame(flush)
1003
1082
  }
@@ -1117,10 +1196,12 @@ export function createConversationScaleAdapter({ document, window, sessions }) {
1117
1196
  setScaleResizeState(resizeActive)
1118
1197
  cancelJump()
1119
1198
  resetWave()
1199
+ requestGeometryStabilization()
1120
1200
  return true
1121
1201
  }
1122
1202
 
1123
1203
  function disconnectRoots() {
1204
+ stopGeometryStabilization()
1124
1205
  clearTimers()
1125
1206
  hidePreview()
1126
1207
  disconnectPreviewObserver()
@@ -2129,10 +2210,22 @@ export function createConversationScaleAdapter({ document, window, sessions }) {
2129
2210
  if (started || !document) return
2130
2211
  started = true
2131
2212
  failed = false
2213
+ window?.addEventListener?.('resize', onHostGeometryChange)
2214
+ window?.addEventListener?.('orientationchange', onHostGeometryChange)
2215
+ window?.addEventListener?.('pageshow', onHostGeometryChange)
2216
+ window?.visualViewport?.addEventListener?.('resize', onHostGeometryChange)
2132
2217
  const ResizeObserver = window?.ResizeObserver
2133
2218
  if (typeof ResizeObserver === 'function') {
2134
2219
  resizeObserver = new ResizeObserver((entries = []) => {
2135
2220
  geometryDirty = true
2221
+ if (phoneScaleHidden()) {
2222
+ stopGeometryStabilization()
2223
+ if (resizeSettleTimer !== undefined) window?.clearTimeout?.(resizeSettleTimer)
2224
+ resizeSettleTimer = undefined
2225
+ setScaleResizeState(false)
2226
+ return
2227
+ }
2228
+ requestGeometryStabilization()
2136
2229
  const operationEntry = entries.find(entry => entry.target === operation)
2137
2230
  const width = Number(operationEntry?.contentRect?.width)
2138
2231
  const height = Number(operationEntry?.contentRect?.height)
@@ -2151,12 +2244,8 @@ export function createConversationScaleAdapter({ document, window, sessions }) {
2151
2244
  return
2152
2245
  }
2153
2246
  if (!resizeActive) {
2247
+ schedule()
2154
2248
  setScaleResizeState(true)
2155
- if (frame !== undefined) {
2156
- if (window?.cancelAnimationFrame) window.cancelAnimationFrame(frame)
2157
- else window?.clearTimeout?.(frame)
2158
- frame = undefined
2159
- }
2160
2249
  }
2161
2250
  if (resizeSettleTimer !== undefined) window?.clearTimeout?.(resizeSettleTimer)
2162
2251
  resizeSettleTimer = window?.setTimeout?.(() => {
@@ -2173,6 +2262,13 @@ export function createConversationScaleAdapter({ document, window, sessions }) {
2173
2262
  const external = mutations.filter(mutation =>
2174
2263
  !mutation.target?.closest?.('[data-prts-conversation-scale], [data-prts-conversation-preview], [data-prts-conversation-history-hint], [data-prts-conversation-history-status]')
2175
2264
  )
2265
+ if (phoneScaleHidden()) return
2266
+ if (external.some(mutation =>
2267
+ operation?.contains?.(mutation.target)
2268
+ || mutation.target?.contains?.(operation)
2269
+ || mutation.target?.matches?.('header, [data-host-header], [data-slot*="header" i]')
2270
+ || mutationAffectsOverlay(mutation)
2271
+ )) requestGeometryStabilization()
2176
2272
  const historyRelevant = external.some(mutation =>
2177
2273
  mutation.type === 'childList'
2178
2274
  && operation?.contains?.(mutation.target)
@@ -2210,9 +2306,17 @@ export function createConversationScaleAdapter({ document, window, sessions }) {
2210
2306
  ],
2211
2307
  })
2212
2308
  }
2309
+ document.fonts?.ready?.then?.(() => {
2310
+ if (started) requestGeometryStabilization()
2311
+ }).catch?.(() => {})
2213
2312
  schedule(true)
2214
2313
  },
2215
2314
  dispose() {
2315
+ window?.removeEventListener?.('resize', onHostGeometryChange)
2316
+ window?.removeEventListener?.('orientationchange', onHostGeometryChange)
2317
+ window?.removeEventListener?.('pageshow', onHostGeometryChange)
2318
+ window?.visualViewport?.removeEventListener?.('resize', onHostGeometryChange)
2319
+ stopGeometryStabilization()
2216
2320
  started = false
2217
2321
  failed = false
2218
2322
  mutationObserver?.disconnect()
@@ -45,7 +45,6 @@ export function applyPrtsPlugin(ctx, environment) {
45
45
  const safeMode = isSafeMode(window?.location?.search ?? '')
46
46
  const storage = window?.localStorage
47
47
  const themeService = contextService(ctx, 'theme')
48
- const theme = createThemeController({ document, window, cssText, service: themeService })
49
48
  const startup = createPrtsStartupSequence({ document, window, prtsEmblem: assets.prtsEmblem, rhodesEmblem: assets.emblem, timings: startupTimings })
50
49
  const composerGlass = createComposerGlassAdapter({ document, window })
51
50
  const assistantGlass = createAssistantGlassAdapter({ document, window })
@@ -60,6 +59,15 @@ export function applyPrtsPlugin(ctx, environment) {
60
59
  sync()
61
60
  },
62
61
  })
62
+ const theme = createThemeController({
63
+ document,
64
+ window,
65
+ cssText,
66
+ service: themeService,
67
+ onTransitionStateChange(active) {
68
+ particleField.setSchemeTransitionActive(active)
69
+ },
70
+ })
63
71
  const sessions = contextService(ctx, 'sessions')
64
72
  const toBottom = createToBottomAdapter({ document, window })
65
73
  const conversationControls = createConversationControlAdapter({ document, window })
@@ -160,8 +168,11 @@ export function applyPrtsPlugin(ctx, environment) {
160
168
  if (!themeAlreadyApplied) theme.apply(preferences)
161
169
  operations ||= createOperationsShell({
162
170
  document, window, assets, adapter, hostGeometry,
163
- onSchemeToggle(next) {
164
- theme.setTheme(next)
171
+ onSchemeToggle(next, interaction) {
172
+ return theme.setTheme(next, { ...interaction, animate: true })
173
+ },
174
+ onSchemeDragStart(next, interaction) {
175
+ return theme.beginThemeTransition(next, interaction)
165
176
  },
166
177
  onThemeDisable() {
167
178
  persistAndApply(updatePreferenceValue(preferences, 'enabled', false))
@@ -169,6 +180,10 @@ export function applyPrtsPlugin(ctx, environment) {
169
180
  onPreferenceChange(key, value) {
170
181
  persistAndApply(updatePreferenceValue(preferences, key, value))
171
182
  },
183
+ onPreferencePreview(key, value) {
184
+ if (key !== 'particleTraversalSpeed') return
185
+ particleField.update(updatePreferenceValue(preferences, key, value))
186
+ },
172
187
  onVisualReset() {
173
188
  persistAndApply({
174
189
  ...DEFAULT_PREFERENCES,