Skip to content

Commit e6d6b03

Browse files
authored
Fix unread reset and notification settings (#1824)
* reset unread with client sync state change * fix notification toggle setting not working * revert formatOnSave vscode setting
1 parent e2228a1 commit e6d6b03

File tree

9 files changed

+62
-100
lines changed

9 files changed

+62
-100
lines changed

.eslintrc.cjs

+8
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,12 @@ module.exports = {
6161
"@typescript-eslint/no-unused-vars": "error",
6262
"@typescript-eslint/no-shadow": "error"
6363
},
64+
overrides: [
65+
{
66+
files: ['*.ts'],
67+
rules: {
68+
'no-undef': 'off',
69+
},
70+
},
71+
],
6472
};

src/app/hooks/usePermission.js

-28
This file was deleted.

src/app/hooks/usePermission.ts

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { useEffect, useState } from "react";
2+
3+
export function usePermissionState(name: PermissionName, initialValue: PermissionState = 'prompt') {
4+
const [permissionState, setPermissionState] = useState<PermissionState>(initialValue);
5+
6+
useEffect(() => {
7+
let permissionStatus: PermissionStatus;
8+
9+
function handlePermissionChange(this: PermissionStatus) {
10+
setPermissionState(this.state);
11+
}
12+
13+
navigator.permissions
14+
.query({ name })
15+
.then((permStatus: PermissionStatus) => {
16+
permissionStatus = permStatus;
17+
handlePermissionChange.apply(permStatus);
18+
permStatus.addEventListener("change", handlePermissionChange);
19+
})
20+
.catch(() => {
21+
// Silence error since FF doesn't support microphone permission
22+
});
23+
24+
return () => {
25+
permissionStatus?.removeEventListener("change", handlePermissionChange);
26+
};
27+
}, [name]);
28+
29+
return permissionState;
30+
}

src/app/organisms/settings/Settings.jsx

+16-13
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,8 @@ import settings from '../../../client/state/settings';
77
import navigation from '../../../client/state/navigation';
88
import {
99
toggleSystemTheme,
10-
toggleNotifications, toggleNotificationSounds,
1110
} from '../../../client/action/settings';
12-
import { usePermission } from '../../hooks/usePermission';
11+
import { usePermissionState } from '../../hooks/usePermission';
1312

1413
import Text from '../../atoms/text/Text';
1514
import IconButton from '../../atoms/button/IconButton';
@@ -230,23 +229,25 @@ function AppearanceSection() {
230229
}
231230

