diff --git a/package.json b/package.json index 9a36f3c..72fc260 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ "chart.js": "^4.4.4", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", + "comlink": "^4.4.1", "dexie": "^4.0.8", "dexie-react-hooks": "^1.1.7", "framer-motion": "^11.5.4", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8b9bdb8..c8a9a66 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -47,6 +47,9 @@ dependencies: clsx: specifier: ^2.1.1 version: 2.1.1 + comlink: + specifier: ^4.4.1 + version: 4.4.1 dexie: specifier: ^4.0.8 version: 4.0.8 @@ -1362,6 +1365,10 @@ packages: /color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + /comlink@4.4.1: + resolution: {integrity: sha512-+1dlx0aY5Jo1vHy/tSsIGpSkN4tS9rZSW8FIhG0JH/crs9wwweswIo/POr451r7bZww3hFbPAKnTpimzL/mm4Q==} + dev: false + /commander@4.1.1: resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} engines: {node: '>= 6'} diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 32ea760..6680cf8 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -5,10 +5,10 @@ import localFont from "next/font/local"; import BackgroundImage from "../components/background-image"; import DatabaseLoader from "../components/loaders/database-loader"; import NavBar from "../components/navbar/navbar"; -import { QueryProvider } from "../components/providers/query-provider"; -import { ThemeProvider } from "../components/providers/theme-provider"; -import { Toaster } from "../components/ui/toaster"; -import { TooltipProvider } from "../components/ui/tooltip"; +import { QueryProvider } from "@/components/providers/query-provider"; +import { ThemeProvider } from "@/components/providers/theme-provider"; +import { Toaster } from "@/components/ui/toaster"; +import { TooltipProvider } from "@/components/ui/tooltip"; import "./globals.css"; const siteFont = localFont({ diff --git a/src/common/song-utils.ts b/src/common/song-utils.ts index a966b7a..5bef4ac 100644 --- a/src/common/song-utils.ts +++ b/src/common/song-utils.ts @@ -1,4 +1,4 @@ -export const diffColors: Record = { +const diffColors: Record = { easy: "MediumSeaGreen", normal: "#59b0f4", hard: "tomato", @@ -45,6 +45,5 @@ export function accuracyToColor(acc: number): string { return badge.color; } } - // Return a default color if no badge matches - return "#000000"; // black or any default color + return "#000000"; // fallback color } diff --git a/src/common/workers/worker.ts b/src/common/workers/worker.ts new file mode 100644 index 0000000..0011f99 --- /dev/null +++ b/src/common/workers/worker.ts @@ -0,0 +1,16 @@ +import * as Comlink from "comlink"; +import { scoresaberFetcher } from "@/common/data-fetcher/impl/scoresaber"; + +export interface WorkerApi { + getName: typeof getName; +} + +const workerApi: WorkerApi = { + getName, +}; + +async function getName() { + return await scoresaberFetcher.lookupPlayer("76561198449412074"); +} + +Comlink.expose(workerApi); diff --git a/src/common/workers/workers.ts b/src/common/workers/workers.ts new file mode 100644 index 0000000..a45f1ec --- /dev/null +++ b/src/common/workers/workers.ts @@ -0,0 +1,5 @@ +import * as Comlink from "comlink"; +import { WorkerApi } from "@/common/workers/worker"; + +export const scoresaberReloadedWorker = () => + Comlink.wrap(new Worker(new URL("./worker.ts", import.meta.url))); diff --git a/src/components/player/player-data.tsx b/src/components/player/player-data.tsx index 43af6fa..9482644 100644 --- a/src/components/player/player-data.tsx +++ b/src/components/player/player-data.tsx @@ -8,6 +8,8 @@ import { useQuery } from "@tanstack/react-query"; import PlayerHeader from "./player-header"; import PlayerRankChart from "./player-rank-chart"; import PlayerScores from "./player-scores"; +import { useEffect } from "react"; +import { scoresaberReloadedWorker } from "@/common/workers/workers"; const REFRESH_INTERVAL = 5 * 60 * 1000; // 5 minutes @@ -31,6 +33,13 @@ export default function PlayerData({ refetchInterval: REFRESH_INTERVAL, }); + useEffect(() => { + (async () => { + const worker = scoresaberReloadedWorker(); + console.log(await worker.getName()); + })(); + }, []); + if (data && (!isLoading || !isError)) { player = data; } diff --git a/src/components/player/player-scores.tsx b/src/components/player/player-scores.tsx index 77caa9a..3d03eac 100644 --- a/src/components/player/player-scores.tsx +++ b/src/components/player/player-scores.tsx @@ -15,6 +15,41 @@ import Pagination from "../input/pagination"; import { Button } from "../ui/button"; import Score from "./score/score"; +type Props = { + initialScoreData?: ScoreSaberPlayerScoresPage; + player: ScoreSaberPlayer; + sort: ScoreSort; + page: number; +}; + +type PageState = { + /** + * The current page + */ + page: number; + + /** + * The current sort + */ + sort: ScoreSort; +}; + +const leaderboards = { + ScoreSaber: { + capabilities: { + search: true, + }, + queries: { + lookupScores: (player: ScoreSaberPlayer, pageState: PageState) => + scoresaberFetcher.lookupPlayerScores({ + playerId: player.id, + sort: ScoreSort.top, + page: 1, + }), + }, + }, +}; + const scoreSort = [ { name: "Top", @@ -52,31 +87,13 @@ const scoreAnimation: Variants = { }, }; -type Props = { - initialScoreData?: ScoreSaberPlayerScoresPage; - player: ScoreSaberPlayer; - sort: ScoreSort; - page: number; -}; - -type PageState = { - /** - * The current page - */ - page: number; - - /** - * The current sort - */ - sort: ScoreSort; -}; - export default function PlayerScores({ initialScoreData, player, sort, page, }: Props) { + const leaderboard = leaderboards.ScoreSaber; const { width } = useWindowDimensions(); const controls = useAnimation(); @@ -96,13 +113,8 @@ export default function PlayerScores({ isLoading, refetch, } = useQuery({ - queryKey: ["playerScores", player.id, pageState], - queryFn: () => - scoresaberFetcher.lookupPlayerScores({ - playerId: player.id, - sort: pageState.sort, - page: pageState.page, - }), + queryKey: ["playerScores", player.id, leaderboard, pageState], + queryFn: () => leaderboard.queries.lookupScores(player, pageState), staleTime: 30 * 1000, // Cache data for 30 seconds });