feat(ai): 支持录制聊天发送快捷键

- 工具中心新增 AI 聊天发送快捷键,默认 Enter 并支持 Ctrl/Cmd/Alt+Enter
- AI 输入框按录制绑定发送,保留 Shift+Enter 换行和输入法 composing 保护
- 修复 shortcutOptions 启动刷新覆盖录制值的问题,并校验脏持久化快捷键
- 补充快捷键、输入框提示和持久化回归测试
- 撤回 macOS Caps Lock 浮层无效前端规避,恢复输入控件 no-auto-cap 属性
- 新增需求进度追踪文档记录验证结果
This commit is contained in:
Syngnat
2026-04-28 18:12:42 +08:00
parent 56eaca9081
commit 5f7578c5ea
13 changed files with 525 additions and 47 deletions

View File

@@ -3,14 +3,15 @@ import { describe, expect, it } from 'vitest';
import { applyNoAutoCapAttributes, applyNoAutoCapAttributesWithin, noAutoCapInputProps } from './inputAutoCap';
describe('inputAutoCap', () => {
it('exports input props that disable correction without forcing native capitalization state', () => {
it('exports input props that disable auto capitalization and correction', () => {
expect(noAutoCapInputProps).toEqual({
autoCapitalize: 'none',
autoCorrect: 'off',
spellCheck: false,
});
});
it('applies correction attributes to inputs and textareas without autocapitalize', () => {
it('applies no-auto-cap attributes to inputs and textareas', () => {
const inputAttributes: Record<string, string> = {};
const textareaAttributes: Record<string, string> = {};
const input = {
@@ -29,10 +30,10 @@ describe('inputAutoCap', () => {
applyNoAutoCapAttributes(input);
applyNoAutoCapAttributes(textarea);
expect(inputAttributes.autocapitalize).toBeUndefined();
expect(inputAttributes.autocapitalize).toBe('none');
expect(inputAttributes.autocorrect).toBe('off');
expect(inputAttributes.spellcheck).toBe('false');
expect(textareaAttributes.autocapitalize).toBeUndefined();
expect(textareaAttributes.autocapitalize).toBe('none');
expect(textareaAttributes.autocorrect).toBe('off');
expect(textareaAttributes.spellcheck).toBe('false');
});
@@ -61,9 +62,9 @@ describe('inputAutoCap', () => {
applyNoAutoCapAttributesWithin(root);
expect(inputAttributes.autocapitalize).toBeUndefined();
expect(inputAttributes.autocapitalize).toBe('none');
expect(inputAttributes.autocorrect).toBe('off');
expect(textareaAttributes.autocapitalize).toBeUndefined();
expect(textareaAttributes.autocapitalize).toBe('none');
expect(textareaAttributes.autocorrect).toBe('off');
});
});