[MM-16139] [MM-16140] [MM-16141] Update the remaining screens/components (#2920)
* Update screens * Update login tests * Remove done * Fix failing tests * Update screens and components * Check styles fix * Update tests * Prevent setState call after component unmounts * Add empty setButtons func to dummy navigator * Remove platform check * Remove Platform import * Update react-native-navigation version * Add separate showModalOverCurrentContext function * check-style fixes * Remove overriding of AppDelegate's window * Fix modal over current context animation * Add showSearchModal navigation action * Check-style fix * Address review comments * Update SettingsSidebar and children * Update EditProfile screen * Update SettingsSidebar * Keep track of latest componentId to appear * Track componentId in state to use in navigation actions * Update FlaggedPosts and children * Update RecentMentions * Update Settings * Store componentIds in ephemeral store * Update AttachmentButton * Remove unnecessary dismissModal * Fix typo * Upate NotificationSettings * Update NotificationSettingsAutoResponder * Update NotificationSettingsMentions * Update NotificationSettingsMobile * Update CreateChannel and children * Update MoreChannels * Update ChannelPeek and children * Update ChannelNavBar and children * Update ChannelPostList and children * Update ChannelInfo and children * Update ChannelAddMembers * Update ChannelMembers * Update EditChannel * Fix setting of top bar buttons * Update Channel screen and children * Update PinnedPosts * Update LongPost * Update PostOptions * Update PostTextboxBase * Update EditPost * Check-styles fix * Update DisplaySettings * Update Timezone * Update SelectTimezone * Update IntlWrapper and Notification * Update InteractiveDialog and children * Update ExpandedAnnouncementBanner * Update ClientUpgradeListener * Update MoreDirectMessages * Update SelectorScreen * Update UserProfile * Update Thread * Update About * Update ImagePreview * Update TextPreview * Update AddReaction * Update ReactionList and children * Update Code * Update TermsOfService * Update Permalink * Update Permalink * Update ErrorTeamsList * Update Search * Remove navigator prop * Fix setButtons calls * Remove navigationComponentId * Fix test * Handle in-app notifs in global event handler * Fix in-app notification handling * Fix typo * Fix tests * Auto dismiss in-app notif after 5 seconds * Fix typo * Update overlay dismissal * Animate in-app notif dismissal and allow gesture dismissal
This commit is contained in:
parent
1b9b1e3f39
commit
5eee2b7652
74 changed files with 598 additions and 899 deletions
|
|
@ -178,7 +178,12 @@ export function popToRoot() {
|
|||
return () => {
|
||||
const componentId = EphemeralStore.getTopComponentId();
|
||||
|
||||
Navigation.popToRoot(componentId);
|
||||
Navigation.popToRoot(componentId).catch(() => {
|
||||
// RNN returns a promise rejection if there are no screens
|
||||
// atop the root screen to pop. We'll do nothing in this
|
||||
// case but we will catch the rejection here so that the
|
||||
// caller doesn't have to.
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -289,7 +294,11 @@ export function dismissModal(options = {}) {
|
|||
|
||||
export function dismissAllModals(options = {}) {
|
||||
return () => {
|
||||
Navigation.dismissAllModals(options);
|
||||
Navigation.dismissAllModals(options).catch(() => {
|
||||
// RNN returns a promise rejection if there are no modals to
|
||||
// dismiss. We'll do nothing in this case but we will catch
|
||||
// the rejection here so that the caller doesn't have to.
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -321,3 +330,32 @@ export function setButtons(componentId, buttons = {leftButtons: [], rightButtons
|
|||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function showOverlay(name, passProps, options = {}) {
|
||||
return () => {
|
||||
const defaultOptions = {
|
||||
overlay: {
|
||||
interceptTouchOutside: false,
|
||||
},
|
||||
};
|
||||
|
||||
Navigation.showOverlay({
|
||||
component: {
|
||||
name,
|
||||
passProps,
|
||||
options: merge(defaultOptions, options),
|
||||
},
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function dismissOverlay(componentId) {
|
||||
return () => {
|
||||
return Navigation.dismissOverlay(componentId).catch(() => {
|
||||
// RNN returns a promise rejection if there is no modal with
|
||||
// this componentId to dismiss. We'll do nothing in this case
|
||||
// but we will catch the rejection here so that the caller
|
||||
// doesn't have to.
|
||||
});
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
|
||||
|
||||
import {ViewTypes} from 'app/constants';
|
||||
|
||||
export function handleSearchDraftChanged(text) {
|
||||
|
|
@ -13,27 +11,3 @@ export function handleSearchDraftChanged(text) {
|
|||
}, getState);
|
||||
};
|
||||
}
|
||||
|
||||
// TODO: Remove this once all screens/components call
|
||||
// app/actions/navigation's showSearchModal
|
||||
export function showSearchModal(navigator, initialValue = '') {
|
||||
return (dispatch, getState) => {
|
||||
const theme = getTheme(getState());
|
||||
|
||||
const options = {
|
||||
screen: 'Search',
|
||||
animated: true,
|
||||
backButtonTitle: '',
|
||||
overrideBackPress: true,
|
||||
passProps: {
|
||||
initialValue,
|
||||
},
|
||||
navigatorStyle: {
|
||||
navBarHidden: true,
|
||||
screenBackgroundColor: theme.centerChannelBg,
|
||||
},
|
||||
};
|
||||
|
||||
navigator.showModal(options);
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,13 +9,6 @@ exports[`profile_picture_button should match snapshot 1`] = `
|
|||
]
|
||||
}
|
||||
maxFileSize={20971520}
|
||||
navigator={
|
||||
Object {
|
||||
"dismissModal": [MockFunction],
|
||||
"push": [MockFunction],
|
||||
"setButtons": [MockFunction],
|
||||
}
|
||||
}
|
||||
theme={
|
||||
Object {
|
||||
"awayIndicator": "#ffbc42",
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@ export default class ClientUpgradeListener extends PureComponent {
|
|||
actions: PropTypes.shape({
|
||||
logError: PropTypes.func.isRequired,
|
||||
setLastUpgradeCheck: PropTypes.func.isRequired,
|
||||
showModal: PropTypes.func.isRequired,
|
||||
dismissModal: PropTypes.func.isRequired,
|
||||
}).isRequired,
|
||||
currentVersion: PropTypes.string,
|
||||
downloadLink: PropTypes.string,
|
||||
|
|
@ -35,7 +37,6 @@ export default class ClientUpgradeListener extends PureComponent {
|
|||
lastUpgradeCheck: PropTypes.number,
|
||||
latestVersion: PropTypes.string,
|
||||
minVersion: PropTypes.string,
|
||||
navigator: PropTypes.object,
|
||||
theme: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
|
|
@ -140,27 +141,26 @@ export default class ClientUpgradeListener extends PureComponent {
|
|||
};
|
||||
|
||||
handleLearnMore = () => {
|
||||
const {actions} = this.props;
|
||||
const {intl} = this.context;
|
||||
this.props.navigator.dismissModal({animationType: 'none'});
|
||||
|
||||
this.props.navigator.showModal({
|
||||
screen: 'ClientUpgrade',
|
||||
title: intl.formatMessage({id: 'mobile.client_upgrade', defaultMessage: 'Upgrade App'}),
|
||||
navigatorStyle: {
|
||||
navBarHidden: false,
|
||||
statusBarHidden: false,
|
||||
statusBarHideWithNavBar: false,
|
||||
},
|
||||
navigatorButtons: {
|
||||
actions.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,
|
||||
}],
|
||||
},
|
||||
passProps: {
|
||||
upgradeType: this.state.upgradeType,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
actions.showModal(screen, title, passProps, options);
|
||||
|
||||
this.toggleUpgradeMessage(false);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -4,11 +4,12 @@ import {bindActionCreators} from 'redux';
|
|||
import {connect} from 'react-redux';
|
||||
|
||||
import {logError} from 'mattermost-redux/actions/errors';
|
||||
import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
|
||||
|
||||
import {showModal, dismissModal} from 'app/actions/navigation';
|
||||
import {setLastUpgradeCheck} from 'app/actions/views/client_upgrade';
|
||||
import getClientUpgrade from 'app/selectors/client_upgrade';
|
||||
import {isLandscape} from 'app/selectors/device';
|
||||
import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
|
||||
|
||||
import ClientUpgradeListener from './client_upgrade_listener';
|
||||
|
||||
|
|
@ -32,6 +33,8 @@ function mapDispatchToProps(dispatch) {
|
|||
actions: bindActionCreators({
|
||||
logError,
|
||||
setLastUpgradeCheck,
|
||||
showModal,
|
||||
dismissModal,
|
||||
}, dispatch),
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ export default class MessageAttachments extends PureComponent {
|
|||
deviceWidth: PropTypes.number.isRequired,
|
||||
postId: PropTypes.string.isRequired,
|
||||
metadata: PropTypes.object,
|
||||
navigator: PropTypes.object.isRequired,
|
||||
onHashtagPress: PropTypes.func,
|
||||
onPermalinkPress: PropTypes.func,
|
||||
theme: PropTypes.object,
|
||||
|
|
@ -33,7 +32,6 @@ export default class MessageAttachments extends PureComponent {
|
|||
deviceHeight,
|
||||
deviceWidth,
|
||||
metadata,
|
||||
navigator,
|
||||
onHashtagPress,
|
||||
onPermalinkPress,
|
||||
postId,
|
||||
|
|
@ -52,7 +50,6 @@ export default class MessageAttachments extends PureComponent {
|
|||
deviceWidth={deviceWidth}
|
||||
key={'att_' + i}
|
||||
metadata={metadata}
|
||||
navigator={navigator}
|
||||
onHashtagPress={onHashtagPress}
|
||||
onPermalinkPress={onPermalinkPress}
|
||||
postId={postId}
|
||||
|
|
|
|||
|
|
@ -37,7 +37,6 @@ describe('PostAttachmentOpenGraph', () => {
|
|||
},
|
||||
isReplyPost: false,
|
||||
link: 'https://mattermost.com/',
|
||||
navigator: {},
|
||||
theme: Preferences.THEMES.default,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -16,23 +16,11 @@ exports[`PostTextBox should match, full snapshot 1`] = `
|
|||
}
|
||||
}
|
||||
>
|
||||
<AttachmentButton
|
||||
<Connect(AttachmentButton)
|
||||
blurTextBox={[Function]}
|
||||
browseFileTypes="public.item"
|
||||
canBrowseFiles={true}
|
||||
canBrowsePhotoLibrary={true}
|
||||
canBrowseVideoLibrary={true}
|
||||
canTakePhoto={true}
|
||||
canTakeVideo={true}
|
||||
extraOptions={null}
|
||||
fileCount={0}
|
||||
maxFileCount={5}
|
||||
maxFileSize={1024}
|
||||
navigator={
|
||||
Object {
|
||||
"showModal": [MockFunction],
|
||||
}
|
||||
}
|
||||
onShowFileMaxWarning={[Function]}
|
||||
onShowFileSizeWarning={[Function]}
|
||||
theme={
|
||||
|
|
@ -64,7 +52,6 @@ exports[`PostTextBox should match, full snapshot 1`] = `
|
|||
}
|
||||
}
|
||||
uploadFiles={[Function]}
|
||||
validMimeTypes={Array []}
|
||||
/>
|
||||
<View
|
||||
style={
|
||||
|
|
|
|||
|
|
@ -38,9 +38,6 @@ describe('PostTextBox', () => {
|
|||
files: [],
|
||||
maxFileSize: 1024,
|
||||
maxMessageLength: 4000,
|
||||
navigator: {
|
||||
showModal: jest.fn(),
|
||||
},
|
||||
rootId: '',
|
||||
theme: Preferences.THEMES.default,
|
||||
uploadFileRequestStatus: 'NOT_STARTED',
|
||||
|
|
|
|||
|
|
@ -10,15 +10,8 @@ import ProfilePictureButton from './profile_picture_button.js';
|
|||
import {Client4} from 'mattermost-redux/client';
|
||||
|
||||
describe('profile_picture_button', () => {
|
||||
const navigator = {
|
||||
setButtons: jest.fn(),
|
||||
dismissModal: jest.fn(),
|
||||
push: jest.fn(),
|
||||
};
|
||||
|
||||
const baseProps = {
|
||||
theme: Preferences.THEMES.default,
|
||||
navigator,
|
||||
currentUser: {
|
||||
first_name: 'Dwight',
|
||||
last_name: 'Schrute',
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
import {bindActionCreators} from 'redux';
|
||||
import {connect} from 'react-redux';
|
||||
|
||||
import {getCurrentChannelId} from 'mattermost-redux/selectors/entities/channels';
|
||||
import {getCurrentUrl} from 'mattermost-redux/selectors/entities/general';
|
||||
import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
|
||||
|
||||
|
|
@ -19,7 +18,6 @@ function mapStateToProps(state) {
|
|||
|
||||
return {
|
||||
theme: getTheme(state),
|
||||
currentChannelId: getCurrentChannelId(state),
|
||||
currentUrl: removeProtocol(getCurrentUrl(state)),
|
||||
locale,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import {Platform} from 'react-native';
|
|||
import {Client4} from 'mattermost-redux/client';
|
||||
import EventEmitter from 'mattermost-redux/utils/event_emitter';
|
||||
|
||||
import {NavigationTypes, ViewTypes} from 'app/constants';
|
||||
import {NavigationTypes} from 'app/constants';
|
||||
import {getTranslations} from 'app/i18n';
|
||||
|
||||
export default class Root extends PureComponent {
|
||||
|
|
@ -18,9 +18,7 @@ export default class Root extends PureComponent {
|
|||
resetToTeams: PropTypes.func.isRequired,
|
||||
}).isRequired,
|
||||
children: PropTypes.node,
|
||||
navigator: PropTypes.object,
|
||||
excludeEvents: PropTypes.bool,
|
||||
currentChannelId: PropTypes.string,
|
||||
currentUrl: PropTypes.string,
|
||||
locale: PropTypes.string.isRequired,
|
||||
theme: PropTypes.object.isRequired,
|
||||
|
|
@ -30,8 +28,6 @@ export default class Root extends PureComponent {
|
|||
Client4.setAcceptLanguage(this.props.locale);
|
||||
|
||||
if (!this.props.excludeEvents) {
|
||||
EventEmitter.on(ViewTypes.NOTIFICATION_IN_APP, this.handleInAppNotification);
|
||||
EventEmitter.on(ViewTypes.NOTIFICATION_TAPPED, this.handleNotificationTapped);
|
||||
EventEmitter.on(NavigationTypes.NAVIGATION_NO_TEAMS, this.handleNoTeams);
|
||||
EventEmitter.on(NavigationTypes.NAVIGATION_ERROR_TEAMS, this.errorTeamsList);
|
||||
}
|
||||
|
|
@ -45,30 +41,11 @@ export default class Root extends PureComponent {
|
|||
|
||||
componentWillUnmount() {
|
||||
if (!this.props.excludeEvents) {
|
||||
EventEmitter.off(ViewTypes.NOTIFICATION_IN_APP, this.handleInAppNotification);
|
||||
EventEmitter.off(ViewTypes.NOTIFICATION_TAPPED, this.handleNotificationTapped);
|
||||
EventEmitter.off(NavigationTypes.NAVIGATION_NO_TEAMS, this.handleNoTeams);
|
||||
EventEmitter.off(NavigationTypes.NAVIGATION_ERROR_TEAMS, this.errorTeamsList);
|
||||
}
|
||||
}
|
||||
|
||||
handleInAppNotification = (notification) => {
|
||||
const {data} = notification;
|
||||
const {currentChannelId, navigator} = this.props;
|
||||
|
||||
if (data && data.channel_id !== currentChannelId) {
|
||||
navigator.showInAppNotification({
|
||||
screen: 'Notification',
|
||||
position: 'top',
|
||||
autoDismissTimerSec: 5,
|
||||
dismissWithSwipe: true,
|
||||
passProps: {
|
||||
notification,
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
handleNoTeams = () => {
|
||||
if (!this.refs.provider) {
|
||||
setTimeout(this.handleNoTeams, 200);
|
||||
|
|
@ -119,18 +96,6 @@ export default class Root extends PureComponent {
|
|||
actions.resetToTeams(screen, title, passProps, options);
|
||||
}
|
||||
|
||||
handleNotificationTapped = async () => {
|
||||
const {navigator} = this.props;
|
||||
|
||||
if (Platform.OS === 'android') {
|
||||
navigator.dismissModal({animation: 'none'});
|
||||
}
|
||||
|
||||
navigator.popToRoot({
|
||||
animated: false,
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
const locale = this.props.locale;
|
||||
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@ describe('ChannelItem', () => {
|
|||
isUnread: true,
|
||||
hasDraft: false,
|
||||
mentions: 0,
|
||||
navigator: {push: () => {}}, // eslint-disable-line no-empty-function
|
||||
onSelectChannel: () => {}, // eslint-disable-line no-empty-function
|
||||
shouldHideChannel: false,
|
||||
showUnreadForMsgs: true,
|
||||
|
|
|
|||
|
|
@ -68,10 +68,12 @@ export default class SettingsDrawer extends PureComponent {
|
|||
}
|
||||
|
||||
componentDidMount() {
|
||||
EventEmitter.on('close_settings_sidebar', this.closeSettingsSidebar);
|
||||
BackHandler.addEventListener('hardwareBackPress', this.handleAndroidBack);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
EventEmitter.off('close_settings_sidebar', this.closeSettingsSidebar);
|
||||
BackHandler.removeEventListener('hardwareBackPress', this.handleAndroidBack);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ const NavigationTypes = keyMirror({
|
|||
NAVIGATION_NO_TEAMS: null,
|
||||
RESTART_APP: null,
|
||||
NAVIGATION_ERROR_TEAMS: null,
|
||||
NAVIGATION_SHOW_OVERLAY: null,
|
||||
});
|
||||
|
||||
export default NavigationTypes;
|
||||
|
|
|
|||
|
|
@ -42,7 +42,6 @@ const ViewTypes = keyMirror({
|
|||
COMMENT_DRAFT_SELECTION_CHANGED: null,
|
||||
|
||||
NOTIFICATION_IN_APP: null,
|
||||
NOTIFICATION_TAPPED: null,
|
||||
|
||||
SET_POST_DRAFT: null,
|
||||
SET_COMMENT_DRAFT: null,
|
||||
|
|
|
|||
|
|
@ -11,11 +11,13 @@ import {close as closeWebSocket} from 'mattermost-redux/actions/websocket';
|
|||
import {Client4} from 'mattermost-redux/client';
|
||||
import {General} from 'mattermost-redux/constants';
|
||||
import EventEmitter from 'mattermost-redux/utils/event_emitter';
|
||||
import {getCurrentChannelId} from 'mattermost-redux/selectors/entities/channels';
|
||||
|
||||
import {setDeviceDimensions, setDeviceOrientation, setDeviceAsTablet, setStatusBarHeight} from 'app/actions/device';
|
||||
import {selectDefaultChannel} from 'app/actions/views/channel';
|
||||
import {showOverlay} from 'app/actions/navigation';
|
||||
import {loadConfigAndLicense, setDeepLinkURL, startDataCleanup} from 'app/actions/views/root';
|
||||
import {NavigationTypes} from 'app/constants';
|
||||
import {NavigationTypes, ViewTypes} from 'app/constants';
|
||||
import {getTranslations} from 'app/i18n';
|
||||
import mattermostManaged from 'app/mattermost_managed';
|
||||
import PushNotifications from 'app/push_notifications';
|
||||
|
|
@ -38,12 +40,15 @@ class GlobalEventHandler {
|
|||
EventEmitter.on(General.SERVER_VERSION_CHANGED, this.onServerVersionChanged);
|
||||
EventEmitter.on(General.CONFIG_CHANGED, this.onServerConfigChanged);
|
||||
EventEmitter.on(General.SWITCH_TO_DEFAULT_CHANNEL, this.onSwitchToDefaultChannel);
|
||||
this.turnOnInAppNotificationHandling();
|
||||
Dimensions.addEventListener('change', this.onOrientationChange);
|
||||
AppState.addEventListener('change', this.onAppStateChange);
|
||||
Linking.addEventListener('url', this.onDeepLink);
|
||||
}
|
||||
|
||||
appActive = async () => {
|
||||
this.turnOnInAppNotificationHandling();
|
||||
|
||||
// if the app is being controlled by an EMM provider
|
||||
if (emmProvider.enabled && emmProvider.inAppPinCode) {
|
||||
const authExpired = (Date.now() - emmProvider.inBackgroundSince) >= PROMPT_IN_APP_PIN_CODE_AFTER;
|
||||
|
|
@ -57,6 +62,8 @@ class GlobalEventHandler {
|
|||
};
|
||||
|
||||
appInactive = () => {
|
||||
this.turnOffInAppNotificationHandling();
|
||||
|
||||
const {dispatch} = this.store;
|
||||
|
||||
// When the app is sent to the background we set the time when that happens
|
||||
|
|
@ -227,6 +234,31 @@ class GlobalEventHandler {
|
|||
dispatch(logout());
|
||||
}
|
||||
};
|
||||
|
||||
turnOnInAppNotificationHandling = () => {
|
||||
EventEmitter.on(ViewTypes.NOTIFICATION_IN_APP, this.handleInAppNotification);
|
||||
}
|
||||
|
||||
turnOffInAppNotificationHandling = () => {
|
||||
EventEmitter.off(ViewTypes.NOTIFICATION_IN_APP, this.handleInAppNotification);
|
||||
}
|
||||
|
||||
handleInAppNotification = (notification) => {
|
||||
const {data} = notification;
|
||||
const {dispatch, getState} = this.store;
|
||||
const state = getState();
|
||||
const currentChannelId = getCurrentChannelId(state);
|
||||
|
||||
if (data && data.channel_id !== currentChannelId) {
|
||||
const screen = 'Notification';
|
||||
const passProps = {
|
||||
notification,
|
||||
};
|
||||
|
||||
EventEmitter.emit(NavigationTypes.NAVIGATION_SHOW_OVERLAY);
|
||||
dispatch(showOverlay(screen, passProps));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default new GlobalEventHandler();
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@ export default class About extends PureComponent {
|
|||
componentId: PropTypes.string,
|
||||
config: PropTypes.object.isRequired,
|
||||
license: PropTypes.object.isRequired,
|
||||
navigator: PropTypes.object.isRequired,
|
||||
theme: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -15,9 +15,12 @@ import {setNavigatorStyles} from 'app/utils/theme';
|
|||
|
||||
export default class AddReaction extends PureComponent {
|
||||
static propTypes = {
|
||||
actions: PropTypes.shape({
|
||||
dismissModal: PropTypes.func.isRequired,
|
||||
setButtons: PropTypes.func.isRequired,
|
||||
}).isRequired,
|
||||
componentId: PropTypes.string,
|
||||
closeButton: PropTypes.object,
|
||||
navigator: PropTypes.object.isRequired,
|
||||
onEmojiPress: PropTypes.func,
|
||||
theme: PropTypes.object.isRequired,
|
||||
};
|
||||
|
|
@ -33,7 +36,7 @@ export default class AddReaction extends PureComponent {
|
|||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
props.navigator.setButtons({
|
||||
props.actions.setButtons(props.componentId, {
|
||||
leftButtons: [{...this.leftButton, icon: props.closeButton}],
|
||||
});
|
||||
}
|
||||
|
|
@ -55,9 +58,7 @@ export default class AddReaction extends PureComponent {
|
|||
}
|
||||
|
||||
close = () => {
|
||||
this.props.navigator.dismissModal({
|
||||
animationType: 'slide-down',
|
||||
});
|
||||
this.props.actions.dismissModal();
|
||||
};
|
||||
|
||||
handleEmojiPress = (emoji) => {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,13 @@
|
|||
// 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 {getTheme} from 'mattermost-redux/selectors/entities/preferences';
|
||||
|
||||
import {dismissModal, setButtons} from 'app/actions/navigation';
|
||||
|
||||
import AddReaction from './add_reaction';
|
||||
|
||||
function mapStateToProps(state) {
|
||||
|
|
@ -13,4 +16,13 @@ function mapStateToProps(state) {
|
|||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps)(AddReaction);
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
actions: bindActionCreators({
|
||||
dismissModal,
|
||||
setButtons,
|
||||
}, dispatch),
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(AddReaction);
|
||||
|
|
|
|||
|
|
@ -20,35 +20,30 @@ import ChannelBase, {ClientUpgradeListener, style} from './channel_base';
|
|||
export default class ChannelAndroid extends ChannelBase {
|
||||
render() {
|
||||
const {height} = Dimensions.get('window');
|
||||
const {
|
||||
navigator,
|
||||
} = this.props;
|
||||
|
||||
const channelLoaderStyle = [style.channelLoader, {height}];
|
||||
const drawerContent = (
|
||||
<SafeAreaView navigator={navigator}>
|
||||
<SafeAreaView>
|
||||
<StatusBar/>
|
||||
<NetworkIndicator/>
|
||||
<ChannelNavBar
|
||||
navigator={navigator}
|
||||
openChannelDrawer={this.openChannelSidebar}
|
||||
openSettingsDrawer={this.openSettingsSidebar}
|
||||
onPress={this.goToChannelInfo}
|
||||
/>
|
||||
<KeyboardLayout>
|
||||
<View style={style.flex}>
|
||||
<ChannelPostList navigator={navigator}/>
|
||||
<ChannelPostList/>
|
||||
</View>
|
||||
<PostTextbox
|
||||
ref={this.postTextbox}
|
||||
navigator={navigator}
|
||||
/>
|
||||
</KeyboardLayout>
|
||||
<ChannelLoader
|
||||
height={height}
|
||||
style={channelLoaderStyle}
|
||||
/>
|
||||
{LocalConfig.EnableMobileClientUpgrade && <ClientUpgradeListener navigator={navigator}/>}
|
||||
{LocalConfig.EnableMobileClientUpgrade && <ClientUpgradeListener/>}
|
||||
</SafeAreaView>
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,6 @@ export default class ChannelIOS extends ChannelBase {
|
|||
const {height} = Dimensions.get('window');
|
||||
const {
|
||||
currentChannelId,
|
||||
navigator,
|
||||
} = this.props;
|
||||
|
||||
const channelLoaderStyle = [style.channelLoader, {height}];
|
||||
|
|
@ -48,17 +47,15 @@ export default class ChannelIOS extends ChannelBase {
|
|||
|
||||
const drawerContent = (
|
||||
<React.Fragment>
|
||||
<SafeAreaView navigator={navigator}>
|
||||
<SafeAreaView>
|
||||
<StatusBar/>
|
||||
<NetworkIndicator/>
|
||||
<ChannelNavBar
|
||||
navigator={navigator}
|
||||
openChannelDrawer={this.openChannelSidebar}
|
||||
openSettingsDrawer={this.openSettingsSidebar}
|
||||
onPress={this.goToChannelInfo}
|
||||
/>
|
||||
<ChannelPostList
|
||||
navigator={navigator}
|
||||
updateNativeScrollView={this.updateNativeScrollView}
|
||||
/>
|
||||
<View nativeID={ACCESSORIES_CONTAINER_NATIVE_ID}>
|
||||
|
|
@ -74,7 +71,7 @@ export default class ChannelIOS extends ChannelBase {
|
|||
height={height}
|
||||
style={channelLoaderStyle}
|
||||
/>
|
||||
{LocalConfig.EnableMobileClientUpgrade && <ClientUpgradeListener navigator={navigator}/>}
|
||||
{LocalConfig.EnableMobileClientUpgrade && <ClientUpgradeListener/>}
|
||||
</SafeAreaView>
|
||||
<KeyboardTrackingView
|
||||
ref={this.keyboardTracker}
|
||||
|
|
@ -85,7 +82,6 @@ export default class ChannelIOS extends ChannelBase {
|
|||
cursorPositionEvent={CHANNEL_POST_TEXTBOX_CURSOR_CHANGE}
|
||||
valueEvent={CHANNEL_POST_TEXTBOX_VALUE_CHANGE}
|
||||
ref={this.postTextbox}
|
||||
navigator={navigator}
|
||||
/>
|
||||
</KeyboardTrackingView>
|
||||
</React.Fragment>
|
||||
|
|
|
|||
|
|
@ -18,8 +18,10 @@ import {changeOpacity, makeStyleSheetFromTheme, setNavigatorStyles} from 'app/ut
|
|||
|
||||
export default class Code extends React.PureComponent {
|
||||
static propTypes = {
|
||||
actions: PropTypes.shape({
|
||||
popTopScreen: PropTypes.func.isRequired,
|
||||
}).isRequired,
|
||||
componentId: PropTypes.string,
|
||||
navigator: PropTypes.object.isRequired,
|
||||
theme: PropTypes.object.isRequired,
|
||||
content: PropTypes.string.isRequired,
|
||||
};
|
||||
|
|
@ -39,7 +41,7 @@ export default class Code extends React.PureComponent {
|
|||
}
|
||||
|
||||
handleAndroidBack = () => {
|
||||
this.props.navigator.pop();
|
||||
this.props.actions.popTopScreen();
|
||||
return true;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,13 @@
|
|||
// 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 {getTheme} from 'mattermost-redux/selectors/entities/preferences';
|
||||
|
||||
import {popTopScreen} from 'app/actions/navigation';
|
||||
|
||||
import Code from './code';
|
||||
|
||||
function mapStateToProps(state) {
|
||||
|
|
@ -13,4 +16,12 @@ function mapStateToProps(state) {
|
|||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps)(Code);
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
actions: bindActionCreators({
|
||||
popTopScreen,
|
||||
}, dispatch),
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(Code);
|
||||
|
|
@ -32,9 +32,9 @@ export default class ErrorTeamsList extends PureComponent {
|
|||
connection: PropTypes.func.isRequired,
|
||||
logout: PropTypes.func.isRequired,
|
||||
selectDefaultTeam: PropTypes.func.isRequired,
|
||||
resetToChannel: PropTypes.func.isRequired,
|
||||
}).isRequired,
|
||||
componentId: PropTypes.string,
|
||||
navigator: PropTypes.object,
|
||||
theme: PropTypes.object,
|
||||
};
|
||||
|
||||
|
|
@ -64,21 +64,10 @@ export default class ErrorTeamsList extends PureComponent {
|
|||
}
|
||||
|
||||
goToChannelView = () => {
|
||||
const {navigator, theme} = this.props;
|
||||
|
||||
navigator.resetTo({
|
||||
screen: 'Channel',
|
||||
animated: false,
|
||||
navigatorStyle: {
|
||||
navBarHidden: true,
|
||||
statusBarHidden: false,
|
||||
statusBarHideWithNavBar: false,
|
||||
screenBackgroundColor: theme.centerChannelBg,
|
||||
},
|
||||
passProps: {
|
||||
disableTermsModal: true,
|
||||
},
|
||||
});
|
||||
const passProps = {
|
||||
disableTermsModal: true,
|
||||
};
|
||||
this.props.actions.resetToChannel(passProps);
|
||||
};
|
||||
|
||||
getUserInfo = async () => {
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ describe('ErrorTeamsList', () => {
|
|||
connection: () => {}, // eslint-disable-line no-empty-function
|
||||
logout: () => {}, // eslint-disable-line no-empty-function
|
||||
selectDefaultTeam: () => {}, // eslint-disable-line no-empty-function
|
||||
resetToChannel: jest.fn(),
|
||||
},
|
||||
componentId: 'component-id',
|
||||
theme: Preferences.THEMES.default,
|
||||
|
|
@ -39,6 +40,7 @@ describe('ErrorTeamsList', () => {
|
|||
const selectDefaultTeam = jest.fn();
|
||||
const logout = jest.fn();
|
||||
const actions = {
|
||||
...baseProps.actions,
|
||||
loadMe,
|
||||
logout,
|
||||
selectDefaultTeam,
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ import {logout, loadMe} from 'mattermost-redux/actions/users';
|
|||
import {connection} from 'app/actions/device';
|
||||
import {selectDefaultTeam} from 'app/actions/views/select_team';
|
||||
|
||||
import {resetToChannel} from 'app/actions/navigation';
|
||||
|
||||
import ErrorTeamsList from './error_teams_list.js';
|
||||
|
||||
function mapDispatchToProps(dispatch) {
|
||||
|
|
@ -17,6 +19,7 @@ function mapDispatchToProps(dispatch) {
|
|||
selectDefaultTeam,
|
||||
connection,
|
||||
loadMe,
|
||||
resetToChannel,
|
||||
}, dispatch),
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,15 +16,15 @@ export default class ExpandedAnnouncementBanner extends React.PureComponent {
|
|||
static propTypes = {
|
||||
actions: PropTypes.shape({
|
||||
dismissBanner: PropTypes.func.isRequired,
|
||||
popTopScreen: PropTypes.func.isRequired,
|
||||
}).isRequired,
|
||||
allowDismissal: PropTypes.bool.isRequired,
|
||||
bannerText: PropTypes.string.isRequired,
|
||||
navigator: PropTypes.object.isRequired,
|
||||
theme: PropTypes.object.isRequired,
|
||||
}
|
||||
|
||||
close = () => {
|
||||
this.props.navigator.pop();
|
||||
this.props.actions.popTopScreen();
|
||||
};
|
||||
|
||||
dismissBanner = () => {
|
||||
|
|
@ -67,7 +67,6 @@ export default class ExpandedAnnouncementBanner extends React.PureComponent {
|
|||
<Markdown
|
||||
baseTextStyle={style.baseTextStyle}
|
||||
blockStyles={getMarkdownBlockStyles(this.props.theme)}
|
||||
navigator={this.props.navigator}
|
||||
onChannelLinkPress={this.handleChannelLinkPress}
|
||||
textStyles={getMarkdownTextStyles(this.props.theme)}
|
||||
value={this.props.bannerText}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import {connect} from 'react-redux';
|
|||
import {getConfig} from 'mattermost-redux/selectors/entities/general';
|
||||
import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
|
||||
|
||||
import {popTopScreen} from 'app/actions/navigation';
|
||||
import {dismissBanner} from 'app/actions/views/announcement';
|
||||
|
||||
import ExpandedAnnouncementBanner from './expanded_announcement_banner';
|
||||
|
|
@ -25,6 +26,7 @@ function mapDispatchToProps(dispatch) {
|
|||
return {
|
||||
actions: bindActionCreators({
|
||||
dismissBanner,
|
||||
popTopScreen,
|
||||
}, dispatch),
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import LinearGradient from 'react-native-linear-gradient';
|
|||
import {intlShape} from 'react-intl';
|
||||
import Permissions from 'react-native-permissions';
|
||||
import Gallery from 'react-native-image-gallery';
|
||||
import {Navigation} from 'react-native-navigation';
|
||||
|
||||
import EventEmitter from 'mattermost-redux/utils/event_emitter';
|
||||
|
||||
|
|
@ -43,13 +44,17 @@ const ANIM_CONFIG = {duration: 300};
|
|||
|
||||
export default class ImagePreview extends PureComponent {
|
||||
static propTypes = {
|
||||
actions: PropTypes.shape({
|
||||
dismissModal: PropTypes.func.isRequired,
|
||||
showModalOverCurrentContext: PropTypes.func.isRequired,
|
||||
}).isRequired,
|
||||
componentId: PropTypes.string.isRequired,
|
||||
canDownloadFiles: PropTypes.bool.isRequired,
|
||||
deviceHeight: PropTypes.number.isRequired,
|
||||
deviceWidth: PropTypes.number.isRequired,
|
||||
files: PropTypes.array,
|
||||
getItemMeasures: PropTypes.func.isRequired,
|
||||
index: PropTypes.number.isRequired,
|
||||
navigator: PropTypes.object,
|
||||
origin: PropTypes.object,
|
||||
target: PropTypes.object,
|
||||
theme: PropTypes.object.isRequired,
|
||||
|
|
@ -66,8 +71,10 @@ export default class ImagePreview extends PureComponent {
|
|||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
props.navigator.setStyle({
|
||||
screenBackgroundColor: '#000',
|
||||
Navigation.mergeOptions(props.componentId, {
|
||||
layout: {
|
||||
backgroundColor: '#000',
|
||||
},
|
||||
});
|
||||
|
||||
this.openAnim = new Animated.Value(0);
|
||||
|
|
@ -103,12 +110,14 @@ export default class ImagePreview extends PureComponent {
|
|||
};
|
||||
|
||||
close = () => {
|
||||
const {getItemMeasures, navigator} = this.props;
|
||||
const {actions, getItemMeasures, componentId} = this.props;
|
||||
const {index} = this.state;
|
||||
|
||||
this.setState({animating: true});
|
||||
navigator.setStyle({
|
||||
screenBackgroundColor: 'transparent',
|
||||
Navigation.mergeOptions(componentId, {
|
||||
layout: {
|
||||
backgroundColor: 'transparent',
|
||||
},
|
||||
});
|
||||
|
||||
getItemMeasures(index, (origin) => {
|
||||
|
|
@ -117,7 +126,7 @@ export default class ImagePreview extends PureComponent {
|
|||
}
|
||||
|
||||
this.animateOpenAnimToValue(0, () => {
|
||||
navigator.dismissModal({animationType: 'none'});
|
||||
actions.dismissModal();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
|
@ -177,7 +186,7 @@ export default class ImagePreview extends PureComponent {
|
|||
};
|
||||
|
||||
renderAttachmentDocument = (file) => {
|
||||
const {canDownloadFiles, theme, navigator} = this.props;
|
||||
const {canDownloadFiles, theme} = this.props;
|
||||
|
||||
return (
|
||||
<View style={[style.flex, style.center]}>
|
||||
|
|
@ -190,7 +199,6 @@ export default class ImagePreview extends PureComponent {
|
|||
file={file}
|
||||
iconHeight={100}
|
||||
iconWidth={100}
|
||||
navigator={navigator}
|
||||
theme={theme}
|
||||
wrapperHeight={200}
|
||||
wrapperWidth={200}
|
||||
|
|
@ -441,6 +449,7 @@ export default class ImagePreview extends PureComponent {
|
|||
};
|
||||
|
||||
showDownloadOptionsIOS = async () => {
|
||||
const {actions} = this.props;
|
||||
const {formatMessage} = this.context.intl;
|
||||
const file = this.getCurrentFile();
|
||||
const items = [];
|
||||
|
|
@ -504,30 +513,17 @@ export default class ImagePreview extends PureComponent {
|
|||
});
|
||||
}
|
||||
|
||||
const options = {
|
||||
title: file.caption,
|
||||
items,
|
||||
onCancelPress: () => this.setHeaderAndFooterVisible(true),
|
||||
};
|
||||
|
||||
if (items.length) {
|
||||
this.setHeaderAndFooterVisible(false);
|
||||
|
||||
this.props.navigator.showModal({
|
||||
screen: 'OptionsModal',
|
||||
title: '',
|
||||
animationType: 'none',
|
||||
passProps: {
|
||||
...options,
|
||||
},
|
||||
navigatorStyle: {
|
||||
navBarHidden: true,
|
||||
statusBarHidden: false,
|
||||
statusBarHideWithNavBar: false,
|
||||
screenBackgroundColor: 'transparent',
|
||||
modalPresentationStyle: 'overCurrentContext',
|
||||
},
|
||||
});
|
||||
const screen = 'OptionsModal';
|
||||
const passProps = {
|
||||
title: file.caption,
|
||||
items,
|
||||
onCancelPress: () => this.setHeaderAndFooterVisible(true),
|
||||
};
|
||||
|
||||
actions.showModalOverCurrentContext(screen, passProps);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import {shallow} from 'enzyme';
|
|||
import {
|
||||
TouchableOpacity,
|
||||
} from 'react-native';
|
||||
import {Navigation} from 'react-native-navigation';
|
||||
|
||||
import Preferences from 'mattermost-redux/constants/preferences';
|
||||
|
||||
|
|
@ -18,6 +19,13 @@ jest.mock('react-native-doc-viewer', () => {
|
|||
OpenFile: jest.fn(),
|
||||
};
|
||||
});
|
||||
jest.mock('react-native-navigation', () => ({
|
||||
Navigation: {
|
||||
mergeOptions: jest.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
Navigation.mergeOptions = jest.fn();
|
||||
|
||||
describe('ImagePreview', () => {
|
||||
const baseProps = {
|
||||
|
|
@ -30,10 +38,14 @@ describe('ImagePreview', () => {
|
|||
],
|
||||
getItemMeasures: jest.fn(),
|
||||
index: 0,
|
||||
navigator: {setStyle: jest.fn()},
|
||||
origin: {},
|
||||
target: {},
|
||||
theme: Preferences.THEMES.default,
|
||||
componentId: 'component-id',
|
||||
actions: {
|
||||
dismissModal: jest.fn(),
|
||||
showModalOverCurrentContext: jest.fn(),
|
||||
},
|
||||
};
|
||||
|
||||
test('should match snapshot', () => {
|
||||
|
|
@ -67,21 +79,26 @@ describe('ImagePreview', () => {
|
|||
expect(wrapper.state('index')).toEqual(1);
|
||||
});
|
||||
|
||||
test('should match call getItemMeasures & navigator.setStyle on close', () => {
|
||||
test('should match call getItemMeasures & Navigation.mergeOptions on close', () => {
|
||||
const getItemMeasures = jest.fn();
|
||||
const navigator = {setStyle: jest.fn()};
|
||||
const wrapper = shallow(
|
||||
<ImagePreview
|
||||
{...baseProps}
|
||||
getItemMeasures={getItemMeasures}
|
||||
navigator={navigator}
|
||||
/>,
|
||||
{context: {intl: {formatMessage: jest.fn()}}},
|
||||
);
|
||||
|
||||
wrapper.instance().close();
|
||||
|
||||
expect(navigator.setStyle).toHaveBeenCalledTimes(2);
|
||||
expect(navigator.setStyle).toBeCalledWith({screenBackgroundColor: 'transparent'});
|
||||
expect(Navigation.mergeOptions).toHaveBeenCalledTimes(2);
|
||||
expect(Navigation.mergeOptions).toHaveBeenCalledWith(
|
||||
baseProps.componentId,
|
||||
{
|
||||
layout: {
|
||||
backgroundColor: 'transparent',
|
||||
},
|
||||
},
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,12 +1,15 @@
|
|||
// 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 {getDimensions} from 'app/selectors/device';
|
||||
import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
|
||||
import {canDownloadFilesOnMobile} from 'mattermost-redux/selectors/entities/general';
|
||||
|
||||
import {dismissModal, showModalOverCurrentContext} from 'app/actions/navigation';
|
||||
import {getDimensions} from 'app/selectors/device';
|
||||
|
||||
import ImagePreview from './image_preview';
|
||||
|
||||
function mapStateToProps(state) {
|
||||
|
|
@ -17,4 +20,13 @@ function mapStateToProps(state) {
|
|||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps)(ImagePreview);
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
actions: bindActionCreators({
|
||||
dismissModal,
|
||||
showModalOverCurrentContext,
|
||||
}, dispatch),
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(ImagePreview);
|
||||
|
|
|
|||
|
|
@ -9,23 +9,12 @@ import Channel from 'app/screens/channel';
|
|||
import Root from 'app/components/root';
|
||||
import SelectServer from 'app/screens/select_server';
|
||||
|
||||
// TODO remove dummy navigator object
|
||||
const navigator = {
|
||||
push: () => {}, // eslint-disable-line no-empty-function
|
||||
setOnNavigatorEvent: () => {}, // eslint-disable-line no-empty-function
|
||||
setStyle: () => {}, // eslint-disable-line no-empty-function
|
||||
setButtons: () => {}, // eslint-disable-line no-empty-function
|
||||
};
|
||||
|
||||
export function registerScreens(store, Provider) {
|
||||
// TODO consolidate this with app/utils/wrap_context_provider
|
||||
const wrapper = (Comp) => (props) => ( // eslint-disable-line react/display-name
|
||||
<Provider store={store}>
|
||||
<Root navigator={navigator}>
|
||||
<Comp
|
||||
{...props}
|
||||
navigator={navigator}
|
||||
/>
|
||||
<Root>
|
||||
<Comp {...props}/>
|
||||
</Root>
|
||||
</Provider>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@ export default class DialogElement extends PureComponent {
|
|||
options: PropTypes.arrayOf(PropTypes.object),
|
||||
value: PropTypes.any,
|
||||
onChange: PropTypes.func,
|
||||
navigator: PropTypes.object,
|
||||
theme: PropTypes.object,
|
||||
};
|
||||
|
||||
|
|
@ -71,7 +70,6 @@ export default class DialogElement extends PureComponent {
|
|||
theme,
|
||||
dataSource,
|
||||
options,
|
||||
navigator,
|
||||
} = this.props;
|
||||
|
||||
let {maxLength} = this.props;
|
||||
|
|
@ -128,7 +126,6 @@ export default class DialogElement extends PureComponent {
|
|||
placeholder={placeholder}
|
||||
showRequiredAsterisk={true}
|
||||
selected={this.state.selected}
|
||||
navigator={navigator}
|
||||
roundedBorders={false}
|
||||
/>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ import {connect} from 'react-redux';
|
|||
import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
|
||||
import {submitInteractiveDialog} from 'mattermost-redux/actions/integrations';
|
||||
|
||||
import {dismissModal} from 'app/actions/navigation';
|
||||
|
||||
import InteractiveDialog from './interactive_dialog';
|
||||
|
||||
function mapStateToProps(state) {
|
||||
|
|
@ -29,6 +31,7 @@ function mapDispatchToProps(dispatch) {
|
|||
return {
|
||||
actions: bindActionCreators({
|
||||
submitInteractiveDialog,
|
||||
dismissModal,
|
||||
}, dispatch),
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,10 +22,10 @@ export default class InteractiveDialog extends PureComponent {
|
|||
elements: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
notifyOnCancel: PropTypes.bool,
|
||||
state: PropTypes.string,
|
||||
navigator: PropTypes.object,
|
||||
theme: PropTypes.object,
|
||||
actions: PropTypes.shape({
|
||||
submitInteractiveDialog: PropTypes.func.isRequired,
|
||||
dismissModal: PropTypes.func.isRequired,
|
||||
}).isRequired,
|
||||
};
|
||||
|
||||
|
|
@ -136,9 +136,7 @@ export default class InteractiveDialog extends PureComponent {
|
|||
}
|
||||
|
||||
handleHide = () => {
|
||||
this.props.navigator.dismissModal({
|
||||
animationType: 'slide-down',
|
||||
});
|
||||
this.props.actions.dismissModal();
|
||||
}
|
||||
|
||||
onChange = (name, value) => {
|
||||
|
|
@ -147,7 +145,7 @@ export default class InteractiveDialog extends PureComponent {
|
|||
}
|
||||
|
||||
render() {
|
||||
const {elements, theme, navigator} = this.props;
|
||||
const {elements, theme} = this.props;
|
||||
const style = getStyleFromTheme(theme);
|
||||
|
||||
return (
|
||||
|
|
@ -172,7 +170,6 @@ export default class InteractiveDialog extends PureComponent {
|
|||
options={e.options}
|
||||
value={this.state.values[e.name]}
|
||||
onChange={this.onChange}
|
||||
navigator={navigator}
|
||||
theme={theme}
|
||||
/>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -19,8 +19,6 @@ describe('InteractiveDialog', () => {
|
|||
theme: Preferences.THEMES.default,
|
||||
actions: {
|
||||
submitInteractiveDialog: jest.fn(),
|
||||
},
|
||||
navigator: {
|
||||
dismissModal: jest.fn(),
|
||||
},
|
||||
componentId: 'component-id',
|
||||
|
|
@ -37,11 +35,9 @@ describe('InteractiveDialog', () => {
|
|||
});
|
||||
|
||||
test('should submit dialog', async () => {
|
||||
const submitInteractiveDialog = jest.fn();
|
||||
const wrapper = shallow(
|
||||
<InteractiveDialog
|
||||
{...baseProps}
|
||||
actions={{submitInteractiveDialog}}
|
||||
/>,
|
||||
);
|
||||
|
||||
|
|
@ -53,16 +49,14 @@ describe('InteractiveDialog', () => {
|
|||
};
|
||||
|
||||
wrapper.instance().handleSubmit();
|
||||
expect(submitInteractiveDialog).toHaveBeenCalledTimes(1);
|
||||
expect(submitInteractiveDialog).toHaveBeenCalledWith(dialog);
|
||||
expect(baseProps.actions.submitInteractiveDialog).toHaveBeenCalledTimes(1);
|
||||
expect(baseProps.actions.submitInteractiveDialog).toHaveBeenCalledWith(dialog);
|
||||
});
|
||||
|
||||
test('should submit dialog on cancel', async () => {
|
||||
const submitInteractiveDialog = jest.fn();
|
||||
const wrapper = shallow(
|
||||
<InteractiveDialog
|
||||
{...baseProps}
|
||||
actions={{submitInteractiveDialog}}
|
||||
notifyOnCancel={true}
|
||||
/>,
|
||||
);
|
||||
|
|
@ -75,21 +69,19 @@ describe('InteractiveDialog', () => {
|
|||
};
|
||||
|
||||
wrapper.instance().navigationButtonPressed({buttonId: 'close-dialog'});
|
||||
expect(submitInteractiveDialog).toHaveBeenCalledTimes(1);
|
||||
expect(submitInteractiveDialog).toHaveBeenCalledWith(dialog);
|
||||
expect(baseProps.actions.submitInteractiveDialog).toHaveBeenCalledTimes(1);
|
||||
expect(baseProps.actions.submitInteractiveDialog).toHaveBeenCalledWith(dialog);
|
||||
});
|
||||
|
||||
test('should not submit dialog on cancel', async () => {
|
||||
const submitInteractiveDialog = jest.fn();
|
||||
const wrapper = shallow(
|
||||
<InteractiveDialog
|
||||
{...baseProps}
|
||||
actions={{submitInteractiveDialog}}
|
||||
notifyOnCancel={false}
|
||||
/>,
|
||||
);
|
||||
|
||||
wrapper.instance().navigationButtonPressed({buttonId: 'close-dialog'});
|
||||
expect(submitInteractiveDialog).not.toHaveBeenCalled();
|
||||
expect(baseProps.actions.submitInteractiveDialog).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ import {getTeammateNameDisplaySetting, getTheme} from 'mattermost-redux/selector
|
|||
import {getCurrentTeamId} from 'mattermost-redux/selectors/entities/teams';
|
||||
import {getCurrentUserId, getUsers} from 'mattermost-redux/selectors/entities/users';
|
||||
|
||||
import {dismissModal, setButtons} from 'app/actions/navigation';
|
||||
|
||||
import MoreDirectMessages from './more_dms';
|
||||
|
||||
function mapStateToProps(state) {
|
||||
|
|
@ -40,6 +42,8 @@ function mapDispatchToProps(dispatch) {
|
|||
getProfilesInTeam,
|
||||
searchProfiles,
|
||||
setChannelDisplayName,
|
||||
dismissModal,
|
||||
setButtons,
|
||||
}, dispatch),
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,13 +39,14 @@ export default class MoreDirectMessages extends PureComponent {
|
|||
getProfilesInTeam: PropTypes.func.isRequired,
|
||||
searchProfiles: PropTypes.func.isRequired,
|
||||
setChannelDisplayName: PropTypes.func.isRequired,
|
||||
dismissModal: PropTypes.func.isRequired,
|
||||
setButtons: PropTypes.func.isRequired,
|
||||
}).isRequired,
|
||||
componentId: PropTypes.string,
|
||||
allProfiles: PropTypes.object.isRequired,
|
||||
currentDisplayName: PropTypes.string,
|
||||
currentTeamId: PropTypes.string.isRequired,
|
||||
currentUserId: PropTypes.string.isRequired,
|
||||
navigator: PropTypes.object,
|
||||
restrictDirectMessage: PropTypes.bool.isRequired,
|
||||
teammateNameDisplay: PropTypes.string,
|
||||
theme: PropTypes.object.isRequired,
|
||||
|
|
@ -108,7 +109,7 @@ export default class MoreDirectMessages extends PureComponent {
|
|||
}
|
||||
|
||||
close = () => {
|
||||
this.props.navigator.dismissModal({animationType: 'slide-down'});
|
||||
this.props.actions.dismissModal();
|
||||
};
|
||||
|
||||
clearSearch = () => {
|
||||
|
|
@ -325,13 +326,14 @@ export default class MoreDirectMessages extends PureComponent {
|
|||
};
|
||||
|
||||
updateNavigationButtons = (startEnabled, context = this.context) => {
|
||||
const {actions, componentId} = this.props;
|
||||
const {formatMessage} = context.intl;
|
||||
this.props.navigator.setButtons({
|
||||
actions.setButtons(componentId, {
|
||||
rightButtons: [{
|
||||
id: START_BUTTON,
|
||||
title: formatMessage({id: 'mobile.more_dms.start', defaultMessage: 'Start'}),
|
||||
text: formatMessage({id: 'mobile.more_dms.start', defaultMessage: 'Start'}),
|
||||
showAsAction: 'always',
|
||||
disabled: !startEnabled,
|
||||
enabled: startEnabled,
|
||||
}],
|
||||
});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ import {getTeammateNameDisplaySetting, getTheme} from 'mattermost-redux/selector
|
|||
import {getUser} from 'mattermost-redux/selectors/entities/users';
|
||||
import {getConfig} from 'mattermost-redux/selectors/entities/general';
|
||||
|
||||
import {dismissOverlay, dismissAllModals, popToRoot} from 'app/actions/navigation';
|
||||
|
||||
import Notification from './notification';
|
||||
|
||||
function mapStateToProps(state, ownProps) {
|
||||
|
|
@ -42,6 +44,9 @@ function mapDispatchToProps(dispatch) {
|
|||
return {
|
||||
actions: bindActionCreators({
|
||||
loadFromPushNotification,
|
||||
dismissOverlay,
|
||||
dismissAllModals,
|
||||
popToRoot,
|
||||
}, dispatch),
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,55 +8,149 @@ import {
|
|||
InteractionManager,
|
||||
Platform,
|
||||
StyleSheet,
|
||||
Text,
|
||||
TouchableOpacity,
|
||||
Text,
|
||||
View,
|
||||
} from 'react-native';
|
||||
|
||||
import FormattedText from 'app/components/formatted_text';
|
||||
import ProfilePicture from 'app/components/profile_picture';
|
||||
import {changeOpacity} from 'app/utils/theme';
|
||||
import {Navigation} from 'react-native-navigation';
|
||||
import * as Animatable from 'react-native-animatable';
|
||||
import {PanGestureHandler} from 'react-native-gesture-handler';
|
||||
|
||||
import {isDirectChannel} from 'mattermost-redux/utils/channel_utils';
|
||||
import EventEmitter from 'mattermost-redux/utils/event_emitter';
|
||||
import {displayUsername} from 'mattermost-redux/utils/user_utils';
|
||||
|
||||
import FormattedText from 'app/components/formatted_text';
|
||||
import ProfilePicture from 'app/components/profile_picture';
|
||||
import {changeOpacity} from 'app/utils/theme';
|
||||
import {NavigationTypes} from 'app/constants';
|
||||
|
||||
import logo from 'assets/images/icon.png';
|
||||
import webhookIcon from 'assets/images/icons/webhook.jpg';
|
||||
|
||||
const IMAGE_SIZE = 33;
|
||||
const AUTO_DISMISS_TIME_MILLIS = 5000;
|
||||
|
||||
export default class Notification extends PureComponent {
|
||||
static propTypes = {
|
||||
actions: PropTypes.shape({
|
||||
loadFromPushNotification: PropTypes.func.isRequired,
|
||||
dismissOverlay: PropTypes.func.isRequired,
|
||||
dismissAllModals: PropTypes.func.isRequired,
|
||||
popToRoot: PropTypes.func.isRequired,
|
||||
}).isRequired,
|
||||
componentId: PropTypes.string.isRequired,
|
||||
channel: PropTypes.object,
|
||||
config: PropTypes.object,
|
||||
deviceWidth: PropTypes.number.isRequired,
|
||||
notification: PropTypes.object.isRequired,
|
||||
teammateNameDisplay: PropTypes.string,
|
||||
navigator: PropTypes.object,
|
||||
theme: PropTypes.object.isRequired,
|
||||
user: PropTypes.object,
|
||||
};
|
||||
|
||||
state = {
|
||||
keyFrames: {
|
||||
from: {
|
||||
translateY: -100,
|
||||
},
|
||||
to: {
|
||||
translateY: 0,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
tapped = false;
|
||||
|
||||
componentDidMount() {
|
||||
this.setDismissTimer();
|
||||
this.setDidDisappearListener();
|
||||
this.setShowOverlayListener();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.clearDismissTimer();
|
||||
this.clearDidDisappearListener();
|
||||
this.clearShowOverlayListener();
|
||||
}
|
||||
|
||||
setDismissTimer = () => {
|
||||
this.dismissTimer = setTimeout(() => {
|
||||
if (!this.tapped) {
|
||||
this.animateDismissOverlay();
|
||||
}
|
||||
}, AUTO_DISMISS_TIME_MILLIS);
|
||||
}
|
||||
|
||||
clearDismissTimer = () => {
|
||||
if (this.dismissTimer) {
|
||||
clearTimeout(this.dismissTimer);
|
||||
this.dismissTimer = null;
|
||||
}
|
||||
}
|
||||
|
||||
setDidDisappearListener = () => {
|
||||
this.didDismissListener = Navigation.events().registerComponentDidDisappearListener(({componentId}) => {
|
||||
if (componentId === this.props.componentId && this.tapped) {
|
||||
const {actions} = this.props;
|
||||
actions.dismissAllModals();
|
||||
actions.popToRoot();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
clearDidDisappearListener = () => {
|
||||
this.didDismissListener.remove();
|
||||
}
|
||||
|
||||
setShowOverlayListener = () => {
|
||||
EventEmitter.on(NavigationTypes.NAVIGATION_SHOW_OVERLAY, this.onNewOverlay);
|
||||
}
|
||||
|
||||
clearShowOverlayListener = () => {
|
||||
EventEmitter.off(NavigationTypes.NAVIGATION_SHOW_OVERLAY, this.onNewOverlay);
|
||||
}
|
||||
|
||||
onNewOverlay = () => {
|
||||
// Dismiss this overlay so that there is only ever one.
|
||||
this.dismissOverlay();
|
||||
}
|
||||
|
||||
dismissOverlay = () => {
|
||||
this.clearDismissTimer();
|
||||
|
||||
const {actions, componentId} = this.props;
|
||||
actions.dismissOverlay(componentId);
|
||||
}
|
||||
|
||||
animateDismissOverlay = () => {
|
||||
this.clearDismissTimer();
|
||||
|
||||
this.setState({
|
||||
keyFrames: {
|
||||
from: {
|
||||
translateY: 0,
|
||||
},
|
||||
to: {
|
||||
translateY: -100,
|
||||
},
|
||||
},
|
||||
});
|
||||
setTimeout(() => this.dismissOverlay(), 1000);
|
||||
}
|
||||
|
||||
notificationTapped = () => {
|
||||
const {actions, navigator, notification} = this.props;
|
||||
this.tapped = true;
|
||||
this.clearDismissTimer();
|
||||
|
||||
const {actions, notification} = this.props;
|
||||
|
||||
EventEmitter.emit('close_channel_drawer');
|
||||
EventEmitter.emit('close_settings_sidebar');
|
||||
InteractionManager.runAfterInteractions(() => {
|
||||
navigator.dismissInAppNotification();
|
||||
this.dismissOverlay();
|
||||
if (!notification.localNotification) {
|
||||
actions.loadFromPushNotification(notification);
|
||||
|
||||
if (Platform.OS === 'android') {
|
||||
navigator.dismissModal({animation: 'none'});
|
||||
}
|
||||
|
||||
navigator.popToRoot({
|
||||
animated: false,
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
|
@ -202,28 +296,39 @@ export default class Notification extends PureComponent {
|
|||
const icon = this.getNotificationIcon();
|
||||
|
||||
return (
|
||||
<View style={[style.container, {width: deviceWidth}]}>
|
||||
<TouchableOpacity
|
||||
style={{flex: 1, flexDirection: 'row'}}
|
||||
onPress={this.notificationTapped}
|
||||
<PanGestureHandler
|
||||
onGestureEvent={this.animateDismissOverlay}
|
||||
minOffsetY={-20}
|
||||
>
|
||||
<Animatable.View
|
||||
duration={250}
|
||||
useNativeDriver={true}
|
||||
animation={this.state.keyFrames}
|
||||
>
|
||||
<View style={style.iconContainer}>
|
||||
{icon}
|
||||
<View style={[style.container, {width: deviceWidth}]}>
|
||||
<TouchableOpacity
|
||||
style={{flex: 1, flexDirection: 'row'}}
|
||||
onPress={this.notificationTapped}
|
||||
>
|
||||
<View style={style.iconContainer}>
|
||||
{icon}
|
||||
</View>
|
||||
<View style={style.textContainer}>
|
||||
{title}
|
||||
<View style={{flex: 1}}>
|
||||
<Text
|
||||
numberOfLines={1}
|
||||
ellipsizeMode='tail'
|
||||
style={style.message}
|
||||
>
|
||||
{messageText}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<View style={style.textContainer}>
|
||||
{title}
|
||||
<View style={{flex: 1}}>
|
||||
<Text
|
||||
numberOfLines={1}
|
||||
ellipsizeMode='tail'
|
||||
style={style.message}
|
||||
>
|
||||
{messageText}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</Animatable.View>
|
||||
</PanGestureHandler>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,13 +16,18 @@ import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
|
|||
import {getCurrentTeamId} from 'mattermost-redux/selectors/entities/teams';
|
||||
import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users';
|
||||
|
||||
import {
|
||||
goToScreen,
|
||||
dismissModal,
|
||||
dismissAllModals,
|
||||
resetToChannel,
|
||||
} from 'app/actions/navigation';
|
||||
import {
|
||||
handleSelectChannel,
|
||||
loadThreadIfNecessary,
|
||||
setChannelDisplayName,
|
||||
setChannelLoading,
|
||||
} from 'app/actions/views/channel';
|
||||
import {showSearchModal} from 'app/actions/views/search';
|
||||
import {handleTeamChange} from 'app/actions/views/select_team';
|
||||
|
||||
import Permalink from './permalink';
|
||||
|
|
@ -74,7 +79,10 @@ function mapDispatchToProps(dispatch) {
|
|||
selectPost,
|
||||
setChannelDisplayName,
|
||||
setChannelLoading,
|
||||
showSearchModal,
|
||||
goToScreen,
|
||||
dismissModal,
|
||||
dismissAllModals,
|
||||
resetToChannel,
|
||||
}, dispatch),
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,6 +57,10 @@ export default class Permalink extends PureComponent {
|
|||
selectPost: PropTypes.func.isRequired,
|
||||
setChannelDisplayName: PropTypes.func.isRequired,
|
||||
setChannelLoading: PropTypes.func.isRequired,
|
||||
goToScreen: PropTypes.func.isRequired,
|
||||
dismissModal: PropTypes.func.isRequired,
|
||||
dismissAllModals: PropTypes.func.isRequired,
|
||||
resetToChannel: PropTypes.func.isRequired,
|
||||
}).isRequired,
|
||||
channelId: PropTypes.string,
|
||||
channelIsArchived: PropTypes.bool,
|
||||
|
|
@ -67,7 +71,6 @@ export default class Permalink extends PureComponent {
|
|||
focusedPostId: PropTypes.string.isRequired,
|
||||
isPermalink: PropTypes.bool,
|
||||
myMembers: PropTypes.object.isRequired,
|
||||
navigator: PropTypes.object,
|
||||
onClose: PropTypes.func,
|
||||
onPress: PropTypes.func,
|
||||
postIds: PropTypes.array,
|
||||
|
|
@ -171,39 +174,29 @@ export default class Permalink extends PureComponent {
|
|||
}
|
||||
|
||||
goToThread = preventDoubleTap((post) => {
|
||||
const {actions, navigator, theme} = this.props;
|
||||
const {actions} = this.props;
|
||||
const channelId = post.channel_id;
|
||||
const rootId = (post.root_id || post.id);
|
||||
const screen = 'Thread';
|
||||
const title = '';
|
||||
const passProps = {
|
||||
channelId,
|
||||
rootId,
|
||||
};
|
||||
|
||||
actions.loadThreadIfNecessary(rootId);
|
||||
actions.selectPost(rootId);
|
||||
|
||||
const options = {
|
||||
screen: 'Thread',
|
||||
animated: true,
|
||||
backButtonTitle: '',
|
||||
navigatorStyle: {
|
||||
navBarTextColor: theme.sidebarHeaderTextColor,
|
||||
navBarBackgroundColor: theme.sidebarHeaderBg,
|
||||
navBarButtonColor: theme.sidebarHeaderTextColor,
|
||||
screenBackgroundColor: theme.centerChannelBg,
|
||||
},
|
||||
passProps: {
|
||||
channelId,
|
||||
rootId,
|
||||
},
|
||||
};
|
||||
|
||||
navigator.push(options);
|
||||
actions.goToScreen(screen, title, passProps);
|
||||
});
|
||||
|
||||
handleClose = () => {
|
||||
const {actions, navigator, onClose} = this.props;
|
||||
const {actions, onClose} = this.props;
|
||||
if (this.refs.view) {
|
||||
this.mounted = false;
|
||||
this.refs.view.zoomOut().then(() => {
|
||||
actions.selectPost('');
|
||||
navigator.dismissModal({animationType: 'none'});
|
||||
actions.dismissModal();
|
||||
|
||||
if (onClose) {
|
||||
onClose();
|
||||
|
|
@ -232,7 +225,7 @@ export default class Permalink extends PureComponent {
|
|||
|
||||
jumpToChannel = (channelId, channelDisplayName) => {
|
||||
if (channelId) {
|
||||
const {actions, channelTeamId, currentTeamId, navigator, onClose, theme} = this.props;
|
||||
const {actions, channelTeamId, currentTeamId, onClose} = this.props;
|
||||
const currentChannelId = this.props.channelId;
|
||||
const {
|
||||
handleSelectChannel,
|
||||
|
|
@ -246,23 +239,13 @@ export default class Permalink extends PureComponent {
|
|||
if (channelId === currentChannelId) {
|
||||
EventEmitter.emit('reset_channel');
|
||||
} else {
|
||||
navigator.resetTo({
|
||||
screen: 'Channel',
|
||||
animated: true,
|
||||
animationType: 'fade',
|
||||
navigatorStyle: {
|
||||
navBarHidden: true,
|
||||
statusBarHidden: false,
|
||||
statusBarHideWithNavBar: false,
|
||||
screenBackgroundColor: theme.centerChannelBg,
|
||||
},
|
||||
passProps: {
|
||||
disableTermsModal: true,
|
||||
},
|
||||
});
|
||||
const passProps = {
|
||||
disableTermsModal: true,
|
||||
};
|
||||
actions.resetToChannel(passProps);
|
||||
}
|
||||
|
||||
navigator.dismissAllModals({animationType: 'slide-down'});
|
||||
actions.dismissAllModals();
|
||||
|
||||
if (onClose) {
|
||||
onClose();
|
||||
|
|
@ -350,7 +333,6 @@ export default class Permalink extends PureComponent {
|
|||
const {
|
||||
currentUserId,
|
||||
focusedPostId,
|
||||
navigator,
|
||||
theme,
|
||||
} = this.props;
|
||||
const {
|
||||
|
|
@ -395,7 +377,6 @@ export default class Permalink extends PureComponent {
|
|||
lastPostIndex={Platform.OS === 'android' ? getLastPostIndex(postIdsState) : -1}
|
||||
currentUserId={currentUserId}
|
||||
lastViewedAt={0}
|
||||
navigator={navigator}
|
||||
highlightPinnedOrFlagged={false}
|
||||
/>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -11,13 +11,6 @@ import Permalink from './permalink.js';
|
|||
jest.mock('react-intl');
|
||||
|
||||
describe('Permalink', () => {
|
||||
const navigator = {
|
||||
dismissAllModals: jest.fn(),
|
||||
dismissModal: jest.fn(),
|
||||
push: jest.fn(),
|
||||
resetTo: jest.fn(),
|
||||
};
|
||||
|
||||
const actions = {
|
||||
getPostsAround: jest.fn(),
|
||||
getPostThread: jest.fn(),
|
||||
|
|
@ -29,6 +22,10 @@ describe('Permalink', () => {
|
|||
selectPost: jest.fn(),
|
||||
setChannelDisplayName: jest.fn(),
|
||||
setChannelLoading: jest.fn(),
|
||||
goToScreen: jest.fn(),
|
||||
dismissModal: jest.fn(),
|
||||
dismissAllModals: jest.fn(),
|
||||
resetToChannel: jest.fn(),
|
||||
};
|
||||
|
||||
const baseProps = {
|
||||
|
|
@ -42,7 +39,6 @@ describe('Permalink', () => {
|
|||
focusedPostId: 'focused_post_id',
|
||||
isPermalink: true,
|
||||
myMembers: {},
|
||||
navigator,
|
||||
onClose: jest.fn(),
|
||||
onPress: jest.fn(),
|
||||
postIds: ['post_id_1', 'focused_post_id', 'post_id_3'],
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ exports[`ReactionList should match snapshot 1`] = `
|
|||
}
|
||||
}
|
||||
>
|
||||
<ReactionRow
|
||||
<Connect(ReactionRow)
|
||||
emojiName="+1"
|
||||
teammateNameDisplay="username"
|
||||
theme={
|
||||
|
|
@ -77,7 +77,7 @@ exports[`ReactionList should match snapshot 1`] = `
|
|||
}
|
||||
}
|
||||
>
|
||||
<ReactionRow
|
||||
<Connect(ReactionRow)
|
||||
emojiName="smile"
|
||||
teammateNameDisplay="username"
|
||||
theme={
|
||||
|
|
@ -138,7 +138,7 @@ Array [
|
|||
}
|
||||
}
|
||||
>
|
||||
<ReactionRow
|
||||
<Connect(ReactionRow)
|
||||
emojiName="+1"
|
||||
teammateNameDisplay="username"
|
||||
theme={
|
||||
|
|
@ -193,7 +193,7 @@ Array [
|
|||
}
|
||||
}
|
||||
>
|
||||
<ReactionRow
|
||||
<Connect(ReactionRow)
|
||||
emojiName="smile"
|
||||
teammateNameDisplay="username"
|
||||
theme={
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ import {makeGetReactionsForPost} from 'mattermost-redux/selectors/entities/posts
|
|||
import {getCurrentUserId, makeGetProfilesByIdsAndUsernames} from 'mattermost-redux/selectors/entities/users';
|
||||
import {getTeammateNameDisplaySetting, getTheme} from 'mattermost-redux/selectors/entities/preferences';
|
||||
|
||||
import {dismissModal} from 'app/actions/navigation';
|
||||
|
||||
import {getUniqueUserIds} from 'app/utils/reaction';
|
||||
|
||||
import ReactionList from './reaction_list';
|
||||
|
|
@ -35,6 +37,7 @@ function mapDispatchToProps(dispatch) {
|
|||
return {
|
||||
actions: bindActionCreators({
|
||||
getMissingProfilesByIds,
|
||||
dismissModal,
|
||||
}, dispatch),
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,8 +28,8 @@ export default class ReactionList extends PureComponent {
|
|||
static propTypes = {
|
||||
actions: PropTypes.shape({
|
||||
getMissingProfilesByIds: PropTypes.func.isRequired,
|
||||
dismissModal: PropTypes.func.isRequired,
|
||||
}).isRequired,
|
||||
navigator: PropTypes.object,
|
||||
reactions: PropTypes.object.isRequired,
|
||||
theme: PropTypes.object.isRequired,
|
||||
teammateNameDisplay: PropTypes.string,
|
||||
|
|
@ -107,9 +107,7 @@ export default class ReactionList extends PureComponent {
|
|||
}
|
||||
|
||||
close = () => {
|
||||
this.props.navigator.dismissModal({
|
||||
animationType: 'none',
|
||||
});
|
||||
this.props.actions.dismissModal();
|
||||
};
|
||||
|
||||
getMissingProfiles = () => {
|
||||
|
|
@ -137,7 +135,6 @@ export default class ReactionList extends PureComponent {
|
|||
|
||||
renderReactionRows = () => {
|
||||
const {
|
||||
navigator,
|
||||
teammateNameDisplay,
|
||||
theme,
|
||||
} = this.props;
|
||||
|
|
@ -157,7 +154,6 @@ export default class ReactionList extends PureComponent {
|
|||
>
|
||||
<ReactionRow
|
||||
emojiName={emojiName}
|
||||
navigator={navigator}
|
||||
teammateNameDisplay={teammateNameDisplay}
|
||||
theme={theme}
|
||||
user={userProfilesById[userId]}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ describe('ReactionList', () => {
|
|||
const baseProps = {
|
||||
actions: {
|
||||
getMissingProfilesByIds: jest.fn(),
|
||||
dismissModal: jest.fn(),
|
||||
},
|
||||
allUserIds: ['user_id_1', 'user_id_2'],
|
||||
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'}},
|
||||
|
|
|
|||
19
app/screens/reaction_list/reaction_row/index.js
Normal file
19
app/screens/reaction_list/reaction_row/index.js
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
// 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 {goToScreen} from 'app/actions/navigation';
|
||||
|
||||
import ReactionRow from './reaction_row';
|
||||
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
actions: bindActionCreators({
|
||||
goToScreen,
|
||||
}, dispatch),
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(null, mapDispatchToProps)(ReactionRow);
|
||||
|
|
@ -21,8 +21,10 @@ import Emoji from 'app/components/emoji';
|
|||
|
||||
export default class ReactionRow extends React.PureComponent {
|
||||
static propTypes = {
|
||||
actions: PropTypes.shape({
|
||||
goToScreen: PropTypes.func.isRequired,
|
||||
}).isRequired,
|
||||
emojiName: PropTypes.string.isRequired,
|
||||
navigator: PropTypes.object,
|
||||
teammateNameDisplay: PropTypes.string.isRequired,
|
||||
theme: PropTypes.object.isRequired,
|
||||
user: PropTypes.object.isRequired,
|
||||
|
|
@ -37,26 +39,15 @@ export default class ReactionRow extends React.PureComponent {
|
|||
};
|
||||
|
||||
goToUserProfile = () => {
|
||||
const {navigator, theme, user} = this.props;
|
||||
const {actions, user} = this.props;
|
||||
const {formatMessage} = this.context.intl;
|
||||
|
||||
const options = {
|
||||
screen: 'UserProfile',
|
||||
title: formatMessage({id: 'mobile.routes.user_profile', defaultMessage: 'Profile'}),
|
||||
animated: true,
|
||||
backButtonTitle: '',
|
||||
passProps: {
|
||||
userId: user.id,
|
||||
},
|
||||
navigatorStyle: {
|
||||
navBarTextColor: theme.sidebarHeaderTextColor,
|
||||
navBarBackgroundColor: theme.sidebarHeaderBg,
|
||||
navBarButtonColor: theme.sidebarHeaderTextColor,
|
||||
screenBackgroundColor: theme.centerChannelBg,
|
||||
},
|
||||
const screen = 'UserProfile';
|
||||
const title = formatMessage({id: 'mobile.routes.user_profile', defaultMessage: 'Profile'});
|
||||
const passProps = {
|
||||
userId: user.id,
|
||||
};
|
||||
|
||||
navigator.push(options);
|
||||
actions.goToScreen(screen, title, passProps);
|
||||
};
|
||||
|
||||
render() {
|
||||
|
|
@ -9,8 +9,10 @@ import ReactionRow from './reaction_row';
|
|||
|
||||
describe('ReactionRow', () => {
|
||||
const baseProps = {
|
||||
actions: {
|
||||
goToScreen: jest.fn(),
|
||||
},
|
||||
emojiName: 'smile',
|
||||
navigator: {},
|
||||
teammateNameDisplay: 'username',
|
||||
theme: Preferences.THEMES.default,
|
||||
user: {id: 'user_id', username: 'username'},
|
||||
|
|
@ -15,7 +15,7 @@ import {isMinimumServerVersion} from 'mattermost-redux/utils/helpers';
|
|||
import {getUserCurrentTimezone} from 'mattermost-redux/utils/timezone_utils';
|
||||
import {getCurrentUser} from 'mattermost-redux/selectors/entities/users';
|
||||
|
||||
import {dismissModal} from 'app/actions/navigation';
|
||||
import {dismissModal, goToScreen, showModalOverCurrentContext} from 'app/actions/navigation';
|
||||
import {loadChannelsByTeamName, loadThreadIfNecessary} from 'app/actions/views/channel';
|
||||
import {handleSearchDraftChanged} from 'app/actions/views/search';
|
||||
import {isLandscape} from 'app/selectors/device';
|
||||
|
|
@ -86,6 +86,8 @@ function mapDispatchToProps(dispatch) {
|
|||
getMorePostsForSearch,
|
||||
selectPost,
|
||||
dismissModal,
|
||||
goToScreen,
|
||||
showModalOverCurrentContext,
|
||||
}, dispatch),
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,12 +57,13 @@ export default class Search extends PureComponent {
|
|||
selectFocusedPostId: PropTypes.func.isRequired,
|
||||
selectPost: PropTypes.func.isRequired,
|
||||
dismissModal: PropTypes.func.isRequired,
|
||||
goToScreen: PropTypes.func.isRequired,
|
||||
showModalOverCurrentContext: PropTypes.func.isRequired,
|
||||
}).isRequired,
|
||||
componentId: PropTypes.string.isRequired,
|
||||
currentTeamId: PropTypes.string.isRequired,
|
||||
initialValue: PropTypes.string,
|
||||
isLandscape: PropTypes.bool.isRequired,
|
||||
navigator: PropTypes.object,
|
||||
postIds: PropTypes.array,
|
||||
archivedPostIds: PropTypes.arrayOf(PropTypes.string),
|
||||
recent: PropTypes.array.isRequired,
|
||||
|
|
@ -183,7 +184,7 @@ export default class Search extends PureComponent {
|
|||
});
|
||||
|
||||
goToThread = (post) => {
|
||||
const {actions, navigator, theme} = this.props;
|
||||
const {actions} = this.props;
|
||||
const channelId = post.channel_id;
|
||||
const rootId = (post.root_id || post.id);
|
||||
|
||||
|
|
@ -191,23 +192,14 @@ export default class Search extends PureComponent {
|
|||
actions.loadThreadIfNecessary(rootId);
|
||||
actions.selectPost(rootId);
|
||||
|
||||
const options = {
|
||||
screen: 'Thread',
|
||||
animated: true,
|
||||
backButtonTitle: '',
|
||||
navigatorStyle: {
|
||||
navBarTextColor: theme.sidebarHeaderTextColor,
|
||||
navBarBackgroundColor: theme.sidebarHeaderBg,
|
||||
navBarButtonColor: theme.sidebarHeaderTextColor,
|
||||
screenBackgroundColor: theme.centerChannelBg,
|
||||
},
|
||||
passProps: {
|
||||
channelId,
|
||||
rootId,
|
||||
},
|
||||
const screen = 'Thread';
|
||||
const title = '';
|
||||
const passProps = {
|
||||
channelId,
|
||||
rootId,
|
||||
};
|
||||
|
||||
navigator.push(options);
|
||||
actions.goToScreen(screen, title, passProps);
|
||||
};
|
||||
|
||||
handleHashtagPress = (hashtag) => {
|
||||
|
|
@ -389,7 +381,6 @@ export default class Search extends PureComponent {
|
|||
postId={item}
|
||||
previewPost={this.previewPost}
|
||||
goToThread={this.goToThread}
|
||||
navigator={this.props.navigator}
|
||||
onHashtagPress={this.handleHashtagPress}
|
||||
onPermalinkPress={this.handlePermalinkPress}
|
||||
managedConfig={mattermostManaged.getCachedConfig()}
|
||||
|
|
@ -449,29 +440,24 @@ export default class Search extends PureComponent {
|
|||
};
|
||||
|
||||
showPermalinkView = (postId, isPermalink) => {
|
||||
const {actions, navigator} = this.props;
|
||||
const {actions} = this.props;
|
||||
|
||||
actions.selectFocusedPostId(postId);
|
||||
|
||||
if (!this.showingPermalink) {
|
||||
const screen = 'Permalink';
|
||||
const passProps = {
|
||||
isPermalink,
|
||||
onClose: this.handleClosePermalink,
|
||||
};
|
||||
const options = {
|
||||
screen: 'Permalink',
|
||||
animationType: 'none',
|
||||
backButtonTitle: '',
|
||||
overrideBackPress: true,
|
||||
navigatorStyle: {
|
||||
navBarHidden: true,
|
||||
screenBackgroundColor: changeOpacity('#000', 0.2),
|
||||
modalPresentationStyle: 'overCurrentContext',
|
||||
},
|
||||
passProps: {
|
||||
isPermalink,
|
||||
onClose: this.handleClosePermalink,
|
||||
layout: {
|
||||
backgroundColor: changeOpacity('#000', 0.2),
|
||||
},
|
||||
};
|
||||
|
||||
this.showingPermalink = true;
|
||||
navigator.showModal(options);
|
||||
actions.showModalOverCurrentContext(screen, passProps, options);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
|
|||
import {getProfiles, searchProfiles} from 'mattermost-redux/actions/users';
|
||||
import {getChannels, searchChannels} from 'mattermost-redux/actions/channels';
|
||||
|
||||
import {popTopScreen} from 'app/actions/navigation';
|
||||
|
||||
import SelectorScreen from './selector_screen';
|
||||
|
||||
function mapStateToProps(state) {
|
||||
|
|
@ -32,6 +34,7 @@ function mapDispatchToProps(dispatch) {
|
|||
getChannels,
|
||||
searchProfiles,
|
||||
searchChannels,
|
||||
popTopScreen,
|
||||
}, dispatch),
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,12 +34,12 @@ export default class SelectorScreen extends PureComponent {
|
|||
getChannels: PropTypes.func.isRequired,
|
||||
searchProfiles: PropTypes.func.isRequired,
|
||||
searchChannels: PropTypes.func.isRequired,
|
||||
popTopScreen: PropTypes.func.isRequired,
|
||||
}),
|
||||
componentId: PropTypes.string,
|
||||
currentTeamId: PropTypes.string.isRequired,
|
||||
data: PropTypes.arrayOf(PropTypes.object),
|
||||
dataSource: PropTypes.string,
|
||||
navigator: PropTypes.object,
|
||||
onSelect: PropTypes.func.isRequired,
|
||||
theme: PropTypes.object.isRequired,
|
||||
};
|
||||
|
|
@ -93,7 +93,7 @@ export default class SelectorScreen extends PureComponent {
|
|||
};
|
||||
|
||||
close = () => {
|
||||
this.props.navigator.pop({animated: true});
|
||||
this.props.actions.popTopScreen();
|
||||
};
|
||||
|
||||
handleSelectItem = (id, item) => {
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ describe('SelectorScreen', () => {
|
|||
getChannels,
|
||||
searchProfiles,
|
||||
searchChannels,
|
||||
popTopScreen: jest.fn(),
|
||||
};
|
||||
|
||||
const baseProps = {
|
||||
|
|
|
|||
|
|
@ -45,87 +45,6 @@ exports[`TermsOfService should enable/disable navigator buttons on setNavigatorB
|
|||
disableAtMentions={true}
|
||||
disableChannelLink={true}
|
||||
disableHashtags={true}
|
||||
navigator={
|
||||
Object {
|
||||
"dismissAllModals": [MockFunction],
|
||||
"dismissModal": [MockFunction],
|
||||
"setButtons": [MockFunction] {
|
||||
"calls": Array [
|
||||
Array [
|
||||
Object {
|
||||
"leftButtons": Array [
|
||||
Object {
|
||||
"disabled": true,
|
||||
"icon": Object {},
|
||||
"id": "reject-terms-of-service",
|
||||
},
|
||||
],
|
||||
"rightButtons": Array [
|
||||
Object {
|
||||
"disabled": true,
|
||||
"id": "accept-terms-of-service",
|
||||
"showAsAction": "always",
|
||||
"title": undefined,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
Array [
|
||||
Object {
|
||||
"leftButtons": Array [
|
||||
Object {
|
||||
"disabled": true,
|
||||
"icon": Object {},
|
||||
"id": "reject-terms-of-service",
|
||||
},
|
||||
],
|
||||
"rightButtons": Array [
|
||||
Object {
|
||||
"disabled": true,
|
||||
"id": "accept-terms-of-service",
|
||||
"showAsAction": "always",
|
||||
"title": undefined,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
Array [
|
||||
Object {
|
||||
"leftButtons": Array [
|
||||
Object {
|
||||
"disabled": false,
|
||||
"icon": Object {},
|
||||
"id": "reject-terms-of-service",
|
||||
},
|
||||
],
|
||||
"rightButtons": Array [
|
||||
Object {
|
||||
"disabled": false,
|
||||
"id": "accept-terms-of-service",
|
||||
"showAsAction": "always",
|
||||
"title": undefined,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
],
|
||||
"results": Array [
|
||||
Object {
|
||||
"type": "return",
|
||||
"value": undefined,
|
||||
},
|
||||
Object {
|
||||
"type": "return",
|
||||
"value": undefined,
|
||||
},
|
||||
Object {
|
||||
"type": "return",
|
||||
"value": undefined,
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
}
|
||||
textStyles={
|
||||
Object {
|
||||
"code": Object {
|
||||
|
|
@ -261,110 +180,6 @@ exports[`TermsOfService should enable/disable navigator buttons on setNavigatorB
|
|||
disableAtMentions={true}
|
||||
disableChannelLink={true}
|
||||
disableHashtags={true}
|
||||
navigator={
|
||||
Object {
|
||||
"dismissAllModals": [MockFunction],
|
||||
"dismissModal": [MockFunction],
|
||||
"setButtons": [MockFunction] {
|
||||
"calls": Array [
|
||||
Array [
|
||||
Object {
|
||||
"leftButtons": Array [
|
||||
Object {
|
||||
"disabled": true,
|
||||
"icon": Object {},
|
||||
"id": "reject-terms-of-service",
|
||||
},
|
||||
],
|
||||
"rightButtons": Array [
|
||||
Object {
|
||||
"disabled": true,
|
||||
"id": "accept-terms-of-service",
|
||||
"showAsAction": "always",
|
||||
"title": undefined,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
Array [
|
||||
Object {
|
||||
"leftButtons": Array [
|
||||
Object {
|
||||
"disabled": true,
|
||||
"icon": Object {},
|
||||
"id": "reject-terms-of-service",
|
||||
},
|
||||
],
|
||||
"rightButtons": Array [
|
||||
Object {
|
||||
"disabled": true,
|
||||
"id": "accept-terms-of-service",
|
||||
"showAsAction": "always",
|
||||
"title": undefined,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
Array [
|
||||
Object {
|
||||
"leftButtons": Array [
|
||||
Object {
|
||||
"disabled": false,
|
||||
"icon": Object {},
|
||||
"id": "reject-terms-of-service",
|
||||
},
|
||||
],
|
||||
"rightButtons": Array [
|
||||
Object {
|
||||
"disabled": false,
|
||||
"id": "accept-terms-of-service",
|
||||
"showAsAction": "always",
|
||||
"title": undefined,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
Array [
|
||||
Object {
|
||||
"leftButtons": Array [
|
||||
Object {
|
||||
"disabled": true,
|
||||
"icon": Object {},
|
||||
"id": "reject-terms-of-service",
|
||||
},
|
||||
],
|
||||
"rightButtons": Array [
|
||||
Object {
|
||||
"disabled": true,
|
||||
"id": "accept-terms-of-service",
|
||||
"showAsAction": "always",
|
||||
"title": undefined,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
],
|
||||
"results": Array [
|
||||
Object {
|
||||
"type": "return",
|
||||
"value": undefined,
|
||||
},
|
||||
Object {
|
||||
"type": "return",
|
||||
"value": undefined,
|
||||
},
|
||||
Object {
|
||||
"type": "return",
|
||||
"value": undefined,
|
||||
},
|
||||
Object {
|
||||
"type": "return",
|
||||
"value": undefined,
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
}
|
||||
textStyles={
|
||||
Object {
|
||||
"code": Object {
|
||||
|
|
@ -572,87 +387,6 @@ exports[`TermsOfService should match snapshot on enableNavigatorLogout 1`] = `
|
|||
disableAtMentions={true}
|
||||
disableChannelLink={true}
|
||||
disableHashtags={true}
|
||||
navigator={
|
||||
Object {
|
||||
"dismissAllModals": [MockFunction],
|
||||
"dismissModal": [MockFunction],
|
||||
"setButtons": [MockFunction] {
|
||||
"calls": Array [
|
||||
Array [
|
||||
Object {
|
||||
"leftButtons": Array [
|
||||
Object {
|
||||
"disabled": true,
|
||||
"icon": Object {},
|
||||
"id": "reject-terms-of-service",
|
||||
},
|
||||
],
|
||||
"rightButtons": Array [
|
||||
Object {
|
||||
"disabled": true,
|
||||
"id": "accept-terms-of-service",
|
||||
"showAsAction": "always",
|
||||
"title": undefined,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
Array [
|
||||
Object {
|
||||
"leftButtons": Array [
|
||||
Object {
|
||||
"disabled": true,
|
||||
"icon": Object {},
|
||||
"id": "reject-terms-of-service",
|
||||
},
|
||||
],
|
||||
"rightButtons": Array [
|
||||
Object {
|
||||
"disabled": true,
|
||||
"id": "accept-terms-of-service",
|
||||
"showAsAction": "always",
|
||||
"title": undefined,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
Array [
|
||||
Object {
|
||||
"leftButtons": Array [
|
||||
Object {
|
||||
"disabled": false,
|
||||
"icon": Object {},
|
||||
"id": "close-terms-of-service",
|
||||
},
|
||||
],
|
||||
"rightButtons": Array [
|
||||
Object {
|
||||
"disabled": true,
|
||||
"id": "accept-terms-of-service",
|
||||
"showAsAction": "always",
|
||||
"title": undefined,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
],
|
||||
"results": Array [
|
||||
Object {
|
||||
"type": "return",
|
||||
"value": undefined,
|
||||
},
|
||||
Object {
|
||||
"type": "return",
|
||||
"value": undefined,
|
||||
},
|
||||
Object {
|
||||
"type": "return",
|
||||
"value": undefined,
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
}
|
||||
textStyles={
|
||||
Object {
|
||||
"code": Object {
|
||||
|
|
|
|||
|
|
@ -8,6 +8,12 @@ import {getTermsOfService, logout, updateMyTermsOfServiceStatus} from 'mattermos
|
|||
import {getConfig} from 'mattermost-redux/selectors/entities/general';
|
||||
import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
|
||||
|
||||
import {
|
||||
setButtons,
|
||||
dismissModal,
|
||||
dismissAllModals,
|
||||
} from 'app/actions/navigation';
|
||||
|
||||
import TermsOfService from './terms_of_service.js';
|
||||
|
||||
function mapStateToProps(state) {
|
||||
|
|
@ -25,6 +31,9 @@ function mapDispatchToProps(dispatch) {
|
|||
getTermsOfService,
|
||||
logout,
|
||||
updateMyTermsOfServiceStatus,
|
||||
setButtons,
|
||||
dismissModal,
|
||||
dismissAllModals,
|
||||
}, dispatch),
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,10 +36,12 @@ export default class TermsOfService extends PureComponent {
|
|||
logout: PropTypes.func.isRequired,
|
||||
getTermsOfService: PropTypes.func.isRequired,
|
||||
updateMyTermsOfServiceStatus: PropTypes.func.isRequired,
|
||||
setButtons: PropTypes.func.isRequired,
|
||||
dismissModal: PropTypes.func.isRequired,
|
||||
dismissAllModals: PropTypes.func.isRequired,
|
||||
}).isRequired,
|
||||
componentId: PropTypes.string,
|
||||
closeButton: PropTypes.object,
|
||||
navigator: PropTypes.object,
|
||||
siteName: PropTypes.string,
|
||||
theme: PropTypes.object,
|
||||
};
|
||||
|
|
@ -71,7 +73,7 @@ export default class TermsOfService extends PureComponent {
|
|||
termsText: '',
|
||||
};
|
||||
|
||||
this.rightButton.title = context.intl.formatMessage({id: 'terms_of_service.agreeButton', defaultMessage: 'I Agree'});
|
||||
this.rightButton.text = context.intl.formatMessage({id: 'terms_of_service.agreeButton', defaultMessage: 'I Agree'});
|
||||
this.leftButton.icon = props.closeButton;
|
||||
|
||||
this.setNavigatorButtons(false);
|
||||
|
|
@ -106,27 +108,28 @@ export default class TermsOfService extends PureComponent {
|
|||
}
|
||||
|
||||
setNavigatorButtons = (enabled = true) => {
|
||||
const {actions, componentId} = this.props;
|
||||
const buttons = {
|
||||
leftButtons: [{...this.leftButton, disabled: !enabled}],
|
||||
rightButtons: [{...this.rightButton, disabled: !enabled}],
|
||||
leftButtons: [{...this.leftButton, enabled}],
|
||||
rightButtons: [{...this.rightButton, enabled}],
|
||||
};
|
||||
|
||||
this.props.navigator.setButtons(buttons);
|
||||
actions.setButtons(componentId, buttons);
|
||||
};
|
||||
|
||||
enableNavigatorLogout = () => {
|
||||
const buttons = {
|
||||
leftButtons: [{...this.leftButton, id: 'close-terms-of-service', disabled: false}],
|
||||
rightButtons: [{...this.rightButton, disabled: true}],
|
||||
leftButtons: [{...this.leftButton, id: 'close-terms-of-service', enabled: true}],
|
||||
rightButtons: [{...this.rightButton, enabled: false}],
|
||||
};
|
||||
|
||||
this.props.navigator.setButtons(buttons);
|
||||
this.props.actions.setButtons(buttons);
|
||||
};
|
||||
|
||||
closeTermsAndLogout = () => {
|
||||
const {actions} = this.props;
|
||||
|
||||
this.props.navigator.dismissAllModals();
|
||||
actions.dismissAllModals();
|
||||
actions.logout();
|
||||
};
|
||||
|
||||
|
|
@ -163,9 +166,7 @@ export default class TermsOfService extends PureComponent {
|
|||
this.registerUserAction(
|
||||
true,
|
||||
() => {
|
||||
this.props.navigator.dismissModal({
|
||||
animationType: 'slide-down',
|
||||
});
|
||||
this.props.actions.dismissModal();
|
||||
},
|
||||
this.handleAcceptTerms
|
||||
);
|
||||
|
|
@ -234,7 +235,7 @@ export default class TermsOfService extends PureComponent {
|
|||
};
|
||||
|
||||
render() {
|
||||
const {navigator, theme} = this.props;
|
||||
const {theme} = this.props;
|
||||
const styles = getStyleSheet(theme);
|
||||
|
||||
const blockStyles = getMarkdownBlockStyles(theme);
|
||||
|
|
@ -267,7 +268,6 @@ export default class TermsOfService extends PureComponent {
|
|||
>
|
||||
<Markdown
|
||||
baseTextStyle={styles.baseText}
|
||||
navigator={navigator}
|
||||
textStyles={textStyles}
|
||||
blockStyles={blockStyles}
|
||||
value={this.state.termsText}
|
||||
|
|
|
|||
|
|
@ -23,15 +23,13 @@ describe('TermsOfService', () => {
|
|||
getTermsOfService: jest.fn(),
|
||||
updateMyTermsOfServiceStatus: jest.fn(),
|
||||
logout: jest.fn(),
|
||||
setButtons: jest.fn(),
|
||||
dismissModal: jest.fn(),
|
||||
dismissAllModals: jest.fn(),
|
||||
};
|
||||
|
||||
const baseProps = {
|
||||
actions,
|
||||
navigator: {
|
||||
dismissAllModals: jest.fn(),
|
||||
dismissModal: jest.fn(),
|
||||
setButtons: jest.fn(),
|
||||
},
|
||||
theme: Preferences.THEMES.default,
|
||||
closeButton: {},
|
||||
siteName: 'Mattermost',
|
||||
|
|
@ -83,18 +81,18 @@ describe('TermsOfService', () => {
|
|||
expect(wrapper.getElement()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('should call props.navigator.setButtons on setNavigatorButtons', async () => {
|
||||
test('should call props.actions.setButtons on setNavigatorButtons', async () => {
|
||||
const wrapper = shallow(
|
||||
<TermsOfService {...baseProps}/>,
|
||||
{context: {intl: {formatMessage: jest.fn()}}},
|
||||
);
|
||||
wrapper.setState({loading: false, termsId: 1, termsText: 'Terms Text'});
|
||||
|
||||
expect(baseProps.navigator.setButtons).toHaveBeenCalledTimes(2);
|
||||
expect(baseProps.actions.setButtons).toHaveBeenCalledTimes(2);
|
||||
wrapper.instance().setNavigatorButtons(true);
|
||||
expect(baseProps.navigator.setButtons).toHaveBeenCalledTimes(3);
|
||||
expect(baseProps.actions.setButtons).toHaveBeenCalledTimes(3);
|
||||
wrapper.instance().setNavigatorButtons(false);
|
||||
expect(baseProps.navigator.setButtons).toHaveBeenCalledTimes(4);
|
||||
expect(baseProps.actions.setButtons).toHaveBeenCalledTimes(4);
|
||||
});
|
||||
|
||||
test('should enable/disable navigator buttons on setNavigatorButtons true/false', () => {
|
||||
|
|
@ -129,6 +127,6 @@ describe('TermsOfService', () => {
|
|||
|
||||
wrapper.setState({loading: false, termsId: 1, termsText: 'Terms Text'});
|
||||
wrapper.instance().closeTermsAndLogout();
|
||||
expect(baseProps.navigator.dismissAllModals).toHaveBeenCalledTimes(1);
|
||||
expect(baseProps.actions.dismissAllModals).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ 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,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -13,28 +13,6 @@ exports[`thread should match snapshot, has root post 1`] = `
|
|||
lastPostIndex={2}
|
||||
lastViewedAt={0}
|
||||
location="thread"
|
||||
navigator={
|
||||
Object {
|
||||
"dismissModal": [MockFunction],
|
||||
"pop": [MockFunction],
|
||||
"resetTo": [MockFunction],
|
||||
"setTitle": [MockFunction] {
|
||||
"calls": Array [
|
||||
Array [
|
||||
Object {
|
||||
"title": undefined,
|
||||
},
|
||||
],
|
||||
],
|
||||
"results": Array [
|
||||
Object {
|
||||
"type": "return",
|
||||
"value": undefined,
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
}
|
||||
onPostPress={[Function]}
|
||||
postIds={
|
||||
Array [
|
||||
|
|
@ -76,28 +54,6 @@ exports[`thread should match snapshot, has root post 1`] = `
|
|||
channelId="channel_id"
|
||||
channelIsArchived={false}
|
||||
cursorPositionEvent="onThreadTextBoxCursorChange"
|
||||
navigator={
|
||||
Object {
|
||||
"dismissModal": [MockFunction],
|
||||
"pop": [MockFunction],
|
||||
"resetTo": [MockFunction],
|
||||
"setTitle": [MockFunction] {
|
||||
"calls": Array [
|
||||
Array [
|
||||
Object {
|
||||
"title": undefined,
|
||||
},
|
||||
],
|
||||
],
|
||||
"results": Array [
|
||||
Object {
|
||||
"type": "return",
|
||||
"value": undefined,
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
}
|
||||
onCloseChannel={[Function]}
|
||||
rootId="root_id"
|
||||
valueEvent="onThreadTextBoxValueChange"
|
||||
|
|
@ -128,28 +84,6 @@ exports[`thread should match snapshot, render footer 1`] = `
|
|||
lastPostIndex={2}
|
||||
lastViewedAt={0}
|
||||
location="thread"
|
||||
navigator={
|
||||
Object {
|
||||
"dismissModal": [MockFunction],
|
||||
"pop": [MockFunction],
|
||||
"resetTo": [MockFunction],
|
||||
"setTitle": [MockFunction] {
|
||||
"calls": Array [
|
||||
Array [
|
||||
Object {
|
||||
"title": undefined,
|
||||
},
|
||||
],
|
||||
],
|
||||
"results": Array [
|
||||
Object {
|
||||
"type": "return",
|
||||
"value": undefined,
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
}
|
||||
onPostPress={[Function]}
|
||||
postIds={
|
||||
Array [
|
||||
|
|
@ -176,28 +110,6 @@ exports[`thread should match snapshot, render footer 2`] = `
|
|||
lastPostIndex={2}
|
||||
lastViewedAt={0}
|
||||
location="thread"
|
||||
navigator={
|
||||
Object {
|
||||
"dismissModal": [MockFunction],
|
||||
"pop": [MockFunction],
|
||||
"resetTo": [MockFunction],
|
||||
"setTitle": [MockFunction] {
|
||||
"calls": Array [
|
||||
Array [
|
||||
Object {
|
||||
"title": undefined,
|
||||
},
|
||||
],
|
||||
],
|
||||
"results": Array [
|
||||
Object {
|
||||
"type": "return",
|
||||
"value": undefined,
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
}
|
||||
onPostPress={[Function]}
|
||||
postIds={
|
||||
Array [
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ import {selectPost} from 'mattermost-redux/actions/posts';
|
|||
import {makeGetChannel, getMyCurrentChannelMembership} from 'mattermost-redux/selectors/entities/channels';
|
||||
import {makeGetPostIdsForThread} from 'mattermost-redux/selectors/entities/posts';
|
||||
|
||||
import {popTopScreen, resetToChannel} from 'app/actions/navigation';
|
||||
|
||||
import Thread from './thread';
|
||||
|
||||
function makeMapStateToProps() {
|
||||
|
|
@ -37,6 +39,8 @@ function mapDispatchToProps(dispatch) {
|
|||
return {
|
||||
actions: bindActionCreators({
|
||||
selectPost,
|
||||
popTopScreen,
|
||||
resetToChannel,
|
||||
}, dispatch),
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ export default class ThreadAndroid extends ThreadBase {
|
|||
const {
|
||||
channelId,
|
||||
myMember,
|
||||
navigator,
|
||||
postIds,
|
||||
rootId,
|
||||
channelIsArchived,
|
||||
|
|
@ -36,7 +35,6 @@ export default class ThreadAndroid extends ThreadBase {
|
|||
currentUserId={myMember && myMember.user_id}
|
||||
lastViewedAt={this.state.lastViewedAt}
|
||||
lastPostIndex={-1}
|
||||
navigator={navigator}
|
||||
onPostPress={this.hideKeyboard}
|
||||
location={THREAD}
|
||||
/>
|
||||
|
|
@ -47,7 +45,6 @@ export default class ThreadAndroid extends ThreadBase {
|
|||
channelIsArchived={channelIsArchived}
|
||||
rootId={rootId}
|
||||
channelId={channelId}
|
||||
navigator={navigator}
|
||||
onCloseChannel={this.onCloseChannel}
|
||||
/>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@ export default class ThreadIOS extends ThreadBase {
|
|||
const {
|
||||
channelId,
|
||||
myMember,
|
||||
navigator,
|
||||
postIds,
|
||||
rootId,
|
||||
channelIsArchived,
|
||||
|
|
@ -47,7 +46,6 @@ export default class ThreadIOS extends ThreadBase {
|
|||
lastPostIndex={getLastPostIndex(postIds)}
|
||||
currentUserId={myMember && myMember.user_id}
|
||||
lastViewedAt={this.state.lastViewedAt}
|
||||
navigator={navigator}
|
||||
onPostPress={this.hideKeyboard}
|
||||
location={THREAD}
|
||||
scrollViewNativeID={SCROLLVIEW_NATIVE_ID}
|
||||
|
|
@ -77,7 +75,6 @@ export default class ThreadIOS extends ThreadBase {
|
|||
channelIsArchived={channelIsArchived}
|
||||
rootId={rootId}
|
||||
channelId={channelId}
|
||||
navigator={navigator}
|
||||
onCloseChannel={this.onCloseChannel}
|
||||
cursorPositionEvent={THREAD_POST_TEXTBOX_CURSOR_CHANGE}
|
||||
valueEvent={THREAD_POST_TEXTBOX_VALUE_CHANGE}
|
||||
|
|
|
|||
|
|
@ -11,22 +11,22 @@ import PostList from 'app/components/post_list';
|
|||
import ThreadIOS from './thread.ios';
|
||||
|
||||
jest.mock('react-intl');
|
||||
jest.mock('react-native-navigation', () => ({
|
||||
Navigation: {
|
||||
mergeOptions: jest.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
describe('thread', () => {
|
||||
const navigator = {
|
||||
dismissModal: jest.fn(),
|
||||
pop: jest.fn(),
|
||||
resetTo: jest.fn(),
|
||||
setTitle: jest.fn(),
|
||||
};
|
||||
const baseProps = {
|
||||
actions: {
|
||||
selectPost: jest.fn(),
|
||||
popTopScreen: jest.fn(),
|
||||
resetToChannel: jest.fn(),
|
||||
},
|
||||
channelId: 'channel_id',
|
||||
channelType: General.OPEN_CHANNEL,
|
||||
displayName: 'channel_display_name',
|
||||
navigator,
|
||||
myMember: {last_viewed_at: 0, user_id: 'member_user_id'},
|
||||
rootId: 'root_id',
|
||||
theme: Preferences.THEMES.default,
|
||||
|
|
@ -55,35 +55,19 @@ describe('thread', () => {
|
|||
expect(wrapper.getElement()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('should call props.navigator on onCloseChannel', () => {
|
||||
const channelScreen = {
|
||||
screen: 'Channel',
|
||||
title: '',
|
||||
animated: false,
|
||||
backButtonTitle: '',
|
||||
navigatorStyle: {
|
||||
animated: true,
|
||||
animationType: 'fade',
|
||||
navBarHidden: true,
|
||||
statusBarHidden: false,
|
||||
statusBarHideWithNavBar: false,
|
||||
screenBackgroundColor: 'transparent',
|
||||
},
|
||||
passProps: {
|
||||
disableTermsModal: true,
|
||||
},
|
||||
test('should call props.actions.resetToChannel on onCloseChannel', () => {
|
||||
const passProps = {
|
||||
disableTermsModal: true,
|
||||
};
|
||||
const newNavigator = {...navigator};
|
||||
const wrapper = shallow(
|
||||
<ThreadIOS
|
||||
{...baseProps}
|
||||
navigator={newNavigator}
|
||||
/>,
|
||||
{context: {intl: {formatMessage: jest.fn()}}},
|
||||
);
|
||||
wrapper.instance().onCloseChannel();
|
||||
expect(newNavigator.resetTo).toHaveBeenCalledTimes(1);
|
||||
expect(newNavigator.resetTo).toBeCalledWith(channelScreen);
|
||||
expect(baseProps.actions.resetToChannel).toHaveBeenCalledTimes(1);
|
||||
expect(baseProps.actions.resetToChannel).toBeCalledWith(passProps);
|
||||
});
|
||||
|
||||
test('should match snapshot, render footer', () => {
|
||||
|
|
|
|||
|
|
@ -3,8 +3,9 @@
|
|||
|
||||
import React, {PureComponent} from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {Keyboard, Platform} from 'react-native';
|
||||
import {Keyboard} from 'react-native';
|
||||
import {intlShape} from 'react-intl';
|
||||
import {Navigation} from 'react-native-navigation';
|
||||
|
||||
import {General, RequestStatus} from 'mattermost-redux/constants';
|
||||
|
||||
|
|
@ -16,12 +17,13 @@ export default class ThreadBase extends PureComponent {
|
|||
static propTypes = {
|
||||
actions: PropTypes.shape({
|
||||
selectPost: PropTypes.func.isRequired,
|
||||
popTopScreen: PropTypes.func.isRequired,
|
||||
resetToChannel: PropTypes.func.isRequired,
|
||||
}).isRequired,
|
||||
componentId: PropTypes.string,
|
||||
channelId: PropTypes.string.isRequired,
|
||||
channelType: PropTypes.string,
|
||||
displayName: PropTypes.string,
|
||||
navigator: PropTypes.object,
|
||||
myMember: PropTypes.object.isRequired,
|
||||
rootId: PropTypes.string.isRequired,
|
||||
theme: PropTypes.object.isRequired,
|
||||
|
|
@ -53,8 +55,12 @@ export default class ThreadBase extends PureComponent {
|
|||
|
||||
this.postTextbox = React.createRef();
|
||||
|
||||
this.props.navigator.setTitle({
|
||||
title,
|
||||
Navigation.mergeOptions(props.componentId, {
|
||||
topBar: {
|
||||
title: {
|
||||
text: title,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
this.state = {
|
||||
|
|
@ -82,17 +88,7 @@ export default class ThreadBase extends PureComponent {
|
|||
}
|
||||
|
||||
close = () => {
|
||||
const {navigator} = this.props;
|
||||
|
||||
if (Platform.OS === 'ios') {
|
||||
navigator.pop({
|
||||
animated: true,
|
||||
});
|
||||
} else {
|
||||
navigator.dismissModal({
|
||||
animationType: 'slide-down',
|
||||
});
|
||||
}
|
||||
this.props.actions.popTopScreen();
|
||||
};
|
||||
|
||||
handleAutoComplete = (value) => {
|
||||
|
|
@ -124,22 +120,9 @@ export default class ThreadBase extends PureComponent {
|
|||
};
|
||||
|
||||
onCloseChannel = () => {
|
||||
this.props.navigator.resetTo({
|
||||
screen: 'Channel',
|
||||
title: '',
|
||||
animated: false,
|
||||
backButtonTitle: '',
|
||||
navigatorStyle: {
|
||||
animated: true,
|
||||
animationType: 'fade',
|
||||
navBarHidden: true,
|
||||
statusBarHidden: false,
|
||||
statusBarHideWithNavBar: false,
|
||||
screenBackgroundColor: 'transparent',
|
||||
},
|
||||
passProps: {
|
||||
disableTermsModal: true,
|
||||
},
|
||||
});
|
||||
const passProps = {
|
||||
disableTermsModal: true,
|
||||
};
|
||||
this.props.actions.resetToChannel(passProps);
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,13 @@ import {loadBot} from 'mattermost-redux/actions/bots';
|
|||
import {getBotAccounts} from 'mattermost-redux/selectors/entities/bots';
|
||||
import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users';
|
||||
|
||||
import {
|
||||
setButtons,
|
||||
dismissModal,
|
||||
resetToChannel,
|
||||
goToScreen,
|
||||
} from 'app/actions/navigation';
|
||||
|
||||
import UserProfile from './user_profile';
|
||||
|
||||
function mapStateToProps(state, ownProps) {
|
||||
|
|
@ -43,6 +50,10 @@ function mapDispatchToProps(dispatch) {
|
|||
makeDirectChannel,
|
||||
setChannelDisplayName,
|
||||
loadBot,
|
||||
setButtons,
|
||||
dismissModal,
|
||||
resetToChannel,
|
||||
goToScreen,
|
||||
}, dispatch),
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,11 +33,14 @@ export default class UserProfile extends PureComponent {
|
|||
makeDirectChannel: PropTypes.func.isRequired,
|
||||
setChannelDisplayName: PropTypes.func.isRequired,
|
||||
loadBot: PropTypes.func.isRequired,
|
||||
setButtons: PropTypes.func.isRequired,
|
||||
dismissModal: PropTypes.func.isRequired,
|
||||
resetToChannel: PropTypes.func.isRequired,
|
||||
goToScreen: PropTypes.func.isRequired,
|
||||
}).isRequired,
|
||||
componentId: PropTypes.string,
|
||||
config: PropTypes.object.isRequired,
|
||||
currentDisplayName: PropTypes.string,
|
||||
navigator: PropTypes.object,
|
||||
teammateNameDisplay: PropTypes.string,
|
||||
theme: PropTypes.object.isRequired,
|
||||
user: PropTypes.object.isRequired,
|
||||
|
|
@ -61,13 +64,13 @@ export default class UserProfile extends PureComponent {
|
|||
super(props);
|
||||
|
||||
if (props.isMyUser) {
|
||||
this.rightButton.title = context.intl.formatMessage({id: 'mobile.routes.user_profile.edit', defaultMessage: 'Edit'});
|
||||
this.rightButton.text = context.intl.formatMessage({id: 'mobile.routes.user_profile.edit', defaultMessage: 'Edit'});
|
||||
|
||||
const buttons = {
|
||||
rightButtons: [this.rightButton],
|
||||
};
|
||||
|
||||
props.navigator.setButtons(buttons);
|
||||
props.actions.setButtons(props.componentId, buttons);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -97,30 +100,17 @@ export default class UserProfile extends PureComponent {
|
|||
}
|
||||
|
||||
close = () => {
|
||||
const {navigator, theme} = this.props;
|
||||
const {actions, fromSettings} = this.props;
|
||||
|
||||
if (this.props.fromSettings) {
|
||||
navigator.dismissModal({
|
||||
animationType: 'slide-down',
|
||||
});
|
||||
if (fromSettings) {
|
||||
actions.dismissModal();
|
||||
return;
|
||||
}
|
||||
|
||||
navigator.resetTo({
|
||||
screen: 'Channel',
|
||||
animated: true,
|
||||
navigatorStyle: {
|
||||
animated: true,
|
||||
animationType: 'fade',
|
||||
navBarHidden: true,
|
||||
statusBarHidden: false,
|
||||
statusBarHideWithNavBar: false,
|
||||
screenBackgroundColor: theme.centerChannelBg,
|
||||
},
|
||||
passProps: {
|
||||
disableTermsModal: true,
|
||||
},
|
||||
});
|
||||
const passProps = {
|
||||
disableTermsModal: true,
|
||||
};
|
||||
actions.resetToChannel(passProps);
|
||||
};
|
||||
|
||||
getDisplayName = () => {
|
||||
|
|
@ -231,27 +221,15 @@ export default class UserProfile extends PureComponent {
|
|||
};
|
||||
|
||||
goToEditProfile = () => {
|
||||
const {user: currentUser} = this.props;
|
||||
const {actions, user: currentUser} = this.props;
|
||||
const {formatMessage} = this.context.intl;
|
||||
const commandType = 'Push';
|
||||
|
||||
const {navigator, theme} = this.props;
|
||||
const options = {
|
||||
screen: 'EditProfile',
|
||||
title: formatMessage({id: 'mobile.routes.edit_profile', defaultMessage: 'Edit Profile'}),
|
||||
animated: true,
|
||||
backButtonTitle: '',
|
||||
passProps: {currentUser, commandType},
|
||||
navigatorStyle: {
|
||||
navBarTextColor: theme.sidebarHeaderTextColor,
|
||||
navBarBackgroundColor: theme.sidebarHeaderBg,
|
||||
navBarButtonColor: theme.sidebarHeaderTextColor,
|
||||
screenBackgroundColor: theme.centerChannelBg,
|
||||
},
|
||||
};
|
||||
const screen = 'EditProfile';
|
||||
const title = formatMessage({id: 'mobile.routes.edit_profile', defaultMessage: 'Edit Profile'});
|
||||
const passProps = {currentUser, commandType};
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
navigator.push(options);
|
||||
actions.goToScreen(screen, title, passProps);
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,10 @@ describe('user_profile', () => {
|
|||
setChannelDisplayName: jest.fn(),
|
||||
makeDirectChannel: jest.fn(),
|
||||
loadBot: jest.fn(),
|
||||
setButtons: jest.fn(),
|
||||
dismissModal: jest.fn(),
|
||||
resetToChannel: jest.fn(),
|
||||
goToScreen: jest.fn(),
|
||||
};
|
||||
const baseProps = {
|
||||
actions,
|
||||
|
|
@ -29,11 +33,6 @@ describe('user_profile', () => {
|
|||
ShowEmailAddress: true,
|
||||
},
|
||||
teammateNameDisplay: 'username',
|
||||
navigator: {
|
||||
resetTo: jest.fn(),
|
||||
push: jest.fn(),
|
||||
dismissModal: jest.fn(),
|
||||
},
|
||||
teams: [],
|
||||
theme: Preferences.THEMES.default,
|
||||
enableTimezone: false,
|
||||
|
|
@ -90,16 +89,9 @@ describe('user_profile', () => {
|
|||
});
|
||||
|
||||
test('should push EditProfile', async () => {
|
||||
const props = {
|
||||
...baseProps,
|
||||
navigator: {
|
||||
push: jest.fn(),
|
||||
},
|
||||
};
|
||||
|
||||
const wrapper = shallow(
|
||||
<UserProfile
|
||||
{...props}
|
||||
{...baseProps}
|
||||
user={user}
|
||||
/>,
|
||||
{context: {intl: {formatMessage: jest.fn()}}},
|
||||
|
|
@ -107,18 +99,18 @@ describe('user_profile', () => {
|
|||
|
||||
wrapper.instance().goToEditProfile();
|
||||
setTimeout(() => {
|
||||
expect(props.navigator.push).toHaveBeenCalledTimes(1);
|
||||
expect(baseProps.actions.goToScreen).toHaveBeenCalledTimes(1);
|
||||
}, 16);
|
||||
});
|
||||
|
||||
test('should call goToEditProfile', () => {
|
||||
const props = {
|
||||
...baseProps,
|
||||
navigator: {
|
||||
push: jest.fn(),
|
||||
actions: {
|
||||
...baseProps.actions,
|
||||
goToScreen: jest.fn(),
|
||||
},
|
||||
};
|
||||
|
||||
const wrapper = shallow(
|
||||
<UserProfile
|
||||
{...props}
|
||||
|
|
@ -130,7 +122,7 @@ describe('user_profile', () => {
|
|||
const event = {buttonId: wrapper.instance().rightButton.id};
|
||||
wrapper.instance().navigationButtonPressed(event);
|
||||
setTimeout(() => {
|
||||
expect(props.navigator.push).toHaveBeenCalledTimes(1);
|
||||
expect(baseProps.actions.goToScreen).toHaveBeenCalledTimes(1);
|
||||
}, 0);
|
||||
});
|
||||
|
||||
|
|
@ -147,11 +139,11 @@ describe('user_profile', () => {
|
|||
|
||||
const event = {buttonId: 'close-settings'};
|
||||
wrapper.instance().navigationButtonPressed(event);
|
||||
expect(props.navigator.dismissModal).toHaveBeenCalledTimes(1);
|
||||
expect(props.actions.dismissModal).toHaveBeenCalledTimes(1);
|
||||
|
||||
props.fromSettings = false;
|
||||
wrapper.setProps({...props});
|
||||
wrapper.instance().navigationButtonPressed(event);
|
||||
expect(props.navigator.resetTo).toHaveBeenCalledTimes(1);
|
||||
expect(props.actions.resetToChannel).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import {
|
|||
createPostForNotificationReply,
|
||||
loadFromPushNotification,
|
||||
} from 'app/actions/views/root';
|
||||
import {dismissAllModals, popToRoot} from 'app/actions/navigation';
|
||||
import {ViewTypes} from 'app/constants';
|
||||
import {getLocalizedMessage} from 'app/i18n';
|
||||
import {getCurrentServerUrl, getAppCredentials} from 'app/init/credentials';
|
||||
|
|
@ -45,7 +46,13 @@ class PushNotificationUtils {
|
|||
await this.store.dispatch(loadFromPushNotification(notification, true));
|
||||
|
||||
if (!EphemeralStore.appStartedFromPushNotification) {
|
||||
EventEmitter.emit(ViewTypes.NOTIFICATION_TAPPED);
|
||||
EventEmitter.emit('close_channel_drawer');
|
||||
EventEmitter.emit('close_settings_sidebar');
|
||||
|
||||
const {dispatch} = this.store;
|
||||
dispatch(dismissAllModals());
|
||||
dispatch(popToRoot());
|
||||
|
||||
PushNotifications.resetNotification();
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -6,10 +6,8 @@ import IntlWrapper from 'app/components/root';
|
|||
|
||||
export function wrapWithContextProvider(Comp, excludeEvents = true) {
|
||||
return (props) => { //eslint-disable-line react/display-name
|
||||
const {navigator} = props; //eslint-disable-line react/prop-types
|
||||
return (
|
||||
<IntlWrapper
|
||||
navigator={navigator}
|
||||
excludeEvents={excludeEvents}
|
||||
>
|
||||
<Comp {...props}/>
|
||||
|
|
|
|||
|
|
@ -13,4 +13,4 @@ SPEC CHECKSUMS:
|
|||
|
||||
PODFILE CHECKSUM: 63cb0d0aef536c8cbf15bf664fcfe31852a13dd1
|
||||
|
||||
COCOAPODS: 1.6.1
|
||||
COCOAPODS: 1.5.3
|
||||
|
|
|
|||
Loading…
Reference in a new issue