[MM-16008] Update setNavigatorStyles and replace setOnNavigatorEvent (#2877)

* Update setNavigatorStyles

* Replace navigator.setOnNavigatorEvent and callbacks

* Update unit tests

* Save user notify props on componentWillUnmount

* Add TODOs about removing componentDidAppear/setNavigatorStyles

* check-styles fix

* Fix eslint errors
This commit is contained in:
Miguel Alatzar 2019-06-14 08:14:26 -07:00 committed by GitHub
parent 2e423a9f64
commit 7d67f1214e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
63 changed files with 562 additions and 656 deletions

View file

@ -21,7 +21,6 @@ exports[`profile_picture_button should match snapshot 1`] = `
"dismissModal": [MockFunction],
"push": [MockFunction],
"setButtons": [MockFunction],
"setOnNavigatorEvent": [MockFunction],
}
}
theme={

View file

@ -11,7 +11,6 @@ import {Client4} from 'mattermost-redux/client';
describe('profile_picture_button', () => {
const navigator = {
setOnNavigatorEvent: jest.fn(),
setButtons: jest.fn(),
dismissModal: jest.fn(),
push: jest.fn(),

View file

@ -5,6 +5,7 @@ import React, {PureComponent} from 'react';
import PropTypes from 'prop-types';
import {Dimensions, Keyboard, NativeModules, View} from 'react-native';
import SafeArea from 'react-native-safe-area';
import {Navigation} from 'react-native-navigation';
import {DeviceTypes} from 'app/constants';
import mattermostManaged from 'app/mattermost_managed';
@ -33,10 +34,6 @@ export default class SafeAreaIos extends PureComponent {
constructor(props) {
super(props);
if (props.navigator) {
props.navigator.setOnNavigatorEvent(this.onNavigatorEvent);
}
this.state = {
keyboard: false,
safeAreaInsets: {
@ -56,6 +53,8 @@ export default class SafeAreaIos extends PureComponent {
}
componentDidMount() {
this.navigationEventListener = Navigation.events().bindComponent(this);
Dimensions.addEventListener('change', this.getSafeAreaInsets);
this.keyboardDidShowListener = Keyboard.addListener('keyboardWillShow', this.keyboardWillShow);
this.keyboardDidHideListener = Keyboard.addListener('keyboardWillHide', this.keyboardWillHide);
@ -70,6 +69,14 @@ export default class SafeAreaIos extends PureComponent {
this.mounted = false;
}
componentDidAppear() {
this.getSafeAreaInsets();
}
componentDidDisappear() {
this.getSafeAreaInsets();
}
getStatusBarHeight = () => {
try {
StatusBarManager.getHeight(
@ -106,15 +113,6 @@ export default class SafeAreaIos extends PureComponent {
this.setState({keyboard: true});
};
onNavigatorEvent = (event) => {
switch (event.id) {
case 'willAppear':
case 'didDisappear':
this.getSafeAreaInsets();
break;
}
};
renderTopBar = () => {
const {safeAreaInsets, statusBarHeight} = this.state;
const {headerComponent, excludeHeader, forceTop, navBarBackgroundColor, theme} = this.props;

View file

@ -194,6 +194,9 @@ export default class SettingsDrawer extends PureComponent {
goToSettings = preventDoubleTap(() => {
const {intl} = this.context;
// TODO: Ensure all styles used in app/utils/theme's setNavigatorStyles
// are passed to Settings when this showModal call is updated to RNN v2,
// then remove setNavigatorStyles call in app/screens/settings/general/settings.js
this.openModal(
'Settings',
intl.formatMessage({id: 'mobile.routes.settings', defaultMessage: 'Settings'}),

View file

@ -23,6 +23,7 @@ const MATTERMOST_BUNDLE_IDS = ['com.mattermost.rnbeta', 'com.mattermost.rn'];
export default class About extends PureComponent {
static propTypes = {
componentId: PropTypes.string,
config: PropTypes.object.isRequired,
license: PropTypes.object.isRequired,
navigator: PropTypes.object.isRequired,
@ -31,7 +32,7 @@ export default class About extends PureComponent {
componentWillReceiveProps(nextProps) {
if (this.props.theme !== nextProps.theme) {
setNavigatorStyles(this.props.navigator, nextProps.theme);
setNavigatorStyles(this.props.componentId, nextProps.theme);
}
}

View file

@ -7,6 +7,7 @@ import {
StyleSheet,
View,
} from 'react-native';
import {Navigation} from 'react-native-navigation';
import EmojiPicker from 'app/components/emoji_picker';
import {emptyFunction} from 'app/utils/general';
@ -14,6 +15,7 @@ import {setNavigatorStyles} from 'app/utils/theme';
export default class AddReaction extends PureComponent {
static propTypes = {
componentId: PropTypes.string,
closeButton: PropTypes.object,
navigator: PropTypes.object.isRequired,
onEmojiPress: PropTypes.func,
@ -31,15 +33,24 @@ export default class AddReaction extends PureComponent {
constructor(props) {
super(props);
props.navigator.setOnNavigatorEvent(this.onNavigatorEvent);
props.navigator.setButtons({
leftButtons: [{...this.leftButton, icon: props.closeButton}],
});
}
componentDidMount() {
this.navigationEventListener = Navigation.events().bindComponent(this);
}
componentWillReceiveProps(nextProps) {
if (this.props.theme !== nextProps.theme) {
setNavigatorStyles(this.props.navigator, nextProps.theme);
setNavigatorStyles(this.props.componentId, nextProps.theme);
}
}
navigationButtonPressed({buttonId}) {
if (buttonId === 'close-edit-post') {
this.close();
}
}
@ -49,16 +60,6 @@ export default class AddReaction extends PureComponent {
});
};
onNavigatorEvent = (event) => {
if (event.type === 'NavBarButtonPress') {
switch (event.id) {
case 'close-edit-post':
this.close();
break;
}
}
};
handleEmojiPress = (emoji) => {
this.props.onEmojiPress(emoji);
this.close();

View file

@ -9,6 +9,7 @@ import {
Platform,
View,
} from 'react-native';
import {Navigation} from 'react-native-navigation';
import {debounce} from 'mattermost-redux/actions/helpers';
import {General} from 'mattermost-redux/constants';
@ -33,6 +34,7 @@ export default class ChannelAddMembers extends PureComponent {
handleAddChannelMembers: PropTypes.func.isRequired,
searchProfiles: PropTypes.func.isRequired,
}).isRequired,
componentId: PropTypes.string,
currentChannelId: PropTypes.string.isRequired,
currentChannelGroupConstrained: PropTypes.bool,
currentTeamId: PropTypes.string.isRequired,
@ -72,13 +74,14 @@ export default class ChannelAddMembers extends PureComponent {
showAsAction: 'always',
};
props.navigator.setOnNavigatorEvent(this.onNavigatorEvent);
props.navigator.setButtons({
rightButtons: [this.addButton],
});
}
componentDidMount() {
this.navigationEventListener = Navigation.events().bindComponent(this);
const {actions, currentTeamId} = this.props;
actions.getTeamStats(currentTeamId);
@ -88,14 +91,20 @@ export default class ChannelAddMembers extends PureComponent {
}
componentDidUpdate(prevProps) {
const {navigator, theme} = this.props;
const {componentId, theme} = this.props;
const {adding, selectedIds} = this.state;
const enabled = Object.keys(selectedIds).length > 0 && !adding;
this.enableAddOption(enabled);
if (theme !== prevProps.theme) {
setNavigatorStyles(navigator, theme);
setNavigatorStyles(componentId, theme);
}
}
navigationButtonPressed({buttonId}) {
if (buttonId === this.addButton.id) {
this.handleAddMembersPress();
}
}
@ -188,14 +197,6 @@ export default class ChannelAddMembers extends PureComponent {
});
};
onNavigatorEvent = (event) => {
if (event.type === 'NavBarButtonPress') {
if (event.id === this.addButton.id) {
this.handleAddMembersPress();
}
}
};
onSearch = (text) => {
if (text) {
this.setState({term: text});

View file

@ -24,9 +24,9 @@ describe('ChannelAddMembers', () => {
navigator: {
pop: jest.fn(),
setButtons: jest.fn(),
setOnNavigatorEvent: jest.fn(),
},
theme: Preferences.THEMES.default,
componentId: 'component-id',
};
test('should render without error and call functions on mount', () => {
@ -39,8 +39,6 @@ describe('ChannelAddMembers', () => {
expect(baseProps.navigator.setButtons).toBeCalledTimes(2);
expect(baseProps.navigator.setButtons.mock.calls[0][0]).toEqual({rightButtons: [button]});
expect(baseProps.navigator.setButtons.mock.calls[1][0]).toEqual({rightButtons: [button]});
expect(baseProps.navigator.setOnNavigatorEvent).toBeCalledTimes(1);
});
test('should match state on clearSearch', () => {

View file

@ -43,6 +43,7 @@ export default class ChannelInfo extends PureComponent {
handleSelectChannel: PropTypes.func.isRequired,
setChannelDisplayName: PropTypes.func.isRequired,
}),
componentId: PropTypes.string,
viewArchivedChannels: PropTypes.bool.isRequired,
canDeleteChannel: PropTypes.bool.isRequired,
currentChannel: PropTypes.object.isRequired,
@ -82,7 +83,7 @@ export default class ChannelInfo extends PureComponent {
componentWillReceiveProps(nextProps) {
if (this.props.theme !== nextProps.theme) {
setNavigatorStyles(this.props.navigator, nextProps.theme);
setNavigatorStyles(this.props.componentId, nextProps.theme);
}
let isFavorite = this.state.isFavorite;

View file

@ -9,6 +9,7 @@ import {
View,
} from 'react-native';
import {intlShape} from 'react-intl';
import {Navigation} from 'react-native-navigation';
import {debounce} from 'mattermost-redux/actions/helpers';
import {General} from 'mattermost-redux/constants';
@ -32,6 +33,7 @@ export default class ChannelMembers extends PureComponent {
handleRemoveChannelMembers: PropTypes.func.isRequired,
searchProfiles: PropTypes.func.isRequired,
}).isRequired,
componentId: PropTypes.string,
canManageUsers: PropTypes.bool.isRequired,
currentChannelId: PropTypes.string.isRequired,
currentChannelMembers: PropTypes.array,
@ -67,7 +69,6 @@ export default class ChannelMembers extends PureComponent {
title: context.intl.formatMessage({id: 'channel_members_modal.remove', defaultMessage: 'Remove'}),
};
props.navigator.setOnNavigatorEvent(this.onNavigatorEvent);
if (props.canManageUsers) {
props.navigator.setButtons({
rightButtons: [this.removeButton],
@ -76,18 +77,26 @@ export default class ChannelMembers extends PureComponent {
}
componentDidMount() {
this.navigationEventListener = Navigation.events().bindComponent(this);
this.getProfiles();
}
componentDidUpdate(prevProps) {
const {navigator, theme} = this.props;
const {componentId, theme} = this.props;
const {removing, selectedIds} = this.state;
const enabled = Object.keys(selectedIds).length > 0 && !removing;
this.enableRemoveOption(enabled);
if (theme !== prevProps.theme) {
setNavigatorStyles(navigator, theme);
setNavigatorStyles(componentId, theme);
}
}
navigationButtonPressed({buttonId}) {
if (buttonId === this.removeButton.id) {
this.handleRemoveMembersPress();
}
}
@ -188,14 +197,6 @@ export default class ChannelMembers extends PureComponent {
this.setState({loading: false, profiles: [...profiles, ...data]});
};
onNavigatorEvent = (event) => {
if (event.type === 'NavBarButtonPress') {
if (event.id === this.removeButton.id) {
this.handleRemoveMembersPress();
}
}
};
onSearch = (text) => {
if (text) {
this.setState({term: text});

View file

@ -4,6 +4,7 @@
import React, {PureComponent} from 'react';
import PropTypes from 'prop-types';
import {Platform, View} from 'react-native';
import {Navigation} from 'react-native-navigation';
import {getLastPostIndex} from 'mattermost-redux/utils/post_list';
@ -32,13 +33,16 @@ export default class ChannelPeek extends PureComponent {
constructor(props) {
super(props);
this.props.navigator.setOnNavigatorEvent(this.onNavigatorEvent);
props.actions.loadPostsIfNecessaryWithRetry(props.channelId);
this.state = {
visiblePostIds: this.getVisiblePostIds(props),
};
}
componentDidMount() {
this.navigationEventListener = Navigation.events().bindComponent(this);
}
componentWillReceiveProps(nextProps) {
const {postIds: nextPostIds} = nextProps;
@ -53,19 +57,17 @@ export default class ChannelPeek extends PureComponent {
});
}
navigationButtonPressed({buttonId}) {
if (buttonId === 'action-mark-as-read') {
const {actions, channelId} = this.props;
actions.markChannelViewedAndRead(channelId);
}
}
getVisiblePostIds = (props) => {
return props.postIds.slice(0, 15);
};
onNavigatorEvent = (event) => {
if (event.type === 'PreviewActionPress') {
if (event.id === 'action-mark-as-read') {
const {actions, channelId} = this.props;
actions.markChannelViewedAndRead(channelId);
}
}
};
render() {
const {
channelId,

View file

@ -12,6 +12,7 @@ import {
View,
} from 'react-native';
import {intlShape} from 'react-intl';
import {Navigation} from 'react-native-navigation';
import FormattedText from 'app/components/formatted_text';
import StatusBar from 'app/components/status_bar';
@ -26,6 +27,7 @@ export default class ClientUpgrade extends PureComponent {
logError: PropTypes.func.isRequired,
setLastUpgradeCheck: PropTypes.func.isRequired,
}).isRequired,
componentId: PropTypes.string,
currentVersion: PropTypes.string,
closeAction: PropTypes.func,
userCheckedForUpgrade: PropTypes.bool,
@ -44,13 +46,14 @@ export default class ClientUpgrade extends PureComponent {
constructor(props) {
super(props);
this.props.navigator.setOnNavigatorEvent(this.onNavigatorEvent);
this.state = {
upgradeType: UpgradeTypes.NO_UPGRADE,
};
}
componentDidMount() {
this.navigationEventListener = Navigation.events().bindComponent(this);
if (this.props.userCheckedForUpgrade) {
this.checkUpgrade(this.props);
}
@ -58,7 +61,15 @@ export default class ClientUpgrade extends PureComponent {
componentWillReceiveProps(nextProps) {
if (this.props.theme !== nextProps.theme) {
setNavigatorStyles(this.props.navigator, nextProps.theme);
setNavigatorStyles(this.props.componentId, nextProps.theme);
}
}
navigationButtonPressed({buttonId}) {
if (buttonId === 'close-upgrade') {
this.props.navigator.dismissModal({
animationType: 'slide-down',
});
}
}
@ -117,16 +128,6 @@ export default class ClientUpgrade extends PureComponent {
});
};
onNavigatorEvent = (event) => {
if (event.type === 'NavBarButtonPress') {
if (event.id === 'close-upgrade') {
this.props.navigator.dismissModal({
animationType: 'slide-down',
});
}
}
};
renderMustUpgrade() {
const {theme} = this.props;
const styles = getStyleFromTheme(theme);

View file

@ -18,6 +18,7 @@ import {changeOpacity, makeStyleSheetFromTheme, setNavigatorStyles} from 'app/ut
export default class Code extends React.PureComponent {
static propTypes = {
componentId: PropTypes.string,
navigator: PropTypes.object.isRequired,
theme: PropTypes.object.isRequired,
content: PropTypes.string.isRequired,
@ -29,7 +30,7 @@ export default class Code extends React.PureComponent {
componentWillReceiveProps(nextProps) {
if (this.props.theme !== nextProps.theme) {
setNavigatorStyles(this.props.navigator, nextProps.theme);
setNavigatorStyles(this.props.componentId, nextProps.theme);
}
}

View file

@ -8,6 +8,7 @@ import {
Keyboard,
InteractionManager,
} from 'react-native';
import {Navigation} from 'react-native-navigation';
import {General, RequestStatus} from 'mattermost-redux/constants';
import EventEmitter from 'mattermost-redux/utils/event_emitter';
@ -17,6 +18,7 @@ import {setNavigatorStyles} from 'app/utils/theme';
export default class CreateChannel extends PureComponent {
static propTypes = {
componentId: PropTypes.string,
navigator: PropTypes.object.isRequired,
theme: PropTypes.object.isRequired,
deviceWidth: PropTypes.number.isRequired,
@ -72,17 +74,17 @@ export default class CreateChannel extends PureComponent {
buttons.leftButtons = [this.left];
}
props.navigator.setOnNavigatorEvent(this.onNavigatorEvent);
props.navigator.setButtons(buttons);
}
componentDidMount() {
this.navigationEventListener = Navigation.events().bindComponent(this);
this.emitCanCreateChannel(false);
}
componentWillReceiveProps(nextProps) {
if (this.props.theme !== nextProps.theme) {
setNavigatorStyles(this.props.navigator, nextProps.theme);
setNavigatorStyles(this.props.componentId, nextProps.theme);
}
const {createChannelRequest} = nextProps;
@ -109,6 +111,17 @@ export default class CreateChannel extends PureComponent {
}
}
navigationButtonPressed({buttonId}) {
switch (buttonId) {
case 'close-new-channel':
this.close(!this.props.closeButton);
break;
case 'create-channel':
this.onCreateChannel();
break;
}
}
close = (goBack = false) => {
if (goBack) {
this.props.navigator.pop({animated: true});
@ -149,19 +162,6 @@ export default class CreateChannel extends PureComponent {
this.props.actions.handleCreateChannel(displayName, purpose, header, this.props.channelType);
};
onNavigatorEvent = (event) => {
if (event.type === 'NavBarButtonPress') {
switch (event.id) {
case 'close-new-channel':
this.close(!this.props.closeButton);
break;
case 'create-channel':
this.onCreateChannel();
break;
}
}
};
onDisplayNameChange = (displayName) => {
this.setState({displayName});
};

View file

@ -8,6 +8,7 @@ import {
Keyboard,
InteractionManager,
} from 'react-native';
import {Navigation} from 'react-native-navigation';
import {General, RequestStatus} from 'mattermost-redux/constants';
import EventEmitter from 'mattermost-redux/utils/event_emitter';
@ -56,6 +57,7 @@ export default class EditChannel extends PureComponent {
getChannel: PropTypes.func.isRequired,
setChannelDisplayName: PropTypes.func.isRequired,
}),
componentId: PropTypes.string,
navigator: PropTypes.object.isRequired,
theme: PropTypes.object.isRequired,
deviceWidth: PropTypes.number.isRequired,
@ -102,17 +104,18 @@ export default class EditChannel extends PureComponent {
rightButtons: [this.rightButton],
};
props.navigator.setOnNavigatorEvent(this.onNavigatorEvent);
props.navigator.setButtons(buttons);
}
componentDidMount() {
this.navigationEventListener = Navigation.events().bindComponent(this);
this.emitCanUpdateChannel(false);
}
componentWillReceiveProps(nextProps) {
if (this.props.theme !== nextProps.theme) {
setNavigatorStyles(this.props.navigator, nextProps.theme);
setNavigatorStyles(this.props.componentId, nextProps.theme);
}
const {updateChannelRequest} = nextProps;
@ -139,6 +142,17 @@ export default class EditChannel extends PureComponent {
}
}
navigationButtonPressed({buttonId}) {
switch (buttonId) {
case 'close-edit-channel':
this.close();
break;
case 'edit-channel':
this.onUpdateChannel();
break;
}
}
close = () => {
const {channel: {type}} = this.props;
const isDirect = type === General.DM_CHANNEL || type === General.GM_CHANNEL;
@ -238,19 +252,6 @@ export default class EditChannel extends PureComponent {
}
};
onNavigatorEvent = (event) => {
if (event.type === 'NavBarButtonPress') {
switch (event.id) {
case 'close-edit-channel':
this.close();
break;
case 'edit-channel':
this.onUpdateChannel();
break;
}
}
};
onDisplayNameChange = (displayName) => {
this.setState({displayName});
};

View file

@ -7,6 +7,7 @@ import {
Platform,
View,
} from 'react-native';
import {Navigation} from 'react-native-navigation';
import ErrorText from 'app/components/error_text';
import Loading from 'app/components/loading';
@ -22,6 +23,7 @@ export default class EditPost extends PureComponent {
actions: PropTypes.shape({
editPost: PropTypes.func.isRequired,
}),
componentId: PropTypes.string,
closeButton: PropTypes.object,
deviceHeight: PropTypes.number,
deviceWidth: PropTypes.number,
@ -50,7 +52,6 @@ export default class EditPost extends PureComponent {
this.state = {message: props.post.message};
this.rightButton.title = context.intl.formatMessage({id: 'edit_post.save', defaultMessage: 'Save'});
props.navigator.setOnNavigatorEvent(this.onNavigatorEvent);
props.navigator.setButtons({
leftButtons: [{...this.leftButton, icon: props.closeButton}],
rightButtons: [this.rightButton],
@ -58,12 +59,14 @@ export default class EditPost extends PureComponent {
}
componentDidMount() {
this.navigationEventListener = Navigation.events().bindComponent(this);
this.focus();
}
componentWillReceiveProps(nextProps) {
if (this.props.theme !== nextProps.theme) {
setNavigatorStyles(this.props.navigator, nextProps.theme);
setNavigatorStyles(this.props.componentId, nextProps.theme);
}
const {editPostRequest} = nextProps;
@ -87,6 +90,17 @@ export default class EditPost extends PureComponent {
}
}
navigationButtonPressed({buttonId}) {
switch (buttonId) {
case 'close-edit-post':
this.close();
break;
case 'edit-post':
this.onEditPost();
break;
}
}
close = () => {
this.props.navigator.dismissModal({
animationType: 'slide-down',
@ -121,19 +135,6 @@ export default class EditPost extends PureComponent {
this.props.actions.editPost(post);
};
onNavigatorEvent = (event) => {
if (event.type === 'NavBarButtonPress') {
switch (event.id) {
case 'close-edit-post':
this.close();
break;
case 'edit-post':
this.onEditPost();
break;
}
}
};
onPostChangeText = (message) => {
this.setState({message});
if (message) {

View file

@ -52,19 +52,6 @@ exports[`edit_profile should match snapshot 1`] = `
},
],
},
"setOnNavigatorEvent": [MockFunction] {
"calls": Array [
Array [
[Function],
],
],
"results": Array [
Object {
"type": "return",
"value": undefined,
},
],
},
}
}
onShowFileSizeWarning={[Function]}

