diff --git a/android/capacitor/src/main/java/com/getcapacitor/Plugin.java b/android/capacitor/src/main/java/com/getcapacitor/Plugin.java index 76af8b86d..aeea5f6e5 100644 --- a/android/capacitor/src/main/java/com/getcapacitor/Plugin.java +++ b/android/capacitor/src/main/java/com/getcapacitor/Plugin.java @@ -416,6 +416,16 @@ public void removeListener(PluginCall call) { } } + /** + * Exported plugin call to remove all listeners from this plugin + * @param call + */ + @SuppressWarnings("unused") + @PluginMethod(returnType=PluginMethod.RETURN_NONE) + public void removeAllListeners(PluginCall call) { + eventListeners.clear(); + } + /** * Exported plugin call to request all permissions for this plugin * @param call diff --git a/core/src/core-plugin-definitions.ts b/core/src/core-plugin-definitions.ts index c6daccf92..1972f51c2 100644 --- a/core/src/core-plugin-definitions.ts +++ b/core/src/core-plugin-definitions.ts @@ -63,6 +63,11 @@ export interface AccessibilityPlugin { * Listen for screen reader state change (on/off) */ addListener(eventName: 'accessibilityScreenReaderStateChange', listenerFunc: ScreenReaderStateChangeCallback): PluginListenerHandle; + + /** + * Remove all native listeners for this plugin + */ + removeAllListeners(): void; } export interface AccessibilitySpeakOptions { @@ -131,6 +136,11 @@ export interface AppPlugin extends Plugin { * If you want to close the app, call `App.exitApp()`. */ addListener(eventName: 'backButton', listenerFunc: (data: AppUrlOpen) => void): PluginListenerHandle; + + /** + * Remove all native listeners for this plugin + */ + removeAllListeners(): void; } export interface AppState { @@ -235,6 +245,10 @@ export interface BrowserPlugin extends Plugin { addListener(eventName: 'browserFinished', listenerFunc: (info: any) => void): PluginListenerHandle; addListener(eventName: 'browserPageLoaded', listenerFunc: (info: any) => void): PluginListenerHandle; + /** + * Remove all native listeners for this plugin + */ + removeAllListeners(): void; } export interface BrowserOpenOptions { @@ -950,6 +964,11 @@ export interface KeyboardPlugin extends Plugin { addListener(eventName: 'keyboardDidShow', listenerFunc: (info: KeyboardInfo) => void): PluginListenerHandle; addListener(eventName: 'keyboardWillHide', listenerFunc: () => void): PluginListenerHandle; addListener(eventName: 'keyboardDidHide', listenerFunc: () => void): PluginListenerHandle; + + /** + * Remove all native listeners for this plugin + */ + removeAllListeners(): void; } export interface KeyboardInfo { @@ -1101,6 +1120,11 @@ export interface LocalNotificationsPlugin extends Plugin { requestPermission(): Promise; addListener(eventName: 'localNotificationReceived', listenerFunc: (notification: LocalNotification) => void): PluginListenerHandle; addListener(eventName: 'localNotificationActionPerformed', listenerFunc: (notificationAction: LocalNotificationActionPerformed) => void): PluginListenerHandle; + + /** + * Remove all native listeners for this plugin + */ + removeAllListeners(): void; } @@ -1194,6 +1218,11 @@ export interface MotionPlugin extends Plugin { * Listen for device orientation change (compass heading, etc.) */ addListener(eventName: 'orientation', listenerFunc: (event: MotionOrientationEventResult) => void): PluginListenerHandle; + + /** + * Remove all native listeners for this plugin + */ + removeAllListeners(): void; } export type MotionWatchOrientationCallback = (accel: MotionOrientationEventResult) => void; @@ -1237,6 +1266,11 @@ export interface NetworkPlugin extends Plugin { * Listen for network status change events */ addListener(eventName: 'networkStatusChange', listenerFunc: (status: NetworkStatus) => void): PluginListenerHandle; + + /** + * Remove all native listeners for this plugin + */ + removeAllListeners(): void; } export interface NetworkStatus { @@ -1514,6 +1548,11 @@ export interface PushNotificationsPlugin extends Plugin { addListener(eventName: 'registrationError', listenerFunc: (error: any) => void): PluginListenerHandle; addListener(eventName: 'pushNotificationReceived', listenerFunc: (notification: PushNotification) => void): PluginListenerHandle; addListener(eventName: 'pushNotificationActionPerformed', listenerFunc: (notification: PushNotificationActionPerformed) => void): PluginListenerHandle; + + /** + * Remove all native listeners for this plugin + */ + removeAllListeners(): void; } // diff --git a/core/src/web/app.ts b/core/src/web/app.ts index 3c761313f..4ada3d479 100644 --- a/core/src/web/app.ts +++ b/core/src/web/app.ts @@ -1,6 +1,6 @@ import { WebPlugin } from './index'; -import { AppPlugin, AppLaunchUrl, } from '../core-plugin-definitions'; +import { AppPlugin, AppLaunchUrl } from '../core-plugin-definitions'; export class AppPluginWeb extends WebPlugin implements AppPlugin { constructor() { diff --git a/core/src/web/index.ts b/core/src/web/index.ts index 88b845092..b5d91f549 100644 --- a/core/src/web/index.ts +++ b/core/src/web/index.ts @@ -128,6 +128,14 @@ export class WebPlugin { } } + removeAllListeners(): void { + this.listeners = {}; + for (const listener in this.windowListeners) { + this.removeWindowListener(this.windowListeners[listener]); + } + this.windowListeners = {}; + } + notifyListeners(eventName: string, data: any): void { let listeners = this.listeners[eventName]; if (listeners) { diff --git a/ios/Capacitor/Capacitor/CAPPlugin.h b/ios/Capacitor/Capacitor/CAPPlugin.h index c72afe80a..6956d6635 100644 --- a/ios/Capacitor/Capacitor/CAPPlugin.h +++ b/ios/Capacitor/Capacitor/CAPPlugin.h @@ -23,6 +23,7 @@ - (BOOL)hasListeners:(NSString *)eventName; - (void)addListener:(CAPPluginCall *)call; - (void)removeListener:(CAPPluginCall *)call; +- (void)removeAllListeners:(CAPPluginCall *)call; // Called after init if the plugin wants to do // some loading so the plugin author doesn't diff --git a/ios/Capacitor/Capacitor/CAPPlugin.m b/ios/Capacitor/Capacitor/CAPPlugin.m index 5ec22f618..5e0c98479 100644 --- a/ios/Capacitor/Capacitor/CAPPlugin.m +++ b/ios/Capacitor/Capacitor/CAPPlugin.m @@ -120,6 +120,10 @@ - (void)removeListener:(CAPPluginCall *)call { [self.bridge releaseCallWithCallbackId:callbackId]; } +- (void)removeAllListeners:(CAPPluginCall *)call { + [self.eventListeners removeAllObjects]; +} + - (NSArray*)getListeners:(NSString *)eventName { NSArray* listeners = [self.eventListeners objectForKey:eventName]; return listeners; diff --git a/ios/Capacitor/Capacitor/Plugins/DefaultPlugins.m b/ios/Capacitor/Capacitor/Plugins/DefaultPlugins.m index 305fa4512..6881f6902 100644 --- a/ios/Capacitor/Capacitor/Plugins/DefaultPlugins.m +++ b/ios/Capacitor/Capacitor/Plugins/DefaultPlugins.m @@ -5,6 +5,7 @@ CAP_PLUGIN(CAPAccessibilityPlugin, "Accessibility", CAP_PLUGIN_METHOD(isScreenReaderEnabled, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(speak, CAPPluginReturnPromise); + CAP_PLUGIN_METHOD(removeAllListeners, CAPPluginReturnNone); ) CAP_PLUGIN(CAPAppPlugin, "App", @@ -12,6 +13,7 @@ CAP_PLUGIN_METHOD(getLaunchUrl, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(canOpenUrl, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(openUrl, CAPPluginReturnPromise); + CAP_PLUGIN_METHOD(removeAllListeners, CAPPluginReturnNone); ) CAP_PLUGIN(CAPBackgroundTaskPlugin, "BackgroundTask", @@ -23,6 +25,7 @@ CAP_PLUGIN_METHOD(open, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(close, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(prefetch, CAPPluginReturnPromise); + CAP_PLUGIN_METHOD(removeAllListeners, CAPPluginReturnNone); ) CAP_PLUGIN(CAPCameraPlugin, "Camera", @@ -80,6 +83,7 @@ CAP_PLUGIN_METHOD(setStyle, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(setResizeMode, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(setScroll, CAPPluginReturnPromise); + CAP_PLUGIN_METHOD(removeAllListeners, CAPPluginReturnNone); ) CAP_PLUGIN(CAPLocalNotificationsPlugin, "LocalNotifications", @@ -89,6 +93,7 @@ CAP_PLUGIN_METHOD(getPending, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(registerActionTypes, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(areEnabled, CAPPluginReturnPromise); + CAP_PLUGIN_METHOD(removeAllListeners, CAPPluginReturnNone); ) CAP_PLUGIN(CAPModalsPlugin, "Modals", @@ -100,6 +105,7 @@ CAP_PLUGIN(CAPNetworkPlugin, "Network", CAP_PLUGIN_METHOD(getStatus, CAPPluginReturnPromise); + CAP_PLUGIN_METHOD(removeAllListeners, CAPPluginReturnNone); ) CAP_PLUGIN(CAPPermissionsPlugin, "Permissions", @@ -115,6 +121,7 @@ CAP_PLUGIN_METHOD(createChannel, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(deleteChannel, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(listChannels, CAPPluginReturnPromise); + CAP_PLUGIN_METHOD(removeAllListeners, CAPPluginReturnNone); ) CAP_PLUGIN(CAPPhotosPlugin, "Photos",