refactor(transcription): hoist @mention constants to shared module
Single source of truth for MAX_QUERY_LENGTH, SEARCH_DEBOUNCE_MS, and SEARCH_RESULT_LIMIT — MentionDropdown imports MAX_QUERY_LENGTH; PersonMentionEditor imports the debounce + result-limit; the spec's mirror now imports SEARCH_DEBOUNCE_MS so it can never drift. Unblocks the displayName length-cap fix (Felix #3 on PR #629). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -4,17 +4,18 @@ import type { components } from '$lib/generated/api';
|
||||
import { formatLifeDateRange } from '$lib/person/personLifeDates';
|
||||
import { untrack } from 'svelte';
|
||||
import { m } from '$lib/paraglide/messages.js';
|
||||
|
||||
type Person = components['schemas']['Person'];
|
||||
|
||||
// Layered defence cap on the @mention search query length (CWE-400
|
||||
// amplification). The <input maxlength> attribute below caps direct
|
||||
// user edits, but the editor-mirror path (Tiptap contenteditable -> mirror
|
||||
// $effect -> searchQuery) is not covered by `maxlength` since the
|
||||
// contenteditable has no such enforcement. Clipping at the mirror keeps
|
||||
// the cap honest from both paths. Tracked server-side separately.
|
||||
// Nora #1 on PR #629.
|
||||
const MAX_QUERY_LENGTH = 100;
|
||||
// Nora #1 on PR #629. Hoisted to mentionConstants.ts so the host editor
|
||||
// (PersonMentionEditor) can clip the inserted displayName to the same cap
|
||||
// — see Felix #3 on PR #629.
|
||||
import { MAX_QUERY_LENGTH } from './mentionConstants';
|
||||
|
||||
type Person = components['schemas']['Person'];
|
||||
|
||||
// The dropdown receives a single reactive state object. PersonMentionEditor
|
||||
// mutates fields on this object (model.items = ..., etc.) and Svelte's $state
|
||||
|
||||
@@ -9,9 +9,7 @@ import type { PersonMention } from '$lib/shared/types';
|
||||
import { deserialize, serialize } from '$lib/shared/discussion/mentionSerializer';
|
||||
import { debounce } from '$lib/shared/utils/debounce';
|
||||
import MentionDropdown from './MentionDropdown.svelte';
|
||||
|
||||
const SEARCH_DEBOUNCE_MS = 150;
|
||||
const SEARCH_RESULT_LIMIT = 5;
|
||||
import { SEARCH_DEBOUNCE_MS, SEARCH_RESULT_LIMIT } from './mentionConstants';
|
||||
|
||||
type Person = components['schemas']['Person'];
|
||||
|
||||
|
||||
@@ -11,14 +11,14 @@ import { page, userEvent } from 'vitest/browser';
|
||||
import PersonMentionEditorHost from './PersonMentionEditor.test-host.svelte';
|
||||
import type { components } from '$lib/generated/api';
|
||||
import { m } from '$lib/paraglide/messages.js';
|
||||
// Single source of truth for the debounce window — imported from the shared
|
||||
// module so the test cannot drift from production. Sara on PR #629 round 3.
|
||||
import { SEARCH_DEBOUNCE_MS } from './mentionConstants';
|
||||
|
||||
type Person = components['schemas']['Person'];
|
||||
type PersonMention = components['schemas']['PersonMention'];
|
||||
|
||||
// Mirror of the debounce in PersonMentionEditor.svelte. Naming the magic and
|
||||
// using a generous slack (SEARCH_DEBOUNCE_MS + 350 = 500 ms) kills CI-jitter
|
||||
// flakiness Sara raised on PR #629.
|
||||
const SEARCH_DEBOUNCE_MS = 150;
|
||||
// Slack on top of the debounce to absorb CI jitter (total 500 ms is generous).
|
||||
const POST_DEBOUNCE_SLACK_MS = 350;
|
||||
|
||||
const AUGUSTE: Person = {
|
||||
|
||||
6
frontend/src/lib/shared/discussion/mentionConstants.ts
Normal file
6
frontend/src/lib/shared/discussion/mentionConstants.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
/** Shared knobs for the @mention typeahead. Single source of truth for
|
||||
* the dropdown component and the host editor — keeps the layered length
|
||||
* cap and the debounce window consistent across both files. */
|
||||
export const MAX_QUERY_LENGTH = 100;
|
||||
export const SEARCH_DEBOUNCE_MS = 150;
|
||||
export const SEARCH_RESULT_LIMIT = 5;
|
||||
Reference in New Issue
Block a user