[NEW] Create channel layout (#420)
* RoomsListView layout * Rooms list layout * Sort component * Header icons * Default header colors * Add server dropdown * Close sort dropdown if server dropdown will open * UserItem * Room type icon * Search working * Tests updated * Android layout * Using realm queries instead of array iterates * Animation duration * Fixed render bug * - NewMessageView - backButtonTitle always empty - SearchBox created * New create channel layout * Search refactored * loginSuccess dismiss modal * Tests working
After Width: | Height: | Size: 402 B |
After Width: | Height: | Size: 747 B |
After Width: | Height: | Size: 276 B |
After Width: | Height: | Size: 458 B |
After Width: | Height: | Size: 451 B |
After Width: | Height: | Size: 959 B |
After Width: | Height: | Size: 621 B |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 900 B |
After Width: | Height: | Size: 2.0 KiB |
|
@ -84,7 +84,9 @@ export const NAVIGATION = createRequestTypes('NAVIGATION', ['SET']);
|
|||
export const SERVER = createRequestTypes('SERVER', [
|
||||
...defaultTypes,
|
||||
'SELECT_SUCCESS',
|
||||
'SELECT_REQUEST'
|
||||
'SELECT_REQUEST',
|
||||
'INIT_ADD',
|
||||
'FINISH_ADD'
|
||||
]);
|
||||
export const METEOR = createRequestTypes('METEOR_CONNECT', [...defaultTypes, 'DISCONNECT', 'DISCONNECT_BY_USER']);
|
||||
export const LOGOUT = 'LOGOUT'; // logout is always success
|
||||
|
|
|
@ -33,3 +33,15 @@ export function serverFailure(err) {
|
|||
err
|
||||
};
|
||||
}
|
||||
|
||||
export function serverInitAdd() {
|
||||
return {
|
||||
type: SERVER.INIT_ADD
|
||||
};
|
||||
}
|
||||
|
||||
export function serverFinishAdd() {
|
||||
return {
|
||||
type: SERVER.FINISH_ADD
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
export const AVATAR_COLORS = ['#F44336', '#E91E63', '#9C27B0', '#673AB7', '#3F51B5', '#2196F3', '#03A9F4', '#00BCD4', '#009688', '#4CAF50', '#8BC34A', '#CDDC39', '#FFC107', '#FF9800', '#FF5722', '#795548', '#9E9E9E', '#607D8B'];
|
||||
export const ESLINT_FIX = null;
|
||||
export const COLOR_DANGER = '#f5455c';
|
||||
export const COLOR_BUTTON_PRIMARY = '#2D6AEA';
|
||||
export const COLOR_TEXT = '#292E35';
|
||||
export const COLOR_SEPARATOR = '#CBCED1';
|
||||
export const STATUS_COLORS = {
|
||||
online: '#2de0a5',
|
||||
busy: COLOR_DANGER,
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
import React from 'react';
|
||||
import { View, StyleSheet, Image, TextInput, Platform } from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import I18n from '../i18n';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
backgroundColor: Platform.OS === 'ios' ? '#F7F8FA' : '#54585E'
|
||||
},
|
||||
searchBox: {
|
||||
alignItems: 'center',
|
||||
backgroundColor: '#E1E5E8',
|
||||
borderRadius: 10,
|
||||
color: '#8E8E93',
|
||||
flexDirection: 'row',
|
||||
fontSize: 17,
|
||||
height: 36,
|
||||
margin: 16,
|
||||
marginVertical: 10,
|
||||
paddingHorizontal: 10
|
||||
},
|
||||
icon: {
|
||||
width: 14,
|
||||
height: 14
|
||||
},
|
||||
input: {
|
||||
color: '#8E8E93',
|
||||
flex: 1,
|
||||
fontSize: 17,
|
||||
marginLeft: 8,
|
||||
paddingTop: 0,
|
||||
paddingBottom: 0
|
||||
}
|
||||
});
|
||||
|
||||
const SearchBox = ({ onChangeText, testID }) => (
|
||||
<View style={styles.container}>
|
||||
<View style={styles.searchBox}>
|
||||
<Image source={{ uri: 'textinput_search' }} style={styles.icon} />
|
||||
<TextInput
|
||||
autoCapitalize='none'
|
||||
autoCorrect={false}
|
||||
blurOnSubmit
|
||||
clearButtonMode='while-editing'
|
||||
placeholder={I18n.t('Search')}
|
||||
returnKeyType='search'
|
||||
style={styles.input}
|
||||
testID={testID}
|
||||
underlineColorAndroid='transparent'
|
||||
onChangeText={onChangeText}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
|
||||
SearchBox.propTypes = {
|
||||
onChangeText: PropTypes.func.isRequired,
|
||||
testID: PropTypes.string
|
||||
};
|
||||
|
||||
export default SearchBox;
|
|
@ -236,6 +236,7 @@ export default class Sidebar extends Component {
|
|||
setTimeout(() => {
|
||||
NavigationActions.push({
|
||||
screen: 'NewServerView',
|
||||
backButtonTitle: '',
|
||||
passProps: {
|
||||
server: item.id
|
||||
},
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
export default {
|
||||
'1_online_member': '1 online member',
|
||||
'1_person_reacted': '1 person reacted',
|
||||
'1_user': '1 user',
|
||||
'error-action-not-allowed': '{{action}} is not allowed',
|
||||
'error-application-not-found': 'Application not found',
|
||||
'error-archived-duplicate-name': 'There\'s an archived channel with name {{room_name}}',
|
||||
|
@ -110,6 +111,7 @@ export default {
|
|||
Cancel_recording: 'Cancel recording',
|
||||
Cancel: 'Cancel',
|
||||
changing_avatar: 'changing avatar',
|
||||
creating_channel: 'creating channel',
|
||||
Channel_Name: 'Channel Name',
|
||||
Channels: 'Channels',
|
||||
Chats: 'Chats',
|
||||
|
@ -160,6 +162,7 @@ export default {
|
|||
Has_left_the_channel: 'Has left the channel',
|
||||
I_have_an_account: 'I have an account',
|
||||
Invisible: 'Invisible',
|
||||
Invite: 'Invite',
|
||||
is_a_valid_RocketChat_instance: 'is a valid Rocket.Chat instance',
|
||||
is_not_a_valid_RocketChat_instance: 'is not a valid Rocket.Chat instance',
|
||||
is_typing: 'is typing',
|
||||
|
@ -188,13 +191,15 @@ export default {
|
|||
muted: 'muted',
|
||||
My_servers: 'My servers',
|
||||
N_online_members: '{{n}} online members',
|
||||
N_person_reacted: '{{n}} people reacted',
|
||||
N_people_reacted: '{{n}} people reacted',
|
||||
N_users: '{{n}} users',
|
||||
name: 'name',
|
||||
Name: 'Name',
|
||||
New_in_RocketChat_question_mark: 'New in Rocket.Chat?',
|
||||
New_Message: 'New Message',
|
||||
New_Password: 'New Password',
|
||||
New_Server: 'New Server',
|
||||
Next: 'Next',
|
||||
No_files: 'No files',
|
||||
No_mentioned_messages: 'No mentioned messages',
|
||||
No_pinned_messages: 'No pinned messages',
|
||||
|
|
|
@ -528,6 +528,56 @@ const RocketChat = {
|
|||
return _sendMessageCall(JSON.parse(JSON.stringify(message)));
|
||||
},
|
||||
|
||||
async search({ text, filterUsers = true, filterRooms = true }) {
|
||||
const searchText = text.trim();
|
||||
if (searchText === '') {
|
||||
delete this.oldPromise;
|
||||
return [];
|
||||
}
|
||||
|
||||
let data = database.objects('subscriptions').filtered('name CONTAINS[c] $0', searchText);
|
||||
|
||||
if (filterUsers && !filterRooms) {
|
||||
data = data.filtered('t = $0', 'd');
|
||||
} else if (!filterUsers && filterRooms) {
|
||||
data = data.filtered('t != $0', 'd');
|
||||
}
|
||||
data = data.slice(0, 7);
|
||||
|
||||
const usernames = data.map(sub => sub.name);
|
||||
try {
|
||||
if (data.length < 7) {
|
||||
if (this.oldPromise) {
|
||||
this.oldPromise('cancel');
|
||||
}
|
||||
|
||||
const { users, rooms } = await Promise.race([
|
||||
RocketChat.spotlight(searchText, usernames, { users: filterUsers, rooms: filterRooms }),
|
||||
new Promise((resolve, reject) => this.oldPromise = reject)
|
||||
]);
|
||||
|
||||
data = data.concat(users.map(user => ({
|
||||
...user,
|
||||
rid: user.username,
|
||||
name: user.username,
|
||||
t: 'd',
|
||||
search: true
|
||||
})), rooms.map(room => ({
|
||||
rid: room._id,
|
||||
...room,
|
||||
search: true
|
||||
})));
|
||||
|
||||
delete this.oldPromise;
|
||||
}
|
||||
|
||||
return data;
|
||||
} catch (e) {
|
||||
console.warn(e);
|
||||
return [];
|
||||
}
|
||||
},
|
||||
|
||||
spotlight(search, usernames, type) {
|
||||
return call('spotlight', search, usernames, type);
|
||||
},
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react';
|
||||
import { Text, View, StyleSheet, Platform } from 'react-native';
|
||||
import { Text, View, StyleSheet, Platform, ViewPropTypes, Image } from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import Avatar from '../containers/Avatar';
|
||||
|
@ -7,7 +7,8 @@ import Touch from '../utils/touch';
|
|||
|
||||
const styles = StyleSheet.create({
|
||||
button: {
|
||||
height: 54
|
||||
height: 54,
|
||||
backgroundColor: '#fff'
|
||||
},
|
||||
container: {
|
||||
flexDirection: 'row'
|
||||
|
@ -24,24 +25,33 @@ const styles = StyleSheet.create({
|
|||
fontSize: 18,
|
||||
color: '#0C0D0F',
|
||||
marginTop: Platform.OS === 'ios' ? 6 : 3,
|
||||
marginBottom: 1
|
||||
marginBottom: 1,
|
||||
textAlign: 'left'
|
||||
},
|
||||
username: {
|
||||
fontSize: 14,
|
||||
color: '#9EA2A8'
|
||||
},
|
||||
icon: {
|
||||
width: 20,
|
||||
height: 20,
|
||||
marginHorizontal: 15,
|
||||
resizeMode: 'contain',
|
||||
alignSelf: 'center'
|
||||
}
|
||||
});
|
||||
|
||||
const UserItem = ({
|
||||
name, username, onPress, testID, onLongPress
|
||||
name, username, onPress, testID, onLongPress, style, icon
|
||||
}) => (
|
||||
<Touch onPress={onPress} onLongPress={onLongPress} style={styles.button} testID={testID}>
|
||||
<View style={styles.container}>
|
||||
<View style={[styles.container, style]}>
|
||||
<Avatar text={username} size={30} type='d' style={styles.avatar} />
|
||||
<View style={styles.textContainer}>
|
||||
<Text style={styles.name}>{name}</Text>
|
||||
<Text style={styles.username}>@{username}</Text>
|
||||
</View>
|
||||
{icon ? <Image source={{ uri: icon }} style={styles.icon} /> : null}
|
||||
</View>
|
||||
</Touch>
|
||||
);
|
||||
|
@ -51,7 +61,9 @@ UserItem.propTypes = {
|
|||
username: PropTypes.string.isRequired,
|
||||
onPress: PropTypes.func.isRequired,
|
||||
testID: PropTypes.string.isRequired,
|
||||
onLongPress: PropTypes.func
|
||||
onLongPress: PropTypes.func,
|
||||
style: ViewPropTypes.style,
|
||||
icon: PropTypes.string
|
||||
};
|
||||
|
||||
export default UserItem;
|
||||
|
|
|
@ -6,7 +6,7 @@ const initialState = {
|
|||
failure: false,
|
||||
server: '',
|
||||
loading: true,
|
||||
adding: true
|
||||
adding: false
|
||||
};
|
||||
|
||||
|
||||
|
@ -16,16 +16,14 @@ export default function server(state = initialState, action) {
|
|||
return {
|
||||
...state,
|
||||
connecting: true,
|
||||
failure: false,
|
||||
adding: true
|
||||
failure: false
|
||||
};
|
||||
case SERVER.FAILURE:
|
||||
return {
|
||||
...state,
|
||||
connecting: false,
|
||||
connected: false,
|
||||
failure: true,
|
||||
adding: false
|
||||
failure: true
|
||||
};
|
||||
case SERVER.SELECT_REQUEST:
|
||||
return {
|
||||
|
@ -43,6 +41,16 @@ export default function server(state = initialState, action) {
|
|||
connected: true,
|
||||
loading: false
|
||||
};
|
||||
case SERVER.INIT_ADD:
|
||||
return {
|
||||
...state,
|
||||
adding: true
|
||||
};
|
||||
case SERVER.FINISH_ADD:
|
||||
return {
|
||||
...state,
|
||||
adding: false
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
|
|
@ -12,25 +12,26 @@ const create = function* create(data) {
|
|||
|
||||
const handleRequest = function* handleRequest({ data }) {
|
||||
try {
|
||||
// yield delay(1000);
|
||||
const auth = yield select(state => state.login.isAuthenticated);
|
||||
if (!auth) {
|
||||
yield take(LOGIN.SUCCESS);
|
||||
}
|
||||
const result = yield call(create, data);
|
||||
yield put(createChannelSuccess(result));
|
||||
yield delay(300);
|
||||
const { rid, name } = result;
|
||||
NavigationActions.popToRoot();
|
||||
yield delay(1000);
|
||||
NavigationActions.dismissModal();
|
||||
yield delay(600);
|
||||
NavigationActions.push({
|
||||
screen: 'RoomView',
|
||||
title: name,
|
||||
backButtonTitle: '',
|
||||
passProps: {
|
||||
room: { rid, name },
|
||||
rid,
|
||||
name
|
||||
}
|
||||
});
|
||||
yield put(createChannelSuccess(result));
|
||||
} catch (err) {
|
||||
yield put(createChannelFailure(err));
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ const navigate = function* go({ params, sameServer = true }) {
|
|||
if (canOpenRoom) {
|
||||
return NavigationActions.push({
|
||||
screen: 'RoomView',
|
||||
backButtonTitle: '',
|
||||
passProps: {
|
||||
rid: params.rid
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import { put, call, take, takeLatest, select, all } from 'redux-saga/effects';
|
|||
|
||||
import * as types from '../actions/actionsTypes';
|
||||
import { appStart } from '../actions';
|
||||
import { serverFinishAdd } from '../actions/server';
|
||||
import {
|
||||
// loginRequest,
|
||||
// loginSubmit,
|
||||
|
@ -38,13 +39,18 @@ const forgotPasswordCall = args => RocketChat.forgotPassword(args);
|
|||
const handleLoginSuccess = function* handleLoginSuccess() {
|
||||
try {
|
||||
const user = yield select(getUser);
|
||||
const adding = yield select(state => state.server.adding);
|
||||
yield AsyncStorage.setItem(RocketChat.TOKEN_KEY, user.token);
|
||||
if (!user.username || user.isRegistering) {
|
||||
yield put(registerIncomplete());
|
||||
} else {
|
||||
yield delay(300);
|
||||
NavigationActions.dismissModal();
|
||||
yield put(appStart('inside'));
|
||||
if (adding) {
|
||||
NavigationActions.dismissModal();
|
||||
} else {
|
||||
yield put(appStart('inside'));
|
||||
}
|
||||
yield put(serverFinishAdd());
|
||||
}
|
||||
} catch (e) {
|
||||
log('handleLoginSuccess', e);
|
||||
|
|
|
@ -80,6 +80,7 @@ const goRoom = function* goRoom({ rid, name }) {
|
|||
yield delay(1000);
|
||||
NavigationActions.push({
|
||||
screen: 'RoomView',
|
||||
backButtonTitle: '',
|
||||
passProps: {
|
||||
room: { rid, name },
|
||||
rid,
|
||||
|
|
|
@ -44,7 +44,7 @@ const handleSelectServer = function* handleSelectServer({ server }) {
|
|||
const handleServerRequest = function* handleServerRequest({ server }) {
|
||||
try {
|
||||
yield call(validate, server);
|
||||
yield call(NavigationActions.push, { screen: 'LoginSignupView', title: server });
|
||||
yield call(NavigationActions.push, { screen: 'LoginSignupView', title: server, backButtonTitle: '' });
|
||||
database.databases.serversDB.write(() => {
|
||||
database.databases.serversDB.create('servers', { id: server, current: false }, true);
|
||||
});
|
||||
|
|
|
@ -1,29 +1,85 @@
|
|||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import PropTypes from 'prop-types';
|
||||
import { View, Text, Switch, SafeAreaView, ScrollView, Platform } from 'react-native';
|
||||
import { View, Text, Switch, SafeAreaView, ScrollView, TextInput, StyleSheet, FlatList, Platform } from 'react-native';
|
||||
|
||||
import RCTextInput from '../containers/TextInput';
|
||||
import Loading from '../containers/Loading';
|
||||
import LoggedView from './View';
|
||||
import { createChannelRequest } from '../actions/createChannel';
|
||||
import styles from './Styles';
|
||||
import { removeUser } from '../actions/selectedUsers';
|
||||
import sharedStyles from './Styles';
|
||||
import KeyboardView from '../presentation/KeyboardView';
|
||||
import scrollPersistTaps from '../utils/scrollPersistTaps';
|
||||
import Button from '../containers/Button';
|
||||
import I18n from '../i18n';
|
||||
import UserItem from '../presentation/UserItem';
|
||||
import { showErrorAlert } from '../utils/info';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
backgroundColor: '#f7f8fa'
|
||||
},
|
||||
list: {
|
||||
width: '100%',
|
||||
backgroundColor: '#FFFFFF'
|
||||
},
|
||||
separator: {
|
||||
marginLeft: 60
|
||||
},
|
||||
formSeparator: {
|
||||
marginLeft: 15
|
||||
},
|
||||
input: {
|
||||
height: 54,
|
||||
paddingHorizontal: 18,
|
||||
color: '#9EA2A8',
|
||||
backgroundColor: '#fff',
|
||||
fontSize: 18
|
||||
},
|
||||
swithContainer: {
|
||||
height: 54,
|
||||
backgroundColor: '#fff',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
flexDirection: 'row',
|
||||
paddingHorizontal: 18
|
||||
},
|
||||
label: {
|
||||
color: '#0C0D0F',
|
||||
fontSize: 18,
|
||||
fontWeight: '500'
|
||||
},
|
||||
invitedHeader: {
|
||||
marginTop: 18,
|
||||
marginHorizontal: 15,
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center'
|
||||
},
|
||||
invitedTitle: {
|
||||
color: '#2F343D',
|
||||
fontSize: 22,
|
||||
fontWeight: 'bold',
|
||||
lineHeight: 41
|
||||
},
|
||||
invitedCount: {
|
||||
color: '#9EA2A8',
|
||||
fontSize: 15
|
||||
}
|
||||
});
|
||||
|
||||
@connect(state => ({
|
||||
createChannel: state.createChannel,
|
||||
users: state.selectedUsers.users
|
||||
}), dispatch => ({
|
||||
create: data => dispatch(createChannelRequest(data))
|
||||
create: data => dispatch(createChannelRequest(data)),
|
||||
removeUser: user => dispatch(removeUser(user))
|
||||
}))
|
||||
/** @extends React.Component */
|
||||
export default class CreateChannelView extends LoggedView {
|
||||
static propTypes = {
|
||||
navigator: PropTypes.object,
|
||||
create: PropTypes.func.isRequired,
|
||||
removeUser: PropTypes.func.isRequired,
|
||||
createChannel: PropTypes.object.isRequired,
|
||||
users: PropTypes.array.isRequired
|
||||
};
|
||||
|
@ -36,6 +92,7 @@ export default class CreateChannelView extends LoggedView {
|
|||
readOnly: false,
|
||||
broadcast: false
|
||||
};
|
||||
props.navigator.setOnNavigatorEvent(this.onNavigatorEvent.bind(this));
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
|
@ -44,6 +101,36 @@ export default class CreateChannelView extends LoggedView {
|
|||
}, 600);
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
if (this.props.createChannel.error && prevProps.createChannel.error !== this.props.createChannel.error) {
|
||||
setTimeout(() => {
|
||||
const msg = this.props.createChannel.error.reason || I18n.t('There_was_an_error_while_action', { action: I18n.t('creating_channel') });
|
||||
showErrorAlert(msg);
|
||||
}, 300);
|
||||
}
|
||||
}
|
||||
|
||||
onChangeText = (channelName) => {
|
||||
const rightButtons = [];
|
||||
if (channelName.trim().length > 0) {
|
||||
rightButtons.push({
|
||||
id: 'create',
|
||||
title: 'Create',
|
||||
testID: 'create-channel-submit'
|
||||
});
|
||||
}
|
||||
this.props.navigator.setButtons({ rightButtons });
|
||||
this.setState({ channelName });
|
||||
}
|
||||
|
||||
async onNavigatorEvent(event) {
|
||||
if (event.type === 'NavBarButtonPress') {
|
||||
if (event.id === 'create') {
|
||||
this.submit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
submit = () => {
|
||||
if (!this.state.channelName.trim() || this.props.createChannel.isFetching) {
|
||||
return;
|
||||
|
@ -62,47 +149,35 @@ export default class CreateChannelView extends LoggedView {
|
|||
});
|
||||
}
|
||||
|
||||
renderChannelNameError() {
|
||||
if (
|
||||
!this.props.createChannel.failure ||
|
||||
this.props.createChannel.error.error !== 'error-duplicate-channel-name'
|
||||
) {
|
||||
return null;
|
||||
removeUser = (user) => {
|
||||
if (this.props.users.length === 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
return (
|
||||
<Text style={[styles.label_white, styles.label_error]} testID='create-channel-error'>
|
||||
{this.props.createChannel.error.reason}
|
||||
</Text>
|
||||
);
|
||||
this.props.removeUser(user);
|
||||
}
|
||||
|
||||
renderSwitch = ({
|
||||
id, value, label, description, onValueChange, disabled = false
|
||||
id, value, label, onValueChange, disabled = false
|
||||
}) => (
|
||||
<View style={{ marginBottom: 15 }}>
|
||||
<View style={styles.switchContainer}>
|
||||
<Switch
|
||||
value={value}
|
||||
onValueChange={onValueChange}
|
||||
testID={`create-channel-${ id }`}
|
||||
onTintColor='#2de0a5'
|
||||
tintColor={Platform.OS === 'android' ? '#f5455c' : null}
|
||||
disabled={disabled}
|
||||
/>
|
||||
<Text style={styles.switchLabel}>{label}</Text>
|
||||
</View>
|
||||
<Text style={styles.switchDescription}>{description}</Text>
|
||||
<View style={styles.swithContainer}>
|
||||
<Text style={styles.label}>{I18n.t(label)}</Text>
|
||||
<Switch
|
||||
value={value}
|
||||
onValueChange={onValueChange}
|
||||
testID={`create-channel-${ id }`}
|
||||
onTintColor='#2de0a5'
|
||||
tintColor={Platform.OS === 'android' ? '#f5455c' : null}
|
||||
disabled={disabled}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
)
|
||||
|
||||
renderType() {
|
||||
const { type } = this.state;
|
||||
return this.renderSwitch({
|
||||
id: 'type',
|
||||
value: type,
|
||||
label: type ? I18n.t('Private_Channel') : I18n.t('Public_Channel'),
|
||||
description: type ? I18n.t('Just_invited_people_can_access_this_channel') : I18n.t('Everyone_can_access_this_channel'),
|
||||
label: 'Private_Channel',
|
||||
onValueChange: value => this.setState({ type: value })
|
||||
});
|
||||
}
|
||||
|
@ -112,8 +187,7 @@ export default class CreateChannelView extends LoggedView {
|
|||
return this.renderSwitch({
|
||||
id: 'readonly',
|
||||
value: readOnly,
|
||||
label: I18n.t('Read_Only_Channel'),
|
||||
description: readOnly ? I18n.t('Only_authorized_users_can_write_new_messages') : I18n.t('All_users_in_the_channel_can_write_new_messages'),
|
||||
label: 'Read_Only_Channel',
|
||||
onValueChange: value => this.setState({ readOnly: value }),
|
||||
disabled: broadcast
|
||||
});
|
||||
|
@ -124,8 +198,7 @@ export default class CreateChannelView extends LoggedView {
|
|||
return this.renderSwitch({
|
||||
id: 'broadcast',
|
||||
value: broadcast,
|
||||
label: I18n.t('Broadcast_Channel'),
|
||||
description: I18n.t('Broadcast_channel_Description'),
|
||||
label: 'Broadcast_Channel',
|
||||
onValueChange: (value) => {
|
||||
this.setState({
|
||||
broadcast: value,
|
||||
|
@ -135,39 +208,70 @@ export default class CreateChannelView extends LoggedView {
|
|||
});
|
||||
}
|
||||
|
||||
renderSeparator = () => <View style={[sharedStyles.separator, styles.separator]} />
|
||||
|
||||
renderFormSeparator = () => <View style={[sharedStyles.separator, styles.formSeparator]} />
|
||||
|
||||
renderItem = ({ item }) => (
|
||||
<UserItem
|
||||
name={item.fname}
|
||||
username={item.name}
|
||||
onPress={() => this.removeUser(item)}
|
||||
testID={`create-channel-view-item-${ item.name }`}
|
||||
/>
|
||||
)
|
||||
|
||||
renderInvitedList = () => (
|
||||
<FlatList
|
||||
data={this.props.users}
|
||||
extraData={this.props.users}
|
||||
keyExtractor={item => item._id}
|
||||
style={[styles.list, sharedStyles.separatorVertical]}
|
||||
renderItem={this.renderItem}
|
||||
ItemSeparatorComponent={this.renderSeparator}
|
||||
enableEmptySections
|
||||
keyboardShouldPersistTaps='always'
|
||||
/>
|
||||
)
|
||||
|
||||
render() {
|
||||
const userCount = this.props.users.length;
|
||||
return (
|
||||
<KeyboardView
|
||||
contentContainerStyle={styles.container}
|
||||
contentContainerStyle={[sharedStyles.container, styles.container]}
|
||||
keyboardVerticalOffset={128}
|
||||
>
|
||||
<ScrollView {...scrollPersistTaps} contentContainerStyle={styles.containerScrollView}>
|
||||
<SafeAreaView testID='create-channel-view'>
|
||||
<RCTextInput
|
||||
inputRef={ref => this.channelNameRef = ref}
|
||||
label={I18n.t('Channel_Name')}
|
||||
value={this.state.channelName}
|
||||
onChangeText={channelName => this.setState({ channelName })}
|
||||
placeholder={I18n.t('Type_the_channel_name_here')}
|
||||
returnKeyType='done'
|
||||
testID='create-channel-name'
|
||||
/>
|
||||
{this.renderChannelNameError()}
|
||||
{this.renderType()}
|
||||
{this.renderReadOnly()}
|
||||
{this.renderBroadcast()}
|
||||
<View style={styles.alignItemsFlexStart}>
|
||||
<Button
|
||||
title={I18n.t('Create')}
|
||||
type='primary'
|
||||
onPress={this.submit}
|
||||
disabled={this.state.channelName.length === 0 || this.props.createChannel.isFetching}
|
||||
testID='create-channel-submit'
|
||||
<SafeAreaView testID='create-channel-view'>
|
||||
<ScrollView {...scrollPersistTaps}>
|
||||
<View style={sharedStyles.separatorVertical}>
|
||||
<TextInput
|
||||
ref={ref => this.channelNameRef = ref}
|
||||
style={styles.input}
|
||||
label={I18n.t('Channel_Name')}
|
||||
value={this.state.channelName}
|
||||
onChangeText={this.onChangeText}
|
||||
placeholder={I18n.t('Channel_Name')}
|
||||
returnKeyType='done'
|
||||
testID='create-channel-name'
|
||||
autoCorrect={false}
|
||||
autoCapitalize='none'
|
||||
underlineColorAndroid='transparent'
|
||||
/>
|
||||
{this.renderFormSeparator()}
|
||||
{this.renderType()}
|
||||
{this.renderFormSeparator()}
|
||||
{this.renderReadOnly()}
|
||||
{this.renderFormSeparator()}
|
||||
{this.renderBroadcast()}
|
||||
</View>
|
||||
<View style={styles.invitedHeader}>
|
||||
<Text style={styles.invitedTitle}>{I18n.t('Invite')}</Text>
|
||||
<Text style={styles.invitedCount}>{userCount === 1 ? I18n.t('1_user') : I18n.t('N_users', { n: userCount })}</Text>
|
||||
</View>
|
||||
{this.renderInvitedList()}
|
||||
<Loading visible={this.props.createChannel.isFetching} />
|
||||
</SafeAreaView>
|
||||
</ScrollView>
|
||||
</ScrollView>
|
||||
</SafeAreaView>
|
||||
</KeyboardView>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -182,7 +182,7 @@ export default class LoginSignupView extends LoggedView {
|
|||
this.props.navigator.push({
|
||||
screen: 'LoginView',
|
||||
title: this.props.server,
|
||||
backButtonTitle: I18n.t('Welcome')
|
||||
backButtonTitle: ''
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -190,7 +190,7 @@ export default class LoginSignupView extends LoggedView {
|
|||
this.props.navigator.push({
|
||||
screen: 'RegisterView',
|
||||
title: this.props.server,
|
||||
backButtonTitle: I18n.t('Welcome')
|
||||
backButtonTitle: ''
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -68,7 +68,7 @@ export default class LoginView extends LoggedView {
|
|||
this.props.navigator.push({
|
||||
screen: 'RegisterView',
|
||||
title: this.props.server,
|
||||
backButtonTitle: I18n.t('Login')
|
||||
backButtonTitle: ''
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -76,7 +76,7 @@ export default class LoginView extends LoggedView {
|
|||
this.props.navigator.push({
|
||||
screen: 'ForgotPasswordView',
|
||||
title: I18n.t('Forgot_Password'),
|
||||
backButtonTitle: I18n.t('Login')
|
||||
backButtonTitle: ''
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,166 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { View, StyleSheet, SafeAreaView, FlatList, Text, Platform, Image } from 'react-native';
|
||||
|
||||
import database from '../lib/realm';
|
||||
import RocketChat from '../lib/rocketchat';
|
||||
import UserItem from '../presentation/UserItem';
|
||||
import debounce from '../utils/debounce';
|
||||
import LoggedView from './View';
|
||||
import sharedStyles from './Styles';
|
||||
import I18n from '../i18n';
|
||||
import Touch from '../utils/touch';
|
||||
import SearchBox from '../containers/SearchBox';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
safeAreaView: {
|
||||
flex: 1,
|
||||
backgroundColor: Platform.OS === 'ios' ? '#F7F8FA' : '#E1E5E8'
|
||||
},
|
||||
separator: {
|
||||
marginLeft: 60
|
||||
},
|
||||
createChannelButton: {
|
||||
marginVertical: 25
|
||||
},
|
||||
createChannelContainer: {
|
||||
height: 47,
|
||||
backgroundColor: '#fff',
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center'
|
||||
},
|
||||
createChannelIcon: {
|
||||
width: 24,
|
||||
height: 24,
|
||||
marginHorizontal: 18
|
||||
},
|
||||
createChannelText: {
|
||||
color: '#1D74F5',
|
||||
fontSize: 18
|
||||
}
|
||||
});
|
||||
|
||||
/** @extends React.Component */
|
||||
export default class SelectedUsersView extends LoggedView {
|
||||
static navigatorButtons = {
|
||||
leftButtons: [{
|
||||
id: 'cancel',
|
||||
title: I18n.t('Cancel')
|
||||
}]
|
||||
}
|
||||
|
||||
static propTypes = {
|
||||
navigator: PropTypes.object,
|
||||
onPressItem: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super('NewMessageView', props);
|
||||
this.data = database.objects('subscriptions').filtered('t = $0', 'd').sorted('roomUpdatedAt', true);
|
||||
this.state = {
|
||||
search: []
|
||||
};
|
||||
this.data.addListener(this.updateState);
|
||||
props.navigator.setOnNavigatorEvent(this.onNavigatorEvent.bind(this));
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.updateState.stop();
|
||||
this.data.removeAllListeners();
|
||||
}
|
||||
|
||||
async onNavigatorEvent(event) {
|
||||
if (event.type === 'NavBarButtonPress') {
|
||||
if (event.id === 'cancel') {
|
||||
this.props.navigator.dismissModal();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onSearchChangeText(text) {
|
||||
this.search(text);
|
||||
}
|
||||
|
||||
onPressItem = (item) => {
|
||||
this.props.navigator.dismissModal();
|
||||
setTimeout(() => {
|
||||
this.props.onPressItem(item);
|
||||
}, 600);
|
||||
}
|
||||
|
||||
updateState = debounce(() => {
|
||||
this.forceUpdate();
|
||||
}, 1000);
|
||||
|
||||
search = async(text) => {
|
||||
const result = await RocketChat.search({ text, filterRooms: false });
|
||||
this.setState({
|
||||
search: result
|
||||
});
|
||||
}
|
||||
|
||||
createChannel = () => {
|
||||
this.props.navigator.push({
|
||||
screen: 'SelectedUsersView',
|
||||
title: I18n.t('Select_Users'),
|
||||
backButtonTitle: '',
|
||||
passProps: {
|
||||
nextAction: 'CREATE_CHANNEL'
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
renderHeader = () => (
|
||||
<View>
|
||||
<SearchBox onChangeText={text => this.onSearchChangeText(text)} testID='new-message-view-search' />
|
||||
<Touch onPress={this.createChannel} style={styles.createChannelButton} testID='new-message-view-create-channel'>
|
||||
<View style={[sharedStyles.separatorVertical, styles.createChannelContainer]}>
|
||||
<Image style={styles.createChannelIcon} source={{ uri: 'plus' }} />
|
||||
<Text style={styles.createChannelText}>{I18n.t('Create_Channel')}</Text>
|
||||
</View>
|
||||
</Touch>
|
||||
</View>
|
||||
)
|
||||
|
||||
renderSeparator = () => <View style={[sharedStyles.separator, styles.separator]} />;
|
||||
|
||||
renderItem = ({ item, index }) => {
|
||||
let style = {};
|
||||
if (index === 0) {
|
||||
style = { ...sharedStyles.separatorTop };
|
||||
}
|
||||
if (this.state.search.length > 0 && index === this.state.search.length - 1) {
|
||||
style = { ...style, ...sharedStyles.separatorBottom };
|
||||
}
|
||||
if (this.state.search.length === 0 && index === this.data.length - 1) {
|
||||
style = { ...style, ...sharedStyles.separatorBottom };
|
||||
}
|
||||
return (
|
||||
<UserItem
|
||||
name={item.search ? item.name : item.fname}
|
||||
username={item.search ? item.username : item.name}
|
||||
onPress={() => this.onPressItem(item)}
|
||||
testID={`new-message-view-item-${ item.name }`}
|
||||
style={style}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
renderList = () => (
|
||||
<FlatList
|
||||
data={this.state.search.length > 0 ? this.state.search : this.data}
|
||||
extraData={this.state}
|
||||
keyExtractor={item => item._id}
|
||||
ListHeaderComponent={this.renderHeader}
|
||||
renderItem={this.renderItem}
|
||||
ItemSeparatorComponent={this.renderSeparator}
|
||||
keyboardShouldPersistTaps='always'
|
||||
/>
|
||||
)
|
||||
|
||||
render = () => (
|
||||
<SafeAreaView style={styles.safeAreaView} testID='new-message-view'>
|
||||
{this.renderList()}
|
||||
</SafeAreaView>
|
||||
);
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Text, ScrollView, Keyboard, SafeAreaView, Image, Alert, StyleSheet, Platform } from 'react-native';
|
||||
import { Text, ScrollView, Keyboard, SafeAreaView, Image, Alert, StyleSheet } from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { serverRequest } from '../actions/server';
|
||||
import { serverRequest, selectServerRequest, serverInitAdd, serverFinishAdd } from '../actions/server';
|
||||
import sharedStyles from './Styles';
|
||||
import scrollPersistTaps from '../utils/scrollPersistTaps';
|
||||
import Button from '../containers/Button';
|
||||
|
@ -12,7 +12,6 @@ import LoggedView from './View';
|
|||
import I18n from '../i18n';
|
||||
import { scale, verticalScale, moderateScale } from '../utils/scaling';
|
||||
import KeyboardView from '../presentation/KeyboardView';
|
||||
import { iconsMap } from '../Icons';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
image: {
|
||||
|
@ -45,9 +44,13 @@ const defaultServer = 'https://open.rocket.chat';
|
|||
@connect(state => ({
|
||||
connecting: state.server.connecting,
|
||||
failure: state.server.failure,
|
||||
currentServer: state.server.server
|
||||
currentServer: state.server.server,
|
||||
adding: state.server.adding
|
||||
}), dispatch => ({
|
||||
connectServer: url => dispatch(serverRequest(url))
|
||||
initAdd: () => dispatch(serverInitAdd()),
|
||||
finishAdd: () => dispatch(serverFinishAdd()),
|
||||
connectServer: server => dispatch(serverRequest(server)),
|
||||
selectServer: server => dispatch(selectServerRequest(server))
|
||||
}))
|
||||
/** @extends React.Component */
|
||||
export default class NewServerView extends LoggedView {
|
||||
|
@ -55,10 +58,14 @@ export default class NewServerView extends LoggedView {
|
|||
navigator: PropTypes.object,
|
||||
server: PropTypes.string,
|
||||
connecting: PropTypes.bool.isRequired,
|
||||
adding: PropTypes.bool,
|
||||
failure: PropTypes.bool.isRequired,
|
||||
connectServer: PropTypes.func.isRequired,
|
||||
selectServer: PropTypes.func.isRequired,
|
||||
previousServer: PropTypes.string,
|
||||
currentServer: PropTypes.string
|
||||
currentServer: PropTypes.string,
|
||||
initAdd: PropTypes.func,
|
||||
finishAdd: PropTypes.func
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
|
@ -69,25 +76,8 @@ export default class NewServerView extends LoggedView {
|
|||
props.navigator.setOnNavigatorEvent(this.onNavigatorEvent.bind(this));
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
// if previousServer exists, New Server View is a modal
|
||||
if (this.props.previousServer) {
|
||||
const closeButton = {
|
||||
id: 'close',
|
||||
testID: 'new-server-close',
|
||||
title: I18n.t('Close')
|
||||
};
|
||||
if (Platform.OS === 'android') {
|
||||
closeButton.icon = iconsMap.close;
|
||||
}
|
||||
this.props.navigator.setButtons({
|
||||
leftButtons: [closeButton]
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { server } = this.props;
|
||||
const { server, previousServer } = this.props;
|
||||
if (server) {
|
||||
this.props.connectServer(server);
|
||||
this.setState({ text: server });
|
||||
|
@ -96,6 +86,9 @@ export default class NewServerView extends LoggedView {
|
|||
this.input.focus();
|
||||
}, 600);
|
||||
}
|
||||
if (previousServer) {
|
||||
this.props.initAdd();
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
|
@ -104,16 +97,22 @@ export default class NewServerView extends LoggedView {
|
|||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
const {
|
||||
selectServer, previousServer, currentServer, adding, finishAdd
|
||||
} = this.props;
|
||||
if (adding) {
|
||||
if (previousServer !== currentServer) {
|
||||
selectServer(previousServer);
|
||||
}
|
||||
finishAdd();
|
||||
}
|
||||
}
|
||||
|
||||
onNavigatorEvent(event) {
|
||||
if (event.type === 'NavBarButtonPress') {
|
||||
if (event.id === 'close') {
|
||||
const {
|
||||
navigator, connectServer, previousServer, currentServer
|
||||
} = this.props;
|
||||
navigator.dismissModal();
|
||||
if (previousServer !== currentServer) {
|
||||
connectServer(previousServer);
|
||||
}
|
||||
if (event.id === 'cancel') {
|
||||
this.props.navigator.dismissModal();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ const userAgent = Platform.OS === 'ios' ? 'UserAgent' : userAgentAndroid;
|
|||
@connect(state => ({
|
||||
server: state.server.server
|
||||
}))
|
||||
export default class TermsServiceView extends React.PureComponent {
|
||||
export default class OAuthView extends React.PureComponent {
|
||||
static navigatorButtons = {
|
||||
leftButtons: [{
|
||||
id: 'close',
|
||||
|
|
|
@ -21,6 +21,7 @@ export default class OnboardingView extends LoggedView {
|
|||
connectServer = () => {
|
||||
this.props.navigator.push({
|
||||
screen: 'NewServerView',
|
||||
backButtonTitle: '',
|
||||
navigatorStyle: {
|
||||
navBarHidden: true
|
||||
}
|
||||
|
@ -30,6 +31,7 @@ export default class OnboardingView extends LoggedView {
|
|||
joinCommunity = () => {
|
||||
this.props.navigator.push({
|
||||
screen: 'NewServerView',
|
||||
backButtonTitle: '',
|
||||
passProps: {
|
||||
server: 'https://open.rocket.chat'
|
||||
},
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { View, ScrollView, SafeAreaView, Keyboard, Platform, Dimensions } from 'react-native';
|
||||
import { View, ScrollView, SafeAreaView, Keyboard, Dimensions } from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
import Dialog from 'react-native-dialog';
|
||||
import SHA256 from 'js-sha256';
|
||||
|
@ -61,7 +61,7 @@ export default class ProfileView extends LoggedView {
|
|||
componentWillMount() {
|
||||
this.props.navigator.setButtons({
|
||||
leftButtons: [{
|
||||
id: 'sideMenu',
|
||||
id: 'settings',
|
||||
icon: { uri: 'settings', scale: Dimensions.get('window').scale }
|
||||
}]
|
||||
});
|
||||
|
@ -91,7 +91,7 @@ export default class ProfileView extends LoggedView {
|
|||
|
||||
onNavigatorEvent(event) {
|
||||
if (event.type === 'NavBarButtonPress') {
|
||||
if (event.id === 'sideMenu' && Platform.OS === 'ios') {
|
||||
if (event.id === 'settings') {
|
||||
this.props.navigator.toggleDrawer({
|
||||
side: 'left'
|
||||
});
|
||||
|
|
|
@ -93,7 +93,7 @@ export default class RegisterView extends LoggedView {
|
|||
this.props.navigator.push({
|
||||
screen: 'TermsServiceView',
|
||||
title: I18n.t('Terms_of_Service'),
|
||||
backButtonTitle: I18n.t('Sign_Up')
|
||||
backButtonTitle: ''
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -101,7 +101,7 @@ export default class RegisterView extends LoggedView {
|
|||
this.props.navigator.push({
|
||||
screen: 'PrivacyPolicyView',
|
||||
title: I18n.t('Privacy_Policy'),
|
||||
backButtonTitle: I18n.t('Sign_Up')
|
||||
backButtonTitle: ''
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -65,7 +65,8 @@ export default class RoomActionsView extends LoggedView {
|
|||
this.props.navigator.push({
|
||||
screen: item.route,
|
||||
title: item.name,
|
||||
passProps: item.params
|
||||
passProps: item.params,
|
||||
backButtonTitle: ''
|
||||
});
|
||||
}
|
||||
if (item.event) {
|
||||
|
|
|
@ -118,6 +118,7 @@ export default class RoomInfoView extends LoggedView {
|
|||
this.props.navigator.push({
|
||||
screen: 'RoomInfoEditView',
|
||||
title: I18n.t('Room_Info_Edit'),
|
||||
backButtonTitle: '',
|
||||
passProps: {
|
||||
rid: this.props.rid
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { FlatList, View, TextInput, Vibration, SafeAreaView } from 'react-native';
|
||||
import { FlatList, View, Vibration, SafeAreaView } from 'react-native';
|
||||
import ActionSheet from 'react-native-actionsheet';
|
||||
|
||||
import LoggedView from '../View';
|
||||
|
@ -12,6 +12,7 @@ import database from '../../lib/realm';
|
|||
import { showToast } from '../../utils/info';
|
||||
import log from '../../utils/log';
|
||||
import I18n from '../../i18n';
|
||||
import SearchBox from '../../containers/SearchBox';
|
||||
|
||||
/** @extends React.Component */
|
||||
export default class RoomMembersView extends LoggedView {
|
||||
|
@ -132,6 +133,7 @@ export default class RoomMembersView extends LoggedView {
|
|||
this.props.navigator.push({
|
||||
screen: 'RoomView',
|
||||
title: name,
|
||||
backButtonTitle: '',
|
||||
passProps: {
|
||||
room: { rid, name },
|
||||
rid,
|
||||
|
@ -162,20 +164,7 @@ export default class RoomMembersView extends LoggedView {
|
|||
}
|
||||
|
||||
renderSearchBar = () => (
|
||||
<View style={styles.searchBoxView}>
|
||||
<TextInput
|
||||
underlineColorAndroid='transparent'
|
||||
style={styles.searchBox}
|
||||
onChangeText={text => this.onSearchChangeText(text)}
|
||||
returnKeyType='search'
|
||||
placeholder={I18n.t('Search')}
|
||||
clearButtonMode='while-editing'
|
||||
blurOnSubmit
|
||||
autoCorrect={false}
|
||||
autoCapitalize='none'
|
||||
testID='room-members-view-search'
|
||||
/>
|
||||
</View>
|
||||
<SearchBox onChangeText={text => this.onSearchChangeText(text)} testID='room-members-view-search' />
|
||||
)
|
||||
|
||||
renderSeparator = () => <View style={styles.separator} />;
|
||||
|
|
|
@ -127,6 +127,7 @@ export default class RoomView extends LoggedView {
|
|||
this.props.navigator.push({
|
||||
screen: 'RoomActionsView',
|
||||
title: I18n.t('Actions'),
|
||||
backButtonTitle: '',
|
||||
passProps: {
|
||||
rid: this.state.room.rid
|
||||
}
|
||||
|
|
|
@ -86,6 +86,13 @@ export default class ServerDropdown extends Component {
|
|||
title: I18n.t('Add_Server'),
|
||||
passProps: {
|
||||
previousServer: this.props.server
|
||||
},
|
||||
navigatorButtons: {
|
||||
leftButtons: [{
|
||||
id: 'cancel',
|
||||
testID: 'new-server-close',
|
||||
title: I18n.t('Close')
|
||||
}]
|
||||
}
|
||||
});
|
||||
}, ANIMATION_DURATION);
|
||||
|
@ -101,6 +108,7 @@ export default class ServerDropdown extends Component {
|
|||
setTimeout(() => {
|
||||
this.props.navigator.push({
|
||||
screen: 'NewServerView',
|
||||
backButtonTitle: '',
|
||||
passProps: {
|
||||
server
|
||||
},
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Platform, View, TextInput, FlatList, BackHandler, ActivityIndicator, SafeAreaView, Text, Image, Dimensions, ScrollView, Keyboard } from 'react-native';
|
||||
import { Platform, View, FlatList, BackHandler, ActivityIndicator, SafeAreaView, Text, Image, Dimensions, ScrollView, Keyboard } from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
import { isEqual } from 'lodash';
|
||||
|
||||
import SearchBox from '../../containers/SearchBox';
|
||||
import database from '../../lib/realm';
|
||||
import RocketChat from '../../lib/rocketchat';
|
||||
import RoomItem from '../../presentation/RoomItem';
|
||||
|
@ -26,7 +27,7 @@ const leftButtons = [{
|
|||
testID: 'rooms-list-view-sidebar'
|
||||
}];
|
||||
const rightButtons = [{
|
||||
id: 'createChannel',
|
||||
id: 'newMessage',
|
||||
icon: { uri: 'new_channel', scale: Dimensions.get('window').scale },
|
||||
testID: 'rooms-list-view-create-channel'
|
||||
}];
|
||||
|
@ -38,7 +39,6 @@ if (Platform.OS === 'android') {
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
@connect((state) => {
|
||||
let result = {
|
||||
userId: state.login.user && state.login.user.id,
|
||||
|
@ -74,7 +74,6 @@ export default class RoomsListView extends LoggedView {
|
|||
|
||||
static navigatorStyle = {
|
||||
navBarCustomView: 'RoomsListHeaderView',
|
||||
navBarComponentAlignment: 'fill',
|
||||
navBarBackgroundColor: isAndroid() ? '#2F343D' : undefined,
|
||||
navBarTextColor: isAndroid() ? '#FFF' : undefined,
|
||||
navBarButtonColor: isAndroid() ? '#FFF' : undefined
|
||||
|
@ -157,6 +156,10 @@ export default class RoomsListView extends LoggedView {
|
|||
this.removeListener(this.direct);
|
||||
this.removeListener(this.livechat);
|
||||
|
||||
if (database && database.deleteAll) {
|
||||
database.deleteAll();
|
||||
}
|
||||
|
||||
if (this.timeout) {
|
||||
clearTimeout(this.timeout);
|
||||
}
|
||||
|
@ -165,12 +168,12 @@ export default class RoomsListView extends LoggedView {
|
|||
onNavigatorEvent(event) {
|
||||
const { navigator } = this.props;
|
||||
if (event.type === 'NavBarButtonPress') {
|
||||
if (event.id === 'createChannel') {
|
||||
this.props.navigator.push({
|
||||
screen: 'SelectedUsersView',
|
||||
title: I18n.t('Select_Users'),
|
||||
if (event.id === 'newMessage') {
|
||||
this.props.navigator.showModal({
|
||||
screen: 'NewMessageView',
|
||||
title: I18n.t('New_Message'),
|
||||
passProps: {
|
||||
nextAction: 'CREATE_CHANNEL'
|
||||
onPressItem: this._onPressItem
|
||||
}
|
||||
});
|
||||
} else if (event.id === 'settings') {
|
||||
|
@ -190,10 +193,6 @@ export default class RoomsListView extends LoggedView {
|
|||
}
|
||||
}
|
||||
|
||||
onSearchChangeText(text) {
|
||||
this.search(text);
|
||||
}
|
||||
|
||||
getSubscriptions = () => {
|
||||
if (this.props.server && this.hasActiveDB()) {
|
||||
if (this.props.sidebarSortby === 'alphabetical') {
|
||||
|
@ -285,7 +284,6 @@ export default class RoomsListView extends LoggedView {
|
|||
navigator.setButtons({ leftButtons, rightButtons });
|
||||
navigator.setStyle({
|
||||
navBarCustomView: 'RoomsListHeaderView',
|
||||
navBarComponentAlignment: 'fill',
|
||||
navBarBackgroundColor: isAndroid() ? '#2F343D' : undefined,
|
||||
navBarTextColor: isAndroid() ? '#FFF' : undefined,
|
||||
navBarButtonColor: isAndroid() ? '#FFF' : undefined
|
||||
|
@ -327,55 +325,18 @@ export default class RoomsListView extends LoggedView {
|
|||
|
||||
_isUnread = item => item.unread > 0 || item.alert
|
||||
|
||||
async search(text) {
|
||||
const searchText = text.trim();
|
||||
if (searchText === '') {
|
||||
delete this.oldPromise;
|
||||
return this.setState({
|
||||
search: []
|
||||
});
|
||||
}
|
||||
|
||||
let data = database.objects('subscriptions').filtered('name CONTAINS[c] $0', searchText).slice(0, 7);
|
||||
|
||||
const usernames = data.map(sub => sub.name);
|
||||
try {
|
||||
if (data.length < 7) {
|
||||
if (this.oldPromise) {
|
||||
this.oldPromise('cancel');
|
||||
}
|
||||
|
||||
const { users, rooms } = await Promise.race([
|
||||
RocketChat.spotlight(searchText, usernames, { users: true, rooms: true }),
|
||||
new Promise((resolve, reject) => this.oldPromise = reject)
|
||||
]);
|
||||
|
||||
data = data.concat(users.map(user => ({
|
||||
...user,
|
||||
rid: user.username,
|
||||
name: user.username,
|
||||
t: 'd',
|
||||
search: true
|
||||
})), rooms.map(room => ({
|
||||
rid: room._id,
|
||||
...room,
|
||||
search: true
|
||||
})));
|
||||
|
||||
delete this.oldPromise;
|
||||
}
|
||||
this.setState({
|
||||
search: data
|
||||
});
|
||||
} catch (e) {
|
||||
// alert(JSON.stringify(e));
|
||||
}
|
||||
search = async(text) => {
|
||||
const result = await RocketChat.search({ text });
|
||||
this.setState({
|
||||
search: result
|
||||
});
|
||||
}
|
||||
|
||||
goRoom = (rid, name) => {
|
||||
this.props.navigator.push({
|
||||
screen: 'RoomView',
|
||||
title: name,
|
||||
backButtonTitle: '',
|
||||
passProps: {
|
||||
room: { rid, name },
|
||||
rid,
|
||||
|
@ -429,22 +390,7 @@ export default class RoomsListView extends LoggedView {
|
|||
|
||||
renderSearchBar = () => {
|
||||
if (Platform.OS === 'ios') {
|
||||
return (
|
||||
<View style={styles.searchBoxView}>
|
||||
<TextInput
|
||||
underlineColorAndroid='transparent'
|
||||
style={styles.searchBox}
|
||||
onChangeText={text => this.onSearchChangeText(text)}
|
||||
returnKeyType='search'
|
||||
placeholder={I18n.t('Search')}
|
||||
clearButtonMode='while-editing'
|
||||
blurOnSubmit
|
||||
autoCorrect={false}
|
||||
autoCapitalize='none'
|
||||
testID='rooms-list-view-search'
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
return <SearchBox onChangeText={text => this.search(text)} testID='rooms-list-view-search' />;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -537,7 +483,7 @@ export default class RoomsListView extends LoggedView {
|
|||
|
||||
return (
|
||||
<ScrollView
|
||||
contentOffset={Platform.OS === 'ios' ? { x: 0, y: 37 } : {}}
|
||||
contentOffset={Platform.OS === 'ios' ? { x: 0, y: 56 } : {}}
|
||||
keyboardShouldPersistTaps='always'
|
||||
testID='rooms-list-view-list'
|
||||
>
|
||||
|
|
|
@ -31,17 +31,6 @@ export default StyleSheet.create({
|
|||
height: 22,
|
||||
color: 'white'
|
||||
},
|
||||
searchBoxView: {
|
||||
backgroundColor: '#eee'
|
||||
},
|
||||
searchBox: {
|
||||
backgroundColor: '#fff',
|
||||
margin: 5,
|
||||
borderRadius: 5,
|
||||
padding: 5,
|
||||
paddingLeft: 10,
|
||||
color: '#aaa'
|
||||
},
|
||||
loading: {
|
||||
flex: 1
|
||||
},
|
||||
|
|
|
@ -1,56 +1,29 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { View, StyleSheet, TextInput, Text, TouchableOpacity, SafeAreaView, FlatList, LayoutAnimation } from 'react-native';
|
||||
import { View, StyleSheet, SafeAreaView, FlatList, LayoutAnimation, Platform } from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { addUser, removeUser, reset, setLoading } from '../actions/selectedUsers';
|
||||
import database from '../lib/realm';
|
||||
import RocketChat from '../lib/rocketchat';
|
||||
import UserItem from '../presentation/UserItem';
|
||||
import Avatar from '../containers/Avatar';
|
||||
import Loading from '../containers/Loading';
|
||||
import debounce from '../utils/debounce';
|
||||
import LoggedView from './View';
|
||||
import I18n from '../i18n';
|
||||
import log from '../utils/log';
|
||||
import { iconsMap } from '../Icons';
|
||||
import SearchBox from '../containers/SearchBox';
|
||||
import sharedStyles from './Styles';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
alignItems: 'stretch',
|
||||
justifyContent: 'center'
|
||||
},
|
||||
safeAreaView: {
|
||||
flex: 1,
|
||||
backgroundColor: '#FFFFFF'
|
||||
backgroundColor: Platform.OS === 'ios' ? '#F7F8FA' : '#E1E5E8'
|
||||
},
|
||||
list: {
|
||||
width: '100%',
|
||||
backgroundColor: '#FFFFFF'
|
||||
},
|
||||
searchBoxView: {
|
||||
backgroundColor: '#eee'
|
||||
},
|
||||
searchBox: {
|
||||
backgroundColor: '#fff',
|
||||
margin: 5,
|
||||
borderRadius: 5,
|
||||
padding: 5,
|
||||
paddingLeft: 10,
|
||||
color: '#aaa'
|
||||
},
|
||||
selectItemView: {
|
||||
width: 80,
|
||||
height: 80,
|
||||
padding: 8,
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center'
|
||||
header: {
|
||||
backgroundColor: '#fff'
|
||||
},
|
||||
separator: {
|
||||
height: StyleSheet.hairlineWidth,
|
||||
backgroundColor: '#E1E5E8',
|
||||
marginLeft: 60
|
||||
}
|
||||
});
|
||||
|
@ -95,15 +68,19 @@ export default class SelectedUsersView extends LoggedView {
|
|||
});
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (nextProps.users.length !== this.props.users.length) {
|
||||
const { length } = nextProps.users;
|
||||
async componentDidUpdate(prevProps) {
|
||||
const isVisible = await this.props.navigator.screenIsCurrentlyVisible();
|
||||
if (!isVisible) {
|
||||
return;
|
||||
}
|
||||
if (prevProps.users.length !== this.props.users.length) {
|
||||
const { length } = this.props.users;
|
||||
const rightButtons = [];
|
||||
if (length > 0) {
|
||||
rightButtons.push({
|
||||
id: 'create',
|
||||
testID: 'selected-users-view-submit',
|
||||
icon: iconsMap.add
|
||||
title: I18n.t('Next'),
|
||||
testID: 'selected-users-view-submit'
|
||||
});
|
||||
}
|
||||
this.props.navigator.setButtons({ rightButtons });
|
||||
|
@ -123,7 +100,8 @@ export default class SelectedUsersView extends LoggedView {
|
|||
if (nextAction === 'CREATE_CHANNEL') {
|
||||
this.props.navigator.push({
|
||||
screen: 'CreateChannelView',
|
||||
title: I18n.t('Create_Channel')
|
||||
title: I18n.t('Create_Channel'),
|
||||
backButtonTitle: ''
|
||||
});
|
||||
} else {
|
||||
try {
|
||||
|
@ -148,90 +126,40 @@ export default class SelectedUsersView extends LoggedView {
|
|||
this.forceUpdate();
|
||||
}, 1000);
|
||||
|
||||
async search(text) {
|
||||
const searchText = text.trim();
|
||||
if (searchText === '') {
|
||||
delete this.oldPromise;
|
||||
return this.setState({
|
||||
search: []
|
||||
});
|
||||
}
|
||||
|
||||
let data = this.data.filtered('name CONTAINS[c] $0 AND t = $1', searchText, 'd').slice(0, 7);
|
||||
|
||||
const usernames = data.map(sub => sub.map);
|
||||
try {
|
||||
if (data.length < 7) {
|
||||
if (this.oldPromise) {
|
||||
this.oldPromise('cancel');
|
||||
}
|
||||
|
||||
const { users } = await Promise.race([
|
||||
RocketChat.spotlight(searchText, usernames, { users: true, rooms: false }),
|
||||
new Promise((resolve, reject) => this.oldPromise = reject)
|
||||
]);
|
||||
|
||||
data = users.map(user => ({
|
||||
...user,
|
||||
rid: user.username,
|
||||
name: user.username,
|
||||
t: 'd',
|
||||
search: true
|
||||
}));
|
||||
|
||||
delete this.oldPromise;
|
||||
}
|
||||
this.setState({
|
||||
search: data
|
||||
});
|
||||
} catch (e) {
|
||||
// alert(JSON.stringify(e));
|
||||
}
|
||||
search = async(text) => {
|
||||
const result = await RocketChat.search({ text, filterRooms: false });
|
||||
this.setState({
|
||||
search: result
|
||||
});
|
||||
}
|
||||
|
||||
isChecked = username => this.props.users.findIndex(el => el.name === username) !== -1;
|
||||
|
||||
toggleUser = (user) => {
|
||||
LayoutAnimation.easeInEaseOut();
|
||||
const index = this.props.users.findIndex(el => el.name === user.name);
|
||||
if (index === -1) {
|
||||
if (!this.isChecked(user.name)) {
|
||||
this.props.addUser(user);
|
||||
} else {
|
||||
this.props.removeUser(user);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
_onPressItem = (id, item = {}) => {
|
||||
if (item.search) {
|
||||
this.toggleUser({ _id: item._id, name: item.username });
|
||||
this.toggleUser({ _id: item._id, name: item.username, fname: item.name });
|
||||
} else {
|
||||
this.toggleUser({ _id: item._id, name: item.name });
|
||||
this.toggleUser({ _id: item._id, name: item.name, fname: item.fname });
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
_onPressSelectedItem = item => this.toggleUser(item);
|
||||
|
||||
renderHeader = () => (
|
||||
<View style={styles.container}>
|
||||
{this.renderSearchBar()}
|
||||
<View style={styles.header}>
|
||||
<SearchBox onChangeText={text => this.onSearchChangeText(text)} testID='select-users-view-search' />
|
||||
{this.renderSelected()}
|
||||
</View>
|
||||
);
|
||||
|
||||
renderSearchBar = () => (
|
||||
<View style={styles.searchBoxView}>
|
||||
<TextInput
|
||||
underlineColorAndroid='transparent'
|
||||
style={styles.searchBox}
|
||||
onChangeText={text => this.onSearchChangeText(text)}
|
||||
returnKeyType='search'
|
||||
placeholder={I18n.t('Search')}
|
||||
clearButtonMode='while-editing'
|
||||
blurOnSubmit
|
||||
testID='select-users-view-search'
|
||||
autoCorrect={false}
|
||||
autoCapitalize='none'
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
)
|
||||
|
||||
renderSelected = () => {
|
||||
if (this.props.users.length === 0) {
|
||||
|
@ -241,57 +169,70 @@ export default class SelectedUsersView extends LoggedView {
|
|||
<FlatList
|
||||
data={this.props.users}
|
||||
keyExtractor={item => item._id}
|
||||
style={styles.list}
|
||||
style={[styles.list, sharedStyles.separatorTop]}
|
||||
contentContainerStyle={{ marginVertical: 5 }}
|
||||
renderItem={this.renderSelectedItem}
|
||||
enableEmptySections
|
||||
keyboardShouldPersistTaps='always'
|
||||
horizontal
|
||||
/>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
renderSelectedItem = ({ item }) => (
|
||||
<TouchableOpacity
|
||||
key={item._id}
|
||||
style={styles.selectItemView}
|
||||
<UserItem
|
||||
name={item.fname}
|
||||
username={item.name}
|
||||
onPress={() => this._onPressSelectedItem(item)}
|
||||
testID={`selected-user-${ item.name }`}
|
||||
>
|
||||
<Avatar text={item.name} size={40} />
|
||||
<Text ellipsizeMode='tail' numberOfLines={1} style={{ fontSize: 10 }}>
|
||||
{item.name}
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
|
||||
renderSeparator = () => <View style={styles.separator} />;
|
||||
|
||||
renderItem = ({ item }) => (
|
||||
<UserItem
|
||||
name={item.fname ? item.fname : item.name}
|
||||
username={item.fname ? item.name : item.username}
|
||||
onPress={() => this._onPressItem(item._id, item)}
|
||||
testID={`select-users-view-item-${ item.name }`}
|
||||
style={{ paddingRight: 15 }}
|
||||
/>
|
||||
)
|
||||
|
||||
renderSeparator = () => <View style={[sharedStyles.separator, styles.separator]} />
|
||||
|
||||
renderItem = ({ item, index }) => {
|
||||
const name = item.search ? item.name : item.fname;
|
||||
const username = item.search ? item.username : item.name;
|
||||
let style = {};
|
||||
if (index === 0) {
|
||||
style = { ...sharedStyles.separatorTop };
|
||||
}
|
||||
if (this.state.search.length > 0 && index === this.state.search.length - 1) {
|
||||
style = { ...style, ...sharedStyles.separatorBottom };
|
||||
}
|
||||
if (this.state.search.length === 0 && index === this.data.length - 1) {
|
||||
style = { ...style, ...sharedStyles.separatorBottom };
|
||||
}
|
||||
return (
|
||||
<UserItem
|
||||
name={name}
|
||||
username={username}
|
||||
onPress={() => this._onPressItem(item._id, item)}
|
||||
testID={`select-users-view-item-${ item.name }`}
|
||||
icon={this.isChecked(username) ? 'check' : null}
|
||||
style={style}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
renderList = () => (
|
||||
<FlatList
|
||||
data={this.state.search.length > 0 ? this.state.search : this.data}
|
||||
extraData={this.props}
|
||||
keyExtractor={item => item._id}
|
||||
style={styles.list}
|
||||
renderItem={this.renderItem}
|
||||
ListHeaderComponent={this.renderHeader}
|
||||
ItemSeparatorComponent={this.renderSeparator}
|
||||
ListHeaderComponent={this.renderHeader}
|
||||
enableEmptySections
|
||||
keyboardShouldPersistTaps='always'
|
||||
/>
|
||||
);
|
||||
)
|
||||
|
||||
render = () => (
|
||||
<SafeAreaView style={styles.safeAreaView} testID='select-users-view'>
|
||||
{this.renderList()}
|
||||
<Loading visible={this.props.loading} />
|
||||
</SafeAreaView>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { View, ScrollView, SafeAreaView, Platform, Dimensions } from 'react-native';
|
||||
import { View, ScrollView, SafeAreaView, Dimensions } from 'react-native';
|
||||
import RNPickerSelect from 'react-native-picker-select';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
|
@ -50,7 +50,7 @@ export default class SettingsView extends LoggedView {
|
|||
componentWillMount() {
|
||||
this.props.navigator.setButtons({
|
||||
leftButtons: [{
|
||||
id: 'sideMenu',
|
||||
id: 'settings',
|
||||
icon: { uri: 'settings', scale: Dimensions.get('window').scale }
|
||||
}]
|
||||
});
|
||||
|
@ -65,7 +65,7 @@ export default class SettingsView extends LoggedView {
|
|||
|
||||
onNavigatorEvent(event) {
|
||||
if (event.type === 'NavBarButtonPress') {
|
||||
if (event.id === 'sideMenu' && Platform.OS === 'ios') {
|
||||
if (event.id === 'settings') {
|
||||
this.props.navigator.toggleDrawer({
|
||||
side: 'left'
|
||||
});
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { StyleSheet, Platform } from 'react-native';
|
||||
|
||||
import { COLOR_DANGER, COLOR_BUTTON_PRIMARY, COLOR_TEXT } from '../constants/colors';
|
||||
import { COLOR_DANGER, COLOR_BUTTON_PRIMARY, COLOR_TEXT, COLOR_SEPARATOR } from '../constants/colors';
|
||||
|
||||
export default StyleSheet.create({
|
||||
container: {
|
||||
|
@ -197,5 +197,22 @@ export default StyleSheet.create({
|
|||
width: 44,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
},
|
||||
separator: {
|
||||
height: StyleSheet.hairlineWidth,
|
||||
backgroundColor: COLOR_SEPARATOR
|
||||
},
|
||||
separatorTop: {
|
||||
borderColor: COLOR_SEPARATOR,
|
||||
borderTopWidth: StyleSheet.hairlineWidth
|
||||
},
|
||||
separatorBottom: {
|
||||
borderColor: COLOR_SEPARATOR,
|
||||
borderBottomWidth: StyleSheet.hairlineWidth
|
||||
},
|
||||
separatorVertical: {
|
||||
borderColor: COLOR_SEPARATOR,
|
||||
borderTopWidth: StyleSheet.hairlineWidth,
|
||||
borderBottomWidth: StyleSheet.hairlineWidth
|
||||
}
|
||||
});
|
||||
|
|
|
@ -6,6 +6,7 @@ import ForgotPasswordView from './ForgotPasswordView';
|
|||
import LoginSignupView from './LoginSignupView';
|
||||
import LoginView from './LoginView';
|
||||
import MentionedMessagesView from './MentionedMessagesView';
|
||||
import NewMessageView from './NewMessageView';
|
||||
import NewServerView from './NewServerView';
|
||||
import OAuthView from './OAuthView';
|
||||
import OnboardingView from './OnboardingView';
|
||||
|
@ -36,6 +37,7 @@ export const registerScreens = (store) => {
|
|||
Navigation.registerComponent('LoginSignupView', () => LoginSignupView, store, Provider);
|
||||
Navigation.registerComponent('LoginView', () => LoginView, store, Provider);
|
||||
Navigation.registerComponent('MentionedMessagesView', () => MentionedMessagesView, store, Provider);
|
||||
Navigation.registerComponent('NewMessageView', () => NewMessageView, store, Provider);
|
||||
Navigation.registerComponent('NewServerView', () => NewServerView, store, Provider);
|
||||
Navigation.registerComponent('OAuthView', () => OAuthView, store, Provider);
|
||||
Navigation.registerComponent('OnboardingView', () => OnboardingView, store, Provider);
|
||||
|
|
|
@ -30,14 +30,14 @@ describe('Welcome screen', () => {
|
|||
await element(by.id('welcome-view-login')).tap();
|
||||
await waitFor(element(by.id('login-view'))).toBeVisible().withTimeout(2000);
|
||||
await expect(element(by.id('login-view'))).toBeVisible();
|
||||
await tapBack('Welcome');
|
||||
await tapBack();
|
||||
});
|
||||
|
||||
it('should navigate to register', async() => {
|
||||
await element(by.id('welcome-view-register')).tap();
|
||||
await waitFor(element(by.id('register-view'))).toBeVisible().withTimeout(2000);
|
||||
await expect(element(by.id('register-view'))).toBeVisible();
|
||||
await tapBack('Welcome');
|
||||
await tapBack();
|
||||
});
|
||||
|
||||
afterEach(async() => {
|
||||
|
|
|
@ -49,18 +49,18 @@ describe('Login screen', () => {
|
|||
await element(by.id('login-view-register')).tap();
|
||||
await waitFor(element(by.id('register-view'))).toBeVisible().withTimeout(2000);
|
||||
await expect(element(by.id('register-view'))).toBeVisible();
|
||||
await tapBack('Login');
|
||||
await tapBack();
|
||||
});
|
||||
|
||||
it('should navigate to forgot password', async() => {
|
||||
await element(by.id('login-view-forgot-password')).tap();
|
||||
await waitFor(element(by.id('forgot-password-view'))).toBeVisible().withTimeout(2000);
|
||||
await expect(element(by.id('forgot-password-view'))).toBeVisible();
|
||||
await tapBack('Login');
|
||||
await tapBack();
|
||||
});
|
||||
|
||||
it('should navigate to welcome', async() => {
|
||||
await tapBack('Welcome');
|
||||
await tapBack();
|
||||
await waitFor(element(by.id('welcome-view'))).toBeVisible().withTimeout(2000);
|
||||
await expect(element(by.id('welcome-view'))).toBeVisible();
|
||||
await element(by.id('welcome-view-login')).tap();
|
||||
|
|
|
@ -11,9 +11,9 @@ describe('Rooms list screen', () => {
|
|||
await expect(element(by.id('rooms-list-view'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have rooms list', async() => {
|
||||
await expect(element(by.id('rooms-list-view-list'))).toBeVisible();
|
||||
});
|
||||
// it('should have rooms list', async() => {
|
||||
// await expect(element(by.id('rooms-list-view-list'))).toBeVisible();
|
||||
// });
|
||||
|
||||
it('should have room item', async() => {
|
||||
await expect(element(by.id('rooms-list-view-item-general'))).toExist();
|
||||
|
@ -38,9 +38,12 @@ describe('Rooms list screen', () => {
|
|||
|
||||
describe('Usage', async() => {
|
||||
it('should search room and navigate', async() => {
|
||||
await element(by.id('rooms-list-view-list')).swipe('down');
|
||||
await waitFor(element(by.id('rooms-list-view-search'))).toBeVisible().withTimeout(2000);
|
||||
await expect(element(by.id('rooms-list-view-search'))).toBeVisible();
|
||||
// await element(by.id('rooms-list-view-list')).swipe('down');
|
||||
// await waitFor(element(by.id('rooms-list-view-search'))).toBeVisible().withTimeout(2000);
|
||||
// await expect(element(by.id('rooms-list-view-search'))).toBeVisible();
|
||||
|
||||
await waitFor(element(by.id('rooms-list-view-search'))).toExist().withTimeout(2000);
|
||||
|
||||
await element(by.id('rooms-list-view-search')).replaceText('rocket.cat');
|
||||
await waitFor(element(by.id('rooms-list-view-item-rocket.cat'))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.id('rooms-list-view-item-rocket.cat'))).toBeVisible();
|
||||
|
@ -49,7 +52,7 @@ describe('Rooms list screen', () => {
|
|||
await expect(element(by.id('room-view'))).toBeVisible();
|
||||
await waitFor(element(by.text('rocket.cat'))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.text('rocket.cat'))).toBeVisible();
|
||||
await tapBack('Messages');
|
||||
await tapBack(2);
|
||||
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
|
||||
await expect(element(by.id('rooms-list-view'))).toBeVisible();
|
||||
await element(by.id('rooms-list-view-search')).replaceText('');
|
||||
|
|
|
@ -3,37 +3,70 @@ const {
|
|||
} = require('detox');
|
||||
const { takeScreenshot } = require('./helpers/screenshot');
|
||||
const data = require('./data');
|
||||
const { tapBack } = require('./helpers/app');
|
||||
const { tapBack, sleep } = require('./helpers/app');
|
||||
|
||||
describe('Create room screen', () => {
|
||||
before(async() => {
|
||||
await sleep(5000);
|
||||
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
|
||||
await device.reloadReactNative();
|
||||
await element(by.id('rooms-list-view-create-channel')).tap();
|
||||
await waitFor(element(by.id('select-users-view'))).toBeVisible().withTimeout(2000);
|
||||
await waitFor(element(by.id('new-message-view'))).toBeVisible().withTimeout(2000);
|
||||
});
|
||||
|
||||
describe('Render', async() => {
|
||||
it('should have select users screen', async() => {
|
||||
await expect(element(by.id('select-users-view'))).toBeVisible();
|
||||
});
|
||||
describe('New Message', async() => {
|
||||
describe('Render', async() => {
|
||||
it('should have new message screen', async() => {
|
||||
await expect(element(by.id('new-message-view'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have search input', async() => {
|
||||
await waitFor(element(by.id('new-message-view-search'))).toExist().withTimeout(2000);
|
||||
await expect(element(by.id('new-message-view-search'))).toExist();
|
||||
});
|
||||
|
||||
after(async() => {
|
||||
takeScreenshot();
|
||||
});
|
||||
})
|
||||
|
||||
it('should have search input', async() => {
|
||||
await expect(element(by.id('select-users-view-search'))).toBeVisible();
|
||||
});
|
||||
describe('Usage', async() => {
|
||||
it('should back to rooms list', async() => {
|
||||
await tapBack();
|
||||
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
|
||||
await expect(element(by.id('rooms-list-view'))).toBeVisible();
|
||||
await element(by.id('rooms-list-view-create-channel')).tap();
|
||||
await waitFor(element(by.id('new-message-view'))).toBeVisible().withTimeout(2000);
|
||||
});
|
||||
|
||||
after(async() => {
|
||||
takeScreenshot();
|
||||
});
|
||||
it('should search user and navigate', async() => {
|
||||
await element(by.id('new-message-view-search')).replaceText('rocket.cat');
|
||||
await waitFor(element(by.id('new-message-view-item-rocket.cat'))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.id('new-message-view-item-rocket.cat'))).toBeVisible();
|
||||
await element(by.id('new-message-view-item-rocket.cat')).tap();
|
||||
await waitFor(element(by.id('room-view'))).toBeVisible().withTimeout(10000);
|
||||
await expect(element(by.id('room-view'))).toBeVisible();
|
||||
await waitFor(element(by.text('rocket.cat'))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.text('rocket.cat'))).toBeVisible();
|
||||
await tapBack(2);
|
||||
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
|
||||
await element(by.id('rooms-list-view-create-channel')).tap();
|
||||
});
|
||||
|
||||
it('should navigate to select users', async() => {
|
||||
await element(by.id('new-message-view-create-channel')).tap();
|
||||
await waitFor(element(by.id('select-users-view'))).toBeVisible().withTimeout(2000);
|
||||
await expect(element(by.id('select-users-view'))).toBeVisible();
|
||||
});
|
||||
|
||||
|
||||
after(async() => {
|
||||
takeScreenshot();
|
||||
});
|
||||
})
|
||||
});
|
||||
|
||||
describe('Usage', async() => {
|
||||
it('should back to rooms list', async() => {
|
||||
await tapBack('Messages');
|
||||
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
|
||||
await expect(element(by.id('rooms-list-view'))).toBeVisible();
|
||||
await element(by.id('rooms-list-view-create-channel')).tap();
|
||||
await waitFor(element(by.id('select-users-view'))).toBeVisible().withTimeout(2000);
|
||||
});
|
||||
|
||||
describe('Select Users', async() => {
|
||||
it('should search users', async() => {
|
||||
await element(by.id('select-users-view-search')).replaceText('rocket.cat');
|
||||
await waitFor(element(by.id(`select-users-view-item-rocket.cat`))).toBeVisible().withTimeout(10000);
|
||||
|
@ -57,52 +90,65 @@ describe('Create room screen', () => {
|
|||
await element(by.id('selected-users-view-submit')).tap();
|
||||
await waitFor(element(by.id('create-channel-view'))).toBeVisible().withTimeout(5000);
|
||||
await expect(element(by.id('create-channel-view'))).toBeVisible();
|
||||
await expect(element(by.id('create-channel-name'))).toBeVisible();
|
||||
await expect(element(by.id('create-channel-type'))).toBeVisible();
|
||||
await expect(element(by.id('create-channel-readonly'))).toBeVisible();
|
||||
await expect(element(by.id('create-channel-broadcast'))).toExist();
|
||||
await expect(element(by.id('create-channel-submit'))).toExist();
|
||||
});
|
||||
})
|
||||
|
||||
it('should get invalid room', async() => {
|
||||
await element(by.id('create-channel-name')).replaceText('general');
|
||||
await element(by.id('create-channel-submit')).tap();
|
||||
await waitFor(element(by.id('create-channel-error'))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.id('create-channel-error'))).toBeVisible();
|
||||
});
|
||||
describe('Create Channel', async() => {
|
||||
describe('Render', async() => {
|
||||
it('should render all fields', async() => {
|
||||
await expect(element(by.id('create-channel-name'))).toBeVisible();
|
||||
await expect(element(by.id('create-channel-type'))).toBeVisible();
|
||||
await expect(element(by.id('create-channel-readonly'))).toBeVisible();
|
||||
await expect(element(by.id('create-channel-broadcast'))).toExist();
|
||||
})
|
||||
})
|
||||
|
||||
it('should create public room', async() => {
|
||||
await element(by.id('create-channel-name')).replaceText(`public${ data.random }`);
|
||||
await element(by.id('create-channel-type')).tap();
|
||||
await element(by.id('create-channel-submit')).tap();
|
||||
await waitFor(element(by.id('room-view'))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.id('room-view'))).toBeVisible();
|
||||
await waitFor(element(by.text(`public${ data.random }`))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.text(`public${ data.random }`))).toBeVisible();
|
||||
await tapBack('Messages');
|
||||
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
|
||||
await waitFor(element(by.id(`rooms-list-view-item-public${ data.random }`))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.id(`rooms-list-view-item-public${ data.random }`))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should create private room', async() => {
|
||||
await element(by.id('rooms-list-view-create-channel')).tap();
|
||||
await waitFor(element(by.id('select-users-view'))).toBeVisible().withTimeout(2000);
|
||||
await element(by.id('select-users-view-item-rocket.cat')).tap();
|
||||
await waitFor(element(by.id('selected-user-rocket.cat'))).toBeVisible().withTimeout(5000);
|
||||
await element(by.id('selected-users-view-submit')).tap();
|
||||
await waitFor(element(by.id('create-channel-view'))).toBeVisible().withTimeout(5000);
|
||||
await element(by.id('create-channel-name')).replaceText(`private${ data.random }`);
|
||||
await element(by.id('create-channel-submit')).tap();
|
||||
await waitFor(element(by.id('room-view'))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.id('room-view'))).toBeVisible();
|
||||
await waitFor(element(by.text(`private${ data.random }`))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.text(`private${ data.random }`))).toBeVisible();
|
||||
await tapBack('Messages');
|
||||
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
|
||||
await waitFor(element(by.id(`rooms-list-view-item-private${ data.random }`))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.id(`rooms-list-view-item-private${ data.random }`))).toBeVisible();
|
||||
});
|
||||
describe('Usage', async() => {
|
||||
it('should get invalid room', async() => {
|
||||
await element(by.id('create-channel-name')).replaceText('general');
|
||||
await element(by.id('create-channel-submit')).tap();
|
||||
await waitFor(element(by.text(`A channel with name 'general' exists`))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.text(`A channel with name 'general' exists`))).toBeVisible();
|
||||
await element(by.text('OK')).tap();
|
||||
});
|
||||
|
||||
it('should create public room', async() => {
|
||||
await element(by.id('create-channel-name')).replaceText(`public${ data.random }`);
|
||||
await element(by.id('create-channel-type')).tap();
|
||||
await element(by.id('create-channel-submit')).tap();
|
||||
await waitFor(element(by.id('room-view'))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.id('room-view'))).toBeVisible();
|
||||
await waitFor(element(by.text(`public${ data.random }`))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.text(`public${ data.random }`))).toBeVisible();
|
||||
await tapBack(2);
|
||||
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
|
||||
await waitFor(element(by.id(`rooms-list-view-item-public${ data.random }`))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.id(`rooms-list-view-item-public${ data.random }`))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should create private room', async() => {
|
||||
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
|
||||
await device.reloadReactNative();
|
||||
await element(by.id('rooms-list-view-create-channel')).tap();
|
||||
await waitFor(element(by.id('new-message-view'))).toBeVisible().withTimeout(2000);
|
||||
await element(by.id('new-message-view-create-channel')).tap();
|
||||
await waitFor(element(by.id('select-users-view'))).toBeVisible().withTimeout(2000);
|
||||
await element(by.id('select-users-view-item-rocket.cat')).tap();
|
||||
await waitFor(element(by.id('selected-user-rocket.cat'))).toBeVisible().withTimeout(5000);
|
||||
await element(by.id('selected-users-view-submit')).tap();
|
||||
await waitFor(element(by.id('create-channel-view'))).toBeVisible().withTimeout(5000);
|
||||
await element(by.id('create-channel-name')).replaceText(`private${ data.random }`);
|
||||
await element(by.id('create-channel-submit')).tap();
|
||||
await waitFor(element(by.id('room-view'))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.id('room-view'))).toBeVisible();
|
||||
await waitFor(element(by.text(`private${ data.random }`))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.text(`private${ data.random }`))).toBeVisible();
|
||||
await tapBack(2);
|
||||
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
|
||||
await waitFor(element(by.id(`rooms-list-view-item-private${ data.random }`))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.id(`rooms-list-view-item-private${ data.random }`))).toBeVisible();
|
||||
});
|
||||
})
|
||||
|
||||
afterEach(async() => {
|
||||
takeScreenshot();
|
||||
|
|
|
@ -74,7 +74,7 @@ describe('Room screen', () => {
|
|||
describe('Usage', async() => {
|
||||
describe('Header', async() => {
|
||||
it('should back to rooms list', async() => {
|
||||
await tapBack('Messages');
|
||||
await tapBack(2);
|
||||
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
|
||||
await expect(element(by.id('rooms-list-view'))).toBeVisible();
|
||||
await navigateToRoom();
|
||||
|
@ -84,7 +84,7 @@ describe('Room screen', () => {
|
|||
await element(by.id('room-view-header-actions')).tap();
|
||||
await waitFor(element(by.id('room-actions-view'))).toBeVisible().withTimeout(2000);
|
||||
await expect(element(by.id('room-actions-view'))).toBeVisible();
|
||||
await tapBack(`private${ data.random }`);
|
||||
await tapBack();
|
||||
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
|
||||
});
|
||||
});
|
||||
|
@ -287,7 +287,8 @@ describe('Room screen', () => {
|
|||
});
|
||||
|
||||
after(async() => {
|
||||
await tapBack('Messages');
|
||||
await waitFor(element(by.id('room-view'))).toBeVisible().withTimeout(5000);
|
||||
await tapBack(2);
|
||||
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
|
||||
await expect(element(by.id('rooms-list-view'))).toBeVisible();
|
||||
});
|
||||
|
|
|
@ -21,15 +21,16 @@ async function navigateToRoomActions(type) {
|
|||
await waitFor(element(by.id('room-actions-view'))).toBeVisible().withTimeout(5000);
|
||||
}
|
||||
|
||||
async function backToActions() {
|
||||
await tapBack('Actions');
|
||||
await waitFor(element(by.id('rooms-actions-view'))).toBeVisible().withTimeout(2000);
|
||||
async function backToActions(index = 0) {
|
||||
await tapBack(index);
|
||||
await waitFor(element(by.id('room-actions-view'))).toBeVisible().withTimeout(2000);
|
||||
await expect(element(by.id('room-actions-view'))).toBeVisible();
|
||||
}
|
||||
|
||||
async function backToRoomsList(room) {
|
||||
await tapBack(room);
|
||||
async function backToRoomsList() {
|
||||
await tapBack();
|
||||
await waitFor(element(by.id('room-view'))).toBeVisible().withTimeout(2000);
|
||||
await tapBack('Messages');
|
||||
await tapBack(2);
|
||||
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
|
||||
}
|
||||
|
||||
|
@ -98,7 +99,7 @@ describe('Room actions screen', () => {
|
|||
});
|
||||
|
||||
after(async() => {
|
||||
await backToRoomsList('rocket.cat');
|
||||
await backToRoomsList();
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -247,10 +248,10 @@ describe('Room actions screen', () => {
|
|||
await element(by.id('room-actions-search')).tap();
|
||||
await waitFor(element(by.id('search-messages-view'))).toExist().withTimeout(2000);
|
||||
await expect(element(by.id('search-message-view-input'))).toBeVisible();
|
||||
await element(by.id('search-message-view-input')).tap();
|
||||
await element(by.id('search-message-view-input')).replaceText(`/${ data.random }message/`);
|
||||
await waitFor(element(by.text(`${ data.random }message`).withAncestor(by.id('search-messages-view'))).atIndex(0)).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.text(`${ data.random }message`).withAncestor(by.id('search-messages-view'))).atIndex(0)).toBeVisible();
|
||||
await element(by.traits(['button'])).atIndex(0).tap();
|
||||
await backToActions();
|
||||
});
|
||||
|
||||
|
@ -284,7 +285,7 @@ describe('Room actions screen', () => {
|
|||
await expect(element(by.text('You are the last owner. Please set new owner before leaving the room.'))).toBeVisible();
|
||||
await takeScreenshot();
|
||||
await element(by.text('OK')).tap();
|
||||
await waitFor(element(by.id('rooms-actions-view'))).toBeVisible().withTimeout(2000);
|
||||
await waitFor(element(by.id('room-actions-view'))).toBeVisible().withTimeout(2000);
|
||||
});
|
||||
|
||||
describe('Add User', async() => {
|
||||
|
@ -304,7 +305,7 @@ describe('Room actions screen', () => {
|
|||
await element(by.id('room-members-view-toggle-status')).tap();
|
||||
await waitFor(element(by.id(`room-members-view-item-${ data.alternateUser }`))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.id(`room-members-view-item-${ data.alternateUser }`))).toBeVisible();
|
||||
await backToActions();
|
||||
await backToActions(1);
|
||||
});
|
||||
|
||||
after(async() => {
|
||||
|
@ -363,8 +364,8 @@ describe('Room actions screen', () => {
|
|||
await expect(element(by.id('room-view'))).toBeVisible();
|
||||
await waitFor(element(by.text(data.alternateUser))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.text(data.alternateUser))).toBeVisible();
|
||||
await tapBack('Messages');
|
||||
await waitFor(element(by.id('room-list-view'))).toBeVisible().withTimeout(2000);
|
||||
await tapBack(2);
|
||||
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
|
||||
});
|
||||
|
||||
afterEach(async() => {
|
||||
|
|
|
@ -158,7 +158,7 @@ describe('Room info screen', () => {
|
|||
await expect(element(by.text('Settings succesfully changed!'))).toBeVisible();
|
||||
await waitFor(element(by.text('Settings succesfully changed!'))).toBeNotVisible().withTimeout(10000);
|
||||
await expect(element(by.text('Settings succesfully changed!'))).toBeNotVisible();
|
||||
await tapBack('Room Info');
|
||||
await tapBack();
|
||||
await waitFor(element(by.id('room-info-view'))).toBeVisible().withTimeout(2000);
|
||||
await waitFor(element(by.id('room-info-view-name'))).toHaveText(`${ room }new`).withTimeout(60000);
|
||||
await expect(element(by.id('room-info-view-name'))).toHaveText(`${ room }new`);
|
||||
|
@ -206,7 +206,7 @@ describe('Room info screen', () => {
|
|||
await expect(element(by.text('Settings succesfully changed!'))).toBeVisible();
|
||||
await waitFor(element(by.text('Settings succesfully changed!'))).toBeNotVisible().withTimeout(10000);
|
||||
await expect(element(by.text('Settings succesfully changed!'))).toBeNotVisible();
|
||||
await tapBack('Room Info');
|
||||
await tapBack();
|
||||
await waitFor(element(by.id('room-info-view'))).toBeVisible().withTimeout(2000);
|
||||
await waitFor(element(by.id('room-info-view-description'))).toHaveText('new description').withTimeout(60000);
|
||||
await expect(element(by.id('room-info-view-description'))).toHaveText('new description');
|
||||
|
@ -223,7 +223,7 @@ describe('Room info screen', () => {
|
|||
await expect(element(by.text('Settings succesfully changed!'))).toBeVisible();
|
||||
await waitFor(element(by.text('Settings succesfully changed!'))).toBeNotVisible().withTimeout(10000);
|
||||
await expect(element(by.text('Settings succesfully changed!'))).toBeNotVisible();
|
||||
await tapBack('Room Info');
|
||||
await tapBack();
|
||||
await waitFor(element(by.id('room-info-view'))).toBeVisible().withTimeout(2000);
|
||||
await waitFor(element(by.id('room-info-view-topic'))).toHaveText('new topic').withTimeout(60000);
|
||||
await expect(element(by.id('room-info-view-topic'))).toHaveText('new topic');
|
||||
|
@ -240,7 +240,7 @@ describe('Room info screen', () => {
|
|||
await expect(element(by.text('Settings succesfully changed!'))).toBeVisible();
|
||||
await waitFor(element(by.text('Settings succesfully changed!'))).toBeNotVisible().withTimeout(10000);
|
||||
await expect(element(by.text('Settings succesfully changed!'))).toBeNotVisible();
|
||||
await tapBack('Room Info');
|
||||
await tapBack();
|
||||
await waitFor(element(by.id('room-info-view'))).toBeVisible().withTimeout(2000);
|
||||
await waitFor(element(by.id('room-info-view-announcement'))).toHaveText('new announcement').withTimeout(60000);
|
||||
await expect(element(by.id('room-info-view-announcement'))).toHaveText('new announcement');
|
||||
|
|
|
@ -12,6 +12,8 @@ describe('Broadcast room', () => {
|
|||
|
||||
it('should create broadcast room', async() => {
|
||||
await element(by.id('rooms-list-view-create-channel')).tap();
|
||||
await waitFor(element(by.id('new-message-view'))).toBeVisible().withTimeout(2000);
|
||||
await element(by.id('new-message-view-create-channel')).tap();
|
||||
await waitFor(element(by.id('select-users-view'))).toBeVisible().withTimeout(2000);
|
||||
await element(by.id(`select-users-view-item-${ data.alternateUser }`)).tap();
|
||||
await waitFor(element(by.id(`selected-user-${ data.alternateUser }`))).toBeVisible().withTimeout(5000);
|
||||
|
@ -30,14 +32,14 @@ describe('Broadcast room', () => {
|
|||
await waitFor(element(by.id('room-info-view'))).toBeVisible().withTimeout(2000);
|
||||
await waitFor(element(by.id('room-info-view-broadcast'))).toBeVisible().withTimeout(2000);
|
||||
await expect(element(by.id('room-info-view-broadcast'))).toBeVisible();
|
||||
await tapBack('Actions');
|
||||
await tapBack(1);
|
||||
await waitFor(element(by.id('room-actions-view'))).toBeVisible().withTimeout(2000);
|
||||
await tapBack(`broadcast${ data.random }`);
|
||||
await tapBack();
|
||||
await waitFor(element(by.id('room-view'))).toBeVisible().withTimeout(2000);
|
||||
await tapBack('Messages');
|
||||
await tapBack(2);
|
||||
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
|
||||
await waitFor(element(by.id(`rooms-list-view-item-broadcast${ data.random }`))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.id(`rooms-list-view-item-broadcast${ data.random }`))).toBeVisible();
|
||||
await waitFor(element(by.id(`rooms-list-view-item-broadcast${ data.random }`))).toExist().withTimeout(60000);
|
||||
await expect(element(by.id(`rooms-list-view-item-broadcast${ data.random }`))).toExist();
|
||||
});
|
||||
|
||||
it('should send message', async() => {
|
||||
|
@ -51,7 +53,7 @@ describe('Broadcast room', () => {
|
|||
});
|
||||
|
||||
it('should login as user without write message authorization and enter room', async() => {
|
||||
await tapBack('Messages');
|
||||
await tapBack(2);
|
||||
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
|
||||
await expect(element(by.id('rooms-list-view'))).toBeVisible();
|
||||
await logout();
|
||||
|
@ -61,7 +63,8 @@ describe('Broadcast room', () => {
|
|||
await element(by.id('login-view-submit')).tap();
|
||||
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(10000);
|
||||
// await device.reloadReactNative(); // remove after fix logout
|
||||
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(10000);
|
||||
// await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(10000);
|
||||
await element(by.id('rooms-list-view-search')).replaceText(`broadcast${ data.random }`);
|
||||
await waitFor(element(by.id(`rooms-list-view-item-broadcast${ data.random }`))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.id(`rooms-list-view-item-broadcast${ data.random }`))).toBeVisible();
|
||||
await element(by.id(`rooms-list-view-item-broadcast${ data.random }`)).tap();
|
||||
|
@ -107,7 +110,7 @@ describe('Broadcast room', () => {
|
|||
|
||||
after(async() => {
|
||||
// log back as main test user and left screen on RoomsListView
|
||||
await tapBack('Messages');
|
||||
await tapBack(2);
|
||||
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
|
||||
await logout();
|
||||
await navigateToLogin();
|
||||
|
|
|
@ -36,12 +36,8 @@ async function logout() {
|
|||
await expect(element(by.id('onboarding-view'))).toBeVisible();
|
||||
}
|
||||
|
||||
async function tapBack(label) {
|
||||
try {
|
||||
return element(by.traits(['button']).and(by.label(label || 'Back'))).atIndex(0).tap();
|
||||
} catch (err) {
|
||||
return element(by.type('_UIModernBarButton').and(by.label(label || 'Back'))).tap();
|
||||
}
|
||||
async function tapBack(index) {
|
||||
await element(by.type('_UIModernBarButton')).atIndex(index || 0).tap();
|
||||
}
|
||||
|
||||
async function sleep(ms) {
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "plus.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "plus@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "plus@3x.png",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 276 B |
After Width: | Height: | Size: 451 B |
After Width: | Height: | Size: 621 B |
23
ios/RocketChatRN/Images.xcassets/Icons/textinput_search.imageset/Contents.json
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "textinput_search.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "textinput_search@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "textinput_search@3x.png",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
ios/RocketChatRN/Images.xcassets/Icons/textinput_search.imageset/textinput_search.png
vendored
Normal file
After Width: | Height: | Size: 458 B |
BIN
ios/RocketChatRN/Images.xcassets/Icons/textinput_search.imageset/textinput_search@2x.png
vendored
Normal file
After Width: | Height: | Size: 959 B |
BIN
ios/RocketChatRN/Images.xcassets/Icons/textinput_search.imageset/textinput_search@3x.png
vendored
Normal file
After Width: | Height: | Size: 1.5 KiB |
|
@ -15999,7 +15999,7 @@
|
|||
}
|
||||
},
|
||||
"react-native-navigation": {
|
||||
"version": "git+https://github.com/RocketChat/react-native-navigation.git#1a428f14ddda77511676d0c6d863083ce6225e32",
|
||||
"version": "git+https://github.com/RocketChat/react-native-navigation.git#024095e7679afa0b4e9475f4ffce45d9e50ca5ad",
|
||||
"from": "git+https://github.com/RocketChat/react-native-navigation.git",
|
||||
"requires": {
|
||||
"lodash": "4.x.x"
|
||||
|
|