diff options
author | B. Stack <bgstack15@gmail.com> | 2023-11-10 17:12:41 -0500 |
---|---|---|
committer | B. Stack <bgstack15@gmail.com> | 2023-11-10 17:12:41 -0500 |
commit | 6bb4b9a5600dc7278acee769f3dc4a6be0296229 (patch) | |
tree | 6e49d1f702b332a65957e3c239062a2f342f30b6 | |
parent | add build-rpm.sh (diff) | |
download | radicaleinfcloud-6bb4b9a5600dc7278acee769f3dc4a6be0296229.tar.gz radicaleinfcloud-6bb4b9a5600dc7278acee769f3dc4a6be0296229.tar.bz2 radicaleinfcloud-6bb4b9a5600dc7278acee769f3dc4a6be0296229.zip |
add desktop notifications
Use the calendar color for the icon, if it is defined. Event-specific
color is not supported at this time.
-rw-r--r-- | radicale_infcloud/web/data_process.js | 9 | ||||
-rw-r--r-- | radicale_infcloud/web/index.html | 2 | ||||
-rw-r--r-- | radicale_infcloud/web/interface.js | 1 | ||||
-rw-r--r-- | radicale_infcloud/web/notifications.js | 127 |
4 files changed, 138 insertions, 1 deletions
diff --git a/radicale_infcloud/web/data_process.js b/radicale_infcloud/web/data_process.js index 69f81d4..d0cf40e 100644 --- a/radicale_infcloud/web/data_process.js +++ b/radicale_infcloud/web/data_process.js @@ -165,6 +165,7 @@ function setAlertTimeouts(isTodo, alertTime, dateStart, dateEnd, params, firstIn if(aTime!==''&&aTime>now) { var delay=aTime-now; + var this_color = ""; if(maxAlarmValue<delay) delay=maxAlarmValue; if(isTodo) @@ -173,7 +174,13 @@ function setAlertTimeouts(isTodo, alertTime, dateStart, dateEnd, params, firstIn }, delay,startTime); else alertTimeOut[alertTimeOut.length]=setTimeout(function(startTime){ - showAlertEvents(uid, (aTime-now), {start:new Date(startTime.getTime()), allDay:params.allDay, title:params.title}); + var collections=globalResourceCalDAVList.collections; + for(var i=0;i<collections.length;i++) { + if(uid.startsWith(collections[i].uid)) { + this_color = collections[i].ecolor; + } + } + showAlertEvents(uid, (aTime-now), {start:new Date(startTime.getTime()), allDay:params.allDay, title:params.title, color:this_color}); }, delay,startTime); } } diff --git a/radicale_infcloud/web/index.html b/radicale_infcloud/web/index.html index a0c8fd6..75af8ee 100644 --- a/radicale_infcloud/web/index.html +++ b/radicale_infcloud/web/index.html @@ -60,6 +60,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. <script src="main.js" type="text/javascript"></script> <script src="forms.js" type="text/javascript"></script> <script src="timezones.js" type="text/javascript"></script> + <script src="notifications.js" type="text/javascript"></script> </head> <body> <div id="cacheDialog"> @@ -143,6 +144,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. <tr><td><kbd>Ctrl</kbd><kbd>3</kbd></td><td>Week view</td></tr> <tr><td><kbd>Ctrl</kbd><kbd>4</kbd></td><td>Day view</td></tr> </table> + <button id="testNotification" onclick="clickTestNotification()">Send test notification</button> </div> <div id="aboutDialog" title="About dialog"> <div id="aboutCloseButton">x</div> diff --git a/radicale_infcloud/web/interface.js b/radicale_infcloud/web/interface.js index 7f7304b..d98860d 100644 --- a/radicale_infcloud/web/interface.js +++ b/radicale_infcloud/web/interface.js @@ -1215,6 +1215,7 @@ function showAlertEvents(inputUID, realDelay, alarmObject) timeString=' - '+timeS; } + SendColorizedNotification(alarmObject.title,timeString,img_cal,"",alarmObject.color); $('#alertBoxContent').append("<div class='alert_item'><img src='images/calendarB.svg' alt='Calendar'/><label>"+alarmObject.title+dateString+timeString+"</label></div>"); } } diff --git a/radicale_infcloud/web/notifications.js b/radicale_infcloud/web/notifications.js new file mode 100644 index 0000000..06670a5 --- /dev/null +++ b/radicale_infcloud/web/notifications.js @@ -0,0 +1,127 @@ +/* +vim: set et ts=3 sw=3 sts=3: +InfCloud - the open source CalDAV/CardDAV Web Client +Copyright (C) 2011-2023 + B. Stack <bgstack15@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +// InfCloud/CalDAVZap location for this image +const img_cal = "images/banner_calendar.svg"; +const notification_attempts = 10; +const notification_ms = 200; +// Due to how browsers/css work with colors, you can pass #000000 or web safe color names. +var colors = Array("red","orange","yellow","green","blue","purple","black","white","brown"); + +function colorizeSvg(inSvg, oldColor, newColor) { + // In case we have to do more than `s//g` in the future. + return inSvg.replaceAll(oldColor, newColor); +} + +function SendColorizedNotification(_title, _body, _icon, _tag, _color) { + // given _icon as path on server, get contents and adjust the main color in it to desired color. + // The 585858 is the specific color of the calendar.svg we intend to replace. + const xhr = new XMLHttpRequest(); + xhr.open("GET",_icon); + xhr.onload = () => { + // Ref: https://stackoverflow.com/questions/28450471/convert-inline-svg-to-base64-string + newSvg = colorizeSvg(xhr.responseText,"#585858",_color); + encodedData = window.btoa(newSvg); // turn it into the base64 stream + encodedData = "data:image/svg+xml;base64," + encodedData; // prepend the type of stream + SendNotification(_title, _body, encodedData, _tag, _color); + } + xhr.send(); +} + +function SendNotification(_title, _body, _icon, _tag) { + // From: https://developer.mozilla.org/en-US/docs/Web/API/notification + if (!("Notification" in window)) { + // Check if the browser supports notifications + alert("This browser does not support desktop notification"); + } else if (Notification.permission === "granted") { + // Check whether notification permissions have already been granted; + // if so, create a notification + console.log("trying option 1"); + const notification = new Notification(String(_title), { tag: _tag, body: _body, icon: _icon }); + // … + } else if (Notification.permission !== "denied") { + // We need to ask the user for permission + Notification.requestPermission().then((permission) => { + // If the user accepts, let's create a notification + if (permission === "granted") { + console.log("trying option 2"); + const notification = new Notification(String(_title), { tag: _tag, body: _body, icon: _icon }); + // … + } + }); + } + // At last, if the user has denied notifications, and you + // want to be respectful there is no need to bother them anymore. + console.log("trying option 3"); +} + +function SendNotificationManyTimes(_title, _body, _icon, _tag) { + // From: https://developer.mozilla.org/en-US/docs/Web/API/Notifications_API/Using_the_Notifications_API + if (Notification?.permission === "granted") { + // If the user agreed to get notified + // Let's try to send ten notifications + let i = 0; + // Using an interval cause some browsers (including Firefox) are blocking notifications if there are too much in a certain time. + const interval = setInterval(() => { + // Thanks to the tag, we should only see the "Hi! 9" notification + const n = new Notification(String(_title), { tag: _tag, body: _body, icon: _icon }); + //const n = new Notification(`Hi! breakfast ${i}`, { tag: "soManyNotification", body: "this is body?", icon: img }); + if (i === (notification_attempts-1)) { + clearInterval(interval); + } + i++; + }, notification_ms); + } else if (Notification && Notification.permission !== "denied") { + // If the user hasn't told if they want to be notified or not + // Note: because of Chrome, we are not sure the permission property + // is set, therefore it's unsafe to check for the "default" value. + Notification.requestPermission().then((status) => { + // If the user said okay + if (status === "granted") { + let i = 0; + // Using an interval cause some browsers (including Firefox) are blocking notifications if there are too much in a certain time. + const interval = setInterval(() => { + // Thanks to the tag, we should only see the "Hi! 9" notification + const n = new Notification(String(_title), { tag: _tag, body: _body, icon: _icon }); + if (i === (notification_attempts-1)) { + clearInterval(interval); + } + i++; + }, notification_ms); + } else { + // Otherwise, we can fallback to a regular modal alert + alert(String(_title)+": "+String(_body)); + } + }); + } else { + // If the user refuses to get notified, we can fallback to a regular modal alert + alert(String(_title)+": "+String(_body)); + } +} + +function getRandomColor() { + return colors[Math.floor(Math.random()*colors.length)]; +} + +function clickTestNotification() +{ + console.log("inside the click listener function"); + SendColorizedNotification("sample calendar appointment","in 0 minutes",img_cal,"",getRandomColor()); +} |