Spaces:
Runtime error
Runtime error
better cancel click handler
Browse files
.devcontainer/devcontainer.json
CHANGED
|
@@ -14,7 +14,10 @@
|
|
| 14 |
"customizations": {
|
| 15 |
"vscode": {
|
| 16 |
"extensions": [
|
| 17 |
-
"GitHub.vscode-pull-request-github"
|
|
|
|
|
|
|
|
|
|
| 18 |
]
|
| 19 |
}
|
| 20 |
},
|
|
|
|
| 14 |
"customizations": {
|
| 15 |
"vscode": {
|
| 16 |
"extensions": [
|
| 17 |
+
"GitHub.vscode-pull-request-github",
|
| 18 |
+
"bradlc.vscode-tailwindcss",
|
| 19 |
+
"svelte.svelte-vscode",
|
| 20 |
+
"csstools.postcss"
|
| 21 |
]
|
| 22 |
}
|
| 23 |
},
|
frontend/src/lib/App.svelte
CHANGED
|
@@ -7,7 +7,7 @@
|
|
| 7 |
import PromptModal from '$lib/PromptModal.svelte';
|
| 8 |
import { COLORS, EMOJIS } from '$lib/constants';
|
| 9 |
import { PUBLIC_WS_INPAINTING } from '$env/static/public';
|
| 10 |
-
import type {
|
| 11 |
import { Status } from '$lib/types';
|
| 12 |
import { loadingState, currZoomTransform, maskEl } from '$lib/store';
|
| 13 |
import { useMyPresence, useObject, useOthers } from '$lib/liveblocks';
|
|
@@ -51,11 +51,9 @@
|
|
| 51 |
}
|
| 52 |
function onClose() {
|
| 53 |
showModal = false;
|
| 54 |
-
console.log('close Modal');
|
| 55 |
}
|
| 56 |
|
| 57 |
function onPaint() {
|
| 58 |
-
console.log('onPaint');
|
| 59 |
generateImage();
|
| 60 |
showModal = false;
|
| 61 |
}
|
|
@@ -74,10 +72,9 @@
|
|
| 74 |
|
| 75 |
const payload = {
|
| 76 |
fn_index: 0,
|
| 77 |
-
data: [base64Crop, prompt, 0.75, 7.5,
|
| 78 |
session_hash: sessionHash
|
| 79 |
};
|
| 80 |
-
console.log('payload', payload);
|
| 81 |
|
| 82 |
const websocket = new WebSocket(PUBLIC_WS_INPAINTING);
|
| 83 |
// websocket.onopen = async function (event) {
|
|
@@ -137,15 +134,18 @@
|
|
| 137 |
setTimeout(() => {
|
| 138 |
$loadingState = '';
|
| 139 |
}, 2000);
|
|
|
|
|
|
|
|
|
|
|
|
|
| 140 |
} catch (err) {
|
| 141 |
const tError = err as Error;
|
| 142 |
$loadingState = tError?.message;
|
|
|
|
|
|
|
|
|
|
| 143 |
}
|
| 144 |
websocket.close();
|
| 145 |
-
myPresence.update({
|
| 146 |
-
status: Status.ready,
|
| 147 |
-
currentPrompt: ''
|
| 148 |
-
});
|
| 149 |
return;
|
| 150 |
case 'process_starts':
|
| 151 |
$loadingState = 'Processing';
|
|
|
|
| 7 |
import PromptModal from '$lib/PromptModal.svelte';
|
| 8 |
import { COLORS, EMOJIS } from '$lib/constants';
|
| 9 |
import { PUBLIC_WS_INPAINTING } from '$env/static/public';
|
| 10 |
+
import type { PromptImgKey, Presence } from '$lib/types';
|
| 11 |
import { Status } from '$lib/types';
|
| 12 |
import { loadingState, currZoomTransform, maskEl } from '$lib/store';
|
| 13 |
import { useMyPresence, useObject, useOthers } from '$lib/liveblocks';
|
|
|
|
| 51 |
}
|
| 52 |
function onClose() {
|
| 53 |
showModal = false;
|
|
|
|
| 54 |
}
|
| 55 |
|
| 56 |
function onPaint() {
|
|
|
|
| 57 |
generateImage();
|
| 58 |
showModal = false;
|
| 59 |
}
|
|
|
|
| 72 |
|
| 73 |
const payload = {
|
| 74 |
fn_index: 0,
|
| 75 |
+
data: [base64Crop, prompt, 0.75, 7.5, 35, 'patchmatch'],
|
| 76 |
session_hash: sessionHash
|
| 77 |
};
|
|
|
|
| 78 |
|
| 79 |
const websocket = new WebSocket(PUBLIC_WS_INPAINTING);
|
| 80 |
// websocket.onopen = async function (event) {
|
|
|
|
| 134 |
setTimeout(() => {
|
| 135 |
$loadingState = '';
|
| 136 |
}, 2000);
|
| 137 |
+
myPresence.update({
|
| 138 |
+
status: Status.ready,
|
| 139 |
+
currentPrompt: ''
|
| 140 |
+
});
|
| 141 |
} catch (err) {
|
| 142 |
const tError = err as Error;
|
| 143 |
$loadingState = tError?.message;
|
| 144 |
+
myPresence.update({
|
| 145 |
+
status: Status.ready
|
| 146 |
+
});
|
| 147 |
}
|
| 148 |
websocket.close();
|
|
|
|
|
|
|
|
|
|
|
|
|
| 149 |
return;
|
| 150 |
case 'process_starts':
|
| 151 |
$loadingState = 'Processing';
|
frontend/src/lib/Buttons/PPButton.svelte
CHANGED
|
@@ -5,7 +5,7 @@
|
|
| 5 |
<button
|
| 6 |
on:click
|
| 7 |
disabled={isLoading}
|
| 8 |
-
class="button-paint"
|
| 9 |
title="New Paint Frame"
|
| 10 |
>
|
| 11 |
{#if isLoading}
|
|
@@ -24,6 +24,6 @@
|
|
| 24 |
@apply disabled:opacity-50 dark:bg-white dark:text-black bg-black text-white rounded-2xl text-xs shadow-sm focus:outline-none focus:border-gray-400;
|
| 25 |
} */
|
| 26 |
.button-paint {
|
| 27 |
-
@apply text-sm font-mono bg-violet-100 text-violet-900 min-w-[25ch] flex justify-center items-center disabled:opacity-50
|
| 28 |
}
|
| 29 |
</style>
|
|
|
|
| 5 |
<button
|
| 6 |
on:click
|
| 7 |
disabled={isLoading}
|
| 8 |
+
class="button-paint {isLoading ? 'cursor-wait' : 'cursor-pointer'}"
|
| 9 |
title="New Paint Frame"
|
| 10 |
>
|
| 11 |
{#if isLoading}
|
|
|
|
| 24 |
@apply disabled:opacity-50 dark:bg-white dark:text-black bg-black text-white rounded-2xl text-xs shadow-sm focus:outline-none focus:border-gray-400;
|
| 25 |
} */
|
| 26 |
.button-paint {
|
| 27 |
+
@apply text-sm font-mono bg-violet-100 text-violet-900 min-w-[25ch] flex justify-center items-center disabled:opacity-50 rounded-xl px-3 py-1 shadow-sm focus:outline-none focus:border-gray-400;
|
| 28 |
}
|
| 29 |
</style>
|
frontend/src/lib/Buttons/RoomsSelector.svelte
CHANGED
|
@@ -2,8 +2,10 @@
|
|
| 2 |
import Room from '$lib/Icons/Room.svelte';
|
| 3 |
import Pin from '$lib/Icons/Pin.svelte';
|
| 4 |
import People from '$lib/Icons/People.svelte';
|
|
|
|
| 5 |
|
| 6 |
export let isLoading = false;
|
|
|
|
| 7 |
|
| 8 |
let rooms = [
|
| 9 |
{ label: 'room 1', total: 11, capacity: 20 },
|
|
@@ -13,39 +15,77 @@
|
|
| 13 |
{ label: 'room 5', total: 11, capacity: 20 }
|
| 14 |
];
|
| 15 |
|
| 16 |
-
let
|
| 17 |
-
|
|
|
|
| 18 |
|
| 19 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 20 |
|
| 21 |
-
|
| 22 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 23 |
<Room />
|
| 24 |
-
<span>
|
| 25 |
<People />
|
| 26 |
-
<span>
|
| 27 |
-
</
|
| 28 |
-
|
| 29 |
-
<li class="grid-row gap-2">
|
| 30 |
-
<span>
|
| 31 |
-
{#if i === selectedRoom}
|
| 32 |
-
<Pin />
|
| 33 |
-
{/if}
|
| 34 |
-
</span>
|
| 35 |
-
<span> {room.label} </span>
|
| 36 |
-
<span />
|
| 37 |
-
<span>{room.total} / {room.capacity}</span>
|
| 38 |
-
</li>
|
| 39 |
-
{/each}
|
| 40 |
-
</ul>
|
| 41 |
|
| 42 |
<style lang="postcss" scoped>
|
| 43 |
-
/* .button {
|
| 44 |
-
@apply disabled:opacity-50 dark:bg-white dark:text-black bg-black text-white rounded-2xl text-xs shadow-sm focus:outline-none focus:border-gray-400;
|
| 45 |
-
} */
|
| 46 |
-
.button-paint {
|
| 47 |
-
@apply text-sm font-mono bg-violet-100 text-violet-900 min-w-[25ch] flex justify-center items-center disabled:opacity-50 dark:bg-white dark:text-black rounded-2xl px-3 py-1 shadow-sm focus:outline-none focus:border-gray-400;
|
| 48 |
-
}
|
| 49 |
.grid-row {
|
| 50 |
display: grid;
|
| 51 |
grid-template-columns: 0.5fr 2fr 0.5fr 2fr;
|
|
|
|
| 2 |
import Room from '$lib/Icons/Room.svelte';
|
| 3 |
import Pin from '$lib/Icons/Pin.svelte';
|
| 4 |
import People from '$lib/Icons/People.svelte';
|
| 5 |
+
import { onMount } from 'svelte';
|
| 6 |
|
| 7 |
export let isLoading = false;
|
| 8 |
+
let boxEl: HTMLElement;
|
| 9 |
|
| 10 |
let rooms = [
|
| 11 |
{ label: 'room 1', total: 11, capacity: 20 },
|
|
|
|
| 15 |
{ label: 'room 5', total: 11, capacity: 20 }
|
| 16 |
];
|
| 17 |
|
| 18 |
+
let selectedRoomID = 0;
|
| 19 |
+
let collapsed = true;
|
| 20 |
+
$: selectedRoom = rooms[selectedRoomID];
|
| 21 |
|
| 22 |
+
function clickHandler(event: Event) {
|
| 23 |
+
if (!boxEl.contains(event.target as Node)) {
|
| 24 |
+
collapsed = true;
|
| 25 |
+
}
|
| 26 |
+
}
|
| 27 |
+
onMount(() => {
|
| 28 |
+
window.addEventListener('click', clickHandler, true);
|
| 29 |
+
return () => {
|
| 30 |
+
window.removeEventListener('click', clickHandler, true);
|
| 31 |
+
};
|
| 32 |
+
});
|
| 33 |
+
</script>
|
| 34 |
|
| 35 |
+
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
| 36 |
+
<div
|
| 37 |
+
class="bg-violet-100 text-violet-900 px-3 py-1 font-mono font-medium tracking-tight relative z-0
|
| 38 |
+
{isLoading ? 'opacity-50' : ''}
|
| 39 |
+
{collapsed ? 'rounded-xl' : 'rounded-b-xl'}"
|
| 40 |
+
bind:this={boxEl}
|
| 41 |
+
>
|
| 42 |
+
{#if !collapsed}
|
| 43 |
+
<div class="absolute z-10 left-0 right-0 bottom-full rounded-t-xl bg-violet-100 px-3 py-1">
|
| 44 |
+
<ul>
|
| 45 |
+
<li class="grid-row gap-2 pb-3">
|
| 46 |
+
<Room />
|
| 47 |
+
<span> room </span>
|
| 48 |
+
<People />
|
| 49 |
+
<span> players </span>
|
| 50 |
+
</li>
|
| 51 |
+
{#each rooms as room, i}
|
| 52 |
+
<li>
|
| 53 |
+
<!-- svelte-ignore a11y-invalid-attribute -->
|
| 54 |
+
<a
|
| 55 |
+
href="#"
|
| 56 |
+
on:click|preventDefault={() => (selectedRoomID = i)}
|
| 57 |
+
class="grid-row gap-2 hover:bg-gray-300
|
| 58 |
+
{i === selectedRoomID ? 'text-green-600' : ''}"
|
| 59 |
+
>
|
| 60 |
+
<span>
|
| 61 |
+
{#if i === selectedRoomID}
|
| 62 |
+
<Pin />
|
| 63 |
+
{/if}
|
| 64 |
+
</span>
|
| 65 |
+
<span> {room.label} </span>
|
| 66 |
+
<span />
|
| 67 |
+
<span>{room.total} / {room.capacity}</span>
|
| 68 |
+
</a>
|
| 69 |
+
</li>
|
| 70 |
+
{/each}
|
| 71 |
+
</ul>
|
| 72 |
+
<div class="border-t-2 border-t-gray-400 border-opacity-50" />
|
| 73 |
+
</div>
|
| 74 |
+
{/if}
|
| 75 |
+
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
| 76 |
+
<div
|
| 77 |
+
class="grid-row gap-2 relative
|
| 78 |
+
{isLoading ? 'cursor-wait' : 'cursor-pointer'}"
|
| 79 |
+
on:click={() => (isLoading ? null : (collapsed = !collapsed))}
|
| 80 |
+
>
|
| 81 |
<Room />
|
| 82 |
+
<span> {selectedRoom.label} </span>
|
| 83 |
<People />
|
| 84 |
+
<span> {selectedRoom.total} / {selectedRoom.capacity} </span>
|
| 85 |
+
</div>
|
| 86 |
+
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 87 |
|
| 88 |
<style lang="postcss" scoped>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 89 |
.grid-row {
|
| 90 |
display: grid;
|
| 91 |
grid-template-columns: 0.5fr 2fr 0.5fr 2fr;
|
frontend/src/lib/PromptModal.svelte
CHANGED
|
@@ -7,25 +7,29 @@
|
|
| 7 |
export let initPrompt = '';
|
| 8 |
let prompt: string;
|
| 9 |
let inputEl: HTMLInputElement;
|
|
|
|
| 10 |
const myPresence = useMyPresence();
|
| 11 |
|
| 12 |
const onKeyup = (e: KeyboardEvent) => {
|
| 13 |
if (e.key === 'Escape') {
|
| 14 |
-
|
|
|
|
|
|
|
|
|
|
| 15 |
}
|
| 16 |
};
|
| 17 |
|
| 18 |
onMount(() => {
|
| 19 |
inputEl.focus();
|
| 20 |
-
inputEl.addEventListener('focusout', cancel);
|
| 21 |
prompt = initPrompt;
|
| 22 |
window.addEventListener('keyup', onKeyup);
|
|
|
|
|
|
|
| 23 |
return () => {
|
| 24 |
window.removeEventListener('keyup', onKeyup);
|
| 25 |
-
|
| 26 |
};
|
| 27 |
});
|
| 28 |
-
|
| 29 |
let timer: NodeJS.Timeout;
|
| 30 |
function debouce(newPrompt: string) {
|
| 31 |
clearTimeout(timer);
|
|
@@ -39,7 +43,6 @@
|
|
| 39 |
}
|
| 40 |
function onPrompt() {
|
| 41 |
if (prompt.trim() !== '') {
|
| 42 |
-
console.log('Prompting with: ', prompt);
|
| 43 |
dispatch('paint');
|
| 44 |
dispatch('close');
|
| 45 |
}
|
|
@@ -48,9 +51,10 @@
|
|
| 48 |
const target = event.target as HTMLInputElement;
|
| 49 |
debouce(target.value);
|
| 50 |
}
|
| 51 |
-
function
|
| 52 |
-
if (
|
| 53 |
-
|
|
|
|
| 54 |
myPresence.update({
|
| 55 |
status: Status.ready
|
| 56 |
});
|
|
@@ -62,7 +66,7 @@
|
|
| 62 |
class="fixed w-screen top-0 left-0 bottom-0 right-0 max-h-screen z-50 flex items-center justify-center bg-black bg-opacity-80 px-3"
|
| 63 |
on:submit|preventDefault={onPrompt}
|
| 64 |
>
|
| 65 |
-
<div class="flex bg-white rounded-2xl px-2 w-full max-w-md">
|
| 66 |
<input
|
| 67 |
value={prompt}
|
| 68 |
bind:this={inputEl}
|
|
|
|
| 7 |
export let initPrompt = '';
|
| 8 |
let prompt: string;
|
| 9 |
let inputEl: HTMLInputElement;
|
| 10 |
+
let boxEl: HTMLDivElement;
|
| 11 |
const myPresence = useMyPresence();
|
| 12 |
|
| 13 |
const onKeyup = (e: KeyboardEvent) => {
|
| 14 |
if (e.key === 'Escape') {
|
| 15 |
+
myPresence.update({
|
| 16 |
+
status: Status.ready
|
| 17 |
+
});
|
| 18 |
+
dispatch('close');
|
| 19 |
}
|
| 20 |
};
|
| 21 |
|
| 22 |
onMount(() => {
|
| 23 |
inputEl.focus();
|
|
|
|
| 24 |
prompt = initPrompt;
|
| 25 |
window.addEventListener('keyup', onKeyup);
|
| 26 |
+
window.addEventListener('click', cancelHandler, true);
|
| 27 |
+
|
| 28 |
return () => {
|
| 29 |
window.removeEventListener('keyup', onKeyup);
|
| 30 |
+
window.removeEventListener('click', cancelHandler, true);
|
| 31 |
};
|
| 32 |
});
|
|
|
|
| 33 |
let timer: NodeJS.Timeout;
|
| 34 |
function debouce(newPrompt: string) {
|
| 35 |
clearTimeout(timer);
|
|
|
|
| 43 |
}
|
| 44 |
function onPrompt() {
|
| 45 |
if (prompt.trim() !== '') {
|
|
|
|
| 46 |
dispatch('paint');
|
| 47 |
dispatch('close');
|
| 48 |
}
|
|
|
|
| 51 |
const target = event.target as HTMLInputElement;
|
| 52 |
debouce(target.value);
|
| 53 |
}
|
| 54 |
+
function cancelHandler(event: Event) {
|
| 55 |
+
if (boxEl.contains(event.target as Node)) {
|
| 56 |
+
return;
|
| 57 |
+
}
|
| 58 |
myPresence.update({
|
| 59 |
status: Status.ready
|
| 60 |
});
|
|
|
|
| 66 |
class="fixed w-screen top-0 left-0 bottom-0 right-0 max-h-screen z-50 flex items-center justify-center bg-black bg-opacity-80 px-3"
|
| 67 |
on:submit|preventDefault={onPrompt}
|
| 68 |
>
|
| 69 |
+
<div class="flex bg-white rounded-2xl px-2 w-full max-w-md" bind:this={boxEl}>
|
| 70 |
<input
|
| 71 |
value={prompt}
|
| 72 |
bind:this={inputEl}
|