| @@ -1,7 +1,6 @@ | |||
| import React from 'react' | |||
| import type { FC } from 'react' | |||
| import type { Metadata } from 'next' | |||
| import { SharePageContextProvider } from '@/context/share-page-context' | |||
| export const metadata: Metadata = { | |||
| icons: 'data:,', // prevent browser from using default favicon | |||
| @@ -12,9 +11,7 @@ const Layout: FC<{ | |||
| }> = ({ children }) => { | |||
| return ( | |||
| <div className="min-w-[300px] h-full pb-[env(safe-area-inset-bottom)]"> | |||
| <SharePageContextProvider> | |||
| {children} | |||
| </SharePageContextProvider> | |||
| {children} | |||
| </div> | |||
| ) | |||
| } | |||
| @@ -5,7 +5,7 @@ import { | |||
| RiPlayLargeFill, | |||
| } from '@remixicon/react' | |||
| import Toast from '@/app/components/base/toast' | |||
| import { useAppContext } from '@/context/app-context' | |||
| import useTheme from '@/hooks/use-theme' | |||
| import { Theme } from '@/types/app' | |||
| import cn from '@/utils/classnames' | |||
| @@ -24,7 +24,7 @@ const AudioPlayer: React.FC<AudioPlayerProps> = ({ src }) => { | |||
| const [hasStartedPlaying, setHasStartedPlaying] = useState(false) | |||
| const [hoverTime, setHoverTime] = useState(0) | |||
| const [isAudioAvailable, setIsAudioAvailable] = useState(true) | |||
| const { theme } = useAppContext() | |||
| const { theme } = useTheme() | |||
| useEffect(() => { | |||
| const audio = audioRef.current | |||
| @@ -206,7 +206,7 @@ const ChatWrapper = () => { | |||
| isResponding={isResponding} | |||
| chatContainerInnerClassName={`mx-auto pt-6 w-full max-w-[720px] ${isMobile && 'px-4'}`} | |||
| chatFooterClassName='pb-4' | |||
| chatFooterInnerClassName={`mx-auto w-full max-w-[720px] ${isMobile && 'px-4'}`} | |||
| chatFooterInnerClassName={`mx-auto w-full max-w-[720px] ${isMobile ? 'px-2' : 'px-4'}`} | |||
| onSend={doSend} | |||
| inputs={currentConversationId ? currentConversationItem?.inputs as any : newConversationInputs} | |||
| inputsForm={inputsForms} | |||
| @@ -48,10 +48,13 @@ export class ThemeBuilder { | |||
| private buildChecker = false | |||
| public get theme() { | |||
| if (this._theme === undefined) | |||
| throw new Error('The theme should be built first and then accessed') | |||
| else | |||
| if (this._theme === undefined) { | |||
| this._theme = new Theme() | |||
| return this._theme | |||
| } | |||
| else { | |||
| return this._theme | |||
| } | |||
| } | |||
| public buildTheme(chatColorTheme: string | null = null, chatColorThemeInverted = false) { | |||
| @@ -26,7 +26,7 @@ import MarkdownButton from '@/app/components/base/markdown-blocks/button' | |||
| import MarkdownForm from '@/app/components/base/markdown-blocks/form' | |||
| import ThinkBlock from '@/app/components/base/markdown-blocks/think-block' | |||
| import { Theme } from '@/types/app' | |||
| import { useAppContext } from '@/context/app-context' | |||
| import useTheme from '@/hooks/use-theme' | |||
| import cn from '@/utils/classnames' | |||
| // Available language https://github.com/react-syntax-highlighter/react-syntax-highlighter/blob/master/AVAILABLE_LANGUAGES_HLJS.MD | |||
| @@ -107,7 +107,7 @@ export function PreCode(props: { children: any }) { | |||
| // or use the non-minified dev environment for full errors and additional helpful warnings. | |||
| const CodeBlock: any = memo(({ inline, className, children, ...props }: any) => { | |||
| const { theme } = useAppContext() | |||
| const { theme } = useTheme() | |||
| const [isSVG, setIsSVG] = useState(true) | |||
| const match = /language-(\w+)/.exec(className || '') | |||
| const language = match?.[1] | |||
| @@ -1,47 +0,0 @@ | |||
| 'use client' | |||
| import { useCallback, useEffect, useState } from 'react' | |||
| import { createContext, useContextSelector } from 'use-context-selector' | |||
| import type { FC, ReactNode } from 'react' | |||
| import { Theme } from '@/types/app' | |||
| export type SharePageContextValue = { | |||
| theme: Theme | |||
| setTheme: (theme: Theme) => void | |||
| } | |||
| const SharePageContext = createContext<SharePageContextValue>({ | |||
| theme: Theme.light, | |||
| setTheme: () => { }, | |||
| }) | |||
| export function useSelector<T>(selector: (value: SharePageContextValue) => T): T { | |||
| return useContextSelector(SharePageContext, selector) | |||
| } | |||
| export type SharePageContextProviderProps = { | |||
| children: ReactNode | |||
| } | |||
| export const SharePageContextProvider: FC<SharePageContextProviderProps> = ({ children }) => { | |||
| const [theme, setTheme] = useState<Theme>(Theme.light) | |||
| const handleSetTheme = useCallback((theme: Theme) => { | |||
| setTheme(theme) | |||
| globalThis.document.documentElement.setAttribute('data-theme', theme) | |||
| }, []) | |||
| useEffect(() => { | |||
| globalThis.document.documentElement.setAttribute('data-theme', theme) | |||
| // eslint-disable-next-line react-hooks/exhaustive-deps | |||
| }, []) | |||
| return ( | |||
| <SharePageContext.Provider value={{ | |||
| theme, | |||
| setTheme: handleSetTheme, | |||
| }}> | |||
| {children} | |||
| </SharePageContext.Provider> | |||
| ) | |||
| } | |||
| export default SharePageContextProvider | |||