rn: add ability to disable crash reporting

This commit is contained in:
tmoldovan8x8 2020-05-08 00:05:48 +03:00 committed by GitHub
parent f646bc7a7a
commit b3f16926d4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 267 additions and 62 deletions

View File

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

View File

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

View File

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

View File

@ -14,11 +14,13 @@ android {
buildTypes {
debug {
buildConfigField "boolean", "LIBRE_BUILD", "${rootProject.ext.libreBuild}"
buildConfigField "boolean", "GOOGLE_SERVICES_ENABLED", "${rootProject.ext.googleServicesEnabled}"
}
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
buildConfigField "boolean", "LIBRE_BUILD", "${rootProject.ext.libreBuild}"
buildConfigField "boolean", "GOOGLE_SERVICES_ENABLED", "${rootProject.ext.googleServicesEnabled}"
}
}
@ -70,6 +72,7 @@ dependencies {
implementation project(':react-native-calendar-events')
implementation project(':react-native-community-async-storage')
implementation project(':react-native-community_netinfo')
implementation project(':react-native-default-preference')
implementation project(':react-native-immersive')
implementation project(':react-native-keep-awake')
implementation project(':react-native-linear-gradient')

View File

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

View File

@ -16,11 +16,14 @@
*/
package org.jitsi.meet.sdk;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import com.facebook.react.ReactInstanceManager;
public class JitsiMeet {
/**
* Default {@link JitsiMeetConferenceOptions} which will be used for all conferences. When
* joining a conference these options will be merged with the ones passed to
@ -72,4 +75,10 @@ public class JitsiMeet {
reactInstanceManager.showDevOptionsDialog();
}
}
}
public static boolean isCrashReportingDisabled(Context context) {
SharedPreferences preferences = context.getSharedPreferences("jitsi-default-preferences", Context.MODE_PRIVATE);
String value = preferences.getString("isCrashReportingDisabled", "");
return Boolean.parseBoolean(value);
}
}

View File

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

View File

@ -9,6 +9,8 @@ include ':react-native-community-async-storage'
project(':react-native-community-async-storage').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-community/async-storage/android')
include ':react-native-community_netinfo'
project(':react-native-community_netinfo').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-community/netinfo/android')
include ':react-native-default-preference'
project(':react-native-default-preference').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-default-preference/android')
include ':react-native-google-signin'
project(':react-native-google-signin').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-community/google-signin/android')
include ':react-native-immersive'
@ -24,4 +26,4 @@ project(':react-native-svg').projectDir = new File(rootProject.projectDir, '../
include ':react-native-webrtc'
project(':react-native-webrtc').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-webrtc/android')
include ':react-native-webview'
project(':react-native-webview').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-webview/android')
project(':react-native-webview').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-webview/android')

View File

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

View File

@ -353,6 +353,8 @@ PODS:
- ReactCommon/turbomodule/core (= 0.61.5-jitsi.1)
- RNCAsyncStorage (1.3.4):
- React
- RNDefaultPreference (1.4.2):
- React
- RNGoogleSignin (3.0.1):
- GoogleSignIn (~> 5.0.0)
- React
@ -409,6 +411,7 @@ DEPENDENCIES:
- React-RCTVibration (from `../node_modules/react-native/Libraries/Vibration`)
- ReactCommon/turbomodule (from `../node_modules/react-native/ReactCommon`)
- "RNCAsyncStorage (from `../node_modules/@react-native-community/async-storage`)"
- RNDefaultPreference (from `../node_modules/react-native-default-preference`)
- "RNGoogleSignin (from `../node_modules/@react-native-community/google-signin`)"
- RNSound (from `../node_modules/react-native-sound`)
- RNSVG (from `../node_modules/react-native-svg`)
@ -416,13 +419,11 @@ DEPENDENCIES:
- Yoga (from `../node_modules/react-native/ReactCommon/yoga`)
SPEC REPOS:
https://github.com/CocoaPods/Specs.git:
trunk:
- Amplitude-iOS
- AppAuth
- boost-for-react-native
- CocoaLumberjack
- ObjectiveDropboxOfficial
trunk:
- AppAuth
- Crashlytics
- Fabric
- Firebase
@ -442,6 +443,7 @@ SPEC REPOS:
- GTMAppAuth
- GTMSessionFetcher
- nanopb
- ObjectiveDropboxOfficial
- PromisesObjC
EXTERNAL SOURCES:
@ -509,6 +511,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/ReactCommon"
RNCAsyncStorage:
:path: "../node_modules/@react-native-community/async-storage"
RNDefaultPreference:
:path: "../node_modules/react-native-default-preference"
RNGoogleSignin:
:path: "../node_modules/@react-native-community/google-signin"
RNSound:
@ -578,12 +582,13 @@ SPEC CHECKSUMS:
React-RCTVibration: a1bcfcdc0b5a73a1b0829a34cee22bd0e95bacba
ReactCommon: 675681aba4fecff5acbc0e440530cc422103c610
RNCAsyncStorage: 8e31405a9f12fbf42c2bb330e4560bfd79c18323
RNDefaultPreference: 56a405ce61033ac77b95004dccd7ac54c2eb50d1
RNGoogleSignin: 39336070b35fc4cea6a98cf111e00480317be0ae
RNSound: c980916b596cc15c8dcd2f6ecd3b13c4881dbe20
RNSVG: aac12785382e8fd4f28d072fe640612e34914631
RNWatch: 09738b339eceb66e4d80a2371633ca5fb380fa42
Yoga: 7b4209fda2441f99d54dd6cf4c82b094409bb68f
PODFILE CHECKSUM: f615794fb9184757b00cd16e534824ba6ee2fc98
PODFILE CHECKSUM: 082858daebbe170e7a490de433e7f2a99e0c3701
COCOAPODS: 1.9.1

View File

@ -24,19 +24,10 @@
@import Firebase;
@import JitsiMeet;
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Initialize Crashlytics and Firebase if a valid GoogleService-Info.plist file was provided.
if ([FIRUtilities appContainsRealServiceInfoPlist]) {
NSLog(@"Enablign Crashlytics and Firebase");
[FIRApp configure];
[Fabric with:@[[Crashlytics class]]];
}
JitsiMeet *jitsiMeet = [JitsiMeet sharedInstance];
jitsiMeet.conferenceActivityType = JitsiMeetConferenceActivityType;
@ -54,6 +45,13 @@
#endif
}];
// Initialize Crashlytics and Firebase if a valid GoogleService-Info.plist file was provided.
if ([FIRUtilities appContainsRealServiceInfoPlist] && ![jitsiMeet isCrashReportingDisabled]) {
NSLog(@"Enabling Crashlytics and Firebase");
[FIRApp configure];
[Fabric with:@[[Crashlytics class]]];
}
[jitsiMeet application:application didFinishLaunchingWithOptions:launchOptions];
return YES;

View File

@ -16,12 +16,7 @@
#import "FIRUtilities.h"
// Plist file name.
NSString *const kGoogleServiceInfoFileName = @"GoogleService-Info";
// Plist file type.
NSString *const kGoogleServiceInfoFileType = @"plist";
NSString *const kGoogleAppIDPlistKey = @"GOOGLE_APP_ID";
@import JitsiMeet;
@implementation FIRUtilities
@ -30,37 +25,11 @@ NSString *const kGoogleAppIDPlistKey = @"GOOGLE_APP_ID";
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSBundle *bundle = [NSBundle mainBundle];
containsRealServiceInfoPlist = [self containsRealServiceInfoPlistInBundle:bundle];
containsRealServiceInfoPlist = [InfoPlistUtil containsRealServiceInfoPlistInBundle:bundle];
});
return containsRealServiceInfoPlist;
}
+ (BOOL)containsRealServiceInfoPlistInBundle:(NSBundle *)bundle {
NSString *bundlePath = bundle.bundlePath;
if (!bundlePath.length) {
return NO;
}
NSString *plistFilePath = [bundle pathForResource:kGoogleServiceInfoFileName
ofType:kGoogleServiceInfoFileType];
if (!plistFilePath.length) {
return NO;
}
NSDictionary *plist = [NSDictionary dictionaryWithContentsOfFile:plistFilePath];
if (!plist) {
return NO;
}
// Perform a very naive validation by checking to see if the plist has the dummy google app id
NSString *googleAppID = plist[kGoogleAppIDPlistKey];
if (!googleAppID.length) {
return NO;
}
return YES;
}
+ (NSURL *)extractURL: (FIRDynamicLink*)dynamicLink {
NSURL *url = nil;
if (dynamicLink != nil) {

View File

@ -42,6 +42,8 @@
C69EFA0E209A0F660027712B /* JMCallKitListener.swift in Sources */ = {isa = PBXBuildFile; fileRef = C69EFA0B209A0F660027712B /* JMCallKitListener.swift */; };
C6A34261204EF76800E062DD /* DragGestureController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6A3425E204EF76800E062DD /* DragGestureController.swift */; };
C6CC49AF207412CF000DFA42 /* PiPViewCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6CC49AE207412CF000DFA42 /* PiPViewCoordinator.swift */; };
C8AFD27F2462C613000293D2 /* InfoPlistUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = C8AFD27D2462C613000293D2 /* InfoPlistUtil.h */; settings = {ATTRIBUTES = (Public, ); }; };
C8AFD2802462C613000293D2 /* InfoPlistUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = C8AFD27E2462C613000293D2 /* InfoPlistUtil.m */; };
DE438CDA2350934700DD541D /* JavaScriptSandbox.m in Sources */ = {isa = PBXBuildFile; fileRef = DE438CD82350934700DD541D /* JavaScriptSandbox.m */; };
DE65AACA2317FFCD00290BEC /* LogUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = DE65AAC92317FFCD00290BEC /* LogUtils.h */; };
DE65AACC2318028300290BEC /* JitsiMeetBaseLogHandler+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DE65AACB2318028300290BEC /* JitsiMeetBaseLogHandler+Private.h */; };
@ -105,6 +107,8 @@
C6A3425E204EF76800E062DD /* DragGestureController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DragGestureController.swift; sourceTree = "<group>"; };
C6CC49AE207412CF000DFA42 /* PiPViewCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PiPViewCoordinator.swift; sourceTree = "<group>"; };
C6F99C13204DB63D0001F710 /* JitsiMeetView+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "JitsiMeetView+Private.h"; sourceTree = "<group>"; };
C8AFD27D2462C613000293D2 /* InfoPlistUtil.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = InfoPlistUtil.h; sourceTree = "<group>"; };
C8AFD27E2462C613000293D2 /* InfoPlistUtil.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = InfoPlistUtil.m; sourceTree = "<group>"; };
DE438CD82350934700DD541D /* JavaScriptSandbox.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = JavaScriptSandbox.m; sourceTree = "<group>"; };
DE65AAC92317FFCD00290BEC /* LogUtils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LogUtils.h; sourceTree = "<group>"; };
DE65AACB2318028300290BEC /* JitsiMeetBaseLogHandler+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "JitsiMeetBaseLogHandler+Private.h"; sourceTree = "<group>"; };
@ -223,6 +227,8 @@
DEFE535521FB2E8300011A3A /* ReactUtils.m */,
0B93EF7C1EC9DDCD0030D24D /* RCTBridgeWrapper.h */,
0B93EF7D1EC9DDCD0030D24D /* RCTBridgeWrapper.m */,
C8AFD27D2462C613000293D2 /* InfoPlistUtil.h */,
C8AFD27E2462C613000293D2 /* InfoPlistUtil.m */,
);
path = src;
sourceTree = "<group>";
@ -303,6 +309,7 @@
DE81A2D42316AC4D00AE1940 /* JitsiMeetLogger.h in Headers */,
DE65AACA2317FFCD00290BEC /* LogUtils.h in Headers */,
DEAD3226220C497000E93636 /* JitsiMeetConferenceOptions.h in Headers */,
C8AFD27F2462C613000293D2 /* InfoPlistUtil.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -482,6 +489,7 @@
0B93EF7F1EC9DDCD0030D24D /* RCTBridgeWrapper.m in Sources */,
0BA13D311EE83FF8007BEF7F /* ExternalAPI.m in Sources */,
0BCA49601EC4B6C600B793EE /* POSIX.m in Sources */,
C8AFD2802462C613000293D2 /* InfoPlistUtil.m in Sources */,
C6CC49AF207412CF000DFA42 /* PiPViewCoordinator.swift in Sources */,
DEFC743F21B178FA00E4DD96 /* LocaleDetector.m in Sources */,
0BCA495F1EC4B6C600B793EE /* AudioMode.m in Sources */,

