Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,12 @@ interface MothershipChatProps {
) => void
onStopGeneration: () => void
messageQueue: QueuedMessage[]
editingQueuedId: string | null
dispatchingHeadId: string | null
onRemoveQueuedMessage: (id: string) => void
onSendQueuedMessage: (id: string) => Promise<void>
onEditQueuedMessage: (id: string) => QueuedMessage | undefined
onCancelQueueEdit: () => void
userId?: string
chatId?: string
onContextAdd?: (context: ChatContext) => void
Expand Down Expand Up @@ -183,9 +186,12 @@ export function MothershipChat({
onSubmit,
onStopGeneration,
messageQueue,
editingQueuedId,
dispatchingHeadId,
onRemoveQueuedMessage,
onSendQueuedMessage,
onEditQueuedMessage,
onCancelQueueEdit,
userId,
chatId,
onContextAdd,
Expand Down Expand Up @@ -313,9 +319,12 @@ export function MothershipChat({
<div className={styles.footerInner}>
<QueuedMessages
messageQueue={messageQueue}
editingQueuedId={editingQueuedId}
dispatchingHeadId={dispatchingHeadId}
onRemove={onRemoveQueuedMessage}
onSendNow={onSendQueuedMessage}
onEdit={handleEditQueued}
onCancelEdit={onCancelQueueEdit}
/>
<UserInput
ref={userInputRef}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,33 @@
'use client'

import { useCallback, useRef, useState } from 'react'
import { ArrowUp, ChevronDown, ChevronRight, Paperclip, Pencil, Trash2 } from 'lucide-react'
import { ArrowUp, ChevronDown, ChevronRight, Paperclip, Pencil, Trash2, X } from 'lucide-react'
import { Tooltip } from '@/components/emcn'
import { cn } from '@/lib/core/utils/cn'
import { UserMessageContent } from '@/app/workspace/[workspaceId]/home/components/user-message-content'
import type { QueuedMessage } from '@/app/workspace/[workspaceId]/home/types'

const NARROW_WIDTH_PX = 320

interface QueuedMessagesProps {
messageQueue: QueuedMessage[]
editingQueuedId: string | null
dispatchingHeadId: string | null
onRemove: (id: string) => void
onSendNow: (id: string) => Promise<void>
onEdit: (id: string) => void
onCancelEdit: () => void
}

export function QueuedMessages({ messageQueue, onRemove, onSendNow, onEdit }: QueuedMessagesProps) {
export function QueuedMessages({
messageQueue,
editingQueuedId,
dispatchingHeadId,
onRemove,
onSendNow,
onEdit,
onCancelEdit,
}: QueuedMessagesProps) {
const [isExpanded, setIsExpanded] = useState(true)
const [isNarrow, setIsNarrow] = useState(false)
const roRef = useRef<ResizeObserver | null>(null)
Expand Down Expand Up @@ -57,101 +69,138 @@ export function QueuedMessages({ messageQueue, onRemove, onSendNow, onEdit }: Qu

{isExpanded && (
<div>
{messageQueue.map((msg) => (
<div
key={msg.id}
className='flex items-center gap-2 py-1.5 pr-2 pl-3.5 transition-colors hover-hover:bg-[var(--surface-active)]'
>
<div className='flex size-[16px] shrink-0 items-center justify-center'>
<div className='size-[10px] rounded-full border-[1.5px] border-[color-mix(in_srgb,var(--text-tertiary)_40%,transparent)]' />
</div>
{messageQueue.map((msg) => {
const isEditing = msg.id === editingQueuedId
const isDispatching = msg.id === dispatchingHeadId
return (
<div
key={msg.id}
className={cn(
'flex items-center gap-2 py-1.5 pr-2 pl-3.5 transition-colors hover-hover:bg-[var(--surface-active)]',
isEditing && 'bg-[var(--surface-active)]'
)}
>
<div className='flex size-[16px] shrink-0 items-center justify-center'>
<div
className={cn(
'size-[10px] rounded-full border-[1.5px] border-[color-mix(in_srgb,var(--text-tertiary)_40%,transparent)]',
isEditing &&
'border-[color-mix(in_srgb,var(--text-secondary)_60%,transparent)] border-dashed'
)}
/>
</div>

<div className='min-w-0 flex-1 overflow-hidden'>
<UserMessageContent
content={msg.content}
contexts={msg.contexts}
plainMentions
compact
/>
</div>
<div className='min-w-0 flex-1 overflow-hidden'>
<UserMessageContent
content={msg.content}
contexts={msg.contexts}
plainMentions
compact
/>
</div>

{msg.fileAttachments && msg.fileAttachments.length > 0 && (
<span className='inline-flex min-w-0 max-w-[40%] shrink items-center gap-1 rounded-[5px] bg-[var(--surface-5)] px-[5px] py-0.5 text-[var(--text-primary)] text-small'>
<Paperclip className='size-[12px] shrink-0 text-[var(--text-icon)]' />
{isNarrow ? (
<span className='shrink-0 text-[var(--text-secondary)]'>
{msg.fileAttachments.length}
</span>
{msg.fileAttachments && msg.fileAttachments.length > 0 && (
<span className='inline-flex min-w-0 max-w-[40%] shrink items-center gap-1 rounded-[5px] bg-[var(--surface-5)] px-[5px] py-0.5 text-[var(--text-primary)] text-small'>
<Paperclip className='size-[12px] shrink-0 text-[var(--text-icon)]' />
{isNarrow ? (
<span className='shrink-0 text-[var(--text-secondary)]'>
{msg.fileAttachments.length}
</span>
) : (
<>
<span className='truncate'>{msg.fileAttachments[0].filename}</span>
{msg.fileAttachments.length > 1 && (
<span className='shrink-0 text-[var(--text-secondary)]'>
+{msg.fileAttachments.length - 1}
</span>
)}
</>
)}
</span>
)}

<div className='flex shrink-0 items-center gap-0.5'>
{isEditing ? (
<Tooltip.Root>
<Tooltip.Trigger asChild>
<button
type='button'
onClick={(e) => {
e.stopPropagation()
onCancelEdit()
}}
className='rounded-md p-[5px] text-[var(--text-icon)] transition-colors hover-hover:bg-[var(--surface-active)] hover-hover:text-[var(--text-primary)]'
>
<X className='size-[13px]' />
</button>
</Tooltip.Trigger>
<Tooltip.Content side='top' sideOffset={4}>
Cancel edit
</Tooltip.Content>
</Tooltip.Root>
) : (
<>
<span className='truncate'>{msg.fileAttachments[0].filename}</span>
{msg.fileAttachments.length > 1 && (
<span className='shrink-0 text-[var(--text-secondary)]'>
+{msg.fileAttachments.length - 1}
</span>
)}
</>
)}
</span>
)}

<div className='flex shrink-0 items-center gap-0.5'>
<Tooltip.Root>
<Tooltip.Trigger asChild>
<button
type='button'
onClick={(e) => {
e.stopPropagation()
onEdit(msg.id)
}}
className='rounded-md p-[5px] text-[var(--text-icon)] transition-colors hover-hover:bg-[var(--surface-active)] hover-hover:text-[var(--text-primary)]'
>
<Pencil className='size-[13px]' />
</button>
</Tooltip.Trigger>
<Tooltip.Content side='top' sideOffset={4}>
Edit queued message
</Tooltip.Content>
</Tooltip.Root>
<Tooltip.Root>
<Tooltip.Trigger asChild>
<button
type='button'
disabled={isDispatching}
onClick={(e) => {
e.stopPropagation()
onEdit(msg.id)
}}
className='rounded-md p-[5px] text-[var(--text-icon)] transition-colors hover-hover:bg-[var(--surface-active)] hover-hover:text-[var(--text-primary)] disabled:cursor-not-allowed disabled:opacity-40 disabled:hover-hover:bg-transparent disabled:hover-hover:text-[var(--text-icon)]'
>
<Pencil className='size-[13px]' />
</button>
</Tooltip.Trigger>
<Tooltip.Content side='top' sideOffset={4}>
{isDispatching ? 'Sending now' : 'Edit queued message'}
</Tooltip.Content>
</Tooltip.Root>

<Tooltip.Root>
<Tooltip.Trigger asChild>
<button
type='button'
onClick={(e) => {
e.stopPropagation()
void onSendNow(msg.id)
}}
className='rounded-md p-[5px] text-[var(--text-icon)] transition-colors hover-hover:bg-[var(--surface-active)] hover-hover:text-[var(--text-primary)]'
>
<ArrowUp className='size-[13px]' />
</button>
</Tooltip.Trigger>
<Tooltip.Content side='top' sideOffset={4}>
Send now
</Tooltip.Content>
</Tooltip.Root>
<Tooltip.Root>
<Tooltip.Trigger asChild>
<button
type='button'
disabled={isDispatching}
onClick={(e) => {
e.stopPropagation()
void onSendNow(msg.id)
}}
className='rounded-md p-[5px] text-[var(--text-icon)] transition-colors hover-hover:bg-[var(--surface-active)] hover-hover:text-[var(--text-primary)] disabled:cursor-not-allowed disabled:opacity-40 disabled:hover-hover:bg-transparent disabled:hover-hover:text-[var(--text-icon)]'
>
<ArrowUp className='size-[13px]' />
</button>
</Tooltip.Trigger>
<Tooltip.Content side='top' sideOffset={4}>
Send now
</Tooltip.Content>
</Tooltip.Root>

<Tooltip.Root>
<Tooltip.Trigger asChild>
<button
type='button'
onClick={(e) => {
e.stopPropagation()
onRemove(msg.id)
}}
className='rounded-md p-[5px] text-[var(--text-icon)] transition-colors hover-hover:bg-[var(--surface-active)] hover-hover:text-[var(--text-primary)]'
>
<Trash2 className='size-[13px]' />
</button>
</Tooltip.Trigger>
<Tooltip.Content side='top' sideOffset={4}>
Remove from queue
</Tooltip.Content>
</Tooltip.Root>
<Tooltip.Root>
<Tooltip.Trigger asChild>
<button
type='button'
onClick={(e) => {
e.stopPropagation()
onRemove(msg.id)
}}
className='rounded-md p-[5px] text-[var(--text-icon)] transition-colors hover-hover:bg-[var(--surface-active)] hover-hover:text-[var(--text-primary)]'
>
<Trash2 className='size-[13px]' />
</button>
</Tooltip.Trigger>
<Tooltip.Content side='top' sideOffset={4}>
Remove from queue
</Tooltip.Content>
</Tooltip.Root>
Comment thread
waleedlatif1 marked this conversation as resolved.
</>
)}
</div>
</div>
</div>
))}
)
})}
</div>
)}
</div>
Expand Down
6 changes: 6 additions & 0 deletions apps/sim/app/workspace/[workspaceId]/home/home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,9 @@ export function Home({ chatId }: HomeProps = {}) {
removeFromQueue,
sendNow,
editQueuedMessage,
cancelQueueEdit,
editingQueuedId,
dispatchingHeadId,
previewSession,
genericResourceData,
getCurrentRequestId,
Expand Down Expand Up @@ -349,9 +352,12 @@ export function Home({ chatId }: HomeProps = {}) {
onSubmit={handleSubmit}
onStopGeneration={handleStopGeneration}
messageQueue={messageQueue}
editingQueuedId={editingQueuedId}
dispatchingHeadId={dispatchingHeadId}
onRemoveQueuedMessage={removeFromQueue}
onSendQueuedMessage={sendNow}
onEditQueuedMessage={editQueuedMessage}
onCancelQueueEdit={cancelQueueEdit}
userId={session?.user?.id}
chatId={resolvedChatId}
onContextAdd={handleContextAdd}
Expand Down
Loading
Loading