PLT-6208 Follow policies set in System Console (#456)
This commit is contained in:
parent
70449a4768
commit
007c8bcf35
16 changed files with 235 additions and 145 deletions
|
|
@ -9,7 +9,7 @@ import com.learnium.RNDeviceInfo.RNDeviceInfo;
|
|||
import com.psykar.cookiemanager.CookieManagerPackage;
|
||||
import com.dieam.reactnativepushnotification.ReactNativePushNotificationPackage;
|
||||
import com.oblador.vectoricons.VectorIconsPackage;
|
||||
import com.horcrux.svg.RNSvgPackage;
|
||||
import com.horcrux.svg.SvgPackage;
|
||||
import com.facebook.react.ReactInstanceManager;
|
||||
import com.facebook.react.ReactNativeHost;
|
||||
import com.facebook.react.ReactPackage;
|
||||
|
|
@ -41,7 +41,7 @@ public class MainApplication extends Application implements ReactApplication {
|
|||
new CookieManagerPackage(),
|
||||
new ReactNativePushNotificationPackage(),
|
||||
new VectorIconsPackage(),
|
||||
new RNSvgPackage(),
|
||||
new SvgPackage(),
|
||||
new LinearGradientPackage(),
|
||||
new PickerPackage(),
|
||||
new OrientationPackage()
|
||||
|
|
|
|||
|
|
@ -281,7 +281,6 @@ export function showOptionsModal(options) {
|
|||
|
||||
export function showMoreChannelsModal() {
|
||||
return async (dispatch, getState) => {
|
||||
closeDrawers()(dispatch, getState);
|
||||
dispatch({
|
||||
type: NavigationTypes.NAVIGATION_MODAL,
|
||||
route: Routes.MoreChannels
|
||||
|
|
@ -291,7 +290,6 @@ export function showMoreChannelsModal() {
|
|||
|
||||
export function showDirectMessagesModal() {
|
||||
return async (dispatch, getState) => {
|
||||
closeDrawers()(dispatch, getState);
|
||||
dispatch({
|
||||
type: NavigationTypes.NAVIGATION_MODAL,
|
||||
route: Routes.MoreDirectMessages
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ class ChannelDrawerList extends Component {
|
|||
showDirectMessagesModal: PropTypes.func.isRequired,
|
||||
showMoreChannelsModal: PropTypes.func.isRequired
|
||||
}).isRequired,
|
||||
canCreatePrivateChannels: PropTypes.bool.isRequired,
|
||||
channels: PropTypes.object.isRequired,
|
||||
channelMembers: PropTypes.object,
|
||||
currentTeam: PropTypes.object.isRequired,
|
||||
|
|
@ -186,7 +187,7 @@ class ChannelDrawerList extends Component {
|
|||
return data;
|
||||
}
|
||||
|
||||
const {theme} = this.props;
|
||||
const {canCreatePrivateChannels, theme} = this.props;
|
||||
const styles = getStyleSheet(theme);
|
||||
|
||||
const {
|
||||
|
|
@ -208,8 +209,12 @@ class ChannelDrawerList extends Component {
|
|||
...publicChannels
|
||||
);
|
||||
|
||||
let createPrivateChannel;
|
||||
if (canCreatePrivateChannels) {
|
||||
createPrivateChannel = this.createPrivateChannel;
|
||||
}
|
||||
data.push(
|
||||
this.renderTitle(styles, 'sidebar.pg', 'PRIVATE CHANNELS', this.createPrivateChannel, privateChannels.length > 0),
|
||||
this.renderTitle(styles, 'sidebar.pg', 'PRIVATE CHANNELS', createPrivateChannel, privateChannels.length > 0),
|
||||
...privateChannels
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -20,10 +20,19 @@ import {
|
|||
unmarkFavorite
|
||||
} from 'app/actions/views/channel';
|
||||
|
||||
import {Constants} from 'mattermost-redux/constants';
|
||||
import {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 = getCurrentUserRoles(state);
|
||||
|
||||
return {
|
||||
canCreatePrivateChannels: showCreateOption(config, license, Constants.PRIVATE_CHANNEL, isAdmin(roles), isSystemAdmin(roles)),
|
||||
...ownProps
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,8 @@ export default class CustomList extends PureComponent {
|
|||
selectable: PropTypes.bool,
|
||||
onRowSelect: PropTypes.func,
|
||||
renderRow: PropTypes.func.isRequired,
|
||||
createSections: PropTypes.func
|
||||
createSections: PropTypes.func,
|
||||
showNoResults: PropTypes.bool
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
|
|
@ -37,7 +38,8 @@ export default class CustomList extends PureComponent {
|
|||
loadingText: null,
|
||||
onRowSelect: () => true,
|
||||
createSections: () => true,
|
||||
showSections: true
|
||||
showSections: true,
|
||||
showNoResults: true
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
|
|
@ -48,7 +50,6 @@ export default class CustomList extends PureComponent {
|
|||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
const {data, showSections, searching} = nextProps;
|
||||
this.showNoResults = true;
|
||||
|
||||
if (searching || searching !== this.props.searching) {
|
||||
this.setState(this.buildDataSource(nextProps));
|
||||
|
|
@ -161,7 +162,7 @@ export default class CustomList extends PureComponent {
|
|||
noResults = this.props.data.length === 0;
|
||||
}
|
||||
|
||||
if (this.showNoResults && !this.props.loading && noResults) {
|
||||
if (this.props.showNoResults && !this.props.loading && noResults) {
|
||||
return (
|
||||
<View style={style.noResultContainer}>
|
||||
<FormattedText
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import React, {PropTypes, PureComponent} from 'react';
|
||||
|
|
@ -13,9 +13,6 @@ import {
|
|||
View
|
||||
} from 'react-native';
|
||||
import {injectIntl, intlShape} from 'react-intl';
|
||||
import {Constants} from 'mattermost-redux/constants';
|
||||
import {isSystemMessage} from 'mattermost-redux/utils/post_utils';
|
||||
import {isAdmin} from 'mattermost-redux/utils/user_utils';
|
||||
|
||||
import FormattedText from 'app/components/formatted_text';
|
||||
import FormattedTime from 'app/components/formatted_time';
|
||||
|
|
@ -29,6 +26,11 @@ import ReplyIcon from 'app/components/reply_icon';
|
|||
|
||||
import webhookIcon from 'assets/images/icons/webhook.jpg';
|
||||
|
||||
import {Constants} from 'mattermost-redux/constants';
|
||||
import DelayedAction from 'mattermost-redux/utils/delayed_action';
|
||||
import {canDeletePost, canEditPost, isSystemMessage} from 'mattermost-redux/utils/post_utils';
|
||||
import {isAdmin, isSystemAdmin} from 'mattermost-redux/utils/user_utils';
|
||||
|
||||
const BOT_NAME = 'BOT';
|
||||
|
||||
class Post extends PureComponent {
|
||||
|
|
@ -48,6 +50,7 @@ class Post extends PureComponent {
|
|||
isLastReply: PropTypes.bool,
|
||||
commentedOnDisplayName: PropTypes.string,
|
||||
commentedOnPost: PropTypes.object,
|
||||
license: PropTypes.object.isRequired,
|
||||
roles: PropTypes.string,
|
||||
theme: PropTypes.object.isRequired,
|
||||
onPress: PropTypes.func,
|
||||
|
|
@ -60,6 +63,33 @@ class Post extends PureComponent {
|
|||
}).isRequired
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
const {config, license, currentUserId, roles, post} = props;
|
||||
this.editDisableAction = new DelayedAction(this.handleEditDisable);
|
||||
this.state = {
|
||||
canEdit: canEditPost(config, license, currentUserId, post, this.editDisableAction),
|
||||
canDelete: canDeletePost(config, license, currentUserId, post, isAdmin(roles), isSystemAdmin(roles))
|
||||
};
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
const {config, license, currentUserId, roles, post} = nextProps;
|
||||
this.setState({
|
||||
canEdit: canEditPost(config, license, currentUserId, post, this.editDisableAction),
|
||||
canDelete: canDeletePost(config, license, currentUserId, post, isAdmin(roles), isSystemAdmin(roles))
|
||||
});
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.editDisableAction.cancel();
|
||||
}
|
||||
|
||||
handleEditDisable = () => {
|
||||
this.setState({canEdit: false});
|
||||
};
|
||||
|
||||
handlePostDelete = () => {
|
||||
const {formatMessage} = this.props.intl;
|
||||
const {currentTeamId, post, actions} = this.props;
|
||||
|
|
@ -74,6 +104,7 @@ class Post extends PureComponent {
|
|||
text: formatMessage({id: 'post_info.del', defaultMessage: 'Delete'}),
|
||||
style: 'destructive',
|
||||
onPress: () => {
|
||||
this.editDisableAction.cancel();
|
||||
actions.deletePost(currentTeamId, post);
|
||||
}
|
||||
}]
|
||||
|
|
@ -183,7 +214,7 @@ class Post extends PureComponent {
|
|||
|
||||
renderMessage = (style, messageStyle, replyBar = false) => {
|
||||
const {formatMessage} = this.props.intl;
|
||||
const {currentUserId, isFlagged, post, roles, theme} = this.props;
|
||||
const {isFlagged, post, theme} = this.props;
|
||||
const {flagPost, unflagPost} = this.props.actions;
|
||||
const actions = [];
|
||||
|
||||
|
|
@ -200,11 +231,11 @@ class Post extends PureComponent {
|
|||
});
|
||||
}
|
||||
|
||||
if (post.user_id === currentUserId) {
|
||||
if (this.state.canEdit) {
|
||||
actions.push({text: formatMessage({id: 'post_info.edit', defaultMessage: 'Edit'}), onPress: () => this.handlePostEdit()});
|
||||
}
|
||||
|
||||
if (post.user_id === currentUserId || isAdmin(roles)) {
|
||||
if (this.state.canDelete && post.state !== Constants.POST_DELETED) {
|
||||
actions.push({text: formatMessage({id: 'post_info.del', defaultMessage: 'Delete'}), onPress: () => this.handlePostDelete()});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,16 +22,18 @@ function makeMapStateToProps() {
|
|||
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;
|
||||
|
||||
return {
|
||||
...ownProps,
|
||||
config: state.entities.general.config,
|
||||
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: getCurrentUserRoles(state),
|
||||
theme: getTheme(state),
|
||||
user
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import ChannelInfoRow from './channel_info_row';
|
|||
class ChannelInfo extends PureComponent {
|
||||
static propTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
canDeleteChannel: PropTypes.bool.isRequired,
|
||||
currentTeamId: PropTypes.string.isRequired,
|
||||
currentChannel: PropTypes.object.isRequired,
|
||||
currentChannelCreatorName: PropTypes.string,
|
||||
|
|
@ -152,6 +153,7 @@ class ChannelInfo extends PureComponent {
|
|||
|
||||
render() {
|
||||
const {
|
||||
canDeleteChannel,
|
||||
currentChannel,
|
||||
currentChannelCreatorName,
|
||||
currentChannelMemberCount,
|
||||
|
|
@ -245,7 +247,7 @@ class ChannelInfo extends PureComponent {
|
|||
theme={theme}
|
||||
/>
|
||||
</View>
|
||||
{this.renderLeaveOrDeleteChannelRow() &&
|
||||
{this.renderLeaveOrDeleteChannelRow() && canDeleteChannel &&
|
||||
<View style={style.footer}>
|
||||
<ChannelInfoRow
|
||||
action={() => this.handleDeleteOrLeave('delete')}
|
||||
|
|
|
|||
|
|
@ -22,12 +22,14 @@ import {
|
|||
getChannelsByCategory,
|
||||
canManageChannelMembers
|
||||
} from 'mattermost-redux/selectors/entities/channels';
|
||||
import {getCurrentUserId, getUser, getStatusForUserId} from 'mattermost-redux/selectors/entities/users';
|
||||
import {getUserIdFromChannelName} from 'mattermost-redux/utils/channel_utils';
|
||||
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;
|
||||
|
|
@ -37,6 +39,7 @@ function mapStateToProps(state, ownProps) {
|
|||
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) {
|
||||
|
|
@ -46,6 +49,7 @@ function mapStateToProps(state, ownProps) {
|
|||
|
||||
return {
|
||||
...ownProps,
|
||||
canDeleteChannel: showDeleteOption(config, license, currentChannel, isAdmin(roles), isSystemAdmin(roles), isChannelAdmin(roles)),
|
||||
currentTeamId: state.entities.teams.currentTeamId,
|
||||
currentChannel,
|
||||
currentChannelCreatorName,
|
||||
|
|
|
|||
|
|
@ -9,10 +9,18 @@ import {
|
|||
} from 'react-native';
|
||||
|
||||
import FormattedText from 'app/components/formatted_text';
|
||||
|
||||
import {getTheme} from 'app/selectors/preferences';
|
||||
|
||||
import {Constants} from 'mattermost-redux/constants';
|
||||
import {getCurrentUserRoles} from 'mattermost-redux/selectors/entities/users';
|
||||
import {showCreateOption} from 'mattermost-redux/utils/channel_utils';
|
||||
import {isAdmin, isSystemAdmin} from 'mattermost-redux/utils/user_utils';
|
||||
|
||||
function CreateButton(props) {
|
||||
if (!props.canCreateChannels) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={{flexDirection: 'column', justifyContent: 'center', alignItems: 'center', flex: 1}}>
|
||||
<TouchableOpacity
|
||||
|
|
@ -30,6 +38,7 @@ function CreateButton(props) {
|
|||
}
|
||||
|
||||
CreateButton.propTypes = {
|
||||
canCreateChannels: PropTypes.bool.isRequired,
|
||||
emitter: PropTypes.func.isRequired,
|
||||
theme: PropTypes.object
|
||||
};
|
||||
|
|
@ -39,7 +48,11 @@ CreateButton.defaultProps = {
|
|||
};
|
||||
|
||||
function mapStateToProps(state) {
|
||||
const {config, license} = state.entities.general;
|
||||
const roles = getCurrentUserRoles(state);
|
||||
|
||||
return {
|
||||
canCreateChannels: showCreateOption(config, license, Constants.PRIVATE_CHANNEL, isAdmin(roles), isSystemAdmin(roles)),
|
||||
theme: getTheme(state)
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import {bindActionCreators} from 'redux';
|
|||
|
||||
import navigationSceneConnect from '../navigationSceneConnect';
|
||||
|
||||
import {goBack, goToCreateChannel} from 'app/actions/navigation';
|
||||
import {closeDrawers, goBack, goToCreateChannel} from 'app/actions/navigation';
|
||||
import {getTheme} from 'app/selectors/preferences';
|
||||
import {getMoreChannels as getMoreChannelsSelector} from 'mattermost-redux/selectors/entities/channels';
|
||||
import {handleSelectChannel} from 'app/actions/views/channel';
|
||||
|
|
@ -17,11 +17,12 @@ function mapStateToProps(state) {
|
|||
const {currentUserId} = state.entities.users;
|
||||
const {currentTeamId} = state.entities.teams;
|
||||
const {getMoreChannels: requestStatus} = state.requests.channels;
|
||||
const channels = getMoreChannelsSelector(state);
|
||||
|
||||
return {
|
||||
currentUserId,
|
||||
currentTeamId,
|
||||
channels: getMoreChannelsSelector(state),
|
||||
channels,
|
||||
theme: getTheme(state),
|
||||
requestStatus
|
||||
};
|
||||
|
|
@ -30,6 +31,7 @@ function mapStateToProps(state) {
|
|||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
actions: bindActionCreators({
|
||||
closeDrawers,
|
||||
goBack,
|
||||
handleSelectChannel,
|
||||
goToCreateChannel,
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ class MoreChannels extends PureComponent {
|
|||
subscribeToHeaderEvent: React.PropTypes.func.isRequired,
|
||||
unsubscribeFromHeaderEvent: React.PropTypes.func.isRequired,
|
||||
actions: PropTypes.shape({
|
||||
closeDrawers: PropTypes.func.isRequired,
|
||||
goBack: PropTypes.func.isRequired,
|
||||
handleSelectChannel: PropTypes.func.isRequired,
|
||||
goToCreateChannel: PropTypes.func.isRequired,
|
||||
|
|
@ -69,11 +70,12 @@ class MoreChannels extends PureComponent {
|
|||
this.searchTimeoutId = 0;
|
||||
|
||||
this.state = {
|
||||
channels: [],
|
||||
channels: props.channels,
|
||||
page: 0,
|
||||
adding: false,
|
||||
next: true,
|
||||
searching: false
|
||||
searching: false,
|
||||
showNoResults: false
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -87,12 +89,12 @@ class MoreChannels extends PureComponent {
|
|||
if (this.state.searching &&
|
||||
nextProps.requestStatus.status === RequestStatus.SUCCESS) {
|
||||
const channels = this.filterChannels(nextProps.channels, this.state.term);
|
||||
this.setState({channels});
|
||||
this.setState({channels, showNoResults: true});
|
||||
} else if (requestStatus.status === RequestStatus.STARTED &&
|
||||
nextProps.requestStatus.status === RequestStatus.SUCCESS) {
|
||||
const {page} = this.state;
|
||||
const channels = nextProps.channels.splice(0, (page + 1) * Constants.CHANNELS_CHUNK_SIZE);
|
||||
this.setState({channels});
|
||||
this.setState({channels, showNoResults: true});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -101,9 +103,11 @@ class MoreChannels extends PureComponent {
|
|||
Keyboard.addListener('keyboardDidHide', this.handleAndroidKeyboard);
|
||||
}
|
||||
|
||||
InteractionManager.runAfterInteractions(() => {
|
||||
// set the timeout to 400 cause is the time that the modal takes to open
|
||||
// Somehow interactionManager doesn't care
|
||||
setTimeout(() => {
|
||||
this.props.actions.getMoreChannels(this.props.currentTeamId, 0);
|
||||
});
|
||||
}, 400);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
|
|
@ -208,6 +212,7 @@ class MoreChannels extends PureComponent {
|
|||
id);
|
||||
await this.props.actions.handleSelectChannel(id);
|
||||
|
||||
this.props.actions.closeDrawers();
|
||||
InteractionManager.runAfterInteractions(() => {
|
||||
this.props.actions.goBack();
|
||||
});
|
||||
|
|
@ -218,13 +223,15 @@ class MoreChannels extends PureComponent {
|
|||
};
|
||||
|
||||
render() {
|
||||
const {formatMessage} = this.props.intl;
|
||||
const isLoading = this.props.requestStatus.status === RequestStatus.STARTED;
|
||||
const style = getStyleFromTheme(this.props.theme);
|
||||
const more = this.state.searching ? () => true : this.loadMoreChannels;
|
||||
const {intl, requestStatus, theme} = this.props;
|
||||
const {adding, channels, searching} = this.state;
|
||||
const {formatMessage} = intl;
|
||||
const isLoading = requestStatus.status === RequestStatus.STARTED || requestStatus.status === RequestStatus.NOT_STARTED;
|
||||
const style = getStyleFromTheme(theme);
|
||||
const more = searching ? () => true : this.loadMoreChannels;
|
||||
|
||||
let content;
|
||||
if (this.state.adding) {
|
||||
if (adding) {
|
||||
content = (
|
||||
<View style={style.container}>
|
||||
<Loading/>
|
||||
|
|
@ -250,9 +257,9 @@ class MoreChannels extends PureComponent {
|
|||
/>
|
||||
</View>
|
||||
<ChannelList
|
||||
data={this.state.channels}
|
||||
theme={this.props.theme}
|
||||
searching={this.state.searching}
|
||||
data={channels}
|
||||
theme={theme}
|
||||
searching={searching}
|
||||
onListEndReached={more}
|
||||
loading={isLoading}
|
||||
selectable={false}
|
||||
|
|
@ -261,6 +268,7 @@ class MoreChannels extends PureComponent {
|
|||
renderRow={this.renderChannelRow}
|
||||
onRowPress={this.onSelectChannel}
|
||||
loadingText={{id: 'mobile.loading_channels', defaultMessage: 'Loading Channels...'}}
|
||||
showNoResults={this.state.showNoResults}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import {bindActionCreators} from 'redux';
|
|||
|
||||
import navigationSceneConnect from '../navigationSceneConnect';
|
||||
|
||||
import {goBack} from 'app/actions/navigation';
|
||||
import {closeDrawers, goBack} from 'app/actions/navigation';
|
||||
import {makeDirectChannel} from 'app/actions/views/more_dms';
|
||||
import {getTheme} from 'app/selectors/preferences';
|
||||
import {getProfiles, searchProfiles} from 'mattermost-redux/actions/users';
|
||||
|
|
@ -41,6 +41,7 @@ function mapStateToProps(state, ownProps) {
|
|||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
actions: bindActionCreators({
|
||||
closeDrawers,
|
||||
goBack,
|
||||
makeDirectChannel,
|
||||
getProfiles,
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ class MoreDirectMessages extends PureComponent {
|
|||
subscribeToHeaderEvent: React.PropTypes.func.isRequired,
|
||||
unsubscribeFromHeaderEvent: React.PropTypes.func.isRequired,
|
||||
actions: PropTypes.shape({
|
||||
closeDrawers: PropTypes.func.isRequired,
|
||||
goBack: PropTypes.func.isRequired,
|
||||
makeDirectChannel: PropTypes.func.isRequired,
|
||||
getProfiles: PropTypes.func.isRequired,
|
||||
|
|
@ -61,11 +62,12 @@ class MoreDirectMessages extends PureComponent {
|
|||
this.searchTimeoutId = 0;
|
||||
|
||||
this.state = {
|
||||
profiles: [],
|
||||
profiles: props.profiles,
|
||||
page: 0,
|
||||
adding: false,
|
||||
next: true,
|
||||
searching: false
|
||||
searching: false,
|
||||
showNoResults: false
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -79,7 +81,7 @@ class MoreDirectMessages extends PureComponent {
|
|||
nextProps.requestStatus.status === RequestStatus.SUCCESS) {
|
||||
const {page} = this.state;
|
||||
const profiles = nextProps.profiles.splice(0, (page + 1) * Constants.PROFILE_CHUNK_SIZE);
|
||||
this.setState({profiles});
|
||||
this.setState({profiles, showNoResults: true});
|
||||
} else if (this.state.searching &&
|
||||
nextProps.searchRequest.status === RequestStatus.SUCCESS) {
|
||||
const results = nextProps.profiles.filter((p) => {
|
||||
|
|
@ -87,7 +89,7 @@ class MoreDirectMessages extends PureComponent {
|
|||
return p.username.toLowerCase().includes(term) || p.email.toLowerCase().includes(term) ||
|
||||
p.first_name.toLowerCase().includes(term) || p.last_name.toLowerCase().includes(term);
|
||||
});
|
||||
this.setState({profiles: results});
|
||||
this.setState({profiles: results, showNoResults: true});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -96,9 +98,11 @@ class MoreDirectMessages extends PureComponent {
|
|||
Keyboard.addListener('keyboardDidHide', this.handleAndroidKeyboard);
|
||||
}
|
||||
|
||||
InteractionManager.runAfterInteractions(() => {
|
||||
// set the timeout to 400 cause is the time that the modal takes to open
|
||||
// Somehow interactionManager doesn't care
|
||||
setTimeout(() => {
|
||||
this.props.actions.getProfiles(0);
|
||||
});
|
||||
}, 400);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
|
|
@ -166,20 +170,24 @@ class MoreDirectMessages extends PureComponent {
|
|||
this.setState({adding: true});
|
||||
this.searchBar.blur();
|
||||
await this.props.actions.makeDirectChannel(id);
|
||||
|
||||
this.props.actions.closeDrawers();
|
||||
InteractionManager.runAfterInteractions(() => {
|
||||
this.props.actions.goBack();
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
const {formatMessage} = this.props.intl;
|
||||
const isLoading = (this.props.requestStatus.status === RequestStatus.STARTED) ||
|
||||
(this.props.searchRequest.status === RequestStatus.STARTED);
|
||||
const style = getStyleFromTheme(this.props.theme);
|
||||
const {intl, preferences, requestStatus, searchRequest, theme} = this.props;
|
||||
const {adding, profiles, searching, showNoResults} = this.state;
|
||||
const {formatMessage} = intl;
|
||||
const isLoading = (requestStatus.status === RequestStatus.STARTED) || (requestStatus.status === RequestStatus.NOT_STARTED) ||
|
||||
(searchRequest.status === RequestStatus.STARTED);
|
||||
const style = getStyleFromTheme(theme);
|
||||
const more = this.state.searching ? () => true : this.loadMoreProfiles;
|
||||
|
||||
let content;
|
||||
if (this.state.adding) {
|
||||
if (adding) {
|
||||
content = (
|
||||
<View style={style.container}>
|
||||
<Loading/>
|
||||
|
|
@ -205,11 +213,11 @@ class MoreDirectMessages extends PureComponent {
|
|||
/>
|
||||
</View>
|
||||
<MemberList
|
||||
data={this.state.profiles}
|
||||
theme={this.props.theme}
|
||||
searching={this.state.searching}
|
||||
data={profiles}
|
||||
theme={theme}
|
||||
searching={searching}
|
||||
onListEndReached={more}
|
||||
preferences={this.props.preferences}
|
||||
preferences={preferences}
|
||||
loading={isLoading}
|
||||
selectable={false}
|
||||
listScrollRenderAheadDistance={50}
|
||||
|
|
@ -217,6 +225,7 @@ class MoreDirectMessages extends PureComponent {
|
|||
renderRow={renderMemberRow}
|
||||
onRowPress={this.onSelectMember}
|
||||
loadingText={loadingText}
|
||||
showNoResults={showNoResults}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -15,6 +15,95 @@ import {getFullName} from 'mattermost-redux/utils/user_utils';
|
|||
|
||||
import UserProfileRow from './user_profile_row';
|
||||
|
||||
export default class UserProfile extends PureComponent {
|
||||
static propTypes = {
|
||||
actions: PropTypes.shape({
|
||||
handleSendMessage: PropTypes.func.isRequired
|
||||
}).isRequired,
|
||||
config: PropTypes.object.isRequired,
|
||||
currentUserId: PropTypes.string.isRequired,
|
||||
theme: PropTypes.object.isRequired,
|
||||
user: PropTypes.object.isRequired
|
||||
};
|
||||
|
||||
state = {
|
||||
isFavorite: false
|
||||
};
|
||||
|
||||
getDisplayName = () => {
|
||||
const {theme, user} = this.props;
|
||||
const style = createStyleSheet(theme);
|
||||
|
||||
const displayName = getFullName(user);
|
||||
|
||||
if (displayName) {
|
||||
return <Text style={style.displayName}>{displayName}</Text>;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
buildDisplayBlock = (property) => {
|
||||
const {theme, user} = this.props;
|
||||
const style = createStyleSheet(theme);
|
||||
|
||||
if (user.hasOwnProperty(property) && user[property].length > 0) {
|
||||
return (
|
||||
<View>
|
||||
<Text style={style.header}>{property.toUpperCase()}</Text>
|
||||
<Text style={style.text}>{user[property]}</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
sendMessage = () => {
|
||||
this.props.actions.handleSendMessage(this.props.user.id);
|
||||
};
|
||||
|
||||
render() {
|
||||
const {config, currentUserId, theme, user} = this.props;
|
||||
const style = createStyleSheet(theme);
|
||||
|
||||
return (
|
||||
<View style={style.container}>
|
||||
<ScrollView
|
||||
style={style.scrollView}
|
||||
contentContainerStyle={style.scrollViewContent}
|
||||
>
|
||||
<View style={style.top}>
|
||||
<ProfilePicture
|
||||
user={user}
|
||||
size={150}
|
||||
statusBorderWidth={6}
|
||||
statusSize={40}
|
||||
statusIconSize={18}
|
||||
/>
|
||||
{this.getDisplayName()}
|
||||
<Text style={style.username}>{`@${user.username}`}</Text>
|
||||
</View>
|
||||
<View style={style.content}>
|
||||
{this.buildDisplayBlock('username')}
|
||||
{config.ShowEmailAddress === 'true' && this.buildDisplayBlock('email')}
|
||||
{this.buildDisplayBlock('position')}
|
||||
</View>
|
||||
{currentUserId !== user.id &&
|
||||
<UserProfileRow
|
||||
action={this.sendMessage}
|
||||
defaultMessage='Send Message'
|
||||
icon='paper-plane-o'
|
||||
textId='mobile.routes.user_profile.send_message'
|
||||
theme={theme}
|
||||
/>
|
||||
}
|
||||
</ScrollView>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const createStyleSheet = makeStyleSheetFromTheme((theme) => {
|
||||
return StyleSheet.create({
|
||||
container: {
|
||||
|
|
@ -60,91 +149,3 @@ const createStyleSheet = makeStyleSheetFromTheme((theme) => {
|
|||
}
|
||||
});
|
||||
});
|
||||
|
||||
export default class UserProfile extends PureComponent {
|
||||
static propTypes = {
|
||||
currentUserId: PropTypes.string.isRequired,
|
||||
theme: PropTypes.object.isRequired,
|
||||
user: PropTypes.object.isRequired,
|
||||
actions: PropTypes.shape({
|
||||
handleSendMessage: PropTypes.func.isRequired
|
||||
}).isRequired
|
||||
};
|
||||
|
||||
state = {
|
||||
isFavorite: false
|
||||
}
|
||||
|
||||
getDisplayName = () => {
|
||||
const {theme, user} = this.props;
|
||||
const style = createStyleSheet(theme);
|
||||
|
||||
const displayName = getFullName(user);
|
||||
|
||||
if (displayName) {
|
||||
return <Text style={style.displayName}>{displayName}</Text>;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
buildDisplayBlock = (property) => {
|
||||
const {theme, user} = this.props;
|
||||
const style = createStyleSheet(theme);
|
||||
|
||||
if (user.hasOwnProperty(property) && user[property].length > 0) {
|
||||
return (
|
||||
<View>
|
||||
<Text style={style.header}>{property.toUpperCase()}</Text>
|
||||
<Text style={style.text}>{user[property]}</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
sendMessage = () => {
|
||||
this.props.actions.handleSendMessage(this.props.user.id);
|
||||
}
|
||||
|
||||
render() {
|
||||
const {theme, user} = this.props;
|
||||
const style = createStyleSheet(theme);
|
||||
|
||||
return (
|
||||
<View style={style.container}>
|
||||
<ScrollView
|
||||
style={style.scrollView}
|
||||
contentContainerStyle={style.scrollViewContent}
|
||||
>
|
||||
<View style={style.top}>
|
||||
<ProfilePicture
|
||||
user={user}
|
||||
size={150}
|
||||
statusBorderWidth={6}
|
||||
statusSize={40}
|
||||
statusIconSize={18}
|
||||
/>
|
||||
{this.getDisplayName()}
|
||||
<Text style={style.username}>{`@${user.username}`}</Text>
|
||||
</View>
|
||||
<View style={style.content}>
|
||||
{this.buildDisplayBlock('username')}
|
||||
{this.buildDisplayBlock('email')}
|
||||
{this.buildDisplayBlock('position')}
|
||||
</View>
|
||||
{this.props.currentUserId !== this.props.user.id &&
|
||||
<UserProfileRow
|
||||
action={this.sendMessage}
|
||||
defaultMessage='Send Message'
|
||||
icon='paper-plane-o'
|
||||
textId='mobile.routes.user_profile.send_message'
|
||||
theme={theme}
|
||||
/>
|
||||
}
|
||||
</ScrollView>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,15 +4,19 @@
|
|||
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';
|
||||
|
||||
import navigationSceneConnect from '../navigationSceneConnect';
|
||||
|
||||
function mapStateToProps(state, ownProps) {
|
||||
const {config} = state.entities.general;
|
||||
|
||||
return {
|
||||
currentUserId: state.entities.users.currentUserId,
|
||||
config,
|
||||
currentUserId: getCurrentUserId(state),
|
||||
user: state.entities.users.profiles[ownProps.userId],
|
||||
theme: getTheme(state)
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue