MM-17425 Disable Send button when sending post (1.22) (#3100)
* MM-17425 Disable Send button when sending post (1.22) * Update snapshot and add tests
This commit is contained in:
parent
94aa1be435
commit
e03b72861c
4 changed files with 139 additions and 72 deletions
|
|
@ -98,7 +98,7 @@ exports[`PostTextBox should match, full snapshot 1`] = `
|
|||
visible={false}
|
||||
>
|
||||
<SendButton
|
||||
disabled={false}
|
||||
disabled={true}
|
||||
handleSendMessage={[Function]}
|
||||
theme={
|
||||
Object {
|
||||
|
|
|
|||
|
|
@ -6,6 +6,9 @@ import {shallowWithIntl} from 'test/intl-test-helper';
|
|||
|
||||
import Preferences from 'mattermost-redux/constants/preferences';
|
||||
|
||||
import Fade from 'app/components/fade';
|
||||
import SendButton from 'app/components/send_button';
|
||||
|
||||
import PostTextbox from './post_textbox.ios';
|
||||
|
||||
jest.mock('NativeEventEmitter');
|
||||
|
|
@ -84,4 +87,73 @@ describe('PostTextBox', () => {
|
|||
expect(baseProps.actions.handlePostDraftChanged).toHaveBeenCalledWith(baseProps.channelId, value);
|
||||
expect(baseProps.actions.handlePostDraftChanged).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
describe('send button', () => {
|
||||
test('should initially disable and hide the send button', () => {
|
||||
const wrapper = shallowWithIntl(
|
||||
<PostTextbox {...baseProps}/>
|
||||
);
|
||||
|
||||
expect(wrapper.find(Fade).prop('visible')).toBe(false);
|
||||
expect(wrapper.find(SendButton).prop('disabled')).toBe(true);
|
||||
});
|
||||
|
||||
test('should show a disabled send button when uploading a file', () => {
|
||||
const props = {
|
||||
...baseProps,
|
||||
files: [{loading: true}],
|
||||
};
|
||||
|
||||
const wrapper = shallowWithIntl(
|
||||
<PostTextbox {...props}/>
|
||||
);
|
||||
|
||||
expect(wrapper.find(Fade).prop('visible')).toBe(true);
|
||||
expect(wrapper.find(SendButton).prop('disabled')).toBe(true);
|
||||
});
|
||||
|
||||
test('should show an enabled send button after uploading a file', () => {
|
||||
const props = {
|
||||
...baseProps,
|
||||
files: [{loading: false}],
|
||||
};
|
||||
|
||||
const wrapper = shallowWithIntl(
|
||||
<PostTextbox {...props}/>
|
||||
);
|
||||
|
||||
expect(wrapper.find(Fade).prop('visible')).toBe(true);
|
||||
expect(wrapper.find(SendButton).prop('disabled')).toBe(false);
|
||||
});
|
||||
|
||||
test('should show an enabled send button with a message', () => {
|
||||
const props = {
|
||||
...baseProps,
|
||||
value: 'test',
|
||||
};
|
||||
|
||||
const wrapper = shallowWithIntl(
|
||||
<PostTextbox {...props}/>
|
||||
);
|
||||
|
||||
expect(wrapper.find(Fade).prop('visible')).toBe(true);
|
||||
expect(wrapper.find(SendButton).prop('disabled')).toBe(false);
|
||||
});
|
||||
|
||||
test('should show a disabled send button while sending the message', () => {
|
||||
const props = {
|
||||
...baseProps,
|
||||
value: 'test',
|
||||
};
|
||||
|
||||
const wrapper = shallowWithIntl(
|
||||
<PostTextbox {...props}/>
|
||||
);
|
||||
|
||||
wrapper.setState({sendingMessage: true});
|
||||
|
||||
expect(wrapper.find(Fade).prop('visible')).toBe(true);
|
||||
expect(wrapper.find(SendButton).prop('disabled')).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -91,6 +91,7 @@ export default class PostTextBoxBase extends PureComponent {
|
|||
this.state = {
|
||||
cursorPosition: 0,
|
||||
keyboardType: 'default',
|
||||
sendingMessage: false,
|
||||
top: 0,
|
||||
value: props.value,
|
||||
};
|
||||
|
|
@ -278,10 +279,12 @@ export default class PostTextBoxBase extends PureComponent {
|
|||
};
|
||||
|
||||
handleSendMessage = () => {
|
||||
if (!this.canSend()) {
|
||||
if (!this.canSend() || this.state.sendingMessage) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({sendingMessage: true});
|
||||
|
||||
const {actions, channelId, files, rootId} = this.props;
|
||||
const {value} = this.state;
|
||||
|
||||
|
|
@ -307,6 +310,9 @@ export default class PostTextBoxBase extends PureComponent {
|
|||
}),
|
||||
[{
|
||||
text: intl.formatMessage({id: 'mobile.channel_info.alertNo', defaultMessage: 'No'}),
|
||||
onPress: () => {
|
||||
this.setState({sendingMessage: false});
|
||||
},
|
||||
}, {
|
||||
text: intl.formatMessage({id: 'mobile.channel_info.alertYes', defaultMessage: 'Yes'}),
|
||||
onPress: () => {
|
||||
|
|
@ -388,81 +394,72 @@ export default class PostTextBoxBase extends PureComponent {
|
|||
return this.canSend() || this.isFileLoading();
|
||||
}
|
||||
|
||||
isSendButtonEnabled() {
|
||||
return this.canSend() && !this.state.sendingMessage;
|
||||
}
|
||||
|
||||
sendMessage = () => {
|
||||
const {actions, currentUserId, channelId, files, rootId} = this.props;
|
||||
const {intl} = this.context;
|
||||
const {value} = this.state;
|
||||
|
||||
if (files.length === 0 && !value) {
|
||||
Alert.alert(
|
||||
intl.formatMessage({
|
||||
id: 'mobile.post_textbox.empty.title',
|
||||
defaultMessage: 'Empty Message',
|
||||
}),
|
||||
intl.formatMessage({
|
||||
id: 'mobile.post_textbox.empty.message',
|
||||
defaultMessage: 'You are trying to send an empty message.\nPlease make sure you have a message or at least one attached file.',
|
||||
}),
|
||||
[{
|
||||
text: intl.formatMessage({id: 'mobile.post_textbox.empty.ok', defaultMessage: 'OK'}),
|
||||
}],
|
||||
);
|
||||
if (value.indexOf('/') === 0) {
|
||||
this.sendCommand(value);
|
||||
} else {
|
||||
if (value.indexOf('/') === 0) {
|
||||
this.sendCommand(value);
|
||||
} else {
|
||||
const postFiles = files.filter((f) => !f.failed);
|
||||
const post = {
|
||||
user_id: currentUserId,
|
||||
channel_id: channelId,
|
||||
root_id: rootId,
|
||||
parent_id: rootId,
|
||||
message: value,
|
||||
};
|
||||
const postFiles = files.filter((f) => !f.failed);
|
||||
const post = {
|
||||
user_id: currentUserId,
|
||||
channel_id: channelId,
|
||||
root_id: rootId,
|
||||
parent_id: rootId,
|
||||
message: value,
|
||||
};
|
||||
|
||||
actions.createPost(post, postFiles);
|
||||
actions.createPost(post, postFiles);
|
||||
|
||||
if (postFiles.length) {
|
||||
actions.handleClearFiles(channelId, rootId);
|
||||
}
|
||||
if (postFiles.length) {
|
||||
actions.handleClearFiles(channelId, rootId);
|
||||
}
|
||||
|
||||
if (Platform.OS === 'ios') {
|
||||
// On iOS, if the PostTextbox height increases from its
|
||||
// initial height (due to a multiline post or a post whose
|
||||
// message wraps, for example), then when the text is cleared
|
||||
// the PostTextbox height decrease will be animated. This
|
||||
// animation in conjunction with the PostList animation as it
|
||||
// receives the newly created post is causing issues in the iOS
|
||||
// PostList component as it fails to properly react to its content
|
||||
// size changes. While a proper fix is determined for the PostList
|
||||
// component, a small delay in triggering the height decrease
|
||||
// animation gives the PostList enough time to first handle content
|
||||
// size changes from the new post.
|
||||
setTimeout(() => {
|
||||
this.handleTextChange('');
|
||||
}, 250);
|
||||
} else {
|
||||
this.handleTextChange('');
|
||||
}
|
||||
|
||||
this.changeDraft('');
|
||||
|
||||
let callback;
|
||||
if (Platform.OS === 'android') {
|
||||
// Fixes the issue where Android predictive text would prepend suggestions to the post draft when messages
|
||||
// are typed successively without blurring the input
|
||||
const nextState = {
|
||||
keyboardType: 'email-address',
|
||||
};
|
||||
|
||||
callback = () => this.setState({keyboardType: 'default'});
|
||||
|
||||
this.setState(nextState, callback);
|
||||
}
|
||||
|
||||
EventEmitter.emit('scroll-to-bottom');
|
||||
}
|
||||
|
||||
if (Platform.OS === 'ios') {
|
||||
// On iOS, if the PostTextbox height increases from its
|
||||
// initial height (due to a multiline post or a post whose
|
||||
// message wraps, for example), then when the text is cleared
|
||||
// the PostTextbox height decrease will be animated. This
|
||||
// animation in conjunction with the PostList animation as it
|
||||
// receives the newly created post is causing issues in the iOS
|
||||
// PostList component as it fails to properly react to its content
|
||||
// size changes. While a proper fix is determined for the PostList
|
||||
// component, a small delay in triggering the height decrease
|
||||
// animation gives the PostList enough time to first handle content
|
||||
// size changes from the new post.
|
||||
setTimeout(() => {
|
||||
this.handleTextChange('');
|
||||
|
||||
this.setState({sendingMessage: false});
|
||||
}, 250);
|
||||
} else {
|
||||
this.handleTextChange('');
|
||||
|
||||
this.setState({sendingMessage: false});
|
||||
}
|
||||
|
||||
this.changeDraft('');
|
||||
|
||||
let callback;
|
||||
if (Platform.OS === 'android') {
|
||||
// Fixes the issue where Android predictive text would prepend suggestions to the post draft when messages
|
||||
// are typed successively without blurring the input
|
||||
const nextState = {
|
||||
keyboardType: 'email-address',
|
||||
};
|
||||
|
||||
callback = () => this.setState({keyboardType: 'default'});
|
||||
|
||||
this.setState(nextState, callback);
|
||||
}
|
||||
|
||||
EventEmitter.emit('scroll-to-bottom');
|
||||
};
|
||||
|
||||
getStatusFromSlashCommand = (message) => {
|
||||
|
|
@ -516,6 +513,7 @@ export default class PostTextBoxBase extends PureComponent {
|
|||
const {actions, rootId} = this.props;
|
||||
actions.addReactionToLatestPost(emoji, rootId);
|
||||
this.handleTextChange('');
|
||||
this.setState({sendingMessage: false});
|
||||
this.changeDraft('');
|
||||
};
|
||||
|
||||
|
|
@ -628,7 +626,7 @@ export default class PostTextBoxBase extends PureComponent {
|
|||
/>
|
||||
<Fade visible={this.isSendButtonVisible()}>
|
||||
<SendButton
|
||||
disabled={this.isFileLoading()}
|
||||
disabled={!this.isSendButtonEnabled()}
|
||||
handleSendMessage={this.handleSendMessage}
|
||||
theme={theme}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -352,9 +352,6 @@
|
|||
"mobile.post_pre_header.flagged": "Flagged",
|
||||
"mobile.post_pre_header.pinned": "Pinned",
|
||||
"mobile.post_pre_header.pinned_flagged": "Pinned and Flagged",
|
||||
"mobile.post_textbox.empty.message": "You are trying to send an empty message.\nPlease make sure you have a message or at least one attached file.",
|
||||
"mobile.post_textbox.empty.ok": "OK",
|
||||
"mobile.post_textbox.empty.title": "Empty Message",
|
||||
"mobile.post_textbox.uploadFailedDesc": "Some attachments failed to upload to the server. Are you sure you want to post the message?",
|
||||
"mobile.post_textbox.uploadFailedTitle": "Attachment failure",
|
||||
"mobile.post.cancel": "Cancel",
|
||||
|
|
|
|||
Loading…
Reference in a new issue