import { useCallback, useEffect, useMemo, useRef, useState } from "react" import { nanoid } from "nanoid" import { useRecoilState, useSetRecoilState } from "recoil" import { fileState, serverConfigState } from "@/lib/store" import useInputImage from "@/hooks/useInputImage" import { keepGUIAlive } from "@/lib/utils" import { getServerConfig, isDesktop } from "@/lib/api" import Header from "@/components/Header" import Workspace from "@/components/Workspace" import FileSelect from "@/components/FileSelect" import { Toaster } from "./components/ui/toaster" const SUPPORTED_FILE_TYPE = [ "image/jpeg", "image/png", "image/webp", "image/bmp", "image/tiff", ] function Home() { const [file, setFile] = useRecoilState(fileState) const userInputImage = useInputImage() const setServerConfigState = useSetRecoilState(serverConfigState) // Set Input Image useEffect(() => { setFile(userInputImage) }, [userInputImage, setFile]) // Keeping GUI Window Open useEffect(() => { const fetchData = async () => { const isRunDesktop = await isDesktop().then((res) => res.text()) if (isRunDesktop === "True") { keepGUIAlive() } } fetchData() }, []) useEffect(() => { const fetchServerConfig = async () => { const serverConfig = await getServerConfig().then((res) => res.json()) console.log(serverConfig) setServerConfigState(serverConfig) } fetchServerConfig() }, []) const workspaceId = useMemo(() => { return nanoid() }, [file]) const [isDragging, setIsDragging] = useState(false) const dragCounter = useRef(0) const handleDrag = useCallback((event: any) => { event.preventDefault() event.stopPropagation() }, []) const handleDragIn = useCallback((event: any) => { event.preventDefault() event.stopPropagation() dragCounter.current += 1 if (event.dataTransfer.items && event.dataTransfer.items.length > 0) { setIsDragging(true) } }, []) const handleDragOut = useCallback((event: any) => { event.preventDefault() event.stopPropagation() dragCounter.current -= 1 if (dragCounter.current > 0) return setIsDragging(false) }, []) const handleDrop = useCallback((event: any) => { event.preventDefault() event.stopPropagation() setIsDragging(false) if (event.dataTransfer.files && event.dataTransfer.files.length > 0) { if (event.dataTransfer.files.length > 1) { // setToastState({ // open: true, // desc: "Please drag and drop only one file", // state: "error", // duration: 3000, // }) } else { const dragFile = event.dataTransfer.files[0] const fileType = dragFile.type if (SUPPORTED_FILE_TYPE.includes(fileType)) { setFile(dragFile) } else { // setToastState({ // open: true, // desc: "Please drag and drop an image file", // state: "error", // duration: 3000, // }) } } event.dataTransfer.clearData() } }, []) const onPaste = useCallback((event: any) => { // TODO: when sd side panel open, ctrl+v not work // https://htmldom.dev/paste-an-image-from-the-clipboard/ if (!event.clipboardData) { return } const clipboardItems = event.clipboardData.items const items: DataTransferItem[] = [].slice .call(clipboardItems) .filter((item: DataTransferItem) => { // Filter the image items only return item.type.indexOf("image") !== -1 }) if (items.length === 0) { return } event.preventDefault() event.stopPropagation() // TODO: add confirm dialog const item = items[0] // Get the blob of image const blob = item.getAsFile() if (blob) { setFile(blob) } }, []) useEffect(() => { window.addEventListener("dragenter", handleDragIn) window.addEventListener("dragleave", handleDragOut) window.addEventListener("dragover", handleDrag) window.addEventListener("drop", handleDrop) window.addEventListener("paste", onPaste) return function cleanUp() { window.removeEventListener("dragenter", handleDragIn) window.removeEventListener("dragleave", handleDragOut) window.removeEventListener("dragover", handleDrag) window.removeEventListener("drop", handleDrop) window.removeEventListener("paste", onPaste) } }) return (
{!file ? ( { setFile(f) }} /> ) : ( <> )}
) } export default Home