146 lines
4.4 KiB
Mathematica
146 lines
4.4 KiB
Mathematica
|
// Copyright 2018-present 650 Industries. All rights reserved.
|
||
|
|
||
|
#import <UMReactNativeAdapter/UMReactNativeEventEmitter.h>
|
||
|
#import <UMCore/UMEventEmitter.h>
|
||
|
#import <UMCore/UMExportedModule.h>
|
||
|
#import <UMCore/UMModuleRegistry.h>
|
||
|
|
||
|
@interface UMReactNativeEventEmitter ()
|
||
|
|
||
|
@property (nonatomic, assign) int listenersCount;
|
||
|
@property (nonatomic, weak) UMModuleRegistry *umModuleRegistry;
|
||
|
@property (nonatomic, strong) NSMutableDictionary<NSString *, NSNumber *> *modulesListenersCounts;
|
||
|
|
||
|
@end
|
||
|
|
||
|
@implementation UMReactNativeEventEmitter
|
||
|
|
||
|
- (instancetype)init
|
||
|
{
|
||
|
if (self = [super init]) {
|
||
|
_listenersCount = 0;
|
||
|
_modulesListenersCounts = [NSMutableDictionary dictionary];
|
||
|
}
|
||
|
return self;
|
||
|
}
|
||
|
|
||
|
UM_REGISTER_MODULE();
|
||
|
|
||
|
+ (NSString *)moduleName
|
||
|
{
|
||
|
return @"UMReactNativeEventEmitter";
|
||
|
}
|
||
|
|
||
|
+ (const NSArray<Protocol *> *)exportedInterfaces
|
||
|
{
|
||
|
return @[@protocol(UMEventEmitterService)];
|
||
|
}
|
||
|
|
||
|
- (NSArray<NSString *> *)supportedEvents
|
||
|
{
|
||
|
NSMutableSet<NSString *> *eventsAccumulator = [NSMutableSet set];
|
||
|
for (UMExportedModule *exportedModule in [_umModuleRegistry getAllExportedModules]) {
|
||
|
if ([exportedModule conformsToProtocol:@protocol(UMEventEmitter)]) {
|
||
|
id<UMEventEmitter> eventEmitter = (id<UMEventEmitter>)exportedModule;
|
||
|
[eventsAccumulator addObjectsFromArray:[eventEmitter supportedEvents]];
|
||
|
}
|
||
|
}
|
||
|
return [eventsAccumulator allObjects];
|
||
|
}
|
||
|
|
||
|
RCT_EXPORT_METHOD(addProxiedListener:(NSString *)moduleName eventName:(NSString *)eventName)
|
||
|
{
|
||
|
[self addListener:eventName];
|
||
|
// Validate module
|
||
|
UMExportedModule *module = [_umModuleRegistry getExportedModuleForName:moduleName];
|
||
|
|
||
|
if (RCT_DEBUG && module == nil) {
|
||
|
UMLogError(@"Module for name `%@` has not been found.", moduleName);
|
||
|
return;
|
||
|
} else if (RCT_DEBUG && ![module conformsToProtocol:@protocol(UMEventEmitter)]) {
|
||
|
UMLogError(@"Module `%@` is not an UMEventEmitter, thus it cannot be subscribed to.", moduleName);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Validate eventEmitter
|
||
|
id<UMEventEmitter> eventEmitter = (id<UMEventEmitter>)module;
|
||
|
|
||
|
if (RCT_DEBUG && ![[eventEmitter supportedEvents] containsObject:eventName]) {
|
||
|
UMLogError(@"`%@` is not a supported event type for %@. Supported events are: `%@`",
|
||
|
eventName, moduleName, [[eventEmitter supportedEvents] componentsJoinedByString:@"`, `"]);
|
||
|
}
|
||
|
|
||
|
// Global observing state
|
||
|
_listenersCount += 1;
|
||
|
if (_listenersCount == 1) {
|
||
|
[self startObserving];
|
||
|
}
|
||
|
|
||
|
// Per-module observing state
|
||
|
int newModuleListenersCount = [self moduleListenersCountFor:moduleName] + 1;
|
||
|
if (newModuleListenersCount == 1) {
|
||
|
[eventEmitter startObserving];
|
||
|
}
|
||
|
_modulesListenersCounts[moduleName] = [NSNumber numberWithInt:newModuleListenersCount];
|
||
|
}
|
||
|
|
||
|
RCT_EXPORT_METHOD(removeProxiedListeners:(NSString *)moduleName count:(double)count)
|
||
|
{
|
||
|
[self removeListeners:count];
|
||
|
// Validate module
|
||
|
UMExportedModule *module = [_umModuleRegistry getExportedModuleForName:moduleName];
|
||
|
|
||
|
if (RCT_DEBUG && module == nil) {
|
||
|
UMLogError(@"Module for name `%@` has not been found.", moduleName);
|
||
|
return;
|
||
|
} else if (RCT_DEBUG && ![module conformsToProtocol:@protocol(UMEventEmitter)]) {
|
||
|
UMLogError(@"Module `%@` is not an UMEventEmitter, thus it cannot be subscribed to.", moduleName);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
id<UMEventEmitter> eventEmitter = (id<UMEventEmitter>)module;
|
||
|
|
||
|
// Per-module observing state
|
||
|
int newModuleListenersCount = [self moduleListenersCountFor:moduleName] - count;
|
||
|
if (newModuleListenersCount == 0) {
|
||
|
[eventEmitter stopObserving];
|
||
|
} else if (newModuleListenersCount < 0) {
|
||
|
UMLogError(@"Attempted to remove more `%@` listeners than added", moduleName);
|
||
|
newModuleListenersCount = 0;
|
||
|
}
|
||
|
_modulesListenersCounts[moduleName] = [NSNumber numberWithInt:newModuleListenersCount];
|
||
|
|
||
|
// Global observing state
|
||
|
if (_listenersCount - count < 0) {
|
||
|
UMLogError(@"Attempted to remove more proxied event emitter listeners than added");
|
||
|
_listenersCount = 0;
|
||
|
} else {
|
||
|
_listenersCount -= count;
|
||
|
}
|
||
|
|
||
|
if (_listenersCount == 0) {
|
||
|
[self stopObserving];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
# pragma mark Utilities
|
||
|
|
||
|
- (int)moduleListenersCountFor:(NSString *)moduleName
|
||
|
{
|
||
|
NSNumber *moduleListenersCountNumber = _modulesListenersCounts[moduleName];
|
||
|
int moduleListenersCount = 0;
|
||
|
if (moduleListenersCountNumber != nil) {
|
||
|
moduleListenersCount = [moduleListenersCountNumber intValue];
|
||
|
}
|
||
|
return moduleListenersCount;
|
||
|
}
|
||
|
|
||
|
# pragma mark - UMModuleRegistryConsumer
|
||
|
|
||
|
- (void)setModuleRegistry:(UMModuleRegistry *)moduleRegistry
|
||
|
{
|
||
|
_umModuleRegistry = moduleRegistry;
|
||
|
}
|
||
|
|
||
|
@end
|