Add live duplicate check to the new-entry dialog#2433
Draft
myieye wants to merge 10 commits into
Draft
Conversation
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Spec-cited review against EntrySearchService/SqlHelpers found the client fold diverged: host-locale lowercasing, unconditional accent-stripping (backend keeps diacritics significant when the query has them), and no morph-token handling (typed "-aji" vs suffix entry "aji" missed exact). Also ranks each search by the writing system it was typed in, fixes the mount-time "Checking" flash, singularizes the one-match banner, and closes a pre-existing double-Enter double-create in the dialog. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- match rows expand to reveal Add sense / Go to entry; DictionaryEntry gains an inline mode for the compact collapsed rows - classification: attribute same-word matches to the field that hit (Same headword vs Same lexeme form), rank similar words closest-in-length first, drop cross-field coincidences instead of a vague 'related' kind - classify in a $derived so the lazy morph-types resource warms at mount and re-classifies without re-searching - dedupe queries per field kind: the same text typed as lexeme and gloss keeps its gloss query (same-meaning matches were lost) - share the banner message/tint/Enter-trap between the strip and the extracted DuplicateSummaryPill - scope backend-parity doc claims to the CRDT FTS path; drop unverified FLEx attribution - adapt the Playwright suite to the new interaction model and cover the jump pill (7 tests); pin length-delta boundary, gloss containment direction, and closest-form ranking in unit tests (33; 8/8 targeted mutants killed) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…icates # Conflicts: # frontend/viewer/src/locales/en.po # frontend/viewer/src/locales/es.po # frontend/viewer/src/locales/fr.po # frontend/viewer/src/locales/id.po # frontend/viewer/src/locales/ko.po # frontend/viewer/src/locales/ms.po # frontend/viewer/src/locales/sw.po # frontend/viewer/src/locales/vi.po
…etection-review-ny053c
…fill test gaps - Move new-entry-duplicates.test.ts to tests/ui/ and port it to the DemoProjectPage page object introduced by the E2E restructure (#1866) - Cap the jump pill at 32rem so long headword previews don't stretch it across the whole dialog - New tests: trapEnter unit test, Enter-inside-strip must not create the entry, pill dismiss persists, add-sense must not also create an entry Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01R49zrCE7hPgm9QJ5bfugaV
A failed searchEntries call previously vanished into the unread resource.error — no toast, no status line, the widget just went blank. Show an inline status line instead of a toast: the search re-fires per typing pause, and a toast per failure would bury the dialog. Show-more now uses $plural so translators get per-language plural forms. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01R49zrCE7hPgm9QJ5bfugaV
This reverts commit d267bd1.
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ 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 |
4 tasks
|
The latest updates on your projects. Learn more about Argos notifications ↗︎
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Searches existing entries as you type in the new-entry dialog and surfaces likely duplicates before you save.
Resolves #1752. Supersedes #2411 (same feature, this branch = #2411 + latest
develop+ review fixes below; the review didn't change the feature's direction, UI, or architecture).What it does
duplicate-check.ts— debounced multi-field search (headword/citation/gloss) via the existing FTSsearchEntries; results classified as same word / similar word / similar meaning and ranked strongest-first. Cross-field coincidences (a typed vernacular value that only hit a gloss, or vice versa) are dropped as noise. Classification mirrors the backend match semantics — every parity claim in the file's comments was re-verified against the actual backend code this round (invariant case fold + diacritics significant only when typed,EntrySearchService.StripMorphTokensexact mirror incl. scoring and the postfix-length guard, FwData's no-strip behavior, the <3-char FTS fallback). Collation equivalences (ß≈ss, ligatures, ICU-ignorables) are not replicated, as documented in the file.DuplicateCheck.svelte— collapsible strip inNewEntryDialog.svelte(amber when the word already exists); auto-expands on an exact word match; rows expand in place for "Add sense" / "Go to entry"; "Show N more" for long lists; quiet green "Looks like a new word" when nothing matches.DuplicateSummaryPill.svelte— sticky pill shown when the strip scrolls out of view; click jumps back and expands; dismissible.Changes since #2411
develop, absorbing the E2e test fw lite #1866 E2E-test restructure: the feature's Playwright suite moved totests/ui/and now uses the newDemoProjectPagepage object (the oldBrowsePageit imported was deleted on develop — Add live duplicate check to the new-entry dialog #2411 as-is no longer runs its tests).duplicatesResource.errorwas never read: a failedsearchEntries(e.g. connection loss on a server-hosted session) made the widget silently go blank. Now an inline status line says "Could not check for similar entries"; typing again retries. Deliberately not anAppNotification.errortoast (theEditEntryDialog/ActivityViewprecedent): this search re-fires on every typing pause, and a toast per failure would bury the dialog — the strip already owns a status line.$pluralso translators get per-language plural forms (matches theSyncDialogconvention).trapEnterunit test; Enter pressed inside the strip expands the row and does not create the entry (asserted via entry count); add-sense asserts no duplicate entry was created alongside the rescued sense; pill dismissal persists while matches keep changing.The CodeRabbit race on #2411 (go-to-entry clickable during a pending add-sense) was already fixed there in ad8bfa5 — re-verified here: both row actions disable on
busy, and the dialog's Create honors it.Screenshots
Exact match (amber strip, auto-expanded, light/dark verified):

Row expanded in place with rescue actions:

Jump pill when the strip is out of view (now width-capped):

New word / similar-only (collapsed, muted):


Dark mode spot-checks: exact match · row actions
(Screenshots were committed in d267bd1 and reverted in the next commit, so they don't live on the branch.)
Test evidence
vitest --project unit duplicate-check.test.ts: 34/34 passplaywright -c tests/ui new-entry-duplicates: 9/9 pass (7 ported + 2 new)svelte-check: 0 errors / 0 warnings;eslinton all touched files: cleanReviewer notes / merge interactions
DictionaryEntry.svelte; this PR adds theinlineprop there. Whoever merges second gets a small conflict in the props block + sense-separator markup — keep both changes.src/locales/*.po→ guaranteed extraction conflicts. Resolution: take either side, re-runpnpm run i18n:extract, commit.SortField.SearchRelevance(sorts alphabetically) — the UI tests exercise classification, not backend ranking. Real ranking is covered by the backend's own tests.duplicate-check.ts).Considered and rejected (carried over from #2411)
🤖 Generated with Claude Code
https://claude.ai/code/session_01R49zrCE7hPgm9QJ5bfugaV
Generated by Claude Code