diff --git a/src/components/icon/view/iconView.js b/src/components/icon/view/iconView.js index 8cdb5c864..b0e27928f 100644 --- a/src/components/icon/view/iconView.js +++ b/src/components/icon/view/iconView.js @@ -31,7 +31,7 @@ class IconView extends Component { }; _getIcon = () => { - const { iconType } = this.props; + const { iconType, children } = this.props; const name = this._getIconName(); switch (iconType) { @@ -40,11 +40,11 @@ class IconView extends Component { case 'FontAwesome': return ; case 'SimpleLineIcons': - return {this.props.children}; + return {children}; case 'MaterialCommunityIcons': return ( - {this.props.children} + {children} ); default: diff --git a/src/components/index.js b/src/components/index.js index bc9416943..8f104d8cb 100644 --- a/src/components/index.js +++ b/src/components/index.js @@ -9,6 +9,7 @@ import { NumericKeyboard } from './numericKeyboard'; import { PinAnimatedInput } from './pinAnimatedInput'; import { SideMenu } from './sideMenu'; import Modal from './modal'; +import Icon from './icon'; export { Logo, @@ -24,4 +25,5 @@ export { PinAnimatedInput, SideMenu, Modal, + Icon, }; diff --git a/src/components/sideMenu/container/sideMenuContainer.js b/src/components/sideMenu/container/sideMenuContainer.js index 078847b15..3d821d617 100644 --- a/src/components/sideMenu/container/sideMenuContainer.js +++ b/src/components/sideMenu/container/sideMenuContainer.js @@ -1,10 +1,20 @@ import React, { Component } from 'react'; import { connect } from 'react-redux'; +// Actions import { getUserData } from '../../../realm/realm'; +import { switchAccount } from '../../../providers/steem/auth'; +import { updateCurrentAccount } from '../../../redux/actions/accountAction'; +import { openPinCodeModal } from '../../../redux/actions/applicationActions'; + +// Constanst +import { default as ROUTES } from '../../../constants/routeNames'; + // Component import { SideMenuView } from '..'; +const DEFAULT_IMAGE = require('../../../assets/esteem.png'); + /* * Props Name Description *@props --> props name navigation coming from react-navigation @@ -26,7 +36,15 @@ class SideMenuContainer extends Component { getUserData().then((userData) => { userData.forEach((element) => { - accounts.push({ name: element.username, image: 'test' }); + accounts.push({ + name: `@${element.username}`, + image: element.avatar ? { uri: element.avatar } : DEFAULT_IMAGE, + }); + }); + accounts.push({ + name: 'Add Account', + route: ROUTES.SCREENS.LOGIN, + icon: 'plus-square-o', }); this.setState({ accounts }); }); @@ -36,7 +54,19 @@ class SideMenuContainer extends Component { _navigateToRoute = (route = null) => { const { navigation } = this.props; - navigation.navigate(route); + if (route) { + navigation.navigate(route); + } + }; + + _switchAccount = (username = null) => { + const { dispatch } = this.props; + + username = username.slice(1); + switchAccount(username).then((accountData) => { + dispatch(updateCurrentAccount(accountData)); + dispatch(openPinCodeModal()); + }); }; render() { @@ -50,14 +80,15 @@ class SideMenuContainer extends Component { userAvatar={null} accounts={accounts} currentAccount={currentAccount} + switchAccount={this._switchAccount} /> ); } } const mapStateToProps = state => ({ - isLoggedIn: state.application.isLoggedIn, - currentAccount: state.account.currentAccount, + isLoggedIn: state.application.isLoggedIn || false, + currentAccount: state.account.currentAccount || {}, }); export default connect(mapStateToProps)(SideMenuContainer); diff --git a/src/components/sideMenu/view/sideMenuStyles.js b/src/components/sideMenu/view/sideMenuStyles.js index 7e5172ee7..d21b26e5e 100644 --- a/src/components/sideMenu/view/sideMenuStyles.js +++ b/src/components/sideMenu/view/sideMenuStyles.js @@ -1,11 +1,9 @@ -import { StatusBar, Platform } from 'react-native'; import EStyleSheet from 'react-native-extended-stylesheet'; export default EStyleSheet.create({ container: { flex: 1, flexDirection: 'column', - marginTop: Platform.OS === 'android' && StatusBar.currentHeight, }, headerView: { flex: 1, @@ -26,6 +24,9 @@ export default EStyleSheet.create({ userAvatar: { marginLeft: '$deviceWidth / 10', }, + otherUserAvatar: { + marginLeft: -15, + }, userInfoView: { alignSelf: 'flex-end', marginLeft: 15, @@ -73,4 +74,7 @@ export default EStyleSheet.create({ flex: 1, flexDirection: 'row', }, + addAccountIcon: { + padding: 10, + }, }); diff --git a/src/components/sideMenu/view/sideMenuView.js b/src/components/sideMenu/view/sideMenuView.js index dcfa97d9a..f3c6e7c47 100644 --- a/src/components/sideMenu/view/sideMenuView.js +++ b/src/components/sideMenu/view/sideMenuView.js @@ -3,11 +3,10 @@ import { View, Text } from 'react-native'; import { Thumbnail, List, ListItem, Container, } from 'native-base'; -import Icon from 'react-native-vector-icons/FontAwesome'; import LinearGradient from 'react-native-linear-gradient'; // Components -import { IconButton } from '../..'; +import { Icon, IconButton } from '../..'; // Constants import { default as MENU } from '../../../constants/sideMenuItems'; @@ -54,10 +53,32 @@ class SideMenuView extends Component { } }; + _getNameOfUser = () => { + const { currentAccount } = this.props; + if (Object.keys(currentAccount).length === 0) return ''; + const jsonMetadata = JSON.parse(currentAccount.json_metadata); + if (Object.keys(jsonMetadata).length !== 0) { + return jsonMetadata.profile.name; + } + return currentAccount.name; + }; + + _getUserAvatar = () => { + const { currentAccount } = this.props; + if (Object.keys(currentAccount).length === 0) return DEFAULT_IMAGE; + const jsonMetadata = JSON.parse(currentAccount.json_metadata); + if (Object.keys(jsonMetadata).length !== 0) { + return { uri: jsonMetadata.profile.cover_image }; + } + return DEFAULT_IMAGE; + }; + // Component Functions render() { - const { userAvatar, navigateToRoute, currentAccount } = this.props; + const { + navigateToRoute, currentAccount, isLoggedIn, switchAccount, + } = this.props; const { menuItems, isAddAccountIconActive } = this.state; // TODO: Change dummy data return ( @@ -68,23 +89,28 @@ class SideMenuView extends Component { colors={['#357ce6', '#2d5aa0']} style={styles.headerView} > - - - - Mustafa - @mistikk + {isLoggedIn && ( + + + + {this._getNameOfUser()} + {`@${currentAccount.name}`} + + + {/* TODO: delete android name */} + this._handleOnPressAddAccountIcon()} + style={styles.addAccountIcon} + /> + - - {/* TODO: delete android name */} - this._handleOnPressAddAccountIcon()} - /> - - + )} navigateToRoute(item.route)} + onPress={() => { + if (item.route) { + navigateToRoute(item.route); + } else { + switchAccount(item.name); + } + }} > - + {item.icon && } + {item.image && ( + + )} {item.name} )} diff --git a/src/constants/sideMenuItems.js b/src/constants/sideMenuItems.js index 8de9905bb..b0eb3475d 100644 --- a/src/constants/sideMenuItems.js +++ b/src/constants/sideMenuItems.js @@ -36,18 +36,18 @@ const authMenuItems = [ route: 'Settings', icon: 'gear', }, - { - name: 'LoginTest', - route: ROUTES.SCREENS.LOGIN, - icon: 'user-o', - }, ]; const noAuthMenuItems = [ { - name: 'Login', + name: 'Add Account', route: ROUTES.SCREENS.LOGIN, - icon: 'user-o', + icon: 'plus-square-o', + }, + { + name: 'Settings', + route: 'Settings', + icon: 'gear', }, ]; diff --git a/src/providers/steem/auth.js b/src/providers/steem/auth.js index 2e340be35..01432c4a7 100644 --- a/src/providers/steem/auth.js +++ b/src/providers/steem/auth.js @@ -7,6 +7,7 @@ import { updateUserData, setPinCode, getPinCode, + updateCurrentUsername, } from '../../realm/realm'; import { encryptKey, decryptKey } from '../../utils/crypto'; import steemConnect from './steemConnectAPI'; @@ -21,6 +22,7 @@ export const Login = (username, password) => { posting: null, }; let loginFlag = false; + let avatar = ''; return new Promise((resolve, reject) => { // Get user account data from STEEM Blockchain @@ -53,9 +55,14 @@ export const Login = (username, password) => { } }); + const jsonMetadata = JSON.parse(account.json_metadata); + if (Object.keys(jsonMetadata).length !== 0) { + avatar = jsonMetadata.profile.cover_image; + } if (loginFlag) { const userData = { username, + avatar, authType: 'masterKey', masterKey: '', postingKey: '', @@ -85,10 +92,17 @@ export const Login = (username, password) => { export const loginWithSC2 = async (accessToken) => { await steemConnect.setAccessToken(accessToken); const account = await steemConnect.me(); + let avatar = ''; return new Promise((resolve, reject) => { + const jsonMetadata = JSON.parse(account.json_metadata); + if (Object.keys(jsonMetadata).length !== 0) { + avatar = jsonMetadata.profile.cover_image; + } + const userData = { username: account.account.name, + avatar, authType: 'steemConnect', masterKey: '', postingKey: '', @@ -99,6 +113,7 @@ export const loginWithSC2 = async (accessToken) => { const authData = { isLoggedIn: true, + currentUsername: account.account.name, }; if (isLoggedInUser(account.account.name)) { @@ -154,6 +169,7 @@ export const setUserDataWithPinCode = data => new Promise((resolve, reject) => { .then(() => { const authData = { isLoggedIn: true, + currentUsername: userData.username, }; setAuthStatus(authData) @@ -227,6 +243,7 @@ export const verifyPinCode = async (data) => { if (loginFlag) { const authData = { isLoggedIn: true, + currentUsername: data.username, }; const response = { accessToken: decryptKey(userData.accessToken, data.pinCode), @@ -249,6 +266,20 @@ export const verifyPinCode = async (data) => { }); }; +export const switchAccount = username => new Promise((resolve, reject) => { + getAccount(username) + .then((result) => { + const account = result[0]; + updateCurrentUsername(username).then(() => { + resolve(account); + }).catch(() => { + reject(new Error('Unknown error, please contact to eSteem.')); + }); + }).catch(() => { + reject(new Error('Unknown error, please contact to eSteem.')); + }); +}); + const getPrivateKeys = (username, password) => ({ active: dsteem.PrivateKey.fromLogin(username, password, 'active'), memo: dsteem.PrivateKey.fromLogin(username, password, 'memo'), diff --git a/src/realm/realm.js b/src/realm/realm.js index 218a57bc5..836a28adc 100644 --- a/src/realm/realm.js +++ b/src/realm/realm.js @@ -8,6 +8,7 @@ const userSchema = { name: USER_SCHEMA, properties: { username: { type: 'string' }, + avatar: { type: 'string' }, authType: { type: 'string' }, postingKey: { type: 'string' }, activeKey: { type: 'string' }, @@ -22,6 +23,7 @@ const authSchema = { properties: { isLoggedIn: { type: 'bool', default: false }, pinCode: { type: 'string' }, + currentUsername: { type: 'string' }, }, }; @@ -104,7 +106,7 @@ export const getAuthStatus = () => new Promise((resolve, reject) => { try { const auth = realm.objects(AUTH_SCHEMA); if (auth['0']) { - resolve(auth['0'].isLoggedIn); + resolve(auth['0']); } else { resolve(false); } @@ -116,8 +118,6 @@ export const getAuthStatus = () => new Promise((resolve, reject) => { export const setAuthStatus = authStatus => new Promise((resolve, reject) => { try { const auth = realm.objects(AUTH_SCHEMA); - const test = Array.from(auth); - const test1 = Array.from(auth).length; realm.write(() => { if (Array.from(auth).length > 0) { auth[0].isLoggedIn = authStatus.isLoggedIn; @@ -132,6 +132,28 @@ export const setAuthStatus = authStatus => new Promise((resolve, reject) => { } }); +export const updateCurrentUsername = username => new Promise((resolve, reject) => { + try { + const auth = realm.objects(AUTH_SCHEMA); + realm.write(() => { + if (Array.from(auth).length > 0) { + auth[0].currentUsername = username; + resolve(auth[0]); + } else { + const authData = { + isLoggedIn: false, + pinCode: '', + currentUsername: username, + }; + realm.create(AUTH_SCHEMA, { ...authData }); + resolve(authData); + } + }); + } catch (error) { + reject(error); + } +}); + export const setPinCode = pinCode => new Promise((resolve, reject) => { try { const auth = realm.objects(AUTH_SCHEMA); diff --git a/src/screens/authorProfile/screen/authorScreen.js b/src/screens/authorProfile/screen/authorScreen.js index 66f5f675b..2e984d53e 100644 --- a/src/screens/authorProfile/screen/authorScreen.js +++ b/src/screens/authorProfile/screen/authorScreen.js @@ -104,7 +104,7 @@ class AuthorScreen extends Component { let user; await getAuthStatus().then((res) => { - isLoggedIn = res; + isLoggedIn = res.isLoggedIn; }); if (isLoggedIn) { diff --git a/src/screens/home/screen/homeScreen.js b/src/screens/home/screen/homeScreen.js index eed9be561..81b1da492 100644 --- a/src/screens/home/screen/homeScreen.js +++ b/src/screens/home/screen/homeScreen.js @@ -52,7 +52,7 @@ export default class HomeScreen extends PureComponent { let isLoggedIn; await getAuthStatus().then((res) => { - isLoggedIn = res; + isLoggedIn = res.isLoggedIn; }); if (isLoggedIn) { diff --git a/src/screens/post/container/postContainer.js b/src/screens/post/container/postContainer.js index 717b3070b..db8c6ffbf 100644 --- a/src/screens/post/container/postContainer.js +++ b/src/screens/post/container/postContainer.js @@ -60,7 +60,7 @@ class PostContainer extends Component { let isLoggedIn; await getAuthStatus().then((res) => { - isLoggedIn = res; + isLoggedIn = res.isLoggedIn; }); if (isLoggedIn) { diff --git a/src/screens/profile/_profile.js b/src/screens/profile/_profile.js index dd99c10b1..81ca1ed62 100644 --- a/src/screens/profile/_profile.js +++ b/src/screens/profile/_profile.js @@ -75,7 +75,7 @@ class ProfilePage extends React.Component { let about; await getAuthStatus().then((res) => { - isLoggedIn = res; + isLoggedIn = res.isLoggedIn; }); if (isLoggedIn) { diff --git a/src/screens/profile/container/profileContainer.js b/src/screens/profile/container/profileContainer.js index 945775f5e..0c46e6393 100644 --- a/src/screens/profile/container/profileContainer.js +++ b/src/screens/profile/container/profileContainer.js @@ -147,7 +147,7 @@ class ProfileContainer extends Component { let username; await getAuthStatus().then((res) => { - isLoggedIn = res; + isLoggedIn = res.isLoggedIn; }); if (selectedUser) { diff --git a/src/screens/splash/container/splashContainer.js b/src/screens/splash/container/splashContainer.js index 648d529a0..d90fea694 100644 --- a/src/screens/splash/container/splashContainer.js +++ b/src/screens/splash/container/splashContainer.js @@ -26,13 +26,15 @@ class SplashContainer extends Component { const { navigation, dispatch } = this.props; getAuthStatus().then((res) => { - if (res) { + if (res.isLoggedIn) { getUserData().then((response) => { if (response.length > 0) { response.forEach((accountData) => { - dispatch(addOtherAccount({ username: accountData.username })); + dispatch( + addOtherAccount({ username: accountData.username, avatar: accountData.avatar }), + ); }); - getAccount(response[response.length - 1].username).then((accountData) => { + getAccount(res.currentUsername).then((accountData) => { dispatch(updateCurrentAccount(...accountData)); dispatch(activeApplication()); dispatch(login()); diff --git a/src/screens/wallet/wallet.js b/src/screens/wallet/wallet.js index c1ceef3a4..f55e65d80 100644 --- a/src/screens/wallet/wallet.js +++ b/src/screens/wallet/wallet.js @@ -42,7 +42,7 @@ class WalletPage extends Component { let globalProperties; await getAuthStatus().then((res) => { - isLoggedIn = res; + isLoggedIn = res.isLoggedIn; }); if (isLoggedIn) { diff --git a/src/utils/realm.js b/src/utils/realm.js index e5daaeeaa..2e93bc6e5 100644 --- a/src/utils/realm.js +++ b/src/utils/realm.js @@ -2,7 +2,7 @@ import { getUserData, getAuthStatus } from '../realm/realm'; export const getUserIsLoggedIn = () => { getAuthStatus() - .then(res => res) + .then(res => res.isLoggedIn) .catch(() => null); };