[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', [
|
export const SERVER = createRequestTypes('SERVER', [
|
||||||
...defaultTypes,
|
...defaultTypes,
|
||||||
'SELECT_SUCCESS',
|
'SELECT_SUCCESS',
|
||||||
'SELECT_REQUEST'
|
'SELECT_REQUEST',
|
||||||
|
'INIT_ADD',
|
||||||
|
'FINISH_ADD'
|
||||||
]);
|
]);
|
||||||
export const METEOR = createRequestTypes('METEOR_CONNECT', [...defaultTypes, 'DISCONNECT', 'DISCONNECT_BY_USER']);
|
export const METEOR = createRequestTypes('METEOR_CONNECT', [...defaultTypes, 'DISCONNECT', 'DISCONNECT_BY_USER']);
|
||||||
export const LOGOUT = 'LOGOUT'; // logout is always success
|
export const LOGOUT = 'LOGOUT'; // logout is always success
|
||||||
|
|
|
@ -33,3 +33,15 @@ export function serverFailure(err) {
|
||||||
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 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_DANGER = '#f5455c';
|
||||||
export const COLOR_BUTTON_PRIMARY = '#2D6AEA';
|
export const COLOR_BUTTON_PRIMARY = '#2D6AEA';
|
||||||
export const COLOR_TEXT = '#292E35';
|
export const COLOR_TEXT = '#292E35';
|
||||||
|
export const COLOR_SEPARATOR = '#CBCED1';
|
||||||
export const STATUS_COLORS = {
|
export const STATUS_COLORS = {
|
||||||
online: '#2de0a5',
|
online: '#2de0a5',
|
||||||
busy: COLOR_DANGER,
|
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(() => {
|
setTimeout(() => {
|
||||||
NavigationActions.push({
|
NavigationActions.push({
|
||||||
screen: 'NewServerView',
|
screen: 'NewServerView',
|
||||||
|
backButtonTitle: '',
|
||||||
passProps: {
|
passProps: {
|
||||||
server: item.id
|
server: item.id
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
export default {
|
export default {
|
||||||
'1_online_member': '1 online member',
|
'1_online_member': '1 online member',
|
||||||
'1_person_reacted': '1 person reacted',
|
'1_person_reacted': '1 person reacted',
|
||||||
|
'1_user': '1 user',
|
||||||
'error-action-not-allowed': '{{action}} is not allowed',
|
'error-action-not-allowed': '{{action}} is not allowed',
|
||||||
'error-application-not-found': 'Application not found',
|
'error-application-not-found': 'Application not found',
|
||||||
'error-archived-duplicate-name': 'There\'s an archived channel with name {{room_name}}',
|
'error-archived-duplicate-name': 'There\'s an archived channel with name {{room_name}}',
|
||||||
|
@ -110,6 +111,7 @@ export default {
|
||||||
Cancel_recording: 'Cancel recording',
|
Cancel_recording: 'Cancel recording',
|
||||||
Cancel: 'Cancel',
|
Cancel: 'Cancel',
|
||||||
changing_avatar: 'changing avatar',
|
changing_avatar: 'changing avatar',
|
||||||
|
creating_channel: 'creating channel',
|
||||||
Channel_Name: 'Channel Name',
|
Channel_Name: 'Channel Name',
|
||||||
Channels: 'Channels',
|
Channels: 'Channels',
|
||||||
Chats: 'Chats',
|
Chats: 'Chats',
|
||||||
|
@ -160,6 +162,7 @@ export default {
|
||||||
Has_left_the_channel: 'Has left the channel',
|
Has_left_the_channel: 'Has left the channel',
|
||||||
I_have_an_account: 'I have an account',
|
I_have_an_account: 'I have an account',
|
||||||
Invisible: 'Invisible',
|
Invisible: 'Invisible',
|
||||||
|
Invite: 'Invite',
|
||||||
is_a_valid_RocketChat_instance: 'is a valid Rocket.Chat instance',
|
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_not_a_valid_RocketChat_instance: 'is not a valid Rocket.Chat instance',
|
||||||
is_typing: 'is typing',
|
is_typing: 'is typing',
|
||||||
|
@ -188,13 +191,15 @@ export default {
|
||||||
muted: 'muted',
|
muted: 'muted',
|
||||||
My_servers: 'My servers',
|
My_servers: 'My servers',
|
||||||
N_online_members: '{{n}} online members',
|
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',
|
||||||
Name: 'Name',
|
Name: 'Name',
|
||||||
New_in_RocketChat_question_mark: 'New in Rocket.Chat?',
|
New_in_RocketChat_question_mark: 'New in Rocket.Chat?',
|
||||||
New_Message: 'New Message',
|
New_Message: 'New Message',
|
||||||
New_Password: 'New Password',
|
New_Password: 'New Password',
|
||||||
New_Server: 'New Server',
|
New_Server: 'New Server',
|
||||||
|
Next: 'Next',
|
||||||
No_files: 'No files',
|
No_files: 'No files',
|
||||||
No_mentioned_messages: 'No mentioned messages',
|
No_mentioned_messages: 'No mentioned messages',
|
||||||
No_pinned_messages: 'No pinned messages',
|
No_pinned_messages: 'No pinned messages',
|
||||||
|
|
|
@ -528,6 +528,56 @@ const RocketChat = {
|
||||||
return _sendMessageCall(JSON.parse(JSON.stringify(message)));
|
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) {
|
spotlight(search, usernames, type) {
|
||||||
return call('spotlight', search, usernames, type);
|
return call('spotlight', search, usernames, type);
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react';
|
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 PropTypes from 'prop-types';
|
||||||
|
|
||||||
import Avatar from '../containers/Avatar';
|
import Avatar from '../containers/Avatar';
|
||||||
|
@ -7,7 +7,8 @@ import Touch from '../utils/touch';
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
button: {
|
button: {
|
||||||
height: 54
|
height: 54,
|
||||||
|
backgroundColor: '#fff'
|
||||||
},
|
},
|
||||||
container: {
|
container: {
|
||||||
flexDirection: 'row'
|
flexDirection: 'row'
|
||||||
|
@ -24,24 +25,33 @@ const styles = StyleSheet.create({
|
||||||
fontSize: 18,
|
fontSize: 18,
|
||||||
color: '#0C0D0F',
|
color: '#0C0D0F',
|
||||||
marginTop: Platform.OS === 'ios' ? 6 : 3,
|
marginTop: Platform.OS === 'ios' ? 6 : 3,
|
||||||
marginBottom: 1
|
marginBottom: 1,
|
||||||
|
textAlign: 'left'
|
||||||
},
|
},
|
||||||
username: {
|
username: {
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
color: '#9EA2A8'
|
color: '#9EA2A8'
|
||||||
|
},
|
||||||
|
icon: {
|
||||||
|
width: 20,
|
||||||
|
height: 20,
|
||||||
|
marginHorizontal: 15,
|
||||||
|
resizeMode: 'contain',
|
||||||
|
alignSelf: 'center'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const UserItem = ({
|
const UserItem = ({
|
||||||
name, username, onPress, testID, onLongPress
|
name, username, onPress, testID, onLongPress, style, icon
|
||||||
}) => (
|
}) => (
|
||||||
<Touch onPress={onPress} onLongPress={onLongPress} style={styles.button} testID={testID}>
|
<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} />
|
<Avatar text={username} size={30} type='d' style={styles.avatar} />
|
||||||
<View style={styles.textContainer}>
|
<View style={styles.textContainer}>
|
||||||
<Text style={styles.name}>{name}</Text>
|
<Text style={styles.name}>{name}</Text>
|
||||||
<Text style={styles.username}>@{username}</Text>
|
<Text style={styles.username}>@{username}</Text>
|
||||||
</View>
|
</View>
|
||||||
|
{icon ? <Image source={{ uri: icon }} style={styles.icon} /> : null}
|
||||||
</View>
|
</View>
|
||||||
</Touch>
|
</Touch>
|
||||||
);
|
);
|
||||||
|
@ -51,7 +61,9 @@ UserItem.propTypes = {
|
||||||
username: PropTypes.string.isRequired,
|
username: PropTypes.string.isRequired,
|
||||||
onPress: PropTypes.func.isRequired,
|
onPress: PropTypes.func.isRequired,
|
||||||
testID: PropTypes.string.isRequired,
|
testID: PropTypes.string.isRequired,
|
||||||
onLongPress: PropTypes.func
|
onLongPress: PropTypes.func,
|
||||||
|
style: ViewPropTypes.style,
|
||||||
|
icon: PropTypes.string
|
||||||
};
|
};
|
||||||
|
|
||||||
export default UserItem;
|
export default UserItem;
|
||||||
|
|
|
@ -6,7 +6,7 @@ const initialState = {
|
||||||
failure: false,
|
failure: false,
|
||||||
server: '',
|
server: '',
|
||||||
loading: true,
|
loading: true,
|
||||||
adding: true
|
adding: false
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -16,16 +16,14 @@ export default function server(state = initialState, action) {
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
connecting: true,
|
connecting: true,
|
||||||
failure: false,
|
failure: false
|
||||||
adding: true
|
|
||||||
};
|
};
|
||||||
case SERVER.FAILURE:
|
case SERVER.FAILURE:
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
connecting: false,
|
connecting: false,
|
||||||
connected: false,
|
connected: false,
|
||||||
failure: true,
|
failure: true
|
||||||
adding: false
|
|
||||||
};
|
};
|
||||||
case SERVER.SELECT_REQUEST:
|
case SERVER.SELECT_REQUEST:
|
||||||
return {
|
return {
|
||||||
|
@ -43,6 +41,16 @@ export default function server(state = initialState, action) {
|
||||||
connected: true,
|
connected: true,
|
||||||
loading: false
|
loading: false
|
||||||
};
|
};
|
||||||
|
case SERVER.INIT_ADD:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
adding: true
|
||||||
|
};
|
||||||
|
case SERVER.FINISH_ADD:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
adding: false
|
||||||
|
};
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,25 +12,26 @@ const create = function* create(data) {
|
||||||
|
|
||||||
const handleRequest = function* handleRequest({ data }) {
|
const handleRequest = function* handleRequest({ data }) {
|
||||||
try {
|
try {
|
||||||
// yield delay(1000);
|
|
||||||
const auth = yield select(state => state.login.isAuthenticated);
|
const auth = yield select(state => state.login.isAuthenticated);
|
||||||
if (!auth) {
|
if (!auth) {
|
||||||
yield take(LOGIN.SUCCESS);
|
yield take(LOGIN.SUCCESS);
|
||||||
}
|
}
|
||||||
const result = yield call(create, data);
|
const result = yield call(create, data);
|
||||||
|
yield put(createChannelSuccess(result));
|
||||||
|
yield delay(300);
|
||||||
const { rid, name } = result;
|
const { rid, name } = result;
|
||||||
NavigationActions.popToRoot();
|
NavigationActions.dismissModal();
|
||||||
yield delay(1000);
|
yield delay(600);
|
||||||
NavigationActions.push({
|
NavigationActions.push({
|
||||||
screen: 'RoomView',
|
screen: 'RoomView',
|
||||||
title: name,
|
title: name,
|
||||||
|
backButtonTitle: '',
|
||||||
passProps: {
|
passProps: {
|
||||||
room: { rid, name },
|
room: { rid, name },
|
||||||
rid,
|
rid,
|
||||||
name
|
name
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
yield put(createChannelSuccess(result));
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
yield put(createChannelFailure(err));
|
yield put(createChannelFailure(err));
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ const navigate = function* go({ params, sameServer = true }) {
|
||||||
if (canOpenRoom) {
|
if (canOpenRoom) {
|
||||||
return NavigationActions.push({
|
return NavigationActions.push({
|
||||||
screen: 'RoomView',
|
screen: 'RoomView',
|
||||||
|
backButtonTitle: '',
|
||||||
passProps: {
|
passProps: {
|
||||||
rid: params.rid
|
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 * as types from '../actions/actionsTypes';
|
||||||
import { appStart } from '../actions';
|
import { appStart } from '../actions';
|
||||||
|
import { serverFinishAdd } from '../actions/server';
|
||||||
import {
|
import {
|
||||||
// loginRequest,
|
// loginRequest,
|
||||||
// loginSubmit,
|
// loginSubmit,
|
||||||
|
@ -38,13 +39,18 @@ const forgotPasswordCall = args => RocketChat.forgotPassword(args);
|
||||||
const handleLoginSuccess = function* handleLoginSuccess() {
|
const handleLoginSuccess = function* handleLoginSuccess() {
|
||||||
try {
|
try {
|
||||||
const user = yield select(getUser);
|
const user = yield select(getUser);
|
||||||
|
const adding = yield select(state => state.server.adding);
|
||||||
yield AsyncStorage.setItem(RocketChat.TOKEN_KEY, user.token);
|
yield AsyncStorage.setItem(RocketChat.TOKEN_KEY, user.token);
|
||||||
if (!user.username || user.isRegistering) {
|
if (!user.username || user.isRegistering) {
|
||||||
yield put(registerIncomplete());
|
yield put(registerIncomplete());
|
||||||
} else {
|
} else {
|
||||||
yield delay(300);
|
yield delay(300);
|
||||||
NavigationActions.dismissModal();
|
if (adding) {
|
||||||
yield put(appStart('inside'));
|
NavigationActions.dismissModal();
|
||||||
|
} else {
|
||||||
|
yield put(appStart('inside'));
|
||||||
|
}
|
||||||
|
yield put(serverFinishAdd());
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
log('handleLoginSuccess', e);
|
log('handleLoginSuccess', e);
|
||||||
|
|
|
@ -80,6 +80,7 @@ const goRoom = function* goRoom({ rid, name }) {
|
||||||
yield delay(1000);
|
yield delay(1000);
|
||||||
NavigationActions.push({
|
NavigationActions.push({
|
||||||
screen: 'RoomView',
|
screen: 'RoomView',
|
||||||
|
backButtonTitle: '',
|
||||||
passProps: {
|
passProps: {
|
||||||
room: { rid, name },
|
room: { rid, name },
|
||||||
rid,
|
rid,
|
||||||
|
|
|
@ -44,7 +44,7 @@ const handleSelectServer = function* handleSelectServer({ server }) {
|
||||||
const handleServerRequest = function* handleServerRequest({ server }) {
|
const handleServerRequest = function* handleServerRequest({ server }) {
|
||||||
try {
|
try {
|
||||||
yield call(validate, server);
|
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.write(() => {
|
||||||
database.databases.serversDB.create('servers', { id: server, current: false }, true);
|
database.databases.serversDB.create('servers', { id: server, current: false }, true);
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,29 +1,85 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import PropTypes from 'prop-types';
|
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 Loading from '../containers/Loading';
|
||||||
import LoggedView from './View';
|
import LoggedView from './View';
|
||||||
import { createChannelRequest } from '../actions/createChannel';
|
import { createChannelRequest } from '../actions/createChannel';
|
||||||
import styles from './Styles';
|
import { removeUser } from '../actions/selectedUsers';
|
||||||
|
import sharedStyles from './Styles';
|
||||||
import KeyboardView from '../presentation/KeyboardView';
|
import KeyboardView from '../presentation/KeyboardView';
|
||||||
import scrollPersistTaps from '../utils/scrollPersistTaps';
|
import scrollPersistTaps from '../utils/scrollPersistTaps';
|
||||||
import Button from '../containers/Button';
|
|
||||||
import I18n from '../i18n';
|
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 => ({
|
@connect(state => ({
|
||||||
createChannel: state.createChannel,
|
createChannel: state.createChannel,
|
||||||
users: state.selectedUsers.users
|
users: state.selectedUsers.users
|
||||||
}), dispatch => ({
|
}), dispatch => ({
|
||||||
create: data => dispatch(createChannelRequest(data))
|
create: data => dispatch(createChannelRequest(data)),
|
||||||
|
removeUser: user => dispatch(removeUser(user))
|
||||||
}))
|
}))
|
||||||
/** @extends React.Component */
|
/** @extends React.Component */
|
||||||
export default class CreateChannelView extends LoggedView {
|
export default class CreateChannelView extends LoggedView {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
navigator: PropTypes.object,
|
navigator: PropTypes.object,
|
||||||
create: PropTypes.func.isRequired,
|
create: PropTypes.func.isRequired,
|
||||||
|
removeUser: PropTypes.func.isRequired,
|
||||||
createChannel: PropTypes.object.isRequired,
|
createChannel: PropTypes.object.isRequired,
|
||||||
users: PropTypes.array.isRequired
|
users: PropTypes.array.isRequired
|
||||||
};
|
};
|
||||||
|
@ -36,6 +92,7 @@ export default class CreateChannelView extends LoggedView {
|
||||||
readOnly: false,
|
readOnly: false,
|
||||||
broadcast: false
|
broadcast: false
|
||||||
};
|
};
|
||||||
|
props.navigator.setOnNavigatorEvent(this.onNavigatorEvent.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
@ -44,6 +101,36 @@ export default class CreateChannelView extends LoggedView {
|
||||||
}, 600);
|
}, 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 = () => {
|
submit = () => {
|
||||||
if (!this.state.channelName.trim() || this.props.createChannel.isFetching) {
|
if (!this.state.channelName.trim() || this.props.createChannel.isFetching) {
|
||||||
return;
|
return;
|
||||||
|
@ -62,47 +149,35 @@ export default class CreateChannelView extends LoggedView {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
renderChannelNameError() {
|
removeUser = (user) => {
|
||||||
if (
|
if (this.props.users.length === 1) {
|
||||||
!this.props.createChannel.failure ||
|
return;
|
||||||
this.props.createChannel.error.error !== 'error-duplicate-channel-name'
|
|
||||||
) {
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
this.props.removeUser(user);
|
||||||
return (
|
|
||||||
<Text style={[styles.label_white, styles.label_error]} testID='create-channel-error'>
|
|
||||||
{this.props.createChannel.error.reason}
|
|
||||||
</Text>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
renderSwitch = ({
|
renderSwitch = ({
|
||||||
id, value, label, description, onValueChange, disabled = false
|
id, value, label, onValueChange, disabled = false
|
||||||
}) => (
|
}) => (
|
||||||
<View style={{ marginBottom: 15 }}>
|
<View style={styles.swithContainer}>
|
||||||
<View style={styles.switchContainer}>
|
<Text style={styles.label}>{I18n.t(label)}</Text>
|
||||||
<Switch
|
<Switch
|
||||||
value={value}
|
value={value}
|
||||||
onValueChange={onValueChange}
|
onValueChange={onValueChange}
|
||||||
testID={`create-channel-${ id }`}
|
testID={`create-channel-${ id }`}
|
||||||
onTintColor='#2de0a5'
|
onTintColor='#2de0a5'
|
||||||
tintColor={Platform.OS === 'android' ? '#f5455c' : null}
|
tintColor={Platform.OS === 'android' ? '#f5455c' : null}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
/>
|
/>
|
||||||
<Text style={styles.switchLabel}>{label}</Text>
|
|
||||||
</View>
|
|
||||||
<Text style={styles.switchDescription}>{description}</Text>
|
|
||||||
</View>
|
</View>
|
||||||
);
|
)
|
||||||
|
|
||||||
renderType() {
|
renderType() {
|
||||||
const { type } = this.state;
|
const { type } = this.state;
|
||||||
return this.renderSwitch({
|
return this.renderSwitch({
|
||||||
id: 'type',
|
id: 'type',
|
||||||
value: type,
|
value: type,
|
||||||
label: type ? I18n.t('Private_Channel') : I18n.t('Public_Channel'),
|
label: 'Private_Channel',
|
||||||
description: type ? I18n.t('Just_invited_people_can_access_this_channel') : I18n.t('Everyone_can_access_this_channel'),
|
|
||||||
onValueChange: value => this.setState({ type: value })
|
onValueChange: value => this.setState({ type: value })
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -112,8 +187,7 @@ export default class CreateChannelView extends LoggedView {
|
||||||
return this.renderSwitch({
|
return this.renderSwitch({
|
||||||
id: 'readonly',
|
id: 'readonly',
|
||||||
value: readOnly,
|
value: readOnly,
|
||||||
label: I18n.t('Read_Only_Channel'),
|
label: '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'),
|
|
||||||
onValueChange: value => this.setState({ readOnly: value }),
|
onValueChange: value => this.setState({ readOnly: value }),
|
||||||
disabled: broadcast
|
disabled: broadcast
|
||||||
});
|
});
|
||||||
|
@ -124,8 +198,7 @@ export default class CreateChannelView extends LoggedView {
|
||||||
return this.renderSwitch({
|
return this.renderSwitch({
|
||||||
id: 'broadcast',
|
id: 'broadcast',
|
||||||
value: broadcast,
|
value: broadcast,
|
||||||
label: I18n.t('Broadcast_Channel'),
|
label: 'Broadcast_Channel',
|
||||||
description: I18n.t('Broadcast_channel_Description'),
|
|
||||||
onValueChange: (value) => {
|
onValueChange: (value) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
broadcast: value,
|
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() {
|
render() {
|
||||||
|
const userCount = this.props.users.length;
|
||||||
return (
|
return (
|
||||||
<KeyboardView
|
<KeyboardView
|
||||||
contentContainerStyle={styles.container}
|
contentContainerStyle={[sharedStyles.container, styles.container]}
|
||||||
keyboardVerticalOffset={128}
|
keyboardVerticalOffset={128}
|
||||||
>
|
>
|
||||||
<ScrollView {...scrollPersistTaps} contentContainerStyle={styles.containerScrollView}>
|
<SafeAreaView testID='create-channel-view'>
|
||||||
<SafeAreaView testID='create-channel-view'>
|
<ScrollView {...scrollPersistTaps}>
|
||||||
<RCTextInput
|
<View style={sharedStyles.separatorVertical}>
|
||||||
inputRef={ref => this.channelNameRef = ref}
|
<TextInput
|
||||||
label={I18n.t('Channel_Name')}
|
ref={ref => this.channelNameRef = ref}
|
||||||
value={this.state.channelName}
|
style={styles.input}
|
||||||
onChangeText={channelName => this.setState({ channelName })}
|
label={I18n.t('Channel_Name')}
|
||||||
placeholder={I18n.t('Type_the_channel_name_here')}
|
value={this.state.channelName}
|
||||||
returnKeyType='done'
|
onChangeText={this.onChangeText}
|
||||||
testID='create-channel-name'
|
placeholder={I18n.t('Channel_Name')}
|
||||||
/>
|
returnKeyType='done'
|
||||||
{this.renderChannelNameError()}
|
testID='create-channel-name'
|
||||||
{this.renderType()}
|
autoCorrect={false}
|
||||||
{this.renderReadOnly()}
|
autoCapitalize='none'
|
||||||
{this.renderBroadcast()}
|
underlineColorAndroid='transparent'
|
||||||
<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'
|
|
||||||
/>
|
/>
|
||||||
|
{this.renderFormSeparator()}
|
||||||
|
{this.renderType()}
|
||||||
|
{this.renderFormSeparator()}
|
||||||
|
{this.renderReadOnly()}
|
||||||
|
{this.renderFormSeparator()}
|
||||||
|
{this.renderBroadcast()}
|
||||||
</View>
|
</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} />
|
<Loading visible={this.props.createChannel.isFetching} />
|
||||||
</SafeAreaView>
|
</ScrollView>
|
||||||
</ScrollView>
|
</SafeAreaView>
|
||||||
</KeyboardView>
|
</KeyboardView>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -182,7 +182,7 @@ export default class LoginSignupView extends LoggedView {
|
||||||
this.props.navigator.push({
|
this.props.navigator.push({
|
||||||
screen: 'LoginView',
|
screen: 'LoginView',
|
||||||
title: this.props.server,
|
title: this.props.server,
|
||||||
backButtonTitle: I18n.t('Welcome')
|
backButtonTitle: ''
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -190,7 +190,7 @@ export default class LoginSignupView extends LoggedView {
|
||||||
this.props.navigator.push({
|
this.props.navigator.push({
|
||||||
screen: 'RegisterView',
|
screen: 'RegisterView',
|
||||||
title: this.props.server,
|
title: this.props.server,
|
||||||
backButtonTitle: I18n.t('Welcome')
|
backButtonTitle: ''
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -68,7 +68,7 @@ export default class LoginView extends LoggedView {
|
||||||
this.props.navigator.push({
|
this.props.navigator.push({
|
||||||
screen: 'RegisterView',
|
screen: 'RegisterView',
|
||||||
title: this.props.server,
|
title: this.props.server,
|
||||||
backButtonTitle: I18n.t('Login')
|
backButtonTitle: ''
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ export default class LoginView extends LoggedView {
|
||||||
this.props.navigator.push({
|
this.props.navigator.push({
|
||||||
screen: 'ForgotPasswordView',
|
screen: 'ForgotPasswordView',
|
||||||
title: I18n.t('Forgot_Password'),
|
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 React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
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 { connect } from 'react-redux';
|
||||||
|
|
||||||
import { serverRequest } from '../actions/server';
|
import { serverRequest, selectServerRequest, serverInitAdd, serverFinishAdd } from '../actions/server';
|
||||||
import sharedStyles from './Styles';
|
import sharedStyles from './Styles';
|
||||||
import scrollPersistTaps from '../utils/scrollPersistTaps';
|
import scrollPersistTaps from '../utils/scrollPersistTaps';
|
||||||
import Button from '../containers/Button';
|
import Button from '../containers/Button';
|
||||||
|
@ -12,7 +12,6 @@ import LoggedView from './View';
|
||||||
import I18n from '../i18n';
|
import I18n from '../i18n';
|
||||||
import { scale, verticalScale, moderateScale } from '../utils/scaling';
|
import { scale, verticalScale, moderateScale } from '../utils/scaling';
|
||||||
import KeyboardView from '../presentation/KeyboardView';
|
import KeyboardView from '../presentation/KeyboardView';
|
||||||
import { iconsMap } from '../Icons';
|
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
image: {
|
image: {
|
||||||
|
@ -45,9 +44,13 @@ const defaultServer = 'https://open.rocket.chat';
|
||||||
@connect(state => ({
|
@connect(state => ({
|
||||||
connecting: state.server.connecting,
|
connecting: state.server.connecting,
|
||||||
failure: state.server.failure,
|
failure: state.server.failure,
|
||||||
currentServer: state.server.server
|
currentServer: state.server.server,
|
||||||
|
adding: state.server.adding
|
||||||
}), dispatch => ({
|
}), 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 */
|
/** @extends React.Component */
|
||||||
export default class NewServerView extends LoggedView {
|
export default class NewServerView extends LoggedView {
|
||||||
|
@ -55,10 +58,14 @@ export default class NewServerView extends LoggedView {
|
||||||
navigator: PropTypes.object,
|
navigator: PropTypes.object,
|
||||||
server: PropTypes.string,
|
server: PropTypes.string,
|
||||||
connecting: PropTypes.bool.isRequired,
|
connecting: PropTypes.bool.isRequired,
|
||||||
|
adding: PropTypes.bool,
|
||||||
failure: PropTypes.bool.isRequired,
|
failure: PropTypes.bool.isRequired,
|
||||||
connectServer: PropTypes.func.isRequired,
|
connectServer: PropTypes.func.isRequired,
|
||||||
|
selectServer: PropTypes.func.isRequired,
|
||||||
previousServer: PropTypes.string,
|
previousServer: PropTypes.string,
|
||||||
currentServer: PropTypes.string
|
currentServer: PropTypes.string,
|
||||||
|
initAdd: PropTypes.func,
|
||||||
|
finishAdd: PropTypes.func
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
@ -69,25 +76,8 @@ export default class NewServerView extends LoggedView {
|
||||||
props.navigator.setOnNavigatorEvent(this.onNavigatorEvent.bind(this));
|
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() {
|
componentDidMount() {
|
||||||
const { server } = this.props;
|
const { server, previousServer } = this.props;
|
||||||
if (server) {
|
if (server) {
|
||||||
this.props.connectServer(server);
|
this.props.connectServer(server);
|
||||||
this.setState({ text: server });
|
this.setState({ text: server });
|
||||||
|
@ -96,6 +86,9 @@ export default class NewServerView extends LoggedView {
|
||||||
this.input.focus();
|
this.input.focus();
|
||||||
}, 600);
|
}, 600);
|
||||||
}
|
}
|
||||||
|
if (previousServer) {
|
||||||
|
this.props.initAdd();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
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) {
|
onNavigatorEvent(event) {
|
||||||
if (event.type === 'NavBarButtonPress') {
|
if (event.type === 'NavBarButtonPress') {
|
||||||
if (event.id === 'close') {
|
if (event.id === 'cancel') {
|
||||||
const {
|
this.props.navigator.dismissModal();
|
||||||
navigator, connectServer, previousServer, currentServer
|
|
||||||
} = this.props;
|
|
||||||
navigator.dismissModal();
|
|
||||||
if (previousServer !== currentServer) {
|
|
||||||
connectServer(previousServer);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ const userAgent = Platform.OS === 'ios' ? 'UserAgent' : userAgentAndroid;
|
||||||
@connect(state => ({
|
@connect(state => ({
|
||||||
server: state.server.server
|
server: state.server.server
|
||||||
}))
|
}))
|
||||||
export default class TermsServiceView extends React.PureComponent {
|
export default class OAuthView extends React.PureComponent {
|
||||||
static navigatorButtons = {
|
static navigatorButtons = {
|
||||||
leftButtons: [{
|
leftButtons: [{
|
||||||
id: 'close',
|
id: 'close',
|
||||||
|
|
|
@ -21,6 +21,7 @@ export default class OnboardingView extends LoggedView {
|
||||||
connectServer = () => {
|
connectServer = () => {
|
||||||
this.props.navigator.push({
|
this.props.navigator.push({
|
||||||
screen: 'NewServerView',
|
screen: 'NewServerView',
|
||||||
|
backButtonTitle: '',
|
||||||
navigatorStyle: {
|
navigatorStyle: {
|
||||||
navBarHidden: true
|
navBarHidden: true
|
||||||
}
|
}
|
||||||
|
@ -30,6 +31,7 @@ export default class OnboardingView extends LoggedView {
|
||||||
joinCommunity = () => {
|
joinCommunity = () => {
|
||||||
this.props.navigator.push({
|
this.props.navigator.push({
|
||||||
screen: 'NewServerView',
|
screen: 'NewServerView',
|
||||||
|
backButtonTitle: '',
|
||||||
passProps: {
|
passProps: {
|
||||||
server: 'https://open.rocket.chat'
|
server: 'https://open.rocket.chat'
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
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 { connect } from 'react-redux';
|
||||||
import Dialog from 'react-native-dialog';
|
import Dialog from 'react-native-dialog';
|
||||||
import SHA256 from 'js-sha256';
|
import SHA256 from 'js-sha256';
|
||||||
|
@ -61,7 +61,7 @@ export default class ProfileView extends LoggedView {
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
this.props.navigator.setButtons({
|
this.props.navigator.setButtons({
|
||||||
leftButtons: [{
|
leftButtons: [{
|
||||||
id: 'sideMenu',
|
id: 'settings',
|
||||||
icon: { uri: 'settings', scale: Dimensions.get('window').scale }
|
icon: { uri: 'settings', scale: Dimensions.get('window').scale }
|
||||||
}]
|
}]
|
||||||
});
|
});
|
||||||
|
@ -91,7 +91,7 @@ export default class ProfileView extends LoggedView {
|
||||||
|
|
||||||
onNavigatorEvent(event) {
|
onNavigatorEvent(event) {
|
||||||
if (event.type === 'NavBarButtonPress') {
|
if (event.type === 'NavBarButtonPress') {
|
||||||
if (event.id === 'sideMenu' && Platform.OS === 'ios') {
|
if (event.id === 'settings') {
|
||||||
this.props.navigator.toggleDrawer({
|
this.props.navigator.toggleDrawer({
|
||||||
side: 'left'
|
side: 'left'
|
||||||
});
|
});
|
||||||
|
|
|
@ -93,7 +93,7 @@ export default class RegisterView extends LoggedView {
|
||||||
this.props.navigator.push({
|
this.props.navigator.push({
|
||||||
screen: 'TermsServiceView',
|
screen: 'TermsServiceView',
|
||||||
title: I18n.t('Terms_of_Service'),
|
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({
|
this.props.navigator.push({
|
||||||
screen: 'PrivacyPolicyView',
|
screen: 'PrivacyPolicyView',
|
||||||
title: I18n.t('Privacy_Policy'),
|
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({
|
this.props.navigator.push({
|
||||||
screen: item.route,
|
screen: item.route,
|
||||||
title: item.name,
|
title: item.name,
|
||||||
passProps: item.params
|
passProps: item.params,
|
||||||
|
backButtonTitle: ''
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (item.event) {
|
if (item.event) {
|
||||||
|
|
|
@ -118,6 +118,7 @@ export default class RoomInfoView extends LoggedView {
|
||||||
this.props.navigator.push({
|
this.props.navigator.push({
|
||||||
screen: 'RoomInfoEditView',
|
screen: 'RoomInfoEditView',
|
||||||
title: I18n.t('Room_Info_Edit'),
|
title: I18n.t('Room_Info_Edit'),
|
||||||
|
backButtonTitle: '',
|
||||||
passProps: {
|
passProps: {
|
||||||
rid: this.props.rid
|
rid: this.props.rid
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
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 ActionSheet from 'react-native-actionsheet';
|
||||||
|
|
||||||
import LoggedView from '../View';
|
import LoggedView from '../View';
|
||||||
|
@ -12,6 +12,7 @@ import database from '../../lib/realm';
|
||||||
import { showToast } from '../../utils/info';
|
import { showToast } from '../../utils/info';
|
||||||
import log from '../../utils/log';
|
import log from '../../utils/log';
|
||||||
import I18n from '../../i18n';
|
import I18n from '../../i18n';
|
||||||
|
import SearchBox from '../../containers/SearchBox';
|
||||||
|
|
||||||
/** @extends React.Component */
|
/** @extends React.Component */
|
||||||
export default class RoomMembersView extends LoggedView {
|
export default class RoomMembersView extends LoggedView {
|
||||||
|
@ -132,6 +133,7 @@ export default class RoomMembersView extends LoggedView {
|
||||||
this.props.navigator.push({
|
this.props.navigator.push({
|
||||||
screen: 'RoomView',
|
screen: 'RoomView',
|
||||||
title: name,
|
title: name,
|
||||||
|
backButtonTitle: '',
|
||||||
passProps: {
|
passProps: {
|
||||||
room: { rid, name },
|
room: { rid, name },
|
||||||
rid,
|
rid,
|
||||||
|
@ -162,20 +164,7 @@ export default class RoomMembersView extends LoggedView {
|
||||||
}
|
}
|
||||||
|
|
||||||
renderSearchBar = () => (
|
renderSearchBar = () => (
|
||||||
<View style={styles.searchBoxView}>
|
<SearchBox onChangeText={text => this.onSearchChangeText(text)} testID='room-members-view-search' />
|
||||||
<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>
|
|
||||||
)
|
)
|
||||||
|
|
||||||
renderSeparator = () => <View style={styles.separator} />;
|
renderSeparator = () => <View style={styles.separator} />;
|
||||||
|
|
|
@ -127,6 +127,7 @@ export default class RoomView extends LoggedView {
|
||||||
this.props.navigator.push({
|
this.props.navigator.push({
|
||||||
screen: 'RoomActionsView',
|
screen: 'RoomActionsView',
|
||||||
title: I18n.t('Actions'),
|
title: I18n.t('Actions'),
|
||||||
|
backButtonTitle: '',
|
||||||
passProps: {
|
passProps: {
|
||||||
rid: this.state.room.rid
|
rid: this.state.room.rid
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,6 +86,13 @@ export default class ServerDropdown extends Component {
|
||||||
title: I18n.t('Add_Server'),
|
title: I18n.t('Add_Server'),
|
||||||
passProps: {
|
passProps: {
|
||||||
previousServer: this.props.server
|
previousServer: this.props.server
|
||||||
|
},
|
||||||
|
navigatorButtons: {
|
||||||
|
leftButtons: [{
|
||||||
|
id: 'cancel',
|
||||||
|
testID: 'new-server-close',
|
||||||
|
title: I18n.t('Close')
|
||||||
|
}]
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}, ANIMATION_DURATION);
|
}, ANIMATION_DURATION);
|
||||||
|
@ -101,6 +108,7 @@ export default class ServerDropdown extends Component {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.props.navigator.push({
|
this.props.navigator.push({
|
||||||
screen: 'NewServerView',
|
screen: 'NewServerView',
|
||||||
|
backButtonTitle: '',
|
||||||
passProps: {
|
passProps: {
|
||||||
server
|
server
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
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 { connect } from 'react-redux';
|
||||||
import { isEqual } from 'lodash';
|
import { isEqual } from 'lodash';
|
||||||
|
|
||||||
|
import SearchBox from '../../containers/SearchBox';
|
||||||
import database from '../../lib/realm';
|
import database from '../../lib/realm';
|
||||||
import RocketChat from '../../lib/rocketchat';
|
import RocketChat from '../../lib/rocketchat';
|
||||||
import RoomItem from '../../presentation/RoomItem';
|
import RoomItem from '../../presentation/RoomItem';
|
||||||
|
@ -26,7 +27,7 @@ const leftButtons = [{
|
||||||
testID: 'rooms-list-view-sidebar'
|
testID: 'rooms-list-view-sidebar'
|
||||||
}];
|
}];
|
||||||
const rightButtons = [{
|
const rightButtons = [{
|
||||||
id: 'createChannel',
|
id: 'newMessage',
|
||||||
icon: { uri: 'new_channel', scale: Dimensions.get('window').scale },
|
icon: { uri: 'new_channel', scale: Dimensions.get('window').scale },
|
||||||
testID: 'rooms-list-view-create-channel'
|
testID: 'rooms-list-view-create-channel'
|
||||||
}];
|
}];
|
||||||
|
@ -38,7 +39,6 @@ if (Platform.OS === 'android') {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@connect((state) => {
|
@connect((state) => {
|
||||||
let result = {
|
let result = {
|
||||||
userId: state.login.user && state.login.user.id,
|
userId: state.login.user && state.login.user.id,
|
||||||
|
@ -74,7 +74,6 @@ export default class RoomsListView extends LoggedView {
|
||||||
|
|
||||||
static navigatorStyle = {
|
static navigatorStyle = {
|
||||||
navBarCustomView: 'RoomsListHeaderView',
|
navBarCustomView: 'RoomsListHeaderView',
|
||||||
navBarComponentAlignment: 'fill',
|
|
||||||
navBarBackgroundColor: isAndroid() ? '#2F343D' : undefined,
|
navBarBackgroundColor: isAndroid() ? '#2F343D' : undefined,
|
||||||
navBarTextColor: isAndroid() ? '#FFF' : undefined,
|
navBarTextColor: isAndroid() ? '#FFF' : undefined,
|
||||||
navBarButtonColor: isAndroid() ? '#FFF' : undefined
|
navBarButtonColor: isAndroid() ? '#FFF' : undefined
|
||||||
|
@ -157,6 +156,10 @@ export default class RoomsListView extends LoggedView {
|
||||||
this.removeListener(this.direct);
|
this.removeListener(this.direct);
|
||||||
this.removeListener(this.livechat);
|
this.removeListener(this.livechat);
|
||||||
|
|
||||||
|
if (database && database.deleteAll) {
|
||||||
|
database.deleteAll();
|
||||||
|
}
|
||||||
|
|
||||||
if (this.timeout) {
|
if (this.timeout) {
|
||||||
clearTimeout(this.timeout);
|
clearTimeout(this.timeout);
|
||||||
}
|
}
|
||||||
|
@ -165,12 +168,12 @@ export default class RoomsListView extends LoggedView {
|
||||||
onNavigatorEvent(event) {
|
onNavigatorEvent(event) {
|
||||||
const { navigator } = this.props;
|
const { navigator } = this.props;
|
||||||
if (event.type === 'NavBarButtonPress') {
|
if (event.type === 'NavBarButtonPress') {
|
||||||
if (event.id === 'createChannel') {
|
if (event.id === 'newMessage') {
|
||||||
this.props.navigator.push({
|
this.props.navigator.showModal({
|
||||||
screen: 'SelectedUsersView',
|
screen: 'NewMessageView',
|
||||||
title: I18n.t('Select_Users'),
|
title: I18n.t('New_Message'),
|
||||||
passProps: {
|
passProps: {
|
||||||
nextAction: 'CREATE_CHANNEL'
|
onPressItem: this._onPressItem
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else if (event.id === 'settings') {
|
} else if (event.id === 'settings') {
|
||||||
|
@ -190,10 +193,6 @@ export default class RoomsListView extends LoggedView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onSearchChangeText(text) {
|
|
||||||
this.search(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
getSubscriptions = () => {
|
getSubscriptions = () => {
|
||||||
if (this.props.server && this.hasActiveDB()) {
|
if (this.props.server && this.hasActiveDB()) {
|
||||||
if (this.props.sidebarSortby === 'alphabetical') {
|
if (this.props.sidebarSortby === 'alphabetical') {
|
||||||
|
@ -285,7 +284,6 @@ export default class RoomsListView extends LoggedView {
|
||||||
navigator.setButtons({ leftButtons, rightButtons });
|
navigator.setButtons({ leftButtons, rightButtons });
|
||||||
navigator.setStyle({
|
navigator.setStyle({
|
||||||
navBarCustomView: 'RoomsListHeaderView',
|
navBarCustomView: 'RoomsListHeaderView',
|
||||||
navBarComponentAlignment: 'fill',
|
|
||||||
navBarBackgroundColor: isAndroid() ? '#2F343D' : undefined,
|
navBarBackgroundColor: isAndroid() ? '#2F343D' : undefined,
|
||||||
navBarTextColor: isAndroid() ? '#FFF' : undefined,
|
navBarTextColor: isAndroid() ? '#FFF' : undefined,
|
||||||
navBarButtonColor: isAndroid() ? '#FFF' : undefined
|
navBarButtonColor: isAndroid() ? '#FFF' : undefined
|
||||||
|
@ -327,55 +325,18 @@ export default class RoomsListView extends LoggedView {
|
||||||
|
|
||||||
_isUnread = item => item.unread > 0 || item.alert
|
_isUnread = item => item.unread > 0 || item.alert
|
||||||
|
|
||||||
async search(text) {
|
search = async(text) => {
|
||||||
const searchText = text.trim();
|
const result = await RocketChat.search({ text });
|
||||||
if (searchText === '') {
|
this.setState({
|
||||||
delete this.oldPromise;
|
search: result
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
goRoom = (rid, name) => {
|
goRoom = (rid, name) => {
|
||||||
this.props.navigator.push({
|
this.props.navigator.push({
|
||||||
screen: 'RoomView',
|
screen: 'RoomView',
|
||||||
title: name,
|
title: name,
|
||||||
|
backButtonTitle: '',
|
||||||
passProps: {
|
passProps: {
|
||||||
room: { rid, name },
|
room: { rid, name },
|
||||||
rid,
|
rid,
|
||||||
|
@ -429,22 +390,7 @@ export default class RoomsListView extends LoggedView {
|
||||||
|
|
||||||
renderSearchBar = () => {
|
renderSearchBar = () => {
|
||||||
if (Platform.OS === 'ios') {
|
if (Platform.OS === 'ios') {
|
||||||
return (
|
return <SearchBox onChangeText={text => this.search(text)} testID='rooms-list-view-search' />;
|
||||||
<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>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -537,7 +483,7 @@ export default class RoomsListView extends LoggedView {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ScrollView
|
<ScrollView
|
||||||
contentOffset={Platform.OS === 'ios' ? { x: 0, y: 37 } : {}}
|
contentOffset={Platform.OS === 'ios' ? { x: 0, y: 56 } : {}}
|
||||||
keyboardShouldPersistTaps='always'
|
keyboardShouldPersistTaps='always'
|
||||||
testID='rooms-list-view-list'
|
testID='rooms-list-view-list'
|
||||||
>
|
>
|
||||||
|
|
|
@ -31,17 +31,6 @@ export default StyleSheet.create({
|
||||||
height: 22,
|
height: 22,
|
||||||
color: 'white'
|
color: 'white'
|
||||||
},
|
},
|
||||||
searchBoxView: {
|
|
||||||
backgroundColor: '#eee'
|
|
||||||
},
|
|
||||||
searchBox: {
|
|
||||||
backgroundColor: '#fff',
|
|
||||||
margin: 5,
|
|
||||||
borderRadius: 5,
|
|
||||||
padding: 5,
|
|
||||||
paddingLeft: 10,
|
|
||||||
color: '#aaa'
|
|
||||||
},
|
|
||||||
loading: {
|
loading: {
|
||||||
flex: 1
|
flex: 1
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,56 +1,29 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
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 { connect } from 'react-redux';
|
||||||
|
|
||||||
import { addUser, removeUser, reset, setLoading } from '../actions/selectedUsers';
|
import { addUser, removeUser, reset, setLoading } from '../actions/selectedUsers';
|
||||||
import database from '../lib/realm';
|
import database from '../lib/realm';
|
||||||
import RocketChat from '../lib/rocketchat';
|
import RocketChat from '../lib/rocketchat';
|
||||||
import UserItem from '../presentation/UserItem';
|
import UserItem from '../presentation/UserItem';
|
||||||
import Avatar from '../containers/Avatar';
|
|
||||||
import Loading from '../containers/Loading';
|
import Loading from '../containers/Loading';
|
||||||
import debounce from '../utils/debounce';
|
import debounce from '../utils/debounce';
|
||||||
import LoggedView from './View';
|
import LoggedView from './View';
|
||||||
import I18n from '../i18n';
|
import I18n from '../i18n';
|
||||||
import log from '../utils/log';
|
import log from '../utils/log';
|
||||||
import { iconsMap } from '../Icons';
|
import SearchBox from '../containers/SearchBox';
|
||||||
|
import sharedStyles from './Styles';
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
|
||||||
flex: 1,
|
|
||||||
alignItems: 'stretch',
|
|
||||||
justifyContent: 'center'
|
|
||||||
},
|
|
||||||
safeAreaView: {
|
safeAreaView: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
backgroundColor: '#FFFFFF'
|
backgroundColor: Platform.OS === 'ios' ? '#F7F8FA' : '#E1E5E8'
|
||||||
},
|
},
|
||||||
list: {
|
header: {
|
||||||
width: '100%',
|
backgroundColor: '#fff'
|
||||||
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'
|
|
||||||
},
|
},
|
||||||
separator: {
|
separator: {
|
||||||
height: StyleSheet.hairlineWidth,
|
|
||||||
backgroundColor: '#E1E5E8',
|
|
||||||
marginLeft: 60
|
marginLeft: 60
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -95,15 +68,19 @@ export default class SelectedUsersView extends LoggedView {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
async componentDidUpdate(prevProps) {
|
||||||
if (nextProps.users.length !== this.props.users.length) {
|
const isVisible = await this.props.navigator.screenIsCurrentlyVisible();
|
||||||
const { length } = nextProps.users;
|
if (!isVisible) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (prevProps.users.length !== this.props.users.length) {
|
||||||
|
const { length } = this.props.users;
|
||||||
const rightButtons = [];
|
const rightButtons = [];
|
||||||
if (length > 0) {
|
if (length > 0) {
|
||||||
rightButtons.push({
|
rightButtons.push({
|
||||||
id: 'create',
|
id: 'create',
|
||||||
testID: 'selected-users-view-submit',
|
title: I18n.t('Next'),
|
||||||
icon: iconsMap.add
|
testID: 'selected-users-view-submit'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
this.props.navigator.setButtons({ rightButtons });
|
this.props.navigator.setButtons({ rightButtons });
|
||||||
|
@ -123,7 +100,8 @@ export default class SelectedUsersView extends LoggedView {
|
||||||
if (nextAction === 'CREATE_CHANNEL') {
|
if (nextAction === 'CREATE_CHANNEL') {
|
||||||
this.props.navigator.push({
|
this.props.navigator.push({
|
||||||
screen: 'CreateChannelView',
|
screen: 'CreateChannelView',
|
||||||
title: I18n.t('Create_Channel')
|
title: I18n.t('Create_Channel'),
|
||||||
|
backButtonTitle: ''
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
|
@ -148,90 +126,40 @@ export default class SelectedUsersView extends LoggedView {
|
||||||
this.forceUpdate();
|
this.forceUpdate();
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
|
||||||
async search(text) {
|
search = async(text) => {
|
||||||
const searchText = text.trim();
|
const result = await RocketChat.search({ text, filterRooms: false });
|
||||||
if (searchText === '') {
|
this.setState({
|
||||||
delete this.oldPromise;
|
search: result
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isChecked = username => this.props.users.findIndex(el => el.name === username) !== -1;
|
||||||
|
|
||||||
toggleUser = (user) => {
|
toggleUser = (user) => {
|
||||||
LayoutAnimation.easeInEaseOut();
|
LayoutAnimation.easeInEaseOut();
|
||||||
const index = this.props.users.findIndex(el => el.name === user.name);
|
if (!this.isChecked(user.name)) {
|
||||||
if (index === -1) {
|
|
||||||
this.props.addUser(user);
|
this.props.addUser(user);
|
||||||
} else {
|
} else {
|
||||||
this.props.removeUser(user);
|
this.props.removeUser(user);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
_onPressItem = (id, item = {}) => {
|
_onPressItem = (id, item = {}) => {
|
||||||
if (item.search) {
|
if (item.search) {
|
||||||
this.toggleUser({ _id: item._id, name: item.username });
|
this.toggleUser({ _id: item._id, name: item.username, fname: item.name });
|
||||||
} else {
|
} 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);
|
_onPressSelectedItem = item => this.toggleUser(item);
|
||||||
|
|
||||||
renderHeader = () => (
|
renderHeader = () => (
|
||||||
<View style={styles.container}>
|
<View style={styles.header}>
|
||||||
{this.renderSearchBar()}
|
<SearchBox onChangeText={text => this.onSearchChangeText(text)} testID='select-users-view-search' />
|
||||||
{this.renderSelected()}
|
{this.renderSelected()}
|
||||||
</View>
|
</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 = () => {
|
renderSelected = () => {
|
||||||
if (this.props.users.length === 0) {
|
if (this.props.users.length === 0) {
|
||||||
|
@ -241,57 +169,70 @@ export default class SelectedUsersView extends LoggedView {
|
||||||
<FlatList
|
<FlatList
|
||||||
data={this.props.users}
|
data={this.props.users}
|
||||||
keyExtractor={item => item._id}
|
keyExtractor={item => item._id}
|
||||||
style={styles.list}
|
style={[styles.list, sharedStyles.separatorTop]}
|
||||||
|
contentContainerStyle={{ marginVertical: 5 }}
|
||||||
renderItem={this.renderSelectedItem}
|
renderItem={this.renderSelectedItem}
|
||||||
enableEmptySections
|
enableEmptySections
|
||||||
keyboardShouldPersistTaps='always'
|
keyboardShouldPersistTaps='always'
|
||||||
horizontal
|
horizontal
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
|
|
||||||
renderSelectedItem = ({ item }) => (
|
renderSelectedItem = ({ item }) => (
|
||||||
<TouchableOpacity
|
<UserItem
|
||||||
key={item._id}
|
name={item.fname}
|
||||||
style={styles.selectItemView}
|
username={item.name}
|
||||||
onPress={() => this._onPressSelectedItem(item)}
|
onPress={() => this._onPressSelectedItem(item)}
|
||||||
testID={`selected-user-${ item.name }`}
|
testID={`selected-user-${ item.name }`}
|
||||||
>
|
style={{ paddingRight: 15 }}
|
||||||
<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 }`}
|
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
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 = () => (
|
renderList = () => (
|
||||||
<FlatList
|
<FlatList
|
||||||
data={this.state.search.length > 0 ? this.state.search : this.data}
|
data={this.state.search.length > 0 ? this.state.search : this.data}
|
||||||
extraData={this.props}
|
extraData={this.props}
|
||||||
keyExtractor={item => item._id}
|
keyExtractor={item => item._id}
|
||||||
style={styles.list}
|
|
||||||
renderItem={this.renderItem}
|
renderItem={this.renderItem}
|
||||||
ListHeaderComponent={this.renderHeader}
|
|
||||||
ItemSeparatorComponent={this.renderSeparator}
|
ItemSeparatorComponent={this.renderSeparator}
|
||||||
|
ListHeaderComponent={this.renderHeader}
|
||||||
enableEmptySections
|
enableEmptySections
|
||||||
keyboardShouldPersistTaps='always'
|
keyboardShouldPersistTaps='always'
|
||||||
/>
|
/>
|
||||||
);
|
)
|
||||||
|
|
||||||
render = () => (
|
render = () => (
|
||||||
<SafeAreaView style={styles.safeAreaView} testID='select-users-view'>
|
<SafeAreaView style={styles.safeAreaView} testID='select-users-view'>
|
||||||
{this.renderList()}
|
{this.renderList()}
|
||||||
<Loading visible={this.props.loading} />
|
<Loading visible={this.props.loading} />
|
||||||
</SafeAreaView>
|
</SafeAreaView>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
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 RNPickerSelect from 'react-native-picker-select';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ export default class SettingsView extends LoggedView {
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
this.props.navigator.setButtons({
|
this.props.navigator.setButtons({
|
||||||
leftButtons: [{
|
leftButtons: [{
|
||||||
id: 'sideMenu',
|
id: 'settings',
|
||||||
icon: { uri: 'settings', scale: Dimensions.get('window').scale }
|
icon: { uri: 'settings', scale: Dimensions.get('window').scale }
|
||||||
}]
|
}]
|
||||||
});
|
});
|
||||||
|
@ -65,7 +65,7 @@ export default class SettingsView extends LoggedView {
|
||||||
|
|
||||||
onNavigatorEvent(event) {
|
onNavigatorEvent(event) {
|
||||||
if (event.type === 'NavBarButtonPress') {
|
if (event.type === 'NavBarButtonPress') {
|
||||||
if (event.id === 'sideMenu' && Platform.OS === 'ios') {
|
if (event.id === 'settings') {
|
||||||
this.props.navigator.toggleDrawer({
|
this.props.navigator.toggleDrawer({
|
||||||
side: 'left'
|
side: 'left'
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { StyleSheet, Platform } from 'react-native';
|
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({
|
export default StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
|
@ -197,5 +197,22 @@ export default StyleSheet.create({
|
||||||
width: 44,
|
width: 44,
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
justifyContent: '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 LoginSignupView from './LoginSignupView';
|
||||||
import LoginView from './LoginView';
|
import LoginView from './LoginView';
|
||||||
import MentionedMessagesView from './MentionedMessagesView';
|
import MentionedMessagesView from './MentionedMessagesView';
|
||||||
|
import NewMessageView from './NewMessageView';
|
||||||
import NewServerView from './NewServerView';
|
import NewServerView from './NewServerView';
|
||||||
import OAuthView from './OAuthView';
|
import OAuthView from './OAuthView';
|
||||||
import OnboardingView from './OnboardingView';
|
import OnboardingView from './OnboardingView';
|
||||||
|
@ -36,6 +37,7 @@ export const registerScreens = (store) => {
|
||||||
Navigation.registerComponent('LoginSignupView', () => LoginSignupView, store, Provider);
|
Navigation.registerComponent('LoginSignupView', () => LoginSignupView, store, Provider);
|
||||||
Navigation.registerComponent('LoginView', () => LoginView, store, Provider);
|
Navigation.registerComponent('LoginView', () => LoginView, store, Provider);
|
||||||
Navigation.registerComponent('MentionedMessagesView', () => MentionedMessagesView, store, Provider);
|
Navigation.registerComponent('MentionedMessagesView', () => MentionedMessagesView, store, Provider);
|
||||||
|
Navigation.registerComponent('NewMessageView', () => NewMessageView, store, Provider);
|
||||||
Navigation.registerComponent('NewServerView', () => NewServerView, store, Provider);
|
Navigation.registerComponent('NewServerView', () => NewServerView, store, Provider);
|
||||||
Navigation.registerComponent('OAuthView', () => OAuthView, store, Provider);
|
Navigation.registerComponent('OAuthView', () => OAuthView, store, Provider);
|
||||||
Navigation.registerComponent('OnboardingView', () => OnboardingView, store, Provider);
|
Navigation.registerComponent('OnboardingView', () => OnboardingView, store, Provider);
|
||||||
|
|
|
@ -30,14 +30,14 @@ describe('Welcome screen', () => {
|
||||||
await element(by.id('welcome-view-login')).tap();
|
await element(by.id('welcome-view-login')).tap();
|
||||||
await waitFor(element(by.id('login-view'))).toBeVisible().withTimeout(2000);
|
await waitFor(element(by.id('login-view'))).toBeVisible().withTimeout(2000);
|
||||||
await expect(element(by.id('login-view'))).toBeVisible();
|
await expect(element(by.id('login-view'))).toBeVisible();
|
||||||
await tapBack('Welcome');
|
await tapBack();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should navigate to register', async() => {
|
it('should navigate to register', async() => {
|
||||||
await element(by.id('welcome-view-register')).tap();
|
await element(by.id('welcome-view-register')).tap();
|
||||||
await waitFor(element(by.id('register-view'))).toBeVisible().withTimeout(2000);
|
await waitFor(element(by.id('register-view'))).toBeVisible().withTimeout(2000);
|
||||||
await expect(element(by.id('register-view'))).toBeVisible();
|
await expect(element(by.id('register-view'))).toBeVisible();
|
||||||
await tapBack('Welcome');
|
await tapBack();
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(async() => {
|
afterEach(async() => {
|
||||||
|
|
|
@ -49,18 +49,18 @@ describe('Login screen', () => {
|
||||||
await element(by.id('login-view-register')).tap();
|
await element(by.id('login-view-register')).tap();
|
||||||
await waitFor(element(by.id('register-view'))).toBeVisible().withTimeout(2000);
|
await waitFor(element(by.id('register-view'))).toBeVisible().withTimeout(2000);
|
||||||
await expect(element(by.id('register-view'))).toBeVisible();
|
await expect(element(by.id('register-view'))).toBeVisible();
|
||||||
await tapBack('Login');
|
await tapBack();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should navigate to forgot password', async() => {
|
it('should navigate to forgot password', async() => {
|
||||||
await element(by.id('login-view-forgot-password')).tap();
|
await element(by.id('login-view-forgot-password')).tap();
|
||||||
await waitFor(element(by.id('forgot-password-view'))).toBeVisible().withTimeout(2000);
|
await waitFor(element(by.id('forgot-password-view'))).toBeVisible().withTimeout(2000);
|
||||||
await expect(element(by.id('forgot-password-view'))).toBeVisible();
|
await expect(element(by.id('forgot-password-view'))).toBeVisible();
|
||||||
await tapBack('Login');
|
await tapBack();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should navigate to welcome', async() => {
|
it('should navigate to welcome', async() => {
|
||||||
await tapBack('Welcome');
|
await tapBack();
|
||||||
await waitFor(element(by.id('welcome-view'))).toBeVisible().withTimeout(2000);
|
await waitFor(element(by.id('welcome-view'))).toBeVisible().withTimeout(2000);
|
||||||
await expect(element(by.id('welcome-view'))).toBeVisible();
|
await expect(element(by.id('welcome-view'))).toBeVisible();
|
||||||
await element(by.id('welcome-view-login')).tap();
|
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();
|
await expect(element(by.id('rooms-list-view'))).toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have rooms list', async() => {
|
// it('should have rooms list', async() => {
|
||||||
await expect(element(by.id('rooms-list-view-list'))).toBeVisible();
|
// await expect(element(by.id('rooms-list-view-list'))).toBeVisible();
|
||||||
});
|
// });
|
||||||
|
|
||||||
it('should have room item', async() => {
|
it('should have room item', async() => {
|
||||||
await expect(element(by.id('rooms-list-view-item-general'))).toExist();
|
await expect(element(by.id('rooms-list-view-item-general'))).toExist();
|
||||||
|
@ -38,9 +38,12 @@ describe('Rooms list screen', () => {
|
||||||
|
|
||||||
describe('Usage', async() => {
|
describe('Usage', async() => {
|
||||||
it('should search room and navigate', async() => {
|
it('should search room and navigate', async() => {
|
||||||
await element(by.id('rooms-list-view-list')).swipe('down');
|
// await element(by.id('rooms-list-view-list')).swipe('down');
|
||||||
await waitFor(element(by.id('rooms-list-view-search'))).toBeVisible().withTimeout(2000);
|
// await waitFor(element(by.id('rooms-list-view-search'))).toBeVisible().withTimeout(2000);
|
||||||
await expect(element(by.id('rooms-list-view-search'))).toBeVisible();
|
// 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 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 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();
|
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 expect(element(by.id('room-view'))).toBeVisible();
|
||||||
await waitFor(element(by.text('rocket.cat'))).toBeVisible().withTimeout(60000);
|
await waitFor(element(by.text('rocket.cat'))).toBeVisible().withTimeout(60000);
|
||||||
await expect(element(by.text('rocket.cat'))).toBeVisible();
|
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 waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
|
||||||
await expect(element(by.id('rooms-list-view'))).toBeVisible();
|
await expect(element(by.id('rooms-list-view'))).toBeVisible();
|
||||||
await element(by.id('rooms-list-view-search')).replaceText('');
|
await element(by.id('rooms-list-view-search')).replaceText('');
|
||||||
|
|
|
@ -3,37 +3,70 @@ const {
|
||||||
} = require('detox');
|
} = require('detox');
|
||||||
const { takeScreenshot } = require('./helpers/screenshot');
|
const { takeScreenshot } = require('./helpers/screenshot');
|
||||||
const data = require('./data');
|
const data = require('./data');
|
||||||
const { tapBack } = require('./helpers/app');
|
const { tapBack, sleep } = require('./helpers/app');
|
||||||
|
|
||||||
describe('Create room screen', () => {
|
describe('Create room screen', () => {
|
||||||
before(async() => {
|
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 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() => {
|
describe('New Message', async() => {
|
||||||
it('should have select users screen', async() => {
|
describe('Render', async() => {
|
||||||
await expect(element(by.id('select-users-view'))).toBeVisible();
|
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() => {
|
describe('Usage', async() => {
|
||||||
await expect(element(by.id('select-users-view-search'))).toBeVisible();
|
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() => {
|
it('should search user and navigate', async() => {
|
||||||
takeScreenshot();
|
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() => {
|
describe('Select Users', 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);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should search users', async() => {
|
it('should search users', async() => {
|
||||||
await element(by.id('select-users-view-search')).replaceText('rocket.cat');
|
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);
|
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 element(by.id('selected-users-view-submit')).tap();
|
||||||
await waitFor(element(by.id('create-channel-view'))).toBeVisible().withTimeout(5000);
|
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-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() => {
|
describe('Create Channel', async() => {
|
||||||
await element(by.id('create-channel-name')).replaceText('general');
|
describe('Render', async() => {
|
||||||
await element(by.id('create-channel-submit')).tap();
|
it('should render all fields', async() => {
|
||||||
await waitFor(element(by.id('create-channel-error'))).toBeVisible().withTimeout(60000);
|
await expect(element(by.id('create-channel-name'))).toBeVisible();
|
||||||
await expect(element(by.id('create-channel-error'))).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() => {
|
describe('Usage', async() => {
|
||||||
await element(by.id('create-channel-name')).replaceText(`public${ data.random }`);
|
it('should get invalid room', async() => {
|
||||||
await element(by.id('create-channel-type')).tap();
|
await element(by.id('create-channel-name')).replaceText('general');
|
||||||
await element(by.id('create-channel-submit')).tap();
|
await element(by.id('create-channel-submit')).tap();
|
||||||
await waitFor(element(by.id('room-view'))).toBeVisible().withTimeout(60000);
|
await waitFor(element(by.text(`A channel with name 'general' exists`))).toBeVisible().withTimeout(60000);
|
||||||
await expect(element(by.id('room-view'))).toBeVisible();
|
await expect(element(by.text(`A channel with name 'general' exists`))).toBeVisible();
|
||||||
await waitFor(element(by.text(`public${ data.random }`))).toBeVisible().withTimeout(60000);
|
await element(by.text('OK')).tap();
|
||||||
await expect(element(by.text(`public${ data.random }`))).toBeVisible();
|
});
|
||||||
await tapBack('Messages');
|
|
||||||
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
|
it('should create public room', async() => {
|
||||||
await waitFor(element(by.id(`rooms-list-view-item-public${ data.random }`))).toBeVisible().withTimeout(60000);
|
await element(by.id('create-channel-name')).replaceText(`public${ data.random }`);
|
||||||
await expect(element(by.id(`rooms-list-view-item-public${ data.random }`))).toBeVisible();
|
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);
|
||||||
it('should create private room', async() => {
|
await expect(element(by.id('room-view'))).toBeVisible();
|
||||||
await element(by.id('rooms-list-view-create-channel')).tap();
|
await waitFor(element(by.text(`public${ data.random }`))).toBeVisible().withTimeout(60000);
|
||||||
await waitFor(element(by.id('select-users-view'))).toBeVisible().withTimeout(2000);
|
await expect(element(by.text(`public${ data.random }`))).toBeVisible();
|
||||||
await element(by.id('select-users-view-item-rocket.cat')).tap();
|
await tapBack(2);
|
||||||
await waitFor(element(by.id('selected-user-rocket.cat'))).toBeVisible().withTimeout(5000);
|
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
|
||||||
await element(by.id('selected-users-view-submit')).tap();
|
await waitFor(element(by.id(`rooms-list-view-item-public${ data.random }`))).toBeVisible().withTimeout(60000);
|
||||||
await waitFor(element(by.id('create-channel-view'))).toBeVisible().withTimeout(5000);
|
await expect(element(by.id(`rooms-list-view-item-public${ data.random }`))).toBeVisible();
|
||||||
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);
|
it('should create private room', async() => {
|
||||||
await expect(element(by.id('room-view'))).toBeVisible();
|
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
|
||||||
await waitFor(element(by.text(`private${ data.random }`))).toBeVisible().withTimeout(60000);
|
await device.reloadReactNative();
|
||||||
await expect(element(by.text(`private${ data.random }`))).toBeVisible();
|
await element(by.id('rooms-list-view-create-channel')).tap();
|
||||||
await tapBack('Messages');
|
await waitFor(element(by.id('new-message-view'))).toBeVisible().withTimeout(2000);
|
||||||
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
|
await element(by.id('new-message-view-create-channel')).tap();
|
||||||
await waitFor(element(by.id(`rooms-list-view-item-private${ data.random }`))).toBeVisible().withTimeout(60000);
|
await waitFor(element(by.id('select-users-view'))).toBeVisible().withTimeout(2000);
|
||||||
await expect(element(by.id(`rooms-list-view-item-private${ data.random }`))).toBeVisible();
|
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() => {
|
afterEach(async() => {
|
||||||
takeScreenshot();
|
takeScreenshot();
|
||||||
|
|
|
@ -74,7 +74,7 @@ describe('Room screen', () => {
|
||||||
describe('Usage', async() => {
|
describe('Usage', async() => {
|
||||||
describe('Header', async() => {
|
describe('Header', async() => {
|
||||||
it('should back to rooms list', 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 waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
|
||||||
await expect(element(by.id('rooms-list-view'))).toBeVisible();
|
await expect(element(by.id('rooms-list-view'))).toBeVisible();
|
||||||
await navigateToRoom();
|
await navigateToRoom();
|
||||||
|
@ -84,7 +84,7 @@ describe('Room screen', () => {
|
||||||
await element(by.id('room-view-header-actions')).tap();
|
await element(by.id('room-view-header-actions')).tap();
|
||||||
await waitFor(element(by.id('room-actions-view'))).toBeVisible().withTimeout(2000);
|
await waitFor(element(by.id('room-actions-view'))).toBeVisible().withTimeout(2000);
|
||||||
await expect(element(by.id('room-actions-view'))).toBeVisible();
|
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);
|
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -287,7 +287,8 @@ describe('Room screen', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
after(async() => {
|
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 waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
|
||||||
await expect(element(by.id('rooms-list-view'))).toBeVisible();
|
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);
|
await waitFor(element(by.id('room-actions-view'))).toBeVisible().withTimeout(5000);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function backToActions() {
|
async function backToActions(index = 0) {
|
||||||
await tapBack('Actions');
|
await tapBack(index);
|
||||||
await waitFor(element(by.id('rooms-actions-view'))).toBeVisible().withTimeout(2000);
|
await waitFor(element(by.id('room-actions-view'))).toBeVisible().withTimeout(2000);
|
||||||
|
await expect(element(by.id('room-actions-view'))).toBeVisible();
|
||||||
}
|
}
|
||||||
|
|
||||||
async function backToRoomsList(room) {
|
async function backToRoomsList() {
|
||||||
await tapBack(room);
|
await tapBack();
|
||||||
await waitFor(element(by.id('room-view'))).toBeVisible().withTimeout(2000);
|
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'))).toBeVisible().withTimeout(2000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,7 +99,7 @@ describe('Room actions screen', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
after(async() => {
|
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 element(by.id('room-actions-search')).tap();
|
||||||
await waitFor(element(by.id('search-messages-view'))).toExist().withTimeout(2000);
|
await waitFor(element(by.id('search-messages-view'))).toExist().withTimeout(2000);
|
||||||
await expect(element(by.id('search-message-view-input'))).toBeVisible();
|
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 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 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 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();
|
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 expect(element(by.text('You are the last owner. Please set new owner before leaving the room.'))).toBeVisible();
|
||||||
await takeScreenshot();
|
await takeScreenshot();
|
||||||
await element(by.text('OK')).tap();
|
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() => {
|
describe('Add User', async() => {
|
||||||
|
@ -304,7 +305,7 @@ describe('Room actions screen', () => {
|
||||||
await element(by.id('room-members-view-toggle-status')).tap();
|
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 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 expect(element(by.id(`room-members-view-item-${ data.alternateUser }`))).toBeVisible();
|
||||||
await backToActions();
|
await backToActions(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
after(async() => {
|
after(async() => {
|
||||||
|
@ -363,8 +364,8 @@ describe('Room actions screen', () => {
|
||||||
await expect(element(by.id('room-view'))).toBeVisible();
|
await expect(element(by.id('room-view'))).toBeVisible();
|
||||||
await waitFor(element(by.text(data.alternateUser))).toBeVisible().withTimeout(60000);
|
await waitFor(element(by.text(data.alternateUser))).toBeVisible().withTimeout(60000);
|
||||||
await expect(element(by.text(data.alternateUser))).toBeVisible();
|
await expect(element(by.text(data.alternateUser))).toBeVisible();
|
||||||
await tapBack('Messages');
|
await tapBack(2);
|
||||||
await waitFor(element(by.id('room-list-view'))).toBeVisible().withTimeout(2000);
|
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(async() => {
|
afterEach(async() => {
|
||||||
|
|
|
@ -158,7 +158,7 @@ describe('Room info screen', () => {
|
||||||
await expect(element(by.text('Settings succesfully changed!'))).toBeVisible();
|
await expect(element(by.text('Settings succesfully changed!'))).toBeVisible();
|
||||||
await waitFor(element(by.text('Settings succesfully changed!'))).toBeNotVisible().withTimeout(10000);
|
await waitFor(element(by.text('Settings succesfully changed!'))).toBeNotVisible().withTimeout(10000);
|
||||||
await expect(element(by.text('Settings succesfully changed!'))).toBeNotVisible();
|
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'))).toBeVisible().withTimeout(2000);
|
||||||
await waitFor(element(by.id('room-info-view-name'))).toHaveText(`${ room }new`).withTimeout(60000);
|
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`);
|
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 expect(element(by.text('Settings succesfully changed!'))).toBeVisible();
|
||||||
await waitFor(element(by.text('Settings succesfully changed!'))).toBeNotVisible().withTimeout(10000);
|
await waitFor(element(by.text('Settings succesfully changed!'))).toBeNotVisible().withTimeout(10000);
|
||||||
await expect(element(by.text('Settings succesfully changed!'))).toBeNotVisible();
|
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'))).toBeVisible().withTimeout(2000);
|
||||||
await waitFor(element(by.id('room-info-view-description'))).toHaveText('new description').withTimeout(60000);
|
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');
|
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 expect(element(by.text('Settings succesfully changed!'))).toBeVisible();
|
||||||
await waitFor(element(by.text('Settings succesfully changed!'))).toBeNotVisible().withTimeout(10000);
|
await waitFor(element(by.text('Settings succesfully changed!'))).toBeNotVisible().withTimeout(10000);
|
||||||
await expect(element(by.text('Settings succesfully changed!'))).toBeNotVisible();
|
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'))).toBeVisible().withTimeout(2000);
|
||||||
await waitFor(element(by.id('room-info-view-topic'))).toHaveText('new topic').withTimeout(60000);
|
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');
|
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 expect(element(by.text('Settings succesfully changed!'))).toBeVisible();
|
||||||
await waitFor(element(by.text('Settings succesfully changed!'))).toBeNotVisible().withTimeout(10000);
|
await waitFor(element(by.text('Settings succesfully changed!'))).toBeNotVisible().withTimeout(10000);
|
||||||
await expect(element(by.text('Settings succesfully changed!'))).toBeNotVisible();
|
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'))).toBeVisible().withTimeout(2000);
|
||||||
await waitFor(element(by.id('room-info-view-announcement'))).toHaveText('new announcement').withTimeout(60000);
|
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');
|
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() => {
|
it('should create broadcast room', async() => {
|
||||||
await element(by.id('rooms-list-view-create-channel')).tap();
|
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 waitFor(element(by.id('select-users-view'))).toBeVisible().withTimeout(2000);
|
||||||
await element(by.id(`select-users-view-item-${ data.alternateUser }`)).tap();
|
await element(by.id(`select-users-view-item-${ data.alternateUser }`)).tap();
|
||||||
await waitFor(element(by.id(`selected-user-${ data.alternateUser }`))).toBeVisible().withTimeout(5000);
|
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'))).toBeVisible().withTimeout(2000);
|
||||||
await waitFor(element(by.id('room-info-view-broadcast'))).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 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 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 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'))).toBeVisible().withTimeout(2000);
|
||||||
await waitFor(element(by.id(`rooms-list-view-item-broadcast${ data.random }`))).toBeVisible().withTimeout(60000);
|
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 }`))).toBeVisible();
|
await expect(element(by.id(`rooms-list-view-item-broadcast${ data.random }`))).toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should send message', async() => {
|
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() => {
|
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 waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
|
||||||
await expect(element(by.id('rooms-list-view'))).toBeVisible();
|
await expect(element(by.id('rooms-list-view'))).toBeVisible();
|
||||||
await logout();
|
await logout();
|
||||||
|
@ -61,7 +63,8 @@ describe('Broadcast room', () => {
|
||||||
await element(by.id('login-view-submit')).tap();
|
await element(by.id('login-view-submit')).tap();
|
||||||
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(10000);
|
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(10000);
|
||||||
// await device.reloadReactNative(); // remove after fix logout
|
// 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 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 expect(element(by.id(`rooms-list-view-item-broadcast${ data.random }`))).toBeVisible();
|
||||||
await element(by.id(`rooms-list-view-item-broadcast${ data.random }`)).tap();
|
await element(by.id(`rooms-list-view-item-broadcast${ data.random }`)).tap();
|
||||||
|
@ -107,7 +110,7 @@ describe('Broadcast room', () => {
|
||||||
|
|
||||||
after(async() => {
|
after(async() => {
|
||||||
// log back as main test user and left screen on RoomsListView
|
// 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 waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
|
||||||
await logout();
|
await logout();
|
||||||
await navigateToLogin();
|
await navigateToLogin();
|
||||||
|
|
|
@ -36,12 +36,8 @@ async function logout() {
|
||||||
await expect(element(by.id('onboarding-view'))).toBeVisible();
|
await expect(element(by.id('onboarding-view'))).toBeVisible();
|
||||||
}
|
}
|
||||||
|
|
||||||
async function tapBack(label) {
|
async function tapBack(index) {
|
||||||
try {
|
await element(by.type('_UIModernBarButton')).atIndex(index || 0).tap();
|
||||||
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 sleep(ms) {
|
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": {
|
"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",
|
"from": "git+https://github.com/RocketChat/react-native-navigation.git",
|
||||||
"requires": {
|
"requires": {
|
||||||
"lodash": "4.x.x"
|
"lodash": "4.x.x"
|
||||||
|
|