mirror of
				https://github.com/cinnyapp/cinny.git
				synced 2025-11-04 06:20:28 +03:00 
			
		
		
		
	Notification sounds (#367)
* Basic notification sound support * Add settings option for notification sounds * Allow sound without desktop notifications
This commit is contained in:
		
							parent
							
								
									a2655ee6a5
								
							
						
					
					
						commit
						dc6e153b92
					
				
					 7 changed files with 78 additions and 24 deletions
				
			
		
							
								
								
									
										
											BIN
										
									
								
								public/sound/notification.ogg
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								public/sound/notification.ogg
									
										
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
						 | 
				
			
			@ -7,7 +7,7 @@ import cons from '../../../client/state/cons';
 | 
			
		|||
import settings from '../../../client/state/settings';
 | 
			
		||||
import {
 | 
			
		||||
  toggleSystemTheme, toggleMarkdown, toggleMembershipEvents, toggleNickAvatarEvents,
 | 
			
		||||
  toggleNotifications,
 | 
			
		||||
  toggleNotifications, toggleNotificationSounds,
 | 
			
		||||
} from '../../../client/action/settings';
 | 
			
		||||
import logout from '../../../client/action/logout';
 | 
			
		||||
import { usePermission } from '../../hooks/usePermission';
 | 
			
		||||
| 
						 | 
				
			
			@ -158,6 +158,16 @@ function NotificationsSection() {
 | 
			
		|||
        options={renderOptions()}
 | 
			
		||||
        content={<Text variant="b3">Show notifications when new messages arrive.</Text>}
 | 
			
		||||
      />
 | 
			
		||||
      <SettingTile
 | 
			
		||||
        title="Play notification sounds"
 | 
			
		||||
        options={(
 | 
			
		||||
          <Toggle
 | 
			
		||||
            isActive={settings.isNotificationSounds}
 | 
			
		||||
            onToggle={() => { toggleNotificationSounds(); updateState({}); }}
 | 
			
		||||
          />
 | 
			
		||||
          )}
 | 
			
		||||
        content={<Text variant="b3">Play a sound when new messages arrive.</Text>}
 | 
			
		||||
      />
 | 
			
		||||
    </div>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -200,7 +210,7 @@ function AboutSection() {
 | 
			
		|||
      <div className="set-about__branding">
 | 
			
		||||
        <img width="60" height="60" src={CinnySVG} alt="Cinny logo" />
 | 
			
		||||
        <div>
 | 
			
		||||
          <Text variant="h2" weight='medium'>
 | 
			
		||||
          <Text variant="h2" weight="medium">
 | 
			
		||||
            Cinny
 | 
			
		||||
            <span className="text text-b3" style={{ margin: '0 var(--sp-extra-tight)' }}>{`v${cons.version}`}</span>
 | 
			
		||||
          </Text>
 | 
			
		||||
| 
						 | 
				
			
			@ -223,6 +233,10 @@ function AboutSection() {
 | 
			
		|||
            {/* eslint-disable-next-line react/jsx-one-expression-per-line */ }
 | 
			
		||||
            <Text>The <a href="https://twemoji.twitter.com" target="_blank" rel="noreferrer noopener">Twemoji</a> emoji art is © <a href="https://twemoji.twitter.com" target="_blank" rel="noreferrer noopener">Twitter, Inc and other contributors</a> used under the terms of <a href="https://creativecommons.org/licenses/by/4.0/" target="_blank" rel="noreferrer noopener">CC-BY 4.0</a>.</Text>
 | 
			
		||||
          </li>
 | 
			
		||||
          <li>
 | 
			
		||||
            {/* eslint-disable-next-line react/jsx-one-expression-per-line */ }
 | 
			
		||||
            <Text>The <a href="https://material.io/design/sound/sound-resources.html" target="_blank" rel="noreferrer noopener">Material sound resources</a> are © <a href="https://google.com" target="_blank" rel="noreferrer noopener">Google</a> used under the terms of <a href="https://creativecommons.org/licenses/by/4.0/" target="_blank" rel="noreferrer noopener">CC-BY 4.0</a>.</Text>
 | 
			
		||||
          </li>
 | 
			
		||||
        </ul>
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -36,3 +36,9 @@ export function toggleNotifications() {
 | 
			
		|||
    type: cons.actions.settings.TOGGLE_NOTIFICATIONS,
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function toggleNotificationSounds() {
 | 
			
		||||
  appDispatcher.dispatch({
 | 
			
		||||
    type: cons.actions.settings.TOGGLE_NOTIFICATION_SOUNDS,
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,6 +6,8 @@ import cons from './cons';
 | 
			
		|||
import navigation from './navigation';
 | 
			
		||||
import settings from './settings';
 | 
			
		||||
 | 
			
		||||
import NotificationSound from '../../../public/sound/notification.ogg';
 | 
			
		||||
 | 
			
		||||
function isNotifEvent(mEvent) {
 | 
			
		||||
  const eType = mEvent.getType();
 | 
			
		||||
  if (!cons.supportEventTypes.includes(eType)) return false;
 | 
			
		||||
| 
						 | 
				
			
			@ -185,7 +187,7 @@ class Notifications extends EventEmitter {
 | 
			
		|||
  }
 | 
			
		||||
 | 
			
		||||
  async _displayPopupNoti(mEvent, room) {
 | 
			
		||||
    if (!settings.showNotifications) return;
 | 
			
		||||
    if (!settings.showNotifications && !settings.isNotificationSounds) return;
 | 
			
		||||
 | 
			
		||||
    const actions = this.matrixClient.getPushActionsForEvent(mEvent);
 | 
			
		||||
    if (!actions?.notify) return;
 | 
			
		||||
| 
						 | 
				
			
			@ -196,28 +198,43 @@ class Notifications extends EventEmitter {
 | 
			
		|||
      await mEvent.attemptDecryption(this.matrixClient.crypto);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let title;
 | 
			
		||||
    if (!mEvent.sender || room.name === mEvent.sender.name) {
 | 
			
		||||
      title = room.name;
 | 
			
		||||
    } else if (mEvent.sender) {
 | 
			
		||||
      title = `${mEvent.sender.name} (${room.name})`;
 | 
			
		||||
    if (settings.showNotifications) {
 | 
			
		||||
      let title;
 | 
			
		||||
      if (!mEvent.sender || room.name === mEvent.sender.name) {
 | 
			
		||||
        title = room.name;
 | 
			
		||||
      } else if (mEvent.sender) {
 | 
			
		||||
        title = `${mEvent.sender.name} (${room.name})`;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      const iconSize = 36;
 | 
			
		||||
      const icon = await renderAvatar({
 | 
			
		||||
        text: mEvent.sender.name,
 | 
			
		||||
        bgColor: cssColorMXID(mEvent.getSender()),
 | 
			
		||||
        imageSrc: mEvent.sender?.getAvatarUrl(this.matrixClient.baseUrl, iconSize, iconSize, 'crop'),
 | 
			
		||||
        size: iconSize,
 | 
			
		||||
        borderRadius: 8,
 | 
			
		||||
        scale: 8,
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      const noti = new window.Notification(title, {
 | 
			
		||||
        body: mEvent.getContent().body,
 | 
			
		||||
        icon,
 | 
			
		||||
        silent: settings.isNotificationSounds,
 | 
			
		||||
      });
 | 
			
		||||
      if (settings.isNotificationSounds) {
 | 
			
		||||
        noti.onshow = () => this._playNotiSounds();
 | 
			
		||||
      }
 | 
			
		||||
      noti.onclick = () => selectRoom(room.roomId, mEvent.getId());
 | 
			
		||||
    } else {
 | 
			
		||||
      this._playNotiSounds();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    const iconSize = 36;
 | 
			
		||||
    const icon = await renderAvatar({
 | 
			
		||||
      text: mEvent.sender.name,
 | 
			
		||||
      bgColor: cssColorMXID(mEvent.getSender()),
 | 
			
		||||
      imageSrc: mEvent.sender?.getAvatarUrl(this.matrixClient.baseUrl, iconSize, iconSize, 'crop'),
 | 
			
		||||
      size: iconSize,
 | 
			
		||||
      borderRadius: 8,
 | 
			
		||||
      scale: 8,
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    const noti = new window.Notification(title, {
 | 
			
		||||
      body: mEvent.getContent().body,
 | 
			
		||||
      icon,
 | 
			
		||||
    });
 | 
			
		||||
    noti.onclick = () => selectRoom(room.roomId, mEvent.getId());
 | 
			
		||||
  _playNotiSounds() {
 | 
			
		||||
    if (!this._notiAudio) {
 | 
			
		||||
      this._notiAudio = new Audio(NotificationSound);
 | 
			
		||||
    }
 | 
			
		||||
    this._notiAudio.play();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  _listenEvents() {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -67,6 +67,7 @@ const cons = {
 | 
			
		|||
      TOGGLE_MEMBERSHIP_EVENT: 'TOGGLE_MEMBERSHIP_EVENT',
 | 
			
		||||
      TOGGLE_NICKAVATAR_EVENT: 'TOGGLE_NICKAVATAR_EVENT',
 | 
			
		||||
      TOGGLE_NOTIFICATIONS: 'TOGGLE_NOTIFICATIONS',
 | 
			
		||||
      TOGGLE_NOTIFICATION_SOUNDS: 'TOGGLE_NOTIFICATION_SOUNDS',
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
  events: {
 | 
			
		||||
| 
						 | 
				
			
			@ -135,6 +136,7 @@ const cons = {
 | 
			
		|||
      MEMBERSHIP_EVENTS_TOGGLED: 'MEMBERSHIP_EVENTS_TOGGLED',
 | 
			
		||||
      NICKAVATAR_EVENTS_TOGGLED: 'NICKAVATAR_EVENTS_TOGGLED',
 | 
			
		||||
      NOTIFICATIONS_TOGGLED: 'NOTIFICATIONS_TOGGLED',
 | 
			
		||||
      NOTIFICATION_SOUNDS_TOGGLED: 'NOTIFICATION_SOUNDS_TOGGLED',
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -29,6 +29,7 @@ class Settings extends EventEmitter {
 | 
			
		|||
    this.hideMembershipEvents = this.getHideMembershipEvents();
 | 
			
		||||
    this.hideNickAvatarEvents = this.getHideNickAvatarEvents();
 | 
			
		||||
    this._showNotifications = this.getShowNotifications();
 | 
			
		||||
    this.isNotificationSounds = this.getIsNotificationSounds();
 | 
			
		||||
 | 
			
		||||
    this.isTouchScreenDevice = ('ontouchstart' in window) || (navigator.maxTouchPoints > 0) || (navigator.msMaxTouchPoints > 0);
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -125,6 +126,15 @@ class Settings extends EventEmitter {
 | 
			
		|||
    return settings.showNotifications;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  getIsNotificationSounds() {
 | 
			
		||||
    if (typeof this.isNotificationSounds === 'boolean') return this.isNotificationSounds;
 | 
			
		||||
 | 
			
		||||
    const settings = getSettings();
 | 
			
		||||
    if (settings === null) return true;
 | 
			
		||||
    if (typeof settings.isNotificationSounds === 'undefined') return true;
 | 
			
		||||
    return settings.isNotificationSounds;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  setter(action) {
 | 
			
		||||
    const actions = {
 | 
			
		||||
      [cons.actions.settings.TOGGLE_SYSTEM_THEME]: () => {
 | 
			
		||||
| 
						 | 
				
			
			@ -164,6 +174,11 @@ class Settings extends EventEmitter {
 | 
			
		|||
        setSettings('showNotifications', this._showNotifications);
 | 
			
		||||
        this.emit(cons.events.settings.NOTIFICATIONS_TOGGLED, this._showNotifications);
 | 
			
		||||
      },
 | 
			
		||||
      [cons.actions.settings.TOGGLE_NOTIFICATION_SOUNDS]: () => {
 | 
			
		||||
        this.isNotificationSounds = !this.isNotificationSounds;
 | 
			
		||||
        setSettings('isNotificationSounds', this.isNotificationSounds);
 | 
			
		||||
        this.emit(cons.events.settings.NOTIFICATION_SOUNDS_TOGGLED, this.isNotificationSounds);
 | 
			
		||||
      },
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    actions[action.type]?.();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -39,7 +39,7 @@ module.exports = {
 | 
			
		|||
        use: ['html-loader'],
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        test: /\.(png|jpe?g|gif|otf|ttf|woff|woff2)$/,
 | 
			
		||||
        test: /\.(png|jpe?g|gif|otf|ttf|woff|woff2|ogg)$/,
 | 
			
		||||
        type: 'asset/resource',
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue