Rocket.Chat.ReactNative/app/containers/MessageBox/UploadModal.js

256 lines
6.3 KiB
JavaScript
Raw Normal View History

import React, { Component } from 'react';
import {
2019-01-29 19:52:56 +00:00
View, Text, StyleSheet, Image, ScrollView, TouchableHighlight
} from 'react-native';
import PropTypes from 'prop-types';
import Modal from 'react-native-modal';
import { responsive } from 'react-native-responsive-ui';
import equal from 'deep-equal';
import TextInput from '../TextInput';
import Button from '../Button';
import I18n from '../../i18n';
2018-11-19 18:18:15 +00:00
import sharedStyles from '../../views/Styles';
2019-12-04 16:39:53 +00:00
import { isIOS } from '../../utils/deviceInfo';
import { themes } from '../../constants/colors';
2019-07-18 17:07:37 +00:00
import { CustomIcon } from '../../lib/Icons';
2019-12-04 16:39:53 +00:00
import { withTheme } from '../../theme';
2019-11-25 20:01:17 +00:00
import { withSplit } from '../../split';
const styles = StyleSheet.create({
2018-11-19 18:18:15 +00:00
modal: {
2019-11-25 20:01:17 +00:00
width: '100%',
alignItems: 'center',
margin: 0
2018-11-19 18:18:15 +00:00
},
titleContainer: {
flexDirection: 'row',
paddingHorizontal: 16,
paddingTop: 16
},
title: {
2019-03-29 19:36:07 +00:00
fontSize: 14,
2018-11-19 18:18:15 +00:00
...sharedStyles.textBold
},
container: {
2018-11-19 18:18:15 +00:00
height: 430,
flexDirection: 'column'
},
scrollView: {
flex: 1,
padding: 16
},
image: {
height: 150,
flex: 1,
marginBottom: 16,
resizeMode: 'contain'
},
2019-11-25 20:01:17 +00:00
bigPreview: {
height: 250
},
buttonContainer: {
flexDirection: 'row',
justifyContent: 'space-between',
2019-12-04 16:39:53 +00:00
padding: 16
},
2018-11-19 18:18:15 +00:00
button: {
marginBottom: 0
},
androidButton: {
paddingHorizontal: 15,
justifyContent: 'center',
height: 48,
borderRadius: 2
},
androidButtonText: {
fontSize: 18,
textAlign: 'center'
2019-07-18 17:07:37 +00:00
},
fileIcon: {
margin: 20,
flex: 1,
textAlign: 'center'
},
video: {
flex: 1,
borderRadius: 4,
height: 150,
marginBottom: 6,
alignItems: 'center',
justifyContent: 'center'
}
2018-11-19 18:18:15 +00:00
});
class UploadModal extends Component {
static propTypes = {
isVisible: PropTypes.bool,
file: PropTypes.object,
close: PropTypes.func,
submit: PropTypes.func,
2019-11-25 20:01:17 +00:00
window: PropTypes.object,
2019-12-04 16:39:53 +00:00
theme: PropTypes.string,
2019-11-25 20:01:17 +00:00
split: PropTypes.bool
}
state = {
name: '',
description: '',
file: {}
};
static getDerivedStateFromProps(props, state) {
if (!equal(props.file, state.file) && props.file && props.file.path) {
return {
file: props.file,
name: props.file.filename || 'Filename',
description: ''
};
}
return null;
}
shouldComponentUpdate(nextProps, nextState) {
const { name, description, file } = this.state;
2019-12-04 16:39:53 +00:00
const {
window, isVisible, split, theme
} = this.props;
if (nextState.name !== name) {
return true;
}
2019-11-25 20:01:17 +00:00
if (nextProps.split !== split) {
return true;
}
2019-12-04 16:39:53 +00:00
if (nextProps.theme !== theme) {
return true;
}
if (nextState.description !== description) {
return true;
}
if (nextProps.isVisible !== isVisible) {
return true;
}
if (nextProps.window.width !== window.width) {
return true;
}
if (!equal(nextState.file, file)) {
return true;
}
return false;
}
2018-11-19 18:18:15 +00:00
submit = () => {
const { file, submit } = this.props;
const { name, description } = this.state;
submit({ ...file, name, description });
}
2018-11-19 18:18:15 +00:00
renderButtons = () => {
2019-12-04 16:39:53 +00:00
const { close, theme } = this.props;
2019-01-29 19:52:56 +00:00
if (isIOS) {
2018-11-19 18:18:15 +00:00
return (
2019-12-04 16:39:53 +00:00
<View style={[styles.buttonContainer, { backgroundColor: themes[theme].auxiliaryBackground }]}>
2018-11-19 18:18:15 +00:00
<Button
title={I18n.t('Cancel')}
type='secondary'
2019-12-04 16:39:53 +00:00
backgroundColor={themes[theme].chatComponentBackground}
2018-11-19 18:18:15 +00:00
style={styles.button}
onPress={close}
2019-12-04 16:39:53 +00:00
theme={theme}
2018-11-19 18:18:15 +00:00
/>
<Button
title={I18n.t('Send')}
type='primary'
style={styles.button}
onPress={this.submit}
2019-12-04 16:39:53 +00:00
theme={theme}
2018-11-19 18:18:15 +00:00
/>
</View>
);
}
// FIXME: RNGH don't work well on Android modals: https://github.com/kmagiera/react-native-gesture-handler/issues/139
return (
2019-12-04 16:39:53 +00:00
<View style={[styles.buttonContainer, { backgroundColor: themes[theme].auxiliaryBackground }]}>
2018-11-19 18:18:15 +00:00
<TouchableHighlight
onPress={close}
2019-12-04 16:39:53 +00:00
style={[styles.androidButton, { backgroundColor: themes[theme].chatComponentBackground }]}
underlayColor={themes[theme].chatComponentBackground}
2018-11-19 18:18:15 +00:00
activeOpacity={0.5}
>
2019-12-04 16:39:53 +00:00
<Text style={[styles.androidButtonText, { ...sharedStyles.textBold, color: themes[theme].tintColor }]}>{I18n.t('Cancel')}</Text>
2018-11-19 18:18:15 +00:00
</TouchableHighlight>
<TouchableHighlight
onPress={this.submit}
2019-12-04 16:39:53 +00:00
style={[styles.androidButton, { backgroundColor: themes[theme].tintColor }]}
underlayColor={themes[theme].tintColor}
2018-11-19 18:18:15 +00:00
activeOpacity={0.5}
>
2019-12-04 16:39:53 +00:00
<Text style={[styles.androidButtonText, { ...sharedStyles.textMedium, color: themes[theme].buttonText }]}>{I18n.t('Send')}</Text>
2018-11-19 18:18:15 +00:00
</TouchableHighlight>
</View>
);
}
2019-07-18 17:07:37 +00:00
renderPreview() {
2019-12-04 16:39:53 +00:00
const { file, split, theme } = this.props;
2019-07-18 17:07:37 +00:00
if (file.mime && file.mime.match(/image/)) {
2019-11-25 20:01:17 +00:00
return (<Image source={{ isStatic: true, uri: file.path }} style={[styles.image, split && styles.bigPreview]} />);
2019-07-18 17:07:37 +00:00
}
if (file.mime && file.mime.match(/video/)) {
return (
2019-12-04 16:39:53 +00:00
<View style={[styles.video, { backgroundColor: themes[theme].bannerBackground }]}>
<CustomIcon name='play' size={72} color={themes[theme].buttonText} />
2019-07-18 17:07:37 +00:00
</View>
);
}
2019-12-04 16:39:53 +00:00
return (<CustomIcon name='file-generic' size={72} style={[styles.fileIcon, { color: themes[theme].tintColor }]} />);
2019-07-18 17:07:37 +00:00
}
render() {
const {
2019-12-04 16:39:53 +00:00
window: { width }, isVisible, close, split, theme
} = this.props;
2019-07-18 17:07:37 +00:00
const { name, description } = this.state;
return (
<Modal
isVisible={isVisible}
2018-11-19 18:18:15 +00:00
style={styles.modal}
onBackdropPress={close}
onBackButtonPress={close}
animationIn='fadeIn'
animationOut='fadeOut'
useNativeDriver
hideModalContentWhileAnimating
avoidKeyboard
>
2019-12-04 16:39:53 +00:00
<View style={[styles.container, { width: width - 32, backgroundColor: themes[theme].chatComponentBackground }, split && sharedStyles.modal]}>
2019-09-24 20:16:59 +00:00
<View style={styles.titleContainer}>
2019-12-04 16:39:53 +00:00
<Text style={[styles.title, { color: themes[theme].titleText }]}>{I18n.t('Upload_file_question_mark')}</Text>
2019-09-24 20:16:59 +00:00
</View>
<ScrollView style={styles.scrollView}>
{this.renderPreview()}
<TextInput
placeholder={I18n.t('File_name')}
value={name}
onChangeText={value => this.setState({ name: value })}
2019-12-04 16:39:53 +00:00
theme={theme}
2019-09-24 20:16:59 +00:00
/>
<TextInput
placeholder={I18n.t('File_description')}
value={description}
onChangeText={value => this.setState({ description: value })}
2019-12-04 16:39:53 +00:00
theme={theme}
2019-09-24 20:16:59 +00:00
/>
</ScrollView>
{this.renderButtons()}
</View>
</Modal>
);
}
}
2019-12-04 16:39:53 +00:00
export default responsive(withTheme(withSplit(UploadModal)));