Spaces:
Running
Running
/* eslint-disable react-hooks/exhaustive-deps */ | |
/* eslint-disable jsx-a11y/control-has-associated-label */ | |
import { ArrowLeftIcon, InformationCircleIcon } from '@heroicons/react/outline' | |
import { useEffect, useRef, useState } from 'react' | |
import { useClickAway } from 'react-use' | |
import Button from './components/Button' | |
import FileSelect from './components/FileSelect' | |
import Modal from './components/Modal' | |
import Editor from './Editor' | |
import { resizeImageFile } from './utils' | |
import Progress from './components/Progress' | |
import { downloadModel } from './adapters/cache' | |
import * as m from './paraglide/messages' | |
import { | |
languageTag, | |
onSetLanguageTag, | |
setLanguageTag, | |
} from './paraglide/runtime' | |
function App() { | |
const [file, setFile] = useState<File>() | |
const [stateLanguageTag, setStateLanguageTag] = useState<'en' | 'zh'>('zh') | |
onSetLanguageTag(() => setStateLanguageTag(languageTag())) | |
const [showAbout, setShowAbout] = useState(false) | |
const modalRef = useRef(null) | |
const [downloadProgress, setDownloadProgress] = useState(100) | |
useEffect(() => { | |
downloadModel('inpaint', setDownloadProgress) | |
}, []) | |
useClickAway(modalRef, () => { | |
setShowAbout(false) | |
}) | |
async function startWithDemoImage(img: string) { | |
const imgBlob = await fetch(`/examples/${img}.jpeg`).then(r => r.blob()) | |
setFile(new File([imgBlob], `${img}.jpeg`, { type: 'image/jpeg' })) | |
} | |
return ( | |
<div className="min-h-full flex flex-col"> | |
<header className="z-10 shadow flex flex-row items-center md:justify-between h-14"> | |
<Button | |
className={[ | |
file ? '' : 'opacity-50 pointer-events-none', | |
'pl-1 pr-1 mx-1 sm:mx-5', | |
].join(' ')} | |
icon={<ArrowLeftIcon className="w-6 h-6" />} | |
onClick={() => { | |
setFile(undefined) | |
}} | |
> | |
<div className="md:w-[290px]"> | |
<span className="hidden sm:inline select-none"> | |
{m.start_new()} | |
</span> | |
</div> | |
</Button> | |
<div className="text-4xl font-bold text-blue-600 hover:text-blue-700 transition duration-300 ease-in-out"> | |
Inpaint-web | |
</div> | |
<div className="hidden md:flex justify-end w-[300px] mx-1 sm:mx-5"> | |
<Button | |
className="mr-5 flex" | |
onClick={() => { | |
if (languageTag() === 'zh') { | |
setLanguageTag('en') | |
} else { | |
setLanguageTag('zh') | |
} | |
}} | |
> | |
<p>{languageTag() === 'en' ? '切换到中文' : 'en'}</p> | |
</Button> | |
<Button | |
className="w-38 flex sm:visible" | |
icon={<InformationCircleIcon className="w-6 h-6" />} | |
onClick={() => { | |
setShowAbout(true) | |
}} | |
> | |
<p>{m.feedback()}</p> | |
</Button> | |
</div> | |
</header> | |
<main | |
style={{ | |
height: 'calc(100vh - 56px)', | |
}} | |
className=" relative" | |
> | |
{file ? ( | |
<Editor file={file} /> | |
) : ( | |
<> | |
<div className="flex h-full flex-1 flex-col items-center justify-center overflow-hidden"> | |
<div className="h-72 sm:w-1/2 max-w-5xl"> | |
<FileSelect | |
onSelection={async f => { | |
const { file: resizedFile } = await resizeImageFile( | |
f, | |
1024 * 4 | |
) | |
setFile(resizedFile) | |
}} | |
/> | |
</div> | |
<div className="flex flex-col sm:flex-row pt-10 items-center justify-center cursor-pointer"> | |
<span className="text-gray-500">{m.try_it_images()}</span> | |
<div className="flex space-x-2 sm:space-x-4 px-4"> | |
{['bag', 'dog', 'car', 'bird', 'jacket', 'shoe', 'paris'].map( | |
image => ( | |
<div | |
key={image} | |
onClick={() => startWithDemoImage(image)} | |
role="button" | |
onKeyDown={() => startWithDemoImage(image)} | |
tabIndex={-1} | |
> | |
<img | |
className="rounded-md hover:opacity-75 w-auto h-25" | |
src={`examples/${image}.jpeg`} | |
alt={image} | |
style={{ height: '100px' }} | |
/> | |
</div> | |
) | |
)} | |
</div> | |
</div> | |
</div> | |
</> | |
)} | |
</main> | |
{showAbout && ( | |
<Modal> | |
<div ref={modalRef} className="text-xl space-y-5"> | |
<p> | |
{' '} | |
任何问题到:{' '} | |
<a | |
href="https://github.com/lxfater/inpaint-web" | |
style={{ color: 'blue' }} | |
rel="noreferrer" | |
target="_blank" | |
> | |
Inpaint-web | |
</a>{' '} | |
反馈 | |
</p> | |
<p> | |
{' '} | |
For any questions, please go to:{' '} | |
<a | |
href="https://github.com/lxfater/inpaint-web" | |
style={{ color: 'blue' }} | |
rel="noreferrer" | |
target="_blank" | |
> | |
Inpaint-web | |
</a>{' '} | |
to provide feedback. | |
</p> | |
</div> | |
</Modal> | |
)} | |
{!(downloadProgress === 100) && ( | |
<Modal> | |
<div className="text-xl space-y-5"> | |
<p>{m.inpaint_model_download_message()}</p> | |
<Progress percent={downloadProgress} /> | |
</div> | |
</Modal> | |
)} | |
</div> | |
) | |
} | |
export default App | |