fix(frontend): restaure le suivi automatique du scroll des fils de messages — hook partagé useThreadScrollController — #356 (QA verte)

Cause: la logique de suivi du bas de fil était dupliquée et ad-hoc dans chaque surface (scrollRef, followsLatestRef, showLatestButton dans CustomAgentChatView), et dérivait dans certains cas — le fil ne suivait plus les nouveaux messages.

Fix: nouveau hook partagé shared/lib/useThreadScrollController (resté collé au bas quand l'utilisateur est déjà en bas, position préservée pendant la consultation de l'historique, notice latest sinon) câblé dans CustomAgentChatView, ConversationViewer et TicketAssistantPanel.

QA verte: npm run typecheck exit 0; tests ciblés useThreadScrollController, CustomAgentChatView, ConversationViewer/useConversationThread et tickets verts; npm test 1400/1400 verts (137 fichiers); git diff --check.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-09-14 11:15:10 +02:00
parent 7eb501e013
commit ec941d1af6
7 changed files with 512 additions and 144 deletions

View File

@ -6169,11 +6169,12 @@ describe("CustomAgentChatView", () => {
const scrollTo = vi.fn();
Object.defineProperty(scroll, "scrollTo", { value: scrollTo, configurable: true });
fireEvent.scroll(scroll);
fireEvent.click(screen.getByRole("button", { name: "Aller au dernier message" }));
expect(scrollTo).toHaveBeenCalledWith({ top: 1000, behavior: "smooth" });
expect(screen.queryByRole("button", { name: "Aller au dernier message" })).toBeNull();
fireEvent.click(screen.getByRole("button", { name: "Aller au Final précédent" }));
expect(scrollTo).toHaveBeenLastCalledWith({ top: 0, behavior: "smooth" });
expect(scrollTo).toHaveBeenCalledWith({ top: 0, behavior: "smooth" });
fireEvent.click(screen.getByRole("button", { name: "Aller au dernier message" }));
expect(scrollTo).toHaveBeenLastCalledWith({ top: 1000, behavior: "smooth" });
});
it("surfaces non-NOT_FOUND reattach errors instead of launching a new session", async () => {