232231
function NotificationsSection() {
233-
const [permission, setPermission] = usePermission('notifications', window.Notification?.permission);
234-
235-
const [, updateState] = useState({});
232+
const notifPermission = usePermissionState('notifications', window.Notification?.permission ?? "denied");
233+
const [showNotifications, setShowNotifications] = useSetting(settingsAtom, 'showNotifications')
234+
const [isNotificationSounds, setIsNotificationSounds] = useSetting(settingsAtom, 'isNotificationSounds')
236235

237236
const renderOptions = () => {
238237
if (window.Notification === undefined) {
239238
return <Text className="settings-notifications__not-supported">Not supported in this browser.</Text>;
240239
}
241240

242-
if (permission === 'granted') {
241+
if (notifPermission === 'denied') {
242+
return <Text>Permission Denied</Text>
243+
}
244+
245+
if (notifPermission === 'granted') {
243246
return (
244247
<Toggle
245-
isActive={settings._showNotifications}
248+
isActive={showNotifications}
246249
onToggle={() => {
247-
toggleNotifications();
248-
setPermission(window.Notification?.permission);
249-
updateState({});
250+
setShowNotifications(!showNotifications);
250251
}}
251252
/>
252253
);
@@ -255,7 +256,9 @@ function NotificationsSection() {
255256
return (
256257
<Button
257258
variant="primary"
258-
onClick={() => window.Notification.requestPermission().then(setPermission)}
259+
onClick={() => window.Notification.requestPermission().then(() => {
260+
setShowNotifications(window.Notification?.permission === 'granted');
261+
})}
259262
>
260263
Request permission
261264
</Button>
@@ -275,8 +278,8 @@ function NotificationsSection() {
275278
title="Notification Sound"
276279
options={(
277280
<Toggle
278-
isActive={settings.isNotificationSounds}
279-
onToggle={() => { toggleNotificationSounds(); updateState({}); }}
281+
isActive={isNotificationSounds}
282+
onToggle={() => setIsNotificationSounds(!isNotificationSounds)}
280283
/>
281284
)}
282285
content={<Text variant="b3">Play sound when new messages arrive.</Text>}

src/app/pages/client/ClientNonUIFeatures.tsx

+3-2
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ function InviteNotifications() {
5858
const mx = useMatrixClient();
5959

6060
const navigate = useNavigate();
61+
const [showNotifications] = useSetting(settingsAtom, 'showNotifications');
6162
const [notificationSound] = useSetting(settingsAtom, 'isNotificationSounds');
6263

6364
const notify = useCallback(
@@ -84,15 +85,15 @@ function InviteNotifications() {
8485

8586
useEffect(() => {
8687
if (invites.length > perviousInviteLen && mx.getSyncState() === 'SYNCING') {
87-
if (Notification.permission === 'granted') {
88+
if (showNotifications && Notification.permission === 'granted') {
8889
notify(invites.length - perviousInviteLen);
8990
}
9091

9192
if (notificationSound) {
9293
playSound();
9394
}
9495
}
95-
}, [mx, invites, perviousInviteLen, notificationSound, notify, playSound]);
96+
}, [mx, invites, perviousInviteLen, showNotifications, notificationSound, notify, playSound]);
9697

9798
return (
9899
// eslint-disable-next-line jsx-a11y/media-has-caption

src/app/state/room/roomToUnread.ts

+5-2
Original file line numberDiff line numberDiff line change
@@ -185,8 +185,11 @@ export const useBindRoomToUnreadAtom = (
185185
useSyncState(
186186
mx,
187187
useCallback(
188-
(state) => {
189-
if (state === SyncState.Prepared) {
188+
(state, prevState) => {
189+
if (
190+
(state === SyncState.Prepared && prevState === null) ||
191+
(state === SyncState.Syncing && prevState !== SyncState.Syncing)
192+
) {
190193
setUnreadAtom({
191194
type: 'RESET',
192195
unreadInfos: getUnreadInfos(mx),

src/client/action/settings.js

-12
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,3 @@ export function toggleNickAvatarEvents() {
3030
type: cons.actions.settings.TOGGLE_NICKAVATAR_EVENT,
3131
});
3232
}
33-
34-
export function toggleNotifications() {
35-
appDispatcher.dispatch({
36-
type: cons.actions.settings.TOGGLE_NOTIFICATIONS,
37-
});
38-
}
39-
40-
export function toggleNotificationSounds() {
41-
appDispatcher.dispatch({
42-
type: cons.actions.settings.TOGGLE_NOTIFICATION_SOUNDS,
43-
});
44-
}

src/client/state/cons.js

-4
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,6 @@ const cons = {
5252
TOGGLE_PEOPLE_DRAWER: 'TOGGLE_PEOPLE_DRAWER',
5353
TOGGLE_MEMBERSHIP_EVENT: 'TOGGLE_MEMBERSHIP_EVENT',
5454
TOGGLE_NICKAVATAR_EVENT: 'TOGGLE_NICKAVATAR_EVENT',
55-
TOGGLE_NOTIFICATIONS: 'TOGGLE_NOTIFICATIONS',
56-
TOGGLE_NOTIFICATION_SOUNDS: 'TOGGLE_NOTIFICATION_SOUNDS',
5755
},
5856
},
5957
events: {
@@ -81,8 +79,6 @@ const cons = {
8179
PEOPLE_DRAWER_TOGGLED: 'PEOPLE_DRAWER_TOGGLED',
8280
MEMBERSHIP_EVENTS_TOGGLED: 'MEMBERSHIP_EVENTS_TOGGLED',
8381
NICKAVATAR_EVENTS_TOGGLED: 'NICKAVATAR_EVENTS_TOGGLED',
84-
NOTIFICATIONS_TOGGLED: 'NOTIFICATIONS_TOGGLED',
85-
NOTIFICATION_SOUNDS_TOGGLED: 'NOTIFICATION_SOUNDS_TOGGLED',
8682
},
8783
},
8884
};

src/client/state/settings.js

-39
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,6 @@ class Settings extends EventEmitter {
3333
this.isPeopleDrawer = this.getIsPeopleDrawer();
3434
this.hideMembershipEvents = this.getHideMembershipEvents();
3535
this.hideNickAvatarEvents = this.getHideNickAvatarEvents();
36-
this._showNotifications = this.getShowNotifications();
37-
this.isNotificationSounds = this.getIsNotificationSounds();
3836

3937
this.darkModeQueryList = window.matchMedia('(prefers-color-scheme: dark)');
4038

@@ -137,29 +135,6 @@ class Settings extends EventEmitter {
137135
return settings.isPeopleDrawer;
138136
}
139137

140-
get showNotifications() {
141-
if (window.Notification?.permission !== 'granted') return false;
142-
return this._showNotifications;
143-
}
144-
145-
getShowNotifications() {
146-
if (typeof this._showNotifications === 'boolean') return this._showNotifications;
147-
148-
const settings = getSettings();
149-
if (settings === null) return true;
150-
if (typeof settings.showNotifications === 'undefined') return true;
151-
return settings.showNotifications;
152-
}
153-
154-
getIsNotificationSounds() {
155-
if (typeof this.isNotificationSounds === 'boolean') return this.isNotificationSounds;
156-
157-
const settings = getSettings();
158-
if (settings === null) return true;
159-
if (typeof settings.isNotificationSounds === 'undefined') return true;
160-
return settings.isNotificationSounds;
161-
}
162-
163138
setter(action) {
164139
const actions = {
165140
[cons.actions.settings.TOGGLE_SYSTEM_THEME]: () => {
@@ -185,20 +160,6 @@ class Settings extends EventEmitter {
185160
setSettings('hideNickAvatarEvents', this.hideNickAvatarEvents);
186161
this.emit(cons.events.settings.NICKAVATAR_EVENTS_TOGGLED, this.hideNickAvatarEvents);
187162
},
188-
[cons.actions.settings.TOGGLE_NOTIFICATIONS]: async () => {
189-
if (window.Notification?.permission !== 'granted') {
190-
this._showNotifications = false;
191-
} else {
192-
this._showNotifications = !this._showNotifications;
193-
}
194-
setSettings('showNotifications', this._showNotifications);
195-
this.emit(cons.events.settings.NOTIFICATIONS_TOGGLED, this._showNotifications);
196-
},
197-
[cons.actions.settings.TOGGLE_NOTIFICATION_SOUNDS]: () => {
198-
this.isNotificationSounds = !this.isNotificationSounds;
199-
setSettings('isNotificationSounds', this.isNotificationSounds);
200-
this.emit(cons.events.settings.NOTIFICATION_SOUNDS_TOGGLED, this.isNotificationSounds);
201-
},
202163
};
203164

204165
actions[action.type]?.();

0 commit comments

Comments
 (0)