From 8a019c0817ca0020e1a74a682438a823dfbf4c57 Mon Sep 17 00:00:00 2001 From: Stein Ivar Berghei Date: Thu, 26 Oct 2023 22:51:54 +0200 Subject: [PATCH] Time for React! --- src/app/events.tsx | 23 +++++++++++++ src/app/playlist.tsx | 77 ++++++++++++++++++++++++++++++++++++++++++++ src/app/root.tsx | 23 +++++++++++++ src/app/ws.tsx | 9 ++++++ src/package.json | 7 +++- src/script.js | 6 ++-- src/yarn.lock | 65 +++++++++++++++++++++++++++++++++++++ 7 files changed, 206 insertions(+), 4 deletions(-) create mode 100644 src/app/events.tsx create mode 100644 src/app/playlist.tsx create mode 100644 src/app/root.tsx create mode 100644 src/app/ws.tsx diff --git a/src/app/events.tsx b/src/app/events.tsx new file mode 100644 index 0000000..456ea09 --- /dev/null +++ b/src/app/events.tsx @@ -0,0 +1,23 @@ +function on(eventType: any, listener: { (event: any): void; (this: Document, ev: any): any; }) { + document.addEventListener(eventType, listener); + } + + function off(eventType: any, listener: { (event: any): void; (this: Document, ev: any): any; }) { + document.removeEventListener(eventType, listener); + } + + function once(eventType: any, listener: (arg0: any) => void) { + on(eventType, handleEventOnce); + + function handleEventOnce(event) { + listener(event); + off(eventType, handleEventOnce); + } + } + +function trigger(eventType: string, data: any) { + const event = new CustomEvent(eventType, { detail: data }); + document.dispatchEvent(event); +} + +export { on, once, off, trigger }; \ No newline at end of file diff --git a/src/app/playlist.tsx b/src/app/playlist.tsx new file mode 100644 index 0000000..e59bc80 --- /dev/null +++ b/src/app/playlist.tsx @@ -0,0 +1,77 @@ +import React, { useEffect, useState, useCallback } from "react"; +import CSS from "csstype"; +import { on } from "./events"; +import ws from "./ws"; + +export default function Playlists() { + interface Playlist { + Id: string; + Title: string; + } + + const [playlists, setPlaylists] = useState([]); + const [active, setActive] = useState(""); + + const activeStyle: CSS.Properties = { + backgroundColor: "burlywood", + }; + + const fetchPlaylists = () => { + fetch("/playlists") + .then((response) => { + return response.json(); + }) + .then((data) => { + setPlaylists(data); + }); + }; + + useEffect(() => { + fetchPlaylists(); + }, []); + + const Play = (e: any) => { + console.log(e.target.dataset); + ws.send( + JSON.stringify({ + event: "load_playlist", + payload: e.target.dataset.id, + }) + ); + }; + + const Stop = () => { + ws.send( + JSON.stringify({ + event: "stop", + }) + ); + }; + + on("dnd:song_info", (e: any) => { + setActive(e.detail.playlist); + }); + + return ( +
+
+ {playlists.map((playlist) => { + return ( +
+ {playlist.Title} +
+ ); + })} +
+ Stop +
+
+
+ ); +} diff --git a/src/app/root.tsx b/src/app/root.tsx new file mode 100644 index 0000000..1feb12f --- /dev/null +++ b/src/app/root.tsx @@ -0,0 +1,23 @@ +import React, { createContext } from "react"; +import { createRoot } from "react-dom/client"; +import { trigger, on } from "./events"; +import Playlists from "./playlist"; +import ws from "./ws"; + +function Content() { + ws.onmessage = (e) => { + const data = JSON.parse(e.data); + trigger("dnd:" + data.event, data.payload); + }; + + return ( + <> +

Playlists

+ + + ); +} + +const domNode = document.getElementById("content"); +const root = createRoot(domNode!); +root.render(); diff --git a/src/app/ws.tsx b/src/app/ws.tsx new file mode 100644 index 0000000..06b9e8e --- /dev/null +++ b/src/app/ws.tsx @@ -0,0 +1,9 @@ +import ReconnectingWebSocket from "reconnecting-websocket"; + +const ws = new ReconnectingWebSocket( + (window.location.protocol === "https:" ? "wss://" : "ws://") + + window.location.host + + "/ws" +); + +export default ws; diff --git a/src/package.json b/src/package.json index 5e65b04..f555b9e 100644 --- a/src/package.json +++ b/src/package.json @@ -1,9 +1,14 @@ { "scripts": { - "build": "esbuild script.js --bundle --outdir=/public/" + "build": "esbuild script.js --bundle --outdir=/public/", + "build_test": "esbuild app/*.tsx --bundle --outfile=../public_test/script.js" }, "dependencies": { + "@types/react": "^18.2.33", + "@types/react-dom": "^18.2.14", "esbuild": "^0.15.14", + "react": "^18.2.0", + "react-dom": "^18.2.0", "reconnecting-websocket": "^4.4.0", "sortablejs": "^1.15.0" } diff --git a/src/script.js b/src/script.js index 318c40b..c5ac09f 100644 --- a/src/script.js +++ b/src/script.js @@ -147,19 +147,19 @@ window.onload = function () { avol.value = data.payload.ambiance avol.nextElementSibling.value = data.payload.ambiance break - case "ambiance_download_start": + case "ambiance_encode_start": var progress = document.querySelector("#progressambiance progress") progress.style.display = "initial" progress.style.width = "100%" progress.value = 0 break - case "ambiance_download_progress": + case "ambiance_encode_progress": var progress = document.querySelector("#progressambiance progress") progress.style.display = "initial" progress.value = data.payload.percent console.log(data) break - case "ambiance_download_complete": + case "ambiance_encode_complete": var progress = document.querySelector("#progressambiance progress") progress.style.display = "initial" progress.value = 100 diff --git a/src/yarn.lock b/src/yarn.lock index edb50a8..c5c6383 100644 --- a/src/yarn.lock +++ b/src/yarn.lock @@ -12,6 +12,37 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.15.14.tgz#1221684955c44385f8af34f7240088b7dc08d19d" integrity sha512-eQi9rosGNVQFJyJWV0HCA5WZae/qWIQME7s8/j8DMvnylfBv62Pbu+zJ2eUDqNf2O4u3WB+OEXyfkpBoe194sg== +"@types/prop-types@*": + version "15.7.9" + resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.9.tgz#b6f785caa7ea1fe4414d9df42ee0ab67f23d8a6d" + integrity sha512-n1yyPsugYNSmHgxDFjicaI2+gCNjsBck8UX9kuofAKlc0h1bL+20oSF72KeNaW2DUlesbEVCFgyV2dPGTiY42g== + +"@types/react-dom@^18.2.14": + version "18.2.14" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.2.14.tgz#c01ba40e5bb57fc1dc41569bb3ccdb19eab1c539" + integrity sha512-V835xgdSVmyQmI1KLV2BEIUgqEuinxp9O4G6g3FqO/SqLac049E53aysv0oEFD2kHfejeKU+ZqL2bcFWj9gLAQ== + dependencies: + "@types/react" "*" + +"@types/react@*", "@types/react@^18.2.33": + version "18.2.33" + resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.33.tgz#055356243dc4350a9ee6c6a2c07c5cae12e38877" + integrity sha512-v+I7S+hu3PIBoVkKGpSYYpiBT1ijqEzWpzQD62/jm4K74hPpSP7FF9BnKG6+fg2+62weJYkkBWDJlZt5JO/9hg== + dependencies: + "@types/prop-types" "*" + "@types/scheduler" "*" + csstype "^3.0.2" + +"@types/scheduler@*": + version "0.16.5" + resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.5.tgz#4751153abbf8d6199babb345a52e1eb4167d64af" + integrity sha512-s/FPdYRmZR8SjLWGMCuax7r3qCWQw9QKHzXVukAuuIJkXkDRwp+Pu5LMIVFi0Fxbav35WURicYr8u1QsoybnQw== + +csstype@^3.0.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.2.tgz#1d4bf9d572f11c14031f0436e1c10bc1f571f50b" + integrity sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ== + esbuild-android-64@0.15.14: version "0.15.14" resolved "https://registry.yarnpkg.com/esbuild-android-64/-/esbuild-android-64-0.15.14.tgz#114e55b0d58fb7b45d7fa3d93516bd13fc8869cc" @@ -140,11 +171,45 @@ esbuild@^0.15.14: esbuild-windows-64 "0.15.14" esbuild-windows-arm64 "0.15.14" +"js-tokens@^3.0.0 || ^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +loose-envify@^1.1.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + +react-dom@^18.2.0: + version "18.2.0" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d" + integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g== + dependencies: + loose-envify "^1.1.0" + scheduler "^0.23.0" + +react@^18.2.0: + version "18.2.0" + resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5" + integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ== + dependencies: + loose-envify "^1.1.0" + reconnecting-websocket@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/reconnecting-websocket/-/reconnecting-websocket-4.4.0.tgz#3b0e5b96ef119e78a03135865b8bb0af1b948783" integrity sha512-D2E33ceRPga0NvTDhJmphEgJ7FUYF0v4lr1ki0csq06OdlxKfugGzN0dSkxM/NfqCxYELK4KcaTOUOjTV6Dcng== +scheduler@^0.23.0: + version "0.23.0" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe" + integrity sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw== + dependencies: + loose-envify "^1.1.0" + sortablejs@^1.15.0: version "1.15.0" resolved "https://registry.yarnpkg.com/sortablejs/-/sortablejs-1.15.0.tgz#53230b8aa3502bb77a29e2005808ffdb4a5f7e2a"