From 18b06b5bd791cee5b9c939ebab6ffdd73bfeee19 Mon Sep 17 00:00:00 2001
From: Ajay Bura <32841439+ajbura@users.noreply.github.com>
Date: Fri, 21 Feb 2025 08:40:50 +0530
Subject: [PATCH 1/3] refactor system notification to dedicated file
---
.../settings/notifications/Notifications.tsx | 74 +------------------
.../notifications/SystemNotification.tsx | 73 ++++++++++++++++++
2 files changed, 75 insertions(+), 72 deletions(-)
create mode 100644 src/app/features/settings/notifications/SystemNotification.tsx
diff --git a/src/app/features/settings/notifications/Notifications.tsx b/src/app/features/settings/notifications/Notifications.tsx
index 88e16d296..aa339a031 100644
--- a/src/app/features/settings/notifications/Notifications.tsx
+++ b/src/app/features/settings/notifications/Notifications.tsx
@@ -1,82 +1,12 @@
import React from 'react';
-import { Box, Text, IconButton, Icon, Icons, Scroll, Switch, Button, color } from 'folds';
+import { Box, Text, IconButton, Icon, Icons, Scroll } from 'folds';
import { Page, PageContent, PageHeader } from '../../../components/page';
-import { SequenceCard } from '../../../components/sequence-card';
-import { SequenceCardStyle } from '../styles.css';
-import { SettingTile } from '../../../components/setting-tile';
-import { useSetting } from '../../../state/hooks/settings';
-import { settingsAtom } from '../../../state/settings';
-import { getNotificationState, usePermissionState } from '../../../hooks/usePermission';
+import { SystemNotification } from './SystemNotification';
import { AllMessagesNotifications } from './AllMessages';
import { SpecialMessagesNotifications } from './SpecialMessages';
import { KeywordMessagesNotifications } from './KeywordMessages';
import { IgnoredUserList } from './IgnoredUserList';
-function SystemNotification() {
- const notifPermission = usePermissionState('notifications', getNotificationState());
- const [showNotifications, setShowNotifications] = useSetting(settingsAtom, 'showNotifications');
- const [isNotificationSounds, setIsNotificationSounds] = useSetting(
- settingsAtom,
- 'isNotificationSounds'
- );
-
- const requestNotificationPermission = () => {
- window.Notification.requestPermission();
- };
-
- return (
-
- System
-
-
- {'Notification' in window
- ? 'Notification permission is blocked. Please allow notification permission from browser address bar.'
- : 'Notifications are not supported by the system.'}
-
- ) : (
- Show desktop notifications when message arrive.
- )
- }
- after={
- notifPermission === 'prompt' ? (
-
- ) : (
-
- )
- }
- />
-
-
- }
- />
-
-
- );
-}
-
type NotificationsProps = {
requestClose: () => void;
};
diff --git a/src/app/features/settings/notifications/SystemNotification.tsx b/src/app/features/settings/notifications/SystemNotification.tsx
new file mode 100644
index 000000000..e112765e9
--- /dev/null
+++ b/src/app/features/settings/notifications/SystemNotification.tsx
@@ -0,0 +1,73 @@
+import React from 'react';
+import { Box, Text, Switch, Button, color } from 'folds';
+import { SequenceCard } from '../../../components/sequence-card';
+import { SequenceCardStyle } from '../styles.css';
+import { SettingTile } from '../../../components/setting-tile';
+import { useSetting } from '../../../state/hooks/settings';
+import { settingsAtom } from '../../../state/settings';
+import { getNotificationState, usePermissionState } from '../../../hooks/usePermission';
+
+export function SystemNotification() {
+ const notifPermission = usePermissionState('notifications', getNotificationState());
+ const [showNotifications, setShowNotifications] = useSetting(settingsAtom, 'showNotifications');
+ const [isNotificationSounds, setIsNotificationSounds] = useSetting(
+ settingsAtom,
+ 'isNotificationSounds'
+ );
+
+ const requestNotificationPermission = () => {
+ window.Notification.requestPermission();
+ };
+
+ return (
+
+ System
+
+
+ {'Notification' in window
+ ? 'Notification permission is blocked. Please allow notification permission from browser address bar.'
+ : 'Notifications are not supported by the system.'}
+
+ ) : (
+ Show desktop notifications when message arrive.
+ )
+ }
+ after={
+ notifPermission === 'prompt' ? (
+
+ ) : (
+
+ )
+ }
+ />
+
+
+ }
+ />
+
+
+ );
+}
From 071ad585edc53f553a21adc6f6caf1247dd9b130 Mon Sep 17 00:00:00 2001
From: Ajay Bura <32841439+ajbura@users.noreply.github.com>
Date: Fri, 21 Feb 2025 09:48:22 +0530
Subject: [PATCH 2/3] add hook for email notification status
---
src/app/hooks/useEmailNotifications.ts | 55 ++++++++++++++++++++++++++
1 file changed, 55 insertions(+)
create mode 100644 src/app/hooks/useEmailNotifications.ts
diff --git a/src/app/hooks/useEmailNotifications.ts b/src/app/hooks/useEmailNotifications.ts
new file mode 100644
index 000000000..58639394b
--- /dev/null
+++ b/src/app/hooks/useEmailNotifications.ts
@@ -0,0 +1,55 @@
+import { useCallback } from 'react';
+import { AsyncStatus, useAsyncCallbackValue } from './useAsyncCallback';
+import { useMatrixClient } from './useMatrixClient';
+
+type RefreshHandler = () => void;
+
+type EmailNotificationResult = {
+ enabled: boolean;
+ email?: string;
+};
+
+export const useEmailNotifications = (): [
+ EmailNotificationResult | undefined | null,
+ RefreshHandler
+] => {
+ const mx = useMatrixClient();
+
+ const [emailState, refresh] = useAsyncCallbackValue(
+ useCallback(async () => {
+ const tpIDs = (await mx.getThreePids())?.threepids;
+ const emailAddresses = tpIDs.filter((id) => id.medium === 'email').map((id) => id.address);
+ if (emailAddresses.length === 0)
+ return {
+ enabled: false,
+ };
+
+ const pushers = (await mx.getPushers())?.pushers;
+ const emailPusher = pushers.find(
+ (pusher) => pusher.app_id === 'm.email' && emailAddresses.includes(pusher.pushkey)
+ );
+
+ if (emailPusher?.pushkey) {
+ return {
+ enabled: true,
+ email: emailPusher.pushkey,
+ };
+ }
+
+ return {
+ enabled: false,
+ email: emailAddresses[0],
+ };
+ }, [mx])
+ );
+
+ if (emailState.status === AsyncStatus.Success) {
+ return [emailState.data, refresh];
+ }
+
+ if (emailState.status === AsyncStatus.Error) {
+ return [null, refresh];
+ }
+
+ return [undefined, refresh];
+};
From 0001d10a200472206355cd85c2524f3cd2d3af01 Mon Sep 17 00:00:00 2001
From: Ajay Bura <32841439+ajbura@users.noreply.github.com>
Date: Fri, 21 Feb 2025 09:48:44 +0530
Subject: [PATCH 3/3] add toogle for email notifications in settings
---
.../notifications/SystemNotification.tsx | 89 ++++++++++++++++++-
1 file changed, 87 insertions(+), 2 deletions(-)
diff --git a/src/app/features/settings/notifications/SystemNotification.tsx b/src/app/features/settings/notifications/SystemNotification.tsx
index e112765e9..e0df06df9 100644
--- a/src/app/features/settings/notifications/SystemNotification.tsx
+++ b/src/app/features/settings/notifications/SystemNotification.tsx
@@ -1,11 +1,88 @@
-import React from 'react';
-import { Box, Text, Switch, Button, color } from 'folds';
+import React, { useCallback } from 'react';
+import { Box, Text, Switch, Button, color, Spinner } from 'folds';
+import { IPusherRequest } from 'matrix-js-sdk';
import { SequenceCard } from '../../../components/sequence-card';
import { SequenceCardStyle } from '../styles.css';
import { SettingTile } from '../../../components/setting-tile';
import { useSetting } from '../../../state/hooks/settings';
import { settingsAtom } from '../../../state/settings';
import { getNotificationState, usePermissionState } from '../../../hooks/usePermission';
+import { useEmailNotifications } from '../../../hooks/useEmailNotifications';
+import { AsyncStatus, useAsyncCallback } from '../../../hooks/useAsyncCallback';
+import { useMatrixClient } from '../../../hooks/useMatrixClient';
+
+function EmailNotification() {
+ const mx = useMatrixClient();
+ const [result, refreshResult] = useEmailNotifications();
+
+ const [setState, setEnable] = useAsyncCallback(
+ useCallback(
+ async (email: string, enable: boolean) => {
+ if (enable) {
+ await mx.setPusher({
+ kind: 'email',
+ app_id: 'm.email',
+ pushkey: email,
+ app_display_name: 'Email Notifications',
+ device_display_name: email,
+ lang: 'en',
+ data: {
+ brand: 'Cinny',
+ },
+ append: true,
+ });
+ return;
+ }
+ await mx.setPusher({
+ pushkey: email,
+ app_id: 'm.email',
+ kind: null,
+ } as unknown as IPusherRequest);
+ },
+ [mx]
+ )
+ );
+
+ const handleChange = (value: boolean) => {
+ if (result && result.email) {
+ setEnable(result.email, value).then(() => {
+ refreshResult();
+ });
+ }
+ };
+
+ return (
+
+ {result && !result.email && (
+
+ Your account does not have any email attached.
+
+ )}
+ {result && result.email && <>Send notification to your email. {`("${result.email}")`}>}
+ {result === null && (
+
+ Unexpected Error!
+
+ )}
+ {result === undefined && 'Send notification to your email.'}
+ >
+ }
+ after={
+ <>
+ {setState.status !== AsyncStatus.Loading &&
+ typeof result === 'object' &&
+ result?.email && }
+ {(setState.status === AsyncStatus.Loading || result === undefined) && (
+
+ )}
+ >
+ }
+ />
+ );
+}
export function SystemNotification() {
const notifPermission = usePermissionState('notifications', getNotificationState());
@@ -68,6 +145,14 @@ export function SystemNotification() {
after={}
/>
+
+
+
);
}