-
- }
- onClick={async () => {
- if (await showConfirm(Locale.Home.DeleteChat)) {
- chatStore.deleteSession(chatStore.currentSessionIndex);
- }
- }}
- />
-
+ {isChat && (
+
+ }
+ onClick={async () => {
+ if (await showConfirm(Locale.Home.DeleteChat)) {
+ chatStore.deleteSession(chatStore.currentSessionIndex);
+ }
+ }}
+ />
+
+ )}
} shadow />
diff --git a/app/config/client.ts b/app/config/client.ts
index da582a3e8..30a7eb400 100644
--- a/app/config/client.ts
+++ b/app/config/client.ts
@@ -3,7 +3,7 @@ import { BuildConfig, getBuildConfig } from "./build";
export function getClientConfig() {
if (typeof document !== "undefined") {
// client side
- return JSON.parse(queryMeta("config")) as BuildConfig;
+ return JSON.parse(queryMeta("config") || "{}") as BuildConfig;
}
if (typeof process !== "undefined") {
diff --git a/app/constant.ts b/app/constant.ts
index c56f77cb9..29bda6b7f 100644
--- a/app/constant.ts
+++ b/app/constant.ts
@@ -22,6 +22,7 @@ export enum Path {
Masks = "/masks",
Auth = "/auth",
Sd = "/sd",
+ SdPanel = "/sd-panel",
}
export enum ApiPath {
@@ -48,6 +49,7 @@ export enum StoreKey {
Prompt = "prompt-store",
Update = "chat-update",
Sync = "sync",
+ SdList = "sd-list",
}
export const DEFAULT_SIDEBAR_WIDTH = 300;
diff --git a/app/locales/cn.ts b/app/locales/cn.ts
index a0323d85c..22ff94205 100644
--- a/app/locales/cn.ts
+++ b/app/locales/cn.ts
@@ -494,6 +494,7 @@ const cn = {
AIModel: "AI模型",
ModelVersion: "模型版本",
Submit: "提交生成",
+ ParamIsRequired: (name: string) => `${name}不能为空`,
Styles: {
D3Model: "3D模型",
AnalogFilm: "模拟电影",
@@ -514,6 +515,26 @@ const cn = {
TileTexture: "贴图",
},
},
+ Sd: {
+ SubTitle: (count: number) => `共 ${count} 条绘画`,
+ Actions: {
+ Params: "查看参数",
+ Copy: "复制提示词",
+ Delete: "删除",
+ Retry: "重试",
+ },
+ EmptyRecord: "暂无绘画记录",
+ Status: {
+ Name: "状态",
+ Success: "成功",
+ Error: "失败",
+ Wait: "等待中",
+ Running: "运行中",
+ },
+ Danger: {
+ Delete: "确认删除?",
+ },
+ },
};
type DeepPartial = T extends object
diff --git a/app/locales/en.ts b/app/locales/en.ts
index 29bbe3d00..a47b1ef70 100644
--- a/app/locales/en.ts
+++ b/app/locales/en.ts
@@ -500,6 +500,7 @@ const en: LocaleType = {
AIModel: "AI Model",
ModelVersion: "Model Version",
Submit: "Submit",
+ ParamIsRequired: (name: string) => `${name} is required`,
Styles: {
D3Model: "3d-model",
AnalogFilm: "analog-film",
@@ -520,6 +521,26 @@ const en: LocaleType = {
TileTexture: "tile-texture",
},
},
+ Sd: {
+ SubTitle: (count: number) => `${count} images`,
+ Actions: {
+ Params: "See Params",
+ Copy: "Copy Prompt",
+ Delete: "Delete",
+ Retry: "Retry",
+ },
+ EmptyRecord: "No images yet",
+ Status: {
+ Name: "Status",
+ Success: "Success",
+ Error: "Error",
+ Wait: "Waiting",
+ Running: "Running",
+ },
+ Danger: {
+ Delete: "Confirm to delete?",
+ },
+ },
};
export default en;
diff --git a/app/page.tsx b/app/page.tsx
index b3f169a9b..6d24b0154 100644
--- a/app/page.tsx
+++ b/app/page.tsx
@@ -3,6 +3,7 @@ import { Analytics } from "@vercel/analytics/react";
import { Home } from "./components/home";
import { getServerSideConfig } from "./config/server";
+import { SdDbInit } from "@/app/store/sd";
const serverConfig = getServerSideConfig();
diff --git a/app/store/sd.ts b/app/store/sd.ts
new file mode 100644
index 000000000..b811e0add
--- /dev/null
+++ b/app/store/sd.ts
@@ -0,0 +1,78 @@
+import { initDB, useIndexedDB } from "react-indexed-db-hook";
+import { StoreKey } from "@/app/constant";
+import { create, StoreApi } from "zustand";
+
+export const SdDbConfig = {
+ name: "@chatgpt-next-web/sd",
+ version: 1,
+ objectStoresMeta: [
+ {
+ 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: "created_at",
+ keypath: "created_at",
+ options: { unique: false },
+ },
+ ],
+ },
+ ],
+};
+
+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) {
+ const formData = new FormData();
+ for (let paramsKey in data.params) {
+ formData.append(paramsKey, data.params[paramsKey]);
+ }
+ fetch("https://api.stability.ai/v2beta/stable-image/generate/" + data.model, {
+ method: "POST",
+ 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();
+ });
+}
diff --git a/package.json b/package.json
index 4d06b0b14..22465df36 100644
--- a/package.json
+++ b/package.json
@@ -32,6 +32,7 @@
"node-fetch": "^3.3.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
+ "react-indexed-db-hook": "^1.0.14",
"react-markdown": "^8.0.7",
"react-router-dom": "^6.15.0",
"rehype-highlight": "^6.0.0",
diff --git a/yarn.lock b/yarn.lock
index 72df8cafc..3d15ff5f6 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -5110,6 +5110,11 @@ react-dom@^18.2.0:
loose-envify "^1.1.0"
scheduler "^0.23.0"
+react-indexed-db-hook@^1.0.14:
+ version "1.0.14"
+ resolved "https://registry.npmmirror.com/react-indexed-db-hook/-/react-indexed-db-hook-1.0.14.tgz#a29cd732d592735b6a68dfc94316b7a4a091e6be"
+ integrity sha512-tQ6rWofgXUCBhZp9pRpWzthzPbjqcll5uXMo07lbQTKl47VyL9nw9wfVswRxxzS5yj5Sq/VHUkNUjamWbA/M/w==
+
react-is@^16.13.1, react-is@^16.7.0:
version "16.13.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"