* chore: remove dead/unreferenced files across ui, vscode Remove 59 unused source files (components, hooks, lib utils, stores, barrels, and orphaned vscode github modules) that are not imported by any entry-reachable code. Also drop a stale test mock for the removed execCommands module. Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com> * refactor: remove unused exported symbols (types, functions, consts, hooks) Remove exported symbols whose identifier is referenced nowhere in the repository (verified via repo-wide search), across ui types/contracts, lib utilities, sync layer, stores, and components. Also drop the few imports/private helpers orphaned by these removals. Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com> * refactor: remove more unused exports (desktop, shortcuts, worktree, vscode) Continue removing repo-wide unreferenced exported functions, consts and types across lib/desktop, shortcuts, worktreeSessionCreator, sync, and vscode gitService, with cascading orphaned helpers/imports cleaned up. Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com> * chore: add dead-code cleanup tooling * refactor: checkpoint dead-code cleanup * refactor: remove dead-code suppressions --------- Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com> Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
112 lines
3.0 KiB
TypeScript
112 lines
3.0 KiB
TypeScript
import React from 'react';
|
|
|
|
interface UseStreamingTextThrottleInput {
|
|
text: string;
|
|
isStreaming: boolean;
|
|
throttleMs?: number;
|
|
identityKey?: string;
|
|
}
|
|
|
|
const DEFAULT_STREAMING_TEXT_THROTTLE_MS = 100;
|
|
|
|
const computeStreamingThrottleDelay = (lastEmitAt: number, now: number, throttleMs: number): number => {
|
|
const elapsed = now - lastEmitAt;
|
|
return Math.max(0, throttleMs - elapsed);
|
|
};
|
|
|
|
interface StreamingThrottleState {
|
|
timer: ReturnType<typeof setTimeout> | null;
|
|
pendingText: string;
|
|
lastEmitAt: number;
|
|
}
|
|
|
|
const clearTimer = (state: StreamingThrottleState): void => {
|
|
if (!state.timer) {
|
|
return;
|
|
}
|
|
clearTimeout(state.timer);
|
|
state.timer = null;
|
|
};
|
|
|
|
export const useStreamingTextThrottle = ({
|
|
text,
|
|
isStreaming,
|
|
throttleMs = DEFAULT_STREAMING_TEXT_THROTTLE_MS,
|
|
identityKey,
|
|
}: UseStreamingTextThrottleInput): string => {
|
|
const [throttledText, setThrottledText] = React.useState(text);
|
|
const latestTextRef = React.useRef(text);
|
|
const throttledTextRef = React.useRef(throttledText);
|
|
|
|
const stateRef = React.useRef<StreamingThrottleState>({
|
|
timer: null,
|
|
pendingText: text,
|
|
lastEmitAt: 0,
|
|
});
|
|
|
|
React.useEffect(() => {
|
|
latestTextRef.current = text;
|
|
}, [text]);
|
|
|
|
React.useEffect(() => {
|
|
throttledTextRef.current = throttledText;
|
|
}, [throttledText]);
|
|
|
|
React.useEffect(() => {
|
|
const state = stateRef.current;
|
|
clearTimer(state);
|
|
state.pendingText = latestTextRef.current;
|
|
state.lastEmitAt = 0;
|
|
setThrottledText(latestTextRef.current);
|
|
}, [identityKey]);
|
|
|
|
React.useEffect(() => {
|
|
const state = stateRef.current;
|
|
state.pendingText = text;
|
|
const currentThrottled = throttledTextRef.current;
|
|
const stableText = isStreaming && currentThrottled.length > text.length ? currentThrottled : text;
|
|
|
|
if (!isStreaming) {
|
|
clearTimer(state);
|
|
state.lastEmitAt = Date.now();
|
|
setThrottledText(stableText);
|
|
return;
|
|
}
|
|
|
|
const now = Date.now();
|
|
const remaining = computeStreamingThrottleDelay(state.lastEmitAt, now, throttleMs);
|
|
|
|
if (remaining <= 0) {
|
|
clearTimer(state);
|
|
state.lastEmitAt = now;
|
|
setThrottledText(stableText);
|
|
return;
|
|
}
|
|
|
|
clearTimer(state);
|
|
state.timer = setTimeout(() => {
|
|
state.timer = null;
|
|
state.lastEmitAt = Date.now();
|
|
setThrottledText((prev) => {
|
|
if (isStreaming && prev.length > state.pendingText.length) {
|
|
return prev;
|
|
}
|
|
return state.pendingText;
|
|
});
|
|
}, remaining);
|
|
|
|
return () => {
|
|
clearTimer(state);
|
|
};
|
|
}, [isStreaming, text, throttleMs]);
|
|
|
|
React.useEffect(() => {
|
|
const state = stateRef.current;
|
|
return () => {
|
|
clearTimer(state);
|
|
};
|
|
}, []);
|
|
|
|
return throttledText;
|
|
};
|