View file

@ -8,6 +8,7 @@ import {Alert, View} from 'react-native';
import RNFetchBlob from 'rn-fetch-blob';
import {KeyboardAwareScrollView} from 'react-native-keyboard-aware-scroll-view';
import {DocumentPickerUtil} from 'react-native-document-picker';
import {Navigation} from 'react-native-navigation';
import {Client4} from 'mattermost-redux/client';
@ -114,7 +115,6 @@ export default class EditProfile extends PureComponent {
};
this.rightButton.title = context.intl.formatMessage({id: t('mobile.account.settings.save'), defaultMessage: 'Save'});
props.navigator.setOnNavigatorEvent(this.onNavigatorEvent);
props.navigator.setButtons(buttons);
this.state = {
@ -127,6 +127,21 @@ export default class EditProfile extends PureComponent {
};
}
componentDidMount() {
this.navigationEventListener = Navigation.events().bindComponent(this);
}
navigationButtonPressed({buttonId}) {
switch (buttonId) {
case 'update-profile':
this.submitUser();
break;
case 'close-settings':
this.close();
break;
}
}
canUpdate = (updatedField) => {
const {currentUser} = this.props;
const keys = Object.keys(this.state);
@ -276,19 +291,6 @@ export default class EditProfile extends PureComponent {
});
};
onNavigatorEvent = (event) => {
if (event.type === 'NavBarButtonPress') {
switch (event.id) {
case 'update-profile':
this.submitUser();
break;
case 'close-settings':
this.close();
break;
}
}
};
onShowFileSizeWarning = (filename) => {
const {formatMessage} = this.context.intl;
const fileSizeWarning = formatMessage({

View file

@ -18,7 +18,6 @@ jest.mock('app/utils/theme', () => {
describe('edit_profile', () => {
const navigator = {
setOnNavigatorEvent: jest.fn(),
setButtons: jest.fn(),
dismissModal: jest.fn(),
push: jest.fn(),
@ -46,6 +45,7 @@ describe('edit_profile', () => {
position: 'position',
},
commandType: 'ShowModal',
componentId: 'component-id',
};
test('should match snapshot', async () => {
@ -59,7 +59,6 @@ describe('edit_profile', () => {
test('should match state on handleRemoveProfileImage', () => {
const newNavigator = {
dismissModal: jest.fn(),
setOnNavigatorEvent: jest.fn(),
setButtons: jest.fn(),
};
const wrapper = shallow(

View file

@ -7,6 +7,7 @@ import {
InteractionManager,
View,
} from 'react-native';
import {Navigation} from 'react-native-navigation';
import FailedNetworkAction from 'app/components/failed_network_action';
import Loading from 'app/components/loading';
@ -32,22 +33,33 @@ export default class ErrorTeamsList extends PureComponent {
logout: PropTypes.func.isRequired,
selectDefaultTeam: PropTypes.func.isRequired,
}).isRequired,
componentId: PropTypes.string,
navigator: PropTypes.object,
theme: PropTypes.object,
};
constructor(props) {
super(props);
props.navigator.setOnNavigatorEvent(this.onNavigatorEvent);
this.state = {
loading: false,
};
}
componentDidMount() {
this.navigationEventListener = Navigation.events().bindComponent(this);
}
componentWillReceiveProps(nextProps) {
if (this.props.theme !== nextProps.theme) {
setNavigatorStyles(this.props.navigator, nextProps.theme);
setNavigatorStyles(this.props.componentId, nextProps.theme);
}
}
navigationButtonPressed({buttonId}) {
const {logout} = this.props.actions;
if (buttonId === 'logout') {
InteractionManager.runAfterInteractions(logout);
}
}
@ -83,15 +95,6 @@ export default class ErrorTeamsList extends PureComponent {
}
}
onNavigatorEvent = (event) => {
if (event.type === 'NavBarButtonPress') {
const {logout} = this.props.actions;
if (event.id === 'logout') {
InteractionManager.runAfterInteractions(logout);
}
}
};
render() {
const {theme} = this.props;
const styles = getStyleSheet(theme);

View file

@ -10,10 +10,6 @@ import FailedNetworkAction from 'app/components/failed_network_action';
import ErrorTeamsList from './error_teams_list';
describe('ErrorTeamsList', () => {
const navigator = {
setOnNavigatorEvent: () => {}, // eslint-disable-line no-empty-function
};
const loadMe = async () => {
return {
data: {},
@ -27,8 +23,8 @@ describe('ErrorTeamsList', () => {
logout: () => {}, // eslint-disable-line no-empty-function
selectDefaultTeam: () => {}, // eslint-disable-line no-empty-function
},
componentId: 'component-id',
theme: Preferences.THEMES.default,
navigator,
};
test('should match snapshot', () => {

View file

@ -11,6 +11,7 @@ import {
SafeAreaView,
View,
} from 'react-native';
import {Navigation} from 'react-native-navigation';
import {isDateLine, getDateForDateLine} from 'mattermost-redux/utils/post_list';
@ -54,11 +55,22 @@ export default class FlaggedPosts extends PureComponent {
constructor(props) {
super(props);
props.navigator.setOnNavigatorEvent(this.onNavigatorEvent);
props.actions.clearSearch();
props.actions.getFlaggedPosts();
}
componentDidMount() {
this.navigationEventListener = Navigation.events().bindComponent(this);
}
navigationButtonPressed({buttonId}) {
if (buttonId === 'close-settings') {
this.props.navigator.dismissModal({
animationType: 'slide-down',
});
}
}
goToThread = (post) => {
const {actions, navigator, theme} = this.props;
const channelId = post.channel_id;
@ -108,16 +120,6 @@ export default class FlaggedPosts extends PureComponent {
keyExtractor = (item) => item;
onNavigatorEvent = (event) => {
if (event.type === 'NavBarButtonPress') {
if (event.id === 'close-settings') {
this.props.navigator.dismissModal({
animationType: 'slide-down',
});
}
}
};
previewPost = (post) => {
Keyboard.dismiss();

View file

@ -4,6 +4,7 @@
import React, {PureComponent} from 'react';
import PropTypes from 'prop-types';
import {ScrollView, View} from 'react-native';
import {Navigation} from 'react-native-navigation';
import {checkDialogElementForError, checkIfErrorsMatchElements} from 'mattermost-redux/utils/integration_utils';
@ -16,6 +17,7 @@ import DialogElement from './dialog_element.js';
export default class InteractiveDialog extends PureComponent {
static propTypes = {
componentId: PropTypes.string,
url: PropTypes.string.isRequired,
callbackId: PropTypes.string,
elements: PropTypes.arrayOf(PropTypes.object).isRequired,
@ -36,8 +38,6 @@ export default class InteractiveDialog extends PureComponent {
constructor(props) {
super(props);
props.navigator.setOnNavigatorEvent(this.onNavigatorEvent);
const values = {};
props.elements.forEach((e) => {
values[e.name] = e.default || null;
@ -50,19 +50,21 @@ export default class InteractiveDialog extends PureComponent {
};
}
onNavigatorEvent = (event) => {
if (event.type === 'NavBarButtonPress') {
switch (event.id) {
case 'submit-dialog':
this.handleSubmit();
break;
case 'close-dialog':
this.notifyOnCancelIfNeeded();
this.handleHide();
break;
}
componentDidMount() {
this.navigationEventListener = Navigation.events().bindComponent(this);
}
navigationButtonPressed({buttonId}) {
switch (buttonId) {
case 'submit-dialog':
this.handleSubmit();
break;
case 'close-dialog':
this.notifyOnCancelIfNeeded();
this.handleHide();
break;
}
};
}
handleSubmit = async () => {
const {elements} = this.props;

View file

@ -21,9 +21,9 @@ describe('InteractiveDialog', () => {
submitInteractiveDialog: jest.fn(),
},
navigator: {
setOnNavigatorEvent: jest.fn(),
dismissModal: jest.fn(),
},
componentId: 'component-id',
};
test('should set default values', async () => {
@ -74,7 +74,7 @@ describe('InteractiveDialog', () => {
cancelled: true,
};
wrapper.instance().onNavigatorEvent({type: 'NavBarButtonPress', id: 'close-dialog'});
wrapper.instance().navigationButtonPressed({buttonId: 'close-dialog'});
expect(submitInteractiveDialog).toHaveBeenCalledTimes(1);
expect(submitInteractiveDialog).toHaveBeenCalledWith(dialog);
});
@ -89,7 +89,7 @@ describe('InteractiveDialog', () => {
/>,
);
wrapper.instance().onNavigatorEvent({type: 'NavBarButtonPress', id: 'close-dialog'});
wrapper.instance().navigationButtonPressed({buttonId: 'close-dialog'});
expect(submitInteractiveDialog).not.toHaveBeenCalled();
});
});

View file

@ -11,6 +11,7 @@ import {
import {intlShape} from 'react-intl';
import * as Animatable from 'react-native-animatable';
import MaterialIcon from 'react-native-vector-icons/MaterialIcons';
import {Navigation} from 'react-native-navigation';
import FileAttachmentList from 'app/components/file_attachment_list';
import FormattedText from 'app/components/formatted_text';
@ -65,10 +66,14 @@ export default class LongPost extends PureComponent {
intl: intlShape.isRequired,
};
constructor(props) {
super(props);
componentDidMount() {
this.navigationEventListener = Navigation.events().bindComponent(this);
}
props.navigator.setOnNavigatorEvent(this.onNavigatorEvent);
navigationButtonPressed({buttonId}) {
if (buttonId === 'backPress') {
this.handleClose();
}
}
goToThread = preventDoubleTap((post) => {
@ -117,16 +122,6 @@ export default class LongPost extends PureComponent {
}
};
onNavigatorEvent = (event) => {
switch (event.id) {
case 'backPress':
this.handleClose();
break;
default:
break;
}
};
renderFileAttachments(style) {
const {
fileIds,

View file

@ -5,6 +5,7 @@ import React, {PureComponent} from 'react';
import PropTypes from 'prop-types';
import {intlShape} from 'react-intl';
import {Platform, View} from 'react-native';
import {Navigation} from 'react-native-navigation';
import {debounce} from 'mattermost-redux/actions/helpers';
import {General} from 'mattermost-redux/constants';
@ -29,6 +30,7 @@ export default class MoreChannels extends PureComponent {
searchChannels: PropTypes.func.isRequired,
setChannelDisplayName: PropTypes.func.isRequired,
}).isRequired,
componentId: PropTypes.string,
canCreateChannels: PropTypes.bool.isRequired,
channels: PropTypes.array,
closeButton: PropTypes.object,
@ -79,11 +81,12 @@ export default class MoreChannels extends PureComponent {
buttons.rightButtons = [this.rightButton];
}
props.navigator.setOnNavigatorEvent(this.onNavigatorEvent);
props.navigator.setButtons(buttons);
}
componentDidMount() {
this.navigationEventListener = Navigation.events().bindComponent(this);
this.doGetChannels();
}
@ -92,7 +95,7 @@ export default class MoreChannels extends PureComponent {
let channels;
if (this.props.theme !== nextProps.theme) {
setNavigatorStyles(this.props.navigator, nextProps.theme);
setNavigatorStyles(this.props.componentId, nextProps.theme);
}
if (nextProps.channels !== this.props.channels) {
@ -107,6 +110,17 @@ export default class MoreChannels extends PureComponent {
}
}
navigationButtonPressed({buttonId}) {
switch (buttonId) {
case 'close-more-channels':
this.close();
break;
case 'create-pub-channel':
this.onCreateChannel();
break;
}
}
cancelSearch = () => {
const {channels} = this.props;
@ -166,19 +180,6 @@ export default class MoreChannels extends PureComponent {
this.setState({loading: false});
};
onNavigatorEvent = (event) => {
if (event.type === 'NavBarButtonPress') {
switch (event.id) {
case 'close-more-channels':
this.close();
break;
case 'create-pub-channel':
this.onCreateChannel();
break;
}
}
};
onSelectChannel = async (id) => {
const {intl} = this.context;
const {actions, currentTeamId, currentUserId} = this.props;

View file

@ -12,7 +12,6 @@ jest.mock('react-intl');
describe('MoreChannels', () => {
const navigator = {
setOnNavigatorEvent: jest.fn(),
setButtons: jest.fn(),
dismissModal: jest.fn(),
push: jest.fn(),
@ -35,6 +34,7 @@ describe('MoreChannels', () => {
currentTeamId: 'current_team_id',
navigator,
theme: Preferences.THEMES.default,
componentId: 'component-id',
};
test('should match snapshot', () => {

View file

@ -5,6 +5,7 @@ import React, {PureComponent} from 'react';
import PropTypes from 'prop-types';
import {intlShape} from 'react-intl';
import {Platform, View} from 'react-native';
import {Navigation} from 'react-native-navigation';
import {debounce} from 'mattermost-redux/actions/helpers';
import {General} from 'mattermost-redux/constants';
@ -39,6 +40,7 @@ export default class MoreDirectMessages extends PureComponent {
searchProfiles: PropTypes.func.isRequired,
setChannelDisplayName: PropTypes.func.isRequired,
}).isRequired,
componentId: PropTypes.string,
allProfiles: PropTypes.object.isRequired,
currentDisplayName: PropTypes.string,
currentTeamId: PropTypes.string.isRequired,
@ -70,23 +72,32 @@ export default class MoreDirectMessages extends PureComponent {
selectedCount: 0,
};
props.navigator.setOnNavigatorEvent(this.onNavigatorEvent);
this.updateNavigationButtons(false, context);
}
componentDidMount() {
this.navigationEventListener = Navigation.events().bindComponent(this);
this.getProfiles();
}
componentDidUpdate(prevProps) {
const {navigator, theme} = this.props;
const {componentId, theme} = this.props;
const {selectedCount, startingConversation} = this.state;
const canStart = selectedCount > 0 && !startingConversation;
this.updateNavigationButtons(canStart);
if (theme !== prevProps.theme) {
setNavigatorStyles(navigator, theme);
setNavigatorStyles(componentId, theme);
}
}
navigationButtonPressed({buttonId}) {
if (buttonId === START_BUTTON) {
this.startConversation();
} else if (buttonId === CLOSE_BUTTON) {
this.close();
}
}
@ -235,16 +246,6 @@ export default class MoreDirectMessages extends PureComponent {
return !result.error;
};
onNavigatorEvent = (event) => {
if (event.type === 'NavBarButtonPress') {
if (event.id === START_BUTTON) {
this.startConversation();
} else if (event.id === CLOSE_BUTTON) {
this.close();
}
}
};
onSearch = (text) => {
if (text) {
this.setState({term: text});

View file

@ -13,6 +13,7 @@ import {intlShape} from 'react-intl';
import * as Animatable from 'react-native-animatable';
import MaterialIcon from 'react-native-vector-icons/MaterialIcons';
import AwesomeIcon from 'react-native-vector-icons/FontAwesome';
import {Navigation} from 'react-native-navigation';
import {General} from 'mattermost-redux/constants';
import EventEmitter from 'mattermost-redux/utils/event_emitter';
@ -57,6 +58,7 @@ export default class Permalink extends PureComponent {
setChannelDisplayName: PropTypes.func.isRequired,
setChannelLoading: PropTypes.func.isRequired,
}).isRequired,
componentId: PropTypes.string,
channelId: PropTypes.string,
channelIsArchived: PropTypes.bool,
channelName: PropTypes.string,
@ -131,8 +133,6 @@ export default class Permalink extends PureComponent {
loading = false;
}
props.navigator.setOnNavigatorEvent(this.onNavigatorEvent);
this.state = {
title: channelName,
loading,
@ -146,6 +146,8 @@ export default class Permalink extends PureComponent {
}
componentDidMount() {
this.navigationEventListener = Navigation.events().bindComponent(this);
this.mounted = true;
if (this.state.loading) {
@ -163,6 +165,12 @@ export default class Permalink extends PureComponent {
this.mounted = false;
}
navigationButtonPressed({buttonId}) {
if (buttonId === 'backPress') {
this.handleClose();
}
}
goToThread = preventDoubleTap((post) => {
const {actions, navigator, theme} = this.props;
const channelId = post.channel_id;
@ -315,16 +323,6 @@ export default class Permalink extends PureComponent {
}
};
onNavigatorEvent = (event) => {
switch (event.id) {
case 'backPress':
this.handleClose();
break;
default:
break;
}
};
retry = () => {
if (this.mounted) {
this.setState({loading: true, error: null, retry: false});

View file

@ -16,7 +16,6 @@ describe('Permalink', () => {
dismissModal: jest.fn(),
push: jest.fn(),
resetTo: jest.fn(),
setOnNavigatorEvent: jest.fn(),
};
const actions = {
@ -48,6 +47,7 @@ describe('Permalink', () => {
onPress: jest.fn(),
postIds: ['post_id_1', 'focused_post_id', 'post_id_3'],
theme: Preferences.THEMES.default,
componentId: 'component-id',
};
test('should match snapshot', () => {
@ -82,7 +82,7 @@ describe('Permalink', () => {
);
wrapper.instance().handleClose = jest.fn();
wrapper.instance().onNavigatorEvent({id: 'backPress'});
wrapper.instance().navigationButtonPressed({buttonId: 'backPress'});
expect(wrapper.instance().handleClose).toHaveBeenCalledTimes(1);
});

View file

@ -11,6 +11,7 @@ import {
SafeAreaView,
View,
} from 'react-native';
import {Navigation} from 'react-native-navigation';
import {isDateLine, getDateForDateLine} from 'mattermost-redux/utils/post_list';
@ -27,6 +28,7 @@ import noResultsImage from 'assets/images/no_results/pin.png';
export default class PinnedPosts extends PureComponent {
static propTypes = {
componentId: PropTypes.string,
actions: PropTypes.shape({
clearSearch: PropTypes.func.isRequired,
loadChannelsByTeamName: PropTypes.func.isRequired,
@ -52,18 +54,22 @@ export default class PinnedPosts extends PureComponent {
intl: intlShape.isRequired,
};
constructor(props) {
super(props);
props.navigator.setOnNavigatorEvent(this.onNavigatorEvent);
}
componentDidMount() {
this.navigationEventListener = Navigation.events().bindComponent(this);
const {actions, currentChannelId} = this.props;
actions.clearSearch();
actions.getPinnedPosts(currentChannelId);
}
navigationButtonPressed({buttonId}) {
if (buttonId === 'close-settings') {
this.props.navigator.dismissModal({
animationType: 'slide-down',
});
}
}
goToThread = (post) => {
const {actions, navigator, theme} = this.props;
const channelId = post.channel_id;
@ -113,16 +119,6 @@ export default class PinnedPosts extends PureComponent {
keyExtractor = (item) => item;
onNavigatorEvent = (event) => {
if (event.type === 'NavBarButtonPress') {
if (event.id === 'close-settings') {
this.props.navigator.dismissModal({
animationType: 'slide-down',
});
}
}
};
previewPost = (post) => {
Keyboard.dismiss();

View file

@ -24,23 +24,6 @@ exports[`ReactionList should match snapshot 1`] = `
>
<ReactionRow
emojiName="+1"
navigator={
Object {
"setOnNavigatorEvent": [MockFunction] {
"calls": Array [
Array [
[Function],
],
],
"results": Array [
Object {
"type": "return",
"value": undefined,
},
],
},
}
}
teammateNameDisplay="username"
theme={
Object {
@ -96,23 +79,6 @@ exports[`ReactionList should match snapshot 1`] = `
>
<ReactionRow
emojiName="smile"
navigator={
Object {
"setOnNavigatorEvent": [MockFunction] {
"calls": Array [
Array [
[Function],
],
],
"results": Array [
Object {
"type": "return",
"value": undefined,
},
],
},
}
}
teammateNameDisplay="username"
theme={
Object {
@ -174,23 +140,6 @@ Array [
>
<ReactionRow
emojiName="+1"
navigator={
Object {
"setOnNavigatorEvent": [MockFunction] {
"calls": Array [
Array [
[Function],
],
],
"results": Array [
Object {
"type": "return",
"value": undefined,
},
],
},
}
}
teammateNameDisplay="username"
theme={
Object {
@ -246,23 +195,6 @@ Array [
>
<ReactionRow
emojiName="smile"
navigator={
Object {
"setOnNavigatorEvent": [MockFunction] {
"calls": Array [
Array [
[Function],
],
],
"results": Array [
Object {
"type": "return",
"value": undefined,
},
],
},
}
}
teammateNameDisplay="username"
theme={
Object {

View file

@ -4,6 +4,7 @@
import React, {PureComponent} from 'react';
import PropTypes from 'prop-types';
import {View} from 'react-native';
import {Navigation} from 'react-native-navigation';
import {intlShape} from 'react-intl';
@ -28,6 +29,7 @@ export default class ReactionList extends PureComponent {
actions: PropTypes.shape({
getMissingProfilesByIds: PropTypes.func.isRequired,
}).isRequired,
componentId: PropTypes.string,
navigator: PropTypes.object,
reactions: PropTypes.object.isRequired,
theme: PropTypes.object.isRequired,
@ -58,8 +60,6 @@ export default class ReactionList extends PureComponent {
userProfiles,
userProfilesById: generateUserProfilesById(userProfiles),
};
props.navigator.setOnNavigatorEvent(this.onNavigatorEvent);
}
static getDerivedStateFromProps(nextProps, prevState) {
@ -90,6 +90,8 @@ export default class ReactionList extends PureComponent {
}
componentDidMount() {
this.navigationEventListener = Navigation.events().bindComponent(this);
this.getMissingProfiles();
}
@ -99,13 +101,11 @@ export default class ReactionList extends PureComponent {
}
}
onNavigatorEvent = (event) => {
if (event.type === 'NavBarButtonPress') {
if (event.id === 'close-reaction-list') {
this.close();
}
navigationButtonPressed({buttonId}) {
if (buttonId === 'close-reaction-list') {
this.close();
}
};
}
close = () => {
this.props.navigator.dismissModal({

View file

@ -17,11 +17,11 @@ describe('ReactionList', () => {
getMissingProfilesByIds: jest.fn(),
},
allUserIds: ['user_id_1', 'user_id_2'],
navigator: {setOnNavigatorEvent: jest.fn()},
reactions: {'user_id_1-smile': {emoji_name: 'smile', user_id: 'user_id_1'}, 'user_id_2-+1': {emoji_name: '+1', user_id: 'user_id_2'}},
theme: Preferences.THEMES.default,
teammateNameDisplay: 'username',
userProfiles: [{id: 'user_id_1', username: 'username_1'}, {id: 'user_id_2', username: 'username_2'}],
componentId: 'component-id',
};
test('should match snapshot', () => {

View file

@ -11,6 +11,7 @@ import {
StyleSheet,
View,
} from 'react-native';
import {Navigation} from 'react-native-navigation';
import {isDateLine, getDateForDateLine} from 'mattermost-redux/utils/post_list';
@ -54,11 +55,14 @@ export default class RecentMentions extends PureComponent {
constructor(props) {
super(props);
props.navigator.setOnNavigatorEvent(this.onNavigatorEvent);
props.actions.clearSearch();
props.actions.getRecentMentions();
}
componentDidMount() {
this.navigationEventListener = Navigation.events().bindComponent(this);
}
goToThread = (post) => {
const {actions, navigator, theme} = this.props;
const channelId = post.channel_id;
@ -108,15 +112,13 @@ export default class RecentMentions extends PureComponent {
keyExtractor = (item) => item;
onNavigatorEvent = (event) => {
if (event.type === 'NavBarButtonPress') {
if (event.id === 'close-settings') {
this.props.navigator.dismissModal({
animationType: 'slide-down',
});
}
navigationButtonPressed({buttonId}) {
if (buttonId === 'close-settings') {
this.props.navigator.dismissModal({
animationType: 'slide-down',
});
}
};
}
previewPost = (post) => {
Keyboard.dismiss();

View file

@ -12,6 +12,7 @@ import {
View,
} from 'react-native';
import AwesomeIcon from 'react-native-vector-icons/FontAwesome';
import {Navigation} from 'react-native-navigation';
import {debounce} from 'mattermost-redux/actions/helpers';
import {RequestStatus} from 'mattermost-redux/constants';
@ -85,8 +86,6 @@ export default class Search extends PureComponent {
constructor(props) {
super(props);
props.navigator.setOnNavigatorEvent(this.onNavigatorEvent);
this.contentOffsetY = 0;
this.state = {
channelName: '',
@ -97,6 +96,8 @@ export default class Search extends PureComponent {
}
componentDidMount() {
this.navigationEventListener = Navigation.events().bindComponent(this);
if (this.props.initialValue) {
this.search(this.props.initialValue);
}
@ -140,6 +141,16 @@ export default class Search extends PureComponent {
}
}
navigationButtonPressed({buttonId}) {
if (buttonId === 'backPress') {
if (this.state.preview) {
this.refs.preview.handleClose();
} else {
this.props.navigator.dismissModal();
}
}
}
archivedIndicator = (postID, style) => {
const channelIsArchived = this.props.archivedPostIds.includes(postID);
let archivedIndicator = null;
@ -298,16 +309,6 @@ export default class Search extends PureComponent {
}
}, 100);
onNavigatorEvent = (event) => {
if (event.id === 'backPress') {
if (this.state.preview) {
this.refs.preview.handleClose();
} else {
this.props.navigator.dismissModal();
}
}
};
previewPost = (post) => {
Keyboard.dismiss();

View file

@ -84,6 +84,8 @@ export default class SelectServer extends PureComponent {
}
componentDidMount() {
this.navigationEventListener = Navigation.events().bindComponent(this);
const {allowOtherServers, serverUrl} = this.props;
if (!allowOtherServers && serverUrl) {
// If the app is managed or AutoSelectServerUrl is true in the Config, the server url is set and the user can't change it

View file

@ -10,6 +10,7 @@ import {
TouchableOpacity,
View,
} from 'react-native';
import {Navigation} from 'react-native-navigation';
import {RequestStatus} from 'mattermost-redux/constants';
import EventEmitter from 'mattermost-redux/utils/event_emitter';
@ -45,6 +46,7 @@ export default class SelectTeam extends PureComponent {
joinTeam: PropTypes.func.isRequired,
logout: PropTypes.func.isRequired,
}).isRequired,
componentId: PropTypes.string,
currentUrl: PropTypes.string.isRequired,
navigator: PropTypes.object,
userWithoutTeams: PropTypes.bool,
@ -59,7 +61,6 @@ export default class SelectTeam extends PureComponent {
constructor(props) {
super(props);
props.navigator.setOnNavigatorEvent(this.onNavigatorEvent);
this.state = {
loading: false,
@ -71,12 +72,14 @@ export default class SelectTeam extends PureComponent {
}
componentDidMount() {
this.navigationEventListener = Navigation.events().bindComponent(this);
this.getTeams();
}
componentWillReceiveProps(nextProps) {
if (this.props.theme !== nextProps.theme) {
setNavigatorStyles(this.props.navigator, nextProps.theme);
setNavigatorStyles(this.props.componentId, nextProps.theme);
}
if (this.props.teams !== nextProps.teams) {
@ -84,6 +87,19 @@ export default class SelectTeam extends PureComponent {
}
}
navigationButtonPressed({buttonId}) {
const {logout} = this.props.actions;
switch (buttonId) {
case 'close-teams':
this.close();
break;
case 'logout':
InteractionManager.runAfterInteractions(logout);
break;
}
}
getTeams = () => {
this.setState({loading: true});
this.props.actions.getTeams(this.state.page, TEAMS_PER_PAGE).then(() => {
@ -131,21 +147,6 @@ export default class SelectTeam extends PureComponent {
});
};
onNavigatorEvent = (event) => {
if (event.type === 'NavBarButtonPress') {
const {logout} = this.props.actions;
switch (event.id) {
case 'close-teams':
this.close();
break;
case 'logout':
InteractionManager.runAfterInteractions(logout);
break;
}
}
};
onSelectTeam = async (team) => {
this.setState({joining: true});
const {userWithoutTeams} = this.props;

View file

@ -35,15 +35,13 @@ describe('SelectTeam', () => {
actions,
currentChannelId: 'someId',
currentUrl: 'test',
navigator: {
setOnNavigatorEvent: jest.fn(),
},
userWithoutTeams: false,
teams: [],
theme: Preferences.THEMES.default,
teamsRequest: {
status: RequestStatus.FAILURE,
},
componentId: 'component-id',
};
test('should match snapshot for fail of teams', async () => {

View file

@ -35,6 +35,7 @@ export default class SelectorScreen extends PureComponent {
searchProfiles: PropTypes.func.isRequired,
searchChannels: PropTypes.func.isRequired,
}),
componentId: PropTypes.string,
currentTeamId: PropTypes.string.isRequired,
data: PropTypes.arrayOf(PropTypes.object),
dataSource: PropTypes.string,
@ -65,8 +66,6 @@ export default class SelectorScreen extends PureComponent {
searchResults: [],
term: '',
};
props.navigator.setOnNavigatorEvent(this.onNavigatorEvent);
}
componentDidMount() {
@ -85,7 +84,7 @@ export default class SelectorScreen extends PureComponent {
componentDidUpdate(prevProps) {
if (this.props.theme !== prevProps.theme) {
setNavigatorStyles(this.props.navigator, this.props.theme);
setNavigatorStyles(this.props.componentId, this.props.theme);
}
}

View file

@ -72,9 +72,6 @@ describe('SelectorScreen', () => {
const baseProps = {
actions,
currentTeamId: 'someId',
navigator: {
setOnNavigatorEvent: jest.fn(),
},
onSelect: jest.fn(),
data: [{text: 'text', value: 'value'}],
dataSource: null,

View file

@ -8,6 +8,7 @@ import {
Platform,
View,
} from 'react-native';
import {Navigation} from 'react-native-navigation';
import SettingsItem from 'app/screens/settings/settings_item';
import StatusBar from 'app/components/status_bar';
@ -18,6 +19,7 @@ import ClockDisplay from 'app/screens/clock_display';
export default class DisplaySettings extends PureComponent {
static propTypes = {
componentId: PropTypes.string,
navigator: PropTypes.object.isRequired,
theme: PropTypes.object.isRequired,
enableTheme: PropTypes.bool.isRequired,
@ -32,9 +34,14 @@ export default class DisplaySettings extends PureComponent {
showClockDisplaySettings: false,
};
constructor(props) {
super(props);
props.navigator.setOnNavigatorEvent(this.onNavigatorEvent);
componentDidMount() {
this.navigationEventListener = Navigation.events().bindComponent(this);
}
// TODO: Remove this once styles are passed in push call in
// app/screens/settings/general/settings.js
componentDidAppear() {
setNavigatorStyles(this.props.componentId, this.props.theme);
}
closeClockDisplaySettings = () => {
@ -100,12 +107,6 @@ export default class DisplaySettings extends PureComponent {
});
});
onNavigatorEvent = (event) => {
if (event.id === 'willAppear') {
setNavigatorStyles(this.props.navigator, this.props.theme);
}
};
render() {
const {theme, enableTimezone, enableTheme} = this.props;
const {showClockDisplaySettings} = this.state;

View file

@ -17,8 +17,8 @@ describe('DisplaySettings', () => {
enableTimezone: false,
navigator: {
push: jest.fn(),
setOnNavigatorEvent: jest.fn(),
},
componentId: 'component-id',
};
test('should match snapshot', () => {

View file

@ -11,6 +11,7 @@ import {
View,
} from 'react-native';
import DeviceInfo from 'react-native-device-info';
import {Navigation} from 'react-native-navigation';
import SettingsItem from 'app/screens/settings/settings_item';
import StatusBar from 'app/components/status_bar';
@ -27,6 +28,7 @@ class Settings extends PureComponent {
clearErrors: PropTypes.func.isRequired,
purgeOfflineStore: PropTypes.func.isRequired,
}).isRequired,
componentId: PropTypes.string,
config: PropTypes.object.isRequired,
currentTeamId: PropTypes.string.isRequired,
currentUserId: PropTypes.string.isRequired,
@ -43,9 +45,22 @@ class Settings extends PureComponent {
joinableTeams: [],
};
constructor(props) {
super(props);
this.props.navigator.setOnNavigatorEvent(this.onNavigatorEvent);
componentDidMount() {
this.navigationEventListener = Navigation.events().bindComponent(this);
}
// TODO: Remove this once styles are passed in push/showModal call in
// app/components/sidebars/settings/settings_sidebar.js
componentDidAppear() {
setNavigatorStyles(this.props.componentId, this.props.theme);
}
navigationButtonPressed({buttonId}) {
if (buttonId === 'close-settings') {
this.props.navigator.dismissModal({
animationType: 'slide-down',
});
}
}
errorEmailBody = () => {
@ -107,6 +122,10 @@ class Settings extends PureComponent {
goToDisplaySettings = preventDoubleTap(() => {
const {intl, navigator, theme} = this.props;
// TODO: Ensure all styles used in app/utils/theme's setNavigatorStyles
// are passed to DisplaySettings when this push call is updated to RNN v2
// then remove setNavigatorStyles call in app/screens/settings/display_settings/display_settings.js
navigator.push({
screen: 'DisplaySettings',
title: intl.formatMessage({id: 'user.settings.modal.display', defaultMessage: 'Display'}),
@ -178,20 +197,6 @@ class Settings extends PureComponent {
});
});
onNavigatorEvent = (event) => {
if (event.id === 'willAppear') {
setNavigatorStyles(this.props.navigator, this.props.theme);
}
if (event.type === 'NavBarButtonPress') {
if (event.id === 'close-settings') {
this.props.navigator.dismissModal({
animationType: 'slide-down',
});
}
}
};
openErrorEmail = preventDoubleTap(() => {
const {config} = this.props;
const recipient = config.SupportEmail;

View file

@ -27,6 +27,7 @@ class NotificationSettings extends PureComponent {
actions: PropTypes.shape({
updateMe: PropTypes.func.isRequired,
}),
componentId: PropTypes.string,
currentUser: PropTypes.object.isRequired,
intl: intlShape.isRequired,
navigator: PropTypes.object,
@ -38,7 +39,7 @@ class NotificationSettings extends PureComponent {
componentWillReceiveProps(nextProps) {
if (this.props.theme !== nextProps.theme) {
setNavigatorStyles(this.props.navigator, nextProps.theme);
setNavigatorStyles(this.props.componentId, nextProps.theme);
}
const {updateMeRequest, intl} = nextProps;

View file

@ -7,9 +7,11 @@ import PropTypes from 'prop-types';
import {
View,
} from 'react-native';
import {General} from 'mattermost-redux/constants';
import {Navigation} from 'react-native-navigation';
import {intlShape} from 'react-intl';
import {General} from 'mattermost-redux/constants';
import FormattedText from 'app/components/formatted_text';
import StatusBar from 'app/components/status_bar';
import TextInputWithLocalizedPlaceholder from 'app/components/text_input_with_localized_placeholder';
@ -44,8 +46,6 @@ export default class NotificationSettingsAutoResponder extends PureComponent {
defaultMessage: 'Hello, I am out of office and unable to respond to messages.',
});
props.navigator.setOnNavigatorEvent(this.onNavigatorEvent);
let autoResponderActive = 'false';
if (props.currentUserStatus === General.OUT_OF_OFFICE && notifyProps.auto_responder_active) {
autoResponderActive = 'true';
@ -58,15 +58,13 @@ export default class NotificationSettingsAutoResponder extends PureComponent {
};
}
onNavigatorEvent = (event) => {
if (event.type === 'ScreenChangedEvent') {
switch (event.id) {
case 'willDisappear':
this.saveUserNotifyProps();
break;
}
}
};
componentDidMount() {
this.navigationEventListener = Navigation.events().bindComponent(this);
}
componentWillUnmount() {
this.saveUserNotifyProps();
}
saveUserNotifyProps = () => {
this.props.onBack({

View file

@ -6,7 +6,6 @@ import React from 'react';
import Preferences from 'mattermost-redux/constants/preferences';
import {shallowWithIntl} from 'test/intl-test-helper';
import {emptyFunction} from 'app/utils/general';
import RadioButtonGroup from 'app/components/radio_button';
@ -23,7 +22,6 @@ describe('NotificationSettingsEmailAndroid', () => {
currentUser: {id: 'current_user_id'},
emailInterval: '30',
enableEmailBatching: false,
navigator: {setOnNavigatorEvent: emptyFunction},
actions: {
updateMe: jest.fn(),
savePreferences: jest.fn(),
@ -31,6 +29,7 @@ describe('NotificationSettingsEmailAndroid', () => {
sendEmailNotifications: true,
siteName: 'Mattermost',
theme: Preferences.THEMES.default,
componentId: 'component-id',
};
test('should match snapshot', () => {
@ -154,13 +153,15 @@ describe('NotificationSettingsEmailAndroid', () => {
const instance = wrapper.instance();
instance.saveEmailNotifyProps = jest.fn();
// should not save preference on back button on Android
// Back button on Android should close the modal and trigger
// componentDidDisappear.
// Should not save preference on back button on Android as
// saving email preference on Android is done via Save button
instance.onNavigatorEvent({type: 'ScreenChangedEvent', id: 'willDisappear'});
instance.componentDidDisappear();
expect(instance.saveEmailNotifyProps).toHaveBeenCalledTimes(0);
wrapper.setState({newInterval: '0'});
instance.onNavigatorEvent({type: 'ScreenChangedEvent', id: 'willDisappear'});
instance.componentDidDisappear();
expect(instance.saveEmailNotifyProps).toHaveBeenCalledTimes(0);
});
});

View file

@ -6,8 +6,6 @@ import {shallow} from 'enzyme';
import Preferences from 'mattermost-redux/constants/preferences';
import {emptyFunction} from 'app/utils/general';
import SectionItem from 'app/screens/settings/section_item';
import NotificationSettingsEmailIos from './notification_settings_email.ios.js';
@ -31,7 +29,6 @@ describe('NotificationSettingsEmailIos', () => {
currentUser: {id: 'current_user_id'},
emailInterval: '30',
enableEmailBatching: false,
navigator: {setOnNavigatorEvent: emptyFunction},
actions: {
updateMe: jest.fn(),
savePreferences: jest.fn(),
@ -39,6 +36,7 @@ describe('NotificationSettingsEmailIos', () => {
sendEmailNotifications: true,
siteName: 'Mattermost',
theme: Preferences.THEMES.default,
componentId: 'component-id',
};
test('should match snapshot, renderEmailSection', () => {
@ -57,13 +55,13 @@ describe('NotificationSettingsEmailIos', () => {
const instance = wrapper.instance();
// should not save preference if email interval has not changed.
instance.onNavigatorEvent({type: 'ScreenChangedEvent', id: 'willDisappear'});
instance.componentDidDisappear();
expect(baseProps.actions.updateMe).toHaveBeenCalledTimes(0);
expect(baseProps.actions.savePreferences).toHaveBeenCalledTimes(0);
// should save preference if email interval has changed.
wrapper.setState({newInterval: '0'});
instance.onNavigatorEvent({type: 'ScreenChangedEvent', id: 'willDisappear'});
instance.componentDidDisappear();
expect(baseProps.actions.updateMe).toHaveBeenCalledTimes(1);
expect(baseProps.actions.savePreferences).toHaveBeenCalledTimes(1);
});

View file

@ -4,6 +4,7 @@
import {PureComponent} from 'react';
import {Platform} from 'react-native';
import PropTypes from 'prop-types';
import {Navigation} from 'react-native-navigation';
import {Preferences} from 'mattermost-redux/constants';
import {getEmailInterval} from 'mattermost-redux/utils/notify_props';
@ -17,10 +18,10 @@ export default class NotificationSettingsEmailBase extends PureComponent {
savePreferences: PropTypes.func.isRequired,
updateMe: PropTypes.func.isRequired,
}),
componentId: PropTypes.string,
currentUser: PropTypes.object.isRequired,
emailInterval: PropTypes.string.isRequired,
enableEmailBatching: PropTypes.bool.isRequired,
navigator: PropTypes.object,
sendEmailNotifications: PropTypes.bool.isRequired,
siteName: PropTypes.string,
theme: PropTypes.object.isRequired,
@ -33,7 +34,6 @@ export default class NotificationSettingsEmailBase extends PureComponent {
currentUser,
emailInterval,
enableEmailBatching,
navigator,
sendEmailNotifications,
} = props;
@ -44,13 +44,15 @@ export default class NotificationSettingsEmailBase extends PureComponent {
newInterval: this.computeEmailInterval(notifyProps?.email === 'true' && sendEmailNotifications, enableEmailBatching, emailInterval),
showEmailNotificationsModal: false,
};
}
navigator.setOnNavigatorEvent(this.onNavigatorEvent);
componentDidMount() {
this.navigationEventListener = Navigation.events().bindComponent(this);
}
componentWillReceiveProps(nextProps) {
if (this.props.theme !== nextProps.theme) {
setNavigatorStyles(this.props.navigator, nextProps.theme);
setNavigatorStyles(this.props.componentId, nextProps.theme);
}
const {
@ -74,15 +76,11 @@ export default class NotificationSettingsEmailBase extends PureComponent {
}
}
onNavigatorEvent = (event) => {
if (Platform.OS === 'ios' && event.type === 'ScreenChangedEvent') {
switch (event.id) {
case 'willDisappear':
this.saveEmailNotifyProps();
break;
}
componentDidDisappear() {
if (Platform.OS === 'ios') {
this.saveEmailNotifyProps();
}
};
}
setEmailInterval = (value) => {
this.setState({newInterval: value});

View file

@ -4,12 +4,14 @@
import {PureComponent} from 'react';
import PropTypes from 'prop-types';
import {intlShape} from 'react-intl';
import {Navigation} from 'react-native-navigation';
import {getNotificationProps} from 'app/utils/notify_props';
import {setNavigatorStyles} from 'app/utils/theme';
export default class NotificationSettingsMentionsBase extends PureComponent {
static propTypes = {
componentId: PropTypes.string,
currentUser: PropTypes.object.isRequired,
intl: intlShape.isRequired,
navigator: PropTypes.object,
@ -27,27 +29,25 @@ export default class NotificationSettingsMentionsBase extends PureComponent {
const {currentUser} = props;
const notifyProps = getNotificationProps(currentUser);
props.navigator.setOnNavigatorEvent(this.onNavigatorEvent);
this.goingBack = true; //use to identify if the navigator is popping this screen
this.state = this.setStateFromNotifyProps(notifyProps);
}
componentDidMount() {
this.navigationEventListener = Navigation.events().bindComponent(this);
}
componentWillReceiveProps(nextProps) {
if (this.props.theme !== nextProps.theme) {
setNavigatorStyles(this.props.navigator, nextProps.theme);
setNavigatorStyles(this.props.componentId, nextProps.theme);
}
}
onNavigatorEvent = (event) => {
if (event.type === 'ScreenChangedEvent' && this.goingBack) {
switch (event.id) {
case 'willDisappear':
this.saveUserNotifyProps();
break;
}
componentDidDisappear() {
if (this.goingBack) {
this.saveUserNotifyProps();
}
};
}
setStateFromNotifyProps = (notifyProps) => {
const mentionKeys = (notifyProps.mention_keys || '').split(',');

View file

@ -3,6 +3,7 @@
import React, {PureComponent} from 'react';
import PropTypes from 'prop-types';
import {ScrollView, View} from 'react-native';
import {Navigation} from 'react-native-navigation';
import FormattedText from 'app/components/formatted_text';
import StatusBar from 'app/components/status_bar';
@ -11,6 +12,7 @@ import {changeOpacity, makeStyleSheetFromTheme, setNavigatorStyles} from 'app/ut
export default class NotificationSettingsMentionsKeywords extends PureComponent {
static propTypes = {
componentId: PropTypes.string,
keywords: PropTypes.string,
navigator: PropTypes.object,
onBack: PropTypes.func.isRequired,
@ -23,13 +25,15 @@ export default class NotificationSettingsMentionsKeywords extends PureComponent
this.state = {
keywords: props.keywords,
};
}
props.navigator.setOnNavigatorEvent(this.onNavigatorEvent);
componentDidMount() {
this.navigationEventListener = Navigation.events().bindComponent(this);
}
componentWillReceiveProps(nextProps) {
if (this.props.theme !== nextProps.theme) {
setNavigatorStyles(this.props.navigator, nextProps.theme);
setNavigatorStyles(this.props.componentId, nextProps.theme);
}
}
@ -45,15 +49,9 @@ export default class NotificationSettingsMentionsKeywords extends PureComponent
return this.setState({keywords});
};
onNavigatorEvent = (event) => {
if (event.type === 'ScreenChangedEvent') {
switch (event.id) {
case 'willDisappear':
this.props.onBack(this.state.keywords);
break;
}
}
};
componentDidDisappear() {
this.props.onBack(this.state.keywords);
}
render() {
const {theme} = this.props;

View file

@ -5,12 +5,14 @@ import {PureComponent} from 'react';
import {Platform} from 'react-native';
import PropTypes from 'prop-types';
import {intlShape} from 'react-intl';
import {Navigation} from 'react-native-navigation';
import {getNotificationProps} from 'app/utils/notify_props';
import {setNavigatorStyles} from 'app/utils/theme';
export default class NotificationSettingsMobileBase extends PureComponent {
static propTypes = {
componentId: PropTypes.string,
config: PropTypes.object.isRequired,
currentUser: PropTypes.object.isRequired,
intl: intlShape.isRequired,
@ -37,12 +39,15 @@ export default class NotificationSettingsMobileBase extends PureComponent {
showMobilePushStatusModal: false,
showMobileSoundsModal: false,
};
props.navigator.setOnNavigatorEvent(this.onNavigatorEvent);
}
componentDidMount() {
this.navigationEventListener = Navigation.events().bindComponent(this);
}
componentWillReceiveProps(nextProps) {
if (this.props.theme !== nextProps.theme) {
setNavigatorStyles(this.props.navigator, nextProps.theme);
setNavigatorStyles(this.props.componentId, nextProps.theme);
}
}
@ -79,15 +84,9 @@ export default class NotificationSettingsMobileBase extends PureComponent {
return {};
};
onNavigatorEvent = (event) => {
if (event.type === 'ScreenChangedEvent') {
switch (event.id) {
case 'willDisappear':
this.saveUserNotifyProps();
break;
}
}
};
componentDidDisappear() {
this.saveUserNotifyProps();
}
setMobilePush = (push) => {
this.setState({push});

View file

@ -124,19 +124,6 @@ exports[`TermsOfService should enable/disable navigator buttons on setNavigatorB
},
],
},
"setOnNavigatorEvent": [MockFunction] {
"calls": Array [
Array [
[Function],
],
],
"results": Array [
Object {
"type": "return",
"value": undefined,
},
],
},
}
}
textStyles={
@ -376,19 +363,6 @@ exports[`TermsOfService should enable/disable navigator buttons on setNavigatorB
},
],
},
"setOnNavigatorEvent": [MockFunction] {
"calls": Array [
Array [
[Function],
],
],
"results": Array [
Object {
"type": "return",
"value": undefined,
},
],
},
}
}
textStyles={
@ -677,19 +651,6 @@ exports[`TermsOfService should match snapshot on enableNavigatorLogout 1`] = `
},
],
},
"setOnNavigatorEvent": [MockFunction] {
"calls": Array [
Array [
[Function],
],
],
"results": Array [
Object {
"type": "return",
"value": undefined,
},
],
},
}
}
textStyles={

View file

@ -9,6 +9,7 @@ import {
View,
} from 'react-native';
import {intlShape} from 'react-intl';
import {Navigation} from 'react-native-navigation';
import FailedNetworkAction from 'app/components/failed_network_action';
import Loading from 'app/components/loading';
@ -36,6 +37,7 @@ export default class TermsOfService extends PureComponent {
getTermsOfService: PropTypes.func.isRequired,
updateMyTermsOfServiceStatus: PropTypes.func.isRequired,
}).isRequired,
componentId: PropTypes.string,
closeButton: PropTypes.object,
navigator: PropTypes.object,
siteName: PropTypes.string,
@ -72,37 +74,36 @@ export default class TermsOfService extends PureComponent {
this.rightButton.title = context.intl.formatMessage({id: 'terms_of_service.agreeButton', defaultMessage: 'I Agree'});
this.leftButton.icon = props.closeButton;
props.navigator.setOnNavigatorEvent(this.onNavigatorEvent);
this.setNavigatorButtons(false);
}
componentDidMount() {
this.navigationEventListener = Navigation.events().bindComponent(this);
this.getTerms();
}
componentDidUpdate(prevProps) {
if (this.props.theme !== prevProps.theme) {
setNavigatorStyles(this.props.navigator, this.props.theme);
setNavigatorStyles(this.props.componentId, this.props.theme);
}
}
onNavigatorEvent = (event) => {
if (event.type === 'NavBarButtonPress') {
switch (event.id) {
case 'close-terms-of-service':
this.closeTermsAndLogout();
break;
navigationButtonPressed({buttonId}) {
switch (buttonId) {
case 'close-terms-of-service':
this.closeTermsAndLogout();
break;
case 'reject-terms-of-service':
this.handleRejectTerms();
break;
case 'reject-terms-of-service':
this.handleRejectTerms();
break;
case 'accept-terms-of-service':
this.handleAcceptTerms();
break;
}
case 'accept-terms-of-service':
this.handleAcceptTerms();
break;
}
};
}
setNavigatorButtons = (enabled = true) => {
const buttons = {

View file

@ -31,11 +31,11 @@ describe('TermsOfService', () => {
dismissAllModals: jest.fn(),
dismissModal: jest.fn(),
setButtons: jest.fn(),
setOnNavigatorEvent: jest.fn(),
},
theme: Preferences.THEMES.default,
closeButton: {},
siteName: 'Mattermost',
componentId: 'component-id',
};
test('should match snapshot', () => {

View file

@ -17,6 +17,7 @@ import {changeOpacity, makeStyleSheetFromTheme, setNavigatorStyles} from 'app/ut
export default class TextPreview extends React.PureComponent {
static propTypes = {
componentId: PropTypes.string,
navigator: PropTypes.object.isRequired,
theme: PropTypes.object.isRequired,
content: PropTypes.string.isRequired,
@ -24,7 +25,7 @@ export default class TextPreview extends React.PureComponent {
componentWillReceiveProps(nextProps) {
if (this.props.theme !== nextProps.theme) {
setNavigatorStyles(this.props.navigator, nextProps.theme);
setNavigatorStyles(this.props.componentId, nextProps.theme);
}
}

View file

@ -27,11 +27,11 @@ export default class Theme extends React.PureComponent {
actions: PropTypes.shape({
savePreferences: PropTypes.func.isRequired,
}).isRequired,
componentId: PropTypes.string,
allowedThemes: PropTypes.arrayOf(PropTypes.object),
customTheme: PropTypes.object,
isLandscape: PropTypes.bool.isRequired,
isTablet: PropTypes.bool.isRequired,
navigator: PropTypes.object.isRequired,
teamId: PropTypes.string.isRequired,
theme: PropTypes.object.isRequired,
userId: PropTypes.string.isRequired,
@ -56,7 +56,7 @@ export default class Theme extends React.PureComponent {
componentDidUpdate(prevProps) {
if (prevProps.theme !== this.props.theme) {
setNavigatorStyles(this.props.navigator, this.props.theme);
setNavigatorStyles(this.props.componentId, this.props.theme);
}
}

View file

@ -131,9 +131,6 @@ describe('Theme', () => {
allowedThemes,
isLandscape: false,
isTablet: false,
navigator: {
setOnNavigatorEvent: jest.fn(),
},
teamId: 'test-team',
theme: Preferences.THEMES.default,
userId: 'test-user',

View file

@ -17,6 +17,7 @@ export default class ThreadBase extends PureComponent {
actions: PropTypes.shape({
selectPost: PropTypes.func.isRequired,
}).isRequired,
componentId: PropTypes.string,
channelId: PropTypes.string.isRequired,
channelType: PropTypes.string,
displayName: PropTypes.string,
@ -63,7 +64,7 @@ export default class ThreadBase extends PureComponent {
componentWillReceiveProps(nextProps) {
if (this.props.theme !== nextProps.theme) {
setNavigatorStyles(this.props.navigator, nextProps.theme);
setNavigatorStyles(this.props.componentId, nextProps.theme);
}
if (this.props.postIds !== nextProps.postIds && !nextProps.postIds.length) {

View file

@ -10,6 +10,7 @@ import {
Linking,
} from 'react-native';
import {intlShape} from 'react-intl';
import {Navigation} from 'react-native-navigation';
import {displayUsername} from 'mattermost-redux/utils/user_utils';
import {getUserCurrentTimezone} from 'mattermost-redux/utils/timezone_utils';
@ -33,6 +34,7 @@ export default class UserProfile extends PureComponent {
setChannelDisplayName: PropTypes.func.isRequired,
loadBot: PropTypes.func.isRequired,
}).isRequired,
componentId: PropTypes.string,
config: PropTypes.object.isRequired,
currentDisplayName: PropTypes.string,
navigator: PropTypes.object,
@ -65,23 +67,35 @@ export default class UserProfile extends PureComponent {
rightButtons: [this.rightButton],
};
props.navigator.setOnNavigatorEvent(this.onNavigatorEvent);
props.navigator.setButtons(buttons);
}
}
componentWillReceiveProps(nextProps) {
if (this.props.theme !== nextProps.theme) {
setNavigatorStyles(this.props.navigator, nextProps.theme);
setNavigatorStyles(this.props.componentId, nextProps.theme);
}
}
componentDidMount() {
this.navigationEventListener = Navigation.events().bindComponent(this);
if (this.props.user && this.props.user.is_bot) {
this.props.actions.loadBot(this.props.user.id);
}
}
navigationButtonPressed({buttonId}) {
switch (buttonId) {
case this.rightButton.id:
this.goToEditProfile();
break;
case 'close-settings':
this.close();
break;
}
}
close = () => {
const {navigator, theme} = this.props;
@ -241,19 +255,6 @@ export default class UserProfile extends PureComponent {
});
};
onNavigatorEvent = (event) => {
if (event.type === 'NavBarButtonPress') {
switch (event.id) {
case this.rightButton.id:
this.goToEditProfile();
break;
case 'close-settings':
this.close();
break;
}
}
};
renderAdditionalOptions = () => {
if (!Config.ExperimentalProfileLinks) {
return null;

View file

@ -39,6 +39,7 @@ describe('user_profile', () => {
enableTimezone: false,
militaryTime: false,
isMyUser: false,
componentId: 'component-id',
};
const user = {
@ -126,8 +127,8 @@ describe('user_profile', () => {
{context: {intl: {formatMessage: jest.fn()}}},
);
const event = {type: 'NavBarButtonPress', id: wrapper.instance().rightButton.id};
wrapper.instance().onNavigatorEvent(event);
const event = {buttonId: wrapper.instance().rightButton.id};
wrapper.instance().navigationButtonPressed(event);
setTimeout(() => {
expect(props.navigator.push).toHaveBeenCalledTimes(1);
}, 0);
@ -144,13 +145,13 @@ describe('user_profile', () => {
{context: {intl: {formatMessage: jest.fn()}}},
);
const event = {type: 'NavBarButtonPress', id: 'close-settings'};
wrapper.instance().onNavigatorEvent(event);
const event = {buttonId: 'close-settings'};
wrapper.instance().navigationButtonPressed(event);
expect(props.navigator.dismissModal).toHaveBeenCalledTimes(1);
props.fromSettings = false;
wrapper.setProps({...props});
wrapper.instance().onNavigatorEvent(event);
wrapper.instance().navigationButtonPressed(event);
expect(props.navigator.resetTo).toHaveBeenCalledTimes(1);
});
});

View file

@ -2,6 +2,7 @@
// See LICENSE.txt for license information.
import {StyleSheet} from 'react-native';
import {Navigation} from 'react-native-navigation';
import * as ThemeUtils from 'mattermost-redux/utils/theme_utils';
@ -19,12 +20,21 @@ export function concatStyles(...styles) {
return [].concat(styles);
}
export function setNavigatorStyles(navigator, theme) {
navigator.setStyle({
navBarTextColor: theme.sidebarHeaderTextColor,
navBarBackgroundColor: theme.sidebarHeaderBg,
navBarButtonColor: theme.sidebarHeaderTextColor,
screenBackgroundColor: theme.centerChannelBg,
export function setNavigatorStyles(componentId, theme) {
Navigation.mergeOptions(componentId, {
topBar: {
title: {
color: theme.sidebarHeaderTextColor,
},
background: {
color: theme.sidebarHeaderBg,
},
leftButtonColor: theme.sidebarHeaderTextColor,
rightButtonColor: theme.sidebarHeaderTextColor,
},
layout: {
backgroundColor: theme.centerChannelBg,
},
});
}

174
package-lock.json generated
View file

@ -5238,6 +5238,7 @@
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
"integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
"dev": true,
"optional": true,
"requires": {
"is-extendable": "^0.1.0"
}
@ -5282,7 +5283,8 @@
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
"dev": true
"dev": true,
"optional": true
},
"is-glob": {
"version": "4.0.1",
@ -7662,25 +7664,25 @@
"dependencies": {
"abbrev": {
"version": "1.1.1",
"resolved": false,
"resolved": "",
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
"optional": true
},
"ansi-regex": {
"version": "2.1.1",
"resolved": false,
"resolved": "",
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
"optional": true
},
"aproba": {
"version": "1.2.0",
"resolved": false,
"resolved": "",
"integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==",
"optional": true
},
"are-we-there-yet": {
"version": "1.1.5",
"resolved": false,
"resolved": "",
"integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==",
"optional": true,
"requires": {
@ -7690,14 +7692,15 @@
},
"balanced-match": {
"version": "1.0.0",
"resolved": false,
"resolved": "",
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
"optional": true
},
"brace-expansion": {
"version": "1.1.11",
"resolved": false,
"resolved": "",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@ -7705,37 +7708,37 @@
},
"chownr": {
"version": "1.1.1",
"resolved": false,
"resolved": "",
"integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==",
"optional": true
},
"code-point-at": {
"version": "1.1.0",
"resolved": false,
"resolved": "",
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
"optional": true
},
"concat-map": {
"version": "0.0.1",
"resolved": false,
"resolved": "",
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
"optional": true
},
"console-control-strings": {
"version": "1.1.0",
"resolved": false,
"resolved": "",
"integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=",
"optional": true
},
"core-util-is": {
"version": "1.0.2",
"resolved": false,
"resolved": "",
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
"optional": true
},
"debug": {
"version": "4.1.1",
"resolved": false,
"resolved": "",
"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
"optional": true,
"requires": {
@ -7744,25 +7747,25 @@
},
"deep-extend": {
"version": "0.6.0",
"resolved": false,
"resolved": "",
"integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
"optional": true
},
"delegates": {
"version": "1.0.0",
"resolved": false,
"resolved": "",
"integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=",
"optional": true
},
"detect-libc": {
"version": "1.0.3",
"resolved": false,
"resolved": "",
"integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=",
"optional": true
},
"fs-minipass": {
"version": "1.2.5",
"resolved": false,
"resolved": "",
"integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==",
"optional": true,
"requires": {
@ -7771,13 +7774,13 @@
},
"fs.realpath": {
"version": "1.0.0",
"resolved": false,
"resolved": "",
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
"optional": true
},
"gauge": {
"version": "2.7.4",
"resolved": false,
"resolved": "",
"integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
"optional": true,
"requires": {
@ -7793,7 +7796,7 @@
},
"glob": {
"version": "7.1.3",
"resolved": false,
"resolved": "",
"integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==",
"optional": true,
"requires": {
@ -7807,13 +7810,13 @@
},
"has-unicode": {
"version": "2.0.1",
"resolved": false,
"resolved": "",
"integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=",
"optional": true
},
"iconv-lite": {
"version": "0.4.24",
"resolved": false,
"resolved": "",
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
"optional": true,
"requires": {
@ -7822,7 +7825,7 @@
},
"ignore-walk": {
"version": "3.0.1",
"resolved": false,
"resolved": "",
"integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==",
"optional": true,
"requires": {
@ -7831,7 +7834,7 @@
},
"inflight": {
"version": "1.0.6",
"resolved": false,
"resolved": "",
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
"optional": true,
"requires": {
@ -7841,48 +7844,51 @@
},
"inherits": {
"version": "2.0.3",
"resolved": false,
"resolved": "",
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
"optional": true
},
"ini": {
"version": "1.3.5",
"resolved": false,
"resolved": "",
"integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==",
"optional": true
},
"is-fullwidth-code-point": {
"version": "1.0.0",
"resolved": false,
"resolved": "",
"integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
"optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
},
"isarray": {
"version": "1.0.0",
"resolved": false,
"resolved": "",
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
"optional": true
},
"minimatch": {
"version": "3.0.4",
"resolved": false,
"resolved": "",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
},
"minimist": {
"version": "0.0.8",
"resolved": false,
"resolved": "",
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
"optional": true
},
"minipass": {
"version": "2.3.5",
"resolved": false,
"resolved": "",
"integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==",
"optional": true,
"requires": {
"safe-buffer": "^5.1.2",
"yallist": "^3.0.0"
@ -7890,7 +7896,7 @@
},
"minizlib": {
"version": "1.2.1",
"resolved": false,
"resolved": "",
"integrity": "sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA==",
"optional": true,
"requires": {
@ -7899,21 +7905,22 @@
},
"mkdirp": {
"version": "0.5.1",
"resolved": false,
"resolved": "",
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
"optional": true,
"requires": {
"minimist": "0.0.8"
}
},
"ms": {
"version": "2.1.1",
"resolved": false,
"resolved": "",
"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
"optional": true
},
"needle": {
"version": "2.3.0",
"resolved": false,
"resolved": "",
"integrity": "sha512-QBZu7aAFR0522EyaXZM0FZ9GLpq6lvQ3uq8gteiDUp7wKdy0lSd2hPlgFwVuW1CBkfEs9PfDQsQzZghLs/psdg==",
"optional": true,
"requires": {
@ -7924,7 +7931,7 @@
},
"node-pre-gyp": {
"version": "0.12.0",
"resolved": false,
"resolved": "",
"integrity": "sha512-4KghwV8vH5k+g2ylT+sLTjy5wmUOb9vPhnM8NHvRf9dHmnW/CndrFXy2aRPaPST6dugXSdHXfeaHQm77PIz/1A==",
"optional": true,
"requires": {
@ -7942,7 +7949,7 @@
},
"nopt": {
"version": "4.0.1",
"resolved": false,
"resolved": "",
"integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=",
"optional": true,
"requires": {
@ -7952,13 +7959,13 @@
},
"npm-bundled": {
"version": "1.0.6",
"resolved": false,
"resolved": "",
"integrity": "sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g==",
"optional": true
},
"npm-packlist": {
"version": "1.4.1",
"resolved": false,
"resolved": "",
"integrity": "sha512-+TcdO7HJJ8peiiYhvPxsEDhF3PJFGUGRcFsGve3vxvxdcpO2Z4Z7rkosRM0kWj6LfbK/P0gu3dzk5RU1ffvFcw==",
"optional": true,
"requires": {
@ -7968,7 +7975,7 @@
},
"npmlog": {
"version": "4.1.2",
"resolved": false,
"resolved": "",
"integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
"optional": true,
"requires": {
@ -7980,39 +7987,40 @@
},
"number-is-nan": {
"version": "1.0.1",
"resolved": false,
"resolved": "",
"integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
"optional": true
},
"object-assign": {
"version": "4.1.1",
"resolved": false,
"resolved": "",
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
"optional": true
},
"once": {
"version": "1.4.0",
"resolved": false,
"resolved": "",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"optional": true,
"requires": {
"wrappy": "1"
}
},
"os-homedir": {
"version": "1.0.2",
"resolved": false,
"resolved": "",
"integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=",
"optional": true
},
"os-tmpdir": {
"version": "1.0.2",
"resolved": false,
"resolved": "",
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
"optional": true
},
"osenv": {
"version": "0.1.5",
"resolved": false,
"resolved": "",
"integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==",
"optional": true,
"requires": {
@ -8022,19 +8030,19 @@
},
"path-is-absolute": {
"version": "1.0.1",
"resolved": false,
"resolved": "",
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
"optional": true
},
"process-nextick-args": {
"version": "2.0.0",
"resolved": false,
"resolved": "",
"integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==",
"optional": true
},
"rc": {
"version": "1.2.8",
"resolved": false,
"resolved": "",
"integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
"optional": true,
"requires": {
@ -8046,7 +8054,7 @@
"dependencies": {
"minimist": {
"version": "1.2.0",
"resolved": false,
"resolved": "",
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
"optional": true
}
@ -8054,7 +8062,7 @@
},
"readable-stream": {
"version": "2.3.6",
"resolved": false,
"resolved": "",
"integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
"optional": true,
"requires": {
@ -8069,7 +8077,7 @@
},
"rimraf": {
"version": "2.6.3",
"resolved": false,
"resolved": "",
"integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
"optional": true,
"requires": {
@ -8078,44 +8086,45 @@
},
"safe-buffer": {
"version": "5.1.2",
"resolved": false,
"resolved": "",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
"optional": true
},
"safer-buffer": {
"version": "2.1.2",
"resolved": false,
"resolved": "",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
"optional": true
},
"sax": {
"version": "1.2.4",
"resolved": false,
"resolved": "",
"integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==",
"optional": true
},
"semver": {
"version": "5.7.0",
"resolved": false,
"resolved": "",
"integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==",
"optional": true
},
"set-blocking": {
"version": "2.0.0",
"resolved": false,
"resolved": "",
"integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
"optional": true
},
"signal-exit": {
"version": "3.0.2",
"resolved": false,
"resolved": "",
"integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=",
"optional": true
},
"string-width": {
"version": "1.0.2",
"resolved": false,
"resolved": "",
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
"optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
@ -8124,7 +8133,7 @@
},
"string_decoder": {
"version": "1.1.1",
"resolved": false,
"resolved": "",
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"optional": true,
"requires": {
@ -8133,21 +8142,22 @@
},
"strip-ansi": {
"version": "3.0.1",
"resolved": false,
"resolved": "",
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
"optional": true,
"requires": {
"ansi-regex": "^2.0.0"
}
},
"strip-json-comments": {
"version": "2.0.1",
"resolved": false,
"resolved": "",
"integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
"optional": true
},
"tar": {
"version": "4.4.8",
"resolved": false,
"resolved": "",
"integrity": "sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ==",
"optional": true,
"requires": {
@ -8162,13 +8172,13 @@
},
"util-deprecate": {
"version": "1.0.2",
"resolved": false,
"resolved": "",
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
"optional": true
},
"wide-align": {
"version": "1.1.3",
"resolved": false,
"resolved": "",
"integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==",
"optional": true,
"requires": {
@ -8177,13 +8187,13 @@
},
"wrappy": {
"version": "1.0.2",
"resolved": false,
"resolved": "",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
"optional": true
},
"yallist": {
"version": "3.0.3",
"resolved": false,
"resolved": "",
"integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==",
"optional": true
}
@ -14170,7 +14180,7 @@
"dependencies": {
"ansi-regex": {
"version": "3.0.0",
"resolved": false,
"resolved": "",
"integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
"dev": true
},
@ -14182,7 +14192,7 @@
},
"cliui": {
"version": "4.1.0",
"resolved": false,
"resolved": "",
"integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==",
"dev": true,
"requires": {
@ -14211,7 +14221,7 @@
},
"find-up": {
"version": "3.0.0",
"resolved": false,
"resolved": "",
"integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
"dev": true,
"requires": {
@ -14226,13 +14236,13 @@
},
"invert-kv": {
"version": "2.0.0",
"resolved": false,
"resolved": "",
"integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==",
"dev": true
},
"lcid": {
"version": "2.0.0",
"resolved": false,
"resolved": "",
"integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==",
"dev": true,
"requires": {
@ -14241,7 +14251,7 @@
},
"locate-path": {
"version": "3.0.0",
"resolved": false,
"resolved": "",
"integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
"dev": true,
"requires": {
@ -14268,7 +14278,7 @@
},
"os-locale": {
"version": "3.1.0",
"resolved": false,
"resolved": "",
"integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==",
"dev": true,
"requires": {
@ -14288,7 +14298,7 @@
},
"p-locate": {
"version": "3.0.0",
"resolved": false,
"resolved": "",
"integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
"dev": true,
"requires": {
@ -14309,7 +14319,7 @@
},
"resolve-from": {
"version": "4.0.0",
"resolved": false,
"resolved": "",
"integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
"dev": true
},
@ -14343,7 +14353,7 @@
},
"strip-ansi": {
"version": "4.0.0",
"resolved": false,
"resolved": "",
"integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
"dev": true,
"requires": {
@ -14352,13 +14362,13 @@
},
"uuid": {
"version": "3.3.2",
"resolved": false,
"resolved": "",
"integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==",
"dev": true
},
"y18n": {
"version": "4.0.0",
"resolved": false,
"resolved": "",
"integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==",
"dev": true
},
@ -16045,7 +16055,8 @@
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
"integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=",
"dev": true
"dev": true,
"optional": true
},
"braces": {
"version": "2.3.2",
@ -16308,7 +16319,8 @@
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
"integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
"dev": true
"dev": true,
"optional": true
},
"micromatch": {
"version": "3.1.10",