mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-05-03 14:10:43 +00:00
refactor ui for qwen code hooks
This commit is contained in:
parent
38caa0b218
commit
b08154dbee
21 changed files with 972 additions and 357 deletions
132
packages/cli/src/ui/components/hooks/HookDetailStep.tsx
Normal file
132
packages/cli/src/ui/components/hooks/HookDetailStep.tsx
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
/**
|
||||
* @license
|
||||
* Copyright 2026 Qwen Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { useState } from 'react';
|
||||
import { Box, Text } from 'ink';
|
||||
import { theme } from '../../semantic-colors.js';
|
||||
import { useKeypress } from '../../hooks/useKeypress.js';
|
||||
import type { HookEventDisplayInfo } from './types.js';
|
||||
import { SOURCE_DISPLAY_MAP } from './constants.js';
|
||||
|
||||
interface HookDetailStepProps {
|
||||
hook: HookEventDisplayInfo;
|
||||
onBack: () => void;
|
||||
}
|
||||
|
||||
export function HookDetailStep({
|
||||
hook,
|
||||
onBack,
|
||||
}: HookDetailStepProps): React.JSX.Element {
|
||||
const hasConfigs = hook.configs.length > 0;
|
||||
const [selectedIndex, setSelectedIndex] = useState(0);
|
||||
|
||||
// Handle keyboard navigation
|
||||
useKeypress(
|
||||
(key) => {
|
||||
if (key.name === 'escape') {
|
||||
onBack();
|
||||
} else if (hasConfigs) {
|
||||
if (key.name === 'up') {
|
||||
setSelectedIndex((prev) => Math.max(0, prev - 1));
|
||||
} else if (key.name === 'down') {
|
||||
setSelectedIndex((prev) =>
|
||||
Math.min(hook.configs.length - 1, prev + 1),
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
{ isActive: true },
|
||||
);
|
||||
|
||||
return (
|
||||
<Box flexDirection="column" paddingX={1}>
|
||||
{/* Title */}
|
||||
<Box marginBottom={1}>
|
||||
<Text bold color={theme.text.primary}>
|
||||
{hook.event}
|
||||
</Text>
|
||||
</Box>
|
||||
|
||||
{/* Description */}
|
||||
{hook.description && (
|
||||
<Box marginBottom={1}>
|
||||
<Text color={theme.text.secondary}>{hook.description}</Text>
|
||||
</Box>
|
||||
)}
|
||||
|
||||
{/* Exit codes */}
|
||||
{hook.exitCodes.length > 0 && (
|
||||
<Box flexDirection="column" marginBottom={1}>
|
||||
<Text bold color={theme.text.primary}>
|
||||
Exit codes:
|
||||
</Text>
|
||||
{hook.exitCodes.map((ec, index) => (
|
||||
<Box key={index}>
|
||||
<Text color={theme.text.secondary}>
|
||||
{` ${ec.code}: ${ec.description}`}
|
||||
</Text>
|
||||
</Box>
|
||||
))}
|
||||
</Box>
|
||||
)}
|
||||
|
||||
<Box marginTop={1} />
|
||||
|
||||
{/* Configs or empty state */}
|
||||
{hasConfigs ? (
|
||||
<>
|
||||
<Text bold color={theme.text.primary}>
|
||||
Configured hooks:
|
||||
</Text>
|
||||
{hook.configs.map((config, index) => {
|
||||
const isSelected = index === selectedIndex;
|
||||
const sourceDisplay =
|
||||
SOURCE_DISPLAY_MAP[config.source] || config.source;
|
||||
|
||||
return (
|
||||
<Box key={index}>
|
||||
<Box minWidth={2}>
|
||||
<Text
|
||||
color={isSelected ? theme.text.accent : theme.text.primary}
|
||||
>
|
||||
{isSelected ? '❯' : ' '}
|
||||
</Text>
|
||||
</Box>
|
||||
<Text
|
||||
color={isSelected ? theme.text.accent : theme.text.primary}
|
||||
bold={isSelected}
|
||||
>
|
||||
{`${index + 1}. ${config.config.command}`}
|
||||
</Text>
|
||||
<Text color={theme.text.secondary}> · </Text>
|
||||
<Text color={theme.text.secondary}>{sourceDisplay}</Text>
|
||||
</Box>
|
||||
);
|
||||
})}
|
||||
<Box marginTop={1}>
|
||||
<Text color={theme.text.secondary}>Esc to go back</Text>
|
||||
</Box>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Box>
|
||||
<Text color={theme.text.secondary}>
|
||||
No hooks configured for this event.
|
||||
</Text>
|
||||
</Box>
|
||||
<Box marginTop={1}>
|
||||
<Text color={theme.text.secondary}>
|
||||
To add hooks, edit settings.json directly or ask Qwen.
|
||||
</Text>
|
||||
</Box>
|
||||
<Box marginTop={1}>
|
||||
<Text color={theme.text.secondary}>Esc to go back</Text>
|
||||
</Box>
|
||||
</>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue