fix(assistant): #91 maintien de l'ancre en haut pendant le streaming, libération au scroll manuel
This commit is contained in:
+19
-3
@@ -122,6 +122,9 @@ class BooksLM {
|
||||
this._menuSeq = 0;
|
||||
// Timer that hides the "done" activity indicator after a short delay.
|
||||
this._activityHideTimer = null;
|
||||
// True while the latest question should stay pinned to the top of the
|
||||
// thread (cleared as soon as the user scrolls manually).
|
||||
this._pinnedTurn = false;
|
||||
// Cache of every indexed path per vault, backing instant `@` filtering.
|
||||
this._pathCache = null;
|
||||
this._pathCacheVault = null;
|
||||
@@ -887,6 +890,14 @@ class BooksLM {
|
||||
this._activatePath(path, kind);
|
||||
});
|
||||
|
||||
// A manual scroll releases the top-pinning of the latest question.
|
||||
const messagesEl = panel.querySelector('.bookslm-messages');
|
||||
if (messagesEl) {
|
||||
const unpin = () => { this._pinnedTurn = false; };
|
||||
messagesEl.addEventListener('wheel', unpin, { passive: true });
|
||||
messagesEl.addEventListener('touchmove', unpin, { passive: true });
|
||||
}
|
||||
|
||||
// Close the session / command menus when clicking elsewhere in the panel.
|
||||
panel.addEventListener('click', (e) => {
|
||||
if (!e.target.closest('.bookslm-history-menu') && !e.target.closest('.bookslm-btn-history')) {
|
||||
@@ -1793,16 +1804,20 @@ class BooksLM {
|
||||
}
|
||||
|
||||
if (opts.anchor) this._anchorLatestUser();
|
||||
else if (this._isLoading && this._pinnedTurn) this._anchorLatestUser({ instant: true });
|
||||
else container.scrollTop = prevTop;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scroll the messages window so the most recent user post sits at the very
|
||||
* top of the viewport (its `scroll-margin-top` keeps a breathing gap),
|
||||
* reproducing Notion-AI's conversation anchoring.
|
||||
* reproducing Notion-AI's conversation anchoring. The pin stays active
|
||||
* while the answer streams, so the question never leaves the top — until
|
||||
* the user scrolls manually (see the wheel/touch listeners in `_render()`).
|
||||
*/
|
||||
_anchorLatestUser() {
|
||||
_anchorLatestUser(opts = {}) {
|
||||
if (!this._panel) return;
|
||||
this._pinnedTurn = true;
|
||||
const container = this._panel.querySelector('.bookslm-messages');
|
||||
if (!container) return;
|
||||
const users = container.querySelectorAll('.bookslm-msg.user');
|
||||
@@ -1810,9 +1825,10 @@ class BooksLM {
|
||||
// Fallback (admin notes with no user post): anchor the newest message.
|
||||
const el = users[users.length - 1] || all[all.length - 1] || container.firstElementChild;
|
||||
if (!el) return;
|
||||
const behavior = opts.instant ? 'auto' : 'smooth';
|
||||
const apply = () => {
|
||||
try {
|
||||
el.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||||
el.scrollIntoView({ behavior, block: 'start' });
|
||||
} catch {
|
||||
const cRect = container.getBoundingClientRect();
|
||||
const eRect = el.getBoundingClientRect();
|
||||
|
||||
Reference in New Issue
Block a user