diff --git a/page-share.md b/page-share.md new file mode 100644 index 0000000..34be44d --- /dev/null +++ b/page-share.md @@ -0,0 +1,2 @@ +# Page Share + diff --git a/src/components/Common/ShareBtn.tsx b/src/components/Common/ShareBtn.tsx new file mode 100644 index 0000000..395b216 --- /dev/null +++ b/src/components/Common/ShareBtn.tsx @@ -0,0 +1,193 @@ +import { Form, Image, Input, Modal, Tooltip, message } from "antd" +import { Share } from "lucide-react" +import { useState } from "react" +import type { Message } from "~store/option" +import Markdown from "./Markdown" +import React from "react" +import { useMutation } from "@tanstack/react-query" +import { getPageShareUrl } from "~services/ollama" +import { cleanUrl } from "~libs/clean-url" +import { getUserId, saveWebshare } from "~libs/db" + +type Props = { + messages: Message[] +} + +const reformatMessages = (messages: Message[], username: string) => { + return messages.map((message, idx) => { + return { + id: idx, + name: message.isBot ? message.name : username, + isBot: message.isBot, + message: message.message, + images: message.images + } + }) +} + +export const PlaygroundMessage = ( + props: Message & { + username: string + } +) => { + return ( +
+
+
+
+
+ {props.isBot ? ( +
+ ) : ( +
+ )} +
+
+
+ + {props.isBot ? props.name : props.username} + + +
+ +
+ {/* source if aviable */} + {props.images && props.images.length > 0 && ( +
+ {props.images + .filter((image) => image.length > 0) + .map((image, index) => ( + Uploaded Image + ))} +
+ )} +
+
+
+
+ ) +} + +export const ShareBtn: React.FC = ({ messages }) => { + const [open, setOpen] = useState(false) + const [form] = Form.useForm() + const name = Form.useWatch("name", form) + + React.useEffect(() => { + if (messages.length > 0) { + form.setFieldsValue({ + title: messages[0].message + }) + } + }, [messages]) + + const onSubmit = async (values: { title: string; name: string }) => { + const owner_id = await getUserId() + const chat = reformatMessages(messages, values.name) + const title = values.title + const url = await getPageShareUrl() + const res = await fetch(`${cleanUrl(url)}/api/v1/share/create`, { + method: "POST", + headers: { + "Content-Type": "application/json" + }, + body: JSON.stringify({ + owner_id, + messages: chat, + title + }) + }) + + if (!res.ok) throw new Error("Failed to create share link") + + const data = await res.json() + + return { + ...data, + url: `${cleanUrl(url)}/share/${data.chat_id}`, + api_url: cleanUrl(url), + share_id: data.chat_id + } + } + + const { mutate: createShareLink, isPending } = useMutation({ + mutationFn: onSubmit, + onSuccess: async (data) => { + const url = data.url + navigator.clipboard.writeText(url) + message.success("Link copied to clipboard") + await saveWebshare({ title: data.title, url, api_url: data.api_url, share_id: data.share_id }) + setOpen(false) + }, + onError: (error) => { + message.error(error?.message || "Failed to create share link") + } + }) + + return ( + <> + + + + + setOpen(false)}> +
+ + + + + + + + +
+
+ {messages.map((message, index) => ( + + ))} +
+
+
+ + +
+ +
+
+
+
+ + ) +} diff --git a/src/components/Layouts/Layout.tsx b/src/components/Layouts/Layout.tsx index 4c08354..f50f2d4 100644 --- a/src/components/Layouts/Layout.tsx +++ b/src/components/Layouts/Layout.tsx @@ -16,6 +16,7 @@ import { ZapIcon } from "lucide-react" import { getAllPrompts } from "~libs/db" +import { ShareBtn } from "~components/Common/ShareBtn" export default function OptionLayout({ children @@ -29,7 +30,9 @@ export default function OptionLayout({ clearChat, selectedSystemPrompt, setSelectedQuickPrompt, - setSelectedSystemPrompt + setSelectedSystemPrompt, + messages, + streaming } = useMessageOption() const { @@ -155,6 +158,9 @@ export default function OptionLayout({
+ {pathname === "/" && messages.length > 0 && !streaming && ( + + )} {/* { return ( <>
-