diff --git a/client/src/components/Chat/Messages/MessageNav.tsx b/client/src/components/Chat/Messages/MessageNav.tsx index afb3a9aad9..99d252c5c2 100644 --- a/client/src/components/Chat/Messages/MessageNav.tsx +++ b/client/src/components/Chat/Messages/MessageNav.tsx @@ -313,6 +313,16 @@ function MessageNav({ scrollableRef }: { scrollableRef: React.RefObject { + const last = entries[entries.length - 1]; + if (last?.isEnd === true) { + return { messageEntries: entries.slice(0, -1), endEntry: last }; + } + return { messageEntries: entries, endEntry: null }; + }, [entries]); + const getCurrentVisibleId = useCallback((): string | null => { const container = scrollableRef.current; if (!container) { @@ -518,10 +528,11 @@ function MessageNav({ scrollableRef }: { scrollableRef: React.RefObject { const col = columnRef.current; - if (!col) { + const nav = navRef.current; + if (!col || !nav) { return; } - const ribs = col.querySelectorAll('[data-msg-id]'); + const ribs = nav.querySelectorAll('[data-msg-id]'); const count = ribs.length; if (count === 0) { return; @@ -715,6 +726,38 @@ function MessageNav({ scrollableRef }: { scrollableRef: React.RefObject { + const rect = el.getBoundingClientRect(); + const left = columnRef.current?.getBoundingClientRect().left ?? rect.left; + focusTooltip(MESSAGES_END_ID, rect.top + rect.height / 2, window.innerWidth - left + 8); + }, + [focusTooltip], + ); + + const handleEndPointerEnter = useCallback( + (e: React.PointerEvent) => showEndTip(e.currentTarget), + [showEndTip], + ); + + const handleEndFocus = useCallback( + (e: React.FocusEvent) => showEndTip(e.currentTarget), + [showEndTip], + ); + + const handleEndBlur = useCallback( + (e: React.FocusEvent) => { + const next = e.relatedTarget as Node | null; + if (next && e.currentTarget.contains(next)) { + return; + } + clearTooltip(); + }, + [clearTooltip], + ); + const applyMagnify = useCallback(() => { magRafRef.current = null; const col = columnRef.current; @@ -1209,9 +1252,7 @@ function MessageNav({ scrollableRef }: { scrollableRef: React.RefObject document.removeEventListener('keydown', onKeyDown); }, [focusNav]); - const hasEnd = entries.length > 0 && entries[entries.length - 1].isEnd === true; - const messageCount = hasEnd ? entries.length - 1 : entries.length; - if (messageCount < 3) { + if (messageEntries.length < 3) { return null; } @@ -1252,15 +1293,11 @@ function MessageNav({ scrollableRef }: { scrollableRef: React.RefObject - {entries.map((entry) => { - const label = entry.isEnd - ? localize('com_ui_scroll_to_bottom') - : localize( - entry.isUser - ? 'com_ui_message_nav_go_to_user' - : 'com_ui_message_nav_go_to_assistant', - { 0: entry.preview.slice(0, 30) }, - ); + {messageEntries.map((entry) => { + const label = localize( + entry.isUser ? 'com_ui_message_nav_go_to_user' : 'com_ui_message_nav_go_to_assistant', + { 0: entry.preview.slice(0, 30) }, + ); const isHighlighted = hoveredId != null ? hoveredId === entry.id : visibleIds.has(entry.id); return ( @@ -1276,6 +1313,27 @@ function MessageNav({ scrollableRef }: { scrollableRef: React.RefObject + {endEntry && ( +
+ +
+ )} +