diff --git a/src/app/molecules/room-notification/RoomNotification.jsx b/src/app/molecules/room-notification/RoomNotification.jsx
index 5d118632..26d123bc 100644
--- a/src/app/molecules/room-notification/RoomNotification.jsx
+++ b/src/app/molecules/room-notification/RoomNotification.jsx
@@ -32,28 +32,9 @@ const items = [{
   type: cons.notifs.MUTE,
 }];
 
-function getNotifType(roomId) {
-  const mx = initMatrix.matrixClient;
-  const pushRule = mx.getRoomPushRule('global', roomId);
-
-  if (typeof pushRule === 'undefined') {
-    const overridePushRules = mx.getAccountData('m.push_rules')?.getContent()?.global?.override;
-    if (typeof overridePushRules === 'undefined') return 0;
-
-    const isMuteOverride = overridePushRules.find((rule) => (
-      rule.rule_id === roomId
-      && rule.actions[0] === 'dont_notify'
-      && rule.conditions[0].kind === 'event_match'
-    ));
-
-    return isMuteOverride ? cons.notifs.MUTE : cons.notifs.DEFAULT;
-  }
-  if (pushRule.actions[0] === 'notify') return cons.notifs.ALL_MESSAGES;
-  return cons.notifs.MENTIONS_AND_KEYWORDS;
-}
-
 function setRoomNotifType(roomId, newType) {
   const mx = initMatrix.matrixClient;
+  const { notifications } = initMatrix;
   const roomPushRule = mx.getRoomPushRule('global', roomId);
   const promises = [];
 
@@ -76,7 +57,7 @@ function setRoomNotifType(roomId, newType) {
     return promises;
   }
 
-  const oldState = getNotifType(roomId);
+  const oldState = notifications.getNotiType(roomId);
   if (oldState === cons.notifs.MUTE) {
     promises.push(mx.deletePushRule('global', 'override', roomId));
   }
@@ -115,8 +96,9 @@ function setRoomNotifType(roomId, newType) {
 }
 
 function useNotifications(roomId) {
-  const [activeType, setActiveType] = useState(getNotifType(roomId));
-  useEffect(() => setActiveType(getNotifType(roomId)), [roomId]);
+  const { notifications } = initMatrix;
+  const [activeType, setActiveType] = useState(notifications.getNotiType(roomId));
+  useEffect(() => setActiveType(notifications.getNotiType(roomId)), [roomId]);
 
   const setNotification = useCallback((item) => {
     if (item.type === activeType.type) return;
diff --git a/src/app/molecules/room-selector/RoomSelector.jsx b/src/app/molecules/room-selector/RoomSelector.jsx
index 8bd6c207..fa6daa9e 100644
--- a/src/app/molecules/room-selector/RoomSelector.jsx
+++ b/src/app/molecules/room-selector/RoomSelector.jsx
@@ -11,13 +11,16 @@ import NotificationBadge from '../../atoms/badge/NotificationBadge';
 import { blurOnBubbling } from '../../atoms/button/script';
 
 function RoomSelectorWrapper({
-  isSelected, isUnread, onClick,
+  isSelected, isMuted, isUnread, onClick,
   content, options, onContextMenu,
 }) {
-  let myClass = isUnread ? ' room-selector--unread' : '';
-  myClass += isSelected ? ' room-selector--selected' : '';
+  const classes = ['room-selector'];
+  if (isMuted) classes.push('room-selector--muted');
+  if (isUnread) classes.push('room-selector--unread');
+  if (isSelected) classes.push('room-selector--selected');
+
   return (
-    <div className={`room-selector${myClass}`}>
+    <div className={classes.join(' ')}>
       <button
         className="room-selector__content"
         type="button"
@@ -32,11 +35,13 @@ function RoomSelectorWrapper({
   );
 }
 RoomSelectorWrapper.defaultProps = {
+  isMuted: false,
   options: null,
   onContextMenu: null,
 };
 RoomSelectorWrapper.propTypes = {
   isSelected: PropTypes.bool.isRequired,
+  isMuted: PropTypes.bool,
   isUnread: PropTypes.bool.isRequired,
   onClick: PropTypes.func.isRequired,
   content: PropTypes.node.isRequired,
@@ -46,12 +51,13 @@ RoomSelectorWrapper.propTypes = {
 
 function RoomSelector({
   name, parentName, roomId, imageSrc, iconSrc,
-  isSelected, isUnread, notificationCount, isAlert,
+  isSelected, isMuted, isUnread, notificationCount, isAlert,
   options, onClick, onContextMenu,
 }) {
   return (
     <RoomSelectorWrapper
       isSelected={isSelected}
+      isMuted={isMuted}
       isUnread={isUnread}
       content={(
         <>
@@ -91,6 +97,7 @@ RoomSelector.defaultProps = {
   isSelected: false,
   imageSrc: null,
   iconSrc: null,
+  isMuted: false,
   options: null,
   onContextMenu: null,
 };
@@ -101,6 +108,7 @@ RoomSelector.propTypes = {
   imageSrc: PropTypes.string,
   iconSrc: PropTypes.string,
   isSelected: PropTypes.bool,
+  isMuted: PropTypes.bool,
   isUnread: PropTypes.bool.isRequired,
   notificationCount: PropTypes.oneOfType([
     PropTypes.string,
diff --git a/src/app/molecules/room-selector/RoomSelector.scss b/src/app/molecules/room-selector/RoomSelector.scss
index 7ee8a3a2..59e47473 100644
--- a/src/app/molecules/room-selector/RoomSelector.scss
+++ b/src/app/molecules/room-selector/RoomSelector.scss
@@ -9,6 +9,10 @@
   border-radius: var(--bo-radius);
   cursor: pointer;
 
+  &--muted {
+    opacity: 0.6;
+  }
+
   &--unread {
     .room-selector__content > .text {
       color: var(--tc-surface-high);
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/app/organisms/navigation/RoomsCategory.jsx b/src/app/organisms/navigation/RoomsCategory.jsx
index f31e72f6..b5666512 100644
--- a/src/app/organisms/navigation/RoomsCategory.jsx
+++ b/src/app/organisms/navigation/RoomsCategory.jsx
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
 import './RoomsCategory.scss';
 
 import initMatrix from '../../../client/initMatrix';
-import { selectSpace, selectRoom,openReusableContextMenu } from '../../../client/action/navigation';
+import { selectSpace, selectRoom, openReusableContextMenu } from '../../../client/action/navigation';
 import { getEventCords } from '../../../util/common';
 
 import Text from '../../atoms/text/Text';
diff --git a/src/app/organisms/navigation/Selector.jsx b/src/app/organisms/navigation/Selector.jsx
index 56e57c57..cb1086ea 100644
--- a/src/app/organisms/navigation/Selector.jsx
+++ b/src/app/organisms/navigation/Selector.jsx
@@ -3,6 +3,7 @@ import React, { useEffect } from 'react';
 import PropTypes from 'prop-types';
 
 import initMatrix from '../../../client/initMatrix';
+import cons from '../../../client/state/cons';
 import navigation from '../../../client/state/navigation';
 import { openReusableContextMenu } from '../../../client/action/navigation';
 import { getEventCords, abbreviateNumber } from '../../../util/common';
@@ -23,9 +24,12 @@ function Selector({
   const mx = initMatrix.matrixClient;
   const noti = initMatrix.notifications;
   const room = mx.getRoom(roomId);
+
   let imageSrc = room.getAvatarFallbackMember()?.getAvatarUrl(mx.baseUrl, 24, 24, 'crop') || null;
   if (imageSrc === null) imageSrc = room.getAvatarUrl(mx.baseUrl, 24, 24, 'crop') || null;
 
+  const isMuted = noti.getNotiType(roomId) === cons.notifs.MUTE;
+
   const [, forceUpdate] = useForceUpdate();
 
   useEffect(() => {
@@ -56,7 +60,8 @@ function Selector({
       imageSrc={isDM ? imageSrc : null}
       iconSrc={isDM ? null : joinRuleToIconSrc(room.getJoinRule(), room.isSpaceRoom())}
       isSelected={navigation.selectedRoomId === roomId}
-      isUnread={noti.hasNoti(roomId)}
+      isMuted={isMuted}
+      isUnread={!isMuted && noti.hasNoti(roomId)}
       notificationCount={abbreviateNumber(noti.getTotalNoti(roomId))}
       isAlert={noti.getHighlightNoti(roomId) !== 0}
       onClick={onClick}
diff --git a/src/client/state/Notifications.js b/src/client/state/Notifications.js
index 8ede1696..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();
@@ -39,7 +50,9 @@ class Notifications extends EventEmitter {
   _initNoti() {
     const addNoti = (roomId) => {
       const room = this.matrixClient.getRoom(roomId);
+      if (this.getNotiType(room.roomId) === cons.notifs.MUTE) return;
       if (this.doesRoomHaveUnread(room) === false) return;
+
       const total = room.getUnreadNotificationCount('total');
       const highlight = room.getUnreadNotificationCount('highlight');
       this._setNoti(room.roomId, total ?? 0, highlight ?? 0);
@@ -65,6 +78,22 @@ class Notifications extends EventEmitter {
     return true;
   }
 
+  getNotiType(roomId) {
+    const mx = this.matrixClient;
+    const pushRule = mx.getRoomPushRule('global', roomId);
+
+    if (pushRule === undefined) {
+      const overrideRules = mx.getAccountData('m.push_rules')?.getContent()?.global?.override;
+      if (overrideRules === undefined) return cons.notifs.DEFAULT;
+
+      const isMuted = findMutedRule(overrideRules, roomId);
+
+      return isMuted ? cons.notifs.MUTE : cons.notifs.DEFAULT;
+    }
+    if (pushRule.actions[0] === 'notify') return cons.notifs.ALL_MESSAGES;
+    return cons.notifs.MENTIONS_AND_KEYWORDS;
+  }
+
   getNoti(roomId) {
     return this.roomIdToNoti.get(roomId) || { total: 0, highlight: 0, from: null };
   }
@@ -195,6 +224,7 @@ class Notifications extends EventEmitter {
     this.matrixClient.on('Room.timeline', (mEvent, room) => {
       if (room.isSpaceRoom()) return;
       if (!isNotifEvent(mEvent)) return;
+
       const liveEvents = room.getLiveTimeline().getEvents();
 
       const lastTimelineEvent = liveEvents[liveEvents.length - 1];
@@ -204,6 +234,11 @@ class Notifications extends EventEmitter {
       const total = room.getUnreadNotificationCount('total');
       const highlight = room.getUnreadNotificationCount('highlight');
 
+      if (this.getNotiType(room.roomId) === cons.notifs.MUTE) {
+        this.deleteNoti(room.roomId, total ?? 0, highlight ?? 0);
+        return;
+      }
+
       this._setNoti(room.roomId, total ?? 0, highlight ?? 0);
 
       if (this.matrixClient.getSyncState() === 'SYNCING') {
@@ -211,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',