radames commited on
Commit
a439de3
1 Parent(s): 5636b7a

UI improvements

Browse files
frontend/src/lib/App.svelte CHANGED
@@ -177,9 +177,9 @@
177
  <!-- When others connected, iterate through others and show their cursors -->
178
  {#if $others}
179
  {#each [...$others] as { connectionId, presence } (connectionId)}
180
- {#if (presence?.status === Status.prompting || presence?.status === Status.masking) && presence?.frame}
181
  <Frame
182
- color={COLORS[1 + (connectionId % (COLORS.length - 1))]}
183
  position={presence?.frame}
184
  prompt={presence?.currentPrompt}
185
  transform={$currZoomTransform}
 
177
  <!-- When others connected, iterate through others and show their cursors -->
178
  {#if $others}
179
  {#each [...$others] as { connectionId, presence } (connectionId)}
180
+ {#if (presence?.status === Status.loading || presence?.status === Status.prompting || presence?.status === Status.masking) && presence?.frame}
181
  <Frame
182
+ isLoading={presence?.status === Status.loading}
183
  position={presence?.frame}
184
  prompt={presence?.currentPrompt}
185
  transform={$currZoomTransform}
frontend/src/lib/Buttons/DragButton.svelte CHANGED
@@ -1,10 +1,12 @@
1
  <script lang="ts">
2
  import Move from '$lib/Icons/Move.svelte';
3
  export let isActive = false;
 
4
  </script>
5
 
6
  <button
7
  on:click
 
8
  class="bg-white rounded-full p-2 {isActive ? 'text-blue-700' : 'text-gray-800'}"
9
  title="Enable Dragging"
10
  >
 
1
  <script lang="ts">
2
  import Move from '$lib/Icons/Move.svelte';
3
  export let isActive = false;
4
+ export let isLoading = false;
5
  </script>
6
 
7
  <button
8
  on:click
9
+ disabled={isLoading}
10
  class="bg-white rounded-full p-2 {isActive ? 'text-blue-700' : 'text-gray-800'}"
11
  title="Enable Dragging"
12
  >
frontend/src/lib/Buttons/MaskButton.svelte CHANGED
@@ -1,10 +1,12 @@
1
  <script lang="ts">
2
  import Mask from '$lib/Icons/Mask.svelte';
3
  export let isActive = false;
 
4
  </script>
5
 
6
  <button
7
  on:click
 
8
  class="bg-white rounded-full p-2 {isActive ? 'text-blue-700' : 'text-gray-800'}"
9
  title="Enable Masking"
10
  >
 
1
  <script lang="ts">
2
  import Mask from '$lib/Icons/Mask.svelte';
3
  export let isActive = false;
4
+ export let isLoading = false;
5
  </script>
6
 
7
  <button
8
  on:click
9
+ disabled={isLoading}
10
  class="bg-white rounded-full p-2 {isActive ? 'text-blue-700' : 'text-gray-800'}"
11
  title="Enable Masking"
12
  >
frontend/src/lib/Buttons/PPButton.svelte CHANGED
@@ -1,13 +1,22 @@
1
  <script lang="ts">
 
2
  </script>
3
 
4
- <button on:click class="button-paint bg-violet-100 text-violet-900" title="New Paint Frame">
5
- <span
6
- class="rounded-sm h-6 w-6 flex justify-center items-center border-2 border-dashed border-violet-700 mr-2"
7
- >
8
- +
9
- </span>
10
- <span>Prompt + Paint</span>
 
 
 
 
 
 
 
 
11
  </button>
12
 
13
  <style lang="postcss" scoped>
@@ -15,6 +24,6 @@
15
  @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;
16
  } */
17
  .button-paint {
18
- @apply font-mono 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;
19
  }
20
  </style>
 
1
  <script lang="ts">
2
+ export let isLoading = false;
3
  </script>
4
 
5
+ <button
6
+ on:click
7
+ disabled={isLoading}
8
+ class="button-paint bg-violet-100 text-violet-900 min-w-[25ch] "
9
+ title="New Paint Frame"
10
+ >
11
+ {#if isLoading}
12
+ <span class="font-mono">paiting... </span>{:else}
13
+ <span
14
+ class="rounded-sm h-6 w-6 flex justify-center items-center border-2 border-dashed border-violet-700 mr-2"
15
+ >
16
+ +
17
+ </span>
18
+ <span>Prompt + Paint</span>
19
+ {/if}
20
  </button>
21
 
22
  <style lang="postcss" scoped>
 
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 font-mono flex justify-center items-center disabled:opacity-80 dark:bg-white dark:text-black rounded-2xl px-3 py-1 shadow-sm focus:outline-none focus:border-gray-400;
28
  }
29
  </style>
frontend/src/lib/Buttons/UndoButton.svelte CHANGED
@@ -1,10 +1,12 @@
1
  <script lang="ts">
2
  import Undo from '$lib/Icons/Undo.svelte';
3
  export let isActive = false;
 
4
  </script>
5
 
6
  <button
7
  on:click
 
8
  class="bg-white rounded-full p-2 {isActive ? 'text-blue-700' : 'text-gray-800'}"
9
  title="Clear Masking"
10
  >
 
1
  <script lang="ts">
2
  import Undo from '$lib/Icons/Undo.svelte';
3
  export let isActive = false;
4
+ export let isLoading = false;
5
  </script>
6
 
7
  <button
8
  on:click
9
+ disabled={isLoading}
10
  class="bg-white rounded-full p-2 {isActive ? 'text-blue-700' : 'text-gray-800'}"
11
  title="Clear Masking"
12
  >
frontend/src/lib/Frame.svelte CHANGED
@@ -4,12 +4,8 @@
4
  import type { ZoomTransform } from 'd3-zoom';
5
 
6
  export let transform: ZoomTransform;
7
- export let color = '';
8
  export let position = { x: 0, y: 0 };
9
  export let prompt = '';
10
- export let loadingState = '';
11
- export let interactive = false;
12
- export let isDragging = false;
13
  export let isLoading = false;
14
  $: coord = {
15
  x: transform.applyX(position.x),
@@ -18,29 +14,18 @@
18
  </script>
19
 
20
  <div
21
- class="frame {isDragging ? 'cursor-grabbing' : 'cursor-grab'}"
22
- style={`transform: translateX(${coord.x}px) translateY(${coord.y}px) scale(${transform.k}); border-color: ${color};`}
23
  >
24
- <div class={!interactive ? 'pointer-events-none touch-none' : ''}>
25
- {#if loadingState}
26
- <div class="col-span-2 row-start-1">
27
- <span class="text-white drop-shadow-lg">{loadingState}</span>
28
- </div>
29
- {/if}
30
- {#if isLoading}
31
- <div class="col-start-2 row-start-2">
32
- <LoadingIcon />
33
- </div>
34
- {/if}
35
-
36
- <h2 class="text-lg"></h2>
37
- <div class="absolute bottom-0 font-bold text-lg">{prompt}</div>
38
  </div>
 
 
 
 
 
39
  </div>
40
 
41
  <style lang="postcss" scoped>
42
- .frame {
43
- @apply absolute top-0 left-0 grid grid-cols-3 grid-rows-3 border-2 border-spacing-3 border-sky-500 w-[512px] h-[512px];
44
- transform-origin: 0 0;
45
- }
46
  </style>
 
4
  import type { ZoomTransform } from 'd3-zoom';
5
 
6
  export let transform: ZoomTransform;
 
7
  export let position = { x: 0, y: 0 };
8
  export let prompt = '';
 
 
 
9
  export let isLoading = false;
10
  $: coord = {
11
  x: transform.applyX(position.x),
 
14
  </script>
15
 
16
  <div
17
+ class="frame @apply absolute top-0 left-0 ring-8 ring-[#EC8E65] w-[512px] h-[512px]"
18
+ style={`transform: translateX(${coord.x}px) translateY(${coord.y}px) scale(${transform.k}); transform-origin: 0 0;`}
19
  >
20
+ <div class="pointer-events-none touch-none">
21
+ <div class="font-bold text-xl text-[#EC8E65] text-center px-2 line-clamp-4">{prompt}</div>
 
 
 
 
 
 
 
 
 
 
 
 
22
  </div>
23
+ {#if isLoading}
24
+ <div class="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2">
25
+ <LoadingIcon />
26
+ </div>
27
+ {/if}
28
  </div>
29
 
30
  <style lang="postcss" scoped>
 
 
 
 
31
  </style>
frontend/src/lib/Icons/LoadingIcon.svelte CHANGED
@@ -1,5 +1,5 @@
1
  <svg
2
- class="animate-spin opacity-60"
3
  width="51"
4
  height="51"
5
  viewBox="0 0 21 21"
@@ -12,6 +12,6 @@
12
  />
13
  <path
14
  d="M10.5006 17C9.6233 17 8.77136 16.8286 7.97021 16.4896C7.19572 16.1621 6.50122 15.6924 5.90448 15.0957C5.30774 14.499 4.83797 13.8046 4.5104 13.0302C4.1714 12.2291 4 11.3772 4 10.5C4 10.2474 4.20441 10.043 4.45708 10.043C4.70974 10.043 4.91415 10.2474 4.91415 10.5C4.91415 11.2541 5.06143 11.9854 5.35345 12.6747C5.63532 13.3399 6.0378 13.9379 6.55074 14.4508C7.06368 14.9637 7.66169 15.3674 8.32698 15.6479C9.01514 15.9387 9.74646 16.0859 10.5006 16.0859C11.2548 16.0859 11.9861 15.9387 12.6756 15.6467C13.3409 15.3648 13.9389 14.9624 14.4518 14.4495C14.9647 13.9366 15.3685 13.3387 15.6491 12.6734C15.9398 11.9854 16.0871 11.2541 16.0871 10.5C16.0871 9.7459 15.9398 9.01465 15.6478 8.32529C15.3669 7.66166 14.9604 7.05857 14.4505 6.54922C13.9417 6.03876 13.3384 5.63215 12.6743 5.35205C11.9861 5.06133 11.2548 4.91406 10.5006 4.91406C10.248 4.91406 10.0436 4.70967 10.0436 4.45703C10.0436 4.20439 10.248 4 10.5006 4C11.378 4 12.2299 4.17139 13.0311 4.51035C13.8055 4.83789 14.5 5.30762 15.0968 5.9043C15.6935 6.50098 16.162 7.19668 16.4896 7.96982C16.8286 8.7709 17 9.62275 17 10.5C17 11.3772 16.8286 12.2291 16.4896 13.0302C16.1633 13.8046 15.6935 14.499 15.0968 15.0957C14.5 15.6924 13.8043 16.1608 13.0311 16.4884C12.2299 16.8286 11.378 17 10.5006 17Z"
15
- fill="#1F2937"
16
  />
17
  </svg>
 
1
  <svg
2
+ class="animate-spin"
3
  width="51"
4
  height="51"
5
  viewBox="0 0 21 21"
 
12
  />
13
  <path
14
  d="M10.5006 17C9.6233 17 8.77136 16.8286 7.97021 16.4896C7.19572 16.1621 6.50122 15.6924 5.90448 15.0957C5.30774 14.499 4.83797 13.8046 4.5104 13.0302C4.1714 12.2291 4 11.3772 4 10.5C4 10.2474 4.20441 10.043 4.45708 10.043C4.70974 10.043 4.91415 10.2474 4.91415 10.5C4.91415 11.2541 5.06143 11.9854 5.35345 12.6747C5.63532 13.3399 6.0378 13.9379 6.55074 14.4508C7.06368 14.9637 7.66169 15.3674 8.32698 15.6479C9.01514 15.9387 9.74646 16.0859 10.5006 16.0859C11.2548 16.0859 11.9861 15.9387 12.6756 15.6467C13.3409 15.3648 13.9389 14.9624 14.4518 14.4495C14.9647 13.9366 15.3685 13.3387 15.6491 12.6734C15.9398 11.9854 16.0871 11.2541 16.0871 10.5C16.0871 9.7459 15.9398 9.01465 15.6478 8.32529C15.3669 7.66166 14.9604 7.05857 14.4505 6.54922C13.9417 6.03876 13.3384 5.63215 12.6743 5.35205C11.9861 5.06133 11.2548 4.91406 10.5006 4.91406C10.248 4.91406 10.0436 4.70967 10.0436 4.45703C10.0436 4.20439 10.248 4 10.5006 4C11.378 4 12.2299 4.17139 13.0311 4.51035C13.8055 4.83789 14.5 5.30762 15.0968 5.9043C15.6935 6.50098 16.162 7.19668 16.4896 7.96982C16.8286 8.7709 17 9.62275 17 10.5C17 11.3772 16.8286 12.2291 16.4896 13.0302C16.1633 13.8046 15.6935 14.499 15.0968 15.0957C14.5 15.6924 13.8043 16.1608 13.0311 16.4884C12.2299 16.8286 11.378 17 10.5006 17Z"
15
+ fill="currentColor"
16
  />
17
  </svg>
frontend/src/lib/PaintCanvas.svelte CHANGED
@@ -12,8 +12,8 @@
12
  const myPresence = useMyPresence();
13
  const promptImgStorage = useObject('promptImgStorage');
14
 
15
- const height = 512 * 4;
16
- const width = 512 * 4;
17
 
18
  let containerEl: HTMLDivElement;
19
  let canvasCtx: CanvasRenderingContext2D;
 
12
  const myPresence = useMyPresence();
13
  const promptImgStorage = useObject('promptImgStorage');
14
 
15
+ const height = 512 * 5;
16
+ const width = 512 * 5;
17
 
18
  let containerEl: HTMLDivElement;
19
  let canvasCtx: CanvasRenderingContext2D;
frontend/src/lib/PaintFrame.svelte CHANGED
@@ -35,8 +35,8 @@
35
  let dragEnabled = true;
36
  let isDragging = false;
37
  $: prompt = $myPresence?.currentPrompt;
38
- $: isLoading = $myPresence?.status === Status.loading || false;
39
-
40
  $: coord = {
41
  x: transform.applyX(position.x),
42
  y: transform.applyY(position.y)
@@ -95,6 +95,7 @@
95
  let lastx: number;
96
  let lasty: number;
97
  function dragstarted(event: Event) {
 
98
  const x = event.x / transform.k;
99
  const y = event.y / transform.k;
100
  lastx = x;
@@ -102,6 +103,7 @@
102
  }
103
 
104
  function dragged(event: Event) {
 
105
  const x = event.x / transform.k;
106
  const y = event.y / transform.k;
107
  drawLine({ x, y, lastx, lasty });
@@ -114,6 +116,8 @@
114
  }
115
  function dragMoveHandler() {
116
  function dragstarted(event: Event) {
 
 
117
  const rect = (event.sourceEvent.target as HTMLElement).getBoundingClientRect();
118
  if (event.sourceEvent instanceof TouchEvent) {
119
  offsetX = event.sourceEvent.targetTouches[0].pageX - rect.left;
@@ -126,6 +130,8 @@
126
  }
127
 
128
  function dragged(event: Event) {
 
 
129
  const x = round(transform.invertX(event.x - offsetX));
130
  const y = round(transform.invertY(event.y - offsetY));
131
  position = {
@@ -142,6 +148,8 @@
142
  }
143
 
144
  function dragended(event: Event) {
 
 
145
  isDragging = false;
146
 
147
  const x = round(transform.invertX(event.x - offsetX));
@@ -184,34 +192,33 @@
184
  <div class="frame">
185
  <canvas class={dragEnabled ? '' : 'bg-white'} bind:this={$maskEl} width="512" height="512" />
186
  <div class="pointer-events-none touch-none">
187
- {#if $loadingState}
188
- <div class="col-span-2 row-start-1">
189
- <span class="text-white drop-shadow-lg">{$loadingState}</span>
190
- </div>
191
- {/if}
192
- {#if isLoading}
193
- <div class="col-start-2 row-start-2">
194
- <LoadingIcon />
195
  </div>
196
  {/if}
197
-
198
- <h2 class="text-lg" />
199
- <div class="absolute bottom-0 font-bold text-lg">{prompt}</div>
200
  </div>
 
 
 
 
 
201
  {#if !isDragging}
202
  <div class="absolute top-full ">
203
  <div class="py-2">
204
- <PPButton on:click={() => dispatch('prompt')} />
205
  </div>
206
  </div>
207
  <div class="absolute left-full bottom-0">
208
  <div class="px-2">
209
- <DragButton isActive={dragEnabled} on:click={toggleDrag} />
210
  <div class="flex bg-white rounded-full mt-3">
211
- <MaskButton isActive={!dragEnabled} on:click={toggleDrawMask} />
212
  {#if !dragEnabled}
213
  <span class="border-gray-800 border-opacity-50 border-r-2 my-2" />
214
- <UndoButton on:click={cleanMask} />
215
  {/if}
216
  </div>
217
  </div>
@@ -229,7 +236,7 @@
229
 
230
  <style lang="postcss" scoped>
231
  .frame {
232
- @apply relative grid grid-cols-3 grid-rows-3 ring-8 ring-blue-500 w-[512px] h-[512px];
233
  }
234
  .hand {
235
  cursor: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAAUCAYAAABvVQZ0AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAHSSURBVHgBzVQ9LENRFD4VozZWP4ku/jqJAYNoEQaWNpEwIYJFBINY6UCn6mKTKhYNSTuwVFBiaEgai9bP4CWKUftqv845vU+k7evr2C/5cu6799zvnHvOvQ+gUmEqNimEsKLZQ3YgA0j6TiNXeJPJlIZygEK1yFAmo4rj0Kkg0Jj4DyHyMxKyIt/I+zH5LJrau8V76lPMLa6KjU2vyKhZsbHl1YTX8/dX5X071eyPdX5xDRrr68BiNsNJ+AxsrS1sCf6DIEQub2hoNxJjxO7ivHnMNZqzzlHAIJBIvkBPV6cm7JC11RULWMw1LELRhwf6IPXxxSSRyMU1ztk5mKpmyX9aV0x2KUoitMHW1sxHjd3HWYQyGh7sY1+Z3ZTRMfcpCxLxHwZhZnIc63TEC3TU3iEXj2XdqGGOomKyBhxNq1fi6ZVF3J5tyK+rPGqHXmZX6OAgR61eVCc9UBDE332rzlu3uj0+WRs7GKGxoY5MWi8zZWZygp1KZUSg6yIR1RNzYQeV2/MQLC/MQqmM5HoYb8CDNl/w0GUTlpFLVDPfzi5myZ0DW3szX5Ex5whYLGYFp/pRTAEjyHcaFoX4RvqKPXRTOaJoHJDrmoKMlv0Lqhj8AlEeE/77ZUZMAAAAAElFTkSuQmCC')
 
35
  let dragEnabled = true;
36
  let isDragging = false;
37
  $: prompt = $myPresence?.currentPrompt;
38
+ $: isLoading = $myPresence?.status === Status.loading || $myPresence?.status === Status.prompting || false;
39
+
40
  $: coord = {
41
  x: transform.applyX(position.x),
42
  y: transform.applyY(position.y)
 
95
  let lastx: number;
96
  let lasty: number;
97
  function dragstarted(event: Event) {
98
+ if (isLoading) return;
99
  const x = event.x / transform.k;
100
  const y = event.y / transform.k;
101
  lastx = x;
 
103
  }
104
 
105
  function dragged(event: Event) {
106
+ if (isLoading) return;
107
  const x = event.x / transform.k;
108
  const y = event.y / transform.k;
109
  drawLine({ x, y, lastx, lasty });
 
116
  }
117
  function dragMoveHandler() {
118
  function dragstarted(event: Event) {
119
+ if (isLoading) return;
120
+
121
  const rect = (event.sourceEvent.target as HTMLElement).getBoundingClientRect();
122
  if (event.sourceEvent instanceof TouchEvent) {
123
  offsetX = event.sourceEvent.targetTouches[0].pageX - rect.left;
 
130
  }
131
 
132
  function dragged(event: Event) {
133
+ if (isLoading) return;
134
+
135
  const x = round(transform.invertX(event.x - offsetX));
136
  const y = round(transform.invertY(event.y - offsetY));
137
  position = {
 
148
  }
149
 
150
  function dragended(event: Event) {
151
+ if (isLoading) return;
152
+
153
  isDragging = false;
154
 
155
  const x = round(transform.invertX(event.x - offsetX));
 
192
  <div class="frame">
193
  <canvas class={dragEnabled ? '' : 'bg-white'} bind:this={$maskEl} width="512" height="512" />
194
  <div class="pointer-events-none touch-none">
195
+ {#if prompt}
196
+ <div class="pointer-events-none touch-none">
197
+ <div class="font-bold text-xl text-[#387CFF] text-center px-2 line-clamp-4">
198
+ {prompt}
199
+ </div>
 
 
 
200
  </div>
201
  {/if}
 
 
 
202
  </div>
203
+ {#if isLoading}
204
+ <div class="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2">
205
+ <LoadingIcon />
206
+ </div>
207
+ {/if}
208
  {#if !isDragging}
209
  <div class="absolute top-full ">
210
  <div class="py-2">
211
+ <PPButton {isLoading} on:click={() => dispatch('prompt')} />
212
  </div>
213
  </div>
214
  <div class="absolute left-full bottom-0">
215
  <div class="px-2">
216
+ <DragButton {isLoading} isActive={dragEnabled} on:click={toggleDrag} />
217
  <div class="flex bg-white rounded-full mt-3">
218
+ <MaskButton {isLoading} isActive={!dragEnabled} on:click={toggleDrawMask} />
219
  {#if !dragEnabled}
220
  <span class="border-gray-800 border-opacity-50 border-r-2 my-2" />
221
+ <UndoButton {isLoading} on:click={cleanMask} />
222
  {/if}
223
  </div>
224
  </div>
 
236
 
237
  <style lang="postcss" scoped>
238
  .frame {
239
+ @apply relative grid grid-cols-3 grid-rows-3 ring-8 ring-[#387CFF] w-[512px] h-[512px];
240
  }
241
  .hand {
242
  cursor: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAAUCAYAAABvVQZ0AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAHSSURBVHgBzVQ9LENRFD4VozZWP4ku/jqJAYNoEQaWNpEwIYJFBINY6UCn6mKTKhYNSTuwVFBiaEgai9bP4CWKUftqv845vU+k7evr2C/5cu6799zvnHvOvQ+gUmEqNimEsKLZQ3YgA0j6TiNXeJPJlIZygEK1yFAmo4rj0Kkg0Jj4DyHyMxKyIt/I+zH5LJrau8V76lPMLa6KjU2vyKhZsbHl1YTX8/dX5X071eyPdX5xDRrr68BiNsNJ+AxsrS1sCf6DIEQub2hoNxJjxO7ivHnMNZqzzlHAIJBIvkBPV6cm7JC11RULWMw1LELRhwf6IPXxxSSRyMU1ztk5mKpmyX9aV0x2KUoitMHW1sxHjd3HWYQyGh7sY1+Z3ZTRMfcpCxLxHwZhZnIc63TEC3TU3iEXj2XdqGGOomKyBhxNq1fi6ZVF3J5tyK+rPGqHXmZX6OAgR61eVCc9UBDE332rzlu3uj0+WRs7GKGxoY5MWi8zZWZygp1KZUSg6yIR1RNzYQeV2/MQLC/MQqmM5HoYb8CDNl/w0GUTlpFLVDPfzi5myZ0DW3szX5Ex5whYLGYFp/pRTAEjyHcaFoX4RvqKPXRTOaJoHJDrmoKMlv0Lqhj8AlEeE/77ZUZMAAAAAElFTkSuQmCC')