Skip to content

Commit

Permalink
added pdf renderer
Browse files Browse the repository at this point in the history
  • Loading branch information
trace2798 committed Dec 29, 2023
1 parent 5792fec commit bffa275
Show file tree
Hide file tree
Showing 8 changed files with 1,005 additions and 210 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ import ReactMarkdown from "react-markdown";
import { MemoizedReactMarkdown } from "./markdown";
import remarkGfm from "remark-gfm";
import remarkMath from "remark-math";
import {
ResizableHandle,
ResizablePanel,
ResizablePanelGroup,
} from "@/components/ui/resizable";
import PdfRenderer from "@/components/pdf-renderer";

type Message = {
id: string;
Expand All @@ -34,13 +40,15 @@ interface ChatProps {
pastMessages: Message[];
userId: string;
tenant_id: string;
url: string;
}

export const Chat: FC<ChatProps> = ({
fileId,
tenant_id,
pastMessages,
userId,
url,
}) => {
const router = useRouter();
const {
Expand Down Expand Up @@ -78,18 +86,28 @@ export const Chat: FC<ChatProps> = ({
};
console.log(pastMessages);
return (
<div className="flex flex-col w-full max-w-xl pb-24 mx-auto stretch min-h-screen">
{/* {pastMessages.length > 0 ? (
<>
{pastMessages.map((message, index) => (
<div key={index}>
{message.isUserMessage ? (
<UserMessage text={message.text} />
) : (
<AIMessage text={message.text} />
)}
</div>
))}
<>
<ResizablePanelGroup direction="horizontal">
<ResizablePanel defaultSize={50}>
<PdfRenderer url={url} />{" "}
</ResizablePanel>
<ResizableHandle withHandle />
<ResizablePanel className="pl-5">
{pastMessages.length > 0 ? (
<>
{pastMessages.map((message, index) => (
<div key={index}>
{message.isUserMessage ? (
<UserMessage text={message.text} />
) : (
<AIMessage text={message.text} />
)}
</div>
))}
</>
) : (
""
)}
{messages.map((m) => (
<div
key={m.id}
Expand All @@ -98,76 +116,13 @@ export const Chat: FC<ChatProps> = ({
m.role === "user",
"text-green-500 p-4 w-full flex items-start gap-x-8 rounded-lg max-w-lg bg-muted":
m.role !== "user",
})}
>
<ReactMarkdown
components={{
pre: ({ node, ...props }) => (
<div className="overflow-auto w-full my-2 bg-black/10 p-2 rounded-lg text-blue-400">
<pre {...props} />
</div>
),
code: ({ node, ...props }) => (
<code
className="bg-black/10 rounded-lg p-1 text-indigo-300"
{...props}
/>
),
a: ({ node, ...props }) => (
<a target="_blank" rel="noopener noreferrer" {...props} />
),
li: ({ node, ...props }) => (
<li className="text-green-600" {...props} />
),
}}
className="text-base overflow-hidden leading-7"
>
{m.content}
</ReactMarkdown>
<Button
onClick={() => onCopy(m.content)}
className="hidden group-hover:block"
size="icon"
variant="ghost"
>
<Copy className="w-4 h-4" />
</Button>
</div>
))}
</>
) : (
<>
{messages.map((m) => (
<div
key={m.id}
className={cn("whitespace-pre-wrap group", {
"text-blue-500 text-right p-4 gap-x-8 rounded-lg max-w-lg ":
"prose-p:text-indigo-400 prose-li:text-indigo-400":
m.role === "user",
"text-green-500 p-4 w-full flex items-start gap-x-8 rounded-lg max-w-lg bg-muted":
m.role !== "user",
})}
>
<ReactMarkdown
components={{
pre: ({ node, ...props }) => (
<div className="overflow-auto w-full my-2 bg-black/10 p-2 rounded-lg text-blue-400">
<pre {...props} />
</div>
),
code: ({ node, ...props }) => (
<code
className="bg-black/10 rounded-lg p-1 text-indigo-300"
{...props}
/>
),
a: ({ node, ...props }) => (
<a target="_blank" rel="noopener noreferrer" {...props} />
),
li: ({ node, ...props }) => (
<li className="text-green-600" {...props} />
),
}}
className="text-base overflow-hidden leading-7"
remarkPlugins={[remarkGfm, remarkMath]}
className="text-base prose dark:prose-invert prose-ul:m-0 prose-li:m-0 prose-p:my-0 prose-h3:my-0"
>
{m.content}
</ReactMarkdown>
Expand All @@ -181,124 +136,27 @@ export const Chat: FC<ChatProps> = ({
</Button>
</div>
))}
</>
)} */}
{pastMessages.length > 0 ? (
<>
{pastMessages.map((message, index) => (
<div key={index}>
{message.isUserMessage ? (
<UserMessage text={message.text} />
) : (
<AIMessage text={message.text} />
)}
</div>
))}
</>
) : (
""
)}
{messages.map((m) => (
<div
key={m.id}
className={cn("whitespace-pre-wrap group", {
"text-blue-500 text-right p-4 gap-x-8 rounded-lg max-w-lg ":
m.role === "user",
"text-green-500 p-4 w-full flex items-start gap-x-8 rounded-lg max-w-lg bg-muted":
m.role !== "user",
"prose-p:text-indigo-400 prose-li:text-indigo-400":
m.role === "user",
})}
>
<ReactMarkdown
remarkPlugins={[remarkGfm, remarkMath]}
className="text-base prose dark:prose-invert prose-ul:m-0 prose-li:m-0 prose-p:my-0 prose-h3:my-0"
>
{m.content}
</ReactMarkdown>
{/* <ReactMarkdown
remarkPlugins={[remarkGfm, remarkMath]}
className={cn(
"text-base prose prose-ul:m-0 prose-li:m-0 prose-p:my-0",
{
"prose-p:text-indigo-400": m.role === "user",
"prose-p:text-green-500": m.role !== "user",
}
)}
>
{m.content}
</ReactMarkdown> */}
{/* <MemoizedReactMarkdown
className="prose break-words dark:prose-invert prose-p:leading-relaxed prose-pre:p-0"
remarkPlugins={[remarkGfm, remarkMath]}
components={{
p({ children }) {
return <p className="mb-2 last:mb-0">{children}</p>;
},
code({ node, inline, className, children, ...props }) {
if (children.length) {
if (children[0] == "▍") {
return (
<span className="mt-1 cursor-default animate-pulse">
</span>
);
}
children[0] = (children[0] as string).replace("`▍`", "▍");
}

const match = /language-(\w+)/.exec(className || "");
if (inline) {
return (
<code className={className} {...props}>
{children}
</code>
);
}
return (
<CodeBlock
key={Math.random()}
language={(match && match[1]) || ""}
value={String(children).replace(/\n$/, "")}
{...props}
/>
);
},
}}
>
{m.content}
</MemoizedReactMarkdown> */}
<Button
onClick={() => onCopy(m.content)}
className="hidden group-hover:block"
size="icon"
variant="ghost"
>
<Copy className="w-4 h-4" />
</Button>
</div>
))}

<form onSubmit={handleSubmit}>
{isLoading && (
<div className="p-4 rounded-lg w-1/2 flex items-center justify-center bg-muted mt-10">
<BeatLoader
color={theme === "light" ? "black" : "white"}
size={5}
<form onSubmit={handleSubmit}>
{isLoading && (
<div className="p-4 rounded-lg w-1/2 flex items-center justify-center bg-muted mt-10">
<BeatLoader
color={theme === "light" ? "black" : "white"}
size={5}
/>
</div>
)}
<Input
className="fixed bottom-0 w-[80vw] md:w-full max-w-md p-2 mb-8 min-h-4 border border-gray-300 rounded shadow-xl"
value={input}
placeholder="Talk to the document..."
onChange={handleInputChange}
/>
</div>
)}
<Input
className="fixed bottom-0 w-[80vw] md:w-full max-w-md p-2 mb-8 min-h-4 border border-gray-300 rounded shadow-xl"
value={input}
placeholder="Talk to the document..."
onChange={handleInputChange}
/>
<div ref={scrollRef} />
</form>
</div>
<div ref={scrollRef} />
</form>
</ResizablePanel>
</ResizablePanelGroup>
{/* <div className="flex flex-col w-full max-w-xl pb-24 mx-auto stretch min-h-screen"></div> */}
</>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,23 @@ const FileIdPage = async ({ params }: FileIdPageProps) => {
})
.select();

const fileInfo = await nile
.db("file")
.where({
id: params.fileId,
// user_id: nile.userId,
tenant_id: number,
})
.returning("*")
console.log(fileInfo);
return (
<>
<Chat
fileId={params.fileId}
pastMessages={messages}
userId={nile.userId}
tenant_id={number}
url={fileInfo[0].url}
/>
</>
);
Expand Down
62 changes: 62 additions & 0 deletions components/pdf-fullscreen.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { useState } from "react";
import { Dialog, DialogContent, DialogTrigger } from "./ui/dialog";
import { Button } from "./ui/button";
import { Expand, Loader2 } from "lucide-react";
import SimpleBar from "simplebar-react";
import { Document, Page } from "react-pdf";

// import { useResizeDetector } from "react-resize-detector";
import { toast } from "sonner";

interface PdfFullscreenProps {
fileUrl: string;
}

const PdfFullscreen = ({ fileUrl }: PdfFullscreenProps) => {
const [isOpen, setIsOpen] = useState(false);
const [numPages, setNumPages] = useState<number>();

// const { width, ref } = useResizeDetector();

return (
<Dialog
open={isOpen}
onOpenChange={(v) => {
if (!v) {
setIsOpen(v);
}
}}
>
<DialogTrigger onClick={() => setIsOpen(true)} asChild>
<Button variant="ghost" className="gap-1.5" aria-label="fullscreen">
<Expand className="h-4 w-4" />
</Button>
</DialogTrigger>
<DialogContent className="max-w-7xl w-full">
<SimpleBar autoHide={false} className="max-h-[calc(100vh-10rem)] mt-6">
<div>
<Document
loading={
<div className="flex justify-center">
<Loader2 className="my-24 h-6 w-6 animate-spin" />
</div>
}
onLoadError={() => {
toast.error("Error Loading Pdf");
}}
onLoadSuccess={({ numPages }) => setNumPages(numPages)}
file={fileUrl}
className="max-h-full"
>
{new Array(numPages).fill(0).map((_, i) => (
<Page key={i} pageNumber={i + 1} />
))}
</Document>
</div>
</SimpleBar>
</DialogContent>
</Dialog>
);
};

export default PdfFullscreen;
Loading

0 comments on commit bffa275

Please sign in to comment.