View File

@ -19,6 +19,8 @@
#import <React/RCTBridgeModule.h>
#import <React/RCTLog.h>
#import "InfoPlistUtil.h"
@interface AppInfo : NSObject<RCTBridgeModule>
@end
@ -67,13 +69,15 @@ RCT_EXPORT_MODULE();
buildNumber = @"";
}
BOOL isGoogleServiceEnabled = [InfoPlistUtil containsRealServiceInfoPlistInBundle:[NSBundle mainBundle]];
return @{
@"calendarEnabled": [NSNumber numberWithBool:calendarEnabled],
@"buildNumber": buildNumber,
@"name": name,
@"sdkBundlePath": sdkBundlePath,
@"version": version
@"version": version,
@"GOOGLE_SERVICES_ENABLED": [NSNumber numberWithBool:isGoogleServiceEnabled]
};
};
@end

View File

@ -0,0 +1,23 @@
/*
* Copyright @ 2019-present 8x8, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
@interface InfoPlistUtil : NSObject
+ (BOOL)containsRealServiceInfoPlistInBundle:(NSBundle *)bundle;
@end

View File

@ -0,0 +1,52 @@
/*
* Copyright @ 2019-present 8x8, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "InfoPlistUtil.h"
// Plist file name.
NSString *const kGoogleServiceInfoFileName = @"GoogleService-Info";
// Plist file type.
NSString *const kGoogleServiceInfoFileType = @"plist";
NSString *const kGoogleAppIDPlistKey = @"GOOGLE_APP_ID";
@implementation InfoPlistUtil
+ (BOOL)containsRealServiceInfoPlistInBundle:(NSBundle *)bundle {
NSString *bundlePath = bundle.bundlePath;
if (!bundlePath.length) {
return NO;
}
NSString *plistFilePath = [bundle pathForResource:kGoogleServiceInfoFileName
ofType:kGoogleServiceInfoFileType];
if (!plistFilePath.length) {
return NO;
}
NSDictionary *plist = [NSDictionary dictionaryWithContentsOfFile:plistFilePath];
if (!plist) {
return NO;
}
// Perform a very naive validation by checking to see if the plist has the dummy google app id
NSString *googleAppID = plist[kGoogleAppIDPlistKey];
if (!googleAppID.length) {
return NO;
}
return YES;
}
@end

View File

@ -20,6 +20,7 @@
#import <JitsiMeet/JitsiMeetConferenceOptions.h>
#import <JitsiMeet/JitsiMeetLogger.h>
#import <JitsiMeet/JitsiMeetBaseLogHandler.h>
#import <JitsiMeet/InfoPlistUtil.h>
@interface JitsiMeet : NSObject
@ -64,4 +65,6 @@
- (JitsiMeetConferenceOptions *_Nonnull)getInitialConferenceOptions;
- (BOOL)isCrashReportingDisabled;
@end

View File

@ -107,7 +107,7 @@
JitsiMeetConferenceOptions *conferenceOptions = [JitsiMeetConferenceOptions fromBuilder:^(JitsiMeetConferenceOptionsBuilder *builder) {
builder.room = [url absoluteString];
}];
return [JitsiMeetView setPropsInViews:[conferenceOptions asProps]];
}
@ -132,6 +132,11 @@
return nil;
}
- (BOOL)isCrashReportingDisabled {
NSUserDefaults *userDefaults = [[NSUserDefaults alloc] initWithSuiteName:@"jitsi-default-preferences"];
return [userDefaults stringForKey:@"isCrashReportingDisabled"];
}
- (JitsiMeetConferenceOptions *)optionsFromUserActivity:(NSUserActivity *)userActivity {
NSString *activityType = userActivity.activityType;

View File

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

5
package-lock.json generated
View File

@ -14827,6 +14827,11 @@
}
}
},
"react-native-default-preference": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/react-native-default-preference/-/react-native-default-preference-1.4.2.tgz",
"integrity": "sha512-kNhBLv8s6kO2gJJFEKM7qew7oRvJnygjgG1CU2ZEY6SlG5qsRX8z1Ms7z1Oo/XB7fVfyXrAoZDGhIvy+uiByrg=="
},
"react-native-immersive": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/react-native-immersive/-/react-native-immersive-2.0.0.tgz",

View File

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

View File

@ -2,6 +2,8 @@
import { NativeModules } from 'react-native';
import DefaultPreference from 'react-native-default-preference';
export * from './functions.any';
const { AudioMode } = NativeModules;
@ -19,3 +21,17 @@ export function handleCallIntegrationChange(disabled: boolean) {
AudioMode.setUseConnectionService(!disabled);
}
}
/**
* Handles changes to the `disableCrashReporting` setting.
* Stores the value into platform specific default preference file, so at app
* start-up time it is retrieved on the native side and the crash reporting
* is enabled/disabled.
*
* @param {boolean} disabled - Whether crash reporting is disabled or not.
* @returns {void}
*/
export function handleCrashReportingChange(disabled: boolean) {
DefaultPreference.setName('jitsi-default-preferences').then(
DefaultPreference.set('isCrashReportingDisabled', disabled.toString()));
}

