2019-03-12 16:23:06 +00:00
|
|
|
import React, { Component } from 'react';
|
|
|
|
import PropTypes from 'prop-types';
|
|
|
|
import {
|
2019-10-02 12:18:08 +00:00
|
|
|
ScrollView, Text, View, FlatList, SafeAreaView
|
2019-03-12 16:23:06 +00:00
|
|
|
} from 'react-native';
|
|
|
|
import { connect } from 'react-redux';
|
|
|
|
import equal from 'deep-equal';
|
2019-09-16 20:26:32 +00:00
|
|
|
import { Q } from '@nozbe/watermelondb';
|
2019-03-12 16:23:06 +00:00
|
|
|
|
2019-12-04 16:39:53 +00:00
|
|
|
import Touch from '../../utils/touch';
|
2019-03-12 16:23:06 +00:00
|
|
|
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';
|
2019-12-04 16:39:53 +00:00
|
|
|
import { themes } from '../../constants/colors';
|
2019-09-16 20:26:32 +00:00
|
|
|
import database from '../../lib/database';
|
2019-09-19 13:32:24 +00:00
|
|
|
import { animateNextTransition } from '../../utils/layoutAnimation';
|
2019-12-04 16:39:53 +00:00
|
|
|
import { withTheme } from '../../theme';
|
2019-11-25 20:01:17 +00:00
|
|
|
import { withSplit } from '../../split';
|
2020-02-11 14:09:14 +00:00
|
|
|
import { getUserSelector } from '../../selectors/login';
|
2019-03-12 16:23:06 +00:00
|
|
|
|
|
|
|
const keyExtractor = item => item.id;
|
|
|
|
|
2019-12-04 16:39:53 +00:00
|
|
|
const Separator = React.memo(({ theme }) => <View style={[styles.separator, { borderColor: themes[theme].separatorColor }]} />);
|
|
|
|
Separator.propTypes = {
|
|
|
|
theme: PropTypes.string
|
|
|
|
};
|
2019-03-12 16:23:06 +00:00
|
|
|
|
2019-05-18 19:31:33 +00:00
|
|
|
const permissions = [
|
|
|
|
'view-statistics',
|
|
|
|
'view-room-administration',
|
|
|
|
'view-user-administration',
|
|
|
|
'view-privileged-setting'
|
|
|
|
];
|
|
|
|
|
2019-08-07 13:51:34 +00:00
|
|
|
class Sidebar extends Component {
|
2019-03-12 16:23:06 +00:00
|
|
|
static propTypes = {
|
|
|
|
baseUrl: PropTypes.string,
|
|
|
|
navigation: PropTypes.object,
|
|
|
|
Site_Name: PropTypes.string.isRequired,
|
|
|
|
user: PropTypes.object,
|
2019-09-24 20:10:50 +00:00
|
|
|
activeItemKey: PropTypes.string,
|
2019-12-04 16:39:53 +00:00
|
|
|
theme: PropTypes.string,
|
2019-11-25 20:01:17 +00:00
|
|
|
loadingServer: PropTypes.bool,
|
2020-02-21 16:13:05 +00:00
|
|
|
useRealName: PropTypes.bool,
|
2019-11-25 20:01:17 +00:00
|
|
|
split: PropTypes.bool
|
2019-03-12 16:23:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
constructor(props) {
|
|
|
|
super(props);
|
|
|
|
this.state = {
|
|
|
|
showStatus: false,
|
2019-09-16 20:26:32 +00:00
|
|
|
isAdmin: false,
|
2019-03-12 16:23:06 +00:00
|
|
|
status: []
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
componentDidMount() {
|
|
|
|
this.setStatus();
|
2019-09-16 20:26:32 +00:00
|
|
|
this.setIsAdmin();
|
2019-03-12 16:23:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
componentWillReceiveProps(nextProps) {
|
2019-09-24 20:10:50 +00:00
|
|
|
const { user, loadingServer } = this.props;
|
2019-03-12 16:23:06 +00:00
|
|
|
if (nextProps.user && user && user.language !== nextProps.user.language) {
|
|
|
|
this.setStatus();
|
|
|
|
}
|
2019-09-24 20:10:50 +00:00
|
|
|
if (loadingServer && nextProps.loadingServer !== loadingServer) {
|
|
|
|
this.setIsAdmin();
|
|
|
|
}
|
2019-03-12 16:23:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
shouldComponentUpdate(nextProps, nextState) {
|
2019-09-24 20:10:50 +00:00
|
|
|
const { status, showStatus, isAdmin } = this.state;
|
2019-03-12 16:23:06 +00:00
|
|
|
const {
|
2020-02-21 16:13:05 +00:00
|
|
|
Site_Name, user, baseUrl, activeItemKey, split, useRealName, theme
|
2019-03-12 16:23:06 +00:00
|
|
|
} = 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;
|
|
|
|
}
|
2019-12-04 16:39:53 +00:00
|
|
|
if (nextProps.theme !== theme) {
|
|
|
|
return true;
|
|
|
|
}
|
2019-03-12 16:23:06 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
2019-11-25 20:01:17 +00:00
|
|
|
if (nextProps.split !== split) {
|
|
|
|
return true;
|
|
|
|
}
|
2020-02-21 16:13:05 +00:00
|
|
|
if (nextProps.useRealName !== useRealName) {
|
|
|
|
return true;
|
|
|
|
}
|
2019-03-12 16:23:06 +00:00
|
|
|
if (!equal(nextState.status, status)) {
|
|
|
|
return true;
|
|
|
|
}
|
2019-09-24 20:10:50 +00:00
|
|
|
if (nextState.isAdmin !== isAdmin) {
|
|
|
|
return true;
|
|
|
|
}
|
2019-03-12 16:23:06 +00:00
|
|
|
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')
|
|
|
|
}]
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-09-16 20:26:32 +00:00
|
|
|
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);
|
|
|
|
}
|
2019-03-12 16:23:06 +00:00
|
|
|
}
|
|
|
|
|
2019-09-16 20:26:32 +00:00
|
|
|
sidebarNavigate = (route) => {
|
|
|
|
const { navigation } = this.props;
|
|
|
|
navigation.navigate(route);
|
|
|
|
}
|
|
|
|
|
|
|
|
toggleStatus = () => {
|
2019-09-19 13:32:24 +00:00
|
|
|
animateNextTransition();
|
2019-09-16 20:26:32 +00:00
|
|
|
this.setState(prevState => ({ showStatus: !prevState.showStatus }));
|
2019-05-18 19:31:33 +00:00
|
|
|
}
|
|
|
|
|
2019-03-12 16:23:06 +00:00
|
|
|
renderStatusItem = ({ item }) => {
|
|
|
|
const { user } = this.props;
|
|
|
|
return (
|
|
|
|
<SidebarItem
|
|
|
|
text={item.name}
|
|
|
|
left={<Status style={styles.status} size={12} status={item.id} />}
|
|
|
|
current={user.status === item.id}
|
|
|
|
onPress={() => {
|
|
|
|
this.toggleStatus();
|
|
|
|
if (user.status !== item.id) {
|
|
|
|
try {
|
|
|
|
RocketChat.setUserPresenceDefaultStatus(item.id);
|
|
|
|
} catch (e) {
|
2019-08-23 13:18:47 +00:00
|
|
|
log(e);
|
2019-03-12 16:23:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
renderNavigation = () => {
|
2019-09-16 20:26:32 +00:00
|
|
|
const { isAdmin } = this.state;
|
2019-12-04 16:39:53 +00:00
|
|
|
const { activeItemKey, theme } = this.props;
|
2019-03-12 16:23:06 +00:00
|
|
|
return (
|
2019-09-24 20:26:56 +00:00
|
|
|
<>
|
2019-03-12 16:23:06 +00:00
|
|
|
<SidebarItem
|
|
|
|
text={I18n.t('Chats')}
|
2019-12-04 16:39:53 +00:00
|
|
|
left={<CustomIcon name='message' size={20} color={themes[theme].titleText} />}
|
2019-03-12 16:23:06 +00:00
|
|
|
onPress={() => this.sidebarNavigate('RoomsListView')}
|
|
|
|
testID='sidebar-chats'
|
|
|
|
current={activeItemKey === 'ChatsStack'}
|
|
|
|
/>
|
|
|
|
<SidebarItem
|
|
|
|
text={I18n.t('Profile')}
|
2019-12-04 16:39:53 +00:00
|
|
|
left={<CustomIcon name='user' size={20} color={themes[theme].titleText} />}
|
2019-03-12 16:23:06 +00:00
|
|
|
onPress={() => this.sidebarNavigate('ProfileView')}
|
|
|
|
testID='sidebar-profile'
|
|
|
|
current={activeItemKey === 'ProfileStack'}
|
|
|
|
/>
|
|
|
|
<SidebarItem
|
|
|
|
text={I18n.t('Settings')}
|
2019-12-04 16:39:53 +00:00
|
|
|
left={<CustomIcon name='cog' size={20} color={themes[theme].titleText} />}
|
2019-03-12 16:23:06 +00:00
|
|
|
onPress={() => this.sidebarNavigate('SettingsView')}
|
|
|
|
testID='sidebar-settings'
|
|
|
|
current={activeItemKey === 'SettingsStack'}
|
|
|
|
/>
|
2019-09-16 20:26:32 +00:00
|
|
|
{isAdmin ? (
|
2019-05-18 19:31:33 +00:00
|
|
|
<SidebarItem
|
|
|
|
text={I18n.t('Admin_Panel')}
|
2019-12-04 16:39:53 +00:00
|
|
|
left={<CustomIcon name='shield-alt' size={20} color={themes[theme].titleText} />}
|
2019-05-18 19:31:33 +00:00
|
|
|
onPress={() => this.sidebarNavigate('AdminPanelView')}
|
|
|
|
testID='sidebar-settings'
|
|
|
|
current={activeItemKey === 'AdminPanelStack'}
|
|
|
|
/>
|
|
|
|
) : null}
|
2019-09-24 20:26:56 +00:00
|
|
|
</>
|
2019-03-12 16:23:06 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
renderStatus = () => {
|
|
|
|
const { status } = this.state;
|
|
|
|
const { user } = this.props;
|
|
|
|
return (
|
|
|
|
<FlatList
|
|
|
|
data={status}
|
|
|
|
extraData={user}
|
|
|
|
renderItem={this.renderStatusItem}
|
|
|
|
keyExtractor={keyExtractor}
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
render() {
|
|
|
|
const { showStatus } = this.state;
|
2019-11-25 20:01:17 +00:00
|
|
|
const {
|
2020-02-21 16:13:05 +00:00
|
|
|
user, Site_Name, baseUrl, useRealName, split, theme
|
2019-11-25 20:01:17 +00:00
|
|
|
} = this.props;
|
2019-03-12 16:23:06 +00:00
|
|
|
|
|
|
|
if (!user) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
return (
|
2019-12-04 16:39:53 +00:00
|
|
|
<SafeAreaView testID='sidebar-view' style={[styles.container, { backgroundColor: themes[theme].focusedBackground }]}>
|
|
|
|
<ScrollView
|
|
|
|
style={[
|
|
|
|
styles.container,
|
|
|
|
{
|
|
|
|
backgroundColor: split
|
|
|
|
? themes[theme].backgroundColor
|
|
|
|
: themes[theme].focusedBackground
|
|
|
|
}
|
|
|
|
]}
|
|
|
|
{...scrollPersistTaps}
|
|
|
|
>
|
|
|
|
<Touch
|
2019-03-12 16:23:06 +00:00
|
|
|
onPress={this.toggleStatus}
|
|
|
|
testID='sidebar-toggle-status'
|
|
|
|
style={styles.header}
|
2019-12-04 16:39:53 +00:00
|
|
|
theme={theme}
|
2019-03-12 16:23:06 +00:00
|
|
|
>
|
|
|
|
<Avatar
|
|
|
|
text={user.username}
|
|
|
|
size={30}
|
|
|
|
style={styles.avatar}
|
|
|
|
baseUrl={baseUrl}
|
2019-04-18 20:57:35 +00:00
|
|
|
userId={user.id}
|
|
|
|
token={user.token}
|
2019-03-12 16:23:06 +00:00
|
|
|
/>
|
|
|
|
<View style={styles.headerTextContainer}>
|
|
|
|
<View style={styles.headerUsername}>
|
2019-12-17 14:08:06 +00:00
|
|
|
<Status style={styles.status} size={12} status={user && user.status} theme={theme} />
|
2020-02-21 16:13:05 +00:00
|
|
|
<Text numberOfLines={1} style={[styles.username, { color: themes[theme].titleText }]}>{useRealName ? user.name : user.username}</Text>
|
2019-03-12 16:23:06 +00:00
|
|
|
</View>
|
2019-12-04 16:39:53 +00:00
|
|
|
<Text style={[styles.currentServerText, { color: themes[theme].titleText }]} numberOfLines={1}>{Site_Name}</Text>
|
2019-03-12 16:23:06 +00:00
|
|
|
</View>
|
2019-12-04 16:39:53 +00:00
|
|
|
<CustomIcon name='arrow-down' size={20} style={[styles.headerIcon, showStatus && styles.inverted, { color: themes[theme].titleText }]} />
|
|
|
|
</Touch>
|
2019-03-12 16:23:06 +00:00
|
|
|
|
2020-02-05 15:12:40 +00:00
|
|
|
{!split ? <Separator theme={theme} /> : null}
|
2019-03-12 16:23:06 +00:00
|
|
|
|
2019-11-25 20:01:17 +00:00
|
|
|
{!showStatus && !split ? this.renderNavigation() : null}
|
2019-03-12 16:23:06 +00:00
|
|
|
{showStatus ? this.renderStatus() : null}
|
2020-02-05 15:12:40 +00:00
|
|
|
{!split ? <Separator theme={theme} /> : null}
|
2019-03-12 16:23:06 +00:00
|
|
|
</ScrollView>
|
|
|
|
</SafeAreaView>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
2019-08-07 13:51:34 +00:00
|
|
|
|
|
|
|
const mapStateToProps = state => ({
|
|
|
|
Site_Name: state.settings.Site_Name,
|
2020-02-11 14:09:14 +00:00
|
|
|
user: getUserSelector(state),
|
|
|
|
baseUrl: state.server.server,
|
2020-02-21 16:13:05 +00:00
|
|
|
loadingServer: state.server.loading,
|
|
|
|
useRealName: state.settings.UI_Use_Real_Name
|
2019-08-07 13:51:34 +00:00
|
|
|
});
|
|
|
|
|
2020-02-05 15:12:40 +00:00
|
|
|
export default connect(mapStateToProps)(withTheme(withSplit(Sidebar)));
|