feat: add in prettier and format code for consistency (#168)
This commit is contained in:
+6
-6
@@ -1,9 +1,9 @@
|
||||
import "@/styles/globals.css";
|
||||
import { appWithTranslation } from "next-i18next";
|
||||
import type { AppProps } from "next/app";
|
||||
import { Inter } from "next/font/google";
|
||||
import '@/styles/globals.css';
|
||||
import { appWithTranslation } from 'next-i18next';
|
||||
import type { AppProps } from 'next/app';
|
||||
import { Inter } from 'next/font/google';
|
||||
|
||||
const inter = Inter({ subsets: ["latin"] });
|
||||
const inter = Inter({ subsets: ['latin'] });
|
||||
|
||||
function App({ Component, pageProps }: AppProps<{}>) {
|
||||
return (
|
||||
@@ -13,4 +13,4 @@ function App({ Component, pageProps }: AppProps<{}>) {
|
||||
);
|
||||
}
|
||||
|
||||
export default appWithTranslation(App);
|
||||
export default appWithTranslation(App);
|
||||
|
||||
+6
-7
@@ -1,18 +1,17 @@
|
||||
import { Html, Head, Main, NextScript, DocumentProps } from 'next/document'
|
||||
import i18nextConfig from '../next-i18next.config'
|
||||
import { Html, Head, Main, NextScript, DocumentProps } from 'next/document';
|
||||
import i18nextConfig from '../next-i18next.config';
|
||||
|
||||
type Props = DocumentProps & {
|
||||
// add custom document props
|
||||
}
|
||||
};
|
||||
|
||||
export default function Document(props: Props) {
|
||||
const currentLocale =
|
||||
props.__NEXT_DATA__.locale ??
|
||||
i18nextConfig.i18n.defaultLocale
|
||||
props.__NEXT_DATA__.locale ?? i18nextConfig.i18n.defaultLocale;
|
||||
return (
|
||||
<Html lang={currentLocale}>
|
||||
<Head>
|
||||
<meta name="apple-mobile-web-app-capable" content="yes"/>
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-title" content="Chatbot UI"></meta>
|
||||
</Head>
|
||||
<body>
|
||||
@@ -20,5 +19,5 @@ export default function Document(props: Props) {
|
||||
<NextScript />
|
||||
</body>
|
||||
</Html>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
+9
-9
@@ -1,13 +1,13 @@
|
||||
import { ChatBody, Message, OpenAIModelID } from "@/types";
|
||||
import { DEFAULT_SYSTEM_PROMPT } from "@/utils/app/const";
|
||||
import { OpenAIStream } from "@/utils/server";
|
||||
import tiktokenModel from "@dqbd/tiktoken/encoders/cl100k_base.json";
|
||||
import { init, Tiktoken } from "@dqbd/tiktoken/lite/init";
|
||||
import { ChatBody, Message, OpenAIModelID } from '@/types';
|
||||
import { DEFAULT_SYSTEM_PROMPT } from '@/utils/app/const';
|
||||
import { OpenAIStream } from '@/utils/server';
|
||||
import tiktokenModel from '@dqbd/tiktoken/encoders/cl100k_base.json';
|
||||
import { init, Tiktoken } from '@dqbd/tiktoken/lite/init';
|
||||
// @ts-expect-error
|
||||
import wasm from "../../node_modules/@dqbd/tiktoken/lite/tiktoken_bg.wasm?module";
|
||||
import wasm from '../../node_modules/@dqbd/tiktoken/lite/tiktoken_bg.wasm?module';
|
||||
|
||||
export const config = {
|
||||
runtime: "edge",
|
||||
runtime: 'edge',
|
||||
};
|
||||
|
||||
const handler = async (req: Request): Promise<Response> => {
|
||||
@@ -18,7 +18,7 @@ const handler = async (req: Request): Promise<Response> => {
|
||||
const encoding = new Tiktoken(
|
||||
tiktokenModel.bpe_ranks,
|
||||
tiktokenModel.special_tokens,
|
||||
tiktokenModel.pat_str
|
||||
tiktokenModel.pat_str,
|
||||
);
|
||||
|
||||
const tokenLimit = model.id === OpenAIModelID.GPT_4 ? 6000 : 3000;
|
||||
@@ -51,7 +51,7 @@ const handler = async (req: Request): Promise<Response> => {
|
||||
return new Response(stream);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
return new Response("Error", { status: 500 });
|
||||
return new Response('Error', { status: 500 });
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+18
-17
@@ -1,8 +1,8 @@
|
||||
import { OpenAIModel, OpenAIModelID, OpenAIModels } from "@/types";
|
||||
import { OPENAI_API_HOST } from "@/utils/app/const";
|
||||
import { OpenAIModel, OpenAIModelID, OpenAIModels } from '@/types';
|
||||
import { OPENAI_API_HOST } from '@/utils/app/const';
|
||||
|
||||
export const config = {
|
||||
runtime: "edge"
|
||||
runtime: 'edge',
|
||||
};
|
||||
|
||||
const handler = async (req: Request): Promise<Response> => {
|
||||
@@ -13,22 +13,23 @@ const handler = async (req: Request): Promise<Response> => {
|
||||
|
||||
const response = await fetch(`${OPENAI_API_HOST}/v1/models`, {
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: `Bearer ${key ? key : process.env.OPENAI_API_KEY}`
|
||||
}
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${key ? key : process.env.OPENAI_API_KEY}`,
|
||||
},
|
||||
});
|
||||
|
||||
if (response.status === 401) {
|
||||
return new Response(
|
||||
response.body,
|
||||
{
|
||||
status: 500,
|
||||
headers: response.headers
|
||||
}
|
||||
);
|
||||
return new Response(response.body, {
|
||||
status: 500,
|
||||
headers: response.headers,
|
||||
});
|
||||
} else if (response.status !== 200) {
|
||||
console.error(`OpenAI API returned an error ${response.status}: ${await response.text()}`)
|
||||
throw new Error("OpenAI API returned an error");
|
||||
console.error(
|
||||
`OpenAI API returned an error ${
|
||||
response.status
|
||||
}: ${await response.text()}`,
|
||||
);
|
||||
throw new Error('OpenAI API returned an error');
|
||||
}
|
||||
|
||||
const json = await response.json();
|
||||
@@ -39,7 +40,7 @@ const handler = async (req: Request): Promise<Response> => {
|
||||
if (value === model.id) {
|
||||
return {
|
||||
id: model.id,
|
||||
name: OpenAIModels[value].name
|
||||
name: OpenAIModels[value].name,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -49,7 +50,7 @@ const handler = async (req: Request): Promise<Response> => {
|
||||
return new Response(JSON.stringify(models), { status: 200 });
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
return new Response("Error", { status: 500 });
|
||||
return new Response('Error', { status: 500 });
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+158
-114
@@ -1,35 +1,52 @@
|
||||
import { Chat } from "@/components/Chat/Chat";
|
||||
import { Navbar } from "@/components/Mobile/Navbar";
|
||||
import { Sidebar } from "@/components/Sidebar/Sidebar";
|
||||
import { ChatBody, ChatFolder, Conversation, ErrorMessage, KeyValuePair, Message, OpenAIModel, OpenAIModelID, OpenAIModels } from "@/types";
|
||||
import { cleanConversationHistory, cleanSelectedConversation } from "@/utils/app/clean";
|
||||
import { DEFAULT_SYSTEM_PROMPT } from "@/utils/app/const";
|
||||
import { saveConversation, saveConversations, updateConversation } from "@/utils/app/conversation";
|
||||
import { saveFolders } from "@/utils/app/folders";
|
||||
import { exportData, importData } from "@/utils/app/importExport";
|
||||
import { IconArrowBarLeft, IconArrowBarRight } from "@tabler/icons-react";
|
||||
import { GetServerSideProps } from "next";
|
||||
import Head from "next/head";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
|
||||
import { useTranslation } from "next-i18next";
|
||||
import { Chat } from '@/components/Chat/Chat';
|
||||
import { Navbar } from '@/components/Mobile/Navbar';
|
||||
import { Sidebar } from '@/components/Sidebar/Sidebar';
|
||||
import {
|
||||
ChatBody,
|
||||
ChatFolder,
|
||||
Conversation,
|
||||
ErrorMessage,
|
||||
KeyValuePair,
|
||||
Message,
|
||||
OpenAIModel,
|
||||
OpenAIModelID,
|
||||
OpenAIModels,
|
||||
} from '@/types';
|
||||
import {
|
||||
cleanConversationHistory,
|
||||
cleanSelectedConversation,
|
||||
} from '@/utils/app/clean';
|
||||
import { DEFAULT_SYSTEM_PROMPT } from '@/utils/app/const';
|
||||
import {
|
||||
saveConversation,
|
||||
saveConversations,
|
||||
updateConversation,
|
||||
} from '@/utils/app/conversation';
|
||||
import { saveFolders } from '@/utils/app/folders';
|
||||
import { exportData, importData } from '@/utils/app/importExport';
|
||||
import { IconArrowBarLeft, IconArrowBarRight } from '@tabler/icons-react';
|
||||
import { GetServerSideProps } from 'next';
|
||||
import Head from 'next/head';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
|
||||
interface HomeProps {
|
||||
serverSideApiKeyIsSet: boolean;
|
||||
}
|
||||
|
||||
|
||||
const Home: React.FC<HomeProps> = ({ serverSideApiKeyIsSet }) => {
|
||||
const { t } = useTranslation('chat')
|
||||
const { t } = useTranslation('chat');
|
||||
const [folders, setFolders] = useState<ChatFolder[]>([]);
|
||||
const [conversations, setConversations] = useState<Conversation[]>([]);
|
||||
const [selectedConversation, setSelectedConversation] = useState<Conversation>();
|
||||
const [selectedConversation, setSelectedConversation] =
|
||||
useState<Conversation>();
|
||||
const [loading, setLoading] = useState<boolean>(false);
|
||||
const [models, setModels] = useState<OpenAIModel[]>([]);
|
||||
const [lightMode, setLightMode] = useState<"dark" | "light">("dark");
|
||||
const [lightMode, setLightMode] = useState<'dark' | 'light'>('dark');
|
||||
const [messageIsStreaming, setMessageIsStreaming] = useState<boolean>(false);
|
||||
const [showSidebar, setShowSidebar] = useState<boolean>(true);
|
||||
const [apiKey, setApiKey] = useState<string>("");
|
||||
const [apiKey, setApiKey] = useState<string>('');
|
||||
const [messageError, setMessageError] = useState<boolean>(false);
|
||||
const [modelError, setModelError] = useState<ErrorMessage | null>(null);
|
||||
const [currentMessage, setCurrentMessage] = useState<Message>();
|
||||
@@ -48,12 +65,12 @@ const Home: React.FC<HomeProps> = ({ serverSideApiKeyIsSet }) => {
|
||||
|
||||
updatedConversation = {
|
||||
...selectedConversation,
|
||||
messages: [...updatedMessages, message]
|
||||
messages: [...updatedMessages, message],
|
||||
};
|
||||
} else {
|
||||
updatedConversation = {
|
||||
...selectedConversation,
|
||||
messages: [...selectedConversation.messages, message]
|
||||
messages: [...selectedConversation.messages, message],
|
||||
};
|
||||
}
|
||||
|
||||
@@ -66,17 +83,17 @@ const Home: React.FC<HomeProps> = ({ serverSideApiKeyIsSet }) => {
|
||||
model: updatedConversation.model,
|
||||
messages: updatedConversation.messages,
|
||||
key: apiKey,
|
||||
prompt: updatedConversation.prompt
|
||||
prompt: updatedConversation.prompt,
|
||||
};
|
||||
|
||||
const controller = new AbortController();
|
||||
const response = await fetch("/api/chat", {
|
||||
method: "POST",
|
||||
const response = await fetch('/api/chat', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
"Content-Type": "application/json"
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
signal: controller.signal,
|
||||
body: JSON.stringify(chatBody)
|
||||
body: JSON.stringify(chatBody),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
@@ -98,11 +115,12 @@ const Home: React.FC<HomeProps> = ({ serverSideApiKeyIsSet }) => {
|
||||
|
||||
if (updatedConversation.messages.length === 1) {
|
||||
const { content } = message;
|
||||
const customName = content.length > 30 ? content.substring(0, 30) + "..." : content;
|
||||
const customName =
|
||||
content.length > 30 ? content.substring(0, 30) + '...' : content;
|
||||
|
||||
updatedConversation = {
|
||||
...updatedConversation,
|
||||
name: customName
|
||||
name: customName,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -112,7 +130,7 @@ const Home: React.FC<HomeProps> = ({ serverSideApiKeyIsSet }) => {
|
||||
const decoder = new TextDecoder();
|
||||
let done = false;
|
||||
let isFirst = true;
|
||||
let text = "";
|
||||
let text = '';
|
||||
|
||||
while (!done) {
|
||||
if (stopConversationRef.current === true) {
|
||||
@@ -128,29 +146,34 @@ const Home: React.FC<HomeProps> = ({ serverSideApiKeyIsSet }) => {
|
||||
|
||||
if (isFirst) {
|
||||
isFirst = false;
|
||||
const updatedMessages: Message[] = [...updatedConversation.messages, { role: "assistant", content: chunkValue }];
|
||||
const updatedMessages: Message[] = [
|
||||
...updatedConversation.messages,
|
||||
{ role: 'assistant', content: chunkValue },
|
||||
];
|
||||
|
||||
updatedConversation = {
|
||||
...updatedConversation,
|
||||
messages: updatedMessages
|
||||
messages: updatedMessages,
|
||||
};
|
||||
|
||||
setSelectedConversation(updatedConversation);
|
||||
} else {
|
||||
const updatedMessages: Message[] = updatedConversation.messages.map((message, index) => {
|
||||
if (index === updatedConversation.messages.length - 1) {
|
||||
return {
|
||||
...message,
|
||||
content: text
|
||||
};
|
||||
}
|
||||
const updatedMessages: Message[] = updatedConversation.messages.map(
|
||||
(message, index) => {
|
||||
if (index === updatedConversation.messages.length - 1) {
|
||||
return {
|
||||
...message,
|
||||
content: text,
|
||||
};
|
||||
}
|
||||
|
||||
return message;
|
||||
});
|
||||
return message;
|
||||
},
|
||||
);
|
||||
|
||||
updatedConversation = {
|
||||
...updatedConversation,
|
||||
messages: updatedMessages
|
||||
messages: updatedMessages,
|
||||
};
|
||||
|
||||
setSelectedConversation(updatedConversation);
|
||||
@@ -159,13 +182,15 @@ const Home: React.FC<HomeProps> = ({ serverSideApiKeyIsSet }) => {
|
||||
|
||||
saveConversation(updatedConversation);
|
||||
|
||||
const updatedConversations: Conversation[] = conversations.map((conversation) => {
|
||||
if (conversation.id === selectedConversation.id) {
|
||||
return updatedConversation;
|
||||
}
|
||||
const updatedConversations: Conversation[] = conversations.map(
|
||||
(conversation) => {
|
||||
if (conversation.id === selectedConversation.id) {
|
||||
return updatedConversation;
|
||||
}
|
||||
|
||||
return conversation;
|
||||
});
|
||||
return conversation;
|
||||
},
|
||||
);
|
||||
|
||||
if (updatedConversations.length === 0) {
|
||||
updatedConversations.push(updatedConversation);
|
||||
@@ -184,19 +209,21 @@ const Home: React.FC<HomeProps> = ({ serverSideApiKeyIsSet }) => {
|
||||
title: t('Error fetching models.'),
|
||||
code: null,
|
||||
messageLines: [
|
||||
t('Make sure your OpenAI API key is set in the bottom left of the sidebar.'),
|
||||
t('If you completed this step, OpenAI may be experiencing issues.')
|
||||
]
|
||||
t(
|
||||
'Make sure your OpenAI API key is set in the bottom left of the sidebar.',
|
||||
),
|
||||
t('If you completed this step, OpenAI may be experiencing issues.'),
|
||||
],
|
||||
} as ErrorMessage;
|
||||
|
||||
const response = await fetch("/api/models", {
|
||||
method: "POST",
|
||||
const response = await fetch('/api/models', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
"Content-Type": "application/json"
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
key
|
||||
})
|
||||
key,
|
||||
}),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
@@ -204,9 +231,9 @@ const Home: React.FC<HomeProps> = ({ serverSideApiKeyIsSet }) => {
|
||||
const data = await response.json();
|
||||
Object.assign(error, {
|
||||
code: data.error?.code,
|
||||
messageLines: [data.error?.message]
|
||||
})
|
||||
} catch (e) { }
|
||||
messageLines: [data.error?.message],
|
||||
});
|
||||
} catch (e) {}
|
||||
setModelError(error);
|
||||
return;
|
||||
}
|
||||
@@ -222,21 +249,24 @@ const Home: React.FC<HomeProps> = ({ serverSideApiKeyIsSet }) => {
|
||||
setModelError(null);
|
||||
};
|
||||
|
||||
const handleLightMode = (mode: "dark" | "light") => {
|
||||
const handleLightMode = (mode: 'dark' | 'light') => {
|
||||
setLightMode(mode);
|
||||
localStorage.setItem("theme", mode);
|
||||
localStorage.setItem('theme', mode);
|
||||
};
|
||||
|
||||
const handleApiKeyChange = (apiKey: string) => {
|
||||
setApiKey(apiKey);
|
||||
localStorage.setItem("apiKey", apiKey);
|
||||
localStorage.setItem('apiKey', apiKey);
|
||||
};
|
||||
|
||||
const handleExportData = () => {
|
||||
exportData();
|
||||
};
|
||||
|
||||
const handleImportConversations = (data: { conversations: Conversation[]; folders: ChatFolder[] }) => {
|
||||
const handleImportConversations = (data: {
|
||||
conversations: Conversation[];
|
||||
folders: ChatFolder[];
|
||||
}) => {
|
||||
importData(data.conversations, data.folders);
|
||||
setConversations(data.conversations);
|
||||
setSelectedConversation(data.conversations[data.conversations.length - 1]);
|
||||
@@ -253,7 +283,7 @@ const Home: React.FC<HomeProps> = ({ serverSideApiKeyIsSet }) => {
|
||||
|
||||
const newFolder: ChatFolder = {
|
||||
id: lastFolder ? lastFolder.id + 1 : 1,
|
||||
name
|
||||
name,
|
||||
};
|
||||
|
||||
const updatedFolders = [...folders, newFolder];
|
||||
@@ -271,7 +301,7 @@ const Home: React.FC<HomeProps> = ({ serverSideApiKeyIsSet }) => {
|
||||
if (c.folderId === folderId) {
|
||||
return {
|
||||
...c,
|
||||
folderId: 0
|
||||
folderId: 0,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -286,7 +316,7 @@ const Home: React.FC<HomeProps> = ({ serverSideApiKeyIsSet }) => {
|
||||
if (f.id === folderId) {
|
||||
return {
|
||||
...f,
|
||||
name
|
||||
name,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -302,11 +332,13 @@ const Home: React.FC<HomeProps> = ({ serverSideApiKeyIsSet }) => {
|
||||
|
||||
const newConversation: Conversation = {
|
||||
id: lastConversation ? lastConversation.id + 1 : 1,
|
||||
name: `${t('Conversation')} ${lastConversation ? lastConversation.id + 1 : 1}`,
|
||||
name: `${t('Conversation')} ${
|
||||
lastConversation ? lastConversation.id + 1 : 1
|
||||
}`,
|
||||
messages: [],
|
||||
model: OpenAIModels[OpenAIModelID.GPT_3_5],
|
||||
prompt: DEFAULT_SYSTEM_PROMPT,
|
||||
folderId: 0
|
||||
folderId: 0,
|
||||
};
|
||||
|
||||
const updatedConversations = [...conversations, newConversation];
|
||||
@@ -321,33 +353,43 @@ const Home: React.FC<HomeProps> = ({ serverSideApiKeyIsSet }) => {
|
||||
};
|
||||
|
||||
const handleDeleteConversation = (conversation: Conversation) => {
|
||||
const updatedConversations = conversations.filter((c) => c.id !== conversation.id);
|
||||
const updatedConversations = conversations.filter(
|
||||
(c) => c.id !== conversation.id,
|
||||
);
|
||||
setConversations(updatedConversations);
|
||||
saveConversations(updatedConversations);
|
||||
|
||||
if (updatedConversations.length > 0) {
|
||||
setSelectedConversation(updatedConversations[updatedConversations.length - 1]);
|
||||
setSelectedConversation(
|
||||
updatedConversations[updatedConversations.length - 1],
|
||||
);
|
||||
saveConversation(updatedConversations[updatedConversations.length - 1]);
|
||||
} else {
|
||||
setSelectedConversation({
|
||||
id: 1,
|
||||
name: "New conversation",
|
||||
name: 'New conversation',
|
||||
messages: [],
|
||||
model: OpenAIModels[OpenAIModelID.GPT_3_5],
|
||||
prompt: DEFAULT_SYSTEM_PROMPT,
|
||||
folderId: 0
|
||||
folderId: 0,
|
||||
});
|
||||
localStorage.removeItem("selectedConversation");
|
||||
localStorage.removeItem('selectedConversation');
|
||||
}
|
||||
};
|
||||
|
||||
const handleUpdateConversation = (conversation: Conversation, data: KeyValuePair) => {
|
||||
const handleUpdateConversation = (
|
||||
conversation: Conversation,
|
||||
data: KeyValuePair,
|
||||
) => {
|
||||
const updatedConversation = {
|
||||
...conversation,
|
||||
[data.key]: data.value
|
||||
[data.key]: data.value,
|
||||
};
|
||||
|
||||
const { single, all } = updateConversation(updatedConversation, conversations);
|
||||
const { single, all } = updateConversation(
|
||||
updatedConversation,
|
||||
conversations,
|
||||
);
|
||||
|
||||
setSelectedConversation(single);
|
||||
setConversations(all);
|
||||
@@ -355,20 +397,20 @@ const Home: React.FC<HomeProps> = ({ serverSideApiKeyIsSet }) => {
|
||||
|
||||
const handleClearConversations = () => {
|
||||
setConversations([]);
|
||||
localStorage.removeItem("conversationHistory");
|
||||
localStorage.removeItem('conversationHistory');
|
||||
|
||||
setSelectedConversation({
|
||||
id: 1,
|
||||
name: "New conversation",
|
||||
name: 'New conversation',
|
||||
messages: [],
|
||||
model: OpenAIModels[OpenAIModelID.GPT_3_5],
|
||||
prompt: DEFAULT_SYSTEM_PROMPT,
|
||||
folderId: 0
|
||||
folderId: 0,
|
||||
});
|
||||
localStorage.removeItem("selectedConversation");
|
||||
localStorage.removeItem('selectedConversation');
|
||||
|
||||
setFolders([]);
|
||||
localStorage.removeItem("folders");
|
||||
localStorage.removeItem('folders');
|
||||
};
|
||||
|
||||
const handleEditMessage = (message: Message, messageIndex: number) => {
|
||||
@@ -383,10 +425,13 @@ const Home: React.FC<HomeProps> = ({ serverSideApiKeyIsSet }) => {
|
||||
|
||||
const updatedConversation = {
|
||||
...selectedConversation,
|
||||
messages: updatedMessages
|
||||
messages: updatedMessages,
|
||||
};
|
||||
|
||||
const { single, all } = updateConversation(updatedConversation, conversations);
|
||||
const { single, all } = updateConversation(
|
||||
updatedConversation,
|
||||
conversations,
|
||||
);
|
||||
|
||||
setSelectedConversation(single);
|
||||
setConversations(all);
|
||||
@@ -415,48 +460,54 @@ const Home: React.FC<HomeProps> = ({ serverSideApiKeyIsSet }) => {
|
||||
}, [apiKey]);
|
||||
|
||||
useEffect(() => {
|
||||
const theme = localStorage.getItem("theme");
|
||||
const theme = localStorage.getItem('theme');
|
||||
if (theme) {
|
||||
setLightMode(theme as "dark" | "light");
|
||||
setLightMode(theme as 'dark' | 'light');
|
||||
}
|
||||
|
||||
const apiKey = localStorage.getItem("apiKey");
|
||||
const apiKey = localStorage.getItem('apiKey');
|
||||
if (apiKey) {
|
||||
setApiKey(apiKey);
|
||||
fetchModels(apiKey);
|
||||
} else if (serverSideApiKeyIsSet) {
|
||||
fetchModels("");
|
||||
fetchModels('');
|
||||
}
|
||||
|
||||
if (window.innerWidth < 640) {
|
||||
setShowSidebar(false);
|
||||
}
|
||||
|
||||
const folders = localStorage.getItem("folders");
|
||||
const folders = localStorage.getItem('folders');
|
||||
if (folders) {
|
||||
setFolders(JSON.parse(folders));
|
||||
}
|
||||
|
||||
const conversationHistory = localStorage.getItem("conversationHistory");
|
||||
const conversationHistory = localStorage.getItem('conversationHistory');
|
||||
if (conversationHistory) {
|
||||
const parsedConversationHistory: Conversation[] = JSON.parse(conversationHistory);
|
||||
const cleanedConversationHistory = cleanConversationHistory(parsedConversationHistory);
|
||||
const parsedConversationHistory: Conversation[] =
|
||||
JSON.parse(conversationHistory);
|
||||
const cleanedConversationHistory = cleanConversationHistory(
|
||||
parsedConversationHistory,
|
||||
);
|
||||
setConversations(cleanedConversationHistory);
|
||||
}
|
||||
|
||||
const selectedConversation = localStorage.getItem("selectedConversation");
|
||||
const selectedConversation = localStorage.getItem('selectedConversation');
|
||||
if (selectedConversation) {
|
||||
const parsedSelectedConversation: Conversation = JSON.parse(selectedConversation);
|
||||
const cleanedSelectedConversation = cleanSelectedConversation(parsedSelectedConversation);
|
||||
const parsedSelectedConversation: Conversation =
|
||||
JSON.parse(selectedConversation);
|
||||
const cleanedSelectedConversation = cleanSelectedConversation(
|
||||
parsedSelectedConversation,
|
||||
);
|
||||
setSelectedConversation(cleanedSelectedConversation);
|
||||
} else {
|
||||
setSelectedConversation({
|
||||
id: 1,
|
||||
name: "New conversation",
|
||||
name: 'New conversation',
|
||||
messages: [],
|
||||
model: OpenAIModels[OpenAIModelID.GPT_3_5],
|
||||
prompt: DEFAULT_SYSTEM_PROMPT,
|
||||
folderId: 0
|
||||
folderId: 0,
|
||||
});
|
||||
}
|
||||
}, [serverSideApiKeyIsSet]);
|
||||
@@ -465,22 +516,15 @@ const Home: React.FC<HomeProps> = ({ serverSideApiKeyIsSet }) => {
|
||||
<>
|
||||
<Head>
|
||||
<title>Chatbot UI</title>
|
||||
<meta
|
||||
name="description"
|
||||
content="ChatGPT but better."
|
||||
/>
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1"
|
||||
/>
|
||||
<link
|
||||
rel="icon"
|
||||
href="/favicon.ico"
|
||||
/>
|
||||
<meta name="description" content="ChatGPT but better." />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
</Head>
|
||||
{selectedConversation && (
|
||||
<main className={`flex flex-col h-screen w-screen text-white dark:text-white text-sm ${lightMode}`}>
|
||||
<div className="sm:hidden w-full fixed top-0">
|
||||
<main
|
||||
className={`flex h-screen w-screen flex-col text-sm text-white dark:text-white ${lightMode}`}
|
||||
>
|
||||
<div className="fixed top-0 w-full sm:hidden">
|
||||
<Navbar
|
||||
selectedConversation={selectedConversation}
|
||||
onNewConversation={handleNewConversation}
|
||||
@@ -513,18 +557,18 @@ const Home: React.FC<HomeProps> = ({ serverSideApiKeyIsSet }) => {
|
||||
/>
|
||||
|
||||
<IconArrowBarLeft
|
||||
className="z-50 fixed top-5 left-[270px] sm:top-0.5 sm:left-[270px] sm:text-neutral-700 dark:text-white cursor-pointer hover:text-gray-400 dark:hover:text-gray-300 h-7 w-7 sm:h-8 sm:w-8"
|
||||
className="fixed top-5 left-[270px] z-50 h-7 w-7 cursor-pointer hover:text-gray-400 dark:text-white dark:hover:text-gray-300 sm:top-0.5 sm:left-[270px] sm:h-8 sm:w-8 sm:text-neutral-700"
|
||||
onClick={() => setShowSidebar(!showSidebar)}
|
||||
/>
|
||||
|
||||
<div
|
||||
onClick={() => setShowSidebar(!showSidebar)}
|
||||
className="sm:hidden bg-black opacity-70 z-10 absolute top-0 left-0 h-full w-full"
|
||||
className="absolute top-0 left-0 z-10 h-full w-full bg-black opacity-70 sm:hidden"
|
||||
></div>
|
||||
</div>
|
||||
) : (
|
||||
<IconArrowBarRight
|
||||
className="fixed text-white z-50 top-2.5 left-4 sm:top-0.5 sm:left-4 sm:text-neutral-700 dark:text-white cursor-pointer hover:text-gray-400 dark:hover:text-gray-300 h-7 w-7 sm:h-8 sm:w-8"
|
||||
className="fixed top-2.5 left-4 z-50 h-7 w-7 cursor-pointer text-white hover:text-gray-400 dark:text-white dark:hover:text-gray-300 sm:top-0.5 sm:left-4 sm:h-8 sm:w-8 sm:text-neutral-700"
|
||||
onClick={() => setShowSidebar(!showSidebar)}
|
||||
/>
|
||||
)}
|
||||
@@ -562,6 +606,6 @@ export const getServerSideProps: GetServerSideProps = async ({ locale }) => {
|
||||
'sidebar',
|
||||
'markdown',
|
||||
])),
|
||||
}
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user