diff --git a/__tests__/__snapshots__/RoomItem.js.snap b/__tests__/__snapshots__/RoomItem.js.snap index 5c71d9422..11d20cb8f 100644 --- a/__tests__/__snapshots__/RoomItem.js.snap +++ b/__tests__/__snapshots__/RoomItem.js.snap @@ -231,15 +231,16 @@ exports[`render unread +999 1`] = ` Array [ Object { "alignItems": "center", - "borderRadius": 20, - "height": 40, "justifyContent": "center", "overflow": "hidden", - "width": 40, }, Object { "backgroundColor": "#3F51B5", + "borderRadius": 20, + "height": 40, + "width": 40, }, + undefined, ] } > @@ -249,29 +250,18 @@ exports[`render unread +999 1`] = ` disabled={false} ellipsizeMode="tail" style={ - Object { - "color": "#ffffff", - "fontSize": 20, - } + Array [ + Object { + "color": "#ffffff", + }, + Object { + "fontSize": 20, + }, + ] } > NA - @@ -368,29 +359,18 @@ exports[`render unread 1`] = ` disabled={false} ellipsizeMode="tail" style={ - Object { - "color": "#ffffff", - "fontSize": 20, - } + Array [ + Object { + "color": "#ffffff", + }, + Object { + "fontSize": 20, + }, + ] } > NA - @@ -487,29 +468,18 @@ exports[`renders correctly 1`] = ` disabled={false} ellipsizeMode="tail" style={ - Object { - "color": "#ffffff", - "fontSize": 20, - } + Array [ + Object { + "color": "#ffffff", + }, + Object { + "fontSize": 20, + }, + ] } > NA - + + + + TE + + + + + AA + + + + + BB + + + + + TE + + + + +`; + exports[`Storyshots Channel Cell Direct Messages 1`] = ` @@ -37,15 +192,16 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = ` Array [ Object { "alignItems": "center", - "borderRadius": 20, - "height": 40, "justifyContent": "center", "overflow": "hidden", - "width": 40, }, Object { "backgroundColor": "#8BC34A", + "borderRadius": 20, + "height": 40, + "width": 40, }, + undefined, ] } > @@ -55,10 +211,14 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = ` disabled={false} ellipsizeMode="tail" style={ - Object { - "color": "#ffffff", - "fontSize": 20, - } + Array [ + Object { + "color": "#ffffff", + }, + Object { + "fontSize": 20, + }, + ] } > RC @@ -70,12 +230,15 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = ` } } style={ - Object { - "borderRadius": 20, - "height": 40, - "position": "absolute", - "width": 40, - } + Array [ + Object { + "position": "absolute", + }, + Object { + "height": 40, + "width": 40, + }, + ] } /> @@ -132,15 +295,16 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = ` Array [ Object { "alignItems": "center", - "borderRadius": 20, - "height": 40, "justifyContent": "center", "overflow": "hidden", - "width": 40, }, Object { "backgroundColor": "#8BC34A", + "borderRadius": 20, + "height": 40, + "width": 40, }, + undefined, ] } > @@ -150,10 +314,14 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = ` disabled={false} ellipsizeMode="tail" style={ - Object { - "color": "#ffffff", - "fontSize": 20, - } + Array [ + Object { + "color": "#ffffff", + }, + Object { + "fontSize": 20, + }, + ] } > RC @@ -165,12 +333,15 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = ` } } style={ - Object { - "borderRadius": 20, - "height": 40, - "position": "absolute", - "width": 40, - } + Array [ + Object { + "position": "absolute", + }, + Object { + "height": 40, + "width": 40, + }, + ] } /> @@ -227,15 +398,16 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = ` Array [ Object { "alignItems": "center", - "borderRadius": 20, - "height": 40, "justifyContent": "center", "overflow": "hidden", - "width": 40, }, Object { "backgroundColor": "#8BC34A", + "borderRadius": 20, + "height": 40, + "width": 40, }, + undefined, ] } > @@ -245,10 +417,14 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = ` disabled={false} ellipsizeMode="tail" style={ - Object { - "color": "#ffffff", - "fontSize": 20, - } + Array [ + Object { + "color": "#ffffff", + }, + Object { + "fontSize": 20, + }, + ] } > RC @@ -260,12 +436,15 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = ` } } style={ - Object { - "borderRadius": 20, - "height": 40, - "position": "absolute", - "width": 40, - } + Array [ + Object { + "position": "absolute", + }, + Object { + "height": 40, + "width": 40, + }, + ] } /> @@ -343,15 +522,16 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = ` Array [ Object { "alignItems": "center", - "borderRadius": 20, - "height": 40, "justifyContent": "center", "overflow": "hidden", - "width": 40, }, Object { "backgroundColor": "#795548", + "borderRadius": 20, + "height": 40, + "width": 40, }, + undefined, ] } > @@ -361,10 +541,14 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = ` disabled={false} ellipsizeMode="tail" style={ - Object { - "color": "#ffffff", - "fontSize": 20, - } + Array [ + Object { + "color": "#ffffff", + }, + Object { + "fontSize": 20, + }, + ] } > LC @@ -376,12 +560,15 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = ` } } style={ - Object { - "borderRadius": 20, - "height": 40, - "position": "absolute", - "width": 40, - } + Array [ + Object { + "position": "absolute", + }, + Object { + "height": 40, + "width": 40, + }, + ] } /> @@ -459,15 +646,16 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = ` Array [ Object { "alignItems": "center", - "borderRadius": 20, - "height": 40, "justifyContent": "center", "overflow": "hidden", - "width": 40, }, Object { "backgroundColor": "#795548", + "borderRadius": 20, + "height": 40, + "width": 40, }, + undefined, ] } > @@ -477,10 +665,14 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = ` disabled={false} ellipsizeMode="tail" style={ - Object { - "color": "#ffffff", - "fontSize": 20, - } + Array [ + Object { + "color": "#ffffff", + }, + Object { + "fontSize": 20, + }, + ] } > LC @@ -492,12 +684,15 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = ` } } style={ - Object { - "borderRadius": 20, - "height": 40, - "position": "absolute", - "width": 40, - } + Array [ + Object { + "position": "absolute", + }, + Object { + "height": 40, + "width": 40, + }, + ] } /> @@ -575,15 +770,16 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = ` Array [ Object { "alignItems": "center", - "borderRadius": 20, - "height": 40, "justifyContent": "center", "overflow": "hidden", - "width": 40, }, Object { "backgroundColor": "#795548", + "borderRadius": 20, + "height": 40, + "width": 40, }, + undefined, ] } > @@ -593,10 +789,14 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = ` disabled={false} ellipsizeMode="tail" style={ - Object { - "color": "#ffffff", - "fontSize": 20, - } + Array [ + Object { + "color": "#ffffff", + }, + Object { + "fontSize": 20, + }, + ] } > LC @@ -608,12 +808,15 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = ` } } style={ - Object { - "borderRadius": 20, - "height": 40, - "position": "absolute", - "width": 40, - } + Array [ + Object { + "position": "absolute", + }, + Object { + "height": 40, + "width": 40, + }, + ] } /> @@ -691,15 +894,16 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = ` Array [ Object { "alignItems": "center", - "borderRadius": 20, - "height": 40, "justifyContent": "center", "overflow": "hidden", - "width": 40, }, Object { "backgroundColor": "#795548", + "borderRadius": 20, + "height": 40, + "width": 40, }, + undefined, ] } > @@ -709,10 +913,14 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = ` disabled={false} ellipsizeMode="tail" style={ - Object { - "color": "#ffffff", - "fontSize": 20, - } + Array [ + Object { + "color": "#ffffff", + }, + Object { + "fontSize": 20, + }, + ] } > LC @@ -724,12 +932,15 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = ` } } style={ - Object { - "borderRadius": 20, - "height": 40, - "position": "absolute", - "width": 40, - } + Array [ + Object { + "position": "absolute", + }, + Object { + "height": 40, + "width": 40, + }, + ] } /> @@ -807,15 +1018,16 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = ` Array [ Object { "alignItems": "center", - "borderRadius": 20, - "height": 40, "justifyContent": "center", "overflow": "hidden", - "width": 40, }, Object { "backgroundColor": "#E91E63", + "borderRadius": 20, + "height": 40, + "width": 40, }, + undefined, ] } > @@ -825,29 +1037,18 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = ` disabled={false} ellipsizeMode="tail" style={ - Object { - "color": "#ffffff", - "fontSize": 20, - } + Array [ + Object { + "color": "#ffffff", + }, + Object { + "fontSize": 20, + }, + ] } > W - @@ -920,29 +1122,18 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = ` disabled={false} ellipsizeMode="tail" style={ - Object { - "color": "#ffffff", - "fontSize": 20, - } + Array [ + Object { + "color": "#ffffff", + }, + Object { + "fontSize": 20, + }, + ] } > WW - @@ -1015,29 +1207,18 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = ` disabled={false} ellipsizeMode="tail" style={ - Object { - "color": "#ffffff", - "fontSize": 20, - } + Array [ + Object { + "color": "#ffffff", + }, + Object { + "fontSize": 20, + }, + ] } > - @{item.u.username}; - } - const time = moment(item.ts).format(this.props.Message_TimeFormat); return ( - - {initials} - - + {username} - {aliasUsername}{time} + {item.alias && @{item.u.username}}{time} {this.attachments()} diff --git a/app/components/RoomItem.js b/app/components/RoomItem.js index 7737e03f3..b1957787e 100644 --- a/app/components/RoomItem.js +++ b/app/components/RoomItem.js @@ -1,9 +1,8 @@ import React from 'react'; -import { CachedImage } from 'react-native-img-cache'; import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons'; import PropTypes from 'prop-types'; import { View, Text, StyleSheet, TouchableOpacity } from 'react-native'; - +import Avatar from './avatar'; import avatarInitialsAndColor from '../utils/avatarInitialsAndColor'; const styles = StyleSheet.create({ @@ -81,12 +80,8 @@ export default class RoomItem extends React.PureComponent { } if (type === 'd') { - const { initials, color } = avatarInitialsAndColor(name); return ( - - {initials} - - + ); } diff --git a/app/components/avatar.js b/app/components/avatar.js new file mode 100644 index 000000000..8cc05a7fc --- /dev/null +++ b/app/components/avatar.js @@ -0,0 +1,51 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { StyleSheet, Text, View } from 'react-native'; +import { CachedImage } from 'react-native-img-cache'; +import avatarInitialsAndColor from '../utils/avatarInitialsAndColor'; + +const styles = StyleSheet.create({ + iconContainer: { + overflow: 'hidden', + justifyContent: 'center', + alignItems: 'center' + }, + avatar: { + position: 'absolute' + }, + avatarInitials: { + color: '#ffffff' + } }); + +class Avatar extends React.PureComponent { + render() { + const { text = '', size = 25, baseUrl = this.props.baseUrl, + borderRadius = 5, style, avatar } = this.props; + const { initials, color } = avatarInitialsAndColor(`${ text }`); + return ( + + {initials} + { (avatar || baseUrl) && } + ); + } +} + +Avatar.propTypes = { + style: PropTypes.object, + baseUrl: PropTypes.string, + text: PropTypes.string.isRequired, + avatar: PropTypes.string, + size: PropTypes.number, + borderRadius: PropTypes.number +}; +export default Avatar; diff --git a/app/index.js b/app/index.js index fb6d5b5fa..01fde6b73 100644 --- a/app/index.js +++ b/app/index.js @@ -1,33 +1,38 @@ import PropTypes from 'prop-types'; import React from 'react'; +import { View, Image } from 'react-native'; import { connect } from 'react-redux'; -import { Text } from 'react-native'; +import * as Animatable from 'react-native-animatable'; import setNavigator from './actions/navigator'; +import { appInit } from './actions'; import LoginView from './views/login'; import ListServerView from './views/serverList'; + +import styles from './views/Styles'; + import store from './lib/createStore'; export const authenticated = WrappedComponent => class _p extends React.PureComponent { constructor() { super(); this.login = store.getState().login; - console.log('this.login.token', this.login.token); if (!this.login.token || this.login.failure) { return store.getState().navigator.resetTo({ - screen: 'Login' + screen: 'Login', + animated: false }); } } render() { // Wraps the input component in a container, without mutating it. Good! - return ; + return ((this.login.isAuthenticated || this.login.user) && ); } }; // export class PublicScreen extends React.PureComponent { render() { - return !this.login.isAuthenticated || !this.login.user ? null : (); + return ((this.login.isAuthenticated || this.login.user) && ); } } @@ -43,21 +48,35 @@ export class PrivateScreen extends React.PureComponent { @connect(() => ({ // logged: state.login.isAuthenticated }), dispatch => ({ - setNavigator: navigator => dispatch(setNavigator(navigator)) + setNavigator: navigator => dispatch(setNavigator(navigator)), + appInit: () => dispatch(appInit()) })) export const HomeScreen = class extends React.PureComponent { static propTypes = { + appInit: PropTypes.func.isRequired, setNavigator: PropTypes.func.isRequired, navigator: PropTypes.object.isRequired } + static navigatorStyle = { + navBarHidden: true, + rightButtons: [{ + id: 'close', + title: 'Cancel' + }] + }; componentWillMount() { this.props.setNavigator(this.props.navigator); - this.props.navigator.resetTo({ - screen: 'public' - }); + this.props.appInit(); + // + // this.props.navigator.setDrawerEnabled({ + // side: 'left', // the side of the drawer since you can have two, 'left' / 'right' + // enabled: false // should the drawer be enabled or disabled (locked closed) + // }); } render() { - return (oieee); + return ( + + ); } }; diff --git a/app/lib/rocketchat.js b/app/lib/rocketchat.js index bed91a75d..a9fd9c8b2 100644 --- a/app/lib/rocketchat.js +++ b/app/lib/rocketchat.js @@ -36,7 +36,15 @@ const RocketChat = { console.warn(`AsyncStorage error: ${ error.message }`); } }, - + async testServer(url) { + if (/^(https?:\/\/)?(((\w|[0-9])+(\.(\w|[0-9-_])+)+)|localhost)(:\d+)?$/.test(url)) { + const response = await fetch(url, { method: 'HEAD' }); + if (response.status === 200 && response.headers.get('x-instance-id') != null && response.headers.get('x-instance-id').length) { + return url; + } + } + throw new Error({ error: 'invalid server' }); + }, connect(_url) { return new Promise((resolve) => { const url = `${ _url }/websocket`; @@ -61,7 +69,7 @@ const RocketChat = { const setting = { _id: item._id }; - setting._server = { id: reduxStore.getState().server }; + setting._server = { id: reduxStore.getState().server.server }; if (settingsType[item.type]) { setting[settingsType[item.type]] = item.value; realm.create('settings', setting, true); @@ -78,7 +86,7 @@ const RocketChat = { realm.write(() => { const message = ddbMessage.fields.args[0]; message.temp = false; - message._server = { id: reduxStore.getState().server }; + message._server = { id: reduxStore.getState().server.server }; realm.create('messages', message, true); }); } @@ -86,7 +94,7 @@ const RocketChat = { if (ddbMessage.collection === 'stream-notify-user') { realm.write(() => { const data = ddbMessage.fields.args[1]; - data._server = { id: reduxStore.getState().server }; + data._server = { id: reduxStore.getState().server.server }; realm.create('subscriptions', data, true); }); } @@ -97,13 +105,11 @@ const RocketChat = { }, login(params, callback) { - console.log('login(params, callback)'); return new Promise((resolve, reject) => { Meteor._startLoggingIn(); return Meteor.call('login', params, (err, result) => { Meteor._endLoggingIn(); Meteor._handleLoginCallback(err, result); - console.log('login(params, callback)asdas', err, result); if (err) { reject(err); } else { @@ -172,7 +178,7 @@ const RocketChat = { // if (typeof item.value === 'string') { // subscription.value = item.value; // } - subscription._server = { id: reduxStore.getState().server }; + subscription._server = { id: reduxStore.getState().server.server }; // write('subscriptions', subscription); realm.create('subscriptions', subscription, true); }); @@ -196,7 +202,7 @@ const RocketChat = { realm.write(() => { data.messages.forEach((message) => { message.temp = false; - message._server = { id: reduxStore.getState().server }; + message._server = { id: reduxStore.getState().server.server }; // write('messages', message); realm.create('messages', message, true); }); @@ -226,7 +232,7 @@ const RocketChat = { ts: new Date(), _updatedAt: new Date(), temp: true, - _server: { id: reduxStore.getState().server }, + _server: { id: reduxStore.getState().server.server }, u: { _id: reduxStore.getState().login.user.id || '1', username: reduxStore.getState().login.user.id @@ -370,7 +376,6 @@ const RocketChat = { return subscription; }); // Meteor.subscribe('stream-notify-user', `${ Meteor.userId() }/rooms-changed`, false); - console.log('getRooms resolved', reduxStore.getState().server, data); realm.write(() => { data.forEach((subscription) => { // const subscription = { @@ -379,7 +384,7 @@ const RocketChat = { // if (typeof item.value === 'string') { // subscription.value = item.value; // } - subscription._server = { id: reduxStore.getState().server }; + subscription._server = { id: reduxStore.getState().server.server }; // write('subscriptions', subscription); realm.create('subscriptions', subscription, true); }); diff --git a/app/reducers/createChannel.js b/app/reducers/createChannel.js new file mode 100644 index 000000000..310281991 --- /dev/null +++ b/app/reducers/createChannel.js @@ -0,0 +1,31 @@ +import { CREATE_CHANNEL } from '../actions/actionsTypes'; + +const initialState = { + isFetching: false, + failure: false +}; + +export default function messages(state = initialState, action) { + switch (action.type) { + case CREATE_CHANNEL.REQUEST: + return { ...state, + error: undefined, + failure: false, + isFetching: true + }; + case CREATE_CHANNEL.SUCCESS: + return { ...state, + isFetching: false, + failure: false, + result: action.data + }; + case CREATE_CHANNEL.FAILURE: + return { ...state, + isFetching: false, + failure: true, + error: action.err + }; + default: + return state; + } +} diff --git a/app/reducers/index.js b/app/reducers/index.js index 108f9add5..05ce591fc 100644 --- a/app/reducers/index.js +++ b/app/reducers/index.js @@ -5,8 +5,9 @@ import meteor from './connect'; import messages from './messages'; import server from './server'; import navigator from './navigator'; +import createChannel from './createChannel'; export default combineReducers({ - settings, login, meteor, messages, server, navigator + settings, login, meteor, messages, server, navigator, createChannel }); diff --git a/app/reducers/server.js b/app/reducers/server.js index 8ee296cd5..ea0315e25 100644 --- a/app/reducers/server.js +++ b/app/reducers/server.js @@ -1,9 +1,36 @@ import { SERVER } from '../actions/actionsTypes'; -export default function server(state = '', action) { +const initialState = { + connecting: false, + connected: false, + errorMessage: '', + failure: false, + server: '' +}; + + +export default function server(state = initialState, action) { switch (action.type) { + case SERVER.REQUEST: + return { ...state, + connecting: true, + failure: false + }; + case SERVER.SUCCESS: + return { ...state, + connecting: false, + connected: true, + failure: false + }; + case SERVER.FAILURE: + return { ...state, + connecting: false, + connected: false, + failure: true, + errorMessage: action.err + }; case SERVER.SELECT: - return action.server; + return { ...state, server: action.server }; default: return state; } diff --git a/app/routes/index.js b/app/routes/index.js deleted file mode 100644 index 5b189b99c..000000000 --- a/app/routes/index.js +++ /dev/null @@ -1,39 +0,0 @@ -import React from 'react'; -import { - Scene, - Router - // Actions, - // Reducer, - // ActionConst, - // Tabs, - // Modal, - // Drawer, - // Stack, - // Lightbox -} from 'react-native-router-flux'; -// import { Navigation } from 'react-native-navigation'; -import { Provider } from 'react-redux'; - -import LoginView from '../views/login'; -import NewServerView from '../views/serverNew'; -import ListServerView from '../views/serverList'; -import RoomsListView from '../views/roomsList'; -import RoomView from '../views/room'; -// import PhotoView from '../views/Photo'; -// import CreateChannel from '../views/CreateChannel'; -import store from '../lib/createStore'; - -export default () => ( - - - - - - - - - - - -); -// diff --git a/app/sagas/connect.js b/app/sagas/connect.js index 4a8ac45f3..3b0c6f793 100644 --- a/app/sagas/connect.js +++ b/app/sagas/connect.js @@ -1,10 +1,10 @@ -import { take, put, call, fork, takeLatest, select } from 'redux-saga/effects'; +import { put, call, takeLatest, select } from 'redux-saga/effects'; import { METEOR } from '../actions/actionsTypes'; import RocketChat from '../lib/rocketchat'; import { connectSuccess, connectFailure } from '../actions/connect'; -const getServer = ({ server }) => server; +const getServer = ({ server }) => server.server; const connect = url => RocketChat.connect(url); @@ -17,14 +17,11 @@ const test = function* test() { yield put(connectFailure(err.status)); } }; -const watchConnect = function* watchConnect() { - yield takeLatest(METEOR.REQUEST, test); - while (true) { - yield take(METEOR.DISCONNECT); - } -}; +// const watchConnect = function* watchConnect() { +// }; const root = function* root() { - yield fork(watchConnect); + yield takeLatest(METEOR.REQUEST, test); + // yield fork(watchConnect); // yield fork(auto); }; export default root; diff --git a/app/sagas/createChannel.js b/app/sagas/createChannel.js new file mode 100644 index 000000000..169b10dac --- /dev/null +++ b/app/sagas/createChannel.js @@ -0,0 +1,34 @@ +import { delay } from 'redux-saga'; +import { select, put, call, fork, take } from 'redux-saga/effects'; +import { CREATE_CHANNEL, LOGIN } from '../actions/actionsTypes'; +import { createChannelSuccess, createChannelFailure } from '../actions/createChannel'; +import RocketChat from '../lib/rocketchat'; + + +const create = function* create(data) { + return yield RocketChat.createChannel(data); +}; + +const get = function* get() { + while (true) { + try { + const { data } = yield take(CREATE_CHANNEL.REQUEST); + const auth = yield select(state => state.login.isAuthenticated); + if (!auth) { + yield take(LOGIN.SUCCESS); + } + const result = yield call(create, data); + yield put(createChannelSuccess(result)); + select(({ navigator }) => navigator).dismissModal({ + animationType: 'slide-down' + }); + } catch (err) { + yield delay(2000); + yield put(createChannelFailure(err)); + } + } +}; +const getData = function* getData() { + yield fork(get); +}; +export default getData; diff --git a/app/sagas/index.js b/app/sagas/index.js index fe68aad7f..e8b716056 100644 --- a/app/sagas/index.js +++ b/app/sagas/index.js @@ -6,11 +6,13 @@ import connect from './connect'; import rooms from './rooms'; import messages from './messages'; import selectServer from './selectServer'; +import createChannel from './createChannel'; import init from './init'; const root = function* root() { yield fork(init); yield take(types.APP.READY); + yield fork(createChannel); yield fork(hello); yield fork(rooms); yield fork(login); diff --git a/app/sagas/init.js b/app/sagas/init.js index b06120211..0308610f7 100644 --- a/app/sagas/init.js +++ b/app/sagas/init.js @@ -1,13 +1,23 @@ import { AsyncStorage } from 'react-native'; -import { call, put } from 'redux-saga/effects'; +import { call, put, select, take } from 'redux-saga/effects'; import * as actions from '../actions'; import { setServer } from '../actions/server'; +import { APP } from '../actions/actionsTypes'; const restore = function* restore() { try { + yield take(APP.INIT); + const { navigator } = yield select(state => state); const currentServer = yield call([AsyncStorage, 'getItem'], 'currentServer'); yield put(actions.appReady({})); - if (currentServer) { yield put(setServer(currentServer)); } + if (currentServer) { + yield put(setServer(currentServer)); + } else { + navigator.resetTo({ + screen: 'ListServer', + animated: false + }); + } } catch (e) { console.log(e); } diff --git a/app/sagas/login.js b/app/sagas/login.js index b21d2503e..b987d4f39 100644 --- a/app/sagas/login.js +++ b/app/sagas/login.js @@ -1,12 +1,12 @@ import { AsyncStorage } from 'react-native'; import { take, put, call, takeEvery, fork, select, all, race } from 'redux-saga/effects'; import * as types from '../actions/actionsTypes'; -import { loginRequest, loginSuccess, loginFailure, setToken } from '../actions/login'; +import { loginRequest, loginSuccess, loginFailure, setToken, logout } from '../actions/login'; import RocketChat from '../lib/rocketchat'; const TOKEN_KEY = 'reactnativemeteor_usertoken'; const getUser = state => state.login; -const getServer = state => state.server; +const getServer = state => state.server.server; const loginCall = args => (args.resume ? RocketChat.login(args) : RocketChat.loginWithPassword(args)); const getToken = function* getToken() { @@ -20,6 +20,8 @@ const getToken = function* getToken() { } catch (e) { console.log('getTokenerr', e); } + } else { + yield put(setToken()); } }; @@ -27,10 +29,9 @@ const handleLoginWhenServerChanges = function* handleLoginWhenServerChanges() { // do { try { yield take(types.METEOR.SUCCESS); + yield call(getToken); const { navigator } = yield select(state => state); - navigator.resetTo({ - screen: 'Rooms' - }); + const user = yield select(getUser); if (user.token) { yield put(loginRequest({ resume: user.token })); @@ -47,6 +48,9 @@ const handleLoginWhenServerChanges = function* handleLoginWhenServerChanges() { // }); // } } + navigator.resetTo({ + screen: 'Rooms' + }); } catch (e) { console.log(e); } @@ -66,8 +70,11 @@ const handleLoginRequest = function* handleLoginRequest() { const response = yield call(loginCall, credentials); yield put(loginSuccess(response)); } catch (err) { - // console.log('login failed'); - yield put(loginFailure(err)); + if (err.error === 403) { + yield put(logout()); + } else { + yield put(loginFailure(err)); + } } } }; @@ -93,7 +100,6 @@ const handleLoginSubmit = function* handleLoginSubmit() { }; const root = function* root() { - yield takeEvery(types.SERVER.CHANGED, getToken); yield takeEvery(types.SERVER.CHANGED, handleLoginWhenServerChanges); yield fork(handleLoginRequest); yield takeEvery(types.LOGIN.SUCCESS, saveToken); diff --git a/app/sagas/selectServer.js b/app/sagas/selectServer.js index de45cd34c..88d6a0b8e 100644 --- a/app/sagas/selectServer.js +++ b/app/sagas/selectServer.js @@ -1,17 +1,60 @@ -import { put, takeEvery, call } from 'redux-saga/effects'; +import { put, takeEvery, call, takeLatest, race, take } from 'redux-saga/effects'; +import { delay } from 'redux-saga'; import { AsyncStorage } from 'react-native'; +import { Navigation } from 'react-native-navigation'; import { SERVER } from '../actions/actionsTypes'; import { connectRequest, disconnect } from '../actions/connect'; -import { changedServer } from '../actions/server'; +import { changedServer, serverSuccess, serverFailure, serverRequest } from '../actions/server'; +import RocketChat from '../lib/rocketchat'; +import realm from '../lib/realm'; + +const validate = function* validate(server) { + return yield RocketChat.testServer(server); +}; const selectServer = function* selectServer({ server }) { yield put(disconnect()); yield put(changedServer(server)); - yield console.log('SERVER->', server); yield call([AsyncStorage, 'setItem'], 'currentServer', server); yield put(connectRequest(server)); + yield Navigation.dismissModal({ + animationType: 'slide-down' + }); }; + + +const validateServer = function* validateServer({ server }) { + try { + yield delay(1000); + yield call(validate, server); + yield put(serverSuccess()); + } catch (e) { + console.log(e); + yield put(serverFailure(e)); + } +}; + +const addServer = function* addServer({ server }) { + yield call(serverRequest, server); + + const { error } = race({ + error: take(SERVER.FAILURE), + success: take(SERVER.SUCCESS) + }); + if (!error) { + realm.write(() => { + realm.create('servers', { id: server, current: false }, true); + }); + Navigation.dismissModal({ + animationType: 'slide-down' + }); + } +}; + + const root = function* root() { + yield takeLatest(SERVER.REQUEST, validateServer); yield takeEvery(SERVER.SELECT, selectServer); + yield takeEvery(SERVER.ADD, addServer); }; export default root; diff --git a/app/utils/avatarInitialsAndColor.js b/app/utils/avatarInitialsAndColor.js index 09c41fb1d..13029c66c 100644 --- a/app/utils/avatarInitialsAndColor.js +++ b/app/utils/avatarInitialsAndColor.js @@ -1,6 +1,12 @@ import { AVATAR_COLORS } from '../constants/colors'; export default function(username = '') { + if (username === '') { + return { + initials: '', + colors: 'transparent' + }; + } const position = username.length % AVATAR_COLORS.length; const color = AVATAR_COLORS[position]; diff --git a/app/views/CreateChannel.js b/app/views/CreateChannel.js index 8d9d12eb4..45424e05a 100644 --- a/app/views/CreateChannel.js +++ b/app/views/CreateChannel.js @@ -1,101 +1,83 @@ -import ActionButton from 'react-native-action-button'; -import Icon from 'react-native-vector-icons/Ionicons'; + import React from 'react'; -// import PropTypes from 'prop-types'; -import { TextInput, StyleSheet, View, Text, Switch } from 'react-native'; -import RocketChat from '../lib/rocketchat'; +import { connect } from 'react-redux'; +import PropTypes from 'prop-types'; +import { TextInput, View, Text, Switch, TouchableOpacity, ScrollView } from 'react-native'; +import { createChannelRequest } from '../actions/createChannel'; +import styles from './Styles'; +import KeyboardView from '../components/KeyboardView'; -// import KeyboardView from '../components/KeyboardView'; +@connect(state => ({ + result: state.createChannel +}), dispatch => ({ + createChannel: data => dispatch(createChannelRequest(data)) +})) -const styles = StyleSheet.create({ - view: { - flex: 1, - flexDirection: 'column', - padding: 24 - }, - input: { - // height: 50, - fontSize: 20, - borderColor: '#ffffff', - padding: 5, - borderWidth: 0, - backgroundColor: 'white' - }, - field: { - flex: 1, - flexDirection: 'row', - alignItems: 'center' - }, - field_label: { - flexGrow: 1 - }, - field_input: { - flexGrow: 1, - fontSize: 20, - borderColor: '#ffffff', - padding: 5, - borderWidth: 0, - backgroundColor: 'white' - }, - actionButtonIcon: { - fontSize: 20, - height: 22, - color: 'white' - } -}); -const mainIcon = ; export default class CreateChannelView extends React.Component { - // static propTypes = { - // navigation: PropTypes.object.isRequired - // } - static navigationOptions = () => ({ - title: 'Create Channel' + title: 'Create a New Channel' }); + static propTypes = { + createChannel: PropTypes.func.isRequired, + result: PropTypes.object.isRequired, + navigator: PropTypes.object.isRequired + } constructor(props) { super(props); - - this.state = { + this.default = { channelName: '', type: true }; + this.state = this.default; + this.props.navigator.setTitle({ + title: 'Create Channel' + }); + // this.props.navigator.setSubTitle({ + // subtitle: 'Channels are where your team communicate.' + // }); } submit() { + if (!this.state.channelName.trim() || this.props.result.isFetching) { + return; + } const { channelName, users = [], type = true } = this.state; - RocketChat.createChannel({ name: channelName, users, type }).then(res => Promise.reject(res)); - - // { username: this.state.username }, this.state.password, () => { - // this.props.navigation.dispatch({ type: 'Navigation/BACK' }); - // }); + this.props.createChannel({ name: channelName, users, type }); } render() { return ( - - - this.setState({ channelName })} - autoCorrect={false} - returnKeyType='done' - autoCapitalize='none' - autoFocus - // onSubmitEditing={() => this.textInput.focus()} - placeholder='Type the channel name here' - /> - - - {this.state.type ? 'Public' : 'Private'} - this.setState({ type })} - /> - - {this.state.channelName.length > 0 ? - this.submit()} /> : null } - + + + + Channel Name + this.setState({ channelName })} + autoCorrect={false} + returnKeyType='done' + autoCapitalize='none' + autoFocus + // onSubmitEditing={() => this.textInput.focus()} + placeholder='Type the channel name here' + /> + {(this.props.result.failure && this.props.result.error.error === 'error-duplicate-channel-name') ? {this.props.result.error.reason} : null} + + this.setState({ type })} + /> + {this.state.type ? 'Public' : 'Private'} + + {this.state.type ? 'Everyone can access this channel' : 'Just invited people can access this channel'} + this.submit()} style={[styles.buttonContainer_white, { backgroundColor: (this.state.channelName.length === 0 || this.props.result.isFetching) ? '#e1e5e8' : '#1d74f5' }]}> + { this.props.result.isFetching ? 'LOADING' : 'CREATE' }! + + + + ); } } diff --git a/app/views/Styles.js b/app/views/Styles.js new file mode 100644 index 000000000..1ec446317 --- /dev/null +++ b/app/views/Styles.js @@ -0,0 +1,105 @@ +import { StyleSheet } from 'react-native'; + +export default StyleSheet.create({ + view: { + flex: 1, + flexDirection: 'column', + justifyContent: 'center', + padding: 20, + alignItems: 'stretch', + backgroundColor: '#2f343d' + }, + view_white: { + flex: 1, + flexDirection: 'column', + justifyContent: 'center', + padding: 20, + alignItems: 'stretch', + backgroundColor: '#fff' + }, + logoContainer: { + flex: 1, + alignItems: 'center', + flexGrow: 1, + justifyContent: 'center' + }, + logo: { + width: 150, + // backgroundColor: 'red' + // height: 150, + resizeMode: 'contain' + }, + formContainer: { + // marginBottom: 20 + }, + label: { + lineHeight: 40, + height: 40, + fontSize: 16, + marginBottom: 5, + color: 'white' + }, + label_white: { + lineHeight: 40, + height: 40, + fontSize: 16, + marginBottom: 5, + color: '#2f343d' + }, + input: { + height: 45, + marginBottom: 20, + borderRadius: 2, + // padding: 14, + paddingHorizontal: 10, + borderWidth: 2, + backgroundColor: 'rgba(255,255,255,.2)', + borderColor: '#e1e5e8', + color: 'white' + }, + input_white: { + height: 45, + marginBottom: 20, + borderRadius: 2, + // padding: 14, + paddingHorizontal: 10, + borderWidth: 2, + backgroundColor: 'white', + borderColor: 'rgba(0,0,0,.15)', + color: 'black' + }, + buttonContainer: { + paddingVertical: 15, + backgroundColor: '#414852', + marginBottom: 20 + }, + buttonContainer_white: { + paddingVertical: 15, + backgroundColor: '#1d74f5', + marginBottom: 20 + }, + button: { + textAlign: 'center', + color: 'white', + borderRadius: 2, + fontWeight: '700' + }, + button_white: { + textAlign: 'center', + color: 'white', + borderRadius: 2, + fontWeight: '700' + }, + error: { + textAlign: 'center', + color: 'red', + paddingTop: 5 + }, + loading: { + flex: 1, + position: 'absolute', + backgroundColor: 'rgba(255,255,255,.2)', + left: 0, + top: 0 + } +}); diff --git a/app/views/login.js b/app/views/login.js index dcb5cf98c..8393ebd99 100644 --- a/app/views/login.js +++ b/app/views/login.js @@ -3,7 +3,7 @@ import React from 'react'; import Spinner from 'react-native-loading-spinner-overlay'; import PropTypes from 'prop-types'; -import { Keyboard, Text, TextInput, StyleSheet, View, Image, TouchableOpacity } from 'react-native'; +import { Keyboard, Text, TextInput, View, Image, TouchableOpacity } from 'react-native'; import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; // import * as actions from '../actions'; @@ -11,63 +11,7 @@ import * as loginActions from '../actions/login'; import KeyboardView from '../components/KeyboardView'; // import { Keyboard } from 'react-native' -const styles = StyleSheet.create({ - view: { - flex: 1, - flexDirection: 'column', - justifyContent: 'center', - padding: 20, - alignItems: 'stretch', - backgroundColor: '#2f343d' - }, - logoContainer: { - flex: 1, - alignItems: 'center', - flexGrow: 1, - justifyContent: 'center' - }, - logo: { - width: 150, - // backgroundColor: 'red' - // height: 150, - resizeMode: 'contain' - }, - formContainer: { - // marginBottom: 20 - }, - input: { - height: 40, - marginBottom: 20, - borderRadius: 2, - paddingHorizontal: 10, - borderWidth: 0, - backgroundColor: 'rgba(255,255,255,.2)', - color: 'white' - }, - buttonContainer: { - paddingVertical: 15, - backgroundColor: '#414852', - marginBottom: 20 - }, - button: { - textAlign: 'center', - color: 'white', - borderRadius: 2, - fontWeight: '700' - }, - error: { - textAlign: 'center', - color: 'red', - paddingTop: 5 - }, - loading: { - flex: 1, - position: 'absolute', - backgroundColor: 'rgba(255,255,255,.2)', - left: 0, - top: 0 - } -}); +import styles from './Styles'; class LoginView extends React.Component { static propTypes = { @@ -90,16 +34,33 @@ class LoginView extends React.Component { username: '', password: '' }; - - this.props.navigator.setTitle({ + } + componentWillReceiveProps() { + const { navigator } = this.props; + navigator.setTitle({ title: 'Login' }); - } - - componentWillReceiveProps(nextProps) { - this.props.navigator.setSubTitle({ - subtitle: nextProps.server + navigator.setSubTitle({ + subtitle: this.props.server }); + navigator.setButtons({ + rightButtons: [{ + id: 'close', + title: 'Cancel' + }] + }); + this.props.navigator.setOnNavigatorEvent(this.onNavigatorEvent.bind(this)); + } + onNavigatorEvent = (event) => { + if (event.type === 'NavBarButtonPress') { + if (event.id === 'close') { + this.props.navigator.resetTo({ + screen: 'ListServer', + animated: false + + }); + } + } } submit = () => { const { username, password, code } = this.state; @@ -175,7 +136,7 @@ class LoginView extends React.Component { function mapStateToProps(state) { // console.log(Object.keys(state)); return { - server: state.server, + server: state.server.server, Accounts_EmailOrUsernamePlaceholder: state.settings.Accounts_EmailOrUsernamePlaceholder, Accounts_PasswordPlaceholder: state.settings.Accounts_PasswordPlaceholder, login: state.login diff --git a/app/views/room.js b/app/views/room.js index 2f0e0a29a..0060f4342 100644 --- a/app/views/room.js +++ b/app/views/room.js @@ -46,7 +46,7 @@ const styles = StyleSheet.create({ @connect(state => ({ - server: state.server, + server: state.server.server, Site_Url: state.settings.Site_Url, Message_TimeFormat: state.settings.Message_TimeFormat, loading: state.messages.isFetching diff --git a/app/views/roomsList.js b/app/views/roomsList.js index 5eb9b8240..559fbffff 100644 --- a/app/views/roomsList.js +++ b/app/views/roomsList.js @@ -3,6 +3,7 @@ import { Navigation } from 'react-native-navigation'; import { ListView } from 'realm/react-native'; import React from 'react'; import PropTypes from 'prop-types'; +import Icon from 'react-native-vector-icons/Ionicons'; import { View, StyleSheet, TextInput, Platform } from 'react-native'; import { connect } from 'react-redux'; import * as actions from '../actions'; @@ -55,10 +56,10 @@ const styles = StyleSheet.create({ const ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 }); @connect(state => ({ - server: state.server, + server: state.server.server, login: state.login, Site_Url: state.settings.Site_Url, - canShowList: state.login.token.length || state.login.user.token + canShowList: state.login.token || state.login.user.token }), dispatch => ({ login: () => dispatch(actions.login()), connect: () => dispatch(server.connectRequest()) @@ -219,7 +220,16 @@ export default class RoomsListView extends React.Component { navigateToRoom({ sid: id }); clearSearch(); } - + _createChannel = () => { + Navigation.showModal({ + screen: 'CreateChannel', + title: 'Create a New Channel', + passProps: {}, + navigatorStyle: {}, + navigatorButtons: {}, + animationType: 'slide-up' + }); + } renderSearchBar = () => ( ) renderCreateButtons = () => ( - ); + + { this._createChannel(); }} > + + + ); render= () => ( diff --git a/app/views/serverList.js b/app/views/serverList.js index ec04b22c3..a988ea441 100644 --- a/app/views/serverList.js +++ b/app/views/serverList.js @@ -65,13 +65,15 @@ const zeroconf = new Zeroconf(); @connect(state => ({ - server: state.server + server: state.server.server, + login: state.login }), dispatch => ({ selectServer: server => dispatch(setServer(server)) })) export default class ListServerView extends React.Component { static propTypes = { navigator: PropTypes.object.isRequired, + login: PropTypes.object.isRequired, selectServer: PropTypes.func.isRequired, actions: PropTypes.object, server: PropTypes.string @@ -92,7 +94,7 @@ export default class ListServerView extends React.Component { id: 'add', title: 'Add' }], - leftButtons: props.server && Platform.select({ + leftButtons: props.login.isAuthenticated && props.server && Platform.select({ ios: [{ id: 'close', title: 'Close' diff --git a/app/views/serverNew.js b/app/views/serverNew.js index e4eae9fdf..dbac69be5 100644 --- a/app/views/serverNew.js +++ b/app/views/serverNew.js @@ -2,9 +2,8 @@ import React from 'react'; import PropTypes from 'prop-types'; import { Navigation } from 'react-native-navigation'; import { Text, TextInput, View, StyleSheet } from 'react-native'; -import _ from 'underscore'; -import realm from '../lib/realm'; - +import { connect } from 'react-redux'; +import { serverRequest, addServer } from '../actions/server'; import KeyboardView from '../components/KeyboardView'; const styles = StyleSheet.create({ @@ -47,10 +46,20 @@ const styles = StyleSheet.create({ flexGrow: 1 } }); - +@connect(state => ({ + validInstance: !state.server.failure, + validating: state.server.connecting +}), dispatch => ({ + validateServer: url => dispatch(serverRequest(url)), + addServer: url => dispatch(addServer(url)) +})) export default class NewServerView extends React.Component { static propTypes = { - navigator: PropTypes.object.isRequired + navigator: PropTypes.object.isRequired, + validateServer: PropTypes.func.isRequired, + addServer: PropTypes.func.isRequired, + validating: PropTypes.bool.isRequired, + validInstance: PropTypes.bool.isRequired } static navigationOptions = () => ({ @@ -66,37 +75,11 @@ export default class NewServerView extends React.Component { }; this.submit = () => { - let url = this.state.text.trim(); - if (!url) { - url = this.state.defaultServer; - } else { - url = this.completeUrl(this.state.text); - } - - this.setState({ - editable: false - }); - - this.inputElement.blur(); - this.validateServer(url).then(() => { - realm.write(() => { - realm.create('servers', { id: url, current: false }, true); - }); - Navigation.dismissModal({ - animationType: 'slide-down' - }); - }).catch(() => { - this.setState({ - editable: true - }); - this.inputElement.focus(); - }); + this.props.addServer(this.completeUrl(this.state.text.trim() || this.state.defaultServer)); }; } componentDidMount() { - this._mounted = true; - this.props.navigator.setTitle({ title: 'New server' }); @@ -111,11 +94,6 @@ export default class NewServerView extends React.Component { this.props.navigator.setOnNavigatorEvent(this.onNavigatorEvent.bind(this)); } - - componentWillUnmount() { - this._mounted = false; - } - onNavigatorEvent = (event) => { if (event.type === 'NavBarButtonPress') { if (event.id === 'close') { @@ -128,62 +106,8 @@ export default class NewServerView extends React.Component { onChangeText = (text) => { this.setState({ text }); - - this.validateServerDebounced(text); + this.props.validateServer(this.completeUrl(text)); } - - validateServer = url => new Promise((resolve, reject) => { - url = this.completeUrl(url); - - this.setState({ - validating: false, - url - }); - - if (/^(https?:\/\/)?(((\w|[0-9])+(\.(\w|[0-9-_])+)+)|localhost)(:\d+)?$/.test(url)) { - this.setState({ - validating: true - }); - - fetch(url, { method: 'HEAD' }) - .then((response) => { - if (!this._mounted) { - return; - } - if (response.status === 200 && response.headers.get('x-instance-id') != null && response.headers.get('x-instance-id').length) { - this.setState({ - validInstance: true, - validating: false - }); - resolve(url); - } else { - this.setState({ - validInstance: false, - validating: false - }); - reject(url); - } - }) - .catch(() => { - if (!this._mounted) { - return; - } - this.setState({ - validInstance: false, - validating: false - }); - reject(url); - }); - } else { - this.setState({ - validInstance: undefined - }); - reject(url); - } - }) - - validateServerDebounced = _.debounce(this.validateServer, 1000) - completeUrl = (url) => { url = url.trim(); @@ -203,7 +127,10 @@ export default class NewServerView extends React.Component { } renderValidation = () => { - if (this.state.validating) { + if (!this.state.text.trim()) { + return null; + } + if (this.props.validating) { return ( Validating {this.state.url} ... @@ -211,21 +138,18 @@ export default class NewServerView extends React.Component { ); } - if (this.state.validInstance) { + if (this.props.validInstance) { return ( {this.state.url} is a valid Rocket.Chat instance ); } - - if (this.state.validInstance === false) { - return ( - - {this.state.url} is not a valid Rocket.Chat instance - - ); - } + return ( + + {this.state.url} is not a valid Rocket.Chat instance + + ); } render() { diff --git a/package-lock.json b/package-lock.json index 2cd4d5b6b..256f965ec 100644 --- a/package-lock.json +++ b/package-lock.json @@ -345,7 +345,7 @@ "anymatch": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", - "integrity": "sha1-VT3Lj5HjyImEXf26NMd3IbkLnXo=", + "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", "requires": { "micromatch": "2.3.11", "normalize-path": "2.1.1" @@ -409,7 +409,7 @@ "arr-flatten": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha1-NgSLv/TntH4TZkQxbJlmnqWukfE=" + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" }, "array-differ": { "version": "1.0.0", @@ -533,7 +533,7 @@ "async": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/async/-/async-2.5.0.tgz", - "integrity": "sha1-hDGQ/WtzV6C54clW7d3V7IRitU0=", + "integrity": "sha512-e+lJAJeNWuPCNyxZKOBdaJGyLGHugXVQtrAwtuAe2vhxTYxFTKE73p8JuTmdH0qdQZtDvI4dhJwjZc5zsfIsYw==", "requires": { "lodash": "4.17.4" } @@ -1739,7 +1739,7 @@ "babylon": { "version": "6.17.4", "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.17.4.tgz", - "integrity": "sha1-Pot0AriNIsNCPhN6FXeIOxX/hpo=" + "integrity": "sha512-kChlV+0SXkjE0vUn9OZ7pBMWRFd8uq3mZe8x1K6jhuNcAFAtEnjchFAqB+dYEXKyd+JpT6eppRR78QAr5gTsUw==" }, "balanced-match": { "version": "1.0.0", @@ -2160,6 +2160,7 @@ "requires": { "anymatch": "1.3.2", "async-each": "1.0.1", + "fsevents": "1.1.2", "glob-parent": "2.0.0", "inherits": "2.0.3", "is-binary-path": "1.0.1", @@ -3014,7 +3015,7 @@ "diff": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.0.tgz", - "integrity": "sha1-BWaVFQ16qTI3yn43isOxaCt5Y7k=", + "integrity": "sha512-w0XZubFWn0Adlsapj9EAWX0FqWdO4tz8kc3RiYdWLh4k/V8PTb6i0SMgXt0vRM3zyKnT8tKO7mUlieRQHIjMNg==", "dev": true }, "diffie-hellman": { @@ -3657,7 +3658,7 @@ "esprima": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", - "integrity": "sha1-RJnt3NERDgshi6zy+n9/WfVcqAQ=", + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", "dev": true }, "esquery": { @@ -4245,6 +4246,905 @@ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, + "fsevents": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.2.tgz", + "integrity": "sha512-Sn44E5wQW4bTHXvQmvSHwqbuiXtduD6Rrjm2ZtUEGbyrig+nUH3t/QD4M4/ZXViY556TBpRgZkHLDx3JxPwxiw==", + "dev": true, + "optional": true, + "requires": { + "nan": "2.6.2", + "node-pre-gyp": "0.6.36" + }, + "dependencies": { + "abbrev": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "ajv": { + "version": "4.11.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "co": "4.6.0", + "json-stable-stringify": "1.0.1" + } + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "aproba": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.2.9" + } + }, + "asn1": { + "version": "0.2.3", + "bundled": true, + "dev": true, + "optional": true + }, + "assert-plus": { + "version": "0.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "asynckit": { + "version": "0.4.0", + "bundled": true, + "dev": true, + "optional": true + }, + "aws-sign2": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "aws4": { + "version": "1.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "balanced-match": { + "version": "0.4.2", + "bundled": true, + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "block-stream": { + "version": "0.0.9", + "bundled": true, + "dev": true, + "requires": { + "inherits": "2.0.3" + } + }, + "boom": { + "version": "2.10.1", + "bundled": true, + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "brace-expansion": { + "version": "1.1.7", + "bundled": true, + "dev": true, + "requires": { + "balanced-match": "0.4.2", + "concat-map": "0.0.1" + } + }, + "buffer-shims": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "caseless": { + "version": "0.12.0", + "bundled": true, + "dev": true, + "optional": true + }, + "co": { + "version": "4.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "combined-stream": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "requires": { + "delayed-stream": "1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "cryptiles": { + "version": "2.0.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "boom": "2.10.1" + } + }, + "dashdash": { + "version": "1.14.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "debug": { + "version": "2.6.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.4.2", + "bundled": true, + "dev": true, + "optional": true + }, + "delayed-stream": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "ecc-jsbn": { + "version": "0.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "extend": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "extsprintf": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "forever-agent": { + "version": "0.6.1", + "bundled": true, + "dev": true, + "optional": true + }, + "form-data": { + "version": "2.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.5", + "mime-types": "2.1.15" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "fstream": { + "version": "1.0.11", + "bundled": true, + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "inherits": "2.0.3", + "mkdirp": "0.5.1", + "rimraf": "2.6.1" + } + }, + "fstream-ignore": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "fstream": "1.0.11", + "inherits": "2.0.3", + "minimatch": "3.0.4" + } + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aproba": "1.1.1", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" + } + }, + "getpass": { + "version": "0.1.7", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "glob": { + "version": "7.1.2", + "bundled": true, + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "graceful-fs": { + "version": "4.1.11", + "bundled": true, + "dev": true + }, + "har-schema": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "optional": true + }, + "har-validator": { + "version": "4.2.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ajv": "4.11.8", + "har-schema": "1.0.5" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "hawk": { + "version": "3.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "boom": "2.10.1", + "cryptiles": "2.0.5", + "hoek": "2.16.3", + "sntp": "1.0.9" + } + }, + "hoek": { + "version": "2.16.3", + "bundled": true, + "dev": true + }, + "http-signature": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "0.2.0", + "jsprim": "1.4.0", + "sshpk": "1.13.0" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true + }, + "ini": { + "version": "1.3.4", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-typedarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "isstream": { + "version": "0.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "jodid25519": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "jsbn": { + "version": "0.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "json-schema": { + "version": "0.2.3", + "bundled": true, + "dev": true, + "optional": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "jsonify": "0.0.0" + } + }, + "json-stringify-safe": { + "version": "5.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "jsonify": { + "version": "0.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "jsprim": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.0.2", + "json-schema": "0.2.3", + "verror": "1.3.6" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "mime-db": { + "version": "1.27.0", + "bundled": true, + "dev": true + }, + "mime-types": { + "version": "2.1.15", + "bundled": true, + "dev": true, + "requires": { + "mime-db": "1.27.0" + } + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "requires": { + "brace-expansion": "1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "node-pre-gyp": { + "version": "0.6.36", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "mkdirp": "0.5.1", + "nopt": "4.0.1", + "npmlog": "4.1.0", + "rc": "1.2.1", + "request": "2.81.0", + "rimraf": "2.6.1", + "semver": "5.3.0", + "tar": "2.2.1", + "tar-pack": "3.4.0" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1.1.0", + "osenv": "0.1.4" + } + }, + "npmlog": { + "version": "4.1.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "oauth-sign": { + "version": "0.8.2", + "bundled": true, + "dev": true, + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "performance-now": { + "version": "0.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "1.0.7", + "bundled": true, + "dev": true + }, + "punycode": { + "version": "1.4.1", + "bundled": true, + "dev": true, + "optional": true + }, + "qs": { + "version": "6.4.0", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "deep-extend": "0.4.2", + "ini": "1.3.4", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.2.9", + "bundled": true, + "dev": true, + "requires": { + "buffer-shims": "1.0.0", + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "string_decoder": "1.0.1", + "util-deprecate": "1.0.2" + } + }, + "request": { + "version": "2.81.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aws-sign2": "0.6.0", + "aws4": "1.6.0", + "caseless": "0.12.0", + "combined-stream": "1.0.5", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.1.4", + "har-validator": "4.2.1", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.15", + "oauth-sign": "0.8.2", + "performance-now": "0.2.0", + "qs": "6.4.0", + "safe-buffer": "5.0.1", + "stringstream": "0.0.5", + "tough-cookie": "2.3.2", + "tunnel-agent": "0.6.0", + "uuid": "3.0.1" + } + }, + "rimraf": { + "version": "2.6.1", + "bundled": true, + "dev": true, + "requires": { + "glob": "7.1.2" + } + }, + "safe-buffer": { + "version": "5.0.1", + "bundled": true, + "dev": true + }, + "semver": { + "version": "5.3.0", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sntp": { + "version": "1.0.9", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "hoek": "2.16.3" + } + }, + "sshpk": { + "version": "1.13.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jodid25519": "1.0.2", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "string_decoder": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "requires": { + "safe-buffer": "5.0.1" + } + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "stringstream": { + "version": "0.0.5", + "bundled": true, + "dev": true, + "optional": true + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "2.2.1", + "bundled": true, + "dev": true, + "requires": { + "block-stream": "0.0.9", + "fstream": "1.0.11", + "inherits": "2.0.3" + } + }, + "tar-pack": { + "version": "3.4.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "2.6.8", + "fstream": "1.0.11", + "fstream-ignore": "1.0.5", + "once": "1.4.0", + "readable-stream": "2.2.9", + "rimraf": "2.6.1", + "tar": "2.2.1", + "uid-number": "0.0.6" + } + }, + "tough-cookie": { + "version": "2.3.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "punycode": "1.4.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "bundled": true, + "dev": true, + "optional": true + }, + "uid-number": { + "version": "0.0.6", + "bundled": true, + "dev": true, + "optional": true + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "uuid": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "verror": { + "version": "1.3.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "extsprintf": "1.0.2" + } + }, + "wide-align": { + "version": "1.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "string-width": "1.0.2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true + } + } + }, "fstream": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", @@ -4330,7 +5230,7 @@ "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "requires": { "fs.realpath": "1.0.0", "inflight": "1.0.6", @@ -4369,7 +5269,7 @@ "globals": { "version": "9.18.0", "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", - "integrity": "sha1-qjiWs+abSH8X4x7SFD1pqOMMLYo=" + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==" }, "globby": { "version": "5.0.0", @@ -4585,7 +5485,7 @@ "hosted-git-info": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", - "integrity": "sha1-bWDjSzq7yDEwYsO3mO+NkBoHrzw=" + "integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==" }, "html-comment-regex": { "version": "1.1.1", @@ -4664,7 +5564,7 @@ "iconv-lite": { "version": "0.4.18", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.18.tgz", - "integrity": "sha1-I9hlaxaq5nQqwpcy6o8DNqR4nPI=" + "integrity": "sha512-sr1ZQph3UwHTR0XftSbK85OvBbxe/abLGzEnPENCQwmHf7sck8Oyu4ob3LgBxWWxRoM+QszeUyl7jbqapu2TqA==" }, "icss-replace-symbols": { "version": "1.1.0", @@ -4753,7 +5653,7 @@ "inquirer": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.2.1.tgz", - "integrity": "sha1-Bs6w9UD0XKVIwX1oQJWYeCZfoXU=", + "integrity": "sha512-QgW3eiPN8gpj/K5vVpHADJJgrrF0ho/dZGylikGX7iqAdRgC9FVKYKWFLx6hZDBFcOLEoSqINYrVPeFAeG/PdA==", "requires": { "ansi-escapes": "2.0.0", "chalk": "2.0.1", @@ -5102,13 +6002,13 @@ "istanbul-lib-coverage": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.1.1.tgz", - "integrity": "sha1-c7+5mIhSmUFck9OKPprfeEp3qdo=", + "integrity": "sha512-0+1vDkmzxqJIn5rcoEqapSB4DmPxE31EtI2dF2aCkV5esN9EWHxZ0dwgDClivMXJqE7zaYQxq30hj5L0nlTN5Q==", "dev": true }, "istanbul-lib-hook": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-1.0.7.tgz", - "integrity": "sha1-3WYH8DB2V4/n1vKmMM8UO0m6zdw=", + "integrity": "sha512-3U2HB9y1ZV9UmFlE12Fx+nPtFqIymzrqCksrXujm3NVbAZIJg/RfYgO1XiIa0mbmxTjWpVEVlkIZJ25xVIAfkQ==", "dev": true, "requires": { "append-transform": "0.4.0" @@ -5132,7 +6032,7 @@ "istanbul-lib-report": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-1.1.1.tgz", - "integrity": "sha1-8OVfVmVf+jQiIIC3oM1HYOFAX8k=", + "integrity": "sha512-tvF+YmCmH4thnez6JFX06ujIA19WPa9YUiwjc1uALF2cv5dmE3It8b5I8Ob7FHJ70H9Y5yF+TDkVa/mcADuw1Q==", "dev": true, "requires": { "istanbul-lib-coverage": "1.1.1", @@ -5161,7 +6061,7 @@ "istanbul-lib-source-maps": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.1.tgz", - "integrity": "sha1-pv4ay6jOCO68Y45XLilNJnAIqgw=", + "integrity": "sha512-mukVvSXCn9JQvdJl8wP/iPhqig0MRtuWuD4ZNKo6vB2Ik//AmhAKe3QnPN02dmkRe3lTudFk3rzoHhwU4hb94w==", "dev": true, "requires": { "debug": "2.6.8", @@ -5174,7 +6074,7 @@ "istanbul-reports": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-1.1.1.tgz", - "integrity": "sha1-BCvlyJ4XW8P4ZSPKqynAFOd/7k4=", + "integrity": "sha512-P8G873A0kW24XRlxHVGhMJBhQ8gWAec+dae7ZxOBzxT4w+a9ATSPvRVK3LB1RAJ9S8bg2tOyWHAGW40Zd2dKfw==", "dev": true, "requires": { "handlebars": "4.0.10" @@ -5983,7 +6883,7 @@ "js-yaml": { "version": "3.9.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.9.1.tgz", - "integrity": "sha1-CHdc69/dNZIJ8NKs04PI+GppBKA=", + "integrity": "sha512-CbcG379L1e+mWBnLvHWWeLs8GyV/EMw862uLI3c+GxVyDHWZcjZinwuBd3iW2pgxgIlksW/1vNJa4to+RvDOww==", "dev": true, "requires": { "argparse": "1.0.9", @@ -5999,7 +6899,7 @@ "jschardet": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/jschardet/-/jschardet-1.5.0.tgz", - "integrity": "sha1-ph8xAwalpxGI4bGs0IrdPPuwix4=" + "integrity": "sha512-+Q8JsoEQbrdE+a/gg1F9XO92gcKXgpE5UACqr0sIubjDmBEkd+OOWPGzQeMrWSLxd73r4dHxBeRW7edHu5LmJQ==" }, "jsdom": { "version": "9.12.0", @@ -6299,11 +7199,6 @@ "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=" }, - "lodash.isequal": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=" - }, "lodash.keys": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", @@ -6399,7 +7294,7 @@ "lru-cache": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", - "integrity": "sha1-Yi4y6CSItJJ5EUpPns9F581rulU=", + "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==", "requires": { "pseudomap": "1.0.2", "yallist": "2.1.2" @@ -6698,7 +7593,7 @@ "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "requires": { "brace-expansion": "1.1.8" } @@ -6745,14 +7640,6 @@ "resolved": "https://registry.npmjs.org/mobx/-/mobx-2.7.0.tgz", "integrity": "sha1-zz2C0YwMp/RY2PKiQIF7PcflSgE=" }, - "mobx-react": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/mobx-react/-/mobx-react-4.2.2.tgz", - "integrity": "sha1-25zDyv772DDQWEwRSa9armeCkgE=", - "requires": { - "hoist-non-react-statics": "1.2.0" - } - }, "moment": { "version": "2.18.1", "resolved": "https://registry.npmjs.org/moment/-/moment-2.18.1.tgz", @@ -6854,7 +7741,7 @@ "node-fetch": { "version": "1.7.1", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.1.tgz", - "integrity": "sha1-iZyz0KPJL5UsR/G4dvTIrqvUANU=", + "integrity": "sha512-j8XsFGCLw79vWXkZtMSmmLaOk9z5SQ9bV/tkbZVCqvgwzrjAGq66igobLofHtF63NvMTp2WjytpsNTGKa+XRIQ==", "requires": { "encoding": "0.1.12", "is-stream": "1.1.0" @@ -6982,7 +7869,7 @@ "normalize-package-data": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", - "integrity": "sha1-EvlaMH1YNSB1oEkHuErIvpisAS8=", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", "requires": { "hosted-git-info": "2.5.0", "is-builtin-module": "1.0.0", @@ -7105,92 +7992,6 @@ "mimic-fn": "1.1.0" } }, - "opencollective": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/opencollective/-/opencollective-1.0.3.tgz", - "integrity": "sha1-ruY3K8KBRFg2kMPKja7PwSDdDvE=", - "requires": { - "babel-polyfill": "6.23.0", - "chalk": "1.1.3", - "inquirer": "3.0.6", - "minimist": "1.2.0", - "node-fetch": "1.6.3", - "opn": "4.0.2" - }, - "dependencies": { - "ansi-escapes": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", - "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=" - }, - "babel-polyfill": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.23.0.tgz", - "integrity": "sha1-g2TKYt+Or7gwSZ9pkXdGbDsDSZ0=", - "requires": { - "babel-runtime": "6.25.0", - "core-js": "2.5.0", - "regenerator-runtime": "0.10.5" - } - }, - "core-js": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.0.tgz", - "integrity": "sha1-VpwFCRi+ZIazg3VSAorgRmtxcIY=" - }, - "inquirer": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.0.6.tgz", - "integrity": "sha1-4EqqnQW3o8ubD0B9BDdfBEcZA0c=", - "requires": { - "ansi-escapes": "1.4.0", - "chalk": "1.1.3", - "cli-cursor": "2.1.0", - "cli-width": "2.1.0", - "external-editor": "2.0.4", - "figures": "2.0.0", - "lodash": "4.17.4", - "mute-stream": "0.0.7", - "run-async": "2.3.0", - "rx": "4.1.0", - "string-width": "2.1.1", - "strip-ansi": "3.0.1", - "through": "2.3.8" - } - }, - "node-fetch": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.6.3.tgz", - "integrity": "sha1-3CNO3WSJmC1Y6PDbT2lQKavNjAQ=", - "requires": { - "encoding": "0.1.12", - "is-stream": "1.1.0" - } - }, - "opn": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/opn/-/opn-4.0.2.tgz", - "integrity": "sha1-erwi5kTf9jsKltWrfyeQwPAavJU=", - "requires": { - "object-assign": "4.1.1", - "pinkie-promise": "2.0.1" - } - }, - "regenerator-runtime": { - "version": "0.10.5", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", - "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=" - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "requires": { - "ansi-regex": "2.1.1" - } - } - } - }, "opn": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/opn/-/opn-3.0.3.tgz", @@ -8284,7 +9085,7 @@ "promise": { "version": "7.3.1", "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", - "integrity": "sha1-BktyYCsY+Q8pGSuLG8QY/9Hr078=", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", "requires": { "asap": "2.0.6" } @@ -8414,7 +9215,7 @@ "randomatic": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", - "integrity": "sha1-x6vpzIuHwLqodrGf3oP9RkeX44w=", + "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==", "requires": { "is-number": "3.0.0", "kind-of": "4.0.0" @@ -8798,28 +9599,10 @@ "prop-types": "15.5.10" } }, - "react-native-auto-grow-textinput": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/react-native-auto-grow-textinput/-/react-native-auto-grow-textinput-1.2.0.tgz", - "integrity": "sha512-O+mT2GOrDRzJdg2GbdfuGlO/nn/J8c9pdBCPahLYA8yiAjayAG67XOujGrfuv/wNCF7W94NsYdyfaf2hlOIhYQ==" - }, - "react-native-autogrow-input": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/react-native-autogrow-input/-/react-native-autogrow-input-0.2.1.tgz", - "integrity": "sha512-vWcfqGqzDw4XqRJr4HnHC+dcGAfJDYZiF2B0tBZjtjA6MNSv2TNz5knYZjvLggRgmEflj02r88scvfFputsRig==", - "requires": { - "prop-types": "15.5.10" - } - }, - "react-native-autogrow-textinput": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/react-native-autogrow-textinput/-/react-native-autogrow-textinput-4.1.0.tgz", - "integrity": "sha1-p+WxfrPBarCOMbv7iNkkiO2H8nY=" - }, - "react-native-button": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/react-native-button/-/react-native-button-2.1.0.tgz", - "integrity": "sha1-o54jKSkir+6k974UHdQ+GPG1GHY=", + "react-native-animatable": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/react-native-animatable/-/react-native-animatable-1.2.3.tgz", + "integrity": "sha512-GcIKsSPy9A5VfAGCmivElYwBz/Ds7kawG3CkBDCMFf0fkDXKeHcVffqFe7rUR+5rR31Azvkbmp+tUP+N7kdjyw==", "requires": { "prop-types": "15.5.10" } @@ -8835,11 +9618,6 @@ "integrity": "sha1-XXZC89U60ySgJYk748ZtFqAc2iM=", "dev": true }, - "react-native-console-time-polyfill": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/react-native-console-time-polyfill/-/react-native-console-time-polyfill-0.0.6.tgz", - "integrity": "sha1-eCPYb+g0OcdEgNGxJKkrGnhXGIk=" - }, "react-native-dismiss-keyboard": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/react-native-dismiss-keyboard/-/react-native-dismiss-keyboard-1.0.0.tgz", @@ -8848,7 +9626,7 @@ "react-native-drawer-layout": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/react-native-drawer-layout/-/react-native-drawer-layout-1.3.2.tgz", - "integrity": "sha1-uXQNdmOh3E+IphucbZPS2UjqQm4=", + "integrity": "sha512-fjO0scqbJUfNu2wuEpvywL7DYLXuCXJ2W/zYhWz986rdLytidbys1QGVvkaszHrb4Y7OqO96mTkgpOcP8KWevw==", "requires": { "react-native-dismiss-keyboard": "1.0.0" } @@ -8856,7 +9634,7 @@ "react-native-drawer-layout-polyfill": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/react-native-drawer-layout-polyfill/-/react-native-drawer-layout-polyfill-1.3.2.tgz", - "integrity": "sha1-GSyE16WmuKbSvix9ql5BZFGNDMc=", + "integrity": "sha512-XzPhfLDJrYHru+e8+dFwhf0FtTeAp7JXPpFYezYV6P1nTeA1Tia/kDpFT+O2DWTrBKBEI8FGhZnThrroZmHIxg==", "requires": { "react-native-drawer-layout": "1.3.2" } @@ -8891,15 +9669,10 @@ } } }, - "react-native-form-generator": { - "version": "0.9.9", - "resolved": "https://registry.npmjs.org/react-native-form-generator/-/react-native-form-generator-0.9.9.tgz", - "integrity": "sha1-aKribR6Nw+MAc8zXuymPvf3OG8o=" - }, "react-native-image-picker": { - "version": "0.26.3", - "resolved": "https://registry.npmjs.org/react-native-image-picker/-/react-native-image-picker-0.26.3.tgz", - "integrity": "sha1-CtLu3klQGnBG2ARqc4E2llOcPc0=" + "version": "0.26.4", + "resolved": "https://registry.npmjs.org/react-native-image-picker/-/react-native-image-picker-0.26.4.tgz", + "integrity": "sha512-WZcJGW/06gZZNEUN0Vjeer/78SYNiEKQINernotfZW8EuNe70EUcmOWLMBn4NrOKSdW22iO4zmt0EAcEB9rFVw==" }, "react-native-img-cache": { "version": "1.4.0", @@ -8916,11 +9689,6 @@ } } }, - "react-native-loader": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/react-native-loader/-/react-native-loader-1.1.0.tgz", - "integrity": "sha1-nofojVsKA6JrKFkbI9pzQIoYnkc=" - }, "react-native-loading-spinner-overlay": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/react-native-loading-spinner-overlay/-/react-native-loading-spinner-overlay-0.5.2.tgz", @@ -8956,27 +9724,6 @@ "resolved": "https://registry.npmjs.org/react-native-optimized-flatlist/-/react-native-optimized-flatlist-1.0.1.tgz", "integrity": "sha1-2+6C8gi0i+8jxssm8dXzrFjmdbI=" }, - "react-native-router-flux": { - "version": "4.0.0-beta.21", - "resolved": "https://registry.npmjs.org/react-native-router-flux/-/react-native-router-flux-4.0.0-beta.21.tgz", - "integrity": "sha1-zbs87FsY+rD/24q/OM55B0n2JdA=", - "requires": { - "lodash.isequal": "4.5.0", - "mobx": "3.2.2", - "mobx-react": "4.2.2", - "opencollective": "1.0.3", - "prop-types": "15.5.10", - "react-native-button": "2.1.0", - "react-navigation": "1.0.0-beta.11" - }, - "dependencies": { - "mobx": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/mobx/-/mobx-3.2.2.tgz", - "integrity": "sha1-qmcUWb7e39mIDJSIiaP2K84JJ5w=" - } - } - }, "react-native-svg": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-5.4.1.tgz", @@ -9295,7 +10042,7 @@ "readable-stream": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", "requires": { "core-util-is": "1.0.2", "inherits": "2.0.3", @@ -9577,7 +10324,7 @@ "resolve": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.4.0.tgz", - "integrity": "sha1-p1vgHFPaJdk0qY69DkxKcxL5KoY=", + "integrity": "sha512-aW7sVKPufyHqOmyyLzg/J+8606v5nevBgaliIlV7nUpVMsDnoBGV/cbSLNjZAg9q0Cfd/+easKVKQ8vOu8fn1Q==", "dev": true, "requires": { "path-parse": "1.0.5" @@ -9653,11 +10400,6 @@ "is-promise": "2.1.0" } }, - "rx": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/rx/-/rx-4.1.0.tgz", - "integrity": "sha1-pfE/957zt0D+MKqAP7CfmIBdR4I=" - }, "rx-lite": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", @@ -10157,7 +10899,7 @@ "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha1-q5Pyeo3BPSjKyBXEYhQ6bZASrp4=", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "requires": { "is-fullwidth-code-point": "2.0.0", "strip-ansi": "4.0.0" diff --git a/package.json b/package.json index 6efc64f71..deb8dcec2 100644 --- a/package.json +++ b/package.json @@ -22,22 +22,16 @@ "react-emojione": "^3.1.10", "react-native": "0.46.1", "react-native-action-button": "^2.7.2", - "react-native-auto-grow-textinput": "^1.2.0", - "react-native-autogrow-input": "^0.2.1", - "react-native-autogrow-textinput": "^4.1.0", + "react-native-animatable": "^1.2.3", "react-native-card-view": "0.0.3", - "react-native-console-time-polyfill": "0.0.6", "react-native-easy-markdown": "git+https://github.com/lappalj4/react-native-easy-markdown.git", "react-native-fetch-blob": "^0.10.8", - "react-native-form-generator": "^0.9.9", - "react-native-image-picker": "^0.26.3", + "react-native-image-picker": "^0.26.4", "react-native-img-cache": "^1.4.0", - "react-native-loader": "^1.1.0", - "react-native-loading-spinner-overlay": "^0.5.1", + "react-native-loading-spinner-overlay": "^0.5.2", "react-native-meteor": "^1.1.0", "react-native-navigation": "^1.1.193", "react-native-optimized-flatlist": "^1.0.1", - "react-native-router-flux": "^4.0.0-beta.18", "react-native-svg": "^5.4.1", "react-native-svg-image": "^1.1.4", "react-native-vector-icons": "^4.3.0", diff --git a/storybook/stories/Avatar.js b/storybook/stories/Avatar.js new file mode 100644 index 000000000..204a38bd6 --- /dev/null +++ b/storybook/stories/Avatar.js @@ -0,0 +1,13 @@ +import React from 'react'; +import { ScrollView } from 'react-native'; + +import Avatar from '../../app/components/avatar'; + +export default ( + + + + + + +); diff --git a/storybook/stories/index.js b/storybook/stories/index.js index 005cce830..8575d1a64 100644 --- a/storybook/stories/index.js +++ b/storybook/stories/index.js @@ -7,7 +7,9 @@ import { storiesOf } from '@storybook/react-native'; // import { linkTo } from '@storybook/addon-links'; import DirectMessage from './Channels/DirectMessage'; +import Avatar from './Avatar'; +storiesOf('Avatar', module).add('avatar', () => Avatar); storiesOf('Channel Cell', module).add('Direct Messages', () => DirectMessage); // storiesOf('Welcome', module).add('to Storybook', () => );