mirror of
https://github.com/zhayujie/chatgpt-on-wechat.git
synced 2026-06-02 00:57:41 +08:00
fix(web): smart auto-scroll for chat #2775
This commit is contained in:
@@ -191,8 +191,8 @@ class AgentStreamExecutor:
|
|||||||
# Log user message with model info
|
# Log user message with model info
|
||||||
|
|
||||||
thinking_enabled = self._is_thinking_enabled()
|
thinking_enabled = self._is_thinking_enabled()
|
||||||
thinking_label = "💭 thinking" if thinking_enabled else "⚡ fast"
|
thinking_label = " | 💭 thinking" if thinking_enabled else ""
|
||||||
logger.info(f"🤖 {self.model.model} | {thinking_label} | 👤 {user_message}")
|
logger.info(f"🤖 {self.model.model}{thinking_label} | 👤 {user_message}")
|
||||||
|
|
||||||
# Add user message (Claude format - use content blocks for consistency)
|
# Add user message (Claude format - use content blocks for consistency)
|
||||||
self.messages.append({
|
self.messages.append({
|
||||||
|
|||||||
@@ -288,7 +288,7 @@
|
|||||||
<!-- ====================================================== -->
|
<!-- ====================================================== -->
|
||||||
<!-- VIEW: Chat -->
|
<!-- VIEW: Chat -->
|
||||||
<!-- ====================================================== -->
|
<!-- ====================================================== -->
|
||||||
<div id="view-chat" class="view active">
|
<div id="view-chat" class="view active relative">
|
||||||
<!-- Messages -->
|
<!-- Messages -->
|
||||||
<div id="chat-messages" class="flex-1 overflow-y-auto">
|
<div id="chat-messages" class="flex-1 overflow-y-auto">
|
||||||
<!-- Welcome Screen -->
|
<!-- Welcome Screen -->
|
||||||
@@ -364,6 +364,18 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Scroll-to-bottom FAB -->
|
||||||
|
<button id="scroll-to-bottom-btn"
|
||||||
|
class="hidden absolute right-5 bottom-[80px] z-10
|
||||||
|
w-9 h-9 rounded-full shadow-lg
|
||||||
|
bg-white dark:bg-[#2A2A2A] border border-slate-200 dark:border-white/15
|
||||||
|
text-slate-500 dark:text-slate-400 hover:text-primary-500 dark:hover:text-primary-400
|
||||||
|
flex items-center justify-center cursor-pointer transition-all duration-200
|
||||||
|
hover:shadow-xl hover:scale-105"
|
||||||
|
onclick="_autoScrollEnabled = true; scrollChatToBottom(true);">
|
||||||
|
<i class="fas fa-chevron-down text-sm"></i>
|
||||||
|
</button>
|
||||||
|
|
||||||
<!-- Chat Input -->
|
<!-- Chat Input -->
|
||||||
<div class="flex-shrink-0 border-t border-slate-200 dark:border-white/10 bg-white dark:bg-[#1A1A1A] px-4 py-3">
|
<div class="flex-shrink-0 border-t border-slate-200 dark:border-white/10 bg-white dark:bg-[#1A1A1A] px-4 py-3">
|
||||||
<div class="max-w-3xl mx-auto">
|
<div class="max-w-3xl mx-auto">
|
||||||
|
|||||||
@@ -462,6 +462,16 @@ const sendBtn = document.getElementById('send-btn');
|
|||||||
const messagesDiv = document.getElementById('chat-messages');
|
const messagesDiv = document.getElementById('chat-messages');
|
||||||
const fileInput = document.getElementById('file-input');
|
const fileInput = document.getElementById('file-input');
|
||||||
|
|
||||||
|
// Smart auto-scroll: pause when user scrolls up, resume when near bottom
|
||||||
|
let _autoScrollEnabled = true;
|
||||||
|
const _SCROLL_THRESHOLD = 80; // px from bottom to re-enable auto-scroll
|
||||||
|
|
||||||
|
messagesDiv.addEventListener('scroll', () => {
|
||||||
|
const distFromBottom = messagesDiv.scrollHeight - messagesDiv.scrollTop - messagesDiv.clientHeight;
|
||||||
|
_autoScrollEnabled = distFromBottom <= _SCROLL_THRESHOLD;
|
||||||
|
_updateScrollToBottomBtn();
|
||||||
|
});
|
||||||
|
|
||||||
// Intercept internal navigation links in chat messages
|
// Intercept internal navigation links in chat messages
|
||||||
messagesDiv.addEventListener('click', (e) => {
|
messagesDiv.addEventListener('click', (e) => {
|
||||||
const copyBtn = e.target.closest('.copy-msg-btn');
|
const copyBtn = e.target.closest('.copy-msg-btn');
|
||||||
@@ -1438,7 +1448,8 @@ function createBotMessageEl(content, timestamp, requestId, msg) {
|
|||||||
function addUserMessage(content, timestamp, attachments) {
|
function addUserMessage(content, timestamp, attachments) {
|
||||||
const el = createUserMessageEl(content, timestamp, attachments);
|
const el = createUserMessageEl(content, timestamp, attachments);
|
||||||
messagesDiv.appendChild(el);
|
messagesDiv.appendChild(el);
|
||||||
scrollChatToBottom();
|
_autoScrollEnabled = true;
|
||||||
|
scrollChatToBottom(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function addBotMessage(content, timestamp, requestId) {
|
function addBotMessage(content, timestamp, requestId) {
|
||||||
@@ -1531,7 +1542,7 @@ function loadHistory(page) {
|
|||||||
if (isFirstLoad) {
|
if (isFirstLoad) {
|
||||||
// Use requestAnimationFrame to ensure the DOM has fully rendered
|
// Use requestAnimationFrame to ensure the DOM has fully rendered
|
||||||
// before scrolling, otherwise scrollHeight may not reflect new content.
|
// before scrolling, otherwise scrollHeight may not reflect new content.
|
||||||
requestAnimationFrame(() => scrollChatToBottom());
|
requestAnimationFrame(() => scrollChatToBottom(true));
|
||||||
} else {
|
} else {
|
||||||
// Restore scroll position so loading older messages doesn't jump the view
|
// Restore scroll position so loading older messages doesn't jump the view
|
||||||
messagesDiv.scrollTop = messagesDiv.scrollHeight - prevScrollHeight;
|
messagesDiv.scrollTop = messagesDiv.scrollHeight - prevScrollHeight;
|
||||||
@@ -2049,8 +2060,17 @@ function formatToolArgs(args) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function scrollChatToBottom() {
|
function scrollChatToBottom(force) {
|
||||||
messagesDiv.scrollTop = messagesDiv.scrollHeight;
|
if (force || _autoScrollEnabled) {
|
||||||
|
messagesDiv.scrollTop = messagesDiv.scrollHeight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function _updateScrollToBottomBtn() {
|
||||||
|
const btn = document.getElementById('scroll-to-bottom-btn');
|
||||||
|
if (!btn) return;
|
||||||
|
const distFromBottom = messagesDiv.scrollHeight - messagesDiv.scrollTop - messagesDiv.clientHeight;
|
||||||
|
btn.classList.toggle('hidden', distFromBottom <= _SCROLL_THRESHOLD);
|
||||||
}
|
}
|
||||||
|
|
||||||
function applyHighlighting(container) {
|
function applyHighlighting(container) {
|
||||||
|
|||||||
Reference in New Issue
Block a user