RN-64 Ability to open the app in offline mode (#479)

This commit is contained in:
enahum 2017-04-13 11:57:19 -03:00 committed by GitHub
parent 43e4c5e2f2
commit cdff304be1
54 changed files with 866 additions and 969 deletions

View file

@ -1,17 +0,0 @@
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import {connect} from 'react-redux';
import {getUsersByUsername} from 'mattermost-redux/selectors/entities/users';
import AtMention from './at_mention';
function mapStateToProps(state, ownProps) {
return {
usersByUsername: getUsersByUsername(state),
...ownProps
};
}
export default connect(mapStateToProps)(AtMention);

View file

@ -1,5 +1,17 @@
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import AtMention from './at_mention_container';
export default AtMention;
import {connect} from 'react-redux';
import {getUsersByUsername} from 'mattermost-redux/selectors/entities/users';
import AtMention from './at_mention';
function mapStateToProps(state, ownProps) {
return {
usersByUsername: getUsersByUsername(state),
...ownProps
};
}
export default connect(mapStateToProps)(AtMention);

View file

@ -1,57 +0,0 @@
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import {
goToCreateChannel,
openSettingsModal,
requestCloseModal,
showMoreChannelsModal,
showDirectMessagesModal,
showOptionsModal
} from 'app/actions/navigation';
import {
closeDirectChannel,
leaveChannel,
markFavorite,
unmarkFavorite
} from 'app/actions/views/channel';
import {Constants} from 'mattermost-redux/constants';
import {getCurrentUserId, getCurrentUserRoles} from 'mattermost-redux/selectors/entities/users';
import {showCreateOption} from 'mattermost-redux/utils/channel_utils';
import {isAdmin, isSystemAdmin} from 'mattermost-redux/utils/user_utils';
import ChannelDrawerList from './channel_drawer_list';
function mapStateToProps(state, ownProps) {
const {config, license} = state.entities.general;
const roles = getCurrentUserId(state) ? getCurrentUserRoles(state) : '';
return {
canCreatePrivateChannels: showCreateOption(config, license, Constants.PRIVATE_CHANNEL, isAdmin(roles), isSystemAdmin(roles)),
...ownProps
};
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators({
closeDirectChannel,
goToCreateChannel,
leaveChannel,
markFavorite,
openSettingsModal,
unmarkFavorite,
showOptionsModal,
showDirectMessagesModal,
showMoreChannelsModal,
closeOptionsModal: requestCloseModal
}, dispatch)
};
}
export default connect(mapStateToProps, mapDispatchToProps)(ChannelDrawerList);

View file

@ -1,6 +1,57 @@
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import ChannelListContainer from './channel_drawer_list_container';
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
export default ChannelListContainer;
import {
goToCreateChannel,
openSettingsModal,
requestCloseModal,
showMoreChannelsModal,
showDirectMessagesModal,
showOptionsModal
} from 'app/actions/navigation';
import {
closeDirectChannel,
leaveChannel,
markFavorite,
unmarkFavorite
} from 'app/actions/views/channel';
import {Constants} from 'mattermost-redux/constants';
import {getCurrentUserId, getCurrentUserRoles} from 'mattermost-redux/selectors/entities/users';
import {showCreateOption} from 'mattermost-redux/utils/channel_utils';
import {isAdmin, isSystemAdmin} from 'mattermost-redux/utils/user_utils';
import ChannelDrawerList from './channel_drawer_list';
function mapStateToProps(state, ownProps) {
const {config, license} = state.entities.general;
const roles = getCurrentUserId(state) ? getCurrentUserRoles(state) : '';
return {
canCreatePrivateChannels: showCreateOption(config, license, Constants.PRIVATE_CHANNEL, isAdmin(roles), isSystemAdmin(roles)),
...ownProps
};
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators({
closeDirectChannel,
goToCreateChannel,
leaveChannel,
markFavorite,
openSettingsModal,
unmarkFavorite,
showOptionsModal,
showDirectMessagesModal,
showMoreChannelsModal,
closeOptionsModal: requestCloseModal
}, dispatch)
};
}
export default connect(mapStateToProps, mapDispatchToProps)(ChannelDrawerList);

View file

@ -1,27 +0,0 @@
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import {getDisplayableErrors} from 'mattermost-redux/selectors/errors';
import {dismissError, clearErrors} from 'mattermost-redux/actions/errors';
import ErrorList from './error_list';
function mapStateToProps(state) {
return {
errors: getDisplayableErrors(state)
};
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators({
dismissError,
clearErrors
}, dispatch)
};
}
export default connect(mapStateToProps, mapDispatchToProps)(ErrorList);

View file

@ -1,6 +1,27 @@
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import ErrorListContainer from './error_list_container';
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
export default ErrorListContainer;
import {getDisplayableErrors} from 'mattermost-redux/selectors/errors';
import {dismissError, clearErrors} from 'mattermost-redux/actions/errors';
import ErrorList from './error_list';
function mapStateToProps(state) {
return {
errors: getDisplayableErrors(state)
};
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators({
dismissError,
clearErrors
}, dispatch)
};
}
export default connect(mapStateToProps, mapDispatchToProps)(ErrorList);

View file

@ -77,7 +77,7 @@ export default class OfflineIndicator extends PureComponent {
// set forced to be false after trying for 3 seconds
setTimeout(() => {
closeWebSocket();
closeWebSocket(true);
this.setState({forced: false, network: OFFLINE});
}, 3000);
});

View file

@ -1,6 +1,57 @@
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import Post from './post_container';
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import {deletePost, flagPost, unflagPost} from 'mattermost-redux/actions/posts';
import {getMyPreferences} from 'mattermost-redux/selectors/entities/preferences';
import {getCurrentTeamId} from 'mattermost-redux/selectors/entities/teams';
import {makeGetCommentCountForPost} from 'mattermost-redux/selectors/entities/posts';
import {getCurrentUserId, getCurrentUserRoles, getUser} from 'mattermost-redux/selectors/entities/users';
import {isPostFlagged} from 'mattermost-redux/utils/post_utils';
import {displayUsername} from 'mattermost-redux/utils/user_utils';
export default Post;
import {goToUserProfile, openEditPostModal} from 'app/actions/navigation';
import {getTheme} from 'app/selectors/preferences';
import Post from './post';
function makeMapStateToProps() {
const getCommentCountForPost = makeGetCommentCountForPost();
return function mapStateToProps(state, ownProps) {
const commentedOnUser = ownProps.commentedOnPost ? getUser(state, ownProps.commentedOnPost.user_id) : null;
const user = getUser(state, ownProps.post.user_id);
const myPreferences = getMyPreferences(state);
const {config, license} = state.entities.general;
const roles = getCurrentUserId(state) ? getCurrentUserRoles(state) : '';
return {
...ownProps,
config,
commentCount: getCommentCountForPost(state, ownProps),
commentedOnDisplayName: displayUsername(commentedOnUser, myPreferences),
currentTeamId: getCurrentTeamId(state),
currentUserId: getCurrentUserId(state),
displayName: displayUsername(user, myPreferences),
isFlagged: isPostFlagged(ownProps.post.id, myPreferences),
license,
roles,
theme: getTheme(state),
user
};
};
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators({
deletePost,
flagPost,
goToUserProfile,
openEditPostModal,
unflagPost
}, dispatch)
};
}
export default connect(makeMapStateToProps, mapDispatchToProps)(Post);

