1ce247f03SCharlie Cruzan// Copyright 2018-present 650 Industries. All rights reserved. 2ce247f03SCharlie Cruzan 3ce247f03SCharlie Cruzan#import <EXScreenCapture/EXScreenCaptureModule.h> 4ce247f03SCharlie Cruzan 5*efd75decSTomasz Sapeta#import <ExpoModulesCore/EXEventEmitterService.h> 680a34b81SCharlie Cruzan 780a34b81SCharlie Cruzanstatic NSString * const onScreenshotEventName = @"onScreenshot"; 880a34b81SCharlie Cruzan 9ce247f03SCharlie Cruzan@interface EXScreenCaptureModule () 10ce247f03SCharlie Cruzan 11*efd75decSTomasz Sapeta@property (nonatomic, weak) EXModuleRegistry *moduleRegistry; 1280a34b81SCharlie Cruzan@property (nonatomic, assign) BOOL isListening; 1380a34b81SCharlie Cruzan@property (nonatomic, assign) BOOL isBeingObserved; 14*efd75decSTomasz Sapeta@property (nonatomic, weak) id<EXEventEmitterService> eventEmitter; 15ce247f03SCharlie Cruzan 16ce247f03SCharlie Cruzan@end 17ce247f03SCharlie Cruzan 18ce247f03SCharlie Cruzan@implementation EXScreenCaptureModule { 19ce247f03SCharlie Cruzan UIView *_blockView; 20ce247f03SCharlie Cruzan} 21ce247f03SCharlie Cruzan 22*efd75decSTomasz SapetaEX_EXPORT_MODULE(ExpoScreenCapture); 2380a34b81SCharlie Cruzan 24*efd75decSTomasz Sapeta# pragma mark - EXModuleRegistryConsumer 2580a34b81SCharlie Cruzan 26*efd75decSTomasz Sapeta- (void)setModuleRegistry:(EXModuleRegistry *)moduleRegistry 2780a34b81SCharlie Cruzan{ 2880a34b81SCharlie Cruzan _moduleRegistry = moduleRegistry; 29*efd75decSTomasz Sapeta _eventEmitter = [moduleRegistry getModuleImplementingProtocol:@protocol(EXEventEmitterService)]; 3080a34b81SCharlie Cruzan} 3180a34b81SCharlie Cruzan 32ce247f03SCharlie Cruzan- (instancetype)init { 33ce247f03SCharlie Cruzan if (self = [super init]) { 34ce247f03SCharlie Cruzan CGFloat boundLength = MAX([[UIScreen mainScreen] bounds].size.width, [[UIScreen mainScreen] bounds].size.height); 35ce247f03SCharlie Cruzan _blockView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, boundLength, boundLength)]; 36ce247f03SCharlie Cruzan _blockView.backgroundColor = UIColor.blackColor; 37ce247f03SCharlie Cruzan } 38ce247f03SCharlie Cruzan return self; 39ce247f03SCharlie Cruzan} 40ce247f03SCharlie Cruzan 4180a34b81SCharlie Cruzan# pragma mark - Exported methods 42ce247f03SCharlie Cruzan 43*efd75decSTomasz SapetaEX_EXPORT_METHOD_AS(preventScreenCapture, 44*efd75decSTomasz Sapeta preventScreenCaptureWithResolver:(EXPromiseResolveBlock)resolve 45*efd75decSTomasz Sapeta reject:(EXPromiseRejectBlock)reject) 46ce247f03SCharlie Cruzan{ 47ce247f03SCharlie Cruzan // If already recording, block it 48ce247f03SCharlie Cruzan dispatch_async(dispatch_get_main_queue(), ^{ 49ce247f03SCharlie Cruzan [self preventScreenRecording]; 50ce247f03SCharlie Cruzan }); 51ce247f03SCharlie Cruzan 52ce247f03SCharlie Cruzan // Avoid setting duplicate observers 53ce247f03SCharlie Cruzan [[NSNotificationCenter defaultCenter] removeObserver:self name:UIScreenCapturedDidChangeNotification object:nil]; 54ce247f03SCharlie Cruzan 55ce247f03SCharlie Cruzan [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(preventScreenRecording) name:UIScreenCapturedDidChangeNotification object:nil]; 56ce247f03SCharlie Cruzan 57ce247f03SCharlie Cruzan resolve([NSNull null]); 58ce247f03SCharlie Cruzan} 59ce247f03SCharlie Cruzan 60*efd75decSTomasz SapetaEX_EXPORT_METHOD_AS(allowScreenCapture, 61*efd75decSTomasz Sapeta allowScreenCaptureWithResolver:(EXPromiseResolveBlock)resolve 62*efd75decSTomasz Sapeta rejecter:(EXPromiseRejectBlock)reject) 63ce247f03SCharlie Cruzan{ 64ce247f03SCharlie Cruzan [[NSNotificationCenter defaultCenter] removeObserver:self name:UIScreenCapturedDidChangeNotification object:nil]; 65ce247f03SCharlie Cruzan 66ce247f03SCharlie Cruzan resolve([NSNull null]); 67ce247f03SCharlie Cruzan} 68ce247f03SCharlie Cruzan 69ce247f03SCharlie Cruzan- (void)preventScreenRecording { 70ce247f03SCharlie Cruzan BOOL isCaptured = [[UIScreen mainScreen] isCaptured]; 71ce247f03SCharlie Cruzan 72ce247f03SCharlie Cruzan if (isCaptured) { 73ce247f03SCharlie Cruzan [UIApplication.sharedApplication.keyWindow.subviews.firstObject addSubview:_blockView]; 74ce247f03SCharlie Cruzan } else { 75ce247f03SCharlie Cruzan [_blockView removeFromSuperview]; 76ce247f03SCharlie Cruzan } 77ce247f03SCharlie Cruzan} 78ce247f03SCharlie Cruzan 79*efd75decSTomasz Sapeta# pragma mark - EXEventEmitter 8080a34b81SCharlie Cruzan 8180a34b81SCharlie Cruzan- (NSArray<NSString *> *)supportedEvents 8280a34b81SCharlie Cruzan{ 8380a34b81SCharlie Cruzan return @[onScreenshotEventName]; 8480a34b81SCharlie Cruzan} 8580a34b81SCharlie Cruzan 8680a34b81SCharlie Cruzan- (void)startObserving 8780a34b81SCharlie Cruzan{ 8880a34b81SCharlie Cruzan [self setIsBeingObserved:YES]; 8980a34b81SCharlie Cruzan} 9080a34b81SCharlie Cruzan 9180a34b81SCharlie Cruzan- (void)stopObserving 9280a34b81SCharlie Cruzan{ 9380a34b81SCharlie Cruzan [self setIsBeingObserved:NO]; 9480a34b81SCharlie Cruzan} 9580a34b81SCharlie Cruzan 9680a34b81SCharlie Cruzan- (void)setIsBeingObserved:(BOOL)isBeingObserved 9780a34b81SCharlie Cruzan{ 9880a34b81SCharlie Cruzan _isBeingObserved = isBeingObserved; 9980a34b81SCharlie Cruzan BOOL shouldListen = _isBeingObserved; 10080a34b81SCharlie Cruzan if (shouldListen && !_isListening) { 10180a34b81SCharlie Cruzan // Avoid setting duplicate observers 10280a34b81SCharlie Cruzan [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationUserDidTakeScreenshotNotification object:nil]; 10380a34b81SCharlie Cruzan [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(listenForScreenCapture) name:UIApplicationUserDidTakeScreenshotNotification object:nil]; 10480a34b81SCharlie Cruzan _isListening = YES; 10580a34b81SCharlie Cruzan } else if (!shouldListen && _isListening) { 10680a34b81SCharlie Cruzan [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationUserDidTakeScreenshotNotification object:nil]; 10780a34b81SCharlie Cruzan _isListening = NO; 10880a34b81SCharlie Cruzan } 10980a34b81SCharlie Cruzan} 11080a34b81SCharlie Cruzan 11180a34b81SCharlie Cruzan- (void)listenForScreenCapture 11280a34b81SCharlie Cruzan{ 11380a34b81SCharlie Cruzan [_eventEmitter sendEventWithName:onScreenshotEventName body:nil]; 11480a34b81SCharlie Cruzan} 11580a34b81SCharlie Cruzan 116ce247f03SCharlie Cruzan@end 117