diff options
author | Ven <vendicated@riseup.net> | 2023-02-10 22:33:34 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-02-10 22:33:34 +0100 |
commit | 1d995e58f515dbeb908ba34bf70f829bfd3ccfac (patch) | |
tree | df8c540f5656028502288ab4e58e41754f723bc9 /src/api/Notifications/Notifications.tsx | |
parent | 6114bc6b168607613d06ae8fb4f29e74c763a417 (diff) | |
download | Vencord-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.tsx | 92 |
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++)); + } +} |