`;
@@ -5157,10 +5118,9 @@ exports[`Storyshots UiKitMessage list uikitmessage 1`] = `
"fontSize": 20,
"fontWeight": "300",
"marginLeft": 10,
- "marginTop": 30,
+ "marginVertical": 30,
},
Object {
- "backgroundColor": "#ffffff",
"color": "#0d0e12",
},
undefined,
@@ -5176,10 +5136,9 @@ exports[`Storyshots UiKitMessage list uikitmessage 1`] = `
"fontSize": 20,
"fontWeight": "300",
"marginLeft": 10,
- "marginTop": 30,
+ "marginVertical": 30,
},
Object {
- "backgroundColor": "#ffffff",
"color": "#0d0e12",
},
undefined,
@@ -5195,10 +5154,9 @@ exports[`Storyshots UiKitMessage list uikitmessage 1`] = `
"fontSize": 20,
"fontWeight": "300",
"marginLeft": 10,
- "marginTop": 30,
+ "marginVertical": 30,
},
Object {
- "backgroundColor": "#ffffff",
"color": "#0d0e12",
},
undefined,
@@ -5214,10 +5172,9 @@ exports[`Storyshots UiKitMessage list uikitmessage 1`] = `
"fontSize": 20,
"fontWeight": "300",
"marginLeft": 10,
- "marginTop": 30,
+ "marginVertical": 30,
},
Object {
- "backgroundColor": "#ffffff",
"color": "#0d0e12",
},
undefined,
@@ -5233,10 +5190,9 @@ exports[`Storyshots UiKitMessage list uikitmessage 1`] = `
"fontSize": 20,
"fontWeight": "300",
"marginLeft": 10,
- "marginTop": 30,
+ "marginVertical": 30,
},
Object {
- "backgroundColor": "#ffffff",
"color": "#0d0e12",
},
undefined,
@@ -5252,10 +5208,9 @@ exports[`Storyshots UiKitMessage list uikitmessage 1`] = `
"fontSize": 20,
"fontWeight": "300",
"marginLeft": 10,
- "marginTop": 30,
+ "marginVertical": 30,
},
Object {
- "backgroundColor": "#ffffff",
"color": "#0d0e12",
},
undefined,
@@ -5271,10 +5226,9 @@ exports[`Storyshots UiKitMessage list uikitmessage 1`] = `
"fontSize": 20,
"fontWeight": "300",
"marginLeft": 10,
- "marginTop": 30,
+ "marginVertical": 30,
},
Object {
- "backgroundColor": "#ffffff",
"color": "#0d0e12",
},
undefined,
@@ -5290,10 +5244,9 @@ exports[`Storyshots UiKitMessage list uikitmessage 1`] = `
"fontSize": 20,
"fontWeight": "300",
"marginLeft": 10,
- "marginTop": 30,
+ "marginVertical": 30,
},
Object {
- "backgroundColor": "#ffffff",
"color": "#0d0e12",
},
undefined,
@@ -5309,10 +5262,9 @@ exports[`Storyshots UiKitMessage list uikitmessage 1`] = `
"fontSize": 20,
"fontWeight": "300",
"marginLeft": 10,
- "marginTop": 30,
+ "marginVertical": 30,
},
Object {
- "backgroundColor": "#ffffff",
"color": "#0d0e12",
},
undefined,
@@ -5328,10 +5280,9 @@ exports[`Storyshots UiKitMessage list uikitmessage 1`] = `
"fontSize": 20,
"fontWeight": "300",
"marginLeft": 10,
- "marginTop": 30,
+ "marginVertical": 30,
},
Object {
- "backgroundColor": "#ffffff",
"color": "#0d0e12",
},
undefined,
@@ -5347,10 +5298,9 @@ exports[`Storyshots UiKitMessage list uikitmessage 1`] = `
"fontSize": 20,
"fontWeight": "300",
"marginLeft": 10,
- "marginTop": 30,
+ "marginVertical": 30,
},
Object {
- "backgroundColor": "#ffffff",
"color": "#0d0e12",
},
undefined,
@@ -5366,10 +5316,9 @@ exports[`Storyshots UiKitMessage list uikitmessage 1`] = `
"fontSize": 20,
"fontWeight": "300",
"marginLeft": 10,
- "marginTop": 30,
+ "marginVertical": 30,
},
Object {
- "backgroundColor": "#ffffff",
"color": "#0d0e12",
},
undefined,
@@ -5385,10 +5334,9 @@ exports[`Storyshots UiKitMessage list uikitmessage 1`] = `
"fontSize": 20,
"fontWeight": "300",
"marginLeft": 10,
- "marginTop": 30,
+ "marginVertical": 30,
},
Object {
- "backgroundColor": "#ffffff",
"color": "#0d0e12",
},
undefined,
@@ -5434,10 +5382,9 @@ exports[`Storyshots UiKitModal list UiKitModal 1`] = `
"fontSize": 20,
"fontWeight": "300",
"marginLeft": 10,
- "marginTop": 30,
+ "marginVertical": 30,
},
Object {
- "backgroundColor": "#ffffff",
"color": "#0d0e12",
},
undefined,
@@ -5453,10 +5400,9 @@ exports[`Storyshots UiKitModal list UiKitModal 1`] = `
"fontSize": 20,
"fontWeight": "300",
"marginLeft": 10,
- "marginTop": 30,
+ "marginVertical": 30,
},
Object {
- "backgroundColor": "#ffffff",
"color": "#0d0e12",
},
undefined,
@@ -5472,10 +5418,9 @@ exports[`Storyshots UiKitModal list UiKitModal 1`] = `
"fontSize": 20,
"fontWeight": "300",
"marginLeft": 10,
- "marginTop": 30,
+ "marginVertical": 30,
},
Object {
- "backgroundColor": "#ffffff",
"color": "#0d0e12",
},
undefined,
@@ -5491,10 +5436,9 @@ exports[`Storyshots UiKitModal list UiKitModal 1`] = `
"fontSize": 20,
"fontWeight": "300",
"marginLeft": 10,
- "marginTop": 30,
+ "marginVertical": 30,
},
Object {
- "backgroundColor": "#ffffff",
"color": "#0d0e12",
},
undefined,
@@ -5510,10 +5454,9 @@ exports[`Storyshots UiKitModal list UiKitModal 1`] = `
"fontSize": 20,
"fontWeight": "300",
"marginLeft": 10,
- "marginTop": 30,
+ "marginVertical": 30,
},
Object {
- "backgroundColor": "#ffffff",
"color": "#0d0e12",
},
undefined,
@@ -5529,10 +5472,9 @@ exports[`Storyshots UiKitModal list UiKitModal 1`] = `
"fontSize": 20,
"fontWeight": "300",
"marginLeft": 10,
- "marginTop": 30,
+ "marginVertical": 30,
},
Object {
- "backgroundColor": "#ffffff",
"color": "#0d0e12",
},
undefined,
@@ -5548,10 +5490,9 @@ exports[`Storyshots UiKitModal list UiKitModal 1`] = `
"fontSize": 20,
"fontWeight": "300",
"marginLeft": 10,
- "marginTop": 30,
+ "marginVertical": 30,
},
Object {
- "backgroundColor": "#ffffff",
"color": "#0d0e12",
},
undefined,
@@ -5567,10 +5508,9 @@ exports[`Storyshots UiKitModal list UiKitModal 1`] = `
"fontSize": 20,
"fontWeight": "300",
"marginLeft": 10,
- "marginTop": 30,
+ "marginVertical": 30,
},
Object {
- "backgroundColor": "#ffffff",
"color": "#0d0e12",
},
undefined,
@@ -5586,10 +5526,9 @@ exports[`Storyshots UiKitModal list UiKitModal 1`] = `
"fontSize": 20,
"fontWeight": "300",
"marginLeft": 10,
- "marginTop": 30,
+ "marginVertical": 30,
},
Object {
- "backgroundColor": "#ffffff",
"color": "#0d0e12",
},
undefined,
@@ -5605,10 +5544,9 @@ exports[`Storyshots UiKitModal list UiKitModal 1`] = `
"fontSize": 20,
"fontWeight": "300",
"marginLeft": 10,
- "marginTop": 30,
+ "marginVertical": 30,
},
Object {
- "backgroundColor": "#ffffff",
"color": "#0d0e12",
},
undefined,
diff --git a/android/app/build.gradle b/android/app/build.gradle
index 8bf5d0f93..3a6635823 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -1,7 +1,7 @@
apply plugin: "com.android.application"
+apply plugin: 'com.google.gms.google-services'
+apply plugin: 'com.google.firebase.crashlytics'
apply plugin: 'kotlin-android'
-apply plugin: "io.fabric"
-apply plugin: "com.google.firebase.firebase-perf"
apply plugin: 'com.bugsnag.android.gradle'
import com.android.build.OutputFile
@@ -168,15 +168,18 @@ android {
minifyEnabled enableProguardInReleaseBuilds
setProguardFiles([getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'])
signingConfig signingConfigs.release
+ firebaseCrashlytics {
+ nativeSymbolUploadEnabled true
+ }
}
}
- packagingOptions {
- pickFirst '**/armeabi-v7a/libc++_shared.so'
- pickFirst '**/x86/libc++_shared.so'
- pickFirst '**/arm64-v8a/libc++_shared.so'
- pickFirst '**/x86_64/libc++_shared.so'
- }
+ // packagingOptions {
+ // pickFirst '**/armeabi-v7a/libc++_shared.so'
+ // pickFirst '**/x86/libc++_shared.so'
+ // pickFirst '**/arm64-v8a/libc++_shared.so'
+ // pickFirst '**/x86_64/libc++_shared.so'
+ // }
// applicationVariants are e.g. debug, release
applicationVariants.all { variant ->
@@ -215,11 +218,6 @@ dependencies {
//noinspection GradleDynamicVersion
implementation "com.facebook.react:react-native:+" // From node_modules
implementation "com.google.firebase:firebase-messaging:18.0.0"
- implementation "com.google.firebase:firebase-core:16.0.9"
- implementation "com.google.firebase:firebase-perf:17.0.2"
- implementation('com.crashlytics.sdk.android:crashlytics:2.9.9@aar') {
- transitive = true
- }
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0"
debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") {
exclude group:'com.facebook.fbjni'
@@ -251,5 +249,4 @@ task copyDownloadableDepsToLibs(type: Copy) {
into 'libs'
}
-apply plugin: 'com.google.gms.google-services'
apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
\ No newline at end of file
diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml
index 5cf3292c2..ed773abe1 100644
--- a/android/app/src/debug/AndroidManifest.xml
+++ b/android/app/src/debug/AndroidManifest.xml
@@ -1,8 +1,13 @@
+ xmlns:tools="http://schemas.android.com/tools"
+ package="chat.rocket.reactnative">
-
+
-
+
\ No newline at end of file
diff --git a/android/app/src/debug/java/chat/rocket/reactnative/MainDebugApplication.java b/android/app/src/debug/java/chat/rocket/reactnative/MainDebugApplication.java
new file mode 100644
index 000000000..e6abf3b05
--- /dev/null
+++ b/android/app/src/debug/java/chat/rocket/reactnative/MainDebugApplication.java
@@ -0,0 +1,25 @@
+package chat.rocket.reactnative;
+
+import android.content.Context;
+
+import com.facebook.react.ReactInstanceManager;
+
+public class MainDebugApplication extends MainApplication {
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
+ }
+
+ /**
+ * Loads Flipper in React Native templates. Call this in the onCreate method with something like
+ * initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
+ *
+ * @param context
+ * @param reactInstanceManager
+ */
+ private static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) {
+ ReactNativeFlipper.initializeFlipper(context, reactInstanceManager);
+ }
+}
diff --git a/android/app/src/debug/java/chat/rocket/reactnative/ReactNativeFlipper.java b/android/app/src/debug/java/chat/rocket/reactnative/ReactNativeFlipper.java
index 07e08afd4..42eaf35c8 100644
--- a/android/app/src/debug/java/chat/rocket/reactnative/ReactNativeFlipper.java
+++ b/android/app/src/debug/java/chat/rocket/reactnative/ReactNativeFlipper.java
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the LICENSE file in the root
* directory of this source tree.
*/
-package com.rndiffapp;
+package chat.rocket.reactnative;
import android.content.Context;
import com.facebook.flipper.android.AndroidFlipperClient;
import com.facebook.flipper.android.utils.FlipperUtils;
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index a672c0e28..ebfb8c74d 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -37,8 +37,10 @@
+
+
diff --git a/android/app/src/main/assets/fonts/custom.ttf b/android/app/src/main/assets/fonts/custom.ttf
index 6f30643ad..a96927b90 100644
Binary files a/android/app/src/main/assets/fonts/custom.ttf and b/android/app/src/main/assets/fonts/custom.ttf differ
diff --git a/android/app/src/main/java/chat/rocket/reactnative/Callback.java b/android/app/src/main/java/chat/rocket/reactnative/Callback.java
new file mode 100644
index 000000000..2c2b2833a
--- /dev/null
+++ b/android/app/src/main/java/chat/rocket/reactnative/Callback.java
@@ -0,0 +1,10 @@
+package chat.rocket.reactnative;
+
+import android.os.Bundle;
+import androidx.annotation.Nullable;
+
+public class Callback {
+ public void call(@Nullable Bundle bundle) {
+
+ }
+}
diff --git a/android/app/src/main/java/chat/rocket/reactnative/CustomPushNotification.java b/android/app/src/main/java/chat/rocket/reactnative/CustomPushNotification.java
index 17002faa0..46c086eae 100644
--- a/android/app/src/main/java/chat/rocket/reactnative/CustomPushNotification.java
+++ b/android/app/src/main/java/chat/rocket/reactnative/CustomPushNotification.java
@@ -14,8 +14,9 @@ import android.graphics.drawable.Icon;
import android.os.Build;
import android.os.Bundle;
import android.app.Person;
+import androidx.annotation.Nullable;
-import com.google.gson.*;
+import com.google.gson.Gson;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
import com.bumptech.glide.request.RequestOptions;
@@ -33,15 +34,18 @@ import java.util.List;
import java.util.Map;
import java.util.ArrayList;
import java.util.Date;
+import java.util.Iterator;
import static com.wix.reactnativenotifications.Defs.NOTIFICATION_RECEIVED_EVENT_NAME;
public class CustomPushNotification extends PushNotification {
public static ReactApplicationContext reactApplicationContext;
+ final NotificationManager notificationManager;
public CustomPushNotification(Context context, Bundle bundle, AppLifecycleFacade appLifecycleFacade, AppLaunchHelper appLaunchHelper, JsIOHelper jsIoHelper) {
super(context, bundle, appLifecycleFacade, appLaunchHelper, jsIoHelper);
reactApplicationContext = new ReactApplicationContext(context);
+ notificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
}
private static Map> notificationMessages = new HashMap>();
@@ -54,29 +58,39 @@ public class CustomPushNotification extends PushNotification {
@Override
public void onReceived() throws InvalidNotificationException {
- final Bundle bundle = mNotificationProps.asBundle();
+ Bundle received = mNotificationProps.asBundle();
+ Ejson receivedEjson = new Gson().fromJson(received.getString("ejson", "{}"), Ejson.class);
+ if (receivedEjson.notificationType != null && receivedEjson.notificationType.equals("message-id-only")) {
+ notificationLoad(receivedEjson, new Callback() {
+ @Override
+ public void call(@Nullable Bundle bundle) {
+ if (bundle != null) {
+ mNotificationProps = createProps(bundle);
+ }
+ }
+ });
+ }
+
+ // We should re-read these values since that can be changed by notificationLoad
+ Bundle bundle = mNotificationProps.asBundle();
+ Ejson loadedEjson = new Gson().fromJson(bundle.getString("ejson", "{}"), Ejson.class);
String notId = bundle.getString("notId", "1");
- String title = bundle.getString("title");
if (notificationMessages.get(notId) == null) {
notificationMessages.put(notId, new ArrayList());
}
- Gson gson = new Gson();
- Ejson ejson = gson.fromJson(bundle.getString("ejson", "{}"), Ejson.class);
-
- boolean hasSender = ejson.sender != null;
+ boolean hasSender = loadedEjson.sender != null;
+ String title = bundle.getString("title");
bundle.putLong("time", new Date().getTime());
- bundle.putString("username", hasSender ? ejson.sender.username : title);
- bundle.putString("senderId", hasSender ? ejson.sender._id : "1");
- bundle.putString("avatarUri", ejson.getAvatarUri());
+ bundle.putString("username", hasSender ? loadedEjson.sender.username : title);
+ bundle.putString("senderId", hasSender ? loadedEjson.sender._id : "1");
+ bundle.putString("avatarUri", loadedEjson.getAvatarUri());
notificationMessages.get(notId).add(bundle);
-
- super.postNotification(Integer.parseInt(notId));
-
+ postNotification(Integer.parseInt(notId));
notifyReceivedToJS();
}
@@ -96,9 +110,11 @@ public class CustomPushNotification extends PushNotification {
String notId = bundle.getString("notId", "1");
String title = bundle.getString("title");
String message = bundle.getString("message");
+ Boolean notificationLoaded = bundle.getBoolean("notificationLoaded", false);
+ Ejson ejson = new Gson().fromJson(bundle.getString("ejson", "{}"), Ejson.class);
notification
- .setContentTitle(title)
+ .setContentTitle(title)
.setContentText(message)
.setContentIntent(intent)
.setPriority(Notification.PRIORITY_HIGH)
@@ -109,10 +125,34 @@ public class CustomPushNotification extends PushNotification {
notificationColor(notification);
notificationChannel(notification);
notificationIcons(notification, bundle);
- notificationStyle(notification, notificationId, bundle);
- notificationReply(notification, notificationId, bundle);
notificationDismiss(notification, notificationId);
+ // if notificationType is null (RC < 3.5) or notificationType is different of message-id-only or notification was loaded successfully
+ if (ejson.notificationType == null || !ejson.notificationType.equals("message-id-only") || notificationLoaded) {
+ notificationStyle(notification, notificationId, bundle);
+ notificationReply(notification, notificationId, bundle);
+
+ // message couldn't be loaded from server (Fallback notification)
+ } else {
+ Gson gson = new Gson();
+ // iterate over the current notification ids to dismiss fallback notifications from same server
+ for (Map.Entry> bundleList : notificationMessages.entrySet()) {
+ // iterate over the notifications with this id (same host + rid)
+ Iterator iterator = bundleList.getValue().iterator();
+ while (iterator.hasNext()) {
+ Bundle not = (Bundle) iterator.next();
+ // get the notification info
+ Ejson notEjson = gson.fromJson(not.getString("ejson", "{}"), Ejson.class);
+ // if already has a notification from same server
+ if (ejson.serverURL().equals(notEjson.serverURL())) {
+ String id = not.getString("notId");
+ // cancel this notification
+ notificationManager.cancel(Integer.parseInt(id));
+ }
+ }
+ }
+ }
+
return notification;
}
@@ -300,4 +340,7 @@ public class CustomPushNotification extends PushNotification {
notification.setDeleteIntent(dismissPendingIntent);
}
+ private void notificationLoad(Ejson ejson, Callback callback) {
+ LoadNotification.load(reactApplicationContext, ejson, callback);
+ }
}
diff --git a/android/app/src/main/java/chat/rocket/reactnative/Ejson.java b/android/app/src/main/java/chat/rocket/reactnative/Ejson.java
index 48c370370..0c68e4755 100644
--- a/android/app/src/main/java/chat/rocket/reactnative/Ejson.java
+++ b/android/app/src/main/java/chat/rocket/reactnative/Ejson.java
@@ -9,6 +9,8 @@ public class Ejson {
String rid;
String type;
Sender sender;
+ String messageId;
+ String notificationType;
private String TOKEN_KEY = "reactnativemeteor_usertoken-";
private SharedPreferences sharedPreferences = RNUserDefaultsModule.getPreferences(CustomPushNotification.reactApplicationContext);
diff --git a/android/app/src/main/java/chat/rocket/reactnative/LoadNotification.java b/android/app/src/main/java/chat/rocket/reactnative/LoadNotification.java
new file mode 100644
index 000000000..9c4c03744
--- /dev/null
+++ b/android/app/src/main/java/chat/rocket/reactnative/LoadNotification.java
@@ -0,0 +1,101 @@
+package chat.rocket.reactnative;
+
+import android.os.Bundle;
+import android.content.Context;
+
+import okhttp3.Call;
+import okhttp3.OkHttpClient;
+import okhttp3.HttpUrl;
+import okhttp3.Request;
+import okhttp3.Response;
+import okhttp3.Interceptor;
+
+import com.google.gson.Gson;
+import java.io.IOException;
+
+import com.facebook.react.bridge.ReactApplicationContext;
+
+import chat.rocket.userdefaults.RNUserDefaultsModule;
+
+class JsonResponse {
+ Data data;
+
+ class Data {
+ Notification notification;
+
+ class Notification {
+ String notId;
+ String title;
+ String text;
+ Payload payload;
+
+ class Payload {
+ String host;
+ String rid;
+ String type;
+ Sender sender;
+ String messageId;
+ String notificationType;
+ String name;
+ String messageType;
+
+ class Sender {
+ String _id;
+ String username;
+ String name;
+ }
+ }
+ }
+ }
+}
+
+public class LoadNotification {
+ private static int RETRY_COUNT = 0;
+ private static int[] TIMEOUT = new int[]{ 0, 1, 3, 5, 10 };
+ private static String TOKEN_KEY = "reactnativemeteor_usertoken-";
+
+ public static void load(ReactApplicationContext reactApplicationContext, final Ejson ejson, Callback callback) {
+ final OkHttpClient client = new OkHttpClient();
+ HttpUrl.Builder url = HttpUrl.parse(ejson.serverURL().concat("/api/v1/push.get")).newBuilder();
+
+ Request request = new Request.Builder()
+ .header("x-user-id", ejson.userId())
+ .header("x-auth-token", ejson.token())
+ .url(url.addQueryParameter("id", ejson.messageId).build())
+ .build();
+
+ runRequest(client, request, callback);
+ }
+
+ private static void runRequest(OkHttpClient client, Request request, Callback callback) {
+ try {
+ Thread.sleep(TIMEOUT[RETRY_COUNT] * 1000);
+
+ Response response = client.newCall(request).execute();
+ String body = response.body().string();
+ if (!response.isSuccessful()) {
+ throw new Exception("Error");
+ }
+
+ Gson gson = new Gson();
+ JsonResponse json = gson.fromJson(body, JsonResponse.class);
+
+ Bundle bundle = new Bundle();
+ bundle.putString("notId", json.data.notification.notId);
+ bundle.putString("title", json.data.notification.title);
+ bundle.putString("message", json.data.notification.text);
+ bundle.putString("ejson", gson.toJson(json.data.notification.payload));
+ bundle.putBoolean("notificationLoaded", true);
+
+ callback.call(bundle);
+
+ } catch (Exception e) {
+ if (RETRY_COUNT <= TIMEOUT.length) {
+ RETRY_COUNT++;
+ runRequest(client, request, callback);
+ } else {
+ callback.call(null);
+ }
+ }
+ }
+}
diff --git a/android/app/src/main/java/chat/rocket/reactnative/MainApplication.java b/android/app/src/main/java/chat/rocket/reactnative/MainApplication.java
index 530a2a857..6bcc62be8 100644
--- a/android/app/src/main/java/chat/rocket/reactnative/MainApplication.java
+++ b/android/app/src/main/java/chat/rocket/reactnative/MainApplication.java
@@ -29,10 +29,6 @@ import com.wix.reactnativenotifications.core.notification.INotificationsApplicat
import com.wix.reactnativenotifications.core.notification.IPushNotification;
import com.wix.reactnativekeyboardinput.KeyboardInputPackage;
-import io.invertase.firebase.fabric.crashlytics.RNFirebaseCrashlyticsPackage;
-import io.invertase.firebase.analytics.RNFirebaseAnalyticsPackage;
-import io.invertase.firebase.perf.RNFirebasePerformancePackage;
-
import com.nozbe.watermelondb.WatermelonDBPackage;
import com.reactnativecommunity.viewpager.RNCViewPagerPackage;
@@ -53,9 +49,6 @@ public class MainApplication extends Application implements ReactApplication, IN
protected List getPackages() {
@SuppressWarnings("UnnecessaryLocalVariable")
List packages = new PackageList(this).getPackages();
- packages.add(new RNFirebaseCrashlyticsPackage());
- packages.add(new RNFirebaseAnalyticsPackage());
- packages.add(new RNFirebasePerformancePackage());
packages.add(new KeyboardInputPackage(MainApplication.this));
packages.add(new RNNotificationsPackage(MainApplication.this));
packages.add(new WatermelonDBPackage());
@@ -88,38 +81,6 @@ public class MainApplication extends Application implements ReactApplication, IN
public void onCreate() {
super.onCreate();
SoLoader.init(this, /* native exopackage */ false);
- initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
- }
-
- /**
- * Loads Flipper in React Native templates. Call this in the onCreate method with something like
- * initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
- *
- * @param context
- * @param reactInstanceManager
- */
- private static void initializeFlipper(
- Context context, ReactInstanceManager reactInstanceManager) {
- if (BuildConfig.DEBUG) {
- try {
- /*
- We use reflection here to pick up the class that initializes Flipper,
- since Flipper library is not available in release mode
- */
- Class> aClass = Class.forName("chat.rocket.reactnative");
- aClass
- .getMethod("initializeFlipper", Context.class, ReactInstanceManager.class)
- .invoke(null, context, reactInstanceManager);
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- } catch (NoSuchMethodException e) {
- e.printStackTrace();
- } catch (IllegalAccessException e) {
- e.printStackTrace();
- } catch (InvocationTargetException e) {
- e.printStackTrace();
- }
- }
}
@Override
diff --git a/android/build.gradle b/android/build.gradle
index f1e95820c..52f6ff0f0 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -1,10 +1,10 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext {
- buildToolsVersion = "28.0.3"
+ buildToolsVersion = "29.0.2"
minSdkVersion = 21
- compileSdkVersion = 28
- targetSdkVersion = 28
+ compileSdkVersion = 29
+ targetSdkVersion = 29
glideVersion = "4.9.0"
kotlin_version = "1.3.50"
supportLibVersion = "28.0.0"
@@ -18,10 +18,9 @@ buildscript {
}
}
dependencies {
- classpath 'com.android.tools.build:gradle:3.5.2'
+ classpath 'com.android.tools.build:gradle:3.5.3'
classpath 'com.google.gms:google-services:4.2.0'
- classpath 'io.fabric.tools:gradle:1.28.1'
- classpath 'com.google.firebase:perf-plugin:1.2.1'
+ classpath 'com.google.firebase:firebase-crashlytics-gradle:2.0.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'com.bugsnag:bugsnag-android-gradle-plugin:4.+'
@@ -57,10 +56,10 @@ subprojects { subproject ->
afterEvaluate {
if ((subproject.plugins.hasPlugin('android') || subproject.plugins.hasPlugin('android-library'))) {
android {
- compileSdkVersion 28
- buildToolsVersion "28.0.3"
+ compileSdkVersion 29
+ buildToolsVersion "29.0.2"
defaultConfig {
- targetSdkVersion 28
+ targetSdkVersion 29
}
variantFilter { variant ->
def names = variant.flavors*.name
diff --git a/android/gradle.properties b/android/gradle.properties
index a7df71591..26d0e8372 100644
--- a/android/gradle.properties
+++ b/android/gradle.properties
@@ -27,7 +27,7 @@ android.useAndroidX=true
android.enableJetifier=true
# Version of flipper SDK to use with React Native
-FLIPPER_VERSION=0.33.1
+FLIPPER_VERSION=0.51.0
# App properties
VERSIONCODE=999999999
diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties
index e8758b6d5..7578b974b 100644
--- a/android/gradle/wrapper/gradle-wrapper.properties
+++ b/android/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-6.0.1-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
\ No newline at end of file
diff --git a/android/gradlew b/android/gradlew
index 77564ddb2..645f6ca31 100755
--- a/android/gradlew
+++ b/android/gradlew
@@ -154,19 +154,19 @@ if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
else
eval `echo args$i`="\"$arg\""
fi
- i=$((i+1))
+ i=`expr $i + 1`
done
case $i in
- (0) set -- ;;
- (1) set -- "$args0" ;;
- (2) set -- "$args0" "$args1" ;;
- (3) set -- "$args0" "$args1" "$args2" ;;
- (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
- (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
- (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
- (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
- (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
- (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ 0) set -- ;;
+ 1) set -- "$args0" ;;
+ 2) set -- "$args0" "$args1" ;;
+ 3) set -- "$args0" "$args1" "$args2" ;;
+ 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
@@ -175,14 +175,9 @@ save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
-APP_ARGS=$(save "$@")
+APP_ARGS=`save "$@"`
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
-# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
-if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
- cd "$(dirname "$0")"
-fi
-
exec "$JAVACMD" "$@"
\ No newline at end of file
diff --git a/android/gradlew.bat b/android/gradlew.bat
index 7d3e0e477..8d8accd7c 100644
--- a/android/gradlew.bat
+++ b/android/gradlew.bat
@@ -5,7 +5,7 @@
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
-@rem http://www.apache.org/licenses/LICENSE-2.0
+@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@@ -29,6 +29,9 @@ if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
diff --git a/app/actions/actionsTypes.js b/app/actions/actionsTypes.js
index 65c39d9c6..3fec00201 100644
--- a/app/actions/actionsTypes.js
+++ b/app/actions/actionsTypes.js
@@ -33,6 +33,7 @@ export const ROOMS = createRequestTypes('ROOMS', [
'CLOSE_SEARCH_HEADER'
]);
export const ROOM = createRequestTypes('ROOM', ['SUBSCRIBE', 'UNSUBSCRIBE', 'LEAVE', 'DELETE', 'REMOVED', 'CLOSE', 'FORWARD', 'USER_TYPING']);
+export const INQUIRY = createRequestTypes('INQUIRY', [...defaultTypes, 'SET_ENABLED', 'RESET', 'QUEUE_ADD', 'QUEUE_UPDATE', 'QUEUE_REMOVE']);
export const APP = createRequestTypes('APP', ['START', 'READY', 'INIT', 'INIT_LOCAL_SETTINGS', 'SET_MASTER_DETAIL']);
export const MESSAGES = createRequestTypes('MESSAGES', ['REPLY_BROADCAST']);
export const CREATE_CHANNEL = createRequestTypes('CREATE_CHANNEL', [...defaultTypes]);
diff --git a/app/actions/inquiry.js b/app/actions/inquiry.js
new file mode 100644
index 000000000..0f3402119
--- /dev/null
+++ b/app/actions/inquiry.js
@@ -0,0 +1,55 @@
+import * as types from './actionsTypes';
+
+export function inquirySetEnabled(enabled) {
+ return {
+ type: types.INQUIRY.SET_ENABLED,
+ enabled
+ };
+}
+
+export function inquiryReset() {
+ return {
+ type: types.INQUIRY.RESET
+ };
+}
+
+export function inquiryQueueAdd(inquiry) {
+ return {
+ type: types.INQUIRY.QUEUE_ADD,
+ inquiry
+ };
+}
+
+export function inquiryQueueUpdate(inquiry) {
+ return {
+ type: types.INQUIRY.QUEUE_UPDATE,
+ inquiry
+ };
+}
+
+export function inquiryQueueRemove(inquiryId) {
+ return {
+ type: types.INQUIRY.QUEUE_REMOVE,
+ inquiryId
+ };
+}
+
+export function inquiryRequest() {
+ return {
+ type: types.INQUIRY.REQUEST
+ };
+}
+
+export function inquirySuccess(inquiries) {
+ return {
+ type: types.INQUIRY.SUCCESS,
+ inquiries
+ };
+}
+
+export function inquiryFailure(error) {
+ return {
+ type: types.INQUIRY.FAILURE,
+ error
+ };
+}
diff --git a/app/constants/colors.js b/app/constants/colors.js
index 0b0a8ae7f..f3ad72dc4 100644
--- a/app/constants/colors.js
+++ b/app/constants/colors.js
@@ -10,6 +10,16 @@ export const SWITCH_TRACK_COLOR = {
true: '#2de0a5'
};
+const mentions = {
+ unreadBackground: '#414852',
+ mentionMeColor: '#f5455c',
+ mentionMeBackground: '#ffe9ec',
+ mentionGroupColor: '#f38c39',
+ mentionGroupBackground: '#fde8d7',
+ mentionOtherColor: '#b68d00',
+ mentionOtherBackground: '#fff6d6'
+};
+
export const themes = {
light: {
backgroundColor: '#ffffff',
@@ -53,7 +63,8 @@ export const themes = {
passcodeDotEmpty: '#CBCED1',
passcodeDotFull: '#6C727A',
previewBackground: '#1F2329',
- previewTintColor: '#ffffff'
+ previewTintColor: '#ffffff',
+ ...mentions
},
dark: {
backgroundColor: '#030b1b',
@@ -97,7 +108,8 @@ export const themes = {
passcodeDotEmpty: '#CBCED1',
passcodeDotFull: '#6C727A',
previewBackground: '#030b1b',
- previewTintColor: '#ffffff'
+ previewTintColor: '#ffffff',
+ ...mentions
},
black: {
backgroundColor: '#000000',
@@ -141,6 +153,7 @@ export const themes = {
passcodeDotEmpty: '#CBCED1',
passcodeDotFull: '#6C727A',
previewBackground: '#000000',
- previewTintColor: '#ffffff'
+ previewTintColor: '#ffffff',
+ ...mentions
}
};
diff --git a/app/containers/Avatar.js b/app/containers/Avatar.js
index 66bef8411..c4ed0ba7c 100644
--- a/app/containers/Avatar.js
+++ b/app/containers/Avatar.js
@@ -1,7 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import { View } from 'react-native';
-import FastImage from 'react-native-fast-image';
+import FastImage from '@rocket.chat/react-native-fast-image';
import Touchable from 'react-native-platform-touchable';
import { settings as RocketChatSettings } from '@rocket.chat/sdk';
diff --git a/app/containers/EmojiPicker/CustomEmoji.js b/app/containers/EmojiPicker/CustomEmoji.js
index 381695d05..934155fec 100644
--- a/app/containers/EmojiPicker/CustomEmoji.js
+++ b/app/containers/EmojiPicker/CustomEmoji.js
@@ -1,5 +1,5 @@
import React from 'react';
-import FastImage from 'react-native-fast-image';
+import FastImage from '@rocket.chat/react-native-fast-image';
import PropTypes from 'prop-types';
const CustomEmoji = React.memo(({ baseUrl, emoji, style }) => (
diff --git a/app/containers/HeaderButton.js b/app/containers/HeaderButton.js
index e712a7e1e..cd1808d2f 100644
--- a/app/containers/HeaderButton.js
+++ b/app/containers/HeaderButton.js
@@ -28,7 +28,7 @@ export const CustomHeaderButtons = React.memo(props => (
export const DrawerButton = React.memo(({ navigation, testID, ...otherProps }) => (
-
+
));
@@ -36,7 +36,7 @@ export const CloseModalButton = React.memo(({
navigation, testID, onPress = () => navigation.pop(), ...props
}) => (
-
+
));
@@ -44,14 +44,14 @@ export const CancelModalButton = React.memo(({ onPress, testID }) => (
{isIOS
?
- :
+ :
}
));
export const MoreButton = React.memo(({ onPress, testID }) => (
-
+
));
diff --git a/app/containers/InAppNotification/NotifierComponent.js b/app/containers/InAppNotification/NotifierComponent.js
index 084c2fc0c..be0896c7a 100644
--- a/app/containers/InAppNotification/NotifierComponent.js
+++ b/app/containers/InAppNotification/NotifierComponent.js
@@ -90,6 +90,8 @@ const NotifierComponent = React.memo(({
if (isMasterDetail) {
Navigation.navigate('DrawerNavigator');
+ } else {
+ Navigation.navigate('RoomsListView');
}
goRoom({ item, isMasterDetail });
hideNotification();
@@ -125,7 +127,7 @@ const NotifierComponent = React.memo(({
hitSlop={BUTTON_HIT_SLOP}
background={Touchable.SelectableBackgroundBorderless()}
>
-
+
);
diff --git a/app/containers/InAppNotification/index.js b/app/containers/InAppNotification/index.js
index fd0ad6368..dd6573f33 100644
--- a/app/containers/InAppNotification/index.js
+++ b/app/containers/InAppNotification/index.js
@@ -14,7 +14,7 @@ const InAppNotification = memo(() => {
const state = Navigation.navigationRef.current?.getRootState();
const route = getActiveRoute(state);
if (payload.rid) {
- if (route?.name === 'RoomView' && route.params?.rid === payload.rid) {
+ if ((route?.name === 'RoomView' && route.params?.rid === payload.rid) || route?.name === 'JitsiMeetView') {
return;
}
Notifier.showNotification({
diff --git a/app/containers/LoginServices.js b/app/containers/LoginServices.js
index 11ffc6d97..417e6523a 100644
--- a/app/containers/LoginServices.js
+++ b/app/containers/LoginServices.js
@@ -15,6 +15,7 @@ import OrSeparator from './OrSeparator';
import Touch from '../utils/touch';
import I18n from '../i18n';
import random from '../utils/random';
+import { logEvent, events } from '../utils/log';
import RocketChat from '../lib/rocketchat';
const BUTTON_HEIGHT = 48;
@@ -77,6 +78,7 @@ class LoginServices extends React.PureComponent {
}
onPressFacebook = () => {
+ logEvent(events.ENTER_WITH_FACEBOOK);
const { services, server } = this.props;
const { clientId } = services.facebook;
const endpoint = 'https://m.facebook.com/v2.9/dialog/oauth';
@@ -88,6 +90,7 @@ class LoginServices extends React.PureComponent {
}
onPressGithub = () => {
+ logEvent(events.ENTER_WITH_GITHUB);
const { services, server } = this.props;
const { clientId } = services.github;
const endpoint = `https://github.com/login?client_id=${ clientId }&return_to=${ encodeURIComponent('/login/oauth/authorize') }`;
@@ -99,6 +102,7 @@ class LoginServices extends React.PureComponent {
}
onPressGitlab = () => {
+ logEvent(events.ENTER_WITH_GITLAB);
const { services, server, Gitlab_URL } = this.props;
const { clientId } = services.gitlab;
const baseURL = Gitlab_URL ? Gitlab_URL.trim().replace(/\/*$/, '') : 'https://gitlab.com';
@@ -111,6 +115,7 @@ class LoginServices extends React.PureComponent {
}
onPressGoogle = () => {
+ logEvent(events.ENTER_WITH_GOOGLE);
const { services, server } = this.props;
const { clientId } = services.google;
const endpoint = 'https://accounts.google.com/o/oauth2/auth';
@@ -122,6 +127,7 @@ class LoginServices extends React.PureComponent {
}
onPressLinkedin = () => {
+ logEvent(events.ENTER_WITH_LINKEDIN);
const { services, server } = this.props;
const { clientId } = services.linkedin;
const endpoint = 'https://www.linkedin.com/oauth/v2/authorization';
@@ -133,6 +139,7 @@ class LoginServices extends React.PureComponent {
}
onPressMeteor = () => {
+ logEvent(events.ENTER_WITH_METEOR);
const { services, server } = this.props;
const { clientId } = services['meteor-developer'];
const endpoint = 'https://www.meteor.com/oauth2/authorize';
@@ -143,6 +150,7 @@ class LoginServices extends React.PureComponent {
}
onPressTwitter = () => {
+ logEvent(events.ENTER_WITH_TWITTER);
const { server } = this.props;
const state = this.getOAuthState();
const url = `${ server }/_oauth/twitter/?requestTokenAndRedirect=true&state=${ state }`;
@@ -150,6 +158,7 @@ class LoginServices extends React.PureComponent {
}
onPressWordpress = () => {
+ logEvent(events.ENTER_WITH_WORDPRESS);
const { services, server } = this.props;
const { clientId, serverURL } = services.wordpress;
const endpoint = `${ serverURL }/oauth/authorize`;
@@ -161,6 +170,7 @@ class LoginServices extends React.PureComponent {
}
onPressCustomOAuth = (loginService) => {
+ logEvent(events.ENTER_WITH_CUSTOM_OAUTH);
const { server } = this.props;
const {
serverURL, authorizePath, clientId, scope, service
@@ -175,6 +185,7 @@ class LoginServices extends React.PureComponent {
}
onPressSaml = (loginService) => {
+ logEvent(events.ENTER_WITH_SAML);
const { server } = this.props;
const { clientConfig } = loginService;
const { provider } = clientConfig;
@@ -184,6 +195,7 @@ class LoginServices extends React.PureComponent {
}
onPressCas = () => {
+ logEvent(events.ENTER_WITH_CAS);
const { server, CAS_login_url } = this.props;
const ssoToken = random(17);
const url = `${ CAS_login_url }?service=${ server }/_cas/${ ssoToken }`;
@@ -191,6 +203,7 @@ class LoginServices extends React.PureComponent {
}
onPressAppleLogin = async() => {
+ logEvent(events.ENTER_WITH_APPLE);
try {
const { fullName, email, identityToken } = await AppleAuthentication.signInAsync({
requestedScopes: [
@@ -201,7 +214,7 @@ class LoginServices extends React.PureComponent {
await RocketChat.loginOAuthOrSso({ fullName, email, identityToken });
} catch {
- // Do nothing
+ logEvent(events.ENTER_WITH_APPLE_F);
}
}
diff --git a/app/containers/MessageActions/Header.js b/app/containers/MessageActions/Header.js
index 7847069e1..b7d981d7e 100644
--- a/app/containers/MessageActions/Header.js
+++ b/app/containers/MessageActions/Header.js
@@ -78,7 +78,7 @@ const HeaderFooter = React.memo(({ onReaction, theme }) => (
style={[styles.headerItem, { backgroundColor: themes[theme].auxiliaryBackground }]}
theme={theme}
>
-
+
));
HeaderFooter.propTypes = {
diff --git a/app/containers/MessageActions/index.js b/app/containers/MessageActions/index.js
index 7846e1d70..ff4c4dbf2 100644
--- a/app/containers/MessageActions/index.js
+++ b/app/containers/MessageActions/index.js
@@ -7,7 +7,7 @@ import moment from 'moment';
import RocketChat from '../../lib/rocketchat';
import database from '../../lib/database';
import I18n from '../../i18n';
-import log from '../../utils/log';
+import log, { logEvent } from '../../utils/log';
import Navigation from '../../lib/Navigation';
import { getMessageTranslation } from '../message/utils';
import { LISTENER } from '../Toast';
@@ -15,6 +15,7 @@ import EventEmitter from '../../utils/events';
import { showConfirmationAlert } from '../../utils/info';
import { useActionSheet } from '../ActionSheet';
import Header, { HEADER_HEIGHT } from './Header';
+import events from '../../utils/log/events';
const MessageActions = React.memo(forwardRef(({
room,
@@ -112,11 +113,18 @@ const MessageActions = React.memo(forwardRef(({
const getPermalink = message => RocketChat.getPermalinkMessage(message);
- const handleReply = message => replyInit(message, true);
+ const handleReply = (message) => {
+ logEvent(events.ROOM_MSG_ACTION_REPLY);
+ replyInit(message, true);
+ };
- const handleEdit = message => editInit(message);
+ const handleEdit = (message) => {
+ logEvent(events.ROOM_MSG_ACTION_EDIT);
+ editInit(message);
+ };
const handleCreateDiscussion = (message) => {
+ logEvent(events.ROOM_MSG_ACTION_DISCUSSION);
const params = { message, channel: room, showCloseModal: true };
if (isMasterDetail) {
Navigation.navigate('ModalStackNavigator', { screen: 'CreateDiscussionView', params });
@@ -126,6 +134,7 @@ const MessageActions = React.memo(forwardRef(({
};
const handleUnread = async(message) => {
+ logEvent(events.ROOM_MSG_ACTION_UNREAD);
const { id: messageId, ts } = message;
const { rid } = room;
try {
@@ -144,54 +153,66 @@ const MessageActions = React.memo(forwardRef(({
Navigation.navigate('RoomsListView');
}
} catch (e) {
+ logEvent(events.ROOM_MSG_ACTION_UNREAD_F);
log(e);
}
};
const handlePermalink = async(message) => {
+ logEvent(events.ROOM_MSG_ACTION_PERMALINK);
try {
const permalink = await getPermalink(message);
Clipboard.setString(permalink);
EventEmitter.emit(LISTENER, { message: I18n.t('Permalink_copied_to_clipboard') });
} catch {
- // Do nothing
+ logEvent(events.ROOM_MSG_ACTION_PERMALINK_F);
}
};
const handleCopy = async(message) => {
+ logEvent(events.ROOM_MSG_ACTION_COPY);
await Clipboard.setString(message.msg);
EventEmitter.emit(LISTENER, { message: I18n.t('Copied_to_clipboard') });
};
const handleShare = async(message) => {
+ logEvent(events.ROOM_MSG_ACTION_SHARE);
try {
const permalink = await getPermalink(message);
Share.share({ message: permalink });
} catch {
- // Do nothing
+ logEvent(events.ROOM_MSG_ACTION_SHARE_F);
}
};
- const handleQuote = message => replyInit(message, false);
+ const handleQuote = (message) => {
+ logEvent(events.ROOM_MSG_ACTION_QUOTE);
+ replyInit(message, false);
+ };
const handleStar = async(message) => {
+ logEvent(message.starred ? events.ROOM_MSG_ACTION_UNSTAR : events.ROOM_MSG_ACTION_STAR);
try {
await RocketChat.toggleStarMessage(message.id, message.starred);
EventEmitter.emit(LISTENER, { message: message.starred ? I18n.t('Message_unstarred') : I18n.t('Message_starred') });
} catch (e) {
+ logEvent(events.ROOM_MSG_ACTION_STAR_F);
log(e);
}
};
const handlePin = async(message) => {
+ logEvent(events.ROOM_MSG_ACTION_PIN);
try {
await RocketChat.togglePinMessage(message.id, message.pinned);
} catch (e) {
+ logEvent(events.ROOM_MSG_ACTION_PIN_F);
log(e);
}
};
const handleReaction = (shortname, message) => {
+ logEvent(events.ROOM_MSG_ACTION_REACTION);
if (shortname) {
onReactionPress(shortname, message.id);
} else {
@@ -201,7 +222,13 @@ const MessageActions = React.memo(forwardRef(({
hideActionSheet();
};
- const handleReadReceipt = message => Navigation.navigate('ReadReceiptsView', { messageId: message.id });
+ const handleReadReceipt = (message) => {
+ if (isMasterDetail) {
+ Navigation.navigate('ModalStackNavigator', { screen: 'ReadReceiptsView', params: { messageId: message.id } });
+ } else {
+ Navigation.navigate('ReadReceiptsView', { messageId: message.id });
+ }
+ };
const handleToggleTranslation = async(message) => {
try {
@@ -228,10 +255,12 @@ const MessageActions = React.memo(forwardRef(({
};
const handleReport = async(message) => {
+ logEvent(events.ROOM_MSG_ACTION_REPORT);
try {
await RocketChat.reportMessage(message.id);
Alert.alert(I18n.t('Message_Reported'));
} catch (e) {
+ logEvent(events.ROOM_MSG_ACTION_REPORT_F);
log(e);
}
};
@@ -242,8 +271,10 @@ const MessageActions = React.memo(forwardRef(({
callToAction: I18n.t('Delete'),
onPress: async() => {
try {
+ logEvent(events.ROOM_MSG_ACTION_DELETE);
await RocketChat.deleteMessage(message.id, message.subscription.id);
} catch (e) {
+ logEvent(events.ROOM_MSG_ACTION_DELETE_F);
log(e);
}
}
@@ -290,7 +321,7 @@ const MessageActions = React.memo(forwardRef(({
// Create Discussion
options.push({
title: I18n.t('Start_a_Discussion'),
- icon: 'chat',
+ icon: 'discussions',
onPress: () => handleCreateDiscussion(message)
});
@@ -365,7 +396,7 @@ const MessageActions = React.memo(forwardRef(({
if (allowDelete(message)) {
options.push({
title: I18n.t('Delete'),
- icon: 'trash',
+ icon: 'delete',
danger: true,
onPress: () => handleDelete(message)
});
@@ -375,6 +406,7 @@ const MessageActions = React.memo(forwardRef(({
};
const showMessageActions = async(message) => {
+ logEvent(events.ROOM_SHOW_MSG_ACTIONS);
await getPermissions();
showActionSheet({
options: getOptions(message),
diff --git a/app/containers/MessageBox/CommandsPreview/Item.js b/app/containers/MessageBox/CommandsPreview/Item.js
index 2909f57ee..9fa026dd5 100644
--- a/app/containers/MessageBox/CommandsPreview/Item.js
+++ b/app/containers/MessageBox/CommandsPreview/Item.js
@@ -1,7 +1,7 @@
import React, { useContext, useState } from 'react';
import PropTypes from 'prop-types';
import { TouchableOpacity } from 'react-native';
-import FastImage from 'react-native-fast-image';
+import FastImage from '@rocket.chat/react-native-fast-image';
import styles from '../styles';
import { CustomIcon } from '../../../lib/Icons';
@@ -32,7 +32,7 @@ const Item = ({ item, theme }) => {
{ loading ? : null }
)
- :
+ :
}
);
diff --git a/app/containers/MessageBox/RecordAudio.js b/app/containers/MessageBox/RecordAudio.js
index b9e94988c..5d277023b 100644
--- a/app/containers/MessageBox/RecordAudio.js
+++ b/app/containers/MessageBox/RecordAudio.js
@@ -10,6 +10,7 @@ import styles from './styles';
import I18n from '../../i18n';
import { themes } from '../../constants/colors';
import { CustomIcon } from '../../lib/Icons';
+import { logEvent, events } from '../../utils/log';
const RECORDING_EXTENSION = '.aac';
const RECORDING_SETTINGS = {
@@ -103,6 +104,7 @@ export default class RecordAudio extends React.PureComponent {
}
startRecordingAudio = async() => {
+ logEvent(events.ROOM_AUDIO_RECORD);
if (!this.isRecorderBusy) {
this.isRecorderBusy = true;
try {
@@ -120,13 +122,14 @@ export default class RecordAudio extends React.PureComponent {
await Audio.requestPermissionsAsync();
}
} catch (error) {
- // Do nothing
+ logEvent(events.ROOM_AUDIO_RECORD_F);
}
this.isRecorderBusy = false;
}
};
finishRecordingAudio = async() => {
+ logEvent(events.ROOM_AUDIO_FINISH);
if (!this.isRecorderBusy) {
const { onFinish } = this.props;
@@ -147,7 +150,7 @@ export default class RecordAudio extends React.PureComponent {
onFinish(fileInfo);
} catch (error) {
- // Do nothing
+ logEvent(events.ROOM_AUDIO_FINISH_F);
}
this.setState({ isRecording: false, recordingDurationMillis: 0 });
deactivateKeepAwake();
@@ -156,12 +159,13 @@ export default class RecordAudio extends React.PureComponent {
};
cancelRecordingAudio = async() => {
+ logEvent(events.ROOM_AUDIO_CANCEL);
if (!this.isRecorderBusy) {
this.isRecorderBusy = true;
try {
await this.recording.stopAndUnloadAsync();
} catch (error) {
- // Do nothing
+ logEvent(events.ROOM_AUDIO_CANCEL_F);
}
this.setState({ isRecording: false, recordingDurationMillis: 0 });
deactivateKeepAwake();
@@ -182,7 +186,7 @@ export default class RecordAudio extends React.PureComponent {
accessibilityLabel={I18n.t('Send_audio_message')}
accessibilityTraits='button'
>
-
+
);
}
@@ -199,7 +203,7 @@ export default class RecordAudio extends React.PureComponent {
-
+
);
}, (prevProps, nextProps) => prevProps.replying === nextProps.replying && prevProps.theme === nextProps.theme && isEqual(prevProps.message, nextProps.message));
diff --git a/app/containers/MessageBox/buttons/ActionsButton.js b/app/containers/MessageBox/buttons/ActionsButton.js
index ddfdb94e6..5738e71ba 100644
--- a/app/containers/MessageBox/buttons/ActionsButton.js
+++ b/app/containers/MessageBox/buttons/ActionsButton.js
@@ -8,7 +8,7 @@ const ActionsButton = React.memo(({ theme, onPress }) => (
onPress={onPress}
testID='messagebox-actions'
accessibilityLabel='Message_actions'
- icon='plus'
+ icon='add'
theme={theme}
/>
));
diff --git a/app/containers/MessageBox/buttons/CancelEditingButton.js b/app/containers/MessageBox/buttons/CancelEditingButton.js
index 04f1db9d8..1a6e69bb1 100644
--- a/app/containers/MessageBox/buttons/CancelEditingButton.js
+++ b/app/containers/MessageBox/buttons/CancelEditingButton.js
@@ -8,7 +8,7 @@ const CancelEditingButton = React.memo(({ theme, onPress }) => (
onPress={onPress}
testID='messagebox-cancel-editing'
accessibilityLabel='Cancel_editing'
- icon='Cross'
+ icon='close'
theme={theme}
/>
));
diff --git a/app/containers/MessageBox/buttons/SendButton.js b/app/containers/MessageBox/buttons/SendButton.js
index ef7896dae..4419a316d 100644
--- a/app/containers/MessageBox/buttons/SendButton.js
+++ b/app/containers/MessageBox/buttons/SendButton.js
@@ -8,7 +8,7 @@ const SendButton = React.memo(({ theme, onPress }) => (
onPress={onPress}
testID='messagebox-send-message'
accessibilityLabel='Send_message'
- icon='send-active'
+ icon='send-filled'
theme={theme}
/>
));
diff --git a/app/containers/MessageBox/index.js b/app/containers/MessageBox/index.js
index 813d7d64c..cf1396240 100644
--- a/app/containers/MessageBox/index.js
+++ b/app/containers/MessageBox/index.js
@@ -17,8 +17,8 @@ import RocketChat from '../../lib/rocketchat';
import styles from './styles';
import database from '../../lib/database';
import { emojis } from '../../emojis';
+import log, { logEvent, events } from '../../utils/log';
import RecordAudio from './RecordAudio';
-import log from '../../utils/log';
import I18n from '../../i18n';
import ReplyPreview from './ReplyPreview';
import debounce from '../../utils/debounce';
@@ -122,6 +122,7 @@ class MessageBox extends Component {
command: {}
};
this.text = '';
+ this.selection = { start: 0, end: 0 };
this.focused = false;
// MessageBox Actions
@@ -133,7 +134,7 @@ class MessageBox extends Component {
},
{
title: I18n.t('Take_a_video'),
- icon: 'video-1',
+ icon: 'camera',
onPress: this.takeVideo
},
{
@@ -143,12 +144,12 @@ class MessageBox extends Component {
},
{
title: I18n.t('Choose_file'),
- icon: 'folder',
+ icon: 'attach',
onPress: this.chooseFile
},
{
title: I18n.t('Create_Discussion'),
- icon: 'chat',
+ icon: 'discussions',
onPress: this.createDiscussion
}
];
@@ -331,6 +332,10 @@ class MessageBox extends Component {
this.setInput(text);
}
+ onSelectionChange = (e) => {
+ this.selection = e.nativeEvent.selection;
+ }
+
// eslint-disable-next-line react/sort-comp
debouncedOnChangeText = debounce(async(text) => {
const { sharing } = this.props;
@@ -358,9 +363,9 @@ class MessageBox extends Component {
if (!isTextEmpty) {
try {
- const { start, end } = this.component?.lastNativeSelection;
+ const { start, end } = this.selection;
const cursor = Math.max(start, end);
- const lastNativeText = this.component?.lastNativeText || '';
+ const lastNativeText = this.text;
// matches if text either starts with '/' or have (@,#,:) then it groups whatever comes next of mention type
let regexp = /(#|@|:|^\/)([a-z0-9._-]+)$/im;
@@ -399,7 +404,7 @@ class MessageBox extends Component {
}
const { trackingType } = this.state;
const msg = this.text;
- const { start, end } = this.component?.lastNativeSelection;
+ const { start, end } = this.selection;
const cursor = Math.max(start, end);
const regexp = /([a-z0-9._-]+)$/im;
const result = msg.substr(0, cursor).replace(regexp, '');
@@ -410,7 +415,8 @@ class MessageBox extends Component {
if ((trackingType === MENTIONS_TRACKING_TYPE_COMMANDS) && item.providesPreview) {
this.setState({ showCommandPreview: true });
}
- this.setInput(text);
+ const newCursor = cursor + mentionName.length;
+ this.setInput(text, { start: newCursor, end: newCursor });
this.focus();
requestAnimationFrame(() => this.stopTrackingMention());
}
@@ -443,15 +449,11 @@ class MessageBox extends Component {
let newText = '';
// if messagebox has an active cursor
- if (this.component?.lastNativeSelection) {
- const { start, end } = this.component.lastNativeSelection;
- const cursor = Math.max(start, end);
- newText = `${ text.substr(0, cursor) }${ emoji }${ text.substr(cursor) }`;
- } else {
- // if messagebox doesn't have a cursor, just append selected emoji
- newText = `${ text }${ emoji }`;
- }
- this.setInput(newText);
+ const { start, end } = this.selection;
+ const cursor = Math.max(start, end);
+ newText = `${ text.substr(0, cursor) }${ emoji }${ text.substr(cursor) }`;
+ const newCursor = cursor + emoji.length;
+ this.setInput(newText, { start: newCursor, end: newCursor });
this.setShowSend(true);
}
@@ -551,11 +553,12 @@ class MessageBox extends Component {
this.setState({ commandPreview: [], showCommandPreview: true, command: {} });
}
- setInput = (text) => {
+ setInput = (text, selection) => {
this.text = text;
- if (this.component && this.component.setNativeProps) {
- this.component.setNativeProps({ text });
+ if (selection) {
+ return this.component.setTextAndSelection(text, selection);
}
+ this.component.setNativeProps({ text });
}
setShowSend = (showSend) => {
@@ -582,37 +585,41 @@ class MessageBox extends Component {
}
takePhoto = async() => {
+ logEvent(events.ROOM_BOX_ACTION_PHOTO);
try {
const image = await ImagePicker.openCamera(this.imagePickerConfig);
if (this.canUploadFile(image)) {
this.openShareView([image]);
}
} catch (e) {
- // Do nothing
+ logEvent(events.ROOM_BOX_ACTION_PHOTO_F);
}
}
takeVideo = async() => {
+ logEvent(events.ROOM_BOX_ACTION_VIDEO);
try {
const video = await ImagePicker.openCamera(this.videoPickerConfig);
if (this.canUploadFile(video)) {
this.openShareView([video]);
}
} catch (e) {
- // Do nothing
+ logEvent(events.ROOM_BOX_ACTION_VIDEO_F);
}
}
chooseFromLibrary = async() => {
+ logEvent(events.ROOM_BOX_ACTION_LIBRARY);
try {
const attachments = await ImagePicker.openPicker(this.libraryPickerConfig);
this.openShareView(attachments);
} catch (e) {
- // Do nothing
+ logEvent(events.ROOM_BOX_ACTION_LIBRARY_F);
}
}
chooseFile = async() => {
+ logEvent(events.ROOM_BOX_ACTION_FILE);
try {
const res = await DocumentPicker.pick({
type: [DocumentPicker.types.allFiles]
@@ -628,6 +635,7 @@ class MessageBox extends Component {
}
} catch (e) {
if (!DocumentPicker.isCancel(e)) {
+ logEvent(events.ROOM_BOX_ACTION_FILE_F);
log(e);
}
}
@@ -645,6 +653,7 @@ class MessageBox extends Component {
}
createDiscussion = () => {
+ logEvent(events.ROOM_BOX_ACTION_DISCUSSION);
const { isMasterDetail } = this.props;
const params = { channel: this.room, showCloseModal: true };
if (isMasterDetail) {
@@ -655,6 +664,7 @@ class MessageBox extends Component {
}
showMessageBoxActions = () => {
+ logEvent(events.ROOM_SHOW_BOX_ACTIONS);
const { showActionSheet } = this.props;
showActionSheet({ options: this.options });
}
@@ -665,10 +675,9 @@ class MessageBox extends Component {
this.clearInput();
}
- openEmoji = async() => {
- await this.setState({
- showEmojiKeyboard: true
- });
+ openEmoji = () => {
+ logEvent(events.ROOM_OPEN_EMOJI);
+ this.setState({ showEmojiKeyboard: true });
}
recordingCallback = (recording) => {
@@ -729,6 +738,7 @@ class MessageBox extends Component {
Q.where('id', Q.like(`${ Q.sanitizeLikeString(command) }%`))
).fetch();
if (slashCommand.length > 0) {
+ logEvent(events.COMMAND_RUN);
try {
const messageWithoutCommand = message.replace(/([^\s]+)/, '').trim();
const [{ appId }] = slashCommand;
@@ -736,6 +746,7 @@ class MessageBox extends Component {
RocketChat.runSlashCommand(command, roomId, messageWithoutCommand, triggerId, tmid || messageTmid);
replyCancel();
} catch (e) {
+ logEvent(events.COMMAND_RUN_F);
log(e);
}
this.clearInput();
@@ -888,6 +899,7 @@ class MessageBox extends Component {
blurOnSubmit={false}
placeholder={I18n.t('New_Message')}
onChangeText={this.onChangeText}
+ onSelectionChange={this.onSelectionChange}
underlineColorAndroid='transparent'
defaultValue=''
multiline
diff --git a/app/containers/MessageErrorActions.js b/app/containers/MessageErrorActions.js
index bc7b6bc05..c9975b0e3 100644
--- a/app/containers/MessageErrorActions.js
+++ b/app/containers/MessageErrorActions.js
@@ -81,7 +81,7 @@ const MessageErrorActions = forwardRef(({ tmid }, ref) => {
},
{
title: I18n.t('Delete'),
- icon: 'trash',
+ icon: 'delete',
danger: true,
onPress: () => handleDelete(message)
}
diff --git a/app/containers/Passcode/Base/LockIcon.js b/app/containers/Passcode/Base/LockIcon.js
index 023a355c7..133485cba 100644
--- a/app/containers/Passcode/Base/LockIcon.js
+++ b/app/containers/Passcode/Base/LockIcon.js
@@ -10,7 +10,7 @@ import { CustomIcon } from '../../../lib/Icons';
const LockIcon = React.memo(({ theme }) => (
-
+
));
diff --git a/app/containers/ReactionsModal.js b/app/containers/ReactionsModal.js
index 97812d0e7..68e95a33f 100644
--- a/app/containers/ReactionsModal.js
+++ b/app/containers/ReactionsModal.js
@@ -104,7 +104,7 @@ const ModalContent = React.memo(({
{I18n.t('Reactions')}
diff --git a/app/containers/RoomTypeIcon.js b/app/containers/RoomTypeIcon.js
index 42b8b90b9..77b70c0a9 100644
--- a/app/containers/RoomTypeIcon.js
+++ b/app/containers/RoomTypeIcon.js
@@ -20,19 +20,19 @@ const RoomTypeIcon = React.memo(({
const color = themes[theme].auxiliaryText;
- let icon = 'lock';
+ let icon = 'channel-private';
if (type === 'discussion') {
- icon = 'chat';
+ icon = 'discussions';
} else if (type === 'c') {
- icon = 'hash';
+ icon = 'channel-public';
} else if (type === 'd') {
if (isGroupChat) {
icon = 'team';
} else {
- icon = 'at';
+ icon = 'mention';
}
} else if (type === 'l') {
- icon = 'livechat';
+ icon = 'omnichannel';
}
return (
diff --git a/app/containers/SearchBox.js b/app/containers/SearchBox.js
index 89c51def1..75ed7f080 100644
--- a/app/containers/SearchBox.js
+++ b/app/containers/SearchBox.js
@@ -61,7 +61,7 @@ const SearchBox = ({
]}
>
-
+
{
InteractionManager.runAfterInteractions(() => e?.getNativeRef()?.focus())}
returnKeyType='send'
autoCapitalize='none'
onChangeText={setCode}
diff --git a/app/containers/TwoFactor/styles.js b/app/containers/TwoFactor/styles.js
index 36608408a..1c5c789cb 100644
--- a/app/containers/TwoFactor/styles.js
+++ b/app/containers/TwoFactor/styles.js
@@ -14,9 +14,10 @@ export default StyleSheet.create({
borderRadius: 4
},
title: {
- fontSize: 14,
+ fontSize: 16,
paddingBottom: 8,
- ...sharedStyles.textBold
+ ...sharedStyles.textBold,
+ ...sharedStyles.textAlignCenter
},
subtitle: {
fontSize: 14,
diff --git a/app/containers/UIKit/Image.js b/app/containers/UIKit/Image.js
index b21805e3d..dd7eaa944 100644
--- a/app/containers/UIKit/Image.js
+++ b/app/containers/UIKit/Image.js
@@ -1,6 +1,6 @@
import React from 'react';
import { View, StyleSheet } from 'react-native';
-import FastImage from 'react-native-fast-image';
+import FastImage from '@rocket.chat/react-native-fast-image';
import PropTypes from 'prop-types';
import { BLOCK_CONTEXT } from '@rocket.chat/ui-kit';
diff --git a/app/containers/UIKit/MultiSelect/Chips.js b/app/containers/UIKit/MultiSelect/Chips.js
index 9d0eb0a20..47827141d 100644
--- a/app/containers/UIKit/MultiSelect/Chips.js
+++ b/app/containers/UIKit/MultiSelect/Chips.js
@@ -2,7 +2,7 @@ import React from 'react';
import { Text, View } from 'react-native';
import PropTypes from 'prop-types';
import Touchable from 'react-native-platform-touchable';
-import FastImage from 'react-native-fast-image';
+import FastImage from '@rocket.chat/react-native-fast-image';
import { themes } from '../../../constants/colors';
import { textParser } from '../utils';
@@ -24,7 +24,7 @@ const Chip = ({
<>
{item.imageUrl ? : null}
{textParser([item.text])}
-
+
>
);
diff --git a/app/containers/UIKit/MultiSelect/Items.js b/app/containers/UIKit/MultiSelect/Items.js
index 7a460ac47..4418600f5 100644
--- a/app/containers/UIKit/MultiSelect/Items.js
+++ b/app/containers/UIKit/MultiSelect/Items.js
@@ -2,7 +2,7 @@ import React from 'react';
import { Text, FlatList } from 'react-native';
import PropTypes from 'prop-types';
import Touchable from 'react-native-platform-touchable';
-import FastImage from 'react-native-fast-image';
+import FastImage from '@rocket.chat/react-native-fast-image';
import Separator from '../../Separator';
import Check from '../../Check';
diff --git a/app/containers/UIKit/Overflow.js b/app/containers/UIKit/Overflow.js
index 6d76f6f3f..5acc4e9fe 100644
--- a/app/containers/UIKit/Overflow.js
+++ b/app/containers/UIKit/Overflow.js
@@ -82,7 +82,7 @@ export const Overflow = ({
hitSlop={BUTTON_HIT_SLOP}
style={styles.menu}
>
- {!loading ? : }
+ {!loading ? : }
{
- let mentionStyle = { ...styles.mention, color: themes[theme].buttonText };
if (mention === 'all' || mention === 'here') {
- return {mention};
+ return (
+ {mention}
+
+ );
}
+ let mentionStyle = {};
if (mention === username) {
mentionStyle = {
- ...mentionStyle,
- backgroundColor: themes[theme].actionTintColor
+ color: themes[theme].mentionMeColor,
+ backgroundColor: themes[theme].mentionMeBackground
};
} else {
mentionStyle = {
- ...mentionStyle,
- color: themes[theme].actionTintColor
+ color: themes[theme].mentionOtherColor,
+ backgroundColor: themes[theme].mentionOtherBackground
};
}
- const user = mentions && mentions.length && mentions.find(m => m.username === mention);
+ const user = mentions?.find?.(m => m && m.username === mention);
const handlePress = () => {
+ logEvent(events.ROOM_MENTION_GO_USER_INFO);
const navParam = {
t: 'd',
rid: user && user._id
@@ -39,7 +53,7 @@ const AtMention = React.memo(({
if (user) {
return (
{useRealName && user.name ? user.name : user.username}
diff --git a/app/containers/markdown/Hashtag.js b/app/containers/markdown/Hashtag.js
index 655d3a737..cccb1fb27 100644
--- a/app/containers/markdown/Hashtag.js
+++ b/app/containers/markdown/Hashtag.js
@@ -21,10 +21,16 @@ const Hashtag = React.memo(({
if (channels && channels.length && channels.findIndex(channel => channel.name === hashtag) !== -1) {
return (
- {hashtag}
+ {`#${ hashtag }`}
);
}
diff --git a/app/containers/markdown/index.js b/app/containers/markdown/index.js
index 4da997194..99fb38424 100644
--- a/app/containers/markdown/index.js
+++ b/app/containers/markdown/index.js
@@ -383,9 +383,9 @@ class Markdown extends PureComponent {
m = m.replace(/^\[([\s]]*)\]\(([^)]*)\)\s/, '').trim();
if (preview) {
- m = m.replace(/\n+/g, ' ');
m = shortnameToUnicode(m);
m = removeMarkdown(m);
+ m = m.replace(/\n+/g, ' ');
return (
{m}
diff --git a/app/containers/markdown/styles.js b/app/containers/markdown/styles.js
index c60c77c9d..d005f90f1 100644
--- a/app/containers/markdown/styles.js
+++ b/app/containers/markdown/styles.js
@@ -54,13 +54,9 @@ export default StyleSheet.create({
temp: { opacity: 0.3 },
mention: {
fontSize: 16,
- color: '#0072FE',
padding: 5,
...sharedStyles.textMedium,
- backgroundColor: '#E8F2FF'
- },
- mentionAll: {
- backgroundColor: '#FF5B5A'
+ letterSpacing: 0.5
},
paragraph: {
marginTop: 0,
diff --git a/app/containers/message/Audio.js b/app/containers/message/Audio.js
index 74410fa3f..fad195890 100644
--- a/app/containers/message/Audio.js
+++ b/app/containers/message/Audio.js
@@ -79,7 +79,7 @@ const Button = React.memo(({
{
loading
?
- :
+ :
}
));
diff --git a/app/containers/message/Broadcast.js b/app/containers/message/Broadcast.js
index d4ebe1264..58de1d0dc 100644
--- a/app/containers/message/Broadcast.js
+++ b/app/containers/message/Broadcast.js
@@ -26,7 +26,7 @@ const Broadcast = React.memo(({
testID='message-broadcast-reply'
>
<>
-
+
{I18n.t('Reply')}
>
diff --git a/app/containers/message/CallButton.js b/app/containers/message/CallButton.js
index 2a68237e0..83dcd370d 100644
--- a/app/containers/message/CallButton.js
+++ b/app/containers/message/CallButton.js
@@ -22,7 +22,7 @@ const CallButton = React.memo(({
hitSlop={BUTTON_HIT_SLOP}
>
<>
-
+
{I18n.t('Click_to_join')}
>
diff --git a/app/containers/message/Discussion.js b/app/containers/message/Discussion.js
index 4cdc81abf..c45906c97 100644
--- a/app/containers/message/Discussion.js
+++ b/app/containers/message/Discussion.js
@@ -29,7 +29,7 @@ const Discussion = React.memo(({
hitSlop={BUTTON_HIT_SLOP}
>
<>
-
+
{buttonText}
>
diff --git a/app/containers/message/Image.js b/app/containers/message/Image.js
index 499e793a7..1471b449e 100644
--- a/app/containers/message/Image.js
+++ b/app/containers/message/Image.js
@@ -1,7 +1,7 @@
import React, { useContext } from 'react';
import { View } from 'react-native';
import PropTypes from 'prop-types';
-import FastImage from 'react-native-fast-image';
+import FastImage from '@rocket.chat/react-native-fast-image';
import equal from 'deep-equal';
import { createImageProgress } from 'react-native-image-progress';
import * as Progress from 'react-native-progress';
diff --git a/app/containers/message/Reactions.js b/app/containers/message/Reactions.js
index 6ff654221..7502057f6 100644
--- a/app/containers/message/Reactions.js
+++ b/app/containers/message/Reactions.js
@@ -23,7 +23,7 @@ const AddReaction = React.memo(({ theme }) => {
hitSlop={BUTTON_HIT_SLOP}
>
-
+
);
diff --git a/app/containers/message/Urls.js b/app/containers/message/Urls.js
index b5e43bf6d..946433d43 100644
--- a/app/containers/message/Urls.js
+++ b/app/containers/message/Urls.js
@@ -3,7 +3,7 @@ import {
View, Text, StyleSheet, Clipboard
} from 'react-native';
import PropTypes from 'prop-types';
-import FastImage from 'react-native-fast-image';
+import FastImage from '@rocket.chat/react-native-fast-image';
import isEqual from 'lodash/isEqual';
import Touchable from './Touchable';
diff --git a/app/containers/message/Video.js b/app/containers/message/Video.js
index 3998f2fa0..2e9ef6c2a 100644
--- a/app/containers/message/Video.js
+++ b/app/containers/message/Video.js
@@ -49,7 +49,7 @@ const Video = React.memo(({
background={Touchable.Ripple(themes[theme].bannerBackground)}
>
diff --git a/app/i18n/locales/en.js b/app/i18n/locales/en.js
index e6038732e..72ebbdb4e 100644
--- a/app/i18n/locales/en.js
+++ b/app/i18n/locales/en.js
@@ -483,6 +483,7 @@ export default {
Tags: 'Tags',
Take_a_photo: 'Take a photo',
Take_a_video: 'Take a video',
+ Take_it: 'Take it!',
tap_to_change_status: 'tap to change status',
Tap_to_view_servers_list: 'Tap to view servers list',
Terms_of_Service: ' Terms of Service ',
@@ -621,5 +622,7 @@ export default {
Passcode_app_locked_title: 'App locked',
Passcode_app_locked_subtitle: 'Try again in {{timeLeft}} seconds',
After_seconds_set_by_admin: 'After {{seconds}} seconds (set by admin)',
- Dont_activate: 'Don\'t activate now'
+ Dont_activate: 'Don\'t activate now',
+ Queued_chats: 'Queued chats',
+ Queue_is_empty: 'Queue is empty'
};
diff --git a/app/i18n/locales/pt-BR.js b/app/i18n/locales/pt-BR.js
index 5e1d2342b..8ed4e76da 100644
--- a/app/i18n/locales/pt-BR.js
+++ b/app/i18n/locales/pt-BR.js
@@ -108,8 +108,10 @@ export default {
are_typing: 'estão digitando',
Are_you_sure_question_mark: 'Você tem certeza?',
Are_you_sure_you_want_to_leave_the_room: 'Tem certeza de que deseja sair da sala {{room}}?',
+ Audio: 'Áudio',
Authenticating: 'Autenticando',
Automatic: 'Automático',
+ Auto_Translate: 'Tradução automática',
Avatar_changed_successfully: 'Avatar alterado com sucesso!',
Avatar_Url: 'Avatar URL',
Away: 'Ausente',
@@ -172,6 +174,7 @@ export default {
DELETE: 'EXCLUIR',
deleting_room: 'excluindo sala',
Direct_Messages: 'Mensagens Diretas',
+ DESKTOP_OPTIONS: 'OPÇÕES DE ÁREA DE TRABALHO',
Directory: 'Diretório',
description: 'descrição',
Description: 'Descrição',
@@ -192,6 +195,7 @@ export default {
Email: 'Email',
email: 'e-mail',
Empty_title: 'Título vazio',
+ Enable_Auto_Translate: 'Ativar a tradução automática',
Enable_notifications: 'Habilitar notificações',
Everyone_can_access_this_channel: 'Todos podem acessar este canal',
Error_uploading: 'Erro subindo',
@@ -234,6 +238,7 @@ export default {
Message_HideType_room_unarchived: 'Sala desarquivada',
IP: 'IP',
In_app: 'No app',
+ In_App_and_Desktop_Alert_info: 'Exibe um banner na parte superior da tela quando o aplicativo é aberto e exibe uma notificação na área de trabalho',
Invisible: 'Invisível',
Invite: 'Convidar',
is_typing: 'está digitando',
@@ -299,6 +304,9 @@ export default {
Nothing_to_save: 'Nada para salvar!',
Notify_active_in_this_room: 'Notificar usuários ativos nesta sala',
Notify_all_in_this_room: 'Notificar todos nesta sala',
+ Notifications: 'Notificações',
+ Notification_Duration: 'Duração da notificação',
+ Notification_Preferences: 'Preferências de notificação',
Not_RC_Server: 'Este não é um servidor Rocket.Chat.\n{{contact}}',
No_available_agents_to_transfer: 'Nenhum agente disponível para transferência',
Offline: 'Offline',
@@ -340,6 +348,7 @@ export default {
Profile: 'Perfil',
Public_Channel: 'Canal Público',
Public: 'Público',
+ Push_Notifications_Alert_Info: 'Essas notificações são entregues a você quando o aplicativo não está aberto',
Quote: 'Citar',
Reactions_are_disabled: 'Reagir está desabilitado',
Reactions_are_enabled: 'Reagir está habilitado',
@@ -348,6 +357,8 @@ export default {
Read_External_Permission: 'Permissão de acesso à arquivos',
Read_Only_Channel: 'Canal Somente Leitura',
Read_Only: 'Somente Leitura',
+ Receive_Group_Mentions: 'Receber menções de grupo',
+ Receive_Group_Mentions_Info: 'Receber menções @all e @here',
Register: 'Registrar',
Read_Receipt: 'Lida por',
Repeat_Password: 'Repetir Senha',
@@ -355,6 +366,8 @@ export default {
replies: 'respostas',
reply: 'resposta',
Reply: 'Responder',
+ Receive_Notification: 'Receber Notificação',
+ Receive_notifications_from: 'Receber notificação de {{name}}',
Resend: 'Reenviar',
Reset_password: 'Resetar senha',
resetting_password: 'redefinindo senha',
@@ -411,10 +424,13 @@ export default {
Share: 'Compartilhar',
Share_Link: 'Share Link',
Show_more: 'Mostrar mais..',
+ Show_Unread_Counter: 'Mostrar contador não lido',
+ Show_Unread_Counter_Info: 'O contador não lido é exibido como um emblema à direita do canal, na lista',
Sign_in_your_server: 'Entrar no seu servidor',
Sign_Up: 'Registrar',
Some_field_is_invalid_or_empty: 'Algum campo está inválido ou vazio',
Sorting_by: 'Ordenando por {{key}}',
+ Sound: 'Som da notificação',
Star_room: 'Favoritar sala',
Star: 'Favorito',
Starred_Messages: 'Mensagens Favoritas',
@@ -551,5 +567,7 @@ export default {
Passcode_app_locked_title: 'Aplicativo bloqueado',
Passcode_app_locked_subtitle: 'Tente novamente em {{timeLeft}} segundos',
After_seconds_set_by_admin: 'Após {{seconds}} segundos (Configurado pelo adm)',
- Dont_activate: 'Não ativar agora'
+ Dont_activate: 'Não ativar agora',
+ Queued_chats: 'Bate-papos na fila',
+ Queue_is_empty: 'A fila está vazia'
};
diff --git a/app/index.js b/app/index.js
index 220f50839..e4d9e52cf 100644
--- a/app/index.js
+++ b/app/index.js
@@ -50,6 +50,13 @@ const parseDeepLinking = (url) => {
return parseQuery(url);
}
}
+ const call = /^(https:\/\/)?jitsi.rocket.chat\//;
+ if (url.match(call)) {
+ url = url.replace(call, '').trim();
+ if (url) {
+ return { path: url, isCall: true };
+ }
+ }
}
return null;
};
diff --git a/app/lib/database/model/Server.js b/app/lib/database/model/Server.js
index 5ff103fac..d30b3a3f4 100644
--- a/app/lib/database/model/Server.js
+++ b/app/lib/database/model/Server.js
@@ -25,4 +25,6 @@ export default class Server extends Model {
@field('auto_lock_time') autoLockTime;
@field('biometry') biometry;
+
+ @field('unique_id') uniqueID;
}
diff --git a/app/lib/database/model/Subscription.js b/app/lib/database/model/Subscription.js
index 77efd3783..a94e09423 100644
--- a/app/lib/database/model/Subscription.js
+++ b/app/lib/database/model/Subscription.js
@@ -40,6 +40,8 @@ export default class Subscription extends Model {
@field('user_mentions') userMentions;
+ @field('group_mentions') groupMentions;
+
@date('room_updated_at') roomUpdatedAt;
@field('ro') ro;
diff --git a/app/lib/database/model/migrations.js b/app/lib/database/model/migrations.js
index 260209427..db3b92dc3 100644
--- a/app/lib/database/model/migrations.js
+++ b/app/lib/database/model/migrations.js
@@ -118,6 +118,17 @@ export default schemaMigrations({
]
})
]
+ },
+ {
+ toVersion: 9,
+ steps: [
+ addColumns({
+ table: 'subscriptions',
+ columns: [
+ { name: 'group_mentions', type: 'number', isOptional: true }
+ ]
+ })
+ ]
}
]
});
diff --git a/app/lib/database/model/serversMigrations.js b/app/lib/database/model/serversMigrations.js
index 0163d3bde..8d74b0434 100644
--- a/app/lib/database/model/serversMigrations.js
+++ b/app/lib/database/model/serversMigrations.js
@@ -26,6 +26,17 @@ export default schemaMigrations({
]
})
]
+ },
+ {
+ toVersion: 5,
+ steps: [
+ addColumns({
+ table: 'servers',
+ columns: [
+ { name: 'unique_id', type: 'string', isOptional: true }
+ ]
+ })
+ ]
}
]
});
diff --git a/app/lib/database/schema/app.js b/app/lib/database/schema/app.js
index 97784b3f9..59336e3f0 100644
--- a/app/lib/database/schema/app.js
+++ b/app/lib/database/schema/app.js
@@ -1,7 +1,7 @@
import { appSchema, tableSchema } from '@nozbe/watermelondb';
export default appSchema({
- version: 8,
+ version: 9,
tables: [
tableSchema({
name: 'subscriptions',
@@ -19,6 +19,7 @@ export default appSchema({
{ name: 'roles', type: 'string', isOptional: true },
{ name: 'unread', type: 'number' },
{ name: 'user_mentions', type: 'number' },
+ { name: 'group_mentions', type: 'number' },
{ name: 'room_updated_at', type: 'number' },
{ name: 'ro', type: 'boolean' },
{ name: 'last_open', type: 'number', isOptional: true },
diff --git a/app/lib/database/schema/servers.js b/app/lib/database/schema/servers.js
index 7557f8b1c..b02859e10 100644
--- a/app/lib/database/schema/servers.js
+++ b/app/lib/database/schema/servers.js
@@ -1,7 +1,7 @@
import { appSchema, tableSchema } from '@nozbe/watermelondb';
export default appSchema({
- version: 4,
+ version: 5,
tables: [
tableSchema({
name: 'users',
@@ -28,7 +28,8 @@ export default appSchema({
{ name: 'last_local_authenticated_session', type: 'number', isOptional: true },
{ name: 'auto_lock', type: 'boolean', isOptional: true },
{ name: 'auto_lock_time', type: 'number', isOptional: true },
- { name: 'biometry', type: 'boolean', isOptional: true }
+ { name: 'biometry', type: 'boolean', isOptional: true },
+ { name: 'unique_id', type: 'string', isOptional: true }
]
})
]
diff --git a/app/lib/methods/callJitsi.js b/app/lib/methods/callJitsi.js
index 92f7bc447..7410ed8bd 100644
--- a/app/lib/methods/callJitsi.js
+++ b/app/lib/methods/callJitsi.js
@@ -1,41 +1,41 @@
import reduxStore from '../createStore';
import Navigation from '../Navigation';
+import { logEvent, events } from '../../utils/log';
+
+async function jitsiURL({ rid }) {
+ const { settings } = reduxStore.getState();
+ const { Jitsi_Enabled } = settings;
-const jitsiBaseUrl = ({
- Jitsi_Enabled, Jitsi_SSL, Jitsi_Domain, Jitsi_URL_Room_Prefix, uniqueID
-}) => {
if (!Jitsi_Enabled) {
return '';
}
- const uniqueIdentifier = uniqueID || 'undefined';
- const domain = Jitsi_Domain;
+
+ const {
+ Jitsi_Domain, Jitsi_URL_Room_Prefix, Jitsi_SSL, Jitsi_Enabled_TokenAuth, uniqueID
+ } = settings;
+
+ const domain = `${ Jitsi_Domain }/`;
const prefix = Jitsi_URL_Room_Prefix;
+ const uniqueIdentifier = uniqueID || 'undefined';
+ const protocol = Jitsi_SSL ? 'https://' : 'http://';
- const urlProtocol = Jitsi_SSL ? 'https://' : 'http://';
- const urlDomain = `${ domain }/`;
-
- return `${ urlProtocol }${ urlDomain }${ prefix }${ uniqueIdentifier }`;
-};
-
-async function callJitsi(rid, onlyAudio = false) {
- let accessToken;
let queryString = '';
- const { settings } = reduxStore.getState();
- const { Jitsi_Enabled_TokenAuth } = settings;
-
if (Jitsi_Enabled_TokenAuth) {
try {
- accessToken = await this.methodCallWrapper('jitsi:generateAccessToken', rid);
- } catch (e) {
- // do nothing
+ const accessToken = await this.methodCallWrapper('jitsi:generateAccessToken', rid);
+ queryString = `?jwt=${ accessToken }`;
+ } catch {
+ logEvent(events.RA_JITSI_F);
}
}
- if (accessToken) {
- queryString = `?jwt=${ accessToken }`;
- }
+ return `${ protocol }${ domain }${ prefix }${ uniqueIdentifier }${ rid }${ queryString }`;
+}
- Navigation.navigate('JitsiMeetView', { url: `${ jitsiBaseUrl(settings) }${ rid }${ queryString }`, onlyAudio, rid });
+async function callJitsi(rid, onlyAudio = false) {
+ logEvent(onlyAudio ? events.RA_JITSI_AUDIO : events.RA_JITSI_VIDEO);
+ const url = await jitsiURL.call(this, { rid });
+ Navigation.navigate('JitsiMeetView', { url, onlyAudio, rid });
}
export default callJitsi;
diff --git a/app/lib/methods/canOpenRoom.js b/app/lib/methods/canOpenRoom.js
index 1578837aa..b85728727 100644
--- a/app/lib/methods/canOpenRoom.js
+++ b/app/lib/methods/canOpenRoom.js
@@ -1,4 +1,5 @@
import database from '../database';
+import store from '../createStore';
const restTypes = {
channel: 'channels', direct: 'im', group: 'groups'
@@ -53,11 +54,17 @@ async function open({ type, rid, name }) {
}
}
-export default async function canOpenRoom({ rid, path }) {
+export default async function canOpenRoom({ rid, path, isCall }) {
try {
const db = database.active;
const subsCollection = db.collections.get('subscriptions');
- const [type, name] = path.split('/');
+
+ if (isCall && !rid) {
+ // Extract rid from a Jitsi URL
+ // Eg.: [Jitsi_URL_Room_Prefix][uniqueID][rid][?jwt]
+ const { Jitsi_URL_Room_Prefix, uniqueID } = store.getState().settings;
+ rid = path.replace(`${ Jitsi_URL_Room_Prefix }${ uniqueID }`, '').replace(/\?(.*)/g, '');
+ }
if (rid) {
try {
@@ -75,8 +82,10 @@ export default async function canOpenRoom({ rid, path }) {
}
}
+ const [type, name] = path.split('/');
try {
- return await open.call(this, { type, rid, name });
+ const result = await open.call(this, { type, rid, name });
+ return result;
} catch (e) {
return false;
}
diff --git a/app/lib/methods/getSettings.js b/app/lib/methods/getSettings.js
index e635807e9..2ebad1ed2 100644
--- a/app/lib/methods/getSettings.js
+++ b/app/lib/methods/getSettings.js
@@ -11,7 +11,7 @@ import protectedFunction from './helpers/protectedFunction';
import fetch from '../../utils/fetch';
import { DEFAULT_AUTO_LOCK } from '../../constants/localAuthentication';
-const serverInfoKeys = ['Site_Name', 'UI_Use_Real_Name', 'FileUpload_MediaTypeWhiteList', 'FileUpload_MaxFileSize', 'Force_Screen_Lock', 'Force_Screen_Lock_After'];
+const serverInfoKeys = ['Site_Name', 'UI_Use_Real_Name', 'FileUpload_MediaTypeWhiteList', 'FileUpload_MaxFileSize', 'Force_Screen_Lock', 'Force_Screen_Lock_After', 'uniqueID'];
// these settings are used only on onboarding process
const loginSettings = [
@@ -68,6 +68,9 @@ const serverInfoUpdate = async(serverInfo, iconSetting) => {
return { ...allSettings, autoLockTime: setting.valueAsNumber };
}
}
+ if (setting._id === 'uniqueID') {
+ return { ...allSettings, uniqueID: setting.valueAsString };
+ }
return allSettings;
}, {});
diff --git a/app/lib/methods/subscriptions/inquiry.js b/app/lib/methods/subscriptions/inquiry.js
new file mode 100644
index 000000000..014335dc1
--- /dev/null
+++ b/app/lib/methods/subscriptions/inquiry.js
@@ -0,0 +1,95 @@
+import log from '../../../utils/log';
+import store from '../../createStore';
+import RocketChat from '../../rocketchat';
+import {
+ inquiryRequest,
+ inquiryQueueAdd,
+ inquiryQueueUpdate,
+ inquiryQueueRemove
+} from '../../../actions/inquiry';
+
+const removeListener = listener => listener.stop();
+
+let connectedListener;
+let disconnectedListener;
+let queueListener;
+
+const streamTopic = 'stream-livechat-inquiry-queue-observer';
+
+export default function subscribeInquiry() {
+ const handleConnection = () => {
+ store.dispatch(inquiryRequest());
+ };
+
+ const handleQueueMessageReceived = (ddpMessage) => {
+ const [{ type, ...sub }] = ddpMessage.fields.args;
+
+ // added can be ignored, since it is handled by 'changed' event
+ if (/added/.test(type)) {
+ return;
+ }
+
+ // if the sub isn't on the queue anymore
+ if (sub.status !== 'queued') {
+ // remove it from the queue
+ store.dispatch(inquiryQueueRemove(sub._id));
+ return;
+ }
+
+ const { queued } = store.getState().inquiry;
+ // check if this sub is on the current queue
+ const idx = queued.findIndex(item => item._id === sub._id);
+ if (idx >= 0) {
+ // if it is on the queue let's update
+ store.dispatch(inquiryQueueUpdate(sub));
+ } else {
+ // if it is not on the queue let's add
+ store.dispatch(inquiryQueueAdd(sub));
+ }
+ };
+
+ const stop = () => {
+ if (connectedListener) {
+ connectedListener.then(removeListener);
+ connectedListener = false;
+ }
+ if (disconnectedListener) {
+ disconnectedListener.then(removeListener);
+ disconnectedListener = false;
+ }
+ if (queueListener) {
+ queueListener.then(removeListener);
+ queueListener = false;
+ }
+ };
+
+ connectedListener = this.sdk.onStreamData('connected', handleConnection);
+ disconnectedListener = this.sdk.onStreamData('close', handleConnection);
+ queueListener = this.sdk.onStreamData(streamTopic, handleQueueMessageReceived);
+
+ try {
+ const { user } = store.getState().login;
+ RocketChat.getAgentDepartments(user.id).then((result) => {
+ if (result.success) {
+ const { departments } = result;
+
+ if (!departments.length || RocketChat.hasRole('livechat-manager')) {
+ this.sdk.subscribe(streamTopic, 'public').catch(e => console.log(e));
+ }
+
+ const departmentIds = departments.map(({ departmentId }) => departmentId);
+ departmentIds.forEach((departmentId) => {
+ // subscribe to all departments of the agent
+ this.sdk.subscribe(streamTopic, `department/${ departmentId }`).catch(e => console.log(e));
+ });
+ }
+ });
+
+ return {
+ stop: () => stop()
+ };
+ } catch (e) {
+ log(e);
+ return Promise.reject();
+ }
+}
diff --git a/app/lib/rocketchat.js b/app/lib/rocketchat.js
index cfa959919..52c09f93f 100644
--- a/app/lib/rocketchat.js
+++ b/app/lib/rocketchat.js
@@ -20,6 +20,7 @@ import {
} from '../actions/share';
import subscribeRooms from './methods/subscriptions/rooms';
+import subscribeInquiry from './methods/subscriptions/inquiry';
import getUsersPresence, { getUserPresence, subscribeUsersPresence } from './methods/getUsersPresence';
import protectedFunction from './methods/helpers/protectedFunction';
@@ -72,6 +73,15 @@ const RocketChat = {
}
}
},
+ async subscribeInquiry() {
+ if (!this.inquirySub) {
+ try {
+ this.inquirySub = await subscribeInquiry.call(this);
+ } catch (e) {
+ log(e);
+ }
+ }
+ },
canOpenRoom,
createChannel({
name, users, type, readOnly, broadcast
@@ -203,6 +213,11 @@ const RocketChat = {
this.roomsSub = null;
}
+ if (this.inquirySub) {
+ this.inquirySub.stop();
+ this.inquirySub = null;
+ }
+
if (this.sdk) {
this.sdk.disconnect();
this.sdk = null;
@@ -680,7 +695,7 @@ const RocketChat = {
c: 'channel',
d: 'direct'
}[room.t];
- return `${ server }/${ roomType }/${ room.name }?msg=${ message.id }`;
+ return `${ server }/${ roomType }/${ this.isGroupChat(room) ? room.rid : room.name }?msg=${ message.id }`;
},
getPermalinkChannel(channel) {
const { server } = reduxStore.getState().server;
@@ -816,7 +831,7 @@ const RocketChat = {
},
getAgentDepartments(uid) {
// RC 2.4.0
- return this.sdk.get(`livechat/agents/${ uid }/departments`);
+ return this.sdk.get(`livechat/agents/${ uid }/departments?enabledDepartmentsOnly=true`);
},
getCustomFields() {
// RC 2.2.0
@@ -826,6 +841,16 @@ const RocketChat = {
// RC 0.26.0
return this.methodCallWrapper('livechat:changeLivechatStatus');
},
+ getInquiriesQueued() {
+ // RC 2.4.0
+ return this.sdk.get('livechat/inquiries.queued');
+ },
+ takeInquiry(inquiryId) {
+ // this inquiry is added to the db by the subscriptions stream
+ // and will be removed by the queue stream
+ // RC 2.4.0
+ return this.methodCallWrapper('livechat:takeInquiry', inquiryId);
+ },
getUidDirectMessage(room) {
const { id: userId } = reduxStore.getState().login.user;
@@ -845,6 +870,12 @@ const RocketChat = {
return other && other.length ? other[0] : me;
},
+ isRead(item) {
+ let isUnread = item.archived !== true && item.open === true; // item is not archived and not opened
+ isUnread = isUnread && (item.unread > 0 || item.alert === true); // either its unread count > 0 or its alert
+ return !isUnread;
+ },
+
isGroupChat(room) {
return (room.uids && room.uids.length > 2) || (room.usernames && room.usernames.length > 2);
},
@@ -957,6 +988,14 @@ const RocketChat = {
// RC 0.47.0
return this.sdk.get('chat.getMessage', { msgId });
},
+ hasRole(role) {
+ const shareUser = reduxStore.getState().share.user;
+ const loginUser = reduxStore.getState().login.user;
+ // get user roles on the server from redux
+ const userRoles = (shareUser?.roles || loginUser?.roles) || [];
+
+ return userRoles.indexOf(r => r === role) > -1;
+ },
async hasPermission(permissions, rid) {
const db = database.active;
const subsCollection = db.collections.get('subscriptions');
diff --git a/app/lib/selection.json b/app/lib/selection.json
index 3b26c8ae9..7a375d65a 100644
--- a/app/lib/selection.json
+++ b/app/lib/selection.json
@@ -1 +1 @@
-{"IcoMoonType":"selection","icons":[{"icon":{"paths":["M821.811 544c0 176.73-143.266 320-320 320-176.73 0-319.999-143.27-319.999-320 0-176.731 143.269-320 319.999-320v-64c-212.076 0-383.999 171.923-383.999 384 0 212.079 171.923 384 383.999 384 212.079 0 384-171.921 384-384 0-10.778-0.444-21.449-1.314-32h-64.265c1.045 10.526 1.579 21.201 1.579 32zM821.811 112c0-17.673-14.327-32-32-32s-32 14.327-32 32v112h-112c-17.673 0-32 14.327-32 32s14.327 32 32 32h112v112c0 17.673 14.327 32 32 32s32-14.327 32-32v-112h112c17.673 0 32-14.327 32-32s-14.327-32-32-32h-112v-112zM405.812 512c35.348 0 63.999-28.655 63.999-64 0-35.346-28.651-64-63.999-64-35.346 0-64 28.654-64 64 0 35.345 28.654 64 64 64zM661.811 448c0 35.345-28.651 64-64 64-35.345 0-64-28.655-64-64 0-35.346 28.655-64 64-64 35.349 0 64 28.654 64 64zM351.617 589.077c-10.451-14.251-30.477-17.335-44.728-6.882-14.252 10.449-17.332 30.477-6.881 44.727 37.658 51.354 77.753 84.625 119.178 102.665 41.738 18.18 82.796 19.989 120.36 11.652 73.468-16.307 132.215-70.874 164.070-114.317 10.453-14.251 7.373-34.278-6.878-44.727-14.255-10.453-34.278-7.369-44.732 6.882-26.807 36.557-73.664 77.99-126.327 89.681-25.502 5.662-52.646 4.476-80.939-7.846-28.609-12.459-60.381-37.188-93.123-81.835z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["add-reaction"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":300,"id":145,"name":"add-reaction","prevSize":32,"code":59648},"setIdx":0,"setId":0,"iconIdx":0},{"icon":{"paths":["M568.461 325.606c0 91.58-75.849 165.821-169.411 165.821s-169.412-74.241-169.412-165.821c0-91.579 75.849-165.819 169.412-165.819s169.411 74.24 169.411 165.819zM500.698 325.606c0-54.947-45.508-99.491-101.648-99.491-56.138 0-101.647 44.544-101.647 99.491s45.509 99.492 101.647 99.492c56.14 0 101.648-44.544 101.648-99.492z","M218.476 510.558c28.952-9.109 60.004-9.668 89.28-1.613l51.341 14.135c25.632 7.057 52.819 6.566 78.168-1.408l31.872-10.027c31.206-9.822 64.678-10.423 96.235-1.737 71.957 19.81 121.677 84.049 121.677 157.218v96.239c0 54.946-45.508 99.49-101.645 99.49h-372.707c-56.138 0-101.647-44.544-101.647-99.49v-108.565c0-65.818 43.411-124.105 107.427-144.243zM289.409 572.796c-16.46-4.531-33.918-4.215-50.196 0.905-35.992 11.324-60.399 44.096-60.399 81.101v108.565c0 18.317 15.17 33.165 33.882 33.165h372.707c18.709 0 33.882-14.848 33.882-33.165v-96.239c0-43.452-29.525-81.604-72.26-93.367-18.743-5.158-38.618-4.8-57.152 1.028l-31.872 10.031c-38.023 11.959-78.804 12.698-117.251 2.112l-51.342-14.135z","M812.139 188.646c0-15.913-13.022-28.812-29.090-28.812-16.064 0-29.090 12.9-29.090 28.812v100.844h-101.82c-16.064 0-29.090 12.9-29.090 28.812s13.026 28.813 29.090 28.813h101.82v100.842c0 15.915 13.026 28.813 29.090 28.813 16.068 0 29.090-12.898 29.090-28.813v-100.842h101.82c16.068 0 29.090-12.9 29.090-28.813s-13.022-28.812-29.090-28.812h-101.82v-100.844z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["add-user"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":301,"id":144,"name":"add-user","prevSize":32,"code":59649},"setIdx":0,"setId":0,"iconIdx":1},{"icon":{"paths":["M512 768c0 0 0 0 0 0s0 0 0 0 0 0 0 0c-4.267 0-8.533 0-12.8-4.267 0 0 0 0-4.267 0 0 0 0 0 0 0s0 0 0 0 0 0 0 0v0c-4.267 0-4.267-4.267-8.533-4.267 0 0 0 0 0 0s0 0 0 0l-187.733-187.733c-12.8-12.8-12.8-34.133 0-46.933s29.867-12.8 42.667 0l136.533 136.533v-371.2c4.267-21.333 17.067-34.133 34.133-34.133s34.133 12.8 34.133 34.133v371.2l136.533-136.533c12.8-12.8 34.133-12.8 46.933 0s12.8 34.133 0 46.933l-192 187.733c-4.267 4.267-4.267 4.267-8.533 4.267v0c0 0 0 0 0 0s0 0 0 0 0 0 0 0v0c0 0 0 0 0 0s0 0 0 0v0c-8.533 4.267-12.8 4.267-17.067 4.267 0 0 0 0 0 0s0 0 0 0 0 0 0 0z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["arrow-down"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":302,"id":143,"name":"arrow-down","prevSize":32,"code":59650},"setIdx":0,"setId":0,"iconIdx":2},{"icon":{"paths":["M512 768c-17.067 0-34.133-12.8-34.133-34.133v-371.2l-136.533 136.533c-12.8 12.8-29.867 12.8-42.667 0s-12.8-34.133 0-46.933l192-187.733c0 0 0 0 0 0s0 0 0 0v0c0 0 4.267-4.267 8.533-4.267v0c0 0 0 0 0 0s0 0 0 0v0c0 0 0 0 0 0s0 0 4.267 0c0 0 0 0 0 0s0 0 0 0c0-4.267 4.267-4.267 8.533-4.267v0c0 0 0 0 0 0s0 0 0 0v0c0 0 0 0 0 0s0 0 0 0c4.267 0 8.533 0 12.8 4.267v0c0 0 0 0 0 0s0 0 0 0v0c0 0 0 0 0 0v0c0 0 0 0 0 0v0c4.267 0 8.533 4.267 8.533 4.267s0 0 0 0l192 187.733c12.8 12.8 12.8 34.133 0 46.933s-34.133 12.8-46.933 0l-136.533-136.533v371.2c4.267 21.333-12.8 34.133-29.867 34.133z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["arrow-up"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":303,"id":142,"name":"arrow-up","prevSize":32,"code":59651},"setIdx":0,"setId":0,"iconIdx":3},{"icon":{"paths":["M686.699 116.071c-57.242-19.989-105.792-20.069-138.359-20.071v64l-1.003-64c-92.002 0.342-297.343 47.824-381.24 242.996-17.896 38.968-34.758 103.342-34.758 173.004 0 69.961 17.020 146.283 52.216 207.876 23.229 40.653 92.799 131.375 191.179 173.538 94.86 40.653 206.37 52.343 296.49 16.299 16.41-6.566 24.388-25.19 17.826-41.596-6.562-16.41-25.186-24.393-41.596-17.83-69.879 27.955-163.17 20.446-247.51-15.701-80.82-34.637-141.385-112.448-160.822-146.462-28.804-50.406-43.784-115.418-43.784-176.124 0-60.766 15.020-116.183 29.055-146.59l0.184-0.4 0.173-0.404c69.507-162.182 243.823-204.605 323.588-204.605 31.595 0.002 70.878 0.296 117.261 16.493 46.144 16.113 101.389 48.779 161.822 116.767 43.657 49.114 63.535 114.976 69.389 177.712 5.892 63.121-2.854 118.187-11.546 142.093-6.4 17.6-20.429 45.44-59.392 45.7-18.261-0.806-72.823-14.673-83.123-69.568v-235.063c0-17.673-3.413-34.133-29.013-34.133-19.337 0-26.453 16.46-26.453 34.133v34.133c-35.179-39.86-95.398-68.267-152.747-68.267-106.035 0-191.998 85.961-191.998 192s85.963 192 191.998 192c62.182 0 117.662-29.555 152.747-75.388 25.715 71.078 102.571 93.030 137.015 94.135l0.512 0.017h0.516c82.645 0 111.714-64.806 120.085-87.829 12.642-34.761 21.675-99.695 15.121-169.907-6.588-70.597-29.38-151.402-85.278-214.288-66.901-75.265-131.076-114.598-188.557-134.67zM662.537 512c0 70.694-57.306 128-128 128-70.69 0-127.998-57.306-127.998-128s57.308-128 127.998-128c70.694 0 128 57.306 128 128z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["at"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":304,"id":141,"name":"at","prevSize":32,"code":59652},"setIdx":0,"setId":0,"iconIdx":4},{"icon":{"paths":["M869.030 166.758c7.782 6.063 12.331 15.377 12.331 25.242v448h-0.111c0.073 1.732 0.111 3.477 0.111 5.231 0 69.052-57.31 125.026-128 125.026-70.694 0-128-55.974-128-125.026s57.306-125.030 128-125.030c23.313 0 45.171 6.089 64 16.725v-303.858l-384 96.797v409.139c0 69.052-57.308 125.035-128 125.035s-128-55.979-128-125.030c0-69.052 57.308-125.026 128-125.026 23.314 0 45.173 6.089 64 16.725v-325.777c0-14.66 9.963-27.446 24.178-31.029l448.001-112.929c9.566-2.412 19.708-0.276 27.49 5.787z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["audio"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":305,"id":140,"name":"audio","prevSize":32,"code":59653},"setIdx":0,"setId":0,"iconIdx":5},{"icon":{"paths":["M545.084 554.018c66.466 0 120.346-52.493 120.346-117.239 0-64.753-53.879-117.243-120.346-117.243s-120.347 52.491-120.347 117.243c0 64.747 53.881 117.239 120.347 117.239zM545.084 490.018c-32.708 0-56.346-25.404-56.346-53.239 0-27.84 23.637-53.243 56.346-53.243 32.704 0 56.346 25.403 56.346 53.243 0 27.836-23.642 53.239-56.346 53.239z","M397.208 894.144h-172.125c-17.673 0-32-14.327-32-32v-702.144c0-17.673 14.327-32 32-32h640c17.673 0 32 14.327 32 32v702.144c0 17.673-14.327 32-32 32h-172.126c-6.242 1.276-12.702 1.946-19.319 1.946h-257.11c-6.618 0-13.079-0.67-19.32-1.946zM257.083 830.144h68.244c-3.114-9.455-4.799-19.558-4.799-30.054v-93.449c0-56.107 37.881-105.143 92.172-119.309 19.172-5.005 39.264-5.312 58.583-0.9l42.773 9.766c20.049 4.578 40.909 4.254 60.813-0.939l28.070-7.326c20.689-5.397 42.381-5.73 63.228-0.973 60.535 13.824 103.471 67.665 103.471 129.758v83.371c0 10.496-1.685 20.599-4.8 30.054h68.245v-638.144h-576v638.144zM684.646 830.144c12.25-4.489 20.992-16.252 20.992-30.054v-83.371c0-32.235-22.289-60.186-53.713-67.362-10.825-2.47-22.084-2.3-32.828 0.503l-28.070 7.326c-29.854 7.791-61.141 8.273-91.217 1.404l-42.773-9.766c-9.293-2.121-18.957-1.971-28.177 0.435-26.112 6.814-44.331 30.396-44.331 57.382v93.449c0 13.803 8.74 25.566 20.989 30.054h279.129z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["avatar"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1},{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":306,"id":139,"name":"avatar","prevSize":32,"code":59654},"setIdx":0,"setId":0,"iconIdx":6},{"icon":{"paths":["M412.221 297.373c-12.497-12.497-32.758-12.497-45.255 0l-192 192.001c-12.497 12.497-12.497 32.755 0 45.252l192 192c12.497 12.497 32.758 12.497 45.255 0s12.497-32.755 0-45.252l-137.373-137.374h578.745v128c0 17.673 14.327 32 32 32s32-14.327 32-32v-160c0-17.673-14.327-32-32-32h-610.745l137.373-137.373c12.497-12.497 12.497-32.758 0-45.255z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["back"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":307,"id":138,"name":"back","prevSize":32,"code":59655},"setIdx":0,"setId":0,"iconIdx":7},{"icon":{"paths":["M761.847 361.376c12.497 12.497 12.497 32.758 0 45.255l-110.95 110.95 110.95 110.946c12.497 12.497 12.497 32.759 0 45.257s-32.759 12.497-45.257 0l-110.946-110.95-110.95 110.95c-12.497 12.497-32.759 12.497-45.257 0s-12.497-32.759 0-45.257l110.95-110.946-110.95-110.95c-12.497-12.497-12.497-32.758 0-45.255s32.759-12.497 45.257 0l110.95 110.948 110.946-110.948c12.497-12.497 32.759-12.497 45.257 0z","M336.313 218.073c12.061-16.393 31.2-26.073 51.552-26.073h468.204c35.345 0 64 28.654 64 64v512c0 35.345-28.655 64-64 64h-468.204c-20.352 0-39.491-9.681-51.551-26.074l-188.343-256c-16.598-22.562-16.598-53.291 0-75.853l188.343-256zM387.864 256l-188.343 256 188.343 256h468.204v-512h-468.204z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["backspace"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1},{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":308,"id":137,"name":"backspace","prevSize":32,"code":59656},"setIdx":0,"setId":0,"iconIdx":8},{"icon":{"paths":["M682.539 288v-32c0-88.366-71.633-160-160-160s-160 71.634-160 160v32h-96c-53.019 0-96 42.981-96 96v352c0 106.039 85.961 192 192 192h320c106.039 0 192-85.961 192-192v-352c0-53.019-42.982-96-96-96h-96zM618.539 288h-192v-32c0-53.019 42.982-96 96-96 53.022 0 96 42.981 96 96v32zM618.539 352v160c0 17.673 14.327 32 32 32s32-14.327 32-32v-160h96c17.673 0 32 14.327 32 32v352c0 70.694-57.306 128-128 128h-320c-70.693 0-128-57.306-128-128v-352c0-17.673 14.327-32 32-32h96v160c0 17.673 14.327 32 32 32s32-14.327 32-32v-160h192z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["bag"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":309,"id":136,"name":"bag","prevSize":32,"code":59657},"setIdx":0,"setId":0,"iconIdx":9},{"icon":{"paths":["M876.796 512c0-86.89-31.484-166.427-83.665-227.826l-496.163 496.161c61.399 52.181 140.937 83.665 227.828 83.665 194.402 0 352-157.598 352-352zM252.144 734.652l495.299-495.302c-60.659-49.597-138.18-79.349-222.647-79.349-194.406 0-352.001 157.596-352.001 352 0 84.467 29.752 161.988 79.349 222.652zM940.796 512c0 229.751-186.253 416-416 416-229.752 0-416.001-186.249-416.001-416s186.249-416 416.001-416c229.747 0 416 186.249 416 416z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["ban"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":310,"id":135,"name":"ban","prevSize":32,"code":59658},"setIdx":0,"setId":0,"iconIdx":10},{"icon":{"paths":["M833.084 384v306.743l54.626 54.63c9.152 9.152 11.891 22.916 6.938 34.871-4.954 11.959-16.623 19.755-29.564 19.755h-465.731l63.999-64h305.732v-305.732l63.492-63.492c0.337 5.699 0.508 11.441 0.508 17.224zM748.105 179.728l-45.257 45.255c-40.486-40.169-96.226-64.983-157.764-64.983-123.712 0-224 100.288-224 224v222.746l-64 64v-286.746c0-159.058 128.942-288 288-288 79.211 0 150.95 31.978 203.021 83.728zM449.084 832c0 53.018 42.978 96 96 96 53.018 0 96-42.982 96-96h-192zM912.956 150.62c-12.497-12.497-32.755-12.497-45.252 0l-675.618 675.616c-12.497 12.497-12.497 32.759 0 45.257s32.758 12.497 45.255 0l675.615-675.618c12.497-12.497 12.497-32.758 0-45.255z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["bell-off"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":311,"id":134,"name":"bell-off","prevSize":32,"code":59659},"setIdx":0,"setId":0,"iconIdx":11},{"icon":{"paths":["M638.831 832h-192c0 53.018 42.982 96 96 96s96-42.982 96-96zM766.831 736v-352c0-123.712-100.288-224-224-224s-224 100.288-224 224v352h448zM222.831 800c-12.943 0-24.611-7.795-29.564-19.755-4.953-11.955-2.215-25.719 6.937-34.871l54.627-54.63v-306.743c0-159.058 128.942-288 288-288 159.057 0 288 128.942 288 288v309.333l41.6 55.467c7.27 9.698 8.444 22.669 3.021 33.51-5.419 10.842-16.499 17.69-28.621 17.69h-624z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["bell"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":312,"id":133,"name":"bell","prevSize":32,"code":59660},"setIdx":0,"setId":0,"iconIdx":12},{"icon":{"paths":["M403.558 775.415c-17.673 0-32-14.327-32-32v-453.166c0-17.673 14.327-32 32-32h137.075c56.119 0 98.27 11.603 126.447 34.81 28.416 23.206 42.624 57.542 42.624 103.007 0 24.153-6.865 45.585-20.599 64.29-13.734 18.47-32.444 32.798-56.124 42.978 27.942 7.817 49.967 22.733 66.069 44.757 16.337 21.786 24.508 47.834 24.508 78.144 0 46.409-15.036 82.876-45.111 109.397-30.071 26.522-72.576 39.782-127.514 39.782h-147.375zM439.757 533.53v186.121h112.597c31.731 0 56.713-8.171 74.948-24.508 18.466-16.576 27.703-39.309 27.703-68.198 0-62.276-33.86-93.414-101.585-93.414h-113.664zM439.757 478.827h103.006c29.837 0 53.636-7.458 71.394-22.379 17.997-14.916 26.995-35.163 26.995-60.737 0-28.416-8.286-49.017-24.862-61.804-16.576-13.024-41.796-19.536-75.657-19.536h-100.877v164.456z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["bold"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":313,"id":132,"name":"bold","prevSize":32,"code":59661},"setIdx":0,"setId":0,"iconIdx":13},{"icon":{"paths":["M371.558 445.44c0-17.677 14.327-32.002 32-32.002h256c17.673 0 32 14.325 32 32.002 0 17.673-14.327 32-32 32h-256c-17.673 0-32-14.327-32-32z","M371.558 322.558c0-17.673 14.327-32 32-32h256c17.673 0 32 14.327 32 32s-14.327 32-32 32h-256c-17.673 0-32-14.327-32-32z","M883.558 679.68c0 17.673-14.327 32-32 32h-18.509c-8.218 40.546-8.218 82.334 0 122.88h19.789c16.969 0 30.72 13.756 30.72 30.72s-13.751 30.72-30.72 30.72h-545.28c-70.692 0-128-55.014-128-122.88v-453.12c0-106.039 85.961-192 192-192h480c17.673 0 32 14.327 32 32v519.68zM767.979 834.56c-6.788-40.678-6.788-82.202 0-122.88h-460.42c-35.346 0-64 27.507-64 61.44s28.654 61.44 64 61.44h460.42zM243.558 647.68h576v-455.68h-448c-70.692 0-128 57.308-128 128v327.68z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["book"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":314,"id":131,"name":"book","prevSize":32,"code":59662},"setIdx":0,"setId":0,"iconIdx":14},{"icon":{"paths":["M241.303 224h319.998v576h-96v-112c0-8.836-7.159-16-16-16h-95.998c-8.837 0-16 7.164-16 16v112h-96v-576zM625.301 448h192v352h-192v-352zM849.301 384h-224v-192c0-17.673-14.323-32-32-32h-383.998c-17.673 0-32 14.327-32 32v640c0 17.673 14.327 32 32 32h639.998c17.677 0 32-14.327 32-32v-416c0-17.673-14.323-32-32-32zM321.303 288c-8.837 0-16 7.163-16 16v32c0 8.837 7.163 16 16 16h32c8.836 0 16-7.163 16-16v-32c0-8.837-7.164-16-16-16h-32zM305.303 432c0-8.837 7.163-16 16-16h32c8.836 0 16 7.163 16 16v32c0 8.836-7.164 16-16 16h-32c-8.837 0-16-7.164-16-16v-32zM321.303 544c-8.837 0-16 7.164-16 16v32c0 8.836 7.163 16 16 16h32c8.836 0 16-7.164 16-16v-32c0-8.836-7.164-16-16-16h-32zM433.301 304c0-8.837 7.164-16 16-16h32c8.841 0 16 7.163 16 16v32c0 8.837-7.159 16-16 16h-32c-8.836 0-16-7.163-16-16v-32zM449.301 416c-8.836 0-16 7.163-16 16v32c0 8.836 7.164 16 16 16h32c8.841 0 16-7.164 16-16v-32c0-8.837-7.159-16-16-16h-32zM433.301 560c0-8.836 7.164-16 16-16h32c8.841 0 16 7.164 16 16v32c0 8.836-7.159 16-16 16h-32c-8.836 0-16-7.164-16-16v-32zM705.301 512c-8.836 0-16 7.164-16 16v32c0 8.836 7.164 16 16 16h32c8.841 0 16-7.164 16-16v-32c0-8.836-7.159-16-16-16h-32zM689.301 656c0-8.836 7.164-16 16-16h32c8.841 0 16 7.164 16 16v32c0 8.836-7.159 16-16 16h-32c-8.836 0-16-7.164-16-16v-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["business"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":315,"id":130,"name":"business","prevSize":32,"code":59663},"setIdx":0,"setId":0,"iconIdx":15},{"icon":{"paths":["M293.783 157.44c0-16.259 13.181-29.44 29.44-29.44s29.44 13.181 29.44 29.44v58.877h353.278v-58.877c0-16.259 13.184-29.44 29.44-29.44 16.26 0 29.44 13.181 29.44 29.44v58.877h85.764c17.673 0 32 14.327 32 32v583.679c0 17.673-14.327 32-32 32h-642.562c-17.673 0-32-14.327-32-32v-583.679c0-1.105 0.056-2.196 0.165-3.272 1.639-16.136 15.266-28.728 31.835-28.728h85.76v-58.877zM818.586 392.957h-578.562v407.039h578.562v-407.039zM440.986 644.476c0-8.836 7.164-16 16-16h26.88c8.836 0 16 7.164 16 16v26.88c0 8.836-7.164 16-16 16h-26.88c-8.836 0-16-7.164-16-16v-26.88zM339.223 510.72c-8.837 0-16 7.164-16 16v26.88c0 8.836 7.163 16 16 16h26.88c8.837 0 16-7.164 16-16v-26.88c0-8.836-7.163-16-16-16h-26.88zM558.741 526.72c0-8.836 7.164-16 16-16h26.88c8.841 0 16 7.164 16 16v26.88c0 8.836-7.159 16-16 16h-26.88c-8.836 0-16-7.164-16-16v-26.88zM339.223 628.476c-8.837 0-16 7.164-16 16v26.88c0 8.836 7.163 16 16 16h26.88c8.837 0 16-7.164 16-16v-26.88c0-8.836-7.163-16-16-16h-26.88zM558.741 644.476c0-8.836 7.164-16 16-16h26.88c8.841 0 16 7.164 16 16v26.88c0 8.836-7.159 16-16 16h-26.88c-8.836 0-16-7.164-16-16v-26.88zM456.981 510.72c-8.836 0-16 7.164-16 16v26.88c0 8.836 7.164 16 16 16h26.88c8.841 0 16-7.164 16-16v-26.88c0-8.836-7.159-16-16-16h-26.88zM676.501 526.72c0-8.836 7.164-16 16-16h26.88c8.836 0 16 7.164 16 16v26.88c0 8.836-7.164 16-16 16h-26.88c-8.836 0-16-7.164-16-16v-26.88zM692.501 628.476c-8.836 0-16 7.164-16 16v26.88c0 8.836 7.164 16 16 16h26.88c8.836 0 16-7.164 16-16v-26.88c0-8.836-7.164-16-16-16h-26.88z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["calendar"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":316,"id":129,"name":"calendar","prevSize":32,"code":59664},"setIdx":0,"setId":0,"iconIdx":16},{"icon":{"paths":["M195.378 192.002c0-15.807 12.815-28.622 28.622-28.622h128c15.807 0 28.622 12.815 28.622 28.622s-12.815 28.622-28.622 28.622h-128c-15.807 0-28.622-12.814-28.622-28.622z","M736 560c0 97.203-78.797 176-176 176s-176-78.797-176-176c0-97.199 78.797-175.998 176-175.998s176 78.799 176 175.998zM672 560c0-61.854-50.146-112-112-112s-112 50.146-112 112c0 61.858 50.146 112 112 112s112-50.142 112-112z","M192 256.002c-35.346 0-64 28.654-64 64v447.998c0 35.349 28.654 64 64 64h640c35.345 0 64-28.651 64-64v-447.998c0-35.346-28.655-64-64-64h-640zM832 320.002v447.998h-640v-447.998h640z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["Camera"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":317,"id":128,"name":"Camera","prevSize":32,"code":59665},"setIdx":0,"setId":0,"iconIdx":17},{"icon":{"paths":["M522.539 864c-194.404 0-352-157.598-352-352 0-194.404 157.596-352 352-352 194.406 0 352 157.596 352 352 0 194.402-157.594 352-352 352zM522.539 928c229.751 0 416-186.249 416-416s-186.249-416-416-416c-229.75 0-416 186.249-416 416s186.249 416 416 416zM673.165 361.373c12.497 12.497 12.497 32.758 0 45.255l-105.37 105.373 105.37 105.374c12.497 12.497 12.497 32.755 0 45.252s-32.755 12.497-45.252 0l-105.374-105.37-105.372 105.37c-12.497 12.497-32.758 12.497-45.255 0s-12.497-32.755 0-45.252l105.375-105.374-105.375-105.373c-12.497-12.497-12.497-32.758 0-45.255s32.758-12.497 45.255 0l105.372 105.371 105.374-105.371c12.497-12.497 32.755-12.497 45.252 0z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["cancel"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":318,"id":127,"name":"cancel","prevSize":32,"code":59666},"setIdx":0,"setId":0,"iconIdx":18},{"icon":{"paths":["M261.842 304.026c-49.642 68.947-66.502 152.644-66.502 207.97v1.451l-0.131 1.446c-9.702 106.718 28.59 181.931 90.135 234.005 62.938 53.257 152.153 83.733 244.198 93.961 91.964 10.219 193.271 1.446 273.306-15.479 40.021-8.465 73.613-18.735 97.442-29.077 9.246-4.015 16.439-7.787 21.734-11.127-2.462-1.566-5.444-3.302-9.003-5.197-9.22-4.911-19.776-9.579-30.733-14.366l-1.911-0.836c-9.668-4.224-20.471-8.943-28.659-13.521-14.831-8.294-29.385-17.732-40-27.772-5.227-4.941-11.17-11.571-15.147-19.827-4.211-8.742-7.228-21.794-1.31-35.601 31.979-74.62 47.181-115.49 54.541-142.481 6.874-25.199 6.874-37.888 6.874-58.061v-0.183c0-16.038-9.323-89.517-55.812-158.033-45.018-66.338-125.99-129.968-274.854-129.968-134.639 0-215.698 55.382-264.166 122.698zM209.904 266.63c60.332-83.796 160.606-149.302 316.104-149.302 171.136 0 271.492 75.037 327.812 158.032 54.839 80.818 66.854 167.337 66.854 193.969 0 22.383-0.021 41.694-9.131 75.085-8.128 29.807-23.479 70.929-51.942 137.924 5.261 4.169 13.069 9.306 23.36 15.061 5.312 2.974 13.483 6.554 24.964 11.571 10.654 4.655 23.437 10.266 35.174 16.512 11.26 5.995 24.414 14.033 34.202 24.542 10.231 10.991 20.971 29.845 13.299 52.864-5.056 15.164-16.798 25.937-26.577 33.092-10.628 7.774-23.817 14.763-38.255 21.030-29.005 12.587-67.029 23.962-109.679 32.981-85.312 18.039-193.583 27.588-293.619 16.474-99.953-11.106-202.739-44.629-278.468-108.71-76.833-65.011-123.811-159.996-112.66-287.223 0.286-65.549 19.841-162.346 78.561-243.902zM531.337 320c17.677 0 32 14.327 32 32v224c0 17.673-14.323 32-32 32-17.673 0-32-14.327-32-32v-224c0-17.673 14.327-32 32-32zM563.337 672c0-17.673-14.323-32-32-32-17.673 0-32 14.327-32 32s14.327 32 32 32c17.677 0 32-14.327 32-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["canned_responsed"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":319,"id":126,"name":"canned_responsed","prevSize":32,"code":59667},"setIdx":0,"setId":0,"iconIdx":19},{"icon":{"paths":["M332.711 105.235c12.497-12.48 32.758-12.48 45.255 0s12.497 32.715 0 45.195l-105.373 105.233h610.743c17.677 0 32 14.308 32 31.958v111.852c0 17.65-14.323 31.959-32 31.959-17.673 0-32-14.309-32-31.959v-79.894h-578.743l105.373 105.233c12.497 12.482 12.497 32.715 0 45.195s-32.758 12.48-45.255 0l-160-159.788c-12.497-12.48-12.497-32.715 0-45.195l160-159.789zM745.967 917.414c-12.497 12.48-32.759 12.48-45.257 0s-12.497-32.713 0-45.193l105.374-105.233h-610.746c-17.673 0-32-14.31-32-31.957v-111.855c0-17.647 14.327-31.957 32-31.957s32 14.31 32 31.957v79.898h578.746l-105.374-105.237c-12.497-12.48-12.497-32.713 0-45.193s32.759-12.48 45.257 0l160 159.787c12.497 12.48 12.497 32.717 0 45.197l-160 159.787z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["change"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":320,"id":125,"name":"change","prevSize":32,"code":59668},"setIdx":0,"setId":0,"iconIdx":20},{"icon":{"paths":["M578.97 127.99c-121.694 0-200.971 50.509-248.812 115.801-46.216 63.073-61.638 137.752-61.933 188.615-8.705 98.748 28.601 172.898 89.423 223.471 59.686 49.626 140.201 75.26 217.85 83.738 77.751 8.486 161.715 1.195 227.857-12.548 33.062-6.869 62.771-15.578 85.641-25.331 11.366-4.847 22.029-10.368 30.797-16.67 7.872-5.662 18.539-14.976 23.241-28.834 7.287-21.474-3.132-38.784-11.964-48.102-8.41-8.879-19.426-15.403-28.241-20.015-9.306-4.868-19.379-9.207-27.533-12.71-8.973-3.853-14.857-6.396-18.56-8.431-4.843-2.662-8.841-5.086-12.028-7.202 20.258-47.142 31.552-77.043 37.7-99.191 7.292-26.27 7.313-41.723 7.313-58.907 0-21.523-9.604-88.542-52.809-151.109-44.702-64.73-124.075-122.573-257.941-122.573zM332.22 433.894c0-40.414 12.606-101.841 49.562-152.276 35.784-48.835 95.884-89.628 197.188-89.628 112.090 0 172.092 46.886 205.278 94.94 34.679 50.219 41.472 104.040 41.472 114.741v0.2c0 14.918 0 23.638-4.983 41.594-5.491 19.776-16.964 50.189-41.54 106.534-5.798 13.295-2.756 25.771 1.156 33.754 3.665 7.479 9.007 13.244 13.333 17.263 8.836 8.213 20.651 15.684 32.222 22.046 6.618 3.635 15.236 7.334 22.562 10.475l1.566 0.67c5.901 2.539 11.52 4.971 16.687 7.42-0.913 0.41-1.856 0.823-2.837 1.237-17.741 7.569-43.076 15.206-73.553 21.542-60.949 12.663-138.065 19.209-207.889 11.584-69.926-7.633-136.981-30.336-183.878-69.325-45.46-37.798-73.675-92.066-66.481-169.822l0.136-1.472v-1.476zM836.463 553.348l-0.073-0.081c0 0 0.009 0.009 0.030 0.034 0.009 0.013 0.026 0.030 0.043 0.047z","M195.856 502.468c7.496-11.255 16.26-22.259 26.436-32.589 0.876 31.744 6.169 61.227 15.216 88.358-15.094 30.878-18.374 59.315-18.374 65.357v0.188c0 11.379 0 17.532 3.524 30.699 3.993 14.916 12.441 38.212 30.867 82.022 5.256 12.497 2.48 24.098-0.985 31.428-3.249 6.874-7.925 12.058-11.511 15.514-7.319 7.057-16.852 13.257-25.751 18.33-5.008 2.854-11.334 5.705-16.546 8.026 11.182 3.942 24.979 7.817 40.802 11.226 44.977 9.694 101.833 14.673 153.062 8.87 51.282-5.807 99.777-23.014 133.351-51.964l0.606-0.525c14.797 2.782 29.53 4.937 44.053 6.519 10.884 1.19 21.858 2.091 32.875 2.722-10.121 14.797-22.161 28.045-35.742 39.753-46.362 39.974-108.544 60.365-167.943 67.089-59.451 6.729-123.406 0.947-173.745-9.899-25.169-5.427-48.056-12.352-65.901-20.245-8.86-3.917-17.457-8.503-24.686-13.892-6.431-4.791-15.831-13.171-20.001-25.92-6.422-19.631 2.792-35.443 10.458-43.831 7.193-7.872 16.405-13.461 23.248-17.173 7.309-3.968 15.158-7.467 21.234-10.176 6.907-3.076 10.854-4.855 13.183-6.182 1.35-0.768 2.591-1.502 3.727-2.197-13.937-33.886-21.975-56.119-26.479-72.947-5.68-21.222-5.7-33.873-5.7-47.433 0-17.711 7.436-71.138 40.721-121.126zM172.64 797.244c-0.011 0.004 0.084 0.107 0.318 0.303-0.19-0.205-0.306-0.303-0.318-0.303zM196.89 737.084c-0.003 0-0.052 0.051-0.137 0.149l0.112-0.119c0.019-0.021 0.027-0.030 0.025-0.030z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["chat"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1},{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":321,"id":124,"name":"chat","prevSize":32,"code":59669},"setIdx":0,"setId":0,"iconIdx":21},{"icon":{"paths":["M883.081 233.251c12.565 12.43 12.676 32.691 0.243 45.254l-474.874 480.001c-6.013 6.076-14.208 9.498-22.758 9.493s-16.742-3.426-22.752-9.506l-165.124-167.091c-12.423-12.57-12.303-32.828 0.268-45.252s32.832-12.305 45.254 0.269l142.376 144.068 452.115-456.993c12.429-12.564 32.691-12.672 45.252-0.243z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["check"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":322,"id":123,"name":"check","prevSize":32,"code":59670},"setIdx":0,"setId":0,"iconIdx":22},{"icon":{"paths":["M310.004 393.373c12.497-12.497 32.758-12.497 45.255 0l185.375 185.371 185.37-185.371c12.497-12.497 32.759-12.497 45.257 0s12.497 32.758 0 45.254l-208 208c-12.497 12.497-32.759 12.497-45.257 0l-207.999-208c-12.497-12.495-12.497-32.757 0-45.254z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["chevron-down"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":323,"id":122,"name":"chevron-down","prevSize":32,"code":59671},"setIdx":0,"setId":0,"iconIdx":23},{"icon":{"paths":["M663.77 281.373c12.497 12.497 12.497 32.758 0 45.255l-185.374 185.373 185.374 185.374c12.497 12.497 12.497 32.755 0 45.252s-32.759 12.497-45.257 0l-208-208c-12.497-12.497-12.497-32.755 0-45.252l208-208.001c12.497-12.497 32.759-12.497 45.257 0z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["chevron-left"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":324,"id":121,"name":"chevron-left","prevSize":32,"code":59672},"setIdx":0,"setId":0,"iconIdx":24},{"icon":{"paths":["M428.77 742.626c-12.498-12.497-12.498-32.755 0-45.252l185.37-185.374-185.37-185.373c-12.498-12.497-12.498-32.758 0-45.255 12.497-12.497 32.755-12.497 45.252 0l208 208.001c12.497 12.497 12.497 32.755 0 45.252l-208 208c-12.497 12.497-32.755 12.497-45.252 0z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["chevron-right"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":325,"id":120,"name":"chevron-right","prevSize":32,"code":59673},"setIdx":0,"setId":0,"iconIdx":25},{"icon":{"paths":["M773.513 630.626c-12.497 12.497-32.759 12.497-45.257 0l-185.37-185.37-185.373 185.37c-12.497 12.497-32.758 12.497-45.255 0s-12.497-32.755 0-45.252l207.998-208.001c12.497-12.497 32.759-12.497 45.257 0l208 208.001c12.497 12.497 12.497 32.755 0 45.252z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["chevron-up"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":326,"id":119,"name":"chevron-up","prevSize":32,"code":59674},"setIdx":0,"setId":0,"iconIdx":26},{"icon":{"paths":["M538.321 864c194.406 0 352-157.598 352-352 0-46.519-9.024-90.932-25.417-131.582l48.516-48.518c26.214 54.496 40.9 115.584 40.9 180.1 0 229.751-186.249 416-416 416-229.75 0-416-186.249-416-416s186.25-416 416-416c95.377 0 183.253 32.096 253.423 86.076l-45.709 45.712c-58.223-42.623-130.031-67.788-207.714-67.788-194.404 0-352 157.596-352 352 0 194.402 157.596 352 352 352zM928.951 230.624c12.497-12.499 12.493-32.76-0.004-45.255-12.501-12.495-32.764-12.491-45.257 0.008l-345.387 345.504-105.34-105.491c-12.487-12.506-32.748-12.52-45.254-0.032-12.506 12.489-12.52 32.747-0.032 45.253l127.97 128.158c6.003 6.007 14.144 9.387 22.635 9.387 8.495 0.004 16.64-3.371 22.643-9.374l368.026-368.156z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["circle-check"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":327,"id":118,"name":"circle-check","prevSize":32,"code":59675},"setIdx":0,"setId":0,"iconIdx":27},{"icon":{"paths":["M501.884 229.047c19.767-23.931 49.89-36.827 80.849-34.615l143.936 10.281c42.052 3.004 77.222 33.091 86.703 74.17l30.349 131.517c6.643 28.785-0.337 59.028-18.923 81.991l-252.369 311.744c-11.119 13.739-31.27 15.859-45.005 4.74-13.734-11.123-15.859-31.27-4.736-45.009l252.365-311.744c6.195-7.654 8.521-17.737 6.306-27.331l-30.349-131.517c-3.157-13.693-14.882-23.722-28.898-24.723l-143.936-10.281c-10.321-0.737-20.361 3.561-26.953 11.538l-265.998 322c-5.439 6.583-8.020 15.066-7.171 23.565l7.581 75.81c1.636 16.358 15.401 28.817 31.841 28.817h104.305c9.44 0 18.396-4.169 24.476-11.388l227.597-270.268-10.052-70.344h-69.257l-230.406 276.488c-11.314 13.577-31.492 15.411-45.069 4.096s-15.411-31.492-4.097-45.069l230.403-276.487c12.16-14.592 30.174-23.028 49.169-23.028h69.257c31.851 0 58.854 23.419 63.36 54.949l10.048 70.345c2.577 18.044-2.662 36.331-14.404 50.274l-227.593 270.268c-18.24 21.662-45.116 34.163-73.432 34.163h-104.305c-49.32 0-90.616-37.372-95.523-86.447l-7.581-75.814c-2.549-25.489 5.196-50.944 21.511-70.694l266-321.997z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["clip"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":328,"id":117,"name":"clip","prevSize":32,"code":59676},"setIdx":0,"setId":0,"iconIdx":28},{"icon":{"paths":["M629.756 192c0-53.019-42.978-96-96-96-53.018 0-96 42.981-96 96h-191.999c-17.673 0-32 14.327-32 32v672c0 17.673 14.327 32 32 32h575.999c17.673 0 32-14.327 32-32v-672c0-17.673-14.327-32-32-32h-192zM277.757 864v-608h96v64c0 17.673 14.327 32 32 32h255.999c17.673 0 32-14.327 32-32v-64h96v608h-511.999zM533.756 224c17.673 0 32-14.327 32-32s-14.327-32-32-32c-17.673 0-32 14.327-32 32s14.327 32 32 32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["Clipboard"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":329,"id":116,"name":"Clipboard","prevSize":32,"code":59677},"setIdx":0,"setId":0,"iconIdx":29},{"icon":{"paths":["M901.594 512c0 194.402-157.594 352-352 352-194.404 0-352-157.598-352-352 0-194.404 157.596-352 352-352 194.406 0 352 157.596 352 352zM965.594 512c0-229.751-186.249-416-416-416-229.75 0-416 186.249-416 416s186.25 416 416 416c229.751 0 416-186.249 416-416zM581.594 288c0-17.673-14.327-32-32-32s-32 14.327-32 32v224c0 8.486 3.371 16.627 9.374 22.626l96 96c12.497 12.497 32.755 12.497 45.252 0s12.497-32.755 0-45.252l-86.626-86.63v-210.743z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["clock"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":330,"id":115,"name":"clock","prevSize":32,"code":59678},"setIdx":0,"setId":0,"iconIdx":30},{"icon":{"paths":["M285.923 356.674c6.747-28.299 25.696-52.006 51.209-67.153 25.601-15.2 56.323-20.858 84.699-14.531 27.64 6.163 55.113 24.12 74.872 60.34l22.541 41.324 30.135-36.161c27.238-32.687 85.129-39.712 134.716-14.063 23.561 12.187 42.206 30.617 52.062 53.489 9.655 22.406 12.109 51.898-1.434 89.15l-15.616 42.935h45.687c53.606 0 82.419 15.881 97.638 33.749 15.654 18.377 21.897 44.651 18.556 74.718-3.341 30.080-16.051 60.514-33.455 82.889-17.937 23.066-36.646 32.644-50.739 32.644h-544c-18.791 0-37.068-10.359-52.195-31.578-15.217-21.342-24.977-51.051-25.818-81.31-0.84-30.229 7.237-57.916 23.733-77.495 15.796-18.743 42.268-33.617 86.279-33.617h59.792l-33.166-49.749c-27.882-41.826-32.117-77.816-25.498-105.581zM531.012 272.079c-26.342-32.073-59.665-51.619-95.253-59.554-45.623-10.174-92.901-0.833-131.299 21.965-38.487 22.85-69.538 60.142-80.791 107.342-8.278 34.72-5.369 72.759 10.731 111.77-35.67 8.465-64.099 26.185-84.825 50.782-29.004 34.423-39.927 78.733-38.766 120.508 1.159 41.737 14.399 84.032 37.682 116.689 23.373 32.781 59.096 58.423 104.305 58.423h544c41.907 0 77.201-26.419 101.261-57.353 24.597-31.629 41.886-73.199 46.545-115.115 4.659-41.933-3.098-87.659-33.446-123.285-24.107-28.297-59.503-46.771-105.617-53.453 5.833-35.196 1.69-67.676-10.603-96.207-16.644-38.627-47.002-67.196-81.438-85.009-54.903-28.397-128.734-32.652-182.485 2.495zM524.796 437.329c17.673 0 32 14.323 32 32v53.325h53.333c17.673 0 32 14.327 32 32s-14.327 32-32 32h-53.333v53.342c0 17.673-14.327 32-32 32s-32-14.327-32-32v-53.342h-53.333c-17.673 0-32-14.327-32-32s14.327-32 32-32h53.333v-53.325c0-17.677 14.327-32 32-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["cloud_Plus"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":331,"id":114,"name":"cloud_Plus","prevSize":32,"code":59679},"setIdx":0,"setId":0,"iconIdx":31},{"icon":{"paths":["M515.776 928c-14.217 0-28.275-0.713-42.142-2.112-16.695-1.681-30.558-12.531-36.689-27.392l-40.54-98.308-98.161 40.841c-14.837 6.174-32.3 4.045-45.292-6.554-21.839-17.818-41.831-37.811-59.65-59.648-10.601-12.992-12.726-30.455-6.553-45.295l40.839-98.159-98.307-40.542c-14.864-6.127-25.713-19.994-27.395-36.689-1.396-13.867-2.111-27.925-2.111-42.142s0.714-28.275 2.11-42.142c1.681-16.695 12.531-30.558 27.395-36.685l98.308-40.543-40.84-98.163c-6.173-14.836-4.047-32.3 6.553-45.292 17.818-21.838 37.81-41.83 59.648-59.648 12.992-10.601 30.455-12.726 45.292-6.554l98.163 40.84 40.54-98.309c6.131-14.865 19.994-25.714 36.689-27.395 13.867-1.396 27.925-2.111 42.142-2.111s28.275 0.714 42.142 2.111c16.695 1.681 30.558 12.53 36.689 27.395l40.542 98.309 98.163-40.84c14.835-6.173 32.299-4.047 45.291 6.554 21.837 17.818 41.83 37.81 59.648 59.648 10.598 12.992 12.723 30.455 6.554 45.292l-40.841 98.163 98.308 40.543c14.861 6.127 25.711 19.994 27.392 36.685 1.399 13.867 2.112 27.925 2.112 42.142s-0.713 28.275-2.112 42.142c-1.681 16.695-12.531 30.562-27.392 36.689l-98.308 40.542 40.841 98.159c6.17 14.839 4.045 32.303-6.554 45.295-17.822 21.837-37.811 41.83-59.652 59.648-12.992 10.598-30.455 12.727-45.291 6.554l-98.159-40.841-40.542 98.308c-6.131 14.861-19.994 25.711-36.689 27.392-13.867 1.399-27.925 2.112-42.142 2.112zM448.23 757.982l43.383 105.203c7.979 0.542 16.034 0.815 24.162 0.815s16.183-0.273 24.162-0.815l43.383-105.203c9.455-22.921 35.733-33.805 58.628-24.282l105.054 43.708c12.156-10.598 23.578-22.020 34.18-34.176l-43.708-105.058c-9.527-22.895 1.357-49.173 24.282-58.624l105.203-43.383c0.542-7.983 0.815-16.038 0.815-24.166 0-8.124-0.273-16.183-0.815-24.162l-105.203-43.383c-22.925-9.455-33.809-35.731-24.282-58.625l43.708-105.058c-10.603-12.156-22.020-23.577-34.176-34.177l-105.058 43.709c-22.895 9.525-49.173-1.359-58.628-24.283l-43.383-105.204c-7.979-0.54-16.038-0.815-24.162-0.815s-16.183 0.275-24.162 0.815l-43.383 105.204c-9.455 22.924-35.732 33.809-58.627 24.283l-105.058-43.709c-12.155 10.6-23.577 22.022-34.177 34.177l43.709 105.058c9.525 22.895-1.359 49.17-24.283 58.625l-105.203 43.383c-0.54 7.979-0.815 16.038-0.815 24.162 0 8.128 0.275 16.183 0.815 24.166l105.202 43.383c22.924 9.451 33.809 35.729 24.283 58.624l-43.708 105.058c10.601 12.156 22.022 23.578 34.179 34.176l105.056-43.708c22.895-9.523 49.172 1.361 58.627 24.282zM419.776 512c0-53.018 42.982-96 96-96s96 42.982 96 96c0 53.018-42.982 96-96 96s-96-42.982-96-96zM515.776 352c-88.367 0-160 71.634-160 160 0 88.367 71.633 160 160 160s160-71.633 160-160c0-88.366-71.633-160-160-160z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["cog"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":332,"id":113,"name":"cog","prevSize":32,"code":59680},"setIdx":0,"setId":0,"iconIdx":32},{"icon":{"paths":["M470.033 272c-35.349 0-64.002 28.654-64.002 64v480c0 35.345 28.652 64 64.002 64h352c35.345 0 64-28.655 64-64v-304c0-6.511-1.988-12.864-5.692-18.214l-134.455-194.215c-11.955-17.267-31.62-27.57-52.621-27.57h-223.232zM470.033 336h144v144c0 35.345 28.651 64 64 64h144v272h-352v-480zM678.033 480v-144h15.232l99.691 144h-114.923zM150.031 208c0-35.346 28.654-64 64-64h241.845c18.031 0 35.226 7.607 47.356 20.949l39.138 43.051h-328.339v480h128v64h-128c-35.346 0-64-28.655-64-64v-480z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["copy"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":333,"id":112,"name":"copy","prevSize":32,"code":59681},"setIdx":0,"setId":0,"iconIdx":33},{"icon":{"paths":["M225.083 181.328c-53.019 0-96 42.98-96 96v469.334c0 53.018 42.981 96 96 96h640c53.018 0 96-42.982 96-96v-469.334c0-53.019-42.982-96-96-96h-640zM193.083 277.328c0-17.673 14.327-32 32-32h640c17.673 0 32 14.327 32 32v202.672h-704v-202.672zM193.083 544h704v202.662c0 17.673-14.327 32-32 32h-640c-17.673 0-32-14.327-32-32v-202.662zM843.75 661.329c0-35.349-28.655-64-64-64-35.349 0-64 28.651-64 64 0 35.345 28.651 64 64 64 35.345 0 64-28.655 64-64z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["creditcard"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":334,"id":111,"name":"creditcard","prevSize":32,"code":59682},"setIdx":0,"setId":0,"iconIdx":34},{"icon":{"paths":["M826.185 262.627c12.497-12.497 12.497-32.758 0-45.255s-32.755-12.497-45.252 0l-249.374 249.371-249.373-249.371c-12.497-12.497-32.758-12.497-45.255 0s-12.497 32.758 0 45.255l249.371 249.373-249.371 249.374c-12.497 12.497-12.497 32.755 0 45.252s32.758 12.497 45.255 0l249.373-249.37 249.374 249.37c12.497 12.497 32.755 12.497 45.252 0s12.497-32.755 0-45.252l-249.37-249.374 249.37-249.373z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["Cross"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":335,"id":110,"name":"Cross","prevSize":32,"code":59683},"setIdx":0,"setId":0,"iconIdx":35},{"icon":{"paths":["M511.488 141.563l-298.665 136.533c-11.39 5.207-18.696 16.58-18.696 29.103v386.846c0 11.819 6.513 22.673 16.941 28.233l298.666 159.292c9.412 5.018 20.706 5.018 30.118 0l298.667-159.292c10.428-5.559 16.943-16.414 16.943-28.233v-386.846c0-12.524-7.309-23.896-18.697-29.103l-298.667-136.533c-8.448-3.862-18.159-3.862-26.611 0zM258.128 357.014l234.668 107.276v335.71l-234.668-125.154v-317.832zM556.796 800v-335.71l234.667-107.276v317.832l-234.667 125.154zM524.796 408.548l-221.701-101.348 221.701-101.348 221.696 101.348-221.696 101.348z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["cube"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":336,"id":109,"name":"cube","prevSize":32,"code":59684},"setIdx":0,"setId":0,"iconIdx":36},{"icon":{"paths":["M431.872 256c0-44.183-35.816-80-79.999-80s-80 35.817-80 80c0 44.183 35.817 80 80 80s79.999-35.817 79.999-80zM475.84 288c-14.208 55.207-64.324 96-123.967 96s-109.758-40.793-123.968-96h-89.367c-17.673 0-32-14.327-32-32s14.327-32 32-32h89.367c14.209-55.207 64.325-96 123.968-96s109.759 40.793 123.967 96h430.699c17.673 0 32 14.327 32 32s-14.327 32-32 32h-430.699zM106.539 768c0-17.673 14.327-32 32-32h89.367c14.209-55.206 64.325-96 123.968-96 60.782 0 111.67 42.368 124.743 99.179 4.207-2.035 8.93-3.179 13.922-3.179h416c17.673 0 32 14.327 32 32s-14.327 32-32 32h-416c-4.992 0-9.715-1.143-13.922-3.179-13.073 56.811-63.961 99.179-124.743 99.179-59.643 0-109.758-40.794-123.968-96h-89.367c-17.673 0-32-14.327-32-32zM351.873 848c44.183 0 79.999-35.819 79.999-80s-35.816-80-79.999-80c-44.183 0-80 35.819-80 80s35.817 80 80 80zM806.571 543.757c-14.127 55.33-64.299 96.243-124.032 96.243-59.729 0-109.905-40.913-124.028-96.243-1.301 0.162-2.628 0.243-3.972 0.243h-416c-17.673 0-32-14.327-32-32s14.327-32 32-32h416c1.344 0 2.671 0.081 3.972 0.243 14.123-55.331 64.299-96.243 124.028-96.243 59.733 0 109.905 40.913 124.032 96.243 1.301-0.162 2.624-0.243 3.968-0.243h96c17.673 0 32 14.327 32 32s-14.327 32-32 32h-96c-1.344 0-2.667-0.081-3.968-0.243zM762.539 512c0-44.181-35.819-80-80-80s-80 35.819-80 80c0 44.181 35.819 80 80 80s80-35.819 80-80z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["customize"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":337,"id":108,"name":"customize","prevSize":32,"code":59685},"setIdx":0,"setId":0,"iconIdx":37},{"icon":{"paths":["M738.735 298.663c0-17.673-14.327-32-32-32s-32 14.327-32 32v426.666c0 17.673 14.327 32 32 32s32-14.327 32-32v-426.666z","M536.064 394.671c17.677 0 32 14.327 32 32v298.667c0 17.673-14.323 32-32 32-17.673 0-32-14.327-32-32v-298.667c0-17.673 14.327-32 32-32z","M397.399 554.671c0-17.673-14.327-32-32-32s-32 14.327-32 32v170.667c0 17.677 14.327 32 32 32s32-14.323 32-32v-170.667z","M152.067 199.555v624.888c0 39.518 32.036 71.556 71.555 71.556h624.89c39.518 0 71.556-32.038 71.556-71.556v-624.888c0-39.519-32.038-71.555-71.556-71.555h-624.89c-39.519 0-71.555 32.037-71.555 71.555zM223.622 192h624.89c4.173 0 7.556 3.383 7.556 7.555v624.888c0 4.173-3.383 7.556-7.556 7.556h-624.89c-4.173 0-7.555-3.383-7.555-7.556v-624.888c0-4.173 3.383-7.555 7.555-7.555z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["dashboard"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":338,"id":107,"name":"dashboard","prevSize":32,"code":59686},"setIdx":0,"setId":0,"iconIdx":38},{"icon":{"paths":["M582.033 672c-17.677 0-32 14.327-32 32s14.323 32 32 32h224c17.673 0 32-14.327 32-32v-208c0-17.673-14.327-32-32-32-17.677 0-32 14.327-32 32v130.743l-233.374-233.371c-12.497-12.497-32.759-12.497-45.257 0l-73.371 73.371-169.373-169.371c-12.497-12.497-32.758-12.497-45.255 0s-12.497 32.758 0 45.255l192 191.999c12.497 12.497 32.758 12.497 45.255 0l73.374-73.37 210.743 210.743h-146.743z"],"attrs":[{"fill":"rgb(245, 69, 92)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["Decreasing Arrow"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":4}]}},"attrs":[{"fill":"rgb(245, 69, 92)"}],"properties":{"order":339,"id":106,"name":"Decreasing-Arrow","prevSize":32,"code":59687},"setIdx":0,"setId":0,"iconIdx":39},{"icon":{"paths":["M358.638 778.671c-17.673 0-32 14.327-32 32s14.327 32 32 32h341.334c17.673 0 32-14.327 32-32s-14.327-32-32-32h-341.334z","M102.638 298.672c0-70.692 57.307-128 128-128h597.334c70.69 0 128 57.308 128 128v298.666c0 70.694-57.31 128-128 128h-597.334c-70.693 0-128-57.306-128-128v-298.666zM230.638 234.672c-35.346 0-64 28.654-64 64v298.666c0 35.349 28.654 64 64 64h597.334c35.345 0 64-28.655 64-64v-298.666c0-35.346-28.655-64-64-64h-597.334z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["desktop"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1},{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":340,"id":105,"name":"desktop","prevSize":32,"code":59688},"setIdx":0,"setId":0,"iconIdx":40},{"icon":{"paths":["M328.285 159.791c0-17.649-14.327-31.958-32-31.958h-64c-17.673 0-32 14.308-32 31.958v63.916c0 17.65 14.327 31.958 32 31.958h64c17.673 0 32-14.308 32-31.958v-63.916zM328.285 585.894c0-17.651-14.327-31.957-32-31.957h-64c-17.673 0-32 14.306-32 31.957v63.915c0 17.651 14.327 31.957 32 31.957h64c17.673 0 32-14.306 32-31.957v-63.915zM456.286 159.791c0-17.649 14.327-31.958 32-31.958h64c17.673 0 32 14.308 32 31.958v63.916c0 17.65-14.327 31.958-32 31.958h-64c-17.673 0-32-14.308-32-31.958v-63.916zM584.286 372.843c0-17.65-14.327-31.958-32-31.958h-64c-17.673 0-32 14.308-32 31.958v63.914c0 17.651 14.327 31.957 32 31.957h64c17.673 0 32-14.306 32-31.957v-63.914zM456.286 585.894c0-17.651 14.327-31.957 32-31.957h64c17.673 0 32 14.306 32 31.957v63.915c0 17.651-14.327 31.957-32 31.957h-64c-17.673 0-32-14.306-32-31.957v-63.915zM584.286 798.946c0-17.651-14.327-31.957-32-31.957h-64c-17.673 0-32 14.306-32 31.957v63.915c0 17.651 14.327 31.957 32 31.957h64c17.673 0 32-14.306 32-31.957v-63.915zM712.286 159.791c0-17.649 14.327-31.958 32-31.958h64c17.673 0 32 14.308 32 31.958v63.916c0 17.65-14.327 31.958-32 31.958h-64c-17.673 0-32-14.308-32-31.958v-63.916zM840.286 372.843c0-17.65-14.327-31.958-32-31.958h-64c-17.673 0-32 14.308-32 31.958v63.914c0 17.651 14.327 31.957 32 31.957h64c17.673 0 32-14.306 32-31.957v-63.914zM712.286 585.894c0-17.651 14.327-31.957 32-31.957h64c17.673 0 32 14.306 32 31.957v63.915c0 17.651-14.327 31.957-32 31.957h-64c-17.673 0-32-14.306-32-31.957v-63.915zM328.285 372.843c0-17.65-14.327-31.958-32-31.958h-64c-17.673 0-32 14.308-32 31.958v63.914c0 17.651 14.327 31.957 32 31.957h64c17.673 0 32-14.306 32-31.957v-63.914z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["dialpad"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":341,"id":104,"name":"dialpad","prevSize":32,"code":59689},"setIdx":0,"setId":0,"iconIdx":41},{"icon":{"paths":["M520.286 96c80.094 0 154.901 22.636 218.377 61.859l-46.746 46.746c-24.742-13.843-51.324-24.785-79.287-32.368 12.169 22.394 23.078 49.096 32.405 79.249l-51.998 51.999c-5.658-22.993-12.169-44.004-19.349-62.666-12.821-33.338-26.522-55.927-38.473-69.070-8.397-9.235-13.431-11.29-14.929-11.698-1.498 0.407-6.532 2.463-14.929 11.698-11.951 13.143-25.651 35.731-38.473 69.070-16.299 42.377-29.175 96.867-36.339 159.182h65.975l-64 63.999h-7.116c-0.116 2.47-0.223 4.949-0.322 7.437l-64.536 64.538c-0.173-7.936-0.261-15.927-0.261-23.974 0-16.23 0.358-32.247 1.053-48h-189.809c-2.14 15.697-3.245 31.718-3.245 48 0 33.28 4.619 65.485 13.251 96h106.984l-64 64h-17.852c2.004 3.921 4.079 7.799 6.223 11.631l-46.746 46.746c-39.223-63.475-61.859-138.283-61.859-218.377 0-229.751 186.25-416 416.001-416zM874.428 293.623l-46.746 46.746c10.56 18.873 19.43 38.819 26.411 59.632h-86.046l-64 63.999h164.992c2.142 15.697 3.247 31.718 3.247 48 0 33.28-4.621 65.485-13.252 96h-183.027c2.799-30.814 4.279-62.959 4.279-96 0-8.047-0.090-16.038-0.26-23.974l-64.538 64.538c-0.751 19.008-2.022 37.517-3.763 55.437h-51.678l-64 64h107.093c-7.373 42.458-17.489 80.081-29.453 111.185-12.821 33.335-26.522 55.923-38.473 69.069-8.397 9.233-13.431 11.29-14.929 11.695-1.498-0.405-6.532-2.462-14.929-11.695-11.951-13.146-25.651-35.733-38.473-69.069-7.181-18.662-13.692-39.676-19.349-62.673l-51.998 52.002c9.327 30.153 20.238 56.853 32.406 79.249-27.966-7.582-54.548-18.526-79.287-32.367l-46.746 46.746c63.347 39.142 137.984 61.769 217.899 61.858h0.956c229.53-0.26 415.522-186.411 415.522-416 0-80.094-22.635-154.903-61.858-218.377zM427.942 172.237c-113.551 30.788-204.311 116.98-241.465 227.764h179.674c10-93.227 32.176-173.254 61.791-227.764zM612.629 851.763c24.397-44.902 43.742-107.119 55.394-179.763h165.879c-44.651 87.347-124.723 153.583-221.274 179.763zM833.66 153.373c12.497-12.497 32.755-12.497 45.252 0s12.497 32.758 0 45.255l-672 671.999c-12.497 12.497-32.758 12.497-45.255 0s-12.497-32.755 0-45.252l672.002-672.001z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["directory-off"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":342,"id":103,"name":"directory-off","prevSize":32,"code":59690},"setIdx":0,"setId":0,"iconIdx":42},{"icon":{"paths":["M870.033 511.326c0 33.237-4.621 65.399-13.252 95.876h-183.031c2.799-30.78 4.284-62.878 4.284-95.876 0-16.209-0.358-32.205-1.054-47.936h189.807c2.138 15.676 3.247 31.676 3.247 47.936zM612.911 463.39c0.738 15.65 1.122 31.646 1.122 47.936 0 33.353-1.604 65.468-4.565 95.876h-182.874c-2.958-30.409-4.562-62.524-4.562-95.876 0-16.29 0.383-32.286 1.12-47.936h189.76zM672.166 399.476c-10.001-93.104-32.175-173.025-61.79-227.464 113.549 30.747 204.309 116.826 241.463 227.464h-179.674zM425.689 172.012c-29.615 54.438-51.791 134.359-61.791 227.464h-179.674c37.154-110.638 127.914-196.717 241.465-227.464zM428.288 399.476c7.164-62.232 20.041-116.651 36.339-158.972 12.826-33.295 26.526-55.853 38.477-68.979 8.397-9.223 13.427-11.276 14.929-11.683 1.498 0.407 6.528 2.46 14.929 11.683 11.951 13.126 25.651 35.684 38.473 68.979 16.299 42.321 29.175 96.739 36.339 158.972h-179.486zM359.085 463.39c-0.696 15.731-1.053 31.727-1.053 47.936 0 32.998 1.481 65.097 4.281 95.876h-183.031c-8.632-30.477-13.251-62.639-13.251-95.876 0-16.26 1.105-32.26 3.245-47.936h189.809zM370.294 671.117c11.652 72.55 30.998 134.682 55.392 179.524-96.549-26.146-176.621-92.292-221.273-179.524h165.881zM518.511 926.775c229.53-0.256 415.522-186.163 415.522-415.45 0-229.447-186.253-415.451-416-415.451-229.752 0-416.002 186.004-416.002 415.451 0 229.291 185.992 415.194 415.524 415.45 0.158 0.004 0.316 0.004 0.478 0.004 0.158 0 0.316 0 0.478-0.004zM610.377 850.641c24.393-44.843 43.742-106.978 55.394-179.524h165.879c-44.655 87.232-124.723 153.378-221.274 179.524zM600.883 671.117c-7.369 42.398-17.485 79.974-29.449 111.036-12.821 33.293-26.522 55.851-38.473 68.979-8.401 9.22-13.431 11.273-14.929 11.682-1.498-0.41-6.532-2.462-14.929-11.682-11.951-13.129-25.651-35.686-38.477-68.979-11.959-31.061-22.080-68.638-29.449-111.036h165.705z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["directory"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":343,"id":102,"name":"directory","prevSize":32,"code":59691},"setIdx":0,"setId":0,"iconIdx":43},{"icon":{"paths":["M901.594 511.326c0-194.147-157.594-351.535-352-351.535-194.404 0-352 157.388-352 351.535 0 194.15 157.596 351.535 352 351.535 194.406 0 352-157.385 352-351.535zM965.594 511.326c0 229.449-186.249 415.454-416 415.454-229.75 0-416-186.005-416-415.454 0-229.447 186.25-415.451 416-415.451 229.751 0 416 186.004 416 415.451zM731.853 570.615l-159.97 155.511c-12.42 12.079-32.218 12.079-44.642 0l-159.968-155.511c-12.664-12.309-12.937-32.542-0.609-45.188 12.327-12.651 32.587-12.924 45.251-0.61l105.65 102.707v-275.987c0-17.65 14.327-31.958 32-31.958s32 14.308 32 31.958v275.987l105.647-102.707c12.668-12.314 32.926-12.041 45.252 0.61 12.326 12.646 12.053 32.879-0.61 45.188z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["download"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":344,"id":101,"name":"download","prevSize":32,"code":59692},"setIdx":0,"setId":0,"iconIdx":44},{"icon":{"paths":["M835.046 154.27c-37.385-39.598-100.237-40.213-138.394-1.354l-487.64 496.646c-12.266 12.493-20.875 28.1-24.894 45.129l-34.767 147.307c-6.682 28.309 17.085 54.537 45.958 50.714l133.245-17.643c20.625-2.731 39.803-12.079 54.648-26.637l507.782-498.004c37.286-36.567 38.434-96.202 2.581-134.174l-58.517-61.983zM742.349 197.665c12.719-12.953 33.673-12.748 46.131 0.451l58.522 61.983c11.947 12.657 11.567 32.536-0.862 44.725l-112.183 110.023-103.428-103.293 111.821-113.889zM585.715 357.193l102.575 102.438-349.932 343.198c-4.948 4.851-11.341 7.97-18.216 8.879l-101.046 13.38 27.316-115.733c1.34-5.675 4.209-10.88 8.298-15.044l331.006-337.118z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["edit"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":345,"id":100,"name":"edit","prevSize":32,"code":59693},"setIdx":0,"setId":0,"iconIdx":45},{"icon":{"paths":["M340.612 644.885c-21.571-19.618-6.007-52.885 23.151-52.885 8.965 0 17.527 3.529 24.272 9.438 21.605 18.918 42.642 31.957 62.704 40.508 36.561 15.59 71.804 17.109 104.794 9.941 37.628-8.179 72.657-27.81 102.106-51.345 6.729-5.376 14.997-8.542 23.607-8.542 30.217 0 45.619 34.257 22.4 53.594-36.915 30.741-82.795 57.591-134.524 68.834-44.796 9.732-93.67 7.629-143.484-13.606-28.791-12.275-57.233-30.656-85.026-55.936z","M410.707 480c35.347 0 63.998-28.655 63.998-64 0-35.346-28.651-64-63.998-64s-64 28.654-64 64c0 35.345 28.654 64 64 64z","M634.705 480c35.349 0 64-28.655 64-64 0-35.346-28.651-64-64-64-35.345 0-64 28.654-64 64 0 35.345 28.655 64 64 64z","M938.539 512c0 229.751-186.249 416-416 416-229.75 0-416-186.249-416-416s186.249-416 416-416c229.751 0 416 186.249 416 416zM874.539 512c0-194.404-157.594-352-352-352-194.404 0-352 157.596-352 352 0 194.402 157.596 352 352 352 194.406 0 352-157.598 352-352z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["emoji"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":346,"id":99,"name":"emoji","prevSize":32,"code":59694},"setIdx":0,"setId":0,"iconIdx":46},{"icon":{"paths":["M352.456 430.882l224.491 224.491-126.118 126.118-224.492-224.491 126.12-126.118zM397.711 385.626l192.117-192.116 224.491 224.49-192.119 192.116-224.489-224.49zM612.454 125.628c-12.497-12.497-32.759-12.497-45.257 0l-408.744 408.747c-12.497 12.497-12.497 32.755 0 45.252l269.744 269.747c5.231 5.231 11.823 8.269 18.633 9.122v0.068h0.572c2.274 0.243 4.574 0.243 6.848 0h440.58c17.673 0 32-14.327 32-32s-14.327-32-32-32h-366.566l353.937-353.937c12.493-12.497 12.493-32.757 0-45.254l-269.747-269.745z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["eraser"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":347,"id":98,"name":"eraser","prevSize":32,"code":59695},"setIdx":0,"setId":0,"iconIdx":47},{"icon":{"paths":["M193.303 96c-17.673 0-32 14.327-32 32v768c0 17.673 14.327 32 32 32h511.998c17.677 0 32-14.327 32-32v-96c0-17.673-14.323-32-32-32-17.673 0-32 14.327-32 32v64h-447.998v-704h447.998v64c0 17.673 14.327 32 32 32 17.677 0 32-14.327 32-32v-96c0-17.673-14.323-32-32-32h-511.998zM919.932 489.374l-160-160.001c-12.497-12.497-32.759-12.497-45.257 0s-12.497 32.758 0 45.255l105.374 105.373h-418.746c-17.673 0-32 14.327-32 32s14.327 32 32 32h418.746l-105.374 105.374c-12.497 12.497-12.497 32.755 0 45.252s32.759 12.497 45.257 0l160-160c12.497-12.497 12.497-32.755 0-45.252z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["exit"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":348,"id":97,"name":"exit","prevSize":32,"code":59696},"setIdx":0,"setId":0,"iconIdx":48},{"icon":{"paths":["M878.182 398.148c-0.188 17.672-14.669 31.847-32.337 31.655-17.673-0.188-31.846-14.666-31.659-32.338l1.318-123.488-193.438 193.437c-12.497 12.497-32.759 12.497-45.257 0s-12.497-32.755 0-45.254l193.442-193.439-123.49 1.319c-17.673 0.189-32.149-13.984-32.341-31.657-0.188-17.672 13.986-32.151 31.659-32.34l201.92-2.156c8.606-0.092 16.883 3.286 22.967 9.37s9.463 14.365 9.374 22.969l-2.159 201.921zM185.6 626.517c0.189-17.673 14.668-31.842 32.34-31.654s31.845 14.669 31.657 32.341l-1.318 123.486 193.438-193.438c12.497-12.497 32.759-12.497 45.257 0s12.497 32.759 0 45.257l-193.44 193.438 123.488-1.318c17.672-0.192 32.153 13.982 32.34 31.654s-13.986 32.154-31.657 32.341l-201.92 2.155c-8.605 0.094-16.884-3.285-22.969-9.37s-9.463-14.366-9.371-22.967l2.156-201.924z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["expand-arrow"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":349,"id":96,"name":"expand-arrow","prevSize":32,"code":59697},"setIdx":0,"setId":0,"iconIdx":49},{"icon":{"paths":["M831.403 153.173c12.497-12.48 32.759-12.48 45.257 0s12.497 32.715 0 45.195l-672.001 671.115c-12.497 12.48-32.758 12.48-45.255 0s-12.497-32.717 0-45.197l671.999-671.113zM113.338 479.424c101.801-153.5 303.397-327.248 541.399-225.142l-49.515 49.446c-56.452-19.184-107.934-19.478-153.318-9.713-114.756 24.688-215.372 118.236-280.423 213.585 38.582 47.94 75.869 86.711 111.715 117.73l-45.303 45.244c-39.632-34.692-80.083-77.333-121.158-129.007-14.229-17.903-16.035-43.089-3.397-62.144zM800.256 349.994l-45.269 45.21c35.499 31.386 72.243 70.857 110.042 119.924-61.466 95.061-158.447 188.433-271.765 213.342-46.69 10.266-100.493 9.719-160.38-11.588l-49.268 49.203c244.34 107.191 442.804-69.069 540.067-223.957 11.657-18.564 9.882-42.598-3.392-60.049-40.439-53.163-80.533-96.801-120.034-132.084zM517.632 346.974c13.687 0 26.999 1.57 39.748 4.534l-203.469 203.201c-3.895-13.82-5.974-28.365-5.974-43.379 0-90.772 75.974-164.356 169.694-164.356zM681.527 468.57l-202.999 202.726c12.553 2.867 25.647 4.386 39.104 4.386 93.717 0 169.694-73.583 169.694-164.352 0-14.793-2.018-29.129-5.798-42.761z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["eye-off"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":350,"id":95,"name":"eye-off","prevSize":32,"code":59698},"setIdx":0,"setId":0,"iconIdx":50},{"icon":{"paths":["M591.010 728.469c-107.23 23.569-251.957-9.865-421.785-220.873 65.051-95.349 165.667-188.897 280.422-213.585 108.169-23.272 250.953 10.59 413.124 221.112-61.461 95.061-158.443 188.433-271.761 213.346zM918.033 482.074c-347.132-456.358-668.857-210.875-806.95-2.654-12.638 19.055-10.832 44.241 3.398 62.144 362.307 455.817 676.142 208.862 806.945 0.559 11.657-18.564 9.882-42.598-3.392-60.049zM621.069 511.326c0-53.641-45.457-100.44-105.694-100.44s-105.693 46.8-105.693 100.44c0 53.636 45.456 100.437 105.693 100.437s105.694-46.801 105.694-100.437zM685.069 511.326c0 90.769-75.972 164.352-169.694 164.352-93.718 0-169.693-73.583-169.693-164.352 0-90.772 75.975-164.356 169.693-164.356 93.722 0 169.694 73.584 169.694 164.356z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["eye"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":351,"id":94,"name":"eye","prevSize":32,"code":59699},"setIdx":0,"setId":0,"iconIdx":51},{"icon":{"paths":["M172.794 256c0-17.673 14.327-32 32-32h640.001c17.673 0 32 14.327 32 32s-14.327 32-32 32h-640.001c-17.673 0-32-14.327-32-32zM172.794 421.161c0-17.673 14.327-32 32-32h640.001c17.673 0 32 14.327 32 32s-14.327 32.001-32 32.001h-640.001c-17.673 0-32-14.327-32-32.001zM172.794 602.837c0-17.673 14.327-32 32-32h640.001c17.673 0 32 14.327 32 32s-14.327 32-32 32h-640.001c-17.673 0-32-14.327-32-32zM172.794 768c0-17.673 14.327-32 32-32h344.616c17.673 0 32 14.327 32 32s-14.327 32-32 32h-344.616c-17.673 0-32-14.327-32-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["File-doc"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":352,"id":93,"name":"File-doc","prevSize":32,"code":59700},"setIdx":0,"setId":0,"iconIdx":52},{"icon":{"paths":["M899.776 572.574h-269.013l-250.606-423.241h269.063l250.556 423.241zM362.605 190.906l134.483 238.078-230.78 408.354-134.532-237.922 230.829-408.51zM442.718 615.979h455.706l-134.532 258.688h-465.642l144.468-258.688z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["File-GoogleDrive"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":353,"id":92,"name":"File-GoogleDrive","prevSize":32,"code":59701},"setIdx":0,"setId":0,"iconIdx":53},{"icon":{"paths":["M541.619 128c200.294 0 362.667 162.371 362.667 362.667h-362.667v-362.667z","M136.285 533.333c0-200.295 162.371-362.667 362.668-362.667v362.667h362.667c0 200.294-162.372 362.667-362.667 362.667-200.296 0-362.668-162.372-362.668-362.667z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["File-Keynote"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1},{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":354,"id":91,"name":"File-Keynote","prevSize":32,"code":59702},"setIdx":0,"setId":0,"iconIdx":54},{"icon":{"paths":["M886.575 567.625c-41.856-41.139-161.237-29.828-220.928-22.285-59.004-35.998-98.458-85.705-126.242-158.727 13.376-55.195 34.645-139.187 18.522-191.982-14.404-89.82-129.673-80.907-146.138-20.227-15.095 55.194-1.372 131.987 24.014 230.035-34.305 81.935-85.42 191.981-121.441 255.059-68.611 35.311-161.235 89.822-174.957 158.387-11.321 54.165 89.194 189.239 261.063-106.961 76.845-25.37 160.548-56.567 234.647-68.907 64.836 34.965 140.651 58.278 191.424 58.278 87.479 0 96.055-96.674 60.036-132.672zM206.985 834.342c17.495-46.967 84.048-101.133 104.288-119.991-65.18 103.876-104.288 122.389-104.288 119.991zM486.916 180.918c25.387 0 22.985 110.047 6.174 139.872-15.091-47.653-14.75-139.872-6.174-139.872zM403.212 649.216c33.277-57.937 61.748-126.844 84.733-187.524 28.476 51.767 64.836 93.248 103.262 121.702-71.356 14.741-133.449 44.911-187.995 65.822zM854.669 632.077c0 0-17.152 20.57-127.957-26.743 120.41-8.913 140.309 18.513 127.957 26.743z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["File-pdf"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":355,"id":90,"name":"File-pdf","prevSize":32,"code":59703},"setIdx":0,"setId":0,"iconIdx":55},{"icon":{"paths":["M143.105 192.005c-17.673 0-32 14.327-32 32v576.020c0 17.673 14.327 32 32 32h767.999c17.677 0 32-14.327 32-32v-576.020c0-17.673-14.323-32-32-32h-767.999zM175.105 378.307v-122.302h149.334v122.302h-149.334zM175.105 442.308h149.334v141.722h-149.334v-141.722zM175.105 648.030h149.334v119.996h-149.334v-119.996zM388.439 768.026v-119.996h490.665v119.996h-490.665zM879.104 584.030h-490.665v-141.722h490.665v141.722zM879.104 378.307h-490.665v-122.302h490.665v122.302z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["File-sheets"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":356,"id":89,"name":"File-sheets","prevSize":32,"code":59704},"setIdx":0,"setId":0,"iconIdx":56},{"icon":{"paths":["M390.031 149.138c0-11.766 9.551-21.305 21.333-21.305h85.335c11.78 0 21.333 9.539 21.333 21.305v106.526h-106.668c-11.782 0-21.333-9.539-21.333-21.305v-85.221z","M518.033 255.665h106.667c11.78 0 21.333 9.539 21.333 21.305v85.221c0 11.767-9.553 21.305-21.333 21.305h-106.667v-127.831z","M390.031 404.801c0-11.767 9.551-21.305 21.333-21.305h106.668v127.83h-106.668c-11.782 0-21.333-9.536-21.333-21.303v-85.222z","M518.033 511.326h106.667c11.78 0 21.333 9.54 21.333 21.308v106.526h-128v-127.834z","M432.7 639.159h213.333v213.052c0 23.531-19.106 42.611-42.667 42.611h-170.667c-23.566 0-42.668-19.081-42.668-42.611v-170.445c0-23.531 19.102-42.607 42.668-42.607zM496.7 724.378c-11.785 0-21.333 9.54-21.333 21.308v42.607c0 11.767 9.549 21.308 21.333 21.308h42.667c11.78 0 21.333-9.54 21.333-21.308v-42.607c0-11.767-9.553-21.308-21.333-21.308h-42.667z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["file-zip"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1},{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":357,"id":88,"name":"file-zip","prevSize":32,"code":59705},"setIdx":0,"setId":0,"iconIdx":57},{"icon":{"paths":["M147.558 351.536c0-17.649 14.327-31.958 32-31.958h704c17.673 0 32 14.308 32 31.958s-14.327 31.958-32 31.958h-704c-17.673 0-32-14.308-32-31.958zM232.892 521.98c0-17.651 14.327-31.957 32-31.957h533.333c17.673 0 32 14.306 32 31.957s-14.327 31.957-32 31.957h-533.333c-17.673 0-32-14.31-32-31.957zM350.225 660.459c-17.673 0-32 14.31-32 31.957 0 17.651 14.327 31.962 32 31.962h362.667c17.673 0 32-14.31 32-31.962 0-17.647-14.327-31.957-32-31.957h-362.667z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["filter"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":358,"id":87,"name":"filter","prevSize":32,"code":59706},"setIdx":0,"setId":0,"iconIdx":58},{"icon":{"paths":["M649.412 896c-2.803 0-5.295-0.623-7.168-0.939-61.999-16.858-102.814-39.646-145.813-80.858-55.147-54.007-85.368-125.815-85.368-202.3 0-65.873 56.705-119.573 126.495-119.573 69.794 0 126.498 53.7 126.498 119.573 0 34.965 31.467 63.373 69.79 63.373s69.794-28.407 69.794-63.373c0-135.808-119.642-246.636-266.705-246.636-104.998 0-200.337 57.132-243.333 145.793-14.332 29.35-21.498 63.066-21.498 100.843 0 28.719 2.493 73.365 24.925 131.746 2.804 7.181 2.493 14.673-0.623 21.854-3.116 6.865-9.036 11.861-16.202 14.357-2.804 1.25-6.231 1.562-9.658 1.562-11.84 0-22.433-7.181-26.483-18.108-19.006-50.261-28.353-99.9-28.353-151.727 0-46.204 9.036-88.35 26.795-125.5 52.343-108.020 167.935-177.64 294.43-177.64 178.53 0 323.721 135.805 323.721 302.828 0 65.873-56.704 119.573-126.81 119.573-70.101 0-126.805-53.7-126.805-119.573 0-34.965-31.471-63.373-69.794-63.373-38.635 0-69.79 28.407-69.79 63.373 0 61.504 24.303 119.262 68.544 162.342 35.209 34.031 68.86 53.073 120.58 67.123 7.164 1.873 13.397 6.554 17.135 13.111s4.672 14.362 2.803 21.231c-2.803 11.861-14.020 20.915-27.106 20.915zM453.124 888.196c-7.791 0-15.266-3.123-20.254-8.742-33.336-32.781-51.718-54.012-77.89-100.527-26.795-47.142-41.127-105.212-41.127-167.339 0-116.446 100.948-211.354 224.954-211.354 124.002 0 224.951 94.908 224.951 211.354 0 15.612-12.463 28.1-28.352 28.1-15.893 0-28.668-12.177-28.668-28.1 0-85.538-75.396-155.157-168.243-155.157-92.851 0-168.249 69.619-168.249 155.157 0 52.45 11.84 100.527 34.272 139.554 23.367 41.519 38.945 59.004 68.858 88.661 10.901 11.238 10.901 28.723 0 39.65-5.922 5.931-13.086 8.742-20.254 8.742zM726.059 818.889c-47.36 0-88.798-11.866-123.383-34.965-59.196-39.65-94.716-103.962-94.716-172.335 0-15.607 12.463-28.096 28.352-28.096 15.893 0 28.356 12.489 28.356 28.096 0 49.643 26.172 96.781 69.79 125.504 25.237 16.858 55.147 24.977 91.601 24.977 7.787 0 22.434-0.939 38.012-3.746 1.557-0.311 3.426-0.311 4.983-0.311 13.709 0 25.237 9.988 27.729 23.411 1.246 7.181-0.311 14.673-4.361 20.608-4.361 6.242-10.906 10.611-18.697 11.861-23.364 4.685-43.93 4.996-47.667 4.996zM215.087 435.823c-5.609 0-11.217-1.562-16.202-4.992-6.543-4.062-10.593-10.616-12.151-18.109-1.246-7.493 0.311-14.985 4.985-21.229 38.634-53.698 87.862-95.844 146.125-125.502 60.133-30.595 129.612-46.829 200.963-46.829 71.036 0 140.203 15.922 200.026 46.205 58.573 29.658 107.802 71.493 146.125 124.566 4.361 5.932 6.229 13.425 4.983 20.917s-5.606 14.049-11.84 18.42c-4.983 3.435-10.59 4.992-16.512 4.992-9.037 0-17.758-4.369-23.057-11.861-33.335-45.893-75.708-82.107-125.559-107.083-52.343-26.224-112.789-40.273-174.477-40.273-62.315 0-122.76 14.049-175.103 40.585-49.851 25.912-92.536 62.127-126.185 108.644-3.739 6.869-12.463 11.55-22.121 11.55zM760.017 239.142c-4.672 0-9.344-1.249-13.397-3.434-71.347-35.902-133.35-51.512-207.501-51.512-74.466 0-144.258 17.483-207.818 51.825-4.050 2.185-8.724 3.122-13.397 3.122-10.282 0-19.629-5.62-24.925-14.361-3.739-6.556-4.674-14.361-2.493-21.542s7.166-13.424 13.709-16.858c72.595-38.712 151.732-58.38 234.924-58.38 82.564 0 154.846 17.795 233.984 58.068 6.857 3.434 11.84 9.366 14.332 16.858 2.185 7.18 1.25 14.673-2.18 21.229-4.983 9.053-14.643 14.985-25.237 14.985z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["fingerprint"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":359,"id":86,"name":"fingerprint","prevSize":32,"code":59707},"setIdx":0,"setId":0,"iconIdx":59},{"icon":{"paths":["M292.988 170.667c0-17.673 14.327-32 32-32h500.62c12.122 0 23.202 6.848 28.625 17.689 5.419 10.841 4.25 23.814-3.025 33.511l-122.133 162.845 122.133 162.843c7.275 9.698 8.444 22.673 3.025 33.51-5.423 10.842-16.503 17.69-28.625 17.69h-468.62v286.579c0 17.673-14.327 32-32 32s-32-14.327-32-32v-682.667zM356.988 502.754h404.62l-98.133-130.843c-8.533-11.378-8.533-27.023 0-38.4l98.133-130.845h-404.62v300.087z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["flag"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":360,"id":85,"name":"flag","prevSize":32,"code":59708},"setIdx":0,"setId":0,"iconIdx":60},{"icon":{"paths":["M158.225 213.333c0-17.673 14.327-32 32-32h234.057c7.184 0 14.156 2.416 19.796 6.86l88.815 69.94h339.998c17.673 0 32 14.327 32 32v520.533c0 17.673-14.327 32-32 32h-682.667c-17.673 0-32-14.327-32-32v-597.333zM222.225 245.333v533.333h618.667v-456.533h-319.087c-7.181 0-14.153-2.416-19.797-6.86l-88.812-69.94h-190.97z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["folder"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":361,"id":84,"name":"folder","prevSize":32,"code":59709},"setIdx":0,"setId":0,"iconIdx":61},{"icon":{"paths":["M374.031 544c0-17.673-14.327-32-32-32s-32 14.327-32 32v32h-32c-17.673 0-32 14.327-32 32s14.327 32 32 32h32v32c0 17.673 14.327 32 32 32s32-14.327 32-32v-32h32c17.673 0 32.002-14.327 32.002-32s-14.329-32-32.002-32h-32v-32z","M750.033 624c30.925 0 56-25.071 56-56s-25.075-56-56-56c-30.929 0-56 25.071-56 56s25.071 56 56 56z","M678.033 664c0 30.929-25.075 56-56 56-30.929 0-56-25.071-56-56s25.071-56 56-56c30.925 0 56 25.071 56 56z","M710.033 128c0-17.673-14.327-32-32-32-17.677 0-32 14.327-32 32v96h-128c-17.677 0-32 14.327-32 32v96h-192.002c-106.039 0-192 85.961-192 192v128c0 106.039 85.961 192 192 192h448.002c106.035 0 192-85.961 192-192v-128c0-106.039-85.965-192-192-192h-192v-64h128c17.673 0 32-14.327 32-32v-128zM870.033 544v128c0 70.694-57.31 128-128 128h-448.002c-70.693 0-128-57.306-128-128v-128c0-70.694 57.307-128 128-128h448.002c70.69 0 128 57.306 128 128z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["game"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":362,"id":83,"name":"game","prevSize":32,"code":59710},"setIdx":0,"setId":0,"iconIdx":62},{"icon":{"paths":["M143.049 272c0-17.673 14.327-32 32-32h703.999c17.673 0 32 14.327 32 32s-14.327 32-32 32h-703.999c-17.673 0-32-14.327-32-32zM303.049 432c0 17.673-14.327 32-32 32s-32-14.327-32-32c0-17.673 14.327-32 32-32s32 14.327 32 32zM303.049 752c0 17.673-14.327 32-32 32s-32-14.327-32-32c0-17.673 14.327-32 32-32s32 14.327 32 32zM463.049 624c17.673 0 32-14.327 32-32s-14.327-32-32-32c-17.673 0-32 14.327-32 32s14.327 32 32 32zM399.049 400c-17.673 0-32 14.327-32 32s14.327 32 32 32h479.999c17.673 0 32-14.327 32-32s-14.327-32-32-32h-479.999zM367.049 752c0-17.673 14.327-32 32-32h479.999c17.673 0 32 14.327 32 32s-14.327 32-32 32h-479.999c-17.673 0-32-14.327-32-32zM591.049 560c-17.673 0-32 14.327-32 32s14.327 32 32 32h288c17.673 0 32-14.327 32-32s-14.327-32-32-32h-288z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["group-by-type"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":363,"id":82,"name":"group-by-type","prevSize":32,"code":59711},"setIdx":0,"setId":0,"iconIdx":63},{"icon":{"paths":["M579.776 352c-17.673 0-32-14.327-32-32s14.327-32 32-32h224c17.673 0 32 14.327 32 32v208c0 17.673-14.327 32-32 32s-32-14.327-32-32v-130.745l-233.374 233.371c-12.497 12.497-32.755 12.497-45.252 0l-73.374-73.37-169.373 169.37c-12.497 12.497-32.758 12.497-45.255 0s-12.497-32.755 0-45.252l192-192c12.497-12.497 32.756-12.497 45.254 0l73.374 73.37 210.743-210.743h-146.743z"],"attrs":[{"fill":"rgb(45, 224, 165)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["Growing Arrow"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":2}]}},"attrs":[{"fill":"rgb(45, 224, 165)"}],"properties":{"order":364,"id":81,"name":"Growing-Arrow","prevSize":32,"code":59712},"setIdx":0,"setId":0,"iconIdx":64},{"icon":{"paths":["M371.339 128c17.673 0 32 14.327 32 32v144h287.998v-144c0-17.673 14.327-32 32-32 17.677 0 32 14.327 32 32v144h144c17.677 0 32 14.327 32 32s-14.323 32-32 32h-144v288h144c17.677 0 32 14.327 32 32s-14.323 32-32 32h-144v144c0 17.673-14.323 32-32 32-17.673 0-32-14.327-32-32v-144h-287.998v144c0 17.673-14.327 32-32 32s-32-14.327-32-32v-144h-144c-17.673 0-32-14.327-32-32s14.327-32 32-32h144v-288h-144c-17.673 0-32-14.327-32-32s14.327-32 32-32h144v-144c0-17.673 14.327-32 32-32zM403.339 368v288h287.998v-288h-287.998z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["hash"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":365,"id":80,"name":"hash","prevSize":32,"code":59713},"setIdx":0,"setId":0,"iconIdx":65},{"icon":{"paths":["M954.321 512c0 229.751-186.249 416-416 416-229.75 0-416-186.249-416-416s186.25-416 416-416c229.751 0 416 186.249 416 416zM594.108 859.605l-41.83-156.105c-4.608 0.333-9.263 0.499-13.956 0.499-4.57 0-9.101-0.158-13.594-0.474l-41.835 156.134c18.057 2.854 36.57 4.339 55.428 4.339 18.982 0 37.615-1.502 55.787-4.395zM462.511 688.452c-47.551-20.459-85.181-59.571-103.676-108.126l-155.029 41.54c33.968 103.484 114.617 185.805 217.045 222.054l41.66-155.469zM186.321 512c0 16.090 1.079 31.927 3.17 47.445l156.905-42.044c-0.049-1.796-0.075-3.597-0.075-5.402 0-4.911 0.184-9.779 0.547-14.596l-156.051-41.813c-2.959 18.368-4.496 37.21-4.496 56.41zM419.926 180.407c-99.159 35.408-177.785 114.033-213.196 213.191l155.535 41.675c19.357-44.352 54.982-79.977 99.337-99.331l-41.676-155.535zM538.321 160c-19.196 0-38.037 1.537-56.401 4.495l41.813 156.051c4.817-0.361 9.681-0.546 14.588-0.546 5.030 0 10.018 0.194 14.95 0.573l41.805-156.022c-18.475-2.995-37.431-4.552-56.755-4.552zM656.128 843.802c102.66-36.45 183.394-119.194 217.097-223.121l-154.974-41.523c-18.291 48.981-56.013 88.491-103.787 109.15l41.664 155.494zM887.317 558.199c1.98-15.121 3.004-30.541 3.004-46.199 0-18.769-1.468-37.197-4.297-55.172l-156.16 41.843c0.303 4.403 0.457 8.849 0.457 13.329 0 1.378-0.013 2.752-0.043 4.122l157.039 42.078zM870.332 394.775c-35.166-99.601-113.886-178.641-213.278-214.248l-41.681 155.559c44.582 19.556 80.311 55.564 99.503 100.343l155.456-41.653zM666.321 512c0-70.694-57.306-128-128-128-70.69 0-128 57.306-128 128s57.309 128 128 128c70.694 0 128-57.306 128-128z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["help"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":366,"id":79,"name":"help","prevSize":32,"code":59714},"setIdx":0,"setId":0,"iconIdx":66},{"icon":{"paths":["M860.578 512c0 176.73-143.27 320-320 320-176.733 0-320.001-143.27-320.001-320h-64c0 212.079 171.923 384 384.001 384 212.075 0 384-171.921 384-384 0-212.077-171.925-384-384-384-123.72 0-233.773 58.508-304.001 149.364v-101.364c0-17.673-14.327-32-32-32s-32 14.327-32 32v192c0 17.673 14.327 32 32 32h176c17.673 0 32-14.327 32-32s-14.327-32-32-32h-107.295c57.239-86.755 155.582-144 267.296-144 176.73 0 320 143.269 320 320z","M572.578 320c0-17.673-14.327-32-32-32s-32 14.327-32 32v224c0 8.486 3.371 16.627 9.37 22.626l96 96c12.497 12.497 32.759 12.497 45.257 0s12.497-32.755 0-45.252l-86.626-86.63v-210.743z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["history"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1},{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":367,"id":78,"name":"history","prevSize":32,"code":59715},"setIdx":0,"setId":0,"iconIdx":67},{"icon":{"paths":["M523.78 195.090l224.166 259.702v365.751c0 5.85-4.745 10.59-10.603 10.59h-136.235v-149.623c0-23.394-18.991-42.359-42.415-42.359h-85.841c-23.424 0-42.411 18.965-42.411 42.359v149.623h-136.23c-5.856 0-10.603-4.74-10.603-10.59v-365.824l224.107-259.63c4.228-4.9 11.831-4.9 16.064 0zM562.257 894.669h175.087c40.99 0 74.223-33.186 74.223-74.125v-243.883h56.154c12.437 0 23.735-7.241 28.915-18.534 5.184-11.294 3.298-24.567-4.826-33.975l-319.846-370.545c-29.606-34.302-82.825-34.301-112.435 0l-319.846 370.545c-8.122 9.408-10.007 22.682-4.825 33.975s16.479 18.534 28.918 18.534h56.214v243.883c0 40.939 33.23 74.125 74.222 74.125h175.083c1.173 0.098 2.359 0.145 3.558 0.145h85.841c1.199 0 2.389-0.047 3.563-0.145z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["home"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":368,"id":77,"name":"home","prevSize":32,"code":59716},"setIdx":0,"setId":0,"iconIdx":68},{"icon":{"paths":["M440.67 405.333c0 47.13-38.203 85.333-85.331 85.333s-85.333-38.204-85.333-85.333c0-47.128 38.205-85.333 85.333-85.333s85.331 38.205 85.331 85.333z","M131.339 192c0-17.673 14.327-32 32-32h767.998c17.677 0 32 14.327 32 32v640c0 17.673-14.323 32-32 32h-767.998c-17.673 0-32-14.327-32-32v-640zM195.339 764.164l151.704-176.99c9.27-10.816 24.571-14.199 37.538-8.307l153.122 69.602 160.474-204.241c6.012-7.646 15.172-12.147 24.9-12.228 9.728-0.077 18.965 4.271 25.097 11.823l151.164 186.048v-405.871h-703.998v540.164zM248.914 800h650.423v-68.638l-175.578-216.102-166.784 212.271-176.988-80.448-131.073 152.917z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["image"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1},{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":369,"id":76,"name":"image","prevSize":32,"code":59717},"setIdx":0,"setId":0,"iconIdx":69},{"icon":{"paths":["M527.049 873.024c-199.388 0-361.025-161.634-361.025-361.024s161.637-361.026 361.025-361.026c199.39 0 361.028 161.637 361.028 361.026s-161.638 361.024-361.028 361.024zM527.049 938.667c235.644 0 426.667-191.027 426.667-426.667 0-235.642-191.023-426.667-426.667-426.667-235.641 0-426.666 191.025-426.666 426.667 0 235.639 191.025 426.667 426.666 426.667zM559.872 347.898c0 18.126-14.694 32.82-32.823 32.82-18.125 0-32.819-14.694-32.819-32.82s14.694-32.82 32.819-32.82c18.129 0 32.823 14.694 32.823 32.82zM527.049 413.539c-18.125 0-32.819 14.694-32.819 32.819v229.747c0 18.125 14.694 32.819 32.819 32.819 18.129 0 32.823-14.694 32.823-32.819v-229.747c0-18.125-14.694-32.819-32.823-32.819z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["info"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":370,"id":75,"name":"info","prevSize":32,"code":59718},"setIdx":0,"setId":0,"iconIdx":70},{"icon":{"paths":["M357.949 550.626c-12.497-12.497-12.497-32.755 0-45.252s32.758-12.497 45.255 0l105.374 105.37v-418.743c0-17.673 14.327-32 32-32s32 14.327 32 32v418.743l105.37-105.37c12.497-12.497 32.759-12.497 45.257 0s12.497 32.755 0 45.252l-160 160c-12.497 12.497-32.759 12.497-45.257 0l-159.998-160zM140.577 864c0 17.673 14.327 32 32 32h768.001c17.673 0 32-14.327 32-32v-512c0-17.673-14.327-32-32-32h-96c-17.673 0-32 14.327-32 32s14.327 32 32 32h64v448h-704.001v-448h64c17.673 0 32-14.327 32-32s-14.327-32-32-32h-96c-17.673 0-32 14.327-32 32v512z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["inport"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":371,"id":74,"name":"inport","prevSize":32,"code":59719},"setIdx":0,"setId":0,"iconIdx":71},{"icon":{"paths":["M190.831 512c0-17.673 13.133-32 29.333-32h645.333c16.201 0 29.333 14.327 29.333 32s-13.133 32-29.333 32h-645.333c-16.201 0-29.333-14.327-29.333-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["intermediate"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":372,"id":73,"name":"intermediate","prevSize":32,"code":59720},"setIdx":0,"setId":0,"iconIdx":72},{"icon":{"paths":["M565.811 352c17.673 0 32-14.327 32-32s-14.327-32-32-32c-17.673 0-32 14.327-32 32s14.327 32 32 32zM581.423 436.996c2.756-17.457-9.161-33.844-26.62-36.6-17.455-2.756-33.843 9.161-36.599 26.616l-48 304c-2.756 17.459 9.161 33.843 26.62 36.599 17.455 2.756 33.843-9.161 36.599-26.615l48-304z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["italic"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":373,"id":72,"name":"italic","prevSize":32,"code":59721},"setIdx":0,"setId":0,"iconIdx":73},{"icon":{"paths":["M376.067 512c-88.366 0-160-71.633-160-160 0-88.366 71.634-160 160-160 88.364 0 160.002 71.634 160.002 160 0 26.934-6.656 52.313-18.411 74.583l11.913 11.915-0.132 0.128 299.136 299.136c3.533 9.924 6.413 20.975 7.74 31.607 1.651 13.218 0.563 22.967-1.873 28.937-1.771 4.335-4.22 7.232-10.773 9.015-8.316 2.261-24.516 2.795-52.821-5.504-8.525-3.806-27.721-16.282-45.133-35.379-18.18-19.938-29.645-41.856-29.645-62.438 0-15.642-11.311-28.992-26.739-31.565l-91.75-15.292c-3.767-2.658-18.769-15.693-10.133-58.867 2.099-10.492-1.186-21.338-8.751-28.902l-88.201-88.196c-26.466 19.379-59.11 30.822-94.427 30.822zM592.239 410.916c5.103-18.773 7.829-38.527 7.829-58.916 0-123.712-100.288-224-224.002-224-123.712 0-224 100.288-224 224s100.288 224 224 224c29.287 0 57.26-5.619 82.903-15.842l43.008 43.008c-7.155 65.493 23.991 104.533 55.97 115.191l2.381 0.794 74.859 12.476c7.083 31.407 25.173 58.125 43.234 77.935 23.121 25.357 50.957 44.629 69.76 52.151l1.323 0.529 1.37 0.41c34.714 10.415 64.73 13.188 89.591 6.426 26.782-7.283 44.331-24.785 53.227-46.583 8.23-20.164 8.474-42.283 6.127-61.065-2.402-19.217-7.898-37.956-14.042-53.312-1.609-4.023-4.019-7.68-7.083-10.743l-286.455-286.458zM408.067 336c0 26.51-21.49 48-48 48s-48-21.49-48-48c0-26.51 21.49-48 48-48s48 21.49 48 48z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["key"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":374,"id":71,"name":"key","prevSize":32,"code":59722},"setIdx":0,"setId":0,"iconIdx":74},{"icon":{"paths":["M186.321 224c-35.346 0-64 28.654-64 64v448c0 35.345 28.654 64 64 64h704c35.345 0 64-28.655 64-64v-448c0-35.346-28.655-64-64-64h-704zM186.321 288h704v448h-704v-448zM282.321 352c-17.673 0-32 14.327-32 32s14.327 32 32 32h64c17.673 0 32-14.327 32-32s-14.327-32-32-32h-64zM282.321 512c0-17.673 14.327-32 32-32h64c17.673 0 32 14.327 32 32s-14.327 32-32 32h-64c-17.673 0-32-14.327-32-32zM506.321 480c-17.673 0-32 14.327-32 32s14.327 32 32 32h64c17.673 0 32-14.327 32-32s-14.327-32-32-32h-64zM666.321 512c0-17.673 14.327-32 32-32h64c17.673 0 32 14.327 32 32s-14.327 32-32 32h-64c-17.673 0-32-14.327-32-32zM506.321 352c-17.673 0-32 14.327-32 32s14.327 32 32 32h64c17.673 0 32-14.327 32-32s-14.327-32-32-32h-64zM346.321 640c0-17.673 14.327-32 32-32h320c17.673 0 32 14.327 32 32s-14.327 32-32 32h-320c-17.673 0-32-14.327-32-32zM730.321 352c-17.673 0-32 14.327-32 32s14.327 32 32 32h64c17.673 0 32-14.327 32-32s-14.327-32-32-32h-64z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["keyboard"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":375,"id":70,"name":"keyboard","prevSize":32,"code":59723},"setIdx":0,"setId":0,"iconIdx":75},{"icon":{"paths":["M711.381 256c0-17.673-14.327-32-32-32s-32 14.327-32 32v56.876l-80.346 13.999c-17.412 3.034-29.065 19.607-26.031 37.018s19.605 29.066 37.018 26.032l69.359-12.085v69.371c-30.383 6.852-60.459 20.075-84.151 43.14-27.925 27.183-44.075 65.242-44.075 113.809 0 25.741 6.263 48.26 18.453 66.62 12.186 18.351 29.065 30.682 47.253 37.999 35.354 14.225 76.719 10.176 108.126-4.578l1.207-0.567c31.125-14.618 62.494-29.35 90.722-57.818 21.325-21.504 39.71-49.536 56.849-88.674 5.653 9.498 9.591 20.966 10.287 34.338 1.63 31.526-14.281 82.812-87.957 153.417-12.757 12.228-13.193 32.486-0.964 45.244 12.228 12.762 32.486 13.193 45.248 0.964 80.192-76.851 110.583-145.033 107.588-202.935-2.987-57.655-38.588-96.021-70.677-113.954-20.774-13.013-50.214-22.827-81.216-28.288-16.623-2.931-34.47-4.749-52.693-4.996v-74.242l101.722-17.723c17.408-3.034 29.065-19.607 26.031-37.018s-19.61-29.066-37.018-26.032l-90.735 15.809v-45.724zM607.872 536.209c10.163-9.894 23.565-17.476 39.509-22.703v138.65c-13.444 2.547-27.486 1.732-38.635-2.752-7.71-3.102-13.658-7.757-17.822-14.029-4.156-6.259-7.77-15.996-7.77-31.215 0-33.348 10.569-54.174 24.717-67.951zM739.473 600.751c-8.683 8.755-17.783 15.706-28.092 22.076v-117.888c14.127 0.239 28.224 1.66 41.587 4.015 13.589 2.394 25.685 5.623 35.763 9.165-16.879 42.039-33.067 66.304-49.259 82.633zM277.182 565.333h98.385l-49.193-184.882-49.193 184.882zM420.328 733.559l-27.732-104.226h-132.442l-27.732 104.226c-4.544 17.079-22.073 27.243-39.152 22.699s-27.24-22.076-22.696-39.151l106.323-399.601c13.494-50.714 85.463-50.713 98.957 0l106.323 399.601c4.544 17.075-5.615 34.607-22.694 39.151s-34.609-5.619-39.153-22.699z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["language"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":376,"id":69,"name":"language","prevSize":32,"code":59724},"setIdx":0,"setId":0,"iconIdx":76},{"icon":{"paths":["M260.423 275.61l-13.972 14.271c-37.092 37.884-36.449 98.665 1.435 135.757l145.621 142.576c37.883 37.090 98.666 36.446 135.756-1.438l13.973-14.268c0.721-0.742 1.434-1.489 2.125-2.244l0.102 0.098c5.807-5.905 13.888-9.566 22.822-9.566 17.673 0 32 14.327 32 32 0 9.6-4.228 18.21-10.923 24.077l-14.37 14.677c-61.82 63.142-163.119 64.213-226.26 2.394l-145.621-142.575c-63.141-61.82-64.212-163.121-2.392-226.262l13.972-14.271c61.82-63.141 163.121-64.212 226.263-2.392l74.692 73.131c0.977 0.847 1.899 1.752 2.769 2.71l0.371 0.366-0.026 0.026c4.932 5.63 7.923 13.005 7.923 21.079 0 17.673-14.327 32-32 32-7.829 0-15.002-2.813-20.565-7.482l-0.107 0.108-77.834-76.207c-37.884-37.092-98.665-36.449-135.757 1.435zM796.147 768l13.973-14.268c37.090-37.884 36.45-98.667-1.438-135.757l-145.617-142.575c-37.888-37.090-98.667-36.45-135.761 1.434l-13.969 14.272c-0.725 0.738-1.434 1.485-2.129 2.244l-0.102-0.102c-5.803 5.905-13.884 9.57-22.818 9.57-17.677 0-32-14.327-32-32 0-9.6 4.224-18.214 10.918-24.077l14.37-14.682c61.82-63.139 163.123-64.21 226.261-2.389l145.621 142.575c63.142 61.82 64.213 163.119 2.394 226.261l-13.973 14.268c-61.82 63.142-163.119 64.213-226.261 2.394l-74.692-73.131c-0.977-0.849-1.903-1.754-2.769-2.709l-0.371-0.367 0.021-0.026c-4.932-5.632-7.919-13.005-7.919-21.077 0-17.673 14.323-32 32-32 7.829 0 15.002 2.812 20.565 7.479l0.102-0.107 77.837 76.207c37.884 37.090 98.667 36.45 135.757-1.438z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["link"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":377,"id":68,"name":"link","prevSize":32,"code":59725},"setIdx":0,"setId":0,"iconIdx":77},{"icon":{"paths":["M234.667 672c35.346 0 64-28.655 64-64s-28.654-64-64-64c-35.346 0-64 28.655-64 64s28.654 64 64 64z","M362.667 576c-17.673 0-32 14.327-32 32s14.327 32 32 32h544c17.673 0 32-14.327 32-32s-14.327-32-32-32h-544z","M234.667 480c35.346 0 64-28.655 64-64 0-35.346-28.654-64-64-64s-64 28.654-64 64c0 35.345 28.654 64 64 64z","M362.667 384c-17.673 0-32 14.327-32 32s14.327 32 32 32h544c17.673 0 32-14.327 32-32s-14.327-32-32-32h-544z","M234.667 288c35.346 0 64-28.654 64-64s-28.654-64-64-64c-35.346 0-64 28.654-64 64s28.654 64 64 64z","M362.667 192c-17.673 0-32 14.327-32 32s14.327 32 32 32h544c17.673 0 32-14.327 32-32s-14.327-32-32-32h-544z","M234.667 864c35.346 0 64-28.655 64-64s-28.654-64-64-64c-35.346 0-64 28.655-64 64s28.654 64 64 64z","M362.667 768c-17.673 0-32 14.327-32 32s14.327 32 32 32h544c17.673 0 32-14.327 32-32s-14.327-32-32-32h-544z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["list-condensed"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":378,"id":67,"name":"list-condensed","prevSize":32,"code":59726},"setIdx":0,"setId":0,"iconIdx":78},{"icon":{"paths":["M316.577 192c0-17.673 14.327-32 32-32h544.001c17.673 0 32 14.327 32 32s-14.327 32-32 32h-544.001c-17.673 0-32-14.327-32-32zM316.577 288c0-17.673 14.327-32 32-32h448.001c17.673 0 32 14.327 32 32s-14.327 32-32 32h-448.001c-17.673 0-32-14.327-32-32zM220.577 304c35.346 0 64-28.654 64-64s-28.654-64-64-64c-35.346 0-64 28.654-64 64s28.654 64 64 64z","M316.577 464c0-17.673 14.327-32 32-32h544.001c17.673 0 32 14.327 32 32s-14.327 32-32 32h-544.001c-17.673 0-32-14.327-32-32zM316.577 560c0-17.673 14.327-32 32-32h448.001c17.673 0 32 14.327 32 32s-14.327 32-32 32h-448.001c-17.673 0-32-14.327-32-32zM220.577 576c35.346 0 64-28.655 64-64s-28.654-64-64-64c-35.346 0-64 28.655-64 64s28.654 64 64 64z","M316.577 736c0-17.673 14.327-32 32-32h544.001c17.673 0 32 14.327 32 32s-14.327 32-32 32h-544.001c-17.673 0-32-14.327-32-32zM316.577 832c0-17.673 14.327-32 32-32h448.001c17.673 0 32 14.327 32 32s-14.327 32-32 32h-448.001c-17.673 0-32-14.327-32-32zM220.577 848c35.346 0 64-28.655 64-64s-28.654-64-64-64c-35.346 0-64 28.655-64 64s28.654 64 64 64z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["list-extended"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":379,"id":66,"name":"list-extended","prevSize":32,"code":59727},"setIdx":0,"setId":0,"iconIdx":79},{"icon":{"paths":["M222.831 320c35.346 0 64-28.654 64-64s-28.654-64-64-64c-35.346 0-64 28.654-64 64s28.654 64 64 64z","M350.831 224c-17.673 0-32 14.327-32 32s14.327 32 32 32h544c17.673 0 32-14.327 32-32s-14.327-32-32-32h-544z","M222.831 576c35.346 0 64-28.655 64-64s-28.654-64-64-64c-35.346 0-64 28.655-64 64s28.654 64 64 64z","M350.831 480c-17.673 0-32 14.327-32 32s14.327 32 32 32h544c17.673 0 32-14.327 32-32s-14.327-32-32-32h-544z","M222.831 832c35.346 0 64-28.655 64-64s-28.654-64-64-64c-35.346 0-64 28.655-64 64s28.654 64 64 64z","M350.831 736c-17.673 0-32 14.327-32 32s14.327 32 32 32h544c17.673 0 32-14.327 32-32s-14.327-32-32-32h-544z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["list-medium"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":380,"id":65,"name":"list-medium","prevSize":32,"code":59728},"setIdx":0,"setId":0,"iconIdx":80},{"icon":{"paths":["M700.147 361.892c4.681-24.975 34.701-34.093 49.126-13.174 31.991 46.404 50.726 102.656 50.726 163.281 0 60.629-18.735 116.881-50.726 163.285-14.426 20.919-44.446 11.802-49.126-13.175l-1.707-9.101c-1.583-8.431 0.384-17.084 4.855-24.401 20.749-33.967 32.704-73.89 32.704-116.608 0-42.714-11.955-82.637-32.704-116.604-4.471-7.319-6.438-15.972-4.855-24.402l1.707-9.102z","M320.705 395.396c-20.749 33.967-32.705 73.891-32.705 116.604 0 42.718 11.956 82.641 32.705 116.608 4.471 7.317 6.436 15.97 4.856 24.401l-1.707 9.101c-4.683 24.977-34.703 34.095-49.127 13.175-31.994-46.404-50.728-102.656-50.728-163.285 0-60.625 18.734-116.878 50.728-163.281 14.423-20.919 44.444-11.801 49.127 13.174l1.707 9.102c1.58 8.43-0.385 17.083-4.856 24.402z","M728.764 209.256l-0.512 2.747c-2.236 11.911 2.534 23.968 11.763 31.822 75.861 64.565 123.985 160.751 123.985 268.175 0 107.426-48.124 203.614-123.985 268.177-9.229 7.855-13.999 19.913-11.763 31.821l0.512 2.748c4.194 22.362 29.692 33.195 47.262 18.743 92.796-76.292 151.974-191.979 151.974-321.489 0-129.507-59.179-245.193-151.974-321.489-17.57-14.448-43.068-3.615-47.262 18.745z","M283.986 243.825c9.229-7.854 13.998-19.911 11.764-31.822l-0.515-2.747c-4.192-22.359-29.69-33.193-47.262-18.745-92.793 76.296-151.973 191.982-151.973 321.489 0 129.51 59.18 245.197 151.973 321.489 17.572 14.451 43.070 3.618 47.262-18.743l0.515-2.748c2.233-11.908-2.536-23.966-11.764-31.821-75.863-64.563-123.986-160.751-123.986-268.177 0-107.424 48.122-203.61 123.986-268.175z","M608 512c0 53.022-42.982 96-96 96s-96-42.978-96-96c0-53.018 42.982-95.999 96-95.999s96 42.981 96 95.999z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["Live"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1},{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":381,"id":64,"name":"Live","prevSize":32,"code":59729},"setIdx":0,"setId":0,"iconIdx":81},{"icon":{"paths":["M719.398 512v54.818c-0.196 76.634-43.682 143.091-107.298 176.209-5.525-25.634-28.326-44.847-55.612-44.847h-72.405c-31.42 0-56.887 25.472-56.887 56.892v41.374c0 31.415 25.468 56.887 56.887 56.887h72.405c28.471 0 52.062-20.919 56.23-48.226 69.171-26.795 123.797-82.773 148.77-152.828 4.719 1.267 9.677 1.941 14.797 1.941h28.446c31.415 0 56.887-25.468 56.887-56.887v-85.333c0-31.42-25.472-56.887-56.887-56.887h-28.446v-28.446c0-141.385-114.615-256-256-256s-256 114.615-256 256v23.275h-28.445c-31.419 0-56.889 25.468-56.889 56.887v103.433c0 31.42 25.47 56.892 56.889 56.892h28.444c31.419 0 56.889-25.472 56.889-56.892v-36.203h0.149c-0.099-2.573-0.148-5.158-0.148-7.757v-139.636c0-109.966 89.145-199.111 199.111-199.111 109.965 0 199.113 89.145 199.113 199.111v85.333z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["livechat"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":382,"id":63,"name":"livechat","prevSize":32,"code":59730},"setIdx":0,"setId":0,"iconIdx":82},{"icon":{"paths":["M357.812 304c0-97.202 78.8-176 175.999-176 97.203 0 176 78.798 176 176v142.477h16c53.022 0 96 42.978 96 96v257.523c0 53.018-42.978 96-96 96h-383.999c-53.019 0-96-42.982-96-96v-257.523c0-53.022 42.981-96 96-96h16v-142.477zM421.812 446.477h223.999v-142.477c0-61.856-50.142-112-112-112-61.854 0-111.999 50.144-111.999 112v142.477zM341.812 510.477c-17.673 0-32 14.327-32 32v257.523c0 17.673 14.327 32 32 32h383.999c17.673 0 32-14.327 32-32v-257.523c0-17.673-14.327-32-32-32h-383.999z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["lock"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":384,"id":61,"name":"lock","prevSize":32,"code":59731},"setIdx":0,"setId":0,"iconIdx":84},{"icon":{"paths":["M721.519 449.771c0-142.502-115.674-258.022-258.364-258.022-142.688 0-258.361 115.52-258.361 258.022s115.672 258.022 258.361 258.022c142.69 0 258.364-115.52 258.364-258.022zM667.174 699.042c-55.573 45.419-126.609 72.666-204.019 72.666-178.035 0-322.361-144.137-322.361-321.937s144.326-321.937 322.361-321.937c178.035 0 322.364 144.137 322.364 321.937 0 77.303-27.285 148.245-72.759 203.742l186.594 186.347c12.587 12.574 12.587 32.956 0 45.53-12.591 12.574-33.003 12.574-45.589 0l-186.59-186.347z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["magnifier"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":385,"id":60,"name":"magnifier","prevSize":32,"code":59732},"setIdx":0,"setId":0,"iconIdx":85},{"icon":{"paths":["M213.812 736h639.999v-448h-639.999v448zM149.812 256c0-17.673 14.327-32 32-32h703.999c17.673 0 32 14.327 32 32v512c0 17.673-14.327 32-32 32h-703.999c-17.673 0-32-14.327-32-32v-512zM327.117 389.082c-14.866-9.557-34.665-5.253-44.222 9.613s-5.253 34.665 9.613 44.223l241.303 155.123 241.306-155.123c14.865-9.557 19.17-29.356 9.613-44.223s-29.355-19.17-44.22-9.613l-206.699 132.876-206.694-132.876z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["mail"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":386,"id":59,"name":"mail","prevSize":32,"code":59733},"setIdx":0,"setId":0,"iconIdx":86},{"icon":{"paths":["M840.533 802.133h-640c-17.067 0-34.133-12.8-34.133-34.133s12.8-34.133 34.133-34.133h640c17.067 0 34.133 12.8 34.133 34.133s-17.067 34.133-34.133 34.133zM840.533 546.133h-640c-17.067 0-34.133-12.8-34.133-34.133s12.8-34.133 34.133-34.133h640c17.067 0 34.133 12.8 34.133 34.133s-17.067 34.133-34.133 34.133zM840.533 290.133h-640c-21.333 0-34.133-17.067-34.133-34.133s12.8-34.133 34.133-34.133h640c17.067 0 34.133 12.8 34.133 34.133s-17.067 34.133-34.133 34.133z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["menu_hamburguer"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":387,"id":58,"name":"menu_hamburguer","prevSize":32,"code":59734},"setIdx":0,"setId":0,"iconIdx":87},{"icon":{"paths":["M576 256c0 35.346-28.655 64-64 64s-64-28.654-64-64c0-35.346 28.655-64 64-64s64 28.654 64 64z","M576 512c0 35.345-28.655 64-64 64s-64-28.655-64-64c0-35.345 28.655-64 64-64s64 28.655 64 64z","M576 768c0 35.345-28.655 64-64 64s-64-28.655-64-64c0-35.345 28.655-64 64-64s64 28.655 64 64z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["menu"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":388,"id":57,"name":"menu","prevSize":32,"code":59735},"setIdx":0,"setId":0,"iconIdx":88},{"icon":{"paths":["M492.89 128c104.256 0 181.252 29.018 237.495 70.652l-44.318 44.317c-45.521-31.22-107.746-53.057-193.178-53.057-129.726 0-207.83 53.576-254.53 118.696-47.831 66.699-64.077 147.668-64.077 201.185v1.404l-0.127 1.399c-7.328 80.926 13.761 143.13 51.784 190.498l-43.879 43.883c-50.179-59.904-78.131-139.046-69.44-238.596 0.276-63.411 19.117-157.053 75.696-235.949 58.132-81.062 154.749-144.433 304.573-144.433zM837.897 332.498l-47.006 47.009c16.503 42.634 20.608 78.524 20.608 89.011v0.179c0 19.516 0 31.791-6.622 56.171-7.091 26.108-21.739 65.647-52.553 137.835-5.7 13.355-2.795 25.98 1.259 34.436 3.836 7.987 9.562 14.4 14.596 19.183 10.227 9.711 24.252 18.837 38.545 26.867 7.885 4.429 18.295 8.994 27.61 13.077l1.843 0.806c10.556 4.634 20.727 9.148 29.615 13.897 3.426 1.835 6.298 3.516 8.674 5.030-5.107 3.23-12.036 6.882-20.945 10.765-22.959 10.005-55.326 19.938-93.888 28.126-77.116 16.375-174.724 24.862-263.339 14.976-43.746-4.881-86.827-14.528-126.534-29.231l-47.543 47.543c52.771 23.019 110.495 36.89 167.267 43.221 96.388 10.752 200.708 1.515 282.91-15.936 41.097-8.725 77.73-19.729 105.681-31.906 13.909-6.063 26.615-12.821 36.855-20.343 9.425-6.925 20.736-17.344 25.609-32.017 7.394-22.268-2.957-40.503-12.813-51.136-9.429-10.167-22.106-17.941-32.956-23.74-11.311-6.046-23.625-11.469-33.89-15.979-11.059-4.851-18.935-8.316-24.055-11.191-9.911-5.568-17.438-10.534-22.507-14.571 27.422-64.806 42.219-104.589 50.048-133.423 8.777-32.303 8.798-50.982 8.798-72.64 0-20.105-7.053-75.5-35.268-136.020zM851.089 153.373c12.497-12.497 32.759-12.497 45.257 0 12.493 12.497 12.493 32.758 0 45.255l-682.669 682.665c-12.497 12.497-32.758 12.497-45.255 0s-12.497-32.755 0-45.252l682.667-682.668z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["message_off"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":389,"id":56,"name":"message_off","prevSize":32,"code":59736},"setIdx":0,"setId":0,"iconIdx":89},{"icon":{"paths":["M236.105 308.609c-47.832 66.699-64.077 147.668-64.077 201.185v1.404l-0.127 1.399c-9.347 103.236 27.547 175.996 86.848 226.377 60.642 51.516 146.603 80.998 235.293 90.893 88.61 9.886 186.219 1.399 263.339-14.976 38.558-8.188 70.929-18.121 93.888-28.126 8.905-3.883 15.838-7.535 20.941-10.765-2.372-1.515-5.248-3.196-8.674-5.030-8.883-4.749-19.055-9.263-29.611-13.897l-1.843-0.806c-9.314-4.083-19.725-8.649-27.614-13.077-14.293-8.030-28.314-17.156-38.545-26.867-5.035-4.783-10.761-11.196-14.592-19.183-4.058-8.457-6.963-21.082-1.259-34.436 30.81-72.188 45.457-111.727 52.548-137.835 6.622-24.38 6.622-36.655 6.622-56.171v-0.179c0-15.514-8.981-86.595-53.777-152.876-43.375-64.175-121.395-125.729-264.828-125.729-129.729 0-207.832 53.576-254.532 118.696zM186.061 272.433c58.132-81.062 154.749-144.433 304.576-144.433 164.894 0 261.589 72.589 315.857 152.878 52.838 78.182 64.414 161.879 64.414 187.641 0 21.658-0.021 40.337-8.794 72.64-7.834 28.834-22.626 68.617-50.048 133.423 5.069 4.036 12.591 9.003 22.507 14.571 5.12 2.876 12.992 6.34 24.051 11.191 10.266 4.51 22.583 9.933 33.894 15.979 10.846 5.798 23.522 13.572 32.951 23.74 9.86 10.633 20.207 28.868 12.817 51.136-4.873 14.673-16.183 25.092-25.613 32.017-10.24 7.522-22.946 14.281-36.855 20.343-27.947 12.177-64.585 23.181-105.681 31.906-82.197 17.451-186.522 26.688-282.906 15.936-96.312-10.743-195.348-43.174-268.316-105.165-74.031-62.891-119.296-154.778-108.551-277.854 0.276-63.411 19.117-157.053 75.696-235.949z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["message"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":390,"id":55,"name":"message","prevSize":32,"code":59737},"setIdx":0,"setId":0,"iconIdx":90},{"icon":{"paths":["M520.286 128c75.546 0 138.859 52.355 155.644 122.761l-59.644 59.644v-22.406c0-53.019-42.982-96-96-96-53.022 0-96.001 42.981-96.001 96v128c0 24.068 8.858 46.067 23.489 62.916l-45.322 45.321c-26.182-28.484-42.167-66.496-42.167-108.237v-128c0-88.366 71.634-160 160.001-160zM569.634 568.243l102.895-102.895c-15.765 48.674-54.221 87.13-102.895 102.895zM296.285 416c0 72.154 23.182 123.102 55.327 159.078l-45.303 45.303c-43.427-47.351-74.024-113.993-74.024-204.382 0-17.673 14.327-32 32-32s32 14.327 32 32zM486.942 650.935l-51.806 51.81c18.56 6.374 36.582 10.807 53.15 13.636v115.618h-160.001c-17.673 0-32 14.327-32 32s14.327 32 32 32h384.001c17.673 0 32-14.327 32-32s-14.327-32-32-32h-160v-115.618c44.638-7.62 99.819-26.897 147.721-64.38 60.702-47.501 108.279-123.29 108.279-236.002 0-17.673-14.327-32-32-32s-32 14.327-32 32c0 92.087-37.76 149.632-83.721 185.6-46.468 36.361-102.737 51.58-140.279 54.327-9.971-0.73-21.265-2.338-33.344-4.992zM833.66 153.373c12.493-12.497 32.755-12.497 45.252 0s12.497 32.758 0 45.255l-672 671.999c-12.497 12.497-32.758 12.497-45.255 0s-12.497-32.755 0-45.252l672.002-672.001z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["mic-off"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":391,"id":54,"name":"mic-off","prevSize":32,"code":59738},"setIdx":0,"setId":0,"iconIdx":91},{"icon":{"paths":["M614.033 288c0-53.019-42.982-96-96-96-53.022 0-96.002 42.981-96.002 96v128c0 53.018 42.98 96 96.002 96 53.018 0 96-42.982 96-96v-128zM358.031 288c0-88.366 71.635-160 160.002-160 88.363 0 160 71.634 160 160v128c0 88.367-71.637 160-160 160-88.367 0-160.002-71.633-160.002-160v-128zM262.031 384c17.673 0 32 14.327 32 32 0 92.087 37.758 149.632 83.72 185.6 46.466 36.361 102.735 51.58 140.282 54.327 37.542-2.748 93.811-17.967 140.279-54.327 45.961-35.968 83.721-93.513 83.721-185.6 0-17.673 14.323-32 32-32 17.673 0 32 14.327 32 32 0 112.713-47.578 188.501-108.284 236.002-47.902 37.483-103.078 56.759-147.716 64.38v115.618h160c17.673 0 32 14.327 32 32s-14.327 32-32 32h-384.002c-17.673 0-32-14.327-32-32s14.327-32 32-32h160.002v-115.618c-44.642-7.62-99.82-26.897-147.722-64.38-60.705-47.501-108.28-123.29-108.28-236.002 0-17.673 14.327-32 32-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["mic"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":392,"id":53,"name":"mic","prevSize":32,"code":59739},"setIdx":0,"setId":0,"iconIdx":92},{"icon":{"paths":["M571.797 242.504c0.188-17.672 14.665-31.845 32.337-31.657s31.846 14.668 31.659 32.34l-1.318 123.488 193.438-193.438c12.497-12.497 32.759-12.497 45.252 0 12.497 12.497 12.497 32.758 0 45.255l-193.438 193.438 123.49-1.319c17.673-0.189 32.149 13.984 32.341 31.658 0.188 17.673-13.986 32.149-31.659 32.337l-201.92 2.159c-8.606 0.090-16.883-3.285-22.967-9.374-6.089-6.084-9.463-14.362-9.374-22.967l2.159-201.921zM496.384 782.148c-0.188 17.673-14.669 31.846-32.341 31.659-17.673-0.192-31.842-14.669-31.654-32.341l1.318-123.49-193.439 193.438c-12.497 12.497-32.758 12.497-45.255 0s-12.497-32.755 0-45.252l193.438-193.438-123.488 1.318c-17.672 0.188-32.151-13.986-32.34-31.659s13.984-32.149 31.656-32.337l201.923-2.159c8.602-0.090 16.883 3.285 22.967 9.37 6.084 6.089 9.463 14.366 9.37 22.972l-2.155 201.92z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["minimize-arrow"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":393,"id":52,"name":"minimize-arrow","prevSize":32,"code":59740},"setIdx":0,"setId":0,"iconIdx":93},{"icon":{"paths":["M265.497 170.662c0-47.128 38.205-85.333 85.333-85.333h384.001c47.13 0 85.333 38.205 85.333 85.333v682.668c0 47.125-38.204 85.333-85.333 85.333h-384.001c-47.128 0-85.333-38.208-85.333-85.333v-682.668zM329.497 170.662v682.668c0 11.78 9.551 21.333 21.333 21.333h384.001c11.78 0 21.333-9.553 21.333-21.333v-682.668c0-11.782-9.553-21.333-21.333-21.333h-96.294c-2.65 24.002-22.997 42.672-47.706 42.672h-96c-24.708 0-45.056-18.67-47.71-42.672h-96.291c-11.782 0-21.333 9.551-21.333 21.333z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["mobile"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":394,"id":51,"name":"mobile","prevSize":32,"code":59741},"setIdx":0,"setId":0,"iconIdx":94},{"icon":{"paths":["M353.234 231.569c-62.881 49.504-135.086 136.548-141.94 266.125-5.762 108.924 37.404 187.187 89.915 241.51 53.259 55.1 115.701 84.924 144.247 94.443 41.865 13.952 114.274 29.534 234.645-15.607 34.859-13.069 73.165-42.095 108.305-78.426 14.272-14.754 27.614-30.293 39.599-45.773-28.774 9.293-61.7 17.758-96.589 23.595-56.192 9.404-119.287 12.322-179.409-0.235-2.492-0.521-4.962-1.033-7.411-1.536-22.195-4.578-42.735-8.815-62.588-17.651-23.091-10.274-43.806-25.89-69.299-51.383-42.097-42.095-89.142-107.221-89.372-213.841-1.569-34.084 4.622-81.88 13.763-129.219 4.625-23.946 10.142-48.465 16.132-72.002zM379.548 138.22c32.8-17.15 63.708 15.843 53.877 45.907-12.236 37.414-24.587 85.511-33.484 131.58-9.024 46.731-13.946 88.633-12.643 114.698l0.040 0.798v0.802c0 84.915 36.173 134.916 70.629 169.374 22.507 22.507 36.834 32.277 50.061 38.165 13.231 5.884 26.833 8.717 51.085 13.764 1.924 0.397 3.917 0.815 5.982 1.246 49.911 10.423 104.529 8.337 155.755-0.239 65.434-10.953 122.385-31.979 152.375-47.386 17.566-9.020 34.991-2.466 44.48 5.965 9.66 8.589 19.371 27.153 8.883 46.955-20.634 38.95-53.645 84.42-92.181 124.262-38.212 39.509-84.318 76.036-131.831 93.854-135.629 50.863-223.219 34.441-277.356 16.397-36.516-12.173-108.392-46.912-170.026-110.677-62.381-64.533-114.684-159.428-107.81-289.37 10.79-203.98 157.584-317.1 232.164-356.095z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["moon"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":395,"id":50,"name":"moon","prevSize":32,"code":59742},"setIdx":0,"setId":0,"iconIdx":95},{"icon":{"paths":["M405.458 769.293c-12.497 12.497-32.758 12.497-45.255 0l-192-192c-12.497-12.497-12.497-32.755 0-45.252l192-192.001c12.497-12.497 32.758-12.497 45.255 0s12.497 32.758 0 45.255l-137.373 137.373h578.745v-192h-192c-17.673 0-32-14.327-32-32s14.327-32 32-32h224c17.673 0 32 14.327 32 32v256c0 17.673-14.327 32-32 32h-610.745l137.373 137.374c12.497 12.497 12.497 32.755 0 45.252z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["multiline"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":396,"id":49,"name":"multiline","prevSize":32,"code":59743},"setIdx":0,"setId":0,"iconIdx":96},{"icon":{"paths":["M211.776 176c-35.346 0-64 28.654-64 64v576c0 35.345 28.654 64 64 64h576c35.345 0 64-28.655 64-64v-576c0-35.346-28.655-64-64-64h-576zM211.776 240h576v576h-576v-576zM702.404 558.153c-0.192 17.673-14.669 31.842-32.341 31.654s-31.846-14.669-31.659-32.341l1.323-123.588-309.344 308.77c-12.508 12.484-32.77 12.467-45.255-0.043-12.485-12.506-12.466-32.768 0.042-45.252l309.199-308.627-123.388 1.318c-17.673 0.189-32.149-13.984-32.337-31.657-0.192-17.672 13.982-32.151 31.654-32.34l201.92-2.156c8.606-0.092 16.887 3.286 22.972 9.371s9.459 14.364 9.37 22.969l-2.155 201.922z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["new_window"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":397,"id":48,"name":"new_window","prevSize":32,"code":59744},"setIdx":0,"setId":0,"iconIdx":97},{"icon":{"paths":["M832.781 183.279c-37.141-37.936-98.074-38.532-135.953-1.331l-348.017 341.786c-12.722 12.497-21.706 28.284-25.943 45.594l-23.65 96.623c-6.931 28.318 16.732 54.771 45.686 51.072l90.574-11.563c20.198-2.577 39.049-11.503 53.833-25.485l360.013-340.471c38.933-36.82 40.119-98.352 2.633-136.64l-19.174-19.584zM741.705 227.52c12.625-12.4 32.934-12.201 45.316 0.444l19.174 19.584c12.497 12.762 12.1 33.273-0.879 45.547l-69.871 66.081-63.364-63.28 69.623-68.376zM626.445 340.713l62.511 62.427-243.648 230.426c-4.928 4.659-11.213 7.633-17.946 8.495l-58.232 7.433 15.908-64.99c1.412-5.769 4.407-11.034 8.648-15.198l232.759-228.593zM202.54 265.251c0-17.65 14.327-31.958 32-31.958h280.958c17.677 0 32-14.308 32-31.958s-14.323-31.958-32-31.958h-280.958c-53.019 0-96 42.924-96 95.874v533.695c0 52.949 42.981 95.872 96 95.872h529.065c53.022 0 96-42.923 96-95.872v-279.044c0-17.651-14.323-31.962-32-31.962-17.673 0-32 14.31-32 31.962v279.044c0 17.651-14.323 31.957-32 31.957h-529.065c-17.673 0-32-14.306-32-31.957v-533.695z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["new-chat"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":398,"id":47,"name":"new-chat","prevSize":32,"code":59745},"setIdx":0,"setId":0,"iconIdx":98},{"icon":{"paths":["M879.049 512c0-194.404-157.598-352-352-352-194.405 0-352 157.596-352 352 0 194.402 157.596 352 352 352 194.402 0 352-157.598 352-352zM943.049 512c0 229.751-186.249 416-416 416s-416-186.249-416-416c0-229.751 186.25-416 416-416s416 186.249 416 416zM415.047 383.995v256.001c0 17.673 14.325 32 32.002 32 17.673 0 32-14.327 32-32v-256.001c0-17.673-14.327-32-32-32-17.677 0-32.002 14.327-32.002 32zM575.044 383.995v256.001c0 17.673 14.327 32 32 32s32-14.327 32-32v-256.001c0-17.673-14.327-32-32-32s-32 14.327-32 32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["pause_outline"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":399,"id":46,"name":"pause_outline","prevSize":32,"code":59746},"setIdx":0,"setId":0,"iconIdx":99},{"icon":{"paths":["M529.301 928c229.751 0 416-186.249 416-416s-186.249-416-416-416c-229.75 0-415.999 186.249-415.999 416s186.249 416 415.999 416zM417.301 383.995c0-17.673 14.328-32 32-32s32 14.327 32 32v256.001c0 17.673-14.327 32-32 32s-32-14.327-32-32v-256.001zM577.301 383.995c0-17.673 14.323-32 32-32 17.673 0 32 14.327 32 32v256.001c0 17.673-14.327 32-32 32-17.677 0-32-14.327-32-32v-256.001z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["pause"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":400,"id":45,"name":"pause","prevSize":32,"code":59747},"setIdx":0,"setId":0,"iconIdx":100},{"icon":{"paths":["M838.165 153.373c12.497-12.497 32.759-12.497 45.257 0s12.497 32.758 0 45.255l-672 671.999c-12.497 12.497-32.758 12.497-45.255 0s-12.497-32.755 0-45.252l671.998-672.001zM588.407 569.067l-44.71 44.71c7.851 5.905 15.851 11.452 23.535 16.013 9.203 5.461 22.839 12.578 36.975 13.222 16.222 0.738 31.445-5.299 42.47-10.974 11.742-6.042 22.788-13.824 31.74-20.945 1.058-0.836 2.138-1.229 2.884-1.34 0.405-0.060 0.614-0.030 0.687-0.013l121.097 59.076c-5.577 29.329-20.378 66.769-42.389 92.621-11.23 13.184-23.198 22.037-35.388 26.317-11.597 4.075-25.404 4.766-42.654-1.673-48.422-18.074-103.407-53.154-151.689-89.263-14.029-10.492-27.298-20.919-39.467-30.844l-44.39 44.39c14.187 11.686 29.837 24.064 46.443 36.48 49.809 37.248 110.451 76.561 167.262 97.762 30.276 11.298 59.149 11.238 85.197 2.086 25.451-8.939 46.093-25.783 62.246-44.757 31.868-37.423 50.637-88.141 57.058-126.246 4.723-27.985-11.772-51.767-33.135-62.191l-122.807-59.908c-24.41-11.908-51.465-6.003-69.837 8.61-7.006 5.572-14.541 10.739-21.444 14.289-5.572 2.867-8.93 3.742-10.308 4.006l-0.094-0.038c-0.994-0.401-3.733-1.515-8.572-4.386-3.277-1.946-6.869-4.301-10.709-7.006zM326.431 589.683l44.39-44.39c-9.92-12.164-20.351-25.438-30.839-39.462-36.109-48.286-71.191-103.267-89.262-151.691-6.437-17.249-5.748-31.055-1.676-42.651 4.283-12.192 13.134-24.16 26.319-35.388 25.85-22.012 63.29-36.814 92.622-42.392l59.075 121.096c0.017 0.076 0.047 0.285-0.013 0.687-0.111 0.75-0.503 1.83-1.341 2.884-7.118 8.951-14.901 20.001-20.943 31.741-5.673 11.025-11.714 26.246-10.976 42.472 0.643 14.135 7.761 27.772 13.222 36.971 4.562 7.689 10.109 15.684 16.014 23.535l44.707-44.71c-2.701-3.836-5.056-7.433-7.002-10.709-2.871-4.838-3.985-7.578-4.386-8.567l-0.038-0.094c0.265-1.382 1.139-4.738 4.006-10.312 3.55-6.9 8.717-14.437 14.289-21.443 14.613-18.374 20.518-45.425 8.61-69.835l-59.91-122.809c-10.421-21.361-34.203-37.856-62.191-33.137-38.103 6.425-88.824 25.194-126.246 57.060-18.972 16.155-35.817 36.795-44.758 62.246-9.15 26.048-9.211 54.92 2.087 85.196 21.202 56.813 60.513 117.455 97.761 167.26 12.417 16.606 24.795 32.256 36.478 46.443z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["phone_disabled"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":401,"id":44,"name":"phone_disabled","prevSize":32,"code":59748},"setIdx":0,"setId":0,"iconIdx":101},{"icon":{"paths":["M835.362 700.309c23.612 8.508 53.538 2.842 70.827-22.601 23.539-34.637 47.279-88.691 51.405-142.588 2.095-27.324-0.725-56.482-12.992-83.234-12.557-27.379-33.963-49.885-64.853-64.647-57.963-27.7-132.228-44.291-196.911-54.061-65.092-9.831-123.46-13.179-151.275-13.179v68.72c24.375 0 79.603 3.066 141.901 12.475 62.703 9.471 129.621 24.95 179.029 48.558 17.596 8.414 27.345 19.686 32.934 31.876 5.875 12.813 8.192 29.009 6.737 48-2.85 37.227-19.674 77.867-37.321 105.020l-133.867-48.243c-0.073-0.043-0.247-0.183-0.503-0.542-0.474-0.67-0.986-1.818-1.148-3.29-1.361-12.497-3.789-27.149-8.021-40.981-3.977-12.988-10.799-29.525-23.403-41.574-10.978-10.492-26.402-15.565-37.295-18.47-12.518-3.345-26.863-5.7-40.922-7.39-28.22-3.396-58.603-4.501-78.127-4.501v68.719c17.762 0 45.538 1.033 70.63 4.053 12.599 1.515 23.701 3.435 32.196 5.705 5.73 1.532 8.589 2.795 9.626 3.255l0.098 0.043c0.832 1.28 2.675 4.57 4.685 11.136 2.492 8.128 4.25 18.010 5.316 27.793 2.795 25.66 18.505 51.298 45.487 61.022l135.765 48.926zM227.756 700.305c-23.615 8.512-53.54 2.842-70.828-22.596-23.537-34.637-47.277-88.691-51.405-142.588-2.093-27.324 0.727-56.482 12.995-83.234 12.556-27.38 33.962-49.886 64.852-64.648 57.966-27.701 132.23-44.292 196.913-54.063 65.089-9.832 123.462-13.176 151.28-13.176v68.72c-24.38 0-79.607 3.062-141.907 12.472-62.705 9.472-129.623 24.951-179.029 48.561-17.599 8.41-27.345 19.686-32.934 31.872-5.877 12.817-8.193 29.013-6.738 48 2.851 37.231 19.671 77.867 37.321 105.024l133.868-48.243c0.070-0.047 0.247-0.188 0.502-0.546 0.475-0.67 0.985-1.813 1.145-3.285 1.362-12.501 3.79-27.149 8.024-40.981 3.976-12.992 10.798-29.53 23.401-41.574 10.981-10.496 26.402-15.569 37.295-18.475 12.521-3.345 26.868-5.7 40.922-7.39 28.224-3.396 58.607-4.497 78.127-4.497v68.719c-17.758 0-45.538 1.028-70.63 4.049-12.599 1.515-23.701 3.439-32.196 5.705-5.728 1.532-8.59 2.795-9.627 3.255l-0.097 0.043c-0.831 1.28-2.675 4.57-4.686 11.136-2.489 8.132-4.249 18.010-5.315 27.797-2.796 25.655-18.505 51.294-45.49 61.018l-135.762 48.926z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["phone-off"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":402,"id":43,"name":"phone-off","prevSize":32,"code":59749},"setIdx":0,"setId":0,"iconIdx":102},{"icon":{"paths":["M421.043 204.615c-10.421-21.361-34.203-37.856-62.191-33.137-38.103 6.425-88.824 25.194-126.246 57.060-18.972 16.155-35.817 36.795-44.758 62.246-9.15 26.048-9.211 54.92 2.087 85.196 21.202 56.813 60.514 117.455 97.761 167.26 37.482 50.125 74.609 91.554 93.327 110.272l44.173-44.173c-16.405-16.405-51.598-55.539-87.472-103.509-36.108-48.286-71.191-103.267-89.262-151.691-6.437-17.249-5.748-31.055-1.675-42.651 4.282-12.192 13.134-24.16 26.319-35.388 25.85-22.012 63.29-36.814 92.622-42.392l59.075 121.096c0.018 0.075 0.047 0.285-0.012 0.687-0.111 0.75-0.504 1.83-1.343 2.884-7.118 8.951-14.9 20.001-20.943 31.741-5.673 11.025-11.714 26.246-10.976 42.472 0.643 14.135 7.761 27.772 13.222 36.971 6.277 10.577 14.417 21.743 22.792 32.29 16.806 21.175 36.54 42.33 49.677 55.467l44.173-44.173c-11.951-11.951-29.978-31.309-44.924-50.133-7.505-9.455-13.739-18.159-17.997-25.335-2.871-4.838-3.985-7.578-4.39-8.567l-0.038-0.094c0.265-1.382 1.139-4.738 4.006-10.312 3.554-6.9 8.721-14.437 14.289-21.443 14.613-18.374 20.523-45.425 8.614-69.835l-59.913-122.809zM829.922 613.5c21.363 10.423 37.858 34.206 33.139 62.191-6.426 38.106-25.195 88.823-57.062 126.246-16.154 18.974-36.791 35.819-62.246 44.757-26.048 9.152-54.921 9.212-85.193-2.086-56.815-21.201-117.457-60.514-167.262-97.762-50.125-37.483-91.554-74.607-110.273-93.325l44.173-44.173c16.406 16.405 55.54 51.597 103.51 87.471 48.286 36.109 103.266 71.189 151.693 89.263 17.246 6.434 31.053 5.747 42.65 1.673 12.19-4.279 24.158-13.133 35.388-26.317 22.012-25.852 36.813-63.292 42.394-92.621l-121.097-59.076c-0.077-0.017-0.286-0.047-0.687 0.013-0.751 0.111-1.83 0.503-2.884 1.34-8.951 7.121-20.002 14.903-31.744 20.945-11.025 5.675-26.244 11.712-42.47 10.974-14.135-0.644-27.772-7.761-36.971-13.222-10.577-6.276-21.743-14.417-32.29-22.788-21.171-16.811-42.33-36.544-55.467-49.681l44.173-44.173c11.951 11.951 31.309 29.982 50.133 44.928 9.455 7.501 18.159 13.734 25.335 17.997 4.838 2.871 7.578 3.985 8.567 4.386l0.094 0.038c1.382-0.265 4.736-1.139 10.313-4.006 6.899-3.55 14.434-8.717 21.444-14.289 18.372-14.613 45.423-20.518 69.833-8.61l122.807 59.908z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["phone"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":403,"id":42,"name":"phone","prevSize":32,"code":59750},"setIdx":0,"setId":0,"iconIdx":103},{"icon":{"paths":["M550.259 128.018c-72.38-1.375-144.906 25.78-199.307 80.524-54.654 54.999-89.302 136.056-89.301 239.466 0 80.23 44.5 174.869 97.546 252.804 53.065 77.965 120.829 148.16 176.142 175.821l15.194 7.603 14.805-8.333c217.161-122.15 272.311-333.879 272.311-427.895 0-101.732-27.921-181.775-80.179-236.931-52.343-55.247-125.295-81.503-207.211-83.060zM325.651 448.009c-0-88.591 29.353-152.747 70.698-194.353 41.598-41.862 97.069-62.705 152.694-61.648 68.992 1.311 124.041 23.055 161.967 63.089 38.020 40.126 62.639 102.647 62.639 192.913 0 74.551-44.689 253.679-224.175 363.034-39.684-25.613-92.186-79.855-137.369-146.24-50.954-74.863-86.454-156.22-86.454-216.794zM581.649 416c0-17.673-14.323-32-32-32-17.673 0-32 14.327-32 32s14.327 32 32 32c17.677 0 32-14.327 32-32zM645.649 416c0 53.018-42.978 96-96 96-53.018 0-96-42.982-96-96 0-53.019 42.982-96 96-96 53.022 0 96 42.981 96 96z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["pin-map"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":404,"id":41,"name":"pin-map","prevSize":32,"code":59751},"setIdx":0,"setId":0,"iconIdx":104},{"icon":{"paths":["M431.689 199.401c17.54-17.543 45.986-17.543 63.526 0 17.545 17.543 17.545 45.987 0 63.53l-43.657 43.659 177.826 177.827 60.343-60.338c24.99-24.994 65.515-24.994 90.509 0l45.252 45.256-331.866 331.87-45.257-45.257c-24.994-24.994-24.994-65.515 0-90.509l60.339-60.339-177.828-177.83-43.66 43.661c-17.543 17.545-45.987 17.545-63.53 0s-17.544-45.986 0-63.529l208.001-207.999zM178.433 362.145c-42.537 42.537-42.537 111.502 0 154.041 42.001 42.001 109.771 42.53 152.421 1.583l87.335 87.339-15.077 15.074c-49.987 49.988-49.987 131.034 0 181.022l67.881 67.878c12.497 12.497 32.759 12.497 45.257 0l167.932-167.932 88.017 92.002c12.215 12.77 32.474 13.222 45.244 1.003 12.77-12.215 13.218-32.474 1.003-45.244l-88.994-93.026 163.921-163.925c12.497-12.497 12.497-32.759 0-45.257l-67.883-67.88c-49.984-49.987-131.029-49.987-181.018 0l-15.906 15.907-87.326-87.322c41.766-42.596 41.51-110.984-0.768-153.262-42.539-42.537-111.501-42.537-154.039 0l-207.999 207.999z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["pin"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":405,"id":40,"name":"pin","prevSize":32,"code":59752},"setIdx":0,"setId":0,"iconIdx":105},{"icon":{"paths":["M520.286 928.004c229.751 0 416-186.249 416-416 0-229.749-186.249-415.999-416-415.999s-416.001 186.25-416.001 415.999c0 229.751 186.25 416 416.001 416zM460.134 357.193l195.255 136.768c14.204 9.95 18.496 30.874 9.579 46.729-2.432 4.322-5.705 7.979-9.579 10.692l-195.255 136.768c-14.208 9.95-32.956 5.163-41.87-10.692-3.036-5.397-4.646-11.644-4.646-18.018v-273.536c0-18.72 13.599-33.897 30.371-33.897 5.709 0 11.307 1.798 16.145 5.186z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["play"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":406,"id":39,"name":"play","prevSize":32,"code":59753},"setIdx":0,"setId":0,"iconIdx":106},{"icon":{"paths":["M547.776 208c0-17.673-14.323-32-32-32-17.673 0-32 14.327-32 32v271.996h-271.997c-17.673 0-32 14.327-32 32s14.327 32 32 32h271.997v272.004c0 17.673 14.327 32 32 32 17.677 0 32-14.327 32-32v-272.004h272.004c17.673 0 32-14.327 32-32-0.004-17.673-14.327-32-32.004-32h-272v-271.996z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["plus"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":407,"id":38,"name":"plus","prevSize":32,"code":59754},"setIdx":0,"setId":0,"iconIdx":107},{"icon":{"paths":["M476.924 704.371c0-33.643 26.278-47.676 72.73-47.676 46.447 0 72.725 14.033 72.725 47.676 0 32.96-13.188 111.070-23.91 149.764-4.966 17.805-22.080 25.169-48.815 25.169-26.739 0-43.853-7.364-48.815-25.173-10.714-38.665-23.915-116.689-23.915-149.76zM654.43 870.374l0.026-0.094c6.174-22.289 12.565-53.862 17.382-83.447 4.689-28.791 8.725-60.71 8.725-82.462 0-35.891-15.817-67.802-46.797-87.113-26.035-16.226-57.156-19.925-84.113-19.925-26.961 0-58.078 3.699-84.113 19.925-30.985 19.311-46.797 51.221-46.797 87.113 0 21.807 4.036 53.73 8.726 82.517 4.817 29.577 11.209 61.12 17.382 83.392l0.021 0.085c7.403 26.556 24.981 45.666 46.874 56.469 19.469 9.609 40.422 11.831 57.907 11.831 17.481 0 38.434-2.223 57.903-11.831 21.888-10.799 39.471-29.905 46.874-56.461zM497.289 460.8c0-28.275 23.441-51.2 52.365-51.2 28.919 0 52.361 22.925 52.361 51.2s-23.441 51.2-52.361 51.2c-28.924 0-52.365-22.925-52.365-51.2zM549.653 341.333c-67.482 0-122.185 53.487-122.185 119.467s54.703 119.467 122.185 119.467c67.477 0 122.18-53.487 122.18-119.467s-54.703-119.467-122.18-119.467zM715.456 537.254c-6.665 13.79-3.887 31.108 6.272 42.573 14.089 15.893 39.851 17.937 50.206-0.606 19.644-35.17 30.805-75.52 30.805-118.421 0-136.672-113.31-247.467-253.090-247.467-139.777 0-253.090 110.795-253.090 247.467 0 42.901 11.164 83.251 30.806 118.421 10.354 18.543 36.119 16.499 50.205 0.606 10.16-11.465 12.939-28.783 6.275-42.573-11.204-23.189-17.469-49.105-17.469-76.454 0-98.97 82.054-179.2 183.272-179.2s183.275 80.23 183.275 179.2c0 27.349-6.268 53.265-17.468 76.454zM767.812 699.793c-0.307-10.658 3.541-21.069 10.927-28.762 52.77-54.955 85.094-128.9 85.094-210.231 0-169.662-140.663-307.2-314.185-307.2-173.516 0-314.18 137.538-314.18 307.2 0 81.331 32.323 155.277 85.093 210.231 7.386 7.693 11.234 18.103 10.928 28.762-0.833 29.018-31.273 47.915-52.122 27.716-70.223-68.041-113.718-162.406-113.718-266.709 0-207.365 171.922-375.467 383.998-375.467 212.079 0 384 168.102 384 375.467 0 104.303-43.494 198.673-113.719 266.709-20.847 20.203-51.285 1.306-52.117-27.716z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["podcast"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":408,"id":37,"name":"podcast","prevSize":32,"code":59755},"setIdx":0,"setId":0,"iconIdx":108},{"icon":{"paths":["M395.145 448c0-17.673 14.327-32 31.999-32h213.333c17.673 0 32 14.327 32 32s-14.327 32-32 32h-213.333c-17.672 0-31.999-14.327-31.999-32z","M427.145 544c-17.672 0-31.999 14.327-31.999 32s14.327 32 31.999 32h213.333c17.673 0 32-14.327 32-32s-14.327-32-32-32h-213.333z","M277.812 128c-17.673 0-32 14.327-32 32v704c0 17.673 14.327 32 32 32h511.999c17.673 0 32-14.327 32-32v-501.745c0-6.67-2.082-13.172-5.961-18.6l-144.465-202.255c-6.007-8.41-15.706-13.4-26.039-13.4h-367.534zM757.811 372.51v459.49h-447.999v-640h319.064l128.934 180.51z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["post"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":409,"id":36,"name":"post","prevSize":32,"code":59756},"setIdx":0,"setId":0,"iconIdx":109},{"icon":{"paths":["M236.518 636.689c-14.92-9.472-34.694-5.056-44.167 9.86-9.473 14.921-5.057 34.697 9.863 44.169l298.667 189.632c10.466 6.643 23.834 6.643 34.304 0l298.667-189.632c14.921-9.472 19.337-29.248 9.865-44.169-9.476-14.916-29.248-19.332-44.169-9.86l-281.515 178.739-281.515-178.739zM192.351 494.848c9.473-14.921 29.247-19.337 44.167-9.865l281.515 178.743 281.515-178.743c14.921-9.472 34.692-5.056 44.169 9.865 9.472 14.921 5.056 34.692-9.865 44.169l-298.667 189.628c-10.47 6.647-23.838 6.647-34.304 0l-298.668-189.628c-14.92-9.476-19.335-29.248-9.862-44.169zM535.185 143.657l298.667 189.63c9.246 5.871 14.848 16.062 14.848 27.014s-5.602 21.144-14.848 27.015l-298.667 189.631c-10.47 6.647-23.838 6.647-34.304 0l-298.667-189.631c-9.246-5.871-14.848-16.062-14.848-27.015s5.602-21.144 14.848-27.014l298.667-189.63c10.466-6.647 23.834-6.647 34.304 0zM279.066 360.302l238.967 151.724 238.967-151.724-238.967-151.725-238.967 151.725z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["queue"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":410,"id":35,"name":"queue","prevSize":32,"code":59757},"setIdx":0,"setId":0,"iconIdx":110},{"icon":{"paths":["M197.594 224c-11.706 0-22.477 6.391-28.087 16.666s-5.161 22.792 1.169 32.638l112.304 174.696h-69.387c-17.673 0-32 14.327-32 32v288c0 17.673 14.327 32 32 32h256c17.673 0 32-14.327 32-32v-288c0-6.135-1.762-12.143-5.082-17.306l-144-223.999c-5.888-9.159-16.029-14.696-26.918-14.696h-128zM368.512 462.694l-112.305-174.694h51.916l129.47 201.399v246.601h-192v-224h96c11.706 0 22.478-6.391 28.087-16.666s5.161-22.793-1.169-32.64zM613.594 224c-11.708 0-22.477 6.391-28.087 16.666-5.606 10.274-5.158 22.792 1.169 32.638l112.307 174.696h-69.389c-17.673 0-32 14.327-32 32v288c0 17.673 14.327 32 32 32h256c17.673 0 32-14.327 32-32v-288c0-6.135-1.762-12.143-5.082-17.306l-144-223.999c-5.888-9.159-16.030-14.696-26.918-14.696h-128zM784.512 462.694l-112.303-174.694h51.913l129.472 201.399v246.601h-192v-224h96c11.708 0 22.477-6.391 28.087-16.666s5.158-22.793-1.169-32.64z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["quote"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":411,"id":34,"name":"quote","prevSize":32,"code":59758},"setIdx":0,"setId":0,"iconIdx":111},{"icon":{"paths":["M865.084 512c0-176.731-143.27-320-320-320-176.732 0-320 143.269-320 320 0 176.73 143.269 320 320 320 176.73 0 320-143.27 320-320zM929.084 512c0 212.079-171.921 384-384 384-212.078 0-384-171.921-384-384 0-212.077 171.923-384 384-384 212.079 0 384 171.923 384 384zM545.084 704c-106.039 0-192-85.961-192-192s85.961-192 192-192c106.039 0 192 85.961 192 192s-85.961 192-192 192z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["rec"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":412,"id":33,"name":"rec","prevSize":32,"code":59759},"setIdx":0,"setId":0,"iconIdx":112},{"icon":{"paths":["M922.321 512h-63.983c0-175.415-145.754-320-328.521-320-115.27 0-215.817 57.513-274.36 144h110.768c17.673 0 32 14.327 32 32s-14.327 32-32 32h-179.904c-17.673 0-32-14.327-32-32v-192c0-17.673 14.327-32 32-32s32 14.327 32 32v102.32c71.751-91.401 184.591-150.32 311.496-150.32 216.781 0 392.503 171.923 392.503 384 0 1.114 0.009 2.227 0 3.337v-3.337z","M154.319 512h63.986c0 175.415 145.752 320 328.519 320 115.268 0 215.817-57.515 274.359-144h-110.767c-17.673 0-32-14.327-32-32s14.327-32 32-32h179.904c17.673 0 32 14.327 32 32v192c0 17.673-14.327 32-32 32s-32-14.327-32-32v-102.319c-71.753 91.401-184.593 150.319-311.497 150.319-216.783 0-392.505-171.921-392.505-384 0-1.084-0.009-2.163 0-3.247v3.247z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["refresh"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1},{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":413,"id":32,"name":"refresh","prevSize":32,"code":59760},"setIdx":0,"setId":0,"iconIdx":113},{"icon":{"paths":["M922.325 238.961l-297.476 637.446c-16.853 36.113-69.619 31.458-79.889-7.049l-66.001-247.501 151.249-189.056-219.993 109.995-226.834-113.417c-35.43-17.715-29.696-69.947 8.733-79.555l681.201-170.3c34.837-8.71 64.196 26.892 49.011 59.436z"],"attrs":[{"fill":"rgb(29, 116, 245)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["send-active"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":3}]}},"attrs":[{"fill":"rgb(29, 116, 245)"}],"properties":{"order":414,"id":31,"name":"send-active","prevSize":32,"code":59761},"setIdx":0,"setId":0,"iconIdx":114},{"icon":{"paths":["M906.598 192.976c7.851 9.521 9.527 22.708 4.309 33.891l-298.667 640c-5.692 12.194-18.406 19.529-31.812 18.342-13.406-1.182-24.636-10.628-28.105-23.629l-81.621-306.074-285.77-142.884c-11.978-5.989-18.959-18.802-17.498-32.113s11.056-24.305 24.048-27.553l682.668-170.667c11.972-2.993 24.597 1.165 32.448 10.686zM534.396 545.967l57.084 214.054 233.028-499.351-533.582 133.396 203.606 101.802 69.513-52.134c14.135-10.603 34.193-7.735 44.8 6.4 10.603 14.14 7.735 34.197-6.4 44.8l-68.049 51.034z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["send"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":415,"id":30,"name":"send","prevSize":32,"code":59762},"setIdx":0,"setId":0,"iconIdx":115},{"icon":{"paths":["M732.22 300.76c12.497-12.854 12.497-33.694 0-46.548l-160-164.571c-12.497-12.854-32.755-12.854-45.252 0l-160.001 164.571c-12.497 12.854-12.497 33.694 0 46.548s32.758 12.854 45.255 0l105.373-108.383v430.711c0 18.176 14.327 32.913 32 32.913s32-14.737 32-32.913v-430.711l105.374 108.384c12.497 12.854 32.755 12.854 45.252 0z","M229.594 384h160v64h-128v416h576v-416h-128v-64h160c17.673 0 32 14.327 32 32v480c0 17.673-14.327 32-32 32h-640c-17.673 0-32-14.327-32-32v-480c0-17.673 14.327-32 32-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["share"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1},{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":416,"id":29,"name":"share","prevSize":32,"code":59763},"setIdx":0,"setId":0,"iconIdx":116},{"icon":{"paths":["M697.165 405.072c11.639-13.3 10.291-33.517-3.008-45.155-13.303-11.638-33.519-10.29-45.154 3.011l-125.252 143.146-39.919-45.623c-11.635-13.299-31.855-14.647-45.154-3.008-13.3 11.635-14.647 31.855-3.008 45.154l64 73.143c6.076 6.942 14.852 10.927 24.081 10.927s18.005-3.985 24.081-10.927l149.333-170.668z","M575.074 143.050c-12.855-3.633-26.449-3.753-39.364-0.345l-264.723 69.849c-29.793 7.861-52.548 33.743-54.753 65.633-23.59 341.205 187.75 520.29 276.51 579.793 33.135 22.212 75.362 22.144 108.416-0.26 88.218-59.789 297.118-239.070 272.61-580.212-2.249-31.321-24.337-56.895-53.504-65.14l-245.193-69.318zM552.038 204.588c1.847-0.487 3.789-0.47 5.623 0.049l245.197 69.318c4.292 1.214 6.839 4.781 7.078 8.139 22.148 308.363-165.303 468.849-244.685 522.652-11.439 7.753-25.365 7.791-36.873 0.077-80.081-53.687-269.603-214.054-248.298-522.22 0.235-3.389 2.833-7.003 7.234-8.165l264.723-69.849z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["shield-check"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1},{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":417,"id":28,"name":"shield-check","prevSize":32,"code":59764},"setIdx":0,"setId":0,"iconIdx":117},{"icon":{"paths":["M548.638 142.705c12.919-3.408 26.509-3.288 39.364 0.345l245.197 69.318c29.163 8.245 51.251 33.818 53.504 65.14 24.503 341.142-184.397 520.423-272.614 580.212-33.050 22.404-75.281 22.473-108.416 0.26-88.759-59.503-300.099-238.588-276.509-579.793 2.205-31.89 24.96-57.772 54.753-65.633l264.722-69.849zM570.59 204.637c-1.835-0.519-3.776-0.536-5.623-0.049l-264.722 69.849c-4.4 1.161-6.999 4.776-7.233 8.165-21.305 308.166 168.216 468.533 248.301 522.22 11.507 7.714 25.434 7.676 36.873-0.077 79.377-53.803 266.833-214.289 244.681-522.652-0.239-3.358-2.786-6.925-7.078-8.139l-245.197-69.318z","M526.012 337.336c-19.759 4.672-47.249 12.307-81.152 24.553 20.813 108.772 53.222 187.014 81.152 238.833v-263.385zM528.205 271.316c33.771-6.898 61.807 19.742 61.807 51.124v360.965c0 17.024-10.334 31.748-25.643 37.521-15.671 5.909-33.779 1.331-44.86-12.676-32.657-41.267-106.324-152.947-141.192-354.563-3.241-18.744 7.065-37.694 25.329-44.726 56.185-21.63 99.095-32.442 124.559-37.644z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["shield"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1},{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":418,"id":27,"name":"shield","prevSize":32,"code":59765},"setIdx":0,"setId":0,"iconIdx":118},{"icon":{"paths":["M802.705 213.333c-17.673 0-32 14.327-32 32v533.333c0 17.673 14.327 32 32 32s32-14.327 32-32v-533.333c0-17.673-14.327-32-32-32z","M624.939 341.333c-17.677 0-32 14.327-32 32v405.333c0 17.673 14.323 32 32 32 17.673 0 32-14.327 32-32v-405.333c0-17.673-14.327-32-32-32z","M447.168 810.667c-17.673 0-31.999-14.327-31.999-32v-277.333c0-17.673 14.326-32 31.999-32s32 14.327 32 32v277.333c0 17.673-14.327 32-32 32z","M269.4 597.333c-17.673 0-32 14.327-32 32v149.333c0 17.673 14.327 32 32 32s32-14.327 32-32v-149.333c0-17.673-14.327-32-32-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["signal"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":419,"id":26,"name":"signal","prevSize":32,"code":59766},"setIdx":0,"setId":0,"iconIdx":119},{"icon":{"paths":["M658.731 204.798c16.495 6.344 24.725 24.859 18.381 41.354l-213.333 554.667c-6.345 16.495-24.862 24.725-41.356 18.381-16.495-6.345-24.724-24.862-18.38-41.357l213.335-554.666c6.345-16.495 24.858-24.724 41.353-18.38zM349.871 361.371c12.497 12.497 12.497 32.758 0 45.255l-105.373 105.374 105.373 105.37c12.497 12.497 12.497 32.759 0 45.257s-32.758 12.497-45.255 0l-128-128c-12.497-12.497-12.497-32.759 0-45.257l128-127.999c12.497-12.497 32.758-12.497 45.255 0zM731.281 361.371c12.497-12.497 32.759-12.497 45.257 0l128 127.999c12.497 12.497 12.497 32.759 0 45.257l-128 128c-12.497 12.497-32.759 12.497-45.257 0s-12.497-32.759 0-45.257l105.374-105.37-105.374-105.374c-12.497-12.497-12.497-32.758 0-45.255z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["snippet"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":420,"id":25,"name":"snippet","prevSize":32,"code":59767},"setIdx":0,"setId":0,"iconIdx":120},{"icon":{"paths":["M312.019 192c13.364 0 25.321 8.305 29.987 20.829l96.002 257.699c6.17 16.559-2.257 34.987-18.817 41.156-16.561 6.17-34.988-2.253-41.158-18.816l-20.476-54.963h-91.075l-20.476 54.963c-6.17 16.563-24.596 24.986-41.158 18.816s-24.986-24.597-18.816-41.156l96-257.699c4.666-12.524 16.623-20.829 29.987-20.829zM333.714 373.904l-21.695-58.238-21.696 58.238h43.391z","M544.789 626.436c-12.156 12.826-11.61 33.079 1.22 45.235l160 151.586c12.343 11.695 31.676 11.695 44.019 0l160-151.586c12.83-12.156 13.376-32.41 1.22-45.235-12.156-12.83-32.41-13.38-45.239-1.225l-105.988 100.42v-501.632c0-17.673-14.327-32-32-32-17.677 0-32 14.327-32 32v501.632l-105.993-100.42c-12.83-12.156-33.084-11.605-45.239 1.225z","M216.019 570.944c-17.673 0-32 14.327-32 32 0 17.677 14.327 32 32 32h116.145l-139.065 142.733c-8.979 9.216-11.565 22.916-6.564 34.769 5.001 11.857 16.617 19.563 29.484 19.563h192c17.673 0 32.002-14.327 32.002-32s-14.329-32-32.002-32h-116.145l139.063-142.733c8.981-9.216 11.567-22.912 6.566-34.769-5.001-11.853-16.618-19.563-29.485-19.563h-192z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["sort az"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":421,"id":24,"name":"sort-az","prevSize":32,"code":59768},"setIdx":0,"setId":0,"iconIdx":121},{"icon":{"paths":["M930.837 666.347c12.591-12.237 12.86-32.35 0.606-44.924-12.254-12.57-32.393-12.843-44.979-0.602l-105.975 103.019v-500.14c0-17.545-14.242-31.768-31.808-31.768-17.57 0-31.808 14.223-31.808 31.768v500.14l-105.975-103.019c-12.587-12.241-32.725-11.968-44.979 0.602-12.254 12.574-11.985 32.687 0.606 44.924l159.97 155.511c12.348 12.006 32.026 12.006 44.373 0l159.97-155.511zM572.715 333.224c17.566 0 31.808-14.223 31.808-31.767s-14.242-31.767-31.808-31.767h-431.921c-17.568 0-31.81 14.223-31.81 31.767s14.242 31.767 31.81 31.767h431.921zM476.732 535.39c17.566 0 31.808-14.221 31.808-31.765 0-17.549-14.242-31.77-31.808-31.77h-335.938c-17.568 0-31.81 14.221-31.81 31.77 0 17.545 14.242 31.765 31.81 31.765h335.938zM396.746 722.005c17.568 0 31.811-14.225 31.811-31.77s-14.243-31.765-31.811-31.765h-255.952c-17.568 0-31.81 14.221-31.81 31.765s14.242 31.77 31.81 31.77h255.952z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["sort-1"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":422,"id":23,"name":"sort-1","prevSize":32,"code":59769},"setIdx":0,"setId":0,"iconIdx":122},{"icon":{"paths":["M724.019 626.56c12.676-12.314 32.934-12.023 45.252 0.649 12.318 12.676 12.023 32.934-0.649 45.252l-208 202.121c-12.42 12.066-32.183 12.066-44.604 0l-207.998-202.121c-12.675-12.318-12.965-32.576-0.649-45.252 12.317-12.672 32.576-12.962 45.25-0.649l185.699 180.45 185.698-180.45zM724.019 416.798c12.676 12.317 32.934 12.027 45.252-0.649 12.318-12.675 12.023-32.934-0.649-45.25l-208-202.119c-12.42-12.067-32.183-12.067-44.604 0l-207.998 202.119c-12.675 12.316-12.965 32.576-0.649 45.25 12.317 12.676 32.576 12.966 45.25 0.649l185.699-180.449 185.698 180.449z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["sort"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":423,"id":22,"name":"sort","prevSize":32,"code":59770},"setIdx":0,"setId":0,"iconIdx":123},{"icon":{"paths":["M207.049 405.333h213.333v-213.333h-213.333v213.333zM143.049 170.667c0-23.564 19.103-42.667 42.667-42.667h255.999c23.565 0 42.667 19.103 42.667 42.667v256c0 23.565-19.102 42.667-42.667 42.667h-255.999c-23.564 0-42.667-19.102-42.667-42.667v-256zM633.715 405.333h213.333v-213.333h-213.333v213.333zM569.715 170.667c0-23.564 19.102-42.667 42.667-42.667h256c23.565 0 42.667 19.103 42.667 42.667v256c0 23.565-19.102 42.667-42.667 42.667h-256c-23.565 0-42.667-19.102-42.667-42.667v-256zM633.715 618.667h213.333v213.333h-213.333v-213.333zM612.382 554.667c-23.565 0-42.667 19.102-42.667 42.667v256c0 23.565 19.102 42.667 42.667 42.667h256c23.565 0 42.667-19.102 42.667-42.667v-256c0-23.565-19.102-42.667-42.667-42.667h-256zM207.049 832h213.333v-213.333h-213.333v213.333zM143.049 597.333c0-23.565 19.103-42.667 42.667-42.667h255.999c23.565 0 42.667 19.102 42.667 42.667v256c0 23.565-19.102 42.667-42.667 42.667h-255.999c-23.564 0-42.667-19.102-42.667-42.667v-256z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["squares"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":424,"id":21,"name":"squares","prevSize":32,"code":59771},"setIdx":0,"setId":0,"iconIdx":124},{"icon":{"paths":["M618.005 170.244c-20.868-57.726-103.155-55.816-121.323 2.816l-58.974 190.35h-221.514c-58.947 0-86.549 72.943-42.37 111.965l157.591 139.204-53.209 216.93c-14.17 57.771 51.25 101.935 99.535 67.2l177.74-127.881 177.741 127.881c48.286 34.735 113.702-9.429 99.533-67.2l-53.385-217.651 147.891-139.968c42.031-39.778 13.875-110.481-43.994-110.481h-195.439l-69.824-193.165z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["star-filled"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":425,"id":20,"name":"star-filled","prevSize":32,"code":59772},"setIdx":0,"setId":0,"iconIdx":125},{"icon":{"paths":["M494.43 172.834c18.163-58.554 100.454-60.462 121.323-2.812l69.82 192.91h195.443c57.869 0 86.025 70.608 43.989 110.335l-147.887 139.785 53.385 217.361c14.17 57.694-51.251 101.803-99.533 67.11l-177.741-127.706-177.742 127.706c-48.284 34.692-113.705-9.417-99.535-67.11l53.209-216.64-157.591-139.021c-44.179-38.976-16.577-111.82 42.37-111.82h221.511l58.978-190.098zM625.387 384.66l-69.824-192.91-58.978 190.098c-8.299 26.758-33.079 44.998-61.133 44.998h-221.511l157.591 139.025c17.834 15.731 25.456 40.047 19.787 63.125l-53.209 216.644 177.743-127.706c22.327-16.047 52.425-16.047 74.752 0l177.741 127.706-53.385-217.361c-5.483-22.319 1.451-45.854 18.163-61.649l147.891-139.785h-195.443c-26.957 0-51.025-16.868-60.186-42.186z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["star"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":426,"id":19,"name":"star","prevSize":32,"code":59773},"setIdx":0,"setId":0,"iconIdx":126},{"icon":{"paths":["M556.403 548.215h-255.503c-20.173 0-36.527-16.354-36.527-36.527s16.354-36.527 36.527-36.527h102.99c-21.547-22.75-32.32-50.118-32.32-82.102 0-39.587 15.766-72.27 47.297-98.048 31.76-26.008 72.959-39.012 123.596-39.012 34.522 0 65.25 6.675 92.177 20.024 27.162 13.349 48.102 31.762 62.835 55.238 8.849 13.888 15.083 28.54 18.697 43.958 4.198 17.914-11.174 33.030-29.572 33.030s-32.499-15.279-37.828-32.89c-4.617-15.263-12.779-28.121-24.486-38.574-19.332-17.492-46.609-26.238-81.822-26.238-32.683 0-58.231 7.25-76.642 21.75-18.185 14.27-27.277 34.179-27.277 59.726 0 20.484 8.631 37.86 25.894 52.132 13.764 11.046 35.012 21.385 63.744 31.006h247.556c20.173 0 36.527 16.354 36.527 36.527s-16.354 36.527-36.527 36.527h-90.027c7.138 7.215 13.133 14.878 17.975 22.989 11.507 18.871 17.263 41.079 17.263 66.628 0 40.738-15.881 73.421-47.642 98.048-31.761 24.397-74.227 36.595-127.394 36.595-34.522 0-66.748-6.558-96.666-19.678-29.922-13.35-53.053-31.531-69.394-54.549-9.777-13.965-16.588-29.077-20.432-45.338-4.233-17.903 11.182-33.028 29.581-33.028s32.466 15.364 38.447 32.764c5.316 15.475 14.771 28.604 28.356 39.39 22.558 17.493 52.591 26.236 90.108 26.236 34.982 0 61.798-7.134 80.439-21.402 18.645-14.272 27.964-33.719 27.964-58.347s-8.627-43.614-25.89-56.964c-14.332-11.273-38.34-22.387-72.026-33.344z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["strike"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":427,"id":18,"name":"strike","prevSize":32,"code":59774},"setIdx":0,"setId":0,"iconIdx":127},{"icon":{"paths":["M513.084 117.333c0-17.673 14.327-32 32-32s32 14.327 32 32v106.667c0 17.673-14.327 32-32 32s-32-14.327-32-32v-106.667zM803.123 214.629c12.497-12.497 32.759-12.497 45.257 0s12.497 32.758 0 45.255l-75.413 75.412c-12.497 12.497-32.759 12.497-45.257 0s-12.497-32.758 0-45.255l75.413-75.412zM368.46 694.63c-12.497-12.497-32.758-12.497-45.255 0l-75.495 75.494c-12.497 12.497-12.497 32.755 0 45.252s32.758 12.497 45.255 0l75.495-75.494c12.497-12.497 12.497-32.755 0-45.252zM513.084 800c0-17.673 14.327-32 32-32s32 14.327 32 32v106.667c0 17.673-14.327 32-32 32s-32-14.327-32-32v-106.667zM245.084 211.999c-12.497 12.497-12.497 32.758 0 45.255l75.349 75.349c12.497 12.497 32.758 12.497 45.255 0s12.497-32.758 0-45.255l-75.349-75.349c-12.497-12.497-32.758-12.497-45.255 0zM727.71 739.883c-12.497-12.497-12.497-32.759 0-45.257s32.759-12.497 45.257 0l75.328 75.328c12.497 12.497 12.497 32.759 0 45.257s-32.759 12.497-45.257 0l-75.328-75.328zM119.483 512c0 17.673 14.327 32 32 32h106.666c17.673 0 32-14.327 32-32s-14.327-32-32-32h-106.667c-17.673 0-32 14.327-32 32zM833.084 544c-17.673 0-32-14.327-32-32s14.327-32 32-32h106.667c17.673 0 32 14.327 32 32s-14.327 32-32 32h-106.667zM699.9 512c0-85.505-69.316-154.82-154.82-154.82s-154.818 69.315-154.818 154.82c0 85.504 69.314 154.816 154.818 154.816s154.82-69.312 154.82-154.816zM758.413 512c0 117.82-95.509 213.333-213.333 213.333-117.82 0-213.332-95.514-213.332-213.333 0-117.822 95.512-213.335 213.332-213.335 117.824 0 213.333 95.513 213.333 213.335z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["Sun"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":428,"id":17,"name":"Sun","prevSize":32,"code":59775},"setIdx":0,"setId":0,"iconIdx":128},{"icon":{"paths":["M376.285 412.435c-53.592 0-96-42.819-96-94.367s42.408-94.366 96-94.366c53.594 0 96.001 42.819 96.001 94.366s-42.406 94.367-96.001 94.367zM376.285 476.352c88.368 0 160.001-70.867 160.001-158.284s-71.633-158.282-160.001-158.282c-88.365 0-160 70.865-160 158.282s71.635 158.284 160 158.284zM721.886 396.606c-35.921 0-64-28.646-64-62.71s28.079-62.71 64-62.71c35.917 0 64 28.646 64 62.71s-28.083 62.71-64 62.71zM721.886 460.523c70.69 0 128-56.693 128-126.626s-57.31-126.626-128-126.626c-70.694 0-128 56.692-128 126.626s57.306 126.626 128 126.626zM205.744 526.571c27.344-8.695 56.671-9.229 84.32-1.536l48.489 13.491c24.207 6.733 49.884 6.268 73.824-1.348l30.102-9.57c29.474-9.37 61.086-9.946 90.889-1.655 67.959 18.91 114.918 80.226 114.918 150.071v91.866c0 52.45-42.982 94.967-96 94.967h-352.001c-53.019 0-96-42.517-96-94.967v-103.633c0-62.822 40.999-118.46 101.459-137.685zM272.736 585.98c-15.545-4.322-32.033-4.023-47.407 0.866-33.993 10.807-57.044 42.091-57.044 77.41v103.633c0 17.485 14.327 31.654 32 31.654h352.001c17.673 0 32-14.17 32-31.654v-91.866c0-41.476-27.887-77.892-68.25-89.122-17.698-4.924-36.471-4.582-53.973 0.981l-30.101 9.57c-35.91 11.422-74.425 12.122-110.737 2.018l-48.489-13.491zM699.486 777.685h140.8c53.018 0 96-42.923 96-95.872v-30.571c0-56.802-38.618-106.351-93.751-120.294-21.397-5.414-43.849-5.035-65.054 1.092l-16.401 4.745c-21.841 6.31-44.971 6.703-67.012 1.126l-29.811-7.539c-19.904-5.035-40.794-4.685-60.518 1.015-1.062 0.311-2.125 0.631-3.174 0.969 10.714 4.045 20.894 9.527 30.255 16.354l2.428 1.771 15.040 13.193c9.937 8.713 18.142 19.221 24.183 30.972l2.206 4.292 3.678 0.934c33.062 8.363 67.759 7.778 100.523-1.694l16.401-4.74c10.283-2.974 21.171-3.157 31.548-0.529 26.735 6.763 45.461 30.788 45.461 58.334v30.571c0 17.651-14.327 31.957-32 31.957h-140.8v63.915z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["team"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":429,"id":16,"name":"team","prevSize":32,"code":59776},"setIdx":0,"setId":0,"iconIdx":129},{"icon":{"paths":["M227.087 308.609c-47.831 66.699-64.077 147.668-64.077 201.185v1.404l-0.127 1.399c-9.348 103.236 27.547 175.996 86.848 226.377 60.643 51.516 146.604 80.998 235.291 90.893 88.61 9.886 186.223 1.399 263.339-14.976 38.562-8.188 70.929-18.121 93.888-28.126 8.909-3.883 15.838-7.535 20.945-10.765-2.377-1.515-5.248-3.196-8.678-5.030-8.883-4.749-19.055-9.263-29.611-13.897l-1.843-0.806c-9.314-4.083-19.725-8.649-27.61-13.077-14.293-8.030-28.318-17.156-38.545-26.867-5.035-4.783-10.761-11.196-14.596-19.183-4.058-8.457-6.959-21.082-1.259-34.436 30.814-72.188 45.457-111.727 52.548-137.835 6.622-24.38 6.622-36.655 6.622-56.171v-0.179c0-15.514-8.977-86.595-53.777-152.876-43.371-64.175-121.395-125.729-264.828-125.729-129.727 0-207.831 53.576-254.531 118.696zM177.043 272.433c58.132-81.062 154.749-144.433 304.574-144.433 164.894 0 261.594 72.589 315.857 152.878 52.838 78.182 64.414 161.879 64.414 187.641 0 21.658-0.017 40.337-8.794 72.64-7.834 28.834-22.626 68.617-50.048 133.423 5.069 4.036 12.591 9.003 22.507 14.571 5.12 2.876 12.992 6.34 24.055 11.191 10.261 4.51 22.579 9.933 33.89 15.979 10.846 5.798 23.526 13.572 32.951 23.74 9.86 10.633 20.211 28.868 12.817 51.136-4.873 14.673-16.183 25.092-25.609 32.017-10.24 7.522-22.946 14.281-36.86 20.343-27.947 12.177-64.58 23.181-105.681 31.906-82.197 17.451-186.522 26.688-282.906 15.936-96.31-10.743-195.347-43.174-268.314-105.165-74.031-62.891-119.295-154.778-108.551-277.854 0.276-63.411 19.118-157.053 75.696-235.949zM337.729 422.052c0-17.648 14.25-31.955 31.828-31.955h183.011c17.574 0 31.825 14.307 31.825 31.955s-14.251 31.955-31.825 31.955h-183.011c-17.578 0-31.828-14.306-31.828-31.955zM369.557 539.708c-17.578 0-31.828 14.306-31.828 31.957 0 17.647 14.25 31.953 31.828 31.953h224.12c17.579 0 31.825-14.306 31.825-31.953 0-17.651-14.246-31.957-31.825-31.957h-224.12z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["threads"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":430,"id":15,"name":"threads","prevSize":32,"code":59777},"setIdx":0,"setId":0,"iconIdx":130},{"icon":{"paths":["M485.811 318.068c0-51.548-42.406-94.366-95.999-94.366s-96 42.819-96 94.366c0 51.548 42.408 94.367 96 94.367s95.999-42.819 95.999-94.367zM549.811 318.068c0 87.417-71.633 158.284-159.999 158.284s-160-70.867-160-158.284c0-87.417 71.634-158.282 160-158.282s159.999 70.865 159.999 158.282zM303.591 525.035c-27.649-7.693-56.976-7.159-84.32 1.536-60.46 19.226-101.459 74.863-101.459 137.685v103.633c0 52.45 42.981 94.967 96 94.967h351.999c3.605 0 7.164-0.196 10.667-0.576v-64.538c-3.337 1.169-6.925 1.801-10.667 1.801h-351.999c-17.673 0-32-14.17-32-31.654v-103.633c0-35.319 23.051-66.603 57.043-77.41 15.374-4.89 31.862-5.188 47.407-0.866l48.489 13.491c36.311 10.103 74.826 9.404 110.739-2.018l30.097-9.57c17.506-5.564 36.279-5.905 53.978-0.981 18.901 5.257 35.068 16.038 46.912 30.281v-79.714c-9.31-4.749-19.2-8.627-29.585-11.516-29.803-8.29-61.414-7.714-90.889 1.655l-30.1 9.57c-23.941 7.616-49.617 8.081-73.825 1.348l-48.489-13.491zM785.182 489.033c-12.331-12.651-32.589-12.919-45.252-0.61s-12.937 32.542-0.61 45.193l102.844 105.506h-324.352c-17.673 0-32 14.31-32 31.962 0 17.647 14.327 31.957 32 31.957h324.352l-102.844 105.51c-12.326 12.646-12.053 32.879 0.61 45.188 12.663 12.314 32.922 12.041 45.252-0.606l155.716-159.761c12.092-12.407 12.092-32.175 0-44.582l-155.716-159.757z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["transfer"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":431,"id":14,"name":"transfer","prevSize":32,"code":59778},"setIdx":0,"setId":0,"iconIdx":131},{"icon":{"paths":["M769.084 864.209v-447.408h-448v447.408h448zM257.083 864.209v-447.408c-35.346 0-64-28.616-64-63.916v-127.831c0-35.299 28.654-63.916 64-63.916h224c0-35.299 28.655-63.915 64-63.915s64 28.616 64 63.915h224c35.345 0 64 28.616 64 63.916v127.831c0 35.299-28.655 63.916-64 63.916v447.408c0 35.298-28.655 63.915-64 63.915h-448c-35.346 0-64-28.617-64-63.915zM833.084 225.055h-576v127.831h576v-127.831zM449.084 544.631v191.748c0 17.647 14.327 31.957 32 31.957s32-14.31 32-31.957v-191.748c0-17.647-14.327-31.957-32-31.957s-32 14.31-32 31.957zM609.084 512.674c17.673 0 32 14.31 32 31.957v191.748c0 17.647-14.327 31.957-32 31.957s-32-14.31-32-31.957v-191.748c0-17.647 14.327-31.957 32-31.957z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["trash"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":432,"id":13,"name":"trash","prevSize":32,"code":59779},"setIdx":0,"setId":0,"iconIdx":132},{"icon":{"paths":["M810.667 576c-35.345 0-64-28.655-64-64s28.655-64 64-64c35.345 0 64 28.655 64 64s-28.655 64-64 64z","M554.667 576c-35.345 0-64-28.655-64-64s28.655-64 64-64c35.345 0 64 28.655 64 64s-28.655 64-64 64z","M298.667 576c-35.346 0-64-28.655-64-64s28.654-64 64-64c35.346 0 64 28.655 64 64s-28.654 64-64 64z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["truncation"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":433,"id":12,"name":"truncation","prevSize":32,"code":59780},"setIdx":0,"setId":0,"iconIdx":133},{"icon":{"paths":["M408.067 320c0-17.673-14.327-32-32-32s-32 14.327-32 32v256c0 106.039 85.962 192 192.002 192 106.035 0 192-85.961 192-192v-256c0-17.673-14.327-32-32-32-17.677 0-32 14.327-32 32v256c0 70.694-57.31 128-128 128-70.694 0-128.002-57.306-128.002-128v-256zM376.067 848c-17.673 0-32 14.327-32 32s14.327 32 32 32h320.002c17.673 0 32-14.327 32-32s-14.327-32-32-32h-320.002z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["underline"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":434,"id":11,"name":"underline","prevSize":32,"code":59781},"setIdx":0,"setId":0,"iconIdx":134},{"icon":{"paths":["M536.068 832c176.73 0 320-143.27 320-320 0-176.731-143.27-320-320-320-111.715 0-210.058 57.245-267.297 144h107.296c17.673 0 32 14.327 32 32s-14.327 32-32 32h-176c-17.673 0-32-14.327-32-32v-192c0-17.673 14.327-32 32-32s32 14.327 32 32v101.364c70.228-90.856 180.282-149.364 304.002-149.364 212.075 0 384 171.923 384 384 0 212.079-171.925 384-384 384-212.079 0-384.002-171.921-384.002-384h64c0 176.73 143.269 320 320.002 320z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["undo"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":435,"id":10,"name":"undo","prevSize":32,"code":59782},"setIdx":0,"setId":0,"iconIdx":135},{"icon":{"paths":["M297.194 356.679c-6.619 27.765-2.384 63.755 25.498 105.58l33.166 49.749h-59.792c-44.011 0-70.483 14.874-86.279 33.621-16.496 19.575-24.573 47.262-23.733 77.491 0.841 30.259 10.601 59.968 25.818 81.31 15.127 21.218 33.403 31.578 52.195 31.578h144v64h-144.001c-45.209 0-80.932-25.638-104.305-58.423-23.283-32.657-36.523-74.948-37.682-116.689-1.161-41.771 9.763-86.084 38.766-120.508 20.726-24.597 49.155-42.317 84.825-50.782-16.1-39.010-19.008-77.050-10.731-111.77 11.253-47.2 42.304-84.492 80.791-107.342 38.399-22.798 85.676-32.138 131.301-21.965 35.584 7.935 68.911 27.48 95.253 59.554 53.751-35.147 127.582-30.892 182.485-2.495 34.436 17.812 64.789 46.382 81.434 85.009 12.297 28.531 16.439 61.011 10.607 96.206 46.114 6.682 81.51 25.156 105.617 53.453 30.349 35.627 38.101 81.353 33.442 123.285-4.655 41.92-21.943 83.486-46.545 115.115-24.060 30.933-59.354 57.353-101.257 57.353h-144v-64h144c14.093 0 32.798-9.579 50.739-32.644 17.399-22.374 30.114-52.804 33.455-82.889 3.341-30.067-2.906-56.341-18.556-74.718-15.219-17.869-44.036-33.749-97.638-33.749h-45.687l15.612-42.935c13.547-37.252 11.093-66.743 1.438-89.149-9.856-22.872-28.501-41.302-52.066-53.489-49.587-25.649-107.473-18.624-134.716 14.063l-30.131 36.162-22.545-41.324c-19.755-36.22-47.228-54.176-74.871-60.34-28.374-6.327-59.096-0.669-84.697 14.531-25.513 15.148-44.463 38.854-51.209 67.153zM655.044 588.779l-96-99.051c-6.029-6.217-14.319-9.728-22.976-9.728-8.661 0-16.951 3.511-22.98 9.728l-96 99.051c-12.3 12.689-11.983 32.947 0.707 45.248s32.948 11.985 45.249-0.708l41.024-42.321v273.003c0 17.673 14.323 32 32 32 17.673 0 32-14.327 32-32v-273.003l41.020 42.321c12.301 12.693 32.559 13.009 45.248 0.708 12.693-12.301 13.009-32.559 0.708-45.248z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["upload"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":436,"id":9,"name":"upload","prevSize":32,"code":59783},"setIdx":0,"setId":0,"iconIdx":136},{"icon":{"paths":["M618.539 336c0-53.019-42.978-96-96-96-53.018 0-96 42.981-96 96s42.982 96 96 96c53.022 0 96-42.981 96-96zM682.539 336c0 88.366-71.633 160-160 160s-160-71.634-160-160c0-88.366 71.633-160 160-160s160 71.634 160 160zM422.991 551.799c-24.621-5.769-50.286-5.363-74.713 1.178-67.087 17.971-113.738 78.763-113.738 148.215v66.807c0 53.018 42.981 96 96 96h384c53.022 0 96-42.982 96-96v-58.53c0-74.3-51.149-138.825-123.49-155.78l-6.455-1.51c-25.673-6.020-52.437-5.598-77.905 1.225l-49.63 13.295c-20.378 5.457-41.788 5.794-62.323 0.981l-67.744-15.881zM364.836 614.797c14.238-3.81 29.199-4.049 43.55-0.683l67.744 15.876c30.805 7.219 62.925 6.716 93.487-1.472l49.63-13.295c15.283-4.092 31.339-4.343 46.741-0.734l6.455 1.51c43.405 10.176 74.095 48.887 74.095 93.47v58.53c0 17.673-14.327 32-32 32h-384c-17.673 0-32-14.327-32-32v-66.807c0-40.486 27.193-75.921 66.297-86.396z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["user"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":437,"id":8,"name":"user","prevSize":32,"code":59784},"setIdx":0,"setId":0,"iconIdx":137},{"icon":{"paths":["M266.539 202.672c0-17.673 19.103-32 42.667-32h256c23.565 0 42.667 14.327 42.667 32s-19.102 32-42.667 32h-256c-23.564 0-42.667-14.327-42.667-32zM170.539 383.995c0-5.891 4.776-10.667 10.667-10.667h512c5.892 0 10.667 4.776 10.667 10.667v85.334c0 11.375 6.037 21.892 15.859 27.631 9.822 5.734 21.952 5.828 31.859 0.243l97.83-55.164c2.53-1.429 4.855-3.191 6.908-5.248 6.72-6.72 18.21-1.958 18.21 7.543v263.322c0 9.502-11.49 14.259-18.21 7.539-2.052-2.052-4.378-3.819-6.908-5.244l-97.83-55.164c-9.907-5.589-22.037-5.495-31.859 0.243-9.822 5.734-15.859 16.256-15.859 27.631v85.333c0 5.888-4.774 10.667-10.667 10.667h-512c-5.891 0-10.667-4.779-10.667-10.667v-384.001zM181.206 309.328c-41.237 0-74.667 33.429-74.667 74.667v384.001c0 41.237 33.429 74.667 74.667 74.667h512c41.237 0 74.667-33.429 74.667-74.667v-30.554l46.78 26.377c47.42 41.993 123.887 8.7 123.887-56.162v-263.322c0-64.864-76.467-98.155-123.887-56.164l-46.78 26.377v-30.553c0-41.237-33.429-74.667-74.667-74.667h-512z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["video-1"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":438,"id":7,"name":"video-1","prevSize":32,"code":59785},"setIdx":0,"setId":0,"iconIdx":138},{"icon":{"paths":["M313.716 170.672c-23.564 0-42.667 14.327-42.667 32s19.103 32 42.667 32h255.999c23.565 0 42.667-14.327 42.667-32s-19.102-32-42.667-32h-255.999z","M560.759 503.454c11.268-11.268 11.191-29.611-0.166-40.973-11.362-11.358-29.705-11.435-40.973-0.171l-71.403 71.403-71.995-71.996c-11.361-11.362-29.704-11.435-40.971-0.171-11.267 11.268-11.191 29.611 0.17 40.973l71.996 71.996-71.401 71.403c-11.267 11.264-11.191 29.606 0.17 40.969s29.704 11.439 40.971 0.171l71.401-71.403 71.996 71.996c11.362 11.362 29.705 11.439 40.973 0.171 11.264-11.264 11.187-29.611-0.171-40.969l-71.996-71.996 71.398-71.403z","M111.049 383.995c0-41.237 33.429-74.667 74.667-74.667h511.999c41.237 0 74.667 33.429 74.667 74.667v30.553l46.78-26.377c47.42-41.99 123.887-8.7 123.887 56.164v263.322c0 64.862-76.467 98.155-123.887 56.162l-46.78-26.377v30.554c0 41.237-33.429 74.667-74.667 74.667h-511.999c-41.237 0-74.667-33.429-74.667-74.667v-384.001zM185.716 373.328c-5.891 0-10.667 4.776-10.667 10.667v384.001c0 5.888 4.776 10.667 10.667 10.667h511.999c5.892 0 10.667-4.779 10.667-10.667v-85.333c0-11.375 6.037-21.897 15.859-27.631 9.822-5.739 21.952-5.833 31.859-0.243l97.83 55.164c2.53 1.425 4.855 3.191 6.908 5.244 6.72 6.72 18.21 1.963 18.21-7.539v-263.322c0-9.502-11.49-14.263-18.21-7.543-2.052 2.057-4.378 3.819-6.908 5.248l-97.83 55.164c-9.907 5.585-22.037 5.491-31.859-0.243-9.822-5.739-15.859-16.256-15.859-27.631v-85.334c0-5.891-4.774-10.667-10.667-10.667h-511.999z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["video-disabled"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":439,"id":6,"name":"video-disabled","prevSize":32,"code":59786},"setIdx":0,"setId":0,"iconIdx":139},{"icon":{"paths":["M878.921 153.128c-12.497-12.497-32.755-12.497-45.252 0l-668.247 668.244c-12.497 12.497-12.497 32.759 0 45.257s32.758 12.497 45.255 0l668.244-668.246c12.497-12.497 12.497-32.758 0-45.255zM311.461 170.672c-23.564 0-42.667 14.327-42.667 32s19.102 32 42.667 32h256.001c23.565 0 42.667-14.327 42.667-32s-19.102-32-42.667-32h-256.001zM586.965 309.329h-403.504c-41.237 0-74.667 33.429-74.667 74.667v384c0 6.012 0.71 11.853 2.051 17.455l61.949-61.952v-339.503c0-5.891 4.775-10.667 10.667-10.667h339.504l64-64zM389.133 778.662h306.33c5.888 0 10.667-4.774 10.667-10.667v-85.333c0-11.375 6.037-21.897 15.859-27.631 9.822-5.739 21.948-5.833 31.855-0.243l97.83 55.164c2.534 1.425 4.855 3.191 6.912 5.244 6.72 6.72 18.21 1.963 18.21-7.539v-263.322c0-9.502-11.49-14.263-18.21-7.543-2.057 2.057-4.378 3.819-6.912 5.248l-97.83 55.164c-9.907 5.585-22.033 5.495-31.855-0.243s-15.859-16.256-15.859-27.631v-7.663l110.775-73.495c47.42-41.99 123.891-8.7 123.891 56.164v263.322c0 64.862-76.471 98.155-123.891 56.162l-46.775-26.377v30.554c0 41.237-33.429 74.667-74.667 74.667h-370.33l64-64z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["video-off"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":440,"id":5,"name":"video-off","prevSize":32,"code":59787},"setIdx":0,"setId":0,"iconIdx":140},{"icon":{"paths":["M307.615 224c-17.673 0-32 14.327-32 32s14.327 32 32 32h255.999c17.673 0 32-14.327 32-32s-14.327-32-32-32h-255.999z","M190.281 341.328c-23.564 0-42.667 19.102-42.667 42.667v384.001c0 23.565 19.102 42.667 42.667 42.667h511.999c23.565 0 42.667-19.102 42.667-42.667v-128l97.83 97.83c26.88 26.876 72.836 7.842 72.836-30.17v-263.322c0-38.012-45.956-57.049-72.836-30.17l-97.83 97.831v-128.001c0-23.564-19.102-42.667-42.667-42.667h-511.999z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["video"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1},{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":441,"id":4,"name":"video","prevSize":32,"code":59788},"setIdx":0,"setId":0,"iconIdx":141},{"icon":{"paths":["M319.276 661.342h-118.991v-298.665h118.991l12.367-48.047c11.845-46.020 53.695-79.953 103.311-79.953h64v554.665h-64c-49.615 0-91.466-33.933-103.311-79.949l-12.367-48.051zM178.952 725.342h90.71c18.946 73.613 85.766 128 165.291 128h85.333c23.565 0 42.667-19.102 42.667-42.667v-597.332c0-23.564-19.102-42.667-42.667-42.667h-85.333c-79.524 0-146.345 54.391-165.291 128h-90.71c-23.564 0-42.667 19.103-42.667 42.667v341.332c0 23.565 19.103 42.667 42.667 42.667zM894.912 393.373c12.497 12.497 12.497 32.758 0 45.254l-73.374 73.374 73.374 73.374c12.497 12.497 12.497 32.755 0 45.252s-32.759 12.497-45.252 0l-73.374-73.37-73.374 73.37c-12.497 12.497-32.759 12.497-45.252 0-12.497-12.497-12.497-32.755 0-45.252l73.37-73.374-73.37-73.374c-12.497-12.495-12.497-32.757 0-45.254 12.493-12.497 32.755-12.497 45.252 0l73.374 73.371 73.374-73.371c12.493-12.497 32.755-12.497 45.252 0z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["volume-disabled"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":442,"id":3,"name":"volume-disabled","prevSize":32,"code":59789},"setIdx":0,"setId":0,"iconIdx":142},{"icon":{"paths":["M872.158 153.127c-12.497-12.497-32.755-12.497-45.252 0l-668.247 668.244c-12.497 12.497-12.497 32.759 0 45.257s32.758 12.497 45.255 0l668.244-668.246c12.497-12.497 12.497-32.758 0-45.255zM680.674 480.358l55.923-55.923c16.256 79.564 14.511 161.864-5.231 240.844l-11.622 46.485c-4.288 17.148-21.662 27.571-38.805 23.283-17.148-4.284-27.571-21.658-23.283-38.805l11.622-46.485c13.875-55.509 17.673-112.875 11.396-169.399zM823.194 385.922l-11.315-36.77 51.209-51.206 21.278 69.154c33.344 108.369 31.991 224.448-3.861 332.010l-33.446 100.343c-5.589 16.764-23.71 25.826-40.478 20.237s-25.826-23.71-20.237-40.478l33.446-100.339c31.637-94.912 32.828-197.333 3.405-292.952zM496.7 664.333l64-64v210.342c0 23.565-19.106 42.667-42.667 42.667h-85.333c-35.462 0-68.396-10.812-95.687-29.325l46.612-46.609c14.701 7.629 31.395 11.934 49.075 11.934h64v-125.009zM134.031 682.675c0 19.742 13.403 36.348 31.604 41.22l62.552-62.554h-30.156v-298.665h118.99l12.367-48.047c11.845-46.020 53.696-79.953 103.312-79.953h64v158.156l64-64v-115.49c0-23.564-19.106-42.667-42.667-42.667h-85.333c-79.526 0-146.346 54.391-165.292 128h-90.71c-23.564 0-42.667 19.103-42.667 42.667v341.332z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["volume-off"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":443,"id":2,"name":"volume-off","prevSize":32,"code":59790},"setIdx":0,"setId":0,"iconIdx":143},{"icon":{"paths":["M303.875 631.121h-113.433v-280.89h113.433l12.367-48.048c11.055-42.953 50.122-74.619 96.423-74.619h58.665v526.223h-58.665c-46.301 0-85.368-31.667-96.423-74.62l-12.367-48.047zM167.331 695.121h86.931c18.156 70.541 82.193 122.667 158.403 122.667h81.777c22.583 0 40.887-18.308 40.887-40.892v-572.443c0-22.582-18.304-40.889-40.887-40.889h-81.778c-76.21 0-140.246 52.124-158.403 122.667h-86.931c-22.582 0-40.889 18.307-40.889 40.889v327.11c0 22.583 18.307 40.892 40.889 40.892zM650.236 316.516c17.148-4.286 34.522 6.138 38.805 23.284l11.14 44.551c20.804 83.229 20.804 170.303 0 253.529l-11.14 44.553c-4.284 17.148-21.658 27.571-38.805 23.283-17.143-4.284-27.567-21.658-23.283-38.805l11.14-44.553c18.257-73.037 18.257-149.444 0-222.484l-11.14-44.551c-4.284-17.146 6.14-34.519 23.283-38.806zM811.251 235.938c-5.201-16.892-23.108-26.372-39.996-21.175-16.892 5.198-26.372 23.104-21.175 39.996l35.533 115.49c28.117 91.37 26.978 189.239-3.251 279.931l-32.055 96.158c-5.589 16.768 3.473 34.889 20.237 40.478 16.768 5.589 34.889-3.473 40.478-20.237l32.055-96.162c34.449-103.343 35.746-214.869 3.708-318.99l-35.533-115.49z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["volume"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":444,"id":1,"name":"volume","prevSize":32,"code":59791},"setIdx":0,"setId":0,"iconIdx":144},{"icon":{"paths":["M540.578 351.999c17.673 0 32 14.327 32 32v224.001c0 17.673-14.327 32-32 32s-32-14.327-32-32v-224.001c0-17.673 14.327-32 32-32z","M540.578 672c17.673 0 32 14.327 32 32s-14.327 32-32 32c-17.673 0-32-14.327-32-32s14.327-32 32-32z","M595.678 158.342c-24.772-41.922-85.427-41.922-110.199 0l-359.923 609.099c-25.21 42.662 5.545 96.559 55.1 96.559h719.842c49.557 0 80.311-53.897 55.1-96.559l-359.919-609.099zM540.578 190.901l359.919 609.099h-719.842l359.923-609.099z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["warning"],"colorPermutations":{"10811412212282312341245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}]}},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":445,"id":0,"name":"warning","prevSize":32,"code":59792},"setIdx":0,"setId":0,"iconIdx":145}],"height":1024,"metadata":{"name":"custom"},"preferences":{"showGlyphs":true,"showCodes":true,"showQuickUse":true,"showQuickUse2":true,"showSVGs":true,"fontPref":{"prefix":"icon-","metadata":{"fontFamily":"custom","majorVersion":1,"minorVersion":0},"metrics":{"emSize":1024,"baseline":6.25,"whitespace":50},"embed":false,"showVersion":false,"showMetadata":false,"showMetrics":false,"showSelector":false},"imagePref":{"prefix":"icon-","png":true,"useClassSelector":true,"color":0,"bgColor":16777215,"name":"icomoon","classSelector":".icon"},"historySize":50,"gridSize":16}}
\ No newline at end of file
+{"IcoMoonType":"selection","icons":[{"icon":{"paths":["M794.598 131.828c-24.994-24.994-65.515-24.994-90.509 0l-529.769 529.769c-9.564 9.562-15.852 21.909-17.962 35.273l-19.585 124.019c-1.384 8.764-0.941 17.28 1.005 25.229 7.587 30.997 38.032 53.367 72.195 47.974l124.022-19.584c13.36-2.112 25.708-8.401 35.272-17.963l529.771-529.769c12.497-12.497 18.743-28.877 18.743-45.257 0-10.365-2.505-20.73-7.509-30.111-2.901-5.443-6.647-10.556-11.238-15.144l-104.435-104.437zM629.845 296.585l119.497-119.5 104.439 104.436-119.501 119.5-104.435-104.436zM199.991 830.874l19.585-124.019 365.013-365.015 104.435 104.436-365.012 365.013-124.021 19.584z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["edit"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":544,"id":172,"name":"edit","prevSize":32,"code":59835},"setIdx":0,"setId":3,"iconIdx":0},{"icon":{"paths":["M410.708 527.33c26.575 0 48.121-21.585 48.121-48.213s-21.547-48.213-48.121-48.213c-26.576 0-48.12 21.585-48.12 48.213s21.544 48.213 48.12 48.213z","M603.187 479.117c0 26.628-21.542 48.213-48.119 48.213s-48.119-21.585-48.119-48.213c0-26.628 21.542-48.213 48.119-48.213s48.119 21.585 48.119 48.213z","M747.55 479.117c0 26.628-21.542 48.213-48.119 48.213s-48.119-21.585-48.119-48.213c0-26.628 21.542-48.213 48.119-48.213s48.119 21.585 48.119 48.213z","M101.734 813.683l119.625 31.279c85.312 22.31 173.449-16.252 238.694-79.71 29.5 4.796 59.874 7.245 90.675 7.245 218.295 0 404.339-122.863 404.339-294.519 0-171.663-186.039-294.519-404.339-294.519-218.313 0-404.35 122.852-404.339 294.524 0 65.071 27.642 125.013 75.655 173.585-2.847 24.836-14.596 44.732-36.049 68.553l-84.261 93.564zM550.729 258.994c183.13 0 331.601 98.043 331.601 218.984 0 120.93-148.471 218.982-331.601 218.982-40.781 0-79.834-4.877-115.913-13.76-36.667 45.598-117.332 109.005-195.694 88.516 25.489-28.305 63.251-76.13 55.168-154.91-46.968-37.781-75.162-86.135-75.162-138.829-0.008-120.949 148.46-218.984 331.599-218.984z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["baloon-ellipsis"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":372,"id":171,"name":"baloon-ellipsis","prevSize":32,"code":59648},"setIdx":0,"setId":3,"iconIdx":1},{"icon":{"paths":["M912.401 572.574h-269.013l-250.606-423.241h269.063l250.556 423.241zM375.23 190.906l134.483 238.078-230.78 408.354-134.532-237.922 230.829-408.51zM455.343 615.979h455.706l-134.532 258.688h-465.642l144.468-258.688z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["file-google-drive"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":373,"id":170,"name":"file-google-drive","prevSize":32,"code":59649},"setIdx":0,"setId":3,"iconIdx":2},{"icon":{"paths":["M892.437 567.625c-41.856-41.139-161.237-29.828-220.928-22.285-59.004-35.998-98.458-85.705-126.242-158.727 13.376-55.195 34.645-139.187 18.526-191.982-14.409-89.82-129.677-80.907-146.143-20.227-15.094 55.194-1.372 131.987 24.014 230.035-34.305 81.935-85.42 191.981-121.44 255.059-68.611 35.311-161.235 89.822-174.957 158.387-11.321 54.165 89.194 189.239 261.063-106.961 76.845-25.37 160.548-56.567 234.647-68.907 64.836 34.965 140.651 58.278 191.424 58.278 87.479 0 96.055-96.674 60.036-132.672zM212.848 834.342c17.496-46.967 84.048-101.133 104.288-119.991-65.18 103.876-104.288 122.389-104.288 119.991zM492.779 180.918c25.387 0 22.985 110.047 6.174 139.872-15.091-47.653-14.75-139.872-6.174-139.872zM409.074 649.216c33.277-57.937 61.748-126.844 84.733-187.524 28.476 51.767 64.836 93.248 103.262 121.702-71.356 14.741-133.449 44.911-187.995 65.822zM860.531 632.077c0 0-17.152 20.57-127.957-26.743 120.41-8.913 140.309 18.513 127.957 26.743z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["file-pdf"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":374,"id":169,"name":"file-pdf","prevSize":32,"code":59650},"setIdx":0,"setId":3,"iconIdx":3},{"icon":{"paths":["M862.455 324.045c-35.2-60.31-82.944-108.058-143.249-143.253-60.314-35.197-126.161-52.792-197.581-52.792-71.415 0-137.28 17.6-197.58 52.792-60.31 35.194-108.054 82.943-143.253 143.253-35.194 60.308-52.792 126.165-52.792 197.568 0 85.773 25.024 162.901 75.086 231.407 50.056 68.51 114.721 115.917 193.99 142.225 9.227 1.711 16.058 0.508 20.499-3.584 4.443-4.096 6.662-9.225 6.662-15.369 0-1.024-0.088-10.249-0.259-27.678-0.176-17.429-0.259-32.631-0.259-45.606l-11.789 2.039c-7.516 1.378-16.998 1.963-28.446 1.796-11.442-0.162-23.321-1.361-35.619-3.588-12.304-2.21-23.748-7.334-34.342-15.364-10.588-8.030-18.104-18.543-22.547-31.518l-5.125-11.793c-3.416-7.851-8.794-16.576-16.142-26.138-7.347-9.57-14.778-16.055-22.294-19.473l-3.589-2.569c-2.391-1.707-4.61-3.767-6.662-6.157-2.050-2.389-3.585-4.779-4.61-7.172-1.027-2.398-0.176-4.365 2.562-5.905 2.737-1.545 7.685-2.291 14.864-2.291l10.247 1.532c6.834 1.37 15.287 5.461 25.371 12.297 10.078 6.835 18.362 15.718 24.856 26.645 7.863 14.012 17.335 24.691 28.446 32.038 11.101 7.347 22.294 11.017 33.568 11.017s21.010-0.858 29.214-2.556c8.195-1.711 15.884-4.279 23.062-7.693 3.075-22.903 11.446-40.495 25.112-52.796-19.473-2.048-36.983-5.129-52.535-9.229-15.542-4.1-31.604-10.761-48.173-19.998-16.578-9.22-30.331-20.672-41.262-34.334-10.932-13.666-19.904-31.612-26.904-53.815-7.003-22.212-10.505-47.838-10.505-76.881 0-41.348 13.5-76.538 40.493-105.584-12.645-31.088-11.451-65.94 3.585-104.55 9.909-3.079 24.604-0.768 44.078 6.917 19.477 7.689 33.738 14.275 42.796 19.736 9.058 5.459 16.316 10.085 21.784 13.837 31.782-8.881 64.58-13.322 98.406-13.322s66.633 4.441 98.415 13.322l19.477-12.295c13.316-8.204 29.043-15.722 47.142-22.556 18.112-6.831 31.957-8.712 41.532-5.633 15.369 38.612 16.738 73.461 4.092 104.55 26.991 29.045 40.495 64.243 40.495 105.587 0 29.039-3.516 54.746-10.509 77.129-6.997 22.387-16.047 40.316-27.149 53.82-11.115 13.5-24.956 24.862-41.523 34.082-16.576 9.225-32.64 15.885-48.183 19.989-15.548 4.105-33.058 7.189-52.531 9.237 17.762 15.373 26.641 39.633 26.641 72.772v108.139c0 6.14 2.138 11.268 6.413 15.369 4.271 4.092 11.017 5.295 20.245 3.58 79.279-26.304 143.945-73.711 193.997-142.221 50.048-68.506 75.081-145.634 75.081-231.407-0.017-71.394-17.621-137.247-52.8-197.555z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["Github"]},"attrs":[{}],"properties":{"order":375,"id":168,"name":"Github","prevSize":32,"code":59651},"setIdx":0,"setId":3,"iconIdx":4},{"icon":{"paths":["M510.144 910.66l156.407-481.412h-312.813l156.406 481.412z","M510.144 910.66l-156.405-481.412h-219.199l375.604 481.412z","M134.541 429.248l-47.612 146.287c-4.37 13.342 0.46 28.062 11.73 36.113l411.484 299.012-375.603-481.412z","M134.54 429.252h219.199l-94.304-290.039c-4.83-14.95-25.991-14.95-30.821 0l-94.074 290.039z","M510.144 910.66l156.407-481.412h219.196l-375.603 481.412z","M885.747 429.248l47.612 146.287c4.373 13.342-0.457 28.062-11.729 36.113l-411.486 299.012 375.603-481.412z","M885.747 429.252h-219.196l94.302-290.039c4.83-14.95 25.993-14.95 30.822 0l94.071 290.039z"],"attrs":[{"fill":"rgb(226, 67, 41)"},{"fill":"rgb(252, 109, 38)"},{"fill":"rgb(252, 163, 38)"},{"fill":"rgb(226, 67, 41)"},{"fill":"rgb(252, 109, 38)"},{"fill":"rgb(252, 163, 38)"},{"fill":"rgb(226, 67, 41)"}],"isMulticolor":true,"isMulticolor2":false,"grid":0,"tags":["Gitlab"]},"attrs":[{"fill":"rgb(226, 67, 41)"},{"fill":"rgb(252, 109, 38)"},{"fill":"rgb(252, 163, 38)"},{"fill":"rgb(226, 67, 41)"},{"fill":"rgb(252, 109, 38)"},{"fill":"rgb(252, 163, 38)"},{"fill":"rgb(226, 67, 41)"}],"properties":{"order":376,"id":167,"name":"Gitlab","prevSize":32,"code":59652,"codes":[59652,59653,59654,59655,59656,59657,59658]},"setIdx":0,"setId":3,"iconIdx":5},{"icon":{"paths":["M881.941 442.176h-361.655v148.54h206.66c-8.9 48-35.955 88.67-76.625 115.9v96.346h124.1c72.614-66.85 114.505-165.295 114.505-282.24 0-27.226-2.445-53.41-6.985-78.545z","M520.286 896c103.68 0 190.605-34.385 254.135-93.035l-124.1-96.35c-34.385 23.040-78.37 36.655-130.035 36.655-100.015 0-184.67-67.55-214.866-158.31h-128.291v99.49c63.185 125.495 193.047 211.55 343.157 211.55z","M305.42 584.964c-7.68-23.040-12.044-47.65-12.044-72.96s4.364-49.92 12.044-72.96v-99.492h-128.291c-26.007 51.84-40.844 110.487-40.844 172.452 0 61.961 14.836 120.61 40.844 172.45l128.291-99.49z","M520.286 280.727c56.375 0 106.995 19.375 146.79 57.425l110.14-110.138c-66.5-61.964-153.425-100.015-256.93-100.015-150.11 0-279.971 86.051-343.157 211.549l128.291 99.491c30.196-90.764 114.851-158.313 214.866-158.313z"],"attrs":[{"fill":"rgb(66, 133, 244)"},{"fill":"rgb(52, 168, 83)"},{"fill":"rgb(251, 188, 5)"},{"fill":"rgb(234, 67, 53)"}],"width":1067,"isMulticolor":true,"isMulticolor2":false,"grid":0,"tags":["Google"]},"attrs":[{"fill":"rgb(66, 133, 244)"},{"fill":"rgb(52, 168, 83)"},{"fill":"rgb(251, 188, 5)"},{"fill":"rgb(234, 67, 53)"}],"properties":{"order":377,"id":166,"name":"Google","prevSize":32,"code":59659,"codes":[59659,59660,59661,59662]},"setIdx":0,"setId":3,"iconIdx":6},{"icon":{"paths":["M839.189 128h-654.548c-31.254 0-56.642 24.79-56.642 55.383v657.214c0 30.592 25.388 55.424 56.642 55.424h654.548c31.317 0 56.811-24.832 56.811-55.424v-657.214c0-30.593-25.493-55.383-56.811-55.383z","M298.842 233.729c36.438 0 66.007 29.59 66.007 66.050 0 36.481-29.569 66.071-66.007 66.071-36.588 0-66.092-29.59-66.092-66.071 0-36.46 29.505-66.050 66.092-66.050zM241.795 782.438h114.030v-366.515h-114.030v366.515z","M427.273 415.921h109.188v50.114h1.579c15.189-28.821 52.352-59.202 107.755-59.202 115.354 0 136.666 75.884 136.666 174.598v201.007h-113.903v-178.244c0-42.496-0.725-97.178-59.179-97.178-59.285 0-68.331 46.319-68.331 94.148v181.274h-113.775v-366.517z"],"attrs":[{"fill":"rgb(0, 113, 161)"},{"fill":"rgb(255, 255, 254)"},{"fill":"rgb(255, 255, 254)"}],"isMulticolor":true,"isMulticolor2":false,"grid":0,"tags":["Linkedin"]},"attrs":[{"fill":"rgb(0, 113, 161)"},{"fill":"rgb(255, 255, 254)"},{"fill":"rgb(255, 255, 254)"}],"properties":{"order":378,"id":165,"name":"Linkedin","prevSize":32,"code":59663,"codes":[59663,59664,59665]},"setIdx":0,"setId":3,"iconIdx":7},{"icon":{"paths":["M85.333 85.333l730.795 774.089c0 0 24.896 17.557 43.934-2.927 19.038-20.489 4.395-40.973 4.395-40.973l-779.123-730.189zM316.727 158.5l556.515 599.956c0 0 24.896 17.557 43.938-2.927 19.038-20.489 4.39-40.973 4.39-40.973l-604.844-556.056zM710.682 915.025l-556.516-599.952 604.845 556.057c0 0 14.643 20.484-4.395 40.969-19.038 20.489-43.934 2.927-43.934 2.927zM512.337 221.417l388.804 419.151c0 0 17.395 12.271 30.694-2.044 13.303-14.31 3.072-28.625 3.072-28.625l-422.571-388.482zM596.523 915.674l-388.803-419.153 422.569 388.484c0 0 10.231 14.31-3.068 28.625-13.303 14.31-30.699 2.044-30.699 2.044zM712.145 312.141l176.222 190.549c0 0 8.602 5.751 15.181-0.956s1.519-13.414 1.519-13.414l-192.922-176.179zM481.229 880.226l-176.218-190.549 192.922 176.179c0 0 5.060 6.707-1.519 13.414s-15.185 0.956-15.185 0.956z"],"attrs":[{"fill":"rgb(222, 79, 79)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["Meteor"]},"attrs":[{"fill":"rgb(222, 79, 79)"}],"properties":{"order":379,"id":164,"name":"Meteor","prevSize":32,"code":59666},"setIdx":0,"setId":3,"iconIdx":8},{"icon":{"paths":["M385.058 837.38c290.193 0 448.922-240.111 448.922-448.329 0-6.82 0-13.609-0.465-20.367 30.878-22.306 57.536-49.924 78.716-81.562-28.791 12.742-59.341 21.099-90.62 24.791 32.939-19.692 57.587-50.665 69.367-87.153-30.972 18.354-64.853 31.289-100.19 38.246-48.905-51.936-126.618-64.647-189.559-31.006s-95.458 105.266-79.317 174.714c-126.86-6.351-245.054-66.192-325.169-164.628-41.876 71.997-20.487 164.102 48.848 210.338-25.108-0.742-49.67-7.505-71.61-19.721 0 0.644 0 1.323 0 1.997 0.020 75.004 52.962 139.61 126.58 154.462-23.228 6.323-47.599 7.249-71.241 2.701 20.669 64.188 79.903 108.16 147.404 109.427-55.869 43.849-124.886 67.652-195.945 67.584-12.553-0.026-25.094-0.785-37.559-2.274 72.153 46.242 156.107 70.771 241.839 70.656z"],"attrs":[{"fill":"rgb(29, 161, 242)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["Twitter"]},"attrs":[{"fill":"rgb(29, 161, 242)"}],"properties":{"order":380,"id":163,"name":"Twitter","prevSize":32,"code":59667},"setIdx":0,"setId":3,"iconIdx":9},{"icon":{"paths":["M317.896 231.569c-62.882 49.504-135.086 136.548-141.94 266.125-5.762 108.924 37.404 187.187 89.916 241.51 53.259 55.1 115.701 84.924 144.248 94.443 41.861 13.952 114.271 29.534 234.646-15.607 34.859-13.069 73.161-42.095 108.301-78.426 14.272-14.754 27.614-30.293 39.599-45.773-28.774 9.293-61.696 17.758-96.589 23.595-56.188 9.404-119.287 12.322-179.409-0.235-2.492-0.521-4.958-1.033-7.411-1.536-22.191-4.578-42.731-8.815-62.583-17.651-23.095-10.274-43.808-25.89-69.3-51.383-42.097-42.095-89.143-107.221-89.372-213.841-1.569-34.084 4.621-81.88 13.763-129.219 4.624-23.946 10.142-48.465 16.132-72.002zM344.209 138.22c32.8-17.15 63.709 15.843 53.877 45.907-12.235 37.414-24.586 85.511-33.483 131.58-9.024 46.731-13.946 88.633-12.643 114.698l0.040 0.798v0.802c0 84.915 36.172 134.916 70.627 169.374 22.505 22.507 36.833 32.277 50.064 38.165 13.227 5.884 26.829 8.717 51.085 13.764 1.924 0.397 3.913 0.815 5.978 1.246 49.911 10.423 104.533 8.337 155.759-0.239 65.434-10.953 122.385-31.979 152.375-47.386 17.562-9.020 34.991-2.466 44.476 5.965 9.664 8.589 19.375 27.153 8.887 46.955-20.638 38.95-53.645 84.42-92.181 124.262-38.217 39.509-84.318 76.036-131.836 93.854-135.625 50.863-223.215 34.441-277.353 16.397-36.516-12.173-108.392-46.912-170.026-110.677-62.381-64.533-114.683-159.428-107.809-289.37 10.79-203.98 157.583-317.1 232.164-356.095z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["moon"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":381,"id":162,"name":"moon","prevSize":32,"code":59668},"setIdx":0,"setId":3,"iconIdx":10},{"icon":{"paths":["M480 117.333c0-17.673 14.327-32 32-32s32 14.327 32 32v106.667c0 17.673-14.327 32-32 32s-32-14.327-32-32v-106.667zM770.039 214.629c12.497-12.497 32.759-12.497 45.257 0s12.497 32.758 0 45.255l-75.413 75.412c-12.497 12.497-32.759 12.497-45.257 0s-12.497-32.758 0-45.255l75.413-75.412zM335.377 694.63c-12.497-12.497-32.758-12.497-45.255 0l-75.495 75.494c-12.497 12.497-12.497 32.755 0 45.252s32.758 12.497 45.255 0l75.495-75.494c12.497-12.497 12.497-32.755 0-45.252zM480 800c0-17.673 14.327-32 32-32s32 14.327 32 32v106.667c0 17.673-14.327 32-32 32s-32-14.327-32-32v-106.667zM212 211.999c-12.497 12.497-12.497 32.758 0 45.255l75.349 75.349c12.497 12.497 32.758 12.497 45.255 0s12.497-32.758 0-45.255l-75.349-75.349c-12.497-12.497-32.758-12.497-45.255 0zM694.626 739.883c-12.497-12.497-12.497-32.759 0-45.257s32.759-12.497 45.257 0l75.328 75.328c12.497 12.497 12.497 32.759 0 45.257s-32.759 12.497-45.257 0l-75.328-75.328zM86.4 512c0 17.673 14.327 32 32 32h106.667c17.673 0 32-14.327 32-32s-14.327-32-32-32h-106.667c-17.673 0-32 14.327-32 32zM800 544c-17.673 0-32-14.327-32-32s14.327-32 32-32h106.667c17.673 0 32 14.327 32 32s-14.327 32-32 32h-106.667zM666.816 512c0-85.505-69.316-154.82-154.82-154.82-85.503 0-154.817 69.315-154.817 154.82 0 85.504 69.315 154.816 154.817 154.816 85.504 0 154.82-69.312 154.82-154.816zM725.329 512c0 117.82-95.509 213.333-213.333 213.333-117.819 0-213.332-95.514-213.332-213.333 0-117.822 95.512-213.335 213.332-213.335 117.824 0 213.333 95.513 213.333 213.335z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["sun"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":382,"id":161,"name":"sun","prevSize":32,"code":59669},"setIdx":0,"setId":3,"iconIdx":11},{"icon":{"paths":["M195.378 191.997c0-15.807 12.815-28.622 28.622-28.622h128c15.807 0 28.622 12.815 28.622 28.622s-12.815 28.622-28.622 28.622h-128c-15.807 0-28.622-12.814-28.622-28.622z","M736 559.996c0 97.203-78.797 176-176 176s-176-78.797-176-176c0-97.203 78.797-175.999 176-175.999s176 78.796 176 175.999zM672 559.996c0-61.854-50.146-112-112-112s-112 50.146-112 112c0 61.858 50.146 112 112 112s112-50.142 112-112z","M192 255.997c-35.346 0-64 28.654-64 64v447.999c0 35.345 28.654 64 64 64h640c35.345 0 64-28.655 64-64v-447.999c0-35.346-28.655-64-64-64h-640zM832 319.997v447.999h-640v-447.999h640z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["camera-photo"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":383,"id":160,"name":"camera-photo","prevSize":32,"code":59670},"setIdx":0,"setId":3,"iconIdx":12},{"icon":{"paths":["M700.147 361.892c4.681-24.975 34.701-34.093 49.126-13.174 31.991 46.404 50.726 102.656 50.726 163.281 0 60.629-18.735 116.881-50.726 163.285-14.426 20.919-44.446 11.802-49.126-13.175l-1.707-9.101c-1.583-8.431 0.384-17.084 4.855-24.401 20.749-33.967 32.704-73.89 32.704-116.608 0-42.714-11.955-82.637-32.704-116.604-4.471-7.319-6.438-15.972-4.855-24.402l1.707-9.102z","M320.705 395.396c-20.749 33.967-32.705 73.891-32.705 116.604 0 42.718 11.956 82.641 32.705 116.608 4.471 7.317 6.436 15.97 4.856 24.401l-1.707 9.101c-4.683 24.977-34.703 34.095-49.127 13.175-31.994-46.404-50.728-102.656-50.728-163.285 0-60.625 18.734-116.878 50.728-163.281 14.423-20.919 44.444-11.801 49.127 13.174l1.707 9.102c1.58 8.43-0.385 17.083-4.856 24.402z","M728.764 209.256l-0.512 2.747c-2.236 11.911 2.534 23.968 11.763 31.822 75.861 64.565 123.985 160.751 123.985 268.175 0 107.426-48.124 203.614-123.985 268.177-9.229 7.855-13.999 19.913-11.763 31.821l0.512 2.748c4.194 22.362 29.692 33.195 47.262 18.743 92.796-76.292 151.974-191.979 151.974-321.489 0-129.507-59.179-245.193-151.974-321.489-17.57-14.448-43.068-3.615-47.262 18.745z","M283.986 243.825c9.229-7.854 13.998-19.911 11.764-31.822l-0.515-2.747c-4.192-22.359-29.69-33.193-47.262-18.745-92.793 76.296-151.973 191.982-151.973 321.489 0 129.51 59.18 245.197 151.973 321.489 17.572 14.451 43.070 3.618 47.262-18.743l0.515-2.748c2.233-11.908-2.536-23.966-11.764-31.821-75.863-64.563-123.986-160.751-123.986-268.177 0-107.424 48.122-203.61 123.986-268.175z","M608 512c0 53.022-42.982 96-96 96s-96-42.978-96-96c0-53.018 42.982-95.999 96-95.999s96 42.981 96 95.999z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["live"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":384,"id":159,"name":"live","prevSize":32,"code":59671},"setIdx":0,"setId":3,"iconIdx":13},{"icon":{"paths":["M527.782 128c75.546 0 138.859 52.355 155.644 122.761l-59.644 59.644v-22.406c0-53.019-42.982-96-96-96-53.022 0-96 42.981-96 96v128c0 24.068 8.858 46.067 23.488 62.916l-45.322 45.321c-26.182-28.484-42.167-66.496-42.167-108.237v-128c0-88.366 71.634-160 160.001-160zM577.131 568.243l102.895-102.895c-15.765 48.674-54.221 87.13-102.895 102.895zM303.781 416c0 72.154 23.182 123.102 55.327 159.078l-45.303 45.303c-43.427-47.351-74.024-113.993-74.024-204.382 0-17.673 14.327-32 32-32s32 14.327 32 32zM494.438 650.935l-51.806 51.81c18.56 6.374 36.578 10.807 53.15 13.636v115.618h-160.001c-17.673 0-32 14.327-32 32s14.327 32 32 32h384.001c17.673 0 32-14.327 32-32s-14.327-32-32-32h-160v-115.618c44.638-7.62 99.819-26.897 147.721-64.38 60.702-47.501 108.279-123.29 108.279-236.002 0-17.673-14.327-32-32-32s-32 14.327-32 32c0 92.087-37.76 149.632-83.721 185.6-46.468 36.361-102.737 51.58-140.279 54.327-9.971-0.73-21.265-2.338-33.344-4.992zM841.152 153.373c12.497-12.497 32.759-12.497 45.257 0s12.497 32.758 0 45.255l-672 671.999c-12.497 12.497-32.758 12.497-45.255 0s-12.497-32.755 0-45.252l671.998-672.001z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["microphone-disabled"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":385,"id":158,"name":"microphone-disabled","prevSize":32,"code":59672},"setIdx":0,"setId":3,"iconIdx":14},{"icon":{"paths":["M621.53 288c0-53.019-42.982-96-96-96-53.022 0-96 42.981-96 96v128c0 53.018 42.978 96 96 96 53.018 0 96-42.982 96-96v-128zM365.529 288c0-88.366 71.634-160 160.001-160 88.363 0 160 71.634 160 160v128c0 88.367-71.637 160-160 160-88.367 0-160.001-71.633-160.001-160v-128zM269.529 384c17.673 0 32 14.327 32 32 0 92.087 37.758 149.632 83.72 185.6 46.465 36.361 102.734 51.58 140.281 54.327 37.542-2.748 93.811-17.967 140.279-54.327 45.961-35.968 83.721-93.513 83.721-185.6 0-17.673 14.327-32 32-32s32 14.327 32 32c0 112.713-47.578 188.501-108.279 236.002-47.902 37.483-103.083 56.759-147.721 64.38v115.618h160c17.673 0 32 14.327 32 32s-14.327 32-32 32h-384.001c-17.673 0-32-14.327-32-32s14.327-32 32-32h160.001v-115.618c-44.642-7.62-99.819-26.897-147.721-64.38-60.705-47.501-108.28-123.29-108.28-236.002 0-17.673 14.327-32 32-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["microphone"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":386,"id":157,"name":"microphone","prevSize":32,"code":59673},"setIdx":0,"setId":3,"iconIdx":15},{"icon":{"paths":["M384 149.138c0-11.766 9.551-21.305 21.333-21.305h85.333c11.78 0 21.333 9.539 21.333 21.305v106.526h-106.667c-11.782 0-21.333-9.539-21.333-21.305v-85.221z","M512 255.665h106.667c11.78 0 21.333 9.539 21.333 21.305v85.221c0 11.767-9.553 21.305-21.333 21.305h-106.667v-127.831z","M384 404.801c0-11.767 9.551-21.305 21.333-21.305h106.667v127.83h-106.667c-11.782 0-21.333-9.536-21.333-21.303v-85.222z","M512 511.326h106.667c11.78 0 21.333 9.54 21.333 21.308v106.526h-128v-127.834z","M426.667 639.159c-23.564 0-42.667 19.076-42.667 42.607v170.445c0 23.531 19.103 42.611 42.667 42.611h170.667c23.565 0 42.667-19.081 42.667-42.611v-213.052h-213.333zM490.667 724.378c-11.78 0-21.333 9.54-21.333 21.308v42.607c0 11.767 9.553 21.308 21.333 21.308h42.667c11.78 0 21.333-9.54 21.333-21.308v-42.607c0-11.767-9.553-21.308-21.333-21.308h-42.667z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["zip"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":387,"id":156,"name":"zip","prevSize":32,"code":59674},"setIdx":0,"setId":3,"iconIdx":16},{"icon":{"paths":["M288 224c-17.673 0-32 14.327-32 32s14.327 32 32 32h256c17.673 0 32-14.327 32-32s-14.327-32-32-32h-256z","M170.667 341.328c-23.564 0-42.667 19.102-42.667 42.667v384.001c0 23.565 19.103 42.667 42.667 42.667h512c23.565 0 42.667-19.102 42.667-42.667v-128l97.83 97.83c26.88 26.876 72.836 7.842 72.836-30.17v-263.322c0-38.012-45.956-57.049-72.836-30.17l-97.83 97.831v-128.001c0-23.564-19.102-42.667-42.667-42.667h-512z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["camera-filled"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":388,"id":155,"name":"camera-filled","prevSize":32,"code":59675},"setIdx":0,"setId":3,"iconIdx":17},{"icon":{"paths":["M809.003 166.758c7.782 6.063 12.331 15.377 12.331 25.242v448h-0.111c0.073 1.732 0.111 3.477 0.111 5.231 0 69.052-57.306 125.026-128 125.026s-128-55.974-128-125.026c0-69.052 57.306-125.030 128-125.030 23.313 0 45.171 6.089 64 16.725v-303.858l-384 96.797v409.139c0 69.052-57.308 125.035-128 125.035s-128-55.979-128-125.030c0-69.052 57.308-125.026 128-125.026 23.314 0 45.173 6.089 64 16.725v-325.777c0-14.66 9.963-27.446 24.178-31.029l448.001-112.929c9.566-2.412 19.708-0.276 27.49 5.787z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["musical-note"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":389,"id":154,"name":"musical-note","prevSize":32,"code":59676},"setIdx":0,"setId":3,"iconIdx":18},{"icon":{"paths":["M533.333 128c200.294 0 362.667 162.371 362.667 362.667h-362.667v-362.667z","M128 533.333c0-200.295 162.371-362.667 362.667-362.667v362.667h362.667c0 200.294-162.372 362.667-362.667 362.667s-362.667-162.372-362.667-362.667z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["pizza-graph"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":390,"id":153,"name":"pizza-graph","prevSize":32,"code":59677},"setIdx":0,"setId":3,"iconIdx":19},{"icon":{"paths":["M405.333 405.333c0 47.13-38.205 85.333-85.333 85.333s-85.333-38.204-85.333-85.333c0-47.128 38.205-85.333 85.333-85.333s85.333 38.205 85.333 85.333z","M96 192c0-17.673 14.327-32 32-32h768c17.673 0 32 14.327 32 32v640c0 17.673-14.327 32-32 32h-768c-17.673 0-32-14.327-32-32v-640zM160 764.164l151.704-176.99c9.269-10.816 24.571-14.199 37.538-8.307l153.124 69.602 160.474-204.241c6.007-7.646 15.172-12.147 24.9-12.228 9.728-0.077 18.961 4.271 25.097 11.823l151.164 186.048v-405.871h-704v540.164zM213.575 800h650.425v-68.638l-175.582-216.102-166.78 212.271-176.99-80.448-131.073 152.917z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["image"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":391,"id":152,"name":"image","prevSize":32,"code":59678},"setIdx":0,"setId":3,"iconIdx":20},{"icon":{"paths":["M671.057 183.163c16.683 16.663 16.683 43.677 0 60.34l-268.852 268.497 268.852 268.497c16.683 16.661 16.683 43.678 0 60.339-16.687 16.661-43.738 16.661-60.42 0l-299.061-298.667c-8.012-8-12.513-18.854-12.513-30.17s4.501-22.17 12.513-30.17l299.061-298.667c16.683-16.662 43.733-16.662 60.42 0z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["chevron-left-big"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":392,"id":151,"name":"chevron-left-big","prevSize":32,"code":59679},"setIdx":0,"setId":3,"iconIdx":21},{"icon":{"paths":["M160.253 256c0-17.673 14.327-32 32-32h640.844c17.677 0 32 14.327 32 32s-14.323 32-32 32h-640.844c-17.673 0-32-14.327-32-32zM160.253 512c0-17.673 14.327-32 32-32h640.844c17.677 0 32 14.327 32 32s-14.323 32-32 32h-640.844c-17.673 0-32-14.327-32-32zM160.253 768c0-17.673 14.327-32 32-32h640.844c17.677 0 32 14.327 32 32s-14.323 32-32 32h-640.844c-17.673 0-32-14.327-32-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["hamburguer"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":393,"id":150,"name":"hamburguer","prevSize":32,"code":59680},"setIdx":0,"setId":3,"iconIdx":22},{"icon":{"paths":["M512 96c80.094 0 154.901 22.636 218.377 61.859l-46.746 46.746c-24.738-13.843-51.324-24.785-79.287-32.368 12.169 22.394 23.078 49.096 32.405 79.249l-51.998 51.999c-5.658-22.993-12.169-44.004-19.349-62.666-12.821-33.338-26.522-55.927-38.473-69.070-8.397-9.235-13.431-11.29-14.929-11.698-1.498 0.407-6.532 2.463-14.929 11.698-11.951 13.143-25.651 35.731-38.473 69.070-16.299 42.377-29.175 96.867-36.34 159.182h65.976l-64 63.999h-7.114c-0.116 2.47-0.224 4.949-0.322 7.437l-64.536 64.538c-0.174-7.936-0.262-15.927-0.262-23.974 0-16.23 0.358-32.247 1.054-48h-189.809c-2.14 15.697-3.245 31.718-3.245 48 0 33.28 4.619 65.485 13.251 96h106.984l-64 64h-17.852c2.004 3.921 4.079 7.799 6.223 11.631l-46.746 46.746c-39.223-63.475-61.859-138.283-61.859-218.377 0-229.751 186.249-416 416-416zM866.142 293.623l-46.746 46.746c10.56 18.873 19.43 38.819 26.411 59.632h-86.046l-64 63.999h164.992c2.142 15.697 3.247 31.718 3.247 48 0 33.28-4.617 65.485-13.252 96h-183.027c2.799-30.814 4.279-62.959 4.279-96 0-8.047-0.085-16.038-0.26-23.974l-64.538 64.538c-0.751 19.008-2.022 37.517-3.763 55.437h-51.678l-64 64h107.093c-7.369 42.458-17.489 80.081-29.453 111.185-12.821 33.335-26.522 55.923-38.473 69.069-8.397 9.233-13.431 11.29-14.929 11.695-1.498-0.405-6.532-2.462-14.929-11.695-11.951-13.146-25.651-35.733-38.473-69.069-7.177-18.662-13.692-39.676-19.349-62.673l-51.998 52.002c9.327 30.153 20.238 56.853 32.404 79.249-27.964-7.582-54.546-18.526-79.285-32.367l-46.746 46.746c63.347 39.142 137.984 61.769 217.899 61.858h0.956c229.53-0.26 415.522-186.411 415.522-416 0-80.094-22.635-154.903-61.858-218.377zM419.657 172.237c-113.551 30.788-204.311 116.98-241.465 227.764h179.674c10-93.227 32.176-173.254 61.791-227.764zM604.348 851.763c24.393-44.902 43.738-107.119 55.39-179.763h165.879c-44.651 87.347-124.723 153.583-221.269 179.763zM825.374 153.373c12.497-12.497 32.755-12.497 45.252 0s12.497 32.758 0 45.255l-671.999 671.999c-12.497 12.497-32.758 12.497-45.255 0s-12.497-32.755 0-45.252l672.001-672.001z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["directory-disabled"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":394,"id":149,"name":"directory-disabled","prevSize":32,"code":59681},"setIdx":0,"setId":3,"iconIdx":23},{"icon":{"paths":["M864 511.326c0 33.237-4.621 65.399-13.252 95.876h-183.027c2.799-30.78 4.279-62.878 4.279-95.876 0-16.209-0.358-32.205-1.054-47.936h189.807c2.142 15.676 3.247 31.676 3.247 47.936zM606.882 463.39c0.734 15.65 1.118 31.646 1.118 47.936 0 33.353-1.604 65.468-4.561 95.876h-182.876c-2.958-30.409-4.562-62.524-4.562-95.876 0-16.29 0.383-32.286 1.12-47.936h189.762zM666.133 399.476c-9.997-93.104-32.175-173.025-61.79-227.464 113.553 30.747 204.309 116.826 241.463 227.464h-179.674zM419.657 172.012c-29.615 54.438-51.791 134.359-61.791 227.464h-179.674c37.155-110.638 127.914-196.717 241.465-227.464zM422.259 399.476c7.164-62.232 20.041-116.651 36.34-158.972 12.821-33.295 26.522-55.853 38.473-68.979 8.397-9.223 13.431-11.276 14.929-11.683 1.498 0.407 6.532 2.46 14.929 11.683 11.951 13.126 25.651 35.684 38.473 68.979 16.299 42.321 29.175 96.739 36.339 158.972h-179.482zM353.054 463.39c-0.696 15.731-1.054 31.727-1.054 47.936 0 32.998 1.482 65.097 4.282 95.876h-183.031c-8.632-30.477-13.251-62.639-13.251-95.876 0-16.26 1.105-32.26 3.245-47.936h189.809zM364.263 671.117c11.652 72.55 30.999 134.682 55.392 179.524-96.549-26.146-176.621-92.292-221.273-179.524h165.881zM512.478 926.775c229.53-0.256 415.522-186.163 415.522-415.45 0-229.447-186.249-415.451-416-415.451s-416 186.004-416 415.451c0 229.291 185.992 415.194 415.522 415.45 0.158 0.004 0.32 0.004 0.478 0.004s0.32 0 0.478-0.004zM604.348 850.641c24.393-44.843 43.738-106.978 55.39-179.524h165.879c-44.651 87.232-124.723 153.378-221.269 179.524zM594.854 671.117c-7.369 42.398-17.489 79.974-29.453 111.036-12.821 33.293-26.522 55.851-38.473 68.979-8.397 9.22-13.431 11.273-14.929 11.682-1.498-0.41-6.532-2.462-14.929-11.682-11.951-13.129-25.651-35.686-38.473-68.979-11.964-31.061-22.080-68.638-29.453-111.036h165.709z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["directory"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":395,"id":148,"name":"directory","prevSize":32,"code":59682},"setIdx":0,"setId":3,"iconIdx":24},{"icon":{"paths":["M864 512c0 194.402-157.598 352-352 352-194.404 0-352-157.598-352-352 0-194.404 157.596-352 352-352 194.402 0 352 157.596 352 352zM928 512c0-229.751-186.249-416-416-416s-416 186.249-416 416c0 229.751 186.249 416 416 416s416-186.249 416-416zM544 288c0-17.673-14.327-32-32-32s-32 14.327-32 32v224c0 8.486 3.371 16.627 9.374 22.626l96 96c12.497 12.497 32.755 12.497 45.252 0s12.497-32.755 0-45.252l-86.626-86.63v-210.743z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["clock"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":396,"id":147,"name":"clock","prevSize":32,"code":59683},"setIdx":0,"setId":3,"iconIdx":25},{"icon":{"paths":["M577.353 256c0 35.346-28.655 64-64 64s-64-28.654-64-64c0-35.346 28.655-64 64-64s64 28.654 64 64z","M577.353 512c0 35.345-28.655 64-64 64s-64-28.655-64-64c0-35.345 28.655-64 64-64s64 28.655 64 64z","M577.353 768c0 35.345-28.655 64-64 64s-64-28.655-64-64c0-35.345 28.655-64 64-64s64 28.655 64 64z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["kebab"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":397,"id":146,"name":"kebab","prevSize":32,"code":59684},"setIdx":0,"setId":3,"iconIdx":26},{"icon":{"paths":["M512 873.024c-199.389 0-361.026-161.634-361.026-361.024s161.637-361.026 361.026-361.026c199.39 0 361.024 161.637 361.024 361.026s-161.634 361.024-361.024 361.024zM512 938.667c235.639 0 426.667-191.027 426.667-426.667 0-235.642-191.027-426.667-426.667-426.667-235.642 0-426.667 191.025-426.667 426.667 0 235.639 191.025 426.667 426.667 426.667zM544.819 347.898c0 18.126-14.694 32.82-32.819 32.82s-32.819-14.694-32.819-32.82c0-18.127 14.694-32.82 32.819-32.82s32.819 14.694 32.819 32.82zM512 413.539c-18.125 0-32.819 14.694-32.819 32.819v229.747c0 18.125 14.694 32.819 32.819 32.819s32.819-14.694 32.819-32.819v-229.747c0-18.125-14.694-32.819-32.819-32.819z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["info"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":398,"id":145,"name":"info","prevSize":32,"code":59685},"setIdx":0,"setId":3,"iconIdx":27},{"icon":{"paths":["M864 511.326c0-194.147-157.598-351.535-352-351.535-194.404 0-352 157.388-352 351.535 0 194.15 157.596 351.535 352 351.535 194.402 0 352-157.385 352-351.535zM928 511.326c0 229.449-186.249 415.454-416 415.454s-416-186.005-416-415.454c0-229.447 186.249-415.451 416-415.451s416 186.004 416 415.451zM694.259 570.615l-159.97 155.511c-12.425 12.079-32.218 12.079-44.642 0l-159.968-155.511c-12.664-12.309-12.937-32.542-0.61-45.188 12.328-12.651 32.587-12.924 45.251-0.61l105.65 102.707v-275.987c0-17.65 14.327-31.958 32-31.958s32 14.308 32 31.958v275.987l105.647-102.707c12.668-12.314 32.926-12.041 45.252 0.61 12.326 12.646 12.053 32.879-0.61 45.188z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["arrow-down-circle"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":399,"id":144,"name":"arrow-down-circle","prevSize":32,"code":59686},"setIdx":0,"setId":3,"iconIdx":28},{"icon":{"paths":["M512 864c194.402 0 352-157.598 352-352 0-46.519-9.024-90.932-25.417-131.582l48.516-48.518c26.214 54.496 40.9 115.584 40.9 180.1 0 229.751-186.249 416-416 416s-416-186.249-416-416c0-229.751 186.249-416 416-416 95.377 0 183.253 32.096 253.423 86.076l-45.709 45.712c-58.223-42.623-130.031-67.788-207.714-67.788-194.404 0-352 157.596-352 352 0 194.402 157.596 352 352 352zM902.63 230.624c12.497-12.499 12.493-32.76-0.009-45.255-12.497-12.495-32.759-12.491-45.252 0.008l-345.387 345.504-105.339-105.491c-12.488-12.506-32.749-12.52-45.255-0.032-12.506 12.489-12.52 32.747-0.032 45.253l127.971 128.158c6.003 6.007 14.144 9.387 22.635 9.387 8.495 0.004 16.636-3.371 22.643-9.374l368.026-368.156z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["circle-check"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":400,"id":143,"name":"circle-check","prevSize":32,"code":59687},"setIdx":0,"setId":3,"iconIdx":29},{"icon":{"paths":["M512 352.004c17.673 0 32 14.327 32 32v224c0 17.673-14.327 32-32 32s-32-14.327-32-32v-224c0-17.673 14.327-32 32-32z","M512 672.004c17.673 0 32 14.327 32 32s-14.327 32-32 32c-17.673 0-32-14.327-32-32s14.327-32 32-32z","M567.1 158.348c-24.772-41.922-85.427-41.922-110.199 0l-359.921 609.098c-25.21 42.662 5.544 96.559 55.099 96.559h719.845c49.553 0 80.307-53.897 55.095-96.559l-359.919-609.098zM512 190.906l359.923 609.098h-719.845l359.922-609.098z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["warning"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":401,"id":142,"name":"warning","prevSize":32,"code":59688},"setIdx":0,"setId":3,"iconIdx":30},{"icon":{"paths":["M512.606 128.018c-72.375-1.375-144.904 25.78-199.305 80.524-54.654 54.999-89.301 136.056-89.301 239.466 0 80.23 44.5 174.869 97.546 252.804 53.065 77.965 120.83 148.16 176.139 175.821l15.194 7.603 14.81-8.333c217.156-122.15 272.311-333.879 272.311-427.895 0-101.732-27.925-181.775-80.179-236.931-52.343-55.247-125.295-81.503-207.215-83.060zM288 448.009c0-88.591 29.353-152.747 70.699-194.353 41.599-41.862 97.071-62.705 152.691-61.648 68.992 1.311 124.041 23.055 161.971 63.089 38.016 40.126 62.639 102.647 62.639 192.913 0 74.551-44.689 253.679-224.175 363.034-39.684-25.613-92.187-79.855-137.371-146.24-50.954-74.863-86.454-156.22-86.454-216.794zM544 416c0-17.673-14.327-32-32-32s-32 14.327-32 32c0 17.673 14.327 32 32 32s32-14.327 32-32zM608 416c0 53.018-42.982 96-96 96s-96-42.982-96-96c0-53.019 42.982-96 96-96s96 42.981 96 96z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["pin-map"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":402,"id":141,"name":"pin-map","prevSize":32,"code":59689},"setIdx":0,"setId":3,"iconIdx":31},{"icon":{"paths":["M192 736h640v-448h-640v448zM128 256c0-17.673 14.327-32 32-32h704c17.673 0 32 14.327 32 32v512c0 17.673-14.327 32-32 32h-704c-17.673 0-32-14.327-32-32v-512zM305.304 389.082c-14.866-9.557-34.665-5.253-44.222 9.613s-5.253 34.665 9.613 44.223l241.304 155.123 241.306-155.123c14.865-9.557 19.17-29.356 9.613-44.223s-29.355-19.17-44.224-9.613l-206.694 132.876-206.696-132.876z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["mail"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":403,"id":140,"name":"mail","prevSize":32,"code":59690},"setIdx":0,"setId":3,"iconIdx":32},{"icon":{"paths":["M160 224c-35.346 0-64 28.654-64 64v448c0 35.345 28.654 64 64 64h704c35.345 0 64-28.655 64-64v-448c0-35.346-28.655-64-64-64h-704zM160 288h704v448h-704v-448zM256 352c-17.673 0-32 14.327-32 32s14.327 32 32 32h64c17.673 0 32-14.327 32-32s-14.327-32-32-32h-64zM256 512c0-17.673 14.327-32 32-32h64c17.673 0 32 14.327 32 32s-14.327 32-32 32h-64c-17.673 0-32-14.327-32-32zM480 480c-17.673 0-32 14.327-32 32s14.327 32 32 32h64c17.673 0 32-14.327 32-32s-14.327-32-32-32h-64zM640 512c0-17.673 14.327-32 32-32h64c17.673 0 32 14.327 32 32s-14.327 32-32 32h-64c-17.673 0-32-14.327-32-32zM480 352c-17.673 0-32 14.327-32 32s14.327 32 32 32h64c17.673 0 32-14.327 32-32s-14.327-32-32-32h-64zM320 640c0-17.673 14.327-32 32-32h320c17.673 0 32 14.327 32 32s-14.327 32-32 32h-320c-17.673 0-32-14.327-32-32zM704 352c-17.673 0-32 14.327-32 32s14.327 32 32 32h64c17.673 0 32-14.327 32-32s-14.327-32-32-32h-64z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["keyboard"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":404,"id":139,"name":"keyboard","prevSize":32,"code":59691},"setIdx":0,"setId":3,"iconIdx":33},{"icon":{"paths":["M266.667 170.667c0-17.673 14.327-32 32-32h500.621c12.122 0 23.202 6.848 28.625 17.689 5.419 10.841 4.25 23.814-3.025 33.511l-122.133 162.845 122.133 162.843c7.275 9.698 8.444 22.673 3.025 33.51-5.423 10.842-16.503 17.69-28.625 17.69h-468.621v286.579c0 17.673-14.327 32-32 32s-32-14.327-32-32v-682.667zM330.667 502.754h404.621l-98.133-130.843c-8.533-11.378-8.533-27.023 0-38.4l98.133-130.845h-404.621v300.087z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["flag"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":405,"id":138,"name":"flag","prevSize":32,"code":59692},"setIdx":0,"setId":3,"iconIdx":34},{"icon":{"paths":["M354.254 512c-88.366 0-160-71.633-160-160 0-88.366 71.634-160 160-160s159.999 71.634 159.999 160c0 26.934-6.656 52.313-18.411 74.583l11.917 11.915-0.132 0.128 299.136 299.136c3.533 9.924 6.409 20.975 7.74 31.607 1.651 13.218 0.563 22.967-1.877 28.937-1.766 4.335-4.22 7.232-10.769 9.015-8.316 2.261-24.521 2.795-52.821-5.504-8.525-3.806-27.721-16.282-45.133-35.379-18.18-19.938-29.649-41.856-29.649-62.438 0-15.642-11.307-28.992-26.739-31.565l-91.75-15.292c-3.763-2.658-18.765-15.693-10.129-58.867 2.095-10.492-1.186-21.338-8.751-28.902l-88.201-88.196c-26.467 19.379-59.111 30.822-94.429 30.822zM570.423 410.916c5.107-18.773 7.829-38.527 7.829-58.916 0-123.712-100.288-224-223.999-224-123.712 0-224 100.288-224 224s100.288 224 224 224c29.287 0 57.261-5.619 82.904-15.842l43.008 43.008c-7.155 65.493 23.991 104.533 55.97 115.191l2.381 0.794 74.854 12.476c7.083 31.407 25.173 58.125 43.234 77.935 23.125 25.357 50.961 44.629 69.764 52.151l1.323 0.529 1.365 0.41c34.714 10.415 64.73 13.188 89.596 6.426 26.782-7.283 44.331-24.785 53.227-46.583 8.23-20.164 8.474-42.283 6.127-61.065-2.402-19.217-7.898-37.956-14.042-53.312-1.609-4.023-4.019-7.68-7.083-10.743l-286.46-286.458zM386.254 336c0 26.51-21.49 48-48 48s-48-21.49-48-48c0-26.51 21.49-48 48-48s48 21.49 48 48z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["encrypted"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":406,"id":137,"name":"encrypted","prevSize":32,"code":59693},"setIdx":0,"setId":3,"iconIdx":35},{"icon":{"paths":["M694.626 300.76c12.497-12.854 12.497-33.694 0-46.548l-160-164.571c-12.497-12.854-32.755-12.854-45.252 0l-160.001 164.571c-12.497 12.854-12.497 33.694 0 46.548s32.758 12.854 45.255 0l105.373-108.383v430.711c0 18.176 14.327 32.913 32 32.913s32-14.737 32-32.913v-430.711l105.374 108.384c12.497 12.854 32.755 12.854 45.252 0z","M192 384h160v64h-128v416h576v-416h-128v-64h160c17.673 0 32 14.327 32 32v480c0 17.673-14.327 32-32 32h-640c-17.673 0-32-14.327-32-32v-480c0-17.673 14.327-32 32-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["share"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":407,"id":136,"name":"share","prevSize":32,"code":59694},"setIdx":0,"setId":3,"iconIdx":36},{"icon":{"paths":["M273.128 356.679c-6.619 27.765-2.384 63.755 25.498 105.58l21.374 32.060v17.69h-48c-44.011 0-70.483 14.874-86.278 33.621-16.496 19.575-24.573 47.262-23.734 77.491 0.841 30.259 10.601 59.968 25.818 81.31 15.127 21.218 33.403 31.578 52.194 31.578h80v64h-80c-45.209 0-80.933-25.638-104.305-58.423-23.283-32.657-36.523-74.948-37.682-116.689-1.161-41.771 9.763-86.084 38.767-120.508 20.726-24.597 49.155-42.317 84.825-50.782-16.1-39.010-19.009-77.050-10.731-111.77 11.253-47.2 42.304-84.492 80.791-107.342 38.399-22.798 85.676-32.138 131.301-21.965 35.587 7.935 68.909 27.48 95.252 59.554 53.751-35.147 127.582-30.892 182.485-2.495 34.436 17.812 64.794 46.382 81.438 85.009 12.292 28.531 16.435 61.011 10.603 96.206 46.114 6.682 81.51 25.156 105.617 53.453 30.349 35.627 38.106 81.353 33.446 123.285-4.659 41.92-21.948 83.486-46.545 115.115-24.060 30.933-59.354 57.353-101.261 57.353h-80v-64h80c14.093 0 32.802-9.579 50.739-32.644 17.404-22.374 30.114-52.804 33.455-82.889 3.341-30.067-2.901-56.341-18.556-74.718-15.219-17.869-44.032-33.749-97.638-33.749h-45.687l15.616-42.935c13.542-37.252 11.089-66.743 1.434-89.149-9.856-22.872-28.501-41.302-52.062-53.489-49.587-25.649-107.477-18.624-134.716 14.063l-30.135 36.162-22.541-41.324c-19.759-36.22-47.232-54.176-74.872-60.34-28.375-6.327-59.098-0.669-84.699 14.531-25.513 15.148-44.462 38.854-51.209 67.153zM630.98 787.221c12.297-12.689 11.981-32.947-0.708-45.248-12.693-12.301-32.951-11.985-45.252 0.708l-41.020 42.321v-273.003c0-17.673-14.327-32-32-32s-32 14.327-32 32v273.003l-41.020-42.321c-12.301-12.693-32.561-13.009-45.251-0.708s-13.007 32.559-0.707 45.248l95.998 99.051c6.029 6.217 14.319 9.728 22.98 9.728s16.951-3.511 22.98-9.728l96-99.051z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["download"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":408,"id":135,"name":"download","prevSize":32,"code":59695},"setIdx":0,"setId":3,"iconIdx":37},{"icon":{"paths":["M273.128 356.679c-6.619 27.765-2.384 63.755 25.498 105.58l33.166 49.749h-59.792c-44.011 0-70.483 14.874-86.278 33.621-16.496 19.575-24.573 47.262-23.734 77.491 0.841 30.259 10.601 59.968 25.818 81.31 15.127 21.218 33.403 31.578 52.194 31.578h144v64h-144c-45.209 0-80.933-25.638-104.305-58.423-23.283-32.657-36.523-74.948-37.682-116.689-1.161-41.771 9.763-86.084 38.767-120.508 20.726-24.597 49.155-42.317 84.825-50.782-16.1-39.010-19.009-77.050-10.731-111.77 11.253-47.2 42.304-84.492 80.791-107.342 38.399-22.798 85.676-32.138 131.301-21.965 35.587 7.935 68.909 27.48 95.252 59.554 53.751-35.147 127.582-30.892 182.485-2.495 34.436 17.812 64.794 46.382 81.438 85.009 12.292 28.531 16.435 61.011 10.603 96.206 46.114 6.682 81.51 25.156 105.617 53.453 30.349 35.627 38.106 81.353 33.446 123.285-4.659 41.92-21.948 83.486-46.545 115.115-24.060 30.933-59.354 57.353-101.261 57.353h-144v-64h144c14.093 0 32.802-9.579 50.739-32.644 17.404-22.374 30.114-52.804 33.455-82.889 3.341-30.067-2.901-56.341-18.556-74.718-15.219-17.869-44.032-33.749-97.638-33.749h-45.687l15.616-42.935c13.547-37.252 11.089-66.743 1.434-89.149-9.856-22.872-28.501-41.302-52.062-53.489-49.587-25.649-107.477-18.624-134.716 14.063l-30.135 36.162-22.541-41.324c-19.759-36.22-47.232-54.176-74.872-60.34-28.375-6.327-59.098-0.669-84.699 14.531-25.513 15.148-44.462 38.854-51.209 67.153zM630.98 588.779l-96-99.051c-6.029-6.217-14.319-9.728-22.98-9.728s-16.951 3.511-22.98 9.728l-95.998 99.051c-12.3 12.689-11.983 32.947 0.707 45.248s32.951 11.985 45.251-0.708l41.020-42.321v273.003c0 17.673 14.327 32 32 32s32-14.327 32-32v-273.003l41.020 42.321c12.301 12.693 32.559 13.009 45.252 0.708 12.689-12.301 13.005-32.559 0.708-45.248z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["upload"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":409,"id":134,"name":"upload","prevSize":32,"code":59696},"setIdx":0,"setId":3,"iconIdx":38},{"icon":{"paths":["M444.156 742.626c-12.497-12.497-12.497-32.755 0-45.252l185.374-185.374-185.374-185.373c-12.497-12.497-12.497-32.758 0-45.255s32.759-12.497 45.257 0l208 208.001c12.497 12.497 12.497 32.755 0 45.252l-208 208c-12.497 12.497-32.759 12.497-45.257 0z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["chevron-right"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":410,"id":133,"name":"chevron-right","prevSize":32,"code":59697},"setIdx":0,"setId":3,"iconIdx":39},{"icon":{"paths":["M593.822 281.373c12.497 12.497 12.497 32.758 0 45.255l-185.372 185.373 185.372 185.374c12.497 12.497 12.497 32.755 0 45.252s-32.755 12.497-45.252 0l-208.002-208c-12.497-12.497-12.497-32.755 0-45.252l208.002-208.001c12.497-12.497 32.755-12.497 45.252 0z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["chevron-left"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":411,"id":132,"name":"chevron-left","prevSize":32,"code":59698},"setIdx":0,"setId":3,"iconIdx":40},{"icon":{"paths":["M746.236 587.959c-12.497 12.497-32.759 12.497-45.257 0l-185.374-185.371-185.371 185.371c-12.497 12.497-32.758 12.497-45.255 0s-12.497-32.755 0-45.252l208-208.001c12.497-12.497 32.759-12.497 45.257 0l208 208.001c12.497 12.497 12.497 32.755 0 45.252z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["chevron-up"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":412,"id":131,"name":"chevron-up","prevSize":32,"code":59699},"setIdx":0,"setId":3,"iconIdx":41},{"icon":{"paths":["M282.726 436.041c12.497-12.498 32.758-12.498 45.255 0l185.372 185.37 185.374-185.37c12.497-12.498 32.755-12.498 45.252 0s12.497 32.755 0 45.252l-208 208c-12.497 12.497-32.755 12.497-45.252 0l-208.001-208c-12.497-12.497-12.497-32.755 0-45.252z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["chevron-down"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":413,"id":130,"name":"chevron-down","prevSize":32,"code":59700},"setIdx":0,"setId":3,"iconIdx":42},{"icon":{"paths":["M697.698 626.56c12.676-12.314 32.934-12.023 45.252 0.649 12.314 12.676 12.023 32.934-0.649 45.252l-208 202.121c-12.42 12.066-32.183 12.066-44.604 0l-207.999-202.121c-12.675-12.318-12.965-32.576-0.649-45.252 12.317-12.672 32.576-12.962 45.25-0.649l185.699 180.45 185.698-180.45zM697.698 416.798c12.676 12.317 32.934 12.027 45.252-0.649 12.314-12.675 12.023-32.934-0.649-45.25l-208-202.119c-12.42-12.067-32.183-12.067-44.604 0l-207.999 202.119c-12.675 12.316-12.965 32.576-0.649 45.25 12.316 12.676 32.576 12.966 45.25 0.649l185.699-180.449 185.698 180.449z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["order"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":414,"id":129,"name":"order","prevSize":32,"code":59701},"setIdx":0,"setId":3,"iconIdx":43},{"icon":{"paths":["M930.253 512c0 229.751-186.249 416-416 416-229.749 0-415.999-186.249-415.999-416s186.249-416 415.999-416c229.751 0 416 186.249 416 416zM570.039 859.605l-41.83-156.105c-4.608 0.333-9.263 0.499-13.956 0.499-4.57 0-9.101-0.158-13.594-0.474l-41.835 156.134c18.057 2.854 36.57 4.339 55.428 4.339 18.982 0 37.615-1.502 55.787-4.395zM438.443 688.452c-47.551-20.459-85.181-59.571-103.675-108.126l-155.028 41.54c33.967 103.484 114.617 185.805 217.044 222.054l41.659-155.469zM162.254 512c0 16.090 1.079 31.927 3.17 47.445l156.904-42.044c-0.049-1.796-0.074-3.597-0.074-5.402 0-4.911 0.184-9.779 0.546-14.596l-156.051-41.813c-2.958 18.368-4.495 37.21-4.495 56.41zM395.858 180.407c-99.159 35.408-177.785 114.033-213.195 213.191l155.535 41.675c19.356-44.352 54.982-79.977 99.336-99.331l-41.676-155.535zM514.253 160c-19.196 0-38.037 1.537-56.401 4.495l41.813 156.051c4.817-0.361 9.681-0.546 14.588-0.546 5.030 0 10.018 0.194 14.95 0.573l41.805-156.022c-18.475-2.995-37.431-4.552-56.755-4.552zM632.064 843.802c102.656-36.45 183.39-119.194 217.092-223.121l-154.974-41.523c-18.291 48.981-56.009 88.491-103.787 109.15l41.668 155.494zM863.249 558.199c1.984-15.121 3.004-30.541 3.004-46.199 0-18.769-1.468-37.197-4.297-55.172l-156.156 41.843c0.299 4.403 0.452 8.849 0.452 13.329 0 1.378-0.013 2.752-0.043 4.122l157.039 42.078zM846.263 394.775c-35.166-99.601-113.886-178.641-213.278-214.248l-41.681 155.559c44.587 19.556 80.311 55.564 99.507 100.343l155.452-41.653zM642.253 512c0-70.694-57.306-128-128-128-70.69 0-127.999 57.306-127.999 128s57.309 128 127.999 128c70.694 0 128-57.306 128-128z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["support"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":415,"id":128,"name":"support","prevSize":32,"code":59702},"setIdx":0,"setId":3,"iconIdx":44},{"icon":{"paths":["M336 128c17.673 0 32 14.327 32 32v144h288v-144c0-17.673 14.327-32 32-32s32 14.327 32 32v144h144c17.673 0 32 14.327 32 32s-14.327 32-32 32h-144v288h144c17.673 0 32 14.327 32 32s-14.327 32-32 32h-144v144c0 17.673-14.327 32-32 32s-32-14.327-32-32v-144h-288v144c0 17.673-14.327 32-32 32s-32-14.327-32-32v-144h-144c-17.673 0-32-14.327-32-32s14.327-32 32-32h144v-288h-144c-17.673 0-32-14.327-32-32s14.327-32 32-32h144v-144c0-17.673 14.327-32 32-32zM368 368v288h288v-288h-288z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["channel-public"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":416,"id":127,"name":"channel-public","prevSize":32,"code":59703},"setIdx":0,"setId":3,"iconIdx":45},{"icon":{"paths":["M138.667 213.333c0-17.673 14.327-32 32-32h234.057c7.183 0 14.156 2.416 19.798 6.86l88.814 69.94h339.998c17.673 0 32 14.327 32 32v520.533c0 17.673-14.327 32-32 32h-682.667c-17.673 0-32-14.327-32-32v-597.333zM202.667 245.333v533.333h618.667v-456.533h-319.087c-7.181 0-14.153-2.416-19.797-6.86l-88.813-69.94h-190.97z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["folder"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":417,"id":126,"name":"folder","prevSize":32,"code":59704},"setIdx":0,"setId":3,"iconIdx":46},{"icon":{"paths":["M160 800c-11.706 0-22.478-6.391-28.087-16.666s-5.161-22.793 1.169-32.64l112.304-174.694h-69.387c-17.673 0-32-14.327-32-32v-288c0-17.673 14.327-32 32-32h256c17.673 0 32 14.327 32 32v288c0 6.135-1.762 12.143-5.082 17.306l-144.001 224c-5.888 9.156-16.029 14.694-26.918 14.694h-128zM330.918 561.306l-112.304 174.694h51.916l129.47-201.399v-246.601h-192v224h96c11.706 0 22.478 6.391 28.087 16.666s5.161 22.793-1.169 32.64zM576 800c-11.708 0-22.477-6.391-28.087-16.666s-5.158-22.793 1.169-32.64l112.307-174.694h-69.389c-17.673 0-32-14.327-32-32v-288c0-17.673 14.327-32 32-32h256c17.673 0 32 14.327 32 32v288c0 6.135-1.762 12.143-5.082 17.306l-144 224c-5.888 9.156-16.030 14.694-26.918 14.694h-128zM746.918 561.306l-112.307 174.694h51.917l129.472-201.399v-246.601h-192v224h96c11.708 0 22.477 6.391 28.087 16.666s5.158 22.793-1.169 32.64z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["quote"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":418,"id":125,"name":"quote","prevSize":32,"code":59705},"setIdx":0,"setId":3,"iconIdx":47},{"icon":{"paths":["M321.626 430.882l224.49 224.491-126.12 126.118-224.49-224.491 126.12-126.118zM366.881 385.626l192.116-192.116 224.491 224.49-192.115 192.116-224.492-224.49zM581.623 125.628c-12.497-12.497-32.759-12.497-45.257 0l-408.743 408.747c-12.497 12.497-12.497 32.755 0 45.252l269.745 269.747c5.23 5.231 11.82 8.269 18.631 9.122v0.068h0.571c2.276 0.243 4.573 0.243 6.85 0h440.579c17.673 0 32-14.327 32-32s-14.327-32-32-32h-366.566l353.937-353.937c12.497-12.497 12.497-32.757 0-45.254l-269.747-269.745z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["prune"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":419,"id":124,"name":"prune","prevSize":32,"code":59706},"setIdx":0,"setId":3,"iconIdx":48},{"icon":{"paths":["M536.845 548.215h-255.502c-20.173 0-36.527-16.354-36.527-36.527s16.354-36.527 36.527-36.527h102.99c-21.546-22.75-32.32-50.118-32.32-82.102 0-39.587 15.766-72.27 47.297-98.048 31.764-26.008 72.959-39.012 123.596-39.012 34.526 0 65.25 6.675 92.177 20.024 27.162 13.349 48.107 31.762 62.835 55.238 8.849 13.888 15.083 28.54 18.697 43.958 4.198 17.914-11.17 33.030-29.572 33.030-18.398 0-32.499-15.279-37.828-32.89-4.617-15.263-12.779-28.121-24.486-38.574-19.332-17.492-46.609-26.238-81.822-26.238-32.683 0-58.231 7.25-76.642 21.75-18.185 14.27-27.275 34.179-27.275 59.726 0 20.484 8.629 37.86 25.892 52.132 13.764 11.046 35.012 21.385 63.744 31.006h247.556c20.173 0 36.527 16.354 36.527 36.527s-16.354 36.527-36.527 36.527h-90.027c7.138 7.215 13.133 14.878 17.975 22.989 11.511 18.871 17.263 41.079 17.263 66.628 0 40.738-15.881 73.421-47.642 98.048-31.761 24.397-74.227 36.595-127.394 36.595-34.522 0-66.743-6.558-96.666-19.678-29.921-13.35-53.052-31.531-69.393-54.549-9.777-13.965-16.588-29.077-20.432-45.338-4.233-17.903 11.182-33.028 29.581-33.028s32.466 15.364 38.446 32.764c5.318 15.475 14.771 28.604 28.356 39.39 22.558 17.493 52.591 26.236 90.108 26.236 34.987 0 61.798-7.134 80.439-21.402 18.645-14.272 27.968-33.719 27.968-58.347s-8.631-43.614-25.894-56.964c-14.332-11.273-38.34-22.387-72.026-33.344z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["strike"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":420,"id":123,"name":"strike","prevSize":32,"code":59707},"setIdx":0,"setId":3,"iconIdx":49},{"icon":{"paths":["M388.508 320c0-17.673-14.327-32-32-32s-32 14.327-32 32v256c0 106.039 85.961 192 192.002 192 106.035 0 192-85.961 192-192v-256c0-17.673-14.327-32-32-32-17.677 0-32 14.327-32 32v256c0 70.694-57.31 128-128 128-70.694 0-128.002-57.306-128.002-128v-256zM356.508 848c-17.673 0-32 14.327-32 32s14.327 32 32 32h320.002c17.673 0 32-14.327 32-32s-14.327-32-32-32h-320.002z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["underline"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":421,"id":122,"name":"underline","prevSize":32,"code":59708},"setIdx":0,"setId":3,"iconIdx":50},{"icon":{"paths":["M546.253 352c17.673 0 32-14.327 32-32s-14.327-32-32-32c-17.673 0-32 14.327-32 32s14.327 32 32 32zM561.865 436.996c2.756-17.457-9.161-33.844-26.62-36.6-17.455-2.756-33.843 9.161-36.599 26.616l-48 304c-2.756 17.459 9.161 33.843 26.62 36.599 17.455 2.756 33.843-9.161 36.599-26.615l48-304z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["italic"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":422,"id":121,"name":"italic","prevSize":32,"code":59709},"setIdx":0,"setId":3,"iconIdx":51},{"icon":{"paths":["M384 775.415c-17.673 0-32-14.327-32-32v-453.166c0-17.673 14.327-32 32-32h137.075c56.119 0 98.27 11.603 126.447 34.81 28.416 23.206 42.624 57.542 42.624 103.007 0 24.153-6.865 45.585-20.599 64.29-13.734 18.47-32.444 32.798-56.124 42.978 27.942 7.817 49.967 22.733 66.069 44.757 16.337 21.786 24.508 47.834 24.508 78.144 0 46.409-15.036 82.876-45.111 109.397-30.071 26.522-72.576 39.782-127.514 39.782h-147.375zM420.198 533.53v186.121h112.598c31.731 0 56.713-8.171 74.944-24.508 18.47-16.576 27.708-39.309 27.708-68.198 0-62.276-33.865-93.414-101.585-93.414h-113.664zM420.198 478.827h103.006c29.837 0 53.636-7.458 71.394-22.379 17.997-14.916 26.995-35.163 26.995-60.737 0-28.416-8.286-49.017-24.862-61.804-16.576-13.024-41.796-19.536-75.657-19.536h-100.877v164.456z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["bold"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":423,"id":120,"name":"bold","prevSize":32,"code":59710},"setIdx":0,"setId":3,"iconIdx":52},{"icon":{"paths":["M639.172 204.798c16.495 6.344 24.725 24.859 18.381 41.354l-213.333 554.667c-6.345 16.495-24.861 24.725-41.356 18.381s-24.724-24.862-18.38-41.357l213.335-554.666c6.34-16.495 24.858-24.724 41.353-18.38zM330.312 361.371c12.497 12.497 12.497 32.758 0 45.255l-105.373 105.374 105.373 105.37c12.497 12.497 12.497 32.759 0 45.257s-32.758 12.497-45.255 0l-128-128c-12.497-12.497-12.497-32.759 0-45.257l128-127.999c12.497-12.497 32.758-12.497 45.255 0zM711.723 361.371c12.497-12.497 32.759-12.497 45.257 0l128 127.999c12.497 12.497 12.497 32.759 0 45.257l-128 128c-12.497 12.497-32.759 12.497-45.257 0s-12.497-32.759 0-45.257l105.374-105.37-105.374-105.374c-12.497-12.497-12.497-32.758 0-45.255z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["code"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":424,"id":119,"name":"code","prevSize":32,"code":59711},"setIdx":0,"setId":3,"iconIdx":53},{"icon":{"paths":["M769.293 649.374c12.497 12.497 12.497 32.755 0 45.252l-192 192c-12.497 12.497-32.755 12.497-45.252 0l-192.001-192c-12.497-12.497-12.497-32.755 0-45.252s32.758-12.497 45.255 0l137.373 137.37v-578.743h-192v192c0 17.673-14.327 32-32 32s-32-14.327-32-32v-224c0-17.673 14.327-32 32-32h256c17.673 0 32 14.327 32 32v610.743l137.374-137.37c12.497-12.497 32.755-12.497 45.252 0z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["jump-to-message"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":425,"id":118,"name":"jump-to-message","prevSize":32,"code":59712},"setIdx":0,"setId":3,"iconIdx":54},{"icon":{"paths":["M385 769.293c-12.497 12.497-32.758 12.497-45.255 0l-192-192c-12.497-12.497-12.497-32.755 0-45.252l192-192.001c12.497-12.497 32.758-12.497 45.255 0s12.497 32.758 0 45.255l-137.373 137.373h578.745v-192h-192c-17.673 0-32-14.327-32-32s14.327-32 32-32h224c17.673 0 32 14.327 32 32v256c0 17.673-14.327 32-32 32h-610.745l137.373 137.374c12.497 12.497 12.497 32.755 0 45.252z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["arrow-return"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":426,"id":117,"name":"arrow-return","prevSize":32,"code":59713},"setIdx":0,"setId":3,"iconIdx":55},{"icon":{"paths":["M385 297.373c-12.497-12.497-32.758-12.497-45.255 0l-192 192.001c-12.497 12.497-12.497 32.755 0 45.252l192 192c12.497 12.497 32.758 12.497 45.255 0s12.497-32.755 0-45.252l-137.373-137.374h578.745v128c0 17.673 14.327 32 32 32s32-14.327 32-32v-160c0-17.673-14.327-32-32-32h-610.745l137.373-137.373c12.497-12.497 12.497-32.758 0-45.255z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["arrow-back"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":427,"id":116,"name":"arrow-back","prevSize":32,"code":59714},"setIdx":0,"setId":3,"iconIdx":56},{"icon":{"paths":["M307.745 105.235c12.497-12.48 32.758-12.48 45.255 0s12.497 32.715 0 45.195l-105.373 105.233h610.745c17.673 0 32 14.308 32 31.958v111.852c0 17.65-14.327 31.959-32 31.959s-32-14.309-32-31.959v-79.894h-578.745l105.373 105.233c12.497 12.482 12.497 32.715 0 45.195s-32.758 12.48-45.255 0l-160-159.788c-12.497-12.48-12.497-32.715 0-45.195l160-159.789zM720.998 917.414c-12.497 12.48-32.755 12.48-45.252 0s-12.497-32.713 0-45.193l105.37-105.233h-610.743c-17.673 0-32-14.31-32-31.957v-111.855c0-17.647 14.327-31.957 32-31.957s32 14.31 32 31.957v79.898h578.743l-105.37-105.237c-12.497-12.48-12.497-32.713 0-45.193s32.755-12.48 45.252 0l160 159.787c12.497 12.48 12.497 32.717 0 45.197l-160 159.787z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["arrow-looping"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":428,"id":115,"name":"arrow-looping","prevSize":32,"code":59715},"setIdx":0,"setId":3,"iconIdx":57},{"icon":{"paths":["M276.48 157.44c0-16.259 13.181-29.44 29.44-29.44s29.44 13.181 29.44 29.44v58.877h353.28v-58.877c0-16.259 13.18-29.44 29.44-29.44s29.44 13.181 29.44 29.44v58.877h85.76c17.673 0 32 14.327 32 32v583.679c0 17.673-14.327 32-32 32h-642.56c-17.673 0-32-14.327-32-32v-583.679c0-1.105 0.056-2.196 0.165-3.272 1.639-16.136 15.267-28.728 31.835-28.728h85.76v-58.877zM801.28 392.957h-578.56v407.039h578.56v-407.039zM423.68 644.476c0-8.836 7.163-16 16-16h26.88c8.836 0 16 7.164 16 16v26.88c0 8.836-7.164 16-16 16h-26.88c-8.836 0-16-7.164-16-16v-26.88zM321.92 510.72c-8.836 0-16 7.164-16 16v26.88c0 8.836 7.164 16 16 16h26.88c8.837 0 16-7.164 16-16v-26.88c0-8.836-7.163-16-16-16h-26.88zM541.44 526.72c0-8.836 7.164-16 16-16h26.88c8.836 0 16 7.164 16 16v26.88c0 8.836-7.164 16-16 16h-26.88c-8.836 0-16-7.164-16-16v-26.88zM321.92 628.476c-8.836 0-16 7.164-16 16v26.88c0 8.836 7.164 16 16 16h26.88c8.837 0 16-7.164 16-16v-26.88c0-8.836-7.163-16-16-16h-26.88zM541.44 644.476c0-8.836 7.164-16 16-16h26.88c8.836 0 16 7.164 16 16v26.88c0 8.836-7.164 16-16 16h-26.88c-8.836 0-16-7.164-16-16v-26.88zM439.68 510.72c-8.836 0-16 7.164-16 16v26.88c0 8.836 7.164 16 16 16h26.88c8.836 0 16-7.164 16-16v-26.88c0-8.836-7.164-16-16-16h-26.88zM659.2 526.72c0-8.836 7.164-16 16-16h26.88c8.836 0 16 7.164 16 16v26.88c0 8.836-7.164 16-16 16h-26.88c-8.836 0-16-7.164-16-16v-26.88zM675.2 628.476c-8.836 0-16 7.164-16 16v26.88c0 8.836 7.164 16 16 16h26.88c8.836 0 16-7.164 16-16v-26.88c0-8.836-7.164-16-16-16h-26.88z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["calendar"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":429,"id":114,"name":"calendar","prevSize":32,"code":59716},"setIdx":0,"setId":3,"iconIdx":58},{"icon":{"paths":["M774.426 576c-35.345 0-64-28.655-64-64s28.655-64 64-64c35.345 0 64 28.655 64 64s-28.655 64-64 64z","M518.426 576c-35.345 0-64-28.655-64-64s28.655-64 64-64c35.345 0 64 28.655 64 64s-28.655 64-64 64z","M262.426 576c-35.346 0-64-28.655-64-64s28.654-64 64-64c35.346 0 64 28.655 64 64s-28.654 64-64 64z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["meatballs"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":430,"id":113,"name":"meatballs","prevSize":32,"code":59717},"setIdx":0,"setId":3,"iconIdx":59},{"icon":{"paths":["M521.357 195.096l224.171 259.701v365.751c0 5.85-4.749 10.59-10.607 10.59h-136.235v-149.623c0-23.394-18.987-42.355-42.411-42.355h-85.841c-23.424 0-42.415 18.961-42.415 42.355v149.623h-136.229c-5.856 0-10.603-4.74-10.603-10.59v-365.824l224.105-259.628c4.233-4.9 11.836-4.9 16.064 0zM559.834 894.673h175.087c40.994 0 74.223-33.186 74.223-74.125v-243.883h56.154c12.437 0 23.735-7.241 28.919-18.534 5.18-11.294 3.294-24.567-4.826-33.975l-319.846-370.544c-29.611-34.302-82.829-34.302-112.435 0l-319.848 370.544c-8.122 9.408-10.007 22.682-4.825 33.975s16.48 18.534 28.918 18.534h56.214v243.883c0 40.939 33.231 74.125 74.223 74.125h175.085c1.173 0.098 2.359 0.149 3.558 0.149h85.841c1.199 0 2.385-0.051 3.558-0.149z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["home"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":431,"id":112,"name":"home","prevSize":32,"code":59718},"setIdx":0,"setId":3,"iconIdx":60},{"icon":{"paths":["M832 512c0 176.73-143.27 320-320 320-176.731 0-320-143.27-320-320h-64c0 212.079 171.923 384 384 384 212.079 0 384-171.921 384-384 0-212.077-171.921-384-384-384-123.718 0-233.772 58.508-304 149.364v-101.364c0-17.673-14.327-32-32-32s-32 14.327-32 32v192c0 17.673 14.327 32 32 32h176c17.673 0 32-14.327 32-32s-14.327-32-32-32h-107.295c57.239-86.755 155.582-144 267.295-144 176.73 0 320 143.269 320 320z","M544 320c0-17.673-14.327-32-32-32s-32 14.327-32 32v224c0 8.486 3.371 16.627 9.374 22.626l96 96c12.497 12.497 32.755 12.497 45.252 0s12.497-32.755 0-45.252l-86.626-86.63v-210.743z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["history"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":432,"id":111,"name":"history","prevSize":32,"code":59719},"setIdx":0,"setId":3,"iconIdx":61},{"icon":{"paths":["M854.507 233.251c12.561 12.43 12.672 32.691 0.243 45.254l-474.877 480.001c-6.013 6.076-14.208 9.498-22.757 9.493s-16.743-3.426-22.752-9.506l-165.124-167.091c-12.423-12.57-12.303-32.828 0.268-45.252s32.832-12.305 45.254 0.269l142.376 144.068 452.113-456.993c12.429-12.564 32.691-12.672 45.257-0.243z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["check"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":433,"id":110,"name":"check","prevSize":32,"code":59720},"setIdx":0,"setId":3,"iconIdx":62},{"icon":{"paths":["M711.113 512v54.818c-0.196 76.634-43.682 143.091-107.298 176.209-5.525-25.634-28.326-44.847-55.612-44.847h-72.405c-31.42 0-56.888 25.472-56.888 56.892v41.374c0 31.415 25.469 56.887 56.888 56.887h72.405c28.471 0 52.062-20.919 56.235-48.226 69.167-26.795 123.797-82.773 148.77-152.828 4.715 1.267 9.677 1.941 14.793 1.941h28.446c31.415 0 56.887-25.468 56.887-56.887v-85.333c0-31.42-25.472-56.887-56.887-56.887h-28.446v-28.446c0-141.385-114.615-256-256-256s-256 114.615-256 256v23.275h-28.445c-31.419 0-56.889 25.468-56.889 56.887v103.433c0 31.42 25.47 56.892 56.889 56.892h28.445c31.419 0 56.889-25.472 56.889-56.892v-36.203h0.149c-0.099-2.573-0.148-5.158-0.148-7.757v-139.636c0-109.966 89.145-199.111 199.11-199.111s199.113 89.145 199.113 199.111v85.333z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["omnichannel"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":434,"id":109,"name":"omnichannel","prevSize":32,"code":59721},"setIdx":0,"setId":3,"iconIdx":63},{"icon":{"paths":["M512 554.018c66.466 0 120.346-52.493 120.346-117.239 0-64.753-53.879-117.243-120.346-117.243s-120.347 52.491-120.347 117.243c0 64.747 53.881 117.239 120.347 117.239zM512 490.018c-32.708 0-56.346-25.404-56.346-53.239 0-27.84 23.637-53.243 56.346-53.243 32.704 0 56.346 25.403 56.346 53.243 0 27.836-23.642 53.239-56.346 53.239z","M364.125 894.144h-172.125c-17.673 0-32-14.327-32-32v-702.144c0-17.673 14.327-32 32-32h640c17.673 0 32 14.327 32 32v702.144c0 17.673-14.327 32-32 32h-172.126c-6.242 1.276-12.702 1.946-19.319 1.946h-257.109c-6.618 0-13.079-0.67-19.32-1.946zM224 830.144h68.244c-3.114-9.455-4.799-19.558-4.799-30.054v-93.449c0-56.107 37.881-105.143 92.172-119.309 19.171-5.005 39.265-5.312 58.583-0.9l42.773 9.766c20.049 4.578 40.909 4.254 60.813-0.939l28.070-7.326c20.693-5.397 42.381-5.73 63.232-0.973 60.531 13.824 103.467 67.665 103.467 129.758v83.371c0 10.496-1.685 20.599-4.8 30.054h68.245v-638.144h-576v638.144zM651.567 830.144c12.245-4.489 20.988-16.252 20.988-30.054v-83.371c0-32.235-22.289-60.186-53.713-67.362-10.825-2.47-22.084-2.3-32.828 0.503l-28.070 7.326c-29.85 7.791-61.141 8.273-91.217 1.404l-42.775-9.766c-9.29-2.121-18.955-1.971-28.175 0.435-26.112 6.814-44.331 30.396-44.331 57.382v93.449c0 13.803 8.74 25.566 20.989 30.054h279.133z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["avatar"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":435,"id":108,"name":"avatar","prevSize":32,"code":59722},"setIdx":0,"setId":3,"iconIdx":64},{"icon":{"paths":["M651.358 116.071c-57.242-19.989-105.788-20.069-138.355-20.071l-0.004 64-0.998-64c-92.005 0.342-297.345 47.824-381.242 242.996-17.897 38.968-34.758 103.342-34.758 173.004 0 69.961 17.020 146.283 52.216 207.876 23.229 40.653 92.798 131.375 191.178 173.538 94.863 40.653 206.368 52.343 296.488 16.299 16.41-6.566 24.393-25.19 17.83-41.596-6.566-16.41-25.19-24.393-41.596-17.83-69.879 27.955-163.174 20.446-247.512-15.701-80.82-34.637-141.385-112.448-160.822-146.462-28.804-50.406-43.784-115.418-43.784-176.124 0-60.766 15.020-116.183 29.055-146.59l0.184-0.4 0.174-0.404c69.507-162.182 243.825-204.605 323.586-204.605 31.599 0.002 70.882 0.296 117.261 16.493 46.144 16.113 101.389 48.779 161.822 116.767 43.657 49.114 63.535 114.976 69.389 177.712 5.892 63.121-2.85 118.187-11.541 142.093-6.404 17.6-20.429 45.44-59.392 45.7-18.261-0.806-72.823-14.673-83.123-69.568v-235.063c0-17.673-3.413-34.133-29.013-34.133-19.337 0-26.453 16.46-26.453 34.133v34.133c-35.183-39.86-95.403-68.267-152.747-68.267-106.039 0-192 85.961-192 192s85.961 192 192 192c62.178 0 117.658-29.555 152.747-75.388 25.711 71.078 102.571 93.030 137.011 94.135l0.516 0.017h0.512c82.645 0 111.714-64.806 120.085-87.829 12.642-34.761 21.675-99.695 15.125-169.907-6.592-70.597-29.38-151.402-85.278-214.288-66.906-75.265-131.076-114.598-188.561-134.67zM627.2 512c0 70.694-57.306 128-128 128s-128-57.306-128-128c0-70.694 57.306-128 128-128s128 57.306 128 128z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["mention"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":436,"id":107,"name":"mention","prevSize":32,"code":59723},"setIdx":0,"setId":3,"iconIdx":65},{"icon":{"paths":["M370.254 544c0-17.673-14.327-32-32-32s-32 14.327-32 32v32h-32c-17.673 0-32 14.327-32 32s14.327 32 32 32h32v32c0 17.673 14.327 32 32 32s32-14.327 32-32v-32h32c17.673 0 31.999-14.327 31.999-32s-14.326-32-31.999-32h-32v-32z","M746.253 624c30.929 0 56-25.071 56-56s-25.071-56-56-56c-30.925 0-56 25.071-56 56s25.075 56 56 56z","M674.253 664c0 30.929-25.071 56-56 56-30.925 0-56-25.071-56-56s25.075-56 56-56c30.929 0 56 25.071 56 56z","M706.253 128c0-17.673-14.327-32-32-32s-32 14.327-32 32v96h-128c-17.673 0-32 14.327-32 32v96h-191.999c-106.039 0-192 85.961-192 192v128c0 106.039 85.961 192 192 192h447.999c106.039 0 192-85.961 192-192v-128c0-106.039-85.961-192-192-192h-192v-64h128c17.673 0 32-14.327 32-32v-128zM866.253 544v128c0 70.694-57.306 128-128 128h-447.999c-70.693 0-128-57.306-128-128v-128c0-70.694 57.307-128 128-128h447.999c70.694 0 128 57.306 128 128z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["game"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":437,"id":106,"name":"game","prevSize":32,"code":59724},"setIdx":0,"setId":3,"iconIdx":66},{"icon":{"paths":["M550.037 242.504c0.192-17.672 14.669-31.845 32.341-31.657s31.846 14.668 31.659 32.34l-1.318 123.488 193.438-193.438c12.497-12.497 32.755-12.497 45.252 0s12.497 32.758 0 45.255l-193.438 193.438 123.49-1.319c17.673-0.189 32.149 13.984 32.337 31.658 0.192 17.673-13.982 32.149-31.654 32.337l-201.92 2.159c-8.606 0.090-16.887-3.285-22.972-9.374-6.084-6.084-9.459-14.362-9.37-22.967l2.155-201.921zM474.628 782.148c-0.192 17.673-14.669 31.846-32.341 31.659-17.672-0.192-31.845-14.669-31.656-32.341l1.318-123.49-193.438 193.438c-12.497 12.497-32.758 12.497-45.255 0s-12.497-32.755 0-45.252l193.438-193.438-123.488 1.318c-17.672 0.188-32.151-13.986-32.34-31.659s13.984-32.149 31.657-32.337l201.919-2.159c8.606-0.090 16.887 3.285 22.972 9.37 6.084 6.089 9.463 14.366 9.37 22.972l-2.155 201.92z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["arrow-collapse"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":438,"id":105,"name":"arrow-collapse","prevSize":32,"code":59725},"setIdx":0,"setId":3,"iconIdx":67},{"icon":{"paths":["M858.624 398.148c-0.188 17.672-14.669 31.847-32.337 31.655-17.673-0.188-31.846-14.666-31.659-32.338l1.318-123.488-193.438 193.437c-12.497 12.497-32.759 12.497-45.257 0s-12.497-32.755 0-45.254l193.442-193.439-123.49 1.319c-17.673 0.189-32.154-13.984-32.341-31.657s13.986-32.151 31.659-32.34l201.92-2.156c8.606-0.092 16.883 3.286 22.967 9.37s9.463 14.365 9.374 22.969l-2.159 201.921zM166.041 626.517c0.189-17.673 14.668-31.842 32.34-31.654s31.845 14.669 31.657 32.341l-1.319 123.486 193.438-193.438c12.497-12.497 32.759-12.497 45.257 0s12.497 32.759 0 45.257l-193.44 193.438 123.488-1.318c17.672-0.192 32.153 13.982 32.341 31.654s-13.985 32.154-31.657 32.341l-201.921 2.155c-8.605 0.094-16.884-3.285-22.969-9.37s-9.463-14.366-9.37-22.967l2.156-201.924z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["arrow-expand"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":439,"id":104,"name":"arrow-expand","prevSize":32,"code":59726},"setIdx":0,"setId":3,"iconIdx":68},{"icon":{"paths":["M586.372 672c-17.673 0-32 14.327-32 32s14.327 32 32 32h224c17.673 0 32-14.327 32-32v-208c0-17.673-14.327-32-32-32s-32 14.327-32 32v130.743l-233.374-233.371c-12.497-12.497-32.755-12.497-45.252 0l-73.374 73.371-169.373-169.371c-12.497-12.497-32.758-12.497-45.255 0s-12.497 32.758 0 45.255l192 191.999c12.497 12.497 32.756 12.497 45.254 0l73.374-73.37 210.743 210.743h-146.743z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["arrow-decrease"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":440,"id":103,"name":"arrow-decrease","prevSize":32,"code":59727},"setIdx":0,"setId":3,"iconIdx":69},{"icon":{"paths":["M584.115 352c-17.673 0-32-14.327-32-32s14.327-32 32-32h224c17.677 0 32 14.327 32 32v208c0 17.673-14.323 32-32 32-17.673 0-32-14.327-32-32v-130.745l-233.37 233.371c-12.497 12.497-32.759 12.497-45.257 0l-73.372-73.37-169.373 169.37c-12.497 12.497-32.758 12.497-45.255 0s-12.497-32.755 0-45.252l192-192c12.497-12.497 32.759-12.497 45.256 0l73.37 73.37 210.748-210.743h-146.748z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["arrow-increase"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":441,"id":102,"name":"arrow-increase","prevSize":32,"code":59728},"setIdx":0,"setId":3,"iconIdx":70},{"icon":{"paths":["M498.697 141.563l-298.668 136.533c-11.39 5.207-18.696 16.58-18.696 29.103v386.846c0 11.819 6.513 22.673 16.941 28.233l298.668 159.292c9.408 5.018 20.706 5.018 30.114 0l298.667-159.292c10.428-5.559 16.943-16.414 16.943-28.233v-386.846c0-12.524-7.305-23.896-18.697-29.103l-298.667-136.533c-8.448-3.862-18.159-3.862-26.607 0zM245.333 357.014l234.667 107.276v335.71l-234.667-125.154v-317.832zM544 800l234.667-125.154v-317.832l-234.667 107.276v335.71zM512 408.548l-221.699-101.348 221.699-101.348 221.7 101.348-221.7 101.348z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["apps"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":442,"id":101,"name":"apps","prevSize":32,"code":59729},"setIdx":0,"setId":3,"iconIdx":71},{"icon":{"paths":["M129.353 351.541c0-17.65 14.327-31.958 32-31.958h704c17.673 0 32 14.308 32 31.958s-14.327 31.958-32 31.958h-704c-17.673 0-32-14.308-32-31.958zM214.686 521.984c0-17.651 14.327-31.957 32-31.957h533.333c17.673 0 32 14.306 32 31.957s-14.327 31.957-32 31.957h-533.333c-17.673 0-32-14.306-32-31.957zM332.019 660.467c-17.673 0-32 14.306-32 31.957 0 17.647 14.327 31.957 32 31.957h362.667c17.673 0 32-14.31 32-31.957 0-17.651-14.327-31.957-32-31.957h-362.667z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["donner"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":443,"id":100,"name":"donner","prevSize":32,"code":59730},"setIdx":0,"setId":3,"iconIdx":72},{"icon":{"paths":["M192 181.333c-53.019 0-96 42.981-96 96v469.333c0 53.018 42.981 96 96 96h640c53.018 0 96-42.982 96-96v-469.333c0-53.019-42.982-96-96-96h-640zM160 277.333c0-17.673 14.327-32 32-32h640c17.673 0 32 14.327 32 32v202.671h-704v-202.671zM160 544.004h704v202.662c0 17.673-14.327 32-32 32h-640c-17.673 0-32-14.327-32-32v-202.662zM810.667 661.333c0-35.345-28.655-64-64-64s-64 28.655-64 64c0 35.345 28.655 64 64 64s64-28.655 64-64z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["card"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":444,"id":99,"name":"card","prevSize":32,"code":59731},"setIdx":0,"setId":3,"iconIdx":73},{"icon":{"paths":["M192 405.333h213.333v-213.333h-213.333v213.333zM128 170.667c0-23.564 19.103-42.667 42.667-42.667h256c23.565 0 42.667 19.103 42.667 42.667v256c0 23.565-19.102 42.667-42.667 42.667h-256c-23.564 0-42.667-19.102-42.667-42.667v-256zM618.667 405.333h213.333v-213.333h-213.333v213.333zM554.667 170.667c0-23.564 19.102-42.667 42.667-42.667h256c23.565 0 42.667 19.103 42.667 42.667v256c0 23.565-19.102 42.667-42.667 42.667h-256c-23.565 0-42.667-19.102-42.667-42.667v-256zM618.667 618.667h213.333v213.333h-213.333v-213.333zM597.333 554.667c-23.565 0-42.667 19.102-42.667 42.667v256c0 23.565 19.102 42.667 42.667 42.667h256c23.565 0 42.667-19.102 42.667-42.667v-256c0-23.565-19.102-42.667-42.667-42.667h-256zM192 832h213.333v-213.333h-213.333v213.333zM128 597.333c0-23.565 19.103-42.667 42.667-42.667h256c23.565 0 42.667 19.102 42.667 42.667v256c0 23.565-19.102 42.667-42.667 42.667h-256c-23.564 0-42.667-19.102-42.667-42.667v-256z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["squares"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":445,"id":98,"name":"squares","prevSize":32,"code":59732},"setIdx":0,"setId":3,"iconIdx":74},{"icon":{"paths":["M694.626 473.374c12.497 12.497 12.497 32.755 0 45.252s-32.755 12.497-45.252 0l-105.374-105.371v418.745c0 17.673-14.327 32-32 32s-32-14.327-32-32v-418.745l-105.373 105.371c-12.497 12.497-32.758 12.497-45.255 0s-12.497-32.755 0-45.252l160.001-160.001c12.497-12.497 32.755-12.497 45.252 0l160 160.001zM912 160c0-17.673-14.327-32-32-32h-768c-17.673 0-32 14.327-32 32v512c0 17.673 14.327 32 32 32h96c17.673 0 32-14.327 32-32s-14.327-32-32-32h-64v-448h704v448h-64c-17.673 0-32 14.327-32 32s14.327 32 32 32h96c17.673 0 32-14.327 32-32v-512z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["arrow-up-box"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":446,"id":97,"name":"arrow-up-box","prevSize":32,"code":59733},"setIdx":0,"setId":3,"iconIdx":75},{"icon":{"paths":["M329.373 550.626c-12.497-12.497-12.497-32.755 0-45.252s32.758-12.497 45.255 0l105.373 105.37v-418.743c0-17.673 14.327-32 32-32s32 14.327 32 32v418.743l105.374-105.37c12.497-12.497 32.755-12.497 45.252 0s12.497 32.755 0 45.252l-160 160c-12.497 12.497-32.755 12.497-45.252 0l-160.001-160zM112 864c0 17.673 14.327 32 32 32h768c17.673 0 32-14.327 32-32v-512c0-17.673-14.327-32-32-32h-96c-17.673 0-32 14.327-32 32s14.327 32 32 32h64v448h-704v-448h64c17.673 0 32-14.327 32-32s-14.327-32-32-32h-96c-17.673 0-32 14.327-32 32v512z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["arrow-down-box"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":447,"id":96,"name":"arrow-down-box","prevSize":32,"code":59734},"setIdx":0,"setId":3,"iconIdx":76},{"icon":{"paths":["M128 192c-17.673 0-32 14.327-32 32v576.021c0 17.673 14.327 32 32 32h768c17.673 0 32-14.327 32-32v-576.021c0-17.673-14.327-32-32-32h-768zM160 378.302v-122.302h149.333v122.302h-149.333zM160 442.304h149.333v141.722h-149.333v-141.722zM160 648.026h149.333v119.996h-149.333v-119.996zM373.333 768.021v-119.996h490.667v119.996h-490.667zM864 584.026h-490.667v-141.722h490.667v141.722zM864 378.302h-490.667v-122.302h490.667v122.302z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["file-sheet"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":448,"id":95,"name":"file-sheet","prevSize":32,"code":59735},"setIdx":0,"setId":3,"iconIdx":77},{"icon":{"paths":["M905.088 512c0-194.404-157.598-352-352-352-194.405 0-352.001 157.596-352.001 352 0 194.402 157.596 352 352.001 352 194.402 0 352-157.598 352-352zM969.088 512c0 229.751-186.249 416-416 416s-416.001-186.249-416.001-416c0-229.751 186.25-416 416.001-416s416 186.249 416 416zM441.088 383.995v256.001c0 17.673 14.323 32 32 32 17.673 0 32-14.327 32-32v-256.001c0-17.673-14.327-32-32-32-17.677 0-32 14.327-32 32zM601.084 383.995v256.001c0 17.673 14.327 32 32 32s32-14.327 32-32v-256.001c0-17.673-14.327-32-32-32s-32 14.327-32 32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["pause"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":449,"id":94,"name":"pause","prevSize":32,"code":59736},"setIdx":0,"setId":3,"iconIdx":78},{"icon":{"paths":["M512.674 928c229.751 0 416-186.249 416-416s-186.249-416-416-416c-229.749 0-415.998 186.249-415.998 416s186.249 416 415.998 416zM400.675 383.995c0-17.673 14.327-32 32-32s32 14.327 32 32v256.001c0 17.673-14.327 32-32 32s-32-14.327-32-32v-256.001zM560.674 383.995c0-17.673 14.327-32 32-32s32 14.327 32 32v256.001c0 17.673-14.327 32-32 32s-32-14.327-32-32v-256.001z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["pause-filled"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":450,"id":93,"name":"pause-filled","prevSize":32,"code":59737},"setIdx":0,"setId":3,"iconIdx":79},{"icon":{"paths":["M512.678 928.004c229.747 0 416-186.249 416-416 0-229.749-186.253-415.999-416-415.999-229.752 0-416.001 186.25-416.001 415.999 0 229.751 186.249 416 416.001 416zM452.523 357.193l195.255 136.768c14.208 9.95 18.496 30.874 9.583 46.729-2.432 4.322-5.709 7.979-9.583 10.692l-195.255 136.768c-14.204 9.95-32.95 5.163-41.866-10.692-3.036-5.397-4.646-11.644-4.646-18.018v-273.536c0-18.72 13.597-33.897 30.372-33.897 5.709 0 11.307 1.798 16.141 5.186z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["play-filled"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":451,"id":92,"name":"play-filled","prevSize":32,"code":59738},"setIdx":0,"setId":3,"iconIdx":80},{"icon":{"paths":["M230.487 636.693c-14.92-9.472-34.694-5.056-44.167 9.865-9.473 14.916-5.058 34.692 9.862 44.164l298.665 189.632c10.47 6.647 23.838 6.647 34.304 0l298.667-189.632c14.921-9.472 19.337-29.248 9.865-44.164-9.472-14.921-29.248-19.337-44.169-9.865l-281.515 178.739-281.513-178.739zM186.32 494.852c9.473-14.921 29.247-19.337 44.167-9.86l281.513 178.739 281.515-178.739c14.921-9.476 34.697-5.060 44.169 9.86s5.056 34.697-9.865 44.169l-298.667 189.628c-10.466 6.647-23.834 6.647-34.304 0l-298.665-189.628c-14.92-9.472-19.336-29.248-9.862-44.169zM529.152 143.663l298.667 189.63c9.25 5.871 14.848 16.062 14.848 27.015s-5.598 21.144-14.848 27.015l-298.667 189.629c-10.466 6.647-23.834 6.647-34.304 0l-298.665-189.629c-9.246-5.871-14.848-16.062-14.848-27.015s5.602-21.144 14.848-27.015l298.665-189.63c10.47-6.647 23.838-6.647 34.304 0zM273.035 360.307l238.965 151.723 238.967-151.723-238.967-151.725-238.965 151.725z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["queue"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":452,"id":91,"name":"queue","prevSize":32,"code":59739},"setIdx":0,"setId":3,"iconIdx":81},{"icon":{"paths":["M512 928c-14.217 0-28.275-0.713-42.142-2.112-16.695-1.681-30.558-12.531-36.689-27.392l-40.54-98.308-98.161 40.841c-14.837 6.174-32.3 4.045-45.292-6.554-21.839-17.818-41.831-37.811-59.65-59.648-10.601-12.992-12.726-30.455-6.553-45.295l40.839-98.159-98.307-40.542c-14.864-6.127-25.714-19.994-27.395-36.689-1.396-13.867-2.111-27.925-2.111-42.142s0.714-28.275 2.11-42.142c1.681-16.695 12.531-30.558 27.395-36.685l98.307-40.543-40.84-98.163c-6.173-14.836-4.047-32.3 6.553-45.292 17.818-21.838 37.81-41.83 59.648-59.648 12.992-10.601 30.455-12.726 45.292-6.554l98.163 40.84 40.54-98.309c6.131-14.865 19.994-25.714 36.689-27.395 13.867-1.396 27.925-2.111 42.142-2.111s28.275 0.714 42.142 2.111c16.695 1.681 30.558 12.53 36.689 27.395l40.542 98.309 98.163-40.84c14.835-6.173 32.299-4.047 45.291 6.554 21.837 17.818 41.83 37.81 59.648 59.648 10.598 12.992 12.723 30.455 6.554 45.292l-40.841 98.163 98.308 40.543c14.861 6.127 25.711 19.994 27.392 36.685 1.399 13.867 2.112 27.925 2.112 42.142s-0.713 28.275-2.112 42.142c-1.681 16.695-12.531 30.562-27.392 36.689l-98.308 40.542 40.836 98.159c6.174 14.839 4.049 32.303-6.549 45.295-17.822 21.837-37.811 41.83-59.652 59.648-12.992 10.598-30.455 12.727-45.291 6.554l-98.159-40.841-40.542 98.308c-6.131 14.861-19.994 25.711-36.689 27.392-13.867 1.399-27.925 2.112-42.142 2.112zM444.454 757.982l43.383 105.203c7.979 0.542 16.034 0.815 24.162 0.815s16.183-0.273 24.162-0.815l43.383-105.203c9.455-22.921 35.733-33.805 58.628-24.282l105.054 43.708c12.156-10.598 23.578-22.020 34.18-34.176l-43.708-105.058c-9.527-22.895 1.357-49.173 24.282-58.624l105.203-43.383c0.542-7.983 0.815-16.038 0.815-24.166 0-8.124-0.273-16.183-0.815-24.162l-105.203-43.383c-22.925-9.455-33.809-35.731-24.282-58.625l43.708-105.058c-10.603-12.156-22.020-23.577-34.176-34.177l-105.058 43.709c-22.895 9.525-49.173-1.359-58.628-24.283l-43.383-105.204c-7.979-0.54-16.038-0.815-24.162-0.815s-16.183 0.275-24.162 0.815l-43.383 105.204c-9.455 22.924-35.732 33.809-58.627 24.283l-105.058-43.709c-12.156 10.6-23.577 22.022-34.177 34.177l43.709 105.058c9.525 22.895-1.359 49.17-24.283 58.625l-105.203 43.383c-0.54 7.979-0.815 16.038-0.815 24.162 0 8.128 0.275 16.183 0.815 24.166l105.202 43.383c22.924 9.451 33.809 35.729 24.283 58.624l-43.708 105.058c10.601 12.156 22.022 23.578 34.179 34.176l105.056-43.708c22.895-9.523 49.172 1.361 58.627 24.282zM416 512c0-53.018 42.982-96 96-96s96 42.982 96 96c0 53.018-42.982 96-96 96s-96-42.982-96-96zM512 352c-88.366 0-160 71.634-160 160 0 88.367 71.634 160 160 160 88.367 0 160-71.633 160-160 0-88.366-71.633-160-160-160z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["administration"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":453,"id":90,"name":"administration","prevSize":32,"code":59740},"setIdx":0,"setId":3,"iconIdx":82},{"icon":{"paths":["M561.668 127.99c-121.698 0-200.973 50.509-248.815 115.801-46.216 63.073-61.638 137.752-61.933 188.615-8.705 98.748 28.601 172.898 89.423 223.471 59.685 49.626 140.202 75.26 217.847 83.738 77.751 8.486 161.715 1.195 227.857-12.548 33.067-6.869 62.775-15.578 85.641-25.331 11.366-4.847 22.029-10.368 30.797-16.67 7.876-5.662 18.543-14.976 23.245-28.834 7.283-21.474-3.136-38.784-11.968-48.102-8.41-8.879-19.426-15.403-28.237-20.015-9.306-4.868-19.379-9.207-27.533-12.71-8.977-3.853-14.861-6.396-18.56-8.431-4.847-2.662-8.845-5.086-12.028-7.202 20.254-47.142 31.548-77.043 37.696-99.191 7.292-26.27 7.313-41.723 7.313-58.907 0-21.523-9.6-88.542-52.809-151.109-44.702-64.73-124.070-122.573-257.937-122.573zM314.916 433.894c0-40.414 12.606-101.841 49.562-152.276 35.783-48.835 95.882-89.628 197.19-89.628 112.085 0 172.087 46.886 205.274 94.94 34.679 50.219 41.472 104.040 41.472 114.741v0.2c0.004 14.918 0.004 23.638-4.979 41.594-5.491 19.776-16.964 50.189-41.54 106.534-5.798 13.295-2.761 25.771 1.156 33.754 3.665 7.479 9.003 13.244 13.329 17.263 8.836 8.213 20.655 15.684 32.226 22.046 6.618 3.635 15.236 7.334 22.562 10.475l1.562 0.67c5.905 2.539 11.52 4.971 16.687 7.42-0.909 0.41-1.856 0.823-2.833 1.237-17.741 7.569-43.081 15.206-73.557 21.542-60.945 12.663-138.065 19.209-207.885 11.584-69.926-7.633-136.986-30.336-183.881-69.325-45.46-37.798-73.674-92.066-66.481-169.822l0.136-1.472v-1.476zM819.162 553.348l-0.073-0.081c0 0 0.009 0.009 0.026 0.034 0.013 0.013 0.026 0.030 0.047 0.047z","M178.552 502.468c7.496-11.255 16.26-22.259 26.436-32.589 0.876 31.744 6.169 61.227 15.216 88.358-15.094 30.878-18.374 59.315-18.374 65.357v0.188c-0 11.379-0 17.532 3.523 30.699 3.993 14.916 12.441 38.212 30.867 82.022 5.256 12.497 2.48 24.098-0.985 31.428-3.249 6.874-7.925 12.058-11.511 15.514-7.319 7.057-16.852 13.257-25.751 18.33-5.008 2.854-11.333 5.705-16.546 8.026 11.182 3.942 24.979 7.817 40.803 11.226 44.976 9.694 101.833 14.673 153.062 8.87 51.281-5.807 99.779-23.014 133.353-51.964l0.606-0.525c14.793 2.782 29.53 4.937 44.053 6.519 10.88 1.19 21.858 2.091 32.875 2.722-10.121 14.797-22.165 28.045-35.742 39.753-46.362 39.974-108.544 60.365-167.945 67.089-59.451 6.729-123.406 0.947-173.745-9.899-25.169-5.427-48.056-12.352-65.902-20.245-8.86-3.917-17.457-8.503-24.686-13.892-6.431-4.791-15.831-13.171-20.001-25.92-6.422-19.631 2.792-35.443 10.458-43.831 7.193-7.872 16.405-13.461 23.247-17.173 7.309-3.968 15.158-7.467 21.235-10.176 6.906-3.076 10.854-4.855 13.183-6.182 1.35-0.768 2.59-1.502 3.727-2.197-13.937-33.886-21.975-56.119-26.479-72.947-5.68-21.222-5.7-33.873-5.7-47.433 0-17.711 7.436-71.138 40.721-121.126zM155.337 797.244c-0.012 0.004 0.084 0.107 0.317 0.303-0.19-0.205-0.306-0.303-0.317-0.303zM179.587 737.084c-0.003 0-0.052 0.051-0.137 0.149l0.112-0.119c0.019-0.021 0.027-0.030 0.025-0.030z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["discussions"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":454,"id":89,"name":"discussions","prevSize":32,"code":59741},"setIdx":0,"setId":3,"iconIdx":83},{"icon":{"paths":["M223.311 308.609c-47.831 66.699-64.077 147.668-64.077 201.185v1.404l-0.127 1.399c-9.348 103.236 27.547 175.996 86.848 226.377 60.643 51.516 146.604 80.998 235.291 90.893 88.61 9.886 186.223 1.399 263.339-14.976 38.562-8.188 70.929-18.121 93.888-28.126 8.909-3.883 15.838-7.535 20.945-10.765-2.377-1.515-5.248-3.196-8.678-5.030-8.883-4.749-19.055-9.263-29.611-13.897l-1.843-0.806c-9.314-4.083-19.725-8.649-27.61-13.077-14.293-8.030-28.318-17.156-38.545-26.867-5.035-4.783-10.761-11.196-14.596-19.183-4.058-8.457-6.959-21.082-1.259-34.436 30.814-72.188 45.457-111.727 52.548-137.835 6.622-24.38 6.622-36.655 6.622-56.171v-0.179c0-15.514-8.977-86.595-53.777-152.876-43.371-64.175-121.395-125.729-264.828-125.729-129.727 0-207.831 53.576-254.531 118.696zM173.267 272.433c58.132-81.062 154.749-144.433 304.574-144.433 164.894 0 261.594 72.589 315.857 152.878 52.838 78.182 64.414 161.879 64.414 187.641 0 21.658-0.017 40.337-8.794 72.64-7.834 28.834-22.626 68.617-50.048 133.423 5.069 4.036 12.591 9.003 22.507 14.571 5.12 2.876 12.992 6.34 24.055 11.191 10.261 4.51 22.579 9.933 33.89 15.979 10.846 5.798 23.526 13.572 32.951 23.74 9.86 10.633 20.211 28.868 12.817 51.136-4.873 14.673-16.183 25.092-25.609 32.017-10.24 7.522-22.946 14.281-36.86 20.343-27.947 12.177-64.585 23.181-105.681 31.906-82.197 17.451-186.522 26.688-282.906 15.936-96.311-10.743-195.347-43.174-268.314-105.165-74.031-62.891-119.295-154.778-108.551-277.854 0.276-63.411 19.118-157.053 75.696-235.949zM333.953 422.052c0-17.648 14.25-31.955 31.828-31.955h183.011c17.574 0 31.825 14.307 31.825 31.955s-14.251 31.955-31.825 31.955h-183.011c-17.578 0-31.828-14.306-31.828-31.955zM365.781 539.708c-17.578 0-31.828 14.306-31.828 31.957 0 17.647 14.25 31.953 31.828 31.953h224.12c17.579 0 31.825-14.306 31.825-31.953 0-17.651-14.246-31.957-31.825-31.957h-224.12z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["threads"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":455,"id":88,"name":"threads","prevSize":32,"code":59742},"setIdx":0,"setId":3,"iconIdx":84},{"icon":{"paths":["M877.402 153.128c-12.497-12.497-32.759-12.497-45.257 0l-668.244 668.244c-12.497 12.497-12.497 32.759 0 45.257s32.758 12.497 45.255 0l668.246-668.246c12.497-12.497 12.497-32.758 0-45.255zM309.94 170.672c-23.564 0-42.667 14.327-42.667 32s19.103 32 42.667 32h255.999c23.565 0 42.667-14.327 42.667-32s-19.102-32-42.667-32h-255.999zM585.446 309.329h-403.506c-41.237 0-74.667 33.429-74.667 74.667v384c0 6.012 0.71 11.853 2.051 17.455l61.949-61.952v-339.503c0-5.891 4.776-10.667 10.667-10.667h339.506l64-64zM387.612 778.662h306.327c5.892 0 10.667-4.774 10.667-10.667v-85.333c0-11.375 6.037-21.897 15.859-27.631 9.822-5.739 21.952-5.833 31.859-0.243l97.83 55.164c2.53 1.425 4.855 3.191 6.908 5.244 6.72 6.72 18.21 1.963 18.21-7.539v-263.322c0-9.502-11.49-14.263-18.206-7.543-2.057 2.057-4.382 3.819-6.912 5.248l-97.83 55.164c-9.907 5.585-22.037 5.495-31.859-0.243s-15.859-16.256-15.859-27.631v-7.663l110.78-73.495c47.42-41.99 123.887-8.7 123.887 56.164v263.322c0 64.862-76.467 98.155-123.887 56.162l-46.78-26.377v30.554c0 41.237-33.429 74.667-74.667 74.667h-370.327l64-64z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["camera-disabled"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":456,"id":87,"name":"camera-disabled","prevSize":32,"code":59743},"setIdx":0,"setId":3,"iconIdx":85},{"icon":{"paths":["M312.195 170.672c-23.564 0-42.667 14.327-42.667 32s19.102 32 42.667 32h256.001c23.565 0 42.667-14.327 42.667-32s-19.102-32-42.667-32h-256.001z","M559.241 503.454c11.268-11.268 11.191-29.611-0.171-40.973-11.362-11.358-29.705-11.435-40.969-0.171l-71.403 71.403-71.997-71.996c-11.36-11.362-29.704-11.435-40.971-0.171-11.267 11.268-11.191 29.611 0.17 40.973l71.997 71.996-71.402 71.403c-11.267 11.264-11.191 29.606 0.17 40.969s29.704 11.439 40.971 0.171l71.404-71.403 71.996 71.996c11.358 11.362 29.705 11.439 40.969 0.171 11.268-11.264 11.191-29.611-0.171-40.969l-71.996-71.996 71.403-71.403z","M109.529 383.995c0-41.237 33.429-74.667 74.667-74.667h512.001c41.237 0 74.667 33.429 74.667 74.667v30.553l46.78-26.377c47.415-41.99 123.887-8.7 123.887 56.164v263.322c0 64.862-76.471 98.155-123.887 56.162l-46.78-26.377v30.554c0 41.237-33.429 74.667-74.667 74.667h-512.001c-41.237 0-74.667-33.429-74.667-74.667v-384.001zM184.195 373.328c-5.891 0-10.667 4.776-10.667 10.667v384.001c0 5.888 4.776 10.667 10.667 10.667h512.001c5.888 0 10.667-4.779 10.667-10.667v-85.333c0-11.375 6.037-21.897 15.859-27.631 9.822-5.739 21.948-5.833 31.859-0.243l97.826 55.164c2.534 1.425 4.855 3.191 6.912 5.244 6.72 6.72 18.21 1.963 18.21-7.539v-263.322c0-9.502-11.49-14.263-18.21-7.543-2.052 2.057-4.378 3.819-6.912 5.248l-97.826 55.164c-9.911 5.585-22.037 5.491-31.859-0.243-9.822-5.739-15.859-16.256-15.859-27.631v-85.334c0-5.891-4.779-10.667-10.667-10.667h-512.001z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["camera-unavailable"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":457,"id":86,"name":"camera-unavailable","prevSize":32,"code":59744},"setIdx":0,"setId":3,"iconIdx":86},{"icon":{"paths":["M265.018 202.672c0-17.673 19.102-32 42.667-32h256.001c23.565 0 42.667 14.327 42.667 32s-19.102 32-42.667 32h-256.001c-23.564 0-42.667-14.327-42.667-32zM169.018 383.995c0-5.891 4.776-10.667 10.667-10.667h512.001c5.888 0 10.667 4.776 10.667 10.667v85.334c0 11.375 6.037 21.892 15.859 27.631 9.822 5.734 21.948 5.828 31.855 0.243l97.83-55.164c2.534-1.429 4.855-3.191 6.912-5.248 6.72-6.72 18.21-1.958 18.21 7.543v263.322c0 9.502-11.49 14.259-18.21 7.539-2.057-2.052-4.378-3.819-6.912-5.244l-97.83-55.164c-9.907-5.589-22.033-5.495-31.855 0.243-9.822 5.734-15.859 16.256-15.859 27.631v85.333c0 5.888-4.779 10.667-10.667 10.667h-512.001c-5.891 0-10.667-4.779-10.667-10.667v-384.001zM179.685 309.328c-41.237 0-74.667 33.429-74.667 74.667v384.001c0 41.237 33.43 74.667 74.667 74.667h512.001c41.237 0 74.667-33.429 74.667-74.667v-30.554l46.775 26.377c47.42 41.993 123.891 8.7 123.891-56.162v-263.322c0-64.864-76.471-98.155-123.891-56.164l-46.775 26.377v-30.553c0-41.237-33.429-74.667-74.667-74.667h-512.001z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["camera"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":458,"id":85,"name":"camera","prevSize":32,"code":59745},"setIdx":0,"setId":3,"iconIdx":87},{"icon":{"paths":["M317.754 661.342h-118.99v-298.665h118.99l12.367-48.047c11.845-46.020 53.696-79.953 103.308-79.953h64v554.665h-64c-49.613 0-91.464-33.933-103.308-79.949l-12.367-48.051zM177.431 725.342h90.71c18.946 73.613 85.766 128 165.288 128h85.333c23.565 0 42.667-19.102 42.667-42.667v-597.332c0-23.564-19.102-42.667-42.667-42.667h-85.333c-79.522 0-146.342 54.391-165.288 128h-90.71c-23.564 0-42.667 19.103-42.667 42.667v341.332c0 23.565 19.103 42.667 42.667 42.667zM893.393 393.373c12.497 12.497 12.497 32.758 0 45.254l-73.374 73.374 73.374 73.374c12.497 12.497 12.497 32.755 0 45.252s-32.759 12.497-45.257 0l-73.374-73.37-73.37 73.37c-12.497 12.497-32.759 12.497-45.257 0s-12.497-32.755 0-45.252l73.374-73.374-73.374-73.374c-12.497-12.495-12.497-32.757 0-45.254s32.759-12.497 45.257 0l73.37 73.371 73.374-73.371c12.497-12.497 32.759-12.497 45.257 0z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["audio-unavailable"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":459,"id":84,"name":"audio-unavailable","prevSize":32,"code":59746},"setIdx":0,"setId":3,"iconIdx":88},{"icon":{"paths":["M870.639 153.127c-12.497-12.497-32.759-12.497-45.257 0l-668.244 668.244c-12.497 12.497-12.497 32.759 0 45.257s32.758 12.497 45.255 0l668.246-668.246c12.497-12.497 12.497-32.758 0-45.255zM679.155 480.358l55.919-55.923c16.256 79.564 14.515 161.864-5.231 240.844l-11.622 46.485c-4.284 17.148-21.658 27.571-38.805 23.283-17.143-4.284-27.567-21.658-23.283-38.805l11.622-46.485c13.875-55.509 17.677-112.875 11.401-169.399zM821.675 385.922l-11.315-36.77 51.204-51.206 21.278 69.154c33.344 108.369 31.996 224.448-3.857 332.010l-33.451 100.343c-5.589 16.764-23.71 25.826-40.474 20.237-16.768-5.589-25.83-23.71-20.241-40.478l33.446-100.339c31.637-94.912 32.828-197.333 3.409-292.952zM495.177 664.333l64-64v210.342c0 23.565-19.102 42.667-42.667 42.667h-85.333c-35.46 0-68.394-10.812-95.684-29.325l46.611-46.609c14.701 7.629 31.395 11.934 49.073 11.934h64v-125.009zM132.51 682.675c0 19.742 13.403 36.348 31.604 41.22l62.552-62.554h-30.156v-298.665h118.991l12.367-48.047c11.845-46.020 53.695-79.953 103.309-79.953h64v158.156l64-64v-115.49c0-23.564-19.102-42.667-42.667-42.667h-85.333c-79.523 0-146.343 54.391-165.289 128h-90.71c-23.564 0-42.667 19.103-42.667 42.667v341.332z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["audio-disabled"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":460,"id":83,"name":"audio-disabled","prevSize":32,"code":59747},"setIdx":0,"setId":3,"iconIdx":89},{"icon":{"paths":["M300.099 631.121h-113.433v-280.89h113.433l12.367-48.048c11.055-42.953 50.122-74.619 96.423-74.619h58.665v526.223h-58.665c-46.301 0-85.367-31.667-96.423-74.62l-12.367-48.047zM163.555 695.121h86.931c18.156 70.541 82.193 122.667 158.403 122.667h81.778c22.583 0 40.887-18.308 40.887-40.892v-572.443c0-22.582-18.304-40.889-40.887-40.889h-81.778c-76.21 0-140.246 52.124-158.403 122.667h-86.931c-22.582 0-40.889 18.307-40.889 40.889v327.11c0 22.583 18.307 40.892 40.889 40.892zM646.46 316.516c17.148-4.286 34.522 6.138 38.805 23.284l11.14 44.551c20.804 83.229 20.804 170.303 0 253.529l-11.14 44.553c-4.284 17.148-21.658 27.571-38.805 23.283-17.143-4.284-27.571-21.658-23.283-38.805l11.14-44.553c18.257-73.037 18.257-149.444 0-222.484l-11.14-44.551c-4.288-17.146 6.14-34.519 23.283-38.806zM807.475 235.938c-5.201-16.892-23.108-26.372-39.996-21.175-16.892 5.198-26.372 23.104-21.175 39.996l35.533 115.49c28.117 91.37 26.978 189.239-3.251 279.931l-32.055 96.158c-5.589 16.768 3.473 34.889 20.237 40.478 16.768 5.589 34.889-3.473 40.478-20.237l32.055-96.162c34.449-103.343 35.746-214.869 3.708-318.99l-35.533-115.49z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["audio"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":461,"id":82,"name":"audio","prevSize":32,"code":59748},"setIdx":0,"setId":3,"iconIdx":90},{"icon":{"paths":["M439.275 704.371c0-33.643 26.278-47.676 72.725-47.676s72.73 14.033 72.73 47.676c0 32.96-13.193 111.070-23.915 149.764-4.962 17.805-22.076 25.169-48.815 25.169-26.735 0-43.853-7.364-48.815-25.173-10.714-38.665-23.91-116.689-23.91-149.76zM616.781 870.374l0.021-0.094c6.178-22.289 12.57-53.862 17.387-83.447 4.685-28.791 8.721-60.71 8.721-82.462 0-35.891-15.812-67.802-46.797-87.113-26.035-16.226-57.152-19.925-84.113-19.925-26.957 0-58.078 3.699-84.113 19.925-30.982 19.311-46.795 51.221-46.795 87.113 0 21.807 4.036 53.73 8.726 82.517 4.819 29.577 11.21 61.12 17.381 83.392l0.024 0.085c7.401 26.556 24.983 45.666 46.871 56.469 19.473 9.609 40.427 11.831 57.907 11.831 17.485 0 38.434-2.223 57.907-11.831 21.888-10.799 39.471-29.905 46.874-56.461zM459.635 460.8c0-28.275 23.445-51.2 52.365-51.2s52.365 22.925 52.365 51.2c0 28.275-23.445 51.2-52.365 51.2s-52.365-22.925-52.365-51.2zM512 341.333c-67.477 0-122.182 53.487-122.182 119.467s54.704 119.467 122.182 119.467c67.477 0 122.18-53.487 122.18-119.467s-54.703-119.467-122.18-119.467zM677.803 537.254c-6.665 13.79-3.883 31.108 6.276 42.573 14.084 15.893 39.851 17.937 50.206-0.606 19.639-35.17 30.805-75.52 30.805-118.421 0-136.672-113.314-247.467-253.090-247.467-139.779 0-253.092 110.795-253.092 247.467 0 42.901 11.164 83.251 30.806 118.421 10.355 18.543 36.119 16.499 50.205 0.606 10.16-11.465 12.939-28.783 6.275-42.573-11.203-23.189-17.469-49.105-17.469-76.454 0-98.97 82.054-179.2 183.274-179.2 101.218 0 183.27 80.23 183.27 179.2 0 27.349-6.263 53.265-17.468 76.454zM730.159 699.793c-0.303-10.658 3.546-21.069 10.931-28.762 52.77-54.955 85.090-128.9 85.090-210.231 0-169.662-140.663-307.2-314.18-307.2s-314.182 137.538-314.182 307.2c0 81.331 32.323 155.277 85.094 210.231 7.386 7.693 11.234 18.103 10.928 28.762-0.832 29.018-31.273 47.915-52.121 27.716-70.223-68.041-113.718-162.406-113.718-266.709 0-207.365 171.923-375.467 384-375.467 212.079 0 384 168.102 384 375.467 0 104.303-43.494 198.673-113.719 266.709-20.851 20.203-51.29 1.306-52.122-27.716z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["live-streaming"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":462,"id":81,"name":"live-streaming","prevSize":32,"code":59749},"setIdx":0,"setId":3,"iconIdx":91},{"icon":{"paths":["M680.55 256c0-17.673-14.327-32-32-32s-32 14.327-32 32v56.876l-80.346 13.999c-17.412 3.034-29.069 19.607-26.035 37.018s19.61 29.066 37.022 26.032l69.359-12.085v69.371c-30.383 6.852-60.459 20.075-84.151 43.14-27.925 27.183-44.075 65.242-44.075 113.809 0 25.741 6.263 48.26 18.453 66.62 12.186 18.351 29.065 30.682 47.253 37.999 35.354 14.225 76.719 10.176 108.126-4.578l1.207-0.567c31.125-14.618 62.494-29.35 90.722-57.818 21.325-21.504 39.71-49.536 56.849-88.674 5.653 9.498 9.591 20.966 10.287 34.338 1.63 31.526-14.281 82.812-87.957 153.417-12.762 12.228-13.193 32.486-0.964 45.244 12.228 12.762 32.486 13.193 45.244 0.964 80.196-76.851 110.588-145.033 107.593-202.935-2.987-57.655-38.588-96.021-70.677-113.954-20.774-13.013-50.214-22.827-81.216-28.288-16.623-2.931-34.47-4.749-52.693-4.996v-74.242l101.717-17.723c17.412-3.034 29.069-19.607 26.035-37.018s-19.61-29.066-37.018-26.032l-90.735 15.809v-45.724zM577.041 536.209c10.163-9.894 23.565-17.476 39.509-22.703v138.65c-13.444 2.547-27.486 1.732-38.635-2.752-7.71-3.102-13.658-7.757-17.822-14.029-4.156-6.259-7.77-15.996-7.77-31.215 0-33.348 10.564-54.174 24.717-67.951zM708.642 600.751c-8.683 8.755-17.783 15.706-28.092 22.076v-117.888c14.127 0.239 28.224 1.66 41.587 4.015 13.589 2.394 25.681 5.623 35.763 9.165-16.879 42.039-33.067 66.304-49.259 82.633zM246.351 565.333h98.385l-49.193-184.882-49.193 184.882zM389.497 733.559l-27.732-104.226h-132.443l-27.732 104.226c-4.544 17.079-22.073 27.243-39.152 22.699s-27.241-22.076-22.696-39.151l106.323-399.601c13.494-50.714 85.464-50.713 98.957 0l106.323 399.601c4.544 17.075-5.615 34.607-22.694 39.151s-34.609-5.619-39.153-22.699z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["language"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":463,"id":80,"name":"language","prevSize":32,"code":59750},"setIdx":0,"setId":3,"iconIdx":92},{"icon":{"paths":["M224 224h320v576h-96v-112c0-8.836-7.164-16-16-16h-96c-8.837 0-16 7.164-16 16v112h-96v-576zM608 448h192v352h-192v-352zM832 384h-224v-192c0-17.673-14.327-32-32-32h-384c-17.673 0-32 14.327-32 32v640c0 17.673 14.327 32 32 32h640c17.673 0 32-14.327 32-32v-416c0-17.673-14.327-32-32-32zM304 288c-8.837 0-16 7.163-16 16v32c0 8.837 7.163 16 16 16h32c8.837 0 16-7.163 16-16v-32c0-8.837-7.163-16-16-16h-32zM288 432c0-8.837 7.163-16 16-16h32c8.837 0 16 7.163 16 16v32c0 8.836-7.163 16-16 16h-32c-8.837 0-16-7.164-16-16v-32zM304 544c-8.837 0-16 7.164-16 16v32c0 8.836 7.163 16 16 16h32c8.837 0 16-7.164 16-16v-32c0-8.836-7.163-16-16-16h-32zM416 304c0-8.837 7.163-16 16-16h32c8.836 0 16 7.163 16 16v32c0 8.837-7.164 16-16 16h-32c-8.837 0-16-7.163-16-16v-32zM432 416c-8.837 0-16 7.163-16 16v32c0 8.836 7.163 16 16 16h32c8.836 0 16-7.164 16-16v-32c0-8.837-7.164-16-16-16h-32zM416 560c0-8.836 7.163-16 16-16h32c8.836 0 16 7.164 16 16v32c0 8.836-7.164 16-16 16h-32c-8.837 0-16-7.164-16-16v-32zM688 512c-8.836 0-16 7.164-16 16v32c0 8.836 7.164 16 16 16h32c8.836 0 16-7.164 16-16v-32c0-8.836-7.164-16-16-16h-32zM672 656c0-8.836 7.164-16 16-16h32c8.836 0 16 7.164 16 16v32c0 8.836-7.164 16-16 16h-32c-8.836 0-16-7.164-16-16v-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["business"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":464,"id":79,"name":"business","prevSize":32,"code":59751},"setIdx":0,"setId":3,"iconIdx":93},{"icon":{"paths":["M714.667 298.663c0-17.673-14.327-32-32-32s-32 14.327-32 32v426.666c0 17.673 14.327 32 32 32s32-14.327 32-32v-426.666z","M512 394.671c17.673 0 32 14.327 32 32v298.667c0 17.673-14.327 32-32 32s-32-14.327-32-32v-298.667c0-17.673 14.327-32 32-32z","M373.333 554.671c0-17.673-14.327-32-32-32s-32 14.327-32 32v170.667c0 17.677 14.327 32 32 32s32-14.323 32-32v-170.667z","M128 199.555v624.888c0 39.518 32.037 71.556 71.555 71.556h624.888c39.518 0 71.556-32.038 71.556-71.556v-624.888c0-39.519-32.038-71.555-71.556-71.555h-624.888c-39.519 0-71.555 32.037-71.555 71.555zM199.555 192h624.888c4.173 0 7.556 3.383 7.556 7.555v624.888c0 4.173-3.383 7.556-7.556 7.556h-624.888c-4.173 0-7.555-3.383-7.555-7.556v-624.888c0-4.173 3.383-7.555 7.555-7.555z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["dashboard"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":465,"id":78,"name":"dashboard","prevSize":32,"code":59752},"setIdx":0,"setId":3,"iconIdx":94},{"icon":{"paths":["M160 256c0-17.673 14.327-32 32-32h640c17.673 0 32 14.327 32 32s-14.327 32-32 32h-640c-17.673 0-32-14.327-32-32zM160 421.161c0-17.673 14.327-32 32-32h640c17.673 0 32 14.327 32 32s-14.327 32.001-32 32.001h-640c-17.673 0-32-14.327-32-32.001zM160 602.837c0-17.673 14.327-32 32-32h640c17.673 0 32 14.327 32 32s-14.327 32-32 32h-640c-17.673 0-32-14.327-32-32zM160 768c0-17.673 14.327-32 32-32h344.614c17.673 0 32 14.327 32 32s-14.327 32-32 32h-344.614c-17.673 0-32-14.327-32-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["document"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":466,"id":77,"name":"document","prevSize":32,"code":59753},"setIdx":0,"setId":3,"iconIdx":95},{"icon":{"paths":["M421.334 256c0-44.183-35.817-80-80-80s-80 35.817-80 80c0 44.183 35.817 80 80 80s80-35.817 80-80zM465.301 288c-14.208 55.207-64.324 96-123.967 96s-109.758-40.793-123.968-96h-89.367c-17.673 0-32-14.327-32-32s14.327-32 32-32h89.367c14.209-55.207 64.325-96 123.968-96s109.759 40.793 123.967 96h430.699c17.673 0 32 14.327 32 32s-14.327 32-32 32h-430.699zM96 768c0-17.673 14.327-32 32-32h89.367c14.209-55.206 64.325-96 123.968-96 60.782 0 111.671 42.368 124.744 99.179 4.207-2.035 8.93-3.179 13.922-3.179h416c17.673 0 32 14.327 32 32s-14.327 32-32 32h-416c-4.992 0-9.715-1.143-13.922-3.179-13.073 56.811-63.962 99.179-124.744 99.179-59.643 0-109.758-40.794-123.968-96h-89.367c-17.673 0-32-14.327-32-32zM341.334 848c44.183 0 80-35.819 80-80s-35.817-80-80-80c-44.183 0-80 35.819-80 80s35.817 80 80 80zM796.032 543.757c-14.127 55.33-64.303 96.243-124.032 96.243s-109.905-40.913-124.028-96.243c-1.301 0.162-2.628 0.243-3.972 0.243h-416c-17.673 0-32-14.327-32-32s14.327-32 32-32h416c1.344 0 2.671 0.081 3.972 0.243 14.123-55.331 64.299-96.243 124.028-96.243s109.905 40.913 124.032 96.243c1.297-0.162 2.624-0.243 3.968-0.243h96c17.673 0 32 14.327 32 32s-14.327 32-32 32h-96c-1.344 0-2.671-0.081-3.968-0.243zM752 512c0-44.181-35.819-80-80-80s-80 35.819-80 80c0 44.181 35.819 80 80 80s80-35.819 80-80z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["settings"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":467,"id":76,"name":"settings","prevSize":32,"code":59754},"setIdx":0,"setId":3,"iconIdx":96},{"icon":{"paths":["M464 272c-35.345 0-64 28.654-64 64v480c0 35.345 28.655 64 64 64h352c35.345 0 64-28.655 64-64v-304c0-6.511-1.984-12.864-5.692-18.214l-134.455-194.215c-11.955-17.267-31.616-27.57-52.621-27.57h-223.232zM464 336h144v144c0 35.345 28.655 64 64 64h144v272h-352v-480zM672 480v-144h15.232l99.695 144h-114.927zM144 208c0-35.346 28.654-64 64-64h241.843c18.031 0 35.226 7.607 47.356 20.949l39.138 43.051h-328.337v480h128v64h-128c-35.346 0-64-28.655-64-64v-480z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["copy"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":468,"id":75,"name":"copy","prevSize":32,"code":59755},"setIdx":0,"setId":3,"iconIdx":97},{"icon":{"paths":["M825.135 560.657l-84.617-11.038c1.237-9.481 1.882-19.187 1.882-29.086s-0.644-19.605-1.882-29.086l84.617-11.038c1.715 13.133 2.598 26.526 2.598 40.124s-0.883 26.991-2.598 40.124zM804.425 402.941l-78.827 32.686c-7.458-17.989-17.242-34.822-28.996-50.116l67.665-51.996c16.243 21.139 29.798 44.451 40.158 69.426zM707.55 276.801l-51.994 67.663c-15.296-11.753-32.128-21.534-50.116-28.995l32.687-78.825c24.973 10.356 48.286 23.913 69.423 40.157zM560.657 215.93l-11.038 84.617c-9.481-1.237-19.187-1.88-29.086-1.88s-19.605 0.643-29.086 1.88l-11.038-84.617c13.133-1.713 26.526-2.597 40.124-2.597s26.991 0.884 40.124 2.597zM402.941 236.644l32.686 78.825c-17.989 7.461-34.822 17.242-50.116 28.995l-51.996-67.663c21.139-16.244 44.451-29.801 69.426-40.157zM276.801 333.515l67.663 51.996c-11.753 15.294-21.534 32.126-28.995 50.116l-78.825-32.686c10.356-24.975 23.913-48.287 40.157-69.426zM215.93 480.41c-1.713 13.133-2.597 26.526-2.597 40.124s0.884 26.991 2.597 40.124l84.617-11.038c-1.237-9.481-1.88-19.187-1.88-29.086s0.643-19.605 1.88-29.086l-84.617-11.038zM236.644 638.127l78.825-32.687c7.461 17.988 17.242 34.82 28.995 50.116l-67.663 51.994c-16.244-21.137-29.801-44.45-40.157-69.423zM333.515 764.267l51.996-67.665c15.294 11.755 32.126 21.538 50.116 28.996l-32.686 78.827c-24.975-10.359-48.287-23.915-69.426-40.158zM480.41 825.135l11.038-84.617c9.481 1.237 19.187 1.882 29.086 1.882s19.605-0.644 29.086-1.882l11.038 84.617c-13.133 1.715-26.526 2.598-40.124 2.598s-26.991-0.883-40.124-2.598zM638.127 804.425l-32.687-78.827c17.988-7.458 34.82-17.242 50.116-28.996l51.994 67.665c-21.137 16.243-44.45 29.798-69.423 40.158zM764.267 707.55l-67.665-51.994c11.755-15.296 21.538-32.128 28.996-50.116l78.827 32.687c-10.359 24.973-23.915 48.286-40.158 69.423z"],"attrs":[{"fill":"rgb(158, 162, 168)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["status-loading"]},"attrs":[{"fill":"rgb(158, 162, 168)"}],"properties":{"order":469,"id":74,"name":"status-loading","prevSize":32,"code":59756},"setIdx":0,"setId":3,"iconIdx":98},{"icon":{"paths":["M520.533 742.4c-122.534 0-221.867-99.332-221.867-221.867s99.333-221.867 221.867-221.867c122.534 0 221.867 99.333 221.867 221.867s-99.332 221.867-221.867 221.867zM520.533 827.733c169.66 0 307.2-137.54 307.2-307.2 0-169.662-137.54-307.2-307.2-307.2-169.662 0-307.2 137.538-307.2 307.2 0 169.66 137.538 307.2 307.2 307.2z"],"attrs":[{"fill":"rgb(158, 162, 168)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["status-invisible"]},"attrs":[{"fill":"rgb(158, 162, 168)"}],"properties":{"order":470,"id":73,"name":"status-invisible","prevSize":32,"code":59757},"setIdx":0,"setId":3,"iconIdx":99},{"icon":{"paths":["M520.533 827.733c-169.662 0-307.2-137.54-307.2-307.2 0-169.662 137.538-307.2 307.2-307.2 169.66 0 307.2 137.538 307.2 307.2 0 169.66-137.54 307.2-307.2 307.2zM563.2 341.333c0-23.564-19.102-42.667-42.667-42.667s-42.667 19.103-42.667 42.667v199.706l144.013 115.213c18.402 14.72 45.252 11.738 59.972-6.665s11.738-45.252-6.665-59.972l-111.987-89.587v-158.694z"],"attrs":[{"fill":"rgb(243, 190, 8)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["status-away"]},"attrs":[{"fill":"rgb(243, 190, 8)"}],"properties":{"order":471,"id":72,"name":"status-away","prevSize":32,"code":59758},"setIdx":0,"setId":3,"iconIdx":100},{"icon":{"paths":["M520.533 827.733c169.66 0 307.2-137.54 307.2-307.2 0-169.662-137.54-307.2-307.2-307.2-169.662 0-307.2 137.538-307.2 307.2 0 169.66 137.538 307.2 307.2 307.2zM418.133 477.867c-23.564 0-42.667 19.102-42.667 42.667 0 23.561 19.103 42.667 42.667 42.667h204.8c23.565 0 42.667-19.106 42.667-42.667 0-23.565-19.102-42.667-42.667-42.667h-204.8z"],"attrs":[{"fill":"rgb(245, 69, 92)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["status-busy"]},"attrs":[{"fill":"rgb(245, 69, 92)"}],"properties":{"order":472,"id":71,"name":"status-busy","prevSize":32,"code":59759},"setIdx":0,"setId":3,"iconIdx":101},{"icon":{"paths":["M819.2 512c0 169.662-137.538 307.2-307.2 307.2s-307.2-137.538-307.2-307.2c0-169.662 137.538-307.2 307.2-307.2s307.2 137.538 307.2 307.2z"],"attrs":[{"fill":"rgb(45, 224, 165)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["status-online"]},"attrs":[{"fill":"rgb(45, 224, 165)"}],"properties":{"order":473,"id":70,"name":"status-online","prevSize":32,"code":59760},"setIdx":0,"setId":3,"iconIdx":102},{"icon":{"paths":["M430.844 103.994c80.695-16.052 164.339-7.814 240.354 23.673 76.011 31.486 140.983 84.806 186.692 153.216 45.713 68.411 70.11 148.839 70.11 231.117h-64c0-69.619-20.642-137.674-59.324-195.561-38.677-57.886-93.653-103.003-157.973-129.645-64.316-26.642-135.091-33.613-203.375-20.031-68.281 13.582-131.001 47.107-180.23 96.335s-82.753 111.949-96.335 180.23c-13.582 68.284-6.611 139.059 20.031 203.375 26.642 64.32 71.759 119.296 129.645 157.973 57.886 38.682 125.941 59.324 195.561 59.324v64c-82.278 0-162.706-24.397-231.117-70.11-68.41-45.709-121.731-110.682-153.216-186.692v0c-31.486-76.015-39.724-159.659-23.673-240.354 16.051-80.697 55.671-154.821 113.85-213s132.303-97.799 213-113.85z","M593.156 920.009c-80.695 16.051-164.339 7.812-240.353-23.676-76.014-31.484-140.984-84.804-186.695-153.216s-70.109-148.838-70.109-231.117h64c0 69.619 20.644 137.673 59.322 195.558 38.678 57.89 93.653 103.006 157.973 129.647 64.317 26.641 135.093 33.613 203.377 20.032 68.279-13.585 130.999-47.108 180.228-96.337s82.752-111.949 96.337-180.228c13.581-68.284 6.609-139.059-20.032-203.377-26.641-64.32-71.757-119.295-129.643-157.973-57.89-38.678-125.943-59.322-195.563-59.322v-64c82.278 0 162.705 24.398 231.117 70.109s121.732 110.681 153.216 186.695v0c31.488 76.014 39.727 159.657 23.676 240.353-16.055 80.695-55.676 154.82-113.852 213.001-58.18 58.176-132.305 97.796-213.001 113.852z"],"attrs":[{"fill":"rgb(228, 231, 234)"},{"fill":"rgb(9, 90, 210)"}],"isMulticolor":true,"isMulticolor2":false,"grid":0,"tags":["loading"]},"attrs":[{"fill":"rgb(228, 231, 234)"},{"fill":"rgb(9, 90, 210)"}],"properties":{"order":474,"id":69,"name":"loading","prevSize":32,"code":59761,"codes":[59761,59762]},"setIdx":0,"setId":3,"iconIdx":103},{"icon":{"paths":["M305.297 498.091c-12.356-12.634-12.129-32.896 0.507-45.252l191.971-187.717c12.437-12.161 32.307-12.161 44.745 0l191.97 187.717c12.638 12.356 12.864 32.619 0.508 45.252-12.356 12.638-32.619 12.864-45.252 0.508l-137.6-134.55v372.11c0 17.673-14.323 32-32 32-17.673 0-32-14.327-32-32v-372.11l-137.595 134.55c-12.636 12.356-32.896 12.13-45.252-0.508z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["arrow-up"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":475,"id":68,"name":"arrow-up","prevSize":32,"code":59763},"setIdx":0,"setId":3,"iconIdx":104},{"icon":{"paths":["M734.997 526.067c12.356 12.634 12.13 32.896-0.508 45.248l-191.97 187.721c-12.437 12.16-32.307 12.16-44.745 0l-191.97-187.721c-12.636-12.352-12.863-32.614-0.507-45.248 12.356-12.638 32.616-12.864 45.252-0.508l137.595 134.549v-372.109c0-17.673 14.327-32 32-32 17.677 0 32 14.327 32 32v372.109l137.6-134.549c12.634-12.356 32.896-12.13 45.252 0.508z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["arrow-down"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":476,"id":67,"name":"arrow-down","prevSize":32,"code":59764},"setIdx":0,"setId":3,"iconIdx":105},{"icon":{"paths":["M832.678 512c0-176.731-143.27-320-320-320-176.733 0-320.001 143.269-320.001 320 0 176.73 143.269 320 320.001 320 176.73 0 320-143.27 320-320zM896.678 512c0 212.079-171.925 384-384 384-212.079 0-384.001-171.921-384.001-384 0-212.077 171.923-384 384.001-384 212.075 0 384 171.923 384 384zM512.678 704c-106.040 0-192.001-85.961-192.001-192s85.961-192 192.001-192c106.039 0 192 85.961 192 192s-85.961 192-192 192z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["record"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":477,"id":66,"name":"record","prevSize":32,"code":59765},"setIdx":0,"setId":3,"iconIdx":106},{"icon":{"paths":["M132.506 272c0-17.673 14.327-32 32-32h703.999c17.673 0 32 14.327 32 32s-14.327 32-32 32h-703.999c-17.673 0-32-14.327-32-32zM292.506 432c0 17.673-14.327 32-32 32s-32-14.327-32-32c0-17.673 14.327-32 32-32s32 14.327 32 32zM292.506 752c0 17.673-14.327 32-32 32s-32-14.327-32-32c0-17.673 14.327-32 32-32s32 14.327 32 32zM452.506 624c17.673 0 32-14.327 32-32s-14.327-32-32-32c-17.673 0-31.999 14.327-31.999 32s14.327 32 31.999 32zM388.506 400c-17.673 0-32 14.327-32 32s14.327 32 32 32h479.999c17.673 0 32-14.327 32-32s-14.327-32-32-32h-479.999zM356.506 752c0-17.673 14.327-32 32-32h479.999c17.673 0 32 14.327 32 32s-14.327 32-32 32h-479.999c-17.673 0-32-14.327-32-32zM580.506 560c-17.673 0-32 14.327-32 32s14.327 32 32 32h288c17.673 0 32-14.327 32-32s-14.327-32-32-32h-288z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["group-by-type"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":478,"id":65,"name":"group-by-type","prevSize":32,"code":59766},"setIdx":0,"setId":3,"iconIdx":107},{"icon":{"paths":["M825.374 153.373c12.497-12.497 32.755-12.497 45.252 0s12.497 32.758 0 45.255l-671.999 671.999c-12.497 12.497-32.758 12.497-45.255 0s-12.497-32.755 0-45.252l672.001-672.001zM575.612 569.067l-44.706 44.71c7.846 5.905 15.846 11.452 23.535 16.013 9.199 5.461 22.835 12.578 36.971 13.222 16.226 0.738 31.445-5.299 42.47-10.974 11.742-6.042 22.793-13.824 31.744-20.945 1.054-0.836 2.133-1.229 2.884-1.34 0.401-0.060 0.61-0.030 0.687-0.013l121.097 59.076c-5.581 29.329-20.382 66.769-42.394 92.621-11.23 13.184-23.198 22.037-35.388 26.317-11.597 4.075-25.404 4.766-42.65-1.673-48.427-18.074-103.407-53.154-151.693-89.263-14.029-10.492-27.298-20.919-39.467-30.844l-44.39 44.39c14.187 11.686 29.841 24.064 46.447 36.48 49.805 37.248 110.447 76.561 167.258 97.762 30.276 11.298 59.149 11.238 85.197 2.086 25.455-8.939 46.093-25.783 62.246-44.757 31.868-37.423 50.637-88.141 57.062-126.246 4.719-27.985-11.776-51.767-33.139-62.191l-122.807-59.908c-24.41-11.908-51.46-6.003-69.837 8.61-7.006 5.572-14.541 10.739-21.44 14.289-5.577 2.867-8.93 3.742-10.313 4.006l-0.094-0.038c-0.99-0.401-3.729-1.515-8.567-4.386-3.277-1.946-6.874-4.301-10.714-7.006zM313.636 589.683l44.39-44.39c-9.92-12.164-20.35-25.438-30.839-39.462-36.108-48.286-71.191-103.267-89.262-151.691-6.437-17.249-5.748-31.055-1.675-42.651 4.282-12.192 13.134-24.16 26.319-35.388 25.85-22.012 63.29-36.814 92.623-42.392l59.075 121.096c0.018 0.076 0.047 0.285-0.012 0.687-0.111 0.75-0.504 1.83-1.343 2.884-7.118 8.951-14.9 20.001-20.943 31.741-5.673 11.025-11.714 26.246-10.976 42.472 0.643 14.135 7.761 27.772 13.222 36.971 4.562 7.689 10.109 15.684 16.014 23.535l44.705-44.71c-2.701-3.836-5.056-7.433-7.002-10.709-2.867-4.838-3.981-7.578-4.386-8.567l-0.038-0.094c0.265-1.382 1.139-4.738 4.006-10.312 3.55-6.9 8.717-14.437 14.289-21.443 14.613-18.374 20.523-45.425 8.614-69.835l-59.913-122.809c-10.421-21.361-34.203-37.856-62.191-33.137-38.103 6.425-88.824 25.194-126.246 57.060-18.972 16.155-35.817 36.795-44.758 62.246-9.15 26.048-9.211 54.92 2.088 85.196 21.201 56.813 60.513 117.455 97.761 167.26 12.417 16.606 24.795 32.256 36.478 46.443z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["phone-disabled"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":479,"id":64,"name":"phone-disabled","prevSize":32,"code":59767},"setIdx":0,"setId":3,"iconIdx":108},{"icon":{"paths":["M801.122 657.591c22.477 7.735 50.957 2.581 67.409-20.544 22.4-31.488 44.992-80.623 48.922-129.617 1.993-24.841-0.691-51.345-12.365-75.665-11.951-24.887-32.324-45.347-61.722-58.766-55.164-25.181-125.841-40.262-187.396-49.144-61.948-8.937-117.495-11.981-143.966-11.981v62.47c23.198 0 75.755 2.787 135.044 11.341 59.674 8.61 123.358 22.681 170.377 44.143 16.751 7.646 26.027 17.894 31.347 28.975 5.589 11.648 7.795 26.372 6.409 43.635-2.714 33.839-18.718 70.784-35.516 95.467l-127.398-43.853c-0.068-0.043-0.239-0.171-0.478-0.495-0.452-0.61-0.939-1.651-1.092-2.991-1.297-11.362-3.605-24.678-7.633-37.252-3.785-11.806-10.278-26.842-22.272-37.794-10.449-9.54-25.126-14.148-35.494-16.794-11.917-3.038-25.566-5.18-38.946-6.716-26.859-3.085-55.77-4.092-74.351-4.092v62.468c16.9 0 43.341 0.939 67.217 3.686 11.994 1.374 22.554 3.123 30.643 5.184 5.449 1.391 8.175 2.543 9.161 2.957l0.094 0.043c0.789 1.161 2.543 4.151 4.459 10.121 2.368 7.39 4.041 16.375 5.056 25.267 2.662 23.326 17.613 46.63 43.294 55.471l129.199 44.476zM222.876 657.587c-22.474 7.735-50.954 2.581-67.407-20.544-22.4-31.488-44.993-80.623-48.922-129.617-1.992-24.841 0.691-51.345 12.367-75.665 11.948-24.887 32.321-45.347 61.719-58.765 55.165-25.181 125.841-40.263 187.399-49.144 61.946-8.937 117.494-11.981 143.964-11.981v62.47c-23.198 0-75.755 2.787-135.043 11.341-59.675 8.61-123.36 22.681-170.38 44.143-16.748 7.646-26.025 17.894-31.343 28.975-5.593 11.648-7.797 26.372-6.412 43.635 2.714 33.843 18.721 70.784 35.518 95.467l127.4-43.853c0.067-0.043 0.235-0.171 0.478-0.495 0.452-0.61 0.937-1.651 1.090-2.991 1.296-11.362 3.606-24.678 7.636-37.252 3.784-11.806 10.276-26.842 22.27-37.794 10.45-9.54 25.127-14.148 35.493-16.794 11.916-3.038 25.568-5.18 38.947-6.716 26.859-3.085 55.77-4.092 74.351-4.092v62.468c-16.9 0-43.341 0.939-67.221 3.686-11.989 1.378-22.551 3.123-30.638 5.184-5.452 1.391-8.175 2.543-9.162 2.957l-0.092 0.043c-0.791 1.161-2.546 4.151-4.459 10.121-2.368 7.39-4.044 16.375-5.058 25.267-2.66 23.326-17.611 46.63-43.292 55.471l-129.202 44.476z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["phone-end"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":480,"id":63,"name":"phone-end","prevSize":32,"code":59768},"setIdx":0,"setId":3,"iconIdx":109},{"icon":{"paths":["M410.504 204.615c-10.421-21.361-34.203-37.856-62.191-33.137-38.103 6.425-88.824 25.194-126.246 57.060-18.972 16.155-35.817 36.795-44.758 62.246-9.15 26.048-9.211 54.92 2.088 85.196 21.201 56.813 60.513 117.455 97.761 167.26 37.482 50.125 74.609 91.554 93.327 110.272l44.173-44.173c-16.405-16.405-51.598-55.539-87.472-103.509-36.108-48.286-71.191-103.267-89.262-151.691-6.437-17.249-5.748-31.055-1.675-42.651 4.282-12.192 13.134-24.16 26.319-35.388 25.85-22.012 63.29-36.814 92.623-42.392l59.075 121.096c0.018 0.075 0.047 0.285-0.012 0.687-0.111 0.75-0.504 1.83-1.343 2.884-7.118 8.951-14.9 20.001-20.943 31.741-5.673 11.025-11.714 26.246-10.976 42.472 0.643 14.135 7.761 27.772 13.222 36.971 6.277 10.577 14.417 21.743 22.79 32.29 16.809 21.175 36.542 42.33 49.679 55.467l44.173-44.173c-11.951-11.951-29.978-31.309-44.924-50.133-7.505-9.455-13.739-18.159-18.001-25.335-2.867-4.838-3.981-7.578-4.386-8.567l-0.038-0.094c0.265-1.382 1.139-4.738 4.006-10.312 3.55-6.9 8.717-14.437 14.289-21.443 14.613-18.374 20.523-45.425 8.614-69.835l-59.913-122.809zM819.383 613.5c21.363 10.423 37.858 34.206 33.139 62.191-6.426 38.106-25.195 88.823-57.062 126.246-16.154 18.974-36.791 35.819-62.246 44.757-26.048 9.152-54.921 9.212-85.197-2.086-56.811-21.201-117.453-60.514-167.258-97.762-50.125-37.483-91.555-74.607-110.273-93.325l44.173-44.173c16.407 16.405 55.54 51.597 103.511 87.471 48.286 36.109 103.266 71.189 151.693 89.263 17.246 6.434 31.053 5.747 42.65 1.673 12.19-4.279 24.158-13.133 35.388-26.317 22.012-25.852 36.813-63.292 42.394-92.621l-121.097-59.076c-0.077-0.017-0.286-0.047-0.687 0.013-0.751 0.111-1.83 0.503-2.884 1.34-8.951 7.121-20.002 14.903-31.744 20.945-11.025 5.675-26.244 11.712-42.47 10.974-14.135-0.644-27.772-7.761-36.971-13.222-10.577-6.276-21.743-14.417-32.29-22.788-21.175-16.811-42.33-36.544-55.467-49.681l44.173-44.173c11.951 11.951 31.309 29.982 50.133 44.928 9.455 7.501 18.159 13.734 25.335 17.997 4.838 2.871 7.578 3.985 8.567 4.386l0.094 0.038c1.382-0.265 4.736-1.139 10.313-4.006 6.899-3.55 14.434-8.717 21.44-14.289 18.377-14.613 45.427-20.518 69.837-8.61l122.807 59.908z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["phone"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":481,"id":62,"name":"phone","prevSize":32,"code":59769},"setIdx":0,"setId":3,"iconIdx":110},{"icon":{"paths":["M802.257 544c0 176.73-143.27 320-320 320-176.733 0-320.002-143.27-320.002-320 0-176.731 143.269-320 320.002-320v-64c-212.079 0-384.002 171.923-384.002 384 0 212.079 171.922 384 384.002 384 212.075 0 384-171.921 384-384 0-10.778-0.444-21.449-1.314-32h-64.269c1.045 10.526 1.583 21.201 1.583 32zM802.257 112c0-17.673-14.327-32-32-32-17.677 0-32 14.327-32 32v112h-112c-17.677 0-32 14.327-32 32s14.323 32 32 32h112v112c0 17.673 14.323 32 32 32 17.673 0 32-14.327 32-32v-112h112c17.673 0 32-14.327 32-32s-14.327-32-32-32h-112v-112zM386.255 512c35.346 0 64.002-28.655 64.002-64 0-35.346-28.656-64-64.002-64s-64 28.654-64 64c0 35.345 28.654 64 64 64zM642.257 448c0 35.345-28.655 64-64 64-35.349 0-64-28.655-64-64 0-35.346 28.651-64 64-64 35.345 0 64 28.654 64 64zM332.060 589.077c-10.451-14.251-30.477-17.335-44.729-6.882-14.252 10.449-17.332 30.477-6.881 44.727 37.658 51.354 77.753 84.625 119.178 102.665 41.737 18.18 82.796 19.989 120.364 11.652 73.468-16.307 132.211-70.874 164.070-114.317 10.449-14.251 7.369-34.278-6.882-44.727-14.251-10.453-34.278-7.369-44.727 6.882-26.812 36.557-73.668 77.99-126.332 89.681-25.502 5.662-52.642 4.476-80.938-7.846-28.608-12.459-60.38-37.188-93.122-81.835z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["reaction-add"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":482,"id":61,"name":"reaction-add","prevSize":32,"code":59770},"setIdx":0,"setId":3,"iconIdx":111},{"icon":{"paths":["M226.503 304.026c-49.642 68.947-66.502 152.644-66.502 207.97v1.451l-0.131 1.446c-9.702 106.718 28.59 181.931 90.135 234.005 62.938 53.257 152.152 83.733 244.195 93.961 91.968 10.219 193.271 1.446 273.31-15.479 40.017-8.465 73.613-18.735 97.438-29.077 9.246-4.015 16.439-7.787 21.739-11.127-2.466-1.566-5.449-3.302-9.003-5.197-9.225-4.911-19.78-9.579-30.733-14.366l-1.916-0.836c-9.664-4.224-20.471-8.943-28.655-13.521-14.835-8.294-29.389-17.732-40.004-27.772-5.227-4.941-11.166-11.571-15.147-19.827-4.211-8.742-7.223-21.794-1.306-35.601 31.979-74.62 47.177-115.49 54.537-142.481 6.874-25.199 6.874-37.888 6.874-58.061v-0.183c0-16.038-9.318-89.517-55.812-158.033-45.013-66.338-125.99-129.968-274.854-129.968-134.636 0-215.696 55.382-264.163 122.698zM174.565 266.63c60.333-83.796 160.607-149.302 316.102-149.302 171.136 0 271.497 75.037 327.812 158.032 54.839 80.818 66.854 167.337 66.854 193.969 0 22.383-0.021 41.694-9.126 75.085-8.128 29.807-23.484 70.929-51.942 137.924 5.261 4.169 13.069 9.306 23.356 15.061 5.316 2.974 13.487 6.554 24.964 11.571 10.654 4.655 23.437 10.266 35.174 16.512 11.26 5.995 24.418 14.033 34.202 24.542 10.231 10.991 20.975 29.845 13.299 52.864-5.056 15.164-16.794 25.937-26.577 33.092-10.628 7.774-23.817 14.763-38.251 21.030-29.009 12.587-67.029 23.962-109.683 32.981-85.312 18.039-193.583 27.588-293.615 16.474-99.956-11.106-202.741-44.629-278.47-108.71-76.833-65.011-123.811-159.996-112.66-287.223 0.286-65.549 19.841-162.346 78.561-243.902zM496 320c17.673 0 32 14.327 32 32v224c0 17.673-14.327 32-32 32s-32-14.327-32-32v-224c0-17.673 14.327-32 32-32zM528 672c0-17.673-14.327-32-32-32s-32 14.327-32 32c0 17.673 14.327 32 32 32s32-14.327 32-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["canned-response"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":483,"id":60,"name":"canned-response","prevSize":32,"code":59771},"setIdx":0,"setId":3,"iconIdx":112},{"icon":{"paths":["M332.328 644.885c-21.571-19.618-6.007-52.885 23.151-52.885 8.965 0 17.527 3.529 24.272 9.438 21.605 18.918 42.641 31.957 62.702 40.508 36.565 15.59 71.808 17.109 104.794 9.941 37.632-8.179 72.657-27.81 102.11-51.345 6.724-5.376 14.997-8.542 23.607-8.542 30.217 0 45.615 34.257 22.396 53.594-36.911 30.741-82.79 57.591-134.519 68.834-44.8 9.732-93.67 7.629-143.486-13.606-28.791-12.275-57.234-30.656-85.026-55.936z","M402.423 480c35.345 0 64-28.655 64-64 0-35.346-28.655-64-64-64s-64 28.654-64 64c0 35.345 28.654 64 64 64z","M626.423 480c35.345 0 64-28.655 64-64 0-35.346-28.655-64-64-64s-64 28.654-64 64c0 35.345 28.655 64 64 64z","M930.257 512c0 229.751-186.253 416-416 416-229.752 0-416.002-186.249-416.002-416s186.249-416 416.002-416c229.747 0 416 186.249 416 416zM866.257 512c0-194.404-157.598-352-352-352-194.406 0-352.002 157.596-352.002 352 0 194.402 157.596 352 352.002 352 194.402 0 352-157.598 352-352z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["emoji"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":484,"id":59,"name":"emoji","prevSize":32,"code":59772},"setIdx":0,"setId":3,"iconIdx":113},{"icon":{"paths":["M480.094 128c104.26 0 181.252 29.018 237.495 70.652l-44.318 44.317c-45.521-31.22-107.746-53.057-193.178-53.057-129.725 0-207.828 53.576-254.528 118.696-47.832 66.699-64.077 147.668-64.077 201.185v1.404l-0.127 1.399c-7.328 80.926 13.761 143.13 51.784 190.498l-43.879 43.883c-50.179-59.904-78.131-139.046-69.44-238.596 0.276-63.411 19.117-157.053 75.696-235.949 58.132-81.062 154.749-144.433 304.572-144.433zM825.105 332.498l-47.010 47.009c16.503 42.634 20.608 78.524 20.608 89.011v0.179c0 19.516 0 31.791-6.622 56.171-7.091 26.108-21.739 65.647-52.553 137.835-5.7 13.355-2.795 25.98 1.263 34.436 3.831 7.987 9.557 14.4 14.592 19.183 10.227 9.711 24.252 18.837 38.545 26.867 7.889 4.429 18.3 8.994 27.614 13.077l1.843 0.806c10.556 4.634 20.727 9.148 29.611 13.897 3.426 1.835 6.302 3.516 8.674 5.030-5.103 3.23-12.036 6.882-20.941 10.765-22.959 10.005-55.33 19.938-93.888 28.126-77.12 16.375-174.729 24.862-263.339 14.976-43.746-4.881-86.83-14.528-126.537-29.231l-47.543 47.543c52.771 23.019 110.493 36.89 167.266 43.221 96.388 10.752 200.708 1.515 282.91-15.936 41.097-8.725 77.734-19.729 105.681-31.906 13.909-6.063 26.615-12.821 36.855-20.343 9.425-6.925 20.74-17.344 25.609-32.017 7.394-22.268-2.953-40.503-12.813-51.136-9.429-10.167-22.106-17.941-32.956-23.74-11.311-6.046-23.625-11.469-33.89-15.979-11.059-4.851-18.931-8.316-24.051-11.191-9.916-5.568-17.442-10.534-22.507-14.571 27.422-64.806 42.214-104.589 50.048-133.423 8.772-32.303 8.794-50.982 8.794-72.64 0-20.105-7.053-75.5-35.264-136.020zM838.293 153.373c12.497-12.497 32.759-12.497 45.257 0s12.497 32.758 0 45.255l-682.667 682.665c-12.497 12.497-32.758 12.497-45.255 0s-12.497-32.755 0-45.252l682.665-682.668z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["message-disabled"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":485,"id":58,"name":"message-disabled","prevSize":32,"code":59773},"setIdx":0,"setId":3,"iconIdx":114},{"icon":{"paths":["M223.311 308.609c-47.831 66.699-64.077 147.668-64.077 201.185v1.404l-0.127 1.399c-9.348 103.236 27.547 175.996 86.848 226.377 60.643 51.516 146.604 80.998 235.291 90.893 88.61 9.886 186.223 1.399 263.339-14.976 38.562-8.188 70.929-18.121 93.888-28.126 8.909-3.883 15.838-7.535 20.945-10.765-2.377-1.515-5.248-3.196-8.678-5.030-8.883-4.749-19.055-9.263-29.611-13.897l-1.843-0.806c-9.314-4.083-19.725-8.649-27.61-13.077-14.293-8.030-28.318-17.156-38.545-26.867-5.035-4.783-10.761-11.196-14.596-19.183-4.058-8.457-6.959-21.082-1.259-34.436 30.814-72.188 45.457-111.727 52.553-137.835 6.622-24.38 6.622-36.655 6.618-56.171v-0.179c0-15.514-8.977-86.595-53.777-152.876-43.371-64.175-121.395-125.729-264.828-125.729-129.727 0-207.831 53.576-254.531 118.696zM173.267 272.433c58.132-81.062 154.749-144.433 304.574-144.433 164.894 0 261.594 72.589 315.857 152.878 52.838 78.182 64.414 161.879 64.414 187.641 0 21.658-0.017 40.337-8.794 72.64-7.834 28.834-22.626 68.617-50.048 133.423 5.069 4.036 12.591 9.003 22.507 14.571 5.12 2.876 12.992 6.34 24.055 11.191 10.261 4.51 22.579 9.933 33.89 15.979 10.846 5.798 23.526 13.572 32.951 23.74 9.86 10.633 20.211 28.868 12.817 51.136-4.873 14.673-16.183 25.092-25.609 32.017-10.24 7.522-22.946 14.281-36.86 20.343-27.947 12.177-64.58 23.181-105.681 31.906-82.197 17.451-186.522 26.688-282.906 15.936-96.31-10.743-195.347-43.174-268.314-105.165-74.031-62.891-119.295-154.778-108.551-277.854 0.276-63.411 19.118-157.053 75.696-235.949z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["message"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":486,"id":57,"name":"message","prevSize":32,"code":59774},"setIdx":0,"setId":3,"iconIdx":115},{"icon":{"paths":["M273.129 356.679c6.747-28.299 25.696-52.005 51.209-67.153 25.601-15.2 56.323-20.858 84.699-14.531 27.639 6.164 55.116 24.12 74.871 60.34l22.541 41.324 30.135-36.162c27.238-32.687 85.129-39.712 134.716-14.063 23.561 12.187 42.206 30.617 52.062 53.489 9.655 22.406 12.113 51.897-1.434 89.149l-15.616 42.935h45.687c53.606 0 82.419 15.881 97.643 33.749 15.65 18.377 21.897 44.651 18.556 74.718-3.345 30.084-16.055 60.514-33.455 82.889-17.941 23.066-36.651 32.644-50.743 32.644h-543.998c-18.791 0-37.067-10.359-52.194-31.578-15.217-21.342-24.977-51.051-25.818-81.31-0.84-30.229 7.238-57.916 23.734-77.491 15.795-18.748 42.268-33.621 86.278-33.621h59.792l-33.166-49.749c-27.882-41.825-32.118-77.815-25.498-105.58zM518.221 272.084c-26.342-32.073-59.669-51.619-95.255-59.554-45.624-10.173-92.902-0.833-131.301 21.965-38.487 22.85-69.538 60.142-80.791 107.342-8.278 34.72-5.369 72.759 10.731 111.77-35.67 8.465-64.099 26.185-84.825 50.782-29.004 34.423-39.927 78.737-38.767 120.508 1.159 41.741 14.399 84.032 37.682 116.689 23.373 32.785 59.097 58.423 104.305 58.423h543.999c41.907 0 77.201-26.419 101.261-57.353 24.597-31.629 41.886-73.195 46.545-115.115 4.659-41.933-3.098-87.659-33.446-123.285-24.102-28.297-59.503-46.771-105.613-53.453 5.833-35.195 1.685-67.675-10.607-96.206-16.644-38.627-46.997-67.197-81.438-85.009-54.899-28.397-128.734-32.652-182.481 2.495zM512 437.333c17.673 0 32 14.327 32 32v53.329h53.333c17.673 0 32 14.323 32 32 0 17.673-14.327 32-32 32h-53.333v53.338c0 17.673-14.327 32-32 32s-32-14.327-32-32v-53.338h-53.333c-17.672 0-31.999-14.327-31.999-32 0-17.677 14.327-32 31.999-32h53.333v-53.329c0-17.673 14.327-32 32-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["cloud-connectivity"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":487,"id":56,"name":"cloud-connectivity","prevSize":32,"code":59775},"setIdx":0,"setId":3,"iconIdx":116},{"icon":{"paths":["M515.558 142.7c12.915-3.408 26.505-3.288 39.36 0.345l245.197 69.318c29.163 8.245 51.255 33.818 53.504 65.14 24.503 341.143-184.397 520.424-272.614 580.213-33.050 22.404-75.277 22.473-108.416 0.26-88.759-59.503-300.099-238.588-276.509-579.794 2.205-31.89 24.96-57.772 54.753-65.632l264.726-69.849zM537.506 204.631c-1.835-0.519-3.776-0.536-5.623-0.049l-264.722 69.849c-4.4 1.161-6.999 4.776-7.233 8.165-21.305 308.167 168.215 468.534 248.301 522.217 11.507 7.714 25.434 7.68 36.873-0.073 79.377-53.803 266.833-214.289 244.681-522.653-0.239-3.358-2.786-6.925-7.078-8.139l-245.197-69.318z","M492.928 337.331c-19.759 4.672-47.249 12.307-81.151 24.553 20.812 108.773 53.221 187.015 81.151 238.829v-263.382zM495.125 271.311c33.766-6.897 61.803 19.742 61.803 51.124v360.966c0 17.024-10.334 31.748-25.643 37.521-15.671 5.909-33.779 1.327-44.86-12.676-32.657-41.267-106.324-152.951-141.192-354.565-3.241-18.744 7.065-37.694 25.329-44.725 56.185-21.63 99.095-32.442 124.562-37.644z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["shield"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":488,"id":55,"name":"shield","prevSize":32,"code":59776},"setIdx":0,"setId":3,"iconIdx":117},{"icon":{"paths":["M664.081 405.067c11.639-13.3 10.291-33.517-3.008-45.155s-33.519-10.29-45.154 3.011l-125.252 143.142-39.919-45.619c-11.635-13.299-31.852-14.647-45.153-3.008-13.3 11.635-14.648 31.851-3.011 45.154l64.001 73.143c6.076 6.942 14.852 10.927 24.081 10.927s18.005-3.985 24.081-10.927l149.333-170.669z","M541.99 143.045c-12.855-3.633-26.449-3.753-39.364-0.345l-264.722 69.849c-29.793 7.861-52.548 33.743-54.753 65.632-23.59 341.206 187.75 520.291 276.51 579.794 33.135 22.212 75.362 22.144 108.416-0.26 88.218-59.789 297.118-239.070 272.614-580.213-2.253-31.321-24.341-56.895-53.508-65.14l-245.193-69.318zM518.955 204.582c1.847-0.487 3.789-0.47 5.623 0.049l245.197 69.318c4.292 1.214 6.839 4.781 7.078 8.139 22.153 308.364-165.303 468.85-244.685 522.653-11.435 7.753-25.365 7.787-36.873 0.073-80.083-53.683-269.603-214.050-248.298-522.217 0.234-3.389 2.833-7.004 7.234-8.165l264.723-69.849z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["shield-check"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":489,"id":54,"name":"shield-check","prevSize":32,"code":59777},"setIdx":0,"setId":3,"iconIdx":118},{"icon":{"paths":["M373.333 448c0-17.673 14.327-32 32-32h213.334c17.673 0 32 14.327 32 32s-14.327 32-32 32h-213.334c-17.673 0-32-14.327-32-32z","M405.333 544c-17.673 0-32 14.327-32 32s14.327 32 32 32h213.334c17.673 0 32-14.327 32-32s-14.327-32-32-32h-213.334z","M256 128c-17.673 0-32 14.327-32 32v704c0 17.673 14.327 32 32 32h512c17.673 0 32-14.327 32-32v-501.745c0-6.67-2.082-13.172-5.961-18.6l-144.469-202.255c-6.003-8.41-15.701-13.4-26.039-13.4h-367.531zM736 372.51v459.49h-448v-640h319.066l128.934 180.51z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["file-document"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":490,"id":53,"name":"file-document","prevSize":32,"code":59778},"setIdx":0,"setId":3,"iconIdx":119},{"icon":{"paths":["M352 445.44c0-17.677 14.327-32.002 32-32.002h256c17.673 0 32 14.325 32 32.002 0 17.673-14.327 32-32 32h-256c-17.673 0-32-14.327-32-32z","M352 322.558c0-17.673 14.327-32 32-32h256c17.673 0 32 14.327 32 32s-14.327 32-32 32h-256c-17.673 0-32-14.327-32-32z","M864 679.68c0 17.673-14.327 32-32 32h-18.509c-8.218 40.546-8.218 82.334 0 122.88h19.789c16.964 0 30.72 13.756 30.72 30.72s-13.756 30.72-30.72 30.72h-545.28c-70.692 0-128-55.014-128-122.88v-453.12c0-106.039 85.961-192 192-192h480c17.673 0 32 14.327 32 32v519.68zM748.42 834.56c-6.788-40.678-6.788-82.202 0-122.88h-460.42c-35.346 0-64 27.507-64 61.44s28.654 61.44 64 61.44h460.42zM224 647.68h576v-455.68h-448c-70.692 0-128 57.308-128 128v327.68z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["book"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":491,"id":52,"name":"book","prevSize":32,"code":59779},"setIdx":0,"setId":3,"iconIdx":120},{"icon":{"paths":["M778.641 213.333c-17.673 0-32 14.327-32 32v533.333c0 17.673 14.327 32 32 32s32-14.327 32-32v-533.333c0-17.673-14.327-32-32-32z","M600.87 341.333c-17.673 0-32 14.327-32 32v405.333c0 17.673 14.327 32 32 32s32-14.327 32-32v-405.333c0-17.673-14.327-32-32-32z","M423.103 810.667c-17.673 0-32-14.327-32-32v-277.333c0-17.673 14.327-32 32-32s32.001 14.327 32.001 32v277.333c0 17.673-14.327 32-32.001 32z","M245.333 597.333c-17.673 0-32 14.327-32 32v149.333c0 17.673 14.327 32 32 32s32-14.327 32-32v-149.333c0-17.673-14.327-32-32-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["signal"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":492,"id":51,"name":"signal","prevSize":32,"code":59780},"setIdx":0,"setId":3,"iconIdx":121},{"icon":{"paths":["M160 512c0-17.673 13.133-32 29.333-32h645.333c16.201 0 29.333 14.327 29.333 32s-13.133 32-29.333 32h-645.333c-16.201 0-29.333-14.327-29.333-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["h-bar"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":493,"id":50,"name":"h-bar","prevSize":32,"code":59781},"setIdx":0,"setId":3,"iconIdx":122},{"icon":{"paths":["M292.515 192c13.364 0 25.321 8.305 29.987 20.829l96 257.699c6.17 16.559-2.255 34.987-18.816 41.156s-34.988-2.253-41.158-18.816l-20.476-54.963h-91.075l-20.476 54.963c-6.17 16.563-24.596 24.986-41.158 18.816s-24.985-24.597-18.816-41.156l96-257.699c4.666-12.524 16.623-20.829 29.987-20.829zM314.211 373.904l-21.695-58.238-21.696 58.238h43.391z","M525.286 626.436c-12.156 12.826-11.61 33.079 1.22 45.235l160 151.586c12.343 11.695 31.676 11.695 44.019 0l160-151.586c12.826-12.156 13.376-32.41 1.22-45.235-12.156-12.83-32.41-13.38-45.239-1.225l-105.993 100.42v-501.632c0-17.673-14.327-32-32-32s-32 14.327-32 32v501.632l-105.988-100.42c-12.83-12.156-33.084-11.605-45.239 1.225z","M196.515 570.944c-17.673 0-32 14.327-32 32 0 17.677 14.327 32 32 32h116.145l-139.065 142.733c-8.979 9.216-11.565 22.916-6.564 34.769 5.001 11.857 16.617 19.563 29.484 19.563h192c17.673 0 32-14.327 32-32s-14.327-32-32-32h-116.145l139.065-142.733c8.979-9.216 11.565-22.912 6.564-34.769-5.001-11.853-16.617-19.563-29.484-19.563h-192z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["sort-az"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":494,"id":49,"name":"sort-az","prevSize":32,"code":59782},"setIdx":0,"setId":3,"iconIdx":123},{"icon":{"paths":["M922.551 666.351c12.587-12.237 12.86-32.35 0.606-44.919-12.254-12.574-32.393-12.843-44.983-0.606l-105.971 103.019v-500.139c0-17.545-14.242-31.767-31.808-31.767-17.57 0-31.812 14.223-31.812 31.767v500.139l-105.971-103.019c-12.591-12.237-32.73-11.968-44.983 0.606-12.254 12.57-11.981 32.683 0.606 44.919l159.97 155.511c12.352 12.006 32.026 12.006 44.378 0l159.97-155.511zM564.425 333.229c17.57 0 31.808-14.223 31.808-31.767s-14.238-31.767-31.808-31.767h-431.919c-17.568 0-31.809 14.223-31.809 31.767s14.242 31.767 31.809 31.767h431.919zM468.442 535.394c17.57 0 31.812-14.221 31.812-31.765s-14.242-31.77-31.812-31.77h-335.936c-17.568 0-31.809 14.225-31.809 31.77s14.242 31.765 31.809 31.765h335.936zM388.458 722.010c17.568 0 31.809-14.221 31.809-31.765s-14.241-31.77-31.809-31.77h-255.952c-17.568 0-31.809 14.225-31.809 31.77s14.241 31.765 31.809 31.765h255.952z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["sort"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":495,"id":48,"name":"sort","prevSize":32,"code":59783},"setIdx":0,"setId":3,"iconIdx":124},{"icon":{"paths":["M822.242 183.279c-37.141-37.936-98.074-38.532-135.953-1.331l-348.017 341.786c-12.722 12.497-21.706 28.284-25.943 45.594l-23.65 96.623c-6.931 28.318 16.732 54.771 45.685 51.072l90.573-11.563c20.195-2.577 39.050-11.503 53.834-25.485l360.013-340.471c38.933-36.82 40.119-98.352 2.633-136.64l-19.174-19.584zM731.166 227.52c12.625-12.4 32.934-12.201 45.316 0.444l19.174 19.584c12.497 12.762 12.1 33.273-0.879 45.547l-69.871 66.081-63.364-63.28 69.623-68.376zM615.906 340.713l62.511 62.427-243.652 230.426c-4.928 4.659-11.211 7.633-17.943 8.495l-58.231 7.433 15.908-64.99c1.412-5.769 4.407-11.034 8.648-15.198l232.76-228.593zM192.001 265.251c0-17.65 14.327-31.958 32-31.958h280.959c17.673 0 32-14.308 32-31.958s-14.327-31.958-32-31.958h-280.959c-53.019 0-96 42.924-96 95.874v533.695c0 52.949 42.981 95.872 96 95.872h529.065c53.022 0 96-42.923 96-95.872v-279.044c0-17.651-14.327-31.962-32-31.962s-32 14.31-32 31.962v279.044c0 17.651-14.327 31.957-32 31.957h-529.065c-17.673 0-32-14.306-32-31.957v-533.695z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["create"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":496,"id":47,"name":"create","prevSize":32,"code":59784},"setIdx":0,"setId":3,"iconIdx":125},{"icon":{"paths":["M252.138 275.61l-13.972 14.271c-37.092 37.884-36.449 98.665 1.435 135.757l145.62 142.576c37.885 37.090 98.665 36.446 135.756-1.438l13.973-14.268c0.725-0.742 1.434-1.489 2.129-2.244l0.098 0.098c5.807-5.905 13.888-9.566 22.822-9.566 17.673 0 32 14.327 32 32 0 9.6-4.228 18.21-10.923 24.077l-14.37 14.677c-61.82 63.142-163.119 64.213-226.26 2.394l-145.62-142.575c-63.141-61.82-64.212-163.121-2.392-226.262l13.972-14.271c61.82-63.141 163.121-64.212 226.263-2.392l74.692 73.131c0.977 0.847 1.899 1.752 2.769 2.71l0.371 0.366-0.026 0.026c4.937 5.63 7.923 13.005 7.923 21.079 0 17.673-14.327 32-32 32-7.829 0-15.002-2.813-20.565-7.482l-0.107 0.108-77.833-76.207c-37.885-37.092-98.665-36.449-135.757 1.435zM787.861 768l13.973-14.268c37.090-37.884 36.45-98.667-1.434-135.757l-145.621-142.575c-37.888-37.090-98.667-36.45-135.757 1.434l-13.973 14.272c-0.725 0.738-1.434 1.485-2.129 2.244l-0.098-0.102c-5.807 5.905-13.888 9.57-22.822 9.57-17.673 0-32-14.327-32-32 0-9.6 4.228-18.214 10.923-24.077l0.397-0.41 13.973-14.272c61.82-63.139 163.119-64.21 226.261-2.389l145.617 142.575c63.142 61.82 64.213 163.119 2.394 226.261l-13.973 14.268c-61.82 63.142-163.119 64.213-226.261 2.394l-74.692-73.131c-0.977-0.849-1.899-1.754-2.769-2.709l-0.371-0.367 0.026-0.026c-4.937-5.632-7.923-13.005-7.923-21.077 0-17.673 14.327-32 32-32 7.829 0 15.002 2.812 20.565 7.479l0.107-0.107 77.833 76.207c37.884 37.090 98.667 36.45 135.757-1.438z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["link"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":497,"id":46,"name":"link","prevSize":32,"code":59785},"setIdx":0,"setId":3,"iconIdx":126},{"icon":{"paths":["M234.667 170.662c0-47.128 38.205-85.333 85.333-85.333h384c47.13 0 85.333 38.205 85.333 85.333v682.668c0 47.125-38.204 85.333-85.333 85.333h-384c-47.128 0-85.333-38.208-85.333-85.333v-682.668zM298.667 170.662v682.668c0 11.78 9.551 21.333 21.333 21.333h384c11.78 0 21.333-9.553 21.333-21.333v-682.668c0-11.782-9.553-21.333-21.333-21.333h-96.29c-2.654 24.002-23.002 42.672-47.71 42.672h-96c-24.708 0-45.056-18.67-47.707-42.672h-96.293c-11.782 0-21.333 9.551-21.333 21.333z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["mobile"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":498,"id":45,"name":"mobile","prevSize":32,"code":59786},"setIdx":0,"setId":3,"iconIdx":127},{"icon":{"paths":["M261.333 96c-17.673 0-32 14.327-32 32v768c0 17.673 14.327 32 32 32h512c17.673 0 32-14.327 32-32v-96c0-17.673-14.327-32-32-32s-32 14.327-32 32v64h-448v-704h448v64c0 17.673 14.327 32 32 32s32-14.327 32-32v-96c0-17.673-14.327-32-32-32h-512zM987.959 489.374l-160-160.001c-12.497-12.497-32.755-12.497-45.252 0s-12.497 32.758 0 45.255l105.37 105.373h-418.743c-17.673 0-32 14.327-32 32s14.327 32 32 32h418.743l-105.37 105.374c-12.497 12.497-12.497 32.755 0 45.252s32.755 12.497 45.252 0l160-160c12.497-12.497 12.497-32.755 0-45.252z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["logout"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":499,"id":44,"name":"logout","prevSize":32,"code":59787},"setIdx":0,"setId":3,"iconIdx":128},{"icon":{"paths":["M736 864.209v-447.408h-448v447.408h448zM224 864.209v-447.408c-35.346 0-64-28.616-64-63.916v-127.831c0-35.299 28.654-63.916 64-63.916h224c0-35.299 28.655-63.915 64-63.915s64 28.616 64 63.915h224c35.345 0 64 28.616 64 63.916v127.831c0 35.299-28.655 63.916-64 63.916v447.408c0 35.298-28.655 63.915-64 63.915h-448c-35.346 0-64-28.617-64-63.915zM800 225.055h-576v127.831h576v-127.831zM416 544.631v191.748c0 17.647 14.327 31.957 32 31.957s32-14.31 32-31.957v-191.748c0-17.647-14.327-31.957-32-31.957s-32 14.31-32 31.957zM576 512.674c17.673 0 32 14.31 32 31.957v191.748c0 17.647-14.327 31.957-32 31.957s-32-14.31-32-31.957v-191.748c0-17.647 14.327-31.957 32-31.957z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["delete"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":500,"id":43,"name":"delete","prevSize":32,"code":59788},"setIdx":0,"setId":3,"iconIdx":129},{"icon":{"paths":["M891.494 238.961l-297.476 637.446c-16.853 36.113-69.619 31.458-79.889-7.049l-66.001-247.501 151.249-189.056-219.993 109.995-226.834-113.417c-35.43-17.715-29.696-69.947 8.733-79.555l681.2-170.3c34.837-8.71 64.196 26.892 49.011 59.436z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["send-filled"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":501,"id":42,"name":"send-filled","prevSize":32,"code":59789},"setIdx":0,"setId":3,"iconIdx":130},{"icon":{"paths":["M878.020 192.976c7.851 9.521 9.527 22.708 4.309 33.891l-298.667 640c-5.692 12.194-18.402 19.529-31.808 18.342-13.406-1.182-24.64-10.628-28.109-23.629l-81.617-306.074-285.774-142.884c-11.977-5.989-18.959-18.802-17.498-32.113s11.056-24.305 24.048-27.553l682.667-170.667c11.972-2.993 24.597 1.165 32.448 10.686zM505.822 545.967l57.079 214.054 233.028-499.351-533.581 133.396 203.605 101.802 69.513-52.134c14.14-10.603 34.197-7.735 44.8 6.4 10.603 14.14 7.74 34.197-6.4 44.8l-68.045 51.034z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["send"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":502,"id":41,"name":"send","prevSize":32,"code":59790},"setIdx":0,"setId":3,"iconIdx":131},{"icon":{"paths":["M800 384v306.743l54.626 54.63c9.152 9.152 11.891 22.916 6.938 34.871-4.954 11.959-16.619 19.755-29.564 19.755h-465.73l64.002-64h305.728v-305.732l63.492-63.492c0.337 5.699 0.508 11.441 0.508 17.224zM715.021 179.728l-45.257 45.255c-40.486-40.169-96.226-64.983-157.764-64.983-123.711 0-224 100.288-224 224v222.746l-64 64v-286.746c0-159.058 128.942-288 288-288 79.211 0 150.95 31.978 203.021 83.728zM416 832c0 53.018 42.982 96 96 96 53.022 0 96-42.982 96-96h-192zM879.872 150.62c-12.493-12.497-32.755-12.497-45.252 0l-675.617 675.616c-12.497 12.497-12.497 32.759 0 45.257s32.758 12.497 45.255 0l675.614-675.618c12.497-12.497 12.497-32.758 0-45.255z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["notification-disabled"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":503,"id":40,"name":"notification-disabled","prevSize":32,"code":59791},"setIdx":0,"setId":3,"iconIdx":132},{"icon":{"paths":["M608 832h-192c0 53.018 42.983 96 96 96s96-42.982 96-96zM736 736v-352c0-123.712-100.288-224-224-224s-224 100.288-224 224v352h448zM192 800c-12.943 0-24.611-7.795-29.564-19.755-4.953-11.955-2.215-25.719 6.937-34.871l54.627-54.63v-306.743c0-159.058 128.942-288 288-288 159.057 0 288 128.942 288 288v309.333l41.6 55.467c7.27 9.698 8.444 22.669 3.021 33.51-5.419 10.842-16.499 17.69-28.621 17.69h-624z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["notification"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":504,"id":39,"name":"notification","prevSize":32,"code":59792},"setIdx":0,"setId":3,"iconIdx":133},{"icon":{"paths":["M194.254 320c35.346 0 64-28.654 64-64s-28.654-64-64-64c-35.346 0-64 28.654-64 64s28.654 64 64 64z","M322.254 224c-17.673 0-32 14.327-32 32s14.327 32 32 32h543.999c17.673 0 32-14.327 32-32s-14.327-32-32-32h-543.999z","M194.254 576c35.346 0 64-28.655 64-64s-28.654-64-64-64c-35.346 0-64 28.655-64 64s28.654 64 64 64z","M322.254 480c-17.673 0-32 14.327-32 32s14.327 32 32 32h543.999c17.673 0 32-14.327 32-32s-14.327-32-32-32h-543.999z","M194.254 832c35.346 0 64-28.655 64-64s-28.654-64-64-64c-35.346 0-64 28.655-64 64s28.654 64 64 64z","M322.254 736c-17.673 0-32 14.327-32 32s14.327 32 32 32h543.999c17.673 0 32-14.327 32-32s-14.327-32-32-32h-543.999z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["view-medium"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":505,"id":38,"name":"view-medium","prevSize":32,"code":59793},"setIdx":0,"setId":3,"iconIdx":134},{"icon":{"paths":["M206.090 672c35.346 0 64-28.655 64-64s-28.654-64-64-64c-35.346 0-64 28.655-64 64s28.654 64 64 64z","M334.090 576c-17.673 0-32 14.327-32 32s14.327 32 32 32h543.999c17.673 0 32-14.327 32-32s-14.327-32-32-32h-543.999z","M206.090 480c35.346 0 64-28.655 64-64 0-35.346-28.654-64-64-64s-64 28.654-64 64c0 35.345 28.654 64 64 64z","M334.090 384c-17.673 0-32 14.327-32 32s14.327 32 32 32h543.999c17.673 0 32-14.327 32-32s-14.327-32-32-32h-543.999z","M206.090 288c35.346 0 64-28.654 64-64s-28.654-64-64-64c-35.346 0-64 28.654-64 64s28.654 64 64 64z","M334.090 192c-17.673 0-32 14.327-32 32s14.327 32 32 32h543.999c17.673 0 32-14.327 32-32s-14.327-32-32-32h-543.999z","M206.090 864c35.346 0 64-28.655 64-64s-28.654-64-64-64c-35.346 0-64 28.655-64 64s28.654 64 64 64z","M334.090 768c-17.673 0-32 14.327-32 32s14.327 32 32 32h543.999c17.673 0 32-14.327 32-32s-14.327-32-32-32h-543.999z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["view-condensed"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":506,"id":37,"name":"view-condensed","prevSize":32,"code":59794},"setIdx":0,"setId":3,"iconIdx":135},{"icon":{"paths":["M288 192c0-17.673 14.327-32 32-32h544c17.673 0 32 14.327 32 32s-14.327 32-32 32h-544c-17.673 0-32-14.327-32-32zM288 288c0-17.673 14.327-32 32-32h448c17.673 0 32 14.327 32 32s-14.327 32-32 32h-448c-17.673 0-32-14.327-32-32zM192 304c35.346 0 64-28.654 64-64s-28.654-64-64-64c-35.346 0-64 28.654-64 64s28.654 64 64 64z","M288 464c0-17.673 14.327-32 32-32h544c17.673 0 32 14.327 32 32s-14.327 32-32 32h-544c-17.673 0-32-14.327-32-32zM288 560c0-17.673 14.327-32 32-32h448c17.673 0 32 14.327 32 32s-14.327 32-32 32h-448c-17.673 0-32-14.327-32-32zM192 576c35.346 0 64-28.655 64-64s-28.654-64-64-64c-35.346 0-64 28.655-64 64s28.654 64 64 64z","M288 736c0-17.673 14.327-32 32-32h544c17.673 0 32 14.327 32 32s-14.327 32-32 32h-544c-17.673 0-32-14.327-32-32zM288 832c0-17.673 14.327-32 32-32h448c17.673 0 32 14.327 32 32s-14.327 32-32 32h-448c-17.673 0-32-14.327-32-32zM192 848c35.346 0 64-28.655 64-64s-28.654-64-64-64c-35.346 0-64 28.655-64 64s28.654 64 64 64z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["view-extended"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":507,"id":36,"name":"view-extended","prevSize":32,"code":59795},"setIdx":0,"setId":3,"iconIdx":136},{"icon":{"paths":["M825.374 153.173c12.497-12.48 32.755-12.48 45.252 0s12.497 32.715 0 45.195l-671.999 671.115c-12.497 12.48-32.758 12.48-45.255 0s-12.497-32.717 0-45.197l672.002-671.113zM107.307 479.424c101.801-153.5 303.397-327.248 541.397-225.142l-49.51 49.446c-56.452-19.184-107.934-19.478-153.323-9.713-114.755 24.688-215.37 118.236-280.422 213.585 38.582 47.94 75.869 86.711 111.715 117.73l-45.303 45.244c-39.632-34.692-80.083-77.333-121.157-129.007-14.229-17.903-16.035-43.089-3.398-62.144zM794.227 349.994l-45.269 45.21c35.494 31.386 72.239 70.857 110.037 119.924-61.461 95.061-158.443 188.433-271.761 213.342-46.694 10.266-100.493 9.719-160.384-11.588l-49.266 49.203c244.342 107.191 442.802-69.069 540.065-223.957 11.657-18.564 9.882-42.598-3.392-60.049-40.439-53.163-80.533-96.801-120.030-132.084zM511.599 346.974c13.692 0 26.999 1.57 39.753 4.534l-203.471 203.201c-3.895-13.82-5.974-28.365-5.974-43.379 0-90.772 75.975-164.356 169.693-164.356zM675.494 468.57l-202.995 202.726c12.553 2.867 25.643 4.386 39.1 4.386 93.722 0 169.694-73.583 169.694-164.352 0-14.793-2.018-29.129-5.798-42.761z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["unread-on-top-disabled"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":508,"id":35,"name":"unread-on-top-disabled","prevSize":32,"code":59796},"setIdx":0,"setId":3,"iconIdx":137},{"icon":{"paths":["M587.234 728.474c-107.23 23.573-251.957-9.865-421.785-220.868 65.051-95.352 165.667-188.9 280.422-213.588 108.169-23.272 250.953 10.59 413.124 221.111-61.461 95.061-158.443 188.433-271.761 213.346zM914.257 482.082c-347.132-456.361-668.857-210.879-806.95-2.658-12.638 19.055-10.832 44.241 3.398 62.144 362.307 455.817 676.142 208.862 806.945 0.563 11.657-18.569 9.882-42.598-3.392-60.049zM617.293 511.33c0-53.641-45.457-100.439-105.694-100.439s-105.693 46.799-105.693 100.439c0 53.636 45.456 100.437 105.693 100.437s105.694-46.801 105.694-100.437zM681.293 511.33c0 90.769-75.972 164.352-169.694 164.352-93.718 0-169.693-73.583-169.693-164.352 0-90.771 75.975-164.355 169.693-164.355 93.722 0 169.694 73.584 169.694 164.355z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["unread-on-top"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":509,"id":34,"name":"unread-on-top","prevSize":32,"code":59797},"setIdx":0,"setId":3,"iconIdx":138},{"icon":{"paths":["M544 208c0-17.673-14.323-32-32-32-17.673 0-32 14.327-32 32v271.996h-271.997c-17.673 0-32 14.327-32 32s14.327 32 32 32h271.997v272.004c0 17.673 14.327 32 32 32 17.677 0 32-14.327 32-32v-272.004h272.004c17.673 0 32-14.327 31.996-32 0-17.673-14.323-32-32-32h-272v-271.996z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["add"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":510,"id":33,"name":"add","prevSize":32,"code":59798},"setIdx":0,"setId":3,"iconIdx":139},{"icon":{"paths":["M806.626 262.627c12.497-12.497 12.497-32.758 0-45.255s-32.755-12.497-45.252 0l-249.374 249.371-249.373-249.371c-12.497-12.497-32.758-12.497-45.255 0s-12.497 32.758 0 45.255l249.371 249.373-249.371 249.374c-12.497 12.497-12.497 32.755 0 45.252s32.758 12.497 45.255 0l249.373-249.37 249.374 249.37c12.497 12.497 32.755 12.497 45.252 0s12.497-32.755 0-45.252l-249.37-249.374 249.37-249.373z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["close"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":511,"id":32,"name":"close","prevSize":32,"code":59799},"setIdx":0,"setId":3,"iconIdx":140},{"icon":{"paths":["M416 128c-35.346 0-64 28.654-64 64v226.636c20.775-2.822 42.133-3.455 64-1.527v-225.11h176v180.706c0 35.346 28.655 64 64 64h176v331.294h-120.555c-17.156 22.178-36.322 43.87-57.31 64h177.865c35.345 0 64-28.655 64-64v-363.294c0-6.41-1.924-12.672-5.525-17.975l-156.634-230.682c-11.913-17.545-31.74-28.049-52.945-28.049h-264.896zM656 372.706v-180.706h24.896l122.697 180.706h-147.593zM165.234 668.544c120.524 156.143 218.24 174.588 285.134 158.741 73.293-17.361 139.23-81.647 183.462-151.761-115.153-155.87-211.58-174.588-279.148-158.916-74.361 17.25-142.706 81.685-189.449 151.936zM101.723 649.037c100.621-162.799 337.62-357.19 593.253 1.788 9.071 12.74 10.321 29.82 2.423 43.315-95.275 162.854-326.394 358.345-593.236-0.222-9.745-13.094-11.022-30.997-2.44-44.881zM398.961 735.991c31.512 0 60.269-26.854 60.269-64 0-37.141-28.757-64-60.269-64-31.514 0-60.268 26.859-60.268 64 0 37.146 28.755 64 60.268 64zM398.961 799.991c68.632 0 124.269-57.306 124.269-128 0-70.69-55.637-128-124.269-128s-124.268 57.31-124.268 128c0 70.694 55.637 128 124.268 128z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["auditing"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":512,"id":31,"name":"auditing","prevSize":32,"code":59800},"setIdx":0,"setId":3,"iconIdx":141},{"icon":{"paths":["M416 586.445v177.233l75.516-62.929c11.866-9.89 29.103-9.89 40.969 0l75.516 62.929v-177.233c-29.094 13.82-61.645 21.555-96 21.555s-66.906-7.735-96-21.555zM352 540.766v291.234c0 12.416 7.183 23.71 18.427 28.979 11.244 5.265 24.521 3.554 34.059-4.395l107.514-89.596 107.516 89.596c9.536 7.949 22.814 9.66 34.057 4.395 11.247-5.269 18.428-16.563 18.428-28.979v-291.234c39.59-40.401 64-95.731 64-156.766 0-123.712-100.288-224-224-224s-224 100.288-224 224c0 61.035 24.41 116.365 64 156.766zM416 512.013l-0.015-0.013c-38.854-29.193-63.985-75.661-63.985-128 0-88.366 71.634-160 160-160 88.367 0 160 71.634 160 160 0 52.34-25.131 98.808-63.983 128l-0.017 0.013c-26.739 20.083-59.981 31.987-96 31.987s-69.261-11.904-96-31.987z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["enterprise-feature"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":513,"id":30,"name":"enterprise-feature","prevSize":32,"code":59801},"setIdx":0,"setId":3,"iconIdx":142},{"icon":{"paths":["M749.756 660.215c16.887-16.435 17.259-43.447 0.823-60.335-16.431-16.887-43.443-17.259-60.335-0.823l59.511 61.158zM512 832.021l-29.756 30.579c16.563 16.115 42.948 16.115 59.511 0l-29.756-30.579zM333.754 599.057c-16.889-16.435-43.901-16.064-60.334 0.823s-16.064 43.9 0.825 60.335l59.509-61.158zM690.244 599.057l-208 202.385 59.511 61.158 208-202.385-59.511-61.158zM541.756 801.442l-208.001-202.385-59.509 61.158 207.999 202.385 59.511-61.158z","M749.756 363.805c16.887 16.433 17.259 43.445 0.823 60.334-16.431 16.889-43.443 17.26-60.335 0.826l59.511-61.16zM512 191.999l-29.756-30.58c16.563-16.116 42.948-16.116 59.511 0l-29.756 30.58zM333.754 424.965c-16.889 16.434-43.901 16.063-60.334-0.825s-16.064-43.901 0.825-60.334l59.509 61.159zM690.244 424.965l-208-202.386 59.511-61.159 208 202.386-59.511 61.16zM541.756 222.579l-208.001 202.386-59.509-61.159 207.999-202.386 59.511 61.159z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(158, 162, 168)","opacity":0.7}],"isMulticolor":true,"isMulticolor2":true,"grid":0,"tags":["ordering-ascending"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(158, 162, 168)","opacity":0.7}],"properties":{"order":514,"id":29,"name":"ordering-ascending","prevSize":32,"code":59802,"codes":[59802,59803]},"setIdx":0,"setId":3,"iconIdx":143},{"icon":{"paths":["M274.246 363.785c-16.889 16.433-17.258 43.445-0.825 60.334s43.445 17.259 60.334 0.825l-59.509-61.159zM512 191.978l29.756-30.58c-16.563-16.116-42.948-16.116-59.511 0l29.756 30.58zM690.244 424.944c16.892 16.434 43.904 16.063 60.335-0.825 16.435-16.889 16.064-43.901-0.823-60.334l-59.511 61.159zM333.754 424.944l208.001-202.386-59.511-61.16-207.999 202.386 59.509 61.159zM482.244 222.558l208 202.386 59.511-61.159-208-202.386-59.511 61.16z","M274.246 660.194c-16.889-16.431-17.258-43.443-0.825-60.335 16.433-16.887 43.445-17.259 60.334-0.823l-59.509 61.158zM512 832l29.756 30.579c-16.563 16.115-42.948 16.115-59.511 0l29.756-30.579zM690.244 599.036c16.892-16.435 43.904-16.064 60.335 0.823 16.435 16.892 16.064 43.904-0.823 60.335l-59.511-61.158zM333.754 599.036l208.001 202.385-59.511 61.158-207.999-202.385 59.509-61.158zM482.244 801.421l208-202.385 59.511 61.158-208 202.385-59.511-61.158z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(158, 162, 168)","opacity":0.7}],"isMulticolor":true,"isMulticolor2":true,"grid":0,"tags":["ordering-descending"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(158, 162, 168)","opacity":0.7}],"properties":{"order":515,"id":28,"name":"ordering-descending","prevSize":32,"code":59804,"codes":[59804,59805]},"setIdx":0,"setId":3,"iconIdx":144},{"icon":{"paths":["M448 192c-17.673 0-32 14.327-32 32v128c0 17.673 14.327 32 32 32h128c17.673 0 32-14.327 32-32v-128c0-17.673-14.327-32-32-32h-128z","M416 448c0-17.673 14.327-32 32-32h128c17.673 0 32 14.327 32 32v128c0 17.673-14.327 32-32 32h-128c-17.673 0-32-14.327-32-32v-128z","M416 672c0-17.673 14.327-32 32-32h128c17.673 0 32 14.327 32 32v128c0 17.673-14.327 32-32 32h-128c-17.673 0-32-14.327-32-32v-128z"],"attrs":[{"fill":"rgb(245, 69, 92)"},{"fill":"rgb(245, 69, 92)"},{"fill":"rgb(245, 69, 92)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["priority-high"]},"attrs":[{"fill":"rgb(245, 69, 92)"},{"fill":"rgb(245, 69, 92)"},{"fill":"rgb(245, 69, 92)"}],"properties":{"order":516,"id":27,"name":"priority-high","prevSize":32,"code":59806},"setIdx":0,"setId":3,"iconIdx":145},{"icon":{"paths":["M448 416c-17.673 0-32 14.327-32 32v128c0 17.673 14.327 32 32 32h128c17.673 0 32-14.327 32-32v-128c0-17.673-14.327-32-32-32h-128zM448 640c-17.673 0-32 14.327-32 32v128c0 17.673 14.327 32 32 32h128c17.673 0 32-14.327 32-32v-128c0-17.673-14.327-32-32-32h-128z","M448 192h128c17.673 0 32 14.327 32 32v128c0 17.673-14.327 32-32 32h-128c-17.673 0-32-14.327-32-32v-128c0-17.673 14.327-32 32-32z"],"attrs":[{"fill":"rgb(243, 190, 8)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":true,"isMulticolor2":false,"grid":0,"tags":["priority-medium"]},"attrs":[{"fill":"rgb(243, 190, 8)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":517,"id":26,"name":"priority-medium","prevSize":32,"code":59807,"codes":[59807,59808]},"setIdx":0,"setId":3,"iconIdx":146},{"icon":{"paths":["M448 640h128c17.673 0 32 14.327 32 32v128c0 17.673-14.327 32-32 32h-128c-17.673 0-32-14.327-32-32v-128c0-17.673 14.327-32 32-32z","M448 192c-17.673 0-32 14.327-32 32v128c0 17.673 14.327 32 32 32h128c17.673 0 32-14.327 32-32v-128c0-17.673-14.327-32-32-32h-128zM448 416c-17.673 0-32 14.327-32 32v128c0 17.673 14.327 32 32 32h128c17.673 0 32-14.327 32-32v-128c0-17.673-14.327-32-32-32h-128z"],"attrs":[{"fill":"rgb(45, 224, 165)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":true,"isMulticolor2":false,"grid":0,"tags":["priority-low"]},"attrs":[{"fill":"rgb(45, 224, 165)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":518,"id":25,"name":"priority-low","prevSize":32,"code":59809,"codes":[59809,59810]},"setIdx":0,"setId":3,"iconIdx":147},{"icon":{"paths":["M768 224c17.673 0 32 14.327 32 32v544c0 17.673-14.327 32-32 32h-544c-17.673 0-32-14.327-32-32v-128c17.673 0 32-14.327 32-32s-14.327-32-32-32v-192c17.673 0 32-14.327 32-32s-14.327-32-32-32v-96c0-17.673 14.327-32 32-32h544zM128 608c-17.673 0-32 14.327-32 32s14.327 32 32 32v128c0 53.018 42.981 96 96 96h544c53.018 0 96-42.982 96-96v-544c0-53.019-42.982-96-96-96h-544c-53.019 0-96 42.981-96 96v96c-17.673 0-32 14.327-32 32s14.327 32 32 32v192zM425.205 514.266c13.315-3.567 27.309-3.789 40.732-0.644l31.518 7.39c8.73 2.044 17.83 1.903 26.492-0.418l22.182-5.943c14.289-3.823 29.329-4.036 43.682-0.674 40.431 9.476 69.325 45.585 69.325 87.279v24.337c0 31.812-25.788 57.6-57.6 57.6h-180.736c-31.812 0-57.6-25.788-57.6-57.6v-30.528c0-37.862 25.432-71.002 62.005-80.798zM454.251 563.473c-5.205-1.22-10.633-1.135-15.799 0.247-14.186 3.802-24.051 16.657-24.051 31.343v30.528c0 3.533 2.865 6.4 6.4 6.4h180.736c3.537 0 6.4-2.867 6.4-6.4v-24.337c0-17.749-12.365-33.34-29.807-37.427-6.182-1.451-12.659-1.353-18.752 0.282l-22.187 5.943c-16.811 4.501-34.475 4.779-51.418 0.806l-31.522-7.386zM536.448 420.48c0-13.962-11.315-25.28-25.28-25.28-13.961 0-25.28 11.319-25.28 25.28 0 13.96 11.319 25.28 25.28 25.28 13.965 0 25.28-11.319 25.28-25.28zM587.648 420.48c0 42.24-34.24 76.48-76.48 76.48s-76.48-34.24-76.48-76.48c0-42.239 34.24-76.48 76.48-76.48s76.48 34.242 76.48 76.48z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["contacts"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":519,"id":24,"name":"contacts","prevSize":32,"code":59811},"setIdx":0,"setId":3,"iconIdx":148},{"icon":{"paths":["M302.769 192h418.464l23.185 72.727h-0.213l23.795 64c0 41.27-31.305 69.818-64 69.818s-64-28.548-64-69.818c0-18.477-14.327-33.455-32-33.455s-32 14.978-32 33.455c0 41.27-31.305 69.818-64 69.818s-64-28.548-64-69.818c0-18.477-14.327-33.455-32-33.455s-32 14.978-32 33.455c0 41.27-31.305 69.818-64 69.818s-64-28.548-64-69.818l23.793-64h-0.213l23.188-72.727zM212.406 264.727l36.491-114.448c4.231-13.27 16.56-22.279 30.488-22.279h465.23c13.931 0 26.257 9.009 30.49 22.279l56.896 178.448c0 33.937-12.083 64.925-32 88.515v350.775c0 53.022-42.982 96-96 96h-384c-53.019 0-96-42.978-96-96v-350.775c-19.916-23.59-32-54.577-32-88.515l20.406-64zM288 458.33v309.687c0 17.673 14.327 32 32 32h128v-192.017h128v192.017h128c17.673 0 32-14.327 32-32v-309.687c-10.227 2.752-20.949 4.215-32 4.215-38.229 0-72.546-17.523-96-45.303-23.454 27.78-57.771 45.303-96 45.303s-72.546-17.523-96-45.303c-23.454 27.78-57.77 45.303-96 45.303-11.049 0-21.772-1.463-32-4.215z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["marketplace"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":520,"id":23,"name":"marketplace","prevSize":32,"code":59812},"setIdx":0,"setId":3,"iconIdx":149},{"icon":{"paths":["M224 224c-17.673 0-32 14.327-32 32v544c0 17.673 14.327 32 32 32h544c17.673 0 32-14.327 32-32v-544c0-17.673-14.327-32-32-32h-544zM128 256c0-53.019 42.981-96 96-96h544c53.018 0 96 42.981 96 96v544c0 53.018-42.982 96-96 96h-544c-53.019 0-96-42.982-96-96v-544zM608 460.813c0 41.801-26.714 77.359-64 90.539v133.461h-64v-133.461c-37.286-13.18-64-48.738-64-90.539 0-53.020 42.982-96 96-96s96 42.981 96 96zM608 588.826c38.861-29.193 64-75.665 64-128.013 0-88.366-71.633-160-160-160-88.366 0-160 71.635-160 160 0 52.348 25.138 98.82 64 128.013v127.987c0 17.673 14.327 32 32 32h128c17.673 0 32-14.327 32-32v-127.987z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["auth"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":521,"id":22,"name":"auth","prevSize":32,"code":59813},"setIdx":0,"setId":3,"iconIdx":150},{"icon":{"paths":["M623.091 896c-2.803 0-5.299-0.623-7.168-0.939-61.999-16.858-102.818-39.646-145.813-80.858-55.147-54.007-85.369-125.815-85.369-202.3 0-65.873 56.705-119.573 126.495-119.573 69.794 0 126.498 53.7 126.498 119.573 0 34.965 31.467 63.373 69.79 63.373s69.794-28.407 69.794-63.373c0-135.808-119.646-246.636-266.705-246.636-104.997 0-200.337 57.132-243.334 145.793-14.332 29.35-21.498 63.066-21.498 100.843 0 28.719 2.493 73.365 24.925 131.746 2.804 7.181 2.493 14.673-0.623 21.854-3.116 6.865-9.036 11.861-16.201 14.357-2.804 1.25-6.231 1.562-9.658 1.562-11.84 0-22.433-7.181-26.484-18.108-19.005-50.261-28.352-99.9-28.352-151.727 0-46.204 9.036-88.35 26.795-125.5 52.343-108.020 167.935-177.64 294.431-177.64 178.53 0 323.721 135.805 323.721 302.828 0 65.873-56.704 119.573-126.81 119.573-70.101 0-126.805-53.7-126.805-119.573 0-34.965-31.471-63.373-69.794-63.373-38.635 0-69.79 28.407-69.79 63.373 0 61.504 24.303 119.262 68.544 162.342 35.209 34.031 68.855 53.073 120.576 67.123 7.168 1.873 13.397 6.554 17.139 13.111 3.738 6.558 4.672 14.362 2.803 21.231-2.803 11.861-14.020 20.915-27.106 20.915zM426.803 888.196c-7.79 0-15.267-3.123-20.253-8.742-33.338-32.781-51.72-54.012-77.892-100.527-26.795-47.142-41.127-105.212-41.127-167.339 0-116.446 100.948-211.354 224.95-211.354 124.006 0 224.956 94.908 224.956 211.354 0 15.612-12.463 28.1-28.356 28.1-15.889 0-28.663-12.177-28.663-28.1 0-85.538-75.401-155.157-168.247-155.157-92.846 0-168.245 69.619-168.245 155.157 0 52.45 11.84 100.527 34.272 139.554 23.368 41.519 38.946 59.004 68.855 88.661 10.906 11.238 10.906 28.723 0 39.65-5.918 5.931-13.086 8.742-20.25 8.742zM699.738 818.889c-47.36 0-88.798-11.866-123.383-34.965-59.196-39.65-94.716-103.962-94.716-172.335 0-15.607 12.463-28.096 28.352-28.096s28.352 12.489 28.352 28.096c0 49.643 26.172 96.781 69.794 125.504 25.237 16.858 55.147 24.977 91.601 24.977 7.787 0 22.43-0.939 38.012-3.746 1.557-0.311 3.426-0.311 4.983-0.311 13.709 0 25.237 9.988 27.729 23.411 1.246 7.181-0.311 14.673-4.361 20.608-4.365 6.242-10.906 10.611-18.697 11.861-23.364 4.685-43.93 4.996-47.667 4.996zM188.765 435.823c-5.608 0-11.216-1.562-16.201-4.992-6.543-4.062-10.593-10.616-12.151-18.109-1.246-7.493 0.311-14.985 4.985-21.229 38.634-53.698 87.862-95.844 146.125-125.502 60.133-30.595 129.612-46.829 200.96-46.829 71.040 0 140.207 15.922 200.030 46.205 58.573 29.658 107.802 71.493 146.125 124.566 4.361 5.932 6.229 13.425 4.983 20.917s-5.606 14.049-11.84 18.42c-4.983 3.435-10.594 4.992-16.512 4.992-9.037 0-17.758-4.369-23.057-11.861-33.335-45.893-75.712-82.107-125.559-107.083-52.343-26.224-112.789-40.273-174.481-40.273-62.31 0-122.756 14.049-175.1 40.585-49.851 25.912-92.535 62.127-126.185 108.644-3.739 6.869-12.463 11.55-22.121 11.55zM733.696 239.142c-4.672 0-9.344-1.249-13.397-3.434-71.347-35.902-133.35-51.512-207.505-51.512-74.462 0-144.254 17.483-207.814 51.825-4.050 2.185-8.724 3.122-13.397 3.122-10.282 0-19.629-5.62-24.925-14.361-3.739-6.556-4.674-14.361-2.493-21.542s7.166-13.424 13.709-16.858c72.596-38.712 151.733-58.38 234.921-58.38 82.569 0 154.85 17.795 233.988 58.068 6.857 3.434 11.84 9.366 14.332 16.858 2.185 7.18 1.246 14.673-2.18 21.229-4.983 9.053-14.643 14.985-25.237 14.985z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["fingerprint"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":522,"id":21,"name":"fingerprint","prevSize":32,"code":59814},"setIdx":0,"setId":3,"iconIdx":151},{"icon":{"paths":["M737.779 361.376c12.497 12.497 12.497 32.758 0 45.255l-110.946 110.95 110.946 110.946c12.497 12.497 12.497 32.759 0 45.257s-32.759 12.497-45.252 0l-110.95-110.95-110.95 110.95c-12.497 12.497-32.755 12.497-45.254 0-12.497-12.497-12.497-32.759 0-45.257l110.947-110.946-110.947-110.95c-12.497-12.497-12.497-32.758 0-45.255 12.498-12.497 32.756-12.497 45.254 0l110.95 110.948 110.95-110.948c12.493-12.497 32.755-12.497 45.252 0z","M312.247 218.073c12.061-16.393 31.199-26.073 51.551-26.073h468.202c35.345 0 64 28.654 64 64v512c0 35.345-28.655 64-64 64h-468.202c-20.352 0-39.491-9.681-51.551-26.074l-188.343-256c-16.598-22.562-16.598-53.291 0-75.853l188.343-256zM363.798 256l-188.343 256 188.343 256h468.202v-512h-468.202z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["backspace"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":523,"id":20,"name":"backspace","prevSize":32,"code":59815},"setIdx":0,"setId":3,"iconIdx":152},{"icon":{"paths":["M208 176c-35.346 0-64 28.654-64 64v576c0 35.345 28.654 64 64 64h576c35.345 0 64-28.655 64-64v-576c0-35.346-28.655-64-64-64h-576zM208 240h576v576h-576v-576zM698.628 558.153c-0.192 17.673-14.669 31.842-32.341 31.654s-31.846-14.669-31.659-32.341l1.323-123.588-309.344 308.77c-12.508 12.484-32.77 12.467-45.255-0.043-12.485-12.506-12.466-32.768 0.042-45.252l309.199-308.627-123.388 1.318c-17.673 0.189-32.149-13.984-32.337-31.657-0.192-17.672 13.982-32.151 31.654-32.34l201.92-2.156c8.606-0.092 16.887 3.286 22.972 9.371s9.459 14.364 9.37 22.969l-2.155 201.922z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["new-window"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":524,"id":19,"name":"new-window","prevSize":32,"code":59816},"setIdx":0,"setId":3,"iconIdx":153},{"icon":{"paths":["M464 318.068c0-51.548-42.408-94.366-96-94.366s-96 42.819-96 94.366c0 51.548 42.408 94.367 96 94.367s96-42.819 96-94.367zM528 318.068c0 87.417-71.633 158.284-160 158.284-88.366 0-160-70.867-160-158.284s71.634-158.282 160-158.282c88.367 0 160 70.865 160 158.282zM281.778 525.035c-27.649-7.693-56.976-7.159-84.32 1.536-60.46 19.226-101.459 74.863-101.459 137.685v103.633c0 52.45 42.981 94.967 96 94.967h352c3.605 0 7.164-0.196 10.667-0.576v-64.538c-3.337 1.169-6.925 1.801-10.667 1.801h-352c-17.673 0-32-14.17-32-31.654v-103.633c0-35.319 23.051-66.603 57.043-77.41 15.374-4.89 31.862-5.188 47.407-0.866l48.489 13.491c36.311 10.103 74.826 9.404 110.737-2.018l30.1-9.57c17.502-5.564 36.275-5.905 53.978-0.981 18.901 5.257 35.063 16.038 46.912 30.281v-79.714c-9.31-4.749-19.204-8.627-29.585-11.516-29.803-8.29-61.414-7.714-90.889 1.655l-30.101 9.57c-23.941 7.616-49.617 8.081-73.825 1.348l-48.489-13.491zM763.366 489.033c-12.326-12.651-32.585-12.919-45.248-0.61s-12.937 32.542-0.61 45.193l102.839 105.506h-324.348c-17.673 0-32 14.31-32 31.962 0 17.647 14.327 31.957 32 31.957h324.348l-102.839 105.51c-12.326 12.646-12.053 32.879 0.61 45.188 12.663 12.314 32.922 12.041 45.248-0.606l155.721-159.761c12.092-12.407 12.092-32.175 0-44.582l-155.721-159.757z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["user-forward"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":525,"id":18,"name":"user-forward","prevSize":32,"code":59817},"setIdx":0,"setId":3,"iconIdx":154},{"icon":{"paths":["M320 159.791c0-17.649-14.327-31.958-32-31.958h-64c-17.673 0-32 14.308-32 31.958v63.916c0 17.65 14.327 31.958 32 31.958h64c17.673 0 32-14.308 32-31.958v-63.916zM320 585.894c0-17.651-14.327-31.957-32-31.957h-64c-17.673 0-32 14.306-32 31.957v63.915c0 17.651 14.327 31.957 32 31.957h64c17.673 0 32-14.306 32-31.957v-63.915zM448 159.791c0-17.649 14.327-31.958 32-31.958h64c17.673 0 32 14.308 32 31.958v63.916c0 17.65-14.327 31.958-32 31.958h-64c-17.673 0-32-14.308-32-31.958v-63.916zM576 372.843c0-17.65-14.327-31.958-32-31.958h-64c-17.673 0-32 14.308-32 31.958v63.914c0 17.651 14.327 31.957 32 31.957h64c17.673 0 32-14.306 32-31.957v-63.914zM448 585.894c0-17.651 14.327-31.957 32-31.957h64c17.673 0 32 14.306 32 31.957v63.915c0 17.651-14.327 31.957-32 31.957h-64c-17.673 0-32-14.306-32-31.957v-63.915zM576 798.946c0-17.651-14.327-31.957-32-31.957h-64c-17.673 0-32 14.306-32 31.957v63.915c0 17.651 14.327 31.957 32 31.957h64c17.673 0 32-14.306 32-31.957v-63.915zM704 159.791c0-17.649 14.327-31.958 32-31.958h64c17.673 0 32 14.308 32 31.958v63.916c0 17.65-14.327 31.958-32 31.958h-64c-17.673 0-32-14.308-32-31.958v-63.916zM832 372.843c0-17.65-14.327-31.958-32-31.958h-64c-17.673 0-32 14.308-32 31.958v63.914c0 17.651 14.327 31.957 32 31.957h64c17.673 0 32-14.306 32-31.957v-63.914zM704 585.894c0-17.651 14.327-31.957 32-31.957h64c17.673 0 32 14.306 32 31.957v63.915c0 17.651-14.327 31.957-32 31.957h-64c-17.673 0-32-14.306-32-31.957v-63.915zM320 372.843c0-17.65-14.327-31.958-32-31.958h-64c-17.673 0-32 14.308-32 31.958v63.914c0 17.651 14.327 31.957 32 31.957h64c17.673 0 32-14.306 32-31.957v-63.914z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["dialpad"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":526,"id":17,"name":"dialpad","prevSize":32,"code":59818},"setIdx":0,"setId":3,"iconIdx":155},{"icon":{"paths":["M482.325 229.047c19.767-23.931 49.89-36.827 80.849-34.615l143.936 10.281c42.052 3.004 77.222 33.091 86.703 74.17l30.349 131.517c6.643 28.785-0.337 59.028-18.923 81.991l-252.369 311.744c-11.119 13.739-31.27 15.859-45.005 4.74-13.734-11.123-15.859-31.27-4.736-45.009l252.365-311.744c6.195-7.654 8.521-17.737 6.306-27.331l-30.349-131.517c-3.157-13.693-14.882-23.722-28.898-24.723l-143.936-10.281c-10.321-0.737-20.361 3.561-26.953 11.538l-265.999 322c-5.438 6.583-8.020 15.066-7.17 23.565l7.581 75.81c1.636 16.358 15.401 28.817 31.841 28.817h104.305c9.439 0 18.397-4.169 24.476-11.388l227.597-270.268-10.052-70.344h-69.257l-230.406 276.488c-11.314 13.577-31.492 15.411-45.069 4.096s-15.412-31.492-4.097-45.069l230.403-276.487c12.16-14.592 30.174-23.028 49.169-23.028h69.257c31.851 0 58.854 23.419 63.356 54.949l10.052 70.345c2.577 18.044-2.662 36.331-14.404 50.274l-227.593 270.268c-18.24 21.662-45.116 34.163-73.432 34.163h-104.305c-49.321 0-90.616-37.372-95.524-86.447l-7.581-75.814c-2.549-25.489 5.196-50.944 21.511-70.694l266-321.997z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["attach"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":527,"id":16,"name":"attach","prevSize":32,"code":59819},"setIdx":0,"setId":3,"iconIdx":156},{"icon":{"paths":["M896 512h-63.987c0-175.415-145.749-320-328.516-320-115.27 0-215.817 57.513-274.36 144h110.768c17.673 0 32 14.327 32 32s-14.327 32-32 32h-179.904c-17.673 0-32-14.327-32-32v-192c0-17.673 14.327-32 32-32s32 14.327 32 32v102.32c71.751-91.401 184.591-150.32 311.497-150.32 216.781 0 392.503 171.923 392.503 384 0 1.114 0.009 2.227 0 3.337v-3.337z","M127.997 512h63.986c0 175.415 145.751 320 328.52 320 115.268 0 215.817-57.515 274.359-144h-110.767c-17.677 0-32-14.327-32-32s14.323-32 32-32h179.904c17.673 0 32 14.327 32 32v192c0 17.673-14.327 32-32 32s-32-14.327-32-32v-102.319c-71.753 91.401-184.593 150.319-311.497 150.319-216.783 0-392.506-171.921-392.506-384 0-1.084-0.009-2.163 0-3.247v3.247z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["refresh"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":528,"id":15,"name":"refresh","prevSize":32,"code":59820},"setIdx":0,"setId":3,"iconIdx":157},{"icon":{"paths":["M512 832c176.73 0 320-143.27 320-320 0-176.731-143.27-320-320-320-111.713 0-210.056 57.245-267.295 144h107.295c17.673 0 32 14.327 32 32s-14.327 32-32 32h-176c-17.673 0-32-14.327-32-32v-192c0-17.673 14.327-32 32-32s32 14.327 32 32v101.364c70.228-90.856 180.282-149.364 304-149.364 212.079 0 384 171.923 384 384 0 212.079-171.921 384-384 384-212.077 0-384-171.921-384-384h64c0 176.73 143.269 320 320 320z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["undo"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":529,"id":14,"name":"undo","prevSize":32,"code":59821},"setIdx":0,"setId":3,"iconIdx":158},{"icon":{"paths":["M553.412 325.606c0 91.58-75.849 165.821-169.412 165.821s-169.412-74.241-169.412-165.821c0-91.579 75.848-165.819 169.412-165.819s169.412 74.24 169.412 165.819zM485.649 325.606c0-54.947-45.513-99.491-101.649-99.491-56.138 0-101.647 44.544-101.647 99.491s45.509 99.492 101.647 99.492c56.137 0 101.649-44.544 101.649-99.492z","M203.427 510.558c28.952-9.109 60.004-9.668 89.279-1.613l51.342 14.135c25.632 7.057 52.819 6.566 78.167-1.408l31.873-10.027c31.206-9.822 64.678-10.423 96.23-1.737 71.962 19.81 121.681 84.049 121.681 157.218v96.239c0 54.946-45.508 99.49-101.649 99.49h-372.704c-56.138 0-101.647-44.544-101.647-99.49v-108.565c0-65.818 43.411-124.105 107.427-144.243zM274.359 572.796c-16.46-4.531-33.918-4.215-50.196 0.905-35.992 11.324-60.399 44.096-60.399 81.101v108.565c0 18.317 15.169 33.165 33.882 33.165h372.704c18.714 0 33.886-14.848 33.886-33.165v-96.239c0-43.452-29.53-81.604-72.265-93.367-18.739-5.158-38.618-4.8-57.148 1.028l-31.872 10.031c-38.024 11.959-78.804 12.698-117.251 2.112l-51.342-14.135z","M797.090 188.646c0-15.913-13.022-28.812-29.090-28.812s-29.090 12.9-29.090 28.812v100.844h-101.82c-16.064 0-29.090 12.9-29.090 28.812s13.026 28.813 29.090 28.813h101.82v100.842c0 15.915 13.022 28.813 29.090 28.813s29.090-12.898 29.090-28.813v-100.842h101.82c16.064 0 29.090-12.9 29.090-28.813s-13.026-28.812-29.090-28.812h-101.82v-100.844z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["user-add"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":530,"id":13,"name":"user-add","prevSize":32,"code":59822},"setIdx":0,"setId":3,"iconIdx":159},{"icon":{"paths":["M608 192c0-53.019-42.982-96-96-96s-96 42.981-96 96h-192c-17.673 0-32 14.327-32 32v672c0 17.673 14.327 32 32 32h576c17.673 0 32-14.327 32-32v-672c0-17.673-14.327-32-32-32h-192zM256 864v-608h96v64c0 17.673 14.327 32 32 32h256c17.673 0 32-14.327 32-32v-64h96v608h-512zM512 224c17.673 0 32-14.327 32-32s-14.327-32-32-32c-17.673 0-32 14.327-32 32s14.327 32 32 32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["clipboard"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":531,"id":12,"name":"clipboard","prevSize":32,"code":59823},"setIdx":0,"setId":3,"iconIdx":160},{"icon":{"paths":["M341.335 778.671c-17.673 0-32 14.327-32 32s14.327 32 32 32h341.332c17.673 0 32-14.327 32-32s-14.327-32-32-32h-341.332zM85.335 298.672c0-70.692 57.308-128 128-128h597.332c70.694 0 128 57.308 128 128v298.666c0 70.694-57.306 128-128 128h-597.332c-70.693 0-128-57.306-128-128v-298.666zM213.335 234.672c-35.346 0-64 28.654-64 64v298.666c0 35.349 28.654 64 64 64h597.332c35.349 0 64-28.655 64-64v-298.666c0-35.346-28.651-64-64-64h-597.332zM256 320c0-11.782 9.551-21.333 21.333-21.333h170.667c11.78 0 21.333 9.551 21.333 21.333s-9.553 21.333-21.333 21.333h-170.667c-11.782 0-21.333-9.551-21.333-21.333zM277.333 554.667c-11.782 0-21.333 9.553-21.333 21.333s9.551 21.333 21.333 21.333h85.333c11.782 0 21.333-9.553 21.333-21.333s-9.551-21.333-21.333-21.333h-85.333zM554.667 320c0-11.782 9.553-21.333 21.333-21.333h170.667c11.78 0 21.333 9.551 21.333 21.333s-9.553 21.333-21.333 21.333h-170.667c-11.78 0-21.333-9.551-21.333-21.333zM448 554.667c-11.78 0-21.333 9.553-21.333 21.333s9.553 21.333 21.333 21.333h298.667c11.78 0 21.333-9.553 21.333-21.333s-9.553-21.333-21.333-21.333h-298.667zM256 448c0-11.78 9.551-21.333 21.333-21.333h213.333c11.78 0 21.333 9.553 21.333 21.333s-9.553 21.333-21.333 21.333h-213.333c-11.782 0-21.333-9.553-21.333-21.333zM618.667 426.667c-11.78 0-21.333 9.553-21.333 21.333s9.553 21.333 21.333 21.333h128c11.78 0 21.333-9.553 21.333-21.333s-9.553-21.333-21.333-21.333h-128z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["log-view"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":532,"id":11,"name":"log-view","prevSize":32,"code":59824},"setIdx":0,"setId":3,"iconIdx":161},{"icon":{"paths":["M341.335 778.671c-17.673 0-32 14.327-32 32s14.327 32 32 32h341.332c17.673 0 32-14.327 32-32s-14.327-32-32-32h-341.332z","M85.335 298.672c0-70.692 57.308-128 128-128h597.332c70.694 0 128 57.308 128 128v298.666c0 70.694-57.306 128-128 128h-597.332c-70.693 0-128-57.306-128-128v-298.666zM213.335 234.672c-35.346 0-64 28.654-64 64v298.666c0 35.349 28.654 64 64 64h597.332c35.349 0 64-28.655 64-64v-298.666c0-35.346-28.651-64-64-64h-597.332z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["desktop"]},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":533,"id":10,"name":"desktop","prevSize":32,"code":59825},"setIdx":0,"setId":3,"iconIdx":162},{"icon":{"paths":["M403.11 199.401c17.543-17.543 45.987-17.543 63.531 0 17.54 17.543 17.54 45.987 0 63.53l-43.66 43.659 177.83 177.827 60.339-60.338c24.994-24.994 65.515-24.994 90.509 0l45.257 45.256-331.87 331.87-45.255-45.257c-24.994-24.994-24.994-65.515 0-90.509l60.338-60.339-177.827-177.83-43.66 43.661c-17.543 17.545-45.987 17.545-63.53 0s-17.543-45.986 0-63.529l207.999-207.999zM149.856 362.145c-42.537 42.537-42.537 111.502 0 154.041 42.001 42.001 109.771 42.53 152.421 1.583l87.335 87.339-15.077 15.074c-49.987 49.988-49.987 131.034 0 181.022l67.884 67.878c12.497 12.497 32.755 12.497 45.252 0l167.936-167.932 88.013 92.002c12.215 12.77 32.474 13.222 45.244 1.003 12.77-12.215 13.218-32.474 1.003-45.244l-88.994-93.026 163.925-163.925c12.493-12.497 12.493-32.759 0-45.257l-67.883-67.88c-49.988-49.987-131.034-49.987-181.022 0l-15.906 15.907-87.322-87.322c41.762-42.596 41.506-110.984-0.772-153.262-42.534-42.537-111.502-42.537-154.038 0l-207.999 207.999z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["pin"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":534,"id":9,"name":"pin","prevSize":32,"code":59826},"setIdx":0,"setId":3,"iconIdx":163},{"icon":{"paths":["M593.937 170.244c-20.864-57.726-103.155-55.816-121.318 2.816l-58.978 190.35h-221.512c-58.947 0-86.549 72.943-42.37 111.965l157.591 139.204-53.209 216.93c-14.17 57.771 51.25 101.935 99.535 67.2l177.739-127.881 177.741 127.881c48.286 34.735 113.707-9.429 99.537-67.2l-53.389-217.651 147.891-139.968c42.031-39.778 13.879-110.481-43.994-110.481h-195.439l-69.824-193.165z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["star-filled"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":535,"id":8,"name":"star-filled","prevSize":32,"code":59827},"setIdx":0,"setId":3,"iconIdx":164},{"icon":{"paths":["M472.619 172.834c18.163-58.554 100.454-60.462 121.318-2.812l69.824 192.91h195.439c57.873 0 86.025 70.608 43.994 110.335l-147.891 139.785 53.389 217.361c14.17 57.694-51.251 101.803-99.537 67.11l-177.741-127.706-177.739 127.706c-48.284 34.692-113.705-9.417-99.535-67.11l53.209-216.64-157.591-139.021c-44.179-38.976-16.577-111.82 42.37-111.82h221.512l58.978-190.098zM603.571 384.66l-69.82-192.91-58.978 190.098c-8.303 26.758-33.084 44.998-61.133 44.998h-221.512l157.591 139.025c17.834 15.731 25.456 40.047 19.787 63.125l-53.209 216.644 177.74-127.706c22.332-16.047 52.425-16.047 74.756 0l177.741 127.706-53.389-217.361c-5.478-22.319 1.455-45.854 18.167-61.649l147.887-139.785h-195.439c-26.957 0-51.025-16.868-60.19-42.186z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["star"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":536,"id":7,"name":"star","prevSize":32,"code":59828},"setIdx":0,"setId":3,"iconIdx":165},{"icon":{"paths":["M708.723 449.771c0-142.502-115.674-258.022-258.364-258.022-142.687 0-258.359 115.52-258.359 258.022s115.673 258.022 258.359 258.022c142.69 0 258.364-115.52 258.364-258.022zM654.379 699.042c-55.573 45.419-126.609 72.666-204.019 72.666-178.033 0-322.359-144.137-322.359-321.937s144.326-321.937 322.359-321.937c178.035 0 322.364 144.137 322.364 321.937 0 77.303-27.281 148.245-72.755 203.742l186.59 186.347c12.591 12.574 12.591 32.956 0 45.53-12.587 12.574-32.998 12.574-45.589 0l-186.59-186.347z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["search"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":537,"id":6,"name":"search","prevSize":32,"code":59829},"setIdx":0,"setId":3,"iconIdx":166},{"icon":{"paths":["M336 304c0-97.202 78.798-176 176-176 97.203 0 176 78.798 176 176v142.477h16c53.018 0 96 42.978 96 96v257.523c0 53.018-42.982 96-96 96h-384c-53.019 0-96-42.982-96-96v-257.523c0-53.022 42.981-96 96-96h16v-142.477zM400 446.477h224v-142.477c0-61.856-50.146-112-112-112s-112 50.144-112 112v142.477zM320 510.477c-17.673 0-32 14.327-32 32v257.523c0 17.673 14.327 32 32 32h384c17.673 0 32-14.327 32-32v-257.523c0-17.673-14.327-32-32-32h-384z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["channel-private"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":538,"id":5,"name":"channel-private","prevSize":32,"code":59830},"setIdx":0,"setId":3,"iconIdx":167},{"icon":{"paths":["M512 864c-194.404 0-352-157.598-352-352 0-194.404 157.596-352 352-352 194.406 0 352 157.596 352 352 0 194.402-157.594 352-352 352zM512 928c229.751 0 416-186.249 416-416s-186.249-416-416-416c-229.751 0-416 186.249-416 416s186.249 416 416 416zM662.626 361.373c12.497 12.497 12.497 32.758 0 45.255l-105.37 105.373 105.37 105.374c12.497 12.497 12.497 32.755 0 45.252s-32.755 12.497-45.252 0l-105.374-105.37-105.373 105.37c-12.497 12.497-32.758 12.497-45.255 0s-12.497-32.755 0-45.252l105.371-105.374-105.371-105.373c-12.497-12.497-12.497-32.758 0-45.255s32.758-12.497 45.255 0l105.373 105.371 105.374-105.371c12.497-12.497 32.755-12.497 45.252 0z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["input-clear"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":539,"id":4,"name":"input-clear","prevSize":32,"code":59831},"setIdx":0,"setId":3,"iconIdx":168},{"icon":{"paths":["M875.273 512c0-86.89-31.484-166.427-83.665-227.826l-496.163 496.161c61.399 52.181 140.937 83.665 227.828 83.665 194.402 0 352-157.598 352-352zM250.62 734.652l495.3-495.302c-60.659-49.597-138.18-79.349-222.647-79.349-194.406 0-352.002 157.596-352.002 352 0 84.467 29.752 161.988 79.349 222.652zM939.273 512c0 229.751-186.253 416-416 416-229.752 0-416.002-186.249-416.002-416s186.249-416 416.002-416c229.747 0 416 186.249 416 416z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"width":1067,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["ban"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":540,"id":3,"name":"ban","prevSize":32,"code":59832},"setIdx":0,"setId":3,"iconIdx":169},{"icon":{"paths":["M368 412.435c-53.592 0-96-42.819-96-94.367s42.408-94.366 96-94.366c53.592 0 96 42.819 96 94.366s-42.408 94.367-96 94.367zM368 476.352c88.367 0 160-70.867 160-158.284s-71.633-158.282-160-158.282c-88.366 0-160 70.865-160 158.282s71.634 158.284 160 158.284zM713.6 396.606c-35.921 0-64-28.646-64-62.71s28.079-62.71 64-62.71c35.921 0 64 28.646 64 62.71s-28.079 62.71-64 62.71zM713.6 460.523c70.69 0 128-56.693 128-126.626s-57.31-126.626-128-126.626c-70.694 0-128 56.692-128 126.626s57.306 126.626 128 126.626zM197.459 526.571c27.344-8.695 56.671-9.229 84.32-1.536l48.489 13.491c24.207 6.733 49.884 6.268 73.824-1.348l30.101-9.57c29.474-9.37 61.086-9.946 90.889-1.655 67.964 18.91 114.918 80.226 114.918 150.071v91.866c0 52.45-42.982 94.967-96 94.967h-352c-53.019 0-96-42.517-96-94.967v-103.633c0-62.822 40.999-118.46 101.459-137.685zM264.451 585.98c-15.545-4.322-32.034-4.023-47.407 0.866-33.993 10.807-57.044 42.091-57.044 77.41v103.633c0 17.485 14.327 31.654 32 31.654h352c17.673 0 32-14.17 32-31.654v-91.866c0-41.476-27.887-77.892-68.245-89.122-17.702-4.924-36.476-4.582-53.978 0.981l-30.1 9.57c-35.91 11.422-74.426 12.122-110.737 2.018l-48.489-13.491zM691.2 777.685h140.8c53.018 0 96-42.923 96-95.872v-30.571c0-56.802-38.613-106.351-93.747-120.294-21.397-5.414-43.853-5.035-65.058 1.092l-16.397 4.745c-21.845 6.31-44.975 6.703-67.017 1.126l-29.807-7.539c-19.908-5.035-40.798-4.685-60.523 1.015-1.062 0.311-2.121 0.631-3.174 0.969 10.714 4.045 20.898 9.527 30.255 16.354l2.428 1.771 15.040 13.193c9.937 8.713 18.142 19.221 24.183 30.972l2.206 4.292 3.678 0.934c33.062 8.363 67.759 7.778 100.523-1.694l16.401-4.74c10.283-2.974 21.171-3.157 31.548-0.529 26.735 6.763 45.461 30.788 45.461 58.334v30.571c0 17.651-14.327 31.957-32 31.957h-140.8v63.915z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["team"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":541,"id":2,"name":"team","prevSize":32,"code":59833},"setIdx":0,"setId":3,"iconIdx":170},{"icon":{"paths":["M608 336c0-53.019-42.982-96-96-96s-96 42.981-96 96c0 53.019 42.982 96 96 96s96-42.981 96-96zM672 336c0 88.366-71.633 160-160 160-88.366 0-160-71.634-160-160s71.634-160 160-160c88.367 0 160 71.634 160 160zM412.451 551.799c-24.621-5.769-50.286-5.363-74.713 1.178-67.087 17.971-113.738 78.763-113.738 148.215v66.807c0 53.018 42.981 96 96 96h384c53.018 0 96-42.982 96-96v-58.53c0-74.3-51.149-138.825-123.49-155.78l-6.455-1.51c-25.673-6.020-52.437-5.598-77.909 1.225l-49.626 13.295c-20.378 5.457-41.788 5.794-62.327 0.981l-67.741-15.881zM354.297 614.797c14.238-3.81 29.199-4.049 43.55-0.683l67.744 15.876c30.805 7.219 62.921 6.716 93.487-1.472l49.626-13.295c15.283-4.092 31.343-4.343 46.746-0.734l6.455 1.51c43.405 10.176 74.095 48.887 74.095 93.47v58.53c0 17.673-14.327 32-32 32h-384c-17.673 0-32-14.327-32-32v-66.807c0-40.486 27.193-75.921 66.297-86.396z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["user"]},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":542,"id":1,"name":"user","prevSize":32,"code":59834},"setIdx":0,"setId":3,"iconIdx":171}],"height":1024,"metadata":{"name":"custom"},"preferences":{"showGlyphs":true,"showQuickUse":true,"showQuickUse2":true,"showSVGs":true,"fontPref":{"prefix":"icon-","metadata":{"fontFamily":"custom","majorVersion":1,"minorVersion":0},"metrics":{"emSize":1024,"baseline":6.25,"whitespace":50},"embed":false,"noie8":true,"ie7":false,"showSelector":false,"showMetrics":false,"showMetadata":false,"showVersion":false},"imagePref":{"prefix":"icon-","png":true,"useClassSelector":true,"color":0,"bgColor":16777215,"classSelector":".icon"},"historySize":50,"showCodes":true,"gridSize":16}}
\ No newline at end of file
diff --git a/app/notifications/push/index.js b/app/notifications/push/index.js
index 865a6ad61..40ccbea16 100644
--- a/app/notifications/push/index.js
+++ b/app/notifications/push/index.js
@@ -10,7 +10,7 @@ export const onNotification = (notification) => {
if (data) {
try {
const {
- rid, name, sender, type, host
+ rid, name, sender, type, host, messageType
} = EJSON.parse(data.ejson);
const types = {
@@ -24,7 +24,8 @@ export const onNotification = (notification) => {
const params = {
host,
rid,
- path: `${ types[type] }/${ roomName }`
+ path: `${ types[type] }/${ roomName }`,
+ isCall: messageType === 'jitsi_call_started'
};
store.dispatch(deepLinkingOpen(params));
} catch (e) {
diff --git a/app/presentation/ImageViewer/ImageComponent.js b/app/presentation/ImageViewer/ImageComponent.js
index cb365f03e..cf00e4322 100644
--- a/app/presentation/ImageViewer/ImageComponent.js
+++ b/app/presentation/ImageViewer/ImageComponent.js
@@ -6,7 +6,7 @@ export const ImageComponent = (type) => {
const { Image } = require('react-native');
Component = Image;
} else {
- const FastImage = require('react-native-fast-image').default;
+ const FastImage = require('@rocket.chat/react-native-fast-image').default;
Component = FastImage;
}
return Component;
diff --git a/app/presentation/KeyboardView.js b/app/presentation/KeyboardView.js
index 9bd25191e..628213825 100644
--- a/app/presentation/KeyboardView.js
+++ b/app/presentation/KeyboardView.js
@@ -1,6 +1,6 @@
import React from 'react';
import PropTypes from 'prop-types';
-import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view';
+import { KeyboardAwareScrollView } from '@codler/react-native-keyboard-aware-scroll-view';
import scrollPersistTaps from '../utils/scrollPersistTaps';
export default class KeyboardView extends React.PureComponent {
diff --git a/app/presentation/RoomItem/Actions.js b/app/presentation/RoomItem/Actions.js
index 20e5efad6..c10dd716a 100644
--- a/app/presentation/RoomItem/Actions.js
+++ b/app/presentation/RoomItem/Actions.js
@@ -107,7 +107,7 @@ export const RightActions = React.memo(({
>
<>
-
+
{I18n.t('Hide')}
>
diff --git a/app/presentation/RoomItem/RoomItem.js b/app/presentation/RoomItem/RoomItem.js
new file mode 100644
index 000000000..d0496ef98
--- /dev/null
+++ b/app/presentation/RoomItem/RoomItem.js
@@ -0,0 +1,190 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { View } from 'react-native';
+
+import styles from './styles';
+import Wrapper from './Wrapper';
+import UnreadBadge from '../UnreadBadge';
+import TypeIcon from './TypeIcon';
+import LastMessage from './LastMessage';
+import Title from './Title';
+import UpdatedAt from './UpdatedAt';
+import Touchable from './Touchable';
+
+const RoomItem = ({
+ rid,
+ type,
+ prid,
+ name,
+ avatar,
+ width,
+ avatarSize,
+ baseUrl,
+ userId,
+ username,
+ token,
+ showLastMessage,
+ status,
+ useRealName,
+ theme,
+ isFocused,
+ isGroupChat,
+ isRead,
+ date,
+ accessibilityLabel,
+ favorite,
+ lastMessage,
+ alert,
+ hideUnreadStatus,
+ unread,
+ userMentions,
+ groupMentions,
+ roomUpdatedAt,
+ testID,
+ swipeEnabled,
+ onPress,
+ toggleFav,
+ toggleRead,
+ hideChannel
+}) => (
+
+
+ {showLastMessage
+ ? (
+ <>
+
+
+
+
+
+
+
+
+
+ >
+ )
+ : (
+
+
+
+
+
+ )
+ }
+
+
+);
+
+RoomItem.propTypes = {
+ rid: PropTypes.string.isRequired,
+ type: PropTypes.string.isRequired,
+ prid: PropTypes.string,
+ name: PropTypes.string.isRequired,
+ avatar: PropTypes.string.isRequired,
+ baseUrl: PropTypes.string.isRequired,
+ showLastMessage: PropTypes.bool,
+ userId: PropTypes.string,
+ username: PropTypes.string,
+ token: PropTypes.string,
+ avatarSize: PropTypes.number,
+ testID: PropTypes.string,
+ width: PropTypes.number,
+ status: PropTypes.string,
+ useRealName: PropTypes.bool,
+ theme: PropTypes.string,
+ isFocused: PropTypes.bool,
+ isGroupChat: PropTypes.bool,
+ isRead: PropTypes.bool,
+ date: PropTypes.string,
+ accessibilityLabel: PropTypes.string,
+ lastMessage: PropTypes.object,
+ favorite: PropTypes.bool,
+ alert: PropTypes.bool,
+ hideUnreadStatus: PropTypes.bool,
+ unread: PropTypes.number,
+ userMentions: PropTypes.number,
+ groupMentions: PropTypes.number,
+ roomUpdatedAt: PropTypes.instanceOf(Date),
+ swipeEnabled: PropTypes.bool,
+ toggleFav: PropTypes.func,
+ toggleRead: PropTypes.func,
+ onPress: PropTypes.func,
+ hideChannel: PropTypes.func
+};
+
+RoomItem.defaultProps = {
+ avatarSize: 48,
+ status: 'offline',
+ swipeEnabled: true
+};
+
+export default RoomItem;
diff --git a/app/presentation/RoomItem/Title.js b/app/presentation/RoomItem/Title.js
new file mode 100644
index 000000000..6f4f848d6
--- /dev/null
+++ b/app/presentation/RoomItem/Title.js
@@ -0,0 +1,31 @@
+import React from 'react';
+import { Text } from 'react-native';
+import PropTypes from 'prop-types';
+
+import styles from './styles';
+import { themes } from '../../constants/colors';
+
+const Title = React.memo(({
+ name, theme, hideUnreadStatus, alert
+}) => (
+
+ {name}
+
+));
+
+Title.propTypes = {
+ name: PropTypes.string,
+ theme: PropTypes.string,
+ hideUnreadStatus: PropTypes.bool,
+ alert: PropTypes.bool
+};
+
+export default Title;
diff --git a/app/presentation/RoomItem/Touchable.js b/app/presentation/RoomItem/Touchable.js
index 911436fe0..b0c9fe3e0 100644
--- a/app/presentation/RoomItem/Touchable.js
+++ b/app/presentation/RoomItem/Touchable.js
@@ -26,7 +26,8 @@ class Touchable extends React.Component {
hideChannel: PropTypes.func,
children: PropTypes.element,
theme: PropTypes.string,
- isFocused: PropTypes.bool
+ isFocused: PropTypes.bool,
+ swipeEnabled: PropTypes.bool
}
constructor(props) {
@@ -168,7 +169,7 @@ class Touchable extends React.Component {
render() {
const {
- testID, isRead, width, favorite, children, theme, isFocused
+ testID, isRead, width, favorite, children, theme, isFocused, swipeEnabled
} = this.props;
return (
@@ -177,6 +178,7 @@ class Touchable extends React.Component {
minDeltaX={20}
onGestureEvent={this._onGestureEvent}
onHandlerStateChange={this._onHandlerStateChange}
+ enabled={swipeEnabled}
>
{
- if (!unread || unread <= 0) {
- return;
- }
- if (unread >= 1000) {
- unread = '999+';
- }
- const mentioned = userMentions > 0 && type !== 'd';
-
- return (
-
- { unread }
-
-
- );
-});
-
-UnreadBadge.propTypes = {
- theme: PropTypes.string,
- unread: PropTypes.number,
- userMentions: PropTypes.number,
- type: PropTypes.string
-};
-
-export default UnreadBadge;
diff --git a/app/presentation/RoomItem/UpdatedAt.js b/app/presentation/RoomItem/UpdatedAt.js
new file mode 100644
index 000000000..667a05bf0
--- /dev/null
+++ b/app/presentation/RoomItem/UpdatedAt.js
@@ -0,0 +1,49 @@
+import React from 'react';
+import { Text } from 'react-native';
+import PropTypes from 'prop-types';
+
+import styles from './styles';
+import { themes } from '../../constants/colors';
+import { capitalize } from '../../utils/room';
+
+const UpdatedAt = React.memo(({
+ roomUpdatedAt, date, theme, hideUnreadStatus, alert
+}) => {
+ if (!roomUpdatedAt) {
+ return null;
+ }
+ return (
+
+ {capitalize(date)}
+
+ );
+});
+
+UpdatedAt.propTypes = {
+ roomUpdatedAt: PropTypes.instanceOf(Date),
+ date: PropTypes.string,
+ theme: PropTypes.string,
+ hideUnreadStatus: PropTypes.bool,
+ alert: PropTypes.bool
+};
+
+export default UpdatedAt;
diff --git a/app/presentation/RoomItem/Wrapper.js b/app/presentation/RoomItem/Wrapper.js
new file mode 100644
index 000000000..a7473cae2
--- /dev/null
+++ b/app/presentation/RoomItem/Wrapper.js
@@ -0,0 +1,58 @@
+import React from 'react';
+import { View } from 'react-native';
+import PropTypes from 'prop-types';
+
+import styles from './styles';
+import { themes } from '../../constants/colors';
+import Avatar from '../../containers/Avatar';
+
+const RoomItemInner = ({
+ accessibilityLabel,
+ avatar,
+ avatarSize,
+ type,
+ baseUrl,
+ userId,
+ token,
+ theme,
+ children
+}) => (
+
+
+
+ {children}
+
+
+);
+
+RoomItemInner.propTypes = {
+ accessibilityLabel: PropTypes.string,
+ avatar: PropTypes.string,
+ avatarSize: PropTypes.number,
+ type: PropTypes.string,
+ baseUrl: PropTypes.string,
+ userId: PropTypes.string,
+ token: PropTypes.string,
+ theme: PropTypes.string,
+ children: PropTypes.element
+};
+
+export default RoomItemInner;
diff --git a/app/presentation/RoomItem/index.js b/app/presentation/RoomItem/index.js
index 1b3ee93f2..395d8d81e 100644
--- a/app/presentation/RoomItem/index.js
+++ b/app/presentation/RoomItem/index.js
@@ -1,97 +1,89 @@
-import React, { useEffect } from 'react';
+import React, { useEffect, useState } from 'react';
import PropTypes from 'prop-types';
-import { View, Text } from 'react-native';
import { connect } from 'react-redux';
-import Avatar from '../../containers/Avatar';
import I18n from '../../i18n';
-import styles, { ROW_HEIGHT } from './styles';
-import UnreadBadge from './UnreadBadge';
-import TypeIcon from './TypeIcon';
-import LastMessage from './LastMessage';
-import { capitalize, formatDate } from '../../utils/room';
-import Touchable from './Touchable';
-import { themes } from '../../constants/colors';
+import { ROW_HEIGHT } from './styles';
+import { formatDate } from '../../utils/room';
+import RoomItem from './RoomItem';
export { ROW_HEIGHT };
const attrs = [
- 'name',
- 'unread',
- 'userMentions',
- 'showLastMessage',
- 'useRealName',
- 'alert',
- 'type',
'width',
- 'isRead',
- 'favorite',
'status',
'connected',
'theme',
- 'isFocused'
+ 'isFocused',
+ 'forceUpdate',
+ 'showLastMessage'
];
-const arePropsEqual = (oldProps, newProps) => {
- const { _updatedAt: _updatedAtOld } = oldProps;
- const { _updatedAt: _updatedAtNew } = newProps;
- if (_updatedAtOld && _updatedAtNew && _updatedAtOld.toISOString() !== _updatedAtNew.toISOString()) {
- return false;
- }
- return attrs.every(key => oldProps[key] === newProps[key]);
-};
+const arePropsEqual = (oldProps, newProps) => attrs.every(key => oldProps[key] === newProps[key]);
-const RoomItem = React.memo(({
+const RoomItemContainer = React.memo(({
+ item,
onPress,
width,
- favorite,
toggleFav,
- isRead,
- rid,
toggleRead,
hideChannel,
testID,
- unread,
- userMentions,
- name,
- _updatedAt,
- alert,
- type,
avatarSize,
baseUrl,
userId,
username,
token,
id,
- prid,
showLastMessage,
- hideUnreadStatus,
- lastMessage,
status,
- avatar,
useRealName,
getUserPresence,
- isGroupChat,
connected,
theme,
- isFocused
+ isFocused,
+ getRoomTitle,
+ getRoomAvatar,
+ getIsGroupChat,
+ getIsRead,
+ swipeEnabled
}) => {
+ const [, setForceUpdate] = useState(1);
+
useEffect(() => {
- if (connected && type === 'd' && id) {
+ if (connected && item.t === 'd' && id) {
getUserPresence(id);
}
}, [connected]);
- const date = lastMessage && formatDate(lastMessage.ts);
+ useEffect(() => {
+ if (item?.observe) {
+ const observable = item.observe();
+ const subscription = observable?.subscribe?.(() => {
+ setForceUpdate(prevForceUpdate => prevForceUpdate + 1);
+ });
+
+ return () => {
+ subscription?.unsubscribe?.();
+ };
+ }
+ }, []);
+
+ const name = getRoomTitle(item);
+ const avatar = getRoomAvatar(item);
+ const isGroupChat = getIsGroupChat(item);
+ const isRead = getIsRead(item);
+ const _onPress = () => onPress(item);
+ const date = item.lastMessage?.ts && formatDate(item.lastMessage.ts);
let accessibilityLabel = name;
- if (unread === 1) {
- accessibilityLabel += `, ${ unread } ${ I18n.t('alert') }`;
- } else if (unread > 1) {
- accessibilityLabel += `, ${ unread } ${ I18n.t('alerts') }`;
+ if (item.unread === 1) {
+ accessibilityLabel += `, ${ item.unread } ${ I18n.t('alert') }`;
+ } else if (item.unread > 1) {
+ accessibilityLabel += `, ${ item.unread } ${ I18n.t('alerts') }`;
}
- if (userMentions > 0) {
+ if (item.userMentions > 0) {
accessibilityLabel += `, ${ I18n.t('you_were_mentioned') }`;
}
@@ -100,120 +92,50 @@ const RoomItem = React.memo(({
}
return (
-
-
-
-
-
-
-
- {name}
-
- {_updatedAt ? (
-
- {capitalize(date)}
-
- ) : null}
-
-
-
-
-
-
-
-
+ size={avatarSize}
+ baseUrl={baseUrl}
+ userId={userId}
+ token={token}
+ prid={item.prid}
+ status={status}
+ hideUnreadStatus={item.hideUnreadStatus}
+ alert={item.alert}
+ roomUpdatedAt={item.roomUpdatedAt}
+ lastMessage={item.lastMessage}
+ showLastMessage={showLastMessage}
+ username={username}
+ useRealName={useRealName}
+ unread={item.unread}
+ groupMentions={item.groupMentions}
+ swipeEnabled={swipeEnabled}
+ />
);
}, arePropsEqual);
-RoomItem.propTypes = {
- type: PropTypes.string.isRequired,
- name: PropTypes.string.isRequired,
+RoomItemContainer.propTypes = {
+ item: PropTypes.object.isRequired,
baseUrl: PropTypes.string.isRequired,
showLastMessage: PropTypes.bool,
- _updatedAt: PropTypes.string,
- lastMessage: PropTypes.object,
- alert: PropTypes.bool,
- unread: PropTypes.number,
- userMentions: PropTypes.number,
id: PropTypes.string,
- prid: PropTypes.string,
onPress: PropTypes.func,
userId: PropTypes.string,
username: PropTypes.string,
@@ -221,27 +143,31 @@ RoomItem.propTypes = {
avatarSize: PropTypes.number,
testID: PropTypes.string,
width: PropTypes.number,
- favorite: PropTypes.bool,
- isRead: PropTypes.bool,
- rid: PropTypes.string,
status: PropTypes.string,
toggleFav: PropTypes.func,
toggleRead: PropTypes.func,
hideChannel: PropTypes.func,
- avatar: PropTypes.bool,
- hideUnreadStatus: PropTypes.bool,
useRealName: PropTypes.bool,
getUserPresence: PropTypes.func,
connected: PropTypes.bool,
- isGroupChat: PropTypes.bool,
theme: PropTypes.string,
- isFocused: PropTypes.bool
+ isFocused: PropTypes.bool,
+ getRoomTitle: PropTypes.func,
+ getRoomAvatar: PropTypes.func,
+ getIsGroupChat: PropTypes.func,
+ getIsRead: PropTypes.func,
+ swipeEnabled: PropTypes.bool
};
-RoomItem.defaultProps = {
+RoomItemContainer.defaultProps = {
avatarSize: 48,
status: 'offline',
- getUserPresence: () => {}
+ getUserPresence: () => {},
+ getRoomTitle: () => 'title',
+ getRoomAvatar: () => '',
+ getIsGroupChat: () => false,
+ getIsRead: () => false,
+ swipeEnabled: true
};
const mapStateToProps = (state, ownProps) => {
@@ -260,4 +186,4 @@ const mapStateToProps = (state, ownProps) => {
};
};
-export default connect(mapStateToProps)(RoomItem);
+export default connect(mapStateToProps)(RoomItemContainer);
diff --git a/app/presentation/RoomItem/styles.js b/app/presentation/RoomItem/styles.js
index 93c70a845..fb110e4ce 100644
--- a/app/presentation/RoomItem/styles.js
+++ b/app/presentation/RoomItem/styles.js
@@ -8,6 +8,9 @@ export const SMALL_SWIPE = ACTION_WIDTH / 2;
export const LONG_SWIPE = ACTION_WIDTH * 3;
export default StyleSheet.create({
+ flex: {
+ flex: 1
+ },
container: {
flexDirection: 'row',
alignItems: 'center',
@@ -48,23 +51,6 @@ export default StyleSheet.create({
updateAlert: {
...sharedStyles.textSemibold
},
- unreadNumberContainer: {
- minWidth: 21,
- height: 21,
- paddingVertical: 3,
- paddingHorizontal: 5,
- borderRadius: 10.5,
- alignItems: 'center',
- justifyContent: 'center',
- marginLeft: 10
- },
- unreadText: {
- overflow: 'hidden',
- fontSize: 13,
- ...sharedStyles.textMedium,
- letterSpacing: 0.56,
- textAlign: 'center'
- },
status: {
marginLeft: 4,
marginRight: 7,
diff --git a/app/presentation/ServerItem/index.js b/app/presentation/ServerItem/index.js
index 094b86a94..53163a43c 100644
--- a/app/presentation/ServerItem/index.js
+++ b/app/presentation/ServerItem/index.js
@@ -1,7 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import { View, Text } from 'react-native';
-import FastImage from 'react-native-fast-image';
+import FastImage from '@rocket.chat/react-native-fast-image';
import Touch from '../../utils/touch';
import Check from '../../containers/Check';
diff --git a/app/presentation/UnreadBadge.js b/app/presentation/UnreadBadge.js
new file mode 100644
index 000000000..88f7db416
--- /dev/null
+++ b/app/presentation/UnreadBadge.js
@@ -0,0 +1,73 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { View, Text, StyleSheet } from 'react-native';
+
+import sharedStyles from '../views/Styles';
+import { themes } from '../constants/colors';
+
+const styles = StyleSheet.create({
+ unreadNumberContainer: {
+ minWidth: 21,
+ height: 21,
+ paddingVertical: 3,
+ paddingHorizontal: 5,
+ borderRadius: 10.5,
+ alignItems: 'center',
+ justifyContent: 'center',
+ marginLeft: 10
+ },
+ unreadText: {
+ overflow: 'hidden',
+ fontSize: 13,
+ ...sharedStyles.textMedium,
+ letterSpacing: 0.56,
+ textAlign: 'center'
+ }
+});
+
+const UnreadBadge = React.memo(({
+ theme, unread, userMentions, groupMentions, style
+}) => {
+ if (!unread || unread <= 0) {
+ return;
+ }
+ if (unread >= 1000) {
+ unread = '999+';
+ }
+
+ let backgroundColor = themes[theme].unreadBackground;
+ const color = themes[theme].buttonText;
+ if (userMentions > 0) {
+ backgroundColor = themes[theme].mentionMeColor;
+ } else if (groupMentions > 0) {
+ backgroundColor = themes[theme].mentionGroupColor;
+ }
+
+ return (
+
+ {unread}
+
+
+ );
+});
+
+UnreadBadge.propTypes = {
+ theme: PropTypes.string,
+ unread: PropTypes.number,
+ userMentions: PropTypes.number,
+ groupMentions: PropTypes.number,
+ style: PropTypes.object
+};
+
+export default UnreadBadge;
diff --git a/app/presentation/UserItem.js b/app/presentation/UserItem.js
index 1f536af06..fb61e2bc9 100644
--- a/app/presentation/UserItem.js
+++ b/app/presentation/UserItem.js
@@ -1,13 +1,14 @@
import React from 'react';
-import { Text, View, StyleSheet } from 'react-native';
+import {
+ Text, View, StyleSheet, Pressable
+} from 'react-native';
import PropTypes from 'prop-types';
import Avatar from '../containers/Avatar';
import { CustomIcon } from '../lib/Icons';
import sharedStyles from '../views/Styles';
import { themes } from '../constants/colors';
-import Touch from '../utils/touch';
-import LongPress from '../utils/longPress';
+import { isIOS } from '../utils/deviceInfo';
const styles = StyleSheet.create({
button: {
@@ -43,23 +44,28 @@ const styles = StyleSheet.create({
const UserItem = ({
name, username, onPress, testID, onLongPress, style, icon, baseUrl, user, theme
}) => (
-
-
-
-
-
- {name}
- @{username}
-
- {icon ? : null}
+ ({
+ backgroundColor: isIOS && pressed
+ ? themes[theme].bannerBackground
+ : 'transparent'
+ })}
+ >
+
+
+
+ {name}
+ @{username}
-
-
+ {icon ? : null}
+
+
);
UserItem.propTypes = {
diff --git a/app/reducers/index.js b/app/reducers/index.js
index 1ac810c33..968254ffd 100644
--- a/app/reducers/index.js
+++ b/app/reducers/index.js
@@ -16,6 +16,7 @@ import activeUsers from './activeUsers';
import usersTyping from './usersTyping';
import inviteLinks from './inviteLinks';
import createDiscussion from './createDiscussion';
+import inquiry from './inquiry';
export default combineReducers({
settings,
@@ -34,5 +35,6 @@ export default combineReducers({
activeUsers,
usersTyping,
inviteLinks,
- createDiscussion
+ createDiscussion,
+ inquiry
});
diff --git a/app/reducers/inquiry.js b/app/reducers/inquiry.js
new file mode 100644
index 000000000..230280c83
--- /dev/null
+++ b/app/reducers/inquiry.js
@@ -0,0 +1,51 @@
+import { INQUIRY } from '../actions/actionsTypes';
+
+const initialState = {
+ enabled: false,
+ queued: [],
+ error: {}
+};
+
+export default function inquiry(state = initialState, action) {
+ switch (action.type) {
+ case INQUIRY.SUCCESS:
+ return {
+ ...state,
+ queued: action.inquiries
+ };
+ case INQUIRY.FAILURE:
+ return {
+ ...state,
+ error: action.error
+ };
+ case INQUIRY.SET_ENABLED:
+ return {
+ ...state,
+ enabled: action.enabled
+ };
+ case INQUIRY.QUEUE_ADD:
+ return {
+ ...state,
+ queued: [...state.queued, action.inquiry]
+ };
+ case INQUIRY.QUEUE_UPDATE:
+ return {
+ ...state,
+ queued: state.queued.map((item) => {
+ if (item._id === action.inquiry._id) {
+ return action.inquiry;
+ }
+ return item;
+ })
+ };
+ case INQUIRY.QUEUE_REMOVE:
+ return {
+ ...state,
+ queued: state.queued.filter(({ _id }) => _id !== action.inquiryId)
+ };
+ case INQUIRY.RESET:
+ return initialState;
+ default:
+ return state;
+ }
+}
diff --git a/app/sagas/createChannel.js b/app/sagas/createChannel.js
index 062a0092b..2c642006c 100644
--- a/app/sagas/createChannel.js
+++ b/app/sagas/createChannel.js
@@ -10,6 +10,7 @@ import RocketChat from '../lib/rocketchat';
import Navigation from '../lib/Navigation';
import database from '../lib/database';
import I18n from '../i18n';
+import { logEvent, events } from '../utils/log';
import { goRoom } from '../utils/goRoom';
const createChannel = function createChannel(data) {
@@ -29,11 +30,14 @@ const handleRequest = function* handleRequest({ data }) {
let sub;
if (data.group) {
+ logEvent(events.SELECTED_USERS_CREATE_GROUP);
const result = yield call(createGroupChat);
if (result.success) {
({ room: sub } = result);
}
} else {
+ const { type, readOnly, broadcast } = data;
+ logEvent(events.CREATE_CHANNEL_CREATE, { type: type ? 'private' : 'public', readOnly, broadcast });
sub = yield call(createChannel, data);
}
@@ -52,6 +56,7 @@ const handleRequest = function* handleRequest({ data }) {
yield put(createChannelSuccess(sub));
} catch (err) {
+ logEvent(events[data.group ? 'SELECTED_USERS_CREATE_GROUP_F' : 'CREATE_CHANNEL_CREATE_F']);
yield put(createChannelFailure(err));
}
};
diff --git a/app/sagas/createDiscussion.js b/app/sagas/createDiscussion.js
index 1e53e57d4..a185e6671 100644
--- a/app/sagas/createDiscussion.js
+++ b/app/sagas/createDiscussion.js
@@ -7,12 +7,14 @@ import { CREATE_DISCUSSION, LOGIN } from '../actions/actionsTypes';
import { createDiscussionSuccess, createDiscussionFailure } from '../actions/createDiscussion';
import RocketChat from '../lib/rocketchat';
import database from '../lib/database';
+import { logEvent, events } from '../utils/log';
const create = function* create(data) {
return yield RocketChat.createDiscussion(data);
};
const handleRequest = function* handleRequest({ data }) {
+ logEvent(events.CREATE_DISCUSSION_CREATE);
try {
const auth = yield select(state => state.login.isAuthenticated);
if (!auth) {
@@ -35,12 +37,13 @@ const handleRequest = function* handleRequest({ data }) {
} catch {
// do nothing
}
-
yield put(createDiscussionSuccess(sub));
} else {
+ logEvent(events.CREATE_DISCUSSION_CREATE_F);
yield put(createDiscussionFailure(result));
}
} catch (err) {
+ logEvent(events.CREATE_DISCUSSION_CREATE_F);
yield put(createDiscussionFailure(err));
}
};
diff --git a/app/sagas/deepLinking.js b/app/sagas/deepLinking.js
index 2069cbd07..b650a06a9 100644
--- a/app/sagas/deepLinking.js
+++ b/app/sagas/deepLinking.js
@@ -5,14 +5,17 @@ import RNUserDefaults from 'rn-user-defaults';
import Navigation from '../lib/Navigation';
import * as types from '../actions/actionsTypes';
-import { selectServerRequest } from '../actions/server';
+import { selectServerRequest, serverInitAdd } from '../actions/server';
import { inviteLinksSetToken, inviteLinksRequest } from '../actions/inviteLinks';
import database from '../lib/database';
import RocketChat from '../lib/rocketchat';
import EventEmitter from '../utils/events';
-import { appStart, ROOT_INSIDE } from '../actions/app';
+import {
+ appStart, ROOT_INSIDE, ROOT_NEW_SERVER, appInit
+} from '../actions/app';
import { localAuthenticate } from '../utils/localAuthentication';
import { goRoom } from '../utils/goRoom';
+import callJitsi from '../lib/methods/callJitsi';
const roomTypes = {
channel: 'c', direct: 'd', group: 'p', channels: 'l'
@@ -48,7 +51,11 @@ const navigate = function* navigate({ params }) {
roomUserId: RocketChat.getUidDirectMessage(room),
...room
};
- goRoom({ item, isMasterDetail });
+ yield goRoom({ item, isMasterDetail });
+
+ if (params.isCall) {
+ callJitsi(item.rid);
+ }
}
} else {
yield handleInviteLink({ params });
@@ -56,14 +63,41 @@ const navigate = function* navigate({ params }) {
}
};
+const fallbackNavigation = function* fallbackNavigation() {
+ const currentRoot = yield select(state => state.app.root);
+ if (currentRoot) {
+ return;
+ }
+ yield put(appInit());
+};
+
const handleOpen = function* handleOpen({ params }) {
- if (!params.host) {
+ const serversDB = database.servers;
+ const serversCollection = serversDB.collections.get('servers');
+
+ let { host } = params;
+ if (params.isCall && !host) {
+ const servers = yield serversCollection.query().fetch();
+ // search from which server is that call
+ servers.forEach(({ uniqueID, id }) => {
+ if (params.path.includes(uniqueID)) {
+ host = id;
+ }
+ });
+ }
+
+ // If there's no host on the deep link params and the app is opened, just call appInit()
+ if (!host) {
+ yield fallbackNavigation();
return;
}
- let { host } = params;
+ // If there's host, continue
if (!/^(http|https)/.test(host)) {
- host = `https://${ params.host }`;
+ host = `https://${ host }`;
+ } else {
+ // Notification should always come from https
+ host = host.replace('http://', 'https://');
}
// remove last "/" from host
if (host.slice(-1) === '/') {
@@ -87,8 +121,6 @@ const handleOpen = function* handleOpen({ params }) {
yield navigate({ params });
} else {
// search if deep link's server already exists
- const serversDB = database.servers;
- const serversCollection = serversDB.collections.get('servers');
try {
const servers = yield serversCollection.find(host);
if (servers && user) {
@@ -104,9 +136,12 @@ const handleOpen = function* handleOpen({ params }) {
// if deep link is from a different server
const result = yield RocketChat.getServerInfo(host);
if (!result.success) {
+ // Fallback to prevent the app from being stuck on splash screen
+ yield fallbackNavigation();
return;
}
- Navigation.navigate('NewServerView', { previousServer: server });
+ yield put(appStart({ root: ROOT_NEW_SERVER }));
+ yield put(serverInitAdd(server));
yield delay(1000);
EventEmitter.emit('NewServer', { server: host });
diff --git a/app/sagas/index.js b/app/sagas/index.js
index 27886be83..772df5717 100644
--- a/app/sagas/index.js
+++ b/app/sagas/index.js
@@ -10,6 +10,7 @@ import state from './state';
import deepLinking from './deepLinking';
import inviteLinks from './inviteLinks';
import createDiscussion from './createDiscussion';
+import inquiry from './inquiry';
const root = function* root() {
yield all([
@@ -23,7 +24,8 @@ const root = function* root() {
state(),
deepLinking(),
inviteLinks(),
- createDiscussion()
+ createDiscussion(),
+ inquiry()
]);
};
diff --git a/app/sagas/inquiry.js b/app/sagas/inquiry.js
new file mode 100644
index 000000000..9ee7e27fe
--- /dev/null
+++ b/app/sagas/inquiry.js
@@ -0,0 +1,38 @@
+import { put, takeLatest, select } from 'redux-saga/effects';
+
+import * as types from '../actions/actionsTypes';
+import RocketChat from '../lib/rocketchat';
+import { inquirySuccess, inquiryFailure, inquirySetEnabled } from '../actions/inquiry';
+
+const handleRequest = function* handleRequest() {
+ try {
+ const routingConfig = yield RocketChat.getRoutingConfig();
+ const statusLivechat = yield select(state => state.login.user.statusLivechat);
+ // if routingConfig showQueue is enabled and omnichannel is enabled
+ const showQueue = routingConfig.showQueue && statusLivechat === 'available';
+
+ if (showQueue) {
+ // get all the current chats on the queue
+ const result = yield RocketChat.getInquiriesQueued();
+ if (result.success) {
+ const { inquiries } = result;
+
+ // subscribe to inquiry queue changes
+ RocketChat.subscribeInquiry();
+
+ // put request result on redux state
+ yield put(inquirySuccess(inquiries));
+ }
+ }
+
+ // set enabled to know if we should show the queue button
+ yield put(inquirySetEnabled(showQueue));
+ } catch (e) {
+ yield put(inquiryFailure(e));
+ }
+};
+
+const root = function* root() {
+ yield takeLatest(types.INQUIRY.REQUEST, handleRequest);
+};
+export default root;
diff --git a/app/sagas/login.js b/app/sagas/login.js
index 587b9b7ba..01ab28453 100644
--- a/app/sagas/login.js
+++ b/app/sagas/login.js
@@ -15,9 +15,10 @@ import {
loginFailure, loginSuccess, setUser, logout
} from '../actions/login';
import { roomsRequest } from '../actions/rooms';
+import { inquiryRequest } from '../actions/inquiry';
import { toMomentLocale } from '../utils/moment';
import RocketChat from '../lib/rocketchat';
-import log from '../utils/log';
+import log, { logEvent, events } from '../utils/log';
import I18n from '../i18n';
import database from '../lib/database';
import EventEmitter from '../utils/events';
@@ -32,6 +33,7 @@ const loginCall = args => RocketChat.login(args);
const logoutCall = args => RocketChat.logout(args);
const handleLoginRequest = function* handleLoginRequest({ credentials, logoutOnError = false }) {
+ logEvent(events.LOGIN_DEFAULT_LOGIN);
try {
let result;
if (credentials.resume) {
@@ -52,6 +54,7 @@ const handleLoginRequest = function* handleLoginRequest({ credentials, logoutOnE
if (logoutOnError && (e.data && e.data.message && /you've been logged out by the server/i.test(e.data.message))) {
yield put(logout(true));
} else {
+ logEvent(events.LOGIN_DEFAULT_LOGIN_F);
yield put(loginFailure(e));
}
}
@@ -91,6 +94,7 @@ const handleLoginSuccess = function* handleLoginSuccess({ user }) {
const server = yield select(getServer);
yield put(roomsRequest());
+ yield put(inquiryRequest());
yield fork(fetchPermissions);
yield fork(fetchCustomEmojis);
yield fork(fetchRoles);
@@ -204,6 +208,10 @@ const handleSetUser = function* handleSetUser({ user }) {
const userId = yield select(state => state.login.user.id);
yield put(setActiveUsers({ [userId]: user }));
}
+
+ if (user && user.statusLivechat) {
+ yield put(inquiryRequest());
+ }
};
const root = function* root() {
diff --git a/app/sagas/room.js b/app/sagas/room.js
index c7402f93a..3b1b321ad 100644
--- a/app/sagas/room.js
+++ b/app/sagas/room.js
@@ -8,7 +8,7 @@ import Navigation from '../lib/Navigation';
import * as types from '../actions/actionsTypes';
import { removedRoom } from '../actions/room';
import RocketChat from '../lib/rocketchat';
-import log from '../utils/log';
+import log, { logEvent, events } from '../utils/log';
import I18n from '../i18n';
import { showErrorAlert } from '../utils/info';
@@ -48,12 +48,14 @@ const handleRemovedRoom = function* handleRemovedRoom() {
};
const handleLeaveRoom = function* handleLeaveRoom({ rid, t }) {
+ logEvent(events.RA_LEAVE);
try {
const result = yield RocketChat.leaveRoom(rid, t);
if (result.success) {
yield handleRemovedRoom();
}
} catch (e) {
+ logEvent(events.RA_LEAVE_F);
if (e.data && e.data.errorType === 'error-you-are-last-owner') {
Alert.alert(I18n.t('Oops'), I18n.t(e.data.errorType));
} else {
@@ -63,12 +65,14 @@ const handleLeaveRoom = function* handleLeaveRoom({ rid, t }) {
};
const handleDeleteRoom = function* handleDeleteRoom({ rid, t }) {
+ logEvent(events.RI_EDIT_DELETE);
try {
const result = yield RocketChat.deleteRoom(rid, t);
if (result.success) {
yield handleRemovedRoom();
}
} catch (e) {
+ logEvent(events.RI_EDIT_DELETE_F);
Alert.alert(I18n.t('Oops'), I18n.t('There_was_an_error_while_action', { action: I18n.t('deleting_room') }));
}
};
diff --git a/app/sagas/selectServer.js b/app/sagas/selectServer.js
index 429b2642c..51728b8a8 100644
--- a/app/sagas/selectServer.js
+++ b/app/sagas/selectServer.js
@@ -19,6 +19,7 @@ import I18n from '../i18n';
import { SERVERS, TOKEN, SERVER_URL } from '../constants/userDefaults';
import { BASIC_AUTH_KEY, setBasicAuth } from '../utils/fetch';
import { appStart, ROOT_INSIDE, ROOT_OUTSIDE } from '../actions/app';
+import { inquiryReset } from '../actions/inquiry';
const getServerInfo = function* getServerInfo({ server, raiseError = true }) {
try {
@@ -65,6 +66,7 @@ const getServerInfo = function* getServerInfo({ server, raiseError = true }) {
const handleSelectServer = function* handleSelectServer({ server, version, fetchVersion }) {
try {
+ yield put(inquiryReset());
const serversDB = database.servers;
yield RNUserDefaults.set('currentServer', server);
const userId = yield RNUserDefaults.get(`${ RocketChat.TOKEN_KEY }-${ server }`);
diff --git a/app/selectors/inquiry.js b/app/selectors/inquiry.js
new file mode 100644
index 000000000..baeb09ef8
--- /dev/null
+++ b/app/selectors/inquiry.js
@@ -0,0 +1,8 @@
+import { createSelector } from 'reselect';
+
+const getInquiryQueue = state => state.inquiry.queued;
+
+export const getInquiryQueueSelector = createSelector(
+ [getInquiryQueue],
+ queue => queue
+);
diff --git a/app/stacks/InsideStack.js b/app/stacks/InsideStack.js
index e29c39dd9..e9a4a7a74 100644
--- a/app/stacks/InsideStack.js
+++ b/app/stacks/InsideStack.js
@@ -30,6 +30,7 @@ import PickerView from '../views/PickerView';
import ThreadMessagesView from '../views/ThreadMessagesView';
import MarkdownTableView from '../views/MarkdownTableView';
import ReadReceiptsView from '../views/ReadReceiptView';
+import QueueListView from '../views/QueueListView';
// Profile Stack
import ProfileView from '../views/ProfileView';
@@ -112,7 +113,6 @@ const ChatsStackNavigator = () => {
{
component={ReadReceiptsView}
options={ReadReceiptsView.navigationOptions}
/>
+
);
};
diff --git a/app/stacks/MasterDetailStack/index.js b/app/stacks/MasterDetailStack/index.js
index 0b27d89df..800bad1d7 100644
--- a/app/stacks/MasterDetailStack/index.js
+++ b/app/stacks/MasterDetailStack/index.js
@@ -41,6 +41,7 @@ import ScreenLockConfigView from '../../views/ScreenLockConfigView';
import AdminPanelView from '../../views/AdminPanelView';
import NewMessageView from '../../views/NewMessageView';
import CreateChannelView from '../../views/CreateChannelView';
+import QueueListView from '../../views/QueueListView';
// InsideStackNavigator
import AttachmentView from '../../views/AttachmentView';
@@ -139,7 +140,6 @@ const ModalStackNavigator = React.memo(({ navigation }) => {
{
component={DirectoryView}
options={props => DirectoryView.navigationOptions({ ...props, isMasterDetail: true })}
/>
+ QueueListView.navigationOptions({ ...props, isMasterDetail: true })}
+ />
{
ReadReceiptsView.navigationOptions({ ...props, isMasterDetail: true })}
/>
{
};
};
+export const logEvent = (eventName, payload) => {
+ try {
+ analytics().logEvent(eventName, payload);
+ leaveBreadcrumb(eventName, payload);
+ } catch {
+ // Do nothing
+ }
+};
+
export const setCurrentScreen = (currentScreen) => {
analytics().setCurrentScreen(currentScreen);
leaveBreadcrumb(currentScreen, { type: 'navigation' });
@@ -30,6 +42,7 @@ export default (e) => {
}
};
});
+ crashlytics().recordError(e);
} else {
console.log(e);
}
diff --git a/app/utils/longPress.js b/app/utils/longPress.js
deleted file mode 100644
index e491efcb9..000000000
--- a/app/utils/longPress.js
+++ /dev/null
@@ -1,44 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import { State, LongPressGestureHandler } from 'react-native-gesture-handler';
-
-class LongPress extends React.Component {
- setNativeProps(props) {
- this.ref.setNativeProps(props);
- }
-
- getRef = (ref) => {
- this.ref = ref;
- };
-
- longPress = ({ nativeEvent }) => {
- const { onLongPress } = this.props;
- if (nativeEvent.state === State.ACTIVE) {
- if (onLongPress) {
- onLongPress();
- }
- }
- };
-
- render() {
- const { children, ...props } = this.props;
-
- return (
-
- {children}
-
- );
- }
-}
-
-LongPress.propTypes = {
- children: PropTypes.node,
- onLongPress: PropTypes.func
-};
-
-export default LongPress;
diff --git a/app/utils/review.js b/app/utils/review.js
index 1c38f67c8..17ba73c90 100644
--- a/app/utils/review.js
+++ b/app/utils/review.js
@@ -5,6 +5,7 @@ import { isIOS } from './deviceInfo';
import I18n from '../i18n';
import { showErrorAlert } from './info';
import { STORE_REVIEW_LINK } from '../constants/links';
+import { logEvent, events } from './log';
const store = isIOS ? 'App Store' : 'Play Store';
@@ -31,6 +32,7 @@ const onCancelPress = () => {
};
export const onReviewPress = async() => {
+ logEvent(events.SE_REVIEW_THIS_APP);
await onCancelPress();
try {
const supported = await Linking.canOpenURL(STORE_REVIEW_LINK);
@@ -38,6 +40,7 @@ export const onReviewPress = async() => {
Linking.openURL(STORE_REVIEW_LINK);
}
} catch (e) {
+ logEvent(events.SE_REVIEW_THIS_APP_F);
showErrorAlert(I18n.t('Review_app_unable_store', { store }));
}
};
diff --git a/app/views/AdminPanelView/index.js b/app/views/AdminPanelView/index.js
index 283e2ef74..41005fc93 100644
--- a/app/views/AdminPanelView/index.js
+++ b/app/views/AdminPanelView/index.js
@@ -31,6 +31,8 @@ class AdminPanelView extends React.Component {
{}}
source={{ uri: `${ baseUrl }/admin/info?layout=embedded` }}
injectedJavaScript={`Meteor.loginWithToken('${ token }', function() { })`}
/>
diff --git a/app/views/AutoTranslateView/index.js b/app/views/AutoTranslateView/index.js
index 0f52db69f..5a1671b82 100644
--- a/app/views/AutoTranslateView/index.js
+++ b/app/views/AutoTranslateView/index.js
@@ -15,6 +15,7 @@ import { SWITCH_TRACK_COLOR, themes } from '../../constants/colors';
import scrollPersistTaps from '../../utils/scrollPersistTaps';
import { withTheme } from '../../theme';
import SafeAreaView from '../../containers/SafeAreaView';
+import { logEvent, events } from '../../utils/log';
const styles = StyleSheet.create({
contentContainerStyle: {
@@ -48,13 +49,14 @@ SectionSeparator.propTypes = {
};
class AutoTranslateView extends React.Component {
- static navigationOptions = {
+ static navigationOptions = () => ({
title: I18n.t('Auto_Translate')
- }
+ })
static propTypes = {
route: PropTypes.object,
- theme: PropTypes.string
+ theme: PropTypes.string,
+ navigation: PropTypes.object
}
constructor(props) {
@@ -102,6 +104,7 @@ class AutoTranslateView extends React.Component {
}
toggleAutoTranslate = async() => {
+ logEvent(events.AT_TOGGLE_TRANSLATE);
const { enableAutoTranslate } = this.state;
try {
await RocketChat.saveAutoTranslate({
@@ -112,11 +115,13 @@ class AutoTranslateView extends React.Component {
});
this.setState({ enableAutoTranslate: !enableAutoTranslate });
} catch (error) {
+ logEvent(events.AT_TOGGLE_TRANSLATE_F);
console.log(error);
}
}
saveAutoTranslateLanguage = async(language) => {
+ logEvent(events.AT_SET_LANG);
try {
await RocketChat.saveAutoTranslate({
rid: this.rid,
@@ -125,6 +130,7 @@ class AutoTranslateView extends React.Component {
});
this.setState({ selectedLanguage: language });
} catch (error) {
+ logEvent(events.AT_SET_LANG_F);
console.log(error);
}
}
diff --git a/app/views/ChangePasscodeView.js b/app/views/ChangePasscodeView.js
index ec4a5ab19..ddfdbd0a0 100644
--- a/app/views/ChangePasscodeView.js
+++ b/app/views/ChangePasscodeView.js
@@ -83,7 +83,7 @@ const ChangePasscodeView = React.memo(({ theme }) => {
{!data?.force
? (
-
+
)
: null}
diff --git a/app/views/CreateChannelView.js b/app/views/CreateChannelView.js
index 09e32eb6b..c4f2c5407 100644
--- a/app/views/CreateChannelView.js
+++ b/app/views/CreateChannelView.js
@@ -21,6 +21,7 @@ import { SWITCH_TRACK_COLOR, themes } from '../constants/colors';
import { withTheme } from '../theme';
import { Review } from '../utils/review';
import { getUserSelector } from '../selectors/login';
+import { logEvent, events } from '../utils/log';
import SafeAreaView from '../containers/SafeAreaView';
const styles = StyleSheet.create({
@@ -72,9 +73,9 @@ const styles = StyleSheet.create({
});
class CreateChannelView extends React.Component {
- static navigationOptions = {
+ static navigationOptions = () => ({
title: I18n.t('Create_Channel')
- }
+ });
static propTypes = {
navigation: PropTypes.object,
@@ -166,6 +167,7 @@ class CreateChannelView extends React.Component {
}
removeUser = (user) => {
+ logEvent(events.CREATE_CHANNEL_REMOVE_USER);
const { removeUser } = this.props;
removeUser(user);
}
@@ -194,7 +196,10 @@ class CreateChannelView extends React.Component {
id: 'type',
value: type,
label: 'Private_Channel',
- onValueChange: value => this.setState({ type: value })
+ onValueChange: (value) => {
+ logEvent(events.CREATE_CHANNEL_TOGGLE_TYPE);
+ this.setState({ type: value });
+ }
});
}
@@ -204,7 +209,10 @@ class CreateChannelView extends React.Component {
id: 'readonly',
value: readOnly,
label: 'Read_Only_Channel',
- onValueChange: value => this.setState({ readOnly: value }),
+ onValueChange: (value) => {
+ logEvent(events.CREATE_CHANNEL_TOGGLE_READ_ONLY);
+ this.setState({ readOnly: value });
+ },
disabled: broadcast
});
}
@@ -216,6 +224,7 @@ class CreateChannelView extends React.Component {
value: broadcast,
label: 'Broadcast_Channel',
onValueChange: (value) => {
+ logEvent(events.CREATE_CHANNEL_TOGGLE_BROADCAST);
this.setState({
broadcast: value,
readOnly: value ? true : readOnly
diff --git a/app/views/CreateDiscussionView/index.js b/app/views/CreateDiscussionView/index.js
index 206a70203..7fe6e6977 100644
--- a/app/views/CreateDiscussionView/index.js
+++ b/app/views/CreateDiscussionView/index.js
@@ -25,6 +25,7 @@ import SelectUsers from './SelectUsers';
import styles from './styles';
import SafeAreaView from '../../containers/SafeAreaView';
import { goRoom } from '../../utils/goRoom';
+import { logEvent, events } from '../../utils/log';
class CreateChannelView extends React.Component {
propTypes = {
@@ -129,6 +130,16 @@ class CreateChannelView extends React.Component {
);
};
+ selectChannel = ({ value }) => {
+ logEvent(events.CREATE_DISCUSSION_SELECT_CHANNEL);
+ this.setState({ channel: { rid: value } });
+ }
+
+ selectUsers = ({ value }) => {
+ logEvent(events.CREATE_DISCUSSION_SELECT_USERS);
+ this.setState({ users: value });
+ }
+
render() {
const { name, users } = this.state;
const {
@@ -149,7 +160,7 @@ class CreateChannelView extends React.Component {
userId={user.id}
token={user.token}
initial={this.channel && { text: RocketChat.getRoomTitle(this.channel) }}
- onChannelSelect={({ value }) => this.setState({ channel: { rid: value } })}
+ onChannelSelect={this.selectChannel}
theme={theme}
/>
this.setState({ users: value })}
+ onUserSelect={this.selectUsers}
theme={theme}
/>
({
title: I18n.t('Default_browser')
- }
+ })
static propTypes = {
theme: PropTypes.string
@@ -113,12 +114,13 @@ class DefaultBrowserView extends React.Component {
}
changeDefaultBrowser = async(newBrowser) => {
+ logEvent(events.DB_CHANGE_DEFAULT_BROWSER, { browser: newBrowser });
try {
const browser = newBrowser !== 'inApp' ? newBrowser : null;
await RNUserDefaults.set(DEFAULT_BROWSER_KEY, browser);
this.setState({ browser });
} catch {
- // do nothing
+ logEvent(events.DB_CHANGE_DEFAULT_BROWSER_F);
}
}
@@ -137,7 +139,7 @@ class DefaultBrowserView extends React.Component {
const { title, value } = item;
return (
this.changeDefaultBrowser(value)}
testID={`default-browser-view-${ title }`}
right={this.isSelected(value) ? this.renderIcon : null}
diff --git a/app/views/DirectoryView/Options.js b/app/views/DirectoryView/Options.js
index 223c88e75..18483bda9 100644
--- a/app/views/DirectoryView/Options.js
+++ b/app/views/DirectoryView/Options.js
@@ -61,7 +61,7 @@ export default class DirectoryOptions extends PureComponent {
let icon = 'user';
if (itemType === 'channels') {
text = 'Channels';
- icon = 'hash';
+ icon = 'channel-public';
}
return (
diff --git a/app/views/DirectoryView/index.js b/app/views/DirectoryView/index.js
index 49c89781c..6a02092af 100644
--- a/app/views/DirectoryView/index.js
+++ b/app/views/DirectoryView/index.js
@@ -16,7 +16,7 @@ import StatusBar from '../../containers/StatusBar';
import ActivityIndicator from '../../containers/ActivityIndicator';
import { CloseModalButton } from '../../containers/HeaderButton';
import debounce from '../../utils/debounce';
-import log from '../../utils/log';
+import log, { logEvent, events } from '../../utils/log';
import Options from './Options';
import { withTheme } from '../../theme';
import { themes } from '../../constants/colors';
@@ -115,6 +115,12 @@ class DirectoryView extends React.Component {
changeType = (type) => {
this.setState({ type, data: [] }, () => this.search());
+
+ if (type === 'users') {
+ logEvent(events.DIRECTORY_SEARCH_USERS);
+ } else if (type === 'channels') {
+ logEvent(events.DIRECTORY_SEARCH_CHANNELS);
+ }
}
toggleWorkspace = () => {
@@ -166,7 +172,7 @@ class DirectoryView extends React.Component {
theme={theme}
>
-
+
{type === 'users' ? I18n.t('Users') : I18n.t('Channels')}
diff --git a/app/views/ForgotPasswordView.js b/app/views/ForgotPasswordView.js
index d233c0578..319682c75 100644
--- a/app/views/ForgotPasswordView.js
+++ b/app/views/ForgotPasswordView.js
@@ -12,6 +12,7 @@ import RocketChat from '../lib/rocketchat';
import { withTheme } from '../theme';
import { themes } from '../constants/colors';
import FormContainer, { FormContainerInner } from '../containers/FormContainer';
+import { logEvent, events } from '../utils/log';
class ForgotPasswordView extends React.Component {
static navigationOptions = ({ route }) => ({
@@ -56,6 +57,7 @@ class ForgotPasswordView extends React.Component {
}
resetPassword = async() => {
+ logEvent(events.FP_FORGOT_PASSWORD);
const { email, invalidEmail } = this.state;
if (invalidEmail || !email) {
return;
@@ -69,6 +71,7 @@ class ForgotPasswordView extends React.Component {
showErrorAlert(I18n.t('Forgot_password_If_this_email_is_registered'), I18n.t('Alert'));
}
} catch (e) {
+ logEvent(events.FP_FORGOT_PASSWORD_F);
const msg = (e.data && e.data.error) || I18n.t('There_was_an_error_while_action', { action: I18n.t('resetting_password') });
showErrorAlert(msg, I18n.t('Alert'));
}
diff --git a/app/views/InviteUsersEditView/index.js b/app/views/InviteUsersEditView/index.js
index ee9874298..d5f8d6fb4 100644
--- a/app/views/InviteUsersEditView/index.js
+++ b/app/views/InviteUsersEditView/index.js
@@ -18,12 +18,10 @@ import { themes } from '../../constants/colors';
import { withTheme } from '../../theme';
import Separator from '../../containers/Separator';
import SafeAreaView from '../../containers/SafeAreaView';
+import { logEvent, events } from '../../utils/log';
const OPTIONS = {
days: [{
- label: I18n.t('Never'), value: 0
- },
- {
label: '1', value: 1
},
{
@@ -36,9 +34,6 @@ const OPTIONS = {
label: '30', value: 30
}],
maxUses: [{
- label: I18n.t('No_limit'), value: 0
- },
- {
label: '1', value: 1
},
{
@@ -59,9 +54,9 @@ const OPTIONS = {
};
class InviteUsersView extends React.Component {
- static navigationOptions = {
+ static navigationOptions = () => ({
title: I18n.t('Invite_users')
- }
+ })
static propTypes = {
navigation: PropTypes.object,
@@ -78,6 +73,7 @@ class InviteUsersView extends React.Component {
}
onValueChangePicker = (key, value) => {
+ logEvent(events.IU_EDIT_SET_LINK_PARAM);
const { inviteLinksSetParams } = this.props;
const params = {
[key]: value
@@ -86,14 +82,18 @@ class InviteUsersView extends React.Component {
}
createInviteLink = () => {
+ logEvent(events.IU_EDIT_CREATE_LINK);
const { createInviteLink, navigation } = this.props;
createInviteLink(this.rid);
navigation.pop();
}
- renderPicker = (key) => {
+ renderPicker = (key, first) => {
const { props } = this;
const { theme } = props;
+ const firstEl = [{
+ label: I18n.t(first), value: 0
+ }];
return (
this.onValueChangePicker(key, value)}
- items={OPTIONS[key]}
+ items={firstEl.concat(OPTIONS[key])}
/>
);
}
@@ -121,13 +121,13 @@ class InviteUsersView extends React.Component {
this.renderPicker('days')}
+ right={() => this.renderPicker('days', 'Never')}
theme={theme}
/>
this.renderPicker('maxUses')}
+ right={() => this.renderPicker('maxUses', 'No_limit')}
theme={theme}
/>
diff --git a/app/views/InviteUsersView/index.js b/app/views/InviteUsersView/index.js
index 5b7e4b010..875594b12 100644
--- a/app/views/InviteUsersView/index.js
+++ b/app/views/InviteUsersView/index.js
@@ -18,11 +18,12 @@ import StatusBar from '../../containers/StatusBar';
import { themes } from '../../constants/colors';
import { withTheme } from '../../theme';
import SafeAreaView from '../../containers/SafeAreaView';
+import { logEvent, events } from '../../utils/log';
class InviteUsersView extends React.Component {
- static navigationOptions = {
+ static navigationOptions = () => ({
title: I18n.t('Invite_users')
- }
+ })
static propTypes = {
navigation: PropTypes.object,
@@ -50,6 +51,7 @@ class InviteUsersView extends React.Component {
}
share = () => {
+ logEvent(events.IU_SHARE);
const { invite } = this.props;
if (!invite || !invite.url) {
return;
@@ -58,6 +60,7 @@ class InviteUsersView extends React.Component {
}
edit = () => {
+ logEvent(events.IU_GO_IU_EDIT);
const { navigation } = this.props;
navigation.navigate('InviteUsersEditView', { rid: this.rid });
}
diff --git a/app/views/JitsiMeetView.js b/app/views/JitsiMeetView.js
index 6c0fce96a..6b7a15688 100644
--- a/app/views/JitsiMeetView.js
+++ b/app/views/JitsiMeetView.js
@@ -8,6 +8,7 @@ import RocketChat from '../lib/rocketchat';
import { getUserSelector } from '../selectors/login';
import sharedStyles from './Styles';
+import { logEvent, events } from '../utils/log';
const formatUrl = (url, baseUrl, uriSize, avatarAuthURLFragment) => (
`${ baseUrl }/avatar/${ url }?format=png&width=${ uriSize }&height=${ uriSize }${ avatarAuthURLFragment }`
@@ -59,6 +60,7 @@ class JitsiMeetView extends React.Component {
}
componentWillUnmount() {
+ logEvent(events.JM_CONFERENCE_TERMINATE);
if (this.jitsiTimeout) {
BackgroundTimer.clearInterval(this.jitsiTimeout);
}
@@ -68,6 +70,7 @@ class JitsiMeetView extends React.Component {
// Jitsi Update Timeout needs to be called every 10 seconds to make sure
// call is not ended and is available to web users.
onConferenceJoined = () => {
+ logEvent(events.JM_CONFERENCE_JOIN);
RocketChat.updateJitsiTimeout(this.rid).catch(e => console.log(e));
if (this.jitsiTimeout) {
BackgroundTimer.clearInterval(this.jitsiTimeout);
@@ -78,6 +81,7 @@ class JitsiMeetView extends React.Component {
}
onConferenceTerminated = () => {
+ logEvent(events.JM_CONFERENCE_TERMINATE);
const { navigation } = this.props;
if (this.jitsiTimeout) {
BackgroundTimer.clearInterval(this.jitsiTimeout);
diff --git a/app/views/LanguageView/index.js b/app/views/LanguageView/index.js
index 640602d83..0420da72f 100644
--- a/app/views/LanguageView/index.js
+++ b/app/views/LanguageView/index.js
@@ -6,7 +6,7 @@ import { connect } from 'react-redux';
import RocketChat from '../../lib/rocketchat';
import I18n from '../../i18n';
import { showErrorAlert } from '../../utils/info';
-import log from '../../utils/log';
+import log, { logEvent, events } from '../../utils/log';
import { setUser as setUserAction } from '../../actions/login';
import StatusBar from '../../containers/StatusBar';
import { CustomIcon } from '../../lib/Icons';
@@ -58,9 +58,9 @@ const LANGUAGES = [
];
class LanguageView extends React.Component {
- static navigationOptions = {
+ static navigationOptions = () => ({
title: I18n.t('Change_Language')
- }
+ })
static propTypes = {
user: PropTypes.object,
@@ -112,6 +112,7 @@ class LanguageView extends React.Component {
}
changeLanguage = async(language) => {
+ logEvent(events.LANG_SET_LANGUAGE);
const { user, setUser } = this.props;
const params = {};
@@ -134,10 +135,11 @@ class LanguageView extends React.Component {
record.language = params.language;
});
} catch (e) {
- // do nothing
+ logEvent(events.LANG_SET_LANGUAGE_F);
}
});
} catch (e) {
+ logEvent(events.LANG_SET_LANGUAGE_F);
showErrorAlert(I18n.t('There_was_an_error_while_action', { action: I18n.t('saving_preferences') }));
log(e);
}
diff --git a/app/views/LivechatEditView.js b/app/views/LivechatEditView.js
index 363413946..332eb3ca7 100644
--- a/app/views/LivechatEditView.js
+++ b/app/views/LivechatEditView.js
@@ -218,7 +218,7 @@ const LivechatEditView = ({
{ inputs.tags = e; }}
label={I18n.t('Tags')}
- iconRight='plus'
+ iconRight='add'
onIconRightPress={() => {
const lastText = inputs.tags._lastNativeText || '';
if (lastText.length) {
diff --git a/app/views/LoginView.js b/app/views/LoginView.js
index abc901272..95d8a90d3 100644
--- a/app/views/LoginView.js
+++ b/app/views/LoginView.js
@@ -6,7 +6,6 @@ import {
import { connect } from 'react-redux';
import equal from 'deep-equal';
-import { analytics } from '../utils/log';
import sharedStyles from './Styles';
import Button from '../containers/Button';
import I18n from '../i18n';
@@ -121,7 +120,6 @@ class LoginView extends React.Component {
const { loginRequest } = this.props;
Keyboard.dismiss();
loginRequest({ user, password });
- analytics().logEvent('login');
}
renderUserForm = () => {
diff --git a/app/views/MarkdownTableView.js b/app/views/MarkdownTableView.js
index 049623444..3c552bcf1 100644
--- a/app/views/MarkdownTableView.js
+++ b/app/views/MarkdownTableView.js
@@ -8,9 +8,9 @@ import { themes } from '../constants/colors';
import { withTheme } from '../theme';
class MarkdownTableView extends React.Component {
- static navigationOptions = {
+ static navigationOptions = () => ({
title: I18n.t('Table')
- }
+ })
static propTypes = {
route: PropTypes.object,
diff --git a/app/views/MessagesView/index.js b/app/views/MessagesView/index.js
index c01b63c25..4e826d3fc 100644
--- a/app/views/MessagesView/index.js
+++ b/app/views/MessagesView/index.js
@@ -18,10 +18,6 @@ import { withActionSheet } from '../../containers/ActionSheet';
import SafeAreaView from '../../containers/SafeAreaView';
class MessagesView extends React.Component {
- static navigationOptions = ({ route }) => ({
- title: I18n.t(route.params?.name)
- });
-
static propTypes = {
user: PropTypes.object,
baseUrl: PropTypes.string,
@@ -39,6 +35,7 @@ class MessagesView extends React.Component {
messages: [],
fileLoading: true
};
+ this.setHeader();
this.rid = props.route.params?.rid;
this.t = props.route.params?.t;
this.content = this.defineMessagesViewContent(props.route.params?.name);
@@ -65,10 +62,16 @@ class MessagesView extends React.Component {
if (fileLoading !== nextState.fileLoading) {
return true;
}
-
return false;
}
+ setHeader = () => {
+ const { route, navigation } = this.props;
+ navigation.setOptions({
+ title: I18n.t(route.params?.name)
+ });
+ }
+
navToRoomInfo = (navParam) => {
const { navigation, user } = this.props;
if (navParam.rid === user.id) {
@@ -78,9 +81,7 @@ class MessagesView extends React.Component {
}
defineMessagesViewContent = (name) => {
- const { messages } = this.state;
const { user, baseUrl, theme } = this.props;
-
const renderItemCommonProps = item => ({
item,
baseUrl,
@@ -101,6 +102,7 @@ class MessagesView extends React.Component {
Files: {
name: I18n.t('Files'),
fetchFunc: async() => {
+ const { messages } = this.state;
const result = await RocketChat.getFiles(this.rid, this.t, messages.length);
return { ...result, messages: result.files };
},
@@ -125,12 +127,15 @@ class MessagesView extends React.Component {
// Mentions Messages Screen
Mentions: {
name: I18n.t('Mentions'),
- fetchFunc: () => RocketChat.getMessages(
- this.rid,
- this.t,
- { 'mentions._id': { $in: [user.id] } },
- messages.length
- ),
+ fetchFunc: () => {
+ const { messages } = this.state;
+ return RocketChat.getMessages(
+ this.rid,
+ this.t,
+ { 'mentions._id': { $in: [user.id] } },
+ messages.length
+ );
+ },
noDataMsg: I18n.t('No_mentioned_messages'),
testID: 'mentioned-messages-view',
renderItem: item => (
@@ -144,12 +149,15 @@ class MessagesView extends React.Component {
// Starred Messages Screen
Starred: {
name: I18n.t('Starred'),
- fetchFunc: () => RocketChat.getMessages(
- this.rid,
- this.t,
- { 'starred._id': { $in: [user.id] } },
- messages.length
- ),
+ fetchFunc: () => {
+ const { messages } = this.state;
+ return RocketChat.getMessages(
+ this.rid,
+ this.t,
+ { 'starred._id': { $in: [user.id] } },
+ messages.length
+ );
+ },
noDataMsg: I18n.t('No_starred_messages'),
testID: 'starred-messages-view',
renderItem: item => (
@@ -166,7 +174,10 @@ class MessagesView extends React.Component {
// Pinned Messages Screen
Pinned: {
name: I18n.t('Pinned'),
- fetchFunc: () => RocketChat.getMessages(this.rid, this.t, { pinned: true }, messages.length),
+ fetchFunc: () => {
+ const { messages } = this.state;
+ return RocketChat.getMessages(this.rid, this.t, { pinned: true }, messages.length);
+ },
noDataMsg: I18n.t('No_pinned_messages'),
testID: 'pinned-messages-view',
renderItem: item => (
diff --git a/app/views/ModalBlockView.js b/app/views/ModalBlockView.js
index 57b415fdc..e88d30885 100644
--- a/app/views/ModalBlockView.js
+++ b/app/views/ModalBlockView.js
@@ -3,7 +3,7 @@ import { StyleSheet, View } from 'react-native';
import PropTypes from 'prop-types';
import isEqual from 'lodash/isEqual';
import { connect } from 'react-redux';
-import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view';
+import { KeyboardAwareScrollView } from '@codler/react-native-keyboard-aware-scroll-view';
import { withTheme } from '../theme';
import EventEmitter from '../utils/events';
diff --git a/app/views/NewMessageView.js b/app/views/NewMessageView.js
index 4e07d5409..9a1042900 100644
--- a/app/views/NewMessageView.js
+++ b/app/views/NewMessageView.js
@@ -14,7 +14,7 @@ import RocketChat from '../lib/rocketchat';
import UserItem from '../presentation/UserItem';
import sharedStyles from './Styles';
import I18n from '../i18n';
-import log from '../utils/log';
+import log, { logEvent, events } from '../utils/log';
import SearchBox from '../containers/SearchBox';
import { CustomIcon } from '../lib/Icons';
import { CloseModalButton } from '../containers/HeaderButton';
@@ -133,11 +133,13 @@ class NewMessageView extends React.Component {
}
createChannel = () => {
+ logEvent(events.NEW_MSG_CREATE_CHANNEL);
const { navigation } = this.props;
navigation.navigate('SelectedUsersViewCreateChannel', { nextAction: () => navigation.navigate('CreateChannelView') });
}
createGroupChat = () => {
+ logEvent(events.NEW_MSG_CREATE_GROUP_CHAT);
const { createChannel, maxUsers, navigation } = this.props;
navigation.navigate('SelectedUsersViewCreateChannel', {
nextAction: () => createChannel({ group: true }),
@@ -147,6 +149,7 @@ class NewMessageView extends React.Component {
}
goRoom = (item) => {
+ logEvent(events.NEW_MSG_CHAT_WITH_USER);
const { isMasterDetail, navigation } = this.props;
if (isMasterDetail) {
navigation.pop();
@@ -174,6 +177,7 @@ class NewMessageView extends React.Component {
}
createDiscussion = () => {
+ logEvent(events.NEW_MSG_CREATE_DISCUSSION);
Navigation.navigate('CreateDiscussionView');
}
@@ -186,7 +190,7 @@ class NewMessageView extends React.Component {
{this.renderButton({
onPress: this.createChannel,
title: I18n.t('Create_Channel'),
- icon: 'hash',
+ icon: 'channel-public',
testID: 'new-message-view-create-channel',
first: true
})}
@@ -199,7 +203,7 @@ class NewMessageView extends React.Component {
{this.renderButton({
onPress: this.createDiscussion,
title: I18n.t('Create_Discussion'),
- icon: 'chat',
+ icon: 'discussions',
testID: 'new-message-view-create-discussion'
})}
diff --git a/app/views/NewServerView.js b/app/views/NewServerView.js
index b9429c05a..ec1229393 100644
--- a/app/views/NewServerView.js
+++ b/app/views/NewServerView.js
@@ -7,11 +7,12 @@ import { connect } from 'react-redux';
import * as FileSystem from 'expo-file-system';
import DocumentPicker from 'react-native-document-picker';
import RNUserDefaults from 'rn-user-defaults';
-import { encode } from 'base-64';
+import { Base64 } from 'js-base64';
import parse from 'url-parse';
import EventEmitter from '../utils/events';
import { selectServerRequest, serverRequest } from '../actions/server';
+import { inviteLinksClear as inviteLinksClearAction } from '../actions/inviteLinks';
import sharedStyles from './Styles';
import Button from '../containers/Button';
import TextInput from '../containers/TextInput';
@@ -20,7 +21,7 @@ import FormContainer, { FormContainerInner } from '../containers/FormContainer';
import I18n from '../i18n';
import { isIOS } from '../utils/deviceInfo';
import { themes } from '../constants/colors';
-import log from '../utils/log';
+import log, { logEvent, events } from '../utils/log';
import { animateNextTransition } from '../utils/layoutAnimation';
import { withTheme } from '../theme';
import { setBasicAuth, BASIC_AUTH_KEY } from '../utils/fetch';
@@ -61,9 +62,9 @@ const styles = StyleSheet.create({
});
class NewServerView extends React.Component {
- static navigationOptions = {
+ static navigationOptions = () => ({
title: I18n.t('Workspaces')
- }
+ })
static propTypes = {
navigation: PropTypes.object,
@@ -72,16 +73,13 @@ class NewServerView extends React.Component {
connectServer: PropTypes.func.isRequired,
selectServer: PropTypes.func.isRequired,
adding: PropTypes.bool,
- previousServer: PropTypes.string
+ previousServer: PropTypes.string,
+ inviteLinksClear: PropTypes.func
}
constructor(props) {
super(props);
- if (props.adding) {
- props.navigation.setOptions({
- headerLeft: () =>
- });
- }
+ this.setHeader();
this.state = {
text: '',
@@ -92,11 +90,27 @@ class NewServerView extends React.Component {
BackHandler.addEventListener('hardwareBackPress', this.handleBackPress);
}
+ componentDidUpdate(prevProps) {
+ const { adding } = this.props;
+ if (prevProps.adding !== adding) {
+ this.setHeader();
+ }
+ }
+
componentWillUnmount() {
EventEmitter.removeListener('NewServer', this.handleNewServerEvent);
BackHandler.removeEventListener('hardwareBackPress', this.handleBackPress);
}
+ setHeader = () => {
+ const { adding, navigation } = this.props;
+ if (adding) {
+ navigation.setOptions({
+ headerLeft: () =>
+ });
+ }
+ }
+
handleBackPress = () => {
const { navigation, previousServer } = this.props;
if (navigation.isFocused() && previousServer) {
@@ -111,7 +125,8 @@ class NewServerView extends React.Component {
}
close = () => {
- const { selectServer, previousServer } = this.props;
+ const { selectServer, previousServer, inviteLinksClear } = this.props;
+ inviteLinksClear();
selectServer(previousServer);
}
@@ -124,6 +139,7 @@ class NewServerView extends React.Component {
}
submit = async() => {
+ logEvent(events.NEWSERVER_CONNECT_TO_WORKSPACE);
const { text, certificate } = this.state;
const { connectServer } = this.props;
let cert = null;
@@ -135,6 +151,7 @@ class NewServerView extends React.Component {
try {
await FileSystem.copyAsync({ from: certificate.path, to: certificatePath });
} catch (e) {
+ logEvent(events.NEWSERVER_CONNECT_TO_WORKSPACE_F);
log(e);
}
cert = {
@@ -152,6 +169,7 @@ class NewServerView extends React.Component {
}
connectOpen = () => {
+ logEvent(events.NEWSERVER_JOIN_OPEN_WORKSPACE);
this.setState({ connectingOpen: true });
const { connectServer } = this.props;
connectServer('https://open.rocket.chat');
@@ -161,7 +179,7 @@ class NewServerView extends React.Component {
try {
const parsedUrl = parse(text, true);
if (parsedUrl.auth.length) {
- const credentials = encode(parsedUrl.auth);
+ const credentials = Base64.encode(parsedUrl.auth);
await RNUserDefaults.set(`${ BASIC_AUTH_KEY }-${ server }`, credentials);
setBasicAuth(credentials);
}
@@ -321,7 +339,8 @@ const mapStateToProps = state => ({
const mapDispatchToProps = dispatch => ({
connectServer: (server, certificate) => dispatch(serverRequest(server, certificate)),
- selectServer: server => dispatch(selectServerRequest(server))
+ selectServer: server => dispatch(selectServerRequest(server)),
+ inviteLinksClear: () => dispatch(inviteLinksClearAction())
});
export default connect(mapStateToProps, mapDispatchToProps)(withTheme(NewServerView));
diff --git a/app/views/NotificationPreferencesView/index.js b/app/views/NotificationPreferencesView/index.js
index 31a0fc679..4fad41839 100644
--- a/app/views/NotificationPreferencesView/index.js
+++ b/app/views/NotificationPreferencesView/index.js
@@ -16,7 +16,7 @@ import RocketChat from '../../lib/rocketchat';
import { withTheme } from '../../theme';
import protectedFunction from '../../lib/methods/helpers/protectedFunction';
import SafeAreaView from '../../containers/SafeAreaView';
-import log from '../../utils/log';
+import log, { events, logEvent } from '../../utils/log';
const SectionTitle = React.memo(({ title, theme }) => (
({
title: I18n.t('Notification_Preferences')
- }
+ })
static propTypes = {
navigation: PropTypes.object,
@@ -181,6 +181,7 @@ class NotificationPreferencesView extends React.Component {
}
saveNotificationSettings = async(key, value, params) => {
+ logEvent(events[`NP_${ key.toUpperCase() }`]);
const { room } = this.state;
const db = database.active;
@@ -206,6 +207,7 @@ class NotificationPreferencesView extends React.Component {
}));
});
} catch (e) {
+ logEvent(events[`NP_${ key.toUpperCase() }_F`]);
log(e);
}
}
@@ -229,7 +231,7 @@ class NotificationPreferencesView extends React.Component {
const { room } = this.state;
const { theme } = this.props;
const text = room[key] ? OPTIONS[key].find(option => option.value === room[key]) : OPTIONS[key][0];
- return {text?.label};
+ return {I18n.t(text?.label, { defaultValue: text?.label, second: text?.second })};
}
renderSwitch = (key) => {
diff --git a/app/views/OnboardingView/index.js b/app/views/OnboardingView/index.js
index 0a1ac7383..5be0446c1 100644
--- a/app/views/OnboardingView/index.js
+++ b/app/views/OnboardingView/index.js
@@ -14,6 +14,7 @@ import { isTablet } from '../../utils/deviceInfo';
import { themes } from '../../constants/colors';
import { withTheme } from '../../theme';
import FormContainer, { FormContainerInner } from '../../containers/FormContainer';
+import { logEvent, events } from '../../utils/log';
class OnboardingView extends React.Component {
static navigationOptions = {
@@ -69,15 +70,17 @@ class OnboardingView extends React.Component {
}
connectServer = () => {
+ logEvent(events.ONBOARD_JOIN_A_WORKSPACE);
const { navigation } = this.props;
navigation.navigate('NewServerView');
}
createWorkspace = async() => {
+ logEvent(events.ONBOARD_CREATE_NEW_WORKSPACE);
try {
await Linking.openURL('https://cloud.rocket.chat/trial');
} catch {
- // do nothing
+ logEvent(events.ONBOARD_CREATE_NEW_WORKSPACE_F);
}
}
diff --git a/app/views/PickerView.js b/app/views/PickerView.js
index 489d8a42f..062e373ab 100644
--- a/app/views/PickerView.js
+++ b/app/views/PickerView.js
@@ -42,7 +42,7 @@ const Item = React.memo(({
theme
}) => (
)}
onPress={onItemPress}
theme={theme}
diff --git a/app/views/ProfileView/index.js b/app/views/ProfileView/index.js
index f6155c2a2..8d289935b 100644
--- a/app/views/ProfileView/index.js
+++ b/app/views/ProfileView/index.js
@@ -18,7 +18,7 @@ import { LISTENER } from '../../containers/Toast';
import EventEmitter from '../../utils/events';
import RocketChat from '../../lib/rocketchat';
import RCTextInput from '../../containers/TextInput';
-import log from '../../utils/log';
+import log, { logEvent, events } from '../../utils/log';
import I18n from '../../i18n';
import Button from '../../containers/Button';
import Avatar from '../../containers/Avatar';
@@ -223,8 +223,10 @@ class ProfileView extends React.Component {
try {
if (avatar.url) {
try {
+ logEvent(events.PROFILE_SAVE_AVATAR);
await RocketChat.setAvatarFromService(avatar);
} catch (e) {
+ logEvent(events.PROFILE_SAVE_AVATAR_F);
this.setState({ saving: false, currentPassword: null });
return this.handleError(e, 'setAvatarFromService', 'changing_avatar');
}
@@ -233,6 +235,7 @@ class ProfileView extends React.Component {
const result = await RocketChat.saveUserProfile(params, customFields);
if (result.success) {
+ logEvent(events.PROFILE_SAVE_CHANGES);
if (customFields) {
setUser({ customFields, ...params });
} else {
@@ -243,6 +246,7 @@ class ProfileView extends React.Component {
}
this.setState({ saving: false });
} catch (e) {
+ logEvent(events.PROFILE_SAVE_CHANGES_F);
this.setState({ saving: false, currentPassword: null });
this.handleError(e, 'saveUserProfile', 'saving_profile');
}
@@ -281,13 +285,20 @@ class ProfileView extends React.Component {
includeBase64: true
};
try {
+ logEvent(events.PROFILE_PICK_AVATAR);
const response = await ImagePicker.openPicker(options);
this.setAvatar({ url: response.path, data: `data:image/jpeg;base64,${ response.data }`, service: 'upload' });
} catch (error) {
+ logEvent(events.PROFILE_PICK_AVATAR_F);
console.warn(error);
}
}
+ pickImageWithURL = (avatarUrl) => {
+ logEvent(events.PROFILE_PICK_AVATAR_WITH_URL);
+ this.setAvatar({ url: avatarUrl, data: avatarUrl, service: 'url' });
+ }
+
renderAvatarButton = ({
key, child, onPress, disabled = false
}) => {
@@ -331,7 +342,7 @@ class ProfileView extends React.Component {
})}
{this.renderAvatarButton({
child: ,
- onPress: () => this.setAvatar({ url: avatarUrl, data: avatarUrl, service: 'url' }),
+ onPress: () => this.pickImageWithURL(avatarUrl),
disabled: !avatarUrl,
key: 'profile-view-avatar-url-button'
})}
diff --git a/app/views/QueueListView.js b/app/views/QueueListView.js
new file mode 100644
index 000000000..301f09a0f
--- /dev/null
+++ b/app/views/QueueListView.js
@@ -0,0 +1,160 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { FlatList } from 'react-native';
+import { connect } from 'react-redux';
+import isEqual from 'react-fast-compare';
+
+import I18n from '../i18n';
+import RoomItem, { ROW_HEIGHT } from '../presentation/RoomItem';
+import { MAX_SIDEBAR_WIDTH } from '../constants/tablet';
+import { isTablet, isIOS } from '../utils/deviceInfo';
+import { getUserSelector } from '../selectors/login';
+import { withTheme } from '../theme';
+import { withDimensions } from '../dimensions';
+import SafeAreaView from '../containers/SafeAreaView';
+import { themes } from '../constants/colors';
+import StatusBar from '../containers/StatusBar';
+import { goRoom } from '../utils/goRoom';
+import { CloseModalButton } from '../containers/HeaderButton';
+import RocketChat from '../lib/rocketchat';
+import { logEvent, events } from '../utils/log';
+import { getInquiryQueueSelector } from '../selectors/inquiry';
+
+const INITIAL_NUM_TO_RENDER = isTablet ? 20 : 12;
+const getItemLayout = (data, index) => ({
+ length: ROW_HEIGHT,
+ offset: ROW_HEIGHT * index,
+ index
+});
+const keyExtractor = item => item.rid;
+
+class QueueListView extends React.Component {
+ static navigationOptions = ({ navigation, isMasterDetail }) => {
+ const options = {
+ title: I18n.t('Queued_chats')
+ };
+ if (isMasterDetail) {
+ options.headerLeft = () => ;
+ }
+ return options;
+ }
+
+ static propTypes = {
+ user: PropTypes.shape({
+ id: PropTypes.string,
+ username: PropTypes.string,
+ token: PropTypes.string
+ }),
+ isMasterDetail: PropTypes.bool,
+ width: PropTypes.number,
+ queued: PropTypes.array,
+ server: PropTypes.string,
+ useRealName: PropTypes.bool,
+ navigation: PropTypes.object,
+ theme: PropTypes.string
+ }
+
+ shouldComponentUpdate(nextProps) {
+ const { queued } = this.props;
+ if (!isEqual(nextProps.queued, queued)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ onPressItem = (item = {}) => {
+ logEvent(events.QL_GO_ROOM);
+ const { navigation, isMasterDetail } = this.props;
+ if (isMasterDetail) {
+ navigation.navigate('DrawerNavigator');
+ } else {
+ navigation.navigate('RoomsListView');
+ }
+
+ goRoom({
+ item: {
+ ...item,
+ // we're calling v as visitor on our mergeSubscriptionsRooms
+ visitor: item.v
+ },
+ isMasterDetail
+ });
+ };
+
+ getRoomTitle = item => RocketChat.getRoomTitle(item)
+
+ getRoomAvatar = item => RocketChat.getRoomAvatar(item)
+
+ getUidDirectMessage = room => RocketChat.getUidDirectMessage(room)
+
+ renderItem = ({ item }) => {
+ const {
+ user: {
+ id: userId,
+ username,
+ token
+ },
+ server,
+ useRealName,
+ theme,
+ isMasterDetail,
+ width
+ } = this.props;
+ const id = this.getUidDirectMessage(item);
+
+ return (
+
+ );
+ }
+
+ render() {
+ const { queued, theme } = this.props;
+ return (
+
+
+
+
+ );
+ }
+}
+
+const mapStateToProps = state => ({
+ user: getUserSelector(state),
+ isMasterDetail: state.app.isMasterDetail,
+ server: state.server.server,
+ useRealName: state.settings.UI_Use_Real_Name,
+ queued: getInquiryQueueSelector(state)
+});
+export default connect(mapStateToProps)(withDimensions(withTheme(QueueListView)));
diff --git a/app/views/ReadReceiptView/index.js b/app/views/ReadReceiptView/index.js
index c5ea398a9..9ec188d0d 100644
--- a/app/views/ReadReceiptView/index.js
+++ b/app/views/ReadReceiptView/index.js
@@ -8,6 +8,7 @@ import { connect } from 'react-redux';
import Avatar from '../../containers/Avatar';
import styles from './styles';
import ActivityIndicator from '../../containers/ActivityIndicator';
+import { CloseModalButton } from '../../containers/HeaderButton';
import I18n from '../../i18n';
import RocketChat from '../../lib/rocketchat';
import StatusBar from '../../containers/StatusBar';
@@ -17,8 +18,14 @@ import { getUserSelector } from '../../selectors/login';
import SafeAreaView from '../../containers/SafeAreaView';
class ReadReceiptView extends React.Component {
- static navigationOptions = {
- title: I18n.t('Read_Receipt')
+ static navigationOptions = ({ navigation, isMasterDetail }) => {
+ const options = {
+ title: I18n.t('Read_Receipt')
+ };
+ if (isMasterDetail) {
+ options.headerLeft = () => ;
+ }
+ return options;
}
static propTypes = {
diff --git a/app/views/RegisterView.js b/app/views/RegisterView.js
index 1e0ce2654..23711a7cd 100644
--- a/app/views/RegisterView.js
+++ b/app/views/RegisterView.js
@@ -6,7 +6,7 @@ import {
import { connect } from 'react-redux';
import RNPickerSelect from 'react-native-picker-select';
-import log from '../utils/log';
+import log, { logEvent, events } from '../utils/log';
import sharedStyles from './Styles';
import Button from '../containers/Button';
import I18n from '../i18n';
@@ -114,6 +114,7 @@ class RegisterView extends React.Component {
}
submit = async() => {
+ logEvent(events.REGISTER_DEFAULT_SIGN_UP);
if (!this.valid()) {
return;
}
@@ -149,6 +150,7 @@ class RegisterView extends React.Component {
return loginRequest({ user: email, password });
}
if (e.data?.error) {
+ logEvent(events.REGISTER_DEFAULT_SIGN_UP_F);
showErrorAlert(e.data.error, I18n.t('Oops'));
}
}
diff --git a/app/views/RoomActionsView/index.js b/app/views/RoomActionsView/index.js
index 67aff37e4..13070fb49 100644
--- a/app/views/RoomActionsView/index.js
+++ b/app/views/RoomActionsView/index.js
@@ -14,7 +14,7 @@ import sharedStyles from '../Styles';
import Avatar from '../../containers/Avatar';
import Status from '../../containers/Status';
import RocketChat from '../../lib/rocketchat';
-import log from '../../utils/log';
+import log, { logEvent, events } from '../../utils/log';
import RoomTypeIcon from '../../containers/RoomTypeIcon';
import I18n from '../../i18n';
import scrollPersistTaps from '../../utils/scrollPersistTaps';
@@ -91,7 +91,7 @@ class RoomActionsView extends React.Component {
this.mounted = true;
const { room, member } = this.state;
if (room.rid) {
- if (!room.id) {
+ if (!room.id && !this.isOmnichannelPreview) {
try {
const result = await RocketChat.getChannelInfo(room.rid);
if (result.success) {
@@ -135,13 +135,20 @@ class RoomActionsView extends React.Component {
}
}
+ get isOmnichannelPreview() {
+ const { room } = this.state;
+ return room.t === 'l' && room.status === 'queued';
+ }
+
onPressTouchable = (item) => {
- if (item.route) {
+ const { route, event, params } = item;
+ if (route) {
+ logEvent(events[`RA_GO_${ route.replace('View', '').toUpperCase() }${ params.name ? params.name.toUpperCase() : '' }`]);
const { navigation } = this.props;
- navigation.navigate(item.route, item.params);
+ navigation.navigate(route, params);
}
- if (item.event) {
- return item.event();
+ if (event) {
+ return event();
}
}
@@ -229,7 +236,7 @@ class RoomActionsView extends React.Component {
const isGroupChat = RocketChat.isGroupChat(room);
const notificationsAction = {
- icon: 'bell',
+ icon: 'notification',
name: I18n.t('Notifications'),
route: 'NotificationPrefView',
params: { rid, room },
@@ -238,13 +245,13 @@ class RoomActionsView extends React.Component {
const jitsiActions = jitsiEnabled ? [
{
- icon: 'mic',
+ icon: 'phone',
name: I18n.t('Voice_call'),
event: () => RocketChat.callJitsi(rid, true),
testID: 'room-actions-voice'
},
{
- icon: 'video-1',
+ icon: 'camera',
name: I18n.t('Video_call'),
event: () => RocketChat.callJitsi(rid),
testID: 'room-actions-video'
@@ -270,14 +277,14 @@ class RoomActionsView extends React.Component {
}, {
data: [
{
- icon: 'clip',
+ icon: 'attach',
name: I18n.t('Files'),
route: 'MessagesView',
params: { rid, t, name: 'Files' },
testID: 'room-actions-files'
},
{
- icon: 'at',
+ icon: 'mention',
name: I18n.t('Mentions'),
route: 'MessagesView',
params: { rid, t, name: 'Mentions' },
@@ -291,7 +298,7 @@ class RoomActionsView extends React.Component {
testID: 'room-actions-starred'
},
{
- icon: 'magnifier',
+ icon: 'search',
name: I18n.t('Search'),
route: 'SearchMessagesView',
params: { rid },
@@ -365,7 +372,7 @@ class RoomActionsView extends React.Component {
if (canAddUser) {
actions.push({
- icon: 'plus',
+ icon: 'add',
name: I18n.t('Add_users'),
route: 'SelectedUsersView',
params: {
@@ -378,7 +385,7 @@ class RoomActionsView extends React.Component {
}
if (canInviteUser) {
actions.push({
- icon: 'add-user',
+ icon: 'user-add',
name: I18n.t('Invite_users'),
route: 'InviteUsersView',
params: {
@@ -394,7 +401,7 @@ class RoomActionsView extends React.Component {
sections.push({
data: [
{
- icon: 'exit',
+ icon: 'logout',
name: I18n.t('Leave_channel'),
type: 'danger',
event: this.leaveChannel,
@@ -407,36 +414,38 @@ class RoomActionsView extends React.Component {
} else if (t === 'l') {
sections[2].data = [];
- sections[2].data.push({
- icon: 'cancel',
- name: I18n.t('Close'),
- event: this.closeLivechat
- });
-
- if (canForwardGuest) {
+ if (!this.isOmnichannelPreview) {
sections[2].data.push({
- icon: 'transfer',
- name: I18n.t('Forward'),
- route: 'ForwardLivechatView',
+ icon: 'close',
+ name: I18n.t('Close'),
+ event: this.closeLivechat
+ });
+
+ if (canForwardGuest) {
+ sections[2].data.push({
+ icon: 'user-forward',
+ name: I18n.t('Forward'),
+ route: 'ForwardLivechatView',
+ params: { rid }
+ });
+ }
+
+ if (canReturnQueue) {
+ sections[2].data.push({
+ icon: 'undo',
+ name: I18n.t('Return'),
+ event: this.returnLivechat
+ });
+ }
+
+ sections[2].data.push({
+ icon: 'history',
+ name: I18n.t('Navigation_history'),
+ route: 'VisitorNavigationView',
params: { rid }
});
}
- if (canReturnQueue) {
- sections[2].data.push({
- icon: 'undo',
- name: I18n.t('Return'),
- event: this.returnLivechat
- });
- }
-
- sections[2].data.push({
- icon: 'history',
- name: I18n.t('Navigation_history'),
- route: 'VisitorNavigationView',
- params: { rid }
- });
-
sections.push({
data: [notificationsAction],
renderItem: this.renderItem
@@ -506,17 +515,20 @@ class RoomActionsView extends React.Component {
}
toggleBlockUser = () => {
+ logEvent(events.RA_TOGGLE_BLOCK_USER);
const { room } = this.state;
const { rid, blocker } = room;
const { member } = this.state;
try {
RocketChat.toggleBlockUser(rid, member._id, !blocker);
} catch (e) {
+ logEvent(events.RA_TOGGLE_BLOCK_USER_F);
log(e);
}
}
handleShare = () => {
+ logEvent(events.RA_SHARE);
const { room } = this.state;
const permalink = RocketChat.getPermalinkChannel(room);
if (!permalink) {
diff --git a/app/views/RoomInfoEditView/index.js b/app/views/RoomInfoEditView/index.js
index 5db7c7883..4d913e1cd 100644
--- a/app/views/RoomInfoEditView/index.js
+++ b/app/views/RoomInfoEditView/index.js
@@ -23,7 +23,7 @@ import RCTextInput from '../../containers/TextInput';
import Loading from '../../containers/Loading';
import SwitchContainer from './SwitchContainer';
import random from '../../utils/random';
-import log from '../../utils/log';
+import log, { logEvent, events } from '../../utils/log';
import I18n from '../../i18n';
import StatusBar from '../../containers/StatusBar';
import { themes } from '../../constants/colors';
@@ -48,9 +48,9 @@ const PERMISSIONS_ARRAY = [
];
class RoomInfoEditView extends React.Component {
- static navigationOptions = {
+ static navigationOptions = () => ({
title: I18n.t('Room_Info_Edit')
- }
+ })
static propTypes = {
route: PropTypes.object,
@@ -150,6 +150,7 @@ class RoomInfoEditView extends React.Component {
}
reset = () => {
+ logEvent(events.RI_EDIT_RESET);
this.clearErrors();
this.init(this.room);
}
@@ -173,6 +174,7 @@ class RoomInfoEditView extends React.Component {
}
submit = async() => {
+ logEvent(events.RI_EDIT_SAVE);
Keyboard.dismiss();
const {
room, name, description, topic, announcement, t, ro, reactWhenReadOnly, joinCode, systemMessages
@@ -242,6 +244,7 @@ class RoomInfoEditView extends React.Component {
await this.setState({ saving: false });
setTimeout(() => {
if (error) {
+ logEvent(events.RI_EDIT_SAVE_F);
showErrorAlert(I18n.t('There_was_an_error_while_action', { action: I18n.t('saving_settings') }));
} else {
EventEmitter.emit(LISTENER, { message: I18n.t('Settings_succesfully_changed') });
@@ -289,8 +292,10 @@ class RoomInfoEditView extends React.Component {
style: 'destructive',
onPress: async() => {
try {
+ logEvent(events.RI_EDIT_TOGGLE_ARCHIVE);
await RocketChat.toggleArchiveRoom(rid, t, !archived);
} catch (e) {
+ logEvent(events.RI_EDIT_TOGGLE_ARCHIVE_F);
log(e);
}
}
@@ -333,6 +338,26 @@ class RoomInfoEditView extends React.Component {
);
}
+ toggleRoomType = (value) => {
+ logEvent(events.RI_EDIT_TOGGLE_ROOM_TYPE);
+ this.setState({ t: value });
+ }
+
+ toggleReadOnly = (value) => {
+ logEvent(events.RI_EDIT_TOGGLE_READ_ONLY);
+ this.setState({ ro: value });
+ }
+
+ toggleReactions = (value) => {
+ logEvent(events.RI_EDIT_TOGGLE_REACTIONS);
+ this.setState({ reactWhenReadOnly: value });
+ }
+
+ toggleHideSystemMessages = (value) => {
+ logEvent(events.RI_EDIT_TOGGLE_SYSTEM_MSG);
+ this.setState(({ systemMessages }) => ({ enableSysMes: value, systemMessages: value ? systemMessages : [] }));
+ }
+
render() {
const {
name, nameError, description, topic, announcement, t, ro, reactWhenReadOnly, room, joinCode, saving, permissions, archived, enableSysMes
@@ -410,7 +435,7 @@ class RoomInfoEditView extends React.Component {
leftLabelSecondary={I18n.t('Everyone_can_access_this_channel')}
rightLabelPrimary={I18n.t('Private')}
rightLabelSecondary={I18n.t('Just_invited_people_can_access_this_channel')}
- onValueChange={value => this.setState({ t: value })}
+ onValueChange={this.toggleRoomType}
theme={theme}
testID='room-info-edit-view-t'
/>
@@ -420,7 +445,7 @@ class RoomInfoEditView extends React.Component {
leftLabelSecondary={I18n.t('All_users_in_the_channel_can_write_new_messages')}
rightLabelPrimary={I18n.t('Read_Only')}
rightLabelSecondary={I18n.t('Only_authorized_users_can_write_new_messages')}
- onValueChange={value => this.setState({ ro: value })}
+ onValueChange={this.toggleReadOnly}
disabled={!permissions[PERMISSION_SET_READONLY] || room.broadcast}
theme={theme}
testID='room-info-edit-view-ro'
@@ -433,7 +458,7 @@ class RoomInfoEditView extends React.Component {
leftLabelSecondary={I18n.t('Reactions_are_disabled')}
rightLabelPrimary={I18n.t('Allow_Reactions')}
rightLabelSecondary={I18n.t('Reactions_are_enabled')}
- onValueChange={value => this.setState({ reactWhenReadOnly: value })}
+ onValueChange={this.toggleReactions}
disabled={!permissions[PERMISSION_SET_REACT_WHEN_READONLY]}
theme={theme}
testID='room-info-edit-view-react-when-ro'
@@ -455,7 +480,7 @@ class RoomInfoEditView extends React.Component {
leftLabelSecondary={enableSysMes ? I18n.t('Overwrites_the_server_configuration_and_use_room_config') : I18n.t('Uses_server_configuration')}
theme={theme}
testID='room-info-edit-switch-system-messages'
- onValueChange={value => this.setState(({ systemMessages }) => ({ enableSysMes: value, systemMessages: value ? systemMessages : [] }))}
+ onValueChange={this.toggleHideSystemMessages}
labelContainerStyle={styles.hideSystemMessages}
leftLabelStyle={styles.systemMessagesLabel}
>
diff --git a/app/views/RoomInfoView/Livechat.js b/app/views/RoomInfoView/Livechat.js
index a93ea1714..09e14a608 100644
--- a/app/views/RoomInfoView/Livechat.js
+++ b/app/views/RoomInfoView/Livechat.js
@@ -44,7 +44,7 @@ const Livechat = ({ room, roomUser, theme }) => {
}
};
- useEffect(() => { getRoom(); }, []);
+ useEffect(() => { getRoom(); }, [room]);
return (
<>
diff --git a/app/views/RoomInfoView/index.js b/app/views/RoomInfoView/index.js
index b3711b0f4..a0160d517 100644
--- a/app/views/RoomInfoView/index.js
+++ b/app/views/RoomInfoView/index.js
@@ -17,11 +17,13 @@ import RoomTypeIcon from '../../containers/RoomTypeIcon';
import I18n from '../../i18n';
import { CustomHeaderButtons, CloseModalButton } from '../../containers/HeaderButton';
import StatusBar from '../../containers/StatusBar';
-import log from '../../utils/log';
+import log, { logEvent, events } from '../../utils/log';
import { themes } from '../../constants/colors';
import { withTheme } from '../../theme';
import { getUserSelector } from '../../selectors/login';
import Markdown from '../../containers/markdown';
+import { LISTENER } from '../../containers/Toast';
+import EventEmitter from '../../utils/events';
import Livechat from './Livechat';
import Channel from './Channel';
@@ -59,7 +61,8 @@ class RoomInfoView extends React.Component {
baseUrl: PropTypes.string,
rooms: PropTypes.array,
theme: PropTypes.string,
- isMasterDetail: PropTypes.bool
+ isMasterDetail: PropTypes.bool,
+ jitsiEnabled: PropTypes.bool
}
constructor(props) {
@@ -114,7 +117,11 @@ class RoomInfoView extends React.Component {
- navigation.navigate(t === 'l' ? 'LivechatEditView' : 'RoomInfoEditView', { rid, room, roomUser })}
+ onPress={() => {
+ const isLivechat = t === 'l';
+ logEvent(events[`RI_GO_${ isLivechat ? 'LIVECHAT' : 'RI' }_EDIT`]);
+ navigation.navigate(isLivechat ? 'LivechatEditView' : 'RoomInfoEditView', { rid, room, roomUser });
+ }}
testID='room-info-view-edit-button'
/>
@@ -167,11 +174,11 @@ class RoomInfoView extends React.Component {
}
loadUser = async() => {
- const { room: roomState, roomUser } = this.state;
+ const { room, roomUser } = this.state;
if (_.isEmpty(roomUser)) {
try {
- const roomUserId = RocketChat.getUidDirectMessage(roomState);
+ const roomUserId = RocketChat.getUidDirectMessage(room);
const result = await RocketChat.getUserInfo(roomUserId);
if (result.success) {
const { user } = result;
@@ -183,9 +190,7 @@ class RoomInfoView extends React.Component {
}));
}
- const room = await this.getDirect(user.username);
-
- this.setState({ roomUser: user, room: { ...roomState, rid: room.rid } });
+ this.setState({ roomUser: user });
}
} catch {
// do nothing
@@ -194,6 +199,7 @@ class RoomInfoView extends React.Component {
}
loadRoom = async() => {
+ const { room: roomState } = this.state;
const { route } = this.props;
let room = route.params?.room;
if (room && room.observe) {
@@ -207,7 +213,7 @@ class RoomInfoView extends React.Component {
const result = await RocketChat.getRoomInfo(this.rid);
if (result.success) {
({ room } = result);
- this.setState({ room });
+ this.setState({ room: { ...roomState, ...room } });
}
} catch (e) {
log(e);
@@ -220,18 +226,31 @@ class RoomInfoView extends React.Component {
}
}
- getDirect = async(username) => {
+ createDirect = () => new Promise(async(resolve, reject) => {
+ const { route } = this.props;
+
+ // We don't need to create a direct
+ const member = route.params?.member;
+ if (!_.isEmpty(member)) {
+ return resolve();
+ }
+
+ // TODO: Check if some direct with the user already exists on database
try {
+ const { roomUser: { username } } = this.state;
const result = await RocketChat.createDirectMessage(username);
if (result.success) {
- return result.room;
+ const { room: { rid } } = result;
+ return this.setState(({ room }) => ({ room: { ...room, rid } }), resolve);
}
} catch {
// do nothing
}
- }
+ reject();
+ })
goRoom = () => {
+ logEvent(events.RI_GO_ROOM_USER);
const { roomUser, room } = this.state;
const { name, username } = roomUser;
const { rooms, navigation, isMasterDetail } = this.props;
@@ -287,9 +306,19 @@ class RoomInfoView extends React.Component {
renderButton = (onPress, iconName, text) => {
const { theme } = this.props;
+
+ const onActionPress = async() => {
+ try {
+ await this.createDirect();
+ onPress();
+ } catch {
+ EventEmitter.emit(LISTENER, { message: I18n.t('error-action-not-allowed', { action: I18n.t('Create_Direct_Messages') }) });
+ }
+ };
+
return (
(
-
- {this.renderButton(this.goRoom, 'message', I18n.t('Message'))}
- {this.renderButton(this.videoCall, 'video-1', I18n.t('Video_call'))}
-
- )
+ renderButtons = () => {
+ const { jitsiEnabled } = this.props;
+ return (
+
+ {this.renderButton(this.goRoom, 'message', I18n.t('Message'))}
+ {jitsiEnabled ? this.renderButton(this.videoCall, 'camera', I18n.t('Video_call')) : null}
+
+ );
+ }
renderContent = () => {
const { room, roomUser } = this.state;
@@ -348,7 +380,8 @@ const mapStateToProps = state => ({
baseUrl: state.server.server,
user: getUserSelector(state),
rooms: state.room.rooms,
- isMasterDetail: state.app.isMasterDetail
+ isMasterDetail: state.app.isMasterDetail,
+ jitsiEnabled: state.settings.Jitsi_Enabled || false
});
export default connect(mapStateToProps)(withTheme(RoomInfoView));
diff --git a/app/views/RoomMembersView/index.js b/app/views/RoomMembersView/index.js
index 8134e9183..cb6c7b7d4 100644
--- a/app/views/RoomMembersView/index.js
+++ b/app/views/RoomMembersView/index.js
@@ -146,7 +146,7 @@ class RoomMembersView extends React.Component {
showActionSheet({
options: [{
- icon: userIsMuted ? 'volume' : 'volume-off',
+ icon: userIsMuted ? 'audio' : 'audio-disabled',
title: I18n.t(userIsMuted ? 'Unmute' : 'Mute'),
onPress: () => {
showConfirmationAlert({
diff --git a/app/views/RoomView/Banner.js b/app/views/RoomView/Banner.js
index af6cd3002..5ee5bb9a2 100644
--- a/app/views/RoomView/Banner.js
+++ b/app/views/RoomView/Banner.js
@@ -35,7 +35,7 @@ const Banner = React.memo(({
diff --git a/app/views/RoomView/Header/Icon.js b/app/views/RoomView/Header/Icon.js
index 7de286c24..7eaa02ad0 100644
--- a/app/views/RoomView/Header/Icon.js
+++ b/app/views/RoomView/Header/Icon.js
@@ -36,17 +36,17 @@ const Icon = React.memo(({
let icon;
if (type === 'discussion') {
- icon = 'chat';
+ icon = 'discussions';
} else if (type === 'thread') {
icon = 'threads';
} else if (type === 'c') {
- icon = 'hash';
+ icon = 'channel-public';
} else if (type === 'l') {
- icon = 'livechat';
+ icon = 'omnichannel';
} else if (type === 'd') {
icon = 'team';
} else {
- icon = 'lock';
+ icon = 'channel-private';
}
return (
{
+ logEvent(events.ROOM_GO_THREADS);
const {
rid, t, navigation, isMasterDetail
} = this.props;
@@ -69,6 +71,7 @@ class RightButtonsContainer extends React.PureComponent {
}
goSearchView = () => {
+ logEvent(events.ROOM_GO_SEARCH);
const {
rid, navigation, isMasterDetail
} = this.props;
@@ -80,6 +83,7 @@ class RightButtonsContainer extends React.PureComponent {
}
toggleFollowThread = () => {
+ logEvent(events.ROOM_TOGGLE_FOLLOW_THREADS);
const { isFollowingThread } = this.state;
const { toggleFollowThread } = this.props;
if (toggleFollowThread) {
@@ -98,7 +102,7 @@ class RightButtonsContainer extends React.PureComponent {
@@ -117,7 +121,7 @@ class RightButtonsContainer extends React.PureComponent {
) : null}
diff --git a/app/views/RoomView/List.js b/app/views/RoomView/List.js
index d0dc7c88d..209ec18bb 100644
--- a/app/views/RoomView/List.js
+++ b/app/views/RoomView/List.js
@@ -1,7 +1,6 @@
import React from 'react';
import { FlatList, RefreshControl } from 'react-native';
import PropTypes from 'prop-types';
-import orderBy from 'lodash/orderBy';
import { Q } from '@nozbe/watermelondb';
import moment from 'moment';
import isEqual from 'lodash/isEqual';
@@ -15,9 +14,10 @@ import EmptyRoom from './EmptyRoom';
import { isIOS } from '../../utils/deviceInfo';
import { animateNextTransition } from '../../utils/layoutAnimation';
import ActivityIndicator from '../../containers/ActivityIndicator';
-import debounce from '../../utils/debounce';
import { themes } from '../../constants/colors';
+const QUERY_SIZE = 50;
+
class List extends React.Component {
static propTypes = {
onEndReached: PropTypes.func,
@@ -47,7 +47,8 @@ class List extends React.Component {
super(props);
console.time(`${ this.constructor.name } init`);
console.time(`${ this.constructor.name } mount`);
-
+ this.count = 0;
+ this.needsFetch = false;
this.mounted = false;
this.state = {
loading: true,
@@ -56,7 +57,7 @@ class List extends React.Component {
refreshing: false,
animated: false
};
- this.init();
+ this.query();
this.unsubscribeFocus = props.navigation.addListener('focus', () => {
if (this.mounted) {
this.setState({ animated: true });
@@ -72,72 +73,6 @@ class List extends React.Component {
console.timeEnd(`${ this.constructor.name } mount`);
}
- // eslint-disable-next-line react/sort-comp
- async init() {
- const { rid, tmid } = this.props;
- const db = database.active;
-
- // handle servers with version < 3.0.0
- let { hideSystemMessages = [] } = this.props;
- if (!Array.isArray(hideSystemMessages)) {
- hideSystemMessages = [];
- }
-
- if (tmid) {
- try {
- this.thread = await db.collections
- .get('threads')
- .find(tmid);
- } catch (e) {
- console.log(e);
- }
- this.messagesObservable = db.collections
- .get('thread_messages')
- .query(Q.where('rid', tmid), Q.or(Q.where('t', Q.notIn(hideSystemMessages)), Q.where('t', Q.eq(null))))
- .observe();
- } else if (rid) {
- this.messagesObservable = db.collections
- .get('messages')
- .query(Q.where('rid', rid), Q.or(Q.where('t', Q.notIn(hideSystemMessages)), Q.where('t', Q.eq(null))))
- .observe();
- }
-
- if (rid) {
- this.unsubscribeMessages();
- this.messagesSubscription = this.messagesObservable
- .subscribe((data) => {
- if (tmid && this.thread) {
- data = [this.thread, ...data];
- }
- const messages = orderBy(data, ['ts'], ['desc']);
- if (this.mounted) {
- this.setState({ messages }, () => this.update());
- } else {
- this.state.messages = messages;
- }
- this.readThreads();
- });
- }
- }
-
- // eslint-disable-next-line react/sort-comp
- reload = () => {
- this.unsubscribeMessages();
- this.init();
- }
-
- readThreads = async() => {
- const { tmid } = this.props;
-
- if (tmid) {
- try {
- await RocketChat.readThreads(tmid);
- } catch {
- // Do nothing
- }
- }
- }
-
shouldComponentUpdate(nextProps, nextState) {
const { loading, end, refreshing } = this.state;
const { hideSystemMessages, theme } = this.props;
@@ -177,7 +112,7 @@ class List extends React.Component {
console.countReset(`${ this.constructor.name }.render calls`);
}
- onEndReached = debounce(async() => {
+ fetchData = async() => {
const {
loading, end, messages, latest = messages[messages.length - 1]?.ts
} = this.state;
@@ -196,12 +131,99 @@ class List extends React.Component {
result = await RocketChat.loadMessagesForRoom({ rid, t, latest });
}
- this.setState({ end: result.length < 50, loading: false, latest: result[result.length - 1]?.ts }, () => this.loadMoreMessages(result));
+ this.setState({ end: result.length < QUERY_SIZE, loading: false, latest: result[result.length - 1]?.ts }, () => this.loadMoreMessages(result));
} catch (e) {
this.setState({ loading: false });
log(e);
}
- }, 300)
+ }
+
+ query = async() => {
+ this.count += QUERY_SIZE;
+ const { rid, tmid } = this.props;
+ const db = database.active;
+
+ // handle servers with version < 3.0.0
+ let { hideSystemMessages = [] } = this.props;
+ if (!Array.isArray(hideSystemMessages)) {
+ hideSystemMessages = [];
+ }
+
+ if (tmid) {
+ try {
+ this.thread = await db.collections
+ .get('threads')
+ .find(tmid);
+ } catch (e) {
+ console.log(e);
+ }
+ this.messagesObservable = db.collections
+ .get('thread_messages')
+ .query(
+ Q.where('rid', tmid),
+ Q.experimentalSortBy('ts', Q.desc),
+ Q.experimentalSkip(0),
+ Q.experimentalTake(this.count)
+ )
+ .observe();
+ } else if (rid) {
+ this.messagesObservable = db.collections
+ .get('messages')
+ .query(
+ Q.where('rid', rid),
+ Q.experimentalSortBy('ts', Q.desc),
+ Q.experimentalSkip(0),
+ Q.experimentalTake(this.count)
+ )
+ .observe();
+ }
+
+ if (rid) {
+ this.unsubscribeMessages();
+ this.messagesSubscription = this.messagesObservable
+ .subscribe((messages) => {
+ if (messages.length <= this.count) {
+ this.needsFetch = true;
+ }
+ if (tmid && this.thread) {
+ messages = [...messages, this.thread];
+ }
+ messages = messages.filter(m => !m.t || !hideSystemMessages?.includes(m.t));
+
+ if (this.mounted) {
+ this.setState({ messages }, () => this.update());
+ } else {
+ this.state.messages = messages;
+ }
+ this.readThreads();
+ });
+ }
+ }
+
+ reload = () => {
+ this.count = 0;
+ this.query();
+ }
+
+ readThreads = async() => {
+ const { tmid } = this.props;
+
+ if (tmid) {
+ try {
+ await RocketChat.readThreads(tmid);
+ } catch {
+ // Do nothing
+ }
+ }
+ }
+
+ onEndReached = async() => {
+ if (this.needsFetch) {
+ this.needsFetch = false;
+ await this.fetchData();
+ }
+ this.query();
+ }
loadMoreMessages = (result) => {
const { end } = this.state;
@@ -305,7 +327,7 @@ class List extends React.Component {
removeClippedSubviews={isIOS}
initialNumToRender={7}
onEndReached={this.onEndReached}
- onEndReachedThreshold={5}
+ onEndReachedThreshold={0.5}
maxToRenderPerBatch={5}
windowSize={10}
ListFooterComponent={this.renderFooter}
diff --git a/app/views/RoomView/UploadProgress.js b/app/views/RoomView/UploadProgress.js
index d4d8f2a51..ab17efc8b 100644
--- a/app/views/RoomView/UploadProgress.js
+++ b/app/views/RoomView/UploadProgress.js
@@ -172,11 +172,11 @@ class UploadProgress extends Component {
return (
[
-
+
{I18n.t('Uploading')} {item.name}
- this.cancelUpload(item)} />
+ this.cancelUpload(item)} />
,
]
@@ -191,7 +191,7 @@ class UploadProgress extends Component {
{I18n.t('Try_again')}
- this.deleteUpload(item)} />
+ this.deleteUpload(item)} />
);
}
diff --git a/app/views/RoomView/index.js b/app/views/RoomView/index.js
index 0b6afd18f..00df625f1 100644
--- a/app/views/RoomView/index.js
+++ b/app/views/RoomView/index.js
@@ -24,7 +24,7 @@ import MessageBox from '../../containers/MessageBox';
import ReactionPicker from './ReactionPicker';
import UploadProgress from './UploadProgress';
import styles from './styles';
-import log from '../../utils/log';
+import log, { logEvent, events } from '../../utils/log';
import EventEmitter from '../../utils/events';
import I18n from '../../i18n';
import RoomHeaderView, { RightButtons, LeftButtons } from './Header';
@@ -206,12 +206,10 @@ class RoomView extends React.Component {
const { appState, insets } = this.props;
if (appState === 'foreground' && appState !== prevProps.appState && this.rid) {
- this.onForegroundInteraction = InteractionManager.runAfterInteractions(() => {
- // Fire List.init() just to keep observables working
- if (this.list && this.list.current) {
- this.list.current.init();
- }
- });
+ // Fire List.query() just to keep observables working
+ if (this.list && this.list.current) {
+ this.list.current?.query?.();
+ }
}
// If it's not direct message
if (this.t !== 'd') {
@@ -267,9 +265,6 @@ class RoomView extends React.Component {
if (this.didMountInteraction && this.didMountInteraction.cancel) {
this.didMountInteraction.cancel();
}
- if (this.onForegroundInteraction && this.onForegroundInteraction.cancel) {
- this.onForegroundInteraction.cancel();
- }
if (this.willBlurListener && this.willBlurListener.remove) {
this.willBlurListener.remove();
}
@@ -287,6 +282,11 @@ class RoomView extends React.Component {
console.countReset(`${ this.constructor.name }.render calls`);
}
+ get isOmnichannel() {
+ const { room } = this.state;
+ return room.t === 'l';
+ }
+
setHeader = () => {
const { room, unreadsCount, roomUserId: stateRoomUserId } = this.state;
const {
@@ -357,6 +357,7 @@ class RoomView extends React.Component {
}
goRoomActionsView = (screen) => {
+ logEvent(events.ROOM_GO_RA);
const { room, member } = this.state;
const { navigation, isMasterDetail } = this.props;
if (isMasterDetail) {
@@ -649,6 +650,7 @@ class RoomView extends React.Component {
}
sendMessage = (message, tmid) => {
+ logEvent(events.ROOM_SEND_MESSAGE);
const { user } = this.props;
RocketChat.sendMessage(this.rid, message, this.tmid || tmid, user).then(() => {
if (this.list && this.list.current) {
@@ -682,8 +684,15 @@ class RoomView extends React.Component {
setLastOpen = lastOpen => this.setState({ lastOpen });
joinRoom = async() => {
+ logEvent(events.ROOM_JOIN);
try {
- await RocketChat.joinRoom(this.rid, this.t);
+ const { room } = this.state;
+
+ if (this.isOmnichannel) {
+ await RocketChat.takeInquiry(room._id);
+ } else {
+ await RocketChat.joinRoom(this.rid, this.t);
+ }
this.internalSetState({
joined: true
});
@@ -742,6 +751,7 @@ class RoomView extends React.Component {
navToRoomInfo = (navParam) => {
const { navigation, user, isMasterDetail } = this.props;
+ logEvent(events[`ROOM_GO_${ navParam.t === 'd' ? 'USER' : 'ROOM' }_INFO`]);
if (navParam.rid === user.id) {
return;
}
@@ -900,7 +910,7 @@ class RoomView extends React.Component {
style={[styles.joinRoomButton, { backgroundColor: themes[theme].actionTintColor }]}
theme={theme}
>
- {I18n.t('Join')}
+ {I18n.t(this.isOmnichannel ? 'Take_it' : 'Join')}
);
diff --git a/app/views/RoomsListView/Header/Header.js b/app/views/RoomsListView/Header/Header.js
index 839048bc0..fb5d7eb9e 100644
--- a/app/views/RoomsListView/Header/Header.js
+++ b/app/views/RoomsListView/Header/Header.js
@@ -41,7 +41,7 @@ const Header = React.memo(({
const { isLandscape } = useOrientation();
const scale = isIOS && isLandscape && !isTablet ? 0.8 : 1;
const titleFontSize = 16 * scale;
- const subTitleFontSize = 12 * scale;
+ const subTitleFontSize = 14 * scale;
if (showSearchHeader) {
return (
@@ -78,11 +78,11 @@ const Header = React.memo(({
- {subtitle ? {subtitle} : null}
+ {subtitle ? {subtitle} : null}
);
diff --git a/app/views/RoomsListView/Header/index.js b/app/views/RoomsListView/Header/index.js
index 12a57dc00..97244fd5b 100644
--- a/app/views/RoomsListView/Header/index.js
+++ b/app/views/RoomsListView/Header/index.js
@@ -10,6 +10,7 @@ import { withTheme } from '../../../theme';
import EventEmitter from '../../../utils/events';
import { KEY_COMMAND, handleCommandOpenServerDropdown } from '../../../commands';
import { isTablet } from '../../../utils/deviceInfo';
+import { logEvent, events } from '../../../utils/log';
class RoomsListHeaderView extends PureComponent {
static propTypes = {
@@ -53,6 +54,7 @@ class RoomsListHeaderView extends PureComponent {
}
onPress = () => {
+ logEvent(events.RL_TOGGLE_SERVER_DROPDOWN);
const {
showServerDropdown, showSortDropdown, close, open, closeSort
} = this.props;
diff --git a/app/views/RoomsListView/ListHeader/Queue.js b/app/views/RoomsListView/ListHeader/Queue.js
new file mode 100644
index 000000000..0a85d657a
--- /dev/null
+++ b/app/views/RoomsListView/ListHeader/Queue.js
@@ -0,0 +1,49 @@
+import React from 'react';
+import { View, Text, StyleSheet } from 'react-native';
+import PropTypes from 'prop-types';
+
+import Touch from '../../../utils/touch';
+import I18n from '../../../i18n';
+import styles from '../styles';
+import { themes } from '../../../constants/colors';
+import { withTheme } from '../../../theme';
+import UnreadBadge from '../../../presentation/UnreadBadge';
+
+const Queue = React.memo(({
+ searching, goQueue, queueSize, inquiryEnabled, theme
+}) => {
+ if (searching > 0 || !inquiryEnabled) {
+ return null;
+ }
+ return (
+
+
+ {I18n.t('Queued_chats')}
+
+
+
+ );
+});
+
+Queue.propTypes = {
+ searching: PropTypes.bool,
+ goQueue: PropTypes.func,
+ queueSize: PropTypes.number,
+ inquiryEnabled: PropTypes.bool,
+ theme: PropTypes.string
+};
+
+export default withTheme(Queue);
diff --git a/app/views/RoomsListView/ListHeader/index.js b/app/views/RoomsListView/ListHeader/index.js
index dec38b506..5df248787 100644
--- a/app/views/RoomsListView/ListHeader/index.js
+++ b/app/views/RoomsListView/ListHeader/index.js
@@ -1,6 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
+import Queue from './Queue';
import Directory from './Directory';
import Sort from './Sort';
@@ -8,11 +9,15 @@ const ListHeader = React.memo(({
searching,
sortBy,
toggleSort,
- goDirectory
+ goDirectory,
+ goQueue,
+ queueSize,
+ inquiryEnabled
}) => (
<>
+
>
));
@@ -20,7 +25,10 @@ ListHeader.propTypes = {
searching: PropTypes.bool,
sortBy: PropTypes.string,
toggleSort: PropTypes.func,
- goDirectory: PropTypes.func
+ goDirectory: PropTypes.func,
+ goQueue: PropTypes.func,
+ queueSize: PropTypes.number,
+ inquiryEnabled: PropTypes.bool
};
export default ListHeader;
diff --git a/app/views/RoomsListView/ServerDropdown.js b/app/views/RoomsListView/ServerDropdown.js
index be28fdbf7..afeb15eea 100644
--- a/app/views/RoomsListView/ServerDropdown.js
+++ b/app/views/RoomsListView/ServerDropdown.js
@@ -1,6 +1,6 @@
import React, { Component } from 'react';
import {
- View, Text, Animated, Easing, TouchableWithoutFeedback, TouchableOpacity, FlatList, Image
+ View, Text, Animated, Easing, TouchableWithoutFeedback, TouchableOpacity, FlatList, Image, Pressable
} from 'react-native';
import PropTypes from 'prop-types';
import { connect, batch } from 'react-redux';
@@ -12,7 +12,6 @@ import { toggleServerDropdown as toggleServerDropdownAction } from '../../action
import { selectServerRequest as selectServerRequestAction, serverInitAdd as serverInitAddAction } from '../../actions/server';
import { appStart as appStartAction, ROOT_NEW_SERVER } from '../../actions/app';
import styles from './styles';
-import Touch from '../../utils/touch';
import RocketChat from '../../lib/rocketchat';
import I18n from '../../i18n';
import EventEmitter from '../../utils/events';
@@ -21,10 +20,10 @@ import database from '../../lib/database';
import { themes } from '../../constants/colors';
import { withTheme } from '../../theme';
import { KEY_COMMAND, handleCommandSelectServer } from '../../commands';
-import { isTablet } from '../../utils/deviceInfo';
+import { isTablet, isIOS } from '../../utils/deviceInfo';
import { localAuthenticate } from '../../utils/localAuthentication';
import { showConfirmationAlert } from '../../utils/info';
-import LongPress from '../../utils/longPress';
+import { logEvent, events } from '../../utils/log';
import { headerHeight } from '../../containers/Header';
import { goRoom } from '../../utils/goRoom';
@@ -136,6 +135,7 @@ class ServerDropdown extends Component {
}
addServer = () => {
+ logEvent(events.RL_ADD_SERVER);
const { server } = this.props;
this.close();
setTimeout(() => {
@@ -149,6 +149,7 @@ class ServerDropdown extends Component {
} = this.props;
this.close();
if (currentServer !== server) {
+ logEvent(events.RL_CHANGE_SERVER);
const userId = await RNUserDefaults.get(`${ RocketChat.TOKEN_KEY }-${ server }`);
if (isMasterDetail) {
goRoom({ item: {}, isMasterDetail });
@@ -201,37 +202,43 @@ class ServerDropdown extends Component {
const { server, theme } = this.props;
return (
- (item.id === server || this.remove(item.id))}>
- this.select(item.id)}
- testID={`rooms-list-header-server-${ item.id }`}
- theme={theme}
- >
-
- {item.iconURL
- ? (
- console.warn('error loading serverIcon')}
- />
- )
- : (
-
- )
- }
-
- {item.name || item.id}
- {item.id}
-
- {item.id === server ? : null}
+ this.select(item.id)}
+ onLongPress={() => (item.id === server || this.remove(item.id))}
+ testID={`rooms-list-header-server-${ item.id }`}
+ android_ripple={{
+ color: themes[theme].bannerBackground
+ }}
+ style={({ pressed }) => ({
+ backgroundColor: isIOS && pressed
+ ? themes[theme].bannerBackground
+ : 'transparent'
+ })}
+ >
+
+ {item.iconURL
+ ? (
+ console.warn('error loading serverIcon')}
+ />
+ )
+ : (
+
+ )
+ }
+
+ {item.name || item.id}
+ {item.id}
-
-
+ {item.id === server ? : null}
+
+
);
}
diff --git a/app/views/RoomsListView/SortDropdown/index.js b/app/views/RoomsListView/SortDropdown/index.js
index b0c398b85..f50c939d7 100644
--- a/app/views/RoomsListView/SortDropdown/index.js
+++ b/app/views/RoomsListView/SortDropdown/index.js
@@ -10,7 +10,7 @@ import styles from '../styles';
import Touch from '../../../utils/touch';
import RocketChat from '../../../lib/rocketchat';
import { setPreference } from '../../../actions/sortPreferences';
-import log from '../../../utils/log';
+import log, { logEvent, events } from '../../../utils/log';
import I18n from '../../../i18n';
import { CustomIcon } from '../../../lib/Icons';
import { withTheme } from '../../../theme';
@@ -65,31 +65,37 @@ class Sort extends PureComponent {
setSortPreference(param);
RocketChat.saveSortPreference(param);
} catch (e) {
+ logEvent(events.RL_SORT_CHANNELS_F);
log(e);
}
}
sortByName = () => {
+ logEvent(events.RL_SORT_CHANNELS_BY_NAME);
this.setSortPreference({ sortBy: 'alphabetical' });
this.close();
}
sortByActivity = () => {
+ logEvent(events.RL_SORT_CHANNELS_BY_ACTIVITY);
this.setSortPreference({ sortBy: 'activity' });
this.close();
}
toggleGroupByType = () => {
+ logEvent(events.RL_GROUP_CHANNELS_BY_TYPE);
const { groupByType } = this.props;
this.setSortPreference({ groupByType: !groupByType });
}
toggleGroupByFavorites = () => {
+ logEvent(events.RL_GROUP_CHANNELS_BY_FAVORITE);
const { showFavorites } = this.props;
this.setSortPreference({ showFavorites: !showFavorites });
}
toggleUnread = () => {
+ logEvent(events.RL_GROUP_CHANNELS_BY_UNREAD);
const { showUnread } = this.props;
this.setSortPreference({ showUnread: !showUnread });
}
@@ -190,7 +196,7 @@ class Sort extends PureComponent {
(s.unread > 0 || s.alert) && !s.hideUnreadStatus;
const filterIsFavorite = s => s.f;
@@ -89,7 +92,9 @@ const shouldUpdateProps = [
'appState',
'theme',
'isMasterDetail',
- 'refreshing'
+ 'refreshing',
+ 'queueSize',
+ 'inquiryEnabled'
];
const getItemLayout = (data, index) => ({
length: ROW_HEIGHT,
@@ -130,7 +135,9 @@ class RoomsListView extends React.Component {
isMasterDetail: PropTypes.bool,
rooms: PropTypes.array,
width: PropTypes.number,
- insets: PropTypes.object
+ insets: PropTypes.object,
+ queueSize: PropTypes.number,
+ inquiryEnabled: PropTypes.bool
};
constructor(props) {
@@ -140,11 +147,12 @@ class RoomsListView extends React.Component {
this.gotSubscriptions = false;
this.animated = false;
+ this.count = 0;
this.state = {
searching: false,
search: [],
loading: true,
- allChats: [],
+ chatsOrder: [],
chats: [],
item: {}
};
@@ -211,7 +219,7 @@ class RoomsListView extends React.Component {
}
shouldComponentUpdate(nextProps, nextState) {
- const { allChats, searching, item } = this.state;
+ const { chatsOrder, searching, item } = this.state;
// eslint-disable-next-line react/destructuring-assignment
const propsUpdated = shouldUpdateProps.some(key => nextProps[key] !== this.props[key]);
if (propsUpdated) {
@@ -219,7 +227,7 @@ class RoomsListView extends React.Component {
}
// Compare changes only once
- const chatsNotEqual = !isEqual(nextState.allChats, allChats);
+ const chatsNotEqual = !isEqual(nextState.chatsOrder, chatsOrder);
// If they aren't equal, set to update if focused
if (chatsNotEqual) {
@@ -290,7 +298,7 @@ class RoomsListView extends React.Component {
&& prevProps.showUnread === showUnread
)
) {
- this.getSubscriptions(true);
+ this.getSubscriptions();
} else if (
appState === 'foreground'
&& appState !== prevProps.appState
@@ -309,9 +317,7 @@ class RoomsListView extends React.Component {
}
componentWillUnmount() {
- if (this.querySubscription && this.querySubscription.unsubscribe) {
- this.querySubscription.unsubscribe();
- }
+ this.unsubscribeQuery();
if (this.unsubscribeFocus) {
this.unsubscribeFocus();
}
@@ -334,7 +340,7 @@ class RoomsListView extends React.Component {
@@ -356,15 +362,13 @@ class RoomsListView extends React.Component {
- navigation.navigate('ModalStackNavigator', { screen: 'NewMessageView' })
- : () => navigation.navigate('NewMessageStackNavigator')}
+ iconName='create'
+ onPress={this.goToNewMessage}
testID='rooms-list-view-create-channel'
/>
@@ -396,17 +400,8 @@ class RoomsListView extends React.Component {
return allData;
}
- getSubscriptions = async(force = false) => {
- if (this.gotSubscriptions && !force) {
- return;
- }
- this.gotSubscriptions = true;
-
- if (this.querySubscription && this.querySubscription.unsubscribe) {
- this.querySubscription.unsubscribe();
- }
-
- this.setState({ loading: true });
+ getSubscriptions = async() => {
+ this.unsubscribeQuery();
const {
sortBy,
@@ -416,41 +411,49 @@ class RoomsListView extends React.Component {
} = this.props;
const db = database.active;
- const observable = await db.collections
- .get('subscriptions')
- .query(
- Q.where('archived', false),
- Q.where('open', true)
- )
- .observeWithColumns(['room_updated_at', 'unread', 'alert', 'user_mentions', 'f', 't']);
+ let observable;
+
+ const defaultWhereClause = [
+ Q.where('archived', false),
+ Q.where('open', true)
+ ];
+
+ if (sortBy === 'alphabetical') {
+ defaultWhereClause.push(Q.experimentalSortBy(`${ this.useRealName ? 'fname' : 'name' }`, Q.asc));
+ } else {
+ defaultWhereClause.push(Q.experimentalSortBy('room_updated_at', Q.desc));
+ }
+
+ // When we're grouping by something
+ if (this.isGrouping) {
+ observable = await db.collections
+ .get('subscriptions')
+ .query(...defaultWhereClause)
+ .observe();
+
+ // When we're NOT grouping
+ } else {
+ this.count += QUERY_SIZE;
+ observable = await db.collections
+ .get('subscriptions')
+ .query(
+ ...defaultWhereClause,
+ Q.experimentalSkip(0),
+ Q.experimentalTake(this.count)
+ )
+ .observe();
+ }
+
this.querySubscription = observable.subscribe((data) => {
let tempChats = [];
- let chats = [];
- if (sortBy === 'alphabetical') {
- chats = orderBy(data, [`${ this.useRealName ? 'fname' : 'name' }`], ['asc']);
- } else {
- chats = orderBy(data, ['roomUpdatedAt'], ['desc']);
- }
+ let chats = data;
- // it's better to map and test all subs altogether then testing them individually
- const allChats = data.map(item => ({
- alert: item.alert,
- unread: item.unread,
- userMentions: item.userMentions,
- isRead: this.getIsRead(item),
- favorite: item.f,
- lastMessage: item.lastMessage,
- name: this.getRoomTitle(item),
- _updatedAt: item.roomUpdatedAt,
- key: item._id,
- rid: item.rid,
- type: item.t,
- prid: item.prid,
- uids: item.uids,
- usernames: item.usernames,
- visitor: item.visitor
- }));
+ /**
+ * We trigger re-render only when chats order changes
+ * RoomItem handles its own re-render
+ */
+ const chatsOrder = data.map(item => item.rid);
// unread
if (showUnread) {
@@ -484,13 +487,20 @@ class RoomsListView extends React.Component {
this.internalSetState({
chats: tempChats,
- allChats,
+ chatsOrder,
loading: false
});
});
}
+ unsubscribeQuery = () => {
+ if (this.querySubscription && this.querySubscription.unsubscribe) {
+ this.querySubscription.unsubscribe();
+ }
+ }
+
initSearching = () => {
+ logEvent(events.RL_SEARCH);
const { openSearchHeader } = this.props;
this.internalSetState({ searching: true }, () => {
openSearchHeader();
@@ -548,10 +558,19 @@ class RoomsListView extends React.Component {
getRoomAvatar = item => RocketChat.getRoomAvatar(item)
+ isGroupChat = item => RocketChat.isGroupChat(item)
+
+ isRead = item => RocketChat.isRead(item)
+
getUserPresence = uid => RocketChat.getUserPresence(uid)
getUidDirectMessage = room => RocketChat.getUidDirectMessage(room);
+ get isGrouping() {
+ const { showUnread, showFavorites, groupByType } = this.props;
+ return showUnread || showFavorites || groupByType;
+ }
+
onPressItem = (item = {}) => {
const { navigation, isMasterDetail } = this.props;
if (!navigation.isFocused()) {
@@ -566,9 +585,10 @@ class RoomsListView extends React.Component {
if (this.scroll?.scrollToOffset) {
this.scroll.scrollToOffset({ offset: 0 });
}
- };
+ }
toggleSort = () => {
+ logEvent(events.RL_TOGGLE_SORT_DROPDOWN);
const { toggleSortDropdown } = this.props;
this.scrollToTop();
@@ -578,6 +598,7 @@ class RoomsListView extends React.Component {
};
toggleFav = async(rid, favorite) => {
+ logEvent(favorite ? events.RL_UNFAVORITE_CHANNEL : events.RL_FAVORITE_CHANNEL);
try {
const db = database.active;
const result = await RocketChat.toggleFavorite(rid, !favorite);
@@ -595,11 +616,13 @@ class RoomsListView extends React.Component {
});
}
} catch (e) {
+ logEvent(events.RL_TOGGLE_FAVORITE_FAIL);
log(e);
}
};
toggleRead = async(rid, isRead) => {
+ logEvent(isRead ? events.RL_UNREAD_CHANNEL : events.RL_READ_CHANNEL);
try {
const db = database.active;
const result = await RocketChat.toggleRead(isRead, rid);
@@ -617,11 +640,13 @@ class RoomsListView extends React.Component {
});
}
} catch (e) {
+ logEvent(events.RL_TOGGLE_READ_F);
log(e);
}
};
hideChannel = async(rid, type) => {
+ logEvent(events.RL_HIDE_CHANNEL);
try {
const db = database.active;
const result = await RocketChat.hideRoom(rid, type);
@@ -637,11 +662,13 @@ class RoomsListView extends React.Component {
});
}
} catch (e) {
+ logEvent(events.RL_HIDE_CHANNEL_F);
log(e);
}
};
goDirectory = () => {
+ logEvent(events.RL_GO_DIRECTORY);
const { navigation, isMasterDetail } = this.props;
if (isMasterDetail) {
navigation.navigate('ModalStackNavigator', { screen: 'DirectoryView' });
@@ -650,7 +677,22 @@ class RoomsListView extends React.Component {
}
};
+ goQueue = () => {
+ logEvent(events.RL_GO_QUEUE);
+ const { navigation, isMasterDetail, queueSize } = this.props;
+ // prevent navigation to empty list
+ if (!queueSize) {
+ return showErrorAlert(I18n.t('Queue_is_empty'), I18n.t('Oops'));
+ }
+ if (isMasterDetail) {
+ navigation.navigate('ModalStackNavigator', { screen: 'QueueListView' });
+ } else {
+ navigation.navigate('QueueListView');
+ }
+ };
+
goRoom = ({ item, isMasterDetail }) => {
+ logEvent(events.RL_GO_ROOM);
const { item: currentItem } = this.state;
const { rooms } = this.props;
if (currentItem?.rid === item.rid || rooms?.includes(item.rid)) {
@@ -710,6 +752,17 @@ class RoomsListView extends React.Component {
}
}
+ goToNewMessage = () => {
+ logEvent(events.RL_GO_NEW_MSG);
+ const { navigation, isMasterDetail } = this.props;
+
+ if (isMasterDetail) {
+ navigation.navigate('ModalStackNavigator', { screen: 'NewMessageView' });
+ } else {
+ navigation.navigate('NewMessageStackNavigator');
+ }
+ }
+
handleCommands = ({ event }) => {
const { navigation, server, isMasterDetail } = this.props;
const { input } = event;
@@ -743,17 +796,27 @@ class RoomsListView extends React.Component {
roomsRequest({ allData: true });
}
+ onEndReached = () => {
+ // Run only when we're not grouping by anything
+ if (!this.isGrouping) {
+ this.getSubscriptions();
+ }
+ }
+
getScrollRef = ref => (this.scroll = ref);
renderListHeader = () => {
const { searching } = this.state;
- const { sortBy } = this.props;
+ const { sortBy, queueSize, inquiryEnabled } = this.props;
return (
);
};
@@ -774,12 +837,6 @@ class RoomsListView extends React.Component {
);
}
- getIsRead = (item) => {
- let isUnread = item.archived !== true && item.open === true; // item is not archived and not opened
- isUnread = isUnread && (item.unread > 0 || item.alert === true); // either its unread count > 0 or its alert
- return !isUnread;
- };
-
renderItem = ({ item }) => {
if (item.separator) {
return this.renderSectionHeader(item.rid);
@@ -800,32 +857,19 @@ class RoomsListView extends React.Component {
width
} = this.props;
const id = this.getUidDirectMessage(item);
- const isGroupChat = RocketChat.isGroupChat(item);
return (
this.onPressItem(item)}
+ onPress={this.onPressItem}
testID={`rooms-list-view-item-${ item.name }`}
width={isMasterDetail ? MAX_SIDEBAR_WIDTH : width}
toggleFav={this.toggleFav}
@@ -833,7 +877,10 @@ class RoomsListView extends React.Component {
hideChannel={this.hideChannel}
useRealName={useRealName}
getUserPresence={this.getUserPresence}
- isGroupChat={isGroupChat}
+ getRoomTitle={this.getRoomTitle}
+ getRoomAvatar={this.getRoomAvatar}
+ getIsGroupChat={this.isGroupChat}
+ getIsRead={this.isRead}
visitor={item.visitor}
isFocused={currentItem?.rid === item.rid}
/>
@@ -880,6 +927,8 @@ class RoomsListView extends React.Component {
/>
)}
windowSize={9}
+ onEndReached={this.onEndReached}
+ onEndReachedThreshold={0.5}
/>
);
};
@@ -934,7 +983,9 @@ const mapStateToProps = state => ({
useRealName: state.settings.UI_Use_Real_Name,
appState: state.app.ready && state.app.foreground ? 'foreground' : 'background',
StoreLastMessage: state.settings.Store_Last_Message,
- rooms: state.room.rooms
+ rooms: state.room.rooms,
+ queueSize: getInquiryQueueSelector(state).length,
+ inquiryEnabled: state.inquiry.enabled
});
const mapDispatchToProps = dispatch => ({
diff --git a/app/views/ScreenLockConfigView.js b/app/views/ScreenLockConfigView.js
index f235f6caf..0dfb377f2 100644
--- a/app/views/ScreenLockConfigView.js
+++ b/app/views/ScreenLockConfigView.js
@@ -16,6 +16,7 @@ import { supportedBiometryLabel, changePasscode, checkHasPasscode } from '../uti
import { DisclosureImage } from '../containers/DisclosureIndicator';
import { DEFAULT_AUTO_LOCK } from '../constants/localAuthentication';
import SafeAreaView from '../containers/SafeAreaView';
+import { events, logEvent } from '../utils/log';
const styles = StyleSheet.create({
listPadding: {
@@ -29,9 +30,9 @@ const styles = StyleSheet.create({
const DEFAULT_BIOMETRY = false;
class ScreenLockConfigView extends React.Component {
- static navigationOptions = {
+ static navigationOptions = () => ({
title: I18n.t('Screen_lock')
- };
+ });
static propTypes = {
theme: PropTypes.string,
@@ -113,6 +114,7 @@ class ScreenLockConfigView extends React.Component {
}
save = async() => {
+ logEvent(events.SLC_SAVE_SCREEN_LOCK);
const { autoLock, autoLockTime, biometry } = this.state;
const serversDB = database.servers;
await serversDB.action(async() => {
@@ -125,10 +127,12 @@ class ScreenLockConfigView extends React.Component {
}
changePasscode = async({ force }) => {
+ logEvent(events.SLC_CHANGE_PASSCODE);
await changePasscode({ force });
}
toggleAutoLock = () => {
+ logEvent(events.SLC_TOGGLE_AUTOLOCK);
this.setState(({ autoLock }) => ({ autoLock: !autoLock, autoLockTime: DEFAULT_AUTO_LOCK }), async() => {
const { autoLock } = this.state;
if (autoLock) {
@@ -143,6 +147,7 @@ class ScreenLockConfigView extends React.Component {
}
toggleBiometry = () => {
+ logEvent(events.SLC_TOGGLE_BIOMETRY);
this.setState(({ biometry }) => ({ biometry: !biometry }), () => this.save());
}
@@ -152,6 +157,7 @@ class ScreenLockConfigView extends React.Component {
}
changeAutoLockTime = (autoLockTime) => {
+ logEvent(events.SLC_CHANGE_AUTOLOCK_TIME);
this.setState({ autoLockTime }, () => this.save());
}
diff --git a/app/views/SelectServerView.js b/app/views/SelectServerView.js
index 19131a3e8..46418d395 100644
--- a/app/views/SelectServerView.js
+++ b/app/views/SelectServerView.js
@@ -29,9 +29,9 @@ const styles = StyleSheet.create({
});
class SelectServerView extends React.Component {
- static navigationOptions = {
+ static navigationOptions = () => ({
title: I18n.t('Select_Server')
- }
+ })
static propTypes = {
server: PropTypes.string,
diff --git a/app/views/SelectedUsersView.js b/app/views/SelectedUsersView.js
index eb8c7bc8e..396728a86 100644
--- a/app/views/SelectedUsersView.js
+++ b/app/views/SelectedUsersView.js
@@ -11,7 +11,7 @@ import RocketChat from '../lib/rocketchat';
import UserItem from '../presentation/UserItem';
import Loading from '../containers/Loading';
import I18n from '../i18n';
-import log from '../utils/log';
+import log, { logEvent, events } from '../utils/log';
import SearchBox from '../containers/SearchBox';
import sharedStyles from './Styles';
import { Item, CustomHeaderButtons } from '../containers/HeaderButton';
@@ -183,9 +183,10 @@ class SelectedUsersView extends React.Component {
if (this.isGroupChat() && users.length === maxUsers) {
return showErrorAlert(I18n.t('Max_number_of_users_allowed_is_number', { maxUsers }), I18n.t('Oops'));
}
-
+ logEvent(events.SELECTED_USERS_ADD_USER);
addUser(user);
} else {
+ logEvent(events.SELECTED_USERS_REMOVE_USER);
removeUser(user);
}
}
diff --git a/app/views/SettingsView/index.js b/app/views/SettingsView/index.js
index 9cb3c8b05..ee362b772 100644
--- a/app/views/SettingsView/index.js
+++ b/app/views/SettingsView/index.js
@@ -5,6 +5,7 @@ import {
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import AsyncStorage from '@react-native-community/async-storage';
+import FastImage from '@rocket.chat/react-native-fast-image';
import { logout as logoutAction } from '../../actions/login';
import { selectServerRequest as selectServerRequestAction } from '../../actions/server';
@@ -25,7 +26,9 @@ import openLink from '../../utils/openLink';
import scrollPersistTaps from '../../utils/scrollPersistTaps';
import { showErrorAlert, showConfirmationAlert } from '../../utils/info';
import styles from './styles';
-import { loggerConfig, analytics } from '../../utils/log';
+import {
+ loggerConfig, analytics, logEvent, events
+} from '../../utils/log';
import { PLAY_MARKET_LINK, APP_STORE_LINK, LICENSE_LINK } from '../../constants/links';
import { withTheme } from '../../theme';
import SidebarView from '../SidebarView';
@@ -85,6 +88,7 @@ class SettingsView extends React.Component {
}
handleLogout = () => {
+ logEvent(events.SE_LOG_OUT);
showConfirmationAlert({
message: I18n.t('You_will_be_logged_out_of_this_application'),
callToAction: I18n.t('Logout'),
@@ -96,6 +100,7 @@ class SettingsView extends React.Component {
}
handleClearCache = () => {
+ logEvent(events.SE_CLEAR_LOCAL_SERVER_CACHE);
showConfirmationAlert({
message: I18n.t('This_will_clear_all_your_offline_data'),
callToAction: I18n.t('Clear'),
@@ -103,20 +108,22 @@ class SettingsView extends React.Component {
const {
server: { server }, appStart, selectServerRequest
} = this.props;
- await appStart({ root: ROOT_LOADING, text: I18n.t('Clear_cache_loading') });
+ appStart({ root: ROOT_LOADING, text: I18n.t('Clear_cache_loading') });
await RocketChat.clearCache({ server });
- await selectServerRequest(server, null, true);
+ await FastImage.clearMemoryCache();
+ await FastImage.clearDiskCache();
+ selectServerRequest(server, null, true);
}
});
}
toggleCrashReport = (value) => {
+ logEvent(events.SE_TOGGLE_CRASH_REPORT);
AsyncStorage.setItem(CRASH_REPORT_KEY, JSON.stringify(value));
const { toggleCrashReport } = this.props;
toggleCrashReport(value);
loggerConfig.autoNotify = value;
analytics().setAnalyticsCollectionEnabled(value);
-
if (value) {
loggerConfig.clearBeforeSendCallbacks();
} else {
@@ -133,11 +140,13 @@ class SettingsView extends React.Component {
}
navigateToScreen = (screen) => {
+ logEvent(events[`SE_GO_${ screen.replace('View', '').toUpperCase() }`]);
const { navigation } = this.props;
navigation.navigate(screen);
}
sendEmail = async() => {
+ logEvent(events.SE_CONTACT_US);
const subject = encodeURI('React Native App Support');
const email = encodeURI('support@rocket.chat');
const description = encodeURI(`
@@ -147,20 +156,24 @@ class SettingsView extends React.Component {
try {
await Linking.openURL(`mailto:${ email }?subject=${ subject }&body=${ description }`);
} catch (e) {
+ logEvent(events.SE_CONTACT_US_F);
showErrorAlert(I18n.t('error-email-send-failed', { message: 'support@rocket.chat' }));
}
}
shareApp = () => {
+ logEvent(events.SE_SHARE_THIS_APP);
Share.share({ message: isAndroid ? PLAY_MARKET_LINK : APP_STORE_LINK });
}
copyServerVersion = () => {
- const { server } = this.props;
- this.saveToClipboard(server.version);
+ const { server: { version } } = this.props;
+ logEvent(events.SE_COPY_SERVER_VERSION, { serverVersion: version });
+ this.saveToClipboard(version);
}
copyAppVersion = () => {
+ logEvent(events.SE_COPY_APP_VERSION, { appVersion: getReadableVersion });
this.saveToClipboard(getReadableVersion);
}
@@ -170,6 +183,7 @@ class SettingsView extends React.Component {
}
onPressLicense = () => {
+ logEvent(events.SE_READ_LICENSE);
const { theme } = this.props;
openLink(LICENSE_LINK, theme);
}
diff --git a/app/views/ShareListView/index.js b/app/views/ShareListView/index.js
index 7e81998cb..c40bd1843 100644
--- a/app/views/ShareListView/index.js
+++ b/app/views/ShareListView/index.js
@@ -7,7 +7,7 @@ import ShareExtension from 'rn-extensions-share';
import * as FileSystem from 'expo-file-system';
import { connect } from 'react-redux';
import * as mime from 'react-native-mime-types';
-import { isEqual, orderBy } from 'lodash';
+import isEqual from 'react-fast-compare';
import { Q } from '@nozbe/watermelondb';
import database from '../../lib/database';
@@ -32,7 +32,6 @@ const permission = {
message: I18n.t('Read_External_Permission_Message')
};
-const LIMIT = 50;
const getItemLayout = (data, index) => ({ length: ROW_HEIGHT, offset: ROW_HEIGHT * index, index });
const keyExtractor = item => item.rid;
@@ -47,7 +46,7 @@ class ShareListView extends React.Component {
constructor(props) {
super(props);
- this.data = [];
+ this.chats = [];
this.state = {
searching: false,
searchText: '',
@@ -155,7 +154,7 @@ class ShareListView extends React.Component {
headerLeft: () => (searching
? (
-
+
)
: (
@@ -186,22 +185,36 @@ class ShareListView extends React.Component {
this.setState(...args);
}
- getSubscriptions = async(server) => {
+ query = (text) => {
const db = database.active;
+ const defaultWhereClause = [
+ Q.where('archived', false),
+ Q.where('open', true),
+ Q.experimentalSkip(0),
+ Q.experimentalTake(50),
+ Q.experimentalSortBy('room_updated_at', Q.desc)
+ ];
+ if (text) {
+ return db.collections
+ .get('subscriptions')
+ .query(
+ ...defaultWhereClause,
+ Q.or(
+ Q.where('name', Q.like(`%${ Q.sanitizeLikeString(text) }%`)),
+ Q.where('fname', Q.like(`%${ Q.sanitizeLikeString(text) }%`))
+ )
+ ).fetch();
+ }
+ return db.collections.get('subscriptions').query(...defaultWhereClause).fetch();
+ }
+
+ getSubscriptions = async(server) => {
const serversDB = database.servers;
if (server) {
- this.data = await db.collections
- .get('subscriptions')
- .query(
- Q.where('archived', false),
- Q.where('open', true)
- ).fetch();
- this.data = orderBy(this.data, ['roomUpdatedAt'], ['desc']);
-
+ this.chats = await this.query();
const serversCollection = serversDB.collections.get('servers');
this.servers = await serversCollection.query().fetch();
- this.chats = this.data.slice(0, LIMIT);
let serverInfo = {};
try {
serverInfo = await serversCollection.find(server);
@@ -210,8 +223,8 @@ class ShareListView extends React.Component {
}
this.internalSetState({
- chats: this.chats ? this.chats.slice() : [],
- servers: this.servers ? this.servers.slice() : [],
+ chats: this.chats ?? [],
+ servers: this.servers ?? [],
loading: false,
serverInfo
});
@@ -253,10 +266,10 @@ class ShareListView extends React.Component {
});
}
- search = (text) => {
- const result = this.data.filter(item => item.name.includes(text)) || [];
+ search = async(text) => {
+ const result = await this.query(text);
this.internalSetState({
- searchResults: result.slice(0, LIMIT),
+ searchResults: result,
searchText: text
});
}
@@ -297,9 +310,26 @@ class ShareListView extends React.Component {
}
renderItem = ({ item }) => {
+ const { serverInfo } = this.state;
+ const { useRealName } = serverInfo;
const {
userId, token, server, theme
} = this.props;
+ let description;
+ switch (item.t) {
+ case 'c':
+ description = item.topic || item.description;
+ break;
+ case 'p':
+ description = item.topic || item.description;
+ break;
+ case 'd':
+ description = useRealName ? item.name : item.fname;
+ break;
+ default:
+ description = item.fname;
+ break;
+ }
return (
this.shareMessage(item)}
testID={`share-extension-item-${ item.name }`}
diff --git a/app/views/ShareView/Header.js b/app/views/ShareView/Header.js
index 7d0312b95..aa1f88c02 100644
--- a/app/views/ShareView/Header.js
+++ b/app/views/ShareView/Header.js
@@ -45,21 +45,21 @@ const Header = React.memo(({ room, thread, theme }) => {
}
let icon;
if (type === 'discussion') {
- icon = 'chat';
+ icon = 'discussions';
} else if (type === 'thread') {
icon = 'threads';
} else if (type === 'c') {
- icon = 'hash';
+ icon = 'channel-public';
} else if (type === 'l') {
- icon = 'livechat';
+ icon = 'omnichannel';
} else if (type === 'd') {
if (RocketChat.isGroupChat(room)) {
icon = 'team';
} else {
- icon = 'at';
+ icon = 'mention';
}
} else {
- icon = 'lock';
+ icon = 'channel-private';
}
const textColor = themes[theme].previewTintColor;
diff --git a/app/views/ShareView/Preview.js b/app/views/ShareView/Preview.js
index 2aaff22d8..4b3a9eb81 100644
--- a/app/views/ShareView/Preview.js
+++ b/app/views/ShareView/Preview.js
@@ -96,7 +96,7 @@ const Preview = React.memo(({
}
return (
{
return (
@@ -95,7 +95,7 @@ const ThumbContent = React.memo(({ item, theme, isShareExtension }) => {
<>
diff --git a/app/views/SidebarView/index.js b/app/views/SidebarView/index.js
index 2da42c460..6690b3b30 100644
--- a/app/views/SidebarView/index.js
+++ b/app/views/SidebarView/index.js
@@ -8,7 +8,7 @@ import { Q } from '@nozbe/watermelondb';
import Avatar from '../../containers/Avatar';
import Status from '../../containers/Status/Status';
-import log from '../../utils/log';
+import log, { logEvent, events } from '../../utils/log';
import I18n from '../../i18n';
import scrollPersistTaps from '../../utils/scrollPersistTaps';
import { CustomIcon } from '../../lib/Icons';
@@ -18,7 +18,6 @@ import { themes } from '../../constants/colors';
import database from '../../lib/database';
import { withTheme } from '../../theme';
import { getUserSelector } from '../../selectors/login';
-import Navigation from '../../lib/Navigation';
import SafeAreaView from '../../containers/SafeAreaView';
const Separator = React.memo(({ theme }) => );
@@ -135,6 +134,7 @@ class Sidebar extends Component {
}
sidebarNavigate = (route) => {
+ logEvent(events[`SIDEBAR_GO_${ route.replace('StackNavigator', '').replace('View', '').toUpperCase() }`]);
const { navigation } = this.props;
navigation.navigate(route);
}
@@ -164,8 +164,8 @@ class Sidebar extends Component {
}
- onPress={() => Navigation.navigate(routeName)}
+ left={}
+ onPress={() => this.sidebarNavigate(routeName)}
testID='sidebar-settings'
current={this.currentItemKey === routeName}
/>
@@ -193,7 +193,7 @@ class Sidebar extends Component {
/>
}
+ left={}
onPress={() => this.sidebarNavigate('SettingsStackNavigator')}
testID='sidebar-settings'
current={this.currentItemKey === 'SettingsStackNavigator'}
@@ -210,7 +210,7 @@ class Sidebar extends Component {
text={user.statusText || I18n.t('Edit_Status')}
left={}
right={}
- onPress={() => Navigation.navigate('StatusView')}
+ onPress={() => this.sidebarNavigate('StatusView')}
testID='sidebar-custom-status'
/>
);
diff --git a/app/views/StatusView.js b/app/views/StatusView.js
index 2c91fa294..4cc2fa80d 100644
--- a/app/views/StatusView.js
+++ b/app/views/StatusView.js
@@ -11,7 +11,7 @@ import TextInput from '../containers/TextInput';
import EventEmitter from '../utils/events';
import Loading from '../containers/Loading';
import RocketChat from '../lib/rocketchat';
-import log from '../utils/log';
+import log, { logEvent, events } from '../utils/log';
import { LISTENER } from '../containers/Toast';
import { themes } from '../constants/colors';
@@ -24,16 +24,16 @@ import SafeAreaView from '../containers/SafeAreaView';
const STATUS = [{
id: 'online',
- name: I18n.t('Online')
+ name: 'Online'
}, {
id: 'busy',
- name: I18n.t('Busy')
+ name: 'Busy'
}, {
id: 'away',
- name: I18n.t('Away')
+ name: 'Away'
}, {
id: 'offline',
- name: I18n.t('Invisible')
+ name: 'Invisible'
}];
const styles = StyleSheet.create({
@@ -92,6 +92,7 @@ class StatusView extends React.Component {
}
submit = async() => {
+ logEvent(events.STATUS_DONE);
const { statusText } = this.state;
const { user } = this.props;
if (statusText !== user.statusText) {
@@ -114,11 +115,14 @@ class StatusView extends React.Component {
try {
const result = await RocketChat.setUserStatus(user.status, statusText);
if (result.success) {
+ logEvent(events.STATUS_CUSTOM);
EventEmitter.emit(LISTENER, { message: I18n.t('Status_saved_successfully') });
} else {
+ logEvent(events.STATUS_CUSTOM_F);
EventEmitter.emit(LISTENER, { message: I18n.t('error-could-not-change-status') });
}
} catch {
+ logEvent(events.STATUS_CUSTOM_F);
EventEmitter.emit(LISTENER, { message: I18n.t('error-could-not-change-status') });
}
@@ -164,8 +168,9 @@ class StatusView extends React.Component {
const { id, name } = item;
return (
{
+ logEvent(events[`STATUS_${ item.id.toUpperCase() }`]);
if (user.status !== item.id) {
try {
const result = await RocketChat.setUserStatus(item.id, statusText);
@@ -173,6 +178,7 @@ class StatusView extends React.Component {
store.dispatch(setUser({ status: item.id }));
}
} catch (e) {
+ logEvent(events.SET_STATUS_FAIL);
log(e);
}
}
diff --git a/app/views/ThemeView.js b/app/views/ThemeView.js
index d8cd96902..e6e07d1f1 100644
--- a/app/views/ThemeView.js
+++ b/app/views/ThemeView.js
@@ -16,33 +16,34 @@ import { CustomIcon } from '../lib/Icons';
import { THEME_PREFERENCES_KEY } from '../lib/rocketchat';
import { supportSystemTheme } from '../utils/deviceInfo';
import SafeAreaView from '../containers/SafeAreaView';
+import { events, logEvent } from '../utils/log';
const THEME_GROUP = 'THEME_GROUP';
const DARK_GROUP = 'DARK_GROUP';
const SYSTEM_THEME = {
- label: I18n.t('Automatic'),
+ label: 'Automatic',
value: 'automatic',
group: THEME_GROUP
};
const THEMES = [
{
- label: I18n.t('Light'),
+ label: 'Light',
value: 'light',
group: THEME_GROUP
}, {
- label: I18n.t('Dark'),
+ label: 'Dark',
value: 'dark',
group: THEME_GROUP
}, {
- label: I18n.t('Dark'),
+ label: 'Dark',
value: 'dark',
separator: true,
- header: I18n.t('Dark_level'),
+ header: 'Dark_level',
group: DARK_GROUP
}, {
- label: I18n.t('Black'),
+ label: 'Black',
value: 'black',
group: DARK_GROUP
}
@@ -68,9 +69,9 @@ const styles = StyleSheet.create({
});
class ThemeView extends React.Component {
- static navigationOptions = {
+ static navigationOptions = () => ({
title: I18n.t('Theme')
- }
+ })
static propTypes = {
theme: PropTypes.string,
@@ -96,9 +97,11 @@ class ThemeView extends React.Component {
const { value, group } = item;
let changes = {};
if (group === THEME_GROUP && currentTheme !== value) {
+ logEvent(events.THEME_SET_THEME_GROUP, { theme_group: value });
changes = { currentTheme: value };
}
if (group === DARK_GROUP && darkLevel !== value) {
+ logEvent(events.THEME_SET_DARK_LEVEL, { dark_level: value });
changes = { darkLevel: value };
}
this.setTheme(changes);
@@ -129,7 +132,7 @@ class ThemeView extends React.Component {
<>
{item.separator || isFirst ? this.renderSectionHeader(item.header) : null}
this.onClick(item)}
testID={`theme-view-${ value }`}
right={this.isSelected(item) ? this.renderIcon : null}
@@ -139,12 +142,12 @@ class ThemeView extends React.Component {
);
}
- renderSectionHeader = (header = I18n.t('Theme')) => {
+ renderSectionHeader = (header = 'Theme') => {
const { theme } = this.props;
return (
<>
- {header}
+ {I18n.t(header)}
{this.renderSeparator()}
>
@@ -169,7 +172,7 @@ class ThemeView extends React.Component {
item.value}
+ keyExtractor={item => item.value + item.group}
contentContainerStyle={[
styles.list,
{ borderColor: themes[theme].separatorColor }
diff --git a/app/views/WithoutServersView.js b/app/views/WithoutServersView.js
index e5756ea79..136359df1 100644
--- a/app/views/WithoutServersView.js
+++ b/app/views/WithoutServersView.js
@@ -30,7 +30,7 @@ const styles = StyleSheet.create({
});
class WithoutServerView extends React.Component {
- static navigationOptions = {
+ static navigationOptions = () => ({
title: 'Rocket.Chat',
headerLeft: () => (
)
- }
+ })
static propTypes = {
theme: PropTypes.string
diff --git a/app/views/WorkspaceView/ServerAvatar.js b/app/views/WorkspaceView/ServerAvatar.js
index c7e849028..0a82b30f3 100644
--- a/app/views/WorkspaceView/ServerAvatar.js
+++ b/app/views/WorkspaceView/ServerAvatar.js
@@ -3,7 +3,7 @@ import { StyleSheet, View, Text } from 'react-native';
import PropTypes from 'prop-types';
import { createImageProgress } from 'react-native-image-progress';
import * as Progress from 'react-native-progress';
-import FastImage from 'react-native-fast-image';
+import FastImage from '@rocket.chat/react-native-fast-image';
import sharedStyles from '../Styles';
import { themes } from '../../constants/colors';
diff --git a/app/views/WorkspaceView/index.js b/app/views/WorkspaceView/index.js
index 70531b823..553e7135e 100644
--- a/app/views/WorkspaceView/index.js
+++ b/app/views/WorkspaceView/index.js
@@ -13,9 +13,9 @@ import ServerAvatar from './ServerAvatar';
import { getShowLoginButton } from '../../selectors/login';
class WorkspaceView extends React.Component {
- static navigationOptions = {
+ static navigationOptions = () => ({
title: I18n.t('Your_workspace')
- }
+ })
static propTypes = {
navigation: PropTypes.object,
@@ -70,7 +70,7 @@ class WorkspaceView extends React.Component {
-
+
{Site_Name}
{Site_Url}
diff --git a/e2e/README.md b/e2e/README.md
index 597127f2c..995bd3f90 100644
--- a/e2e/README.md
+++ b/e2e/README.md
@@ -1,4 +1,4 @@
-# e2e Testing
+# E2E Testing
## Contents
diff --git a/e2e/data.js b/e2e/data.js
index 4c4c8ca16..d3f4a0df9 100644
--- a/e2e/data.js
+++ b/e2e/data.js
@@ -9,34 +9,39 @@ const data = {
regular: {
username: `userone${ value }`,
password: '123',
- email: `diego.mello+regular${ value }@rocket.chat`
+ email: `mobile+regular${ value }@rocket.chat`
},
alternate: {
username: `usertwo${ value }`,
password: '123',
- email: `diego.mello+alternate${ value }@rocket.chat`,
+ email: `mobile+alternate${ value }@rocket.chat`,
totpSecret: 'NA4GOMZGHBQSK6KEFRVT62DMGJJGSYZJFZIHO3ZOGVXWCYZ6MMZQ'
},
profileChanges: {
username: `userthree${ value }`,
password: '123',
- email: `diego.mello+profileChanges${ value }@rocket.chat`
+ email: `mobile+profileChanges${ value }@rocket.chat`
},
existing: {
username: `existinguser${ value }`,
password: '123',
- email: `diego.mello+existing${ value }@rocket.chat`
+ email: `mobile+existing${ value }@rocket.chat`
}
},
channels: {
- public: {
+ detoxpublic: {
name: 'detox-public'
}
},
+ groups: {
+ private: {
+ name: `detox-private-${ value }`
+ }
+ },
registeringUser: {
username: `newuser${ value }`,
password: `password${ value }`,
- email: `diego.mello+registering${ value }@rocket.chat`
+ email: `mobile+registering${ value }@rocket.chat`
},
random: value
}
diff --git a/e2e/data/data.cloud.js b/e2e/data/data.cloud.js
index 4c4c8ca16..d3f4a0df9 100644
--- a/e2e/data/data.cloud.js
+++ b/e2e/data/data.cloud.js
@@ -9,34 +9,39 @@ const data = {
regular: {
username: `userone${ value }`,
password: '123',
- email: `diego.mello+regular${ value }@rocket.chat`
+ email: `mobile+regular${ value }@rocket.chat`
},
alternate: {
username: `usertwo${ value }`,
password: '123',
- email: `diego.mello+alternate${ value }@rocket.chat`,
+ email: `mobile+alternate${ value }@rocket.chat`,
totpSecret: 'NA4GOMZGHBQSK6KEFRVT62DMGJJGSYZJFZIHO3ZOGVXWCYZ6MMZQ'
},
profileChanges: {
username: `userthree${ value }`,
password: '123',
- email: `diego.mello+profileChanges${ value }@rocket.chat`
+ email: `mobile+profileChanges${ value }@rocket.chat`
},
existing: {
username: `existinguser${ value }`,
password: '123',
- email: `diego.mello+existing${ value }@rocket.chat`
+ email: `mobile+existing${ value }@rocket.chat`
}
},
channels: {
- public: {
+ detoxpublic: {
name: 'detox-public'
}
},
+ groups: {
+ private: {
+ name: `detox-private-${ value }`
+ }
+ },
registeringUser: {
username: `newuser${ value }`,
password: `password${ value }`,
- email: `diego.mello+registering${ value }@rocket.chat`
+ email: `mobile+registering${ value }@rocket.chat`
},
random: value
}
diff --git a/e2e/data/data.docker.js b/e2e/data/data.docker.js
index 5a7ed505c..a22423a63 100644
--- a/e2e/data/data.docker.js
+++ b/e2e/data/data.docker.js
@@ -9,34 +9,39 @@ const data = {
regular: {
username: `userone${ value }`,
password: '123',
- email: `diego.mello+regular${ value }@rocket.chat`
+ email: `mobile+regular${ value }@rocket.chat`
},
alternate: {
username: `usertwo${ value }`,
password: '123',
- email: `diego.mello+alternate${ value }@rocket.chat`,
+ email: `mobile+alternate${ value }@rocket.chat`,
totpSecret: 'NA4GOMZGHBQSK6KEFRVT62DMGJJGSYZJFZIHO3ZOGVXWCYZ6MMZQ'
},
profileChanges: {
username: `userthree${ value }`,
password: '123',
- email: `diego.mello+profileChanges${ value }@rocket.chat`
+ email: `mobile+profileChanges${ value }@rocket.chat`
},
existing: {
username: `existinguser${ value }`,
password: '123',
- email: `diego.mello+existing${ value }@rocket.chat`
+ email: `mobile+existing${ value }@rocket.chat`
}
},
channels: {
- public: {
+ detoxpublic: {
name: 'detox-public'
}
},
+ groups: {
+ private: {
+ name: `detox-private-${ value }`
+ }
+ },
registeringUser: {
username: `newuser${ value }`,
password: `password${ value }`,
- email: `diego.mello+registering${ value }@rocket.chat`
+ email: `mobile+registering${ value }@rocket.chat`
},
random: value
}
diff --git a/e2e/docker/controlRCDemoEnv.sh b/e2e/docker/controlRCDemoEnv.sh
index 16dc49a7a..527d837e3 100755
--- a/e2e/docker/controlRCDemoEnv.sh
+++ b/e2e/docker/controlRCDemoEnv.sh
@@ -42,7 +42,7 @@ if [ "$COMMAND" == "start" ]; then
MAX_ATTEMPTS=60
while [ $ATTEMPT_NUMBER -lt $MAX_ATTEMPTS ]; do # https://stackoverflow.com/a/21189312/399007
ATTEMPT_NUMBER=$((ATTEMPT_NUMBER + 1 ))
- echo "Waiting for server to be up ($ATTEMPT_NUMBER of $MAX_ATTEMPTS)"
+ echo "Checking if servers are ready (attempt $ATTEMPT_NUMBER of $MAX_ATTEMPTS)"
LOGS=$(docker logs rc_test_env_rocketchat_1 2> /dev/null)
if grep -q 'SERVER RUNNING' <<< $LOGS ; then
echo "RocketChat is ready!"
diff --git a/e2e/helpers/app.js b/e2e/helpers/app.js
index 88ef3d5ad..fcc6dc2ea 100644
--- a/e2e/helpers/app.js
+++ b/e2e/helpers/app.js
@@ -14,6 +14,7 @@ async function navigateToWorkspace() {
}
async function navigateToLogin() {
+ await waitFor(element(by.id('onboarding-view'))).toBeVisible().withTimeout(20000);
await navigateToWorkspace();
await element(by.id('workspace-view-login')).tap();
await waitFor(element(by.id('login-view'))).toBeVisible().withTimeout(2000);
@@ -21,6 +22,7 @@ async function navigateToLogin() {
}
async function navigateToRegister() {
+ await waitFor(element(by.id('onboarding-view'))).toBeVisible().withTimeout(20000);
await navigateToWorkspace();
await element(by.id('workspace-view-register')).tap();
await waitFor(element(by.id('register-view'))).toBeVisible().withTimeout(2000);
@@ -31,7 +33,6 @@ async function login(username, password) {
await waitFor(element(by.id('login-view'))).toBeVisible().withTimeout(2000);
await element(by.id('login-view-email')).replaceText(username);
await element(by.id('login-view-password')).replaceText(password);
- await sleep(300);
await element(by.id('login-view-submit')).tap();
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(10000);
}
@@ -61,6 +62,33 @@ async function mockMessage(message) {
await element(by.label(`${ data.random }${ message }`)).atIndex(0).tap();
};
+async function starMessage(message){
+ const messageLabel = `${ data.random }${ message }`
+ await waitFor(element(by.label(messageLabel))).toBeVisible().withTimeout(5000);
+ await element(by.label(messageLabel)).atIndex(0).longPress();
+ await expect(element(by.id('action-sheet'))).toExist();
+ await expect(element(by.id('action-sheet-handle'))).toBeVisible();
+ await element(by.id('action-sheet-handle')).swipe('up', 'fast', 0.5);
+ await element(by.label('Star')).tap();
+ await waitFor(element(by.id('action-sheet'))).toNotExist().withTimeout(5000);
+};
+
+async function pinMessage(message){
+ const messageLabel = `${ data.random }${ message }`
+ await waitFor(element(by.label(messageLabel)).atIndex(0)).toExist();
+ await element(by.label(messageLabel)).atIndex(0).longPress();
+ await expect(element(by.id('action-sheet'))).toExist();
+ await expect(element(by.id('action-sheet-handle'))).toBeVisible();
+ await element(by.id('action-sheet-handle')).swipe('up', 'fast', 0.5);
+ await element(by.label('Pin')).tap();
+ await waitFor(element(by.id('action-sheet'))).toNotExist().withTimeout(5000);
+}
+
+async function dismissReviewNag(){
+ await waitFor(element(by.text('Are you enjoying this app?'))).toExist().withTimeout(60000);
+ await element(by.label('No').and(by.type('_UIAlertControllerActionView'))).tap(); // Tap `no` on ask for review alert
+}
+
async function tapBack() {
await element(by.id('header-back')).atIndex(0).tap();
}
@@ -74,7 +102,22 @@ async function searchRoom(room) {
await expect(element(by.id('rooms-list-view-search-input'))).toExist();
await waitFor(element(by.id('rooms-list-view-search-input'))).toExist().withTimeout(5000);
await element(by.id('rooms-list-view-search-input')).typeText(room);
- await sleep(2000);
+}
+
+async function tryTapping(theElement, timeout, longtap = false){
+ try {
+ if(longtap){
+ await theElement.longPress()
+ } else {
+ await theElement.tap()
+ }
+ } catch(e) {
+ if(timeout <= 0){ //TODO: Maths. How closely has the timeout been honoured here?
+ throw e
+ }
+ await sleep(100)
+ await tryTapping(theElement, timeout - 100)
+ }
}
module.exports = {
@@ -84,7 +127,11 @@ module.exports = {
login,
logout,
mockMessage,
+ starMessage,
+ pinMessage,
+ dismissReviewNag,
tapBack,
sleep,
- searchRoom
+ searchRoom,
+ tryTapping
};
\ No newline at end of file
diff --git a/e2e/helpers/data_setup.js b/e2e/helpers/data_setup.js
index 84e5927ea..d16b41a55 100644
--- a/e2e/helpers/data_setup.js
+++ b/e2e/helpers/data_setup.js
@@ -38,7 +38,7 @@ const createUser = async (username, password, name, email) => {
}
const createChannelIfNotExists = async (channelname) => {
- console.log(`Creating channel ${channelname}`)
+ console.log(`Creating public channel ${channelname}`)
try {
await rocketchat.post('channels.create', {
"name": channelname
@@ -49,7 +49,24 @@ const createChannelIfNotExists = async (channelname) => {
} catch (infoError) {
console.log(JSON.stringify(createError))
console.log(JSON.stringify(infoError))
- throw "Failed to find or create channel"
+ throw "Failed to find or create public channel"
+ }
+ }
+}
+
+const createGroupIfNotExists = async (groupname) => {
+ console.log(`Creating private group ${groupname}`)
+ try {
+ await rocketchat.post('groups.create', {
+ "name": groupname
+ })
+ } catch (createError) {
+ try { //Maybe it exists already?
+ await rocketchat.get(`group.info?roomName=${groupname}`)
+ } catch (infoError) {
+ console.log(JSON.stringify(createError))
+ console.log(JSON.stringify(infoError))
+ throw "Failed to find or create private group"
}
}
}
@@ -71,6 +88,15 @@ const setup = async () => {
}
}
+ await login(data.users.regular.username, data.users.regular.password)
+
+ for (var groupKey in data.groups) {
+ if (data.groups.hasOwnProperty(groupKey)) {
+ const group = data.groups[groupKey]
+ await createGroupIfNotExists(group.name)
+ }
+ }
+
return
}
diff --git a/e2e/tests/assorted/01-changeserver.spec.js b/e2e/tests/assorted/01-changeserver.spec.js
index 0664970a7..7210d7060 100644
--- a/e2e/tests/assorted/01-changeserver.spec.js
+++ b/e2e/tests/assorted/01-changeserver.spec.js
@@ -9,12 +9,12 @@ const checkServer = async(server) => {
await element(by.id('rooms-list-view-sidebar')).tap();
await waitFor(element(by.id('sidebar-view'))).toBeVisible().withTimeout(2000);
await waitFor(element(by.label(label))).toBeVisible().withTimeout(60000);
- await expect(element(by.label(label))).toBeVisible();
await element(by.id('sidebar-close-drawer')).tap();
}
describe('Change server', () => {
before(async() => {
+ await device.launchApp({ permissions: { notifications: 'YES' }, delete: true });
await navigateToLogin();
await login(data.users.regular.username, data.users.regular.password);
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(10000);
@@ -28,8 +28,6 @@ describe('Change server', () => {
await sleep(5000);
await element(by.id('rooms-list-header-server-dropdown-button')).tap();
await waitFor(element(by.id('rooms-list-header-server-dropdown'))).toBeVisible().withTimeout(5000);
- await expect(element(by.id('rooms-list-header-server-dropdown'))).toExist();
- await sleep(1000);
await element(by.id('rooms-list-header-server-add')).tap();
// TODO: refactor
@@ -37,19 +35,16 @@ describe('Change server', () => {
await element(by.id('new-server-view-input')).replaceText(data.alternateServer);
await element(by.id('new-server-view-button')).tap();
await waitFor(element(by.id('workspace-view'))).toBeVisible().withTimeout(60000);
- await expect(element(by.id('workspace-view'))).toBeVisible();
await element(by.id('workspace-view-register')).tap();
await waitFor(element(by.id('register-view'))).toBeVisible().withTimeout(2000);
- await expect(element(by.id('register-view'))).toBeVisible();
+
// Register new user
await element(by.id('register-view-name')).replaceText(data.registeringUser.username);
await element(by.id('register-view-username')).replaceText(data.registeringUser.username);
await element(by.id('register-view-email')).replaceText(data.registeringUser.email);
await element(by.id('register-view-password')).replaceText(data.registeringUser.password);
- await sleep(1000);
await element(by.id('register-view-submit')).tap();
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(60000);
- await expect(element(by.id('rooms-list-view'))).toBeVisible();
// For a sanity test, to make sure roomslist is showing correct rooms
// app CANNOT show public room created on previous tests
@@ -59,11 +54,8 @@ describe('Change server', () => {
});
it('should change back', async() => {
- await sleep(5000);
await element(by.id('rooms-list-header-server-dropdown-button')).tap();
await waitFor(element(by.id('rooms-list-header-server-dropdown'))).toBeVisible().withTimeout(5000);
- await expect(element(by.id('rooms-list-header-server-dropdown'))).toExist();
- await sleep(1000);
await element(by.id(`rooms-list-header-server-${ data.server }`)).tap();
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(10000);
await checkServer(data.server);
diff --git a/e2e/tests/assorted/02-broadcast.spec.js b/e2e/tests/assorted/02-broadcast.spec.js
index 1b2fcc1db..9e87c5e14 100644
--- a/e2e/tests/assorted/02-broadcast.spec.js
+++ b/e2e/tests/assorted/02-broadcast.spec.js
@@ -23,28 +23,16 @@ describe('Broadcast room', () => {
await waitFor(element(by.id('select-users-view'))).toBeVisible().withTimeout(2000);
await element(by.id('select-users-view-search')).replaceText(otheruser.username);
await waitFor(element(by.id(`select-users-view-item-${ otheruser.username }`))).toBeVisible().withTimeout(60000);
- await expect(element(by.id(`select-users-view-item-${ otheruser.username }`))).toBeVisible();
await element(by.id(`select-users-view-item-${ otheruser.username }`)).tap();
await waitFor(element(by.id(`selected-user-${ otheruser.username }`))).toBeVisible().withTimeout(5000);
- await sleep(1000);
await element(by.id('selected-users-view-submit')).tap();
- await sleep(1000);
await waitFor(element(by.id('create-channel-view'))).toExist().withTimeout(5000);
await element(by.id('create-channel-name')).replaceText(`broadcast${ data.random }`);
- await sleep(2000);
- await element(by.id('create-channel-broadcast')).tap();
- if (device.getPlatform() === 'ios') { //Because this tap is FLAKY on iOS
- await expect(element(by.id('create-channel-broadcast'))).toHaveValue('1')
- }
- await sleep(500);
+ await element(by.id('create-channel-broadcast')).longPress(); //https://github.com/facebook/react-native/issues/28032
await element(by.id('create-channel-submit')).tap();
await waitFor(element(by.id('room-view'))).toBeVisible().withTimeout(60000);
- await expect(element(by.id('room-view'))).toBeVisible();
await waitFor(element(by.id(`room-view-title-broadcast${ data.random }`))).toBeVisible().withTimeout(60000);
- await expect(element(by.id(`room-view-title-broadcast${ data.random }`))).toBeVisible();
- await sleep(1000);
await element(by.id('room-view-header-actions')).tap();
- await sleep(1000);
await waitFor(element(by.id('room-actions-view'))).toBeVisible().withTimeout(5000);
await element(by.id('room-actions-info')).tap();
await waitFor(element(by.id('room-info-view'))).toBeVisible().withTimeout(2000);
@@ -64,25 +52,19 @@ describe('Broadcast room', () => {
it('should login as user without write message authorization and enter room', async() => {
await device.launchApp({ permissions: { notifications: 'YES' }, delete: true });
await navigateToLogin();
- await element(by.id('login-view-email')).replaceText(otheruser.username);
- await element(by.id('login-view-password')).replaceText(otheruser.password);
- await sleep(1000);
- await element(by.id('login-view-submit')).tap();
+ await login(otheruser.username, otheruser.password);
+
//await waitFor(element(by.id('two-factor'))).toBeVisible().withTimeout(5000);
//await expect(element(by.id('two-factor'))).toBeVisible();
//const code = GA.gen(data.alternateUserTOTPSecret);
//await element(by.id('two-factor-input')).replaceText(code);
- //await sleep(1000);
//await element(by.id('two-factor-send')).tap();
- await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(10000);
+
await searchRoom(`broadcast${ data.random }`);
await waitFor(element(by.id(`rooms-list-view-item-broadcast${ data.random }`))).toExist().withTimeout(60000);
- await expect(element(by.id(`rooms-list-view-item-broadcast${ data.random }`))).toExist();
await element(by.id(`rooms-list-view-item-broadcast${ data.random }`)).tap();
await waitFor(element(by.id('room-view'))).toBeVisible().withTimeout(5000);
await waitFor(element(by.id(`room-view-title-broadcast${ data.random }`))).toBeVisible().withTimeout(60000);
- await expect(element(by.id(`room-view-title-broadcast${ data.random }`))).toBeVisible();
- await sleep(1000);
});
it('should not have messagebox', async() => {
@@ -95,7 +77,6 @@ describe('Broadcast room', () => {
it('should have the message created earlier', async() => {
await waitFor(element(by.label(`${ data.random }message`)).atIndex(0)).toBeVisible().withTimeout(60000);
- await expect(element(by.label(`${ data.random }message`)).atIndex(0)).toBeVisible();
});
it('should have reply button', async() => {
@@ -104,9 +85,7 @@ describe('Broadcast room', () => {
it('should tap on reply button and navigate to direct room', async() => {
await element(by.id('message-broadcast-reply')).tap();
- await sleep(1000);
await waitFor(element(by.id(`room-view-title-${ testuser.username }`))).toBeVisible().withTimeout(5000);
- await expect(element(by.id(`room-view-title-${ testuser.username }`))).toBeVisible();
});
it('should reply broadcasted message', async() => {
diff --git a/e2e/tests/assorted/03-profile.spec.js b/e2e/tests/assorted/03-profile.spec.js
index e5c321757..9700da1b2 100644
--- a/e2e/tests/assorted/03-profile.spec.js
+++ b/e2e/tests/assorted/03-profile.spec.js
@@ -13,7 +13,7 @@ async function waitForToast() {
// await expect(element(by.id('toast'))).toBeVisible();
// await waitFor(element(by.id('toast'))).toBeNotVisible().withTimeout(10000);
// await expect(element(by.id('toast'))).toBeNotVisible();
- await sleep(5000);
+ await sleep(1);
}
describe('Profile screen', () => {
@@ -24,7 +24,6 @@ describe('Profile screen', () => {
await element(by.id('rooms-list-view-sidebar')).tap();
await waitFor(element(by.id('sidebar-view'))).toBeVisible().withTimeout(2000);
await waitFor(element(by.id('sidebar-profile'))).toBeVisible().withTimeout(2000);
- await expect(element(by.id('sidebar-profile'))).toBeVisible();
await element(by.id('sidebar-profile')).tap();
await waitFor(element(by.id('profile-view'))).toBeVisible().withTimeout(2000);
});
@@ -60,22 +59,18 @@ describe('Profile screen', () => {
it('should have reset avatar button', async() => {
await waitFor(element(by.id('profile-view-reset-avatar'))).toExist().whileElement(by.id('profile-view-list')).scroll(scrollDown, 'down');
- await expect(element(by.id('profile-view-reset-avatar'))).toExist();
});
it('should have upload avatar button', async() => {
await waitFor(element(by.id('profile-view-upload-avatar'))).toExist().whileElement(by.id('profile-view-list')).scroll(scrollDown, 'down');
- await expect(element(by.id('profile-view-upload-avatar'))).toExist();
});
it('should have avatar url button', async() => {
await waitFor(element(by.id('profile-view-avatar-url-button'))).toExist().whileElement(by.id('profile-view-list')).scroll(scrollDown, 'down');
- await expect(element(by.id('profile-view-avatar-url-button'))).toExist();
});
it('should have submit button', async() => {
await waitFor(element(by.id('profile-view-submit'))).toExist().whileElement(by.id('profile-view-list')).scroll(scrollDown, 'down');
- await expect(element(by.id('profile-view-submit'))).toExist();
});
});
@@ -84,15 +79,13 @@ describe('Profile screen', () => {
await element(by.type('UIScrollView')).atIndex(1).swipe('down');
await element(by.id('profile-view-name')).replaceText(`${ profileChangeUser.username }new`);
await element(by.id('profile-view-username')).replaceText(`${ profileChangeUser.username }new`);
- await sleep(1000);
await element(by.type('UIScrollView')).atIndex(1).swipe('up');
- await sleep(1000);
await element(by.id('profile-view-submit')).tap();
await waitForToast();
});
it('should change email and password', async() => {
- await element(by.id('profile-view-email')).replaceText(`diego.mello+profileChangesNew${ data.random }@rocket.chat`);
+ await element(by.id('profile-view-email')).replaceText(`mobile+profileChangesNew${ data.random }@rocket.chat`);
await element(by.id('profile-view-new-password')).replaceText(`${ profileChangeUser.password }new`);
await element(by.id('profile-view-submit')).tap();
await element(by.type('_UIAlertControllerTextField')).replaceText(`${ profileChangeUser.password }`)
@@ -103,7 +96,6 @@ describe('Profile screen', () => {
it('should reset avatar', async() => {
await element(by.type('UIScrollView')).atIndex(1).swipe('up');
- await sleep(1000);
await element(by.id('profile-view-reset-avatar')).tap();
await waitForToast();
});
diff --git a/e2e/tests/assorted/04-setting.spec.js b/e2e/tests/assorted/04-setting.spec.js
index c2cfae6f1..951ccc70d 100644
--- a/e2e/tests/assorted/04-setting.spec.js
+++ b/e2e/tests/assorted/04-setting.spec.js
@@ -1,12 +1,18 @@
const {
device, expect, element, by, waitFor
} = require('detox');
+const { navigateToLogin, login } = require('../../helpers/app');
+
+const data = require('../../data');
+
+const testuser = data.users.regular
describe('Settings screen', () => {
before(async() => {
- await device.launchApp({ newInstance: true });
+ await device.launchApp({ permissions: { notifications: 'YES' }, delete: true });
+ await navigateToLogin();
+ await login(testuser.username, testuser.password);
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(10000);
- await expect(element(by.id('rooms-list-view'))).toBeVisible();
await element(by.id('rooms-list-view-sidebar')).tap();
await waitFor(element(by.id('sidebar-view'))).toBeVisible().withTimeout(2000);
await waitFor(element(by.id('sidebar-settings'))).toBeVisible().withTimeout(2000);
diff --git a/e2e/tests/assorted/05-joinpublicroom.spec.js b/e2e/tests/assorted/05-joinpublicroom.spec.js
index d68d1a955..1c946f0c2 100644
--- a/e2e/tests/assorted/05-joinpublicroom.spec.js
+++ b/e2e/tests/assorted/05-joinpublicroom.spec.js
@@ -2,12 +2,12 @@ const {
device, expect, element, by, waitFor
} = require('detox');
const data = require('../../data');
-const { mockMessage, tapBack, sleep, searchRoom } = require('../../helpers/app');
+const { navigateToLogin, login, mockMessage, tapBack, sleep, searchRoom } = require('../../helpers/app');
-const room = 'detox-public';
+const testuser = data.users.regular
+const room = data.channels.detoxpublic.name;
async function navigateToRoom() {
- await sleep(2000);
await searchRoom(room);
await waitFor(element(by.id(`rooms-list-view-item-${ room }`)).atIndex(0)).toBeVisible().withTimeout(60000);
await element(by.id(`rooms-list-view-item-${ room }`)).atIndex(0).tap();
@@ -15,15 +15,15 @@ async function navigateToRoom() {
}
async function navigateToRoomActions() {
- await sleep(2000);
await element(by.id('room-view-header-actions')).tap();
- await sleep(2000);
await waitFor(element(by.id('room-actions-view'))).toBeVisible().withTimeout(5000);
}
describe('Join public room', () => {
before(async() => {
- await device.launchApp({ newInstance: true });
+ await device.launchApp({ permissions: { notifications: 'YES' }, delete: true });
+ await navigateToLogin();
+ await login(testuser.username, testuser.password);
await navigateToRoom();
});
@@ -167,9 +167,7 @@ describe('Join public room', () => {
await element(by.text('Yes, leave it!')).tap();
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(10000);
// await element(by.id('rooms-list-view-search')).typeText('');
- await sleep(2000);
await waitFor(element(by.id(`rooms-list-view-item-${ room }`))).toBeNotVisible().withTimeout(60000);
- await expect(element(by.id(`rooms-list-view-item-${ room }`))).toBeNotVisible();
});
});
});
diff --git a/e2e/tests/assorted/06-status.spec.js b/e2e/tests/assorted/06-status.spec.js
index ee592d41f..887dcb1e0 100644
--- a/e2e/tests/assorted/06-status.spec.js
+++ b/e2e/tests/assorted/06-status.spec.js
@@ -1,14 +1,21 @@
const {
expect, element, by, waitFor
} = require('detox');
-const { sleep } = require('../../helpers/app');
+const { navigateToLogin, login, sleep } = require('../../helpers/app');
+
+const data = require('../../data');
+const testuser = data.users.regular
async function waitForToast() {
- await sleep(5000);
+ await sleep(1);
}
describe('Status screen', () => {
- before(async() => {
+ before(async () => {
+ await device.launchApp({ permissions: { notifications: 'YES' }, delete: true });
+ await navigateToLogin();
+ await login(testuser.username, testuser.password);
+
await element(by.id('rooms-list-view-sidebar')).tap();
await waitFor(element(by.id('sidebar-view'))).toBeVisible().withTimeout(2000);
await waitFor(element(by.id('sidebar-custom-status'))).toBeVisible().withTimeout(2000);
@@ -17,30 +24,27 @@ describe('Status screen', () => {
await waitFor(element(by.id('status-view'))).toBeVisible().withTimeout(2000);
});
- describe('Render', async() => {
- it('should have status input', async() => {
+ describe('Render', async () => {
+ it('should have status input', async () => {
await expect(element(by.id('status-view-input'))).toBeVisible();
await expect(element(by.id('status-view-online'))).toExist();
await expect(element(by.id('status-view-busy'))).toExist();
await expect(element(by.id('status-view-away'))).toExist();
await expect(element(by.id('status-view-offline'))).toExist();
- });
- });
-
- describe('Usage', async() => {
- it('should change status', async() => {
- await sleep(1000);
- await element(by.id('status-view-busy')).tap();
- await sleep(1000);
- await expect(element(by.id('status-view-current-busy'))).toExist();
- });
+ });
+ });
- it('should change status text', async() => {
+ describe('Usage', async () => {
+ it('should change status', async () => {
+ await element(by.id('status-view-busy')).tap();
+ await expect(element(by.id('status-view-current-busy'))).toExist();
+ });
+
+ it('should change status text', async () => {
await element(by.id('status-view-input')).replaceText('status-text-new');
- await sleep(1000);
await element(by.id('status-view-submit')).tap();
await waitForToast();
await waitFor(element(by.label('status-text-new').withAncestor(by.id('sidebar-custom-status')))).toBeVisible().withTimeout(2000);
- });
- });
-});
+ });
+ });
+});
\ No newline at end of file
diff --git a/e2e/tests/init.js b/e2e/tests/init.js
index bef12f6d3..9eaa721b6 100644
--- a/e2e/tests/init.js
+++ b/e2e/tests/init.js
@@ -1,11 +1,21 @@
const detox = require('detox');
const config = require('../../package.json').detox;
const dataSetup = require('../helpers/data_setup')
+const adapter = require('detox/runners/mocha/adapter');
before(async() => {
- await dataSetup()
- await detox.init(config, { launchApp: false });
- await device.launchApp({ permissions: { notifications: 'YES' } });
+ await Promise.all([dataSetup(), detox.init(config, { launchApp: false })])
+ //await dataSetup()
+ //await detox.init(config, { launchApp: false });
+ //await device.launchApp({ permissions: { notifications: 'YES' } });
+});
+
+beforeEach(async function() {
+ await adapter.beforeEach(this);
+});
+
+afterEach(async function() {
+ await adapter.afterEach(this);
});
after(async() => {
diff --git a/e2e/tests/onboarding/01-onboarding.spec.js b/e2e/tests/onboarding/01-onboarding.spec.js
index c84928d60..4806dcb57 100644
--- a/e2e/tests/onboarding/01-onboarding.spec.js
+++ b/e2e/tests/onboarding/01-onboarding.spec.js
@@ -6,7 +6,7 @@ const data = require('../../data');
describe('Onboarding', () => {
before(async() => {
await device.launchApp({ permissions: { notifications: 'YES' }, delete: true });
- await waitFor(element(by.id('onboarding-view'))).toBeVisible().withTimeout(2000);
+ await waitFor(element(by.id('onboarding-view'))).toBeVisible().withTimeout(20000);
});
describe('Render', () => {
@@ -31,7 +31,6 @@ describe('Onboarding', () => {
it('should navigate to join a workspace', async() => {
await element(by.id('join-workspace')).tap();
await waitFor(element(by.id('new-server-view'))).toBeVisible().withTimeout(60000);
- await expect(element(by.id('new-server-view'))).toBeVisible();
});
it('should enter an invalid server and get error', async() => {
@@ -39,14 +38,12 @@ describe('Onboarding', () => {
await element(by.id('new-server-view-button')).tap();
const errorText = 'Oops!';
await waitFor(element(by.text(errorText))).toBeVisible().withTimeout(60000);
- await expect(element(by.text(errorText))).toBeVisible();
await element(by.text('OK')).tap();
});
it('should tap on "Join our open workspace" and navigate', async() => {
await element(by.id('new-server-view-open')).tap();
await waitFor(element(by.id('workspace-view'))).toBeVisible().withTimeout(60000);
- await expect(element(by.id('workspace-view'))).toBeVisible();
});
it('should enter a valid server without login services and navigate to login', async() => {
@@ -57,7 +54,6 @@ describe('Onboarding', () => {
await element(by.id('new-server-view-input')).replaceText(data.server);
await element(by.id('new-server-view-button')).tap();
await waitFor(element(by.id('workspace-view'))).toBeVisible().withTimeout(60000);
- await expect(element(by.id('workspace-view'))).toBeVisible();
});
});
});
diff --git a/e2e/tests/onboarding/02-legal.spec.js b/e2e/tests/onboarding/02-legal.spec.js
index e8109ece5..191e0647c 100644
--- a/e2e/tests/onboarding/02-legal.spec.js
+++ b/e2e/tests/onboarding/02-legal.spec.js
@@ -4,54 +4,62 @@ const {
const { navigateToRegister, navigateToLogin } = require('../../helpers/app');
describe('Legal screen', () => {
- it('should have legal button on login', async() => {
- await device.launchApp({ newInstance: true });
- await navigateToLogin();
- await waitFor(element(by.id('login-view-more'))).toBeVisible().withTimeout(60000);
- await expect(element(by.id('login-view-more'))).toBeVisible();
- });
- it('should navigate to legal from login', async() => {
- await waitFor(element(by.id('login-view-more'))).toBeVisible().withTimeout(60000);
- await element(by.id('login-view-more')).tap();
- });
-
- it('should have legal button on register', async() => {
- await device.launchApp({ newInstance: true });
- await navigateToRegister();
- await waitFor(element(by.id('register-view-more'))).toBeVisible().withTimeout(60000);
- await expect(element(by.id('register-view-more'))).toBeVisible();
- });
-
- it('should navigate to legal from register', async() => {
- await waitFor(element(by.id('register-view-more'))).toBeVisible().withTimeout(60000);
- await element(by.id('register-view-more')).tap();
- });
-
- it('should have legal screen', async() => {
- await expect(element(by.id('legal-view'))).toBeVisible();
- });
-
- it('should have terms of service button', async() => {
- await expect(element(by.id('legal-terms-button'))).toBeVisible();
- });
-
- it('should have privacy policy button', async() => {
- await expect(element(by.id('legal-privacy-button'))).toBeVisible();
- });
+ describe('From Login', () => {
+ before(async() => {
+ await device.launchApp({ permissions: { notifications: 'YES' }, delete: true });
+ await navigateToLogin();
+ });
-
- // We can't simulate how webview behaves, so I had to disable :(
- // it('should navigate to terms', async() => {
- // await element(by.id('legal-terms-button')).tap();
- // await waitFor(element(by.id('terms-view'))).toBeVisible().withTimeout(2000);
- // await expect(element(by.id('terms-view'))).toBeVisible();
- // });
+ it('should have legal button on login', async() => {
+ await waitFor(element(by.id('login-view-more'))).toBeVisible().withTimeout(60000);
+ });
- // it('should navigate to privacy', async() => {
- // await tapBack();
- // await element(by.id('legal-privacy-button')).tap();
- // await waitFor(element(by.id('privacy-view'))).toBeVisible().withTimeout(2000);
- // await expect(element(by.id('privacy-view'))).toBeVisible();
- // });
+ it('should navigate to legal from login', async() => {
+ await expect(element(by.id('login-view-more'))).toBeVisible();
+ await element(by.id('login-view-more')).tap();
+ await waitFor(element(by.id('legal-view'))).toBeVisible().withTimeout(4000)
+ });
+ });
+
+ describe('From Register', () => {
+ before(async() => {
+ await device.launchApp({ permissions: { notifications: 'YES' }, delete: true });
+ await navigateToRegister();
+ });
+
+ it('should have legal button on register', async() => {
+ await waitFor(element(by.id('register-view-more'))).toBeVisible().withTimeout(60000);
+ });
+
+ it('should navigate to legal from register', async() => {
+ await expect(element(by.id('register-view-more'))).toBeVisible();
+ await element(by.id('register-view-more')).tap();
+ await waitFor(element(by.id('legal-view'))).toBeVisible().withTimeout(4000);
+ });
+
+ it('should have terms of service button', async() => {
+ await expect(element(by.id('legal-terms-button'))).toBeVisible();
+ });
+
+ it('should have privacy policy button', async() => {
+ await expect(element(by.id('legal-privacy-button'))).toBeVisible();
+ });
+
+ // We can't simulate how webview behaves, so I had to disable :(
+ /*
+ it('should navigate to terms', async() => {
+ await element(by.id('legal-terms-button')).tap();
+ await waitFor(element(by.id('terms-view'))).toBeVisible().withTimeout(2000);
+ await expect(element(by.id('terms-view'))).toBeVisible();
+ });
+
+ it('should navigate to privacy', async() => {
+ await tapBack();
+ await element(by.id('legal-privacy-button')).tap();
+ await waitFor(element(by.id('privacy-view'))).toBeVisible().withTimeout(2000);
+ await expect(element(by.id('privacy-view'))).toBeVisible();
+ });
+ */
+ });
});
diff --git a/e2e/tests/onboarding/03-forgotpassword.spec.js b/e2e/tests/onboarding/03-forgotpassword.spec.js
index 2fa710469..88d4c3e90 100644
--- a/e2e/tests/onboarding/03-forgotpassword.spec.js
+++ b/e2e/tests/onboarding/03-forgotpassword.spec.js
@@ -32,7 +32,6 @@ describe('Forgot password screen', () => {
await element(by.id('forgot-password-view-submit')).tap();
await element(by.text('OK')).tap();
await waitFor(element(by.id('login-view'))).toBeVisible().withTimeout(60000);
- await expect(element(by.id('login-view'))).toBeVisible();
});
});
});
diff --git a/e2e/tests/onboarding/04-createuser.spec.js b/e2e/tests/onboarding/04-createuser.spec.js
index dbe28a471..aa75807f2 100644
--- a/e2e/tests/onboarding/04-createuser.spec.js
+++ b/e2e/tests/onboarding/04-createuser.spec.js
@@ -37,6 +37,7 @@ describe('Create user screen', () => {
});
describe('Usage', () => {
+
// FIXME: Detox isn't able to check if it's tappable: https://github.com/wix/Detox/issues/246
// it('should submit invalid email and do nothing', async() => {
// const invalidEmail = 'invalidemail';
@@ -52,10 +53,8 @@ describe('Create user screen', () => {
await element(by.id('register-view-username')).replaceText(data.registeringUser.username);
await element(by.id('register-view-email')).replaceText(data.users.existing.email);
await element(by.id('register-view-password')).replaceText(data.registeringUser.password);
- await sleep(300);
await element(by.id('register-view-submit')).tap();
await waitFor(element(by.text('Email already exists. [403]')).atIndex(0)).toExist().withTimeout(10000);
- await expect(element(by.text('Email already exists. [403]')).atIndex(0)).toExist();
await element(by.text('OK')).tap();
});
@@ -64,10 +63,8 @@ describe('Create user screen', () => {
await element(by.id('register-view-username')).replaceText(data.users.existing.username);
await element(by.id('register-view-email')).replaceText(data.registeringUser.email);
await element(by.id('register-view-password')).replaceText(data.registeringUser.password);
- await sleep(300);
await element(by.id('register-view-submit')).tap();
await waitFor(element(by.text('Username is already in use')).atIndex(0)).toExist().withTimeout(10000);
- await expect(element(by.text('Username is already in use')).atIndex(0)).toExist();
await element(by.text('OK')).tap();
});
@@ -76,10 +73,8 @@ describe('Create user screen', () => {
await element(by.id('register-view-username')).replaceText(data.registeringUser.username);
await element(by.id('register-view-email')).replaceText(data.registeringUser.email);
await element(by.id('register-view-password')).replaceText(data.registeringUser.password);
- await sleep(300);
await element(by.id('register-view-submit')).tap();
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(60000);
- await expect(element(by.id('rooms-list-view'))).toBeVisible();
});
});
});
diff --git a/e2e/tests/onboarding/05-login.spec.js b/e2e/tests/onboarding/05-login.spec.js
index 3734b543d..7c6b4853c 100644
--- a/e2e/tests/onboarding/05-login.spec.js
+++ b/e2e/tests/onboarding/05-login.spec.js
@@ -44,33 +44,27 @@ describe('Login screen', () => {
it('should navigate to register', async() => {
await element(by.id('login-view-register')).tap();
await waitFor(element(by.id('register-view'))).toBeVisible().withTimeout(2000);
- await expect(element(by.id('register-view'))).toBeVisible();
await tapBack();
});
it('should navigate to forgot password', async() => {
await element(by.id('login-view-forgot-password')).tap();
await waitFor(element(by.id('forgot-password-view'))).toExist().withTimeout(2000);
- await expect(element(by.id('forgot-password-view'))).toExist();
await tapBack();
});
it('should insert wrong password and get error', async() => {
await element(by.id('login-view-email')).replaceText(data.users.regular.username);
await element(by.id('login-view-password')).replaceText('NotMyActualPassword');
- await sleep(300);
await element(by.id('login-view-submit')).tap();
await waitFor(element(by.text('Your credentials were rejected! Please try again.'))).toBeVisible().withTimeout(10000);
- await expect(element(by.text('Your credentials were rejected! Please try again.'))).toBeVisible();
await element(by.text('OK')).tap();
});
it('should login with success', async() => {
await element(by.id('login-view-password')).replaceText(data.users.regular.password);
- await sleep(300);
await element(by.id('login-view-submit')).tap();
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(60000);
- await expect(element(by.id('rooms-list-view'))).toBeVisible();
});
});
});
diff --git a/e2e/tests/onboarding/06-roomslist.spec.js b/e2e/tests/onboarding/06-roomslist.spec.js
index 5e7e1e8aa..bbe0b886b 100644
--- a/e2e/tests/onboarding/06-roomslist.spec.js
+++ b/e2e/tests/onboarding/06-roomslist.spec.js
@@ -1,9 +1,17 @@
const {
device, expect, element, by, waitFor
} = require('detox');
-const { logout, tapBack, sleep, searchRoom } = require('../../helpers/app');
+const { login, navigateToLogin, logout, tapBack, sleep, searchRoom } = require('../../helpers/app');
+const data = require('../../data');
describe('Rooms list screen', () => {
+
+ before(async() => {
+ await device.launchApp({ permissions: { notifications: 'YES' }, newInstance: true, delete: true });
+ await navigateToLogin();
+ await login(data.users.regular.username, data.users.regular.password)
+ });
+
describe('Render', () => {
it('should have rooms list screen', async() => {
await expect(element(by.id('rooms-list-view'))).toBeVisible();
@@ -29,18 +37,12 @@ describe('Rooms list screen', () => {
it('should search room and navigate', async() => {
await searchRoom('rocket.cat');
await waitFor(element(by.id('rooms-list-view-item-rocket.cat'))).toBeVisible().withTimeout(60000);
- await expect(element(by.id('rooms-list-view-item-rocket.cat'))).toBeVisible();
await element(by.id('rooms-list-view-item-rocket.cat')).tap();
await waitFor(element(by.id('room-view'))).toBeVisible().withTimeout(10000);
- await expect(element(by.id('room-view'))).toBeVisible();
await waitFor(element(by.id('room-view-title-rocket.cat'))).toBeVisible().withTimeout(60000);
- await expect(element(by.id('room-view-title-rocket.cat'))).toBeVisible();
await tapBack();
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
- await expect(element(by.id('rooms-list-view'))).toBeVisible();
- await sleep(2000);
await waitFor(element(by.id('rooms-list-view-item-rocket.cat'))).toExist().withTimeout(60000);
- await expect(element(by.id('rooms-list-view-item-rocket.cat'))).toExist();
});
it('should logout', async() => {
diff --git a/e2e/tests/room/01-createroom.spec.js b/e2e/tests/room/01-createroom.spec.js
index 1cfbf16a7..3fb464458 100644
--- a/e2e/tests/room/01-createroom.spec.js
+++ b/e2e/tests/room/01-createroom.spec.js
@@ -2,60 +2,59 @@ const {
device, expect, element, by, waitFor
} = require('detox');
const data = require('../../data');
-const { tapBack, sleep, navigateToLogin, login } = require('../../helpers/app');
+const { tapBack, sleep, navigateToLogin, login, tryTapping } = require('../../helpers/app');
+
+
describe('Create room screen', () => {
before(async() => {
+ await device.launchApp({ permissions: { notifications: 'YES' }, delete: true });
await navigateToLogin();
await login(data.users.regular.username, data.users.regular.password);
- await element(by.id('rooms-list-view-create-channel')).tap();
- await waitFor(element(by.id('new-message-view'))).toExist().withTimeout(2000);
});
describe('New Message', async() => {
+ before(async() => {
+ await element(by.id('rooms-list-view-create-channel')).tap();
+ });
+
describe('Render', async() => {
it('should have new message screen', async() => {
- await expect(element(by.id('new-message-view'))).toExist();
+ await waitFor(element(by.id('new-message-view'))).toBeVisible().withTimeout(2000);
});
it('should have search input', async() => {
- await waitFor(element(by.id('new-message-view-search'))).toExist().withTimeout(2000);
- await expect(element(by.id('new-message-view-search'))).toExist();
+ await waitFor(element(by.id('new-message-view-search'))).toBeVisible().withTimeout(2000);
});
})
describe('Usage', async() => {
it('should back to rooms list', async() => {
- await sleep(1000);
+ await waitFor(element(by.id('new-message-view-close'))).toBeVisible().withTimeout(5000);
await element(by.id('new-message-view-close')).tap();
- await waitFor(element(by.id('rooms-list-view'))).toExist().withTimeout(2000);
- await expect(element(by.id('rooms-list-view'))).toExist();
- await element(by.id('rooms-list-view-create-channel')).tap();
- await waitFor(element(by.id('new-message-view'))).toExist().withTimeout(2000);
- await expect(element(by.id('new-message-view'))).toExist();
+
+ await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(5000);
+
+ await tryTapping(element(by.id('rooms-list-view-create-channel')), 3000);
+ //await element(by.id('rooms-list-view-create-channel')).tap();
+ await waitFor(element(by.id('new-message-view'))).toExist().withTimeout(5000);
});
it('should search user and navigate', async() => {
await element(by.id('new-message-view-search')).replaceText('rocket.cat');
await waitFor(element(by.id('new-message-view-item-rocket.cat'))).toExist().withTimeout(60000);
- await expect(element(by.id('new-message-view-item-rocket.cat'))).toExist();
await element(by.id('new-message-view-item-rocket.cat')).tap();
await waitFor(element(by.id('room-view'))).toExist().withTimeout(10000);
- await expect(element(by.id('room-view'))).toExist();
await waitFor(element(by.id('room-view-title-rocket.cat'))).toExist().withTimeout(60000);
- await expect(element(by.id('room-view-title-rocket.cat'))).toExist();
await tapBack();
- await waitFor(element(by.id('rooms-list-view'))).toExist().withTimeout(2000);
+ await waitFor(element(by.id('rooms-list-view'))).toExist().withTimeout(5000);
});
it('should navigate to select users', async() => {
await element(by.id('rooms-list-view-create-channel')).tap();
- await waitFor(element(by.id('new-message-view'))).toExist().withTimeout(2000);
- await expect(element(by.id('new-message-view'))).toExist();
- await sleep(1000);
+ await waitFor(element(by.id('new-message-view'))).toExist().withTimeout(5000);
await element(by.id('new-message-view-create-channel')).tap();
- await waitFor(element(by.id('select-users-view'))).toExist().withTimeout(2000);
- await expect(element(by.id('select-users-view'))).toExist();
+ await waitFor(element(by.id('select-users-view'))).toExist().withTimeout(5000);
});
})
});
@@ -63,35 +62,31 @@ describe('Create room screen', () => {
describe('Select Users', async() => {
it('should search users', async() => {
await element(by.id('select-users-view-search')).replaceText('rocket.cat');
- await waitFor(element(by.id(`select-users-view-item-rocket.cat`))).toExist().withTimeout(10000);
- await expect(element(by.id(`select-users-view-item-rocket.cat`))).toExist();
+ await waitFor(element(by.id(`select-users-view-item-rocket.cat`))).toBeVisible().withTimeout(10000);
});
it('should select/unselect user', async() => {
await element(by.id('select-users-view-item-rocket.cat')).tap();
- await waitFor(element(by.id('selected-user-rocket.cat'))).toExist().withTimeout(5000);
- await expect(element(by.id('selected-user-rocket.cat'))).toExist();
+ await waitFor(element(by.id('selected-user-rocket.cat'))).toBeVisible().withTimeout(10000);
await element(by.id('selected-user-rocket.cat')).tap();
- await waitFor(element(by.id('selected-user-rocket.cat'))).toBeNotVisible().withTimeout(5000);
- await expect(element(by.id('selected-user-rocket.cat'))).toBeNotVisible();
+ await waitFor(element(by.id('selected-user-rocket.cat'))).toBeNotVisible().withTimeout(10000);
await element(by.id('select-users-view-item-rocket.cat')).tap();
- await waitFor(element(by.id('selected-user-rocket.cat'))).toExist().withTimeout(5000);
+ await waitFor(element(by.id('selected-user-rocket.cat'))).toBeVisible().withTimeout(10000);
});
it('should navigate to create channel view', async() => {
await element(by.id('selected-users-view-submit')).tap();
- await waitFor(element(by.id('create-channel-view'))).toExist().withTimeout(5000);
- await expect(element(by.id('create-channel-view'))).toExist();
+ await waitFor(element(by.id('create-channel-view'))).toExist().withTimeout(10000);
});
})
describe('Create Channel', async() => {
describe('Render', async() => {
it('should render all fields', async() => {
- await expect(element(by.id('create-channel-name'))).toExist();
- await expect(element(by.id('create-channel-type'))).toExist();
- await expect(element(by.id('create-channel-readonly'))).toExist();
- await expect(element(by.id('create-channel-broadcast'))).toExist();
+ await expect(element(by.id('create-channel-name'))).toBeVisible();
+ await expect(element(by.id('create-channel-type'))).toBeVisible();
+ await expect(element(by.id('create-channel-readonly'))).toBeVisible();
+ await expect(element(by.id('create-channel-broadcast'))).toBeVisible();
})
})
@@ -108,61 +103,51 @@ describe('Create room screen', () => {
const room = `public${ data.random }`;
await element(by.id('create-channel-name')).replaceText(room);
await element(by.id('create-channel-type')).tap();
- await sleep(1000);
await element(by.id('create-channel-submit')).tap();
await waitFor(element(by.id('room-view'))).toExist().withTimeout(60000);
await expect(element(by.id('room-view'))).toExist();
await waitFor(element(by.id(`room-view-title-${ room }`))).toExist().withTimeout(60000);
await expect(element(by.id(`room-view-title-${ room }`))).toExist();
await tapBack();
- await waitFor(element(by.id('rooms-list-view'))).toExist().withTimeout(2000);
+ await waitFor(element(by.id('rooms-list-view'))).toExist().withTimeout(10000);
await waitFor(element(by.id(`rooms-list-view-item-${ room }`))).toExist().withTimeout(60000);
await expect(element(by.id(`rooms-list-view-item-${ room }`))).toExist();
});
it('should create private room', async() => {
const room = `private${ data.random }`;
- await waitFor(element(by.id('rooms-list-view'))).toExist().withTimeout(2000);
- // await device.launchApp({ newInstance: true });
- await sleep(1000);
+ await waitFor(element(by.id('rooms-list-view'))).toExist().withTimeout(5000);
await element(by.id('rooms-list-view-create-channel')).tap();
- await waitFor(element(by.id('new-message-view'))).toExist().withTimeout(2000);
- await sleep(1000);
+ await waitFor(element(by.id('new-message-view'))).toExist().withTimeout(5000);
await element(by.id('new-message-view-create-channel')).tap();
- await waitFor(element(by.id('select-users-view'))).toExist().withTimeout(2000);
- await sleep(1000);
+ await waitFor(element(by.id('select-users-view'))).toExist().withTimeout(5000);
await element(by.id('select-users-view-item-rocket.cat')).tap();
await waitFor(element(by.id('selected-user-rocket.cat'))).toExist().withTimeout(5000);
await element(by.id('selected-users-view-submit')).tap();
await waitFor(element(by.id('create-channel-view'))).toExist().withTimeout(5000);
await element(by.id('create-channel-name')).replaceText(room);
- await sleep(1000);
await element(by.id('create-channel-submit')).tap();
await waitFor(element(by.id('room-view'))).toExist().withTimeout(60000);
await expect(element(by.id('room-view'))).toExist();
await waitFor(element(by.id(`room-view-title-${ room }`))).toExist().withTimeout(60000);
await expect(element(by.id(`room-view-title-${ room }`))).toExist();
await tapBack();
- await waitFor(element(by.id('rooms-list-view'))).toExist().withTimeout(2000);
+ await waitFor(element(by.id('rooms-list-view'))).toExist().withTimeout(5000);
await waitFor(element(by.id(`rooms-list-view-item-${ room }`))).toExist().withTimeout(60000);
await expect(element(by.id(`rooms-list-view-item-${ room }`))).toExist();
});
it('should create empty room', async() => {
const room = `empty${ data.random }`;
- await waitFor(element(by.id('rooms-list-view'))).toExist().withTimeout(2000);
+ await waitFor(element(by.id('rooms-list-view'))).toExist().withTimeout(10000);
// await device.launchApp({ newInstance: true });
- await sleep(1000);
await element(by.id('rooms-list-view-create-channel')).tap();
- await waitFor(element(by.id('new-message-view'))).toExist().withTimeout(2000);
- await sleep(1000);
+ await waitFor(element(by.id('new-message-view'))).toExist().withTimeout(5000);
await element(by.id('new-message-view-create-channel')).tap();
- await waitFor(element(by.id('select-users-view'))).toExist().withTimeout(2000);
- await sleep(1000);
+ await waitFor(element(by.id('select-users-view'))).toExist().withTimeout(5000);
await element(by.id('selected-users-view-submit')).tap();
- await waitFor(element(by.id('create-channel-view'))).toExist().withTimeout(5000);
+ await waitFor(element(by.id('create-channel-view'))).toExist().withTimeout(10000);
await element(by.id('create-channel-name')).replaceText(room);
- await sleep(1000);
await element(by.id('create-channel-submit')).tap();
await waitFor(element(by.id('room-view'))).toExist().withTimeout(60000);
await expect(element(by.id('room-view'))).toExist();
diff --git a/e2e/tests/room/02-room.spec.js b/e2e/tests/room/02-room.spec.js
index 86fdfc21f..00d5d434d 100644
--- a/e2e/tests/room/02-room.spec.js
+++ b/e2e/tests/room/02-room.spec.js
@@ -2,27 +2,29 @@ const {
device, expect, element, by, waitFor
} = require('detox');
const data = require('../../data');
-const { mockMessage, tapBack, sleep, searchRoom } = require('../../helpers/app');
+const { navigateToLogin, login, mockMessage, tapBack, sleep, searchRoom, starMessage, pinMessage, dismissReviewNag, tryTapping } = require('../../helpers/app');
-async function navigateToRoom() {
- await searchRoom(`private${ data.random }`);
- await waitFor(element(by.id(`rooms-list-view-item-private${ data.random }`))).toExist().withTimeout(60000);
- await element(by.id(`rooms-list-view-item-private${ data.random }`)).tap();
+async function navigateToRoom(roomName) {
+ await device.launchApp({ permissions: { notifications: 'YES' }, delete: true });
+ await navigateToLogin();
+ await login(data.users.regular.username, data.users.regular.password);
+ await searchRoom(`${ roomName }`);
+ await waitFor(element(by.id(`rooms-list-view-item-${ roomName }`))).toExist().withTimeout(60000);
+ await element(by.id(`rooms-list-view-item-${ roomName }`)).tap();
await waitFor(element(by.id('room-view'))).toBeVisible().withTimeout(5000);
}
describe('Room screen', () => {
- const mainRoom = `private${ data.random }`;
+ const mainRoom = data.groups.private.name;
before(async() => {
- await navigateToRoom();
+ await navigateToRoom(mainRoom);
});
describe('Render', async() => {
it('should have room screen', async() => {
await expect(element(by.id('room-view'))).toExist();
await waitFor(element(by.id(`room-view-title-${ mainRoom }`))).toExist().withTimeout(5000);
- await expect(element(by.id(`room-view-title-${ mainRoom }`))).toExist();
});
// Render - Header
@@ -69,22 +71,15 @@ describe('Room screen', () => {
await expect(element(by.label(`${ data.random }message`)).atIndex(0)).toExist();
});
- it('should ask for review', async() => {
- await waitFor(element(by.text('Are you enjoying this app?'))).toExist().withTimeout(60000);
- await expect(element(by.text('Are you enjoying this app?')).atIndex(0)).toExist();
- await element(by.label('No').and(by.type('_UIAlertControllerActionView'))).tap(); // Tap `no` on ask for review alert
- })
it('should show/hide emoji keyboard', async () => {
if (device.getPlatform() === 'android') {
await element(by.id('messagebox-open-emoji')).tap();
await waitFor(element(by.id('messagebox-keyboard-emoji'))).toExist().withTimeout(10000);
- await expect(element(by.id('messagebox-keyboard-emoji'))).toExist();
await expect(element(by.id('messagebox-close-emoji'))).toExist();
await expect(element(by.id('messagebox-open-emoji'))).toBeNotVisible();
await element(by.id('messagebox-close-emoji')).tap();
await waitFor(element(by.id('messagebox-keyboard-emoji'))).toBeNotVisible().withTimeout(10000);
- await expect(element(by.id('messagebox-keyboard-emoji'))).toBeNotVisible();
await expect(element(by.id('messagebox-close-emoji'))).toBeNotVisible();
await expect(element(by.id('messagebox-open-emoji'))).toExist();
}
@@ -94,10 +89,8 @@ describe('Room screen', () => {
await element(by.id('messagebox-input')).tap();
await element(by.id('messagebox-input')).typeText(':joy');
await waitFor(element(by.id('messagebox-container'))).toExist().withTimeout(10000);
- await expect(element(by.id('messagebox-container'))).toExist();
await element(by.id('messagebox-input')).clearText();
await waitFor(element(by.id('messagebox-container'))).toBeNotVisible().withTimeout(10000);
- await expect(element(by.id('messagebox-container'))).toBeNotVisible();
});
it('should show and tap on emoji autocomplete', async() => {
@@ -105,8 +98,6 @@ describe('Room screen', () => {
await element(by.id('messagebox-input')).replaceText(':');
await element(by.id('messagebox-input')).typeText('joy'); // workaround for number keyboard
await waitFor(element(by.id('messagebox-container'))).toExist().withTimeout(10000);
- await expect(element(by.id('messagebox-container'))).toExist();
- await sleep(1000);
await element(by.id('mention-item-joy')).tap();
await expect(element(by.id('messagebox-input'))).toHaveText(':joy: ');
await element(by.id('messagebox-input')).clearText();
@@ -116,25 +107,22 @@ describe('Room screen', () => {
const username = data.users.regular.username
await element(by.id('messagebox-input')).tap();
await element(by.id('messagebox-input')).typeText(`@${ username }`);
- await waitFor(element(by.id('messagebox-container'))).toExist().withTimeout(60000);
- await expect(element(by.id('messagebox-container'))).toExist();
- await sleep(1000);
- await element(by.id(`mention-item-${ username }`)).tap();
+ await waitFor(element(by.id('messagebox-container'))).toExist().withTimeout(4000);
+ await waitFor(element(by.id(`mention-item-${ username }`))).toBeVisible().withTimeout(4000)
+ await tryTapping(element(by.id(`mention-item-${ username }`)), 2000, true);
await expect(element(by.id('messagebox-input'))).toHaveText(`@${ username } `);
- await element(by.id('messagebox-input')).tap();
+ await tryTapping(element(by.id('messagebox-input')), 2000)
await element(by.id('messagebox-input')).typeText(`${ data.random }mention`);
await element(by.id('messagebox-send-message')).tap();
// await waitFor(element(by.label(`@${ data.user } ${ data.random }mention`)).atIndex(0)).toExist().withTimeout(60000);
- await sleep(2000);
});
it('should show and tap on room autocomplete', async() => {
await element(by.id('messagebox-input')).tap();
await element(by.id('messagebox-input')).typeText('#general');
- await waitFor(element(by.id('messagebox-container'))).toExist().withTimeout(60000);
- await expect(element(by.id('messagebox-container'))).toExist();
- await sleep(1000);
- await element(by.id('mention-item-general')).tap();
+ //await waitFor(element(by.id('messagebox-container'))).toExist().withTimeout(4000);
+ await waitFor(element(by.id('mention-item-general'))).toBeVisible().withTimeout(4000);
+ await tryTapping(element(by.id('mention-item-general')), 2000, true)
await expect(element(by.id('messagebox-input'))).toHaveText('#general ');
await element(by.id('messagebox-input')).clearText();
});
@@ -147,7 +135,6 @@ describe('Room screen', () => {
await expect(element(by.id('action-sheet-handle'))).toBeVisible();
await element(by.id('action-sheet-handle')).swipe('up', 'fast', 0.5);
await element(by.label('Permalink')).tap();
- await sleep(1000);
// TODO: test clipboard
});
@@ -158,28 +145,20 @@ describe('Room screen', () => {
await expect(element(by.id('action-sheet-handle'))).toBeVisible();
await element(by.id('action-sheet-handle')).swipe('up', 'fast', 0.5);
await element(by.label('Copy')).tap();
- await sleep(1000);
// TODO: test clipboard
});
it('should star message', async() => {
- await element(by.label(`${ data.random }message`)).atIndex(0).longPress();
- await expect(element(by.id('action-sheet'))).toExist();
- await expect(element(by.id('action-sheet-handle'))).toBeVisible();
- await element(by.id('action-sheet-handle')).swipe('up', 'fast', 0.5);
- await element(by.label('Star')).tap();
- await sleep(1000);
- await waitFor(element(by.id('action-sheet'))).toNotExist().withTimeout(5000);
+ await starMessage('message')
+ await sleep(1000) //https://github.com/RocketChat/Rocket.Chat.ReactNative/issues/2324
await element(by.label(`${ data.random }message`)).atIndex(0).longPress();
await expect(element(by.id('action-sheet'))).toExist();
await expect(element(by.id('action-sheet-handle'))).toBeVisible();
await element(by.id('action-sheet-handle')).swipe('up', 'fast', 0.5);
await waitFor(element(by.label('Unstar'))).toBeVisible().withTimeout(2000);
- await expect(element(by.label('Unstar'))).toBeVisible();
await element(by.id('action-sheet-backdrop')).tap();
- await sleep(1000);
});
it('should react to message', async() => {
@@ -189,14 +168,10 @@ describe('Room screen', () => {
await element(by.id('action-sheet-handle')).swipe('up', 'fast', 0.5);
await element(by.id('add-reaction')).tap();
await waitFor(element(by.id('reaction-picker'))).toBeVisible().withTimeout(2000);
- await expect(element(by.id('reaction-picker'))).toBeVisible();
await element(by.id('reaction-picker-😃')).tap();
await waitFor(element(by.id('reaction-picker-grinning'))).toExist().withTimeout(2000);
- await expect(element(by.id('reaction-picker-grinning'))).toExist();
await element(by.id('reaction-picker-grinning')).tap();
await waitFor(element(by.id('message-reaction-:grinning:'))).toExist().withTimeout(60000);
- await expect(element(by.id('message-reaction-:grinning:'))).toExist();
- await sleep(1000);
});
it('should react to message with frequently used emoji', async() => {
@@ -205,30 +180,27 @@ describe('Room screen', () => {
await expect(element(by.id('action-sheet-handle'))).toBeVisible();
await element(by.id('action-sheet-handle')).swipe('up', 'fast', 0.5);
await waitFor(element(by.id('message-actions-emoji-+1'))).toBeVisible().withTimeout(2000);
- await expect(element(by.id('message-actions-emoji-+1'))).toBeVisible();
await element(by.id('message-actions-emoji-+1')).tap();
await waitFor(element(by.id('message-reaction-:+1:'))).toBeVisible().withTimeout(60000);
- await expect(element(by.id('message-reaction-:+1:'))).toBeVisible();
- await sleep(1000);
});
it('should show reaction picker on add reaction button pressed and have frequently used emoji', async() => {
await element(by.id('message-add-reaction')).tap();
await waitFor(element(by.id('reaction-picker'))).toExist().withTimeout(2000);
- await expect(element(by.id('reaction-picker'))).toExist();
await waitFor(element(by.id('reaction-picker-grinning'))).toExist().withTimeout(2000);
- await expect(element(by.id('reaction-picker-grinning'))).toExist();
await element(by.id('reaction-picker-😃')).tap();
await waitFor(element(by.id('reaction-picker-grimacing'))).toExist().withTimeout(2000);
await element(by.id('reaction-picker-grimacing')).tap();
await waitFor(element(by.id('message-reaction-:grimacing:'))).toExist().withTimeout(60000);
- await sleep(1000);
});
+
+ it('should ask for review', async() => {
+ await dismissReviewNag() //TODO: Create a proper test for this elsewhere.
+ })
it('should remove reaction', async() => {
await element(by.id('message-reaction-:grinning:')).tap();
await waitFor(element(by.id('message-reaction-:grinning:'))).toBeNotVisible().withTimeout(60000);
- await expect(element(by.id('message-reaction-:grinning:'))).toBeNotVisible();
});
it('should edit message', async() => {
@@ -241,7 +213,6 @@ describe('Room screen', () => {
await element(by.id('messagebox-input')).typeText('ed');
await element(by.id('messagebox-send-message')).tap();
await waitFor(element(by.label(`${ data.random }edited (edited)`)).atIndex(0)).toExist().withTimeout(60000);
- await expect(element(by.label(`${ data.random }edited (edited)`)).atIndex(0)).toExist();
});
it('should quote message', async() => {
@@ -253,46 +224,39 @@ describe('Room screen', () => {
await element(by.label('Quote')).tap();
await element(by.id('messagebox-input')).typeText(`${ data.random }quoted`);
await element(by.id('messagebox-send-message')).tap();
- await sleep(1000);
// TODO: test if quote was sent
});
it('should pin message', async() => {
- await waitFor(element(by.label(`${ data.random }edited (edited)`)).atIndex(0)).toExist();
- await element(by.label(`${ data.random }edited (edited)`)).atIndex(0).longPress();
- await expect(element(by.id('action-sheet'))).toExist();
- await expect(element(by.id('action-sheet-handle'))).toBeVisible();
- await element(by.id('action-sheet-handle')).swipe('up', 'fast', 0.5);
- await element(by.label('Pin')).tap();
- await waitFor(element(by.id('action-sheet'))).toNotExist().withTimeout(5000);
- await sleep(1500);
-
- await waitFor(element(by.label(`${ data.random }edited (edited)`)).atIndex(0)).toBeVisible();
- await element(by.label(`${ data.random }edited (edited)`)).atIndex(0).longPress();
- await expect(element(by.id('action-sheet'))).toExist();
+ await mockMessage('pin')
+ await pinMessage('pin')
+
+ await waitFor(element(by.label(`${ data.random }pin`)).atIndex(0)).toBeVisible().withTimeout(2000);
+ await waitFor(element(by.label('Message pinned')).atIndex(0)).toBeVisible().withTimeout(2000);
+ await element(by.label(`${ data.random }pin`)).atIndex(0).longPress();
+ await waitFor(element(by.id('action-sheet'))).toExist().withTimeout(1000);
await expect(element(by.id('action-sheet-handle'))).toBeVisible();
await element(by.id('action-sheet-handle')).swipe('up', 'fast', 0.5);
await waitFor(element(by.label('Unpin'))).toBeVisible().withTimeout(2000);
- await expect(element(by.label('Unpin'))).toBeVisible();
await element(by.id('action-sheet-backdrop')).tap();
});
it('should delete message', async() => {
- await waitFor(element(by.label(`${ data.random }quoted`)).atIndex(0)).toBeVisible();
- await element(by.label(`${ data.random }quoted`)).atIndex(0).longPress();
+ await mockMessage('delete')
+
+ await waitFor(element(by.label(`${ data.random }delete`)).atIndex(0)).toBeVisible();
+ await element(by.label(`${ data.random }delete`)).atIndex(0).longPress();
await expect(element(by.id('action-sheet'))).toExist();
await expect(element(by.id('action-sheet-handle'))).toBeVisible();
await element(by.id('action-sheet-handle')).swipe('up', 'fast', 0.5);
await element(by.label('Delete')).tap();
const deleteAlertMessage = 'You will not be able to recover this message!';
- await waitFor(element(by.text(deleteAlertMessage)).atIndex(0)).toExist().withTimeout(10000);
- await expect(element(by.text(deleteAlertMessage)).atIndex(0)).toExist();
+ await waitFor(element(by.text(deleteAlertMessage)).atIndex(0)).toExist().withTimeout(10000);
await element(by.text('Delete')).tap();
- await sleep(1000);
- await expect(element(by.label(`${ data.random }quoted`)).atIndex(0)).toNotExist();
+ await waitFor(element(by.label(`${ data.random }delete`)).atIndex(0)).toNotExist().withTimeout(2000);
});
});
@@ -317,7 +281,6 @@ describe('Room screen', () => {
await waitFor(element(by.id(`room-view-title-${ thread }`))).toExist().withTimeout(5000);
await expect(element(by.id(`room-view-title-${ thread }`))).toExist();
await tapBack();
- await sleep(1000);
});
it('should toggle follow thread', async() => {
@@ -332,10 +295,13 @@ describe('Room screen', () => {
await waitFor(element(by.id('room-view-header-unfollow'))).toExist().withTimeout(60000);
await expect(element(by.id('room-view-header-unfollow'))).toExist();
await tapBack();
- await sleep(1000);
});
it('should navigate to thread from thread name', async() => {
+ await waitFor(element(by.id('room-view-header-actions').and(by.label(` ${ mainRoom }`)))).toBeVisible().withTimeout(2000);
+ await waitFor(element(by.id('room-view-header-actions').and(by.label(` ${ data.random }thread`)))).toBeNotVisible().withTimeout(2000);
+ await sleep(500) //TODO: Find a better way to wait for the animation to finish and the messagebox-input to be available and usable :(
+
await mockMessage('dummymessagebetweenthethread');
await element(by.label(thread)).atIndex(0).longPress();
await expect(element(by.id('action-sheet'))).toExist();
@@ -352,10 +318,10 @@ describe('Room screen', () => {
await waitFor(element(by.id(`room-view-title-${ thread }`))).toExist().withTimeout(5000);
await expect(element(by.id(`room-view-title-${ thread }`))).toExist();
await tapBack();
- await sleep(1000);
});
it('should navigate to thread from threads view', async() => {
+ await waitFor(element(by.id('room-view-header-threads'))).toExist().withTimeout(1000);
await element(by.id('room-view-header-threads')).tap();
await waitFor(element(by.id('thread-messages-view'))).toExist().withTimeout(5000);
await expect(element(by.id('thread-messages-view'))).toExist();
diff --git a/e2e/tests/room/03-roomactions.spec.js b/e2e/tests/room/03-roomactions.spec.js
index dd5c8defd..43ff025ef 100644
--- a/e2e/tests/room/03-roomactions.spec.js
+++ b/e2e/tests/room/03-roomactions.spec.js
@@ -2,7 +2,7 @@ const {
device, expect, element, by, waitFor
} = require('detox');
const data = require('../../data');
-const { tapBack, sleep, searchRoom } = require('../../helpers/app');
+const { navigateToLogin, login, tapBack, sleep, searchRoom, mockMessage, starMessage, pinMessage } = require('../../helpers/app');
const scrollDown = 200;
@@ -11,13 +11,12 @@ async function navigateToRoomActions(type) {
if (type === 'd') {
room = 'rocket.cat';
} else {
- room = `private${ data.random }`;
+ room = data.groups.private.name;
}
await searchRoom(room);
await waitFor(element(by.id(`rooms-list-view-item-${ room }`))).toExist().withTimeout(60000);
await element(by.id(`rooms-list-view-item-${ room }`)).tap();
await waitFor(element(by.id('room-view'))).toExist().withTimeout(2000);
- await sleep(1000);
await element(by.id('room-view-header-actions')).tap();
await waitFor(element(by.id('room-actions-view'))).toExist().withTimeout(5000);
}
@@ -25,7 +24,6 @@ async function navigateToRoomActions(type) {
async function backToActions() {
await tapBack();
await waitFor(element(by.id('room-actions-view'))).toExist().withTimeout(2000);
- await expect(element(by.id('room-actions-view'))).toExist();
}
async function backToRoomsList() {
@@ -36,10 +34,16 @@ async function backToRoomsList() {
}
describe('Room actions screen', () => {
+
+ before(async() => {
+ await device.launchApp({ permissions: { notifications: 'YES' }, delete: true });
+ await navigateToLogin();
+ await login(data.users.regular.username, data.users.regular.password);
+ });
+
describe('Render', async() => {
describe('Direct', async() => {
before(async() => {
- await device.launchApp({ newInstance: true });
await navigateToRoomActions('d');
});
@@ -197,65 +201,89 @@ describe('Room actions screen', () => {
it('should show mentioned messages', async() => {
await element(by.id('room-actions-mentioned')).tap();
await waitFor(element(by.id('mentioned-messages-view'))).toExist().withTimeout(2000);
- await expect(element(by.id('mentioned-messages-view'))).toExist();
// await waitFor(element(by.text(` ${ data.random }mention`))).toExist().withTimeout(60000);
- // await expect(element(by.text(` ${ data.random }mention`))).toExist();
await backToActions();
});
it('should show starred message and unstar it', async() => {
+
+ //Go back to room and send a message
+ await tapBack();
+ await mockMessage('messageToStar');
+
+ //Star the message
+ await starMessage('messageToStar')
+
+ //Back into Room Actions
+ await element(by.id('room-view-header-actions')).tap();
+ await waitFor(element(by.id('room-actions-view'))).toExist().withTimeout(5000);
+
+ //Go to starred messages
await element(by.id('room-actions-starred')).tap();
await waitFor(element(by.id('starred-messages-view'))).toExist().withTimeout(2000);
- await sleep(1000);
- await waitFor(element(by.label(`${ data.random }message`).withAncestor(by.id('starred-messages-view')))).toBeVisible().withTimeout(60000);
- await expect(element(by.label(`${ data.random }message`).withAncestor(by.id('starred-messages-view')))).toBeVisible();
- await element(by.label(`${ data.random }message`).withAncestor(by.id('starred-messages-view'))).longPress();
-
+ await waitFor(element(by.label(`${ data.random }messageToStar`).withAncestor(by.id('starred-messages-view')))).toBeVisible().withTimeout(60000);
+
+ //Unstar message
+ await element(by.label(`${ data.random }messageToStar`).withAncestor(by.id('starred-messages-view'))).longPress();
await expect(element(by.id('action-sheet'))).toExist();
await expect(element(by.id('action-sheet-handle'))).toBeVisible();
await element(by.label('Unstar')).tap();
- await waitFor(element(by.label(`${ data.random }message`).withAncestor(by.id('starred-messages-view')))).toBeNotVisible().withTimeout(60000);
- await expect(element(by.label(`${ data.random }message`).withAncestor(by.id('starred-messages-view')))).toBeNotVisible();
+ await waitFor(element(by.label(`${ data.random }messageToStar`).withAncestor(by.id('starred-messages-view')))).toBeNotVisible().withTimeout(60000);
await backToActions();
});
it('should show pinned message and unpin it', async() => {
+
+ //Go back to room and send a message
+ await tapBack();
+ await mockMessage('messageToPin');
+
+ //Pin the message
+ await pinMessage('messageToPin')
+
+ //Back into Room Actions
+ await element(by.id('room-view-header-actions')).tap();
+ await waitFor(element(by.id('room-actions-view'))).toExist().withTimeout(5000);
+
await waitFor(element(by.id('room-actions-pinned'))).toExist();
await element(by.id('room-actions-pinned')).tap();
await waitFor(element(by.id('pinned-messages-view'))).toExist().withTimeout(2000);
- await sleep(1000);
- await waitFor(element(by.label(`${ data.random }edited (edited)`).withAncestor(by.id('pinned-messages-view')))).toBeVisible().withTimeout(60000);
- await expect(element(by.label(`${ data.random }edited (edited)`).withAncestor(by.id('pinned-messages-view')))).toBeVisible();
- await element(by.label(`${ data.random }edited (edited)`).withAncestor(by.id('pinned-messages-view'))).longPress();
+ await waitFor(element(by.label(`${ data.random }messageToPin`).withAncestor(by.id('pinned-messages-view')))).toBeVisible().withTimeout(60000);
+ await element(by.label(`${ data.random }messageToPin`).withAncestor(by.id('pinned-messages-view'))).longPress();
await expect(element(by.id('action-sheet'))).toExist();
await expect(element(by.id('action-sheet-handle'))).toBeVisible();
await element(by.label('Unpin')).tap();
- await waitFor(element(by.label(`${ data.random }edited (edited)`).withAncestor(by.id('pinned-messages-view')))).toBeNotVisible().withTimeout(60000);
- await expect(element(by.label(`${ data.random }edited (edited)`).withAncestor(by.id('pinned-messages-view')))).toBeNotVisible();
+ await waitFor(element(by.label(`${ data.random }messageToPin`).withAncestor(by.id('pinned-messages-view')))).toBeNotVisible().withTimeout(60000);
await backToActions();
});
it('should search and find a message', async() => {
+
+ //Go back to room and send a message
+ await tapBack();
+ await mockMessage('messageToFind');
+
+ //Back into Room Actions
+ await element(by.id('room-view-header-actions')).tap();
+ await waitFor(element(by.id('room-actions-view'))).toExist().withTimeout(5000);
+
await element(by.id('room-actions-search')).tap();
await waitFor(element(by.id('search-messages-view'))).toExist().withTimeout(2000);
await expect(element(by.id('search-message-view-input'))).toExist();
- await element(by.id('search-message-view-input')).replaceText(`/${ data.random }message/`);
- await waitFor(element(by.label(`${ data.random }message`).withAncestor(by.id('search-messages-view')))).toExist().withTimeout(60000);
- await expect(element(by.label(`${ data.random }message`).withAncestor(by.id('search-messages-view')))).toExist();
+ await element(by.id('search-message-view-input')).replaceText(`/${ data.random }messageToFind/`);
+ await waitFor(element(by.label(`${ data.random }messageToFind`).withAncestor(by.id('search-messages-view')))).toExist().withTimeout(60000);
await backToActions();
});
});
describe('Notification', async() => {
it('should navigate to notification preference view', async() => {
- await waitFor(element(by.id('room-actions-notifications'))).toExist();
- await expect(element(by.id('room-actions-notifications'))).toExist();
+ await waitFor(element(by.id('room-actions-notifications'))).toExist().withTimeout(2000);
await element(by.id('room-actions-notifications')).tap();
await waitFor(element(by.id('notification-preference-view'))).toExist().withTimeout(2000);
- await expect(element(by.id('notification-preference-view'))).toExist();
});
it('should have receive notification option', async() => {
@@ -271,30 +299,25 @@ describe('Room actions screen', () => {
});
it('should have push notification option', async() => {
- await waitFor(element(by.id('notification-preference-view-push-notification'))).toExist();
- await expect(element(by.id('notification-preference-view-push-notification'))).toExist();
+ await waitFor(element(by.id('notification-preference-view-push-notification'))).toExist().withTimeout(4000);
});
it('should have notification audio option', async() => {
- await waitFor(element(by.id('notification-preference-view-audio'))).toExist();
- await expect(element(by.id('notification-preference-view-audio'))).toExist();
+ await waitFor(element(by.id('notification-preference-view-audio'))).toExist().withTimeout(4000);
});
it('should have notification sound option', async() => {
// Ugly hack to scroll on detox
await element(by.type('UIScrollView')).atIndex(1).scrollTo('bottom');
- await waitFor(element(by.id('notification-preference-view-sound'))).toExist();
- await expect(element(by.id('notification-preference-view-sound'))).toExist();
+ await waitFor(element(by.id('notification-preference-view-sound'))).toExist().withTimeout(4000);
});
it('should have notification duration option', async() => {
- await waitFor(element(by.id('notification-preference-view-notification-duration'))).toExist();
- await expect(element(by.id('notification-preference-view-notification-duration'))).toExist();
+ await waitFor(element(by.id('notification-preference-view-notification-duration'))).toExist().withTimeout(4000);
});
it('should have email alert option', async() => {
- await waitFor(element(by.id('notification-preference-view-email-alert'))).toExist();
- await expect(element(by.id('notification-preference-view-email-alert'))).toExist();
+ await waitFor(element(by.id('notification-preference-view-email-alert'))).toExist().withTimeout(4000);
});
after(async() => {
@@ -309,34 +332,29 @@ describe('Room actions screen', () => {
const user = data.users.alternate
it('should tap on leave channel and raise alert', async() => {
- await waitFor(element(by.id('room-actions-leave-channel'))).toExist();
- await expect(element(by.id('room-actions-leave-channel'))).toExist();
+ await waitFor(element(by.id('room-actions-leave-channel'))).toExist().withTimeout(2000);
await element(by.id('room-actions-leave-channel')).tap();
await waitFor(element(by.text('Yes, leave it!'))).toExist().withTimeout(2000);
- await expect(element(by.text('Yes, leave it!'))).toExist();
await element(by.text('Yes, leave it!')).tap();
- await waitFor(element(by.text('You are the last owner. Please set new owner before leaving the room.'))).toExist().withTimeout(60000);
- await expect(element(by.text('You are the last owner. Please set new owner before leaving the room.'))).toExist();
+ await waitFor(element(by.text('You are the last owner. Please set new owner before leaving the room.'))).toExist().withTimeout(8000);
await element(by.text('OK')).tap();
await waitFor(element(by.id('room-actions-view'))).toExist().withTimeout(2000);
});
it('should add user to the room', async() => {
- await waitFor(element(by.id('room-actions-add-user'))).toExist();
+ await waitFor(element(by.id('room-actions-add-user'))).toExist().withTimeout(4000);
await element(by.id('room-actions-add-user')).tap();
+ await waitFor(element(by.id('select-users-view-search'))).toExist().withTimeout(4000);
await element(by.id('select-users-view-search')).tap();
await element(by.id('select-users-view-search')).replaceText(user.username);
- await waitFor(element(by.id(`select-users-view-item-${ user.username }`))).toExist().withTimeout(60000);
- await expect(element(by.id(`select-users-view-item-${ user.username }`))).toExist();
+ await waitFor(element(by.id(`select-users-view-item-${ user.username }`))).toExist().withTimeout(10000);
await element(by.id(`select-users-view-item-${ user.username }`)).tap();
await waitFor(element(by.id(`selected-user-${ user.username }`))).toExist().withTimeout(5000);
- await expect(element(by.id(`selected-user-${ user.username }`))).toExist();
await element(by.id('selected-users-view-submit')).tap();
await waitFor(element(by.id('room-actions-view'))).toExist().withTimeout(2000);
await element(by.id('room-actions-members')).tap();
await element(by.id('room-members-view-toggle-status')).tap();
await waitFor(element(by.id(`room-members-view-item-${ user.username }`))).toExist().withTimeout(60000);
- await expect(element(by.id(`room-members-view-item-${ user.username }`))).toExist();
await backToActions(1);
});
@@ -344,26 +362,20 @@ describe('Room actions screen', () => {
before(async() => {
await element(by.id('room-actions-members')).tap();
await waitFor(element(by.id('room-members-view'))).toExist().withTimeout(2000);
- await expect(element(by.id('room-members-view'))).toExist();
});
it('should show all users', async() => {
- await sleep(1000);
await element(by.id('room-members-view-toggle-status')).tap();
await waitFor(element(by.id(`room-members-view-item-${ user.username }`))).toExist().withTimeout(60000);
- await expect(element(by.id(`room-members-view-item-${ user.username }`))).toExist();
});
it('should filter user', async() => {
await waitFor(element(by.id(`room-members-view-item-${ user.username }`))).toExist().withTimeout(60000);
- await expect(element(by.id(`room-members-view-item-${ user.username }`))).toExist();
await element(by.id('room-members-view-search')).replaceText('rocket');
await waitFor(element(by.id(`room-members-view-item-${ user.username }`))).toBeNotVisible().withTimeout(60000);
- await expect(element(by.id(`room-members-view-item-${ user.username }`))).toBeNotVisible();
await element(by.id('room-members-view-search')).tap();
await element(by.id('room-members-view-search')).clearText('');
await waitFor(element(by.id(`room-members-view-item-${ user.username }`))).toExist().withTimeout(60000);
- await expect(element(by.id(`room-members-view-item-${ user.username }`))).toExist();
});
// FIXME: mute/unmute isn't working
@@ -391,9 +403,7 @@ describe('Room actions screen', () => {
await waitFor(element(by.id(`room-members-view-item-${ user.username }`))).toExist().withTimeout(5000);
await element(by.id(`room-members-view-item-${ user.username }`)).tap();
await waitFor(element(by.id('room-view'))).toExist().withTimeout(60000);
- await expect(element(by.id('room-view'))).toExist();
await waitFor(element(by.id(`room-view-title-${ user.username }`))).toExist().withTimeout(60000);
- await expect(element(by.id(`room-view-title-${ user.username }`))).toExist();
await tapBack();
await waitFor(element(by.id('rooms-list-view'))).toExist().withTimeout(2000);
});
@@ -407,13 +417,10 @@ describe('Room actions screen', () => {
it('should block/unblock user', async() => {
await waitFor(element(by.id('room-actions-block-user'))).toExist();
- await sleep(1000);
await element(by.id('room-actions-block-user')).tap();
await waitFor(element(by.label('Unblock user'))).toExist().withTimeout(60000);
- await expect(element(by.label('Unblock user'))).toExist();
await element(by.id('room-actions-block-user')).tap();
await waitFor(element(by.label('Block user'))).toExist().withTimeout(60000);
- await expect(element(by.label('Block user'))).toExist();
});
});
});
diff --git a/e2e/tests/room/04-roominfo.spec.js b/e2e/tests/room/04-roominfo.spec.js
index 35a45441b..9382f16cf 100644
--- a/e2e/tests/room/04-roominfo.spec.js
+++ b/e2e/tests/room/04-roominfo.spec.js
@@ -2,23 +2,23 @@ const {
device, expect, element, by, waitFor
} = require('detox');
const data = require('../../data');
-const { tapBack, sleep, searchRoom } = require('../../helpers/app');
+const { navigateToLogin, login, tapBack, sleep, searchRoom } = require('../../helpers/app');
+
+const privateRoomName = data.groups.private.name
async function navigateToRoomInfo(type) {
let room;
if (type === 'd') {
room = 'rocket.cat';
} else {
- room = `private${ data.random }`;
+ room = privateRoomName;
}
await searchRoom(room);
await waitFor(element(by.id(`rooms-list-view-item-${ room }`))).toExist().withTimeout(60000);
await element(by.id(`rooms-list-view-item-${ room }`)).tap();
await waitFor(element(by.id('room-view'))).toExist().withTimeout(2000);
- await sleep(1000);
await element(by.id('room-view-header-actions')).tap();
await waitFor(element(by.id('room-actions-view'))).toExist().withTimeout(5000);
- await sleep(1000);
await element(by.id('room-actions-info')).tap();
await waitFor(element(by.id('room-info-view'))).toExist().withTimeout(2000);
}
@@ -28,13 +28,19 @@ async function waitForToast() {
// await expect(element(by.id('toast'))).toExist();
// await waitFor(element(by.id('toast'))).toBeNotVisible().withTimeout(10000);
// await expect(element(by.id('toast'))).toBeNotVisible();
- await sleep(5000);
+ await sleep(1);
}
describe('Room info screen', () => {
+
+ before(async() => {
+ await device.launchApp({ permissions: { notifications: 'YES' }, delete: true });
+ await navigateToLogin();
+ await login(data.users.regular.username, data.users.regular.password);
+ });
+
describe('Direct', async() => {
before(async() => {
- await device.launchApp({ newInstance: true });
await navigateToRoomInfo('d');
});
@@ -42,11 +48,16 @@ describe('Room info screen', () => {
await expect(element(by.id('room-info-view'))).toExist();
await expect(element(by.id('room-info-view-name'))).toExist();
});
+
+ after(async() => {
+ await tapBack()
+ await tapBack()
+ await tapBack()
+ })
});
describe('Channel/Group', async() => {
before(async() => {
- await device.launchApp({ newInstance: true });
await navigateToRoomInfo('c');
});
@@ -78,7 +89,6 @@ describe('Room info screen', () => {
describe('Render Edit', async() => {
before(async() => {
- await sleep(1000);
await waitFor(element(by.id('room-info-view-edit-button'))).toExist().withTimeout(10000);
await element(by.id('room-info-view-edit-button')).tap();
await waitFor(element(by.id('room-info-edit-view'))).toExist().withTimeout(2000);
@@ -141,7 +151,6 @@ describe('Room info screen', () => {
});
describe('Usage', async() => {
- const room = `private${ data.random }`;
// it('should enter "invalid name" and get error', async() => {
// await element(by.type('UIScrollView')).atIndex(1).swipe('down');
// await element(by.id('room-info-edit-view-name')).replaceText('invalid name');
@@ -155,22 +164,17 @@ describe('Room info screen', () => {
// });
it('should change room name', async() => {
- await element(by.id('room-info-edit-view-name')).replaceText(`${ room }new`);
+ await element(by.id('room-info-edit-view-name')).replaceText(`${ privateRoomName }new`);
await element(by.type('UIScrollView')).atIndex(1).swipe('up');
await element(by.id('room-info-edit-view-submit')).tap();
- await sleep(5000);
await tapBack();
await waitFor(element(by.id('room-info-view'))).toExist().withTimeout(2000);
- await sleep(1000);
- await expect(element(by.id('room-info-view-name'))).toHaveLabel(`${ room }new`);
+ await expect(element(by.id('room-info-view-name'))).toHaveLabel(`${ privateRoomName }new`);
// change name to original
await element(by.id('room-info-view-edit-button')).tap();
- await sleep(1000);
await waitFor(element(by.id('room-info-edit-view'))).toExist().withTimeout(2000);
- await sleep(1000);
- await element(by.id('room-info-edit-view-name')).replaceText(`${ room }`);
+ await element(by.id('room-info-edit-view-name')).replaceText(`${ privateRoomName }`);
await element(by.type('UIScrollView')).atIndex(1).swipe('up');
- await sleep(1000);
await element(by.id('room-info-edit-view-submit')).tap();
await waitForToast();
await element(by.type('UIScrollView')).atIndex(1).swipe('down');
@@ -184,14 +188,11 @@ describe('Room info screen', () => {
await element(by.id('room-info-edit-view-password')).replaceText('abc');
await element(by.type('UIScrollView')).atIndex(1).swipe('up');
await element(by.id('room-info-edit-view-t')).tap();
- await sleep(1000);
- await element(by.id('room-info-edit-view-ro')).tap();
- await sleep(1000);
+ await element(by.id('room-info-edit-view-ro')).longPress(); //https://github.com/facebook/react-native/issues/28032
await element(by.id('room-info-edit-view-react-when-ro')).tap();
- await sleep(1000);
await element(by.id('room-info-edit-view-reset')).tap();
// after reset
- await expect(element(by.id('room-info-edit-view-name'))).toHaveText(room);
+ await expect(element(by.id('room-info-edit-view-name'))).toHaveText(privateRoomName);
await expect(element(by.id('room-info-edit-view-description'))).toHaveText('');
await expect(element(by.id('room-info-edit-view-topic'))).toHaveText('');
await expect(element(by.id('room-info-edit-view-announcement'))).toHaveText('');
@@ -203,55 +204,45 @@ describe('Room info screen', () => {
});
it('should change room description', async() => {
- await sleep(1000);
await element(by.id('room-info-edit-view-description')).replaceText('new description');
await element(by.type('UIScrollView')).atIndex(1).swipe('up');
await element(by.id('room-info-edit-view-submit')).tap();
await waitForToast();
await tapBack();
await waitFor(element(by.id('room-info-view'))).toExist().withTimeout(2000);
- await sleep(1000);
await expect(element(by.label('new description').withAncestor(by.id('room-info-view-description')))).toExist();
});
it('should change room topic', async() => {
- await sleep(1000);
await waitFor(element(by.id('room-info-view-edit-button'))).toExist().withTimeout(10000);
await element(by.id('room-info-view-edit-button')).tap();
await waitFor(element(by.id('room-info-edit-view'))).toExist().withTimeout(2000);
- await sleep(1000);
await element(by.id('room-info-edit-view-topic')).replaceText('new topic');
await element(by.type('UIScrollView')).atIndex(1).swipe('up');
await element(by.id('room-info-edit-view-submit')).tap();
await waitForToast();
await tapBack();
await waitFor(element(by.id('room-info-view'))).toExist().withTimeout(2000);
- await sleep(1000);
await expect(element(by.label('new topic').withAncestor(by.id('room-info-view-topic')))).toExist();
});
it('should change room announcement', async() => {
- await sleep(1000);
await waitFor(element(by.id('room-info-view-edit-button'))).toExist().withTimeout(10000);
await element(by.id('room-info-view-edit-button')).tap();
await waitFor(element(by.id('room-info-edit-view'))).toExist().withTimeout(2000);
- await sleep(1000);
await element(by.id('room-info-edit-view-announcement')).replaceText('new announcement');
await element(by.type('UIScrollView')).atIndex(1).swipe('up');
await element(by.id('room-info-edit-view-submit')).tap();
await waitForToast();
await tapBack();
await waitFor(element(by.id('room-info-view'))).toExist().withTimeout(2000);
- await sleep(1000);
await expect(element(by.label('new announcement').withAncestor(by.id('room-info-view-announcement')))).toExist();
});
it('should change room password', async() => {
- await sleep(1000);
await waitFor(element(by.id('room-info-view-edit-button'))).toExist().withTimeout(10000);
await element(by.id('room-info-view-edit-button')).tap();
await waitFor(element(by.id('room-info-edit-view'))).toExist().withTimeout(2000);
- await sleep(1000);
await element(by.type('UIScrollView')).atIndex(1).swipe('up');
await element(by.id('room-info-edit-view-password')).replaceText('password');
await element(by.id('room-info-edit-view-submit')).tap();
@@ -259,7 +250,6 @@ describe('Room info screen', () => {
});
it('should change room type', async() => {
- await sleep(1000);
await element(by.type('UIScrollView')).atIndex(1).swipe('up');
await element(by.id('room-info-edit-view-t')).tap();
await element(by.id('room-info-edit-view-submit')).tap();
@@ -282,14 +272,11 @@ describe('Room info screen', () => {
// });
it('should archive room', async() => {
- await sleep(1000);
await element(by.type('UIScrollView')).atIndex(1).swipe('up');
await element(by.id('room-info-edit-view-archive')).tap();
await waitFor(element(by.text('Yes, archive it!'))).toExist().withTimeout(5000);
- await expect(element(by.text('Yes, archive it!'))).toExist();
await element(by.text('Yes, archive it!')).tap();
await waitFor(element(by.id('room-info-edit-view-unarchive'))).toExist().withTimeout(60000);
- await expect(element(by.id('room-info-edit-view-unarchive'))).toExist();
await expect(element(by.id('room-info-edit-view-archive'))).toBeNotVisible();
// TODO: needs permission to unarchive
// await element(by.id('room-info-edit-view-archive')).tap();
@@ -301,16 +288,12 @@ describe('Room info screen', () => {
});
it('should delete room', async() => {
- await sleep(1000);
await element(by.type('UIScrollView')).atIndex(1).swipe('up');
await element(by.id('room-info-edit-view-delete')).tap();
await waitFor(element(by.text('Yes, delete it!'))).toExist().withTimeout(5000);
- await expect(element(by.text('Yes, delete it!'))).toExist();
await element(by.text('Yes, delete it!')).tap();
await waitFor(element(by.id('rooms-list-view'))).toExist().withTimeout(10000);
- await sleep(2000);
- await waitFor(element(by.id(`rooms-list-view-item-${ room }`))).toBeNotVisible().withTimeout(60000);
- await expect(element(by.id(`rooms-list-view-item-${ room }`))).toBeNotVisible();
+ await waitFor(element(by.id(`rooms-list-view-item-${ privateRoomName }`))).toBeNotVisible().withTimeout(60000);
});
});
});
diff --git a/ios/NotificationService/Info.plist b/ios/NotificationService/Info.plist
new file mode 100644
index 000000000..496dfc6ce
--- /dev/null
+++ b/ios/NotificationService/Info.plist
@@ -0,0 +1,33 @@
+
+
+
+
+ AppGroup
+ group.ios.chat.rocket
+ CFBundleDevelopmentRegion
+ $(DEVELOPMENT_LANGUAGE)
+ CFBundleDisplayName
+ NotificationService
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ $(PRODUCT_BUNDLE_PACKAGE_TYPE)
+ CFBundleShortVersionString
+ $(MARKETING_VERSION)
+ CFBundleVersion
+ 1
+ NSExtension
+
+ NSExtensionPointIdentifier
+ com.apple.usernotifications.service
+ NSExtensionPrincipalClass
+ $(PRODUCT_MODULE_NAME).NotificationService
+
+
+
diff --git a/ios/NotificationService/NotificationService.entitlements b/ios/NotificationService/NotificationService.entitlements
new file mode 100644
index 000000000..f48f06fbc
--- /dev/null
+++ b/ios/NotificationService/NotificationService.entitlements
@@ -0,0 +1,10 @@
+
+
+
+
+ com.apple.security.application-groups
+
+ group.ios.chat.rocket
+
+
+
diff --git a/ios/NotificationService/NotificationService.swift b/ios/NotificationService/NotificationService.swift
new file mode 100644
index 000000000..bb5352a59
--- /dev/null
+++ b/ios/NotificationService/NotificationService.swift
@@ -0,0 +1,155 @@
+import CoreLocation
+import UserNotifications
+
+struct PushResponse: Decodable {
+ let success: Bool
+ let data: Data
+
+ struct Data: Decodable {
+ let notification: Notification
+
+ struct Notification: Decodable {
+ let notId: Int
+ let title: String
+ let text: String
+ let payload: Payload
+
+ struct Payload: Decodable, Encodable {
+ let host: String
+ let rid: String?
+ let type: String?
+ let sender: Sender?
+ let messageId: String
+ let notificationType: String?
+ let name: String?
+ let messageType: String?
+
+ struct Sender: Decodable, Encodable {
+ let _id: String
+ let username: String
+ let name: String?
+ }
+ }
+ }
+ }
+}
+
+class NotificationService: UNNotificationServiceExtension {
+
+ var contentHandler: ((UNNotificationContent) -> Void)?
+ var bestAttemptContent: UNMutableNotificationContent?
+
+ var retryCount = 0
+ var retryTimeout = [1.0, 3.0, 5.0, 10.0]
+
+ override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
+ self.contentHandler = contentHandler
+ bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
+
+ if let bestAttemptContent = bestAttemptContent {
+ let ejson = (bestAttemptContent.userInfo["ejson"] as? String ?? "").data(using: .utf8)!
+ guard let data = try? (JSONDecoder().decode(PushResponse.Data.Notification.Payload.self, from: ejson)) else {
+ return
+ }
+
+ let notificationType = data.notificationType ?? ""
+
+ // If the notification have the content at her payload, show it
+ if notificationType != "message-id-only" {
+ contentHandler(bestAttemptContent)
+ return
+ }
+
+ let suiteName = Bundle.main.object(forInfoDictionaryKey: "AppGroup") as! String
+ let userDefaults = UserDefaults(suiteName: suiteName)
+
+ var server = data.host
+ if (server.last == "/") {
+ server.removeLast()
+ }
+ let msgId = data.messageId
+
+ let userId = userDefaults?.string(forKey: "reactnativemeteor_usertoken-\(server)") ?? ""
+ let token = userDefaults?.string(forKey: "reactnativemeteor_usertoken-\(userId)") ?? ""
+
+ if userId.isEmpty || token.isEmpty {
+ contentHandler(bestAttemptContent)
+ return
+ }
+
+ var urlComponents = URLComponents(string: "\(server)/api/v1/push.get")!
+ let queryItems = [URLQueryItem(name: "id", value: msgId)]
+ urlComponents.queryItems = queryItems
+
+ var request = URLRequest(url: urlComponents.url!)
+ request.httpMethod = "GET"
+ request.addValue(userId, forHTTPHeaderField: "x-user-id")
+ request.addValue(token, forHTTPHeaderField: "x-auth-token")
+
+ runRequest(request: request, bestAttemptContent: bestAttemptContent, contentHandler: contentHandler)
+ }
+ }
+
+ func runRequest(request: URLRequest, bestAttemptContent: UNMutableNotificationContent, contentHandler: @escaping (UNNotificationContent) -> Void) {
+ let task = URLSession.shared.dataTask(with: request) {(data, response, error) in
+
+ func retryRequest() {
+ // if we can try again
+ if self.retryCount < self.retryTimeout.count {
+ // Try again after X seconds
+ DispatchQueue.main.asyncAfter(deadline: .now() + self.retryTimeout[self.retryCount], execute: {
+ self.runRequest(request: request, bestAttemptContent: bestAttemptContent, contentHandler: contentHandler)
+ self.retryCount += 1
+ })
+ }
+ }
+
+ // If some error happened
+ if error != nil {
+ retryRequest()
+
+ // Check if the request did successfully
+ } else if let response = response as? HTTPURLResponse {
+ // if it not was successfully
+ if response.statusCode != 200 {
+ retryRequest()
+
+ // If the response status is 200
+ } else {
+ // Process data
+ if let data = data {
+ // Parse data of response
+ let push = try? (JSONDecoder().decode(PushResponse.self, from: data))
+ if let push = push {
+ if push.success {
+ bestAttemptContent.title = push.data.notification.title
+ bestAttemptContent.body = push.data.notification.text
+
+ let payload = try? (JSONEncoder().encode(push.data.notification.payload))
+ if let payload = payload {
+ bestAttemptContent.userInfo["ejson"] = String(data: payload, encoding: .utf8) ?? "{}"
+ }
+
+ // Show notification with the content modified
+ contentHandler(bestAttemptContent)
+ return
+ }
+ }
+ }
+ retryRequest()
+ }
+ }
+ }
+
+ task.resume()
+ }
+
+ override func serviceExtensionTimeWillExpire() {
+ // Called just before the extension will be terminated by the system.
+ // Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used.
+ if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent {
+ contentHandler(bestAttemptContent)
+ }
+ }
+
+}
diff --git a/ios/Podfile b/ios/Podfile
index 35f65a777..c1eca515e 100644
--- a/ios/Podfile
+++ b/ios/Podfile
@@ -1,143 +1,23 @@
platform :ios, '11.0'
+require_relative '../node_modules/react-native/scripts/react_native_pods'
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
require_relative '../node_modules/react-native-unimodules/cocoapods.rb'
-def add_flipper_pods!(versions = {})
- versions['Flipper'] ||= '~> 0.33.1'
- versions['DoubleConversion'] ||= '1.1.7'
- versions['Flipper-Folly'] ||= '~> 2.1'
- versions['Flipper-Glog'] ||= '0.3.6'
- versions['Flipper-PeerTalk'] ||= '~> 0.0.4'
- versions['Flipper-RSocket'] ||= '~> 1.0'
-
- pod 'FlipperKit', versions['Flipper'], :configuration => 'Debug'
- pod 'FlipperKit/FlipperKitLayoutPlugin', versions['Flipper'], :configuration => 'Debug'
- pod 'FlipperKit/SKIOSNetworkPlugin', versions['Flipper'], :configuration => 'Debug'
- pod 'FlipperKit/FlipperKitUserDefaultsPlugin', versions['Flipper'], :configuration => 'Debug'
- pod 'FlipperKit/FlipperKitReactPlugin', versions['Flipper'], :configuration => 'Debug'
-
- # List all transitive dependencies for FlipperKit pods
- # to avoid them being linked in Release builds
- pod 'Flipper', versions['Flipper'], :configuration => 'Debug'
- pod 'Flipper-DoubleConversion', versions['DoubleConversion'], :configuration => 'Debug'
- pod 'Flipper-Folly', versions['Flipper-Folly'], :configuration => 'Debug'
- pod 'Flipper-Glog', versions['Flipper-Glog'], :configuration => 'Debug'
- pod 'Flipper-PeerTalk', versions['Flipper-PeerTalk'], :configuration => 'Debug'
- pod 'Flipper-RSocket', versions['Flipper-RSocket'], :configuration => 'Debug'
- pod 'FlipperKit/Core', versions['Flipper'], :configuration => 'Debug'
- pod 'FlipperKit/CppBridge', versions['Flipper'], :configuration => 'Debug'
- pod 'FlipperKit/FBCxxFollyDynamicConvert', versions['Flipper'], :configuration => 'Debug'
- pod 'FlipperKit/FBDefines', versions['Flipper'], :configuration => 'Debug'
- pod 'FlipperKit/FKPortForwarding', versions['Flipper'], :configuration => 'Debug'
- pod 'FlipperKit/FlipperKitHighlightOverlay', versions['Flipper'], :configuration => 'Debug'
- pod 'FlipperKit/FlipperKitLayoutTextSearchable', versions['Flipper'], :configuration => 'Debug'
- pod 'FlipperKit/FlipperKitNetworkPlugin', versions['Flipper'], :configuration => 'Debug'
-end
-
-# Post Install processing for Flipper
-def flipper_post_install(installer)
- installer.pods_project.targets.each do |target|
- if target.name == 'YogaKit'
- target.build_configurations.each do |config|
- config.build_settings['SWIFT_VERSION'] = '4.1'
- end
- end
- end
- file_name = Dir.glob("*.xcodeproj")[0]
- app_project = Xcodeproj::Project.open(file_name)
- app_project.native_targets.each do |target|
- target.build_configurations.each do |config|
- cflags = config.build_settings['OTHER_CFLAGS'] || '$(inherited) '
- unless cflags.include? '-DFB_SONARKIT_ENABLED=1'
- puts 'Adding -DFB_SONARKIT_ENABLED=1 in OTHER_CFLAGS...'
- cflags << '-DFB_SONARKIT_ENABLED=1'
- end
- config.build_settings['OTHER_CFLAGS'] = cflags
- end
- app_project.save
- end
- installer.pods_project.save
+def all_pods
+ config = use_native_modules!
+ use_unimodules!
+ use_react_native!(:path => config["reactNativePath"])
+ use_flipper!
end
target 'RocketChatRN' do
- pod 'FBLazyVector', :path => "../node_modules/react-native/Libraries/FBLazyVector"
- pod 'FBReactNativeSpec', :path => "../node_modules/react-native/Libraries/FBReactNativeSpec"
- pod 'RCTRequired', :path => "../node_modules/react-native/Libraries/RCTRequired"
- pod 'RCTTypeSafety', :path => "../node_modules/react-native/Libraries/TypeSafety"
- pod 'React', :path => '../node_modules/react-native/'
- pod 'React-Core', :path => '../node_modules/react-native/'
- pod 'React-CoreModules', :path => '../node_modules/react-native/React/CoreModules'
- pod 'React-Core/DevSupport', :path => '../node_modules/react-native/'
- pod 'React-RCTActionSheet', :path => '../node_modules/react-native/Libraries/ActionSheetIOS'
- pod 'React-RCTAnimation', :path => '../node_modules/react-native/Libraries/NativeAnimation'
- pod 'React-RCTBlob', :path => '../node_modules/react-native/Libraries/Blob'
- pod 'React-RCTImage', :path => '../node_modules/react-native/Libraries/Image'
- pod 'React-RCTLinking', :path => '../node_modules/react-native/Libraries/LinkingIOS'
- pod 'React-RCTNetwork', :path => '../node_modules/react-native/Libraries/Network'
- pod 'React-RCTSettings', :path => '../node_modules/react-native/Libraries/Settings'
- pod 'React-RCTText', :path => '../node_modules/react-native/Libraries/Text'
- pod 'React-RCTVibration', :path => '../node_modules/react-native/Libraries/Vibration'
- pod 'React-Core/RCTWebSocket', :path => '../node_modules/react-native/'
-
- pod 'React-cxxreact', :path => '../node_modules/react-native/ReactCommon/cxxreact'
- pod 'React-jsi', :path => '../node_modules/react-native/ReactCommon/jsi'
- pod 'React-jsiexecutor', :path => '../node_modules/react-native/ReactCommon/jsiexecutor'
- pod 'React-jsinspector', :path => '../node_modules/react-native/ReactCommon/jsinspector'
- pod 'ReactCommon/callinvoker', :path => "../node_modules/react-native/ReactCommon"
- pod 'ReactCommon/turbomodule/core', :path => "../node_modules/react-native/ReactCommon"
- pod 'Yoga', :path => '../node_modules/react-native/ReactCommon/yoga', :modular_headers => true
-
- pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec'
- pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec'
- pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec'
-
- use_native_modules!
- use_unimodules!
+ all_pods
end
target 'ShareRocketChatRN' do
- pod 'FBLazyVector', :path => "../node_modules/react-native/Libraries/FBLazyVector"
- pod 'FBReactNativeSpec', :path => "../node_modules/react-native/Libraries/FBReactNativeSpec"
- pod 'RCTRequired', :path => "../node_modules/react-native/Libraries/RCTRequired"
- pod 'RCTTypeSafety', :path => "../node_modules/react-native/Libraries/TypeSafety"
- pod 'React', :path => '../node_modules/react-native/'
- pod 'React-Core', :path => '../node_modules/react-native/'
- pod 'React-CoreModules', :path => '../node_modules/react-native/React/CoreModules'
- pod 'React-Core/DevSupport', :path => '../node_modules/react-native/'
- pod 'React-RCTActionSheet', :path => '../node_modules/react-native/Libraries/ActionSheetIOS'
- pod 'React-RCTAnimation', :path => '../node_modules/react-native/Libraries/NativeAnimation'
- pod 'React-RCTBlob', :path => '../node_modules/react-native/Libraries/Blob'
- pod 'React-RCTImage', :path => '../node_modules/react-native/Libraries/Image'
- pod 'React-RCTLinking', :path => '../node_modules/react-native/Libraries/LinkingIOS'
- pod 'React-RCTNetwork', :path => '../node_modules/react-native/Libraries/Network'
- pod 'React-RCTSettings', :path => '../node_modules/react-native/Libraries/Settings'
- pod 'React-RCTText', :path => '../node_modules/react-native/Libraries/Text'
- pod 'React-RCTVibration', :path => '../node_modules/react-native/Libraries/Vibration'
- pod 'React-Core/RCTWebSocket', :path => '../node_modules/react-native/'
-
- pod 'React-cxxreact', :path => '../node_modules/react-native/ReactCommon/cxxreact'
- pod 'React-jsi', :path => '../node_modules/react-native/ReactCommon/jsi'
- pod 'React-jsiexecutor', :path => '../node_modules/react-native/ReactCommon/jsiexecutor'
- pod 'React-jsinspector', :path => '../node_modules/react-native/ReactCommon/jsinspector'
- pod 'ReactCommon/callinvoker', :path => "../node_modules/react-native/ReactCommon"
- pod 'ReactCommon/turbomodule/core', :path => "../node_modules/react-native/ReactCommon"
- pod 'Yoga', :path => '../node_modules/react-native/ReactCommon/yoga', :modular_headers => true
-
- pod 'JitsiMeetSDK', :git => 'https://github.com/RocketChat/jitsi-meet-ios-sdk-releases.git'
-
- pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec'
- pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec'
- pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec'
-
- use_native_modules!
- use_unimodules!
+ all_pods
end
-# Enables Flipper.
-#
-# Note that if you have use_frameworks! enabled, Flipper will not work and
-# you should disable these next few lines.
-add_flipper_pods!
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
@@ -145,4 +25,4 @@ post_install do |installer|
end
end
flipper_post_install(installer)
-end
+end
\ No newline at end of file
diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index fc8055335..c72afcec8 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -1,89 +1,95 @@
PODS:
- boost-for-react-native (1.63.0)
- - BugsnagReactNative (2.23.7):
- - BugsnagReactNative/Core (= 2.23.7)
+ - BugsnagReactNative (2.23.10):
+ - BugsnagReactNative/Core (= 2.23.10)
- React
- - BugsnagReactNative/Core (2.23.7):
+ - BugsnagReactNative/Core (2.23.10):
- React
- CocoaAsyncSocket (7.6.4)
- CocoaLibEvent (1.0.0)
- - Crashlytics (3.14.0):
- - Fabric (~> 1.10.2)
- DoubleConversion (1.1.6)
- EXAppleAuthentication (2.2.1):
- UMCore
- - EXAV (8.1.0):
+ - EXAV (8.2.1):
- UMCore
- UMFileSystemInterface
- UMPermissionsInterface
- - EXConstants (9.0.0):
+ - EXConstants (9.1.1):
- UMConstantsInterface
- UMCore
- - EXFileSystem (8.1.0):
+ - EXFileSystem (9.0.1):
- UMCore
- UMFileSystemInterface
- - EXHaptics (8.1.0):
+ - EXHaptics (8.2.1):
- UMCore
- - EXImageLoader (1.0.1):
+ - EXImageLoader (1.1.1):
- React-Core
- UMCore
- UMImageLoaderInterface
- - EXKeepAwake (8.1.0):
+ - EXKeepAwake (8.2.1):
- UMCore
- - EXLocalAuthentication (9.0.0):
+ - EXLocalAuthentication (9.2.0):
- UMConstantsInterface
- UMCore
- - EXPermissions (8.1.0):
+ - EXPermissions (9.0.1):
- UMCore
- UMPermissionsInterface
- - EXVideoThumbnails (4.1.1):
+ - EXVideoThumbnails (4.2.1):
- UMCore
- UMFileSystemInterface
- - EXWebBrowser (8.2.1):
+ - EXWebBrowser (8.3.1):
- UMCore
- - Fabric (1.10.2)
- - FBLazyVector (0.62.2)
- - FBReactNativeSpec (0.62.2):
- - Folly (= 2018.10.22.00)
- - RCTRequired (= 0.62.2)
- - RCTTypeSafety (= 0.62.2)
- - React-Core (= 0.62.2)
- - React-jsi (= 0.62.2)
- - ReactCommon/turbomodule/core (= 0.62.2)
- - Firebase/Core (6.24.0):
+ - FBLazyVector (0.63.1)
+ - FBReactNativeSpec (0.63.1):
+ - Folly (= 2020.01.13.00)
+ - RCTRequired (= 0.63.1)
+ - RCTTypeSafety (= 0.63.1)
+ - React-Core (= 0.63.1)
+ - React-jsi (= 0.63.1)
+ - ReactCommon/turbomodule/core (= 0.63.1)
+ - Firebase/Analytics (6.27.1):
+ - Firebase/Core
+ - Firebase/Core (6.27.1):
- Firebase/CoreOnly
- - FirebaseAnalytics (= 6.5.0)
- - Firebase/CoreOnly (6.24.0):
- - FirebaseCore (= 6.7.0)
- - FirebaseAnalytics (6.5.0):
- - FirebaseCore (~> 6.7)
- - FirebaseInstallations (~> 1.2)
- - GoogleAppMeasurement (= 6.5.0)
+ - FirebaseAnalytics (= 6.6.2)
+ - Firebase/CoreOnly (6.27.1):
+ - FirebaseCore (= 6.8.1)
+ - Firebase/Crashlytics (6.27.1):
+ - Firebase/CoreOnly
+ - FirebaseCrashlytics (~> 4.2.0)
+ - FirebaseAnalytics (6.6.2):
+ - FirebaseCore (~> 6.8)
+ - FirebaseInstallations (~> 1.4)
+ - GoogleAppMeasurement (= 6.6.2)
- GoogleUtilities/AppDelegateSwizzler (~> 6.0)
- GoogleUtilities/MethodSwizzler (~> 6.0)
- GoogleUtilities/Network (~> 6.0)
- "GoogleUtilities/NSData+zlib (~> 6.0)"
- nanopb (~> 1.30905.0)
- - FirebaseCore (6.7.0):
+ - FirebaseCore (6.8.1):
- FirebaseCoreDiagnostics (~> 1.3)
- - FirebaseCoreDiagnosticsInterop (~> 1.2)
- GoogleUtilities/Environment (~> 6.5)
- GoogleUtilities/Logger (~> 6.5)
- - FirebaseCoreDiagnostics (1.3.0):
- - FirebaseCoreDiagnosticsInterop (~> 1.2)
+ - FirebaseCoreDiagnostics (1.4.0):
- GoogleDataTransportCCTSupport (~> 3.1)
- GoogleUtilities/Environment (~> 6.5)
- GoogleUtilities/Logger (~> 6.5)
- nanopb (~> 1.30905.0)
- - FirebaseCoreDiagnosticsInterop (1.2.0)
- - FirebaseInstallations (1.2.0):
- - FirebaseCore (~> 6.6)
- - GoogleUtilities/Environment (~> 6.6)
- - GoogleUtilities/UserDefaults (~> 6.6)
+ - FirebaseCrashlytics (4.2.0):
+ - FirebaseCore (~> 6.8)
+ - FirebaseInstallations (~> 1.1)
+ - GoogleDataTransport (~> 6.1)
+ - GoogleDataTransportCCTSupport (~> 3.1)
+ - nanopb (~> 1.30905.0)
- PromisesObjC (~> 1.2)
- - Flipper (0.33.1):
- - Flipper-Folly (~> 2.1)
- - Flipper-RSocket (~> 1.0)
+ - FirebaseInstallations (1.5.0):
+ - FirebaseCore (~> 6.8)
+ - GoogleUtilities/Environment (~> 6.7)
+ - GoogleUtilities/UserDefaults (~> 6.7)
+ - PromisesObjC (~> 1.2)
+ - Flipper (0.41.5):
+ - Flipper-Folly (~> 2.2)
+ - Flipper-RSocket (~> 1.1)
- Flipper-DoubleConversion (1.1.7)
- Flipper-Folly (2.2.0):
- boost-for-react-native
@@ -95,76 +101,76 @@ PODS:
- Flipper-PeerTalk (0.0.4)
- Flipper-RSocket (1.1.0):
- Flipper-Folly (~> 2.2)
- - FlipperKit (0.33.1):
- - FlipperKit/Core (= 0.33.1)
- - FlipperKit/Core (0.33.1):
- - Flipper (~> 0.33.1)
+ - FlipperKit (0.41.5):
+ - FlipperKit/Core (= 0.41.5)
+ - FlipperKit/Core (0.41.5):
+ - Flipper (~> 0.41.5)
- FlipperKit/CppBridge
- FlipperKit/FBCxxFollyDynamicConvert
- FlipperKit/FBDefines
- FlipperKit/FKPortForwarding
- - FlipperKit/CppBridge (0.33.1):
- - Flipper (~> 0.33.1)
- - FlipperKit/FBCxxFollyDynamicConvert (0.33.1):
- - Flipper-Folly (~> 2.1)
- - FlipperKit/FBDefines (0.33.1)
- - FlipperKit/FKPortForwarding (0.33.1):
+ - FlipperKit/CppBridge (0.41.5):
+ - Flipper (~> 0.41.5)
+ - FlipperKit/FBCxxFollyDynamicConvert (0.41.5):
+ - Flipper-Folly (~> 2.2)
+ - FlipperKit/FBDefines (0.41.5)
+ - FlipperKit/FKPortForwarding (0.41.5):
- CocoaAsyncSocket (~> 7.6)
- Flipper-PeerTalk (~> 0.0.4)
- - FlipperKit/FlipperKitHighlightOverlay (0.33.1)
- - FlipperKit/FlipperKitLayoutPlugin (0.33.1):
+ - FlipperKit/FlipperKitHighlightOverlay (0.41.5)
+ - FlipperKit/FlipperKitLayoutPlugin (0.41.5):
- FlipperKit/Core
- FlipperKit/FlipperKitHighlightOverlay
- FlipperKit/FlipperKitLayoutTextSearchable
- YogaKit (~> 1.18)
- - FlipperKit/FlipperKitLayoutTextSearchable (0.33.1)
- - FlipperKit/FlipperKitNetworkPlugin (0.33.1):
+ - FlipperKit/FlipperKitLayoutTextSearchable (0.41.5)
+ - FlipperKit/FlipperKitNetworkPlugin (0.41.5):
- FlipperKit/Core
- - FlipperKit/FlipperKitReactPlugin (0.33.1):
+ - FlipperKit/FlipperKitReactPlugin (0.41.5):
- FlipperKit/Core
- - FlipperKit/FlipperKitUserDefaultsPlugin (0.33.1):
+ - FlipperKit/FlipperKitUserDefaultsPlugin (0.41.5):
- FlipperKit/Core
- - FlipperKit/SKIOSNetworkPlugin (0.33.1):
+ - FlipperKit/SKIOSNetworkPlugin (0.41.5):
- FlipperKit/Core
- FlipperKit/FlipperKitNetworkPlugin
- - Folly (2018.10.22.00):
+ - Folly (2020.01.13.00):
- boost-for-react-native
- DoubleConversion
- - Folly/Default (= 2018.10.22.00)
+ - Folly/Default (= 2020.01.13.00)
- glog
- - Folly/Default (2018.10.22.00):
+ - Folly/Default (2020.01.13.00):
- boost-for-react-native
- DoubleConversion
- glog
- glog (0.3.5)
- - GoogleAppMeasurement (6.5.0):
+ - GoogleAppMeasurement (6.6.2):
- GoogleUtilities/AppDelegateSwizzler (~> 6.0)
- GoogleUtilities/MethodSwizzler (~> 6.0)
- GoogleUtilities/Network (~> 6.0)
- "GoogleUtilities/NSData+zlib (~> 6.0)"
- nanopb (~> 1.30905.0)
- - GoogleDataTransport (6.1.0)
- - GoogleDataTransportCCTSupport (3.1.0):
+ - GoogleDataTransport (6.2.1)
+ - GoogleDataTransportCCTSupport (3.2.0):
- GoogleDataTransport (~> 6.1)
- nanopb (~> 1.30905.0)
- - GoogleUtilities/AppDelegateSwizzler (6.6.0):
+ - GoogleUtilities/AppDelegateSwizzler (6.7.1):
- GoogleUtilities/Environment
- GoogleUtilities/Logger
- GoogleUtilities/Network
- - GoogleUtilities/Environment (6.6.0):
+ - GoogleUtilities/Environment (6.7.1):
- PromisesObjC (~> 1.2)
- - GoogleUtilities/Logger (6.6.0):
+ - GoogleUtilities/Logger (6.7.1):
- GoogleUtilities/Environment
- - GoogleUtilities/MethodSwizzler (6.6.0):
+ - GoogleUtilities/MethodSwizzler (6.7.1):
- GoogleUtilities/Logger
- - GoogleUtilities/Network (6.6.0):
+ - GoogleUtilities/Network (6.7.1):
- GoogleUtilities/Logger
- "GoogleUtilities/NSData+zlib"
- GoogleUtilities/Reachability
- - "GoogleUtilities/NSData+zlib (6.6.0)"
- - GoogleUtilities/Reachability (6.6.0):
+ - "GoogleUtilities/NSData+zlib (6.7.1)"
+ - GoogleUtilities/Reachability (6.7.1):
- GoogleUtilities/Logger
- - GoogleUtilities/UserDefaults (6.6.0):
+ - GoogleUtilities/UserDefaults (6.7.1):
- GoogleUtilities/Logger
- JitsiMeetSDK (2.8.1)
- KeyCommands (2.0.3):
@@ -186,177 +192,180 @@ PODS:
- OpenSSL-Universal (1.0.2.19):
- OpenSSL-Universal/Static (= 1.0.2.19)
- OpenSSL-Universal/Static (1.0.2.19)
- - PromisesObjC (1.2.8)
- - RCTRequired (0.62.2)
- - RCTTypeSafety (0.62.2):
- - FBLazyVector (= 0.62.2)
- - Folly (= 2018.10.22.00)
- - RCTRequired (= 0.62.2)
- - React-Core (= 0.62.2)
- - React (0.62.2):
- - React-Core (= 0.62.2)
- - React-Core/DevSupport (= 0.62.2)
- - React-Core/RCTWebSocket (= 0.62.2)
- - React-RCTActionSheet (= 0.62.2)
- - React-RCTAnimation (= 0.62.2)
- - React-RCTBlob (= 0.62.2)
- - React-RCTImage (= 0.62.2)
- - React-RCTLinking (= 0.62.2)
- - React-RCTNetwork (= 0.62.2)
- - React-RCTSettings (= 0.62.2)
- - React-RCTText (= 0.62.2)
- - React-RCTVibration (= 0.62.2)
- - React-Core (0.62.2):
- - Folly (= 2018.10.22.00)
+ - PromisesObjC (1.2.9)
+ - RCTRequired (0.63.1)
+ - RCTTypeSafety (0.63.1):
+ - FBLazyVector (= 0.63.1)
+ - Folly (= 2020.01.13.00)
+ - RCTRequired (= 0.63.1)
+ - React-Core (= 0.63.1)
+ - React (0.63.1):
+ - React-Core (= 0.63.1)
+ - React-Core/DevSupport (= 0.63.1)
+ - React-Core/RCTWebSocket (= 0.63.1)
+ - React-RCTActionSheet (= 0.63.1)
+ - React-RCTAnimation (= 0.63.1)
+ - React-RCTBlob (= 0.63.1)
+ - React-RCTImage (= 0.63.1)
+ - React-RCTLinking (= 0.63.1)
+ - React-RCTNetwork (= 0.63.1)
+ - React-RCTSettings (= 0.63.1)
+ - React-RCTText (= 0.63.1)
+ - React-RCTVibration (= 0.63.1)
+ - React-callinvoker (0.63.1)
+ - React-Core (0.63.1):
+ - Folly (= 2020.01.13.00)
- glog
- - React-Core/Default (= 0.62.2)
- - React-cxxreact (= 0.62.2)
- - React-jsi (= 0.62.2)
- - React-jsiexecutor (= 0.62.2)
+ - React-Core/Default (= 0.63.1)
+ - React-cxxreact (= 0.63.1)
+ - React-jsi (= 0.63.1)
+ - React-jsiexecutor (= 0.63.1)
- Yoga
- - React-Core/CoreModulesHeaders (0.62.2):
- - Folly (= 2018.10.22.00)
+ - React-Core/CoreModulesHeaders (0.63.1):
+ - Folly (= 2020.01.13.00)
- glog
- React-Core/Default
- - React-cxxreact (= 0.62.2)
- - React-jsi (= 0.62.2)
- - React-jsiexecutor (= 0.62.2)
+ - React-cxxreact (= 0.63.1)
+ - React-jsi (= 0.63.1)
+ - React-jsiexecutor (= 0.63.1)
- Yoga
- - React-Core/Default (0.62.2):
- - Folly (= 2018.10.22.00)
+ - React-Core/Default (0.63.1):
+ - Folly (= 2020.01.13.00)
- glog
- - React-cxxreact (= 0.62.2)
- - React-jsi (= 0.62.2)
- - React-jsiexecutor (= 0.62.2)
+ - React-cxxreact (= 0.63.1)
+ - React-jsi (= 0.63.1)
+ - React-jsiexecutor (= 0.63.1)
- Yoga
- - React-Core/DevSupport (0.62.2):
- - Folly (= 2018.10.22.00)
+ - React-Core/DevSupport (0.63.1):
+ - Folly (= 2020.01.13.00)
- glog
- - React-Core/Default (= 0.62.2)
- - React-Core/RCTWebSocket (= 0.62.2)
- - React-cxxreact (= 0.62.2)
- - React-jsi (= 0.62.2)
- - React-jsiexecutor (= 0.62.2)
- - React-jsinspector (= 0.62.2)
+ - React-Core/Default (= 0.63.1)
+ - React-Core/RCTWebSocket (= 0.63.1)
+ - React-cxxreact (= 0.63.1)
+ - React-jsi (= 0.63.1)
+ - React-jsiexecutor (= 0.63.1)
+ - React-jsinspector (= 0.63.1)
- Yoga
- - React-Core/RCTActionSheetHeaders (0.62.2):
- - Folly (= 2018.10.22.00)
+ - React-Core/RCTActionSheetHeaders (0.63.1):
+ - Folly (= 2020.01.13.00)
- glog
- React-Core/Default
- - React-cxxreact (= 0.62.2)
- - React-jsi (= 0.62.2)
- - React-jsiexecutor (= 0.62.2)
+ - React-cxxreact (= 0.63.1)
+ - React-jsi (= 0.63.1)
+ - React-jsiexecutor (= 0.63.1)
- Yoga
- - React-Core/RCTAnimationHeaders (0.62.2):
- - Folly (= 2018.10.22.00)
+ - React-Core/RCTAnimationHeaders (0.63.1):
+ - Folly (= 2020.01.13.00)
- glog
- React-Core/Default
- - React-cxxreact (= 0.62.2)
- - React-jsi (= 0.62.2)
- - React-jsiexecutor (= 0.62.2)
+ - React-cxxreact (= 0.63.1)
+ - React-jsi (= 0.63.1)
+ - React-jsiexecutor (= 0.63.1)
- Yoga
- - React-Core/RCTBlobHeaders (0.62.2):
- - Folly (= 2018.10.22.00)
+ - React-Core/RCTBlobHeaders (0.63.1):
+ - Folly (= 2020.01.13.00)
- glog
- React-Core/Default
- - React-cxxreact (= 0.62.2)
- - React-jsi (= 0.62.2)
- - React-jsiexecutor (= 0.62.2)
+ - React-cxxreact (= 0.63.1)
+ - React-jsi (= 0.63.1)
+ - React-jsiexecutor (= 0.63.1)
- Yoga
- - React-Core/RCTImageHeaders (0.62.2):
- - Folly (= 2018.10.22.00)
+ - React-Core/RCTImageHeaders (0.63.1):
+ - Folly (= 2020.01.13.00)
- glog
- React-Core/Default
- - React-cxxreact (= 0.62.2)
- - React-jsi (= 0.62.2)
- - React-jsiexecutor (= 0.62.2)
+ - React-cxxreact (= 0.63.1)
+ - React-jsi (= 0.63.1)
+ - React-jsiexecutor (= 0.63.1)
- Yoga
- - React-Core/RCTLinkingHeaders (0.62.2):
- - Folly (= 2018.10.22.00)
+ - React-Core/RCTLinkingHeaders (0.63.1):
+ - Folly (= 2020.01.13.00)
- glog
- React-Core/Default
- - React-cxxreact (= 0.62.2)
- - React-jsi (= 0.62.2)
- - React-jsiexecutor (= 0.62.2)
+ - React-cxxreact (= 0.63.1)
+ - React-jsi (= 0.63.1)
+ - React-jsiexecutor (= 0.63.1)
- Yoga
- - React-Core/RCTNetworkHeaders (0.62.2):
- - Folly (= 2018.10.22.00)
+ - React-Core/RCTNetworkHeaders (0.63.1):
+ - Folly (= 2020.01.13.00)
- glog
- React-Core/Default
- - React-cxxreact (= 0.62.2)
- - React-jsi (= 0.62.2)
- - React-jsiexecutor (= 0.62.2)
+ - React-cxxreact (= 0.63.1)
+ - React-jsi (= 0.63.1)
+ - React-jsiexecutor (= 0.63.1)
- Yoga
- - React-Core/RCTSettingsHeaders (0.62.2):
- - Folly (= 2018.10.22.00)
+ - React-Core/RCTSettingsHeaders (0.63.1):
+ - Folly (= 2020.01.13.00)
- glog
- React-Core/Default
- - React-cxxreact (= 0.62.2)
- - React-jsi (= 0.62.2)
- - React-jsiexecutor (= 0.62.2)
+ - React-cxxreact (= 0.63.1)
+ - React-jsi (= 0.63.1)
+ - React-jsiexecutor (= 0.63.1)
- Yoga
- - React-Core/RCTTextHeaders (0.62.2):
- - Folly (= 2018.10.22.00)
+ - React-Core/RCTTextHeaders (0.63.1):
+ - Folly (= 2020.01.13.00)
- glog
- React-Core/Default
- - React-cxxreact (= 0.62.2)
- - React-jsi (= 0.62.2)
- - React-jsiexecutor (= 0.62.2)
+ - React-cxxreact (= 0.63.1)
+ - React-jsi (= 0.63.1)
+ - React-jsiexecutor (= 0.63.1)
- Yoga
- - React-Core/RCTVibrationHeaders (0.62.2):
- - Folly (= 2018.10.22.00)
+ - React-Core/RCTVibrationHeaders (0.63.1):
+ - Folly (= 2020.01.13.00)
- glog
- React-Core/Default
- - React-cxxreact (= 0.62.2)
- - React-jsi (= 0.62.2)
- - React-jsiexecutor (= 0.62.2)
+ - React-cxxreact (= 0.63.1)
+ - React-jsi (= 0.63.1)
+ - React-jsiexecutor (= 0.63.1)
- Yoga
- - React-Core/RCTWebSocket (0.62.2):
- - Folly (= 2018.10.22.00)
+ - React-Core/RCTWebSocket (0.63.1):
+ - Folly (= 2020.01.13.00)
- glog
- - React-Core/Default (= 0.62.2)
- - React-cxxreact (= 0.62.2)
- - React-jsi (= 0.62.2)
- - React-jsiexecutor (= 0.62.2)
+ - React-Core/Default (= 0.63.1)
+ - React-cxxreact (= 0.63.1)
+ - React-jsi (= 0.63.1)
+ - React-jsiexecutor (= 0.63.1)
- Yoga
- - React-CoreModules (0.62.2):
- - FBReactNativeSpec (= 0.62.2)
- - Folly (= 2018.10.22.00)
- - RCTTypeSafety (= 0.62.2)
- - React-Core/CoreModulesHeaders (= 0.62.2)
- - React-RCTImage (= 0.62.2)
- - ReactCommon/turbomodule/core (= 0.62.2)
- - React-cxxreact (0.62.2):
+ - React-CoreModules (0.63.1):
+ - FBReactNativeSpec (= 0.63.1)
+ - Folly (= 2020.01.13.00)
+ - RCTTypeSafety (= 0.63.1)
+ - React-Core/CoreModulesHeaders (= 0.63.1)
+ - React-jsi (= 0.63.1)
+ - React-RCTImage (= 0.63.1)
+ - ReactCommon/turbomodule/core (= 0.63.1)
+ - React-cxxreact (0.63.1):
- boost-for-react-native (= 1.63.0)
- DoubleConversion
- - Folly (= 2018.10.22.00)
+ - Folly (= 2020.01.13.00)
- glog
- - React-jsinspector (= 0.62.2)
- - React-jsi (0.62.2):
+ - React-callinvoker (= 0.63.1)
+ - React-jsinspector (= 0.63.1)
+ - React-jsi (0.63.1):
- boost-for-react-native (= 1.63.0)
- DoubleConversion
- - Folly (= 2018.10.22.00)
+ - Folly (= 2020.01.13.00)
- glog
- - React-jsi/Default (= 0.62.2)
- - React-jsi/Default (0.62.2):
+ - React-jsi/Default (= 0.63.1)
+ - React-jsi/Default (0.63.1):
- boost-for-react-native (= 1.63.0)
- DoubleConversion
- - Folly (= 2018.10.22.00)
+ - Folly (= 2020.01.13.00)
- glog
- - React-jsiexecutor (0.62.2):
+ - React-jsiexecutor (0.63.1):
- DoubleConversion
- - Folly (= 2018.10.22.00)
+ - Folly (= 2020.01.13.00)
- glog
- - React-cxxreact (= 0.62.2)
- - React-jsi (= 0.62.2)
- - React-jsinspector (0.62.2)
+ - React-cxxreact (= 0.63.1)
+ - React-jsi (= 0.63.1)
+ - React-jsinspector (0.63.1)
- react-native-appearance (0.3.4):
- React
- react-native-background-timer (2.2.0):
- React
- - react-native-cameraroll (1.6.0):
+ - react-native-cameraroll (4.0.0):
- React
- - react-native-document-picker (3.3.3):
+ - react-native-document-picker (3.5.3):
- React
- react-native-jitsi-meet (2.1.1):
- JitsiMeetSDK (= 2.8.1)
@@ -365,71 +374,72 @@ PODS:
- React
- react-native-orientation-locker (1.1.8):
- React
- - react-native-safe-area-context (3.0.2):
+ - react-native-safe-area-context (3.1.1):
- React
- - react-native-slider (2.0.9):
+ - react-native-slider (3.0.2):
- React
- - react-native-webview (9.4.0):
+ - react-native-webview (10.3.2):
- React
- - React-RCTActionSheet (0.62.2):
- - React-Core/RCTActionSheetHeaders (= 0.62.2)
- - React-RCTAnimation (0.62.2):
- - FBReactNativeSpec (= 0.62.2)
- - Folly (= 2018.10.22.00)
- - RCTTypeSafety (= 0.62.2)
- - React-Core/RCTAnimationHeaders (= 0.62.2)
- - ReactCommon/turbomodule/core (= 0.62.2)
- - React-RCTBlob (0.62.2):
- - FBReactNativeSpec (= 0.62.2)
- - Folly (= 2018.10.22.00)
- - React-Core/RCTBlobHeaders (= 0.62.2)
- - React-Core/RCTWebSocket (= 0.62.2)
- - React-jsi (= 0.62.2)
- - React-RCTNetwork (= 0.62.2)
- - ReactCommon/turbomodule/core (= 0.62.2)
- - React-RCTImage (0.62.2):
- - FBReactNativeSpec (= 0.62.2)
- - Folly (= 2018.10.22.00)
- - RCTTypeSafety (= 0.62.2)
- - React-Core/RCTImageHeaders (= 0.62.2)
- - React-RCTNetwork (= 0.62.2)
- - ReactCommon/turbomodule/core (= 0.62.2)
- - React-RCTLinking (0.62.2):
- - FBReactNativeSpec (= 0.62.2)
- - React-Core/RCTLinkingHeaders (= 0.62.2)
- - ReactCommon/turbomodule/core (= 0.62.2)
- - React-RCTNetwork (0.62.2):
- - FBReactNativeSpec (= 0.62.2)
- - Folly (= 2018.10.22.00)
- - RCTTypeSafety (= 0.62.2)
- - React-Core/RCTNetworkHeaders (= 0.62.2)
- - ReactCommon/turbomodule/core (= 0.62.2)
- - React-RCTSettings (0.62.2):
- - FBReactNativeSpec (= 0.62.2)
- - Folly (= 2018.10.22.00)
- - RCTTypeSafety (= 0.62.2)
- - React-Core/RCTSettingsHeaders (= 0.62.2)
- - ReactCommon/turbomodule/core (= 0.62.2)
- - React-RCTText (0.62.2):
- - React-Core/RCTTextHeaders (= 0.62.2)
- - React-RCTVibration (0.62.2):
- - FBReactNativeSpec (= 0.62.2)
- - Folly (= 2018.10.22.00)
- - React-Core/RCTVibrationHeaders (= 0.62.2)
- - ReactCommon/turbomodule/core (= 0.62.2)
- - ReactCommon/callinvoker (0.62.2):
+ - React-RCTActionSheet (0.63.1):
+ - React-Core/RCTActionSheetHeaders (= 0.63.1)
+ - React-RCTAnimation (0.63.1):
+ - FBReactNativeSpec (= 0.63.1)
+ - Folly (= 2020.01.13.00)
+ - RCTTypeSafety (= 0.63.1)
+ - React-Core/RCTAnimationHeaders (= 0.63.1)
+ - React-jsi (= 0.63.1)
+ - ReactCommon/turbomodule/core (= 0.63.1)
+ - React-RCTBlob (0.63.1):
+ - FBReactNativeSpec (= 0.63.1)
+ - Folly (= 2020.01.13.00)
+ - React-Core/RCTBlobHeaders (= 0.63.1)
+ - React-Core/RCTWebSocket (= 0.63.1)
+ - React-jsi (= 0.63.1)
+ - React-RCTNetwork (= 0.63.1)
+ - ReactCommon/turbomodule/core (= 0.63.1)
+ - React-RCTImage (0.63.1):
+ - FBReactNativeSpec (= 0.63.1)
+ - Folly (= 2020.01.13.00)
+ - RCTTypeSafety (= 0.63.1)
+ - React-Core/RCTImageHeaders (= 0.63.1)
+ - React-jsi (= 0.63.1)
+ - React-RCTNetwork (= 0.63.1)
+ - ReactCommon/turbomodule/core (= 0.63.1)
+ - React-RCTLinking (0.63.1):
+ - FBReactNativeSpec (= 0.63.1)
+ - React-Core/RCTLinkingHeaders (= 0.63.1)
+ - React-jsi (= 0.63.1)
+ - ReactCommon/turbomodule/core (= 0.63.1)
+ - React-RCTNetwork (0.63.1):
+ - FBReactNativeSpec (= 0.63.1)
+ - Folly (= 2020.01.13.00)
+ - RCTTypeSafety (= 0.63.1)
+ - React-Core/RCTNetworkHeaders (= 0.63.1)
+ - React-jsi (= 0.63.1)
+ - ReactCommon/turbomodule/core (= 0.63.1)
+ - React-RCTSettings (0.63.1):
+ - FBReactNativeSpec (= 0.63.1)
+ - Folly (= 2020.01.13.00)
+ - RCTTypeSafety (= 0.63.1)
+ - React-Core/RCTSettingsHeaders (= 0.63.1)
+ - React-jsi (= 0.63.1)
+ - ReactCommon/turbomodule/core (= 0.63.1)
+ - React-RCTText (0.63.1):
+ - React-Core/RCTTextHeaders (= 0.63.1)
+ - React-RCTVibration (0.63.1):
+ - FBReactNativeSpec (= 0.63.1)
+ - Folly (= 2020.01.13.00)
+ - React-Core/RCTVibrationHeaders (= 0.63.1)
+ - React-jsi (= 0.63.1)
+ - ReactCommon/turbomodule/core (= 0.63.1)
+ - ReactCommon/turbomodule/core (0.63.1):
- DoubleConversion
- - Folly (= 2018.10.22.00)
+ - Folly (= 2020.01.13.00)
- glog
- - React-cxxreact (= 0.62.2)
- - ReactCommon/turbomodule/core (0.62.2):
- - DoubleConversion
- - Folly (= 2018.10.22.00)
- - glog
- - React-Core (= 0.62.2)
- - React-cxxreact (= 0.62.2)
- - React-jsi (= 0.62.2)
- - ReactCommon/callinvoker (= 0.62.2)
+ - React-callinvoker (= 0.63.1)
+ - React-Core (= 0.63.1)
+ - React-cxxreact (= 0.63.1)
+ - React-jsi (= 0.63.1)
- ReactNativeART (1.2.0):
- React
- ReactNativeKeyboardInput (6.0.0):
@@ -442,27 +452,30 @@ PODS:
- React-Core
- RNBootSplash (2.2.5):
- React
- - RNCAsyncStorage (1.10.3):
+ - RNCAsyncStorage (1.11.0):
- React
- RNCMaskedView (0.1.10):
- React
- - RNDateTimePicker (2.3.2):
+ - RNDateTimePicker (2.6.0):
- React
- - RNDeviceInfo (5.5.7):
+ - RNDeviceInfo (5.6.2):
- React
- RNFastImage (8.1.5):
- React
- SDWebImage (~> 5.0)
- SDWebImageWebPCoder (~> 0.4.1)
- - RNFirebase (5.6.0):
- - Firebase/Core
+ - RNFBAnalytics (7.3.1):
+ - Firebase/Analytics (~> 6.27.0)
- React
- - RNFirebase/Crashlytics (= 5.6.0)
- - RNFirebase/Crashlytics (5.6.0):
- - Crashlytics
- - Fabric
- - Firebase/Core
+ - RNFBApp
+ - RNFBApp (8.2.0):
+ - Firebase/CoreOnly (~> 6.27.0)
- React
+ - RNFBCrashlytics (8.1.2):
+ - Firebase/Core (~> 6.27.0)
+ - Firebase/Crashlytics (~> 6.27.0)
+ - React
+ - RNFBApp
- RNGestureHandler (1.6.1):
- React
- RNImageCropPicker (0.31.1):
@@ -476,40 +489,40 @@ PODS:
- TOCropViewController
- RNLocalize (1.4.0):
- React
- - RNReanimated (1.8.0):
+ - RNReanimated (1.9.0):
- React
- RNRootView (1.0.3):
- React
- - RNScreens (2.7.0):
+ - RNScreens (2.9.0):
- React
- RNUserDefaults (1.8.1):
- React
- - RNVectorIcons (6.6.0):
+ - RNVectorIcons (7.0.0):
- React
- - SDWebImage (5.7.4):
- - SDWebImage/Core (= 5.7.4)
- - SDWebImage/Core (5.7.4)
+ - SDWebImage (5.8.4):
+ - SDWebImage/Core (= 5.8.4)
+ - SDWebImage/Core (5.8.4)
- SDWebImageWebPCoder (0.4.1):
- libwebp (~> 1.0)
- SDWebImage/Core (~> 5.5)
- - TOCropViewController (2.5.2)
- - UMAppLoader (1.0.2)
- - UMBarCodeScannerInterface (5.1.0)
- - UMCameraInterface (5.1.0)
- - UMConstantsInterface (5.1.0)
- - UMCore (5.1.2)
- - UMFaceDetectorInterface (5.1.0)
- - UMFileSystemInterface (5.1.0)
- - UMFontInterface (5.1.0)
- - UMImageLoaderInterface (5.1.0)
- - UMPermissionsInterface (5.1.0):
+ - TOCropViewController (2.5.3)
+ - UMAppLoader (1.2.0)
+ - UMBarCodeScannerInterface (5.2.1)
+ - UMCameraInterface (5.2.1)
+ - UMConstantsInterface (5.2.1)
+ - UMCore (5.3.0)
+ - UMFaceDetectorInterface (5.2.1)
+ - UMFileSystemInterface (5.2.1)
+ - UMFontInterface (5.2.1)
+ - UMImageLoaderInterface (5.2.1)
+ - UMPermissionsInterface (5.2.1):
- UMCore
- - UMReactNativeAdapter (5.2.0):
+ - UMReactNativeAdapter (5.4.0):
- React-Core
- UMCore
- UMFontInterface
- - UMSensorsInterface (5.1.0)
- - UMTaskManagerInterface (5.1.0)
+ - UMSensorsInterface (5.2.1)
+ - UMTaskManagerInterface (5.2.1)
- Yoga (1.14.0)
- YogaKit (1.18.1):
- Yoga (~> 1.14)
@@ -530,32 +543,32 @@ DEPENDENCIES:
- EXWebBrowser (from `../node_modules/expo-web-browser/ios`)
- FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`)
- FBReactNativeSpec (from `../node_modules/react-native/Libraries/FBReactNativeSpec`)
- - Flipper (~> 0.33.1)
+ - Flipper (~> 0.41.1)
- Flipper-DoubleConversion (= 1.1.7)
- - Flipper-Folly (~> 2.1)
+ - Flipper-Folly (~> 2.2)
- Flipper-Glog (= 0.3.6)
- Flipper-PeerTalk (~> 0.0.4)
- - Flipper-RSocket (~> 1.0)
- - FlipperKit (~> 0.33.1)
- - FlipperKit/Core (~> 0.33.1)
- - FlipperKit/CppBridge (~> 0.33.1)
- - FlipperKit/FBCxxFollyDynamicConvert (~> 0.33.1)
- - FlipperKit/FBDefines (~> 0.33.1)
- - FlipperKit/FKPortForwarding (~> 0.33.1)
- - FlipperKit/FlipperKitHighlightOverlay (~> 0.33.1)
- - FlipperKit/FlipperKitLayoutPlugin (~> 0.33.1)
- - FlipperKit/FlipperKitLayoutTextSearchable (~> 0.33.1)
- - FlipperKit/FlipperKitNetworkPlugin (~> 0.33.1)
- - FlipperKit/FlipperKitReactPlugin (~> 0.33.1)
- - FlipperKit/FlipperKitUserDefaultsPlugin (~> 0.33.1)
- - FlipperKit/SKIOSNetworkPlugin (~> 0.33.1)
+ - Flipper-RSocket (~> 1.1)
+ - FlipperKit (~> 0.41.1)
+ - FlipperKit/Core (~> 0.41.1)
+ - FlipperKit/CppBridge (~> 0.41.1)
+ - FlipperKit/FBCxxFollyDynamicConvert (~> 0.41.1)
+ - FlipperKit/FBDefines (~> 0.41.1)
+ - FlipperKit/FKPortForwarding (~> 0.41.1)
+ - FlipperKit/FlipperKitHighlightOverlay (~> 0.41.1)
+ - FlipperKit/FlipperKitLayoutPlugin (~> 0.41.1)
+ - FlipperKit/FlipperKitLayoutTextSearchable (~> 0.41.1)
+ - FlipperKit/FlipperKitNetworkPlugin (~> 0.41.1)
+ - FlipperKit/FlipperKitReactPlugin (~> 0.41.1)
+ - FlipperKit/FlipperKitUserDefaultsPlugin (~> 0.41.1)
+ - FlipperKit/SKIOSNetworkPlugin (~> 0.41.1)
- Folly (from `../node_modules/react-native/third-party-podspecs/Folly.podspec`)
- glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`)
- - JitsiMeetSDK (from `https://github.com/RocketChat/jitsi-meet-ios-sdk-releases.git`)
- KeyCommands (from `../node_modules/react-native-keycommands`)
- RCTRequired (from `../node_modules/react-native/Libraries/RCTRequired`)
- RCTTypeSafety (from `../node_modules/react-native/Libraries/TypeSafety`)
- React (from `../node_modules/react-native/`)
+ - React-callinvoker (from `../node_modules/react-native/ReactCommon/callinvoker`)
- React-Core (from `../node_modules/react-native/`)
- React-Core/DevSupport (from `../node_modules/react-native/`)
- React-Core/RCTWebSocket (from `../node_modules/react-native/`)
@@ -583,7 +596,6 @@ DEPENDENCIES:
- React-RCTSettings (from `../node_modules/react-native/Libraries/Settings`)
- React-RCTText (from `../node_modules/react-native/Libraries/Text`)
- React-RCTVibration (from `../node_modules/react-native/Libraries/Vibration`)
- - ReactCommon/callinvoker (from `../node_modules/react-native/ReactCommon`)
- ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`)
- "ReactNativeART (from `../node_modules/@react-native-community/art`)"
- ReactNativeKeyboardInput (from `../node_modules/react-native-keyboard-input`)
@@ -595,8 +607,10 @@ DEPENDENCIES:
- "RNCMaskedView (from `../node_modules/@react-native-community/masked-view`)"
- "RNDateTimePicker (from `../node_modules/@react-native-community/datetimepicker`)"
- RNDeviceInfo (from `../node_modules/react-native-device-info`)
- - RNFastImage (from `../node_modules/react-native-fast-image`)
- - RNFirebase (from `../node_modules/react-native-firebase/ios`)
+ - "RNFastImage (from `../node_modules/@rocket.chat/react-native-fast-image`)"
+ - "RNFBAnalytics (from `../node_modules/@react-native-firebase/analytics`)"
+ - "RNFBApp (from `../node_modules/@react-native-firebase/app`)"
+ - "RNFBCrashlytics (from `../node_modules/@react-native-firebase/crashlytics`)"
- RNGestureHandler (from `../node_modules/react-native-gesture-handler`)
- RNImageCropPicker (from `../node_modules/react-native-image-crop-picker`)
- RNLocalize (from `../node_modules/react-native-localize`)
@@ -625,13 +639,11 @@ SPEC REPOS:
- boost-for-react-native
- CocoaAsyncSocket
- CocoaLibEvent
- - Crashlytics
- - Fabric
- Firebase
- FirebaseAnalytics
- FirebaseCore
- FirebaseCoreDiagnostics
- - FirebaseCoreDiagnosticsInterop
+ - FirebaseCrashlytics
- FirebaseInstallations
- Flipper
- Flipper-DoubleConversion
@@ -644,6 +656,7 @@ SPEC REPOS:
- GoogleDataTransport
- GoogleDataTransportCCTSupport
- GoogleUtilities
+ - JitsiMeetSDK
- libwebp
- nanopb
- OpenSSL-Universal
@@ -688,8 +701,6 @@ EXTERNAL SOURCES:
:podspec: "../node_modules/react-native/third-party-podspecs/Folly.podspec"
glog:
:podspec: "../node_modules/react-native/third-party-podspecs/glog.podspec"
- JitsiMeetSDK:
- :git: https://github.com/RocketChat/jitsi-meet-ios-sdk-releases.git
KeyCommands:
:path: "../node_modules/react-native-keycommands"
RCTRequired:
@@ -698,6 +709,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/Libraries/TypeSafety"
React:
:path: "../node_modules/react-native/"
+ React-callinvoker:
+ :path: "../node_modules/react-native/ReactCommon/callinvoker"
React-Core:
:path: "../node_modules/react-native/"
React-CoreModules:
@@ -771,9 +784,13 @@ EXTERNAL SOURCES:
RNDeviceInfo:
:path: "../node_modules/react-native-device-info"
RNFastImage:
- :path: "../node_modules/react-native-fast-image"
- RNFirebase:
- :path: "../node_modules/react-native-firebase/ios"
+ :path: "../node_modules/@rocket.chat/react-native-fast-image"
+ RNFBAnalytics:
+ :path: "../node_modules/@react-native-firebase/analytics"
+ RNFBApp:
+ :path: "../node_modules/@react-native-firebase/app"
+ RNFBCrashlytics:
+ :path: "../node_modules/@react-native-firebase/crashlytics"
RNGestureHandler:
:path: "../node_modules/react-native-gesture-handler"
RNImageCropPicker:
@@ -819,125 +836,121 @@ EXTERNAL SOURCES:
Yoga:
:path: "../node_modules/react-native/ReactCommon/yoga"
-CHECKOUT OPTIONS:
- JitsiMeetSDK:
- :commit: 9177aaa3afb379e17cc687887485e91e5cd24a49
- :git: https://github.com/RocketChat/jitsi-meet-ios-sdk-releases.git
-
SPEC CHECKSUMS:
boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c
- BugsnagReactNative: 14c1b59cfbf34fd5591b734bfec65a277b677ef8
+ BugsnagReactNative: 98fb350df4bb0c94cce903023531a1a5cc11fa51
CocoaAsyncSocket: 694058e7c0ed05a9e217d1b3c7ded962f4180845
CocoaLibEvent: 2fab71b8bd46dd33ddb959f7928ec5909f838e3f
- Crashlytics: 540b7e5f5da5a042647227a5e3ac51d85eed06df
- DoubleConversion: 5805e889d232975c086db112ece9ed034df7a0b2
+ DoubleConversion: cde416483dac037923206447da6e1454df403714
EXAppleAuthentication: 5b3da71bada29e2423d8ea27e5538ef0d75aba62
- EXAV: 2edd9cd30fe98d04b55325303c7ff01db02d1d0f
- EXConstants: 5304709b1bea70a4828f48ba4c7fc3ec3b2d9b17
- EXFileSystem: cf4232ba7c62dc49b78c2d36005f97b6fddf0b01
- EXHaptics: 013b5065946d4dd7b46ea547b58072d45a206dbd
- EXImageLoader: 5ad6896fa1ef2ee814b551873cbf7a7baccc694a
- EXKeepAwake: d045bc2cf1ad5a04f0323cc7c894b95b414042e0
- EXLocalAuthentication: bbf1026cc289d729da4f29240dd7a8f6a14e4b20
- EXPermissions: 24b97f734ce9172d245a5be38ad9ccfcb6135964
- EXVideoThumbnails: be6984a3cda1e44c45b5c6278244e99855f99a0a
- EXWebBrowser: 5902f99ac5ac551e5c82ff46f13a337b323aa9ea
- Fabric: 706c8b8098fff96c33c0db69cbf81f9c551d0d74
- FBLazyVector: 4aab18c93cd9546e4bfed752b4084585eca8b245
- FBReactNativeSpec: 5465d51ccfeecb7faa12f9ae0024f2044ce4044e
- Firebase: b28e55c60efd98963cd9011fe2fac5a10c2ba124
- FirebaseAnalytics: 7386fc2176e3f93ad8ef34b5b1f2b33a891e4962
- FirebaseCore: e610482f64097b0e9f056cd97bc6b33dfabcbb6a
- FirebaseCoreDiagnostics: 4a773a47bd83bbd5a9b1ccf1ce7caa8b2d535e67
- FirebaseCoreDiagnosticsInterop: 296e2c5f5314500a850ad0b83e9e7c10b011a850
- FirebaseInstallations: 2119fb3e46b0a88bfdbf12562f855ee3252462fa
- Flipper: 6c1f484f9a88d30ab3e272800d53688439e50f69
+ EXAV: 86344030966e0da7e00556fbb97269d9ad16071d
+ EXConstants: f907b3b6ce16e20d1750f22af1e095e924574bcb
+ EXFileSystem: 76875135b61708b9afa7e6a89b72a60ba0fdfa20
+ EXHaptics: 5428b344a216ca5d9df6ca8f65720b2a1ad9f109
+ EXImageLoader: 02ca02c9cd5cc8a97b423207a73a791e0a86bea5
+ EXKeepAwake: 8b0f68242f036b971f9f8976341823cbe6f50812
+ EXLocalAuthentication: 985c65e08a6eb84f8f98b51f7435df138b18b9e8
+ EXPermissions: 80ac3acbdb145930079810fe5b08c022b3428aa8
+ EXVideoThumbnails: f70bdc5511749f3181028f5000bcb7be203c631d
+ EXWebBrowser: d37a5ffdea1b65947352bc001dd9f732463725d4
+ FBLazyVector: a50434c875bd42f2b1c99c712bda892a1dc659c7
+ FBReactNativeSpec: 393853a536428e05a9da00b6290042f09809b15b
+ Firebase: 919186c8e119dd9372a45fd1dd17a8a942bc1892
+ FirebaseAnalytics: 5fa308e1b13f838d0f6dc74719ac2a72e8c5afc4
+ FirebaseCore: 8cd4f8ea22075e0ee582849b1cf79d8816506085
+ FirebaseCoreDiagnostics: 4505e4d4009b1d93f605088ee7d7764d5f0d1c84
+ FirebaseCrashlytics: 7d0fa02ea8842cc4b2ab07b0735edafde1ad77d6
+ FirebaseInstallations: 3c520c951305cbf9ca54eb891ff9e6d1fd384881
+ Flipper: 33585e2d9810fe5528346be33bcf71b37bb7ae13
Flipper-DoubleConversion: 38631e41ef4f9b12861c67d17cb5518d06badc41
Flipper-Folly: c12092ea368353b58e992843a990a3225d4533c3
Flipper-Glog: 1dfd6abf1e922806c52ceb8701a3599a79a200a6
Flipper-PeerTalk: 116d8f857dc6ef55c7a5a75ea3ceaafe878aadc9
Flipper-RSocket: 64e7431a55835eb953b0bf984ef3b90ae9fdddd7
- FlipperKit: 6dc9b8f4ef60d9e5ded7f0264db299c91f18832e
- Folly: 30e7936e1c45c08d884aa59369ed951a8e68cf51
- glog: 1f3da668190260b06b429bb211bfbee5cd790c28
- GoogleAppMeasurement: 4c644d86835d827bab30ab6aabb9ecaf1f500735
- GoogleDataTransport: f6f8eba931df03ebd2232ff4645aa85f8f47b5ab
- GoogleDataTransportCCTSupport: d70a561f7d236af529fee598835caad5e25f6d3d
- GoogleUtilities: 39530bc0ad980530298e9c4af8549e991fd033b1
+ FlipperKit: bc68102cd4952a258a23c9c1b316c7bec1fecf83
+ Folly: b73c3869541e86821df3c387eb0af5f65addfab4
+ glog: 40a13f7840415b9a77023fbcae0f1e6f43192af3
+ GoogleAppMeasurement: 8cd1f289d60e629cf16ab03363b9e89c776b9651
+ GoogleDataTransport: 9a8a16f79feffc7f42096743de2a7c4815e84020
+ GoogleDataTransportCCTSupport: 489c1265d2c85b68187a83a911913d190012158d
+ GoogleUtilities: e121a3867449ce16b0e35ddf1797ea7a389ffdf2
JitsiMeetSDK: 2984eac1343690bf1c0c72bde75b48b0148d0f79
KeyCommands: f66c535f698ed14b3d3a4e58859d79a827ea907e
libwebp: 946cb3063cea9236285f7e9a8505d806d30e07f3
nanopb: c43f40fadfe79e8b8db116583945847910cbabc9
OpenSSL-Universal: 8b48cc0d10c1b2923617dfe5c178aa9ed2689355
- PromisesObjC: c119f3cd559f50b7ae681fa59dc1acd19173b7e6
- RCTRequired: cec6a34b3ac8a9915c37e7e4ad3aa74726ce4035
- RCTTypeSafety: 93006131180074cffa227a1075802c89a49dd4ce
- React: 29a8b1a02bd764fb7644ef04019270849b9a7ac3
- React-Core: b12bffb3f567fdf99510acb716ef1abd426e0e05
- React-CoreModules: 4a9b87bbe669d6c3173c0132c3328e3b000783d0
- React-cxxreact: e65f9c2ba0ac5be946f53548c1aaaee5873a8103
- React-jsi: b6dc94a6a12ff98e8877287a0b7620d365201161
- React-jsiexecutor: 1540d1c01bb493ae3124ed83351b1b6a155db7da
- React-jsinspector: 512e560d0e985d0e8c479a54a4e5c147a9c83493
+ PromisesObjC: b48e0338dbbac2207e611750777895f7a5811b75
+ RCTRequired: d9b1a9e6fa097744ca3ede59f86a35096df7202b
+ RCTTypeSafety: c227cd061983e9e964115afbc4e8730d6a6f1395
+ React: 86e972a20967ee4137aa19dc48319405927c2e94
+ React-callinvoker: 87ee376c25277d74e164ff036b27084e343f3e69
+ React-Core: f5ec03baf7ed58d9f3ee04a8f84e4c97ee8bf4c9
+ React-CoreModules: 958898aa8c069280e866e35a2f29480a81fcf335
+ React-cxxreact: 90de76b9b51575668ad7fd4e33a5a8c143beecc2
+ React-jsi: b32a31da32e030f30bbf9a8d3a9c8325df9e793f
+ React-jsiexecutor: 7ab9cdcdd18d57652fb041f8a147fe9658d4e00a
+ React-jsinspector: 2e28bb487e42dda6c94dbfa0c648d1343767a0fb
react-native-appearance: 0f0e5fc2fcef70e03d48c8fe6b00b9158c2ba8aa
react-native-background-timer: 1f7d560647b40e6a60b01c452ba29c54bf581fc4
- react-native-cameraroll: 02e60e9af9273a3cc3b641632bf651189830aaf8
- react-native-document-picker: dd96ce05bf1453b110d7a3912097bf6d298d2cb6
+ react-native-cameraroll: ae0a7c0cc8462508855707ff623b1e789b692865
+ react-native-document-picker: 825552b827012282baf4b7cbf119d3b37a280c90
react-native-jitsi-meet: f89bcb2cfbd5b15403b9c40738036c4f1af45d05
react-native-notifications: ee8fd739853e72694f3af8b374c8ccb106b7b227
react-native-orientation-locker: f0ca1a8e5031dab6b74bfb4ab33a17ed2c2fcb0d
- react-native-safe-area-context: b11a34881faac509cad5578726c98161ad4d275c
- react-native-slider: e51492f1264d882a8815b71c5870f8978e52887d
- react-native-webview: cf5527893252b3b036eea024a1da6996f7344c74
- React-RCTActionSheet: f41ea8a811aac770e0cc6e0ad6b270c644ea8b7c
- React-RCTAnimation: 49ab98b1c1ff4445148b72a3d61554138565bad0
- React-RCTBlob: a332773f0ebc413a0ce85942a55b064471587a71
- React-RCTImage: e70be9b9c74fe4e42d0005f42cace7981c994ac3
- React-RCTLinking: c1b9739a88d56ecbec23b7f63650e44672ab2ad2
- React-RCTNetwork: 73138b6f45e5a2768ad93f3d57873c2a18d14b44
- React-RCTSettings: 6e3738a87e21b39a8cb08d627e68c44acf1e325a
- React-RCTText: fae545b10cfdb3d247c36c56f61a94cfd6dba41d
- React-RCTVibration: 4356114dbcba4ce66991096e51a66e61eda51256
- ReactCommon: ed4e11d27609d571e7eee8b65548efc191116eb3
+ react-native-safe-area-context: 344b969c45af3d8464d36e8dea264942992ef033
+ react-native-slider: 0221b417686c5957f6e77cd9ac22c1478a165355
+ react-native-webview: 679b6f400176e2ea8a785acf7ae16cf282e7d1eb
+ React-RCTActionSheet: 1702a1a85e550b5c36e2e03cb2bd3adea053de95
+ React-RCTAnimation: ddda576010a878865a4eab83a78acd92176ef6a1
+ React-RCTBlob: 34334384284c81577409d5205bd2b9ff594d8ab6
+ React-RCTImage: e2a661266dca295cffb33909cc64675a2efedb26
+ React-RCTLinking: cd39b9b5e9cbb9e827854e30dfa92d7db074cea8
+ React-RCTNetwork: 16939b7e4058d6f662b304a1f61689e249a2bfcc
+ React-RCTSettings: 24726a62de0c326f9ebfc3838898a501b87ce711
+ React-RCTText: 4f95d322b7e6da72817284abf8a2cdcec18b9cd8
+ React-RCTVibration: f3a9123c244f35c40d3c9f3ec3f0b9e5717bb292
+ ReactCommon: 2905859f84a94a381bb0d8dd3921ccb1a0047cb8
ReactNativeART: 78edc68dd4a1e675338cd0cd113319cf3a65f2ab
ReactNativeKeyboardInput: c37e26821519869993b3b61844350feb9177ff37
ReactNativeKeyboardTrackingView: 02137fac3b2ebd330d74fa54ead48b14750a2306
rn-extensions-share: 8db79372089567cbc5aefe8444869bbc808578d3
rn-fetch-blob: f065bb7ab7fb48dd002629f8bdcb0336602d3cba
RNBootSplash: b3836aa90c5bec690c6cd3c9ab355fcf98d0fe1d
- RNCAsyncStorage: cd7234ff15c010723ed7c499ae4eedc605eac1fd
+ RNCAsyncStorage: d059c3ee71738c39834a627476322a5a8cd5bf36
RNCMaskedView: 5a8ec07677aa885546a0d98da336457e2bea557f
- RNDateTimePicker: 4bd49e09f91ca73d69119a9e1173b0d43b82f5e5
- RNDeviceInfo: e2102056bde3ad5d137fd029d8d431510a00486a
+ RNDateTimePicker: e386ff4ef3300964ed0cad97ce6f206e0effbfdb
+ RNDeviceInfo: ed8557a8bd6443cbc0ab5d375e6808a38a279744
RNFastImage: 35ae972d6727c84ee3f5c6897e07f84d0a3445e9
- RNFirebase: 37daa9a346d070f9f6ee1f3b4aaf4c8e3b1d5d1c
+ RNFBAnalytics: dae6d7b280ba61c96e1bbdd34aca3154388f025e
+ RNFBApp: 6fd8a7e757135d4168bf033a8812c241af7363a0
+ RNFBCrashlytics: 88de72c2476b5868a892d9523b89b86c527c540e
RNGestureHandler: 8f09cd560f8d533eb36da5a6c5a843af9f056b38
RNImageCropPicker: 38865ab4af1b0b2146ad66061196bc0184946855
RNLocalize: b6df30cc25ae736d37874f9bce13351db2f56796
- RNReanimated: 955cf4068714003d2f1a6e2bae3fb1118f359aff
+ RNReanimated: b5ccb50650ba06f6e749c7c329a1bc3ae0c88b43
RNRootView: 895a4813dedeaca82db2fa868ca1c333d790e494
- RNScreens: cf198f915f8a2bf163de94ca9f5bfc8d326c3706
+ RNScreens: c526239bbe0e957b988dacc8d75ac94ec9cb19da
RNUserDefaults: c421fd97ad06b35c16608c5d0fe675db353f632d
- RNVectorIcons: 0bb4def82230be1333ddaeee9fcba45f0b288ed4
- SDWebImage: 48b88379b798fd1e4298f95bb25d2cdabbf4deb3
+ RNVectorIcons: da6fe858f5a65d7bbc3379540a889b0b12aa5976
+ SDWebImage: cf6922231e95550934da2ada0f20f2becf2ceba9
SDWebImageWebPCoder: 36f8f47bd9879a8aea6044765c1351120fd8e3a8
- TOCropViewController: e9da34f484aedd4e5d5a8ab230ba217cfe16c729
- UMAppLoader: ee77a072f9e15128f777ccd6d2d00f52ab4387e6
- UMBarCodeScannerInterface: 9dc692b87e5f20fe277fa57aa47f45d418c3cc6c
- UMCameraInterface: 625878bbf2ba188a8548675e1d1d2e438a653e6d
- UMConstantsInterface: 64060cf86587bcd90b1dbd804cceb6d377a308c1
- UMCore: eb200e882eadafcd31ead290770835fd648c0945
- UMFaceDetectorInterface: d6677d6ddc9ab95a0ca857aa7f8ba76656cc770f
- UMFileSystemInterface: c70ea7147198b9807080f3597f26236be49b0165
- UMFontInterface: d9d3b27af698c5389ae9e20b99ef56a083f491fb
- UMImageLoaderInterface: 14dd2c46c67167491effc9e91250e9510f12709e
- UMPermissionsInterface: 5e83a9167c177e4a0f0a3539345983cc749efb3e
- UMReactNativeAdapter: 126da3486c1a1f11945b649d557d6c2ebb9407b2
- UMSensorsInterface: 48941f70175e2975af1a9386c6d6cb16d8126805
- UMTaskManagerInterface: cb890c79c63885504ddc0efd7a7d01481760aca2
- Yoga: 3ebccbdd559724312790e7742142d062476b698e
+ TOCropViewController: 20a14b6a7a098308bf369e7c8d700dc983a974e6
+ UMAppLoader: 61049c8d55590b74e9ae1d5429bf68d96b4a2528
+ UMBarCodeScannerInterface: e5e4c87797d3d01214e25cd1618866caf5d4f17f
+ UMCameraInterface: 415ac060034edecacdbbaa739c223e3f276e0056
+ UMConstantsInterface: 1a52f2d884c95e8829439da13e36b7669a1a8fb4
+ UMCore: d98083b522b08c0a8ba3992bc263c624ae5d887c
+ UMFaceDetectorInterface: 67c6c82451338da01a4bc00ec46365a2a8ea9057
+ UMFileSystemInterface: 303d696ede28102a7e11d111808bd2ed2c5eb62f
+ UMFontInterface: 6edf1ee8bc55d2030766f8cf0a7b20a5d5a913b0
+ UMImageLoaderInterface: 9cdbf3bab6a513bddd88505cb2340fe02d6a11c0
+ UMPermissionsInterface: 019170ad655f464e3f8d23d2a8bcbda2e645cde4
+ UMReactNativeAdapter: 538efe92e781b5d7678cf95b34c46f2d0989a557
+ UMSensorsInterface: cb5bf31d52c4349f0ff9e3c049bbe4df0d80d383
+ UMTaskManagerInterface: 80653f25c55d9e6d79d6a0a65589fa213feaee11
+ Yoga: d5bd05a2b6b94c52323745c2c2b64557c8c66f64
YogaKit: f782866e155069a2cca2517aafea43200b01fd5a
-PODFILE CHECKSUM: 35d9478dd32cf502959b8efc14411ecf09c66c95
+PODFILE CHECKSUM: 55c04243097892160d63f79f3a23157165b7ac68
-COCOAPODS: 1.8.4
+COCOAPODS: 1.9.3
diff --git a/ios/Pods/Crashlytics/Crashlytics.framework/README b/ios/Pods/Crashlytics/Crashlytics.framework/README
deleted file mode 100644
index 3ebf76719..000000000
--- a/ios/Pods/Crashlytics/Crashlytics.framework/README
+++ /dev/null
@@ -1 +0,0 @@
-We've now combined all our supported platforms into a single podspec. As a result, we moved our submit script to a new location for Cocoapods projects: ${PODS_ROOT}/Crashlytics/submit. To avoid breaking functionality that references the old location of the submit, we've placed this dummy script that calls to the correct location, while providing a helpful warning if it is invoked. This bridge for backwards compatibility will be removed in a future release, so please heed the warning!
diff --git a/ios/Pods/Crashlytics/Crashlytics.framework/submit b/ios/Pods/Crashlytics/Crashlytics.framework/submit
deleted file mode 100755
index b7de4e377..000000000
--- a/ios/Pods/Crashlytics/Crashlytics.framework/submit
+++ /dev/null
@@ -1,6 +0,0 @@
-if [[ -z $PODS_ROOT ]]; then
-echo "error: The submit binary delivered by cocoapods is in a new location, under '$"{"PODS_ROOT"}"/Crashlytics/submit'. This script was put in place for backwards compatibility, but it relies on PODS_ROOT, which does not have a value in your current setup. Please update the path to the submit binary to fix this issue."
-else
-echo "warning: The submit script is now located at '$"{"PODS_ROOT"}"/Crashlytics/submit'. To remove this warning, update your path to point to this new location."
-sh "${PODS_ROOT}/Crashlytics/submit" "$@"
-fi
diff --git a/ios/Pods/Crashlytics/README.md b/ios/Pods/Crashlytics/README.md
deleted file mode 100644
index 996af5078..000000000
--- a/ios/Pods/Crashlytics/README.md
+++ /dev/null
@@ -1,23 +0,0 @@
-
-# Crashlytics
-
-## Overview
-
-[Crashlytics](https://firebase.google.com/docs/crashlytics/get-started?platform=ios) offers the most powerful, yet lightest weight crash reporting solution for iOS.
-
-
-## Setup
-
-To start using Crashlytics, there are two options:
-
-1) The recommended way is to go to the [Firebase Crashlytics Docs](https://firebase.google.com/docs/crashlytics/get-started?platform=ios) and follow the directions there.
-
-2) If you aren't using Firebase yet, go to [Fabric Kits](https://fabric.io/kits), and follow the directions for Crashlytics.
-
-
-## Resources
-
-* [API Reference](https://firebase.google.com/docs/reference/ios/crashlytics/api/reference/Classes)
-* [Forums](https://stackoverflow.com/questions/tagged/google-fabric)
-* [Website](https://firebase.google.com/docs/crashlytics)
-* Follow us on Twitter: [@crashlytics](https://twitter.com/crashlytics)
diff --git a/ios/Pods/Crashlytics/iOS/Crashlytics.framework/Crashlytics b/ios/Pods/Crashlytics/iOS/Crashlytics.framework/Crashlytics
deleted file mode 100755
index 214fb9051..000000000
Binary files a/ios/Pods/Crashlytics/iOS/Crashlytics.framework/Crashlytics and /dev/null differ
diff --git a/ios/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/ANSCompatibility.h b/ios/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/ANSCompatibility.h
deleted file mode 100644
index 6ec011d93..000000000
--- a/ios/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/ANSCompatibility.h
+++ /dev/null
@@ -1,31 +0,0 @@
-//
-// ANSCompatibility.h
-// AnswersKit
-//
-// Copyright (c) 2015 Crashlytics, Inc. All rights reserved.
-//
-
-#pragma once
-
-#if !__has_feature(nullability)
-#define nonnull
-#define nullable
-#define _Nullable
-#define _Nonnull
-#endif
-
-#ifndef NS_ASSUME_NONNULL_BEGIN
-#define NS_ASSUME_NONNULL_BEGIN
-#endif
-
-#ifndef NS_ASSUME_NONNULL_END
-#define NS_ASSUME_NONNULL_END
-#endif
-
-#if __has_feature(objc_generics)
-#define ANS_GENERIC_NSARRAY(type) NSArray
-#define ANS_GENERIC_NSDICTIONARY(key_type,object_key) NSDictionary
-#else
-#define ANS_GENERIC_NSARRAY(type) NSArray
-#define ANS_GENERIC_NSDICTIONARY(key_type,object_key) NSDictionary
-#endif
diff --git a/ios/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/Answers.h b/ios/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/Answers.h
deleted file mode 100644
index 8deacbee5..000000000
--- a/ios/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/Answers.h
+++ /dev/null
@@ -1,210 +0,0 @@
-//
-// Answers.h
-// Crashlytics
-//
-// Copyright (c) 2015 Crashlytics, Inc. All rights reserved.
-//
-
-#import
-#import "ANSCompatibility.h"
-
-NS_ASSUME_NONNULL_BEGIN
-
-/**
- * This class exposes the Answers Events API, allowing you to track key
- * user user actions and metrics in your app.
- */
-@interface Answers : NSObject
-
-/**
- * Log a Sign Up event to see users signing up for your app in real-time, understand how
- * many users are signing up with different methods and their success rate signing up.
- *
- * @param signUpMethodOrNil The method by which a user logged in, e.g. Twitter or Digits.
- * @param signUpSucceededOrNil The ultimate success or failure of the login
- * @param customAttributesOrNil A dictionary of custom attributes to associate with this event.
- */
-+ (void)logSignUpWithMethod:(nullable NSString *)signUpMethodOrNil
- success:(nullable NSNumber *)signUpSucceededOrNil
- customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil;
-
-/**
- * Log an Log In event to see users logging into your app in real-time, understand how many
- * users are logging in with different methods and their success rate logging into your app.
- *
- * @param loginMethodOrNil The method by which a user logged in, e.g. email, Twitter or Digits.
- * @param loginSucceededOrNil The ultimate success or failure of the login
- * @param customAttributesOrNil A dictionary of custom attributes to associate with this event.
- */
-+ (void)logLoginWithMethod:(nullable NSString *)loginMethodOrNil
- success:(nullable NSNumber *)loginSucceededOrNil
- customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil;
-
-/**
- * Log a Share event to see users sharing from your app in real-time, letting you
- * understand what content they're sharing from the type or genre down to the specific id.
- *
- * @param shareMethodOrNil The method by which a user shared, e.g. email, Twitter, SMS.
- * @param contentNameOrNil The human readable name for this piece of content.
- * @param contentTypeOrNil The type of content shared.
- * @param contentIdOrNil The unique identifier for this piece of content. Useful for finding the top shared item.
- * @param customAttributesOrNil A dictionary of custom attributes to associate with this event.
- */
-+ (void)logShareWithMethod:(nullable NSString *)shareMethodOrNil
- contentName:(nullable NSString *)contentNameOrNil
- contentType:(nullable NSString *)contentTypeOrNil
- contentId:(nullable NSString *)contentIdOrNil
- customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil;
-
-/**
- * Log an Invite Event to track how users are inviting other users into
- * your application.
- *
- * @param inviteMethodOrNil The method of invitation, e.g. GameCenter, Twitter, email.
- * @param customAttributesOrNil A dictionary of custom attributes to associate with this event.
- */
-+ (void)logInviteWithMethod:(nullable NSString *)inviteMethodOrNil
- customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil;
-
-/**
- * Log a Purchase event to see your revenue in real-time, understand how many users are making purchases, see which
- * items are most popular, and track plenty of other important purchase-related metrics.
- *
- * @param itemPriceOrNil The purchased item's price.
- * @param currencyOrNil The ISO4217 currency code. Example: USD
- * @param purchaseSucceededOrNil Was the purchase successful or unsuccessful
- * @param itemNameOrNil The human-readable form of the item's name. Example:
- * @param itemTypeOrNil The type, or genre of the item. Example: Song
- * @param itemIdOrNil The machine-readable, unique item identifier Example: SKU
- * @param customAttributesOrNil A dictionary of custom attributes to associate with this purchase.
- */
-+ (void)logPurchaseWithPrice:(nullable NSDecimalNumber *)itemPriceOrNil
- currency:(nullable NSString *)currencyOrNil
- success:(nullable NSNumber *)purchaseSucceededOrNil
- itemName:(nullable NSString *)itemNameOrNil
- itemType:(nullable NSString *)itemTypeOrNil
- itemId:(nullable NSString *)itemIdOrNil
- customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil;
-
-/**
- * Log a Level Start Event to track where users are in your game.
- *
- * @param levelNameOrNil The level name
- * @param customAttributesOrNil A dictionary of custom attributes to associate with this level start event.
- */
-+ (void)logLevelStart:(nullable NSString *)levelNameOrNil
- customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil;
-
-/**
- * Log a Level End event to track how users are completing levels in your game.
- *
- * @param levelNameOrNil The name of the level completed, E.G. "1" or "Training"
- * @param scoreOrNil The score the user completed the level with.
- * @param levelCompletedSuccesfullyOrNil A boolean representing whether or not the level was completed successfully.
- * @param customAttributesOrNil A dictionary of custom attributes to associate with this event.
- */
-+ (void)logLevelEnd:(nullable NSString *)levelNameOrNil
- score:(nullable NSNumber *)scoreOrNil
- success:(nullable NSNumber *)levelCompletedSuccesfullyOrNil
- customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil;
-
-/**
- * Log an Add to Cart event to see users adding items to a shopping cart in real-time, understand how
- * many users start the purchase flow, see which items are most popular, and track plenty of other important
- * purchase-related metrics.
- *
- * @param itemPriceOrNil The purchased item's price.
- * @param currencyOrNil The ISO4217 currency code. Example: USD
- * @param itemNameOrNil The human-readable form of the item's name. Example:
- * @param itemTypeOrNil The type, or genre of the item. Example: Song
- * @param itemIdOrNil The machine-readable, unique item identifier Example: SKU
- * @param customAttributesOrNil A dictionary of custom attributes to associate with this event.
- */
-+ (void)logAddToCartWithPrice:(nullable NSDecimalNumber *)itemPriceOrNil
- currency:(nullable NSString *)currencyOrNil
- itemName:(nullable NSString *)itemNameOrNil
- itemType:(nullable NSString *)itemTypeOrNil
- itemId:(nullable NSString *)itemIdOrNil
- customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil;
-
-/**
- * Log a Start Checkout event to see users moving through the purchase funnel in real-time, understand how many
- * users are doing this and how much they're spending per checkout, and see how it related to other important
- * purchase-related metrics.
- *
- * @param totalPriceOrNil The total price of the cart.
- * @param currencyOrNil The ISO4217 currency code. Example: USD
- * @param itemCountOrNil The number of items in the cart.
- * @param customAttributesOrNil A dictionary of custom attributes to associate with this event.
- */
-+ (void)logStartCheckoutWithPrice:(nullable NSDecimalNumber *)totalPriceOrNil
- currency:(nullable NSString *)currencyOrNil
- itemCount:(nullable NSNumber *)itemCountOrNil
- customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil;
-
-/**
- * Log a Rating event to see users rating content within your app in real-time and understand what
- * content is most engaging, from the type or genre down to the specific id.
- *
- * @param ratingOrNil The integer rating given by the user.
- * @param contentNameOrNil The human readable name for this piece of content.
- * @param contentTypeOrNil The type of content shared.
- * @param contentIdOrNil The unique identifier for this piece of content. Useful for finding the top shared item.
- * @param customAttributesOrNil A dictionary of custom attributes to associate with this event.
- */
-+ (void)logRating:(nullable NSNumber *)ratingOrNil
- contentName:(nullable NSString *)contentNameOrNil
- contentType:(nullable NSString *)contentTypeOrNil
- contentId:(nullable NSString *)contentIdOrNil
- customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil;
-
-/**
- * Log a Content View event to see users viewing content within your app in real-time and
- * understand what content is most engaging, from the type or genre down to the specific id.
- *
- * @param contentNameOrNil The human readable name for this piece of content.
- * @param contentTypeOrNil The type of content shared.
- * @param contentIdOrNil The unique identifier for this piece of content. Useful for finding the top shared item.
- * @param customAttributesOrNil A dictionary of custom attributes to associate with this event.
- */
-+ (void)logContentViewWithName:(nullable NSString *)contentNameOrNil
- contentType:(nullable NSString *)contentTypeOrNil
- contentId:(nullable NSString *)contentIdOrNil
- customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil;
-
-/**
- * Log a Search event allows you to see users searching within your app in real-time and understand
- * exactly what they're searching for.
- *
- * @param queryOrNil The user's query.
- * @param customAttributesOrNil A dictionary of custom attributes to associate with this event.
- */
-+ (void)logSearchWithQuery:(nullable NSString *)queryOrNil
- customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil;
-
-/**
- * Log a Custom Event to see user actions that are uniquely important for your app in real-time, to see how often
- * they're performing these actions with breakdowns by different categories you add. Use a human-readable name for
- * the name of the event, since this is how the event will appear in Answers.
- *
- * @param eventName The human-readable name for the event.
- * @param customAttributesOrNil A dictionary of custom attributes to associate with this event. Attribute keys
- * must be NSString
and values must be NSNumber
or NSString
.
- * @discussion How we treat NSNumbers
:
- * We will provide information about the distribution of values over time.
- *
- * How we treat NSStrings
:
- * NSStrings are used as categorical data, allowing comparison across different category values.
- * Strings are limited to a maximum length of 100 characters, attributes over this length will be
- * truncated.
- *
- * When tracking the Tweet views to better understand user engagement, sending the tweet's length
- * and the type of media present in the tweet allows you to track how tweet length and the type of media influence
- * engagement.
- */
-+ (void)logCustomEventWithName:(NSString *)eventName
- customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil;
-
-@end
-
-NS_ASSUME_NONNULL_END
diff --git a/ios/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/CLSAttributes.h b/ios/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/CLSAttributes.h
deleted file mode 100644
index 1526b0dca..000000000
--- a/ios/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/CLSAttributes.h
+++ /dev/null
@@ -1,33 +0,0 @@
-//
-// CLSAttributes.h
-// Crashlytics
-//
-// Copyright (c) 2015 Crashlytics, Inc. All rights reserved.
-//
-
-#pragma once
-
-#define CLS_DEPRECATED(x) __attribute__ ((deprecated(x)))
-
-#if !__has_feature(nullability)
- #define nonnull
- #define nullable
- #define _Nullable
- #define _Nonnull
-#endif
-
-#ifndef NS_ASSUME_NONNULL_BEGIN
- #define NS_ASSUME_NONNULL_BEGIN
-#endif
-
-#ifndef NS_ASSUME_NONNULL_END
- #define NS_ASSUME_NONNULL_END
-#endif
-
-#if __has_feature(objc_generics)
- #define CLS_GENERIC_NSARRAY(type) NSArray
- #define CLS_GENERIC_NSDICTIONARY(key_type,object_key) NSDictionary
-#else
- #define CLS_GENERIC_NSARRAY(type) NSArray
- #define CLS_GENERIC_NSDICTIONARY(key_type,object_key) NSDictionary
-#endif
diff --git a/ios/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/CLSLogging.h b/ios/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/CLSLogging.h
deleted file mode 100644
index 59590d546..000000000
--- a/ios/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/CLSLogging.h
+++ /dev/null
@@ -1,64 +0,0 @@
-//
-// CLSLogging.h
-// Crashlytics
-//
-// Copyright (c) 2015 Crashlytics, Inc. All rights reserved.
-//
-#ifdef __OBJC__
-#import "CLSAttributes.h"
-#import
-
-NS_ASSUME_NONNULL_BEGIN
-#endif
-
-
-
-/**
- *
- * The CLS_LOG macro provides as easy way to gather more information in your log messages that are
- * sent with your crash data. CLS_LOG prepends your custom log message with the function name and
- * line number where the macro was used. If your app was built with the DEBUG preprocessor macro
- * defined CLS_LOG uses the CLSNSLog function which forwards your log message to NSLog and CLSLog.
- * If the DEBUG preprocessor macro is not defined CLS_LOG uses CLSLog only.
- *
- * Example output:
- * -[AppDelegate login:] line 134 $ login start
- *
- * If you would like to change this macro, create a new header file, unset our define and then define
- * your own version. Make sure this new header file is imported after the Crashlytics header file.
- *
- * #undef CLS_LOG
- * #define CLS_LOG(__FORMAT__, ...) CLSNSLog...
- *
- **/
-#ifdef __OBJC__
-#ifdef DEBUG
-#define CLS_LOG(__FORMAT__, ...) CLSNSLog((@"%s line %d $ " __FORMAT__), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
-#else
-#define CLS_LOG(__FORMAT__, ...) CLSLog((@"%s line %d $ " __FORMAT__), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
-#endif
-#endif
-
-/**
- *
- * Add logging that will be sent with your crash data. This logging will not show up in the system.log
- * and will only be visible in your Crashlytics dashboard.
- *
- **/
-
-#ifdef __OBJC__
-OBJC_EXTERN void CLSLog(NSString *format, ...) NS_FORMAT_FUNCTION(1,2);
-OBJC_EXTERN void CLSLogv(NSString *format, va_list ap) NS_FORMAT_FUNCTION(1,0);
-
-/**
- *
- * Add logging that will be sent with your crash data. This logging will show up in the system.log
- * and your Crashlytics dashboard. It is not recommended for Release builds.
- *
- **/
-OBJC_EXTERN void CLSNSLog(NSString *format, ...) NS_FORMAT_FUNCTION(1,2);
-OBJC_EXTERN void CLSNSLogv(NSString *format, va_list ap) NS_FORMAT_FUNCTION(1,0);
-
-
-NS_ASSUME_NONNULL_END
-#endif
diff --git a/ios/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/CLSReport.h b/ios/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/CLSReport.h
deleted file mode 100644
index a8ff3b0b9..000000000
--- a/ios/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/CLSReport.h
+++ /dev/null
@@ -1,103 +0,0 @@
-//
-// CLSReport.h
-// Crashlytics
-//
-// Copyright (c) 2015 Crashlytics, Inc. All rights reserved.
-//
-
-#import
-#import "CLSAttributes.h"
-
-NS_ASSUME_NONNULL_BEGIN
-
-/**
- * The CLSCrashReport protocol is deprecated. See the CLSReport class and the CrashyticsDelegate changes for details.
- **/
-@protocol CLSCrashReport
-
-@property (nonatomic, copy, readonly) NSString *identifier;
-@property (nonatomic, copy, readonly) NSDictionary *customKeys;
-@property (nonatomic, copy, readonly) NSString *bundleVersion;
-@property (nonatomic, copy, readonly) NSString *bundleShortVersionString;
-@property (nonatomic, readonly, nullable) NSDate *crashedOnDate;
-@property (nonatomic, copy, readonly) NSString *OSVersion;
-@property (nonatomic, copy, readonly) NSString *OSBuildVersion;
-
-@end
-
-/**
- * The CLSReport exposes an interface to the phsyical report that Crashlytics has created. You can
- * use this class to get information about the event, and can also set some values after the
- * event has occurred.
- **/
-@interface CLSReport : NSObject
-
-- (instancetype)init NS_UNAVAILABLE;
-+ (instancetype)new NS_UNAVAILABLE;
-
-/**
- * Returns the session identifier for the report.
- **/
-@property (nonatomic, copy, readonly) NSString *identifier;
-
-/**
- * Returns the custom key value data for the report.
- **/
-@property (nonatomic, copy, readonly) NSDictionary *customKeys;
-
-/**
- * Returns the CFBundleVersion of the application that generated the report.
- **/
-@property (nonatomic, copy, readonly) NSString *bundleVersion;
-
-/**
- * Returns the CFBundleShortVersionString of the application that generated the report.
- **/
-@property (nonatomic, copy, readonly) NSString *bundleShortVersionString;
-
-/**
- * Returns the date that the report was created.
- **/
-@property (nonatomic, copy, readonly) NSDate *dateCreated;
-
-/**
- * Returns the os version that the application crashed on.
- **/
-@property (nonatomic, copy, readonly) NSString *OSVersion;
-
-/**
- * Returns the os build version that the application crashed on.
- **/
-@property (nonatomic, copy, readonly) NSString *OSBuildVersion;
-
-/**
- * Returns YES if the report contains any crash information, otherwise returns NO.
- **/
-@property (nonatomic, assign, readonly) BOOL isCrash;
-
-/**
- * You can use this method to set, after the event, additional custom keys. The rules
- * and semantics for this method are the same as those documented in Crashlytics.h. Be aware
- * that the maximum size and count of custom keys is still enforced, and you can overwrite keys
- * and/or cause excess keys to be deleted by using this method.
- **/
-- (void)setObjectValue:(nullable id)value forKey:(NSString *)key;
-
-/**
- * Record an application-specific user identifier. See Crashlytics.h for details.
- **/
-@property (nonatomic, copy, nullable) NSString * userIdentifier;
-
-/**
- * Record a user name. See Crashlytics.h for details.
- **/
-@property (nonatomic, copy, nullable) NSString * userName;
-
-/**
- * Record a user email. See Crashlytics.h for details.
- **/
-@property (nonatomic, copy, nullable) NSString * userEmail;
-
-@end
-
-NS_ASSUME_NONNULL_END
diff --git a/ios/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/CLSStackFrame.h b/ios/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/CLSStackFrame.h
deleted file mode 100644
index cdb5596cc..000000000
--- a/ios/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/CLSStackFrame.h
+++ /dev/null
@@ -1,38 +0,0 @@
-//
-// CLSStackFrame.h
-// Crashlytics
-//
-// Copyright 2015 Crashlytics, Inc. All rights reserved.
-//
-
-#import
-#import "CLSAttributes.h"
-
-NS_ASSUME_NONNULL_BEGIN
-
-/**
- *
- * This class is used in conjunction with -[Crashlytics recordCustomExceptionName:reason:frameArray:] to
- * record information about non-ObjC/C++ exceptions. All information included here will be displayed
- * in the Crashlytics UI, and can influence crash grouping. Be particularly careful with the use of the
- * address property. If set, Crashlytics will attempt symbolication and could overwrite other properities
- * in the process.
- *
- **/
-@interface CLSStackFrame : NSObject
-
-+ (instancetype)stackFrame;
-+ (instancetype)stackFrameWithAddress:(NSUInteger)address;
-+ (instancetype)stackFrameWithSymbol:(NSString *)symbol;
-
-@property (nonatomic, copy, nullable) NSString *symbol;
-@property (nonatomic, copy, nullable) NSString *rawSymbol;
-@property (nonatomic, copy, nullable) NSString *library;
-@property (nonatomic, copy, nullable) NSString *fileName;
-@property (nonatomic, assign) uint32_t lineNumber;
-@property (nonatomic, assign) uint64_t offset;
-@property (nonatomic, assign) uint64_t address;
-
-@end
-
-NS_ASSUME_NONNULL_END
diff --git a/ios/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/Crashlytics.h b/ios/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/Crashlytics.h
deleted file mode 100644
index 7104ca812..000000000
--- a/ios/Pods/Crashlytics/iOS/Crashlytics.framework/Headers/Crashlytics.h
+++ /dev/null
@@ -1,288 +0,0 @@
-//
-// Crashlytics.h
-// Crashlytics
-//
-// Copyright (c) 2015 Crashlytics, Inc. All rights reserved.
-//
-
-#import
-
-#import "CLSAttributes.h"
-#import "CLSLogging.h"
-#import "CLSReport.h"
-#import "CLSStackFrame.h"
-#import "Answers.h"
-
-NS_ASSUME_NONNULL_BEGIN
-
-@protocol CrashlyticsDelegate;
-
-/**
- * Crashlytics. Handles configuration and initialization of Crashlytics.
- *
- * Note: The Crashlytics class cannot be subclassed. If this is causing you pain for
- * testing, we suggest using either a wrapper class or a protocol extension.
- */
-@interface Crashlytics : NSObject
-
-@property (nonatomic, readonly, copy) NSString *APIKey;
-@property (nonatomic, readonly, copy) NSString *version;
-@property (nonatomic, assign) BOOL debugMode;
-
-/**
- *
- * The delegate can be used to influence decisions on reporting and behavior, as well as reacting
- * to previous crashes.
- *
- * Make certain that the delegate is setup before starting Crashlytics with startWithAPIKey:... or
- * via +[Fabric with:...]. Failure to do will result in missing any delegate callbacks that occur
- * synchronously during start.
- *
- **/
-@property (nonatomic, assign, nullable) id delegate;
-
-/**
- * The recommended way to install Crashlytics into your application is to place a call to +startWithAPIKey:
- * in your -application:didFinishLaunchingWithOptions: or -applicationDidFinishLaunching:
- * method.
- *
- * Note: Starting with 3.0, the submission process has been significantly improved. The delay parameter
- * is no longer required to throttle submissions on launch, performance will be great without it.
- *
- * @param apiKey The Crashlytics API Key for this app
- *
- * @return The singleton Crashlytics instance
- */
-+ (Crashlytics *)startWithAPIKey:(NSString *)apiKey;
-+ (Crashlytics *)startWithAPIKey:(NSString *)apiKey afterDelay:(NSTimeInterval)delay CLS_DEPRECATED("Crashlytics no longer needs or uses the delay parameter. Please use +startWithAPIKey: instead.");
-
-/**
- * If you need the functionality provided by the CrashlyticsDelegate protocol, you can use
- * these convenience methods to activate the framework and set the delegate in one call.
- *
- * @param apiKey The Crashlytics API Key for this app
- * @param delegate A delegate object which conforms to CrashlyticsDelegate.
- *
- * @return The singleton Crashlytics instance
- */
-+ (Crashlytics *)startWithAPIKey:(NSString *)apiKey delegate:(nullable id)delegate;
-+ (Crashlytics *)startWithAPIKey:(NSString *)apiKey delegate:(nullable id)delegate afterDelay:(NSTimeInterval)delay CLS_DEPRECATED("Crashlytics no longer needs or uses the delay parameter. Please use +startWithAPIKey:delegate: instead.");
-
-/**
- * Access the singleton Crashlytics instance.
- *
- * @return The singleton Crashlytics instance
- */
-+ (Crashlytics *)sharedInstance;
-
-/**
- * The easiest way to cause a crash - great for testing!
- */
-- (void)crash;
-
-/**
- * The easiest way to cause a crash with an exception - great for testing.
- */
-- (void)throwException;
-
-/**
- * Specify a user identifier which will be visible in the Crashlytics UI.
- *
- * Many of our customers have requested the ability to tie crashes to specific end-users of their
- * application in order to facilitate responses to support requests or permit the ability to reach
- * out for more information. We allow you to specify up to three separate values for display within
- * the Crashlytics UI - but please be mindful of your end-user's privacy.
- *
- * We recommend specifying a user identifier - an arbitrary string that ties an end-user to a record
- * in your system. This could be a database id, hash, or other value that is meaningless to a
- * third-party observer but can be indexed and queried by you.
- *
- * Optionally, you may also specify the end-user's name or username, as well as email address if you
- * do not have a system that works well with obscured identifiers.
- *
- * Pursuant to our EULA, this data is transferred securely throughout our system and we will not
- * disseminate end-user data unless required to by law. That said, if you choose to provide end-user
- * contact information, we strongly recommend that you disclose this in your application's privacy
- * policy. Data privacy is of our utmost concern.
- *
- * @param identifier An arbitrary user identifier string which ties an end-user to a record in your system.
- */
-- (void)setUserIdentifier:(nullable NSString *)identifier;
-
-/**
- * Specify a user name which will be visible in the Crashlytics UI.
- * Please be mindful of your end-user's privacy and see if setUserIdentifier: can fulfil your needs.
- * @see setUserIdentifier:
- *
- * @param name An end user's name.
- */
-- (void)setUserName:(nullable NSString *)name;
-
-/**
- * Specify a user email which will be visible in the Crashlytics UI.
- * Please be mindful of your end-user's privacy and see if setUserIdentifier: can fulfil your needs.
- *
- * @see setUserIdentifier:
- *
- * @param email An end user's email address.
- */
-- (void)setUserEmail:(nullable NSString *)email;
-
-+ (void)setUserIdentifier:(nullable NSString *)identifier CLS_DEPRECATED("Please access this method via +sharedInstance");
-+ (void)setUserName:(nullable NSString *)name CLS_DEPRECATED("Please access this method via +sharedInstance");
-+ (void)setUserEmail:(nullable NSString *)email CLS_DEPRECATED("Please access this method via +sharedInstance");
-
-/**
- * Set a value for a for a key to be associated with your crash data which will be visible in the Crashlytics UI.
- * When setting an object value, the object is converted to a string. This is typically done by calling
- * -[NSObject description].
- *
- * @param value The object to be associated with the key
- * @param key The key with which to associate the value
- */
-- (void)setObjectValue:(nullable id)value forKey:(NSString *)key;
-
-/**
- * Set an int value for a key to be associated with your crash data which will be visible in the Crashlytics UI.
- *
- * @param value The integer value to be set
- * @param key The key with which to associate the value
- */
-- (void)setIntValue:(int)value forKey:(NSString *)key;
-
-/**
- * Set an BOOL value for a key to be associated with your crash data which will be visible in the Crashlytics UI.
- *
- * @param value The BOOL value to be set
- * @param key The key with which to associate the value
- */
-- (void)setBoolValue:(BOOL)value forKey:(NSString *)key;
-
-/**
- * Set an float value for a key to be associated with your crash data which will be visible in the Crashlytics UI.
- *
- * @param value The float value to be set
- * @param key The key with which to associate the value
- */
-- (void)setFloatValue:(float)value forKey:(NSString *)key;
-
-+ (void)setObjectValue:(nullable id)value forKey:(NSString *)key CLS_DEPRECATED("Please access this method via +sharedInstance");
-+ (void)setIntValue:(int)value forKey:(NSString *)key CLS_DEPRECATED("Please access this method via +sharedInstance");
-+ (void)setBoolValue:(BOOL)value forKey:(NSString *)key CLS_DEPRECATED("Please access this method via +sharedInstance");
-+ (void)setFloatValue:(float)value forKey:(NSString *)key CLS_DEPRECATED("Please access this method via +sharedInstance");
-
-/**
- * This method can be used to record a single exception structure in a report. This is particularly useful
- * when your code interacts with non-native languages like Lua, C#, or Javascript. This call can be
- * expensive and should only be used shortly before process termination. This API is not intended be to used
- * to log NSException objects. All safely-reportable NSExceptions are automatically captured by
- * Crashlytics.
- *
- * @param name The name of the custom exception
- * @param reason The reason this exception occurred
- * @param frameArray An array of CLSStackFrame objects
- */
-- (void)recordCustomExceptionName:(NSString *)name reason:(nullable NSString *)reason frameArray:(CLS_GENERIC_NSARRAY(CLSStackFrame *) *)frameArray;
-
-/**
- *
- * This allows you to record a non-fatal event, described by an NSError object. These events will be grouped and
- * displayed similarly to crashes. Keep in mind that this method can be expensive. Also, the total number of
- * NSErrors that can be recorded during your app's life-cycle is limited by a fixed-size circular buffer. If the
- * buffer is overrun, the oldest data is dropped. Errors are relayed to Crashlytics on a subsequent launch
- * of your application.
- *
- * You can also use the -recordError:withAdditionalUserInfo: to include additional context not represented
- * by the NSError instance itself.
- *
- **/
-- (void)recordError:(NSError *)error;
-- (void)recordError:(NSError *)error withAdditionalUserInfo:(nullable CLS_GENERIC_NSDICTIONARY(NSString *, id) *)userInfo;
-
-- (void)logEvent:(NSString *)eventName CLS_DEPRECATED("Please refer to Answers +logCustomEventWithName:");
-- (void)logEvent:(NSString *)eventName attributes:(nullable NSDictionary *) attributes CLS_DEPRECATED("Please refer to Answers +logCustomEventWithName:");
-+ (void)logEvent:(NSString *)eventName CLS_DEPRECATED("Please refer to Answers +logCustomEventWithName:");
-+ (void)logEvent:(NSString *)eventName attributes:(nullable NSDictionary *) attributes CLS_DEPRECATED("Please refer to Answers +logCustomEventWithName:");
-
-@end
-
-/**
- *
- * The CrashlyticsDelegate protocol provides a mechanism for your application to take
- * action on events that occur in the Crashlytics crash reporting system. You can make
- * use of these calls by assigning an object to the Crashlytics' delegate property directly,
- * or through the convenience +startWithAPIKey:delegate: method.
- *
- */
-@protocol CrashlyticsDelegate
-@optional
-
-
-- (void)crashlyticsDidDetectCrashDuringPreviousExecution:(Crashlytics *)crashlytics CLS_DEPRECATED("Please refer to -crashlyticsDidDetectReportForLastExecution:");
-- (void)crashlytics:(Crashlytics *)crashlytics didDetectCrashDuringPreviousExecution:(id )crash CLS_DEPRECATED("Please refer to -crashlyticsDidDetectReportForLastExecution:");
-
-/**
- *
- * Called when a Crashlytics instance has determined that the last execution of the
- * application resulted in a saved report. This is called synchronously on Crashlytics
- * initialization. Your delegate must invoke the completionHandler, but does not need to do so
- * synchronously, or even on the main thread. Invoking completionHandler with NO will cause the
- * detected report to be deleted and not submitted to Crashlytics. This is useful for
- * implementing permission prompts, or other more-complex forms of logic around submitting crashes.
- *
- * Instead of using this method, you should try to make use of -crashlyticsDidDetectReportForLastExecution:
- * if you can.
- *
- * @warning Failure to invoke the completionHandler will prevent submissions from being reported. Watch out.
- *
- * @warning Just implementing this delegate method will disable all forms of synchronous report submission. This can
- * impact the reliability of reporting crashes very early in application launch.
- *
- * @param report The CLSReport object representing the last detected report
- * @param completionHandler The completion handler to call when your logic has completed.
- *
- */
-- (void)crashlyticsDidDetectReportForLastExecution:(CLSReport *)report completionHandler:(void (^)(BOOL submit))completionHandler;
-
-/**
- *
- * Called when a Crashlytics instance has determined that the last execution of the
- * application resulted in a saved report. This method differs from
- * -crashlyticsDidDetectReportForLastExecution:completionHandler: in three important ways:
- *
- * - it is not called synchronously during initialization
- * - it does not give you the ability to prevent the report from being submitted
- * - the report object itself is immutable
- *
- * Thanks to these limitations, making use of this method does not impact reporting
- * reliabilty in any way.
- *
- * @param report The read-only CLSReport object representing the last detected report
- *
- */
-
-- (void)crashlyticsDidDetectReportForLastExecution:(CLSReport *)report;
-
-/**
- * If your app is running on an OS that supports it (OS X 10.9+, iOS 7.0+), Crashlytics will submit
- * most reports using out-of-process background networking operations. This results in a significant
- * improvement in reliability of reporting, as well as power and performance wins for your users.
- * If you don't want this functionality, you can disable by returning NO from this method.
- *
- * @warning Background submission is not supported for extensions on iOS or OS X.
- *
- * @param crashlytics The Crashlytics singleton instance
- *
- * @return Return NO if you don't want out-of-process background network operations.
- *
- */
-- (BOOL)crashlyticsCanUseBackgroundSessions:(Crashlytics *)crashlytics;
-
-@end
-
-/**
- * `CrashlyticsKit` can be used as a parameter to `[Fabric with:@[CrashlyticsKit]];` in Objective-C. In Swift, use Crashlytics.sharedInstance()
- */
-#define CrashlyticsKit [Crashlytics sharedInstance]
-
-NS_ASSUME_NONNULL_END
diff --git a/ios/Pods/Crashlytics/iOS/Crashlytics.framework/Info.plist b/ios/Pods/Crashlytics/iOS/Crashlytics.framework/Info.plist
deleted file mode 100644
index d86059be5..000000000
Binary files a/ios/Pods/Crashlytics/iOS/Crashlytics.framework/Info.plist and /dev/null differ
diff --git a/ios/Pods/Crashlytics/iOS/Crashlytics.framework/Modules/module.modulemap b/ios/Pods/Crashlytics/iOS/Crashlytics.framework/Modules/module.modulemap
deleted file mode 100644
index da0845e39..000000000
--- a/ios/Pods/Crashlytics/iOS/Crashlytics.framework/Modules/module.modulemap
+++ /dev/null
@@ -1,14 +0,0 @@
-framework module Crashlytics {
- header "Crashlytics.h"
- header "Answers.h"
- header "ANSCompatibility.h"
- header "CLSLogging.h"
- header "CLSReport.h"
- header "CLSStackFrame.h"
- header "CLSAttributes.h"
-
- export *
-
- link "z"
- link "c++"
-}
diff --git a/ios/Pods/Crashlytics/iOS/Crashlytics.framework/run b/ios/Pods/Crashlytics/iOS/Crashlytics.framework/run
deleted file mode 100755
index 736cd2ff5..000000000
--- a/ios/Pods/Crashlytics/iOS/Crashlytics.framework/run
+++ /dev/null
@@ -1,73 +0,0 @@
-#!/bin/sh
-
-# run
-#
-# Copyright (c) 2015 Crashlytics. All rights reserved.
-#
-#
-# This script is meant to be run as a Run Script in the "Build Phases" section
-# of your Xcode project. It sends debug symbols to symbolicate stacktraces,
-# sends build events to track versions, and onboard apps for Crashlytics.
-#
-# This script calls upload-symbols twice:
-#
-# 1) First it calls upload-symbols synchronously in "validation" mode. If the
-# script finds issues with the build environment, it will report errors to Xcode.
-# In validation mode it exits before doing any time consuming work.
-#
-# 2) Then it calls upload-symbols in the background to actually send the build
-# event and upload symbols. It does this in the background so that it doesn't
-# slow down your builds. If an error happens here, you won't see it in Xcode.
-#
-# You can find the output for the background execution in Console.app, by
-# searching for "upload-symbols".
-#
-# If you want verbose output, you can pass the --debug flag to this script
-#
-
-# Figure out where we're being called from
-DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
-
-# If the first argument is specified without a dash, treat it as the Fabric API
-# Key and add it as an argument
-if [ -z "$1" ] || [[ $1 == -* ]]; then
- API_KEY_ARG=""
-else
- API_KEY_ARG="-a $1"; shift
-fi
-
-# If a second argument is specified without a dash, treat it as the Build Secret
-# and add it as an argument
-if [ -z "$1" ] || [[ $1 == -* ]]; then
- BUILD_SECRET_ARG=""
-else
- BUILD_SECRET_ARG="-bs $1"; shift
-fi
-
-# Build up the arguments list, passing through any flags added after the
-# API Key and Build Secret
-ARGUMENTS="$API_KEY_ARG $BUILD_SECRET_ARG $@"
-VALIDATE_ARGUMENTS="$ARGUMENTS --build-phase --validate"
-UPLOAD_ARGUMENTS="$ARGUMENTS --build-phase"
-
-# Quote the path to handle folders with special characters
-COMMAND_PATH="\"$DIR/upload-symbols\" "
-
-# Ensure params are as expected, run in sync mode to validate,
-# and cause a build error if validation fails
-eval $COMMAND_PATH$VALIDATE_ARGUMENTS
-return_code=$?
-
-if [[ $return_code != 0 ]]; then
- exit $return_code
-fi
-
-# Verification passed, convert and upload cSYMs in the background to prevent
-# build delays
-#
-# Note: Validation is performed again at this step before upload
-#
-# Note: Output can still be found in Console.app, by searching for
-# "upload-symbols"
-#
-eval $COMMAND_PATH$UPLOAD_ARGUMENTS > /dev/null 2>&1 &
diff --git a/ios/Pods/Crashlytics/iOS/Crashlytics.framework/submit b/ios/Pods/Crashlytics/iOS/Crashlytics.framework/submit
deleted file mode 100755
index 3fda5cff1..000000000
Binary files a/ios/Pods/Crashlytics/iOS/Crashlytics.framework/submit and /dev/null differ
diff --git a/ios/Pods/Crashlytics/iOS/Crashlytics.framework/upload-symbols b/ios/Pods/Crashlytics/iOS/Crashlytics.framework/upload-symbols
deleted file mode 100755
index 5af65decc..000000000
Binary files a/ios/Pods/Crashlytics/iOS/Crashlytics.framework/upload-symbols and /dev/null differ
diff --git a/ios/Pods/Crashlytics/submit b/ios/Pods/Crashlytics/submit
deleted file mode 100755
index 3fda5cff1..000000000
Binary files a/ios/Pods/Crashlytics/submit and /dev/null differ
diff --git a/ios/Pods/Fabric/Fabric.framework/README b/ios/Pods/Fabric/Fabric.framework/README
deleted file mode 100644
index 3b1fbe24e..000000000
--- a/ios/Pods/Fabric/Fabric.framework/README
+++ /dev/null
@@ -1 +0,0 @@
-We've now combined all our supported platforms into a single podspec. As a result, we moved our run script to a new location for Cocoapods projects: ${PODS_ROOT}/Fabric/run. To avoid breaking builds that reference the old location of the run script, we've placed this dummy script that calls to the correct location, while providing a helpful warning in Xcode if it is invoked. This bridge for backwards compatibility will be removed in a future release, so please heed the warning!
diff --git a/ios/Pods/Fabric/Fabric.framework/run b/ios/Pods/Fabric/Fabric.framework/run
deleted file mode 100755
index b9edd17f9..000000000
--- a/ios/Pods/Fabric/Fabric.framework/run
+++ /dev/null
@@ -1,6 +0,0 @@
-if [[ -z $PODS_ROOT ]]; then
- echo "error: The run binary delivered by cocoapods is in a new location, under '$"{"PODS_ROOT"}"/Fabric/run'. This script was put in place for backwards compatibility, but it relies on PODS_ROOT, which does not have a value in your current setup. Please update the path to the run binary to fix this issue."
-else
- echo "warning: The run script is now located at '$"{"PODS_ROOT"}"/Fabric/run'. To remove this warning, update your Run Script Build Phase to point to this new location."
- sh "${PODS_ROOT}/Fabric/run" "$@"
-fi
diff --git a/ios/Pods/Fabric/README.md b/ios/Pods/Fabric/README.md
deleted file mode 100644
index e99ce8344..000000000
--- a/ios/Pods/Fabric/README.md
+++ /dev/null
@@ -1,27 +0,0 @@
-
-# Fabric
-
-## Overview
-
-[Fabric](https://get.fabric.io) provides developers with the tools they need to build the best apps. Developed and maintained by Google and the team that built Crashlytics.
-
-For a full list of SDKs provided through Fabric visit [https://fabric.io/kits](https://fabric.io/kits).
-
-To follow the migration to Firebase, check out the [Fabric Roadmap](https://get.fabric.io/roadmap).
-
-
-## Setup
-
-Fabric is a dependency for the Crashlytics SDK. To start using Crashlytics, there are two options:
-
-1) The recommended way is to go to the [Firebase Crashlytics Docs](https://firebase.google.com/docs/crashlytics/get-started?platform=ios) and follow the directions there.
-
-2) If you aren't using Firebase yet, go to [Fabric Kits](https://fabric.io/kits), and follow the directions for Crashlytics.
-
-
-## Resources
-
-* [Documentation](https://docs.fabric.io/)
-* [Forums](https://stackoverflow.com/questions/tagged/google-fabric)
-* [Website](https://get.fabric.io)
-* Follow us on Twitter: [@fabric](https://twitter.com/fabric)
diff --git a/ios/Pods/Fabric/iOS/Fabric.framework/Fabric b/ios/Pods/Fabric/iOS/Fabric.framework/Fabric
deleted file mode 100755
index aa394a3de..000000000
Binary files a/ios/Pods/Fabric/iOS/Fabric.framework/Fabric and /dev/null differ
diff --git a/ios/Pods/Fabric/iOS/Fabric.framework/Headers/FABAttributes.h b/ios/Pods/Fabric/iOS/Fabric.framework/Headers/FABAttributes.h
deleted file mode 100644
index 3a9355a7c..000000000
--- a/ios/Pods/Fabric/iOS/Fabric.framework/Headers/FABAttributes.h
+++ /dev/null
@@ -1,51 +0,0 @@
-//
-// FABAttributes.h
-// Fabric
-//
-// Copyright (C) 2015 Twitter, 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.
-//
-
-#pragma once
-
-#define FAB_UNAVAILABLE(x) __attribute__((unavailable(x)))
-
-#if !__has_feature(nullability)
- #define nonnull
- #define nullable
- #define _Nullable
- #define _Nonnull
-#endif
-
-#ifndef NS_ASSUME_NONNULL_BEGIN
- #define NS_ASSUME_NONNULL_BEGIN
-#endif
-
-#ifndef NS_ASSUME_NONNULL_END
- #define NS_ASSUME_NONNULL_END
-#endif
-
-
-/**
- * The following macros are defined here to provide
- * backwards compatability. If you are still using
- * them you should migrate to the native nullability
- * macros.
- */
-#define fab_nullable nullable
-#define fab_nonnull nonnull
-#define FAB_NONNULL __fab_nonnull
-#define FAB_NULLABLE __fab_nullable
-#define FAB_START_NONNULL NS_ASSUME_NONNULL_BEGIN
-#define FAB_END_NONNULL NS_ASSUME_NONNULL_END
diff --git a/ios/Pods/Fabric/iOS/Fabric.framework/Headers/Fabric.h b/ios/Pods/Fabric/iOS/Fabric.framework/Headers/Fabric.h
deleted file mode 100644
index ecbdb53b8..000000000
--- a/ios/Pods/Fabric/iOS/Fabric.framework/Headers/Fabric.h
+++ /dev/null
@@ -1,82 +0,0 @@
-//
-// Fabric.h
-// Fabric
-//
-// Copyright (C) 2015 Twitter, 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
-#import "FABAttributes.h"
-
-NS_ASSUME_NONNULL_BEGIN
-
-#if TARGET_OS_IPHONE
-#if __IPHONE_OS_VERSION_MIN_REQUIRED < 60000
- #error "Fabric's minimum iOS version is 6.0"
-#endif
-#else
-#if __MAC_OS_X_VERSION_MIN_REQUIRED < 1070
- #error "Fabric's minimum OS X version is 10.7"
-#endif
-#endif
-
-/**
- * Fabric Base. Coordinates configuration and starts all provided kits.
- */
-@interface Fabric : NSObject
-
-/**
- * Initialize Fabric and all provided kits. Call this method within your App Delegate's `application:didFinishLaunchingWithOptions:` and provide the kits you wish to use.
- *
- * For example, in Objective-C:
- *
- * `[Fabric with:@[[Crashlytics class], [Twitter class], [Digits class], [MoPub class]]];`
- *
- * Swift:
- *
- * `Fabric.with([Crashlytics.self(), Twitter.self(), Digits.self(), MoPub.self()])`
- *
- * Only the first call to this method is honored. Subsequent calls are no-ops.
- *
- * @param kitClasses An array of kit Class objects
- *
- * @return Returns the shared Fabric instance. In most cases this can be ignored.
- */
-+ (instancetype)with:(NSArray *)kitClasses;
-
-/**
- * Returns the Fabric singleton object.
- */
-+ (instancetype)sharedSDK;
-
-/**
- * This BOOL enables or disables debug logging, such as kit version information. The default value is NO.
- */
-@property (nonatomic, assign) BOOL debug;
-
-/**
- * Unavailable. Use `+sharedSDK` to retrieve the shared Fabric instance.
- */
-- (id)init FAB_UNAVAILABLE("Use +sharedSDK to retrieve the shared Fabric instance.");
-
-/**
- * Unavailable. Use `+sharedSDK` to retrieve the shared Fabric instance.
- */
-+ (instancetype)new FAB_UNAVAILABLE("Use +sharedSDK to retrieve the shared Fabric instance.");
-
-@end
-
-NS_ASSUME_NONNULL_END
-
diff --git a/ios/Pods/Fabric/iOS/Fabric.framework/Info.plist b/ios/Pods/Fabric/iOS/Fabric.framework/Info.plist
deleted file mode 100644
index a617b035f..000000000
Binary files a/ios/Pods/Fabric/iOS/Fabric.framework/Info.plist and /dev/null differ
diff --git a/ios/Pods/Fabric/iOS/Fabric.framework/Modules/module.modulemap b/ios/Pods/Fabric/iOS/Fabric.framework/Modules/module.modulemap
deleted file mode 100644
index 2a312239d..000000000
--- a/ios/Pods/Fabric/iOS/Fabric.framework/Modules/module.modulemap
+++ /dev/null
@@ -1,6 +0,0 @@
-framework module Fabric {
- umbrella header "Fabric.h"
-
- export *
- module * { export * }
-}
\ No newline at end of file
diff --git a/ios/Pods/Fabric/iOS/Fabric.framework/run b/ios/Pods/Fabric/iOS/Fabric.framework/run
deleted file mode 100755
index 736cd2ff5..000000000
--- a/ios/Pods/Fabric/iOS/Fabric.framework/run
+++ /dev/null
@@ -1,73 +0,0 @@
-#!/bin/sh
-
-# run
-#
-# Copyright (c) 2015 Crashlytics. All rights reserved.
-#
-#
-# This script is meant to be run as a Run Script in the "Build Phases" section
-# of your Xcode project. It sends debug symbols to symbolicate stacktraces,
-# sends build events to track versions, and onboard apps for Crashlytics.
-#
-# This script calls upload-symbols twice:
-#
-# 1) First it calls upload-symbols synchronously in "validation" mode. If the
-# script finds issues with the build environment, it will report errors to Xcode.
-# In validation mode it exits before doing any time consuming work.
-#
-# 2) Then it calls upload-symbols in the background to actually send the build
-# event and upload symbols. It does this in the background so that it doesn't
-# slow down your builds. If an error happens here, you won't see it in Xcode.
-#
-# You can find the output for the background execution in Console.app, by
-# searching for "upload-symbols".
-#
-# If you want verbose output, you can pass the --debug flag to this script
-#
-
-# Figure out where we're being called from
-DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
-
-# If the first argument is specified without a dash, treat it as the Fabric API
-# Key and add it as an argument
-if [ -z "$1" ] || [[ $1 == -* ]]; then
- API_KEY_ARG=""
-else
- API_KEY_ARG="-a $1"; shift
-fi
-
-# If a second argument is specified without a dash, treat it as the Build Secret
-# and add it as an argument
-if [ -z "$1" ] || [[ $1 == -* ]]; then
- BUILD_SECRET_ARG=""
-else
- BUILD_SECRET_ARG="-bs $1"; shift
-fi
-
-# Build up the arguments list, passing through any flags added after the
-# API Key and Build Secret
-ARGUMENTS="$API_KEY_ARG $BUILD_SECRET_ARG $@"
-VALIDATE_ARGUMENTS="$ARGUMENTS --build-phase --validate"
-UPLOAD_ARGUMENTS="$ARGUMENTS --build-phase"
-
-# Quote the path to handle folders with special characters
-COMMAND_PATH="\"$DIR/upload-symbols\" "
-
-# Ensure params are as expected, run in sync mode to validate,
-# and cause a build error if validation fails
-eval $COMMAND_PATH$VALIDATE_ARGUMENTS
-return_code=$?
-
-if [[ $return_code != 0 ]]; then
- exit $return_code
-fi
-
-# Verification passed, convert and upload cSYMs in the background to prevent
-# build delays
-#
-# Note: Validation is performed again at this step before upload
-#
-# Note: Output can still be found in Console.app, by searching for
-# "upload-symbols"
-#
-eval $COMMAND_PATH$UPLOAD_ARGUMENTS > /dev/null 2>&1 &
diff --git a/ios/Pods/Fabric/iOS/Fabric.framework/upload-symbols b/ios/Pods/Fabric/iOS/Fabric.framework/upload-symbols
deleted file mode 100755
index a18d0b68f..000000000
Binary files a/ios/Pods/Fabric/iOS/Fabric.framework/upload-symbols and /dev/null differ
diff --git a/ios/Pods/Fabric/run b/ios/Pods/Fabric/run
deleted file mode 100755
index 736cd2ff5..000000000
--- a/ios/Pods/Fabric/run
+++ /dev/null
@@ -1,73 +0,0 @@
-#!/bin/sh
-
-# run
-#
-# Copyright (c) 2015 Crashlytics. All rights reserved.
-#
-#
-# This script is meant to be run as a Run Script in the "Build Phases" section
-# of your Xcode project. It sends debug symbols to symbolicate stacktraces,
-# sends build events to track versions, and onboard apps for Crashlytics.
-#
-# This script calls upload-symbols twice:
-#
-# 1) First it calls upload-symbols synchronously in "validation" mode. If the
-# script finds issues with the build environment, it will report errors to Xcode.
-# In validation mode it exits before doing any time consuming work.
-#
-# 2) Then it calls upload-symbols in the background to actually send the build
-# event and upload symbols. It does this in the background so that it doesn't
-# slow down your builds. If an error happens here, you won't see it in Xcode.
-#
-# You can find the output for the background execution in Console.app, by
-# searching for "upload-symbols".
-#
-# If you want verbose output, you can pass the --debug flag to this script
-#
-
-# Figure out where we're being called from
-DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
-
-# If the first argument is specified without a dash, treat it as the Fabric API
-# Key and add it as an argument
-if [ -z "$1" ] || [[ $1 == -* ]]; then
- API_KEY_ARG=""
-else
- API_KEY_ARG="-a $1"; shift
-fi
-
-# If a second argument is specified without a dash, treat it as the Build Secret
-# and add it as an argument
-if [ -z "$1" ] || [[ $1 == -* ]]; then
- BUILD_SECRET_ARG=""
-else
- BUILD_SECRET_ARG="-bs $1"; shift
-fi
-
-# Build up the arguments list, passing through any flags added after the
-# API Key and Build Secret
-ARGUMENTS="$API_KEY_ARG $BUILD_SECRET_ARG $@"
-VALIDATE_ARGUMENTS="$ARGUMENTS --build-phase --validate"
-UPLOAD_ARGUMENTS="$ARGUMENTS --build-phase"
-
-# Quote the path to handle folders with special characters
-COMMAND_PATH="\"$DIR/upload-symbols\" "
-
-# Ensure params are as expected, run in sync mode to validate,
-# and cause a build error if validation fails
-eval $COMMAND_PATH$VALIDATE_ARGUMENTS
-return_code=$?
-
-if [[ $return_code != 0 ]]; then
- exit $return_code
-fi
-
-# Verification passed, convert and upload cSYMs in the background to prevent
-# build delays
-#
-# Note: Validation is performed again at this step before upload
-#
-# Note: Output can still be found in Console.app, by searching for
-# "upload-symbols"
-#
-eval $COMMAND_PATH$UPLOAD_ARGUMENTS > /dev/null 2>&1 &
diff --git a/ios/Pods/Fabric/upload-symbols b/ios/Pods/Fabric/upload-symbols
deleted file mode 100755
index a18d0b68f..000000000
Binary files a/ios/Pods/Fabric/upload-symbols and /dev/null differ
diff --git a/ios/Pods/Firebase/README.md b/ios/Pods/Firebase/README.md
index 1747cca7a..d778205ff 100644
--- a/ios/Pods/Firebase/README.md
+++ b/ios/Pods/Firebase/README.md
@@ -2,14 +2,20 @@
[![License](https://img.shields.io/cocoapods/l/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase)
[![Platform](https://img.shields.io/cocoapods/p/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase)
+[![Actions Status][gh-abtesting-badge]][gh-actions]
[![Actions Status][gh-auth-badge]][gh-actions]
[![Actions Status][gh-core-badge]][gh-actions]
+[![Actions Status][gh-crashlytics-badge]][gh-actions]
+[![Actions Status][gh-database-badge]][gh-actions]
[![Actions Status][gh-datatransport-badge]][gh-actions]
[![Actions Status][gh-dynamiclinks-badge]][gh-actions]
[![Actions Status][gh-firebasepod-badge]][gh-actions]
[![Actions Status][gh-firestore-badge]][gh-actions]
+[![Actions Status][gh-functions-badge]][gh-actions]
+[![Actions Status][gh-inappmessaging-badge]][gh-actions]
[![Actions Status][gh-interop-badge]][gh-actions]
[![Actions Status][gh-messaging-badge]][gh-actions]
+[![Actions Status][gh-remoteconfig-badge]][gh-actions]
[![Actions Status][gh-storage-badge]][gh-actions]
[![Actions Status][gh-symbolcollision-badge]][gh-actions]
[![Actions Status][gh-zip-badge]][gh-actions]
@@ -92,7 +98,7 @@ Instructions for installing binary frameworks via
To develop Firebase software in this repository, ensure that you have at least
the following software:
- * Xcode 10.1 (or later)
+ * Xcode 10.3 (or later)
* CocoaPods 1.7.2 (or later)
* [CocoaPods generate](https://github.com/square/cocoapods-generate)
@@ -123,6 +129,10 @@ Firestore has a self contained Xcode project. See
See [AddNewPod.md](AddNewPod.md).
+### Managing Headers and Imports
+
+See [HeadersImports.md](HeadersImports.md).
+
### Code Formatting
To ensure that the code is formatted consistently, run the script
@@ -185,8 +195,16 @@ building and running the FirebaseAuth pod along with various samples and tests.
### Firebase Database
-To run the Database Integration tests, make your database authentication rules
-[public](https://firebase.google.com/docs/database/security/quickstart).
+The Firebase Database Integration tests can be run against a locally running Database Emulator
+or against a production instance.
+
+To run against a local emulator instance, invoke `./scripts/run_database_emulator.sh start` before
+running the integration test.
+
+To run against a production instance, provide a valid GoogleServices-Info.plist and copy it to
+`Example/Database/App/GoogleService-Info.plist`. Your Security Rule must be set to
+[public](https://firebase.google.com/docs/database/security/quickstart) while your tests are
+running.
### Firebase Storage
@@ -274,14 +292,20 @@ Your use of Firebase is governed by the
[Terms of Service for Firebase Services](https://firebase.google.com/terms/).
[gh-actions]: https://github.com/firebase/firebase-ios-sdk/actions
+[gh-abtesting-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/abtesting/badge.svg
[gh-auth-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/auth/badge.svg
[gh-core-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/core/badge.svg
+[gh-crashlytics-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/crashlytics/badge.svg
+[gh-database-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/database/badge.svg
[gh-datatransport-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/datatransport/badge.svg
[gh-dynamiclinks-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/dynamiclinks/badge.svg
[gh-firebasepod-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/firebasepod/badge.svg
[gh-firestore-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/firestore/badge.svg
+[gh-functions-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/functions/badge.svg
+[gh-inappmessaging-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/inappmessaging/badge.svg
[gh-interop-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/interop/badge.svg
[gh-messaging-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/messaging/badge.svg
+[gh-remoteconfig-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/remoteconfig/badge.svg
[gh-storage-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/storage/badge.svg
[gh-symbolcollision-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/symbolcollision/badge.svg
[gh-zip-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/zip/badge.svg
diff --git a/ios/Pods/FirebaseAnalytics/Frameworks/FIRAnalyticsConnector.framework/FIRAnalyticsConnector b/ios/Pods/FirebaseAnalytics/Frameworks/FIRAnalyticsConnector.framework/FIRAnalyticsConnector
index bb3a7cae8..8746d38f6 100755
Binary files a/ios/Pods/FirebaseAnalytics/Frameworks/FIRAnalyticsConnector.framework/FIRAnalyticsConnector and b/ios/Pods/FirebaseAnalytics/Frameworks/FIRAnalyticsConnector.framework/FIRAnalyticsConnector differ
diff --git a/ios/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/FirebaseAnalytics b/ios/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/FirebaseAnalytics
index 46030f0c4..e00c279a8 100755
Binary files a/ios/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/FirebaseAnalytics and b/ios/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/FirebaseAnalytics differ
diff --git a/ios/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRAnalytics.h b/ios/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRAnalytics.h
index be0b1faee..15b693c90 100755
--- a/ios/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRAnalytics.h
+++ b/ios/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRAnalytics.h
@@ -90,12 +90,10 @@ NS_SWIFT_NAME(Analytics)
/// Must be called on the main thread.
///
/// Note that screen reporting is enabled automatically and records the class name of the current
-/// UIViewController for you without requiring you to call this method. If you implement
-/// viewDidAppear in your UIViewController but do not call [super viewDidAppear:], that screen class
-/// will not be automatically tracked. The class name can optionally be overridden by calling this
-/// method in the viewDidAppear callback of your UIViewController and specifying the
-/// screenClassOverride parameter. setScreenName:screenClass: must be called after
-/// [super viewDidAppear:].
+/// UIViewController for you without requiring you to call this method. The class name can
+/// optionally be overridden by calling this method in the viewDidAppear callback of your
+/// UIViewController and specifying the screenClassOverride parameter.
+/// `setScreenName:screenClass:` must be called after `[super viewDidAppear:]`.
///
/// If your app does not use a distinct UIViewController for each screen, you should call this
/// method and specify a distinct screenName each time a new screen is presented to the user.
@@ -103,6 +101,9 @@ NS_SWIFT_NAME(Analytics)
/// The screen name and screen class remain in effect until the current UIViewController changes or
/// a new call to setScreenName:screenClass: is made.
///
+/// @warning If you override `viewDidAppear:` in your UIViewController but do not call
+/// `[super viewDidAppear:]`, that screen class will not be tracked.
+///
/// @param screenName The name of the current screen. Should contain 1 to 100 characters. Set to nil
/// to clear the current screen name.
/// @param screenClassOverride The name of the screen class. Should contain 1 to 100 characters. By
diff --git a/ios/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIREventNames.h b/ios/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIREventNames.h
index 674f8b121..807b6159e 100755
--- a/ios/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIREventNames.h
+++ b/ios/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIREventNames.h
@@ -366,7 +366,6 @@ static NSString *const kFIREventViewItemList NS_SWIFT_NAME(AnalyticsEventViewIte
///
/// - @c kFIRParameterSearchTerm (NSString)
///
-/// This constant has been deprecated.
static NSString *const kFIREventViewSearchResults NS_SWIFT_NAME(AnalyticsEventViewSearchResults) =
@"view_search_results";
diff --git a/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRAnalyticsConfiguration.h b/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRAnalyticsConfiguration.h
similarity index 100%
rename from ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRAnalyticsConfiguration.h
rename to ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRAnalyticsConfiguration.h
diff --git a/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRAnalyticsConfiguration.m b/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRAnalyticsConfiguration.m
index 3a7d6de0e..07c786cb7 100644
--- a/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRAnalyticsConfiguration.m
+++ b/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRAnalyticsConfiguration.m
@@ -14,7 +14,7 @@
#import
-#import "FirebaseCore/Sources/Private/FIRAnalyticsConfiguration.h"
+#import "FirebaseCore/Sources/FIRAnalyticsConfiguration.h"
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-implementations"
diff --git a/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRApp.m b/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRApp.m
index 002f93c51..4dfbfa838 100644
--- a/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRApp.m
+++ b/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRApp.m
@@ -22,14 +22,14 @@
#import
#endif
-#import
+#import "FirebaseCore/Sources/Public/FIRApp.h"
+#import "FirebaseCore/Sources/FIRAnalyticsConfiguration.h"
#import "FirebaseCore/Sources/FIRBundleUtil.h"
+#import "FirebaseCore/Sources/FIRComponentContainerInternal.h"
+#import "FirebaseCore/Sources/FIRConfigurationInternal.h"
#import "FirebaseCore/Sources/FIRVersion.h"
-#import "FirebaseCore/Sources/Private/FIRAnalyticsConfiguration.h"
#import "FirebaseCore/Sources/Private/FIRAppInternal.h"
-#import "FirebaseCore/Sources/Private/FIRComponentContainerInternal.h"
-#import "FirebaseCore/Sources/Private/FIRConfigurationInternal.h"
#import "FirebaseCore/Sources/Private/FIRCoreDiagnosticsConnector.h"
#import "FirebaseCore/Sources/Private/FIRLibrary.h"
#import "FirebaseCore/Sources/Private/FIRLogger.h"
@@ -166,7 +166,7 @@ static dispatch_once_t sFirebaseUserAgentOnceToken;
if ([name isEqualToString:kFIRDefaultAppName]) {
if (sDefaultApp) {
- // The default app already exixts. Handle duplicate `configure` calls and return.
+ // The default app already exists. Handle duplicate `configure` calls and return.
[self appWasConfiguredTwice:sDefaultApp usingOptions:options];
return;
}
diff --git a/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRAppAssociationRegistration.h b/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRAppAssociationRegistration.h
similarity index 100%
rename from ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRAppAssociationRegistration.h
rename to ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRAppAssociationRegistration.h
diff --git a/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRAppAssociationRegistration.m b/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRAppAssociationRegistration.m
index e4125cd25..f3f812c74 100644
--- a/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRAppAssociationRegistration.m
+++ b/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRAppAssociationRegistration.m
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#import "FirebaseCore/Sources/Private/FIRAppAssociationRegistration.h"
+#import "FirebaseCore/Sources/FIRAppAssociationRegistration.h"
#import
diff --git a/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRBundleUtil.m b/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRBundleUtil.m
index b858f14c4..de2c29542 100644
--- a/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRBundleUtil.m
+++ b/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRBundleUtil.m
@@ -49,15 +49,19 @@
+ (BOOL)hasBundleIdentifierPrefix:(NSString *)bundleIdentifier inBundles:(NSArray *)bundles {
for (NSBundle *bundle in bundles) {
- // This allows app extensions that have the app's bundle as their prefix to pass this test.
- NSString *applicationBundleIdentifier =
- [GULAppEnvironmentUtil isAppExtension]
- ? [self bundleIdentifierByRemovingLastPartFrom:bundle.bundleIdentifier]
- : bundle.bundleIdentifier;
-
- if ([applicationBundleIdentifier isEqualToString:bundleIdentifier]) {
+ if ([bundle.bundleIdentifier isEqualToString:bundleIdentifier]) {
return YES;
}
+
+ if ([GULAppEnvironmentUtil isAppExtension]) {
+ // A developer could be using the same `FIROptions` for both their app and extension. Since
+ // extensions have a suffix added to the bundleID, we consider a matching prefix as valid.
+ NSString *appBundleIDFromExtension =
+ [self bundleIdentifierByRemovingLastPartFrom:bundle.bundleIdentifier];
+ if ([appBundleIDFromExtension isEqualToString:bundleIdentifier]) {
+ return YES;
+ }
+ }
}
return NO;
}
diff --git a/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRComponentContainerInternal.h b/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRComponentContainerInternal.h
similarity index 93%
rename from ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRComponentContainerInternal.h
rename to ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRComponentContainerInternal.h
index bf39bc6ce..82356060d 100644
--- a/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRComponentContainerInternal.h
+++ b/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRComponentContainerInternal.h
@@ -15,8 +15,8 @@
*/
#import
-#import
-#import
+#import "FirebaseCore/Sources/Private/FIRComponent.h"
+#import "FirebaseCore/Sources/Private/FIRComponentContainer.h"
@class FIRApp;
diff --git a/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRComponentType.m b/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRComponentType.m
index 6410f2ea1..9051336a6 100644
--- a/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRComponentType.m
+++ b/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRComponentType.m
@@ -16,7 +16,7 @@
#import "FirebaseCore/Sources/Private/FIRComponentType.h"
-#import "FirebaseCore/Sources/Private/FIRComponentContainerInternal.h"
+#import "FirebaseCore/Sources/FIRComponentContainerInternal.h"
@implementation FIRComponentType
diff --git a/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRConfiguration.m b/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRConfiguration.m
index a1c9f4a2e..83b3248c3 100644
--- a/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRConfiguration.m
+++ b/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRConfiguration.m
@@ -12,9 +12,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#import "FirebaseCore/Sources/Private/FIRConfigurationInternal.h"
+#import "FirebaseCore/Sources/FIRConfigurationInternal.h"
-#import "FirebaseCore/Sources/Private/FIRAnalyticsConfiguration.h"
+#import "FirebaseCore/Sources/FIRAnalyticsConfiguration.h"
extern void FIRSetLoggerLevel(FIRLoggerLevel loggerLevel);
diff --git a/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRConfigurationInternal.h b/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRConfigurationInternal.h
new file mode 100644
index 000000000..ee1688670
--- /dev/null
+++ b/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRConfigurationInternal.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2019 Google
+ *
+ * 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 "FIRConfiguration.h"
+
+@class FIRAnalyticsConfiguration;
+
+@interface FIRConfiguration ()
+
+/**
+ * The configuration class for Firebase Analytics. This should be removed once the logic for
+ * enabling and disabling Analytics is moved to Analytics.
+ */
+@property(nonatomic, readwrite) FIRAnalyticsConfiguration *analyticsConfiguration;
+
+@end
diff --git a/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRCoreDiagnosticsConnector.m b/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRCoreDiagnosticsConnector.m
index 4981ca1b0..730dd6ef9 100644
--- a/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRCoreDiagnosticsConnector.m
+++ b/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRCoreDiagnosticsConnector.m
@@ -16,12 +16,12 @@
#import "FirebaseCore/Sources/Private/FIRCoreDiagnosticsConnector.h"
-#import
+#import "Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsInterop.h"
-#import
+#import "FirebaseCore/Sources/Public/FIROptions.h"
+#import "FirebaseCore/Sources/FIRDiagnosticsData.h"
#import "FirebaseCore/Sources/Private/FIRAppInternal.h"
-#import "FirebaseCore/Sources/Private/FIRDiagnosticsData.h"
#import "FirebaseCore/Sources/Private/FIROptionsInternal.h"
// Define the interop class symbol declared as an extern in FIRCoreDiagnosticsInterop.
diff --git a/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRDiagnosticsData.h b/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRDiagnosticsData.h
new file mode 100644
index 000000000..5b5ff8ad9
--- /dev/null
+++ b/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRDiagnosticsData.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2019 Google
+ *
+ * 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
+
+#import "Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsData.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+/** Implements the FIRCoreDiagnosticsData protocol to log diagnostics data. */
+@interface FIRDiagnosticsData : NSObject
+
+/** Inserts values into the diagnosticObjects dictionary if the value isn't nil.
+ *
+ * @param value The value to insert if it's not nil.
+ * @param key The key to associate it with.
+ */
+- (void)insertValue:(nullable id)value forKey:(NSString *)key;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRDiagnosticsData.m b/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRDiagnosticsData.m
index bbe0561d9..da9489d99 100644
--- a/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRDiagnosticsData.m
+++ b/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRDiagnosticsData.m
@@ -14,9 +14,9 @@
* limitations under the License.
*/
-#import "FirebaseCore/Sources/Private/FIRDiagnosticsData.h"
+#import "FirebaseCore/Sources/FIRDiagnosticsData.h"
-#import
+#import "FirebaseCore/Sources/Public/FIRApp.h"
#import "FirebaseCore/Sources/Private/FIRAppInternal.h"
#import "FirebaseCore/Sources/Private/FIROptionsInternal.h"
diff --git a/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRLogger.m b/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRLogger.m
index ba2ee1f58..a749cbd94 100644
--- a/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRLogger.m
+++ b/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRLogger.m
@@ -14,9 +14,9 @@
#import "FirebaseCore/Sources/Private/FIRLogger.h"
-#import
#import
#import
+#import "FirebaseCore/Sources/Public/FIRLoggerLevel.h"
#import "FirebaseCore/Sources/FIRVersion.h"
diff --git a/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRAppInternal.h b/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRAppInternal.h
index ad1a186b9..9a0c943db 100644
--- a/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRAppInternal.h
+++ b/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRAppInternal.h
@@ -14,8 +14,19 @@
* limitations under the License.
*/
+#if SWIFT_PACKAGE
+// TODO(paulb777): Investigate if there's a common strategy for both Cocoapods and Swift PM.
+#import "FIRApp.h"
+#else
#import
+#endif
+
+// The has_include is a workaround so the old IID needed for the FIS tests can find FIRErrors.h
+#if __has_include("FirebaseCore/Sources/Private/FIRErrors.h")
+#import "FirebaseCore/Sources/Private/FIRErrors.h"
+#else
#import
+#endif
@class FIRComponentContainer;
@protocol FIRLibrary;
diff --git a/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRComponentContainer.h b/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRComponentContainer.h
index 8dfab9c10..db2bafef8 100644
--- a/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRComponentContainer.h
+++ b/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRComponentContainer.h
@@ -15,8 +15,14 @@
*/
#import
+// The has_include is a workaround so the old IID needed for the FIS tests can find the headers.
+#if __has_include("FirebaseCore/Sources/Private/FIRComponentType.h")
+#import "FirebaseCore/Sources/Private/FIRComponentType.h"
+#import "FirebaseCore/Sources/Private/FIRLibrary.h"
+#else
#import
#import
+#endif
NS_ASSUME_NONNULL_BEGIN
diff --git a/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRErrorCode.h b/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRErrorCode.h
index f77b3d002..c90d9eecf 100644
--- a/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRErrorCode.h
+++ b/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRErrorCode.h
@@ -32,7 +32,8 @@ typedef NS_ENUM(NSInteger, FIRErrorCode) {
FIRErrorCodeInvalidAppID = -101,
/**
- * Error code for failing to configure a specific service.
+ * Error code for failing to configure a specific service. It's deprecated, but
+ * still used after copybara.
*/
FIRErrorCodeConfigFailed = -114,
};
diff --git a/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRLibrary.h b/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRLibrary.h
index af9d9685d..e7a9e077c 100644
--- a/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRLibrary.h
+++ b/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRLibrary.h
@@ -19,7 +19,12 @@
#import
+// The has_include is a workaround so the old IID needed for the FIS tests can find the headers.
+#if __has_include("FirebaseCore/Sources/Private/FIRComponent.h")
+#import "FirebaseCore/Sources/Private/FIRComponent.h"
+#else
#import
+#endif
@class FIRApp;
diff --git a/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRLogger.h b/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRLogger.h
index 548e389a4..6fd778441 100644
--- a/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRLogger.h
+++ b/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRLogger.h
@@ -16,7 +16,12 @@
#import
+#if SWIFT_PACKAGE
+// TODO(paulb777): Investigate if there's a common strategy for both Cocoapods and Swift PM.
+#import "FIRLoggerLevel.h"
+#else
#import
+#endif
NS_ASSUME_NONNULL_BEGIN
diff --git a/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIROptionsInternal.h b/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIROptionsInternal.h
index 0660a3cd8..acaf45868 100644
--- a/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIROptionsInternal.h
+++ b/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIROptionsInternal.h
@@ -14,7 +14,12 @@
* limitations under the License.
*/
+#if SWIFT_PACKAGE
+// TODO(paulb777): Investigate if there's a common strategy for both Cocoapods and Swift PM.
+#import "FIROptions.h"
+#else
#import
+#endif
/**
* Keys for the strings in the plist file.
diff --git a/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FirebaseCoreInternal.h b/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FirebaseCoreInternal.h
new file mode 100644
index 000000000..93af6cb8d
--- /dev/null
+++ b/ios/Pods/FirebaseCore/FirebaseCore/Sources/Private/FirebaseCoreInternal.h
@@ -0,0 +1,31 @@
+// Copyright 2020 Google LLC
+//
+// 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.
+
+// An umbrella header, for any other libraries in this repo to access Firebase Public and Private
+// headers. Any package manager complexity should be handled here.
+
+#if SWIFT_PACKAGE
+@import FirebaseCore;
+#else
+#import
+#endif
+
+#import "FirebaseCore/Sources/Private/FIRAppInternal.h"
+#import "FirebaseCore/Sources/Private/FIRComponent.h"
+#import "FirebaseCore/Sources/Private/FIRComponentContainer.h"
+#import "FirebaseCore/Sources/Private/FIRDependency.h"
+#import "FirebaseCore/Sources/Private/FIRHeartbeatInfo.h"
+#import "FirebaseCore/Sources/Private/FIRLibrary.h"
+#import "FirebaseCore/Sources/Private/FIRLogger.h"
+#import "FirebaseCore/Sources/Private/FIROptionsInternal.h"
diff --git a/ios/Pods/FirebaseCore/FirebaseCore/Sources/Public/FIRConfiguration.h b/ios/Pods/FirebaseCore/FirebaseCore/Sources/Public/FIRConfiguration.h
index 8de3b076a..2b8e678ce 100644
--- a/ios/Pods/FirebaseCore/FirebaseCore/Sources/Public/FIRConfiguration.h
+++ b/ios/Pods/FirebaseCore/FirebaseCore/Sources/Public/FIRConfiguration.h
@@ -16,7 +16,7 @@
#import
-#import
+#import "FIRLoggerLevel.h"
NS_ASSUME_NONNULL_BEGIN
diff --git a/ios/Pods/FirebaseCoreDiagnosticsInterop/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsData.h b/ios/Pods/FirebaseCore/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsData.h
similarity index 100%
rename from ios/Pods/FirebaseCoreDiagnosticsInterop/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsData.h
rename to ios/Pods/FirebaseCore/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsData.h
diff --git a/ios/Pods/FirebaseCore/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsInterop.h b/ios/Pods/FirebaseCore/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsInterop.h
new file mode 100644
index 000000000..2b0eb710c
--- /dev/null
+++ b/ios/Pods/FirebaseCore/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsInterop.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2019 Google
+ *
+ * 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
+
+#import "FIRCoreDiagnosticsData.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+/** Allows the interoperation of FirebaseCore and FirebaseCoreDiagnostics. */
+@protocol FIRCoreDiagnosticsInterop
+
+/** Sends the given diagnostics data.
+ *
+ * @param diagnosticsData The diagnostics data object to send.
+ */
++ (void)sendDiagnosticsData:(id)diagnosticsData;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/ios/Pods/FirebaseCore/README.md b/ios/Pods/FirebaseCore/README.md
index 1747cca7a..d778205ff 100644
--- a/ios/Pods/FirebaseCore/README.md
+++ b/ios/Pods/FirebaseCore/README.md
@@ -2,14 +2,20 @@
[![License](https://img.shields.io/cocoapods/l/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase)
[![Platform](https://img.shields.io/cocoapods/p/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase)
+[![Actions Status][gh-abtesting-badge]][gh-actions]
[![Actions Status][gh-auth-badge]][gh-actions]
[![Actions Status][gh-core-badge]][gh-actions]
+[![Actions Status][gh-crashlytics-badge]][gh-actions]
+[![Actions Status][gh-database-badge]][gh-actions]
[![Actions Status][gh-datatransport-badge]][gh-actions]
[![Actions Status][gh-dynamiclinks-badge]][gh-actions]
[![Actions Status][gh-firebasepod-badge]][gh-actions]
[![Actions Status][gh-firestore-badge]][gh-actions]
+[![Actions Status][gh-functions-badge]][gh-actions]
+[![Actions Status][gh-inappmessaging-badge]][gh-actions]
[![Actions Status][gh-interop-badge]][gh-actions]
[![Actions Status][gh-messaging-badge]][gh-actions]
+[![Actions Status][gh-remoteconfig-badge]][gh-actions]
[![Actions Status][gh-storage-badge]][gh-actions]
[![Actions Status][gh-symbolcollision-badge]][gh-actions]
[![Actions Status][gh-zip-badge]][gh-actions]
@@ -92,7 +98,7 @@ Instructions for installing binary frameworks via
To develop Firebase software in this repository, ensure that you have at least
the following software:
- * Xcode 10.1 (or later)
+ * Xcode 10.3 (or later)
* CocoaPods 1.7.2 (or later)
* [CocoaPods generate](https://github.com/square/cocoapods-generate)
@@ -123,6 +129,10 @@ Firestore has a self contained Xcode project. See
See [AddNewPod.md](AddNewPod.md).
+### Managing Headers and Imports
+
+See [HeadersImports.md](HeadersImports.md).
+
### Code Formatting
To ensure that the code is formatted consistently, run the script
@@ -185,8 +195,16 @@ building and running the FirebaseAuth pod along with various samples and tests.
### Firebase Database
-To run the Database Integration tests, make your database authentication rules
-[public](https://firebase.google.com/docs/database/security/quickstart).
+The Firebase Database Integration tests can be run against a locally running Database Emulator
+or against a production instance.
+
+To run against a local emulator instance, invoke `./scripts/run_database_emulator.sh start` before
+running the integration test.
+
+To run against a production instance, provide a valid GoogleServices-Info.plist and copy it to
+`Example/Database/App/GoogleService-Info.plist`. Your Security Rule must be set to
+[public](https://firebase.google.com/docs/database/security/quickstart) while your tests are
+running.
### Firebase Storage
@@ -274,14 +292,20 @@ Your use of Firebase is governed by the
[Terms of Service for Firebase Services](https://firebase.google.com/terms/).
[gh-actions]: https://github.com/firebase/firebase-ios-sdk/actions
+[gh-abtesting-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/abtesting/badge.svg
[gh-auth-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/auth/badge.svg
[gh-core-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/core/badge.svg
+[gh-crashlytics-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/crashlytics/badge.svg
+[gh-database-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/database/badge.svg
[gh-datatransport-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/datatransport/badge.svg
[gh-dynamiclinks-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/dynamiclinks/badge.svg
[gh-firebasepod-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/firebasepod/badge.svg
[gh-firestore-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/firestore/badge.svg
+[gh-functions-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/functions/badge.svg
+[gh-inappmessaging-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/inappmessaging/badge.svg
[gh-interop-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/interop/badge.svg
[gh-messaging-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/messaging/badge.svg
+[gh-remoteconfig-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/remoteconfig/badge.svg
[gh-storage-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/storage/badge.svg
[gh-symbolcollision-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/symbolcollision/badge.svg
[gh-zip-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/zip/badge.svg
diff --git a/ios/Pods/FirebaseCoreDiagnostics/Firebase/CoreDiagnostics/FIRCDLibrary/FIRCoreDiagnostics.m b/ios/Pods/FirebaseCoreDiagnostics/Firebase/CoreDiagnostics/FIRCDLibrary/FIRCoreDiagnostics.m
index 87d57c4e8..2db7db839 100644
--- a/ios/Pods/FirebaseCoreDiagnostics/Firebase/CoreDiagnostics/FIRCDLibrary/FIRCoreDiagnostics.m
+++ b/ios/Pods/FirebaseCoreDiagnostics/Firebase/CoreDiagnostics/FIRCDLibrary/FIRCoreDiagnostics.m
@@ -26,8 +26,8 @@
#import
#import
-#import
-#import
+#import "Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsData.h"
+#import "Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsInterop.h"
#import
#import
diff --git a/ios/Pods/FirebaseCoreDiagnostics/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsData.h b/ios/Pods/FirebaseCoreDiagnostics/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsData.h
new file mode 100644
index 000000000..69c40721a
--- /dev/null
+++ b/ios/Pods/FirebaseCoreDiagnostics/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsData.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2019 Google
+ *
+ * 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
+
+NS_ASSUME_NONNULL_BEGIN
+
+/** If present, is a BOOL wrapped in an NSNumber. */
+#define kFIRCDIsDataCollectionDefaultEnabledKey @"FIRCDIsDataCollectionDefaultEnabledKey"
+
+/** If present, is an int32_t wrapped in an NSNumber. */
+#define kFIRCDConfigurationTypeKey @"FIRCDConfigurationTypeKey"
+
+/** If present, is an NSString. */
+#define kFIRCDSdkNameKey @"FIRCDSdkNameKey"
+
+/** If present, is an NSString. */
+#define kFIRCDSdkVersionKey @"FIRCDSdkVersionKey"
+
+/** If present, is an int32_t wrapped in an NSNumber. */
+#define kFIRCDllAppsCountKey @"FIRCDllAppsCountKey"
+
+/** If present, is an NSString. */
+#define kFIRCDGoogleAppIDKey @"FIRCDGoogleAppIDKey"
+
+/** If present, is an NSString. */
+#define kFIRCDBundleIDKey @"FIRCDBundleID"
+
+/** If present, is a BOOL wrapped in an NSNumber. */
+#define kFIRCDUsingOptionsFromDefaultPlistKey @"FIRCDUsingOptionsFromDefaultPlistKey"
+
+/** If present, is an NSString. */
+#define kFIRCDLibraryVersionIDKey @"FIRCDLibraryVersionIDKey"
+
+/** If present, is an NSString. */
+#define kFIRCDFirebaseUserAgentKey @"FIRCDFirebaseUserAgentKey"
+
+/** Defines the interface of a data object needed to log diagnostics data. */
+@protocol FIRCoreDiagnosticsData
+
+@required
+
+/** A dictionary containing data (non-exhaustive) to be logged in diagnostics. */
+@property(nonatomic) NSDictionary *diagnosticObjects;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/ios/Pods/FirebaseCoreDiagnostics/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsInterop.h b/ios/Pods/FirebaseCoreDiagnostics/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsInterop.h
new file mode 100644
index 000000000..2b0eb710c
--- /dev/null
+++ b/ios/Pods/FirebaseCoreDiagnostics/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsInterop.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2019 Google
+ *
+ * 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
+
+#import "FIRCoreDiagnosticsData.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+/** Allows the interoperation of FirebaseCore and FirebaseCoreDiagnostics. */
+@protocol FIRCoreDiagnosticsInterop
+
+/** Sends the given diagnostics data.
+ *
+ * @param diagnosticsData The diagnostics data object to send.
+ */
++ (void)sendDiagnosticsData:(id)diagnosticsData;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/ios/Pods/FirebaseCoreDiagnostics/README.md b/ios/Pods/FirebaseCoreDiagnostics/README.md
index 1747cca7a..d778205ff 100644
--- a/ios/Pods/FirebaseCoreDiagnostics/README.md
+++ b/ios/Pods/FirebaseCoreDiagnostics/README.md
@@ -2,14 +2,20 @@
[![License](https://img.shields.io/cocoapods/l/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase)
[![Platform](https://img.shields.io/cocoapods/p/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase)
+[![Actions Status][gh-abtesting-badge]][gh-actions]
[![Actions Status][gh-auth-badge]][gh-actions]
[![Actions Status][gh-core-badge]][gh-actions]
+[![Actions Status][gh-crashlytics-badge]][gh-actions]
+[![Actions Status][gh-database-badge]][gh-actions]
[![Actions Status][gh-datatransport-badge]][gh-actions]
[![Actions Status][gh-dynamiclinks-badge]][gh-actions]
[![Actions Status][gh-firebasepod-badge]][gh-actions]
[![Actions Status][gh-firestore-badge]][gh-actions]
+[![Actions Status][gh-functions-badge]][gh-actions]
+[![Actions Status][gh-inappmessaging-badge]][gh-actions]
[![Actions Status][gh-interop-badge]][gh-actions]
[![Actions Status][gh-messaging-badge]][gh-actions]
+[![Actions Status][gh-remoteconfig-badge]][gh-actions]
[![Actions Status][gh-storage-badge]][gh-actions]
[![Actions Status][gh-symbolcollision-badge]][gh-actions]
[![Actions Status][gh-zip-badge]][gh-actions]
@@ -92,7 +98,7 @@ Instructions for installing binary frameworks via
To develop Firebase software in this repository, ensure that you have at least
the following software:
- * Xcode 10.1 (or later)
+ * Xcode 10.3 (or later)
* CocoaPods 1.7.2 (or later)
* [CocoaPods generate](https://github.com/square/cocoapods-generate)
@@ -123,6 +129,10 @@ Firestore has a self contained Xcode project. See
See [AddNewPod.md](AddNewPod.md).
+### Managing Headers and Imports
+
+See [HeadersImports.md](HeadersImports.md).
+
### Code Formatting
To ensure that the code is formatted consistently, run the script
@@ -185,8 +195,16 @@ building and running the FirebaseAuth pod along with various samples and tests.
### Firebase Database
-To run the Database Integration tests, make your database authentication rules
-[public](https://firebase.google.com/docs/database/security/quickstart).
+The Firebase Database Integration tests can be run against a locally running Database Emulator
+or against a production instance.
+
+To run against a local emulator instance, invoke `./scripts/run_database_emulator.sh start` before
+running the integration test.
+
+To run against a production instance, provide a valid GoogleServices-Info.plist and copy it to
+`Example/Database/App/GoogleService-Info.plist`. Your Security Rule must be set to
+[public](https://firebase.google.com/docs/database/security/quickstart) while your tests are
+running.
### Firebase Storage
@@ -274,14 +292,20 @@ Your use of Firebase is governed by the
[Terms of Service for Firebase Services](https://firebase.google.com/terms/).
[gh-actions]: https://github.com/firebase/firebase-ios-sdk/actions
+[gh-abtesting-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/abtesting/badge.svg
[gh-auth-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/auth/badge.svg
[gh-core-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/core/badge.svg
+[gh-crashlytics-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/crashlytics/badge.svg
+[gh-database-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/database/badge.svg
[gh-datatransport-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/datatransport/badge.svg
[gh-dynamiclinks-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/dynamiclinks/badge.svg
[gh-firebasepod-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/firebasepod/badge.svg
[gh-firestore-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/firestore/badge.svg
+[gh-functions-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/functions/badge.svg
+[gh-inappmessaging-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/inappmessaging/badge.svg
[gh-interop-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/interop/badge.svg
[gh-messaging-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/messaging/badge.svg
+[gh-remoteconfig-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/remoteconfig/badge.svg
[gh-storage-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/storage/badge.svg
[gh-symbolcollision-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/symbolcollision/badge.svg
[gh-zip-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/zip/badge.svg
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSApplication.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSApplication.h
new file mode 100644
index 000000000..75536f7cd
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSApplication.h
@@ -0,0 +1,88 @@
+// Copyright 2019 Google
+//
+// 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
+#if CLS_TARGET_OS_HAS_UIKIT
+#import
+#endif
+
+__BEGIN_DECLS
+
+#define FIRCLSApplicationActivityDefault \
+ (NSActivitySuddenTerminationDisabled | NSActivityAutomaticTerminationDisabled)
+
+/**
+ * Type to indicate application installation source
+ */
+typedef NS_ENUM(NSInteger, FIRCLSApplicationInstallationSourceType) {
+ FIRCLSApplicationInstallationSourceTypeDeveloperInstall = 1,
+ // 2 and 3 are reserved for legacy values.
+ FIRCLSApplicationInstallationSourceTypeAppStore = 4
+};
+
+/**
+ * Returns the application bundle identifier with occurences of "/" replaced by "_"
+ */
+NSString* FIRCLSApplicationGetBundleIdentifier(void);
+
+/**
+ * Returns the SDK's bundle ID
+ */
+NSString* FIRCLSApplicationGetSDKBundleID(void);
+
+/**
+ * Returns the platform identifier, either: ios, mac, or tvos.
+ * Catalyst apps are treated as mac.
+ */
+NSString* FIRCLSApplicationGetPlatform(void);
+
+/**
+ * Returns the user-facing app name
+ */
+NSString* FIRCLSApplicationGetName(void);
+
+/**
+ * Returns the build number
+ */
+NSString* FIRCLSApplicationGetBundleVersion(void);
+
+/**
+ * Returns the human-readable build version
+ */
+NSString* FIRCLSApplicationGetShortBundleVersion(void);
+
+/**
+ * Returns a number to indicate how the app has been installed: Developer / App Store
+ */
+FIRCLSApplicationInstallationSourceType FIRCLSApplicationInstallationSource(void);
+
+BOOL FIRCLSApplicationIsExtension(void);
+NSString* FIRCLSApplicationExtensionPointIdentifier(void);
+
+#if CLS_TARGET_OS_HAS_UIKIT
+UIApplication* FIRCLSApplicationSharedInstance(void);
+#else
+id FIRCLSApplicationSharedInstance(void);
+#endif
+
+void FIRCLSApplicationOpenURL(NSURL* url,
+ NSExtensionContext* extensionContext,
+ void (^completionBlock)(BOOL success));
+
+id FIRCLSApplicationBeginActivity(NSActivityOptions options, NSString* reason);
+void FIRCLSApplicationEndActivity(id activity);
+
+void FIRCLSApplicationActivity(NSActivityOptions options, NSString* reason, void (^block)(void));
+
+__END_DECLS
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSApplication.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSApplication.m
new file mode 100644
index 000000000..219b4bb7a
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSApplication.m
@@ -0,0 +1,211 @@
+// Copyright 2019 Google
+//
+// 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 "FIRCLSApplication.h"
+
+#import "FIRCLSHost.h"
+#import "FIRCLSUtility.h"
+
+#if CLS_TARGET_OS_OSX
+#import
+#endif
+
+#if CLS_TARGET_OS_HAS_UIKIT
+#import
+#endif
+
+NSString* FIRCLSApplicationGetBundleIdentifier(void) {
+ return [[[NSBundle mainBundle] bundleIdentifier] stringByReplacingOccurrencesOfString:@"/"
+ withString:@"_"];
+}
+
+NSString* FIRCLSApplicationGetSDKBundleID(void) {
+ return
+ [@"com.google.firebase.crashlytics." stringByAppendingString:FIRCLSApplicationGetPlatform()];
+}
+
+NSString* FIRCLSApplicationGetPlatform(void) {
+#if defined(TARGET_OS_MACCATALYST) && TARGET_OS_MACCATALYST
+ return @"mac";
+#elif TARGET_OS_IOS
+ return @"ios";
+#elif TARGET_OS_OSX
+ return @"mac";
+#elif TARGET_OS_TV
+ return @"tvos";
+#endif
+}
+
+// these defaults match the FIRCLSInfoPlist helper in FIRCLSIDEFoundation
+NSString* FIRCLSApplicationGetBundleVersion(void) {
+ return [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"];
+}
+
+NSString* FIRCLSApplicationGetShortBundleVersion(void) {
+ return [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"];
+}
+
+NSString* FIRCLSApplicationGetName(void) {
+ NSString* name;
+ NSBundle* mainBundle;
+
+ mainBundle = [NSBundle mainBundle];
+
+ name = [mainBundle objectForInfoDictionaryKey:@"CFBundleDisplayName"];
+ if (name) {
+ return name;
+ }
+
+ name = [mainBundle objectForInfoDictionaryKey:@"CFBundleName"];
+ if (name) {
+ return name;
+ }
+
+ return FIRCLSApplicationGetBundleVersion();
+}
+
+BOOL FIRCLSApplicationHasAppStoreReceipt(void) {
+ NSURL* url = NSBundle.mainBundle.appStoreReceiptURL;
+ return [NSFileManager.defaultManager fileExistsAtPath:[url path]];
+}
+
+FIRCLSApplicationInstallationSourceType FIRCLSApplicationInstallationSource(void) {
+ if (FIRCLSApplicationHasAppStoreReceipt()) {
+ return FIRCLSApplicationInstallationSourceTypeAppStore;
+ }
+
+ return FIRCLSApplicationInstallationSourceTypeDeveloperInstall;
+}
+
+BOOL FIRCLSApplicationIsExtension(void) {
+ return FIRCLSApplicationExtensionPointIdentifier() != nil;
+}
+
+NSString* FIRCLSApplicationExtensionPointIdentifier(void) {
+ id extensionDict = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"NSExtension"];
+
+ if (!extensionDict) {
+ return nil;
+ }
+
+ if (![extensionDict isKindOfClass:[NSDictionary class]]) {
+ FIRCLSSDKLog("Error: NSExtension Info.plist entry is mal-formed\n");
+ return nil;
+ }
+
+ id typeValue = [(NSDictionary*)extensionDict objectForKey:@"NSExtensionPointIdentifier"];
+
+ if (![typeValue isKindOfClass:[NSString class]]) {
+ FIRCLSSDKLog("Error: NSExtensionPointIdentifier Info.plist entry is mal-formed\n");
+ return nil;
+ }
+
+ return typeValue;
+}
+
+#if CLS_TARGET_OS_HAS_UIKIT
+UIApplication* FIRCLSApplicationSharedInstance(void) {
+ if (FIRCLSApplicationIsExtension()) {
+ return nil;
+ }
+
+ return [[UIApplication class] performSelector:@selector(sharedApplication)];
+}
+#elif CLS_TARGET_OS_OSX
+id FIRCLSApplicationSharedInstance(void) {
+ return [NSClassFromString(@"NSApplication") sharedApplication];
+}
+#else
+id FIRCLSApplicationSharedInstance(void) {
+ return nil; // FIXME: what do we actually return for watch?
+}
+#endif
+
+void FIRCLSApplicationOpenURL(NSURL* url,
+ NSExtensionContext* extensionContext,
+ void (^completionBlock)(BOOL success)) {
+ if (extensionContext) {
+ [extensionContext openURL:url completionHandler:completionBlock];
+ return;
+ }
+
+ BOOL result = NO;
+
+#if TARGET_OS_IOS
+ // What's going on here is the value returned is a scalar, but we really need an object to
+ // call this dynamically. Hoops must be jumped.
+ NSInvocationOperation* op =
+ [[NSInvocationOperation alloc] initWithTarget:FIRCLSApplicationSharedInstance()
+ selector:@selector(openURL:)
+ object:url];
+ [op start];
+ [op.result getValue:&result];
+#elif CLS_TARGET_OS_OSX
+ result = [[NSClassFromString(@"NSWorkspace") sharedWorkspace] openURL:url];
+#endif
+
+ completionBlock(result);
+}
+
+id FIRCLSApplicationBeginActivity(NSActivityOptions options, NSString* reason) {
+ if ([[NSProcessInfo processInfo] respondsToSelector:@selector(beginActivityWithOptions:
+ reason:)]) {
+ return [[NSProcessInfo processInfo] beginActivityWithOptions:options reason:reason];
+ }
+
+#if CLS_TARGET_OS_OSX
+ if (options & NSActivitySuddenTerminationDisabled) {
+ [[NSProcessInfo processInfo] disableSuddenTermination];
+ }
+
+ if (options & NSActivityAutomaticTerminationDisabled) {
+ [[NSProcessInfo processInfo] disableAutomaticTermination:reason];
+ }
+#endif
+
+ // encode the options, so we can undo our work later
+ return @{@"options" : @(options), @"reason" : reason};
+}
+
+void FIRCLSApplicationEndActivity(id activity) {
+ if (!activity) {
+ return;
+ }
+
+ if ([[NSProcessInfo processInfo] respondsToSelector:@selector(endActivity:)]) {
+ [[NSProcessInfo processInfo] endActivity:activity];
+ return;
+ }
+
+#if CLS_TARGET_OS_OSX
+ NSInteger options = [[(NSDictionary*)activity objectForKey:@"options"] integerValue];
+
+ if (options & NSActivitySuddenTerminationDisabled) {
+ [[NSProcessInfo processInfo] enableSuddenTermination];
+ }
+
+ if (options & NSActivityAutomaticTerminationDisabled) {
+ [[NSProcessInfo processInfo]
+ enableAutomaticTermination:[(NSDictionary*)activity objectForKey:@"reason"]];
+ }
+#endif
+}
+
+void FIRCLSApplicationActivity(NSActivityOptions options, NSString* reason, void (^block)(void)) {
+ id activity = FIRCLSApplicationBeginActivity(options, reason);
+
+ block();
+
+ FIRCLSApplicationEndActivity(activity);
+}
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSBinaryImage.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSBinaryImage.h
new file mode 100644
index 000000000..f3c0bd718
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSBinaryImage.h
@@ -0,0 +1,81 @@
+// Copyright 2019 Google
+//
+// 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.
+
+#pragma once
+
+#include
+#include
+
+#include "FIRCLSFeatures.h"
+#include "FIRCLSFile.h"
+#include "FIRCLSMachO.h"
+
+__BEGIN_DECLS
+
+// Typically, apps seem to have ~300 binary images loaded
+#define CLS_BINARY_IMAGE_RUNTIME_NODE_COUNT (512)
+#define CLS_BINARY_IMAGE_RUNTIME_NODE_NAME_SIZE (32)
+#define CLS_BINARY_IMAGE_RUNTIME_NODE_RECORD_NAME 0
+
+#define FIRCLSUUIDStringLength (33)
+
+typedef struct {
+ _Atomic(void*) volatile baseAddress;
+ uint64_t size;
+#if CLS_DWARF_UNWINDING_SUPPORTED
+ const void* ehFrame;
+#endif
+#if CLS_COMPACT_UNWINDING_SUPPORTED
+ const void* unwindInfo;
+#endif
+ const void* crashInfo;
+#if CLS_BINARY_IMAGE_RUNTIME_NODE_RECORD_NAME
+ char name[CLS_BINARY_IMAGE_RUNTIME_NODE_NAME_SIZE];
+#endif
+} FIRCLSBinaryImageRuntimeNode;
+
+typedef struct {
+ char uuidString[FIRCLSUUIDStringLength];
+ bool encrypted;
+ FIRCLSMachOVersion builtSDK;
+ FIRCLSMachOVersion minSDK;
+ FIRCLSBinaryImageRuntimeNode node;
+ struct FIRCLSMachOSlice slice;
+ intptr_t vmaddr_slide;
+} FIRCLSBinaryImageDetails;
+
+typedef struct {
+ const char* path;
+} FIRCLSBinaryImageReadOnlyContext;
+
+typedef struct {
+ FIRCLSFile file;
+ FIRCLSBinaryImageRuntimeNode nodes[CLS_BINARY_IMAGE_RUNTIME_NODE_COUNT];
+} FIRCLSBinaryImageReadWriteContext;
+
+void FIRCLSBinaryImageInit(FIRCLSBinaryImageReadOnlyContext* roContext,
+ FIRCLSBinaryImageReadWriteContext* rwContext);
+
+#if CLS_COMPACT_UNWINDING_SUPPORTED
+bool FIRCLSBinaryImageSafeFindImageForAddress(uintptr_t address,
+ FIRCLSBinaryImageRuntimeNode* image);
+bool FIRCLSBinaryImageSafeHasUnwindInfo(FIRCLSBinaryImageRuntimeNode* image);
+#endif
+
+bool FIRCLSBinaryImageFindImageForUUID(const char* uuidString,
+ FIRCLSBinaryImageDetails* imageDetails);
+
+bool FIRCLSBinaryImageRecordMainExecutable(FIRCLSFile* file);
+
+__END_DECLS
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSBinaryImage.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSBinaryImage.m
new file mode 100644
index 000000000..8b707bb44
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSBinaryImage.m
@@ -0,0 +1,571 @@
+// Copyright 2019 Google
+//
+// 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.
+
+#include "FIRCLSBinaryImage.h"
+
+#include
+#include
+
+#include
+
+#include
+
+#include "FIRCLSByteUtility.h"
+#include "FIRCLSFeatures.h"
+#include "FIRCLSFile.h"
+#include "FIRCLSGlobals.h"
+#include "FIRCLSHost.h"
+#include "FIRCLSMachO.h"
+#include "FIRCLSUtility.h"
+
+#include
+
+// this is defined only if __OPEN_SOURCE__ is *not* defined in the TVOS SDK's mach-o/loader.h
+// also, it has not yet made it back to the OSX SDKs, for example
+#ifndef LC_VERSION_MIN_TVOS
+#define LC_VERSION_MIN_TVOS 0x2F
+#endif
+
+#pragma mark Prototypes
+static bool FIRCLSBinaryImageOpenIfNeeded(bool* needsClosing);
+
+static void FIRCLSBinaryImageAddedCallback(const struct mach_header* mh, intptr_t vmaddr_slide);
+static void FIRCLSBinaryImageRemovedCallback(const struct mach_header* mh, intptr_t vmaddr_slide);
+static void FIRCLSBinaryImageChanged(bool added,
+ const struct mach_header* mh,
+ intptr_t vmaddr_slide);
+static bool FIRCLSBinaryImageFillInImageDetails(FIRCLSBinaryImageDetails* details);
+
+static void FIRCLSBinaryImageStoreNode(bool added, FIRCLSBinaryImageDetails imageDetails);
+static void FIRCLSBinaryImageRecordSlice(bool added, const FIRCLSBinaryImageDetails imageDetails);
+
+#pragma mark - Core API
+void FIRCLSBinaryImageInit(FIRCLSBinaryImageReadOnlyContext* roContext,
+ FIRCLSBinaryImageReadWriteContext* rwContext) {
+ // initialize our node array to all zeros
+ memset(&_firclsContext.writable->binaryImage, 0, sizeof(_firclsContext.writable->binaryImage));
+ _firclsContext.writable->binaryImage.file.fd = -1;
+
+ dispatch_async(FIRCLSGetBinaryImageQueue(), ^{
+ if (!FIRCLSUnlinkIfExists(_firclsContext.readonly->binaryimage.path)) {
+ FIRCLSSDKLog("Unable to reset the binary image log file %s\n", strerror(errno));
+ }
+
+ bool needsClosing; // unneeded
+ if (!FIRCLSBinaryImageOpenIfNeeded(&needsClosing)) {
+ FIRCLSSDKLog("Error: Unable to open the binary image log file during init\n");
+ }
+ });
+
+ _dyld_register_func_for_add_image(FIRCLSBinaryImageAddedCallback);
+ _dyld_register_func_for_remove_image(FIRCLSBinaryImageRemovedCallback);
+
+ dispatch_async(FIRCLSGetBinaryImageQueue(), ^{
+ FIRCLSFileClose(&_firclsContext.writable->binaryImage.file);
+ });
+}
+
+static bool FIRCLSBinaryImageOpenIfNeeded(bool* needsClosing) {
+ if (!FIRCLSIsValidPointer(_firclsContext.writable)) {
+ return false;
+ }
+
+ if (!FIRCLSIsValidPointer(_firclsContext.readonly)) {
+ return false;
+ }
+
+ if (!FIRCLSIsValidPointer(needsClosing)) {
+ return false;
+ }
+
+ *needsClosing = false;
+
+ if (FIRCLSFileIsOpen(&_firclsContext.writable->binaryImage.file)) {
+ return true;
+ }
+
+ if (!FIRCLSFileInitWithPath(&_firclsContext.writable->binaryImage.file,
+ _firclsContext.readonly->binaryimage.path, false)) {
+ FIRCLSSDKLog("Error: unable to open binary image log file\n");
+ return false;
+ }
+
+ *needsClosing = true;
+
+ return true;
+}
+
+#if CLS_COMPACT_UNWINDING_SUPPORTED
+bool FIRCLSBinaryImageSafeFindImageForAddress(uintptr_t address,
+ FIRCLSBinaryImageRuntimeNode* image) {
+ if (!FIRCLSContextIsInitialized()) {
+ return false;
+ }
+
+ if (address == 0) {
+ return false;
+ }
+
+ if (!FIRCLSIsValidPointer(image)) {
+ return false;
+ }
+
+ FIRCLSBinaryImageRuntimeNode* nodes = _firclsContext.writable->binaryImage.nodes;
+ if (!nodes) {
+ FIRCLSSDKLogError("The node structure is NULL\n");
+ return false;
+ }
+
+ for (uint32_t i = 0; i < CLS_BINARY_IMAGE_RUNTIME_NODE_COUNT; ++i) {
+ FIRCLSBinaryImageRuntimeNode* node = &nodes[i];
+ if (!FIRCLSIsValidPointer(node)) {
+ FIRCLSSDKLog(
+ "Invalid node pointer encountered in context's writable binary image at index %i", i);
+ continue;
+ }
+
+ if ((address >= (uintptr_t)node->baseAddress) &&
+ (address < (uintptr_t)node->baseAddress + node->size)) {
+ *image = *node; // copy the image
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool FIRCLSBinaryImageSafeHasUnwindInfo(FIRCLSBinaryImageRuntimeNode* image) {
+ return FIRCLSIsValidPointer(image->unwindInfo);
+}
+#endif
+
+bool FIRCLSBinaryImageFindImageForUUID(const char* uuidString,
+ FIRCLSBinaryImageDetails* imageDetails) {
+ if (!imageDetails || !uuidString) {
+ FIRCLSSDKLog("null input\n");
+ return false;
+ }
+
+ uint32_t imageCount = _dyld_image_count();
+
+ for (uint32_t i = 0; i < imageCount; ++i) {
+ const struct mach_header* mh = _dyld_get_image_header(i);
+
+ FIRCLSBinaryImageDetails image;
+
+ image.slice = FIRCLSMachOSliceWithHeader((void*)mh);
+ FIRCLSBinaryImageFillInImageDetails(&image);
+
+ if (strncmp(uuidString, image.uuidString, FIRCLSUUIDStringLength) == 0) {
+ *imageDetails = image;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+#pragma mark - DYLD callback handlers
+static void FIRCLSBinaryImageAddedCallback(const struct mach_header* mh, intptr_t vmaddr_slide) {
+ FIRCLSBinaryImageChanged(true, mh, vmaddr_slide);
+}
+
+static void FIRCLSBinaryImageRemovedCallback(const struct mach_header* mh, intptr_t vmaddr_slide) {
+ FIRCLSBinaryImageChanged(false, mh, vmaddr_slide);
+}
+
+#if CLS_BINARY_IMAGE_RUNTIME_NODE_RECORD_NAME
+static bool FIRCLSBinaryImagePopulateRuntimeNodeName(FIRCLSBinaryImageDetails* details) {
+ if (!FIRCLSIsValidPointer(details)) {
+ return false;
+ }
+
+ memset(details->node.name, 0, CLS_BINARY_IMAGE_RUNTIME_NODE_NAME_SIZE);
+
+ // We have limited storage space for the name. And, we really want to store
+ // "CoreFoundation", not "/System/Library/Fram", so we have to play tricks
+ // to make sure we get the right side of the string.
+ const char* imageName = FIRCLSMachOSliceGetExecutablePath(&details->slice);
+ if (!imageName) {
+ return false;
+ }
+
+ const size_t imageNameLength = strlen(imageName);
+
+ // Remember to leave one character for null-termination.
+ if (imageNameLength > CLS_BINARY_IMAGE_RUNTIME_NODE_NAME_SIZE - 1) {
+ imageName = imageName + (imageNameLength - (CLS_BINARY_IMAGE_RUNTIME_NODE_NAME_SIZE - 1));
+ }
+
+ // subtract one to make sure the string is always null-terminated
+ strncpy(details->node.name, imageName, CLS_BINARY_IMAGE_RUNTIME_NODE_NAME_SIZE - 1);
+
+ return true;
+}
+#endif
+
+// There were plans later to replace this with FIRCLSMachO
+static FIRCLSMachOSegmentCommand FIRCLSBinaryImageMachOGetSegmentCommand(
+ const struct load_command* cmd) {
+ FIRCLSMachOSegmentCommand segmentCommand;
+
+ memset(&segmentCommand, 0, sizeof(FIRCLSMachOSegmentCommand));
+
+ if (!cmd) {
+ return segmentCommand;
+ }
+
+ if (cmd->cmd == LC_SEGMENT) {
+ struct segment_command* segCmd = (struct segment_command*)cmd;
+
+ memcpy(segmentCommand.segname, segCmd->segname, 16);
+ segmentCommand.vmaddr = segCmd->vmaddr;
+ segmentCommand.vmsize = segCmd->vmsize;
+ } else if (cmd->cmd == LC_SEGMENT_64) {
+ struct segment_command_64* segCmd = (struct segment_command_64*)cmd;
+
+ memcpy(segmentCommand.segname, segCmd->segname, 16);
+ segmentCommand.vmaddr = segCmd->vmaddr;
+ segmentCommand.vmsize = segCmd->vmsize;
+ }
+
+ return segmentCommand;
+}
+
+static bool FIRCLSBinaryImageMachOSliceInitSectionByName(FIRCLSMachOSliceRef slice,
+ const char* segName,
+ const char* sectionName,
+ FIRCLSMachOSection* section) {
+ if (!FIRCLSIsValidPointer(slice)) {
+ return false;
+ }
+
+ if (!section) {
+ return false;
+ }
+
+ memset(section, 0, sizeof(FIRCLSMachOSection));
+
+ if (FIRCLSMachOSliceIs64Bit(slice)) {
+ const struct section_64* sect =
+ getsectbynamefromheader_64(slice->startAddress, segName, sectionName);
+ if (!sect) {
+ return false;
+ }
+
+ section->addr = sect->addr;
+ section->size = sect->size;
+ section->offset = sect->offset;
+ } else {
+ const struct section* sect = getsectbynamefromheader(slice->startAddress, segName, sectionName);
+ if (!sect) {
+ return false;
+ }
+
+ section->addr = sect->addr;
+ section->size = sect->size;
+ section->offset = sect->offset;
+ }
+
+ return true;
+}
+
+static bool FIRCLSBinaryImageFillInImageDetails(FIRCLSBinaryImageDetails* details) {
+ if (!FIRCLSIsValidPointer(details)) {
+ return false;
+ }
+
+ if (!FIRCLSIsValidPointer(details->slice.startAddress)) {
+ return false;
+ }
+
+#if CLS_BINARY_IMAGE_RUNTIME_NODE_RECORD_NAME
+ // this is done for debugging purposes, so if it fails, its ok to continue
+ FIRCLSBinaryImagePopulateRuntimeNodeName(details);
+#endif
+
+ // This cast might look a little dubious, but its just because we're using the same
+ // struct types in a few different places.
+ details->node.baseAddress = (void* volatile)details->slice.startAddress;
+
+ FIRCLSMachOSliceEnumerateLoadCommands(
+ &details->slice, ^(uint32_t type, uint32_t size, const struct load_command* cmd) {
+ switch (type) {
+ case LC_UUID: {
+ const uint8_t* uuid = FIRCLSMachOGetUUID(cmd);
+ FIRCLSSafeHexToString(uuid, 16, details->uuidString);
+ } break;
+ case LC_ENCRYPTION_INFO:
+ details->encrypted = FIRCLSMachOGetEncrypted(cmd);
+ break;
+ case LC_SEGMENT:
+ case LC_SEGMENT_64: {
+ FIRCLSMachOSegmentCommand segmentCommand = FIRCLSBinaryImageMachOGetSegmentCommand(cmd);
+
+ if (strncmp(segmentCommand.segname, SEG_TEXT, sizeof(SEG_TEXT)) == 0) {
+ details->node.size = segmentCommand.vmsize;
+ }
+ } break;
+ case LC_VERSION_MIN_MACOSX:
+ case LC_VERSION_MIN_IPHONEOS:
+ case LC_VERSION_MIN_TVOS:
+ case LC_VERSION_MIN_WATCHOS:
+ details->minSDK = FIRCLSMachOGetMinimumOSVersion(cmd);
+ details->builtSDK = FIRCLSMachOGetLinkedSDKVersion(cmd);
+ break;
+ }
+ });
+
+ // We look up the section we want, and we *should* be able to use:
+ //
+ // address of data we want = start address + section.offset
+ //
+ // However, the offset value is coming back funky in iOS 9. So, instead we look up the address
+ // the section should be loaded at, and compute the offset by looking up the address of the
+ // segment itself.
+
+ FIRCLSMachOSection section;
+
+#if CLS_COMPACT_UNWINDING_SUPPORTED
+ if (FIRCLSBinaryImageMachOSliceInitSectionByName(&details->slice, SEG_TEXT, "__unwind_info",
+ §ion)) {
+ details->node.unwindInfo = (void*)(section.addr + details->vmaddr_slide);
+ }
+#endif
+
+#if CLS_DWARF_UNWINDING_SUPPORTED
+ if (FIRCLSBinaryImageMachOSliceInitSectionByName(&details->slice, SEG_TEXT, "__eh_frame",
+ §ion)) {
+ details->node.ehFrame = (void*)(section.addr + details->vmaddr_slide);
+ }
+#endif
+
+ if (FIRCLSBinaryImageMachOSliceInitSectionByName(&details->slice, SEG_DATA, "__crash_info",
+ §ion)) {
+ details->node.crashInfo = (void*)(section.addr + details->vmaddr_slide);
+ }
+
+ return true;
+}
+
+static void FIRCLSBinaryImageChanged(bool added,
+ const struct mach_header* mh,
+ intptr_t vmaddr_slide) {
+ // FIRCLSSDKLog("Binary image %s %p\n", added ? "loaded" : "unloaded", mh);
+
+ FIRCLSBinaryImageDetails imageDetails;
+
+ memset(&imageDetails, 0, sizeof(FIRCLSBinaryImageDetails));
+
+ imageDetails.slice = FIRCLSMachOSliceWithHeader((void*)mh);
+ imageDetails.vmaddr_slide = vmaddr_slide;
+ FIRCLSBinaryImageFillInImageDetails(&imageDetails);
+
+ // this is an atomic operation
+ FIRCLSBinaryImageStoreNode(added, imageDetails);
+
+ // this isn't, so do it on a serial queue
+ dispatch_async(FIRCLSGetBinaryImageQueue(), ^{
+ FIRCLSBinaryImageRecordSlice(added, imageDetails);
+ });
+}
+
+#pragma mark - In-Memory Storage
+static void FIRCLSBinaryImageStoreNode(bool added, FIRCLSBinaryImageDetails imageDetails) {
+ // This function is mutating a structure that needs to be accessed at crash time. We
+ // need to make sure the structure is always in as valid a state as possible.
+ // FIRCLSSDKLog("Storing %s node %p\n", added ? "loaded" : "unloaded",
+ // (void*)imageDetails.node.baseAddress);
+
+ if (!_firclsContext.writable) {
+ FIRCLSSDKLog("Error: Writable context is NULL\n");
+ return;
+ }
+
+ void* searchAddress = NULL;
+ bool success = false;
+ FIRCLSBinaryImageRuntimeNode* nodes = _firclsContext.writable->binaryImage.nodes;
+
+ if (!added) {
+ // capture the search address first
+ searchAddress = imageDetails.node.baseAddress;
+
+ // If we are removing a node, we need to set its entries to zero. By clearing all of
+ // these values, we can just copy in imageDetails.node. Using memset here is slightly
+ // weird, since we have to restore one field. But, this way, if/when the structure changes,
+ // we still do the right thing.
+ memset(&imageDetails.node, 0, sizeof(FIRCLSBinaryImageRuntimeNode));
+
+ // restore the baseAddress, which just got zeroed, and is used for indexing
+ imageDetails.node.baseAddress = searchAddress;
+ }
+
+ for (uint32_t i = 0; i < CLS_BINARY_IMAGE_RUNTIME_NODE_COUNT; ++i) {
+ FIRCLSBinaryImageRuntimeNode* node = &nodes[i];
+
+ if (!node) {
+ FIRCLSSDKLog("Error: Binary image storage is NULL\n");
+ break;
+ }
+
+ // navigate through the array, looking for our matching address
+ if (node->baseAddress != searchAddress) {
+ continue;
+ }
+
+ // Attempt to swap the base address with whatever we are searching for. Success means that
+ // entry has been claims/cleared. Failure means some other thread beat us to it.
+ if (atomic_compare_exchange_strong(&node->baseAddress, &searchAddress,
+ imageDetails.node.baseAddress)) {
+ *node = imageDetails.node;
+ success = true;
+
+ break;
+ }
+
+ // If this is an unload, getting here means two threads unloaded at the same time. I think
+ // that's highly unlikely, and possibly even impossible. So, I'm choosing to abort the process
+ // at this point.
+ if (!added) {
+ FIRCLSSDKLog("Error: Failed to swap during image unload\n");
+ break;
+ }
+ }
+
+ if (!success) {
+ FIRCLSSDKLog("Error: Unable to track a %s node %p\n", added ? "loaded" : "unloaded",
+ (void*)imageDetails.node.baseAddress);
+ }
+}
+
+#pragma mark - On-Disk Storage
+static void FIRCLSBinaryImageRecordDetails(FIRCLSFile* file,
+ const FIRCLSBinaryImageDetails imageDetails) {
+ if (!file) {
+ FIRCLSSDKLog("Error: file is invalid\n");
+ return;
+ }
+
+ FIRCLSFileWriteHashEntryString(file, "uuid", imageDetails.uuidString);
+ FIRCLSFileWriteHashEntryUint64(file, "base", (uintptr_t)imageDetails.slice.startAddress);
+ FIRCLSFileWriteHashEntryUint64(file, "size", imageDetails.node.size);
+}
+
+static void FIRCLSBinaryImageRecordLibraryFrameworkInfo(FIRCLSFile* file, const char* path) {
+ if (!file) {
+ FIRCLSSDKLog("Error: file is invalid\n");
+ return;
+ }
+
+ if (!path) {
+ return;
+ }
+
+ // Because this function is so expensive, we've decided to omit this info for all Apple-supplied
+ // frameworks. This really isn't that bad, because we can know their info ahead of time (within a
+ // small margin of error). With this implemenation, we will still record this info for any
+ // user-built framework, which in the end is the most important thing.
+ if (strncmp(path, "/System", 7) == 0) {
+ return;
+ }
+
+ // check to see if this is a potential framework bundle
+ if (!strstr(path, ".framework")) {
+ return;
+ }
+
+ // My.framework/Versions/A/My for OS X
+ // My.framework/My for iOS
+
+ NSString* frameworkPath = [NSString stringWithUTF8String:path];
+#if TARGET_OS_IPHONE
+ frameworkPath = [frameworkPath stringByDeletingLastPathComponent];
+#else
+ frameworkPath = [frameworkPath stringByDeletingLastPathComponent]; // My.framework/Versions/A
+ frameworkPath = [frameworkPath stringByDeletingLastPathComponent]; // My.framework/Versions
+ frameworkPath = [frameworkPath stringByDeletingLastPathComponent]; // My.framework
+#endif
+
+ NSBundle* const bundle = [NSBundle bundleWithPath:frameworkPath];
+
+ if (!bundle) {
+ return;
+ }
+
+ FIRCLSFileWriteHashEntryNSStringUnlessNilOrEmpty(file, "bundle_id", [bundle bundleIdentifier]);
+ FIRCLSFileWriteHashEntryNSStringUnlessNilOrEmpty(
+ file, "build_version", [bundle objectForInfoDictionaryKey:@"CFBundleVersion"]);
+ FIRCLSFileWriteHashEntryNSStringUnlessNilOrEmpty(
+ file, "display_version", [bundle objectForInfoDictionaryKey:@"CFBundleShortVersionString"]);
+}
+
+static void FIRCLSBinaryImageRecordSlice(bool added, const FIRCLSBinaryImageDetails imageDetails) {
+ bool needsClosing = false;
+ if (!FIRCLSBinaryImageOpenIfNeeded(&needsClosing)) {
+ FIRCLSSDKLog("Error: unable to open binary image log file\n");
+ return;
+ }
+
+ FIRCLSFile* file = &_firclsContext.writable->binaryImage.file;
+
+ FIRCLSFileWriteSectionStart(file, added ? "load" : "unload");
+
+ FIRCLSFileWriteHashStart(file);
+
+ const char* path = FIRCLSMachOSliceGetExecutablePath((FIRCLSMachOSliceRef)&imageDetails.slice);
+
+ FIRCLSFileWriteHashEntryString(file, "path", path);
+
+ if (added) {
+ // this won't work if the binary has been unloaded
+ FIRCLSBinaryImageRecordLibraryFrameworkInfo(file, path);
+ }
+
+ FIRCLSBinaryImageRecordDetails(file, imageDetails);
+
+ FIRCLSFileWriteHashEnd(file);
+
+ FIRCLSFileWriteSectionEnd(file);
+
+ if (needsClosing) {
+ FIRCLSFileClose(file);
+ }
+}
+
+bool FIRCLSBinaryImageRecordMainExecutable(FIRCLSFile* file) {
+ FIRCLSBinaryImageDetails imageDetails;
+
+ memset(&imageDetails, 0, sizeof(FIRCLSBinaryImageDetails));
+
+ imageDetails.slice = FIRCLSMachOSliceGetCurrent();
+ FIRCLSBinaryImageFillInImageDetails(&imageDetails);
+
+ FIRCLSFileWriteSectionStart(file, "executable");
+ FIRCLSFileWriteHashStart(file);
+
+ FIRCLSFileWriteHashEntryString(file, "architecture",
+ FIRCLSMachOSliceGetArchitectureName(&imageDetails.slice));
+
+ FIRCLSBinaryImageRecordDetails(file, imageDetails);
+ FIRCLSFileWriteHashEntryBoolean(file, "encrypted", imageDetails.encrypted);
+ FIRCLSFileWriteHashEntryString(file, "minimum_sdk_version",
+ [FIRCLSMachOFormatVersion(&imageDetails.minSDK) UTF8String]);
+ FIRCLSFileWriteHashEntryString(file, "built_sdk_version",
+ [FIRCLSMachOFormatVersion(&imageDetails.builtSDK) UTF8String]);
+
+ FIRCLSFileWriteHashEnd(file);
+ FIRCLSFileWriteSectionEnd(file);
+
+ return true;
+}
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSContext.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSContext.h
new file mode 100644
index 000000000..bdb43418c
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSContext.h
@@ -0,0 +1,121 @@
+// Copyright 2019 Google
+//
+// 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.
+
+#pragma once
+
+#include "FIRCLSAllocate.h"
+#include "FIRCLSBinaryImage.h"
+#include "FIRCLSException.h"
+#include "FIRCLSFeatures.h"
+#include "FIRCLSHost.h"
+#include "FIRCLSInternalLogging.h"
+#include "FIRCLSMachException.h"
+#include "FIRCLSSignal.h"
+#include "FIRCLSUserLogging.h"
+
+#include
+#include
+
+// The purpose of the crash context is to hold values that absolutely must be read and/or written at
+// crash time. For robustness against memory corruption, they are protected with guard pages.
+// Further, the context is seperated into read-only and read-write sections.
+
+__BEGIN_DECLS
+
+#ifdef __OBJC__
+@class FIRCLSInternalReport;
+@class FIRCLSSettings;
+@class FIRCLSInstallIdentifierModel;
+@class FIRCLSFileManager;
+#endif
+
+typedef struct {
+ volatile bool initialized;
+ volatile bool debuggerAttached;
+ const char* previouslyCrashedFileFullPath;
+ const char* logPath;
+#if CLS_USE_SIGALTSTACK
+ void* signalStack;
+#endif
+#if CLS_MACH_EXCEPTION_SUPPORTED
+ void* machStack;
+#endif
+ void* delegate;
+ void* callbackDelegate;
+
+ FIRCLSBinaryImageReadOnlyContext binaryimage;
+ FIRCLSExceptionReadOnlyContext exception;
+ FIRCLSHostReadOnlyContext host;
+ FIRCLSSignalReadContext signal;
+#if CLS_MACH_EXCEPTION_SUPPORTED
+ FIRCLSMachExceptionReadContext machException;
+#endif
+ FIRCLSUserLoggingReadOnlyContext logging;
+} FIRCLSReadOnlyContext;
+
+typedef struct {
+ FIRCLSInternalLoggingWritableContext internalLogging;
+ volatile bool crashOccurred;
+ FIRCLSBinaryImageReadWriteContext binaryImage;
+ FIRCLSUserLoggingWritableContext logging;
+ FIRCLSExceptionWritableContext exception;
+} FIRCLSReadWriteContext;
+
+typedef struct {
+ FIRCLSReadOnlyContext* readonly;
+ FIRCLSReadWriteContext* writable;
+ FIRCLSAllocatorRef allocator;
+} FIRCLSContext;
+
+typedef struct {
+ void* delegate;
+ const char* customBundleId;
+ const char* rootPath;
+ const char* previouslyCrashedFileRootPath;
+ const char* sessionId;
+ const char* installId;
+ const char* betaToken;
+#if CLS_MACH_EXCEPTION_SUPPORTED
+ exception_mask_t machExceptionMask;
+#endif
+ bool errorsEnabled;
+ bool customExceptionsEnabled;
+ uint32_t maxCustomExceptions;
+ uint32_t maxErrorLogSize;
+ uint32_t maxLogSize;
+ uint32_t maxKeyValues;
+} FIRCLSContextInitData;
+
+#ifdef __OBJC__
+bool FIRCLSContextInitialize(FIRCLSInternalReport* report,
+ FIRCLSSettings* settings,
+ FIRCLSInstallIdentifierModel* installIDModel,
+ FIRCLSFileManager* fileManager);
+
+// Re-writes the metadata file on the current thread
+void FIRCLSContextUpdateMetadata(FIRCLSInternalReport* report,
+ FIRCLSSettings* settings,
+ FIRCLSInstallIdentifierModel* installIDModel,
+ FIRCLSFileManager* fileManager);
+#endif
+
+void FIRCLSContextBaseInit(void);
+void FIRCLSContextBaseDeinit(void);
+
+bool FIRCLSContextIsInitialized(void);
+bool FIRCLSContextHasCrashed(void);
+void FIRCLSContextMarkHasCrashed(void);
+bool FIRCLSContextMarkAndCheckIfCrashed(void);
+
+__END_DECLS
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSContext.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSContext.m
new file mode 100644
index 000000000..26d46c72e
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSContext.m
@@ -0,0 +1,468 @@
+// Copyright 2019 Google
+//
+// 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.
+
+#include "FIRCLSContext.h"
+
+#include
+#include
+
+#import "FIRCLSFileManager.h"
+#import "FIRCLSInstallIdentifierModel.h"
+#import "FIRCLSInternalReport.h"
+#import "FIRCLSSettings.h"
+
+#include "FIRCLSApplication.h"
+#include "FIRCLSCrashedMarkerFile.h"
+#include "FIRCLSDefines.h"
+#include "FIRCLSFeatures.h"
+#include "FIRCLSGlobals.h"
+#include "FIRCLSProcess.h"
+#include "FIRCLSUtility.h"
+
+// The writable size is our handler stack plus whatever scratch we need. We have to use this space
+// extremely carefully, however, because thread stacks always needs to be page-aligned. Only the
+// first allocation is gauranteed to be page-aligned.
+//
+// CLS_SIGNAL_HANDLER_STACK_SIZE and CLS_MACH_EXCEPTION_HANDLER_STACK_SIZE are platform dependant,
+// defined as 0 for tv/watch.
+#define CLS_MINIMUM_READWRITE_SIZE \
+ (CLS_SIGNAL_HANDLER_STACK_SIZE + CLS_MACH_EXCEPTION_HANDLER_STACK_SIZE + \
+ sizeof(FIRCLSReadWriteContext))
+
+// We need enough space here for the context, plus storage for strings.
+#define CLS_MINIMUM_READABLE_SIZE (sizeof(FIRCLSReadOnlyContext) + 4096 * 4)
+
+static const int64_t FIRCLSContextInitWaitTime = 5LL * NSEC_PER_SEC;
+
+static bool FIRCLSContextRecordMetadata(const char* path, const FIRCLSContextInitData* initData);
+static const char* FIRCLSContextAppendToRoot(NSString* root, NSString* component);
+static void FIRCLSContextAllocate(FIRCLSContext* context);
+
+FIRCLSContextInitData FIRCLSContextBuildInitData(FIRCLSInternalReport* report,
+ FIRCLSSettings* settings,
+ FIRCLSInstallIdentifierModel* installIDModel,
+ FIRCLSFileManager* fileManager) {
+ // Because we need to start the crash reporter right away,
+ // it starts up either with default settings, or cached settings
+ // from the last time they were fetched
+
+ FIRCLSContextInitData initData;
+
+ memset(&initData, 0, sizeof(FIRCLSContextInitData));
+
+ initData.customBundleId = nil;
+ initData.installId = [installIDModel.installID UTF8String];
+ initData.sessionId = [[report identifier] UTF8String];
+ initData.rootPath = [[report path] UTF8String];
+ initData.previouslyCrashedFileRootPath = [[fileManager rootPath] UTF8String];
+ initData.errorsEnabled = [settings errorReportingEnabled];
+ initData.customExceptionsEnabled = [settings customExceptionsEnabled];
+ initData.maxCustomExceptions = [settings maxCustomExceptions];
+ initData.maxErrorLogSize = [settings errorLogBufferSize];
+ initData.maxLogSize = [settings logBufferSize];
+ initData.maxKeyValues = [settings maxCustomKeys];
+
+ // If this is set, then we could attempt to do a synchronous submission for certain kinds of
+ // events (exceptions). This is a very cool feature, but adds complexity to the backend. For now,
+ // we're going to leave this disabled. It does work in the exception case, but will ultimtely
+ // result in the following crash to be discared. Usually that crash isn't interesting. But, if it
+ // was, we'd never have a chance to see it.
+ initData.delegate = nil;
+
+#if CLS_MACH_EXCEPTION_SUPPORTED
+ __block exception_mask_t mask = 0;
+
+ // TODO(b/141241224) This if statement was hardcoded to no, so this block was never run
+ // FIRCLSSignalEnumerateHandledSignals(^(int idx, int signal) {
+ // if ([self.delegate ensureDeliveryOfUnixSignal:signal]) {
+ // mask |= FIRCLSMachExceptionMaskForSignal(signal);
+ // }
+ // });
+
+ initData.machExceptionMask = mask;
+#endif
+
+ return initData;
+}
+
+bool FIRCLSContextInitialize(FIRCLSInternalReport* report,
+ FIRCLSSettings* settings,
+ FIRCLSInstallIdentifierModel* installIDModel,
+ FIRCLSFileManager* fileManager) {
+ FIRCLSContextInitData initDataObj =
+ FIRCLSContextBuildInitData(report, settings, installIDModel, fileManager);
+ FIRCLSContextInitData* initData = &initDataObj;
+
+ if (!initData) {
+ return false;
+ }
+
+ FIRCLSContextBaseInit();
+
+ dispatch_group_t group = dispatch_group_create();
+ dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
+
+ if (!FIRCLSIsValidPointer(initData->rootPath)) {
+ return false;
+ }
+
+ NSString* rootPath = [NSString stringWithUTF8String:initData->rootPath];
+
+ // setup our SDK log file synchronously, because other calls may depend on it
+ _firclsContext.readonly->logPath = FIRCLSContextAppendToRoot(rootPath, @"sdk.log");
+ if (!FIRCLSUnlinkIfExists(_firclsContext.readonly->logPath)) {
+ FIRCLSErrorLog(@"Unable to write initialize SDK write paths %s", strerror(errno));
+ }
+
+ // some values that aren't tied to particular subsystem
+ _firclsContext.readonly->debuggerAttached = FIRCLSProcessDebuggerAttached();
+ _firclsContext.readonly->delegate = initData->delegate;
+
+ dispatch_group_async(group, queue, ^{
+ FIRCLSHostInitialize(&_firclsContext.readonly->host);
+ });
+
+ dispatch_group_async(group, queue, ^{
+ _firclsContext.readonly->logging.errorStorage.maxSize = 0;
+ _firclsContext.readonly->logging.errorStorage.maxEntries =
+ initData->errorsEnabled ? initData->maxCustomExceptions : 0;
+ _firclsContext.readonly->logging.errorStorage.restrictBySize = false;
+ _firclsContext.readonly->logging.errorStorage.entryCount =
+ &_firclsContext.writable->logging.errorsCount;
+ _firclsContext.readonly->logging.errorStorage.aPath =
+ FIRCLSContextAppendToRoot(rootPath, FIRCLSReportErrorAFile);
+ _firclsContext.readonly->logging.errorStorage.bPath =
+ FIRCLSContextAppendToRoot(rootPath, FIRCLSReportErrorBFile);
+
+ _firclsContext.readonly->logging.logStorage.maxSize = initData->maxLogSize;
+ _firclsContext.readonly->logging.logStorage.maxEntries = 0;
+ _firclsContext.readonly->logging.logStorage.restrictBySize = true;
+ _firclsContext.readonly->logging.logStorage.entryCount = NULL;
+ _firclsContext.readonly->logging.logStorage.aPath =
+ FIRCLSContextAppendToRoot(rootPath, FIRCLSReportLogAFile);
+ _firclsContext.readonly->logging.logStorage.bPath =
+ FIRCLSContextAppendToRoot(rootPath, FIRCLSReportLogBFile);
+ _firclsContext.readonly->logging.customExceptionStorage.aPath =
+ FIRCLSContextAppendToRoot(rootPath, FIRCLSReportCustomExceptionAFile);
+ _firclsContext.readonly->logging.customExceptionStorage.bPath =
+ FIRCLSContextAppendToRoot(rootPath, FIRCLSReportCustomExceptionBFile);
+ _firclsContext.readonly->logging.customExceptionStorage.maxSize = 0;
+ _firclsContext.readonly->logging.customExceptionStorage.restrictBySize = false;
+ _firclsContext.readonly->logging.customExceptionStorage.maxEntries =
+ initData->maxCustomExceptions;
+ _firclsContext.readonly->logging.customExceptionStorage.entryCount =
+ &_firclsContext.writable->exception.customExceptionCount;
+
+ _firclsContext.readonly->logging.userKVStorage.maxCount = initData->maxKeyValues;
+ _firclsContext.readonly->logging.userKVStorage.incrementalPath =
+ FIRCLSContextAppendToRoot(rootPath, FIRCLSReportUserIncrementalKVFile);
+ _firclsContext.readonly->logging.userKVStorage.compactedPath =
+ FIRCLSContextAppendToRoot(rootPath, FIRCLSReportUserCompactedKVFile);
+
+ _firclsContext.readonly->logging.internalKVStorage.maxCount = 32; // Hardcode = bad
+ _firclsContext.readonly->logging.internalKVStorage.incrementalPath =
+ FIRCLSContextAppendToRoot(rootPath, FIRCLSReportInternalIncrementalKVFile);
+ _firclsContext.readonly->logging.internalKVStorage.compactedPath =
+ FIRCLSContextAppendToRoot(rootPath, FIRCLSReportInternalCompactedKVFile);
+
+ FIRCLSUserLoggingInit(&_firclsContext.readonly->logging, &_firclsContext.writable->logging);
+ });
+
+ dispatch_group_async(group, queue, ^{
+ _firclsContext.readonly->binaryimage.path =
+ FIRCLSContextAppendToRoot(rootPath, FIRCLSReportBinaryImageFile);
+
+ FIRCLSBinaryImageInit(&_firclsContext.readonly->binaryimage,
+ &_firclsContext.writable->binaryImage);
+ });
+
+ dispatch_group_async(group, queue, ^{
+ NSString* rootPath = [NSString stringWithUTF8String:initData->previouslyCrashedFileRootPath];
+ NSString* fileName = [NSString stringWithUTF8String:FIRCLSCrashedMarkerFileName];
+ _firclsContext.readonly->previouslyCrashedFileFullPath =
+ FIRCLSContextAppendToRoot(rootPath, fileName);
+ });
+
+ if (!_firclsContext.readonly->debuggerAttached) {
+ dispatch_group_async(group, queue, ^{
+ _firclsContext.readonly->signal.path =
+ FIRCLSContextAppendToRoot(rootPath, FIRCLSReportSignalFile);
+
+ FIRCLSSignalInitialize(&_firclsContext.readonly->signal);
+ });
+
+#if CLS_MACH_EXCEPTION_SUPPORTED
+ dispatch_group_async(group, queue, ^{
+ _firclsContext.readonly->machException.path =
+ FIRCLSContextAppendToRoot(rootPath, FIRCLSReportMachExceptionFile);
+
+ FIRCLSMachExceptionInit(&_firclsContext.readonly->machException, initData->machExceptionMask);
+ });
+#endif
+
+ dispatch_group_async(group, queue, ^{
+ _firclsContext.readonly->exception.path =
+ FIRCLSContextAppendToRoot(rootPath, FIRCLSReportExceptionFile);
+ _firclsContext.readonly->exception.maxCustomExceptions =
+ initData->customExceptionsEnabled ? initData->maxCustomExceptions : 0;
+
+ FIRCLSExceptionInitialize(&_firclsContext.readonly->exception,
+ &_firclsContext.writable->exception, initData->delegate);
+ });
+ } else {
+ FIRCLSSDKLog("Debugger present - not installing handlers\n");
+ }
+
+ dispatch_group_async(group, queue, ^{
+ const char* metaDataPath = [[rootPath stringByAppendingPathComponent:FIRCLSReportMetadataFile]
+ fileSystemRepresentation];
+ if (!FIRCLSContextRecordMetadata(metaDataPath, initData)) {
+ FIRCLSSDKLog("Unable to record context metadata\n");
+ }
+ });
+
+ // At this point we need to do two things. First, we need to do our memory protection *only* after
+ // all of these initialization steps are really done. But, we also want to wait as long as
+ // possible for these to be complete. If we do not, there's a chance that we will not be able to
+ // correctly report a crash shortly after start.
+
+ // Note at this will retain the group, so its totally fine to release the group here.
+ dispatch_group_notify(group, queue, ^{
+ _firclsContext.readonly->initialized = true;
+ __sync_synchronize();
+
+ if (!FIRCLSAllocatorProtect(_firclsContext.allocator)) {
+ FIRCLSSDKLog("Error: Memory protection failed\n");
+ }
+ });
+
+ if (dispatch_group_wait(group, dispatch_time(DISPATCH_TIME_NOW, FIRCLSContextInitWaitTime)) !=
+ 0) {
+ FIRCLSSDKLog("Error: Delayed initialization\n");
+ }
+
+ return true;
+}
+
+void FIRCLSContextUpdateMetadata(FIRCLSInternalReport* report,
+ FIRCLSSettings* settings,
+ FIRCLSInstallIdentifierModel* installIDModel,
+ FIRCLSFileManager* fileManager) {
+ FIRCLSContextInitData initDataObj =
+ FIRCLSContextBuildInitData(report, settings, installIDModel, fileManager);
+ FIRCLSContextInitData* initData = &initDataObj;
+
+ NSString* rootPath = [NSString stringWithUTF8String:initData->rootPath];
+
+ const char* metaDataPath =
+ [[rootPath stringByAppendingPathComponent:FIRCLSReportMetadataFile] fileSystemRepresentation];
+
+ if (!FIRCLSContextRecordMetadata(metaDataPath, initData)) {
+ FIRCLSErrorLog(@"Unable to update context metadata");
+ }
+}
+
+void FIRCLSContextBaseInit(void) {
+ NSString* sdkBundleID = FIRCLSApplicationGetSDKBundleID();
+
+ NSString* loggingQueueName = [sdkBundleID stringByAppendingString:@".logging"];
+ NSString* binaryImagesQueueName = [sdkBundleID stringByAppendingString:@".binary-images"];
+ NSString* exceptionQueueName = [sdkBundleID stringByAppendingString:@".exception"];
+
+ _firclsLoggingQueue = dispatch_queue_create([loggingQueueName UTF8String], DISPATCH_QUEUE_SERIAL);
+ _firclsBinaryImageQueue =
+ dispatch_queue_create([binaryImagesQueueName UTF8String], DISPATCH_QUEUE_SERIAL);
+ _firclsExceptionQueue =
+ dispatch_queue_create([exceptionQueueName UTF8String], DISPATCH_QUEUE_SERIAL);
+
+ FIRCLSContextAllocate(&_firclsContext);
+
+ _firclsContext.writable->internalLogging.logFd = -1;
+ _firclsContext.writable->internalLogging.logLevel = FIRCLSInternalLogLevelDebug;
+ _firclsContext.writable->crashOccurred = false;
+
+ _firclsContext.readonly->initialized = false;
+
+ __sync_synchronize();
+}
+
+static void FIRCLSContextAllocate(FIRCLSContext* context) {
+ // create the allocator, and the contexts
+ // The ordering here is really important, because the "stack" variable must be
+ // page-aligned. There's no mechanism to ask the allocator to do alignment, but we
+ // do know the very first allocation in a region is aligned to a page boundary.
+
+ context->allocator = FIRCLSAllocatorCreate(CLS_MINIMUM_READWRITE_SIZE, CLS_MINIMUM_READABLE_SIZE);
+
+ context->readonly =
+ FIRCLSAllocatorSafeAllocate(context->allocator, sizeof(FIRCLSReadOnlyContext), CLS_READONLY);
+ memset(context->readonly, 0, sizeof(FIRCLSReadOnlyContext));
+
+#if CLS_MEMORY_PROTECTION_ENABLED
+#if CLS_MACH_EXCEPTION_SUPPORTED
+ context->readonly->machStack = FIRCLSAllocatorSafeAllocate(
+ context->allocator, CLS_MACH_EXCEPTION_HANDLER_STACK_SIZE, CLS_READWRITE);
+#endif
+#if CLS_USE_SIGALTSTACK
+ context->readonly->signalStack =
+ FIRCLSAllocatorSafeAllocate(context->allocator, CLS_SIGNAL_HANDLER_STACK_SIZE, CLS_READWRITE);
+#endif
+#else
+#if CLS_MACH_EXCEPTION_SUPPORTED
+ context->readonly->machStack = valloc(CLS_MACH_EXCEPTION_HANDLER_STACK_SIZE);
+#endif
+#if CLS_USE_SIGALTSTACK
+ context->readonly->signalStack = valloc(CLS_SIGNAL_HANDLER_STACK_SIZE);
+#endif
+#endif
+
+#if CLS_MACH_EXCEPTION_SUPPORTED
+ memset(_firclsContext.readonly->machStack, 0, CLS_MACH_EXCEPTION_HANDLER_STACK_SIZE);
+#endif
+#if CLS_USE_SIGALTSTACK
+ memset(_firclsContext.readonly->signalStack, 0, CLS_SIGNAL_HANDLER_STACK_SIZE);
+#endif
+
+ context->writable = FIRCLSAllocatorSafeAllocate(context->allocator,
+ sizeof(FIRCLSReadWriteContext), CLS_READWRITE);
+ memset(context->writable, 0, sizeof(FIRCLSReadWriteContext));
+}
+
+void FIRCLSContextBaseDeinit(void) {
+ _firclsContext.readonly->initialized = false;
+
+ FIRCLSAllocatorDestroy(_firclsContext.allocator);
+}
+
+bool FIRCLSContextIsInitialized(void) {
+ __sync_synchronize();
+ if (!FIRCLSIsValidPointer(_firclsContext.readonly)) {
+ return false;
+ }
+
+ return _firclsContext.readonly->initialized;
+}
+
+bool FIRCLSContextHasCrashed(void) {
+ if (!FIRCLSContextIsInitialized()) {
+ return false;
+ }
+
+ // we've already run a full barrier above, so this read is ok
+ return _firclsContext.writable->crashOccurred;
+}
+
+void FIRCLSContextMarkHasCrashed(void) {
+ if (!FIRCLSContextIsInitialized()) {
+ return;
+ }
+
+ _firclsContext.writable->crashOccurred = true;
+ __sync_synchronize();
+}
+
+bool FIRCLSContextMarkAndCheckIfCrashed(void) {
+ if (!FIRCLSContextIsInitialized()) {
+ return false;
+ }
+
+ if (_firclsContext.writable->crashOccurred) {
+ return true;
+ }
+
+ _firclsContext.writable->crashOccurred = true;
+ __sync_synchronize();
+
+ return false;
+}
+
+static const char* FIRCLSContextAppendToRoot(NSString* root, NSString* component) {
+ return FIRCLSDupString(
+ [[root stringByAppendingPathComponent:component] fileSystemRepresentation]);
+}
+
+static bool FIRCLSContextRecordIdentity(FIRCLSFile* file, const FIRCLSContextInitData* initData) {
+ FIRCLSFileWriteSectionStart(file, "identity");
+
+ FIRCLSFileWriteHashStart(file);
+
+ FIRCLSFileWriteHashEntryString(file, "generator", CLS_SDK_GENERATOR_NAME);
+ FIRCLSFileWriteHashEntryString(file, "display_version", CLS_SDK_DISPLAY_VERSION);
+ FIRCLSFileWriteHashEntryString(file, "build_version", CLS_SDK_DISPLAY_VERSION);
+ FIRCLSFileWriteHashEntryUint64(file, "started_at", time(NULL));
+
+ FIRCLSFileWriteHashEntryString(file, "session_id", initData->sessionId);
+ FIRCLSFileWriteHashEntryString(file, "install_id", initData->installId);
+ FIRCLSFileWriteHashEntryString(file, "beta_token", initData->betaToken);
+ FIRCLSFileWriteHashEntryBoolean(file, "absolute_log_timestamps", true);
+
+ FIRCLSFileWriteHashEnd(file);
+ FIRCLSFileWriteSectionEnd(file);
+
+ return true;
+}
+
+static bool FIRCLSContextRecordApplication(FIRCLSFile* file, const char* customBundleId) {
+ FIRCLSFileWriteSectionStart(file, "application");
+
+ FIRCLSFileWriteHashStart(file);
+
+ FIRCLSFileWriteHashEntryString(file, "bundle_id",
+ [FIRCLSApplicationGetBundleIdentifier() UTF8String]);
+ FIRCLSFileWriteHashEntryString(file, "custom_bundle_id", customBundleId);
+ FIRCLSFileWriteHashEntryString(file, "build_version",
+ [FIRCLSApplicationGetBundleVersion() UTF8String]);
+ FIRCLSFileWriteHashEntryString(file, "display_version",
+ [FIRCLSApplicationGetShortBundleVersion() UTF8String]);
+ FIRCLSFileWriteHashEntryString(file, "extension_id",
+ [FIRCLSApplicationExtensionPointIdentifier() UTF8String]);
+
+ FIRCLSFileWriteHashEnd(file);
+ FIRCLSFileWriteSectionEnd(file);
+
+ return true;
+}
+
+static bool FIRCLSContextRecordMetadata(const char* path, const FIRCLSContextInitData* initData) {
+ if (!FIRCLSUnlinkIfExists(path)) {
+ FIRCLSSDKLog("Unable to unlink existing metadata file %s\n", strerror(errno));
+ }
+
+ FIRCLSFile file;
+
+ if (!FIRCLSFileInitWithPath(&file, path, false)) {
+ FIRCLSSDKLog("Unable to open metadata file %s\n", strerror(errno));
+ return false;
+ }
+
+ if (!FIRCLSContextRecordIdentity(&file, initData)) {
+ FIRCLSSDKLog("Unable to write out identity metadata\n");
+ }
+
+ if (!FIRCLSHostRecord(&file)) {
+ FIRCLSSDKLog("Unable to write out host metadata\n");
+ }
+
+ if (!FIRCLSContextRecordApplication(&file, initData->customBundleId)) {
+ FIRCLSSDKLog("Unable to write out application metadata\n");
+ }
+
+ if (!FIRCLSBinaryImageRecordMainExecutable(&file)) {
+ FIRCLSSDKLog("Unable to write out executable metadata\n");
+ }
+
+ FIRCLSFileClose(&file);
+
+ return true;
+}
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSCrashedMarkerFile.c b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSCrashedMarkerFile.c
new file mode 100644
index 000000000..5dd67fdec
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSCrashedMarkerFile.c
@@ -0,0 +1,31 @@
+// Copyright 2019 Google
+//
+// 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.
+
+#include "FIRCLSCrashedMarkerFile.h"
+#include "FIRCLSFile.h"
+#include "FIRCLSUtility.h"
+
+const char *FIRCLSCrashedMarkerFileName = "previously-crashed";
+
+void FIRCLSCreateCrashedMarkerFile() {
+ FIRCLSFile file;
+
+ if (!FIRCLSFileInitWithPath(&file, _firclsContext.readonly->previouslyCrashedFileFullPath, false)) {
+ FIRCLSSDKLog("Unable to create the crashed marker file\n");
+ return;
+ }
+
+ FIRCLSFileClose(&file);
+ FIRCLSSDKLog("Created the crashed marker file\n");
+}
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSCrashedMarkerFile.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSCrashedMarkerFile.h
new file mode 100644
index 000000000..ccf427673
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSCrashedMarkerFile.h
@@ -0,0 +1,19 @@
+// Copyright 2019 Google
+//
+// 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.
+
+#include
+
+extern const char *FIRCLSCrashedMarkerFileName;
+
+void FIRCLSCreateCrashedMarkerFile(void);
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSGlobals.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSGlobals.h
new file mode 100644
index 000000000..4f125cf08
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSGlobals.h
@@ -0,0 +1,28 @@
+// Copyright 2019 Google
+//
+// 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.
+
+#include "FIRCLSContext.h"
+
+__BEGIN_DECLS
+
+extern FIRCLSContext _firclsContext;
+extern dispatch_queue_t _firclsLoggingQueue;
+extern dispatch_queue_t _firclsBinaryImageQueue;
+extern dispatch_queue_t _firclsExceptionQueue;
+
+#define FIRCLSGetLoggingQueue() (_firclsLoggingQueue)
+#define FIRCLSGetBinaryImageQueue() (_firclsBinaryImageQueue)
+#define FIRCLSGetExceptionQueue() (_firclsExceptionQueue)
+
+__END_DECLS
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSHost.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSHost.h
new file mode 100644
index 000000000..24b1acd13
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSHost.h
@@ -0,0 +1,37 @@
+// Copyright 2019 Google
+//
+// 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.
+
+#pragma once
+
+#include
+#include
+
+#include "FIRCLSFile.h"
+
+typedef struct {
+ const char* documentDirectoryPath;
+ vm_size_t pageSize;
+} FIRCLSHostReadOnlyContext;
+
+__BEGIN_DECLS
+
+void FIRCLSHostInitialize(FIRCLSHostReadOnlyContext* roContext);
+
+vm_size_t FIRCLSHostGetPageSize(void);
+
+bool FIRCLSHostRecord(FIRCLSFile* file);
+
+void FIRCLSHostWriteDiskUsage(FIRCLSFile* file);
+
+__END_DECLS
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSHost.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSHost.m
new file mode 100644
index 000000000..87ff0f7ae
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSHost.m
@@ -0,0 +1,161 @@
+// Copyright 2019 Google
+//
+// 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.
+
+#include "FIRCLSHost.h"
+
+#include
+#include
+#include
+
+#import "FIRCLSApplication.h"
+#include "FIRCLSDefines.h"
+#import "FIRCLSFABHost.h"
+#include "FIRCLSFile.h"
+#include "FIRCLSGlobals.h"
+#include "FIRCLSUtility.h"
+
+#if TARGET_OS_IPHONE
+#import
+#else
+#import
+#endif
+
+#define CLS_HOST_SYSCTL_BUFFER_SIZE (128)
+
+#if CLS_CPU_ARM64
+#define CLS_MAX_NATIVE_PAGE_SIZE (1024 * 16)
+#else
+// return 4K, which is correct for all platforms except arm64, currently
+#define CLS_MAX_NATIVE_PAGE_SIZE (1024 * 4)
+#endif
+#define CLS_MIN_NATIVE_PAGE_SIZE (1024 * 4)
+
+#pragma mark Prototypes
+static void FIRCLSHostWriteSysctlEntry(
+ FIRCLSFile* file, const char* key, const char* sysctlKey, void* buffer, size_t bufferSize);
+static void FIRCLSHostWriteModelInfo(FIRCLSFile* file);
+static void FIRCLSHostWriteOSVersionInfo(FIRCLSFile* file);
+
+#pragma mark - API
+void FIRCLSHostInitialize(FIRCLSHostReadOnlyContext* roContext) {
+ _firclsContext.readonly->host.pageSize = FIRCLSHostGetPageSize();
+ _firclsContext.readonly->host.documentDirectoryPath = NULL;
+
+ // determine where the document directory is mounted, so we can get file system statistics later
+ NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
+ if ([paths count]) {
+ _firclsContext.readonly->host.documentDirectoryPath =
+ FIRCLSDupString([[paths objectAtIndex:0] fileSystemRepresentation]);
+ }
+}
+
+vm_size_t FIRCLSHostGetPageSize(void) {
+ size_t size;
+ int pageSize;
+
+ // hw.pagesize is defined as HW_PAGESIZE, which is an int. It's important to match
+ // these types. Turns out that sysctl will not init the data to zero, but it appears
+ // that sysctlbyname does. This API is nicer, but that's important to keep in mind.
+
+ pageSize = 0;
+ size = sizeof(pageSize);
+ if (sysctlbyname("hw.pagesize", &pageSize, &size, NULL, 0) != 0) {
+ FIRCLSSDKLog("sysctlbyname failed while trying to get hw.pagesize\n");
+
+ return CLS_MAX_NATIVE_PAGE_SIZE;
+ }
+
+ // if the returned size is not the expected value, abort
+ if (size != sizeof(pageSize)) {
+ return CLS_MAX_NATIVE_PAGE_SIZE;
+ }
+
+ // put in some guards to make sure our size is reasonable
+ if (pageSize > CLS_MAX_NATIVE_PAGE_SIZE) {
+ return CLS_MAX_NATIVE_PAGE_SIZE;
+ }
+
+ if (pageSize < CLS_MIN_NATIVE_PAGE_SIZE) {
+ return CLS_MIN_NATIVE_PAGE_SIZE;
+ }
+
+ return pageSize;
+}
+
+static void FIRCLSHostWriteSysctlEntry(
+ FIRCLSFile* file, const char* key, const char* sysctlKey, void* buffer, size_t bufferSize) {
+ if (sysctlbyname(sysctlKey, buffer, &bufferSize, NULL, 0) != 0) {
+ FIRCLSFileWriteHashEntryString(file, key, "(failed)");
+ return;
+ }
+
+ FIRCLSFileWriteHashEntryString(file, key, buffer);
+}
+
+static void FIRCLSHostWriteModelInfo(FIRCLSFile* file) {
+ FIRCLSFileWriteHashEntryString(file, "model", [FIRCLSHostModelInfo() UTF8String]);
+
+ // allocate a static buffer for the sysctl values, which are typically
+ // quite short
+ char buffer[CLS_HOST_SYSCTL_BUFFER_SIZE];
+
+#if TARGET_OS_EMBEDDED
+ FIRCLSHostWriteSysctlEntry(file, "machine", "hw.model", buffer, CLS_HOST_SYSCTL_BUFFER_SIZE);
+#else
+ FIRCLSHostWriteSysctlEntry(file, "machine", "hw.machine", buffer, CLS_HOST_SYSCTL_BUFFER_SIZE);
+ FIRCLSHostWriteSysctlEntry(file, "cpu", "machdep.cpu.brand_string", buffer,
+ CLS_HOST_SYSCTL_BUFFER_SIZE);
+#endif
+}
+
+static void FIRCLSHostWriteOSVersionInfo(FIRCLSFile* file) {
+ FIRCLSFileWriteHashEntryString(file, "os_build_version", [FIRCLSHostOSBuildVersion() UTF8String]);
+ FIRCLSFileWriteHashEntryString(file, "os_display_version",
+ [FIRCLSHostOSDisplayVersion() UTF8String]);
+ FIRCLSFileWriteHashEntryString(file, "platform", [FIRCLSApplicationGetPlatform() UTF8String]);
+}
+
+bool FIRCLSHostRecord(FIRCLSFile* file) {
+ FIRCLSFileWriteSectionStart(file, "host");
+
+ FIRCLSFileWriteHashStart(file);
+
+ FIRCLSHostWriteModelInfo(file);
+ FIRCLSHostWriteOSVersionInfo(file);
+ FIRCLSFileWriteHashEntryString(file, "locale",
+ [[[NSLocale currentLocale] localeIdentifier] UTF8String]);
+
+ FIRCLSFileWriteHashEnd(file);
+
+ FIRCLSFileWriteSectionEnd(file);
+
+ return true;
+}
+
+void FIRCLSHostWriteDiskUsage(FIRCLSFile* file) {
+ struct statfs tStats;
+
+ FIRCLSFileWriteSectionStart(file, "storage");
+
+ FIRCLSFileWriteHashStart(file);
+
+ if (statfs(_firclsContext.readonly->host.documentDirectoryPath, &tStats) == 0) {
+ FIRCLSFileWriteHashEntryUint64(file, "free", tStats.f_bavail * tStats.f_bsize);
+ FIRCLSFileWriteHashEntryUint64(file, "total", tStats.f_blocks * tStats.f_bsize);
+ }
+
+ FIRCLSFileWriteHashEnd(file);
+
+ FIRCLSFileWriteSectionEnd(file);
+}
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSProcess.c b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSProcess.c
new file mode 100644
index 000000000..415466ec4
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSProcess.c
@@ -0,0 +1,824 @@
+// Copyright 2019 Google
+//
+// 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.
+
+#include "FIRCLSProcess.h"
+#include "FIRCLSDefines.h"
+#include "FIRCLSFeatures.h"
+#include "FIRCLSGlobals.h"
+#include "FIRCLSProfiling.h"
+#include "FIRCLSThreadState.h"
+#include "FIRCLSUnwind.h"
+#include "FIRCLSUtility.h"
+
+#include
+#include
+#include
+#include
+
+#define THREAD_NAME_BUFFER_SIZE (64)
+
+#pragma mark Prototypes
+static bool FIRCLSProcessGetThreadName(FIRCLSProcess *process,
+ thread_t thread,
+ char *buffer,
+ size_t length);
+static const char *FIRCLSProcessGetThreadDispatchQueueName(FIRCLSProcess *process, thread_t thread);
+
+#pragma mark - API
+bool FIRCLSProcessInit(FIRCLSProcess *process, thread_t crashedThread, void *uapVoid) {
+ if (!process) {
+ return false;
+ }
+
+ process->task = mach_task_self();
+ process->thisThread = mach_thread_self();
+ process->crashedThread = crashedThread;
+ process->uapVoid = uapVoid;
+
+ if (task_threads(process->task, &process->threads, &process->threadCount) != KERN_SUCCESS) {
+ // failed to get all threads
+ process->threadCount = 0;
+ FIRCLSSDKLog("Error: unable to get task threads\n");
+
+ return false;
+ }
+
+ return true;
+}
+
+bool FIRCLSProcessDestroy(FIRCLSProcess *process) {
+ return false;
+}
+
+// https://developer.apple.com/library/mac/#qa/qa2004/qa1361.html
+bool FIRCLSProcessDebuggerAttached(void) {
+ int junk;
+ int mib[4];
+ struct kinfo_proc info;
+ size_t size;
+
+ // Initialize the flags so that, if sysctl fails for some bizarre
+ // reason, we get a predictable result.
+ info.kp_proc.p_flag = 0;
+
+ // Initialize mib, which tells sysctl the info we want, in this case
+ // we're looking for information about a specific process ID.
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_PID;
+ mib[3] = getpid();
+
+ // Call sysctl.
+ size = sizeof(info);
+ junk = sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0);
+ if (junk != 0) {
+ FIRCLSSDKLog("sysctl failed while trying to get kinfo_proc\n");
+ return false;
+ }
+
+ // We're being debugged if the P_TRACED flag is set.
+ return (info.kp_proc.p_flag & P_TRACED) != 0;
+}
+
+#pragma mark - Thread Support
+static bool FIRCLSProcessIsCurrentThread(FIRCLSProcess *process, thread_t thread) {
+ return MACH_PORT_INDEX(process->thisThread) == MACH_PORT_INDEX(thread);
+}
+
+static bool FIRCLSProcessIsCrashedThread(FIRCLSProcess *process, thread_t thread) {
+ return MACH_PORT_INDEX(process->crashedThread) == MACH_PORT_INDEX(thread);
+}
+
+static uint32_t FIRCLSProcessGetThreadCount(FIRCLSProcess *process) {
+ return process->threadCount;
+}
+
+static thread_t FIRCLSProcessGetThread(FIRCLSProcess *process, uint32_t index) {
+ if (index >= process->threadCount) {
+ return MACH_PORT_NULL;
+ }
+
+ return process->threads[index];
+}
+
+bool FIRCLSProcessSuspendAllOtherThreads(FIRCLSProcess *process) {
+ mach_msg_type_number_t i;
+ bool success;
+
+ success = true;
+ for (i = 0; i < process->threadCount; ++i) {
+ thread_t thread;
+
+ thread = FIRCLSProcessGetThread(process, i);
+
+ if (FIRCLSProcessIsCurrentThread(process, thread)) {
+ continue;
+ }
+
+ // FIXME: workaround to get this building on watch, but we need to suspend/resume threads!
+#if CLS_CAN_SUSPEND_THREADS
+ success = success && (thread_suspend(thread) == KERN_SUCCESS);
+#endif
+ }
+
+ return success;
+}
+
+bool FIRCLSProcessResumeAllOtherThreads(FIRCLSProcess *process) {
+ mach_msg_type_number_t i;
+ bool success;
+
+ success = true;
+ for (i = 0; i < process->threadCount; ++i) {
+ thread_t thread;
+
+ thread = FIRCLSProcessGetThread(process, i);
+
+ if (FIRCLSProcessIsCurrentThread(process, thread)) {
+ continue;
+ }
+
+ // FIXME: workaround to get this building on watch, but we need to suspend/resume threads!
+#if CLS_CAN_SUSPEND_THREADS
+ success = success && (thread_resume(thread) == KERN_SUCCESS);
+#endif
+ }
+
+ return success;
+}
+
+#pragma mark - Thread Properties
+void *FIRCLSThreadGetCurrentPC(void) {
+ return __builtin_return_address(0);
+}
+
+static bool FIRCLSProcessGetThreadState(FIRCLSProcess *process,
+ thread_t thread,
+ FIRCLSThreadContext *context) {
+ if (!FIRCLSIsValidPointer(context)) {
+ FIRCLSSDKLogError("invalid context supplied");
+ return false;
+ }
+
+ // If the thread context we should use is non-NULL, then just assign it here. Otherwise,
+ // query the thread state
+ if (FIRCLSProcessIsCrashedThread(process, thread) && FIRCLSIsValidPointer(process->uapVoid)) {
+ *context = *((_STRUCT_UCONTEXT *)process->uapVoid)->uc_mcontext;
+ return true;
+ }
+
+ // Here's a wild trick: emulate what thread_get_state would do. It apppears that
+ // we cannot reliably unwind out of thread_get_state. So, instead of trying, setup
+ // a thread context that resembles what the real thing would look like
+ if (FIRCLSProcessIsCurrentThread(process, thread)) {
+ FIRCLSSDKLog("Faking current thread\n");
+ memset(context, 0, sizeof(FIRCLSThreadContext));
+
+ // Compute the frame address, and then base the stack value off of that. A frame pushes
+ // two pointers onto the stack, so we have to offset.
+ const uintptr_t frameAddress = (uintptr_t)__builtin_frame_address(0);
+ const uintptr_t stackAddress = FIRCLSUnwindStackPointerFromFramePointer(frameAddress);
+
+#if CLS_CPU_X86_64
+ context->__ss.__rip = (uintptr_t)FIRCLSThreadGetCurrentPC();
+ context->__ss.__rbp = frameAddress;
+ context->__ss.__rsp = stackAddress;
+#elif CLS_CPU_I386
+ context->__ss.__eip = (uintptr_t)FIRCLSThreadGetCurrentPC();
+ context->__ss.__ebp = frameAddress;
+ context->__ss.__esp = stackAddress;
+#elif CLS_CPU_ARM64
+ FIRCLSThreadContextSetPC(context, (uintptr_t)FIRCLSThreadGetCurrentPC());
+ FIRCLSThreadContextSetFramePointer(context, frameAddress);
+ FIRCLSThreadContextSetLinkRegister(context, (uintptr_t)__builtin_return_address(0));
+ FIRCLSThreadContextSetStackPointer(context, stackAddress);
+#elif CLS_CPU_ARM
+ context->__ss.__pc = (uintptr_t)FIRCLSThreadGetCurrentPC();
+ context->__ss.__r[7] = frameAddress;
+ context->__ss.__lr = (uintptr_t)__builtin_return_address(0);
+ context->__ss.__sp = stackAddress;
+#endif
+
+ return true;
+ }
+
+#if !TARGET_OS_WATCH
+ // try to get the value by querying the thread state
+ mach_msg_type_number_t stateCount = FIRCLSThreadStateCount;
+ if (thread_get_state(thread, FIRCLSThreadState, (thread_state_t)(&(context->__ss)),
+ &stateCount) != KERN_SUCCESS) {
+ FIRCLSSDKLogError("failed to get thread state\n");
+ return false;
+ }
+
+ return true;
+#else
+ return false;
+#endif
+}
+
+static bool FIRCLSProcessGetThreadName(FIRCLSProcess *process,
+ thread_t thread,
+ char *buffer,
+ size_t length) {
+ pthread_t pthread;
+
+ if (!buffer || length <= 0) {
+ return false;
+ }
+
+ pthread = pthread_from_mach_thread_np(thread);
+
+ return pthread_getname_np(pthread, buffer, length) == 0;
+}
+
+static const char *FIRCLSProcessGetThreadDispatchQueueName(FIRCLSProcess *process,
+ thread_t thread) {
+ thread_identifier_info_data_t info;
+ mach_msg_type_number_t infoCount;
+ dispatch_queue_t *queueAddress;
+ dispatch_queue_t queue;
+ const char *string;
+
+ infoCount = THREAD_IDENTIFIER_INFO_COUNT;
+ if (thread_info(thread, THREAD_IDENTIFIER_INFO, (thread_info_t)&info, &infoCount) !=
+ KERN_SUCCESS) {
+ FIRCLSSDKLog("unable to get thread info\n");
+ return NULL;
+ }
+
+ queueAddress = (dispatch_queue_t *)info.dispatch_qaddr;
+ if (queueAddress == NULL) {
+ return "";
+ }
+
+ // Sometimes a queue address is invalid. I cannot explain why this is, but
+ // it can cause a crash.
+ if (!FIRCLSReadMemory((vm_address_t)queueAddress, &queue, sizeof(void *))) {
+ return "";
+ }
+
+ // here, we know it is safe to de-reference this address, so attempt to get the queue name
+ if (!queue) {
+ return "";
+ }
+
+ string = dispatch_queue_get_label(queue);
+
+ // but, we still don't if the entire string is valid, so check that too
+ if (!FIRCLSReadString((vm_address_t)string, (char **)&string, 128)) {
+ return "";
+ }
+
+ return string;
+}
+
+#pragma mark - Data Recording
+static bool FIRCLSProcessRecordThreadRegisters(FIRCLSThreadContext context, FIRCLSFile *file) {
+#if CLS_CPU_ARM
+ FIRCLSFileWriteHashEntryUint64(file, "r0", context.__ss.__r[0]);
+ FIRCLSFileWriteHashEntryUint64(file, "r1", context.__ss.__r[1]);
+ FIRCLSFileWriteHashEntryUint64(file, "r2", context.__ss.__r[2]);
+ FIRCLSFileWriteHashEntryUint64(file, "r3", context.__ss.__r[3]);
+ FIRCLSFileWriteHashEntryUint64(file, "r4", context.__ss.__r[4]);
+ FIRCLSFileWriteHashEntryUint64(file, "r5", context.__ss.__r[5]);
+ FIRCLSFileWriteHashEntryUint64(file, "r6", context.__ss.__r[6]);
+ FIRCLSFileWriteHashEntryUint64(file, "r7", context.__ss.__r[7]);
+ FIRCLSFileWriteHashEntryUint64(file, "r8", context.__ss.__r[8]);
+ FIRCLSFileWriteHashEntryUint64(file, "r9", context.__ss.__r[9]);
+ FIRCLSFileWriteHashEntryUint64(file, "r10", context.__ss.__r[10]);
+ FIRCLSFileWriteHashEntryUint64(file, "r11", context.__ss.__r[11]);
+ FIRCLSFileWriteHashEntryUint64(file, "ip", context.__ss.__r[12]);
+ FIRCLSFileWriteHashEntryUint64(file, "sp", context.__ss.__sp);
+ FIRCLSFileWriteHashEntryUint64(file, "lr", context.__ss.__lr);
+ FIRCLSFileWriteHashEntryUint64(file, "pc", context.__ss.__pc);
+ FIRCLSFileWriteHashEntryUint64(file, "cpsr", context.__ss.__cpsr);
+#elif CLS_CPU_ARM64
+ FIRCLSFileWriteHashEntryUint64(file, "x0", context.__ss.__x[0]);
+ FIRCLSFileWriteHashEntryUint64(file, "x1", context.__ss.__x[1]);
+ FIRCLSFileWriteHashEntryUint64(file, "x2", context.__ss.__x[2]);
+ FIRCLSFileWriteHashEntryUint64(file, "x3", context.__ss.__x[3]);
+ FIRCLSFileWriteHashEntryUint64(file, "x4", context.__ss.__x[4]);
+ FIRCLSFileWriteHashEntryUint64(file, "x5", context.__ss.__x[5]);
+ FIRCLSFileWriteHashEntryUint64(file, "x6", context.__ss.__x[6]);
+ FIRCLSFileWriteHashEntryUint64(file, "x7", context.__ss.__x[7]);
+ FIRCLSFileWriteHashEntryUint64(file, "x8", context.__ss.__x[8]);
+ FIRCLSFileWriteHashEntryUint64(file, "x9", context.__ss.__x[9]);
+ FIRCLSFileWriteHashEntryUint64(file, "x10", context.__ss.__x[10]);
+ FIRCLSFileWriteHashEntryUint64(file, "x11", context.__ss.__x[11]);
+ FIRCLSFileWriteHashEntryUint64(file, "x12", context.__ss.__x[12]);
+ FIRCLSFileWriteHashEntryUint64(file, "x13", context.__ss.__x[13]);
+ FIRCLSFileWriteHashEntryUint64(file, "x14", context.__ss.__x[14]);
+ FIRCLSFileWriteHashEntryUint64(file, "x15", context.__ss.__x[15]);
+ FIRCLSFileWriteHashEntryUint64(file, "x16", context.__ss.__x[16]);
+ FIRCLSFileWriteHashEntryUint64(file, "x17", context.__ss.__x[17]);
+ FIRCLSFileWriteHashEntryUint64(file, "x18", context.__ss.__x[18]);
+ FIRCLSFileWriteHashEntryUint64(file, "x19", context.__ss.__x[19]);
+ FIRCLSFileWriteHashEntryUint64(file, "x20", context.__ss.__x[20]);
+ FIRCLSFileWriteHashEntryUint64(file, "x21", context.__ss.__x[21]);
+ FIRCLSFileWriteHashEntryUint64(file, "x22", context.__ss.__x[22]);
+ FIRCLSFileWriteHashEntryUint64(file, "x23", context.__ss.__x[23]);
+ FIRCLSFileWriteHashEntryUint64(file, "x24", context.__ss.__x[24]);
+ FIRCLSFileWriteHashEntryUint64(file, "x25", context.__ss.__x[25]);
+ FIRCLSFileWriteHashEntryUint64(file, "x26", context.__ss.__x[26]);
+ FIRCLSFileWriteHashEntryUint64(file, "x27", context.__ss.__x[27]);
+ FIRCLSFileWriteHashEntryUint64(file, "x28", context.__ss.__x[28]);
+ FIRCLSFileWriteHashEntryUint64(file, "fp", FIRCLSThreadContextGetFramePointer(&context));
+ FIRCLSFileWriteHashEntryUint64(file, "sp", FIRCLSThreadContextGetStackPointer(&context));
+ FIRCLSFileWriteHashEntryUint64(file, "lr", FIRCLSThreadContextGetLinkRegister(&context));
+ FIRCLSFileWriteHashEntryUint64(file, "pc", FIRCLSThreadContextGetPC(&context));
+ FIRCLSFileWriteHashEntryUint64(file, "cpsr", context.__ss.__cpsr);
+#elif CLS_CPU_I386
+ FIRCLSFileWriteHashEntryUint64(file, "eax", context.__ss.__eax);
+ FIRCLSFileWriteHashEntryUint64(file, "ebx", context.__ss.__ebx);
+ FIRCLSFileWriteHashEntryUint64(file, "ecx", context.__ss.__ecx);
+ FIRCLSFileWriteHashEntryUint64(file, "edx", context.__ss.__edx);
+ FIRCLSFileWriteHashEntryUint64(file, "edi", context.__ss.__edi);
+ FIRCLSFileWriteHashEntryUint64(file, "esi", context.__ss.__esi);
+ FIRCLSFileWriteHashEntryUint64(file, "ebp", context.__ss.__ebp);
+ FIRCLSFileWriteHashEntryUint64(file, "esp", context.__ss.__esp);
+ FIRCLSFileWriteHashEntryUint64(file, "ss", context.__ss.__ss);
+ FIRCLSFileWriteHashEntryUint64(file, "eflags", context.__ss.__eflags);
+ FIRCLSFileWriteHashEntryUint64(file, "eip", context.__ss.__eip);
+ FIRCLSFileWriteHashEntryUint64(file, "cs", context.__ss.__cs);
+ FIRCLSFileWriteHashEntryUint64(file, "ds", context.__ss.__ds);
+ FIRCLSFileWriteHashEntryUint64(file, "es", context.__ss.__es);
+ FIRCLSFileWriteHashEntryUint64(file, "fs", context.__ss.__fs);
+ FIRCLSFileWriteHashEntryUint64(file, "gs", context.__ss.__gs);
+
+ // how do we get the cr2 register?
+#elif CLS_CPU_X86_64
+ FIRCLSFileWriteHashEntryUint64(file, "rax", context.__ss.__rax);
+ FIRCLSFileWriteHashEntryUint64(file, "rbx", context.__ss.__rbx);
+ FIRCLSFileWriteHashEntryUint64(file, "rcx", context.__ss.__rcx);
+ FIRCLSFileWriteHashEntryUint64(file, "rdx", context.__ss.__rdx);
+ FIRCLSFileWriteHashEntryUint64(file, "rdi", context.__ss.__rdi);
+ FIRCLSFileWriteHashEntryUint64(file, "rsi", context.__ss.__rsi);
+ FIRCLSFileWriteHashEntryUint64(file, "rbp", context.__ss.__rbp);
+ FIRCLSFileWriteHashEntryUint64(file, "rsp", context.__ss.__rsp);
+ FIRCLSFileWriteHashEntryUint64(file, "r8", context.__ss.__r8);
+ FIRCLSFileWriteHashEntryUint64(file, "r9", context.__ss.__r9);
+ FIRCLSFileWriteHashEntryUint64(file, "r10", context.__ss.__r10);
+ FIRCLSFileWriteHashEntryUint64(file, "r11", context.__ss.__r11);
+ FIRCLSFileWriteHashEntryUint64(file, "r12", context.__ss.__r12);
+ FIRCLSFileWriteHashEntryUint64(file, "r13", context.__ss.__r13);
+ FIRCLSFileWriteHashEntryUint64(file, "r14", context.__ss.__r14);
+ FIRCLSFileWriteHashEntryUint64(file, "r15", context.__ss.__r15);
+ FIRCLSFileWriteHashEntryUint64(file, "rip", context.__ss.__rip);
+ FIRCLSFileWriteHashEntryUint64(file, "rflags", context.__ss.__rflags);
+ FIRCLSFileWriteHashEntryUint64(file, "cs", context.__ss.__cs);
+ FIRCLSFileWriteHashEntryUint64(file, "fs", context.__ss.__fs);
+ FIRCLSFileWriteHashEntryUint64(file, "gs", context.__ss.__gs);
+#endif
+
+ return true;
+}
+
+static bool FIRCLSProcessRecordThread(FIRCLSProcess *process, thread_t thread, FIRCLSFile *file) {
+ FIRCLSUnwindContext unwindContext;
+ FIRCLSThreadContext context;
+
+ if (!FIRCLSProcessGetThreadState(process, thread, &context)) {
+ FIRCLSSDKLogError("unable to get thread state");
+ return false;
+ }
+
+ if (!FIRCLSUnwindInit(&unwindContext, context)) {
+ FIRCLSSDKLog("unable to init unwind context\n");
+
+ return false;
+ }
+
+ FIRCLSFileWriteHashStart(file);
+
+ // registers
+ FIRCLSFileWriteHashKey(file, "registers");
+ FIRCLSFileWriteHashStart(file);
+
+ FIRCLSProcessRecordThreadRegisters(context, file);
+
+ FIRCLSFileWriteHashEnd(file);
+
+ // stacktrace
+ FIRCLSFileWriteHashKey(file, "stacktrace");
+
+ // stacktrace is an array of integers
+ FIRCLSFileWriteArrayStart(file);
+
+ uint32_t repeatedPCCount = 0;
+ uint64_t repeatedPC = 0;
+ const FIRCLSInternalLogLevel level = _firclsContext.writable->internalLogging.logLevel;
+
+ while (FIRCLSUnwindNextFrame(&unwindContext)) {
+ const uintptr_t pc = FIRCLSUnwindGetPC(&unwindContext);
+ const uint32_t frameCount = FIRCLSUnwindGetFrameRepeatCount(&unwindContext);
+
+ if (repeatedPC == pc && repeatedPC != 0) {
+ // actively counting a recursion
+ repeatedPCCount = frameCount;
+ continue;
+ }
+
+ if (frameCount >= FIRCLSUnwindInfiniteRecursionCountThreshold && repeatedPC == 0) {
+ repeatedPC = pc;
+ FIRCLSSDKLogWarn("Possible infinite recursion - suppressing logging\n");
+ _firclsContext.writable->internalLogging.logLevel = FIRCLSInternalLogLevelWarn;
+ continue;
+ }
+
+ if (repeatedPC != 0) {
+ // at this point, we've recorded a repeated PC, but it is now no longer
+ // repeating, so we can restore the logging
+ _firclsContext.writable->internalLogging.logLevel = level;
+ }
+
+ FIRCLSFileWriteArrayEntryUint64(file, pc);
+ }
+
+ FIRCLSFileWriteArrayEnd(file);
+
+ // crashed?
+ if (FIRCLSProcessIsCrashedThread(process, thread)) {
+ FIRCLSFileWriteHashEntryBoolean(file, "crashed", true);
+ }
+
+ if (repeatedPC != 0) {
+ FIRCLSFileWriteHashEntryUint64(file, "repeated_pc", repeatedPC);
+ FIRCLSFileWriteHashEntryUint64(file, "repeat_count", repeatedPCCount);
+ }
+
+ // Just for extra safety, restore the logging level again. The logic
+ // above is fairly tricky, this is cheap, and no logging is a real pain.
+ _firclsContext.writable->internalLogging.logLevel = level;
+
+ // end thread info
+ FIRCLSFileWriteHashEnd(file);
+
+ return true;
+}
+
+bool FIRCLSProcessRecordAllThreads(FIRCLSProcess *process, FIRCLSFile *file) {
+ uint32_t threadCount;
+ uint32_t i;
+
+ threadCount = FIRCLSProcessGetThreadCount(process);
+
+ FIRCLSFileWriteSectionStart(file, "threads");
+
+ FIRCLSFileWriteArrayStart(file);
+
+ for (i = 0; i < threadCount; ++i) {
+ thread_t thread;
+
+ thread = FIRCLSProcessGetThread(process, i);
+
+ FIRCLSSDKLogInfo("recording thread %d data\n", i);
+ if (!FIRCLSProcessRecordThread(process, thread, file)) {
+ return false;
+ }
+ }
+
+ FIRCLSFileWriteArrayEnd(file);
+
+ FIRCLSFileWriteSectionEnd(file);
+
+ FIRCLSSDKLogInfo("completed recording all thread data\n");
+
+ return true;
+}
+
+void FIRCLSProcessRecordThreadNames(FIRCLSProcess *process, FIRCLSFile *file) {
+ uint32_t threadCount;
+ uint32_t i;
+
+ FIRCLSFileWriteSectionStart(file, "thread_names");
+
+ FIRCLSFileWriteArrayStart(file);
+
+ threadCount = FIRCLSProcessGetThreadCount(process);
+ for (i = 0; i < threadCount; ++i) {
+ thread_t thread;
+ char name[THREAD_NAME_BUFFER_SIZE];
+
+ thread = FIRCLSProcessGetThread(process, i);
+
+ name[0] = 0; // null-terminate, just in case nothing is written
+
+ FIRCLSProcessGetThreadName(process, thread, name, THREAD_NAME_BUFFER_SIZE);
+
+ FIRCLSFileWriteArrayEntryString(file, name);
+ }
+
+ FIRCLSFileWriteArrayEnd(file);
+ FIRCLSFileWriteSectionEnd(file);
+}
+
+void FIRCLSProcessRecordDispatchQueueNames(FIRCLSProcess *process, FIRCLSFile *file) {
+ uint32_t threadCount;
+ uint32_t i;
+
+ FIRCLSFileWriteSectionStart(file, "dispatch_queue_names");
+
+ FIRCLSFileWriteArrayStart(file);
+
+ threadCount = FIRCLSProcessGetThreadCount(process);
+ for (i = 0; i < threadCount; ++i) {
+ thread_t thread;
+ const char *name;
+
+ thread = FIRCLSProcessGetThread(process, i);
+
+ name = FIRCLSProcessGetThreadDispatchQueueName(process, thread);
+
+ FIRCLSFileWriteArrayEntryString(file, name);
+ }
+
+ FIRCLSFileWriteArrayEnd(file);
+ FIRCLSFileWriteSectionEnd(file);
+}
+
+#pragma mark - Othe Process Info
+bool FIRCLSProcessGetMemoryUsage(uint64_t *active,
+ uint64_t *inactive,
+ uint64_t *wired,
+ uint64_t *freeMem) {
+ mach_port_t hostPort;
+ mach_msg_type_number_t hostSize;
+ vm_size_t pageSize;
+ vm_statistics_data_t vmStat;
+
+ hostPort = mach_host_self();
+
+ hostSize = sizeof(vm_statistics_data_t) / sizeof(integer_t);
+
+ pageSize = _firclsContext.readonly->host.pageSize;
+
+ if (host_statistics(hostPort, HOST_VM_INFO, (host_info_t)&vmStat, &hostSize) != KERN_SUCCESS) {
+ FIRCLSSDKLog("Failed to get vm statistics\n");
+ return false;
+ }
+
+ if (!(active && inactive && wired && freeMem)) {
+ FIRCLSSDKLog("Invalid pointers\n");
+ return false;
+ }
+
+ // compute the sizes in bytes and return the values
+ *active = vmStat.active_count * pageSize;
+ *inactive = vmStat.inactive_count * pageSize;
+ *wired = vmStat.wire_count * pageSize;
+ *freeMem = vmStat.free_count * pageSize;
+
+ return true;
+}
+
+bool FIRCLSProcessGetInfo(FIRCLSProcess *process,
+ uint64_t *virtualSize,
+ uint64_t *residentSize,
+ time_value_t *userTime,
+ time_value_t *systemTime) {
+ struct task_basic_info_64 taskInfo;
+ mach_msg_type_number_t count;
+
+ count = TASK_BASIC_INFO_64_COUNT;
+ if (task_info(process->task, TASK_BASIC_INFO_64, (task_info_t)&taskInfo, &count) !=
+ KERN_SUCCESS) {
+ FIRCLSSDKLog("Failed to get task info\n");
+ return false;
+ }
+
+ if (!(virtualSize && residentSize && userTime && systemTime)) {
+ FIRCLSSDKLog("Invalid pointers\n");
+ return false;
+ }
+
+ *virtualSize = taskInfo.virtual_size;
+ *residentSize = taskInfo.resident_size;
+ *userTime = taskInfo.user_time;
+ *systemTime = taskInfo.system_time;
+
+ return true;
+}
+
+void FIRCLSProcessRecordStats(FIRCLSProcess *process, FIRCLSFile *file) {
+ uint64_t active;
+ uint64_t inactive;
+ uint64_t virtualSize;
+ uint64_t residentSize;
+ uint64_t wired;
+ uint64_t freeMem;
+ time_value_t userTime;
+ time_value_t systemTime;
+
+ if (!FIRCLSProcessGetMemoryUsage(&active, &inactive, &wired, &freeMem)) {
+ FIRCLSSDKLog("Unable to get process memory usage\n");
+ return;
+ }
+
+ if (!FIRCLSProcessGetInfo(process, &virtualSize, &residentSize, &userTime, &systemTime)) {
+ FIRCLSSDKLog("Unable to get process stats\n");
+ return;
+ }
+
+ FIRCLSFileWriteSectionStart(file, "process_stats");
+
+ FIRCLSFileWriteHashStart(file);
+
+ FIRCLSFileWriteHashEntryUint64(file, "active", active);
+ FIRCLSFileWriteHashEntryUint64(file, "inactive", inactive);
+ FIRCLSFileWriteHashEntryUint64(file, "wired", wired);
+ FIRCLSFileWriteHashEntryUint64(file, "freeMem", freeMem); // Intentionally left in, for now. Arg.
+ FIRCLSFileWriteHashEntryUint64(file, "free_mem", freeMem);
+ FIRCLSFileWriteHashEntryUint64(file, "virtual", virtualSize);
+ FIRCLSFileWriteHashEntryUint64(file, "resident", active);
+ FIRCLSFileWriteHashEntryUint64(file, "user_time",
+ (userTime.seconds * 1000 * 1000) + userTime.microseconds);
+ FIRCLSFileWriteHashEntryUint64(file, "sys_time",
+ (systemTime.seconds * 1000 * 1000) + systemTime.microseconds);
+
+ FIRCLSFileWriteHashEnd(file);
+
+ FIRCLSFileWriteSectionEnd(file);
+}
+
+#pragma mark - Runtime Info
+#define OBJC_MSG_SEND_START ((vm_address_t)objc_msgSend)
+#define OBJC_MSG_SEND_SUPER_START ((vm_address_t)objc_msgSendSuper)
+#define OBJC_MSG_SEND_END (OBJC_MSG_SEND_START + 66)
+#define OBJC_MSG_SEND_SUPER_END (OBJC_MSG_SEND_SUPER_START + 66)
+
+#if !CLS_CPU_ARM64
+#define OBJC_MSG_SEND_STRET_START ((vm_address_t)objc_msgSend_stret)
+#define OBJC_MSG_SEND_SUPER_STRET_START ((vm_address_t)objc_msgSendSuper_stret)
+#define OBJC_MSG_SEND_STRET_END (OBJC_MSG_SEND_STRET_START + 66)
+#define OBJC_MSG_SEND_SUPER_STRET_END (OBJC_MSG_SEND_SUPER_STRET_START + 66)
+#endif
+
+#if CLS_CPU_X86
+#define OBJC_MSG_SEND_FPRET_START ((vm_address_t)objc_msgSend_fpret)
+#define OBJC_MSG_SEND_FPRET_END (OBJC_MSG_SEND_FPRET_START + 66)
+#endif
+
+static const char *FIRCLSProcessGetObjCSelectorName(FIRCLSThreadContext registers) {
+ void *selectorAddress;
+ void *selRegister;
+#if !CLS_CPU_ARM64
+ void *stretSelRegister;
+#endif
+ vm_address_t pc;
+
+ // First, did we crash in objc_msgSend? The two ways I can think
+ // of doing this are to use dladdr, and then comparing the strings to
+ // objc_msg*, or looking up the symbols, and guessing if we are "close enough".
+
+ selectorAddress = NULL;
+
+#if CLS_CPU_ARM
+ pc = registers.__ss.__pc;
+ selRegister = (void *)registers.__ss.__r[1];
+ stretSelRegister = (void *)registers.__ss.__r[2];
+#elif CLS_CPU_ARM64
+ pc = FIRCLSThreadContextGetPC(®isters);
+ selRegister = (void *)registers.__ss.__x[1];
+#elif CLS_CPU_I386
+ pc = registers.__ss.__eip;
+ selRegister = (void *)registers.__ss.__ecx;
+ stretSelRegister = (void *)registers.__ss.__ecx;
+#elif CLS_CPU_X86_64
+ pc = registers.__ss.__rip;
+ selRegister = (void *)registers.__ss.__rsi;
+ stretSelRegister = (void *)registers.__ss.__rdx;
+#endif
+
+ if ((pc >= OBJC_MSG_SEND_START) && (pc <= OBJC_MSG_SEND_END)) {
+ selectorAddress = selRegister;
+ }
+
+#if !CLS_CPU_ARM64
+ if ((pc >= OBJC_MSG_SEND_SUPER_START) && (pc <= OBJC_MSG_SEND_SUPER_END)) {
+ selectorAddress = selRegister;
+ }
+
+ if ((pc >= OBJC_MSG_SEND_STRET_START) && (pc <= OBJC_MSG_SEND_STRET_END)) {
+ selectorAddress = stretSelRegister;
+ }
+
+ if ((pc >= OBJC_MSG_SEND_SUPER_STRET_START) && (pc <= OBJC_MSG_SEND_SUPER_STRET_END)) {
+ selectorAddress = stretSelRegister;
+ }
+
+#if CLS_CPU_X86
+ if ((pc >= OBJC_MSG_SEND_FPRET_START) && (pc <= OBJC_MSG_SEND_FPRET_END)) {
+ selectorAddress = selRegister;
+ }
+#endif
+#endif
+
+ if (!selectorAddress) {
+ return "";
+ }
+
+ if (!FIRCLSReadString((vm_address_t)selectorAddress, (char **)&selectorAddress, 128)) {
+ FIRCLSSDKLog("Unable to read the selector string\n");
+ return "";
+ }
+
+ return selectorAddress;
+}
+
+#define CRASH_ALIGN __attribute__((aligned(8)))
+typedef struct {
+ unsigned version CRASH_ALIGN;
+ const char *message CRASH_ALIGN;
+ const char *signature CRASH_ALIGN;
+ const char *backtrace CRASH_ALIGN;
+ const char *message2 CRASH_ALIGN;
+ void *reserved CRASH_ALIGN;
+ void *reserved2 CRASH_ALIGN;
+} crash_info_t;
+
+static void FIRCLSProcessRecordCrashInfo(FIRCLSFile *file) {
+ // TODO: this should be abstracted into binary images, if possible
+ FIRCLSBinaryImageRuntimeNode *nodes = _firclsContext.writable->binaryImage.nodes;
+ if (!nodes) {
+ FIRCLSSDKLogError("The node structure is NULL\n");
+ return;
+ }
+
+ for (uint32_t i = 0; i < CLS_BINARY_IMAGE_RUNTIME_NODE_COUNT; ++i) {
+ FIRCLSBinaryImageRuntimeNode *node = &nodes[i];
+
+ if (!node->crashInfo) {
+ continue;
+ }
+
+ crash_info_t info;
+
+ if (!FIRCLSReadMemory((vm_address_t)node->crashInfo, &info, sizeof(crash_info_t))) {
+ continue;
+ }
+
+ FIRCLSSDKLogDebug("Found crash info with version %d\n", info.version);
+
+ // Currently support versions 0 through 5.
+ // 4 was in use for a long time, but it appears that with iOS 9 / swift 2.0, the verison has
+ // been bumped.
+ if (info.version > 5) {
+ continue;
+ }
+
+ if (!info.message) {
+ continue;
+ }
+
+#if CLS_BINARY_IMAGE_RUNTIME_NODE_RECORD_NAME
+ FIRCLSSDKLogInfo("Found crash info for %s\n", node->name);
+#endif
+
+ FIRCLSSDKLogDebug("attempting to read crash info string\n");
+
+ char *string = NULL;
+
+ if (!FIRCLSReadString((vm_address_t)info.message, &string, 256)) {
+ FIRCLSSDKLogError("Failed to copy crash info string\n");
+ continue;
+ }
+
+ FIRCLSFileWriteArrayEntryHexEncodedString(file, string);
+ }
+}
+
+void FIRCLSProcessRecordRuntimeInfo(FIRCLSProcess *process, FIRCLSFile *file) {
+ FIRCLSThreadContext mcontext;
+
+ if (!FIRCLSProcessGetThreadState(process, process->crashedThread, &mcontext)) {
+ FIRCLSSDKLogError("unable to get crashed thread state");
+ }
+
+ FIRCLSFileWriteSectionStart(file, "runtime");
+
+ FIRCLSFileWriteHashStart(file);
+
+ FIRCLSFileWriteHashEntryString(file, "objc_selector", FIRCLSProcessGetObjCSelectorName(mcontext));
+
+ FIRCLSFileWriteHashKey(file, "crash_info_entries");
+
+ FIRCLSFileWriteArrayStart(file);
+ FIRCLSProcessRecordCrashInfo(file);
+ FIRCLSFileWriteArrayEnd(file);
+
+ FIRCLSFileWriteHashEnd(file);
+
+ FIRCLSFileWriteSectionEnd(file);
+}
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSProcess.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSProcess.h
new file mode 100644
index 000000000..dbe758ffd
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSProcess.h
@@ -0,0 +1,45 @@
+// Copyright 2019 Google
+//
+// 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.
+
+#pragma once
+
+#include
+#include
+
+#include "FIRCLSFile.h"
+
+typedef struct {
+ // task info
+ mach_port_t task;
+
+ // thread stuff
+ thread_t thisThread;
+ thread_t crashedThread;
+ thread_act_array_t threads;
+ mach_msg_type_number_t threadCount;
+ void *uapVoid; // current thread state
+} FIRCLSProcess;
+
+bool FIRCLSProcessInit(FIRCLSProcess *process, thread_t crashedThread, void *uapVoid);
+bool FIRCLSProcessDestroy(FIRCLSProcess *process);
+bool FIRCLSProcessDebuggerAttached(void);
+
+bool FIRCLSProcessSuspendAllOtherThreads(FIRCLSProcess *process);
+bool FIRCLSProcessResumeAllOtherThreads(FIRCLSProcess *process);
+
+void FIRCLSProcessRecordThreadNames(FIRCLSProcess *process, FIRCLSFile *file);
+void FIRCLSProcessRecordDispatchQueueNames(FIRCLSProcess *process, FIRCLSFile *file);
+bool FIRCLSProcessRecordAllThreads(FIRCLSProcess *process, FIRCLSFile *file);
+void FIRCLSProcessRecordStats(FIRCLSProcess *process, FIRCLSFile *file);
+void FIRCLSProcessRecordRuntimeInfo(FIRCLSProcess *process, FIRCLSFile *file);
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSUserLogging.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSUserLogging.h
new file mode 100644
index 000000000..e1ee897d6
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSUserLogging.h
@@ -0,0 +1,101 @@
+// Copyright 2019 Google
+//
+// 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.
+
+#pragma once
+
+#include "FIRCLSFile.h"
+
+__BEGIN_DECLS
+
+#ifdef __OBJC__
+extern NSString* const FIRCLSStartTimeKey;
+extern NSString* const FIRCLSFirstRunloopTurnTimeKey;
+extern NSString* const FIRCLSInBackgroundKey;
+#if TARGET_OS_IPHONE
+extern NSString* const FIRCLSDeviceOrientationKey;
+extern NSString* const FIRCLSUIOrientationKey;
+#endif
+extern NSString* const FIRCLSUserIdentifierKey;
+extern NSString* const FIRCLSUserNameKey;
+extern NSString* const FIRCLSUserEmailKey;
+extern NSString* const FIRCLSDevelopmentPlatformNameKey;
+extern NSString* const FIRCLSDevelopmentPlatformVersionKey;
+#endif
+
+extern const uint32_t FIRCLSUserLoggingMaxKVEntries;
+
+typedef struct {
+ const char* incrementalPath;
+ const char* compactedPath;
+
+ uint32_t maxIncrementalCount;
+ uint32_t maxCount;
+} FIRCLSUserLoggingKVStorage;
+
+typedef struct {
+ const char* aPath;
+ const char* bPath;
+ uint32_t maxSize;
+ uint32_t maxEntries;
+ bool restrictBySize;
+ uint32_t* entryCount;
+} FIRCLSUserLoggingABStorage;
+
+typedef struct {
+ FIRCLSUserLoggingKVStorage userKVStorage;
+ FIRCLSUserLoggingKVStorage internalKVStorage;
+
+ FIRCLSUserLoggingABStorage logStorage;
+ FIRCLSUserLoggingABStorage errorStorage;
+ FIRCLSUserLoggingABStorage customExceptionStorage;
+} FIRCLSUserLoggingReadOnlyContext;
+
+typedef struct {
+ const char* activeUserLogPath;
+ const char* activeErrorLogPath;
+ const char* activeCustomExceptionPath;
+ uint32_t userKVCount;
+ uint32_t internalKVCount;
+ uint32_t errorsCount;
+} FIRCLSUserLoggingWritableContext;
+
+void FIRCLSUserLoggingInit(FIRCLSUserLoggingReadOnlyContext* roContext,
+ FIRCLSUserLoggingWritableContext* rwContext);
+
+#ifdef __OBJC__
+void FIRCLSUserLoggingRecordUserKeyValue(NSString* key, id value);
+void FIRCLSUserLoggingRecordInternalKeyValue(NSString* key, id value);
+void FIRCLSUserLoggingWriteInternalKeyValue(NSString* key, NSString* value);
+
+void FIRCLSUserLoggingRecordError(NSError* error, NSDictionary* additionalUserInfo);
+
+NSDictionary* FIRCLSUserLoggingGetCompactedKVEntries(FIRCLSUserLoggingKVStorage* storage,
+ bool decodeHex);
+void FIRCLSUserLoggingCompactKVEntries(FIRCLSUserLoggingKVStorage* storage);
+
+void FIRCLSUserLoggingRecordKeyValue(NSString* key,
+ id value,
+ FIRCLSUserLoggingKVStorage* storage,
+ uint32_t* counter);
+
+void FIRCLSUserLoggingWriteAndCheckABFiles(FIRCLSUserLoggingABStorage* storage,
+ const char** activePath,
+ void (^openedFileBlock)(FIRCLSFile* file));
+
+NSArray* FIRCLSUserLoggingStoredKeyValues(const char* path);
+
+OBJC_EXTERN void FIRCLSLog(NSString* format, ...) NS_FORMAT_FUNCTION(1, 2);
+#endif
+
+__END_DECLS
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSUserLogging.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSUserLogging.m
new file mode 100644
index 000000000..0bb768cfe
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSUserLogging.m
@@ -0,0 +1,523 @@
+// Copyright 2019 Google
+//
+// 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.
+
+#include "FIRCLSUserLogging.h"
+
+#include
+
+#include "FIRCLSGlobals.h"
+#include "FIRCLSUtility.h"
+
+#import "FIRCLSReportManager_Private.h"
+
+NSString *const FIRCLSStartTimeKey = @"com.crashlytics.kit-start-time";
+NSString *const FIRCLSFirstRunloopTurnTimeKey = @"com.crashlytics.first-run-loop-time";
+NSString *const FIRCLSInBackgroundKey = @"com.crashlytics.in-background";
+#if TARGET_OS_IPHONE
+NSString *const FIRCLSDeviceOrientationKey = @"com.crashlytics.device-orientation";
+NSString *const FIRCLSUIOrientationKey = @"com.crashlytics.ui-orientation";
+#endif
+NSString *const FIRCLSUserIdentifierKey = @"com.crashlytics.user-id";
+NSString *const FIRCLSDevelopmentPlatformNameKey = @"com.crashlytics.development-platform-name";
+NSString *const FIRCLSDevelopmentPlatformVersionKey =
+ @"com.crashlytics.development-platform-version";
+
+const uint32_t FIRCLSUserLoggingMaxKVEntries = 64;
+
+#pragma mark - Prototypes
+static void FIRCLSUserLoggingWriteKeyValue(NSString *key,
+ NSString *value,
+ FIRCLSUserLoggingKVStorage *storage,
+ uint32_t *counter);
+static void FIRCLSUserLoggingCheckAndSwapABFiles(FIRCLSUserLoggingABStorage *storage,
+ const char **activePath,
+ off_t fileSize);
+void FIRCLSLogInternal(NSString *message);
+
+#pragma mark - Setup
+void FIRCLSUserLoggingInit(FIRCLSUserLoggingReadOnlyContext *roContext,
+ FIRCLSUserLoggingWritableContext *rwContext) {
+ rwContext->activeUserLogPath = roContext->logStorage.aPath;
+ rwContext->activeErrorLogPath = roContext->errorStorage.aPath;
+ rwContext->activeCustomExceptionPath = roContext->customExceptionStorage.aPath;
+
+ rwContext->userKVCount = 0;
+ rwContext->internalKVCount = 0;
+ rwContext->errorsCount = 0;
+
+ roContext->userKVStorage.maxIncrementalCount = FIRCLSUserLoggingMaxKVEntries;
+ roContext->internalKVStorage.maxIncrementalCount = roContext->userKVStorage.maxIncrementalCount;
+}
+
+#pragma mark - KV Logging
+void FIRCLSUserLoggingRecordInternalKeyValue(NSString *key, id value) {
+ FIRCLSUserLoggingRecordKeyValue(key, value, &_firclsContext.readonly->logging.internalKVStorage,
+ &_firclsContext.writable->logging.internalKVCount);
+}
+
+void FIRCLSUserLoggingWriteInternalKeyValue(NSString *key, NSString *value) {
+ // Unsynchronized - must be run on the correct queue
+ FIRCLSUserLoggingWriteKeyValue(key, value, &_firclsContext.readonly->logging.internalKVStorage,
+ &_firclsContext.writable->logging.internalKVCount);
+}
+
+void FIRCLSUserLoggingRecordUserKeyValue(NSString *key, id value) {
+ FIRCLSUserLoggingRecordKeyValue(key, value, &_firclsContext.readonly->logging.userKVStorage,
+ &_firclsContext.writable->logging.userKVCount);
+}
+
+static id FIRCLSUserLoggingGetComponent(NSDictionary *entry,
+ NSString *componentName,
+ bool decodeHex) {
+ id value = [entry objectForKey:componentName];
+
+ return (decodeHex && value != [NSNull null]) ? FIRCLSFileHexDecodeString([value UTF8String])
+ : value;
+}
+
+static NSString *FIRCLSUserLoggingGetKey(NSDictionary *entry, bool decodeHex) {
+ return FIRCLSUserLoggingGetComponent(entry, @"key", decodeHex);
+}
+
+static id FIRCLSUserLoggingGetValue(NSDictionary *entry, bool decodeHex) {
+ return FIRCLSUserLoggingGetComponent(entry, @"value", decodeHex);
+}
+
+NSDictionary *FIRCLSUserLoggingGetCompactedKVEntries(FIRCLSUserLoggingKVStorage *storage,
+ bool decodeHex) {
+ if (!FIRCLSIsValidPointer(storage)) {
+ FIRCLSSDKLogError("storage invalid\n");
+ return nil;
+ }
+
+ NSArray *incrementalKVs = FIRCLSUserLoggingStoredKeyValues(storage->incrementalPath);
+ NSArray *compactedKVs = FIRCLSUserLoggingStoredKeyValues(storage->compactedPath);
+
+ NSMutableDictionary *finalKVSet = [NSMutableDictionary new];
+
+ // These should all be unique, so there might be a more efficient way to
+ // do this
+ for (NSDictionary *entry in compactedKVs) {
+ NSString *key = FIRCLSUserLoggingGetKey(entry, decodeHex);
+ NSString *value = FIRCLSUserLoggingGetValue(entry, decodeHex);
+
+ if (!key || !value) {
+ FIRCLSSDKLogError("compacted key/value contains a nil and must be dropped\n");
+ continue;
+ }
+
+ [finalKVSet setObject:value forKey:key];
+ }
+
+ // Now, assign the incremental values, in file order, so we overwrite any older values.
+ for (NSDictionary *entry in incrementalKVs) {
+ NSString *key = FIRCLSUserLoggingGetKey(entry, decodeHex);
+ NSString *value = FIRCLSUserLoggingGetValue(entry, decodeHex);
+
+ if (!key || !value) {
+ FIRCLSSDKLogError("incremental key/value contains a nil and must be dropped\n");
+ continue;
+ }
+
+ if ([value isEqual:[NSNull null]]) {
+ [finalKVSet removeObjectForKey:key];
+ } else {
+ [finalKVSet setObject:value forKey:key];
+ }
+ }
+
+ return finalKVSet;
+}
+
+void FIRCLSUserLoggingCompactKVEntries(FIRCLSUserLoggingKVStorage *storage) {
+ if (!FIRCLSIsValidPointer(storage)) {
+ FIRCLSSDKLogError("Error: storage invalid\n");
+ return;
+ }
+
+ NSDictionary *finalKVs = FIRCLSUserLoggingGetCompactedKVEntries(storage, false);
+
+ if (unlink(storage->compactedPath) != 0) {
+ FIRCLSSDKLog("Error: Unable to remove compacted KV store before compaction %s\n",
+ strerror(errno));
+ }
+
+ FIRCLSFile file;
+
+ if (!FIRCLSFileInitWithPath(&file, storage->compactedPath, true)) {
+ FIRCLSSDKLog("Error: Unable to open compacted k-v file\n");
+ return;
+ }
+
+ uint32_t maxCount = storage->maxCount;
+ if ([finalKVs count] > maxCount) {
+ // We need to remove keys, to avoid going over the max.
+ // This is just about the worst way to go about doing this. There are lots of smarter ways,
+ // but it's very uncommon to go down this path.
+ NSArray *keys = [finalKVs allKeys];
+
+ FIRCLSSDKLogInfo("Truncating KV set, which is above max %d\n", maxCount);
+
+ finalKVs =
+ [finalKVs dictionaryWithValuesForKeys:[keys subarrayWithRange:NSMakeRange(0, maxCount)]];
+ }
+
+ for (NSString *key in finalKVs) {
+ NSString *value = [finalKVs objectForKey:key];
+
+ FIRCLSFileWriteSectionStart(&file, "kv");
+ FIRCLSFileWriteHashStart(&file);
+ // tricky - the values stored incrementally have already been hex-encoded
+ FIRCLSFileWriteHashEntryString(&file, "key", [key UTF8String]);
+ FIRCLSFileWriteHashEntryString(&file, "value", [value UTF8String]);
+ FIRCLSFileWriteHashEnd(&file);
+ FIRCLSFileWriteSectionEnd(&file);
+ }
+
+ FIRCLSFileClose(&file);
+
+ if (unlink(storage->incrementalPath) != 0) {
+ FIRCLSSDKLog("Error: Unable to remove incremental KV store after compaction %s\n",
+ strerror(errno));
+ }
+}
+
+void FIRCLSUserLoggingRecordKeyValue(NSString *key,
+ id value,
+ FIRCLSUserLoggingKVStorage *storage,
+ uint32_t *counter) {
+ if (!FIRCLSIsValidPointer(key)) {
+ FIRCLSSDKLogWarn("User provided bad key\n");
+ return;
+ }
+
+ // ensure that any invalid pointer is actually set to nil
+ if (!FIRCLSIsValidPointer(value) && value != nil) {
+ FIRCLSSDKLogWarn("Bad value pointer being clamped to nil\n");
+ value = nil;
+ }
+
+ if (!FIRCLSContextIsInitialized()) {
+ return;
+ }
+
+ if ([value respondsToSelector:@selector(description)]) {
+ value = [value description];
+ } else {
+ // passing nil will result in a JSON null being written, which is deserialized as [NSNull null],
+ // signaling to remove the key during compaction
+ value = nil;
+ }
+
+ dispatch_sync(FIRCLSGetLoggingQueue(), ^{
+ FIRCLSUserLoggingWriteKeyValue(key, value, storage, counter);
+ });
+}
+
+static void FIRCLSUserLoggingWriteKeyValue(NSString *key,
+ NSString *value,
+ FIRCLSUserLoggingKVStorage *storage,
+ uint32_t *counter) {
+ FIRCLSFile file;
+
+ if (!FIRCLSIsValidPointer(storage) || !FIRCLSIsValidPointer(counter)) {
+ FIRCLSSDKLogError("Bad parameters\n");
+ return;
+ }
+
+ if (!FIRCLSFileInitWithPath(&file, storage->incrementalPath, true)) {
+ FIRCLSSDKLogError("Unable to open k-v file\n");
+ return;
+ }
+
+ FIRCLSFileWriteSectionStart(&file, "kv");
+ FIRCLSFileWriteHashStart(&file);
+ FIRCLSFileWriteHashEntryHexEncodedString(&file, "key", [key UTF8String]);
+ FIRCLSFileWriteHashEntryHexEncodedString(&file, "value", [value UTF8String]);
+ FIRCLSFileWriteHashEnd(&file);
+ FIRCLSFileWriteSectionEnd(&file);
+
+ FIRCLSFileClose(&file);
+
+ *counter += 1;
+ if (*counter >= storage->maxIncrementalCount) {
+ dispatch_async(FIRCLSGetLoggingQueue(), ^{
+ FIRCLSUserLoggingCompactKVEntries(storage);
+ *counter = 0;
+ });
+ }
+}
+
+NSArray *FIRCLSUserLoggingStoredKeyValues(const char *path) {
+ if (!FIRCLSContextIsInitialized()) {
+ return nil;
+ }
+
+ return FIRCLSFileReadSections(path, true, ^NSObject *(id obj) {
+ return [obj objectForKey:@"kv"];
+ });
+}
+
+#pragma mark - NSError Logging
+static void FIRCLSUserLoggingRecordErrorUserInfo(FIRCLSFile *file,
+ const char *fileKey,
+ NSDictionary *userInfo) {
+ if ([userInfo count] == 0) {
+ return;
+ }
+
+ FIRCLSFileWriteHashKey(file, fileKey);
+ FIRCLSFileWriteArrayStart(file);
+
+ for (id key in userInfo) {
+ id value = [userInfo objectForKey:key];
+ if (![value respondsToSelector:@selector(description)]) {
+ continue;
+ }
+
+ FIRCLSFileWriteArrayStart(file);
+ FIRCLSFileWriteArrayEntryHexEncodedString(file, [key UTF8String]);
+ FIRCLSFileWriteArrayEntryHexEncodedString(file, [[value description] UTF8String]);
+ FIRCLSFileWriteArrayEnd(file);
+ }
+
+ FIRCLSFileWriteArrayEnd(file);
+}
+
+static void FIRCLSUserLoggingWriteError(FIRCLSFile *file,
+ NSError *error,
+ NSDictionary *additionalUserInfo,
+ NSArray *addresses,
+ uint64_t timestamp) {
+ FIRCLSFileWriteSectionStart(file, "error");
+ FIRCLSFileWriteHashStart(file);
+ FIRCLSFileWriteHashEntryHexEncodedString(file, "domain", [[error domain] UTF8String]);
+ FIRCLSFileWriteHashEntryInt64(file, "code", [error code]);
+ FIRCLSFileWriteHashEntryUint64(file, "time", timestamp);
+
+ // addresses
+ FIRCLSFileWriteHashKey(file, "stacktrace");
+ FIRCLSFileWriteArrayStart(file);
+ for (NSNumber *address in addresses) {
+ FIRCLSFileWriteArrayEntryUint64(file, [address unsignedLongLongValue]);
+ }
+ FIRCLSFileWriteArrayEnd(file);
+
+ // user-info
+ FIRCLSUserLoggingRecordErrorUserInfo(file, "info", [error userInfo]);
+ FIRCLSUserLoggingRecordErrorUserInfo(file, "extra_info", additionalUserInfo);
+
+ FIRCLSFileWriteHashEnd(file);
+ FIRCLSFileWriteSectionEnd(file);
+}
+
+void FIRCLSUserLoggingRecordError(NSError *error,
+ NSDictionary *additionalUserInfo) {
+ if (!error) {
+ return;
+ }
+
+ if (!FIRCLSContextIsInitialized()) {
+ return;
+ }
+
+ // record the stacktrace and timestamp here, so we
+ // are as close as possible to the user's log statement
+ NSArray *addresses = [NSThread callStackReturnAddresses];
+ uint64_t timestamp = time(NULL);
+
+ FIRCLSUserLoggingWriteAndCheckABFiles(
+ &_firclsContext.readonly->logging.errorStorage,
+ &_firclsContext.writable->logging.activeErrorLogPath, ^(FIRCLSFile *file) {
+ FIRCLSUserLoggingWriteError(file, error, additionalUserInfo, addresses, timestamp);
+ });
+}
+
+#pragma mark - CLSLog Support
+void FIRCLSLog(NSString *format, ...) {
+ // If the format is nil do nothing just like NSLog.
+ if (!format) {
+ return;
+ }
+
+ va_list args;
+ va_start(args, format);
+ NSString *msg = [[NSString alloc] initWithFormat:format arguments:args];
+ va_end(args);
+
+ FIRCLSLogInternal(msg);
+}
+
+#pragma mark - Properties
+uint32_t FIRCLSUserLoggingMaxLogSize(void) {
+ // don't forget that the message encoding overhead is 2x, and we
+ // wrap everything in a json structure with time. So, there is
+ // quite a penalty
+
+ uint32_t size = 1024 * 64;
+
+ return size * 2;
+}
+
+uint32_t FIRCLSUserLoggingMaxErrorSize(void) {
+ return FIRCLSUserLoggingMaxLogSize();
+}
+
+#pragma mark - AB Logging
+void FIRCLSUserLoggingCheckAndSwapABFiles(FIRCLSUserLoggingABStorage *storage,
+ const char **activePath,
+ off_t fileSize) {
+ if (!activePath || !storage) {
+ return;
+ }
+
+ if (!*activePath) {
+ return;
+ }
+
+ if (storage->restrictBySize) {
+ if (fileSize <= storage->maxSize) {
+ return;
+ }
+ } else {
+ if (!FIRCLSIsValidPointer(storage->entryCount)) {
+ FIRCLSSDKLogError("Error: storage has invalid pointer, but is restricted by entry count\n");
+ return;
+ }
+
+ if (*storage->entryCount < storage->maxEntries) {
+ return;
+ }
+
+ // Here we have rolled over, so we have to reset our counter.
+ *storage->entryCount = 0;
+ }
+
+ // if it is too big:
+ // - reset the other log
+ // - make it active
+ const char *otherPath = NULL;
+
+ if (*activePath == storage->aPath) {
+ otherPath = storage->bPath;
+ } else {
+ // take this path if the pointer is invalid as well, to reset
+ otherPath = storage->aPath;
+ }
+
+ // guard here against path being nil or empty
+ NSString *pathString = [NSString stringWithUTF8String:otherPath];
+
+ if ([pathString length] > 0) {
+ // ignore the error, because there is nothing we can do to recover here, and its likely
+ // any failures would be intermittent
+
+ [[NSFileManager defaultManager] removeItemAtPath:pathString error:nil];
+ }
+
+ *activePath = otherPath;
+}
+
+void FIRCLSUserLoggingWriteAndCheckABFiles(FIRCLSUserLoggingABStorage *storage,
+ const char **activePath,
+ void (^openedFileBlock)(FIRCLSFile *file)) {
+ if (!storage || !activePath || !openedFileBlock) {
+ return;
+ }
+
+ if (!*activePath) {
+ return;
+ }
+
+ if (storage->restrictBySize) {
+ if (storage->maxSize == 0) {
+ return;
+ }
+ } else {
+ if (storage->maxEntries == 0) {
+ return;
+ }
+ }
+
+ dispatch_sync(FIRCLSGetLoggingQueue(), ^{
+ FIRCLSFile file;
+
+ if (!FIRCLSFileInitWithPath(&file, *activePath, true)) {
+ FIRCLSSDKLog("Unable to open log file\n");
+ return;
+ }
+
+ openedFileBlock(&file);
+
+ off_t fileSize = 0;
+ FIRCLSFileCloseWithOffset(&file, &fileSize);
+
+ // increment the count before calling FIRCLSUserLoggingCheckAndSwapABFiles, so the value
+ // reflects the actual amount of stuff written
+ if (!storage->restrictBySize && FIRCLSIsValidPointer(storage->entryCount)) {
+ *storage->entryCount += 1;
+ }
+
+ dispatch_async(FIRCLSGetLoggingQueue(), ^{
+ FIRCLSUserLoggingCheckAndSwapABFiles(storage, activePath, fileSize);
+ });
+ });
+}
+
+void FIRCLSLogInternalWrite(FIRCLSFile *file, NSString *message, uint64_t time) {
+ FIRCLSFileWriteSectionStart(file, "log");
+ FIRCLSFileWriteHashStart(file);
+ FIRCLSFileWriteHashEntryHexEncodedString(file, "msg", [message UTF8String]);
+ FIRCLSFileWriteHashEntryUint64(file, "time", time);
+ FIRCLSFileWriteHashEnd(file);
+ FIRCLSFileWriteSectionEnd(file);
+}
+
+void FIRCLSLogInternal(NSString *message) {
+ if (!message) {
+ return;
+ }
+
+ if (!FIRCLSContextIsInitialized()) {
+ FIRCLSWarningLog(@"WARNING: FIRCLSLog has been used before (or concurrently with) "
+ @"Crashlytics initialization and cannot be recorded. The message was: \n%@",
+ message);
+ return;
+ }
+ struct timeval te;
+
+ NSUInteger messageLength = [message length];
+ int maxLogSize = _firclsContext.readonly->logging.logStorage.maxSize;
+
+ if (messageLength > maxLogSize) {
+ FIRCLSWarningLog(
+ @"WARNING: Attempted to write %zd bytes, but %d is the maximum size of the log. "
+ @"Truncating to %d bytes.\n",
+ messageLength, maxLogSize, maxLogSize);
+ message = [message substringToIndex:maxLogSize];
+ }
+
+ // unable to get time - abort
+ if (gettimeofday(&te, NULL) != 0) {
+ return;
+ }
+
+ const uint64_t time = te.tv_sec * 1000LL + te.tv_usec / 1000;
+
+ FIRCLSUserLoggingWriteAndCheckABFiles(&_firclsContext.readonly->logging.logStorage,
+ &_firclsContext.writable->logging.activeUserLogPath,
+ ^(FIRCLSFile *file) {
+ FIRCLSLogInternalWrite(file, message, time);
+ });
+}
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSNetworkClient.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSNetworkClient.h
new file mode 100644
index 000000000..2c259c296
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSNetworkClient.h
@@ -0,0 +1,61 @@
+// Copyright 2019 Google
+//
+// 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
+
+typedef NS_ENUM(NSInteger, FIRCLSNetworkClientErrorType) {
+ FIRCLSNetworkClientErrorTypeUnknown = -1,
+ FIRCLSNetworkClientErrorTypeFileUnreadable = -2
+};
+
+extern NSString *const FIRCLSNetworkClientErrorDomain;
+
+@protocol FIRCLSNetworkClientDelegate;
+@class FIRCLSDataCollectionToken;
+@class FIRCLSFileManager;
+
+@interface FIRCLSNetworkClient : NSObject
+
+- (instancetype)init NS_UNAVAILABLE;
++ (instancetype)new NS_UNAVAILABLE;
+- (instancetype)initWithQueue:(NSOperationQueue *)queue
+ fileManager:(FIRCLSFileManager *)fileManager
+ delegate:(id)delegate;
+
+@property(nonatomic, weak) id delegate;
+
+@property(nonatomic, readonly) NSOperationQueue *operationQueue;
+@property(nonatomic, readonly) BOOL supportsBackgroundRequests;
+
+- (void)startUploadRequest:(NSURLRequest *)request
+ filePath:(NSString *)path
+ dataCollectionToken:(FIRCLSDataCollectionToken *)dataCollectionToken
+ immediately:(BOOL)immediate;
+
+- (void)attemptToReconnectBackgroundSessionWithCompletionBlock:(void (^)(void))completionBlock;
+
+@end
+
+@class FIRCLSNetworkClient;
+
+@protocol FIRCLSNetworkClientDelegate
+@required
+- (BOOL)networkClientCanUseBackgroundSessions:(FIRCLSNetworkClient *)client;
+
+@optional
+- (void)networkClient:(FIRCLSNetworkClient *)client
+ didFinishUploadWithPath:(NSString *)path
+ error:(NSError *)error;
+
+@end
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSNetworkClient.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSNetworkClient.m
new file mode 100644
index 000000000..5fee0ca9f
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSNetworkClient.m
@@ -0,0 +1,366 @@
+// Copyright 2019 Google
+//
+// 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 "FIRCLSNetworkClient.h"
+
+#import "FIRCLSApplication.h"
+#import "FIRCLSByteUtility.h"
+#import "FIRCLSDataCollectionToken.h"
+#import "FIRCLSDefines.h"
+#import "FIRCLSFileManager.h"
+#import "FIRCLSNetworkResponseHandler.h"
+#import "FIRCLSURLSession.h"
+#import "FIRCLSURLSessionConfiguration.h"
+
+#import "FIRCLSUtility.h"
+
+NSString *const FIRCLSNetworkClientErrorDomain = @"FIRCLSNetworkError";
+
+NSString *const FIRCLSNetworkClientBackgroundIdentifierSuffix = @".crash.background-session";
+
+@interface FIRCLSNetworkClient () {
+ NSURLSession *_session;
+}
+
+@property(nonatomic, strong) void (^backgroundCompletionHandler)(void);
+@property(nonatomic, strong, readonly) NSURLSession *session;
+@property(nonatomic, assign) BOOL canUseBackgroundSession;
+@property(nonatomic, strong) FIRCLSFileManager *fileManager;
+
+@end
+
+@implementation FIRCLSNetworkClient
+
+- (instancetype)initWithQueue:(NSOperationQueue *)queue
+ fileManager:(FIRCLSFileManager *)fileManager
+ delegate:(id)delegate {
+ self = [super init];
+ if (!self) {
+ return nil;
+ }
+
+ _operationQueue = queue;
+ _delegate = delegate;
+ _fileManager = fileManager;
+
+ self.canUseBackgroundSession = [_delegate networkClientCanUseBackgroundSessions:self];
+
+ if (!self.supportsBackgroundRequests) {
+ FIRCLSDeveloperLog(
+ "Crashlytics:Crash:Client",
+ @"Background session uploading not supported, asynchronous uploading will be used");
+ }
+
+ return self;
+}
+
+#pragma mark - Background Support
+- (NSURLSession *)session {
+ // Creating a NSURLSession takes some time. Doing it lazily saves us time in the normal case.
+ if (_session) {
+ return _session;
+ }
+
+ NSURLSessionConfiguration *config = nil;
+
+ Class urlSessionClass;
+ Class urlSessionConfigurationClass;
+#if FIRCLSURLSESSION_REQUIRED
+ urlSessionClass = [FIRCLSURLSession class];
+ urlSessionConfigurationClass = [FIRCLSURLSessionConfiguration class];
+#else
+ urlSessionClass = [NSURLSession class];
+ urlSessionConfigurationClass = [NSURLSessionConfiguration class];
+#endif
+
+ if (self.supportsBackgroundRequests) {
+ NSString *sdkBundleID = FIRCLSApplicationGetSDKBundleID();
+ NSString *backgroundConfigName =
+ [sdkBundleID stringByAppendingString:FIRCLSNetworkClientBackgroundIdentifierSuffix];
+
+ config = [urlSessionConfigurationClass backgroundSessionConfiguration:backgroundConfigName];
+#if TARGET_OS_IPHONE
+ [config setSessionSendsLaunchEvents:NO];
+#endif
+ }
+
+ if (!config) {
+ // take this code path if we don't support background requests OR if we failed to create a
+ // background configuration
+ config = [urlSessionConfigurationClass defaultSessionConfiguration];
+ }
+
+ _session = [urlSessionClass sessionWithConfiguration:config
+ delegate:self
+ delegateQueue:self.operationQueue];
+
+ if (!_session || !config) {
+ FIRCLSErrorLog(@"Failed to initialize");
+ }
+
+ return _session;
+}
+
+#if FIRCLSURLSESSION_REQUIRED
+- (BOOL)NSURLSessionAvailable {
+ if ([[FIRCLSURLSession class] respondsToSelector:@selector(NSURLSessionShouldBeUsed)]) {
+ return [FIRCLSURLSession NSURLSessionShouldBeUsed];
+ }
+
+ return NSClassFromString(@"NSURLSession") != nil;
+}
+#endif
+
+- (BOOL)supportsBackgroundRequests {
+ return !FIRCLSApplicationIsExtension()
+#if FIRCLSURLSESSION_REQUIRED
+ && [self NSURLSessionAvailable]
+#endif
+ && self.canUseBackgroundSession;
+}
+
+- (void)attemptToReconnectBackgroundSessionWithCompletionBlock:(void (^)(void))completionBlock {
+ if (!self.supportsBackgroundRequests) {
+ if (completionBlock) {
+ completionBlock();
+ }
+ return;
+ }
+
+ // This is the absolute minimum necessary. Perhaps we can do better?
+ if (completionBlock) {
+ [[NSOperationQueue mainQueue] addOperationWithBlock:completionBlock];
+ }
+}
+
+#pragma mark - API
+- (void)startUploadRequest:(NSURLRequest *)request
+ filePath:(NSString *)path
+ dataCollectionToken:(FIRCLSDataCollectionToken *)dataCollectionToken
+ immediately:(BOOL)immediate {
+ if (![dataCollectionToken isValid]) {
+ FIRCLSErrorLog(@"An upload was requested with an invalid data collection token.");
+ return;
+ }
+
+ if (immediate) {
+ [self startImmediateUploadRequest:request filePath:path];
+ return;
+ }
+
+ NSString *description = [self relativeTaskPathForAbsolutePath:path];
+ [self checkForExistingTaskMatchingDescription:description
+ completionBlock:^(BOOL found) {
+ if (found) {
+ FIRCLSDeveloperLog(
+ "Crashlytics:Crash:Client",
+ @"A task currently exists for this upload, skipping");
+ return;
+ }
+
+ [self startNewUploadRequest:request filePath:path];
+ }];
+}
+
+#pragma mark - Support API
+- (void)startImmediateUploadRequest:(NSURLRequest *)request filePath:(NSString *)path {
+ // check the ivar directly, to avoid going back to the delegate
+ if (self.supportsBackgroundRequests) {
+ // this can be done here, because the request will be started synchronously.
+ [self startNewUploadRequest:request filePath:path];
+ return;
+ }
+
+ if (![[NSFileManager defaultManager] isReadableFileAtPath:path]) {
+ FIRCLSSDKLog("Error: file unreadable\n");
+ // Following the same logic as below, do not try to inform the delegate
+ return;
+ }
+
+ NSMutableURLRequest *mutableRequest = [request mutableCopy];
+
+ [mutableRequest setHTTPBodyStream:[NSInputStream inputStreamWithFileAtPath:path]];
+
+ NSURLResponse *requestResponse = nil;
+
+ [[NSURLSession sharedSession]
+ dataTaskWithRequest:mutableRequest
+ completionHandler:^(NSData *_Nullable data, NSURLResponse *_Nullable response,
+ NSError *_Nullable error) {
+ [FIRCLSNetworkResponseHandler
+ clientResponseType:requestResponse
+ handler:^(FIRCLSNetworkClientResponseType type, NSInteger statusCode) {
+ if (type != FIRCLSNetworkClientResponseSuccess) {
+ // don't even inform the delegate of a failure here, because we don't
+ // want any action to be taken synchronously
+ return;
+ }
+
+ [[self delegate] networkClient:self
+ didFinishUploadWithPath:path
+ error:error];
+ }];
+ }];
+}
+
+- (void)startNewUploadRequest:(NSURLRequest *)request filePath:(NSString *)path {
+ if (![[NSFileManager defaultManager] isReadableFileAtPath:path]) {
+ [self.operationQueue addOperationWithBlock:^{
+ [self
+ handleTaskDescription:path
+ completedWithError:[NSError errorWithDomain:FIRCLSNetworkClientErrorDomain
+ code:FIRCLSNetworkClientErrorTypeFileUnreadable
+ userInfo:@{@"path" : path}]];
+ }];
+
+ return;
+ }
+
+ NSURLSessionUploadTask *task = [self.session uploadTaskWithRequest:request
+ fromFile:[NSURL fileURLWithPath:path]];
+
+ // set the description, so we can determine what file was successfully uploaded later on
+ [task setTaskDescription:[self relativeTaskPathForAbsolutePath:path]];
+
+ [task resume];
+}
+
+- (NSString *)rootPath {
+ return self.fileManager.rootPath;
+}
+
+- (NSString *)absolutePathForRelativeTaskPath:(NSString *)path {
+ return [self.rootPath stringByAppendingPathComponent:path];
+}
+
+- (NSString *)relativeTaskPathForAbsolutePath:(NSString *)path {
+ // make sure this has a tailing slash, so the path looks relative
+ NSString *root = [self.rootPath stringByAppendingString:@"/"];
+
+ if (![path hasPrefix:root]) {
+ FIRCLSSDKLog("Error: path '%s' is not at the root '%s'", [path UTF8String], [root UTF8String]);
+ return nil;
+ }
+
+ return [path stringByReplacingOccurrencesOfString:root withString:@""];
+}
+
+#pragma mark - Task Management
+- (BOOL)taskArray:(NSArray *)array hasTaskMatchingDescription:(NSString *)description {
+ NSUInteger idx = [array indexOfObjectPassingTest:^BOOL(id obj, NSUInteger arrayIdx, BOOL *stop) {
+ return [[obj taskDescription] isEqualToString:description];
+ }];
+
+ return idx != NSNotFound;
+}
+
+- (void)checkSession:(NSURLSession *)session
+ forTasksMatchingDescription:(NSString *)description
+ completionBlock:(void (^)(BOOL found))block {
+ if (!session) {
+ block(NO);
+ return;
+ }
+
+ [session getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks,
+ NSArray *downloadTasks) {
+ if ([self taskArray:uploadTasks hasTaskMatchingDescription:description]) {
+ block(YES);
+ return;
+ }
+
+ if ([self taskArray:dataTasks hasTaskMatchingDescription:description]) {
+ block(YES);
+ return;
+ }
+
+ if ([self taskArray:downloadTasks hasTaskMatchingDescription:description]) {
+ block(YES);
+ return;
+ }
+
+ block(NO);
+ }];
+}
+
+- (void)checkForExistingTaskMatchingDescription:(NSString *)description
+ completionBlock:(void (^)(BOOL found))block {
+ // Do not instantiate the normal session, because if it doesn't exist yet, it cannot possibly have
+ // existing tasks
+ [_operationQueue addOperationWithBlock:^{
+ [self checkSession:self.session
+ forTasksMatchingDescription:description
+ completionBlock:^(BOOL found) {
+ block(found);
+ }];
+ }];
+}
+
+#pragma mark - Result Handling
+// This method is duplicated from FIRCLSFABNetworkClient. Sharing it is a little weird - I didn't
+// feel like it fit into FIRCLSNetworkResponseHandler.
+- (void)runAfterRetryValueFromResponse:(NSURLResponse *)response block:(void (^)(void))block {
+ NSTimeInterval delay = [FIRCLSNetworkResponseHandler retryValueForResponse:response];
+
+ // FIRCLSDeveloperLog("Network", @"Restarting request after %f", delay);
+
+ FIRCLSAddOperationAfter(delay, _operationQueue, block);
+}
+
+- (void)restartTask:(NSURLSessionTask *)task {
+ NSURLRequest *request = [task originalRequest];
+
+ [self runAfterRetryValueFromResponse:[task response]
+ block:^{
+ NSString *path = [self
+ absolutePathForRelativeTaskPath:[task taskDescription]];
+
+ [self startNewUploadRequest:request filePath:path];
+ }];
+}
+
+- (void)handleTask:(NSURLSessionTask *)task completedWithError:(NSError *)error {
+ [self handleTaskDescription:[task taskDescription] completedWithError:error];
+}
+
+- (void)handleTaskDescription:(NSString *)taskDescription completedWithError:(NSError *)error {
+ NSString *path = [self absolutePathForRelativeTaskPath:taskDescription];
+
+ [[self delegate] networkClient:self didFinishUploadWithPath:path error:error];
+}
+
+#pragma mark - NSURLSessionDelegate
+- (void)URLSession:(NSURLSession *)session didBecomeInvalidWithError:(NSError *)error {
+ FIRCLSDeveloperLog("Crashlytics:Crash:Client", @"session became invalid: %@", error);
+}
+
+// Careful! Not implementing this method appears to cause a crash when using a background task
+- (void)URLSession:(NSURLSession *)session
+ task:(NSURLSessionTask *)task
+ didCompleteWithError:(NSError *)error {
+ [FIRCLSNetworkResponseHandler handleCompletedResponse:task.response
+ forOriginalRequest:task.originalRequest
+ error:error
+ block:^(BOOL restart, NSError *taskError) {
+ if (restart) {
+ [self restartTask:task];
+ return;
+ }
+
+ [self handleTask:task
+ completedWithError:taskError];
+ }];
+}
+
+@end
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSReportManager.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSReportManager.h
new file mode 100644
index 000000000..02b7031a5
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSReportManager.h
@@ -0,0 +1,57 @@
+// Copyright 2019 Google
+//
+// 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
+
+#include "FIRCLSApplicationIdentifierModel.h"
+#include "FIRCLSProfiling.h"
+#include "FIRCrashlytics.h"
+
+@class FBLPromise;
+
+NS_ASSUME_NONNULL_BEGIN
+
+@class FIRCLSDataCollectionArbiter;
+@class FIRCLSFileManager;
+@class FIRCLSInternalReport;
+@class FIRCLSSettings;
+@class GDTCORTransport;
+@class FIRInstallations;
+@protocol FIRAnalyticsInterop;
+
+@interface FIRCLSReportManager : NSObject
+
+- (instancetype)initWithFileManager:(FIRCLSFileManager *)fileManager
+ installations:(FIRInstallations *)installations
+ analytics:(nullable id)analytics
+ googleAppID:(NSString *)googleAppID
+ dataArbiter:(FIRCLSDataCollectionArbiter *)dataArbiter
+ googleTransport:(GDTCORTransport *)googleTransport
+ appIDModel:(FIRCLSApplicationIdentifierModel *)appIDModel
+ settings:(FIRCLSSettings *)settings NS_DESIGNATED_INITIALIZER;
+- (instancetype)init NS_UNAVAILABLE;
++ (instancetype)new NS_UNAVAILABLE;
+
+- (FBLPromise *)startWithProfilingMark:(FIRCLSProfileMark)mark;
+
+- (FBLPromise *)checkForUnsentReports;
+- (FBLPromise *)sendUnsentReports;
+- (FBLPromise *)deleteUnsentReports;
+
+@end
+
+extern NSString *const FIRCLSConfigSubmitReportsKey;
+extern NSString *const FIRCLSConfigPackageReportsKey;
+
+NS_ASSUME_NONNULL_END
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSReportManager.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSReportManager.m
new file mode 100644
index 000000000..cf04b3f1f
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSReportManager.m
@@ -0,0 +1,909 @@
+// Copyright 2019 Google
+//
+// 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.
+
+//
+// The report manager has the ability to send to two different endpoints.
+//
+// The old legacy flow for a report goes through the following states/folders:
+// 1. active - .clsrecords optimized for crash time persistence
+// 2. processing - .clsrecords with attempted symbolication
+// 3. prepared-legacy - .multipartmime of compressed .clsrecords
+//
+// The new flow for a report goes through the following states/folders:
+// 1. active - .clsrecords optimized for crash time persistence
+// 2. processing - .clsrecords with attempted symbolication
+// 3. prepared - .clsrecords moved from processing with no changes
+//
+// The code was designed so the report processing workflows are not dramatically different from one
+// another. The design will help avoid having a lot of conditional code blocks throughout the
+// codebase.
+//
+
+#include
+
+#if __has_include()
+#import
+#else
+#import "FBLPromises.h"
+#endif
+
+#import "FIRCLSApplication.h"
+#import "FIRCLSDataCollectionArbiter.h"
+#import "FIRCLSDataCollectionToken.h"
+#import "FIRCLSDefines.h"
+#import "FIRCLSFeatures.h"
+#import "FIRCLSFileManager.h"
+#import "FIRCLSInternalReport.h"
+#import "FIRCLSLogger.h"
+#import "FIRCLSNetworkClient.h"
+#import "FIRCLSPackageReportOperation.h"
+#import "FIRCLSProcessReportOperation.h"
+#import "FIRCLSReportUploader.h"
+#import "FIRCLSSettings.h"
+#import "FIRCLSSymbolResolver.h"
+#import "FIRCLSUserLogging.h"
+
+#include "FIRCLSGlobals.h"
+#include "FIRCLSUtility.h"
+
+#import "FIRCLSConstants.h"
+#import "FIRCLSExecutionIdentifierModel.h"
+#import "FIRCLSInstallIdentifierModel.h"
+#import "FIRCLSSettingsOnboardingManager.h"
+
+#import "FIRCLSReportManager_Private.h"
+
+#import "Interop/Analytics/Public/FIRAnalyticsInterop.h"
+#import "Interop/Analytics/Public/FIRAnalyticsInteropListener.h"
+
+#include "FIRAEvent+Internal.h"
+#include "FIRCLSFCRAnalytics.h"
+
+#if TARGET_OS_IPHONE
+#import
+#else
+#import
+#endif
+
+static NSTimeInterval const CLSReportRetryInterval = 10 * 60;
+
+static NSString *FIRCLSFirebaseAnalyticsEventLogFormat = @"$A$:%@";
+
+@interface FIRCLSAnalyticsInteropListener : NSObject {
+}
+@end
+
+@implementation FIRCLSAnalyticsInteropListener
+
+- (void)messageTriggered:(NSString *)name parameters:(NSDictionary *)parameters {
+ NSDictionary *event = @{
+ @"name" : name,
+ @"parameters" : parameters,
+ };
+ NSString *json = FIRCLSFIRAEventDictionaryToJSON(event);
+ if (json != nil) {
+ FIRCLSLog(FIRCLSFirebaseAnalyticsEventLogFormat, json);
+ }
+}
+
+@end
+
+/**
+ * A FIRReportAction is used to indicate how to handle unsent reports.
+ */
+typedef NS_ENUM(NSInteger, FIRCLSReportAction) {
+ /** Upload the reports to Crashlytics. */
+ FIRCLSReportActionSend,
+ /** Delete the reports without uploading them. */
+ FIRCLSReportActionDelete,
+};
+
+/**
+ * This is just a helper to make code using FIRReportAction more readable.
+ */
+typedef NSNumber FIRCLSWrappedReportAction;
+@implementation NSNumber (FIRCLSWrappedReportAction)
+- (FIRCLSReportAction)reportActionValue {
+ return [self intValue];
+}
+@end
+
+/**
+ * This is a helper to make code using NSNumber for bools more readable.
+ */
+typedef NSNumber FIRCLSWrappedBool;
+
+@interface FIRCLSReportManager () {
+ FIRCLSFileManager *_fileManager;
+ FIRCLSNetworkClient *_networkClient;
+ FIRCLSReportUploader *_uploader;
+ dispatch_queue_t _dispatchQueue;
+ NSOperationQueue *_operationQueue;
+ id _analytics;
+
+ // A promise that will be resolved when unsent reports are found on the device, and
+ // processReports: can be called to decide how to deal with them.
+ FBLPromise *_unsentReportsAvailable;
+
+ // A promise that will be resolved when the user has provided an action that they want to perform
+ // for all the unsent reports.
+ FBLPromise *_reportActionProvided;
+
+ // A promise that will be resolved when all unsent reports have been "handled". They won't
+ // necessarily have been uploaded, but we will know whether they should be sent or deleted, and
+ // the initial work to make that happen will have been processed on the work queue.
+ //
+ // Currently only used for testing
+ FBLPromise *_unsentReportsHandled;
+
+ // A token to make sure that checkForUnsentReports only gets called once.
+ atomic_bool _checkForUnsentReportsCalled;
+
+ BOOL _registeredAnalyticsEventListener;
+}
+
+@property(nonatomic, readonly) NSString *googleAppID;
+
+@property(nonatomic, strong) FIRCLSDataCollectionArbiter *dataArbiter;
+
+// Uniquely identifies a build / binary of the app
+@property(nonatomic, strong) FIRCLSApplicationIdentifierModel *appIDModel;
+
+// Uniquely identifies an install of the app
+@property(nonatomic, strong) FIRCLSInstallIdentifierModel *installIDModel;
+
+// Uniquely identifies a run of the app
+@property(nonatomic, strong) FIRCLSExecutionIdentifierModel *executionIDModel;
+
+// Settings fetched from the server
+@property(nonatomic, strong) FIRCLSSettings *settings;
+
+// Runs the operations that fetch settings and call onboarding endpoints
+@property(nonatomic, strong) FIRCLSSettingsOnboardingManager *settingsAndOnboardingManager;
+
+@property(nonatomic, strong) GDTCORTransport *googleTransport;
+
+@end
+
+@implementation FIRCLSReportManager
+
+// Used only for internal data collection E2E testing
+static void (^reportSentCallback)(void);
+
+- (instancetype)initWithFileManager:(FIRCLSFileManager *)fileManager
+ installations:(FIRInstallations *)installations
+ analytics:(id)analytics
+ googleAppID:(NSString *)googleAppID
+ dataArbiter:(FIRCLSDataCollectionArbiter *)dataArbiter
+ googleTransport:(GDTCORTransport *)googleTransport
+ appIDModel:(FIRCLSApplicationIdentifierModel *)appIDModel
+ settings:(FIRCLSSettings *)settings {
+ self = [super init];
+ if (!self) {
+ return nil;
+ }
+
+ _fileManager = fileManager;
+ _analytics = analytics;
+ _googleAppID = [googleAppID copy];
+ _dataArbiter = dataArbiter;
+
+ _googleTransport = googleTransport;
+
+ NSString *sdkBundleID = FIRCLSApplicationGetSDKBundleID();
+
+ _operationQueue = [NSOperationQueue new];
+ [_operationQueue setMaxConcurrentOperationCount:1];
+ [_operationQueue setName:[sdkBundleID stringByAppendingString:@".work-queue"]];
+
+ _dispatchQueue = dispatch_queue_create("com.google.firebase.crashlytics.startup", 0);
+ _operationQueue.underlyingQueue = _dispatchQueue;
+
+ _networkClient = [self clientWithOperationQueue:_operationQueue];
+
+ _unsentReportsAvailable = [FBLPromise pendingPromise];
+ _reportActionProvided = [FBLPromise pendingPromise];
+ _unsentReportsHandled = [FBLPromise pendingPromise];
+
+ _checkForUnsentReportsCalled = NO;
+
+ _installIDModel = [[FIRCLSInstallIdentifierModel alloc] initWithInstallations:installations];
+ _executionIDModel = [[FIRCLSExecutionIdentifierModel alloc] init];
+
+ _settings = settings;
+ _appIDModel = appIDModel;
+
+ _settingsAndOnboardingManager =
+ [[FIRCLSSettingsOnboardingManager alloc] initWithAppIDModel:appIDModel
+ installIDModel:self.installIDModel
+ settings:self.settings
+ fileManager:self.fileManager
+ googleAppID:self.googleAppID];
+
+ return self;
+}
+
+- (FIRCLSNetworkClient *)clientWithOperationQueue:(NSOperationQueue *)queue {
+ return [[FIRCLSNetworkClient alloc] initWithQueue:queue fileManager:_fileManager delegate:self];
+}
+
+/**
+ * Returns the number of unsent reports on the device, including the ones passed in.
+ */
+- (int)unsentReportsCountWithPreexisting:(NSArray *)paths {
+ int count = [self countSubmittableAndDeleteUnsubmittableReportPaths:paths];
+
+ count += _fileManager.processingPathContents.count;
+
+ if (self.settings.shouldUseNewReportEndpoint) {
+ count += _fileManager.preparedPathContents.count;
+ } else {
+ count += _fileManager.legacyPreparedPathContents.count;
+ }
+ return count;
+}
+
+// This method returns a promise that is resolved with a wrapped FIRReportAction once the user has
+// indicated whether they want to upload currently cached reports.
+// This method should only be called when we have determined there is at least 1 unsent report.
+// This method waits until either:
+// 1. Data collection becomes enabled, in which case, the promise will be resolved with Send.
+// 2. The developer uses the processCrashReports API to indicate whether the report
+// should be sent or deleted, at which point the promise will be resolved with the action.
+- (FBLPromise *)waitForReportAction {
+ FIRCLSDebugLog(@"[Crashlytics:Crash] Notifying that unsent reports are available.");
+ [_unsentReportsAvailable fulfill:@YES];
+
+ // If data collection gets enabled while we are waiting for an action, go ahead and send the
+ // reports, and any subsequent explicit response will be ignored.
+ FBLPromise *collectionEnabled =
+ [[self.dataArbiter waitForCrashlyticsCollectionEnabled]
+ then:^id _Nullable(NSNumber *_Nullable value) {
+ return @(FIRCLSReportActionSend);
+ }];
+
+ FIRCLSDebugLog(@"[Crashlytics:Crash] Waiting for send/deleteUnsentReports to be called.");
+ // Wait for either the processReports callback to be called, or data collection to be enabled.
+ return [FBLPromise race:@[ collectionEnabled, _reportActionProvided ]];
+}
+
+- (FBLPromise *)checkForUnsentReports {
+ bool expectedCalled = NO;
+ if (!atomic_compare_exchange_strong(&_checkForUnsentReportsCalled, &expectedCalled, YES)) {
+ FIRCLSErrorLog(@"checkForUnsentReports should only be called once per execution.");
+ return [FBLPromise resolvedWith:@NO];
+ }
+ return _unsentReportsAvailable;
+}
+
+- (FBLPromise *)sendUnsentReports {
+ [_reportActionProvided fulfill:@(FIRCLSReportActionSend)];
+ return _unsentReportsHandled;
+}
+
+- (FBLPromise *)deleteUnsentReports {
+ [_reportActionProvided fulfill:@(FIRCLSReportActionDelete)];
+ return _unsentReportsHandled;
+}
+
+- (FBLPromise *)startWithProfilingMark:(FIRCLSProfileMark)mark {
+ NSString *executionIdentifier = self.executionIDModel.executionID;
+
+ // This needs to be called before any values are read from settings
+ NSTimeInterval currentTimestamp = [NSDate timeIntervalSinceReferenceDate];
+ [self.settings reloadFromCacheWithGoogleAppID:self.googleAppID currentTimestamp:currentTimestamp];
+
+ if (![self validateAppIdentifiers]) {
+ return [FBLPromise resolvedWith:@NO];
+ }
+
+#if DEBUG
+ FIRCLSDebugLog(@"Root: %@", [_fileManager rootPath]);
+#endif
+
+ if ([self.dataArbiter isLegacyDataCollectionKeyInPlist]) {
+ FIRCLSErrorLog(@"Found legacy data collection key in app's Info.plist: "
+ @"firebase_crashlytics_collection_enabled");
+ FIRCLSErrorLog(@"Please update your Info.plist to use the new data collection key: "
+ @"FirebaseCrashlyticsCollectionEnabled");
+ FIRCLSErrorLog(@"The legacy data collection Info.plist value could be overridden by "
+ @"calling: [Fabric with:...]");
+ FIRCLSErrorLog(@"The new value can be overridden by calling: [[FIRCrashlytics "
+ @"crashlytics] setCrashlyticsCollectionEnabled:]");
+
+ return [FBLPromise resolvedWith:@NO];
+ }
+
+ if (![_fileManager createReportDirectories]) {
+ return [FBLPromise resolvedWith:@NO];
+ }
+
+ // Grab existing reports
+ BOOL launchFailure = [self checkForAndCreateLaunchMarker];
+ NSArray *preexistingReportPaths = _fileManager.activePathContents;
+
+ FIRCLSInternalReport *report = [self setupCurrentReport:executionIdentifier];
+ if (!report) {
+ FIRCLSErrorLog(@"Unable to setup a new report");
+ }
+
+ if (![self startCrashReporterWithProfilingMark:mark report:report]) {
+ FIRCLSErrorLog(@"Unable to start crash reporter");
+ report = nil;
+ }
+
+ // Regenerate the Install ID on a background thread if it needs to rotate because
+ // fetching the Firebase Install ID can be slow on some devices. This should happen after we
+ // create the session on disk so that we can update the Install ID in the written crash report
+ // metadata.
+ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
+ [self checkAndRotateInstallUUIDIfNeededWithReport:report];
+ });
+
+ FBLPromise *promise = [FBLPromise resolvedWith:@(report != nil)];
+
+ if ([self.dataArbiter isCrashlyticsCollectionEnabled]) {
+ FIRCLSDebugLog(@"Automatic data collection is enabled.");
+ FIRCLSDebugLog(@"Unsent reports will be uploaded at startup");
+ FIRCLSDataCollectionToken *dataCollectionToken = [FIRCLSDataCollectionToken validToken];
+
+ [self beginSettingsAndOnboardingWithToken:dataCollectionToken waitForSettingsRequest:NO];
+
+ [self beginReportUploadsWithToken:dataCollectionToken
+ preexistingReportPaths:preexistingReportPaths
+ blockingSend:launchFailure
+ report:report];
+
+ // If data collection is enabled, the SDK will not notify the user
+ // when unsent reports are available, or respect Send / DeleteUnsentReports
+ [_unsentReportsAvailable fulfill:@NO];
+
+ } else {
+ FIRCLSDebugLog(@"Automatic data collection is disabled.");
+
+ // TODO: This counting of the file system happens on the main thread. Now that some of the other
+ // work below has been made async and moved to the dispatch queue, maybe we can move this code
+ // to the dispatch queue as well.
+ int unsentReportsCount = [self unsentReportsCountWithPreexisting:preexistingReportPaths];
+ if (unsentReportsCount > 0) {
+ FIRCLSDebugLog(
+ @"[Crashlytics:Crash] %d unsent reports are available. Checking for upload permission.",
+ unsentReportsCount);
+ // Wait for an action to get sent, either from processReports: or automatic data collection.
+ promise = [[self waitForReportAction]
+ onQueue:_dispatchQueue
+ then:^id _Nullable(FIRCLSWrappedReportAction *_Nullable wrappedAction) {
+ // Process the actions for the reports on disk.
+ FIRCLSReportAction action = [wrappedAction reportActionValue];
+ if (action == FIRCLSReportActionSend) {
+ FIRCLSDebugLog(@"Sending unsent reports.");
+ FIRCLSDataCollectionToken *dataCollectionToken =
+ [FIRCLSDataCollectionToken validToken];
+
+ // For the new report endpoint, the orgID is not needed.
+ // For the legacy report endpoint, wait on settings if orgID is not available.
+ BOOL waitForSetting =
+ !self.settings.shouldUseNewReportEndpoint && !self.settings.orgID;
+
+ [self beginSettingsAndOnboardingWithToken:dataCollectionToken
+ waitForSettingsRequest:waitForSetting];
+
+ [self beginReportUploadsWithToken:dataCollectionToken
+ preexistingReportPaths:preexistingReportPaths
+ blockingSend:NO
+ report:report];
+
+ } else if (action == FIRCLSReportActionDelete) {
+ FIRCLSDebugLog(@"Deleting unsent reports.");
+ [self deleteUnsentReportsWithPreexisting:preexistingReportPaths];
+ } else {
+ FIRCLSErrorLog(@"Unknown report action: %d", action);
+ }
+ return @(report != nil);
+ }];
+ } else {
+ FIRCLSDebugLog(@"[Crashlytics:Crash] There are no unsent reports.");
+ [_unsentReportsAvailable fulfill:@NO];
+ }
+ }
+
+ if (report != nil) {
+ // capture the start-up time here, but record it asynchronously
+ double endMark = FIRCLSProfileEnd(mark);
+
+ dispatch_async(FIRCLSGetLoggingQueue(), ^{
+ FIRCLSUserLoggingWriteInternalKeyValue(FIRCLSStartTimeKey, [@(endMark) description]);
+ });
+ }
+
+ // To make the code more predictable and therefore testable, don't resolve the startup promise
+ // until the operations that got queued up for processing reports have been processed through the
+ // work queue.
+ NSOperationQueue *__weak queue = _operationQueue;
+ FBLPromise *__weak unsentReportsHandled = _unsentReportsHandled;
+ promise = [promise then:^id _Nullable(NSNumber *_Nullable value) {
+ [queue waitUntilAllOperationsAreFinished];
+ // Signal that to callers of processReports that everything is finished.
+ [unsentReportsHandled fulfill:nil];
+ return value;
+ }];
+
+ return promise;
+}
+
+- (void)checkAndRotateInstallUUIDIfNeededWithReport:(FIRCLSInternalReport *)report {
+ [self.installIDModel regenerateInstallIDIfNeededWithBlock:^(BOOL didRotate) {
+ if (!didRotate) {
+ return;
+ }
+
+ FIRCLSContextUpdateMetadata(report, self.settings, self.installIDModel, self->_fileManager);
+ }];
+}
+
+- (void)beginSettingsAndOnboardingWithToken:(FIRCLSDataCollectionToken *)token
+ waitForSettingsRequest:(BOOL)waitForSettings {
+ if (self.settings.isCacheExpired) {
+ // This method can be called more than once if the user calls
+ // SendUnsentReports again, so don't repeat the settings fetch
+ static dispatch_once_t settingsFetchOnceToken;
+ dispatch_once(&settingsFetchOnceToken, ^{
+ [self.settingsAndOnboardingManager beginSettingsAndOnboardingWithGoogleAppId:self.googleAppID
+ token:token
+ waitForCompletion:waitForSettings];
+ });
+ }
+}
+
+- (void)beginReportUploadsWithToken:(FIRCLSDataCollectionToken *)token
+ preexistingReportPaths:(NSArray *)preexistingReportPaths
+ blockingSend:(BOOL)blockingSend
+ report:(FIRCLSInternalReport *)report {
+ if (self.settings.collectReportsEnabled) {
+ [self processExistingReportPaths:preexistingReportPaths
+ dataCollectionToken:token
+ asUrgent:blockingSend];
+ [self handleContentsInOtherReportingDirectoriesWithToken:token];
+
+ } else {
+ FIRCLSInfoLog(@"Collect crash reports is disabled");
+ [self deleteUnsentReportsWithPreexisting:preexistingReportPaths];
+ }
+}
+
+- (BOOL)startCrashReporterWithProfilingMark:(FIRCLSProfileMark)mark
+ report:(FIRCLSInternalReport *)report {
+ if (!report) {
+ return NO;
+ }
+
+ if (!FIRCLSContextInitialize(report, self.settings, self.installIDModel, _fileManager)) {
+ return NO;
+ }
+
+ [self setupStateNotifications];
+
+ [self registerAnalyticsEventListener];
+
+ [self crashReportingSetupCompleted:mark];
+
+ return YES;
+}
+
+- (void)crashReportingSetupCompleted:(FIRCLSProfileMark)mark {
+ // check our handlers
+ FIRCLSDispatchAfter(2.0, dispatch_get_main_queue(), ^{
+ FIRCLSExceptionCheckHandlers((__bridge void *)(self));
+ FIRCLSSignalCheckHandlers();
+#if CLS_MACH_EXCEPTION_SUPPORTED
+ FIRCLSMachExceptionCheckHandlers();
+#endif
+ });
+
+ // remove the launch failure marker and record the startup time
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [self removeLaunchFailureMarker];
+ dispatch_async(FIRCLSGetLoggingQueue(), ^{
+ FIRCLSUserLoggingWriteInternalKeyValue(FIRCLSFirstRunloopTurnTimeKey,
+ [@(FIRCLSProfileEnd(mark)) description]);
+ });
+ });
+}
+
+- (BOOL)validateAppIdentifiers {
+ // When the ApplicationIdentifierModel fails to initialize, it is usually due to
+ // failing computeExecutableInfo. This can happen if the user sets the
+ // Exported Symbols File in Build Settings, and leaves off the one symbol
+ // that Crashlytics needs, "__mh_execute_header" (wich is defined in mach-o/ldsyms.h as
+ // _MH_EXECUTE_SYM). From https://github.com/firebase/firebase-ios-sdk/issues/5020
+ if (!self.appIDModel) {
+ FIRCLSErrorLog(
+ @"Crashlytics could not find the symbol for the app's main function and cannot "
+ @"start up. This can happen when Exported Symbols File is set in Build Settings. To "
+ @"resolve this, add \"__mh_execute_header\" as a newline to your Exported Symbols File.");
+ return NO;
+ }
+
+ if (self.appIDModel.bundleID.length == 0) {
+ FIRCLSErrorLog(@"An application must have a valid bundle identifier in its Info.plist");
+ return NO;
+ }
+
+ return YES;
+}
+
+- (FIRCLSReportUploader *)uploader {
+ if (!_uploader) {
+ _uploader = [[FIRCLSReportUploader alloc] initWithQueue:self.operationQueue
+ delegate:self
+ dataSource:self
+ client:self.networkClient
+ fileManager:_fileManager
+ analytics:_analytics];
+ }
+
+ return _uploader;
+}
+
+#pragma mark - Reporting Lifecycle
+
+- (FIRCLSInternalReport *)setupCurrentReport:(NSString *)executionIdentifier {
+ [self createLaunchFailureMarker];
+
+ NSString *reportPath = [_fileManager setupNewPathForExecutionIdentifier:executionIdentifier];
+
+ return [[FIRCLSInternalReport alloc] initWithPath:reportPath
+ executionIdentifier:executionIdentifier];
+}
+
+- (int)countSubmittableAndDeleteUnsubmittableReportPaths:(NSArray *)reportPaths {
+ int count = 0;
+ for (NSString *path in reportPaths) {
+ FIRCLSInternalReport *report = [FIRCLSInternalReport reportWithPath:path];
+ if ([report needsToBeSubmitted]) {
+ count++;
+ } else {
+ [self.operationQueue addOperationWithBlock:^{
+ [self->_fileManager removeItemAtPath:path];
+ }];
+ }
+ }
+ return count;
+}
+
+- (void)processExistingReportPaths:(NSArray *)reportPaths
+ dataCollectionToken:(FIRCLSDataCollectionToken *)dataCollectionToken
+ asUrgent:(BOOL)urgent {
+ for (NSString *path in reportPaths) {
+ [self processExistingActiveReportPath:path
+ dataCollectionToken:dataCollectionToken
+ asUrgent:urgent];
+ }
+}
+
+- (void)processExistingActiveReportPath:(NSString *)path
+ dataCollectionToken:(FIRCLSDataCollectionToken *)dataCollectionToken
+ asUrgent:(BOOL)urgent {
+ FIRCLSInternalReport *report = [FIRCLSInternalReport reportWithPath:path];
+
+ // TODO: needsToBeSubmitted should really be called on the background queue.
+ if (![report needsToBeSubmitted]) {
+ [self.operationQueue addOperationWithBlock:^{
+ [self->_fileManager removeItemAtPath:path];
+ }];
+
+ return;
+ }
+
+ if (urgent && [dataCollectionToken isValid]) {
+ // We can proceed without the delegate.
+ [[self uploader] prepareAndSubmitReport:report
+ dataCollectionToken:dataCollectionToken
+ asUrgent:urgent
+ withProcessing:YES];
+ return;
+ }
+
+ [self submitReport:report dataCollectionToken:dataCollectionToken];
+}
+
+- (void)submitReport:(FIRCLSInternalReport *)report
+ dataCollectionToken:(FIRCLSDataCollectionToken *)dataCollectionToken {
+ [self.operationQueue addOperationWithBlock:^{
+ [[self uploader] prepareAndSubmitReport:report
+ dataCollectionToken:dataCollectionToken
+ asUrgent:NO
+ withProcessing:YES];
+ }];
+
+ [self didSubmitReport];
+}
+
+// This is the side-effect of calling deleteUnsentReports, or collect_reports setting
+// being false
+- (void)deleteUnsentReportsWithPreexisting:(NSArray *)preexistingReportPaths {
+ [self removeExistingReportPaths:preexistingReportPaths];
+
+ [self removeExistingReportPaths:self.fileManager.processingPathContents];
+ if (self.settings.shouldUseNewReportEndpoint) {
+ [self removeExistingReportPaths:self.fileManager.preparedPathContents];
+ } else {
+ [self removeExistingReportPaths:self.fileManager.legacyPreparedPathContents];
+ }
+}
+
+- (void)removeExistingReportPaths:(NSArray *)reportPaths {
+ [self.operationQueue addOperationWithBlock:^{
+ for (NSString *path in reportPaths) {
+ [self.fileManager removeItemAtPath:path];
+ }
+ }];
+}
+
+- (void)handleContentsInOtherReportingDirectoriesWithToken:(FIRCLSDataCollectionToken *)token {
+ [self handleExistingFilesInProcessingWithToken:token];
+ [self handleExistingFilesInPreparedWithToken:token];
+}
+
+- (void)handleExistingFilesInProcessingWithToken:(FIRCLSDataCollectionToken *)token {
+ NSArray *processingPaths = _fileManager.processingPathContents;
+
+ // deal with stuff in processing more carefully - do not process again
+ [self.operationQueue addOperationWithBlock:^{
+ for (NSString *path in processingPaths) {
+ FIRCLSInternalReport *report = [FIRCLSInternalReport reportWithPath:path];
+ [[self uploader] prepareAndSubmitReport:report
+ dataCollectionToken:token
+ asUrgent:NO
+ withProcessing:NO];
+ }
+ }];
+}
+
+- (void)handleExistingFilesInPreparedWithToken:(FIRCLSDataCollectionToken *)token {
+ NSArray *preparedPaths = self.settings.shouldUseNewReportEndpoint
+ ? _fileManager.preparedPathContents
+ : _fileManager.legacyPreparedPathContents;
+
+ // Give our network client a chance to reconnect here, if needed. This attempts to avoid
+ // trying to re-submit a prepared file that is already in flight.
+ [self.networkClient attemptToReconnectBackgroundSessionWithCompletionBlock:^{
+ [self.operationQueue addOperationWithBlock:^{
+ [self uploadPreexistingFiles:preparedPaths withToken:token];
+ }];
+ }];
+}
+
+- (void)uploadPreexistingFiles:(NSArray *)files withToken:(FIRCLSDataCollectionToken *)token {
+ // Because this could happen quite a bit after the inital set of files was
+ // captured, some could be completed (deleted). So, just double-check to make sure
+ // the file still exists.
+
+ for (NSString *path in files) {
+ if (![[_fileManager underlyingFileManager] fileExistsAtPath:path]) {
+ continue;
+ }
+
+ [[self uploader] uploadPackagedReportAtPath:path dataCollectionToken:token asUrgent:NO];
+ }
+}
+
+- (void)retryUploadForReportAtPath:(NSString *)path
+ dataCollectionToken:(FIRCLSDataCollectionToken *)token {
+ FIRCLSAddOperationAfter(CLSReportRetryInterval, self.operationQueue, ^{
+ FIRCLSDeveloperLog("Crashlytics:Crash", @"re-attempting report submission");
+ [[self uploader] uploadPackagedReportAtPath:path dataCollectionToken:token asUrgent:NO];
+ });
+}
+
+#pragma mark - Launch Failure Detection
+- (NSString *)launchFailureMarkerPath {
+ return [[_fileManager structurePath] stringByAppendingPathComponent:@"launchmarker"];
+}
+
+- (BOOL)createLaunchFailureMarker {
+ // It's tempting to use - [NSFileManger createFileAtPath:contents:attributes:] here. But that
+ // operation, even with empty/nil contents does a ton of work to write out nothing via a
+ // temporarly file. This is a much faster implemenation.
+ const char *path = [[self launchFailureMarkerPath] fileSystemRepresentation];
+
+#if TARGET_OS_IPHONE
+ /*
+ * data-protected non-portable open(2) :
+ * int open_dprotected_np(user_addr_t path, int flags, int class, int dpflags, int mode)
+ */
+ int fd = open_dprotected_np(path, O_WRONLY | O_CREAT | O_TRUNC, 4, 0, 0644);
+#else
+ int fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
+#endif
+ if (fd == -1) {
+ return NO;
+ }
+
+ return close(fd) == 0;
+}
+
+- (BOOL)launchFailureMarkerPresent {
+ return [[_fileManager underlyingFileManager] fileExistsAtPath:[self launchFailureMarkerPath]];
+}
+
+- (BOOL)removeLaunchFailureMarker {
+ return [_fileManager removeItemAtPath:[self launchFailureMarkerPath]];
+}
+
+- (BOOL)checkForAndCreateLaunchMarker {
+ BOOL launchFailure = [self launchFailureMarkerPresent];
+ if (launchFailure) {
+ FIRCLSDeveloperLog("Crashlytics:Crash",
+ @"Last launch failed: this may indicate a crash shortly after app launch.");
+ } else {
+ [self createLaunchFailureMarker];
+ }
+
+ return launchFailure;
+}
+
+#pragma mark -
+
+- (void)registerAnalyticsEventListener {
+ if (_registeredAnalyticsEventListener) {
+ return;
+ }
+ FIRCLSAnalyticsInteropListener *listener = [[FIRCLSAnalyticsInteropListener alloc] init];
+ [FIRCLSFCRAnalytics registerEventListener:listener toAnalytics:_analytics];
+ _registeredAnalyticsEventListener = YES;
+}
+
+#pragma mark - Notifications
+- (void)setupStateNotifications {
+ [self captureInitialNotificationStates];
+
+#if TARGET_OS_IOS
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(willBecomeActive:)
+ name:UIApplicationWillEnterForegroundNotification
+ object:nil];
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(didBecomeInactive:)
+ name:UIApplicationDidEnterBackgroundNotification
+ object:nil];
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(didChangeOrientation:)
+ name:UIDeviceOrientationDidChangeNotification
+ object:nil];
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+ [[NSNotificationCenter defaultCenter]
+ addObserver:self
+ selector:@selector(didChangeUIOrientation:)
+ name:UIApplicationDidChangeStatusBarOrientationNotification
+ object:nil];
+#pragma clang diagnostic pop
+
+#elif CLS_TARGET_OS_OSX
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(willBecomeActive:)
+ name:@"NSApplicationWillBecomeActiveNotification"
+ object:nil];
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(didBecomeInactive:)
+ name:@"NSApplicationDidResignActiveNotification"
+ object:nil];
+#endif
+}
+
+- (void)captureInitialNotificationStates {
+#if TARGET_OS_IOS
+ UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
+ UIInterfaceOrientation statusBarOrientation =
+ [FIRCLSApplicationSharedInstance() statusBarOrientation];
+#endif
+
+ // It's nice to do this async, so we don't hold up the main thread while doing three
+ // consecutive IOs here.
+ dispatch_async(FIRCLSGetLoggingQueue(), ^{
+ FIRCLSUserLoggingWriteInternalKeyValue(FIRCLSInBackgroundKey, @"0");
+#if TARGET_OS_IOS
+ FIRCLSUserLoggingWriteInternalKeyValue(FIRCLSDeviceOrientationKey,
+ [@(orientation) description]);
+ FIRCLSUserLoggingWriteInternalKeyValue(FIRCLSUIOrientationKey,
+ [@(statusBarOrientation) description]);
+#endif
+ });
+}
+
+- (void)willBecomeActive:(NSNotification *)notification {
+ FIRCLSUserLoggingRecordInternalKeyValue(FIRCLSInBackgroundKey, @NO);
+}
+
+- (void)didBecomeInactive:(NSNotification *)notification {
+ FIRCLSUserLoggingRecordInternalKeyValue(FIRCLSInBackgroundKey, @YES);
+}
+
+#if TARGET_OS_IOS
+- (void)didChangeOrientation:(NSNotification *)notification {
+ UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
+
+ FIRCLSUserLoggingRecordInternalKeyValue(FIRCLSDeviceOrientationKey, @(orientation));
+}
+
+- (void)didChangeUIOrientation:(NSNotification *)notification {
+ UIInterfaceOrientation statusBarOrientation =
+ [FIRCLSApplicationSharedInstance() statusBarOrientation];
+
+ FIRCLSUserLoggingRecordInternalKeyValue(FIRCLSUIOrientationKey, @(statusBarOrientation));
+}
+#endif
+
+#pragma mark - FIRCLSNetworkClientDelegate
+- (BOOL)networkClientCanUseBackgroundSessions:(FIRCLSNetworkClient *)client {
+ return !FIRCLSApplicationIsExtension();
+}
+
+- (void)networkClient:(FIRCLSNetworkClient *)client
+ didFinishUploadWithPath:(NSString *)path
+ error:(NSError *)error {
+ // Route this through to the reports uploader.
+ // Since this callback happens after an upload finished, then we can assume that the original data
+ // collection was authorized. This isn't ideal, but it's better than trying to plumb the data
+ // collection token through all the system networking callbacks.
+ FIRCLSDataCollectionToken *token = [FIRCLSDataCollectionToken validToken];
+ [[self uploader] reportUploadAtPath:path dataCollectionToken:token completedWithError:error];
+}
+
+#pragma mark - FIRCLSReportUploaderDelegate
+
+- (void)didCompletePackageSubmission:(NSString *)path
+ dataCollectionToken:(FIRCLSDataCollectionToken *)token
+ error:(NSError *)error {
+ if (!error) {
+ FIRCLSDeveloperLog("Crashlytics:Crash", @"report submission successful");
+ return;
+ }
+
+ FIRCLSDeveloperLog("Crashlytics:Crash", @"report submission failed with error %@", error);
+ FIRCLSSDKLog("Error: failed to submit report '%s'\n", error.description.UTF8String);
+
+ [self retryUploadForReportAtPath:path dataCollectionToken:token];
+}
+
+- (void)didCompleteAllSubmissions {
+ [self.operationQueue addOperationWithBlock:^{
+ // Dealloc the reports uploader. If we need it again (if we re-enqueued submissions from
+ // didCompletePackageSubmission:, we can just create it again
+ self->_uploader = nil;
+
+ FIRCLSDeveloperLog("Crashlytics:Crash", @"report submission complete");
+ }];
+}
+
+#pragma mark - UITest Helpers
+
+// Used only for internal data collection E2E testing
+- (void)didSubmitReport {
+ if (reportSentCallback) {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ reportSentCallback();
+ });
+ }
+}
+
++ (void)setReportSentCallback:(void (^)(void))callback {
+ reportSentCallback = callback;
+}
+
+@end
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSReportManager_Private.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSReportManager_Private.h
new file mode 100644
index 000000000..f7f139740
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSReportManager_Private.h
@@ -0,0 +1,36 @@
+// Copyright 2019 Google
+//
+// 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 "FIRCLSReportManager.h"
+#import "FIRCLSReportUploader.h"
+
+@class FIRCLSInstallIdentifierModel;
+
+@interface FIRCLSReportManager ()
+
+@property(nonatomic, strong) NSOperationQueue *operationQueue;
+@property(nonatomic, strong) FIRCLSNetworkClient *networkClient;
+@property(nonatomic, readonly) FIRCLSReportUploader *uploader;
+@property(nonatomic, strong) FIRCLSFileManager *fileManager;
+
+@end
+
+@interface FIRCLSReportManager (PrivateMethods)
+
+- (BOOL)createLaunchFailureMarker;
+- (BOOL)launchFailureMarkerPresent;
+
+- (BOOL)potentiallySubmittableCrashOccurred;
+
+@end
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSReportUploader.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSReportUploader.h
new file mode 100644
index 000000000..c1cf8b4a1
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSReportUploader.h
@@ -0,0 +1,80 @@
+// Copyright 2019 Google
+//
+// 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
+
+#import
+
+@class FIRCLSDataCollectionToken;
+@class FIRCLSInternalReport;
+@class FIRCLSSettings;
+@class FIRCLSFileManager;
+@class FIRCLSNetworkClient;
+@class FIRCLSReportUploader;
+
+@protocol FIRCLSReportUploaderDelegate;
+@protocol FIRCLSReportUploaderDataSource;
+@protocol FIRAnalyticsInterop;
+
+@interface FIRCLSReportUploader : NSObject
+
+- (instancetype)init NS_UNAVAILABLE;
++ (instancetype)new NS_UNAVAILABLE;
+- (instancetype)initWithQueue:(NSOperationQueue *)queue
+ delegate:(id)delegate
+ dataSource:(id)dataSource
+ client:(FIRCLSNetworkClient *)client
+ fileManager:(FIRCLSFileManager *)fileManager
+ analytics:(id)analytics NS_DESIGNATED_INITIALIZER;
+
+@property(nonatomic, weak) id delegate;
+@property(nonatomic, weak) id dataSource;
+
+@property(nonatomic, readonly) NSOperationQueue *operationQueue;
+@property(nonatomic, readonly) FIRCLSNetworkClient *networkClient;
+@property(nonatomic, readonly) FIRCLSFileManager *fileManager;
+
+- (BOOL)prepareAndSubmitReport:(FIRCLSInternalReport *)report
+ dataCollectionToken:(FIRCLSDataCollectionToken *)dataCollectionToken
+ asUrgent:(BOOL)urgent
+ withProcessing:(BOOL)shouldProcess;
+
+- (BOOL)uploadPackagedReportAtPath:(NSString *)path
+ dataCollectionToken:(FIRCLSDataCollectionToken *)dataCollectionToken
+ asUrgent:(BOOL)urgent;
+
+- (void)reportUploadAtPath:(NSString *)path
+ dataCollectionToken:(FIRCLSDataCollectionToken *)dataCollectionToken
+ completedWithError:(NSError *)error;
+
+@end
+
+@protocol FIRCLSReportUploaderDelegate
+@required
+
+- (void)didCompletePackageSubmission:(NSString *)path
+ dataCollectionToken:(FIRCLSDataCollectionToken *)token
+ error:(NSError *)error;
+- (void)didCompleteAllSubmissions;
+
+@end
+
+@protocol FIRCLSReportUploaderDataSource
+@required
+
+- (NSString *)googleAppID;
+- (FIRCLSSettings *)settings;
+- (GDTCORTransport *)googleTransport;
+
+@end
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSReportUploader.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSReportUploader.m
new file mode 100644
index 000000000..6b8263534
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSReportUploader.m
@@ -0,0 +1,356 @@
+// Copyright 2019 Google
+//
+// 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 "Interop/Analytics/Public/FIRAnalyticsInterop.h"
+
+#import "FIRCLSApplication.h"
+#import "FIRCLSDataCollectionArbiter.h"
+#import "FIRCLSDataCollectionToken.h"
+#import "FIRCLSDefines.h"
+#import "FIRCLSFCRAnalytics.h"
+#import "FIRCLSFileManager.h"
+#import "FIRCLSInstallIdentifierModel.h"
+#import "FIRCLSInternalReport.h"
+#import "FIRCLSNetworkClient.h"
+#import "FIRCLSPackageReportOperation.h"
+#import "FIRCLSProcessReportOperation.h"
+#import "FIRCLSReportAdapter.h"
+#import "FIRCLSReportUploader_Private.h"
+#import "FIRCLSSettings.h"
+#import "FIRCLSSymbolResolver.h"
+
+#include "FIRCLSUtility.h"
+
+#import "FIRCLSConstants.h"
+#import "FIRCLSMultipartMimeStreamEncoder.h"
+#import "FIRCLSURLBuilder.h"
+
+#import
+#import
+
+@interface FIRCLSReportUploader () {
+ id _analytics;
+}
+@end
+
+@implementation FIRCLSReportUploader
+
+- (instancetype)initWithQueue:(NSOperationQueue *)queue
+ delegate:(id)delegate
+ dataSource:(id)dataSource
+ client:(FIRCLSNetworkClient *)client
+ fileManager:(FIRCLSFileManager *)fileManager
+ analytics:(id)analytics {
+ self = [super init];
+ if (!self) {
+ return nil;
+ }
+
+ _operationQueue = queue;
+ _delegate = delegate;
+ _dataSource = dataSource;
+ _networkClient = client;
+ _fileManager = fileManager;
+ _analytics = analytics;
+
+ return self;
+}
+
+#pragma mark - Packaging and Submission
+- (BOOL)prepareAndSubmitReport:(FIRCLSInternalReport *)report
+ dataCollectionToken:(FIRCLSDataCollectionToken *)dataCollectionToken
+ asUrgent:(BOOL)urgent
+ withProcessing:(BOOL)shouldProcess {
+ __block BOOL success = NO;
+
+ if (![dataCollectionToken isValid]) {
+ FIRCLSErrorLog(@"Data collection disabled and report will not be submitted");
+ return NO;
+ }
+
+ if (!self.dataSource.settings.orgID && !self.dataSource.settings.shouldUseNewReportEndpoint) {
+ FIRCLSDebugLog(
+ @"Skipping report with id '%@' this run of the app because Organization ID was "
+ @"nil. Report via the legacy endpoint will upload once settings are download successfully",
+ report.identifier);
+ return YES;
+ }
+
+ FIRCLSApplicationActivity(
+ FIRCLSApplicationActivityDefault, @"Crashlytics Crash Report Processing", ^{
+ if (shouldProcess) {
+ if (![self.fileManager moveItemAtPath:report.path
+ toDirectory:self.fileManager.processingPath]) {
+ FIRCLSErrorLog(@"Unable to move report for processing");
+ return;
+ }
+
+ // adjust the report's path, and process it
+ [report setPath:[self.fileManager.processingPath
+ stringByAppendingPathComponent:report.directoryName]];
+
+ FIRCLSSymbolResolver *resolver = [[FIRCLSSymbolResolver alloc] init];
+
+ FIRCLSProcessReportOperation *processOperation =
+ [[FIRCLSProcessReportOperation alloc] initWithReport:report resolver:resolver];
+
+ [processOperation start];
+ }
+
+ NSString *packagedPath;
+
+ FIRCLSDebugLog(@"Preparing the report for the new endpoint: %d",
+ self.dataSource.settings.shouldUseNewReportEndpoint);
+
+ // With the new report endpoint, the report is deleted once it is written to GDT
+ // Check if the report has a crash file before the report is moved or deleted
+ BOOL isCrash = report.isCrash;
+
+ if (self.dataSource.settings.shouldUseNewReportEndpoint) {
+ // For the new endpoint, just move the .clsrecords from "processing" -> "prepared"
+ if (![self.fileManager moveItemAtPath:report.path
+ toDirectory:self.fileManager.preparedPath]) {
+ FIRCLSErrorLog(@"Unable to move report to prepared");
+ return;
+ }
+
+ packagedPath = [self.fileManager.preparedPath
+ stringByAppendingPathComponent:report.path.lastPathComponent];
+ } else {
+ // For the legacy endpoint, continue generate the multipartmime file in "prepared-legacy"
+ FIRCLSPackageReportOperation *packageOperation =
+ [[FIRCLSPackageReportOperation alloc] initWithReport:report
+ fileManager:self.fileManager
+ settings:self.dataSource.settings];
+
+ [packageOperation start];
+ packagedPath = packageOperation.finalPath;
+ if (!packagedPath) {
+ FIRCLSErrorLog(@"Unable to package report");
+ return;
+ }
+
+ if (![self.fileManager removeItemAtPath:report.path]) {
+ FIRCLSErrorLog(@"Unable to remove a processing item");
+ }
+ }
+
+ NSLog(@"[Firebase/Crashlytics] Packaged report with id '%@' for submission",
+ report.identifier);
+
+ success = [self uploadPackagedReportAtPath:packagedPath
+ dataCollectionToken:dataCollectionToken
+ asUrgent:urgent];
+
+ // If the upload was successful and the report contained a crash forward it to Google
+ // Analytics.
+ if (success && isCrash) {
+ [FIRCLSFCRAnalytics logCrashWithTimeStamp:report.crashedOnDate.timeIntervalSince1970
+ toAnalytics:self->_analytics];
+ }
+ });
+
+ return success;
+}
+
+- (BOOL)submitPackageMultipartMimeAtPath:(NSString *)multipartmimePath
+ dataCollectionToken:(FIRCLSDataCollectionToken *)dataCollectionToken
+ synchronously:(BOOL)synchronous {
+ FIRCLSDeveloperLog(@"Crashlytics:Crash:Reports", "Submitting %@ %@",
+ synchronous ? @"sync" : @"async", multipartmimePath);
+
+ if ([[[self fileManager] fileSizeAtPath:multipartmimePath] unsignedIntegerValue] == 0) {
+ FIRCLSDeveloperLog("Crashlytics:Crash:Reports", @"Already-submitted report being ignored");
+ return NO;
+ }
+
+ NSTimeInterval timeout = 10.0;
+
+ // If we are submitting synchronously, be more aggressive with the timeout. However,
+ // we only need this if the client does not support background requests.
+ if (synchronous && ![[self networkClient] supportsBackgroundRequests]) {
+ timeout = 2.0;
+ }
+
+ NSMutableURLRequest *request = [self mutableRequestWithURL:[self reportURL] timeout:timeout];
+
+ [request setHTTPMethod:@"POST"];
+
+ if (![self fillInRequest:request forMultipartMimeDataAtPath:multipartmimePath]) {
+ return NO;
+ }
+
+ [[self networkClient] startUploadRequest:request
+ filePath:multipartmimePath
+ dataCollectionToken:dataCollectionToken
+ immediately:synchronous];
+
+ return YES;
+}
+
+- (BOOL)uploadPackagedReportAtPath:(NSString *)path
+ dataCollectionToken:(FIRCLSDataCollectionToken *)dataCollectionToken
+ asUrgent:(BOOL)urgent {
+ FIRCLSDeveloperLog("Crashlytics:Crash:Reports", @"Submitting report%@",
+ urgent ? @" as urgent" : @"");
+
+ // Check with the legacy path as the new path will always be contained in the legacy path
+ BOOL isNewPreparedPath = ![path containsString:self.fileManager.legacyPreparedPath];
+
+ if (isNewPreparedPath && self.dataSource.settings.shouldUseNewReportEndpoint) {
+ if (![dataCollectionToken isValid]) {
+ FIRCLSErrorLog(@"A report upload was requested with an invalid data collection token.");
+ return NO;
+ }
+
+ FIRCLSReportAdapter *adapter =
+ [[FIRCLSReportAdapter alloc] initWithPath:path googleAppId:self.dataSource.googleAppID];
+
+ GDTCOREvent *event = [self.dataSource.googleTransport eventForTransport];
+ event.dataObject = adapter;
+ event.qosTier = GDTCOREventQoSFast; // Bypass batching, send immediately
+
+ dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
+
+ __block BOOL success = YES;
+
+ [self.dataSource.googleTransport
+ sendDataEvent:event
+ onComplete:^(BOOL wasWritten, NSError *error) {
+ if (!wasWritten) {
+ FIRCLSDeveloperLog("Crashlytics:Crash:Reports",
+ @"Failed to send crash report due to gdt write failure.");
+ success = NO;
+ return;
+ }
+
+ if (error) {
+ FIRCLSDeveloperLog("Crashlytics:Crash:Reports",
+ @"Failed to send crash report due to gdt error: %@",
+ error.localizedDescription);
+ success = NO;
+ return;
+ }
+
+ FIRCLSDeveloperLog("Crashlytics:Crash:Reports",
+ @"Completed report submission with id: %@", path.lastPathComponent);
+
+ if (urgent) {
+ dispatch_semaphore_signal(semaphore);
+ }
+
+ [self cleanUpSubmittedReportAtPath:path];
+ }];
+
+ if (urgent) {
+ dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
+ }
+
+ return success;
+
+ } else if (!isNewPreparedPath && !self.dataSource.settings.shouldUseNewReportEndpoint) {
+ return [self submitPackageMultipartMimeAtPath:path
+ dataCollectionToken:dataCollectionToken
+ synchronously:urgent];
+ }
+
+ // Unsupported state
+ return NO;
+}
+
+- (BOOL)cleanUpSubmittedReportAtPath:(NSString *)path {
+ if (![[self fileManager] removeItemAtPath:path]) {
+ FIRCLSErrorLog(@"Unable to remove packaged submission");
+ return NO;
+ }
+
+ return YES;
+}
+
+- (void)reportUploadAtPath:(NSString *)path
+ dataCollectionToken:(FIRCLSDataCollectionToken *)dataCollectionToken
+ completedWithError:(NSError *)error {
+ FIRCLSDeveloperLog("Crashlytics:Crash:Reports", @"completed submission of %@", path);
+
+ if (!error) {
+ [self cleanUpSubmittedReportAtPath:path];
+ }
+
+ [[self delegate] didCompletePackageSubmission:path
+ dataCollectionToken:dataCollectionToken
+ error:error];
+}
+
+#pragma mark - Properties (TODO: Can delete once the experiment is over)
+
+- (NSURL *)reportURL {
+ FIRCLSURLBuilder *url = [FIRCLSURLBuilder URLWithBase:FIRCLSReportsEndpoint];
+
+ [url appendComponent:@"/sdk-api/v1/platforms/"];
+ [url appendComponent:FIRCLSApplicationGetPlatform()];
+ [url appendComponent:@"/apps/"];
+ [url appendComponent:self.dataSource.settings.fetchedBundleID];
+ [url appendComponent:@"/reports"];
+
+ return [url URL];
+}
+
+- (NSString *)localeIdentifier {
+ return [[NSLocale currentLocale] localeIdentifier];
+}
+
+#pragma mark - URL Requests
+- (NSMutableURLRequest *)mutableRequestWithURL:(NSURL *)url timeout:(NSTimeInterval)timeout {
+ NSMutableURLRequest *request =
+ [NSMutableURLRequest requestWithURL:url
+ cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
+ timeoutInterval:timeout];
+
+ NSString *localeId = [self localeIdentifier];
+
+ [request setValue:@CLS_SDK_GENERATOR_NAME forHTTPHeaderField:FIRCLSNetworkUserAgent];
+ [request setValue:FIRCLSNetworkApplicationJson forHTTPHeaderField:FIRCLSNetworkAccept];
+ [request setValue:FIRCLSNetworkUTF8 forHTTPHeaderField:FIRCLSNetworkAcceptCharset];
+ [request setValue:localeId forHTTPHeaderField:FIRCLSNetworkAcceptLanguage];
+ [request setValue:localeId forHTTPHeaderField:FIRCLSNetworkContentLanguage];
+ [request setValue:FIRCLSDeveloperToken forHTTPHeaderField:FIRCLSNetworkCrashlyticsDeveloperToken];
+ [request setValue:FIRCLSApplicationGetSDKBundleID()
+ forHTTPHeaderField:FIRCLSNetworkCrashlyticsAPIClientId];
+ [request setValue:@CLS_SDK_DISPLAY_VERSION
+ forHTTPHeaderField:FIRCLSNetworkCrashlyticsAPIClientDisplayVersion];
+ [request setValue:[[self dataSource] googleAppID]
+ forHTTPHeaderField:FIRCLSNetworkCrashlyticsGoogleAppId];
+
+ return request;
+}
+
+- (BOOL)fillInRequest:(NSMutableURLRequest *)request forMultipartMimeDataAtPath:(NSString *)path {
+ NSString *boundary = [[path lastPathComponent] stringByDeletingPathExtension];
+
+ [request setValue:[FIRCLSMultipartMimeStreamEncoder
+ contentTypeHTTPHeaderValueWithBoundary:boundary]
+ forHTTPHeaderField:@"Content-Type"];
+
+ NSNumber *fileSize = [[self fileManager] fileSizeAtPath:path];
+ if (fileSize == nil) {
+ FIRCLSErrorLog(@"Could not determine size of multipart mime file");
+ return NO;
+ }
+
+ [request setValue:[fileSize stringValue] forHTTPHeaderField:@"Content-Length"];
+
+ return YES;
+}
+
+@end
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSReportUploader_Private.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSReportUploader_Private.h
new file mode 100644
index 000000000..f54dc1673
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSReportUploader_Private.h
@@ -0,0 +1,23 @@
+// Copyright 2019 Google
+//
+// 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 "FIRCLSReportUploader.h"
+
+@interface FIRCLSReportUploader (PrivateMethods)
+
+@property(nonatomic, readonly) NSURL *reportURL;
+
+- (NSMutableURLRequest *)mutableRequestWithURL:(NSURL *)url timeout:(NSTimeInterval)timeout;
+
+@end
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/DataCollection/FIRCLSDataCollectionArbiter.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/DataCollection/FIRCLSDataCollectionArbiter.h
new file mode 100644
index 000000000..147bc7bbc
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/DataCollection/FIRCLSDataCollectionArbiter.h
@@ -0,0 +1,39 @@
+// Copyright 2019 Google
+//
+// 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
+
+@class FIRApp;
+@class FBLPromise;
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface FIRCLSDataCollectionArbiter : NSObject
+
+- (instancetype)init NS_UNAVAILABLE;
+
+- (instancetype)initWithApp:(FIRApp *)app withAppInfo:(NSDictionary *)dict;
+
+- (BOOL)isLegacyDataCollectionKeyInPlist;
+
+- (BOOL)isCrashlyticsCollectionEnabled;
+
+- (void)setCrashlyticsCollectionEnabled:(BOOL)enabled;
+
+// Returns a promise that is fulfilled once data collection is enabled.
+- (FBLPromise *)waitForCrashlyticsCollectionEnabled;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/DataCollection/FIRCLSDataCollectionArbiter.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/DataCollection/FIRCLSDataCollectionArbiter.m
new file mode 100644
index 000000000..e7d5996cf
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/DataCollection/FIRCLSDataCollectionArbiter.m
@@ -0,0 +1,148 @@
+// Copyright 2019 Google
+//
+// 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 "FIRCLSDataCollectionArbiter.h"
+
+#if __has_include()
+#import
+#else
+#import "FBLPromises.h"
+#endif
+
+#import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h"
+
+#import "FIRCLSUserDefaults.h"
+
+// The legacy data collection setting allows Fabric customers to turn off auto-
+// initialization, but can be overridden by calling [Fabric with:].
+//
+// While we support Fabric, we must have two different versions, because
+// they require these slightly different semantics.
+NSString *const FIRCLSLegacyCrashlyticsCollectionKey = @"firebase_crashlytics_collection_enabled";
+
+// The new data collection setting can be set by an API that is stored in FIRCLSUserDefaults
+NSString *const FIRCLSDataCollectionEnabledKey = @"com.crashlytics.data_collection";
+
+// The new data collection setting also allows Firebase customers to turn off data
+// collection in their Info.plist, and can be overridden by setting it to true using
+// the setCrashlyticsCollectionEnabled API.
+NSString *const FIRCLSCrashlyticsCollectionKey = @"FirebaseCrashlyticsCollectionEnabled";
+
+typedef NS_ENUM(NSInteger, FIRCLSDataCollectionSetting) {
+ FIRCLSDataCollectionSettingNotSet = 0,
+ FIRCLSDataCollectionSettingEnabled = 1,
+ FIRCLSDataCollectionSettingDisabled = 2,
+};
+
+@interface FIRCLSDataCollectionArbiter () {
+ NSLock *_mutex;
+ FBLPromise *_dataCollectionEnabled;
+ BOOL _promiseResolved;
+ FIRApp *_app;
+ NSDictionary *_appInfo;
+}
+@end
+
+@implementation FIRCLSDataCollectionArbiter
+
+- (instancetype)initWithApp:(FIRApp *)app withAppInfo:(NSDictionary *)dict {
+ self = [super init];
+ if (self) {
+ _mutex = [[NSLock alloc] init];
+ _appInfo = dict;
+ _app = app;
+ if ([FIRCLSDataCollectionArbiter isCrashlyticsCollectionEnabledWithApp:app withAppInfo:dict]) {
+ _dataCollectionEnabled = [FBLPromise resolvedWith:nil];
+ _promiseResolved = YES;
+ } else {
+ _dataCollectionEnabled = [FBLPromise pendingPromise];
+ _promiseResolved = NO;
+ }
+ }
+
+ return self;
+}
+
+/*
+ * Legacy collection key that we provide for customers to disable Crash reporting.
+ * Customers can later turn on Crashlytics using Fabric.with if they choose to do so.
+ *
+ * This flag is unsupported for the "New SDK"
+ */
+- (BOOL)isLegacyDataCollectionKeyInPlist {
+ if ([_appInfo objectForKey:FIRCLSLegacyCrashlyticsCollectionKey]) {
+ return true;
+ }
+
+ return false;
+}
+
+// This functionality is called in the initializer before self is fully initialized,
+// so a class method is used. The instance method below allows for a consistent clean API.
++ (BOOL)isCrashlyticsCollectionEnabledWithApp:(FIRApp *)app withAppInfo:(NSDictionary *)dict {
+ FIRCLSDataCollectionSetting stickySetting = [FIRCLSDataCollectionArbiter stickySetting];
+ if (stickySetting != FIRCLSDataCollectionSettingNotSet) {
+ return stickySetting == FIRCLSDataCollectionSettingEnabled;
+ }
+
+ id firebaseCrashlyticsCollectionEnabled = [dict objectForKey:FIRCLSCrashlyticsCollectionKey];
+ if ([firebaseCrashlyticsCollectionEnabled isKindOfClass:[NSString class]] ||
+ [firebaseCrashlyticsCollectionEnabled isKindOfClass:[NSNumber class]]) {
+ return [firebaseCrashlyticsCollectionEnabled boolValue];
+ }
+
+ return [app isDataCollectionDefaultEnabled];
+}
+
+- (BOOL)isCrashlyticsCollectionEnabled {
+ return [FIRCLSDataCollectionArbiter isCrashlyticsCollectionEnabledWithApp:_app
+ withAppInfo:_appInfo];
+}
+
+- (void)setCrashlyticsCollectionEnabled:(BOOL)enabled {
+ FIRCLSUserDefaults *userDefaults = [FIRCLSUserDefaults standardUserDefaults];
+ FIRCLSDataCollectionSetting setting =
+ enabled ? FIRCLSDataCollectionSettingEnabled : FIRCLSDataCollectionSettingDisabled;
+ [userDefaults setInteger:setting forKey:FIRCLSDataCollectionEnabledKey];
+ [userDefaults synchronize];
+
+ [_mutex lock];
+ if (enabled) {
+ if (!_promiseResolved) {
+ [_dataCollectionEnabled fulfill:nil];
+ _promiseResolved = YES;
+ }
+ } else {
+ if (_promiseResolved) {
+ _dataCollectionEnabled = [FBLPromise pendingPromise];
+ _promiseResolved = NO;
+ }
+ }
+ [_mutex unlock];
+}
+
++ (FIRCLSDataCollectionSetting)stickySetting {
+ FIRCLSUserDefaults *userDefaults = [FIRCLSUserDefaults standardUserDefaults];
+ return [userDefaults integerForKey:FIRCLSDataCollectionEnabledKey];
+}
+
+- (FBLPromise *)waitForCrashlyticsCollectionEnabled {
+ FBLPromise *result = nil;
+ [_mutex lock];
+ result = _dataCollectionEnabled;
+ [_mutex unlock];
+ return result;
+}
+
+@end
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/DataCollection/FIRCLSDataCollectionToken.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/DataCollection/FIRCLSDataCollectionToken.h
new file mode 100644
index 000000000..4ab2bb661
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/DataCollection/FIRCLSDataCollectionToken.h
@@ -0,0 +1,45 @@
+// Copyright 2019 Google
+//
+// 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
+
+NS_ASSUME_NONNULL_BEGIN
+
+/**
+ * A FIRCLSDataCollectionToken represents having permission to upload data. A data collection token
+ * is either valid or nil. Every function that directly initiates a network operation that will
+ * result in data collection must check to make sure it has been passed a valid token. Tokens should
+ * only be created when either (1) automatic data collection is enabled, or (2) the user has
+ * explicitly given permission to collect data for a particular purpose, using the API. For all the
+ * functions in between, the data collection token getting passed as an argument helps to document
+ * and enforce the flow of data collection permission through the SDK.
+ */
+@interface FIRCLSDataCollectionToken : NSObject
+
+/**
+ * Creates a valid token. Only call this method when either (1) automatic data collection is
+ * enabled, or (2) the user has explicitly given permission to collect data for a particular
+ * purpose, using the API.
+ */
++ (instancetype)validToken;
+
+/**
+ * Use this to verify that a token is valid. If this is called on a nil instance, it will return NO.
+ * @return YES.
+ */
+- (BOOL)isValid;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/DataCollection/FIRCLSDataCollectionToken.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/DataCollection/FIRCLSDataCollectionToken.m
new file mode 100644
index 000000000..1a41ee1df
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/DataCollection/FIRCLSDataCollectionToken.m
@@ -0,0 +1,27 @@
+// Copyright 2019 Google
+//
+// 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 "FIRCLSDataCollectionToken.h"
+
+@implementation FIRCLSDataCollectionToken
+
++ (instancetype)validToken {
+ return [[FIRCLSDataCollectionToken alloc] init];
+}
+
+- (BOOL)isValid {
+ return YES;
+}
+
+@end
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSession.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSession.h
new file mode 100644
index 000000000..fa53468c1
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSession.h
@@ -0,0 +1,84 @@
+// Copyright 2019 Google
+//
+// 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 "FIRCLSURLSessionAvailability.h"
+
+#if FIRCLSURLSESSION_REQUIRED
+
+#import "FIRCLSURLSessionConfiguration.h"
+
+#import
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface FIRCLSURLSession : NSObject {
+ id _delegate;
+ NSOperationQueue *_delegateQueue;
+ NSURLSessionConfiguration *_configuration;
+ NSMutableSet *_taskSet;
+ dispatch_queue_t _queue;
+
+ NSString *_sessionDescription;
+}
+
++ (BOOL)NSURLSessionShouldBeUsed;
+
++ (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration;
++ (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration
+ delegate:(nullable id)delegate
+ delegateQueue:(nullable NSOperationQueue *)queue;
+
+@property(nonatomic, readonly, retain) NSOperationQueue *delegateQueue;
+@property(nonatomic, readonly, retain) id delegate;
+@property(nonatomic, readonly, copy) NSURLSessionConfiguration *configuration;
+
+@property(nonatomic, copy) NSString *sessionDescription;
+
+- (void)getTasksWithCompletionHandler:
+ (void (^)(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks))completionHandler;
+
+// task creation - suitable for background operations
+- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromFile:(NSURL *)fileURL;
+
+- (NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request;
+- (NSURLSessionDownloadTask *)downloadTaskWithURL:(NSURL *)url;
+
+// convenience methods (that are not available for background sessions
+- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request
+ completionHandler:(nullable void (^)(NSData *data,
+ NSURLResponse *response,
+ NSError *error))completionHandler;
+- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request;
+
+- (NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request
+ completionHandler:
+ (nullable void (^)(NSURL *targetPath,
+ NSURLResponse *response,
+ NSError *error))completionHandler;
+
+- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request
+ fromFile:(NSURL *)fileURL
+ completionHandler:
+ (nullable void (^)(NSData *data,
+ NSURLResponse *response,
+ NSError *error))completionHandler;
+
+- (void)invalidateAndCancel;
+- (void)finishTasksAndInvalidate;
+
+@end
+
+NS_ASSUME_NONNULL_END
+
+#endif
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSession.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSession.m
new file mode 100644
index 000000000..981542368
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSession.m
@@ -0,0 +1,346 @@
+// Copyright 2019 Google
+//
+// 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 "FIRCLSURLSessionAvailability.h"
+
+#if FIRCLSURLSESSION_REQUIRED
+#import "FIRCLSURLSession.h"
+
+#import "FIRCLSURLSessionDataTask.h"
+#import "FIRCLSURLSessionDataTask_PrivateMethods.h"
+#import "FIRCLSURLSessionDownloadTask.h"
+#import "FIRCLSURLSessionDownloadTask_PrivateMethods.h"
+#import "FIRCLSURLSessionTask_PrivateMethods.h"
+#import "FIRCLSURLSessionUploadTask.h"
+
+#define DELEGATE ((id)self->_delegate)
+
+@interface FIRCLSURLSession ()
+
+@property(nonatomic, retain) NSOperationQueue *delegateQueue;
+@property(nonatomic, retain) id delegate;
+@property(nonatomic, copy) NSURLSessionConfiguration *configuration;
+
+@end
+
+@implementation FIRCLSURLSession
+
+@synthesize delegate = _delegate;
+@synthesize delegateQueue = _delegateQueue;
+@synthesize configuration = _configuration;
+@synthesize sessionDescription = _sessionDescription;
+
++ (BOOL)NSURLSessionShouldBeUsed {
+ if (!NSClassFromString(@"NSURLSession")) {
+ return NO;
+ }
+
+ // We use this as a proxy to verify that we are on at least iOS 8 or 10.10. The first OSes that
+ // has NSURLSession were fairly unstable.
+ return [[NSURLSessionConfiguration class]
+ respondsToSelector:@selector(backgroundSessionConfigurationWithIdentifier:)];
+}
+
++ (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration {
+ return [self sessionWithConfiguration:configuration delegate:nil delegateQueue:nil];
+}
+
++ (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration
+ delegate:(nullable id)delegate
+ delegateQueue:(nullable NSOperationQueue *)queue {
+ if ([self NSURLSessionShouldBeUsed]) {
+ return [NSURLSession sessionWithConfiguration:configuration
+ delegate:delegate
+ delegateQueue:queue];
+ }
+
+ if (!configuration) {
+ return nil;
+ }
+
+#if __has_feature(objc_arc)
+ FIRCLSURLSession *session = [self new];
+#else
+ FIRCLSURLSession *session = [[self new] autorelease];
+#endif
+ [session setDelegate:delegate];
+ // When delegate exists, but delegateQueue is nil, create a serial queue like NSURLSession
+ // documents.
+ if (delegate && !queue) {
+ queue = [self newDefaultDelegateQueue];
+ }
+ session.delegateQueue = queue;
+ session.configuration = configuration;
+ return (NSURLSession *)session;
+}
+
++ (NSOperationQueue *)newDefaultDelegateQueue {
+ NSOperationQueue *delegateQueue = [[NSOperationQueue alloc] init];
+ delegateQueue.name = [NSString stringWithFormat:@"%@ %p", NSStringFromClass(self), self];
+ delegateQueue.maxConcurrentOperationCount = 1;
+ return delegateQueue;
+}
+
+- (instancetype)init {
+ self = [super init];
+ if (!self) {
+ return nil;
+ }
+
+ _queue = dispatch_queue_create("com.crashlytics.URLSession", 0);
+
+ return self;
+}
+
+#if !__has_feature(objc_arc)
+- (void)dealloc {
+ [_taskSet release];
+ [_delegate release];
+ [_delegateQueue release];
+ [_configuration release];
+
+#if !OS_OBJECT_USE_OBJC
+ dispatch_release(_queue);
+#endif
+
+ [super dealloc];
+}
+#endif
+
+#pragma mark - Managing the Session
+
+- (void)invalidateAndCancel {
+ dispatch_sync(_queue, ^{
+ for (FIRCLSURLSessionTask *task in self->_taskSet) {
+ [task cancel];
+ }
+ });
+
+ self.delegate = nil;
+}
+
+- (void)finishTasksAndInvalidate {
+ self.delegate = nil;
+}
+
+#pragma mark -
+
+- (void)getTasksWithCompletionHandler:
+ (void (^)(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks))completionHandler {
+ [[self delegateQueue] addOperationWithBlock:^{
+ // TODO - this is totally wrong, but better than not calling back at all
+ completionHandler(@[], @[], @[]);
+ }];
+}
+
+- (void)removeTaskFromSet:(FIRCLSURLSessionTask *)task {
+ dispatch_async(_queue, ^{
+ [self->_taskSet removeObject:task];
+ });
+}
+
+- (void)configureTask:(FIRCLSURLSessionTask *)task
+ withRequest:(NSURLRequest *)request
+ block:(void (^)(NSMutableURLRequest *mutableRequest))block {
+ NSMutableURLRequest *modifiedRequest = [request mutableCopy];
+
+ dispatch_sync(_queue, ^{
+ [self->_taskSet addObject:task];
+
+ // TODO: this isn't allowed to overwrite existing headers
+ for (NSString *key in [self->_configuration HTTPAdditionalHeaders]) {
+ [modifiedRequest addValue:[[self->_configuration HTTPAdditionalHeaders] objectForKey:key]
+ forHTTPHeaderField:key];
+ }
+ });
+
+ if (block) {
+ block(modifiedRequest);
+ }
+
+ [task setOriginalRequest:modifiedRequest];
+ [task setDelegate:self];
+
+#if !__has_feature(objc_arc)
+ [modifiedRequest release];
+#endif
+}
+
+- (BOOL)shouldInvokeDelegateSelector:(SEL)selector forTask:(FIRCLSURLSessionTask *)task {
+ return [task invokesDelegate] && [_delegate respondsToSelector:selector];
+}
+
+#pragma mark Task Creation
+- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request
+ fromFile:(NSURL *)fileURL {
+ return [self uploadTaskWithRequest:request fromFile:fileURL completionHandler:nil];
+}
+
+- (NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request {
+ return [self downloadTaskWithRequest:request completionHandler:nil];
+}
+
+- (NSURLSessionDownloadTask *)downloadTaskWithURL:(NSURL *)url {
+ return [self downloadTaskWithRequest:[NSURLRequest requestWithURL:url]];
+}
+
+#pragma mark Async Convenience Methods
+- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request
+ completionHandler:(nullable void (^)(NSData *data,
+ NSURLResponse *response,
+ NSError *error))completionHandler {
+ FIRCLSURLSessionDataTask *task = [FIRCLSURLSessionDataTask task];
+
+ if (completionHandler) {
+ [task setCompletionHandler:completionHandler];
+ [task setInvokesDelegate:NO];
+ }
+
+ [self configureTask:task withRequest:request block:nil];
+
+ return (NSURLSessionDataTask *)task;
+}
+
+- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request {
+ return [self dataTaskWithRequest:request completionHandler:nil];
+}
+
+- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request
+ fromFile:(NSURL *)fileURL
+ completionHandler:
+ (nullable void (^)(NSData *data,
+ NSURLResponse *response,
+ NSError *error))completionHandler {
+ FIRCLSURLSessionUploadTask *task = [FIRCLSURLSessionUploadTask task];
+
+ if (completionHandler) {
+ [task setCompletionHandler:completionHandler];
+ [task setInvokesDelegate:NO];
+ }
+
+ [self configureTask:task
+ withRequest:request
+ block:^(NSMutableURLRequest *mutableRequest) {
+ // you cannot set up both of these, and we'll be using the stream here
+ [mutableRequest setHTTPBody:nil];
+ [mutableRequest setHTTPBodyStream:[NSInputStream inputStreamWithURL:fileURL]];
+ }];
+
+ return (NSURLSessionUploadTask *)task;
+}
+
+- (NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request
+ completionHandler:
+ (nullable void (^)(NSURL *targetPath,
+ NSURLResponse *response,
+ NSError *error))completionHandler {
+ FIRCLSURLSessionDownloadTask *task = [FIRCLSURLSessionDownloadTask task];
+
+ if (completionHandler) {
+ [task setDownloadCompletionHandler:completionHandler];
+ [task setInvokesDelegate:NO];
+ }
+
+ [self configureTask:task withRequest:request block:nil];
+
+ return (NSURLSessionDownloadTask *)task;
+}
+
+#pragma mark FIRCLSURLSessionTaskDelegate
+- (NSURLRequest *)task:(FIRCLSURLSessionTask *)task
+ willPerformHTTPRedirection:(NSHTTPURLResponse *)response
+ newRequest:(NSURLRequest *)request {
+ // just accept the proposed redirection
+ return request;
+}
+
+- (void)task:(FIRCLSURLSessionTask *)task didCompleteWithError:(NSError *)error {
+ if (![self shouldInvokeDelegateSelector:@selector(URLSession:task:didCompleteWithError:)
+ forTask:task]) {
+ [self removeTaskFromSet:task];
+ return;
+ }
+
+ [_delegateQueue addOperationWithBlock:^{
+ [DELEGATE URLSession:(NSURLSession *)self
+ task:(NSURLSessionTask *)task
+ didCompleteWithError:error];
+
+ // Note that you *cannot* clean up here, because this method could be run asynchronously with
+ // the delegate methods that care about the state of the task
+ [self removeTaskFromSet:task];
+ }];
+}
+
+#pragma mark FIRCLSURLSessionDataTask
+- (void)task:(FIRCLSURLSessionDataTask *)task didReceiveResponse:(NSURLResponse *)response {
+ if (![self shouldInvokeDelegateSelector:@selector
+ (URLSession:dataTask:didReceiveResponse:completionHandler:)
+ forTask:task]) {
+ return;
+ }
+
+ [_delegateQueue addOperationWithBlock:^{
+ [DELEGATE URLSession:(NSURLSession *)self
+ dataTask:(NSURLSessionDataTask *)task
+ didReceiveResponse:response
+ completionHandler:^(NSURLSessionResponseDisposition disposition){
+ // nothing to do here
+ }];
+ }];
+}
+
+- (void)task:(FIRCLSURLSessionDataTask *)task didReceiveData:(NSData *)data {
+ if (![self shouldInvokeDelegateSelector:@selector(URLSession:dataTask:didReceiveData:)
+ forTask:task]) {
+ return;
+ }
+
+ [_delegateQueue addOperationWithBlock:^{
+ [DELEGATE URLSession:(NSURLSession *)self
+ dataTask:(NSURLSessionDataTask *)task
+ didReceiveData:data];
+ }];
+}
+
+#pragma mark FIRCLSURLSessionDownloadDelegate
+- (void)downloadTask:(FIRCLSURLSessionDownloadTask *)task didFinishDownloadingToURL:(NSURL *)url {
+ if (![self shouldInvokeDelegateSelector:@selector(URLSession:
+ downloadTask:didFinishDownloadingToURL:)
+ forTask:task]) {
+ // We have to be certain that we cleanup only once the delegate no longer cares about the state
+ // of the task being changed. In the case of download, this is either after the delegate method
+ // has been invoked, or here, if the delegate doesn't care.
+ [task cleanup];
+ return;
+ }
+
+ [_delegateQueue addOperationWithBlock:^{
+ [DELEGATE URLSession:(NSURLSession *)self
+ downloadTask:(NSURLSessionDownloadTask *)task
+ didFinishDownloadingToURL:url];
+
+ // Cleanup for the download tasks is a little complex. As long as we do it only after
+ // the delegate has been informed of the completed download, we are ok.
+ [task cleanup];
+ }];
+}
+
+@end
+
+#else
+
+INJECT_STRIP_SYMBOL(clsurlsession)
+
+#endif
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSessionAvailability.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSessionAvailability.h
new file mode 100644
index 000000000..9f3ead01b
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSessionAvailability.h
@@ -0,0 +1,28 @@
+// Copyright 2019 Google
+//
+// 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.
+
+#pragma once
+
+#include
+
+#define FIRCLSURLSESSION_REQUIRED (!TARGET_OS_WATCH && !TARGET_OS_TV)
+
+// These macros generate a function to force a symbol for the containing .o, to work around an issue
+// where strip will not strip debug information without a symbol to strip.
+#define CONCAT_EXPANDED(a, b) a##b
+#define CONCAT(a, b) CONCAT_EXPANDED(a, b)
+#define DUMMY_FUNCTION_NAME(x) CONCAT(fircls_strip_this_, x)
+#define INJECT_STRIP_SYMBOL(x) \
+ void DUMMY_FUNCTION_NAME(x)(void) { \
+ }
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSessionConfiguration.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSessionConfiguration.h
new file mode 100644
index 000000000..bda0f7083
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSessionConfiguration.h
@@ -0,0 +1,42 @@
+// Copyright 2019 Google
+//
+// 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 "FIRCLSURLSessionAvailability.h"
+
+#if FIRCLSURLSESSION_REQUIRED
+
+#import
+
+@interface FIRCLSURLSessionConfiguration : NSObject {
+ NSDictionary *_additionalHeaders;
+ NSURLCache *_URLCache;
+ NSHTTPCookieAcceptPolicy _cookiePolicy;
+}
+
++ (NSURLSessionConfiguration *)defaultSessionConfiguration;
++ (NSURLSessionConfiguration *)ephemeralSessionConfiguration;
++ (NSURLSessionConfiguration *)backgroundSessionConfiguration:(NSString *)identifier;
++ (NSURLSessionConfiguration *)backgroundSessionConfigurationWithIdentifier:(NSString *)identifier;
+
+@property(nonatomic, copy) NSDictionary *HTTPAdditionalHeaders;
+@property(nonatomic, retain) NSURLCache *URLCache;
+@property(nonatomic, assign) NSHTTPCookieAcceptPolicy HTTPCookieAcceptPolicy;
+@property(nonatomic, assign) BOOL sessionSendsLaunchEvents;
+@property(nonatomic, assign) NSTimeInterval timeoutIntervalForRequest;
+@property(nonatomic, assign) NSTimeInterval timeoutIntervalForResource;
+@property(nonatomic, assign) BOOL allowsCellularAccess;
+
+@end
+
+#endif
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSessionConfiguration.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSessionConfiguration.m
new file mode 100644
index 000000000..177e7a6bf
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSessionConfiguration.m
@@ -0,0 +1,92 @@
+// Copyright 2019 Google
+//
+// 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 "FIRCLSURLSessionAvailability.h"
+
+#import "FIRCLSURLSession.h"
+
+#if FIRCLSURLSESSION_REQUIRED
+#import "FIRCLSURLSessionConfiguration.h"
+
+@implementation FIRCLSURLSessionConfiguration
+
+@synthesize URLCache = _URLCache;
+@synthesize HTTPAdditionalHeaders = _additionalHeaders;
+@synthesize HTTPCookieAcceptPolicy = _cookiePolicy;
+
++ (NSURLSessionConfiguration *)defaultSessionConfiguration {
+ if ([FIRCLSURLSession NSURLSessionShouldBeUsed]) {
+ return [NSURLSessionConfiguration defaultSessionConfiguration];
+ }
+
+#if __has_feature(objc_arc)
+ return [self new];
+#else
+ return [[self new] autorelease];
+#endif
+}
+
++ (NSURLSessionConfiguration *)ephemeralSessionConfiguration {
+ if ([FIRCLSURLSession NSURLSessionShouldBeUsed]) {
+ return [NSURLSessionConfiguration ephemeralSessionConfiguration];
+ }
+
+#if __has_feature(objc_arc)
+ return [self new];
+#else
+ return [[self new] autorelease];
+#endif
+}
+
++ (NSURLSessionConfiguration *)backgroundSessionConfiguration:(NSString *)identifier {
+ return [self backgroundSessionConfigurationWithIdentifier:identifier];
+}
+
++ (NSURLSessionConfiguration *)backgroundSessionConfigurationWithIdentifier:(NSString *)identifier {
+ if (![FIRCLSURLSession NSURLSessionShouldBeUsed]) {
+ return nil;
+ }
+
+ if ([[NSURLSessionConfiguration class]
+ respondsToSelector:@selector(backgroundSessionConfigurationWithIdentifier:)]) {
+ return [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:identifier];
+ }
+
+ return [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:identifier];
+}
+
+- (id)copyWithZone:(NSZone *)zone {
+ FIRCLSURLSessionConfiguration *configuration;
+
+ configuration = [FIRCLSURLSessionConfiguration new];
+ [configuration setHTTPAdditionalHeaders:[self HTTPAdditionalHeaders]];
+
+ return configuration;
+}
+
+// This functionality is not supported by the wrapper, so we just stub it out
+- (BOOL)sessionSendsLaunchEvents {
+ return NO;
+}
+
+- (void)setSessionSendsLaunchEvents:(BOOL)sessionSendsLaunchEvents {
+}
+
+@end
+
+#else
+
+INJECT_STRIP_SYMBOL(clsurlsessionconfiguration)
+
+#endif
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSession_PrivateMethods.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSession_PrivateMethods.h
new file mode 100644
index 000000000..84885e1d6
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSession_PrivateMethods.h
@@ -0,0 +1,27 @@
+// Copyright 2019 Google
+//
+// 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 "FIRCLSURLSessionAvailability.h"
+
+#if FIRCLSURLSESSION_REQUIRED
+
+#import
+
+@interface FIRCLSURLSession (PrivateMethods)
+
+- (void)runOnDelegateQueue:(void (^)(void))block;
+
+@end
+
+#endif
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDataTask.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDataTask.h
new file mode 100644
index 000000000..22099584e
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDataTask.h
@@ -0,0 +1,32 @@
+// Copyright 2019 Google
+//
+// 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 "FIRCLSURLSessionAvailability.h"
+
+#if FIRCLSURLSESSION_REQUIRED
+
+#import "FIRCLSURLSessionTask.h"
+
+@interface FIRCLSURLSessionDataTask : FIRCLSURLSessionTask {
+ void (^_completionHandler)(NSData *data, NSURLResponse *response, NSError *error);
+ NSURLConnection *_connection;
+ NSMutableData *_data;
+ NSString *_taskDescription;
+}
+
+@property(nonatomic, copy) NSString *taskDescription;
+
+@end
+
+#endif
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDataTask.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDataTask.m
new file mode 100644
index 000000000..be40ab753
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDataTask.m
@@ -0,0 +1,124 @@
+// Copyright 2019 Google
+//
+// 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 "FIRCLSURLSessionAvailability.h"
+
+#if FIRCLSURLSESSION_REQUIRED
+#import "FIRCLSURLSessionDataTask.h"
+
+#import "FIRCLSURLSessionDataTask_PrivateMethods.h"
+
+#define DELEGATE ((id)[self delegate])
+
+@interface FIRCLSURLSessionDataTask ()
+@end
+
+@implementation FIRCLSURLSessionDataTask
+
+@synthesize connection = _connection;
+@synthesize completionHandler = _completionHandler;
+@synthesize taskDescription = _taskDescription;
+
+#if !__has_feature(objc_arc)
+- (void)dealloc {
+ [_connection release];
+ [_completionHandler release];
+ [_taskDescription release];
+ [_data release];
+
+ [super dealloc];
+}
+#endif
+
+- (void)resume {
+ dispatch_async([self queue], ^{
+ NSURLConnection *connection;
+
+ if ([self connection]) {
+ return;
+ }
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+ connection = [[NSURLConnection alloc] initWithRequest:[self originalRequest]
+ delegate:self
+ startImmediately:NO];
+#pragma clang diagnostic pop
+
+ [self setConnection:connection];
+
+ // bummer we have to do this on a runloop, but other mechanisms require iOS 5 or 10.7
+ [connection scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
+#if !__has_feature(objc_arc)
+ [connection release];
+#endif
+ [connection start];
+ });
+}
+
+- (void)complete {
+ // call completion handler first
+ if (_completionHandler) {
+ // this should go to another queue
+ _completionHandler(_data, [self response], [self error]);
+ }
+
+ // and then finally, call the session delegate completion
+ [DELEGATE task:self didCompleteWithError:[self error]];
+}
+
+- (void)cancel {
+ [self.connection cancel];
+}
+
+#pragma mark NSURLConnectionDelegate
+- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
+ dispatch_async([self queue], ^{
+ [DELEGATE task:self didReceiveResponse:response];
+
+ [self setResponse:response];
+ });
+}
+
+- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
+ dispatch_async([self queue], ^{
+ if (!self->_data) {
+ self->_data = [NSMutableData new];
+ }
+
+ [self->_data appendData:data];
+ [DELEGATE task:self didReceiveData:data];
+ });
+}
+
+- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
+ dispatch_async([self queue], ^{
+ [self setError:error];
+ [self complete];
+ });
+}
+
+- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
+ dispatch_async([self queue], ^{
+ [self complete];
+ });
+}
+
+@end
+
+#else
+
+INJECT_STRIP_SYMBOL(clsurlsessiondatatask)
+
+#endif
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDataTask_PrivateMethods.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDataTask_PrivateMethods.h
new file mode 100644
index 000000000..f85a3776f
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDataTask_PrivateMethods.h
@@ -0,0 +1,43 @@
+// Copyright 2019 Google
+//
+// 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 "FIRCLSURLSessionAvailability.h"
+
+#if FIRCLSURLSESSION_REQUIRED
+
+#import
+
+#import "FIRCLSURLSessionTask_PrivateMethods.h"
+
+@protocol FIRCLSURLSessionDataDelegate;
+
+@interface FIRCLSURLSessionDataTask ()
+
+@property(nonatomic, retain) NSURLConnection *connection;
+@property(nonatomic, copy) void (^completionHandler)
+ (NSData *data, NSURLResponse *response, NSError *error);
+
+- (void)complete;
+
+@end
+
+@protocol FIRCLSURLSessionDataDelegate
+@required
+
+- (void)task:(FIRCLSURLSessionDataTask *)task didReceiveResponse:(NSURLResponse *)response;
+- (void)task:(FIRCLSURLSessionDataTask *)task didReceiveData:(NSData *)data;
+
+@end
+
+#endif
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDownloadTask.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDownloadTask.h
new file mode 100644
index 000000000..314180f7d
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDownloadTask.h
@@ -0,0 +1,31 @@
+// Copyright 2019 Google
+//
+// 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 "FIRCLSURLSessionAvailability.h"
+
+#if FIRCLSURLSESSION_REQUIRED
+
+#import "FIRCLSURLSessionDataTask.h"
+
+@protocol FIRCLSURLSessionDownloadDelegate;
+
+@interface FIRCLSURLSessionDownloadTask : FIRCLSURLSessionDataTask {
+ void (^_downloadCompletionHandler)(NSURL *targetPath, NSURLResponse *response, NSError *error);
+ NSOutputStream *_outputStream;
+ NSURL *_targetURL;
+}
+
+@end
+
+#endif
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDownloadTask.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDownloadTask.m
new file mode 100644
index 000000000..a0c9b2a84
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDownloadTask.m
@@ -0,0 +1,157 @@
+// Copyright 2019 Google
+//
+// 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 "FIRCLSURLSessionAvailability.h"
+
+#if FIRCLSURLSESSION_REQUIRED
+#import "FIRCLSURLSessionDownloadTask.h"
+
+#import "FIRCLSURLSessionDownloadTask_PrivateMethods.h"
+
+#define DELEGATE ((id)[self delegate])
+
+@interface FIRCLSURLSessionDownloadTask ()
+@end
+
+@implementation FIRCLSURLSessionDownloadTask
+
+@synthesize downloadCompletionHandler = _downloadCompletionHandler;
+
+- (id)init {
+ self = [super init];
+ if (!self) {
+ return nil;
+ }
+
+#if __has_feature(objc_arc)
+ _targetURL = [self temporaryFileURL];
+ _outputStream = [NSOutputStream outputStreamWithURL:_targetURL append:NO];
+#else
+ _targetURL = [[self temporaryFileURL] retain];
+ _outputStream = [[NSOutputStream outputStreamWithURL:_targetURL append:NO] retain];
+#endif
+
+ [_outputStream scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
+ [_outputStream setDelegate:self];
+
+ return self;
+}
+
+#if !__has_feature(objc_arc)
+- (void)dealloc {
+ [_downloadCompletionHandler release];
+ [_targetURL release];
+ [_outputStream release];
+
+ [super dealloc];
+}
+#else
+- (void)dealloc {
+ [_outputStream close];
+ _outputStream.delegate = nil;
+}
+#endif
+
+- (NSURL *)temporaryFileURL {
+ NSString *tmpPath;
+
+ tmpPath = [NSTemporaryDirectory()
+ stringByAppendingPathComponent:[[NSProcessInfo processInfo] globallyUniqueString]];
+
+ // TODO: make this actually unique
+ return [NSURL fileURLWithPath:tmpPath isDirectory:NO];
+}
+
+- (void)cleanup {
+ // now, remove the temporary file
+ [[NSFileManager defaultManager] removeItemAtURL:_targetURL error:nil];
+}
+
+- (void)complete {
+ // This is an override of FIRCLSURLSessionDataTask's cleanup method
+
+ // call completion handler first
+ if (_downloadCompletionHandler) {
+ _downloadCompletionHandler(_targetURL, [self response], [self error]);
+ }
+
+ // followed by the session delegate, if there was no error
+ if (![self error]) {
+ [DELEGATE downloadTask:self didFinishDownloadingToURL:_targetURL];
+ }
+
+ // and then finally, call the session delegate completion
+ [DELEGATE task:self didCompleteWithError:[self error]];
+}
+
+- (void)writeDataToStream:(NSData *)data {
+ // open the stream first
+ if ([_outputStream streamStatus] == NSStreamStatusNotOpen) {
+ [_outputStream open];
+ }
+
+ if ([data respondsToSelector:@selector(enumerateByteRangesUsingBlock:)]) {
+ [data enumerateByteRangesUsingBlock:^(const void *bytes, NSRange byteRange, BOOL *stop) {
+ [self->_outputStream write:bytes maxLength:byteRange.length];
+ }];
+
+ return;
+ }
+
+ // fall back to the less-efficient mechanism for older OSes
+ [_outputStream write:[data bytes] maxLength:[data length]];
+}
+
+#pragma mark NSURLConnectionDelegate
+- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
+ dispatch_async([self queue], ^{
+ [self writeDataToStream:data];
+ });
+}
+
+- (void)completeForError {
+ dispatch_async([self queue], ^{
+ [self->_outputStream close];
+ [self->_connection cancel];
+ if (![self error]) {
+ [self setError:[NSError errorWithDomain:@"FIRCLSURLSessionDownloadTaskError"
+ code:-1
+ userInfo:nil]];
+ }
+ [self complete];
+ });
+}
+
+#pragma mark NSStreamDelegate
+- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode {
+ switch (eventCode) {
+ case NSStreamEventHasSpaceAvailable:
+ break;
+ case NSStreamEventErrorOccurred:
+ [self completeForError];
+ break;
+ case NSStreamEventEndEncountered:
+ break;
+ default:
+ break;
+ }
+}
+
+@end
+
+#else
+
+INJECT_STRIP_SYMBOL(clsurlsessiondownloadtask)
+
+#endif
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDownloadTask_PrivateMethods.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDownloadTask_PrivateMethods.h
new file mode 100644
index 000000000..7e8ee9d9f
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDownloadTask_PrivateMethods.h
@@ -0,0 +1,39 @@
+// Copyright 2019 Google
+//
+// 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 "FIRCLSURLSessionAvailability.h"
+
+#if FIRCLSURLSESSION_REQUIRED
+
+#import
+
+#import "FIRCLSURLSessionDataTask_PrivateMethods.h"
+
+@protocol FIRCLSURLSessionDownloadDelegate;
+
+@interface FIRCLSURLSessionDownloadTask ()
+
+@property(nonatomic, copy) void (^downloadCompletionHandler)
+ (NSURL *targetPath, NSURLResponse *response, NSError *error);
+
+@end
+
+@protocol FIRCLSURLSessionDownloadDelegate
+@required
+
+- (void)downloadTask:(FIRCLSURLSessionDownloadTask *)task didFinishDownloadingToURL:(NSURL *)url;
+
+@end
+
+#endif
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionTask.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionTask.h
new file mode 100644
index 000000000..92316464d
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionTask.h
@@ -0,0 +1,38 @@
+// Copyright 2019 Google
+//
+// 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
+
+@protocol FIRCLSURLSessionTaskDelegate;
+
+@interface FIRCLSURLSessionTask : NSObject {
+ __unsafe_unretained id _delegate;
+
+ NSURLRequest* _originalRequest;
+ NSURLRequest* _currentRequest;
+ NSURLResponse* _response;
+ NSError* _error;
+ dispatch_queue_t _queue;
+ BOOL _invokesDelegate;
+}
+
+@property(nonatomic, readonly, copy) NSURLRequest* originalRequest;
+@property(nonatomic, readonly, copy) NSURLRequest* currentRequest;
+@property(nonatomic, readonly, copy) NSURLResponse* response;
+
+@property(nonatomic, readonly, copy) NSError* error;
+
+- (void)resume;
+
+@end
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionTask.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionTask.m
new file mode 100644
index 000000000..8eba2c185
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionTask.m
@@ -0,0 +1,95 @@
+// Copyright 2019 Google
+//
+// 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 "FIRCLSURLSessionAvailability.h"
+
+#if FIRCLSURLSESSION_REQUIRED
+#import "FIRCLSURLSession.h"
+
+#import "FIRCLSURLSessionTask.h"
+
+#import "FIRCLSURLSessionTask_PrivateMethods.h"
+#import "FIRCLSURLSession_PrivateMethods.h"
+
+@implementation FIRCLSURLSessionTask
+
++ (instancetype)task {
+#if __has_feature(objc_arc)
+ return [[self class] new];
+
+#else
+ return [[[self class] new] autorelease];
+#endif
+}
+
+@synthesize currentRequest = _currentRequest;
+@synthesize originalRequest = _originalRequest;
+@synthesize response = _response;
+@synthesize error = _error;
+@synthesize queue = _queue;
+@synthesize invokesDelegate = _invokesDelegate;
+
+- (instancetype)init {
+ self = [super init];
+ if (!self) {
+ return self;
+ }
+
+ _queue = dispatch_queue_create("com.crashlytics.URLSessionTask", 0);
+
+ _invokesDelegate = YES;
+
+ return self;
+}
+
+#if !__has_feature(objc_arc)
+- (void)dealloc {
+ [_originalRequest release];
+ [_currentRequest release];
+ [_response release];
+ [_error release];
+
+#if !OS_OBJECT_USE_OBJC
+ dispatch_release(_queue);
+#endif
+
+ [super dealloc];
+}
+#endif
+
+- (void)start {
+#if DEBUG
+ assert(0 && "Must be implemented by FIRCLSURLSessionTask subclasses");
+#endif
+}
+
+- (void)cancel {
+#if DEBUG
+ assert(0 && "Must be implemented by FIRCLSURLSessionTask subclasses");
+#endif
+}
+
+- (void)resume {
+}
+
+- (void)cleanup {
+}
+
+@end
+
+#else
+
+INJECT_STRIP_SYMBOL(clsurlsessiontask)
+
+#endif
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionTask_PrivateMethods.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionTask_PrivateMethods.h
new file mode 100644
index 000000000..784b3a3ce
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionTask_PrivateMethods.h
@@ -0,0 +1,55 @@
+// Copyright 2019 Google
+//
+// 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 "FIRCLSURLSessionAvailability.h"
+
+#if FIRCLSURLSESSION_REQUIRED
+
+#import
+
+@protocol FIRCLSURLSessionTaskDelegate;
+
+@interface FIRCLSURLSessionTask ()
+
++ (instancetype)task;
+
+@property(nonatomic, assign) id delegate;
+
+@property(nonatomic, copy) NSURLRequest *originalRequest;
+@property(nonatomic, copy) NSURLRequest *currentRequest;
+@property(nonatomic, copy) NSURLResponse *response;
+
+@property(nonatomic, readonly) dispatch_queue_t queue;
+@property(nonatomic, assign) BOOL invokesDelegate;
+
+- (void)cancel;
+
+@property(nonatomic, copy) NSError *error;
+
+- (void)cleanup;
+
+@end
+
+@protocol FIRCLSURLSessionTaskDelegate
+@required
+
+- (NSURLRequest *)task:(FIRCLSURLSessionTask *)task
+ willPerformHTTPRedirection:(NSHTTPURLResponse *)response
+ newRequest:(NSURLRequest *)request;
+
+- (void)task:(FIRCLSURLSessionTask *)task didCompleteWithError:(NSError *)error;
+
+@end
+
+#endif
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionUploadTask.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionUploadTask.h
new file mode 100644
index 000000000..6c5ed8b4b
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionUploadTask.h
@@ -0,0 +1,25 @@
+// Copyright 2019 Google
+//
+// 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 "FIRCLSURLSessionAvailability.h"
+
+#if FIRCLSURLSESSION_REQUIRED
+
+#import "FIRCLSURLSessionDataTask.h"
+
+@interface FIRCLSURLSessionUploadTask : FIRCLSURLSessionDataTask
+
+@end
+
+#endif
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionUploadTask.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionUploadTask.m
new file mode 100644
index 000000000..df3df8382
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionUploadTask.m
@@ -0,0 +1,28 @@
+// Copyright 2019 Google
+//
+// 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 "FIRCLSURLSessionAvailability.h"
+
+#if FIRCLSURLSESSION_REQUIRED
+#import "FIRCLSURLSessionUploadTask.h"
+
+@implementation FIRCLSURLSessionUploadTask
+
+@end
+
+#else
+
+INJECT_STRIP_SYMBOL(clsurlsessionuploadtask)
+
+#endif
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSUserDefaults/FIRCLSUserDefaults.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSUserDefaults/FIRCLSUserDefaults.h
new file mode 100644
index 000000000..6df153268
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSUserDefaults/FIRCLSUserDefaults.h
@@ -0,0 +1,42 @@
+// Copyright 2019 Google
+//
+// 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
+
+extern NSString *const FIRCLSUserDefaultsPathComponent;
+
+@interface FIRCLSUserDefaults : NSObject
+
++ (instancetype)standardUserDefaults;
+
+- (id)objectForKey:(NSString *)key;
+- (NSString *)stringForKey:(NSString *)key;
+- (BOOL)boolForKey:(NSString *)key;
+- (NSInteger)integerForKey:(NSString *)key;
+
+- (void)setObject:(id)object forKey:(NSString *)key;
+- (void)setString:(NSString *)string forKey:(NSString *)key;
+- (void)setBool:(BOOL)boolean forKey:(NSString *)key;
+- (void)setInteger:(NSInteger)integer forKey:(NSString *)key;
+
+- (void)removeObjectForKey:(NSString *)key;
+- (void)removeAllObjects;
+
+- (NSDictionary *)dictionaryRepresentation;
+
+- (void)migrateFromNSUserDefaults:(NSArray *)keysToMigrate;
+- (id)objectForKeyByMigratingFromNSUserDefaults:(NSString *)keyToMigrateOrNil;
+- (void)synchronize;
+
+@end
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSUserDefaults/FIRCLSUserDefaults.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSUserDefaults/FIRCLSUserDefaults.m
new file mode 100644
index 000000000..244dbe169
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSUserDefaults/FIRCLSUserDefaults.m
@@ -0,0 +1,372 @@
+// Copyright 2019 Google
+//
+// 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 "FIRCLSUserDefaults.h"
+
+#import "FIRCLSApplication.h"
+#import "FIRCLSLogger.h"
+
+#define CLS_USER_DEFAULTS_SERIAL_DISPATCH_QUEUE "com.crashlytics.CLSUserDefaults.access"
+#define CLS_USER_DEFAULTS_SYNC_QUEUE "com.crashlytics.CLSUserDefaults.io"
+
+#define CLS_TARGET_CAN_WRITE_TO_DISK !TARGET_OS_TV
+
+// These values are required to stay the same between versions of the SDK so
+// that when end users upgrade, their crashlytics data is still saved on disk.
+#if !CLS_TARGET_CAN_WRITE_TO_DISK
+static NSString *const FIRCLSNSUserDefaultsDataDictionaryKey =
+ @"com.crashlytics.CLSUserDefaults.user-default-key.data-dictionary";
+#endif
+
+NSString *const FIRCLSUserDefaultsPathComponent = @"CLSUserDefaults";
+
+/**
+ * This class is an isolated re-implementation of NSUserDefaults which isolates our storage
+ * from that of our customers. This solves a number of issues we have seen in production, firstly
+ * that customers often delete or clear NSUserDefaults, unintentionally deleting our data.
+ * Further, we have seen thread safety issues in production with NSUserDefaults, as well as a number
+ * of bugs related to accessing NSUserDefaults before the device has been unlocked due to the
+ * NSFileProtection of NSUserDefaults.
+ */
+@interface FIRCLSUserDefaults ()
+@property(nonatomic, readwrite) BOOL synchronizeWroteToDisk;
+#if CLS_TARGET_CAN_WRITE_TO_DISK
+@property(nonatomic, copy, readonly) NSURL *directoryURL;
+@property(nonatomic, copy, readonly) NSURL *fileURL;
+#endif
+@property(nonatomic, copy, readonly)
+ NSDictionary *persistedDataDictionary; // May only be safely accessed on the DictionaryQueue
+@property(nonatomic, copy, readonly)
+ NSMutableDictionary *dataDictionary; // May only be safely accessed on the DictionaryQueue
+@property(nonatomic, readonly) dispatch_queue_t
+ serialDictionaryQueue; // The queue on which all access to the dataDictionary occurs.
+@property(nonatomic, readonly)
+ dispatch_queue_t synchronizationQueue; // The queue on which all disk access occurs.
+
+@end
+
+@implementation FIRCLSUserDefaults
+
+#pragma mark - singleton
+
++ (instancetype)standardUserDefaults {
+ static FIRCLSUserDefaults *standardUserDefaults = nil;
+ static dispatch_once_t onceToken;
+
+ dispatch_once(&onceToken, ^{
+ standardUserDefaults = [[super allocWithZone:NULL] init];
+ });
+
+ return standardUserDefaults;
+}
+
+- (id)copyWithZone:(NSZone *)zone {
+ return self;
+}
+
+- (id)init {
+ if (self = [super init]) {
+ _serialDictionaryQueue =
+ dispatch_queue_create(CLS_USER_DEFAULTS_SERIAL_DISPATCH_QUEUE, DISPATCH_QUEUE_SERIAL);
+ _synchronizationQueue =
+ dispatch_queue_create(CLS_USER_DEFAULTS_SYNC_QUEUE, DISPATCH_QUEUE_SERIAL);
+
+ dispatch_sync(self.serialDictionaryQueue, ^{
+#if CLS_TARGET_CAN_WRITE_TO_DISK
+ self->_directoryURL = [self generateDirectoryURL];
+ self->_fileURL = [[self->_directoryURL
+ URLByAppendingPathComponent:FIRCLSUserDefaultsPathComponent
+ isDirectory:NO] URLByAppendingPathExtension:@"plist"];
+#endif
+ self->_persistedDataDictionary = [self loadDefaults];
+ if (!self->_persistedDataDictionary) {
+ self->_persistedDataDictionary = [NSDictionary dictionary];
+ }
+ self->_dataDictionary = [self->_persistedDataDictionary mutableCopy];
+ });
+ }
+ return self;
+}
+
+- (NSURL *)generateDirectoryURL {
+ NSURL *directoryBaseURL =
+ [[[NSFileManager defaultManager] URLsForDirectory:NSApplicationSupportDirectory
+ inDomains:NSUserDomainMask] lastObject];
+ NSString *hostAppBundleIdentifier = [self getEscapedAppBundleIdentifier];
+ return [self generateDirectoryURLForBaseURL:directoryBaseURL
+ hostAppBundleIdentifier:hostAppBundleIdentifier];
+}
+
+- (NSURL *)generateDirectoryURLForBaseURL:(NSURL *)directoryBaseURL
+ hostAppBundleIdentifier:(NSString *)hostAppBundleIdentifier {
+ NSURL *directoryURL = directoryBaseURL;
+ // On iOS NSApplicationSupportDirectory is contained in the app's bundle. On OSX, it is not (it is
+ // ~/Library/Application Support/). On OSX we create a directory
+ // ~/Library/Application Support//com.crashlytics/ for storing files.
+ // Mac App Store review process requires files to be written to
+ // ~/Library/Application Support//,
+ // so ~/Library/Application Support/com.crashlytics// cannot be used.
+#if !TARGET_OS_SIMULATOR && !TARGET_OS_EMBEDDED
+ if (hostAppBundleIdentifier) {
+ directoryURL = [directoryURL URLByAppendingPathComponent:hostAppBundleIdentifier];
+ }
+#endif
+ directoryURL = [directoryURL URLByAppendingPathComponent:@"com.crashlytics"];
+ return directoryURL;
+}
+
+- (NSString *)getEscapedAppBundleIdentifier {
+ return FIRCLSApplicationGetBundleIdentifier();
+}
+
+#pragma mark - fetch object
+
+- (id)objectForKey:(NSString *)key {
+ __block id result;
+
+ dispatch_sync(self.serialDictionaryQueue, ^{
+ result = [self->_dataDictionary objectForKey:key];
+ });
+
+ return result;
+}
+
+- (NSString *)stringForKey:(NSString *)key {
+ id result = [self objectForKey:key];
+
+ if (result != nil && [result isKindOfClass:[NSString class]]) {
+ return (NSString *)result;
+ } else {
+ return nil;
+ }
+}
+
+- (BOOL)boolForKey:(NSString *)key {
+ id result = [self objectForKey:key];
+ if (result != nil && [result isKindOfClass:[NSNumber class]]) {
+ return [(NSNumber *)result boolValue];
+ } else {
+ return NO;
+ }
+}
+
+// Defaults to 0
+- (NSInteger)integerForKey:(NSString *)key {
+ id result = [self objectForKey:key];
+ if (result && [result isKindOfClass:[NSNumber class]]) {
+ return [(NSNumber *)result integerValue];
+ } else {
+ return 0;
+ }
+}
+
+#pragma mark - set object
+
+- (void)setObject:(id)object forKey:(NSString *)key {
+ dispatch_sync(self.serialDictionaryQueue, ^{
+ [self->_dataDictionary setValue:object forKey:key];
+ });
+}
+
+- (void)setString:(NSString *)string forKey:(NSString *)key {
+ [self setObject:string forKey:key];
+}
+
+- (void)setBool:(BOOL)boolean forKey:(NSString *)key {
+ [self setObject:[NSNumber numberWithBool:boolean] forKey:key];
+}
+
+- (void)setInteger:(NSInteger)integer forKey:(NSString *)key {
+ [self setObject:[NSNumber numberWithInteger:integer] forKey:key];
+}
+
+#pragma mark - removing objects
+
+- (void)removeObjectForKey:(NSString *)key {
+ dispatch_sync(self.serialDictionaryQueue, ^{
+ [self->_dataDictionary removeObjectForKey:key];
+ });
+}
+
+- (void)removeAllObjects {
+ dispatch_sync(self.serialDictionaryQueue, ^{
+ [self->_dataDictionary removeAllObjects];
+ });
+}
+
+#pragma mark - dictionary representation
+
+- (NSDictionary *)dictionaryRepresentation {
+ __block NSDictionary *result;
+
+ dispatch_sync(self.serialDictionaryQueue, ^{
+ result = [self->_dataDictionary copy];
+ });
+
+ return result;
+}
+
+#pragma mark - synchronization
+
+- (void)synchronize {
+ __block BOOL dirty = NO;
+
+ // only write to the disk if the dictionaries have changed
+ dispatch_sync(self.serialDictionaryQueue, ^{
+ dirty = ![self->_persistedDataDictionary isEqualToDictionary:self->_dataDictionary];
+ });
+
+ _synchronizeWroteToDisk = dirty;
+ if (!dirty) {
+ return;
+ }
+
+ NSDictionary *state = [self dictionaryRepresentation];
+ dispatch_sync(self.synchronizationQueue, ^{
+#if CLS_TARGET_CAN_WRITE_TO_DISK
+ BOOL isDirectory = NO;
+ BOOL pathExists = [[NSFileManager defaultManager] fileExistsAtPath:[self->_directoryURL path]
+ isDirectory:&isDirectory];
+
+ if (!pathExists) {
+ NSError *error;
+ if (![[NSFileManager defaultManager] createDirectoryAtURL:self->_directoryURL
+ withIntermediateDirectories:YES
+ attributes:nil
+ error:&error]) {
+ FIRCLSErrorLog(@"Failed to create directory with error: %@", error);
+ }
+ }
+
+ if (![state writeToURL:self->_fileURL atomically:YES]) {
+ FIRCLSErrorLog(@"Unable to open file for writing at path %@", [self->_fileURL path]);
+ } else {
+#if TARGET_OS_IOS
+ // We disable NSFileProtection on our file in order to allow us to access it even if the
+ // device is locked.
+ NSError *error;
+ if (![[NSFileManager defaultManager]
+ setAttributes:@{NSFileProtectionKey : NSFileProtectionNone}
+ ofItemAtPath:[self->_fileURL path]
+ error:&error]) {
+ FIRCLSErrorLog(@"Error setting NSFileProtection: %@", error);
+ }
+#endif
+ }
+#else
+ NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
+ [defaults setObject:state forKey:FIRCLSNSUserDefaultsDataDictionaryKey];
+ [defaults synchronize];
+#endif
+ });
+
+ dispatch_sync(self.serialDictionaryQueue, ^{
+ self->_persistedDataDictionary = [self->_dataDictionary copy];
+ });
+}
+
+- (NSDictionary *)loadDefaults {
+ __block NSDictionary *state = nil;
+ dispatch_sync(self.synchronizationQueue, ^{
+#if CLS_TARGET_CAN_WRITE_TO_DISK
+ BOOL isDirectory = NO;
+ BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:[self->_fileURL path]
+ isDirectory:&isDirectory];
+
+ if (fileExists && !isDirectory) {
+ state = [NSDictionary dictionaryWithContentsOfURL:self->_fileURL];
+ if (nil == state) {
+ FIRCLSErrorLog(@"Failed to read existing UserDefaults file");
+ }
+ } else if (!fileExists) {
+ // No file found. This is expected on first launch.
+ } else if (fileExists && isDirectory) {
+ FIRCLSErrorLog(@"Found directory where file expected. Removing conflicting directory");
+
+ NSError *error;
+ if (![[NSFileManager defaultManager] removeItemAtURL:self->_fileURL error:&error]) {
+ FIRCLSErrorLog(@"Error removing conflicting directory: %@", error);
+ }
+ }
+#else
+ state = [[NSUserDefaults standardUserDefaults] dictionaryForKey:FIRCLSNSUserDefaultsDataDictionaryKey];
+#endif
+ });
+ return state;
+}
+
+#pragma mark - migration
+
+// This method migrates all keys specified from NSUserDefaults to FIRCLSUserDefaults
+// To do so, we copy all known key-value pairs into FIRCLSUserDefaults, synchronize it, then
+// remove the keys from NSUserDefaults and synchronize it.
+- (void)migrateFromNSUserDefaults:(NSArray *)keysToMigrate {
+ BOOL didFindKeys = NO;
+
+ // First, copy all of the keysToMigrate which are stored NSUserDefaults
+ for (NSString *key in keysToMigrate) {
+ id oldValue = [[NSUserDefaults standardUserDefaults] objectForKey:(NSString *)key];
+ if (nil != oldValue) {
+ didFindKeys = YES;
+ [self setObject:oldValue forKey:key];
+ }
+ }
+
+ if (didFindKeys) {
+ // First synchronize FIRCLSUserDefaults such that all keysToMigrate in NSUserDefaults are stored
+ // in FIRCLSUserDefaults. At this point, data is duplicated.
+ [[FIRCLSUserDefaults standardUserDefaults] synchronize];
+
+ for (NSString *key in keysToMigrate) {
+ [[NSUserDefaults standardUserDefaults] removeObjectForKey:(NSString *)key];
+ }
+
+ // This should be our last interaction with NSUserDefaults. All data is migrated into
+ // FIRCLSUserDefaults
+ [[NSUserDefaults standardUserDefaults] synchronize];
+ }
+}
+
+// This method first queries FIRCLSUserDefaults to see if the key exist, and upon failure,
+// searches for the key in NSUserDefaults, and migrates it if found.
+- (id)objectForKeyByMigratingFromNSUserDefaults:(NSString *)keyToMigrateOrNil {
+ if (!keyToMigrateOrNil) {
+ return nil;
+ }
+
+ id clsUserDefaultsValue = [self objectForKey:keyToMigrateOrNil];
+ if (clsUserDefaultsValue != nil) {
+ return clsUserDefaultsValue; // if the value exists in FIRCLSUserDefaults, return it.
+ }
+
+ id oldNSUserDefaultsValue =
+ [[NSUserDefaults standardUserDefaults] objectForKey:keyToMigrateOrNil];
+ if (!oldNSUserDefaultsValue) {
+ return nil; // if the value also does not exist in NSUserDefaults, return nil.
+ }
+
+ // Otherwise, the key exists in NSUserDefaults. Migrate it to FIRCLSUserDefaults
+ // and then return the associated value.
+
+ // First store it in FIRCLSUserDefaults so in the event of a crash, data is not lost.
+ [self setObject:oldNSUserDefaultsValue forKey:keyToMigrateOrNil];
+ [[FIRCLSUserDefaults standardUserDefaults] synchronize];
+
+ [[NSUserDefaults standardUserDefaults] removeObjectForKey:keyToMigrateOrNil];
+ [[NSUserDefaults standardUserDefaults] synchronize];
+
+ return oldNSUserDefaultsValue;
+}
+
+@end
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSUserDefaults/FIRCLSUserDefaults_private.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSUserDefaults/FIRCLSUserDefaults_private.h
new file mode 100644
index 000000000..775bca24a
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSUserDefaults/FIRCLSUserDefaults_private.h
@@ -0,0 +1,23 @@
+// Copyright 2019 Google
+//
+// 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
+#import "FIRCLSUserDefaults.h"
+
+@interface FIRCLSUserDefaults (Private)
+- (BOOL)synchronizeWroteToDisk;
+- (NSDictionary *)loadDefaults;
+- (NSURL *)generateDirectoryURLForBaseURL:(NSURL *)directoryBaseURL
+ hostAppBundleIdentifier:(NSString *)hostAppBundleIdentifer;
+@end
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCrashlytics.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCrashlytics.m
new file mode 100644
index 000000000..16e7a2f44
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCrashlytics.m
@@ -0,0 +1,318 @@
+// Copyright 2019 Google
+//
+// 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.
+
+#include
+
+#if __has_include()
+#import
+#else
+#import "FBLPromises.h"
+#endif
+
+#import "FIRCLSApplicationIdentifierModel.h"
+#include "FIRCLSCrashedMarkerFile.h"
+#import "FIRCLSDataCollectionArbiter.h"
+#import "FIRCLSDefines.h"
+#include "FIRCLSException.h"
+#import "FIRCLSFileManager.h"
+#include "FIRCLSGlobals.h"
+#import "FIRCLSHost.h"
+#include "FIRCLSProfiling.h"
+#import "FIRCLSReport_Private.h"
+#import "FIRCLSSettings.h"
+#import "FIRCLSUserDefaults.h"
+#include "FIRCLSUserLogging.h"
+#include "FIRCLSUtility.h"
+
+#import "FIRCLSByteUtility.h"
+#import "FIRCLSFABHost.h"
+#import "FIRCLSLogger.h"
+
+#import "FIRCLSReportManager.h"
+
+#import
+#import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h"
+#import "Interop/Analytics/Public/FIRAnalyticsInterop.h"
+
+#import
+#import
+
+#if TARGET_OS_IPHONE
+#import
+#endif
+
+FIRCLSContext _firclsContext;
+dispatch_queue_t _firclsLoggingQueue;
+dispatch_queue_t _firclsBinaryImageQueue;
+dispatch_queue_t _firclsExceptionQueue;
+
+static atomic_bool _hasInitializedInstance;
+
+NSString *const FIRCLSGoogleTransportMappingID = @"1206";
+
+/// Empty protocol to register with FirebaseCore's component system.
+@protocol FIRCrashlyticsInstanceProvider
+@end
+
+@interface FIRCrashlytics ()
+
+@property(nonatomic) BOOL didPreviouslyCrash;
+@property(nonatomic, copy) NSString *googleAppID;
+@property(nonatomic) FIRCLSDataCollectionArbiter *dataArbiter;
+@property(nonatomic) FIRCLSFileManager *fileManager;
+@property(nonatomic) FIRCLSReportManager *reportManager;
+@property(nonatomic) GDTCORTransport *googleTransport;
+
+@end
+
+@implementation FIRCrashlytics
+
+#pragma mark - Singleton Support
+
+- (instancetype)initWithApp:(FIRApp *)app
+ appInfo:(NSDictionary *)appInfo
+ installations:(FIRInstallations *)installations
+ analytics:(id)analytics {
+ self = [super init];
+
+ if (self) {
+ bool expectedCalled = NO;
+ if (!atomic_compare_exchange_strong(&_hasInitializedInstance, &expectedCalled, YES)) {
+ FIRCLSErrorLog(@"Cannot instantiate more than one instance of Crashlytics.");
+ return nil;
+ }
+
+ FIRCLSProfileMark mark = FIRCLSProfilingStart();
+
+ NSLog(@"[Firebase/Crashlytics] Version %@", @CLS_SDK_DISPLAY_VERSION);
+
+ FIRCLSDeveloperLog("Crashlytics", @"Running on %@, %@ (%@)", FIRCLSHostModelInfo(),
+ FIRCLSHostOSDisplayVersion(), FIRCLSHostOSBuildVersion());
+
+ _googleTransport = [[GDTCORTransport alloc] initWithMappingID:FIRCLSGoogleTransportMappingID
+ transformers:nil
+ target:kGDTCORTargetCSH];
+
+ _fileManager = [[FIRCLSFileManager alloc] init];
+ _googleAppID = app.options.googleAppID;
+ _dataArbiter = [[FIRCLSDataCollectionArbiter alloc] initWithApp:app withAppInfo:appInfo];
+
+ FIRCLSApplicationIdentifierModel *appModel = [[FIRCLSApplicationIdentifierModel alloc] init];
+ FIRCLSSettings *settings = [[FIRCLSSettings alloc] initWithFileManager:_fileManager
+ appIDModel:appModel];
+
+ _reportManager = [[FIRCLSReportManager alloc] initWithFileManager:_fileManager
+ installations:installations
+ analytics:analytics
+ googleAppID:_googleAppID
+ dataArbiter:_dataArbiter
+ googleTransport:_googleTransport
+ appIDModel:appModel
+ settings:settings];
+
+ // Process did crash during previous execution
+ NSString *crashedMarkerFileName = [NSString stringWithUTF8String:FIRCLSCrashedMarkerFileName];
+ NSString *crashedMarkerFileFullPath =
+ [[_fileManager rootPath] stringByAppendingPathComponent:crashedMarkerFileName];
+ _didPreviouslyCrash = [_fileManager fileExistsAtPath:crashedMarkerFileFullPath];
+
+ if (_didPreviouslyCrash) {
+ // Delete the crash file marker in the background ensure start up is as fast as possible
+ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
+ [self.fileManager removeItemAtPath:crashedMarkerFileFullPath];
+ });
+ }
+
+ [[[_reportManager startWithProfilingMark:mark] then:^id _Nullable(NSNumber *_Nullable value) {
+ if (![value boolValue]) {
+ FIRCLSErrorLog(@"Crash reporting could not be initialized");
+ }
+ return value;
+ }] catch:^void(NSError *error) {
+ FIRCLSErrorLog(@"Crash reporting failed to initialize with error: %@", error);
+ }];
+ }
+
+ return self;
+}
+
++ (void)load {
+ [FIRApp registerInternalLibrary:(Class)self
+ withName:@"firebase-crashlytics"
+ withVersion:@CLS_SDK_DISPLAY_VERSION];
+}
+
++ (NSArray *)componentsToRegister {
+ FIRDependency *analyticsDep =
+ [FIRDependency dependencyWithProtocol:@protocol(FIRAnalyticsInterop)];
+
+ FIRComponentCreationBlock creationBlock =
+ ^id _Nullable(FIRComponentContainer *container, BOOL *isCacheable) {
+ if (!container.app.isDefaultApp) {
+ FIRCLSErrorLog(@"Crashlytics must be used with the default Firebase app.");
+ return nil;
+ }
+
+ id analytics = FIR_COMPONENT(FIRAnalyticsInterop, container);
+
+ FIRInstallations *installations = [FIRInstallations installationsWithApp:container.app];
+
+ *isCacheable = YES;
+
+ return [[FIRCrashlytics alloc] initWithApp:container.app
+ appInfo:NSBundle.mainBundle.infoDictionary
+ installations:installations
+ analytics:analytics];
+ };
+
+ FIRComponent *component =
+ [FIRComponent componentWithProtocol:@protocol(FIRCrashlyticsInstanceProvider)
+ instantiationTiming:FIRInstantiationTimingEagerInDefaultApp
+ dependencies:@[ analyticsDep ]
+ creationBlock:creationBlock];
+ return @[ component ];
+}
+
++ (instancetype)crashlytics {
+ // The container will return the same instance since isCacheable is set
+
+ FIRApp *defaultApp = [FIRApp defaultApp]; // Missing configure will be logged here.
+
+ // Get the instance from the `FIRApp`'s container. This will create a new instance the
+ // first time it is called, and since `isCacheable` is set in the component creation
+ // block, it will return the existing instance on subsequent calls.
+ id instance =
+ FIR_COMPONENT(FIRCrashlyticsInstanceProvider, defaultApp.container);
+
+ // In the component creation block, we return an instance of `FIRCrashlytics`. Cast it and
+ // return it.
+ return (FIRCrashlytics *)instance;
+}
+
+- (void)setCrashlyticsCollectionEnabled:(BOOL)enabled {
+ [self.dataArbiter setCrashlyticsCollectionEnabled:enabled];
+}
+
+- (BOOL)isCrashlyticsCollectionEnabled {
+ return [self.dataArbiter isCrashlyticsCollectionEnabled];
+}
+
+#pragma mark - API: didCrashDuringPreviousExecution
+
+- (BOOL)didCrashDuringPreviousExecution {
+ return self.didPreviouslyCrash;
+}
+
+- (void)processDidCrashDuringPreviousExecution {
+ NSString *crashedMarkerFileName = [NSString stringWithUTF8String:FIRCLSCrashedMarkerFileName];
+ NSString *crashedMarkerFileFullPath =
+ [[self.fileManager rootPath] stringByAppendingPathComponent:crashedMarkerFileName];
+ self.didPreviouslyCrash = [self.fileManager fileExistsAtPath:crashedMarkerFileFullPath];
+
+ if (self.didPreviouslyCrash) {
+ // Delete the crash file marker in the background ensure start up is as fast as possible
+ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
+ [self.fileManager removeItemAtPath:crashedMarkerFileFullPath];
+ });
+ }
+}
+
+#pragma mark - API: Logging
+- (void)log:(NSString *)msg {
+ FIRCLSLog(@"%@", msg);
+}
+
+- (void)logWithFormat:(NSString *)format, ... {
+ va_list args;
+ va_start(args, format);
+ [self logWithFormat:format arguments:args];
+ va_end(args);
+}
+
+- (void)logWithFormat:(NSString *)format arguments:(va_list)args {
+ [self log:[[NSString alloc] initWithFormat:format arguments:args]];
+}
+
+#pragma mark - API: Accessors
+
+- (void)checkForUnsentReportsWithCompletion:(void (^)(BOOL))completion {
+ [[self.reportManager checkForUnsentReports] then:^id _Nullable(NSNumber *_Nullable value) {
+ completion([value boolValue]);
+ return nil;
+ }];
+}
+
+- (void)sendUnsentReports {
+ [self.reportManager sendUnsentReports];
+}
+
+- (void)deleteUnsentReports {
+ [self.reportManager deleteUnsentReports];
+}
+
+#pragma mark - API: setUserID
+- (void)setUserID:(NSString *)userID {
+ FIRCLSUserLoggingRecordInternalKeyValue(FIRCLSUserIdentifierKey, userID);
+}
+
+#pragma mark - API: setCustomValue
+
+- (void)setCustomValue:(id)value forKey:(NSString *)key {
+ FIRCLSUserLoggingRecordUserKeyValue(key, value);
+}
+
+#pragma mark - API: Development Platform
+// These two methods are depercated by our own API, so
+// its ok to implement them
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-implementations"
++ (void)setDevelopmentPlatformName:(NSString *)name {
+ [[self crashlytics] setDevelopmentPlatformName:name];
+}
+
++ (void)setDevelopmentPlatformVersion:(NSString *)version {
+ [[self crashlytics] setDevelopmentPlatformVersion:version];
+}
+#pragma clang diagnostic pop
+
+- (NSString *)developmentPlatformName {
+ FIRCLSErrorLog(@"developmentPlatformName is write-only");
+ return nil;
+}
+
+- (void)setDevelopmentPlatformName:(NSString *)developmentPlatformName {
+ FIRCLSUserLoggingRecordInternalKeyValue(FIRCLSDevelopmentPlatformNameKey,
+ developmentPlatformName);
+}
+
+- (NSString *)developmentPlatformVersion {
+ FIRCLSErrorLog(@"developmentPlatformVersion is write-only");
+ return nil;
+}
+
+- (void)setDevelopmentPlatformVersion:(NSString *)developmentPlatformVersion {
+ FIRCLSUserLoggingRecordInternalKeyValue(FIRCLSDevelopmentPlatformVersionKey,
+ developmentPlatformVersion);
+}
+
+#pragma mark - API: Errors and Exceptions
+- (void)recordError:(NSError *)error {
+ FIRCLSUserLoggingRecordError(error, nil);
+}
+
+- (void)recordExceptionModel:(FIRExceptionModel *)exceptionModel {
+ FIRCLSExceptionRecordModel(exceptionModel);
+}
+
+@end
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRExceptionModel.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRExceptionModel.m
new file mode 100644
index 000000000..f0c4697a8
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRExceptionModel.m
@@ -0,0 +1,42 @@
+// Copyright 2020 Google
+//
+// 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 "FIRExceptionModel.h"
+
+@interface FIRExceptionModel ()
+
+@property(nonatomic, copy) NSString *name;
+@property(nonatomic, copy) NSString *reason;
+
+@end
+
+@implementation FIRExceptionModel
+
+- (instancetype)initWithName:(NSString *)name reason:(NSString *)reason {
+ self = [super init];
+ if (!self) {
+ return nil;
+ }
+
+ _name = [name copy];
+ _reason = [reason copy];
+
+ return self;
+}
+
++ (instancetype)exceptionModelWithName:(NSString *)name reason:(NSString *)reason {
+ return [[FIRExceptionModel alloc] initWithName:name reason:reason];
+}
+
+@end
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRStackFrame.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRStackFrame.m
new file mode 100644
index 000000000..304491465
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRStackFrame.m
@@ -0,0 +1,94 @@
+// Copyright 2020 Google
+//
+// 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 "FIRStackFrame_Private.h"
+
+@interface FIRStackFrame ()
+
+@property(nonatomic, copy, nullable) NSString *symbol;
+@property(nonatomic, copy, nullable) NSString *rawSymbol;
+@property(nonatomic, copy, nullable) NSString *library;
+@property(nonatomic, copy, nullable) NSString *fileName;
+@property(nonatomic, assign) uint32_t lineNumber;
+@property(nonatomic, assign) uint64_t offset;
+@property(nonatomic, assign) uint64_t address;
+
+@property(nonatomic, assign) BOOL isSymbolicated;
+
+@end
+
+@implementation FIRStackFrame
+
+#pragma mark - Public Methods
+
+- (instancetype)initWithSymbol:(NSString *)symbol file:(NSString *)file line:(NSInteger)line {
+ self = [super init];
+ if (!self) {
+ return nil;
+ }
+
+ _symbol = [symbol copy];
+ _fileName = [file copy];
+ _lineNumber = (uint32_t)line;
+
+ _isSymbolicated = true;
+
+ return self;
+}
+
++ (instancetype)stackFrameWithSymbol:(NSString *)symbol file:(NSString *)file line:(NSInteger)line {
+ return [[FIRStackFrame alloc] initWithSymbol:symbol file:file line:line];
+}
+
+#pragma mark - Internal Methods
+
++ (instancetype)stackFrame {
+ return [[self alloc] init];
+}
+
++ (instancetype)stackFrameWithAddress:(NSUInteger)address {
+ FIRStackFrame *frame = [self stackFrame];
+
+ [frame setAddress:address];
+
+ return frame;
+}
+
++ (instancetype)stackFrameWithSymbol:(NSString *)symbol {
+ FIRStackFrame *frame = [self stackFrame];
+
+ frame.symbol = symbol;
+ frame.rawSymbol = symbol;
+
+ return frame;
+}
+
+#pragma mark - Overrides
+
+- (NSString *)description {
+ if (self.isSymbolicated) {
+ return [NSString
+ stringWithFormat:@"{%@ - %@:%u}", [self fileName], [self symbol], [self lineNumber]];
+ }
+
+ if (self.fileName) {
+ return [NSString stringWithFormat:@"{[0x%llx] %@ - %@:%u}", [self address], [self fileName],
+ [self symbol], [self lineNumber]];
+ }
+
+ return [NSString
+ stringWithFormat:@"{[0x%llx + %u] %@}", [self address], [self lineNumber], [self symbol]];
+}
+
+@end
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSException.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSException.h
new file mode 100644
index 000000000..61dac77c3
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSException.h
@@ -0,0 +1,73 @@
+// Copyright 2019 Google
+//
+// 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.
+
+#pragma once
+
+#include
+#include
+
+#ifdef __OBJC__
+#import
+@class FIRStackFrame;
+@class FIRExceptionModel;
+#endif
+
+#define CLS_EXCEPTION_STRING_LENGTH_MAX (1024 * 16)
+
+typedef enum {
+ FIRCLSExceptionTypeUnknown = 0,
+ FIRCLSExceptionTypeObjectiveC = 1,
+ FIRCLSExceptionTypeCpp = 2,
+ // 3 was FIRCLSExceptionTypeJavascript
+ // Keeping these numbers the same just to be safe
+ FIRCLSExceptionTypeCustom = 4
+} FIRCLSExceptionType;
+
+typedef struct {
+ const char* path;
+
+ void (*originalTerminateHandler)(void);
+
+#if !TARGET_OS_IPHONE
+ void* originalNSApplicationReportException;
+#endif
+
+ uint32_t maxCustomExceptions;
+} FIRCLSExceptionReadOnlyContext;
+
+typedef struct {
+ uint32_t customExceptionCount;
+} FIRCLSExceptionWritableContext;
+
+__BEGIN_DECLS
+
+void FIRCLSExceptionInitialize(FIRCLSExceptionReadOnlyContext* roContext,
+ FIRCLSExceptionWritableContext* rwContext,
+ void* delegate);
+void FIRCLSExceptionCheckHandlers(void* delegate);
+
+void FIRCLSExceptionRaiseTestObjCException(void) __attribute((noreturn));
+void FIRCLSExceptionRaiseTestCppException(void) __attribute((noreturn));
+
+#ifdef __OBJC__
+void FIRCLSExceptionRecordModel(FIRExceptionModel* exceptionModel);
+void FIRCLSExceptionRecordNSException(NSException* exception);
+void FIRCLSExceptionRecord(FIRCLSExceptionType type,
+ const char* name,
+ const char* reason,
+ NSArray* frames,
+ BOOL attemptDelivery);
+#endif
+
+__END_DECLS
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSException.mm b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSException.mm
new file mode 100644
index 000000000..6f2099045
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSException.mm
@@ -0,0 +1,410 @@
+// Copyright 2019 Google
+//
+// 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
+
+#include "FIRCLSException.h"
+
+#import "FIRExceptionModel_Private.h"
+#import "FIRStackFrame_Private.h"
+
+#include "FIRCLSApplication.h"
+#include "FIRCLSFile.h"
+#include "FIRCLSGlobals.h"
+#include "FIRCLSHandler.h"
+#import "FIRCLSLogger.h"
+#include "FIRCLSProcess.h"
+#import "FIRCLSUserLogging.h"
+#import "FIRCLSUtility.h"
+
+#include "FIRCLSDemangleOperation.h"
+#import "FIRCLSReportManager_Private.h"
+
+// C++/Objective-C exception handling
+#include
+#include
+#include
+#include
+
+#if !TARGET_OS_IPHONE
+#import
+#import
+#endif
+
+#pragma mark Prototypes
+static void FIRCLSTerminateHandler(void);
+#if !TARGET_OS_IPHONE
+void FIRCLSNSApplicationReportException(id self, SEL cmd, NSException *exception);
+
+typedef void (*NSApplicationReportExceptionFunction)(id, SEL, NSException *);
+
+static BOOL FIRCLSIsNSApplicationCrashOnExceptionsEnabled(void);
+static NSApplicationReportExceptionFunction FIRCLSOriginalNSExceptionReportExceptionFunction(void);
+static Method FIRCLSGetNSApplicationReportExceptionMethod(void);
+
+#endif
+
+#pragma mark - API
+void FIRCLSExceptionInitialize(FIRCLSExceptionReadOnlyContext *roContext,
+ FIRCLSExceptionWritableContext *rwContext,
+ void *delegate) {
+ if (!FIRCLSUnlinkIfExists(roContext->path)) {
+ FIRCLSSDKLog("Unable to reset the exception file %s\n", strerror(errno));
+ }
+
+ roContext->originalTerminateHandler = std::set_terminate(FIRCLSTerminateHandler);
+
+#if !TARGET_OS_IPHONE
+ // If FIRCLSApplicationSharedInstance is null, we don't need this
+ if (FIRCLSIsNSApplicationCrashOnExceptionsEnabled() && FIRCLSApplicationSharedInstance()) {
+ Method m = FIRCLSGetNSApplicationReportExceptionMethod();
+
+ roContext->originalNSApplicationReportException =
+ (void *)method_setImplementation(m, (IMP)FIRCLSNSApplicationReportException);
+ }
+#endif
+
+ rwContext->customExceptionCount = 0;
+}
+
+void FIRCLSExceptionRecordModel(FIRExceptionModel *exceptionModel) {
+ const char *name = [[exceptionModel.name copy] UTF8String];
+ const char *reason = [[exceptionModel.reason copy] UTF8String];
+
+ FIRCLSExceptionRecord(FIRCLSExceptionTypeCustom, name, reason, [exceptionModel.stackTrace copy],
+ NO);
+}
+
+void FIRCLSExceptionRecordNSException(NSException *exception) {
+ FIRCLSSDKLog("Recording an NSException\n");
+
+ NSArray *returnAddresses = [exception callStackReturnAddresses];
+
+ NSString *name = [exception name];
+ NSString *reason = [exception reason];
+
+ // It's tempting to try to make use of callStackSymbols here. But, the output
+ // of that function is not intended to be machine-readible. We could parse it,
+ // but that isn't really worthwhile, considering that address-based symbolication
+ // needs to work anyways.
+
+ // package our frames up into the appropriate format
+ NSMutableArray *frames = [NSMutableArray new];
+
+ for (NSNumber *address in returnAddresses) {
+ [frames addObject:[FIRStackFrame stackFrameWithAddress:[address unsignedIntegerValue]]];
+ }
+
+ FIRCLSExceptionRecord(FIRCLSExceptionTypeObjectiveC, [name UTF8String], [reason UTF8String],
+ frames, YES);
+}
+
+static void FIRCLSExceptionRecordFrame(FIRCLSFile *file, FIRStackFrame *frame) {
+ FIRCLSFileWriteHashStart(file);
+
+ FIRCLSFileWriteHashEntryUint64(file, "pc", [frame address]);
+
+ NSString *string = [frame symbol];
+ if (string) {
+ FIRCLSFileWriteHashEntryHexEncodedString(file, "symbol", [string UTF8String]);
+ }
+
+ FIRCLSFileWriteHashEntryUint64(file, "offset", [frame offset]);
+
+ string = [frame library];
+ if (string) {
+ FIRCLSFileWriteHashEntryHexEncodedString(file, "library", [string UTF8String]);
+ }
+
+ string = [frame fileName];
+ if (string) {
+ FIRCLSFileWriteHashEntryHexEncodedString(file, "file", [string UTF8String]);
+ }
+
+ FIRCLSFileWriteHashEntryUint64(file, "line", [frame lineNumber]);
+
+ FIRCLSFileWriteHashEnd(file);
+}
+
+static bool FIRCLSExceptionIsNative(FIRCLSExceptionType type) {
+ return type == FIRCLSExceptionTypeObjectiveC || type == FIRCLSExceptionTypeCpp;
+}
+
+static const char *FIRCLSExceptionNameForType(FIRCLSExceptionType type) {
+ switch (type) {
+ case FIRCLSExceptionTypeObjectiveC:
+ return "objective-c";
+ case FIRCLSExceptionTypeCpp:
+ return "c++";
+ case FIRCLSExceptionTypeCustom:
+ return "custom";
+ default:
+ break;
+ }
+
+ return "unknown";
+}
+
+void FIRCLSExceptionWrite(FIRCLSFile *file,
+ FIRCLSExceptionType type,
+ const char *name,
+ const char *reason,
+ NSArray *frames) {
+ FIRCLSFileWriteSectionStart(file, "exception");
+
+ FIRCLSFileWriteHashStart(file);
+
+ FIRCLSFileWriteHashEntryString(file, "type", FIRCLSExceptionNameForType(type));
+ FIRCLSFileWriteHashEntryHexEncodedString(file, "name", name);
+ FIRCLSFileWriteHashEntryHexEncodedString(file, "reason", reason);
+ FIRCLSFileWriteHashEntryUint64(file, "time", time(NULL));
+
+ if ([frames count]) {
+ FIRCLSFileWriteHashKey(file, "frames");
+ FIRCLSFileWriteArrayStart(file);
+
+ for (FIRStackFrame *frame in frames) {
+ FIRCLSExceptionRecordFrame(file, frame);
+ }
+
+ FIRCLSFileWriteArrayEnd(file);
+ }
+
+ FIRCLSFileWriteHashEnd(file);
+
+ FIRCLSFileWriteSectionEnd(file);
+}
+
+void FIRCLSExceptionRecord(FIRCLSExceptionType type,
+ const char *name,
+ const char *reason,
+ NSArray *frames,
+ BOOL attemptDelivery) {
+ if (!FIRCLSContextIsInitialized()) {
+ return;
+ }
+
+ bool native = FIRCLSExceptionIsNative(type);
+
+ FIRCLSSDKLog("Recording an exception structure (%d, %d)\n", attemptDelivery, native);
+
+ // exceptions can happen on multiple threads at the same time
+ if (native) {
+ dispatch_sync(_firclsExceptionQueue, ^{
+ const char *path = _firclsContext.readonly->exception.path;
+ FIRCLSFile file;
+
+ if (!FIRCLSFileInitWithPath(&file, path, false)) {
+ FIRCLSSDKLog("Unable to open exception file\n");
+ return;
+ }
+
+ FIRCLSExceptionWrite(&file, type, name, reason, frames);
+
+ // We only want to do this work if we have the expectation that we'll actually crash
+ FIRCLSHandler(&file, mach_thread_self(), NULL);
+
+ FIRCLSFileClose(&file);
+
+ // disallow immediate delivery for non-native exceptions
+ if (attemptDelivery) {
+ FIRCLSHandlerAttemptImmediateDelivery();
+ }
+ });
+ } else {
+ FIRCLSUserLoggingWriteAndCheckABFiles(
+ &_firclsContext.readonly->logging.customExceptionStorage,
+ &_firclsContext.writable->logging.activeCustomExceptionPath, ^(FIRCLSFile *file) {
+ FIRCLSExceptionWrite(file, type, name, reason, frames);
+ });
+ }
+
+ FIRCLSSDKLog("Finished recording an exception structure\n");
+}
+
+// Ignore this message here, because we know that this call will not leak.
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Winvalid-noreturn"
+void FIRCLSExceptionRaiseTestObjCException(void) {
+ [NSException raise:@"CrashlyticsTestException"
+ format:@"This is an Objective-C exception using for testing."];
+}
+
+void FIRCLSExceptionRaiseTestCppException(void) {
+ throw "Crashlytics C++ Test Exception";
+}
+#pragma clang diagnostic pop
+
+static const char *FIRCLSExceptionDemangle(const char *symbol) {
+ return [[FIRCLSDemangleOperation demangleCppSymbol:symbol] UTF8String];
+}
+
+static void FIRCLSCatchAndRecordActiveException(std::type_info *typeInfo) {
+ if (!FIRCLSIsValidPointer(typeInfo)) {
+ FIRCLSSDKLog("Error: invalid parameter\n");
+ return;
+ }
+
+ const char *name = typeInfo->name();
+ FIRCLSSDKLog("Recording exception of type '%s'\n", name);
+
+ // This is a funny technique to get the exception object. The inner @try
+ // has the ability to capture NSException-derived objects. It seems that
+ // c++ trys can do that in some cases, but I was warned by the WWDC labs
+ // that there are cases where that will not work (like for NSException subclasses).
+ try {
+ @try {
+ // This could potentially cause a call to std::terminate() if there is actually no active
+ // exception.
+ throw;
+ } @catch (NSException *exception) {
+#if TARGET_OS_IPHONE
+ FIRCLSExceptionRecordNSException(exception);
+#else
+ // There's no need to record this here, because we're going to get
+ // the value forward to us by AppKit
+ FIRCLSSDKLog("Skipping ObjC exception at this point\n");
+#endif
+ }
+ } catch (const char *exc) {
+ FIRCLSExceptionRecord(FIRCLSExceptionTypeCpp, "const char *", exc, nil, YES);
+ } catch (const std::string &exc) {
+ FIRCLSExceptionRecord(FIRCLSExceptionTypeCpp, "std::string", exc.c_str(), nil, YES);
+ } catch (const std::exception &exc) {
+ FIRCLSExceptionRecord(FIRCLSExceptionTypeCpp, FIRCLSExceptionDemangle(name), exc.what(), nil,
+ YES);
+ } catch (const std::exception *exc) {
+ FIRCLSExceptionRecord(FIRCLSExceptionTypeCpp, FIRCLSExceptionDemangle(name), exc->what(), nil,
+ YES);
+ } catch (const std::bad_alloc &exc) {
+ // it is especially important to avoid demangling in this case, because the expetation at this
+ // point is that all allocations could fail
+ FIRCLSExceptionRecord(FIRCLSExceptionTypeCpp, "std::bad_alloc", exc.what(), nil, YES);
+ } catch (...) {
+ FIRCLSExceptionRecord(FIRCLSExceptionTypeCpp, FIRCLSExceptionDemangle(name), "", nil, YES);
+ }
+}
+
+#pragma mark - Handlers
+static void FIRCLSTerminateHandler(void) {
+ FIRCLSSDKLog("C++ terminate handler invoked\n");
+
+ void (*handler)(void) = _firclsContext.readonly->exception.originalTerminateHandler;
+ if (handler == FIRCLSTerminateHandler) {
+ FIRCLSSDKLog("Error: original handler was set recursively\n");
+ handler = NULL;
+ }
+
+ // Restore pre-existing handler, if any. Do this early, so that
+ // if std::terminate is called while we are executing here, we do not recurse.
+ if (handler) {
+ FIRCLSSDKLog("restoring pre-existing handler\n");
+
+ // To prevent infinite recursion in this function, check that we aren't resetting the terminate
+ // handler to the same function again, which would be this function in the event that we can't
+ // actually change the handler during a terminate.
+ if (std::set_terminate(handler) == handler) {
+ FIRCLSSDKLog("handler has already been restored, aborting\n");
+ abort();
+ }
+ }
+
+ // we can use typeInfo to record the type of the exception,
+ // but we must use a catch to get the value
+ std::type_info *typeInfo = __cxxabiv1::__cxa_current_exception_type();
+ if (typeInfo) {
+ FIRCLSCatchAndRecordActiveException(typeInfo);
+ } else {
+ FIRCLSSDKLog("no active exception\n");
+ }
+
+ // only do this if there was a pre-existing handler
+ if (handler) {
+ FIRCLSSDKLog("invoking pre-existing handler\n");
+ handler();
+ }
+
+ FIRCLSSDKLog("aborting\n");
+ abort();
+}
+
+void FIRCLSExceptionCheckHandlers(void *delegate) {
+#if !TARGET_OS_IPHONE
+ // Check this on OS X all the time, even if the debugger is attached. This is a common
+ // source of errors, so we want to be extra verbose in this case.
+ if (FIRCLSApplicationSharedInstance()) {
+ if (!FIRCLSIsNSApplicationCrashOnExceptionsEnabled()) {
+ FIRCLSWarningLog(@"Warning: NSApplicationCrashOnExceptions is not set. This will "
+ @"result in poor top-level uncaught exception reporting.");
+ }
+ }
+#endif
+
+ if (_firclsContext.readonly->debuggerAttached) {
+ return;
+ }
+
+ void *ptr = NULL;
+
+ ptr = (void *)std::get_terminate();
+ if (ptr != FIRCLSTerminateHandler) {
+ FIRCLSLookupFunctionPointer(ptr, ^(const char *name, const char *lib) {
+ FIRCLSWarningLog(@"Warning: std::get_terminate is '%s' in '%s'", name, lib);
+ });
+ }
+
+#if TARGET_OS_IPHONE
+ ptr = (void *)NSGetUncaughtExceptionHandler();
+ if (ptr) {
+ FIRCLSLookupFunctionPointer(ptr, ^(const char *name, const char *lib) {
+ FIRCLSWarningLog(@"Warning: NSUncaughtExceptionHandler is '%s' in '%s'", name, lib);
+ });
+ }
+#else
+ if (FIRCLSApplicationSharedInstance() && FIRCLSIsNSApplicationCrashOnExceptionsEnabled()) {
+ // In this case, we *might* be able to intercept exceptions. But, verify we've still
+ // swizzled the method.
+ Method m = FIRCLSGetNSApplicationReportExceptionMethod();
+
+ if (method_getImplementation(m) != (IMP)FIRCLSNSApplicationReportException) {
+ FIRCLSWarningLog(
+ @"Warning: top-level NSApplication-reported exceptions cannot be intercepted");
+ }
+ }
+#endif
+}
+
+#pragma mark - AppKit Handling
+#if !TARGET_OS_IPHONE
+static BOOL FIRCLSIsNSApplicationCrashOnExceptionsEnabled(void) {
+ return [[NSUserDefaults standardUserDefaults] boolForKey:@"NSApplicationCrashOnExceptions"];
+}
+
+static Method FIRCLSGetNSApplicationReportExceptionMethod(void) {
+ return class_getInstanceMethod(NSClassFromString(@"NSApplication"), @selector(reportException:));
+}
+
+static NSApplicationReportExceptionFunction FIRCLSOriginalNSExceptionReportExceptionFunction(void) {
+ return (NSApplicationReportExceptionFunction)
+ _firclsContext.readonly->exception.originalNSApplicationReportException;
+}
+
+void FIRCLSNSApplicationReportException(id self, SEL cmd, NSException *exception) {
+ FIRCLSExceptionRecordNSException(exception);
+
+ // Call the original implementation
+ FIRCLSOriginalNSExceptionReportExceptionFunction()(self, cmd, exception);
+}
+
+#endif
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSHandler.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSHandler.h
new file mode 100644
index 000000000..7ce03e416
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSHandler.h
@@ -0,0 +1,26 @@
+// Copyright 2019 Google
+//
+// 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.
+
+#pragma once
+
+#include
+
+#include "FIRCLSFile.h"
+
+__BEGIN_DECLS
+
+void FIRCLSHandler(FIRCLSFile* file, thread_t crashedThread, void* uapVoid);
+void FIRCLSHandlerAttemptImmediateDelivery(void);
+
+__END_DECLS
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSHandler.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSHandler.m
new file mode 100644
index 000000000..918e4265e
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSHandler.m
@@ -0,0 +1,61 @@
+// Copyright 2019 Google
+//
+// 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.
+
+#include "FIRCLSHandler.h"
+
+#include "FIRCLSCrashedMarkerFile.h"
+#include "FIRCLSGlobals.h"
+#include "FIRCLSHost.h"
+#include "FIRCLSProcess.h"
+#include "FIRCLSUtility.h"
+
+#import "FIRCLSReportManager_Private.h"
+
+void FIRCLSHandler(FIRCLSFile* file, thread_t crashedThread, void* uapVoid) {
+ FIRCLSProcess process;
+
+ FIRCLSProcessInit(&process, crashedThread, uapVoid);
+
+ FIRCLSProcessSuspendAllOtherThreads(&process);
+
+ FIRCLSProcessRecordAllThreads(&process, file);
+
+ FIRCLSProcessRecordRuntimeInfo(&process, file);
+ // Get dispatch queue and thread names. Note that getting the thread names
+ // can hang, so let's do that last
+ FIRCLSProcessRecordDispatchQueueNames(&process, file);
+ FIRCLSProcessRecordThreadNames(&process, file);
+
+ // this stuff isn't super important, but we can try
+ FIRCLSProcessRecordStats(&process, file);
+ FIRCLSHostWriteDiskUsage(file);
+
+ // This is the first common point where various crash handlers call into
+ // Store a crash file marker to indicate that a crash has occured
+ FIRCLSCreateCrashedMarkerFile();
+
+ FIRCLSProcessResumeAllOtherThreads(&process);
+
+ // clean up after ourselves
+ FIRCLSProcessDestroy(&process);
+}
+
+void FIRCLSHandlerAttemptImmediateDelivery(void) {
+ // now, attempt to relay the event to the delegate
+ FIRCLSReportManager* manager = (__bridge id)_firclsContext.readonly->delegate;
+
+ if ([manager respondsToSelector:@selector(potentiallySubmittableCrashOccurred)]) {
+ [manager potentiallySubmittableCrashOccurred];
+ }
+}
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSMachException.c b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSMachException.c
new file mode 100644
index 000000000..3ec4e9790
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSMachException.c
@@ -0,0 +1,533 @@
+// Copyright 2019 Google
+//
+// 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.
+
+#include "FIRCLSDefines.h"
+#include "FIRCLSFeatures.h"
+
+#if CLS_MACH_EXCEPTION_SUPPORTED
+
+#include "FIRCLSGlobals.h"
+#include "FIRCLSHandler.h"
+#include "FIRCLSMachException.h"
+#include "FIRCLSProcess.h"
+#include "FIRCLSSignal.h"
+#include "FIRCLSUtility.h"
+
+#include
+#include
+#include
+#include
+
+#pragma mark Prototypes
+static exception_mask_t FIRCLSMachExceptionMask(void);
+static void* FIRCLSMachExceptionServer(void* argument);
+static bool FIRCLSMachExceptionThreadStart(FIRCLSMachExceptionReadContext* context);
+static bool FIRCLSMachExceptionReadMessage(FIRCLSMachExceptionReadContext* context,
+ MachExceptionMessage* message);
+static kern_return_t FIRCLSMachExceptionDispatchMessage(FIRCLSMachExceptionReadContext* context,
+ MachExceptionMessage* message);
+static bool FIRCLSMachExceptionReply(FIRCLSMachExceptionReadContext* context,
+ MachExceptionMessage* message,
+ kern_return_t result);
+static bool FIRCLSMachExceptionRegister(FIRCLSMachExceptionReadContext* context,
+ exception_mask_t ignoreMask);
+static bool FIRCLSMachExceptionUnregister(FIRCLSMachExceptionOriginalPorts* originalPorts,
+ exception_mask_t mask);
+static bool FIRCLSMachExceptionRecord(FIRCLSMachExceptionReadContext* context,
+ MachExceptionMessage* message);
+
+#pragma mark - Initialization
+void FIRCLSMachExceptionInit(FIRCLSMachExceptionReadContext* context, exception_mask_t ignoreMask) {
+ if (!FIRCLSUnlinkIfExists(context->path)) {
+ FIRCLSSDKLog("Unable to reset the mach exception file %s\n", strerror(errno));
+ }
+
+ if (!FIRCLSMachExceptionRegister(context, ignoreMask)) {
+ FIRCLSSDKLog("Unable to register mach exception handler\n");
+ return;
+ }
+
+ if (!FIRCLSMachExceptionThreadStart(context)) {
+ FIRCLSSDKLog("Unable to start thread\n");
+ FIRCLSMachExceptionUnregister(&context->originalPorts, context->mask);
+ }
+}
+
+void FIRCLSMachExceptionCheckHandlers(void) {
+ if (_firclsContext.readonly->debuggerAttached) {
+ return;
+ }
+
+ // It isn't really critical that this be done, as its extremely uncommon to run into
+ // preexisting handlers.
+ // Can use task_get_exception_ports for this.
+}
+
+static exception_mask_t FIRCLSMachExceptionMask(void) {
+ exception_mask_t mask;
+
+ // EXC_BAD_ACCESS
+ // EXC_BAD_INSTRUCTION
+ // EXC_ARITHMETIC
+ // EXC_EMULATION - non-failure
+ // EXC_SOFTWARE - non-failure
+ // EXC_BREAKPOINT - trap instructions, from the debugger and code. Needs special treatment.
+ // EXC_SYSCALL - non-failure
+ // EXC_MACH_SYSCALL - non-failure
+ // EXC_RPC_ALERT - non-failure
+ // EXC_CRASH - see below
+ // EXC_RESOURCE - non-failure, happens when a process exceeds a resource limit
+ // EXC_GUARD - see below
+ //
+ // EXC_CRASH is a special kind of exception. It is handled by launchd, and treated special by
+ // the kernel. Seems that we cannot safely catch it - our handler will never be called. This
+ // is a confirmed kernel bug. Lacking access to EXC_CRASH means we must use signal handlers to
+ // cover all types of crashes.
+ // EXC_GUARD is relatively new, and isn't available on all OS versions. You have to be careful,
+ // becuase you cannot succesfully register hanlders if there are any unrecognized masks. We've
+ // dropped support for old OS versions that didn't have EXC_GUARD (iOS 5 and below, macOS 10.6 and
+ // below) so we always add it now
+
+ mask = EXC_MASK_BAD_ACCESS | EXC_MASK_BAD_INSTRUCTION | EXC_MASK_ARITHMETIC |
+ EXC_MASK_BREAKPOINT | EXC_MASK_GUARD;
+
+ return mask;
+}
+
+static bool FIRCLSMachExceptionThreadStart(FIRCLSMachExceptionReadContext* context) {
+ pthread_attr_t attr;
+
+ if (pthread_attr_init(&attr) != 0) {
+ FIRCLSSDKLog("pthread_attr_init %s\n", strerror(errno));
+ return false;
+ }
+
+ if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0) {
+ FIRCLSSDKLog("pthread_attr_setdetachstate %s\n", strerror(errno));
+ return false;
+ }
+
+ // Use to pre-allocate a stack for this thread
+ // The stack must be page-aligned
+ if (pthread_attr_setstack(&attr, _firclsContext.readonly->machStack,
+ CLS_MACH_EXCEPTION_HANDLER_STACK_SIZE) != 0) {
+ FIRCLSSDKLog("pthread_attr_setstack %s\n", strerror(errno));
+ return false;
+ }
+
+ if (pthread_create(&context->thread, &attr, FIRCLSMachExceptionServer, context) != 0) {
+ FIRCLSSDKLog("pthread_create %s\n", strerror(errno));
+ return false;
+ }
+
+ pthread_attr_destroy(&attr);
+
+ return true;
+}
+
+exception_mask_t FIRCLSMachExceptionMaskForSignal(int signal) {
+ switch (signal) {
+ case SIGTRAP:
+ return EXC_MASK_BREAKPOINT;
+ case SIGSEGV:
+ return EXC_MASK_BAD_ACCESS;
+ case SIGBUS:
+ return EXC_MASK_BAD_ACCESS;
+ case SIGILL:
+ return EXC_MASK_BAD_INSTRUCTION;
+ case SIGABRT:
+ return EXC_MASK_CRASH;
+ case SIGSYS:
+ return EXC_MASK_CRASH;
+ case SIGFPE:
+ return EXC_MASK_ARITHMETIC;
+ }
+
+ return 0;
+}
+
+#pragma mark - Message Handling
+static void* FIRCLSMachExceptionServer(void* argument) {
+ FIRCLSMachExceptionReadContext* context = argument;
+
+ pthread_setname_np("com.google.firebase.crashlytics.MachExceptionServer");
+
+ while (1) {
+ MachExceptionMessage message;
+
+ // read the exception message
+ if (!FIRCLSMachExceptionReadMessage(context, &message)) {
+ break;
+ }
+
+ // handle it, and possibly forward
+ kern_return_t result = FIRCLSMachExceptionDispatchMessage(context, &message);
+
+ // and now, reply
+ if (!FIRCLSMachExceptionReply(context, &message, result)) {
+ break;
+ }
+ }
+
+ FIRCLSSDKLog("Mach exception server thread exiting\n");
+
+ return NULL;
+}
+
+static bool FIRCLSMachExceptionReadMessage(FIRCLSMachExceptionReadContext* context,
+ MachExceptionMessage* message) {
+ mach_msg_return_t r;
+
+ memset(message, 0, sizeof(MachExceptionMessage));
+
+ r = mach_msg(&message->head, MACH_RCV_MSG | MACH_RCV_LARGE, 0, sizeof(MachExceptionMessage),
+ context->port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
+ if (r != MACH_MSG_SUCCESS) {
+ FIRCLSSDKLog("Error receving mach_msg (%d)\n", r);
+ return false;
+ }
+
+ FIRCLSSDKLog("Accepted mach exception message\n");
+
+ return true;
+}
+
+static kern_return_t FIRCLSMachExceptionDispatchMessage(FIRCLSMachExceptionReadContext* context,
+ MachExceptionMessage* message) {
+ FIRCLSSDKLog("Mach exception: 0x%x, count: %d, code: 0x%llx 0x%llx\n", message->exception,
+ message->codeCnt, message->codeCnt > 0 ? message->code[0] : -1,
+ message->codeCnt > 1 ? message->code[1] : -1);
+
+ // This will happen if a child process raises an exception, as the exception ports are
+ // inherited.
+ if (message->task.name != mach_task_self()) {
+ FIRCLSSDKLog("Mach exception task mis-match, returning failure\n");
+ return KERN_FAILURE;
+ }
+
+ FIRCLSSDKLog("Unregistering handler\n");
+ if (!FIRCLSMachExceptionUnregister(&context->originalPorts, context->mask)) {
+ FIRCLSSDKLog("Failed to unregister\n");
+ return KERN_FAILURE;
+ }
+
+ FIRCLSSDKLog("Restoring original signal handlers\n");
+ if (!FIRCLSSignalSafeInstallPreexistingHandlers(&_firclsContext.readonly->signal)) {
+ FIRCLSSDKLog("Failed to restore signal handlers\n");
+ return KERN_FAILURE;
+ }
+
+ FIRCLSSDKLog("Recording mach exception\n");
+ if (!FIRCLSMachExceptionRecord(context, message)) {
+ FIRCLSSDKLog("Failed to record mach exception\n");
+ return KERN_FAILURE;
+ }
+
+ return KERN_SUCCESS;
+}
+
+static bool FIRCLSMachExceptionReply(FIRCLSMachExceptionReadContext* context,
+ MachExceptionMessage* message,
+ kern_return_t result) {
+ MachExceptionReply reply;
+ mach_msg_return_t r;
+
+ // prepare the reply
+ reply.head.msgh_bits = MACH_MSGH_BITS(MACH_MSGH_BITS_REMOTE(message->head.msgh_bits), 0);
+ reply.head.msgh_remote_port = message->head.msgh_remote_port;
+ reply.head.msgh_size = (mach_msg_size_t)sizeof(MachExceptionReply);
+ reply.head.msgh_local_port = MACH_PORT_NULL;
+ reply.head.msgh_id = message->head.msgh_id + 100;
+
+ reply.NDR = NDR_record;
+
+ reply.retCode = result;
+
+ FIRCLSSDKLog("Sending exception reply\n");
+
+ // send it
+ r = mach_msg(&reply.head, MACH_SEND_MSG, reply.head.msgh_size, 0, MACH_PORT_NULL,
+ MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
+ if (r != MACH_MSG_SUCCESS) {
+ FIRCLSSDKLog("mach_msg reply failed (%d)\n", r);
+ return false;
+ }
+
+ FIRCLSSDKLog("Exception reply delivered\n");
+
+ return true;
+}
+
+#pragma mark - Registration
+static bool FIRCLSMachExceptionRegister(FIRCLSMachExceptionReadContext* context,
+ exception_mask_t ignoreMask) {
+ mach_port_t task = mach_task_self();
+
+ kern_return_t kr = mach_port_allocate(task, MACH_PORT_RIGHT_RECEIVE, &context->port);
+ if (kr != KERN_SUCCESS) {
+ FIRCLSSDKLog("Error: mach_port_allocate failed %d\n", kr);
+ return false;
+ }
+
+ kr = mach_port_insert_right(task, context->port, context->port, MACH_MSG_TYPE_MAKE_SEND);
+ if (kr != KERN_SUCCESS) {
+ FIRCLSSDKLog("Error: mach_port_insert_right failed %d\n", kr);
+ mach_port_deallocate(task, context->port);
+ return false;
+ }
+
+ // Get the desired mask, which covers all the mach exceptions we are capable of handling,
+ // but clear out any that are in our ignore list. We do this by ANDing with the bitwise
+ // negation. Because we are only clearing bits, there's no way to set an incorrect mask
+ // using ignoreMask.
+ context->mask = FIRCLSMachExceptionMask() & ~ignoreMask;
+
+ // ORing with MACH_EXCEPTION_CODES will produce 64-bit exception data
+ kr = task_swap_exception_ports(task, context->mask, context->port,
+ EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES, THREAD_STATE_NONE,
+ context->originalPorts.masks, &context->originalPorts.count,
+ context->originalPorts.ports, context->originalPorts.behaviors,
+ context->originalPorts.flavors);
+ if (kr != KERN_SUCCESS) {
+ FIRCLSSDKLog("Error: task_swap_exception_ports %d\n", kr);
+ return false;
+ }
+
+ for (int i = 0; i < context->originalPorts.count; ++i) {
+ FIRCLSSDKLog("original 0x%x 0x%x 0x%x 0x%x\n", context->originalPorts.ports[i],
+ context->originalPorts.masks[i], context->originalPorts.behaviors[i],
+ context->originalPorts.flavors[i]);
+ }
+
+ return true;
+}
+
+static bool FIRCLSMachExceptionUnregister(FIRCLSMachExceptionOriginalPorts* originalPorts,
+ exception_mask_t mask) {
+ kern_return_t kr;
+
+ // Re-register all the old ports.
+ for (mach_msg_type_number_t i = 0; i < originalPorts->count; ++i) {
+ // clear the bits from this original mask
+ mask &= ~originalPorts->masks[i];
+
+ kr =
+ task_set_exception_ports(mach_task_self(), originalPorts->masks[i], originalPorts->ports[i],
+ originalPorts->behaviors[i], originalPorts->flavors[i]);
+ if (kr != KERN_SUCCESS) {
+ FIRCLSSDKLog("unable to restore original port: %d", originalPorts->ports[i]);
+ }
+ }
+
+ // Finally, mark any masks we registered for that do not have an original port as unused.
+ kr = task_set_exception_ports(mach_task_self(), mask, MACH_PORT_NULL,
+ EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES, THREAD_STATE_NONE);
+ if (kr != KERN_SUCCESS) {
+ FIRCLSSDKLog("unable to unset unregistered mask: 0x%x", mask);
+ return false;
+ }
+
+ return true;
+}
+
+#pragma mark - Recording
+static void FIRCLSMachExceptionNameLookup(exception_type_t number,
+ mach_exception_data_type_t code,
+ const char** name,
+ const char** codeName) {
+ if (!name || !codeName) {
+ return;
+ }
+
+ *name = NULL;
+ *codeName = NULL;
+
+ switch (number) {
+ case EXC_BAD_ACCESS:
+ *name = "EXC_BAD_ACCESS";
+ switch (code) {
+ case KERN_INVALID_ADDRESS:
+ *codeName = "KERN_INVALID_ADDRESS";
+ break;
+ case KERN_PROTECTION_FAILURE:
+ *codeName = "KERN_PROTECTION_FAILURE";
+ break;
+ }
+
+ break;
+ case EXC_BAD_INSTRUCTION:
+ *name = "EXC_BAD_INSTRUCTION";
+#if CLS_CPU_X86
+ *codeName = "EXC_I386_INVOP";
+#endif
+ break;
+ case EXC_ARITHMETIC:
+ *name = "EXC_ARITHMETIC";
+#if CLS_CPU_X86
+ switch (code) {
+ case EXC_I386_DIV:
+ *codeName = "EXC_I386_DIV";
+ break;
+ case EXC_I386_INTO:
+ *codeName = "EXC_I386_INTO";
+ break;
+ case EXC_I386_NOEXT:
+ *codeName = "EXC_I386_NOEXT";
+ break;
+ case EXC_I386_EXTOVR:
+ *codeName = "EXC_I386_EXTOVR";
+ break;
+ case EXC_I386_EXTERR:
+ *codeName = "EXC_I386_EXTERR";
+ break;
+ case EXC_I386_EMERR:
+ *codeName = "EXC_I386_EMERR";
+ break;
+ case EXC_I386_BOUND:
+ *codeName = "EXC_I386_BOUND";
+ break;
+ case EXC_I386_SSEEXTERR:
+ *codeName = "EXC_I386_SSEEXTERR";
+ break;
+ }
+#endif
+ break;
+ case EXC_BREAKPOINT:
+ *name = "EXC_BREAKPOINT";
+#if CLS_CPU_X86
+ switch (code) {
+ case EXC_I386_DIVERR:
+ *codeName = "EXC_I386_DIVERR";
+ break;
+ case EXC_I386_SGLSTP:
+ *codeName = "EXC_I386_SGLSTP";
+ break;
+ case EXC_I386_NMIFLT:
+ *codeName = "EXC_I386_NMIFLT";
+ break;
+ case EXC_I386_BPTFLT:
+ *codeName = "EXC_I386_BPTFLT";
+ break;
+ case EXC_I386_INTOFLT:
+ *codeName = "EXC_I386_INTOFLT";
+ break;
+ case EXC_I386_BOUNDFLT:
+ *codeName = "EXC_I386_BOUNDFLT";
+ break;
+ case EXC_I386_INVOPFLT:
+ *codeName = "EXC_I386_INVOPFLT";
+ break;
+ case EXC_I386_NOEXTFLT:
+ *codeName = "EXC_I386_NOEXTFLT";
+ break;
+ case EXC_I386_EXTOVRFLT:
+ *codeName = "EXC_I386_EXTOVRFLT";
+ break;
+ case EXC_I386_INVTSSFLT:
+ *codeName = "EXC_I386_INVTSSFLT";
+ break;
+ case EXC_I386_SEGNPFLT:
+ *codeName = "EXC_I386_SEGNPFLT";
+ break;
+ case EXC_I386_STKFLT:
+ *codeName = "EXC_I386_STKFLT";
+ break;
+ case EXC_I386_GPFLT:
+ *codeName = "EXC_I386_GPFLT";
+ break;
+ case EXC_I386_PGFLT:
+ *codeName = "EXC_I386_PGFLT";
+ break;
+ case EXC_I386_EXTERRFLT:
+ *codeName = "EXC_I386_EXTERRFLT";
+ break;
+ case EXC_I386_ALIGNFLT:
+ *codeName = "EXC_I386_ALIGNFLT";
+ break;
+ case EXC_I386_ENDPERR:
+ *codeName = "EXC_I386_ENDPERR";
+ break;
+ case EXC_I386_ENOEXTFLT:
+ *codeName = "EXC_I386_ENOEXTFLT";
+ break;
+ }
+#endif
+ break;
+ case EXC_GUARD:
+ *name = "EXC_GUARD";
+ break;
+ }
+}
+
+static bool FIRCLSMachExceptionRecord(FIRCLSMachExceptionReadContext* context,
+ MachExceptionMessage* message) {
+ if (!context || !message) {
+ return false;
+ }
+
+ if (FIRCLSContextMarkAndCheckIfCrashed()) {
+ FIRCLSSDKLog("Error: aborting mach exception handler because crash has already occurred\n");
+ exit(1);
+ return false;
+ }
+
+ FIRCLSFile file;
+
+ if (!FIRCLSFileInitWithPath(&file, context->path, false)) {
+ FIRCLSSDKLog("Unable to open mach exception file\n");
+ return false;
+ }
+
+ FIRCLSFileWriteSectionStart(&file, "mach_exception");
+
+ FIRCLSFileWriteHashStart(&file);
+
+ FIRCLSFileWriteHashEntryUint64(&file, "exception", message->exception);
+
+ // record the codes
+ FIRCLSFileWriteHashKey(&file, "codes");
+ FIRCLSFileWriteArrayStart(&file);
+ for (mach_msg_type_number_t i = 0; i < message->codeCnt; ++i) {
+ FIRCLSFileWriteArrayEntryUint64(&file, message->code[i]);
+ }
+ FIRCLSFileWriteArrayEnd(&file);
+
+ const char* name = NULL;
+ const char* codeName = NULL;
+
+ FIRCLSMachExceptionNameLookup(message->exception, message->codeCnt > 0 ? message->code[0] : 0,
+ &name, &codeName);
+
+ FIRCLSFileWriteHashEntryString(&file, "name", name);
+ FIRCLSFileWriteHashEntryString(&file, "code_name", codeName);
+
+ FIRCLSFileWriteHashEntryUint64(&file, "original_ports", context->originalPorts.count);
+ FIRCLSFileWriteHashEntryUint64(&file, "time", time(NULL));
+
+ FIRCLSFileWriteHashEnd(&file);
+
+ FIRCLSFileWriteSectionEnd(&file);
+
+ FIRCLSHandler(&file, message->thread.name, NULL);
+
+ FIRCLSFileClose(&file);
+
+ return true;
+}
+
+#else
+
+INJECT_STRIP_SYMBOL(cls_mach_exception)
+
+#endif
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSMachException.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSMachException.h
new file mode 100644
index 000000000..b19881a7a
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSMachException.h
@@ -0,0 +1,78 @@
+// Copyright 2019 Google
+//
+// 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.
+
+#include "FIRCLSFeatures.h"
+
+#pragma once
+
+#if CLS_MACH_EXCEPTION_SUPPORTED
+
+#include
+#include
+#include
+
+// must be at least PTHREAD_STACK_MIN size
+#define CLS_MACH_EXCEPTION_HANDLER_STACK_SIZE (256 * 1024)
+
+#pragma mark Structures
+#pragma pack(push, 4)
+typedef struct {
+ mach_msg_header_t head;
+ /* start of the kernel processed data */
+ mach_msg_body_t msgh_body;
+ mach_msg_port_descriptor_t thread;
+ mach_msg_port_descriptor_t task;
+ /* end of the kernel processed data */
+ NDR_record_t NDR;
+ exception_type_t exception;
+ mach_msg_type_number_t codeCnt;
+ mach_exception_data_type_t code[EXCEPTION_CODE_MAX];
+ mach_msg_trailer_t trailer;
+} MachExceptionMessage;
+
+typedef struct {
+ mach_msg_header_t head;
+ NDR_record_t NDR;
+ kern_return_t retCode;
+} MachExceptionReply;
+#pragma pack(pop)
+
+typedef struct {
+ mach_msg_type_number_t count;
+ exception_mask_t masks[EXC_TYPES_COUNT];
+ exception_handler_t ports[EXC_TYPES_COUNT];
+ exception_behavior_t behaviors[EXC_TYPES_COUNT];
+ thread_state_flavor_t flavors[EXC_TYPES_COUNT];
+} FIRCLSMachExceptionOriginalPorts;
+
+typedef struct {
+ mach_port_t port;
+ pthread_t thread;
+ const char* path;
+
+ exception_mask_t mask;
+ FIRCLSMachExceptionOriginalPorts originalPorts;
+} FIRCLSMachExceptionReadContext;
+
+#pragma mark - API
+void FIRCLSMachExceptionInit(FIRCLSMachExceptionReadContext* context, exception_mask_t ignoreMask);
+exception_mask_t FIRCLSMachExceptionMaskForSignal(int signal);
+
+void FIRCLSMachExceptionCheckHandlers(void);
+
+#else
+
+#define CLS_MACH_EXCEPTION_HANDLER_STACK_SIZE 0
+
+#endif
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSSignal.c b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSSignal.c
new file mode 100644
index 000000000..5fa302d7c
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSSignal.c
@@ -0,0 +1,318 @@
+// Copyright 2019 Google
+//
+// 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.
+
+#include "FIRCLSSignal.h"
+#include "FIRCLSGlobals.h"
+#include "FIRCLSHandler.h"
+#include "FIRCLSUtility.h"
+
+#include
+#include
+
+static const int FIRCLSFatalSignals[FIRCLSSignalCount] = {SIGABRT, SIGBUS, SIGFPE, SIGILL,
+ SIGSEGV, SIGSYS, SIGTRAP};
+
+#if CLS_USE_SIGALTSTACK
+static void FIRCLSSignalInstallAltStack(FIRCLSSignalReadContext *roContext);
+#endif
+static void FIRCLSSignalInstallHandlers(FIRCLSSignalReadContext *roContext);
+static void FIRCLSSignalHandler(int signal, siginfo_t *info, void *uapVoid);
+
+void FIRCLSSignalInitialize(FIRCLSSignalReadContext *roContext) {
+ if (!FIRCLSUnlinkIfExists(roContext->path)) {
+ FIRCLSSDKLog("Unable to reset the signal log file %s\n", strerror(errno));
+ }
+
+#if CLS_USE_SIGALTSTACK
+ FIRCLSSignalInstallAltStack(roContext);
+#endif
+ FIRCLSSignalInstallHandlers(roContext);
+#if TARGET_IPHONE_SIMULATOR
+ // prevent the OpenGL stack (by way of OpenGLES.framework/libLLVMContainer.dylib) from installing
+ // signal handlers that do not chain back
+ // TODO: I don't believe this is necessary as of recent iOS releases
+ bool *ptr = dlsym(RTLD_DEFAULT, "_ZN4llvm23DisablePrettyStackTraceE");
+ if (ptr) {
+ *ptr = true;
+ }
+#endif
+}
+
+void FIRCLSSignalEnumerateHandledSignals(void (^block)(int idx, int signal)) {
+ for (int i = 0; i < FIRCLSSignalCount; ++i) {
+ block(i, FIRCLSFatalSignals[i]);
+ }
+}
+
+#if CLS_USE_SIGALTSTACK
+
+static void FIRCLSSignalInstallAltStack(FIRCLSSignalReadContext *roContext) {
+ stack_t signalStack;
+ stack_t originalStack;
+
+ signalStack.ss_sp = _firclsContext.readonly->signalStack;
+ signalStack.ss_size = CLS_SIGNAL_HANDLER_STACK_SIZE;
+ signalStack.ss_flags = 0;
+
+ if (sigaltstack(&signalStack, &originalStack) != 0) {
+ FIRCLSSDKLog("Unable to setup stack %s\n", strerror(errno));
+
+ return;
+ }
+
+ roContext->originalStack.ss_sp = NULL;
+ roContext->originalStack = originalStack;
+}
+
+#endif
+
+static void FIRCLSSignalInstallHandlers(FIRCLSSignalReadContext *roContext) {
+ FIRCLSSignalEnumerateHandledSignals(^(int idx, int signal) {
+ struct sigaction action;
+ struct sigaction previousAction;
+
+ action.sa_sigaction = FIRCLSSignalHandler;
+ // SA_RESETHAND seems like it would be great, but it doesn't appear to
+ // work correctly. After taking a signal, causing another identical signal in
+ // the handler will *not* cause the default handler to be invokved (which should
+ // terminate the process). I've found some evidence that others have seen this
+ // behavior on MAC OS X.
+ action.sa_flags = SA_SIGINFO | SA_ONSTACK;
+
+ sigemptyset(&action.sa_mask);
+
+ previousAction.sa_sigaction = NULL;
+ if (sigaction(signal, &action, &previousAction) != 0) {
+ FIRCLSSDKLog("Unable to install handler for %d (%s)\n", signal, strerror(errno));
+ }
+
+ // store the last action, so it can be recalled
+ roContext->originalActions[idx].sa_sigaction = NULL;
+
+ if (previousAction.sa_sigaction) {
+ roContext->originalActions[idx] = previousAction;
+ }
+ });
+}
+
+void FIRCLSSignalCheckHandlers(void) {
+ if (_firclsContext.readonly->debuggerAttached) {
+ return;
+ }
+
+ FIRCLSSignalEnumerateHandledSignals(^(int idx, int signal) {
+ struct sigaction previousAction;
+ Dl_info info;
+ void *ptr;
+
+ if (sigaction(signal, 0, &previousAction) != 0) {
+ fprintf(stderr, "Unable to read signal handler\n");
+ return;
+ }
+
+ ptr = previousAction.__sigaction_u.__sa_handler;
+ const char *signalName = NULL;
+ const char *codeName = NULL;
+
+ FIRCLSSignalNameLookup(signal, 0, &signalName, &codeName);
+
+ if (ptr == FIRCLSSignalHandler) {
+ return;
+ }
+
+ const char *name = NULL;
+ if (dladdr(ptr, &info) != 0) {
+ name = info.dli_sname;
+ }
+
+ fprintf(stderr,
+ "[Crashlytics] The signal %s has a non-Crashlytics handler (%s). This will interfere "
+ "with reporting.\n",
+ signalName, name);
+ });
+}
+
+void FIRCLSSignalSafeRemoveHandlers(bool includingAbort) {
+ for (int i = 0; i < FIRCLSSignalCount; ++i) {
+ struct sigaction sa;
+
+ if (!includingAbort && (FIRCLSFatalSignals[i] == SIGABRT)) {
+ continue;
+ }
+
+ sa.sa_handler = SIG_DFL;
+ sigemptyset(&sa.sa_mask);
+
+ if (sigaction(FIRCLSFatalSignals[i], &sa, NULL) != 0)
+ FIRCLSSDKLog("Unable to set default handler for %d (%s)\n", i, strerror(errno));
+ }
+}
+
+bool FIRCLSSignalSafeInstallPreexistingHandlers(FIRCLSSignalReadContext *roContext) {
+ bool success;
+
+ FIRCLSSignalSafeRemoveHandlers(true);
+
+#if CLS_USE_SIGALTSTACK
+
+ // re-install the original stack, if needed
+ if (roContext->originalStack.ss_sp) {
+ if (sigaltstack(&roContext->originalStack, 0) != 0) {
+ FIRCLSSDKLog("Unable to setup stack %s\n", strerror(errno));
+
+ return false;
+ }
+ }
+
+#endif
+
+ // re-install the original handlers, if any
+ success = true;
+ for (int i = 0; i < FIRCLSSignalCount; ++i) {
+ if (roContext->originalActions[i].sa_sigaction == NULL) {
+ continue;
+ }
+
+ if (sigaction(FIRCLSFatalSignals[i], &roContext->originalActions[i], 0) != 0) {
+ FIRCLSSDKLog("Unable to install handler for %d (%s)\n", i, strerror(errno));
+ success = false;
+ }
+ }
+
+ return success;
+}
+
+void FIRCLSSignalNameLookup(int number, int code, const char **name, const char **codeName) {
+ if (!name || !codeName) {
+ return;
+ }
+
+ *codeName = NULL;
+
+ switch (number) {
+ case SIGABRT:
+ *name = "SIGABRT";
+ *codeName = "ABORT";
+ break;
+ case SIGBUS:
+ *name = "SIGBUS";
+ break;
+ case SIGFPE:
+ *name = "SIGFPE";
+ break;
+ case SIGILL:
+ *name = "SIGILL";
+ break;
+ case SIGSEGV:
+ *name = "SIGSEGV";
+ break;
+ case SIGSYS:
+ *name = "SIGSYS";
+ break;
+ case SIGTRAP:
+ *name = "SIGTRAP";
+ break;
+ default:
+ *name = "UNKNOWN";
+ break;
+ }
+}
+
+static void FIRCLSSignalRecordSignal(int savedErrno, siginfo_t *info, void *uapVoid) {
+ if (!_firclsContext.readonly) {
+ return;
+ }
+
+ if (FIRCLSContextMarkAndCheckIfCrashed()) {
+ FIRCLSSDKLog("Error: aborting signal handler because crash has already occurred");
+ exit(1);
+ return;
+ }
+
+ FIRCLSFile file;
+
+ if (!FIRCLSFileInitWithPath(&file, _firclsContext.readonly->signal.path, false)) {
+ FIRCLSSDKLog("Unable to open signal file\n");
+ return;
+ }
+
+ FIRCLSFileWriteSectionStart(&file, "signal");
+
+ FIRCLSFileWriteHashStart(&file);
+
+ if (FIRCLSIsValidPointer(info)) {
+ FIRCLSFileWriteHashEntryUint64(&file, "number", info->si_signo);
+ FIRCLSFileWriteHashEntryUint64(&file, "code", info->si_code);
+ FIRCLSFileWriteHashEntryUint64(&file, "address", (uint64_t)info->si_addr);
+
+ const char *name = NULL;
+ const char *codeName = NULL;
+
+ FIRCLSSignalNameLookup(info->si_signo, info->si_code, &name, &codeName);
+
+ FIRCLSFileWriteHashEntryString(&file, "name", name);
+ FIRCLSFileWriteHashEntryString(&file, "code_name", codeName);
+ }
+
+ FIRCLSFileWriteHashEntryUint64(&file, "errno", savedErrno);
+ FIRCLSFileWriteHashEntryUint64(&file, "time", time(NULL));
+
+ FIRCLSFileWriteHashEnd(&file);
+
+ FIRCLSFileWriteSectionEnd(&file);
+
+ FIRCLSHandler(&file, mach_thread_self(), uapVoid);
+
+ FIRCLSFileClose(&file);
+}
+
+static void FIRCLSSignalHandler(int signal, siginfo_t *info, void *uapVoid) {
+ int savedErrno;
+ sigset_t set;
+
+ // save errno, both because it is interesting, and so we can restore it afterwards
+ savedErrno = errno;
+ errno = 0;
+
+ FIRCLSSDKLog("Signal: %d\n", signal);
+
+ // it is important to do this before unmasking signals, otherwise we can get
+ // called in a loop
+ FIRCLSSignalSafeRemoveHandlers(true);
+
+ sigfillset(&set);
+ if (sigprocmask(SIG_UNBLOCK, &set, NULL) != 0) {
+ FIRCLSSDKLog("Unable to unmask signals - we risk infinite recursion here\n");
+ }
+
+ // check info and uapVoid, and set them to appropriate values if invalid. This can happen
+ // if we have been called without the SA_SIGINFO flag set
+ if (!FIRCLSIsValidPointer(info)) {
+ info = NULL;
+ }
+
+ if (!FIRCLSIsValidPointer(uapVoid)) {
+ uapVoid = NULL;
+ }
+
+ FIRCLSSignalRecordSignal(savedErrno, info, uapVoid);
+
+ // re-install original handlers
+ if (_firclsContext.readonly) {
+ FIRCLSSignalSafeInstallPreexistingHandlers(&_firclsContext.readonly->signal);
+ }
+
+ // restore errno
+ errno = savedErrno;
+}
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSSignal.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSSignal.h
new file mode 100644
index 000000000..3b6b1b4e2
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSSignal.h
@@ -0,0 +1,51 @@
+// Copyright 2019 Google
+//
+// 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.
+
+#pragma once
+
+#include "FIRCLSFeatures.h"
+#include "FIRCLSFile.h"
+
+#include
+#include
+
+#define FIRCLSSignalCount (7)
+
+// per man sigaltstack, MINSIGSTKSZ is the minimum *overhead* needed to support
+// a signal stack. The actual stack size must be larger. Let's pick the recommended
+// size.
+#if CLS_USE_SIGALTSTACK
+#define CLS_SIGNAL_HANDLER_STACK_SIZE (SIGSTKSZ * 2)
+#else
+#define CLS_SIGNAL_HANDLER_STACK_SIZE 0
+#endif
+
+typedef struct {
+ const char* path;
+ struct sigaction originalActions[FIRCLSSignalCount];
+
+#if CLS_USE_SIGALTSTACK
+ stack_t originalStack;
+#endif
+} FIRCLSSignalReadContext;
+
+void FIRCLSSignalInitialize(FIRCLSSignalReadContext* roContext);
+void FIRCLSSignalCheckHandlers(void);
+
+void FIRCLSSignalSafeRemoveHandlers(bool includingAbort);
+bool FIRCLSSignalSafeInstallPreexistingHandlers(FIRCLSSignalReadContext* roContext);
+
+void FIRCLSSignalNameLookup(int number, int code, const char** name, const char** codeName);
+
+void FIRCLSSignalEnumerateHandledSignals(void (^block)(int idx, int signal));
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRAEvent+Internal.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRAEvent+Internal.h
new file mode 100644
index 000000000..f0de9fed9
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRAEvent+Internal.h
@@ -0,0 +1,23 @@
+// Copyright 2019 Google
+//
+// 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.
+
+#ifndef FIRAEvent_Internal_h
+#define FIRAEvent_Internal_h
+
+#import "FIRAEvent.h"
+#import "FIRAValue.h"
+
+NSString* FIRCLSFIRAEventDictionaryToJSON(NSDictionary* eventAsDictionary);
+
+#endif /* FIRAEvent_Internal_h */
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRAEvent+Internal.m b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRAEvent+Internal.m
new file mode 100644
index 000000000..4591e29f1
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRAEvent+Internal.m
@@ -0,0 +1,42 @@
+// Copyright 2019 Google
+//
+// 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 "FIRAEvent+Internal.h"
+
+#import "FIRCLSUtility.h"
+
+NSString* FIRCLSFIRAEventDictionaryToJSON(NSDictionary* eventAsDictionary) {
+ NSError* error = nil;
+
+ if (eventAsDictionary == nil) {
+ return nil;
+ }
+
+ if (![NSJSONSerialization isValidJSONObject:eventAsDictionary]) {
+ FIRCLSSDKLog("Firebase Analytics event is not valid JSON");
+ return nil;
+ }
+
+ NSData* jsonData = [NSJSONSerialization dataWithJSONObject:eventAsDictionary
+ options:0
+ error:&error];
+
+ if (error == nil) {
+ NSString* json = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
+ return json;
+ } else {
+ FIRCLSSDKLog("Unable to convert Firebase Analytics event to json");
+ return nil;
+ }
+}
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRAEvent.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRAEvent.h
new file mode 100644
index 000000000..9fcbd6602
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRAEvent.h
@@ -0,0 +1,79 @@
+// Copyright 2019 Google
+//
+// 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
+
+@class FIRAPBEvent;
+
+/// An application event.
+@interface FIRAEvent : NSObject
+
+/// Origin of this event (eg "app" or "auto").
+@property(nonatomic, readonly) NSString *origin;
+
+/// Name of this event.
+@property(nonatomic, readonly) NSString *name;
+
+/// Timestamp of when this event was fired.
+@property(nonatomic, readonly) NSTimeInterval timestamp;
+
+/// Timestamp of the previous time an event with this name was fired, if any.
+@property(nonatomic, readonly) NSTimeInterval previousTimestamp;
+
+/// The event's parameters as {NSString : NSString} or {NSString : NSNumber}.
+@property(nonatomic, readonly) NSDictionary *parameters;
+
+/// Indicates whether the event has the conversion parameter. Setting to YES adds the conversion
+/// parameter if not already present. Setting to NO removes the conversion parameter and adds an
+/// error.
+@property(nonatomic, getter=isConversion) BOOL conversion;
+
+/// Indicates whether the event has the real-time parameter. Setting to YES adds the real-time
+/// parameter if not already present. Setting to NO removes the real-time parameter.
+@property(nonatomic, getter=isRealtime) BOOL realtime;
+
+/// Indicates whether the event has debug parameter. Setting to YES adds the debug parameter if
+/// not already present. Setting to NO removes the debug parameter.
+@property(nonatomic, getter=isDebug) BOOL debug;
+
+/// The populated FIRAPBEvent for proto.
+@property(nonatomic, readonly) FIRAPBEvent *protoEvent;
+
+/// Creates an event with the given parameters. Parameters will be copied and normalized. Returns
+/// nil if the name does not meet length requirements.
+/// If |parameters| contains the "_o" parameter, its value will be overwritten with the value of
+/// |origin|.
+- (instancetype)initWithOrigin:(NSString *)origin
+ isPublic:(BOOL)isPublic
+ name:(NSString *)name
+ timestamp:(NSTimeInterval)timestamp
+ previousTimestamp:(NSTimeInterval)previousTimestamp
+ parameters:(NSDictionary *)parameters NS_DESIGNATED_INITIALIZER;
+
+- (instancetype)init NS_UNAVAILABLE;
+
+/// Returns a new event object with the given previousTimestamp.
+- (instancetype)copyWithPreviousTimestamp:(NSTimeInterval)previousTimestamp;
+
+/// Returns a new event object with the new parameters.
+- (instancetype)copyWithParameters:(NSDictionary *)parameters;
+
+/// Returns YES if all parameters in screenParameters were added to the event object. Returns NO if
+/// screenParameters is nil/empty or the event already contains any of the screen parameter keys.
+/// Performs internal validation on the screen parameter values and converts them to FIRAValue
+/// objects if they aren't already. screenParameters should be a dictionary of
+/// { NSString : NSString | NSNumber } or { NSString : FIRAValue }.
+- (BOOL)addScreenParameters:(NSDictionary *)screenParameters;
+
+@end
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRAValue.h b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRAValue.h
new file mode 100644
index 000000000..7d10ec308
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRAValue.h
@@ -0,0 +1,69 @@
+// Copyright 2019 Google
+//
+// 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
+
+typedef NS_ENUM(NSInteger, FIRAValueType) {
+ kFIRAValueTypeDouble = 0,
+ kFIRAValueTypeInteger,
+ kFIRAValueTypeString,
+};
+
+@interface FIRAValue : NSObject
+
+/// The type of the value.
+@property(nonatomic, readonly) FIRAValueType valueType;
+
+#pragma mark - Double type.
+
+/// Indicates whether the FIRAValue instance is a floating point.
+@property(nonatomic, readonly) BOOL isDouble;
+
+/// Float value. Check valueType to see if this attribute has float value.
+@property(nonatomic, readonly) double doubleValue;
+
+#pragma mark - Integer type.
+
+/// Indicates whether the FIRAValue instance is an integer.
+@property(nonatomic, readonly) BOOL isInt64;
+
+/// Int64 value. Check valueType to see if this attribute has int64 value.
+@property(nonatomic, readonly) int64_t int64Value;
+
+#pragma mark - String type.
+
+/// Indicates whether the FIRAValue instance is a string.
+@property(nonatomic, readonly) BOOL isString;
+
+/// String value. Check valueType to see if this attribute has string value.
+@property(nonatomic, readonly) NSString *stringValue;
+
+#pragma mark - Initializers.
+
+/// Creates a @c FIRAValue if |object| is of type NSString or NSNumber. Returns |object| if it's
+/// already a FIRAValue. Returns nil otherwise.
++ (instancetype)valueFromObject:(id)object;
+
+/// Creates a @c FIRAValue with double value.
+- (instancetype)initWithDouble:(double)value;
+
+/// Creates a @c FIRAValue with int64 value.
+- (instancetype)initWithInt64:(int64_t)value;
+
+/// Creates a @c FIRAValue with string value.
+- (instancetype)initWithString:(NSString *)stringValue;
+
+- (instancetype)init NS_UNAVAILABLE;
+
+@end
diff --git a/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSAllocate.c b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSAllocate.c
new file mode 100644
index 000000000..febafd2ab
--- /dev/null
+++ b/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSAllocate.c
@@ -0,0 +1,238 @@
+// Copyright 2019 Google
+//
+// 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.
+
+#include