Notifications: Play sound when notifications are turned off (#1553)

This commit is contained in:
Alexander Zinchuk 2021-11-19 03:22:32 +03:00
parent 7ea9dd116f
commit 04f8d03e82
4 changed files with 39 additions and 33 deletions

View File

@ -1,4 +1,5 @@
import { ChangeEvent } from 'react';
import useDebounce from '../../../hooks/useDebounce';
import React, {
FC, memo, useCallback, useEffect,
} from '../../../lib/teact/teact';
@ -10,6 +11,7 @@ import { SettingsScreens } from '../../../types';
import { pick } from '../../../util/iteratees';
import useLang from '../../../hooks/useLang';
import useHistoryBack from '../../../hooks/useHistoryBack';
import { playNotifySound } from '../../../util/notifications';
import Checkbox from '../../ui/Checkbox';
import RangeSlider from '../../ui/RangeSlider';
@ -61,6 +63,8 @@ const SettingsNotifications: FC<OwnProps & StateProps & DispatchProps> = ({
loadNotificationSettings();
}, [loadNotificationSettings]);
const runDebounced = useDebounce(500, false, true);
const handleSettingsChange = useCallback((
e: ChangeEvent<HTMLInputElement>,
peerType: 'contact' | 'group' | 'broadcast',
@ -123,12 +127,12 @@ const SettingsNotifications: FC<OwnProps & StateProps & DispatchProps> = ({
<div className="settings-item-slider">
<RangeSlider
label="Sound"
disabled={!hasWebNotifications}
min={0}
max={10}
value={notificationSoundVolume}
onChange={(volume) => {
updateWebNotificationSettings({ notificationSoundVolume: volume });
runDebounced(() => playNotifySound(undefined, volume));
}}
/>
</div>

View File

@ -4,7 +4,7 @@ import { ApiUpdate, MAIN_THREAD_ID } from '../../../api/types';
import { ARCHIVED_FOLDER_ID, MAX_ACTIVE_PINNED_CHATS } from '../../../config';
import { pick } from '../../../util/iteratees';
import { closeMessageNotifications, showNewMessageNotification } from '../../../util/notifications';
import { closeMessageNotifications, notifyAboutNewMessage } from '../../../util/notifications';
import { updateAppBadge } from '../../../util/appBadge';
import {
updateChat,
@ -20,7 +20,6 @@ import {
selectChatListType,
selectCurrentMessageList,
selectCountNotMutedUnread,
selectNotifySettings,
} from '../../selectors';
import { throttle } from '../../../util/schedulers';
@ -131,15 +130,11 @@ addReducer('apiUpdate', (global, actions, update: ApiUpdate) => {
}
updateAppBadge(selectCountNotMutedUnread(getGlobal()));
const { hasWebNotifications } = selectNotifySettings(global);
if (hasWebNotifications) {
showNewMessageNotification({
notifyAboutNewMessage({
chat,
message,
isActiveChat,
});
}
break;
}

View File

@ -90,15 +90,16 @@ const expirationTime = 12 * 60 * 60 * 1000; // 12 hours
const soundPlayedDelay = 3 * 1000;
const soundPlayedIds = new Set<string>();
async function playSound(id: string) {
if (soundPlayedIds.has(id)) return;
export async function playNotifySound(id?: string, volume?: number) {
if (id !== undefined && soundPlayedIds.has(id)) return;
const { notificationSoundVolume } = selectNotifySettings(getGlobal());
const volume = notificationSoundVolume / 10;
if (volume === 0) return;
const currentVolume = volume ? volume / 10 : notificationSoundVolume / 10;
if (currentVolume === 0) return;
const audio = new Audio('./notification.mp3');
audio.volume = volume;
audio.volume = currentVolume;
audio.setAttribute('mozaudiochannel', 'notification');
if (id !== undefined) {
audio.addEventListener('ended', () => {
soundPlayedIds.add(id);
}, { once: true });
@ -106,6 +107,7 @@ async function playSound(id: string) {
setTimeout(() => {
soundPlayedIds.delete(id);
}, soundPlayedDelay);
}
try {
await audio.play();
@ -117,7 +119,7 @@ async function playSound(id: string) {
}
}
export const playNotificationSound = debounce(playSound, 1000, true, false);
export const playNotifySoundDebounced = debounce(playNotifySound, 1000, true, false);
function checkIfShouldResubscribe(subscription: PushSubscription | null) {
const global = getGlobal();
@ -168,7 +170,7 @@ let areSettingsLoaded = false;
// Load notification settings from the api
async function loadNotificationSettings() {
if (areSettingsLoaded) return;
if (areSettingsLoaded) return selectNotifySettings(getGlobal());
const [resultSettings, resultExceptions] = await Promise.all([
callApi('fetchNotificationSettings', {
serverTimeOffset: getGlobal().serverTimeOffset,
@ -177,7 +179,7 @@ async function loadNotificationSettings() {
serverTimeOffset: getGlobal().serverTimeOffset,
}),
]);
if (!resultSettings) return;
if (!resultSettings) return selectNotifySettings(getGlobal());
let global = replaceSettings(getGlobal(), resultSettings);
if (resultExceptions) {
@ -185,6 +187,7 @@ async function loadNotificationSettings() {
}
setGlobal(global);
areSettingsLoaded = true;
return selectNotifySettings(global);
}
export async function subscribe() {
@ -313,17 +316,21 @@ async function getAvatar(chat: ApiChat) {
return mediaData;
}
export async function showNewMessageNotification({
export async function notifyAboutNewMessage({
chat,
message,
isActiveChat,
}: { chat: ApiChat; message: Partial<ApiMessage>; isActiveChat: boolean }) {
const { hasWebNotifications } = await loadNotificationSettings();
if (!checkIfShouldNotify(chat, isActiveChat)) return;
if (!hasWebNotifications) {
// only play sound if web notifications are disabled
playNotifySoundDebounced(String(message.id) || chat.id);
return;
}
if (!checkIfNotificationsSupported()) return;
if (!message.id) return;
await loadNotificationSettings();
if (!checkIfShouldNotify(chat, isActiveChat)) return;
const {
title,
body,
@ -373,7 +380,7 @@ export async function showNewMessageNotification({
// Play sound when notification is displayed
notification.onshow = () => {
playNotificationSound(String(message.id) || chat.id);
playNotifySoundDebounced(String(message.id) || chat.id);
};
}
}

View File

@ -1,7 +1,7 @@
import { DEBUG } from '../config';
import { getDispatch } from '../lib/teact/teactn';
import { IS_ANDROID, IS_IOS, IS_SERVICE_WORKER_SUPPORTED } from './environment';
import { notifyClientReady, playNotificationSound } from './notifications';
import { notifyClientReady, playNotifySoundDebounced } from './notifications';
type WorkerAction = {
type: string;
@ -23,7 +23,7 @@ function handleWorkerMessage(e: MessageEvent) {
}
break;
case 'playNotificationSound':
playNotificationSound(action.payload.id);
playNotifySoundDebounced(action.payload.id);
break;
}
}