Spaces:
Running
on
CPU Upgrade
Running
on
CPU Upgrade
prepare infinite scroll
Browse files- package-lock.json +7 -1
- package.json +2 -1
- src/lib/cards.json +0 -0
- src/lib/components/GoTop.svelte +21 -0
- src/lib/utils/index.ts +16 -1
- src/routes/+page.svelte +21 -16
- src/routes/+page.ts +6 -1
- src/routes/api/community/+server.ts +8 -19
package-lock.json
CHANGED
@@ -9,7 +9,8 @@
|
|
9 |
"version": "0.0.1",
|
10 |
"dependencies": {
|
11 |
"@iconify/svelte": "^3.1.4",
|
12 |
-
"@sveltejs/adapter-node": "^1.3.1"
|
|
|
13 |
},
|
14 |
"devDependencies": {
|
15 |
"@fontsource/fira-mono": "^4.5.10",
|
@@ -3420,6 +3421,11 @@
|
|
3420 |
"svelte": "^3.19.0 || ^4.0.0"
|
3421 |
}
|
3422 |
},
|
|
|
|
|
|
|
|
|
|
|
3423 |
"node_modules/svelte-preprocess": {
|
3424 |
"version": "5.1.1",
|
3425 |
"resolved": "https://registry.npmjs.org/svelte-preprocess/-/svelte-preprocess-5.1.1.tgz",
|
|
|
9 |
"version": "0.0.1",
|
10 |
"dependencies": {
|
11 |
"@iconify/svelte": "^3.1.4",
|
12 |
+
"@sveltejs/adapter-node": "^1.3.1",
|
13 |
+
"svelte-infinite-scroll": "^2.0.1"
|
14 |
},
|
15 |
"devDependencies": {
|
16 |
"@fontsource/fira-mono": "^4.5.10",
|
|
|
3421 |
"svelte": "^3.19.0 || ^4.0.0"
|
3422 |
}
|
3423 |
},
|
3424 |
+
"node_modules/svelte-infinite-scroll": {
|
3425 |
+
"version": "2.0.1",
|
3426 |
+
"resolved": "https://registry.npmjs.org/svelte-infinite-scroll/-/svelte-infinite-scroll-2.0.1.tgz",
|
3427 |
+
"integrity": "sha512-goTHCfOHRDCs8C5MeSuIc6LlAQ8zVQ+M4Y3LyvrDjx5rqSSxSrdCuQwIyWYNcO6j6/mnqRro3QB64ClBzfn+Wg=="
|
3428 |
+
},
|
3429 |
"node_modules/svelte-preprocess": {
|
3430 |
"version": "5.1.1",
|
3431 |
"resolved": "https://registry.npmjs.org/svelte-preprocess/-/svelte-preprocess-5.1.1.tgz",
|
package.json
CHANGED
@@ -36,6 +36,7 @@
|
|
36 |
"type": "module",
|
37 |
"dependencies": {
|
38 |
"@iconify/svelte": "^3.1.4",
|
39 |
-
"@sveltejs/adapter-node": "^1.3.1"
|
|
|
40 |
}
|
41 |
}
|
|
|
36 |
"type": "module",
|
37 |
"dependencies": {
|
38 |
"@iconify/svelte": "^3.1.4",
|
39 |
+
"@sveltejs/adapter-node": "^1.3.1",
|
40 |
+
"svelte-infinite-scroll": "^2.0.1"
|
41 |
}
|
42 |
}
|
src/lib/cards.json
ADDED
The diff for this file is too large to render.
See raw diff
|
|
src/lib/components/GoTop.svelte
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<script lang="ts">
|
2 |
+
import { browser } from "$app/environment";
|
3 |
+
import Icon from "@iconify/svelte";
|
4 |
+
|
5 |
+
const goTop = () => {
|
6 |
+
const element = document.getElementById('app');
|
7 |
+
element?.scrollTo({ top: 0, behavior: 'smooth' });
|
8 |
+
}
|
9 |
+
|
10 |
+
// WIP display only if scroll > 0 dynamically
|
11 |
+
$: visible = browser ? (document?.getElementById('app') as HTMLElement)?.scrollTop > 0 : false;
|
12 |
+
</script>
|
13 |
+
|
14 |
+
<button
|
15 |
+
class="rounded-full h-12 w-12 bg-white shadow-lg brightness-90 transition-all duration-200 hover:brightness-110 fixed bottom-8 right-8 flex items-center justify-center text-indigo-500 z-10"
|
16 |
+
class:opacity-0={!visible}
|
17 |
+
class:pointer-events-none={!visible}
|
18 |
+
on:click={goTop}
|
19 |
+
>
|
20 |
+
<Icon icon="foundation:arrow-up" class="w-8 h-8" />
|
21 |
+
</button>
|
src/lib/utils/index.ts
CHANGED
@@ -1 +1,16 @@
|
|
1 |
-
export const REACTION_EMOJIS = ["β€οΈ", "π€©", "π", "π₯"]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
export const REACTION_EMOJIS = ["β€οΈ", "π€©", "π", "π₯"]
|
2 |
+
|
3 |
+
export const COMMUNITY_FILTER_OPTIONS = [
|
4 |
+
{
|
5 |
+
label: "Most Liked",
|
6 |
+
value: "likes",
|
7 |
+
icon: "lucide:heart",
|
8 |
+
iconColor: "text-red-500"
|
9 |
+
},
|
10 |
+
{
|
11 |
+
label: "New",
|
12 |
+
value: "new",
|
13 |
+
icon: "lucide:zap",
|
14 |
+
iconColor: "text-yellow-500"
|
15 |
+
},
|
16 |
+
];
|
src/routes/+page.svelte
CHANGED
@@ -1,30 +1,29 @@
|
|
1 |
<script lang="ts">
|
|
|
|
|
|
|
2 |
import Button from "$lib/components/Button.svelte";
|
3 |
import Card from "$lib/components/community/Card.svelte";
|
4 |
import Input from "$lib/components/fields/Input.svelte";
|
5 |
import Radio from "$lib/components/fields/Radio.svelte";
|
|
|
|
|
6 |
|
7 |
export let data;
|
8 |
|
9 |
let form = {
|
10 |
-
filter: "likes"
|
|
|
11 |
}
|
12 |
|
13 |
-
|
14 |
-
{
|
15 |
-
label: "Most Liked",
|
16 |
-
value: "likes",
|
17 |
-
icon: "lucide:heart",
|
18 |
-
iconColor: "text-red-500"
|
19 |
-
},
|
20 |
-
{
|
21 |
-
label: "New",
|
22 |
-
value: "new",
|
23 |
-
icon: "lucide:zap",
|
24 |
-
iconColor: "text-yellow-500"
|
25 |
-
},
|
26 |
-
];
|
27 |
|
|
|
|
|
|
|
|
|
|
|
|
|
28 |
</script>
|
29 |
|
30 |
<svelte:head>
|
@@ -36,7 +35,7 @@
|
|
36 |
Community Gallery
|
37 |
</h1>
|
38 |
<div class="flex items-center justify-between mt-5">
|
39 |
-
<Radio options={
|
40 |
<div class="flex items-center justify-end gap-5">
|
41 |
<Button icon="ic:round-plus" theme="dark" size="lg">Upload own Image</Button>
|
42 |
<Button icon="fluent:glance-horizontal-sparkles-16-filled" href="/generate" theme="pink" size="lg">Generate</Button>
|
@@ -49,4 +48,10 @@
|
|
49 |
{#each data.cards as card}
|
50 |
<Card card={card} />
|
51 |
{/each}
|
|
|
|
|
|
|
|
|
|
|
|
|
52 |
</div>
|
|
|
1 |
<script lang="ts">
|
2 |
+
import { browser } from "$app/environment";
|
3 |
+
import InfiniteScroll from "svelte-infinite-scroll";
|
4 |
+
|
5 |
import Button from "$lib/components/Button.svelte";
|
6 |
import Card from "$lib/components/community/Card.svelte";
|
7 |
import Input from "$lib/components/fields/Input.svelte";
|
8 |
import Radio from "$lib/components/fields/Radio.svelte";
|
9 |
+
import { COMMUNITY_FILTER_OPTIONS } from "$lib/utils/index.js";
|
10 |
+
import GoTop from "$lib/components/GoTop.svelte";
|
11 |
|
12 |
export let data;
|
13 |
|
14 |
let form = {
|
15 |
+
filter: "likes",
|
16 |
+
page: "0",
|
17 |
}
|
18 |
|
19 |
+
$: elementScroll = browser ? document?.getElementById('app') : undefined;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
20 |
|
21 |
+
const fetchMore = async () => {
|
22 |
+
form = {...form, page: (Number(form.page) + 1).toString()};
|
23 |
+
const response = await fetch(`/api/community?${new URLSearchParams(form)}`);
|
24 |
+
const new_cards = await response.json();
|
25 |
+
data = {...data, cards: [...data.cards, ...new_cards]};
|
26 |
+
}
|
27 |
</script>
|
28 |
|
29 |
<svelte:head>
|
|
|
35 |
Community Gallery
|
36 |
</h1>
|
37 |
<div class="flex items-center justify-between mt-5">
|
38 |
+
<Radio options={COMMUNITY_FILTER_OPTIONS} value="{form.filter}" onChange={(filter) => form = {...form, filter }} />
|
39 |
<div class="flex items-center justify-end gap-5">
|
40 |
<Button icon="ic:round-plus" theme="dark" size="lg">Upload own Image</Button>
|
41 |
<Button icon="fluent:glance-horizontal-sparkles-16-filled" href="/generate" theme="pink" size="lg">Generate</Button>
|
|
|
48 |
{#each data.cards as card}
|
49 |
<Card card={card} />
|
50 |
{/each}
|
51 |
+
<InfiniteScroll
|
52 |
+
elementScroll="{elementScroll ?? undefined}"
|
53 |
+
threshold={100}
|
54 |
+
on:loadMore={fetchMore}
|
55 |
+
/>
|
56 |
+
<GoTop />
|
57 |
</div>
|
src/routes/+page.ts
CHANGED
@@ -1,5 +1,10 @@
|
|
1 |
export async function load({ fetch }) {
|
2 |
-
const data = await fetch("/api/community"
|
|
|
|
|
|
|
|
|
|
|
3 |
const cards = await data.json()
|
4 |
return { cards }
|
5 |
}
|
|
|
1 |
export async function load({ fetch }) {
|
2 |
+
const data = await fetch("/api/community?page=1", {
|
3 |
+
method: "GET",
|
4 |
+
headers: {
|
5 |
+
"Content-Type": "application/json"
|
6 |
+
}
|
7 |
+
})
|
8 |
const cards = await data.json()
|
9 |
return { cards }
|
10 |
}
|
src/routes/api/community/+server.ts
CHANGED
@@ -1,30 +1,19 @@
|
|
1 |
-
import { error, json } from '@sveltejs/kit';
|
2 |
// import { env } from '$env/dynamic/private'
|
3 |
|
4 |
-
import
|
5 |
-
import { REACTION_EMOJIS } from "$lib/utils";
|
6 |
|
7 |
/** @type {import('./$types').RequestHandler} */
|
8 |
|
9 |
-
export async function GET() {
|
10 |
const hasError = false
|
11 |
-
|
12 |
-
const
|
13 |
-
reactions: REACTION_EMOJIS.sort(() => Math.random() - Math.random()).slice(0,
|
14 |
-
Math.floor(Math.random() * REACTION_EMOJIS.length)
|
15 |
-
).map((emoji) => ({
|
16 |
-
emoji,
|
17 |
-
users: Array.from({ length: Math.floor(Math.random() * 10) }, (_, i) => i.toString()),
|
18 |
-
})),
|
19 |
-
id: i.toString(),
|
20 |
-
model_name: "CommunityCard",
|
21 |
-
prompt: "What is your favorite color?",
|
22 |
-
image: "https://picsum.photos/seed/" + i + "/500/500",
|
23 |
-
}))
|
24 |
-
|
25 |
if (hasError) {
|
26 |
return error(500, 'Internal Server Error')
|
27 |
}
|
28 |
-
|
|
|
|
|
29 |
return json(cards)
|
30 |
}
|
|
|
1 |
+
import { error, json, type RequestEvent } from '@sveltejs/kit';
|
2 |
// import { env } from '$env/dynamic/private'
|
3 |
|
4 |
+
import jsonData from "$lib/cards.json";
|
|
|
5 |
|
6 |
/** @type {import('./$types').RequestHandler} */
|
7 |
|
8 |
+
export async function GET(request : RequestEvent) {
|
9 |
const hasError = false
|
10 |
+
|
11 |
+
const page = parseInt(request.url.searchParams.get('page') || '0')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
if (hasError) {
|
13 |
return error(500, 'Internal Server Error')
|
14 |
}
|
15 |
+
|
16 |
+
const cards = jsonData.slice(page * 25, page * 25 + 25)
|
17 |
+
|
18 |
return json(cards)
|
19 |
}
|