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 (@available(iOS 11.0, *) ) { 48ce247f03SCharlie Cruzan // If already recording, block it 49ce247f03SCharlie Cruzan dispatch_async(dispatch_get_main_queue(), ^{ 50ce247f03SCharlie Cruzan [self preventScreenRecording]; 51ce247f03SCharlie Cruzan }); 52ce247f03SCharlie Cruzan 53ce247f03SCharlie Cruzan // Avoid setting duplicate observers 54ce247f03SCharlie Cruzan [[NSNotificationCenter defaultCenter] removeObserver:self name:UIScreenCapturedDidChangeNotification object:nil]; 55ce247f03SCharlie Cruzan 56ce247f03SCharlie Cruzan [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(preventScreenRecording) name:UIScreenCapturedDidChangeNotification object:nil]; 57ce247f03SCharlie Cruzan } 58ce247f03SCharlie Cruzan 59ce247f03SCharlie Cruzan resolve([NSNull null]); 60ce247f03SCharlie Cruzan} 61ce247f03SCharlie Cruzan 62*efd75decSTomasz SapetaEX_EXPORT_METHOD_AS(allowScreenCapture, 63*efd75decSTomasz Sapeta allowScreenCaptureWithResolver:(EXPromiseResolveBlock)resolve 64*efd75decSTomasz Sapeta rejecter:(EXPromiseRejectBlock)reject) 65ce247f03SCharlie Cruzan{ 66ce247f03SCharlie Cruzan if (@available(iOS 11.0, *)) { 67ce247f03SCharlie Cruzan [[NSNotificationCenter defaultCenter] removeObserver:self name:UIScreenCapturedDidChangeNotification object:nil]; 68ce247f03SCharlie Cruzan } 69ce247f03SCharlie Cruzan 70ce247f03SCharlie Cruzan resolve([NSNull null]); 71ce247f03SCharlie Cruzan} 72ce247f03SCharlie Cruzan 73ce247f03SCharlie Cruzan- (void)preventScreenRecording { 74ce247f03SCharlie Cruzan if (@available(iOS 11.0, *)) { 75ce247f03SCharlie Cruzan BOOL isCaptured = [[UIScreen mainScreen] isCaptured]; 76ce247f03SCharlie Cruzan 77ce247f03SCharlie Cruzan if (isCaptured) { 78ce247f03SCharlie Cruzan [UIApplication.sharedApplication.keyWindow.subviews.firstObject addSubview:_blockView]; 79ce247f03SCharlie Cruzan } else { 80ce247f03SCharlie Cruzan [_blockView removeFromSuperview]; 81ce247f03SCharlie Cruzan } 82ce247f03SCharlie Cruzan } 83ce247f03SCharlie Cruzan} 84ce247f03SCharlie Cruzan 85*efd75decSTomasz Sapeta# pragma mark - EXEventEmitter 8680a34b81SCharlie Cruzan 8780a34b81SCharlie Cruzan- (NSArray<NSString *> *)supportedEvents 8880a34b81SCharlie Cruzan{ 8980a34b81SCharlie Cruzan return @[onScreenshotEventName]; 9080a34b81SCharlie Cruzan} 9180a34b81SCharlie Cruzan 9280a34b81SCharlie Cruzan- (void)startObserving 9380a34b81SCharlie Cruzan{ 9480a34b81SCharlie Cruzan [self setIsBeingObserved:YES]; 9580a34b81SCharlie Cruzan} 9680a34b81SCharlie Cruzan 9780a34b81SCharlie Cruzan- (void)stopObserving 9880a34b81SCharlie Cruzan{ 9980a34b81SCharlie Cruzan [self setIsBeingObserved:NO]; 10080a34b81SCharlie Cruzan} 10180a34b81SCharlie Cruzan 10280a34b81SCharlie Cruzan- (void)setIsBeingObserved:(BOOL)isBeingObserved 10380a34b81SCharlie Cruzan{ 10480a34b81SCharlie Cruzan _isBeingObserved = isBeingObserved; 10580a34b81SCharlie Cruzan BOOL shouldListen = _isBeingObserved; 10680a34b81SCharlie Cruzan if (shouldListen && !_isListening) { 10780a34b81SCharlie Cruzan // Avoid setting duplicate observers 10880a34b81SCharlie Cruzan [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationUserDidTakeScreenshotNotification object:nil]; 10980a34b81SCharlie Cruzan [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(listenForScreenCapture) name:UIApplicationUserDidTakeScreenshotNotification object:nil]; 11080a34b81SCharlie Cruzan _isListening = YES; 11180a34b81SCharlie Cruzan } else if (!shouldListen && _isListening) { 11280a34b81SCharlie Cruzan [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationUserDidTakeScreenshotNotification object:nil]; 11380a34b81SCharlie Cruzan _isListening = NO; 11480a34b81SCharlie Cruzan } 11580a34b81SCharlie Cruzan} 11680a34b81SCharlie Cruzan 11780a34b81SCharlie Cruzan- (void)listenForScreenCapture 11880a34b81SCharlie Cruzan{ 11980a34b81SCharlie Cruzan [_eventEmitter sendEventWithName:onScreenshotEventName body:nil]; 12080a34b81SCharlie Cruzan} 12180a34b81SCharlie Cruzan 122ce247f03SCharlie Cruzan@end 123