Skip to content

Conversation

@aojunhao123
Copy link
Contributor

@aojunhao123 aojunhao123 commented Dec 30, 2025

Summary by CodeRabbit

Bug Fixes

  • 改进了使用输入法编辑器 (IME) 时的 Escape 键处理,避免在文本组成期内误触发 Escape 事件。
  • 在窗口级别对输入法组成结束进行了更稳健的处理,降低误报概率并确保释放锁定后正常响应。

Tests

  • 新增并调整测试以验证 IME 场景中 Escape 键的正确行为,并提供重置 IME 锁的测试钩子以保证测试隔离。

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Dec 30, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

该 PR 在 useEscKeyDown 中加入 IME 组合结束后的按键锁定(200ms),并导出 resetEscKeyDownLock(),同时更新测试以验证在锁定期内 Escape 不触发 onEsc,仅在锁定期后才触发。

Changes

内聚组别 / 文件 变更摘要
IME 组合锁定与栈管理
src/useEscKeyDown.ts
新增 IME_LOCK_DURATION = 200,引入 lastCompositionEndTime(及 resetEscKeyDownLock() 导出),监听 compositionend 事件以记录结束时间;在 Escape 处理逻辑中若在锁定期内则忽略事件;调整堆栈 push/filter 行为并在 effect 中绑定/清理 compositionend 监听器。
锁定期行为测试
tests/index.test.tsx
在测试中导入并在 afterEach 中重置 IME 锁(resetEscKeyDownLock);新增用例模拟 compositionend 后在 0ms/100ms/250ms 触发 Escape,断言在锁定期内不触发 onEsc、锁定期后触发;使用假定时器推进时间以验证行为。

Sequence Diagram(s)

(此次变更为局部事件/钩子调整,未生成序列图)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • zombieJ

Poem

🐇 风中轻啜一口胡萝卜茶,键盘声里我守着节拍,
组合结束短短二百毫秒,我替输入安放小小防护带。
测试通过小鼓噔噔,用户体验静悄悄,
我是一只代码的兔子,跳跃着把回归稳稳抱怀。

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title accurately summarizes the main change: adding IME lock mechanism to prevent unintended portal closures during IME composition.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1bb9ceb and dd9081a.

📒 Files selected for processing (2)
  • src/useEscKeyDown.ts
  • tests/index.test.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/useEscKeyDown.ts
🧰 Additional context used
🧬 Code graph analysis (1)
tests/index.test.tsx (1)
src/useEscKeyDown.ts (1)
  • resetEscKeyDownLock (11-13)
🔇 Additional comments (3)
tests/index.test.tsx (3)

4-4: 导入语句正确!

新增的 resetEscKeyDownLockstack 导入是必需的,分别用于测试清理(afterEach)和堆栈状态验证。


31-33: 优秀的测试清理实践!

afterEach 中调用 resetEscKeyDownLock() 确保了测试之间的隔离,防止 IME 锁定状态在测试之间泄漏。这对于新功能的测试正确性至关重要。


376-400: 测试定时器配置正确,无需修改。

实现中使用 Date.now() 而非 performance.now(),jest.useFakeTimers() 默认即可正确模拟 Date.now()。第 377 行的配置已足够,无需 modern: true 选项。测试逻辑正确验证了 IME 锁定期(200ms)的行为。


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

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @aojunhao123, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request enhances the useEscKeyDown hook by implementing an Input Method Editor (IME) lock. The core purpose is to prevent accidental component closures, such as modals or popovers, that can occur when the Escape key is pressed inadvertently shortly after completing text input using an IME. This change improves the overall user experience by making the Escape key handling more robust and less prone to misinterpretation during IME usage.

Highlights

  • IME Lock Implementation: A new mechanism has been introduced to prevent the onEsc callback from being triggered immediately after an Input Method Editor (IME) composition ends. This lock lasts for 200 milliseconds, mitigating unintended closures.
  • Composition End Event Handling: The useEscKeyDown hook now listens for the compositionend event, recording the timestamp to enforce the IME lock duration effectively.
  • Enhanced Test Coverage: A dedicated test case has been added to tests/index.test.tsx to thoroughly verify the behavior of the new IME lock, ensuring onEsc is not called prematurely after IME activity.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@codecov
Copy link

codecov bot commented Dec 30, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 94.77%. Comparing base (52bdacf) to head (dd9081a).

Additional details and impacted files
@@            Coverage Diff             @@
##           master      #34      +/-   ##
==========================================
+ Coverage   94.36%   94.77%   +0.40%     
==========================================
  Files           7        7              
  Lines         142      153      +11     
  Branches       49       50       +1     
==========================================
+ Hits          134      145      +11     
  Misses          8        8              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces an IME lock to prevent the onEsc callback from firing unintentionally when the Escape key is used to interact with an IME. The implementation is clean and includes a new test case that validates the behavior correctly. I have a couple of suggestions to improve the reliability of the timing mechanism by using performance.now() instead of Date.now(). Additionally, I noticed a potential pre-existing issue in useEscKeyDown.ts where useMemo is used for side effects and logic is duplicated with useEffect, which could lead to bugs. I recommend addressing this in a follow-up to improve the hook's correctness.

Comment on lines 17 to 18
const now = Date.now();
if (now - compositionEndTimeRef.current < IME_LOCK_DURATION) {
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

For measuring time intervals, performance.now() is generally preferred over Date.now(). performance.now() provides a monotonically increasing timestamp that is not affected by system time changes, making it more reliable for calculating durations.

Suggested change
const now = Date.now();
if (now - compositionEndTimeRef.current < IME_LOCK_DURATION) {
const now = performance.now();
if (now - compositionEndTimeRef.current < IME_LOCK_DURATION) {

});

const handleCompositionEnd = useEvent(() => {
compositionEndTimeRef.current = Date.now();
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

For consistency and reliability in measuring time intervals, it's better to use performance.now() here as well, to match the usage in handleEscKeyDown.

Suggested change
compositionEndTimeRef.current = Date.now();
compositionEndTimeRef.current = performance.now();

Copy link

@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)
tests/index.test.tsx (1)

373-397: 测试逻辑正确,建议考虑导入常量以提高可维护性。

测试覆盖了 IME 锁定窗口的行为:在 compositionEnd 后的 200ms 内按下 Escape 不会触发 onEsc,超过 200ms 后才会触发。逻辑清晰正确。

不过,测试中的时间值(100ms、150ms)与实现中的 IME_LOCK_DURATION(200ms)紧密耦合。如果将来调整锁定时长,测试也需要同步修改。可以考虑从实现文件导出该常量以提高可维护性。

🔎 可选优化方案
- import { stack } from '../src/useEscKeyDown';
+ import { stack, IME_LOCK_DURATION } from '../src/useEscKeyDown';

然后在测试中使用:

jest.advanceTimersByTime(IME_LOCK_DURATION - 100);
// ...
jest.advanceTimersByTime(100 + 50); // 超过 IME_LOCK_DURATION
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 52bdacf and 1bb9ceb.

📒 Files selected for processing (2)
  • src/useEscKeyDown.ts
  • tests/index.test.tsx
🧰 Additional context used
🧬 Code graph analysis (1)
src/useEscKeyDown.ts (1)
src/Portal.tsx (1)
  • EscCallback (24-30)
🔇 Additional comments (4)
src/useEscKeyDown.ts (4)

8-9: 常量定义合理。

200ms 的锁定时长对于处理 IME 组合结束后的误触场景是合适的。如果需要在测试中使用该值,可以考虑导出此常量。


13-29: IME 锁定逻辑实现正确。

  • compositionEndTimeRef 初始值为 0 确保首次 Escape 不会被误阻止
  • 使用 useEvent 包装 handleCompositionEnd 保持回调引用稳定,避免重复注册监听器
  • 时间差判断逻辑清晰,Date.now() - compositionEndTimeRef.current < IME_LOCK_DURATION 能有效过滤 IME 结束后的短时间内的 Escape 按键

48-55: 事件监听器管理正确。

compositionend 监听器在 Portal 打开时注册,关闭时清理,与 keydown 监听器保持一致的模式。确保了不会产生内存泄漏。


10-57: 整体实现审查通过。

该实现有效防止了 IME 组合结束后立即按下 Escape 键导致的意外关闭行为:

  1. 每个 Portal 实例独立维护 compositionEndTimeRef
  2. compositionend 事件在 window 上监听,能捕获所有输入框的 IME 结束事件
  3. 锁定窗口(200ms)足够覆盖用户完成 IME 输入后按 Escape 的常见场景

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants