From 2fa2831fc208404fa6de43780bc536f2907a91cb Mon Sep 17 00:00:00 2001 From: Weixuan Fu Date: Fri, 22 Mar 2024 17:08:56 +0800 Subject: [PATCH 1/2] cleanup code, display all images search res --- ui/src/apis/TwowaySyncApi.ts | 2 +- ui/src/components/MediaPreview.tsx | 10 +-- ui/src/components/SearchInput.tsx | 8 ++- ui/src/db-tables/TableBase.ts | 7 ++ ui/src/gallery/GalleryModal.tsx | 65 +++++-------------- ui/src/gallery/components/GalleryGridView.tsx | 43 ++++++++++++ .../components/GalleryLeftCarousel.tsx | 5 ++ .../gallery/components/GalleryMediaItem.tsx | 31 +-------- .../gallery/components/GalleryRightTopbar.tsx | 16 ++++- .../MetaBox/GalleryRightMetadataForm.tsx | 3 - 10 files changed, 100 insertions(+), 90 deletions(-) create mode 100644 ui/src/gallery/components/GalleryGridView.tsx diff --git a/ui/src/apis/TwowaySyncApi.ts b/ui/src/apis/TwowaySyncApi.ts index dc6c829..11e1a74 100644 --- a/ui/src/apis/TwowaySyncApi.ts +++ b/ui/src/apis/TwowaySyncApi.ts @@ -163,7 +163,7 @@ export namespace TwowaySyncAPI { name: name, json: JSON.stringify(jsonObj), }; - console.log("createWorkflow", input); + try { const response = await fetch("/workspace/create_workflow_file", { method: "POST", diff --git a/ui/src/components/MediaPreview.tsx b/ui/src/components/MediaPreview.tsx index 99b8c7e..16d2c83 100644 --- a/ui/src/components/MediaPreview.tsx +++ b/ui/src/components/MediaPreview.tsx @@ -30,11 +30,13 @@ export default function MediaPreview({ ? `/workspace/preview_media?filename=${mediaLocalPath}` : `/workspace/view_media?filename=${mediaLocalPath}`, ); - if (!response.ok) throw new Error("Media not found"); - setIsVisible(true); + if (response.status == 404) { + setIsVisible(false); + onBrokenLink?.(); + return; + } } catch (error) { - setIsVisible(false); - onBrokenLink?.(); + console.error("Error checking media exists", error); } }; diff --git a/ui/src/components/SearchInput.tsx b/ui/src/components/SearchInput.tsx index 2b9924f..897271a 100644 --- a/ui/src/components/SearchInput.tsx +++ b/ui/src/components/SearchInput.tsx @@ -5,6 +5,8 @@ import { CSSProperties } from "react"; type Props = { searchValue: string; onUpdateSearchValue: (value: string) => void; + placeholder?: string; + style?: CSSProperties; }; const IconSearchStyle: CSSProperties = { @@ -18,11 +20,11 @@ const IconSearchStyle: CSSProperties = { }; export default function SearchInput(props: Props) { - const { searchValue, onUpdateSearchValue } = props; + const { searchValue, onUpdateSearchValue, style } = props; const isSearchValueNotEmpty = searchValue !== ""; return ( - + {isSearchValueNotEmpty && ( )} { return list as any[]; } + async filter(filterFn: (obj: T) => boolean): Promise { + const list = await indexdb[this.tableName] + .filter(filterFn as any) + .toArray(); + return list as any[]; + } + public async batchQuery(ids: string[]): Promise { const list = await indexdb[this.tableName].bulkGet(ids); return list as any[]; diff --git a/ui/src/gallery/GalleryModal.tsx b/ui/src/gallery/GalleryModal.tsx index 73faed7..ce5c4a3 100644 --- a/ui/src/gallery/GalleryModal.tsx +++ b/ui/src/gallery/GalleryModal.tsx @@ -20,9 +20,10 @@ import { IconArrowLeft, IconX } from "@tabler/icons-react"; import { WorkspaceContext } from "../WorkspaceContext"; import { Media } from "../types/dbTypes"; import { MetaDataInfo } from "./components/GalleryLeftCarousel.tsx"; -import GalleryMediaItem from "./components/GalleryMediaItem.tsx"; -import SearchInput from "../components/SearchInput.tsx"; import { MediaWithMetaData } from "./components/GalleryRightTopbar.tsx"; +import GalleryGridView from "./components/GalleryGridView.tsx"; +import { useDebounce } from "../customHooks/useDebounce.ts"; +import SearchInput from "../components/SearchInput.tsx"; export default function GalleryModal({ onclose }: { onclose: () => void }) { const { curFlowID } = useContext(WorkspaceContext); @@ -33,9 +34,7 @@ export default function GalleryModal({ onclose }: { onclose: () => void }) { const [images, setImages] = useState([]); const [metaData, setMetaData] = useState(); const [searchValue, setSearchValue] = useState(""); - const onUpdateSearchValue = (val: string) => { - setSearchValue(val); - }; + const debounceSearchValue = useDebounce(searchValue, 300); const loadData = async () => { if (curFlowID == null) return; @@ -57,28 +56,10 @@ export default function GalleryModal({ onclose }: { onclose: () => void }) { }); }, []); - const calcImages = searchValue.length - ? images?.filter((v) => - /*!v?.workflowJSON || */ v.workflowJSON?.includes(searchValue ?? ""), - ) - : images; - if (curFlowID == null) { return null; } - const onClickMedia = (media: Media) => { - if (isSelecting) { - if (selectedID.includes(media.id)) { - setSelectedID(selectedID.filter((id) => id !== media.id)); - } else { - setSelectedID([...selectedID, media.id]); - } - return; - } - setMetaData(media); - // window.open(`/workspace/view_media?filename=${media.localPath}`); - }; const isAllSelected = images.length > 0 && selectedID.length === images.length; @@ -90,13 +71,14 @@ export default function GalleryModal({ onclose }: { onclose: () => void }) { Gallery - {workflowName} - - {/* */} - + + setSearchValue(val)} + placeholder="Search prompt, model name, etc." + style={{ width: "300px" }} + /> {isSelecting && ( @@ -124,26 +106,11 @@ export default function GalleryModal({ onclose }: { onclose: () => void }) { - {/* {!metaData ? ( - - {calcImages.map((media) => { - return ( - - ); - })} - - ) : ( */} - - {/* )} */} + {debounceSearchValue.length ? ( + + ) : ( + + )} diff --git a/ui/src/gallery/components/GalleryGridView.tsx b/ui/src/gallery/components/GalleryGridView.tsx new file mode 100644 index 0000000..6208230 --- /dev/null +++ b/ui/src/gallery/components/GalleryGridView.tsx @@ -0,0 +1,43 @@ +import { useEffect, useState } from "react"; +import GalleryMediaItem from "./GalleryMediaItem"; +import { HStack } from "@chakra-ui/react"; +import type { Media } from "../../types/dbTypes"; +import { mediaTable } from "../../db-tables/WorkspaceDB"; + +export default function GalleryGridView({ + searchQuery, +}: { + searchQuery: string; +}) { + const [medias, setMedias] = useState([]); + useEffect(() => { + if (searchQuery === "") { + mediaTable?.listAll().then((data) => { + setMedias(data.slice(0, 50) ?? []); + }); + } else { + mediaTable + ?.filter((v) => v.workflowJSON?.includes(searchQuery) ?? false) + .then((data) => { + setMedias(data); + }); + } + }, [searchQuery]); + + const onClickMedia = (media: Media) => {}; + return ( + + {medias.map((media) => { + return ( + + ); + })} + + ); +} diff --git a/ui/src/gallery/components/GalleryLeftCarousel.tsx b/ui/src/gallery/components/GalleryLeftCarousel.tsx index e2e9e09..f17f2ca 100644 --- a/ui/src/gallery/components/GalleryLeftCarousel.tsx +++ b/ui/src/gallery/components/GalleryLeftCarousel.tsx @@ -4,6 +4,7 @@ import { Box, Flex, Grid, Image } from "@chakra-ui/react"; import Carousel from "../../components/Carousel/Carousel.tsx"; import { MetaInfoBox } from "./GalleryRightTopbar.tsx"; import MediaPreview from "../../components/MediaPreview.tsx"; +import { mediaTable } from "../../db-tables/WorkspaceDB.ts"; interface MetaDataInfoProps { media: Media | null; @@ -53,6 +54,10 @@ export const MetaDataInfo: FC = ({ mediaList, media }) => { mediaLocalPath={media.localPath} size={GALLERY_IMAGE_SIZE} objectFit="contain" + hideBrokenImage + onBrokenLink={() => { + mediaTable?.delete(media.id); + }} /> ))} diff --git a/ui/src/gallery/components/GalleryMediaItem.tsx b/ui/src/gallery/components/GalleryMediaItem.tsx index 2a09f06..00bd144 100644 --- a/ui/src/gallery/components/GalleryMediaItem.tsx +++ b/ui/src/gallery/components/GalleryMediaItem.tsx @@ -27,9 +27,6 @@ interface GalleryMediaItemProps { isSelecting: boolean; selectedID: string[]; onClickMedia: (media: Media) => void; - onRefreshImagesList: () => void; - coverPath: string; - setCoverPath: (path: string) => void; } const GalleryMediaItem: React.FC = ({ @@ -37,9 +34,6 @@ const GalleryMediaItem: React.FC = ({ isSelecting, selectedID, onClickMedia, - onRefreshImagesList, - coverPath, - setCoverPath, }) => { const IMAGE_SIZE = 180; // Define your image size const { curFlowID, loadFilePath } = useContext(WorkspaceContext); @@ -47,7 +41,6 @@ const GalleryMediaItem: React.FC = ({ if (media.localPath == null) { return null; } - const isCover = coverPath != null && coverPath === media.localPath; if (curFlowID == null) { return null; } @@ -65,8 +58,9 @@ const GalleryMediaItem: React.FC = ({ mediaLocalPath={media.localPath} size={IMAGE_SIZE} onBrokenLink={() => { - // setIsVisible(false); + mediaTable?.delete(media.id); }} + hideBrokenImage autoPlay={true} isPreview /> @@ -84,20 +78,6 @@ const GalleryMediaItem: React.FC = ({