View file

@ -14,11 +14,11 @@ import {
} from 'react-native';
import {injectIntl, intlShape} from 'react-intl';
import FileAttachmentList from 'app/components/file_attachment_list/file_attachment_list_container';
import FileAttachmentList from 'app/components/file_attachment_list';
import FormattedText from 'app/components/formatted_text';
import FormattedTime from 'app/components/formatted_time';
import MattermostIcon from 'app/components/mattermost_icon';
import Markdown from 'app/components/markdown/markdown';
import Markdown from 'app/components/markdown';
import OptionsContext from 'app/components/options_context';
import ProfilePicture from 'app/components/profile_picture';
import ReplyIcon from 'app/components/reply_icon';

View file

@ -1,57 +0,0 @@
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import {deletePost, flagPost, unflagPost} from 'mattermost-redux/actions/posts';
import {getMyPreferences} from 'mattermost-redux/selectors/entities/preferences';
import {getCurrentTeamId} from 'mattermost-redux/selectors/entities/teams';
import {makeGetCommentCountForPost} from 'mattermost-redux/selectors/entities/posts';
import {getCurrentUserId, getCurrentUserRoles, getUser} from 'mattermost-redux/selectors/entities/users';
import {isPostFlagged} from 'mattermost-redux/utils/post_utils';
import {displayUsername} from 'mattermost-redux/utils/user_utils';
import {goToUserProfile, openEditPostModal} from 'app/actions/navigation';
import {getTheme} from 'app/selectors/preferences';
import Post from './post';
function makeMapStateToProps() {
const getCommentCountForPost = makeGetCommentCountForPost();
return function mapStateToProps(state, ownProps) {
const commentedOnUser = ownProps.commentedOnPost ? getUser(state, ownProps.commentedOnPost.user_id) : null;
const user = getUser(state, ownProps.post.user_id);
const myPreferences = getMyPreferences(state);
const {config, license} = state.entities.general;
const roles = getCurrentUserId(state) ? getCurrentUserRoles(state) : '';
return {
...ownProps,
config,
commentCount: getCommentCountForPost(state, ownProps),
commentedOnDisplayName: displayUsername(commentedOnUser, myPreferences),
currentTeamId: getCurrentTeamId(state),
currentUserId: getCurrentUserId(state),
displayName: displayUsername(user, myPreferences),
isFlagged: isPostFlagged(ownProps.post.id, myPreferences),
license,
roles,
theme: getTheme(state),
user
};
};
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators({
deletePost,
flagPost,
goToUserProfile,
openEditPostModal,
unflagPost
}, dispatch)
};
}
export default connect(makeMapStateToProps, mapDispatchToProps)(Post);

View file

@ -1,6 +1,17 @@
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import PostList from './post_list_container';
import {connect} from 'react-redux';
export default PostList;
import {getTheme} from 'app/selectors/preferences';
import PostList from './post_list';
function mapStateToProps(state, ownProps) {
return {
theme: getTheme(state),
...ownProps
};
}
export default connect(mapStateToProps)(PostList);

View file

@ -1,17 +0,0 @@
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import {connect} from 'react-redux';
import {getTheme} from 'app/selectors/preferences';
import PostList from './post_list';
function mapStateToProps(state, ownProps) {
return {
theme: getTheme(state),
...ownProps
};
}
export default connect(mapStateToProps)(PostList);

View file

@ -1,6 +1,41 @@
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import PostTextboxContainer from './post_textbox_container';
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import {createPost} from 'mattermost-redux/actions/posts';
import {userTyping} from 'mattermost-redux/actions/websocket';
export default PostTextboxContainer;
import {showOptionsModal, requestCloseModal} from 'app/actions/navigation';
import {handleRemoveLastFile, handleUploadFiles} from 'app/actions/views/file_upload';
import {getTheme} from 'app/selectors/preferences';
import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users';
import {getUsersTyping} from 'mattermost-redux/selectors/entities/typing';
import PostTextbox from './post_textbox';
function mapStateToProps(state, ownProps) {
return {
...ownProps,
channelIsLoading: state.views.channel.loading,
currentUserId: getCurrentUserId(state),
typing: getUsersTyping(state),
theme: getTheme(state),
uploadFileRequestStatus: state.requests.files.uploadFiles.status
};
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators({
createPost,
closeModal: requestCloseModal,
handleRemoveLastFile,
handleUploadFiles,
showOptionsModal,
userTyping
}, dispatch)
};
}
export default connect(mapStateToProps, mapDispatchToProps, null, {withRef: true})(PostTextbox);

View file

@ -1,41 +0,0 @@
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import {createPost} from 'mattermost-redux/actions/posts';
import {userTyping} from 'mattermost-redux/actions/websocket';
import {showOptionsModal, requestCloseModal} from 'app/actions/navigation';
import {handleRemoveLastFile, handleUploadFiles} from 'app/actions/views/file_upload';
import {getTheme} from 'app/selectors/preferences';
import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users';
import {getUsersTyping} from 'mattermost-redux/selectors/entities/typing';
import PostTextbox from './post_textbox';
function mapStateToProps(state, ownProps) {
return {
...ownProps,
channelIsLoading: state.views.channel.loading,
currentUserId: getCurrentUserId(state),
typing: getUsersTyping(state),
theme: getTheme(state),
uploadFileRequestStatus: state.requests.files.uploadFiles.status
};
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators({
createPost,
closeModal: requestCloseModal,
handleRemoveLastFile,
handleUploadFiles,
showOptionsModal,
userTyping
}, dispatch)
};
}
export default connect(mapStateToProps, mapDispatchToProps, null, {withRef: true})(PostTextbox);

View file

@ -1,6 +1,34 @@
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import ProfilePicture from './profile_picture_container';
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
export default ProfilePicture;
import {getTheme} from 'app/selectors/preferences';
import {getStatusesByIdsBatchedDebounced} from 'mattermost-redux/actions/users';
import {getStatusForUserId} from 'mattermost-redux/selectors/entities/users';
import ProfilePicture from './profile_picture';
function mapStateToProps(state, ownProps) {
let status = ownProps.status;
if (!status && ownProps.user) {
status = ownProps.user.status || getStatusForUserId(state, ownProps.user.id);
}
return {
theme: ownProps.theme || getTheme(state),
status,
...ownProps
};
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators({
getStatusForId: getStatusesByIdsBatchedDebounced
}, dispatch)
};
}
export default connect(mapStateToProps, mapDispatchToProps)(ProfilePicture);

View file

@ -1,34 +0,0 @@
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import {getTheme} from 'app/selectors/preferences';
import {getStatusesByIdsBatchedDebounced} from 'mattermost-redux/actions/users';
import {getStatusForUserId} from 'mattermost-redux/selectors/entities/users';
import ProfilePicture from './profile_picture';
function mapStateToProps(state, ownProps) {
let status = ownProps.status;
if (!status && ownProps.user) {
status = ownProps.user.status || getStatusForUserId(state, ownProps.user.id);
}
return {
theme: ownProps.theme || getTheme(state),
status,
...ownProps
};
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators({
getStatusForId: getStatusesByIdsBatchedDebounced
}, dispatch)
};
}
export default connect(mapStateToProps, mapDispatchToProps)(ProfilePicture);

View file