View File

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

View File

@ -9,7 +9,7 @@ import { getLocalParticipant, participantUpdated } from '../participants';
import { MiddlewareRegistry } from '../redux';
import { SETTINGS_UPDATED } from './actionTypes';
import { handleCallIntegrationChange } from './functions';
import { handleCallIntegrationChange, handleCrashReportingChange } from './functions';
/**
* The middleware of the feature base/settings. Distributes changes to the state
@ -30,6 +30,7 @@ MiddlewareRegistry.register(store => next => action => {
_maybeHandleCallIntegrationChange(action);
_maybeSetAudioOnly(store, action);
_updateLocalParticipant(store, action);
_maybeCrashReportingChange(action);
break;
case SET_LOCATION_URL:
_updateLocalParticipantFromUrl(store);
@ -84,6 +85,19 @@ function _maybeHandleCallIntegrationChange({ settings: { disableCallIntegration
}
}
/**
* Handles a change in the `disableCrashReporting` setting.
*
* @param {Object} action - The redux action.
* @private
* @returns {void}
*/
function _maybeCrashReportingChange({ settings: { disableCrashReporting } }) {
if (typeof disableCrashReporting === 'boolean') {
handleCrashReportingChange(disableCrashReporting);
}
}
/**
* Updates {@code startAudioOnly} flag if it's updated in the settings.
*

View File

@ -24,6 +24,7 @@ const DEFAULT_STATE = {
avatarURL: undefined,
cameraDeviceId: undefined,
disableCallIntegration: undefined,
disableCrashReporting: undefined,
disableP2P: undefined,
displayName: undefined,
email: undefined,

View File

@ -36,6 +36,11 @@ type State = {
*/
disableP2P: boolean,
/**
* State variable for the disable crash reporting switch.
*/
disableCrashReporting: boolean,
/**
* State variable for the display name field.
*/
@ -84,6 +89,7 @@ class SettingsView extends AbstractSettingsView<Props, State> {
super(props);
const {
disableCallIntegration,
disableCrashReporting,
disableP2P,
displayName,
email,
@ -94,6 +100,7 @@ class SettingsView extends AbstractSettingsView<Props, State> {
this.state = {
disableCallIntegration,
disableCrashReporting,
disableP2P,
displayName,
email,
@ -107,6 +114,7 @@ class SettingsView extends AbstractSettingsView<Props, State> {
this._onBlurServerURL = this._onBlurServerURL.bind(this);
this._onClose = this._onClose.bind(this);
this._onDisableCallIntegration = this._onDisableCallIntegration.bind(this);
this._onDisableCrashReporting = this._onDisableCrashReporting.bind(this);
this._onDisableP2P = this._onDisableP2P.bind(this);
this._onShowAdvanced = this._onShowAdvanced.bind(this);
this._setURLFieldReference = this._setURLFieldReference.bind(this);
@ -285,6 +293,24 @@ class SettingsView extends AbstractSettingsView<Props, State> {
});
}
_onDisableCrashReporting: (boolean) => void;
/**
* Handles the disable crash reporting change event.
*
* @param {boolean} disableCrashReporting - The new value
* option.
* @private
* @returns {void}
*/
_onDisableCrashReporting(disableCrashReporting) {
if (disableCrashReporting) {
this._showCrashReportingDisableAlert();
} else {
this._disableCrashReporting(disableCrashReporting);
}
}
_onClose: () => void;
/**
@ -367,7 +393,7 @@ class SettingsView extends AbstractSettingsView<Props, State> {
* @returns {React$Element}
*/
_renderAdvancedSettings() {
const { disableCallIntegration, disableP2P, showAdvanced } = this.state;
const { disableCallIntegration, disableP2P, disableCrashReporting, showAdvanced } = this.state;
if (!showAdvanced) {
return (
@ -397,6 +423,15 @@ class SettingsView extends AbstractSettingsView<Props, State> {
onValueChange = { this._onDisableP2P }
value = { disableP2P } />
</FormRow>
{AppInfo.GOOGLE_SERVICES_ENABLED && (
<FormRow
fieldSeparator = { true }
label = 'settingsView.disableCrashReporting'>
<Switch
onValueChange = { this._onDisableCrashReporting }
value = { disableCrashReporting } />
</FormRow>
)}
</>
);
}
@ -436,7 +471,41 @@ class SettingsView extends AbstractSettingsView<Props, State> {
);
}
/**
* Shows an alert warning the user about disabling crash reporting.
*
* @returns {void}
*/
_showCrashReportingDisableAlert() {
const { t } = this.props;
Alert.alert(
t('settingsView.alertTitle'),
t('settingsView.disableCrashReportingWarning'),
[
{
onPress: () => this._disableCrashReporting(true),
text: t('settingsView.alertOk')
},
{
text: t('settingsView.alertCancel')
}
]
);
}
_updateSettings: (Object) => void;
/**
* Updates the settings and sets state for disableCrashReporting.
*
* @param {boolean} disableCrashReporting - Whether crash reporting is disabled or not.
* @returns {void}
*/
_disableCrashReporting(disableCrashReporting) {
this._updateSettings({ disableCrashReporting });
this.setState({ disableCrashReporting });
}
}
/**