diff --git a/static_src/timer.js b/static_src/timer.js index 7a51484ede93ff7e92d811e9bb7af06069c63e59..4729748c509bcc8f4d4ca21678b0872de3279792 100644 --- a/static_src/timer.js +++ b/static_src/timer.js @@ -1,11 +1,23 @@ import $ from "jquery" import Timer from "easytimer.js" +import alertify from "alertifyjs"; +import "alertifyjs/build/css/alertify.css"; + +const updateTimeText = (timer) => { + const timeValues = timer.getTimeValues() + + const hours = String(timeValues.minutes + timeValues.hours * 60 + timeValues.days * 1440).padStart(2, '0') + const seconds = String(timeValues.seconds).padStart(2, '0') + + $('#timer .timer-values').html(`${hours}:${seconds}`) +} + const assignEventListeners = (timer) => { timer.addEventListener( 'secondsUpdated', (event) => { - $('#timer .timer-values').html(timer.getTimeValues().toString(['minutes', 'seconds'])) + updateTimeText(timer) } ) @@ -17,7 +29,7 @@ const assignEventListeners = (timer) => { } ) - $('#timer .timer-values').html(timer.getTimeValues().toString(['minutes', 'seconds'])) + updateTimeText(timer) } $(window).ready( @@ -32,59 +44,79 @@ $(window).ready( } }) - const timerSocket = new WebSocket( - ( - (window.location.protocol === "https:") ? - "wss://" : "ws://" + let timerSocket = null + let isInitialConnect = true + + const connectToSocket = () => { + timerSocket = new WebSocket( + ( + (window.location.protocol === "https:") ? + "wss://" : "ws://" + ) + + window.location.host + + "/ws/timer/" ) - + window.location.host - + "/ws/timer/" - ) - timerSocket.onmessage = (event) => { - const data = JSON.parse(event.data) + if (!isInitialConnect) { + alertify.success("ObnovovánĂ spojenĂ.") + } - if ("status" in data) { - if (data["status"] === "playing") { - // Reset if we are playing again. - const remainingTime = timer.getTimeValues() + isInitialConnect = false - if (remainingTime.seconds === 0 && remainingTime.minutes === 0) { - timer = new Timer({ - countdown: true, - startValues: { - minutes: window.startingTime.minutes, - seconds: window.startingTime.seconds, - } - }) + timerSocket.onmessage = (event) => { + console.log("Received timer message:", event.data) - assignEventListeners(timer) - } + const data = JSON.parse(event.data) + + if ("status" in data) { + if (data["status"] === "playing") { + // Reset if we are playing again. + const remainingTime = timer.getTimeValues() + + if (remainingTime.seconds === 0 && remainingTime.minutes === 0) { + timer = new Timer({ + countdown: true, + startValues: { + minutes: window.startingTime.minutes, + seconds: window.startingTime.seconds, + } + }) - timer.start() - } else if (data["status"] === "paused") { + assignEventListeners(timer) + } + + timer.start() + } else if (data["status"] === "paused") { + timer.pause() + } + } else if ("time" in data) { timer.pause() - } - } else if ("time" in data) { - timer.pause() - window.startingTime = { - minutes: data["time"]["minutes"], - seconds: data["time"]["seconds"] + window.startingTime = { + minutes: data["time"]["minutes"], + seconds: data["time"]["seconds"] + } + + timer = new Timer({ + countdown: true, + startValues: { + minutes: window.startingTime.minutes, + seconds: window.startingTime.seconds, + } + }) + + assignEventListeners(timer) } + } - timer = new Timer({ - countdown: true, - startValues: { - minutes: window.startingTime.minutes, - seconds: window.startingTime.seconds, - } - }) + timerSocket.onclose = (event) => { + alertify.error("Ztráta spojenĂ, pokoušĂme se o zpÄ›tnĂ© pĹ™ipojenĂ.") - assignEventListeners(timer) + setTimeout(connectToSocket, 5000) } } + connectToSocket() assignEventListeners(timer) // --- END Timer --- @@ -120,10 +152,13 @@ $(window).ready( $("#update-time").on( "click", (event) => { + let minutes = Number($("#minutes").val()) + let seconds = Number($("#seconds").val()) + timerSocket.send(JSON.stringify({ "time": { - "minutes": Number($("#minutes").val()), - "seconds": Number($("#seconds").val()) + "minutes": minutes, + "seconds": seconds } })) diff --git a/timer/consumers.py b/timer/consumers.py index 4cdf054f097fa0f5e8c1c6d19b2a125ee9c4e275..e0a9be6c697311c5a1c5cc8521b4531b61238f10 100644 --- a/timer/consumers.py +++ b/timer/consumers.py @@ -1,43 +1,90 @@ +import datetime import json from asgiref.sync import async_to_sync -from channels.generic.websocket import WebsocketConsumer +from channels.generic.websocket import AsyncWebsocketConsumer +import time -class TimerConsumer(WebsocketConsumer): - def connect(self): - async_to_sync(self.channel_layer.group_add)("timer", self.channel_name) +class TimerConsumer(AsyncWebsocketConsumer): + timer_is_running = False - self.accept() + async def connect(self) -> None: + await self.channel_layer.group_add("timer", self.channel_name) + await self.accept() - def disconnect(self, close_code): - pass + async def disconnect(self, close_code) -> None: + await self.channel_layer.group_discard("timer", self.channel_name) - def receive(self, text_data): + async def run_timer(self, minutes: int, seconds: int) -> None: + total_seconds = (minutes * 60) + seconds + first_run = True + + print("running timer") + + for second in range(total_seconds + 1): + if not first_run: + while not self.timer_is_running: + time.sleep(0.05) + + # Do on the first run, then every 5 seconds + if first_run or total_seconds % 5 == 0: + new_seconds = total_seconds % 60 + new_minutes = round((total_seconds - new_seconds) / 60) + + print("sending") + + await self.channel_layer.group_send( + "timer", + { + "type": "timer_message", + "text": json.dumps({ + "time": { + "minutes": new_minutes, + "seconds": new_seconds + } + }) + } + ) + + if not first_run: + total_seconds -= 1 + time.sleep(1) + + first_run = False + + async def receive(self, text_data: str) -> None: json_data = json.loads(text_data) response = None + time_updated = False if "status" in json_data: if json_data["status"] == "playing": response = {"status": "playing"} + self.timer_is_running = True elif json_data["status"] == "paused": response = {"status": "paused"} + self.timer_is_running = False if "time" in json_data: + minutes = json_data["time"]["minutes"] + seconds = json_data["time"]["seconds"] + response = { "time": { - "minutes": json_data["time"]["minutes"], - "seconds": json_data["time"]["seconds"], + "minutes": minutes, + "seconds": seconds, } } + time_updated = True + if response is not None: - async_to_sync(self.channel_layer.group_send)( - "timer", {"type": "timer_message", "text": json.dumps(response)} - ) + if time_updated: + await self.run_timer(minutes, seconds) - self.send(text_data=json.dumps({})) + await self.send(text_data=json.dumps({})) - def timer_message(self, event): - self.send(text_data=event["text"]) + async def timer_message(self, event: dict) -> None: + await self.send(text_data=event["text"]) diff --git a/timer/templates/timer/edit_timer.html b/timer/templates/timer/edit_timer.html index 7e9811af2fa729389ecde962cdcf37d1abe33281..370a72097240343f8caf448e4159434126e0fd13 100644 --- a/timer/templates/timer/edit_timer.html +++ b/timer/templates/timer/edit_timer.html @@ -59,6 +59,8 @@ type="number" id="minutes" name="minutes" + min="0" + max="60" placeholder="Minuty" autocomplete="off" > @@ -67,6 +69,8 @@ type="number" id="seconds" name="seconds" + min="0" + max="60" placeholder="Sekundy" autocomplete="off" > diff --git a/webpack.config.js b/webpack.config.js index 6e3af748fb555b9e8a168d13c4d8a731a4862f46..ce84878402ff4474e3758b8f9ef44a1e2b6c21da 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -33,7 +33,7 @@ module.exports = { }, output: { path: path.resolve(__dirname, "shared", "static", "shared"), - filename: "[name]-[fullhash].js", + filename: "[name].js", }, module: { rules: [