@ -1,6 +1,53 @@
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import RootContainer from './root_container';
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
export default RootContainer;
import Config from 'assets/config.json';
import {closeDrawers, closeModal, goBack, unrenderDrawer} from 'app/actions/navigation';
import {goToNotification, loadConfigAndLicense, queueNotification} from 'app/actions/views/root';
import {setAppState, setDeviceToken} from 'mattermost-redux/actions/general';
import {logout} from 'mattermost-redux/actions/users';
import Root from './root';
function mapStateToProps(state, ownProps) {
const users = state.entities.users;
const {currentUserId} = users;
const {currentTeamId} = state.entities.teams;
const {currentChannelId} = state.entities.channels;
let locale = Config.DefaultLocale;
if (currentUserId && users.profiles[currentUserId]) {
locale = users.profiles[currentUserId].locale;
}
return {
...ownProps,
currentTeamId,
currentChannelId,
locale,
navigation: state.navigation
};
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators({
closeDrawers,
closeModal,
goBack,
loadConfigAndLicense,
logout,
goToNotification,
queueNotification,
setAppState,
setDeviceToken,
unrenderDrawer
}, dispatch)
};
}
export default connect(mapStateToProps, mapDispatchToProps)(Root);

View file

@ -5,7 +5,6 @@ import React, {Component, PropTypes} from 'react';
import {
Alert,
AppState,
AsyncStorage,
BackAndroid,
InteractionManager,
Platform,
@ -43,12 +42,6 @@ export default class Root extends Component {
}).isRequired
};
constructor(props) {
super(props);
this.handleAppStateChange = this.handleAppStateChange.bind(this);
}
componentDidMount() {
this.props.actions.setAppState(AppState.currentState === 'active');
AppState.addEventListener('change', this.handleAppStateChange);
@ -69,13 +62,13 @@ export default class Root extends Component {
}
}
handleAppStateChange(appState) {
handleAppStateChange = (appState) => {
this.props.actions.setAppState(appState === 'active');
if (appState === 'inactive') {
// TODO: See if we still need this
}
}
};
handleAndroidBack = () => {
const {index, isModal, leftDrawerOpen, modal} = this.props.navigation;
@ -125,17 +118,9 @@ export default class Root extends Component {
Client.serverVersion = '';
const storage = await AsyncStorage.getItem('storage');
if (storage) {
setTimeout(async () => {
const {token} = JSON.parse(await AsyncStorage.getItem('storage'));
if (token) {
closeDrawers();
unrenderDrawer();
InteractionManager.runAfterInteractions(logout);
}
}, 1000);
}
closeDrawers();
unrenderDrawer();
InteractionManager.runAfterInteractions(logout);
};
render() {

View file

@ -1,53 +0,0 @@
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import Config from 'assets/config.json';
import {closeDrawers, closeModal, goBack, unrenderDrawer} from 'app/actions/navigation';
import {goToNotification, loadConfigAndLicense, queueNotification} from 'app/actions/views/root';
import {setAppState, setDeviceToken} from 'mattermost-redux/actions/general';
import {logout} from 'mattermost-redux/actions/users';
import Root from './root';
function mapStateToProps(state, ownProps) {
const users = state.entities.users;
const {currentUserId} = users;
const {currentTeamId} = state.entities.teams;
const {currentChannelId} = state.entities.channels;
let locale = Config.DefaultLocale;
if (currentUserId && users.profiles[currentUserId]) {
locale = users.profiles[currentUserId].locale;
}
return {
...ownProps,
currentTeamId,
currentChannelId,
locale,
navigation: state.navigation
};
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators({
closeDrawers,
closeModal,
goBack,
loadConfigAndLicense,
logout,
goToNotification,
queueNotification,
setAppState,
setDeviceToken,
unrenderDrawer
}, dispatch)
};
}
export default connect(mapStateToProps, mapDispatchToProps)(Root);

View file

@ -279,6 +279,7 @@ const state = {
drafts: {},
loading: false
},
connection: true,
fetchCache: {},
i18n: {
locale: ''

View file

@ -1,26 +0,0 @@
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import {bindActionCreators} from 'redux';
import {goToAccountNotifications} from 'app/actions/navigation';
import {getTheme} from 'app/selectors/preferences';
import navigationSceneConnect from '../navigationSceneConnect';
import AccountSettings from './account_settings';
function mapStateToProps(state) {
return {
theme: getTheme(state)
};
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators({
goToAccountNotifications
}, dispatch)
};
}
export default navigationSceneConnect(mapStateToProps, mapDispatchToProps)(AccountSettings);

View file

@ -1,6 +1,26 @@
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import AccountSettingsContainer from './account_settings_container';
import {bindActionCreators} from 'redux';
export default AccountSettingsContainer;
import {goToAccountNotifications} from 'app/actions/navigation';
import {getTheme} from 'app/selectors/preferences';
import navigationSceneConnect from '../navigationSceneConnect';
import AccountSettings from './account_settings';
function mapStateToProps(state) {
return {
theme: getTheme(state)
};
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators({
goToAccountNotifications
}, dispatch)
};
}
export default navigationSceneConnect(mapStateToProps, mapDispatchToProps)(AccountSettings);

View file

