chatgpt-api-web ChatStore {Tr("Version")}{" "}
- {props.chatStore.chatgpt_api_web_version}
+ {ctx.chatStore.chatgpt_api_web_version}
{Tr("Documents and source code are avaliable here")}:{" "}
diff --git a/src/components/Templates.tsx b/src/components/Templates.tsx
index a215fe8..a59809c 100644
--- a/src/components/Templates.tsx
+++ b/src/components/Templates.tsx
@@ -1,14 +1,14 @@
+import { AppContext } from "@/pages/App";
import { TemplateChatStore } from "@/types/chatstore";
import { ChatStore } from "@/types/chatstore";
import { getDefaultParams } from "@/utils/getDefaultParam";
+import { useContext } from "react";
+
+const Templates = () => {
+ const ctx = useContext(AppContext);
+ if (ctx === null) return <>>;
+ const { templates, chatStore, setChatStore, setTemplates } = ctx;
-const Templates = (props: {
- templates: TemplateChatStore[];
- chatStore: ChatStore;
- setChatStore: (cs: ChatStore) => void;
- setTemplates: (templates: TemplateChatStore[]) => void;
-}) => {
- const { templates, chatStore, setChatStore, setTemplates } = props;
return (
<>
{templates.map((t, index) => (
diff --git a/src/listAPIs.tsx b/src/listAPIs.tsx
index e9a2cfc..de8ed72 100644
--- a/src/listAPIs.tsx
+++ b/src/listAPIs.tsx
@@ -13,61 +13,54 @@ import {
} from "@/components/ui/navigation-menu";
import { Button } from "./components/ui/button";
import { cn } from "@/lib/utils";
+import { useContext } from "react";
+import { AppContext } from "./pages/App";
interface Props {
- chatStore: ChatStore;
- setChatStore: (cs: ChatStore) => void;
- tmps: TemplateAPI[];
- setTmps: (tmps: TemplateAPI[]) => void;
label: string;
apiField: string;
keyField: string;
}
-export function ListAPIs({
- tmps,
- setTmps,
- chatStore,
- setChatStore,
- label,
- apiField,
- keyField,
-}: Props) {
+export function ListAPIs({ label, apiField, keyField }: Props) {
+ const ctx = useContext(AppContext);
+ if (ctx === null) return <>>;
+
return (
{label}{" "}
- {tmps.find(
+ {ctx.templateAPIs.find(
(t) =>
- chatStore[apiField as keyof ChatStore] === t.endpoint &&
- chatStore[keyField as keyof ChatStore] === t.key
+ ctx.chatStore[apiField as keyof ChatStore] === t.endpoint &&
+ ctx.chatStore[keyField as keyof ChatStore] === t.key
)?.name &&
`: ${
- tmps.find(
+ ctx.templateAPIs.find(
(t) =>
- chatStore[apiField as keyof ChatStore] === t.endpoint &&
- chatStore[keyField as keyof ChatStore] === t.key
+ ctx.chatStore[apiField as keyof ChatStore] === t.endpoint &&
+ ctx.chatStore[keyField as keyof ChatStore] === t.key
)?.name
}`}
- {tmps.map((t, index) => (
+ {ctx.templateAPIs.map((t, index) => (
-
{
// @ts-ignore
- chatStore[apiField] = t.endpoint;
+ ctx.chatStore[apiField as keyof ChatStore] = t.endpoint;
// @ts-ignore
- chatStore[keyField] = t.key;
- setChatStore({ ...chatStore });
+ ctx.chatStore[keyField] = t.key;
+ ctx.setChatStore({ ...ctx.chatStore });
}}
className={cn(
"block select-none space-y-1 rounded-md p-3 leading-none no-underline outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground",
- chatStore[apiField as keyof ChatStore] === t.endpoint &&
- chatStore[keyField as keyof ChatStore] === t.key
+ ctx.chatStore[apiField as keyof ChatStore] === t.endpoint &&
+ ctx.chatStore[keyField as keyof ChatStore] === t.key
? "bg-accent text-accent-foreground"
: ""
)}
@@ -88,7 +81,7 @@ export function ListAPIs({
const name = prompt(`Give **${label}** template a name`);
if (!name) return;
t.name = name;
- setTmps(structuredClone(tmps));
+ ctx.setTemplateAPIs(structuredClone(ctx.templateAPIs));
}}
>
Edit
@@ -104,8 +97,8 @@ export function ListAPIs({
) {
return;
}
- tmps.splice(index, 1);
- setTmps(structuredClone(tmps));
+ ctx.templateAPIs.splice(index, 1);
+ ctx.setTemplateAPIs(structuredClone(ctx.templateAPIs));
}}
>
Delete
diff --git a/src/message.tsx b/src/message.tsx
index 87b81b0..d13c533 100644
--- a/src/message.tsx
+++ b/src/message.tsx
@@ -1,6 +1,6 @@
import { XMarkIcon } from "@heroicons/react/24/outline";
import Markdown from "react-markdown";
-import { useState } from "react";
+import { useContext, useState } from "react";
import { Tr, langCodeContext, LANG_OPTIONS } from "@/translate";
import { ChatStore, ChatStoreMessage } from "@/types/chatstore";
@@ -26,6 +26,7 @@ import {
MessageSquareOffIcon,
MessageSquarePlusIcon,
} from "lucide-react";
+import { AppContext } from "./pages/App";
export const isVailedJSON = (str: string): boolean => {
try {
@@ -36,14 +37,12 @@ export const isVailedJSON = (str: string): boolean => {
return true;
};
-interface Props {
- messageIndex: number;
- chatStore: ChatStore;
- setChatStore: (cs: ChatStore) => void;
-}
+export default function Message(props: { messageIndex: number }) {
+ const ctx = useContext(AppContext);
+ if (ctx === null) return <>>;
+ const { messageIndex } = props;
+ const { chatStore, setChatStore } = ctx;
-export default function Message(props: Props) {
- const { chatStore, messageIndex, setChatStore } = props;
const chat = chatStore.history[messageIndex];
const [showEdit, setShowEdit] = useState(false);
const [showCopiedHint, setShowCopiedHint] = useState(false);
diff --git a/src/pages/App.tsx b/src/pages/App.tsx
index 0068d22..dc0f33f 100644
--- a/src/pages/App.tsx
+++ b/src/pages/App.tsx
@@ -1,5 +1,5 @@
-import { openDB } from "idb";
-import { useEffect, useState } from "react";
+import { IDBPDatabase, openDB } from "idb";
+import { createContext, useEffect, useState } from "react";
import "@/global.css";
import { calculate_token_length } from "@/chatgpt";
@@ -14,6 +14,43 @@ import { STORAGE_NAME, STORAGE_NAME_SELECTED } from "@/const";
import { upgrade } from "@/indexedDB/upgrade";
import { getTotalCost } from "@/utils/totalCost";
+import {
+ STORAGE_NAME_TEMPLATE,
+ STORAGE_NAME_TEMPLATE_API,
+ STORAGE_NAME_TEMPLATE_API_IMAGE_GEN,
+ STORAGE_NAME_TEMPLATE_API_TTS,
+ STORAGE_NAME_TEMPLATE_API_WHISPER,
+ STORAGE_NAME_TEMPLATE_TOOLS,
+} from "@/const";
+import {
+ ChatStoreMessage,
+ TemplateChatStore,
+ TemplateAPI,
+ TemplateTools,
+} from "../types/chatstore";
+
+interface AppContextType {
+ db: Promise>;
+ chatStore: ChatStore;
+ setChatStore: (cs: ChatStore) => void;
+ selectedChatIndex: number;
+ setSelectedChatIndex: (i: number) => void;
+ templates: TemplateChatStore[];
+ setTemplates: (t: TemplateChatStore[]) => void;
+ templateAPIs: TemplateAPI[];
+ setTemplateAPIs: (t: TemplateAPI[]) => void;
+ templateAPIsWhisper: TemplateAPI[];
+ setTemplateAPIsWhisper: (t: TemplateAPI[]) => void;
+ templateAPIsTTS: TemplateAPI[];
+ setTemplateAPIsTTS: (t: TemplateAPI[]) => void;
+ templateAPIsImageGen: TemplateAPI[];
+ setTemplateAPIsImageGen: (t: TemplateAPI[]) => void;
+ templateTools: TemplateTools[];
+ setTemplateTools: (t: TemplateTools[]) => void;
+}
+
+export const AppContext = createContext(null);
+
import {
Sidebar,
SidebarContent,
@@ -247,6 +284,77 @@ export function App() {
run();
}, []);
+ const [templates, _setTemplates] = useState(
+ JSON.parse(
+ localStorage.getItem(STORAGE_NAME_TEMPLATE) || "[]"
+ ) as TemplateChatStore[]
+ );
+ const [templateAPIs, _setTemplateAPIs] = useState(
+ JSON.parse(
+ localStorage.getItem(STORAGE_NAME_TEMPLATE_API) || "[]"
+ ) as TemplateAPI[]
+ );
+ const [templateAPIsWhisper, _setTemplateAPIsWhisper] = useState(
+ JSON.parse(
+ localStorage.getItem(STORAGE_NAME_TEMPLATE_API_WHISPER) || "[]"
+ ) as TemplateAPI[]
+ );
+ const [templateAPIsTTS, _setTemplateAPIsTTS] = useState(
+ JSON.parse(
+ localStorage.getItem(STORAGE_NAME_TEMPLATE_API_TTS) || "[]"
+ ) as TemplateAPI[]
+ );
+ const [templateAPIsImageGen, _setTemplateAPIsImageGen] = useState(
+ JSON.parse(
+ localStorage.getItem(STORAGE_NAME_TEMPLATE_API_IMAGE_GEN) || "[]"
+ ) as TemplateAPI[]
+ );
+ const [templateTools, _setTemplateTools] = useState(
+ JSON.parse(
+ localStorage.getItem(STORAGE_NAME_TEMPLATE_TOOLS) || "[]"
+ ) as TemplateTools[]
+ );
+ const setTemplates = (templates: TemplateChatStore[]) => {
+ localStorage.setItem(STORAGE_NAME_TEMPLATE, JSON.stringify(templates));
+ _setTemplates(templates);
+ };
+ const setTemplateAPIs = (templateAPIs: TemplateAPI[]) => {
+ localStorage.setItem(
+ STORAGE_NAME_TEMPLATE_API,
+ JSON.stringify(templateAPIs)
+ );
+ _setTemplateAPIs(templateAPIs);
+ };
+ const setTemplateAPIsWhisper = (templateAPIWhisper: TemplateAPI[]) => {
+ localStorage.setItem(
+ STORAGE_NAME_TEMPLATE_API_WHISPER,
+ JSON.stringify(templateAPIWhisper)
+ );
+ _setTemplateAPIsWhisper(templateAPIWhisper);
+ };
+ const setTemplateAPIsTTS = (templateAPITTS: TemplateAPI[]) => {
+ localStorage.setItem(
+ STORAGE_NAME_TEMPLATE_API_TTS,
+ JSON.stringify(templateAPITTS)
+ );
+ _setTemplateAPIsTTS(templateAPITTS);
+ };
+ const setTemplateAPIsImageGen = (templateAPIImageGen: TemplateAPI[]) => {
+ localStorage.setItem(
+ STORAGE_NAME_TEMPLATE_API_IMAGE_GEN,
+ JSON.stringify(templateAPIImageGen)
+ );
+ _setTemplateAPIsImageGen(templateAPIImageGen);
+ };
+ const setTemplateTools = (templateTools: TemplateTools[]) => {
+ localStorage.setItem(
+ STORAGE_NAME_TEMPLATE_TOOLS,
+ JSON.stringify(templateTools)
+ );
+ _setTemplateTools(templateTools);
+ };
+ console.log("[PERFORMANCE!] reading localStorage");
+
return (
<>
@@ -410,13 +518,29 @@ export function App() {