From e4f2b37d8350a5acd4973d0a43aaee0b59b8f5a7 Mon Sep 17 00:00:00 2001 From: Josh Kasten Date: Tue, 1 Aug 2023 04:18:25 +0000 Subject: [PATCH 1/6] improve readability of PermissionManager mocking Improving this readability as we are going to add some more tests using this in a follow up commit in this PR. --- .../support/managers/PermissionManager.ts | 13 ++++++++ .../unit/notifications/permission.test.ts | 31 +++---------------- .../nativePermissionChange.test.ts | 19 +++--------- 3 files changed, 21 insertions(+), 42 deletions(-) create mode 100644 __test__/support/managers/PermissionManager.ts diff --git a/__test__/support/managers/PermissionManager.ts b/__test__/support/managers/PermissionManager.ts new file mode 100644 index 000000000..6275b6ff7 --- /dev/null +++ b/__test__/support/managers/PermissionManager.ts @@ -0,0 +1,13 @@ +import { PermissionUtils } from "../../../src/shared/utils/PermissionUtils"; +import RealPermissionManager from "../../../src/shared/managers/PermissionManager" + +export class PermissionManager { + public static async mockNotificationPermissionChange( + test: jest.It, + nativePermission: NotificationPermission, + ): Promise { + test.stub(RealPermissionManager.prototype, 'getPermissionStatus', nativePermission); + // mimick native permission change + await PermissionUtils.triggerNotificationPermissionChanged(); + } +} \ No newline at end of file diff --git a/__test__/unit/notifications/permission.test.ts b/__test__/unit/notifications/permission.test.ts index 536a65e72..baac2541b 100644 --- a/__test__/unit/notifications/permission.test.ts +++ b/__test__/unit/notifications/permission.test.ts @@ -1,8 +1,7 @@ import ModelCache from "../../../src/core/caching/ModelCache"; -import PermissionManager from "../../../src/shared/managers/PermissionManager"; -import { PermissionUtils } from "../../../src/shared/utils/PermissionUtils"; import { NotificationPermission } from "../../../src/shared/models/NotificationPermission"; import { TestEnvironment } from "../../support/environment/TestEnvironment"; +import { PermissionManager } from "../../support/managers/PermissionManager"; describe('Notifications namespace permission properties', () => { beforeEach(async () => { @@ -15,45 +14,23 @@ describe('Notifications namespace permission properties', () => { jest.resetAllMocks(); }); - test('When permission changes to granted, we update the permission properties on the Notifications namespace', async () => { - test.stub(PermissionManager.prototype, 'getPermissionStatus', Promise.resolve(NotificationPermission.Granted)); - const permissionChangeEventFiredPromise = new Promise(resolve => { - OneSignal.emitter.on(OneSignal.EVENTS.NATIVE_PROMPT_PERMISSIONCHANGED, resolve); - }); - - // mimick native permission change - PermissionUtils.triggerNotificationPermissionChanged(); + await PermissionManager.mockNotificationPermissionChange(test, NotificationPermission.Granted); - await permissionChangeEventFiredPromise expect(OneSignal.Notifications.permission).toBe(true); expect(OneSignal.Notifications.permissionNative).toBe(NotificationPermission.Granted); }); test('When permission changes to default, we update the permission properties on the Notifications namespace', async () => { - test.stub(PermissionManager.prototype, 'getPermissionStatus', Promise.resolve(NotificationPermission.Default)); - const permissionChangeEventFiredPromise = new Promise(resolve => { - OneSignal.emitter.on(OneSignal.EVENTS.NATIVE_PROMPT_PERMISSIONCHANGED, resolve); - }); + await PermissionManager.mockNotificationPermissionChange(test, NotificationPermission.Default); - // mimick native permission change - PermissionUtils.triggerNotificationPermissionChanged(); - - await permissionChangeEventFiredPromise expect(OneSignal.Notifications.permission).toBe(false); expect(OneSignal.Notifications.permissionNative).toBe(NotificationPermission.Default); }); test('When permission changes to denied, we update the permission properties on the Notifications namespace', async () => { - test.stub(PermissionManager.prototype, 'getPermissionStatus', Promise.resolve(NotificationPermission.Denied)); - const permissionChangeEventFiredPromise = new Promise(resolve => { - OneSignal.emitter.on(OneSignal.EVENTS.NATIVE_PROMPT_PERMISSIONCHANGED, resolve); - }); - - // mimick native permission change - PermissionUtils.triggerNotificationPermissionChanged(); + await PermissionManager.mockNotificationPermissionChange(test, NotificationPermission.Denied); - await permissionChangeEventFiredPromise expect(OneSignal.Notifications.permission).toBe(false); expect(OneSignal.Notifications.permissionNative).toBe(NotificationPermission.Denied); }); diff --git a/__test__/unit/pushSubscription/nativePermissionChange.test.ts b/__test__/unit/pushSubscription/nativePermissionChange.test.ts index 9595e0e7c..ebd413798 100644 --- a/__test__/unit/pushSubscription/nativePermissionChange.test.ts +++ b/__test__/unit/pushSubscription/nativePermissionChange.test.ts @@ -1,10 +1,11 @@ import MainHelper from "../../../src/shared/helpers/MainHelper"; import ModelCache from "../../../src/core/caching/ModelCache"; import { OSModel } from '../../../src/core/modelRepo/OSModel' -import PermissionManager from "../../../src/shared/managers/PermissionManager"; import EventHelper from "../../../src/shared/helpers/EventHelper"; import { DUMMY_PUSH_TOKEN } from "../../support/constants"; import { initializeWithPermission } from "../../support/helpers/pushSubscription"; +import { PermissionManager } from "../../support/managers/PermissionManager"; +import { NotificationPermission } from "../../../src/shared/models/NotificationPermission"; describe('Notification Types are set correctly on subscription change', () => { beforeEach(async () => { @@ -19,19 +20,13 @@ describe('Notification Types are set correctly on subscription change', () => { test('When native permission is rejected, we update notification_types to -2 & enabled to false', async () => { await initializeWithPermission('granted'); - test.stub(PermissionManager.prototype, 'getNotificationPermission', Promise.resolve('denied')); const osModelSetSpy = jest.spyOn(OSModel.prototype, 'set'); - const permissionChangeEventFiredPromise = new Promise(resolve => { - OneSignal.emitter.on(OneSignal.EVENTS.NATIVE_PROMPT_PERMISSIONCHANGED, resolve); - }); - // mimick native permission change + await PermissionManager.mockNotificationPermissionChange(test, NotificationPermission.Denied); await MainHelper.checkAndTriggerNotificationPermissionChanged(); await EventHelper.checkAndTriggerSubscriptionChanged(); - await permissionChangeEventFiredPromise; - // check that the set function was called at least once with the correct value expect(osModelSetSpy).toHaveBeenCalledWith('notification_types', -2); expect(osModelSetSpy).toHaveBeenCalledWith('enabled', false); @@ -39,19 +34,13 @@ describe('Notification Types are set correctly on subscription change', () => { test('When native permission is accepted, we update notification_types to 1 & enabled to true', async () => { await initializeWithPermission('denied'); - test.stub(PermissionManager.prototype, 'getNotificationPermission', Promise.resolve('granted')); const osModelSetSpy = jest.spyOn(OSModel.prototype, 'set'); - const permissionChangeEventFiredPromise = new Promise(resolve => { - OneSignal.emitter.on(OneSignal.EVENTS.NATIVE_PROMPT_PERMISSIONCHANGED, resolve); - }); - // mimick native permission change + await PermissionManager.mockNotificationPermissionChange(test, NotificationPermission.Granted); await MainHelper.checkAndTriggerNotificationPermissionChanged(); await EventHelper.checkAndTriggerSubscriptionChanged(); - await permissionChangeEventFiredPromise; - // check that the set function was called at least once with the correct value expect(osModelSetSpy).toHaveBeenCalledWith('notification_types', 1); expect(osModelSetSpy).toHaveBeenCalledWith('enabled', true); From 0d8b1bc935c97844e40b1fe0765b5980f43e5d7d Mon Sep 17 00:00:00 2001 From: Josh Kasten Date: Tue, 1 Aug 2023 16:39:32 +0000 Subject: [PATCH 2/6] rename NATIVE_PROMPT_PERMISSIONCHANGED Rename NATIVE_PROMPT_PERMISSIONCHANGED to NOTIFICATION_PERMISSION_CHANGED_AS_STRING. This is much more accurate name, also ended with "AS_STRING" as we will add a "AS_BOOLEAN" copy of this event in the next commit. --- src/onesignal/NotificationsNamespace.ts | 2 +- src/onesignal/OneSignal.ts | 2 +- src/onesignal/OneSignalEvents.ts | 10 ++++++---- src/onesignal/PushSubscriptionNamespace.ts | 2 +- src/page/bell/Bell.ts | 2 +- src/shared/utils/PermissionUtils.ts | 4 ++-- 6 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/onesignal/NotificationsNamespace.ts b/src/onesignal/NotificationsNamespace.ts index 835e38dc9..2898c551d 100644 --- a/src/onesignal/NotificationsNamespace.ts +++ b/src/onesignal/NotificationsNamespace.ts @@ -16,7 +16,7 @@ export default class NotificationsNamespace extends EventListenerBase { this._permission = _permissionNative === NotificationPermission.Granted; - OneSignal.emitter.on(OneSignal.EVENTS.NATIVE_PROMPT_PERMISSIONCHANGED, (permissionNative: NotificationPermission) => { + OneSignal.emitter.on(OneSignal.EVENTS.NOTIFICATION_PERMISSION_CHANGED_AS_STRING, (permissionNative: NotificationPermission) => { this._permissionNative = permissionNative; this._permission = permissionNative === NotificationPermission.Granted; }); diff --git a/src/onesignal/OneSignal.ts b/src/onesignal/OneSignal.ts index 85de6a46a..6ae569ec5 100644 --- a/src/onesignal/OneSignal.ts +++ b/src/onesignal/OneSignal.ts @@ -169,7 +169,7 @@ export default class OneSignal { OneSignal.__initAlreadyCalled = true; - OneSignal.emitter.on(OneSignal.EVENTS.NATIVE_PROMPT_PERMISSIONCHANGED, + OneSignal.emitter.on(OneSignal.EVENTS.NOTIFICATION_PERMISSION_CHANGED_AS_STRING, EventHelper.onNotificationPermissionChange); OneSignal.emitter.on(OneSignal.EVENTS.SUBSCRIPTION_CHANGED, EventHelper._onSubscriptionChanged); OneSignal.emitter.on(OneSignal.EVENTS.SDK_INITIALIZED, InitHelper.onSdkInitialized); diff --git a/src/onesignal/OneSignalEvents.ts b/src/onesignal/OneSignalEvents.ts index cce2b1a6e..195bb0b8a 100644 --- a/src/onesignal/OneSignalEvents.ts +++ b/src/onesignal/OneSignalEvents.ts @@ -6,11 +6,13 @@ export const ONESIGNAL_EVENTS = { */ CUSTOM_PROMPT_CLICKED: 'customPromptClick', /** - * Occurs when the user clicks "Allow" or "Block" on the native permission prompt on Chrome, Firefox, or Safari. - * This event is used for both HTTP and HTTPS sites and occurs after the user actually grants notification - * permissions for the site. Occurs before the user is actually subscribed to push notifications. + * Occurs immediately when the notification permission changes for the domain at the browser level. + * This normally happens when the user clicks "Allow" or "Block" on the native permission prompt + * on Chrome, Firefox, etc, however it also changes if the end-user clicks on the lock icon and + * manually changes it. + * Occurs BEFORE the actual push subscription is created on on the backend. */ - NATIVE_PROMPT_PERMISSIONCHANGED: 'permissionChange', + NOTIFICATION_PERMISSION_CHANGED_AS_STRING: 'permissionChange', /** * Occurs after the user is officially subscribed to push notifications. The service worker is fully registered * and activated and the user is eligible to receive push notifications at any point after this. diff --git a/src/onesignal/PushSubscriptionNamespace.ts b/src/onesignal/PushSubscriptionNamespace.ts index 4b91288a5..b16cd870c 100644 --- a/src/onesignal/PushSubscriptionNamespace.ts +++ b/src/onesignal/PushSubscriptionNamespace.ts @@ -43,7 +43,7 @@ export default class PushSubscriptionNamespace extends EventListenerBase { this._token = change?.current.token; }); - OneSignal.emitter.on(OneSignal.EVENTS.NATIVE_PROMPT_PERMISSIONCHANGED, async (permission: NotificationPermission) => { + OneSignal.emitter.on(OneSignal.EVENTS.NOTIFICATION_PERMISSION_CHANGED_AS_STRING, async (permission: NotificationPermission) => { this._permission = permission; }); } diff --git a/src/page/bell/Bell.ts b/src/page/bell/Bell.ts index 6c18e1a11..0342ce59a 100755 --- a/src/page/bell/Bell.ts +++ b/src/page/bell/Bell.ts @@ -320,7 +320,7 @@ export default class Bell { } }); - OneSignal.emitter.on(OneSignal.EVENTS.NATIVE_PROMPT_PERMISSIONCHANGED, () => { + OneSignal.emitter.on(OneSignal.EVENTS.NOTIFICATION_PERMISSION_CHANGED_AS_STRING, () => { this.updateState(); }); diff --git a/src/shared/utils/PermissionUtils.ts b/src/shared/utils/PermissionUtils.ts index 6047c397f..357e6f071 100644 --- a/src/shared/utils/PermissionUtils.ts +++ b/src/shared/utils/PermissionUtils.ts @@ -3,7 +3,7 @@ import OneSignalEvent from '../services/OneSignalEvent'; export class PermissionUtils { - // This flag prevents firing the NATIVE_PROMPT_PERMISSIONCHANGED event twice + // This flag prevents firing the NOTIFICATION_PERMISSION_CHANGED_AS_STRING event twice // We use multiple APIs: // 1. Notification.requestPermission callback // 2. navigator.permissions.query({ name: 'notifications' }`).onchange @@ -34,6 +34,6 @@ export class PermissionUtils { } await Database.put('Options', { key: 'notificationPermission', value: newPermission }); - OneSignalEvent.trigger(OneSignal.EVENTS.NATIVE_PROMPT_PERMISSIONCHANGED, newPermission); + OneSignalEvent.trigger(OneSignal.EVENTS.NOTIFICATION_PERMISSION_CHANGED_AS_STRING, newPermission); } } From b5d192dcb32512aa7920d4348ddbf5426120fd83 Mon Sep 17 00:00:00 2001 From: Josh Kasten Date: Tue, 1 Aug 2023 17:08:09 +0000 Subject: [PATCH 3/6] Added addEventListener PermissionChange tests Added test to ensure the correct value is fired on the PermissionChange event. Also test to ensure removeEventListener also works. --- .../unit/notifications/permission.test.ts | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/__test__/unit/notifications/permission.test.ts b/__test__/unit/notifications/permission.test.ts index baac2541b..97eea6bcd 100644 --- a/__test__/unit/notifications/permission.test.ts +++ b/__test__/unit/notifications/permission.test.ts @@ -1,7 +1,21 @@ +import NotificationEventName from "../../../src/page/models/NotificationEventName"; import ModelCache from "../../../src/core/caching/ModelCache"; import { NotificationPermission } from "../../../src/shared/models/NotificationPermission"; import { TestEnvironment } from "../../support/environment/TestEnvironment"; import { PermissionManager } from "../../support/managers/PermissionManager"; +import OneSignal from "../../../src/onesignal/OneSignal"; + +function expectPermissionChangeEvent(expectedPermission: boolean): Promise { + return new Promise((resolver) => { + OneSignal.Notifications.addEventListener( + NotificationEventName.PermissionChange, + (permission: boolean) => { + expect(permission).toBe(expectedPermission) + resolver(); + } + ); + }); +} describe('Notifications namespace permission properties', () => { beforeEach(async () => { @@ -14,6 +28,28 @@ describe('Notifications namespace permission properties', () => { jest.resetAllMocks(); }); + test('When permission changes to granted, ensure permissionChange fires with true', async () => { + const expectedPromise = expectPermissionChangeEvent(true); + await PermissionManager.mockNotificationPermissionChange(test, NotificationPermission.Granted); + await expectedPromise; + }); + + test('When permission changes to Denied, ensure permissionChange fires with false', async () => { + await PermissionManager.mockNotificationPermissionChange(test, NotificationPermission.Granted); + + const expectedPromise = expectPermissionChangeEvent(false); + await PermissionManager.mockNotificationPermissionChange(test, NotificationPermission.Denied); + await expectedPromise; + }); + + test('When permission changes to Default, ensure permissionChange fires with false', async () => { + await PermissionManager.mockNotificationPermissionChange(test, NotificationPermission.Granted); + + const expectedPromise = expectPermissionChangeEvent(false); + await PermissionManager.mockNotificationPermissionChange(test, NotificationPermission.Default); + await expectedPromise; + }); + test('When permission changes to granted, we update the permission properties on the Notifications namespace', async () => { await PermissionManager.mockNotificationPermissionChange(test, NotificationPermission.Granted); @@ -34,4 +70,17 @@ describe('Notifications namespace permission properties', () => { expect(OneSignal.Notifications.permission).toBe(false); expect(OneSignal.Notifications.permissionNative).toBe(NotificationPermission.Denied); }); + + test('When permission changes, removeEventListener should stop callback from firing', async () => { + const callback = (_permission: boolean) => { + throw new Error("Should never be call since removeEventListener should prevent this."); + }; + OneSignal.Notifications.addEventListener(NotificationEventName.PermissionChange, callback); + OneSignal.Notifications.removeEventListener(NotificationEventName.PermissionChange, callback); + + // Change permissions through all possible states to ensure the event has had a chance to fire + await PermissionManager.mockNotificationPermissionChange(test, NotificationPermission.Granted); + await PermissionManager.mockNotificationPermissionChange(test, NotificationPermission.Default); + await PermissionManager.mockNotificationPermissionChange(test, NotificationPermission.Denied); + }); }); From c8d0603d43483feb90d580b0963c6e552f6bd72a Mon Sep 17 00:00:00 2001 From: Josh Kasten Date: Tue, 1 Aug 2023 18:25:57 +0000 Subject: [PATCH 4/6] add NOTIFICATION_PERMISSION_CHANGED_AS_BOOLEAN Add NOTIFICATION_PERMISSION_CHANGED_AS_BOOLEAN to fire public event. --- src/onesignal/OneSignalEvents.ts | 7 ++++++- src/shared/utils/PermissionUtils.ts | 9 +++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/onesignal/OneSignalEvents.ts b/src/onesignal/OneSignalEvents.ts index 195bb0b8a..9b364acea 100644 --- a/src/onesignal/OneSignalEvents.ts +++ b/src/onesignal/OneSignalEvents.ts @@ -12,7 +12,12 @@ export const ONESIGNAL_EVENTS = { * manually changes it. * Occurs BEFORE the actual push subscription is created on on the backend. */ - NOTIFICATION_PERMISSION_CHANGED_AS_STRING: 'permissionChange', + NOTIFICATION_PERMISSION_CHANGED_AS_STRING: 'permissionChangeAsString', + /** + * Same as NOTIFICATION_PERMISSION_CHANGED_AS_STRING, expect a boolean and will be used to fire + * events to the public API OneSignal.Notification.addEventListener("permissionChange", function....) + */ + NOTIFICATION_PERMISSION_CHANGED_AS_BOOLEAN: 'permissionChange', /** * Occurs after the user is officially subscribed to push notifications. The service worker is fully registered * and activated and the user is eligible to receive push notifications at any point after this. diff --git a/src/shared/utils/PermissionUtils.ts b/src/shared/utils/PermissionUtils.ts index 357e6f071..65fd1139a 100644 --- a/src/shared/utils/PermissionUtils.ts +++ b/src/shared/utils/PermissionUtils.ts @@ -35,5 +35,14 @@ export class PermissionUtils { await Database.put('Options', { key: 'notificationPermission', value: newPermission }); OneSignalEvent.trigger(OneSignal.EVENTS.NOTIFICATION_PERMISSION_CHANGED_AS_STRING, newPermission); + + const newPermissionBoolean = newPermission === 'granted'; + const previousPermissionBoolean = previousPermission === 'granted'; + + const shouldBeUpdatedBoolean = newPermissionBoolean !== previousPermissionBoolean || updateIfIdentical; + if (!shouldBeUpdatedBoolean) { + return; + } + OneSignalEvent.trigger(OneSignal.EVENTS.NOTIFICATION_PERMISSION_CHANGED_AS_BOOLEAN, newPermissionBoolean); } } From 26d71c958d72650beba24ee657d6da160432d01a Mon Sep 17 00:00:00 2001 From: Josh Kasten Date: Tue, 1 Aug 2023 18:51:54 +0000 Subject: [PATCH 5/6] change NotificationEventName from enum to type This closer matches our public API --- __test__/unit/notifications/permission.test.ts | 7 +++---- src/onesignal/NotificationsNamespace.ts | 2 +- src/page/models/NotificationEventName.ts | 15 ++++++--------- 3 files changed, 10 insertions(+), 14 deletions(-) diff --git a/__test__/unit/notifications/permission.test.ts b/__test__/unit/notifications/permission.test.ts index 97eea6bcd..9e08a9637 100644 --- a/__test__/unit/notifications/permission.test.ts +++ b/__test__/unit/notifications/permission.test.ts @@ -1,4 +1,3 @@ -import NotificationEventName from "../../../src/page/models/NotificationEventName"; import ModelCache from "../../../src/core/caching/ModelCache"; import { NotificationPermission } from "../../../src/shared/models/NotificationPermission"; import { TestEnvironment } from "../../support/environment/TestEnvironment"; @@ -8,7 +7,7 @@ import OneSignal from "../../../src/onesignal/OneSignal"; function expectPermissionChangeEvent(expectedPermission: boolean): Promise { return new Promise((resolver) => { OneSignal.Notifications.addEventListener( - NotificationEventName.PermissionChange, + "permissionChange", (permission: boolean) => { expect(permission).toBe(expectedPermission) resolver(); @@ -75,8 +74,8 @@ describe('Notifications namespace permission properties', () => { const callback = (_permission: boolean) => { throw new Error("Should never be call since removeEventListener should prevent this."); }; - OneSignal.Notifications.addEventListener(NotificationEventName.PermissionChange, callback); - OneSignal.Notifications.removeEventListener(NotificationEventName.PermissionChange, callback); + OneSignal.Notifications.addEventListener("permissionChange", callback); + OneSignal.Notifications.removeEventListener("permissionChange", callback); // Change permissions through all possible states to ensure the event has had a chance to fire await PermissionManager.mockNotificationPermissionChange(test, NotificationPermission.Granted); diff --git a/src/onesignal/NotificationsNamespace.ts b/src/onesignal/NotificationsNamespace.ts index 2898c551d..b72f81543 100644 --- a/src/onesignal/NotificationsNamespace.ts +++ b/src/onesignal/NotificationsNamespace.ts @@ -4,7 +4,7 @@ import Database from "../shared/services/Database"; import { awaitOneSignalInitAndSupported, logMethodCall } from "../shared/utils/utils"; import OneSignal from "./OneSignal"; import { EventListenerBase } from "../page/userModel/EventListenerBase"; -import NotificationEventName from "../page/models/NotificationEventName"; +import { NotificationEventName } from "../page/models/NotificationEventName"; import { NotificationPermission } from "../shared/models/NotificationPermission"; import NotificationEventTypeMap from "../page/models/NotificationEventTypeMap"; diff --git a/src/page/models/NotificationEventName.ts b/src/page/models/NotificationEventName.ts index 2154fb446..21ed55e3e 100644 --- a/src/page/models/NotificationEventName.ts +++ b/src/page/models/NotificationEventName.ts @@ -1,9 +1,6 @@ -enum NotificationEventName { - Click = "click", - ForegroundWillDisplay = "foregroundWillDisplay", - Dismiss = "dismiss", - PermissionChange = "permissionChange", - PermissionPromptDisplay = "permissionPromptDisplay" -} - -export default NotificationEventName; +export type NotificationEventName = + "click" | + "foregroundWillDisplay" | + "dismiss" | + "permissionChange" | + "permissionPromptDisplay" From b1af11c4cfe19d5a919f284dd2b8471546dae661 Mon Sep 17 00:00:00 2001 From: Josh Kasten Date: Fri, 4 Aug 2023 20:48:32 +0000 Subject: [PATCH 6/6] readability improvements to PermissionUtils --- .../support/managers/PermissionManager.ts | 2 +- src/shared/utils/PermissionUtils.ts | 25 ++++++++++++------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/__test__/support/managers/PermissionManager.ts b/__test__/support/managers/PermissionManager.ts index 6275b6ff7..2fee6fcd0 100644 --- a/__test__/support/managers/PermissionManager.ts +++ b/__test__/support/managers/PermissionManager.ts @@ -10,4 +10,4 @@ export class PermissionManager { // mimick native permission change await PermissionUtils.triggerNotificationPermissionChanged(); } -} \ No newline at end of file +} diff --git a/src/shared/utils/PermissionUtils.ts b/src/shared/utils/PermissionUtils.ts index 65fd1139a..8c5621c2c 100644 --- a/src/shared/utils/PermissionUtils.ts +++ b/src/shared/utils/PermissionUtils.ts @@ -10,37 +10,44 @@ export class PermissionUtils { // Some browsers support both, while others only support Notification.requestPermission private static executing = false; - public static async triggerNotificationPermissionChanged(updateIfIdentical = false) { + public static async triggerNotificationPermissionChanged(force = false) { if (PermissionUtils.executing) { return; } PermissionUtils.executing = true; try { - await PermissionUtils.privateTriggerNotificationPermissionChanged(updateIfIdentical); + await PermissionUtils.privateTriggerNotificationPermissionChanged(force); } finally { PermissionUtils.executing = false; } } - private static async privateTriggerNotificationPermissionChanged(updateIfIdentical: boolean) { + private static async privateTriggerNotificationPermissionChanged(force: boolean) { const newPermission: NotificationPermission = await OneSignal.context.permissionManager.getPermissionStatus(); const previousPermission: NotificationPermission = await Database.get('Options', 'notificationPermission'); - const shouldBeUpdated = newPermission !== previousPermission || updateIfIdentical; - if (!shouldBeUpdated) { + const triggerEvent = newPermission !== previousPermission || force; + if (!triggerEvent) { return; } await Database.put('Options', { key: 'notificationPermission', value: newPermission }); + OneSignalEvent.trigger(OneSignal.EVENTS.NOTIFICATION_PERMISSION_CHANGED_AS_STRING, newPermission); - + this.triggerBooleanPermissionChangeEvent(previousPermission, newPermission, force); + } + + private static triggerBooleanPermissionChangeEvent( + previousPermission: NotificationPermission, + newPermission: NotificationPermission, + force: boolean, + ): void { const newPermissionBoolean = newPermission === 'granted'; const previousPermissionBoolean = previousPermission === 'granted'; - - const shouldBeUpdatedBoolean = newPermissionBoolean !== previousPermissionBoolean || updateIfIdentical; - if (!shouldBeUpdatedBoolean) { + const triggerEvent = newPermissionBoolean !== previousPermissionBoolean || force; + if (!triggerEvent) { return; } OneSignalEvent.trigger(OneSignal.EVENTS.NOTIFICATION_PERMISSION_CHANGED_AS_BOOLEAN, newPermissionBoolean);