Fix UI freeze: Remove high-frequency logging and throttle scroll effects

Performance optimizations to prevent UI freeze during streaming:

1. message-block-list.tsx:
   - Removed createEffect that logged on every messageIds change
   - Removed unused logger import (was causing IPC overload)

2. multi-task-chat.tsx:
   - Changed filteredMessageIds from function to createMemo for proper memoization
   - Throttled auto-scroll effect to only trigger when message COUNT changes
   - Previously it fired on every reactive store update during streaming

These changes prevent excessive re-renders and IPC calls during message streaming.
This commit is contained in:
Gemini AI
2025-12-24 22:27:27 +04:00
Unverified
parent 743d0367e2
commit 961c8743d3
2 changed files with 16 additions and 17 deletions

View File

@@ -107,7 +107,7 @@ export default function MultiTaskChat(props: MultiTaskChatProps) {
};
// Filter messages based on selected task - use store's session messages for the task session
const filteredMessageIds = () => {
const filteredMessageIds = createMemo(() => {
const task = selectedTask();
if (!task) return []; // Show no messages in Pipeline view
@@ -119,7 +119,7 @@ export default function MultiTaskChat(props: MultiTaskChatProps) {
// Fallback to task.messageIds for backward compatibility
return task.messageIds || [];
};
});
// Note: Auto-scroll is handled in two places:
// 1. After sending a message (in handleSendMessage)
@@ -229,13 +229,23 @@ export default function MultiTaskChat(props: MultiTaskChatProps) {
return () => clearInterval(interval);
});
// Auto-scroll when new messages arrive
// Auto-scroll when new messages arrive (throttled to count changes only)
let lastScrolledCount = 0;
createEffect(() => {
const ids = filteredMessageIds();
const count = ids.length;
const thinking = isAgentThinking();
// Scroll when message count changes or when thinking starts (unless user is scrolling)
if ((ids.length > 0 || thinking) && !userScrolling()) {
// Only scroll when message COUNT changes, not on every store update
// This prevents the effect from firing on every streaming chunk
if (count !== lastScrolledCount && count > 0 && !userScrolling()) {
lastScrolledCount = count;
requestAnimationFrame(() => {
setTimeout(scrollToBottom, 50);
});
}
// Also scroll when thinking first starts
if (thinking && count > 0 && !userScrolling()) {
requestAnimationFrame(() => {
setTimeout(scrollToBottom, 50);
});

View File

@@ -1,10 +1,7 @@
import { Index, type Accessor, createEffect } from "solid-js"
import { Index, type Accessor } from "solid-js"
import VirtualItem from "./virtual-item"
import MessageBlock from "./message-block"
import type { InstanceMessageStore } from "../stores/message-v2/instance-store"
import { getLogger } from "../lib/logger"
const log = getLogger("multix-chat")
export function getMessageAnchorId(messageId: string) {
return `message-anchor-${messageId}`
@@ -31,14 +28,6 @@ interface MessageBlockListProps {
}
export default function MessageBlockList(props: MessageBlockListProps) {
createEffect(() => {
const ids = props.messageIds();
log.info("[MessageBlockList] messageIds changed", {
count: ids.length,
ids: ids.slice(-3) // Log last 3 for context
});
});
return (
<>
<Index each={props.messageIds()}>