Skip to content

Commit ff5a601

Browse files
committed
feat(home): add double-enter to send top queued message
1 parent 5eb494d commit ff5a601

File tree

2 files changed

+53
-2
lines changed

2 files changed

+53
-2
lines changed

apps/sim/app/workspace/[workspaceId]/home/components/mothership-chat/mothership-chat.tsx

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use client'
22

3-
import { useLayoutEffect, useRef } from 'react'
3+
import { useCallback, useEffect, useLayoutEffect, useRef } from 'react'
44
import { cn } from '@/lib/core/utils/cn'
55
import { MessageActions } from '@/app/workspace/[workspaceId]/components'
66
import { ChatMessageAttachments } from '@/app/workspace/[workspaceId]/home/components/chat-message-attachments'
@@ -99,6 +99,43 @@ export function MothershipChat({
9999
const hasMessages = messages.length > 0
100100
const initialScrollDoneRef = useRef(false)
101101

102+
const primedQueueIdRef = useRef<string | null>(null)
103+
const primeTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)
104+
const messageQueueRef = useRef(messageQueue)
105+
messageQueueRef.current = messageQueue
106+
const onSendQueuedMessageRef = useRef(onSendQueuedMessage)
107+
onSendQueuedMessageRef.current = onSendQueuedMessage
108+
109+
const clearPrimed = useCallback(() => {
110+
primedQueueIdRef.current = null
111+
if (primeTimerRef.current) {
112+
clearTimeout(primeTimerRef.current)
113+
primeTimerRef.current = null
114+
}
115+
}, [])
116+
117+
const handleEnterWhileEmpty = useCallback(() => {
118+
const topMessage = messageQueueRef.current[0]
119+
if (!topMessage) return false
120+
121+
if (primedQueueIdRef.current === topMessage.id) {
122+
clearPrimed()
123+
void onSendQueuedMessageRef.current(topMessage.id)
124+
return true
125+
}
126+
127+
primedQueueIdRef.current = topMessage.id
128+
if (primeTimerRef.current) clearTimeout(primeTimerRef.current)
129+
primeTimerRef.current = setTimeout(clearPrimed, 3000)
130+
return true
131+
}, [clearPrimed])
132+
133+
useEffect(() => {
134+
return () => {
135+
if (primeTimerRef.current) clearTimeout(primeTimerRef.current)
136+
}
137+
}, [])
138+
102139
useLayoutEffect(() => {
103140
if (!hasMessages) {
104141
initialScrollDoneRef.current = false
@@ -197,6 +234,8 @@ export function MothershipChat({
197234
onContextAdd={onContextAdd}
198235
editValue={editValue}
199236
onEditValueConsumed={onEditValueConsumed}
237+
onEnterWhileEmpty={handleEnterWhileEmpty}
238+
onPrimedDismiss={clearPrimed}
200239
/>
201240
</div>
202241
</div>

apps/sim/app/workspace/[workspaceId]/home/components/user-input/user-input.tsx

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,8 @@ interface UserInputProps {
108108
isInitialView?: boolean
109109
userId?: string
110110
onContextAdd?: (context: ChatContext) => void
111+
onEnterWhileEmpty?: () => boolean
112+
onPrimedDismiss?: () => void
111113
}
112114

113115
export function UserInput({
@@ -120,6 +122,8 @@ export function UserInput({
120122
isInitialView = true,
121123
userId,
122124
onContextAdd,
125+
onEnterWhileEmpty,
126+
onPrimedDismiss,
123127
}: UserInputProps) {
124128
const { workspaceId } = useParams<{ workspaceId: string }>()
125129
const { data: workflowsById = {} } = useWorkflowMap(workspaceId)
@@ -207,6 +211,10 @@ export function UserInput({
207211
filesRef.current = files
208212
const contextRef = useRef(contextManagement)
209213
contextRef.current = contextManagement
214+
const onEnterWhileEmptyRef = useRef(onEnterWhileEmpty)
215+
onEnterWhileEmptyRef.current = onEnterWhileEmpty
216+
const isSendingRef = useRef(isSending)
217+
isSendingRef.current = isSending
210218

211219
useEffect(() => {
212220
return () => {
@@ -447,6 +455,9 @@ export function UserInput({
447455
(e: React.KeyboardEvent<HTMLTextAreaElement>) => {
448456
if (e.key === 'Enter' && !e.shiftKey && !e.nativeEvent.isComposing) {
449457
e.preventDefault()
458+
if (isSendingRef.current && !valueRef.current.trim() && onEnterWhileEmptyRef.current?.()) {
459+
return
460+
}
450461
handleSubmit()
451462
return
452463
}
@@ -539,8 +550,9 @@ export function UserInput({
539550

540551
setValue(newValue)
541552
restartRecognition(newValue)
553+
if (newValue.trim()) onPrimedDismiss?.()
542554
},
543-
[restartRecognition]
555+
[restartRecognition, onPrimedDismiss]
544556
)
545557

546558
const handleSelectAdjust = useCallback(() => {

0 commit comments

Comments
 (0)