// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. import React, {PureComponent} from 'react'; import PropTypes from 'prop-types'; 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'; import Autocomplete, {AUTOCOMPLETE_MAX_HEIGHT} from 'app/components/autocomplete'; import ErrorText from 'app/components/error_text'; import Loading from 'app/components/loading'; import StatusBar from 'app/components/status_bar'; import TextInputWithLocalizedPlaceholder from 'app/components/text_input_with_localized_placeholder'; import {paddingHorizontal as padding} from 'app/components/safe_area_view/iphone_x_spacing'; import {switchKeyboardForCodeBlocks} from 'app/utils/markdown'; import { changeOpacity, makeStyleSheetFromTheme, getKeyboardAppearanceFromTheme, } from 'app/utils/theme'; import {t} from 'app/utils/i18n'; import {dismissModal, setButtons} from 'app/actions/navigation'; export default class EditPost extends PureComponent { static propTypes = { actions: PropTypes.shape({ editPost: PropTypes.func.isRequired, }), componentId: PropTypes.string, closeButton: PropTypes.object, deviceHeight: PropTypes.number, deviceWidth: PropTypes.number, post: PropTypes.object.isRequired, theme: PropTypes.object.isRequired, isLandscape: PropTypes.bool.isRequired, }; static contextTypes = { intl: intlShape, }; leftButton = { id: 'close-edit-post', }; rightButton = { id: 'edit-post', showAsAction: 'always', }; constructor(props, context) { super(props); this.state = { message: props.post.message, cursorPosition: 0, autocompleteVisible: false, keyboardType: 'default', }; this.rightButton.color = props.theme.sidebarHeaderTextColor; this.rightButton.text = context.intl.formatMessage({id: 'edit_post.save', defaultMessage: 'Save'}); setButtons(props.componentId, { leftButtons: [{...this.leftButton, icon: props.closeButton}], rightButtons: [this.rightButton], }); } componentDidMount() { this.navigationEventListener = Navigation.events().bindComponent(this); this.focus(); } navigationButtonPressed({buttonId}) { switch (buttonId) { case 'close-edit-post': this.close(); break; case 'edit-post': this.onEditPost(); break; } } close = () => { Keyboard.dismiss(); dismissModal(); }; emitCanEditPost = (enabled) => { const {componentId} = this.props; setButtons(componentId, { leftButtons: [{...this.leftButton, icon: this.props.closeButton}], rightButtons: [{...this.rightButton, enabled}], }); }; emitEditing = (loading) => { const {componentId} = this.props; setButtons(componentId, { leftButtons: [{...this.leftButton, icon: this.props.closeButton}], rightButtons: [{...this.rightButton, enabled: !loading}], }); }; focus = () => { if (this.messageInput) { this.messageInput.focus(); } }; messageRef = (ref) => { this.messageInput = ref; }; onEditPost = async () => { const {message} = this.state; 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) => { // Workaround to avoid iOS emdash autocorrect in Code Blocks if (Platform.OS === 'ios') { const callback = () => this.onPostSelectionChange(null, true); this.setState({message}, callback); } else { this.setState({message}); } if (message) { this.emitCanEditPost(true); } else { this.emitCanEditPost(false); } }; handleOnSelectionChange = (event) => { this.onPostSelectionChange(event, false); }; onPostSelectionChange = (event, fromOnPostChangeText) => { const cursorPosition = fromOnPostChangeText ? this.state.cursorPosition : event.nativeEvent.selection.end; if (Platform.OS === 'ios') { const keyboardType = switchKeyboardForCodeBlocks(this.state.message, cursorPosition); this.setState({cursorPosition, keyboardType}); } else { this.setState({cursorPosition}); } }; onAutocompleteVisible = (autocompleteVisible) => { this.setState({autocompleteVisible}); } render() { const {deviceHeight, deviceWidth, theme, isLandscape} = this.props; const {editing, message, error, autocompleteVisible} = this.state; const style = getStyleSheet(theme); if (editing) { return ( ); } let displayError; if (error) { displayError = ( ); } const height = Platform.OS === 'android' ? (deviceHeight / 2) - 40 : (deviceHeight / 2); const autocompleteStyles = [ style.autocompleteContainer, {flex: autocompleteVisible ? 1 : 0}, ]; return ( {displayError} ); } } const getStyleSheet = makeStyleSheetFromTheme((theme) => { return { container: { flex: 1, }, scrollView: { flex: 1, backgroundColor: changeOpacity(theme.centerChannelColor, 0.03), }, errorContainer: { paddingHorizontal: 10, }, errorWrapper: { alignItems: 'center', }, inputContainer: { borderTopWidth: 1, borderBottomWidth: 1, borderTopColor: changeOpacity(theme.centerChannelColor, 0.1), borderBottomColor: changeOpacity(theme.centerChannelColor, 0.1), backgroundColor: theme.centerChannelBg, marginTop: 2, }, input: { color: theme.centerChannelColor, fontSize: 14, padding: 15, textAlignVertical: 'top', }, autocompleteContainer: { flex: 1, justifyContent: 'flex-end', }, }; });