@ -64,11 +64,7 @@ export default class Channel extends PureComponent {
this.props.subscribeToHeaderEvent('show_channel_info', () => preventDoubleTap(this.props.actions.goToChannelInfo));
NetInfo.isConnected.addEventListener('change', this.handleConnectionChange);
EventEmitter.on('leave_team', this.handleLeaveTeam);
// Android won't detect the initial connection change that's why we need this
if (Platform.OS === 'android') {
NetInfo.isConnected.fetch().then(this.handleConnectionChange);
}
NetInfo.isConnected.fetch().then(this.handleConnectionChange);
if (this.props.currentTeam) {
const teamId = this.props.currentTeam.id;
@ -77,8 +73,13 @@ export default class Channel extends PureComponent {
}
componentDidMount() {
this.props.actions.startPeriodicStatusUpdates();
this.props.actions.renderDrawer();
const {renderDrawer, startPeriodicStatusUpdates} = this.props.actions;
try {
startPeriodicStatusUpdates();
} catch (error) {
// We don't care about the error
}
renderDrawer();
}
componentWillReceiveProps(nextProps) {
@ -102,18 +103,27 @@ export default class Channel extends PureComponent {
if (isConnected) {
if (!webSocketRequest || webSocketRequest.status === RequestStatus.NOT_STARTED) {
initWebSocket(Platform.OS);
try {
initWebSocket(Platform.OS);
} catch (error) {
// We don't care if it fails
}
}
} else {
closeWebSocket();
closeWebSocket(true);
}
connection(isConnected);
};
loadChannels = (teamId) => {
this.props.actions.loadChannelsIfNecessary(teamId).then(() => {
this.props.actions.loadProfilesAndTeamMembersForDMSidebar(teamId);
return this.props.actions.selectInitialChannel(teamId);
const {
loadChannelsIfNecessary,
loadProfilesAndTeamMembersForDMSidebar,
selectInitialChannel
} = this.props.actions;
loadChannelsIfNecessary(teamId).then(() => {
loadProfilesAndTeamMembersForDMSidebar(teamId);
return selectInitialChannel(teamId);
});
};

View file

@ -1,67 +0,0 @@
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import {bindActionCreators} from 'redux';
import navigationSceneConnect from '../navigationSceneConnect';
import {
goToChannelInfo,
openChannelDrawer,
renderDrawer
} from 'app/actions/navigation';
import {
loadChannelsIfNecessary,
loadProfilesAndTeamMembersForDMSidebar,
selectInitialChannel,
handlePostDraftChanged
} from 'app/actions/views/channel';
import {connection} from 'app/actions/views/connection';
import {selectFirstAvailableTeam} from 'app/actions/views/select_team';
import {getTheme} from 'app/selectors/preferences';
import {startPeriodicStatusUpdates, stopPeriodicStatusUpdates} from 'mattermost-redux/actions/users';
import {getCurrentChannel} from 'mattermost-redux/selectors/entities/channels';
import {getCurrentTeam} from 'mattermost-redux/selectors/entities/teams';
import {
init as initWebSocket,
close as closeWebSocket
} from 'mattermost-redux/actions/websocket';
import Channel from './channel';
function mapStateToProps(state, ownProps) {
const {websocket} = state.requests.general;
return {
...ownProps,
...state.views.channel,
currentTeam: getCurrentTeam(state),
currentChannel: getCurrentChannel(state),
theme: getTheme(state),
webSocketRequest: websocket
};
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators({
connection,
loadChannelsIfNecessary,
loadProfilesAndTeamMembersForDMSidebar,
selectFirstAvailableTeam,
selectInitialChannel,
openChannelDrawer,
handlePostDraftChanged,
goToChannelInfo,
initWebSocket,
closeWebSocket,
startPeriodicStatusUpdates,
stopPeriodicStatusUpdates,
renderDrawer
}, dispatch)
};
}
export default navigationSceneConnect(mapStateToProps, mapDispatchToProps)(Channel);

View file

@ -1,91 +0,0 @@
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import {createSelector} from 'reselect';
import {getPostsBefore} from 'mattermost-redux/actions/posts';
import {getAllPosts, getPostsInCurrentChannel} from 'mattermost-redux/selectors/entities/posts';
import {getCurrentChannelMembership} from 'mattermost-redux/selectors/entities/channels';
import {getCurrentTeamId} from 'mattermost-redux/selectors/entities/teams';
import {goToThread} from 'app/actions/navigation';
import {loadPostsIfNecessary} from 'app/actions/views/channel';
import {getTheme} from 'app/selectors/preferences';
import ChannelPostList from './channel_post_list';
const getPostsInCurrentChannelWithReplyProps = createSelector(
getAllPosts,
getPostsInCurrentChannel,
(allPosts, postsInChannel) => {
const posts = [];
for (let i = 0; i < postsInChannel.length; i++) {
let post = postsInChannel[i];
if (post.root_id) {
let isFirstReply = false;
let isLastReply = false;
let commentedOnPost;
if (i + 1 <= postsInChannel.length) {
const previousPost = postsInChannel[i + 1];
if (previousPost.root_id !== post.root_id) {
isFirstReply = true;
if (previousPost.id !== post.root_id) {
commentedOnPost = allPosts[post.root_id];
}
}
} else {
// The first visible comment will always be the first comment in a thread and will be
// commenting on a post that isn't visible
isFirstReply = true;
commentedOnPost = allPosts[post.root_id];
}
if (i - 1 < 0 || postsInChannel[i - 1].root_id !== post.root_id) {
isLastReply = true;
}
post = {
...post,
isFirstReply,
isLastReply,
commentedOnPost
};
}
posts.push(post);
}
return posts;
}
);
function mapStateToProps(state, ownProps) {
return {
...ownProps,
applicationInitializing: state.views.channel.appInitializing,
currentTeamId: getCurrentTeamId(state),
channelIsLoading: state.views.channel.loading,
myMember: getCurrentChannelMembership(state),
postsRequests: state.requests.posts,
posts: getPostsInCurrentChannelWithReplyProps(state),
theme: getTheme(state)
};
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators({
loadPostsIfNecessary,
getPostsBefore,
goToThread
}, dispatch)
};
}
export default connect(mapStateToProps, mapDispatchToProps)(ChannelPostList);

View file

@ -1,6 +1,91 @@
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import ChannelPostListContainer from './channel_post_list_container';
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import {createSelector} from 'reselect';
import {getPostsBefore} from 'mattermost-redux/actions/posts';
import {getAllPosts, getPostsInCurrentChannel} from 'mattermost-redux/selectors/entities/posts';
import {getCurrentChannelMembership} from 'mattermost-redux/selectors/entities/channels';
import {getCurrentTeamId} from 'mattermost-redux/selectors/entities/teams';
export default ChannelPostListContainer;
import {goToThread} from 'app/actions/navigation';
import {loadPostsIfNecessary} from 'app/actions/views/channel';
import {getTheme} from 'app/selectors/preferences';
import ChannelPostList from './channel_post_list';
const getPostsInCurrentChannelWithReplyProps = createSelector(
getAllPosts,
getPostsInCurrentChannel,
(allPosts, postsInChannel) => {
const posts = [];
for (let i = 0; i < postsInChannel.length; i++) {
let post = postsInChannel[i];
if (post.root_id) {
let isFirstReply = false;
let isLastReply = false;
let commentedOnPost;
if (i + 1 <= postsInChannel.length) {
const previousPost = postsInChannel[i + 1];
if (previousPost.root_id !== post.root_id) {
isFirstReply = true;
if (previousPost.id !== post.root_id) {
commentedOnPost = allPosts[post.root_id];
}
}
} else {
// The first visible comment will always be the first comment in a thread and will be
// commenting on a post that isn't visible
isFirstReply = true;
commentedOnPost = allPosts[post.root_id];
}
if (i - 1 < 0 || postsInChannel[i - 1].root_id !== post.root_id) {
isLastReply = true;
}
post = {
...post,
isFirstReply,
isLastReply,
commentedOnPost
};
}
posts.push(post);
}
return posts;
}
);
function mapStateToProps(state, ownProps) {
return {
...ownProps,
applicationInitializing: state.views.channel.appInitializing,
currentTeamId: getCurrentTeamId(state),
channelIsLoading: state.views.channel.loading,
myMember: getCurrentChannelMembership(state),
postsRequests: state.requests.posts,
posts: getPostsInCurrentChannelWithReplyProps(state),
theme: getTheme(state)
};
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators({
loadPostsIfNecessary,
getPostsBefore,
goToThread
}, dispatch)
};
}
export default connect(mapStateToProps, mapDispatchToProps)(ChannelPostList);

View file

@ -1,6 +1,67 @@
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import ChannelContainer from './channel_container';
import {bindActionCreators} from 'redux';
export default ChannelContainer;
import navigationSceneConnect from '../navigationSceneConnect';
import {
goToChannelInfo,
openChannelDrawer,
renderDrawer
} from 'app/actions/navigation';
import {
loadChannelsIfNecessary,
loadProfilesAndTeamMembersForDMSidebar,
selectInitialChannel,
handlePostDraftChanged
} from 'app/actions/views/channel';
import {connection} from 'app/actions/views/connection';
import {selectFirstAvailableTeam} from 'app/actions/views/select_team';
import {getTheme} from 'app/selectors/preferences';
import {startPeriodicStatusUpdates, stopPeriodicStatusUpdates} from 'mattermost-redux/actions/users';
import {getCurrentChannel} from 'mattermost-redux/selectors/entities/channels';
import {getCurrentTeam} from 'mattermost-redux/selectors/entities/teams';
import {
init as initWebSocket,
close as closeWebSocket
} from 'mattermost-redux/actions/websocket';
import Channel from './channel';
function mapStateToProps(state, ownProps) {
const {websocket} = state.requests.general;
return {
...ownProps,
...state.views.channel,
currentTeam: getCurrentTeam(state),
currentChannel: getCurrentChannel(state),
theme: getTheme(state),
webSocketRequest: websocket
};
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators({
connection,
loadChannelsIfNecessary,
loadProfilesAndTeamMembersForDMSidebar,
selectFirstAvailableTeam,
selectInitialChannel,
openChannelDrawer,
handlePostDraftChanged,
goToChannelInfo,
initWebSocket,
closeWebSocket,
startPeriodicStatusUpdates,
stopPeriodicStatusUpdates,
renderDrawer
}, dispatch)
};
}
export default navigationSceneConnect(mapStateToProps, mapDispatchToProps)(Channel);

View file

@ -1,51 +0,0 @@
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import {bindActionCreators} from 'redux';
import navigationSceneConnect from '../navigationSceneConnect';
import {handleAddChannelMembers} from 'app/actions/views/channel_add_members';
import {goBack} from 'app/actions/navigation';
import {getTheme} from 'app/selectors/preferences';
import {getCurrentChannel, getCurrentChannelStats} from 'mattermost-redux/selectors/entities/channels';
import {getMyPreferences} from 'mattermost-redux/selectors/entities/preferences';
import {getCurrentTeam, getCurrentTeamStats} from 'mattermost-redux/selectors/entities/teams';
import {getProfilesNotInCurrentChannel} from 'mattermost-redux/selectors/entities/users';
import {getTeamStats} from 'mattermost-redux/actions/teams';
import {getProfilesNotInChannel, searchProfiles} from 'mattermost-redux/actions/users';
import ChannelAddMembers from './channel_add_members';
function mapStateToProps(state) {
const currentTeamMemberCount = getCurrentTeamStats(state) && getCurrentTeamStats(state).total_member_count;
const currentChannelMemberCount = getCurrentChannelStats(state) && getCurrentChannelStats(state).member_count;
return {
theme: getTheme(state),
currentChannel: getCurrentChannel(state),
membersNotInChannel: getProfilesNotInCurrentChannel(state),
currentTeam: getCurrentTeam(state),
currentTeamMemberCount,
currentChannelMemberCount,
preferences: getMyPreferences(state),
loadMoreRequestStatus: state.requests.users.getProfilesNotInChannel.status,
addChannelMemberRequestStatus: state.requests.channels.addChannelMember,
searchRequestStatus: state.requests.users.searchProfiles.status,
addChannelMemberStatus: state.requests.channels.addChannelMember.status
};
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators({
getTeamStats,
getProfilesNotInChannel,
goBack,
handleAddChannelMembers,
searchProfiles
}, dispatch)
};
}
export default navigationSceneConnect(mapStateToProps, mapDispatchToProps)(ChannelAddMembers);

