Skip to content

🐛 fix: add HotkeyRegistry for conversation-level hotkey management#12907

Open
sxjeru wants to merge 11 commits into
lobehub:canaryfrom
sxjeru:31111
Open

🐛 fix: add HotkeyRegistry for conversation-level hotkey management#12907
sxjeru wants to merge 11 commits into
lobehub:canaryfrom
sxjeru:31111

Conversation

@sxjeru

@sxjeru sxjeru commented Mar 11, 2026

Copy link
Copy Markdown
Contributor

💻 Change Type

  • ✨ feat
  • 🐛 fix
  • ♻️ refactor
  • 💄 style
  • 👷 build
  • ⚡️ perf
  • ✅ test
  • 📝 docs
  • 🔨 chore

🔗 Related Issue

🔀 Description of Change

🧪 How to Test

  • Tested locally
  • Added/updated tests
  • No tests needed

📸 Screenshots / Videos

Before After
... ...

📝 Additional Information

Summary by Sourcery

Add a conversation-scoped hotkey registry within ConversationProvider to handle message-level keyboard shortcuts using the local conversation store.

New Features:

  • Introduce a Conversation HotkeyRegistry component that wires conversation-level keyboard shortcuts to conversation actions.

Bug Fixes:

  • Ensure regenerate, delete last message, and delete-and-regenerate shortcuts operate on the correct messages within the active conversation context.

@vercel

vercel Bot commented Mar 11, 2026

Copy link
Copy Markdown

@sxjeru is attempting to deploy a commit to the LobeHub OSS Team on Vercel.

A member of the Team first needs to authorize it.

@sourcery-ai

sourcery-ai Bot commented Mar 11, 2026

Copy link
Copy Markdown
Contributor

Reviewer's Guide

Introduces a Conversation-level HotkeyRegistry component that wires conversation store actions into hotkey callbacks, and mounts it inside ConversationProvider so conversation-specific keyboard shortcuts work with local message state.

Sequence diagram for conversation hotkey handling

sequenceDiagram
  actor User
  participant HotkeySystem
  participant HotkeyRegistry
  participant ConversationStore
  participant UIChat

  User->>HotkeySystem: keyDown RegenerateMessage
  HotkeySystem->>HotkeyRegistry: invoke RegenerateMessage callback
  HotkeyRegistry->>ConversationStore: get displayMessages
  HotkeyRegistry->>HotkeyRegistry: getLastAssistantMessageId(displayMessages)
  HotkeyRegistry->>ConversationStore: regenerateAssistantMessage(messageId)
  ConversationStore-->>UIChat: update displayMessages
  UIChat-->>User: show regenerated assistant message
Loading

Class diagram for ConversationProvider and HotkeyRegistry

classDiagram
  class ConversationProvider {
    +children ReactNode
    +ConversationProvider(props)
  }

  class HotkeyRegistry {
    +HotkeyRegistry()
  }

  class ConversationStore {
    +deleteMessage(id)
    +delAndRegenerateMessage(id)
    +regenerateAssistantMessage(id)
    +displayMessages UIChatMessage[]
  }

  class UIChatMessage {
    +id string
    +role string
  }

  class HotkeyEnum {
    <<enumeration>>
    RegenerateMessage
    DeleteLastMessage
    DeleteAndRegenerateMessage
  }

  class useHotkeyById {
    +useHotkeyById(hotkeyId, callback, options, deps)
  }

  class useConversationStore {
    +useConversationStore(selector)
  }

  ConversationProvider *-- HotkeyRegistry
  HotkeyRegistry ..> useConversationStore
  HotkeyRegistry ..> useHotkeyById
  HotkeyRegistry ..> ConversationStore
  HotkeyRegistry ..> HotkeyEnum
  ConversationStore o-- UIChatMessage
Loading

File-Level Changes

Change Details Files
Add a Conversation-level hotkey registry component that binds hotkey IDs to conversation store actions.
  • Create a memoized HotkeyRegistry React component that registers conversation-specific hotkeys using useHotkeyById
  • Wire conversation store actions (delete, delete+regenerate, regenerate) and displayMessages into the registry via useConversationStore selector
  • Implement helper functions to locate the last assistant message and the last message in the display list for use by hotkey callbacks
  • Ensure hotkey callbacks are content-editable aware and include relevant dependencies for proper re-registration
src/features/Conversation/HotkeyRegistry.tsx
Mount the HotkeyRegistry within the ConversationProvider so it has access to the ConversationStore context.
  • Render HotkeyRegistry inside ConversationProvider alongside ConversationPanel and children so it participates in the same provider scope
src/features/Conversation/ConversationProvider.tsx

Assessment against linked issues

Issue Objective Addressed Explanation
#11138 Restore the non-working conversation-level keyboard shortcuts (e.g., regenerate message, delete last message, delete-and-regenerate) in the web client so they function correctly in the browser.

Possibly linked issues

  • #unknown: 该 PR 为会话消息相关快捷键提供注册逻辑,直接修复浏览器端部分快捷键失效的问题。

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hey - I've left some high level feedback:

  • In HotkeyRegistry, you’re subscribing to four store values in a single selector even though each hotkey only needs a subset; consider using separate useConversationStore selectors per hotkey (or useShallow) to reduce unnecessary re-renders and subscriptions.
  • The getLastAssistantMessageId / getLastMessageId helpers embed message-selection rules directly in the component; if this logic is (or might become) shared with other features (e.g., toolbar actions, context menus), consider moving them into a small message-utils module or the store to keep the selection semantics consistent.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `HotkeyRegistry`, you’re subscribing to four store values in a single selector even though each hotkey only needs a subset; consider using separate `useConversationStore` selectors per hotkey (or `useShallow`) to reduce unnecessary re-renders and subscriptions.
- The `getLastAssistantMessageId` / `getLastMessageId` helpers embed message-selection rules directly in the component; if this logic is (or might become) shared with other features (e.g., toolbar actions, context menus), consider moving them into a small message-utils module or the store to keep the selection semantics consistent.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@codecov

codecov Bot commented Mar 11, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 92.07317% with 13 lines in your changes missing coverage. Please review.
✅ Project coverage is 70.34%. Comparing base (64d3bdb) to head (98d7953).

Additional details and impacted files
@@            Coverage Diff             @@
##           canary   #12907      +/-   ##
==========================================
+ Coverage   69.18%   70.34%   +1.16%     
==========================================
  Files        3244     3330      +86     
  Lines      314191   332821   +18630     
  Branches    32992    35164    +2172     
==========================================
+ Hits       217387   234138   +16751     
- Misses      96619    98498    +1879     
  Partials      185      185              
Flag Coverage Δ
app 61.35% <92.07%> (+0.02%) ⬆️
database 89.90% <ø> (?)
packages/agent-manager-runtime 49.69% <ø> (ø)
packages/agent-runtime 81.06% <ø> (ø)
packages/builtin-tool-lobe-agent 18.52% <ø> (ø)
packages/context-engine 84.12% <ø> (ø)
packages/conversation-flow 91.29% <ø> (ø)
packages/device-gateway-client 90.18% <ø> (ø)
packages/eval-dataset-parser 95.15% <ø> (ø)
packages/eval-rubric 76.11% <ø> (ø)
packages/fetch-sse 85.57% <ø> (-1.72%) ⬇️
packages/file-loaders 87.89% <ø> (ø)
packages/memory-user-memory 74.99% <ø> (ø)
packages/model-bank 99.99% <ø> (ø)
packages/model-runtime 84.23% <ø> (ø)
packages/prompts 72.51% <ø> (ø)
packages/python-interpreter 92.90% <ø> (ø)
packages/ssrf-safe-fetch 0.00% <ø> (ø)
packages/types 35.21% <ø> (ø)
packages/utils 85.06% <ø> (ø)
packages/web-crawler 88.08% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

Components Coverage Δ
Store 68.23% <ø> (ø)
Services 54.25% <ø> (ø)
Server 70.66% <ø> (ø)
Libs 56.02% <ø> (+0.13%) ⬆️
Utils 82.08% <ø> (ø)
🚀 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.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b870cbe3b3

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/features/Conversation/ConversationProvider.tsx Outdated
Copilot AI review requested due to automatic review settings March 20, 2026 01:15

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR introduces conversation-scoped registration for message-control hotkeys (regenerate, delete last, delete-and-regenerate) so that shortcuts operate on the currently active conversation’s local ConversationStore, addressing broken/incorrectly-targeted shortcuts reported in #11138.

Changes:

  • Added a lightweight Zustand store to track the “active” conversation key.
  • Added a ConversationHotkeyBoundary to set/clear the active conversation based on focus/pointer interactions.
  • Added HotkeyRegistry (plus tests) and wired it into ConversationProvider to register message-control hotkeys within the provider context.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/features/Conversation/hotkeyStore.ts Adds global state for tracking the active conversation key.
src/features/Conversation/ConversationHotkeyBoundary.tsx Implements focus/pointer-based activation and blur-based deactivation for conversation hotkeys.
src/features/Conversation/HotkeyRegistry.tsx Registers regenerate/delete hotkeys against the per-conversation store, gated by active conversation.
src/features/Conversation/HotkeyRegistry.test.tsx Adds unit tests for enabling logic and basic action selection behavior.
src/features/Conversation/ConversationProvider.tsx Wraps provider contents with the boundary and mounts the hotkey registry.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/features/Conversation/ConversationHotkeyBoundary.tsx
Comment thread src/features/Conversation/ConversationProvider.tsx Outdated
@vercel

vercel Bot commented Mar 20, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
lobehub Ready Ready Preview, Comment Mar 20, 2026 4:07pm

Request Review

@dosubot dosubot Bot added the size:L This PR changes 100-499 lines, ignoring generated files. label May 5, 2026
@dosubot dosubot Bot added size:XL This PR changes 500-999 lines, ignoring generated files. and removed size:L This PR changes 100-499 lines, ignoring generated files. labels May 18, 2026
@dosubot dosubot Bot added size:L This PR changes 100-499 lines, ignoring generated files. and removed size:XL This PR changes 500-999 lines, ignoring generated files. labels May 21, 2026
@sxjeru sxjeru force-pushed the 31111 branch 2 times, most recently from d6b8d68 to 9b2986c Compare May 23, 2026 00:09
@sxjeru sxjeru mentioned this pull request Jun 2, 2026
12 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L This PR changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

部分快捷键失效

2 participants