From bc9006f2c0446e4e3c1d623bdbe3474430e1f712 Mon Sep 17 00:00:00 2001
From: Ajay Bura <ajbura@gmail.com>
Date: Tue, 15 Mar 2022 15:22:03 +0530
Subject: [PATCH] Toggle room mute when changed from other client

Signed-off-by: Ajay Bura <ajbura@gmail.com>
---
 src/app/organisms/navigation/Directs.jsx |  2 +
 src/app/organisms/navigation/Home.jsx    |  2 +
 src/client/state/Notifications.js        | 60 ++++++++++++++++++++----
 src/client/state/cons.js                 |  1 +
 4 files changed, 57 insertions(+), 8 deletions(-)

diff --git a/src/app/organisms/navigation/Directs.jsx b/src/app/organisms/navigation/Directs.jsx
index 49244bc3..61313479 100644
--- a/src/app/organisms/navigation/Directs.jsx
+++ b/src/app/organisms/navigation/Directs.jsx
@@ -33,9 +33,11 @@ function Directs() {
 
     navigation.on(cons.events.navigation.ROOM_SELECTED, selectorChanged);
     notifications.on(cons.events.notifications.NOTI_CHANGED, notiChanged);
+    notifications.on(cons.events.notifications.MUTE_TOGGLED, notiChanged);
     return () => {
       navigation.removeListener(cons.events.navigation.ROOM_SELECTED, selectorChanged);
       notifications.removeListener(cons.events.notifications.NOTI_CHANGED, notiChanged);
+      notifications.removeListener(cons.events.notifications.MUTE_TOGGLED, notiChanged);
     };
   }, []);
 
diff --git a/src/app/organisms/navigation/Home.jsx b/src/app/organisms/navigation/Home.jsx
index c52ead49..35e43a97 100644
--- a/src/app/organisms/navigation/Home.jsx
+++ b/src/app/organisms/navigation/Home.jsx
@@ -62,9 +62,11 @@ function Home({ spaceId }) {
 
     navigation.on(cons.events.navigation.ROOM_SELECTED, selectorChanged);
     notifications.on(cons.events.notifications.NOTI_CHANGED, notiChanged);
+    notifications.on(cons.events.notifications.MUTE_TOGGLED, notiChanged);
     return () => {
       navigation.removeListener(cons.events.navigation.ROOM_SELECTED, selectorChanged);
       notifications.removeListener(cons.events.notifications.NOTI_CHANGED, notiChanged);
+      notifications.removeListener(cons.events.notifications.MUTE_TOGGLED, notiChanged);
     };
   }, []);
 
diff --git a/src/client/state/Notifications.js b/src/client/state/Notifications.js
index b394b787..11fd665e 100644
--- a/src/client/state/Notifications.js
+++ b/src/client/state/Notifications.js
@@ -17,6 +17,17 @@ function isNotifEvent(mEvent) {
   return true;
 }
 
+function isMutedRule(rule) {
+  return rule.actions[0] === 'dont_notify' && rule.conditions[0].kind === 'event_match';
+}
+
+function findMutedRule(overrideRules, roomId) {
+  return overrideRules.find((rule) => (
+    rule.rule_id === roomId
+    && isMutedRule(rule)
+  ));
+}
+
 class Notifications extends EventEmitter {
   constructor(roomList) {
     super();
@@ -72,16 +83,12 @@ class Notifications extends EventEmitter {
     const pushRule = mx.getRoomPushRule('global', roomId);
 
     if (pushRule === undefined) {
-      const overridePushRules = mx.getAccountData('m.push_rules')?.getContent()?.global?.override;
-      if (overridePushRules === undefined) return cons.notifs.DEFAULT;
+      const overrideRules = mx.getAccountData('m.push_rules')?.getContent()?.global?.override;
+      if (overrideRules === undefined) return cons.notifs.DEFAULT;
 
-      const isMuteOverride = overridePushRules.find((rule) => (
-        rule.rule_id === roomId
-        && rule.actions[0] === 'dont_notify'
-        && rule.conditions[0].kind === 'event_match'
-      ));
+      const isMuted = findMutedRule(overrideRules, roomId);
 
-      return isMuteOverride ? cons.notifs.MUTE : cons.notifs.DEFAULT;
+      return isMuted ? cons.notifs.MUTE : cons.notifs.DEFAULT;
     }
     if (pushRule.actions[0] === 'notify') return cons.notifs.ALL_MESSAGES;
     return cons.notifs.MENTIONS_AND_KEYWORDS;
@@ -239,6 +246,43 @@ class Notifications extends EventEmitter {
       }
     });
 
+    this.matrixClient.on('accountData', (mEvent, oldMEvent) => {
+      if (mEvent.getType() === 'm.push_rules') {
+        const override = mEvent?.getContent()?.global?.override;
+        const oldOverride = oldMEvent?.getContent()?.global?.override;
+        if (!override || !oldOverride) return;
+
+        const isMuteToggled = (rule, otherOverride) => {
+          const roomId = rule.rule_id;
+          const room = this.matrixClient.getRoom(roomId);
+          if (room === null) return false;
+          if (room.isSpaceRoom()) return false;
+
+          const isMuted = isMutedRule(rule);
+          if (!isMuted) return false;
+          const isOtherMuted = findMutedRule(otherOverride, roomId);
+          if (isOtherMuted) return false;
+          return true;
+        };
+
+        const mutedRules = override.filter((rule) => isMuteToggled(rule, oldOverride));
+        const unMutedRules = oldOverride.filter((rule) => isMuteToggled(rule, override));
+
+        mutedRules.forEach((rule) => {
+          this.emit(cons.events.notifications.MUTE_TOGGLED, rule.rule_id, true);
+          this.deleteNoti(rule.rule_id);
+        });
+        unMutedRules.forEach((rule) => {
+          this.emit(cons.events.notifications.MUTE_TOGGLED, rule.rule_id, false);
+          const room = this.matrixClient.getRoom(rule.rule_id);
+          if (!this.doesRoomHaveUnread(room)) return;
+          const total = room.getUnreadNotificationCount('total');
+          const highlight = room.getUnreadNotificationCount('highlight');
+          this._setNoti(room.roomId, total ?? 0, highlight ?? 0);
+        });
+      }
+    });
+
     this.matrixClient.on('Room.receipt', (mEvent, room) => {
       if (mEvent.getType() === 'm.receipt') {
         if (room.isSpaceRoom()) return;
diff --git a/src/client/state/cons.js b/src/client/state/cons.js
index 461b1892..c1f7f9ba 100644
--- a/src/client/state/cons.js
+++ b/src/client/state/cons.js
@@ -107,6 +107,7 @@ const cons = {
     notifications: {
       NOTI_CHANGED: 'NOTI_CHANGED',
       FULL_READ: 'FULL_READ',
+      MUTE_TOGGLED: 'MUTE_TOGGLED',
     },
     roomTimeline: {
       READY: 'READY',