Fix Static duplication and input prompt tearing (#1279)

This commit is contained in:
Sandy Tao 2025-06-21 11:11:42 -07:00 committed by GitHub
parent f9b2a33732
commit 03af6235a9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 27 additions and 1 deletions

View File

@ -12,6 +12,7 @@ import {
Static, Static,
Text, Text,
useStdin, useStdin,
useStdout,
useInput, useInput,
type Key as InkKeyType, type Key as InkKeyType,
} from 'ink'; } from 'ink';
@ -66,6 +67,7 @@ import { useTextBuffer } from './components/shared/text-buffer.js';
import * as fs from 'fs'; import * as fs from 'fs';
import { UpdateNotification } from './components/UpdateNotification.js'; import { UpdateNotification } from './components/UpdateNotification.js';
import { checkForUpdates } from './utils/updateCheck.js'; import { checkForUpdates } from './utils/updateCheck.js';
import ansiEscapes from 'ansi-escapes';
const CTRL_EXIT_PROMPT_DURATION_MS = 1000; const CTRL_EXIT_PROMPT_DURATION_MS = 1000;
@ -83,6 +85,7 @@ export const AppWrapper = (props: AppProps) => (
const App = ({ config, settings, startupWarnings = [] }: AppProps) => { const App = ({ config, settings, startupWarnings = [] }: AppProps) => {
const [updateMessage, setUpdateMessage] = useState<string | null>(null); const [updateMessage, setUpdateMessage] = useState<string | null>(null);
const { stdout } = useStdout();
useEffect(() => { useEffect(() => {
checkForUpdates().then(setUpdateMessage); checkForUpdates().then(setUpdateMessage);
@ -98,8 +101,9 @@ const App = ({ config, settings, startupWarnings = [] }: AppProps) => {
const [staticNeedsRefresh, setStaticNeedsRefresh] = useState(false); const [staticNeedsRefresh, setStaticNeedsRefresh] = useState(false);
const [staticKey, setStaticKey] = useState(0); const [staticKey, setStaticKey] = useState(0);
const refreshStatic = useCallback(() => { const refreshStatic = useCallback(() => {
stdout.write(ansiEscapes.clearTerminal);
setStaticKey((prev) => prev + 1); setStaticKey((prev) => prev + 1);
}, [setStaticKey]); }, [setStaticKey, stdout]);
const [geminiMdFileCount, setGeminiMdFileCount] = useState<number>(0); const [geminiMdFileCount, setGeminiMdFileCount] = useState<number>(0);
const [debugMessage, setDebugMessage] = useState<string>(''); const [debugMessage, setDebugMessage] = useState<string>('');
@ -231,6 +235,8 @@ const App = ({ config, settings, startupWarnings = [] }: AppProps) => {
const pendingHistoryItems = [...pendingSlashCommandHistoryItems]; const pendingHistoryItems = [...pendingSlashCommandHistoryItems];
const { rows: terminalHeight, columns: terminalWidth } = useTerminalSize(); const { rows: terminalHeight, columns: terminalWidth } = useTerminalSize();
const lastTerminalWidth = useRef(terminalWidth);
const isInitialMount = useRef(true);
const { stdin, setRawMode } = useStdin(); const { stdin, setRawMode } = useStdin();
const isValidPath = useCallback((filePath: string): boolean => { const isValidPath = useCallback((filePath: string): boolean => {
try { try {
@ -433,6 +439,26 @@ const App = ({ config, settings, startupWarnings = [] }: AppProps) => {
[terminalHeight, footerHeight], [terminalHeight, footerHeight],
); );
useEffect(() => {
// skip refreshing Static during first mount
if (isInitialMount.current) {
isInitialMount.current = false;
return;
}
// debounce so it doesn't fire up too often during resize
const handler = setTimeout(() => {
if (terminalWidth < lastTerminalWidth.current) {
setStaticNeedsRefresh(true);
}
lastTerminalWidth.current = terminalWidth;
}, 300);
return () => {
clearTimeout(handler);
};
}, [terminalWidth]);
useEffect(() => { useEffect(() => {
if (!pendingHistoryItems.length) { if (!pendingHistoryItems.length) {
return; return;