Skip to content

Commit bee1381

Browse files
committed
fix(chat): reset replaced queries and bound workspace previews
1 parent 5c0dd03 commit bee1381

3 files changed

Lines changed: 64 additions & 37 deletions

File tree

‎apps/sim/app/workspace/[workspaceId]/home/components/user-input/components/plus-menu-dropdown/plus-menu-dropdown.tsx‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,9 @@ export const PlusMenuDropdown = React.memo(
233233
const filteredItems = useMemo((): MentionCandidate[] | null => {
234234
const q = query.toLowerCase().trim()
235235
if (!isMention && !q) return null
236-
const workspaceItems: MentionCandidate[] = workspaces
236+
const workspaceItems: MentionCandidate[] = (
237+
q ? workspaces : workspaces.slice(0, MENTION_PREVIEW_DEFAULT_LIMIT)
238+
)
237239
.filter((workspace) => workspace.name.toLowerCase().includes(q))
238240
.map((item) => ({ type: 'workspace', item }))
239241
const resourceItems = q

‎apps/sim/app/workspace/[workspaceId]/home/components/user-input/components/prompt-editor/use-prompt-editor.test.tsx‎

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -166,27 +166,41 @@ describe.each([{ workspaceId: 'ws-1' }, { workspaceId: '', organizationId: 'org-
166166
}
167167
})
168168

169-
it('opens a fresh search when replacing a selected dismissed trigger', () => {
170-
const { result, textarea, unmount } = renderPromptEditor(scope)
171-
const input = (value: string) => {
172-
act(() => {
173-
typeInto(textarea, value)
174-
result().handleInputChange({ target: textarea } as React.ChangeEvent<HTMLTextAreaElement>)
175-
})
176-
}
177-
try {
178-
input('@Quarterly')
179-
act(() => result().handlePlusMenuClose())
180-
act(() => {
181-
textarea.setSelectionRange(0, textarea.value.length)
182-
result().handleSelectAdjust()
183-
})
184-
input('@Roadmap')
185-
expect(result().mentionQuery).toBe('Roadmap')
186-
} finally {
187-
unmount()
169+
it.each(['selection', 'programmatic'])(
170+
'opens a fresh search when replacing a dismissed trigger via %s',
171+
(replacement) => {
172+
const { result, textarea, unmount } = renderPromptEditor(scope)
173+
const input = (value: string) => {
174+
act(() => {
175+
typeInto(textarea, value)
176+
result().handleInputChange({
177+
target: textarea,
178+
} as React.ChangeEvent<HTMLTextAreaElement>)
179+
})
180+
}
181+
try {
182+
input('@Quarterly')
183+
act(() => result().handlePlusMenuClose())
184+
if (replacement === 'selection') {
185+
act(() => {
186+
textarea.setSelectionRange(0, textarea.value.length)
187+
result().handleSelectAdjust()
188+
})
189+
expect(result().mentionQuery).toBeNull()
190+
input('@Roadmap')
191+
} else {
192+
act(() => result().setValue('@Roadmap', { chipify: false }))
193+
act(() => {
194+
typeInto(textarea, result().getValue())
195+
result().handleSelectAdjust()
196+
})
197+
}
198+
expect(result().mentionQuery).toBe('Roadmap')
199+
} finally {
200+
unmount()
201+
}
188202
}
189-
})
203+
)
190204

191205
it.each(['@ ', '@ name', '@Quarterly\n', 'person@example.com'])(
192206
'does not search across a dismissed boundary in %j',

‎apps/sim/app/workspace/[workspaceId]/home/components/user-input/components/prompt-editor/use-prompt-editor.ts‎

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ export function usePromptEditor({
220220
* (outside click or Escape). Mention dismissal lasts until the caret leaves
221221
* that query; slash dismissal lasts until the next edit.
222222
*/
223-
const dismissedMentionStartRef = useRef<number | null>(null)
223+
const dismissedMentionRef = useRef<{ start: number; triggerSelected: boolean } | null>(null)
224224
const dismissedSlashStartRef = useRef<number | null>(null)
225225

226226
const contextManagement = useContextManagement({
@@ -337,6 +337,16 @@ export function usePromptEditor({
337337
*/
338338
const setValue = useCallback((text: string, options?: { chipify?: boolean }) => {
339339
const next = options?.chipify === false ? text : applyAutoMentionsRef.current(text)
340+
atInsertPosRef.current = null
341+
pendingCursorRef.current = null
342+
mentionRangeRef.current = null
343+
dismissedMentionRef.current = null
344+
setMentionQuery(null)
345+
plusMenuRef.current?.close()
346+
slashRangeRef.current = null
347+
dismissedSlashStartRef.current = null
348+
setSlashQuery(null)
349+
skillsMenuRef.current?.close()
340350
valueRef.current = next
341351
setValueState(next)
342352
}, [])
@@ -410,7 +420,7 @@ export function usePromptEditor({
410420
atInsertPosRef.current = null
411421
mentionRangeRef.current = null
412422
setMentionQuery(null)
413-
dismissedMentionStartRef.current = null
423+
dismissedMentionRef.current = null
414424
plusMenuRef.current?.close()
415425
slashRangeRef.current = null
416426
setSlashQuery(null)
@@ -438,7 +448,7 @@ export function usePromptEditor({
438448
plusMenuRef.current?.close()
439449
mentionRangeRef.current = null
440450
setMentionQuery(null)
441-
dismissedMentionStartRef.current = null
451+
dismissedMentionRef.current = null
442452
skillsMenuRef.current?.close()
443453
slashRangeRef.current = null
444454
setSlashQuery(null)
@@ -492,7 +502,7 @@ export function usePromptEditor({
492502
atInsertPosRef.current = newPos
493503
mentionRangeRef.current = null
494504
setMentionQuery(null)
495-
dismissedMentionStartRef.current = null
505+
dismissedMentionRef.current = null
496506
setValueState(newValue)
497507
}
498508

@@ -692,7 +702,9 @@ export function usePromptEditor({
692702
* `onOpenChange` and never call this.
693703
*/
694704
const handlePlusMenuClose = useCallback(() => {
695-
dismissedMentionStartRef.current = mentionRangeRef.current?.start ?? null
705+
dismissedMentionRef.current = mentionRangeRef.current
706+
? { start: mentionRangeRef.current.start, triggerSelected: false }
707+
: null
696708
atInsertPosRef.current = null
697709
mentionRangeRef.current = null
698710
setMentionQuery(null)
@@ -707,13 +719,11 @@ export function usePromptEditor({
707719
const syncMentionState = useCallback(
708720
(textarea: HTMLTextAreaElement, text: string, caret: number) => {
709721
if (!contextsEnabledRef.current) return
710-
const dismissedStart = dismissedMentionStartRef.current
711-
if (
712-
dismissedStart !== null &&
713-
textarea.selectionStart <= dismissedStart &&
714-
textarea.selectionEnd > dismissedStart
715-
) {
716-
dismissedMentionStartRef.current = null
722+
const dismissed = dismissedMentionRef.current
723+
if (dismissed) {
724+
dismissed.triggerSelected =
725+
textarea.selectionStart <= dismissed.start && textarea.selectionEnd > dismissed.start
726+
if (dismissed.triggerSelected) return
717727
}
718728
const active = getActiveMentionAtRef.current(caret, text)
719729
const isOpenable = active && !/[\r\n]/.test(active.query)
@@ -723,18 +733,18 @@ export function usePromptEditor({
723733
setMentionQuery(null)
724734
plusMenuRef.current?.close()
725735
}
726-
dismissedMentionStartRef.current = null
736+
dismissedMentionRef.current = null
727737
return
728738
}
729739

730-
if (active.start === dismissedMentionStartRef.current) {
740+
if (active.start === dismissedMentionRef.current?.start) {
731741
if (mentionRangeRef.current !== null) {
732742
mentionRangeRef.current = null
733743
setMentionQuery(null)
734744
}
735745
return
736746
}
737-
dismissedMentionStartRef.current = null
747+
dismissedMentionRef.current = null
738748

739749
const wasActive = mentionRangeRef.current !== null
740750
mentionRangeRef.current = { start: active.start, end: active.end }
@@ -829,7 +839,8 @@ export function usePromptEditor({
829839
const previousValue = valueRef.current
830840
const nextValue = e.target.value
831841
const hasMentionQuery =
832-
mentionRangeRef.current !== null || dismissedMentionStartRef.current !== null
842+
mentionRangeRef.current !== null || dismissedMentionRef.current !== null
843+
if (dismissedMentionRef.current?.triggerSelected) dismissedMentionRef.current = null
833844

834845
let finalValue = nextValue
835846
if (

0 commit comments

Comments
 (0)