## CHANGES

- Dramatically reduced re-renders by memoizing tons of UI callbacks 🚀
- Input blur now syncs session text via refs, not dependencies 🧠
- File preview history navigation now uses stable, memoized back/forward arrays 🧭
- Thinking status now receives pre-filtered “busy AI” sessions only 🔥
- MainPanel no longer rerenders on keystrokes from inline prop functions 
- New log deletion handler cleanly removes user blocks and updates histories 🗑️
- AI log deletion also prunes persisted Claude JSONL context asynchronously 📜
- Tab actions (rename, reorder, star, unread) now run through memoized handlers 🧩
- “Last Document Graph” opens reliably using ref-backed remembered file path 🕸️
- Replay message now stages images then triggers input processing via ref 🎬
This commit is contained in:
Pedram Amini
2026-01-18 10:12:52 -06:00
parent 302cd59c5d
commit a699332797
3 changed files with 696 additions and 624 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -70,8 +70,9 @@ interface InputAreaProps {
atMentionSuggestions?: Array<{ value: string; type: 'file' | 'folder'; displayText: string; fullPath: string; source?: 'project' | 'autorun' }>;
selectedAtMentionIndex?: number;
setSelectedAtMentionIndex?: (index: number) => void;
// ThinkingStatusPill props - sessions is used to compute thinkingSessions
sessions?: Session[];
// ThinkingStatusPill props - PERF: receive pre-filtered thinkingSessions instead of full sessions
// This prevents re-renders when unrelated session updates occur (e.g., terminal output)
thinkingSessions?: Session[];
namedSessions?: Record<string, string>;
onSessionClick?: (sessionId: string, tabId?: string) => void;
autoRunState?: BatchRunState;
@@ -141,7 +142,7 @@ export const InputArea = React.memo(function InputArea(props: InputAreaProps) {
atMentionStartIndex = -1, setAtMentionStartIndex,
atMentionSuggestions = [], selectedAtMentionIndex = 0,
setSelectedAtMentionIndex,
sessions = [], namedSessions, onSessionClick, autoRunState, onStopAutoRun,
thinkingSessions = [], namedSessions, onSessionClick, autoRunState, onStopAutoRun,
onOpenQueueBrowser,
tabReadOnlyMode = false, onToggleTabReadOnlyMode,
tabSaveToHistory = false, onToggleTabSaveToHistory,
@@ -219,11 +220,7 @@ export const InputArea = React.memo(function InputArea(props: InputAreaProps) {
// Filter slash commands based on input and current mode
const isTerminalMode = session.inputMode === 'terminal';
// PERF: Precompute thinkingSessions to avoid O(n) filter in ThinkingStatusPill on every keystroke
const thinkingSessions = useMemo(
() => sessions.filter(s => s.state === 'busy' && s.busySource === 'ai'),
[sessions]
);
// thinkingSessions is now passed directly from App.tsx (pre-filtered) for better performance
// Get the appropriate command history based on current mode
// Fall back to legacy commandHistory for sessions created before the split

View File

@@ -37,7 +37,9 @@ interface MainPanelProps {
agentSessionsOpen: boolean;
activeAgentSessionId: string | null;
activeSession: Session | null;
sessions: Session[]; // All sessions for InputArea's ThinkingStatusPill
// PERF: Receive pre-filtered thinkingSessions instead of full sessions array.
// This prevents cascade re-renders when unrelated session updates occur.
thinkingSessions: Session[];
theme: Theme;
fontFamily: string;
isMobileLandscape?: boolean;
@@ -265,7 +267,7 @@ interface MainPanelProps {
// due to input value changes. The component will only re-render when its props actually change.
export const MainPanel = React.memo(forwardRef<MainPanelHandle, MainPanelProps>(function MainPanel(props, ref) {
const {
logViewerOpen, agentSessionsOpen, activeAgentSessionId, activeSession, sessions, theme, activeFocus, outputSearchOpen, outputSearchQuery,
logViewerOpen, agentSessionsOpen, activeAgentSessionId, activeSession, thinkingSessions, theme, activeFocus, outputSearchOpen, outputSearchQuery,
inputValue, enterToSendAI, enterToSendTerminal, stagedImages, commandHistoryOpen, commandHistoryFilter,
commandHistorySelectedIndex, slashCommandOpen, slashCommands, selectedSlashCommandIndex,
tabCompletionOpen, tabCompletionSuggestions, selectedTabCompletionIndex, tabCompletionFilter,
@@ -1289,7 +1291,7 @@ export const MainPanel = React.memo(forwardRef<MainPanelHandle, MainPanelProps>(
onInputFocus={handleInputFocus}
onInputBlur={props.onInputBlur}
isAutoModeActive={isCurrentSessionAutoMode}
sessions={sessions}
thinkingSessions={thinkingSessions}
onSessionClick={handleSessionClick}
autoRunState={currentSessionBatchState || undefined}
onStopAutoRun={onStopBatchRun}