Merge pull request #425 from Open-Less/fix/v1.3.1-6

fix(capsule): 入场出场动画加慢加曲线 + thinking 字号/颜色重做 (v1.3.1-6)
This commit is contained in:
TRIP authored and GitHub committed 2026-05-12 18:44:04 +08:00
commit 545c3312c3
8 files changed
+77 -34

No files matched your search

+37 -5
View File
@@ -1910,7 +1910,13 @@ pub mod prompts {
const OUTPUT_BLOCK: &str = "# 输出\n\
直接输出最终文本正文。需要结构化时直接从标题 / 段落 / 编号开始。\n\
禁止以\u{201C}根据你/您给的内容\u{201D}\u{201C}我整理如下\u{201D}\u{201C}以下是整理后的内容\u{201D}\u{201C}优化如下\u{201D}\u{201C}结构化整理如下\u{201D}等句式开头。\n\
\u{4E0D}加解释、总结、客套话、代码围栏(\\`\\`\\`)或 markdown 元注释。";
\u{4E0D}加解释、总结、客套话、代码围栏(\\`\\`\\`)或 markdown 元注释。\n\
\n\
# 反 AI 自述式表达(强约束)\n\
- \u{4E0D}加 AI 自评 / 自述视角的语句:\u{201C}\u{6211}\u{4EEC}\u{770B}\u{4E86}\u{4E00}\u{4E0B}\u{201D}\u{201C}\u{6211}\u{4EEC}\u{53D1}\u{73B0}\u{201D}\u{201C}\u{7ECF}\u{8FC7}\u{5206}\u{6790}\u{201D}\u{201C}\u{7EFC}\u{5408}\u{6765}\u{770B}\u{201D}\u{201C}\u{603B}\u{4F53}\u{800C}\u{8A00}\u{201D}\u{201C}\u{6574}\u{4F53}\u{6765}\u{8BF4}\u{201D}\u{201C}\u{4F9D}\u{6211}\u{6240}\u{89C1}\u{201D}\u{201C}\u{6839}\u{636E}\u{60C5}\u{51B5}\u{201D}\u{201C}\u{4ECE}\u{7ED3}\u{679C}\u{6765}\u{770B}\u{201D}\u{7B49}\u{3002}\n\
- 保持原句的人称视角:原句是\u{201C}\u{6211}\u{201D}就用\u{201C}\u{6211}\u{201D},原句没有\u{201C}\u{6211}\u{4EEC}\u{201D}/\u{201C}\u{54B1}\u{4EEC}\u{201D}就\u{4E0D}凭空引入。\n\
- 直陈用户的实际诉求:原句说\u{201C}没问题\u{201D}就输出\u{201C}没问题\u{201D},\u{4E0D}扩写为\u{201C}\u{6211}\u{4EEC}\u{770B}\u{4E86}\u{4E00}\u{4E0B}\u{6CA1}\u{4EC0}\u{4E48}\u{5927}\u{95EE}\u{9898}\u{201D}\u{3002}\n\
- \u{4E0D}加修饰副词或铺垫句(\u{201C}\u{503C}\u{5F97}\u{4E00}\u{63D0}\u{7684}\u{662F}\u{201D}\u{201C}\u{503C}\u{5F97}\u{6CE8}\u{610F}\u{201D}\u{201C}\u{503C}\u{5F97}\u{8003}\u{8651}\u{201D}\u{7B49}\u{6F2B}\u{8C08}\u{8FC7}\u{6E21}\u{53E5})\u{3002}";
pub fn system_prompt(mode: PolishMode) -> String {
let task_and_example = match mode {
@@ -1928,14 +1934,32 @@ pub mod prompts {
去掉明显口癖、重复、无意义停顿;补充自然标点。\n\
保留用户原意、语气和表达习惯;\u{4E0D}扩写、\u{4E0D}创作。\n\
\n\
# 示例\n\
**工程化直陈**:开发协作 / 任务清单 / 技术沟通 / 工作汇报等场景下,按\u{4E3B}\u{8C13}\u{5BBE}陈述事实,\
\u{4E0D}加修饰副词、铺垫句、AI 自述(\u{201C}\u{6211}\u{4EEC}\u{770B}\u{4E86}\u{4E00}\u{4E0B}\u{201D}\u{201C}\u{603B}\u{4F53}\u{6765}\u{8BF4}\u{201D}等)。\
输出长度尽量贴近原句字数(± 20% 以内),\u{4E0D}让\u{8F7B}\u{5EA6}\u{6DA6}\u{8272}变成扩写。\n\
\n\
# 示例 1\n\
原:那个我觉得这个方案吧大概可以但是可能在性能上还要再看看\n\
出:我觉得这个方案大概可以,但性能上还要再看看。",
出:我觉得这个方案大概可以,但性能上还要再看看。\n\
\n\
# 示例 2(工程化直陈,\u{4E0D}加 AI 自述)\n\
原:嗯我们目前看了一下没什么大问题就是缓存策略可能要改一下\n\
出:目前没什么大问题,缓存策略需要调整。\
\u{200B}(注意:原句\u{6CA1}\u{6709}\u{660E}\u{786E}\u{7684}\u{201C}\u{6211}\u{4EEC}\u{201D}\u{4F5C}\u{4E3A}\u{96C6}\u{4F53},不引入\u{201C}\u{6211}\u{4EEC}\u{770B}\u{4E86}\u{4E00}\u{4E0B}\u{201D}\u{8FD9}\u{79CD}\u{81EA}\u{8FF0}\u{8868}\u{8FBE})",
PolishMode::Structured => "# 任务(清晰结构)\n\
把口述整理为脉络清晰、可直接复制走的结构化文本:保留用户的口语引子(润色后作为首行过渡),\
主动按语义把扁平事项归类成 2\u{2013}4 个主题,用双层格式呈现,尾巴查询用自然收尾句。\n\
\n\
**默认行为:双层 list。判断事项的标准**:\
以下任意一种都算一个事项 \u{2192} \u{4E0D}\u{4F9D}\u{8D56}\u{7528}\u{6237}\u{662F}\u{5426}\u{660E}\u{8BF4}\u{201C}\u{7B2C}\u{4E00}\u{201D}\u{201C}\u{7B2C}\u{4E8C}\u{201D}\u{201C}\u{53E6}\u{5916}\u{201D}\u{7B49}\u{8FDE}\u{63A5}\u{8BCD}\u{3002}\n\
\u{2003}\u{2003}1) 可独立成句的陈述(\u{4E3B}+\u{8C13}+\u{5BBE},如\u{201C}\u{300A}\u{67D0}\u{4E1C}\u{897F}\u{300B}\u{8FD8}\u{662F}\u{767D}\u{8272}\u{201D})\n\
\u{2003}\u{2003}2) 一个独立的请求 / 建议 / 处理方案(\u{5982}\u{201C}\u{8BA9}\u{5B83}\u{6D88}\u{5931}\u{201D}\u{201C}\u{6539}\u{6210}\u{5B9E}\u{9A8C}\u{6027}\u{201D})\n\
\u{2003}\u{2003}3) 一个状态判断 / 结论(\u{5982}\u{201C}\u{6CA1}\u{4EC0}\u{4E48}\u{5927}\u{95EE}\u{9898}\u{201D})\n\
\u{2003}\u{2003}4) 一个针对模块 / 主题 / 实体的描述\u{6216}\u{6307}\u{6307}\u{8981}\u{6C42}\n\
把上述事项数清,\u{2265}3 强制双层化,\u{4E0D}允许把多个独立陈述合\u{6210}一段连贯文字。\n\
即使输入听起来像\u{201C}一段顺着说下来\u{201D}的口播,只要能拆出 \u{2265}3 个独立关注点也必须双层化。\n\
\n\
**不可降级到轻度润色**:本任务的最低输出形态是双层 list 结构,\u{4E0D}允许只补标点 / 断句 / 去口癖然后输出连贯段落。\
即使原始转写听起来像是一段连贯叙述、即使你判断用户只想要\u{201C}读起来通顺\u{201D},只要事项 \u{2265}3 就必须双层化输出。\
输出连贯段落 = 失败。\n\
@@ -2034,9 +2058,17 @@ pub mod prompts {
\u{4E0D}引入空泛客套(\u{201C}希望您一切顺利\u{201D}\u{201C}祝商祺\u{201D}等);\
\u{4E0D}擅自承诺或扩写事实;邮件场景自动识别问候 / 落款。\n\
\n\
# 示例\n\
**工程化正式**:正式 ≠ 扩张。直陈用户原意,\u{4E0D}展开为商务铺垫,\u{4E0D}加\u{201C}\u{7ECF}\u{8FC7}\u{5206}\u{6790}\u{201D}\u{201C}\u{7EFC}\u{5408}\u{6765}\u{770B}\u{201D}\u{201C}\u{503C}\u{5F97}\u{6CE8}\u{610F}\u{7684}\u{662F}\u{201D}\u{7B49}\u{4EE3}\u{5165}\u{7B2C}\u{4E09}\u{65B9}\u{89C6}\u{89D2}\u{7684}\u{8BED}\u{53E5}\u{3002}\
输出长度尽量贴近原句字数(± 30% 以内),\u{4E0D}让\u{6B63}\u{5F0F}\u{5316}\u{6269}\u{5F20}\u{5230}\u{4E24}\u{500D}\u{957F}\u{5EA6}\u{3002}\n\
\n\
# 示例 1\n\
原:那个老板我跟你说下今天的发布我们可能要推迟因为测试还没跑完\n\
出:今天的发布需要推迟,原因是测试尚未完成。",
出:今天的发布需要推迟,原因是测试尚未完成。\n\
\n\
# 示例 2(工程化正式,\u{4E0D}加铺垫与代入语)\n\
原:嗯这次发版前我们看了一下其实问题不大但还是建议把缓存改一改\n\
出:本次发版整体问题不大,建议调整缓存策略。\
\u{200B}(注意:\u{4E0D}写\u{201C}\u{6211}\u{4EEC}\u{770B}\u{4E86}\u{4E00}\u{4E0B}\u{201D}\u{201C}\u{7ECF}\u{8FC7}\u{8BC4}\u{4F30}\u{201D}\u{4E4B}\u{7C7B}\u{4EE3}\u{5165}\u{8BED})",
};
format!(
+18 -14
View File
@@ -195,19 +195,18 @@ function Pill({ os, state, level, insertedChars, message, onCancel, onConfirm }:
>
<span
style={{
// 放大 11 → 14 让 thinking 在胶囊里更显眼。
fontSize: 14,
// 字重 500:用户反馈 700 太粗。500 是 medium 视觉重量,扫光更稳。
fontWeight: 500,
letterSpacing: 0.5,
// 字号 14 + 字重 500 时小写 g/y/p 等下伸字符在 line-height: 1 下会被
// clip。给 line-height 一点冗余 + 上下 1px padding,descender 不再被切。
// v1.3.1-6 用户反馈"thinking 不明显"——字号 14 → 17、字重 500 → 700、
// 配色由用户拍板:两侧底字浅亮黄(#FCD34D / amber-300),中段扫光深蓝
// (var(--ol-blue) ≈ #2563EB)。浅黄底色 + 深蓝扫光对比强但暖底不刺眼。
fontSize: 17,
fontWeight: 700,
letterSpacing: 0.3,
// 字号 17 + 字重 700 时小写 g/y/p 等下伸字符在 line-height: 1 下会被 clip。
// 给 line-height 冗余 + 上下 padding,descender 不再被切。
paddingBlock: 1,
// 扫光:渐变中段用更饱和的 ol-blue(不靠透明度),尾段保留 ink-3 作收尾,
// 整条 stripe 比之前更醒目(用户反馈"扫光不够明显")。
color: 'var(--ol-ink-2)',
backgroundImage:
'linear-gradient(100deg, var(--ol-ink-3) 0%, var(--ol-ink-3) 35%, var(--ol-blue) 50%, var(--ol-ink-3) 65%, var(--ol-ink-3) 100%)',
'linear-gradient(100deg, #FCD34D 0%, #FCD34D 35%, var(--ol-blue) 50%, #FCD34D 65%, #FCD34D 100%)',
backgroundSize: '220% auto',
WebkitBackgroundClip: 'text',
backgroundClip: 'text',
@@ -285,9 +284,10 @@ function Pill({ os, state, level, insertedChars, message, onCancel, onConfirm }:
);
}
// 与 @keyframes capsule-out 的 0.24s 时长一致——必须同步,否则定时器先于
// 与 @keyframes capsule-out 的 0.36s 时长一致——必须同步,否则定时器先于
// 动画结束就 unmount → 用户看到半截动画被截断。
const EXIT_ANIM_MS = 240;
// v1.3.1-6: 从 240ms 加到 360ms 让用户看清退出动画(240ms 太快感知不到)。
const EXIT_ANIM_MS = 360;
// 初始可见 state:Tauri 内运行从 idle 开始(等后端 capsule:state 事件),
// 浏览器 dev 模式从 recording 开始以便直接看到胶囊。
const INITIAL_VISIBLE_STATE: CapsuleState = isTauri ? 'idle' : 'recording';
@@ -398,8 +398,12 @@ export function Capsule() {
// 三平台一致 —— 旧版 Windows 走 animation:'none' 的分支已删除。
// transformOrigin 默认就是 50% 50%,所以 scaleX 天然以中央为锚点。
animation: leaving
? 'capsule-out .24s cubic-bezier(.4,0,.7,.2) forwards'
: 'capsule-in .26s cubic-bezier(.2,.9,.3,1.1) both',
// v1.3.1-6 调整:
// - 入场 .26s → .38s,cubic-bezier 加强 spring overshoot(更曲线感)
// - 出场 .24s → .36s(前面 EXIT_ANIM_MS 也同步到 360),曲线改成 ease-in-out 平滑
// 收缩 + 下移 + 淡出三段同步进行
? 'capsule-out .36s cubic-bezier(.55,.06,.68,.19) forwards'
: 'capsule-in .38s cubic-bezier(.16,.86,.32,1.18) both',
transformOrigin: 'center',
willChange: 'transform, opacity',
}}
+1
View File
@@ -667,6 +667,7 @@ export const en: typeof zhCN = {
title: 'Models',
desc: 'Manage on-device ASR models. Windows can use Microsoft Foundry Local Whisper; Qwen3-ASR model management stays separate.',
qwenTitle: 'Qwen3-ASR model manager',
qwenExperimentalBadge: 'Experimental',
engineUnavailable: 'The Qwen3-ASR inference engine is not bundled on this platform. You can still download models, but Qwen3-ASR cannot be activated here yet.',
qwenUnavailableOnWindows: 'Qwen3-ASR is not supported on Windows yet. Please use Foundry Local Whisper above instead.',
foundryTitle: 'Windows Foundry Local Whisper',
+1
View File
@@ -669,6 +669,7 @@ export const ja: typeof zhCN = {
title: 'モデル設定',
desc: '本機の ASR モデルを管理します。Windows では Microsoft Foundry Local Whisper を使用でき、Qwen3-ASR のモデル管理は独立しています。',
qwenTitle: 'Qwen3-ASR モデル管理',
qwenExperimentalBadge: '実験的',
engineUnavailable: '現在のプラットフォームには Qwen3-ASR 推論エンジンが同梱されていません。モデルのダウンロードは可能ですが、ここではまだ Qwen3-ASR を有効化できません。',
qwenUnavailableOnWindows: 'Windows では Qwen3-ASR にまだ対応していません。上記の Foundry Local Whisper をご利用ください。',
foundryTitle: 'Windows Foundry Local Whisper',
+1
View File
@@ -669,6 +669,7 @@ export const ko: typeof zhCN = {
title: '모델 설정',
desc: '기기 내 ASR 모델을 관리합니다. Windows 에서는 Microsoft Foundry Local Whisper 를 사용할 수 있으며, Qwen3-ASR 모델 관리는 별도로 유지됩니다.',
qwenTitle: 'Qwen3-ASR 모델 관리',
qwenExperimentalBadge: '실험적',
engineUnavailable: '현재 플랫폼에는 Qwen3-ASR 추론 엔진이 포함되어 있지 않습니다. 모델은 다운로드할 수 있지만 여기서는 아직 Qwen3-ASR 을 활성화할 수 없습니다.',
qwenUnavailableOnWindows: 'Windows 에서는 아직 Qwen3-ASR 을 지원하지 않습니다. 위의 Foundry Local Whisper 를 사용해 주세요.',
foundryTitle: 'Windows Foundry Local Whisper',
+1
View File
@@ -665,6 +665,7 @@ export const zhCN = {
title: '模型设置',
desc: '管理本机 ASR 模型。Windows 可使用 Microsoft Foundry Local Whisper;Qwen3-ASR 模型管理保持独立。',
qwenTitle: 'Qwen3-ASR 模型管理',
qwenExperimentalBadge: '实验性',
engineUnavailable: '当前平台暂未集成 Qwen3-ASR 推理引擎。可下载模型,但暂时无法启用 Qwen3-ASR。',
qwenUnavailableOnWindows: 'Windows 暂不支持 Qwen3-ASR,请使用上方 Foundry Local Whisper。',
foundryTitle: 'Windows Foundry Local Whisper',
+1
View File
@@ -667,6 +667,7 @@ export const zhTW: typeof zhCN = {
title: '模型設置',
desc: '管理本機 ASR 模型。Windows 可使用 Microsoft Foundry Local Whisper;Qwen3-ASR 模型管理保持獨立。',
qwenTitle: 'Qwen3-ASR 模型管理',
qwenExperimentalBadge: '實驗性',
engineUnavailable: '當前平臺暫未集成 Qwen3-ASR 推理引擎。可下載模型,但暫時無法啟用 Qwen3-ASR。',
qwenUnavailableOnWindows: 'Windows 暫不支援 Qwen3-ASR,請使用上方的 Foundry Local Whisper。',
foundryTitle: 'Windows Foundry Local Whisper',
+17 -15
View File
@@ -763,13 +763,9 @@ export function LocalAsr({ embedded = false }: LocalAsrProps = {}) {
灰显 + 禁用交互 + 顶部横幅说明不可用,引导他们使用上方 Foundry Local Whisper。
Linux 当前没有任何本地 ASR 提供,沿用 IS_MAC 隐藏(dead UI 仍然要藏)。 */}
{(IS_MAC || IS_WINDOWS) && (<>
{IS_WINDOWS && (
<Card style={{ marginBottom: 16, background: 'rgba(255, 235, 200, 0.4)' }}>
<div role="alert" style={{ fontSize: 13, color: 'var(--ol-ink-2)' }}>
{t('localAsr.qwenUnavailableOnWindows')}
</div>
</Card>
)}
{/* v1.3.1-6 用户反馈:Windows 顶部"暂不支持"banner 白底太显眼。已经整段 opacity/grayscale
+ inert 灰显 + 不可交互了,banner 是 noise,直接删。AT 仍可通过区域 aria-disabled
+ 灰显视觉判断不可用。 */}
<div
aria-disabled={IS_WINDOWS || undefined}
// @ts-expect-error — `inert` 是 HTML5 标准属性(React 19+ 一类型,TS lib.dom 旧版未收录)。
@@ -789,8 +785,17 @@ export function LocalAsr({ embedded = false }: LocalAsrProps = {}) {
</Card>
)}
<div style={{ fontSize: 13, fontWeight: 700, color: 'var(--ol-ink)', margin: '4px 0 10px' }}>
{t('localAsr.qwenTitle')}
<div style={{ display: 'flex', alignItems: 'center', gap: 8, margin: '4px 0 10px' }}>
{/* v1.3.1-6 用户拍板:千问3 ASR 改为「实验性」分组,独立于 Foundry/云端 ASR。
浅 amber badge 跟 thinking 扫光暖色调一致。 */}
<span style={{
fontSize: 10.5, fontWeight: 600, padding: '2px 7px', borderRadius: 4,
background: 'rgba(245, 158, 11, 0.15)', color: '#B45309',
letterSpacing: '0.02em', textTransform: 'uppercase',
}}>{t('localAsr.qwenExperimentalBadge')}</span>
<div style={{ fontSize: 13, fontWeight: 700, color: 'var(--ol-ink)' }}>
{t('localAsr.qwenTitle')}
</div>
</div>
<Card style={{ marginBottom: 16 }}>
@@ -912,12 +917,9 @@ export function LocalAsr({ embedded = false }: LocalAsrProps = {}) {
))}
</div>
) : (
/* Windows 灰显占位:后端列表为空,给一个静态 Card 表明这里"本该是模型列表"。 */
<Card>
<div style={{ fontSize: 13, color: 'var(--ol-ink-3)' }}>
{t('localAsr.qwenUnavailableOnWindows')}
</div>
</Card>
/* v1.3.1-6: Windows 列表为空时不再画白底 banner Card(用户反馈"白色显眼"),
留个低调的灰色 placeholder 维持容器高度。整段已 inert + 灰显,AT 用户感知到的也是"不可用"。 */
<div style={{ minHeight: 60 }} />
)}
</div>
)}