import React from 'react'; import PropTypes from 'prop-types'; import { Text, View, ScrollView, TouchableOpacity, SafeAreaView, Keyboard, Alert } from 'react-native'; import { connect } from 'react-redux'; import LoggedView from '../View'; import KeyboardView from '../../presentation/KeyboardView'; import sharedStyles from '../Styles'; import styles from './styles'; import scrollPersistTaps from '../../utils/scrollPersistTaps'; import { showErrorAlert, showToast } from '../../utils/info'; import database from '../../lib/realm'; import RocketChat from '../../lib/rocketchat'; import { eraseRoom } from '../../actions/room'; import RCTextInput from '../../containers/TextInput'; import Loading from '../../containers/Loading'; import SwitchContainer from './SwitchContainer'; import random from '../../utils/random'; import log from '../../utils/log'; const PERMISSION_SET_READONLY = 'set-readonly'; const PERMISSION_SET_REACT_WHEN_READONLY = 'set-react-when-readonly'; const PERMISSION_ARCHIVE = 'archive-room'; const PERMISSION_UNARCHIVE = 'unarchive-room'; const PERMISSION_DELETE_C = 'delete-c'; const PERMISSION_DELETE_P = 'delete-p'; const PERMISSIONS_ARRAY = [ PERMISSION_SET_READONLY, PERMISSION_SET_REACT_WHEN_READONLY, PERMISSION_ARCHIVE, PERMISSION_UNARCHIVE, PERMISSION_DELETE_C, PERMISSION_DELETE_P ]; @connect(null, dispatch => ({ eraseRoom: rid => dispatch(eraseRoom(rid)) })) export default class RoomInfoEditView extends LoggedView { static propTypes = { navigation: PropTypes.object, eraseRoom: PropTypes.func }; constructor(props) { super('RoomInfoEditView', props); const { rid } = props.navigation.state.params; this.rooms = database.objects('subscriptions').filtered('rid = $0', rid); this.permissions = {}; this.state = { room: {}, name: '', description: '', topic: '', announcement: '', joinCode: '', nameError: {}, saving: false, t: false, ro: false, reactWhenReadOnly: false }; } async componentDidMount() { await this.updateRoom(); this.init(); this.rooms.addListener(this.updateRoom); this.permissions = RocketChat.hasPermission(PERMISSIONS_ARRAY, this.state.room.rid); } componentWillUnmount() { this.rooms.removeAllListeners(); } updateRoom = async() => { const [room] = this.rooms; await this.setState({ room }); } init = () => { const { name, description, topic, announcement, t, ro, reactWhenReadOnly, joinCodeRequired } = this.state.room; // fake password just to user knows about it this.randomValue = random(15); this.setState({ name, description, topic, announcement, t: t === 'p', ro, reactWhenReadOnly, joinCode: joinCodeRequired ? this.randomValue : '' }); } clearErrors = () => { this.setState({ nameError: {} }); } reset = () => { this.clearErrors(); this.init(); } formIsChanged = () => { const { room, name, description, topic, announcement, t, ro, reactWhenReadOnly, joinCode } = this.state; return !(room.name === name && room.description === description && room.topic === topic && room.announcement === announcement && this.randomValue === joinCode && room.t === 'p' === t && room.ro === ro && room.reactWhenReadOnly === reactWhenReadOnly ); } submit = async() => { Keyboard.dismiss(); const { room, name, description, topic, announcement, t, ro, reactWhenReadOnly, joinCode } = this.state; this.setState({ saving: true }); let error = false; if (!this.formIsChanged()) { showErrorAlert('Nothing to save!'); return; } // Clear error objects await this.clearErrors(); const params = {}; // Name if (room.name !== name) { params.roomName = name; } // Description if (room.description !== description) { params.roomDescription = description; } // Topic if (room.topic !== topic) { params.roomTopic = topic; } // Announcement if (room.announcement !== announcement) { params.roomAnnouncement = announcement; } // Room Type if (room.t !== t) { params.roomType = t ? 'p' : 'c'; } // Read Only if (room.ro !== ro) { params.readOnly = ro; } // React When Read Only if (room.reactWhenReadOnly !== reactWhenReadOnly) { params.reactWhenReadOnly = reactWhenReadOnly; } // Join Code if (this.randomValue !== joinCode) { params.joinCode = joinCode; } try { await RocketChat.saveRoomSettings(room.rid, params); } catch (e) { if (e.error === 'error-invalid-room-name') { this.setState({ nameError: e }); } error = true; log('saveRoomSettings', e); } await this.setState({ saving: false }); setTimeout(() => { if (error) { showErrorAlert('There was an error while saving settings!'); } else { showToast('Settings succesfully changed!'); } }, 100); } delete = () => { Alert.alert( 'Are you sure?', 'Deleting a room will delete all messages posted within the room. This cannot be undone.', [ { text: 'Cancel', style: 'cancel' }, { text: 'Yes, delete it!', style: 'destructive', onPress: () => this.props.eraseRoom(this.state.room.rid) } ], { cancelable: false } ); } toggleArchive = () => { const { archived } = this.state.room; const action = `${ archived ? 'un' : '' }archive`; Alert.alert( 'Are you sure?', `Do you really want to ${ action } this room?`, [ { text: 'Cancel', style: 'cancel' }, { text: `Yes, ${ action } it!`, style: 'destructive', onPress: () => { try { RocketChat.toggleArchiveRoom(this.state.room.rid, !archived); } catch (e) { log('toggleArchive', e); } } } ], { cancelable: false } ); } hasDeletePermission = () => ( this.state.room.t === 'p' ? this.permissions[PERMISSION_DELETE_P] : this.permissions[PERMISSION_DELETE_C] ); hasArchivePermission = () => ( this.permissions[PERMISSION_ARCHIVE] || this.permissions[PERMISSION_UNARCHIVE] ); render() { const { name, nameError, description, topic, announcement, t, ro, reactWhenReadOnly, room, joinCode } = this.state; return ( { this.name = e; }} label='Name' value={name} onChangeText={value => this.setState({ name: value })} onSubmitEditing={() => { this.description.focus(); }} error={nameError} testID='room-info-edit-view-name' /> { this.description = e; }} label='Description' value={description} onChangeText={value => this.setState({ description: value })} onSubmitEditing={() => { this.topic.focus(); }} testID='room-info-edit-view-description' /> { this.topic = e; }} label='Topic' value={topic} onChangeText={value => this.setState({ topic: value })} onSubmitEditing={() => { this.announcement.focus(); }} testID='room-info-edit-view-topic' /> { this.announcement = e; }} label='Announcement' value={announcement} onChangeText={value => this.setState({ announcement: value })} onSubmitEditing={() => { this.joinCode.focus(); }} testID='room-info-edit-view-announcement' /> { this.joinCode = e; }} label='Password' value={joinCode} onChangeText={value => this.setState({ joinCode: value })} onSubmitEditing={this.submit} secureTextEntry testID='room-info-edit-view-password' /> this.setState({ t: value })} testID='room-info-edit-view-t' /> this.setState({ ro: value })} disabled={!this.permissions[PERMISSION_SET_READONLY]} testID='room-info-edit-view-ro' /> {ro && this.setState({ reactWhenReadOnly: value })} disabled={!this.permissions[PERMISSION_SET_REACT_WHEN_READONLY]} testID='room-info-edit-view-react-when-ro' /> } SAVE RESET { room.archived ? 'UNARCHIVE' : 'ARCHIVE' } DELETE ); } }