diff --git a/src/lib/ably-client.ts b/src/lib/ably-client.ts index 0470891..7abd007 100644 --- a/src/lib/ably-client.ts +++ b/src/lib/ably-client.ts @@ -3,30 +3,22 @@ import { type Readable, readable } from "svelte/store"; import { browser } from "$app/environment"; export const ablyClientConnection = - browser && new ably.Realtime.Promise({ authUrl: "/ably-auth" }); + browser && new ably.Realtime({ authUrl: "/ably-auth" }); -const channels: { - [key: string]: { - ablyPromise: ably.Types.RealtimeChannelPromise; - svelteStore: Readable; - }; -} = {}; +const messages: { [key: string]: Readable } = {}; export function getChannel(name: string) { if (!ablyClientConnection) return readable(undefined); - if (name in channels) { - const channel = channels[name]; - if (channel.ablyPromise.state != "attached") - channel.ablyPromise.attach().then(); - return channel.svelteStore; - } - const ablyPromise = ablyClientConnection.channels.get(name); - const svelteStore = readable(undefined, (set) => { - ablyPromise.subscribe(set).then(); - return async () => { - await ablyPromise.detach(); + if (name in messages) return messages[name]; + const ablyChannel = ablyClientConnection.channels.get(name); + const message = readable(undefined, (set) => { + ablyChannel.subscribe(set); + return () => { + ablyChannel.detach(); + ablyChannel.unsubscribe(set); + delete messages[name]; }; }); - channels[name] = { ablyPromise, svelteStore }; - return svelteStore; + messages[name] = message; + return message; } diff --git a/src/lib/server/ably-server.ts b/src/lib/server/ably-server.ts index 268ce87..043a623 100644 --- a/src/lib/server/ably-server.ts +++ b/src/lib/server/ably-server.ts @@ -1,18 +1,18 @@ import ably from "ably"; import { ABLY_API_KEY } from "$env/static/private"; -const ablyServer = new ably.Realtime.Promise({ key: ABLY_API_KEY }); +const ablyServer = new ably.Realtime({ key: ABLY_API_KEY }); export default ablyServer; -export async function updateRealtimePoints( +export function updateRealtimePoints( gameId: number, userId: number, points: number, ) { - await ablyServer.channels + ablyServer.channels .get("player:" + gameId + ":" + userId) .publish("points", { points: points }); - await ablyServer.channels + ablyServer.channels .get("game:" + gameId + ":points") .publish("points", { userId, points }); } diff --git a/src/lib/server/get-player-id.ts b/src/lib/server/get-player-id.ts index d09316b..5ee6555 100644 --- a/src/lib/server/get-player-id.ts +++ b/src/lib/server/get-player-id.ts @@ -39,14 +39,12 @@ export default async function getPlayerId( user: { select: { name: true, picture: true } }, }, }); - await ablyServer.channels - .get("game:" + gameId + ":positions") - .publish("create", { - userId: user.id, - picture: newPlayer.user.picture, - svgRef: newPlayer.currRoom.svgRef, - }); - await ablyServer.channels + ablyServer.channels.get("game:" + gameId + ":positions").publish("create", { + userId: user.id, + picture: newPlayer.user.picture, + svgRef: newPlayer.currRoom.svgRef, + }); + ablyServer.channels .get("game:" + gameId + ":points") .publish("create", { userId: user.id, name: newPlayer.user.name }); return newPlayer.id; diff --git a/src/routes/ably-auth/+server.ts b/src/routes/ably-auth/+server.ts index 2b08703..9352a19 100644 --- a/src/routes/ably-auth/+server.ts +++ b/src/routes/ably-auth/+server.ts @@ -18,15 +18,22 @@ export const GET = async ({ locals }) => { for (const player of userData.players) { channels.push("game:" + player.gameId + ":*"); } - return json( - await ablyServer.auth.createTokenRequest({ - capability: channels.reduce( - (acc, channel) => { - acc[channel] = ["subscribe"]; - return acc; - }, - {} as { [key: string]: ["subscribe"] }, - ), - }), - ); + return new Promise((resolve, reject) => { + ablyServer.auth.createTokenRequest( + { + capability: channels.reduce( + (acc, channel) => { + acc[channel] = ["subscribe"]; + return acc; + }, + {} as { [key: string]: ["subscribe"] }, + ), + }, + undefined, + (err, tokenRequest) => { + if (err) reject(err.message); + else resolve(json(tokenRequest)); + }, + ); + }); }; diff --git a/src/routes/game/[gameId=id]/+page.svelte b/src/routes/game/[gameId=id]/+page.svelte index 3e43c9c..81382af 100644 --- a/src/routes/game/[gameId=id]/+page.svelte +++ b/src/routes/game/[gameId=id]/+page.svelte @@ -76,7 +76,7 @@ async function onClickRoom(clickedSvgRef: number) { if (canMoveTo(clickedSvgRef)) { - await goto("answer/?svgRef=" + clickedSvgRef) + await goto("answer/?svgRef=" + clickedSvgRef); } } diff --git a/src/routes/game/[gameId=id]/answer/+page.svelte b/src/routes/game/[gameId=id]/answer/+page.svelte index 83a99d3..1e1a01e 100644 --- a/src/routes/game/[gameId=id]/answer/+page.svelte +++ b/src/routes/game/[gameId=id]/answer/+page.svelte @@ -10,13 +10,14 @@ const emElement = document.createElement("em"); emElement.textContent = answer; usageElm.innerHTML = data.usageTemplate.replaceAll( - "{answer}", emElement.outerHTML - ) + "{answer}", + emElement.outerHTML, + ); } async function onKeyUp(event: KeyboardEvent) { if (event.key == "Enter") { - status = "waiting" + status = "waiting"; const res = await fetch("", { method: "POST", body: answer }); const json = await res.json(); if (res.ok) { @@ -41,10 +42,12 @@ on:keyup={onKeyUp} placeholder="Your answer..." type="text" - > + /> {#if data.wordClass}

{data.wordClass}

{/if}

{data.definition}

- {#if data.usageTemplate}

"{data.usageTemplate}"

{/if} + {#if data.usageTemplate}

+ "{data.usageTemplate}" +

{/if} @@ -73,7 +76,7 @@ } #definition-container { - @media (min-width: 700px) { + @media (width >= 700px) { border: 1px solid black; padding: 10px; width: 600px; @@ -81,7 +84,7 @@ & > * { font-size: 3em; - font-family: Times New Roman, Times, serif + font-family: "Times New Roman", Times, serif; } } @@ -94,7 +97,8 @@ font-weight: bold; } - #word-class, #usage { + #word-class, + #usage { font-style: italic; } @@ -105,15 +109,26 @@ .waiting { cursor: wait; + & input { cursor: wait; } } - .shake { animation: shake 0.15s 2; } + .shake { + animation: shake 0.15s 2; + } @keyframes shake { - 25% { transform: translateX(5px); } - 75% { transform: translateX(-5px); } - 100% { transform: translateX(0); } + 25% { + transform: translateX(5px); + } + + 75% { + transform: translateX(-5px); + } + + 100% { + transform: translateX(0); + } } - \ No newline at end of file + diff --git a/src/routes/game/[gameId=id]/answer/+server.ts b/src/routes/game/[gameId=id]/answer/+server.ts index 0128ed1..36ceb62 100644 --- a/src/routes/game/[gameId=id]/answer/+server.ts +++ b/src/routes/game/[gameId=id]/answer/+server.ts @@ -28,7 +28,6 @@ export const POST = async ({ request, params, locals }) => { ).test(await request.text()); if (correct) { const currMove = player.currMove; - // Done before responding so the client sees the correct number of points const newPlayerData = await prisma.player.update({ where: { id: player.id }, data: { @@ -39,20 +38,13 @@ export const POST = async ({ request, params, locals }) => { }, select: { points: true }, }); - setTimeout(async () => { - // Allow responding to request first - await ablyServer.channels - .get("game:" + params.gameId + ":positions") - .publish("move", { - userId: locals.user.id, - svgRef: currMove.svgRef, - }); - await updateRealtimePoints( - +params.gameId, - locals.user.id, - newPlayerData.points, - ); - }, 1); + ablyServer.channels + .get("game:" + params.gameId + ":positions") + .publish("move", { + userId: locals.user.id, + svgRef: currMove.svgRef, + }); + updateRealtimePoints(+params.gameId, locals.user.id, newPlayerData.points); } return json({ correct }); }; diff --git a/src/routes/game/[gameId=id]/end/+page.server.ts b/src/routes/game/[gameId=id]/end/+page.server.ts index a8ebb7e..2fb5696 100644 --- a/src/routes/game/[gameId=id]/end/+page.server.ts +++ b/src/routes/game/[gameId=id]/end/+page.server.ts @@ -24,7 +24,7 @@ export const load = async ({ params, locals }) => { where: { id: +params.gameId }, data: { isOngoing: false }, }); - await ablyServer.channels + ablyServer.channels .get("game:" + +params.gameId + ":announcements") .publish("end", null); } diff --git a/src/routes/game/[gameId=id]/shop/+page.svelte b/src/routes/game/[gameId=id]/shop/+page.svelte index dd2e072..0d74de1 100644 --- a/src/routes/game/[gameId=id]/shop/+page.svelte +++ b/src/routes/game/[gameId=id]/shop/+page.svelte @@ -14,7 +14,7 @@ async function buyItem(itemId: number) { const res = await fetch(`${itemId}/buy`); - if (!res.ok) alert((await res.json()).message); + if (!res.ok) res.json().then((json) => alert(json.message)); } diff --git a/src/routes/game/[gameId=id]/shop/[itemId=id]/buy/+server.ts b/src/routes/game/[gameId=id]/shop/[itemId=id]/buy/+server.ts index 09e5676..69dd39f 100644 --- a/src/routes/game/[gameId=id]/shop/[itemId=id]/buy/+server.ts +++ b/src/routes/game/[gameId=id]/shop/[itemId=id]/buy/+server.ts @@ -24,12 +24,10 @@ async function moveRoom( where: { id: playerId }, data: { currRoomId: roomId }, }); - await ablyServer.channels - .get("game:" + gameId + ":positions") - .publish("move", { - userId: userId, - svgRef: svgRef, - }); + ablyServer.channels.get("game:" + gameId + ":positions").publish("move", { + userId: userId, + svgRef: svgRef, + }); } const ACTIONS: { [key: string]: (details: ActionDetails) => Promise } = { @@ -130,7 +128,7 @@ const ACTIONS: { [key: string]: (details: ActionDetails) => Promise } = { where: { id: Number(randPlayer.id) }, data: { points: newPoints }, }); - await updateRealtimePoints(gameId, Number(randPlayer.userId), newPoints); + updateRealtimePoints(gameId, Number(randPlayer.userId), newPoints); }, }; @@ -173,13 +171,10 @@ export const GET = async ({ params, locals }) => { where: { id: player.id }, data: { points: { decrement: shopItem.cost } }, }); - setTimeout(async () => { - // Allow responding to the request first - await updateRealtimePoints( - +params.gameId, - locals.user.id, - player.points - shopItem.cost, - ); - }, 1); + updateRealtimePoints( + +params.gameId, + locals.user.id, + player.points - shopItem.cost, + ); return new Response(); };