Add Sentry React Native SDK

parent fdbae6d8
{
"presets": ["react-native"],
"presets": ["react-native", "react-native-dotenv"],
"plugins": ["@babel/plugin-proposal-object-rest-spread", "@babel/transform-regenerator"]
}
\ No newline at end of file
......@@ -60,3 +60,5 @@ buck-out/
*.jsbundle
bundle.js
sentry.properties
.env
\ No newline at end of file
......@@ -3,6 +3,7 @@ import * as matchers from 'redux-saga-test-plan/matchers';
import { throwError } from 'redux-saga-test-plan/providers';
import Snackbar from 'react-native-snackbar';
import { AsyncStorage } from 'react-native';
import { Sentry } from 'react-native-sentry';
import loginSaga, { DISPLAYNAMEKEY, PHOTOKEY, TOKENKEY, USERNAMEKEY } from '../../app/sagas/login';
import { apiRequest } from '../../app/utils/url';
......@@ -27,6 +28,13 @@ jest.mock('../../app/utils/url', () => ({
tokenSelector: () => 'token',
}));
jest.mock('react-native-sentry', () => ({
Sentry: {
setUserContext: () => {},
captureException: () => {},
},
}));
describe('login saga', () => {
const error = new Error('error');
......@@ -42,6 +50,7 @@ describe('login saga', () => {
it('should put the result data when the request succeeds', () => expectSaga(loginSaga)
.provide([
[matchers.call.like({ fn: apiRequest, args: ['token-auth'] }), { token: 'abc123' }],
[matchers.call.like({ fn: Sentry.setUserContext }), {}],
])
.put(loginActions.success('username', 'abc123'))
.put(loginActions.profile('abc123'))
......@@ -51,6 +60,7 @@ describe('login saga', () => {
it('should show a snackbar when the request succeeds', () => expectSaga(loginSaga)
.provide([
[matchers.call.like({ fn: apiRequest, args: ['token-auth'] }), { token: 'abc123' }],
[matchers.call.like({ fn: Sentry.setUserContext }), {}],
])
.dispatch(loginActions.login('username', 'password'))
.silentRun()
......@@ -64,6 +74,7 @@ describe('login saga', () => {
expectSaga(loginSaga)
.provide([
[matchers.call.like({ fn: apiRequest, args: ['token-auth'] }), { token: 'abc123' }],
[matchers.call.like({ fn: Sentry.setUserContext }), {}],
])
.dispatch(loginActions.login('username', 'password'))
.silentRun()
......
......@@ -78,6 +78,7 @@ project.ext.react = [
]
apply from: "../../node_modules/react-native/react.gradle"
apply from: "../../node_modules/react-native-sentry/sentry.gradle"
/**
* Set this to true to create two separate APKs instead of one:
......@@ -145,6 +146,7 @@ android {
}
dependencies {
implementation project(':react-native-sentry')
implementation project(':react-native-locale-detector')
implementation project(':react-native-vector-icons')
implementation project(':react-native-snackbar')
......
......@@ -3,6 +3,7 @@ package com.thaliapp;
import android.app.Application;
import com.facebook.react.ReactApplication;
import io.sentry.RNSentryPackage;
import com.azendoo.reactnativesnackbar.SnackbarPackage;
import com.i18n.reactnativei18n.ReactNativeI18n;
import com.evollu.react.fcm.FIRMessagingPackage;
......@@ -28,6 +29,7 @@ public class MainApplication extends Application implements ReactApplication {
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
new RNSentryPackage(),
new SnackbarPackage(),
new ReactNativeI18n(),
new FIRMessagingPackage(),
......
rootProject.name = 'ThaliApp'
include ':react-native-sentry'
project(':react-native-sentry').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-sentry/android')
include ':react-native-snackbar'
project(':react-native-snackbar').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-snackbar/android')
include ':react-native-locale-detector'
......
import {
call, put, select, takeEvery,
} from 'redux-saga/effects';
import { call, put, select, takeEvery } from 'redux-saga/effects';
import { Sentry } from 'react-native-sentry';
import { apiRequest, tokenSelector } from '../utils/url';
import * as navigationActions from '../actions/navigation';
......@@ -30,10 +29,11 @@ const calendar = function* calendar() {
partner: true,
}));
} catch (error) {
// Swallow the error
Sentry.captureException(error);
}
yield put(calendarActions.success(events.concat(partnerEvents)));
} catch (error) {
Sentry.captureException(error);
yield put(calendarActions.failure());
}
};
......
import {
call, put, takeEvery, select,
} from 'redux-saga/effects';
import { call, put, takeEvery, select } from 'redux-saga/effects';
import { Sentry } from 'react-native-sentry';
import { apiRequest, tokenSelector } from '../utils/url';
import * as eventActions from '../actions/event';
......@@ -36,6 +35,7 @@ const event = function* event(action) {
eventRegistrations,
));
} catch (error) {
Sentry.captureException(error);
yield put(eventActions.failure());
}
};
......
import { call, takeEvery, put } from 'redux-saga/effects';
import { AsyncStorage } from 'react-native';
import Snackbar from 'react-native-snackbar';
import { Sentry } from 'react-native-sentry';
import { apiRequest } from '../utils/url';
import * as loginActions from '../actions/login';
......@@ -78,15 +79,22 @@ const profile = function* profile(action) {
]);
yield put(loginActions.profileSuccess(userProfile.display_name, userProfile.avatar.medium));
} catch (error) {
Sentry.captureException(error);
// Swallow error
}
};
function* success({ payload }) {
const { username } = payload;
yield call(Sentry.setUserContext, { username });
}
const loginSaga = function* loginSaga() {
yield takeEvery(loginActions.LOGIN, login);
yield takeEvery(loginActions.LOGOUT, logout);
yield takeEvery(loginActions.PROFILE, profile);
yield takeEvery(loginActions.TOKEN_INVALID, tokenInvalid);
yield takeEvery(loginActions.SUCCESS, success);
};
export default loginSaga;
import { Dimensions } from 'react-native';
import {
call, put, select, takeEvery,
} from 'redux-saga/effects';
import { call, put, select, takeEvery } from 'redux-saga/effects';
import { Sentry } from 'react-native-sentry';
import { TOTAL_BAR_HEIGHT } from '../ui/components/standardHeader/style/StandardHeader';
import { memberSize } from '../ui/screens/memberList/style/MemberList';
......@@ -38,6 +37,7 @@ const members = function* members(action) {
const response = yield call(apiRequest, 'members', data, params);
yield put(memberActions.success(response.results, response.next, keywords));
} catch (error) {
Sentry.captureException(error);
yield put(memberActions.failure());
}
};
......@@ -61,6 +61,7 @@ const more = function* more(action) {
const responseJson = yield fetch(url, data).then(response => response.json());
yield put(memberActions.moreSuccess(responseJson.results, responseJson.next));
} catch (error) {
Sentry.captureException(error);
yield put(memberActions.moreSuccess([], null));
}
};
......
import {
call, put, takeEvery, select,
} from 'redux-saga/effects';
import { call, put, takeEvery, select } from 'redux-saga/effects';
import { Sentry } from 'react-native-sentry';
import { apiRequest, tokenSelector } from '../utils/url';
import * as pizzaActions from '../actions/pizza';
......@@ -33,6 +32,7 @@ const retrievePizzaInfo = function* retrievePizzaInfo() {
if (error.response !== null && error.response.status === NOT_FOUND) {
yield put(pizzaActions.success(event, null, pizzaList));
} else {
Sentry.captureException(error);
yield put(pizzaActions.failure());
}
}
......@@ -40,6 +40,7 @@ const retrievePizzaInfo = function* retrievePizzaInfo() {
if (error.response !== null && error.response.status === NOT_FOUND) {
yield put(pizzaActions.success(null, null, []));
} else {
Sentry.captureException(error);
yield put(pizzaActions.failure());
}
}
......@@ -60,6 +61,7 @@ const cancel = function* cancel() {
yield call(apiRequest, 'pizzas/orders/me', data);
yield put(pizzaActions.cancelSuccess());
} catch (error) {
Sentry.captureException(error);
yield put(pizzaActions.failure());
}
};
......@@ -84,6 +86,7 @@ const order = function* order(action) {
const orderData = yield call(apiRequest, route, data);
yield put(pizzaActions.orderSuccess(orderData));
} catch (error) {
Sentry.captureException(error);
yield put(pizzaActions.failure());
}
};
......
import { call, put, takeEvery } from 'redux-saga/effects';
import { Sentry } from 'react-native-sentry';
import { apiRequest } from '../utils/url';
import * as profileActions from '../actions/profile';
......@@ -23,6 +24,7 @@ const profile = function* profile(action) {
const profileData = yield call(apiRequest, `members/${member}`, data);
yield put(profileActions.success(profileData));
} catch (error) {
Sentry.captureException(error);
yield put(profileActions.failure());
}
};
......
import { call, takeEvery, select } from 'redux-saga/effects';
import { Platform } from 'react-native';
import FCM from 'react-native-fcm';
import { Sentry } from 'react-native-sentry';
import { apiRequest, tokenSelector } from '../utils/url';
import * as pushNotificationsActions from '../actions/pushNotifications';
......@@ -43,6 +44,7 @@ const register = function* register() {
try {
yield call(apiRequest, 'devices', data);
} catch (err) {
Sentry.captureException(err);
// eat error, om nom nom
}
};
......
......@@ -3,6 +3,7 @@ import {
call, put, select, takeEvery,
} from 'redux-saga/effects';
import Snackbar from 'react-native-snackbar';
import { Sentry } from 'react-native-sentry';
import { apiRequest, tokenSelector } from '../utils/url';
......@@ -38,6 +39,7 @@ const register = function* register(action) {
}
Snackbar.show({ title: 'Registration successful!' });
} catch (error) {
Sentry.captureException(error);
yield put(eventActions.failure());
}
};
......@@ -71,6 +73,7 @@ const update = function* update(action) {
yield delay(50);
Snackbar.show({ title: 'Successfully updated registration' });
} catch (error) {
Sentry.captureException(error);
yield put(registrationActions.failure());
}
};
......@@ -95,6 +98,7 @@ const cancel = function* cancel(action) {
yield call(apiRequest, `registrations/${registration}`, data);
Snackbar.show({ title: 'Successfully cancelled registration' });
} catch (error) {
Sentry.captureException(error);
// Swallow error for now
}
......@@ -122,6 +126,7 @@ const fields = function* fields(action) {
yield put(registrationActions.showFields(registration, response.fields));
yield put(eventActions.done());
} catch (error) {
Sentry.captureException(error);
yield put(eventActions.failure());
}
};
......
import {
call, put, select, takeEvery,
} from 'redux-saga/effects';
import { call, put, select, takeEvery } from 'redux-saga/effects';
import { Sentry } from 'react-native-sentry';
import { apiRequest, tokenSelector } from '../utils/url';
import * as welcomeActions from '../actions/welcome';
......@@ -29,6 +28,7 @@ const welcome = function* welcome() {
if (error.name === 'TokenInvalidError') {
yield put(loginActions.tokenInvalid());
}
Sentry.captureException(error);
yield put(welcomeActions.failure());
}
};
......
import { AppRegistry } from 'react-native';
import { Sentry } from 'react-native-sentry';
import { SENTRY_DSN } from 'react-native-dotenv';
import App from './app/app';
Sentry.config(SENTRY_DSN).install();
AppRegistry.registerComponent('ThaliApp', () => App);
// Copyright (c) 2015 Doe Pics Hit, Inc. All rights reserved.
#import <Foundation/Foundation.h>
#import <UIKit/UIApplication.h>
typedef NSString*(^BBReturnNSStringCallback)(void);
typedef BOOL (^BBReturnBooleanCallback)(void);
typedef void (^BBCallback)(void);
@interface BuddyBuildSDK : NSObject
// Deprecated
+ (void)setup:(id<UIApplicationDelegate>)bbAppDelegate;
/**
* Initialize the SDK
*
* This should be called at (or near) the start of the appdelegate
*/
+ (void)setup;
/*
* Associate arbitrary key/value pairs with your crash reports and user feedback
* which will be visible from the buddybuild dashboard
*/
+ (void)setMetadataObject:(id)object forKey:(NSString*)key;
/*
* Programatically trigger the screenshot feedback UI without pressing the screenshot buttons
* If you have screenshot feedback disabled through the buddybuild setting,
* you can still trigger it by calling this method
*/
+ (void)takeScreenshotAndShowFeedbackScreen;
/*
* If you distribute a build to someone with their email address, buddybuild can
* figure out who they are and attach their info to feedback and crash reports.
*
* However, if you send out a build to a mailing list, or through TestFlight or
* the App Store we are unable to infer who they are. If you see 'Unknown User'
* this is likely the cause.
* Often you'll know the identity of your user, for example, after they've
* logged in. You can provide buddybuild a callback to identify the current user.
*/
+ (void)setUserDisplayNameCallback:(BBReturnNSStringCallback)bbCallback;
/*
* You might have API keys and other secrets that your app needs to consume.
* However, you may not want to check these secrets into the source code.
*
* You can provide your secrets to buddybuild. Buddybuild can then expose them
* to you at build time through environment variables. These secrets can also be
* configured to be included into built app. We obfuscate the device keys to
* prevent unauthorized access.
*/
+ (NSString*)valueForDeviceKey:(NSString*)bbKey;
/*
* To temporarily disable screenshot interception you can provide a callback
* here.
*
* When screenshotting is turned on through a buddybuild setting, and no
* callback is provided then screenshotting is by default on.
*
* If screenshotting is disabled through the buddybuild setting, then this
* callback has no effect
*
*/
+ (void)setScreenshotAllowedCallback:(BBReturnBooleanCallback)bbCallback;
/*
* Once a piece of feedback is sent this callback will be called
* so you can take additional actions if necessary
*/
+ (void)setScreenshotFeedbackSentCallback:(BBCallback)bbCallback;
/*
* Once a crash report is sent this callback will be called
* so you can take additional actions if necessary
*/
+ (void)setCrashReportSentCallback:(BBCallback)bbCallback;
/*
* Buddybuild Build Number
*/
+ (NSString*)buildNumber;
/*
* Scheme
*/
+ (NSString*)scheme;
/*
* App ID
*/
+ (NSString*)appID;
/*
* Build ID
*/
+ (NSString*)buildID;
/*
* Build Configuration
*/
+ (NSString*)buildConfiguration;
/*
* Branch name for this build
*/
+ (NSString*)branchName;
/* Manually invoke the screenshot tutorial
* If you don't want it to appear on app launch, disable it in the
* dashboard by going to settings -> buddybuildSDK -> Feature Settings and turning off the screenshot tutorial
* You will be able to show it at any time from anywhere in your app
*/
+ (void)showScreenshotTutorial;
+ (void)crash;
/*
* Logs to the console only while the debugger is attached (when running in Xcode)
* They can be downloaded in crash instances and feedbacks in the dashboard
*/
+ (void)log:(NSString *)message;
/*
* Starts recording video when running a UI test case.
* Should be called after each "[[[XCUIApplication alloc] init] launch];" in your UI tests codebase.
* Only run in buddybuild while the UI tests run. It will not run locally, on real iOS devices or on TestFlight and App Store installs.
*/
+ (void)startUITests;
/*
* Stops recording video at the end of a UI test case.
* Should be called before each "[super tearDown];" in your UI tests codebase.
* Only run in buddybuild while the UI tests run. It will not run locally, on real iOS devices or on TestFlight and App Store installs.
*/
+ (void)stopUITests;
/*
* Should be called in your app delegate in -[UIApplication application:didReceiveRemoteNotification:fetchCompletionHandler].
* Only run in buddybuild while the UI tests run. It will not run locally, on real iOS devices or on TestFlight and App Store installs.
*/
+ (void)uiTestsDidReceiveRemoteNotification:(NSDictionary *)userInfo;
/*
* DEPRECATED IN SDK 1.0.16+, use setMetadataObject:forKey:
*/
+ (void)setCrashMetadataObject:(id)object forKey:(NSString*)key __deprecated_msg("Use setMetadataObject:forKey: instead");
/*
* DEPRECATED IN SDK 1.0.17+
*/
+ (NSString*)userEmail __deprecated_msg("No longer available");
@end
@interface UIView (BuddyBuildSDK)
// Certain features of buddybuild involve capturing the screen (either through a static screenshot, or as a video for instant replays in crash reporting or video feedback.
// Your app may contain certain sensitive customer information that you do not want to be included in the video.
// If you set this property to be true, this view will be redacted from the screen capture and blacked out
@property (nonatomic, assign) BOOL buddybuildViewIsPrivate;
@end
module BuddyBuildSDK {
umbrella header "Headers/BuddyBuildSDK.h"
export *
module * { export * }
}
......@@ -8,10 +8,10 @@ PODS:
- FirebaseAnalytics (4.0.5):
- FirebaseCore (~> 4.0)
- FirebaseInstanceID (~> 2.0)
- GoogleToolboxForMac/NSData+zlib (~> 2.1)
- "GoogleToolboxForMac/NSData+zlib (~> 2.1)"
- nanopb (~> 0.3)
- FirebaseCore (4.0.13):
- GoogleToolboxForMac/NSData+zlib (~> 2.1)
- "GoogleToolboxForMac/NSData+zlib (~> 2.1)"
- FirebaseInstanceID (2.0.8):
- FirebaseCore (~> 4.0)
- FirebaseMessaging (2.0.8):
......@@ -23,7 +23,7 @@ PODS:
- GoogleToolboxForMac/Defines (2.1.3)
- GoogleToolboxForMac/Logger (2.1.3):
- GoogleToolboxForMac/Defines (= 2.1.3)
- GoogleToolboxForMac/NSData+zlib (2.1.3):
- "GoogleToolboxForMac/NSData+zlib (2.1.3)":
- GoogleToolboxForMac/Defines (= 2.1.3)
- nanopb (0.3.8):
- nanopb/decode (= 0.3.8)
......@@ -36,6 +36,17 @@ DEPENDENCIES:
- Firebase/Core
- Firebase/Messaging
SPEC REPOS:
https://github.com/cocoapods/specs.git:
- Firebase
- FirebaseAnalytics
- FirebaseCore
- FirebaseInstanceID
- FirebaseMessaging
- GoogleToolboxForMac
- nanopb
- Protobuf
SPEC CHECKSUMS:
Firebase: 710decbbc6d9d48530e9a5dba3209740c3532e05
FirebaseAnalytics: 5b02a63ead2c3f0259cfc7f15e053e440587ecf8
......@@ -48,4 +59,4 @@ SPEC CHECKSUMS:
PODFILE CHECKSUM: 81d414439f1f341b58c306e954d202374221992d
COCOAPODS: 1.3.1
COCOAPODS: 1.5.3
......@@ -5,6 +5,7 @@
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */; };
00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */; };
......@@ -39,8 +40,8 @@
2D1FCA53D8DB5ADD28A3D2F3 /* libPods-ThaliApp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 419A54DF78ED5BAF6B5C40B7 /* libPods-ThaliApp.a */; };
2DCD954D1E0B4F2C00145EB5 /* ThaliAppTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* ThaliAppTests.m */; };
307D8943B1734FD58BC954BD /* Entypo.ttf in Resources */ = {isa = PBXBuildFile; fileRef = F808FC5B0C6A43748E179BF6 /* Entypo.ttf */; };
3103539470FB1FA6DC7AFCA9 /* BuddyBuildSDK.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A28109E09731D9E1C9150FFC /* BuddyBuildSDK.framework */; };
31DB89BD6ABB7E6C0D4D89C8 /* AssetsLibrary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D663FC8A08D100CAC7FAD4C5 /* AssetsLibrary.framework */; };
325E07382108B21800195242 /* libRNSentry.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 321550702108B1DC005FCAF5 /* libRNSentry.a */; };
32D3E4CE1ED98F33004F54F8 /* libBVLinearGradient.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 32D3E4871ED98796004F54F8 /* libBVLinearGradient.a */; };
32D3E4CF1ED98F37004F54F8 /* libRNVectorIcons.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 32D3E4A51ED98796004F54F8 /* libRNVectorIcons.a */; };
32F7BA8C1FEADDF60071BF57 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 32F7BA8B1FEADDF60071BF57 /* GoogleService-Info.plist */; };
......@@ -49,6 +50,7 @@
55F8857C1B5F455D81EBEF10 /* SimpleLineIcons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = FF381FFBF70744E6865413C2 /* SimpleLineIcons.ttf */; };
5E9157361DD0AC6A00FF2AA8 /* libRCTAnimation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E9157331DD0AC6500FF2AA8 /* libRCTAnimation.a */; };
832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 832341B51AAA6A8300B99B32 /* libRCTText.a */; };
86282F35D99D42658946ABCB /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 80528B2CE70648EEBDEA60A8 /* libz.tbd */; };
8E0DDF1C5CDB01FC245CCF36 /* CoreTelephony.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 50E212E90F67B915933C4735 /* CoreTelephony.framework */; };
8FE220E4161B43D0AF59C4AB /* EvilIcons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 3AF00CDF61D94356B607ED10 /* EvilIcons.ttf */; };
A21E44FD484CB5F7DC5B119D /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 099E370E94C3C98C0D230EF1 /* QuartzCore.framework */; };
......@@ -136,6 +138,13 @@
remoteGlobalIDString = 2D02E47A1E0B4A5D006451C7;
remoteInfo = "ThaliApp-tvOS";
};
3215506F2108B1DC005FCAF5 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 3215503F2108B1DB005FCAF5 /* RNSentry.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 134814201AA4EA6300B7C361;
remoteInfo = RNSentry;
};
3235464C1FEBF67100283B3E /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 0E27F218F14040B7AFFA10E0 /* RNI18n.xcodeproj */;
......@@ -427,6 +436,9 @@
2A30344F7F0A4E50A76BDA3F /* Zocial.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Zocial.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Zocial.ttf"; sourceTree = "<group>"; };
2D02E47B1E0B4A5D006451C7 /* ThaliApp-tvOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "ThaliApp-tvOS.app"; sourceTree = BUILT_PRODUCTS_DIR; };
2D02E4901E0B4A5D006451C7 /* ThaliApp-tvOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "ThaliApp-tvOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
32154FFE2108B164005FCAF5 /* libSentry.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libSentry.a; sourceTree = BUILT_PRODUCTS_DIR; };
321550002108B164005FCAF5 /* libSentryReactNative.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libSentryReactNative.a; sourceTree = BUILT_PRODUCTS_DIR; };
3215503F2108B1DB005FCAF5 /* RNSentry.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RNSentry.xcodeproj; path = "../node_modules/react-native-sentry/ios/RNSentry.xcodeproj"; sourceTree = "<group>"; };
32F7BA8A1FEADB6E0071BF57 /* ThaliApp.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = ThaliApp.entitlements; path = ThaliApp/ThaliApp.entitlements; sourceTree = "<group>"; };
32F7BA8B1FEADDF60071BF57 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = "<group>"; };
3AF00CDF61D94356B607ED10 /* EvilIcons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = EvilIcons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/EvilIcons.ttf"; sourceTree = "<group>"; };
......@@ -437,6 +449,7 @@
5E91572D1DD0AC6500FF2AA8 /* RCTAnimation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTAnimation.xcodeproj; path = "../node_modules/react-native/Libraries/NativeAnimation/RCTAnimation.xcodeproj"; sourceTree = "<group>"; };
75C9EFCD7D423E299C5EF1A9 /* Pods-ThaliAppTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ThaliAppTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-ThaliAppTests/Pods-ThaliAppTests.debug.xcconfig"; sourceTree = "<group>"; };
78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = "../node_modules/react-native/Libraries/LinkingIOS/RCTLinking.xcodeproj"; sourceTree = "<group>"; };
80528B2CE70648EEBDEA60A8 /* libz.tbd */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; };
832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = "../node_modules/react-native/Libraries/Text/RCTText.xcodeproj"; sourceTree = "<group>"; };
887D168E428BA8BC8B4BEF89 /* CoreMedia.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMedia.framework; path = System/Library/Frameworks/CoreMedia.framework; sourceTree = SDKROOT; };
8AB867AF03AC45AEB3C80BFA /* RNSnackbar.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNSnackbar.xcodeproj; path = "../node_modules/react-native-snackbar/ios/RNSnackbar.xcodeproj"; sourceTree = "<group>"; };
......@@ -474,6 +487,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
325E07382108B21800195242 /* libRNSentry.a in Frameworks */,
ADBDB9381DFEBF1600ED6528 /* libRCTBlob.a in Frameworks */,
5E9157361DD0AC6A00FF2AA8 /* libRCTAnimation.a in Frameworks */,