mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-05-02 21:50:52 +00:00
fix(cli): improve /btw overlay UX — layout, dismiss hints, and history cleanup
- Make /btw overlay mutually exclusive with Composer (replaces input area) - Add dismiss hints: "Press Escape to cancel" (pending) / "Press Space, Enter, or Escape to dismiss" (completed) - Skip adding /btw to conversation history to avoid duplicate display - Prioritize dialog shortcuts over btw dismiss via dialogsVisibleRef - Add `sleep` property to terminal-capture FlowStep for async wait scenarios Made-with: Cursor
This commit is contained in:
parent
130d6888b4
commit
dff9822f9b
6 changed files with 59 additions and 23 deletions
|
|
@ -958,6 +958,7 @@ export const AppContainer = (props: AppContainerProps) => {
|
|||
const ctrlDTimerRef = useRef<NodeJS.Timeout | null>(null);
|
||||
const [escapePressedOnce, setEscapePressedOnce] = useState(false);
|
||||
const escapeTimerRef = useRef<NodeJS.Timeout | null>(null);
|
||||
const dialogsVisibleRef = useRef(false);
|
||||
const [constrainHeight, setConstrainHeight] = useState<boolean>(true);
|
||||
const [ideContextState, setIdeContextState] = useState<
|
||||
IdeContext | undefined
|
||||
|
|
@ -1244,8 +1245,9 @@ export const AppContainer = (props: AppContainerProps) => {
|
|||
handleExit(ctrlDPressedOnce, setCtrlDPressedOnce, ctrlDTimerRef);
|
||||
return;
|
||||
} else if (keyMatchers[Command.ESCAPE](key)) {
|
||||
// Dismiss or cancel btw side-question on Escape
|
||||
if (btwItem) {
|
||||
// Dismiss or cancel btw side-question on Escape,
|
||||
// but only when btw is actually visible (not hidden behind a dialog).
|
||||
if (btwItem && !dialogsVisibleRef.current) {
|
||||
cancelBtw();
|
||||
return;
|
||||
}
|
||||
|
|
@ -1292,8 +1294,13 @@ export const AppContainer = (props: AppContainerProps) => {
|
|||
}
|
||||
|
||||
// Dismiss completed btw side-question on Space or Enter,
|
||||
// but only when the input buffer is empty so we don't swallow user keystrokes.
|
||||
if (btwItem && !btwItem.btw.isPending && buffer.text.length === 0) {
|
||||
// but only when btw is visible and the input buffer is empty.
|
||||
if (
|
||||
btwItem &&
|
||||
!btwItem.btw.isPending &&
|
||||
!dialogsVisibleRef.current &&
|
||||
buffer.text.length === 0
|
||||
) {
|
||||
if (key.name === 'return' || key.sequence === ' ') {
|
||||
setBtwItem(null);
|
||||
return;
|
||||
|
|
@ -1430,6 +1437,7 @@ export const AppContainer = (props: AppContainerProps) => {
|
|||
isApprovalModeDialogOpen ||
|
||||
isResumeDialogOpen ||
|
||||
isExtensionsManagerDialogOpen;
|
||||
dialogsVisibleRef.current = dialogsVisible;
|
||||
|
||||
const {
|
||||
isFeedbackDialogOpen,
|
||||
|
|
|
|||
|
|
@ -31,12 +31,17 @@ const BtwMessageInternal: React.FC<BtwDisplayProps> = ({ btw }) => (
|
|||
</Text>
|
||||
</Box>
|
||||
{btw.isPending ? (
|
||||
<Box>
|
||||
<Text color={Colors.AccentYellow}>{'+ '}</Text>
|
||||
<Text color={Colors.AccentYellow}>{t('Answering...')}</Text>
|
||||
<Box flexDirection="column" marginTop={1}>
|
||||
<Box>
|
||||
<Text color={Colors.AccentYellow}>{'+ '}</Text>
|
||||
<Text color={Colors.AccentYellow}>{t('Answering...')}</Text>
|
||||
</Box>
|
||||
<Box marginTop={1}>
|
||||
<Text dimColor>{t('Press Escape to cancel')}</Text>
|
||||
</Box>
|
||||
</Box>
|
||||
) : (
|
||||
<Box flexDirection="column">
|
||||
<Box flexDirection="column" marginTop={1}>
|
||||
<Text wrap="wrap">{btw.answer}</Text>
|
||||
<Box marginTop={1}>
|
||||
<Text dimColor>{t('Press Space, Enter, or Escape to dismiss')}</Text>
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ import { BundledSkillLoader } from '../../services/BundledSkillLoader.js';
|
|||
import { FileCommandLoader } from '../../services/FileCommandLoader.js';
|
||||
import { McpPromptLoader } from '../../services/McpPromptLoader.js';
|
||||
import { parseSlashCommand } from '../../utils/commands.js';
|
||||
import { isBtwCommand } from '../utils/commandUtils.js';
|
||||
import { clearScreen } from '../../utils/stdioHelpers.js';
|
||||
import { useKeypress } from './useKeypress.js';
|
||||
import {
|
||||
|
|
@ -385,10 +386,12 @@ export const useSlashCommandProcessor = (
|
|||
abortControllerRef.current = abortController;
|
||||
|
||||
const userMessageTimestamp = Date.now();
|
||||
addItemWithRecording(
|
||||
{ type: MessageType.USER, text: trimmed },
|
||||
userMessageTimestamp,
|
||||
);
|
||||
if (!isBtwCommand(trimmed)) {
|
||||
addItemWithRecording(
|
||||
{ type: MessageType.USER, text: trimmed },
|
||||
userMessageTimestamp,
|
||||
);
|
||||
}
|
||||
|
||||
let hasError = false;
|
||||
const {
|
||||
|
|
|
|||
|
|
@ -55,11 +55,6 @@ export const DefaultAppLayout: React.FC = () => {
|
|||
<>
|
||||
{/* Main view: conversation history + main composer / dialogs */}
|
||||
<MainContent />
|
||||
{uiState.btwItem && (
|
||||
<Box marginX={2} width={uiState.mainAreaWidth}>
|
||||
<BtwMessage btw={uiState.btwItem.btw} />
|
||||
</Box>
|
||||
)}
|
||||
<Box flexDirection="column" ref={uiState.mainControlsRef}>
|
||||
{uiState.dialogsVisible ? (
|
||||
<Box
|
||||
|
|
@ -72,6 +67,10 @@ export const DefaultAppLayout: React.FC = () => {
|
|||
addItem={uiState.historyManager.addItem}
|
||||
/>
|
||||
</Box>
|
||||
) : uiState.btwItem ? (
|
||||
<Box marginX={2} width={terminalWidth - 4}>
|
||||
<BtwMessage btw={uiState.btwItem.btw} />
|
||||
</Box>
|
||||
) : (
|
||||
<Composer />
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -26,12 +26,6 @@ export const ScreenReaderAppLayout: React.FC = () => {
|
|||
<MainContent />
|
||||
</Box>
|
||||
|
||||
{uiState.btwItem && (
|
||||
<Box marginX={2} width={uiState.mainAreaWidth}>
|
||||
<BtwMessage btw={uiState.btwItem.btw} />
|
||||
</Box>
|
||||
)}
|
||||
|
||||
{uiState.dialogsVisible ? (
|
||||
<Box marginX={2} flexDirection="column" width={uiState.mainAreaWidth}>
|
||||
<DialogManager
|
||||
|
|
@ -39,6 +33,10 @@ export const ScreenReaderAppLayout: React.FC = () => {
|
|||
addItem={uiState.historyManager.addItem}
|
||||
/>
|
||||
</Box>
|
||||
) : uiState.btwItem ? (
|
||||
<Box marginX={2} width={uiState.terminalWidth - 4}>
|
||||
<BtwMessage btw={uiState.btwItem.btw} />
|
||||
</Box>
|
||||
) : (
|
||||
<Composer />
|
||||
)}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue