From d7229064c4e483f609c06e4b141655f1278af79f Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 5 Aug 2020 11:07:10 +0100 Subject: [PATCH 1/3] Convert Notifier to typescript --- src/@types/global.d.ts | 6 +++++ src/BasePlatform.ts | 2 ++ src/{Notifier.js => Notifier.ts} | 40 +++++++++++++++++--------------- 3 files changed, 29 insertions(+), 19 deletions(-) rename src/{Notifier.js => Notifier.ts} (92%) diff --git a/src/@types/global.d.ts b/src/@types/global.d.ts index 6510c02160..1b3d88ac49 100644 --- a/src/@types/global.d.ts +++ b/src/@types/global.d.ts @@ -26,6 +26,7 @@ import RoomListLayoutStore from "../stores/room-list/RoomListLayoutStore"; import {IntegrationManagers} from "../integrations/IntegrationManagers"; import {ModalManager} from "../Modal"; import SettingsStore from "../settings/SettingsStore"; +import {Notifier} from "../Notifier"; declare global { interface Window { @@ -45,6 +46,7 @@ declare global { mxIntegrationManagers: typeof IntegrationManagers; singletonModalManager: ModalManager; mxSettingsStore: SettingsStore; + mxNotifier: typeof Notifier; } // workaround for https://github.com/microsoft/TypeScript/issues/30933 @@ -77,4 +79,8 @@ declare global { interface PromiseConstructor { allSettled(promises: Promise[]): Promise | ISettledRejected>>; } + + interface HTMLAudioElement { + type?: string; + } } diff --git a/src/BasePlatform.ts b/src/BasePlatform.ts index acf72a986c..1d28aa7f9a 100644 --- a/src/BasePlatform.ts +++ b/src/BasePlatform.ts @@ -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. diff --git a/src/Notifier.js b/src/Notifier.ts similarity index 92% rename from src/Notifier.js rename to src/Notifier.ts index 2ed302267e..5d074156a9 100644 --- a/src/Notifier.js +++ b/src/Notifier.ts @@ -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(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; @@ -280,7 +282,7 @@ const Notifier = { return this.isEnabled() && 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 +291,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 +314,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 +322,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 +340,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 +352,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 +385,8 @@ const Notifier = { }, }; -if (!global.mxNotifier) { - global.mxNotifier = Notifier; +if (!window.mxNotifier) { + window.mxNotifier = Notifier; } -export default global.mxNotifier; +export default window.mxNotifier; From c1e152dba2e91c8a13e926ade9b869163b564a09 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 5 Aug 2020 11:10:12 +0100 Subject: [PATCH 2/3] Decouple Audible notifications from Desktop notifications --- src/Notifier.ts | 3 ++- src/settings/Settings.ts | 2 -- src/settings/controllers/NotificationControllers.ts | 9 --------- 3 files changed, 2 insertions(+), 12 deletions(-) diff --git a/src/Notifier.ts b/src/Notifier.ts index 5d074156a9..6c783a7b33 100644 --- a/src/Notifier.ts +++ b/src/Notifier.ts @@ -279,7 +279,8 @@ export 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: boolean, persistent = true) { diff --git a/src/settings/Settings.ts b/src/settings/Settings.ts index 1989bd7a34..0fd21e1722 100644 --- a/src/settings/Settings.ts +++ b/src/settings/Settings.ts @@ -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, diff --git a/src/settings/controllers/NotificationControllers.ts b/src/settings/controllers/NotificationControllers.ts index fc50af6096..bf5971d02e 100644 --- a/src/settings/controllers/NotificationControllers.ts +++ b/src/settings/controllers/NotificationControllers.ts @@ -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; - } -} From fca48c04262ae6f1a8c4e7391a743ab768c7290c Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 5 Aug 2020 11:22:43 +0100 Subject: [PATCH 3/3] improve types --- src/Notifier.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Notifier.ts b/src/Notifier.ts index 6c783a7b33..473de6c161 100644 --- a/src/Notifier.ts +++ b/src/Notifier.ts @@ -209,7 +209,7 @@ export const Notifier = { return plaf && plaf.supportsNotifications(); }, - setEnabled: function(enable: boolean, callback: () => void) { + setEnabled: function(enable: boolean, callback?: () => void) { const plaf = PlatformPeg.get(); if (!plaf) return;