LinHanjiang's picture
Upload 259 files
74aacd5
import React, { useCallback, useEffect, useMemo } from 'react'
import { useRecoilState, useSetRecoilState } from 'recoil'
import { nanoid } from 'nanoid'
import useInputImage from './hooks/useInputImage'
import { themeState } from './components/Header/ThemeChanger'
import Workspace from './components/Workspace'
import { fileState, serverConfigState, toastState } from './store/Atoms'
import { keepGUIAlive } from './utils'
import Header from './components/Header/Header'
import useHotKey from './hooks/useHotkey'
import { getServerConfig, isDesktop } from './adapters/inpainting'
const SUPPORTED_FILE_TYPE = [
'image/jpeg',
'image/png',
'image/webp',
'image/bmp',
'image/tiff',
]
function App() {
const [file, setFile] = useRecoilState(fileState)
const [theme, setTheme] = useRecoilState(themeState)
const setToastState = useSetRecoilState(toastState)
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()
}, [])
// Dark Mode Hotkey
useHotKey(
'shift+d',
() => {
const newTheme = theme === 'light' ? 'dark' : 'light'
setTheme(newTheme)
},
{},
[theme]
)
useEffect(() => {
document.body.setAttribute('data-theme', theme)
}, [theme])
const workspaceId = useMemo(() => {
return nanoid()
}, [file])
///
const [isDragging, setIsDragging] = React.useState(false)
const dragCounter = React.useRef(0)
const handleDrag = React.useCallback(event => {
event.preventDefault()
event.stopPropagation()
}, [])
const handleDragIn = React.useCallback(event => {
event.preventDefault()
event.stopPropagation()
dragCounter.current += 1
if (event.dataTransfer.items && event.dataTransfer.items.length > 0) {
setIsDragging(true)
}
}, [])
const handleDragOut = React.useCallback(event => {
event.preventDefault()
event.stopPropagation()
dragCounter.current -= 1
if (dragCounter.current > 0) return
setIsDragging(false)
}, [])
const handleDrop = React.useCallback(
event => {
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()
}
},
[setToastState, setFile]
)
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)
}
}, [])
React.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 (
<div className="lama-cleaner">
<Header />
<Workspace key={workspaceId} />
</div>
)
}
export default App