You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

JitsiMeet.m 6.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. /*
  2. * Copyright @ 2019-present 8x8, Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #import <Intents/Intents.h>
  17. #import "Dropbox.h"
  18. #import "JitsiMeet+Private.h"
  19. #import "JitsiMeetConferenceOptions+Private.h"
  20. #import "JitsiMeetView+Private.h"
  21. #import "RCTBridgeWrapper.h"
  22. #import "ReactUtils.h"
  23. #import <RNGoogleSignin/RNGoogleSignin.h>
  24. #import <WebRTC/RTCLogging.h>
  25. @implementation JitsiMeet {
  26. RCTBridgeWrapper *_bridgeWrapper;
  27. NSDictionary *_launchOptions;
  28. }
  29. #pragma mak - This class is a singleton
  30. + (instancetype)sharedInstance {
  31. static JitsiMeet *sharedInstance = nil;
  32. static dispatch_once_t onceToken;
  33. dispatch_once(&onceToken, ^{
  34. sharedInstance = [[self alloc] init];
  35. });
  36. return sharedInstance;
  37. }
  38. - (instancetype)init {
  39. if (self = [super init]) {
  40. // Initialize the on and only bridge for interfacing with React Native.
  41. _bridgeWrapper = [[RCTBridgeWrapper alloc] init];
  42. // Register a fatal error handler for React.
  43. registerReactFatalErrorHandler();
  44. // Register a log handler for React.
  45. registerReactLogHandler();
  46. #if 0
  47. // Enable WebRTC logs
  48. RTCSetMinDebugLogLevel(RTCLoggingSeverityInfo);
  49. #endif
  50. }
  51. return self;
  52. }
  53. #pragma mark - Methods that the App delegate must call
  54. - (BOOL)application:(UIApplication *)application
  55. didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  56. _launchOptions = [launchOptions copy];
  57. [Dropbox setAppKey];
  58. return YES;
  59. }
  60. - (BOOL)application:(UIApplication *)application
  61. continueUserActivity:(NSUserActivity *)userActivity
  62. restorationHandler:(void (^)(NSArray<id<UIUserActivityRestoring>> *))restorationHandler {
  63. JitsiMeetConferenceOptions *options = [self optionsFromUserActivity:userActivity];
  64. return options && [JitsiMeetView setPropsInViews:[options asProps]];
  65. }
  66. - (BOOL)application:(UIApplication *)app
  67. openURL:(NSURL *)url
  68. options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
  69. if ([Dropbox application:app openURL:url options:options]) {
  70. return YES;
  71. }
  72. if ([RNGoogleSignin application:app
  73. openURL:url
  74. options:options]) {
  75. return YES;
  76. }
  77. if (_customUrlScheme == nil || ![_customUrlScheme isEqualToString:url.scheme]) {
  78. return NO;
  79. }
  80. JitsiMeetConferenceOptions *conferenceOptions = [JitsiMeetConferenceOptions fromBuilder:^(JitsiMeetConferenceOptionsBuilder *builder) {
  81. builder.room = [url absoluteString];
  82. }];
  83. return [JitsiMeetView setPropsInViews:[conferenceOptions asProps]];
  84. }
  85. #pragma mark - Utility methods
  86. - (JitsiMeetConferenceOptions *)getInitialConferenceOptions {
  87. if (_launchOptions[UIApplicationLaunchOptionsURLKey]) {
  88. NSURL *url = _launchOptions[UIApplicationLaunchOptionsURLKey];
  89. return [JitsiMeetConferenceOptions fromBuilder:^(JitsiMeetConferenceOptionsBuilder *builder) {
  90. builder.room = [url absoluteString];
  91. }];
  92. } else {
  93. NSDictionary *userActivityDictionary
  94. = _launchOptions[UIApplicationLaunchOptionsUserActivityDictionaryKey];
  95. NSUserActivity *userActivity
  96. = [userActivityDictionary objectForKey:@"UIApplicationLaunchOptionsUserActivityKey"];
  97. if (userActivity != nil) {
  98. return [self optionsFromUserActivity:userActivity];
  99. }
  100. }
  101. return nil;
  102. }
  103. - (JitsiMeetConferenceOptions *)optionsFromUserActivity:(NSUserActivity *)userActivity {
  104. NSString *activityType = userActivity.activityType;
  105. if ([activityType isEqualToString:NSUserActivityTypeBrowsingWeb]) {
  106. // App was started by opening a URL in the browser
  107. NSURL *url = userActivity.webpageURL;
  108. if ([_universalLinkDomains containsObject:url.host]) {
  109. return [JitsiMeetConferenceOptions fromBuilder:^(JitsiMeetConferenceOptionsBuilder *builder) {
  110. builder.room = [url absoluteString];
  111. }];
  112. }
  113. } else if ([activityType isEqualToString:@"INStartAudioCallIntent"]
  114. || [activityType isEqualToString:@"INStartVideoCallIntent"]) {
  115. // App was started by a CallKit Intent
  116. INIntent *intent = userActivity.interaction.intent;
  117. NSArray<INPerson *> *contacts;
  118. NSString *url;
  119. BOOL audioOnly = NO;
  120. if ([intent isKindOfClass:[INStartAudioCallIntent class]]) {
  121. contacts = ((INStartAudioCallIntent *) intent).contacts;
  122. audioOnly = YES;
  123. } else if ([intent isKindOfClass:[INStartVideoCallIntent class]]) {
  124. contacts = ((INStartVideoCallIntent *) intent).contacts;
  125. }
  126. if (contacts && (url = contacts.firstObject.personHandle.value)) {
  127. return [JitsiMeetConferenceOptions fromBuilder:^(JitsiMeetConferenceOptionsBuilder *builder) {
  128. builder.audioOnly = audioOnly;
  129. builder.room = url;
  130. }];
  131. }
  132. } else if (self.conferenceActivityType && [activityType isEqualToString:self.conferenceActivityType]) {
  133. // App was started by continuing a registered NSUserActivity (SiriKit, Handoff, ...)
  134. NSString *url;
  135. if ((url = userActivity.userInfo[@"url"])) {
  136. return [JitsiMeetConferenceOptions fromBuilder:^(JitsiMeetConferenceOptionsBuilder *builder) {
  137. builder.room = url;
  138. }];
  139. }
  140. }
  141. return nil;
  142. }
  143. #pragma mark - Property getter / setters
  144. - (NSArray<NSString *> *)universalLinkDomains {
  145. return _universalLinkDomains ? _universalLinkDomains : @[];
  146. }
  147. - (void)setDefaultConferenceOptions:(JitsiMeetConferenceOptions *)defaultConferenceOptions {
  148. if (defaultConferenceOptions != nil && _defaultConferenceOptions.room != nil) {
  149. @throw [NSException exceptionWithName:@"RuntimeError"
  150. reason:@"'room' must be null in the default conference options"
  151. userInfo:nil];
  152. }
  153. _defaultConferenceOptions = defaultConferenceOptions;
  154. }
  155. #pragma mark - Private API methods
  156. - (NSDictionary *)getDefaultProps {
  157. return _defaultConferenceOptions == nil ? @{} : [_defaultConferenceOptions asProps];
  158. }
  159. - (RCTBridge *)getReactBridge {
  160. return _bridgeWrapper.bridge;
  161. }
  162. @end