mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-01 08:51:11 -07:00
feat(ui): implement refreshed UX for Composer layout
- Promotes refreshed multi-row status area and footer as the default experience. - Stabilizes Composer row heights to prevent layout 'jitter' during typing and model turns. - Unifies active hook status and model loading indicators into a single, stable Row 1. - Refactors settings to use backward-compatible 'Hide' booleans (ui.hideStatusTips, ui.hideStatusWit). - Removes vestigial context usage bleed-through logic in minimal mode to align with global UX direction. - Relocates toast notifications to the top status row for improved visibility. - Updates all CLI UI snapshots and architectural tests to reflect the stabilized layout.
This commit is contained in:
@@ -167,10 +167,10 @@ export interface SummarizeToolOutputSettings {
|
||||
tokenBudget?: number;
|
||||
}
|
||||
|
||||
export type LoadingPhrasesMode = 'tips' | 'witty' | 'all' | 'off';
|
||||
export type StatusHintsMode = 'tips' | 'witty' | 'all' | 'off';
|
||||
|
||||
export interface AccessibilitySettings {
|
||||
/** @deprecated Use ui.loadingPhrases instead. */
|
||||
/** @deprecated Use ui.statusHints instead. */
|
||||
enableLoadingPhrases?: boolean;
|
||||
screenReader?: boolean;
|
||||
}
|
||||
@@ -847,11 +847,11 @@ export function migrateDeprecatedSettings(
|
||||
const oldValue = settings[oldKey];
|
||||
const newValue = settings[newKey];
|
||||
|
||||
if (typeof oldValue === 'boolean') {
|
||||
if (oldValue === true || oldValue === false) {
|
||||
if (foundDeprecated) {
|
||||
foundDeprecated.push(prefix ? `${prefix}.${oldKey}` : oldKey);
|
||||
}
|
||||
if (typeof newValue === 'boolean') {
|
||||
if (newValue === true || newValue === false) {
|
||||
// Both exist, trust the new one
|
||||
if (removeDeprecated) {
|
||||
delete settings[oldKey];
|
||||
@@ -911,6 +911,91 @@ export function migrateDeprecatedSettings(
|
||||
const uiSettings = settings.ui as Record<string, unknown> | undefined;
|
||||
if (uiSettings) {
|
||||
const newUi = { ...uiSettings };
|
||||
let uiModified = false;
|
||||
|
||||
// Migrate hideIntroTips → hideTips (backward compatibility)
|
||||
if (newUi['hideIntroTips'] === true || newUi['hideIntroTips'] === false) {
|
||||
foundDeprecated.push('ui.hideIntroTips');
|
||||
if (newUi['hideTips'] === undefined) {
|
||||
newUi['hideTips'] = newUi['hideIntroTips'];
|
||||
uiModified = true;
|
||||
}
|
||||
if (removeDeprecated) {
|
||||
delete newUi['hideIntroTips'];
|
||||
uiModified = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Migrate loadingPhrases/statusHints (enums) → hideStatusTips/hideStatusWit (booleans)
|
||||
const oldHintSetting = newUi['statusHints'] ?? newUi['loadingPhrases'];
|
||||
if (oldHintSetting !== undefined) {
|
||||
if (newUi['loadingPhrases'] !== undefined) {
|
||||
foundDeprecated.push('ui.loadingPhrases');
|
||||
}
|
||||
if (newUi['statusHints'] !== undefined) {
|
||||
foundDeprecated.push('ui.statusHints');
|
||||
}
|
||||
|
||||
if (
|
||||
newUi['hideStatusTips'] === undefined &&
|
||||
newUi['hideStatusWit'] === undefined
|
||||
) {
|
||||
switch (oldHintSetting) {
|
||||
case 'all':
|
||||
newUi['hideStatusTips'] = false;
|
||||
newUi['hideStatusWit'] = false;
|
||||
uiModified = true;
|
||||
break;
|
||||
case 'tips':
|
||||
newUi['hideStatusTips'] = false;
|
||||
newUi['hideStatusWit'] = true;
|
||||
uiModified = true;
|
||||
break;
|
||||
case 'witty':
|
||||
newUi['hideStatusTips'] = true;
|
||||
newUi['hideStatusWit'] = false;
|
||||
uiModified = true;
|
||||
break;
|
||||
case 'off':
|
||||
newUi['hideStatusTips'] = true;
|
||||
newUi['hideStatusWit'] = true;
|
||||
uiModified = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (removeDeprecated) {
|
||||
if (newUi['loadingPhrases'] !== undefined) {
|
||||
delete newUi['loadingPhrases'];
|
||||
uiModified = true;
|
||||
}
|
||||
if (newUi['statusHints'] !== undefined) {
|
||||
delete newUi['statusHints'];
|
||||
uiModified = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle the recently added (now deprecated) showStatusTips and showStatusWit
|
||||
uiModified =
|
||||
migrateBoolean(
|
||||
newUi,
|
||||
'showStatusTips',
|
||||
'hideStatusTips',
|
||||
'ui',
|
||||
foundDeprecated,
|
||||
) || uiModified;
|
||||
uiModified =
|
||||
migrateBoolean(
|
||||
newUi,
|
||||
'showStatusWit',
|
||||
'hideStatusWit',
|
||||
'ui',
|
||||
foundDeprecated,
|
||||
) || uiModified;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
const accessibilitySettings = newUi['accessibility'] as
|
||||
| Record<string, unknown>
|
||||
@@ -928,26 +1013,34 @@ export function migrateDeprecatedSettings(
|
||||
)
|
||||
) {
|
||||
newUi['accessibility'] = newAccessibility;
|
||||
loadedSettings.setValue(scope, 'ui', newUi);
|
||||
if (!settingsFile.readOnly) {
|
||||
anyModified = true;
|
||||
}
|
||||
uiModified = true;
|
||||
}
|
||||
|
||||
// Migrate enableLoadingPhrases: false → loadingPhrases: 'off'
|
||||
// Migrate enableLoadingPhrases: false → hideStatusTips/hideStatusWit: true
|
||||
const enableLP = newAccessibility['enableLoadingPhrases'];
|
||||
if (
|
||||
typeof enableLP === 'boolean' &&
|
||||
newUi['loadingPhrases'] === undefined
|
||||
) {
|
||||
if (!enableLP) {
|
||||
newUi['loadingPhrases'] = 'off';
|
||||
loadedSettings.setValue(scope, 'ui', newUi);
|
||||
if (!settingsFile.readOnly) {
|
||||
anyModified = true;
|
||||
}
|
||||
}
|
||||
if (enableLP === true || enableLP === false) {
|
||||
foundDeprecated.push('ui.accessibility.enableLoadingPhrases');
|
||||
if (
|
||||
!enableLP &&
|
||||
newUi['hideStatusTips'] === undefined &&
|
||||
newUi['hideStatusWit'] === undefined
|
||||
) {
|
||||
newUi['hideStatusTips'] = true;
|
||||
newUi['hideStatusWit'] = true;
|
||||
uiModified = true;
|
||||
}
|
||||
if (removeDeprecated) {
|
||||
delete newAccessibility['enableLoadingPhrases'];
|
||||
newUi['accessibility'] = newAccessibility;
|
||||
uiModified = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (uiModified) {
|
||||
loadedSettings.setValue(scope, 'ui', newUi);
|
||||
if (!settingsFile.readOnly) {
|
||||
anyModified = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user