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,
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>
);

View File

@ -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}
/>

View File

@ -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',

View File

@ -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>

View File

@ -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()} >

View File

@ -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}

View File

@ -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}

View File

@ -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;

View File

@ -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) {