aboutsummaryrefslogtreecommitdiff
path: root/src/api/Notifications/Notifications.tsx
diff options
context:
space:
mode:
authorVen <vendicated@riseup.net>2023-02-10 22:33:34 +0100
committerGitHub <noreply@github.com>2023-02-10 22:33:34 +0100
commit1d995e58f515dbeb908ba34bf70f829bfd3ccfac (patch)
treedf8c540f5656028502288ab4e58e41754f723bc9 /src/api/Notifications/Notifications.tsx
parent6114bc6b168607613d06ae8fb4f29e74c763a417 (diff)
downloadVencord-1d995e58f515dbeb908ba34bf70f829bfd3ccfac.tar.gz
Vencord-1d995e58f515dbeb908ba34bf70f829bfd3ccfac.tar.bz2
Vencord-1d995e58f515dbeb908ba34bf70f829bfd3ccfac.zip
Notification API (#467)
Co-authored-by: Ven <vendicated@riseup.net> Co-authored-by: afn <hey@afn.lol> Co-authored-by: afn <afnzmn@gmail.com>
Diffstat (limited to 'src/api/Notifications/Notifications.tsx')
-rw-r--r--src/api/Notifications/Notifications.tsx92
1 files changed, 92 insertions, 0 deletions
diff --git a/src/api/Notifications/Notifications.tsx b/src/api/Notifications/Notifications.tsx
new file mode 100644
index 0000000..9c599aa
--- /dev/null
+++ b/src/api/Notifications/Notifications.tsx
@@ -0,0 +1,92 @@
+/*
+ * Vencord, a modification for Discord's desktop app
+ * Copyright (c) 2023 Vendicated and contributors
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+*/
+
+import { Settings } from "@api/settings";
+import { Queue } from "@utils/Queue";
+import { ReactDOM } from "@webpack/common";
+import type { ReactNode } from "react";
+import type { Root } from "react-dom/client";
+
+import NotificationComponent from "./NotificationComponent";
+
+const NotificationQueue = new Queue();
+
+let reactRoot: Root;
+let id = 42;
+
+function getRoot() {
+ if (!reactRoot) {
+ const container = document.createElement("div");
+ container.id = "vc-notification-container";
+ document.body.append(container);
+ reactRoot = ReactDOM.createRoot(container);
+ }
+ return reactRoot;
+}
+
+export interface NotificationData {
+ title: string;
+ body: string;
+ /**
+ * Same as body but can be a custom component.
+ * Will be used over body if present.
+ * Not supported on desktop notifications, those will fall back to body */
+ richBody?: ReactNode;
+ /** Small icon. This is for things like profile pictures and should be square */
+ icon?: string;
+ /** Large image. Optimally, this should be around 16x9 but it doesn't matter much. Desktop Notifications might not support this */
+ image?: string;
+ onClick?(): void;
+ onClose?(): void;
+ color?: string;
+}
+
+function _showNotification(notification: NotificationData, id: number) {
+ const root = getRoot();
+ return new Promise<void>(resolve => {
+ root.render(
+ <NotificationComponent key={id} {...notification} onClose={() => {
+ notification.onClose?.();
+ root.render(null);
+ resolve();
+ }} />,
+ );
+ });
+}
+
+function shouldBeNative() {
+ const { useNative } = Settings.notifications;
+ if (useNative === "always") return true;
+ if (useNative === "not-focused") return !document.hasFocus();
+ return false;
+}
+
+export function showNotification(data: NotificationData) {
+ if (shouldBeNative()) {
+ const { title, body, icon, image, onClick = null, onClose = null } = data;
+ const n = new Notification(title, {
+ body,
+ icon,
+ image
+ });
+ n.onclick = onClick;
+ n.onclose = onClose;
+ } else {
+ NotificationQueue.push(() => _showNotification(data, id++));
+ }
+}