174 lines
4.7 KiB
TypeScript
174 lines
4.7 KiB
TypeScript
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 (
|
|
<main className="flex min-h-screen flex-col items-center justify-between w-full">
|
|
<Toaster />
|
|
<Header />
|
|
<Workspace key={workspaceId} />
|
|
{!file ? (
|
|
<FileSelect
|
|
onSelection={async (f) => {
|
|
setFile(f)
|
|
}}
|
|
/>
|
|
) : (
|
|
<></>
|
|
)}
|
|
</main>
|
|
)
|
|
}
|
|
|
|
export default Home
|