diff --git a/app/actions.ts b/app/actions.ts index 849bcd3..26d4755 100644 --- a/app/actions.ts +++ b/app/actions.ts @@ -2,10 +2,9 @@ import { revalidatePath } from 'next/cache' import { kv } from '@vercel/kv' +import { currentUser } from '@clerk/nextjs' import { type Chat } from '@/lib/types' -import { currentUser } from '@clerk/nextjs' -import { nanoid } from '@/lib/utils' export async function getChats(userId?: string | null) { if (!userId) { @@ -52,9 +51,11 @@ export async function removeChat({ id, path }: { id: string; path: string }) { } const uid = await kv.hget(`chat:${id}`, 'userId') + if (uid !== user.id) { throw new Error('Unauthorized') } + await kv.del(`chat:${id}`) await kv.zrem(`user:chat:${user.id}`, `chat:${id}`) @@ -85,6 +86,16 @@ export async function clearChats() { revalidatePath('/') } +export async function getSharedChat(id: string) { + const chat = await kv.hgetall(`chat:${id}`) + + if (!chat || !chat.sharePath) { + return null + } + + return chat +} + export async function shareChat(chat: Chat) { const user = await currentUser() @@ -92,23 +103,12 @@ export async function shareChat(chat: Chat) { throw new Error('Unauthorized') } - const id = nanoid() - const createdAt = Date.now() - const payload = { - id, - title: chat.title, - userId: user.id, - createdAt, - path: `/share/${id}`, - chat + ...chat, + sharePath: `/share/${chat.id}` } - await kv.hmset(`share:${id}`, payload) - await kv.zadd(`user:share:${user.id}`, { - score: createdAt, - member: `share:${id}` - }) + await kv.hmset(`chat:${chat.id}`, payload) return payload } diff --git a/app/layout.tsx b/app/layout.tsx index 063856d..7662f9e 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -7,7 +7,7 @@ import '@/app/globals.css' import { fontMono, fontSans } from '@/lib/fonts' import { cn } from '@/lib/utils' import { TailwindIndicator } from '@/components/tailwind-indicator' -import { ThemeProvider } from '@/components/theme-provider' +import { Providers } from '@/components/providers' import { Header } from '@/components/header' export const metadata: Metadata = { @@ -44,14 +44,14 @@ export default function RootLayout({ children }: RootLayoutProps) { )} > - +
{/* @ts-ignore */}
{children}
-
+ diff --git a/app/share/[id]/page.tsx b/app/share/[id]/page.tsx new file mode 100644 index 0000000..e487cd2 --- /dev/null +++ b/app/share/[id]/page.tsx @@ -0,0 +1,35 @@ +import { type Metadata } from 'next' +import { auth } from '@clerk/nextjs' + +import { Chat } from '@/components/chat' +import { getChat, getSharedChat } from '@/app/actions' +import { notFound } from 'next/navigation' + +// export const runtime = 'edge' +export const preferredRegion = 'home' + +export interface SharePageProps { + params: { + id: string + } +} + +export async function generateMetadata({ + params +}: SharePageProps): Promise { + const { user } = await auth() + const chat = await getChat(params.id, user?.id ?? '') + return { + title: chat?.title.slice(0, 50) ?? 'Chat' + } +} + +export default async function SharePage({ params }: SharePageProps) { + const chat = await getSharedChat(params.id) + + if (!chat || !chat?.sharePath) { + notFound() + } + + return +} diff --git a/components/prompt-form.tsx b/components/prompt-form.tsx index 2dec66a..3656407 100644 --- a/components/prompt-form.tsx +++ b/components/prompt-form.tsx @@ -9,7 +9,6 @@ import { Button, buttonVariants } from '@/components/ui/button' import { Tooltip, TooltipContent, - TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip' import { IconArrowElbow, IconPlus } from '@/components/ui/icons' @@ -47,51 +46,49 @@ export function PromptForm({ }} ref={formRef} > - -
+
+ + + + + New Chat + + + New Chat + +