2017-09-21 17:08:00 +00:00
|
|
|
import React, { Component } from 'react';
|
|
|
|
import PropTypes from 'prop-types';
|
2018-06-05 01:17:02 +00:00
|
|
|
import { ScrollView, Text, View, StyleSheet, FlatList, LayoutAnimation } from 'react-native';
|
2017-09-21 17:08:00 +00:00
|
|
|
import { connect } from 'react-redux';
|
2018-06-05 01:17:02 +00:00
|
|
|
import { DrawerActions, SafeAreaView } from 'react-navigation';
|
|
|
|
import FastImage from 'react-native-fast-image';
|
|
|
|
import Icon from 'react-native-vector-icons/MaterialIcons';
|
2017-09-21 17:08:00 +00:00
|
|
|
|
2017-12-27 15:22:06 +00:00
|
|
|
import database from '../lib/realm';
|
2018-05-18 17:55:08 +00:00
|
|
|
import { setServer } from '../actions/server';
|
2017-11-07 20:25:04 +00:00
|
|
|
import { logout } from '../actions/login';
|
2018-06-05 01:17:02 +00:00
|
|
|
import Avatar from '../containers/Avatar';
|
|
|
|
import Status from '../containers/status';
|
|
|
|
import Touch from '../utils/touch';
|
|
|
|
import { STATUS_COLORS } from '../constants/colors';
|
|
|
|
import RocketChat from '../lib/rocketchat';
|
|
|
|
import log from '../utils/log';
|
2018-06-01 17:38:13 +00:00
|
|
|
import I18n from '../i18n';
|
2017-09-21 17:08:00 +00:00
|
|
|
|
|
|
|
const styles = StyleSheet.create({
|
2018-06-05 01:17:02 +00:00
|
|
|
selected: {
|
|
|
|
backgroundColor: 'rgba(0, 0, 0, .04)'
|
2017-09-21 17:08:00 +00:00
|
|
|
},
|
2018-06-05 01:17:02 +00:00
|
|
|
item: {
|
|
|
|
flexDirection: 'row',
|
2017-09-21 17:08:00 +00:00
|
|
|
alignItems: 'center'
|
|
|
|
},
|
2018-06-05 01:17:02 +00:00
|
|
|
itemLeft: {
|
|
|
|
marginHorizontal: 10,
|
|
|
|
width: 30,
|
|
|
|
alignItems: 'center'
|
|
|
|
},
|
|
|
|
itemLeftOpacity: {
|
|
|
|
opacity: 0.62
|
2017-09-21 17:08:00 +00:00
|
|
|
},
|
2018-06-05 01:17:02 +00:00
|
|
|
itemText: {
|
|
|
|
marginVertical: 16,
|
|
|
|
fontWeight: 'bold',
|
|
|
|
color: '#292E35'
|
2017-09-21 17:08:00 +00:00
|
|
|
},
|
2018-06-05 01:17:02 +00:00
|
|
|
separator: {
|
|
|
|
borderBottomWidth: StyleSheet.hairlineWidth,
|
|
|
|
borderColor: '#ddd',
|
|
|
|
marginVertical: 4
|
2017-09-21 17:08:00 +00:00
|
|
|
},
|
2018-06-05 01:17:02 +00:00
|
|
|
serverImage: {
|
|
|
|
width: 24,
|
|
|
|
height: 24,
|
|
|
|
borderRadius: 4
|
|
|
|
},
|
|
|
|
header: {
|
|
|
|
paddingVertical: 16,
|
|
|
|
flexDirection: 'row',
|
|
|
|
alignItems: 'center'
|
|
|
|
},
|
|
|
|
headerTextContainer: {
|
|
|
|
flex: 1,
|
|
|
|
flexDirection: 'column',
|
|
|
|
alignItems: 'flex-start'
|
|
|
|
},
|
|
|
|
headerUsername: {
|
|
|
|
flexDirection: 'row',
|
|
|
|
alignItems: 'center'
|
|
|
|
},
|
|
|
|
avatar: {
|
|
|
|
marginHorizontal: 10
|
|
|
|
},
|
|
|
|
status: {
|
|
|
|
borderRadius: 12,
|
|
|
|
width: 12,
|
|
|
|
height: 12,
|
|
|
|
marginRight: 5
|
|
|
|
},
|
|
|
|
currentServerText: {
|
|
|
|
fontWeight: 'bold'
|
2017-09-21 17:08:00 +00:00
|
|
|
}
|
|
|
|
});
|
2018-03-02 21:31:44 +00:00
|
|
|
const keyExtractor = item => item.id;
|
2017-09-21 17:08:00 +00:00
|
|
|
@connect(state => ({
|
2018-06-05 01:17:02 +00:00
|
|
|
server: state.server.server,
|
|
|
|
user: state.login.user
|
2017-09-21 17:08:00 +00:00
|
|
|
}), dispatch => ({
|
2017-11-07 20:25:04 +00:00
|
|
|
selectServer: server => dispatch(setServer(server)),
|
2018-05-18 17:55:08 +00:00
|
|
|
logout: () => dispatch(logout())
|
2017-09-21 17:08:00 +00:00
|
|
|
}))
|
|
|
|
export default class Sidebar extends Component {
|
|
|
|
static propTypes = {
|
|
|
|
server: PropTypes.string.isRequired,
|
|
|
|
selectServer: PropTypes.func.isRequired,
|
2017-11-07 20:25:04 +00:00
|
|
|
navigation: PropTypes.object.isRequired,
|
2018-05-18 17:55:08 +00:00
|
|
|
logout: PropTypes.func.isRequired
|
2017-09-21 17:08:00 +00:00
|
|
|
}
|
|
|
|
|
2018-03-06 17:40:44 +00:00
|
|
|
constructor(props) {
|
|
|
|
super(props);
|
2018-06-05 01:17:02 +00:00
|
|
|
this.state = {
|
|
|
|
servers: [],
|
|
|
|
showServers: false
|
|
|
|
};
|
2018-03-06 17:40:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
componentDidMount() {
|
|
|
|
this.setState(this.getState());
|
2018-06-13 01:33:00 +00:00
|
|
|
this.setStatus();
|
|
|
|
database.databases.serversDB.addListener('change', this.updateState);
|
|
|
|
}
|
|
|
|
|
|
|
|
componentWillReceiveProps(nextProps) {
|
|
|
|
if (nextProps.user && this.props.user && this.props.user.language !== nextProps.user.language) {
|
|
|
|
this.setStatus();
|
|
|
|
}
|
2018-03-06 17:40:44 +00:00
|
|
|
}
|
|
|
|
|
2017-09-21 17:08:00 +00:00
|
|
|
componentWillUnmount() {
|
2017-12-27 15:34:39 +00:00
|
|
|
database.databases.serversDB.removeListener('change', this.updateState);
|
2017-09-21 17:08:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
onPressItem = (item) => {
|
|
|
|
this.props.selectServer(item.id);
|
2018-05-23 13:39:18 +00:00
|
|
|
this.closeDrawer();
|
2017-09-21 17:08:00 +00:00
|
|
|
}
|
|
|
|
|
2018-06-13 01:33:00 +00:00
|
|
|
setStatus = () => {
|
|
|
|
setTimeout(() => {
|
|
|
|
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')
|
|
|
|
}]
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-09-21 17:08:00 +00:00
|
|
|
getState = () => ({
|
2017-12-27 15:34:39 +00:00
|
|
|
servers: database.databases.serversDB.objects('servers')
|
2017-09-21 17:08:00 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
updateState = () => {
|
|
|
|
this.setState(this.getState());
|
|
|
|
}
|
|
|
|
|
2018-05-23 13:39:18 +00:00
|
|
|
closeDrawer = () => {
|
|
|
|
this.props.navigation.dispatch(DrawerActions.closeDrawer());
|
|
|
|
}
|
|
|
|
|
2018-06-05 01:17:02 +00:00
|
|
|
toggleServers = () => {
|
|
|
|
LayoutAnimation.easeInEaseOut();
|
|
|
|
this.setState({ showServers: !this.state.showServers });
|
|
|
|
}
|
|
|
|
|
|
|
|
isRouteFocused = (route) => {
|
|
|
|
const { state } = this.props.navigation;
|
|
|
|
const activeItemKey = state.routes[state.index] ? state.routes[state.index].key : null;
|
|
|
|
return activeItemKey === route;
|
|
|
|
}
|
|
|
|
|
|
|
|
sidebarNavigate = (route) => {
|
|
|
|
const { navigate } = this.props.navigation;
|
|
|
|
if (!this.isRouteFocused(route)) {
|
|
|
|
navigate(route);
|
2018-06-13 01:33:00 +00:00
|
|
|
} else {
|
|
|
|
this.closeDrawer();
|
2018-06-05 01:17:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
renderSeparator = key => <View key={key} style={styles.separator} />;
|
2017-09-21 17:08:00 +00:00
|
|
|
|
2018-06-05 01:17:02 +00:00
|
|
|
renderItem = ({
|
|
|
|
text, left, selected, onPress, testID
|
|
|
|
}) => (
|
|
|
|
<Touch
|
|
|
|
key={text}
|
|
|
|
onPress={onPress}
|
|
|
|
underlayColor='rgba(255, 255, 255, 0.5)'
|
|
|
|
activeOpacity={0.3}
|
|
|
|
testID={testID}
|
2017-09-21 17:08:00 +00:00
|
|
|
>
|
2018-06-05 01:17:02 +00:00
|
|
|
<View style={[styles.item, selected && styles.selected]}>
|
|
|
|
<View style={[styles.itemLeft, !selected && styles.itemLeftOpacity]}>
|
|
|
|
{left}
|
|
|
|
</View>
|
|
|
|
<Text style={styles.itemText}>
|
|
|
|
{text}
|
2017-09-21 17:08:00 +00:00
|
|
|
</Text>
|
|
|
|
</View>
|
2018-06-05 01:17:02 +00:00
|
|
|
</Touch>
|
|
|
|
)
|
|
|
|
|
|
|
|
renderStatusItem = ({ item }) => (
|
|
|
|
this.renderItem({
|
|
|
|
text: item.name,
|
|
|
|
left: <View style={[styles.status, { backgroundColor: STATUS_COLORS[item.id] }]} />,
|
|
|
|
selected: this.props.user.status === item.id,
|
|
|
|
onPress: () => {
|
|
|
|
this.closeDrawer();
|
|
|
|
this.toggleServers();
|
|
|
|
if (this.props.user.status !== item.id) {
|
|
|
|
try {
|
|
|
|
RocketChat.setUserPresenceDefaultStatus(item.id);
|
|
|
|
} catch (e) {
|
|
|
|
log('onPressModalButton', e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
)
|
|
|
|
|
|
|
|
renderServer = ({ item }) => (
|
|
|
|
this.renderItem({
|
|
|
|
text: item.id,
|
|
|
|
left: <FastImage
|
|
|
|
style={styles.serverImage}
|
|
|
|
source={{ uri: encodeURI(`${ item.id }/assets/favicon_32.png`) }}
|
|
|
|
/>,
|
|
|
|
selected: this.props.server === item.id,
|
|
|
|
onPress: () => {
|
|
|
|
this.closeDrawer();
|
|
|
|
this.toggleServers();
|
|
|
|
if (this.props.server !== item.id) {
|
|
|
|
this.props.selectServer(item.id);
|
2018-06-13 01:33:00 +00:00
|
|
|
this.props.navigation.navigate('RoomsList');
|
2018-06-05 01:17:02 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
testID: `sidebar-${ item.id }`
|
|
|
|
})
|
|
|
|
)
|
|
|
|
|
|
|
|
renderNavigation = () => (
|
|
|
|
[
|
|
|
|
this.renderItem({
|
|
|
|
text: I18n.t('Chats'),
|
|
|
|
left: <Icon name='chat-bubble' size={20} />,
|
|
|
|
onPress: () => this.sidebarNavigate('Chats'),
|
|
|
|
selected: this.isRouteFocused('Chats'),
|
|
|
|
testID: 'sidebar-chats'
|
|
|
|
}),
|
|
|
|
this.renderItem({
|
|
|
|
text: I18n.t('Profile'),
|
|
|
|
left: <Icon name='person' size={20} />,
|
|
|
|
onPress: () => this.sidebarNavigate('ProfileView'),
|
|
|
|
selected: this.isRouteFocused('ProfileView'),
|
|
|
|
testID: 'sidebar-profile'
|
|
|
|
}),
|
|
|
|
this.renderItem({
|
|
|
|
text: I18n.t('Settings'),
|
|
|
|
left: <Icon name='settings' size={20} />,
|
|
|
|
onPress: () => this.sidebarNavigate('SettingsView'),
|
|
|
|
selected: this.isRouteFocused('SettingsView'),
|
|
|
|
testID: 'sidebar-settings'
|
|
|
|
}),
|
|
|
|
this.renderSeparator('separator-logout'),
|
|
|
|
this.renderItem({
|
|
|
|
text: I18n.t('Logout'),
|
|
|
|
left: <Icon
|
|
|
|
name='exit-to-app'
|
|
|
|
size={20}
|
|
|
|
/>,
|
|
|
|
onPress: () => this.props.logout(),
|
|
|
|
testID: 'sidebar-logout'
|
|
|
|
})
|
|
|
|
]
|
|
|
|
)
|
|
|
|
|
|
|
|
renderServers = () => (
|
|
|
|
[
|
|
|
|
<FlatList
|
|
|
|
key='status-list'
|
|
|
|
data={this.state.status}
|
|
|
|
extraData={this.props.user}
|
|
|
|
renderItem={this.renderStatusItem}
|
|
|
|
keyExtractor={keyExtractor}
|
|
|
|
/>,
|
|
|
|
this.renderSeparator('separator-status'),
|
|
|
|
<FlatList
|
|
|
|
key='servers-list'
|
|
|
|
data={this.state.servers}
|
|
|
|
extraData={this.props.server}
|
|
|
|
renderItem={this.renderServer}
|
|
|
|
keyExtractor={keyExtractor}
|
|
|
|
/>,
|
|
|
|
this.renderSeparator('separator-add-server'),
|
|
|
|
this.renderItem({
|
|
|
|
text: I18n.t('Add_Server'),
|
|
|
|
left: <Icon
|
|
|
|
name='add'
|
|
|
|
size={20}
|
|
|
|
/>,
|
|
|
|
onPress: () => {
|
|
|
|
this.closeDrawer();
|
|
|
|
this.toggleServers();
|
|
|
|
this.props.navigation.navigate('AddServer');
|
|
|
|
},
|
|
|
|
testID: 'sidebar-add-server'
|
|
|
|
})
|
|
|
|
]
|
|
|
|
)
|
2017-09-21 17:08:00 +00:00
|
|
|
|
|
|
|
render() {
|
2018-06-05 01:17:02 +00:00
|
|
|
const { user, server } = this.props;
|
2017-09-21 17:08:00 +00:00
|
|
|
return (
|
2018-06-05 01:17:02 +00:00
|
|
|
<ScrollView>
|
|
|
|
<SafeAreaView
|
|
|
|
style={styles.container}
|
|
|
|
forceInset={{ top: 'always', horizontal: 'never' }}
|
|
|
|
testID='sidebar'
|
|
|
|
>
|
|
|
|
<Touch
|
|
|
|
onPress={() => this.toggleServers()}
|
|
|
|
underlayColor='rgba(255, 255, 255, 0.5)'
|
|
|
|
activeOpacity={0.3}
|
|
|
|
testID='sidebar-toggle-server'
|
2017-11-13 13:53:45 +00:00
|
|
|
>
|
2018-06-05 01:17:02 +00:00
|
|
|
<View style={styles.header}>
|
|
|
|
<Avatar
|
|
|
|
text={user.username}
|
|
|
|
size={30}
|
|
|
|
style={styles.avatar}
|
|
|
|
/>
|
|
|
|
<View style={styles.headerTextContainer}>
|
|
|
|
<View style={styles.headerUsername}>
|
|
|
|
<Status style={styles.status} id={user.id} />
|
|
|
|
<Text>{user.username}</Text>
|
|
|
|
</View>
|
|
|
|
<Text style={styles.currentServerText}>{server}</Text>
|
|
|
|
</View>
|
|
|
|
<Icon
|
|
|
|
name={this.state.showServers ? 'keyboard-arrow-up' : 'keyboard-arrow-down'}
|
|
|
|
size={30}
|
|
|
|
/>
|
2017-11-13 13:53:45 +00:00
|
|
|
</View>
|
2018-06-05 01:17:02 +00:00
|
|
|
</Touch>
|
|
|
|
|
|
|
|
{this.renderSeparator('separator-header')}
|
|
|
|
|
2018-06-13 01:33:00 +00:00
|
|
|
{!this.state.showServers ? this.renderNavigation() : null}
|
|
|
|
{this.state.showServers ? this.renderServers() : null}
|
2018-06-05 01:17:02 +00:00
|
|
|
</SafeAreaView>
|
2017-09-21 17:08:00 +00:00
|
|
|
</ScrollView>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|