Upgrade to RN 0.59.6 and dependencies (#2777)

* Upgrade to RN 0.59.6 and dependencies

* Remove channel loader unused style

* Update to the latest netInfo that fixes a crash

* Do not set default timezone with moment

* Use RN 0.59.8
This commit is contained in:
Elias Nahum 2019-05-13 13:33:18 -04:00 committed by GitHub
parent 87ee3c893e
commit f36ee37402
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
59 changed files with 6560 additions and 5452 deletions

View file

@ -67,4 +67,4 @@ suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy
suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError
[version]
^0.78.0
^0.92.0

View file

@ -76,10 +76,6 @@ post-install:
@# Need to copy custom RNDocumentPicker.m that implements direct access to the document picker in iOS
@cp ./native_modules/RNDocumentPicker.m node_modules/react-native-document-picker/ios/RNDocumentPicker/RNDocumentPicker.m
@# Need to copy custom RNCWebViewManager.java and RNCWEKWebView.m that implements IWA support for the WebView to avoid forking the lib
@cp ./native_modules/RNCWebViewManager.java node_modules/react-native-webview/android/src/main/java/com/reactnativecommunity/webview/RNCWebViewManager.java
@cp ./native_modules/RNCWKWebView.m node_modules/react-native-webview/ios/RNCWKWebView.m
# Need to copy custom RNCookieManagerIOS.m that fixes a crash when cookies does not have expiration date set
@cp ./native_modules/RNCookieManagerIOS.m node_modules/react-native-cookies/ios/RNCookieManagerIOS/RNCookieManagerIOS.m

View file

@ -75,7 +75,7 @@ import com.android.build.OutputFile
project.ext.react = [
entryFile: "index.js",
bundleCommand: "ram-bundle",
bundleConfig: "packager-config.js"
bundleConfig: "metro.config.js"
]
apply from: "../../node_modules/react-native/react.gradle"
@ -107,7 +107,11 @@ def enableProguardInReleaseBuilds = false
android {
compileSdkVersion rootProject.ext.compileSdkVersion
buildToolsVersion rootProject.ext.buildToolsVersion
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
packagingOptions {
pickFirst 'lib/x86_64/libjsc.so'
@ -141,7 +145,7 @@ android {
reset()
enable enableSeparateBuildPerCPUArchitecture
universalApk false // If true, also generate a universal APK
include "armeabi-v7a", "x86"
include "armeabi-v7a", "x86", "arm64-v8a", "x86_64"
}
}
buildTypes {
@ -165,7 +169,7 @@ android {
variant.outputs.each { output ->
// For each separate APK per architecture, set a unique version code as described here:
// http://tools.android.com/tech-docs/new-build-system/user-guide/apk-splits
def versionCodes = ["armeabi-v7a":1, "x86":2]
def versionCodes = ["armeabi-v7a":1, "x86":2, "arm64-v8a": 3, "x86_64": 4]
def abi = output.getFilter(OutputFile.ABI)
if (abi != null) { // null for the universal-debug, universal-release variants
output.versionCodeOverride =
@ -190,7 +194,7 @@ configurations.all {
resolutionStrategy {
eachDependency { DependencyResolveDetails details ->
if (details.requested.name == 'android-jsc') {
details.useTarget group: details.requested.group, name: 'android-jsc-intl', version: 'r236355'
details.useTarget group: details.requested.group, name: 'android-jsc-intl', version: 'r241213'
}
if (details.requested.name == 'play-services-base') {
details.useTarget group: details.requested.group, name: details.requested.name, version: '15.0.1'
@ -236,6 +240,8 @@ dependencies {
implementation project(':rn-fetch-blob')
implementation project(':react-native-webview')
implementation project(':react-native-gesture-handler')
implementation project(':@react-native-community_async-storage')
implementation project(':@react-native-community_netinfo')
// For animated GIF support
implementation 'com.facebook.fresco:fresco:1.10.0'

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<application android:usesCleartextTraffic="true" tools:targetApi="28" tools:ignore="GoogleAppIndexingWarning" />
</manifest>

View file

@ -2,7 +2,6 @@
package="com.mattermost.rnbeta">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.CAMERA"/>

View file

@ -22,6 +22,8 @@ import com.masteratul.exceptionhandler.ReactNativeExceptionHandlerPackage;
import com.RNFetchBlob.RNFetchBlobPackage;
import com.gantix.JailMonkey.JailMonkeyPackage;
import io.tradle.react.LocalAuthPackage;
import com.reactnativecommunity.asyncstorage.AsyncStoragePackage;
import com.reactnativecommunity.netinfo.NetInfoPackage;
import com.reactnativecommunity.webview.RNCWebViewPackage;
import com.swmansion.gesturehandler.react.RNGestureHandlerPackage;
@ -100,6 +102,8 @@ public class MainApplication extends NavigationApplication implements INotificat
new SharePackage(this),
new KeychainPackage(),
new InitializationPackage(this),
new AsyncStoragePackage(),
new NetInfoPackage(),
new RNCWebViewPackage(),
new RNGestureHandlerPackage()
);

View file

@ -43,3 +43,7 @@ include ':react-native-linear-gradient'
project(':react-native-linear-gradient').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-linear-gradient/android')
include ':react-native-webview'
project(':react-native-webview').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-webview/android')
include ':@react-native-community_async-storage'
project(':@react-native-community_async-storage').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-community/async-storage/android')
include ':@react-native-community_netinfo'
project(':@react-native-community_netinfo').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-community/netinfo/android')

View file

@ -2,7 +2,8 @@
// See LICENSE.txt for license information.
/* eslint-disable global-require*/
import {AsyncStorage, Linking, NativeModules, Platform, Text} from 'react-native';
import {Linking, NativeModules, Platform, Text} from 'react-native';
import AsyncStorage from '@react-native-community/async-storage';
import {setGenericPassword, getGenericPassword, resetGenericPassword} from 'react-native-keychain';
import {loadMe} from 'mattermost-redux/actions/users';

View file

@ -17,4 +17,4 @@ function mapStateToProps(state) {
};
}
export default connect(mapStateToProps, null, null, {withRef: true})(Autocomplete);
export default connect(mapStateToProps, null, null, {forwardRef: true})(Autocomplete);

View file

@ -7,7 +7,7 @@ import {
Platform,
View,
} from 'react-native';
import Placeholder from 'rn-placeholder';
import {ImageContent} from 'rn-placeholder';
import EventEmitter from 'mattermost-redux/utils/event_emitter';
@ -76,7 +76,7 @@ export default class ChannelLoader extends PureComponent {
key={key}
style={[style.section, {backgroundColor: bg}]}
>
<Placeholder.ImageContent
<ImageContent
size={32}
animate='fade'
lineNumber={3}

View file

@ -5,7 +5,7 @@ import React from 'react';
import {Animated, Text} from 'react-native';
import {shallow} from 'enzyme';
import Fade, {FADE_DURATION} from './fade';
import Fade from './fade';
jest.useFakeTimers();
@ -28,15 +28,6 @@ describe('Fade', () => {
);
}
function getAnimValue(begin, end) {
const animValue = new Animated.Value(begin);
animValue.setValue(end);
animValue.stopTracking();
return animValue;
}
test('should render {opacity: 1}', () => {
const wrapper = getWrapper({visible: true});
@ -51,15 +42,6 @@ describe('Fade', () => {
expect(wrapper).toHaveStyle('opacity', new Animated.Value(0));
});
test('should change opacity from 1 to 0', () => {
const wrapper = getWrapper({visible: true});
expect(wrapper).toHaveStyle('opacity', new Animated.Value(1));
wrapper.setProps({visible: false});
jest.advanceTimersByTime(FADE_DURATION);
expect(wrapper).toHaveStyle('opacity', getAnimValue(1, 0));
});
test('should not change opacity when disabled flag is switched', () => {
const wrapper = getWrapper({disabled: false});

View file

@ -1,7 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`PostAttachmentOpenGraph should match snapshot with a single image file 1`] = `
<ScrollView
<ScrollViewMock
horizontal={true}
scrollEnabled={false}
style={
@ -66,5 +66,5 @@ exports[`PostAttachmentOpenGraph should match snapshot with a single image file
}
}
/>
</ScrollView>
</ScrollViewMock>
`;

View file

@ -5,6 +5,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import {intlShape} from 'react-intl';
import {Text} from 'react-native';
import moment from 'moment-timezone';
export default class FormattedTime extends React.PureComponent {
static propTypes = {
@ -28,8 +29,7 @@ export default class FormattedTime extends React.PureComponent {
} = this.props;
if (timeZone) {
return intl.formatDate(value, {
timeZone,
return intl.formatDate(moment.tz(value, timeZone).toDate(), {
hour: 'numeric',
minute: 'numeric',
hour12,
@ -37,17 +37,11 @@ export default class FormattedTime extends React.PureComponent {
}
// If no timezone is defined fallback to the previous implementation
const date = new Date(value);
const militaryTime = !hour12;
const hour = militaryTime ? date.getHours() : (date.getHours() % 12 || 12);
let minute = date.getMinutes();
minute = minute >= 10 ? minute : ('0' + minute);
let time = '';
if (!militaryTime) {
time = (date.getHours() >= 12 ? ' PM' : ' AM');
}
return hour + ':' + minute + time;
return intl.formatDate(new Date(value), {
hour: 'numeric',
minute: 'numeric',
hour12,
});
};
render() {

View file

@ -123,8 +123,8 @@ export default class Markdown extends PureComponent {
htmlInline: this.renderHtml,
table: this.renderTable,
table_row: MarkdownTableRow,
table_cell: MarkdownTableCell,
table_row: this.renderTableRow,
table_cell: this.renderTableCell,
mention_highlight: Renderer.forwardChildren,
@ -379,6 +379,14 @@ export default class Markdown extends PureComponent {
);
};
renderTableRow = (args) => {
return <MarkdownTableRow {...args}/>;
};
renderTableCell = (args) => {
return <MarkdownTableCell {...args}/>;
};
renderLink = ({children, href}) => {
return (
<MarkdownLink

View file

@ -9,11 +9,11 @@ import {
Alert,
Animated,
AppState,
NetInfo,
Platform,
StyleSheet,
View,
} from 'react-native';
import NetInfo from '@react-native-community/netinfo';
import IonIcon from 'react-native-vector-icons/Ionicons';
import FormattedText from 'app/components/formatted_text';

View file

@ -79,6 +79,12 @@ export default class Post extends PureComponent {
intl: intlShape.isRequired,
};
constructor(props) {
super(props);
this.postBodyRef = React.createRef();
}
goToUserProfile = () => {
const {intl} = this.context;
const {navigator, post, theme} = this.props;
@ -229,8 +235,8 @@ export default class Post extends PureComponent {
});
showPostOptions = () => {
if (this.refs.postBody) {
this.refs.postBody.getWrappedInstance().showPostOptions();
if (this.postBodyRef?.current) {
this.postBodyRef.current.showPostOptions();
}
};
@ -337,7 +343,7 @@ export default class Post extends PureComponent {
<View style={rightColumnStyle}>
{postHeader}
<PostBody
ref={'postBody'}
ref={this.postBodyRef}
highlight={highlight}
channelIsReadOnly={channelIsReadOnly}
isLastPost={isLastPost}

View file

@ -93,7 +93,7 @@ exports[`PostAttachmentOpenGraph should match snapshot, without image and descri
<TouchableWithoutFeedback
onPress={[Function]}
>
<Component
<Image
resizeMode="contain"
style={
Array [
@ -267,7 +267,7 @@ exports[`PostAttachmentOpenGraph should match state and snapshot, on renderImage
<TouchableWithoutFeedback
onPress={[Function]}
>
<Component
<Image
resizeMode="contain"
style={
Array [

View file

@ -99,4 +99,4 @@ function makeMapStateToProps() {
};
}
export default connect(makeMapStateToProps, null, null, {withRef: true})(PostBody);
export default connect(makeMapStateToProps, null, null, {forwardRef: true})(PostBody);

View file

@ -27,7 +27,7 @@ exports[`PostPreHeader should match snapshot when flagged and not pinned 1`] = `
}
}
>
<Component
<Image
id="flagIcon"
source={
Object {
@ -96,7 +96,7 @@ exports[`PostPreHeader should match snapshot when pinned and flagged 1`] = `
}
}
>
<Component
<Image
id="pinIcon"
source={
Object {
@ -118,7 +118,7 @@ exports[`PostPreHeader should match snapshot when pinned and flagged 1`] = `
}
}
/>
<Component
<Image
id="flagIcon"
source={
Object {
@ -185,7 +185,7 @@ exports[`PostPreHeader should match snapshot when pinned and flagged but skippin
}
}
>
<Component
<Image
id="pinIcon"
source={
Object {
@ -250,7 +250,7 @@ exports[`PostPreHeader should match snapshot when pinned and flagged but skippin
}
}
>
<Component
<Image
id="flagIcon"
source={
Object {
@ -315,7 +315,7 @@ exports[`PostPreHeader should match snapshot when pinned and not flagged 1`] = `
}
}
>
<Component
<Image
id="pinIcon"
source={
Object {

View file

@ -41,7 +41,6 @@ exports[`DateHeader component should match snapshot when timezone is set 1`] = `
"fontWeight": "600",
}
}
timeZone="America/New_York"
value={1970-01-18T17:19:12.392Z}
weekday="short"
year="numeric"

View file

@ -7,6 +7,7 @@ import {
View,
ViewPropTypes,
} from 'react-native';
import moment from 'moment-timezone';
import FormattedDate from 'app/components/formatted_date';
import {makeStyleSheetFromTheme} from 'app/utils/theme';
@ -33,7 +34,7 @@ export default class DateHeader extends PureComponent {
};
if (timeZone) {
dateFormatProps.timeZone = timeZone;
dateFormatProps.value = moment.tz(date, timeZone).toDate();
}
return (

View file

@ -83,4 +83,4 @@ function mapDispatchToProps(dispatch) {
};
}
export default connect(mapStateToProps, mapDispatchToProps, null, {withRef: true})(PostTextbox);
export default connect(mapStateToProps, mapDispatchToProps, null, {forwardRef: true})(PostTextbox);

View file

@ -13,4 +13,4 @@ function mapStateToProps(state) {
};
}
export default connect(mapStateToProps)(ProgressiveImage);
export default connect(mapStateToProps, null, null, {forwardRef: true})(ProgressiveImage);

View file

@ -59,6 +59,7 @@ export default class DrawerSwiper extends Component {
showTeamsPage = () => {
if (this.refs.swiper) {
this.refs.swiper.scrollToIndex(0, true);
this.swiperPageSelected(0);
}
};

View file

@ -16,4 +16,4 @@ function mapStateToProps(state) {
};
}
export default connect(mapStateToProps, null, null, {withRef: true})(DraweSwiper);
export default connect(mapStateToProps, null, null, {forwardRef: true})(DraweSwiper);

View file

@ -61,4 +61,4 @@ function mapDispatchToProps(dispatch) {
};
}
export default connect(mapStateToProps, mapDispatchToProps, null, {withRef: true})(MainSidebar);
export default connect(mapStateToProps, mapDispatchToProps, null, {forwardRef: true})(MainSidebar);

View file

@ -276,14 +276,14 @@ export default class ChannelSidebar extends Component {
};
showTeams = () => {
if (this.drawerSwiper && this.swiperIndex === 1 && this.props.teamsCount > 1) {
this.drawerSwiper.getWrappedInstance().showTeamsPage();
if (this.drawerSwiper && this.props.teamsCount > 1) {
this.drawerSwiper.showTeamsPage();
}
};
resetDrawer = () => {
if (this.drawerSwiper && this.swiperIndex !== 1) {
this.drawerSwiper.getWrappedInstance().resetPage();
if (this.drawerSwiper) {
this.drawerSwiper.resetPage();
}
};
@ -308,9 +308,9 @@ export default class ChannelSidebar extends Component {
const showTeams = !searching && multipleTeams;
if (this.drawerSwiper) {
if (multipleTeams) {
this.drawerSwiper.getWrappedInstance().runOnLayout();
this.drawerSwiper.runOnLayout();
} else if (!openDrawerOffset) {
this.drawerSwiper.getWrappedInstance().scrollToStart();
this.drawerSwiper.scrollToStart();
}
}

View file

@ -33,4 +33,4 @@ function mapDispatchToProps(dispatch) {
};
}
export default connect(mapStateToProps, mapDispatchToProps, null, {withRef: true})(SettingsSidebar);
export default connect(mapStateToProps, mapDispatchToProps, null, {forwardRef: true})(SettingsSidebar);

View file

@ -14,4 +14,4 @@ function mapStateToProps(state, ownProps) {
};
}
export default connect(mapStateToProps, null, null, {withRef: true})(SlideUpPanel);
export default connect(mapStateToProps, null, null, {forwardRef: true})(SlideUpPanel);

View file

@ -4,12 +4,10 @@
import React, {PureComponent} from 'react';
import PropTypes from 'prop-types';
import {
View,
ScrollView,
ViewPagerAndroid,
Platform,
StyleSheet,
InteractionManager,
ScrollView,
StyleSheet,
View,
} from 'react-native';
export default class Swiper extends PureComponent {
@ -91,34 +89,20 @@ export default class Swiper extends PureComponent {
this.updateIndex(e.nativeEvent.contentOffset.x);
};
onPageScrollStateChanged = (e) => {
switch (e) {
case 'dragging':
this.props.onScrollBegin();
break;
}
};
scrollByWidth = (width) => {
this.offset = width * this.state.index;
if (Platform.OS === 'ios') {
setTimeout(() => {
if (this.scrollView) {
this.scrollView.scrollTo({x: width * this.state.index, animated: false});
}
}, 0);
} else if (this.scrollView) {
this.scrollView.setPageWithoutAnimation(this.state.index);
}
setTimeout(() => {
if (this.scrollView) {
this.scrollView.scrollTo({x: width * this.state.index, animated: false});
}
}, 0);
};
scrollToStart = () => {
if (Platform.OS === 'ios') {
InteractionManager.runAfterInteractions(() => {
this.scrollView.scrollTo({x: 0, animated: false});
});
}
InteractionManager.runAfterInteractions(() => {
this.scrollView.scrollTo({x: 0, animated: false});
});
};
refScrollView = (view) => {
@ -131,39 +115,24 @@ export default class Swiper extends PureComponent {
scrollEnabled,
} = this.props;
if (Platform.OS === 'ios') {
return (
<ScrollView
ref={this.refScrollView}
bounces={false}
horizontal={true}
removeClippedSubviews={true}
automaticallyAdjustContentInsets={true}
showsHorizontalScrollIndicator={false}
showsVerticalScrollIndicator={false}
contentContainerStyle={[styles.wrapperIOS, this.props.style]}
onScrollBeginDrag={this.onScrollBegin}
onMomentumScrollEnd={this.onScrollEnd}
pagingEnabled={scrollEnabled}
keyboardShouldPersistTaps={keyboardShouldPersistTaps}
scrollEnabled={scrollEnabled}
>
{pages}
</ScrollView>
);
}
return (
<ViewPagerAndroid
<ScrollView
ref={this.refScrollView}
initialPage={this.props.initialPage}
onPageSelected={this.onScrollEnd}
onPageScrollStateChanged={this.onPageScrollStateChanged}
bounces={false}
horizontal={true}
removeClippedSubviews={true}
automaticallyAdjustContentInsets={true}
showsHorizontalScrollIndicator={false}
showsVerticalScrollIndicator={false}
contentContainerStyle={[styles.wrapper, this.props.style]}
onScrollBeginDrag={this.onScrollBegin}
onMomentumScrollEnd={this.onScrollEnd}
pagingEnabled={scrollEnabled}
keyboardShouldPersistTaps={keyboardShouldPersistTaps}
scrollEnabled={scrollEnabled}
key={pages.length}
style={[styles.wrapperAndroid, this.props.style]}
>
{pages}
</ViewPagerAndroid>
</ScrollView>
);
};
@ -212,21 +181,9 @@ export default class Swiper extends PureComponent {
return;
}
if (Platform.OS === 'ios') {
this.scrollView.scrollTo({x: (index * this.props.width), animated});
} else {
this.scrollView[animated ? 'setPage' : 'setPageWithoutAnimation'](index);
}
// trigger onScrollEnd manually in android or if not animated
if (!animated || Platform.OS === 'android') {
setImmediate(() => {
this.onScrollEnd({
nativeEvent: {
position: index,
},
});
});
this.scrollView.scrollTo({x: (index * this.props.width), animated});
if (index === 0) {
this.offset = 0;
}
};
@ -278,13 +235,9 @@ const styles = StyleSheet.create({
position: 'relative',
flex: 1,
},
wrapperIOS: {
wrapper: {
backgroundColor: 'transparent',
},
wrapperAndroid: {
backgroundColor: 'transparent',
flex: 1,
},
slide: {
flex: 1,
width: '100%',

View file

@ -1,7 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`UserStatus should match snapshot, away status 1`] = `
<Component
<Image
source={
Object {
"testUri": "../../../dist/assets/images/status/away.png",
@ -18,7 +18,7 @@ exports[`UserStatus should match snapshot, away status 1`] = `
`;
exports[`UserStatus should match snapshot, dnd status 1`] = `
<Component
<Image
source={
Object {
"testUri": "../../../dist/assets/images/status/dnd.png",
@ -35,7 +35,7 @@ exports[`UserStatus should match snapshot, dnd status 1`] = `
`;
exports[`UserStatus should match snapshot, online status 1`] = `
<Component
<Image
source={
Object {
"testUri": "../../../dist/assets/images/status/online.png",
@ -52,7 +52,7 @@ exports[`UserStatus should match snapshot, online status 1`] = `
`;
exports[`UserStatus should match snapshot, should default to offline status 1`] = `
<Component
<Image
source={
Object {
"testUri": "../../../dist/assets/images/status/offline.png",

View file

@ -151,8 +151,8 @@ export default class Channel extends PureComponent {
};
blurPostTextBox = () => {
if (this.postTextbox && this.postTextbox.getWrappedInstance()) {
this.postTextbox.getWrappedInstance().blur();
if (this.postTextbox) {
this.postTextbox.blur();
}
};
@ -184,13 +184,13 @@ export default class Channel extends PureComponent {
channelSidebarRef = (ref) => {
if (ref) {
this.channelSidebar = ref.getWrappedInstance();
this.channelSidebar = ref;
}
};
settingsSidebarRef = (ref) => {
if (ref) {
this.settingsSidebar = ref.getWrappedInstance();
this.settingsSidebar = ref;
}
};

View file

@ -24,7 +24,7 @@ exports[`ForgotPassword match snapshot after success of sendPasswordResetEmail 1
}
}
>
<Component
<Image
source={
Object {
"testUri": "../../../dist/assets/images/logo.png",
@ -108,7 +108,7 @@ exports[`ForgotPassword should match snapshot 1`] = `
}
}
>
<Component
<Image
source={
Object {
"testUri": "../../../dist/assets/images/logo.png",
@ -143,6 +143,7 @@ exports[`ForgotPassword should match snapshot 1`] = `
disableFullscreenUI={true}
keyboardType="email-address"
onChangeText={[Function]}
rejectResponderTermination={true}
style={
Object {
"alignSelf": "stretch",
@ -217,7 +218,7 @@ exports[`ForgotPassword snapshot for error on failure of email regex 1`] = `
}
}
>
<Component
<Image
source={
Object {
"testUri": "../../../dist/assets/images/logo.png",
@ -252,6 +253,7 @@ exports[`ForgotPassword snapshot for error on failure of email regex 1`] = `
disableFullscreenUI={true}
keyboardType="email-address"
onChangeText={[Function]}
rejectResponderTermination={true}
style={
Object {
"alignSelf": "stretch",

View file

@ -79,4 +79,4 @@ function mapDispatchToProps(dispatch) {
};
}
export default connect(makeMapStateToProps, mapDispatchToProps, null, {withRef: true})(Permalink);
export default connect(makeMapStateToProps, mapDispatchToProps, null, {forwardRef: true})(Permalink);

View file

@ -8,7 +8,7 @@ exports[`PostOptions should match snapshot, no option for system message to user
}
}
>
<Connect(SlideUpPanel)
<ForwardRef(forwardConnectRef)
allowStayMiddle={false}
initialPosition={250}
marginFromTop={350}
@ -34,7 +34,7 @@ exports[`PostOptions should match snapshot, no option for system message to user
onPress={[Function]}
text="Add Reaction"
/>
</Connect(SlideUpPanel)>
</ForwardRef(forwardConnectRef)>
</View>
`;
@ -46,7 +46,7 @@ exports[`PostOptions should match snapshot, showing Delete option only for syste
}
}
>
<Connect(SlideUpPanel)
<ForwardRef(forwardConnectRef)
allowStayMiddle={false}
initialPosition={300}
marginFromTop={300}
@ -78,7 +78,7 @@ exports[`PostOptions should match snapshot, showing Delete option only for syste
onPress={[Function]}
text="Delete"
/>
</Connect(SlideUpPanel)>
</ForwardRef(forwardConnectRef)>
</View>
`;
@ -90,7 +90,7 @@ exports[`PostOptions should match snapshot, showing all possible options 1`] = `
}
}
>
<Connect(SlideUpPanel)
<ForwardRef(forwardConnectRef)
allowStayMiddle={false}
initialPosition={300}
marginFromTop={300}
@ -122,6 +122,6 @@ exports[`PostOptions should match snapshot, showing all possible options 1`] = `
onPress={[Function]}
text="Delete"
/>
</Connect(SlideUpPanel)>
</ForwardRef(forwardConnectRef)>
</View>
`;

View file

@ -56,7 +56,7 @@ export default class PostOptions extends PureComponent {
closeWithAnimation = () => {
if (this.slideUpPanel) {
this.slideUpPanel.getWrappedInstance().closeWithAnimation();
this.slideUpPanel.closeWithAnimation();
} else {
this.close();
}

View file

@ -1,7 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`ReactionHeader should match snapshot 1`] = `
<Handler>
<NativeViewGestureHandler>
<AnimatedComponent
style={
Object {
@ -13,7 +13,7 @@ exports[`ReactionHeader should match snapshot 1`] = `
}
}
>
<ScrollView
<ScrollViewMock
alwaysBounceHorizontal={false}
horizontal={true}
overScrollMode="never"
@ -86,9 +86,9 @@ exports[`ReactionHeader should match snapshot 1`] = `
}
}
/>
</ScrollView>
</ScrollViewMock>
</AnimatedComponent>
</Handler>
</NativeViewGestureHandler>
`;
exports[`ReactionHeader should match snapshot, renderContent 1`] = `

View file

@ -8,7 +8,7 @@ exports[`ReactionList should match snapshot 1`] = `
}
}
>
<Connect(SlideUpPanel)
<ForwardRef(forwardConnectRef)
header={[Function]}
headerHeight={37.5}
initialPosition={0.55}
@ -158,7 +158,7 @@ exports[`ReactionList should match snapshot 1`] = `
}
/>
</View>
</Connect(SlideUpPanel)>
</ForwardRef(forwardConnectRef)>
</View>
`;

View file

@ -128,7 +128,7 @@ export default class ReactionList extends PureComponent {
this.setState({selected: emoji});
if (this.slideUpPanel) {
this.slideUpPanel.getWrappedInstance().scrollToTop();
this.slideUpPanel.scrollToTop();
}
};

View file

@ -301,7 +301,7 @@ export default class Search extends PureComponent {
onNavigatorEvent = (event) => {
if (event.id === 'backPress') {
if (this.state.preview) {
this.refs.preview.getWrappedInstance().handleClose();
this.refs.preview.handleClose();
} else {
this.props.navigator.dismissModal();
}

View file

@ -3,7 +3,7 @@
exports[`TermsOfService should enable/disable navigator buttons on setNavigatorButtons true/false 1`] = `
<React.Fragment>
<Connect(StatusBar) />
<ScrollView
<ScrollViewMock
contentContainerStyle={
Object {
"paddingBottom": 50,
@ -225,14 +225,14 @@ exports[`TermsOfService should enable/disable navigator buttons on setNavigatorB
}
value="Terms Text"
/>
</ScrollView>
</ScrollViewMock>
</React.Fragment>
`;
exports[`TermsOfService should enable/disable navigator buttons on setNavigatorButtons true/false 2`] = `
<React.Fragment>
<Connect(StatusBar) />
<ScrollView
<ScrollViewMock
contentContainerStyle={
Object {
"paddingBottom": 50,
@ -477,7 +477,7 @@ exports[`TermsOfService should enable/disable navigator buttons on setNavigatorB
}
value="Terms Text"
/>
</ScrollView>
</ScrollViewMock>
</React.Fragment>
`;
@ -556,7 +556,7 @@ exports[`TermsOfService should match snapshot for get terms 1`] = `
exports[`TermsOfService should match snapshot on enableNavigatorLogout 1`] = `
<React.Fragment>
<Connect(StatusBar) />
<ScrollView
<ScrollViewMock
contentContainerStyle={
Object {
"paddingBottom": 50,
@ -778,6 +778,6 @@ exports[`TermsOfService should match snapshot on enableNavigatorLogout 1`] = `
}
value="Terms Text"
/>
</ScrollView>
</ScrollViewMock>
</React.Fragment>
`;

View file

@ -56,7 +56,7 @@ exports[`thread should match snapshot, has root post 1`] = `
/>
}
/>
<Connect(PostTextbox)
<ForwardRef(forwardConnectRef)
channelId="channel_id"
channelIsArchived={false}
navigator={

View file

@ -9,7 +9,7 @@ exports[`user_profile should match snapshot 1`] = `
}
>
<Connect(StatusBar) />
<ScrollView
<ScrollViewMock
style={
Object {
"backgroundColor": "#ffffff",
@ -193,6 +193,6 @@ exports[`user_profile should match snapshot 1`] = `
}
togglable={false}
/>
</ScrollView>
</ScrollViewMock>
</View>
`;

View file

@ -2,7 +2,8 @@
// See LICENSE.txt for license information.
import {batchActions} from 'redux-batched-actions';
import {AsyncStorage, Platform} from 'react-native';
import {Platform} from 'react-native';
import AsyncStorage from '@react-native-community/async-storage';
import {createBlacklistFilter} from 'redux-persist-transform-filter';
import {createTransform, persistStore} from 'redux-persist';

View file

@ -1,8 +1,8 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {NetInfo, Platform} from 'react-native';
import {Platform} from 'react-native';
import NetInfo from '@react-native-community/netinfo';
import RNFetchBlob from 'rn-fetch-blob';
import {Client4} from 'mattermost-redux/client';

View file

@ -82,6 +82,10 @@ desc 'Increment version number for both Android and iOS'
lane :set_app_version do
version_number = ENV['VERSION_NUMBER']
unless version_number.nil? || version_number.empty?
package = load_config_json('../package.json')
package['version'] = version_number
save_config_json('../package.json', package)
android_set_version_name(
gradle_file: './android/app/build.gradle',
version_name: version_number
@ -140,7 +144,7 @@ end
desc 'Configure the app before building'
lane :configure do
json = load_config_json
json = load_config_json('../dist/assets/config.json')
# Set the Segment API Key
unless ENV['SEGMENT_API_KEY'].nil? || ENV['SEGMENT_API_KEY'].empty?
@ -158,7 +162,7 @@ lane :configure do
end
# Save the config.json file
save_config_json(json)
save_config_json('../dist/assets/config.json', json)
configured = true
end
@ -295,10 +299,6 @@ platform :ios do
app_group_identifiers: [app_group_id]
)
# Save changes to the config.json file
config_json = load_config_json
save_config_json(config_json)
# Sync the provisioning profiles using match
if ENV['SYNC_PROVISIONING_PROFILES'] == 'true'
match(type: ENV['MATCH_TYPE'] || 'adhoc')
@ -507,15 +507,13 @@ platform :android do
end
end
def load_config_json
config_path = '../dist/assets/config.json'
config_file = File.read(config_path)
def load_config_json(json_path)
config_file = File.read(json_path)
JSON.parse(config_file)
end
def save_config_json(json)
config_path = '../dist/assets/config.json'
File.open(config_path, 'w') do |f|
def save_config_json(json_path, json)
File.open(json_path, 'w') do |f|
f.write(JSON.pretty_generate(json))
end
end

View file

@ -2,7 +2,7 @@
// See LICENSE.txt for license information.
import 'react-native/Libraries/Core/InitializeCore';
import {AppRegistry, DeviceEventEmitter, Platform} from 'react-native';
import {AppRegistry, DeviceEventEmitter, Platform, YellowBox} from 'react-native';
import 'react-native-gesture-handler';
import LocalConfig from 'assets/config';
@ -12,6 +12,12 @@ import telemetry from 'app/telemetry';
import 'app/mattermost';
import ShareExtension from 'share_extension/android';
YellowBox.ignoreWarnings([
'Warning: componentWillMount is deprecated',
'Warning: componentWillUpdate is deprecated',
'Warning: componentWillReceiveProps is deprecated',
]);
if (Platform.OS === 'android') {
AppRegistry.registerComponent('MattermostShare', () => ShareExtension);

View file

@ -5,7 +5,6 @@
};
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 */; };
@ -52,6 +51,7 @@
7BD159C40A68467FB5A17141 /* FontAwesome5_Solid.ttf in Resources */ = {isa = PBXBuildFile; fileRef = DC1D660B55BE462A9C3B8028 /* FontAwesome5_Solid.ttf */; };
7F151D3E221B062700FAD8F3 /* RuntimeUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F151D3D221B062700FAD8F3 /* RuntimeUtils.swift */; };
7F151D41221B069200FAD8F3 /* 0155-keys.png in Resources */ = {isa = PBXBuildFile; fileRef = 7F151D40221B069200FAD8F3 /* 0155-keys.png */; };
7F1A56B4227E38B600EF7A90 /* libRNCAsyncStorage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7F1A569B227E389600EF7A90 /* libRNCAsyncStorage.a */; };
7F240A1C220D3A2300637665 /* ShareViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F240A1B220D3A2300637665 /* ShareViewController.swift */; };
7F240A1F220D3A2300637665 /* MainInterface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7F240A1D220D3A2300637665 /* MainInterface.storyboard */; };
7F240A23220D3A2300637665 /* MattermostShare.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 7F240A19220D3A2300637665 /* MattermostShare.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
@ -74,6 +74,7 @@
7F43D6061F6BF9EB001FC614 /* libPods-Mattermost.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7F43D6051F6BF9EB001FC614 /* libPods-Mattermost.a */; };
7F43D63F1F6BFA19001FC614 /* libBVLinearGradient.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 37D8FEC21E80B5230091F3BD /* libBVLinearGradient.a */; };
7F43D6401F6BFA82001FC614 /* libRCTPushNotification.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7F63D2811E6C957C001FAE12 /* libRCTPushNotification.a */; };
7F4C2598227E3B11009144EF /* libRNCNetInfo.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7F4C2595227E3AE9009144EF /* libRNCNetInfo.a */; };
7F5CA9A0208FE3B9004F91CE /* libRNDocumentPicker.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7F5CA991208FE38F004F91CE /* libRNDocumentPicker.a */; };
7F642DF02093533300F3165E /* libRNDeviceInfo.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7F642DED2093530B00F3165E /* libRNDeviceInfo.a */; };
7F72F2EE2211220500F98FFF /* GenericPreview.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7F72F2ED2211220500F98FFF /* GenericPreview.xib */; };
@ -362,6 +363,20 @@
remoteGlobalIDString = 134814201AA4EA6300B7C361;
remoteInfo = RCTLinking;
};
7F1A569A227E389600EF7A90 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 7F1A5663227E389600EF7A90 /* RNCAsyncStorage.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 134814201AA4EA6300B7C361;
remoteInfo = RNCAsyncStorage;
};
7F1A56A4227E389600EF7A90 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 920B7301B6F84DDD80677487 /* RNGestureHandler.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = B5C32A36220C603B000FFB8D;
remoteInfo = "RNGestureHandler-tvOS";
};
7F240A21220D3A2300637665 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */;
@ -418,6 +433,20 @@
remoteGlobalIDString = 3DBE0D0D1F3B181C0099AA32;
remoteInfo = "fishhook-tvOS";
};
7F4C2594227E3AE9009144EF /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 7F4C258F227E3AE9009144EF /* RNCNetInfo.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 134814201AA4EA6300B7C361;
remoteInfo = RNCNetInfo;
};
7F4C2596227E3AE9009144EF /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 7F4C258F227E3AE9009144EF /* RNCNetInfo.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = B5027B1B2237B30F00F1AABA;
remoteInfo = "RNCNetInfo-tvOS";
};
7F581C71221DF8DE0099E66B /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
@ -736,6 +765,7 @@
7F151D40221B069200FAD8F3 /* 0155-keys.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "0155-keys.png"; path = "Mattermost/0155-keys.png"; sourceTree = "<group>"; };
7F151D42221B07F700FAD8F3 /* MattermostShare-Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MattermostShare-Bridging-Header.h"; sourceTree = "<group>"; };
7F151D43221B082A00FAD8F3 /* Mattermost-Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "Mattermost-Bridging-Header.h"; path = "Mattermost/Mattermost-Bridging-Header.h"; sourceTree = "<group>"; };
7F1A5663227E389600EF7A90 /* RNCAsyncStorage.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RNCAsyncStorage.xcodeproj; path = "../node_modules/@react-native-community/async-storage/ios/RNCAsyncStorage.xcodeproj"; sourceTree = "<group>"; };
7F240A19220D3A2300637665 /* MattermostShare.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = MattermostShare.appex; sourceTree = BUILT_PRODUCTS_DIR; };
7F240A1B220D3A2300637665 /* ShareViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareViewController.swift; sourceTree = "<group>"; };
7F240A1E220D3A2300637665 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/MainInterface.storyboard; sourceTree = "<group>"; };
@ -754,6 +784,7 @@
7F292AA51E8ABB1100A450A3 /* splash.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = splash.png; path = SplashScreenResource/splash.png; sourceTree = "<group>"; };
7F43D5DF1F6BF994001FC614 /* libRNSVG.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libRNSVG.a; path = "../../../../../../../Library/Developer/Xcode/DerivedData/Mattermost-czlinsdviifujheezzjvmisotjrm/Build/Products/Debug-iphonesimulator/libRNSVG.a"; sourceTree = "<group>"; };
7F43D6051F6BF9EB001FC614 /* libPods-Mattermost.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libPods-Mattermost.a"; path = "../../../../../../../Library/Developer/Xcode/DerivedData/Mattermost-czlinsdviifujheezzjvmisotjrm/Build/Products/Debug-iphonesimulator/libPods-Mattermost.a"; sourceTree = "<group>"; };
7F4C258F227E3AE9009144EF /* RNCNetInfo.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RNCNetInfo.xcodeproj; path = "../node_modules/@react-native-community/netinfo/ios/RNCNetInfo.xcodeproj"; sourceTree = "<group>"; };
7F54ABFAE6CE4A6DB11D1ED7 /* Roboto-BlackItalic.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Roboto-BlackItalic.ttf"; path = "../assets/fonts/Roboto-BlackItalic.ttf"; sourceTree = "<group>"; };
7F5CA956208FE38F004F91CE /* RNDocumentPicker.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RNDocumentPicker.xcodeproj; path = "../node_modules/react-native-document-picker/ios/RNDocumentPicker.xcodeproj"; sourceTree = "<group>"; };
7F63D27B1E6C957C001FAE12 /* RCTPushNotification.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTPushNotification.xcodeproj; path = "../node_modules/react-native/Libraries/PushNotificationIOS/RCTPushNotification.xcodeproj"; sourceTree = "<group>"; };
@ -855,6 +886,8 @@
139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */,
7F43D63F1F6BFA19001FC614 /* libBVLinearGradient.a in Frameworks */,
7FC200E81EBB65370099331B /* libReactNativeNavigation.a in Frameworks */,
7F1A56B4227E38B600EF7A90 /* libRNCAsyncStorage.a in Frameworks */,
7F4C2598227E3B11009144EF /* libRNCNetInfo.a in Frameworks */,
7F2691A11EE1DC6A007574FE /* libRNNotifications.a in Frameworks */,
7F43D5D61F6BF8C2001FC614 /* libRNLocalAuth.a in Frameworks */,
7F43D5D71F6BF8D0001FC614 /* libRNPasscodeStatus.a in Frameworks */,
@ -1178,6 +1211,14 @@
name = Products;
sourceTree = "<group>";
};
7F1A5664227E389600EF7A90 /* Products */ = {
isa = PBXGroup;
children = (
7F1A569B227E389600EF7A90 /* libRNCAsyncStorage.a */,
);
name = Products;
sourceTree = "<group>";
};
7F240A1A220D3A2300637665 /* MattermostShare */ = {
isa = PBXGroup;
children = (
@ -1227,6 +1268,16 @@
isa = PBXGroup;
children = (
7F46E07F21B5AF9E004060B8 /* libRNGestureHandler.a */,
7F1A56A5227E389600EF7A90 /* libRNGestureHandler-tvOS.a */,
);
name = Products;
sourceTree = "<group>";
};
7F4C2590227E3AE9009144EF /* Products */ = {
isa = PBXGroup;
children = (
7F4C2595227E3AE9009144EF /* libRNCNetInfo.a */,
7F4C2597227E3AE9009144EF /* libRNCNetInfo-tvOS.a */,
);
name = Products;
sourceTree = "<group>";
@ -1393,6 +1444,8 @@
isa = PBXGroup;
children = (
7FABE04022137F2900D0F595 /* UploadAttachments.xcodeproj */,
7F1A5663227E389600EF7A90 /* RNCAsyncStorage.xcodeproj */,
7F4C258F227E3AE9009144EF /* RNCNetInfo.xcodeproj */,
7F26C1C6219C463300FEB42D /* RNCWebView.xcodeproj */,
7FF31C0E21330B4200680B75 /* RNFetchBlob.xcodeproj */,
7F5CA956208FE38F004F91CE /* RNDocumentPicker.xcodeproj */,
@ -1588,6 +1641,7 @@
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
English,
en,
Base,
);
@ -1679,6 +1733,14 @@
ProductGroup = 7F7D7F53201645D300D31155 /* Products */;
ProjectRef = 7F7D7F52201645D300D31155 /* ReactNativePermissions.xcodeproj */;
},
{
ProductGroup = 7F1A5664227E389600EF7A90 /* Products */;
ProjectRef = 7F1A5663227E389600EF7A90 /* RNCAsyncStorage.xcodeproj */;
},
{
ProductGroup = 7F4C2590227E3AE9009144EF /* Products */;
ProjectRef = 7F4C258F227E3AE9009144EF /* RNCNetInfo.xcodeproj */;
},
{
ProductGroup = 372E25631F5F0E1800A2BFAB /* Products */;
ProjectRef = 62A58E5E984E4CF1811620B8 /* RNCookieManagerIOS.xcodeproj */;
@ -1996,6 +2058,20 @@
remoteRef = 78C398B81ACF4ADC00677621 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
7F1A569B227E389600EF7A90 /* libRNCAsyncStorage.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libRNCAsyncStorage.a;
remoteRef = 7F1A569A227E389600EF7A90 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
7F1A56A5227E389600EF7A90 /* libRNGestureHandler-tvOS.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = "libRNGestureHandler-tvOS.a";
remoteRef = 7F1A56A4227E389600EF7A90 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
7F2691A01EE1DC51007574FE /* libRNNotifications.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
@ -2045,6 +2121,20 @@
remoteRef = 7F4C1F851FBE572B0029D1DF /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
7F4C2595227E3AE9009144EF /* libRNCNetInfo.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libRNCNetInfo.a;
remoteRef = 7F4C2594227E3AE9009144EF /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
7F4C2597227E3AE9009144EF /* libRNCNetInfo-tvOS.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = "libRNCNetInfo-tvOS.a";
remoteRef = 7F4C2596227E3AE9009144EF /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
7F581C72221DF8DE0099E66B /* libjsi.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
@ -2567,6 +2657,8 @@
"$(SRCROOT)../node_modules/react-native-svg/ios/**",
"$(SRCROOT)/../node_modules/react-native-gesture-handler/ios/**",
"$(SRCROOT)/UploadAttachments/UploadAttachments/**",
"$(SRCROOT)/../node_modules/@react-native-community/async-storage/ios/",
"$(SRCROOT)/../node_modules/@react-native-community/netinfo/ios/",
);
INFOPLIST_FILE = Mattermost/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 10.3;
@ -2625,6 +2717,8 @@
"$(SRCROOT)../node_modules/react-native-svg/ios/**",
"$(SRCROOT)/../node_modules/react-native-gesture-handler/ios/**",
"$(SRCROOT)/UploadAttachments/UploadAttachments/**",
"$(SRCROOT)/../node_modules/@react-native-community/async-storage/ios/",
"$(SRCROOT)/../node_modules/@react-native-community/netinfo/ios/",
);
INFOPLIST_FILE = Mattermost/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 10.3;

View file

@ -1,693 +0,0 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import "RNCWKWebView.h"
#import <React/RCTConvert.h>
#import <React/RCTAutoInsetsProtocol.h>
#import "RNCWKProcessPoolManager.h"
#import <UIKit/UIKit.h>
#import "objc/runtime.h"
static NSTimer *keyboardTimer;
static NSString *const MessageHandlerName = @"ReactNativeWebView";
static NSURLCredential* clientAuthenticationCredential;
// runtime trick to remove WKWebView keyboard default toolbar
// see: http://stackoverflow.com/questions/19033292/ios-7-uiwebview-keyboard-issue/19042279#19042279
@interface _SwizzleHelperWK : NSObject @end
@implementation _SwizzleHelperWK
-(id)inputAccessoryView
{
return nil;
}
@end
@interface RNCWKWebView () <WKUIDelegate, WKNavigationDelegate, WKScriptMessageHandler, UIScrollViewDelegate, RCTAutoInsetsProtocol>
@property (nonatomic, copy) RCTDirectEventBlock onLoadingStart;
@property (nonatomic, copy) RCTDirectEventBlock onLoadingFinish;
@property (nonatomic, copy) RCTDirectEventBlock onLoadingError;
@property (nonatomic, copy) RCTDirectEventBlock onLoadingProgress;
@property (nonatomic, copy) RCTDirectEventBlock onShouldStartLoadWithRequest;
@property (nonatomic, copy) RCTDirectEventBlock onMessage;
@property (nonatomic, copy) WKWebView *webView;
@end
@implementation RNCWKWebView
{
UIColor * _savedBackgroundColor;
BOOL _savedHideKeyboardAccessoryView;
}
- (instancetype)initWithFrame:(CGRect)frame
{
if ((self = [super initWithFrame:frame])) {
super.backgroundColor = [UIColor clearColor];
_bounces = YES;
_scrollEnabled = YES;
_showsHorizontalScrollIndicator = YES;
_showsVerticalScrollIndicator = YES;
_automaticallyAdjustContentInsets = YES;
_contentInset = UIEdgeInsetsZero;
}
// Workaround for a keyboard dismissal bug present in iOS 12
// https://openradar.appspot.com/radar?id=5018321736957952
if (@available(iOS 12.0, *)) {
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(keyboardWillHide)
name:UIKeyboardWillHideNotification object:nil];
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(keyboardWillShow)
name:UIKeyboardWillShowNotification object:nil];
}
return self;
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
/**
* See https://stackoverflow.com/questions/25713069/why-is-wkwebview-not-opening-links-with-target-blank/25853806#25853806 for details.
*/
- (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures
{
if (!navigationAction.targetFrame.isMainFrame) {
[webView loadRequest:navigationAction.request];
}
return nil;
}
- (void)didMoveToWindow
{
if (self.window != nil && _webView == nil) {
WKWebViewConfiguration *wkWebViewConfig = [WKWebViewConfiguration new];
if (_incognito) {
wkWebViewConfig.websiteDataStore = [WKWebsiteDataStore nonPersistentDataStore];
} else if (_cacheEnabled) {
wkWebViewConfig.websiteDataStore = [WKWebsiteDataStore defaultDataStore];
}
if(self.useSharedProcessPool) {
wkWebViewConfig.processPool = [[RNCWKProcessPoolManager sharedManager] sharedProcessPool];
}
wkWebViewConfig.userContentController = [WKUserContentController new];
if (_messagingEnabled) {
[wkWebViewConfig.userContentController addScriptMessageHandler:self name:MessageHandlerName];
NSString *source = [NSString stringWithFormat:
@"window.%@ = {"
" postMessage: function (data) {"
" window.webkit.messageHandlers.%@.postMessage(String(data));"
" }"
"};", MessageHandlerName, MessageHandlerName
];
WKUserScript *script = [[WKUserScript alloc] initWithSource:source injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:YES];
[wkWebViewConfig.userContentController addUserScript:script];
}
wkWebViewConfig.allowsInlineMediaPlayback = _allowsInlineMediaPlayback;
#if WEBKIT_IOS_10_APIS_AVAILABLE
wkWebViewConfig.mediaTypesRequiringUserActionForPlayback = _mediaPlaybackRequiresUserAction
? WKAudiovisualMediaTypeAll
: WKAudiovisualMediaTypeNone;
wkWebViewConfig.dataDetectorTypes = _dataDetectorTypes;
#else
wkWebViewConfig.mediaPlaybackRequiresUserAction = _mediaPlaybackRequiresUserAction;
#endif
_webView = [[WKWebView alloc] initWithFrame:self.bounds configuration: wkWebViewConfig];
_webView.scrollView.delegate = self;
_webView.UIDelegate = self;
_webView.navigationDelegate = self;
_webView.scrollView.scrollEnabled = _scrollEnabled;
_webView.scrollView.pagingEnabled = _pagingEnabled;
_webView.scrollView.bounces = _bounces;
_webView.scrollView.showsHorizontalScrollIndicator = _showsHorizontalScrollIndicator;
_webView.scrollView.showsVerticalScrollIndicator = _showsVerticalScrollIndicator;
_webView.allowsLinkPreview = _allowsLinkPreview;
[_webView addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:nil];
_webView.allowsBackForwardNavigationGestures = _allowsBackForwardNavigationGestures;
if (_userAgent) {
_webView.customUserAgent = _userAgent;
}
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 /* __IPHONE_11_0 */
if ([_webView.scrollView respondsToSelector:@selector(setContentInsetAdjustmentBehavior:)]) {
_webView.scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
}
#endif
[self addSubview:_webView];
[self setHideKeyboardAccessoryView: _savedHideKeyboardAccessoryView];
[self visitSource];
}
}
// Update webview property when the component prop changes.
- (void)setAllowsBackForwardNavigationGestures:(BOOL)allowsBackForwardNavigationGestures {
_allowsBackForwardNavigationGestures = allowsBackForwardNavigationGestures;
_webView.allowsBackForwardNavigationGestures = _allowsBackForwardNavigationGestures;
}
- (void)removeFromSuperview
{
if (_webView) {
[_webView.configuration.userContentController removeScriptMessageHandlerForName:MessageHandlerName];
[_webView removeObserver:self forKeyPath:@"estimatedProgress"];
[_webView removeFromSuperview];
_webView.scrollView.delegate = nil;
_webView = nil;
}
[super removeFromSuperview];
}
-(void)keyboardWillHide
{
keyboardTimer = [NSTimer scheduledTimerWithTimeInterval:0 target:self selector:@selector(keyboardDisplacementFix) userInfo:nil repeats:false];
[[NSRunLoop mainRunLoop] addTimer:keyboardTimer forMode:NSRunLoopCommonModes];
}
-(void)keyboardWillShow
{
if (keyboardTimer != nil) {
[keyboardTimer invalidate];
}
}
-(void)keyboardDisplacementFix
{
// Additional viewport checks to prevent unintentional scrolls
UIScrollView *scrollView = self.webView.scrollView;
double maxContentOffset = scrollView.contentSize.height - scrollView.frame.size.height;
if (maxContentOffset < 0) {
maxContentOffset = 0;
}
if (scrollView.contentOffset.y > maxContentOffset) {
// https://stackoverflow.com/a/9637807/824966
[UIView animateWithDuration:.25 animations:^{
scrollView.contentOffset = CGPointMake(0, maxContentOffset);
}];
}
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
if ([keyPath isEqual:@"estimatedProgress"] && object == self.webView) {
if(_onLoadingProgress){
NSMutableDictionary<NSString *, id> *event = [self baseEvent];
[event addEntriesFromDictionary:@{@"progress":[NSNumber numberWithDouble:self.webView.estimatedProgress]}];
_onLoadingProgress(event);
}
}else{
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
- (void)setBackgroundColor:(UIColor *)backgroundColor
{
_savedBackgroundColor = backgroundColor;
if (_webView == nil) {
return;
}
CGFloat alpha = CGColorGetAlpha(backgroundColor.CGColor);
self.opaque = _webView.opaque = (alpha == 1.0);
_webView.scrollView.backgroundColor = backgroundColor;
_webView.backgroundColor = backgroundColor;
}
/**
* This method is called whenever JavaScript running within the web view calls:
* - window.webkit.messageHandlers[MessageHandlerName].postMessage
*/
- (void)userContentController:(WKUserContentController *)userContentController
didReceiveScriptMessage:(WKScriptMessage *)message
{
if (_onMessage != nil) {
NSMutableDictionary<NSString *, id> *event = [self baseEvent];
[event addEntriesFromDictionary: @{@"data": message.body}];
_onMessage(event);
}
}
- (void)setSource:(NSDictionary *)source
{
if (![_source isEqualToDictionary:source]) {
_source = [source copy];
if (_webView != nil) {
[self visitSource];
}
}
}
- (void)setContentInset:(UIEdgeInsets)contentInset
{
_contentInset = contentInset;
[RCTView autoAdjustInsetsForView:self
withScrollView:_webView.scrollView
updateOffset:NO];
}
- (void)refreshContentInset
{
[RCTView autoAdjustInsetsForView:self
withScrollView:_webView.scrollView
updateOffset:YES];
}
- (void)visitSource
{
// Check for a static html source first
NSString *html = [RCTConvert NSString:_source[@"html"]];
if (html) {
NSURL *baseURL = [RCTConvert NSURL:_source[@"baseUrl"]];
if (!baseURL) {
baseURL = [NSURL URLWithString:@"about:blank"];
}
[_webView loadHTMLString:html baseURL:baseURL];
return;
}
NSURLRequest *request = [RCTConvert NSURLRequest:_source];
// Because of the way React works, as pages redirect, we actually end up
// passing the redirect urls back here, so we ignore them if trying to load
// the same url. We'll expose a call to 'reload' to allow a user to load
// the existing page.
if ([request.URL isEqual:_webView.URL]) {
return;
}
if (!request.URL) {
// Clear the webview
[_webView loadHTMLString:@"" baseURL:nil];
return;
}
[_webView loadRequest:request];
}
-(void)setHideKeyboardAccessoryView:(BOOL)hideKeyboardAccessoryView
{
if (_webView == nil) {
_savedHideKeyboardAccessoryView = hideKeyboardAccessoryView;
return;
}
if (_savedHideKeyboardAccessoryView == false) {
return;
}
UIView* subview;
for (UIView* view in _webView.scrollView.subviews) {
if([[view.class description] hasPrefix:@"WK"])
subview = view;
}
if(subview == nil) return;
NSString* name = [NSString stringWithFormat:@"%@_SwizzleHelperWK", subview.class.superclass];
Class newClass = NSClassFromString(name);
if(newClass == nil)
{
newClass = objc_allocateClassPair(subview.class, [name cStringUsingEncoding:NSASCIIStringEncoding], 0);
if(!newClass) return;
Method method = class_getInstanceMethod([_SwizzleHelperWK class], @selector(inputAccessoryView));
class_addMethod(newClass, @selector(inputAccessoryView), method_getImplementation(method), method_getTypeEncoding(method));
objc_registerClassPair(newClass);
}
object_setClass(subview, newClass);
}
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
scrollView.decelerationRate = _decelerationRate;
}
- (void)setScrollEnabled:(BOOL)scrollEnabled
{
_scrollEnabled = scrollEnabled;
_webView.scrollView.scrollEnabled = scrollEnabled;
}
- (void)setShowsHorizontalScrollIndicator:(BOOL)showsHorizontalScrollIndicator
{
_showsHorizontalScrollIndicator = showsHorizontalScrollIndicator;
_webView.scrollView.showsHorizontalScrollIndicator = showsHorizontalScrollIndicator;
}
- (void)setShowsVerticalScrollIndicator:(BOOL)showsVerticalScrollIndicator
{
_showsVerticalScrollIndicator = showsVerticalScrollIndicator;
_webView.scrollView.showsVerticalScrollIndicator = showsVerticalScrollIndicator;
}
- (void)postMessage:(NSString *)message
{
NSDictionary *eventInitDict = @{@"data": message};
NSString *source = [NSString
stringWithFormat:@"window.dispatchEvent(new MessageEvent('message', %@));",
RCTJSONStringify(eventInitDict, NULL)
];
[self injectJavaScript: source];
}
- (void)layoutSubviews
{
[super layoutSubviews];
// Ensure webview takes the position and dimensions of RNCWKWebView
_webView.frame = self.bounds;
}
- (NSMutableDictionary<NSString *, id> *)baseEvent
{
NSDictionary *event = @{
@"url": _webView.URL.absoluteString ?: @"",
@"title": _webView.title,
@"loading" : @(_webView.loading),
@"canGoBack": @(_webView.canGoBack),
@"canGoForward" : @(_webView.canGoForward)
};
return [[NSMutableDictionary alloc] initWithDictionary: event];
}
+ (void)setClientAuthenticationCredential:(nullable NSURLCredential*)credential {
clientAuthenticationCredential = credential;
}
#pragma mark - WKNavigationDelegate methods
/**
* alert
*/
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler
{
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"" message:message preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
completionHandler();
}]];
[[self topViewController] presentViewController:alert animated:YES completion:NULL];
}
/**
* confirm
*/
- (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL))completionHandler{
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"" message:message preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
completionHandler(YES);
}]];
[alert addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
completionHandler(NO);
}]];
[[self topViewController] presentViewController:alert animated:YES completion:NULL];
}
/**
* prompt
*/
- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString *))completionHandler{
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"" message:prompt preferredStyle:UIAlertControllerStyleAlert];
[alert addTextFieldWithConfigurationHandler:^(UITextField *textField) {
textField.textColor = [UIColor lightGrayColor];
textField.placeholder = defaultText;
}];
[alert addAction:[UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
completionHandler([[alert.textFields lastObject] text]);
}]];
[[self topViewController] presentViewController:alert animated:YES completion:NULL];
}
/**
* topViewController
*/
-(UIViewController *)topViewController{
   UIViewController *controller = [self topViewControllerWithRootViewController:[self getCurrentWindow].rootViewController];
   return controller;
}
/**
* topViewControllerWithRootViewController
*/
-(UIViewController *)topViewControllerWithRootViewController:(UIViewController *)viewController{
if (viewController==nil) return nil;
if (viewController.presentedViewController!=nil) {
return [self topViewControllerWithRootViewController:viewController.presentedViewController];
} else if ([viewController isKindOfClass:[UITabBarController class]]){
return [self topViewControllerWithRootViewController:[(UITabBarController *)viewController selectedViewController]];
} else if ([viewController isKindOfClass:[UINavigationController class]]){
return [self topViewControllerWithRootViewController:[(UINavigationController *)viewController visibleViewController]];
} else {
return viewController;
}
}
/**
* getCurrentWindow
*/
-(UIWindow *)getCurrentWindow{
UIWindow *window = [UIApplication sharedApplication].keyWindow;
if (window.windowLevel!=UIWindowLevelNormal) {
for (UIWindow *wid in [UIApplication sharedApplication].windows) {
if (window.windowLevel==UIWindowLevelNormal) {
window = wid;
break;
}
}
}
return window;
}
/**
* Decides whether to allow or cancel a navigation.
* @see https://fburl.com/42r9fxob
*/
- (void) webView:(WKWebView *)webView
decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction
decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
{
static NSDictionary<NSNumber *, NSString *> *navigationTypes;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
navigationTypes = @{
@(WKNavigationTypeLinkActivated): @"click",
@(WKNavigationTypeFormSubmitted): @"formsubmit",
@(WKNavigationTypeBackForward): @"backforward",
@(WKNavigationTypeReload): @"reload",
@(WKNavigationTypeFormResubmitted): @"formresubmit",
@(WKNavigationTypeOther): @"other",
};
});
WKNavigationType navigationType = navigationAction.navigationType;
NSURLRequest *request = navigationAction.request;
if (_onShouldStartLoadWithRequest) {
NSMutableDictionary<NSString *, id> *event = [self baseEvent];
[event addEntriesFromDictionary: @{
@"url": (request.URL).absoluteString,
@"navigationType": navigationTypes[@(navigationType)]
}];
if (![self.delegate webView:self
shouldStartLoadForRequest:event
withCallback:_onShouldStartLoadWithRequest]) {
decisionHandler(WKNavigationResponsePolicyCancel);
return;
}
}
if (_onLoadingStart) {
// We have this check to filter out iframe requests and whatnot
BOOL isTopFrame = [request.URL isEqual:request.mainDocumentURL];
if (isTopFrame) {
NSMutableDictionary<NSString *, id> *event = [self baseEvent];
[event addEntriesFromDictionary: @{
@"url": (request.URL).absoluteString,
@"navigationType": navigationTypes[@(navigationType)]
}];
_onLoadingStart(event);
}
}
// Allow all navigation by default
decisionHandler(WKNavigationResponsePolicyAllow);
}
/**
* Called when an error occurs while the web view is loading content.
* @see https://fburl.com/km6vqenw
*/
- (void) webView:(WKWebView *)webView
didFailProvisionalNavigation:(WKNavigation *)navigation
withError:(NSError *)error
{
if (_onLoadingError) {
if ([error.domain isEqualToString:NSURLErrorDomain] && error.code == NSURLErrorCancelled) {
// NSURLErrorCancelled is reported when a page has a redirect OR if you load
// a new URL in the WebView before the previous one came back. We can just
// ignore these since they aren't real errors.
// http://stackoverflow.com/questions/1024748/how-do-i-fix-nsurlerrordomain-error-999-in-iphone-3-0-os
return;
}
if ([error.domain isEqualToString:@"WebKitErrorDomain"] && error.code == 102) {
// Error code 102 "Frame load interrupted" is raised by the WKWebView
// when the URL is from an http redirect. This is a common pattern when
// implementing OAuth with a WebView.
return;
}
NSMutableDictionary<NSString *, id> *event = [self baseEvent];
[event addEntriesFromDictionary:@{
@"didFailProvisionalNavigation": @YES,
@"domain": error.domain,
@"code": @(error.code),
@"description": error.localizedDescription,
}];
_onLoadingError(event);
}
[self setBackgroundColor: _savedBackgroundColor];
}
- (void)evaluateJS:(NSString *)js
thenCall: (void (^)(NSString*)) callback
{
[self.webView evaluateJavaScript: js completionHandler: ^(id result, NSError *error) {
if (error == nil) {
if (callback != nil) {
callback([NSString stringWithFormat:@"%@", result]);
}
} else {
RCTLogError(@"Error evaluating injectedJavaScript: This is possibly due to an unsupported return type. Try adding true to the end of your injectedJavaScript string.");
}
}];
}
-(void) webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler {
NSString *authenticationMethod = [[challenge protectionSpace] authenticationMethod];
if (authenticationMethod == NSURLAuthenticationMethodNTLM || authenticationMethod == NSURLAuthenticationMethodNegotiate) {
NSString *hostName = webView.URL.host;
NSString *title = @"Authentication Challenge";
NSString *message = [NSString stringWithFormat:@"%@ requires user name and password", hostName];
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert];
[alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) {
textField.placeholder = @"User";
}];
[alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) {
textField.placeholder = @"Password";
textField.secureTextEntry = YES;
}];
[alertController addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
NSString *userName = ((UITextField *)alertController.textFields[0]).text;
NSString *password = ((UITextField *)alertController.textFields[1]).text;
NSURLCredential *credential = [[NSURLCredential alloc] initWithUser:userName password:password persistence:NSURLCredentialPersistenceNone];
completionHandler(NSURLSessionAuthChallengeUseCredential, credential);
}]];
[alertController addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
completionHandler(NSURLSessionAuthChallengeUseCredential, nil);
}]];
dispatch_async(dispatch_get_main_queue(), ^{
UIViewController *rootVC = UIApplication.sharedApplication.delegate.window.rootViewController;
while (rootVC.presentedViewController != nil) {
rootVC = rootVC.presentedViewController;
}
[rootVC presentViewController:alertController animated:YES completion:^{}];
});
} else if (!clientAuthenticationCredential) {
completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil);
return;
} else if (authenticationMethod == NSURLAuthenticationMethodClientCertificate) {
completionHandler(NSURLSessionAuthChallengeUseCredential, clientAuthenticationCredential);
} else {
completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
}
}
/**
* Called when the navigation is complete.
* @see https://fburl.com/rtys6jlb
*/
- (void) webView:(WKWebView *)webView
didFinishNavigation:(WKNavigation *)navigation
{
if (_injectedJavaScript) {
[self evaluateJS: _injectedJavaScript thenCall: ^(NSString *jsEvaluationValue) {
NSMutableDictionary *event = [self baseEvent];
event[@"jsEvaluationValue"] = jsEvaluationValue;
if (self.onLoadingFinish) {
self.onLoadingFinish(event);
}
}];
} else if (_onLoadingFinish) {
_onLoadingFinish([self baseEvent]);
}
[self setBackgroundColor: _savedBackgroundColor];
}
- (void)injectJavaScript:(NSString *)script
{
[self evaluateJS: script thenCall: nil];
}
- (void)goForward
{
[_webView goForward];
}
- (void)goBack
{
[_webView goBack];
}
- (void)reload
{
/**
* When the initial load fails due to network connectivity issues,
* [_webView reload] doesn't reload the webpage. Therefore, we must
* manually call [_webView loadRequest:request].
*/
NSURLRequest *request = [RCTConvert NSURLRequest:self.source];
if (request.URL && !_webView.URL.absoluteString.length) {
[_webView loadRequest:request];
}
else {
[_webView reload];
}
}
- (void)stopLoading
{
[_webView stopLoading];
}
- (void)setBounces:(BOOL)bounces
{
_bounces = bounces;
_webView.scrollView.bounces = bounces;
}
@end

