summaryrefslogtreecommitdiff
path: root/packages/cli/src/ui/hooks/useLoadingIndicator.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/cli/src/ui/hooks/useLoadingIndicator.ts')
-rw-r--r--packages/cli/src/ui/hooks/useLoadingIndicator.ts124
1 files changed, 40 insertions, 84 deletions
diff --git a/packages/cli/src/ui/hooks/useLoadingIndicator.ts b/packages/cli/src/ui/hooks/useLoadingIndicator.ts
index ac75986a..46754ac1 100644
--- a/packages/cli/src/ui/hooks/useLoadingIndicator.ts
+++ b/packages/cli/src/ui/hooks/useLoadingIndicator.ts
@@ -4,98 +4,54 @@
* SPDX-License-Identifier: Apache-2.0
*/
-import { useState, useEffect, useRef } from 'react';
-import {
- WITTY_LOADING_PHRASES,
- PHRASE_CHANGE_INTERVAL_MS,
-} from '../constants.js';
import { StreamingState } from '../types.js';
+import { useTimer } from './useTimer.js';
+import { usePhraseCycler } from './usePhraseCycler.js';
+import { useState, useEffect, useRef } from 'react'; // Added useRef
-export const useLoadingIndicator = (
- streamingState: StreamingState,
- isPaused: boolean,
-) => {
- const [elapsedTime, setElapsedTime] = useState(0);
- const [currentLoadingPhrase, setCurrentLoadingPhrase] = useState(
- WITTY_LOADING_PHRASES[0],
- );
- const timerRef = useRef<NodeJS.Timeout | null>(null);
- const phraseIntervalRef = useRef<NodeJS.Timeout | null>(null);
- const currentPhraseIndexRef = useRef<number>(0);
+export const useLoadingIndicator = (streamingState: StreamingState) => {
+ const [timerResetKey, setTimerResetKey] = useState(0);
+ const isTimerActive = streamingState === StreamingState.Responding;
- const [shouldShowSpinner, setShouldShowSpinner] = useState(true);
+ const elapsedTimeFromTimer = useTimer(isTimerActive, timerResetKey);
- useEffect(() => {
- if (streamingState === StreamingState.Responding) {
- if (!isPaused) {
- if (!timerRef.current) {
- // No specific action needed here if timer wasn't running and we are not paused.
- // Elapsed time continues from where it left off or starts from 0 if it's a fresh start.
- }
- if (timerRef.current) clearInterval(timerRef.current);
- timerRef.current = setInterval(() => {
- setElapsedTime((prevTime) => prevTime + 1);
- }, 1000);
- } else {
- if (timerRef.current) {
- clearInterval(timerRef.current);
- timerRef.current = null;
- }
- }
- } else {
- if (timerRef.current) {
- clearInterval(timerRef.current);
- timerRef.current = null;
- }
- setElapsedTime(0);
- }
+ const isPhraseCyclingActive = streamingState === StreamingState.Responding;
+ const isWaiting = streamingState === StreamingState.WaitingForConfirmation;
+ const currentLoadingPhrase = usePhraseCycler(
+ isPhraseCyclingActive,
+ isWaiting,
+ );
- return () => {
- if (timerRef.current) {
- clearInterval(timerRef.current);
- timerRef.current = null;
- }
- };
- }, [streamingState, isPaused]);
+ const [retainedElapsedTime, setRetainedElapsedTime] = useState(0);
+ const prevStreamingStateRef = useRef<StreamingState | null>(null);
useEffect(() => {
- if (streamingState === StreamingState.Responding) {
- if (!isPaused) {
- setShouldShowSpinner(true);
- if (!phraseIntervalRef.current) {
- currentPhraseIndexRef.current = 0;
- setCurrentLoadingPhrase(WITTY_LOADING_PHRASES[0]);
- phraseIntervalRef.current = setInterval(() => {
- currentPhraseIndexRef.current =
- (currentPhraseIndexRef.current + 1) %
- WITTY_LOADING_PHRASES.length;
- setCurrentLoadingPhrase(
- WITTY_LOADING_PHRASES[currentPhraseIndexRef.current],
- );
- }, PHRASE_CHANGE_INTERVAL_MS);
- }
- } else {
- setShouldShowSpinner(false);
- setCurrentLoadingPhrase('Waiting for user confirmation...');
- if (phraseIntervalRef.current) {
- clearInterval(phraseIntervalRef.current);
- phraseIntervalRef.current = null;
- }
- }
- } else {
- if (phraseIntervalRef.current) {
- clearInterval(phraseIntervalRef.current);
- phraseIntervalRef.current = null;
- }
+ if (
+ prevStreamingStateRef.current === StreamingState.WaitingForConfirmation &&
+ streamingState === StreamingState.Responding
+ ) {
+ setTimerResetKey((prevKey) => prevKey + 1);
+ setRetainedElapsedTime(0); // Clear retained time when going back to responding
+ } else if (
+ streamingState === StreamingState.Idle &&
+ prevStreamingStateRef.current === StreamingState.Responding
+ ) {
+ setTimerResetKey((prevKey) => prevKey + 1); // Reset timer when becoming idle from responding
+ setRetainedElapsedTime(0);
+ } else if (streamingState === StreamingState.WaitingForConfirmation) {
+ // Capture the time when entering WaitingForConfirmation
+ // elapsedTimeFromTimer will hold the last value from when isTimerActive was true.
+ setRetainedElapsedTime(elapsedTimeFromTimer);
}
- return () => {
- if (phraseIntervalRef.current) {
- clearInterval(phraseIntervalRef.current);
- phraseIntervalRef.current = null;
- }
- };
- }, [streamingState, isPaused]);
+ prevStreamingStateRef.current = streamingState;
+ }, [streamingState, elapsedTimeFromTimer]);
- return { elapsedTime, currentLoadingPhrase, shouldShowSpinner };
+ return {
+ elapsedTime:
+ streamingState === StreamingState.WaitingForConfirmation
+ ? retainedElapsedTime
+ : elapsedTimeFromTimer,
+ currentLoadingPhrase,
+ };
};