Explorar el Código

rn: add ability to disable crash reporting

j8
tmoldovan8x8 hace 5 años
padre
commit
b3f16926d4
No account linked to committer's email address

+ 4
- 7
android/app/build.gradle Ver fichero

@@ -1,8 +1,5 @@
1 1
 apply plugin: 'com.android.application'
2 2
 
3
-boolean googleServicesEnabled \
4
-    = project.file('google-services.json').exists() && !rootProject.ext.libreBuild
5
-
6 3
 // Crashlytics integration is done as part of Firebase now, so it gets
7 4
 // automagically activated with google-services.json
8 5
 if (googleServicesEnabled) {
@@ -13,7 +10,7 @@ if (googleServicesEnabled) {
13 10
 // This lets us upload a new build at most every 10 seconds for the
14 11
 // next ~680 years.
15 12
 // https://stackoverflow.com/a/38643838
16
-def vcode = (int)(((new Date().getTime()/1000) - 1546297200) / 10)
13
+def vcode = (int) (((new Date().getTime() / 1000) - 1546297200) / 10)
17 14
 
18 15
 android {
19 16
     compileSdkVersion rootProject.ext.compileSdkVersion
@@ -143,8 +140,8 @@ gradle.projectsEvaluated {
143 140
         def targetName = variant.name.capitalize()
144 141
 
145 142
         def currentRunPackagerTask = tasks.create(
146
-                name: "run${targetName}ReactPackager",
147
-                type: Exec) {
143
+            name: "run${targetName}ReactPackager",
144
+            type: Exec) {
148 145
             group = "react"
149 146
             description = "Run the React packager."
150 147
 
@@ -175,5 +172,5 @@ gradle.projectsEvaluated {
175 172
 }
176 173
 
177 174
 if (googleServicesEnabled) {
178
-   apply plugin: 'com.google.gms.google-services'
175
+    apply plugin: 'com.google.gms.google-services'
179 176
 }

+ 4
- 1
android/app/src/main/java/org/jitsi/meet/GoogleServicesHelper.java Ver fichero

@@ -7,6 +7,7 @@ import com.crashlytics.android.Crashlytics;
7 7
 import com.google.firebase.dynamiclinks.FirebaseDynamicLinks;
8 8
 import io.fabric.sdk.android.Fabric;
9 9
 
10
+import org.jitsi.meet.sdk.JitsiMeet;
10 11
 import org.jitsi.meet.sdk.JitsiMeetActivity;
11 12
 
12 13
 /**
@@ -21,7 +22,9 @@ final class GoogleServicesHelper {
21 22
         if (BuildConfig.GOOGLE_SERVICES_ENABLED) {
22 23
             Log.d(activity.getClass().getSimpleName(), "Initializing Google Services");
23 24
 
24
-            Fabric.with(activity, new Crashlytics());
25
+            if (!JitsiMeet.isCrashReportingDisabled(activity)) {
26
+                Fabric.with(activity, new Crashlytics());
27
+            }
25 28
 
26 29
             FirebaseDynamicLinks.getInstance().getDynamicLink(activity.getIntent())
27 30
                 .addOnSuccessListener(activity, pendingDynamicLinkData -> {

+ 2
- 0
android/build.gradle Ver fichero

@@ -161,6 +161,8 @@ ext {
161 161
 
162 162
     // Libre build
163 163
     libreBuild = (System.env.LIBRE_BUILD ?: "false").toBoolean()
164
+
165
+    googleServicesEnabled = project.file('app/google-services.json').exists() && !libreBuild
164 166
 }
165 167
 
166 168
 // Force the version of the Android build tools we have chosen on all

+ 3
- 0
android/sdk/build.gradle Ver fichero

@@ -14,11 +14,13 @@ android {
14 14
     buildTypes {
15 15
         debug {
16 16
             buildConfigField "boolean", "LIBRE_BUILD", "${rootProject.ext.libreBuild}"
17
+            buildConfigField "boolean", "GOOGLE_SERVICES_ENABLED", "${rootProject.ext.googleServicesEnabled}"
17 18
         }
18 19
         release {
19 20
             minifyEnabled false
20 21
             proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
21 22
             buildConfigField "boolean", "LIBRE_BUILD", "${rootProject.ext.libreBuild}"
23
+            buildConfigField "boolean", "GOOGLE_SERVICES_ENABLED", "${rootProject.ext.googleServicesEnabled}"
22 24
         }
23 25
     }
24 26
 
@@ -70,6 +72,7 @@ dependencies {
70 72
     implementation project(':react-native-calendar-events')
71 73
     implementation project(':react-native-community-async-storage')
72 74
     implementation project(':react-native-community_netinfo')
75
+    implementation project(':react-native-default-preference')
73 76
     implementation project(':react-native-immersive')
74 77
     implementation project(':react-native-keep-awake')
75 78
     implementation project(':react-native-linear-gradient')

+ 1
- 0
android/sdk/src/main/java/org/jitsi/meet/sdk/AppInfoModule.java Ver fichero

@@ -76,6 +76,7 @@ class AppInfoModule
76 76
             "version",
77 77
             packageInfo == null ? "" : packageInfo.versionName);
78 78
         constants.put("LIBRE_BUILD", BuildConfig.LIBRE_BUILD);
79
+        constants.put("GOOGLE_SERVICES_ENABLED", BuildConfig.GOOGLE_SERVICES_ENABLED);
79 80
 
80 81
         return constants;
81 82
     }

+ 10
- 1
android/sdk/src/main/java/org/jitsi/meet/sdk/JitsiMeet.java Ver fichero

@@ -16,11 +16,14 @@
16 16
  */
17 17
 package org.jitsi.meet.sdk;
18 18
 
19
+import android.content.Context;
20
+import android.content.SharedPreferences;
19 21
 import android.os.Bundle;
20 22
 
21 23
 import com.facebook.react.ReactInstanceManager;
22 24
 
23 25
 public class JitsiMeet {
26
+
24 27
     /**
25 28
      * Default {@link JitsiMeetConferenceOptions} which will be used for all conferences. When
26 29
      * joining a conference these options will be merged with the ones passed to
@@ -72,4 +75,10 @@ public class JitsiMeet {
72 75
             reactInstanceManager.showDevOptionsDialog();
73 76
         }
74 77
     }
75
-}
78
+
79
+    public static boolean isCrashReportingDisabled(Context context) {
80
+        SharedPreferences preferences = context.getSharedPreferences("jitsi-default-preferences", Context.MODE_PRIVATE);
81
+        String value = preferences.getString("isCrashReportingDisabled", "");
82
+        return Boolean.parseBoolean(value);
83
+    }
84
+}

+ 1
- 0
android/sdk/src/main/java/org/jitsi/meet/sdk/ReactInstanceManagerHolder.java Ver fichero

@@ -190,6 +190,7 @@ class ReactInstanceManagerHolder {
190 190
                 new com.corbt.keepawake.KCKeepAwakePackage(),
191 191
                 new com.facebook.react.shell.MainReactPackage(),
192 192
                 new com.horcrux.svg.SvgPackage(),
193
+                new com.kevinresol.react_native_default_preference.RNDefaultPreferencePackage(),
193 194
                 new com.ocetnik.timer.BackgroundTimerPackage(),
194 195
                 new com.reactnativecommunity.asyncstorage.AsyncStoragePackage(),
195 196
                 new com.reactnativecommunity.netinfo.NetInfoPackage(),

+ 3
- 1
android/settings.gradle Ver fichero

@@ -9,6 +9,8 @@ include ':react-native-community-async-storage'
9 9
 project(':react-native-community-async-storage').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-community/async-storage/android')
10 10
 include ':react-native-community_netinfo'
11 11
 project(':react-native-community_netinfo').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-community/netinfo/android')
12
+include ':react-native-default-preference'
13
+project(':react-native-default-preference').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-default-preference/android')
12 14
 include ':react-native-google-signin'
13 15
 project(':react-native-google-signin').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-community/google-signin/android')
14 16
 include ':react-native-immersive'
@@ -24,4 +26,4 @@ project(':react-native-svg').projectDir = new File(rootProject.projectDir, 	'../
24 26
 include ':react-native-webrtc'
25 27
 project(':react-native-webrtc').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-webrtc/android')
26 28
 include ':react-native-webview'
27
-project(':react-native-webview').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-webview/android')
29
+project(':react-native-webview').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-webview/android')

+ 1
- 0
ios/Podfile Ver fichero

@@ -66,6 +66,7 @@ target 'JitsiMeet' do
66 66
   pod 'RNSound', :path => '../node_modules/react-native-sound'
67 67
   pod 'RNSVG', :path => '../node_modules/react-native-svg'
68 68
   pod 'RNWatch', :path => '../node_modules/react-native-watch-connectivity'
69
+  pod 'RNDefaultPreference', :path => '../node_modules/react-native-default-preference'
69 70
 
70 71
   # Native pod dependencies
71 72
   #

+ 10
- 5
ios/Podfile.lock Ver fichero

@@ -353,6 +353,8 @@ PODS:
353 353
     - ReactCommon/turbomodule/core (= 0.61.5-jitsi.1)
354 354
   - RNCAsyncStorage (1.3.4):
355 355
     - React
356
+  - RNDefaultPreference (1.4.2):
357
+    - React
356 358
   - RNGoogleSignin (3.0.1):
357 359
     - GoogleSignIn (~> 5.0.0)
358 360
     - React
@@ -409,6 +411,7 @@ DEPENDENCIES:
409 411
   - React-RCTVibration (from `../node_modules/react-native/Libraries/Vibration`)
410 412
   - ReactCommon/turbomodule (from `../node_modules/react-native/ReactCommon`)
411 413
   - "RNCAsyncStorage (from `../node_modules/@react-native-community/async-storage`)"
414
+  - RNDefaultPreference (from `../node_modules/react-native-default-preference`)
412 415
   - "RNGoogleSignin (from `../node_modules/@react-native-community/google-signin`)"
413 416
   - RNSound (from `../node_modules/react-native-sound`)
414 417
   - RNSVG (from `../node_modules/react-native-svg`)
@@ -416,13 +419,11 @@ DEPENDENCIES:
416 419
   - Yoga (from `../node_modules/react-native/ReactCommon/yoga`)
417 420
 
418 421
 SPEC REPOS:
419
-  https://github.com/CocoaPods/Specs.git:
422
+  trunk:
420 423
     - Amplitude-iOS
424
+    - AppAuth
421 425
     - boost-for-react-native
422 426
     - CocoaLumberjack
423
-    - ObjectiveDropboxOfficial
424
-  trunk:
425
-    - AppAuth
426 427
     - Crashlytics
427 428
     - Fabric
428 429
     - Firebase
@@ -442,6 +443,7 @@ SPEC REPOS:
442 443
     - GTMAppAuth
443 444
     - GTMSessionFetcher
444 445
     - nanopb
446
+    - ObjectiveDropboxOfficial
445 447
     - PromisesObjC
446 448
 
447 449
 EXTERNAL SOURCES:
@@ -509,6 +511,8 @@ EXTERNAL SOURCES:
509 511
     :path: "../node_modules/react-native/ReactCommon"
510 512
   RNCAsyncStorage:
511 513
     :path: "../node_modules/@react-native-community/async-storage"
514
+  RNDefaultPreference:
515
+    :path: "../node_modules/react-native-default-preference"
512 516
   RNGoogleSignin:
513 517
     :path: "../node_modules/@react-native-community/google-signin"
514 518
   RNSound:
@@ -578,12 +582,13 @@ SPEC CHECKSUMS:
578 582
   React-RCTVibration: a1bcfcdc0b5a73a1b0829a34cee22bd0e95bacba
579 583
   ReactCommon: 675681aba4fecff5acbc0e440530cc422103c610
580 584
   RNCAsyncStorage: 8e31405a9f12fbf42c2bb330e4560bfd79c18323
585
+  RNDefaultPreference: 56a405ce61033ac77b95004dccd7ac54c2eb50d1
581 586
   RNGoogleSignin: 39336070b35fc4cea6a98cf111e00480317be0ae
582 587
   RNSound: c980916b596cc15c8dcd2f6ecd3b13c4881dbe20
583 588
   RNSVG: aac12785382e8fd4f28d072fe640612e34914631
584 589
   RNWatch: 09738b339eceb66e4d80a2371633ca5fb380fa42
585 590
   Yoga: 7b4209fda2441f99d54dd6cf4c82b094409bb68f
586 591
 
587
-PODFILE CHECKSUM: f615794fb9184757b00cd16e534824ba6ee2fc98
592
+PODFILE CHECKSUM: 082858daebbe170e7a490de433e7f2a99e0c3701
588 593
 
589 594
 COCOAPODS: 1.9.1

+ 7
- 9
ios/app/src/AppDelegate.m Ver fichero

@@ -24,19 +24,10 @@
24 24
 @import Firebase;
25 25
 @import JitsiMeet;
26 26
 
27
-
28 27
 @implementation AppDelegate
29 28
 
30 29
 -             (BOOL)application:(UIApplication *)application
31 30
   didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
32
-
33
-    // Initialize Crashlytics and Firebase if a valid GoogleService-Info.plist file was provided.
34
-    if ([FIRUtilities appContainsRealServiceInfoPlist]) {
35
-        NSLog(@"Enablign Crashlytics and Firebase");
36
-        [FIRApp configure];
37
-        [Fabric with:@[[Crashlytics class]]];
38
-    }
39
-
40 31
     JitsiMeet *jitsiMeet = [JitsiMeet sharedInstance];
41 32
 
42 33
     jitsiMeet.conferenceActivityType = JitsiMeetConferenceActivityType;
@@ -54,6 +45,13 @@
54 45
 #endif
55 46
     }];
56 47
 
48
+    // Initialize Crashlytics and Firebase if a valid GoogleService-Info.plist file was provided.
49
+    if ([FIRUtilities appContainsRealServiceInfoPlist] && ![jitsiMeet isCrashReportingDisabled]) {
50
+        NSLog(@"Enabling Crashlytics and Firebase");
51
+        [FIRApp configure];
52
+        [Fabric with:@[[Crashlytics class]]];
53
+    }
54
+
57 55
     [jitsiMeet application:application didFinishLaunchingWithOptions:launchOptions];
58 56
 
59 57
     return YES;

+ 2
- 33
ios/app/src/FIRUtilities.m Ver fichero

@@ -16,12 +16,7 @@
16 16
 
17 17
 #import "FIRUtilities.h"
18 18
 
19
-// Plist file name.
20
-NSString *const kGoogleServiceInfoFileName = @"GoogleService-Info";
21
-// Plist file type.
22
-NSString *const kGoogleServiceInfoFileType = @"plist";
23
-NSString *const kGoogleAppIDPlistKey = @"GOOGLE_APP_ID";
24
-
19
+@import JitsiMeet;
25 20
 
26 21
 @implementation FIRUtilities
27 22
 
@@ -30,37 +25,11 @@ NSString *const kGoogleAppIDPlistKey = @"GOOGLE_APP_ID";
30 25
   static dispatch_once_t onceToken;
31 26
   dispatch_once(&onceToken, ^{
32 27
     NSBundle *bundle = [NSBundle mainBundle];
33
-    containsRealServiceInfoPlist = [self containsRealServiceInfoPlistInBundle:bundle];
28
+    containsRealServiceInfoPlist = [InfoPlistUtil containsRealServiceInfoPlistInBundle:bundle];
34 29
   });
35 30
   return containsRealServiceInfoPlist;
36 31
 }
37 32
 
38
-+ (BOOL)containsRealServiceInfoPlistInBundle:(NSBundle *)bundle {
39
-  NSString *bundlePath = bundle.bundlePath;
40
-  if (!bundlePath.length) {
41
-    return NO;
42
-  }
43
-
44
-  NSString *plistFilePath = [bundle pathForResource:kGoogleServiceInfoFileName
45
-                                             ofType:kGoogleServiceInfoFileType];
46
-  if (!plistFilePath.length) {
47
-    return NO;
48
-  }
49
-
50
-  NSDictionary *plist = [NSDictionary dictionaryWithContentsOfFile:plistFilePath];
51
-  if (!plist) {
52
-    return NO;
53
-  }
54
-
55
-  // Perform a very naive validation by checking to see if the plist has the dummy google app id
56
-  NSString *googleAppID = plist[kGoogleAppIDPlistKey];
57
-  if (!googleAppID.length) {
58
-    return NO;
59
-  }
60
-
61
-  return YES;
62
-}
63
-
64 33
 + (NSURL *)extractURL: (FIRDynamicLink*)dynamicLink {
65 34
   NSURL *url = nil;
66 35
   if (dynamicLink != nil) {

+ 8
- 0
ios/sdk/sdk.xcodeproj/project.pbxproj Ver fichero

@@ -42,6 +42,8 @@
42 42
 		C69EFA0E209A0F660027712B /* JMCallKitListener.swift in Sources */ = {isa = PBXBuildFile; fileRef = C69EFA0B209A0F660027712B /* JMCallKitListener.swift */; };
43 43
 		C6A34261204EF76800E062DD /* DragGestureController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6A3425E204EF76800E062DD /* DragGestureController.swift */; };
44 44
 		C6CC49AF207412CF000DFA42 /* PiPViewCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6CC49AE207412CF000DFA42 /* PiPViewCoordinator.swift */; };
45
+		C8AFD27F2462C613000293D2 /* InfoPlistUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = C8AFD27D2462C613000293D2 /* InfoPlistUtil.h */; settings = {ATTRIBUTES = (Public, ); }; };
46
+		C8AFD2802462C613000293D2 /* InfoPlistUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = C8AFD27E2462C613000293D2 /* InfoPlistUtil.m */; };
45 47
 		DE438CDA2350934700DD541D /* JavaScriptSandbox.m in Sources */ = {isa = PBXBuildFile; fileRef = DE438CD82350934700DD541D /* JavaScriptSandbox.m */; };
46 48
 		DE65AACA2317FFCD00290BEC /* LogUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = DE65AAC92317FFCD00290BEC /* LogUtils.h */; };
47 49
 		DE65AACC2318028300290BEC /* JitsiMeetBaseLogHandler+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DE65AACB2318028300290BEC /* JitsiMeetBaseLogHandler+Private.h */; };
@@ -105,6 +107,8 @@
105 107
 		C6A3425E204EF76800E062DD /* DragGestureController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DragGestureController.swift; sourceTree = "<group>"; };
106 108
 		C6CC49AE207412CF000DFA42 /* PiPViewCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PiPViewCoordinator.swift; sourceTree = "<group>"; };
107 109
 		C6F99C13204DB63D0001F710 /* JitsiMeetView+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "JitsiMeetView+Private.h"; sourceTree = "<group>"; };
110
+		C8AFD27D2462C613000293D2 /* InfoPlistUtil.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = InfoPlistUtil.h; sourceTree = "<group>"; };
111
+		C8AFD27E2462C613000293D2 /* InfoPlistUtil.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = InfoPlistUtil.m; sourceTree = "<group>"; };
108 112
 		DE438CD82350934700DD541D /* JavaScriptSandbox.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = JavaScriptSandbox.m; sourceTree = "<group>"; };
109 113
 		DE65AAC92317FFCD00290BEC /* LogUtils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LogUtils.h; sourceTree = "<group>"; };
110 114
 		DE65AACB2318028300290BEC /* JitsiMeetBaseLogHandler+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "JitsiMeetBaseLogHandler+Private.h"; sourceTree = "<group>"; };
@@ -223,6 +227,8 @@
223 227
 				DEFE535521FB2E8300011A3A /* ReactUtils.m */,
