clean up chatStore

This commit is contained in:
2024-12-27 18:02:14 +08:00
parent 092ac46c15
commit 66a6f263a5
9 changed files with 70 additions and 91 deletions

View File

@@ -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" && (

View File

@@ -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 (

View File

@@ -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{" "}

View File

@@ -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}>

View File

@@ -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">

View File

@@ -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

View File

@@ -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 ${

View File

@@ -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}
/> />

View File

@@ -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);