diff --git a/apps/web/desktop/events.js b/apps/web/desktop/events.js
index 469e37bdf..b036ee6bc 100644
--- a/apps/web/desktop/events.js
+++ b/apps/web/desktop/events.js
@@ -23,5 +23,6 @@ export const EVENTS = {
updateDownloadProgress: "updateDownloadProgress",
updateDownloadCompleted: "updateDownloadCompleted",
updateNotAvailable: "updateNotAvailable",
- themeChanged: "themeChanged"
+ themeChanged: "themeChanged",
+ notificationClicked: "notificationClicked"
};
diff --git a/apps/web/desktop/ipc/actions/bringToFront.js b/apps/web/desktop/ipc/actions/bringToFront.js
new file mode 100644
index 000000000..02ae593ce
--- /dev/null
+++ b/apps/web/desktop/ipc/actions/bringToFront.js
@@ -0,0 +1,24 @@
+/*
+This file is part of the Notesnook project (https://notesnook.com/)
+
+Copyright (C) 2023 Streetwriters (Private) Limited
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+*/
+
+export default () => {
+ if (!global.win) return;
+ global.win.show();
+ global.win.moveTop();
+};
diff --git a/apps/web/desktop/ipc/actions/index.js b/apps/web/desktop/ipc/actions/index.js
index 27714208d..9309fe8ad 100644
--- a/apps/web/desktop/ipc/actions/index.js
+++ b/apps/web/desktop/ipc/actions/index.js
@@ -25,6 +25,8 @@ import open from "./open";
import saveFile from "./saveFile";
import setZoomFactor from "./setZoomFactor";
import setPrivacyMode from "./setPrivacyMode";
+import showNotification from "./showNotification";
+import bringToFront from "./bringToFront";
const actions = {
changeAppTheme,
@@ -34,7 +36,9 @@ const actions = {
open,
saveFile,
setZoomFactor,
- setPrivacyMode
+ setPrivacyMode,
+ showNotification,
+ bringToFront
};
export function getAction(actionName) {
diff --git a/apps/web/desktop/ipc/actions/showNotification.js b/apps/web/desktop/ipc/actions/showNotification.js
new file mode 100644
index 000000000..1e23636eb
--- /dev/null
+++ b/apps/web/desktop/ipc/actions/showNotification.js
@@ -0,0 +1,42 @@
+/*
+This file is part of the Notesnook project (https://notesnook.com/)
+
+Copyright (C) 2023 Streetwriters (Private) Limited
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+*/
+import { Notification, shell } from "electron";
+import { join } from "path";
+import { EVENTS } from "../../events";
+import { sendMessageToRenderer } from "../utils";
+import { platform } from "os";
+
+export default (args) => {
+ if (!global.win) return;
+ const notification = new Notification({
+ ...args,
+ icon: join(
+ __dirname,
+ platform() === "win32" ? "app.ico" : "favicon-72x72.png"
+ )
+ });
+ notification.show();
+ if (args.urgency === "critical") {
+ shell.beep();
+ }
+
+ notification.addListener("click", () => {
+ sendMessageToRenderer(EVENTS.notificationClicked, { tag: args.tag });
+ });
+};
diff --git a/apps/web/src/commands/bring-to-front.js b/apps/web/src/commands/bring-to-front.js
new file mode 100644
index 000000000..5ffbfe6f4
--- /dev/null
+++ b/apps/web/src/commands/bring-to-front.js
@@ -0,0 +1,24 @@
+/*
+This file is part of the Notesnook project (https://notesnook.com/)
+
+Copyright (C) 2023 Streetwriters (Private) Limited
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+*/
+
+import { invokeCommand } from "./index";
+
+export default function bringToFront() {
+ invokeCommand("bringToFront");
+}
diff --git a/apps/web/src/commands/index.js b/apps/web/src/commands/index.js
index 5ca3b87ba..38913031d 100644
--- a/apps/web/src/commands/index.js
+++ b/apps/web/src/commands/index.js
@@ -32,7 +32,7 @@ export function invokeCommand(type, payload = {}) {
if (isDesktop()) {
window.api.receive("fromMain", (args) => {
console.log(args);
- const { type } = args;
- AppEventManager.publish(type, args);
+ const { type, ...other } = args;
+ AppEventManager.publish(type, other);
});
}
diff --git a/apps/web/src/commands/show-notification.js b/apps/web/src/commands/show-notification.js
new file mode 100644
index 000000000..3e0ac384a
--- /dev/null
+++ b/apps/web/src/commands/show-notification.js
@@ -0,0 +1,40 @@
+/*
+This file is part of the Notesnook project (https://notesnook.com/)
+
+Copyright (C) 2023 Streetwriters (Private) Limited
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+*/
+
+import { EVENTS } from "@notesnook/desktop/events";
+import { AppEventManager } from "../common/app-events";
+import { invokeCommand } from "./index";
+
+/**
+ *
+ * @param {import("electron").NotificationConstructorOptions & { tag: string }} options
+ * @param {() => void} onClicked
+ */
+export default function showNotification(options, onClicked) {
+ invokeCommand("showNotification", options);
+ const { unsubscribe } = AppEventManager.subscribe(
+ EVENTS.notificationClicked,
+ ({ tag }) => {
+ if (tag === options.tag) {
+ onClicked();
+ unsubscribe();
+ }
+ }
+ );
+}
diff --git a/apps/web/src/stores/reminder-store.js b/apps/web/src/stores/reminder-store.js
index d176a2178..52731aa27 100644
--- a/apps/web/src/stores/reminder-store.js
+++ b/apps/web/src/stores/reminder-store.js
@@ -26,7 +26,9 @@ import { showReminderPreviewDialog } from "../common/dialog-controller";
import dayjs from "dayjs";
import Config from "../utils/config";
import { store as notestore } from "./note-store";
-import { isTesting } from "../utils/platform";
+import { isDesktop, isTesting } from "../utils/platform";
+import showNotification from "../commands/show-notification";
+import bringToFront from "../commands/bring-to-front";
class ReminderStore extends BaseStore {
reminders = [];
@@ -81,6 +83,13 @@ async function resetReminders(reminders) {
}
}
+/**
+ *
+ * @param {string} id
+ * @param {import("@notesnook/core/collections/reminders").Reminder} reminder
+ * @param {string} cron
+ * @returns
+ */
function scheduleReminder(id, reminder, cron) {
return TaskScheduler.register(`reminder:${id}`, cron, () => {
if (!Config.get("reminderNotifications", true)) return;
@@ -90,18 +99,42 @@ function scheduleReminder(id, reminder, cron) {
return;
}
- const notification = new Notification(reminder.title, {
- body: reminder.description,
- vibrate: reminder.priority === "vibrate",
- silent: reminder.priority === "silent",
- tag: id,
- renotify: true,
- requireInteraction: true
- });
+ if (isDesktop()) {
+ showNotification(
+ {
+ title: reminder.title,
+ body: reminder.description,
+ silent: reminder.priority === "silent",
+ timeoutType: reminder.priority === "urgent" ? "never" : "default",
+ urgency:
+ reminder.priority === "urgent"
+ ? "critical"
+ : reminder.priority === "vibrate"
+ ? "normal"
+ : "low",
+ focusOnClick: true,
+ tag: id
+ },
+ () => {
+ bringToFront();
+ showReminderPreviewDialog(reminder);
+ }
+ );
+ } else {
+ const notification = new Notification(reminder.title, {
+ body: reminder.description,
+ vibrate: reminder.priority === "vibrate",
+ silent: reminder.priority === "silent",
+ tag: id,
+ renotify: true,
+ requireInteraction: true
+ });
- notification.onclick = function () {
- showReminderPreviewDialog(reminder);
- };
+ notification.onclick = function () {
+ window.focus();
+ showReminderPreviewDialog(reminder);
+ };
+ }
store.refresh(false);
});