@linxin666/dsh-remote-web-ui 0.1.6 → 0.1.7
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.md +14 -5
- package/lib/mobile.js +133 -9
- package/lib/mobile.js.map +1 -1
- package/lib/types/mobile/mux.d.ts +66 -2
- package/lib/types/mobile/mux.d.ts.map +1 -1
- package/lib/types/mobile/mux.js +155 -8
- package/lib/types/mobile/mux.test.d.ts +2 -0
- package/lib/types/mobile/mux.test.d.ts.map +1 -0
- package/lib/types/mobile/mux.test.js +141 -0
- package/lib/types/mobile/views/App.d.ts.map +1 -1
- package/lib/types/mobile/views/App.js +6 -0
- package/lib/types/mobile/views/ChatView.d.ts.map +1 -1
- package/lib/types/mobile/views/ChatView.js +20 -6
- package/lib/types/mobile/views/ChatView.test.js +92 -2
- package/package.json +1 -1
- package/src/mobile/mux.test.ts +172 -0
- package/src/mobile/mux.ts +170 -8
- package/src/mobile/views/App.tsx +7 -0
- package/src/mobile/views/ChatView.test.tsx +98 -3
- package/src/mobile/views/ChatView.tsx +20 -6
|
@@ -126,7 +126,6 @@ export function ChatView({ session, mux, onBack }: ChatViewProps) {
|
|
|
126
126
|
// plugin (augmentation), so the base SDK map is indexed loosely.
|
|
127
127
|
const projections = page.projections?.values as Record<string, unknown> | undefined
|
|
128
128
|
setPermissions(parsePermissionSelect(projections?.['permissions']))
|
|
129
|
-
scrollToBottom()
|
|
130
129
|
},
|
|
131
130
|
(reason: unknown) => {
|
|
132
131
|
if (cancelled) return
|
|
@@ -163,17 +162,32 @@ export function ChatView({ session, mux, onBack }: ChatViewProps) {
|
|
|
163
162
|
})
|
|
164
163
|
}, [mux, session.sessionId])
|
|
165
164
|
|
|
166
|
-
// Keep the newest content visible while streaming.
|
|
167
|
-
useEffect(() => {
|
|
168
|
-
if (messages.some(message => message.pending === true)) scrollToBottom()
|
|
169
|
-
}, [messages])
|
|
170
|
-
|
|
171
165
|
const scrollToBottom = useCallback(() => {
|
|
172
166
|
const el = scrollRef.current
|
|
173
167
|
if (el === undefined) return
|
|
174
168
|
el.scrollTop = el.scrollHeight
|
|
175
169
|
}, [])
|
|
176
170
|
|
|
171
|
+
// Track the last message's fold key so scrolling only fires when the
|
|
172
|
+
// newest message actually changes (seq bump and/or pending flip). Runs
|
|
173
|
+
// after React has committed the render, so scrollHeight reflects the
|
|
174
|
+
// freshly appended content.
|
|
175
|
+
const lastMessageKeyRef = useRef<string | undefined>(undefined)
|
|
176
|
+
|
|
177
|
+
// Keep the newest content visible. This covers the initial tail page (the
|
|
178
|
+
// effect runs after commit, fixing the stale scrollHeight from the old
|
|
179
|
+
// open-time scrollToBottom), live streaming chunks on the pending message,
|
|
180
|
+
// and finalized/appended messages. Prepending older pages via loadOlder
|
|
181
|
+
// leaves the last message untouched, so it never disturbs the scroll position.
|
|
182
|
+
useEffect(() => {
|
|
183
|
+
const last = messages[messages.length - 1]
|
|
184
|
+
if (last === undefined) return
|
|
185
|
+
const key = last.seq + ':' + (last.pending === true ? 'p' : 'f')
|
|
186
|
+
if (key === lastMessageKeyRef.current) return
|
|
187
|
+
lastMessageKeyRef.current = key
|
|
188
|
+
scrollToBottom()
|
|
189
|
+
}, [messages, scrollToBottom])
|
|
190
|
+
|
|
177
191
|
/** Load one older page and prepend it. The fold is directional (incremental
|
|
178
192
|
* tails only), so the older page folds standalone and concatenates ahead —
|
|
179
193
|
* host page boundaries never cut a message, so the seam is exact. */
|