diff --git a/app/components/post_textbox/index.js b/app/components/post_textbox/index.js
index b4fe0934f..817962e2d 100644
--- a/app/components/post_textbox/index.js
+++ b/app/components/post_textbox/index.js
@@ -50,6 +50,14 @@ function mapStateToProps(state, ownProps) {
const currentChannelStats = getCurrentChannelStats(state);
const currentChannelMembersCount = currentChannelStats?.member_count || 0; // eslint-disable-line camelcase
const isTimezoneEnabled = config?.ExperimentalTimezone === 'true';
+ const canPost = haveIChannelPermission(
+ state,
+ {
+ channel: currentChannel.id,
+ team: currentChannel.team_id,
+ permission: Permissions.CREATE_POST,
+ },
+ );
let useChannelMentions = true;
if (isMinimumServerVersion(state.entities.general.serverVersion, 5, 22)) {
@@ -83,6 +91,7 @@ function mapStateToProps(state, ownProps) {
currentChannelMembersCount,
isTimezoneEnabled,
isLandscape: isLandscape(state),
+ canPost,
useChannelMentions,
};
}
diff --git a/app/components/post_textbox/post_textbox.test.js b/app/components/post_textbox/post_textbox.test.js
index 930e2ab7e..c6aaa4dc6 100644
--- a/app/components/post_textbox/post_textbox.test.js
+++ b/app/components/post_textbox/post_textbox.test.js
@@ -63,6 +63,7 @@ describe('PostTextBox', () => {
valueEvent: '',
isLandscape: false,
screenId: 'NavigationScreen1',
+ canPost: true,
currentChannelMembersCount: 50,
enableConfirmNotificationsToChannel: true,
useChannelMentions: true,
@@ -554,5 +555,15 @@ describe('PostTextBox', () => {
wrapper.setProps({value: 'value', channelId: 'channel-id2'});
expect(wrapper.state('value')).toEqual('value');
});
+
+ test('should be disabled without the create_post permission', () => {
+ const props = {...baseProps, canPost: false};
+
+ const wrapper = shallowWithIntl(
+ ,
+ );
+
+ expect(wrapper.find(PasteableTextInput).prop('editable')).toBe(false);
+ });
});
diff --git a/app/components/post_textbox/post_textbox_base.js b/app/components/post_textbox/post_textbox_base.js
index 7ef2c4d07..96513e56d 100644
--- a/app/components/post_textbox/post_textbox_base.js
+++ b/app/components/post_textbox/post_textbox_base.js
@@ -97,6 +97,7 @@ export default class PostTextBoxBase extends PureComponent {
currentChannel: PropTypes.object,
isLandscape: PropTypes.bool.isRequired,
screenId: PropTypes.string.isRequired,
+ canPost: PropTypes.bool.isRequired,
useChannelMentions: PropTypes.bool.isRequired,
};
@@ -257,7 +258,7 @@ export default class PostTextBoxBase extends PureComponent {
};
getTextInputButton = (actionType) => {
- const {channelIsReadOnly, theme} = this.props;
+ const {channelIsReadOnly, theme, canPost} = this.props;
const style = getStyleSheet(theme);
let button = null;
@@ -265,7 +266,7 @@ export default class PostTextBoxBase extends PureComponent {
let iconColor = changeOpacity(theme.centerChannelColor, 0.64);
let isDisabled = false;
- if (!channelIsReadOnly) {
+ if (!channelIsReadOnly && canPost) {
switch (actionType) {
case 'at':
isDisabled = this.state.value[this.state.value.length - 1] === '@';
@@ -313,7 +314,7 @@ export default class PostTextBoxBase extends PureComponent {
}
getMediaButton = (actionType) => {
- const {canUploadFiles, channelIsReadOnly, files, maxFileSize, theme} = this.props;
+ const {canUploadFiles, channelIsReadOnly, files, maxFileSize, theme, canPost} = this.props;
const style = getStyleSheet(theme);
let button = null;
const props = {
@@ -328,7 +329,7 @@ export default class PostTextBoxBase extends PureComponent {
buttonContainerStyle: style.iconWrapper,
};
- if (canUploadFiles && !channelIsReadOnly) {
+ if (canUploadFiles && !channelIsReadOnly && canPost) {
switch (actionType) {
case 'file':
button = (
@@ -351,11 +352,11 @@ export default class PostTextBoxBase extends PureComponent {
}
getInputContainerStyle = () => {
- const {channelIsReadOnly, theme} = this.props;
+ const {channelIsReadOnly, theme, canPost} = this.props;
const style = getStyleSheet(theme);
const inputContainerStyle = [style.inputContainer];
- if (channelIsReadOnly) {
+ if (channelIsReadOnly || !canPost) {
inputContainerStyle.push(style.readonlyContainer);
}
@@ -363,10 +364,10 @@ export default class PostTextBoxBase extends PureComponent {
};
getPlaceHolder = () => {
- const {channelIsReadOnly, rootId} = this.props;
+ const {channelIsReadOnly, rootId, canPost} = this.props;
let placeholder;
- if (channelIsReadOnly) {
+ if (channelIsReadOnly || !canPost) {
placeholder = {id: t('mobile.create_post.read_only'), defaultMessage: 'This channel is read-only.'};
} else if (rootId) {
placeholder = {id: t('create_comment.addComment'), defaultMessage: 'Add a comment...'};
@@ -897,7 +898,7 @@ export default class PostTextBoxBase extends PureComponent {
renderTextBox = () => {
const {intl} = this.context;
- const {channelDisplayName, channelIsArchived, channelIsReadOnly, theme, isLandscape, files, rootId} = this.props;
+ const {channelDisplayName, channelIsArchived, channelIsReadOnly, theme, isLandscape, files, rootId, canPost} = this.props;
const style = getStyleSheet(theme);
if (channelIsArchived) {
@@ -949,12 +950,12 @@ export default class PostTextBoxBase extends PureComponent {
keyboardType={this.state.keyboardType}
onEndEditing={this.handleEndEditing}
disableFullscreenUI={true}
- editable={!channelIsReadOnly}
+ editable={!channelIsReadOnly && canPost}
onPaste={this.handlePasteFiles}
keyboardAppearance={getKeyboardAppearanceFromTheme(theme)}
onContentSizeChange={Platform.OS === 'android' ? this.handleInputSizeChange : null}
/>
- {!channelIsReadOnly &&
+ {!channelIsReadOnly && canPost &&
{
general: {
serverVersion: '5.18',
},
+ channels: {myMembers: {}},
+ teams: {myMembers: {}},
+ roles: {roles: {}},
+ users: {profiles: {}},
},
};
diff --git a/app/screens/post_options/post_options.test.js b/app/screens/post_options/post_options.test.js
index 53e112abe..df4b1ea57 100644
--- a/app/screens/post_options/post_options.test.js
+++ b/app/screens/post_options/post_options.test.js
@@ -122,4 +122,10 @@ describe('PostOptions', () => {
expect(actions.deletePost).toBeCalled();
expect(actions.removePost).toBeCalled();
});
+
+ test('should not show reply option without create_post permission', () => {
+ const wrapper = getWrapper({canPost: false});
+
+ expect(wrapper.findWhere((node) => node.key() === 'reply')).toMatchObject({});
+ });
});