Skip to content

Feat/optimization typing hook #1067

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

AqingCyan
Copy link

@AqingCyan AqingCyan commented Jul 25, 2025

🤔 这个变动的性质是?

  • 🆕 新特性提交
  • 🐞 Bug 修复
  • 📝 站点、文档改进
  • 📽️ 演示代码改进
  • 💄 组件样式/交互改进
  • 🤖 TypeScript 定义更新
  • 📦 包体积优化
  • ⚡️ 性能优化
  • ⭐️ 功能增强
  • 🌐 国际化改进
  • 🛠 重构
  • 🎨 代码风格优化
  • ✅ 测试用例
  • 🔀 分支合并
  • ⏩ 工作流程
  • ⌨️ 无障碍改进
  • ❓ 其他改动(是关于什么的改动?)

🔗 相关 Issue

优化 Bubble 组件在 AI 对话场景中的打字体验问题。当 AI 输出内容发生变更时(如:"今天天气真好" → "今天天气不好"),原有逻辑会从头开始重新打字,导致用户体验不佳。

💡 需求背景和解决方案

要解决的具体问题:

当 AI 输出修改文本时,Bubble 组件的打字效果总是从头开始,即使新旧内容有公共前缀。例如:

  • 旧内容:"今天天气真好"
  • 新内容:"今天天气不好"
  • 原有行为:重新从 "今" 开始打字
  • 期望行为:从 "不" 开始继续打字

解决方案:

  • 新增 findCommonPrefix 函数,计算两个字符串的最长公共前缀
  • 优化 useTypedEffect hook 的重置逻辑:从公共前缀差异点开始继续打字
  • 保持原有的 content.indexOf(prevContentRef.current) !== 0 条件检查
  • 在公共前缀计算前添加空字符串检查

新增测试用例:

为确保功能稳定性和代码健壮性,新增了 4 个关键测试用例

  1. Bubble typing should continue from common prefix difference point

    • 测试场景:"今天天气真好""今天天气不好"
    • 验证:从 "不" 字开始继续打字,而非从头开始
  2. Bubble typing should handle shorter new content

    • 测试场景:"你好你好你好""你好"
    • 验证:新内容比公共前缀短时,直接显示完整内容
  3. Bubble typing should restart from beginning when no common prefix

    • 测试场景:"你好""再见"
    • 验证:完全不同的字符串从头开始打字
  4. Bubble typing should handle empty string edge cases

    • 测试场景:处理空字符串与非空字符串之间的转换
    • 验证:边界检查逻辑的正确性和健壮性

测试覆盖率:

  • useTypedEffect.ts 达到 100% 完全覆盖

API 实现:

现有 API 保持不变,内部逻辑优化:

<Bubble typing content="今天天气不好" />

站点文档更新

文档更新文字说明:

## zh-CN

通过设置 `typing` 属性,开启打字效果。当 `content` 更新时,若之前的内容是更新内容的子集(前缀),则会继续输出。如果有差异,则会智能地从公共前缀的差异点继续输出,而不是重新开始。例如从 "今天天气真好" 更新为 "今天天气不好" 时,会从 "不" 字开始继续打字。

## en-US

Enable typing output by setting the `typing` prop. When `content` is updated, if the previous content is a subset (prefix) of the new content, it will continue to output. If there are differences, it will intelligently continue output from the common prefix difference point instead of restarting. For example, when updating from "The weather is nice today." to "The weather is bad today.", it will continue typing from "bad".

示例更新

image

效果对比:

  • 修改前"今天天气真好""今天天气不好" 会显示 "今""今天""今天天""今天天气""今天天气不""今天天气不好"
  • 修改后"今天天气真好""今天天气不好" 会显示 "今天天气不""今天天气不好"

📝 更新日志

语言 更新描述
🇺🇸 英文 Bubble optimized typing effect to continue from common prefix difference point instead of restarting from beginning when content changes, enhanced with boundary checks for improved robustness
🇨🇳 中文 Bubble 优化打字效果,内容变更时从公共前缀差异点继续打字

Copy link
Contributor

Prepare preview

Copy link
Contributor

coderabbitai bot commented Jul 25, 2025

📝 Walkthrough
## Walkthrough

本次变更主要优化了 Bubble 组件在内容变更时的打字动画行为。通过新增公共前缀比较逻辑,组件在内容更新时能够更智能地决定从何处继续打字动画,并新增了相关测试用例以覆盖这些场景。同时,演示文档和示例组件也进行了相应更新,展示了更智能的打字续写效果。

## Changes

| 文件/分组                                                         | 变更摘要                                                         |
|------------------------------------------------------------------|------------------------------------------------------------------|
| components/bubble/__tests__/index.test.tsx                       | 新增四项测试,覆盖内容变更时打字动画的公共前缀、截断、无前缀及空字符串等场景。调整了 import 顺序。 |
| components/bubble/hooks/useTypedEffect.ts                        | 新增 `findCommonPrefix` 辅助函数,优化内容变更时打字动画的起始逻辑,支持根据公共前缀长度调整打字起点。 |
| components/bubble/demo/typing.md                                 | 增强文档,详细说明内容更新时打字动画如何基于公共前缀智能续写,添加中英文示例说明。               |
| components/bubble/demo/typing.tsx                                | 新增“智能公共前缀续写”示例,增加状态变量和按钮切换示例句,调整布局,演示更智能的打字动画效果。  |

## Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 分钟

## Poem

> 代码兔儿跳又跳,  
> 气泡动画更巧妙。  
> 公共前缀细分明,  
> 打字续写不慌张。  
> 新测试来护航,  
> 兔子乐在代码旁!  
> 🐇✨

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a833ed6 and 3c77b29.

⛔ Files ignored due to path filters (2)
  • components/bubble/__tests__/__snapshots__/demo-extend.test.ts.snap is excluded by !**/*.snap
  • components/bubble/__tests__/__snapshots__/demo.test.ts.snap is excluded by !**/*.snap
📒 Files selected for processing (2)
  • components/bubble/demo/typing.md (1 hunks)
  • components/bubble/demo/typing.tsx (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • components/bubble/demo/typing.md
🔇 Additional comments (6)
components/bubble/demo/typing.tsx (6)

3-3: 导入必要的组件支持新布局

添加 Space 组件导入以支持新的布局结构,这是合理的变更。


8-13: 示例数据设计良好,有效展示功能特性

correctionExamples 数组包含了多种场景的示例文本,能够很好地展示智能前缀续写功能:

  • 具有公共前缀的内容变更
  • 长度不同的内容
  • 完全不同的内容起始

这些示例能有效验证和展示优化后的打字动画行为。


17-17: 状态管理简洁合理

新增的 correctionDemo 状态用于控制当前展示的示例索引,命名清晰,初始化合理。


20-42: UI重构提升演示效果

使用 FlexSpace 组件重新组织布局结构,通过以下方式提升了演示效果:

  • 清晰的章节分离和标题
  • 合理的间距设置
  • 保持原有功能的同时改善了视觉组织

布局重构使演示更加清晰易懂。


44-60: 新增演示部分有效展示核心功能

"Smart Prefix Continuation" 部分很好地展示了此次优化的核心功能:

  • 清晰的章节标题说明演示内容
  • 按钮文本显示当前位置和总数,用户体验良好
  • 使用模运算实现循环切换逻辑正确
  • 保持一致的打字参数确保公平对比

该演示部分完美契合 PR 目标,能让用户直观感受到优化效果。


1-66: 演示组件整体实现优秀

整个演示组件的实现质量很高:

  • 代码结构清晰,组织良好
  • 有效展示了基础功能和新的智能前缀续写功能
  • UI 设计合理,用户体验良好
  • 示例选择恰当,能够突出优化效果
  • 遵循了 React 和 Ant Design 的最佳实践

这个演示能够很好地帮助用户理解和体验新功能的价值。

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@dosubot dosubot bot added the enhancement New feature or request label Jul 25, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
components/bubble/hooks/useTypedEffect.ts (1)

48-61: 打字重置逻辑优化合理,建议增加边界检查

新的重置逻辑很好地实现了从公共前缀差异点继续打字的功能,三种场景处理得当:

  • 无公共前缀:从头开始 (index = 1)
  • 有部分公共前缀:从差异点开始 (index = commonPrefixLength + 1)
  • 新内容等于或短于公共前缀:直接显示全部内容

但建议添加对空字符串的边界检查以提高代码健壮性。

考虑添加空字符串检查:

 ) {
+  // Handle empty strings
+  if (!content || !prevContentRef.current) {
+    setTypingIndex(1);
+    return;
+  }
+
   // Find the longest common prefix between new and old content
   const commonPrefixLength = findCommonPrefix(content, prevContentRef.current);
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9084ec7 and 98c7566.

📒 Files selected for processing (2)
  • components/bubble/__tests__/index.test.tsx (2 hunks)
  • components/bubble/hooks/useTypedEffect.ts (2 hunks)
🔇 Additional comments (5)
components/bubble/hooks/useTypedEffect.ts (1)

9-21: 算法实现正确且高效

findCommonPrefix 函数实现简洁清晰,时间复杂度为 O(min(n,m)),空间复杂度为 O(1)。算法逻辑正确,能够准确找到两个字符串的最长公共前缀长度。

components/bubble/__tests__/index.test.tsx (4)

5-5: 导入语句调整合理

Bubble 组件的导入移到测试工具导入之后,保持了导入顺序的一致性。


108-123: 测试用例设计优秀,完美验证核心功能

这个测试用例很好地验证了公共前缀优化的核心功能:

  • 使用中文字符串 "今天天气真好" → "今天天气不好" 作为测试数据
  • 正确验证了从公共前缀 "今天天气" 后继续打字的行为
  • 断言逻辑准确:首先显示到差异点 "今天天气不",然后完成全部内容

测试覆盖了最重要的使用场景,与 PR 目标完全一致。


125-137: 边界情况测试覆盖完整

这个测试用例很好地处理了新内容比公共前缀短的边界情况:

  • 验证了从 "你好你好你好" 更改为 "你好" 的场景
  • 正确断言新内容立即完整显示,因为新内容长度不超过公共前缀
  • 覆盖了 setTypingIndex(content.length) 分支的逻辑

139-154: 无公共前缀场景测试完整

测试用例正确验证了完全不同内容的重启行为:

  • 使用 "你好" → "再见" 验证无公共前缀场景
  • 正确断言打字动画从头开始 (显示 "再")
  • 覆盖了 commonPrefixLength === 0 的处理逻辑

三个测试用例共同构成了完整的功能验证矩阵。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant