import React from 'react'; import PropTypes from 'prop-types'; import { ScrollView, Text, View } from 'react-native'; import { BorderlessButton } from 'react-native-gesture-handler'; import { connect } from 'react-redux'; import UAParser from 'ua-parser-js'; import isEmpty from 'lodash/isEmpty'; import { CustomIcon } from '../../lib/Icons'; import Status from '../../containers/Status'; import Avatar from '../../containers/Avatar'; import sharedStyles from '../Styles'; import RocketChat from '../../lib/rocketchat'; import RoomTypeIcon from '../../containers/RoomTypeIcon'; import I18n from '../../i18n'; import * as HeaderButton from '../../containers/HeaderButton'; import StatusBar from '../../containers/StatusBar'; import log, { events, logEvent } from '../../utils/log'; import { themes } from '../../constants/colors'; import { withTheme } from '../../theme'; import Markdown from '../../containers/markdown'; import { LISTENER } from '../../containers/Toast'; import EventEmitter from '../../utils/events'; import SafeAreaView from '../../containers/SafeAreaView'; import { goRoom } from '../../utils/goRoom'; import Navigation from '../../lib/Navigation'; import Livechat from './Livechat'; import Channel from './Channel'; import Direct from './Direct'; import styles from './styles'; const getRoomTitle = (room, type, name, username, statusText, theme) => type === 'd' ? ( <> {name} {username && ( {`@${username}`} )} {!!statusText && ( )} ) : ( {RocketChat.getRoomTitle(room)} ); class RoomInfoView extends React.Component { static propTypes = { navigation: PropTypes.object, route: PropTypes.object, rooms: PropTypes.array, theme: PropTypes.string, isMasterDetail: PropTypes.bool, jitsiEnabled: PropTypes.bool, editRoomPermission: PropTypes.array, editOmnichannelContact: PropTypes.array, editLivechatRoomCustomfields: PropTypes.array, roles: PropTypes.array }; constructor(props) { super(props); const room = props.route.params?.room; const roomUser = props.route.params?.member; this.rid = props.route.params?.rid; this.t = props.route.params?.t; this.state = { room: room || { rid: this.rid, t: this.t }, roomUser: roomUser || {}, showEdit: false }; } componentDidMount() { if (this.isDirect) { this.loadUser(); } else { this.loadRoom(); } this.setHeader(); const { navigation } = this.props; this.unsubscribeFocus = navigation.addListener('focus', () => { if (this.isLivechat) { this.loadVisitor(); } }); } componentWillUnmount() { if (this.subscription && this.subscription.unsubscribe) { this.subscription.unsubscribe(); } if (this.unsubscribeFocus) { this.unsubscribeFocus(); } } setHeader = () => { const { roomUser, room, showEdit } = this.state; const { navigation, route } = this.props; const t = route.params?.t; const rid = route.params?.rid; const showCloseModal = route.params?.showCloseModal; navigation.setOptions({ headerLeft: showCloseModal ? () => : undefined, title: t === 'd' ? I18n.t('User_Info') : I18n.t('Room_Info'), headerRight: showEdit ? () => ( { const isLivechat = t === 'l'; logEvent(events[`RI_GO_${isLivechat ? 'LIVECHAT' : 'RI'}_EDIT`]); navigation.navigate(isLivechat ? 'LivechatEditView' : 'RoomInfoEditView', { rid, room, roomUser }); }} testID='room-info-view-edit-button' /> ) : null }); }; get isDirect() { const { room } = this.state; return room.t === 'd'; } get isLivechat() { const { room } = this.state; return room.t === 'l'; } getRoleDescription = id => { const { roles } = this.props; return roles[id]; }; loadVisitor = async () => { const { room } = this.state; try { const result = await RocketChat.getVisitorInfo(room?.visitor?._id); if (result.success) { const { visitor } = result; if (visitor.userAgent) { const ua = new UAParser(); ua.setUA(visitor.userAgent); visitor.os = `${ua.getOS().name} ${ua.getOS().version}`; visitor.browser = `${ua.getBrowser().name} ${ua.getBrowser().version}`; } this.setState({ roomUser: visitor }, () => this.setHeader()); } } catch (error) { // Do nothing } }; parseRoles = roleArray => Promise.all( roleArray.map(async role => { const description = await this.getRoleDescription(role); return description; }) ); loadUser = async () => { const { room, roomUser } = this.state; if (isEmpty(roomUser)) { try { const roomUserId = RocketChat.getUidDirectMessage(room); const result = await RocketChat.getUserInfo(roomUserId); if (result.success) { const { user } = result; const { roles } = user; if (roles && roles.length) { user.parsedRoles = await this.parseRoles(roles); } this.setState({ roomUser: user }); } } catch { // do nothing } } else { try { const { roles } = roomUser; if (roles && roles.length) { const parsedRoles = await this.parseRoles(roles); this.setState({ roomUser: { ...roomUser, parsedRoles } }); } else { this.setState({ roomUser }); } } catch (e) { // do nothing } } }; loadRoom = async () => { const { room: roomState } = this.state; const { route, editRoomPermission, editOmnichannelContact, editLivechatRoomCustomfields } = this.props; let room = route.params?.room; if (room && room.observe) { this.roomObservable = room.observe(); this.subscription = this.roomObservable.subscribe(changes => { this.setState({ room: changes }, () => this.setHeader()); }); } else { try { const result = await RocketChat.getRoomInfo(this.rid); if (result.success) { ({ room } = result); this.setState({ room: { ...roomState, ...room } }); } } catch (e) { log(e); } } const permissionToEdit = this.isLivechat ? [editOmnichannelContact, editLivechatRoomCustomfields] : [editRoomPermission]; const permissions = await RocketChat.hasPermission(permissionToEdit, room.rid); if (permissions.some(Boolean)) { this.setState({ showEdit: true }, () => this.setHeader()); } }; createDirect = () => new Promise(async (resolve, reject) => { const { route } = this.props; // We don't need to create a direct const member = route.params?.member; if (!isEmpty(member)) { return resolve(); } // TODO: Check if some direct with the user already exists on database try { const { roomUser: { username } } = this.state; const result = await RocketChat.createDirectMessage(username); if (result.success) { const { room: { rid } } = result; return this.setState(({ room }) => ({ room: { ...room, rid } }), resolve); } } catch { // do nothing } reject(); }); goRoom = () => { logEvent(events.RI_GO_ROOM_USER); const { roomUser, room } = this.state; const { name, username } = roomUser; const { rooms, navigation, isMasterDetail } = this.props; const params = { rid: room.rid, name: RocketChat.getRoomTitle({ t: room.t, fname: name, name: username }), t: room.t, roomUserId: RocketChat.getUidDirectMessage(room) }; if (room.rid) { // if it's on master detail layout, we close the modal and replace RoomView if (isMasterDetail) { Navigation.navigate('DrawerNavigator'); goRoom({ item: params, isMasterDetail }); } else { let navigate = navigation.push; // if this is a room focused if (rooms.includes(room.rid)) { ({ navigate } = navigation); } navigate('RoomView', params); } } }; videoCall = () => { const { room } = this.state; RocketChat.callJitsi(room); }; renderAvatar = (room, roomUser) => { const { theme } = this.props; return ( {this.t === 'd' && roomUser._id ? ( ) : null} ); }; renderButton = (onPress, iconName, text) => { const { theme } = this.props; const onActionPress = async () => { try { if (this.isDirect) { await this.createDirect(); } onPress(); } catch { EventEmitter.emit(LISTENER, { message: I18n.t('error-action-not-allowed', { action: I18n.t('Create_Direct_Messages') }) }); } }; return ( {text} ); }; renderButtons = () => { const { jitsiEnabled } = this.props; return ( {this.renderButton(this.goRoom, 'message', I18n.t('Message'))} {jitsiEnabled && this.isDirect ? this.renderButton(this.videoCall, 'camera', I18n.t('Video_call')) : null} ); }; renderContent = () => { const { room, roomUser } = this.state; const { theme } = this.props; if (this.isDirect) { return ; } else if (this.t === 'l') { return ; } return ; }; render() { const { room, roomUser } = this.state; const { theme } = this.props; return ( {this.renderAvatar(room, roomUser)} {getRoomTitle(room, this.t, roomUser?.name, roomUser?.username, roomUser?.statusText, theme)} {this.renderButtons()} {this.renderContent()} ); } } const mapStateToProps = state => ({ rooms: state.room.rooms, isMasterDetail: state.app.isMasterDetail, jitsiEnabled: state.settings.Jitsi_Enabled || false, editRoomPermission: state.permissions['edit-room'], editOmnichannelContact: state.permissions['edit-omnichannel-contact'], editLivechatRoomCustomfields: state.permissions['edit-livechat-room-customfields'], roles: state.roles }); export default connect(mapStateToProps)(withTheme(RoomInfoView));