mirror of https://github.com/vector-im/riot-web
Merge pull request #5088 from matrix-org/t3chguy/notifications/14880
Decouple Audible notifications from Desktop notificationspull/21833/head
commit
fe2f29d78e
|
@ -27,6 +27,7 @@ import {IntegrationManagers} from "../integrations/IntegrationManagers";
|
|||
import {ModalManager} from "../Modal";
|
||||
import SettingsStore from "../settings/SettingsStore";
|
||||
import {ActiveRoomObserver} from "../ActiveRoomObserver";
|
||||
import {Notifier} from "../Notifier";
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
|
@ -47,6 +48,7 @@ declare global {
|
|||
mxIntegrationManagers: typeof IntegrationManagers;
|
||||
singletonModalManager: ModalManager;
|
||||
mxSettingsStore: SettingsStore;
|
||||
mxNotifier: typeof Notifier;
|
||||
}
|
||||
|
||||
// workaround for https://github.com/microsoft/TypeScript/issues/30933
|
||||
|
@ -79,4 +81,8 @@ declare global {
|
|||
interface PromiseConstructor {
|
||||
allSettled<T>(promises: Promise<T>[]): Promise<Array<ISettledFulfilled<T> | ISettledRejected>>;
|
||||
}
|
||||
|
||||
interface HTMLAudioElement {
|
||||
type?: string;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -155,6 +155,8 @@ export default abstract class BasePlatform {
|
|||
|
||||
loudNotification(ev: Event, room: Object) {
|
||||
}
|
||||
clearNotification(notif: Notification) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a promise that resolves to a string representing the current version of the application.
|
||||
|
|
|
@ -17,6 +17,9 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
||||
import { Room } from "matrix-js-sdk/src/models/room";
|
||||
|
||||
import { MatrixClientPeg } from './MatrixClientPeg';
|
||||
import SdkConfig from './SdkConfig';
|
||||
import PlatformPeg from './PlatformPeg';
|
||||
|
@ -28,9 +31,7 @@ import * as sdk from './index';
|
|||
import { _t } from './languageHandler';
|
||||
import Modal from './Modal';
|
||||
import SettingsStore from "./settings/SettingsStore";
|
||||
import {
|
||||
hideToast as hideNotificationsToast,
|
||||
} from "./toasts/DesktopNotificationsToast";
|
||||
import { hideToast as hideNotificationsToast } from "./toasts/DesktopNotificationsToast";
|
||||
import {SettingLevel} from "./settings/SettingLevel";
|
||||
|
||||
/*
|
||||
|
@ -55,7 +56,7 @@ const typehandlers = {
|
|||
},
|
||||
};
|
||||
|
||||
const Notifier = {
|
||||
export const Notifier = {
|
||||
notifsByRoom: {},
|
||||
|
||||
// A list of event IDs that we've received but need to wait until
|
||||
|
@ -63,14 +64,14 @@ const Notifier = {
|
|||
// or not
|
||||
pendingEncryptedEventIds: [],
|
||||
|
||||
notificationMessageForEvent: function(ev) {
|
||||
notificationMessageForEvent: function(ev: MatrixEvent) {
|
||||
if (typehandlers.hasOwnProperty(ev.getContent().msgtype)) {
|
||||
return typehandlers[ev.getContent().msgtype](ev);
|
||||
}
|
||||
return TextForEvent.textForEvent(ev);
|
||||
},
|
||||
|
||||
_displayPopupNotification: function(ev, room) {
|
||||
_displayPopupNotification: function(ev: MatrixEvent, room: Room) {
|
||||
const plaf = PlatformPeg.get();
|
||||
if (!plaf) {
|
||||
return;
|
||||
|
@ -125,7 +126,7 @@ const Notifier = {
|
|||
}
|
||||
},
|
||||
|
||||
getSoundForRoom: function(roomId) {
|
||||
getSoundForRoom: function(roomId: string) {
|
||||
// We do no caching here because the SDK caches setting
|
||||
// and the browser will cache the sound.
|
||||
const content = SettingsStore.getValue("notificationSound", roomId);
|
||||
|
@ -153,12 +154,13 @@ const Notifier = {
|
|||
};
|
||||
},
|
||||
|
||||
_playAudioNotification: async function(ev, room) {
|
||||
_playAudioNotification: async function(ev: MatrixEvent, room: Room) {
|
||||
const sound = this.getSoundForRoom(room.roomId);
|
||||
console.log(`Got sound ${sound && sound.name || "default"} for ${room.roomId}`);
|
||||
|
||||
try {
|
||||
const selector = document.querySelector(sound ? `audio[src='${sound.url}']` : "#messageAudio");
|
||||
const selector =
|
||||
document.querySelector<HTMLAudioElement>(sound ? `audio[src='${sound.url}']` : "#messageAudio");
|
||||
let audioElement = selector;
|
||||
if (!selector) {
|
||||
if (!sound) {
|
||||
|
@ -207,7 +209,7 @@ const Notifier = {
|
|||
return plaf && plaf.supportsNotifications();
|
||||
},
|
||||
|
||||
setEnabled: function(enable, callback) {
|
||||
setEnabled: function(enable: boolean, callback?: () => void) {
|
||||
const plaf = PlatformPeg.get();
|
||||
if (!plaf) return;
|
||||
|
||||
|
@ -277,10 +279,11 @@ const Notifier = {
|
|||
},
|
||||
|
||||
isAudioEnabled: function() {
|
||||
return this.isEnabled() && SettingsStore.getValue("audioNotificationsEnabled");
|
||||
// We don't route Audio via the HTML Notifications API so it is possible regardless of other things
|
||||
return SettingsStore.getValue("audioNotificationsEnabled");
|
||||
},
|
||||
|
||||
setToolbarHidden: function(hidden, persistent = true) {
|
||||
setToolbarHidden: function(hidden: boolean, persistent = true) {
|
||||
this.toolbarHidden = hidden;
|
||||
|
||||
Analytics.trackEvent('Notifier', 'Set Toolbar Hidden', hidden);
|
||||
|
@ -289,7 +292,7 @@ const Notifier = {
|
|||
|
||||
// update the info to localStorage for persistent settings
|
||||
if (persistent && global.localStorage) {
|
||||
global.localStorage.setItem("notifications_hidden", hidden);
|
||||
global.localStorage.setItem("notifications_hidden", String(hidden));
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -312,7 +315,7 @@ const Notifier = {
|
|||
return this.toolbarHidden;
|
||||
},
|
||||
|
||||
onSyncStateChange: function(state) {
|
||||
onSyncStateChange: function(state: string) {
|
||||
if (state === "SYNCING") {
|
||||
this.isSyncing = true;
|
||||
} else if (state === "STOPPED" || state === "ERROR") {
|
||||
|
@ -320,7 +323,7 @@ const Notifier = {
|
|||
}
|
||||
},
|
||||
|
||||
onEvent: function(ev) {
|
||||
onEvent: function(ev: MatrixEvent) {
|
||||
if (!this.isSyncing) return; // don't alert for any messages initially
|
||||
if (ev.sender && ev.sender.userId === MatrixClientPeg.get().credentials.userId) return;
|
||||
|
||||
|
@ -338,7 +341,7 @@ const Notifier = {
|
|||
this._evaluateEvent(ev);
|
||||
},
|
||||
|
||||
onEventDecrypted: function(ev) {
|
||||
onEventDecrypted: function(ev: MatrixEvent) {
|
||||
// 'decrypted' means the decryption process has finished: it may have failed,
|
||||
// in which case it might decrypt soon if the keys arrive
|
||||
if (ev.isDecryptionFailure()) return;
|
||||
|
@ -350,7 +353,7 @@ const Notifier = {
|
|||
this._evaluateEvent(ev);
|
||||
},
|
||||
|
||||
onRoomReceipt: function(ev, room) {
|
||||
onRoomReceipt: function(ev: MatrixEvent, room: Room) {
|
||||
if (room.getUnreadNotificationCount() === 0) {
|
||||
// ideally we would clear each notification when it was read,
|
||||
// but we have no way, given a read receipt, to know whether
|
||||
|
@ -383,8 +386,8 @@ const Notifier = {
|
|||
},
|
||||
};
|
||||
|
||||
if (!global.mxNotifier) {
|
||||
global.mxNotifier = Notifier;
|
||||
if (!window.mxNotifier) {
|
||||
window.mxNotifier = Notifier;
|
||||
}
|
||||
|
||||
export default global.mxNotifier;
|
||||
export default window.mxNotifier;
|
|
@ -19,7 +19,6 @@ import { MatrixClient } from 'matrix-js-sdk/src/client';
|
|||
|
||||
import { _td } from '../languageHandler';
|
||||
import {
|
||||
AudioNotificationsEnabledController,
|
||||
NotificationBodyEnabledController,
|
||||
NotificationsEnabledController,
|
||||
} from "./controllers/NotificationControllers";
|
||||
|
@ -460,7 +459,6 @@ export const SETTINGS: {[setting: string]: ISetting} = {
|
|||
"audioNotificationsEnabled": {
|
||||
supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS,
|
||||
default: true,
|
||||
controller: new AudioNotificationsEnabledController(),
|
||||
},
|
||||
"enableWidgetScreenshots": {
|
||||
supportedLevels: LEVELS_ACCOUNT_SETTINGS,
|
||||
|
|
|
@ -79,12 +79,3 @@ export class NotificationBodyEnabledController extends SettingController {
|
|||
return calculatedValue;
|
||||
}
|
||||
}
|
||||
|
||||
export class AudioNotificationsEnabledController extends SettingController {
|
||||
public getValueOverride(level: SettingLevel, roomId: string, calculatedValue: any): any {
|
||||
if (!getNotifier().isPossible()) return false;
|
||||
|
||||
// Note: Audio notifications are *not* enabled by default.
|
||||
return calculatedValue;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue