This commit is contained in:
parent
a45002f693
commit
10719b6d83
21 changed files with 533 additions and 35 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -5,3 +5,6 @@ certs
|
|||
.env.production
|
||||
.env.staging
|
||||
stepData.ndjson
|
||||
|
||||
public/bannerImages/*
|
||||
!public/bannerImages/.gitkeep
|
30
lib/db/client.ts
Normal file
30
lib/db/client.ts
Normal file
|
@ -0,0 +1,30 @@
|
|||
import type { BindParams, QueryExecResult } from "sql.js";
|
||||
import { RpcProvider } from "worker-rpc";
|
||||
import DbWorker from "./db.worker?worker";
|
||||
|
||||
const worker = new DbWorker();
|
||||
|
||||
const rpcProvider = new RpcProvider((message, transfer) =>
|
||||
worker.postMessage(message, transfer),
|
||||
);
|
||||
|
||||
worker.onmessage = (e) => rpcProvider.dispatch(e.data);
|
||||
|
||||
export async function getDbClient() {
|
||||
await new Promise<void>((resolve) => {
|
||||
rpcProvider.registerSignalHandler("ready", () => {
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
return {
|
||||
async run(s: string, p?: BindParams[]) {
|
||||
return await rpcProvider.rpc("run", { s, p });
|
||||
},
|
||||
async exec(s: string, p?: BindParams[]): Promise<QueryExecResult[]> {
|
||||
return await rpcProvider.rpc("exec", { s, p });
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export const dbClient = await getDbClient();
|
59
lib/db/db.worker.ts
Normal file
59
lib/db/db.worker.ts
Normal file
|
@ -0,0 +1,59 @@
|
|||
import sqlWasmUrl from "@jlongster/sql.js/dist/sql-wasm.wasm?url";
|
||||
import initSqlJs from "@jlongster/sql.js";
|
||||
import { SQLiteFS } from "absurd-sql";
|
||||
import type { Database } from "sql.js";
|
||||
import IndexedDBBackend from "absurd-sql/dist/indexeddb-backend";
|
||||
import { RpcProvider } from "worker-rpc";
|
||||
|
||||
let SQL;
|
||||
let db: Database;
|
||||
|
||||
async function init() {
|
||||
const SQL = await initSqlJs({
|
||||
locateFile: (file) => {
|
||||
console.log("FILE IS", file);
|
||||
console.log("url is", sqlWasmUrl);
|
||||
switch (file) {
|
||||
case "sql-wasm.wasm":
|
||||
return sqlWasmUrl;
|
||||
}
|
||||
return file;
|
||||
},
|
||||
});
|
||||
|
||||
const sqlFS = new SQLiteFS(SQL.FS, new IndexedDBBackend());
|
||||
SQL.register_for_idb(sqlFS);
|
||||
|
||||
SQL.FS.mkdir("/sql");
|
||||
SQL.FS.mount(sqlFS, {}, "/sql");
|
||||
|
||||
const path = "/sql/db.sqlite";
|
||||
if (typeof SharedArrayBuffer === "undefined") {
|
||||
const stream = SQL.FS.open(path, "a+");
|
||||
await stream.node.contents.readIfFallback();
|
||||
SQL.FS.close(stream);
|
||||
}
|
||||
|
||||
db = new SQL.Database(path, { filename: true });
|
||||
db.exec("PRAGMA journal_mode=MEMORY;");
|
||||
}
|
||||
|
||||
await init();
|
||||
|
||||
const rpcProvider = new RpcProvider((message, transfer) =>
|
||||
self.postMessage(message, undefined, transfer),
|
||||
);
|
||||
|
||||
self.addEventListener("message", (evt) => rpcProvider.dispatch(evt.data));
|
||||
|
||||
rpcProvider.registerRpcHandler("run", ({ s, p }) => {
|
||||
return db.run(s, p);
|
||||
});
|
||||
|
||||
rpcProvider.registerRpcHandler("exec", ({ s, p }) => {
|
||||
return db.exec(s, p);
|
||||
});
|
||||
|
||||
console.log("SHIET");
|
||||
|
||||
rpcProvider.signal("ready");
|
7
lib/idb.ts
Normal file
7
lib/idb.ts
Normal file
|
@ -0,0 +1,7 @@
|
|||
// TODO: Actually do a partial download
|
||||
export function downloadDatafile() {
|
||||
// Get download status from local storage
|
||||
const stepDataDownloadStatus = localStorage.getItem(
|
||||
"stepDataDownloadStatus",
|
||||
) ?? { hash: null };
|
||||
}
|
|
@ -25,10 +25,13 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
export default function ndjsonStream(stream: ReadableStream) {
|
||||
export default function ndjsonStream<T>(
|
||||
stream: ReadableStream,
|
||||
): ReadableStream<T> {
|
||||
// For cancellation
|
||||
let is_reader: ReadableStreamDefaultReader | undefined = undefined;
|
||||
let cancellationRequest = false;
|
||||
|
||||
return new ReadableStream({
|
||||
start: (controller) => {
|
||||
const reader = stream.getReader();
|
||||
|
@ -46,7 +49,7 @@ export default function ndjsonStream(stream: ReadableStream) {
|
|||
data_buf = data_buf.trim();
|
||||
if (data_buf.length !== 0) {
|
||||
try {
|
||||
const data_l = JSON.parse(data_buf);
|
||||
const data_l = JSON.parse(data_buf) as T;
|
||||
controller.enqueue(data_l);
|
||||
} catch (e) {
|
||||
controller.error(e);
|
||||
|
|
|
@ -111,7 +111,7 @@ function parseArrowStream(
|
|||
const arrows: Arrow[] = [];
|
||||
const freezes: FreezeBody[] = [];
|
||||
|
||||
let currentFreezeDirections: string[] = [];
|
||||
const currentFreezeDirections: string[] = [];
|
||||
const openFreezes: Record<
|
||||
FreezeBody["direction"],
|
||||
Partial<FreezeBody> | null
|
||||
|
|
|
@ -1,13 +1,19 @@
|
|||
import { stat, readFile, readdir, copyFile } from "node:fs/promises";
|
||||
import { join, extname, resolve } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { join, extname, dirname, resolve } from "node:path";
|
||||
import { createHash } from "node:crypto";
|
||||
import { parseDwi } from "./parseDwi";
|
||||
import { parseSm } from "./parseSm";
|
||||
|
||||
const FILENAME = fileURLToPath(import.meta.url);
|
||||
const REPO_ROOT = dirname(dirname(dirname(FILENAME)));
|
||||
|
||||
type RawSimfile = Omit<Simfile, "mix" | "title"> & {
|
||||
title: string;
|
||||
titletranslit: string | null;
|
||||
banner: string | null;
|
||||
bannerEncoded: string | null;
|
||||
bannerHash: string | null;
|
||||
bannerFilename: string | null;
|
||||
displayBpm: string | undefined;
|
||||
};
|
||||
type Parser = (simfileSource: string, titleDir: string) => Promise<RawSimfile>;
|
||||
|
@ -71,7 +77,13 @@ async function parseSimfile(
|
|||
const bannerPath = join(stepchartSongDirPath, rawStepchart.banner);
|
||||
try {
|
||||
const bannerData = await readFile(bannerPath);
|
||||
rawStepchart.bannerEncoded = bannerData.toString("base64");
|
||||
const hash = createHash("sha256").update(bannerData).digest("hex");
|
||||
const ext = extname(rawStepchart.banner);
|
||||
const filename = `${hash}${ext}`;
|
||||
const outPath = join(REPO_ROOT, "public", "bannerImages", filename);
|
||||
copyFile(bannerPath, outPath);
|
||||
rawStepchart.bannerHash = hash;
|
||||
rawStepchart.bannerFilename = filename;
|
||||
} catch (e) {}
|
||||
|
||||
// if (bannerMeta !== undefined) {
|
||||
|
|
|
@ -16,7 +16,8 @@ function concludesANoteTag(line: string | undefined): boolean {
|
|||
return line[0] === ";" || (line[0] === "," && line[1] === ";");
|
||||
}
|
||||
|
||||
function getMeasureLength(lines: string[], i: number): number {
|
||||
function getMeasureLength(lines: string[], i0: number): number {
|
||||
let i = i0;
|
||||
let measureLength = 0;
|
||||
|
||||
for (
|
||||
|
@ -44,8 +45,9 @@ function isRest(line: string): boolean {
|
|||
function findFirstNonEmptyMeasure(
|
||||
mode: "single" | "double",
|
||||
lines: string[],
|
||||
i: number,
|
||||
i0: number,
|
||||
): { firstNonEmptyMeasureIndex: number; numMeasuresSkipped: number } {
|
||||
let i = i0;
|
||||
let numMeasuresSkipped = 0;
|
||||
let measureIndex = i;
|
||||
|
||||
|
@ -202,7 +204,8 @@ async function parseSm(sm: string, _titlePath: string): Promise<RawSimfile> {
|
|||
return freezes;
|
||||
}
|
||||
|
||||
function parseNotes(lines: string[], i: number, bpmString: string): number {
|
||||
function parseNotes(lines: string[], i0: number, bpmString: string): number {
|
||||
let i = i0;
|
||||
// move past #NOTES into the note metadata
|
||||
i++;
|
||||
const mode = lines[i++].replace("dance-", "").replace(":", "");
|
||||
|
|
1
lib/stepcharts/stepcharts.d.ts
vendored
1
lib/stepcharts/stepcharts.d.ts
vendored
|
@ -52,6 +52,7 @@ type Stop = {
|
|||
};
|
||||
|
||||
type Stepchart = {
|
||||
src: string;
|
||||
arrows: Arrow[];
|
||||
freezes: FreezeBody[];
|
||||
bpm: Bpm[];
|
||||
|
|
11
package.json
11
package.json
|
@ -19,6 +19,7 @@
|
|||
"@types/ndjson": "^2.0.4",
|
||||
"@types/react": "^18.3.2",
|
||||
"@types/react-dom": "^18.3.0",
|
||||
"@types/sql.js": "^1.4.9",
|
||||
"@vite-pwa/assets-generator": "^0.2.4",
|
||||
"@vitejs/plugin-basic-ssl": "^1.1.0",
|
||||
"@vitejs/plugin-react-swc": "^3.6.0",
|
||||
|
@ -33,9 +34,16 @@
|
|||
"dependencies": {
|
||||
"@emotion/react": "^11.11.4",
|
||||
"@emotion/styled": "^11.11.5",
|
||||
"@fontsource/inter": "^5.0.18",
|
||||
"@jlongster/sql.js": "^1.6.7",
|
||||
"@mui/icons-material": "^5.15.17",
|
||||
"@mui/joy": "5.0.0-beta.36",
|
||||
"@mui/material": "^5.15.17",
|
||||
"@tanstack/react-query": "^5.36.1",
|
||||
"@tanstack/react-table": "^8.17.3",
|
||||
"@zlepper/rpc": "^0.0.10",
|
||||
"@zlepper/web-worker-rpc": "^0.0.10",
|
||||
"absurd-sql": "^0.0.54",
|
||||
"classnames": "^2.5.1",
|
||||
"jotai": "^2.8.0",
|
||||
"ndjson": "^2.0.0",
|
||||
|
@ -43,6 +51,7 @@
|
|||
"react-dom": "^18.3.1",
|
||||
"react-router": "^6.23.1",
|
||||
"react-router-dom": "^6.23.1",
|
||||
"stream-json": "^1.8.0"
|
||||
"stream-json": "^1.8.0",
|
||||
"worker-rpc": "^0.2.0"
|
||||
}
|
||||
}
|
||||
|
|
266
pnpm-lock.yaml
266
pnpm-lock.yaml
|
@ -14,15 +14,36 @@ importers:
|
|||
'@emotion/styled':
|
||||
specifier: ^11.11.5
|
||||
version: 11.11.5(@emotion/react@11.11.4(@types/react@18.3.2)(react@18.3.1))(@types/react@18.3.2)(react@18.3.1)
|
||||
'@fontsource/inter':
|
||||
specifier: ^5.0.18
|
||||
version: 5.0.18
|
||||
'@jlongster/sql.js':
|
||||
specifier: ^1.6.7
|
||||
version: 1.6.7
|
||||
'@mui/icons-material':
|
||||
specifier: ^5.15.17
|
||||
version: 5.15.17(@mui/material@5.15.17(@emotion/react@11.11.4(@types/react@18.3.2)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.2)(react@18.3.1))(@types/react@18.3.2)(react@18.3.1))(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.2)(react@18.3.1)
|
||||
'@mui/joy':
|
||||
specifier: 5.0.0-beta.36
|
||||
version: 5.0.0-beta.36(@emotion/react@11.11.4(@types/react@18.3.2)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.2)(react@18.3.1))(@types/react@18.3.2)(react@18.3.1))(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@mui/material':
|
||||
specifier: ^5.15.17
|
||||
version: 5.15.17(@emotion/react@11.11.4(@types/react@18.3.2)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.2)(react@18.3.1))(@types/react@18.3.2)(react@18.3.1))(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@tanstack/react-query':
|
||||
specifier: ^5.36.1
|
||||
version: 5.36.1(react@18.3.1)
|
||||
'@tanstack/react-table':
|
||||
specifier: ^8.17.3
|
||||
version: 8.17.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@zlepper/rpc':
|
||||
specifier: ^0.0.10
|
||||
version: 0.0.10
|
||||
'@zlepper/web-worker-rpc':
|
||||
specifier: ^0.0.10
|
||||
version: 0.0.10(@zlepper/rpc@0.0.10)
|
||||
absurd-sql:
|
||||
specifier: ^0.0.54
|
||||
version: 0.0.54
|
||||
classnames:
|
||||
specifier: ^2.5.1
|
||||
version: 2.5.1
|
||||
|
@ -47,6 +68,9 @@ importers:
|
|||
stream-json:
|
||||
specifier: ^1.8.0
|
||||
version: 1.8.0
|
||||
worker-rpc:
|
||||
specifier: ^0.2.0
|
||||
version: 0.2.0
|
||||
devDependencies:
|
||||
'@biomejs/biome':
|
||||
specifier: ^1.7.3
|
||||
|
@ -60,6 +84,9 @@ importers:
|
|||
'@types/react-dom':
|
||||
specifier: ^18.3.0
|
||||
version: 18.3.0
|
||||
'@types/sql.js':
|
||||
specifier: ^1.4.9
|
||||
version: 1.4.9
|
||||
'@vite-pwa/assets-generator':
|
||||
specifier: ^0.2.4
|
||||
version: 0.2.4
|
||||
|
@ -945,6 +972,12 @@ packages:
|
|||
'@floating-ui/utils@0.2.2':
|
||||
resolution: {integrity: sha512-J4yDIIthosAsRZ5CPYP/jQvUAQtlZTTD/4suA08/FEnlxqW3sKS9iAhgsa9VYLZ6vDHn/ixJgIqRQPotoBjxIw==}
|
||||
|
||||
'@fontsource/inter@5.0.18':
|
||||
resolution: {integrity: sha512-YCsoYPTcs713sI7tLtxaPrIhXAXvEetGg5Ry02ivA8qUOb3fQHojbK/X9HLD5OOKvFUNR2Ynkwb1kR1hVKQHpw==}
|
||||
|
||||
'@jlongster/sql.js@1.6.7':
|
||||
resolution: {integrity: sha512-4hf0kZr5WPoirdR5hUSfQ9O0JpH/qlW1CaR2wZ6zGrDz1xjSdTPuR8AW/oXzIHnJvZSEvlcIE+dfXJZwh/Lxfw==}
|
||||
|
||||
'@jridgewell/gen-mapping@0.3.5':
|
||||
resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==}
|
||||
engines: {node: '>=6.0.0'}
|
||||
|
@ -977,9 +1010,23 @@ packages:
|
|||
'@types/react':
|
||||
optional: true
|
||||
|
||||
'@mui/base@5.0.0-beta.42':
|
||||
resolution: {integrity: sha512-fWRiUJVCHCPF+mxd5drn08bY2qRw3jj5f1SSQdUXmaJ/yKpk23ys8MgLO2KGVTRtbks/+ctRfgffGPbXifj0Ug==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
peerDependencies:
|
||||
'@types/react': ^17.0.0 || ^18.0.0
|
||||
react: ^17.0.0 || ^18.0.0
|
||||
react-dom: ^17.0.0 || ^18.0.0
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
|
||||
'@mui/core-downloads-tracker@5.15.17':
|
||||
resolution: {integrity: sha512-DVAejDQkjNnIac7MfP8sLzuo7fyrBPxNdXe+6bYqOqg1z2OPTlfFAejSNzWe7UenRMuFu9/AyFXj/X2vN2w6dA==}
|
||||
|
||||
'@mui/core-downloads-tracker@6.0.0-dev.240424162023-9968b4889d':
|
||||
resolution: {integrity: sha512-doh3M3U7HUGSBIWGe1yvesSbfDguMRjP0N09ogWSBM2hovXAlgULhMgcRTepAZLLwfRxFII0bCohq6B9NqoKuw==}
|
||||
|
||||
'@mui/icons-material@5.15.17':
|
||||
resolution: {integrity: sha512-xVzl2De7IY36s/keHX45YMiCpsIx3mNv2xwDgtBkRSnZQtVk+Gqufwj1ktUxEyjzEhBl0+PiNJqYC31C+n1n6A==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
|
@ -991,6 +1038,23 @@ packages:
|
|||
'@types/react':
|
||||
optional: true
|
||||
|
||||
'@mui/joy@5.0.0-beta.36':
|
||||
resolution: {integrity: sha512-fFW8jqA/6JcnjjSUgiFJ17bbvMxwFU+daT5Ohpi1qYrDub0XYj1+8UYDUgGCLsv8XNe50AkbnqidtAlMpq7Glg==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
peerDependencies:
|
||||
'@emotion/react': ^11.5.0
|
||||
'@emotion/styled': ^11.3.0
|
||||
'@types/react': ^17.0.0 || ^18.0.0
|
||||
react: ^17.0.0 || ^18.0.0
|
||||
react-dom: ^17.0.0 || ^18.0.0
|
||||
peerDependenciesMeta:
|
||||
'@emotion/react':
|
||||
optional: true
|
||||
'@emotion/styled':
|
||||
optional: true
|
||||
'@types/react':
|
||||
optional: true
|
||||
|
||||
'@mui/material@5.15.17':
|
||||
resolution: {integrity: sha512-ru/MLvTkCh0AZXmqwIpqGTOoVBS/sX48zArXq/DvktxXZx4fskiRA2PEc7Rk5ZlFiZhKh4moL4an+l8zZwq49Q==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
|
@ -1018,6 +1082,16 @@ packages:
|
|||
'@types/react':
|
||||
optional: true
|
||||
|
||||
'@mui/private-theming@6.0.0-alpha.5':
|
||||
resolution: {integrity: sha512-jMo45tVNOA0t2GEIgOiroPHWkranirwNGdzElxjbNmNXhxniFHDISKzCvEljCEfU88syAwm9fi22CwmqwIbfag==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
peerDependencies:
|
||||
'@types/react': ^17.0.0 || ^18.0.0
|
||||
react: ^17.0.0 || ^18.0.0
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
|
||||
'@mui/styled-engine@5.15.14':
|
||||
resolution: {integrity: sha512-RILkuVD8gY6PvjZjqnWhz8fu68dVkqhM5+jYWfB5yhlSQKg+2rHkmEwm75XIeAqI3qwOndK6zELK5H6Zxn4NHw==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
|
@ -1031,6 +1105,19 @@ packages:
|
|||
'@emotion/styled':
|
||||
optional: true
|
||||
|
||||
'@mui/styled-engine@6.0.0-alpha.5':
|
||||
resolution: {integrity: sha512-M+nvgL6V9JAnJTy9WJLXXWKfe5YnkIpzheXszsvwi0Yoig/er1DcUwhd7fiKhrgSzEhB9eKXA93fdzFdf1+mcQ==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
peerDependencies:
|
||||
'@emotion/react': ^11.4.1
|
||||
'@emotion/styled': ^11.3.0
|
||||
react: ^17.0.0 || ^18.0.0
|
||||
peerDependenciesMeta:
|
||||
'@emotion/react':
|
||||
optional: true
|
||||
'@emotion/styled':
|
||||
optional: true
|
||||
|
||||
'@mui/system@5.15.15':
|
||||
resolution: {integrity: sha512-aulox6N1dnu5PABsfxVGOZffDVmlxPOVgj56HrUnJE8MCSh8lOvvkd47cebIVQQYAjpwieXQXiDPj5pwM40jTQ==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
|
@ -1047,6 +1134,22 @@ packages:
|
|||
'@types/react':
|
||||
optional: true
|
||||
|
||||
'@mui/system@6.0.0-dev.240424162023-9968b4889d':
|
||||
resolution: {integrity: sha512-Y3yCFUHN1xMK62hJJBqzZb1YQvHNaHc7JUX01eU6QTPojtIbGMF2jCOP/EQw77/byahNbxeLoAIQx10F0IR3Rw==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
peerDependencies:
|
||||
'@emotion/react': ^11.5.0
|
||||
'@emotion/styled': ^11.3.0
|
||||
'@types/react': ^17.0.0 || ^18.0.0
|
||||
react: ^17.0.0 || ^18.0.0
|
||||
peerDependenciesMeta:
|
||||
'@emotion/react':
|
||||
optional: true
|
||||
'@emotion/styled':
|
||||
optional: true
|
||||
'@types/react':
|
||||
optional: true
|
||||
|
||||
'@mui/types@7.2.14':
|
||||
resolution: {integrity: sha512-MZsBZ4q4HfzBsywtXgM1Ksj6HDThtiwmOKUXH1pKYISI9gAVXCNHNpo7TlGoGrBaYWZTdNoirIN7JsQcQUjmQQ==}
|
||||
peerDependencies:
|
||||
|
@ -1065,6 +1168,16 @@ packages:
|
|||
'@types/react':
|
||||
optional: true
|
||||
|
||||
'@mui/utils@6.0.0-alpha.5':
|
||||
resolution: {integrity: sha512-E0MNO8pfIkxsF/Ql+W0J0t4uTgXsTjGHrKr3UhnyFRLqP+JFg5tCvGcSqL0bCDck60Kuc77JCYMr4wbJrhk3LA==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
peerDependencies:
|
||||
'@types/react': ^17.0.0 || ^18.0.0
|
||||
react: ^17.0.0 || ^18.0.0
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
|
||||
'@nodelib/fs.scandir@2.1.5':
|
||||
resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
|
||||
engines: {node: '>= 8'}
|
||||
|
@ -1359,9 +1472,23 @@ packages:
|
|||
peerDependencies:
|
||||
react: ^18.0.0
|
||||
|
||||
'@tanstack/react-table@8.17.3':
|
||||
resolution: {integrity: sha512-5gwg5SvPD3lNAXPuJJz1fOCEZYk9/GeBFH3w/hCgnfyszOIzwkwgp5I7Q4MJtn0WECp84b5STQUDdmvGi8m3nA==}
|
||||
engines: {node: '>=12'}
|
||||
peerDependencies:
|
||||
react: '>=16.8'
|
||||
react-dom: '>=16.8'
|
||||
|
||||
'@tanstack/table-core@8.17.3':
|
||||
resolution: {integrity: sha512-mPBodDGVL+fl6d90wUREepHa/7lhsghg2A3vFpakEhrhtbIlgNAZiMr7ccTgak5qbHqF14Fwy+W1yFWQt+WmYQ==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
'@types/cacheable-request@6.0.3':
|
||||
resolution: {integrity: sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==}
|
||||
|
||||
'@types/emscripten@1.39.12':
|
||||
resolution: {integrity: sha512-AQImDBgudQfMqUBfrjZYilRxoHDzTBp+ejh+g1fY67eSMalwIKtBXofjpyI0JBgNpHGzxeGAR2QDya0wxW9zbA==}
|
||||
|
||||
'@types/estree@0.0.39':
|
||||
resolution: {integrity: sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==}
|
||||
|
||||
|
@ -1407,6 +1534,9 @@ packages:
|
|||
'@types/responselike@1.0.3':
|
||||
resolution: {integrity: sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==}
|
||||
|
||||
'@types/sql.js@1.4.9':
|
||||
resolution: {integrity: sha512-ep8b36RKHlgWPqjNG9ToUrPiwkhwh0AEzy883mO5Xnd+cL6VBH1EvSjBAAuxLUFF2Vn/moE3Me6v9E1Lo+48GQ==}
|
||||
|
||||
'@types/through@0.0.33':
|
||||
resolution: {integrity: sha512-HsJ+z3QuETzP3cswwtzt2vEIiHBk/dCcHGhbmG5X3ecnwFD/lPrMpliGXxSCg03L9AhrdwA4Oz/qfspkDW+xGQ==}
|
||||
|
||||
|
@ -1429,6 +1559,17 @@ packages:
|
|||
peerDependencies:
|
||||
vite: ^4 || ^5
|
||||
|
||||
'@zlepper/rpc@0.0.10':
|
||||
resolution: {integrity: sha512-NAcpr2KGrRIGFkkTB5Eniz3eYhYExY52IJu5V0dOsgBCSg5qcaqjpF71ue4lCMT10fJ/jzhexuFhvFlbZ8dQ5g==}
|
||||
|
||||
'@zlepper/web-worker-rpc@0.0.10':
|
||||
resolution: {integrity: sha512-aqTgsHl9KwWGxE18MhKV8fWgsPorrPS/wapXjwijglPO+WOnN938az0bmxMRw1cgyXqj1dyD65jB8hm2A0RCVg==}
|
||||
peerDependencies:
|
||||
'@zlepper/rpc': ^0.0.10
|
||||
|
||||
absurd-sql@0.0.54:
|
||||
resolution: {integrity: sha512-p+SWTtpRs2t3sXMLxkTyLRZkEzxTv/zG/Bl93wibegLZTGAHGk68SJMWslRWHBGh63ka/ePGTXGHh1117++45Q==}
|
||||
|
||||
acorn@8.11.3:
|
||||
resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==}
|
||||
engines: {node: '>=0.4.0'}
|
||||
|
@ -2278,6 +2419,9 @@ packages:
|
|||
resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
|
||||
engines: {node: '>= 8'}
|
||||
|
||||
microevent.ts@0.2.1:
|
||||
resolution: {integrity: sha512-YaOQr4V70QzTy3sTRkBUa7+clmN4rMdKs9L5wCCxYjo8gknO/FXhcEX5Pot4IWtAdiZqhxN7vskoywQbAOAkDQ==}
|
||||
|
||||
micromatch@4.0.5:
|
||||
resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==}
|
||||
engines: {node: '>=8.6'}
|
||||
|
@ -2618,6 +2762,9 @@ packages:
|
|||
run-parallel@1.2.0:
|
||||
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
|
||||
|
||||
safari-14-idb-fix@1.0.6:
|
||||
resolution: {integrity: sha512-oTEQOdMwRX+uCtWCKT1nx2gAeSdpr8elg/2gcaKUH00SJU2xWESfkx11nmXwTRHy7xfQoj1o4TTQvdmuBosTnA==}
|
||||
|
||||
safe-array-concat@1.1.2:
|
||||
resolution: {integrity: sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==}
|
||||
engines: {node: '>=0.4'}
|
||||
|
@ -3055,6 +3202,9 @@ packages:
|
|||
workbox-window@7.1.0:
|
||||
resolution: {integrity: sha512-ZHeROyqR+AS5UPzholQRDttLFqGMwP0Np8MKWAdyxsDETxq3qOAyXvqessc3GniohG6e0mAqSQyKOHmT8zPF7g==}
|
||||
|
||||
worker-rpc@0.2.0:
|
||||
resolution: {integrity: sha512-S74HnfAdmMlUYmr6+Lx6TmxvffM2vRZSk4RfI/Bxco4xZGw+FREzLRZhFxf8QIzI2/5NKNMn5+Pj69Bp+rweIg==}
|
||||
|
||||
wrappy@1.0.2:
|
||||
resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
|
||||
|
||||
|
@ -3997,6 +4147,10 @@ snapshots:
|
|||
|
||||
'@floating-ui/utils@0.2.2': {}
|
||||
|
||||
'@fontsource/inter@5.0.18': {}
|
||||
|
||||
'@jlongster/sql.js@1.6.7': {}
|
||||
|
||||
'@jridgewell/gen-mapping@0.3.5':
|
||||
dependencies:
|
||||
'@jridgewell/set-array': 1.2.1
|
||||
|
@ -4033,8 +4187,24 @@ snapshots:
|
|||
optionalDependencies:
|
||||
'@types/react': 18.3.2
|
||||
|
||||
'@mui/base@5.0.0-beta.42(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.24.5
|
||||
'@floating-ui/react-dom': 2.0.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@mui/types': 7.2.14(@types/react@18.3.2)
|
||||
'@mui/utils': 6.0.0-alpha.5(@types/react@18.3.2)(react@18.3.1)
|
||||
'@popperjs/core': 2.11.8
|
||||
clsx: 2.1.1
|
||||
prop-types: 15.8.1
|
||||
react: 18.3.1
|
||||
react-dom: 18.3.1(react@18.3.1)
|
||||
optionalDependencies:
|
||||
'@types/react': 18.3.2
|
||||
|
||||
'@mui/core-downloads-tracker@5.15.17': {}
|
||||
|
||||
'@mui/core-downloads-tracker@6.0.0-dev.240424162023-9968b4889d': {}
|
||||
|
||||
'@mui/icons-material@5.15.17(@mui/material@5.15.17(@emotion/react@11.11.4(@types/react@18.3.2)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.2)(react@18.3.1))(@types/react@18.3.2)(react@18.3.1))(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.2)(react@18.3.1)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.24.5
|
||||
|
@ -4043,6 +4213,23 @@ snapshots:
|
|||
optionalDependencies:
|
||||
'@types/react': 18.3.2
|
||||
|
||||
'@mui/joy@5.0.0-beta.36(@emotion/react@11.11.4(@types/react@18.3.2)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.2)(react@18.3.1))(@types/react@18.3.2)(react@18.3.1))(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.24.5
|
||||
'@mui/base': 5.0.0-beta.42(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@mui/core-downloads-tracker': 6.0.0-dev.240424162023-9968b4889d
|
||||
'@mui/system': 6.0.0-dev.240424162023-9968b4889d(@emotion/react@11.11.4(@types/react@18.3.2)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.2)(react@18.3.1))(@types/react@18.3.2)(react@18.3.1))(@types/react@18.3.2)(react@18.3.1)
|
||||
'@mui/types': 7.2.14(@types/react@18.3.2)
|
||||
'@mui/utils': 6.0.0-alpha.5(@types/react@18.3.2)(react@18.3.1)
|
||||
clsx: 2.1.1
|
||||
prop-types: 15.8.1
|
||||
react: 18.3.1
|
||||
react-dom: 18.3.1(react@18.3.1)
|
||||
optionalDependencies:
|
||||
'@emotion/react': 11.11.4(@types/react@18.3.2)(react@18.3.1)
|
||||
'@emotion/styled': 11.11.5(@emotion/react@11.11.4(@types/react@18.3.2)(react@18.3.1))(@types/react@18.3.2)(react@18.3.1)
|
||||
'@types/react': 18.3.2
|
||||
|
||||
'@mui/material@5.15.17(@emotion/react@11.11.4(@types/react@18.3.2)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.2)(react@18.3.1))(@types/react@18.3.2)(react@18.3.1))(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.24.5
|
||||
|
@ -4073,6 +4260,15 @@ snapshots:
|
|||
optionalDependencies:
|
||||
'@types/react': 18.3.2
|
||||
|
||||
'@mui/private-theming@6.0.0-alpha.5(@types/react@18.3.2)(react@18.3.1)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.24.5
|
||||
'@mui/utils': 6.0.0-alpha.5(@types/react@18.3.2)(react@18.3.1)
|
||||
prop-types: 15.8.1
|
||||
react: 18.3.1
|
||||
optionalDependencies:
|
||||
'@types/react': 18.3.2
|
||||
|
||||
'@mui/styled-engine@5.15.14(@emotion/react@11.11.4(@types/react@18.3.2)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.2)(react@18.3.1))(@types/react@18.3.2)(react@18.3.1))(react@18.3.1)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.24.5
|
||||
|
@ -4084,6 +4280,17 @@ snapshots:
|
|||
'@emotion/react': 11.11.4(@types/react@18.3.2)(react@18.3.1)
|
||||
'@emotion/styled': 11.11.5(@emotion/react@11.11.4(@types/react@18.3.2)(react@18.3.1))(@types/react@18.3.2)(react@18.3.1)
|
||||
|
||||
'@mui/styled-engine@6.0.0-alpha.5(@emotion/react@11.11.4(@types/react@18.3.2)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.2)(react@18.3.1))(@types/react@18.3.2)(react@18.3.1))(react@18.3.1)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.24.5
|
||||
'@emotion/cache': 11.11.0
|
||||
csstype: 3.1.3
|
||||
prop-types: 15.8.1
|
||||
react: 18.3.1
|
||||
optionalDependencies:
|
||||
'@emotion/react': 11.11.4(@types/react@18.3.2)(react@18.3.1)
|
||||
'@emotion/styled': 11.11.5(@emotion/react@11.11.4(@types/react@18.3.2)(react@18.3.1))(@types/react@18.3.2)(react@18.3.1)
|
||||
|
||||
'@mui/system@5.15.15(@emotion/react@11.11.4(@types/react@18.3.2)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.2)(react@18.3.1))(@types/react@18.3.2)(react@18.3.1))(@types/react@18.3.2)(react@18.3.1)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.24.5
|
||||
|
@ -4100,6 +4307,22 @@ snapshots:
|
|||
'@emotion/styled': 11.11.5(@emotion/react@11.11.4(@types/react@18.3.2)(react@18.3.1))(@types/react@18.3.2)(react@18.3.1)
|
||||
'@types/react': 18.3.2
|
||||
|
||||
'@mui/system@6.0.0-dev.240424162023-9968b4889d(@emotion/react@11.11.4(@types/react@18.3.2)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.2)(react@18.3.1))(@types/react@18.3.2)(react@18.3.1))(@types/react@18.3.2)(react@18.3.1)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.24.5
|
||||
'@mui/private-theming': 6.0.0-alpha.5(@types/react@18.3.2)(react@18.3.1)
|
||||
'@mui/styled-engine': 6.0.0-alpha.5(@emotion/react@11.11.4(@types/react@18.3.2)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.2)(react@18.3.1))(@types/react@18.3.2)(react@18.3.1))(react@18.3.1)
|
||||
'@mui/types': 7.2.14(@types/react@18.3.2)
|
||||
'@mui/utils': 6.0.0-alpha.5(@types/react@18.3.2)(react@18.3.1)
|
||||
clsx: 2.1.1
|
||||
csstype: 3.1.3
|
||||
prop-types: 15.8.1
|
||||
react: 18.3.1
|
||||
optionalDependencies:
|
||||
'@emotion/react': 11.11.4(@types/react@18.3.2)(react@18.3.1)
|
||||
'@emotion/styled': 11.11.5(@emotion/react@11.11.4(@types/react@18.3.2)(react@18.3.1))(@types/react@18.3.2)(react@18.3.1)
|
||||
'@types/react': 18.3.2
|
||||
|
||||
'@mui/types@7.2.14(@types/react@18.3.2)':
|
||||
optionalDependencies:
|
||||
'@types/react': 18.3.2
|
||||
|
@ -4114,6 +4337,16 @@ snapshots:
|
|||
optionalDependencies:
|
||||
'@types/react': 18.3.2
|
||||
|
||||
'@mui/utils@6.0.0-alpha.5(@types/react@18.3.2)(react@18.3.1)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.24.5
|
||||
'@types/prop-types': 15.7.12
|
||||
prop-types: 15.8.1
|
||||
react: 18.3.1
|
||||
react-is: 18.3.1
|
||||
optionalDependencies:
|
||||
'@types/react': 18.3.2
|
||||
|
||||
'@nodelib/fs.scandir@2.1.5':
|
||||
dependencies:
|
||||
'@nodelib/fs.stat': 2.0.5
|
||||
|
@ -4360,6 +4593,14 @@ snapshots:
|
|||
'@tanstack/query-core': 5.36.1
|
||||
react: 18.3.1
|
||||
|
||||
'@tanstack/react-table@8.17.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||
dependencies:
|
||||
'@tanstack/table-core': 8.17.3
|
||||
react: 18.3.1
|
||||
react-dom: 18.3.1(react@18.3.1)
|
||||
|
||||
'@tanstack/table-core@8.17.3': {}
|
||||
|
||||
'@types/cacheable-request@6.0.3':
|
||||
dependencies:
|
||||
'@types/http-cache-semantics': 4.0.4
|
||||
|
@ -4367,6 +4608,8 @@ snapshots:
|
|||
'@types/node': 20.12.12
|
||||
'@types/responselike': 1.0.3
|
||||
|
||||
'@types/emscripten@1.39.12': {}
|
||||
|
||||
'@types/estree@0.0.39': {}
|
||||
|
||||
'@types/estree@1.0.5': {}
|
||||
|
@ -4413,6 +4656,11 @@ snapshots:
|
|||
dependencies:
|
||||
'@types/node': 20.12.12
|
||||
|
||||
'@types/sql.js@1.4.9':
|
||||
dependencies:
|
||||
'@types/emscripten': 1.39.12
|
||||
'@types/node': 20.12.12
|
||||
|
||||
'@types/through@0.0.33':
|
||||
dependencies:
|
||||
'@types/node': 20.12.12
|
||||
|
@ -4439,6 +4687,16 @@ snapshots:
|
|||
transitivePeerDependencies:
|
||||
- '@swc/helpers'
|
||||
|
||||
'@zlepper/rpc@0.0.10': {}
|
||||
|
||||
'@zlepper/web-worker-rpc@0.0.10(@zlepper/rpc@0.0.10)':
|
||||
dependencies:
|
||||
'@zlepper/rpc': 0.0.10
|
||||
|
||||
absurd-sql@0.0.54:
|
||||
dependencies:
|
||||
safari-14-idb-fix: 1.0.6
|
||||
|
||||
acorn@8.11.3: {}
|
||||
|
||||
agent-base@6.0.2:
|
||||
|
@ -5360,6 +5618,8 @@ snapshots:
|
|||
|
||||
merge2@1.4.1: {}
|
||||
|
||||
microevent.ts@0.2.1: {}
|
||||
|
||||
micromatch@4.0.5:
|
||||
dependencies:
|
||||
braces: 3.0.2
|
||||
|
@ -5716,6 +5976,8 @@ snapshots:
|
|||
dependencies:
|
||||
queue-microtask: 1.2.3
|
||||
|
||||
safari-14-idb-fix@1.0.6: {}
|
||||
|
||||
safe-array-concat@1.1.2:
|
||||
dependencies:
|
||||
call-bind: 1.0.7
|
||||
|
@ -6279,6 +6541,10 @@ snapshots:
|
|||
'@types/trusted-types': 2.0.7
|
||||
workbox-core: 7.1.0
|
||||
|
||||
worker-rpc@0.2.0:
|
||||
dependencies:
|
||||
microevent.ts: 0.2.1
|
||||
|
||||
wrappy@1.0.2: {}
|
||||
|
||||
yallist@3.1.1: {}
|
||||
|
|
0
public/bannerImages/.gitkeep
Normal file
0
public/bannerImages/.gitkeep
Normal file
|
@ -27,9 +27,22 @@ async function* mixToSongs(
|
|||
|
||||
async function* processSong(gen: AsyncGenerator<[string, string]>) {
|
||||
for await (const [mix, song] of gen) {
|
||||
const totalPath = join(stepchartsDir, mix, song);
|
||||
const meta = await stat(totalPath);
|
||||
if (!meta.isDirectory()) continue;
|
||||
|
||||
try {
|
||||
const parsed = await parseSimfile(stepchartsDir, mix, song);
|
||||
yield parsed;
|
||||
for (const [name, chart] of Object.entries(parsed.charts)) {
|
||||
yield {
|
||||
difficulty: name,
|
||||
artist: parsed.artist,
|
||||
title: parsed.title.titleName,
|
||||
titleRomanized: parsed.title.translitTitleName,
|
||||
bannerFilename: parsed.bannerFilename,
|
||||
};
|
||||
}
|
||||
// yield parsed;
|
||||
} catch (e) {
|
||||
console.error("failed on", mix, song, ":", e.message);
|
||||
}
|
||||
|
@ -45,3 +58,5 @@ for await (const songObj of outIter) {
|
|||
writer.write(JSON.stringify(songObj));
|
||||
writer.write("\n");
|
||||
}
|
||||
|
||||
console.log("Done.");
|
||||
|
|
35
src/App.tsx
35
src/App.tsx
|
@ -19,7 +19,8 @@ import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
|||
import { CHART_STORE_CREATION_EVENT, dbStatusAtom } from "./globals";
|
||||
import NavBar from "./components/NavBar";
|
||||
import WarningBars from "./components/WarningBars";
|
||||
import { useAtom, useSetAtom } from "jotai";
|
||||
import { useAtom, useAtomValue, useSetAtom } from "jotai";
|
||||
import { dbClient, getDbClient } from "../lib/db/client";
|
||||
|
||||
const queryClient = new QueryClient();
|
||||
|
||||
|
@ -76,23 +77,23 @@ export function AppWrapper() {
|
|||
}
|
||||
|
||||
export default function App() {
|
||||
const setDbStatus = useSetAtom(dbStatusAtom);
|
||||
|
||||
useEffect(() => {
|
||||
const worker = new ImportChartWorker();
|
||||
worker.postMessage("start");
|
||||
worker.onmessage = (evt) => {
|
||||
console.log("got event from web worker", evt);
|
||||
switch (evt.kind) {
|
||||
case "dbIsBlocked": {
|
||||
setDbStatus((db) => ({ ...db, status: "upgrading" }));
|
||||
}
|
||||
}
|
||||
if (evt.kind === "chartStoreCreate") {
|
||||
document.dispatchEvent(CHART_STORE_CREATION_EVENT);
|
||||
}
|
||||
};
|
||||
});
|
||||
(async () => {
|
||||
// await getDbClient();
|
||||
console.log("WTF?", dbClient);
|
||||
|
||||
console.log("a");
|
||||
await dbClient.run(
|
||||
"CREATE TABLE IF NOT EXISTS rows (lol INTEGER PRIMARY KEY AUTOINCREMENT , what STRING);",
|
||||
);
|
||||
console.log("b");
|
||||
await dbClient.run("INSERT INTO rows (what) VALUES ('helloge')");
|
||||
console.log("c");
|
||||
const result = await dbClient.exec("SELECT * FROM rows");
|
||||
console.log("d");
|
||||
console.log("RESULT", result);
|
||||
})();
|
||||
}, [dbClient]);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
|
81
src/components/ChartsTable.tsx
Normal file
81
src/components/ChartsTable.tsx
Normal file
|
@ -0,0 +1,81 @@
|
|||
import {
|
||||
flexRender,
|
||||
getCoreRowModel,
|
||||
useReactTable,
|
||||
} from "@tanstack/react-table";
|
||||
|
||||
export default function ChartsTable({ data }) {
|
||||
console.log(data);
|
||||
const table = useReactTable({
|
||||
data,
|
||||
columns: [
|
||||
{
|
||||
accessorKey: "bannerFilename",
|
||||
cell: ({ cell, row }) => {
|
||||
const value = cell.getValue();
|
||||
return (
|
||||
<div>
|
||||
<img
|
||||
style={{ width: "100px" }}
|
||||
src={`${import.meta.env.BASE_URL}bannerImages/${value}`}
|
||||
alt={`Banner image`}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
},
|
||||
{ accessorKey: "difficulty" },
|
||||
{ accessorKey: "artist" },
|
||||
{ accessorKey: "title" },
|
||||
],
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
});
|
||||
|
||||
return (
|
||||
<table>
|
||||
<thead>
|
||||
{table.getHeaderGroups().map((headerGroup) => (
|
||||
<tr key={headerGroup.id}>
|
||||
{headerGroup.headers.map((header) => (
|
||||
<th key={header.id}>
|
||||
{header.isPlaceholder
|
||||
? null
|
||||
: flexRender(
|
||||
header.column.columnDef.header,
|
||||
header.getContext(),
|
||||
)}
|
||||
</th>
|
||||
))}
|
||||
</tr>
|
||||
))}
|
||||
</thead>
|
||||
<tbody>
|
||||
{table.getRowModel().rows.map((row) => (
|
||||
<tr key={row.id}>
|
||||
{row.getVisibleCells().map((cell) => (
|
||||
<td key={cell.id}>
|
||||
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
||||
</td>
|
||||
))}
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
<tfoot>
|
||||
{table.getFooterGroups().map((footerGroup) => (
|
||||
<tr key={footerGroup.id}>
|
||||
{footerGroup.headers.map((header) => (
|
||||
<th key={header.id}>
|
||||
{header.isPlaceholder
|
||||
? null
|
||||
: flexRender(
|
||||
header.column.columnDef.footer,
|
||||
header.getContext(),
|
||||
)}
|
||||
</th>
|
||||
))}
|
||||
</tr>
|
||||
))}
|
||||
</tfoot>
|
||||
</table>
|
||||
);
|
||||
}
|
|
@ -1,10 +1,12 @@
|
|||
.bar {
|
||||
display: flex;
|
||||
min-width: 0;
|
||||
border-top: 1px solid lightgray;
|
||||
}
|
||||
|
||||
.searchBar {
|
||||
flex-grow: 1;
|
||||
min-width: 0;
|
||||
|
||||
display: flex;
|
||||
|
||||
|
@ -14,3 +16,7 @@
|
|||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
.searchEntry {
|
||||
font-size: 20pt;
|
||||
}
|
|
@ -7,6 +7,7 @@ export default function NavBar() {
|
|||
<nav className={styles.bar}>
|
||||
<div className={styles.searchBar}>
|
||||
<input
|
||||
className={styles.searchEntry}
|
||||
placeholder="Search charts..."
|
||||
// biome-ignore lint/a11y/noAutofocus: this is the only one in the page
|
||||
autoFocus
|
||||
|
|
|
@ -4,7 +4,7 @@ import WarningIcon from "@mui/icons-material/Warning";
|
|||
import Chip from "./Chip";
|
||||
import { dbStatusAtom } from "../globals";
|
||||
import { useAtom, useAtomValue } from "jotai";
|
||||
import { ReactNode } from "react";
|
||||
import type { ReactNode } from "react";
|
||||
|
||||
export default function WarningBars() {
|
||||
return (
|
||||
|
@ -42,7 +42,7 @@ function StatusBar() {
|
|||
const statuses = [];
|
||||
|
||||
statuses.push(
|
||||
<Chip>
|
||||
<Chip key="lol">
|
||||
db: <DbStatusChip />
|
||||
</Chip>,
|
||||
);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import App from "./App";
|
||||
import { createRoot } from "react-dom/client";
|
||||
import { StrictMode } from "react";
|
||||
import "@fontsource/inter";
|
||||
import "./global.scss";
|
||||
|
||||
// biome-ignore lint/style/noNonNullAssertion: don't care
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import { APP_DATA_VERSION, CHART_STORE_CREATION_EVENT } from "../globals";
|
||||
import { useReactTable } from "@tanstack/react-table";
|
||||
import ChartsTable from "../components/ChartsTable";
|
||||
|
||||
function openDb(): Promise<IDBOpenDBRequest> {
|
||||
return new Promise((resolve) => {
|
||||
|
@ -52,10 +54,7 @@ export default function Charts() {
|
|||
if (fetchChartsQuery.isSuccess) {
|
||||
inner = (
|
||||
<div>
|
||||
{fetchChartsQuery.data.map((chart) => (
|
||||
// <div>{JSON.stringify(Object.keys(chart))}</div>
|
||||
<div>{JSON.stringify(chart.title)}</div>
|
||||
))}
|
||||
<ChartsTable data={fetchChartsQuery.data} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ export default defineConfig(({ mode }) => ({
|
|||
manifest: {
|
||||
icons: [{ src: "pwa-192x192.png", purpose: "any", sizes: "192x192" }],
|
||||
},
|
||||
includeAssets: ["public/bannerImages/*"],
|
||||
}),
|
||||
|
||||
basicSsl({
|
||||
|
|
Loading…
Reference in a new issue