From 494a8e071c773a4bedacc23ac5bbd1323345e042 Mon Sep 17 00:00:00 2001 From: Raunak Raj <71929976+bajrangCoder@users.noreply.github.com> Date: Tue, 12 Nov 2024 19:11:42 +0530 Subject: [PATCH 1/2] feat(notifications): implement persistent notification system with toast notification --- src/lang/ar-ye.json | 4 +- src/lang/be-by.json | 4 +- src/lang/bn-bd.json | 4 +- src/lang/cs-cz.json | 4 +- src/lang/de-de.json | 4 +- src/lang/en-us.json | 4 +- src/lang/es-sv.json | 4 +- src/lang/fr-fr.json | 4 +- src/lang/hi-in.json | 4 +- src/lang/hu-hu.json | 4 +- src/lang/id-id.json | 4 +- src/lang/ir-fa.json | 4 +- src/lang/it-it.json | 4 +- src/lang/ja-jp.json | 4 +- src/lang/ko-kr.json | 4 +- src/lang/ml-in.json | 4 +- src/lang/mm-unicode.json | 4 +- src/lang/mm-zawgyi.json | 4 +- src/lang/pl-pl.json | 4 +- src/lang/pt-br.json | 4 +- src/lang/pu-in.json | 4 +- src/lang/ru-ru.json | 4 +- src/lang/tl-ph.json | 4 +- src/lang/tr-tr.json | 4 +- src/lang/uk-ua.json | 4 +- src/lang/uz-uz.json | 4 +- src/lang/vi-vn.json | 4 +- src/lang/zh-cn.json | 4 +- src/lang/zh-hant.json | 4 +- src/lang/zh-tw.json | 4 +- src/lib/acode.js | 26 +++ src/lib/main.js | 6 +- src/lib/notificationManager.js | 250 ++++++++++++++++++++++++ src/sidebarApps/index.js | 1 + src/sidebarApps/notification/index.js | 60 ++++++ src/sidebarApps/notification/style.scss | 142 ++++++++++++++ src/styles/main.scss | 120 +++++++++++- 37 files changed, 693 insertions(+), 32 deletions(-) create mode 100644 src/lib/notificationManager.js create mode 100644 src/sidebarApps/notification/index.js create mode 100644 src/sidebarApps/notification/style.scss diff --git a/src/lang/ar-ye.json b/src/lang/ar-ye.json index 2352e42df..9166d7feb 100644 --- a/src/lang/ar-ye.json +++ b/src/lang/ar-ye.json @@ -388,5 +388,7 @@ "delete entries": "Are you sure you want to delete {count} items?", "deleting items": "Deleting {count} items...", "import project zip": "Import Project(zip)", - "changelog": "Change Log" + "changelog": "Change Log", + "notifications": "Notifications", + "no_unread_notifications": "No unread notifications" } diff --git a/src/lang/be-by.json b/src/lang/be-by.json index 488edf542..3f15d31b8 100644 --- a/src/lang/be-by.json +++ b/src/lang/be-by.json @@ -388,5 +388,7 @@ "delete entries": "Are you sure you want to delete {count} items?", "deleting items": "Deleting {count} items...", "import project zip": "Import Project(zip)", - "changelog": "Change Log" + "changelog": "Change Log", + "notifications": "Notifications", + "no_unread_notifications": "No unread notifications" } diff --git a/src/lang/bn-bd.json b/src/lang/bn-bd.json index 4aedbfb7e..071a97fab 100644 --- a/src/lang/bn-bd.json +++ b/src/lang/bn-bd.json @@ -388,5 +388,7 @@ "delete entries": "Are you sure you want to delete {count} items?", "deleting items": "Deleting {count} items...", "import project zip": "Import Project(zip)", - "changelog": "Change Log" + "changelog": "Change Log", + "notifications": "Notifications", + "no_unread_notifications": "No unread notifications" } diff --git a/src/lang/cs-cz.json b/src/lang/cs-cz.json index 7601abb27..45d461315 100644 --- a/src/lang/cs-cz.json +++ b/src/lang/cs-cz.json @@ -388,5 +388,7 @@ "delete entries": "Are you sure you want to delete {count} items?", "deleting items": "Deleting {count} items...", "import project zip": "Import Project(zip)", - "changelog": "Change Log" + "changelog": "Change Log", + "notifications": "Notifications", + "no_unread_notifications": "No unread notifications" } diff --git a/src/lang/de-de.json b/src/lang/de-de.json index 5dda4e5f0..4c3d22d59 100644 --- a/src/lang/de-de.json +++ b/src/lang/de-de.json @@ -388,5 +388,7 @@ "delete entries": "Sind sie sicher, das Sie {count} Einträge löschen wollen?", "deleting items": "Löschen von {count} Einträgen...", "import project zip": "Projekt(-Zip) importieren", - "changelog": "Änderungsbericht" + "changelog": "Änderungsbericht", + "notifications": "Notifications", + "no_unread_notifications": "No unread notifications" } diff --git a/src/lang/en-us.json b/src/lang/en-us.json index c602d9ff0..288181481 100644 --- a/src/lang/en-us.json +++ b/src/lang/en-us.json @@ -389,5 +389,7 @@ "delete entries": "Are you sure you want to delete {count} items?", "deleting items": "Deleting {count} items...", "import project zip": "Import Project(zip)", - "changelog": "Change Log" + "changelog": "Change Log", + "notifications": "Notifications", + "no_unread_notifications": "No unread notifications" } diff --git a/src/lang/es-sv.json b/src/lang/es-sv.json index 2646e0446..d76718ca2 100644 --- a/src/lang/es-sv.json +++ b/src/lang/es-sv.json @@ -388,5 +388,7 @@ "delete entries": "Are you sure you want to delete {count} items?", "deleting items": "Deleting {count} items...", "import project zip": "Import Project(zip)", - "changelog": "Change Log" + "changelog": "Change Log", + "notifications": "Notifications", + "no_unread_notifications": "No unread notifications" } diff --git a/src/lang/fr-fr.json b/src/lang/fr-fr.json index 11886892a..4c3de3f87 100644 --- a/src/lang/fr-fr.json +++ b/src/lang/fr-fr.json @@ -388,5 +388,7 @@ "delete entries": "Are you sure you want to delete {count} items?", "deleting items": "Deleting {count} items...", "import project zip": "Import Project(zip)", - "changelog": "Change Log" + "changelog": "Change Log", + "notifications": "Notifications", + "no_unread_notifications": "No unread notifications" } diff --git a/src/lang/hi-in.json b/src/lang/hi-in.json index 72df39228..1f9f55d62 100644 --- a/src/lang/hi-in.json +++ b/src/lang/hi-in.json @@ -389,5 +389,7 @@ "delete entries": "Are you sure you want to delete {count} items?", "deleting items": "Deleting {count} items...", "import project zip": "Import Project(zip)", - "changelog": "Change Log" + "changelog": "Change Log", + "notifications": "Notifications", + "no_unread_notifications": "No unread notifications" } diff --git a/src/lang/hu-hu.json b/src/lang/hu-hu.json index 9a12ac35b..b4f0c389b 100644 --- a/src/lang/hu-hu.json +++ b/src/lang/hu-hu.json @@ -388,5 +388,7 @@ "delete entries": "Biztosan töröl {count} elemet?", "deleting items": "{count} elem törlése…", "import project zip": "Projekt importálása zip-ből", - "changelog": "Változásnapló" + "changelog": "Változásnapló", + "notifications": "Notifications", + "no_unread_notifications": "No unread notifications" } diff --git a/src/lang/id-id.json b/src/lang/id-id.json index e21115fbf..b41eedeae 100644 --- a/src/lang/id-id.json +++ b/src/lang/id-id.json @@ -390,5 +390,7 @@ "delete entries": "Are you sure you want to delete {count} items?", "deleting items": "Deleting {count} items...", "import project zip": "Import Project(zip)", - "changelog": "Change Log" + "changelog": "Change Log", + "notifications": "Notifications", + "no_unread_notifications": "No unread notifications" } diff --git a/src/lang/ir-fa.json b/src/lang/ir-fa.json index 90e66cf8f..531413a5e 100644 --- a/src/lang/ir-fa.json +++ b/src/lang/ir-fa.json @@ -389,5 +389,7 @@ "delete entries": "Are you sure you want to delete {count} items?", "deleting items": "Deleting {count} items...", "import project zip": "Import Project(zip)", - "changelog": "Change Log" + "changelog": "Change Log", + "notifications": "Notifications", + "no_unread_notifications": "No unread notifications" } diff --git a/src/lang/it-it.json b/src/lang/it-it.json index ff28c2ccb..e73d8f05b 100644 --- a/src/lang/it-it.json +++ b/src/lang/it-it.json @@ -388,5 +388,7 @@ "delete entries": "Are you sure you want to delete {count} items?", "deleting items": "Deleting {count} items...", "import project zip": "Import Project(zip)", - "changelog": "Change Log" + "changelog": "Change Log", + "notifications": "Notifications", + "no_unread_notifications": "No unread notifications" } diff --git a/src/lang/ja-jp.json b/src/lang/ja-jp.json index 634e3e443..7f37d338e 100644 --- a/src/lang/ja-jp.json +++ b/src/lang/ja-jp.json @@ -388,5 +388,7 @@ "delete entries": "Are you sure you want to delete {count} items?", "deleting items": "Deleting {count} items...", "import project zip": "Import Project(zip)", - "changelog": "Change Log" + "changelog": "Change Log", + "notifications": "Notifications", + "no_unread_notifications": "No unread notifications" } diff --git a/src/lang/ko-kr.json b/src/lang/ko-kr.json index 977242e10..8f6b5cf6e 100644 --- a/src/lang/ko-kr.json +++ b/src/lang/ko-kr.json @@ -388,5 +388,7 @@ "delete entries": "Are you sure you want to delete {count} items?", "deleting items": "Deleting {count} items...", "import project zip": "Import Project(zip)", - "changelog": "Change Log" + "changelog": "Change Log", + "notifications": "Notifications", + "no_unread_notifications": "No unread notifications" } diff --git a/src/lang/ml-in.json b/src/lang/ml-in.json index 9af5d8745..b800a32b8 100644 --- a/src/lang/ml-in.json +++ b/src/lang/ml-in.json @@ -388,5 +388,7 @@ "delete entries": "Are you sure you want to delete {count} items?", "deleting items": "Deleting {count} items...", "import project zip": "Import Project(zip)", - "changelog": "Change Log" + "changelog": "Change Log", + "notifications": "Notifications", + "no_unread_notifications": "No unread notifications" } diff --git a/src/lang/mm-unicode.json b/src/lang/mm-unicode.json index 55eda463c..79f349a6f 100644 --- a/src/lang/mm-unicode.json +++ b/src/lang/mm-unicode.json @@ -388,5 +388,7 @@ "delete entries": "Are you sure you want to delete {count} items?", "deleting items": "Deleting {count} items...", "import project zip": "Import Project(zip)", - "changelog": "Change Log" + "changelog": "Change Log", + "notifications": "Notifications", + "no_unread_notifications": "No unread notifications" } diff --git a/src/lang/mm-zawgyi.json b/src/lang/mm-zawgyi.json index cc7985d06..28e219e86 100644 --- a/src/lang/mm-zawgyi.json +++ b/src/lang/mm-zawgyi.json @@ -388,5 +388,7 @@ "delete entries": "Are you sure you want to delete {count} items?", "deleting items": "Deleting {count} items...", "import project zip": "Import Project(zip)", - "changelog": "Change Log" + "changelog": "Change Log", + "notifications": "Notifications", + "no_unread_notifications": "No unread notifications" } diff --git a/src/lang/pl-pl.json b/src/lang/pl-pl.json index 84db2e8fd..a4ae54a04 100644 --- a/src/lang/pl-pl.json +++ b/src/lang/pl-pl.json @@ -388,5 +388,7 @@ "delete entries": "Are you sure you want to delete {count} items?", "deleting items": "Deleting {count} items...", "import project zip": "Import Project(zip)", - "changelog": "Change Log" + "changelog": "Change Log", + "notifications": "Notifications", + "no_unread_notifications": "No unread notifications" } diff --git a/src/lang/pt-br.json b/src/lang/pt-br.json index aced1abfe..002a5d29e 100644 --- a/src/lang/pt-br.json +++ b/src/lang/pt-br.json @@ -388,5 +388,7 @@ "delete entries": "Are you sure you want to delete {count} items?", "deleting items": "Deleting {count} items...", "import project zip": "Import Project(zip)", - "changelog": "Change Log" + "changelog": "Change Log", + "notifications": "Notifications", + "no_unread_notifications": "No unread notifications" } diff --git a/src/lang/pu-in.json b/src/lang/pu-in.json index 0c27599e8..0e820ca2d 100644 --- a/src/lang/pu-in.json +++ b/src/lang/pu-in.json @@ -388,5 +388,7 @@ "delete entries": "Are you sure you want to delete {count} items?", "deleting items": "Deleting {count} items...", "import project zip": "Import Project(zip)", - "changelog": "Change Log" + "changelog": "Change Log", + "notifications": "Notifications", + "no_unread_notifications": "No unread notifications" } diff --git a/src/lang/ru-ru.json b/src/lang/ru-ru.json index 6e4f04ecc..1e9c7f684 100644 --- a/src/lang/ru-ru.json +++ b/src/lang/ru-ru.json @@ -389,5 +389,7 @@ "delete entries": "Are you sure you want to delete {count} items?", "deleting items": "Deleting {count} items...", "import project zip": "Import Project(zip)", - "changelog": "Change Log" + "changelog": "Change Log", + "notifications": "Notifications", + "no_unread_notifications": "No unread notifications" } diff --git a/src/lang/tl-ph.json b/src/lang/tl-ph.json index c495606b2..2e8b6f1ef 100644 --- a/src/lang/tl-ph.json +++ b/src/lang/tl-ph.json @@ -388,5 +388,7 @@ "delete entries": "Are you sure you want to delete {count} items?", "deleting items": "Deleting {count} items...", "import project zip": "Import Project(zip)", - "changelog": "Change Log" + "changelog": "Change Log", + "notifications": "Notifications", + "no_unread_notifications": "No unread notifications" } diff --git a/src/lang/tr-tr.json b/src/lang/tr-tr.json index 175412e0e..c0bf553ff 100644 --- a/src/lang/tr-tr.json +++ b/src/lang/tr-tr.json @@ -388,5 +388,7 @@ "delete entries": "Are you sure you want to delete {count} items?", "deleting items": "Deleting {count} items...", "import project zip": "Import Project(zip)", - "changelog": "Change Log" + "changelog": "Change Log", + "notifications": "Notifications", + "no_unread_notifications": "No unread notifications" } diff --git a/src/lang/uk-ua.json b/src/lang/uk-ua.json index 95acbcd52..68fc10565 100644 --- a/src/lang/uk-ua.json +++ b/src/lang/uk-ua.json @@ -388,5 +388,7 @@ "delete entries": "Are you sure you want to delete {count} items?", "deleting items": "Deleting {count} items...", "import project zip": "Import Project(zip)", - "changelog": "Change Log" + "changelog": "Change Log", + "notifications": "Notifications", + "no_unread_notifications": "No unread notifications" } diff --git a/src/lang/uz-uz.json b/src/lang/uz-uz.json index e5c097846..60728f7c5 100644 --- a/src/lang/uz-uz.json +++ b/src/lang/uz-uz.json @@ -388,5 +388,7 @@ "delete entries": "Are you sure you want to delete {count} items?", "deleting items": "Deleting {count} items...", "import project zip": "Import Project(zip)", - "changelog": "Change Log" + "changelog": "Change Log", + "notifications": "Notifications", + "no_unread_notifications": "No unread notifications" } diff --git a/src/lang/vi-vn.json b/src/lang/vi-vn.json index c5b282270..33e6f1cf5 100644 --- a/src/lang/vi-vn.json +++ b/src/lang/vi-vn.json @@ -389,5 +389,7 @@ "delete entries": "Are you sure you want to delete {count} items?", "deleting items": "Deleting {count} items...", "import project zip": "Import Project(zip)", - "changelog": "Change Log" + "changelog": "Change Log", + "notifications": "Notifications", + "no_unread_notifications": "No unread notifications" } diff --git a/src/lang/zh-cn.json b/src/lang/zh-cn.json index 25c1c12cd..da2107015 100644 --- a/src/lang/zh-cn.json +++ b/src/lang/zh-cn.json @@ -388,5 +388,7 @@ "delete entries": "Are you sure you want to delete {count} items?", "deleting items": "Deleting {count} items...", "import project zip": "Import Project(zip)", - "changelog": "Change Log" + "changelog": "Change Log", + "notifications": "Notifications", + "no_unread_notifications": "No unread notifications" } diff --git a/src/lang/zh-hant.json b/src/lang/zh-hant.json index f035e00f6..006f2fb0f 100644 --- a/src/lang/zh-hant.json +++ b/src/lang/zh-hant.json @@ -388,5 +388,7 @@ "delete entries": "Are you sure you want to delete {count} items?", "deleting items": "Deleting {count} items...", "import project zip": "Import Project(zip)", - "changelog": "Change Log" + "changelog": "Change Log", + "notifications": "Notifications", + "no_unread_notifications": "No unread notifications" } diff --git a/src/lang/zh-tw.json b/src/lang/zh-tw.json index 8218c4740..4de70f9b4 100644 --- a/src/lang/zh-tw.json +++ b/src/lang/zh-tw.json @@ -388,5 +388,7 @@ "delete entries": "Are you sure you want to delete {count} items?", "deleting items": "Deleting {count} items...", "import project zip": "Import Project(zip)", - "changelog": "Change Log" + "changelog": "Change Log", + "notifications": "Notifications", + "no_unread_notifications": "No unread notifications" } diff --git a/src/lib/acode.js b/src/lib/acode.js index c3b6423f4..238a2c064 100644 --- a/src/lib/acode.js +++ b/src/lib/acode.js @@ -22,6 +22,7 @@ import commands from "lib/commands"; import EditorFile from "lib/editorFile"; import files from "lib/fileList"; import fonts from "lib/fonts"; +import NotificationManager from "lib/notificationManager"; import openFolder from "lib/openFolder"; import projects from "lib/projects"; import selectionMenu from "lib/selectionMenu"; @@ -416,4 +417,29 @@ export default class Acode { url = await helpers.toInternalUri(url); return url; } + /** + * Push a notification + * @param {string} title Title of the notification + * @param {string} message Message body of the notification + * @param {Object} options Notification options + * @param {string} [options.icon] Icon for the notification, can be a URL or a base64 encoded image or icon class or svg string + * @param {boolean} [options.autoClose=true] Whether notification should auto close + * @param {Function} [options.action=null] Action callback when notification is clicked + * @param {('info'|'warning'|'error'|'success')} [options.type='info'] Type of notification + */ + pushNotification( + title, + message, + { icon, autoClose = true, action = null, type = "info" } = {}, + ) { + const nm = new NotificationManager(); + nm.pushNotification({ + title, + message, + icon, + autoClose, + action, + type, + }); + } } diff --git a/src/lib/main.js b/src/lib/main.js index 5d48caf4a..e7ecb7856 100644 --- a/src/lib/main.js +++ b/src/lib/main.js @@ -50,6 +50,7 @@ import { setKeyBindings } from "ace/commands"; import { initModes } from "ace/modelist"; import { keydownState } from "handlers/keyboard"; import { initFileList } from "lib/fileList"; +import NotificationManager from "lib/notificationManager"; import { addedFolder } from "lib/openFolder"; import { getEncoding, initEncodings } from "utils/encodings"; import constants from "./constants"; @@ -369,7 +370,10 @@ async function loadApp() { }); //#endregion - window.log("info", "Started app and services..."); + const notificationManager = new NotificationManager(); + notificationManager.init(); + + window.log("info", "Started app and its services..."); new EditorFile(); diff --git a/src/lib/notificationManager.js b/src/lib/notificationManager.js new file mode 100644 index 000000000..3d23fa5f3 --- /dev/null +++ b/src/lib/notificationManager.js @@ -0,0 +1,250 @@ +import sidebarApps from "sidebarApps"; + +// Singleton instance +let instance = null; + +export default class NotificationManager { + DEFAULT_ICON = ``; + MAX_NOTIFICATIONS = 20; + notifications = []; + REFRESH_INTERVAL = 60000; // 1 minute refresh interval + timeUpdateInterval = null; + + constructor() { + if (instance) { + return instance; + } + this.notifications = this.loadNotifications(); + instance = this; + } + + init() { + document.body.appendChild( +
, + ); + this.renderNotifications(); + this.startTimeUpdates(); + + sidebarApps + .get("notification") + ?.querySelector(".notifications-container") + .addEventListener("click", this.handleClick.bind(this)); + } + + startTimeUpdates() { + if (this.timeUpdateInterval) { + clearInterval(this.timeUpdateInterval); + } + + this.timeUpdateInterval = setInterval(() => { + this.updateNotificationTimes(); + }, this.REFRESH_INTERVAL); + } + + updateNotificationTimes() { + const container = sidebarApps + .get("notification") + ?.querySelector(".notifications-container"); + + if (!container) return; + + container.querySelectorAll(".notification-time").forEach((timeElement) => { + const notificationItem = timeElement.closest(".notification-item"); + const id = notificationItem?.dataset.id; + if (!id) return; + + const notification = this.notifications.find( + (n) => n.id === Number.parseInt(id), + ); + if (notification) { + timeElement.textContent = this.formatTime(notification.time); + } + }); + } + + loadNotifications() { + try { + const notifications = + JSON.parse(localStorage.getItem("notifications")) || []; + return notifications.map((n) => ({ + ...n, + time: new Date(n.time), + })); + } catch { + return []; + } + } + + saveNotifications() { + localStorage.setItem("notifications", JSON.stringify(this.notifications)); + } + + renderNotifications() { + const container = sidebarApps + .get("notification") + ?.querySelector(".notifications-container"); + if (!container) return; + + if (this.notifications.length === 0) { + container.innerHTML = `