From 3767b2c7f98540934ebfb4862cc13a87b29547dc Mon Sep 17 00:00:00 2001 From: licoy Date: Mon, 15 Jul 2024 15:29:56 +0800 Subject: [PATCH] test --- app/components/sd-panel.tsx | 6 +- app/components/sd.tsx | 55 ++++++++--- app/constant.ts | 2 - app/store/sd.ts | 178 +++++++++++++++++++++--------------- 4 files changed, 150 insertions(+), 91 deletions(-) diff --git a/app/components/sd-panel.tsx b/app/components/sd-panel.tsx index d7476ccf8..12a54c732 100644 --- a/app/components/sd-panel.tsx +++ b/app/components/sd-panel.tsx @@ -6,7 +6,7 @@ import locales from "@/app/locales"; import { nanoid } from "nanoid"; import { useIndexedDB } from "react-indexed-db-hook"; import { StoreKey } from "@/app/constant"; -import { SdDbInit, sendSdTask, useSdStore } from "@/app/store/sd"; +import { SdDbInit, useSdStore } from "@/app/store/sd"; SdDbInit(); @@ -287,7 +287,7 @@ export function SdPanel() { setParams(getModelParamBasicData(model.params({}), params)); }; const sdListDb = useIndexedDB(StoreKey.SdList); - const { execCountInc } = useSdStore(); + const sdStore = useSdStore(); const handleSubmit = () => { const columns = currentModel.params(params); const reqParams: any = {}; @@ -309,7 +309,7 @@ export function SdPanel() { created_at: new Date().toLocaleString(), img_data: "", }; - sendSdTask(data, sdListDb, execCountInc, () => { + sdStore.sendTask(data, sdListDb, () => { setParams(getModelParamBasicData(columns, params, true)); }); }; diff --git a/app/components/sd.tsx b/app/components/sd.tsx index cc0e326e3..02f94ae09 100644 --- a/app/components/sd.tsx +++ b/app/components/sd.tsx @@ -21,7 +21,7 @@ import CopyIcon from "@/app/icons/copy.svg"; import PromptIcon from "@/app/icons/prompt.svg"; import ResetIcon from "@/app/icons/reload.svg"; import { useIndexedDB } from "react-indexed-db-hook"; -import { sendSdTask, useSdStore } from "@/app/store/sd"; +import { useSdStore } from "@/app/store/sd"; import locales from "@/app/locales"; import LoadingIcon from "../icons/three-dots.svg"; import ErrorIcon from "../icons/delete.svg"; @@ -31,6 +31,7 @@ import { showImageModal, showModal, } from "@/app/components/ui-lib"; +import { func } from "prop-types"; function getBase64ImgUrl(base64Data: string, contentType: string) { const byteCharacters = atob(base64Data); @@ -93,7 +94,7 @@ function getSdTaskStatus(item: any) { ); } -export function Sd() { +export async function Sd() { const isMobileScreen = useMobileScreen(); const navigate = useNavigate(); const clientConfig = useMemo(() => getClientConfig(), []); @@ -101,14 +102,41 @@ export function Sd() { const config = useAppConfig(); const scrollRef = useRef(null); const sdListDb = useIndexedDB(StoreKey.SdList); - const [sdImages, setSdImages] = useState([]); - const { execCount, execCountInc } = useSdStore(); + const sdStore = useSdStore(); + const [sdImages, setSdImages] = useState(sdStore.draw); useEffect(() => { - sdListDb.getAll().then((data) => { - setSdImages(((data as never[]) || []).reverse()); + setSdImages(sdStore.draw); + }, [sdStore.currentId]); + + const useIndexeddb: any = {}; + + async function getImageData(item: any) { + let id = item.img_data; + if (id.indexOf("indexeddb://")) { + id = id.replace("indexeddb://", ""); + } + const link = id.split("@"); + if (link.length != 2) { + return id; + } + let db = useIndexeddb[link[0]]; + if (!db) { + // eslint-disable-next-line react-hooks/rules-of-hooks + db = useIndexedDB(link[0]); + useIndexeddb[link[0]] = db; + } + db.getByID(link[1]).then((data: any) => { + console.log(data); + item.img = data; }); - }, [execCount]); + } + + sdImages.forEach((item: any) => { + if (item.status === "success") { + getImageData(item); + } + }); return (
@@ -161,11 +189,11 @@ export function Sd() { {item.status === "success" ? ( {`${item.id}`} { showImageModal( - getBase64ImgUrl(item.img_data, "image/png"), + getBase64ImgUrl(item.img, "image/png"), true, isMobileScreen ? { width: "100%", height: "fit-content" } @@ -258,7 +286,7 @@ export function Sd() { created_at: new Date().toLocaleString(), img_data: "", }; - sendSdTask(reqData, sdListDb, execCountInc); + sdStore.sendTask(reqData, sdListDb); }} /> { - setSdImages( - sdImages.filter( - (i: any) => i.id !== item.id, - ), + sdStore.draw = sdImages.filter( + (i: any) => i.id !== item.id, ); + sdStore.getNextId(); }, (error) => { console.error(error); diff --git a/app/constant.ts b/app/constant.ts index c51e85a15..201843e90 100644 --- a/app/constant.ts +++ b/app/constant.ts @@ -1,5 +1,3 @@ -import { stabilityRequestCall } from "@/app/store/sd"; - export const OWNER = "Yidadaa"; export const REPO = "ChatGPT-Next-Web"; export const REPO_URL = `https://github.com/${OWNER}/${REPO}`; diff --git a/app/store/sd.ts b/app/store/sd.ts index 970f190f8..ec0d5cfec 100644 --- a/app/store/sd.ts +++ b/app/store/sd.ts @@ -1,8 +1,9 @@ -import { initDB, useIndexedDB } from "react-indexed-db-hook"; +import { initDB } from "react-indexed-db-hook"; import { StabilityPath, StoreKey } from "@/app/constant"; -import { create, StoreApi } from "zustand"; import { showToast } from "@/app/components/ui-lib"; import { getHeaders } from "@/app/client/api"; +import { createPersistStore } from "@/app/utils/store"; +import { nanoid } from "nanoid"; export const SdDbConfig = { name: "@chatgpt-next-web/sd", @@ -12,16 +13,7 @@ export const SdDbConfig = { store: StoreKey.SdList, storeConfig: { keyPath: "id", autoIncrement: true }, storeSchema: [ - { name: "model", keypath: "model", options: { unique: false } }, - { - name: "model_name", - keypath: "model_name", - options: { unique: false }, - }, - { name: "status", keypath: "status", options: { unique: false } }, - { name: "params", keypath: "params", options: { unique: false } }, - { name: "img_data", keypath: "img_data", options: { unique: false } }, - { name: "error", keypath: "error", options: { unique: false } }, + { name: "data", keypath: "data", options: { unique: false } }, { name: "created_at", keypath: "created_at", @@ -36,64 +28,106 @@ export function SdDbInit() { initDB(SdDbConfig); } -type SdStore = { - execCount: number; - execCountInc: () => void; -}; - -export const useSdStore = create()((set) => ({ - execCount: 1, - execCountInc: () => set((state) => ({ execCount: state.execCount + 1 })), -})); - -export function sendSdTask(data: any, db: any, inc: any, okCall?: Function) { - db.add(data).then( - (id: number) => { - data = { ...data, id, status: "running" }; - db.update(data); - inc(); - stabilityRequestCall(data, db, inc); - okCall?.(); - }, - (error: any) => { - console.error(error); - showToast(`error: ` + error.message); - }, - ); -} - -export function stabilityRequestCall(data: any, db: any, inc: any) { - const formData = new FormData(); - for (let paramsKey in data.params) { - formData.append(paramsKey, data.params[paramsKey]); +export const useSdStore = createPersistStore< + { + currentId: number; + draw: any[]; + }, + { + getNextId: () => number; + sendTask: (data: any, db: any, okCall?: Function) => void; + updateDraw: (draw: any) => void; } - const headers = getHeaders(); - delete headers["Content-Type"]; - fetch(`/api/stability/${StabilityPath.GeneratePath}/${data.model}`, { - method: "POST", - headers: { - ...headers, - Accept: "application/json", - }, - body: formData, - }) - .then((response) => response.json()) - .then((resData) => { - if (resData.errors && resData.errors.length > 0) { - db.update({ ...data, status: "error", error: resData.errors[0] }); - inc(); - return; - } - if (resData.finish_reason === "SUCCESS") { - db.update({ ...data, status: "success", img_data: resData.image }); - } else { - db.update({ ...data, status: "error", error: JSON.stringify(resData) }); - } - inc(); - }) - .catch((error) => { - db.update({ ...data, status: "error", error: error.message }); - console.error("Error:", error); - inc(); - }); -} +>( + { + currentId: 0, + draw: [], + }, + (set, _get) => { + function get() { + return { + ..._get(), + ...methods, + }; + } + + const methods = { + getNextId() { + const id = ++_get().currentId; + set({ currentId: id }); + return id; + }, + sendTask(data: any, db: any, okCall?: Function) { + data = { ...data, id: nanoid(), status: "running" }; + set({ draw: [data, ..._get().draw] }); + // db.update(data); + this.getNextId(); + this.stabilityRequestCall(data, db); + okCall?.(); + }, + stabilityRequestCall(data: any, db: any) { + const formData = new FormData(); + for (let paramsKey in data.params) { + formData.append(paramsKey, data.params[paramsKey]); + } + const headers = getHeaders(); + delete headers["Content-Type"]; + fetch(`/api/stability/${StabilityPath.GeneratePath}/${data.model}`, { + method: "POST", + headers: { + ...headers, + Accept: "application/json", + }, + body: formData, + }) + .then((response) => response.json()) + .then((resData) => { + if (resData.errors && resData.errors.length > 0) { + this.updateDraw({ + ...data, + status: "error", + error: resData.errors[0], + }); + this.getNextId(); + return; + } + if (resData.finish_reason === "SUCCESS") { + const imgId = nanoid(); + db.add({ id: data.id, data: resData.image }); + this.updateDraw({ + ...data, + status: "success", + img_data: `indexeddb://${StoreKey.SdList}@${imgId}`, + }); + } else { + this.updateDraw({ + ...data, + status: "error", + error: JSON.stringify(resData), + }); + } + this.getNextId(); + }) + .catch((error) => { + this.updateDraw({ ...data, status: "error", error: error.message }); + console.error("Error:", error); + this.getNextId(); + }); + }, + updateDraw(draw: any) { + _get().draw.some((item, index) => { + if (item.id === draw.id) { + _get().draw[index] = draw; + return true; + } + }); + }, + }; + + return methods; + }, + { + name: StoreKey.SdList, + version: 1.0, + }, +);