224 228
 				0B93EF7C1EC9DDCD0030D24D /* RCTBridgeWrapper.h */,
225 229
 				0B93EF7D1EC9DDCD0030D24D /* RCTBridgeWrapper.m */,
230
+				C8AFD27D2462C613000293D2 /* InfoPlistUtil.h */,
231
+				C8AFD27E2462C613000293D2 /* InfoPlistUtil.m */,
226 232
 			);
227 233
 			path = src;
228 234
 			sourceTree = "<group>";
@@ -303,6 +309,7 @@
303 309
 				DE81A2D42316AC4D00AE1940 /* JitsiMeetLogger.h in Headers */,
304 310
 				DE65AACA2317FFCD00290BEC /* LogUtils.h in Headers */,
305 311
 				DEAD3226220C497000E93636 /* JitsiMeetConferenceOptions.h in Headers */,
312
+				C8AFD27F2462C613000293D2 /* InfoPlistUtil.h in Headers */,
306 313
 			);
307 314
 			runOnlyForDeploymentPostprocessing = 0;
308 315
 		};
@@ -482,6 +489,7 @@
482 489
 				0B93EF7F1EC9DDCD0030D24D /* RCTBridgeWrapper.m in Sources */,
483 490
 				0BA13D311EE83FF8007BEF7F /* ExternalAPI.m in Sources */,
484 491
 				0BCA49601EC4B6C600B793EE /* POSIX.m in Sources */,
492
+				C8AFD2802462C613000293D2 /* InfoPlistUtil.m in Sources */,
485 493
 				C6CC49AF207412CF000DFA42 /* PiPViewCoordinator.swift in Sources */,
486 494
 				DEFC743F21B178FA00E4DD96 /* LocaleDetector.m in Sources */,
487 495
 				0BCA495F1EC4B6C600B793EE /* AudioMode.m in Sources */,

+ 6
- 2
ios/sdk/src/AppInfo.m Ver fichero

@@ -19,6 +19,8 @@
19 19
 #import <React/RCTBridgeModule.h>
20 20
 #import <React/RCTLog.h>
21 21
 
22
+#import "InfoPlistUtil.h"
23
+
22 24
 @interface AppInfo : NSObject<RCTBridgeModule>
23 25
 @end
24 26
 
@@ -67,13 +69,15 @@ RCT_EXPORT_MODULE();
67 69
         buildNumber = @"";
68 70
     }
69 71
 
72
+    BOOL isGoogleServiceEnabled = [InfoPlistUtil containsRealServiceInfoPlistInBundle:[NSBundle mainBundle]];
73
+    
70 74
     return @{
71 75
         @"calendarEnabled": [NSNumber numberWithBool:calendarEnabled],
72 76
         @"buildNumber": buildNumber,
73 77
         @"name": name,
74 78
         @"sdkBundlePath": sdkBundlePath,
75
-        @"version": version
79
+        @"version": version,
80
+        @"GOOGLE_SERVICES_ENABLED": [NSNumber numberWithBool:isGoogleServiceEnabled]
76 81
     };
