move code to utils/file

This commit is contained in:
lloydzhou 2024-07-15 20:09:21 +08:00
parent e2f0206d88
commit 33450ce429
6 changed files with 88 additions and 89 deletions

View File

@ -6,9 +6,10 @@ import locales from "@/app/locales";
import { nanoid } from "nanoid";
import { useIndexedDB } from "react-indexed-db-hook";
import { StoreKey } from "@/app/constant";
import { SdDbInit, useSdStore } from "@/app/store/sd";
import { useSdStore } from "@/app/store/sd";
import { FileDbInit } from "@/app/utils/file";
SdDbInit();
FileDbInit();
const sdCommonParams = (model: string, data: any) => {
return [

View File

@ -3,7 +3,7 @@ import styles from "@/app/components/sd.module.scss";
import { IconButton } from "@/app/components/button";
import ReturnIcon from "@/app/icons/return.svg";
import Locale from "@/app/locales";
import { Path, StoreKey } from "@/app/constant";
import { Path } from "@/app/constant";
import React, { useEffect, useMemo, useRef, useState } from "react";
import {
copyToClipboard,
@ -20,7 +20,6 @@ import DeleteIcon from "@/app/icons/clear.svg";
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 { useSdStore } from "@/app/store/sd";
import locales from "@/app/locales";
import LoadingIcon from "../icons/three-dots.svg";
@ -30,19 +29,10 @@ import {
showConfirm,
showImageModal,
showModal,
IndexDBImage,
} from "@/app/components/ui-lib";
import { func } from "prop-types";
function getBase64ImgUrl(base64Data: string, contentType: string) {
const byteCharacters = atob(base64Data);
const byteNumbers = new Array(byteCharacters.length);
for (let i = 0; i < byteCharacters.length; i++) {
byteNumbers[i] = byteCharacters.charCodeAt(i);
}
const byteArray = new Uint8Array(byteNumbers);
const blob = new Blob([byteArray], { type: contentType });
return URL.createObjectURL(blob);
}
import { useFileDB } from "@/app/utils/file";
function getSdTaskStatus(item: any) {
let s: string;
@ -94,45 +84,6 @@ function getSdTaskStatus(item: any) {
);
}
function IndexDBImage({ img_data, title, isMobileScreen }) {
const [src, setSrc] = useState(img_data);
const sdListDb = useIndexedDB(StoreKey.SdList);
const img_id = useMemo(
() => img_data.replace("indexeddb://", "").split("@").pop(),
[img_data],
);
useEffect(() => {
sdListDb
.getByID(img_id)
.then(({ data }) => {
setSrc(data);
})
.catch((e) => {
setSrc(img_data);
});
}, [img_data, img_id]);
return (
<img
className={styles["img"]}
src={`data:image/png;base64,${src}`}
alt={title}
onClick={(e) => {
showImageModal(
getBase64ImgUrl(src, "image/png"),
true,
isMobileScreen
? { width: "100%", height: "fit-content" }
: { maxWidth: "100%", maxHeight: "100%" },
isMobileScreen
? { width: "100%", height: "fit-content" }
: { width: "100%", height: "100%" },
);
}}
/>
);
}
export function Sd() {
const isMobileScreen = useMobileScreen();
const navigate = useNavigate();
@ -140,7 +91,7 @@ export function Sd() {
const showMaxIcon = !isMobileScreen && !clientConfig?.isApp;
const config = useAppConfig();
const scrollRef = useRef<HTMLDivElement>(null);
const sdListDb = useIndexedDB(StoreKey.SdList);
const fileDb = useFileDB();
const sdStore = useSdStore();
const [sdImages, setSdImages] = useState(sdStore.draw);
@ -197,13 +148,25 @@ export function Sd() {
className={styles["sd-img-item"]}
>
{item.status === "success" ? (
<>
<IndexDBImage
img_data={item.img_data}
title={item.id}
isMobileScreen={isMobileScreen}
/>
</>
<IndexDBImage
className={styles["img"]}
db={fileDb}
src={item.img_data}
alt={item.id}
onClick={(data, e) => {
showImageModal(
data,
true,
isMobileScreen
? { width: "100%", height: "fit-content" }
: { maxWidth: "100%", maxHeight: "100%" },
isMobileScreen
? { width: "100%", height: "fit-content" }
: { width: "100%", height: "100%" },
);
}}
isMobileScreen={isMobileScreen}
/>
) : item.status === "error" ? (
<div className={styles["pre-img"]}>
<ErrorIcon />
@ -286,7 +249,7 @@ export function Sd() {
created_at: new Date().toLocaleString(),
img_data: "",
};
sdStore.sendTask(reqData, sdListDb);
sdStore.sendTask(reqData, fileDb);
}}
/>
<ChatAction
@ -295,7 +258,7 @@ export function Sd() {
onClick={async () => {
if (await showConfirm(Locale.Sd.Danger.Delete)) {
// remove img_data + remove item in list
sdListDb.deleteRecord(item.id).then(
fileDb.deleteRecord(item.id).then(
() => {
sdStore.draw = sdImages.filter(
(i: any) => i.id !== item.id,

View File

@ -19,6 +19,7 @@ import React, {
MouseEvent,
useEffect,
useState,
useMemo,
} from "react";
import { IconButton } from "./button";
@ -510,3 +511,29 @@ export function Selector<T>(props: {
</div>
);
}
export function IndexDBImage({ src, alt, onClick, db, className }) {
const [data, setData] = useState(src);
const imgId = useMemo(
() => src.replace("indexeddb://", "").split("@").pop(),
[src],
);
useEffect(() => {
db.getByID(imgId)
.then(({ data }) => {
setData(`data:image/png;base64,${data}`);
})
.catch((e) => {
setData(src);
});
}, [src, imgId]);
return (
<img
className={className}
src={data}
alt={alt}
onClick={(e) => onClick(data, e)}
/>
);
}

View File

@ -55,6 +55,7 @@ export enum FileName {
}
export enum StoreKey {
File = "chat-next-web-file",
Chat = "chat-next-web-store",
Access = "access-control",
Config = "app-config",

View File

@ -1,33 +1,9 @@
import { initDB } from "react-indexed-db-hook";
import { StabilityPath, StoreKey } from "@/app/constant";
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",
version: 1,
objectStoresMeta: [
{
store: StoreKey.SdList,
storeConfig: { keyPath: "id", autoIncrement: true },
storeSchema: [
{ name: "data", keypath: "data", options: { unique: false } },
{
name: "created_at",
keypath: "created_at",
options: { unique: false },
},
],
},
],
};
export function SdDbInit() {
initDB(SdDbConfig);
}
export const useSdStore = createPersistStore<
{
currentId: number;
@ -96,7 +72,7 @@ export const useSdStore = createPersistStore<
this.updateDraw({
...data,
status: "success",
img_data: `indexeddb://${StoreKey.SdList}@${data.id}`,
img_data: `indexeddb://${StoreKey.File}@${data.id}`,
});
} else {
this.updateDraw({

31
app/utils/file.tsx Normal file
View File

@ -0,0 +1,31 @@
"use client";
import { initDB } from "react-indexed-db-hook";
import { StoreKey } from "@/app/constant";
import { useIndexedDB } from "react-indexed-db-hook";
export const FileDbConfig = {
name: "@chatgpt-next-web/file",
version: 1,
objectStoresMeta: [
{
store: StoreKey.File,
storeConfig: { keyPath: "id", autoIncrement: true },
storeSchema: [
{ name: "data", keypath: "data", options: { unique: false } },
{
name: "created_at",
keypath: "created_at",
options: { unique: false },
},
],
},
],
};
export function FileDbInit() {
initDB(FileDbConfig);
}
export function useFileDB() {
return useIndexedDB(StoreKey.File);
}