feat(cli): improve auth dialog UX with clearer three-option layout

- Replace nested API-KEY submenu with flat three-option layout
- Add descriptive labels for each authentication method:
  - Qwen OAuth: Free, up to 1,000 requests/day
  - Alibaba Cloud Coding Plan: Paid, multiple model providers
  - API Key: Bring your own API key
- Simplify region selection for Coding Plan (China vs Global)
- Use DescriptiveRadioButtonSelect for better visual hierarchy
- Add itemGap prop to BaseSelectionList for spacing
- Update i18n strings in en.js, zh.js, and ru.js
- Simplify custom API key configuration info view
- Clean up unused region-specific strings

Closes #2016

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
tanzhenxin 2026-03-01 15:22:35 +08:00
parent 1f46ed28d9
commit d3cdad5100
20 changed files with 442 additions and 619 deletions

View file

@ -57,9 +57,6 @@ export function ApiKeyInput({
return (
<Box flexDirection="column">
<Box marginBottom={1}>
<Text>{t('Please enter your API key:')}</Text>
</Box>
<TextInput value={apiKey} onChange={setApiKey} placeholder="sk-sp-..." />
{error && (
<Box marginTop={1}>
@ -67,18 +64,18 @@ export function ApiKeyInput({
</Box>
)}
<Box marginTop={1}>
<Text>{t('You can get your exclusive Coding Plan API-KEY here:')}</Text>
<Text>{t('You can get your Coding Plan API key here')}</Text>
</Box>
<Box marginTop={0}>
<Link url={apiKeyUrl} fallback={false}>
<Text color={theme.status.success} underline>
<Text color={theme.text.link} underline>
{apiKeyUrl}
</Text>
</Link>
</Box>
<Box marginTop={1}>
<Text color={theme.text.secondary}>
{t('(Press Enter to submit, Escape to cancel)')}
{t('Enter to submit, Esc to go back')}
</Text>
</Box>
</Box>

View file

@ -30,6 +30,8 @@ export interface BaseSelectionListProps<
showNumbers?: boolean;
showScrollArrows?: boolean;
maxItemsToShow?: number;
/** Gap (in rows) between each item. */
itemGap?: number;
renderItem: (item: TItem, context: RenderItemContext) => React.ReactNode;
}
@ -59,6 +61,7 @@ export function BaseSelectionList<
showNumbers = true,
showScrollArrows = false,
maxItemsToShow = 10,
itemGap = 0,
renderItem,
}: BaseSelectionListProps<T, TItem>): React.JSX.Element {
const { activeIndex } = useSelectionList({
@ -89,7 +92,7 @@ export function BaseSelectionList<
const numberColumnWidth = String(items.length).length;
return (
<Box flexDirection="column">
<Box flexDirection="column" gap={itemGap}>
{/* Use conditional coloring instead of conditional rendering */}
{showScrollArrows && (
<Text

View file

@ -12,7 +12,7 @@ import type { SelectionListItem } from '../../hooks/useSelectionList.js';
export interface DescriptiveRadioSelectItem<T> extends SelectionListItem<T> {
title: React.ReactNode;
description: string;
description: React.ReactNode;
}
export interface DescriptiveRadioButtonSelectProps<T> {
@ -32,6 +32,8 @@ export interface DescriptiveRadioButtonSelectProps<T> {
showScrollArrows?: boolean;
/** The maximum number of items to show at once. */
maxItemsToShow?: number;
/** Gap (in rows) between each item. */
itemGap?: number;
}
/**
@ -48,6 +50,7 @@ export function DescriptiveRadioButtonSelect<T>({
showNumbers = false,
showScrollArrows = false,
maxItemsToShow = 10,
itemGap = 0,
}: DescriptiveRadioButtonSelectProps<T>): React.JSX.Element {
return (
<BaseSelectionList<T, DescriptiveRadioSelectItem<T>>
@ -59,6 +62,7 @@ export function DescriptiveRadioButtonSelect<T>({
showNumbers={showNumbers}
showScrollArrows={showScrollArrows}
maxItemsToShow={maxItemsToShow}
itemGap={itemGap}
renderItem={(item, { titleColor }) => (
<Box flexDirection="column" key={item.key}>
<Text color={titleColor}>{item.title}</Text>