77 82
 };
78
-
79 83
 @end

+ 23
- 0
ios/sdk/src/InfoPlistUtil.h Ver fichero

@@ -0,0 +1,23 @@
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
+
17
+#import <Foundation/Foundation.h>
18
+
19
+@interface InfoPlistUtil : NSObject
20
+
21
++ (BOOL)containsRealServiceInfoPlistInBundle:(NSBundle *)bundle;
22
+
23
+@end

+ 52
- 0
ios/sdk/src/InfoPlistUtil.m Ver fichero

@@ -0,0 +1,52 @@
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
+
17
+#import "InfoPlistUtil.h"
18
+
19
+// Plist file name.
20
+NSString *const kGoogleServiceInfoFileName = @"GoogleService-Info";
21
+// Plist file type.
22
+NSString *const kGoogleServiceInfoFileType = @"plist";
23
+NSString *const kGoogleAppIDPlistKey = @"GOOGLE_APP_ID";
24
+
25
+@implementation InfoPlistUtil
26
+
27
++ (BOOL)containsRealServiceInfoPlistInBundle:(NSBundle *)bundle {
28
+  NSString *bundlePath = bundle.bundlePath;
29
+  if (!bundlePath.length) {
30
+    return NO;
31
+  }
32
+
33
+  NSString *plistFilePath = [bundle pathForResource:kGoogleServiceInfoFileName
34
+                                             ofType:kGoogleServiceInfoFileType];
35
+  if (!plistFilePath.length) {
36
+    return NO;
37
+  }
38
+
39
+  NSDictionary *plist = [NSDictionary dictionaryWithContentsOfFile:plistFilePath];
40
+  if (!plist) {
41
+    return NO;
42
+  }
43
+
44
+  // Perform a very naive validation by checking to see if the plist has the dummy google app id
45
+  NSString *googleAppID = plist[kGoogleAppIDPlistKey];
46
+  if (!googleAppID.length) {
47
+    return NO;
48
+  }
49
+
50
+  return YES;
51
+}
52
+@end