View file

@ -1,877 +0,0 @@
package com.reactnativecommunity.webview;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.DownloadManager;
import android.content.Context;
import com.facebook.react.uimanager.UIManagerModule;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Pattern;
import javax.annotation.Nullable;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import android.content.ActivityNotFoundException;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.text.TextUtils;
import android.text.InputType;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.webkit.ConsoleMessage;
import android.webkit.CookieManager;
import android.webkit.DownloadListener;
import android.webkit.GeolocationPermissions;
import android.webkit.JavascriptInterface;
import android.webkit.URLUtil;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebResourceRequest;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.webkit.HttpAuthHandler;
import android.widget.EditText;
import android.widget.LinearLayout;
import com.facebook.common.logging.FLog;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.LifecycleEventListener;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.ReadableMapKeySetIterator;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.common.MapBuilder;
import com.facebook.react.common.ReactConstants;
import com.facebook.react.common.build.ReactBuildConfig;
import com.facebook.react.module.annotations.ReactModule;
import com.facebook.react.uimanager.SimpleViewManager;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.annotations.ReactProp;
import com.facebook.react.uimanager.events.ContentSizeChangeEvent;
import com.facebook.react.uimanager.events.Event;
import com.facebook.react.uimanager.events.EventDispatcher;
import com.facebook.react.uimanager.events.RCTEventEmitter;
import com.reactnativecommunity.webview.events.TopLoadingErrorEvent;
import com.reactnativecommunity.webview.events.TopLoadingFinishEvent;
import com.reactnativecommunity.webview.events.TopLoadingStartEvent;
import com.reactnativecommunity.webview.events.TopMessageEvent;
import com.reactnativecommunity.webview.events.TopLoadingProgressEvent;
import com.reactnativecommunity.webview.events.TopShouldStartLoadWithRequestEvent;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import javax.annotation.Nullable;
import org.json.JSONException;
import org.json.JSONObject;
import android.util.Log;
/**
* Manages instances of {@link WebView}
*
* Can accept following commands:
* - GO_BACK
* - GO_FORWARD
* - RELOAD
* - LOAD_URL
*
* {@link WebView} instances could emit following direct events:
* - topLoadingFinish
* - topLoadingStart
* - topLoadingStart
* - topLoadingProgress
* - topShouldStartLoadWithRequest
*
* Each event will carry the following properties:
* - target - view's react tag
* - url - url set for the webview
* - loading - whether webview is in a loading state
* - title - title of the current page
* - canGoBack - boolean, whether there is anything on a history stack to go back
* - canGoForward - boolean, whether it is possible to request GO_FORWARD command
*/
@ReactModule(name = RNCWebViewManager.REACT_CLASS)
public class RNCWebViewManager extends SimpleViewManager<WebView> {
protected static final String REACT_CLASS = "RNCWebView";
private RNCWebViewPackage aPackage;
protected static final String HTML_ENCODING = "UTF-8";
protected static final String HTML_MIME_TYPE = "text/html";
protected static final String JAVASCRIPT_INTERFACE = "ReactNativeWebView";
protected static final String HTTP_METHOD_POST = "POST";
public static final int COMMAND_GO_BACK = 1;
public static final int COMMAND_GO_FORWARD = 2;
public static final int COMMAND_RELOAD = 3;
public static final int COMMAND_STOP_LOADING = 4;
public static final int COMMAND_POST_MESSAGE = 5;
public static final int COMMAND_INJECT_JAVASCRIPT = 6;
public static final int COMMAND_LOAD_URL = 7;
// Use `webView.loadUrl("about:blank")` to reliably reset the view
// state and release page resources (including any running JavaScript).
protected static final String BLANK_URL = "about:blank";
protected WebViewConfig mWebViewConfig;
protected static class RNCWebViewClient extends WebViewClient {
protected boolean mLastLoadFailed = false;
protected @Nullable ReadableArray mUrlPrefixesForDefaultIntent;
protected Activity mCurrentActivity;
public void setCurrentActivity(Activity mCurrentActivity) {
this.mCurrentActivity = mCurrentActivity;
}
@Override
public void onPageFinished(WebView webView, String url) {
super.onPageFinished(webView, url);
if (!mLastLoadFailed) {
RNCWebView reactWebView = (RNCWebView) webView;
reactWebView.callInjectedJavaScript();
emitFinishEvent(webView, url);
}
}
@Override
public void onPageStarted(WebView webView, String url, Bitmap favicon) {
super.onPageStarted(webView, url, favicon);
mLastLoadFailed = false;
dispatchEvent(
webView,
new TopLoadingStartEvent(
webView.getId(),
createWebViewEvent(webView, url)));
}
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
dispatchEvent(view, new TopShouldStartLoadWithRequestEvent(view.getId(), url));
return true;
}
@TargetApi(Build.VERSION_CODES.N)
@Override
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
dispatchEvent(view, new TopShouldStartLoadWithRequestEvent(view.getId(), request.getUrl().toString()));
return true;
}
@Override
public void onReceivedError(
WebView webView,
int errorCode,
String description,
String failingUrl) {
super.onReceivedError(webView, errorCode, description, failingUrl);
mLastLoadFailed = true;
// In case of an error JS side expect to get a finish event first, and then get an error event
// Android WebView does it in the opposite way, so we need to simulate that behavior
emitFinishEvent(webView, failingUrl);
WritableMap eventData = createWebViewEvent(webView, failingUrl);
eventData.putDouble("code", errorCode);
eventData.putString("description", description);
dispatchEvent(
webView,
new TopLoadingErrorEvent(webView.getId(), eventData));
}
@Override
public void onReceivedHttpAuthRequest(WebView view,
final HttpAuthHandler handler, String host, String realm)
{
Log.d("ReactNative", "host = " + host + " realm = " + realm);
if (this.mCurrentActivity != null) {
final EditText usernameInput = new EditText(this.mCurrentActivity);
usernameInput.setHint("Username");
final EditText passwordInput = new EditText(this.mCurrentActivity);
passwordInput.setHint("Password");
passwordInput.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
LinearLayout layout = new LinearLayout(this.mCurrentActivity);
layout.setOrientation(LinearLayout.VERTICAL);
layout.addView(usernameInput);
layout.addView(passwordInput);
AlertDialog.Builder authDialog = new AlertDialog.Builder(this.mCurrentActivity)
.setTitle("Authentication Challenge")
.setMessage(host + " requires user name and password ")
.setView(layout)
.setCancelable(false)
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialogInterface, int i) {
handler.proceed(usernameInput.getText().toString(), passwordInput.getText().toString());
dialogInterface.dismiss();
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.dismiss();
handler.cancel();
}
});
if (view != null) {
authDialog.show();
}
} else {
handler.cancel();
}
}
protected void emitFinishEvent(WebView webView, String url) {
dispatchEvent(
webView,
new TopLoadingFinishEvent(
webView.getId(),
createWebViewEvent(webView, url)));
}
protected WritableMap createWebViewEvent(WebView webView, String url) {
WritableMap event = Arguments.createMap();
event.putDouble("target", webView.getId());
// Don't use webView.getUrl() here, the URL isn't updated to the new value yet in callbacks
// like onPageFinished
event.putString("url", url);
event.putBoolean("loading", !mLastLoadFailed && webView.getProgress() != 100);
event.putString("title", webView.getTitle());
event.putBoolean("canGoBack", webView.canGoBack());
event.putBoolean("canGoForward", webView.canGoForward());
return event;
}
public void setUrlPrefixesForDefaultIntent(ReadableArray specialUrls) {
mUrlPrefixesForDefaultIntent = specialUrls;
}
}
/**
* Subclass of {@link WebView} that implements {@link LifecycleEventListener} interface in order
* to call {@link WebView#destroy} on activity destroy event and also to clear the client
*/
protected static class RNCWebView extends WebView implements LifecycleEventListener {
protected @Nullable String injectedJS;
protected boolean messagingEnabled = false;
protected @Nullable RNCWebViewClient mRNCWebViewClient;
protected boolean sendContentSizeChangeEvents = false;
protected ReactContext reactContext;
public void setSendContentSizeChangeEvents(boolean sendContentSizeChangeEvents) {
this.sendContentSizeChangeEvents = sendContentSizeChangeEvents;
}
protected class RNCWebViewBridge {
RNCWebView mContext;
RNCWebViewBridge(RNCWebView c) {
mContext = c;
}
/**
* This method is called whenever JavaScript running within the web view calls:
* - window[JAVASCRIPT_INTERFACE].postMessage
*/
@JavascriptInterface
public void postMessage(String message) {
mContext.onMessage(message);
}
}
/**
* WebView must be created with an context of the current activity
*
* Activity Context is required for creation of dialogs internally by WebView
* Reactive Native needed for access to ReactNative internal system functionality
*
*/
public RNCWebView(ThemedReactContext reactContext) {
super(reactContext);
this.reactContext = reactContext;
}
@Override
public void onHostResume() {
// do nothing
}
@Override
public void onHostPause() {
// do nothing
}
@Override
public void onHostDestroy() {
cleanupCallbacksAndDestroy();
}
@Override
protected void onSizeChanged(int w, int h, int ow, int oh) {
super.onSizeChanged(w, h, ow, oh);
if (sendContentSizeChangeEvents) {
dispatchEvent(
this,
new ContentSizeChangeEvent(
this.getId(),
w,
h
)
);
}
}
@Override
public void setWebViewClient(WebViewClient client) {
super.setWebViewClient(client);
Log.d("ReactNative", "SETTING THE WEBVIEW CLIENT");
mRNCWebViewClient = (RNCWebViewClient)client;
if (this.reactContext != null && this.reactContext.getCurrentActivity() != null && mRNCWebViewClient != null) {
mRNCWebViewClient.setCurrentActivity(this.reactContext.getCurrentActivity());
}
}
public @Nullable RNCWebViewClient getRNCWebViewClient() {
return mRNCWebViewClient;
}
public void setInjectedJavaScript(@Nullable String js) {
injectedJS = js;
}
protected RNCWebViewBridge createRNCWebViewBridge(RNCWebView webView) {
return new RNCWebViewBridge(webView);
}
@SuppressLint("AddJavascriptInterface")
public void setMessagingEnabled(boolean enabled) {
if (messagingEnabled == enabled) {
return;
}
messagingEnabled = enabled;
if (enabled) {
addJavascriptInterface(createRNCWebViewBridge(this), JAVASCRIPT_INTERFACE);
} else {
removeJavascriptInterface(JAVASCRIPT_INTERFACE);
}
}
protected void evaluateJavascriptWithFallback(String script) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
evaluateJavascript(script, null);
return;
}
try {
loadUrl("javascript:" + URLEncoder.encode(script, "UTF-8"));
} catch (UnsupportedEncodingException e) {
// UTF-8 should always be supported
throw new RuntimeException(e);
}
}
public void callInjectedJavaScript() {
if (getSettings().getJavaScriptEnabled() &&
injectedJS != null &&
!TextUtils.isEmpty(injectedJS)) {
evaluateJavascriptWithFallback("(function() {\n" + injectedJS + ";\n})();");
}
}
public void onMessage(String message) {
dispatchEvent(this, new TopMessageEvent(this.getId(), message));
}
protected void cleanupCallbacksAndDestroy() {
setWebViewClient(null);
destroy();
}
}
public RNCWebViewManager() {
mWebViewConfig = new WebViewConfig() {
public void configWebView(WebView webView) {
}
};
}
public RNCWebViewManager(WebViewConfig webViewConfig) {
mWebViewConfig = webViewConfig;
}
@Override
public String getName() {
return REACT_CLASS;
}
protected RNCWebView createRNCWebViewInstance(ThemedReactContext reactContext) {
return new RNCWebView(reactContext);
}
@Override
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
protected WebView createViewInstance(ThemedReactContext reactContext) {
RNCWebView webView = createRNCWebViewInstance(reactContext);
webView.setWebChromeClient(new WebChromeClient() {
@Override
public boolean onConsoleMessage(ConsoleMessage message) {
if (ReactBuildConfig.DEBUG) {
return super.onConsoleMessage(message);
}
// Ignore console logs in non debug builds.
return true;
}
@Override
public void onProgressChanged(WebView webView, int newProgress) {
super.onProgressChanged(webView, newProgress);
WritableMap event = Arguments.createMap();
event.putDouble("target", webView.getId());
event.putString("title", webView.getTitle());
event.putBoolean("canGoBack", webView.canGoBack());
event.putBoolean("canGoForward", webView.canGoForward());
event.putDouble("progress", (float)newProgress/100);
dispatchEvent(
webView,
new TopLoadingProgressEvent(
webView.getId(),
event));
}
@Override
public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) {
callback.invoke(origin, true, false);
}
protected void openFileChooser(ValueCallback<Uri> filePathCallback, String acceptType) {
getModule().startPhotoPickerIntent(filePathCallback, acceptType);
}
protected void openFileChooser(ValueCallback<Uri> filePathCallback) {
getModule().startPhotoPickerIntent(filePathCallback, "");
}
protected void openFileChooser(ValueCallback<Uri> filePathCallback, String acceptType, String capture) {
getModule().startPhotoPickerIntent(filePathCallback, acceptType);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
String[] acceptTypes = fileChooserParams.getAcceptTypes();
boolean allowMultiple = fileChooserParams.getMode() == WebChromeClient.FileChooserParams.MODE_OPEN_MULTIPLE;
Intent intent = fileChooserParams.createIntent();
return getModule().startPhotoPickerIntent(filePathCallback, intent, acceptTypes, allowMultiple);
}
});
reactContext.addLifecycleEventListener(webView);
mWebViewConfig.configWebView(webView);
WebSettings settings = webView.getSettings();
settings.setBuiltInZoomControls(true);
settings.setDisplayZoomControls(false);
settings.setDomStorageEnabled(true);
settings.setAllowFileAccess(false);
settings.setAllowContentAccess(false);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
settings.setAllowFileAccessFromFileURLs(false);
setAllowUniversalAccessFromFileURLs(webView, false);
}
setMixedContentMode(webView, "never");
// Fixes broken full-screen modals/galleries due to body height being 0.
webView.setLayoutParams(
new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT));
setGeolocationEnabled(webView, false);
if (ReactBuildConfig.DEBUG && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
WebView.setWebContentsDebuggingEnabled(true);
}
webView.setDownloadListener(new DownloadListener() {
public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength) {
RNCWebViewModule module = getModule();
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
String fileName = URLUtil.guessFileName(url, contentDisposition, mimetype);
String downloadMessage = "Downloading " + fileName;
//Attempt to add cookie, if it exists
URL urlObj = null;
try {
urlObj = new URL(url);
String baseUrl = urlObj.getProtocol() + "://" + urlObj.getHost();
String cookie = CookieManager.getInstance().getCookie(baseUrl);
request.addRequestHeader("Cookie", cookie);
System.out.println("Got cookie for DownloadManager: " + cookie);
} catch (MalformedURLException e) {
System.out.println("Error getting cookie for DownloadManager: " + e.toString());
e.printStackTrace();
}
//Finish setting up request
request.addRequestHeader("User-Agent", userAgent);
request.setTitle(fileName);
request.setDescription(downloadMessage);
request.allowScanningByMediaScanner();
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName);
module.setDownloadRequest(request);
if (module.grantFileDownloaderPermissions()) {
module.downloadFile();
}
}
});
return webView;
}
@ReactProp(name = "javaScriptEnabled")
public void setJavaScriptEnabled(WebView view, boolean enabled) {
view.getSettings().setJavaScriptEnabled(enabled);
}
@ReactProp(name = "showsHorizontalScrollIndicator")
public void setShowsHorizontalScrollIndicator(WebView view, boolean enabled) {
view.setHorizontalScrollBarEnabled(enabled);
}
@ReactProp(name = "showsVerticalScrollIndicator")
public void setShowsVerticalScrollIndicator(WebView view, boolean enabled) {
view.setVerticalScrollBarEnabled(enabled);
}
@ReactProp(name = "cacheEnabled")
public void setCacheEnabled(WebView view, boolean enabled) {
if (enabled) {
Context ctx = view.getContext();
if (ctx != null) {
view.getSettings().setAppCachePath(ctx.getCacheDir().getAbsolutePath());
view.getSettings().setCacheMode(WebSettings.LOAD_DEFAULT);
view.getSettings().setAppCacheEnabled(true);
}
} else {
view.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
view.getSettings().setAppCacheEnabled(false);
}
}
@ReactProp(name = "androidHardwareAccelerationDisabled")
public void setHardwareAccelerationDisabled(WebView view, boolean disabled) {
if (disabled) {
view.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
}
@ReactProp(name = "overScrollMode")
public void setOverScrollMode(WebView view, String overScrollModeString) {
Integer overScrollMode;
switch (overScrollModeString) {
case "never":
overScrollMode = View.OVER_SCROLL_NEVER;
break;
case "content":
overScrollMode = View.OVER_SCROLL_IF_CONTENT_SCROLLS;
break;
case "always":
default:
overScrollMode = View.OVER_SCROLL_ALWAYS;
break;
}
view.setOverScrollMode(overScrollMode);
}
@ReactProp(name = "thirdPartyCookiesEnabled")
public void setThirdPartyCookiesEnabled(WebView view, boolean enabled) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
CookieManager.getInstance().setAcceptThirdPartyCookies(view, enabled);
}
}
@ReactProp(name = "scalesPageToFit")
public void setScalesPageToFit(WebView view, boolean enabled) {
view.getSettings().setUseWideViewPort(!enabled);
}
@ReactProp(name = "domStorageEnabled")
public void setDomStorageEnabled(WebView view, boolean enabled) {
view.getSettings().setDomStorageEnabled(enabled);
}
@ReactProp(name = "userAgent")
public void setUserAgent(WebView view, @Nullable String userAgent) {
if (userAgent != null) {
// TODO(8496850): Fix incorrect behavior when property is unset (uA == null)
view.getSettings().setUserAgentString(userAgent);
}
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
@ReactProp(name = "mediaPlaybackRequiresUserAction")
public void setMediaPlaybackRequiresUserAction(WebView view, boolean requires) {
view.getSettings().setMediaPlaybackRequiresUserGesture(requires);
}
@ReactProp(name = "allowUniversalAccessFromFileURLs")
public void setAllowUniversalAccessFromFileURLs(WebView view, boolean allow) {
view.getSettings().setAllowUniversalAccessFromFileURLs(allow);
}
@ReactProp(name = "saveFormDataDisabled")
public void setSaveFormDataDisabled(WebView view, boolean disable) {
view.getSettings().setSaveFormData(!disable);
}
@ReactProp(name = "injectedJavaScript")
public void setInjectedJavaScript(WebView view, @Nullable String injectedJavaScript) {
((RNCWebView) view).setInjectedJavaScript(injectedJavaScript);
}
@ReactProp(name = "messagingEnabled")
public void setMessagingEnabled(WebView view, boolean enabled) {
((RNCWebView) view).setMessagingEnabled(enabled);
}
@ReactProp(name = "source")
public void setSource(WebView view, @Nullable ReadableMap source) {
if (source != null) {
if (source.hasKey("html")) {
String html = source.getString("html");
if (source.hasKey("baseUrl")) {
view.loadDataWithBaseURL(
source.getString("baseUrl"), html, HTML_MIME_TYPE, HTML_ENCODING, null);
} else {
view.loadData(html, HTML_MIME_TYPE + "; charset=" + HTML_ENCODING, null);
}
return;
}
if (source.hasKey("uri")) {
String url = source.getString("uri");
String previousUrl = view.getUrl();
if (previousUrl != null && previousUrl.equals(url)) {
return;
}
if (source.hasKey("method")) {
String method = source.getString("method");
if (method.equalsIgnoreCase(HTTP_METHOD_POST)) {
byte[] postData = null;
if (source.hasKey("body")) {
String body = source.getString("body");
try {
postData = body.getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
postData = body.getBytes();
}
}
if (postData == null) {
postData = new byte[0];
}
view.postUrl(url, postData);
return;
}
}
HashMap<String, String> headerMap = new HashMap<>();
if (source.hasKey("headers")) {
ReadableMap headers = source.getMap("headers");
ReadableMapKeySetIterator iter = headers.keySetIterator();
while (iter.hasNextKey()) {
String key = iter.nextKey();
if ("user-agent".equals(key.toLowerCase(Locale.ENGLISH))) {
if (view.getSettings() != null) {
view.getSettings().setUserAgentString(headers.getString(key));
}
} else {
headerMap.put(key, headers.getString(key));
}
}
}
view.loadUrl(url, headerMap);
return;
}
}
view.loadUrl(BLANK_URL);
}
@ReactProp(name = "onContentSizeChange")
public void setOnContentSizeChange(WebView view, boolean sendContentSizeChangeEvents) {
((RNCWebView) view).setSendContentSizeChangeEvents(sendContentSizeChangeEvents);
}
@ReactProp(name = "mixedContentMode")
public void setMixedContentMode(WebView view, @Nullable String mixedContentMode) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (mixedContentMode == null || "never".equals(mixedContentMode)) {
view.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_NEVER_ALLOW);
} else if ("always".equals(mixedContentMode)) {
view.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
} else if ("compatibility".equals(mixedContentMode)) {
view.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_COMPATIBILITY_MODE);
}
}
}
@ReactProp(name = "urlPrefixesForDefaultIntent")
public void setUrlPrefixesForDefaultIntent(
WebView view,
@Nullable ReadableArray urlPrefixesForDefaultIntent) {
RNCWebViewClient client = ((RNCWebView) view).getRNCWebViewClient();
if (client != null && urlPrefixesForDefaultIntent != null) {
client.setUrlPrefixesForDefaultIntent(urlPrefixesForDefaultIntent);
}
}
@ReactProp(name = "allowFileAccess")
public void setAllowFileAccess(
WebView view,
@Nullable Boolean allowFileAccess) {
view.getSettings().setAllowFileAccess(allowFileAccess != null && allowFileAccess);
}
@ReactProp(name = "geolocationEnabled")
public void setGeolocationEnabled(
WebView view,
@Nullable Boolean isGeolocationEnabled) {
view.getSettings().setGeolocationEnabled(isGeolocationEnabled != null && isGeolocationEnabled);
}
@Override
protected void addEventEmitters(ThemedReactContext reactContext, WebView view) {
// Do not register default touch emitter and let WebView implementation handle touches
view.setWebViewClient(new RNCWebViewClient());
}
@Override
public Map getExportedCustomDirectEventTypeConstants() {
Map export = super.getExportedCustomDirectEventTypeConstants();
if (export == null) {
export = MapBuilder.newHashMap();
}
export.put(TopLoadingProgressEvent.EVENT_NAME, MapBuilder.of("registrationName", "onLoadingProgress"));
export.put(TopShouldStartLoadWithRequestEvent.EVENT_NAME, MapBuilder.of("registrationName", "onShouldStartLoadWithRequest"));
return export;
}
@Override
public @Nullable Map<String, Integer> getCommandsMap() {
return MapBuilder.of(
"goBack", COMMAND_GO_BACK,
"goForward", COMMAND_GO_FORWARD,
"reload", COMMAND_RELOAD,
"stopLoading", COMMAND_STOP_LOADING,
"postMessage", COMMAND_POST_MESSAGE,
"injectJavaScript", COMMAND_INJECT_JAVASCRIPT,
"loadUrl", COMMAND_LOAD_URL
);
}
@Override
public void receiveCommand(WebView root, int commandId, @Nullable ReadableArray args) {
switch (commandId) {
case COMMAND_GO_BACK:
root.goBack();
break;
case COMMAND_GO_FORWARD:
root.goForward();
break;
case COMMAND_RELOAD:
root.reload();
break;
case COMMAND_STOP_LOADING:
root.stopLoading();
break;
case COMMAND_POST_MESSAGE:
try {
RNCWebView reactWebView = (RNCWebView) root;
JSONObject eventInitDict = new JSONObject();
eventInitDict.put("data", args.getString(0));
reactWebView.evaluateJavascriptWithFallback("(function () {" +
"var event;" +
"var data = " + eventInitDict.toString() + ";" +
"try {" +
"event = new MessageEvent('message', data);" +
"} catch (e) {" +
"event = document.createEvent('MessageEvent');" +
"event.initMessageEvent('message', true, true, data.data, data.origin, data.lastEventId, data.source);" +
"}" +
"document.dispatchEvent(event);" +
"})();");
} catch (JSONException e) {
throw new RuntimeException(e);
}
break;
case COMMAND_INJECT_JAVASCRIPT:
RNCWebView reactWebView = (RNCWebView) root;
reactWebView.evaluateJavascriptWithFallback(args.getString(0));
break;
case COMMAND_LOAD_URL:
if (args == null) {
throw new RuntimeException("Arguments for loading an url are null!");
}
root.loadUrl(args.getString(0));
break;
}
}
@Override
public void onDropViewInstance(WebView webView) {
super.onDropViewInstance(webView);
((ThemedReactContext) webView.getContext()).removeLifecycleEventListener((RNCWebView) webView);
((RNCWebView) webView).cleanupCallbacksAndDestroy();
}
protected static void dispatchEvent(WebView webView, Event event) {
ReactContext reactContext = (ReactContext) webView.getContext();
EventDispatcher eventDispatcher =
reactContext.getNativeModule(UIManagerModule.class).getEventDispatcher();
eventDispatcher.dispatchEvent(event);
}
public RNCWebViewPackage getPackage() {
return this.aPackage;
}
public void setPackage(RNCWebViewPackage aPackage) {
this.aPackage = aPackage;
}
public RNCWebViewModule getModule() {
return this.aPackage.getModule();
}
}