View file

@ -1,6 +1,51 @@
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import ChannelAddMembersContainer from './channel_add_members_container';
import {bindActionCreators} from 'redux';
export default ChannelAddMembersContainer;
import navigationSceneConnect from '../navigationSceneConnect';
import {handleAddChannelMembers} from 'app/actions/views/channel_add_members';
import {goBack} from 'app/actions/navigation';
import {getTheme} from 'app/selectors/preferences';
import {getCurrentChannel, getCurrentChannelStats} from 'mattermost-redux/selectors/entities/channels';
import {getMyPreferences} from 'mattermost-redux/selectors/entities/preferences';
import {getCurrentTeam, getCurrentTeamStats} from 'mattermost-redux/selectors/entities/teams';
import {getProfilesNotInCurrentChannel} from 'mattermost-redux/selectors/entities/users';
import {getTeamStats} from 'mattermost-redux/actions/teams';
import {getProfilesNotInChannel, searchProfiles} from 'mattermost-redux/actions/users';
import ChannelAddMembers from './channel_add_members';
function mapStateToProps(state) {
const currentTeamMemberCount = getCurrentTeamStats(state) && getCurrentTeamStats(state).total_member_count;
const currentChannelMemberCount = getCurrentChannelStats(state) && getCurrentChannelStats(state).member_count;
return {
theme: getTheme(state),
currentChannel: getCurrentChannel(state),
membersNotInChannel: getProfilesNotInCurrentChannel(state),
currentTeam: getCurrentTeam(state),
currentTeamMemberCount,
currentChannelMemberCount,
preferences: getMyPreferences(state),
loadMoreRequestStatus: state.requests.users.getProfilesNotInChannel.status,
addChannelMemberRequestStatus: state.requests.channels.addChannelMember,
searchRequestStatus: state.requests.users.searchProfiles.status,
addChannelMemberStatus: state.requests.channels.addChannelMember.status
};
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators({
getTeamStats,
getProfilesNotInChannel,
goBack,
handleAddChannelMembers,
searchProfiles
}, dispatch)
};
}
export default navigationSceneConnect(mapStateToProps, mapDispatchToProps)(ChannelAddMembers);

View file

@ -29,16 +29,25 @@ export default class ChannelDrawer extends PureComponent {
selectChannel = (id) => {
const {
actions,
currentChannel,
currentTeam
} = this.props;
this.props.actions.markChannelAsRead(currentChannel.id);
this.props.actions.setChannelLoading();
this.props.actions.viewChannel(currentTeam.id, id);
this.props.actions.closeDrawers();
const {
closeDrawers,
handleSelectChannel,
markChannelAsRead,
setChannelLoading,
viewChannel
} = actions;
markChannelAsRead(currentChannel.id);
setChannelLoading();
viewChannel(currentTeam.id, id);
closeDrawers();
InteractionManager.runAfterInteractions(() => {
this.props.actions.handleSelectChannel(id);
handleSelectChannel(id);
});
};

View file

@ -1,40 +0,0 @@
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import {closeDrawers} from 'app/actions/navigation';
import {handleSelectChannel, setChannelLoading} from 'app/actions/views/channel';
import {getChannelsByCategory, getCurrentChannel} from 'mattermost-redux/selectors/entities/channels';
import {getTheme} from 'app/selectors/preferences';
import {getCurrentTeam} from 'mattermost-redux/selectors/entities/teams';
import {viewChannel, markChannelAsRead} from 'mattermost-redux/actions/channels';
import ChannelDrawer from './channel_drawer.js';
function mapStateToProps(state) {
return {
currentTeam: getCurrentTeam(state),
currentChannel: getCurrentChannel(state),
channels: getChannelsByCategory(state),
channelMembers: state.entities.channels.myMembers,
theme: getTheme(state)
};
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators({
closeDrawers,
handleSelectChannel,
viewChannel,
markChannelAsRead,
setChannelLoading
}, dispatch)
};
}
export default connect(mapStateToProps, mapDispatchToProps)(ChannelDrawer);

View file

