Spaces:
Runtime error
Runtime error
switch rooms api
Browse files- frontend/src/lib/Buttons/RoomsSelector.svelte +79 -55
- frontend/src/lib/Menu.svelte +2 -0
- frontend/src/lib/constants.ts +2 -0
- frontend/src/lib/store.ts +2 -1
- frontend/src/lib/types.ts +6 -0
- frontend/src/routes/+layout.ts +0 -6
- frontend/src/routes/+page.svelte +17 -18
- frontend/src/routes/+page.ts +14 -0
- stablediffusion-infinity/app.py +8 -2
frontend/src/lib/Buttons/RoomsSelector.svelte
CHANGED
@@ -3,17 +3,18 @@
|
|
3 |
import Pin from '$lib/Icons/Pin.svelte';
|
4 |
import People from '$lib/Icons/People.svelte';
|
5 |
import { onMount } from 'svelte';
|
6 |
-
|
|
|
|
|
|
|
7 |
export let isLoading = false;
|
8 |
let boxEl: HTMLElement;
|
9 |
|
10 |
-
let rooms =
|
11 |
-
.fill(0)
|
12 |
-
.map((_, i) => ({ label: `room ${i}`, total: ~~Math.random() * 20, capacity: 20 }));
|
13 |
|
14 |
-
let selectedRoomID = 0;
|
15 |
let collapsed = true;
|
16 |
-
$: selectedRoom = rooms
|
|
|
17 |
|
18 |
function clickHandler(event: Event) {
|
19 |
if (!boxEl.contains(event.target as Node)) {
|
@@ -21,71 +22,94 @@
|
|
21 |
}
|
22 |
}
|
23 |
onMount(() => {
|
|
|
24 |
window.addEventListener('click', clickHandler, true);
|
|
|
25 |
return () => {
|
26 |
window.removeEventListener('click', clickHandler, true);
|
|
|
27 |
};
|
28 |
});
|
|
|
|
|
|
|
|
|
29 |
</script>
|
30 |
|
31 |
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
32 |
-
|
33 |
-
|
|
|
34 |
{isLoading ? 'opacity-50' : ''}
|
35 |
{collapsed ? 'rounded-xl' : 'rounded-b-xl'}"
|
36 |
-
|
37 |
-
|
38 |
-
>
|
39 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
40 |
<div
|
41 |
-
class=
|
|
|
42 |
>
|
43 |
-
|
44 |
-
<
|
45 |
<Room />
|
46 |
-
<span>
|
|
|
|
|
47 |
<People />
|
48 |
-
<span>
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
<span>
|
63 |
-
{#if i === selectedRoomID}
|
64 |
-
<Pin />
|
65 |
-
{/if}
|
66 |
-
</span>
|
67 |
-
<span> {room.label} </span>
|
68 |
-
<span />
|
69 |
-
<span>{room.total} / {room.capacity}</span>
|
70 |
-
</a>
|
71 |
-
</li>
|
72 |
-
{/each}
|
73 |
-
</ul>
|
74 |
-
<div class="border-t-2 border-t-gray-400 border-opacity-50" />
|
75 |
</div>
|
76 |
-
{/if}
|
77 |
-
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
78 |
-
<div
|
79 |
-
class="grid-row gap-2 relative
|
80 |
-
{isLoading ? 'cursor-wait' : 'cursor-pointer'}"
|
81 |
-
on:click={() => (isLoading ? null : (collapsed = !collapsed))}
|
82 |
-
>
|
83 |
-
<Room />
|
84 |
-
<span> {selectedRoom.label} </span>
|
85 |
-
<People />
|
86 |
-
<span> {selectedRoom.total} / {selectedRoom.capacity} </span>
|
87 |
</div>
|
88 |
-
|
89 |
|
90 |
<style lang="postcss" scoped>
|
91 |
.grid-row {
|
|
|
3 |
import Pin from '$lib/Icons/Pin.svelte';
|
4 |
import People from '$lib/Icons/People.svelte';
|
5 |
import { onMount } from 'svelte';
|
6 |
+
import { PUBLIC_API_BASE } from '$env/static/public';
|
7 |
+
import type { RoomResponse } from '$lib/types';
|
8 |
+
import { selectedRoomID } from '$lib/store';
|
9 |
+
import { MAX_CAPACITY } from '$lib/constants';
|
10 |
export let isLoading = false;
|
11 |
let boxEl: HTMLElement;
|
12 |
|
13 |
+
let rooms: RoomResponse[] = [];
|
|
|
|
|
14 |
|
|
|
15 |
let collapsed = true;
|
16 |
+
$: selectedRoom = rooms.find((room) => room.id === $selectedRoomID);
|
17 |
+
$: loadingRooms = rooms.length > 0;
|
18 |
|
19 |
function clickHandler(event: Event) {
|
20 |
if (!boxEl.contains(event.target as Node)) {
|
|
|
22 |
}
|
23 |
}
|
24 |
onMount(() => {
|
25 |
+
refreshRooms();
|
26 |
window.addEventListener('click', clickHandler, true);
|
27 |
+
const interval = setInterval(refreshRooms, 3000);
|
28 |
return () => {
|
29 |
window.removeEventListener('click', clickHandler, true);
|
30 |
+
clearInterval(interval);
|
31 |
};
|
32 |
});
|
33 |
+
|
34 |
+
async function refreshRooms() {
|
35 |
+
rooms = await fetch(PUBLIC_API_BASE + '/rooms').then((res) => res.json());
|
36 |
+
}
|
37 |
</script>
|
38 |
|
39 |
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
40 |
+
{#if loadingRooms}
|
41 |
+
<div
|
42 |
+
class="text-xs md:text-sm bg-violet-100 text-violet-900 px-3 py-1 font-mono font-medium tracking-tight relative z-0 min-w-[25ch]
|
43 |
{isLoading ? 'opacity-50' : ''}
|
44 |
{collapsed ? 'rounded-xl' : 'rounded-b-xl'}"
|
45 |
+
title="Choose a different room"
|
46 |
+
bind:this={boxEl}
|
47 |
+
>
|
48 |
+
{#if !collapsed}
|
49 |
+
<div class="absolute left-0 right-0 bottom-full rounded-t-xl bg-violet-100 px-1">
|
50 |
+
<ul class="relative overflow-scroll max-h-72">
|
51 |
+
<li class="grid-row gap-2 pb-3 sticky top-0 bg-violet-100 py-2">
|
52 |
+
<Room />
|
53 |
+
<span> room </span>
|
54 |
+
<People />
|
55 |
+
<span> players </span>
|
56 |
+
</li>
|
57 |
+
{#each rooms as room}
|
58 |
+
<li>
|
59 |
+
<!-- svelte-ignore a11y-invalid-attribute -->
|
60 |
+
<a
|
61 |
+
href="#"
|
62 |
+
on:click|preventDefault={() => {
|
63 |
+
$selectedRoomID = room.id;
|
64 |
+
collapsed = true;
|
65 |
+
}}
|
66 |
+
class="grid-row gap-2 hover:bg-gray-300
|
67 |
+
{room.id === $selectedRoomID ? 'text-green-600' : ''}"
|
68 |
+
>
|
69 |
+
<span>
|
70 |
+
{#if room.id === $selectedRoomID}
|
71 |
+
<Pin />
|
72 |
+
{/if}
|
73 |
+
</span>
|
74 |
+
<span>room {room.id} </span>
|
75 |
+
<span />
|
76 |
+
<span>{room.users_count} / {MAX_CAPACITY}</span>
|
77 |
+
</a>
|
78 |
+
</li>
|
79 |
+
{/each}
|
80 |
+
</ul>
|
81 |
+
<div class="border-t-2 border-t-gray-400 border-opacity-50" />
|
82 |
+
</div>
|
83 |
+
{/if}
|
84 |
+
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
85 |
<div
|
86 |
+
class={isLoading ? 'cursor-wait' : 'cursor-pointer'}
|
87 |
+
on:click={() => (isLoading ? null : (collapsed = !collapsed))}
|
88 |
>
|
89 |
+
{#if selectedRoom}
|
90 |
+
<div class="grid-row gap-2">
|
91 |
<Room />
|
92 |
+
<span>
|
93 |
+
room {selectedRoom?.id}
|
94 |
+
</span>
|
95 |
<People />
|
96 |
+
<span>
|
97 |
+
{selectedRoom?.users_count} / {MAX_CAPACITY}
|
98 |
+
</span>
|
99 |
+
</div>
|
100 |
+
{:else}
|
101 |
+
<div class="grid-row gap-2">
|
102 |
+
<Room />
|
103 |
+
<span>
|
104 |
+
Loading...
|
105 |
+
<People />
|
106 |
+
<span> ... / ... </span>
|
107 |
+
</span>
|
108 |
+
</div>
|
109 |
+
{/if}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
110 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
111 |
</div>
|
112 |
+
{/if}
|
113 |
|
114 |
<style lang="postcss" scoped>
|
115 |
.grid-row {
|
frontend/src/lib/Menu.svelte
CHANGED
@@ -4,7 +4,9 @@
|
|
4 |
import RoomsSelector from '$lib/Buttons/RoomsSelector.svelte';
|
5 |
import LiveBlocks from '$lib/Icons/LiveBlocks.svelte';
|
6 |
const dispatch = createEventDispatcher();
|
|
|
7 |
export let isLoading = false;
|
|
|
8 |
const onKeyup = (e: KeyboardEvent) => {
|
9 |
if (e.key === 'Enter') {
|
10 |
dispatch('prompt');
|
|
|
4 |
import RoomsSelector from '$lib/Buttons/RoomsSelector.svelte';
|
5 |
import LiveBlocks from '$lib/Icons/LiveBlocks.svelte';
|
6 |
const dispatch = createEventDispatcher();
|
7 |
+
|
8 |
export let isLoading = false;
|
9 |
+
|
10 |
const onKeyup = (e: KeyboardEvent) => {
|
11 |
if (e.key === 'Enter') {
|
12 |
dispatch('prompt');
|
frontend/src/lib/constants.ts
CHANGED
@@ -7,3 +7,5 @@ export const COLORS = Object.values(colors)
|
|
7 |
|
8 |
export const EMOJIS = ['🐝', '🐌', '🐞', '🐜', '🦋', '🐛', '🐝', '🐞', '🦟', '🦗', '🕷', '🦂', '🐢', '🐍', '🦎', '🦖', '🦕', '🐙', '🦑', '🐠', '🐟', '🐡', '🐬', '🦈', '🐳', '🐋', '🐊', '🐅', '🐆', '🦓', '🦍', '🦧', '🐘', '🦛', '🦏', '🐪', '🐫', '🦒', '🐃', '🐂', '🐄', '🐎', '🐖',
|
9 |
'🐏', '🐑', '🐐', '🐕', '🐩', '🐈', '🐓', '🦃', '🦅', '🦆', '🦢', '🦉', '🦚', '🦜', '🦇', '🐁', '🐀', '🐿', '🐇', '🐿', '🦔', '🦇', '🐻', '🐻', '🐨', '🐼', '🐵', '🙈', '🙉', '🙊', '🐒', '🐉', '🐲', '🦕', '🦖', '🐊', '🐢', '🦎', '🐍', '🐦', '🐧', '🦅', '🦆', '🦉', '🦇']
|
|
|
|
|
|
7 |
|
8 |
export const EMOJIS = ['🐝', '🐌', '🐞', '🐜', '🦋', '🐛', '🐝', '🐞', '🦟', '🦗', '🕷', '🦂', '🐢', '🐍', '🦎', '🦖', '🦕', '🐙', '🦑', '🐠', '🐟', '🐡', '🐬', '🦈', '🐳', '🐋', '🐊', '🐅', '🐆', '🦓', '🦍', '🦧', '🐘', '🦛', '🦏', '🐪', '🐫', '🦒', '🐃', '🐂', '🐄', '🐎', '🐖',
|
9 |
'🐏', '🐑', '🐐', '🐕', '🐩', '🐈', '🐓', '🦃', '🦅', '🦆', '🦢', '🦉', '🦚', '🦜', '🦇', '🐁', '🐀', '🐿', '🐇', '🐿', '🦔', '🦇', '🐻', '🐻', '🐨', '🐼', '🐵', '🙈', '🙉', '🙊', '🐒', '🐉', '🐲', '🦕', '🦖', '🐊', '🐢', '🦎', '🐍', '🐦', '🐧', '🦅', '🦆', '🦉', '🦇']
|
10 |
+
|
11 |
+
export const MAX_CAPACITY = 20;
|
frontend/src/lib/store.ts
CHANGED
@@ -4,4 +4,5 @@ import { type ZoomTransform, zoomIdentity } from 'd3-zoom';
|
|
4 |
export const loadingState = writable<string>('');
|
5 |
export const currZoomTransform = writable<ZoomTransform>(zoomIdentity);
|
6 |
export const canvasEl = writable<HTMLCanvasElement>();
|
7 |
-
export const maskEl = writable<HTMLCanvasElement>();
|
|
|
|
4 |
export const loadingState = writable<string>('');
|
5 |
export const currZoomTransform = writable<ZoomTransform>(zoomIdentity);
|
6 |
export const canvasEl = writable<HTMLCanvasElement>();
|
7 |
+
export const maskEl = writable<HTMLCanvasElement>();
|
8 |
+
export const selectedRoomID = writable<number | null>();
|
frontend/src/lib/types.ts
CHANGED
@@ -34,3 +34,9 @@ export type PromptImgObject = {
|
|
34 |
};
|
35 |
|
36 |
export type PromptImgKey = string;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
34 |
};
|
35 |
|
36 |
export type PromptImgKey = string;
|
37 |
+
|
38 |
+
export interface RoomResponse {
|
39 |
+
id: number;
|
40 |
+
room_id: string;
|
41 |
+
users_count: number;
|
42 |
+
}
|
frontend/src/routes/+layout.ts
DELETED
@@ -1,6 +0,0 @@
|
|
1 |
-
import { PUBLIC_API_BASE } from '$env/static/public';
|
2 |
-
|
3 |
-
export async function load({ fetch }) {
|
4 |
-
const rooms = await fetch(PUBLIC_API_BASE + "/rooms").then((res) => res.json());
|
5 |
-
return { rooms };
|
6 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
frontend/src/routes/+page.svelte
CHANGED
@@ -17,26 +17,21 @@
|
|
17 |
import App from '$lib/App.svelte';
|
18 |
import type { PageData } from './$types';
|
19 |
import { PUBLIC_API_BASE } from '$env/static/public';
|
20 |
-
|
21 |
export let data: PageData;
|
22 |
|
23 |
-
let
|
24 |
let loaded = false;
|
25 |
let client: Client;
|
26 |
|
27 |
-
$:
|
28 |
-
|
|
|
|
|
29 |
}
|
30 |
onMount(() => {
|
31 |
-
document.addEventListener('wheel', (e) => e.preventDefault(), { passive: false });
|
32 |
-
|
33 |
-
// Add random id to room param if not set, and return the id string
|
34 |
-
// e.g. /?room=758df70b5e94c13289df6
|
35 |
-
roomId = 'sd-multiplayer-room-0';
|
36 |
-
|
37 |
-
// Connect to the authentication API for Liveblocks
|
38 |
client = createClient({
|
39 |
-
// publicApiKey: 'pk_test_JlUZGH3kQmhmZQiqU2l8eIi5'
|
40 |
authEndpoint: PUBLIC_API_BASE + '/auth'
|
41 |
});
|
42 |
|
@@ -45,12 +40,16 @@
|
|
45 |
</script>
|
46 |
|
47 |
{#if loaded}
|
48 |
-
<!-- Provides Liveblocks hooks to children -->
|
49 |
<LiveblocksProvider {client}>
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
|
|
|
|
|
|
|
|
|
|
55 |
</LiveblocksProvider>
|
56 |
{/if}
|
|
|
17 |
import App from '$lib/App.svelte';
|
18 |
import type { PageData } from './$types';
|
19 |
import { PUBLIC_API_BASE } from '$env/static/public';
|
20 |
+
import { selectedRoomID } from '$lib/store';
|
21 |
export let data: PageData;
|
22 |
|
23 |
+
let rooms = data.rooms;
|
24 |
let loaded = false;
|
25 |
let client: Client;
|
26 |
|
27 |
+
$: roomId = rooms.find((room) => room.id === $selectedRoomID)?.room_id;
|
28 |
+
|
29 |
+
$:{
|
30 |
+
console.log("ROOM ID", $selectedRoomID);
|
31 |
}
|
32 |
onMount(() => {
|
33 |
+
// document.addEventListener('wheel', (e) => e.preventDefault(), { passive: false });
|
|
|
|
|
|
|
|
|
|
|
|
|
34 |
client = createClient({
|
|
|
35 |
authEndpoint: PUBLIC_API_BASE + '/auth'
|
36 |
});
|
37 |
|
|
|
40 |
</script>
|
41 |
|
42 |
{#if loaded}
|
|
|
43 |
<LiveblocksProvider {client}>
|
44 |
+
{#if roomId}
|
45 |
+
<RoomProvider id={roomId}>
|
46 |
+
<App />
|
47 |
+
</RoomProvider>
|
48 |
+
{:else}
|
49 |
+
<div class="flex flex-col items-center justify-center h-full">
|
50 |
+
<h1 class="text-2xl font-bold">No room selected</h1>
|
51 |
+
<p class="text-gray-500">Please select a room in the URL</p>
|
52 |
+
</div>
|
53 |
+
{/if}
|
54 |
</LiveblocksProvider>
|
55 |
{/if}
|
frontend/src/routes/+page.ts
ADDED
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { PUBLIC_API_BASE } from '$env/static/public';
|
2 |
+
import type { RoomResponse } from '$lib/types';
|
3 |
+
import { selectedRoomID } from '$lib/store';
|
4 |
+
import { MAX_CAPACITY } from '$lib/constants';
|
5 |
+
|
6 |
+
export const prerender = true
|
7 |
+
export const ssr = false
|
8 |
+
export async function load() {
|
9 |
+
const res = await fetch(PUBLIC_API_BASE + '/rooms');
|
10 |
+
const rooms: RoomResponse[] = await res.json();
|
11 |
+
const room = rooms.find(room => room.users_count < MAX_CAPACITY) || null;
|
12 |
+
selectedRoomID.set(room ? room.id : null);
|
13 |
+
return { rooms };
|
14 |
+
}
|
stablediffusion-infinity/app.py
CHANGED
@@ -264,7 +264,7 @@ def get_room_count(room_id: str, jwtToken: str = ''):
|
|
264 |
|
265 |
|
266 |
@app.on_event("startup")
|
267 |
-
@repeat_every(seconds=60
|
268 |
async def sync_rooms():
|
269 |
print("Syncing rooms")
|
270 |
try:
|
@@ -290,7 +290,7 @@ async def get_rooms(db: sqlite3.Connection = Depends(get_db)):
|
|
290 |
|
291 |
|
292 |
@app.post('/api/auth')
|
293 |
-
async def autorize(request: Request):
|
294 |
data = await request.json()
|
295 |
room = data["room"]
|
296 |
payload = {
|
@@ -302,6 +302,12 @@ async def autorize(request: Request):
|
|
302 |
response = requests.post(f"https://api.liveblocks.io/v2/rooms/{room}/authorize",
|
303 |
headers={"Authorization": f"Bearer {LIVEBLOCKS_SECRET}"}, json=payload)
|
304 |
if response.status_code == 200:
|
|
|
|
|
|
|
|
|
|
|
|
|
305 |
return response.json()
|
306 |
else:
|
307 |
raise Exception(response.status_code, response.text)
|
|
|
264 |
|
265 |
|
266 |
@app.on_event("startup")
|
267 |
+
@repeat_every(seconds=60)
|
268 |
async def sync_rooms():
|
269 |
print("Syncing rooms")
|
270 |
try:
|
|
|
290 |
|
291 |
|
292 |
@app.post('/api/auth')
|
293 |
+
async def autorize(request: Request, db: sqlite3.Connection = Depends(get_db)):
|
294 |
data = await request.json()
|
295 |
room = data["room"]
|
296 |
payload = {
|
|
|
302 |
response = requests.post(f"https://api.liveblocks.io/v2/rooms/{room}/authorize",
|
303 |
headers={"Authorization": f"Bearer {LIVEBLOCKS_SECRET}"}, json=payload)
|
304 |
if response.status_code == 200:
|
305 |
+
# user in, incremente room count
|
306 |
+
# cursor = db.cursor()
|
307 |
+
# cursor.execute(
|
308 |
+
# "UPDATE rooms SET users_count = users_count + 1 WHERE room_id = ?", (room,))
|
309 |
+
# db.commit()
|
310 |
+
sync_rooms()
|
311 |
return response.json()
|
312 |
else:
|
313 |
raise Exception(response.status_code, response.text)
|