dsh-smooth-stream 0.4.3 → 0.6.0
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/README.en.md +13 -0
- package/README.md +13 -0
- package/lib/client.js +962 -1051
- package/lib/client.js.map +1 -1
- package/lib/index.js +22 -6
- package/package.json +11 -5
- package/src/client/AgentRowEntrance.module.css +43 -0
- package/src/client/FollowHost.tsx +18 -1
- package/src/client/SmoothStreamCard.module.css +34 -0
- package/src/client/SmoothStreamCard.tsx +39 -10
- package/src/client/TypewriterAssistantNodeView.tsx +130 -21
- package/src/client/TypewriterToolNodeView.tsx +9 -1
- package/src/client/clientStore.ts +71 -12
- package/src/client/index.ts +15 -29
- package/src/client/locales.ts +25 -5
- package/src/client/smooth-stream-card-controller.ts +10 -6
- package/src/client/smooth-stream-settings-api.ts +6 -4
- package/src/client/teleprompterGlide.ts +1021 -75
- package/src/client/turn-process-face.d.ts +27 -0
- package/src/plugin.ts +30 -6
- package/src/settings-api.ts +4 -2
- package/src/settings.ts +26 -8
- package/src/client/auto-collapse-controller.ts +0 -1072
|
@@ -13,29 +13,88 @@
|
|
|
13
13
|
|
|
14
14
|
type ClientRuntimeClient = typeof import('@deepseek-ai/dsh-client-runtime/client')
|
|
15
15
|
|
|
16
|
+
export interface SnapshotStoreLike<T> {
|
|
17
|
+
getSnapshot(): T
|
|
18
|
+
subscribe(listener: (state: T) => void): () => void
|
|
19
|
+
update(mutator: (draft: T) => void): void
|
|
20
|
+
set(next: T): void
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function fallbackSnapshotStore<T extends object>(init: T): SnapshotStoreLike<T> {
|
|
24
|
+
let state = init
|
|
25
|
+
const listeners = new Set<(state: T) => void>()
|
|
26
|
+
return {
|
|
27
|
+
getSnapshot: () => state,
|
|
28
|
+
subscribe: listener => {
|
|
29
|
+
listeners.add(listener)
|
|
30
|
+
return () => { listeners.delete(listener) }
|
|
31
|
+
},
|
|
32
|
+
update: mutator => {
|
|
33
|
+
const draft = Object.create(
|
|
34
|
+
Object.getPrototypeOf(state),
|
|
35
|
+
Object.getOwnPropertyDescriptors(state),
|
|
36
|
+
) as T
|
|
37
|
+
mutator(draft)
|
|
38
|
+
state = draft
|
|
39
|
+
for (const listener of [...listeners]) listener(state)
|
|
40
|
+
},
|
|
41
|
+
set: next => {
|
|
42
|
+
state = next
|
|
43
|
+
for (const listener of [...listeners]) listener(state)
|
|
44
|
+
},
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
16
48
|
/**
|
|
17
49
|
* Runtime require: the module-loader factory scopes its own resolver over the
|
|
18
50
|
* booting kernel's table; under Node (vitest) there is no global require, so
|
|
19
51
|
* fall back to `createRequire`.
|
|
20
52
|
*/
|
|
21
|
-
function pickRequire(): NodeRequire {
|
|
22
|
-
if (typeof require === 'function')
|
|
53
|
+
function pickRequire(): NodeRequire | null {
|
|
54
|
+
if (typeof require === 'function') {
|
|
55
|
+
try {
|
|
56
|
+
return require
|
|
57
|
+
} catch {
|
|
58
|
+
return null
|
|
59
|
+
}
|
|
60
|
+
}
|
|
23
61
|
if (typeof process !== 'undefined' && typeof process.getBuiltinModule === 'function') {
|
|
24
|
-
|
|
25
|
-
|
|
62
|
+
try {
|
|
63
|
+
const { createRequire } = process.getBuiltinModule('node:module')
|
|
64
|
+
return createRequire(process.cwd() + '/package.json')
|
|
65
|
+
} catch {
|
|
66
|
+
return null
|
|
67
|
+
}
|
|
26
68
|
}
|
|
27
|
-
|
|
69
|
+
return null
|
|
28
70
|
}
|
|
29
71
|
|
|
30
|
-
let clientStore: ClientRuntimeClient
|
|
72
|
+
let clientStore: Partial<ClientRuntimeClient> | undefined
|
|
31
73
|
|
|
32
74
|
try {
|
|
33
|
-
|
|
34
|
-
|
|
75
|
+
const req = pickRequire()
|
|
76
|
+
if (req !== null) {
|
|
77
|
+
try {
|
|
78
|
+
// 0.1.2+ seeds the split store package directly into the module table.
|
|
79
|
+
clientStore = req('@deepseek-ai/dsh-client-store') as ClientRuntimeClient
|
|
80
|
+
} catch {
|
|
81
|
+
try {
|
|
82
|
+
// ≤ 0.1.1 owns the store engine on the client-runtime client face.
|
|
83
|
+
clientStore = req('@deepseek-ai/dsh-client-runtime/client') as ClientRuntimeClient
|
|
84
|
+
} catch {
|
|
85
|
+
// Fallback below
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
35
89
|
} catch {
|
|
36
|
-
//
|
|
37
|
-
|
|
90
|
+
// Fallback below
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export interface SnapshotStore<T> {
|
|
94
|
+
getSnapshot(): T
|
|
95
|
+
subscribe(listener: () => void): () => void
|
|
96
|
+
update(mutator: (draft: T) => void): void
|
|
97
|
+
set(next: T): void
|
|
38
98
|
}
|
|
39
99
|
|
|
40
|
-
export const createSnapshotStore = clientStore
|
|
41
|
-
export type { SnapshotStore } from '@deepseek-ai/dsh-client-runtime/client'
|
|
100
|
+
export const createSnapshotStore = (clientStore?.createSnapshotStore ?? fallbackSnapshotStore) as <T extends object>(init: T) => SnapshotStore<T>
|
package/src/client/index.ts
CHANGED
|
@@ -7,7 +7,6 @@ import type { ConnectionHandle } from '@deepseek-ai/dsh-client-connection/client
|
|
|
7
7
|
import type {} from '@deepseek-ai/dsh-client-ui-settings-plugins/client'
|
|
8
8
|
import type { ChatNodeViewProps } from '@deepseek-ai/dsh-client-ui-conversation/client'
|
|
9
9
|
import { TypewriterAssistantNodeView } from './TypewriterAssistantNodeView.tsx'
|
|
10
|
-
import { AutoCollapseController } from './auto-collapse-controller.ts'
|
|
11
10
|
import { wrapFollowNodeView, type FollowWrapProps } from './TypewriterToolNodeView.tsx'
|
|
12
11
|
import { SmoothStreamCard } from './SmoothStreamCard.tsx'
|
|
13
12
|
import { SmoothStreamCardController } from './smooth-stream-card-controller.ts'
|
|
@@ -88,7 +87,10 @@ function readBootConfig(): StreamConfig {
|
|
|
88
87
|
* @param ctx - Browser context carrying the slot registry.
|
|
89
88
|
* @returns Restorer that puts the original components back.
|
|
90
89
|
*/
|
|
91
|
-
function wrapAgentChatRows(
|
|
90
|
+
function wrapAgentChatRows(
|
|
91
|
+
ctx: ClientContext,
|
|
92
|
+
useControlScroll: () => boolean,
|
|
93
|
+
): () => void {
|
|
92
94
|
const restores: Array<() => void> = []
|
|
93
95
|
const wrapped = new WeakSet<object>()
|
|
94
96
|
|
|
@@ -99,7 +101,7 @@ function wrapAgentChatRows(ctx: ClientContext): () => void {
|
|
|
99
101
|
const current = entry.component
|
|
100
102
|
if (!isWrappableComponent(current) || wrapped.has(current)) continue
|
|
101
103
|
const inner = current as ComponentType<FollowWrapProps>
|
|
102
|
-
const next = wrapFollowNodeView(inner)
|
|
104
|
+
const next = wrapFollowNodeView(inner, useControlScroll)
|
|
103
105
|
wrapped.add(next)
|
|
104
106
|
entry.component = next
|
|
105
107
|
restores.push(() => {
|
|
@@ -154,8 +156,9 @@ class SettingsCell {
|
|
|
154
156
|
if (
|
|
155
157
|
pending === this.pending
|
|
156
158
|
&& next.enabled === this.value.enabled
|
|
159
|
+
&& next.controlScroll === this.value.controlScroll
|
|
160
|
+
&& next.motionPreference === this.value.motionPreference
|
|
157
161
|
&& next.thinkAutoExpand === this.value.thinkAutoExpand
|
|
158
|
-
&& next.autoCollapse === this.value.autoCollapse
|
|
159
162
|
&& next.debugEnabled === this.value.debugEnabled
|
|
160
163
|
&& next.debugTuning === this.value.debugTuning
|
|
161
164
|
) return
|
|
@@ -169,11 +172,6 @@ class SettingsCell {
|
|
|
169
172
|
return !this.pending && this.value.enabled
|
|
170
173
|
}
|
|
171
174
|
|
|
172
|
-
/** Whether finished turns should fold behind a summary row right now. */
|
|
173
|
-
autoCollapseActive(): boolean {
|
|
174
|
-
return !this.pending && this.value.autoCollapse
|
|
175
|
-
}
|
|
176
|
-
|
|
177
175
|
readonly getSnapshot = (): StreamSettings => this.value
|
|
178
176
|
|
|
179
177
|
readonly subscribe = (listener: () => void): () => void => {
|
|
@@ -196,25 +194,11 @@ class SettingsCell {
|
|
|
196
194
|
export function apply(ctx: ClientContext): void {
|
|
197
195
|
const config = readBootConfig()
|
|
198
196
|
const settings = new SettingsCell()
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
// flipping the preference restores every folded row immediately.
|
|
205
|
-
ctx.inject(['slots'], () => {
|
|
206
|
-
const autoCollapse = new AutoCollapseController()
|
|
207
|
-
const syncAutoCollapse = (): void => {
|
|
208
|
-
if (settings.autoCollapseActive()) autoCollapse.start()
|
|
209
|
-
else autoCollapse.stop()
|
|
210
|
-
}
|
|
211
|
-
const unsubscribe = settings.subscribe(syncAutoCollapse)
|
|
212
|
-
syncAutoCollapse()
|
|
213
|
-
return () => {
|
|
214
|
-
unsubscribe()
|
|
215
|
-
autoCollapse.stop()
|
|
216
|
-
}
|
|
217
|
-
})
|
|
197
|
+
const useControlScroll = (): boolean => useSyncExternalStore(
|
|
198
|
+
settings.subscribe,
|
|
199
|
+
() => settings.getSnapshot().controlScroll,
|
|
200
|
+
() => settings.getSnapshot().controlScroll,
|
|
201
|
+
)
|
|
218
202
|
|
|
219
203
|
// The card talks to the plugin-owned loopback RPC, so the core settings
|
|
220
204
|
// namespace allowlist cannot make it disappear. The stream still applies
|
|
@@ -286,6 +270,8 @@ export function apply(ctx: ClientContext): void {
|
|
|
286
270
|
scrollSpeedPxPerSec: config.scrollSpeedPxPerSec,
|
|
287
271
|
maxScrollSpeedPxPerSec: config.maxScrollSpeedPxPerSec,
|
|
288
272
|
thinkAutoExpand: preferences.thinkAutoExpand,
|
|
273
|
+
controlScroll: preferences.controlScroll,
|
|
274
|
+
motionPreference: preferences.motionPreference,
|
|
289
275
|
})
|
|
290
276
|
}
|
|
291
277
|
ctx.slots.inject('conversation.chat.node', () => {
|
|
@@ -298,7 +284,7 @@ export function apply(ctx: ClientContext): void {
|
|
|
298
284
|
return
|
|
299
285
|
}
|
|
300
286
|
if (releaseTakeover !== undefined) return
|
|
301
|
-
const unwrap = wrapAgentChatRows(ctx)
|
|
287
|
+
const unwrap = wrapAgentChatRows(ctx, useControlScroll)
|
|
302
288
|
const unshadow = ctx.slots.register({
|
|
303
289
|
name: 'conversation.chat.node',
|
|
304
290
|
key: 'assistant-step',
|
package/src/client/locales.ts
CHANGED
|
@@ -7,8 +7,12 @@ export const NS = 'settings.smoothStream'
|
|
|
7
7
|
export type SmoothStreamLocaleKey =
|
|
8
8
|
| 'title' | 'description'
|
|
9
9
|
| 'enabled' | 'enabledHint'
|
|
10
|
+
| 'controlScroll' | 'controlScrollHint'
|
|
11
|
+
| 'motionPreference' | 'motionPreferenceHint'
|
|
12
|
+
| 'motionAuto' | 'motionAutoHint'
|
|
13
|
+
| 'motionForceSmooth' | 'motionForceSmoothHint'
|
|
14
|
+
| 'motionForceReduced' | 'motionForceReducedHint'
|
|
10
15
|
| 'thinkAutoExpand' | 'thinkAutoExpandHint'
|
|
11
|
-
| 'autoCollapse' | 'autoCollapseHint'
|
|
12
16
|
| 'debugEnabled' | 'debugEnabledHint' | 'debugUnavailable'
|
|
13
17
|
| 'debugPanelTitle' | 'debugPanelToggle' | 'debugPanelClose' | 'debugGuide'
|
|
14
18
|
| 'debugLive' | 'debugIdle' | 'debugUnsaved'
|
|
@@ -35,10 +39,18 @@ export const en: Record<SmoothStreamLocaleKey, string> = {
|
|
|
35
39
|
description: 'How replies are revealed while they stream.',
|
|
36
40
|
enabled: 'Enable smooth streaming',
|
|
37
41
|
enabledHint: 'Let this plugin render and follow streaming replies. Turn off to use the built-in Harness renderer.',
|
|
42
|
+
controlScroll: 'Take over scrolling',
|
|
43
|
+
controlScrollHint: 'On by default; smooth-stream writes the conversation scroll position. Turn off to leave bottom-follow to Harness.',
|
|
44
|
+
motionPreference: 'Motion',
|
|
45
|
+
motionPreferenceHint: 'How streaming responds to the system reduce-motion setting.',
|
|
46
|
+
motionAuto: 'Follow system',
|
|
47
|
+
motionAutoHint: 'Reduced-motion systems get raw text (accessibility first).',
|
|
48
|
+
motionForceSmooth: 'Always smooth',
|
|
49
|
+
motionForceSmoothHint: 'Keep the smoothing engine even when the system asks for reduced motion.',
|
|
50
|
+
motionForceReduced: 'Always raw',
|
|
51
|
+
motionForceReducedHint: 'Render raw text even when the system allows motion.',
|
|
38
52
|
thinkAutoExpand: 'Auto-expand thinking',
|
|
39
53
|
thinkAutoExpandHint: 'Open the thinking block while it streams. Turn off to keep it collapsed.',
|
|
40
|
-
autoCollapse: 'Collapse finished work',
|
|
41
|
-
autoCollapseHint: 'When a reply finishes, fold its thinking, tools, and intermediate output behind one “Processed” summary so only the final answer shows. Click the summary to expand again; works with streaming on or off.',
|
|
42
54
|
debugEnabled: 'Show render diagnostics',
|
|
43
55
|
debugEnabledHint: 'Show live streaming and scroll metrics on the right side of the chat. Tune values there, then save them here.',
|
|
44
56
|
debugUnavailable: 'Live diagnostics require a newer plugin Host.',
|
|
@@ -115,10 +127,18 @@ export const zh: Record<SmoothStreamLocaleKey, string> = {
|
|
|
115
127
|
description: '回复在流式输出时如何逐字展现。',
|
|
116
128
|
enabled: '启用丝滑流式渲染',
|
|
117
129
|
enabledHint: '由本插件渲染并跟随流式回复;关闭后使用 Harness 内置渲染。',
|
|
130
|
+
controlScroll: '接管滚动',
|
|
131
|
+
controlScrollHint: '默认开启,由丝滑流式写入会话滚动位置;关闭后贴底滚动交给 Harness。',
|
|
132
|
+
motionPreference: '动效偏好',
|
|
133
|
+
motionPreferenceHint: '流式渲染如何响应系统的「减少动态效果」设置。',
|
|
134
|
+
motionAuto: '跟随系统',
|
|
135
|
+
motionAutoHint: '系统开启减少动态效果时直接呈现原始文本(优先无障碍)。',
|
|
136
|
+
motionForceSmooth: '始终平滑',
|
|
137
|
+
motionForceSmoothHint: '即使系统要求减少动态效果,仍保持平滑流式渲染。',
|
|
138
|
+
motionForceReduced: '始终原始',
|
|
139
|
+
motionForceReducedHint: '即使系统允许动效,也直接呈现原始文本。',
|
|
118
140
|
thinkAutoExpand: '自动展开思考',
|
|
119
141
|
thinkAutoExpandHint: '思考块在流式时自动展开;关闭后保持折叠,可手动展开。',
|
|
120
|
-
autoCollapse: '完成后自动折叠',
|
|
121
|
-
autoCollapseHint: '回复处理完成后,把思考、工具与过程输出折叠为一行“已处理”摘要,只展示最终回复;点击摘要可再次展开。开启或关闭流式渲染均可用,默认开启。',
|
|
122
142
|
debugEnabled: '显示渲染调试面板',
|
|
123
143
|
debugEnabledHint: '在聊天右侧显示流式渲染和滚动的实时参数,可在面板中调节并在这里保存。',
|
|
124
144
|
debugUnavailable: '当前 Host 版本不支持实时调试,请先更新插件 Host。',
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
DEFAULT_STREAM_DEBUG_TUNING,
|
|
6
6
|
DEFAULT_STREAM_SETTINGS,
|
|
7
7
|
type StreamDebugTuning,
|
|
8
|
+
type StreamMotionPreference,
|
|
8
9
|
type StreamSettings,
|
|
9
10
|
} from '../settings.ts'
|
|
10
11
|
import type {
|
|
@@ -22,8 +23,9 @@ export interface SmoothStreamCardState {
|
|
|
22
23
|
saving: boolean
|
|
23
24
|
failed: boolean
|
|
24
25
|
enabled: boolean
|
|
26
|
+
controlScroll: boolean
|
|
27
|
+
motionPreference: StreamMotionPreference
|
|
25
28
|
thinkAutoExpand: boolean
|
|
26
|
-
autoCollapse: boolean
|
|
27
29
|
debugEnabled: boolean
|
|
28
30
|
debugTuning: StreamDebugTuning
|
|
29
31
|
debugAvailable: boolean
|
|
@@ -52,7 +54,7 @@ export class SmoothStreamCardController {
|
|
|
52
54
|
private readonly store = createSnapshotStore<SmoothStreamCardState>(this.projection())
|
|
53
55
|
private loaded: StreamSettingsView | undefined
|
|
54
56
|
private loadedDebug: StreamDebugSettingsView | undefined
|
|
55
|
-
private stagedBase: Pick<StreamSettings, 'enabled' | '
|
|
57
|
+
private stagedBase: Pick<StreamSettings, 'enabled' | 'controlScroll' | 'motionPreference' | 'thinkAutoExpand'> | undefined
|
|
56
58
|
private stagedDebug: Pick<StreamSettings, 'debugEnabled' | 'debugTuning'> | undefined
|
|
57
59
|
private saving = false
|
|
58
60
|
private failed = false
|
|
@@ -90,12 +92,13 @@ export class SmoothStreamCardController {
|
|
|
90
92
|
hooks: { smoothStreamCard: this.store },
|
|
91
93
|
edit: (patch) => {
|
|
92
94
|
if (this.saving) return
|
|
93
|
-
if (patch.enabled !== undefined || patch.
|
|
95
|
+
if (patch.enabled !== undefined || patch.controlScroll !== undefined || patch.motionPreference !== undefined || patch.thinkAutoExpand !== undefined) {
|
|
94
96
|
this.stagedBase = {
|
|
95
97
|
...this.baseValues(),
|
|
96
98
|
...(patch.enabled === undefined ? {} : { enabled: patch.enabled }),
|
|
99
|
+
...(patch.controlScroll === undefined ? {} : { controlScroll: patch.controlScroll }),
|
|
100
|
+
...(patch.motionPreference === undefined ? {} : { motionPreference: patch.motionPreference }),
|
|
97
101
|
...(patch.thinkAutoExpand === undefined ? {} : { thinkAutoExpand: patch.thinkAutoExpand }),
|
|
98
|
-
...(patch.autoCollapse === undefined ? {} : { autoCollapse: patch.autoCollapse }),
|
|
99
102
|
}
|
|
100
103
|
}
|
|
101
104
|
if (this.loadedDebug !== undefined && (patch.debugEnabled !== undefined || patch.debugTuning !== undefined)) {
|
|
@@ -140,11 +143,12 @@ export class SmoothStreamCardController {
|
|
|
140
143
|
}
|
|
141
144
|
}
|
|
142
145
|
|
|
143
|
-
private baseValues(): Pick<StreamSettings, 'enabled' | '
|
|
146
|
+
private baseValues(): Pick<StreamSettings, 'enabled' | 'controlScroll' | 'motionPreference' | 'thinkAutoExpand'> {
|
|
144
147
|
return this.stagedBase ?? {
|
|
145
148
|
enabled: this.loaded?.enabled ?? DEFAULT_STREAM_SETTINGS.enabled,
|
|
149
|
+
controlScroll: this.loaded?.controlScroll ?? DEFAULT_STREAM_SETTINGS.controlScroll,
|
|
150
|
+
motionPreference: this.loaded?.motionPreference ?? DEFAULT_STREAM_SETTINGS.motionPreference,
|
|
146
151
|
thinkAutoExpand: this.loaded?.thinkAutoExpand ?? DEFAULT_STREAM_SETTINGS.thinkAutoExpand,
|
|
147
|
-
autoCollapse: this.loaded?.autoCollapse ?? DEFAULT_STREAM_SETTINGS.autoCollapse,
|
|
148
152
|
}
|
|
149
153
|
}
|
|
150
154
|
|
|
@@ -23,8 +23,9 @@ function settingsView(value: unknown): StreamSettingsView {
|
|
|
23
23
|
|| !['npm', 'development', 'unmanaged'].includes(data.installation as string)
|
|
24
24
|
|| typeof data.writable !== 'boolean'
|
|
25
25
|
|| typeof data.enabled !== 'boolean'
|
|
26
|
+
|| typeof data.controlScroll !== 'boolean'
|
|
27
|
+
|| !['auto', 'force-smooth', 'force-reduced'].includes(data.motionPreference as string)
|
|
26
28
|
|| typeof data.thinkAutoExpand !== 'boolean'
|
|
27
|
-
|| typeof data.autoCollapse !== 'boolean'
|
|
28
29
|
|| typeof data.canUpgrade !== 'boolean') {
|
|
29
30
|
throw new Error('dsh-smooth-stream: malformed settings response')
|
|
30
31
|
}
|
|
@@ -68,7 +69,7 @@ function accepted(result: Awaited<ReturnType<ConnectionHandle['rpc']['call']>>):
|
|
|
68
69
|
/** Narrow client contract consumed by the staged settings-card controller. */
|
|
69
70
|
export interface SmoothStreamSettingsApi {
|
|
70
71
|
read(): Promise<StreamSettingsView>
|
|
71
|
-
write(settings: Pick<StreamSettings, 'enabled' | '
|
|
72
|
+
write(settings: Pick<StreamSettings, 'enabled' | 'controlScroll' | 'motionPreference' | 'thinkAutoExpand'> & Partial<Pick<StreamSettings, 'debugEnabled' | 'debugTuning'>>): Promise<StreamSettingsView>
|
|
72
73
|
readDebug(): Promise<StreamDebugSettingsView>
|
|
73
74
|
writeDebug(settings: Pick<StreamSettings, 'debugEnabled' | 'debugTuning'>): Promise<StreamDebugSettingsView>
|
|
74
75
|
upgrade(): Promise<StreamUpgradeView>
|
|
@@ -80,14 +81,15 @@ export function createSmoothStreamSettingsApi(connection: ConnectionHandle): Smo
|
|
|
80
81
|
async read(): Promise<StreamSettingsView> {
|
|
81
82
|
return settingsView(accepted(await connection.rpc.call(STREAM_SETTINGS_RPC_CHANNEL, STREAM_SETTINGS_RPC.read, {})))
|
|
82
83
|
},
|
|
83
|
-
async write(settings: Pick<StreamSettings, 'enabled' | '
|
|
84
|
+
async write(settings: Pick<StreamSettings, 'enabled' | 'controlScroll' | 'motionPreference' | 'thinkAutoExpand'> & Partial<Pick<StreamSettings, 'debugEnabled' | 'debugTuning'>>): Promise<StreamSettingsView> {
|
|
84
85
|
return settingsView(accepted(await connection.rpc.call(
|
|
85
86
|
STREAM_SETTINGS_RPC_CHANNEL,
|
|
86
87
|
STREAM_SETTINGS_RPC.write,
|
|
87
88
|
{
|
|
88
89
|
enabled: settings.enabled,
|
|
90
|
+
controlScroll: settings.controlScroll,
|
|
91
|
+
motionPreference: settings.motionPreference,
|
|
89
92
|
thinkAutoExpand: settings.thinkAutoExpand,
|
|
90
|
-
autoCollapse: settings.autoCollapse,
|
|
91
93
|
...(settings.debugEnabled === undefined || settings.debugTuning === undefined
|
|
92
94
|
? {}
|
|
93
95
|
: { debugEnabled: settings.debugEnabled, debugTuning: settings.debugTuning }),
|