Add Perf metrics, some cleanup & dep updates (#5378)

This commit is contained in:
Elias Nahum 2021-05-12 08:48:20 -04:00 committed by GitHub
parent f47f872b1a
commit 288c847518
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
81 changed files with 2065 additions and 2929 deletions

View file

@ -33,8 +33,6 @@ import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactMarker;
import com.facebook.react.bridge.ReactMarkerConstants;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.module.model.ReactModuleInfo;
import com.facebook.react.module.model.ReactModuleInfoProvider;
@ -132,9 +130,6 @@ private final ReactNativeHost mReactNativeHost =
SoLoader.init(this, /* native exopackage */ false);
initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
// Uncomment to listen to react markers for build that has telemetry enabled
// addReactMarkerListener();
}
@Override
@ -195,38 +190,6 @@ private final ReactNativeHost mReactNativeHost =
return null;
}
private void addReactMarkerListener() {
ReactMarker.addListener(new ReactMarker.MarkerListener() {
@Override
public void logMarker(ReactMarkerConstants name, @Nullable String tag, int instanceKey) {
if (name.toString() == ReactMarkerConstants.RELOAD.toString()) {
APP_START_TIME = System.currentTimeMillis();
RELOAD = System.currentTimeMillis();
} else if (name.toString() == ReactMarkerConstants.PROCESS_PACKAGES_START.toString()) {
PROCESS_PACKAGES_START = System.currentTimeMillis();
} else if (name.toString() == ReactMarkerConstants.PROCESS_PACKAGES_END.toString()) {
PROCESS_PACKAGES_END = System.currentTimeMillis();
} else if (name.toString() == ReactMarkerConstants.CONTENT_APPEARED.toString()) {
CONTENT_APPEARED = System.currentTimeMillis();
ReactContext ctx = getRunningReactContext();
if (ctx != null) {
WritableMap map = Arguments.createMap();
map.putDouble("appReload", RELOAD);
map.putDouble("appContentAppeared", CONTENT_APPEARED);
map.putDouble("processPackagesStart", PROCESS_PACKAGES_START);
map.putDouble("processPackagesEnd", PROCESS_PACKAGES_END);
ctx.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).
emit("nativeMetrics", map);
}
}
}
});
}
/**
* Loads Flipper in React Native templates. Call this in the onCreate method with something like
* initializeFlipper(this, getReactNativeHost().getReactInstanceManager());

View file

@ -29,19 +29,6 @@ buildscript {
}
}
subprojects {
afterEvaluate {
android {
compileSdkVersion rootProject.ext.compileSdkVersion
buildToolsVersion rootProject.ext.buildToolsVersion
defaultConfig {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
}
}
}
}
allprojects {
repositories {
google()

View file

@ -15,13 +15,6 @@ export function connection(isOnline) {
};
}
export function setStatusBarHeight(height = 20) {
return {
type: DeviceTypes.STATUSBAR_HEIGHT_CHANGED,
data: height,
};
}
export function setDeviceDimensions(height, width) {
return {
type: DeviceTypes.DEVICE_DIMENSIONS_CHANGED,
@ -51,5 +44,4 @@ export default {
setDeviceDimensions,
setDeviceOrientation,
setDeviceAsTablet,
setStatusBarHeight,
};

View file

@ -36,7 +36,7 @@ import {lastChannelIdForTeam, loadSidebarDirectMessagesProfiles} from '@actions/
import {getPosts, getPostsBefore, getPostsSince, loadUnreadChannelPosts} from '@actions/views/post';
import {INSERT_TO_COMMENT, INSERT_TO_DRAFT} from '@constants/post_draft';
import {getChannelReachable} from '@selectors/channel';
import telemetry from '@telemetry';
import telemetry, {PERF_MARKERS} from '@telemetry';
import {isDirectChannelVisible, isGroupChannelVisible, getChannelSinceValue, privateChannelJoinPrompt} from '@utils/channels';
import {isPendingPost} from '@utils/general';
import {fetchAppBindings} from '@mm-redux/actions/apps';
@ -194,6 +194,14 @@ export function handleSelectChannel(channelId) {
const member = myMembers[channelId];
if (channel) {
let markerExtra;
if (channel.display_name) {
markerExtra = `Channel: ${channel.display_name}`;
} else {
markerExtra = `Channel: ${channel.type === General.DM_CHANNEL ? 'Direct Channel' : channel.name}`;
}
telemetry.start([PERF_MARKERS.CHANNEL_RENDER], Date.now(), [markerExtra]);
dispatch(loadPostsIfNecessaryWithRetry(channelId));
let previousChannelId = null;
@ -531,12 +539,6 @@ export function leaveChannel(channel, reset = false) {
}
export function setChannelLoading(loading = true) {
if (loading) {
telemetry.start(['channel:loading']);
} else {
telemetry.end(['channel:loading']);
}
return {
type: ViewTypes.SET_CHANNEL_LOADER,
loading,
@ -585,9 +587,6 @@ export function increasePostVisibility(channelId, postId) {
return true;
}
telemetry.reset();
telemetry.start(['posts:loading']);
dispatch({
type: ViewTypes.LOADING_POSTS,
data: true,
@ -618,8 +617,6 @@ export function increasePostVisibility(channelId, postId) {
}
dispatch(batchActions(actions, 'BATCH_LOAD_MORE_POSTS'));
telemetry.end(['posts:loading']);
telemetry.save();
return hasMorePost;
};

View file

@ -1,10 +0,0 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {ViewTypes} from 'app/constants';
export function setLastUpgradeCheck() {
return {
type: ViewTypes.SET_LAST_UPGRADE_CHECK,
};
}

View file

@ -4,7 +4,6 @@
import {batchActions} from 'redux-batched-actions';
import {NavigationTypes, ViewTypes} from '@constants';
import {analytics} from '@init/analytics.ts';
import {ChannelTypes, GeneralTypes, TeamTypes} from '@mm-redux/action_types';
import {fetchMyChannelsAndMembers, getChannelAndMyMember} from '@mm-redux/actions/channels';
import {getDataRetentionPolicy} from '@mm-redux/actions/general';
@ -180,14 +179,6 @@ export function createPostForNotificationReply(post) {
};
}
export function recordLoadTime(screenName, category) {
return async (dispatch, getState) => {
const {currentUserId} = getState().entities.users;
analytics.recordTime(screenName, category, currentUserId);
};
}
export function setDeepLinkURL(url) {
return {
type: ViewTypes.SET_DEEP_LINK_URL,

View file

@ -17,6 +17,7 @@ import CompassIcon from '@components/compass_icon';
import ProfilePicture from '@components/profile_picture';
import {BotTag, GuestTag} from '@components/tag';
import TouchableWithFeedback from '@components/touchable_with_feedback';
import telemetry, {PERF_MARKERS} from '@telemetry';
import {preventDoubleTap} from '@utils/tap';
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
import {t} from '@utils/i18n';
@ -27,6 +28,7 @@ class ChannelIntro extends PureComponent {
creator: PropTypes.object,
currentChannel: PropTypes.object.isRequired,
currentChannelMembers: PropTypes.array.isRequired,
emptyChannel: PropTypes.bool,
intl: intlShape.isRequired,
theme: PropTypes.object.isRequired,
teammateNameDisplay: PropTypes.string.isRequired,
@ -36,6 +38,12 @@ class ChannelIntro extends PureComponent {
currentChannelMembers: [],
};
componentDidMount() {
if (this.props.emptyChannel) {
telemetry.end([PERF_MARKERS.CHANNEL_RENDER]);
}
}
goToUserProfile = async (userId) => {
const {intl, theme} = this.props;
const screen = 'UserProfile';

View file

@ -1,265 +0,0 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React, {PureComponent} from 'react';
import PropTypes from 'prop-types';
import {
Alert,
Animated,
TouchableOpacity,
View,
} from 'react-native';
import {intlShape} from 'react-intl';
import CompassIcon from '@components/compass_icon';
import FormattedText from '@components/formatted_text';
import {DeviceTypes} from '@constants';
import {checkUpgradeType, isUpgradeAvailable} from '@utils/client_upgrade';
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
import {tryOpenURL} from '@utils/url';
import {showModal, dismissModal} from '@actions/navigation';
const {View: AnimatedView} = Animated;
const UPDATE_TIMEOUT = 60000;
export default class ClientUpgradeListener extends PureComponent {
static propTypes = {
actions: PropTypes.shape({
logError: PropTypes.func.isRequired,
setLastUpgradeCheck: PropTypes.func.isRequired,
}).isRequired,
currentVersion: PropTypes.string,
downloadLink: PropTypes.string,
forceUpgrade: PropTypes.bool,
isLandscape: PropTypes.bool,
lastUpgradeCheck: PropTypes.number,
latestVersion: PropTypes.string,
minVersion: PropTypes.string,
theme: PropTypes.object.isRequired,
};
static contextTypes = {
intl: intlShape,
};
constructor(props) {
super(props);
CompassIcon.getImageSource('close', 24, this.props.theme.sidebarHeaderTextColor).then((source) => {
this.closeButton = source;
});
this.state = {
top: new Animated.Value(-100),
};
}
componentDidMount() {
const {forceUpgrade, isLandscape, lastUpgradeCheck, latestVersion, minVersion} = this.props;
if (forceUpgrade || Date.now() - lastUpgradeCheck > UPDATE_TIMEOUT) {
this.checkUpgrade(minVersion, latestVersion, isLandscape);
}
}
setTop(top) {
this.setState({top});
}
componentDidUpdate(prevProps) {
const {forceUpgrade, latestVersion, minVersion} = prevProps;
const {latestVersion: nextLatestVersion, minVersion: nextMinVersion, lastUpgradeCheck} = this.props;
const versionMismatch = latestVersion !== nextLatestVersion || minVersion !== nextMinVersion;
if (versionMismatch && (forceUpgrade || Date.now() - lastUpgradeCheck > UPDATE_TIMEOUT)) {
this.checkUpgrade(minVersion, latestVersion, this.props.isLandscape);
} else if (prevProps.isLandscape !== this.props.isLandscape &&
isUpgradeAvailable(this.state.upgradeType) && DeviceTypes.IS_IPHONE_WITH_INSETS) {
const newTop = this.props.isLandscape ? 45 : 100;
this.setTop(new Animated.Value(newTop));
}
}
checkUpgrade = (minVersion, latestVersion, isLandscape) => {
const {actions, currentVersion} = this.props;
const upgradeType = checkUpgradeType(currentVersion, minVersion, latestVersion, actions.logError);
this.setState({upgradeType});
if (!isUpgradeAvailable(upgradeType)) {
return;
}
setTimeout(() => {
this.toggleUpgradeMessage(true, isLandscape);
}, 500);
actions.setLastUpgradeCheck();
};
toggleUpgradeMessage = (show = true, isLandscape) => {
let toValue = -100;
if (show) {
if (DeviceTypes.IS_IPHONE_WITH_INSETS && isLandscape) {
toValue = 45;
} else {
toValue = DeviceTypes.IS_IPHONE_WITH_INSETS ? 100 : 75;
}
}
Animated.timing(this.state.top, {
toValue,
duration: 300,
}).start();
};
handleDismiss = () => {
this.toggleUpgradeMessage(false);
};
handleDownload = () => {
const {downloadLink} = this.props;
const {intl} = this.context;
const onError = () => {
Alert.alert(
intl.formatMessage({
id: 'mobile.client_upgrade.download_error.title',
defaultMessage: 'Upgrade Error',
}),
intl.formatMessage({
id: 'mobile.client_upgrade.download_error.message',
defaultMessage: 'An error occurred while trying to open the download link.',
}),
);
};
tryOpenURL(downloadLink, onError);
this.toggleUpgradeMessage(false);
};
handleLearnMore = () => {
const {intl} = this.context;
dismissModal();
const screen = 'ClientUpgrade';
const title = intl.formatMessage({id: 'mobile.client_upgrade', defaultMessage: 'Upgrade App'});
const passProps = {
upgradeType: this.state.upgradeType,
};
const options = {
topBar: {
leftButtons: [{
id: 'close-upgrade',
icon: this.closeButton,
}],
},
};
showModal(screen, title, passProps, options);
this.toggleUpgradeMessage(false);
};
render() {
if (!isUpgradeAvailable(this.state.upgradeType)) {
return null;
}
const {forceUpgrade, theme} = this.props;
const styles = getStyleSheet(theme);
return (
<AnimatedView
style={[styles.wrapper, {top: this.state.top}]}
>
<View style={styles.container}>
<View style={styles.message}>
<FormattedText
id='mobile.client_upgrade.listener.message'
defaultMessage='A client upgrade is available!'
style={styles.messageText}
/>
</View>
<View style={styles.bottom}>
<TouchableOpacity onPress={this.handleDownload}>
<FormattedText
style={styles.button}
id='mobile.client_upgrade.listener.upgrade_button'
defaultMessage='Upgrade'
/>
</TouchableOpacity>
<TouchableOpacity onPress={this.handleLearnMore}>
<FormattedText
style={styles.button}
id='mobile.client_upgrade.listener.learn_more_button'
defaultMessage='Learn More'
/>
</TouchableOpacity>
{!forceUpgrade &&
<TouchableOpacity onPress={this.handleDismiss}>
<FormattedText
style={styles.button}
id='mobile.client_upgrade.listener.dismiss_button'
defaultMessage='Dismiss'
/>
</TouchableOpacity>
}
</View>
</View>
</AnimatedView>
);
}
}
const getStyleSheet = makeStyleSheetFromTheme((theme) => {
return {
bottom: {
flexDirection: 'row',
justifyContent: 'space-around',
borderTopColor: changeOpacity(theme.centerChannelColor, 0.2),
backgroundColor: changeOpacity(theme.centerChannelColor, 0.06),
borderTopWidth: 1,
},
button: {
color: theme.linkColor,
fontSize: 13,
paddingHorizontal: 5,
paddingVertical: 5,
},
container: {
flex: 1,
backgroundColor: changeOpacity(theme.centerChannelBg, 0.8),
borderRadius: 5,
},
message: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
messageText: {
fontSize: 16,
color: changeOpacity(theme.centerChannelColor, 0.8),
fontWeight: '600',
},
wrapper: {
position: 'absolute',
elevation: 5,
left: 30,
right: 30,
height: 75,
backgroundColor: 'white',
borderColor: changeOpacity(theme.centerChannelColor, 0.2),
borderWidth: 2,
borderRadius: 5,
shadowColor: theme.centerChannelColor,
shadowOffset: {
width: 0,
height: 3,
},
shadowOpacity: 0.2,
shadowRadius: 2,
},
};
});

View file

@ -1,39 +0,0 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import {logError} from '@mm-redux/actions/errors';
import {getTheme} from '@mm-redux/selectors/entities/preferences';
import {setLastUpgradeCheck} from 'app/actions/views/client_upgrade';
import getClientUpgrade from 'app/selectors/client_upgrade';
import {isLandscape} from 'app/selectors/device';
import ClientUpgradeListener from './client_upgrade_listener';
function mapStateToProps(state) {
const {currentVersion, downloadLink, forceUpgrade, latestVersion, minVersion} = getClientUpgrade(state);
return {
currentVersion,
downloadLink,
forceUpgrade,
isLandscape: isLandscape(state),
lastUpgradeCheck: state.views.clientUpgrade.lastUpdateCheck,
latestVersion,
minVersion,
theme: getTheme(state),
};
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators({
logError,
setLastUpgradeCheck,
}, dispatch),
};
}
export default connect(mapStateToProps, mapDispatchToProps)(ClientUpgradeListener);

View file

@ -25,8 +25,6 @@ import {preventDoubleTap} from '@utils/tap';
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
import {showModalOverCurrentContext} from '@actions/navigation';
import telemetry from '@telemetry';
import {renderSystemMessage} from './system_message_helpers';
let FileAttachmentList;
@ -105,18 +103,6 @@ export default class PostBody extends PureComponent {
isLongPost: false,
};
logTelemetry = () => {
telemetry.end([
'channel:switch_initial',
'channel:switch_loaded',
'post_list:permalink',
'post_list:thread',
'team:switch',
'start:overall',
]);
telemetry.save();
}
measurePost = (event) => {
const {height} = event.nativeEvent.layout;
const {showLongPost} = this.props;
@ -126,10 +112,6 @@ export default class PostBody extends PureComponent {
isLongPost: height >= this.state.maxHeight,
});
}
if (this.props.isLastPost) {
this.logTelemetry();
}
};
openLongPost = preventDoubleTap(() => {
@ -363,6 +345,7 @@ export default class PostBody extends PureComponent {
const messageStyles = {messageStyle, textStyles};
const intl = this.context.intl;
const systemMessage = renderSystemMessage(this.props, messageStyles, intl);
if (systemMessage) {
return systemMessage;
}

View file

@ -6,18 +6,17 @@ import PropTypes from 'prop-types';
import {Alert, DeviceEventEmitter, FlatList, Platform, RefreshControl, StyleSheet} from 'react-native';
import {intlShape} from 'react-intl';
import CombinedUserActivityPost from '@components/combined_user_activity_post';
import Post from '@components/post';
import {DeepLinkTypes, ListTypes, NavigationTypes} from '@constants';
import {Posts} from '@mm-redux/constants';
import EventEmitter from '@mm-redux/utils/event_emitter';
import * as PostListUtils from '@mm-redux/utils/post_list';
import telemetry, {PERF_MARKERS} from '@telemetry';
import {errorBadChannel} from '@utils/draft';
import CombinedUserActivityPost from 'app/components/combined_user_activity_post';
import Post from 'app/components/post';
import {DeepLinkTypes, ListTypes, NavigationTypes} from '@constants';
import {makeExtraData} from '@utils/list_view';
import {matchDeepLink, PERMALINK_GENERIC_TEAM_NAME_REDIRECT} from '@utils/url';
import mattermostManaged from 'app/mattermost_managed';
import {makeExtraData} from 'app/utils/list_view';
import {matchDeepLink, PERMALINK_GENERIC_TEAM_NAME_REDIRECT} from 'app/utils/url';
import telemetry from 'app/telemetry';
import DateHeader from './date_header';
import NewMessagesDivider from './new_messages_divider';
@ -98,6 +97,7 @@ export default class PostList extends PureComponent {
this.shouldScrollToBottom = false;
this.makeExtraData = makeExtraData();
this.flatListRef = React.createRef();
this.initialRender = false;
}
componentDidMount() {
@ -215,13 +215,16 @@ export default class PostList extends PureComponent {
handleLayout = (event) => {
const {height} = event.nativeEvent.layout;
if (!this.initialRender && this.props.postIds.length) {
telemetry.end([PERF_MARKERS.CHANNEL_RENDER]);
this.initialRender = true;
}
if (this.postListHeight !== height) {
this.postListHeight = height;
}
};
handlePermalinkPress = (postId, teamName) => {
telemetry.start(['post_list:permalink']);
const {showPermalink} = this.props.actions;
showPermalink(this.context.intl, teamName, postId);
@ -362,6 +365,7 @@ export default class PostList extends PureComponent {
postId={postId}
highlight={highlightPostId === postId}
isLastPost={lastPostIndex === index}
hey={index}
{...postProps}
/>
);
@ -370,6 +374,7 @@ export default class PostList extends PureComponent {
resetPostList = () => {
this.contentOffsetY = 0;
this.hasDoneInitialScroll = false;
this.initialRender = false;
if (this.scrollAfterInteraction) {
this.scrollAfterInteraction.cancel();

View file

@ -18,8 +18,6 @@ import {
} from 'react-native';
import PropTypes from 'prop-types';
import telemetry from 'app/telemetry';
const MIN_SWIPE_DISTANCE = 3;
const VX_MAX = 0.1;
@ -307,8 +305,6 @@ export default class DrawerLayout extends Component {
}).start(() => {
this.handleOpenValueChanged({value: 1});
if (this.props.onDrawerOpen) {
telemetry.end(['channel:open_drawer']);
telemetry.save();
this.props.onDrawerOpen();
}
@ -328,7 +324,6 @@ export default class DrawerLayout extends Component {
}).start(() => {
this.handleOpenValueChanged({value: 0});
if (this.props.onDrawerClose) {
telemetry.end(['channel:close_drawer']);
this.props.onDrawerClose();
this.canClose = true;
}

View file

@ -12,28 +12,9 @@ import {getCurrentUser} from '@mm-redux/selectors/entities/users';
import {setChannelDisplayName, handleSelectChannel} from 'app/actions/views/channel';
import {makeDirectChannel} from 'app/actions/views/more_dms';
import telemetry from 'app/telemetry';
import MainSidebar from './main_sidebar';
export function logChannelSwitch(channelId, currentChannelId) {
return (dispatch, getState) => {
if (channelId === currentChannelId) {
return;
}
const metrics = [];
if (getState().entities.posts.postsInChannel[channelId]) {
metrics.push('channel:switch_loaded');
} else {
metrics.push('channel:switch_initial');
}
telemetry.reset();
telemetry.start(metrics);
};
}
function mapStateToProps(state) {
const currentUser = getCurrentUser(state);
@ -51,7 +32,6 @@ function mapDispatchToProps(dispatch) {
actions: bindActionCreators({
getTeams,
joinChannel,
logChannelSwitch,
makeDirectChannel,
setChannelDisplayName,
handleSelectChannel,

View file

@ -15,7 +15,6 @@ describe('MainSidebar', () => {
const baseProps = {
actions: {
getTeams: jest.fn(),
logChannelSwitch: jest.fn(),
makeDirectChannel: jest.fn(),
setChannelDisplayName: jest.fn(),
setChannelLoading: jest.fn(),

View file

@ -15,8 +15,6 @@ import {NavigationTypes, WebsocketEvents} from '@constants';
import {General} from '@mm-redux/constants';
import EventEmitter from '@mm-redux/utils/event_emitter';
import {t} from '@utils/i18n';
import tracker from '@utils/time_tracker';
import telemetry from '@telemetry/';
import ChannelsList from './channels_list';
import DrawerSwiper from './drawer_swiper';
@ -28,7 +26,6 @@ export default class MainSidebarBase extends Component {
getTeams: PropTypes.func.isRequired,
handleSelectChannel: PropTypes.func,
joinChannel: PropTypes.func.isRequired,
logChannelSwitch: PropTypes.func.isRequired,
makeDirectChannel: PropTypes.func.isRequired,
setChannelDisplayName: PropTypes.func.isRequired,
}).isRequired,
@ -267,10 +264,9 @@ export default class MainSidebarBase extends Component {
};
selectChannel = (channel, currentChannelId, closeDrawer = true) => {
const {logChannelSwitch, handleSelectChannel} = this.props.actions;
const {handleSelectChannel} = this.props.actions;
if (closeDrawer) {
telemetry.start(['channel:close_drawer']);
this.closeMainSidebar();
}
@ -278,10 +274,6 @@ export default class MainSidebarBase extends Component {
return;
}
logChannelSwitch(channel.id, currentChannelId);
tracker.channelSwitch = Date.now();
if (!channel) {
const utils = require('app/utils/general');
const intl = this.getIntl();

View file

@ -20,11 +20,9 @@ import CompassIcon from '@components/compass_icon';
import FormattedText from '@components/formatted_text';
import {DeviceTypes, ListTypes, ViewTypes} from '@constants';
import {getCurrentServerUrl} from '@init/credentials';
import telemetry from '@telemetry';
import {preventDoubleTap} from '@utils/tap';
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
import {removeProtocol} from '@utils/url';
import tracker from '@utils/time_tracker';
import TeamsListItem from './teams_list_item';
@ -70,15 +68,9 @@ export default class TeamsList extends PureComponent {
selectTeam = (teamId) => {
const {actions, closeMainSidebar, currentTeamId} = this.props;
if (teamId !== currentTeamId) {
telemetry.reset();
telemetry.start(['team:switch']);
}
StatusBar.setHidden(false, 'slide');
requestAnimationFrame(() => {
if (teamId !== currentTeamId) {
tracker.teamSwitch = Date.now();
actions.handleTeamChange(teamId);
}
});

View file

@ -11,7 +11,6 @@ const deviceTypes = keyMirror({
DEVICE_DIMENSIONS_CHANGED: null,
DEVICE_TYPE_CHANGED: null,
DEVICE_ORIENTATION_CHANGED: null,
STATUSBAR_HEIGHT_CHANGED: null,
});
const isPhoneWithInsets = Platform.OS === 'ios' && DeviceInfo.hasNotch();

View file

@ -8,7 +8,7 @@ import DeviceTypes from './device';
import ListTypes from './list';
import NavigationTypes from './navigation';
import Types from './types';
import ViewTypes, {UpgradeTypes} from './view';
import ViewTypes from './view';
import WebsocketEvents from './websocket';
export {
@ -18,7 +18,6 @@ export {
DeviceTypes,
ListTypes,
NavigationTypes,
UpgradeTypes,
Types,
ViewTypes,
WebsocketEvents,

View file

@ -9,13 +9,6 @@ import keyMirror from '@mm-redux/utils/key_mirror';
// The iPhone 11 and iPhone 11 Pro Max have a navbar height of 44 and iPhone 11 Pro has 32
const IPHONE_11_LANDSCAPE_HEIGHT = ['iPhone 11', 'iPhone 11 Pro Max'];
export const UpgradeTypes = {
CAN_UPGRADE: 'can_upgrade',
MUST_UPGRADE: 'must_upgrade',
NO_UPGRADE: 'no_upgrade',
IS_BETA: 'is_beta',
};
export const SidebarSectionTypes = {
UNREADS: 'unreads',
FAVORITE: 'favorite',
@ -89,8 +82,6 @@ const ViewTypes = keyMirror({
RECEIVED_POSTS_FOR_CHANNEL_AT_TIME: null,
SET_LAST_UPGRADE_CHECK: null,
ADD_RECENT_EMOJI: null,
ADD_RECENT_EMOJI_ARRAY: null,
ANNOUNCEMENT_BANNER: null,

View file

@ -6,7 +6,6 @@ import {Dimensions} from 'react-native';
import LocalConfig from '@assets/config.json';
import {Config} from '@mm-redux/types/config';
import tracker from '@utils/time_tracker';
import {isSystemAdmin} from '@mm-redux/utils/user_utils';
type RudderClient = {
@ -103,24 +102,6 @@ class Analytics {
this.analytics.track(event, properties, options);
}
recordTime(screenName: string, category: string, userId: string) {
if (this.analytics) {
const track: Record<string, number> = tracker;
const startTime: number = track[category];
track[category] = 0;
this.analytics.screen(
screenName, {
userId: this.diagnosticId,
context: this.context,
properties: {
user_actual_id: userId,
time: Date.now() - startTime,
},
},
);
}
}
trackAPI(event: string, props?: any) {
this.trackEvent('api', event, props);
}

View file

@ -1,26 +1,24 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {Alert, AppState, Dimensions, Linking, NativeModules, Platform} from 'react-native';
import {AppState, Dimensions, Linking, Platform} from 'react-native';
import AsyncStorage from '@react-native-community/async-storage';
import CookieManager from 'react-native-cookies';
import DeviceInfo from 'react-native-device-info';
import {getLocales} from 'react-native-localize';
import RNFetchBlob from 'rn-fetch-blob';
import semver from 'semver/preload';
import {setDeviceDimensions, setDeviceOrientation, setDeviceAsTablet, setStatusBarHeight} from '@actions/device';
import {setDeviceDimensions, setDeviceOrientation, setDeviceAsTablet} from '@actions/device';
import {selectDefaultChannel} from '@actions/views/channel';
import {showOverlay} from '@actions/navigation';
import {loadConfigAndLicense, setDeepLinkURL, startDataCleanup} from '@actions/views/root';
import {loadMe, logout} from '@actions/views/user';
import LocalConfig from '@assets/config';
import {NavigationTypes, ViewTypes} from '@constants';
import {getTranslations, resetMomentLocale} from '@i18n';
import {resetMomentLocale} from '@i18n';
import {setupPermanentSidebar} from '@init/device';
import PushNotifications from '@init/push_notifications';
import {setAppState, setServerVersion} from '@mm-redux/actions/general';
import {getTeams} from '@mm-redux/actions/teams';
import {autoUpdateTimezone} from '@mm-redux/actions/timezone';
import {close as closeWebSocket} from '@actions/websocket';
import {Client4} from '@client/rest';
@ -31,10 +29,8 @@ import {getCurrentUser, getUser} from '@mm-redux/selectors/entities/users';
import {isTimezoneEnabled} from '@mm-redux/selectors/entities/timezone';
import EventEmitter from '@mm-redux/utils/event_emitter';
import {isMinimumServerVersion} from '@mm-redux/utils/helpers';
import {getCurrentLocale} from '@selectors/i18n';
import initialState from '@store/initial_state';
import Store from '@store/store';
import {t} from '@utils/i18n';
import {deleteFileCache} from '@utils/file';
import {getDeviceTimezone} from '@utils/timezone';
@ -45,7 +41,6 @@ import {getAppCredentials, removeAppCredentials} from './credentials';
import emmProvider from './emm_provider';
import {analytics} from '@init/analytics.ts';
const {StatusBarManager} = NativeModules;
const PROMPT_IN_APP_PIN_CODE_AFTER = 5 * 1000;
class GlobalEventHandler {
@ -100,17 +95,6 @@ class GlobalEventHandler {
const window = Dimensions.get('window');
this.onOrientationChange({window});
this.StatusBarSizeIOS = require('react-native-status-bar-size');
if (Platform.OS === 'ios') {
this.StatusBarSizeIOS.addEventListener('willChange', this.onStatusBarHeightChange);
StatusBarManager.getHeight(
(data) => {
this.onStatusBarHeightChange(data.height);
},
);
}
this.JavascriptAndNativeErrorHandler = require('app/utils/error_handling').default;
this.JavascriptAndNativeErrorHandler.initializeErrorHandling(Store.redux);
@ -259,19 +243,10 @@ class GlobalEventHandler {
const user = getUser(state, currentUserId);
await dispatch(loadConfigAndLicense());
await dispatch(getTeams());
await dispatch(loadMe(user));
const window = Dimensions.get('window');
this.onOrientationChange({window});
if (Platform.OS === 'ios') {
StatusBarManager.getHeight(
(data) => {
this.onStatusBarHeightChange(data.height);
},
);
}
};
onServerConfigChanged = (config) => {
@ -285,32 +260,12 @@ class GlobalEventHandler {
onServerVersionChanged = async (serverVersion) => {
const {dispatch, getState} = Store.redux;
const state = getState();
const match = serverVersion && serverVersion.match(/^[0-9]*.[0-9]*.[0-9]*(-[a-zA-Z0-9.-]*)?/g);
const version = match && match[0];
const locale = getCurrentLocale(state);
const translations = getTranslations(locale);
if (serverVersion) {
if (semver.valid(version) && semver.lt(version, LocalConfig.MinServerVersion)) {
Alert.alert(
translations[t('mobile.server_upgrade.title')],
translations[t('mobile.server_upgrade.description')],
[{
text: translations[t('mobile.server_upgrade.button')],
onPress: this.serverUpgradeNeeded,
}],
{cancelable: false},
);
} else if (state.entities.users && state.entities.users.currentUserId) {
dispatch(setServerVersion(serverVersion));
dispatch(loadConfigAndLicense());
}
if (serverVersion && state.entities.users && state.entities.users.currentUserId) {
dispatch(setServerVersion(serverVersion));
dispatch(loadConfigAndLicense());
}
};
onStatusBarHeightChange = (nextStatusBarHeight) => {
Store.redux.dispatch(setStatusBarHeight(nextStatusBarHeight));
};
onSwitchToDefaultChannel = (teamId) => {
Store.redux.dispatch(selectDefaultChannel(teamId));
};

View file

@ -1,12 +1,10 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {Alert} from 'react-native';
import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';
import semver from 'semver/preload';
import {MinServerVersion} from '@assets/config';
import * as I18n from '@i18n';
import PushNotification from '@init/push_notifications';
import EventEmitter from '@mm-redux/utils/event_emitter';
@ -29,10 +27,6 @@ jest.mock('@utils/error_handling', () => ({
},
}));
jest.mock('react-native-status-bar-size', () => ({
addEventListener: jest.fn(),
}));
jest.mock('@mm-redux/actions/general', () => ({
setAppState: jest.fn(),
setServerVersion: jest.fn().mockReturnValue('setServerVersion'),
@ -149,7 +143,7 @@ describe('GlobalEventHandler', () => {
jest.clearAllMocks();
});
const minVersion = semver.parse(MinServerVersion);
const minVersion = semver.parse('5.31.0');
const currentUserId = 'current-user-id';
Store.redux.getState = jest.fn().mockReturnValue({
entities: {
@ -165,13 +159,11 @@ describe('GlobalEventHandler', () => {
const dispatch = jest.spyOn(Store.redux, 'dispatch');
const configureAnalytics = jest.spyOn(GlobalEventHandler, 'configureAnalytics');
const alert = jest.spyOn(Alert, 'alert');
it('should dispatch on invalid version with currentUserId', async () => {
const invalidVersion = 'a.b.c';
await GlobalEventHandler.onServerVersionChanged(invalidVersion);
expect(alert).not.toHaveBeenCalled();
expect(dispatch).toHaveBeenCalledTimes(2);
expect(dispatch).toHaveBeenCalledWith('setServerVersion');
expect(dispatch).toHaveBeenCalledWith('loadConfigAndLicense');
@ -180,41 +172,28 @@ describe('GlobalEventHandler', () => {
it('should dispatch on gte min server version with currentUserId', async () => {
let version = minVersion.version;
await GlobalEventHandler.onServerVersionChanged(version);
expect(alert).not.toHaveBeenCalled();
expect(dispatch).toHaveBeenCalledTimes(2);
expect(dispatch).toHaveBeenCalledWith('setServerVersion');
expect(dispatch).toHaveBeenCalledWith('loadConfigAndLicense');
version = semver.coerce(minVersion.major + 1).version;
await GlobalEventHandler.onServerVersionChanged(version);
expect(alert).not.toHaveBeenCalled();
expect(dispatch).toHaveBeenCalledTimes(4);
});
it('should alert on lt min server version', async () => {
const version = semver.coerce(minVersion.major - 1).version;
await GlobalEventHandler.onServerVersionChanged(version);
expect(alert).toHaveBeenCalled();
expect(dispatch).not.toHaveBeenCalled();
expect(configureAnalytics).not.toHaveBeenCalled();
});
it('should not alert nor dispatch on empty, null, undefined server version', async () => {
it('should not dispatch on empty, null, undefined server version', async () => {
let version;
await GlobalEventHandler.onServerVersionChanged(version);
expect(alert).not.toHaveBeenCalled();
expect(dispatch).not.toHaveBeenCalled();
expect(configureAnalytics).not.toHaveBeenCalled();
version = '';
await GlobalEventHandler.onServerVersionChanged(version);
expect(alert).not.toHaveBeenCalled();
expect(dispatch).not.toHaveBeenCalled();
expect(configureAnalytics).not.toHaveBeenCalled();
version = null;
await GlobalEventHandler.onServerVersionChanged(version);
expect(alert).not.toHaveBeenCalled();
expect(dispatch).not.toHaveBeenCalled();
expect(configureAnalytics).not.toHaveBeenCalled();
});

View file

@ -10,7 +10,6 @@ import EventEmitter from '@mm-redux/utils/event_emitter';
import {resetToChannel, resetToSelectServer} from '@actions/navigation';
import {setDeepLinkURL} from '@actions/views/root';
import {loadMe, logout} from '@actions/views/user';
import telemetry from 'app/telemetry';
import {NavigationTypes} from '@constants';
import {getAppCredentials} from '@init/credentials';
import emmProvider from '@init/emm_provider';
@ -23,6 +22,7 @@ import EphemeralStore from '@store/ephemeral_store';
import getStorage from '@store/mmkv_adapter';
import Store from '@store/store';
import {waitForHydration} from '@store/utils';
import telemetry from '@telemetry';
import {validatePreviousVersion} from '@utils/general';
import {captureJSException} from '@utils/sentry';
@ -49,11 +49,6 @@ const init = async () => {
};
const launchApp = (credentials) => {
telemetry.start([
'start:select_server_screen',
'start:channel_screen',
]);
const store = Store.redux;
waitForHydration(store, async () => {
Linking.getInitialURL().then((url) => {
@ -70,7 +65,7 @@ const launchApp = (credentials) => {
await globalEventHandler.configureAnalytics();
// eslint-disable-next-line no-console
console.log('Launch app in Channel screen');
resetToChannel({skipMetrics: true});
resetToChannel();
} else {
const error = new Error(`Previous app version "${previousVersion}" is invalid.`);
captureJSException(error, false, store);
@ -79,9 +74,10 @@ const launchApp = (credentials) => {
} else {
resetToSelectServer(emmProvider.allowOtherServers);
}
telemetry.startSinceLaunch(credentials ? 'Launch on Channel Screen' : 'Launch on Server Screen');
});
telemetry.startSinceLaunch(['start:splash_screen']);
EphemeralStore.appStarted = true;
};

View file

@ -12,7 +12,6 @@ import {GetStateFunc, DispatchFunc, ActionFunc, batchActions} from '@mm-redux/ty
import {logError} from './errors';
import {loadRolesIfNeeded} from './roles';
import {loadMe} from './users';
import {bindClientFunc, forceLogoutIfNecessary, FormattedError} from './helpers';
export function getPing(): ActionFunc {
@ -139,15 +138,6 @@ export function setServerVersion(serverVersion: string): ActionFunc {
};
}
export function setStoreFromLocalData(data: { token: string; url: string }): ActionFunc {
return async (dispatch: DispatchFunc, getState) => {
Client4.setToken(data.token);
Client4.setUrl(data.url);
return loadMe()(dispatch, getState);
};
}
export function getSupportedTimezones() {
return bindClientFunc({
clientFunc: Client4.getTimezones,
@ -195,7 +185,6 @@ export default {
setAppState,
setDeviceToken,
setServerVersion,
setStoreFromLocalData,
setUrl,
getRedirectLocation,
};

View file

@ -8,7 +8,7 @@ import {General} from '../constants';
import {UserTypes, TeamTypes} from '@mm-redux/action_types';
import {getAllCustomEmojis} from './emojis';
import {getClientConfig, setServerVersion} from './general';
import {getMyTeams, getMyTeamMembers, getMyTeamUnreads} from './teams';
import {getMyTeams} from './teams';
import {loadRolesIfNeeded} from './roles';
import {getUserIdFromChannelName, isDirectChannel, isDirectChannelVisible, isGroupChannel, isGroupChannelVisible} from '@mm-redux/utils/channel_utils';
import {removeUserFromList} from '@mm-redux/utils/user_utils';
@ -194,47 +194,6 @@ function completeLogin(data: UserProfile): ActionFunc {
};
}
export function loadMe(): ActionFunc {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => {
const state = getState();
const config = getConfig(state);
const deviceId = state.entities.general.deviceToken;
if (deviceId) {
Client4.attachDevice(deviceId);
}
const promises = [
dispatch(getMe()),
dispatch(getMyPreferences()),
dispatch(getMyTeams()),
dispatch(getMyTeamMembers()),
dispatch(getMyTeamUnreads()),
];
// Sometimes the server version is set in one or the other
const serverVersion = Client4.getServerVersion() || getState().entities.general.serverVersion;
dispatch(setServerVersion(serverVersion));
if (!isMinimumServerVersion(serverVersion, 4, 7) && config.EnableCustomEmoji === 'true') {
dispatch(getAllCustomEmojis());
}
await Promise.all(promises);
const {currentUserId} = getState().entities.users;
const user = getState().entities.users.profiles[currentUserId];
if (currentUserId) {
analytics.setUserId(currentUserId);
}
if (user) {
analytics.setUserRoles(user.roles);
}
return {data: true};
};
}
export function getProfiles(page = 0, perPage: number = General.PROFILE_CHUNK_SIZE, options: any = {}): ActionFunc {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => {
const {currentUserId} = getState().entities.users;

View file

@ -7,12 +7,10 @@ import connection from './connection';
import dimension from './dimension';
import isTablet from './is_tablet';
import orientation from './orientation';
import statusBarHeight from './status_bar';
export default combineReducers({
connection,
dimension,
isTablet,
orientation,
statusBarHeight,
});

View file

@ -1,18 +0,0 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
const initialState = {
lastUpdateCheck: 0,
};
import {ViewTypes} from 'app/constants';
export default function clientUpgrade(state = initialState, action) {
switch (action.type) {
case ViewTypes.SET_LAST_UPGRADE_CHECK:
return {
lastUpdateCheck: Date.now(),
};
default:
return state;
}
}

View file

@ -5,7 +5,6 @@ import {combineReducers} from 'redux';
import announcement from './announcement';
import channel from './channel';
import clientUpgrade from './client_upgrade';
import i18n from './i18n';
import recentEmojis from './recent_emojis';
import root from './root';
@ -20,7 +19,6 @@ import post from './post';
export default combineReducers({
announcement,
channel,
clientUpgrade,
i18n,
recentEmojis,
root,

View file

@ -5,7 +5,6 @@ import React from 'react';
import {StyleSheet, View, BackHandler, ToastAndroid} from 'react-native';
import {openMainSideMenu, openSettingsSideMenu} from '@actions/navigation';
import LocalConfig from '@assets/config';
import AnnouncementBanner from 'app/components/announcement_banner';
import KeyboardLayout from '@components/layout/keyboard_layout';
import InteractiveDialogController from '@components/interactive_dialog_controller';
@ -18,7 +17,7 @@ import EphemeralStore from '@store/ephemeral_store';
import ChannelNavBar from './channel_nav_bar';
import ChannelPostList from './channel_post_list';
import ChannelBase, {ClientUpgradeListener} from './channel_base';
import ChannelBase from './channel_base';
let backPressedCount = 0;
@ -93,7 +92,6 @@ export default class ChannelAndroid extends ChannelBase {
{component}
<NetworkIndicator/>
<AnnouncementBanner/>
{LocalConfig.EnableMobileClientUpgrade && <ClientUpgradeListener/>}
</>
);

View file

@ -5,7 +5,6 @@ import React from 'react';
import {View} from 'react-native';
import {SafeAreaView} from 'react-native-safe-area-context';
import LocalConfig from '@assets/config';
import AnnouncementBanner from 'app/components/announcement_banner';
import Autocomplete from '@components/autocomplete';
import InteractiveDialogController from '@components/interactive_dialog_controller';
@ -18,7 +17,7 @@ import DEVICE from '@constants/device';
import {ACCESSORIES_CONTAINER_NATIVE_ID, CHANNEL_POST_TEXTBOX_CURSOR_CHANGE, CHANNEL_POST_TEXTBOX_VALUE_CHANGE} from '@constants/post_draft';
import {makeStyleSheetFromTheme} from '@utils/theme';
import ChannelBase, {ClientUpgradeListener} from './channel_base';
import ChannelBase from './channel_base';
import ChannelNavBar from './channel_nav_bar';
import ChannelPostList from './channel_post_list';
@ -66,7 +65,6 @@ export default class ChannelIOS extends ChannelBase {
updateNativeScrollView={this.updateNativeScrollView}
registerTypingAnimation={this.registerTypingAnimation}
/>
{LocalConfig.EnableMobileClientUpgrade && <ClientUpgradeListener/>}
</>
);
}

View file

@ -10,19 +10,14 @@ import {General} from '@mm-redux/constants';
import EventEmitter from '@mm-redux/utils/event_emitter';
import {showModal, showModalOverCurrentContext} from '@actions/navigation';
import LocalConfig from '@assets/config';
import {UPDATE_NATIVE_SCROLLVIEW, TYPING_VISIBLE} from '@constants/post_draft';
import CompassIcon from '@components/compass_icon';
import PushNotifications from '@init/push_notifications';
import EphemeralStore from '@store/ephemeral_store';
import telemetry, {PERF_MARKERS} from '@telemetry';
import {unsupportedServer} from '@utils/supported_server';
import {preventDoubleTap} from '@utils/tap';
import {setNavigatorStyles} from '@utils/theme';
import tracker from '@utils/time_tracker';
import PushNotifications from '@init/push_notifications';
import telemetry from 'app/telemetry';
export let ClientUpgradeListener;
export default class ChannelBase extends PureComponent {
static propTypes = {
@ -31,7 +26,6 @@ export default class ChannelBase extends PureComponent {
loadChannelsForTeam: PropTypes.func.isRequired,
selectDefaultTeam: PropTypes.func.isRequired,
selectInitialChannel: PropTypes.func.isRequired,
recordLoadTime: PropTypes.func.isRequired,
}).isRequired,
componentId: PropTypes.string.isRequired,
currentChannelId: PropTypes.string,
@ -43,7 +37,6 @@ export default class ChannelBase extends PureComponent {
teamName: PropTypes.string,
theme: PropTypes.object.isRequired,
showTermsOfService: PropTypes.bool,
skipMetrics: PropTypes.bool,
};
static contextTypes = {
@ -63,8 +56,8 @@ export default class ChannelBase extends PureComponent {
channelsRequestFailed: false,
};
if (LocalConfig.EnableMobileClientUpgrade && !ClientUpgradeListener) {
ClientUpgradeListener = require('app/components/client_upgrade_listener').default;
if (props.currentChannelId) {
telemetry.start([PERF_MARKERS.CHANNEL_RENDER], Date.now(), ['Initial Channel Render']);
}
this.typingAnimations = [];
@ -79,7 +72,6 @@ export default class ChannelBase extends PureComponent {
isSupportedServer,
isSystemAdmin,
showTermsOfService,
skipMetrics,
} = this.props;
EventEmitter.on('leave_team', this.handleLeaveTeam);
@ -99,27 +91,15 @@ export default class ChannelBase extends PureComponent {
});
}
if (tracker.initialLoad && !skipMetrics) {
actions.recordLoadTime('Start time', 'initialLoad');
}
if (showTermsOfService && !disableTermsModal) {
this.showTermsOfServiceModal();
} else if (!isSupportedServer) {
// Only display the Alert if the TOS does not need to show first
unsupportedServer(isSystemAdmin, this.context.intl.formatMessage);
}
if (!skipMetrics) {
telemetry.end(['start:channel_screen']);
}
}
componentDidUpdate(prevProps) {
if (tracker.teamSwitch) {
this.props.actions.recordLoadTime('Switch Team', 'teamSwitch');
}
if (prevProps.isSupportedServer && !this.props.isSupportedServer) {
unsupportedServer(this.props.isSystemAdmin, this.context.intl.formatMessage);
}
@ -150,10 +130,6 @@ export default class ChannelBase extends PureComponent {
this.updateNativeScrollView();
});
}
if (LocalConfig.EnableMobileClientUpgrade && !ClientUpgradeListener) {
ClientUpgradeListener = require('app/components/client_upgrade_listener').default;
}
}
componentWillUnmount() {

View file

@ -25,7 +25,6 @@ describe('ChannelBase', () => {
getChannelStats: jest.fn(),
loadChannelsForTeam: jest.fn(),
markChannelViewedAndRead: jest.fn(),
recordLoadTime: jest.fn(),
selectDefaultTeam: jest.fn(),
selectInitialChannel: jest.fn(),
},

View file

@ -16,7 +16,6 @@ import {preventDoubleTap} from '@utils/tap';
import {makeStyleSheetFromTheme} from '@utils/theme';
import {t} from '@utils/i18n';
import telemetry from '@telemetry';
import {LARGE_BADGE_RIGHT_POSITION, SMALL_BADGE_RIGHT_POSITION, MAX_BADGE_RIGHT_POSITION} from '@constants/view';
export default class MainSidebarDrawerButton extends PureComponent {
@ -56,7 +55,6 @@ export default class MainSidebarDrawerButton extends PureComponent {
}
handlePress = preventDoubleTap(() => {
telemetry.start(['channel:open_drawer']);
this.props.openSidebar();
});

View file

@ -16,9 +16,7 @@ import RetryBarIndicator from '@components/retry_bar_indicator';
import {TYPING_HEIGHT} from '@constants/post_draft';
import EventEmitter from '@mm-redux/utils/event_emitter';
import {getLastPostIndex} from '@mm-redux/utils/post_list';
import tracker from '@utils/time_tracker';
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
import telemetry from '@telemetry';
import {CHANNEL} from '@constants/screen';
let ChannelIntro = null;
@ -31,7 +29,6 @@ export default class ChannelPostList extends PureComponent {
getPostThread: PropTypes.func.isRequired,
increasePostVisibility: PropTypes.func.isRequired,
selectPost: PropTypes.func.isRequired,
recordLoadTime: PropTypes.func.isRequired,
refreshChannelWithRetry: PropTypes.func.isRequired,
setChannelRefreshing: PropTypes.func,
}).isRequired,
@ -70,9 +67,6 @@ export default class ChannelPostList extends PureComponent {
componentDidUpdate(prevProps) {
if (this.props.channelId !== prevProps.channelId) {
this.isLoadingMoreTop = false;
if (tracker.channelSwitch) {
this.props.actions.recordLoadTime('Switch Channel', 'channelSwitch');
}
}
if (!prevProps.postIds?.length && this.props.postIds?.length > 0 && this.props.updateNativeScrollView) {
@ -99,7 +93,6 @@ export default class ChannelPostList extends PureComponent {
}
goToThread = (post) => {
telemetry.start(['post_list:thread']);
const {actions, channelId} = this.props;
const rootId = (post.root_id || post.id);
@ -163,6 +156,7 @@ export default class ChannelPostList extends PureComponent {
return (
<ChannelIntro
channelId={this.props.channelId}
emptyChannel={this.props.postIds.length === 0}
/>
);
};
@ -190,7 +184,7 @@ export default class ChannelPostList extends PureComponent {
theme={theme}
/>
);
} else {
} else if (channelId) {
component = (
<PostList
testID='channel.post_list'

View file

@ -15,7 +15,6 @@ describe('ChannelPostList', () => {
getPostThread: jest.fn(),
increasePostVisibility: jest.fn(),
selectPost: jest.fn(),
recordLoadTime: jest.fn(),
refreshChannelWithRetry: jest.fn(),
},
channelId: 'channel-id',

View file

@ -10,7 +10,6 @@ import {
refreshChannelWithRetry,
} from '@actions/views/channel';
import {getPostThread} from '@actions/views/post';
import {recordLoadTime} from 'app/actions/views/root';
import {Types} from '@constants';
import {selectPost} from '@mm-redux/actions/posts';
import {getPostIdsInCurrentChannel} from '@mm-redux/selectors/entities/posts';
@ -46,7 +45,6 @@ function mapDispatchToProps(dispatch) {
getPostThread,
increasePostVisibility,
selectPost,
recordLoadTime,
refreshChannelWithRetry,
}, dispatch),
};

View file

@ -5,7 +5,6 @@ import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import {loadChannelsForTeam, selectInitialChannel} from '@actions/views/channel';
import {recordLoadTime} from '@actions/views/root';
import {selectDefaultTeam} from '@actions/views/select_team';
import {ViewTypes} from '@constants';
import {getChannelStats} from '@mm-redux/actions/channels';
@ -59,7 +58,6 @@ function mapDispatchToProps(dispatch) {
loadChannelsForTeam,
selectDefaultTeam,
selectInitialChannel,
recordLoadTime,
}, dispatch),
};
}

View file

@ -1,335 +0,0 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React, {PureComponent} from 'react';
import {Navigation} from 'react-native-navigation';
import PropTypes from 'prop-types';
import {
Alert,
Image,
ScrollView,
TouchableOpacity,
View,
} from 'react-native';
import {intlShape} from 'react-intl';
import {SafeAreaView} from 'react-native-safe-area-context';
import {popTopScreen, dismissModal} from '@actions/navigation';
import FormattedText from '@components/formatted_text';
import StatusBar from '@components/status_bar';
import {UpgradeTypes} from '@constants';
import {checkUpgradeType, isUpgradeAvailable} from '@utils/client_upgrade';
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
import {tryOpenURL} from '@utils/url';
export default class ClientUpgrade extends PureComponent {
static propTypes = {
actions: PropTypes.shape({
logError: PropTypes.func.isRequired,
setLastUpgradeCheck: PropTypes.func.isRequired,
}).isRequired,
currentVersion: PropTypes.string,
closeAction: PropTypes.func,
userCheckedForUpgrade: PropTypes.bool,
downloadLink: PropTypes.string.isRequired,
forceUpgrade: PropTypes.bool,
latestVersion: PropTypes.string,
theme: PropTypes.object.isRequired,
upgradeType: PropTypes.string,
};
static contextTypes = {
intl: intlShape,
};
constructor(props) {
super(props);
this.state = {
upgradeType: UpgradeTypes.NO_UPGRADE,
};
}
componentDidMount() {
this.navigationEventListener = Navigation.events().bindComponent(this);
if (this.props.userCheckedForUpgrade) {
this.checkUpgrade(this.props);
}
}
navigationButtonPressed({buttonId}) {
if (buttonId === 'close-upgrade') {
dismissModal();
}
}
checkUpgrade = ({minVersion, latestVersion}) => {
const {actions, currentVersion, downloadLink} = this.props;
// We need at least minVersion or latestVersion and the app downloadlink
if (!(latestVersion || minVersion) || !downloadLink) {
return;
}
const upgradeType = checkUpgradeType(currentVersion, minVersion, latestVersion, actions.logError);
if (upgradeType === UpgradeTypes.NO_UPGRADE) {
return;
}
this.setState({
upgradeType,
});
actions.setLastUpgradeCheck();
}
handleClose = () => {
const {
closeAction,
userCheckedForUpgrade,
} = this.props;
if (closeAction) {
closeAction();
} else if (userCheckedForUpgrade) {
popTopScreen();
} else {
dismissModal();
}
};
handleDownload = () => {
const {downloadLink} = this.props;
const {intl} = this.context;
const onError = () => {
Alert.alert(
intl.formatMessage({
id: 'mobile.client_upgrade.download_error.title',
defaultMessage: 'Upgrade Error',
}),
intl.formatMessage({
id: 'mobile.client_upgrade.download_error.message',
defaultMessage: 'An error occurred while trying to open the download link.',
}),
);
};
tryOpenURL(downloadLink, onError);
};
renderMustUpgrade() {
const {theme} = this.props;
const styles = getStyleFromTheme(theme);
return (
<View style={styles.messageContent}>
<FormattedText
id='mobile.client_upgrade.must_upgrade_title'
defaultMessage='Upgrade Required'
style={styles.messageTitle}
/>
<FormattedText
id='mobile.client_upgrade.must_upgrade_subtitle'
defaultMessage='Please update the app to continue.'
style={styles.messageSubtitle}
/>
</View>
);
}
renderCanUpgrade() {
const {theme} = this.props;
const styles = getStyleFromTheme(theme);
return (
<View style={styles.messageContent}>
<FormattedText
id='mobile.client_upgrade.can_upgrade_title'
defaultMessage='Upgrade Available!'
style={styles.messageTitle}
/>
<FormattedText
id='mobile.client_upgrade.can_upgrade_subtitle'
defaultMessage={'There\'s a new upgrade ready for download.'}
style={styles.messageSubtitle}
/>
</View>
);
}
renderNoUpgrade() {
const {theme} = this.props;
const styles = getStyleFromTheme(theme);
return (
<View style={styles.messageContent}>
<FormattedText
id='mobile.client_upgrade.no_upgrade_title'
defaultMessage='Your App Is Up to Date'
style={styles.messageTitle}
/>
<FormattedText
id='mobile.client_upgrade.no_upgrade_subtitle'
defaultMessage={'You\'re already using the latest version.'}
style={styles.messageSubtitle}
/>
</View>
);
}
renderMessageContent = () => {
const {currentVersion, forceUpgrade, latestVersion, upgradeType: passedUpgradeType, userCheckedForUpgrade, theme} = this.props;
const styles = getStyleFromTheme(theme);
const upgradeType = userCheckedForUpgrade ? this.state.upgradeType : passedUpgradeType;
let messageComponent;
switch (upgradeType) {
case UpgradeTypes.CAN_UPGRADE:
messageComponent = this.renderCanUpgrade();
break;
case UpgradeTypes.MUST_UPGRADE:
messageComponent = this.renderMustUpgrade();
break;
default:
case UpgradeTypes.NO_UPGRADE:
case UpgradeTypes.IS_BETA:
messageComponent = this.renderNoUpgrade();
break;
}
return (
<View style={styles.messageContainer}>
{messageComponent}
{upgradeType !== UpgradeTypes.IS_BETA && (
<FormattedText
id='mobile.client_upgrade.current_version'
defaultMessage='Lastest Version: {version}'
style={styles.messageSubtitle}
values={{
version: latestVersion,
}}
/>
)}
<FormattedText
id='mobile.client_upgrade.latest_version'
defaultMessage='Your Version: {version}'
style={styles.messageSubtitle}
values={{
version: currentVersion,
}}
/>
{isUpgradeAvailable(this.state.upgradeType) &&
<View>
<TouchableOpacity
onPress={this.handleDownload}
style={styles.messageButton}
>
<FormattedText
id='mobile.client_upgrade.upgrade'
defaultMessage='Upgrade'
style={styles.messageButtonText}
/>
</TouchableOpacity>
{!forceUpgrade &&
<TouchableOpacity
onPress={this.handleClose}
style={styles.messageCloseButton}
>
<FormattedText
id='mobile.client_upgrade.close'
defaultMessage='Upgrade Later'
style={styles.messageCloseButtonText}
/>
</TouchableOpacity>
}
</View>
}
</View>
);
}
render() {
const {theme} = this.props;
const styles = getStyleFromTheme(theme);
return (
<SafeAreaView style={styles.container}>
<StatusBar/>
<ScrollView
style={styles.scrollView}
contentContainerStyle={styles.scrollViewContent}
>
<Image
source={require('@assets/images/logo.png')}
style={{height: 72, resizeMode: 'contain'}}
/>
{this.renderMessageContent()}
</ScrollView>
</SafeAreaView>
);
}
}
const getStyleFromTheme = makeStyleSheetFromTheme((theme) => {
return {
container: {
flex: 1,
},
logo: {
marginTop: 75,
},
messageButton: {
marginBottom: 15,
borderWidth: 2,
borderRadius: 2,
alignItems: 'center',
justifyContent: 'center',
borderColor: theme.buttonBg,
},
messageButtonText: {
paddingVertical: 10,
paddingHorizontal: 20,
fontWeight: '600',
color: theme.buttonBg,
},
messageContainer: {
marginTop: 25,
flex: 1,
alignSelf: 'stretch',
alignItems: 'center',
},
messageCloseButton: {
marginBottom: 15,
alignItems: 'center',
justifyContent: 'center',
},
messageSubtitle: {
fontSize: 16,
marginBottom: 20,
color: theme.centerChannelColor,
textAlign: 'center',
paddingHorizontal: 30,
},
messageTitle: {
fontSize: 24,
marginBottom: 20,
fontWeight: '600',
color: theme.centerChannelColor,
textAlign: 'center',
paddingHorizontal: 30,
},
scrollView: {
flex: 1,
backgroundColor: changeOpacity(theme.centerChannelColor, 0.03),
},
scrollViewContent: {
paddingBottom: 20,
alignItems: 'center',
},
};
});

View file

@ -1,36 +0,0 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import {logError} from '@mm-redux/actions/errors';
import {setLastUpgradeCheck} from 'app/actions/views/client_upgrade';
import getClientUpgrade from 'app/selectors/client_upgrade';
import {getTheme} from '@mm-redux/selectors/entities/preferences';
import ClientUpgrade from './client_upgrade';
function mapStateToProps(state) {
const {currentVersion, downloadLink, forceUpgrade, latestVersion, minVersion} = getClientUpgrade(state);
return {
currentVersion,
downloadLink,
forceUpgrade,
latestVersion,
minVersion,
theme: getTheme(state),
};
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators({
logError,
setLastUpgradeCheck,
}, dispatch),
};
}
export default connect(mapStateToProps, mapDispatchToProps)(ClientUpgrade);

View file

@ -126,6 +126,8 @@ const PrepareFile = forwardRef<PrepareFileRef, PrepareFileProps>(({intl, isLands
if (path && share && !canceled) {
Share.open({
message: '',
title: '',
url: `file://${path}`,
showAppsToView: true,
}).catch(() => {

View file

@ -67,6 +67,7 @@ export default class Gallery extends PureComponent {
sharedElementTransitions.push({
fromId: `gallery-${file.id}`,
toId: `image-${file.id}`,
duration: 300,
interpolation: {type: 'accelerateDecelerate', factor: 8},
});
}
@ -79,10 +80,6 @@ export default class Gallery extends PureComponent {
});
}
const options = {
layout: {
backgroundColor: '#000',
componentBackgroundColor: '#000',
},
topBar: {
visible: this.footer.current?.getWrappedInstance().isVisible(),
background: {
@ -90,6 +87,7 @@ export default class Gallery extends PureComponent {
},
title: {
text: title,
color: '#FFF',
},
backButton: {
enableMenu: false,

View file

@ -10,6 +10,7 @@ import {calculateDimensions} from '@utils/images';
import {GalleryItemProps} from 'types/screens/gallery';
// @ts-expect-error: Ignore the typescript error for createAnimatedComponent
const AnimatedImage = Animated.createAnimatedComponent(FastImage);
const GalleryImage = ({file, deviceHeight, deviceWidth, style}: GalleryItemProps) => {

View file

@ -4,7 +4,7 @@
import React, {useEffect, useMemo, useRef, useState} from 'react';
import {Platform, StyleSheet, View} from 'react-native';
import {PanGestureHandler, PinchGestureHandler, State, TapGestureHandler, TapGestureHandlerStateChangeEvent} from 'react-native-gesture-handler';
import Animated, {abs, add, and, call, clockRunning, cond, divide, eq, greaterOrEq, greaterThan, multiply, neq, not, onChange, set, sub, useCode, Easing, ceil} from 'react-native-reanimated';
import Animated, {abs, add, and, call, clockRunning, cond, divide, eq, greaterOrEq, greaterThan, multiply, neq, not, onChange, set, sub, useCode, EasingNode, ceil} from 'react-native-reanimated';
import {clamp, snapPoint, timing, useClock, usePanGestureHandler, usePinchGestureHandler, useTapGestureHandler, useValue, vec} from 'react-native-redash/lib/module/v1';
import {isImage, isVideo} from '@utils/file';
import {calculateDimensions} from '@utils/images';
@ -216,7 +216,7 @@ const GalleryViewer = (props: GalleryProps) => {
], set(translateY, timing({from: translateY, to: 0}))),
]),
cond(and(eq(pan.state, State.END), neq(translationX, 0)), [
set(translateX, timing({clock, from: translateX, to: snapTo, duration: 250, easing: Easing.out(Easing.quad)})),
set(translateX, timing({clock, from: translateX, to: snapTo, duration: 250, easing: EasingNode.out(EasingNode.quad)})),
set(offsetX, translateX),
cond(not(clockRunning(clock)), [
vec.set(translate, 0),

View file

@ -61,9 +61,6 @@ Navigation.setLazyComponentRegistrator((screenName) => {
case 'ChannelNotificationPreference':
screen = require('@screens/channel_notification_preference').default;
break;
case 'ClientUpgrade':
screen = require('@screens/client_upgrade').default;
break;
case 'ClockDisplaySettings':
screen = require('@screens/settings/clock_display').default;
break;
@ -149,6 +146,9 @@ Navigation.setLazyComponentRegistrator((screenName) => {
case 'OptionsModal':
screen = require('@screens/options_modal').default;
break;
case 'PerfMetrics':
screen = require('@screens/perf_metrics').default;
break;
case 'Permalink':
screen = require('@screens/permalink').default;
break;

View file

@ -27,11 +27,9 @@ import StatusBar from '@components/status_bar';
import {t} from '@utils/i18n';
import {preventDoubleTap} from '@utils/tap';
import {changeOpacity} from '@utils/theme';
import tracker from '@utils/time_tracker';
import mattermostManaged from 'app/mattermost_managed';
import {GlobalStyles} from 'app/styles';
import telemetry from 'app/telemetry';
export const mfaExpectedErrors = ['mfa.validate_token.authenticate.app_error', 'ent.mfa.validate_token.authenticate.app_error'];
@ -75,9 +73,6 @@ export default class Login extends PureComponent {
}
goToChannel = () => {
telemetry.remove(['start:overall']);
tracker.initialLoad = Date.now();
this.scheduleSessionExpiredNotification();
resetToChannel();

View file

@ -0,0 +1,46 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React from 'react';
import {FlatList, View} from 'react-native';
import {useSelector} from 'react-redux';
import {getTheme} from '@mm-redux/selectors/entities/preferences';
import {changeOpacity, makeStyleFromTheme} from '@mm-redux/utils/theme_utils';
import telemetry, {PerfMetric} from '@telemetry';
import type {Theme} from '@mm-redux/types/preferences';
import PerfItem from './item';
const getStyleSheet = makeStyleFromTheme((theme: Theme) => {
return {
container: {
backgroundColor: changeOpacity(theme.centerChannelColor, 0.1),
flex: 1,
},
};
});
const PerfMetrics = () => {
const theme: Theme = useSelector(getTheme);
const style = getStyleSheet(theme);
const data: PerfMetric[] = telemetry.getMetrics();
return (
<View style={style.container}>
<FlatList
data={data}
keyExtractor={(item: PerfMetric) => `${item.name}-${item.startTime}`}
renderItem={({item}) => (
<PerfItem
metric={item}
theme={theme}
/>
)}
/>
</View>
);
};
export default PerfMetrics;

View file

@ -0,0 +1,88 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React from 'react';
import {Text, View} from 'react-native';
import {makeStyleSheetFromTheme} from '@utils/theme';
import type {Theme} from '@mm-redux/types/preferences';
import type {PerfMetric} from '@telemetry';
type PerfItemProps = {
metric: PerfMetric;
theme: Theme
};
const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({
container: {
alignItems: 'flex-start',
backgroundColor: theme.centerChannelBg,
margin: 5,
paddingVertical: 10,
paddingHorizontal: 5,
borderRadius: 5,
},
totalTime: {
fontWeight: 'bold',
borderWidth: 1,
borderRadius: 10,
paddingVertical: 1,
paddingHorizontal: 4,
textAlign: 'center',
marginVertical: 3,
},
text: {
color: theme.centerChannelColor,
fontSize: 16,
},
extra: {
paddingHorizontal: 5,
paddingVertical: 3,
flex: 1,
},
name: {
fontSize: 18,
fontWeight: 'bold',
textAlign: 'center',
padding: 0,
},
}));
const PerfItem = ({metric, theme}: PerfItemProps) => {
const styles = getStyleSheet(theme);
const time = (metric.endTime || 0) - metric.startTime;
const getStatusTextColor = (totalTime: number) => {
if (totalTime <= 500) {
return theme.onlineIndicator;
}
if (totalTime <= 2000) {
return theme.awayIndicator;
}
return theme.dndIndicator;
};
const getStatusStyles = (totalTime: number) => ({
color: getStatusTextColor(totalTime),
borderColor: getStatusTextColor(totalTime),
});
return (
<View style={styles.container}>
<Text style={[styles.text, styles.name]}>
{metric.name}
</Text>
<Text style={[styles.totalTime, getStatusStyles(time)]}>
{time + 'ms'}
</Text>
<Text style={[styles.text, styles.extra]}>
{metric.extra}
</Text>
</View>
);
};
export default PerfItem;

View file

@ -4,31 +4,25 @@
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import {setLastUpgradeCheck} from '@actions/views/client_upgrade';
import {loadConfigAndLicense} from '@actions/views/root';
import {handleServerUrlChanged} from '@actions/views/select_server';
import {scheduleExpiredNotification} from '@actions/views/session';
import {getPing, resetPing, setServerVersion} from '@mm-redux/actions/general';
import {login} from '@mm-redux/actions/users';
import {getConfig, getLicense} from '@mm-redux/selectors/entities/general';
import getClientUpgrade from '@selectors/client_upgrade';
import SelectServer from './select_server';
function mapStateToProps(state) {
const config = getConfig(state);
const license = getLicense(state);
const {currentVersion, latestVersion, minVersion} = getClientUpgrade(state);
return {
...state.views.selectServer,
config,
currentVersion,
deepLinkURL: state.views.root.deepLinkURL,
hasConfigAndLicense: Object.keys(config).length > 0 && Object.keys(license).length > 0,
latestVersion,
license,
minVersion,
};
}
@ -41,7 +35,6 @@ function mapDispatchToProps(dispatch) {
loadConfigAndLicense,
login,
resetPing,
setLastUpgradeCheck,
setServerVersion,
}, dispatch),
};

View file

@ -35,16 +35,13 @@ import fetchConfig from '@init/fetch';
import globalEventHandler from '@init/global_event_handler';
import {Client4} from '@client/rest';
import {isMinimumServerVersion} from '@mm-redux/utils/helpers';
import {checkUpgradeType, isUpgradeAvailable} from '@utils/client_upgrade';
import {t} from '@utils/i18n';
import {preventDoubleTap} from '@utils/tap';
import {changeOpacity} from '@utils/theme';
import tracker from '@utils/time_tracker';
import {isValidUrl, stripTrailingSlashes} from '@utils/url';
import mattermostBucket from 'app/mattermost_bucket';
import {GlobalStyles} from 'app/styles';
import telemetry from 'app/telemetry';
export default class SelectServer extends PureComponent {
static propTypes = {
@ -55,16 +52,12 @@ export default class SelectServer extends PureComponent {
loadConfigAndLicense: PropTypes.func.isRequired,
login: PropTypes.func.isRequired,
resetPing: PropTypes.func.isRequired,
setLastUpgradeCheck: PropTypes.func.isRequired,
setServerVersion: PropTypes.func.isRequired,
}).isRequired,
allowOtherServers: PropTypes.bool,
config: PropTypes.object,
currentVersion: PropTypes.string,
hasConfigAndLicense: PropTypes.bool.isRequired,
latestVersion: PropTypes.string,
license: PropTypes.object,
minVersion: PropTypes.string,
serverUrl: PropTypes.string.isRequired,
deepLinkURL: PropTypes.string,
};
@ -115,25 +108,11 @@ export default class SelectServer extends PureComponent {
this.certificateListener = DeviceEventEmitter.addListener('RNFetchBlobCertificate', this.selectCertificate);
this.sslProblemListener = DeviceEventEmitter.addListener('RNFetchBlobSslProblem', this.handleSslProblem);
telemetry.end(['start:select_server_screen']);
telemetry.save();
}
componentDidUpdate(prevProps, prevState) {
if (this.state.connected && this.props.hasConfigAndLicense && !(prevState.connected && prevProps.hasConfigAndLicense)) {
if (LocalConfig.EnableMobileClientUpgrade) {
this.props.actions.setLastUpgradeCheck();
const {currentVersion, minVersion, latestVersion} = this.props;
const upgradeType = checkUpgradeType(currentVersion, minVersion, latestVersion);
if (isUpgradeAvailable(upgradeType)) {
this.handleShowClientUpgrade(upgradeType);
} else {
this.handleLoginOptions(this.props);
}
} else {
this.handleLoginOptions(this.props);
}
this.handleLoginOptions();
}
}
@ -251,9 +230,9 @@ export default class SelectServer extends PureComponent {
}
});
handleLoginOptions = async (props = this.props) => {
handleLoginOptions = async () => {
const {formatMessage} = this.context.intl;
const {config, license} = props;
const {config, license} = this.props;
const samlEnabled = config.EnableSaml === 'true' && license.IsLicensed === 'true' && license.SAML === 'true';
const gitlabEnabled = config.EnableSignUpWithGitLab === 'true';
const googleEnabled = config.EnableSignUpWithGoogle === 'true' && license.IsLicensed === 'true';
@ -293,23 +272,6 @@ export default class SelectServer extends PureComponent {
}
};
handleShowClientUpgrade = (upgradeType) => {
const {formatMessage} = this.context.intl;
const screen = 'ClientUpgrade';
const title = formatMessage({id: 'mobile.client_upgrade', defaultMessage: 'Client Upgrade'});
const passProps = {
closeAction: this.handleLoginOptions,
upgradeType,
};
const options = {
statusBar: {
visible: false,
},
};
this.goToNextScreen(screen, title, passProps, options);
};
handleTextChanged = (url) => {
this.setState({url});
};
@ -319,8 +281,6 @@ export default class SelectServer extends PureComponent {
};
loginWithCertificate = async () => {
tracker.initialLoad = Date.now();
await this.props.actions.login('credential', 'password');
this.scheduleSessionExpiredNotification();

View file

@ -14,7 +14,6 @@ describe('SelectServer', () => {
loadConfigAndLicense: jest.fn(),
login: jest.fn(),
resetPing: jest.fn(),
setLastUpgradeCheck: jest.fn(),
setServerVersion: jest.fn(),
};

View file

@ -15,7 +15,7 @@ import {
import {SafeAreaView} from 'react-native-safe-area-context';
import * as Sentry from '@sentry/react-native';
import {dismissAllModals} from '@actions/navigation';
import {dismissAllModals, goToScreen} from '@actions/navigation';
import Config from '@assets/config';
import StatusBar from '@components/status_bar';
import {getFormattedFileSize} from '@mm-redux/utils/file_utils';
@ -137,6 +137,10 @@ class AdvancedSettings extends Component {
);
};
showPerfMetrics = preventDoubleTap(() => {
goToScreen('PerfMetrics', 'Performance Metrics');
});
render() {
const {theme} = this.props;
const style = getStyleSheet(theme);
@ -160,12 +164,25 @@ class AdvancedSettings extends Component {
iconName='trash-can-outline'
isDestructor={true}
onPress={this.clearOfflineCache}
separator={false}
separator={Boolean(Config.ShowPerformanceMarkers)}
showArrow={false}
rightComponent={this.renderCacheFileSize()}
theme={theme}
testID='advanced_settings.delete_documents_and_data.action'
/>
{Config.ShowPerformanceMarkers &&
<SettingsItem
defaultMessage='Performance Metrics'
i18nId='mobile.advanced_settings.performance_title'
iconName='chart-bar'
isDestructor={false}
onPress={this.showPerfMetrics}
separator={false}
showArrow={true}
theme={theme}
testID='advanced_settings.performance.action'
/>
}
<View style={style.divider}/>
{this.renderSentryDebugOptions()}
</ScrollView>

View file

@ -15,7 +15,6 @@ import {Navigation} from 'react-native-navigation';
import {SafeAreaView} from 'react-native-safe-area-context';
import {goToScreen, dismissModal} from '@actions/navigation';
import LocalConfig from '@assets/config';
import StatusBar from '@components/status_bar';
import SettingsItem from '@screens/settings/settings_item';
import {t} from '@utils/i18n';
@ -123,17 +122,6 @@ class Settings extends PureComponent {
goToScreen(screen, title, passProps);
});
goToClientUpgrade = preventDoubleTap(() => {
const {intl} = this.props;
const screen = 'ClientUpgrade';
const title = intl.formatMessage({id: 'mobile.client_upgrade', defaultMessage: 'Upgrade App'});
const passProps = {
userCheckedForUpgrade: true,
};
goToScreen(screen, title, passProps);
});
openErrorEmail = preventDoubleTap(() => {
const {config, intl} = this.props;
const recipient = config.SupportEmail;
@ -246,18 +234,6 @@ class Settings extends PureComponent {
theme={theme}
separator={true}
/>
{LocalConfig.EnableMobileClientUpgrade && LocalConfig.EnableMobileClientUpgradeUserSetting &&
<SettingsItem
testID='general_settings.check_for_upgrade.action'
defaultMessage='Check for Upgrade'
i18nId={t('mobile.settings.modal.check_for_upgrade')}
iconName='update'
onPress={this.goToClientUpgrade}
showArrow={showArrow}
theme={theme}
separator={true}
/>
}
<SettingsItem
testID='general_settings.about.action'
defaultMessage='About {appTitle}'

View file

@ -51,7 +51,6 @@ describe('SidebarSettings', () => {
const mainProps = {
actions: {
getTeams: jest.fn(),
logChannelSwitch: jest.fn(),
makeDirectChannel: jest.fn(),
setChannelDisplayName: jest.fn(),
setChannelLoading: jest.fn(),

View file

@ -8,7 +8,6 @@ import type {GlobalState} from '@mm-redux/types/store';
import {resetToChannel} from 'app/actions/navigation';
import {ViewTypes} from 'app/constants';
import tracker from 'app/utils/time_tracker';
import {scheduleExpiredNotification} from '@actions/views/session';
import {ssoLogin} from '@actions/views/user';
import emmProvider from '@init/emm_provider';
@ -92,7 +91,6 @@ function SSO({intl, ssoType}: SSOProps) {
};
const goToChannel = () => {
tracker.initialLoad = Date.now();
scheduleSessionExpiredNotification();
resetToChannel();
};

View file

@ -1,34 +0,0 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {createSelector} from 'reselect';
import {Platform} from 'react-native';
import DeviceInfo from 'react-native-device-info';
import LocalConfig from '@assets/config';
import {getConfig} from '@mm-redux/selectors/entities/general';
const getClientUpgrade = createSelector(
getConfig,
(config) => {
const {AndroidMinVersion, AndroidLatestVersion, IosMinVersion, IosLatestVersion} = config;
let minVersion = IosMinVersion;
let latestVersion = IosLatestVersion;
let downloadLink = LocalConfig.MobileClientUpgradeIosIpaLink;
if (Platform.OS === 'android') {
minVersion = AndroidMinVersion;
latestVersion = AndroidLatestVersion;
downloadLink = LocalConfig.MobileClientUpgradeAndroidApkLink;
}
return {
currentVersion: DeviceInfo.getVersion(),
downloadLink,
forceUpgrade: LocalConfig.EnableForceMobileClientUpgrade,
latestVersion,
minVersion,
};
},
);
export default getClientUpgrade;

View file

@ -9,10 +9,6 @@ export function getConnection(state) {
return state.device.connection;
}
export function getStatusBarHeight(state) {
return state.device.statusBarHeight;
}
export function isLandscape(state) {
return state.device.dimension.deviceWidth > state.device.dimension.deviceHeight;
}

View file

@ -1,6 +0,0 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import telemetry from './telemetry';
export default telemetry;

87
app/telemetry/index.ts Normal file
View file

@ -0,0 +1,87 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {getTimeSinceStartup} from 'react-native-startup-time';
export interface PerfMetric {
name: string;
startTime: number;
endTime?: number;
extra: string;
}
export const PERF_MARKERS = {
START_SINCE_LAUNCH: 'Start Since Launch',
CHANNEL_RENDER: 'Channel Render',
CHANNEL_SWITCH: 'Channe Switch',
};
class Telemetry {
metrics: PerfMetric[];
currentMetrics: Record<string, PerfMetric>;
constructor() {
this.metrics = [];
this.currentMetrics = {};
}
getMetrics = () => {
return this.metrics;
}
reset() {
this.currentMetrics = {};
}
start(names = [], time = 0, extra = []) {
const startTime = Date.now();
names.forEach((name, index) => {
this.currentMetrics[name] = {
extra: extra[index],
name,
startTime: time || startTime,
};
});
}
end(names = []) {
const endTime = Date.now();
names.forEach((name) => {
const finalMetric = this.currentMetrics[name];
if (finalMetric && finalMetric.startTime >= 0) {
this.metrics.push({
...finalMetric,
endTime,
});
Reflect.deleteProperty(this.currentMetrics, name);
}
});
}
startSinceLaunch(extra = '') {
getTimeSinceStartup().then((endTime) => {
this.metrics.push({
extra,
name: PERF_MARKERS.START_SINCE_LAUNCH,
startTime: 0,
endTime,
});
});
}
remove(names = []) {
names.forEach((name) => {
const currentMetric = this.currentMetrics[name];
if (currentMetric) {
Reflect.deleteProperty(this.currentMetrics, name);
}
});
}
}
const telemetry = new Telemetry();
export default telemetry;

View file

@ -1,157 +0,0 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import LocalConfig from '@assets/config';
import Store from '@store/store';
import {
saveToTelemetryServer,
getDeviceInfo,
setTraceRecord,
} from './telemetry_utils';
class Telemetry {
constructor() {
this.appStartTime = 0;
this.reactInitializedStartTime = 0;
this.reactInitializedEndTime = 0;
this.metrics = [];
this.currentMetrics = {};
this.pendingSinceLaunchMetrics = [];
}
setAppStartTime(startTime) {
this.appStartTime = startTime;
}
reset() {
this.metrics = [];
this.currentMetrics = {};
this.pendingSinceLaunchMetrics = [];
}
canSendTelemetry() {
const {config} = Store.redux.getState().entities.general;
return Boolean(!__DEV__ && config.EnableDiagnostics === 'true' && LocalConfig.TelemetryEnabled);
}
start(names = [], time = 0) {
if (this.canSendTelemetry()) {
const d = new Date();
const startTime = d.getTime();
names.forEach((name) => {
this.currentMetrics[name] = {
name,
startTime: time || startTime,
};
});
}
}
end(names = []) {
if (this.canSendTelemetry()) {
const d = new Date();
const endTime = d.getTime();
names.forEach((name) => {
const finalMetric = this.currentMetrics[name];
if (finalMetric && finalMetric.startTime > 0) {
this.metrics.push({
...finalMetric,
endTime,
});
Reflect.deleteProperty(this.currentMetrics, name);
}
});
}
}
include(metrics = []) {
if (this.canSendTelemetry()) {
metrics.forEach((metric) => {
this.metrics.push({
name: metric.name,
startTime: metric.startTime,
endTime: metric.endTime,
});
});
}
}
startSinceLaunch(names = []) {
if (this.canSendTelemetry()) {
const d = new Date();
const endTime = d.getTime();
names.forEach((name) => {
if (!this.appStartTime) {
this.pendingSinceLaunchMetrics.push({
name,
endTime,
});
return;
}
this.metrics.push({
name,
startTime: this.appStartTime,
endTime,
});
});
}
}
remove(names = []) {
names.forEach((name) => {
const currentMetric = this.currentMetrics[name];
if (currentMetric) {
Reflect.deleteProperty(this.currentMetrics, name);
}
});
}
async save() {
if (!this.canSendTelemetry()) {
return;
}
this.pendingSinceLaunchMetrics.forEach((pendingMetric) => {
this.metrics.push({
...pendingMetric,
startTime: this.appStartTime,
});
});
if (this.metrics.length === 0) {
return;
}
const metrics = this.metrics.filter((m) => m.endTime && m.startTime).map((metric) => {
const {name, startTime, endTime} = metric;
let dur;
if (endTime && startTime) {
dur = (endTime - startTime) * 1000;
}
return setTraceRecord({
name,
time: startTime * 1000,
dur,
});
});
const {config} = Store.redux.getState().entities.general;
const deviceInfo = getDeviceInfo();
deviceInfo.server_version = config.Version;
saveToTelemetryServer({trace_events: metrics, device_info: deviceInfo});
this.reset();
}
}
const telemetry = new Telemetry();
export default telemetry;

View file

@ -1,34 +0,0 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
class Telemetry {
constructor() {
this.appStartTime = 0;
this.reactInitializedStartTime = 0;
this.reactInitializedEndTime = 0;
this.metrics = [];
this.currentMetrics = {};
this.pendingSinceLaunchMetrics = [];
}
setAppStartTime = () => true;
reset = () => true;
canSendTelemetry = () => false;
start = () => true;
end = () => true;
include = () => true;
startSinceLaunch = () => true;
remove = () => true;
save = () => true;
}
const telemetry = new Telemetry();
export default telemetry;

View file

@ -1,102 +0,0 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {Dimensions} from 'react-native';
import DeviceInfo from 'react-native-device-info';
import * as RNLocalize from 'react-native-localize';
import LocalConfig from '@assets/config';
export function saveToTelemetryServer(data) {
const {
TelemetryEnabled,
TelemetryUrl,
TelemetryApiKey,
} = LocalConfig;
if (TelemetryEnabled && TelemetryUrl) {
fetch(TelemetryUrl, {
method: 'post',
body: JSON.stringify({data}),
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
'x-api-key': TelemetryApiKey,
},
});
}
}
const presetTID = {
'start:overall': 0,
'start:process_packages': 1,
'start:content_appeared': 2,
'start:select_server_screen': 3,
'start:channel_screen': 4,
'team:switch': 5,
'channel:loading': 6,
'channel:switch_loaded': 7,
'channel:switch_initial': 8,
'channel:close_drawer': 9,
'channel:open_drawer': 10,
'posts:loading': 11,
'post_list:thread': 12,
'post_list:permalink': 13,
};
export function setTraceRecord({
name,
time: ts,
dur = 0,
instanceKey = 0,
pid = 0,
}) {
const tid = presetTID[name];
return {
cat: 'react-native',
ph: 'X',
name,
ts,
dur,
pid,
tid,
args: {
instanceKey,
tag: name,
},
};
}
export async function getDeviceInfo() {
const {height, width} = Dimensions.get('window');
return {
api_level: await DeviceInfo.getAPILevel(),
build_number: DeviceInfo.getBuildNumber(),
bundle_id: DeviceInfo.getBundleId(),
brand: DeviceInfo.getBrand(),
country: RNLocalize.getCountry(),
device_id: DeviceInfo.getDeviceId(),
device_locale: RNLocalize.getLocales()[0].languageCode,
device_type: DeviceInfo.getDeviceType(),
device_unique_id: DeviceInfo.getUniqueID(),
height: height ? Math.floor(height) : 0,
is_emulator: await DeviceInfo.isEmulator(),
is_tablet: DeviceInfo.isTablet(),
manufacturer: await DeviceInfo.getManufacturer(),
max_memory: await DeviceInfo.getMaxMemory(),
model: DeviceInfo.getModel(),
system_name: DeviceInfo.getSystemName(),
system_version: DeviceInfo.getSystemVersion(),
timezone: RNLocalize.getTimeZone(),
app_version: DeviceInfo.getVersion(),
width: width ? Math.floor(width) : 0,
};
}
export default {
getDeviceInfo,
setTraceRecord,
};

View file

@ -1,35 +0,0 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import semver from 'semver';
import LocalConfig from '@assets/config';
import {UpgradeTypes} from '@constants';
export function checkUpgradeType(currentVersion, minVersion, latestVersion, logError) {
let upgradeType = UpgradeTypes.NO_UPGRADE;
try {
if (semver.gt(currentVersion, latestVersion)) {
upgradeType = UpgradeTypes.IS_BETA;
} else if (minVersion && semver.lt(currentVersion, minVersion)) {
upgradeType = UpgradeTypes.MUST_UPGRADE;
} else if (latestVersion && semver.lt(currentVersion, latestVersion)) {
if (LocalConfig.EnableForceMobileClientUpgrade) {
upgradeType = UpgradeTypes.MUST_UPGRADE;
} else {
upgradeType = UpgradeTypes.CAN_UPGRADE;
}
}
} catch (error) {
logError(error.message);
}
return upgradeType;
}
export function isUpgradeAvailable(upgradeType) {
return [
UpgradeTypes.CAN_UPGRADE,
UpgradeTypes.MUST_UPGRADE,
].includes(upgradeType);
}

View file

@ -11,7 +11,6 @@ import {mergeNavigationOptions} from 'app/actions/navigation';
const MODAL_SCREENS_WITHOUT_BACK = [
'AddReaction',
'ChannelInfo',
'ClientUpgrade',
'CreateChannel',
'EditPost',
'ErrorTeamsList',

View file

@ -1,8 +0,0 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
export default {
initialLoad: 0,
channelSwitch: 0,
teamSwitch: 0,
};

View file

@ -1,17 +1,19 @@
{
"DefaultServerUrl": "",
"TestServerUrl": "http://localhost:8065",
"DefaultTheme": "default",
"ShowErrorsList": false,
"MinServerVersion": "4.0.0",
"EELearnURL": "about.mattermost.com",
"TeamEditionLearnURL": "mattermost.org",
"AboutTeamURL": "http://www.mattermost.org/",
"AboutEnterpriseURL": "http://about.mattermost.com/",
"PlatformNoticeURL": "https://about.mattermost.com/platform-notice-txt/",
"AboutEnterpriseURL": "https://mattermost.com/",
"PlatformNoticeURL": "https://mattermost.com/platform-notice-txt/",
"MobileNoticeURL": "https://about.mattermost.com/mobile-notice-txt/",
"RudderApiKey": "",
"AutoSelectServerUrl": false,
"CustomRequestHeaders": {},
"ExperimentalNormalizeMarkdownLinks": false,
"HideEmailLoginExperimental": false,
"HideGitLabLoginExperimental": false,
"HideLDAPLoginExperimental": false,
@ -19,6 +21,7 @@
"HideO365LoginExperimental": false,
"SentryEnabled": false,
"ShowSentryDebugOptions": false,
"SentryDsnIos": "",
"SentryDsnAndroid": "",
"SentryOptions": {
@ -28,22 +31,6 @@
"console": true
}
},
"ExperimentalNormalizeMarkdownLinks": false,
"AutoSelectServerUrl": false,
"EnableMobileClientUpgrade": false,
"EnableMobileClientUpgradeUserSetting": false,
"EnableForceMobileClientUpgrade": false,
"MobileClientUpgradeAndroidApkLink": "https://about.mattermost.com/mattermost-android-app/",
"MobileClientUpgradeIosIpaLink": "https://about.mattermost.com/mattermost-ios-app/",
"ShowSentryDebugOptions": false,
"CustomRequestHeaders": {},
"TelemetryEnabled": false,
"TelemetryUrl": "",
"TelemetryApiKey": ""
"ShowPerformanceMarkers": false
}

View file

@ -240,23 +240,6 @@
"mobile.channel_list.unreads": "UNREADS",
"mobile.channel_loader.still_loading": "Still trying to load your content...",
"mobile.channel_members.add_members_alert": "You must select at least one member to add to the channel.",
"mobile.client_upgrade": "Update App",
"mobile.client_upgrade.can_upgrade_subtitle": "A new version is available for download.",
"mobile.client_upgrade.can_upgrade_title": "Update Available",
"mobile.client_upgrade.close": "Update Later",
"mobile.client_upgrade.current_version": "Latest Version: {version}",
"mobile.client_upgrade.download_error.message": "An error occurred downloading the new version.",
"mobile.client_upgrade.download_error.title": "Unable to Install Update",
"mobile.client_upgrade.latest_version": "Your Version: {version}",
"mobile.client_upgrade.listener.dismiss_button": "Dismiss",
"mobile.client_upgrade.listener.learn_more_button": "Learn More",
"mobile.client_upgrade.listener.message": "A client upgrade is available!",
"mobile.client_upgrade.listener.upgrade_button": "Upgrade",
"mobile.client_upgrade.must_upgrade_subtitle": "Please update the app to continue.",
"mobile.client_upgrade.must_upgrade_title": "Update Required",
"mobile.client_upgrade.no_upgrade_subtitle": "You already have the latest version.",
"mobile.client_upgrade.no_upgrade_title": "Your App Is Up to Date",
"mobile.client_upgrade.upgrade": "Update",
"mobile.commands.error_title": "Error Executing Command",
"mobile.components.error_list.dismiss_all": "Dismiss All",
"mobile.components.select_server_view.connect": "Connect",
@ -525,7 +508,6 @@
"mobile.server_ssl.error.title": "Untrusted Certificate",
"mobile.server_upgrade.alert_description": "This server version is unsupported and users will be exposed to compatibility issues that cause crashes or severe bugs breaking core functionality of the app. Upgrading to server version {serverVersion} or later is required.",
"mobile.server_upgrade.button": "OK",
"mobile.server_upgrade.description": "\nA server upgrade is required to use the Mattermost app. Please ask your System Administrator for details.\n",
"mobile.server_upgrade.dismiss": "Dismiss",
"mobile.server_upgrade.learn_more": "Learn More",
"mobile.server_upgrade.title": "Server upgrade required",
@ -536,7 +518,6 @@
"mobile.set_status.dnd": "Do Not Disturb",
"mobile.set_status.offline": "Offline",
"mobile.set_status.online": "Online",
"mobile.settings.modal.check_for_upgrade": "Check for Updates",
"mobile.share_extension.channel": "Channel",
"mobile.share_extension.error_close": "Close",
"mobile.share_extension.error_message": "An error has occurred while using the share extension.",

View file

@ -11,7 +11,6 @@ class GeneralSettingsScreen {
displayAction: 'general_settings.display.action',
selectTeamAction: 'general_settings.select_team.action',
advancedAction: 'general_settings.advanced.action',
checkForUpgradeAction: 'general_settings.checkForUpgrade.action',
aboutAction: 'general_settings.about.action',
helpAction: 'general_settings.help.action',
reportAction: 'general_settings.report.action',
@ -23,7 +22,6 @@ class GeneralSettingsScreen {
displayAction = element(by.id(this.testID.displayAction));
selectTeamAction = element(by.id(this.testID.selectTeamAction));
advancedAction = element(by.id(this.testID.advancedAction));
checkForUpgradeAction = element(by.id(this.testID.checkForUpgradeAction));
aboutAction = element(by.id(this.testID.aboutAction));
helpAction = element(by.id(this.testID.helpAction));
reportAction = element(by.id(this.testID.reportAction));

444
detox/package-lock.json generated
View file

@ -152,13 +152,31 @@
}
},
"@babel/helper-hoist-variables": {
"version": "7.13.0",
"resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.13.0.tgz",
"integrity": "sha512-0kBzvXiIKfsCA0y6cFEIJf4OdzfpRuNk4+YTeHZpGGc666SATFKTz6sRncwFnQk7/ugJ4dSrCj6iJuvW4Qwr2g==",
"version": "7.13.16",
"resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.13.16.tgz",
"integrity": "sha512-1eMtTrXtrwscjcAeO4BVK+vvkxaLJSPFz1w1KLawz6HLNi9bPFGBNwwDyVfiu1Tv/vRRFYfoGaKhmAQPGPn5Wg==",
"dev": true,
"requires": {
"@babel/traverse": "^7.13.0",
"@babel/types": "^7.13.0"
"@babel/traverse": "^7.13.15",
"@babel/types": "^7.13.16"
},
"dependencies": {
"@babel/helper-validator-identifier": {
"version": "7.14.0",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz",
"integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==",
"dev": true
},
"@babel/types": {
"version": "7.14.1",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.1.tgz",
"integrity": "sha512-S13Qe85fzLs3gYRUnrpyeIrBJIMYv33qSTg1qoBwiG6nPKwUWAD9odSzWhEedpwOIzSEI6gbdQIWEMiCI42iBA==",
"dev": true,
"requires": {
"@babel/helper-validator-identifier": "^7.14.0",
"to-fast-properties": "^2.0.0"
}
}
}
},
"@babel/helper-member-expression-to-functions": {
@ -344,6 +362,16 @@
"@babel/helper-plugin-utils": "^7.13.0"
}
},
"@babel/plugin-proposal-class-static-block": {
"version": "7.13.11",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.13.11.tgz",
"integrity": "sha512-fJTdFI4bfnMjvxJyNuaf8i9mVcZ0UhetaGEUHaHV9KEnibLugJkZAtXikR8KcYj+NYmI4DZMS8yQAyg+hvfSqg==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.13.0",
"@babel/plugin-syntax-class-static-block": "^7.12.13"
}
},
"@babel/plugin-proposal-dynamic-import": {
"version": "7.13.8",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.13.8.tgz",
@ -448,6 +476,34 @@
"@babel/helper-plugin-utils": "^7.13.0"
}
},
"@babel/plugin-proposal-private-property-in-object": {
"version": "7.14.0",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.14.0.tgz",
"integrity": "sha512-59ANdmEwwRUkLjB7CRtwJxxwtjESw+X2IePItA+RGQh+oy5RmpCh/EvVVvh5XQc3yxsm5gtv0+i9oBZhaDNVTg==",
"dev": true,
"requires": {
"@babel/helper-annotate-as-pure": "^7.12.13",
"@babel/helper-create-class-features-plugin": "^7.14.0",
"@babel/helper-plugin-utils": "^7.13.0",
"@babel/plugin-syntax-private-property-in-object": "^7.14.0"
},
"dependencies": {
"@babel/helper-create-class-features-plugin": {
"version": "7.14.1",
"resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.14.1.tgz",
"integrity": "sha512-r8rsUahG4ywm0QpGcCrLaUSOuNAISR3IZCg4Fx05Ozq31aCUrQsTLH6KPxy0N5ULoQ4Sn9qjNdGNtbPWAC6hYg==",
"dev": true,
"requires": {
"@babel/helper-annotate-as-pure": "^7.12.13",
"@babel/helper-function-name": "^7.12.13",
"@babel/helper-member-expression-to-functions": "^7.13.12",
"@babel/helper-optimise-call-expression": "^7.12.13",
"@babel/helper-replace-supers": "^7.13.12",
"@babel/helper-split-export-declaration": "^7.12.13"
}
}
}
},
"@babel/plugin-proposal-unicode-property-regex": {
"version": "7.12.13",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.12.13.tgz",
@ -485,6 +541,15 @@
"@babel/helper-plugin-utils": "^7.12.13"
}
},
"@babel/plugin-syntax-class-static-block": {
"version": "7.12.13",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.12.13.tgz",
"integrity": "sha512-ZmKQ0ZXR0nYpHZIIuj9zE7oIqCx2hw9TKi+lIo73NNrMPAZGHfS92/VRV0ZmPj6H2ffBgyFHXvJ5NYsNeEaP2A==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.12.13"
}
},
"@babel/plugin-syntax-dynamic-import": {
"version": "7.8.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz",
@ -575,6 +640,15 @@
"@babel/helper-plugin-utils": "^7.8.0"
}
},
"@babel/plugin-syntax-private-property-in-object": {
"version": "7.14.0",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.0.tgz",
"integrity": "sha512-bda3xF8wGl5/5btF794utNOL0Jw+9jE5C1sLZcoK7c4uonE/y3iQiyG+KbkF3WBV/paX58VCpjhxLPkdj5Fe4w==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.13.0"
}
},
"@babel/plugin-syntax-top-level-await": {
"version": "7.12.13",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.12.13.tgz",
@ -614,12 +688,12 @@
}
},
"@babel/plugin-transform-block-scoping": {
"version": "7.12.13",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.12.13.tgz",
"integrity": "sha512-Pxwe0iqWJX4fOOM2kEZeUuAxHMWb9nK+9oh5d11bsLoB0xMg+mkDpt0eYuDZB7ETrY9bbcVlKUGTOGWy7BHsMQ==",
"version": "7.14.1",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.14.1.tgz",
"integrity": "sha512-2mQXd0zBrwfp0O1moWIhPpEeTKDvxyHcnma3JATVP1l+CctWBuot6OJG8LQ4DnBj4ZZPSmlb/fm4mu47EOAnVA==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.12.13"
"@babel/helper-plugin-utils": "^7.13.0"
}
},
"@babel/plugin-transform-classes": {
@ -647,9 +721,9 @@
}
},
"@babel/plugin-transform-destructuring": {
"version": "7.13.0",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.13.0.tgz",
"integrity": "sha512-zym5em7tePoNT9s964c0/KU3JPPnuq7VhIxPRefJ4/s82cD+q1mgKfuGRDMCPL0HTyKz4dISuQlCusfgCJ86HA==",
"version": "7.13.17",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.13.17.tgz",
"integrity": "sha512-UAUqiLv+uRLO+xuBKKMEpC+t7YRNVRqBsWWq1yKXbBZBje/t3IXCiSinZhjn/DC3qzBfICeYd2EFGEbHsh5RLA==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.13.0"
@ -722,26 +796,160 @@
}
},
"@babel/plugin-transform-modules-amd": {
"version": "7.13.0",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.13.0.tgz",
"integrity": "sha512-EKy/E2NHhY/6Vw5d1k3rgoobftcNUmp9fGjb9XZwQLtTctsRBOTRO7RHHxfIky1ogMN5BxN7p9uMA3SzPfotMQ==",
"version": "7.14.0",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.14.0.tgz",
"integrity": "sha512-CF4c5LX4LQ03LebQxJ5JZes2OYjzBuk1TdiF7cG7d5dK4lAdw9NZmaxq5K/mouUdNeqwz3TNjnW6v01UqUNgpQ==",
"dev": true,
"requires": {
"@babel/helper-module-transforms": "^7.13.0",
"@babel/helper-module-transforms": "^7.14.0",
"@babel/helper-plugin-utils": "^7.13.0",
"babel-plugin-dynamic-import-node": "^2.3.3"
},
"dependencies": {
"@babel/generator": {
"version": "7.14.1",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.14.1.tgz",
"integrity": "sha512-TMGhsXMXCP/O1WtQmZjpEYDhCYC9vFhayWZPJSZCGkPJgUqX0rF0wwtrYvnzVxIjcF80tkUertXVk5cwqi5cAQ==",
"dev": true,
"requires": {
"@babel/types": "^7.14.1",
"jsesc": "^2.5.1",
"source-map": "^0.5.0"
}
},
"@babel/helper-module-transforms": {
"version": "7.14.0",
"resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.14.0.tgz",
"integrity": "sha512-L40t9bxIuGOfpIGA3HNkJhU9qYrf4y5A5LUSw7rGMSn+pcG8dfJ0g6Zval6YJGd2nEjI7oP00fRdnhLKndx6bw==",
"dev": true,
"requires": {
"@babel/helper-module-imports": "^7.13.12",
"@babel/helper-replace-supers": "^7.13.12",
"@babel/helper-simple-access": "^7.13.12",
"@babel/helper-split-export-declaration": "^7.12.13",
"@babel/helper-validator-identifier": "^7.14.0",
"@babel/template": "^7.12.13",
"@babel/traverse": "^7.14.0",
"@babel/types": "^7.14.0"
}
},
"@babel/helper-validator-identifier": {
"version": "7.14.0",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz",
"integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==",
"dev": true
},
"@babel/parser": {
"version": "7.14.1",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.1.tgz",
"integrity": "sha512-muUGEKu8E/ftMTPlNp+mc6zL3E9zKWmF5sDHZ5MSsoTP9Wyz64AhEf9kD08xYJ7w6Hdcu8H550ircnPyWSIF0Q==",
"dev": true
},
"@babel/traverse": {
"version": "7.14.0",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.14.0.tgz",
"integrity": "sha512-dZ/a371EE5XNhTHomvtuLTUyx6UEoJmYX+DT5zBCQN3McHemsuIaKKYqsc/fs26BEkHs/lBZy0J571LP5z9kQA==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.12.13",
"@babel/generator": "^7.14.0",
"@babel/helper-function-name": "^7.12.13",
"@babel/helper-split-export-declaration": "^7.12.13",
"@babel/parser": "^7.14.0",
"@babel/types": "^7.14.0",
"debug": "^4.1.0",
"globals": "^11.1.0"
}
},
"@babel/types": {
"version": "7.14.1",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.1.tgz",
"integrity": "sha512-S13Qe85fzLs3gYRUnrpyeIrBJIMYv33qSTg1qoBwiG6nPKwUWAD9odSzWhEedpwOIzSEI6gbdQIWEMiCI42iBA==",
"dev": true,
"requires": {
"@babel/helper-validator-identifier": "^7.14.0",
"to-fast-properties": "^2.0.0"
}
}
}
},
"@babel/plugin-transform-modules-commonjs": {
"version": "7.13.8",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.13.8.tgz",
"integrity": "sha512-9QiOx4MEGglfYZ4XOnU79OHr6vIWUakIj9b4mioN8eQIoEh+pf5p/zEB36JpDFWA12nNMiRf7bfoRvl9Rn79Bw==",
"version": "7.14.0",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.14.0.tgz",
"integrity": "sha512-EX4QePlsTaRZQmw9BsoPeyh5OCtRGIhwfLquhxGp5e32w+dyL8htOcDwamlitmNFK6xBZYlygjdye9dbd9rUlQ==",
"dev": true,
"requires": {
"@babel/helper-module-transforms": "^7.13.0",
"@babel/helper-module-transforms": "^7.14.0",
"@babel/helper-plugin-utils": "^7.13.0",
"@babel/helper-simple-access": "^7.12.13",
"@babel/helper-simple-access": "^7.13.12",
"babel-plugin-dynamic-import-node": "^2.3.3"
},
"dependencies": {
"@babel/generator": {
"version": "7.14.1",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.14.1.tgz",
"integrity": "sha512-TMGhsXMXCP/O1WtQmZjpEYDhCYC9vFhayWZPJSZCGkPJgUqX0rF0wwtrYvnzVxIjcF80tkUertXVk5cwqi5cAQ==",
"dev": true,
"requires": {
"@babel/types": "^7.14.1",
"jsesc": "^2.5.1",
"source-map": "^0.5.0"
}
},
"@babel/helper-module-transforms": {
"version": "7.14.0",
"resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.14.0.tgz",
"integrity": "sha512-L40t9bxIuGOfpIGA3HNkJhU9qYrf4y5A5LUSw7rGMSn+pcG8dfJ0g6Zval6YJGd2nEjI7oP00fRdnhLKndx6bw==",
"dev": true,
"requires": {
"@babel/helper-module-imports": "^7.13.12",
"@babel/helper-replace-supers": "^7.13.12",
"@babel/helper-simple-access": "^7.13.12",
"@babel/helper-split-export-declaration": "^7.12.13",
"@babel/helper-validator-identifier": "^7.14.0",
"@babel/template": "^7.12.13",
"@babel/traverse": "^7.14.0",
"@babel/types": "^7.14.0"
}
},
"@babel/helper-validator-identifier": {
"version": "7.14.0",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz",
"integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==",
"dev": true
},
"@babel/parser": {
"version": "7.14.1",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.1.tgz",
"integrity": "sha512-muUGEKu8E/ftMTPlNp+mc6zL3E9zKWmF5sDHZ5MSsoTP9Wyz64AhEf9kD08xYJ7w6Hdcu8H550ircnPyWSIF0Q==",
"dev": true
},
"@babel/traverse": {
"version": "7.14.0",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.14.0.tgz",
"integrity": "sha512-dZ/a371EE5XNhTHomvtuLTUyx6UEoJmYX+DT5zBCQN3McHemsuIaKKYqsc/fs26BEkHs/lBZy0J571LP5z9kQA==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.12.13",
"@babel/generator": "^7.14.0",
"@babel/helper-function-name": "^7.12.13",
"@babel/helper-split-export-declaration": "^7.12.13",
"@babel/parser": "^7.14.0",
"@babel/types": "^7.14.0",
"debug": "^4.1.0",
"globals": "^11.1.0"
}
},
"@babel/types": {
"version": "7.14.1",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.1.tgz",
"integrity": "sha512-S13Qe85fzLs3gYRUnrpyeIrBJIMYv33qSTg1qoBwiG6nPKwUWAD9odSzWhEedpwOIzSEI6gbdQIWEMiCI42iBA==",
"dev": true,
"requires": {
"@babel/helper-validator-identifier": "^7.14.0",
"to-fast-properties": "^2.0.0"
}
}
}
},
"@babel/plugin-transform-modules-systemjs": {
@ -758,13 +966,80 @@
}
},
"@babel/plugin-transform-modules-umd": {
"version": "7.13.0",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.13.0.tgz",
"integrity": "sha512-D/ILzAh6uyvkWjKKyFE/W0FzWwasv6vPTSqPcjxFqn6QpX3u8DjRVliq4F2BamO2Wee/om06Vyy+vPkNrd4wxw==",
"version": "7.14.0",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.14.0.tgz",
"integrity": "sha512-nPZdnWtXXeY7I87UZr9VlsWme3Y0cfFFE41Wbxz4bbaexAjNMInXPFUpRRUJ8NoMm0Cw+zxbqjdPmLhcjfazMw==",
"dev": true,
"requires": {
"@babel/helper-module-transforms": "^7.13.0",
"@babel/helper-module-transforms": "^7.14.0",
"@babel/helper-plugin-utils": "^7.13.0"
},
"dependencies": {
"@babel/generator": {
"version": "7.14.1",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.14.1.tgz",
"integrity": "sha512-TMGhsXMXCP/O1WtQmZjpEYDhCYC9vFhayWZPJSZCGkPJgUqX0rF0wwtrYvnzVxIjcF80tkUertXVk5cwqi5cAQ==",
"dev": true,
"requires": {
"@babel/types": "^7.14.1",
"jsesc": "^2.5.1",
"source-map": "^0.5.0"
}
},
"@babel/helper-module-transforms": {
"version": "7.14.0",
"resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.14.0.tgz",
"integrity": "sha512-L40t9bxIuGOfpIGA3HNkJhU9qYrf4y5A5LUSw7rGMSn+pcG8dfJ0g6Zval6YJGd2nEjI7oP00fRdnhLKndx6bw==",
"dev": true,
"requires": {
"@babel/helper-module-imports": "^7.13.12",
"@babel/helper-replace-supers": "^7.13.12",
"@babel/helper-simple-access": "^7.13.12",
"@babel/helper-split-export-declaration": "^7.12.13",
"@babel/helper-validator-identifier": "^7.14.0",
"@babel/template": "^7.12.13",
"@babel/traverse": "^7.14.0",
"@babel/types": "^7.14.0"
}
},
"@babel/helper-validator-identifier": {
"version": "7.14.0",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz",
"integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==",
"dev": true
},
"@babel/parser": {
"version": "7.14.1",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.1.tgz",
"integrity": "sha512-muUGEKu8E/ftMTPlNp+mc6zL3E9zKWmF5sDHZ5MSsoTP9Wyz64AhEf9kD08xYJ7w6Hdcu8H550ircnPyWSIF0Q==",
"dev": true
},
"@babel/traverse": {
"version": "7.14.0",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.14.0.tgz",
"integrity": "sha512-dZ/a371EE5XNhTHomvtuLTUyx6UEoJmYX+DT5zBCQN3McHemsuIaKKYqsc/fs26BEkHs/lBZy0J571LP5z9kQA==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.12.13",
"@babel/generator": "^7.14.0",
"@babel/helper-function-name": "^7.12.13",
"@babel/helper-split-export-declaration": "^7.12.13",
"@babel/parser": "^7.14.0",
"@babel/types": "^7.14.0",
"debug": "^4.1.0",
"globals": "^11.1.0"
}
},
"@babel/types": {
"version": "7.14.1",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.1.tgz",
"integrity": "sha512-S13Qe85fzLs3gYRUnrpyeIrBJIMYv33qSTg1qoBwiG6nPKwUWAD9odSzWhEedpwOIzSEI6gbdQIWEMiCI42iBA==",
"dev": true,
"requires": {
"@babel/helper-validator-identifier": "^7.14.0",
"to-fast-properties": "^2.0.0"
}
}
}
},
"@babel/plugin-transform-named-capturing-groups-regex": {
@ -911,18 +1186,19 @@
}
},
"@babel/preset-env": {
"version": "7.13.15",
"resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.13.15.tgz",
"integrity": "sha512-D4JAPMXcxk69PKe81jRJ21/fP/uYdcTZ3hJDF5QX2HSI9bBxxYw/dumdR6dGumhjxlprHPE4XWoPaqzZUVy2MA==",
"version": "7.14.1",
"resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.14.1.tgz",
"integrity": "sha512-0M4yL1l7V4l+j/UHvxcdvNfLB9pPtIooHTbEhgD/6UGyh8Hy3Bm1Mj0buzjDXATCSz3JFibVdnoJZCrlUCanrQ==",
"dev": true,
"requires": {
"@babel/compat-data": "^7.13.15",
"@babel/helper-compilation-targets": "^7.13.13",
"@babel/compat-data": "^7.14.0",
"@babel/helper-compilation-targets": "^7.13.16",
"@babel/helper-plugin-utils": "^7.13.0",
"@babel/helper-validator-option": "^7.12.17",
"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.13.12",
"@babel/plugin-proposal-async-generator-functions": "^7.13.15",
"@babel/plugin-proposal-class-properties": "^7.13.0",
"@babel/plugin-proposal-class-static-block": "^7.13.11",
"@babel/plugin-proposal-dynamic-import": "^7.13.8",
"@babel/plugin-proposal-export-namespace-from": "^7.12.13",
"@babel/plugin-proposal-json-strings": "^7.13.8",
@ -933,9 +1209,11 @@
"@babel/plugin-proposal-optional-catch-binding": "^7.13.8",
"@babel/plugin-proposal-optional-chaining": "^7.13.12",
"@babel/plugin-proposal-private-methods": "^7.13.0",
"@babel/plugin-proposal-private-property-in-object": "^7.14.0",
"@babel/plugin-proposal-unicode-property-regex": "^7.12.13",
"@babel/plugin-syntax-async-generators": "^7.8.4",
"@babel/plugin-syntax-class-properties": "^7.12.13",
"@babel/plugin-syntax-class-static-block": "^7.12.13",
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
"@babel/plugin-syntax-export-namespace-from": "^7.8.3",
"@babel/plugin-syntax-json-strings": "^7.8.3",
@ -945,14 +1223,15 @@
"@babel/plugin-syntax-object-rest-spread": "^7.8.3",
"@babel/plugin-syntax-optional-catch-binding": "^7.8.3",
"@babel/plugin-syntax-optional-chaining": "^7.8.3",
"@babel/plugin-syntax-private-property-in-object": "^7.14.0",
"@babel/plugin-syntax-top-level-await": "^7.12.13",
"@babel/plugin-transform-arrow-functions": "^7.13.0",
"@babel/plugin-transform-async-to-generator": "^7.13.0",
"@babel/plugin-transform-block-scoped-functions": "^7.12.13",
"@babel/plugin-transform-block-scoping": "^7.12.13",
"@babel/plugin-transform-block-scoping": "^7.14.1",
"@babel/plugin-transform-classes": "^7.13.0",
"@babel/plugin-transform-computed-properties": "^7.13.0",
"@babel/plugin-transform-destructuring": "^7.13.0",
"@babel/plugin-transform-destructuring": "^7.13.17",
"@babel/plugin-transform-dotall-regex": "^7.12.13",
"@babel/plugin-transform-duplicate-keys": "^7.12.13",
"@babel/plugin-transform-exponentiation-operator": "^7.12.13",
@ -960,10 +1239,10 @@
"@babel/plugin-transform-function-name": "^7.12.13",
"@babel/plugin-transform-literals": "^7.12.13",
"@babel/plugin-transform-member-expression-literals": "^7.12.13",
"@babel/plugin-transform-modules-amd": "^7.13.0",
"@babel/plugin-transform-modules-commonjs": "^7.13.8",
"@babel/plugin-transform-modules-amd": "^7.14.0",
"@babel/plugin-transform-modules-commonjs": "^7.14.0",
"@babel/plugin-transform-modules-systemjs": "^7.13.8",
"@babel/plugin-transform-modules-umd": "^7.13.0",
"@babel/plugin-transform-modules-umd": "^7.14.0",
"@babel/plugin-transform-named-capturing-groups-regex": "^7.12.13",
"@babel/plugin-transform-new-target": "^7.12.13",
"@babel/plugin-transform-object-super": "^7.12.13",
@ -979,12 +1258,48 @@
"@babel/plugin-transform-unicode-escapes": "^7.12.13",
"@babel/plugin-transform-unicode-regex": "^7.12.13",
"@babel/preset-modules": "^0.1.4",
"@babel/types": "^7.13.14",
"@babel/types": "^7.14.1",
"babel-plugin-polyfill-corejs2": "^0.2.0",
"babel-plugin-polyfill-corejs3": "^0.2.0",
"babel-plugin-polyfill-regenerator": "^0.2.0",
"core-js-compat": "^3.9.0",
"semver": "^6.3.0"
},
"dependencies": {
"@babel/compat-data": {
"version": "7.14.0",
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.14.0.tgz",
"integrity": "sha512-vu9V3uMM/1o5Hl5OekMUowo3FqXLJSw+s+66nt0fSWVWTtmosdzn45JHOB3cPtZoe6CTBDzvSw0RdOY85Q37+Q==",
"dev": true
},
"@babel/helper-compilation-targets": {
"version": "7.13.16",
"resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.13.16.tgz",
"integrity": "sha512-3gmkYIrpqsLlieFwjkGgLaSHmhnvlAYzZLlYVjlW+QwI+1zE17kGxuJGmIqDQdYp56XdmGeD+Bswx0UTyG18xA==",
"dev": true,
"requires": {
"@babel/compat-data": "^7.13.15",
"@babel/helper-validator-option": "^7.12.17",
"browserslist": "^4.14.5",
"semver": "^6.3.0"
}
},
"@babel/helper-validator-identifier": {
"version": "7.14.0",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz",
"integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==",
"dev": true
},
"@babel/types": {
"version": "7.14.1",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.1.tgz",
"integrity": "sha512-S13Qe85fzLs3gYRUnrpyeIrBJIMYv33qSTg1qoBwiG6nPKwUWAD9odSzWhEedpwOIzSEI6gbdQIWEMiCI42iBA==",
"dev": true,
"requires": {
"@babel/helper-validator-identifier": "^7.14.0",
"to-fast-properties": "^2.0.0"
}
}
}
},
"@babel/preset-modules": {
@ -1001,9 +1316,9 @@
}
},
"@babel/runtime": {
"version": "7.13.10",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.10.tgz",
"integrity": "sha512-4QPkjJq6Ns3V/RgpEahRk+AGfL0eO6RHHtTWoNNr5mO49G6B5+X6d6THgWEAvTrznU5xYpbAlVKRYcsCgh/Akw==",
"version": "7.14.0",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.0.tgz",
"integrity": "sha512-JELkvo/DlpNdJ7dlyw/eY7E0suy5i5GQH+Vlxaq1nsNJ+H7f4Vtv3jMeCEgRhZZQFXTjldYfQgv2qmM6M1v5wA==",
"dev": true,
"requires": {
"regenerator-runtime": "^0.13.4"
@ -2665,9 +2980,9 @@
"dev": true
},
"detox": {
"version": "18.11.2",
"resolved": "https://registry.npmjs.org/detox/-/detox-18.11.2.tgz",
"integrity": "sha512-zEm4sdz6ItKIzWByfLldPzk8SLE562l+/nRKUBfV9fXzys6VeZ7YKb1YbMmC2JF0slmR4rIqCr9Fji4laDwE6w==",
"version": "18.13.0",
"resolved": "https://registry.npmjs.org/detox/-/detox-18.13.0.tgz",
"integrity": "sha512-YQPhi+uUGhVXYQm4W76EyKXdDKXnxq3dO+9ua22gGhNGwiJDbV8TUOavZNMbjBKWLb+OueGKOEBp4uNGOrVANw==",
"dev": true,
"requires": {
"bunyan": "^1.8.12",
@ -2684,6 +2999,7 @@
"proper-lockfile": "^3.0.2",
"resolve-from": "^5.0.0",
"sanitize-filename": "^1.6.1",
"semver": "^7.0.0",
"serialize-error": "^8.0.1",
"shell-quote": "^1.7.2",
"signal-exit": "^3.0.3",
@ -2694,6 +3010,32 @@
"ws": "^7.0.0",
"yargs": "^16.0.3",
"yargs-unparser": "^2.0.0"
},
"dependencies": {
"lru-cache": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
"dev": true,
"requires": {
"yallist": "^4.0.0"
}
},
"semver": {
"version": "7.3.5",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
"integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
"dev": true,
"requires": {
"lru-cache": "^6.0.0"
}
},
"yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"dev": true
}
}
},
"diff-sequences": {
@ -4334,9 +4676,9 @@
}
},
"jest-html-reporters": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/jest-html-reporters/-/jest-html-reporters-2.1.3.tgz",
"integrity": "sha512-46QGqnILYTlkFINsYnQ333VGZqFhi9pUHY7T3G/66U3iQm725pm+HHMsWBIN/XgXEkIP9jsEKlCg6kg4pAAUrA==",
"version": "2.1.6",
"resolved": "https://registry.npmjs.org/jest-html-reporters/-/jest-html-reporters-2.1.6.tgz",
"integrity": "sha512-L81yXCctu0clmRl2rDeq5nWdH6Sy1U0IJgf+wy6wUTPcCmfg3JIfJnTug0mWSgQqtk0I5IMZ7Z+c4317uMNgMw==",
"dev": true,
"requires": {
"fs-extra": "^9.0.1",
@ -5905,9 +6247,9 @@
}
},
"open": {
"version": "8.0.5",
"resolved": "https://registry.npmjs.org/open/-/open-8.0.5.tgz",
"integrity": "sha512-hkPXCz7gijWp2GoWqsQ4O/5p7F6d5pIQ/+9NyeWG1nABJ4zvLi9kJRv1a44kVf5p13wK0WMoiRA+Xey68yOytA==",
"version": "8.0.8",
"resolved": "https://registry.npmjs.org/open/-/open-8.0.8.tgz",
"integrity": "sha512-3XmKIU8+H/TVr8wB8C4vj0z748+yBydSvtpzZVS6vQ1dKNHB6AiPbhaoG+89zb80717GPk9y/7OvK0R6FXkNmQ==",
"dev": true,
"requires": {
"define-lazy-prop": "^2.0.0",
@ -6789,9 +7131,9 @@
"dev": true
},
"serialize-error": {
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-8.0.1.tgz",
"integrity": "sha512-r5o60rWFS+8/b49DNAbB+GXZA0SpDpuWE758JxDKgRTga05r3U5lwyksE91dYKDhXSmnu36RALj615E6Aj5pSg==",
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-8.1.0.tgz",
"integrity": "sha512-3NnuWfM6vBYoy5gZFvHiYsVbafvI9vZv/+jlIigFn4oP4zjNPK3LhcY0xSCgeb1a5L8jO71Mit9LlNoi2UfDDQ==",
"dev": true,
"requires": {
"type-fest": "^0.20.2"

View file

@ -5,20 +5,20 @@
"author": "Mattermost, Inc.",
"devDependencies": {
"@babel/plugin-proposal-class-properties": "7.13.0",
"@babel/plugin-transform-modules-commonjs": "7.13.8",
"@babel/plugin-transform-modules-commonjs": "7.14.0",
"@babel/plugin-transform-runtime": "7.13.15",
"@babel/preset-env": "7.13.15",
"@babel/preset-env": "7.14.1",
"axios": "0.21.1",
"babel-jest": "26.6.3",
"babel-plugin-module-resolver": "4.1.0",
"client-oauth2": "github:larkox/js-client-oauth2#e24e2eb5dfcbbbb3a59d095e831dbe0012b0ac49",
"deepmerge": "4.2.2",
"detox": "18.11.2",
"detox": "18.13.0",
"form-data": "4.0.0",
"jest": "26.6.3",
"jest-circus": "26.6.3",
"jest-cli": "26.6.3",
"jest-html-reporters": "2.1.3",
"jest-html-reporters": "2.1.6",
"jest-junit": "12.0.0",
"sanitize-filename": "1.6.3",
"uuid": "8.3.2"

View file

@ -592,7 +592,6 @@ platform :android do
unless configured
configure
end
configure_telemetry_android
update_identifiers
replace_assets
link_sentry_android
@ -622,27 +621,6 @@ platform :android do
sh "mv #{lane_context[SharedValues::GRADLE_APK_OUTPUT_PATH]} #{Pathname.new(File.expand_path(File.dirname(__FILE__))).parent.to_s}/Mattermost-unsigned.apk"
end
desc 'Update config and module/listener for Android telemetry'
lane :configure_telemetry_android do
if ENV['TELEMETRY_ENABLED'] == 'true' && ENV['TELEMETRY_URL'] != '' && ENV['TELEMETRY_API_KEY'] != ''
# Update telemetry config
json = load_config_json('../dist/assets/config.json')
json['TelemetryEnabled'] = true
json['TelemetryUrl'] = ENV['TELEMETRY_URL']
json['TelemetryApiKey'] = ENV['TELEMETRY_API_KEY']
save_json_as_file('../dist/assets/config.json', json)
beta_dir = './android/app/src/main/java/com/mattermost/rnbeta/'
# Listen to telemetry react markers
find_replace_string(
path_to_file: "#{beta_dir}MainApplication.java",
old_string: '// addReactMarkerListener();',
new_string: 'addReactMarkerListener();'
)
end
end
lane :update_identifiers do
# Set the name for the app
app_name = ENV['APP_NAME'] || 'Mattermost Beta'

View file

@ -2,12 +2,10 @@
// See LICENSE.txt for license information.
import 'react-native/Libraries/Core/InitializeCore';
import {DeviceEventEmitter, Platform, Text} from 'react-native';
import {Platform, Text} from 'react-native';
import 'react-native-gesture-handler';
import LocalConfig from '@assets/config';
import 'app/mattermost';
import telemetry from 'app/telemetry';
if (Platform.OS === 'android') {
require('harmony-reflect');
@ -18,9 +16,9 @@ if (__DEV__) {
LogBox.ignoreLogs([
'Warning: componentWillReceiveProps',
'Warning: componentWillMount',
'Warning: StatusBarIOS',
'`-[RCTRootView cancelTouches]`',
'Animated',
'If you want to use Reanimated 2 then go through our installation steps https://docs.swmansion.com/react-native-reanimated/docs/installation',
// Hide warnings caused by React Native (https://github.com/facebook/react-native/issues/20841)
'Require cycle: node_modules/react-native/Libraries/Network/fetch.js',
@ -58,19 +56,6 @@ if (Platform.OS === 'android') {
const AppRegistry = require('react-native/Libraries/ReactNative/AppRegistry');
AppRegistry.registerComponent('MattermostShare', () => ShareExtension);
setFontFamily();
if (LocalConfig.TelemetryEnabled) {
const metricsSubscription = DeviceEventEmitter.addListener('nativeMetrics', (metrics) => {
telemetry.setAppStartTime(metrics.appReload);
telemetry.include([
{name: 'start:process_packages', startTime: metrics.processPackagesStart, endTime: metrics.processPackagesEnd},
{name: 'start:content_appeared', startTime: metrics.appReload, endTime: metrics.appContentAppeared},
]);
telemetry.start(['start:overall'], metrics.appReload);
DeviceEventEmitter.removeSubscription(metricsSubscription);
});
}
}
// Uncomment the snippet below if you want to update the modules

View file

@ -3,17 +3,17 @@ PODS:
- BVLinearGradient (2.5.6):
- React
- DoubleConversion (1.1.6)
- FBLazyVector (0.64.0)
- FBReactNativeSpec (0.64.0):
- FBLazyVector (0.64.1)
- FBReactNativeSpec (0.64.1):
- RCT-Folly (= 2020.01.13.00)
- RCTRequired (= 0.64.0)
- RCTTypeSafety (= 0.64.0)
- React-Core (= 0.64.0)
- React-jsi (= 0.64.0)
- ReactCommon/turbomodule/core (= 0.64.0)
- RCTRequired (= 0.64.1)
- RCTTypeSafety (= 0.64.1)
- React-Core (= 0.64.1)
- React-jsi (= 0.64.1)
- ReactCommon/turbomodule/core (= 0.64.1)
- glog (0.3.5)
- jail-monkey (2.3.3):
- React
- jail-monkey (2.3.4):
- React-Core
- libwebp (1.2.0):
- libwebp/demux (= 1.2.0)
- libwebp/mux (= 1.2.0)
@ -26,17 +26,17 @@ PODS:
- MMKV (1.2.7):
- MMKVCore (~> 1.2.7)
- MMKVCore (1.2.7)
- Permission-Camera (3.0.1):
- Permission-Camera (3.0.3):
- RNPermissions
- Permission-MediaLibrary (3.0.1):
- Permission-MediaLibrary (3.0.3):
- RNPermissions
- Permission-Microphone (3.0.1):
- Permission-Microphone (3.0.3):
- RNPermissions
- Permission-Notifications (3.0.1):
- Permission-Notifications (3.0.3):
- RNPermissions
- Permission-PhotoLibrary (3.0.1):
- Permission-PhotoLibrary (3.0.3):
- RNPermissions
- Permission-PhotoLibraryAddOnly (3.0.1):
- Permission-PhotoLibraryAddOnly (3.0.3):
- RNPermissions
- RCT-Folly (2020.01.13.00):
- boost-for-react-native
@ -47,193 +47,193 @@ PODS:
- boost-for-react-native
- DoubleConversion
- glog
- RCTRequired (0.64.0)
- RCTTypeSafety (0.64.0):
- FBLazyVector (= 0.64.0)
- RCTRequired (0.64.1)
- RCTTypeSafety (0.64.1):
- FBLazyVector (= 0.64.1)
- RCT-Folly (= 2020.01.13.00)
- RCTRequired (= 0.64.0)
- React-Core (= 0.64.0)
- RCTRequired (= 0.64.1)
- React-Core (= 0.64.1)
- RCTYouTube (2.0.1):
- React
- YoutubePlayer-in-WKWebView (~> 0.3.1)
- React (0.64.0):
- React-Core (= 0.64.0)
- React-Core/DevSupport (= 0.64.0)
- React-Core/RCTWebSocket (= 0.64.0)
- React-RCTActionSheet (= 0.64.0)
- React-RCTAnimation (= 0.64.0)
- React-RCTBlob (= 0.64.0)
- React-RCTImage (= 0.64.0)
- React-RCTLinking (= 0.64.0)
- React-RCTNetwork (= 0.64.0)
- React-RCTSettings (= 0.64.0)
- React-RCTText (= 0.64.0)
- React-RCTVibration (= 0.64.0)
- React-callinvoker (0.64.0)
- React-Core (0.64.0):
- React (0.64.1):
- React-Core (= 0.64.1)
- React-Core/DevSupport (= 0.64.1)
- React-Core/RCTWebSocket (= 0.64.1)
- React-RCTActionSheet (= 0.64.1)
- React-RCTAnimation (= 0.64.1)
- React-RCTBlob (= 0.64.1)
- React-RCTImage (= 0.64.1)
- React-RCTLinking (= 0.64.1)
- React-RCTNetwork (= 0.64.1)
- React-RCTSettings (= 0.64.1)
- React-RCTText (= 0.64.1)
- React-RCTVibration (= 0.64.1)
- React-callinvoker (0.64.1)
- React-Core (0.64.1):
- glog
- RCT-Folly (= 2020.01.13.00)
- React-Core/Default (= 0.64.0)
- React-cxxreact (= 0.64.0)
- React-jsi (= 0.64.0)
- React-jsiexecutor (= 0.64.0)
- React-perflogger (= 0.64.0)
- React-Core/Default (= 0.64.1)
- React-cxxreact (= 0.64.1)
- React-jsi (= 0.64.1)
- React-jsiexecutor (= 0.64.1)
- React-perflogger (= 0.64.1)
- Yoga
- React-Core/CoreModulesHeaders (0.64.0):
- React-Core/CoreModulesHeaders (0.64.1):
- glog
- RCT-Folly (= 2020.01.13.00)
- React-Core/Default
- React-cxxreact (= 0.64.0)
- React-jsi (= 0.64.0)
- React-jsiexecutor (= 0.64.0)
- React-perflogger (= 0.64.0)
- React-cxxreact (= 0.64.1)
- React-jsi (= 0.64.1)
- React-jsiexecutor (= 0.64.1)
- React-perflogger (= 0.64.1)
- Yoga
- React-Core/Default (0.64.0):
- React-Core/Default (0.64.1):
- glog
- RCT-Folly (= 2020.01.13.00)
- React-cxxreact (= 0.64.0)
- React-jsi (= 0.64.0)
- React-jsiexecutor (= 0.64.0)
- React-perflogger (= 0.64.0)
- React-cxxreact (= 0.64.1)
- React-jsi (= 0.64.1)
- React-jsiexecutor (= 0.64.1)
- React-perflogger (= 0.64.1)
- Yoga
- React-Core/DevSupport (0.64.0):
- React-Core/DevSupport (0.64.1):
- glog
- RCT-Folly (= 2020.01.13.00)
- React-Core/Default (= 0.64.0)
- React-Core/RCTWebSocket (= 0.64.0)
- React-cxxreact (= 0.64.0)
- React-jsi (= 0.64.0)
- React-jsiexecutor (= 0.64.0)
- React-jsinspector (= 0.64.0)
- React-perflogger (= 0.64.0)
- React-Core/Default (= 0.64.1)
- React-Core/RCTWebSocket (= 0.64.1)
- React-cxxreact (= 0.64.1)
- React-jsi (= 0.64.1)
- React-jsiexecutor (= 0.64.1)
- React-jsinspector (= 0.64.1)
- React-perflogger (= 0.64.1)
- Yoga
- React-Core/RCTActionSheetHeaders (0.64.0):
- React-Core/RCTActionSheetHeaders (0.64.1):
- glog
- RCT-Folly (= 2020.01.13.00)
- React-Core/Default
- React-cxxreact (= 0.64.0)
- React-jsi (= 0.64.0)
- React-jsiexecutor (= 0.64.0)
- React-perflogger (= 0.64.0)
- React-cxxreact (= 0.64.1)
- React-jsi (= 0.64.1)
- React-jsiexecutor (= 0.64.1)
- React-perflogger (= 0.64.1)
- Yoga
- React-Core/RCTAnimationHeaders (0.64.0):
- React-Core/RCTAnimationHeaders (0.64.1):
- glog
- RCT-Folly (= 2020.01.13.00)
- React-Core/Default
- React-cxxreact (= 0.64.0)
- React-jsi (= 0.64.0)
- React-jsiexecutor (= 0.64.0)
- React-perflogger (= 0.64.0)
- React-cxxreact (= 0.64.1)
- React-jsi (= 0.64.1)
- React-jsiexecutor (= 0.64.1)
- React-perflogger (= 0.64.1)
- Yoga
- React-Core/RCTBlobHeaders (0.64.0):
- React-Core/RCTBlobHeaders (0.64.1):
- glog
- RCT-Folly (= 2020.01.13.00)
- React-Core/Default
- React-cxxreact (= 0.64.0)
- React-jsi (= 0.64.0)
- React-jsiexecutor (= 0.64.0)
- React-perflogger (= 0.64.0)
- React-cxxreact (= 0.64.1)
- React-jsi (= 0.64.1)
- React-jsiexecutor (= 0.64.1)
- React-perflogger (= 0.64.1)
- Yoga
- React-Core/RCTImageHeaders (0.64.0):
- React-Core/RCTImageHeaders (0.64.1):
- glog
- RCT-Folly (= 2020.01.13.00)
- React-Core/Default
- React-cxxreact (= 0.64.0)
- React-jsi (= 0.64.0)
- React-jsiexecutor (= 0.64.0)
- React-perflogger (= 0.64.0)
- React-cxxreact (= 0.64.1)
- React-jsi (= 0.64.1)
- React-jsiexecutor (= 0.64.1)
- React-perflogger (= 0.64.1)
- Yoga
- React-Core/RCTLinkingHeaders (0.64.0):
- React-Core/RCTLinkingHeaders (0.64.1):
- glog
- RCT-Folly (= 2020.01.13.00)
- React-Core/Default
- React-cxxreact (= 0.64.0)
- React-jsi (= 0.64.0)
- React-jsiexecutor (= 0.64.0)
- React-perflogger (= 0.64.0)
- React-cxxreact (= 0.64.1)
- React-jsi (= 0.64.1)
- React-jsiexecutor (= 0.64.1)
- React-perflogger (= 0.64.1)
- Yoga
- React-Core/RCTNetworkHeaders (0.64.0):
- React-Core/RCTNetworkHeaders (0.64.1):
- glog
- RCT-Folly (= 2020.01.13.00)
- React-Core/Default
- React-cxxreact (= 0.64.0)
- React-jsi (= 0.64.0)
- React-jsiexecutor (= 0.64.0)
- React-perflogger (= 0.64.0)
- React-cxxreact (= 0.64.1)
- React-jsi (= 0.64.1)
- React-jsiexecutor (= 0.64.1)
- React-perflogger (= 0.64.1)
- Yoga
- React-Core/RCTSettingsHeaders (0.64.0):
- React-Core/RCTSettingsHeaders (0.64.1):
- glog
- RCT-Folly (= 2020.01.13.00)
- React-Core/Default
- React-cxxreact (= 0.64.0)
- React-jsi (= 0.64.0)
- React-jsiexecutor (= 0.64.0)
- React-perflogger (= 0.64.0)
- React-cxxreact (= 0.64.1)
- React-jsi (= 0.64.1)
- React-jsiexecutor (= 0.64.1)
- React-perflogger (= 0.64.1)
- Yoga
- React-Core/RCTTextHeaders (0.64.0):
- React-Core/RCTTextHeaders (0.64.1):
- glog
- RCT-Folly (= 2020.01.13.00)
- React-Core/Default
- React-cxxreact (= 0.64.0)
- React-jsi (= 0.64.0)
- React-jsiexecutor (= 0.64.0)
- React-perflogger (= 0.64.0)
- React-cxxreact (= 0.64.1)
- React-jsi (= 0.64.1)
- React-jsiexecutor (= 0.64.1)
- React-perflogger (= 0.64.1)
- Yoga
- React-Core/RCTVibrationHeaders (0.64.0):
- React-Core/RCTVibrationHeaders (0.64.1):
- glog
- RCT-Folly (= 2020.01.13.00)
- React-Core/Default
- React-cxxreact (= 0.64.0)
- React-jsi (= 0.64.0)
- React-jsiexecutor (= 0.64.0)
- React-perflogger (= 0.64.0)
- React-cxxreact (= 0.64.1)
- React-jsi (= 0.64.1)
- React-jsiexecutor (= 0.64.1)
- React-perflogger (= 0.64.1)
- Yoga
- React-Core/RCTWebSocket (0.64.0):
- React-Core/RCTWebSocket (0.64.1):
- glog
- RCT-Folly (= 2020.01.13.00)
- React-Core/Default (= 0.64.0)
- React-cxxreact (= 0.64.0)
- React-jsi (= 0.64.0)
- React-jsiexecutor (= 0.64.0)
- React-perflogger (= 0.64.0)
- React-Core/Default (= 0.64.1)
- React-cxxreact (= 0.64.1)
- React-jsi (= 0.64.1)
- React-jsiexecutor (= 0.64.1)
- React-perflogger (= 0.64.1)
- Yoga
- React-CoreModules (0.64.0):
- FBReactNativeSpec (= 0.64.0)
- React-CoreModules (0.64.1):
- FBReactNativeSpec (= 0.64.1)
- RCT-Folly (= 2020.01.13.00)
- RCTTypeSafety (= 0.64.0)
- React-Core/CoreModulesHeaders (= 0.64.0)
- React-jsi (= 0.64.0)
- React-RCTImage (= 0.64.0)
- ReactCommon/turbomodule/core (= 0.64.0)
- React-cxxreact (0.64.0):
- RCTTypeSafety (= 0.64.1)
- React-Core/CoreModulesHeaders (= 0.64.1)
- React-jsi (= 0.64.1)
- React-RCTImage (= 0.64.1)
- ReactCommon/turbomodule/core (= 0.64.1)
- React-cxxreact (0.64.1):
- boost-for-react-native (= 1.63.0)
- DoubleConversion
- glog
- RCT-Folly (= 2020.01.13.00)
- React-callinvoker (= 0.64.0)
- React-jsi (= 0.64.0)
- React-jsinspector (= 0.64.0)
- React-perflogger (= 0.64.0)
- React-runtimeexecutor (= 0.64.0)
- React-jsi (0.64.0):
- React-callinvoker (= 0.64.1)
- React-jsi (= 0.64.1)
- React-jsinspector (= 0.64.1)
- React-perflogger (= 0.64.1)
- React-runtimeexecutor (= 0.64.1)
- React-jsi (0.64.1):
- boost-for-react-native (= 1.63.0)
- DoubleConversion
- glog
- RCT-Folly (= 2020.01.13.00)
- React-jsi/Default (= 0.64.0)
- React-jsi/Default (0.64.0):
- React-jsi/Default (= 0.64.1)
- React-jsi/Default (0.64.1):
- boost-for-react-native (= 1.63.0)
- DoubleConversion
- glog
- RCT-Folly (= 2020.01.13.00)
- React-jsiexecutor (0.64.0):
- React-jsiexecutor (0.64.1):
- DoubleConversion
- glog
- RCT-Folly (= 2020.01.13.00)
- React-cxxreact (= 0.64.0)
- React-jsi (= 0.64.0)
- React-perflogger (= 0.64.0)
- React-jsinspector (0.64.0)
- React-cxxreact (= 0.64.1)
- React-jsi (= 0.64.1)
- React-perflogger (= 0.64.1)
- React-jsinspector (0.64.1)
- react-native-cameraroll (4.0.4):
- React-Core
- react-native-cookies (3.2.0):
@ -259,6 +259,8 @@ PODS:
- React
- react-native-safe-area-context (3.2.0):
- React-Core
- react-native-startup-time (2.0.0):
- React
- react-native-video (5.1.1):
- React-Core
- react-native-video/Video (= 5.1.1)
@ -266,80 +268,80 @@ PODS:
- React-Core
- react-native-webview (7.0.1):
- React
- React-perflogger (0.64.0)
- React-RCTActionSheet (0.64.0):
- React-Core/RCTActionSheetHeaders (= 0.64.0)
- React-RCTAnimation (0.64.0):
- FBReactNativeSpec (= 0.64.0)
- React-perflogger (0.64.1)
- React-RCTActionSheet (0.64.1):
- React-Core/RCTActionSheetHeaders (= 0.64.1)
- React-RCTAnimation (0.64.1):
- FBReactNativeSpec (= 0.64.1)
- RCT-Folly (= 2020.01.13.00)
- RCTTypeSafety (= 0.64.0)
- React-Core/RCTAnimationHeaders (= 0.64.0)
- React-jsi (= 0.64.0)
- ReactCommon/turbomodule/core (= 0.64.0)
- React-RCTBlob (0.64.0):
- FBReactNativeSpec (= 0.64.0)
- RCTTypeSafety (= 0.64.1)
- React-Core/RCTAnimationHeaders (= 0.64.1)
- React-jsi (= 0.64.1)
- ReactCommon/turbomodule/core (= 0.64.1)
- React-RCTBlob (0.64.1):
- FBReactNativeSpec (= 0.64.1)
- RCT-Folly (= 2020.01.13.00)
- React-Core/RCTBlobHeaders (= 0.64.0)
- React-Core/RCTWebSocket (= 0.64.0)
- React-jsi (= 0.64.0)
- React-RCTNetwork (= 0.64.0)
- ReactCommon/turbomodule/core (= 0.64.0)
- React-RCTImage (0.64.0):
- FBReactNativeSpec (= 0.64.0)
- React-Core/RCTBlobHeaders (= 0.64.1)
- React-Core/RCTWebSocket (= 0.64.1)
- React-jsi (= 0.64.1)
- React-RCTNetwork (= 0.64.1)
- ReactCommon/turbomodule/core (= 0.64.1)
- React-RCTImage (0.64.1):
- FBReactNativeSpec (= 0.64.1)
- RCT-Folly (= 2020.01.13.00)
- RCTTypeSafety (= 0.64.0)
- React-Core/RCTImageHeaders (= 0.64.0)
- React-jsi (= 0.64.0)
- React-RCTNetwork (= 0.64.0)
- ReactCommon/turbomodule/core (= 0.64.0)
- React-RCTLinking (0.64.0):
- FBReactNativeSpec (= 0.64.0)
- React-Core/RCTLinkingHeaders (= 0.64.0)
- React-jsi (= 0.64.0)
- ReactCommon/turbomodule/core (= 0.64.0)
- React-RCTNetwork (0.64.0):
- FBReactNativeSpec (= 0.64.0)
- RCTTypeSafety (= 0.64.1)
- React-Core/RCTImageHeaders (= 0.64.1)
- React-jsi (= 0.64.1)
- React-RCTNetwork (= 0.64.1)
- ReactCommon/turbomodule/core (= 0.64.1)
- React-RCTLinking (0.64.1):
- FBReactNativeSpec (= 0.64.1)
- React-Core/RCTLinkingHeaders (= 0.64.1)
- React-jsi (= 0.64.1)
- ReactCommon/turbomodule/core (= 0.64.1)
- React-RCTNetwork (0.64.1):
- FBReactNativeSpec (= 0.64.1)
- RCT-Folly (= 2020.01.13.00)
- RCTTypeSafety (= 0.64.0)
- React-Core/RCTNetworkHeaders (= 0.64.0)
- React-jsi (= 0.64.0)
- ReactCommon/turbomodule/core (= 0.64.0)
- React-RCTSettings (0.64.0):
- FBReactNativeSpec (= 0.64.0)
- RCTTypeSafety (= 0.64.1)
- React-Core/RCTNetworkHeaders (= 0.64.1)
- React-jsi (= 0.64.1)
- ReactCommon/turbomodule/core (= 0.64.1)
- React-RCTSettings (0.64.1):
- FBReactNativeSpec (= 0.64.1)
- RCT-Folly (= 2020.01.13.00)
- RCTTypeSafety (= 0.64.0)
- React-Core/RCTSettingsHeaders (= 0.64.0)
- React-jsi (= 0.64.0)
- ReactCommon/turbomodule/core (= 0.64.0)
- React-RCTText (0.64.0):
- React-Core/RCTTextHeaders (= 0.64.0)
- React-RCTVibration (0.64.0):
- FBReactNativeSpec (= 0.64.0)
- RCTTypeSafety (= 0.64.1)
- React-Core/RCTSettingsHeaders (= 0.64.1)
- React-jsi (= 0.64.1)
- ReactCommon/turbomodule/core (= 0.64.1)
- React-RCTText (0.64.1):
- React-Core/RCTTextHeaders (= 0.64.1)
- React-RCTVibration (0.64.1):
- FBReactNativeSpec (= 0.64.1)
- RCT-Folly (= 2020.01.13.00)
- React-Core/RCTVibrationHeaders (= 0.64.0)
- React-jsi (= 0.64.0)
- ReactCommon/turbomodule/core (= 0.64.0)
- React-runtimeexecutor (0.64.0):
- React-jsi (= 0.64.0)
- ReactCommon/turbomodule/core (0.64.0):
- React-Core/RCTVibrationHeaders (= 0.64.1)
- React-jsi (= 0.64.1)
- ReactCommon/turbomodule/core (= 0.64.1)
- React-runtimeexecutor (0.64.1):
- React-jsi (= 0.64.1)
- ReactCommon/turbomodule/core (0.64.1):
- DoubleConversion
- glog
- RCT-Folly (= 2020.01.13.00)
- React-callinvoker (= 0.64.0)
- React-Core (= 0.64.0)
- React-cxxreact (= 0.64.0)
- React-jsi (= 0.64.0)
- React-perflogger (= 0.64.0)
- React-callinvoker (= 0.64.1)
- React-Core (= 0.64.1)
- React-cxxreact (= 0.64.1)
- React-jsi (= 0.64.1)
- React-perflogger (= 0.64.1)
- ReactNativeExceptionHandler (2.10.10):
- React-Core
- ReactNativeKeyboardTrackingView (5.7.0):
- React
- ReactNativeNavigation (7.11.3):
- ReactNativeNavigation (7.14.0):
- React-Core
- React-RCTImage
- React-RCTText
- ReactNativeNavigation/Core (= 7.11.3)
- ReactNativeNavigation/Core (7.11.3):
- ReactNativeNavigation/Core (= 7.14.0)
- ReactNativeNavigation/Core (7.14.0):
- React-Core
- React-RCTImage
- React-RCTText
@ -349,9 +351,9 @@ PODS:
- React-Core
- RNCClipboard (1.5.1):
- React-Core
- RNCMaskedView (0.1.10):
- RNCMaskedView (0.1.11):
- React
- RNDeviceInfo (8.0.8):
- RNDeviceInfo (8.1.3):
- React-Core
- RNDevMenu (4.0.2):
- React-Core
@ -365,27 +367,54 @@ PODS:
- React-Core
- RNGestureHandler (1.10.3):
- React-Core
- RNKeychain (6.2.0):
- React
- RNLocalize (2.0.2):
- RNKeychain (7.0.0):
- React-Core
- RNPermissions (3.0.1):
- RNLocalize (2.0.3):
- React-Core
- RNPermissions (3.0.3):
- React-Core
- RNReactNativeHapticFeedback (1.11.0):
- React-Core
- RNReanimated (1.13.2):
- RNReanimated (2.1.0):
- DoubleConversion
- FBLazyVector
- FBReactNativeSpec
- glog
- RCT-Folly
- RCTRequired
- RCTTypeSafety
- React
- React-callinvoker
- React-Core
- React-Core/DevSupport
- React-Core/RCTWebSocket
- React-CoreModules
- React-cxxreact
- React-jsi
- React-jsiexecutor
- React-jsinspector
- React-RCTActionSheet
- React-RCTAnimation
- React-RCTBlob
- React-RCTImage
- React-RCTLinking
- React-RCTNetwork
- React-RCTSettings
- React-RCTText
- React-RCTVibration
- ReactCommon/turbomodule/core
- Yoga
- RNRudderSdk (1.0.0):
- React
- Rudder
- RNScreens (3.0.0):
- RNScreens (3.1.1):
- React-Core
- RNSentry (2.4.0):
- RNSentry (2.4.2):
- React-Core
- Sentry (= 6.1.4)
- RNShare (5.1.7):
- RNShare (6.0.1):
- React-Core
- RNSVG (12.1.0):
- RNSVG (12.1.1):
- React
- RNVectorIcons (8.1.0):
- React-Core
@ -443,6 +472,7 @@ DEPENDENCIES:
- react-native-passcode-status (from `../node_modules/react-native-passcode-status`)
- react-native-safe-area (from `../node_modules/react-native-safe-area`)
- react-native-safe-area-context (from `../node_modules/react-native-safe-area-context`)
- react-native-startup-time (from `../node_modules/react-native-startup-time`)
- react-native-video (from `../node_modules/react-native-video`)
- react-native-webview (from `../node_modules/react-native-webview`)
- React-perflogger (from `../node_modules/react-native/ReactCommon/reactperflogger`)
@ -571,6 +601,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native-safe-area"
react-native-safe-area-context:
:path: "../node_modules/react-native-safe-area-context"
react-native-startup-time:
:path: "../node_modules/react-native-startup-time"
react-native-video:
:path: "../node_modules/react-native-video"
react-native-webview:
@ -652,31 +684,31 @@ SPEC CHECKSUMS:
boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c
BVLinearGradient: e3aad03778a456d77928f594a649e96995f1c872
DoubleConversion: cf9b38bf0b2d048436d9a82ad2abe1404f11e7de
FBLazyVector: 49cbe4b43e445b06bf29199b6ad2057649e4c8f5
FBReactNativeSpec: 4862b23f27a9cdb8fdb1710af411fa677dcdd3cf
FBLazyVector: 7b423f9e248eae65987838148c36eec1dbfe0b53
FBReactNativeSpec: 5f648f4f07de2b0b37afa48029ed2b894d9ebfd0
glog: 73c2498ac6884b13ede40eda8228cb1eee9d9d62
jail-monkey: 80c9e34da2cd54023e5ad08bf7051ec75bd43d5b
jail-monkey: 0b62fb896246639f4203ea90358e08db91b7f5ea
libwebp: e90b9c01d99205d03b6bb8f2c8c415e5a4ef66f0
MMKV: 22e5136f7d00197bc0fc9694b7f71519f0d1ca12
MMKVCore: 607b7b05f2c2140056b5d338e45f2c14bf3f4232
Permission-Camera: 0d2d15352e9c54c3ea8686c8c21fb1a9edf3431b
Permission-MediaLibrary: a9b436b1127dff9d65fb699ebbdbd2dd9362fa16
Permission-Microphone: 60319bf64f89a035f5bf8d00107fab31b904005c
Permission-Notifications: 0db4fc644c3f5a8628f81696ca1b3019ce8bce32
Permission-PhotoLibrary: e5d0500209f22e2a5b281501cd3744a965747726
Permission-PhotoLibraryAddOnly: fba90734d82a6e577631b3267d660de42ebd649f
Permission-Camera: 104ac17250aa2632a0d488caca4e91b1d42fb70a
Permission-MediaLibrary: 5da8d6cdc18fcea48f9dd900f852bce112d68754
Permission-Microphone: 19d712e494fe874d61d9e537998d10237d28465b
Permission-Notifications: 41bc12e1ea68c62ac782526c361f15fd0a26e6f4
Permission-PhotoLibrary: 67f5337aa90463df9b1df53bc195ec280a4a327e
Permission-PhotoLibraryAddOnly: 80ff7188f5c2c1c7e995b66bbf7c6177d2a217ca
RCT-Folly: ec7a233ccc97cc556cf7237f0db1ff65b986f27c
RCTRequired: 2f8cb5b7533219bf4218a045f92768129cf7050a
RCTTypeSafety: 512728b73549e72ad7330b92f3d42936f2a4de5b
RCTRequired: ec2ebc96b7bfba3ca5c32740f5a0c6a014a274d2
RCTTypeSafety: 22567f31e67c3e088c7ac23ea46ab6d4779c0ea5
RCTYouTube: 7ff7d42f5ed42d185198681e967fd2c2b661375d
React: 98eac01574128a790f0bbbafe2d1a8607291ac24
React-callinvoker: def3f7fae16192df68d9b69fd4bbb59092ee36bc
React-Core: 70a52aa5dbe9b83befae82038451a7df9fd54c5a
React-CoreModules: 052edef46117862e2570eb3a0f06d81c61d2c4b8
React-cxxreact: c1dc71b30653cfb4770efdafcbdc0ad6d388baab
React-jsi: 74341196d9547cbcbcfa4b3bbbf03af56431d5a1
React-jsiexecutor: 06a9c77b56902ae7ffcdd7a4905f664adc5d237b
React-jsinspector: 0ae35a37b20d5e031eb020a69cc5afdbd6406301
React: a241e3dbb1e91d06332f1dbd2b3ab26e1a4c4b9d
React-callinvoker: da4d1c6141696a00163960906bc8a55b985e4ce4
React-Core: 46ba164c437d7dac607b470c83c8308b05799748
React-CoreModules: 217bd14904491c7b9940ff8b34a3fe08013c2f14
React-cxxreact: 0090588ae6660c4615d3629fdd5c768d0983add4
React-jsi: 5de8204706bd872b78ea646aee5d2561ca1214b6
React-jsiexecutor: 124e8f99992490d0d13e0649d950d3e1aae06fe9
React-jsinspector: 500a59626037be5b3b3d89c5151bc3baa9abf1a9
react-native-cameraroll: 7c6c7ca84844f93b3dac9a87670bbad6541684ec
react-native-cookies: 854d59c4135c70b92a02ca4930e68e4e2eb58150
react-native-document-picker: d2b8fa4d9b268a316515b1f631236f7a87813df6
@ -689,42 +721,43 @@ SPEC CHECKSUMS:
react-native-passcode-status: 88c4f6e074328bc278bd127646b6c694ad5a530a
react-native-safe-area: e8230b0017d76c00de6b01e2412dcf86b127c6a3
react-native-safe-area-context: e471852c5ed67eea4b10c5d9d43c1cebae3b231d
react-native-startup-time: c4c433fcf7ccac3c622f5d522e4ef18fb3bb0c9c
react-native-video: 1574074179ecaf6a9dd067116c8f31bf9fec15c8
react-native-webview: 0d1c2b4e7ffb0543a74fa0512f2f8dc5fb0e49e2
React-perflogger: 9c547d8f06b9bf00cb447f2b75e8d7f19b7e02af
React-RCTActionSheet: 3080b6e12e0e1a5b313c8c0050699b5c794a1b11
React-RCTAnimation: 3f96f21a497ae7dabf4d2f150ee43f906aaf516f
React-RCTBlob: 283b8e5025e7f954176bc48164f846909002f3ed
React-RCTImage: 5088a484faac78f2d877e1b79125d3bb1ea94a16
React-RCTLinking: 5e8fbb3e9a8bc2e4e3eb15b1eb8bda5fcac27b8c
React-RCTNetwork: 38ec277217b1e841d5e6a1fa78da65b9212ccb28
React-RCTSettings: 242d6e692108c3de4f3bb74b7586a8799e9ab070
React-RCTText: 8746736ac8eb5a4a74719aa695b7a236a93a83d2
React-RCTVibration: 0fd6b21751a33cb72fce1a4a33ab9678416d307a
React-runtimeexecutor: cad74a1eaa53ee6e7a3620231939d8fe2c6afcf0
ReactCommon: cfe2b7fd20e0dbd2d1185cd7d8f99633fbc5ff05
React-perflogger: aad6d4b4a267936b3667260d1f649b6f6069a675
React-RCTActionSheet: fc376be462c9c8d6ad82c0905442fd77f82a9d2a
React-RCTAnimation: ba0a1c3a2738be224a08092fa7f1b444ab77d309
React-RCTBlob: f758d4403fc5828a326dc69e27b41e1a92f34947
React-RCTImage: ce57088705f4a8d03f6594b066a59c29143ba73e
React-RCTLinking: 852a3a95c65fa63f657a4b4e2d3d83a815e00a7c
React-RCTNetwork: 9d7ccb8a08d522d71700b4fb677d9fa28cccd118
React-RCTSettings: d8aaf4389ff06114dee8c42ef5f0f2915946011e
React-RCTText: 809c12ed6b261796ba056c04fcd20d8b90bcc81d
React-RCTVibration: 4b99a7f5c6c0abbc5256410cc5425fb8531986e1
React-runtimeexecutor: ff951a0c241bfaefc4940a3f1f1a229e7cb32fa6
ReactCommon: bedc99ed4dae329c4fcf128d0c31b9115e5365ca
ReactNativeExceptionHandler: b11ff67c78802b2f62eed0e10e75cb1ef7947c60
ReactNativeKeyboardTrackingView: 02137fac3b2ebd330d74fa54ead48b14750a2306
ReactNativeNavigation: 906b631a6847c26cacf5cb3791566f1fe205c65c
ReactNativeNavigation: ff4873e683e5f23822af097e4fe643c82469c3d2
rn-fetch-blob: 17961aec08caae68bb8fc0e5b40f93b3acfa6932
RNCAsyncStorage: cb9a623793918c6699586281f0b51cbc38f046f9
RNCClipboard: 5e299c6df8e0c98f3d7416b86ae563d3a9f768a3
RNCMaskedView: f5c7d14d6847b7b44853f7acb6284c1da30a3459
RNDeviceInfo: 6d24c244896857a89685312335e5ae344d6c9699
RNCMaskedView: f127cd9652acfa31b91dcff613e07ba18b774db6
RNDeviceInfo: 49f6d50f861c7810fac2dd9b71cfb56cc1940e14
RNDevMenu: 9f80d65b80ba1fa84e5361d017b8c854a2f05005
RNFastImage: d4870d58f5936111c56218dbd7fcfc18e65b58ff
RNFileViewer: 83cc066ad795b1f986791d03b56fe0ee14b6a69f
RNGestureHandler: a479ebd5ed4221a810967000735517df0d2db211
RNKeychain: b8e0711b959a19c5b057d1e970d3c83d159b6da5
RNLocalize: 47e22ef8c36df1d572e42a87c8ae22e3fcf551dd
RNPermissions: eb94f9fdc0a8ecd02fcce0676d56ffb1395d41e1
RNKeychain: f75b8c8b2f17d3b2aa1f25b4a0ac5b83d947ff8f
RNLocalize: 29e84ea169d3bca6c3b83584536c7f586a07fb98
RNPermissions: d6679ecf0c21bf6de5a619b20df4304182792da8
RNReactNativeHapticFeedback: 653a8c126a0f5e88ce15ffe280b3ff37e1fbb285
RNReanimated: e03f7425cb7a38dcf1b644d680d1bfc91c3337ad
RNReanimated: b8c8004b43446e3c2709fe64b2b41072f87428ad
RNRudderSdk: 5d99b1a5a582ab55d6213b38018d35e98818af63
RNScreens: e8e8dd0588b5da0ab57dcca76ab9b2d8987757e0
RNSentry: b0d55027200c96f52e26b9bfb20296d47fc5051d
RNShare: 503c37af86611beadccba46156fcc42170c9fb42
RNSVG: ce9d996113475209013317e48b05c21ee988d42e
RNScreens: bd1523c3bde7069b8e958e5a16e1fc7722ad0bdd
RNSentry: e86fb2e2fec0365644f4b582938bf66be515acce
RNShare: 755de6bac084428f8fd8fb54c376f126f40e560c
RNSVG: 551acb6562324b1d52a4e0758f7ca0ec234e278f
RNVectorIcons: 31cebfcf94e8cf8686eb5303ae0357da64d7a5a4
Rudder: ef340f877a39653f19e69124dffae12fde3f881b
SDWebImage: c666b97e1fa9c64b4909816a903322018f0a9c84
@ -732,7 +765,7 @@ SPEC CHECKSUMS:
Sentry: 9d055e2de30a77685e86b219acf02e59b82091fc
Swime: d7b2c277503b6cea317774aedc2dce05613f8b0b
XCDYouTubeKit: 79baadb0560673a67c771eba45f83e353fd12c1f
Yoga: 8c8436d4171c87504c648ae23b1d81242bdf3bbf
Yoga: a7de31c64fe738607e7a3803e3f591a4b1df7393
YoutubePlayer-in-WKWebView: cfbf46da51d7370662a695a8f351e5fa1d3e1008
PODFILE CHECKSUM: 8f9184e7a51675aa02c8489226782a6a87b8d987

1927
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -7,16 +7,16 @@
"license": "Apache 2.0",
"private": true,
"dependencies": {
"@babel/runtime": "7.13.10",
"@babel/runtime": "7.14.0",
"@react-native-community/async-storage": "1.12.1",
"@react-native-community/cameraroll": "4.0.4",
"@react-native-community/clipboard": "1.5.1",
"@react-native-community/masked-view": "0.1.10",
"@react-native-community/masked-view": "0.1.11",
"@react-native-community/netinfo": "6.0.0",
"@react-navigation/native": "5.9.3",
"@react-navigation/stack": "5.14.3",
"@react-navigation/native": "5.9.4",
"@react-navigation/stack": "5.14.5",
"@rudderstack/rudder-sdk-react-native": "1.0.6",
"@sentry/react-native": "2.4.0",
"@sentry/react-native": "2.4.2",
"analytics-react-native": "1.2.0",
"commonmark": "github:mattermost/commonmark.js#d716e1c89e0a6721051df7bc74ad7683e1ae438f",
"commonmark-react-renderer": "github:mattermost/commonmark-react-renderer#81af294317ebe19b5cc195d7fbc4f4a58177854c",
@ -26,21 +26,21 @@
"form-data": "4.0.0",
"fuse.js": "6.4.6",
"intl": "1.2.5",
"jail-monkey": "2.3.3",
"jail-monkey": "2.3.4",
"mime-db": "1.47.0",
"moment-timezone": "0.5.33",
"prop-types": "15.7.2",
"react": "17.0.2",
"react-intl": "2.8.0",
"react-native": "0.64.0",
"react-native": "0.64.1",
"react-native-android-open-settings": "1.3.0",
"react-native-animatable": "1.3.3",
"react-native-button": "3.0.1",
"react-native-calendars": "1.1254.0",
"react-native-calendars": "1.1260.0",
"react-native-cookies": "github:mattermost/react-native-cookies#b35bafc388ae09c83bd875e887daf6a0755e0b40",
"react-native-device-info": "8.0.8",
"react-native-device-info": "8.1.3",
"react-native-document-picker": "5.0.3",
"react-native-elements": "3.3.2",
"react-native-elements": "3.4.1",
"react-native-exception-handler": "2.10.10",
"react-native-fast-image": "8.3.4",
"react-native-file-viewer": "2.1.4",
@ -50,31 +50,31 @@
"react-native-image-picker": "2.3.4",
"react-native-keyboard-aware-scrollview": "2.1.0",
"react-native-keyboard-tracking-view": "5.7.0",
"react-native-keychain": "6.2.0",
"react-native-keychain": "7.0.0",
"react-native-linear-gradient": "2.5.6",
"react-native-local-auth": "1.6.0",
"react-native-localize": "2.0.2",
"react-native-localize": "2.0.3",
"react-native-mmkv-storage": "0.4.4",
"react-native-navigation": "7.11.3",
"react-native-navigation": "7.14.0",
"react-native-notifications": "3.4.2",
"react-native-passcode-status": "1.1.2",
"react-native-permissions": "3.0.1",
"react-native-reanimated": "1.13.2",
"react-native-redash": "16.0.8",
"react-native-permissions": "3.0.3",
"react-native-reanimated": "2.1.0",
"react-native-redash": "16.0.11",
"react-native-safe-area": "0.5.1",
"react-native-safe-area-context": "3.2.0",
"react-native-screens": "3.0.0",
"react-native-screens": "3.1.1",
"react-native-section-list-get-item-layout": "2.2.3",
"react-native-share": "5.1.7",
"react-native-share": "6.0.1",
"react-native-slider": "0.11.0",
"react-native-status-bar-size": "0.3.3",
"react-native-svg": "12.1.0",
"react-native-startup-time": "2.0.0",
"react-native-svg": "12.1.1",
"react-native-vector-icons": "8.1.0",
"react-native-video": "5.1.1",
"react-native-webview": "github:mattermost/react-native-webview#b5e22940a613869d3999feac9451ee65352f4fbe",
"react-native-youtube": "2.0.1",
"react-redux": "7.2.3",
"redux": "4.0.5",
"react-redux": "7.2.4",
"redux": "4.1.0",
"redux-action-buffer": "1.2.0",
"redux-batched-actions": "0.5.0",
"redux-persist": "6.0.0",
@ -84,29 +84,29 @@
"rn-fetch-blob": "0.12.0",
"rn-placeholder": "3.0.3",
"semver": "7.3.5",
"serialize-error": "8.0.1",
"serialize-error": "8.1.0",
"shallow-equals": "1.0.0",
"tinycolor2": "1.4.2",
"url-parse": "1.5.1"
},
"devDependencies": {
"@babel/cli": "7.13.14",
"@babel/core": "7.13.14",
"@babel/plugin-transform-runtime": "7.13.10",
"@babel/preset-env": "7.13.12",
"@babel/register": "7.13.14",
"@babel/cli": "7.13.16",
"@babel/core": "7.14.0",
"@babel/plugin-transform-runtime": "7.13.15",
"@babel/preset-env": "7.14.1",
"@babel/register": "7.13.16",
"@react-native-community/eslint-config": "2.0.0",
"@storybook/addon-knobs": "6.2.2",
"@storybook/addon-knobs": "6.2.9",
"@storybook/addon-ondevice-knobs": "5.3.25",
"@storybook/react-native": "5.3.25",
"@storybook/react-native-server": "5.3.23",
"@testing-library/react-native": "7.2.0",
"@types/enzyme": "3.10.8",
"@types/enzyme-adapter-react-16": "1.0.6",
"@types/jest": "26.0.22",
"@types/jest": "26.0.23",
"@types/moment-timezone": "0.5.30",
"@types/react": "17.0.3",
"@types/react-native": "0.64.2",
"@types/react": "17.0.5",
"@types/react-native": "0.64.5",
"@types/react-native-share": "3.3.2",
"@types/react-native-video": "5.0.4",
"@types/react-redux": "7.1.16",
@ -114,32 +114,32 @@
"@types/shallow-equals": "1.0.0",
"@types/tinycolor2": "1.4.2",
"@types/url-parse": "1.4.3",
"@typescript-eslint/eslint-plugin": "4.20.0",
"@typescript-eslint/parser": "4.20.0",
"@typescript-eslint/eslint-plugin": "4.22.1",
"@typescript-eslint/parser": "4.22.1",
"babel-eslint": "10.1.0",
"babel-jest": "26.6.3",
"babel-loader": "8.2.2",
"babel-plugin-module-resolver": "4.1.0",
"babel-plugin-transform-remove-console": "6.9.4",
"deep-freeze": "0.0.1",
"detox": "18.11.2",
"detox": "18.13.0",
"enzyme": "3.11.0",
"enzyme-adapter-react-16": "1.15.6",
"enzyme-to-json": "3.6.1",
"eslint": "7.23.0",
"enzyme-to-json": "3.6.2",
"eslint": "7.26.0",
"eslint-plugin-header": "3.1.1",
"eslint-plugin-jest": "24.3.3",
"eslint-plugin-jest": "24.3.6",
"eslint-plugin-mattermost": "github:mattermost/eslint-plugin-mattermost#070ce792d105482ffb2b27cfc0b7e78b3d20acee",
"eslint-plugin-react": "7.23.1",
"harmony-reflect": "1.6.1",
"eslint-plugin-react": "7.23.2",
"harmony-reflect": "1.6.2",
"husky": "^6.0.0",
"isomorphic-fetch": "3.0.0",
"jest": "26.6.3",
"jest-cli": "26.6.3",
"jest-enzyme": "7.1.2",
"jetifier": "1.6.6",
"jetifier": "2.0.0",
"jsdom-global": "3.0.2",
"metro-react-native-babel-preset": "0.65.2",
"metro-react-native-babel-preset": "0.66.0",
"mmjstool": "github:mattermost/mattermost-utilities#3faa6075089a541d8c90ed85114e644c7a23fedf",
"mock-async-storage": "2.2.0",
"mock-socket": "9.0.3",
@ -148,14 +148,14 @@
"patch-package": "6.4.7",
"react-dom": "17.0.2",
"react-native-dev-menu": "4.0.2",
"react-native-dotenv": "2.5.3",
"react-native-storybook-loader": "2.0.2",
"react-native-dotenv": "2.5.5",
"react-native-storybook-loader": "2.0.4",
"redux-mock-store": "1.5.4",
"redux-persist-node-storage": "2.0.0",
"socketcluster": "16.0.1",
"ts-jest": "26.5.4",
"typescript": "4.2.3",
"underscore": "1.12.1",
"ts-jest": "26.5.6",
"typescript": "4.2.4",
"underscore": "1.13.1",
"util": "0.12.3"
},
"scripts": {

View file

@ -1,5 +1,5 @@
diff --git a/node_modules/react-native-elements/dist/searchbar/SearchBar-android.js b/node_modules/react-native-elements/dist/searchbar/SearchBar-android.js
index 4261cea..183bde1 100644
index fe25d36..a2a1a34 100644
--- a/node_modules/react-native-elements/dist/searchbar/SearchBar-android.js
+++ b/node_modules/react-native-elements/dist/searchbar/SearchBar-android.js
@@ -10,7 +10,7 @@ var __rest = (this && this.__rest) || function (s, e) {
@ -11,7 +11,7 @@ index 4261cea..183bde1 100644
import { renderNode } from '../helpers';
import Input from '../input/Input';
import Icon from '../icons/Icon';
@@ -65,18 +65,16 @@ class SearchBar extends Component {
@@ -74,18 +74,11 @@ class SearchBar extends Component {
this.props.onChangeText(text);
this.setState({ isEmpty: text === '' });
};
@ -24,21 +24,17 @@ index 4261cea..183bde1 100644
isEmpty: value ? value === '' : true,
};
- Keyboard.addListener('keyboardDidHide', this._keyboardDidHide);
}
- }
- componentWillUnmount() {
- Keyboard.removeListener('keyboardDidHide', this._keyboardDidHide);
+ componentDidUpdate(prevProps) {
+ if (this.props.value !== prevProps.value) {
+ this.setState({isEmpty: this.props.value === ''});
+ }
}
render() {
const _a = this.props, { theme, clearIcon = { name: 'clear' }, containerStyle, leftIconContainerStyle, rightIconContainerStyle, inputContainerStyle, inputStyle, searchIcon = { name: 'search' }, cancelIcon = { name: 'arrow-back' }, showLoading = false, loadingProps = {} } = _a, attributes = __rest(_a, ["theme", "clearIcon", "containerStyle", "leftIconContainerStyle", "rightIconContainerStyle", "inputContainerStyle", "inputStyle", "searchIcon", "cancelIcon", "showLoading", "loadingProps"]);
var _a;
diff --git a/node_modules/react-native-elements/dist/searchbar/SearchBar-ios.js b/node_modules/react-native-elements/dist/searchbar/SearchBar-ios.js
index b0761ab..4fa5e83 100644
index 9581256..b10d579 100644
--- a/node_modules/react-native-elements/dist/searchbar/SearchBar-ios.js
+++ b/node_modules/react-native-elements/dist/searchbar/SearchBar-ios.js
@@ -82,6 +82,11 @@ class SearchBar extends Component {
@@ -79,6 +79,11 @@ class SearchBar extends Component {
cancelButtonWidth: null,
};
}
@ -50,7 +46,7 @@ index b0761ab..4fa5e83 100644
render() {
const _a = this.props, { theme, cancelButtonProps, cancelButtonTitle, clearIcon, containerStyle, leftIconContainerStyle, rightIconContainerStyle, inputContainerStyle, inputStyle, placeholderTextColor, showLoading, loadingProps, searchIcon, showCancel } = _a, attributes = __rest(_a, ["theme", "cancelButtonProps", "cancelButtonTitle", "clearIcon", "containerStyle", "leftIconContainerStyle", "rightIconContainerStyle", "inputContainerStyle", "inputStyle", "placeholderTextColor", "showLoading", "loadingProps", "searchIcon", "showCancel"]);
const { hasFocus, isEmpty } = this.state;
@@ -159,7 +164,6 @@ const styles = StyleSheet.create({
@@ -154,7 +159,6 @@ const styles = StyleSheet.create({
paddingBottom: 13,
paddingTop: 13,
flexDirection: 'row',
@ -58,7 +54,7 @@ index b0761ab..4fa5e83 100644
alignItems: 'center',
},
input: {
@@ -169,7 +173,7 @@ const styles = StyleSheet.create({
@@ -164,7 +168,7 @@ const styles = StyleSheet.create({
inputContainer: {
borderBottomWidth: 0,
borderRadius: 9,

View file

@ -1,5 +1,5 @@
diff --git a/node_modules/react-native-keychain/android/src/main/java/com/oblador/keychain/KeychainModule.java b/node_modules/react-native-keychain/android/src/main/java/com/oblador/keychain/KeychainModule.java
index d4ded69..af35eaa 100644
index 3da433f..7bbc965 100644
--- a/node_modules/react-native-keychain/android/src/main/java/com/oblador/keychain/KeychainModule.java
+++ b/node_modules/react-native-keychain/android/src/main/java/com/oblador/keychain/KeychainModule.java
@@ -1,6 +1,7 @@
@ -7,10 +7,10 @@ index d4ded69..af35eaa 100644
import android.os.Build;
+import android.os.Bundle;
import android.os.Looper;
import android.text.TextUtils;
import android.util.Log;
@@ -128,6 +129,7 @@ public class KeychainModule extends ReactContextBaseJavaModule {
@@ -129,6 +130,7 @@ public class KeychainModule extends ReactContextBaseJavaModule {
//region Members
/** Name-to-instance lookup map. */
private final Map<String, CipherStorage> cipherStorageMap = new HashMap<>();
@ -18,7 +18,7 @@ index d4ded69..af35eaa 100644
/** Shared preferences storage. */
private final PrefsStorage prefsStorage;
//endregion
@@ -139,13 +141,13 @@ public class KeychainModule extends ReactContextBaseJavaModule {
@@ -140,13 +142,13 @@ public class KeychainModule extends ReactContextBaseJavaModule {
super(reactContext);
prefsStorage = new PrefsStorage(reactContext);
@ -36,7 +36,7 @@ index d4ded69..af35eaa 100644
}
/** Allow initialization in chain. */
@@ -277,6 +279,12 @@ public class KeychainModule extends ReactContextBaseJavaModule {
@@ -278,6 +280,11 @@ public class KeychainModule extends ReactContextBaseJavaModule {
@Nullable final ReadableMap options,
@NonNull final Promise promise) {
try {
@ -45,11 +45,10 @@ index d4ded69..af35eaa 100644
+ promise.resolve(Arguments.fromBundle(cached));
+ return;
+ }
+
final ResultSet resultSet = prefsStorage.getEncryptedEntry(alias);
if (resultSet == null) {
@@ -299,6 +307,7 @@ public class KeychainModule extends ReactContextBaseJavaModule {
@@ -300,6 +307,7 @@ public class KeychainModule extends ReactContextBaseJavaModule {
credentials.putString(Maps.USERNAME, decryptionResult.username);
credentials.putString(Maps.PASSWORD, decryptionResult.password);
credentials.putString(Maps.STORAGE, current.getCipherStorageName());

View file

@ -66,21 +66,4 @@ index 815e1c6..a35a087 100644
+ [hitTestResult isKindOfClass:[RNCSafeAreaProvider class]]) {
return nil;
}
diff --git a/node_modules/react-native-navigation/lib/ios/RNNViewLocation.m b/node_modules/react-native-navigation/lib/ios/RNNViewLocation.m
index 6b9981d..f725701 100644
--- a/node_modules/react-native-navigation/lib/ios/RNNViewLocation.m
+++ b/node_modules/react-native-navigation/lib/ios/RNNViewLocation.m
@@ -31,11 +31,7 @@ - (CGFloat)getClippedCornerRadius:(UIView *)view {
- (CATransform3D)getTransform:(UIView *)view {
if (view) {
- if (!CATransform3DEqualToTransform(view.layer.transform, CATransform3DIdentity)) {
- return view.layer.transform;
- } else {
- return [self getTransform:view.superview];
- }
+ return view.layer.transform;
}
return CATransform3DIdentity;

View file

@ -44,6 +44,8 @@ const ChannelItem = ({onSelect, selected, channel}: ChannelItemProps) => {
);
}
const channelType = channelTypes[channel.type] || PublicChannel;
return (
<TouchableHighlight
underlayColor={changeOpacity(theme.sidebarTextHoverBg, 0.5)}
@ -51,7 +53,7 @@ const ChannelItem = ({onSelect, selected, channel}: ChannelItemProps) => {
>
<View style={styles.container}>
<View style={styles.item}>
{channelTypes[channel.type] || PublicChannel}
{channelType()}
<Text
testID='share_extension.channel_item.display_name'
style={[styles.text]}

View file

@ -48,7 +48,7 @@
"@share/*": ["share_extension/*"],
"@store": ["app/store/index"],
"@store/*": ["app/store/*"],
"@telemetry/*": ["/app/telemetry/*"],
"@telemetry": ["app/telemetry/index"],
"@utils/*": ["app/utils/*"],
"@websocket": ["app/client/websocket"],
"*": ["./*", "node_modules/*"],