From 12eddadc0720e7950d7a7954aace4c47a96310bf Mon Sep 17 00:00:00 2001 From: Pierre-Olivier Mercier Date: Sat, 1 Dec 2018 18:15:03 +0100 Subject: [PATCH] frontend: browser notifications of challenge events --- frontend/static/js/challenge.js | 55 +++++++++++++++++++++++++++++++++ frontend/static/js/common.js | 6 ++++ 2 files changed, 61 insertions(+) diff --git a/frontend/static/js/challenge.js b/frontend/static/js/challenge.js index fd38a6c4..9ccaf0e5 100644 --- a/frontend/static/js/challenge.js +++ b/frontend/static/js/challenge.js @@ -46,6 +46,14 @@ angular.module("FICApp", ["ngRoute", "ngSanitize"]) $rootScope.current_theme = 0; $rootScope.current_exercice = 0; $rootScope.current_tag = undefined; + $rootScope.notify_field = 0; + + Notification.requestPermission().then(function(result) { + if (result == "granted") + $rootScope.notify_field = 7; + else + $rootScope.notify_field = 0; + }); }) .controller("DataController", function($sce, $scope, $http, $rootScope, $interval, $location) { var actMenu = function() { @@ -146,6 +154,52 @@ angular.module("FICApp", ["ngRoute", "ngSanitize"]) }); } + var refreshEventsInterval; + var eventsLastRefresh; + var eventsLastTreated; + var refreshEvents = function() { + if (refreshEventsInterval) + $interval.cancel(refreshEventsInterval); + var refreshRate = 1200; + if ($rootScope.notify_field == 0 && eventsLastTreated) + refreshRate = 30000; + refreshEventsInterval = $interval(refreshEvents, Math.floor(Math.random() * refreshRate * 2) + refreshRate); + + if (!eventsLastTreated) { + eventsLastTreated = $rootScope.getSrvTime(); + if (!eventsLastTreated) + return; + } + + $http.get("/events.json").then(function(response) { + if (eventsLastRefresh != undefined && eventsLastRefresh == response.headers()["last-modified"]) + return; + eventsLastRefresh = response.headers()["last-modified"]; + + var maxTimeSeen = eventsLastTreated; + for (var i = response.data.length - 1; i >= 0; i--) { + var event = response.data[i]; + + event.time = new Date(event.time); + if (event.time <= eventsLastTreated) + continue; + else if (event.time > maxTimeSeen) + maxTimeSeen = event.time; + + if ($rootScope.notify_field != 0) { + var notification = new Notification("Challenge forensic", {body: event.txt.replace(/(<([^>]+)>)/ig,""), icon: "/favicon.ico"}); + notification.onclick = function(ev) { + $location.url("/edit"); + }; + setTimeout(notification.close.bind(notification), 4000); + } + }; + + if (maxTimeSeen > eventsLastTreated) + eventsLastTreated = maxTimeSeen; + }); + } + var refreshMyInterval; var refreshMy = function() { if (refreshMyInterval) @@ -219,6 +273,7 @@ angular.module("FICApp", ["ngRoute", "ngSanitize"]) refreshSettings(); refreshThemes(); $rootScope.refreshTeams(); + refreshEvents(); } else if (justSettings) { refreshSettings(); diff --git a/frontend/static/js/common.js b/frontend/static/js/common.js index 87e9c371..4cd2a211 100644 --- a/frontend/static/js/common.js +++ b/frontend/static/js/common.js @@ -138,6 +138,12 @@ angular.module("FICApp") $scope.time = {}; + $rootScope.getSrvTime = function() { + if (time.cu && time.he) + return new Date(Date.now() + (time.cu - time.he)); + else + return undefined; + } $rootScope.recvTime = function(response) { time = { "cu": Math.floor(response.headers("x-fic-time") * 1000),