diff --git a/package-lock.json b/package-lock.json index 2714d2f..86b1fb1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,16 +1,17 @@ { - "name": "syng-weg", + "name": "syng-web", "version": "2.0.0", "lockfileVersion": 2, "requires": true, "packages": { "": { - "name": "syng-weg", + "name": "syng-web", "version": "2.0.0", "dependencies": { "@fortawesome/fontawesome-free": "^6.2.1", "@fortawesome/fontawesome-svg-core": "^6.2.1", "@fortawesome/free-brands-svg-icons": "^6.2.1", + "@fortawesome/free-regular-svg-icons": "^6.2.1", "@fortawesome/free-solid-svg-icons": "^6.2.1", "@fortawesome/vue-fontawesome": "^3.0.2", "foundation-sites": "^6.7.5", @@ -108,6 +109,29 @@ "node": ">=6" } }, + "node_modules/@fortawesome/free-regular-svg-icons": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.5.2.tgz", + "integrity": "sha512-iabw/f5f8Uy2nTRtJ13XZTS1O5+t+anvlamJ3zJGLEVE2pKsAWhPv2lq01uQlfgCX7VaveT3EVs515cCN9jRbw==", + "hasInstallScript": true, + "license": "(CC-BY-4.0 AND MIT)", + "dependencies": { + "@fortawesome/fontawesome-common-types": "6.5.2" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/free-regular-svg-icons/node_modules/@fortawesome/fontawesome-common-types": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.5.2.tgz", + "integrity": "sha512-gBxPg3aVO6J0kpfHNILc+NMhXnqHumFxOmjYCFfOiLZfwhnnfhtsdA2hfJlDnj+8PjAs6kKQPenOTKj3Rf7zHw==", + "hasInstallScript": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/@fortawesome/free-solid-svg-icons": { "version": "6.4.0", "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.4.0.tgz", @@ -1041,6 +1065,21 @@ "@fortawesome/fontawesome-common-types": "6.4.0" } }, + "@fortawesome/free-regular-svg-icons": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.5.2.tgz", + "integrity": "sha512-iabw/f5f8Uy2nTRtJ13XZTS1O5+t+anvlamJ3zJGLEVE2pKsAWhPv2lq01uQlfgCX7VaveT3EVs515cCN9jRbw==", + "requires": { + "@fortawesome/fontawesome-common-types": "6.5.2" + }, + "dependencies": { + "@fortawesome/fontawesome-common-types": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.5.2.tgz", + "integrity": "sha512-gBxPg3aVO6J0kpfHNILc+NMhXnqHumFxOmjYCFfOiLZfwhnnfhtsdA2hfJlDnj+8PjAs6kKQPenOTKj3Rf7zHw==" + } + } + }, "@fortawesome/free-solid-svg-icons": { "version": "6.4.0", "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.4.0.tgz", diff --git a/package.json b/package.json index b000e10..75afad5 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "@fortawesome/fontawesome-svg-core": "^6.2.1", "@fortawesome/free-brands-svg-icons": "^6.2.1", "@fortawesome/free-solid-svg-icons": "^6.2.1", + "@fortawesome/free-regular-svg-icons": "^6.2.1", "@fortawesome/vue-fontawesome": "^3.0.2", "foundation-sites": "^6.7.5", "socket.io-client": "^4.5.3", diff --git a/src/App.vue b/src/App.vue index 2883b6d..263847f 100644 --- a/src/App.vue +++ b/src/App.vue @@ -28,16 +28,31 @@ const state = ref({ 'secret': null, 'current_entry': null, 'current_name': null, + 'last_notification_uuid': null, 'searching': false, 'last_msg': "", 'join_msg': null, 'uid': null, 'double_entry': {'artist': null, 'title': null, 'reason': null}, 'waiting_room_policy': null, + 'notify_me': [], 'config': {} }) onMounted(() => { + if (!window.Notification) { + console.log('Browser does not support notifications.'); + } else { + if (Notification.permission !== 'granted') { + Notification.requestPermission().then( + p => { + if (p !== 'granted') { + console.log('User blocked notifications.'); + } + } + ).catch(err => console.error(err)) + } + } window.addEventListener("resize", (e) => { state.value.is_small = (e.target.innerWidth < 768) }); $(document).foundation(); if(localStorage.name && localStorage.name != "null"){ state.value.name = localStorage.name } @@ -47,6 +62,7 @@ onMounted(() => { } if(localStorage.secret){ state.value.secret = localStorage.secret } if(localStorage.uid){ state.value.uid = localStorage.uid } + if(localStorage.notify_me) { state.value.notify_me = JSON.parse(localStorage.notify_me); } if(state.value.server && state.value.room && state.value.name) { connect() } @@ -58,7 +74,7 @@ function emptyLocalStorageAndLogout() { localStorage.removeItem('name') localStorage.removeItem('room') localStorage.removeItem('uid') - state.socket.disconnect() + state.value.socket.disconnect() state.value.joined = false } @@ -70,7 +86,7 @@ function updateName(evt) { evt.target.textContent = state.value.name;} function setServer(server) { state.value.server = server } function setSearchTerm(searchTerm) { state.value.search.searchTerm = searchTerm } function update_config(config) { - state.socket.emit("update_config", {"config": config}) + state.value.socket.emit("update_config", {"config": config}) close_config() } @@ -80,18 +96,14 @@ function search() { append({"ident": state.value.search.searchTerm, "source": "youtube"}) } else { state.value.searching = true - state.socket.emit("search", {"query": state.value.search.searchTerm }) + state.value.socket.emit("search", {"query": state.value.search.searchTerm }) } } function show_config() { - state.socket.emit("show_config"); + state.value.socket.emit("show_config"); } -function waitingRoomToQueue(uuid) { - state.socket.emit("waiting-room-to-queue", {"uuid": uuid}) -} - function append(entry) { checked_append_with_name(entry, state.value.name) } @@ -113,7 +125,7 @@ function append_anyway(ident, name, source, uid) { state.value.current_name = null; state.value.current_entry = null; state.value.double_entry = {'artist': null, 'title': null, 'reason': null}; - state.socket.emit("append-anyway", {"ident": ident, "performer": name, "source": source, "uid": uid }); + state.value.socket.emit("append-anyway", {"ident": ident, "performer": name, "source": source, "uid": uid }); $("#queue-tab-title").click(); } @@ -124,7 +136,7 @@ function raw_append(ident, name, source, uid) { state.value.current_name = null; state.value.current_entry = null; state.value.double_entry = {'artist': null, 'title': null, 'reason': null}; - state.socket.emit("append", {"ident": ident, "performer": name, "source": source, "uid": uid }); + state.value.socket.emit("append", {"ident": ident, "performer": name, "source": source, "uid": uid }); $("#queue-tab-title").click(); } @@ -134,7 +146,7 @@ function wait_append(ident, name, source, uid) { state.value.current_name = null; state.value.current_entry = null; - state.socket.emit("waiting-room-append", {"ident": ident, "performer": name, "source": source, "uid": uid }); + state.value.socket.emit("waiting-room-append", {"ident": ident, "performer": name, "source": source, "uid": uid }); $("#queue-tab-title").click(); } @@ -162,62 +174,89 @@ function connect() { state.value.uid = Math.random(); } } - registerSocketEvents(state.socket) + registerSocketEvents(state.value.socket) } -function skipCurrent() { - state.socket.emit("skip-current") +function notify_disable(uuid) { + let notify_me = JSON.parse(localStorage.notify_me) + let idx = notify_me.indexOf(uuid); + notify_me.splice(idx, 1); + localStorage.setItem("notify_me", JSON.stringify(notify_me)) + state.value.notify_me = notify_me } -function moveUp(uuid) { - state.socket.emit("move-up", {"uuid": uuid}) -} - -function skip(uuid) { - state.socket.emit("skip", {"uuid": uuid}) +function notify_enable(uuid) { + let notify_me = JSON.parse(localStorage.notify_me) + notify_me.push(uuid) + localStorage.setItem("notify_me", JSON.stringify(notify_me)) + state.value.notify_me = notify_me } function registerSocketEvents() { - state.socket = io(state.value.server) - state.socket.on("search-results", (results) => { + state.value.socket = io(state.value.server) + state.value.socket.on("search-results", (results) => { state.value.searching = false state.value.search.searchResults = results.results }) - state.socket.on("connect", () => { joinRoom() }) + state.value.socket.on("connect", () => { joinRoom() }) - state.socket.io.on("reconnect", () => { joinRoom() }) + state.value.socket.io.on("reconnect", () => { joinRoom() }) - state.socket.on("state", (val) => { + state.value.socket.on("state", (val) => { + if(!localStorage.notify_me) { + localStorage.setItem("notify_me", "[]"); + state.value.notify_me = [] + } + + var new_notify = [] // Somehow Array.filter does not work + state.value.notify_me.forEach((uuid) => { + for(const entry of val.queue) { + if(entry.uuid === uuid) { + new_notify.push(uuid) + }; + }; + }); + state.value.notify_me = new_notify; + + localStorage.setItem("notify_me", JSON.stringify(state.value.notify_me)) + + if (val.queue.length > 1 && + val.queue[1].uuid != state.value.last_notification_uuid && + state.value.notify_me.indexOf(val.queue[1].uuid) !== -1 && + Notification.permission === 'granted') { + state.value.last_notification_uuid = val.queue[1].uuid; + new Notification("Next Up for " + val.queue[1].performer + ":", {body: val.queue[1].artist + " - " + val.queue[1].title}) + } state.value.queue=val.queue state.value.recent=val.recent state.value.waiting_room = val.waiting_room state.value.waiting_room_policy = val.config.waiting_room_policy }) - state.socket.on("config", (response) => { + state.value.socket.on("config", (response) => { state.value.config=response $("#config").foundation("open") }) - state.socket.on("update_config", (response) => { + state.value.socket.on("update_config", (response) => { console.log(response) state.value.waiting_room_policy = response["waiting_room_policy"] console.log(state) }) - state.socket.on("msg", (response) => { + state.value.socket.on("msg", (response) => { state.value.last_msg = response.msg $("#msg").foundation("open") }) - state.socket.on("ask_for_waitingroom", (response) => { + state.value.socket.on("ask_for_waitingroom", (response) => { state.value.double_entry = response.old_entry; state.value.current_entry = response.current_entry; $("#alreadyqueued").foundation("open"); }) - state.socket.on("err", (response) => { + state.value.socket.on("err", (response) => { console.log(response) switch(response.type) { case "QUEUE_FULL": @@ -247,7 +286,7 @@ function registerSocketEvents() { function joinRoom() { console.log("Joining room " + state.value.room) - state.socket.emit("register-web", {"room": state.value.room}, (response) => { + state.value.socket.emit("register-web", {"room": state.value.room}, (response) => { if(response === true) { localStorage.name = state.value.name localStorage.server = state.value.server @@ -257,7 +296,7 @@ function joinRoom() { state.value.joined = true router.push({name: "room", params: {room: state.value.room}}) if (state.value.secret) { - state.socket.emit("register-admin", {"secret": state.value.secret}, (response) => { + state.value.socket.emit("register-admin", {"secret": state.value.secret}, (response) => { state.value.admin = response }) } @@ -269,7 +308,7 @@ function joinRoom() { "target='_blank'>Syng and run it with
syng-client " + state.value.server + "" if(state.value.joined) { - state.socket.disconnect() + state.value.socket.disconnect() setTimeout(() => connect(), 2000) } } @@ -286,10 +325,8 @@ function joinRoom() { @update:searchTerm="setSearchTerm" @search="search" @append="append" - @skip="skip" - @skipCurrent="skipCurrent" - @moveUp="moveUp" - @waitingRoomToQueue="waitingRoomToQueue" + @notify_disable="notify_disable" + @notify_enable="notify_enable" />