Skip to content

Commit

Permalink
Minor code refactoring and cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
blrchen committed Feb 18, 2024
1 parent 6d5e535 commit 91893b1
Show file tree
Hide file tree
Showing 14 changed files with 124 additions and 74 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/docker.chatgpt-lite.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ on:
- main

jobs:
build_and_push_image:
build-and-push-image:
name: Push image to Docker Hub
runs-on: ubuntu-latest
steps:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ import {
import { debounce } from 'lodash-es'
import { AiOutlineClose, AiOutlineDelete, AiOutlineEdit } from 'react-icons/ai'
import { LuMessageSquarePlus } from 'react-icons/lu'
import ChatContext from './chatContext'
import { Persona } from './interface'
import { ChatContext, Persona } from '@/components'

export interface PersonaPanelProps {}

Expand Down
3 changes: 2 additions & 1 deletion app/chat/page.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
'use client'
import { Suspense } from 'react'
import { Flex } from '@radix-ui/themes'
import { Chat, ChatContext, ChatSideBar, PersonaPanel, useChatHook } from '@/components'
import { Chat, ChatContext, ChatSideBar, useChatHook } from '@/components'
import PersonaModal from './PersonaModal'
import PersonaPanel from './PersonaPanel'

const ChatProvider = () => {
const provider = useChatHook()
Expand Down
5 changes: 0 additions & 5 deletions components/Chat/Chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import {
useState
} from 'react'
import { Flex, Heading, IconButton, ScrollArea, Tooltip } from '@radix-ui/themes'
import clipboard from 'clipboard'
import ContentEditable from 'react-contenteditable'
import toast from 'react-hot-toast'
import { AiOutlineClear, AiOutlineLoading3Quarters, AiOutlineUnorderedList } from 'react-icons/ai'
Expand Down Expand Up @@ -206,10 +205,6 @@ const Chat = (props: ChatProps, ref: any) => {
}
})

useEffect(() => {
new clipboard('.copy-btn').on('success', () => {})
}, [])

return (
<Flex direction="column" height="100%" className="relative" gap="3">
<Flex
Expand Down
36 changes: 32 additions & 4 deletions components/Chat/Message.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
'use client'

import { Avatar, Flex } from '@radix-ui/themes'
import { useCallback, useState } from 'react'
import { Avatar, Flex, IconButton, Tooltip } from '@radix-ui/themes'
import { FaRegCopy } from 'react-icons/fa'
import { HiUser } from 'react-icons/hi'
import { SiOpenai } from 'react-icons/si'
import { RiRobot2Line } from 'react-icons/ri'
import { Markdown } from '@/components'
import { useCopyToClipboard } from '@/hooks/useCopyToClipboard'
import { ChatMessage } from './interface'

export interface MessageProps {
Expand All @@ -13,11 +16,21 @@ export interface MessageProps {
const Message = (props: MessageProps) => {
const { role, content } = props.message
const isUser = role === 'user'
const copy = useCopyToClipboard()
const [tooltipOpen, setTooltipOpen] = useState<boolean>(false)

const onCopy = useCallback(() => {
copy(content, (isSuccess) => {
if (isSuccess) {
setTooltipOpen(true)
}
})
}, [content, copy])

return (
<Flex gap="4" className="mb-5">
<Avatar
fallback={isUser ? <HiUser className="size-4" /> : <SiOpenai className="size-4" />}
fallback={isUser ? <HiUser className="size-4" /> : <RiRobot2Line className="size-4" />}
color={isUser ? undefined : 'green'}
size="2"
radius="full"
Expand All @@ -34,7 +47,22 @@ const Message = (props: MessageProps) => {
}}
></div>
) : (
<Markdown>{content}</Markdown>
<Flex direction="column" gap="4">
<Markdown>{content}</Markdown>
<Flex gap="4" align="center">
<Tooltip open={tooltipOpen} content="Copied!">
<IconButton
className="cursor-pointer"
variant="outline"
color="gray"
onClick={onCopy}
onMouseLeave={() => setTooltipOpen(false)}
>
<FaRegCopy />
</IconButton>
</Tooltip>
</Flex>
</Flex>
)}
</div>
</Flex>
Expand Down
3 changes: 0 additions & 3 deletions components/Chat/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
'use client'

export * from './interface'
export { default as Chat } from './Chat'
export { default as ChatSideBar } from './ChatSideBar'
export { default as PersonaPanel } from './PersonaPanel'
export { default as ChatContext } from './chatContext'
export { default as useChatHook } from './useChatHook'
4 changes: 2 additions & 2 deletions components/Header.tsx → components/Header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import { Avatar, Flex, Heading, IconButton, Select, Tooltip } from '@radix-ui/th
import cs from 'classnames'
import NextLink from 'next/link'
import { FaAdjust, FaGithub, FaMoon, FaRegSun } from 'react-icons/fa'
import { Link } from './Link'
import { useTheme } from './Themes'
import { Link } from '../Link'
import { useTheme } from '../Themes'

export const Header = () => {
const { theme, setTheme } = useTheme()
Expand Down
1 change: 1 addition & 0 deletions components/Header/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './Header'
13 changes: 10 additions & 3 deletions components/Link.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,19 @@ interface LinkProps {
className?: string
color?: LinkOwnProps['color']
children?: React.ReactNode
disabled?: boolean
highContrast?: boolean
}

export const Link = ({ href, className, children, color }: LinkProps) => {
export const Link = ({ href, className, children, color, highContrast, disabled }: LinkProps) => {
return (
<NextLink href={href} passHref legacyBehavior>
<RadixLink className={className} color={color}>
<NextLink href={href} passHref legacyBehavior aria-disabled={disabled}>
<RadixLink
className={className}
color={color}
aria-disabled={disabled}
highContrast={highContrast}
>
{children}
</RadixLink>
</NextLink>
Expand Down
72 changes: 48 additions & 24 deletions components/Markdown.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { IconButton } from '@radix-ui/themes'
'use client'

import { ClassAttributes, Fragment, HTMLAttributes, useCallback, useState } from 'react'
import { IconButton, Tooltip } from '@radix-ui/themes'
import cs from 'classnames'
import { RxClipboardCopy } from 'react-icons/rx'
import ReactMarkdown from 'react-markdown'
import ReactMarkdown, { ExtraProps } from 'react-markdown'
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'
import { vscDarkPlus } from 'react-syntax-highlighter/dist/esm/styles/prism'
import rehypeKatex from 'rehype-katex'
Expand All @@ -11,12 +14,54 @@ import remarkGfm from 'remark-gfm'
import remarkMath from 'remark-math'
import remarkParse from 'remark-parse'
import remarkRehype from 'remark-rehype'
import { useCopyToClipboard } from '@/hooks/useCopyToClipboard'

export interface MarkdownProps {
className?: string
children: string
}

const HighlightCode = (
props: ClassAttributes<HTMLElement> & HTMLAttributes<HTMLElement> & ExtraProps
) => {
const { children, className, ref, ...rest } = props
const match = /language-(\w+)/.exec(className || '')
const copy = useCopyToClipboard()
const [tooltipOpen, setTooltipOpen] = useState<boolean>(false)

const code = match ? String(children).replace(/\n$/, '') : ''

const onCopy = useCallback(() => {
copy(code, (isSuccess) => {
if (isSuccess) {
setTooltipOpen(true)
}
})
}, [code, copy])

return match ? (
<Fragment>
<Tooltip open={tooltipOpen} content="Copied!">
<IconButton
className="absolute right-4 top-4 cursor-pointer"
variant="solid"
onClick={onCopy}
onMouseLeave={() => setTooltipOpen(false)}
>
<RxClipboardCopy />
</IconButton>
</Tooltip>
<SyntaxHighlighter {...rest} style={vscDarkPlus} language={match[1]} PreTag="div">
{code}
</SyntaxHighlighter>
</Fragment>
) : (
<code ref={ref} {...rest} className={cs('highlight', className)}>
{children}
</code>
)
}

export const Markdown = ({ className, children }: MarkdownProps) => {
return (
<ReactMarkdown
Expand All @@ -25,32 +70,11 @@ export const Markdown = ({ className, children }: MarkdownProps) => {
rehypePlugins={[rehypeRaw, rehypeKatex, rehypeStringify]}
components={{
code(props) {
const { children, className, ref, ...rest } = props
const match = /language-(\w+)/.exec(className || '')
return match ? (
<>
<IconButton
className="absolute right-4 top-4 copy-btn cursor-pointer"
variant="solid"
data-clipboard-text={children}
>
<RxClipboardCopy />
</IconButton>
<SyntaxHighlighter {...rest} style={vscDarkPlus} language={match[1]} PreTag="div">
{String(children).replace(/\n$/, '')}
</SyntaxHighlighter>
</>
) : (
<code ref={ref} {...rest} className={cs('highlight', className)}>
{children}
</code>
)
return <HighlightCode {...props} />
}
}}
>
{children}
</ReactMarkdown>
)
}

export default Markdown
2 changes: 2 additions & 0 deletions components/Themes/ThemeContext.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
'use client'

import { createContext } from 'react'
import { UseThemeProps } from './interface'

Expand Down
2 changes: 0 additions & 2 deletions components/Themes/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
'use client'

export * from './interface'
export * from './useTheme'
export * from './ThemeProvider'
25 changes: 25 additions & 0 deletions hooks/useCopyToClipboard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { useCallback } from 'react'

type CopyFn = (text: string, callback?: (data: any) => void) => Promise<boolean> // Return success

export const useCopyToClipboard = (): CopyFn => {
const copy: CopyFn = useCallback(async (text, callback) => {
if (!navigator?.clipboard) {
console.warn('Clipboard not supported')
callback?.(false)
return false
}

try {
await navigator.clipboard.writeText(text)
callback?.(true)
return true
} catch (error) {
console.warn('Copy failed', error)
callback?.(false)
return false
}
}, [])

return copy
}
27 changes: 0 additions & 27 deletions styles/globals.scss
Original file line number Diff line number Diff line change
Expand Up @@ -424,33 +424,6 @@ body {
@apply flex flex-col;
}

.table-fixed-header {
.rt-TableRootTable {
overflow: initial !important;
}

.rt-TableHeader {
--table-row-background-color: var(--gray-2) !important;
position: relative;
z-index: 1;
.rt-TableCell {
&:first-child {
border-top-left-radius: calc(var(--table-border-radius) - 1px);
}
&:last-child {
border-top-right-radius: calc(var(--table-border-radius) - 1px);
}
}
}

.react-loading-skeleton {
z-index: 0;
}
.rt-ScrollAreaScrollbar {
z-index: 2;
}
}

.navbar-collapse {
@apply max-md:absolute max-md:top-14 max-md:gap-0 max-md:left-0 max-md:right-0 max-md:px-1 max-md:flex-col max-md:items-start max-md:backdrop-blur-md max-md:bg-[--color-page-background] max-md:shadow-sm max-md:overflow-hidden;
height: 0;
Expand Down

0 comments on commit 91893b1

Please sign in to comment.