mirror of
https://github.com/ecency/ecency-mobile.git
synced 2024-12-19 11:21:41 +03:00
Merge pull request #762 from esteemapp/feature/transfer
Feature/transfer
This commit is contained in:
commit
b7e5d692b7
@ -89,7 +89,6 @@ class BasicHeaderView extends Component {
|
||||
isLoading,
|
||||
isLoggedIn,
|
||||
isModalHeader,
|
||||
isPostSending,
|
||||
rightButtonText,
|
||||
isPreviewActive,
|
||||
isReply,
|
||||
|
@ -4,7 +4,6 @@ export default EStyleSheet.create({
|
||||
container: {
|
||||
marginVertical: 15,
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
paddingHorizontal: 16,
|
||||
},
|
||||
fitContent: {
|
||||
@ -12,9 +11,9 @@ export default EStyleSheet.create({
|
||||
},
|
||||
iconTextWrapper: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
alignSelf: 'center',
|
||||
alignItems: 'center',
|
||||
alignItems: 'flex-start',
|
||||
flex: 5,
|
||||
},
|
||||
iconWrapper: {
|
||||
alignSelf: 'center',
|
||||
@ -29,8 +28,9 @@ export default EStyleSheet.create({
|
||||
},
|
||||
rightTextWrapper: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'center',
|
||||
justifyContent: 'flex-end',
|
||||
alignSelf: 'center',
|
||||
flex: 5,
|
||||
},
|
||||
text: {
|
||||
fontFamily: '$primaryFont',
|
||||
@ -74,4 +74,7 @@ export default EStyleSheet.create({
|
||||
justifyContent: 'center',
|
||||
alignSelf: 'center',
|
||||
},
|
||||
dropdownWrapper: {
|
||||
flex: 1,
|
||||
},
|
||||
});
|
||||
|
@ -4,6 +4,7 @@ import { View, Text } from 'react-native';
|
||||
// Components
|
||||
import GrayWrapper from '../grayWrapper/grayWrapperView';
|
||||
import { Icon } from '../../../icon';
|
||||
import { DropdownButton } from '../../../dropdownButton';
|
||||
|
||||
// Styles
|
||||
import styles from './walletLineItemStyles';
|
||||
@ -23,6 +24,9 @@ const WalletLineItem = ({
|
||||
textColor,
|
||||
index,
|
||||
style,
|
||||
dropdown,
|
||||
dropdownOptions,
|
||||
onDropdownSelect,
|
||||
}) => (
|
||||
<GrayWrapper isGray={index && index % 2 !== 0}>
|
||||
<View style={[styles.container, fitContent && styles.fitContent, style]}>
|
||||
@ -73,6 +77,17 @@ const WalletLineItem = ({
|
||||
</Text>
|
||||
</View>
|
||||
)}
|
||||
{dropdown && (
|
||||
<View style={styles.dropdownWrapper}>
|
||||
<DropdownButton
|
||||
isHasChildIcon
|
||||
iconName="arrow-drop-down"
|
||||
options={dropdownOptions}
|
||||
noHighlight
|
||||
onSelect={onDropdownSelect}
|
||||
/>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
</GrayWrapper>
|
||||
);
|
||||
|
@ -52,6 +52,8 @@ class TransactionView extends PureComponent {
|
||||
{transactions
|
||||
&& transactions.map((item, index) => {
|
||||
const transactionData = groomingTransactionData(item, steemPerMVests, formatNumber);
|
||||
if (transactionData.length === 0) return null;
|
||||
|
||||
const value = transactionData.value.split(' ');
|
||||
|
||||
return (
|
||||
|
1
src/components/transferFormItem/index.js
Normal file
1
src/components/transferFormItem/index.js
Normal file
@ -0,0 +1 @@
|
||||
export { default as TransferFormItem } from './view/transferFormItemView';
|
@ -0,0 +1,21 @@
|
||||
import EStyleSheet from 'react-native-extended-stylesheet';
|
||||
|
||||
export default EStyleSheet.create({
|
||||
container: {
|
||||
flexDirection: 'row',
|
||||
paddingHorizontal: 20,
|
||||
},
|
||||
leftPart: {
|
||||
flex: 1,
|
||||
padding: 10,
|
||||
justifyContent: 'center',
|
||||
color: '$primaryBlack',
|
||||
},
|
||||
text: {
|
||||
color: '$primaryBlack',
|
||||
},
|
||||
rightPart: {
|
||||
flex: 2,
|
||||
padding: 10,
|
||||
},
|
||||
});
|
17
src/components/transferFormItem/view/transferFormItemView.js
Normal file
17
src/components/transferFormItem/view/transferFormItemView.js
Normal file
@ -0,0 +1,17 @@
|
||||
import React from 'react';
|
||||
import { View, Text } from 'react-native';
|
||||
import styles from './transferFormItemStyles';
|
||||
|
||||
/* Props
|
||||
* ------------------------------------------------
|
||||
* @prop { type } name - Description....
|
||||
*/
|
||||
|
||||
const TransferFormItemView = ({ rightComponent, label }) => (
|
||||
<View style={styles.container}>
|
||||
<View style={styles.leftPart}>{label && <Text style={styles.text}>{label}</Text>}</View>
|
||||
<View style={styles.rightPart}>{rightComponent && rightComponent()}</View>
|
||||
</View>
|
||||
);
|
||||
|
||||
export default TransferFormItemView;
|
@ -138,7 +138,9 @@ class WalletContainer extends Component {
|
||||
};
|
||||
|
||||
render() {
|
||||
const { currentAccount, selectedUser, isDarkTheme } = this.props;
|
||||
const {
|
||||
currentAccount, selectedUser, isDarkTheme, setPinCodeState,
|
||||
} = this.props;
|
||||
const { walletData, isClaiming, isRefreshing } = this.state;
|
||||
|
||||
return (
|
||||
@ -151,6 +153,7 @@ class WalletContainer extends Component {
|
||||
handleOnWalletRefresh={this._handleOnWalletRefresh}
|
||||
isRefreshing={isRefreshing}
|
||||
isDarkTheme={isDarkTheme}
|
||||
setPinCodeState={setPinCodeState}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@ -55,6 +55,7 @@ class WalletView extends PureComponent {
|
||||
selectedUsername,
|
||||
walletData,
|
||||
isDarkTheme,
|
||||
setPinCodeState,
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
@ -113,7 +114,11 @@ class WalletView extends PureComponent {
|
||||
})}
|
||||
expanded
|
||||
>
|
||||
<WalletDetails intl={intl} walletData={walletData} />
|
||||
<WalletDetails
|
||||
intl={intl}
|
||||
walletData={walletData}
|
||||
setPinCodeState={setPinCodeState}
|
||||
/>
|
||||
</CollapsibleCard>
|
||||
<Transaction walletData={walletData} />
|
||||
</Fragment>
|
||||
|
@ -1,4 +1,11 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import { withNavigation } from 'react-navigation';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
// Constants
|
||||
import ROUTES from '../../../constants/routeNames';
|
||||
|
||||
import { openPinCodeModal } from '../../../redux/actions/applicationActions';
|
||||
|
||||
// Component
|
||||
import WalletDetailsView from '../view/walletDetailsView';
|
||||
@ -19,12 +26,33 @@ class WalletContainer extends PureComponent {
|
||||
// Component Life Cycle Functions
|
||||
|
||||
// Component Functions
|
||||
_navigate = (transferType, fundType) => {
|
||||
const { dispatch, setPinCodeState, walletData } = this.props;
|
||||
let balance;
|
||||
|
||||
switch (fundType) {
|
||||
case 'STEEM':
|
||||
balance = Math.round(walletData.balance * 1000) / 1000;
|
||||
break;
|
||||
case 'SBD':
|
||||
balance = Math.round(walletData.sbdBalance * 1000) / 1000;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
setPinCodeState({
|
||||
navigateTo: ROUTES.SCREENS.TRANSFER,
|
||||
navigateParams: { transferType, fundType, balance },
|
||||
});
|
||||
dispatch(openPinCodeModal());
|
||||
};
|
||||
|
||||
render() {
|
||||
const { intl, walletData } = this.props;
|
||||
|
||||
return <WalletDetailsView intl={intl} walletData={walletData} />;
|
||||
return <WalletDetailsView intl={intl} walletData={walletData} navigate={this._navigate} />;
|
||||
}
|
||||
}
|
||||
|
||||
export default WalletContainer;
|
||||
export default connect()(withNavigation(WalletContainer));
|
||||
|
@ -29,7 +29,11 @@ class WalletDetailsView extends PureComponent {
|
||||
// Component Functions
|
||||
|
||||
render() {
|
||||
const { walletData, intl } = this.props;
|
||||
const { walletData, intl, navigate } = this.props;
|
||||
|
||||
const steemDropdown = ['transferToken', 'transferToSaving', 'powerUp'];
|
||||
const sbdDropdown = ['transferToken', 'transferToSaving'];
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<WalletLineItem
|
||||
@ -38,6 +42,9 @@ class WalletDetailsView extends PureComponent {
|
||||
iconName="ios-information-circle-outline"
|
||||
rightText={`${Math.round(walletData.balance * 1000) / 1000} STEEM`}
|
||||
isBoldText
|
||||
dropdown
|
||||
dropdownOptions={steemDropdown.map(item => intl.formatMessage({ id: `transfer.${item}` }))}
|
||||
onDropdownSelect={index => navigate(steemDropdown[index], 'STEEM')}
|
||||
/>
|
||||
<GrayWrapper isGray>
|
||||
<WalletLineItem
|
||||
@ -87,6 +94,9 @@ class WalletDetailsView extends PureComponent {
|
||||
iconName="ios-information-circle-outline"
|
||||
rightText={`$${Math.round(walletData.sbdBalance * 1000) / 1000}`}
|
||||
isBoldText
|
||||
dropdown
|
||||
dropdownOptions={sbdDropdown.map(item => intl.formatMessage({ id: `transfer.${item}` }))}
|
||||
onDropdownSelect={a => navigate(steemDropdown[a], 'SBD')}
|
||||
/>
|
||||
<GrayWrapper isGray>
|
||||
<WalletLineItem
|
||||
|
@ -181,7 +181,8 @@
|
||||
"cancel": "Cancel",
|
||||
"delete": "Delete",
|
||||
"copied": "Copied!",
|
||||
"no_internet": "No connection!"
|
||||
"no_internet": "No connection!",
|
||||
"confirm": "Confirm"
|
||||
},
|
||||
"post": {
|
||||
"reblog_alert": "Are you sure you want to reblog?"
|
||||
@ -248,5 +249,21 @@
|
||||
"reputation": "reputation",
|
||||
"votes": "votes",
|
||||
"age": "age"
|
||||
},
|
||||
"transfer": {
|
||||
"title": "Transfer To Account",
|
||||
"from": "From",
|
||||
"to": "To",
|
||||
"amount": "Amount",
|
||||
"memo": "Memo",
|
||||
"information": "Are you sure to transfer to funds?",
|
||||
"amount_desc": "Balance",
|
||||
"memo_desc": "This memo is public",
|
||||
"to_placeholder": "Username",
|
||||
"memo_placeholder": "Enter your notes here",
|
||||
"transferToken": "Transfer",
|
||||
"transferToSaving": "Transfer To Saving",
|
||||
"powerUp": "Power Up",
|
||||
"steemconnect_title": "Steemconnect Transfer"
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ export default {
|
||||
VOTERS: `Voters${SCREEN_SUFFIX}`,
|
||||
BOOKMARKS: `Bookmarks${SCREEN_SUFFIX}`,
|
||||
SEARCH_RESULT: `SearchResult${SCREEN_SUFFIX}`,
|
||||
TRANSFER: `Transfer${SCREEN_SUFFIX}`,
|
||||
},
|
||||
DRAWER: {
|
||||
MAIN: `Main${DRAWER_SUFFIX}`,
|
||||
|
6
src/constants/steemConnectOptions.js
Normal file
6
src/constants/steemConnectOptions.js
Normal file
@ -0,0 +1,6 @@
|
||||
export const steemConnectOptions = {
|
||||
base_url: 'https://app.steemconnect.com/',
|
||||
client_id: 'esteem-app',
|
||||
redirect_uri: 'http://127.0.0.1:3415/', // http://127.0.0.1:3415
|
||||
scope: 'vote,comment,delete_comment,comment_options,custom_json,claim_reward_balance,offline',
|
||||
};
|
@ -21,6 +21,7 @@ import {
|
||||
SteemConnect,
|
||||
Voters,
|
||||
SearchResult,
|
||||
Transfer,
|
||||
} from '../screens';
|
||||
|
||||
// Components
|
||||
@ -99,6 +100,12 @@ const stackNavigatior = createStackNavigator(
|
||||
header: () => null,
|
||||
},
|
||||
},
|
||||
[ROUTES.SCREENS.TRANSFER]: {
|
||||
screen: RootComponent()(Transfer),
|
||||
navigationOptions: {
|
||||
header: () => null,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
headerMode: 'none',
|
||||
|
@ -439,13 +439,10 @@ export const getPostWithComments = async (user, permlink) => {
|
||||
* @param postingKey private posting key
|
||||
*/
|
||||
|
||||
export const vote = (account, pin, author, permlink, weight) => _vote(
|
||||
account, pin, author, permlink, weight,
|
||||
)
|
||||
.then((resp) => {
|
||||
userActivity(account.username, 120, resp.block_num, resp.id);
|
||||
return resp;
|
||||
});
|
||||
export const vote = (account, pin, author, permlink, weight) => _vote(account, pin, author, permlink, weight).then((resp) => {
|
||||
userActivity(account.username, 120, resp.block_num, resp.id);
|
||||
return resp;
|
||||
});
|
||||
|
||||
const _vote = async (currentAccount, pin, author, permlink, weight) => {
|
||||
const digitPinCode = getDigitPinCode(pin);
|
||||
@ -513,18 +510,126 @@ export const upvoteAmount = async (input) => {
|
||||
return estimated;
|
||||
};
|
||||
|
||||
export const transferToken = (data, activeKey) => {
|
||||
const key = PrivateKey.fromString(activeKey);
|
||||
return new Promise((resolve, reject) => {
|
||||
client.broadcast
|
||||
.transfer(data, key)
|
||||
.then((result) => {
|
||||
resolve(result);
|
||||
})
|
||||
.catch((err) => {
|
||||
reject(err);
|
||||
});
|
||||
});
|
||||
export const transferToken = (currentAccount, pin, data) => {
|
||||
const digitPinCode = getDigitPinCode(pin);
|
||||
const key = getAnyPrivateKey({ activeKey: currentAccount.local.activeKey }, digitPinCode);
|
||||
|
||||
if (key) {
|
||||
const privateKey = PrivateKey.fromString(key);
|
||||
const args = {
|
||||
from: data.from,
|
||||
to: data.destination,
|
||||
amount: data.amount,
|
||||
memo: data.memo,
|
||||
};
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
client.broadcast
|
||||
.transfer(args, privateKey)
|
||||
.then((result) => {
|
||||
resolve(result);
|
||||
})
|
||||
.catch((err) => {
|
||||
reject(err);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return Promise.reject(new Error('You dont have permission!'));
|
||||
};
|
||||
|
||||
export const transferToSavings = (currentAccount, pin, data) => {
|
||||
const digitPinCode = getDigitPinCode(pin);
|
||||
const key = getAnyPrivateKey({ activeKey: currentAccount.local.activeKey }, digitPinCode);
|
||||
|
||||
if (key) {
|
||||
const privateKey = PrivateKey.fromString(key);
|
||||
|
||||
const args = [[
|
||||
'transfer_to_savings',
|
||||
{
|
||||
from: data.from,
|
||||
to: data.destination,
|
||||
amount: data.amount,
|
||||
memo: data.memo,
|
||||
},
|
||||
]];
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
client.broadcast
|
||||
.sendOperations(args, privateKey)
|
||||
.then((result) => {
|
||||
resolve(result);
|
||||
})
|
||||
.catch((err) => {
|
||||
reject(err);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return Promise.reject(new Error('You dont have permission!'));
|
||||
};
|
||||
|
||||
export const transferFromSavings = (currentAccount, pin, data) => {
|
||||
const digitPinCode = getDigitPinCode(pin);
|
||||
const key = getAnyPrivateKey({ activeKey: currentAccount.local.activeKey }, digitPinCode);
|
||||
|
||||
if (key) {
|
||||
const privateKey = PrivateKey.fromString(key);
|
||||
const args = [[
|
||||
'transfer_from_savings',
|
||||
{
|
||||
from: data.from,
|
||||
to: data.destination,
|
||||
amount: data.amount,
|
||||
memo: data.memo,
|
||||
request_id: data.requestId,
|
||||
},
|
||||
]];
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
client.broadcast
|
||||
.sendOperations(args, privateKey)
|
||||
.then((result) => {
|
||||
resolve(result);
|
||||
})
|
||||
.catch((err) => {
|
||||
reject(err);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return Promise.reject(new Error('You dont have permission!'));
|
||||
};
|
||||
|
||||
export const transferToVesting = (currentAccount, pin, data) => {
|
||||
const digitPinCode = getDigitPinCode(pin);
|
||||
const key = getAnyPrivateKey({ activeKey: currentAccount.local.activeKey }, digitPinCode);
|
||||
|
||||
if (key) {
|
||||
const privateKey = PrivateKey.fromString(key);
|
||||
const args = [[
|
||||
'transfer_to_vesting',
|
||||
{
|
||||
from: data.from,
|
||||
to: data.destination,
|
||||
amount: data.amount,
|
||||
},
|
||||
]];
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
client.broadcast
|
||||
.sendOperations(args, privateKey)
|
||||
.then((result) => {
|
||||
resolve(result);
|
||||
})
|
||||
.catch((err) => {
|
||||
reject(err);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return Promise.reject(new Error('You dont have permission!'));
|
||||
};
|
||||
|
||||
export const followUser = async (currentAccount, pin, data) => {
|
||||
@ -631,30 +736,6 @@ export const delegate = (data, activeKey) => {
|
||||
});
|
||||
};
|
||||
|
||||
export const transferToVesting = (data, activeKey) => {
|
||||
const privateKey = PrivateKey.fromString(activeKey);
|
||||
|
||||
const op = [
|
||||
'transfer_to_vesting',
|
||||
{
|
||||
from: data.from,
|
||||
to: data.to,
|
||||
amount: data.amount,
|
||||
},
|
||||
];
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
client.broadcast
|
||||
.sendOperations([op], privateKey)
|
||||
.then((result) => {
|
||||
resolve(result);
|
||||
})
|
||||
.catch((error) => {
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
export const withdrawVesting = (data, activeKey) => {
|
||||
const privateKey = PrivateKey.fromString(activeKey);
|
||||
const op = [
|
||||
@ -837,9 +918,7 @@ const _postContent = async (
|
||||
|
||||
// Re-blog
|
||||
// TODO: remove pinCode
|
||||
export const reblog = (account, pinCode, author, permlink) => _reblog(
|
||||
account, pinCode, author, permlink,
|
||||
).then((resp) => {
|
||||
export const reblog = (account, pinCode, author, permlink) => _reblog(account, pinCode, author, permlink).then((resp) => {
|
||||
userActivity(account.name, 130, resp.block_num, resp.id);
|
||||
return resp;
|
||||
});
|
||||
@ -925,7 +1004,7 @@ const getAnyPrivateKey = (local, pin) => {
|
||||
}
|
||||
|
||||
if (activeKey) {
|
||||
return decryptKey(local.postingKey, pin);
|
||||
return decryptKey(local.activeKey, pin);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -127,12 +127,7 @@ export const unFollow = data => new Promise((resolve, reject) => {
|
||||
*/
|
||||
export const claimRewards = data => new Promise((resolve, reject) => {
|
||||
steemConnect
|
||||
.claimRewardBalance(
|
||||
data.account,
|
||||
data.rewardSteem,
|
||||
data.rewardSBD,
|
||||
data.VESTS,
|
||||
)
|
||||
.claimRewardBalance(data.account, data.rewardSteem, data.rewardSBD, data.VESTS)
|
||||
.then((result) => {
|
||||
resolve(result);
|
||||
})
|
||||
|
@ -15,6 +15,7 @@ import { Voters } from './voters';
|
||||
import RootComponent from './root';
|
||||
import SteemConnect from './steem-connect/steemConnect';
|
||||
import { SearchResult } from './searchResult';
|
||||
import Transfer from './transfer';
|
||||
|
||||
export {
|
||||
Bookmarks,
|
||||
@ -34,4 +35,5 @@ export {
|
||||
SteemConnect,
|
||||
Voters,
|
||||
SearchResult,
|
||||
Transfer,
|
||||
};
|
||||
|
@ -80,7 +80,7 @@ class PinCodeContainer extends Component {
|
||||
|
||||
_resetPinCode = pin => new Promise((resolve, reject) => {
|
||||
const {
|
||||
currentAccount, dispatch, accessToken, navigateTo, navigation, intl,
|
||||
currentAccount, dispatch, accessToken, navigateTo, navigateParams, navigation, intl,
|
||||
} = this.props;
|
||||
const { isOldPinVerified, oldPinCode } = this.state;
|
||||
|
||||
@ -102,7 +102,7 @@ class PinCodeContainer extends Component {
|
||||
|
||||
dispatch(closePinCodeModal());
|
||||
if (navigateTo) {
|
||||
navigation.navigate(navigateTo);
|
||||
navigation.navigate(navigateTo, navigateParams);
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
@ -135,7 +135,7 @@ class PinCodeContainer extends Component {
|
||||
|
||||
_setFirstPinCode = pin => new Promise((resolve) => {
|
||||
const {
|
||||
currentAccount, dispatch, accessToken, navigateTo, navigation,
|
||||
currentAccount, dispatch, accessToken, navigateTo, navigateParams, navigation,
|
||||
} = this.props;
|
||||
|
||||
const pinData = {
|
||||
@ -155,7 +155,7 @@ class PinCodeContainer extends Component {
|
||||
this._savePinCode(pin);
|
||||
dispatch(closePinCodeModal());
|
||||
if (navigateTo) {
|
||||
navigation.navigate(navigateTo);
|
||||
navigation.navigate(navigateTo, navigateParams);
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
@ -165,7 +165,7 @@ class PinCodeContainer extends Component {
|
||||
|
||||
_verifyPinCode = pin => new Promise((resolve, reject) => {
|
||||
const {
|
||||
currentAccount, dispatch, accessToken, navigateTo, navigation, intl,
|
||||
currentAccount, dispatch, accessToken, navigateTo, navigateParams, navigation, intl,
|
||||
} = this.props;
|
||||
|
||||
// If the user is exist, we are just checking to pin and navigating to home screen
|
||||
@ -184,8 +184,9 @@ class PinCodeContainer extends Component {
|
||||
[_currentAccount.local] = realmData;
|
||||
dispatch(updateCurrentAccount({ ..._currentAccount }));
|
||||
dispatch(closePinCodeModal());
|
||||
console.log('navigateParams :', navigateParams);
|
||||
if (navigateTo) {
|
||||
navigation.navigate(navigateTo);
|
||||
navigation.navigate(navigateTo, navigateParams);
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
|
@ -76,10 +76,7 @@ class ProfileContainer extends Component {
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
const {
|
||||
navigation,
|
||||
currentAccount,
|
||||
activeBottomTab,
|
||||
isLoggedIn,
|
||||
navigation, currentAccount, activeBottomTab, isLoggedIn,
|
||||
} = this.props;
|
||||
const currentUsername = currentAccount.name !== nextProps.currentAccount.name && nextProps.currentAccount.name;
|
||||
|
||||
@ -201,19 +198,19 @@ class ProfileContainer extends Component {
|
||||
const { username } = this.state;
|
||||
|
||||
if (error) {
|
||||
this.setState({
|
||||
error,
|
||||
}, () => alert(error));
|
||||
this.setState(
|
||||
{
|
||||
error,
|
||||
},
|
||||
() => alert(error),
|
||||
);
|
||||
} else {
|
||||
this._fetchProfile(username, true);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
_fetchProfile = async (username = null, isProfileAction = false) => {
|
||||
const {
|
||||
username: _username, isFollowing, isMuted,
|
||||
} = this.state;
|
||||
const { username: _username, isFollowing, isMuted } = this.state;
|
||||
|
||||
if (username) {
|
||||
const { isLoggedIn, currentAccount } = this.props;
|
||||
@ -239,9 +236,9 @@ class ProfileContainer extends Component {
|
||||
}
|
||||
|
||||
/**
|
||||
* This follow code totally a work arround
|
||||
* Ceated for server response delay.
|
||||
*/
|
||||
* This follow code totally a work arround
|
||||
* Ceated for server response delay.
|
||||
*/
|
||||
if (isProfileAction && (isFollowing === _isFollowing && isMuted === _isMuted)) {
|
||||
this._fetchProfile(_username, true);
|
||||
} else {
|
||||
@ -355,7 +352,7 @@ class ProfileContainer extends Component {
|
||||
username,
|
||||
} = this.state;
|
||||
const {
|
||||
isDarkTheme, isLoggedIn, currency, navigation,
|
||||
isDarkTheme, isLoggedIn, currency, navigation, setPinCodeState,
|
||||
} = this.props;
|
||||
const activePage = (navigation.state.params && navigation.state.params.activePage) || 0;
|
||||
|
||||
@ -385,6 +382,7 @@ class ProfileContainer extends Component {
|
||||
selectedQuickProfile={selectedQuickProfile}
|
||||
selectedUser={user}
|
||||
username={username}
|
||||
setPinCodeState={setPinCodeState}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@ -84,6 +84,7 @@ class ProfileScreen extends PureComponent {
|
||||
selectedUser,
|
||||
username,
|
||||
activePage,
|
||||
setPinCodeState,
|
||||
} = this.props;
|
||||
|
||||
const {
|
||||
@ -249,6 +250,7 @@ class ProfileScreen extends PureComponent {
|
||||
<Wallet
|
||||
setEstimatedWalletValue={this._setEstimatedWalletValue}
|
||||
selectedUser={selectedUser}
|
||||
setPinCodeState={setPinCodeState}
|
||||
/>
|
||||
) : (
|
||||
<WalletDetailsPlaceHolder />
|
||||
|
@ -12,9 +12,7 @@ import {
|
||||
setCurrency as setCurrency2DB,
|
||||
setServer,
|
||||
setNotificationSettings,
|
||||
setDefaultFooter,
|
||||
setLanguage as setLanguage2DB,
|
||||
setNotificationIsOpen,
|
||||
setNsfw as setNsfw2DB,
|
||||
setTheme,
|
||||
} from '../../../realm/realm';
|
||||
@ -27,7 +25,6 @@ import {
|
||||
setApi,
|
||||
isDarkTheme,
|
||||
isDefaultFooter,
|
||||
isNotificationOpen,
|
||||
openPinCodeModal,
|
||||
setNsfw,
|
||||
} from '../../../redux/actions/applicationActions';
|
||||
|
120
src/screens/transfer/container/transferContainer.js
Normal file
120
src/screens/transfer/container/transferContainer.js
Normal file
@ -0,0 +1,120 @@
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
// Services and Actions
|
||||
import {
|
||||
lookupAccounts,
|
||||
transferToken,
|
||||
transferFromSavings,
|
||||
transferToSavings,
|
||||
transferToVesting,
|
||||
} from '../../../providers/steem/dsteem';
|
||||
import { toastNotification } from '../../../redux/actions/uiAction';
|
||||
|
||||
// Middleware
|
||||
|
||||
// Constants
|
||||
|
||||
// Utilities
|
||||
|
||||
// Component
|
||||
import TransferView from '../screen/transferScreen';
|
||||
|
||||
/*
|
||||
* Props Name Description Value
|
||||
*@props --> props name here description here Value Type Here
|
||||
*
|
||||
*/
|
||||
|
||||
class ExampleContainer extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {};
|
||||
}
|
||||
|
||||
// Component Life Cycle Functions
|
||||
|
||||
// Component Functions
|
||||
_getAccountsWithUsername = async (username) => {
|
||||
const validUsers = await lookupAccounts(username);
|
||||
return validUsers;
|
||||
};
|
||||
|
||||
_transferToAccount = (from, destination, amount, memo) => {
|
||||
const {
|
||||
currentAccount, pinCode, navigation, dispatch,
|
||||
} = this.props;
|
||||
|
||||
const transferType = navigation.getParam('transferType', '');
|
||||
const fundType = navigation.getParam('fundType', '');
|
||||
let func;
|
||||
|
||||
const data = {
|
||||
from,
|
||||
destination,
|
||||
amount,
|
||||
memo,
|
||||
};
|
||||
data.amount = `${data.amount} ${fundType}`;
|
||||
|
||||
switch (transferType) {
|
||||
case 'transferToken':
|
||||
func = transferToken;
|
||||
break;
|
||||
case 'transferToSaving':
|
||||
func = transferToSavings;
|
||||
break;
|
||||
case 'powerUp':
|
||||
func = transferToVesting;
|
||||
break;
|
||||
case 'withdrawToSaving':
|
||||
func = transferFromSavings;
|
||||
data.requestId = new Date().getTime() >>> 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return func(currentAccount, pinCode, data)
|
||||
.then(() => {
|
||||
dispatch(toastNotification('Successfull'));
|
||||
navigation.goBack();
|
||||
})
|
||||
.catch((err) => {
|
||||
dispatch(toastNotification(err.message));
|
||||
});
|
||||
};
|
||||
|
||||
_handleOnModalClose = () => {
|
||||
const { navigation } = this.props;
|
||||
navigation.goBack();
|
||||
};
|
||||
|
||||
render() {
|
||||
const { accounts, currentAccount, navigation } = this.props;
|
||||
|
||||
const fundType = navigation.getParam('fundType', '');
|
||||
const balance = navigation.getParam('balance', '');
|
||||
|
||||
return (
|
||||
<TransferView
|
||||
accounts={accounts}
|
||||
getAccountsWithUsername={this._getAccountsWithUsername}
|
||||
transferToAccount={this._transferToAccount}
|
||||
handleOnModalClose={this._handleOnModalClose}
|
||||
accountType={currentAccount.local.authType}
|
||||
balance={balance}
|
||||
fundType={fundType}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
accounts: state.account.otherAccounts,
|
||||
currentAccount: state.account.currentAccount,
|
||||
pinCode: state.account.pin,
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps)(ExampleContainer);
|
5
src/screens/transfer/index.js
Normal file
5
src/screens/transfer/index.js
Normal file
@ -0,0 +1,5 @@
|
||||
import TransferScreen from './screen/transferScreen';
|
||||
import Transfer from './container/transferContainer';
|
||||
|
||||
export { TransferScreen, Transfer };
|
||||
export default Transfer;
|
195
src/screens/transfer/screen/transferScreen.js
Normal file
195
src/screens/transfer/screen/transferScreen.js
Normal file
@ -0,0 +1,195 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
import React, { Fragment, Component } from 'react';
|
||||
import { Text, View, WebView } from 'react-native';
|
||||
import ActionSheet from 'react-native-actionsheet';
|
||||
import { injectIntl } from 'react-intl';
|
||||
|
||||
import { steemConnectOptions } from '../../../constants/steemConnectOptions';
|
||||
import AUTH_TYPE from '../../../constants/authType';
|
||||
|
||||
import { BasicHeader } from '../../../components/basicHeader';
|
||||
import { TextInput } from '../../../components/textInput';
|
||||
import { TransferFormItem } from '../../../components/transferFormItem';
|
||||
import { MainButton } from '../../../components/mainButton';
|
||||
import { DropdownButton } from '../../../components/dropdownButton';
|
||||
import { UserAvatar } from '../../../components/userAvatar';
|
||||
import { Icon } from '../../../components/icon';
|
||||
import { Modal } from '../../../components/modal';
|
||||
|
||||
import styles from './transferStyles';
|
||||
/* Props
|
||||
* ------------------------------------------------
|
||||
* @prop { type } name - Description....
|
||||
*/
|
||||
|
||||
class TransferView extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
from: props.accounts[0].username,
|
||||
destination: '',
|
||||
amount: '',
|
||||
memo: '',
|
||||
isUsernameValid: false,
|
||||
steemConnectTransfer: false,
|
||||
};
|
||||
}
|
||||
|
||||
// Component Life Cycles
|
||||
|
||||
// Component Functions
|
||||
_setState = (key, value) => {
|
||||
const { getAccountsWithUsername, balance } = this.props;
|
||||
|
||||
if (key) {
|
||||
switch (key) {
|
||||
case 'destination':
|
||||
getAccountsWithUsername(value).then((res) => {
|
||||
const isValid = res.includes(value);
|
||||
|
||||
this.setState({ isUsernameValid: isValid });
|
||||
});
|
||||
this.setState({ [key]: value });
|
||||
break;
|
||||
case 'amount':
|
||||
if (!isNaN(value) && parseFloat(value) <= parseFloat(balance)) this.setState({ [key]: value });
|
||||
break;
|
||||
|
||||
default:
|
||||
this.setState({ [key]: value });
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
_handleTransferAction = () => {
|
||||
const { transferToAccount, accountType } = this.props;
|
||||
const {
|
||||
from, destination, amount, memo,
|
||||
} = this.state;
|
||||
|
||||
if (accountType === AUTH_TYPE.STEEM_CONNECT) {
|
||||
this.setState({ steemConnectTransfer: true });
|
||||
} else {
|
||||
transferToAccount(from, destination, amount, memo);
|
||||
}
|
||||
};
|
||||
|
||||
_renderInput = (placeholder, state) => (
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
onChangeText={text => this._setState(state, text)}
|
||||
value={this.state[state]}
|
||||
placeholder={placeholder}
|
||||
placeholderTextColor="#c1c5c7"
|
||||
autoCapitalize="none"
|
||||
keyboardType="numeric"
|
||||
/>
|
||||
);
|
||||
|
||||
_renderDropdown = accounts => (
|
||||
<DropdownButton
|
||||
style={styles.dropdown}
|
||||
options={accounts.map(item => item.username)}
|
||||
defaultText={accounts[0].username}
|
||||
selectedOptionIndex={0}
|
||||
onSelect={(index, value) => this.setState({ from: value })}
|
||||
/>
|
||||
);
|
||||
|
||||
_renderDescription = text => <Text style={styles.description}>{text}</Text>;
|
||||
|
||||
render() {
|
||||
const { accounts, intl, handleOnModalClose, balance, fundType } = this.props;
|
||||
const {
|
||||
destination, isUsernameValid, amount, steemConnectTransfer, memo,
|
||||
} = this.state;
|
||||
|
||||
const path = `sign/transfer?from=${
|
||||
accounts[0].username
|
||||
}&to=${destination}&amount=${encodeURIComponent(`${amount} STEEM`)}&memo=${encodeURIComponent(
|
||||
memo,
|
||||
)}`;
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<BasicHeader title={intl.formatMessage({ id: 'transfer.title' })} />
|
||||
<View style={styles.container}>
|
||||
<View style={styles.topContent}>
|
||||
<UserAvatar
|
||||
username={accounts[0].username}
|
||||
size="xl"
|
||||
style={styles.userAvatar}
|
||||
noAction
|
||||
/>
|
||||
<Icon style={styles.icon} name="arrow-forward" iconType="MaterialIcons" />
|
||||
<UserAvatar username={destination} size="xl" style={styles.userAvatar} noAction />
|
||||
</View>
|
||||
<View style={styles.middleContent}>
|
||||
<TransferFormItem
|
||||
label={intl.formatMessage({ id: 'transfer.from' })}
|
||||
rightComponent={() => this._renderDropdown(accounts)}
|
||||
/>
|
||||
<TransferFormItem
|
||||
label={intl.formatMessage({ id: 'transfer.to' })}
|
||||
rightComponent={() => this._renderInput(
|
||||
intl.formatMessage({ id: 'transfer.to_placeholder' }),
|
||||
'destination',
|
||||
)
|
||||
}
|
||||
/>
|
||||
<TransferFormItem
|
||||
label={intl.formatMessage({ id: 'transfer.amount' })}
|
||||
rightComponent={() => this._renderInput(intl.formatMessage({ id: 'transfer.amount' }), 'amount')}
|
||||
/>
|
||||
<TransferFormItem
|
||||
rightComponent={() => this._renderDescription(`${intl.formatMessage({ id: 'transfer.amount_desc' })} ${balance} ${fundType}`)}
|
||||
/>
|
||||
<TransferFormItem
|
||||
label={intl.formatMessage({ id: 'transfer.memo' })}
|
||||
rightComponent={() => this._renderInput(intl.formatMessage({ id: 'transfer.memo_placeholder' }), 'memo')
|
||||
}
|
||||
/>
|
||||
<TransferFormItem
|
||||
rightComponent={() => this._renderDescription(intl.formatMessage({ id: 'transfer.memo_desc' }))
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
<View style={styles.bottomContent}>
|
||||
<MainButton
|
||||
style={styles.button}
|
||||
isDisable={!(amount && isUsernameValid)}
|
||||
onPress={() => this.ActionSheet.show()}
|
||||
>
|
||||
<Text style={styles.buttonText}>NEXT</Text>
|
||||
</MainButton>
|
||||
</View>
|
||||
</View>
|
||||
<ActionSheet
|
||||
ref={o => (this.ActionSheet = o)}
|
||||
options={[
|
||||
intl.formatMessage({ id: 'alert.confirm' }),
|
||||
intl.formatMessage({ id: 'alert.cancel' }),
|
||||
]}
|
||||
title={intl.formatMessage({ id: 'transfer.information' })}
|
||||
cancelButtonIndex={1}
|
||||
destructiveButtonIndex={0}
|
||||
onPress={(index) => {
|
||||
index === 0 ? this._handleTransferAction() : null;
|
||||
}}
|
||||
/>
|
||||
<Modal
|
||||
isOpen={steemConnectTransfer}
|
||||
isFullScreen
|
||||
isCloseButton
|
||||
handleOnModalClose={handleOnModalClose}
|
||||
title={intl.formatMessage({ id: 'transfer.steemconnect_title' })}
|
||||
>
|
||||
<WebView source={{ uri: `${steemConnectOptions.base_url}${path}` }} />
|
||||
</Modal>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default injectIntl(TransferView);
|
57
src/screens/transfer/screen/transferStyles.js
Normal file
57
src/screens/transfer/screen/transferStyles.js
Normal file
@ -0,0 +1,57 @@
|
||||
import EStyleSheet from 'react-native-extended-stylesheet';
|
||||
|
||||
export default EStyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: '$primaryBackgroundColor',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
topContent: {
|
||||
flexDirection: 'row',
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
middleContent: {
|
||||
flex: 3,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
bottomContent: {
|
||||
flex: 2,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
input: {
|
||||
borderWidth: 1,
|
||||
borderColor: '$borderColor',
|
||||
borderRadius: 10,
|
||||
padding: 10,
|
||||
color: '$primaryBlack',
|
||||
},
|
||||
description: {
|
||||
color: '$iconColor',
|
||||
},
|
||||
button: {
|
||||
width: '$deviceWidth / 3',
|
||||
marginTop: 30,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
buttonText: {
|
||||
color: 'white',
|
||||
},
|
||||
dropdown: {
|
||||
borderWidth: 1,
|
||||
borderColor: '$borderColor',
|
||||
borderRadius: 10,
|
||||
flex: 1,
|
||||
padding: 10,
|
||||
},
|
||||
icon: {
|
||||
fontSize: 40,
|
||||
color: '$iconColor',
|
||||
marginHorizontal: 20,
|
||||
},
|
||||
});
|
@ -95,7 +95,7 @@ export const groomingTransactionData = (transaction, steemPerMVests, formatNumbe
|
||||
result.icon = 'reorder';
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
return [];
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user