diff --git a/README.md b/README.md index b1e46c8..5c12354 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ To change size, set root font size (default 10px) ``` To right align ```css -body { flex-direction: row-reverse; } .row { justify-content: flex-end; } +body > .row { flex-direction: row-reverse; } .row { justify-content: flex-end; } ``` To change fade duration (default 300ms) ```css diff --git a/index.html b/index.html index 63c1c6d..51bc108 100644 --- a/index.html +++ b/index.html @@ -6,24 +6,24 @@ -
-
-
- Title - Subtitle -
- -
- Artist - Mapper -
- -
- Easy - - Diff Label - - 25f +
+ +
+
+ Title + Subtitle +
+
+ Artist + Mapper +
+
+ Easy + + Diff Label + + 25f +
diff --git a/main.js b/main.js index 4476e30..64af5c8 100644 --- a/main.js +++ b/main.js @@ -1,15 +1,46 @@ "use strict"; -// https://github.com/hardcpp/BeatSaberPlus/wiki/%5BEN%5D-Song-Overlay -const bspUrl = "ws://localhost:2947/socket"; +// Data providers + +const beatSaberPlus = { + // https://github.com/hardcpp/BeatSaberPlus/wiki/%5BEN%5D-Song-Overlay + url: "ws://localhost:2947/socket", + + /** @param {MessageEvent} e */ + onMessage: function(e) { + /** @type {BeatSaberPlusEvent} */ + const data = JSON.parse(e.data); + switch (data._type) { + case "event": + switch (data._event) { + case "gameState": + document.body.dataset.gameState = data.gameStateChanged; + break; + + case "mapInfo": + updateMapInfo(data.mapInfoChanged); + break; + } + break; + + default: + console.log("message", e.data); + break; + } + }, +}; + +// WebSocket connection + +const provider = beatSaberPlus; const retryMs = 10000; let retries = 0; function connect() { - console.log(`Connecting to ${bspUrl} (attempt ${retries++})`); - const ws = new WebSocket(bspUrl); + console.log(`Connecting to ${provider.url} (attempt ${retries++})`); + const ws = new WebSocket(provider.url); ws.onopen = onOpen; - ws.onmessage = onMessage; + ws.onmessage = provider.onMessage; ws.onclose = onClose; } @@ -18,42 +49,21 @@ function onOpen() { retries = 0; } -/** @param {MessageEvent} e */ -function onMessage(e) { - /** @type {BeatSaberPlusEvent} */ - const data = JSON.parse(e.data); - switch (data._type) { - case "event": - switch (data._event) { - case "gameState": - document.body.dataset.gameState = data.gameStateChanged; - break; - - case "mapInfo": - updateMapInfo(data.mapInfoChanged); - break; - } - break; - - default: - console.log("message", e.data); - break; - } -} - /** @param {CloseEvent} e */ function onClose(e) { console.log(`Connection closed. code: ${e.code}, reason: ${e.reason}, clean: ${e.wasClean}`); setTimeout(connect, retryMs); } -const cover = document.getElementById("cover"); +// Map info + +const cover = document.getElementById("coverImg"); const title = document.getElementById("title"); const subTitle = document.getElementById("subTitle"); const artist = document.getElementById("artist"); const mapper = document.getElementById("mapper"); const difficulty = document.getElementById("difficulty"); -const characteristicIcon = document.getElementById("characteristicIcon"); +const characteristic = document.getElementById("characteristicImg"); const difficultyLabel = document.getElementById("difficultyLabel"); const type = document.getElementById("type"); const bsrKey = document.getElementById("bsrKey"); @@ -62,13 +72,13 @@ const bsrKey = document.getElementById("bsrKey"); async function updateMapInfo(data) { const custom = data.level_id.startsWith("custom_level_"); const wip = custom && data.level_id.endsWith("WIP"); - cover.style.backgroundImage = data.coverRaw ? `url("data:image/jpeg;base64,${data.coverRaw}")` : ""; + cover.src = data.coverRaw ? `data:image/jpeg;base64,${data.coverRaw}` : "images/unknown.svg"; title.textContent = data.name || ""; subTitle.textContent = data.sub_name || ""; artist.textContent = data.artist || ""; mapper.textContent = data.mapper || ""; difficulty.textContent = data.difficulty.replace("Plus", " +") || ""; - characteristicIcon.src = `images/characteristic/${data.characteristic}.svg`; + characteristic.src = `images/characteristic/${data.characteristic}.svg`; difficultyLabel.textContent = ""; // BS+ does not provide label type.textContent = !custom ? "OST" : wip ? "WIP" : ""; bsrKey.textContent = data.BSRKey || "???"; // Always empty? @@ -95,6 +105,4 @@ async function updateMapInfo(data) { connect(); -document.documentElement.onclick = function() { - document.body.dataset.gameState = document.body.dataset.gameState === "Playing" ? "Menu" : "Playing"; -}; +document.documentElement.onclick = () => document.body.classList.toggle("preview"); diff --git a/style.css b/style.css index e4f6130..eadc0c7 100644 --- a/style.css +++ b/style.css @@ -10,12 +10,13 @@ html { } body { - display: flex; margin: 0; padding: 1.4rem 1.6rem; - gap: 1.6rem; overflow: hidden; font-family: "Montserrat", sans-serif; + font-size: 1.5rem; + font-weight: 600; + line-height: 1.2; white-space: nowrap; background: rgba(0, 0, 0, 0); color: white; @@ -24,47 +25,45 @@ body { } body.loading, -body:not([data-game-state="Playing"]) { +body:not([data-game-state="Playing"], .preview) { opacity: 0; } -#cover { - width: 6.8rem; - height: 6.8rem; - border-radius: 0.6rem; - background-image: url("images/unknown.svg"); - background-repeat: no-repeat; - background-size: contain; - flex-shrink: 0; +.row { + display: flex; + gap: 1.6rem; } -#songData { +.column { display: flex; flex-direction: column; flex-grow: 1; - justify-content: space-between; - margin: -0.4rem 0 -0.2rem; + gap: 0.35rem; + margin-top: -0.4rem; overflow: hidden; - line-height: 1.2; - font-size: 1.5rem; - font-weight: 600; } -#songData * { +.column * { overflow: hidden; text-overflow: ellipsis; } -#songData .row { - display: flex; +.column .row { align-items: baseline; - column-gap: 0.6em; + gap: 0.9rem; } -#songData span:empty { +.column span:empty { display: none; } +#coverImg { + width: 6.8rem; + height: 6.8rem; + border-radius: 0.6rem; + flex-shrink: 0; +} + #title { font-size: 2.4rem; font-weight: 700; @@ -91,7 +90,7 @@ body:not([data-game-state="Playing"]) { flex-shrink: 99999; } -#characteristicIcon { +#characteristicImg { width: 1.1em; height: 1.1em; flex-shrink: 0; diff --git a/types.d.ts b/types.d.ts index 8e17f1e..ecf57d4 100644 --- a/types.d.ts +++ b/types.d.ts @@ -65,6 +65,7 @@ type MapInfoChanged = MapInfoChangedEvent["mapInfoChanged"]; interface Document { // Assume non-null - getElementById(elementId: `${string}Icon`): HTMLImageElement; + getElementById(elementId: `${string}Img`): HTMLImageElement; + getElementById(elementId: `${string}Input`): HTMLInputElement; getElementById(elementId: string): HTMLElement; }