mirror of
https://github.com/siteboon/claudecodeui.git
synced 2026-05-31 00:55:42 +08:00
fix(chat): stabilize provider/message handling and complete chat i18n coverage
Unify provider typing, harden realtime message effects, normalize tool input
serialization, and finish i18n/a11y updates across chat UI components.
- tighten provider contracts from `Provider | string` to `SessionProvider` in:
- `useChatProviderState`
- `useChatComposerState`
- `useChatRealtimeHandlers`
- `ChatMessagesPane`
- `ProviderSelectionEmptyState`
- refactor `AssistantThinkingIndicator` to accept `selectedProvider` via props
instead of reading provider from local storage during render
- fix stale-closure risk in `useChatRealtimeHandlers` by:
- adding missing effect dependencies
- introducing `lastProcessedMessageRef` to prevent duplicate processing when
dependencies change without a new message object
- standardize `toolInput` shape in `messageTransforms`:
- add `normalizeToolInput(...)`
- ensure all conversion paths produce consistent string output
- remove mixed `null`/raw/stringified variants across cursor/session branches
- harden tool display fallback in `CollapsibleDisplay`:
- default border class now falls back safely for unknown categories
- improve chat i18n consistency:
- localize hardcoded strings in `MessageComponent`
(`permissions.*`, `interactive.*`, `thinking.emoji`, `json.response`,
`messageTypes.error`)
- localize button titles in `ChatInputControls`
(`input.clearInput`, `input.scrollToBottom`)
- localize provider-specific empty-project prompt in `ChatInterface`
(`projectSelection.startChatWithProvider`)
- localize repeated “Start the next task” prompt in
`ProviderSelectionEmptyState` (`tasks.nextTaskPrompt`)
- add missing translation keys in all supported chat locales:
- `src/i18n/locales/en/chat.json`
- `src/i18n/locales/ko/chat.json`
- `src/i18n/locales/zh-CN/chat.json`
- new keys:
- `input.clearInput`
- `input.scrollToBottom`
- `projectSelection.startChatWithProvider`
- `tasks.nextTaskPrompt`
- improve attachment remove-button accessibility in `ImageAttachment`:
- add `type="button"` and `aria-label`
- make control visible on touch/small screens and focusable states
- preserve hover behavior on larger screens
Validation:
- `npm run typecheck`
This commit is contained in:
@@ -3,14 +3,13 @@ import { useTranslation } from 'react-i18next';
|
||||
import SessionProviderLogo from '../../../SessionProviderLogo';
|
||||
import NextTaskBanner from '../../../NextTaskBanner.jsx';
|
||||
import { CLAUDE_MODELS, CURSOR_MODELS, CODEX_MODELS } from '../../../../../shared/modelConstants';
|
||||
import type { Provider } from '../../types/types';
|
||||
import type { ProjectSession } from '../../../../types/app';
|
||||
import type { ProjectSession, SessionProvider } from '../../../../types/app';
|
||||
|
||||
interface ProviderSelectionEmptyStateProps {
|
||||
selectedSession: ProjectSession | null;
|
||||
currentSessionId: string | null;
|
||||
provider: Provider | string;
|
||||
setProvider: (next: Provider | string) => void;
|
||||
provider: SessionProvider;
|
||||
setProvider: (next: SessionProvider) => void;
|
||||
textareaRef: React.RefObject<HTMLTextAreaElement>;
|
||||
claudeModel: string;
|
||||
setClaudeModel: (model: string) => void;
|
||||
@@ -42,8 +41,10 @@ export default function ProviderSelectionEmptyState({
|
||||
setInput,
|
||||
}: ProviderSelectionEmptyStateProps) {
|
||||
const { t } = useTranslation('chat');
|
||||
// Reuse one translated prompt so task-start behavior stays consistent across empty and session states.
|
||||
const nextTaskPrompt = t('tasks.nextTaskPrompt', { defaultValue: 'Start the next task' });
|
||||
|
||||
const selectProvider = (nextProvider: Provider) => {
|
||||
const selectProvider = (nextProvider: SessionProvider) => {
|
||||
setProvider(nextProvider);
|
||||
localStorage.setItem('selected-provider', nextProvider);
|
||||
setTimeout(() => textareaRef.current?.focus(), 100);
|
||||
@@ -202,7 +203,7 @@ export default function ProviderSelectionEmptyState({
|
||||
|
||||
{provider && tasksEnabled && isTaskMasterInstalled && (
|
||||
<div className="mt-4 px-4 sm:px-0">
|
||||
<NextTaskBanner onStartTask={() => setInput('Start the next task')} onShowAllTasks={onShowAllTasks} />
|
||||
<NextTaskBanner onStartTask={() => setInput(nextTaskPrompt)} onShowAllTasks={onShowAllTasks} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
@@ -214,7 +215,7 @@ export default function ProviderSelectionEmptyState({
|
||||
|
||||
{tasksEnabled && isTaskMasterInstalled && (
|
||||
<div className="mt-4 px-4 sm:px-0">
|
||||
<NextTaskBanner onStartTask={() => setInput('Start the next task')} onShowAllTasks={onShowAllTasks} />
|
||||
<NextTaskBanner onStartTask={() => setInput(nextTaskPrompt)} onShowAllTasks={onShowAllTasks} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user