Skip to content

Commit 4a9d0f8

Browse files
committed
fix(notifications): register bridge listeners once
1 parent 908fb74 commit 4a9d0f8

2 files changed

Lines changed: 50 additions & 17 deletions

File tree

src/NotificationsNamespace.test.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,27 @@ describe('Notifications', () => {
222222

223223
expect(mockPlugin.addListener).not.toHaveBeenCalled();
224224
});
225+
226+
test.each([['click'], ['foregroundWillDisplay'], ['permissionChange']] as const)(
227+
'should register the bridge %s listener only once across multiple subscriptions',
228+
(eventType) => {
229+
notifications.addEventListener(eventType, vi.fn());
230+
notifications.addEventListener(eventType, vi.fn());
231+
notifications.addEventListener(eventType, vi.fn());
232+
233+
expect(mockPlugin.addListener).toHaveBeenCalledTimes(1);
234+
},
235+
);
236+
237+
test('should call proceedWithWillDisplay only once per push regardless of subscriber count', () => {
238+
notifications.addEventListener('foregroundWillDisplay', vi.fn());
239+
notifications.addEventListener('foregroundWillDisplay', vi.fn());
240+
241+
const callback = mockPlugin.addListener.mock.calls[0][1];
242+
callback(mockNotification());
243+
244+
expect(mockPlugin.proceedWithWillDisplay).toHaveBeenCalledTimes(1);
245+
});
225246
});
226247

227248
describe('removeEventListener', () => {

src/NotificationsNamespace.ts

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ export default class Notifications {
2424
private _permissionObserverList: ((event: boolean) => void)[] = [];
2525
private _notificationClickedListeners: ((event: NotificationClickEvent) => void)[] = [];
2626
private _notificationWillDisplayListeners: ((event: NotificationWillDisplayEvent) => void)[] = [];
27+
private _hasRegisteredClickListener = false;
28+
private _hasRegisteredForegroundWillDisplayListener = false;
29+
private _hasRegisteredPermissionListener = false;
2730

2831
constructor(plugin: OneSignalCapacitorPlugin) {
2932
this._plugin = plugin;
@@ -103,29 +106,38 @@ export default class Notifications {
103106
): void {
104107
if (event === 'click') {
105108
this._notificationClickedListeners.push(listener as (event: NotificationClickEvent) => void);
106-
void this._plugin.addListener('notificationClick', (json: NotificationClickEvent) => {
107-
this._processFunctionList(this._notificationClickedListeners, json);
108-
});
109+
if (!this._hasRegisteredClickListener) {
110+
this._hasRegisteredClickListener = true;
111+
void this._plugin.addListener('notificationClick', (json: NotificationClickEvent) => {
112+
this._processFunctionList(this._notificationClickedListeners, json);
113+
});
114+
}
109115
} else if (event === 'foregroundWillDisplay') {
110116
this._notificationWillDisplayListeners.push(
111117
listener as (event: NotificationWillDisplayEvent) => void,
112118
);
113-
void this._plugin.addListener(
114-
'notificationForegroundWillDisplay',
115-
(notification: OSNotification) => {
116-
this._notificationWillDisplayListeners.forEach((listener) => {
117-
listener(new NotificationWillDisplayEvent(notification));
118-
});
119-
void this._plugin.proceedWithWillDisplay({
120-
notificationId: notification.notificationId,
121-
});
122-
},
123-
);
119+
if (!this._hasRegisteredForegroundWillDisplayListener) {
120+
this._hasRegisteredForegroundWillDisplayListener = true;
121+
void this._plugin.addListener(
122+
'notificationForegroundWillDisplay',
123+
(notification: OSNotification) => {
124+
this._notificationWillDisplayListeners.forEach((listener) => {
125+
listener(new NotificationWillDisplayEvent(notification));
126+
});
127+
void this._plugin.proceedWithWillDisplay({
128+
notificationId: notification.notificationId,
129+
});
130+
},
131+
);
132+
}
124133
} else if (event === 'permissionChange') {
125134
this._permissionObserverList.push(listener as (event: boolean) => void);
126-
void this._plugin.addListener('permissionChange', (state: { permission: boolean }) => {
127-
this._processFunctionList(this._permissionObserverList, state.permission);
128-
});
135+
if (!this._hasRegisteredPermissionListener) {
136+
this._hasRegisteredPermissionListener = true;
137+
void this._plugin.addListener('permissionChange', (state: { permission: boolean }) => {
138+
this._processFunctionList(this._permissionObserverList, state.permission);
139+
});
140+
}
129141
}
130142
}
131143

0 commit comments

Comments
 (0)