enzostvs HF staff commited on
Commit
3b4bd9f
β€’
1 Parent(s): 1bc7bbb

store generation + add loading

Browse files
src/lib/components/generate/Response.svelte CHANGED
@@ -1,16 +1,20 @@
1
  <script lang="ts">
2
- import Button from "../Button.svelte";
 
3
 
4
- export let response: string | ArrayBuffer | null = '';
5
- export let form: { model: any, inputs: string };
 
 
 
6
 
7
  let loading: boolean = false;
8
  let already_saved: boolean = false;
9
 
10
  const saveImage = () => {
11
  const link = document.createElement('a');
12
- link.href = response as string;
13
- link.download = `${form?.inputs?.slice(0, 20)}.png`;
14
  document.body.appendChild(link);
15
  link.click();
16
  document.body.removeChild(link);
@@ -24,70 +28,113 @@
24
  headers: {
25
  "Content-Type": "application/json"
26
  },
27
- body: JSON.stringify({ image: response, generation: form })
28
  }).then(() => {
29
  loading = false;
30
  already_saved = true;
31
  })
32
  }
33
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
  </script>
35
 
36
- <div class="w-full border-t xl:border-t-0 xl:border-l border-neutral-800 h-full col-span-5 xl:col-span-2" class:!border-black={!response}>
37
- {#if response}
38
- {#if typeof response === "string"}
39
- <img src={response} alt="Generation" class="w-full mx-auto object-contain" />
40
- <div class="p-8 w-full">
41
- <div class="w-full flex items-center justify-end gap-4">
42
- <Button size="lg" theme="light" icon="material-symbols:save" iconPosition="right" onClick={saveImage}>Save</Button>
43
- <Button
44
- size="lg"
45
- theme="blue"
46
- icon="bxs:share"
47
- iconPosition="right"
48
- loading={loading}
49
- disabled={loading || already_saved}
50
- onClick={share}
51
- >
52
- {#if already_saved}
53
- Shared!
54
- {:else}
55
- Share with community
56
- {/if}
57
- </Button>
58
- </div>
59
- <p class="text-neutral-500 text-sm text-right mt-2.5">
60
- All images not shared with the community are deleted right after generation.
61
- <br>
62
- Your informations are not shared with anyone.
63
- </p>
64
- {#if form}
65
- <div class="mt-6 grid grid-cols-1 gap-4">
66
- <div>
67
- <p class="text-neutral-400 font-semibold text-xs uppercase">
68
- Model selected
69
- </p>
70
- <div class="flex items-center justify-start gap-4 px-2 py-2.5 hover:bg-neutral-800/60 transition-all duration-200 rounded-lg cursor-pointer w-full text-left">
71
- <img src={form?.model.image} alt={form?.model.title} class="w-14 h-14 rounded-lg object-cover" />
72
- <div>
73
- <p class="text-neutral-200 text-base font-medium">{form?.model.title}</p>
74
- <p class="text-neutral-400 text-sm">{form?.model.id}</p>
 
 
 
 
 
 
 
 
 
 
 
75
  </div>
76
  </div>
 
 
 
 
 
 
77
  </div>
78
- <div>
79
- <p class="text-neutral-400 font-semibold text-xs uppercase">
80
- Prompt
81
- </p>
82
- <p class="text-neutral-200 text-base font-medium mt-2">"{form.inputs}"</p>
83
- </div>
84
- </div>
85
- {/if}
86
- </div>
87
- {:else}
88
- <div>
89
- error displayed.
90
- </div>
91
  {/if}
92
  {/if}
93
  </div>
 
1
  <script lang="ts">
2
+ import { get } from "svelte/store";
3
+ import { generationStore } from "$lib/stores/use-generation";
4
 
5
+ import Button from "$lib/components/Button.svelte";
6
+ import Loading from "$lib/components/Loading.svelte";
7
+
8
+ let generation = get(generationStore);
9
+ export let loading_generation: boolean = false;
10
 
11
  let loading: boolean = false;
12
  let already_saved: boolean = false;
13
 
14
  const saveImage = () => {
15
  const link = document.createElement('a');
16
+ link.href = generation?.image as string;
17
+ link.download = `${generation?.form?.inputs?.slice(0, 20)}.png`;
18
  document.body.appendChild(link);
19
  link.click();
20
  document.body.removeChild(link);
 
28
  headers: {
29
  "Content-Type": "application/json"
30
  },
31
+ body: JSON.stringify({ image: generation?.image, generation: generation?.form })
32
  }).then(() => {
33
  loading = false;
34
  already_saved = true;
35
  })
36
  }
37
 
38
+ generationStore.subscribe((value) => {
39
+ console.log(value);
40
+ generation = value;
41
+ })
42
+
43
+ // create a ms countup depending on the generation time, to show the user how long it took to generate the image
44
+ let ms = 0;
45
+ let interval: any;
46
+ const start = () => {
47
+ interval = setInterval(() => {
48
+ ms += 100;
49
+ }, 100)
50
+ }
51
+ const stop = () => {
52
+ clearInterval(interval);
53
+ }
54
+
55
+ $: if (!loading_generation) {
56
+ ms = 0;
57
+ stop();
58
+ } else {
59
+ start();
60
+ }
61
+
62
+ const format = (ms: number) => {
63
+ const date = new Date(ms);
64
+ const seconds = date.getSeconds();
65
+ const milliseconds = Math.round(date.getMilliseconds() / 100);
66
+ return `${seconds}.${milliseconds}s`;
67
+ }
68
+
69
+
70
  </script>
71
 
72
+ <div class=" w-full border-t xl:border-t-0 xl:border-l border-neutral-800 h-full col-span-5 xl:col-span-2" class:!border-black={!generation?.image || loading_generation} class:animate-pulse={loading_generation}>
73
+ {#if loading_generation}
74
+ <div class="w-full h-full flex items-center justify-center flex-col gap-3 bg-neutral-950 relative">
75
+ <p class="text-neutral-100 text-xl font-semibold">
76
+ {format(ms)}
77
+ </p>
78
+ <p class="text-xs italic text-neutral-500">
79
+ Generating image...
80
+ </p>
81
+ </div>
82
+ {:else}
83
+ {#if generation?.image}
84
+ {#if typeof generation?.image === "string"}
85
+ <img src={generation?.image} alt="Generation" class="w-full mx-auto object-contain" />
86
+ <div class="p-8 w-full">
87
+ <div class="w-full flex items-center justify-end gap-4">
88
+ <Button size="lg" theme="light" icon="material-symbols:save" iconPosition="right" onClick={saveImage}>Save</Button>
89
+ <Button
90
+ size="lg"
91
+ theme="blue"
92
+ icon="bxs:share"
93
+ iconPosition="right"
94
+ loading={loading}
95
+ disabled={loading || already_saved}
96
+ onClick={share}
97
+ >
98
+ {#if already_saved}
99
+ Shared!
100
+ {:else}
101
+ Share with community
102
+ {/if}
103
+ </Button>
104
+ </div>
105
+ <p class="text-neutral-500 text-sm text-right mt-2.5">
106
+ All images not shared with the community are deleted right after generation.
107
+ <br>
108
+ Your informations are not shared with anyone.
109
+ </p>
110
+ {#if generation?.form}
111
+ <div class="mt-6 grid grid-cols-1 gap-4">
112
+ <div>
113
+ <p class="text-neutral-400 font-semibold text-xs uppercase">
114
+ Model selected
115
+ </p>
116
+ <div class="flex items-center justify-start gap-4 px-2 py-2.5 hover:bg-neutral-800/60 transition-all duration-200 rounded-lg cursor-pointer w-full text-left">
117
+ <img src={generation?.form?.model.image} alt={generation?.form?.model.title} class="w-14 h-14 rounded-lg object-cover" />
118
+ <div>
119
+ <p class="text-neutral-200 text-base font-medium">{generation?.form?.model.title}</p>
120
+ <p class="text-neutral-400 text-sm">{generation?.form?.model.id}</p>
121
+ </div>
122
  </div>
123
  </div>
124
+ <div>
125
+ <p class="text-neutral-400 font-semibold text-xs uppercase">
126
+ Prompt
127
+ </p>
128
+ <p class="text-neutral-200 text-base font-medium mt-2">"{generation?.form.inputs}"</p>
129
+ </div>
130
  </div>
131
+ {/if}
132
+ </div>
133
+ {:else}
134
+ <div>
135
+ Something went wrong
136
+ </div>
137
+ {/if}
 
 
 
 
 
 
138
  {/if}
139
  {/if}
140
  </div>
src/lib/components/sidebar/Sidebar.svelte CHANGED
@@ -69,8 +69,7 @@
69
  class="text-white text-center text-base pb-8 px-8 flex items-center justify-center gap-2 cursor-pointer"
70
  on:click={openWindowLogin}
71
  >
72
- <img src={HFLogo} alt="Hugging Face logo" class="w-8 h-8 inline-block" />
73
- <u>Sign in with Hugging Face</u>
74
  </button>
75
  {/if}
76
  </aside>
 
69
  class="text-white text-center text-base pb-8 px-8 flex items-center justify-center gap-2 cursor-pointer"
70
  on:click={openWindowLogin}
71
  >
72
+ <img src="https://huggingface.co/datasets/huggingface/badges/resolve/main/sign-in-with-huggingface-lg.svg" alt="Hugging Face Sign In" class="w-auto inline-block" />
 
73
  </button>
74
  {/if}
75
  </aside>
src/lib/stores/use-generation.ts ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ import { writable } from "svelte/store";
3
+
4
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
5
+ export const generationStore = writable<{
6
+ form?: Record<string, any>,
7
+ image?: string | ArrayBuffer | null,
8
+ }>(undefined);
src/routes/generate/+page.svelte CHANGED
@@ -4,18 +4,21 @@
4
  </svelte:head>
5
 
6
  <script lang="ts">
 
 
7
  import Button from "$lib/components/Button.svelte";
8
  import Textarea from "$lib/components/fields/Textarea.svelte";
9
  import Banner from "$lib/components/generate/Banner.svelte";
10
  import Response from "$lib/components/generate/Response.svelte";
11
  import Autocomplete from "$lib/components/models/autocomplete/Autocomplete.svelte";
 
12
 
13
  export let data
 
14
 
15
  let loading: boolean = false;
16
- let response: string | ArrayBuffer | null = '';
17
 
18
- let form = {
19
  model: data?.model ?? null,
20
  inputs: "",
21
  parameters: {
@@ -41,15 +44,13 @@
41
  reader.readAsDataURL(blob)
42
  reader.onloadend = () => {
43
  const base64data = reader.result
44
- response = base64data
 
 
 
45
  }
46
  }
47
 
48
- const res = await request.clone().json().catch(() => ({}))
49
- if (res) {
50
- response = res
51
- }
52
-
53
  loading = false
54
  }
55
  </script>
@@ -100,5 +101,5 @@
100
  </div>
101
  </div>
102
  </div>
103
- <Response response={response} form={form} />
104
  </main>
 
4
  </svelte:head>
5
 
6
  <script lang="ts">
7
+ import { get } from "svelte/store";
8
+
9
  import Button from "$lib/components/Button.svelte";
10
  import Textarea from "$lib/components/fields/Textarea.svelte";
11
  import Banner from "$lib/components/generate/Banner.svelte";
12
  import Response from "$lib/components/generate/Response.svelte";
13
  import Autocomplete from "$lib/components/models/autocomplete/Autocomplete.svelte";
14
+ import { generationStore } from "$lib/stores/use-generation";
15
 
16
  export let data
17
+ let generation = get(generationStore);
18
 
19
  let loading: boolean = false;
 
20
 
21
+ let form = generation?.form ?? {
22
  model: data?.model ?? null,
23
  inputs: "",
24
  parameters: {
 
44
  reader.readAsDataURL(blob)
45
  reader.onloadend = () => {
46
  const base64data = reader.result
47
+ generationStore.set({
48
+ image: base64data,
49
+ form: form
50
+ })
51
  }
52
  }
53
 
 
 
 
 
 
54
  loading = false
55
  }
56
  </script>
 
101
  </div>
102
  </div>
103
  </div>
104
+ <Response loading_generation={loading} />
105
  </main>