9423
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,62 +1,64 @@
{
"name": "mattermost-mobile",
"version": "1.3.2",
"version": "1.19.0",
"description": "Mattermost Mobile with React Native",
"repository": "git@github.com:mattermost/mattermost-mobile.git",
"author": "Mattermost, Inc.",
"license": "Apache 2.0",
"private": true,
"dependencies": {
"@babel/runtime": "7.3.1",
"@babel/runtime": "7.4.4",
"@react-native-community/async-storage": "1.4.0",
"@react-native-community/netinfo": "2.0.10",
"analytics-react-native": "1.2.0",
"commonmark": "github:mattermost/commonmark.js#6c3136c18ae8bb7842f8491d160f370a334fd903",
"commonmark-react-renderer": "github:mattermost/commonmark-react-renderer#3a2ac19cab725ad28b170fdc1d397dddedcf87eb",
"deep-equal": "1.0.1",
"emoji-regex": "7.0.3",
"fuse.js": "3.4.2",
"emoji-regex": "8.0.0",
"fuse.js": "3.4.4",
"intl": "1.2.5",
"jail-monkey": "2.0.0",
"jsc-android": "236355.1.1",
"jail-monkey": "2.2.0",
"jsc-android": "241213.1.0",
"mattermost-redux": "github:mattermost/mattermost-redux#57061465c52c27bc25f646b1de8c85915aa62415",
"mime-db": "1.40.0",
"moment-timezone": "0.5.23",
"moment-timezone": "0.5.25",
"prop-types": "15.7.2",
"react": "16.8.2",
"react": "16.8.6",
"react-intl": "2.8.0",
"react-native": "0.58.5",
"react-native-animatable": "1.3.1",
"react-native": "0.59.8",
"react-native-animatable": "1.3.2",
"react-native-bottom-sheet": "1.0.3",
"react-native-button": "2.3.0",
"react-native-calendars": "github:mattermost/react-native-calendars#e399bb749c0a944f009e75e7b45748299aea35d6",
"react-native-button": "2.4.0",
"react-native-calendars": "github:mattermost/react-native-calendars#4937ec5a3bf7e86f9f35fcd85eb4aa6133f45b58",
"react-native-circular-progress": "1.1.0",
"react-native-cookies": "github:joeferraro/react-native-cookies#f11374745deba9f18f7b8a9bb4b0b2573026f522",
"react-native-device-info": "github:mattermost/react-native-device-info#00c9ff7dc11e63b06e0624cc1c4b0cc2bc4e7a39",
"react-native-device-info": "github:mattermost/react-native-device-info#ee766d80b154439deb662da08e93ceb56c0df8ad",
"react-native-doc-viewer": "2.7.8",
"react-native-document-picker": "2.2.0",
"react-native-exception-handler": "2.10.6",
"react-native-gesture-handler": "1.0.15",
"react-native-document-picker": "2.3.0",
"react-native-exception-handler": "2.10.7",
"react-native-gesture-handler": "1.2.1",
"react-native-image-gallery": "github:mattermost/react-native-image-gallery#c1a9f7118e90cc87d47620bc0584c9cac4b0cf38",
"react-native-image-picker": "0.28.0",
"react-native-image-picker": "0.28.1",
"react-native-keyboard-aware-scroll-view": "0.8.0",
"react-native-keychain": "3.1.1",
"react-native-linear-gradient": "2.5.3",
"react-native-keychain": "3.1.3",
"react-native-linear-gradient": "2.5.4",
"react-native-local-auth": "github:mattermost/react-native-local-auth#cc9ce2f468fbf7b431dfad3191a31aaa9227a6ab",
"react-native-navigation": "github:migbot/react-native-navigation#03c623c373f818827a463ca0fe90f86f56e71b2f",
"react-native-notifications": "github:mattermost/react-native-notifications#c58499aedf9bd4c9a405196ec807019ed316f2bb",
"react-native-notifications": "github:mattermost/react-native-notifications#721fcb41b3c265a5eec208a1df181d4ffcafa477",
"react-native-passcode-status": "1.1.1",
"react-native-permissions": "1.1.1",
"react-native-safe-area": "0.5.0",
"react-native-safe-area": "0.5.1",
"react-native-section-list-get-item-layout": "2.2.3",
"react-native-sentry": "0.42.0",
"react-native-slider": "0.11.0",
"react-native-status-bar-size": "0.3.3",
"react-native-svg": "9.2.4",
"react-native-vector-icons": "6.3.0",
"react-native-video": "4.4.0",
"react-native-webview": "5.2.1",
"react-native-svg": "9.4.0",
"react-native-vector-icons": "6.4.2",
"react-native-video": "4.4.1",
"react-native-webview": "github:mattermost/react-native-webview#34e1dbef70413134ddda85df863c962f24b8826e",
"react-native-youtube": "github:mattermost/react-native-youtube#3f395b620ae4e05a3f1c6bdeef3a1158e78daadc",
"react-navigation": "3.2.3",
"react-redux": "5.1.1",
"react-navigation": "3.9.1",
"react-redux": "7.0.3",
"redux": "4.0.1",
"redux-batched-actions": "0.4.1",
"redux-persist": "4.10.2",
@ -64,46 +66,47 @@
"redux-thunk": "2.3.0",
"reselect": "4.0.0",
"rn-fetch-blob": "github:mattermost/react-native-fetch-blob#4ba6980c29608ff8915c70b500b273a0c2fd47b5",
"rn-placeholder": "github:mattermost/rn-placeholder#bfee66eb54f1f06d1425a0ad511a5e16559bf82c",
"semver": "5.6.0",
"rn-placeholder": "github:mattermost/rn-placeholder#0389b32e0c7e2f88ea21b4bd978b5834fb09ab1d",
"semver": "6.0.0",
"shallow-equals": "1.0.0",
"tinycolor2": "1.4.1",
"url-parse": "1.4.4"
"url-parse": "1.4.7"
},
"devDependencies": {
"@babel/cli": "7.2.3",
"@babel/core": "7.3.3",
"@babel/plugin-transform-runtime": "7.2.0",
"@babel/preset-env": "7.3.1",
"@babel/register": "7.0.0",
"babel-core": "7.0.0-bridge.0",
"@babel/cli": "7.4.4",
"@babel/core": "7.4.4",
"@babel/plugin-transform-runtime": "7.4.4",
"@babel/preset-env": "7.4.4",
"@babel/register": "7.4.4",
"babel-eslint": "10.0.1",
"babel-jest": "24.8.0",
"babel-plugin-module-resolver": "3.2.0",
"babel-plugin-transform-remove-console": "6.9.4",
"deep-freeze": "0.0.1",
"enzyme": "3.8.0",
"enzyme-adapter-react-16": "1.9.1",
"enzyme": "3.9.0",
"enzyme-adapter-react-16": "1.13.0",
"enzyme-to-json": "3.3.5",
"eslint": "5.14.0",
"eslint": "5.16.0",
"eslint-config-mattermost": "github:mattermost/eslint-config-mattermost",
"eslint-plugin-header": "3.0.0",
"eslint-plugin-jest": "22.3.0",
"eslint-plugin-react": "7.12.4",
"jest": "24.1.0",
"jest-cli": "24.1.0",
"eslint-plugin-jest": "22.5.1",
"eslint-plugin-react": "7.13.0",
"jest": "24.8.0",
"jest-cli": "24.8.0",
"jest-enzyme": "7.0.2",
"jsdom-global": "3.0.2",
"metro-react-native-babel-preset": "0.51.1",
"metro-react-native-babel-preset": "0.54.0",
"mmjstool": "github:mattermost/mattermost-utilities",
"nyc": "13.3.0",
"react-dom": "16.8.2",
"nyc": "14.1.1",
"react-dom": "16.8.6",
"react-test-renderer": "16.8.6",
"redux-mock-store": "1.5.3",
"remote-redux-devtools": "0.5.16",
"socketcluster": "14.3.3",
"underscore": "1.9.1"
},
"scripts": {
"start": "node ./node_modules/react-native/local-cli/cli.js start --config ../../../../packager-config.js",
"start": "node ./node_modules/react-native/local-cli/cli.js start",
"check": "eslint --ignore-path .gitignore --ignore-pattern node_modules --quiet .",
"fix": "eslint --ignore-path .gitignore --ignore-pattern node_modules --quiet . --fix",
"postinstall": "make post-install",

View file

@ -1,57 +1,22 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
module.exports = [
'app/app.js',
'app/components/app_icon.js',
'app/components/at_mention/at_mention.js',
'app/components/at_mention/index.js',
'app/components/attachment_button.js',
'app/components/autocomplete/at_mention/at_mention.js',
'app/components/autocomplete/at_mention/index.js',
'app/components/autocomplete/at_mention_item/at_mention_item.js',
'app/components/autocomplete/at_mention_item/index.js',
'app/components/autocomplete/autocomplete.js',
'app/components/autocomplete/autocomplete_divider/autocomplete_divider.js',
'app/components/autocomplete/autocomplete_divider/index.js',
'app/components/autocomplete/autocomplete_section_header.js',
'app/components/autocomplete/channel_mention/channel_mention.js',
'app/components/autocomplete/channel_mention/index.js',
'app/components/autocomplete/channel_mention_item/channel_mention_item.js',
'app/components/autocomplete/channel_mention_item/index.js',
'app/components/autocomplete/date_suggestion/date_suggestion.js',
'app/components/autocomplete/date_suggestion/index.js',
'app/components/autocomplete/emoji_suggestion/emoji_suggestion.js',
'app/components/autocomplete/emoji_suggestion/index.js',
'app/components/autocomplete/index.js',
'app/components/autocomplete/slash_suggestion/index.js',
'app/components/autocomplete/slash_suggestion/slash_suggestion.js',
'app/components/autocomplete/slash_suggestion/slash_suggestion_item.js',
'app/components/autocomplete/special_mention_item.js',
'app/components/badge.js',
'app/components/channel_icon.js',
'app/components/channel_link/channel_link.js',
'app/components/channel_link/index.js',
'app/components/channel_loader/channel_loader.js',
'app/components/channel_loader/index.js',
'app/components/combined_system_message/combined_system_message.js',
'app/components/combined_system_message/index.js',
'app/components/combined_system_message/last_users.js',
'app/components/emoji/emoji.js',
'app/components/emoji/index.js',
'app/components/fade.js',
'app/components/file_attachment_list/file_attachment_icon.js',
'app/components/file_attachment_list/file_attachment_image.js',
'app/components/file_upload_preview/file_upload_item/file_upload_item.js',
'app/components/file_upload_preview/file_upload_item/index.js',
'app/components/file_upload_preview/file_upload_preview.js',
'app/components/file_upload_preview/file_upload_remove.js',
'app/components/file_upload_preview/file_upload_retry.js',
'app/components/file_upload_preview/index.js',
'app/components/formatted_date.js',
'app/components/formatted_markdown_text.js',
'app/components/formatted_text.js',
'app/components/formatted_time.js',
'app/components/interactive_dialog_controller/index.js',
'app/components/interactive_dialog_controller/interactive_dialog_controller.js',
'app/components/layout/keyboard_layout/index.js',
'app/components/layout/keyboard_layout/keyboard_layout.js',
'app/components/loading.js',
@ -80,7 +45,6 @@ module.exports = [
'app/components/markdown/markdown_table_row/markdown_table_row.js',
'app/components/network_indicator/index.js',
'app/components/network_indicator/network_indicator.js',
'app/components/paper_plane.js',
'app/components/post/index.js',
'app/components/post/post.js',
'app/components/post_body/index.js',
@ -92,13 +56,10 @@ module.exports = [
'app/components/post_list/date_header/index.js',
'app/components/post_list/index.js',
'app/components/post_list/new_messages_divider.js',
'app/components/post_list/post_list.android.js',
'app/components/post_list/post_list_base.js',
'app/components/post_list/post_list.js',
'app/components/post_list_retry.js',
'app/components/post_profile_picture/index.js',
'app/components/post_profile_picture/post_profile_picture.js',
'app/components/post_textbox/components/typing/index.js',
'app/components/post_textbox/components/typing/typing.js',
'app/components/post_textbox/index.js',
'app/components/post_textbox/post_textbox.js',
'app/components/profile_picture/index.js',
@ -106,40 +67,13 @@ module.exports = [
'app/components/progressive_image/index.js',
'app/components/progressive_image/progressive_image.js',
'app/components/reply_icon.js',
'app/components/retry_bar_indicator/index.js',
'app/components/retry_bar_indicator/retry_bar_indicator.js',
'app/components/safe_area_view/index.js',
'app/components/safe_area_view/safe_area_view.android.js',
'app/components/show_more_button/index.js',
'app/components/show_more_button/show_more_button.js',
'app/components/sidebars/drawer_layout.js',
'app/components/sidebars/main/channels_list/channel_item/channel_item.js',
'app/components/sidebars/main/channels_list/channel_item/index.js',
'app/components/sidebars/main/channels_list/channels_list.js',
'app/components/sidebars/main/channels_list/index.js',
'app/components/sidebars/main/channels_list/list/index.js',
'app/components/sidebars/main/channels_list/list/list.js',
'app/components/sidebars/main/channels_list/switch_teams_button/index.js',
'app/components/sidebars/main/channels_list/switch_teams_button/switch_teams_button.js',
'app/components/sidebars/main/drawer_swipper/drawer_swiper.js',
'app/components/sidebars/main/drawer_swipper/index.js',
'app/components/sidebars/main/index.js',
'app/components/sidebars/main/main_sidebar.js',
'app/components/sidebars/main/teams_list/index.js',
'app/components/sidebars/main/teams_list/teams_list.js',
'app/components/sidebars/main/teams_list/teams_list_item/index.js',
'app/components/sidebars/main/teams_list/teams_list_item/teams_list_item.js',
'app/components/sidebars/settings/drawer_item.js',
'app/components/sidebars/settings/index.js',
'app/components/sidebars/settings/settings_sidebar.js',
'app/components/sidebars/settings/status_label/index.js',
'app/components/sidebars/settings/status_label/status_label.js',
'app/components/sidebars/settings/user_info/index.js',
'app/components/sidebars/settings/user_info/user_info.js',
'app/components/start/empty_toolbar.js',
'app/components/status_bar/index.js',
'app/components/status_bar/status_bar.js',
'app/components/swiper.js',
'app/components/user_status/index.js',
'app/components/user_status/user_status.js',
'app/components/vector_icon.js',
@ -204,6 +138,7 @@ module.exports = [
'app/screens/index.js',
'app/screens/select_server/index.js',
'app/screens/select_server/select_server.js',
'app/selectors/client_upgrade.js',
'app/store/index.js',
'app/store/middleware.js',
'app/store/thunk.js',
@ -211,7 +146,6 @@ module.exports = [
'app/telemetry/telemetry.android.js',
'app/telemetry/telemetry_utils.js',
'app/utils/avoid_native_bridge.js',
'app/utils/client_upgrade.js',
'app/utils/general.js',
'app/utils/i18n.js',
'app/utils/image_cache_manager.js',
@ -262,9 +196,11 @@ module.exports = [
'node_modules/@babel/runtime/helpers/slicedToArray.js',
'node_modules/@babel/runtime/helpers/toConsumableArray.js',
'node_modules/@babel/runtime/helpers/typeof.js',
'node_modules/@babel/runtime/node_modules/regenerator-runtime/runtime-module.js',
'node_modules/@babel/runtime/node_modules/regenerator-runtime/runtime.js',
'node_modules/@babel/runtime/regenerator/index.js',
'node_modules/@react-native-community/async-storage/lib/AsyncStorage.js',
'node_modules/@react-native-community/async-storage/lib/index.js',
'node_modules/@react-native-community/netinfo/js/index.js',
'node_modules/base-64/base64.js',
'node_modules/commonmark-react-renderer/src/commonmark-react-renderer.js',
'node_modules/component-emitter/index.js',
@ -344,10 +280,12 @@ module.exports = [
'node_modules/core-js/modules/es6.set.js',
'node_modules/core-js/modules/es6.string.includes.js',
'node_modules/core-js/modules/es6.string.iterator.js',
'node_modules/core-js/modules/es6.string.starts-with.js',
'node_modules/core-js/modules/es6.symbol.js',
'node_modules/core-js/modules/es7.array.includes.js',
'node_modules/core-js/modules/es7.object.define-getter.js',
'node_modules/core-js/modules/es7.object.define-setter.js',
'node_modules/core-js/modules/es7.object.entries.js',
'node_modules/core-js/modules/es7.object.values.js',
'node_modules/core-js/modules/es7.symbol.async-iterator.js',
'node_modules/core-js/modules/web.dom.iterable.js',
@ -360,9 +298,7 @@ module.exports = [
'node_modules/event-target-shim/lib/custom-event-target.js',
'node_modules/event-target-shim/lib/event-target.js',
'node_modules/fbjs/lib/ExecutionEnvironment.js',
'node_modules/fbjs/lib/Promise.native.js',
'node_modules/fbjs/lib/areEqual.js',
'node_modules/fbjs/lib/invariant.js',
'node_modules/fbjs/lib/keyMirror.js',
'node_modules/fbjs/lib/keyOf.js',
'node_modules/fbjs/lib/performance.js',
@ -452,26 +388,37 @@ module.exports = [
'node_modules/lodash/omit.js',
'node_modules/lodash/pick.js',
'node_modules/lodash/union.js',
'node_modules/mattermost-redux/action_types/admin.js',
'node_modules/mattermost-redux/action_types/alerts.js',
'node_modules/mattermost-redux/action_types/bots.js',
'node_modules/mattermost-redux/action_types/channels.js',
'node_modules/mattermost-redux/action_types/emojis.js',
'node_modules/mattermost-redux/action_types/errors.js',
'node_modules/mattermost-redux/action_types/files.js',
'node_modules/mattermost-redux/action_types/general.js',
'node_modules/mattermost-redux/action_types/gifs.js',
'node_modules/mattermost-redux/action_types/groups.js',
'node_modules/mattermost-redux/action_types/index.js',
'node_modules/mattermost-redux/action_types/integrations.js',
'node_modules/mattermost-redux/action_types/jobs.js',
'node_modules/mattermost-redux/action_types/posts.js',
'node_modules/mattermost-redux/action_types/preferences.js',
'node_modules/mattermost-redux/action_types/roles.js',
'node_modules/mattermost-redux/action_types/schemes.js',
'node_modules/mattermost-redux/action_types/search.js',
'node_modules/mattermost-redux/action_types/teams.js',
'node_modules/mattermost-redux/action_types/users.js',
'node_modules/mattermost-redux/client/client4.js',
'node_modules/mattermost-redux/client/fetch_etag.js',
'node_modules/mattermost-redux/client/index.js',
'node_modules/mattermost-redux/constants/alerts.js',
'node_modules/mattermost-redux/constants/emoji.js',
'node_modules/mattermost-redux/constants/files.js',
'node_modules/mattermost-redux/constants/general.js',
'node_modules/mattermost-redux/constants/groups.js',
'node_modules/mattermost-redux/constants/index.js',
'node_modules/mattermost-redux/constants/permissions.js',
'node_modules/mattermost-redux/constants/plugins.js',
'node_modules/mattermost-redux/constants/posts.js',
'node_modules/mattermost-redux/constants/preferences.js',
'node_modules/mattermost-redux/constants/request_status.js',
@ -480,22 +427,47 @@ module.exports = [
'node_modules/mattermost-redux/constants/users.js',
'node_modules/mattermost-redux/constants/websocket.js',
'node_modules/mattermost-redux/node_modules/redux-persist/lib/constants.js',
'node_modules/mattermost-redux/reducers/entities/admin.js',
'node_modules/mattermost-redux/reducers/entities/alerts.js',
'node_modules/mattermost-redux/reducers/entities/bots.js',
'node_modules/mattermost-redux/reducers/entities/channels.js',
'node_modules/mattermost-redux/reducers/entities/emojis.js',
'node_modules/mattermost-redux/reducers/entities/files.js',
'node_modules/mattermost-redux/reducers/entities/general.js',
'node_modules/mattermost-redux/reducers/entities/gifs.js',
'node_modules/mattermost-redux/reducers/entities/groups.js',
'node_modules/mattermost-redux/reducers/entities/index.js',
'node_modules/mattermost-redux/reducers/entities/integrations.js',
'node_modules/mattermost-redux/reducers/entities/jobs.js',
'node_modules/mattermost-redux/reducers/entities/posts.js',
'node_modules/mattermost-redux/reducers/entities/preferences.js',
'node_modules/mattermost-redux/reducers/entities/roles.js',
'node_modules/mattermost-redux/reducers/entities/schemes.js',
'node_modules/mattermost-redux/reducers/entities/search.js',
'node_modules/mattermost-redux/reducers/entities/teams.js',
'node_modules/mattermost-redux/reducers/entities/typing.js',
'node_modules/mattermost-redux/reducers/entities/users.js',
'node_modules/mattermost-redux/reducers/errors/index.js',
'node_modules/mattermost-redux/reducers/index.js',
'node_modules/mattermost-redux/reducers/requests/admin.js',
'node_modules/mattermost-redux/reducers/requests/channels.js',
'node_modules/mattermost-redux/reducers/requests/files.js',
'node_modules/mattermost-redux/reducers/requests/general.js',
'node_modules/mattermost-redux/reducers/requests/groups.js',
'node_modules/mattermost-redux/reducers/requests/helpers.js',
'node_modules/mattermost-redux/reducers/requests/index.js',
'node_modules/mattermost-redux/reducers/requests/integrations.js',
'node_modules/mattermost-redux/reducers/requests/jobs.js',
'node_modules/mattermost-redux/reducers/requests/posts.js',
'node_modules/mattermost-redux/reducers/requests/preferences.js',
'node_modules/mattermost-redux/reducers/requests/roles.js',
'node_modules/mattermost-redux/reducers/requests/schemes.js',
'node_modules/mattermost-redux/reducers/requests/search.js',
'node_modules/mattermost-redux/reducers/requests/teams.js',
'node_modules/mattermost-redux/reducers/requests/users.js',
'node_modules/mattermost-redux/selectors/entities/emojis.js',
'node_modules/mattermost-redux/selectors/entities/general.js',
'node_modules/mattermost-redux/selectors/entities/integrations.js',
'node_modules/mattermost-redux/selectors/entities/teams.js',
'node_modules/mattermost-redux/store/configureStore.prod.js',
'node_modules/mattermost-redux/store/helpers.js',
@ -503,11 +475,17 @@ module.exports = [
'node_modules/mattermost-redux/store/initial_state.js',
'node_modules/mattermost-redux/store/middleware.js',
'node_modules/mattermost-redux/store/reducer_registry.js',
'node_modules/mattermost-redux/utils/deep_freeze.js',
'node_modules/mattermost-redux/utils/event_emitter.js',
'node_modules/mattermost-redux/utils/file_utils.js',
'node_modules/mattermost-redux/utils/helpers.js',
'node_modules/mattermost-redux/utils/key_mirror.js',
'node_modules/mattermost-redux/utils/post_list.js',
'node_modules/mattermost-redux/utils/theme_utils.js',
'node_modules/moment-timezone/data/packed/latest.json',
'node_modules/moment-timezone/index.js',
'node_modules/moment-timezone/moment-timezone.js',
'node_modules/moment/moment.js',
'node_modules/object-assign/index.js',
'node_modules/pascalcase/index.js',
'node_modules/path-to-regexp/index.js',
@ -531,11 +509,9 @@ module.exports = [
'node_modules/react-intl/locale-data/index.js',
'node_modules/react-is/cjs/react-is.production.min.js',
'node_modules/react-is/index.js',
'node_modules/react-lifecycles-compat/react-lifecycles-compat.cjs.js',
'node_modules/react-native-button/Button.js',
'node_modules/react-native-button/coalesceNonElementChildren.js',
'node_modules/react-native-device-info/deviceinfo.js',
'node_modules/react-native-keychain/index.js',
'node_modules/react-native-linear-gradient/common.js',
'node_modules/react-native-linear-gradient/index.android.js',
'node_modules/react-native-local-auth/LocalAuth.android.js',
@ -552,67 +528,6 @@ module.exports = [
'node_modules/react-native-navigation/src/views/sharedElementTransition.android.js',
'node_modules/react-native-notifications/index.android.js',
'node_modules/react-native-notifications/notification.android.js',
'node_modules/react-native-recyclerview-list/index.js',
'node_modules/react-native-recyclerview-list/src/Constants.js',
'node_modules/react-native-recyclerview-list/src/DataSource.js',
'node_modules/react-native-recyclerview-list/src/RecyclerRefresh.js',
'node_modules/react-native-recyclerview-list/src/RecyclerViewList.js',
'node_modules/react-native-svg/elements/Circle.js',
'node_modules/react-native-svg/elements/ClipPath.js',
'node_modules/react-native-svg/elements/Defs.js',
'node_modules/react-native-svg/elements/Ellipse.js',
'node_modules/react-native-svg/elements/G.js',
'node_modules/react-native-svg/elements/Image.js',
'node_modules/react-native-svg/elements/Line.js',
'node_modules/react-native-svg/elements/LinearGradient.js',
'node_modules/react-native-svg/elements/Mask.js',
'node_modules/react-native-svg/elements/Path.js',
'node_modules/react-native-svg/elements/Pattern.js',
'node_modules/react-native-svg/elements/Polygon.js',
'node_modules/react-native-svg/elements/Polyline.js',
'node_modules/react-native-svg/elements/RadialGradient.js',
'node_modules/react-native-svg/elements/Rect.js',
'node_modules/react-native-svg/elements/Shape.js',
'node_modules/react-native-svg/elements/Stop.js',
'node_modules/react-native-svg/elements/Svg.js',
'node_modules/react-native-svg/elements/Symbol.js',
'node_modules/react-native-svg/elements/TSpan.js',
'node_modules/react-native-svg/elements/Text.js',
'node_modules/react-native-svg/elements/TextPath.js',
'node_modules/react-native-svg/elements/Use.js',
'node_modules/react-native-svg/index.js',
'node_modules/react-native-svg/lib/Matrix2D.js',
'node_modules/react-native-svg/lib/SvgTouchableMixin.js',
'node_modules/react-native-svg/lib/extract/extractBrush.js',
'node_modules/react-native-svg/lib/extract/extractClipPath.js',
'node_modules/react-native-svg/lib/extract/extractColor.js',
'node_modules/react-native-svg/lib/extract/extractFill.js',
'node_modules/react-native-svg/lib/extract/extractGradient.js',
'node_modules/react-native-svg/lib/extract/extractLengthList.js',
'node_modules/react-native-svg/lib/extract/extractOpacity.js',
'node_modules/react-native-svg/lib/extract/extractPolyPoints.js',
'node_modules/react-native-svg/lib/extract/extractProps.js',
'node_modules/react-native-svg/lib/extract/extractResponder.js',
'node_modules/react-native-svg/lib/extract/extractStroke.js',
'node_modules/react-native-svg/lib/extract/extractText.js',
'node_modules/react-native-svg/lib/extract/extractTransform.js',
'node_modules/react-native-svg/lib/extract/extractViewBox.js',
'node_modules/react-native-svg/lib/extract/transform.js',
'node_modules/react-native-svg/lib/units.js',
'node_modules/react-native-vector-icons/FontAwesome.js',
'node_modules/react-native-vector-icons/Foundation.js',
'node_modules/react-native-vector-icons/Ionicons.js',
'node_modules/react-native-vector-icons/MaterialIcons.js',
'node_modules/react-native-vector-icons/glyphmaps/FontAwesome.json',
'node_modules/react-native-vector-icons/glyphmaps/Foundation.json',
'node_modules/react-native-vector-icons/glyphmaps/Ionicons.json',
'node_modules/react-native-vector-icons/glyphmaps/MaterialIcons.json',
'node_modules/react-native-vector-icons/lib/create-icon-set.js',
'node_modules/react-native-vector-icons/lib/ensure-native-module-available.js',
'node_modules/react-native-vector-icons/lib/icon-button.js',
'node_modules/react-native-vector-icons/lib/react-native.js',
'node_modules/react-native-vector-icons/lib/tab-bar-item-ios.js',
'node_modules/react-native-vector-icons/lib/toolbar-android.js',
'node_modules/react-native/Libraries/Animated/src/Animated.js',
'node_modules/react-native/Libraries/Animated/src/AnimatedEvent.js',
'node_modules/react-native/Libraries/Animated/src/AnimatedImplementation.js',
@ -632,9 +547,7 @@ module.exports = [
'node_modules/react-native/Libraries/BatchedBridge/NativeModules.js',
'node_modules/react-native/Libraries/Color/normalizeColor.js',
'node_modules/react-native/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js',
'node_modules/react-native/Libraries/Components/ScrollResponder.js',
'node_modules/react-native/Libraries/Components/ScrollView/ScrollView.js',
'node_modules/react-native/Libraries/Components/Slider/Slider.js',
'node_modules/react-native/Libraries/Components/StatusBar/StatusBar.js',
'node_modules/react-native/Libraries/Components/Switch/Switch.js',
'node_modules/react-native/Libraries/Components/TextInput/TextInput.js',
@ -648,9 +561,6 @@ module.exports = [
'node_modules/react-native/Libraries/Components/View/ReactNativeViewAttributes.js',
'node_modules/react-native/Libraries/Components/View/View.js',
'node_modules/react-native/Libraries/Components/View/ViewNativeComponent.js',
'node_modules/react-native/Libraries/Components/ViewPager/ViewPagerAndroid.android.js',
'node_modules/react-native/Libraries/Components/WebView/WebView.android.js',
'node_modules/react-native/Libraries/Components/WebView/WebViewShared.js',
'node_modules/react-native/Libraries/Core/ExceptionsManager.js',
'node_modules/react-native/Libraries/Core/InitializeCore.js',
'node_modules/react-native/Libraries/Core/ReactNativeVersion.js',
@ -699,6 +609,7 @@ module.exports = [
'node_modules/react-native/Libraries/PermissionsAndroid/PermissionsAndroid.js',
'node_modules/react-native/Libraries/Promise.js',
'node_modules/react-native/Libraries/ReactNative/AppRegistry.js',
'node_modules/react-native/Libraries/ReactNative/FabricUIManager.js',
'node_modules/react-native/Libraries/ReactNative/I18nManager.js',
'node_modules/react-native/Libraries/ReactNative/UIManager.js',
'node_modules/react-native/Libraries/ReactNative/UIManagerProperties.js',
@ -708,7 +619,6 @@ module.exports = [
'node_modules/react-native/Libraries/Renderer/shims/ReactNative.js',
'node_modules/react-native/Libraries/Renderer/shims/ReactNativeViewConfigRegistry.js',
'node_modules/react-native/Libraries/Renderer/shims/createReactNativeComponentClass.js',
'node_modules/react-native/Libraries/Storage/AsyncStorage.js',
'node_modules/react-native/Libraries/StyleSheet/StyleSheet.js',
'node_modules/react-native/Libraries/StyleSheet/StyleSheetValidation.js',
'node_modules/react-native/Libraries/StyleSheet/flattenStyle.js',
@ -730,12 +640,8 @@ module.exports = [
'node_modules/react-native/Libraries/Utilities/differ/deepDiffer.js',
'node_modules/react-native/Libraries/Utilities/differ/sizesDiffer.js',
'node_modules/react-native/Libraries/Utilities/logError.js',
'node_modules/react-native/Libraries/Utilities/stringifySafe.js',
'node_modules/react-native/Libraries/WebSocket/WebSocket.js',
'node_modules/react-native/Libraries/YellowBox/Data/YellowBoxRegistry.js',
'node_modules/react-native/Libraries/YellowBox/UI/YellowBoxList.js',
'node_modules/react-native/Libraries/YellowBox/UI/YellowBoxListRow.js',
'node_modules/react-native/Libraries/YellowBox/UI/YellowBoxStyle.js',
'node_modules/react-native/Libraries/YellowBox/YellowBox.js',
'node_modules/react-native/Libraries/react-native/React.js',
'node_modules/react-native/Libraries/react-native/react-native-implementation.js',
'node_modules/react-native/Libraries/vendor/core/ErrorUtils.js',
@ -752,6 +658,7 @@ module.exports = [
'node_modules/react-proxy/modules/deleteUnknownAutoBindMethods.js',
'node_modules/react-proxy/modules/index.js',
'node_modules/react-proxy/modules/supportsProtoAssignment.js',
'node_modules/react-redux/lib/components/Context.js',
'node_modules/react-redux/lib/components/Provider.js',
'node_modules/react-redux/lib/components/connectAdvanced.js',
'node_modules/react-redux/lib/connect/connect.js',
@ -762,9 +669,10 @@ module.exports = [
'node_modules/react-redux/lib/connect/verifySubselectors.js',
'node_modules/react-redux/lib/connect/wrapMapToProps.js',
'node_modules/react-redux/lib/index.js',
'node_modules/react-redux/lib/utils/PropTypes.js',
'node_modules/react-redux/lib/utils/Subscription.js',
'node_modules/react-redux/lib/utils/batch.js',
'node_modules/react-redux/lib/utils/isPlainObject.js',
'node_modules/react-redux/lib/utils/reactBatchedUpdates.native.js',
'node_modules/react-redux/lib/utils/shallowEqual.js',
'node_modules/react-redux/lib/utils/verifyPlainObject.js',
'node_modules/react-redux/lib/utils/warning.js',
@ -806,47 +714,12 @@ module.exports = [
'node_modules/rn-fetch-blob/android.js',
'node_modules/rn-fetch-blob/cba/index.js',
'node_modules/rn-fetch-blob/class/RNFetchBlobFile.js',
'node_modules/rn-fetch-blob/class/RNFetchBlobReadStream.js',
'node_modules/rn-fetch-blob/class/RNFetchBlobSession.js',
'node_modules/rn-fetch-blob/class/RNFetchBlobWriteStream.js',
'node_modules/rn-fetch-blob/fs.js',
'node_modules/rn-fetch-blob/index.js',
'node_modules/rn-fetch-blob/ios.js',
'node_modules/rn-fetch-blob/json-stream.js',
'node_modules/rn-fetch-blob/lib/oboe-browser.min.js',
'node_modules/rn-fetch-blob/polyfill/Blob.js',
'node_modules/rn-fetch-blob/polyfill/Event.js',
'node_modules/rn-fetch-blob/polyfill/EventTarget.js',
'node_modules/rn-fetch-blob/polyfill/Fetch.js',
'node_modules/rn-fetch-blob/polyfill/File.js',
'node_modules/rn-fetch-blob/polyfill/FileReader.js',
'node_modules/rn-fetch-blob/polyfill/ProgressEvent.js',
'node_modules/rn-fetch-blob/polyfill/XMLHttpRequest.js',
'node_modules/rn-fetch-blob/polyfill/XMLHttpRequestEventTarget.js',
'node_modules/rn-fetch-blob/polyfill/index.js',
'node_modules/rn-fetch-blob/utils/log.js',
'node_modules/rn-fetch-blob/utils/unicode.js',
'node_modules/rn-fetch-blob/utils/uri.js',
'node_modules/rn-fetch-blob/utils/uuid.js',
'node_modules/rn-host-detect/index.js',
'node_modules/rn-placeholder/index.js',
'node_modules/rn-placeholder/node_modules/prop-types/checkPropTypes.js',
'node_modules/rn-placeholder/node_modules/prop-types/factoryWithTypeCheckers.js',
'node_modules/rn-placeholder/node_modules/prop-types/index.js',
'node_modules/rn-placeholder/node_modules/prop-types/lib/ReactPropTypesSecret.js',
'node_modules/rn-placeholder/src/animation/animations.js',
'node_modules/rn-placeholder/src/animation/fade.js',
'node_modules/rn-placeholder/src/animation/shine.js',
'node_modules/rn-placeholder/src/box/box.style.js',
'node_modules/rn-placeholder/src/components.js',
'node_modules/rn-placeholder/src/imageContent/imageContent.js',
'node_modules/rn-placeholder/src/line/line.style.js',
'node_modules/rn-placeholder/src/media/media.style.js',
'node_modules/rn-placeholder/src/multiWords/multiWords.js',
'node_modules/rn-placeholder/src/paragraph/paragraph.js',
'node_modules/rn-placeholder/src/placeholder.js',
'node_modules/rn-placeholder/src/placeholderContainer.js',
'node_modules/rn-placeholder/src/placeholderStylify.js',
'node_modules/sc-errors/decycle.js',
'node_modules/sc-errors/index.js',
'node_modules/sc-formatter/index.js',
@ -856,8 +729,7 @@ module.exports = [
'node_modules/scheduler/tracing.js',
'node_modules/semver/semver.js',
'node_modules/shallow-equals/index.js',
'node_modules/stacktrace-parser/index.js',
'node_modules/stacktrace-parser/lib/stacktrace-parser.js',
'node_modules/stacktrace-parser/dist/stack-trace-parser.umd.js',
'node_modules/symbol-observable/lib/index.js',
'node_modules/symbol-observable/lib/ponyfill.js',
'node_modules/tinycolor2/tinycolor.js',

View file

@ -5,52 +5,16 @@ module.exports = ['./node_modules/app/app.js',
'./node_modules/app/components/at_mention/at_mention.js',
'./node_modules/app/components/at_mention/index.js',
'./node_modules/app/components/attachment_button.js',
'./node_modules/app/components/autocomplete/at_mention/at_mention.js',
'./node_modules/app/components/autocomplete/at_mention/index.js',
'./node_modules/app/components/autocomplete/at_mention_item/at_mention_item.js',
'./node_modules/app/components/autocomplete/at_mention_item/index.js',
'./node_modules/app/components/autocomplete/autocomplete.js',
'./node_modules/app/components/autocomplete/autocomplete_divider/autocomplete_divider.js',
'./node_modules/app/components/autocomplete/autocomplete_divider/index.js',
'./node_modules/app/components/autocomplete/autocomplete_section_header.js',
'./node_modules/app/components/autocomplete/channel_mention/channel_mention.js',
'./node_modules/app/components/autocomplete/channel_mention/index.js',
'./node_modules/app/components/autocomplete/channel_mention_item/channel_mention_item.js',
'./node_modules/app/components/autocomplete/channel_mention_item/index.js',
'./node_modules/app/components/autocomplete/date_suggestion/date_suggestion.js',
'./node_modules/app/components/autocomplete/date_suggestion/index.js',
'./node_modules/app/components/autocomplete/emoji_suggestion/emoji_suggestion.js',
'./node_modules/app/components/autocomplete/emoji_suggestion/index.js',
'./node_modules/app/components/autocomplete/index.js',
'./node_modules/app/components/autocomplete/slash_suggestion/index.js',
'./node_modules/app/components/autocomplete/slash_suggestion/slash_suggestion.js',
'./node_modules/app/components/autocomplete/slash_suggestion/slash_suggestion_item.js',
'./node_modules/app/components/autocomplete/special_mention_item.js',
'./node_modules/app/components/badge.js',
'./node_modules/app/components/channel_icon.js',
'./node_modules/app/components/channel_link/channel_link.js',
'./node_modules/app/components/channel_link/index.js',
'./node_modules/app/components/channel_loader/channel_loader.js',
'./node_modules/app/components/channel_loader/index.js',
'./node_modules/app/components/combined_system_message/combined_system_message.js',
'./node_modules/app/components/combined_system_message/index.js',
'./node_modules/app/components/combined_system_message/last_users.js',
'./node_modules/app/components/emoji/emoji.js',
'./node_modules/app/components/emoji/index.js',
'./node_modules/app/components/fade.js',
'./node_modules/app/components/file_attachment_list/file_attachment_icon.js',
'./node_modules/app/components/file_attachment_list/file_attachment_image.js',
'./node_modules/app/components/file_upload_preview/file_upload_item/file_upload_item.js',
'./node_modules/app/components/file_upload_preview/file_upload_item/index.js',
'./node_modules/app/components/file_upload_preview/file_upload_preview.js',
'./node_modules/app/components/file_upload_preview/file_upload_remove.js',
'./node_modules/app/components/file_upload_preview/file_upload_retry.js',
'./node_modules/app/components/file_upload_preview/index.js',
'./node_modules/app/components/formatted_date.js',
'./node_modules/app/components/formatted_markdown_text.js',
'./node_modules/app/components/formatted_text.js',
'./node_modules/app/components/formatted_time.js',
'./node_modules/app/components/interactive_dialog_controller/index.js',
'./node_modules/app/components/interactive_dialog_controller/interactive_dialog_controller.js',
'./node_modules/app/components/layout/keyboard_layout/index.js',
'./node_modules/app/components/layout/keyboard_layout/keyboard_layout.js',
'./node_modules/app/components/loading.js',
@ -79,7 +43,6 @@ module.exports = ['./node_modules/app/app.js',
'./node_modules/app/components/markdown/markdown_table_row/markdown_table_row.js',
'./node_modules/app/components/network_indicator/index.js',
'./node_modules/app/components/network_indicator/network_indicator.js',
'./node_modules/app/components/paper_plane.js',
'./node_modules/app/components/post/index.js',
'./node_modules/app/components/post/post.js',
'./node_modules/app/components/post_body/index.js',
@ -91,13 +54,10 @@ module.exports = ['./node_modules/app/app.js',
'./node_modules/app/components/post_list/date_header/index.js',
'./node_modules/app/components/post_list/index.js',
'./node_modules/app/components/post_list/new_messages_divider.js',
'./node_modules/app/components/post_list/post_list.android.js',
'./node_modules/app/components/post_list/post_list_base.js',
'./node_modules/app/components/post_list/post_list.js',
'./node_modules/app/components/post_list_retry.js',
'./node_modules/app/components/post_profile_picture/index.js',
'./node_modules/app/components/post_profile_picture/post_profile_picture.js',
'./node_modules/app/components/post_textbox/components/typing/index.js',
'./node_modules/app/components/post_textbox/components/typing/typing.js',
'./node_modules/app/components/post_textbox/index.js',
'./node_modules/app/components/post_textbox/post_textbox.js',
'./node_modules/app/components/profile_picture/index.js',
@ -176,6 +136,7 @@ module.exports = ['./node_modules/app/app.js',
'./node_modules/app/screens/index.js',
'./node_modules/app/screens/select_server/index.js',
'./node_modules/app/screens/select_server/select_server.js',
'./node_modules/app/selectors/client_upgrade.js',
'./node_modules/app/store/index.js',
'./node_modules/app/store/middleware.js',
'./node_modules/app/store/thunk.js',
@ -183,7 +144,6 @@ module.exports = ['./node_modules/app/app.js',
'./node_modules/app/telemetry/telemetry.android.js',
'./node_modules/app/telemetry/telemetry_utils.js',
'./node_modules/app/utils/avoid_native_bridge.js',
'./node_modules/app/utils/client_upgrade.js',
'./node_modules/app/utils/general.js',
'./node_modules/app/utils/i18n.js',
'./node_modules/app/utils/image_cache_manager.js',
@ -213,9 +173,11 @@ module.exports = ['./node_modules/app/app.js',
'./node_modules/node_modules/@babel/runtime/helpers/slicedToArray.js',
'./node_modules/node_modules/@babel/runtime/helpers/toConsumableArray.js',
'./node_modules/node_modules/@babel/runtime/helpers/typeof.js',
'./node_modules/node_modules/@babel/runtime/node_modules/regenerator-runtime/runtime-module.js',
'./node_modules/node_modules/@babel/runtime/node_modules/regenerator-runtime/runtime.js',
'./node_modules/node_modules/@babel/runtime/regenerator/index.js',
'./node_modules/node_modules/@react-native-community/async-storage/lib/AsyncStorage.js',
'./node_modules/node_modules/@react-native-community/async-storage/lib/index.js',
'./node_modules/node_modules/@react-native-community/netinfo/js/index.js',
'./node_modules/node_modules/base-64/base64.js',
'./node_modules/node_modules/commonmark-react-renderer/src/commonmark-react-renderer.js',
'./node_modules/node_modules/component-emitter/index.js',
@ -295,10 +257,12 @@ module.exports = ['./node_modules/app/app.js',
'./node_modules/node_modules/core-js/modules/es6.set.js',
'./node_modules/node_modules/core-js/modules/es6.string.includes.js',
'./node_modules/node_modules/core-js/modules/es6.string.iterator.js',
'./node_modules/node_modules/core-js/modules/es6.string.starts-with.js',
'./node_modules/node_modules/core-js/modules/es6.symbol.js',
'./node_modules/node_modules/core-js/modules/es7.array.includes.js',
'./node_modules/node_modules/core-js/modules/es7.object.define-getter.js',
'./node_modules/node_modules/core-js/modules/es7.object.define-setter.js',
'./node_modules/node_modules/core-js/modules/es7.object.entries.js',
'./node_modules/node_modules/core-js/modules/es7.object.values.js',
'./node_modules/node_modules/core-js/modules/es7.symbol.async-iterator.js',
'./node_modules/node_modules/core-js/modules/web.dom.iterable.js',
@ -311,9 +275,7 @@ module.exports = ['./node_modules/app/app.js',
'./node_modules/node_modules/event-target-shim/lib/custom-event-target.js',
'./node_modules/node_modules/event-target-shim/lib/event-target.js',
'./node_modules/node_modules/fbjs/lib/ExecutionEnvironment.js',
'./node_modules/node_modules/fbjs/lib/Promise.native.js',
'./node_modules/node_modules/fbjs/lib/areEqual.js',
'./node_modules/node_modules/fbjs/lib/invariant.js',
'./node_modules/node_modules/fbjs/lib/keyMirror.js',
'./node_modules/node_modules/fbjs/lib/keyOf.js',
'./node_modules/node_modules/fbjs/lib/performance.js',
@ -403,26 +365,37 @@ module.exports = ['./node_modules/app/app.js',
'./node_modules/node_modules/lodash/omit.js',
'./node_modules/node_modules/lodash/pick.js',
'./node_modules/node_modules/lodash/union.js',
'./node_modules/node_modules/mattermost-redux/action_types/admin.js',
'./node_modules/node_modules/mattermost-redux/action_types/alerts.js',
'./node_modules/node_modules/mattermost-redux/action_types/bots.js',
'./node_modules/node_modules/mattermost-redux/action_types/channels.js',
'./node_modules/node_modules/mattermost-redux/action_types/emojis.js',
'./node_modules/node_modules/mattermost-redux/action_types/errors.js',
'./node_modules/node_modules/mattermost-redux/action_types/files.js',
'./node_modules/node_modules/mattermost-redux/action_types/general.js',
'./node_modules/node_modules/mattermost-redux/action_types/gifs.js',
'./node_modules/node_modules/mattermost-redux/action_types/groups.js',
'./node_modules/node_modules/mattermost-redux/action_types/index.js',
'./node_modules/node_modules/mattermost-redux/action_types/integrations.js',
'./node_modules/node_modules/mattermost-redux/action_types/jobs.js',
'./node_modules/node_modules/mattermost-redux/action_types/posts.js',
'./node_modules/node_modules/mattermost-redux/action_types/preferences.js',
'./node_modules/node_modules/mattermost-redux/action_types/roles.js',
'./node_modules/node_modules/mattermost-redux/action_types/schemes.js',
'./node_modules/node_modules/mattermost-redux/action_types/search.js',
'./node_modules/node_modules/mattermost-redux/action_types/teams.js',
'./node_modules/node_modules/mattermost-redux/action_types/users.js',
'./node_modules/node_modules/mattermost-redux/client/client4.js',
'./node_modules/node_modules/mattermost-redux/client/fetch_etag.js',
'./node_modules/node_modules/mattermost-redux/client/index.js',
'./node_modules/node_modules/mattermost-redux/constants/alerts.js',
'./node_modules/node_modules/mattermost-redux/constants/emoji.js',
'./node_modules/node_modules/mattermost-redux/constants/files.js',
'./node_modules/node_modules/mattermost-redux/constants/general.js',
'./node_modules/node_modules/mattermost-redux/constants/groups.js',
'./node_modules/node_modules/mattermost-redux/constants/index.js',
'./node_modules/node_modules/mattermost-redux/constants/permissions.js',
'./node_modules/node_modules/mattermost-redux/constants/plugins.js',
'./node_modules/node_modules/mattermost-redux/constants/posts.js',
'./node_modules/node_modules/mattermost-redux/constants/preferences.js',
'./node_modules/node_modules/mattermost-redux/constants/request_status.js',
@ -431,22 +404,47 @@ module.exports = ['./node_modules/app/app.js',
'./node_modules/node_modules/mattermost-redux/constants/users.js',
'./node_modules/node_modules/mattermost-redux/constants/websocket.js',
'./node_modules/node_modules/mattermost-redux/node_modules/redux-persist/lib/constants.js',
'./node_modules/node_modules/mattermost-redux/reducers/entities/admin.js',
'./node_modules/node_modules/mattermost-redux/reducers/entities/alerts.js',
'./node_modules/node_modules/mattermost-redux/reducers/entities/bots.js',
'./node_modules/node_modules/mattermost-redux/reducers/entities/channels.js',
'./node_modules/node_modules/mattermost-redux/reducers/entities/emojis.js',
'./node_modules/node_modules/mattermost-redux/reducers/entities/files.js',
'./node_modules/node_modules/mattermost-redux/reducers/entities/general.js',
'./node_modules/node_modules/mattermost-redux/reducers/entities/gifs.js',
'./node_modules/node_modules/mattermost-redux/reducers/entities/groups.js',
'./node_modules/node_modules/mattermost-redux/reducers/entities/index.js',
'./node_modules/node_modules/mattermost-redux/reducers/entities/integrations.js',
'./node_modules/node_modules/mattermost-redux/reducers/entities/jobs.js',
'./node_modules/node_modules/mattermost-redux/reducers/entities/posts.js',
'./node_modules/node_modules/mattermost-redux/reducers/entities/preferences.js',
'./node_modules/node_modules/mattermost-redux/reducers/entities/roles.js',
'./node_modules/node_modules/mattermost-redux/reducers/entities/schemes.js',
'./node_modules/node_modules/mattermost-redux/reducers/entities/search.js',
'./node_modules/node_modules/mattermost-redux/reducers/entities/teams.js',
'./node_modules/node_modules/mattermost-redux/reducers/entities/typing.js',
'./node_modules/node_modules/mattermost-redux/reducers/entities/users.js',
'./node_modules/node_modules/mattermost-redux/reducers/errors/index.js',
'./node_modules/node_modules/mattermost-redux/reducers/index.js',
'./node_modules/node_modules/mattermost-redux/reducers/requests/admin.js',
'./node_modules/node_modules/mattermost-redux/reducers/requests/channels.js',
'./node_modules/node_modules/mattermost-redux/reducers/requests/files.js',
'./node_modules/node_modules/mattermost-redux/reducers/requests/general.js',
'./node_modules/node_modules/mattermost-redux/reducers/requests/groups.js',
'./node_modules/node_modules/mattermost-redux/reducers/requests/helpers.js',
'./node_modules/node_modules/mattermost-redux/reducers/requests/index.js',
'./node_modules/node_modules/mattermost-redux/reducers/requests/integrations.js',
'./node_modules/node_modules/mattermost-redux/reducers/requests/jobs.js',
'./node_modules/node_modules/mattermost-redux/reducers/requests/posts.js',
'./node_modules/node_modules/mattermost-redux/reducers/requests/preferences.js',
'./node_modules/node_modules/mattermost-redux/reducers/requests/roles.js',
'./node_modules/node_modules/mattermost-redux/reducers/requests/schemes.js',
'./node_modules/node_modules/mattermost-redux/reducers/requests/search.js',
'./node_modules/node_modules/mattermost-redux/reducers/requests/teams.js',
'./node_modules/node_modules/mattermost-redux/reducers/requests/users.js',
'./node_modules/node_modules/mattermost-redux/selectors/entities/emojis.js',
'./node_modules/node_modules/mattermost-redux/selectors/entities/general.js',
'./node_modules/node_modules/mattermost-redux/selectors/entities/integrations.js',
'./node_modules/node_modules/mattermost-redux/selectors/entities/teams.js',
'./node_modules/node_modules/mattermost-redux/store/configureStore.prod.js',
'./node_modules/node_modules/mattermost-redux/store/helpers.js',
@ -454,11 +452,16 @@ module.exports = ['./node_modules/app/app.js',
'./node_modules/node_modules/mattermost-redux/store/initial_state.js',
'./node_modules/node_modules/mattermost-redux/store/middleware.js',
'./node_modules/node_modules/mattermost-redux/store/reducer_registry.js',
'./node_modules/node_modules/mattermost-redux/utils/deep_freeze.js',
'./node_modules/node_modules/mattermost-redux/utils/event_emitter.js',
'./node_modules/node_modules/mattermost-redux/utils/file_utils.js',
'./node_modules/node_modules/mattermost-redux/utils/helpers.js',
'./node_modules/node_modules/mattermost-redux/utils/key_mirror.js',
'./node_modules/node_modules/mattermost-redux/utils/post_list.js',
'./node_modules/node_modules/mattermost-redux/utils/theme_utils.js',
'./node_modules/node_modules/moment-timezone/index.js',
'./node_modules/node_modules/moment-timezone/moment-timezone.js',
'./node_modules/node_modules/moment/moment.js',
'./node_modules/node_modules/object-assign/index.js',
'./node_modules/node_modules/pascalcase/index.js',
'./node_modules/node_modules/path-to-regexp/index.js',
@ -477,15 +480,14 @@ module.exports = ['./node_modules/app/app.js',
'./node_modules/node_modules/querystring/encode.js',
'./node_modules/node_modules/querystring/index.js',
'./node_modules/node_modules/querystringify/index.js',
'./node_modules/node_modules/react-deep-force-update/lib/index.js',
'./node_modules/node_modules/react-intl/lib/index.js',
'./node_modules/node_modules/react-intl/locale-data/index.js',
'./node_modules/node_modules/react-is/cjs/react-is.production.min.js',
'./node_modules/node_modules/react-is/index.js',
'./node_modules/node_modules/react-lifecycles-compat/react-lifecycles-compat.cjs.js',
'./node_modules/node_modules/react-native-button/Button.js',
'./node_modules/node_modules/react-native-button/coalesceNonElementChildren.js',
'./node_modules/node_modules/react-native-device-info/deviceinfo.js',
'./node_modules/node_modules/react-native-keychain/index.js',
'./node_modules/node_modules/react-native-linear-gradient/common.js',
'./node_modules/node_modules/react-native-linear-gradient/index.android.js',
'./node_modules/node_modules/react-native-local-auth/LocalAuth.android.js',
@ -502,63 +504,6 @@ module.exports = ['./node_modules/app/app.js',
'./node_modules/node_modules/react-native-navigation/src/views/sharedElementTransition.android.js',
'./node_modules/node_modules/react-native-notifications/index.android.js',
'./node_modules/node_modules/react-native-notifications/notification.android.js',
'./node_modules/node_modules/react-native-recyclerview-list/index.js',
'./node_modules/node_modules/react-native-recyclerview-list/src/Constants.js',
'./node_modules/node_modules/react-native-recyclerview-list/src/DataSource.js',
'./node_modules/node_modules/react-native-recyclerview-list/src/RecyclerRefresh.js',
'./node_modules/node_modules/react-native-recyclerview-list/src/RecyclerViewList.js',
'./node_modules/node_modules/react-native-svg/elements/Circle.js',
'./node_modules/node_modules/react-native-svg/elements/ClipPath.js',
'./node_modules/node_modules/react-native-svg/elements/Defs.js',
'./node_modules/node_modules/react-native-svg/elements/Ellipse.js',
'./node_modules/node_modules/react-native-svg/elements/G.js',
'./node_modules/node_modules/react-native-svg/elements/Image.js',
'./node_modules/node_modules/react-native-svg/elements/Line.js',
'./node_modules/node_modules/react-native-svg/elements/LinearGradient.js',
'./node_modules/node_modules/react-native-svg/elements/Mask.js',
'./node_modules/node_modules/react-native-svg/elements/Path.js',
'./node_modules/node_modules/react-native-svg/elements/Pattern.js',
'./node_modules/node_modules/react-native-svg/elements/Polygon.js',
'./node_modules/node_modules/react-native-svg/elements/Polyline.js',
'./node_modules/node_modules/react-native-svg/elements/RadialGradient.js',
'./node_modules/node_modules/react-native-svg/elements/Rect.js',
'./node_modules/node_modules/react-native-svg/elements/Shape.js',
'./node_modules/node_modules/react-native-svg/elements/Stop.js',
'./node_modules/node_modules/react-native-svg/elements/Svg.js',
'./node_modules/node_modules/react-native-svg/elements/Symbol.js',
'./node_modules/node_modules/react-native-svg/elements/TSpan.js',
'./node_modules/node_modules/react-native-svg/elements/Text.js',
'./node_modules/node_modules/react-native-svg/elements/TextPath.js',
'./node_modules/node_modules/react-native-svg/elements/Use.js',
'./node_modules/node_modules/react-native-svg/index.js',
'./node_modules/node_modules/react-native-svg/lib/Matrix2D.js',
'./node_modules/node_modules/react-native-svg/lib/SvgTouchableMixin.js',
'./node_modules/node_modules/react-native-svg/lib/extract/extractBrush.js',
'./node_modules/node_modules/react-native-svg/lib/extract/extractClipPath.js',
'./node_modules/node_modules/react-native-svg/lib/extract/extractColor.js',
'./node_modules/node_modules/react-native-svg/lib/extract/extractFill.js',
'./node_modules/node_modules/react-native-svg/lib/extract/extractGradient.js',
'./node_modules/node_modules/react-native-svg/lib/extract/extractLengthList.js',
'./node_modules/node_modules/react-native-svg/lib/extract/extractOpacity.js',
'./node_modules/node_modules/react-native-svg/lib/extract/extractPolyPoints.js',
'./node_modules/node_modules/react-native-svg/lib/extract/extractProps.js',
'./node_modules/node_modules/react-native-svg/lib/extract/extractResponder.js',
'./node_modules/node_modules/react-native-svg/lib/extract/extractStroke.js',
'./node_modules/node_modules/react-native-svg/lib/extract/extractText.js',
'./node_modules/node_modules/react-native-svg/lib/extract/extractTransform.js',
'./node_modules/node_modules/react-native-svg/lib/extract/extractViewBox.js',
'./node_modules/node_modules/react-native-svg/lib/extract/transform.js',
'./node_modules/node_modules/react-native-svg/lib/units.js',
'./node_modules/node_modules/react-native-vector-icons/FontAwesome.js',
'./node_modules/node_modules/react-native-vector-icons/Foundation.js',
'./node_modules/node_modules/react-native-vector-icons/Ionicons.js',
'./node_modules/node_modules/react-native-vector-icons/MaterialIcons.js',
'./node_modules/node_modules/react-native-vector-icons/lib/create-icon-set.js',
'./node_modules/node_modules/react-native-vector-icons/lib/ensure-native-module-available.js',
'./node_modules/node_modules/react-native-vector-icons/lib/icon-button.js',
'./node_modules/node_modules/react-native-vector-icons/lib/react-native.js',
'./node_modules/node_modules/react-native-vector-icons/lib/tab-bar-item-ios.js',
'./node_modules/node_modules/react-native-vector-icons/lib/toolbar-android.js',
'./node_modules/node_modules/react-native/Libraries/Animated/src/Animated.js',
'./node_modules/node_modules/react-native/Libraries/Animated/src/AnimatedEvent.js',
'./node_modules/node_modules/react-native/Libraries/Animated/src/AnimatedImplementation.js',
@ -578,9 +523,7 @@ module.exports = ['./node_modules/app/app.js',
'./node_modules/node_modules/react-native/Libraries/BatchedBridge/NativeModules.js',
'./node_modules/node_modules/react-native/Libraries/Color/normalizeColor.js',
'./node_modules/node_modules/react-native/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js',
'./node_modules/node_modules/react-native/Libraries/Components/ScrollResponder.js',
'./node_modules/node_modules/react-native/Libraries/Components/ScrollView/ScrollView.js',
'./node_modules/node_modules/react-native/Libraries/Components/Slider/Slider.js',
'./node_modules/node_modules/react-native/Libraries/Components/StatusBar/StatusBar.js',
'./node_modules/node_modules/react-native/Libraries/Components/Switch/Switch.js',
'./node_modules/node_modules/react-native/Libraries/Components/TextInput/TextInput.js',
@ -594,9 +537,6 @@ module.exports = ['./node_modules/app/app.js',
'./node_modules/node_modules/react-native/Libraries/Components/View/ReactNativeViewAttributes.js',
'./node_modules/node_modules/react-native/Libraries/Components/View/View.js',
'./node_modules/node_modules/react-native/Libraries/Components/View/ViewNativeComponent.js',
'./node_modules/node_modules/react-native/Libraries/Components/ViewPager/ViewPagerAndroid.android.js',
'./node_modules/node_modules/react-native/Libraries/Components/WebView/WebView.android.js',
'./node_modules/node_modules/react-native/Libraries/Components/WebView/WebViewShared.js',
'./node_modules/node_modules/react-native/Libraries/Core/ExceptionsManager.js',
'./node_modules/node_modules/react-native/Libraries/Core/InitializeCore.js',
'./node_modules/node_modules/react-native/Libraries/Core/ReactNativeVersion.js',
@ -645,6 +585,7 @@ module.exports = ['./node_modules/app/app.js',
'./node_modules/node_modules/react-native/Libraries/PermissionsAndroid/PermissionsAndroid.js',
'./node_modules/node_modules/react-native/Libraries/Promise.js',
'./node_modules/node_modules/react-native/Libraries/ReactNative/AppRegistry.js',
'./node_modules/node_modules/react-native/Libraries/ReactNative/FabricUIManager.js',
'./node_modules/node_modules/react-native/Libraries/ReactNative/I18nManager.js',
'./node_modules/node_modules/react-native/Libraries/ReactNative/UIManager.js',
'./node_modules/node_modules/react-native/Libraries/ReactNative/UIManagerProperties.js',
@ -654,7 +595,6 @@ module.exports = ['./node_modules/app/app.js',
'./node_modules/node_modules/react-native/Libraries/Renderer/shims/ReactNative.js',
'./node_modules/node_modules/react-native/Libraries/Renderer/shims/ReactNativeViewConfigRegistry.js',
'./node_modules/node_modules/react-native/Libraries/Renderer/shims/createReactNativeComponentClass.js',
'./node_modules/node_modules/react-native/Libraries/Storage/AsyncStorage.js',
'./node_modules/node_modules/react-native/Libraries/StyleSheet/StyleSheet.js',
'./node_modules/node_modules/react-native/Libraries/StyleSheet/StyleSheetValidation.js',
'./node_modules/node_modules/react-native/Libraries/StyleSheet/flattenStyle.js',
@ -676,6 +616,7 @@ module.exports = ['./node_modules/app/app.js',
'./node_modules/node_modules/react-native/Libraries/Utilities/differ/deepDiffer.js',
'./node_modules/node_modules/react-native/Libraries/Utilities/differ/sizesDiffer.js',
'./node_modules/node_modules/react-native/Libraries/Utilities/logError.js',
'./node_modules/node_modules/react-native/Libraries/Utilities/stringifySafe.js',
'./node_modules/node_modules/react-native/Libraries/WebSocket/WebSocket.js',
'./node_modules/node_modules/react-native/Libraries/react-native/React.js',
'./node_modules/node_modules/react-native/Libraries/react-native/react-native-implementation.js',
@ -693,6 +634,7 @@ module.exports = ['./node_modules/app/app.js',
'./node_modules/node_modules/react-proxy/modules/deleteUnknownAutoBindMethods.js',
'./node_modules/node_modules/react-proxy/modules/index.js',
'./node_modules/node_modules/react-proxy/modules/supportsProtoAssignment.js',
'./node_modules/node_modules/react-redux/lib/components/Context.js',
'./node_modules/node_modules/react-redux/lib/components/Provider.js',
'./node_modules/node_modules/react-redux/lib/components/connectAdvanced.js',
'./node_modules/node_modules/react-redux/lib/connect/connect.js',
@ -703,9 +645,10 @@ module.exports = ['./node_modules/app/app.js',
'./node_modules/node_modules/react-redux/lib/connect/verifySubselectors.js',
'./node_modules/node_modules/react-redux/lib/connect/wrapMapToProps.js',
'./node_modules/node_modules/react-redux/lib/index.js',
'./node_modules/node_modules/react-redux/lib/utils/PropTypes.js',
'./node_modules/node_modules/react-redux/lib/utils/Subscription.js',
'./node_modules/node_modules/react-redux/lib/utils/batch.js',
'./node_modules/node_modules/react-redux/lib/utils/isPlainObject.js',
'./node_modules/node_modules/react-redux/lib/utils/reactBatchedUpdates.native.js',
'./node_modules/node_modules/react-redux/lib/utils/shallowEqual.js',
'./node_modules/node_modules/react-redux/lib/utils/verifyPlainObject.js',
'./node_modules/node_modules/react-redux/lib/utils/warning.js',
@ -747,47 +690,12 @@ module.exports = ['./node_modules/app/app.js',
'./node_modules/node_modules/rn-fetch-blob/android.js',
'./node_modules/node_modules/rn-fetch-blob/cba/index.js',
'./node_modules/node_modules/rn-fetch-blob/class/RNFetchBlobFile.js',
'./node_modules/node_modules/rn-fetch-blob/class/RNFetchBlobReadStream.js',
'./node_modules/node_modules/rn-fetch-blob/class/RNFetchBlobSession.js',
'./node_modules/node_modules/rn-fetch-blob/class/RNFetchBlobWriteStream.js',
'./node_modules/node_modules/rn-fetch-blob/fs.js',
'./node_modules/node_modules/rn-fetch-blob/index.js',
'./node_modules/node_modules/rn-fetch-blob/ios.js',
'./node_modules/node_modules/rn-fetch-blob/json-stream.js',
'./node_modules/node_modules/rn-fetch-blob/lib/oboe-browser.min.js',
'./node_modules/node_modules/rn-fetch-blob/polyfill/Blob.js',
'./node_modules/node_modules/rn-fetch-blob/polyfill/Event.js',
'./node_modules/node_modules/rn-fetch-blob/polyfill/EventTarget.js',
'./node_modules/node_modules/rn-fetch-blob/polyfill/Fetch.js',
'./node_modules/node_modules/rn-fetch-blob/polyfill/File.js',
'./node_modules/node_modules/rn-fetch-blob/polyfill/FileReader.js',
'./node_modules/node_modules/rn-fetch-blob/polyfill/ProgressEvent.js',
'./node_modules/node_modules/rn-fetch-blob/polyfill/XMLHttpRequest.js',
'./node_modules/node_modules/rn-fetch-blob/polyfill/XMLHttpRequestEventTarget.js',
'./node_modules/node_modules/rn-fetch-blob/polyfill/index.js',
'./node_modules/node_modules/rn-fetch-blob/utils/log.js',
'./node_modules/node_modules/rn-fetch-blob/utils/unicode.js',
'./node_modules/node_modules/rn-fetch-blob/utils/uri.js',
'./node_modules/node_modules/rn-fetch-blob/utils/uuid.js',
'./node_modules/node_modules/rn-host-detect/index.js',
'./node_modules/node_modules/rn-placeholder/index.js',
'./node_modules/node_modules/rn-placeholder/node_modules/prop-types/checkPropTypes.js',
'./node_modules/node_modules/rn-placeholder/node_modules/prop-types/factoryWithTypeCheckers.js',
'./node_modules/node_modules/rn-placeholder/node_modules/prop-types/index.js',
'./node_modules/node_modules/rn-placeholder/node_modules/prop-types/lib/ReactPropTypesSecret.js',
'./node_modules/node_modules/rn-placeholder/src/animation/animations.js',
'./node_modules/node_modules/rn-placeholder/src/animation/fade.js',
'./node_modules/node_modules/rn-placeholder/src/animation/shine.js',
'./node_modules/node_modules/rn-placeholder/src/box/box.style.js',
'./node_modules/node_modules/rn-placeholder/src/components.js',
'./node_modules/node_modules/rn-placeholder/src/imageContent/imageContent.js',
'./node_modules/node_modules/rn-placeholder/src/line/line.style.js',
'./node_modules/node_modules/rn-placeholder/src/media/media.style.js',
'./node_modules/node_modules/rn-placeholder/src/multiWords/multiWords.js',
'./node_modules/node_modules/rn-placeholder/src/paragraph/paragraph.js',
'./node_modules/node_modules/rn-placeholder/src/placeholder.js',
'./node_modules/node_modules/rn-placeholder/src/placeholderContainer.js',
'./node_modules/node_modules/rn-placeholder/src/placeholderStylify.js',
'./node_modules/node_modules/sc-errors/decycle.js',
'./node_modules/node_modules/sc-errors/index.js',
'./node_modules/node_modules/sc-formatter/index.js',
@ -797,7 +705,8 @@ module.exports = ['./node_modules/app/app.js',
'./node_modules/node_modules/scheduler/tracing.js',
'./node_modules/node_modules/semver/semver.js',
'./node_modules/node_modules/shallow-equals/index.js',
'./node_modules/node_modules/stacktrace-parser/dist/stack-trace-parser.umd.js',
'./node_modules/node_modules/symbol-observable/lib/index.js',
'./node_modules/node_modules/symbol-observable/lib/ponyfill.js',
'./node_modules/node_modules/tinycolor2/tinycolor.js',
'./node_modules/node_modules/url-parse/index.js'];
'./node_modules/node_modules/url-parse/index.js'];