[NEW] Directory and Federation (#967)
* Initial * Search working * Refactor layout * Layout and search working * Navigate * Remove inline styles and fix i18n * Federation setting * Missing i18n * Fix android style * Refactor
This commit is contained in:
parent
4382eca8b6
commit
b7e6d3615f
|
@ -14,6 +14,9 @@ export default {
|
||||||
CROWD_Enable: {
|
CROWD_Enable: {
|
||||||
type: 'valueAsBoolean'
|
type: 'valueAsBoolean'
|
||||||
},
|
},
|
||||||
|
FEDERATION_Enabled: {
|
||||||
|
type: 'valueAsBoolean'
|
||||||
|
},
|
||||||
LDAP_Enable: {
|
LDAP_Enable: {
|
||||||
type: 'valueAsBoolean'
|
type: 'valueAsBoolean'
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { StyleSheet } from 'react-native';
|
||||||
|
|
||||||
|
import { CustomIcon } from '../lib/Icons';
|
||||||
|
import sharedStyles from '../views/Styles';
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
icon: {
|
||||||
|
width: 22,
|
||||||
|
height: 22,
|
||||||
|
marginHorizontal: 15,
|
||||||
|
...sharedStyles.textColorDescription
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const Check = React.memo(() => <CustomIcon style={styles.icon} size={22} name='check' />);
|
||||||
|
|
||||||
|
export default Check;
|
|
@ -34,7 +34,7 @@ const styles = StyleSheet.create({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const SearchBox = ({ onChangeText, testID }) => (
|
const SearchBox = ({ onChangeText, onSubmitEditing, testID }) => (
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
<View style={styles.searchBox}>
|
<View style={styles.searchBox}>
|
||||||
<CustomIcon name='magnifier' size={14} color='#8E8E93' />
|
<CustomIcon name='magnifier' size={14} color='#8E8E93' />
|
||||||
|
@ -49,6 +49,7 @@ const SearchBox = ({ onChangeText, testID }) => (
|
||||||
testID={testID}
|
testID={testID}
|
||||||
underlineColorAndroid='transparent'
|
underlineColorAndroid='transparent'
|
||||||
onChangeText={onChangeText}
|
onChangeText={onChangeText}
|
||||||
|
onSubmitEditing={onSubmitEditing}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
@ -56,6 +57,7 @@ const SearchBox = ({ onChangeText, testID }) => (
|
||||||
|
|
||||||
SearchBox.propTypes = {
|
SearchBox.propTypes = {
|
||||||
onChangeText: PropTypes.func.isRequired,
|
onChangeText: PropTypes.func.isRequired,
|
||||||
|
onSubmitEditing: PropTypes.func,
|
||||||
testID: PropTypes.string
|
testID: PropTypes.string
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -142,9 +142,10 @@ export default {
|
||||||
DELETE: 'DELETE',
|
DELETE: 'DELETE',
|
||||||
description: 'description',
|
description: 'description',
|
||||||
Description: 'Description',
|
Description: 'Description',
|
||||||
|
Directory: 'Directory',
|
||||||
|
Direct_Messages: 'Direct Messages',
|
||||||
Disable_notifications: 'Disable notifications',
|
Disable_notifications: 'Disable notifications',
|
||||||
Discussions: 'Discussions',
|
Discussions: 'Discussions',
|
||||||
Direct_Messages: 'Direct Messages',
|
|
||||||
Dont_Have_An_Account: 'Don\'t have an account?',
|
Dont_Have_An_Account: 'Don\'t have an account?',
|
||||||
Do_you_really_want_to_key_this_room_question_mark: 'Do you really want to {{key}} this room?',
|
Do_you_really_want_to_key_this_room_question_mark: 'Do you really want to {{key}} this room?',
|
||||||
edit: 'edit',
|
edit: 'edit',
|
||||||
|
@ -294,6 +295,9 @@ export default {
|
||||||
saving_settings: 'saving settings',
|
saving_settings: 'saving settings',
|
||||||
Search_Messages: 'Search Messages',
|
Search_Messages: 'Search Messages',
|
||||||
Search: 'Search',
|
Search: 'Search',
|
||||||
|
Search_by: 'Search by',
|
||||||
|
Search_global_users: 'Search for global users',
|
||||||
|
Search_global_users_description: 'If you turn-on, you can search for any user from others companies or servers.',
|
||||||
Select_Avatar: 'Select Avatar',
|
Select_Avatar: 'Select Avatar',
|
||||||
Select_Users: 'Select Users',
|
Select_Users: 'Select Users',
|
||||||
Send: 'Send',
|
Send: 'Send',
|
||||||
|
@ -348,6 +352,7 @@ export default {
|
||||||
Updating: 'Updating...',
|
Updating: 'Updating...',
|
||||||
Uploading: 'Uploading',
|
Uploading: 'Uploading',
|
||||||
Upload_file_question_mark: 'Upload file?',
|
Upload_file_question_mark: 'Upload file?',
|
||||||
|
Users: 'Users',
|
||||||
User_added_by: 'User {{userAdded}} added by {{userBy}}',
|
User_added_by: 'User {{userAdded}} added by {{userBy}}',
|
||||||
User_has_been_key: 'User has been {{key}}!',
|
User_has_been_key: 'User has been {{key}}!',
|
||||||
User_is_no_longer_role_by_: '{{user}} is no longer {{role}} by {{userBy}}',
|
User_is_no_longer_role_by_: '{{user}} is no longer {{role}} by {{userBy}}',
|
||||||
|
|
|
@ -146,11 +146,12 @@ export default {
|
||||||
delete: 'excluir',
|
delete: 'excluir',
|
||||||
Delete: 'Excluir',
|
Delete: 'Excluir',
|
||||||
DELETE: 'EXCLUIR',
|
DELETE: 'EXCLUIR',
|
||||||
|
Direct_Messages: 'Mensagens Diretas',
|
||||||
|
Directory: 'Diretório',
|
||||||
description: 'descrição',
|
description: 'descrição',
|
||||||
Description: 'Descrição',
|
Description: 'Descrição',
|
||||||
Disable_notifications: 'Desabilitar notificações',
|
Disable_notifications: 'Desabilitar notificações',
|
||||||
Discussions: 'Discussões',
|
Discussions: 'Discussões',
|
||||||
Direct_Messages: 'Mensagens Diretas',
|
|
||||||
Dont_Have_An_Account: 'Não tem uma conta?',
|
Dont_Have_An_Account: 'Não tem uma conta?',
|
||||||
Do_you_really_want_to_key_this_room_question_mark: 'Você quer realmente {{key}} esta sala?',
|
Do_you_really_want_to_key_this_room_question_mark: 'Você quer realmente {{key}} esta sala?',
|
||||||
edit: 'editar',
|
edit: 'editar',
|
||||||
|
@ -293,6 +294,9 @@ export default {
|
||||||
saving_settings: 'salvando configurações',
|
saving_settings: 'salvando configurações',
|
||||||
Search_Messages: 'Buscar Mensagens',
|
Search_Messages: 'Buscar Mensagens',
|
||||||
Search: 'Buscar',
|
Search: 'Buscar',
|
||||||
|
Search_by: 'Buscar por',
|
||||||
|
Search_global_users: 'Busca por usuários globais',
|
||||||
|
Search_global_users_description: 'Caso ativado, busca por usuários de outras empresas ou servidores.',
|
||||||
Select_Avatar: 'Selecionar Avatar',
|
Select_Avatar: 'Selecionar Avatar',
|
||||||
Select_Users: 'Selecionar Usuários',
|
Select_Users: 'Selecionar Usuários',
|
||||||
Send: 'Enviar',
|
Send: 'Enviar',
|
||||||
|
@ -344,6 +348,7 @@ export default {
|
||||||
Updating: 'Atualizando...',
|
Updating: 'Atualizando...',
|
||||||
Uploading: 'Subindo arquivo',
|
Uploading: 'Subindo arquivo',
|
||||||
Upload_file_question_mark: 'Enviar arquivo?',
|
Upload_file_question_mark: 'Enviar arquivo?',
|
||||||
|
Users: 'Usuários',
|
||||||
User_added_by: 'Usuário {{userAdded}} adicionado por {{userBy}}',
|
User_added_by: 'Usuário {{userAdded}} adicionado por {{userBy}}',
|
||||||
User_has_been_key: 'Usuário foi {{key}}!',
|
User_has_been_key: 'Usuário foi {{key}}!',
|
||||||
User_is_no_longer_role_by_: '{{user}} não pertence mais à {{role}} por {{userBy}}',
|
User_is_no_longer_role_by_: '{{user}} não pertence mais à {{role}} por {{userBy}}',
|
||||||
|
|
|
@ -16,6 +16,7 @@ import AuthLoadingView from './views/AuthLoadingView';
|
||||||
import RoomsListView from './views/RoomsListView';
|
import RoomsListView from './views/RoomsListView';
|
||||||
import RoomView from './views/RoomView';
|
import RoomView from './views/RoomView';
|
||||||
import NewMessageView from './views/NewMessageView';
|
import NewMessageView from './views/NewMessageView';
|
||||||
|
import DirectoryView from './views/DirectoryView';
|
||||||
import LoginView from './views/LoginView';
|
import LoginView from './views/LoginView';
|
||||||
import Navigation from './lib/Navigation';
|
import Navigation from './lib/Navigation';
|
||||||
import Sidebar from './views/SidebarView';
|
import Sidebar from './views/SidebarView';
|
||||||
|
@ -110,7 +111,8 @@ const ChatsStack = createStackNavigator({
|
||||||
SearchMessagesView,
|
SearchMessagesView,
|
||||||
SelectedUsersView,
|
SelectedUsersView,
|
||||||
ThreadMessagesView,
|
ThreadMessagesView,
|
||||||
MessagesView
|
MessagesView,
|
||||||
|
DirectoryView
|
||||||
}, {
|
}, {
|
||||||
defaultNavigationOptions: defaultHeader
|
defaultNavigationOptions: defaultHeader
|
||||||
});
|
});
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { Rocketchat as RocketchatClient } from '@rocket.chat/sdk';
|
||||||
import reduxStore from './createStore';
|
import reduxStore from './createStore';
|
||||||
import defaultSettings from '../constants/settings';
|
import defaultSettings from '../constants/settings';
|
||||||
import messagesStatus from '../constants/messagesStatus';
|
import messagesStatus from '../constants/messagesStatus';
|
||||||
import database, { safeAddListener } from './realm';
|
import database from './realm';
|
||||||
import log from '../utils/log';
|
import log from '../utils/log';
|
||||||
import { isIOS, getBundleId } from '../utils/deviceInfo';
|
import { isIOS, getBundleId } from '../utils/deviceInfo';
|
||||||
import EventEmitter from '../utils/events';
|
import EventEmitter from '../utils/events';
|
||||||
|
@ -57,23 +57,6 @@ const RocketChat = {
|
||||||
// RC 0.51.0
|
// RC 0.51.0
|
||||||
return this.sdk.methodCall(type ? 'createPrivateGroup' : 'createChannel', name, users, readOnly, {}, { broadcast });
|
return this.sdk.methodCall(type ? 'createPrivateGroup' : 'createChannel', name, users, readOnly, {}, { broadcast });
|
||||||
},
|
},
|
||||||
async createDirectMessageAndWait(username) {
|
|
||||||
const room = await RocketChat.createDirectMessage(username);
|
|
||||||
return new Promise((resolve) => {
|
|
||||||
const data = database.objects('subscriptions')
|
|
||||||
.filtered('rid = $1', room.rid);
|
|
||||||
|
|
||||||
if (data.length) {
|
|
||||||
return resolve(data[0]);
|
|
||||||
}
|
|
||||||
safeAddListener(data, () => {
|
|
||||||
if (!data.length) { return; }
|
|
||||||
data.removeAllListeners();
|
|
||||||
resolve(data[0]);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
async getUserToken() {
|
async getUserToken() {
|
||||||
try {
|
try {
|
||||||
return await AsyncStorage.getItem(TOKEN_KEY);
|
return await AsyncStorage.getItem(TOKEN_KEY);
|
||||||
|
@ -849,6 +832,14 @@ const RocketChat = {
|
||||||
this.sdk.subscribe('stream-notify-logged', 'user-status');
|
this.sdk.subscribe('stream-notify-logged', 'user-status');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
getDirectory({
|
||||||
|
query, count, offset, sort
|
||||||
|
}) {
|
||||||
|
// RC 1.0
|
||||||
|
return this.sdk.get('directory', {
|
||||||
|
query, count, offset, sort
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { Text, View } from 'react-native';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
import Avatar from '../../containers/Avatar';
|
||||||
|
import Touch from '../../utils/touch';
|
||||||
|
import RoomTypeIcon from '../../containers/RoomTypeIcon';
|
||||||
|
import styles from './styles';
|
||||||
|
|
||||||
|
const DirectoryItemLabel = React.memo(({ text }) => {
|
||||||
|
if (!text) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return <Text style={styles.directoryItemLabel}>{text}</Text>;
|
||||||
|
});
|
||||||
|
|
||||||
|
const DirectoryItem = ({
|
||||||
|
title, description, avatar, onPress, testID, style, baseUrl, user, rightLabel, type
|
||||||
|
}) => (
|
||||||
|
<Touch onPress={onPress} style={styles.directoryItemButton} testID={testID}>
|
||||||
|
<View style={[styles.directoryItemContainer, style]}>
|
||||||
|
<Avatar
|
||||||
|
text={avatar}
|
||||||
|
size={30}
|
||||||
|
type={type}
|
||||||
|
style={styles.directoryItemAvatar}
|
||||||
|
baseUrl={baseUrl}
|
||||||
|
userId={user.id}
|
||||||
|
token={user.token}
|
||||||
|
/>
|
||||||
|
<View style={styles.directoryItemTextContainer}>
|
||||||
|
<View style={styles.directoryItemTextTitle}>
|
||||||
|
<RoomTypeIcon type='c' />
|
||||||
|
<Text style={styles.directoryItemName} numberOfLines={1}>{title}</Text>
|
||||||
|
</View>
|
||||||
|
<Text style={styles.directoryItemUsername} numberOfLines={1}>{description}</Text>
|
||||||
|
</View>
|
||||||
|
<DirectoryItemLabel text={rightLabel} />
|
||||||
|
</View>
|
||||||
|
</Touch>
|
||||||
|
);
|
||||||
|
|
||||||
|
DirectoryItem.propTypes = {
|
||||||
|
title: PropTypes.string.isRequired,
|
||||||
|
description: PropTypes.string,
|
||||||
|
avatar: PropTypes.string,
|
||||||
|
type: PropTypes.string,
|
||||||
|
user: PropTypes.shape({
|
||||||
|
id: PropTypes.string,
|
||||||
|
token: PropTypes.string
|
||||||
|
}),
|
||||||
|
baseUrl: PropTypes.string.isRequired,
|
||||||
|
onPress: PropTypes.func.isRequired,
|
||||||
|
testID: PropTypes.string.isRequired,
|
||||||
|
style: PropTypes.any,
|
||||||
|
rightLabel: PropTypes.string
|
||||||
|
};
|
||||||
|
|
||||||
|
DirectoryItemLabel.propTypes = {
|
||||||
|
text: PropTypes.string
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DirectoryItem;
|
|
@ -0,0 +1,121 @@
|
||||||
|
import React, { PureComponent } from 'react';
|
||||||
|
import {
|
||||||
|
View, Text, Animated, Easing, TouchableWithoutFeedback, Switch
|
||||||
|
} from 'react-native';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
import Touch from '../../utils/touch';
|
||||||
|
import styles from './styles';
|
||||||
|
import { CustomIcon } from '../../lib/Icons';
|
||||||
|
import Check from '../../containers/Check';
|
||||||
|
import I18n from '../../i18n';
|
||||||
|
|
||||||
|
const ANIMATION_DURATION = 200;
|
||||||
|
const ANIMATION_PROPS = {
|
||||||
|
duration: ANIMATION_DURATION,
|
||||||
|
easing: Easing.inOut(Easing.quad),
|
||||||
|
useNativeDriver: true
|
||||||
|
};
|
||||||
|
|
||||||
|
export default class DirectoryOptions extends PureComponent {
|
||||||
|
static propTypes = {
|
||||||
|
type: PropTypes.string,
|
||||||
|
globalUsers: PropTypes.bool,
|
||||||
|
isFederationEnabled: PropTypes.bool,
|
||||||
|
close: PropTypes.func,
|
||||||
|
changeType: PropTypes.func,
|
||||||
|
toggleWorkspace: PropTypes.func
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.animatedValue = new Animated.Value(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
Animated.timing(
|
||||||
|
this.animatedValue,
|
||||||
|
{
|
||||||
|
toValue: 1,
|
||||||
|
...ANIMATION_PROPS
|
||||||
|
},
|
||||||
|
).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
close = () => {
|
||||||
|
const { close } = this.props;
|
||||||
|
Animated.timing(
|
||||||
|
this.animatedValue,
|
||||||
|
{
|
||||||
|
toValue: 0,
|
||||||
|
...ANIMATION_PROPS
|
||||||
|
},
|
||||||
|
).start(() => close());
|
||||||
|
}
|
||||||
|
|
||||||
|
renderItem = (itemType) => {
|
||||||
|
const { changeType, type: propType } = this.props;
|
||||||
|
let text = 'Users';
|
||||||
|
let icon = 'user';
|
||||||
|
if (itemType === 'channels') {
|
||||||
|
text = 'Channels';
|
||||||
|
icon = 'hashtag';
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Touch style={styles.dropdownItemButton} onPress={() => changeType(itemType)}>
|
||||||
|
<View style={styles.dropdownItemContainer}>
|
||||||
|
<CustomIcon style={styles.dropdownItemIcon} size={22} name={icon} />
|
||||||
|
<Text style={styles.dropdownItemText}>{I18n.t(text)}</Text>
|
||||||
|
{propType === itemType ? <Check /> : null}
|
||||||
|
</View>
|
||||||
|
</Touch>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const translateY = this.animatedValue.interpolate({
|
||||||
|
inputRange: [0, 1],
|
||||||
|
outputRange: [-326, 0]
|
||||||
|
});
|
||||||
|
const backdropOpacity = this.animatedValue.interpolate({
|
||||||
|
inputRange: [0, 1],
|
||||||
|
outputRange: [0, 0.3]
|
||||||
|
});
|
||||||
|
const { globalUsers, toggleWorkspace, isFederationEnabled } = this.props;
|
||||||
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
<TouchableWithoutFeedback onPress={this.close}>
|
||||||
|
<Animated.View style={[styles.backdrop, { opacity: backdropOpacity }]} />
|
||||||
|
</TouchableWithoutFeedback>
|
||||||
|
<Animated.View style={[styles.dropdownContainer, { transform: [{ translateY }] }]}>
|
||||||
|
<Touch
|
||||||
|
onPress={this.close}
|
||||||
|
style={styles.dropdownContainerHeader}
|
||||||
|
>
|
||||||
|
<View style={styles.dropdownItemContainer}>
|
||||||
|
<Text style={styles.dropdownToggleText}>{I18n.t('Search_by')}</Text>
|
||||||
|
<CustomIcon style={[styles.dropdownItemIcon, styles.inverted]} size={22} name='arrow-down' />
|
||||||
|
</View>
|
||||||
|
</Touch>
|
||||||
|
{this.renderItem('channels')}
|
||||||
|
{this.renderItem('users')}
|
||||||
|
{isFederationEnabled
|
||||||
|
? (
|
||||||
|
<React.Fragment>
|
||||||
|
<View style={styles.dropdownSeparator} />
|
||||||
|
<View style={[styles.dropdownItemContainer, styles.globalUsersContainer]}>
|
||||||
|
<View style={styles.globalUsersTextContainer}>
|
||||||
|
<Text style={styles.dropdownItemText}>{I18n.t('Search_global_users')}</Text>
|
||||||
|
<Text style={styles.dropdownItemDescription}>{I18n.t('Search_global_users_description')}</Text>
|
||||||
|
</View>
|
||||||
|
<Switch value={globalUsers} onValueChange={toggleWorkspace} />
|
||||||
|
</View>
|
||||||
|
</React.Fragment>
|
||||||
|
)
|
||||||
|
: null}
|
||||||
|
</Animated.View>
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,248 @@
|
||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import {
|
||||||
|
View, FlatList, Text
|
||||||
|
} from 'react-native';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { SafeAreaView } from 'react-navigation';
|
||||||
|
|
||||||
|
import RocketChat from '../../lib/rocketchat';
|
||||||
|
import DirectoryItem from './DirectoryItem';
|
||||||
|
import sharedStyles from '../Styles';
|
||||||
|
import I18n from '../../i18n';
|
||||||
|
import Touch from '../../utils/touch';
|
||||||
|
import SearchBox from '../../containers/SearchBox';
|
||||||
|
import { CustomIcon } from '../../lib/Icons';
|
||||||
|
import StatusBar from '../../containers/StatusBar';
|
||||||
|
import RCActivityIndicator from '../../containers/ActivityIndicator';
|
||||||
|
import debounce from '../../utils/debounce';
|
||||||
|
import log from '../../utils/log';
|
||||||
|
import Options from './Options';
|
||||||
|
import styles from './styles';
|
||||||
|
|
||||||
|
@connect(state => ({
|
||||||
|
baseUrl: state.settings.Site_Url || state.server ? state.server.server : '',
|
||||||
|
user: {
|
||||||
|
id: state.login.user && state.login.user.id,
|
||||||
|
token: state.login.user && state.login.user.token
|
||||||
|
},
|
||||||
|
isFederationEnabled: state.settings.FEDERATION_Enabled
|
||||||
|
}))
|
||||||
|
export default class DirectoryView extends React.Component {
|
||||||
|
static navigationOptions = () => ({
|
||||||
|
title: I18n.t('Directory')
|
||||||
|
})
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
navigation: PropTypes.object,
|
||||||
|
baseUrl: PropTypes.string,
|
||||||
|
isFederationEnabled: PropTypes.bool,
|
||||||
|
user: PropTypes.shape({
|
||||||
|
id: PropTypes.string,
|
||||||
|
token: PropTypes.string
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
data: [],
|
||||||
|
loading: false,
|
||||||
|
text: '',
|
||||||
|
total: -1,
|
||||||
|
showOptionsDropdown: false,
|
||||||
|
globalUsers: true,
|
||||||
|
type: 'channels'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.load({});
|
||||||
|
}
|
||||||
|
|
||||||
|
onSearchChangeText = (text) => {
|
||||||
|
this.setState({ text });
|
||||||
|
}
|
||||||
|
|
||||||
|
onPressItem = (item) => {
|
||||||
|
const { navigation } = this.props;
|
||||||
|
try {
|
||||||
|
const onPressItem = navigation.getParam('onPressItem', () => {});
|
||||||
|
onPressItem(item);
|
||||||
|
} catch (error) {
|
||||||
|
console.log('DirectoryView -> onPressItem -> error', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line react/sort-comp
|
||||||
|
load = debounce(async({ newSearch = false }) => {
|
||||||
|
if (newSearch) {
|
||||||
|
this.setState({ data: [], total: -1, loading: false });
|
||||||
|
}
|
||||||
|
|
||||||
|
const {
|
||||||
|
loading, text, total, data: { length }
|
||||||
|
} = this.state;
|
||||||
|
if (loading || length === total) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState({ loading: true });
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { data, type, globalUsers } = this.state;
|
||||||
|
const query = { text, type, workspace: globalUsers ? 'all' : 'local' };
|
||||||
|
const directories = await RocketChat.getDirectory({
|
||||||
|
query,
|
||||||
|
offset: data.length,
|
||||||
|
count: 50,
|
||||||
|
sort: (type === 'users') ? { username: 1 } : { usersCount: -1 }
|
||||||
|
});
|
||||||
|
if (directories.success) {
|
||||||
|
this.setState({
|
||||||
|
data: [...data, ...directories.result],
|
||||||
|
loading: false,
|
||||||
|
total: directories.total
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.setState({ loading: false });
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
log('err_load_directory', error);
|
||||||
|
this.setState({ loading: false });
|
||||||
|
}
|
||||||
|
}, 200)
|
||||||
|
|
||||||
|
search = () => {
|
||||||
|
this.load({ newSearch: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
changeType = (type) => {
|
||||||
|
this.setState({ type, data: [] }, () => this.search());
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleWorkspace = () => {
|
||||||
|
this.setState(({ globalUsers }) => ({ globalUsers: !globalUsers, data: [] }), () => this.search());
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleDropdown = () => {
|
||||||
|
this.setState(({ showOptionsDropdown }) => ({ showOptionsDropdown: !showOptionsDropdown }));
|
||||||
|
}
|
||||||
|
|
||||||
|
goRoom = async({ rid, name, t }) => {
|
||||||
|
const { navigation } = this.props;
|
||||||
|
await navigation.navigate('RoomsListView');
|
||||||
|
navigation.navigate('RoomView', { rid, name, t });
|
||||||
|
}
|
||||||
|
|
||||||
|
onPressItem = async(item) => {
|
||||||
|
const { type } = this.state;
|
||||||
|
if (type === 'users') {
|
||||||
|
const result = await RocketChat.createDirectMessage(item.username);
|
||||||
|
if (result.success) {
|
||||||
|
this.goRoom({ rid: result.room._id, name: item.username, t: 'd' });
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.goRoom({ rid: item._id, name: item.name, t: 'c' });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
renderHeader = () => {
|
||||||
|
const { type } = this.state;
|
||||||
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
<SearchBox
|
||||||
|
onChangeText={this.onSearchChangeText}
|
||||||
|
onSubmitEditing={this.search}
|
||||||
|
testID='federation-view-search'
|
||||||
|
/>
|
||||||
|
<Touch onPress={this.toggleDropdown} testID='federation-view-create-channel'>
|
||||||
|
<View style={[sharedStyles.separatorVertical, styles.toggleDropdownContainer]}>
|
||||||
|
<CustomIcon style={styles.toggleDropdownIcon} size={20} name={type === 'users' ? 'user' : 'hashtag'} />
|
||||||
|
<Text style={styles.toggleDropdownText}>{type === 'users' ? I18n.t('Users') : I18n.t('Channels')}</Text>
|
||||||
|
<CustomIcon name='arrow-down' size={20} style={styles.toggleDropdownArrow} />
|
||||||
|
</View>
|
||||||
|
</Touch>
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderSeparator = () => <View style={[sharedStyles.separator, styles.separator]} />;
|
||||||
|
|
||||||
|
renderItem = ({ item, index }) => {
|
||||||
|
const { data, type } = this.state;
|
||||||
|
const { baseUrl, user } = this.props;
|
||||||
|
|
||||||
|
let style;
|
||||||
|
if (index === data.length - 1) {
|
||||||
|
style = sharedStyles.separatorBottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
const commonProps = {
|
||||||
|
title: item.name,
|
||||||
|
onPress: () => this.onPressItem(item),
|
||||||
|
baseUrl,
|
||||||
|
testID: `federation-view-item-${ item.name }`,
|
||||||
|
style,
|
||||||
|
user
|
||||||
|
};
|
||||||
|
|
||||||
|
if (type === 'users') {
|
||||||
|
return (
|
||||||
|
<DirectoryItem
|
||||||
|
avatar={item.username}
|
||||||
|
description={item.username}
|
||||||
|
rightLabel={item.federation && item.federation.peer}
|
||||||
|
type='d'
|
||||||
|
{...commonProps}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<DirectoryItem
|
||||||
|
avatar={item.name}
|
||||||
|
description={item.topic}
|
||||||
|
rightLabel={I18n.t('N_users', { n: item.usersCount })}
|
||||||
|
type='c'
|
||||||
|
{...commonProps}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
render = () => {
|
||||||
|
const {
|
||||||
|
data, loading, showOptionsDropdown, type, globalUsers
|
||||||
|
} = this.state;
|
||||||
|
const { isFederationEnabled } = this.props;
|
||||||
|
return (
|
||||||
|
<SafeAreaView style={styles.safeAreaView} testID='directory-view' forceInset={{ bottom: 'never' }}>
|
||||||
|
<StatusBar />
|
||||||
|
<FlatList
|
||||||
|
data={data}
|
||||||
|
style={styles.list}
|
||||||
|
contentContainerStyle={styles.listContainer}
|
||||||
|
extraData={this.state}
|
||||||
|
keyExtractor={item => item._id}
|
||||||
|
ListHeaderComponent={this.renderHeader}
|
||||||
|
renderItem={this.renderItem}
|
||||||
|
ItemSeparatorComponent={this.renderSeparator}
|
||||||
|
keyboardShouldPersistTaps='always'
|
||||||
|
ListFooterComponent={loading ? <RCActivityIndicator /> : null}
|
||||||
|
onEndReached={() => this.load({})}
|
||||||
|
/>
|
||||||
|
{showOptionsDropdown
|
||||||
|
? (
|
||||||
|
<Options
|
||||||
|
type={type}
|
||||||
|
globalUsers={globalUsers}
|
||||||
|
close={this.toggleDropdown}
|
||||||
|
changeType={this.changeType}
|
||||||
|
toggleWorkspace={this.toggleWorkspace}
|
||||||
|
isFederationEnabled={isFederationEnabled}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
: null}
|
||||||
|
</SafeAreaView>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,151 @@
|
||||||
|
import { StyleSheet } from 'react-native';
|
||||||
|
|
||||||
|
import { COLOR_WHITE, COLOR_SEPARATOR, COLOR_PRIMARY } from '../../constants/colors';
|
||||||
|
import { isIOS } from '../../utils/deviceInfo';
|
||||||
|
import sharedStyles from '../Styles';
|
||||||
|
|
||||||
|
export default StyleSheet.create({
|
||||||
|
safeAreaView: {
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: isIOS ? '#F7F8FA' : '#E1E5E8'
|
||||||
|
},
|
||||||
|
list: {
|
||||||
|
flex: 1
|
||||||
|
},
|
||||||
|
listContainer: {
|
||||||
|
paddingBottom: 30
|
||||||
|
},
|
||||||
|
separator: {
|
||||||
|
marginLeft: 60
|
||||||
|
},
|
||||||
|
toggleDropdownContainer: {
|
||||||
|
height: 47,
|
||||||
|
backgroundColor: COLOR_WHITE,
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center'
|
||||||
|
},
|
||||||
|
toggleDropdownIcon: {
|
||||||
|
color: COLOR_PRIMARY,
|
||||||
|
marginLeft: 20,
|
||||||
|
marginRight: 17
|
||||||
|
},
|
||||||
|
toggleDropdownText: {
|
||||||
|
flex: 1,
|
||||||
|
color: COLOR_PRIMARY,
|
||||||
|
fontSize: 17,
|
||||||
|
...sharedStyles.textRegular
|
||||||
|
},
|
||||||
|
toggleDropdownArrow: {
|
||||||
|
...sharedStyles.textColorDescription,
|
||||||
|
marginRight: 15
|
||||||
|
},
|
||||||
|
dropdownContainer: {
|
||||||
|
backgroundColor: COLOR_WHITE,
|
||||||
|
width: '100%',
|
||||||
|
position: 'absolute',
|
||||||
|
top: 0
|
||||||
|
},
|
||||||
|
backdrop: {
|
||||||
|
...StyleSheet.absoluteFill,
|
||||||
|
backgroundColor: '#000000'
|
||||||
|
},
|
||||||
|
dropdownContainerHeader: {
|
||||||
|
height: 47,
|
||||||
|
borderBottomWidth: StyleSheet.hairlineWidth,
|
||||||
|
borderColor: COLOR_SEPARATOR,
|
||||||
|
alignItems: 'center',
|
||||||
|
backgroundColor: isIOS ? COLOR_WHITE : '#54585E',
|
||||||
|
flexDirection: 'row'
|
||||||
|
},
|
||||||
|
dropdownItemButton: {
|
||||||
|
height: 57,
|
||||||
|
justifyContent: 'center'
|
||||||
|
},
|
||||||
|
dropdownItemContainer: {
|
||||||
|
flex: 1,
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center'
|
||||||
|
},
|
||||||
|
dropdownItemText: {
|
||||||
|
fontSize: 18,
|
||||||
|
flex: 1,
|
||||||
|
...sharedStyles.textColorNormal,
|
||||||
|
...sharedStyles.textRegular
|
||||||
|
},
|
||||||
|
dropdownItemDescription: {
|
||||||
|
fontSize: 14,
|
||||||
|
flex: 1,
|
||||||
|
marginTop: 2,
|
||||||
|
...sharedStyles.textColorDescription,
|
||||||
|
...sharedStyles.textRegular
|
||||||
|
},
|
||||||
|
dropdownToggleText: {
|
||||||
|
fontSize: 15,
|
||||||
|
flex: 1,
|
||||||
|
marginLeft: 15,
|
||||||
|
...sharedStyles.textColorDescription,
|
||||||
|
...sharedStyles.textRegular
|
||||||
|
},
|
||||||
|
dropdownItemIcon: {
|
||||||
|
width: 22,
|
||||||
|
height: 22,
|
||||||
|
marginHorizontal: 15,
|
||||||
|
...sharedStyles.textColorDescription
|
||||||
|
},
|
||||||
|
dropdownSeparator: {
|
||||||
|
height: StyleSheet.hairlineWidth,
|
||||||
|
backgroundColor: COLOR_SEPARATOR,
|
||||||
|
marginHorizontal: 15,
|
||||||
|
flex: 1
|
||||||
|
},
|
||||||
|
directoryItemButton: {
|
||||||
|
height: 54,
|
||||||
|
backgroundColor: COLOR_WHITE
|
||||||
|
},
|
||||||
|
directoryItemContainer: {
|
||||||
|
flex: 1,
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
paddingHorizontal: 15
|
||||||
|
},
|
||||||
|
directoryItemAvatar: {
|
||||||
|
marginRight: 12
|
||||||
|
},
|
||||||
|
directoryItemTextTitle: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center'
|
||||||
|
},
|
||||||
|
directoryItemTextContainer: {
|
||||||
|
flex: 1,
|
||||||
|
flexDirection: 'column',
|
||||||
|
justifyContent: 'center'
|
||||||
|
},
|
||||||
|
directoryItemName: {
|
||||||
|
flex: 1,
|
||||||
|
fontSize: 17,
|
||||||
|
...sharedStyles.textMedium,
|
||||||
|
...sharedStyles.textColorNormal
|
||||||
|
},
|
||||||
|
directoryItemUsername: {
|
||||||
|
fontSize: 14,
|
||||||
|
...sharedStyles.textRegular,
|
||||||
|
...sharedStyles.textColorDescription
|
||||||
|
},
|
||||||
|
directoryItemLabel: {
|
||||||
|
fontSize: 14,
|
||||||
|
paddingLeft: 10,
|
||||||
|
...sharedStyles.textRegular,
|
||||||
|
...sharedStyles.textColorDescription
|
||||||
|
},
|
||||||
|
inverted: {
|
||||||
|
transform: [{ scaleY: -1 }]
|
||||||
|
},
|
||||||
|
globalUsersContainer: {
|
||||||
|
padding: 15
|
||||||
|
},
|
||||||
|
globalUsersTextContainer: {
|
||||||
|
flex: 1,
|
||||||
|
flexDirection: 'column'
|
||||||
|
}
|
||||||
|
});
|
|
@ -40,7 +40,8 @@ const styles = StyleSheet.create({
|
||||||
},
|
},
|
||||||
createChannelIcon: {
|
createChannelIcon: {
|
||||||
color: COLOR_PRIMARY,
|
color: COLOR_PRIMARY,
|
||||||
marginHorizontal: 18
|
marginLeft: 18,
|
||||||
|
marginRight: 15
|
||||||
},
|
},
|
||||||
createChannelText: {
|
createChannelText: {
|
||||||
color: COLOR_PRIMARY,
|
color: COLOR_PRIMARY,
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
|
|
||||||
import { CustomIcon } from '../../lib/Icons';
|
|
||||||
import styles from './styles';
|
|
||||||
|
|
||||||
const Check = React.memo(() => <CustomIcon style={styles.sortIcon} size={22} name='check' />);
|
|
||||||
|
|
||||||
export default Check;
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { View, Text } from 'react-native';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
import { CustomIcon } from '../../../lib/Icons';
|
||||||
|
import I18n from '../../../i18n';
|
||||||
|
import Touch from '../../../utils/touch';
|
||||||
|
import styles from '../styles';
|
||||||
|
import DisclosureIndicator from '../../../containers/DisclosureIndicator';
|
||||||
|
|
||||||
|
|
||||||
|
const Directory = React.memo(({ goDirectory }) => (
|
||||||
|
<Touch
|
||||||
|
key='rooms-list-view-sort'
|
||||||
|
onPress={goDirectory}
|
||||||
|
style={styles.dropdownContainerHeader}
|
||||||
|
>
|
||||||
|
<View style={styles.sortItemContainer}>
|
||||||
|
<CustomIcon style={styles.directoryIcon} size={22} name='discover' />
|
||||||
|
<Text style={styles.directoryText}>{I18n.t('Directory')}</Text>
|
||||||
|
<DisclosureIndicator />
|
||||||
|
</View>
|
||||||
|
</Touch>
|
||||||
|
));
|
||||||
|
|
||||||
|
Directory.propTypes = {
|
||||||
|
goDirectory: PropTypes.func
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Directory;
|
|
@ -2,13 +2,15 @@ import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
import SearchBar from './SearchBar';
|
import SearchBar from './SearchBar';
|
||||||
|
import Directory from './Directory';
|
||||||
import Sort from './Sort';
|
import Sort from './Sort';
|
||||||
|
|
||||||
const ListHeader = React.memo(({
|
const ListHeader = React.memo(({
|
||||||
searchLength, sortBy, onChangeSearchText, toggleSort
|
searchLength, sortBy, onChangeSearchText, toggleSort, goDirectory
|
||||||
}) => (
|
}) => (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<SearchBar onChangeSearchText={onChangeSearchText} />
|
<SearchBar onChangeSearchText={onChangeSearchText} />
|
||||||
|
<Directory goDirectory={goDirectory} />
|
||||||
<Sort searchLength={searchLength} sortBy={sortBy} toggleSort={toggleSort} />
|
<Sort searchLength={searchLength} sortBy={sortBy} toggleSort={toggleSort} />
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
));
|
));
|
||||||
|
@ -17,7 +19,8 @@ ListHeader.propTypes = {
|
||||||
searchLength: PropTypes.number,
|
searchLength: PropTypes.number,
|
||||||
sortBy: PropTypes.string,
|
sortBy: PropTypes.string,
|
||||||
onChangeSearchText: PropTypes.func,
|
onChangeSearchText: PropTypes.func,
|
||||||
toggleSort: PropTypes.func
|
toggleSort: PropTypes.func,
|
||||||
|
goDirectory: PropTypes.func
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ListHeader;
|
export default ListHeader;
|
||||||
|
|
|
@ -16,7 +16,7 @@ import Touch from '../../utils/touch';
|
||||||
import RocketChat from '../../lib/rocketchat';
|
import RocketChat from '../../lib/rocketchat';
|
||||||
import I18n from '../../i18n';
|
import I18n from '../../i18n';
|
||||||
import EventEmitter from '../../utils/events';
|
import EventEmitter from '../../utils/events';
|
||||||
import Check from './Check';
|
import Check from '../../containers/Check';
|
||||||
|
|
||||||
const ROW_HEIGHT = 68;
|
const ROW_HEIGHT = 68;
|
||||||
const ANIMATION_DURATION = 200;
|
const ANIMATION_DURATION = 200;
|
||||||
|
|
|
@ -12,7 +12,7 @@ import { setPreference } from '../../actions/sortPreferences';
|
||||||
import log from '../../utils/log';
|
import log from '../../utils/log';
|
||||||
import I18n from '../../i18n';
|
import I18n from '../../i18n';
|
||||||
import { CustomIcon } from '../../lib/Icons';
|
import { CustomIcon } from '../../lib/Icons';
|
||||||
import Check from './Check';
|
import Check from '../../containers/Check';
|
||||||
|
|
||||||
const ANIMATION_DURATION = 200;
|
const ANIMATION_DURATION = 200;
|
||||||
|
|
||||||
|
@ -106,7 +106,7 @@ export default class Sort extends PureComponent {
|
||||||
render() {
|
render() {
|
||||||
const translateY = this.animatedValue.interpolate({
|
const translateY = this.animatedValue.interpolate({
|
||||||
inputRange: [0, 1],
|
inputRange: [0, 1],
|
||||||
outputRange: [-245, 41]
|
outputRange: [-326, 0]
|
||||||
});
|
});
|
||||||
const backdropOpacity = this.animatedValue.interpolate({
|
const backdropOpacity = this.animatedValue.interpolate({
|
||||||
inputRange: [0, 1],
|
inputRange: [0, 1],
|
||||||
|
@ -117,14 +117,24 @@ export default class Sort extends PureComponent {
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
[
|
<React.Fragment>
|
||||||
<TouchableWithoutFeedback key='sort-backdrop' onPress={this.close}>
|
<TouchableWithoutFeedback key='sort-backdrop' onPress={this.close}>
|
||||||
<Animated.View style={[styles.backdrop, { opacity: backdropOpacity }]} />
|
<Animated.View style={[styles.backdrop, { opacity: backdropOpacity }]} />
|
||||||
</TouchableWithoutFeedback>,
|
</TouchableWithoutFeedback>
|
||||||
<Animated.View
|
<Animated.View
|
||||||
key='sort-container'
|
key='sort-container'
|
||||||
style={[styles.dropdownContainer, { transform: [{ translateY }] }]}
|
style={[styles.dropdownContainer, { transform: [{ translateY }] }]}
|
||||||
>
|
>
|
||||||
|
<Touch
|
||||||
|
key='sort-toggle'
|
||||||
|
onPress={this.close}
|
||||||
|
style={styles.dropdownContainerHeader}
|
||||||
|
>
|
||||||
|
<View style={styles.sortItemContainer}>
|
||||||
|
<Text style={styles.sortToggleText}>{I18n.t('Sorting_by', { key: I18n.t(sortBy === 'alphabetical' ? 'name' : 'activity') })}</Text>
|
||||||
|
<CustomIcon style={styles.sortIcon} size={22} name='sort1' />
|
||||||
|
</View>
|
||||||
|
</Touch>
|
||||||
<Touch key='sort-alphabetical' style={styles.sortItemButton} onPress={this.sortByName}>
|
<Touch key='sort-alphabetical' style={styles.sortItemButton} onPress={this.sortByName}>
|
||||||
<View style={styles.sortItemContainer}>
|
<View style={styles.sortItemContainer}>
|
||||||
<CustomIcon style={styles.sortIcon} size={22} name='sort' />
|
<CustomIcon style={styles.sortIcon} size={22} name='sort' />
|
||||||
|
@ -161,18 +171,8 @@ export default class Sort extends PureComponent {
|
||||||
{showUnread ? <Check /> : null}
|
{showUnread ? <Check /> : null}
|
||||||
</View>
|
</View>
|
||||||
</Touch>
|
</Touch>
|
||||||
</Animated.View>,
|
</Animated.View>
|
||||||
<Touch
|
</React.Fragment>
|
||||||
key='sort-toggle'
|
|
||||||
onPress={this.close}
|
|
||||||
style={[styles.dropdownContainerHeader, styles.sortToggleContainerClose]}
|
|
||||||
>
|
|
||||||
<View style={styles.sortItemContainer}>
|
|
||||||
<Text style={styles.sortToggleText}>{I18n.t('Sorting_by', { key: I18n.t(sortBy === 'alphabetical' ? 'name' : 'activity') })}</Text>
|
|
||||||
<CustomIcon style={styles.sortIcon} size={22} name='sort1' />
|
|
||||||
</View>
|
|
||||||
</Touch>
|
|
||||||
]
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -379,6 +379,11 @@ export default class RoomsListView extends React.Component {
|
||||||
}, 100);
|
}, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
goDirectory = () => {
|
||||||
|
const { navigation } = this.props;
|
||||||
|
navigation.navigate('DirectoryView');
|
||||||
|
}
|
||||||
|
|
||||||
getScrollRef = ref => this.scroll = ref
|
getScrollRef = ref => this.scroll = ref
|
||||||
|
|
||||||
renderListHeader = () => {
|
renderListHeader = () => {
|
||||||
|
@ -390,6 +395,7 @@ export default class RoomsListView extends React.Component {
|
||||||
sortBy={sortBy}
|
sortBy={sortBy}
|
||||||
onChangeSearchText={this.search}
|
onChangeSearchText={this.search}
|
||||||
toggleSort={this.toggleSort}
|
toggleSort={this.toggleSort}
|
||||||
|
goDirectory={this.goDirectory}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { StyleSheet } from 'react-native';
|
import { StyleSheet } from 'react-native';
|
||||||
import { isIOS } from '../../utils/deviceInfo';
|
import { isIOS } from '../../utils/deviceInfo';
|
||||||
import {
|
import {
|
||||||
COLOR_SEPARATOR, COLOR_TEXT, COLOR_PRIMARY, COLOR_WHITE
|
COLOR_SEPARATOR, COLOR_TEXT, COLOR_PRIMARY, COLOR_WHITE, COLOR_TEXT_DESCRIPTION
|
||||||
} from '../../constants/colors';
|
} from '../../constants/colors';
|
||||||
|
|
||||||
import sharedStyles from '../Styles';
|
import sharedStyles from '../Styles';
|
||||||
|
@ -147,5 +147,17 @@ export default StyleSheet.create({
|
||||||
height: StyleSheet.hairlineWidth,
|
height: StyleSheet.hairlineWidth,
|
||||||
backgroundColor: COLOR_SEPARATOR,
|
backgroundColor: COLOR_SEPARATOR,
|
||||||
marginLeft: 72
|
marginLeft: 72
|
||||||
|
},
|
||||||
|
directoryIcon: {
|
||||||
|
width: 22,
|
||||||
|
height: 22,
|
||||||
|
marginHorizontal: 15,
|
||||||
|
color: isIOS ? COLOR_PRIMARY : COLOR_TEXT_DESCRIPTION
|
||||||
|
},
|
||||||
|
directoryText: {
|
||||||
|
fontSize: 15,
|
||||||
|
flex: 1,
|
||||||
|
color: isIOS ? COLOR_PRIMARY : COLOR_TEXT_DESCRIPTION,
|
||||||
|
...sharedStyles.textRegular
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue