clean up chatStore
This commit is contained in:
@@ -1,8 +1,13 @@
|
|||||||
import { ChatStore } from "@/types/chatstore";
|
import { ChatStore } from "@/types/chatstore";
|
||||||
import { Tr } from "@/translate";
|
import { Tr } from "@/translate";
|
||||||
|
import { useContext } from "react";
|
||||||
|
import { AppContext } from "@/pages/App";
|
||||||
|
|
||||||
const VersionHint = (props: { chatStore: ChatStore }) => {
|
const VersionHint = () => {
|
||||||
const { chatStore } = props;
|
const ctx = useContext(AppContext);
|
||||||
|
if (!ctx) return <div>error</div>;
|
||||||
|
|
||||||
|
const { chatStore } = ctx;
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{chatStore.chatgpt_api_web_version < "v1.3.0" && (
|
{chatStore.chatgpt_api_web_version < "v1.3.0" && (
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { createRef } from "react";
|
import { createRef, useContext } from "react";
|
||||||
|
|
||||||
import { ChatStore } from "@/types/chatstore";
|
import { ChatStore } from "@/types/chatstore";
|
||||||
import { useEffect, useState, Dispatch } from "react";
|
import { useEffect, useState, Dispatch } from "react";
|
||||||
@@ -10,13 +10,17 @@ import {
|
|||||||
MicIcon,
|
MicIcon,
|
||||||
VoicemailIcon,
|
VoicemailIcon,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
|
import { AppContext } from "@/pages/App";
|
||||||
|
|
||||||
const WhisperButton = (props: {
|
const WhisperButton = (props: {
|
||||||
chatStore: ChatStore;
|
|
||||||
inputMsg: string;
|
inputMsg: string;
|
||||||
setInputMsg: Dispatch<string>;
|
setInputMsg: Dispatch<string>;
|
||||||
}) => {
|
}) => {
|
||||||
const { chatStore, inputMsg, setInputMsg } = props;
|
const ctx = useContext(AppContext);
|
||||||
|
if (!ctx) return <div>error</div>;
|
||||||
|
const { chatStore } = ctx;
|
||||||
|
|
||||||
|
const { inputMsg, setInputMsg } = props;
|
||||||
const mediaRef = createRef();
|
const mediaRef = createRef();
|
||||||
const [isRecording, setIsRecording] = useState("Mic");
|
const [isRecording, setIsRecording] = useState("Mic");
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useState, useEffect, Dispatch } from "react";
|
import { useState, useEffect, Dispatch, useContext } from "react";
|
||||||
import { Tr, langCodeContext, LANG_OPTIONS, tr } from "@/translate";
|
import { Tr, langCodeContext, LANG_OPTIONS, tr } from "@/translate";
|
||||||
import { ChatStore, ChatStoreMessage } from "@/types/chatstore";
|
import { ChatStore, ChatStoreMessage } from "@/types/chatstore";
|
||||||
import { EditMessageString } from "@/editMessageString";
|
import { EditMessageString } from "@/editMessageString";
|
||||||
@@ -13,16 +13,18 @@ import {
|
|||||||
DialogTrigger,
|
DialogTrigger,
|
||||||
} from "@/components/ui/dialog";
|
} from "@/components/ui/dialog";
|
||||||
import { Button } from "./components/ui/button";
|
import { Button } from "./components/ui/button";
|
||||||
|
import { AppContext } from "./pages/App";
|
||||||
|
|
||||||
interface EditMessageProps {
|
interface EditMessageProps {
|
||||||
chat: ChatStoreMessage;
|
chat: ChatStoreMessage;
|
||||||
chatStore: ChatStore;
|
|
||||||
showEdit: boolean;
|
showEdit: boolean;
|
||||||
setShowEdit: Dispatch<boolean>;
|
setShowEdit: Dispatch<boolean>;
|
||||||
setChatStore: (cs: ChatStore) => void;
|
|
||||||
}
|
}
|
||||||
export function EditMessage(props: EditMessageProps) {
|
export function EditMessage(props: EditMessageProps) {
|
||||||
const { showEdit, setShowEdit, chat, setChatStore, chatStore } = props;
|
const ctx = useContext(AppContext);
|
||||||
|
if (!ctx) return <div>error</div>;
|
||||||
|
|
||||||
|
const { showEdit, setShowEdit, chat } = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog open={showEdit} onOpenChange={setShowEdit}>
|
<Dialog open={showEdit} onOpenChange={setShowEdit}>
|
||||||
@@ -37,21 +39,11 @@ export function EditMessage(props: EditMessageProps) {
|
|||||||
</DialogDescription>
|
</DialogDescription>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
{typeof chat.content === "string" ? (
|
{typeof chat.content === "string" ? (
|
||||||
<EditMessageString
|
<EditMessageString chat={chat} setShowEdit={setShowEdit} />
|
||||||
chat={chat}
|
|
||||||
chatStore={chatStore}
|
|
||||||
setChatStore={setChatStore}
|
|
||||||
setShowEdit={setShowEdit}
|
|
||||||
/>
|
|
||||||
) : (
|
) : (
|
||||||
<EditMessageDetail
|
<EditMessageDetail chat={chat} setShowEdit={setShowEdit} />
|
||||||
chat={chat}
|
|
||||||
chatStore={chatStore}
|
|
||||||
setChatStore={setChatStore}
|
|
||||||
setShowEdit={setShowEdit}
|
|
||||||
/>
|
|
||||||
)}
|
)}
|
||||||
{chatStore.develop_mode && (
|
{ctx.chatStore.develop_mode && (
|
||||||
<Button
|
<Button
|
||||||
variant="destructive"
|
variant="destructive"
|
||||||
className="w-full"
|
className="w-full"
|
||||||
@@ -66,7 +58,7 @@ export function EditMessage(props: EditMessageProps) {
|
|||||||
} else {
|
} else {
|
||||||
chat.content = "";
|
chat.content = "";
|
||||||
}
|
}
|
||||||
setChatStore({ ...chatStore });
|
ctx.setChatStore({ ...ctx.chatStore });
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Switch to{" "}
|
Switch to{" "}
|
||||||
|
|||||||
@@ -14,19 +14,19 @@ import {
|
|||||||
} from "@/components/ui/drawer";
|
} from "@/components/ui/drawer";
|
||||||
|
|
||||||
import { Button } from "./components/ui/button";
|
import { Button } from "./components/ui/button";
|
||||||
|
import { useContext } from "react";
|
||||||
|
import { AppContext } from "./pages/App";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
chat: ChatStoreMessage;
|
chat: ChatStoreMessage;
|
||||||
chatStore: ChatStore;
|
|
||||||
setChatStore: (cs: ChatStore) => void;
|
|
||||||
setShowEdit: (se: boolean) => void;
|
setShowEdit: (se: boolean) => void;
|
||||||
}
|
}
|
||||||
export function EditMessageDetail({
|
export function EditMessageDetail({ chat, setShowEdit }: Props) {
|
||||||
chat,
|
const ctx = useContext(AppContext);
|
||||||
chatStore,
|
if (!ctx) return <div>error</div>;
|
||||||
setChatStore,
|
|
||||||
setShowEdit,
|
const { chatStore, setChatStore } = ctx;
|
||||||
}: Props) {
|
|
||||||
if (typeof chat.content !== "object") return <div>error</div>;
|
if (typeof chat.content !== "object") return <div>error</div>;
|
||||||
return (
|
return (
|
||||||
<Drawer open={true} onOpenChange={setShowEdit}>
|
<Drawer open={true} onOpenChange={setShowEdit}>
|
||||||
|
|||||||
@@ -4,19 +4,19 @@ import { calculate_token_length } from "@/chatgpt";
|
|||||||
import { Tr } from "@/translate";
|
import { Tr } from "@/translate";
|
||||||
|
|
||||||
import { Textarea } from "@/components/ui/textarea";
|
import { Textarea } from "@/components/ui/textarea";
|
||||||
|
import { useContext } from "react";
|
||||||
|
import { AppContext } from "./pages/App";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
chat: ChatStoreMessage;
|
chat: ChatStoreMessage;
|
||||||
chatStore: ChatStore;
|
|
||||||
setChatStore: (cs: ChatStore) => void;
|
|
||||||
setShowEdit: (se: boolean) => void;
|
setShowEdit: (se: boolean) => void;
|
||||||
}
|
}
|
||||||
export function EditMessageString({
|
export function EditMessageString({ chat, setShowEdit }: Props) {
|
||||||
chat,
|
const ctx = useContext(AppContext);
|
||||||
chatStore,
|
if (!ctx) return <div>error</div>;
|
||||||
setChatStore,
|
|
||||||
setShowEdit,
|
const { chatStore, setChatStore } = ctx;
|
||||||
}: Props) {
|
|
||||||
if (typeof chat.content !== "string") return <div>error</div>;
|
if (typeof chat.content !== "string") return <div>error</div>;
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
|
|||||||
@@ -12,19 +12,15 @@ import {
|
|||||||
} from "@/components/ui/navigation-menu";
|
} from "@/components/ui/navigation-menu";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import { Button } from "./components/ui/button";
|
import { Button } from "./components/ui/button";
|
||||||
|
import { useContext } from "react";
|
||||||
|
import { AppContext } from "./pages/App";
|
||||||
|
|
||||||
|
export function ListToolsTempaltes() {
|
||||||
|
const ctx = useContext(AppContext);
|
||||||
|
if (!ctx) return <div>error</div>;
|
||||||
|
|
||||||
|
const { chatStore, setChatStore } = ctx;
|
||||||
|
|
||||||
interface Props {
|
|
||||||
templateTools: TemplateTools[];
|
|
||||||
setTemplateTools: (tmps: TemplateTools[]) => void;
|
|
||||||
chatStore: ChatStore;
|
|
||||||
setChatStore: (cs: ChatStore) => void;
|
|
||||||
}
|
|
||||||
export function ListToolsTempaltes({
|
|
||||||
chatStore,
|
|
||||||
templateTools,
|
|
||||||
setTemplateTools,
|
|
||||||
setChatStore,
|
|
||||||
}: Props) {
|
|
||||||
return (
|
return (
|
||||||
<NavigationMenuItem className="p-3">
|
<NavigationMenuItem className="p-3">
|
||||||
<NavigationMenuTrigger>
|
<NavigationMenuTrigger>
|
||||||
@@ -42,7 +38,7 @@ export function ListToolsTempaltes({
|
|||||||
</NavigationMenuTrigger>
|
</NavigationMenuTrigger>
|
||||||
<NavigationMenuContent>
|
<NavigationMenuContent>
|
||||||
<ul className="grid w-[400px] gap-3 p-4 md:w-[500px] md:grid-cols-2 lg:w-[600px]">
|
<ul className="grid w-[400px] gap-3 p-4 md:w-[500px] md:grid-cols-2 lg:w-[600px]">
|
||||||
{templateTools.map((t, index) => (
|
{ctx.templateTools.map((t, index) => (
|
||||||
<li key={index}>
|
<li key={index}>
|
||||||
<NavigationMenuLink asChild>
|
<NavigationMenuLink asChild>
|
||||||
<a
|
<a
|
||||||
@@ -73,7 +69,7 @@ export function ListToolsTempaltes({
|
|||||||
const name = prompt(`Give **tools** template a name`);
|
const name = prompt(`Give **tools** template a name`);
|
||||||
if (!name) return;
|
if (!name) return;
|
||||||
t.name = name;
|
t.name = name;
|
||||||
setTemplateTools(structuredClone(templateTools));
|
ctx.setTemplateTools(structuredClone(ctx.templateTools));
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Edit
|
Edit
|
||||||
@@ -89,8 +85,8 @@ export function ListToolsTempaltes({
|
|||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
templateTools.splice(index, 1);
|
ctx.templateTools.splice(index, 1);
|
||||||
setTemplateTools(structuredClone(templateTools));
|
ctx.setTemplateTools(structuredClone(ctx.templateTools));
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Delete
|
Delete
|
||||||
|
|||||||
@@ -208,23 +208,11 @@ export default function Message(props: { messageIndex: number }) {
|
|||||||
icon={<ClipboardIcon className="size-4" />}
|
icon={<ClipboardIcon className="size-4" />}
|
||||||
onClick={() => copyToClipboard(getMessageText(chat))}
|
onClick={() => copyToClipboard(getMessageText(chat))}
|
||||||
/>
|
/>
|
||||||
{chatStore.tts_api && chatStore.tts_key && (
|
{chatStore.tts_api && chatStore.tts_key && <TTSButton chat={chat} />}
|
||||||
<TTSButton
|
|
||||||
chatStore={chatStore}
|
|
||||||
chat={chat}
|
|
||||||
setChatStore={setChatStore}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
<TTSPlay chat={chat} />
|
<TTSPlay chat={chat} />
|
||||||
</ChatBubbleActionWrapper>
|
</ChatBubbleActionWrapper>
|
||||||
</ChatBubble>
|
</ChatBubble>
|
||||||
<EditMessage
|
<EditMessage showEdit={showEdit} setShowEdit={setShowEdit} chat={chat} />
|
||||||
showEdit={showEdit}
|
|
||||||
setShowEdit={setShowEdit}
|
|
||||||
chat={chat}
|
|
||||||
chatStore={chatStore}
|
|
||||||
setChatStore={setChatStore}
|
|
||||||
/>
|
|
||||||
{chatStore.develop_mode && (
|
{chatStore.develop_mode && (
|
||||||
<div
|
<div
|
||||||
className={`flex flex-wrap items-center gap-2 mt-2 ${
|
className={`flex flex-wrap items-center gap-2 mt-2 ${
|
||||||
|
|||||||
@@ -454,14 +454,7 @@ export default function ChatBOX() {
|
|||||||
keyField="image_gen_key"
|
keyField="image_gen_key"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{ctx.templateTools.length > 0 && (
|
{ctx.templateTools.length > 0 && <ListToolsTempaltes />}
|
||||||
<ListToolsTempaltes
|
|
||||||
templateTools={ctx.templateTools}
|
|
||||||
setTemplateTools={ctx.setTemplateTools}
|
|
||||||
chatStore={chatStore}
|
|
||||||
setChatStore={setChatStore}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</NavigationMenuList>
|
</NavigationMenuList>
|
||||||
</NavigationMenu>
|
</NavigationMenu>
|
||||||
</div>
|
</div>
|
||||||
@@ -599,7 +592,7 @@ export default function ChatBOX() {
|
|||||||
</Alert>
|
</Alert>
|
||||||
)}
|
)}
|
||||||
</p>
|
</p>
|
||||||
<VersionHint chatStore={chatStore} />
|
<VersionHint />
|
||||||
{showRetry && (
|
{showRetry && (
|
||||||
<p className="text-right p-2 my-2 dark:text-white">
|
<p className="text-right p-2 my-2 dark:text-white">
|
||||||
<Button
|
<Button
|
||||||
@@ -681,7 +674,6 @@ export default function ChatBOX() {
|
|||||||
{chatStore.whisper_api && chatStore.whisper_key && (
|
{chatStore.whisper_api && chatStore.whisper_key && (
|
||||||
<>
|
<>
|
||||||
<WhisperButton
|
<WhisperButton
|
||||||
chatStore={chatStore}
|
|
||||||
inputMsg={inputMsg}
|
inputMsg={inputMsg}
|
||||||
setInputMsg={setInputMsg}
|
setInputMsg={setInputMsg}
|
||||||
/>
|
/>
|
||||||
|
|||||||
26
src/tts.tsx
26
src/tts.tsx
@@ -1,16 +1,15 @@
|
|||||||
import { SpeakerWaveIcon } from "@heroicons/react/24/outline";
|
import { SpeakerWaveIcon } from "@heroicons/react/24/outline";
|
||||||
import { useMemo, useState } from "react";
|
import { useContext, useMemo, useState } from "react";
|
||||||
|
|
||||||
import { addTotalCost } from "@/utils/totalCost";
|
import { addTotalCost } from "@/utils/totalCost";
|
||||||
import { ChatStore, ChatStoreMessage } from "@/types/chatstore";
|
import { ChatStore, ChatStoreMessage } from "@/types/chatstore";
|
||||||
import { Message, getMessageText } from "@/chatgpt";
|
import { Message, getMessageText } from "@/chatgpt";
|
||||||
import { AudioLinesIcon, LoaderCircleIcon } from "lucide-react";
|
import { AudioLinesIcon, LoaderCircleIcon } from "lucide-react";
|
||||||
import { Button } from "./components/ui/button";
|
import { Button } from "./components/ui/button";
|
||||||
|
import { AppContext } from "./pages/App";
|
||||||
|
|
||||||
interface TTSProps {
|
interface TTSProps {
|
||||||
chatStore: ChatStore;
|
|
||||||
chat: ChatStoreMessage;
|
chat: ChatStoreMessage;
|
||||||
setChatStore: (cs: ChatStore) => void;
|
|
||||||
}
|
}
|
||||||
interface TTSPlayProps {
|
interface TTSPlayProps {
|
||||||
chat: ChatStoreMessage;
|
chat: ChatStoreMessage;
|
||||||
@@ -33,25 +32,28 @@ export function TTSPlay(props: TTSPlayProps) {
|
|||||||
}
|
}
|
||||||
export default function TTSButton(props: TTSProps) {
|
export default function TTSButton(props: TTSProps) {
|
||||||
const [generating, setGenerating] = useState(false);
|
const [generating, setGenerating] = useState(false);
|
||||||
|
const ctx = useContext(AppContext);
|
||||||
|
if (!ctx) return <div>error</div>;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
size="icon"
|
size="icon"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
const api = props.chatStore.tts_api;
|
const api = ctx.chatStore.tts_api;
|
||||||
const api_key = props.chatStore.tts_key;
|
const api_key = ctx.chatStore.tts_key;
|
||||||
const model = "tts-1";
|
const model = "tts-1";
|
||||||
const input = getMessageText(props.chat);
|
const input = getMessageText(props.chat);
|
||||||
const voice = props.chatStore.tts_voice;
|
const voice = ctx.chatStore.tts_voice;
|
||||||
|
|
||||||
const body: Record<string, any> = {
|
const body: Record<string, any> = {
|
||||||
model,
|
model,
|
||||||
input,
|
input,
|
||||||
voice,
|
voice,
|
||||||
response_format: props.chatStore.tts_format || "mp3",
|
response_format: ctx.chatStore.tts_format || "mp3",
|
||||||
};
|
};
|
||||||
if (props.chatStore.tts_speed_enabled) {
|
if (ctx.chatStore.tts_speed_enabled) {
|
||||||
body["speed"] = props.chatStore.tts_speed;
|
body["speed"] = ctx.chatStore.tts_speed;
|
||||||
}
|
}
|
||||||
|
|
||||||
setGenerating(true);
|
setGenerating(true);
|
||||||
@@ -68,13 +70,13 @@ export default function TTSButton(props: TTSProps) {
|
|||||||
.then((blob) => {
|
.then((blob) => {
|
||||||
// update price
|
// update price
|
||||||
const cost = (input.length * 0.015) / 1000;
|
const cost = (input.length * 0.015) / 1000;
|
||||||
props.chatStore.cost += cost;
|
ctx.chatStore.cost += cost;
|
||||||
addTotalCost(cost);
|
addTotalCost(cost);
|
||||||
props.setChatStore({ ...props.chatStore });
|
ctx.setChatStore({ ...ctx.chatStore });
|
||||||
|
|
||||||
// save blob
|
// save blob
|
||||||
props.chat.audio = blob;
|
props.chat.audio = blob;
|
||||||
props.setChatStore({ ...props.chatStore });
|
ctx.setChatStore({ ...ctx.chatStore });
|
||||||
|
|
||||||
const url = URL.createObjectURL(blob);
|
const url = URL.createObjectURL(blob);
|
||||||
const audio = new Audio(url);
|
const audio = new Audio(url);
|
||||||
|
|||||||
Reference in New Issue
Block a user