import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { ScrollView, Text, View, FlatList, SafeAreaView } from 'react-native'; import { connect } from 'react-redux'; import equal from 'deep-equal'; import { Q } from '@nozbe/watermelondb'; import Touch from '../../utils/touch'; import { logout as logoutAction } from '../../actions/login'; import Avatar from '../../containers/Avatar'; import Status from '../../containers/Status/Status'; import RocketChat from '../../lib/rocketchat'; import log from '../../utils/log'; import I18n from '../../i18n'; import scrollPersistTaps from '../../utils/scrollPersistTaps'; import { CustomIcon } from '../../lib/Icons'; import styles from './styles'; import SidebarItem from './SidebarItem'; import { themes } from '../../constants/colors'; import database from '../../lib/database'; import { animateNextTransition } from '../../utils/layoutAnimation'; import { withTheme } from '../../theme'; import { withSplit } from '../../split'; const keyExtractor = item => item.id; const Separator = React.memo(({ theme }) => ); Separator.propTypes = { theme: PropTypes.string }; const permissions = [ 'view-statistics', 'view-room-administration', 'view-user-administration', 'view-privileged-setting' ]; class Sidebar extends Component { static propTypes = { baseUrl: PropTypes.string, navigation: PropTypes.object, Site_Name: PropTypes.string.isRequired, user: PropTypes.object, logout: PropTypes.func.isRequired, activeItemKey: PropTypes.string, theme: PropTypes.string, loadingServer: PropTypes.bool, split: PropTypes.bool } constructor(props) { super(props); this.state = { showStatus: false, isAdmin: false, status: [] }; } componentDidMount() { this.setStatus(); this.setIsAdmin(); } componentWillReceiveProps(nextProps) { const { user, loadingServer } = this.props; if (nextProps.user && user && user.language !== nextProps.user.language) { this.setStatus(); } if (loadingServer && nextProps.loadingServer !== loadingServer) { this.setIsAdmin(); } } shouldComponentUpdate(nextProps, nextState) { const { status, showStatus, isAdmin } = this.state; const { Site_Name, user, baseUrl, activeItemKey, split, theme } = this.props; if (nextState.showStatus !== showStatus) { return true; } if (nextProps.Site_Name !== Site_Name) { return true; } if (nextProps.Site_Name !== Site_Name) { return true; } if (nextProps.baseUrl !== baseUrl) { return true; } if (nextProps.activeItemKey !== activeItemKey) { return true; } if (nextProps.theme !== theme) { return true; } if (nextProps.user && user) { if (nextProps.user.language !== user.language) { return true; } if (nextProps.user.status !== user.status) { return true; } if (nextProps.user.username !== user.username) { return true; } } if (nextProps.split !== split) { return true; } if (!equal(nextState.status, status)) { return true; } if (nextState.isAdmin !== isAdmin) { return true; } return false; } setStatus = () => { this.setState({ status: [{ id: 'online', name: I18n.t('Online') }, { id: 'busy', name: I18n.t('Busy') }, { id: 'away', name: I18n.t('Away') }, { id: 'offline', name: I18n.t('Invisible') }] }); } async setIsAdmin() { const db = database.active; const { user } = this.props; const { roles } = user; try { if (roles) { const permissionsCollection = db.collections.get('permissions'); const permissionsFiltered = await permissionsCollection.query(Q.where('id', Q.oneOf(permissions))).fetch(); const isAdmin = permissionsFiltered.reduce((result, permission) => ( result || permission.roles.some(r => roles.indexOf(r) !== -1)), false); this.setState({ isAdmin }); } } catch (e) { log(e); } } logout = () => { const { logout } = this.props; logout(); } sidebarNavigate = (route) => { const { navigation } = this.props; navigation.navigate(route); } toggleStatus = () => { animateNextTransition(); this.setState(prevState => ({ showStatus: !prevState.showStatus })); } renderStatusItem = ({ item }) => { const { user } = this.props; return ( } current={user.status === item.id} onPress={() => { this.toggleStatus(); if (user.status !== item.id) { try { RocketChat.setUserPresenceDefaultStatus(item.id); } catch (e) { log(e); } } }} /> ); } renderNavigation = () => { const { isAdmin } = this.state; const { activeItemKey, theme } = this.props; return ( <> } onPress={() => this.sidebarNavigate('RoomsListView')} testID='sidebar-chats' current={activeItemKey === 'ChatsStack'} /> } onPress={() => this.sidebarNavigate('ProfileView')} testID='sidebar-profile' current={activeItemKey === 'ProfileStack'} /> } onPress={() => this.sidebarNavigate('SettingsView')} testID='sidebar-settings' current={activeItemKey === 'SettingsStack'} /> {isAdmin ? ( } onPress={() => this.sidebarNavigate('AdminPanelView')} testID='sidebar-settings' current={activeItemKey === 'AdminPanelStack'} /> ) : null} } onPress={this.logout} testID='sidebar-logout' /> ); } renderStatus = () => { const { status } = this.state; const { user } = this.props; return ( ); } render() { const { showStatus } = this.state; const { user, Site_Name, baseUrl, split, theme } = this.props; if (!user) { return null; } return ( {user.username} {Site_Name} {!split || showStatus ? : null} {!showStatus && !split ? this.renderNavigation() : null} {showStatus ? this.renderStatus() : null} ); } } const mapStateToProps = state => ({ Site_Name: state.settings.Site_Name, user: { id: state.login.user && state.login.user.id, language: state.login.user && state.login.user.language, status: state.login.user && state.login.user.status, username: state.login.user && state.login.user.username, token: state.login.user && state.login.user.token, roles: state.login.user && state.login.user.roles }, baseUrl: state.settings.Site_Url || state.server ? state.server.server : '', loadingServer: state.server.loading }); const mapDispatchToProps = dispatch => ({ logout: () => dispatch(logoutAction()) }); export default connect(mapStateToProps, mapDispatchToProps)(withTheme(withSplit(Sidebar)));