mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-20 02:00:40 -07:00
feat(cli): implement customizable witty phrase positioning
- Add ui.wittyPhrasePosition setting (status, inline, ambient) - Refactor usePhraseCycler to return tips and wit separately - Implement 'inline' position: append witty phrases in gray after status - Update status length estimation to account for inline wit - Replace pause icon with up arrow (↑) for awaiting approval - Remove 'Tip:' prefix from loading phrases - Update unit tests and research report
This commit is contained in:
@@ -42,7 +42,7 @@ export const useLoadingIndicator = ({
|
||||
|
||||
const isPhraseCyclingActive = streamingState === StreamingState.Responding;
|
||||
const isWaiting = streamingState === StreamingState.WaitingForConfirmation;
|
||||
const currentLoadingPhrase = usePhraseCycler(
|
||||
const { currentTip, currentWittyPhrase } = usePhraseCycler(
|
||||
isPhraseCyclingActive,
|
||||
isWaiting,
|
||||
shouldShowFocusHint,
|
||||
@@ -89,6 +89,8 @@ export const useLoadingIndicator = ({
|
||||
streamingState === StreamingState.WaitingForConfirmation
|
||||
? retainedElapsedTime
|
||||
: elapsedTimeFromTimer,
|
||||
currentLoadingPhrase: retryPhrase || currentLoadingPhrase,
|
||||
currentLoadingPhrase: retryPhrase || currentTip || currentWittyPhrase,
|
||||
currentTip,
|
||||
currentWittyPhrase,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -30,14 +30,14 @@ const TestComponent = ({
|
||||
loadingPhrasesMode?: LoadingPhrasesMode;
|
||||
customPhrases?: string[];
|
||||
}) => {
|
||||
const phrase = usePhraseCycler(
|
||||
const { currentTip, currentWittyPhrase } = usePhraseCycler(
|
||||
isActive,
|
||||
isWaiting,
|
||||
isInteractiveShellWaiting,
|
||||
loadingPhrasesMode,
|
||||
customPhrases,
|
||||
);
|
||||
return <Text>{phrase}</Text>;
|
||||
return <Text>{currentTip || currentWittyPhrase}</Text>;
|
||||
};
|
||||
|
||||
describe('usePhraseCycler', () => {
|
||||
|
||||
@@ -31,7 +31,8 @@ export const usePhraseCycler = (
|
||||
customPhrases?: string[],
|
||||
maxLength?: number,
|
||||
) => {
|
||||
const [currentLoadingPhrase, setCurrentLoadingPhrase] = useState<
|
||||
const [currentTip, setCurrentTip] = useState<string | undefined>(undefined);
|
||||
const [currentWittyPhrase, setCurrentWittyPhrase] = useState<
|
||||
string | undefined
|
||||
>(undefined);
|
||||
|
||||
@@ -46,17 +47,20 @@ export const usePhraseCycler = (
|
||||
}
|
||||
|
||||
if (shouldShowFocusHint) {
|
||||
setCurrentLoadingPhrase(INTERACTIVE_SHELL_WAITING_PHRASE);
|
||||
setCurrentTip(INTERACTIVE_SHELL_WAITING_PHRASE);
|
||||
setCurrentWittyPhrase(undefined);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isWaiting) {
|
||||
setCurrentLoadingPhrase('Waiting for user confirmation...');
|
||||
setCurrentTip('Waiting for user confirmation...');
|
||||
setCurrentWittyPhrase(undefined);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isActive || loadingPhrasesMode === 'off') {
|
||||
setCurrentLoadingPhrase(undefined);
|
||||
setCurrentTip(undefined);
|
||||
setCurrentWittyPhrase(undefined);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -66,7 +70,6 @@ export const usePhraseCycler = (
|
||||
: WITTY_LOADING_PHRASES;
|
||||
|
||||
const setRandomPhrase = () => {
|
||||
let phraseList: readonly string[];
|
||||
let currentMode = loadingPhrasesMode;
|
||||
|
||||
// In 'all' mode, we decide once per phrase cycle what to show
|
||||
@@ -79,23 +82,12 @@ export const usePhraseCycler = (
|
||||
}
|
||||
}
|
||||
|
||||
switch (currentMode) {
|
||||
case 'tips':
|
||||
phraseList = INFORMATIVE_TIPS;
|
||||
break;
|
||||
case 'witty':
|
||||
phraseList = wittyPhrases;
|
||||
break;
|
||||
default:
|
||||
phraseList = INFORMATIVE_TIPS;
|
||||
break;
|
||||
}
|
||||
const phraseList =
|
||||
currentMode === 'witty' ? wittyPhrases : INFORMATIVE_TIPS;
|
||||
|
||||
// If we have a maxLength, we need to account for potential prefixes.
|
||||
// Tips are prefixed with "Tip: " in the Composer UI.
|
||||
const prefixLength = currentMode === 'tips' ? 5 : 0;
|
||||
const adjustedMaxLength =
|
||||
maxLength !== undefined ? maxLength - prefixLength : undefined;
|
||||
const adjustedMaxLength = maxLength;
|
||||
|
||||
const filteredList =
|
||||
adjustedMaxLength !== undefined
|
||||
@@ -104,10 +96,18 @@ export const usePhraseCycler = (
|
||||
|
||||
if (filteredList.length > 0) {
|
||||
const randomIndex = Math.floor(Math.random() * filteredList.length);
|
||||
setCurrentLoadingPhrase(filteredList[randomIndex]);
|
||||
const selected = filteredList[randomIndex];
|
||||
if (currentMode === 'witty') {
|
||||
setCurrentWittyPhrase(selected);
|
||||
setCurrentTip(undefined);
|
||||
} else {
|
||||
setCurrentTip(selected);
|
||||
setCurrentWittyPhrase(undefined);
|
||||
}
|
||||
} else {
|
||||
// If no phrases fit, try to fallback to a very short list or nothing
|
||||
setCurrentLoadingPhrase(undefined);
|
||||
setCurrentTip(undefined);
|
||||
setCurrentWittyPhrase(undefined);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -134,5 +134,5 @@ export const usePhraseCycler = (
|
||||
maxLength,
|
||||
]);
|
||||
|
||||
return currentLoadingPhrase;
|
||||
return { currentTip, currentWittyPhrase };
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user