Time for React!
parent
605bd7f29e
commit
8a019c0817
|
@ -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 };
|
|
@ -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<Playlist[]>([]);
|
||||||
|
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 (
|
||||||
|
<section>
|
||||||
|
<div id="items" className="item-container">
|
||||||
|
{playlists.map((playlist) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
key={playlist.Id}
|
||||||
|
onClick={Play}
|
||||||
|
className="item"
|
||||||
|
data-id={playlist.Id}
|
||||||
|
style={playlist.Id == active ? activeStyle : {}}
|
||||||
|
>
|
||||||
|
{playlist.Title}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
<div className="item locked stop" onClick={Stop} data-id="reset">
|
||||||
|
Stop
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
|
@ -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 (
|
||||||
|
<>
|
||||||
|
<h2 className="bot">Playlists</h2>
|
||||||
|
<Playlists />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const domNode = document.getElementById("content");
|
||||||
|
const root = createRoot(domNode!);
|
||||||
|
root.render(<Content />);
|
|
@ -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;
|
|
@ -1,9 +1,14 @@
|
||||||
{
|
{
|
||||||
"scripts": {
|
"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": {
|
"dependencies": {
|
||||||
|
"@types/react": "^18.2.33",
|
||||||
|
"@types/react-dom": "^18.2.14",
|
||||||
"esbuild": "^0.15.14",
|
"esbuild": "^0.15.14",
|
||||||
|
"react": "^18.2.0",
|
||||||
|
"react-dom": "^18.2.0",
|
||||||
"reconnecting-websocket": "^4.4.0",
|
"reconnecting-websocket": "^4.4.0",
|
||||||
"sortablejs": "^1.15.0"
|
"sortablejs": "^1.15.0"
|
||||||
}
|
}
|
||||||
|
|
|
@ -147,19 +147,19 @@ window.onload = function () {
|
||||||
avol.value = data.payload.ambiance
|
avol.value = data.payload.ambiance
|
||||||
avol.nextElementSibling.value = data.payload.ambiance
|
avol.nextElementSibling.value = data.payload.ambiance
|
||||||
break
|
break
|
||||||
case "ambiance_download_start":
|
case "ambiance_encode_start":
|
||||||
var progress = document.querySelector("#progressambiance progress")
|
var progress = document.querySelector("#progressambiance progress")
|
||||||
progress.style.display = "initial"
|
progress.style.display = "initial"
|
||||||
progress.style.width = "100%"
|
progress.style.width = "100%"
|
||||||
progress.value = 0
|
progress.value = 0
|
||||||
break
|
break
|
||||||
case "ambiance_download_progress":
|
case "ambiance_encode_progress":
|
||||||
var progress = document.querySelector("#progressambiance progress")
|
var progress = document.querySelector("#progressambiance progress")
|
||||||
progress.style.display = "initial"
|
progress.style.display = "initial"
|
||||||
progress.value = data.payload.percent
|
progress.value = data.payload.percent
|
||||||
console.log(data)
|
console.log(data)
|
||||||
break
|
break
|
||||||
case "ambiance_download_complete":
|
case "ambiance_encode_complete":
|
||||||
var progress = document.querySelector("#progressambiance progress")
|
var progress = document.querySelector("#progressambiance progress")
|
||||||
progress.style.display = "initial"
|
progress.style.display = "initial"
|
||||||
progress.value = 100
|
progress.value = 100
|
||||||
|
|
|
@ -12,6 +12,37 @@
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.15.14.tgz#1221684955c44385f8af34f7240088b7dc08d19d"
|
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.15.14.tgz#1221684955c44385f8af34f7240088b7dc08d19d"
|
||||||
integrity sha512-eQi9rosGNVQFJyJWV0HCA5WZae/qWIQME7s8/j8DMvnylfBv62Pbu+zJ2eUDqNf2O4u3WB+OEXyfkpBoe194sg==
|
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:
|
esbuild-android-64@0.15.14:
|
||||||
version "0.15.14"
|
version "0.15.14"
|
||||||
resolved "https://registry.yarnpkg.com/esbuild-android-64/-/esbuild-android-64-0.15.14.tgz#114e55b0d58fb7b45d7fa3d93516bd13fc8869cc"
|
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-64 "0.15.14"
|
||||||
esbuild-windows-arm64 "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:
|
reconnecting-websocket@^4.4.0:
|
||||||
version "4.4.0"
|
version "4.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/reconnecting-websocket/-/reconnecting-websocket-4.4.0.tgz#3b0e5b96ef119e78a03135865b8bb0af1b948783"
|
resolved "https://registry.yarnpkg.com/reconnecting-websocket/-/reconnecting-websocket-4.4.0.tgz#3b0e5b96ef119e78a03135865b8bb0af1b948783"
|
||||||
integrity sha512-D2E33ceRPga0NvTDhJmphEgJ7FUYF0v4lr1ki0csq06OdlxKfugGzN0dSkxM/NfqCxYELK4KcaTOUOjTV6Dcng==
|
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:
|
sortablejs@^1.15.0:
|
||||||
version "1.15.0"
|
version "1.15.0"
|
||||||
resolved "https://registry.yarnpkg.com/sortablejs/-/sortablejs-1.15.0.tgz#53230b8aa3502bb77a29e2005808ffdb4a5f7e2a"
|
resolved "https://registry.yarnpkg.com/sortablejs/-/sortablejs-1.15.0.tgz#53230b8aa3502bb77a29e2005808ffdb4a5f7e2a"
|
||||||
|
|
Loading…
Reference in New Issue