diff --git a/src/components/App.tsx b/src/components/App.tsx
index c1d6f59..a9bceff 100644
--- a/src/components/App.tsx
+++ b/src/components/App.tsx
@@ -109,7 +109,7 @@ export function App() {
}}
>
-
+
diff --git a/src/components/ChatHeader.tsx b/src/components/ChatHeader.tsx
index 7e1d333..03d5a32 100644
--- a/src/components/ChatHeader.tsx
+++ b/src/components/ChatHeader.tsx
@@ -68,11 +68,19 @@ export function ChatHeader() {
/>
-
-
-
-
-
+
+ ({
+ [theme.fn.smallerThan('md')]: {
+ marginRight: '2.5rem',
+ paddingBottom: 3,
+ },
+ })}
+ >
+
+
+
diff --git a/src/components/Layout.tsx b/src/components/Layout.tsx
index 125c258..d8050d3 100644
--- a/src/components/Layout.tsx
+++ b/src/components/Layout.tsx
@@ -153,29 +153,20 @@ export function Layout() {
}}
/>
-
-
-
-
-
-
-
-
-
- setOpened((o) => !o)}
- size="sm"
- color={theme.colors.gray[6]}
- className="app-region-no-drag"
- />
-
-
+
+
+ ({
+ [theme.fn.smallerThan('md')]: {
+ marginRight: '2.5rem',
+ },
+ })}
+ >
+
+
+
+
}
- {/*
-
- {config.allowDarkModeToggle && (
-
- toggleColorScheme()}
- >
- {colorScheme === "dark" ? (
-
- ) : (
-
- )}
-
-
- )}
- {config.allowSettingsModal && (
-
-
-
-
-
-
-
- )}
- {config.githubUrl && (
-
-
-
-
-
- )}
- {config.showTwitterLink && (
-
-
-
-
-
- )}
- {config.showFeedbackLink && (
-
- {
- if (window.todesktop) {
- event.preventDefault();
- window.todesktop.contents.openUrlInBrowser(
- "https://feedback.chatpad.ai"
- );
- }
- }}
- target="_blank"
- sx={{ flex: 1 }}
- size="xl"
- >
-
-
-
- )}
-
- */}
}
header={
diff --git a/src/routes/ChatRoute.tsx b/src/routes/ChatRoute.tsx
index 1c36f5a..3a5d2be 100644
--- a/src/routes/ChatRoute.tsx
+++ b/src/routes/ChatRoute.tsx
@@ -4,7 +4,6 @@ import {
Card,
Container,
Flex,
- MediaQuery,
Select,
Skeleton,
Stack,
@@ -12,7 +11,7 @@ import {
} from "@mantine/core";
import { notifications } from "@mantine/notifications";
import { KeyboardEvent, useState, type ChangeEvent, useEffect } from "react";
-import { AiOutlineSend } from "react-icons/ai";
+import { IconSend, IconPlayerStop } from "@tabler/icons-react";
import { MessageItem } from "../components/MessageItem";
import { Message, Prompt, detaDB, generateKey } from "../db";
import { useChatId } from "../hooks/useChatId";
@@ -56,6 +55,9 @@ export function ChatRoute() {
const [content, setContent] = useState("");
const [contentDraft, setContentDraft] = useState("");
const [submitting, setSubmitting] = useState(false);
+ const [generating, setGenerating] = useState(false);
+ const [coolDown, setCoolDown] = useState(false);
+ const [chatStream, setChatStream] = useState(null);
const [promptKey, setPromptKey] = useState(null);
const [newPromptTitle, setNewPromptTitle] = useState(null);
const [selectedModel, setSelectedModel] = useState(null);
@@ -69,13 +71,8 @@ export function ChatRoute() {
}
}, [chat]);
- // const chat = useLiveQuery(async () => {
- // if (!chatId) return null;
- // return db.chats.get(chatId);
- // }, [chatId]);
-
const submit = async () => {
- if (submitting) return;
+ if (submitting || coolDown) return;
if (!chatId) {
notifications.show({
@@ -161,9 +158,10 @@ export function ChatRoute() {
}, generateKey())
setMessages(current => [...current, systemMessage as unknown as Message])
+ setGenerating(true)
const messageId = systemMessage!.key as string
- await createStreamChatCompletion(
+ const chatCompletionStream = createStreamChatCompletion(
{ ...settings, openAiModel: model },
[
{
@@ -186,9 +184,16 @@ export function ChatRoute() {
return message;
}));
- }
+ },
+ () => {
+ setGenerating(false)
+ setChatStream(null)
+ setCoolDown(true);
+ setTimeout(() => setCoolDown(false), 500);
+ },
);
+ setChatStream(chatCompletionStream)
setSubmitting(false);
if (chat?.description === "New Chat") {
@@ -247,6 +252,7 @@ export function ChatRoute() {
}
}
} catch (error: any) {
+ setGenerating(false)
if (error.toJSON().message === "Network Error") {
notifications.show({
title: "Error",
@@ -267,6 +273,13 @@ export function ChatRoute() {
}
};
+ const stopGeneration = async () => {
+ if (chatStream) {
+ chatStream.abort()
+ setChatStream(null)
+ }
+ }
+
const onUserMsgToggle = (event: KeyboardEvent) => {
const { selectionStart, selectionEnd } = event.currentTarget;
if (
@@ -345,7 +358,7 @@ export function ChatRoute() {
mb="sm"
style={{
display: "flex",
- justifyContent: "flex-end",
+ justifyContent: "flex-start",
alignItems: "center",
gap: 10,
}}
@@ -384,66 +397,18 @@ export function ChatRoute() {
{newPromptTitle && }
- //
- //
- //
- //
- //
- //
)}
-
+
diff --git a/src/utils/openai.ts b/src/utils/openai.ts
index 6120f73..ab8562b 100644
--- a/src/utils/openai.ts
+++ b/src/utils/openai.ts
@@ -21,12 +21,13 @@ function getClient(
return new OpenAIApi(configuration);
}
-export async function createStreamChatCompletion(
+export function createStreamChatCompletion(
settings: Settings,
messages: ChatCompletionRequestMessage[],
chatId: string,
messageId: string,
- onContent: (content: string, isFinal: boolean) => void
+ onContent: (content: string, isFinal: boolean) => void,
+ onDone: () => void
) {
const model = settings?.openAiModel ?? config.defaultModel;
@@ -47,9 +48,11 @@ export async function createStreamChatCompletion(
}
onContent(content, isFinal);
},
- onDone() {},
+ onDone() {
+ onDone()
+ },
onError(error) {
- console.error(error);
+ throw error;
},
},
}