fix: match Code microphone and send button order

This commit is contained in:
鲨鱼辣椒 committed 2026-10-13 19:20:27 +08:00
1 parent f61efaf046
commit ddb942f944
4 files changed
+13 -2

No files matched your search

@@ -26,7 +26,7 @@
## Verification
- Current-baseline 253 related regression tests passed (11 files), 28 voice tests including StrictMode passed, and 31 new upload/lifecycle tests passed: 312 disjoint cases. Final typecheck, focused lint (0 errors; two existing CloudChat warnings), full Renderer/Main/Preload/utility Vite build and project-docs/diff gates passed. Independent review has no open blocker. 17 disjoint Electron scenarios passed: 12 in first run plus 5 targeted reruns after updating inherited timestamp/recovery assertions to the exact current trial contract. Published voice fixture validates WAV transcription, latest-draft append, no automatic prompts, 32px buttons and multi-line growth; layout covers narrow/wide windows, long messages, attachments and stream/stop. Voice screenshot visually inspected by root and QA. Fixture audio never accesses the real microphone or paid provider. Real microphone/provider transcription remains distinct from fixture validation.
- Current-baseline 253 related regression tests passed (11 files), 28 voice tests including StrictMode passed, and 31 new upload/lifecycle tests passed: 312 disjoint cases. Final typecheck, focused lint (0 errors; two existing CloudChat warnings), full Renderer/Main/Preload/utility Vite build and project-docs/diff gates passed. Independent review has no open blocker. 17 disjoint Electron scenarios passed: 12 in first run plus 5 targeted reruns after updating inherited timestamp/recovery assertions to the exact current trial contract. Published voice fixture validates WAV transcription, latest-draft append, no automatic prompts, 32px buttons and multi-line growth; layout covers narrow/wide windows, long messages, attachments and stream/stop. Voice screenshot visually inspected by root and QA. Final comparison moved the microphone beside send on the right, matching Code; a fresh full build/typecheck and two targeted Electron reruns passed, including 4px adjacency and 375px layout. Fixture audio never accesses the real microphone or paid provider. Real microphone/provider transcription remains distinct from fixture validation.
## Follow-ups
+3 -1
View File
@@ -441,7 +441,6 @@ export function CloudChat({ slug, previewRevision: latestRevision, initialThread
headerTarget={attachmentHeader === undefined ? localAttachmentHeader : attachmentHeader} activeView={activeView}
deliveryHistory={history}
filesRevision={`${history?.messages.at(-1)?.id ?? ''}:${history?.run?.agent_run_id ?? ''}:${history?.run?.status ?? ''}`}
actions={<ComposerVoiceButton voiceInput={voiceInput} />}
onBusy={setAttachmentBusy} disabled={!editable || running || voicePending} ensureThread={async () => {
if (thread) return thread.thread_id;
const expectedGeneration = generation.current;
@@ -452,8 +451,11 @@ export function CloudChat({ slug, previewRevision: latestRevision, initialThread
return created.thread_id;
}} footer={<>
<span className="agent-chat-keyboard-hint">Enter 发送 · Shift + Enter 换行</span>
<div className="agent-chat-composer-controls">
<ComposerVoiceButton voiceInput={voiceInput} />
{running ? <Button className="agent-chat-stop agent-chat-submit" size="icon" variant="outline" disabled={busy} onClick={() => void cancel()} type="button" aria-label="停止" title="停止"><Square className="h-3.5 w-3.5 fill-current" /></Button>
: <Button className="agent-chat-send agent-chat-submit" size="icon" type="submit" aria-label={busy ? '正在提交' : intent ? '重试本次发送' : '发送'} title={intent ? '重试本次发送' : '发送'} disabled={!canSend}>{busy ? <LoaderCircle className="h-4 w-4 animate-spin" /> : <ArrowUp className="h-4 w-4" />}</Button>}
</div>
</>}>
<Textarea aria-label="消息" className="agent-chat-input resize-none border-0 shadow-none focus-visible:ring-0" maxLength={32000}
rows={Math.min(6, Math.max(1, query.split('\n').length))}
+1
View File
@@ -146,6 +146,7 @@
.agent-chat-composer .agent-attachment-add:hover:not(:disabled) { background: hsl(var(--surface-subtle)); }
.agent-chat-composer .agent-attachment-add > svg { width: 16px; height: 16px; }
.agent-attachment-toolbar .agent-chat-keyboard-hint { margin-left: auto; }
.agent-chat-composer-controls { display: flex; min-width: 0; flex-shrink: 0; align-items: center; gap: 4px; margin-left: auto; }
.agent-attachment-toolbar > :is(.agent-chat-send, .agent-chat-stop, .agent-chat-submit) { margin-left: auto; }
.agent-attachment-toolbar .agent-chat-keyboard-hint + :is(.agent-chat-send, .agent-chat-stop, .agent-chat-submit) { margin-left: 4px; }
.agent-chat-composer .agent-attachment-selected { gap: 8px; margin-bottom: 8px; padding-inline: 4px; }
+8
View File
@@ -359,6 +359,14 @@ test('personal cloud Agent identity, configuration and separate published chat i
expect(sendGeometry.width).toBe(32);
expect(sendGeometry.height).toBe(32);
expect(sendGeometry.radius).toBeGreaterThanOrEqual(sendGeometry.width / 2);
const toolbarPositions = await voiceComposer.locator('[aria-label="添加文件或图片"], [aria-label="语音输入"], [aria-label="发送"]').evaluateAll(elements =>
Object.fromEntries(elements.map(element => {
const bounds = element.getBoundingClientRect();
return [element.getAttribute('aria-label'), { left: bounds.left, right: bounds.right }];
})));
expect(toolbarPositions['语音输入'].left).toBeGreaterThan(toolbarPositions['添加文件或图片'].right);
expect(toolbarPositions['发送'].left).toBeGreaterThan(toolbarPositions['语音输入'].right);
expect(toolbarPositions['发送'].left - toolbarPositions['语音输入'].right).toBeCloseTo(4, 1);
await voiceDraft.fill('原来的想法');
await voiceComposer.getByRole('button', { name: '语音输入', exact: true }).click();
await expect(voiceComposer.getByRole('button', { name: '停止语音输入' })).toBeVisible();