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