@ -1,6 +1,40 @@
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import ChannelDrawerContainer from './channel_drawer_container';
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
export default ChannelDrawerContainer;
import {closeDrawers} from 'app/actions/navigation';
import {handleSelectChannel, setChannelLoading} from 'app/actions/views/channel';
import {getChannelsByCategory, getCurrentChannel} from 'mattermost-redux/selectors/entities/channels';
import {getTheme} from 'app/selectors/preferences';
import {getCurrentTeam} from 'mattermost-redux/selectors/entities/teams';
import {viewChannel, markChannelAsRead} from 'mattermost-redux/actions/channels';
import ChannelDrawer from './channel_drawer.js';
function mapStateToProps(state) {
return {
currentTeam: getCurrentTeam(state),
currentChannel: getCurrentChannel(state),
channels: getChannelsByCategory(state),
channelMembers: state.entities.channels.myMembers,
theme: getTheme(state)
};
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators({
closeDrawers,
handleSelectChannel,
viewChannel,
markChannelAsRead,
setChannelLoading
}, dispatch)
};
}
export default connect(mapStateToProps, mapDispatchToProps)(ChannelDrawer);

View file

@ -1,83 +0,0 @@
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import {bindActionCreators} from 'redux';
import {goToChannelMembers, goToChannelAddMembers, goBack} from 'app/actions/navigation';
import {
closeDMChannel,
closeGMChannel,
leaveChannel,
markFavorite,
unmarkFavorite
} from 'app/actions/views/channel';
import navigationSceneConnect from 'app/scenes/navigationSceneConnect';
import {getTheme} from 'app/selectors/preferences';
import {getChannelStats, deleteChannel} from 'mattermost-redux/actions/channels';
import {Constants} from 'mattermost-redux/constants';
import {
getCurrentChannel,
getCurrentChannelStats,
getChannelsByCategory,
canManageChannelMembers
} from 'mattermost-redux/selectors/entities/channels';
import {getCurrentUserId, getUser, getStatusForUserId, getCurrentUserRoles} from 'mattermost-redux/selectors/entities/users';
import {getUserIdFromChannelName, showDeleteOption} from 'mattermost-redux/utils/channel_utils';
import {isAdmin, isChannelAdmin, isSystemAdmin} from 'mattermost-redux/utils/user_utils';
import ChannelInfo from './channel_info';
function mapStateToProps(state, ownProps) {
const {config, license} = state.entities.general;
const currentChannel = getCurrentChannel(state);
const currentChannelCreator = getUser(state, currentChannel.creator_id);
const currentChannelCreatorName = currentChannelCreator && currentChannelCreator.username;
const currentChannelMemberCount = getCurrentChannelStats(state) && getCurrentChannelStats(state).member_count;
const currentUserId = getCurrentUserId(state);
const favoriteChannels = getChannelsByCategory(state).favoriteChannels.map((f) => f.id);
const isCurrent = currentChannel.id === state.entities.channels.currentChannelId;
const isFavorite = favoriteChannels.indexOf(currentChannel.id) > -1;
const leaveChannelRequest = state.requests.channels.leaveChannel;
const roles = getCurrentUserRoles(state);
let status;
if (currentChannel.type === Constants.DM_CHANNEL) {
const teammateId = getUserIdFromChannelName(currentUserId, currentChannel.name);
status = getStatusForUserId(state, teammateId);
}
return {
...ownProps,
canDeleteChannel: showDeleteOption(config, license, currentChannel, isAdmin(roles), isSystemAdmin(roles), isChannelAdmin(roles)),
currentTeamId: state.entities.teams.currentTeamId,
currentChannel,
currentChannelCreatorName,
currentChannelMemberCount,
isCurrent,
isFavorite,
leaveChannelRequest,
status,
theme: getTheme(state),
canManageUsers: canManageChannelMembers(state)
};
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators({
closeDMChannel,
closeGMChannel,
deleteChannel,
getChannelStats,
goBack,
goToChannelAddMembers,
goToChannelMembers,
leaveChannel,
markFavorite,
unmarkFavorite
}, dispatch)
};
}
export default navigationSceneConnect(mapStateToProps, mapDispatchToProps)(ChannelInfo);

View file

@ -1,6 +1,83 @@
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import ChannelInfoContainer from './channel_info_container';
import {bindActionCreators} from 'redux';
export default ChannelInfoContainer;
import {goToChannelMembers, goToChannelAddMembers, goBack} from 'app/actions/navigation';
import {
closeDMChannel,
closeGMChannel,
leaveChannel,
markFavorite,
unmarkFavorite
} from 'app/actions/views/channel';
import navigationSceneConnect from 'app/scenes/navigationSceneConnect';
import {getTheme} from 'app/selectors/preferences';
import {getChannelStats, deleteChannel} from 'mattermost-redux/actions/channels';
import {Constants} from 'mattermost-redux/constants';
import {
getCurrentChannel,
getCurrentChannelStats,
getChannelsByCategory,
canManageChannelMembers
} from 'mattermost-redux/selectors/entities/channels';
import {getCurrentUserId, getUser, getStatusForUserId, getCurrentUserRoles} from 'mattermost-redux/selectors/entities/users';
import {getUserIdFromChannelName, showDeleteOption} from 'mattermost-redux/utils/channel_utils';
import {isAdmin, isChannelAdmin, isSystemAdmin} from 'mattermost-redux/utils/user_utils';
import ChannelInfo from './channel_info';
function mapStateToProps(state, ownProps) {
const {config, license} = state.entities.general;
const currentChannel = getCurrentChannel(state);
const currentChannelCreator = getUser(state, currentChannel.creator_id);
const currentChannelCreatorName = currentChannelCreator && currentChannelCreator.username;
const currentChannelMemberCount = getCurrentChannelStats(state) && getCurrentChannelStats(state).member_count;
const currentUserId = getCurrentUserId(state);
const favoriteChannels = getChannelsByCategory(state).favoriteChannels.map((f) => f.id);
const isCurrent = currentChannel.id === state.entities.channels.currentChannelId;
const isFavorite = favoriteChannels.indexOf(currentChannel.id) > -1;
const leaveChannelRequest = state.requests.channels.leaveChannel;
const roles = getCurrentUserRoles(state);
let status;
if (currentChannel.type === Constants.DM_CHANNEL) {
const teammateId = getUserIdFromChannelName(currentUserId, currentChannel.name);
status = getStatusForUserId(state, teammateId);
}
return {
...ownProps,
canDeleteChannel: showDeleteOption(config, license, currentChannel, isAdmin(roles), isSystemAdmin(roles), isChannelAdmin(roles)),
currentTeamId: state.entities.teams.currentTeamId,
currentChannel,
currentChannelCreatorName,
currentChannelMemberCount,
isCurrent,
isFavorite,
leaveChannelRequest,
status,
theme: getTheme(state),
canManageUsers: canManageChannelMembers(state)
};
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators({
closeDMChannel,
closeGMChannel,
deleteChannel,
getChannelStats,
goBack,
goToChannelAddMembers,
goToChannelMembers,
leaveChannel,
markFavorite,
unmarkFavorite
}, dispatch)
};
}
export default navigationSceneConnect(mapStateToProps, mapDispatchToProps)(ChannelInfo);

View file

