remind me to never try to handle a 53MB json file again

This commit is contained in:
not-nullptr 2024-03-16 19:00:09 +00:00
parent 99bfc69c64
commit 188e38c6ec
19 changed files with 185 additions and 109 deletions

View file

@ -1,60 +1,36 @@
<script lang="ts">
import type { IRoom } from "$types/rooms";
export let icon: string | undefined;
export let room: IRoom;
</script>
<div class="room">
<h3>{room.name} <span class="game">({room.preferredGameName || "No preferred game"})</span></h3>
<p>{room.description}</p>
<div class="player-count">
{room.players.length} / {room.maxPlayers} | {#if room.players.length > 4}
{#each room.players.slice(0, 4) as player}
{player.nickname}{#if player !== room.players[3]},{" "}
{/if}
{/each}
and {room.players.length - 4}
{room.players.length - 4 === 1 ? "other" : "others"}
{:else}
{#each room.players as player}
{player.nickname}{#if player !== room.players[room.players.length - 1]},{" "}
{/if}
{/each}
{/if} | {room.hasPassword ? "Private" : "Public"}
</div>
<div class="top-right">
{room.address}:{room.port}
<div class="relative flex h-fit items-center gap-6 rounded-[2.25rem] bg-[#110d10] p-6">
{#if icon}
<img src={icon} alt="Icon for '{room.preferredGameName}'" class="h-[100px] rounded-2xl" />
{/if}
<div>
<h2 class="mb-2 text-[20px] leading-[1.41] md:text-[28px] md:leading-[1.1]">
{room.name}
<span class="ml-1 text-base font-normal text-gray-500"
>({room.preferredGameName || "No preferred game"})</span
>
</h2>
<p>{room.description}</p>
<div class="mt-2 text-sm text-gray-600">
{room.players.length} / {room.maxPlayers} | {#if room.players.length > 4}
{#each room.players.slice(0, 4) as player}
{player.nickname}{#if player !== room.players[3]},{" "}
{/if}
{/each}
and {room.players.length - 4}
{room.players.length - 4 === 1 ? "other" : "others"}
{:else}
{#each room.players as player}
{player.nickname}{#if player !== room.players[room.players.length - 1]},{" "}
{/if}
{/each}
{/if} | {room.hasPassword ? "Private" : "Public"} | {room.address}:{room.port}
</div>
</div>
</div>
<style>
.room {
border: solid thin #353e52;
padding: 8px 12px;
background-color: var(--color-primary);
border-radius: 16px;
box-shadow: 0 0 48px 0 rgba(39, 56, 75, 0.5);
position: relative;
}
.player-count {
margin-top: 4px;
}
.game {
margin-left: 4px;
}
.top-right {
position: absolute;
top: 8px;
right: 12px;
}
.top-right,
.player-count,
.game {
opacity: 0.5;
font-size: 16px;
}
</style>

View file

@ -1,5 +0,0 @@
{
"landingHeader": "suyu",
"landingOne": "Suyu is an open-source, Switch compatible emulator with almost full coverage of the game library.",
"landingCardHeader": "We care about preservation"
}

View file

@ -0,0 +1,28 @@
interface SwitchGame {
bannerUrl: string;
category: string[];
description: string;
developer: null;
frontBoxArt: null;
iconUrl: string;
id: string;
intro: null | string;
isDemo: boolean;
key: null;
languages: string[];
name: string;
nsuId: number;
numberOfPlayers: number;
publisher: string;
rating: number;
ratingContent: string[];
region: null;
releaseDate: number;
rightsId: string;
screenshots: string[];
size: number;
version: null;
}
export const globalData: {
games: SwitchGame[];
} = { games: [] };

View file

@ -0,0 +1,7 @@
export function load({ cookies, url }) {
const token = cookies.get("token");
return {
tokenCookie: token,
url: url.pathname,
};
}

View file

@ -21,7 +21,7 @@
href: string;
}
const token = writable("");
const token = writable(data.tokenCookie || "");
function transitionIn(node: HTMLElement, { duration = 360 }: TransitionConfig) {
if ($reducedMotion)
@ -29,7 +29,7 @@
duration: 0,
};
node = node.querySelector(".content") || node;
const intensity = node.dataset.intensity || "160";
const intensity = node.dataset.intensityIn || "160";
const UA = navigator.userAgent;
const ff = UA.indexOf("Firefox") > -1;
if (!dropdownCloseFinished) {
@ -86,7 +86,7 @@
duration: 0,
};
node = node.querySelector(".content") || node;
const intensity = node.dataset.intensity || "160";
const intensity = node.dataset.intensityOut || "240";
if (!dropdownCloseFinished)
return {
duration: 0,
@ -149,8 +149,8 @@
href: "https://gitlab.com/suyu-emu/",
},
{
name: $token ? "Account" : "Sign up",
href: $token ? "/account" : "/signup",
name: $token || data.tokenCookie ? "Account" : "Sign up",
href: $token || data.tokenCookie ? "/account" : "/signup",
},
] as NavItem[];
@ -216,10 +216,11 @@
});
</script>
<!-- unfortunately, firefox is horrendous at rendering transforms so we can't enable it there -->
{#if navigator.userAgent.indexOf("Firefox") === -1}
<div
class="opacity-10"
style="position: fixed; width: 100vw; height: 100vh; --mask-image: linear-gradient(to bottom, transparent 50px, black 150px); mask-image: var(--mask-image); -webkit-mask-image: var(--mask-image);"
class="opacity-5"
style="position: fixed; width: 100vw; height: 100vh; --mask-image: linear-gradient(to bottom, transparent 50px, black 150px, transparent); mask-image: var(--mask-image); -webkit-mask-image: var(--mask-image);"
>
<BackgroundProvider size={90} gap={16} speed={0.25} />
</div>
@ -318,7 +319,7 @@
<div
style="transition: 180ms ease;"
aria-hidden={!dropdownOpenFinished && !dropdownOpen}
class={`${navigator.userAgent.indexOf("Firefox") > -1 ? "bg-[#0e0d10]" : "bg-[rgba(0,0,0,0.25)] backdrop-blur-xl"} fixed left-0 z-[99999] h-screen w-full p-9 pt-[120px] ${dropdownOpen ? "pointer-events-auto visible opacity-100" : "pointer-events-none opacity-0"} ${!dropdownOpen && dropdownCloseFinished ? "invisible" : ""}`}
class={`fixed left-0 z-[99999] h-screen w-full bg-[#0e0d10] p-9 pt-[120px] ${dropdownOpen ? "pointer-events-auto visible opacity-100" : "pointer-events-none opacity-0"} ${!dropdownOpen && dropdownCloseFinished ? "invisible" : ""}`}
>
<div class={`flex flex-col gap-8`}>
<!-- <a href="##"><h1 class="w-full text-5xl">Blog</h1></a>

View file

@ -1,5 +0,0 @@
export function load({ url }) {
return {
url: url.pathname,
};
}

View file

@ -1,5 +1,6 @@
import { building } from "$app/environment";
import { DISCORD_USER_TOKEN, GITLAB_API_TOKEN } from "$env/static/private";
import { globalData } from "$lib/server/other";
let memberCount = 0;
let starCount = 0;
@ -40,13 +41,25 @@ async function fetchServerSideData() {
console.log("Stars count:", starCount);
}
if (!building) {
await fetchServerSideData();
setInterval(fetchServerSideData, 1000 * 60 * 10);
async function fetchSlowServerSideData() {
console.log("Fetching game data");
const res = await fetch("https://raw.githubusercontent.com/blawar/titledb/master/US.en.json");
let gamesText = await res.text();
gamesText = gamesText.replaceAll(/\\u[0-9a-fA-F]{4}/gm, "");
globalData.games = Object.values(JSON.parse(gamesText));
console.log("Fetched game data");
}
export async function load(opts) {
if (!building) {
await Promise.all([await fetchServerSideData(), await fetchSlowServerSideData()]);
setInterval(fetchServerSideData, 1000 * 60 * 10);
setInterval(fetchSlowServerSideData, 1000 * 60 * 60 * 12);
}
export async function load({ cookies }) {
const token = cookies.get("token");
return {
tokenCookie: token,
memberCount,
starCount,
roleMembers,

View file

@ -6,9 +6,9 @@
import { Dialog } from "radix-svelte";
export let data: PageData;
$: memberCount = parseFloat(data.memberCount.toPrecision(2));
$: contributors = parseFloat(data.roleMembers["1214817156420862012"].toPrecision(2));
$: starCount = parseFloat(data.starCount.toPrecision(2));
$: memberCount = parseFloat(data.memberCount?.toPrecision(2));
$: contributors = parseFloat(data.roleMembers["1214817156420862012"]?.toPrecision(2));
$: starCount = parseFloat(data.starCount?.toPrecision(2));
let metadata = {
url: "https://suyu.dev",
title: "suyu - Open-source, non-profit Switch emulator",
@ -40,7 +40,7 @@
</svelte:head>
<div
class="relative flex w-full flex-col gap-6 overflow-hidden rounded-[2.25rem] rounded-bl-none rounded-br-none bg-[rgba(0,0,0,0.25)] p-8 backdrop-blur-xl md:p-12 lg:rounded-bl-none lg:rounded-br-[2.25rem]"
class="relative flex w-full flex-col gap-6 overflow-hidden rounded-[2.25rem] rounded-bl-none rounded-br-none bg-[#110d10] p-8 md:p-12 lg:rounded-bl-none lg:rounded-br-[2.25rem]"
>
<svg
xmlns="http://www.w3.org/2000/svg"
@ -88,7 +88,7 @@
</Dialog.Trigger>
<Dialog.Portal>
<Dialog.Overlay
class="fixed inset-0 z-[9999] bg-black/80 data-[state=open]:animate-[overlayShow_555ms_cubic-bezier(.16,1,.3,1)]"
class="fixed inset-0 z-[9999] bg-[#110d10]/80 data-[state=open]:animate-[overlayShow_555ms_cubic-bezier(.16,1,.3,1)]"
/>
<Dialog.Content
class="fixed left-[50%] top-[50%] z-[9999] max-h-[85vh] w-[90vw] max-w-[450px] translate-x-[-50%]
@ -142,7 +142,7 @@
<div class="flex w-full flex-col lg:flex-row">
<div
class="flex w-full flex-shrink-0 flex-col gap-8 rounded-b-[2.25rem] bg-black p-12 lg:w-[35%]"
class="flex w-full flex-shrink-0 flex-col gap-8 rounded-b-[2.25rem] bg-[#110d10] p-12 lg:w-[35%]"
>
<h1 class="text-[48px] leading-[0.9]">By the numbers</h1>
<div class="flex flex-col gap-0">
@ -200,12 +200,12 @@
<div class="text-[#A6A5A7]">members on Discord</div>
</div>
</div>
<div class="flex w-full flex-1 rounded-[2.25rem] bg-black lg:rounded-tl-none">
<div class="flex w-full flex-1 rounded-[2.25rem] bg-[#110d10] lg:rounded-tl-none">
<div
class="flex w-full flex-1 rounded-[2.25rem] rounded-bl-none rounded-tr-none bg-[#131215] pt-8 lg:pl-8"
>
<div
class="h-full w-full overflow-hidden rounded-[2.25rem] bg-black shadow-lg ring ring-[#ffffff11]"
class="h-full w-full overflow-hidden rounded-[2.25rem] bg-[#110d10] shadow-lg ring ring-[#ffffff11]"
>
<img
class="h-full max-h-[496px] w-full object-cover"
@ -287,7 +287,7 @@
</div>
<div
class="relative mt-48 flex w-full flex-col gap-6 overflow-hidden rounded-[2.25rem] bg-black p-8 md:p-12"
class="relative mt-48 flex w-full flex-col gap-6 overflow-hidden rounded-[2.25rem] bg-[#110d10] p-8 md:p-12"
>
<h1 class="text-[24px] leading-[1.41] md:text-[60px] md:leading-[1.1]">
were passionate about preserving games.

View file

@ -29,10 +29,10 @@
name: "Lobbies",
href: "/account/lobbies",
},
{
name: "Friends",
href: "/account/friends",
},
// {
// name: "Friends",
// href: "/account/friends",
// },
];
function navClick(e: MouseEvent | HTMLAnchorElement) {
@ -144,13 +144,11 @@
[
{
opacity: "1",
filter: "blur(0px)",
transform: "translateY(0px)",
marginTop: "0px",
},
{
opacity: "0",
filter: "blur(20px)",
transform: "translateY(-50px)",
marginTop: "40px",
},
],
$reducedMotion
@ -170,7 +168,7 @@
{#key data.url}
<div
class={`navbar ${data.url} relative z-50 mb-4 flex w-max gap-1 overflow-hidden rounded-full bg-black p-1`}
class={`navbar ${data.url} relative z-50 mb-4 flex w-max gap-1 overflow-hidden rounded-full bg-[#110d10] p-1`}
bind:this={navBar}
>
<div
@ -194,7 +192,7 @@
{/key}
<div class="relative">
<div class="content absolute w-full">
<div data-intensity-in={80} data-intensity-out={140} class="content absolute w-full">
<slot />
</div>
</div>

View file

@ -32,7 +32,7 @@
<div class="relative h-[calc(100vh-200px)] flex-col gap-6 overflow-hidden">
<div
class="relative flex w-full flex-col gap-6 overflow-hidden rounded-[2.25rem] bg-black p-8 md:p-12"
class="relative flex w-full flex-col gap-6 overflow-hidden rounded-[2.25rem] bg-[#110d10] p-8 md:p-12"
>
<svg
xmlns="http://www.w3.org/2000/svg"
@ -55,9 +55,9 @@
<h2 class="text-[36px] leading-[1.41] md:text-[48px] md:leading-[1.1]">Multiplayer</h2>
<p class="text-wrap text-lg leading-relaxed text-[#A6A5A7]">
Hey, <span
class="bg-gradient-to-r from-[#60c7e9] via-[#e06bb3] to-[#f94d4d] bg-clip-text font-bold text-transparent"
class="bg-gradient-to-r from-[#60c7e9] via-[#e06bb3] to-[#f94d4d] bg-clip-text font-black tracking-tighter text-transparent"
>{data.user.username}</span
>! This is your <i>token</i>, used to authenticate your identity within suyu. Your token
>! This is your <b>token</b>, used to authenticate your identity within suyu. Your token
should be kept private. If you believe it has been compromised, please contact us
immediately.
</p>

View file

@ -1,6 +1,6 @@
<div class="relative h-[calc(100vh-200px)] flex-col gap-6 overflow-hidden">
<div
class="relative flex w-full flex-col gap-6 overflow-hidden rounded-[2.25rem] bg-black p-8 md:p-12"
class="relative flex w-full flex-col gap-6 overflow-hidden rounded-[2.25rem] bg-[#110d10] p-8 md:p-12"
>
<h2 class=" text-[36px] leading-[1.41] md:text-[48px] md:leading-[1.1]">Friends</h2>
<p class="text-md text-wrap leading-relaxed text-[#4e4e4e]">

View file

@ -1,7 +1,14 @@
import { building } from "$app/environment";
import { RoomManager } from "$lib/server/class/Room.js";
import { globalData } from "$lib/server/other/index.js";
export function load({ request }) {
const rooms = RoomManager.getRooms().map((r) => r.toJSON()) || [];
const requiredGames = rooms
.map((r) => r.preferredGameName.toUpperCase().trim())
.map((r) => globalData.games.find((g) => g.name.toUpperCase().trim() === r));
return {
rooms: RoomManager.getRooms().map((r) => r.toJSON()) || [],
rooms: rooms,
games: requiredGames,
};
}

View file

@ -1,15 +1,61 @@
<script lang="ts">
import Room from "$components/Room.svelte";
import { reducedMotion } from "$lib/accessibility";
import { transition } from "$lib/util/animation";
import { onMount } from "svelte";
import type { PageData } from "./$types";
export let data: PageData;
$: console.log(data);
function transitionIn() {
const rooms = document.querySelectorAll<HTMLDivElement>(".room");
rooms.forEach((room, i) => {
const x = parseInt(room.dataset.index!);
room.getAnimations().forEach((animation) => animation.cancel());
room.style.zIndex = ((i + 1) * 5).toString();
room.animate(
[
{
transform: "translateY(-200px)",
opacity: "0",
filter: "blur(20px)",
},
{
transform: "translateY(0px)",
opacity: "1",
filter: "blur(0px)",
},
],
$reducedMotion
? {
duration: 0,
fill: "forwards",
}
: {
duration: 700,
easing: transition,
delay: x * 80,
fill: "forwards",
},
).onfinish = () => {
room.style.opacity = "1";
};
});
}
onMount(() => {
transitionIn();
});
</script>
<div class="relative h-[calc(100vh-200px)] flex-col gap-6 overflow-hidden">
<div
class="relative flex w-full flex-col gap-6 overflow-hidden rounded-[2.25rem] bg-black p-8 md:p-12"
>
{#each data.rooms as room}
<p>{room.name}</p>
<div class="relative h-[calc(100vh-200px)]">
<div class="relative flex w-full flex-col gap-4 pb-6">
{#each data.rooms as room, i}
<div class="room opacity-0" data-index={i}>
<Room icon={data.games[i]?.iconUrl} {room} />
</div>
{/each}
</div>
</div>

View file

@ -33,7 +33,7 @@
filter: "blur(0px)",
},
],
reducedMotion
$reducedMotion
? {
duration: 0,
fill: "forwards",
@ -71,7 +71,7 @@
{#each data.posts as post}
<a href={`/blog/${post.slug}`}>
<div
class="card relative h-[250px] w-full translate-y-[-200px] overflow-hidden rounded-[2.25rem] border-2 border-solid border-zinc-700 bg-black p-8 opacity-0 blur-[20px] lg:h-[400px]"
class="card relative h-[250px] w-full translate-y-[-200px] overflow-hidden rounded-[2.25rem] border-2 border-solid border-zinc-700 bg-[#110d10] p-8 opacity-0 blur-[20px] lg:h-[400px]"
>
<div
style="--mask-image: linear-gradient(to bottom, rgba(0, 0, 0, 1) 0%, rgba(0,0,0,0) 100%); mask-image: var(--mask-image); -webkit-mask-image: var(--mask-image);"

View file

@ -29,7 +29,7 @@
<textarea
id="write"
bind:value={content}
class="h-full w-full resize-none rounded-2xl !border-none bg-black p-4 font-[Consolas] !outline-none ring ring-[#ffffff11] focus:ring-[#ffffff44]"
class="h-full w-full resize-none rounded-2xl !border-none bg-[#110d10] p-4 font-[Consolas] !outline-none ring ring-[#ffffff11] focus:ring-[#ffffff44]"
></textarea>
</form>
</div>

View file

@ -3,7 +3,7 @@
</svelte:head>
<div
class="relative flex w-full flex-col gap-6 overflow-hidden rounded-[2.25rem] bg-black p-8 md:p-12"
class="relative flex w-full flex-col gap-6 overflow-hidden rounded-[2.25rem] bg-[#110d10] md:p-12"
>
<svg
xmlns="http://www.w3.org/2000/svg"

View file

@ -45,7 +45,7 @@
<div
class="align-center relative flex h-[calc(100vh-200px)] flex-col items-center justify-center gap-6 overflow-hidden"
>
<div class="flex h-fit w-full max-w-[500px] flex-col rounded-[2.25rem] bg-black p-10">
<div class="flex h-fit w-full max-w-[500px] flex-col rounded-[2.25rem] bg-[#110d10] p-10">
<h1 class="text-[60px] md:leading-[1.1]">Sign up</h1>
<div class="mt-4 flex flex-col gap-4">
<p>