mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-06 11:24:00 +00:00
fix(voice): follow a new chat request once the log is full
The conversation is kept to its newest 60 messages, so once full it no longer grows as a message is sent, and a reader who had scrolled up was left behind by their own request. The view now spots a send by the newest user message's id instead of the list's length.
This commit is contained in:
1 parent
51b561815c
commit
eed6162753
2 files changed
+39
-1
No files matched your search
@@ -37,9 +37,12 @@ const onListScroll = () => {
|
|||||||
const el = list.value;
|
const el = list.value;
|
||||||
if (el) stuck = el.scrollHeight - el.scrollTop - el.clientHeight < 24;
|
if (el) stuck = el.scrollHeight - el.scrollTop - el.clientHeight < 24;
|
||||||
};
|
};
|
||||||
|
// A send is a new newest user message. The log is capped, so a full one
|
||||||
|
// does not grow as it takes a message: compare ids, not lengths.
|
||||||
|
const lastSent = (list) => list?.findLast((entry) => entry.role === 'user')?.id;
|
||||||
watch(messages, (next, previous) => {
|
watch(messages, (next, previous) => {
|
||||||
const sent =
|
const sent =
|
||||||
next.length > (previous?.length ?? 0) && next.at(-1)?.role === 'user';
|
next.at(-1)?.role === 'user' && lastSent(next) !== lastSent(previous);
|
||||||
if (!stuck && !sent) return;
|
if (!stuck && !sent) return;
|
||||||
void nextTick(() => {
|
void nextTick(() => {
|
||||||
if (list.value) list.value.scrollTop = list.value.scrollHeight;
|
if (list.value) list.value.scrollTop = list.value.scrollHeight;
|
||||||
|
|||||||
@@ -319,6 +319,41 @@ test('the conversation follows new messages only while read at the bottom', asyn
|
|||||||
assert.equal(top, 800);
|
assert.equal(top, 800);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('a message sent from higher up a full, capped log is still followed', async (t) => {
|
||||||
|
manualFrames(t);
|
||||||
|
const { pinia, settle } = mountVoiceView(t);
|
||||||
|
const { ui, session, send, reply } = chat(t, { pinia });
|
||||||
|
ui.emit('chat-button');
|
||||||
|
for (let turn = 1; turn <= 30; turn++) {
|
||||||
|
await send(`Request ${turn}`);
|
||||||
|
reply(`Answer ${turn}`, { itemId: `reply-${turn}`, final: true });
|
||||||
|
session.emit({ type: 'completion', status: 'completed' });
|
||||||
|
}
|
||||||
|
await settle();
|
||||||
|
// The log keeps its newest 60 messages, so sending no longer lengthens it.
|
||||||
|
assert.equal(ui.chatMessages.length, 60);
|
||||||
|
const list = $('#gev-chat-messages');
|
||||||
|
let top = 800;
|
||||||
|
Object.defineProperties(list, {
|
||||||
|
scrollHeight: { configurable: true, get: () => 1000 },
|
||||||
|
clientHeight: { configurable: true, get: () => 200 },
|
||||||
|
scrollTop: {
|
||||||
|
configurable: true,
|
||||||
|
get: () => top,
|
||||||
|
set: (value) => {
|
||||||
|
top = Math.min(value, 800);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
top = 300;
|
||||||
|
list.dispatchEvent(new Event('scroll'));
|
||||||
|
await send('Show live flights');
|
||||||
|
await settle();
|
||||||
|
assert.equal(ui.chatMessages.length, 60);
|
||||||
|
assert.equal(ui.chatMessages.at(-1).text, 'Show live flights');
|
||||||
|
assert.equal(top, 800, 'the new request is brought into view');
|
||||||
|
});
|
||||||
|
|
||||||
test('the chat gear is named for the settings it opens', async (t) => {
|
test('the chat gear is named for the settings it opens', async (t) => {
|
||||||
const { pinia, settle } = mountVoiceView(t);
|
const { pinia, settle } = mountVoiceView(t);
|
||||||
const { ui } = chat(t, { pinia });
|
const { ui } = chat(t, { pinia });
|
||||||
|
|||||||
Reference in new issue
Block a user