@ -1,48 +0,0 @@
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import {bindActionCreators} from 'redux';
import navigationSceneConnect from '../navigationSceneConnect';
import {goBack} from 'app/actions/navigation';
import {handleRemoveChannelMembers} from 'app/actions/views/channel_members';
import {getTheme} from 'app/selectors/preferences';
import {getCurrentChannel, getCurrentChannelStats, canManageChannelMembers} from 'mattermost-redux/selectors/entities/channels';
import {getMyPreferences} from 'mattermost-redux/selectors/entities/preferences';
import {getCurrentTeam} from 'mattermost-redux/selectors/entities/teams';
import {getProfilesInCurrentChannel} from 'mattermost-redux/selectors/entities/users';
import {getProfilesInChannel, searchProfiles} from 'mattermost-redux/actions/users';
import ChannelMembers from './channel_members';
function mapStateToProps(state) {
const currentChannelMemberCount = getCurrentChannelStats(state) && getCurrentChannelStats(state).member_count;
return {
theme: getTheme(state),
currentChannel: getCurrentChannel(state),
currentChannelMembers: getProfilesInCurrentChannel(state),
currentChannelMemberCount,
currentUserId: state.entities.users.currentUserId,
currentTeam: getCurrentTeam(state),
preferences: getMyPreferences(state),
requestStatus: state.requests.users.getProfilesInChannel.status,
searchRequestStatus: state.requests.users.searchProfiles.status,
removeMembersStatus: state.requests.channels.removeChannelMember.status,
canManageUsers: canManageChannelMembers(state)
};
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators({
getProfilesInChannel,
goBack,
handleRemoveChannelMembers,
searchProfiles
}, dispatch)
};
}
export default navigationSceneConnect(mapStateToProps, mapDispatchToProps)(ChannelMembers);

View file

@ -1,6 +1,48 @@
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import ChannelMembersContainer from './channel_members_container';
import {bindActionCreators} from 'redux';
export default ChannelMembersContainer;
import navigationSceneConnect from '../navigationSceneConnect';
import {goBack} from 'app/actions/navigation';
import {handleRemoveChannelMembers} from 'app/actions/views/channel_members';
import {getTheme} from 'app/selectors/preferences';
import {getCurrentChannel, getCurrentChannelStats, canManageChannelMembers} from 'mattermost-redux/selectors/entities/channels';
import {getMyPreferences} from 'mattermost-redux/selectors/entities/preferences';
import {getCurrentTeam} from 'mattermost-redux/selectors/entities/teams';
import {getProfilesInCurrentChannel} from 'mattermost-redux/selectors/entities/users';
import {getProfilesInChannel, searchProfiles} from 'mattermost-redux/actions/users';
import ChannelMembers from './channel_members';
function mapStateToProps(state) {
const currentChannelMemberCount = getCurrentChannelStats(state) && getCurrentChannelStats(state).member_count;
return {
theme: getTheme(state),
currentChannel: getCurrentChannel(state),
currentChannelMembers: getProfilesInCurrentChannel(state),
currentChannelMemberCount,
currentUserId: state.entities.users.currentUserId,
currentTeam: getCurrentTeam(state),
preferences: getMyPreferences(state),
requestStatus: state.requests.users.getProfilesInChannel.status,
searchRequestStatus: state.requests.users.searchProfiles.status,
removeMembersStatus: state.requests.channels.removeChannelMember.status,
canManageUsers: canManageChannelMembers(state)
};
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators({
getProfilesInChannel,
goBack,
handleRemoveChannelMembers,
searchProfiles
}, dispatch)
};
}
export default navigationSceneConnect(mapStateToProps, mapDispatchToProps)(ChannelMembers);

View file

@ -13,17 +13,17 @@ import CreateChannel from './create_channel';
import EditPost from './edit_post';
import ImagePreview from './image_preview';
import LoadTeam from './load_team';
import Login from './login/login_container.js';
import Login from './login';
import LoginOptions from './login_options';
import Mfa from './mfa';
import MoreChannels from './more_channels';
import MoreDirectMessages from './more_dms';
import OptionsModal from './options_modal';
import Settings from './settings';
import Root from './root/root_container.js';
import Search from './search/search_container.js';
import SelectServer from './select_server/select_server_container.js';
import SelectTeam from './select_team/select_team_container.js';
import Root from './root';
import Search from './search';
import SelectServer from './select_server';
import SelectTeam from './select_team';
import Thread from './thread';
import UserProfile from './user_profile';
import Saml from './saml';

View file

@ -1,6 +1,40 @@
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import LoadTeamContainer from './load_team_container';
import {bindActionCreators} from 'redux';
export default LoadTeamContainer;
import {getCurrentTeam} from 'mattermost-redux/selectors/entities/teams';
import {goToChannelView} from 'app/actions/views/load_team';
import {clearNotification, goToNotification} from 'app/actions/views/root';
import {handleTeamChange} from 'app/actions/views/select_team';
import {getTheme} from 'app/selectors/preferences';
import navigationSceneConnect from '../navigationSceneConnect';
import LoadTeam from './load_team';
function mapStateToProps(state) {
return {
config: state.entities.general.config,
theme: getTheme(state),
teamsRequest: state.requests.teams.allTeams,
teams: state.entities.teams.teams,
currentTeam: getCurrentTeam(state),
myMembers: state.entities.teams.myMembers,
notification: state.views.notification
};
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators({
clearNotification,
goToChannelView,
goToNotification,
handleTeamChange
}, dispatch)
};
}
export default navigationSceneConnect(mapStateToProps, mapDispatchToProps)(LoadTeam);

View file

@ -27,7 +27,7 @@ export default class LoadTeam extends PureComponent {
static navigationProps = {
renderBackButton: () => null,
renderTitleComponent: () => null
}
};
componentDidMount() {
const {notification, currentTeam, myMembers, teams} = this.props;
@ -60,7 +60,8 @@ export default class LoadTeam extends PureComponent {
}
onSelectTeam(team) {
this.props.actions.handleTeamChange(team).then(this.props.actions.goToChannelView);
const {handleTeamChange, goToChannelView} = this.props.actions;
handleTeamChange(team).then(goToChannelView);
}
render() {

View file

@ -1,40 +0,0 @@
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import {bindActionCreators} from 'redux';
import {getCurrentTeam} from 'mattermost-redux/selectors/entities/teams';
import {goToChannelView} from 'app/actions/views/load_team';
import {clearNotification, goToNotification} from 'app/actions/views/root';
import {handleTeamChange} from 'app/actions/views/select_team';
import {getTheme} from 'app/selectors/preferences';
import navigationSceneConnect from '../navigationSceneConnect';
import LoadTeam from './load_team.js';
function mapStateToProps(state) {
return {
config: state.entities.general.config,
theme: getTheme(state),
teamsRequest: state.requests.teams.allTeams,
teams: state.entities.teams.teams,
currentTeam: getCurrentTeam(state),
myMembers: state.entities.teams.myMembers,
notification: state.views.notification
};
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators({
clearNotification,
goToChannelView,
goToNotification,
handleTeamChange
}, dispatch)
};
}
export default navigationSceneConnect(mapStateToProps, mapDispatchToProps)(LoadTeam);

View file

@ -1,6 +1,32 @@
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import MfaContainer from './mfa_container';
import {bindActionCreators} from 'redux';
export default MfaContainer;
import navigationSceneConnect from '../navigationSceneConnect';
import {goBack} from 'app/actions/navigation';
import {login} from 'mattermost-redux/actions/users';
import Mfa from './mfa';
function mapStateToProps(state) {
const {login: loginRequest} = state.requests.users;
const {loginId, password} = state.views.login;
return {
loginId,
password,
loginRequest
};
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators({
goBack,
login
}, dispatch)
};
}
export default navigationSceneConnect(mapStateToProps, mapDispatchToProps)(Mfa);

View file

