Spaces:
Running
on
CPU Upgrade
Running
on
CPU Upgrade
wip: save image if user is logged + save in persistent storage
Browse files- .gitignore +2 -1
- prisma/schema.prisma +1 -0
- src/lib/components/community/Card.svelte +2 -1
- src/lib/components/generate/Response.svelte +2 -0
- src/lib/stores/use-generation.ts +2 -0
- src/routes/api/community/+server.ts +2 -1
- src/routes/api/generate/+server.ts +54 -7
- src/routes/generate/+page.svelte +6 -12
- vite.config.ts +6 -1
.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('
|
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 |
-
|
|
|
|
|
|
|
|
|
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((
|
35 |
-
|
|
|
|
|
|
|
|
|
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 |
-
|
51 |
-
|
52 |
-
|
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 |
-
|
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 |
});
|