diff --git a/app/components/channel_drawer/channels_list/channel_item/channel_item.js b/app/components/channel_drawer/channels_list/channel_item/channel_item.js
index cf4855aa8..3b2a979b7 100644
--- a/app/components/channel_drawer/channels_list/channel_item/channel_item.js
+++ b/app/components/channel_drawer/channels_list/channel_item/channel_item.js
@@ -31,6 +31,7 @@ export default class ChannelItem extends PureComponent {
mentions: PropTypes.number.isRequired,
navigator: PropTypes.object,
onSelectChannel: PropTypes.func.isRequired,
+ shouldHideChannel: PropTypes.bool,
status: PropTypes.string,
teammateDeletedAt: PropTypes.number,
type: PropTypes.string.isRequired,
@@ -81,12 +82,17 @@ export default class ChannelItem extends PureComponent {
isMyUser,
isUnread,
mentions,
+ shouldHideChannel,
status,
teammateDeletedAt,
theme,
type,
} = this.props;
+ if (shouldHideChannel) {
+ return null;
+ }
+
const {intl} = this.context;
let channelDisplayName = displayName;
diff --git a/app/components/channel_drawer/channels_list/channel_item/index.js b/app/components/channel_drawer/channels_list/channel_item/index.js
index ef25b66e2..416ee3c5f 100644
--- a/app/components/channel_drawer/channels_list/channel_item/index.js
+++ b/app/components/channel_drawer/channels_list/channel_item/index.js
@@ -4,7 +4,7 @@
import {connect} from 'react-redux';
import {General} from 'mattermost-redux/constants';
-import {getCurrentChannelId, makeGetChannel, getMyChannelMember} from 'mattermost-redux/selectors/entities/channels';
+import {getCurrentChannelId, makeGetChannel, getMyChannelMember, isChannelReadOnlyById} from 'mattermost-redux/selectors/entities/channels';
import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
import {getCurrentUserId, getUser} from 'mattermost-redux/selectors/entities/users';
import {isChannelMuted} from 'mattermost-redux/utils/channel_utils';
@@ -29,6 +29,9 @@ function makeMapStateToProps() {
}
}
+ const isReadOnly = isChannelReadOnlyById(state, channel.id);
+ const shouldHideChannel = !ownProps.isSearchResult && !ownProps.isFavorite && isReadOnly;
+
return {
currentChannelId: getCurrentChannelId(state),
displayName: channel.display_name,
@@ -36,6 +39,7 @@ function makeMapStateToProps() {
isChannelMuted: isChannelMuted(member),
isMyUser,
mentions: member ? member.mention_count : 0,
+ shouldHideChannel,
status: channel.status,
teammateDeletedAt,
theme: getTheme(state),
diff --git a/app/components/channel_drawer/channels_list/filtered_list/filtered_list.js b/app/components/channel_drawer/channels_list/filtered_list/filtered_list.js
index 067aa6133..d8bb6607b 100644
--- a/app/components/channel_drawer/channels_list/filtered_list/filtered_list.js
+++ b/app/components/channel_drawer/channels_list/filtered_list/filtered_list.js
@@ -113,6 +113,7 @@ class FilteredList extends Component {
ref={channel.id}
channelId={channel.id}
channel={channel}
+ isSearchResult={true}
isUnread={false}
mentions={0}
onSelectChannel={this.onSelectChannel}
diff --git a/app/components/channel_drawer/channels_list/list/index.js b/app/components/channel_drawer/channels_list/list/index.js
index ca719a2a5..22c812153 100644
--- a/app/components/channel_drawer/channels_list/list/index.js
+++ b/app/components/channel_drawer/channels_list/list/index.js
@@ -15,7 +15,7 @@ import {getCurrentUserId, getCurrentUserRoles} from 'mattermost-redux/selectors/
import {getCurrentTeamId} from 'mattermost-redux/selectors/entities/teams';
import {getTheme, getFavoritesPreferences} from 'mattermost-redux/selectors/entities/preferences';
import {showCreateOption} from 'mattermost-redux/utils/channel_utils';
-import {isAdmin, isSystemAdmin} from 'mattermost-redux/utils/user_utils';
+import {isAdmin as checkIsAdmin, isSystemAdmin as checkIsSystemAdmin} from 'mattermost-redux/utils/user_utils';
import List from './list';
@@ -24,13 +24,16 @@ function mapStateToProps(state) {
const roles = getCurrentUserId(state) ? getCurrentUserRoles(state) : '';
const unreadChannelIds = getSortedUnreadChannelIds(state);
const favoriteChannelIds = getSortedFavoriteChannelIds(state);
- const publicChannelIds = getSortedPublicChannelIds(state);
const privateChannelIds = getSortedPrivateChannelIds(state);
const directChannelIds = getSortedDirectChannelIds(state);
const currentTeamId = getCurrentTeamId(state);
+ const publicChannelIds = getSortedPublicChannelIds(state);
+
+ const isAdmin = checkIsAdmin(roles);
+ const isSystemAdmin = checkIsSystemAdmin(roles);
return {
- canCreatePrivateChannels: showCreateOption(state, config, license, currentTeamId, General.PRIVATE_CHANNEL, isAdmin(roles), isSystemAdmin(roles)),
+ canCreatePrivateChannels: showCreateOption(state, config, license, currentTeamId, General.PRIVATE_CHANNEL, isAdmin, isSystemAdmin),
unreadChannelIds,
favoriteChannelIds,
publicChannelIds,
diff --git a/app/components/channel_drawer/channels_list/list/list.js b/app/components/channel_drawer/channels_list/list/list.js
index c21e18c73..887a56285 100644
--- a/app/components/channel_drawer/channels_list/list/list.js
+++ b/app/components/channel_drawer/channels_list/list/list.js
@@ -257,6 +257,7 @@ export default class List extends PureComponent {
return (
diff --git a/app/components/post/index.js b/app/components/post/index.js
index 6ec909aeb..55c5a1ca1 100644
--- a/app/components/post/index.js
+++ b/app/components/post/index.js
@@ -5,13 +5,13 @@ import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import {createPost, deletePost, removePost} from 'mattermost-redux/actions/posts';
+import {getCurrentChannelId, isCurrentChannelReadOnly} from 'mattermost-redux/selectors/entities/channels';
import {getPost} from 'mattermost-redux/selectors/entities/posts';
import {getCurrentUserId, getCurrentUserRoles} from 'mattermost-redux/selectors/entities/users';
import {getMyPreferences, getTheme} from 'mattermost-redux/selectors/entities/preferences';
import {getCurrentTeamUrl, getCurrentTeamId} from 'mattermost-redux/selectors/entities/teams';
-import {getCurrentChannelId} from 'mattermost-redux/selectors/entities/channels';
import {canDeletePost, canEditPost, isPostFlagged} from 'mattermost-redux/utils/post_utils';
-import {isAdmin, isSystemAdmin} from 'mattermost-redux/utils/user_utils';
+import {isAdmin as checkIsAdmin, isSystemAdmin as checkIsSystemAdmin} from 'mattermost-redux/utils/user_utils';
import {insertToDraft, setPostTooltipVisible} from 'app/actions/views/channel';
import {addReaction} from 'app/actions/views/emoji';
@@ -56,14 +56,18 @@ function mapStateToProps(state, ownProps) {
const {deviceWidth} = getDimensions(state);
+ const isAdmin = checkIsAdmin(roles);
+ const isSystemAdmin = checkIsSystemAdmin(roles);
+
let canDelete = false;
let canEdit = false;
if (post) {
- canDelete = canDeletePost(state, config, license, currentTeamId, currentChannelId, currentUserId, post, isAdmin(roles), isSystemAdmin(roles));
+ canDelete = canDeletePost(state, config, license, currentTeamId, currentChannelId, currentUserId, post, isAdmin, isSystemAdmin);
canEdit = canEditPost(state, config, license, currentTeamId, currentChannelId, currentUserId, post);
}
return {
+ channelIsReadOnly: isCurrentChannelReadOnly(state),
config,
canDelete,
canEdit,
diff --git a/app/components/post/post.js b/app/components/post/post.js
index 16fddc5a7..ce36b8aaa 100644
--- a/app/components/post/post.js
+++ b/app/components/post/post.js
@@ -39,6 +39,7 @@ export default class Post extends PureComponent {
insertToDraft: PropTypes.func.isRequired,
removePost: PropTypes.func.isRequired,
}).isRequired,
+ channelIsReadOnly: PropTypes.bool,
config: PropTypes.object.isRequired,
currentTeamUrl: PropTypes.string.isRequired,
currentUserId: PropTypes.string.isRequired,
@@ -70,6 +71,7 @@ export default class Post extends PureComponent {
static defaultProps = {
isSearchResult: false,
showLongPost: false,
+ channelIsReadOnly: false,
};
static contextTypes = {
@@ -377,6 +379,7 @@ export default class Post extends PureComponent {
render() {
const {
+ channelIsReadOnly,
commentedOnPost,
highlight,
isLastReply,
@@ -443,6 +446,7 @@ export default class Post extends PureComponent {
canDelete={this.props.canDelete}
canEdit={this.state.canEdit}
highlight={highlight}
+ channelIsReadOnly={channelIsReadOnly}
isSearchResult={isSearchResult}
navigator={this.props.navigator}
onAddReaction={this.handleAddReaction}
diff --git a/app/components/post_body/post_body.js b/app/components/post_body/post_body.js
index f8a15ebeb..66db41a2f 100644
--- a/app/components/post_body/post_body.js
+++ b/app/components/post_body/post_body.js
@@ -37,6 +37,7 @@ export default class PostBody extends PureComponent {
}).isRequired,
canDelete: PropTypes.bool,
canEdit: PropTypes.bool,
+ channelIsReadOnly: PropTypes.bool.isRequired,
fileIds: PropTypes.array,
hasBeenDeleted: PropTypes.bool,
hasBeenEdited: PropTypes.bool,
@@ -116,6 +117,7 @@ export default class PostBody extends PureComponent {
canEdit,
canDelete,
canAddReaction,
+ channelIsReadOnly,
hasBeenDeleted,
isPending,
isFailed,
@@ -132,7 +134,7 @@ export default class PostBody extends PureComponent {
// we should check for the user roles and permissions
if (!isPendingOrFailedPost && !isSystemMessage && !isPostEphemeral) {
- if (canAddReaction) {
+ if (canAddReaction && !channelIsReadOnly) {
actions.push({
text: formatMessage({id: 'mobile.post_info.add_reaction', defaultMessage: 'Add Reaction'}),
onPress: this.props.onAddReaction,
@@ -147,16 +149,18 @@ export default class PostBody extends PureComponent {
});
}
- if (isFlagged) {
- actions.push({
- text: formatMessage({id: 'post_info.mobile.unflag', defaultMessage: 'Unflag'}),
- onPress: this.unflagPost,
- });
- } else {
- actions.push({
- text: formatMessage({id: 'post_info.mobile.flag', defaultMessage: 'Flag'}),
- onPress: this.flagPost,
- });
+ if (!channelIsReadOnly) {
+ if (isFlagged) {
+ actions.push({
+ text: formatMessage({id: 'post_info.mobile.unflag', defaultMessage: 'Unflag'}),
+ onPress: this.unflagPost,
+ });
+ } else {
+ actions.push({
+ text: formatMessage({id: 'post_info.mobile.flag', defaultMessage: 'Flag'}),
+ onPress: this.flagPost,
+ });
+ }
}
if (canEdit) {
diff --git a/app/components/post_textbox/index.js b/app/components/post_textbox/index.js
index 7a8d75b40..4fd71c362 100644
--- a/app/components/post_textbox/index.js
+++ b/app/components/post_textbox/index.js
@@ -6,7 +6,7 @@ import {connect} from 'react-redux';
import {General} from 'mattermost-redux/constants';
import {createPost} from 'mattermost-redux/actions/posts';
-import {getCurrentChannel} from 'mattermost-redux/selectors/entities/channels';
+import {getCurrentChannel, isCurrentChannelReadOnly} from 'mattermost-redux/selectors/entities/channels';
import {canUploadFilesOnMobile, getConfig} from 'mattermost-redux/selectors/entities/general';
import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users';
@@ -41,6 +41,7 @@ function mapStateToProps(state, ownProps) {
channelId: ownProps.channelId || (currentChannel ? currentChannel.id : ''),
canUploadFiles: canUploadFilesOnMobile(state),
channelIsLoading: state.views.channel.loading,
+ channelIsReadOnly: isCurrentChannelReadOnly(state),
currentUserId: getCurrentUserId(state),
deactivatedChannel,
files: currentDraft.files,
diff --git a/app/components/post_textbox/post_textbox.js b/app/components/post_textbox/post_textbox.js
index a0814ceab..2d2138aea 100644
--- a/app/components/post_textbox/post_textbox.js
+++ b/app/components/post_textbox/post_textbox.js
@@ -39,6 +39,7 @@ export default class PostTextbox extends PureComponent {
canUploadFiles: PropTypes.bool.isRequired,
channelId: PropTypes.string.isRequired,
channelIsLoading: PropTypes.bool.isRequired,
+ channelIsReadOnly: PropTypes.bool.isRequired,
currentUserId: PropTypes.string.isRequired,
deactivatedChannel: PropTypes.bool.isRequired,
files: PropTypes.array,
@@ -397,6 +398,7 @@ export default class PostTextbox extends PureComponent {
canUploadFiles,
channelId,
channelIsLoading,
+ channelIsReadOnly,
deactivatedChannel,
files,
navigator,
@@ -422,7 +424,9 @@ export default class PostTextbox extends PureComponent {
const textValue = channelIsLoading ? '' : this.state.value;
let placeholder;
- if (rootId) {
+ if (channelIsReadOnly) {
+ placeholder = {id: 'mobile.create_post.read_only', defaultMessage: 'This channel is read-only.'};
+ } else if (rootId) {
placeholder = {id: 'create_comment.addComment', defaultMessage: 'Add a comment...'};
} else {
placeholder = {id: 'create_post.write', defaultMessage: 'Write a message...'};
@@ -463,8 +467,8 @@ export default class PostTextbox extends PureComponent {
rootId={rootId}
/>
- {attachmentButton}
-
+ {!channelIsReadOnly && attachmentButton}
+
{this.renderSendButton()}
diff --git a/app/screens/channel_info/index.js b/app/screens/channel_info/index.js
index db0432c7d..ee0659b38 100644
--- a/app/screens/channel_info/index.js
+++ b/app/screens/channel_info/index.js
@@ -21,10 +21,11 @@ import {
getCurrentChannelStats,
getSortedFavoriteChannelIds,
getMyCurrentChannelMembership,
+ isCurrentChannelReadOnly,
} from 'mattermost-redux/selectors/entities/channels';
import {getCurrentUserId, getUser, getStatusForUserId, getCurrentUserRoles} from 'mattermost-redux/selectors/entities/users';
import {getUserIdFromChannelName, isChannelMuted, showDeleteOption, showManagementOptions} from 'mattermost-redux/utils/channel_utils';
-import {isAdmin, isChannelAdmin, isSystemAdmin} from 'mattermost-redux/utils/user_utils';
+import {isAdmin as checkIsAdmin, isChannelAdmin as checkIsChannelAdmin, isSystemAdmin as checkIsSystemAdmin} from 'mattermost-redux/utils/user_utils';
import {
closeDMChannel,
@@ -56,9 +57,16 @@ function mapStateToProps(state) {
status = getStatusForUserId(state, teammateId);
}
+ const isAdmin = checkIsAdmin(roles);
+ const isChannelAdmin = checkIsChannelAdmin(roles);
+ const isSystemAdmin = checkIsSystemAdmin(roles);
+
+ const channelIsReadOnly = isCurrentChannelReadOnly(state);
+ const canEditChannel = !channelIsReadOnly && showManagementOptions(state, config, license, currentChannel, isAdmin, isSystemAdmin, isChannelAdmin);
+
return {
- canDeleteChannel: showDeleteOption(state, config, license, currentChannel, isAdmin(roles), isSystemAdmin(roles), isChannelAdmin(roles)),
- canEditChannel: showManagementOptions(state, config, license, currentChannel, isAdmin(roles), isSystemAdmin(roles), isChannelAdmin(roles)),
+ canDeleteChannel: showDeleteOption(state, config, license, currentChannel, isAdmin, isSystemAdmin, isChannelAdmin),
+ canEditChannel,
currentChannel,
currentChannelCreatorName,
currentChannelMemberCount,
diff --git a/assets/base/config.json b/assets/base/config.json
index 1b12796ba..4d7500889 100644
--- a/assets/base/config.json
+++ b/assets/base/config.json
@@ -28,9 +28,9 @@
"console": true
}
},
-
+
"ExperimentalNormalizeMarkdownLinks": false,
-
+
"AutoSelectServerUrl": false,
"EnableMobileClientUpgrade": false,
diff --git a/assets/base/i18n/en.json b/assets/base/i18n/en.json
index 999cc8417..1a36ba8e3 100644
--- a/assets/base/i18n/en.json
+++ b/assets/base/i18n/en.json
@@ -2071,6 +2071,7 @@
"mobile.create_channel": "Create",
"mobile.create_channel.private": "New Private Channel",
"mobile.create_channel.public": "New Public Channel",
+ "mobile.create_post.read_only": "This channel is read-only",
"mobile.custom_list.no_results": "No Results",
"mobile.document_preview.failed_description": "An error occurred while opening the document. Please make sure you have a {fileType} viewer installed and try again.\n",
"mobile.document_preview.failed_title": "Open Document failed",