|
<script lang="ts"> |
|
import Cursor from '$lib/Cursor.svelte'; |
|
import Frame from '$lib/Frame.svelte'; |
|
import Canvas from '$lib/Canvas.svelte'; |
|
import Menu from '$lib/Menu.svelte'; |
|
import PromptModal from '$lib/PromptModal.svelte'; |
|
import type { Room } from '@liveblocks/client'; |
|
import { COLORS, EMOJIS } from '$lib/constants'; |
|
import { PUBLIC_WS_INPAINTING } from '$env/static/public'; |
|
import { onMount } from 'svelte'; |
|
import { |
|
isLoading, |
|
loadingState, |
|
currZoomTransform, |
|
myPresence, |
|
others, |
|
isPrompting, |
|
clickedPosition, |
|
imagesList, |
|
showFrames |
|
} from '$lib/store'; |
|
import { base64ToBlob, uploadImage } from '$lib/utils'; |
|
|
|
|
|
|
|
|
|
|
|
export let room: Room; |
|
onMount(() => {}); |
|
|
|
async function onClose(e: CustomEvent) { |
|
$isPrompting = false; |
|
} |
|
async function onPrompt(e: CustomEvent) { |
|
const prompt = e.detail.prompt; |
|
const imgURLs = await generateImage(prompt); |
|
$isPrompting = false; |
|
console.log('prompt', prompt, imgURLs); |
|
} |
|
async function generateImage(_prompt: string) { |
|
if (!_prompt || $isLoading == true) return; |
|
$loadingState = 'Pending'; |
|
$isLoading = true; |
|
const sessionHash = crypto.randomUUID(); |
|
|
|
const payload = { |
|
fn_index: 0, |
|
data: [ |
|
null, |
|
//{ mask: null, image: null }, |
|
_prompt, |
|
true |
|
], |
|
session_hash: sessionHash |
|
}; |
|
const websocket = new WebSocket(PUBLIC_WS_INPAINTING); |
|
{ |
|
// websocket.send(JSON.stringify({ hash: sessionHash })); |
|
|
|
websocket.onclose = (evt) => { |
|
if (!evt.wasClean) { |
|
$loadingState = 'Error'; |
|
$isLoading = false; |
|
} |
|
}; |
|
websocket.onmessage = async function (event) { |
|
try { |
|
const data = JSON.parse(event.data); |
|
$loadingState = ''; |
|
switch (data.msg) { |
|
case 'send_data': |
|
$loadingState = 'Sending Data'; |
|
websocket.send(JSON.stringify(payload)); |
|
break; |
|
case 'queue_full': |
|
$loadingState = 'Queue full'; |
|
websocket.close(); |
|
$isLoading = false; |
|
return; |
|
case 'estimation': |
|
const { msg, rank, queue_size } = data; |
|
$loadingState = `On queue ${rank}/${queue_size}`; |
|
break; |
|
case 'process_generating': |
|
$loadingState = data.success ? 'Generating' : 'Error'; |
|
break; |
|
case 'process_completed': |
|
try { |
|
const imgBase64 = data.output.data[0] as string; |
|
const isNSWF = data.output.data[1] as boolean; |
|
|
|
const imgBlob = await base64ToBlob(imgBase64); |
|
const imgURL = await uploadImage(imgBlob, _prompt); |
|
|
|
$imagesList.push({ |
|
prompt: _prompt, |
|
imgURL: imgURL, |
|
position: $clickedPosition |
|
}); |
|
console.log(imgURL); |
|
$loadingState = data.success ? 'Complete' : 'Error'; |
|
} catch (e) { |
|
$loadingState = e.message; |
|
} |
|
websocket.close(); |
|
$isLoading = false; |
|
return; |
|
case 'process_starts': |
|
$loadingState = 'Processing'; |
|
break; |
|
} |
|
} catch (e) { |
|
console.error(e); |
|
$isLoading = false; |
|
$loadingState = 'Error'; |
|
} |
|
}; |
|
} |
|
let modal = false; |
|
</script> |
|
|
|
<!-- Show the current user's cursor location --> |
|
<div class="text touch-none pointer-events-none"> |
|
{$loadingState} |
|
{$isLoading} |
|
</div> |
|
{#if $isPrompting} |
|
<PromptModal on:prompt={onPrompt} on:close={onClose} /> |
|
{/if} |
|
<div class="fixed top-0 left-0 z-0 w-screen h-screen"> |
|
<Canvas /> |
|
|
|
<main class="z-10 relative"> |
|
{#if $imagesList && $showFrames} |
|
{#each $imagesList as image, i} |
|
<Frame |
|
color={COLORS[0]} |
|
position={$imagesList.get(i).position} |
|
transform={$currZoomTransform} |
|
/> |
|
{/each} |
|
{/if} |
|
{#if $clickedPosition} |
|
<Frame color={COLORS[0]} position={$clickedPosition} transform={$currZoomTransform} /> |
|
{/if} |
|
{#if $myPresence?.cursor} |
|
<Frame color={COLORS[0]} position={$myPresence.cursor} transform={$currZoomTransform} /> |
|
<Cursor |
|
emoji={EMOJIS[0]} |
|
color={COLORS[0]} |
|
position={$myPresence.cursor} |
|
transform={$currZoomTransform} |
|
/> |
|
{/if} |
|
|
|
<!-- When others connected, iterate through others and show their cursors --> |
|
{#if others} |
|
{#each [...$others] as { connectionId, presence } (connectionId)} |
|
{#if presence?.cursor} |
|
<Frame |
|
color={COLORS[1 + (connectionId % (COLORS.length - 1))]} |
|
position={presence.cursor} |
|
transform={$currZoomTransform} |
|
/> |
|
|
|
<Cursor |
|
emoji={EMOJIS[1 + (connectionId % (EMOJIS.length - 1))]} |
|
color={COLORS[1 + (connectionId % (COLORS.length - 1))]} |
|
position={presence.cursor} |
|
transform={$currZoomTransform} |
|
/> |
|
{/if} |
|
{/each} |
|
{/if} |
|
</main> |
|
</div> |
|
<div class="fixed bottom-0 left-0 right-0 z-10 my-2"> |
|
<Menu /> |
|
</div> |
|
|
|
<style lang="postcss" scoped> |
|
</style> |
|
|