diff --git a/.circleci/config.yml b/.circleci/config.yml index 6418dd91d..d413ed527 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -71,12 +71,12 @@ jobs: - run: name: Build command: | - detox build + detox build --configuration ios.sim.release - run: name: Test command: | - detox test + detox test --configuration ios.sim.release --cleanup - store_artifacts: path: /tmp/screenshots diff --git a/__tests__/__snapshots__/RoomItem.js.snap b/__tests__/__snapshots__/RoomItem.js.snap index 33aec8e75..c2fcbe4b7 100644 --- a/__tests__/__snapshots__/RoomItem.js.snap +++ b/__tests__/__snapshots__/RoomItem.js.snap @@ -102,6 +102,7 @@ exports[`render channel 1`] = ` "fontStyle": "normal", "fontWeight": "normal", }, + Object {}, ] } > @@ -259,6 +260,7 @@ exports[`render no icon 1`] = ` "fontStyle": "normal", "fontWeight": "normal", }, + Object {}, ] } > @@ -416,6 +418,7 @@ exports[`render private group 1`] = ` "fontStyle": "normal", "fontWeight": "normal", }, + Object {}, ] } > @@ -636,6 +639,7 @@ exports[`render unread +999 1`] = ` "fontStyle": "normal", "fontWeight": "normal", }, + Object {}, ] } > @@ -875,6 +879,7 @@ exports[`render unread 1`] = ` "fontStyle": "normal", "fontWeight": "normal", }, + Object {}, ] } > @@ -1114,6 +1119,7 @@ exports[`renders correctly 1`] = ` "fontStyle": "normal", "fontWeight": "normal", }, + Object {}, ] } > diff --git a/__tests__/__snapshots__/Storyshots.test.js.snap b/__tests__/__snapshots__/Storyshots.test.js.snap index af7b22ae6..43564cf54 100644 --- a/__tests__/__snapshots__/Storyshots.test.js.snap +++ b/__tests__/__snapshots__/Storyshots.test.js.snap @@ -460,6 +460,7 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = ` "fontStyle": "normal", "fontWeight": "normal", }, + Object {}, ] } > @@ -674,6 +675,7 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = ` "fontStyle": "normal", "fontWeight": "normal", }, + Object {}, ] } > @@ -892,6 +894,7 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = ` "fontStyle": "normal", "fontWeight": "normal", }, + Object {}, ] } > @@ -1126,6 +1129,7 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = ` "fontStyle": "normal", "fontWeight": "normal", }, + Object {}, ] } > @@ -1364,6 +1368,7 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = ` "fontStyle": "normal", "fontWeight": "normal", }, + Object {}, ] } > @@ -1598,6 +1603,7 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = ` "fontStyle": "normal", "fontWeight": "normal", }, + Object {}, ] } > @@ -1832,6 +1838,7 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = ` "fontStyle": "normal", "fontWeight": "normal", }, + Object {}, ] } > @@ -2066,6 +2073,7 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = ` "fontStyle": "normal", "fontWeight": "normal", }, + Object {}, ] } > @@ -2300,6 +2308,7 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = ` "fontStyle": "normal", "fontWeight": "normal", }, + Object {}, ] } > @@ -2514,6 +2523,7 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = ` "fontStyle": "normal", "fontWeight": "normal", }, + Object {}, ] } > @@ -2728,6 +2738,7 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = ` "fontStyle": "normal", "fontWeight": "normal", }, + Object {}, ] } > diff --git a/app/Icons.js b/app/Icons.js index d9f947972..b5329d741 100644 --- a/app/Icons.js +++ b/app/Icons.js @@ -10,9 +10,10 @@ const icons = { [`${ prefix }-menu`]: [30, Ionicons, 'menu'], [`${ prefix }-star`]: [30, Ionicons, 'star'], [`${ prefix }-star-outline`]: [30, Ionicons, 'starOutline'], - [isIOS ? 'ios-create-outline' : 'md-create']: [30, Ionicons, 'create'], + [isIOS ? 'ios-create' : 'md-create']: [30, Ionicons, 'create'], [`${ prefix }-more`]: [30, Ionicons, 'more'], - [`${ prefix }-add`]: [30, Ionicons, 'add'] + [`${ prefix }-add`]: [30, Ionicons, 'add'], + [`${ prefix }-close`]: [30, Ionicons, 'close'] }; const iconsMap = {}; diff --git a/app/Navigation.js b/app/Navigation.js index f192d2a80..e7bb38bed 100644 --- a/app/Navigation.js +++ b/app/Navigation.js @@ -8,6 +8,7 @@ class NavigationActionsClass { popToRoot = params => this.navigator && this.navigator.popToRoot(params); resetTo = params => this.navigator && this.navigator.resetTo(params); toggleDrawer = params => this.navigator && this.navigator.toggleDrawer(params); + dismissModal = params => this.navigator && this.navigator.dismissModal(params); } export const NavigationActions = new NavigationActionsClass(); diff --git a/app/actions/actionsTypes.js b/app/actions/actionsTypes.js index f65142f66..eb56da9e5 100644 --- a/app/actions/actionsTypes.js +++ b/app/actions/actionsTypes.js @@ -76,9 +76,7 @@ export const NAVIGATION = createRequestTypes('NAVIGATION', ['SET']); export const SERVER = createRequestTypes('SERVER', [ ...defaultTypes, 'SELECT_SUCCESS', - 'SELECT_REQUEST', - 'CHANGED', - 'ADD' + 'SELECT_REQUEST' ]); export const METEOR = createRequestTypes('METEOR_CONNECT', [...defaultTypes, 'DISCONNECT', 'DISCONNECT_BY_USER']); export const LOGOUT = 'LOGOUT'; // logout is always success diff --git a/app/actions/server.js b/app/actions/server.js index 4bca6c236..51d1bafff 100644 --- a/app/actions/server.js +++ b/app/actions/server.js @@ -21,14 +21,6 @@ export function serverRequest(server) { }; } -export function addServer(server) { - return { - type: SERVER.ADD, - server - }; -} - - export function serverSuccess() { return { type: SERVER.SUCCESS @@ -41,11 +33,3 @@ export function serverFailure(err) { err }; } - - -export function changedServer(server) { - return { - type: SERVER.CHANGED, - server - }; -} diff --git a/app/containers/Button/index.js b/app/containers/Button/index.js index 2709aae9f..3bb13137b 100644 --- a/app/containers/Button/index.js +++ b/app/containers/Button/index.js @@ -1,48 +1,53 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { StyleSheet, View, Text, Platform } from 'react-native'; +import { StyleSheet, View, Text, Platform, ActivityIndicator } from 'react-native'; import { COLOR_BUTTON_PRIMARY, COLOR_TEXT } from '../../constants/colors'; import Touch from '../../utils/touch'; +import { scale, moderateScale, verticalScale } from '../../utils/scaling'; const colors = { - backgroundPrimary: COLOR_BUTTON_PRIMARY, - backgroundSecondary: 'white', + background_primary: COLOR_BUTTON_PRIMARY, + background_secondary: 'white', - textColorPrimary: 'white', - textColorSecondary: COLOR_TEXT + text_color_primary: 'white', + text_color_secondary: COLOR_TEXT }; /* eslint-disable react-native/no-unused-styles */ const styles = StyleSheet.create({ container: { - paddingHorizontal: 15, - paddingVertical: 10 + paddingHorizontal: scale(15), + justifyContent: 'center', + height: scale(48) }, text: { + fontSize: moderateScale(18), + height: verticalScale(20), + lineHeight: verticalScale(20), textAlign: 'center', - fontWeight: '700' + fontWeight: '500' }, background_primary: { - backgroundColor: colors.backgroundPrimary + backgroundColor: colors.background_primary }, background_secondary: { - backgroundColor: colors.backgroundSecondary + backgroundColor: colors.background_secondary }, text_color_primary: { - color: colors.textColorPrimary + color: colors.text_color_primary }, text_color_secondary: { - color: colors.textColorSecondary + color: colors.text_color_secondary }, margin: { - marginBottom: 10 + marginBottom: verticalScale(10) }, disabled: { opacity: 0.5 }, border: { - borderRadius: 2 + borderRadius: scale(2) } }); @@ -53,26 +58,28 @@ export default class Button extends React.PureComponent { onPress: PropTypes.func, disabled: PropTypes.bool, margin: PropTypes.any, - backgroundColor: PropTypes.string + backgroundColor: PropTypes.string, + loading: PropTypes.bool } static defaultProps = { title: 'Press me!', type: 'primary', onPress: () => alert('It works!'), - disabled: false + disabled: false, + loading: false } render() { const { - title, type, onPress, disabled, margin, backgroundColor, ...otherProps + title, type, onPress, disabled, margin, backgroundColor, loading, ...otherProps } = this.props; return ( - {title} + { + loading ? + : + {title} + } ); diff --git a/app/containers/Sidebar.js b/app/containers/Sidebar.js index 6a79a16d2..0cbf8aa3f 100644 --- a/app/containers/Sidebar.js +++ b/app/containers/Sidebar.js @@ -1,12 +1,13 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; -import { ScrollView, Text, View, StyleSheet, FlatList, LayoutAnimation, SafeAreaView } from 'react-native'; +import { ScrollView, Text, View, StyleSheet, FlatList, LayoutAnimation, SafeAreaView, AsyncStorage } from 'react-native'; import { connect } from 'react-redux'; import FastImage from 'react-native-fast-image'; import Icon from 'react-native-vector-icons/MaterialIcons'; import database from '../lib/realm'; import { selectServerRequest } from '../actions/server'; +import { appStart } from '../actions'; import { logout } from '../actions/login'; import Avatar from '../containers/Avatar'; import Status from '../containers/status'; @@ -16,6 +17,7 @@ import RocketChat from '../lib/rocketchat'; import log from '../utils/log'; import I18n from '../i18n'; import { NavigationActions } from '../Navigation'; +import scrollPersistTaps from '../utils/scrollPersistTaps'; const styles = StyleSheet.create({ container: { @@ -86,7 +88,8 @@ const keyExtractor = item => item.id; } }), dispatch => ({ selectServerRequest: server => dispatch(selectServerRequest(server)), - logout: () => dispatch(logout()) + logout: () => dispatch(logout()), + appStart: () => dispatch(appStart('outside')) })) export default class Sidebar extends Component { static propTypes = { @@ -94,7 +97,8 @@ export default class Sidebar extends Component { server: PropTypes.string.isRequired, selectServerRequest: PropTypes.func.isRequired, user: PropTypes.object, - logout: PropTypes.func.isRequired + logout: PropTypes.func.isRequired, + appStart: PropTypes.func } constructor(props) { @@ -206,7 +210,7 @@ export default class Sidebar extends Component { try { RocketChat.setUserPresenceDefaultStatus(item.id); } catch (e) { - log('onPressModalButton', e); + log('setUserPresenceDefaultStatus', e); } } } @@ -226,6 +230,21 @@ export default class Sidebar extends Component { this.toggleServers(); if (this.props.server !== item.id) { this.props.selectServerRequest(item.id); + const token = await AsyncStorage.getItem(`${ RocketChat.TOKEN_KEY }-${ item.id }`); + if (!token) { + this.props.appStart(); + setTimeout(() => { + NavigationActions.push({ + screen: 'NewServerView', + passProps: { + server: item.id + }, + navigatorStyle: { + navBarHidden: true + } + }); + }, 1000); + } } }, testID: `sidebar-${ item.id }` @@ -289,9 +308,12 @@ export default class Sidebar extends Component { onPress: () => { this.closeDrawer(); this.toggleServers(); - NavigationActions.push({ + this.props.navigator.showModal({ screen: 'NewServerView', - title: I18n.t('Add_Server') + title: I18n.t('Add_Server'), + passProps: { + previousServer: this.props.server + } }); }, testID: 'sidebar-add-server' @@ -305,8 +327,8 @@ export default class Sidebar extends Component { return null; } return ( - - + + this.toggleServers()} underlayColor='rgba(255, 255, 255, 0.5)' @@ -338,8 +360,8 @@ export default class Sidebar extends Component { {!this.state.showServers ? this.renderNavigation() : null} {this.state.showServers ? this.renderServers() : null} - - + + ); } } diff --git a/app/containers/TextInput.js b/app/containers/TextInput.js index fb8504ad8..68178c178 100644 --- a/app/containers/TextInput.js +++ b/app/containers/TextInput.js @@ -1,7 +1,6 @@ import React from 'react'; import { View, StyleSheet, Text, TextInput, ViewPropTypes, Platform } from 'react-native'; import PropTypes from 'prop-types'; - import Icon from 'react-native-vector-icons/MaterialCommunityIcons'; import sharedStyles from '../views/Styles'; @@ -21,13 +20,11 @@ const styles = StyleSheet.create({ fontSize: 14, paddingTop: 12, paddingBottom: 12, - // paddingTop: 5, - // paddingBottom: 5, paddingHorizontal: 10, - borderWidth: 2, - borderRadius: 4, + borderWidth: 1.5, + borderRadius: 2, backgroundColor: 'white', - borderColor: 'rgba(0,0,0,.15)', + borderColor: '#E7EBF2', color: 'black' }, labelError: { diff --git a/app/containers/message/Markdown.js b/app/containers/message/Markdown.js index 67454c115..29d7e4f79 100644 --- a/app/containers/message/Markdown.js +++ b/app/containers/message/Markdown.js @@ -65,7 +65,8 @@ export default class Markdown extends React.Component { } return null; }, - blocklink: () => {}, + hardbreak: () => null, + blocklink: () => null, image: node => ( // TODO: should use Image component diff --git a/app/i18n/locales/en.js b/app/i18n/locales/en.js index ef8175340..cdb64afec 100644 --- a/app/i18n/locales/en.js +++ b/app/i18n/locales/en.js @@ -116,6 +116,7 @@ export default { Code: 'Code', Colaborative: 'Colaborative', Connect: 'Connect', + Connect_to_a_server: 'Connect to a server', Connected_to: 'Connected to', Connecting: 'Connecting', Copied_to_clipboard: 'Copied to clipboard!', @@ -123,6 +124,7 @@ export default { Copy_Permalink: 'Copy Permalink', Create_account: 'Create account', Create_Channel: 'Create Channel', + Create_a_new_workspace: 'Create a new workspace', Create: 'Create', Delete_Room_Warning: 'Deleting a room will delete all messages posted within the room. This cannot be undone.', delete: 'delete', @@ -153,6 +155,7 @@ export default { is_a_valid_RocketChat_instance: 'is a valid Rocket.Chat instance', is_not_a_valid_RocketChat_instance: 'is not a valid Rocket.Chat instance', is_typing: 'is typing', + Join_the_community: 'Join the community', Just_invited_people_can_access_this_channel: 'Just invited people can access this channel', Language: 'Language', last_message: 'last message', @@ -197,9 +200,11 @@ export default { Notify_active_in_this_room: 'Notify active users in this room', Notify_all_in_this_room: 'Notify all in this room', Offline: 'Offline', + Oops: 'Oops!', Online: 'Online', Only_authorized_users_can_write_new_messages: 'Only authorized users can write new messages', Open_emoji_selector: 'Open emoji selector', + Open_Source_Communication: 'Open Source Communication', Or_continue_using_social_accounts: 'Or continue using social accounts', Password: 'Password', Permalink_copied_to_clipboard: 'Permalink copied to clipboard!', @@ -274,6 +279,7 @@ export default { tap_to_change_status: 'tap to change status', Tap_to_view_servers_list: 'Tap to view servers list', Terms_of_Service: ' Terms of Service ', + The_URL_is_invalid: 'The URL you entered is invalid. Check it and try again, please!', There_was_an_error_while_action: 'There was an error while {{action}}!', This_room_is_blocked: 'This room is blocked', This_room_is_read_only: 'This room is read only', @@ -307,6 +313,7 @@ export default { Welcome: 'Welcome', Welcome_title_pt_1: 'Prepare to take off with', Welcome_title_pt_2: 'the ultimate chat platform', + Welcome_to_RocketChat: 'Welcome to Rocket.Chat', Yes_action_it: 'Yes, {{action}} it!', Yesterday: 'Yesterday', You_are_in_preview_mode: 'You are in preview mode', diff --git a/app/index.js b/app/index.js index d0ceb4ef9..8427d44ce 100644 --- a/app/index.js +++ b/app/index.js @@ -4,7 +4,6 @@ import { Navigation } from 'react-native-navigation'; import store from './lib/createStore'; import { appInit } from './actions'; -import database from './lib/realm'; import { iconsLoaded } from './Icons'; import { registerScreens } from './views'; import { deepLinkingOpen } from './actions/deepLinking'; @@ -27,21 +26,21 @@ const startLogged = () => { }); }; -const startNotLogged = (route) => { +const startNotLogged = () => { Navigation.startSingleScreenApp({ screen: { - screen: route, - title: route === 'NewServerView' ? I18n.t('New_Server') : I18n.t('Servers') + screen: 'OnboardingView', + navigatorStyle: { + navBarHidden: true + } }, - animationType: 'fade' + animationType: 'fade', + appStyle: { + orientation: 'portrait' + } }); }; -const hasServers = () => { - const db = database.databases.serversDB.objects('servers'); - return db.length > 0; -}; - const handleOpenURL = ({ url }) => { if (url) { url = url.replace(/rocketchat:\/\/|https:\/\/go.rocket.chat\//, ''); @@ -77,11 +76,7 @@ export default class App extends Component { if (this.currentRoot !== root) { this.currentRoot = root; if (root === 'outside') { - if (hasServers()) { - startNotLogged('ListServerView'); - } else { - startNotLogged('NewServerView'); - } + startNotLogged(); } else if (root === 'inside') { startLogged(); } diff --git a/app/lib/methods/helpers/mergeSubscriptionsRooms.js b/app/lib/methods/helpers/mergeSubscriptionsRooms.js index a95d59b95..05a866f6e 100644 --- a/app/lib/methods/helpers/mergeSubscriptionsRooms.js +++ b/app/lib/methods/helpers/mergeSubscriptionsRooms.js @@ -2,6 +2,9 @@ import normalizeMessage from './normalizeMessage'; // TODO: delete and update export const merge = (subscription, room) => { + if (!subscription) { + return; + } if (room) { if (room.rid) { subscription.rid = room.rid; diff --git a/app/reducers/server.js b/app/reducers/server.js index 6b9d8c29e..db6d59119 100644 --- a/app/reducers/server.js +++ b/app/reducers/server.js @@ -3,11 +3,10 @@ import { SERVER } from '../actions/actionsTypes'; const initialState = { connecting: false, connected: false, - errorMessage: '', failure: false, server: '', - adding: false, - loading: true + loading: true, + adding: true }; @@ -17,14 +16,8 @@ export default function server(state = initialState, action) { return { ...state, connecting: true, - failure: false - }; - case SERVER.SUCCESS: - return { - ...state, - connecting: false, - connected: true, - failure: false + failure: false, + adding: true }; case SERVER.FAILURE: return { @@ -32,24 +25,22 @@ export default function server(state = initialState, action) { connecting: false, connected: false, failure: true, - errorMessage: action.err - }; - case SERVER.ADD: - return { - ...state, - adding: true + adding: false }; case SERVER.SELECT_REQUEST: return { ...state, server: action.server, + connecting: true, + connected: false, loading: true }; case SERVER.SELECT_SUCCESS: return { ...state, server: action.server, - adding: false, + connecting: false, + connected: true, loading: false }; default: diff --git a/app/sagas/createChannel.js b/app/sagas/createChannel.js index f9b285616..9f64e3b40 100644 --- a/app/sagas/createChannel.js +++ b/app/sagas/createChannel.js @@ -12,7 +12,7 @@ const create = function* create(data) { const handleRequest = function* handleRequest({ data }) { try { - yield delay(1000); + // yield delay(1000); const auth = yield select(state => state.login.isAuthenticated); if (!auth) { yield take(LOGIN.SUCCESS); diff --git a/app/sagas/deepLinking.js b/app/sagas/deepLinking.js index 11bbbd35b..ce21d94b4 100644 --- a/app/sagas/deepLinking.js +++ b/app/sagas/deepLinking.js @@ -3,7 +3,7 @@ import { takeLatest, take, select, put } from 'redux-saga/effects'; import * as types from '../actions/actionsTypes'; import { appStart } from '../actions'; -import { selectServerRequest, addServer } from '../actions/server'; +import { selectServerRequest } from '../actions/server'; import database from '../lib/realm'; import RocketChat from '../lib/rocketchat'; import { NavigationActions } from '../Navigation'; @@ -73,7 +73,7 @@ const handleOpen = function* handleOpen({ params }) { yield navigate({ params, sameServer: false }); } } else { - yield put(addServer(host)); + yield put(selectServerRequest(host)); } } }; diff --git a/app/sagas/login.js b/app/sagas/login.js index 25ce45c52..cf7732a19 100644 --- a/app/sagas/login.js +++ b/app/sagas/login.js @@ -23,6 +23,7 @@ import { import RocketChat from '../lib/rocketchat'; import log from '../utils/log'; import I18n from '../i18n'; +import { NavigationActions } from '../Navigation'; const getUser = state => state.login.user; const getServer = state => state.server.server; @@ -44,6 +45,7 @@ const handleLoginSuccess = function* handleLoginSuccess() { yield put(registerIncomplete()); } else { yield delay(300); + NavigationActions.dismissModal(); yield put(appStart('inside')); } } catch (e) { @@ -103,7 +105,10 @@ const handleLogout = function* handleLogout() { }; const handleRegisterIncomplete = function* handleRegisterIncomplete() { - yield put(appStart('outside')); + const server = yield select(state => state.server); + if (!server.adding) { + yield put(appStart('outside')); + } }; const handleForgotPasswordRequest = function* handleForgotPasswordRequest({ email }) { diff --git a/app/sagas/selectServer.js b/app/sagas/selectServer.js index ae30f4e9e..9a1e4f248 100644 --- a/app/sagas/selectServer.js +++ b/app/sagas/selectServer.js @@ -1,17 +1,15 @@ import { put, call, takeLatest } from 'redux-saga/effects'; -import { delay } from 'redux-saga'; import { AsyncStorage } from 'react-native'; import { NavigationActions } from '../Navigation'; import { SERVER } from '../actions/actionsTypes'; import * as actions from '../actions'; import { connectRequest } from '../actions/connect'; -import { serverSuccess, serverFailure, selectServerRequest, selectServerSuccess } from '../actions/server'; +import { serverFailure, selectServerRequest, selectServerSuccess } from '../actions/server'; import { setRoles } from '../actions/roles'; import RocketChat from '../lib/rocketchat'; import database from '../lib/realm'; import log from '../utils/log'; -import I18n from '../i18n'; const validate = function* validate(server) { return yield RocketChat.testServer(server); @@ -24,8 +22,6 @@ const handleSelectServer = function* handleSelectServer({ server }) { const token = yield AsyncStorage.getItem(`${ RocketChat.TOKEN_KEY }-${ server }`); if (token) { yield put(actions.appStart('inside')); - } else { - yield put(actions.appStart('outside')); } const settings = database.objects('settings'); @@ -45,33 +41,22 @@ const handleSelectServer = function* handleSelectServer({ server }) { } }; -const validateServer = function* validateServer({ server }) { +const handleServerRequest = function* handleServerRequest({ server }) { try { - yield delay(1000); yield call(validate, server); - yield put(serverSuccess()); - } catch (e) { - console.warn('validateServer', e); - yield put(serverFailure(e)); - } -}; - -const addServer = function* addServer({ server }) { - try { - yield put(actions.appStart('outside')); - yield call(NavigationActions.resetTo, { screen: 'ListServerView', title: I18n.t('Servers') }); + yield call(NavigationActions.push, { screen: 'LoginSignupView', title: server }); database.databases.serversDB.write(() => { database.databases.serversDB.create('servers', { id: server, current: false }, true); }); yield put(selectServerRequest(server)); } catch (e) { - log('addServer', e); + yield put(serverFailure()); + log('handleServerRequest', e); } }; const root = function* root() { - yield takeLatest(SERVER.REQUEST, validateServer); yield takeLatest(SERVER.SELECT_REQUEST, handleSelectServer); - yield takeLatest(SERVER.ADD, addServer); + yield takeLatest(SERVER.REQUEST, handleServerRequest); }; export default root; diff --git a/app/static/images/connectServer.png b/app/static/images/connectServer.png new file mode 100644 index 000000000..e5e2c021f Binary files /dev/null and b/app/static/images/connectServer.png differ diff --git a/app/static/images/connectServer@2x.png b/app/static/images/connectServer@2x.png new file mode 100644 index 000000000..5cd548403 Binary files /dev/null and b/app/static/images/connectServer@2x.png differ diff --git a/app/static/images/connectServer@3x.png b/app/static/images/connectServer@3x.png new file mode 100644 index 000000000..a75cf1fa7 Binary files /dev/null and b/app/static/images/connectServer@3x.png differ diff --git a/app/static/images/disclosureIndicator.png b/app/static/images/disclosureIndicator.png new file mode 100644 index 000000000..ad75c1fbe Binary files /dev/null and b/app/static/images/disclosureIndicator.png differ diff --git a/app/static/images/disclosureIndicator@2x.png b/app/static/images/disclosureIndicator@2x.png new file mode 100644 index 000000000..b3e963102 Binary files /dev/null and b/app/static/images/disclosureIndicator@2x.png differ diff --git a/app/static/images/disclosureIndicator@3x.png b/app/static/images/disclosureIndicator@3x.png new file mode 100644 index 000000000..788e682e8 Binary files /dev/null and b/app/static/images/disclosureIndicator@3x.png differ diff --git a/app/static/images/logoSmall.png b/app/static/images/logoSmall.png new file mode 100644 index 000000000..75d82a00d Binary files /dev/null and b/app/static/images/logoSmall.png differ diff --git a/app/static/images/logoSmall@2x.png b/app/static/images/logoSmall@2x.png new file mode 100644 index 000000000..a3e70aa1f Binary files /dev/null and b/app/static/images/logoSmall@2x.png differ diff --git a/app/static/images/logoSmall@3x.png b/app/static/images/logoSmall@3x.png new file mode 100644 index 000000000..0eb81e2e2 Binary files /dev/null and b/app/static/images/logoSmall@3x.png differ diff --git a/app/static/images/logo_with_text.png b/app/static/images/logo_with_text.png deleted file mode 100644 index 623349a06..000000000 Binary files a/app/static/images/logo_with_text.png and /dev/null differ diff --git a/app/static/images/navicon_add@2x.png b/app/static/images/navicon_add@2x.png deleted file mode 100644 index 4df23afcc..000000000 Binary files a/app/static/images/navicon_add@2x.png and /dev/null differ diff --git a/app/static/images/navicon_menu@2x.png b/app/static/images/navicon_menu@2x.png deleted file mode 100644 index 12c54031f..000000000 Binary files a/app/static/images/navicon_menu@2x.png and /dev/null differ diff --git a/app/static/images/onboarding.png b/app/static/images/onboarding.png new file mode 100644 index 000000000..c3b3f90fb Binary files /dev/null and b/app/static/images/onboarding.png differ diff --git a/app/static/images/onboarding@2x.png b/app/static/images/onboarding@2x.png new file mode 100644 index 000000000..f0b2bc754 Binary files /dev/null and b/app/static/images/onboarding@2x.png differ diff --git a/app/static/images/onboarding@3x.png b/app/static/images/onboarding@3x.png new file mode 100644 index 000000000..c5fda3c19 Binary files /dev/null and b/app/static/images/onboarding@3x.png differ diff --git a/app/static/images/planet.png b/app/static/images/planet.png deleted file mode 100644 index 29989ae75..000000000 Binary files a/app/static/images/planet.png and /dev/null differ diff --git a/app/static/images/plusWhite.png b/app/static/images/plusWhite.png new file mode 100644 index 000000000..4cceffccc Binary files /dev/null and b/app/static/images/plusWhite.png differ diff --git a/app/static/images/plusWhite@2x.png b/app/static/images/plusWhite@2x.png new file mode 100644 index 000000000..69276aa00 Binary files /dev/null and b/app/static/images/plusWhite@2x.png differ diff --git a/app/static/images/plusWhite@3x.png b/app/static/images/plusWhite@3x.png new file mode 100644 index 000000000..5a9c0ceee Binary files /dev/null and b/app/static/images/plusWhite@3x.png differ diff --git a/app/static/images/server.png b/app/static/images/server.png new file mode 100644 index 000000000..68d0a3a91 Binary files /dev/null and b/app/static/images/server.png differ diff --git a/app/static/images/server@2x.png b/app/static/images/server@2x.png new file mode 100644 index 000000000..faa77e0bc Binary files /dev/null and b/app/static/images/server@2x.png differ diff --git a/app/static/images/server@3x.png b/app/static/images/server@3x.png new file mode 100644 index 000000000..402786c78 Binary files /dev/null and b/app/static/images/server@3x.png differ diff --git a/app/utils/openLink.android.js b/app/utils/openLink/index.android.js similarity index 53% rename from app/utils/openLink.android.js rename to app/utils/openLink/index.android.js index 59ab9fba2..804318476 100644 --- a/app/utils/openLink.android.js +++ b/app/utils/openLink/index.android.js @@ -1,4 +1,4 @@ -import CustomTabsAndroid from '../nativeModules/CustomTabsAndroid'; +import CustomTabsAndroid from '../../nativeModules/CustomTabsAndroid'; const openLink = url => CustomTabsAndroid.openURL(url); diff --git a/app/utils/openLink.ios.js b/app/utils/openLink/index.ios.js similarity index 100% rename from app/utils/openLink.ios.js rename to app/utils/openLink/index.ios.js diff --git a/app/utils/scaling.js b/app/utils/scaling.js new file mode 100644 index 000000000..17fc1b93e --- /dev/null +++ b/app/utils/scaling.js @@ -0,0 +1,12 @@ +import { Dimensions } from 'react-native'; + +const { width, height } = Dimensions.get('window'); + +const guidelineBaseWidth = 375; +const guidelineBaseHeight = 667; + +const scale = size => (width / guidelineBaseWidth) * size; +const verticalScale = size => (height / guidelineBaseHeight) * size; +const moderateScale = (size, factor = 0.5) => size + ((scale(size) - size) * factor); + +export { scale, verticalScale, moderateScale }; diff --git a/app/views/ListServerView.js b/app/views/ListServerView.js deleted file mode 100644 index 072e4e372..000000000 --- a/app/views/ListServerView.js +++ /dev/null @@ -1,205 +0,0 @@ -import React from 'react'; -import Icon from 'react-native-vector-icons/Ionicons'; -import PropTypes from 'prop-types'; -import { View, Text, SectionList, StyleSheet, SafeAreaView } from 'react-native'; -import { connect } from 'react-redux'; - -import LoggedView from './View'; -import { selectServerRequest } from '../actions/server'; -import database from '../lib/realm'; -import Fade from '../animations/fade'; -import Touch from '../utils/touch'; -import I18n from '../i18n'; -import { iconsMap } from '../Icons'; - -const styles = StyleSheet.create({ - container: { - flex: 1, - backgroundColor: '#fff' - }, - separator: { - height: 1, - backgroundColor: '#eee' - }, - headerStyle: { - backgroundColor: '#eee', - lineHeight: 24, - paddingLeft: 14, - color: '#888' - }, - serverItem: { - flexDirection: 'row', - alignItems: 'center', - backgroundColor: '#fff', - padding: 14 - }, - listItem: { - color: '#666', - flexGrow: 1, - lineHeight: 30 - }, - serverChecked: { - flexGrow: 0 - } -}); - -@connect(state => ({ - server: state.server.server, - login: state.login, - connected: state.meteor.connected -}), dispatch => ({ - selectServerRequest: server => dispatch(selectServerRequest(server)) -})) -/** @extends React.Component */ -export default class ListServerView extends LoggedView { - static propTypes = { - navigator: PropTypes.object, - login: PropTypes.object.isRequired, - selectServerRequest: PropTypes.func.isRequired, - server: PropTypes.string - } - - constructor(props) { - super('ListServerView', props); - this.focused = true; - this.state = { - sections: [] - }; - this.data = database.databases.serversDB.objects('servers'); - this.data.addListener(this.updateState); - props.navigator.setOnNavigatorEvent(this.onNavigatorEvent.bind(this)); - } - - async componentWillMount() { - this.props.navigator.setButtons({ - rightButtons: [{ - id: 'addServer', - icon: iconsMap.add - }] - }); - } - - componentDidMount() { - this.updateState(); - this.jumpToSelectedServer(); - } - - componentWillReceiveProps(nextProps) { - if (this.props.server !== nextProps.server && nextProps.server && !this.props.login.isRegistering) { - this.timeout = setTimeout(() => { - this.openLogin(nextProps.server); - }, 1000); - } - } - - componentWillUnmount() { - this.data.removeAllListeners(); - if (this.timeout) { - clearTimeout(this.timeout); - } - } - - onNavigatorEvent(event) { - if (event.type === 'NavBarButtonPress') { - if (event.id === 'addServer') { - this.props.navigator.push({ - screen: 'NewServerView', - title: I18n.t('New_Server') - }); - } - } else if (event.type === 'ScreenChangedEvent') { - this.focused = event.id === 'didAppear' || event.id === 'onActivityResumed'; - } - } - - onPressItem = (item) => { - this.selectAndNavigateTo(item.id); - } - - getState = () => { - const sections = [{ - title: I18n.t('My_servers'), - data: this.data - }]; - - return { - ...this.state, - sections - }; - }; - - openLogin = (server) => { - if (this.focused) { - this.props.navigator.push({ - screen: 'LoginSignupView', - title: server - }); - } - } - - selectAndNavigateTo = (server) => { - this.props.selectServerRequest(server); - this.openLogin(server); - } - - jumpToSelectedServer() { - if (this.props.server && !this.props.login.isRegistering) { - setTimeout(() => { - this.openLogin(this.props.server); - }, 1000); - } - } - - updateState = () => { - this.setState(this.getState()); - } - - renderItem = ({ item }) => ( - { this.onPressItem(item); }} - > - - - {item.id} - - - - - - - ); - - - renderSectionHeader = ({ section }) => ( - {section.title} - ); - - renderSeparator = () => ( - - ); - - render() { - return ( - - item.id} - ItemSeparatorComponent={this.renderSeparator} - /> - - ); - } -} diff --git a/app/views/LoginSignupView.js b/app/views/LoginSignupView.js index 2ef0ba760..9560021fd 100644 --- a/app/views/LoginSignupView.js +++ b/app/views/LoginSignupView.js @@ -281,16 +281,11 @@ export default class LoginSignupView extends LoggedView { > - {I18n.t('Welcome_title_pt_1')} {I18n.t('Welcome_title_pt_2')}