Spaces:
Sleeping
Sleeping
'use client' | |
import * as React from 'react' | |
import { type DialogProps } from '@radix-ui/react-dialog' | |
import { toast } from 'react-hot-toast' | |
import { ServerActionResult, type Chat } from '@/lib/types' | |
import { Button } from '@/components/ui/button' | |
import { | |
Dialog, | |
DialogContent, | |
DialogDescription, | |
DialogFooter, | |
DialogHeader, | |
DialogTitle | |
} from '@/components/ui/dialog' | |
import { IconSpinner } from '@/components/ui/icons' | |
import { useCopyToClipboard } from '@/lib/hooks/use-copy-to-clipboard' | |
interface ChatShareDialogProps extends DialogProps { | |
chat: Pick<Chat, 'id' | 'title' | 'messages'> | |
shareChat: (id: string) => ServerActionResult<Chat> | |
onCopy: () => void | |
} | |
export function ChatShareDialog({ | |
chat, | |
shareChat, | |
onCopy, | |
...props | |
}: ChatShareDialogProps) { | |
const { copyToClipboard } = useCopyToClipboard({ timeout: 1000 }) | |
const [isSharePending, startShareTransition] = React.useTransition() | |
const copyShareLink = React.useCallback( | |
async (chat: Chat) => { | |
if (!chat.sharePath) { | |
return toast.error('Could not copy share link to clipboard') | |
} | |
const url = new URL(window.location.href) | |
url.pathname = chat.sharePath | |
copyToClipboard(url.toString()) | |
onCopy() | |
toast.success('Share link copied to clipboard', { | |
style: { | |
borderRadius: '10px', | |
background: '#333', | |
color: '#fff', | |
fontSize: '14px' | |
}, | |
iconTheme: { | |
primary: 'white', | |
secondary: 'black' | |
} | |
}) | |
}, | |
[copyToClipboard, onCopy] | |
) | |
return ( | |
<Dialog {...props}> | |
<DialogContent> | |
<DialogHeader> | |
<DialogTitle>Share link to chat</DialogTitle> | |
<DialogDescription> | |
Anyone with the URL will be able to view the shared chat. | |
</DialogDescription> | |
</DialogHeader> | |
<div className="p-4 space-y-1 text-sm border rounded-md"> | |
<div className="font-medium">{chat.title}</div> | |
<div className="text-muted-foreground"> | |
{chat.messages.length} messages | |
</div> | |
</div> | |
<DialogFooter className="items-center"> | |
<Button | |
disabled={isSharePending} | |
onClick={() => { | |
// @ts-ignore | |
startShareTransition(async () => { | |
const result = await shareChat(chat.id) | |
if (result && 'error' in result) { | |
toast.error(result.error) | |
return | |
} | |
copyShareLink(result) | |
}) | |
}} | |
> | |
{isSharePending ? ( | |
<> | |
<IconSpinner className="mr-2 animate-spin" /> | |
Copying... | |
</> | |
) : ( | |
<>Copy link</> | |
)} | |
</Button> | |
</DialogFooter> | |
</DialogContent> | |
</Dialog> | |
) | |
} | |