enzostvs HF staff commited on
Commit
404baa5
β€’
1 Parent(s): 83deba1

wip: save image if user is logged + save in persistent storage

Browse files
.gitignore CHANGED
@@ -11,4 +11,5 @@ node_modules
11
  vite.config.js.timestamp-*
12
  vite.config.ts.timestamp-*
13
  prisma/dev.db
14
- prisma/migrations/*
 
 
11
  vite.config.js.timestamp-*
12
  vite.config.ts.timestamp-*
13
  prisma/dev.db
14
+ prisma/migrations/*
15
+ uploads/*
prisma/schema.prisma CHANGED
@@ -29,6 +29,7 @@ model Gallery {
29
  createdAt DateTime @default(now())
30
  prompt String
31
  image String
 
32
  reactions Reaction[]
33
  model Model @relation(fields: [modelId], references: [id])
34
  modelId String
 
29
  createdAt DateTime @default(now())
30
  prompt String
31
  image String
32
+ isPublic Boolean @default(false)
33
  reactions Reaction[]
34
  model Model @relation(fields: [modelId], references: [id])
35
  modelId String
src/lib/components/community/Card.svelte CHANGED
@@ -1,6 +1,7 @@
1
  <script lang="ts">
2
  import type { CommunityCard } from "$lib/type";
3
  import Button from "$lib/components/Button.svelte";
 
4
 
5
  import Reactions from "./reactions/Reactions.svelte";
6
 
@@ -11,7 +12,7 @@
11
  class="cursor-pointer group bg-neutral-700 rounded-xl h-[400px] relative flex items-start justify-between flex-col p-5 transition-all duration-200 brightness-75 hover:brightness-100 z-[1] overflow-hidden"
12
  >
13
  <div class="w-full h-full absolute top-0 left-0 -z-[1] rounded-xl overflow-hidden">
14
- <div class="w-full h-full bg-center bg-cover transition-all duration-200 group-hover:scale-110 " style="background-image: url('https://huggingface.co/datasets/enzostvs/loras-studio/resolve/main/{card.image}?expose=true');"></div>
15
  </div>
16
  <div class="group-hover:opacity-100 opacity-0 translate-y-full group-hover:translate-y-0 transition-all duration-200 flex flex-col gap-4 w-full">
17
  <div class="bg-black/40 backdrop-blur-sm border border-white/30 rounded-lg px-6 py-3 text-white transition-all duration-200 w-full">
 
1
  <script lang="ts">
2
  import type { CommunityCard } from "$lib/type";
3
  import Button from "$lib/components/Button.svelte";
4
+ import { env } from "$env/dynamic/public";
5
 
6
  import Reactions from "./reactions/Reactions.svelte";
7
 
 
12
  class="cursor-pointer group bg-neutral-700 rounded-xl h-[400px] relative flex items-start justify-between flex-col p-5 transition-all duration-200 brightness-75 hover:brightness-100 z-[1] overflow-hidden"
13
  >
14
  <div class="w-full h-full absolute top-0 left-0 -z-[1] rounded-xl overflow-hidden">
15
+ <div class="w-full h-full bg-center bg-cover transition-all duration-200 group-hover:scale-110 " style="background-image: url('{env.PUBLIC_FILE_UPLOAD_DIR}/{card.image}');"></div>
16
  </div>
17
  <div class="group-hover:opacity-100 opacity-0 translate-y-full group-hover:translate-y-0 transition-all duration-200 flex flex-col gap-4 w-full">
18
  <div class="bg-black/40 backdrop-blur-sm border border-white/30 rounded-lg px-6 py-3 text-white transition-all duration-200 w-full">
src/lib/components/generate/Response.svelte CHANGED
@@ -39,6 +39,8 @@
39
  generation = value;
40
  })
41
 
 
 
42
  // create a ms countup depending on the generation time, to show the user how long it took to generate the image
43
  let ms = 0;
44
  let interval: any;
 
39
  generation = value;
40
  })
41
 
42
+ $: console.log(generation);
43
+
44
  // create a ms countup depending on the generation time, to show the user how long it took to generate the image
45
  let ms = 0;
46
  let interval: any;
src/lib/stores/use-generation.ts CHANGED
@@ -1,8 +1,10 @@
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);
 
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ import type { CommunityCard } from "$lib/type";
3
  import { writable } from "svelte/store";
4
 
5
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
6
  export const generationStore = writable<{
7
  form?: Record<string, any>,
8
+ gallery?: CommunityCard,
9
  image?: string | ArrayBuffer | null,
10
  }>(undefined);
src/routes/api/community/+server.ts CHANGED
@@ -13,7 +13,8 @@ export async function GET(request : RequestEvent) {
13
  where: {
14
  OR: [
15
  { prompt: { contains: search } },
16
- ]
 
17
  },
18
  orderBy: {
19
  ...(filter === 'new' ? {
 
13
  where: {
14
  OR: [
15
  { prompt: { contains: search } },
16
+ ],
17
+ isPublic: true
18
  },
19
  orderBy: {
20
  ...(filter === 'new' ? {
src/routes/api/generate/+server.ts CHANGED
@@ -2,8 +2,15 @@
2
 
3
  import { json, type RequestEvent } from '@sveltejs/kit';
4
  import { env } from '$env/dynamic/private'
 
 
 
5
 
6
- export async function POST({ request } : RequestEvent) {
 
 
 
 
7
  const generation = await request.json()
8
 
9
  if (!generation?.model?.id) {
@@ -31,8 +38,12 @@ export async function POST({ request } : RequestEvent) {
31
  },
32
  body: JSON.stringify(generation),
33
  })
34
- .then((res) => res.blob())
35
- .then((blob) => blob)
 
 
 
 
36
  .catch((error) => {
37
  return {
38
  error: error.message,
@@ -47,9 +58,45 @@ export async function POST({ request } : RequestEvent) {
47
  }, { status: 400 })
48
  }
49
 
50
- return new Response(response, {
51
- headers: {
52
- 'Content-Type': 'image/png',
53
- },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
54
  })
55
  }
 
2
 
3
  import { json, type RequestEvent } from '@sveltejs/kit';
4
  import { env } from '$env/dynamic/private'
5
+ import { env as publicEnv } from '$env/dynamic/public';
6
+ import { promises } from 'fs';
7
+ import { randomUUID } from 'crypto';
8
 
9
+ import { tokenIsAvailable } from '$lib/utils';
10
+ import prisma from '$lib/prisma';
11
+
12
+ export async function POST({ request, cookies } : RequestEvent) {
13
+ const token = cookies.get('hf_access_token')
14
  const generation = await request.json()
15
 
16
  if (!generation?.model?.id) {
 
38
  },
39
  body: JSON.stringify(generation),
40
  })
41
+ .then((response) => {
42
+ return response.arrayBuffer()
43
+ })
44
+ .then((response) => {
45
+ return Buffer.from(response)
46
+ })
47
  .catch((error) => {
48
  return {
49
  error: error.message,
 
58
  }, { status: 400 })
59
  }
60
 
61
+ let gallery;
62
+
63
+ if (token) {
64
+ const user = await tokenIsAvailable(token)
65
+ if (user?.sub) {
66
+ const dir = await promises.opendir(env.SECRET_FILE_UPLOAD_DIR).catch(() => null)
67
+ if (!dir) {
68
+ await promises.mkdir(env.SECRET_FILE_UPLOAD_DIR)
69
+ }
70
+ const file_name_formatted = randomUUID() + "_" + generation?.inputs?.replaceAll(/[^a-zA-Z0-9]/g, "-") + ".png"
71
+ await promises.writeFile(`${publicEnv.PUBLIC_FILE_UPLOAD_DIR}/${file_name_formatted}`, response)
72
+
73
+ gallery = await prisma.gallery.create({
74
+ data: {
75
+ image: file_name_formatted,
76
+ prompt: generation.inputs,
77
+ isPublic: false,
78
+ user: {
79
+ connect: {
80
+ sub: user.sub
81
+ }
82
+ },
83
+ model: {
84
+ connect: {
85
+ id: generation.model.id
86
+ }
87
+ },
88
+ }
89
+ })
90
+ .catch((error) => {
91
+ console.log(error)
92
+ })
93
+ }
94
+ }
95
+
96
+ const image = Buffer.from(response).toString('base64')
97
+
98
+ return json({
99
+ image: "data:image/png;base64," + image,
100
+ gallery
101
  })
102
  }
src/routes/generate/+page.svelte CHANGED
@@ -37,20 +37,14 @@
37
  },
38
  body: JSON.stringify(form)
39
  });
40
- const blob = await request?.clone()?.blob()
41
 
42
- if (blob) {
43
- const reader = new FileReader()
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>
 
37
  },
38
  body: JSON.stringify(form)
39
  });
 
40
 
41
+ const response = await request.json();
 
 
 
 
 
 
 
 
 
 
42
 
43
+ generationStore.set({
44
+ image: response?.image,
45
+ gallery: response?.gallery,
46
+ form: form
47
+ })
48
  loading = false
49
  }
50
  </script>
vite.config.ts CHANGED
@@ -1,10 +1,15 @@
1
  import { sveltekit } from '@sveltejs/kit/vite';
2
  import { enhancedImages } from '@sveltejs/enhanced-img';
3
- import { defineConfig } from 'vite';
4
 
5
  export default defineConfig({
6
  plugins: [
7
  enhancedImages(),
8
  sveltekit()
9
  ],
 
 
 
 
 
10
  });
 
1
  import { sveltekit } from '@sveltejs/kit/vite';
2
  import { enhancedImages } from '@sveltejs/enhanced-img';
3
+ import { defineConfig, searchForWorkspaceRoot } from 'vite';
4
 
5
  export default defineConfig({
6
  plugins: [
7
  enhancedImages(),
8
  sveltekit()
9
  ],
10
+ server: {
11
+ fs: {
12
+ allow: [searchForWorkspaceRoot(process.cwd()),'/uploads']
13
+ }
14
+ }
15
  });