@ -1,32 +0,0 @@
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import {bindActionCreators} from 'redux';
import navigationSceneConnect from '../navigationSceneConnect';
import {goBack} from 'app/actions/navigation';
import {login} from 'mattermost-redux/actions/users';
import Mfa from './mfa';
function mapStateToProps(state) {
const {login: loginRequest} = state.requests.users;
const {loginId, password} = state.views.login;
return {
loginId,
password,
loginRequest
};
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators({
goBack,
login
}, dispatch)
};
}
export default navigationSceneConnect(mapStateToProps, mapDispatchToProps)(Mfa);

View file

@ -9,7 +9,7 @@ import {goToSelectServer} from 'app/actions/views/root';
import {handleServerUrlChanged} from 'app/actions/views/select_server';
import {goToLoadTeam} from 'app/actions/navigation';
import {setStoreFromLocalData} from 'mattermost-redux/actions/general';
import {loadMe} from 'mattermost-redux/actions/users';
import Root from './root';
@ -29,7 +29,7 @@ function mapDispatchToProps(dispatch) {
goToLoadTeam,
goToSelectServer,
handleServerUrlChanged,
setStoreFromLocalData
loadMe
}, dispatch)
};
}

View file

@ -5,6 +5,7 @@ import React, {PropTypes, PureComponent} from 'react';
import Orientation from 'react-native-orientation';
import Loading from 'app/components/loading';
import Client from 'mattermost-redux/client';
import {RequestStatus} from 'mattermost-redux/constants';
import SplashScreen from 'react-native-smart-splash-screen';
@ -17,9 +18,8 @@ export default class Root extends PureComponent {
goToLoadTeam: PropTypes.func,
goToSelectServer: PropTypes.func,
handleServerUrlChanged: PropTypes.func.isRequired,
setStoreFromLocalData: PropTypes.func
}).isRequired,
hydrationComplete: PropTypes.bool.isRequired
loadMe: PropTypes.func
}).isRequired
};
static navigationProps = {
@ -53,18 +53,22 @@ export default class Root extends PureComponent {
};
loadStoreAndScene = (credentials = {}) => {
const {actions, loginRequest} = this.props;
const {goToLoadTeam, goToSelectServer, loadMe} = actions;
if (credentials.token && credentials.url) {
// Will probably need to make this optimistic since we
// assume that the stored token is good.
this.props.actions.setStoreFromLocalData(credentials);
this.props.actions.goToLoadTeam();
} else {
this.selectServer();
}
};
if (loginRequest.status === RequestStatus.NOT_STARTED) {
Client.setToken(credentials.token);
Client.setUrl(credentials.url);
selectServer = async () => {
this.props.actions.goToSelectServer();
loadMe().then(goToLoadTeam).catch(goToLoadTeam);
} else {
goToLoadTeam();
}
} else {
goToSelectServer();
}
};
render() {

View file

@ -1,6 +1,56 @@
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import ThreadContainer from './thread_container';
import {bindActionCreators} from 'redux';
export default ThreadContainer;
import {handleCommentDraftChanged} from 'app/actions/views/thread';
import {selectPost} from 'mattermost-redux/actions/posts';
import {makeGetPostsForThread} from 'mattermost-redux/selectors/entities/posts';
import {getTheme} from 'app/selectors/preferences';
import {getCurrentChannelMembership} from 'mattermost-redux/selectors/entities/channels';
import {getCurrentTeamId} from 'mattermost-redux/selectors/entities/teams';
import navigationSceneConnect from '../navigationSceneConnect';
import Thread from './thread';
function makeMapStateToProps() {
// Create a getPostsForThread selector for each instance of Thread so that each Thread
// is memoized correctly based on its own props
const getPostsForThread = makeGetPostsForThread();
return function mapStateToProps(state, ownProps) {
const posts = getPostsForThread(state, ownProps);
let teamId = state.entities.channels.channels[ownProps.channelId].team_id;
if (!teamId) {
// We can't make a post without a team id, so get it from the current team
teamId = getCurrentTeamId(state);
}
const threadDraft = state.views.thread.drafts[ownProps.rootId];
return {
...ownProps,
teamId,
channelId: ownProps.channelId,
myMember: getCurrentChannelMembership(state),
rootId: ownProps.rootId,
draft: threadDraft.draft,
files: threadDraft.files,
posts,
theme: getTheme(state)
};
};
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators({
handleCommentDraftChanged,
selectPost
}, dispatch)
};
}
export default navigationSceneConnect(makeMapStateToProps, mapDispatchToProps)(Thread);

View file

@ -1,56 +0,0 @@
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import {bindActionCreators} from 'redux';
import {handleCommentDraftChanged} from 'app/actions/views/thread';
import {selectPost} from 'mattermost-redux/actions/posts';
import {makeGetPostsForThread} from 'mattermost-redux/selectors/entities/posts';
import {getTheme} from 'app/selectors/preferences';
import {getCurrentChannelMembership} from 'mattermost-redux/selectors/entities/channels';
import {getCurrentTeamId} from 'mattermost-redux/selectors/entities/teams';
import navigationSceneConnect from '../navigationSceneConnect';
import Thread from './thread';
function makeMapStateToProps() {
// Create a getPostsForThread selector for each instance of Thread so that each Thread
// is memoized correctly based on its own props
const getPostsForThread = makeGetPostsForThread();
return function mapStateToProps(state, ownProps) {
const posts = getPostsForThread(state, ownProps);
let teamId = state.entities.channels.channels[ownProps.channelId].team_id;
if (!teamId) {
// We can't make a post without a team id, so get it from the current team
teamId = getCurrentTeamId(state);
}
const threadDraft = state.views.thread.drafts[ownProps.rootId];
return {
...ownProps,
teamId,
channelId: ownProps.channelId,
myMember: getCurrentChannelMembership(state),
rootId: ownProps.rootId,
draft: threadDraft.draft,
files: threadDraft.files,
posts,
theme: getTheme(state)
};
};
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators({
handleCommentDraftChanged,
selectPost
}, dispatch)
};
}
export default navigationSceneConnect(makeMapStateToProps, mapDispatchToProps)(Thread);

View file

@ -1,6 +1,33 @@
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import UserProfileContainer from './user_profile_container';
import {bindActionCreators} from 'redux';
export default UserProfileContainer;
import {handleSendMessage} from 'app/actions/views/user_profile';
import navigationSceneConnect from 'app/scenes/navigationSceneConnect';
import {getTheme} from 'app/selectors/preferences';
import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users';
import UserProfile from './user_profile';
function mapStateToProps(state, ownProps) {
const {config} = state.entities.general;
return {
config,
currentUserId: getCurrentUserId(state),
user: state.entities.users.profiles[ownProps.userId],
theme: getTheme(state)
};
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators({
handleSendMessage
}, dispatch)
};
}
export default navigationSceneConnect(mapStateToProps, mapDispatchToProps)(UserProfile);

View file

@ -1,33 +0,0 @@
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import {bindActionCreators} from 'redux';
import {handleSendMessage} from 'app/actions/views/user_profile';
import navigationSceneConnect from 'app/scenes/navigationSceneConnect';
import {getTheme} from 'app/selectors/preferences';
import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users';
import UserProfile from './user_profile';
function mapStateToProps(state, ownProps) {
const {config} = state.entities.general;
return {
config,
currentUserId: getCurrentUserId(state),
user: state.entities.users.profiles[ownProps.userId],
theme: getTheme(state)
};
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators({
handleSendMessage
}, dispatch)
};
}
export default navigationSceneConnect(mapStateToProps, mapDispatchToProps)(UserProfile);