+ 3
- 0
ios/sdk/src/JitsiMeet.h Ver fichero

@@ -20,6 +20,7 @@
20 20
 #import <JitsiMeet/JitsiMeetConferenceOptions.h>
21 21
 #import <JitsiMeet/JitsiMeetLogger.h>
22 22
 #import <JitsiMeet/JitsiMeetBaseLogHandler.h>
23
+#import <JitsiMeet/InfoPlistUtil.h>
23 24
 
24 25
 
25 26
 @interface JitsiMeet : NSObject
@@ -64,4 +65,6 @@
64 65
 
65 66
 - (JitsiMeetConferenceOptions *_Nonnull)getInitialConferenceOptions;
66 67
 
68
+- (BOOL)isCrashReportingDisabled;
69
+
67 70
 @end

+ 6
- 1
ios/sdk/src/JitsiMeet.m Ver fichero

@@ -107,7 +107,7 @@
107 107
     JitsiMeetConferenceOptions *conferenceOptions = [JitsiMeetConferenceOptions fromBuilder:^(JitsiMeetConferenceOptionsBuilder *builder) {
108 108
         builder.room = [url absoluteString];
109 109
     }];
110
-    
110
+
111 111
     return [JitsiMeetView setPropsInViews:[conferenceOptions asProps]];
112 112
 }
113 113
 
@@ -132,6 +132,11 @@
132 132
     return nil;
133 133
 }
134 134
 
135
+- (BOOL)isCrashReportingDisabled {
136
+    NSUserDefaults *userDefaults = [[NSUserDefaults alloc] initWithSuiteName:@"jitsi-default-preferences"];
137
+    return [userDefaults stringForKey:@"isCrashReportingDisabled"];
138
+}
139
+
135 140
 - (JitsiMeetConferenceOptions *)optionsFromUserActivity:(NSUserActivity *)userActivity {
136 141
     NSString *activityType = userActivity.activityType;
137 142
 

+ 3
- 0
lang/main.json Ver fichero

@@ -582,12 +582,15 @@
582 582
     "settingsView": {
583 583
         "advanced": "Advanced",
584 584
         "alertOk": "OK",
585
+        "alertCancel": "Cancel",
585 586
         "alertTitle": "Warning",
586 587
         "alertURLText": "The entered server URL is invalid",
587 588
         "buildInfoSection": "Build Information",
588 589
         "conferenceSection": "Conference",
589 590
         "disableCallIntegration": "Disable native call integration",
590 591
         "disableP2P": "Disable Peer-To-Peer mode",
592
+        "disableCrashReporting": "Disable crash reporting",
593
+        "disableCrashReportingWarning": "Are you sure you want to disable crash reporting? The setting will be applied after you restart the app.",
591 594
         "displayName": "Display name",
592 595
         "email": "Email",
593 596
         "header": "Settings",

+ 5
- 0
package-lock.json Ver fichero

@@ -14827,6 +14827,11 @@
14827 14827
         }
14828 14828
       }
14829 14829
     },
