* Dismiss keyboard on edit post close * Don't use edit post request * Focus on error Co-authored-by: Miguel Alatzar <this.migbot@gmail.com>
This commit is contained in:
parent
c15bb73d45
commit
88f1041f89
6 changed files with 1989 additions and 1844 deletions
File diff suppressed because it is too large
Load diff
|
|
@ -392,15 +392,20 @@ export function deletePost(post: ExtendedPost) {
|
|||
}
|
||||
|
||||
export function editPost(post: Post) {
|
||||
return bindClientFunc({
|
||||
clientFunc: Client4.patchPost,
|
||||
onRequest: PostTypes.EDIT_POST_REQUEST,
|
||||
onSuccess: [PostTypes.RECEIVED_POST, PostTypes.EDIT_POST_SUCCESS],
|
||||
onFailure: PostTypes.EDIT_POST_FAILURE,
|
||||
params: [
|
||||
post,
|
||||
],
|
||||
});
|
||||
return async (dispatch: DispatchFunc, getState: GetStateFunc) => {
|
||||
let data;
|
||||
|
||||
try {
|
||||
data = await Client4.patchPost(post);
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(error, dispatch, getState);
|
||||
return {error};
|
||||
}
|
||||
|
||||
dispatch(receivedPost(post));
|
||||
|
||||
return {data};
|
||||
};
|
||||
}
|
||||
|
||||
export function getUnreadPostData(unreadChan: ChannelUnread, state: GlobalState) {
|
||||
|
|
|
|||
93
app/screens/edit_post/__snapshots__/edit_post.test.js.snap
Normal file
93
app/screens/edit_post/__snapshots__/edit_post.test.js.snap
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`EditPost should match snapshot 1`] = `
|
||||
<View
|
||||
style={
|
||||
Object {
|
||||
"flex": 1,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Connect(StatusBar) />
|
||||
<View
|
||||
style={
|
||||
Object {
|
||||
"backgroundColor": "rgba(61,60,64,0.03)",
|
||||
"flex": 1,
|
||||
}
|
||||
}
|
||||
>
|
||||
<View
|
||||
style={
|
||||
Array [
|
||||
Object {
|
||||
"backgroundColor": "#ffffff",
|
||||
"borderBottomColor": "rgba(61,60,64,0.1)",
|
||||
"borderBottomWidth": 1,
|
||||
"borderTopColor": "rgba(61,60,64,0.1)",
|
||||
"borderTopWidth": 1,
|
||||
"marginTop": 2,
|
||||
},
|
||||
null,
|
||||
Object {
|
||||
"height": NaN,
|
||||
},
|
||||
]
|
||||
}
|
||||
>
|
||||
<TextInputWithLocalizedPlaceholder
|
||||
blurOnSubmit={false}
|
||||
disableFullscreenUI={true}
|
||||
keyboardAppearance="light"
|
||||
keyboardType="default"
|
||||
multiline={true}
|
||||
numberOfLines={10}
|
||||
onChangeText={[Function]}
|
||||
onSelectionChange={[Function]}
|
||||
placeholder={
|
||||
Object {
|
||||
"defaultMessage": "Edit the post...",
|
||||
"id": "edit_post.editPost",
|
||||
}
|
||||
}
|
||||
placeholderTextColor="rgba(61,60,64,0.4)"
|
||||
style={
|
||||
Array [
|
||||
Object {
|
||||
"color": "#3d3c40",
|
||||
"fontSize": 14,
|
||||
"padding": 15,
|
||||
"textAlignVertical": "top",
|
||||
},
|
||||
Object {
|
||||
"height": NaN,
|
||||
},
|
||||
]
|
||||
}
|
||||
underlineColorAndroid="transparent"
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
<KeyboardTrackingView
|
||||
style={
|
||||
Array [
|
||||
Object {
|
||||
"flex": 1,
|
||||
"justifyContent": "flex-end",
|
||||
},
|
||||
Object {
|
||||
"flex": 0,
|
||||
},
|
||||
]
|
||||
}
|
||||
>
|
||||
<Connect(Autocomplete)
|
||||
cursorPosition={0}
|
||||
maxHeight={200}
|
||||
nestedScrollEnabled={true}
|
||||
onChangeText={[Function]}
|
||||
onVisible={[Function]}
|
||||
/>
|
||||
</KeyboardTrackingView>
|
||||
</View>
|
||||
`;
|
||||
|
|
@ -6,6 +6,7 @@ import {intlShape} from 'react-intl';
|
|||
import {
|
||||
Platform,
|
||||
View,
|
||||
Keyboard,
|
||||
} from 'react-native';
|
||||
import {Navigation} from 'react-native-navigation';
|
||||
import {KeyboardTrackingView} from 'react-native-keyboard-tracking-view';
|
||||
|
|
@ -36,7 +37,6 @@ export default class EditPost extends PureComponent {
|
|||
closeButton: PropTypes.object,
|
||||
deviceHeight: PropTypes.number,
|
||||
deviceWidth: PropTypes.number,
|
||||
editPostRequest: PropTypes.object.isRequired,
|
||||
post: PropTypes.object.isRequired,
|
||||
theme: PropTypes.object.isRequired,
|
||||
isLandscape: PropTypes.bool.isRequired,
|
||||
|
|
@ -80,28 +80,6 @@ export default class EditPost extends PureComponent {
|
|||
this.focus();
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
const {editPostRequest} = nextProps;
|
||||
|
||||
if (this.props.editPostRequest !== editPostRequest) {
|
||||
switch (editPostRequest.status) {
|
||||
case RequestStatus.STARTED:
|
||||
this.emitEditing(true);
|
||||
this.setState({error: null, editing: true});
|
||||
break;
|
||||
case RequestStatus.SUCCESS:
|
||||
this.emitEditing(false);
|
||||
this.setState({error: null, editing: false});
|
||||
this.close();
|
||||
break;
|
||||
case RequestStatus.FAILURE:
|
||||
this.emitEditing(false);
|
||||
this.setState({error: editPostRequest.error, editing: false});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
navigationButtonPressed({buttonId}) {
|
||||
switch (buttonId) {
|
||||
case 'close-edit-post':
|
||||
|
|
@ -114,6 +92,7 @@ export default class EditPost extends PureComponent {
|
|||
}
|
||||
|
||||
close = () => {
|
||||
Keyboard.dismiss();
|
||||
dismissModal();
|
||||
};
|
||||
|
||||
|
|
@ -134,17 +113,37 @@ export default class EditPost extends PureComponent {
|
|||
};
|
||||
|
||||
focus = () => {
|
||||
this.messageInput.focus();
|
||||
if (this.messageInput) {
|
||||
this.messageInput.focus();
|
||||
}
|
||||
};
|
||||
|
||||
messageRef = (ref) => {
|
||||
this.messageInput = ref;
|
||||
};
|
||||
|
||||
onEditPost = () => {
|
||||
onEditPost = async () => {
|
||||
const {message} = this.state;
|
||||
const post = Object.assign({}, this.props.post, {message});
|
||||
this.props.actions.editPost(post);
|
||||
const {post, actions} = this.props;
|
||||
const editedPost = Object.assign({}, post, {message});
|
||||
|
||||
this.setState({
|
||||
editing: true,
|
||||
error: null,
|
||||
});
|
||||
|
||||
this.emitEditing(true);
|
||||
const {error} = await actions.editPost(editedPost);
|
||||
this.emitEditing(false);
|
||||
|
||||
if (error) {
|
||||
this.setState({
|
||||
editing: false,
|
||||
error,
|
||||
}, this.focus);
|
||||
} else {
|
||||
this.setState({editing: false}, this.close);
|
||||
}
|
||||
};
|
||||
|
||||
onPostChangeText = (message) => {
|
||||
|
|
@ -228,7 +227,6 @@ export default class EditPost extends PureComponent {
|
|||
multiline={true}
|
||||
numberOfLines={10}
|
||||
style={[style.input, {height}]}
|
||||
autoFocus={true}
|
||||
placeholder={{id: t('edit_post.editPost'), defaultMessage: 'Edit the post...'}}
|
||||
placeholderTextColor={changeOpacity(theme.centerChannelColor, 0.4)}
|
||||
underlineColorAndroid='transparent'
|
||||
|
|
|
|||
96
app/screens/edit_post/edit_post.test.js
Normal file
96
app/screens/edit_post/edit_post.test.js
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import React from 'react';
|
||||
import {Keyboard} from 'react-native';
|
||||
|
||||
import Preferences from '@mm-redux/constants/preferences';
|
||||
|
||||
import {shallowWithIntl} from 'test/intl-test-helper';
|
||||
|
||||
import EditPost from './edit_post';
|
||||
|
||||
describe('EditPost', () => {
|
||||
const baseProps = {
|
||||
actions: {
|
||||
editPost: jest.fn(),
|
||||
},
|
||||
post: {},
|
||||
theme: Preferences.THEMES.default,
|
||||
isLandscape: false,
|
||||
};
|
||||
|
||||
test('should match snapshot', () => {
|
||||
const wrapper = shallowWithIntl(
|
||||
<EditPost {...baseProps}/>,
|
||||
);
|
||||
|
||||
expect(wrapper.getElement()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('should dismiss keyboard on close', () => {
|
||||
Keyboard.dismiss = jest.fn();
|
||||
expect(Keyboard.dismiss).not.toHaveBeenCalled();
|
||||
|
||||
const wrapper = shallowWithIntl(
|
||||
<EditPost {...baseProps}/>,
|
||||
);
|
||||
wrapper.instance().close();
|
||||
expect(Keyboard.dismiss).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test('should handle edit post action error', async () => {
|
||||
const error = 'error';
|
||||
const props = {
|
||||
...baseProps,
|
||||
actions: {
|
||||
editPost: jest.fn().mockResolvedValueOnce({error}),
|
||||
},
|
||||
};
|
||||
|
||||
const wrapper = shallowWithIntl(
|
||||
<EditPost {...props}/>,
|
||||
);
|
||||
const instance = wrapper.instance();
|
||||
instance.emitEditing = jest.fn();
|
||||
instance.setState = jest.fn();
|
||||
|
||||
await instance.onEditPost();
|
||||
|
||||
expect(instance.emitEditing.mock.calls).toEqual([
|
||||
[true],
|
||||
[false],
|
||||
]);
|
||||
expect(instance.setState.mock.calls).toEqual([
|
||||
[{editing: true, error: null}],
|
||||
[{editing: false, error}, instance.focus],
|
||||
]);
|
||||
});
|
||||
|
||||
test('should handle edit post action success', async () => {
|
||||
const props = {
|
||||
...baseProps,
|
||||
actions: {
|
||||
editPost: jest.fn().mockResolvedValueOnce({}),
|
||||
},
|
||||
};
|
||||
|
||||
const wrapper = shallowWithIntl(
|
||||
<EditPost {...props}/>,
|
||||
);
|
||||
const instance = wrapper.instance();
|
||||
instance.emitEditing = jest.fn();
|
||||
instance.setState = jest.fn();
|
||||
|
||||
await instance.onEditPost();
|
||||
|
||||
expect(instance.emitEditing.mock.calls).toEqual([
|
||||
[true],
|
||||
[false],
|
||||
]);
|
||||
expect(instance.setState.mock.calls).toEqual([
|
||||
[{editing: true, error: null}],
|
||||
[{editing: false}, instance.close],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
|
@ -12,11 +12,8 @@ import {getDimensions, isLandscape} from 'app/selectors/device';
|
|||
import EditPost from './edit_post';
|
||||
|
||||
function mapStateToProps(state, ownProps) {
|
||||
const {editPost: editPostRequest} = state.requests.posts;
|
||||
|
||||
return {
|
||||
...getDimensions(state),
|
||||
editPostRequest,
|
||||
post: ownProps.post,
|
||||
theme: getTheme(state),
|
||||
isLandscape: isLandscape(state),
|
||||
|
|
|
|||
Loading…
Reference in a new issue