verdnatura-chat/app/views/ShareView/index.js

246 lines
6.4 KiB
JavaScript
Raw Normal View History

[RELEASE] Merge beta into master (#1082) * Bump version to 1.16.0 (#1014) * [IMPROVEMENT] Share credentials with Rocket.Chat.iOS (#982) * :sparkles: Create user table * :sparkles: Introduce user table * :fire: Remove unused table * :heavy_plus_sign: Add userdefaults to storage data * :green_heart: Fix android build * :sparkles: Get credentials from iOS native client * :fire: Remove unused code * :rewind: Revert sign xcode * :bug: Fix first login-logout * :art: Use constants to UserDefaults Keys * :bug: Fix clear server-user-info on logout * :bug: Fix filter null value * :ambulance: Remove user object in logout * :sparkles: Fix get servers from native-client * :ambulance: Fix error on change server * [FIX] Don't run UserDefaults credentials on Android (#1015) * :bug: Fix native credentials (android) * Fix migration loop * [IMPROVEMENT] Hide frequently used emoji tab when empty (#792) * [IMPROVEMENT] Bigger emoji in emoji only messages (#793) * issue #725: bigger emoji in emoji only message * issue-725/add storybook for Message/Emoji * issue-725: update storybook/Message jest snapshot * comment storybook import * allow spaces and line breaks in emoji only message * merge develop * revert unnecessary spacing * [FIX] Empty message if contains only a link (#787) * Fix empty message if contains only a link * :bug: Fix empty space * [IMPROVEMENT] Refactor empty space regex on quote (#1017) * :art: Improve regex to empty space on quote * :art: Improve on regex to empty space on quote * [NEW] Custom fields on signup (#1013) * added custom feilds on registration * added flag as leftIcon and removed lable * added try and catch * typo * [CHORE] Renew provisioning profiles (#1020) * [NEW] Auto-translate (#1012) * Update realm * View original and translate working * Read AutoTranslate_Enabled setting * RocketChat.canAutoTranslate() * AutoTranslateView * Save language * Auto-translate switch * Translate message * [IMPROVEMENT] Use haptics rather than vibration (#1016) * Install expo-haptics * Use expo-haptics rather than RN's Vibration module * [IMPROVEMENT] Use Rest API for file upload (#1005) * removed rn-fetch-blob and use native XMLHttpRequest instead * removed unnessary changes * fix android bug * fix android bug * added tmid support * fix bug * fixed isssue with cacel model * fix problems with audio * done requested changes * fix bug with android * [CHORE] [CI] [TESTS] update detox to make ci pass (#1026) * feat: update detox to 12.11.3 to make CI pass * ci: comment all jobs but leave e2e-test job * commit to rerun IC e2e-test job * ci: uncomment all CI jobs * [NEW] Room swipe actions: mark as read/unread, hide, fav (#976) * added unread and fav feature * changed the layout * fix jest * done requested changes * added requested changes * [FIX] Android build (#1027) * [FIX] Android build * CircleCI error * [FIX] iOS share credentials build (#1028) * [FIX] iOS share credentials build * Use `hasMigration` as a string * [CI] Restore cache on CI (#1029) * feat: add fastlane save\restore cache config; comment not needed jobs; * install fastlane using 'bundle install' * install fastlane using 'sudo bundle install' * uncomment ios build commands * run set up google services in ios folder * add working_directory: ios to ios-build steps * remove 'cd ios' from Fastlane build step * add save\restore cache for npm modules * group save_cache steps * cache fastlane in ios-testflight job * uncomment previously commented jobs\steps * fix: add missing colon * use key for caching: node-modules-{{ checksum ".circleci/config.yml" }}-{{ checksum "yarn.lock" }} * add names for save\restore steps * ci: add `default` step with `working_directory: ~/repo` to ios-build job * return back caching npm: `node-v1-{{ checksum "package.json" }}-{{ arch }}` * fix: add missing curly braces * save\restore cache in e2e-test job; remove {{arch}} from cache names * add names to restore_cache steps in android-build job * add names to save_cache steps in android-build job * add names to all save\restore steps; change checksum package.json to yarn.lock * change `npm` to `NPM` in steps naming * remove {{ checksum circle ci }} from android-build job and fix naming of steps * [FIX] Rooms swipes (#1034) * Regression: on press style feedback * Action button styles * Fix animations * Styles changed * Update subscription without having to wait for socket * Calculate width on RoomsListView instead * [FIX] Decrease bigger emoji size to 30 (#1031) * [FIX] Append server URL on avatar if necessary (#1038) * Comment removeClippedSubviews * Comment width animation * Remove redux from RoomItem * Fix wrong re-render comparison * Remove listener * Raise minDeltaX * memo actions * Spring with native driver * Refactor functions * Fix props issues * Remove RoomItem.height * Long swipe * Refactor animations * this.rowTranslation -> this.transX * Moved state to this * Bump version to 1.16.1 (#1045) * [FIX] Set UserDefaults AppGroup on notification tap (#1047) * [FIX] Auto-translate messages as they arrive * Fix favorite button * [FIX] Swipe animations (#1044) * Comment removeClippedSubviews * Comment width animation * Remove redux from RoomItem * Fix wrong re-render comparison * Remove listener * Raise minDeltaX * memo actions * Spring with native driver * Refactor functions * Fix props issues * Remove RoomItem.height * Long swipe * Refactor animations * this.rowTranslation -> this.transX * Moved state to this * Fix favorite button * [FIX] Auto-translate messages as they arrive (#1049) * Comment removeClippedSubviews * Comment width animation * Remove redux from RoomItem * Fix wrong re-render comparison * Remove listener * Raise minDeltaX * memo actions * Spring with native driver * Refactor functions * Fix props issues * Remove RoomItem.height * Long swipe * Refactor animations * this.rowTranslation -> this.transX * Moved state to this * [FIX] Auto-translate messages as they arrive * [i18n] Add missing de translations (#1040) * [CHORE] Switch to react-native-localize (#1043) * Bump version to 1.17.0 (#1057) * Load views as needed (#1056) * [IMPROVEMENT] Change "resend" icon position (#1048) * [NEW] Video support (#801) * [NEW] File upload (#882) * [NEW] Share extension (#942) * [FIX] Share extension CI build (#1060) * Change bundleID * Provisioning * get provisioning profile * [IMPROVEMENT] Reusable toast (#1065) * [FIX] Moment locales (#1066) * [FIX] Share Extension issues (#1064) * [FIX] Empty white list enables all media types upload (#1077) * Merge branch 'master' into develop (#1079) * [FIX] Empty white list enables all media types upload (#1080) * Create utils to media (canUpload) * Fix variable name * [CHORE] Update README (#1081)
2019-07-29 20:44:39 +00:00
import React from 'react';
import PropTypes from 'prop-types';
import {
View, Text, TextInput, Image
} from 'react-native';
import { connect } from 'react-redux';
import ShareExtension from 'rn-extensions-share';
import {
COLOR_TEXT_DESCRIPTION
} from '../../constants/colors';
import I18n from '../../i18n';
import RocketChat from '../../lib/rocketchat';
import { CustomIcon } from '../../lib/Icons';
import log from '../../utils/log';
import styles from './styles';
import Loading from './Loading';
import database from '../../lib/realm';
import { CustomHeaderButtons, Item } from '../../containers/HeaderButton';
import { isReadOnly, isBlocked } from '../../utils/room';
@connect(({ share }) => ({
user: {
id: share.user && share.user.id,
username: share.user && share.user.username,
token: share.user && share.user.token
},
baseUrl: share ? share.server : ''
}))
export default class ShareView extends React.Component {
static navigationOptions = ({ navigation }) => {
const canSend = navigation.getParam('canSend', true);
return ({
title: I18n.t('Share'),
headerRight:
canSend
? (
<CustomHeaderButtons>
<Item
title={I18n.t('Send')}
onPress={navigation.getParam('sendMessage')}
testID='send-message-share-view'
buttonStyle={styles.send}
/>
</CustomHeaderButtons>
)
: null
});
}
static propTypes = {
navigation: PropTypes.object,
user: PropTypes.shape({
id: PropTypes.string.isRequired,
username: PropTypes.string.isRequired,
token: PropTypes.string.isRequired
}),
baseUrl: PropTypes.string.isRequired
};
constructor(props) {
super(props);
const { navigation } = this.props;
const rid = navigation.getParam('rid', '');
const name = navigation.getParam('name', '');
const value = navigation.getParam('value', '');
const isMedia = navigation.getParam('isMedia', false);
const fileInfo = navigation.getParam('fileInfo', {});
this.rooms = database.objects('subscriptions').filtered('rid = $0', rid);
this.state = {
rid,
value,
isMedia,
name,
fileInfo,
loading: false,
room: this.rooms[0] || { rid },
file: {
name: fileInfo ? fileInfo.name : '',
description: ''
}
};
}
componentDidMount() {
const { room } = this.state;
const { navigation, user } = this.props;
const { username } = user;
navigation.setParams({ sendMessage: this._sendMessage, canSend: !(isReadOnly(room, { username }) || isBlocked(room)) });
}
bytesToSize = bytes => `${ (bytes / 1048576).toFixed(2) }MB`;
_sendMessage = async() => {
const { isMedia } = this.state;
this.setState({ loading: true });
if (isMedia) {
await this.sendMediaMessage();
} else {
await this.sendTextMessage();
}
this.setState({ loading: false });
ShareExtension.close();
}
sendMediaMessage = async() => {
const { rid, fileInfo, file } = this.state;
const { baseUrl: server, user } = this.props;
const { name, description } = file;
const fileMessage = { ...fileInfo, name, description };
if (fileInfo && rid !== '') {
try {
await RocketChat.sendFileMessage(rid, fileMessage, undefined, server, user);
} catch (e) {
log('err_send_media_message', e);
}
}
}
sendTextMessage = async() => {
const { value, rid } = this.state;
const { user } = this.props;
if (value !== '' && rid !== '') {
try {
await RocketChat.sendMessage(rid, value, undefined, user);
} catch (error) {
log('err_share_extension_send_message', error);
}
}
};
renderPreview = () => {
const { fileInfo } = this.state;
const icon = fileInfo.mime.match(/image/)
? <Image source={{ isStatic: true, uri: fileInfo.path }} style={styles.mediaImage} />
: (
<View style={styles.mediaIconContainer}>
<CustomIcon name='file-generic' style={styles.mediaIcon} />
</View>
);
return (
<View style={styles.mediaContent}>
{icon}
<View style={styles.mediaInfo}>
<Text style={styles.mediaText} numberOfLines={1}>{fileInfo.name}</Text>
<Text style={styles.mediaText}>{this.bytesToSize(fileInfo.size)}</Text>
</View>
</View>
);
};
renderMediaContent = () => {
const { fileInfo, file } = this.state;
return fileInfo ? (
<View style={styles.mediaContainer}>
{this.renderPreview()}
<View style={styles.mediaInputContent}>
<TextInput
style={[styles.mediaNameInput, styles.input]}
placeholder={I18n.t('File_name')}
onChangeText={name => this.setState({ file: { ...file, name } })}
underlineColorAndroid='transparent'
defaultValue={file.name}
placeholderTextColor={COLOR_TEXT_DESCRIPTION}
/>
<TextInput
style={[styles.mediaDescriptionInput, styles.input]}
placeholder={I18n.t('File_description')}
onChangeText={description => this.setState({ file: { ...file, description } })}
underlineColorAndroid='transparent'
defaultValue={file.description}
multiline
textAlignVertical='top'
placeholderTextColor={COLOR_TEXT_DESCRIPTION}
autoFocus
/>
</View>
</View>
) : null;
};
renderInput = () => {
const { value } = this.state;
return (
<TextInput
style={[styles.input, styles.textInput]}
placeholder=''
onChangeText={handleText => this.setState({ value: handleText })}
underlineColorAndroid='transparent'
defaultValue={value}
multiline
textAlignVertical='top'
placeholderTextColor={COLOR_TEXT_DESCRIPTION}
autoFocus
/>
);
}
renderError = () => {
const { room } = this.state;
return (
<View style={[styles.container, styles.centered]}>
<Text style={styles.title}>
{
isBlocked(room) ? I18n.t('This_room_is_blocked') : I18n.t('This_room_is_read_only')
}
</Text>
</View>
);
}
render() {
const { user } = this.props;
const { username } = user;
const {
name, loading, isMedia, room
} = this.state;
if (isReadOnly(room, { username }) || isBlocked(room)) {
return this.renderError();
}
return (
<View style={styles.container}>
<View style={isMedia ? styles.toContent : styles.toContentText}>
<Text style={styles.text} numberOfLines={1}>
<Text style={styles.to}>{`${ I18n.t('To') }: `}</Text>
<Text style={styles.name}>{`${ name }`}</Text>
</Text>
</View>
<View style={styles.content}>
{isMedia ? this.renderMediaContent() : this.renderInput()}
</View>
{ loading ? <Loading /> : null }
</View>
);
}
}