14830
+    "react-native-default-preference": {
14831
+      "version": "1.4.2",
14832
+      "resolved": "https://registry.npmjs.org/react-native-default-preference/-/react-native-default-preference-1.4.2.tgz",
14833
+      "integrity": "sha512-kNhBLv8s6kO2gJJFEKM7qew7oRvJnygjgG1CU2ZEY6SlG5qsRX8z1Ms7z1Oo/XB7fVfyXrAoZDGhIvy+uiByrg=="
14834
+    },
14830 14835
     "react-native-immersive": {
14831 14836
       "version": "2.0.0",
14832 14837
       "resolved": "https://registry.npmjs.org/react-native-immersive/-/react-native-immersive-2.0.0.tgz",

+ 1
- 0
package.json Ver fichero

@@ -72,6 +72,7 @@
72 72
     "react-native-calendar-events": "github:jitsi/react-native-calendar-events#902e6e92d6bae450a6052f76ba4d02f977ffd8f2",
73 73
     "react-native-callstats": "3.61.0",
74 74
     "react-native-collapsible": "1.5.1",
75
+    "react-native-default-preference": "1.4.2",
75 76
     "react-native-immersive": "2.0.0",
76 77
     "react-native-keep-awake": "4.0.0",
77 78
     "react-native-linear-gradient": "2.5.6",

+ 16
- 0
react/features/base/settings/functions.native.js Ver fichero

@@ -2,6 +2,8 @@
2 2
 
3 3
 import { NativeModules } from 'react-native';
4 4
 
5
+import DefaultPreference from 'react-native-default-preference';
6
+
5 7
 export * from './functions.any';
6 8
 
7 9
 const { AudioMode } = NativeModules;
@@ -19,3 +21,17 @@ export function handleCallIntegrationChange(disabled: boolean) {
19 21
         AudioMode.setUseConnectionService(!disabled);
20 22
     }
21 23
 }
24
+
25
+/**
26
+ * Handles changes to the `disableCrashReporting` setting.
27
+ * Stores the value into platform specific default preference file, so at app
28
+ * start-up time it is retrieved on the native side and the crash reporting
29
+ * is enabled/disabled.
30
+ *
31
+ * @param {boolean} disabled - Whether crash reporting is disabled or not.
32
+ * @returns {void}
33
+ */
34
+export function handleCrashReportingChange(disabled: boolean) {
35
+    DefaultPreference.setName('jitsi-default-preferences').then(
36
+        DefaultPreference.set('isCrashReportingDisabled', disabled.toString()));
37
+}

+ 10
- 0
react/features/base/settings/functions.web.js Ver fichero

