diff --git a/src/components/Settings.tsx b/src/components/Settings.tsx
new file mode 100644
index 0000000..5dd8a92
--- /dev/null
+++ b/src/components/Settings.tsx
@@ -0,0 +1,13 @@
+import { Button } from "@/components/ui/button";
+import { Input } from "@/components/ui/input";
+import { Label } from "@/components/ui/label";
+import {
+ Sheet,
+ SheetClose,
+ SheetContent,
+ SheetDescription,
+ SheetFooter,
+ SheetHeader,
+ SheetTitle,
+ SheetTrigger,
+} from "@/components/ui/sheet";
diff --git a/src/main.tsx b/src/main.tsx
index 7c3522c..1cd9d59 100644
--- a/src/main.tsx
+++ b/src/main.tsx
@@ -4,6 +4,7 @@ import { useState, useEffect } from "preact/hooks";
import { App } from "@/pages/App";
import { Tr, langCodeContext, LANG_OPTIONS } from "@/translate";
import { SidebarProvider } from "@/components/ui/sidebar";
+import { Toaster } from "@/components/ui/toaster";
function Base() {
const [langCode, _setLangCode] = useState("en-US");
@@ -49,6 +50,7 @@ function Base() {
+
);
diff --git a/src/pages/App.tsx b/src/pages/App.tsx
index 4356ebc..7ce3b37 100644
--- a/src/pages/App.tsx
+++ b/src/pages/App.tsx
@@ -12,10 +12,42 @@ import { newChatStore } from "@/types/newChatstore";
import { STORAGE_NAME, STORAGE_NAME_SELECTED } from "@/const";
import { upgrade } from "@/indexedDB/upgrade";
+import {
+ Sidebar,
+ SidebarContent,
+ SidebarFooter,
+ SidebarGroup,
+ SidebarGroupContent,
+ SidebarGroupLabel,
+ SidebarHeader,
+ SidebarMenu,
+ SidebarMenuButton,
+ SidebarMenuItem,
+ SidebarRail,
+ SidebarInset,
+ SidebarTrigger,
+} from "@/components/ui/sidebar";
+import { Button } from "@/components/ui/button";
+
+import {
+ AlertDialog,
+ AlertDialogAction,
+ AlertDialogCancel,
+ AlertDialogContent,
+ AlertDialogDescription,
+ AlertDialogFooter,
+ AlertDialogHeader,
+ AlertDialogTitle,
+ AlertDialogTrigger,
+} from "@/components/ui/alert-dialog";
+
+import { useToast } from "@/hooks/use-toast";
+import { Separator } from "@/components/ui/separator";
+
export function App() {
// init selected index
const [selectedChatIndex, setSelectedChatIndex] = useState(
- parseInt(localStorage.getItem(STORAGE_NAME_SELECTED) ?? "1"),
+ parseInt(localStorage.getItem(STORAGE_NAME_SELECTED) ?? "1")
);
console.log("selectedChatIndex", selectedChatIndex);
useEffect(() => {
@@ -27,6 +59,8 @@ export function App() {
upgrade,
});
+ const { toast } = useToast();
+
const getChatStoreByIndex = async (index: number): Promise => {
const ret: ChatStore = await (await db).get(STORAGE_NAME, index);
if (ret === null || ret === undefined) return newChatStore({});
@@ -54,7 +88,7 @@ export function App() {
const max = chatStore.maxTokens - chatStore.tokenMargin;
let sum = 0;
chatStore.postBeginIndex = chatStore.history.filter(
- ({ hide }) => !hide,
+ ({ hide }) => !hide
).length;
for (const msg of chatStore.history
.filter(({ hide }) => !hide)
@@ -69,7 +103,7 @@ export function App() {
// manually estimate token
chatStore.totalTokens = calculate_token_length(
- chatStore.systemMessageContent,
+ chatStore.systemMessageContent
);
for (const msg of chatStore.history
.filter(({ hide }) => !hide)
@@ -82,7 +116,7 @@ export function App() {
// update total tokens
chatStore.totalTokens = calculate_token_length(
- chatStore.systemMessageContent,
+ chatStore.systemMessageContent
);
for (const msg of chatStore.history
.filter(({ hide }) => !hide)
@@ -101,7 +135,7 @@ export function App() {
// all chat store indexes
const [allChatStoreIndexes, setAllChatStoreIndexes] = useState(
- [],
+ []
);
const handleNewChatStoreWithOldOne = async (chatStore: ChatStore) => {
@@ -114,7 +148,6 @@ export function App() {
};
const handleDEL = async () => {
- if (!confirm("Are you sure you want to delete this chat history?")) return;
console.log("remove item", `${STORAGE_NAME}-${selectedChatIndex}`);
(await db).delete(STORAGE_NAME, selectedChatIndex);
const newAllChatStoreIndexes = await (await db).getAllKeys(STORAGE_NAME);
@@ -129,6 +162,11 @@ export function App() {
console.log("next is", next);
setSelectedChatIndex(next as number);
setAllChatStoreIndexes(newAllChatStoreIndexes);
+
+ toast({
+ title: "Chat history deleted",
+ description: `Chat history ${selectedChatIndex} has been deleted.`,
+ });
};
const handleCLS = async () => {
@@ -176,60 +214,87 @@ export function App() {
}, []);
return (
-
-
-
-
-
- {(allChatStoreIndexes as number[])
- .slice()
- .reverse()
- .map((i) => {
- // reverse
- return (
- -
-
-
- );
- })}
-
-
-
-
+ <>
+
+
+
+
+
+
+ Conversation
+
+
+ {(allChatStoreIndexes as number[])
+ .slice()
+ .reverse()
+ .map((i) => {
+ // reverse
+ return (
+ setSelectedChatIndex(i)}
+ >
+
+ {i}
+
+
+ );
+ })}
+
+
+
+
+
+
+
+
+
+
+
+ Are you absolutely sure?
+
+ This action cannot be undone. This will permanently delete the
+ chat history.
+
+
+
+ Cancel
+
+ Delete
+
+
+
+
+
{chatStore.develop_mode && (
-
+
)}
-
-
-
-
+
+
+
+
+
+
+
+ >
);
}
diff --git a/src/pages/Chatbox.tsx b/src/pages/Chatbox.tsx
index fe34fa7..1bb3390 100644
--- a/src/pages/Chatbox.tsx
+++ b/src/pages/Chatbox.tsx
@@ -131,7 +131,7 @@ export default function ChatBOX(props: {
// update tool call arguments
const tool = allChunkTool.find(
- (tool) => tool.index === tool_call.index,
+ (tool) => tool.index === tool_call.index
);
if (!tool) {
@@ -146,7 +146,7 @@ export default function ChatBOX(props: {
allChunkMessage.join("") +
allChunkTool.map((tool) => {
return `Tool Call ID: ${tool.id}\nType: ${tool.type}\nFunction: ${tool.function.name}\nArguments: ${tool.function.arguments}`;
- }),
+ })
);
}
setShowGenerating(false);
@@ -295,7 +295,7 @@ export default function ChatBOX(props: {
setShowGenerating(true);
const response = await client._fetch(
chatStore.streamMode,
- chatStore.logprobs,
+ chatStore.logprobs
);
const contentType = response.headers.get("content-type");
if (contentType?.startsWith("text/event-stream")) {
@@ -365,33 +365,33 @@ export default function ChatBOX(props: {
const [templates, _setTemplates] = useState(
JSON.parse(
- localStorage.getItem(STORAGE_NAME_TEMPLATE) || "[]",
- ) as TemplateChatStore[],
+ localStorage.getItem(STORAGE_NAME_TEMPLATE) || "[]"
+ ) as TemplateChatStore[]
);
const [templateAPIs, _setTemplateAPIs] = useState(
JSON.parse(
- localStorage.getItem(STORAGE_NAME_TEMPLATE_API) || "[]",
- ) as TemplateAPI[],
+ localStorage.getItem(STORAGE_NAME_TEMPLATE_API) || "[]"
+ ) as TemplateAPI[]
);
const [templateAPIsWhisper, _setTemplateAPIsWhisper] = useState(
JSON.parse(
- localStorage.getItem(STORAGE_NAME_TEMPLATE_API_WHISPER) || "[]",
- ) as TemplateAPI[],
+ localStorage.getItem(STORAGE_NAME_TEMPLATE_API_WHISPER) || "[]"
+ ) as TemplateAPI[]
);
const [templateAPIsTTS, _setTemplateAPIsTTS] = useState(
JSON.parse(
- localStorage.getItem(STORAGE_NAME_TEMPLATE_API_TTS) || "[]",
- ) as TemplateAPI[],
+ 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[],
+ localStorage.getItem(STORAGE_NAME_TEMPLATE_API_IMAGE_GEN) || "[]"
+ ) as TemplateAPI[]
);
const [toolsTemplates, _setToolsTemplates] = useState(
JSON.parse(
- localStorage.getItem(STORAGE_NAME_TEMPLATE_TOOLS) || "[]",
- ) as TemplateTools[],
+ localStorage.getItem(STORAGE_NAME_TEMPLATE_TOOLS) || "[]"
+ ) as TemplateTools[]
);
const setTemplates = (templates: TemplateChatStore[]) => {
localStorage.setItem(STORAGE_NAME_TEMPLATE, JSON.stringify(templates));
@@ -400,35 +400,35 @@ export default function ChatBOX(props: {
const setTemplateAPIs = (templateAPIs: TemplateAPI[]) => {
localStorage.setItem(
STORAGE_NAME_TEMPLATE_API,
- JSON.stringify(templateAPIs),
+ JSON.stringify(templateAPIs)
);
_setTemplateAPIs(templateAPIs);
};
const setTemplateAPIsWhisper = (templateAPIWhisper: TemplateAPI[]) => {
localStorage.setItem(
STORAGE_NAME_TEMPLATE_API_WHISPER,
- JSON.stringify(templateAPIWhisper),
+ JSON.stringify(templateAPIWhisper)
);
_setTemplateAPIsWhisper(templateAPIWhisper);
};
const setTemplateAPIsTTS = (templateAPITTS: TemplateAPI[]) => {
localStorage.setItem(
STORAGE_NAME_TEMPLATE_API_TTS,
- JSON.stringify(templateAPITTS),
+ JSON.stringify(templateAPITTS)
);
_setTemplateAPIsTTS(templateAPITTS);
};
const setTemplateAPIsImageGen = (templateAPIImageGen: TemplateAPI[]) => {
localStorage.setItem(
STORAGE_NAME_TEMPLATE_API_IMAGE_GEN,
- JSON.stringify(templateAPIImageGen),
+ JSON.stringify(templateAPIImageGen)
);
_setTemplateAPIsImageGen(templateAPIImageGen);
};
const setTemplateTools = (templateTools: TemplateTools[]) => {
localStorage.setItem(
STORAGE_NAME_TEMPLATE_TOOLS,
- JSON.stringify(templateTools),
+ JSON.stringify(templateTools)
);
_setToolsTemplates(templateTools);
};
@@ -574,7 +574,7 @@ export default function ChatBOX(props: {
↖{Tr("Click the conor to create a new chat")}
⚠
{Tr(
- "All chat history and settings are stored in the local browser",
+ "All chat history and settings are stored in the local browser"
)}
diff --git a/src/setAPIsTemplate.tsx b/src/setAPIsTemplate.tsx
index c3a3319..0bb2936 100644
--- a/src/setAPIsTemplate.tsx
+++ b/src/setAPIsTemplate.tsx
@@ -1,5 +1,6 @@
import { TemplateAPI } from "@/types/chatstore";
import { Tr } from "@/translate";
+import { Button } from "./components/ui/button";
interface Props {
tmps: TemplateAPI[];
@@ -16,8 +17,10 @@ export function SetAPIsTemplate({
label,
}: Props) {
return (
-
+
);
}
diff --git a/src/settings.tsx b/src/settings.tsx
index 9b92712..8b0a1d6 100644
--- a/src/settings.tsx
+++ b/src/settings.tsx
@@ -1,17 +1,4 @@
import { themeChange } from "theme-change";
-import {
- InformationCircleIcon,
- CheckIcon,
- NoSymbolIcon,
- CogIcon,
- KeyIcon,
- EyeIcon,
- EllipsisHorizontalCircleIcon,
- HandRaisedIcon,
- AdjustmentsHorizontalIcon,
- Cog6ToothIcon,
- ListBulletIcon,
-} from "@heroicons/react/24/outline";
import { createRef } from "preact";
import {
@@ -35,6 +22,64 @@ import { SetAPIsTemplate } from "@/setAPIsTemplate";
import { autoHeight } from "@/textarea";
import { getDefaultParams } from "@/utils/getDefaultParam";
+import { Button } from "@/components/ui/button";
+import { Input } from "@/components/ui/input";
+import { Label } from "@/components/ui/label";
+import {
+ Sheet,
+ SheetClose,
+ SheetContent,
+ SheetDescription,
+ SheetFooter,
+ SheetHeader,
+ SheetTitle,
+ SheetTrigger,
+} from "@/components/ui/sheet";
+import {
+ Accordion,
+ AccordionContent,
+ AccordionItem,
+ AccordionTrigger,
+} from "@/components/ui/accordion";
+import {
+ Card,
+ CardContent,
+ CardDescription,
+ CardHeader,
+ CardTitle,
+} from "@/components/ui/card";
+import {
+ Tooltip,
+ TooltipContent,
+ TooltipProvider,
+ TooltipTrigger,
+} from "@/components/ui/tooltip";
+import {
+ Dialog,
+ DialogContent,
+ DialogDescription,
+ DialogFooter,
+ DialogHeader,
+ DialogTitle,
+ DialogTrigger,
+} from "@/components/ui/dialog";
+import { Checkbox } from "@/components/ui/checkbox";
+import { Textarea } from "@/components/ui/textarea";
+import {
+ BanIcon,
+ CheckIcon,
+ CircleEllipsisIcon,
+ CogIcon,
+ Ellipsis,
+ EyeIcon,
+ InfoIcon,
+ KeyIcon,
+ ListIcon,
+ MoveHorizontalIcon,
+} from "lucide-react";
+import { Separator } from "./components/ui/separator";
+import { Slider } from "./components/ui/slider";
+
const TTS_VOICES: string[] = [
"alloy",
"echo",
@@ -66,65 +111,68 @@ const SelectModel = (props: {
}
const [useCustomModel, setUseCustomModel] = useState(shouldIUseCustomModel);
return (
-
-
-
-
+
+
-
+
+
+
+
setUseCustomModel(!useCustomModel)}
/>
- ) : (
-
- )}
-
-
-
+
+
+
+ {useCustomModel ? (
+ ) => {
+ props.chatStore.model = e.target.value;
+ props.setChatStore({ ...props.chatStore });
+ }}
+ />
+ ) : (
+
+ )}
+
);
};
@@ -136,21 +184,26 @@ const LongInput = (props: {
help: string;
}) => {
return (
-
+ />
+
);
};
-const Input = (props: {
+const InputField = (props: {
chatStore: ChatStore;
setChatStore: (cs: ChatStore) => void;
field:
@@ -181,49 +234,49 @@ const Input = (props: {
}) => {
const [hideInput, setHideInput] = useState(true);
return (
-
-
- {props.field}
-
-
-
-
-