diff --git a/src/components/iconButton/view/iconButtonView.js b/src/components/iconButton/view/iconButtonView.js index c70415827..b93f7a70a 100644 --- a/src/components/iconButton/view/iconButtonView.js +++ b/src/components/iconButton/view/iconButtonView.js @@ -1,5 +1,5 @@ import React, { Fragment } from 'react'; -import { TouchableHighlight } from 'react-native'; +import { TouchableHighlight, ActivityIndicator } from 'react-native'; import { Icon } from '../../icon'; import styles from './iconButtonStyles'; @@ -22,28 +22,33 @@ const IconButton = ({ onPress, size, style, + isLoading, }) => ( onPress && onPress()} + onPress={() => !isLoading && onPress && onPress()} underlayColor={backgroundColor || 'white'} disabled={disabled} > - + {!isLoading ? ( + + ) : ( + + )} ); diff --git a/src/components/profileEditForm/profileEditFormView.js b/src/components/profileEditForm/profileEditFormView.js index 5f0407bac..7dbb5e83a 100644 --- a/src/components/profileEditForm/profileEditFormView.js +++ b/src/components/profileEditForm/profileEditFormView.js @@ -15,12 +15,15 @@ import { IconButton } from '../iconButton'; import styles from './profileEditFormStyles'; const ProfileEditFormView = ({ + avatarUrl, coverUrl, isDarkTheme, formData, intl, handleOnItemChange, showImageUploadActions, + isLoading, + handleOnSubmit, ...props }) => ( @@ -29,8 +32,9 @@ const ProfileEditFormView = ({ style={styles.saveButton} iconType="MaterialIcons" name="save" - onPress={() => alert('asd')} + onPress={handleOnSubmit} size={30} + isLoading={isLoading} /> { - const { dispatch, currentUsername } = this.props; + const { + dispatch, + currentUsername: { name }, + } = this.props; - const routeName = currentUsername === username ? ROUTES.TABBAR.PROFILE : ROUTES.SCREENS.PROFILE; + const routeName = name === username ? ROUTES.TABBAR.PROFILE : ROUTES.SCREENS.PROFILE; const navigateAction = NavigationActions.navigate({ routeName, @@ -42,11 +45,24 @@ class UserAvatarView extends Component { }; render() { - const { username, size, style, disableSize, noAction, avatarUrl } = this.props; + const { + username, + size, + style, + disableSize, + noAction, + avatarUrl, + currentUsername: { name, avatar }, + } = this.props; const imageSize = size === 'xl' ? 'large' : 'small'; let _size; const _avatar = username - ? { uri: avatarUrl || `https://steemitimages.com/u/${username}/avatar/${imageSize}` } + ? { + uri: + avatarUrl || name === username + ? avatar + : `https://steemitimages.com/u/${username}/avatar/${imageSize}`, + } : DEFAULT_IMAGE; if (!disableSize) { @@ -73,7 +89,7 @@ class UserAvatarView extends Component { } const mapStateToProps = state => ({ - currentUsername: state.account.currentAccount.name, + currentUsername: state.account.currentAccount, }); export default connect(mapStateToProps)(UserAvatarView); diff --git a/src/containers/profileEditContainer.js b/src/containers/profileEditContainer.js index f20786628..008e2bc37 100644 --- a/src/containers/profileEditContainer.js +++ b/src/containers/profileEditContainer.js @@ -4,8 +4,14 @@ import { connect } from 'react-redux'; import { injectIntl } from 'react-intl'; import ImagePicker from 'react-native-image-crop-picker'; import get from 'lodash/get'; +import { withNavigation } from 'react-navigation'; import { uploadImage } from '../providers/esteem/esteem'; + +import { profileUpdate, getUser } from '../providers/steem/dsteem'; +import { getUserDataWithUsername } from '../realm/realm'; +import { updateCurrentAccount } from '../redux/actions/accountAction'; + // import ROUTES from '../constants/routeNames'; const FORM_DATA = [ @@ -44,7 +50,7 @@ class ProfileEditContainer extends Component { constructor(props) { super(props); this.state = { - isUploading: false, + isLoading: false, about: get(props.currentAccount, 'about.profile.about'), name: get(props.currentAccount, 'about.profile.name'), location: get(props.currentAccount, 'about.profile.location'), @@ -61,15 +67,17 @@ class ProfileEditContainer extends Component { _handleOnSave = () => {}; _handleOnItemChange = (val, item) => { - console.log(val, item); + this.setState({ [item]: val }); }; _uploadImage = (media, action) => { const { intl } = this.props; + + this.setState({ isLoading: true }); uploadImage(media) .then(res => { if (res.data && res.data.url) { - this.setState({ [action]: res.data.url, isUploading: false }); + this.setState({ [action]: res.data.url, isLoading: false }); } }) .catch(error => { @@ -81,7 +89,7 @@ class ProfileEditContainer extends Component { error.message || error.toString(), ); } - this.setState({ isUploading: false }); + this.setState({ isLoading: false }); }); }; @@ -118,7 +126,7 @@ class ProfileEditContainer extends Component { }; _handleMediaOnSelected = (media, action) => { - this.setState({ isUploading: true }, () => { + this.setState({ isLoading: true }, () => { this._uploadImage(media, action); }); }; @@ -138,25 +146,58 @@ class ProfileEditContainer extends Component { } }; + _handleOnSubmit = async () => { + const { currentAccount, pinCode, dispatch, navigation } = this.props; + const { name, location, website, about, coverUrl, avatarUrl } = this.state; + + await this.setState({ isLoading: true }); + + const params = { + profile_image: avatarUrl, + cover_image: coverUrl, + name, + website, + about, + location, + }; + + await profileUpdate(params, pinCode, currentAccount) + .then(async () => { + const _currentAccount = { ...currentAccount }; + _currentAccount.about.profile = { ...params }; + _currentAccount.display_name = name; + + dispatch(updateCurrentAccount(_currentAccount)); + + navigation.goBack(); + }) + .catch(error => { + Alert.alert(error); + }); + + this.setState({ isLoading: false }); + }; + render() { const { children, currentAccount, isDarkTheme } = this.props; - const { isUploading, name, location, website, about, coverUrl, avatarUrl } = this.state; + const { isLoading, name, location, website, about, coverUrl, avatarUrl } = this.state; return ( children && children({ + about, + avatarUrl, + coverUrl, currentAccount, - isDarkTheme, formData: FORM_DATA, - isUploading, handleMediaAction: this._handleMediaAction, handleOnItemChange: this._handleOnItemChange, - name, + handleOnSubmit: this._handleOnSubmit, + isDarkTheme, + isLoading, location, + name, website, - about, - coverUrl, - avatarUrl, }) ); } @@ -165,6 +206,7 @@ class ProfileEditContainer extends Component { const mapStateToProps = state => ({ currentAccount: state.account.currentAccount, isDarkTheme: state.application.isDarkTheme, + pinCode: state.application.pin, }); -export default connect(mapStateToProps)(injectIntl(ProfileEditContainer)); +export default connect(mapStateToProps)(injectIntl(withNavigation(ProfileEditContainer))); diff --git a/src/providers/steem/dsteem.js b/src/providers/steem/dsteem.js index 80521035a..62579b7ff 100644 --- a/src/providers/steem/dsteem.js +++ b/src/providers/steem/dsteem.js @@ -1,3 +1,4 @@ +/* eslint-disable camelcase */ import { Client, PrivateKey } from 'dsteem'; import steemConnect from 'steemconnect'; import Config from 'react-native-config'; @@ -231,7 +232,7 @@ export const ignoreUser = async (currentAccount, pin, data) => { const key = getAnyPrivateKey(currentAccount.local, digitPinCode); if (currentAccount.local.authType === AUTH_TYPE.STEEM_CONNECT) { - const token = decryptKey(currentAccount.local.accessToken, digitPinCode); + const token = decryptKey(get(currentAccount, 'local.accessToken'), digitPinCode); const api = steemConnect.Initialize({ accessToken: token, }); @@ -373,7 +374,7 @@ export const deleteComment = (currentAccount, pin, permlink) => { const key = getAnyPrivateKey(currentAccount.local, digitPinCode); if (currentAccount.local.authType === AUTH_TYPE.STEEM_CONNECT) { - const token = decryptKey(currentAccount.local.accessToken, digitPinCode); + const token = decryptKey(get(currentAccount, 'local.accessToken'), digitPinCode); const api = steemConnect.Initialize({ accessToken: token, }); @@ -453,7 +454,7 @@ const _vote = async (currentAccount, pin, author, permlink, weight) => { const key = getAnyPrivateKey(currentAccount.local, digitPinCode); if (currentAccount.local.authType === AUTH_TYPE.STEEM_CONNECT) { - const token = decryptKey(currentAccount.local.accessToken, digitPinCode); + const token = decryptKey(get(currentAccount, 'local.accessToken'), digitPinCode); const api = steemConnect.Initialize({ accessToken: token, }); @@ -797,7 +798,7 @@ export const unfollowUser = async (currentAccount, pin, data) => { const key = getAnyPrivateKey(currentAccount.local, digitPinCode); if (currentAccount.local.authType === AUTH_TYPE.STEEM_CONNECT) { - const token = decryptKey(currentAccount.local.accessToken, digitPinCode); + const token = decryptKey(get(currentAccount, 'local.accessToken'), digitPinCode); const api = steemConnect.Initialize({ accessToken: token, }); @@ -1163,6 +1164,61 @@ export const boost = (currentAccount, pinCode, point, permlink, author) => { return Promise.reject(new Error('Something went wrong!')); }; +export const profileUpdate = async (params, pin, currentAccount) => { + const digitPinCode = getDigitPinCode(pin); + const key = getActiveKey(get(currentAccount, 'local'), digitPinCode); + + if (get(currentAccount, 'local.authType') === AUTH_TYPE.STEEM_CONNECT) { + // TODO: will do it + const token = decryptKey(get(currentAccount, 'local.accessToken'), digitPinCode); + const api = steemConnect.Initialize({ + accessToken: token, + }); + + const _params = { + account: get(currentAccount, 'name'), + memo_key: get(currentAccount, 'memo_key'), + json_metadata: jsonStringify({ profile: params }), + }; + + const opArray = [['account_update', _params]]; + + return api.broadcast(opArray).then(resp => resp.result); + } + + if (key) { + const opArray = [ + [ + 'account_update', + { + account: get(currentAccount, 'name'), + memo_key: get(currentAccount, 'memo_key'), + json_metadata: jsonStringify({ profile: params }), + }, + ], + ]; + + const privateKey = PrivateKey.fromString(key); + + return new Promise((resolve, reject) => { + client.broadcast + .sendOperations(opArray, privateKey) + .then(result => { + resolve(result); + }) + .catch(error => { + if (get(error, 'jse_info.code') === 4030100) { + error.message = + 'We noticed that your device has incorrect date or time. Please fix Date & Time or Set Automatically and try again.'; + } + reject(error); + }); + }); + } + + return Promise.reject(new Error('You dont have permission!')); +}; + // HELPERS const getAnyPrivateKey = (local, pin) => { diff --git a/src/screens/home/screen/homeScreen.js b/src/screens/home/screen/homeScreen.js index ebc439670..9a8de3b46 100644 --- a/src/screens/home/screen/homeScreen.js +++ b/src/screens/home/screen/homeScreen.js @@ -23,8 +23,6 @@ class HomeScreen extends PureComponent { render() { const { currentAccount, intl, isLoggedIn } = this.props; - let tag; - return (
@@ -50,7 +48,7 @@ class HomeScreen extends PureComponent { diff --git a/src/screens/profileEdit/screen/profileEditScreen.js b/src/screens/profileEdit/screen/profileEditScreen.js index a42ceb087..91c6d308d 100644 --- a/src/screens/profileEdit/screen/profileEditScreen.js +++ b/src/screens/profileEdit/screen/profileEditScreen.js @@ -49,6 +49,8 @@ class ProfileEditScreen extends PureComponent { about, avatarUrl, coverUrl, + isLoading, + handleOnSubmit, }) => ( this._showImageUploadActions('coverUrl')} handleOnItemChange={handleOnItemChange} + isLoading={isLoading} + handleOnSubmit={handleOnSubmit} />