@@ -41,3 +41,13 @@ export function getCurrentOutputDeviceId(state: Object) {
41 41
  */
42 42
 export function handleCallIntegrationChange(disabled: boolean) { // eslint-disable-line no-unused-vars
43 43
 }
44
+
45
+/**
46
+ * Handles changes to the `disableCrashReporting` setting.
47
+ * Noop on web.
48
+ *
49
+ * @param {boolean} disabled - Whether crash reporting is disabled or not.
50
+ * @returns {void}
51
+ */
52
+export function handleCrashReportingChange(disabled: boolean) { // eslint-disable-line no-unused-vars
53
+}

+ 15
- 1
react/features/base/settings/middleware.js Ver fichero

@@ -9,7 +9,7 @@ import { getLocalParticipant, participantUpdated } from '../participants';
9 9
 import { MiddlewareRegistry } from '../redux';
10 10
 
11 11
 import { SETTINGS_UPDATED } from './actionTypes';
12
-import { handleCallIntegrationChange } from './functions';
12
+import { handleCallIntegrationChange, handleCrashReportingChange } from './functions';
13 13
 
14 14
 /**
15 15
  * The middleware of the feature base/settings. Distributes changes to the state
@@ -30,6 +30,7 @@ MiddlewareRegistry.register(store => next => action => {
30 30
         _maybeHandleCallIntegrationChange(action);
31 31
         _maybeSetAudioOnly(store, action);
32 32
         _updateLocalParticipant(store, action);
33
+        _maybeCrashReportingChange(action);
33 34
         break;
34 35
     case SET_LOCATION_URL:
35 36
         _updateLocalParticipantFromUrl(store);
@@ -84,6 +85,19 @@ function _maybeHandleCallIntegrationChange({ settings: { disableCallIntegration
84 85
     }
85 86
 }
86 87
 
88
+/**
89
+ * Handles a change in the `disableCrashReporting` setting.
90
+ *
91
+ * @param {Object} action - The redux action.
92
+ * @private
93
+ * @returns {void}
94
+ */
95
+function _maybeCrashReportingChange({ settings: { disableCrashReporting } }) {
96
+    if (typeof disableCrashReporting === 'boolean') {
97
+        handleCrashReportingChange(disableCrashReporting);
98
+    }
99
+}
100
+
87 101
 /**
88 102
  * Updates {@code startAudioOnly} flag if it's updated in the settings.
89 103
  *

+ 1
- 0
react/features/base/settings/reducer.js Ver fichero

@@ -24,6 +24,7 @@ const DEFAULT_STATE = {
24 24
     avatarURL: undefined,
25 25
     cameraDeviceId: undefined,
26 26
     disableCallIntegration: undefined,
27
+    disableCrashReporting: undefined,
27 28
     disableP2P: undefined,
28 29
     displayName: undefined,
29 30
     email: undefined,

+ 70
- 1
react/features/settings/components/native/SettingsView.js Ver fichero

@@ -36,6 +36,11 @@ type State = {
36 36
      */
37 37
     disableP2P: boolean,
38 38
 
39
+    /**
40
+     * State variable for the disable crash reporting switch.
41
+     */
42
+    disableCrashReporting: boolean,
43
+
39 44
     /**
40 45
      * State variable for the display name field.
41 46
      */
@@ -84,6 +89,7 @@ class SettingsView extends AbstractSettingsView<Props, State> {
84 89
         super(props);
85 90
         const {
86 91
             disableCallIntegration,
92
+            disableCrashReporting,
87 93
             disableP2P,
88 94
             displayName,
89 95
             email,
@@ -94,6 +100,7 @@ class SettingsView extends AbstractSettingsView<Props, State> {
94 100
 
95 101
         this.state = {
96 102
             disableCallIntegration,
103
+            disableCrashReporting,
97 104
             disableP2P,
98 105
             displayName,
99 106
             email,
@@ -107,6 +114,7 @@ class SettingsView extends AbstractSettingsView<Props, State> {
107 114
         this._onBlurServerURL = this._onBlurServerURL.bind(this);
108 115
         this._onClose = this._onClose.bind(this);
109 116
         this._onDisableCallIntegration = this._onDisableCallIntegration.bind(this);
117
+        this._onDisableCrashReporting = this._onDisableCrashReporting.bind(this);
110 118
         this._onDisableP2P = this._onDisableP2P.bind(this);
111 119
         this._onShowAdvanced = this._onShowAdvanced.bind(this);
112 120
         this._setURLFieldReference = this._setURLFieldReference.bind(this);
@@ -285,6 +293,24 @@ class SettingsView extends AbstractSettingsView<Props, State> {
285 293
         });
286 294
     }
287 295
 
296
+    _onDisableCrashReporting: (boolean) => void;
297
+
298
+    /**
299
+     * Handles the disable crash reporting change event.
300
+     *
301
+     * @param {boolean} disableCrashReporting - The new value
302
+     * option.
303
+     * @private
304
+     * @returns {void}
305
+     */
306
+    _onDisableCrashReporting(disableCrashReporting) {
307
+        if (disableCrashReporting) {
308
+            this._showCrashReportingDisableAlert();
309
+        } else {
310
+            this._disableCrashReporting(disableCrashReporting);
311
+        }
312
+    }
313
+
288 314
     _onClose: () => void;
289 315
 
290 316
     /**
@@ -367,7 +393,7 @@ class SettingsView extends AbstractSettingsView<Props, State> {
367 393
      * @returns {React$Element}
368 394
      */
369 395
     _renderAdvancedSettings() {
370
-        const { disableCallIntegration, disableP2P, showAdvanced } = this.state;
396
+        const { disableCallIntegration, disableP2P, disableCrashReporting, showAdvanced } = this.state;
371 397
 
372 398
         if (!showAdvanced) {
373 399
             return (
@@ -397,6 +423,15 @@ class SettingsView extends AbstractSettingsView<Props, State> {
397 423
                         onValueChange = { this._onDisableP2P }
398 424
                         value = { disableP2P } />
399 425
                 </FormRow>
426
+                {AppInfo.GOOGLE_SERVICES_ENABLED && (
427
+                    <FormRow
428
+                        fieldSeparator = { true }
429
+                        label = 'settingsView.disableCrashReporting'>
430
+                        <Switch
431
+                            onValueChange = { this._onDisableCrashReporting }
432
+                            value = { disableCrashReporting } />
433
+                    </FormRow>
434
+                )}
400 435
             </>
401 436
         );
402 437
     }
@@ -436,7 +471,41 @@ class SettingsView extends AbstractSettingsView<Props, State> {
436 471
         );
437 472
     }
438 473
 
474
+    /**
475
+     * Shows an alert warning the user about disabling crash reporting.
476
+     *
477
+     * @returns {void}
478
+     */
479
+    _showCrashReportingDisableAlert() {
480
+        const { t } = this.props;
481
+
482
+        Alert.alert(
483
+            t('settingsView.alertTitle'),
484
+            t('settingsView.disableCrashReportingWarning'),
485
+            [
486
+                {
487
+                    onPress: () => this._disableCrashReporting(true),
488
+                    text: t('settingsView.alertOk')
489
+                },
490
+                {
491
+                    text: t('settingsView.alertCancel')
492
+                }
493
+            ]
494
+        );
495
+    }
496
+
439 497
     _updateSettings: (Object) => void;
498
+
499
+    /**
500
+     * Updates the settings and sets state for disableCrashReporting.
501
+     *
502
+     * @param {boolean} disableCrashReporting - Whether crash reporting is disabled or not.
503
+     * @returns {void}
504
+     */
505
+    _disableCrashReporting(disableCrashReporting) {
506
+        this._updateSettings({ disableCrashReporting });
507
+        this.setState({ disableCrashReporting });
508
+    }
440 509
 }
441 510
 
442 511
 /**

Loading…
Cancelar
Guardar