mirror of
https://github.com/ecency/ecency-mobile.git
synced 2024-12-16 18:03:14 +03:00
Merge remote-tracking branch 'upstream/development' into nt/use-query-notifications
This commit is contained in:
commit
b8ea6db4e5
@ -30,9 +30,7 @@ const DraftsScreen = ({
|
||||
moveScheduleToDraft,
|
||||
initialTabIndex,
|
||||
}) => {
|
||||
|
||||
|
||||
const isDarkTheme = useAppSelector(state=>state.application.isDarkTheme);
|
||||
const isDarkTheme = useAppSelector((state) => state.application.isDarkTheme);
|
||||
|
||||
// Component Functions
|
||||
const _renderItem = (item, type) => {
|
||||
@ -105,13 +103,16 @@ const DraftsScreen = ({
|
||||
removeClippedSubviews={false}
|
||||
renderItem={({ item }) => _renderItem(item, type)}
|
||||
ListEmptyComponent={_renderEmptyContent()}
|
||||
refreshControl={<RefreshControl
|
||||
refreshing={isLoading}
|
||||
onRefresh={onRefresh}
|
||||
progressBackgroundColor="#357CE6"
|
||||
tintColor={!isDarkTheme ? '#357ce6' : '#96c0ff'}
|
||||
titleColor="#fff"
|
||||
colors={['#fff']} />}
|
||||
refreshControl={
|
||||
<RefreshControl
|
||||
refreshing={isLoading}
|
||||
onRefresh={onRefresh}
|
||||
progressBackgroundColor="#357CE6"
|
||||
tintColor={!isDarkTheme ? '#357ce6' : '#96c0ff'}
|
||||
titleColor="#fff"
|
||||
colors={['#fff']}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
|
@ -33,13 +33,13 @@ export interface PostOptionsModalRef {
|
||||
interface PostOptionsModalProps {
|
||||
body:string;
|
||||
draftId:string;
|
||||
thumbIndex:number,
|
||||
thumbUrl:string,
|
||||
isEdit:boolean;
|
||||
isCommunityPost:boolean;
|
||||
rewardType: string;
|
||||
isUploading: boolean;
|
||||
handleRewardChange:(rewardType:string)=>void;
|
||||
handleThumbSelection:(index:number)=>void;
|
||||
handleThumbSelection:(url:string)=>void;
|
||||
handleScheduleChange:(datetime:string|null)=>void;
|
||||
handleShouldReblogChange:(shouldReblog:boolean)=>void;
|
||||
handleFormUpdate:()=>void;
|
||||
@ -48,7 +48,7 @@ interface PostOptionsModalProps {
|
||||
const PostOptionsModal = forwardRef(({
|
||||
body,
|
||||
draftId,
|
||||
thumbIndex,
|
||||
thumbUrl,
|
||||
isEdit,
|
||||
isCommunityPost,
|
||||
rewardType,
|
||||
@ -121,8 +121,8 @@ const PostOptionsModal = forwardRef(({
|
||||
}
|
||||
|
||||
// handle index change here instead of useeffetc
|
||||
const _handleThumbIndexSelection = (index:number) => {
|
||||
handleThumbSelection(index)
|
||||
const _handleThumbIndexSelection = (url:string) => {
|
||||
handleThumbSelection(url)
|
||||
}
|
||||
|
||||
const _renderContent = () => (
|
||||
@ -190,7 +190,7 @@ const PostOptionsModal = forwardRef(({
|
||||
|
||||
<ThumbSelectionContent
|
||||
body={body}
|
||||
thumbIndex={thumbIndex}
|
||||
thumbUrl={thumbUrl}
|
||||
isUploading={isUploading}
|
||||
onThumbSelection={_handleThumbIndexSelection}
|
||||
/>
|
||||
|
@ -1,4 +1,3 @@
|
||||
import { ViewStyle } from 'react-native';
|
||||
import EStyleSheet from 'react-native-extended-stylesheet';
|
||||
import { getBottomSpace } from 'react-native-iphone-x-helper';
|
||||
|
||||
@ -20,9 +19,12 @@ export default EStyleSheet.create({
|
||||
borderRadius:12,
|
||||
backgroundColor:'$primaryLightGray'
|
||||
},
|
||||
selectedStyle:{
|
||||
borderWidth:4,
|
||||
borderColor:'$primaryBlack'
|
||||
checkContainer:{
|
||||
position: 'absolute',
|
||||
top: 12,
|
||||
left: 6,
|
||||
backgroundColor: '$pureWhite',
|
||||
borderRadius: 12
|
||||
},
|
||||
settingLabel:{
|
||||
color: '$primaryDarkGray',
|
||||
|
@ -1,61 +1,91 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
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 { FlatList } from 'react-native-gesture-handler';
|
||||
import { extractImageUrls } from '../../../utils/editor';
|
||||
import styles from './styles';
|
||||
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 {
|
||||
body: string;
|
||||
thumbIndex: number;
|
||||
thumbUrl: string;
|
||||
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 [imageUrls, setImageUrls] = useState<string[]>([]);
|
||||
const [needMore, setNeedMore] = useState(true);
|
||||
const [thumbIndex, setThumbIndex] = useState(0);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
const urls = extractImageUrls({ body });
|
||||
|
||||
if (urls.length < 2) {
|
||||
setNeedMore(true);
|
||||
onThumbSelection(0);
|
||||
onThumbSelection(urls[0] || '');
|
||||
setThumbIndex(0);
|
||||
setImageUrls([])
|
||||
} else {
|
||||
setNeedMore(false);
|
||||
setImageUrls(urls)
|
||||
}
|
||||
|
||||
const _urlIndex = urls.indexOf(thumbUrl)
|
||||
if (_urlIndex < 0) {
|
||||
onThumbSelection(urls[0] || '');
|
||||
setThumbIndex(0);
|
||||
} else {
|
||||
setThumbIndex(_urlIndex)
|
||||
}
|
||||
|
||||
}, [body])
|
||||
|
||||
|
||||
//VIEW_RENDERERS
|
||||
const _renderImageItem = ({ item, index }: { item: string, index: number }) => {
|
||||
const _onPress = () => {
|
||||
onThumbSelection(index);
|
||||
onThumbSelection(item);
|
||||
setThumbIndex(index);
|
||||
}
|
||||
|
||||
const selectedStyle = index === thumbIndex ? styles.selectedStyle : null
|
||||
const isSelected = item === thumbUrl && index === thumbIndex;
|
||||
|
||||
return (
|
||||
<TouchableOpacity onPress={() => _onPress()} >
|
||||
<FastImage
|
||||
source={{ uri: item }}
|
||||
style={{ ...styles.thumbStyle, ...selectedStyle }}
|
||||
style={styles.thumbStyle}
|
||||
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>
|
||||
)
|
||||
}
|
||||
|
||||
const _renderHeader = () => (
|
||||
isUploading &&
|
||||
<View style={{flex:1, justifyContent:'center', marginRight: 16}}>
|
||||
isUploading &&
|
||||
<View style={{ flex: 1, justifyContent: 'center', marginRight: 16 }}>
|
||||
<ActivityIndicator color={ESStyleSheet.value('$primaryBlack')} />
|
||||
</View>
|
||||
|
||||
|
@ -11,12 +11,12 @@ import { useIntl } from 'react-intl';
|
||||
|
||||
|
||||
export interface ThumbSelectionModalProps {
|
||||
thumbIndex:number;
|
||||
thumbUrl:string;
|
||||
onThumbSelection:(index:number)=>void;
|
||||
}
|
||||
|
||||
|
||||
const ThumbSelectionModal = ({ onThumbSelection, thumbIndex }:ThumbSelectionModalProps, ref) => {
|
||||
const ThumbSelectionModal = ({ onThumbSelection, thumbUrl }:ThumbSelectionModalProps, ref) => {
|
||||
const intl = useIntl();
|
||||
|
||||
const [imageUrls, setImageUrls] = useState<string[]>([]);
|
||||
@ -57,7 +57,7 @@ const ThumbSelectionModal = ({ onThumbSelection, thumbIndex }:ThumbSelectionModa
|
||||
_onSelection(index);
|
||||
}
|
||||
|
||||
const selectedStyle = index === thumbIndex ? styles.selectedStyle : null
|
||||
const selectedStyle = item === thumbUrl ? styles.selectedStyle : null
|
||||
|
||||
return (
|
||||
<TouchableOpacity onPress={() => _onPress()} >
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { injectIntl } from 'react-intl';
|
||||
import { Alert } from 'react-native';
|
||||
import { Alert, AppState, AppStateStatus } from 'react-native';
|
||||
import get from 'lodash/get';
|
||||
import AsyncStorage from '@react-native-community/async-storage';
|
||||
import { isArray } from 'lodash';
|
||||
@ -44,6 +44,7 @@ import {
|
||||
updateDraftCache,
|
||||
} from '../../../redux/actions/cacheActions';
|
||||
import QUERIES from '../../../providers/queries/queryKeys';
|
||||
import bugsnapInstance from '../../../config/bugsnag';
|
||||
|
||||
/*
|
||||
* Props Name Description Value
|
||||
@ -54,6 +55,7 @@ import QUERIES from '../../../providers/queries/queryKeys';
|
||||
class EditorContainer extends Component<any, any> {
|
||||
_isMounted = false;
|
||||
_updatedDraftFields = null;
|
||||
_appState = AppState.currentState;
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
@ -71,14 +73,12 @@ class EditorContainer extends Component<any, any> {
|
||||
uploadProgress: 0,
|
||||
post: null,
|
||||
uploadedImage: null,
|
||||
isDraft: false,
|
||||
community: [],
|
||||
rewardType: 'default',
|
||||
sharedSnippetText: null,
|
||||
onLoadDraftPress: false,
|
||||
thumbIndex: 0,
|
||||
thumbUrl: '',
|
||||
shouldReblog: false,
|
||||
failedImageUploads: 0,
|
||||
};
|
||||
}
|
||||
|
||||
@ -105,7 +105,6 @@ class EditorContainer extends Component<any, any> {
|
||||
|
||||
this.setState({
|
||||
draftId: _draft._id,
|
||||
isDraft: true,
|
||||
});
|
||||
this._getStorageDraft(username, isReply, _draft);
|
||||
}
|
||||
@ -173,13 +172,13 @@ class EditorContainer extends Component<any, any> {
|
||||
this._fetchDraftsForComparison(isReply);
|
||||
}
|
||||
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 (
|
||||
prevState.rewardType !== this.state.rewardType ||
|
||||
prevProps.beneficiariesMap !== this.props.beneficiariesMap
|
||||
@ -188,8 +187,21 @@ class EditorContainer extends Component<any, any> {
|
||||
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) => {
|
||||
const { drafts, dispatch } = this.props;
|
||||
const { drafts } = this.props;
|
||||
if (isReply) {
|
||||
const _draft = drafts.get(paramDraft._id);
|
||||
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 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({
|
||||
draftPost: {
|
||||
body: get(_localDraft, 'body', ''),
|
||||
title: get(_localDraft, 'title', ''),
|
||||
tags: get(_localDraft, 'tags', '').split(','),
|
||||
isDraft: paramDraft ? true : false,
|
||||
draftId: paramDraft ? paramDraft._id : null,
|
||||
meta: _localDraft.meta ? _localDraft.meta : null,
|
||||
},
|
||||
@ -234,7 +247,6 @@ class EditorContainer extends Component<any, any> {
|
||||
tags: _tags,
|
||||
meta: paramDraft.meta ? paramDraft.meta : null,
|
||||
},
|
||||
isDraft: true,
|
||||
draftId: paramDraft._id,
|
||||
});
|
||||
|
||||
@ -250,9 +262,8 @@ class EditorContainer extends Component<any, any> {
|
||||
const body = draft.body;
|
||||
if (draft.meta && draft.meta.image) {
|
||||
const urls = extractImageUrls({ body });
|
||||
const draftThumbIndex = urls.indexOf(draft.meta.image[0]);
|
||||
this.setState({
|
||||
thumbIndex: draftThumbIndex,
|
||||
thumbUrl: draft.meta.image[0],
|
||||
});
|
||||
}
|
||||
|
||||
@ -290,7 +301,7 @@ class EditorContainer extends Component<any, any> {
|
||||
* @param isReply
|
||||
**/
|
||||
_fetchDraftsForComparison = async (isReply) => {
|
||||
const { currentAccount, isLoggedIn, intl, dispatch, drafts } = this.props;
|
||||
const { currentAccount, isLoggedIn, drafts } = this.props;
|
||||
const username = get(currentAccount, 'name', '');
|
||||
|
||||
//initilizes editor with reply or non remote id less draft
|
||||
@ -345,7 +356,6 @@ class EditorContainer extends Component<any, any> {
|
||||
//initilize editor as draft
|
||||
this.setState({
|
||||
draftId: _draft._id,
|
||||
isDraft: true,
|
||||
});
|
||||
this._getStorageDraft(username, isReply, _draft);
|
||||
};
|
||||
@ -373,11 +383,18 @@ class EditorContainer extends Component<any, any> {
|
||||
};
|
||||
|
||||
_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;
|
||||
|
||||
if (isReply) {
|
||||
try {
|
||||
//saves draft locallly
|
||||
this._saveCurrentDraft(this._updatedDraftFields);
|
||||
} catch (err) {
|
||||
console.warn('local draft safe failed, skipping for remote only', err);
|
||||
bugsnapInstance.notify(err);
|
||||
}
|
||||
|
||||
if (isReply) {
|
||||
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,
|
||||
beneficiaries,
|
||||
rewardType,
|
||||
@ -467,9 +484,6 @@ class EditorContainer extends Component<any, any> {
|
||||
isDraftSaving: false,
|
||||
isDraftSaved: false,
|
||||
});
|
||||
|
||||
//saves draft locally if remote draft save fails
|
||||
this._saveCurrentDraft(this._updatedDraftFields);
|
||||
}
|
||||
|
||||
dispatch(
|
||||
@ -529,7 +543,7 @@ class EditorContainer extends Component<any, any> {
|
||||
pinCode,
|
||||
// isDefaultFooter,
|
||||
} = this.props;
|
||||
const { rewardType, isPostSending, thumbIndex, draftId, shouldReblog } = this.state;
|
||||
const { rewardType, isPostSending, thumbUrl, draftId, shouldReblog } = this.state;
|
||||
|
||||
const beneficiaries = this._extractBeneficiaries();
|
||||
|
||||
@ -542,7 +556,7 @@ class EditorContainer extends Component<any, any> {
|
||||
isPostSending: true,
|
||||
});
|
||||
|
||||
const meta = extractMetadata(fields.body, thumbIndex);
|
||||
const meta = extractMetadata(fields.body, thumbUrl);
|
||||
const _tags = fields.tags.filter((tag) => tag && tag !== ' ');
|
||||
|
||||
const jsonMeta = makeJsonMetadata(meta, _tags);
|
||||
@ -703,7 +717,7 @@ class EditorContainer extends Component<any, any> {
|
||||
|
||||
_submitEdit = async (fields) => {
|
||||
const { currentAccount, pinCode, dispatch } = this.props;
|
||||
const { post, isEdit, isPostSending, thumbIndex, isReply } = this.state;
|
||||
const { post, isEdit, isPostSending, thumbUrl, isReply } = this.state;
|
||||
|
||||
if (isPostSending) {
|
||||
return;
|
||||
@ -729,7 +743,7 @@ class EditorContainer extends Component<any, any> {
|
||||
newBody = patch;
|
||||
}
|
||||
|
||||
const meta = extractMetadata(fields.body, thumbIndex);
|
||||
const meta = extractMetadata(fields.body, thumbUrl);
|
||||
|
||||
let jsonMeta = {};
|
||||
|
||||
@ -1019,9 +1033,9 @@ class EditorContainer extends Component<any, any> {
|
||||
});
|
||||
};
|
||||
|
||||
_handleSetThumbIndex = (index: number) => {
|
||||
_handleSetThumbUrl = (url: string) => {
|
||||
this.setState({
|
||||
thumbIndex: index,
|
||||
thumbUrl: url,
|
||||
});
|
||||
};
|
||||
|
||||
@ -1050,7 +1064,7 @@ class EditorContainer extends Component<any, any> {
|
||||
community,
|
||||
sharedSnippetText,
|
||||
onLoadDraftPress,
|
||||
thumbIndex,
|
||||
thumbUrl,
|
||||
uploadProgress,
|
||||
rewardType,
|
||||
} = this.state;
|
||||
@ -1090,8 +1104,8 @@ class EditorContainer extends Component<any, any> {
|
||||
draftId={draftId}
|
||||
sharedSnippetText={sharedSnippetText}
|
||||
onLoadDraftPress={onLoadDraftPress}
|
||||
thumbIndex={thumbIndex}
|
||||
setThumbIndex={this._handleSetThumbIndex}
|
||||
thumbUrl={thumbUrl}
|
||||
setThumbUrl={this._handleSetThumbUrl}
|
||||
uploadProgress={uploadProgress}
|
||||
rewardType={rewardType}
|
||||
getBeneficiaries={this._extractBeneficiaries}
|
||||
|
@ -192,10 +192,10 @@ class EditorScreen extends Component {
|
||||
}
|
||||
};
|
||||
|
||||
_handleOnThumbSelection = (index) => {
|
||||
const { setThumbIndex } = this.props;
|
||||
if (setThumbIndex) {
|
||||
setThumbIndex(index);
|
||||
_handleOnThumbSelection = (url:string) => {
|
||||
const { setThumbUrl } = this.props;
|
||||
if (setThumbUrl) {
|
||||
setThumbUrl(url);
|
||||
}
|
||||
};
|
||||
|
||||
@ -236,7 +236,7 @@ class EditorScreen extends Component {
|
||||
};
|
||||
|
||||
_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 };
|
||||
|
||||
@ -248,7 +248,7 @@ class EditorScreen extends Component {
|
||||
fields.tags = content;
|
||||
}
|
||||
|
||||
const meta = Object.assign({}, extractMetadata(fields.body, thumbIndex), {
|
||||
const meta = Object.assign({}, extractMetadata(fields.body, thumbUrl), {
|
||||
tags: fields.tags,
|
||||
beneficiaries: getBeneficiaries(),
|
||||
rewardType,
|
||||
@ -381,7 +381,7 @@ class EditorScreen extends Component {
|
||||
autoFocusText,
|
||||
sharedSnippetText,
|
||||
onLoadDraftPress,
|
||||
thumbIndex,
|
||||
thumbUrl,
|
||||
uploadProgress,
|
||||
rewardType,
|
||||
setIsUploading,
|
||||
@ -484,7 +484,7 @@ class EditorScreen extends Component {
|
||||
ref={(componentRef) => (this.postOptionsModalRef = componentRef)}
|
||||
body={fields.body}
|
||||
draftId={draftId}
|
||||
thumbIndex={thumbIndex}
|
||||
thumbUrl={thumbUrl}
|
||||
isEdit={isEdit}
|
||||
isCommunityPost={selectedCommunity !== null}
|
||||
rewardType={rewardType}
|
||||
|
@ -1,7 +1,6 @@
|
||||
import getSlug from 'speakingurl';
|
||||
import { diff_match_patch as diffMatchPatch } from 'diff-match-patch';
|
||||
import VersionNumber from 'react-native-version-number';
|
||||
import { PanGestureHandler } from 'react-native-gesture-handler';
|
||||
import MimeTypes from 'mime-types';
|
||||
|
||||
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 out = {};
|
||||
@ -239,8 +238,8 @@ export const extractMetadata = (body:string, thumbIndex?:number) => {
|
||||
}
|
||||
|
||||
if (matchedImages.length) {
|
||||
if(thumbIndex){
|
||||
matchedImages.splice(0, 0, matchedImages.splice(thumbIndex, 1)[0]);
|
||||
if(thumbUrl){
|
||||
matchedImages.sort((item)=>item === thumbUrl ? -1 : 1);
|
||||
}
|
||||
|
||||
out.image = matchedImages;
|
||||
|
@ -1,21 +1,39 @@
|
||||
import get from 'lodash/get';
|
||||
import { operationOrders } from '@hiveio/dhive/lib/utils';
|
||||
import { utils } from '@hiveio/dhive';
|
||||
import parseDate from './parseDate';
|
||||
import parseToken from './parseToken';
|
||||
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 { 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 { getEstimatedAmount } from './vote';
|
||||
import { getPointsSummary, getPointsHistory } from '../providers/ecency/ePoint';
|
||||
// Constant
|
||||
import POINTS from '../constants/options/points';
|
||||
import { COIN_IDS } from '../constants/defaultCoins';
|
||||
import { operationOrders } from '@hiveio/dhive/lib/utils';
|
||||
import { ConversionRequest, OpenOrderItem, OrdersData, SavingsWithdrawRequest } from '../providers/hive/hive.types';
|
||||
import {
|
||||
ConversionRequest,
|
||||
OpenOrderItem,
|
||||
SavingsWithdrawRequest,
|
||||
} from '../providers/hive/hive.types';
|
||||
import parseAsset from './parseAsset';
|
||||
import { utils } from '@hiveio/dhive';
|
||||
|
||||
|
||||
export const transferTypes = [
|
||||
'curation_reward',
|
||||
@ -39,24 +57,16 @@ export const transferTypes = [
|
||||
'fill_vesting_withdraw',
|
||||
];
|
||||
|
||||
const ECENCY_ACTIONS = [
|
||||
'dropdown_transfer', 'dropdown_promote', 'dropdown_boost'
|
||||
];
|
||||
const ECENCY_ACTIONS = ['dropdown_transfer', 'dropdown_promote', 'dropdown_boost'];
|
||||
const HIVE_ACTIONS = [
|
||||
'transfer_token',
|
||||
'transfer_to_savings',
|
||||
'transfer_to_vesting',
|
||||
'withdraw_hive'
|
||||
];
|
||||
const HBD_ACTIONS = [
|
||||
'transfer_token',
|
||||
'transfer_to_savings',
|
||||
'convert',
|
||||
'withdraw_hbd'
|
||||
'withdraw_hive',
|
||||
];
|
||||
const HBD_ACTIONS = ['transfer_token', 'transfer_to_savings', 'convert', 'withdraw_hbd'];
|
||||
const HIVE_POWER_ACTIONS = ['delegate', 'power_down'];
|
||||
|
||||
|
||||
export const groomingTransactionData = (transaction, hivePerMVests) => {
|
||||
if (!transaction || !hivePerMVests) {
|
||||
return [];
|
||||
@ -64,7 +74,7 @@ export const groomingTransactionData = (transaction, hivePerMVests) => {
|
||||
|
||||
const result = {
|
||||
iconType: 'MaterialIcons',
|
||||
trxIndex:transaction[0]
|
||||
trxIndex: transaction[0],
|
||||
};
|
||||
|
||||
[result.textKey] = transaction[1].op;
|
||||
@ -102,8 +112,9 @@ export const groomingTransactionData = (transaction, hivePerMVests) => {
|
||||
.toFixed(3)
|
||||
.replace(',', '.');
|
||||
|
||||
result.value = `${hbdPayout > 0 ? `${hbdPayout} HBD` : ''} ${hivePayout > 0 ? `${hivePayout} HIVE` : ''
|
||||
} ${vestingPayout > 0 ? `${vestingPayout} HP` : ''}`;
|
||||
result.value = `${hbdPayout > 0 ? `${hbdPayout} HBD` : ''} ${
|
||||
hivePayout > 0 ? `${hivePayout} HIVE` : ''
|
||||
} ${vestingPayout > 0 ? `${vestingPayout} HP` : ''}`;
|
||||
|
||||
result.details = author && permlink ? `@${author}/${permlink}` : null;
|
||||
if (result.textKey === 'comment_benefactor_reward') {
|
||||
@ -117,8 +128,9 @@ export const groomingTransactionData = (transaction, hivePerMVests) => {
|
||||
rewardHive = parseToken(rewardHive).toFixed(3).replace(',', '.');
|
||||
rewardVests = vestsToHp(parseToken(rewardVests), hivePerMVests).toFixed(3).replace(',', '.');
|
||||
|
||||
result.value = `${rewardHdb > 0 ? `${rewardHdb} HBD` : ''} ${rewardHive > 0 ? `${rewardHive} HIVE` : ''
|
||||
} ${rewardVests > 0 ? `${rewardVests} HP` : ''}`;
|
||||
result.value = `${rewardHdb > 0 ? `${rewardHdb} HBD` : ''} ${
|
||||
rewardHive > 0 ? `${rewardHive} HIVE` : ''
|
||||
} ${rewardVests > 0 ? `${rewardVests} HP` : ''}`;
|
||||
break;
|
||||
case 'transfer':
|
||||
case 'transfer_to_savings':
|
||||
@ -263,7 +275,7 @@ export const groomingWalletData = async (user, globalProps, userCurrency) => {
|
||||
walletData.nextVestingWithdrawal = Math.round(timeDiff / (1000 * 3600));
|
||||
|
||||
//TOOD: transfer history can be separated from here
|
||||
const op = utils.operationOrders
|
||||
const op = utils.operationOrders;
|
||||
const ops = [
|
||||
op.transfer, //HIVE
|
||||
op.author_reward, //HBD, HP
|
||||
@ -279,7 +291,7 @@ export const groomingWalletData = async (user, globalProps, userCurrency) => {
|
||||
op.sps_fund, //HBD
|
||||
op.comment_benefactor_reward, //HP
|
||||
op.return_vesting_delegation, //HP
|
||||
]
|
||||
];
|
||||
|
||||
const history = await getAccountHistory(get(user, 'name'), ops);
|
||||
|
||||
@ -291,10 +303,10 @@ export const groomingWalletData = async (user, globalProps, userCurrency) => {
|
||||
return walletData;
|
||||
};
|
||||
|
||||
|
||||
|
||||
const fetchPendingRequests = async (username: string, coinSymbol: string): Promise<CoinActivity[]> => {
|
||||
|
||||
const fetchPendingRequests = async (
|
||||
username: string,
|
||||
coinSymbol: string,
|
||||
): Promise<CoinActivity[]> => {
|
||||
const _rawConversions = await getConversionRequests(username);
|
||||
const _rawOpenOrdres = await getOpenOrders(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);
|
||||
|
||||
const openOrderRequests = _rawOpenOrdres
|
||||
.filter(request => request.sell_price.base.includes(coinSymbol))
|
||||
.filter((request) => request.sell_price.base.includes(coinSymbol))
|
||||
.map((request) => {
|
||||
const { base, quote } = request?.sell_price || {};
|
||||
return ({
|
||||
iconType: "MaterialIcons",
|
||||
return {
|
||||
iconType: 'MaterialIcons',
|
||||
textKey: 'open_order',
|
||||
expires: request.expiration,
|
||||
created: request.created,
|
||||
icon: 'reorder',
|
||||
value: base || '-- --',
|
||||
details: base && quote ? `@ ${base} = ${quote}` : '',
|
||||
} as CoinActivity)
|
||||
})
|
||||
} as CoinActivity;
|
||||
});
|
||||
|
||||
const withdrawRequests = _rawWithdrawRequests
|
||||
.filter(request => request.amount.includes(coinSymbol))
|
||||
.filter((request) => request.amount.includes(coinSymbol))
|
||||
.map((request) => {
|
||||
return ({
|
||||
iconType: "MaterialIcons",
|
||||
textKey: "withdraw_savings",
|
||||
return {
|
||||
iconType: 'MaterialIcons',
|
||||
textKey: 'withdraw_savings',
|
||||
created: request.complete,
|
||||
icon: "compare-arrows",
|
||||
icon: 'compare-arrows',
|
||||
value: request.amount,
|
||||
details: request.from && request.to ? `@${request.from} to @${request.to}` : null,
|
||||
memo: request.memo || null
|
||||
} as CoinActivity)
|
||||
})
|
||||
memo: request.memo || null,
|
||||
} as CoinActivity;
|
||||
});
|
||||
|
||||
const conversionRequests = _rawConversions
|
||||
.filter(request => request.amount.includes(coinSymbol))
|
||||
.filter((request) => request.amount.includes(coinSymbol))
|
||||
.map((request) => {
|
||||
return ({
|
||||
iconType: "MaterialIcons",
|
||||
textKey: "convert_request",
|
||||
return {
|
||||
iconType: 'MaterialIcons',
|
||||
textKey: 'convert_request',
|
||||
created: request.conversion_date,
|
||||
icon: "hourglass-full",
|
||||
value: request.amount
|
||||
} as CoinActivity)
|
||||
})
|
||||
icon: 'hourglass-full',
|
||||
value: request.amount,
|
||||
} as CoinActivity;
|
||||
});
|
||||
|
||||
const pendingRequests = [
|
||||
...openOrderRequests,
|
||||
...withdrawRequests,
|
||||
...conversionRequests
|
||||
];
|
||||
const pendingRequests = [...openOrderRequests, ...withdrawRequests, ...conversionRequests];
|
||||
|
||||
pendingRequests.sort((a, b) => (
|
||||
new Date(a.expires || a.created).getTime() > new Date(b.expires || b.created).getTime() ? 1 : -1
|
||||
))
|
||||
pendingRequests.sort((a, b) =>
|
||||
new Date(a.expires || a.created).getTime() > new Date(b.expires || b.created).getTime()
|
||||
? 1
|
||||
: -1,
|
||||
);
|
||||
|
||||
return pendingRequests;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param username
|
||||
* @param coinId
|
||||
* @param coinSymbol
|
||||
* @param globalProps
|
||||
*
|
||||
* @param username
|
||||
* @param coinId
|
||||
* @param coinSymbol
|
||||
* @param globalProps
|
||||
* @returns {Promise<CoinActivitiesCollection>}
|
||||
*/
|
||||
export const fetchCoinActivities = async (
|
||||
@ -370,131 +379,109 @@ export const fetchCoinActivities = async (
|
||||
coinSymbol: string,
|
||||
globalProps: GlobalProps,
|
||||
startIndex: number,
|
||||
limit:number
|
||||
|
||||
limit: number,
|
||||
): Promise<CoinActivitiesCollection> => {
|
||||
|
||||
const op = operationOrders;
|
||||
let history = [];
|
||||
|
||||
switch (coinId) {
|
||||
case COIN_IDS.ECENCY: {
|
||||
|
||||
//TODO: remove condition when we have a way to fetch paginated points data
|
||||
if(startIndex !== -1){
|
||||
if (startIndex !== -1) {
|
||||
return {
|
||||
completed:[],
|
||||
pending:[]
|
||||
}
|
||||
completed: [],
|
||||
pending: [],
|
||||
};
|
||||
}
|
||||
|
||||
const pointActivities = await getPointsHistory(username);
|
||||
console.log("Points Activities", pointActivities);
|
||||
const completed = pointActivities && pointActivities.length ?
|
||||
pointActivities.map((item) =>
|
||||
groomingPointsTransactionData({
|
||||
...item,
|
||||
icon: get(POINTS[get(item, 'type')], 'icon'),
|
||||
iconType: get(POINTS[get(item, 'type')], 'iconType'),
|
||||
textKey: get(POINTS[get(item, 'type')], 'textKey'),
|
||||
})
|
||||
) : [];
|
||||
console.log('Points Activities', pointActivities);
|
||||
const completed =
|
||||
pointActivities && pointActivities.length
|
||||
? pointActivities.map((item) =>
|
||||
groomingPointsTransactionData({
|
||||
...item,
|
||||
icon: get(POINTS[get(item, 'type')], 'icon'),
|
||||
iconType: get(POINTS[get(item, 'type')], 'iconType'),
|
||||
textKey: get(POINTS[get(item, 'type')], 'textKey'),
|
||||
}),
|
||||
)
|
||||
: [];
|
||||
return {
|
||||
completed,
|
||||
pending: [] as CoinActivity[]
|
||||
}
|
||||
pending: [] as CoinActivity[],
|
||||
};
|
||||
}
|
||||
case COIN_IDS.HIVE:
|
||||
history = await getAccountHistory(username, [
|
||||
op.transfer, //HIVE
|
||||
op.transfer_to_vesting, //HIVE, HP
|
||||
op.withdraw_vesting, //HIVE, HP
|
||||
op.transfer_to_savings, //HIVE, HBD
|
||||
op.transfer_from_savings, //HIVE, HBD
|
||||
op.fill_order, //HIVE, HBD
|
||||
], startIndex, limit);
|
||||
history = await getAccountHistory(
|
||||
username,
|
||||
[
|
||||
op.transfer, //HIVE
|
||||
op.transfer_to_vesting, //HIVE, HP
|
||||
op.withdraw_vesting, //HIVE, HP
|
||||
op.transfer_to_savings, //HIVE, HBD
|
||||
op.transfer_from_savings, //HIVE, HBD
|
||||
op.fill_order, //HIVE, HBD
|
||||
],
|
||||
startIndex,
|
||||
limit,
|
||||
);
|
||||
break;
|
||||
case COIN_IDS.HBD:
|
||||
history = await getAccountHistory(username, [
|
||||
op.transfer, //HIVE //HBD
|
||||
op.author_reward, //HBD, HP
|
||||
op.transfer_to_savings, //HIVE, HBD
|
||||
op.transfer_from_savings, //HIVE, HBD
|
||||
op.fill_convert_request, //HBD
|
||||
op.fill_order, //HIVE, HBD
|
||||
op.sps_fund, //HBD
|
||||
], startIndex, limit);
|
||||
history = await getAccountHistory(
|
||||
username,
|
||||
[
|
||||
op.transfer, //HIVE //HBD
|
||||
op.author_reward, //HBD, HP
|
||||
op.transfer_to_savings, //HIVE, HBD
|
||||
op.transfer_from_savings, //HIVE, HBD
|
||||
op.fill_convert_request, //HBD
|
||||
op.fill_order, //HIVE, HBD
|
||||
op.sps_fund, //HBD
|
||||
],
|
||||
startIndex,
|
||||
limit,
|
||||
);
|
||||
break;
|
||||
case COIN_IDS.HP:
|
||||
history = await getAccountHistory(username, [
|
||||
op.author_reward, //HBD, HP
|
||||
op.curation_reward, //HP
|
||||
op.transfer_to_vesting, //HIVE, HP
|
||||
op.withdraw_vesting, //HIVE, HP
|
||||
op.interest, //HP
|
||||
op.claim_reward_balance, //HP
|
||||
op.comment_benefactor_reward, //HP
|
||||
op.return_vesting_delegation, //HP
|
||||
], startIndex, limit);
|
||||
history = await getAccountHistory(
|
||||
username,
|
||||
[
|
||||
op.author_reward, //HBD, HP
|
||||
op.curation_reward, //HP
|
||||
op.transfer_to_vesting, //HIVE, HP
|
||||
op.withdraw_vesting, //HIVE, HP
|
||||
op.interest, //HP
|
||||
op.claim_reward_balance, //HP
|
||||
op.comment_benefactor_reward, //HP
|
||||
op.return_vesting_delegation, //HP
|
||||
],
|
||||
startIndex,
|
||||
limit,
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
const transfers = history.filter((tx) => transferTypes.includes(get(tx[1], 'op[0]', false)));
|
||||
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
|
||||
? activities.filter((item) => {
|
||||
return (
|
||||
item &&
|
||||
item.value &&
|
||||
item.value.includes(coinSymbol)
|
||||
);
|
||||
})
|
||||
return 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);
|
||||
return {
|
||||
completed: filterdActivities,
|
||||
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 ({
|
||||
coins,
|
||||
@ -505,36 +492,32 @@ export const fetchCoinsData = async ({
|
||||
refresh,
|
||||
quotes,
|
||||
}: {
|
||||
coins: CoinBase[],
|
||||
currentAccount: any,
|
||||
vsCurrency: string,
|
||||
currencyRate: number,
|
||||
globalProps: GlobalProps,
|
||||
quotes: { [key: string]: QuoteItem }
|
||||
refresh: boolean,
|
||||
})
|
||||
: Promise<{ [key: string]: CoinData }> => {
|
||||
|
||||
coins: CoinBase[];
|
||||
currentAccount: any;
|
||||
vsCurrency: string;
|
||||
currencyRate: number;
|
||||
globalProps: GlobalProps;
|
||||
quotes: { [key: string]: QuoteItem };
|
||||
refresh: boolean;
|
||||
}): Promise<{ [key: string]: CoinData }> => {
|
||||
const username = currentAccount.username;
|
||||
const { base, quote, hivePerMVests } = globalProps
|
||||
|
||||
const coinData = {} as { [key: string]: CoinData };
|
||||
const walletData = {} as any;
|
||||
|
||||
|
||||
if (!username) {
|
||||
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
|
||||
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
|
||||
const _prices = !refresh && quotes ? quotes : await getLatestQuotes(currencyRate); //TODO: figure out a way to handle other currencies
|
||||
|
||||
|
||||
coins.forEach((coinBase) => {
|
||||
|
||||
switch (coinBase.id) {
|
||||
case COIN_IDS.ECENCY: {
|
||||
const balance = _pointsSummary.points ? parseFloat(_pointsSummary.points) : 0;
|
||||
@ -549,7 +532,7 @@ export const fetchCoinsData = async ({
|
||||
currentPrice: ppEstm,
|
||||
unclaimedBalance: unclaimedBalance,
|
||||
actions: ECENCY_ACTIONS,
|
||||
}
|
||||
};
|
||||
break;
|
||||
}
|
||||
case COIN_IDS.HIVE: {
|
||||
@ -557,7 +540,6 @@ export const fetchCoinsData = async ({
|
||||
const savings = parseToken(userdata.savings_balance);
|
||||
const ppHive = _prices[coinBase.id].price;
|
||||
|
||||
|
||||
coinData[coinBase.id] = {
|
||||
balance: Math.round(balance * 1000) / 1000,
|
||||
estimateValue: (balance + savings) * ppHive,
|
||||
@ -566,7 +548,7 @@ export const fetchCoinsData = async ({
|
||||
currentPrice: ppHive,
|
||||
unclaimedBalance: '',
|
||||
actions: HIVE_ACTIONS,
|
||||
}
|
||||
};
|
||||
break;
|
||||
}
|
||||
|
||||
@ -583,33 +565,27 @@ export const fetchCoinsData = async ({
|
||||
currentPrice: ppHbd,
|
||||
unclaimedBalance: '',
|
||||
actions: HBD_ACTIONS,
|
||||
}
|
||||
};
|
||||
break;
|
||||
}
|
||||
case COIN_IDS.HP: {
|
||||
const _getBalanceStr = (val: number, cur: string) => (val ? Math.round(val * 1000) / 1000 + cur : '');
|
||||
const balance = Math.round(
|
||||
vestsToHp(parseToken(userdata.vesting_shares), hivePerMVests) * 1000,
|
||||
) / 1000;
|
||||
const _getBalanceStr = (val: number, cur: string) =>
|
||||
val ? Math.round(val * 1000) / 1000 + cur : '';
|
||||
const balance =
|
||||
Math.round(vestsToHp(parseToken(userdata.vesting_shares), hivePerMVests) * 1000) / 1000;
|
||||
|
||||
const receivedHP = vestsToHp(
|
||||
parseToken(userdata.received_vesting_shares),
|
||||
hivePerMVests,
|
||||
)
|
||||
const receivedHP = vestsToHp(parseToken(userdata.received_vesting_shares), hivePerMVests);
|
||||
|
||||
const delegatedHP = vestsToHp(
|
||||
parseToken(userdata.delegated_vesting_shares),
|
||||
hivePerMVests,
|
||||
)
|
||||
const delegatedHP = vestsToHp(parseToken(userdata.delegated_vesting_shares), hivePerMVests);
|
||||
|
||||
//agggregate claim button text
|
||||
const unclaimedBalance = [
|
||||
_getBalanceStr(parseToken(userdata.reward_hive_balance), ' HIVE'),
|
||||
_getBalanceStr(parseToken(userdata.reward_hbd_balance), ' HBD'),
|
||||
_getBalanceStr(parseToken(userdata.reward_vesting_hive), ' HP')
|
||||
_getBalanceStr(parseToken(userdata.reward_vesting_hive), ' HP'),
|
||||
].reduce(
|
||||
(prevVal, bal) => prevVal + (!bal ? '' : (`${prevVal !== '' ? ' ' : ''}${bal}`)),
|
||||
''
|
||||
(prevVal, bal) => prevVal + (!bal ? '' : `${prevVal !== '' ? ' ' : ''}${bal}`),
|
||||
'',
|
||||
);
|
||||
|
||||
//calculate power down
|
||||
@ -619,49 +595,57 @@ export const fetchCoinsData = async ({
|
||||
|
||||
const nextVestingSharesWithdrawal = isPoweringDown
|
||||
? Math.min(
|
||||
parseAsset(userdata.vesting_withdraw_rate).amount,
|
||||
(Number(userdata.to_withdraw) - Number(userdata.withdrawn)) / 1e6
|
||||
) : 0;
|
||||
const nextVestingSharesWithdrawalHive = isPoweringDown ? vestsToHp(nextVestingSharesWithdrawal, hivePerMVests) : 0;
|
||||
parseAsset(userdata.vesting_withdraw_rate).amount,
|
||||
(Number(userdata.to_withdraw) - Number(userdata.withdrawn)) / 1e6,
|
||||
)
|
||||
: 0;
|
||||
const nextVestingSharesWithdrawalHive = isPoweringDown
|
||||
? vestsToHp(nextVestingSharesWithdrawal, hivePerMVests)
|
||||
: 0;
|
||||
|
||||
const estimateVoteValueStr = '$ ' + getEstimatedAmount(userdata, globalProps);
|
||||
|
||||
//aaggregate extra data pairs
|
||||
const extraDataPairs:DataPair[] = [];
|
||||
const extraDataPairs: DataPair[] = [];
|
||||
|
||||
if (delegatedHP) {
|
||||
extraDataPairs.push({
|
||||
dataKey: 'delegated_hive_power',
|
||||
value: `- ${delegatedHP.toFixed(3)} HP`,
|
||||
isClickable: true
|
||||
})
|
||||
isClickable: true,
|
||||
});
|
||||
}
|
||||
|
||||
if (receivedHP) {
|
||||
extraDataPairs.push({
|
||||
dataKey: 'received_hive_power',
|
||||
value: `+ ${receivedHP.toFixed(3)} HP`,
|
||||
isClickable: true
|
||||
})
|
||||
isClickable: true,
|
||||
});
|
||||
}
|
||||
|
||||
if (nextVestingSharesWithdrawalHive) {
|
||||
extraDataPairs.push({
|
||||
dataKey: 'powering_down_hive_power',
|
||||
value: `- ${nextVestingSharesWithdrawalHive.toFixed(3)} HP`
|
||||
})
|
||||
value: `- ${nextVestingSharesWithdrawalHive.toFixed(3)} HP`,
|
||||
});
|
||||
}
|
||||
|
||||
extraDataPairs.concat([
|
||||
{
|
||||
dataKey: 'total_hive_power',
|
||||
value: `${(balance - delegatedHP + receivedHP - nextVestingSharesWithdrawalHive).toFixed(3)} HP`
|
||||
}, {
|
||||
value: `${(
|
||||
balance -
|
||||
delegatedHP +
|
||||
receivedHP -
|
||||
nextVestingSharesWithdrawalHive
|
||||
).toFixed(3)} HP`,
|
||||
},
|
||||
{
|
||||
dataKey: 'vote_value',
|
||||
value: estimateVoteValueStr
|
||||
}
|
||||
])
|
||||
|
||||
value: estimateVoteValueStr,
|
||||
},
|
||||
]);
|
||||
|
||||
const ppHive = _prices[COIN_IDS.HIVE].price;
|
||||
coinData[coinBase.id] = {
|
||||
@ -672,22 +656,29 @@ export const fetchCoinsData = async ({
|
||||
currentPrice: ppHive,
|
||||
actions: HIVE_POWER_ACTIONS,
|
||||
extraDataPairs: [
|
||||
...extraDataPairs, {
|
||||
...extraDataPairs,
|
||||
{
|
||||
dataKey: 'total_hive_power',
|
||||
value: `${(balance - delegatedHP + receivedHP - nextVestingSharesWithdrawalHive).toFixed(3)} HP`
|
||||
}, {
|
||||
value: `${(
|
||||
balance -
|
||||
delegatedHP +
|
||||
receivedHP -
|
||||
nextVestingSharesWithdrawalHive
|
||||
).toFixed(3)} HP`,
|
||||
},
|
||||
{
|
||||
dataKey: 'vote_value',
|
||||
value: estimateVoteValueStr
|
||||
}
|
||||
]
|
||||
}
|
||||
value: estimateVoteValueStr,
|
||||
},
|
||||
],
|
||||
};
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
//TODO:discard unnessacry data processings towards the end of PR
|
||||
walletData.rewardHiveBalance = parseToken(userdata.reward_hive_balance);
|
||||
@ -709,8 +700,6 @@ export const fetchCoinsData = async ({
|
||||
walletData.savingBalance = parseToken(userdata.savings_balance);
|
||||
walletData.savingBalanceHbd = parseToken(userdata.savings_hbd_balance);
|
||||
|
||||
|
||||
|
||||
walletData.hivePerMVests = hivePerMVests;
|
||||
const pricePerHive = base / quote;
|
||||
|
||||
@ -723,15 +712,12 @@ export const fetchCoinsData = async ({
|
||||
|
||||
walletData.estimatedValue = totalHive * pricePerHive + totalHbd;
|
||||
|
||||
|
||||
|
||||
walletData.showPowerDown = userdata.next_vesting_withdrawal !== '1969-12-31T23:59:59';
|
||||
const timeDiff = Math.abs(parseDate(userdata.next_vesting_withdrawal) - new Date());
|
||||
walletData.nextVestingWithdrawal = Math.round(timeDiff / (1000 * 3600));
|
||||
|
||||
|
||||
return coinData;
|
||||
}
|
||||
};
|
||||
|
||||
function compare(a, b) {
|
||||
if (a[1].block < b[1].block) {
|
||||
|
Loading…
Reference in New Issue
Block a user