| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  | function reloadApp() { | 
					
						
							| 
									
										
										
										
											2020-08-26 22:12:01 +02:00
										 |  |  |     //window.location.reload(true);
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function parseDate(str) { | 
					
						
							|  |  |  |     try { | 
					
						
							|  |  |  |         return new Date(Date.parse(str)); | 
					
						
							| 
									
										
										
										
											2018-03-24 23:37:55 -04:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |     catch (e) { | 
					
						
							|  |  |  |         throw new Error("Can't parse date from " + str + ": " + e.stack); | 
					
						
							| 
									
										
										
										
											2018-03-24 23:37:55 -04:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2018-03-24 23:37:55 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  | function padNum(num) { | 
					
						
							|  |  |  |     return (num <= 9 ? "0" : "") + num; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2018-03-24 23:37:55 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  | function formatTime(date) { | 
					
						
							|  |  |  |     return padNum(date.getHours()) + ":" + padNum(date.getMinutes()); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2018-03-24 23:37:55 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  | function formatTimeWithSeconds(date) { | 
					
						
							|  |  |  |     return padNum(date.getHours()) + ":" + padNum(date.getMinutes()) + ":" + padNum(date.getSeconds()); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-12-23 11:02:38 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-16 22:03:30 +01:00
										 |  |  | // this is producing local time!
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  | function formatDate(date) { | 
					
						
							| 
									
										
										
										
											2018-08-15 08:48:16 +02:00
										 |  |  | //    return padNum(date.getDate()) + ". " + padNum(date.getMonth() + 1) + ". " + date.getFullYear();
 | 
					
						
							|  |  |  |     // instead of european format we'll just use ISO as that's pretty unambiguous
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return formatDateISO(date); | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2017-12-23 12:19:15 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-16 22:03:30 +01:00
										 |  |  | // this is producing local time!
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  | function formatDateISO(date) { | 
					
						
							|  |  |  |     return date.getFullYear() + "-" + padNum(date.getMonth() + 1) + "-" + padNum(date.getDate()); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-12-23 12:19:15 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  | function formatDateTime(date) { | 
					
						
							|  |  |  |     return formatDate(date) + " " + formatTime(date); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-12-28 19:00:31 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-26 14:26:57 +02:00
										 |  |  | function localNowDateTime() { | 
					
						
							|  |  |  |     return dayjs().format('YYYY-MM-DD HH:mm:ss.SSSZZ') | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  | function now() { | 
					
						
							|  |  |  |     return formatTimeWithSeconds(new Date()); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2018-01-22 23:18:08 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  | function isElectron() { | 
					
						
							| 
									
										
										
										
											2019-02-09 19:25:55 +01:00
										 |  |  |     return !!(window && window.process && window.process.type); | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2018-01-25 23:49:03 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-02 14:04:53 +01:00
										 |  |  | function isMac() { | 
					
						
							|  |  |  |     return navigator.platform.indexOf('Mac') > -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  | function assertArguments() { | 
					
						
							|  |  |  |     for (const i in arguments) { | 
					
						
							|  |  |  |         if (!arguments[i]) { | 
					
						
							| 
									
										
										
										
											2018-08-06 22:29:03 +02:00
										 |  |  |             console.trace(`Argument idx#${i} should not be falsy: ${arguments[i]}`); | 
					
						
							| 
									
										
										
										
											2018-03-24 23:37:55 -04:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2018-03-06 23:04:35 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-24 21:07:55 +02:00
										 |  |  | const entityMap = { | 
					
						
							|  |  |  |     '&': '&', | 
					
						
							|  |  |  |     '<': '<', | 
					
						
							|  |  |  |     '>': '>', | 
					
						
							|  |  |  |     '"': '"', | 
					
						
							|  |  |  |     "'": ''', | 
					
						
							|  |  |  |     '/': '/', | 
					
						
							|  |  |  |     '`': '`', | 
					
						
							|  |  |  |     '=': '=' | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  | function escapeHtml(str) { | 
					
						
							| 
									
										
										
										
											2020-06-24 21:07:55 +02:00
										 |  |  |     return str.replace(/[&<>"'`=\/]/g, s => entityMap[s]); | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2018-03-24 23:37:55 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  | async function stopWatch(what, func) { | 
					
						
							|  |  |  |     const start = new Date(); | 
					
						
							| 
									
										
										
										
											2018-03-24 23:37:55 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |     const ret = await func(); | 
					
						
							| 
									
										
										
										
											2018-02-04 20:23:30 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-10 16:36:25 +01:00
										 |  |  |     const tookMs = Date.now() - start.getTime(); | 
					
						
							| 
									
										
										
										
											2018-02-04 20:23:30 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |     console.log(`${what} took ${tookMs}ms`); | 
					
						
							| 
									
										
										
										
											2018-02-04 20:23:30 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |     return ret; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2018-02-19 22:02:03 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  | function formatValueWithWhitespace(val) { | 
					
						
							| 
									
										
										
										
											2019-12-09 23:07:45 +01:00
										 |  |  |     return /[^\w_-]/.test(val) ? '"' + val + '"' : val; | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2018-02-21 20:30:15 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-01 09:59:44 -04:00
										 |  |  | function formatLabel(label) { | 
					
						
							| 
									
										
										
										
											2020-05-28 23:59:08 +02:00
										 |  |  |     let str = "#" + formatValueWithWhitespace(label.name); | 
					
						
							| 
									
										
										
										
											2018-03-24 23:37:55 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-01 09:59:44 -04:00
										 |  |  |     if (label.value !== "") { | 
					
						
							|  |  |  |         str += "=" + formatValueWithWhitespace(label.value); | 
					
						
							| 
									
										
										
										
											2018-02-19 22:02:03 -05:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |     return str; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function getHost() { | 
					
						
							|  |  |  |     const url = new URL(window.location.href); | 
					
						
							|  |  |  |     return url.protocol + "//" + url.hostname + ":" + url.port; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2018-02-25 10:55:21 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  | function download(url) { | 
					
						
							| 
									
										
										
										
											2019-11-09 13:01:05 +01:00
										 |  |  |     url += '?' + Date.now(); // don't use cache
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |     if (isElectron()) { | 
					
						
							| 
									
										
										
										
											2020-04-27 20:58:31 +02:00
										 |  |  |         const remote = dynamicRequire('electron').remote; | 
					
						
							| 
									
										
										
										
											2018-02-25 10:55:21 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |         remote.getCurrentWebContents().downloadURL(url); | 
					
						
							| 
									
										
										
										
											2018-02-25 10:55:21 -05:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |     else { | 
					
						
							|  |  |  |         window.location.href = url; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2018-03-04 23:28:26 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  | function toObject(array, fn) { | 
					
						
							|  |  |  |     const obj = {}; | 
					
						
							| 
									
										
										
										
											2018-03-04 23:28:26 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |     for (const item of array) { | 
					
						
							| 
									
										
										
										
											2018-03-25 23:25:17 -04:00
										 |  |  |         const [key, value] = fn(item); | 
					
						
							| 
									
										
										
										
											2018-03-24 23:37:55 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 23:25:17 -04:00
										 |  |  |         obj[key] = value; | 
					
						
							| 
									
										
										
										
											2018-03-04 23:28:26 -05:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |     return obj; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2018-03-12 23:27:21 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  | function randomString(len) { | 
					
						
							|  |  |  |     let text = ""; | 
					
						
							|  |  |  |     const possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; | 
					
						
							| 
									
										
										
										
											2018-03-12 23:27:21 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |     for (let i = 0; i < len; i++) { | 
					
						
							|  |  |  |         text += possible.charAt(Math.floor(Math.random() * possible.length)); | 
					
						
							| 
									
										
										
										
											2018-03-12 23:27:21 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |     return text; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-12 22:41:53 +02:00
										 |  |  | function bindGlobalShortcut(keyboardShortcut, handler) { | 
					
						
							| 
									
										
										
										
											2019-05-19 16:56:16 +02:00
										 |  |  |     bindElShortcut($(document), keyboardShortcut, handler); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function bindElShortcut($el, keyboardShortcut, handler) { | 
					
						
							| 
									
										
										
										
											2018-12-24 18:39:31 +01:00
										 |  |  |     if (isDesktop()) { | 
					
						
							| 
									
										
										
										
											2019-11-24 22:01:10 +01:00
										 |  |  |         keyboardShortcut = normalizeShortcut(keyboardShortcut); | 
					
						
							| 
									
										
										
										
											2019-01-09 21:42:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-19 16:56:16 +02:00
										 |  |  |         $el.bind('keydown', keyboardShortcut, e => { | 
					
						
							| 
									
										
										
										
											2019-08-25 21:55:36 +02:00
										 |  |  |             handler(e); | 
					
						
							| 
									
										
										
										
											2018-03-25 19:49:33 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-24 18:39:31 +01:00
										 |  |  |             e.preventDefault(); | 
					
						
							| 
									
										
										
										
											2019-08-25 21:55:36 +02:00
										 |  |  |             e.stopPropagation(); | 
					
						
							| 
									
										
										
										
											2018-12-24 18:39:31 +01:00
										 |  |  |         }); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-03-25 19:49:33 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-24 22:01:10 +01:00
										 |  |  | /** | 
					
						
							|  |  |  |  * Normalize to the form expected by the jquery.hotkeys.js | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | function normalizeShortcut(shortcut) { | 
					
						
							|  |  |  |     return shortcut | 
					
						
							|  |  |  |         .toLowerCase() | 
					
						
							|  |  |  |         .replace("enter", "return") | 
					
						
							|  |  |  |         .replace("delete", "del") | 
					
						
							|  |  |  |         .replace("ctrl+alt", "alt+ctrl") | 
					
						
							|  |  |  |         .replace("meta+alt", "alt+meta"); // alt needs to be first;
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-24 10:10:36 +01:00
										 |  |  | function isMobile() { | 
					
						
							| 
									
										
										
										
											2019-01-14 23:50:45 +01:00
										 |  |  |     return window.device === "mobile" | 
					
						
							|  |  |  |         // window.device is not available in setup
 | 
					
						
							|  |  |  |         || (!window.device && /Mobi/.test(navigator.userAgent)); | 
					
						
							| 
									
										
										
										
											2018-12-24 10:10:36 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function isDesktop() { | 
					
						
							| 
									
										
										
										
											2019-01-14 23:50:45 +01:00
										 |  |  |     return window.device === "desktop" | 
					
						
							|  |  |  |         // window.device is not available in setup
 | 
					
						
							|  |  |  |         || (!window.device && !/Mobi/.test(navigator.userAgent)); | 
					
						
							| 
									
										
										
										
											2018-12-24 10:10:36 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-13 21:53:09 +01:00
										 |  |  | // cookie code below works for simple use cases only - ASCII only
 | 
					
						
							|  |  |  | // not setting path so that cookies do not leak into other websites if multiplexed with reverse proxy
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-29 00:09:16 +01:00
										 |  |  | function setCookie(name, value) { | 
					
						
							|  |  |  |     const date = new Date(Date.now() + 10 * 365 * 24 * 60 * 60 * 1000); | 
					
						
							|  |  |  |     const expires = "; expires=" + date.toUTCString(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-13 21:53:09 +01:00
										 |  |  |     document.cookie = name + "=" + (value || "")  + expires + ";"; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function setSessionCookie(name, value) { | 
					
						
							| 
									
										
										
										
											2020-05-20 00:03:33 +02:00
										 |  |  |     document.cookie = name + "=" + (value || "") + "; SameSite=Strict"; | 
					
						
							| 
									
										
										
										
											2019-03-13 21:53:09 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function getCookie(name) { | 
					
						
							|  |  |  |     const valueMatch = document.cookie.match('(^|;) ?' + name + '=([^;]*)(;|$)'); | 
					
						
							|  |  |  |     return valueMatch ? valueMatch[2] : null; | 
					
						
							| 
									
										
										
										
											2018-12-29 00:09:16 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-28 21:42:37 +01:00
										 |  |  | function getNoteTypeClass(type) { | 
					
						
							|  |  |  |     return "type-" + type; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function getMimeTypeClass(mime) { | 
					
						
							|  |  |  |     const semicolonIdx = mime.indexOf(';'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (semicolonIdx !== -1) { | 
					
						
							|  |  |  |         // stripping everything following the semicolon
 | 
					
						
							|  |  |  |         mime = mime.substr(0, semicolonIdx); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return 'mime-' + mime.toLowerCase().replace(/[\W_]+/g,"-"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-10 22:45:03 +02:00
										 |  |  | function closeActiveDialog() { | 
					
						
							|  |  |  |     if (glob.activeDialog) { | 
					
						
							|  |  |  |         glob.activeDialog.modal('hide'); | 
					
						
							| 
									
										
										
										
											2020-02-09 10:00:13 +01:00
										 |  |  |         glob.activeDialog = null; | 
					
						
							| 
									
										
										
										
											2019-06-10 22:45:03 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-09 10:00:13 +01:00
										 |  |  | let $lastFocusedElement = null; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function saveFocusedElement() { | 
					
						
							|  |  |  |     $lastFocusedElement = $(":focus"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function focusSavedElement() { | 
					
						
							|  |  |  |     if (!$lastFocusedElement) { | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ($lastFocusedElement.hasClass("ck")) { | 
					
						
							|  |  |  |         // must handle CKEditor separately because of this bug: https://github.com/ckeditor/ckeditor5/issues/607
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-16 11:22:37 +01:00
										 |  |  |         const editor = $lastFocusedElement | 
					
						
							|  |  |  |             .closest('.ck-editor__editable') | 
					
						
							|  |  |  |             .prop('ckeditorInstance'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         editor.editing.view.focus(); | 
					
						
							| 
									
										
										
										
											2020-02-09 10:00:13 +01:00
										 |  |  |     } else { | 
					
						
							|  |  |  |         $lastFocusedElement.focus(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     $lastFocusedElement = null; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-18 11:14:09 +02:00
										 |  |  | async function openDialog($dialog) { | 
					
						
							| 
									
										
										
										
											2020-02-09 10:00:13 +01:00
										 |  |  |     closeActiveDialog(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     glob.activeDialog = $dialog; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     saveFocusedElement(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     $dialog.modal(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     $dialog.on('hidden.bs.modal', () => { | 
					
						
							|  |  |  |         if (!glob.activeDialog || glob.activeDialog === $dialog) { | 
					
						
							|  |  |  |             focusSavedElement(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2020-04-18 11:14:09 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     const keyboardActionsService = (await import("./keyboard_actions.js")).default; | 
					
						
							|  |  |  |     keyboardActionsService.updateDisplayedShortcuts($dialog); | 
					
						
							| 
									
										
										
										
											2020-02-09 10:00:13 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-05 20:27:30 +02:00
										 |  |  | function isHtmlEmpty(html) { | 
					
						
							| 
									
										
										
										
											2020-03-26 16:59:40 +01:00
										 |  |  |     if (!html) { | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-04 13:22:07 +01:00
										 |  |  |     html = html.toLowerCase(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-29 17:11:44 +02:00
										 |  |  |     return !html.includes('<img') | 
					
						
							|  |  |  |         && !html.includes('<section') | 
					
						
							|  |  |  |         // line below will actually attempt to load images so better to check for images first
 | 
					
						
							|  |  |  |         && $("<div>").html(html).text().trim().length === 0; | 
					
						
							| 
									
										
										
										
											2019-10-05 20:27:30 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-08 23:09:57 +01:00
										 |  |  | async function clearBrowserCache() { | 
					
						
							|  |  |  |     if (isElectron()) { | 
					
						
							| 
									
										
										
										
											2020-04-27 20:58:31 +02:00
										 |  |  |         const win = dynamicRequire('electron').remote.getCurrentWindow(); | 
					
						
							| 
									
										
										
										
											2019-11-08 23:09:57 +01:00
										 |  |  |         await win.webContents.session.clearCache(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-22 20:35:17 +01:00
										 |  |  | /** | 
					
						
							|  |  |  |  * @param url - should be without initial slash!!! | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | function getUrlForDownload(url) { | 
					
						
							|  |  |  |     if (isElectron()) { | 
					
						
							|  |  |  |         // electron needs absolute URL so we extract current host, port, protocol
 | 
					
						
							|  |  |  |         return getHost() + '/' + url; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         // web server can be deployed on subdomain so we need to use relative path
 | 
					
						
							|  |  |  |         return url; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-19 11:16:36 +03:00
										 |  |  | function copySelectionToClipboard() { | 
					
						
							| 
									
										
										
										
											2020-01-19 09:25:35 +01:00
										 |  |  |     const text = window.getSelection().toString(); | 
					
						
							| 
									
										
										
										
											2020-01-19 11:16:36 +03:00
										 |  |  |     if (navigator.clipboard) { | 
					
						
							| 
									
										
										
										
											2020-01-19 09:25:35 +01:00
										 |  |  |         navigator.clipboard.writeText(text); | 
					
						
							| 
									
										
										
										
											2020-01-19 11:16:36 +03:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 16:28:19 +08:00
										 |  |  | function isCKEditorInitialized() { | 
					
						
							|  |  |  |     return !!(window && window.cutToNote); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-12 14:22:51 +02:00
										 |  |  | function dynamicRequire(moduleName) { | 
					
						
							|  |  |  |     if (typeof __non_webpack_require__ !== 'undefined') { | 
					
						
							|  |  |  |         return __non_webpack_require__(moduleName); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         return require(moduleName); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-13 10:23:36 +02:00
										 |  |  | function timeLimit(promise, limitMs) { | 
					
						
							| 
									
										
										
										
											2020-07-29 23:34:49 +02:00
										 |  |  |     // better stack trace if created outside of promise
 | 
					
						
							|  |  |  |     const error = new Error('Process exceeded time limit ' + limitMs); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-11 00:13:56 +02:00
										 |  |  |     return new Promise((res, rej) => { | 
					
						
							|  |  |  |         let resolved = false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-13 22:34:15 +02:00
										 |  |  |         promise.then(result => { | 
					
						
							| 
									
										
										
										
											2020-06-11 00:13:56 +02:00
										 |  |  |             resolved = true; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-13 22:34:15 +02:00
										 |  |  |             res(result); | 
					
						
							| 
									
										
										
										
											2020-06-11 00:13:56 +02:00
										 |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         setTimeout(() => { | 
					
						
							|  |  |  |             if (!resolved) { | 
					
						
							| 
									
										
										
										
											2020-07-29 23:34:49 +02:00
										 |  |  |                 rej(error); | 
					
						
							| 
									
										
										
										
											2020-06-11 00:13:56 +02:00
										 |  |  |             } | 
					
						
							|  |  |  |         }, limitMs); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  | export default { | 
					
						
							|  |  |  |     reloadApp, | 
					
						
							|  |  |  |     parseDate, | 
					
						
							|  |  |  |     padNum, | 
					
						
							|  |  |  |     formatTime, | 
					
						
							|  |  |  |     formatTimeWithSeconds, | 
					
						
							|  |  |  |     formatDate, | 
					
						
							|  |  |  |     formatDateISO, | 
					
						
							|  |  |  |     formatDateTime, | 
					
						
							| 
									
										
										
										
											2020-04-26 14:26:57 +02:00
										 |  |  |     localNowDateTime, | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |     now, | 
					
						
							|  |  |  |     isElectron, | 
					
						
							| 
									
										
										
										
											2018-12-02 14:04:53 +01:00
										 |  |  |     isMac, | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |     assertArguments, | 
					
						
							|  |  |  |     escapeHtml, | 
					
						
							|  |  |  |     stopWatch, | 
					
						
							|  |  |  |     formatLabel, | 
					
						
							|  |  |  |     download, | 
					
						
							|  |  |  |     toObject, | 
					
						
							| 
									
										
										
										
											2018-03-25 19:49:33 -04:00
										 |  |  |     randomString, | 
					
						
							| 
									
										
										
										
											2019-08-12 22:41:53 +02:00
										 |  |  |     bindGlobalShortcut, | 
					
						
							| 
									
										
										
										
											2019-05-19 16:56:16 +02:00
										 |  |  |     bindElShortcut, | 
					
						
							| 
									
										
										
										
											2018-12-24 10:10:36 +01:00
										 |  |  |     isMobile, | 
					
						
							| 
									
										
										
										
											2018-12-29 00:09:16 +01:00
										 |  |  |     isDesktop, | 
					
						
							| 
									
										
										
										
											2019-01-28 21:42:37 +01:00
										 |  |  |     setCookie, | 
					
						
							| 
									
										
										
										
											2019-03-13 21:53:09 +01:00
										 |  |  |     setSessionCookie, | 
					
						
							|  |  |  |     getCookie, | 
					
						
							| 
									
										
										
										
											2019-01-28 21:42:37 +01:00
										 |  |  |     getNoteTypeClass, | 
					
						
							| 
									
										
										
										
											2019-06-10 22:45:03 +02:00
										 |  |  |     getMimeTypeClass, | 
					
						
							| 
									
										
										
										
											2019-10-05 20:27:30 +02:00
										 |  |  |     closeActiveDialog, | 
					
						
							| 
									
										
										
										
											2020-02-09 10:00:13 +01:00
										 |  |  |     openDialog, | 
					
						
							|  |  |  |     saveFocusedElement, | 
					
						
							|  |  |  |     focusSavedElement, | 
					
						
							| 
									
										
										
										
											2019-11-08 23:09:57 +01:00
										 |  |  |     isHtmlEmpty, | 
					
						
							| 
									
										
										
										
											2019-11-22 20:35:17 +01:00
										 |  |  |     clearBrowserCache, | 
					
						
							| 
									
										
										
										
											2019-11-24 22:01:10 +01:00
										 |  |  |     getUrlForDownload, | 
					
						
							| 
									
										
										
										
											2020-01-19 11:16:36 +03:00
										 |  |  |     normalizeShortcut, | 
					
						
							| 
									
										
										
										
											2020-02-02 16:28:19 +08:00
										 |  |  |     copySelectionToClipboard, | 
					
						
							| 
									
										
										
										
											2020-04-12 14:22:51 +02:00
										 |  |  |     isCKEditorInitialized, | 
					
						
							| 
									
										
										
										
											2020-06-11 00:13:56 +02:00
										 |  |  |     dynamicRequire, | 
					
						
							|  |  |  |     timeLimit | 
					
						
							| 
									
										
										
										
											2020-05-20 00:03:33 +02:00
										 |  |  | }; |