diff --git a/src/domain/session/settings/SettingsViewModel.js b/src/domain/session/settings/SettingsViewModel.js index ec171eea..221e39da 100644 --- a/src/domain/session/settings/SettingsViewModel.js +++ b/src/domain/session/settings/SettingsViewModel.js @@ -22,6 +22,8 @@ class PushNotificationStatus { this.supported = null; this.enabled = false; this.updating = false; + this.enabledOnServer = null; + this.serverError = null; } } @@ -129,6 +131,8 @@ export class SettingsViewModel extends ViewModel { async togglePushNotifications() { this.pushNotifications.updating = true; + this.pushNotifications.enabledOnServer = null; + this.pushNotifications.serverError = null; this.emitChange("pushNotifications.updating"); try { if (await this._session.enablePushNotifications(!this.pushNotifications.enabled)) { @@ -142,5 +146,17 @@ export class SettingsViewModel extends ViewModel { this.emitChange("pushNotifications.updating"); } } + + async checkPushEnabledOnServer() { + this.pushNotifications.enabledOnServer = null; + this.pushNotifications.serverError = null; + try { + this.pushNotifications.enabledOnServer = await this._session.checkPusherEnabledOnHomeServer(); + this.emitChange("pushNotifications.enabledOnServer"); + } catch (err) { + this.pushNotifications.serverError = err; + this.emitChange("pushNotifications.serverError"); + } + } } diff --git a/src/matrix/Session.js b/src/matrix/Session.js index 735967bf..0ddf44ae 100644 --- a/src/matrix/Session.js +++ b/src/matrix/Session.js @@ -522,6 +522,18 @@ export class Session { const pusherData = await readTxn.session.get(PUSHER_KEY); return !!pusherData; } + + async checkPusherEnabledOnHomeServer() { + const readTxn = await this._storage.readTxn([this._storage.storeNames.session]); + const pusherData = await readTxn.session.get(PUSHER_KEY); + if (!pusherData) { + return false; + } + const myPusher = new Pusher(pusherData); + const serverPushersData = await this._hsApi.getPushers().response(); + const serverPushers = (serverPushersData?.pushers || []).map(data => new Pusher(data)); + return serverPushers.some(p => p.equals(myPusher)); + } } export function tests() { diff --git a/src/matrix/net/HomeServerApi.js b/src/matrix/net/HomeServerApi.js index a6acaf74..f8dfa517 100644 --- a/src/matrix/net/HomeServerApi.js +++ b/src/matrix/net/HomeServerApi.js @@ -258,6 +258,10 @@ export class HomeServerApi { setPusher(pusher, options = null) { return this._post("/pushers/set", null, pusher, options); } + + getPushers(options = null) { + return this._get("/pushers", null, null, options); + } } export function tests() { diff --git a/src/matrix/push/Pusher.js b/src/matrix/push/Pusher.js index cc370f82..99baeae6 100644 --- a/src/matrix/push/Pusher.js +++ b/src/matrix/push/Pusher.js @@ -37,4 +37,14 @@ export class Pusher { serialize() { return this._description; } + + equals(pusher) { + if (this._description.app_id !== pusher._description.app_id) { + return false; + } + if (this._description.pushkey !== pusher._description.pushkey) { + return false; + } + return JSON.stringify(this._description.data) === JSON.stringify(pusher._description.data); + } } diff --git a/src/platform/web/ui/general/TemplateView.js b/src/platform/web/ui/general/TemplateView.js index 6b016b9b..e82a492e 100644 --- a/src/platform/web/ui/general/TemplateView.js +++ b/src/platform/web/ui/general/TemplateView.js @@ -322,7 +322,11 @@ class TemplateBuilder { map(mapFn, renderFn) { return this.mapView(mapFn, mappedValue => { return new TemplateView(this._value, (t, vm) => { - return renderFn(mappedValue, t, vm); + const rootNode = renderFn(mappedValue, t, vm); + if (!rootNode) { + return document.createComment("map placeholder"); + } + return rootNode; }); }); } diff --git a/src/platform/web/ui/session/settings/SettingsView.js b/src/platform/web/ui/session/settings/SettingsView.js index 4d4b2aba..b4a47bea 100644 --- a/src/platform/web/ui/session/settings/SettingsView.js +++ b/src/platform/web/ui/session/settings/SettingsView.js @@ -66,6 +66,27 @@ export class SettingsView extends TemplateView { } else { return t.p(vm.i18n`Push notifications are not supported on this browser`); } + }), + t.if(vm => vm.pushNotifications.supported && vm.pushNotifications.enabled, t => { + return t.div([ + t.p([ + "If you think push notifications are not being delivered, ", + t.button({className: "link", onClick: () => vm.checkPushEnabledOnServer()}, "check"), + " if they got disabled on the server" + ]), + t.map(vm => vm.pushNotifications.enabledOnServer, (enabled, t) => { + if (enabled === true) { + return t.p("Push notifications are still enabled on the server, so everything should be working. Sometimes notifications can get dropped if they can't be delivered within a given time."); + } else if (enabled === false) { + return t.p("Push notifications have been disabled on the server, likely due to a bug. Please re-enable them by clicking Disable and then Enable again above."); + } + }), + t.map(vm => vm.pushNotifications.serverError, (err, t) => { + if (err) { + return t.p("Couln't not check on server: " + err.message); + } + }) + ]); }) );