added find-in-message search to the message details viewer - #4572
added find-in-message search to the message details viewer#4572viktor-tanov wants to merge 1 commit into
Conversation
Expanded message rows render their key, value and headers in a read-only Ace viewer with no way to search the document. Ctrl-F/Command-F fell through to the browser's find, which cannot see the rows Ace virtualises out of the DOM, so large payloads were effectively unsearchable. Ace's built-in find command is replaced with one that opens an in-panel find bar, backed by a useEditorSearch hook that drives Ace's own search API. Matches are counted and highlighted, Enter/Shift+Enter step through them and Esc closes the bar. Scans are debounced and require two characters, since a single character matches nearly everywhere in a multi-megabyte message. Switching tabs resets the search, because each tab is a different document. EditorViewer gains an optional onLoad passthrough so callers can reach the underlying Ace instance; it is not invoked for the plain-text fallback, and the panel handler leaves the browser's find in place in that case. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
📝 WalkthroughWalkthroughMessage content now supports Ace-backed search with debounced matching, navigation, keyboard shortcuts, focus restoration, themed highlights, and a conditional find bar. ChangesMessage content search
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant User
participant MessageContent
participant MessageSearch
participant EditorViewer
participant useEditorSearch
participant AceEditor
User->>MessageContent: Press Ctrl-F or Command-F
MessageContent->>MessageSearch: Open find bar
MessageSearch->>MessageContent: Submit search term
MessageContent->>EditorViewer: Register Ace search command
EditorViewer-->>MessageContent: Provide Ace editor instance
MessageContent->>useEditorSearch: Update search term
useEditorSearch->>AceEditor: Search and highlight matches
AceEditor-->>useEditorSearch: Return match ranges
useEditorSearch-->>MessageSearch: Display match status
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (2)
kafka-ui-react-app/src/components/Topics/Topic/Messages/MessageContent/useEditorSearch.ts (2)
127-140: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winFlush a pending scan before stepping.
matchCountstays 0 until the debounce elapses. If the user presses Enter within 300 ms of the last keystroke,stepreturns early and the keystroke does nothing. Flush the pending scan first so the first Enter navigates.♻️ Proposed refactor
const step = React.useCallback( (direction: 1 | -1) => { - if (!editor || matchCount === 0) return; + if (!editor) return; + // Enter can arrive inside the debounce window; run the scan now so the + // keystroke is not swallowed. + runSearch.flush(); + if (matchCount === 0) return; if (direction === 1) {
matchCountis still read from the previous render in the same tick, so a follow-up state read is required for the very first Enter. An alternative is to keep the flush inMessageSearch's Enter handler.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@kafka-ui-react-app/src/components/Topics/Topic/Messages/MessageContent/useEditorSearch.ts` around lines 127 - 140, Update the step callback to flush any pending debounced search scan before checking matchCount or navigating, ensuring the first Enter within the debounce window is handled. Because the flushed scan may not update matchCount until a later render, add the necessary follow-up state handling or move the flush into MessageSearch’s Enter handler while preserving next/previous navigation and current-match updates.
45-54: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valuePass a shallow clone of
FIND_OPTIONSintoeditor.find.Ace 1.7.1 writes
options.needleand may writeoptions.startonto the object passed toEditor.find, while the module-level constant is shared across viewer instances. A shallow clone at the call site keeps the shared options constant unchanged between searches.♻️ Proposed refactor
- const found = editor.find(needle, FIND_OPTIONS); + const found = editor.find(needle, { ...FIND_OPTIONS });🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@kafka-ui-react-app/src/components/Topics/Topic/Messages/MessageContent/useEditorSearch.ts` around lines 45 - 54, Update the `editor.find` call in `useEditorSearch` to pass a shallow clone of `FIND_OPTIONS` rather than the shared constant directly, allowing Ace to add `needle` or `start` without mutating module-level search options.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In
`@kafka-ui-react-app/src/components/Topics/Topic/Messages/MessageContent/useEditorSearch.ts`:
- Around line 127-140: Update the step callback to flush any pending debounced
search scan before checking matchCount or navigating, ensuring the first Enter
within the debounce window is handled. Because the flushed scan may not update
matchCount until a later render, add the necessary follow-up state handling or
move the flush into MessageSearch’s Enter handler while preserving next/previous
navigation and current-match updates.
- Around line 45-54: Update the `editor.find` call in `useEditorSearch` to pass
a shallow clone of `FIND_OPTIONS` rather than the shared constant directly,
allowing Ace to add `needle` or `start` without mutating module-level search
options.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: b4e42671-5b28-474c-bbdc-d8360442c687
📒 Files selected for processing (10)
kafka-ui-react-app/src/components/Topics/Topic/Messages/MessageContent/MessageContent.styled.tskafka-ui-react-app/src/components/Topics/Topic/Messages/MessageContent/MessageContent.tsxkafka-ui-react-app/src/components/Topics/Topic/Messages/MessageContent/MessageSearch.styled.tskafka-ui-react-app/src/components/Topics/Topic/Messages/MessageContent/MessageSearch.tsxkafka-ui-react-app/src/components/Topics/Topic/Messages/MessageContent/__tests__/MessageContent.spec.tsxkafka-ui-react-app/src/components/Topics/Topic/Messages/MessageContent/__tests__/MessageSearch.spec.tsxkafka-ui-react-app/src/components/Topics/Topic/Messages/MessageContent/__tests__/useEditorSearch.spec.tskafka-ui-react-app/src/components/Topics/Topic/Messages/MessageContent/useEditorSearch.tskafka-ui-react-app/src/components/common/EditorViewer/EditorViewer.tsxkafka-ui-react-app/src/theme/theme.ts
Expanded message rows render their key, value and headers in a read-only Ace viewer with no way to search the document. Ctrl-F/Command-F fell through to the browser's find, which cannot see the rows Ace virtualises out of the DOM, so large payloads were effectively unsearchable.
Ace's built-in find command is replaced with one that opens an in-panel find bar, backed by a useEditorSearch hook that drives Ace's own search API. Matches are counted and highlighted, Enter/Shift+Enter step through them and Esc closes the bar. Scans are debounced and require two characters, since a single character matches nearly everywhere in a multi-megabyte message. Switching tabs resets the search, because each tab is a different document.
EditorViewer gains an optional onLoad passthrough so callers can reach the underlying Ace instance; it is not invoked for the plain-text fallback, and the panel handler leaves the browser's find in place in that case.
What changes did you make? (Give an overview)
Is there anything you'd like reviewers to focus on?
How Has This Been Tested? (put an "x" (case-sensitive!) next to an item)
Checklist (put an "x" (case-sensitive!) next to all the items, otherwise the build will fail)
Check out Contributing and Code of Conduct
Summary by CodeRabbit
New Features
Bug Fixes