Merge remote-tracking branch 'upstream/development' into nt/use-query-notifications

This commit is contained in:
Nouman Tahir 2022-09-22 14:26:01 +05:00
commit b8ea6db4e5
9 changed files with 330 additions and 298 deletions

View File

@ -30,9 +30,7 @@ const DraftsScreen = ({
moveScheduleToDraft, moveScheduleToDraft,
initialTabIndex, initialTabIndex,
}) => { }) => {
const isDarkTheme = useAppSelector((state) => state.application.isDarkTheme);
const isDarkTheme = useAppSelector(state=>state.application.isDarkTheme);
// Component Functions // Component Functions
const _renderItem = (item, type) => { const _renderItem = (item, type) => {
@ -105,13 +103,16 @@ const DraftsScreen = ({
removeClippedSubviews={false} removeClippedSubviews={false}
renderItem={({ item }) => _renderItem(item, type)} renderItem={({ item }) => _renderItem(item, type)}
ListEmptyComponent={_renderEmptyContent()} ListEmptyComponent={_renderEmptyContent()}
refreshControl={<RefreshControl refreshControl={
refreshing={isLoading} <RefreshControl
onRefresh={onRefresh} refreshing={isLoading}
progressBackgroundColor="#357CE6" onRefresh={onRefresh}
tintColor={!isDarkTheme ? '#357ce6' : '#96c0ff'} progressBackgroundColor="#357CE6"
titleColor="#fff" tintColor={!isDarkTheme ? '#357ce6' : '#96c0ff'}
colors={['#fff']} />} titleColor="#fff"
colors={['#fff']}
/>
}
/> />
</View> </View>
); );

View File

@ -33,13 +33,13 @@ export interface PostOptionsModalRef {
interface PostOptionsModalProps { interface PostOptionsModalProps {
body:string; body:string;
draftId:string; draftId:string;
thumbIndex:number, thumbUrl:string,
isEdit:boolean; isEdit:boolean;
isCommunityPost:boolean; isCommunityPost:boolean;
rewardType: string; rewardType: string;
isUploading: boolean; isUploading: boolean;
handleRewardChange:(rewardType:string)=>void; handleRewardChange:(rewardType:string)=>void;
handleThumbSelection:(index:number)=>void; handleThumbSelection:(url:string)=>void;
handleScheduleChange:(datetime:string|null)=>void; handleScheduleChange:(datetime:string|null)=>void;
handleShouldReblogChange:(shouldReblog:boolean)=>void; handleShouldReblogChange:(shouldReblog:boolean)=>void;
handleFormUpdate:()=>void; handleFormUpdate:()=>void;
@ -48,7 +48,7 @@ interface PostOptionsModalProps {
const PostOptionsModal = forwardRef(({ const PostOptionsModal = forwardRef(({
body, body,
draftId, draftId,
thumbIndex, thumbUrl,
isEdit, isEdit,
isCommunityPost, isCommunityPost,
rewardType, rewardType,
@ -121,8 +121,8 @@ const PostOptionsModal = forwardRef(({
} }
// handle index change here instead of useeffetc // handle index change here instead of useeffetc
const _handleThumbIndexSelection = (index:number) => { const _handleThumbIndexSelection = (url:string) => {
handleThumbSelection(index) handleThumbSelection(url)
} }
const _renderContent = () => ( const _renderContent = () => (
@ -190,7 +190,7 @@ const PostOptionsModal = forwardRef(({
<ThumbSelectionContent <ThumbSelectionContent
body={body} body={body}
thumbIndex={thumbIndex} thumbUrl={thumbUrl}
isUploading={isUploading} isUploading={isUploading}
onThumbSelection={_handleThumbIndexSelection} onThumbSelection={_handleThumbIndexSelection}
/> />

View File

@ -1,4 +1,3 @@
import { ViewStyle } from 'react-native';
import EStyleSheet from 'react-native-extended-stylesheet'; import EStyleSheet from 'react-native-extended-stylesheet';
import { getBottomSpace } from 'react-native-iphone-x-helper'; import { getBottomSpace } from 'react-native-iphone-x-helper';
@ -20,9 +19,12 @@ export default EStyleSheet.create({
borderRadius:12, borderRadius:12,
backgroundColor:'$primaryLightGray' backgroundColor:'$primaryLightGray'
}, },
selectedStyle:{ checkContainer:{
borderWidth:4, position: 'absolute',
borderColor:'$primaryBlack' top: 12,
left: 6,
backgroundColor: '$pureWhite',
borderRadius: 12
}, },
settingLabel:{ settingLabel:{
color: '$primaryDarkGray', color: '$primaryDarkGray',

View File

@ -1,61 +1,91 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { useIntl } from 'react-intl'; import { useIntl } from 'react-intl';
import { ActivityIndicator, Text, TouchableOpacity, View } from 'react-native'; import { ActivityIndicator, Alert, Text, TouchableOpacity, View } from 'react-native';
import FastImage from 'react-native-fast-image'; import FastImage from 'react-native-fast-image';
import { FlatList } from 'react-native-gesture-handler'; import { FlatList } from 'react-native-gesture-handler';
import { extractImageUrls } from '../../../utils/editor'; import { extractImageUrls } from '../../../utils/editor';
import styles from './styles'; import styles from './styles';
import ESStyleSheet from 'react-native-extended-stylesheet'; import ESStyleSheet from 'react-native-extended-stylesheet';
import { Icon } from '../../../components';
import EStyleSheet from 'react-native-extended-stylesheet';
import { View as AnimatedView } from 'react-native-animatable';
interface ThumbSelectionContentProps { interface ThumbSelectionContentProps {
body: string; body: string;
thumbIndex: number; thumbUrl: string;
isUploading: boolean; isUploading: boolean;
onThumbSelection: (index: number) => void; onThumbSelection: (url: string) => void;
} }
const ThumbSelectionContent = ({ body, thumbIndex, onThumbSelection, isUploading }: ThumbSelectionContentProps) => { const ThumbSelectionContent = ({ body, thumbUrl, onThumbSelection, isUploading }: ThumbSelectionContentProps) => {
const intl = useIntl(); const intl = useIntl();
const [imageUrls, setImageUrls] = useState<string[]>([]); const [imageUrls, setImageUrls] = useState<string[]>([]);
const [needMore, setNeedMore] = useState(true); const [needMore, setNeedMore] = useState(true);
const [thumbIndex, setThumbIndex] = useState(0);
useEffect(() => { useEffect(() => {
const urls = extractImageUrls({ body }); const urls = extractImageUrls({ body });
if (urls.length < 2) { if (urls.length < 2) {
setNeedMore(true); setNeedMore(true);
onThumbSelection(0); onThumbSelection(urls[0] || '');
setThumbIndex(0);
setImageUrls([]) setImageUrls([])
} else { } else {
setNeedMore(false); setNeedMore(false);
setImageUrls(urls) setImageUrls(urls)
} }
const _urlIndex = urls.indexOf(thumbUrl)
if (_urlIndex < 0) {
onThumbSelection(urls[0] || '');
setThumbIndex(0);
} else {
setThumbIndex(_urlIndex)
}
}, [body]) }, [body])
//VIEW_RENDERERS //VIEW_RENDERERS
const _renderImageItem = ({ item, index }: { item: string, index: number }) => { const _renderImageItem = ({ item, index }: { item: string, index: number }) => {
const _onPress = () => { const _onPress = () => {
onThumbSelection(index); onThumbSelection(item);
setThumbIndex(index);
} }
const selectedStyle = index === thumbIndex ? styles.selectedStyle : null const isSelected = item === thumbUrl && index === thumbIndex;
return ( return (
<TouchableOpacity onPress={() => _onPress()} > <TouchableOpacity onPress={() => _onPress()} >
<FastImage <FastImage
source={{ uri: item }} source={{ uri: item }}
style={{ ...styles.thumbStyle, ...selectedStyle }} style={styles.thumbStyle}
resizeMode='cover' resizeMode='cover'
/> />
{isSelected && (
<AnimatedView duration={300} animation='zoomIn' style={styles.checkContainer}>
<Icon
color={EStyleSheet.value('$primaryBlue')}
iconType="MaterialCommunityIcons"
name={'checkbox-marked-circle'}
size={20}
/>
</AnimatedView>
)}
</TouchableOpacity> </TouchableOpacity>
) )
} }
const _renderHeader = () => ( const _renderHeader = () => (
isUploading && isUploading &&
<View style={{flex:1, justifyContent:'center', marginRight: 16}}> <View style={{ flex: 1, justifyContent: 'center', marginRight: 16 }}>
<ActivityIndicator color={ESStyleSheet.value('$primaryBlack')} /> <ActivityIndicator color={ESStyleSheet.value('$primaryBlack')} />
</View> </View>

View File

@ -11,12 +11,12 @@ import { useIntl } from 'react-intl';
export interface ThumbSelectionModalProps { export interface ThumbSelectionModalProps {
thumbIndex:number; thumbUrl:string;
onThumbSelection:(index:number)=>void; onThumbSelection:(index:number)=>void;
} }
const ThumbSelectionModal = ({ onThumbSelection, thumbIndex }:ThumbSelectionModalProps, ref) => { const ThumbSelectionModal = ({ onThumbSelection, thumbUrl }:ThumbSelectionModalProps, ref) => {
const intl = useIntl(); const intl = useIntl();
const [imageUrls, setImageUrls] = useState<string[]>([]); const [imageUrls, setImageUrls] = useState<string[]>([]);
@ -57,7 +57,7 @@ const ThumbSelectionModal = ({ onThumbSelection, thumbIndex }:ThumbSelectionModa
_onSelection(index); _onSelection(index);
} }
const selectedStyle = index === thumbIndex ? styles.selectedStyle : null const selectedStyle = item === thumbUrl ? styles.selectedStyle : null
return ( return (
<TouchableOpacity onPress={() => _onPress()} > <TouchableOpacity onPress={() => _onPress()} >

View File

@ -1,7 +1,7 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { injectIntl } from 'react-intl'; import { injectIntl } from 'react-intl';
import { Alert } from 'react-native'; import { Alert, AppState, AppStateStatus } from 'react-native';
import get from 'lodash/get'; import get from 'lodash/get';
import AsyncStorage from '@react-native-community/async-storage'; import AsyncStorage from '@react-native-community/async-storage';
import { isArray } from 'lodash'; import { isArray } from 'lodash';
@ -44,6 +44,7 @@ import {
updateDraftCache, updateDraftCache,
} from '../../../redux/actions/cacheActions'; } from '../../../redux/actions/cacheActions';
import QUERIES from '../../../providers/queries/queryKeys'; import QUERIES from '../../../providers/queries/queryKeys';
import bugsnapInstance from '../../../config/bugsnag';
/* /*
* Props Name Description Value * Props Name Description Value
@ -54,6 +55,7 @@ import QUERIES from '../../../providers/queries/queryKeys';
class EditorContainer extends Component<any, any> { class EditorContainer extends Component<any, any> {
_isMounted = false; _isMounted = false;
_updatedDraftFields = null; _updatedDraftFields = null;
_appState = AppState.currentState;
constructor(props) { constructor(props) {
super(props); super(props);
@ -71,14 +73,12 @@ class EditorContainer extends Component<any, any> {
uploadProgress: 0, uploadProgress: 0,
post: null, post: null,
uploadedImage: null, uploadedImage: null,
isDraft: false,
community: [], community: [],
rewardType: 'default', rewardType: 'default',
sharedSnippetText: null, sharedSnippetText: null,
onLoadDraftPress: false, onLoadDraftPress: false,
thumbIndex: 0, thumbUrl: '',
shouldReblog: false, shouldReblog: false,
failedImageUploads: 0,
}; };
} }
@ -105,7 +105,6 @@ class EditorContainer extends Component<any, any> {
this.setState({ this.setState({
draftId: _draft._id, draftId: _draft._id,
isDraft: true,
}); });
this._getStorageDraft(username, isReply, _draft); this._getStorageDraft(username, isReply, _draft);
} }
@ -173,13 +172,13 @@ class EditorContainer extends Component<any, any> {
this._fetchDraftsForComparison(isReply); this._fetchDraftsForComparison(isReply);
} }
this._requestKeyboardFocus(); this._requestKeyboardFocus();
AppState.addEventListener('change', this._handleAppStateChange);
} }
componentWillUnmount() {
this._isMounted = false;
}
componentDidUpdate(prevProps: Readonly<any>, prevState: Readonly<any>, snapshot?: any): void {
componentDidUpdate(prevProps: Readonly<any>, prevState: Readonly<any>): void {
if ( if (
prevState.rewardType !== this.state.rewardType || prevState.rewardType !== this.state.rewardType ||
prevProps.beneficiariesMap !== this.props.beneficiariesMap prevProps.beneficiariesMap !== this.props.beneficiariesMap
@ -188,8 +187,21 @@ class EditorContainer extends Component<any, any> {
this._handleFormChanged(); this._handleFormChanged();
} }
} }
componentWillUnmount() {
AppState.removeEventListener('change', this._handleAppStateChange);
this._isMounted = false;
}
_handleAppStateChange = (nextAppState:AppStateStatus) => {
if (this._appState.match(/active|forground/) && nextAppState === 'inactive') {
this._saveCurrentDraft(this._updatedDraftFields);
}
this._appState = nextAppState;
}
_getStorageDraft = async (username, isReply, paramDraft) => { _getStorageDraft = async (username, isReply, paramDraft) => {
const { drafts, dispatch } = this.props; const { drafts } = this.props;
if (isReply) { if (isReply) {
const _draft = drafts.get(paramDraft._id); const _draft = drafts.get(paramDraft._id);
if (_draft && _draft.body) { if (_draft && _draft.body) {
@ -207,13 +219,14 @@ class EditorContainer extends Component<any, any> {
//if _draft is returned and param draft is available, compare timestamp, use latest //if _draft is returned and param draft is available, compare timestamp, use latest
//if no draft, use result anayways //if no draft, use result anayways
if (_localDraft && (!paramDraft || paramDraft.timestamp < _localDraft.updated)) { const _remoteDraftModifiedAt = paramDraft ? new Date(paramDraft.modified).getTime() : 0;
const _useLocalDraft = _localDraft && _remoteDraftModifiedAt < _localDraft.updated;
if (_useLocalDraft) {
this.setState({ this.setState({
draftPost: { draftPost: {
body: get(_localDraft, 'body', ''), body: get(_localDraft, 'body', ''),
title: get(_localDraft, 'title', ''), title: get(_localDraft, 'title', ''),
tags: get(_localDraft, 'tags', '').split(','), tags: get(_localDraft, 'tags', '').split(','),
isDraft: paramDraft ? true : false,
draftId: paramDraft ? paramDraft._id : null, draftId: paramDraft ? paramDraft._id : null,
meta: _localDraft.meta ? _localDraft.meta : null, meta: _localDraft.meta ? _localDraft.meta : null,
}, },
@ -234,7 +247,6 @@ class EditorContainer extends Component<any, any> {
tags: _tags, tags: _tags,
meta: paramDraft.meta ? paramDraft.meta : null, meta: paramDraft.meta ? paramDraft.meta : null,
}, },
isDraft: true,
draftId: paramDraft._id, draftId: paramDraft._id,
}); });
@ -250,9 +262,8 @@ class EditorContainer extends Component<any, any> {
const body = draft.body; const body = draft.body;
if (draft.meta && draft.meta.image) { if (draft.meta && draft.meta.image) {
const urls = extractImageUrls({ body }); const urls = extractImageUrls({ body });
const draftThumbIndex = urls.indexOf(draft.meta.image[0]);
this.setState({ this.setState({
thumbIndex: draftThumbIndex, thumbUrl: draft.meta.image[0],
}); });
} }
@ -290,7 +301,7 @@ class EditorContainer extends Component<any, any> {
* @param isReply * @param isReply
**/ **/
_fetchDraftsForComparison = async (isReply) => { _fetchDraftsForComparison = async (isReply) => {
const { currentAccount, isLoggedIn, intl, dispatch, drafts } = this.props; const { currentAccount, isLoggedIn, drafts } = this.props;
const username = get(currentAccount, 'name', ''); const username = get(currentAccount, 'name', '');
//initilizes editor with reply or non remote id less draft //initilizes editor with reply or non remote id less draft
@ -345,7 +356,6 @@ class EditorContainer extends Component<any, any> {
//initilize editor as draft //initilize editor as draft
this.setState({ this.setState({
draftId: _draft._id, draftId: _draft._id,
isDraft: true,
}); });
this._getStorageDraft(username, isReply, _draft); this._getStorageDraft(username, isReply, _draft);
}; };
@ -373,11 +383,18 @@ class EditorContainer extends Component<any, any> {
}; };
_saveDraftToDB = async (fields, saveAsNew = false) => { _saveDraftToDB = async (fields, saveAsNew = false) => {
const { isDraftSaved, draftId, thumbIndex, isReply, rewardType } = this.state; const { isDraftSaved, draftId, thumbUrl, isReply, rewardType } = this.state;
const { currentAccount, dispatch, intl, queryClient } = this.props; const { currentAccount, dispatch, intl, queryClient } = this.props;
if (isReply) { try {
//saves draft locallly
this._saveCurrentDraft(this._updatedDraftFields); this._saveCurrentDraft(this._updatedDraftFields);
} catch (err) {
console.warn('local draft safe failed, skipping for remote only', err);
bugsnapInstance.notify(err);
}
if (isReply) {
return; return;
} }
@ -400,7 +417,7 @@ class EditorContainer extends Component<any, any> {
}; };
} }
const meta = Object.assign({}, extractMetadata(draftField.body, thumbIndex), { const meta = Object.assign({}, extractMetadata(draftField.body, thumbUrl), {
tags: draftField.tags, tags: draftField.tags,
beneficiaries, beneficiaries,
rewardType, rewardType,
@ -467,9 +484,6 @@ class EditorContainer extends Component<any, any> {
isDraftSaving: false, isDraftSaving: false,
isDraftSaved: false, isDraftSaved: false,
}); });
//saves draft locally if remote draft save fails
this._saveCurrentDraft(this._updatedDraftFields);
} }
dispatch( dispatch(
@ -529,7 +543,7 @@ class EditorContainer extends Component<any, any> {
pinCode, pinCode,
// isDefaultFooter, // isDefaultFooter,
} = this.props; } = this.props;
const { rewardType, isPostSending, thumbIndex, draftId, shouldReblog } = this.state; const { rewardType, isPostSending, thumbUrl, draftId, shouldReblog } = this.state;
const beneficiaries = this._extractBeneficiaries(); const beneficiaries = this._extractBeneficiaries();
@ -542,7 +556,7 @@ class EditorContainer extends Component<any, any> {
isPostSending: true, isPostSending: true,
}); });
const meta = extractMetadata(fields.body, thumbIndex); const meta = extractMetadata(fields.body, thumbUrl);
const _tags = fields.tags.filter((tag) => tag && tag !== ' '); const _tags = fields.tags.filter((tag) => tag && tag !== ' ');
const jsonMeta = makeJsonMetadata(meta, _tags); const jsonMeta = makeJsonMetadata(meta, _tags);
@ -703,7 +717,7 @@ class EditorContainer extends Component<any, any> {
_submitEdit = async (fields) => { _submitEdit = async (fields) => {
const { currentAccount, pinCode, dispatch } = this.props; const { currentAccount, pinCode, dispatch } = this.props;
const { post, isEdit, isPostSending, thumbIndex, isReply } = this.state; const { post, isEdit, isPostSending, thumbUrl, isReply } = this.state;
if (isPostSending) { if (isPostSending) {
return; return;
@ -729,7 +743,7 @@ class EditorContainer extends Component<any, any> {
newBody = patch; newBody = patch;
} }
const meta = extractMetadata(fields.body, thumbIndex); const meta = extractMetadata(fields.body, thumbUrl);
let jsonMeta = {}; let jsonMeta = {};
@ -1019,9 +1033,9 @@ class EditorContainer extends Component<any, any> {
}); });
}; };
_handleSetThumbIndex = (index: number) => { _handleSetThumbUrl = (url: string) => {
this.setState({ this.setState({
thumbIndex: index, thumbUrl: url,
}); });
}; };
@ -1050,7 +1064,7 @@ class EditorContainer extends Component<any, any> {
community, community,
sharedSnippetText, sharedSnippetText,
onLoadDraftPress, onLoadDraftPress,
thumbIndex, thumbUrl,
uploadProgress, uploadProgress,
rewardType, rewardType,
} = this.state; } = this.state;
@ -1090,8 +1104,8 @@ class EditorContainer extends Component<any, any> {
draftId={draftId} draftId={draftId}
sharedSnippetText={sharedSnippetText} sharedSnippetText={sharedSnippetText}
onLoadDraftPress={onLoadDraftPress} onLoadDraftPress={onLoadDraftPress}
thumbIndex={thumbIndex} thumbUrl={thumbUrl}
setThumbIndex={this._handleSetThumbIndex} setThumbUrl={this._handleSetThumbUrl}
uploadProgress={uploadProgress} uploadProgress={uploadProgress}
rewardType={rewardType} rewardType={rewardType}
getBeneficiaries={this._extractBeneficiaries} getBeneficiaries={this._extractBeneficiaries}

View File

@ -192,10 +192,10 @@ class EditorScreen extends Component {
} }
}; };
_handleOnThumbSelection = (index) => { _handleOnThumbSelection = (url:string) => {
const { setThumbIndex } = this.props; const { setThumbUrl } = this.props;
if (setThumbIndex) { if (setThumbUrl) {
setThumbIndex(index); setThumbUrl(url);
} }
}; };
@ -236,7 +236,7 @@ class EditorScreen extends Component {
}; };
_handleFormUpdate = (componentID, content) => { _handleFormUpdate = (componentID, content) => {
const { handleFormChanged, thumbIndex, rewardType, getBeneficiaries } = this.props; const { handleFormChanged, thumbUrl, rewardType, getBeneficiaries } = this.props;
const { fields: _fields } = this.state; const { fields: _fields } = this.state;
const fields = { ..._fields }; const fields = { ..._fields };
@ -248,7 +248,7 @@ class EditorScreen extends Component {
fields.tags = content; fields.tags = content;
} }
const meta = Object.assign({}, extractMetadata(fields.body, thumbIndex), { const meta = Object.assign({}, extractMetadata(fields.body, thumbUrl), {
tags: fields.tags, tags: fields.tags,
beneficiaries: getBeneficiaries(), beneficiaries: getBeneficiaries(),
rewardType, rewardType,
@ -381,7 +381,7 @@ class EditorScreen extends Component {
autoFocusText, autoFocusText,
sharedSnippetText, sharedSnippetText,
onLoadDraftPress, onLoadDraftPress,
thumbIndex, thumbUrl,
uploadProgress, uploadProgress,
rewardType, rewardType,
setIsUploading, setIsUploading,
@ -484,7 +484,7 @@ class EditorScreen extends Component {
ref={(componentRef) => (this.postOptionsModalRef = componentRef)} ref={(componentRef) => (this.postOptionsModalRef = componentRef)}
body={fields.body} body={fields.body}
draftId={draftId} draftId={draftId}
thumbIndex={thumbIndex} thumbUrl={thumbUrl}
isEdit={isEdit} isEdit={isEdit}
isCommunityPost={selectedCommunity !== null} isCommunityPost={selectedCommunity !== null}
rewardType={rewardType} rewardType={rewardType}

View File

@ -1,7 +1,6 @@
import getSlug from 'speakingurl'; import getSlug from 'speakingurl';
import { diff_match_patch as diffMatchPatch } from 'diff-match-patch'; import { diff_match_patch as diffMatchPatch } from 'diff-match-patch';
import VersionNumber from 'react-native-version-number'; import VersionNumber from 'react-native-version-number';
import { PanGestureHandler } from 'react-native-gesture-handler';
import MimeTypes from 'mime-types'; import MimeTypes from 'mime-types';
export const getWordsCount = (text) => export const getWordsCount = (text) =>
@ -214,7 +213,7 @@ export const extractFilenameFromPath = ({path, mimeType}:{path:string, mimeType?
} }
} }
export const extractMetadata = (body:string, thumbIndex?:number) => { export const extractMetadata = (body:string, thumbUrl?:string) => {
const userReg = /(^|\s)(@[a-z][-.a-z\d]+[a-z\d])/gim; const userReg = /(^|\s)(@[a-z][-.a-z\d]+[a-z\d])/gim;
const out = {}; const out = {};
@ -239,8 +238,8 @@ export const extractMetadata = (body:string, thumbIndex?:number) => {
} }
if (matchedImages.length) { if (matchedImages.length) {
if(thumbIndex){ if(thumbUrl){
matchedImages.splice(0, 0, matchedImages.splice(thumbIndex, 1)[0]); matchedImages.sort((item)=>item === thumbUrl ? -1 : 1);
} }
out.image = matchedImages; out.image = matchedImages;

View File

@ -1,21 +1,39 @@
import get from 'lodash/get'; import get from 'lodash/get';
import { operationOrders } from '@hiveio/dhive/lib/utils';
import { utils } from '@hiveio/dhive';
import parseDate from './parseDate'; import parseDate from './parseDate';
import parseToken from './parseToken'; import parseToken from './parseToken';
import { vestsToHp } from './conversions'; import { vestsToHp } from './conversions';
import { getAccount, getAccountHistory, getConversionRequests, getFeedHistory, getOpenOrders, getSavingsWithdrawFrom } from '../providers/hive/dhive'; import {
fetchGlobalProps,
getAccount,
getAccountHistory,
getConversionRequests,
getFeedHistory,
getOpenOrders,
getSavingsWithdrawFrom,
} from '../providers/hive/dhive';
import { getCurrencyTokenRate, getLatestQuotes } from '../providers/ecency/ecency'; import { getCurrencyTokenRate, getLatestQuotes } from '../providers/ecency/ecency';
import { CoinActivitiesCollection, CoinActivity, CoinBase, CoinData, DataPair, QuoteItem } from '../redux/reducers/walletReducer'; import {
CoinActivitiesCollection,
CoinActivity,
CoinBase,
CoinData,
DataPair,
QuoteItem,
} from '../redux/reducers/walletReducer';
import { GlobalProps } from '../redux/reducers/accountReducer'; import { GlobalProps } from '../redux/reducers/accountReducer';
import { getEstimatedAmount } from './vote'; import { getEstimatedAmount } from './vote';
import { getPointsSummary, getPointsHistory } from '../providers/ecency/ePoint'; import { getPointsSummary, getPointsHistory } from '../providers/ecency/ePoint';
// Constant // Constant
import POINTS from '../constants/options/points'; import POINTS from '../constants/options/points';
import { COIN_IDS } from '../constants/defaultCoins'; import { COIN_IDS } from '../constants/defaultCoins';
import { operationOrders } from '@hiveio/dhive/lib/utils'; import {
import { ConversionRequest, OpenOrderItem, OrdersData, SavingsWithdrawRequest } from '../providers/hive/hive.types'; ConversionRequest,
OpenOrderItem,
SavingsWithdrawRequest,
} from '../providers/hive/hive.types';
import parseAsset from './parseAsset'; import parseAsset from './parseAsset';
import { utils } from '@hiveio/dhive';
export const transferTypes = [ export const transferTypes = [
'curation_reward', 'curation_reward',
@ -39,24 +57,16 @@ export const transferTypes = [
'fill_vesting_withdraw', 'fill_vesting_withdraw',
]; ];
const ECENCY_ACTIONS = [ const ECENCY_ACTIONS = ['dropdown_transfer', 'dropdown_promote', 'dropdown_boost'];
'dropdown_transfer', 'dropdown_promote', 'dropdown_boost'
];
const HIVE_ACTIONS = [ const HIVE_ACTIONS = [
'transfer_token', 'transfer_token',
'transfer_to_savings', 'transfer_to_savings',
'transfer_to_vesting', 'transfer_to_vesting',
'withdraw_hive' 'withdraw_hive',
];
const HBD_ACTIONS = [
'transfer_token',
'transfer_to_savings',
'convert',
'withdraw_hbd'
]; ];
const HBD_ACTIONS = ['transfer_token', 'transfer_to_savings', 'convert', 'withdraw_hbd'];
const HIVE_POWER_ACTIONS = ['delegate', 'power_down']; const HIVE_POWER_ACTIONS = ['delegate', 'power_down'];
export const groomingTransactionData = (transaction, hivePerMVests) => { export const groomingTransactionData = (transaction, hivePerMVests) => {
if (!transaction || !hivePerMVests) { if (!transaction || !hivePerMVests) {
return []; return [];
@ -64,7 +74,7 @@ export const groomingTransactionData = (transaction, hivePerMVests) => {
const result = { const result = {
iconType: 'MaterialIcons', iconType: 'MaterialIcons',
trxIndex:transaction[0] trxIndex: transaction[0],
}; };
[result.textKey] = transaction[1].op; [result.textKey] = transaction[1].op;
@ -102,8 +112,9 @@ export const groomingTransactionData = (transaction, hivePerMVests) => {
.toFixed(3) .toFixed(3)
.replace(',', '.'); .replace(',', '.');
result.value = `${hbdPayout > 0 ? `${hbdPayout} HBD` : ''} ${hivePayout > 0 ? `${hivePayout} HIVE` : '' result.value = `${hbdPayout > 0 ? `${hbdPayout} HBD` : ''} ${
} ${vestingPayout > 0 ? `${vestingPayout} HP` : ''}`; hivePayout > 0 ? `${hivePayout} HIVE` : ''
} ${vestingPayout > 0 ? `${vestingPayout} HP` : ''}`;
result.details = author && permlink ? `@${author}/${permlink}` : null; result.details = author && permlink ? `@${author}/${permlink}` : null;
if (result.textKey === 'comment_benefactor_reward') { if (result.textKey === 'comment_benefactor_reward') {
@ -117,8 +128,9 @@ export const groomingTransactionData = (transaction, hivePerMVests) => {
rewardHive = parseToken(rewardHive).toFixed(3).replace(',', '.'); rewardHive = parseToken(rewardHive).toFixed(3).replace(',', '.');
rewardVests = vestsToHp(parseToken(rewardVests), hivePerMVests).toFixed(3).replace(',', '.'); rewardVests = vestsToHp(parseToken(rewardVests), hivePerMVests).toFixed(3).replace(',', '.');
result.value = `${rewardHdb > 0 ? `${rewardHdb} HBD` : ''} ${rewardHive > 0 ? `${rewardHive} HIVE` : '' result.value = `${rewardHdb > 0 ? `${rewardHdb} HBD` : ''} ${
} ${rewardVests > 0 ? `${rewardVests} HP` : ''}`; rewardHive > 0 ? `${rewardHive} HIVE` : ''
} ${rewardVests > 0 ? `${rewardVests} HP` : ''}`;
break; break;
case 'transfer': case 'transfer':
case 'transfer_to_savings': case 'transfer_to_savings':
@ -263,7 +275,7 @@ export const groomingWalletData = async (user, globalProps, userCurrency) => {
walletData.nextVestingWithdrawal = Math.round(timeDiff / (1000 * 3600)); walletData.nextVestingWithdrawal = Math.round(timeDiff / (1000 * 3600));
//TOOD: transfer history can be separated from here //TOOD: transfer history can be separated from here
const op = utils.operationOrders const op = utils.operationOrders;
const ops = [ const ops = [
op.transfer, //HIVE op.transfer, //HIVE
op.author_reward, //HBD, HP op.author_reward, //HBD, HP
@ -279,7 +291,7 @@ export const groomingWalletData = async (user, globalProps, userCurrency) => {
op.sps_fund, //HBD op.sps_fund, //HBD
op.comment_benefactor_reward, //HP op.comment_benefactor_reward, //HP
op.return_vesting_delegation, //HP op.return_vesting_delegation, //HP
] ];
const history = await getAccountHistory(get(user, 'name'), ops); const history = await getAccountHistory(get(user, 'name'), ops);
@ -291,10 +303,10 @@ export const groomingWalletData = async (user, globalProps, userCurrency) => {
return walletData; return walletData;
}; };
const fetchPendingRequests = async (
username: string,
const fetchPendingRequests = async (username: string, coinSymbol: string): Promise<CoinActivity[]> => { coinSymbol: string,
): Promise<CoinActivity[]> => {
const _rawConversions = await getConversionRequests(username); const _rawConversions = await getConversionRequests(username);
const _rawOpenOrdres = await getOpenOrders(username); const _rawOpenOrdres = await getOpenOrders(username);
const _rawWithdrawRequests = await getSavingsWithdrawFrom(username); const _rawWithdrawRequests = await getSavingsWithdrawFrom(username);
@ -302,66 +314,63 @@ const fetchPendingRequests = async (username: string, coinSymbol: string): Promi
console.log('fetched pending requests', _rawConversions, _rawOpenOrdres, _rawWithdrawRequests); console.log('fetched pending requests', _rawConversions, _rawOpenOrdres, _rawWithdrawRequests);
const openOrderRequests = _rawOpenOrdres const openOrderRequests = _rawOpenOrdres
.filter(request => request.sell_price.base.includes(coinSymbol)) .filter((request) => request.sell_price.base.includes(coinSymbol))
.map((request) => { .map((request) => {
const { base, quote } = request?.sell_price || {}; const { base, quote } = request?.sell_price || {};
return ({ return {
iconType: "MaterialIcons", iconType: 'MaterialIcons',
textKey: 'open_order', textKey: 'open_order',
expires: request.expiration, expires: request.expiration,
created: request.created, created: request.created,
icon: 'reorder', icon: 'reorder',
value: base || '-- --', value: base || '-- --',
details: base && quote ? `@ ${base} = ${quote}` : '', details: base && quote ? `@ ${base} = ${quote}` : '',
} as CoinActivity) } as CoinActivity;
}) });
const withdrawRequests = _rawWithdrawRequests const withdrawRequests = _rawWithdrawRequests
.filter(request => request.amount.includes(coinSymbol)) .filter((request) => request.amount.includes(coinSymbol))
.map((request) => { .map((request) => {
return ({ return {
iconType: "MaterialIcons", iconType: 'MaterialIcons',
textKey: "withdraw_savings", textKey: 'withdraw_savings',
created: request.complete, created: request.complete,
icon: "compare-arrows", icon: 'compare-arrows',
value: request.amount, value: request.amount,
details: request.from && request.to ? `@${request.from} to @${request.to}` : null, details: request.from && request.to ? `@${request.from} to @${request.to}` : null,
memo: request.memo || null memo: request.memo || null,
} as CoinActivity) } as CoinActivity;
}) });
const conversionRequests = _rawConversions const conversionRequests = _rawConversions
.filter(request => request.amount.includes(coinSymbol)) .filter((request) => request.amount.includes(coinSymbol))
.map((request) => { .map((request) => {
return ({ return {
iconType: "MaterialIcons", iconType: 'MaterialIcons',
textKey: "convert_request", textKey: 'convert_request',
created: request.conversion_date, created: request.conversion_date,
icon: "hourglass-full", icon: 'hourglass-full',
value: request.amount value: request.amount,
} as CoinActivity) } as CoinActivity;
}) });
const pendingRequests = [ const pendingRequests = [...openOrderRequests, ...withdrawRequests, ...conversionRequests];
...openOrderRequests,
...withdrawRequests,
...conversionRequests
];
pendingRequests.sort((a, b) => ( pendingRequests.sort((a, b) =>
new Date(a.expires || a.created).getTime() > new Date(b.expires || b.created).getTime() ? 1 : -1 new Date(a.expires || a.created).getTime() > new Date(b.expires || b.created).getTime()
)) ? 1
: -1,
);
return pendingRequests; return pendingRequests;
} };
/** /**
* *
* @param username * @param username
* @param coinId * @param coinId
* @param coinSymbol * @param coinSymbol
* @param globalProps * @param globalProps
* @returns {Promise<CoinActivitiesCollection>} * @returns {Promise<CoinActivitiesCollection>}
*/ */
export const fetchCoinActivities = async ( export const fetchCoinActivities = async (
@ -370,131 +379,109 @@ export const fetchCoinActivities = async (
coinSymbol: string, coinSymbol: string,
globalProps: GlobalProps, globalProps: GlobalProps,
startIndex: number, startIndex: number,
limit:number limit: number,
): Promise<CoinActivitiesCollection> => { ): Promise<CoinActivitiesCollection> => {
const op = operationOrders; const op = operationOrders;
let history = []; let history = [];
switch (coinId) { switch (coinId) {
case COIN_IDS.ECENCY: { case COIN_IDS.ECENCY: {
//TODO: remove condition when we have a way to fetch paginated points data //TODO: remove condition when we have a way to fetch paginated points data
if(startIndex !== -1){ if (startIndex !== -1) {
return { return {
completed:[], completed: [],
pending:[] pending: [],
} };
} }
const pointActivities = await getPointsHistory(username); const pointActivities = await getPointsHistory(username);
console.log("Points Activities", pointActivities); console.log('Points Activities', pointActivities);
const completed = pointActivities && pointActivities.length ? const completed =
pointActivities.map((item) => pointActivities && pointActivities.length
groomingPointsTransactionData({ ? pointActivities.map((item) =>
...item, groomingPointsTransactionData({
icon: get(POINTS[get(item, 'type')], 'icon'), ...item,
iconType: get(POINTS[get(item, 'type')], 'iconType'), icon: get(POINTS[get(item, 'type')], 'icon'),
textKey: get(POINTS[get(item, 'type')], 'textKey'), iconType: get(POINTS[get(item, 'type')], 'iconType'),
}) textKey: get(POINTS[get(item, 'type')], 'textKey'),
) : []; }),
)
: [];
return { return {
completed, completed,
pending: [] as CoinActivity[] pending: [] as CoinActivity[],
} };
} }
case COIN_IDS.HIVE: case COIN_IDS.HIVE:
history = await getAccountHistory(username, [ history = await getAccountHistory(
op.transfer, //HIVE username,
op.transfer_to_vesting, //HIVE, HP [
op.withdraw_vesting, //HIVE, HP op.transfer, //HIVE
op.transfer_to_savings, //HIVE, HBD op.transfer_to_vesting, //HIVE, HP
op.transfer_from_savings, //HIVE, HBD op.withdraw_vesting, //HIVE, HP
op.fill_order, //HIVE, HBD op.transfer_to_savings, //HIVE, HBD
], startIndex, limit); op.transfer_from_savings, //HIVE, HBD
op.fill_order, //HIVE, HBD
],
startIndex,
limit,
);
break; break;
case COIN_IDS.HBD: case COIN_IDS.HBD:
history = await getAccountHistory(username, [ history = await getAccountHistory(
op.transfer, //HIVE //HBD username,
op.author_reward, //HBD, HP [
op.transfer_to_savings, //HIVE, HBD op.transfer, //HIVE //HBD
op.transfer_from_savings, //HIVE, HBD op.author_reward, //HBD, HP
op.fill_convert_request, //HBD op.transfer_to_savings, //HIVE, HBD
op.fill_order, //HIVE, HBD op.transfer_from_savings, //HIVE, HBD
op.sps_fund, //HBD op.fill_convert_request, //HBD
], startIndex, limit); op.fill_order, //HIVE, HBD
op.sps_fund, //HBD
],
startIndex,
limit,
);
break; break;
case COIN_IDS.HP: case COIN_IDS.HP:
history = await getAccountHistory(username, [ history = await getAccountHistory(
op.author_reward, //HBD, HP username,
op.curation_reward, //HP [
op.transfer_to_vesting, //HIVE, HP op.author_reward, //HBD, HP
op.withdraw_vesting, //HIVE, HP op.curation_reward, //HP
op.interest, //HP op.transfer_to_vesting, //HIVE, HP
op.claim_reward_balance, //HP op.withdraw_vesting, //HIVE, HP
op.comment_benefactor_reward, //HP op.interest, //HP
op.return_vesting_delegation, //HP op.claim_reward_balance, //HP
], startIndex, limit); op.comment_benefactor_reward, //HP
op.return_vesting_delegation, //HP
],
startIndex,
limit,
);
break; break;
} }
const transfers = history.filter((tx) => transferTypes.includes(get(tx[1], 'op[0]', false))); const transfers = history.filter((tx) => transferTypes.includes(get(tx[1], 'op[0]', false)));
transfers.sort(compare); transfers.sort(compare);
const activities = transfers.map(item => groomingTransactionData(item, globalProps.hivePerMVests)); const activities = transfers.map((item) =>
groomingTransactionData(item, globalProps.hivePerMVests),
);
const filterdActivities: CoinActivity[] = activities const filterdActivities: CoinActivity[] = activities
? activities.filter((item) => { ? activities.filter((item) => {
return ( return item && item.value && item.value.includes(coinSymbol);
item && })
item.value &&
item.value.includes(coinSymbol)
);
})
: []; : [];
console.log('FILTERED comap', activities.length, filterdActivities.length) console.log('FILTERED comap', activities.length, filterdActivities.length);
const pendingRequests = await fetchPendingRequests(username, coinSymbol); const pendingRequests = await fetchPendingRequests(username, coinSymbol);
return { return {
completed: filterdActivities, completed: filterdActivities,
pending: pendingRequests, pending: pendingRequests,
} };
};
}
const calculateConvertingAmount = (requests: ConversionRequest[]): number => {
if (!requests || !requests.length) {
return 0;
}
//TODO: add method body
// ecency-vision -> src/common/components/wallet-hive/index.tsx#fetchConvertingAmount
throw new Error("calculateConvertingAmount method body not implemented yet");
}
const calculateSavingsWithdrawalAmount = (requests: SavingsWithdrawRequest[], coinSymbol: string): number => {
return requests.reduce((prevVal, curRequest) => {
const _amount = curRequest.amount;
return _amount.includes(coinSymbol)
? prevVal + parseAsset(_amount).amount
: prevVal
}, 0);
}
const calculateOpenOrdersAmount = (requests: OpenOrderItem[], coinSymbol: string): number => {
return requests.reduce((prevVal, curRequest) => {
const _basePrice = curRequest.sell_price.base;
return _basePrice.includes(coinSymbol)
? prevVal + parseAsset(_basePrice).amount
: prevVal
}, 0);
}
export const fetchCoinsData = async ({ export const fetchCoinsData = async ({
coins, coins,
@ -505,36 +492,32 @@ export const fetchCoinsData = async ({
refresh, refresh,
quotes, quotes,
}: { }: {
coins: CoinBase[], coins: CoinBase[];
currentAccount: any, currentAccount: any;
vsCurrency: string, vsCurrency: string;
currencyRate: number, currencyRate: number;
globalProps: GlobalProps, globalProps: GlobalProps;
quotes: { [key: string]: QuoteItem } quotes: { [key: string]: QuoteItem };
refresh: boolean, refresh: boolean;
}) }): Promise<{ [key: string]: CoinData }> => {
: Promise<{ [key: string]: CoinData }> => {
const username = currentAccount.username; const username = currentAccount.username;
const { base, quote, hivePerMVests } = globalProps
const coinData = {} as { [key: string]: CoinData }; const coinData = {} as { [key: string]: CoinData };
const walletData = {} as any; const walletData = {} as any;
if (!username) { if (!username) {
return walletData; return walletData;
} }
//fetch latest global props if refresh or data not available
const { base, quote, hivePerMVests } =
refresh || !globalProps || !globalProps.hivePerMVests ? await fetchGlobalProps() : globalProps;
//TODO: Use already available accoutn for frist wallet start //TODO: Use already available accoutn for frist wallet start
const userdata = refresh ? await getAccount(username) : currentAccount; const userdata = refresh ? await getAccount(username) : currentAccount;
const _pointsSummary = refresh ? await getPointsSummary(username) : currentAccount.pointsSummary const _pointsSummary = refresh ? await getPointsSummary(username) : currentAccount.pointsSummary;
//TODO: cache data in redux or fetch once on wallet startup //TODO: cache data in redux or fetch once on wallet startup
const _prices = !refresh && quotes ? quotes : await getLatestQuotes(currencyRate); //TODO: figure out a way to handle other currencies const _prices = !refresh && quotes ? quotes : await getLatestQuotes(currencyRate); //TODO: figure out a way to handle other currencies
coins.forEach((coinBase) => { coins.forEach((coinBase) => {
switch (coinBase.id) { switch (coinBase.id) {
case COIN_IDS.ECENCY: { case COIN_IDS.ECENCY: {
const balance = _pointsSummary.points ? parseFloat(_pointsSummary.points) : 0; const balance = _pointsSummary.points ? parseFloat(_pointsSummary.points) : 0;
@ -549,7 +532,7 @@ export const fetchCoinsData = async ({
currentPrice: ppEstm, currentPrice: ppEstm,
unclaimedBalance: unclaimedBalance, unclaimedBalance: unclaimedBalance,
actions: ECENCY_ACTIONS, actions: ECENCY_ACTIONS,
} };
break; break;
} }
case COIN_IDS.HIVE: { case COIN_IDS.HIVE: {
@ -557,7 +540,6 @@ export const fetchCoinsData = async ({
const savings = parseToken(userdata.savings_balance); const savings = parseToken(userdata.savings_balance);
const ppHive = _prices[coinBase.id].price; const ppHive = _prices[coinBase.id].price;
coinData[coinBase.id] = { coinData[coinBase.id] = {
balance: Math.round(balance * 1000) / 1000, balance: Math.round(balance * 1000) / 1000,
estimateValue: (balance + savings) * ppHive, estimateValue: (balance + savings) * ppHive,
@ -566,7 +548,7 @@ export const fetchCoinsData = async ({
currentPrice: ppHive, currentPrice: ppHive,
unclaimedBalance: '', unclaimedBalance: '',
actions: HIVE_ACTIONS, actions: HIVE_ACTIONS,
} };
break; break;
} }
@ -583,33 +565,27 @@ export const fetchCoinsData = async ({
currentPrice: ppHbd, currentPrice: ppHbd,
unclaimedBalance: '', unclaimedBalance: '',
actions: HBD_ACTIONS, actions: HBD_ACTIONS,
} };
break; break;
} }
case COIN_IDS.HP: { case COIN_IDS.HP: {
const _getBalanceStr = (val: number, cur: string) => (val ? Math.round(val * 1000) / 1000 + cur : ''); const _getBalanceStr = (val: number, cur: string) =>
const balance = Math.round( val ? Math.round(val * 1000) / 1000 + cur : '';
vestsToHp(parseToken(userdata.vesting_shares), hivePerMVests) * 1000, const balance =
) / 1000; Math.round(vestsToHp(parseToken(userdata.vesting_shares), hivePerMVests) * 1000) / 1000;
const receivedHP = vestsToHp( const receivedHP = vestsToHp(parseToken(userdata.received_vesting_shares), hivePerMVests);
parseToken(userdata.received_vesting_shares),
hivePerMVests,
)
const delegatedHP = vestsToHp( const delegatedHP = vestsToHp(parseToken(userdata.delegated_vesting_shares), hivePerMVests);
parseToken(userdata.delegated_vesting_shares),
hivePerMVests,
)
//agggregate claim button text //agggregate claim button text
const unclaimedBalance = [ const unclaimedBalance = [
_getBalanceStr(parseToken(userdata.reward_hive_balance), ' HIVE'), _getBalanceStr(parseToken(userdata.reward_hive_balance), ' HIVE'),
_getBalanceStr(parseToken(userdata.reward_hbd_balance), ' HBD'), _getBalanceStr(parseToken(userdata.reward_hbd_balance), ' HBD'),
_getBalanceStr(parseToken(userdata.reward_vesting_hive), ' HP') _getBalanceStr(parseToken(userdata.reward_vesting_hive), ' HP'),
].reduce( ].reduce(
(prevVal, bal) => prevVal + (!bal ? '' : (`${prevVal !== '' ? ' ' : ''}${bal}`)), (prevVal, bal) => prevVal + (!bal ? '' : `${prevVal !== '' ? ' ' : ''}${bal}`),
'' '',
); );
//calculate power down //calculate power down
@ -619,49 +595,57 @@ export const fetchCoinsData = async ({
const nextVestingSharesWithdrawal = isPoweringDown const nextVestingSharesWithdrawal = isPoweringDown
? Math.min( ? Math.min(
parseAsset(userdata.vesting_withdraw_rate).amount, parseAsset(userdata.vesting_withdraw_rate).amount,
(Number(userdata.to_withdraw) - Number(userdata.withdrawn)) / 1e6 (Number(userdata.to_withdraw) - Number(userdata.withdrawn)) / 1e6,
) : 0; )
const nextVestingSharesWithdrawalHive = isPoweringDown ? vestsToHp(nextVestingSharesWithdrawal, hivePerMVests) : 0; : 0;
const nextVestingSharesWithdrawalHive = isPoweringDown
? vestsToHp(nextVestingSharesWithdrawal, hivePerMVests)
: 0;
const estimateVoteValueStr = '$ ' + getEstimatedAmount(userdata, globalProps); const estimateVoteValueStr = '$ ' + getEstimatedAmount(userdata, globalProps);
//aaggregate extra data pairs //aaggregate extra data pairs
const extraDataPairs:DataPair[] = []; const extraDataPairs: DataPair[] = [];
if (delegatedHP) { if (delegatedHP) {
extraDataPairs.push({ extraDataPairs.push({
dataKey: 'delegated_hive_power', dataKey: 'delegated_hive_power',
value: `- ${delegatedHP.toFixed(3)} HP`, value: `- ${delegatedHP.toFixed(3)} HP`,
isClickable: true isClickable: true,
}) });
} }
if (receivedHP) { if (receivedHP) {
extraDataPairs.push({ extraDataPairs.push({
dataKey: 'received_hive_power', dataKey: 'received_hive_power',
value: `+ ${receivedHP.toFixed(3)} HP`, value: `+ ${receivedHP.toFixed(3)} HP`,
isClickable: true isClickable: true,
}) });
} }
if (nextVestingSharesWithdrawalHive) { if (nextVestingSharesWithdrawalHive) {
extraDataPairs.push({ extraDataPairs.push({
dataKey: 'powering_down_hive_power', dataKey: 'powering_down_hive_power',
value: `- ${nextVestingSharesWithdrawalHive.toFixed(3)} HP` value: `- ${nextVestingSharesWithdrawalHive.toFixed(3)} HP`,
}) });
} }
extraDataPairs.concat([ extraDataPairs.concat([
{ {
dataKey: 'total_hive_power', dataKey: 'total_hive_power',
value: `${(balance - delegatedHP + receivedHP - nextVestingSharesWithdrawalHive).toFixed(3)} HP` value: `${(
}, { balance -
delegatedHP +
receivedHP -
nextVestingSharesWithdrawalHive
).toFixed(3)} HP`,
},
{
dataKey: 'vote_value', dataKey: 'vote_value',
value: estimateVoteValueStr value: estimateVoteValueStr,
} },
]) ]);
const ppHive = _prices[COIN_IDS.HIVE].price; const ppHive = _prices[COIN_IDS.HIVE].price;
coinData[coinBase.id] = { coinData[coinBase.id] = {
@ -672,22 +656,29 @@ export const fetchCoinsData = async ({
currentPrice: ppHive, currentPrice: ppHive,
actions: HIVE_POWER_ACTIONS, actions: HIVE_POWER_ACTIONS,
extraDataPairs: [ extraDataPairs: [
...extraDataPairs, { ...extraDataPairs,
{
dataKey: 'total_hive_power', dataKey: 'total_hive_power',
value: `${(balance - delegatedHP + receivedHP - nextVestingSharesWithdrawalHive).toFixed(3)} HP` value: `${(
}, { balance -
delegatedHP +
receivedHP -
nextVestingSharesWithdrawalHive
).toFixed(3)} HP`,
},
{
dataKey: 'vote_value', dataKey: 'vote_value',
value: estimateVoteValueStr value: estimateVoteValueStr,
} },
] ],
} };
break; break;
} }
default: default:
break; break;
} }
}) });
//TODO:discard unnessacry data processings towards the end of PR //TODO:discard unnessacry data processings towards the end of PR
walletData.rewardHiveBalance = parseToken(userdata.reward_hive_balance); walletData.rewardHiveBalance = parseToken(userdata.reward_hive_balance);
@ -709,8 +700,6 @@ export const fetchCoinsData = async ({
walletData.savingBalance = parseToken(userdata.savings_balance); walletData.savingBalance = parseToken(userdata.savings_balance);
walletData.savingBalanceHbd = parseToken(userdata.savings_hbd_balance); walletData.savingBalanceHbd = parseToken(userdata.savings_hbd_balance);
walletData.hivePerMVests = hivePerMVests; walletData.hivePerMVests = hivePerMVests;
const pricePerHive = base / quote; const pricePerHive = base / quote;
@ -723,15 +712,12 @@ export const fetchCoinsData = async ({
walletData.estimatedValue = totalHive * pricePerHive + totalHbd; walletData.estimatedValue = totalHive * pricePerHive + totalHbd;
walletData.showPowerDown = userdata.next_vesting_withdrawal !== '1969-12-31T23:59:59'; walletData.showPowerDown = userdata.next_vesting_withdrawal !== '1969-12-31T23:59:59';
const timeDiff = Math.abs(parseDate(userdata.next_vesting_withdrawal) - new Date()); const timeDiff = Math.abs(parseDate(userdata.next_vesting_withdrawal) - new Date());
walletData.nextVestingWithdrawal = Math.round(timeDiff / (1000 * 3600)); walletData.nextVestingWithdrawal = Math.round(timeDiff / (1000 * 3600));
return coinData; return coinData;
} };
function compare(a, b) { function compare(a, b) {
if (a[1].block < b[1].block) { if (a[1].block < b[1].block) {