feat(ui): add responsive search & filter to Voice Library and Main Editor (fixes #966) - #1016
feat(ui): add responsive search & filter to Voice Library and Main Editor (fixes #966)#1016devangkantharia wants to merge 4 commits into
Conversation
…iles and add Hindi to qwen engine
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
📝 WalkthroughWalkthroughThe PR adds searchable and filterable voice-profile lists, ChangesVoice profile experience
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant User
participant VoicesTab
participant useImportProfile
participant Toast
User->>VoicesTab: Select .voicebox.zip file
VoicesTab->>VoicesTab: Validate file and request confirmation
User->>VoicesTab: Confirm import
VoicesTab->>useImportProfile: Import profile
useImportProfile-->>VoicesTab: Return success or error
VoicesTab->>Toast: Show import result
Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 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.
Actionable comments posted: 5
🤖 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.
Inline comments:
In `@app/src/components/MainEditor/MainEditor.tsx`:
- Around line 117-124: Add the localized clear-search accessible name
aria-label={t('main.clearSearch')} to the button in MainEditor.tsx at lines
117-124 and the corresponding button in VoicesTab.tsx at lines 236-243,
preserving their existing behavior and styling.
In `@app/src/components/VoiceProfiles/ProfileList.tsx`:
- Around line 120-122: Update the query-specific empty-state paragraph in the
ProfileList component to use the existing t() translation function with an
interpolated search query. Add or reuse a translation key containing the search
placeholder, and preserve the current message and styling for locales with the
translated text.
In `@app/src/components/VoicesTab/VoicesTab.tsx`:
- Around line 72-74: Update the search matching logic in VoicesTab to assign q
from search.trim() before lowercasing, so surrounding whitespace is excluded
from matching while preserving the existing case-insensitive name search.
- Around line 352-369: Use a shared dialog-close handler for the Dialog’s
onOpenChange and the cancel button so every close path sets importDialogOpen to
false, clears selectedFile, and resets fileInputRef.current.value. Replace the
inline cancel cleanup while preserving the existing import dialog behavior.
In `@app/src/lib/constants/languages.ts`:
- Line 42: Remove Hindi (`hi`) from the `qwen`, `qwen_custom_voice`, and `tada`
language maps in the language constants, while preserving it for backends that
explicitly support Hindi.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 09b8bb20-72cc-422d-bf64-46559ef11ece
📒 Files selected for processing (9)
app/src/components/Generation/FloatingGenerateBox.tsxapp/src/components/History/HistoryTable.tsxapp/src/components/MainEditor/MainEditor.tsxapp/src/components/VoiceProfiles/ProfileCard.tsxapp/src/components/VoiceProfiles/ProfileList.tsxapp/src/components/VoicesTab/VoicesTab.tsxapp/src/i18n/locales/en/translation.jsonapp/src/index.cssapp/src/lib/constants/languages.ts
…zation, and dialog cleanup
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
app/src/components/VoicesTab/VoicesTab.tsx (1)
102-109: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winReset the file input after rejecting an invalid file.
At Line 108, the handler returns without clearing the input value. If the user selects the same invalid file again, the browser may not emit another
changeevent, so the user receives no new feedback. Cleare.target.valuebefore returning.Proposed fix
if (!file.name.endsWith('.voicebox.zip')) { + e.target.value = ''; toast({ title: t('main.import.invalidTitle'), description: t('main.import.invalidDescription'), variant: 'destructive', });🤖 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 `@app/src/components/VoicesTab/VoicesTab.tsx` around lines 102 - 109, In the invalid-file branch of the file change handler in VoicesTab, clear the file input value via e.target.value before returning after the destructive toast, so selecting the same invalid file again triggers a new change event.
🤖 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.
Outside diff comments:
In `@app/src/components/VoicesTab/VoicesTab.tsx`:
- Around line 102-109: In the invalid-file branch of the file change handler in
VoicesTab, clear the file input value via e.target.value before returning after
the destructive toast, so selecting the same invalid file again triggers a new
change event.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 194f3adc-5049-4d1c-9958-25b1d973a7b5
📒 Files selected for processing (4)
app/src/components/MainEditor/MainEditor.tsxapp/src/components/VoiceProfiles/ProfileList.tsxapp/src/components/VoicesTab/VoicesTab.tsxapp/src/i18n/locales/en/translation.json
🚧 Files skipped from review as they are similar to previous changes (3)
- app/src/i18n/locales/en/translation.json
- app/src/components/MainEditor/MainEditor.tsx
- app/src/components/VoiceProfiles/ProfileList.tsx
|
Heads-up on a file overlap rather than a review comment — no objection to this PR, the two changes are complementary. #1005 (folders + list view for voices and clips) touches three of the same files:
Search and folders want to compose — filter within a folder is the natural end state — but whichever of these lands second will need a rebase through those three files. Flagging so @jamiepine can sequence rather than discover it at merge time. If this one goes first I'll take the rebase on my side. One clarification for #966 while I'm here: the Voices tab already has a search box on |
…mposes jamiepine#1016 adds voice search and threads a query into ProfileList as a prop. This branch rewrites the same component for folders and a card/list toggle, so the two collide in exactly one file. Rather than leave that to whoever rebases second, ProfileList now takes the same `search` prop and does the filtering folder-aware. Filtering happens before bucketing, which is the part that only makes sense once both features exist: a match stays in the folder it belongs to instead of collapsing into one flat list. Folders with no matches are hidden while a query is active -- a wall of empty folder headers is noise -- but they come back when the query clears, since the header is also the drop target for filing a voice. The match predicate is jamiepine#1016's (name, description, language, preset_engine, default_engine), and so is the alphabetical tiebreak in the sort; without it the order inside a folder is whatever the API returned. Their selected-profile-first rule is deliberately not adopted -- it reads differently once voices are grouped, and it interacts with the scroll-into-view effect above, so that is a UX call for the author of jamiepine#1016 and the maintainer, not one to make silently here. `profiles.list.noVoicesMatch` is added in all nine locales rather than English only, so the string is not left half-translated. No search box is added here. The input, the VoicesTab filters and the layout work stay in jamiepine#1016; this is only the seam it plugs into. Refs jamiepine#1016, jamiepine#966 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Following up on my earlier comment — I went and read both diffs properly rather than leaving it at "these will conflict", and then did something about it. Summary: the real overlap is one file, and I've made my side of it accept your search prop, so this PR should end up smaller rather than fighting mine. The overlap is narrower than the file list suggestsOf the three shared files, two are non-issues:
What I changed on my branch
I used your match predicate as-is (name, description, language, preset_engine, default_engine) and your alphabetical sort tiebreak — that one's a straight improvement over what I had, which left intra-folder order to whatever the API returned. Also added No search box on my side. The input, the VoicesTab filters, If #1005 lands first, your Two things I deliberately did not decideSelected-profile-first sorting. Your sort is supported → selected → alphabetical. I took the alphabetical part but not selected-first: with voices grouped into folders it reads differently, and it interacts with the scroll-into-view effect directly above it (selecting reorders, then the effect scrolls to the moved card). Might be fine, might be jumpy — that's yours and @jamiepine's call, and easy to add on top of what I've pushed. The layout rework — @jamiepine, this one needs you. This PR isn't only search. It also changes I'm not claiming mine is better — the horizontal scroll on narrow viewports is genuinely awkward and this may well be the right fix. But it's a product decision bundled into a search PR, it's the one part that can't be mechanically composed with folder sections, and whichever of us defers should do it deliberately rather than at rebase time. Splitting the layout change into its own PR would make both of these trivial to land. Happy to take the rebase on my side either way — just say which order you want. |
|
Thanks @Lvigentini for the thoughtful review and for proactively updating your branch 3addcb1 to integrate the search props! Really appreciate the great collaboration. 👍 To share a bit of context on the layout adjustments in When testing the search feature on smaller window sizes and split-screen views, I noticed that single-row horizontal scrolling caused cards to clip and obscured the history table behind the floating input bar. To make searching and browsing voices feel smooth on all screen sizes, I added a few responsive polish details alongside the search bar:
I felt these layout details made the search experience feel more cohesive on smaller screens, but I am completely open to @jamiepine's guidance on whether to keep them together or split/sequence them alongside PR #1005! 🙌 |
Summary
This PR implements search and filtering capabilities across the Generate Tab (
MainEditor.tsx) and Voice Library (VoicesTab.tsx) to solve #966.Users can now instantly search profiles by text query or filter them by voice type and language instead of manually scrolling through the list.
What Was Added
Live Search Bar (
MainEditor.tsx&VoicesTab.tsx):Xclear search button.Voice Type & Language Filters (
VoicesTab.tsx):Preset(built-in models),Cloned(voice reference samples), orDesigned(character prompts).English,Spanish,French,German,Hindi,Japanese, etc.).Empty States & i18n Localization:
translation.json.Changed Files
app/src/components/MainEditor/MainEditor.tsx– Added search bar and search state under the main header row.app/src/components/VoiceProfiles/ProfileList.tsx– Added search filtering and empty search state card.app/src/components/VoicesTab/VoicesTab.tsx– Redesigned header toolbar with search bar, Voice Type filter, Language filter, and reset button.app/src/i18n/locales/en/translation.json– Added i18n keys for search & filter UI text.app/src/components/Generation/FloatingGenerateBox.tsx&languages.ts– Fixed engine auto-switching sequence for profile selection and language code mapping.Summary by CodeRabbit
.voicebox.zipfiles with confirmation and success/error feedback.