Skip to content

Commit

Permalink
Merge pull request #12 from e-roy:refactor-markdown-viewer
Browse files Browse the repository at this point in the history
refactor markdown viewer
  • Loading branch information
e-roy authored Dec 26, 2023
2 parents 0e94a56 + 682a6d4 commit 92dda9c
Show file tree
Hide file tree
Showing 10 changed files with 299 additions and 205 deletions.
6 changes: 1 addition & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
# Gemini Pro Vision Playground


This project is a simple playground for using the Gemini Pro Vision and Gemini Pro AI models.


I created this to help others building apps with the gemini-pro and gemin-pro-vision models. If you find it helpful, please give a ⭐

https://github.com/e-roy/gemini-pro-vision-playground/assets/70700747/e0e80929-285c-441f-87f5-34d68593b787




## Getting Started

Get your Google AI API key [here](https://ai.google.dev/tutorials/setup)
Expand Down
4 changes: 2 additions & 2 deletions src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ export default function Home() {
const { selectedModel } = useControlContext();

return (
<main className="grid md:grid-cols-12 max-h-screen h-screen max-w-6xl m-auto gap-4 p-2 md:p-4 my-12 md:my-0">
<main className="grid md:grid-cols-12 max-h-screen md:h-screen max-w-6xl m-auto gap-4 p-2 md:p-4 my-12 md:my-0">
<div className="relative md:col-span-3 h-[95vh]">
<ControlContainer />
</div>
<div className="md:col-span-9 h-[95vh]">
<div className="md:col-span-9">
{selectedModel === "gemini-pro" ? (
<ChatContainer />
) : (
Expand Down
65 changes: 32 additions & 33 deletions src/components/ChatContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,13 @@ import React, {
} from "react";
import { Message, useChat } from "ai/react";
import { Card } from "./ui/card";
import {
HoverCard,
HoverCardContent,
HoverCardTrigger,
} from "@/components/ui/hover-card";
import { MarkdownViewer } from "./MarkdownViewer";

import { MarkdownViewer } from "./markdown-viewer/MarkdownViewer";
import { useControlContext } from "@/providers/ControlContext";
import { CommonForm } from "./CommonForm";
import { TypingBubble } from "./TypingBubble";
import { MessageCircleX } from "lucide-react";
import { MessageCircleX, User, Bot } from "lucide-react";
import { Button } from "./ui/button";

export const ChatContainer = () => {
const { generalSettings, safetySettings } = useControlContext();
Expand Down Expand Up @@ -63,39 +60,41 @@ export const ChatContainer = () => {
return (
<div className="flex flex-col h-[95vh]">
<Card className="flex flex-col flex-1 overflow-hidden">
{messages.length > 0 && (
<div className={`flex p-4`}>
<Button
variant={`secondary`}
type={`button`}
size={`sm`}
onClick={handleClearChat}
>
<MessageCircleX className={`mr-2`} /> Clear chat history
</Button>
</div>
)}
<div className="flex-1 overflow-y-auto">
{messages.length > 0 && (
<div className={`flex justify-end p-4`}>
<HoverCard openDelay={200}>
<HoverCardTrigger asChild onClick={handleClearChat}>
<div className={`text-primary/60 hover:text-primary/90`}>
<MessageCircleX />
</div>
</HoverCardTrigger>
<HoverCardContent
align="start"
className="w-[260px] text-sm"
side="right"
>
Clear chat history
</HoverCardContent>
</HoverCard>
</div>
)}
{messages.map((message: Message) => (
<div
key={message.id}
className={`${
message.role === "user" ? "justify-end" : "justify-start"
} flex m-4`}
>
<div key={message.id} className={`flex`}>
<div
className={`${
message.role === "user"
? "bg-primary/20 dark:bg-primary/20"
? ""
: "bg-primary/10 dark:bg-primary/10"
} px-4 py-2 rounded-lg`}
} px-4 py-8 w-full`}
>
<div className={`my-4`}>
{message.role === "user" ? (
<div className={`flex space-x-4 font-medium`}>
<User />
<div>You</div>
</div>
) : (
<div className={`flex space-x-4 font-medium`}>
<Bot />
<div>Gemini Pro</div>
</div>
)}
</div>
<MarkdownViewer text={message.content} />
</div>
</div>
Expand Down
163 changes: 0 additions & 163 deletions src/components/MarkdownViewer.tsx

This file was deleted.

2 changes: 1 addition & 1 deletion src/components/VisionContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import React, { useState, useCallback } from "react";
import { useControlContext } from "@/providers/ControlContext";
import { Card } from "@/components/ui/card";

import { MarkdownViewer } from "./MarkdownViewer";
import { MarkdownViewer } from "./markdown-viewer/MarkdownViewer";
import { CommonForm } from "./CommonForm";
import { TypingBubble } from "./TypingBubble";

Expand Down
92 changes: 92 additions & 0 deletions src/components/markdown-viewer/MarkdownViewer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
"use client";
// components/MarkdownViewer.tsx
import React, { useMemo } from "react";
import ReactMarkdown from "react-markdown";
import remarkGfm from "remark-gfm";
import rehypeRaw from "rehype-raw";
import rehypeSanitize from "rehype-sanitize";

import { UlComponent, OlComponent, LiComponent } from "./list";

import { PreComponent, CodeBlock } from "./code";

import {
TableComponent,
TheadComponent,
TbodyComponent,
TrComponent,
ThComponent,
TdComponent,
} from "./table";

type AnchorProps = {
href: string;
children: React.ReactNode;
};

const Anchor: React.FC<AnchorProps> = ({ href, children }) => {
return (
<a
href={href}
className="text-blue-500 hover:underline"
target="_blank"
rel="noopener noreferrer"
>
{children}
</a>
);
};

const MemoizedAnchor = React.memo(Anchor);

const MemoizedUlComponent = React.memo(UlComponent);
const MemoizedOlComponent = React.memo(OlComponent);
const MemoizedLiComponent = React.memo(LiComponent);

const MemoizedPreComponent = React.memo(PreComponent);
const MemoizedCodeBlock = React.memo(CodeBlock);

const MemoizedTableComponent = React.memo(TableComponent);
const MemoizedTheadComponent = React.memo(TheadComponent);
const MemoizedTbodyComponent = React.memo(TbodyComponent);
const MemoizedTrComponent = React.memo(TrComponent);
const MemoizedThComponent = React.memo(ThComponent);
const MemoizedTdComponent = React.memo(TdComponent);

interface IMarkdownViewerProps {
text: string;
}

export const MarkdownViewer: React.FC<IMarkdownViewerProps> = ({ text }) => {
const components = useMemo(
() => ({
a: MemoizedAnchor,

ul: MemoizedUlComponent,
ol: MemoizedOlComponent,
li: MemoizedLiComponent,

pre: MemoizedPreComponent,
code: MemoizedCodeBlock,

table: MemoizedTableComponent,
thead: MemoizedTheadComponent,
tbody: MemoizedTbodyComponent,
tr: MemoizedTrComponent,
th: MemoizedThComponent,
td: MemoizedTdComponent,
}),
[]
);

return (
<ReactMarkdown
// @ts-ignore
components={components}
remarkPlugins={[remarkGfm]}
rehypePlugins={[rehypeRaw, rehypeSanitize]}
>
{text}
</ReactMarkdown>
);
};
Loading

0 comments on commit 92dda9c

Please sign in to comment.