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