From 75bc2fa50f4741094554cbee2f0646da73b3cf8f Mon Sep 17 00:00:00 2001 From: Danilo Prates Date: Mon, 13 Sep 2021 15:46:44 -0300 Subject: [PATCH 01/60] [DDW-694] Initial file structure --- source/renderer/app/Routes.js | 11 ++-- source/renderer/app/actions/assets-actions.js | 2 + .../renderer/app/components/assets/Asset.js | 6 +-- .../app/components/assets/AssetContent.js | 8 +-- .../assets/AssetTransactionConfirmation.js | 4 +- .../wallet/navigation/WalletNavigation.js | 10 ++++ .../WalletSendAssetsConfirmationDialog.js | 6 +-- .../wallet/summary/WalletSummary.js | 6 +-- .../wallet/summary/WalletSummaryAsset.js | 10 ++-- .../wallet/summary/WalletSummaryAssets.js | 6 +-- .../components/wallet/tokens/WalletTokens.js | 41 ++++++++++++++ .../wallet/tokens/WalletTokens.scss | 2 + .../wallet/transactions/Transaction.js | 6 +-- .../wallet/transactions/WalletTransactions.js | 6 +-- .../transactions/WalletTransactionsList.js | 6 +-- .../app/config/walletNavigationConfig.js | 1 + .../containers/wallet/WalletSummaryPage.js | 26 ++------- .../app/containers/wallet/WalletTokensPage.js | 54 +++++++++++++++++++ .../wallet/WalletTransactionsPage.js | 4 +- .../WalletSendConfirmationDialogContainer.js | 4 +- source/renderer/app/routes-config.js | 1 + source/renderer/app/stores/AssetsStore.js | 18 +++++++ storybook/stories/assets/Asset.stories.js | 2 +- .../wallets/send/WalletSend.stories.js | 2 +- .../wallets/summary/WalletSummary.stories.js | 2 +- .../transactions/Transaction.stories.js | 2 +- .../transactions/TransactionsList.stories.js | 4 +- 27 files changed, 182 insertions(+), 68 deletions(-) create mode 100644 source/renderer/app/components/wallet/tokens/WalletTokens.js create mode 100644 source/renderer/app/components/wallet/tokens/WalletTokens.scss create mode 100644 source/renderer/app/containers/wallet/WalletTokensPage.js diff --git a/source/renderer/app/Routes.js b/source/renderer/app/Routes.js index 9e519ec3b5..c9f740640f 100644 --- a/source/renderer/app/Routes.js +++ b/source/renderer/app/Routes.js @@ -1,4 +1,3 @@ -// @flow import React from 'react'; import { Switch, Route, Redirect, withRouter } from 'react-router-dom'; import { ROUTES } from './routes-config'; @@ -30,6 +29,7 @@ import WalletSummaryPage from './containers/wallet/WalletSummaryPage'; import WalletSendPage from './containers/wallet/WalletSendPage'; import WalletReceivePage from './containers/wallet/WalletReceivePage'; import WalletTransactionsPage from './containers/wallet/WalletTransactionsPage'; +import WalletTokensPage from './containers/wallet/WalletTokensPage'; import WalletSettingsPage from './containers/wallet/WalletSettingsPage'; import WalletUtxoPage from './containers/wallet/WalletUtxoPage'; import VotingRegistrationPage from './containers/voting/VotingRegistrationPage'; @@ -64,15 +64,16 @@ export const Routes = withRouter(() => ( path={ROUTES.WALLETS.SUMMARY} component={WalletSummaryPage} /> - + + = new Action(); onAssetSettingsCancel: Action = new Action(); + onOpenAssetSend: Action<{ uniqueId: string }> = new Action(); + onCopyAssetParam: Action<{ uniqueId: string }> = new Action(); } diff --git a/source/renderer/app/components/assets/Asset.js b/source/renderer/app/components/assets/Asset.js index 67d579ddfc..ca8b643200 100644 --- a/source/renderer/app/components/assets/Asset.js +++ b/source/renderer/app/components/assets/Asset.js @@ -74,7 +74,7 @@ type Props = { asset: AssetProps, small?: boolean, hidePopOver?: boolean, - onCopyAssetItem?: Function, + onCopyAssetParam?: Function, onClickSettings?: Function, assetSettingsDialogWasOpened?: ?boolean, anyAssetWasHovered?: ?boolean, @@ -221,7 +221,7 @@ export default class Asset extends Component { renderPillPopOverContainer = () => { const { asset, - onCopyAssetItem, + onCopyAssetParam, assetSettingsDialogWasOpened, anyAssetWasHovered, } = this.props; @@ -229,7 +229,7 @@ export default class Asset extends Component { const popOverContent = ( { assetItem: string, value: string ) => { - const { onCopyAssetItem } = props; - if (onCopyAssetItem) { - onCopyAssetItem(assetItem, value); + const { onCopyAssetParam } = props; + if (onCopyAssetParam) { + onCopyAssetParam(assetItem, value); } clearTimeout(copyNotificationTimeout); setItemCopied(newItemCopied); diff --git a/source/renderer/app/components/assets/AssetTransactionConfirmation.js b/source/renderer/app/components/assets/AssetTransactionConfirmation.js index 095c8c1d8e..e2ebf1d208 100644 --- a/source/renderer/app/components/assets/AssetTransactionConfirmation.js +++ b/source/renderer/app/components/assets/AssetTransactionConfirmation.js @@ -68,7 +68,7 @@ type Props = { amount: BigNumber, }; -const onCopyAssetItem = () => {}; +const onCopyAssetParam = () => {}; const AssetTransactionConfirmation = observer((props: Props) => { const { @@ -113,7 +113,7 @@ const AssetTransactionConfirmation = observer((props: Props) => { diff --git a/source/renderer/app/components/wallet/navigation/WalletNavigation.js b/source/renderer/app/components/wallet/navigation/WalletNavigation.js index 0d9d6be5c6..0a9897b0ca 100755 --- a/source/renderer/app/components/wallet/navigation/WalletNavigation.js +++ b/source/renderer/app/components/wallet/navigation/WalletNavigation.js @@ -40,6 +40,11 @@ const messages = defineMessages({ description: 'Label for the "Transactions" nav button in the wallet navigation.', }, + tokens: { + id: 'wallet.navigation.tokens', + defaultMessage: '!!!Tokens', + description: 'Label for the "Tokens" nav button in the wallet navigation.', + }, settings: { id: 'wallet.navigation.settings', defaultMessage: '!!!Settings', @@ -103,6 +108,11 @@ export default class WalletNavigation extends Component { label: intl.formatMessage(messages.transactions), icon: transactionsIcon, }, + { + id: WALLET_NAV_IDS.TOKENS, + label: intl.formatMessage(messages.tokens), + icon: transactionsIcon, + }, { id: WALLET_NAV_IDS.SETTINGS, type: 'dropdown', diff --git a/source/renderer/app/components/wallet/send-form/WalletSendAssetsConfirmationDialog.js b/source/renderer/app/components/wallet/send-form/WalletSendAssetsConfirmationDialog.js index 95d263a6fb..e0f212e221 100644 --- a/source/renderer/app/components/wallet/send-form/WalletSendAssetsConfirmationDialog.js +++ b/source/renderer/app/components/wallet/send-form/WalletSendAssetsConfirmationDialog.js @@ -53,7 +53,7 @@ type Props = { hwDeviceStatus: HwDeviceStatus, isHardwareWallet: boolean, onInitiateTransaction: Function, - onCopyAssetItem: Function, + onCopyAssetParam: Function, isTrezor: boolean, formattedTotalAmount: string, }; @@ -242,7 +242,7 @@ export default class WalletSendAssetsConfirmationDialog extends Component< onExternalLinkClick, hwDeviceStatus, isHardwareWallet, - onCopyAssetItem, + onCopyAssetParam, wallet, formattedTotalAmount, totalAmount, @@ -359,7 +359,7 @@ export default class WalletSendAssetsConfirmationDialog extends Component< diff --git a/source/renderer/app/components/wallet/summary/WalletSummary.js b/source/renderer/app/components/wallet/summary/WalletSummary.js index 71d360ad7b..9047fbcd21 100644 --- a/source/renderer/app/components/wallet/summary/WalletSummary.js +++ b/source/renderer/app/components/wallet/summary/WalletSummary.js @@ -24,7 +24,7 @@ type Props = { onCurrencySettingClick: Function, assets: Array, onOpenAssetSend: Function, - onCopyAssetItem: Function, + onCopyAssetParam: Function, onAssetSettings: Function, isLoadingAssets: boolean, assetSettingsDialogWasOpened: boolean, @@ -49,7 +49,7 @@ export default class WalletSummary extends Component { onCurrencySettingClick, assets, onOpenAssetSend, - onCopyAssetItem, + onCopyAssetParam, onAssetSettings, assetSettingsDialogWasOpened, isLoadingAssets, @@ -89,7 +89,7 @@ export default class WalletSummary extends Component { assets={assets} onOpenAssetSend={onOpenAssetSend} isLoadingAssets={isLoadingAssets} - onCopyAssetItem={onCopyAssetItem} + onCopyAssetParam={onCopyAssetParam} onAssetSettings={onAssetSettings} assetSettingsDialogWasOpened={assetSettingsDialogWasOpened} currentLocale={currentLocale} diff --git a/source/renderer/app/components/wallet/summary/WalletSummaryAsset.js b/source/renderer/app/components/wallet/summary/WalletSummaryAsset.js index 4ff19caa66..4ae19d96e5 100644 --- a/source/renderer/app/components/wallet/summary/WalletSummaryAsset.js +++ b/source/renderer/app/components/wallet/summary/WalletSummaryAsset.js @@ -48,7 +48,7 @@ const messages = defineMessages({ type Props = { asset: AssetToken, onOpenAssetSend: Function, - onCopyAssetItem: Function, + onCopyAssetParam: Function, onAssetSettings: Function, anyAssetWasHovered: boolean, isLoading: boolean, @@ -68,7 +68,7 @@ const WalletSummaryAsset = observer((props: Props) => { const header = () => { const { asset, - onCopyAssetItem, + onCopyAssetParam, isLoading, anyAssetWasHovered, assetSettingsDialogWasOpened, @@ -84,7 +84,7 @@ const WalletSummaryAsset = observer((props: Props) => {
{ ); }; - const { asset, onCopyAssetItem } = props; + const { asset, onCopyAssetParam } = props; const componentStyles = classNames(styles.component, { [styles.isExpanded]: isExpanded, }); @@ -193,7 +193,7 @@ const WalletSummaryAsset = observer((props: Props) => {
{footer()} diff --git a/source/renderer/app/components/wallet/summary/WalletSummaryAssets.js b/source/renderer/app/components/wallet/summary/WalletSummaryAssets.js index af8d43c639..f4880b3490 100644 --- a/source/renderer/app/components/wallet/summary/WalletSummaryAssets.js +++ b/source/renderer/app/components/wallet/summary/WalletSummaryAssets.js @@ -68,7 +68,7 @@ type Props = { wallet: Wallet, assets: Array, onOpenAssetSend: Function, - onCopyAssetItem: Function, + onCopyAssetParam: Function, onAssetSettings: Function, currentLocale: string, isLoadingAssets: boolean, @@ -150,7 +150,7 @@ export default class WalletSummaryAssets extends Component { const { wallet, onOpenAssetSend, - onCopyAssetItem, + onCopyAssetParam, onAssetSettings, assetSettingsDialogWasOpened, isLoadingAssets, @@ -183,7 +183,7 @@ export default class WalletSummaryAssets extends Component { key={asset.uniqueId} asset={asset} onOpenAssetSend={onOpenAssetSend} - onCopyAssetItem={onCopyAssetItem} + onCopyAssetParam={onCopyAssetParam} onAssetSettings={onAssetSettings} anyAssetWasHovered={anyAssetWasHovered} assetSettingsDialogWasOpened={assetSettingsDialogWasOpened} diff --git a/source/renderer/app/components/wallet/tokens/WalletTokens.js b/source/renderer/app/components/wallet/tokens/WalletTokens.js new file mode 100644 index 0000000000..472adcb2ec --- /dev/null +++ b/source/renderer/app/components/wallet/tokens/WalletTokens.js @@ -0,0 +1,41 @@ +// @flow +import React from 'react'; +import classnames from 'classnames'; +import { defineMessages, intlShape, injectIntl } from 'react-intl'; +import { observer } from 'mobx-react'; +import styles from './WalletTokens.scss'; +import Wallet from '../../../domains/Wallet'; +import type { AssetToken } from '../../../api/assets/types'; + +// const messages = defineMessages({ +// fingerprintItem: { +// id: 'assets.assetToken.item.fingerprint', +// defaultMessage: '!!!Fingerprint', +// description: '"fingerprint" item.', +// }, +// }); + +type Props = { + wallet: Wallet, + assets: Array, + onOpenAssetSend: Function, + onCopyAssetParam: Function, + onAssetSettings: Function, + currentLocale: string, + isLoadingAssets: boolean, + assetSettingsDialogWasOpened: boolean, + intl: intlShape.isRequired, +}; + +const WalletTokens = observer((props: Props) => { + console.log('props', props); + const { assets } = props; + + return ( +
+
{JSON.stringify(assets, null, 2)}
+
+ ); +}); + +export default injectIntl(WalletTokens); diff --git a/source/renderer/app/components/wallet/tokens/WalletTokens.scss b/source/renderer/app/components/wallet/tokens/WalletTokens.scss new file mode 100644 index 0000000000..27bdc0eb43 --- /dev/null +++ b/source/renderer/app/components/wallet/tokens/WalletTokens.scss @@ -0,0 +1,2 @@ +.component { +} diff --git a/source/renderer/app/components/wallet/transactions/Transaction.js b/source/renderer/app/components/wallet/transactions/Transaction.js index 865ea6a276..2a870abfb3 100644 --- a/source/renderer/app/components/wallet/transactions/Transaction.js +++ b/source/renderer/app/components/wallet/transactions/Transaction.js @@ -264,7 +264,7 @@ type Props = { hasAssetsEnabled: boolean, isInternalAddress: Function, isLoadingAssets: boolean, - onCopyAssetItem: Function, + onCopyAssetParam: Function, }; type State = { @@ -486,7 +486,7 @@ export default class Transaction extends Component { isDeletingTransaction, currentTimeFormat, isLoadingAssets, - onCopyAssetItem, + onCopyAssetParam, } = this.props; const { intl } = this.context; @@ -694,7 +694,7 @@ export default class Transaction extends Component { diff --git a/source/renderer/app/components/wallet/transactions/WalletTransactions.js b/source/renderer/app/components/wallet/transactions/WalletTransactions.js index 9c9e3583cd..147aad6fde 100644 --- a/source/renderer/app/components/wallet/transactions/WalletTransactions.js +++ b/source/renderer/app/components/wallet/transactions/WalletTransactions.js @@ -47,7 +47,7 @@ type Props = { hasAssetsEnabled: boolean, getAsset: Function, isInternalAddress: Function, - onCopyAssetItem: Function, + onCopyAssetParam: Function, }; type State = { @@ -95,7 +95,7 @@ export default class WalletTransactions extends Component { hasAssetsEnabled, getAsset, isInternalAddress, - onCopyAssetItem, + onCopyAssetParam, } = this.props; // Guard against potential null values @@ -140,7 +140,7 @@ export default class WalletTransactions extends Component { getAsset={getAsset} isRenderingAsVirtualList isInternalAddress={isInternalAddress} - onCopyAssetItem={onCopyAssetItem} + onCopyAssetParam={onCopyAssetParam} /> ); } diff --git a/source/renderer/app/components/wallet/transactions/WalletTransactionsList.js b/source/renderer/app/components/wallet/transactions/WalletTransactionsList.js index 3f4d2293a3..da677ebe4a 100644 --- a/source/renderer/app/components/wallet/transactions/WalletTransactionsList.js +++ b/source/renderer/app/components/wallet/transactions/WalletTransactionsList.js @@ -69,7 +69,7 @@ type Props = { hasAssetsEnabled: boolean, getAsset: Function, isInternalAddress: Function, - onCopyAssetItem: Function, + onCopyAssetParam: Function, }; type State = { @@ -221,7 +221,7 @@ export default class WalletTransactionsList extends Component { hasAssetsEnabled, getAsset, isInternalAddress, - onCopyAssetItem, + onCopyAssetParam, } = this.props; const { isFirstInGroup, isLastInGroup, tx } = data; const txClasses = classnames([ @@ -259,7 +259,7 @@ export default class WalletTransactionsList extends Component { hasAssetsEnabled={hasAssetsEnabled} isInternalAddress={isInternalAddress} isLoadingAssets={isLoadingAssets} - onCopyAssetItem={onCopyAssetItem} + onCopyAssetParam={onCopyAssetParam} />
); diff --git a/source/renderer/app/config/walletNavigationConfig.js b/source/renderer/app/config/walletNavigationConfig.js index 580d683a21..8ac109012c 100644 --- a/source/renderer/app/config/walletNavigationConfig.js +++ b/source/renderer/app/config/walletNavigationConfig.js @@ -4,6 +4,7 @@ export const WALLET_NAV_IDS = { SEND: 'send', RECEIVE: 'receive', TRANSACTIONS: 'transactions', + TOKENS: 'tokens', SETTINGS: 'settings', }; diff --git a/source/renderer/app/containers/wallet/WalletSummaryPage.js b/source/renderer/app/containers/wallet/WalletSummaryPage.js index d99be71dad..3781a51a9d 100755 --- a/source/renderer/app/containers/wallet/WalletSummaryPage.js +++ b/source/renderer/app/containers/wallet/WalletSummaryPage.js @@ -15,7 +15,6 @@ import { WALLET_ASSETS_ENABLED } from '../../config/walletsConfig'; import { ellipsis } from '../../utils/strings'; import { getAssetTokens } from '../../utils/assets'; import type { InjectedProps } from '../../types/injectedPropsType'; -import type { AssetToken } from '../../api/assets/types'; export const messages = defineMessages({ noTransactions: { @@ -50,22 +49,7 @@ export default class WalletSummaryPage extends Component { }); }; - handleOpenAssetSend = ({ uniqueId }: AssetToken) => { - const { stores } = this.props; - const { wallets } = stores; - const { active } = wallets; - if (active) { - const { id } = active; - const { wallets: walletActions, router } = this.props.actions; - walletActions.setActiveAsset.trigger(uniqueId); - router.goToRoute.trigger({ - route: ROUTES.WALLETS.PAGE, - params: { id, page: 'send' }, - }); - } - }; - - handleOnCopyAssetItem = (assetItem: string, fullValue: string) => { + handleOnCopyAssetParam = (assetItem: string, fullValue: string) => { const value = ellipsis(fullValue, 15, 15); this.props.actions.wallets.copyAssetItem.trigger({ assetItem, @@ -87,7 +71,7 @@ export default class WalletSummaryPage extends Component { } = stores; const { getAsset, assetSettingsDialogWasOpened } = assets; const { isInternalAddress } = addresses; - const { onAssetSettingsOpen } = actions.assets; + const { onAssetSettingsOpen, onOpenAssetSend } = actions.assets; const { openExternalLink, environment: { network }, @@ -151,7 +135,7 @@ export default class WalletSummaryPage extends Component { isInternalAddress={isInternalAddress} hasAssetsEnabled={hasAssetsEnabled} getAsset={getAsset} - onCopyAssetItem={this.handleOnCopyAssetItem} + onCopyAssetParam={this.handleOnCopyAssetParam} /> ); } else if (!hasAny) { @@ -177,8 +161,8 @@ export default class WalletSummaryPage extends Component { onCurrencySettingClick={this.handleCurrencySettingsClick} assets={assetTokens} assetSettingsDialogWasOpened={assetSettingsDialogWasOpened} - onOpenAssetSend={this.handleOpenAssetSend} - onCopyAssetItem={this.handleOnCopyAssetItem} + onOpenAssetSend={onOpenAssetSend.trigger} + onCopyAssetParam={this.handleOnCopyAssetParam} onAssetSettings={onAssetSettingsOpen.trigger} onExternalLinkClick={app.openExternalLink} /> diff --git a/source/renderer/app/containers/wallet/WalletTokensPage.js b/source/renderer/app/containers/wallet/WalletTokensPage.js new file mode 100644 index 0000000000..4eb94df033 --- /dev/null +++ b/source/renderer/app/containers/wallet/WalletTokensPage.js @@ -0,0 +1,54 @@ +// @flow +import React from 'react'; +import { observer, inject } from 'mobx-react'; +import WalletTokens from '../../components/wallet/tokens/WalletTokens'; +import type { InjectedProps } from '../../types/injectedPropsType'; +import { getAssetTokens } from '../../utils/assets'; + +type Props = InjectedProps; + +const WalletTokensPage = inject( + 'stores', + 'actions' +)( + observer((props: Props) => { + const { actions, stores } = props; + const { assets, profile, wallets } = stores; + const { getAsset, assetSettingsDialogWasOpened } = assets; + const { onAssetSettingsOpen, onOpenAssetSend } = actions.assets; + const { active: activeWallet } = wallets; + const { active: wallet } = wallets; + + const { currentLocale } = profile; + + // Guard against potential null values + if (!wallet) + throw new Error('Active wallet required for WalletSummaryPage.'); + + const walletTokens = wallet.assets.total; + const assetTokens = getAssetTokens(walletTokens, getAsset); + const totalRawAssets = wallet.assets.total.length; + const totalAssets = assetTokens.length; + const hasRawAssets = wallet.assets.total.length > 0; + const isLoadingAssets = hasRawAssets && totalAssets < totalRawAssets; + + // Guard against potential null values + if (!activeWallet) + throw new Error('Active wallet required for WalletReceivePage.'); + + return ( + {}} + onOpenAssetSend={onOpenAssetSend.trigger} + wallet={activeWallet} + /> + ); + }) +); + +export default WalletTokensPage; diff --git a/source/renderer/app/containers/wallet/WalletTransactionsPage.js b/source/renderer/app/containers/wallet/WalletTransactionsPage.js index efdd82a476..33243bde18 100755 --- a/source/renderer/app/containers/wallet/WalletTransactionsPage.js +++ b/source/renderer/app/containers/wallet/WalletTransactionsPage.js @@ -12,7 +12,7 @@ type Props = InjectedProps; @inject('stores', 'actions') @observer export default class WalletTransactionsPage extends Component { - handleOnCopyAssetItem = (assetItem: string, fullValue: string) => { + handleOnCopyAssetParam = (assetItem: string, fullValue: string) => { const value = ellipsis(fullValue, 15, 15); this.props.actions.wallets.copyAssetItem.trigger({ assetItem, @@ -85,7 +85,7 @@ export default class WalletTransactionsPage extends Component { hasAssetsEnabled={hasAssetsEnabled} isInternalAddress={isInternalAddress} getAsset={getAsset} - onCopyAssetItem={this.handleOnCopyAssetItem} + onCopyAssetParam={this.handleOnCopyAssetParam} /> ); } diff --git a/source/renderer/app/containers/wallet/dialogs/WalletSendConfirmationDialogContainer.js b/source/renderer/app/containers/wallet/dialogs/WalletSendConfirmationDialogContainer.js index f4eb0fac17..e39be870f3 100644 --- a/source/renderer/app/containers/wallet/dialogs/WalletSendConfirmationDialogContainer.js +++ b/source/renderer/app/containers/wallet/dialogs/WalletSendConfirmationDialogContainer.js @@ -49,7 +49,7 @@ export default class WalletSendConfirmationDialogContainer extends Component { + handleOnCopyAssetParam = (assetItem: string, fullValue: string) => { const value = ellipsis(fullValue, 15, 15); this.props.actions.wallets.copyAssetItem.trigger({ assetItem, @@ -132,7 +132,7 @@ export default class WalletSendConfirmationDialogContainer extends Component diff --git a/source/renderer/app/routes-config.js b/source/renderer/app/routes-config.js index d31d1b549c..82074b581b 100644 --- a/source/renderer/app/routes-config.js +++ b/source/renderer/app/routes-config.js @@ -27,6 +27,7 @@ export const ROUTES = { TRANSACTIONS: '/wallets/:id/transactions', SEND: '/wallets/:id/send', RECEIVE: '/wallets/:id/receive', + TOKENS: '/wallets/:id/tokens', SETTINGS: '/wallets/:id/settings', UTXO: '/wallets/:id/utxo', }, diff --git a/source/renderer/app/stores/AssetsStore.js b/source/renderer/app/stores/AssetsStore.js index 500cfac93e..74a15e6200 100644 --- a/source/renderer/app/stores/AssetsStore.js +++ b/source/renderer/app/stores/AssetsStore.js @@ -4,6 +4,7 @@ import { get } from 'lodash'; import Store from './lib/Store'; import Request from './lib/LocalizedRequest'; import Asset from '../domains/Asset'; +import { ROUTES } from '../routes-config'; import { requestGetter } from '../utils/storesUtils'; import type { GetAssetsResponse, AssetToken } from '../api/assets/types'; @@ -30,6 +31,7 @@ export default class AssetsStore extends Store { assetsActions.onAssetSettingsOpen.listen(this._onAssetSettingsOpen); assetsActions.onAssetSettingsSubmit.listen(this._onAssetSettingsSubmit); assetsActions.onAssetSettingsCancel.listen(this._onAssetSettingsCancel); + assetsActions.onOpenAssetSend.listen(this._onOpenAssetSend); walletsActions.refreshWalletsDataSuccess.once(this._refreshAssetsData); walletsActions.setActiveAsset.listen(this._setActiveAsset); @@ -97,6 +99,22 @@ export default class AssetsStore extends Store { this.editingsAsset = null; }; + @action _onOpenAssetSend = ({ uniqueId }: { uniqueId: string }) => { + console.log('_onOpenAssetSend', uniqueId); + const { stores, actions } = this; + const { wallets } = stores; + const { active } = wallets; + if (active) { + const { id } = active; + const { wallets: walletActions, router } = actions; + walletActions.setActiveAsset.trigger(uniqueId); + router.goToRoute.trigger({ + route: ROUTES.WALLETS.PAGE, + params: { id, page: 'send' }, + }); + } + }; + @action _refreshAssetsData = () => { if (this.stores.networkStatus.isConnected) { const { all } = this.stores.wallets; diff --git a/storybook/stories/assets/Asset.stories.js b/storybook/stories/assets/Asset.stories.js index d59f072f43..1ed74ed522 100644 --- a/storybook/stories/assets/Asset.stories.js +++ b/storybook/stories/assets/Asset.stories.js @@ -45,7 +45,7 @@ storiesOf('Assets|Asset pill', module) }} small={boolean('small', false)} hidePopOver={boolean('hidePopOver')} - onCopyAssetItem={action('onCopyAssetItem')} + onCopyAssetParam={action('onCopyAssetParam')} onClickSettings={ boolean('Is configurable', true) ? action('onClickSettings') : null } diff --git a/storybook/stories/wallets/send/WalletSend.stories.js b/storybook/stories/wallets/send/WalletSend.stories.js index 36541768a5..c6f0cd23b8 100644 --- a/storybook/stories/wallets/send/WalletSend.stories.js +++ b/storybook/stories/wallets/send/WalletSend.stories.js @@ -373,7 +373,7 @@ storiesOf('Wallets|Send', module) hwDeviceStatus={HwDeviceStatuses.CONNECTING} isHardwareWallet={boolean('isHardwareWallet', false)} onInitiateTransaction={() => null} - onCopyAssetItem={() => {}} + onCopyAssetParam={() => {}} isTrezor={boolean('isTrezor', false)} formattedTotalAmount="21.000000" /> diff --git a/storybook/stories/wallets/summary/WalletSummary.stories.js b/storybook/stories/wallets/summary/WalletSummary.stories.js index 23f1460c05..20ad0d9fca 100644 --- a/storybook/stories/wallets/summary/WalletSummary.stories.js +++ b/storybook/stories/wallets/summary/WalletSummary.stories.js @@ -253,7 +253,7 @@ storiesOf('Wallets|Summary', module) ]} isLoadingAssets={boolean('isLoadingAssets', false)} onOpenAssetSend={action('onOpenAssetSend')} - onCopyAssetItem={action('onCopyAsset')} + onCopyAssetParam={action('onCopyAsset')} onAssetSettings={action('onAssetSettings')} hasAssetsEnabled={boolean('hasAssetsEnabled', true)} assetSettingsDialogWasOpened={boolean( diff --git a/storybook/stories/wallets/transactions/Transaction.stories.js b/storybook/stories/wallets/transactions/Transaction.stories.js index 3b153b8283..972dfedd86 100644 --- a/storybook/stories/wallets/transactions/Transaction.stories.js +++ b/storybook/stories/wallets/transactions/Transaction.stories.js @@ -215,7 +215,7 @@ storiesOf('Wallets|Transactions', module) onDetailsToggled={action('onDetailsToggled')} onOpenExternalLink={action('onOpenExternalLink')} isInternalAddress={() => direction === 'incoming'} - onCopyAssetItem={action('onCopyAssetItem')} + onCopyAssetParam={action('onCopyAssetParam')} /> ); }); diff --git a/storybook/stories/wallets/transactions/TransactionsList.stories.js b/storybook/stories/wallets/transactions/TransactionsList.stories.js index 24743694bf..31cf600d33 100644 --- a/storybook/stories/wallets/transactions/TransactionsList.stories.js +++ b/storybook/stories/wallets/transactions/TransactionsList.stories.js @@ -211,7 +211,7 @@ storiesOf('Wallets|Transactions', module) transactions={transactions} hasAssetsEnabled={false} getAsset={getAsset} - onCopyAssetItem={() => {}} + onCopyAssetParam={() => {}} /> ); }) @@ -253,7 +253,7 @@ storiesOf('Wallets|Transactions', module) transactions={transactions} hasAssetsEnabled={hasAssetsEnabled} getAsset={getAsset} - onCopyAssetItem={() => {}} + onCopyAssetParam={() => {}} /> ); }); From fa917a4c97a8751623d4f00d91658f581827a834 Mon Sep 17 00:00:00 2001 From: Danilo Prates Date: Mon, 13 Sep 2021 16:27:40 -0300 Subject: [PATCH 02/60] [DDW-694] Improve file structure --- source/renderer/app/actions/assets-actions.js | 6 +- .../renderer/app/actions/wallets-actions.js | 1 - .../renderer/app/components/assets/Asset.js | 14 +-- .../app/components/assets/AssetContent.js | 112 +++++++++--------- .../app/components/assets/AssetContent.scss | 2 +- .../components/wallet/tokens/WalletTokens.js | 2 +- .../notifications/NotificationsContainer.js | 15 +-- .../containers/wallet/WalletSummaryPage.js | 18 ++- .../app/containers/wallet/WalletTokensPage.js | 14 +-- .../wallet/WalletTransactionsPage.js | 11 +- .../WalletSendConfirmationDialogContainer.js | 11 +- source/renderer/app/i18n/locales/en-US.json | 19 +-- source/renderer/app/i18n/locales/ja-JP.json | 19 +-- source/renderer/app/stores/AssetsStore.js | 17 ++- .../renderer/app/types/notificationTypes.js | 4 +- 15 files changed, 129 insertions(+), 136 deletions(-) diff --git a/source/renderer/app/actions/assets-actions.js b/source/renderer/app/actions/assets-actions.js index 40fff3b02a..221739fe08 100644 --- a/source/renderer/app/actions/assets-actions.js +++ b/source/renderer/app/actions/assets-actions.js @@ -12,5 +12,9 @@ export default class AssetsActions { }> = new Action(); onAssetSettingsCancel: Action = new Action(); onOpenAssetSend: Action<{ uniqueId: string }> = new Action(); - onCopyAssetParam: Action<{ uniqueId: string }> = new Action(); + onCopyAssetParam: Action<{ param: string, fullValue: string }> = new Action(); + copyAssetParamNotification: Action<{ + param: string, + shortValue: string, + }> = new Action(); } diff --git a/source/renderer/app/actions/wallets-actions.js b/source/renderer/app/actions/wallets-actions.js index 5d58110cbc..0a5050fa6a 100644 --- a/source/renderer/app/actions/wallets-actions.js +++ b/source/renderer/app/actions/wallets-actions.js @@ -82,7 +82,6 @@ export default class WalletsActions { copyWalletPublicKey: Action<{ publicKey: string }> = new Action(); copyICOPublicKey: Action<{ publicKey: string }> = new Action(); copyAddress: Action<{ address: string }> = new Action(); - copyAssetItem: Action<{ assetItem: string, value: string }> = new Action(); updateCertificateStep: Action = new Action(); closeCertificateGeneration: Action = new Action(); closeRewardsCsvGeneration: Action = new Action(); diff --git a/source/renderer/app/components/assets/Asset.js b/source/renderer/app/components/assets/Asset.js index ca8b643200..43d5251325 100644 --- a/source/renderer/app/components/assets/Asset.js +++ b/source/renderer/app/components/assets/Asset.js @@ -16,37 +16,37 @@ import type { Asset as AssetProps } from '../../api/assets/types'; const messages = defineMessages({ fingerprintItem: { - id: 'assets.assetToken.item.fingerprint', + id: 'assets.assetToken.param.fingerprint', defaultMessage: '!!!Fingerprint', description: '"fingerprint" item.', }, policyIdItem: { - id: 'assets.assetToken.item.policyId', + id: 'assets.assetToken.param.policyId', defaultMessage: '!!!Policy Id', description: '"policyId" item.', }, assetNameItem: { - id: 'assets.assetToken.item.assetName', + id: 'assets.assetToken.param.assetName', defaultMessage: '!!!Asset name', description: '"assetName" item.', }, nameItem: { - id: 'assets.assetToken.item.name', + id: 'assets.assetToken.param.name', defaultMessage: '!!!Name', description: '"name" item.', }, tickerItem: { - id: 'assets.assetToken.item.ticker', + id: 'assets.assetToken.param.ticker', defaultMessage: '!!!Ticker', description: '"ticker" item.', }, descriptionItem: { - id: 'assets.assetToken.item.description', + id: 'assets.assetToken.param.description', defaultMessage: '!!!Description', description: '"description" item.', }, blank: { - id: 'assets.assetToken.item.blank', + id: 'assets.assetToken.param.blank', defaultMessage: '!!!Blank', description: '"Blank" item value.', }, diff --git a/source/renderer/app/components/assets/AssetContent.js b/source/renderer/app/components/assets/AssetContent.js index 694318899c..9b0a609995 100644 --- a/source/renderer/app/components/assets/AssetContent.js +++ b/source/renderer/app/components/assets/AssetContent.js @@ -14,40 +14,40 @@ import { ASSET_TOKEN_ID_COPY_FEEDBACK } from '../../config/timingConfig'; import type { Asset as AssetProps } from '../../api/assets/types'; const messages = defineMessages({ - fingerprintItem: { - id: 'assets.assetToken.item.fingerprint', + fingerprintrenderAssetParam: { + id: 'assets.assetToken.param.fingerprint', defaultMessage: '!!!Fingerprint', - description: '"fingerprint" item.', + description: '"fingerprint" param.', }, - policyIdItem: { - id: 'assets.assetToken.item.policyId', + policyIdrenderAssetParam: { + id: 'assets.assetToken.param.policyId', defaultMessage: '!!!Policy Id', - description: '"policyId" item.', + description: '"policyId" param.', }, - assetNameItem: { - id: 'assets.assetToken.item.assetName', + assetNamerenderAssetParam: { + id: 'assets.assetToken.param.assetName', defaultMessage: '!!!Asset name', - description: '"assetName" item.', + description: '"assetName" param.', }, - nameItem: { - id: 'assets.assetToken.item.name', + namerenderAssetParam: { + id: 'assets.assetToken.param.name', defaultMessage: '!!!Name', - description: '"name" item.', + description: '"name" param.', }, - tickerItem: { - id: 'assets.assetToken.item.ticker', + tickerrenderAssetParam: { + id: 'assets.assetToken.param.ticker', defaultMessage: '!!!Ticker', - description: '"ticker" item.', + description: '"ticker" param.', }, - descriptionItem: { - id: 'assets.assetToken.item.description', + descriptionrenderAssetParam: { + id: 'assets.assetToken.param.description', defaultMessage: '!!!Description', - description: '"description" item.', + description: '"description" param.', }, blank: { - id: 'assets.assetToken.item.blank', + id: 'assets.assetToken.param.blank', defaultMessage: '!!!Blank', - description: '"Blank" item value.', + description: '"Blank" param value.', }, settingsCogPopOver: { id: 'assets.assetToken.settings.cogPopOver', @@ -78,45 +78,41 @@ type Props = { hasError?: boolean, }; -type ItemCopied = ?string; +type ParamCopied = ?string; const AssetContent = observer((props: Props) => { - const [itemCopied, setItemCopied] = useState(null); + const [paramCopied, setParamCopied] = useState(null); let copyNotificationTimeout: TimeoutID; - const handleCopyItem = ( - newItemCopied: string, - assetItem: string, - value: string + const handleCopyParam = ( + newParamCopied: string, + param: string, + fullValue: string ) => { const { onCopyAssetParam } = props; if (onCopyAssetParam) { - onCopyAssetParam(assetItem, value); + onCopyAssetParam({ param, fullValue }); } clearTimeout(copyNotificationTimeout); - setItemCopied(newItemCopied); + setParamCopied(newParamCopied); copyNotificationTimeout = setTimeout(() => { - setItemCopied(null); + setParamCopied(null); }, ASSET_TOKEN_ID_COPY_FEEDBACK); }; - const renderAssetItem = ( - assetId: string, - assetItem: string, - value: string - ) => { - const icon = itemCopied === assetId ? copyCheckmarkIcon : copyIcon; + const renderAssetParam = (assetId: string, param: string, value: string) => { + const icon = paramCopied === assetId ? copyCheckmarkIcon : copyIcon; const iconClassnames = classnames([ styles.copyIcon, - itemCopied === assetId ? styles.copiedIcon : null, + paramCopied === assetId ? styles.copiedIcon : null, ]); const onCopy = () => { - handleCopyItem(assetId, assetItem, value); + handleCopyParam(assetId, param, value); }; return ( -
+
{value} @@ -144,9 +140,9 @@ const AssetContent = observer((props: Props) => {
{highlightFingerprint && (
- {renderAssetItem( + {renderAssetParam( 'fingerprint', - intl.formatMessage(messages.fingerprintItem), + intl.formatMessage(messages.fingerprintrenderAssetParam), fingerprint )}
@@ -154,11 +150,11 @@ const AssetContent = observer((props: Props) => {
{!highlightFingerprint && ( <> -
{intl.formatMessage(messages.fingerprintItem)}
+
{intl.formatMessage(messages.fingerprintrenderAssetParam)}
- {renderAssetItem( + {renderAssetParam( 'fingerprint', - intl.formatMessage(messages.fingerprintItem), + intl.formatMessage(messages.fingerprintrenderAssetParam), fingerprint )}
@@ -166,11 +162,11 @@ const AssetContent = observer((props: Props) => { )} {ticker && ( <> -
{intl.formatMessage(messages.tickerItem)}
+
{intl.formatMessage(messages.tickerrenderAssetParam)}
- {renderAssetItem( + {renderAssetParam( 'ticker', - intl.formatMessage(messages.tickerItem), + intl.formatMessage(messages.tickerrenderAssetParam), ticker )}
@@ -178,11 +174,11 @@ const AssetContent = observer((props: Props) => { )} {name && ( <> -
{intl.formatMessage(messages.nameItem)}
+
{intl.formatMessage(messages.namerenderAssetParam)}
- {renderAssetItem( + {renderAssetParam( 'name', - intl.formatMessage(messages.nameItem), + intl.formatMessage(messages.namerenderAssetParam), name )}
@@ -190,30 +186,30 @@ const AssetContent = observer((props: Props) => { )} {description && ( <> -
{intl.formatMessage(messages.descriptionItem)}
+
{intl.formatMessage(messages.descriptionrenderAssetParam)}
- {renderAssetItem( + {renderAssetParam( 'description', - intl.formatMessage(messages.descriptionItem), + intl.formatMessage(messages.descriptionrenderAssetParam), description )}
)} -
{intl.formatMessage(messages.policyIdItem)}
+
{intl.formatMessage(messages.policyIdrenderAssetParam)}
- {renderAssetItem( + {renderAssetParam( 'policyId', - intl.formatMessage(messages.policyIdItem), + intl.formatMessage(messages.policyIdrenderAssetParam), policyId )}
-
{intl.formatMessage(messages.assetNameItem)}
+
{intl.formatMessage(messages.assetNamerenderAssetParam)}
{assetName ? ( - renderAssetItem( + renderAssetParam( 'assetName', - intl.formatMessage(messages.assetNameItem), + intl.formatMessage(messages.assetNamerenderAssetParam), assetName ) ) : ( diff --git a/source/renderer/app/components/assets/AssetContent.scss b/source/renderer/app/components/assets/AssetContent.scss index c3f15f44c6..449d3bec5d 100644 --- a/source/renderer/app/components/assets/AssetContent.scss +++ b/source/renderer/app/components/assets/AssetContent.scss @@ -103,7 +103,7 @@ } } -.assetItem { +.assetParam { cursor: pointer; display: inline-flex; flex-direction: column; diff --git a/source/renderer/app/components/wallet/tokens/WalletTokens.js b/source/renderer/app/components/wallet/tokens/WalletTokens.js index 472adcb2ec..75ffbdecfb 100644 --- a/source/renderer/app/components/wallet/tokens/WalletTokens.js +++ b/source/renderer/app/components/wallet/tokens/WalletTokens.js @@ -9,7 +9,7 @@ import type { AssetToken } from '../../../api/assets/types'; // const messages = defineMessages({ // fingerprintItem: { -// id: 'assets.assetToken.item.fingerprint', +// id: 'assets.assetToken.param.fingerprint', // defaultMessage: '!!!Fingerprint', // description: '"fingerprint" item.', // }, diff --git a/source/renderer/app/containers/notifications/NotificationsContainer.js b/source/renderer/app/containers/notifications/NotificationsContainer.js index 49f26a4386..2fbbf23528 100644 --- a/source/renderer/app/containers/notifications/NotificationsContainer.js +++ b/source/renderer/app/containers/notifications/NotificationsContainer.js @@ -61,10 +61,10 @@ const messages = defineMessages({ description: 'Notification for the wallet address copy success in the Wallet Receive page.', }, - copyAssetItem: { - id: 'notification.copyAssetItem', + copyAssetParam: { + id: 'notification.copyAssetParam', defaultMessage: - '!!!{assetItem}: {value} copied to clipboard', + '!!!{param}: {shortValue} copied to clipboard', description: 'Notification for the wallet assetItem copy success in the Wallet Receive page.', }, @@ -140,10 +140,6 @@ export default class NotificationsContainer extends Component { id: 'copyAddress', actionToListenAndOpen: this.props.actions.wallets.copyAddress, }, - { - id: 'copyAssetItem', - actionToListenAndOpen: this.props.actions.wallets.copyAssetItem, - }, { id: 'downloadAddressPDFSuccess', actionToListenAndOpen: this.props.actions.wallets @@ -165,6 +161,11 @@ export default class NotificationsContainer extends Component { actionToListenAndOpen: this.props.actions.networkStatus .copyStateDirectoryPath, }, + { + id: 'copyAssetParam', + actionToListenAndOpen: this.props.actions.assets + .copyAssetParamNotification, + }, ]; notificationsData: { diff --git a/source/renderer/app/containers/wallet/WalletSummaryPage.js b/source/renderer/app/containers/wallet/WalletSummaryPage.js index 3781a51a9d..450a241af2 100755 --- a/source/renderer/app/containers/wallet/WalletSummaryPage.js +++ b/source/renderer/app/containers/wallet/WalletSummaryPage.js @@ -49,14 +49,6 @@ export default class WalletSummaryPage extends Component { }); }; - handleOnCopyAssetParam = (assetItem: string, fullValue: string) => { - const value = ellipsis(fullValue, 15, 15); - this.props.actions.wallets.copyAssetItem.trigger({ - assetItem, - value, - }); - }; - render() { const { intl } = this.context; const { stores, actions } = this.props; @@ -71,7 +63,11 @@ export default class WalletSummaryPage extends Component { } = stores; const { getAsset, assetSettingsDialogWasOpened } = assets; const { isInternalAddress } = addresses; - const { onAssetSettingsOpen, onOpenAssetSend } = actions.assets; + const { + onAssetSettingsOpen, + onOpenAssetSend, + onCopyAssetParam, + } = actions.assets; const { openExternalLink, environment: { network }, @@ -135,7 +131,7 @@ export default class WalletSummaryPage extends Component { isInternalAddress={isInternalAddress} hasAssetsEnabled={hasAssetsEnabled} getAsset={getAsset} - onCopyAssetParam={this.handleOnCopyAssetParam} + onCopyAssetParam={onCopyAssetParam.trigger} /> ); } else if (!hasAny) { @@ -162,7 +158,7 @@ export default class WalletSummaryPage extends Component { assets={assetTokens} assetSettingsDialogWasOpened={assetSettingsDialogWasOpened} onOpenAssetSend={onOpenAssetSend.trigger} - onCopyAssetParam={this.handleOnCopyAssetParam} + onCopyAssetParam={onCopyAssetParam.trigger} onAssetSettings={onAssetSettingsOpen.trigger} onExternalLinkClick={app.openExternalLink} /> diff --git a/source/renderer/app/containers/wallet/WalletTokensPage.js b/source/renderer/app/containers/wallet/WalletTokensPage.js index 4eb94df033..296f2afd25 100644 --- a/source/renderer/app/containers/wallet/WalletTokensPage.js +++ b/source/renderer/app/containers/wallet/WalletTokensPage.js @@ -17,25 +17,19 @@ const WalletTokensPage = inject( const { getAsset, assetSettingsDialogWasOpened } = assets; const { onAssetSettingsOpen, onOpenAssetSend } = actions.assets; const { active: activeWallet } = wallets; - const { active: wallet } = wallets; - const { currentLocale } = profile; // Guard against potential null values - if (!wallet) + if (!activeWallet) throw new Error('Active wallet required for WalletSummaryPage.'); - const walletTokens = wallet.assets.total; + const walletTokens = activeWallet.assets.total; const assetTokens = getAssetTokens(walletTokens, getAsset); - const totalRawAssets = wallet.assets.total.length; + const totalRawAssets = activeWallet.assets.total.length; const totalAssets = assetTokens.length; - const hasRawAssets = wallet.assets.total.length > 0; + const hasRawAssets = activeWallet.assets.total.length > 0; const isLoadingAssets = hasRawAssets && totalAssets < totalRawAssets; - // Guard against potential null values - if (!activeWallet) - throw new Error('Active wallet required for WalletReceivePage.'); - return ( { - handleOnCopyAssetParam = (assetItem: string, fullValue: string) => { - const value = ellipsis(fullValue, 15, 15); - this.props.actions.wallets.copyAssetItem.trigger({ - assetItem, - value, - }); - }; - render() { const { actions, stores } = this.props; const { app, wallets, addresses, profile, assets } = stores; @@ -48,6 +40,7 @@ export default class WalletTransactionsPage extends Component { const { searchLimit = 0 } = filterOptions || {}; const { transactions: transactionActions } = this.props.actions; const { filterTransactions, requestCSVFile } = transactionActions; + const { onCopyAssetParam } = actions.assets; const hasAssetsEnabled = WALLET_ASSETS_ENABLED; @@ -85,7 +78,7 @@ export default class WalletTransactionsPage extends Component { hasAssetsEnabled={hasAssetsEnabled} isInternalAddress={isInternalAddress} getAsset={getAsset} - onCopyAssetParam={this.handleOnCopyAssetParam} + onCopyAssetParam={onCopyAssetParam.trigger} /> ); } diff --git a/source/renderer/app/containers/wallet/dialogs/WalletSendConfirmationDialogContainer.js b/source/renderer/app/containers/wallet/dialogs/WalletSendConfirmationDialogContainer.js index e39be870f3..78e3d87c13 100644 --- a/source/renderer/app/containers/wallet/dialogs/WalletSendConfirmationDialogContainer.js +++ b/source/renderer/app/containers/wallet/dialogs/WalletSendConfirmationDialogContainer.js @@ -49,14 +49,6 @@ export default class WalletSendConfirmationDialogContainer extends Component { - const value = ellipsis(fullValue, 15, 15); - this.props.actions.wallets.copyAssetItem.trigger({ - assetItem, - value, - }); - }; - render() { const { actions, @@ -104,6 +96,7 @@ export default class WalletSendConfirmationDialogContainer extends Component @@ -132,7 +125,7 @@ export default class WalletSendConfirmationDialogContainer extends Component diff --git a/source/renderer/app/i18n/locales/en-US.json b/source/renderer/app/i18n/locales/en-US.json index 880dc3d91f..8ca9726ca1 100755 --- a/source/renderer/app/i18n/locales/en-US.json +++ b/source/renderer/app/i18n/locales/en-US.json @@ -36,13 +36,13 @@ "appUpdate.overlay.subtitle": "You are currently running Daedalus version {currentAppVersion}.
Daedalus version {availableAppVersion} is now available to download.", "appUpdate.overlay.title": "Software update available!", "assets.assetAmount.unformattedAmount": "Unformatted amount: {amount}", - "assets.assetToken.item.assetName": "Asset name", - "assets.assetToken.item.blank": "Blank", - "assets.assetToken.item.description": "Description", - "assets.assetToken.item.fingerprint": "Fingerprint", - "assets.assetToken.item.name": "Name", - "assets.assetToken.item.policyId": "Policy Id", - "assets.assetToken.item.ticker": "Ticker", + "assets.assetToken.param.assetName": "Asset name", + "assets.assetToken.param.blank": "Blank", + "assets.assetToken.param.description": "Description", + "assets.assetToken.param.fingerprint": "Fingerprint", + "assets.assetToken.param.name": "Name", + "assets.assetToken.param.policyId": "Policy Id", + "assets.assetToken.param.ticker": "Ticker", "assets.assetToken.settings.cogPopOver": "You can configure the number of decimal places for this native token.", "assets.settings.dialog.decimalPrecision.label": "Number of decimal places", "assets.settings.dialog.default": "(default)", @@ -208,7 +208,7 @@ "noDiskSpace.error.overlayContent": "Daedalus requires at least {diskSpaceRequired} of hard drive space to operate. Your computer is missing {diskSpaceMissing} of available space. Please delete some files to increase available hard drive space to continue using Daedalus.

It is recommended to have at least 15% of hard drive space available ({diskSpaceRecommended} in your case) for normal and stable operation of the operating system and installed programs. We strongly recommend that you free up at least that amount of space from your hard drive.", "noDiskSpace.error.overlayTitle": "Daedalus requires more hard drive space", "notification.copyAddress": "Address: {address} copied to clipboard", - "notification.copyAssetItem": "{assetItem}: {value} copied to clipboard", + "notification.copyAssetParam": "{param}: {shortValue} copied to clipboard", "notification.copyICOPublicKey": "Multi-signature public key: {publicKey} copied to clipboard", "notification.copyStateDirectoryPath": "Daedalus state directory copied to clipboard", "notification.copyWalletPublicKey": "Public key: {publicKey} copied to clipboard", @@ -799,6 +799,7 @@ "wallet.navigation.send": "Send", "wallet.navigation.settings": "Settings", "wallet.navigation.summary": "Summary", + "wallet.navigation.tokens": "Tokens", "wallet.navigation.transactions": "Transactions", "wallet.navigation.utxo": "Wallet UTXO distribution", "wallet.notResponding.description": "

The {walletName} wallet is not responding. This is caused by a known but rare issue, which is currently being fixed.

Please restart the Cardano node by clicking the button below, which should resolve the issue.

If the issue persists, or if it happens again, please submit a support request.

", @@ -1210,4 +1211,4 @@ "wallet.transferFunds.dialog2.total.label": "Total", "widgets.itemsDropdown.syncingLabel": "Syncing", "widgets.itemsDropdown.syncingLabelProgress": "Syncing {syncingProgress}%" -} \ No newline at end of file +} diff --git a/source/renderer/app/i18n/locales/ja-JP.json b/source/renderer/app/i18n/locales/ja-JP.json index dc61810a07..201c666092 100755 --- a/source/renderer/app/i18n/locales/ja-JP.json +++ b/source/renderer/app/i18n/locales/ja-JP.json @@ -36,13 +36,13 @@ "appUpdate.overlay.subtitle": "このDaedalusはバージョン{currentAppVersion}です。
現在Daedalus {availableAppVersion}がダウンロード可能です", "appUpdate.overlay.title": "ソフトウェアが更新できます!", "assets.assetAmount.unformattedAmount": "書式なしの金額:{amount}", - "assets.assetToken.item.assetName": "アセット名", - "assets.assetToken.item.blank": "なし", - "assets.assetToken.item.description": "説明", - "assets.assetToken.item.fingerprint": "フィンガープリント", - "assets.assetToken.item.name": "名称", - "assets.assetToken.item.policyId": "ポリシーID", - "assets.assetToken.item.ticker": "ティッカー", + "assets.assetToken.param.assetName": "アセット名", + "assets.assetToken.param.blank": "なし", + "assets.assetToken.param.description": "説明", + "assets.assetToken.param.fingerprint": "フィンガープリント", + "assets.assetToken.param.name": "名称", + "assets.assetToken.param.policyId": "ポリシーID", + "assets.assetToken.param.ticker": "ティッカー", "assets.assetToken.settings.cogPopOver": "このネイティブトークンの小数点以下の桁数を設定できます", "assets.settings.dialog.decimalPrecision.label": "小数点以下の桁数", "assets.settings.dialog.default": "(初期設定)", @@ -208,7 +208,7 @@ "noDiskSpace.error.overlayContent": "Daedalusを動作させるには、ハードディスクに{diskSpaceRequired}以上の空き容量が必要です。ご使用のコンピューターには空き容量が{diskSpaceMissing}不足しています。Daedalusのご利用を続けるためには、ファイルをいくつか削除して空き容量を増やしてください。

オペレーティングシステムとインストール済みプログラムを正常かつ安定した状態で動作させるには、ハードディスクに少なくとも15%(ご使用のコンピューターの場合は{diskSpaceRecommended})の空き容量が必要です。ハードディスクにこれ以上の空き容量を確保してください。", "noDiskSpace.error.overlayTitle": "ハードディスクの空き容量が不足しているためDaedalusを作動できません", "notification.copyAddress": "アドレス:{address}をクリップボードにコピーしました", - "notification.copyAssetItem": "{assetItem}: {value} をクリップボードにコピーしました", + "notification.copyAssetParam": "{param}: {shortValue} をクリップボードにコピーしました", "notification.copyICOPublicKey": "マルチシグ公開鍵: {publicKey} クリップボードにコピーされました", "notification.copyStateDirectoryPath": "Daedalusステータスディレクトリーをクリップボードにコピーしました", "notification.copyWalletPublicKey": "公開鍵: {publicKey} をクリップボードにコピーしました", @@ -799,6 +799,7 @@ "wallet.navigation.send": "送金", "wallet.navigation.settings": "設定", "wallet.navigation.summary": "概要", + "wallet.navigation.tokens": "トークン", "wallet.navigation.transactions": "トランザクション", "wallet.navigation.utxo": "ウォレットのUTXO分布", "wallet.notResponding.description": "

「{walletName}」ウォレットは応答していません。これは既知の稀に生じる不具合によるものであり、この不具合は現在修正されました。

下のボタンをクリックしてCardanoノードを再起動すると、問題は解消されます。

問題が解消しない場合、または再び発生した場合は、サポートリクエストを送信してください。

", @@ -1210,4 +1211,4 @@ "wallet.transferFunds.dialog2.total.label": "合計", "widgets.itemsDropdown.syncingLabel": "同期", "widgets.itemsDropdown.syncingLabelProgress": "同期中 {syncingProgress}%" -} \ No newline at end of file +} diff --git a/source/renderer/app/stores/AssetsStore.js b/source/renderer/app/stores/AssetsStore.js index 74a15e6200..6f2c594015 100644 --- a/source/renderer/app/stores/AssetsStore.js +++ b/source/renderer/app/stores/AssetsStore.js @@ -6,6 +6,7 @@ import Request from './lib/LocalizedRequest'; import Asset from '../domains/Asset'; import { ROUTES } from '../routes-config'; import { requestGetter } from '../utils/storesUtils'; +import { ellipsis } from '../utils/strings'; import type { GetAssetsResponse, AssetToken } from '../api/assets/types'; type WalletId = string; @@ -32,6 +33,7 @@ export default class AssetsStore extends Store { assetsActions.onAssetSettingsSubmit.listen(this._onAssetSettingsSubmit); assetsActions.onAssetSettingsCancel.listen(this._onAssetSettingsCancel); assetsActions.onOpenAssetSend.listen(this._onOpenAssetSend); + assetsActions.onCopyAssetParam.listen(this._onCopyAssetParam); walletsActions.refreshWalletsDataSuccess.once(this._refreshAssetsData); walletsActions.setActiveAsset.listen(this._setActiveAsset); @@ -100,7 +102,6 @@ export default class AssetsStore extends Store { }; @action _onOpenAssetSend = ({ uniqueId }: { uniqueId: string }) => { - console.log('_onOpenAssetSend', uniqueId); const { stores, actions } = this; const { wallets } = stores; const { active } = wallets; @@ -115,6 +116,20 @@ export default class AssetsStore extends Store { } }; + @action _onCopyAssetParam = ({ + param, + fullValue, + }: { + param: string, + fullValue: string, + }) => { + const shortValue = ellipsis(fullValue, 15, 15); + this.actions.assets.copyAssetParamNotification.trigger({ + param, + shortValue, + }); + }; + @action _refreshAssetsData = () => { if (this.stores.networkStatus.isConnected) { const { all } = this.stores.wallets; diff --git a/source/renderer/app/types/notificationTypes.js b/source/renderer/app/types/notificationTypes.js index cd5d4310eb..aff06edcfe 100644 --- a/source/renderer/app/types/notificationTypes.js +++ b/source/renderer/app/types/notificationTypes.js @@ -5,7 +5,6 @@ export type NotificationId = | 'copyWalletPublicKey' | 'copyICOPublicKey' | 'copyAddress' - | 'copyAssetItem' | 'copyStateDirectoryPath' | 'downloadAddressPDFSuccess' | 'downloadLogsProgress' @@ -13,7 +12,8 @@ export type NotificationId = | 'downloadQRCodeImageSuccess' | 'downloadVotingPDFSuccess' | 'downloadRewardsCSVSuccess' - | 'downloadTransactionsCSVSuccess'; + | 'downloadTransactionsCSVSuccess' + | 'copyAssetParam'; export type NotificationConfig = { id: NotificationId, From 0caff211e9b2b40b63b22d3acf9ca834d7cbcdc0 Mon Sep 17 00:00:00 2001 From: Danilo Prates Date: Mon, 13 Sep 2021 16:39:41 -0300 Subject: [PATCH 03/60] [DDW-694] CHANGELOG --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c6ebf1c8c3..15dcbe3cc5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ Changelog ### Features +- Implemented the wallet Tokens dedicated screen ([PR 2671](https://github.com/input-output-hk/daedalus/pull/2671)) - Implemented static screens for signing dApp interaction transactions ([PR 2626](https://github.com/input-output-hk/daedalus/pull/2626)) ### Fixes From 4d23d512d7f685ee1704e448a214f185626d8464 Mon Sep 17 00:00:00 2001 From: Danilo Prates Date: Mon, 13 Sep 2021 19:15:20 -0300 Subject: [PATCH 04/60] [DDW-694] Search init --- .../app/components/navigation/NavButton.scss | 2 +- .../wallet/navigation/WalletNavigation.js | 11 - .../components/wallet/tokens/WalletToken.js | 206 ++++++++++++++++++ .../components/wallet/tokens/WalletToken.scss | 127 +++++++++++ .../components/wallet/tokens/WalletTokens.js | 59 +++-- .../wallet/tokens/WalletTokens.scss | 1 + .../wallet/tokens/WalletTokensList.js | 117 ++++++++++ .../wallet/tokens/WalletTokensSearch.js | 50 +++++ .../wallet/tokens/WalletTokensSearch.scss | 38 ++++ .../widgets/forms/AssetsDropdown.js | 3 +- 10 files changed, 582 insertions(+), 32 deletions(-) create mode 100644 source/renderer/app/components/wallet/tokens/WalletToken.js create mode 100644 source/renderer/app/components/wallet/tokens/WalletToken.scss create mode 100644 source/renderer/app/components/wallet/tokens/WalletTokensList.js create mode 100644 source/renderer/app/components/wallet/tokens/WalletTokensSearch.js create mode 100644 source/renderer/app/components/wallet/tokens/WalletTokensSearch.scss diff --git a/source/renderer/app/components/navigation/NavButton.scss b/source/renderer/app/components/navigation/NavButton.scss index 8307559de8..84e4808a97 100755 --- a/source/renderer/app/components/navigation/NavButton.scss +++ b/source/renderer/app/components/navigation/NavButton.scss @@ -35,7 +35,7 @@ justify-content: center; padding: 0 5px; text-align: center; - width: calc(100% - 30px); + width: calc(100% - 8px); } .label { diff --git a/source/renderer/app/components/wallet/navigation/WalletNavigation.js b/source/renderer/app/components/wallet/navigation/WalletNavigation.js index 0a9897b0ca..c849308fa4 100755 --- a/source/renderer/app/components/wallet/navigation/WalletNavigation.js +++ b/source/renderer/app/components/wallet/navigation/WalletNavigation.js @@ -8,11 +8,6 @@ import { LEGACY_WALLET_EXCLUDED_NAV_ITEMS, } from '../../../config/walletNavigationConfig'; import Navigation from '../../navigation/Navigation'; -import summaryIcon from '../../../assets/images/wallet-nav/summary-ic.inline.svg'; -import sendIcon from '../../../assets/images/wallet-nav/send-ic.inline.svg'; -import receiveIcon from '../../../assets/images/wallet-nav/receive-ic.inline.svg'; -import transactionsIcon from '../../../assets/images/wallet-nav/transactions-ic.inline.svg'; -import settingsIcon from '../../../assets/images/wallet-nav/wallet-settings-2-ic.inline.svg'; import type { NavButtonProps, NavDropdownProps, @@ -91,33 +86,27 @@ export default class WalletNavigation extends Component { { id: WALLET_NAV_IDS.SUMMARY, label: intl.formatMessage(messages.summary), - icon: summaryIcon, }, { id: WALLET_NAV_IDS.SEND, label: intl.formatMessage(messages.send), - icon: sendIcon, }, { id: WALLET_NAV_IDS.RECEIVE, label: intl.formatMessage(messages.receive), - icon: receiveIcon, }, { id: WALLET_NAV_IDS.TRANSACTIONS, label: intl.formatMessage(messages.transactions), - icon: transactionsIcon, }, { id: WALLET_NAV_IDS.TOKENS, label: intl.formatMessage(messages.tokens), - icon: transactionsIcon, }, { id: WALLET_NAV_IDS.SETTINGS, type: 'dropdown', label: intl.formatMessage(messages.more), - icon: settingsIcon, hasNotification, options: [ { diff --git a/source/renderer/app/components/wallet/tokens/WalletToken.js b/source/renderer/app/components/wallet/tokens/WalletToken.js new file mode 100644 index 0000000000..92e7cbaa67 --- /dev/null +++ b/source/renderer/app/components/wallet/tokens/WalletToken.js @@ -0,0 +1,206 @@ +// @flow +import React, { useState } from 'react'; +import { observer } from 'mobx-react'; +import { defineMessages, intlShape, injectIntl } from 'react-intl'; +import { Button } from 'react-polymorph/lib/components/Button'; +import { PopOver } from 'react-polymorph/lib/components/PopOver'; +import classNames from 'classnames'; +import { get } from 'lodash'; +import SVGInline from 'react-svg-inline'; +import styles from './WalletToken.scss'; +import Asset from '../../assets/Asset'; +import AssetAmount from '../../assets/AssetAmount'; +import AssetContent from '../../assets/AssetContent'; +import type { AssetToken } from '../../../api/assets/types'; +import arrow from '../../../assets/images/collapse-arrow-small.inline.svg'; +import warningIcon from '../../../assets/images/asset-token-warning-ic.inline.svg'; + +const messages = defineMessages({ + tokenSendButton: { + id: 'wallet.summary.asset.tokenSendButton', + defaultMessage: '!!!Send', + description: 'Send button on Wallet summary assets page', + }, + amountLabel: { + id: 'wallet.summary.asset.amountLabel', + defaultMessage: '!!!Amount', + description: 'Amount label on Wallet summary assets page', + }, + settingsButtonLabel: { + id: 'wallet.summary.asset.settings.button.label', + defaultMessage: '!!!Settings', + description: 'Settings label on Wallet summary assets page', + }, + settingsWarningPopOverAvailable: { + id: 'assets.warning.available', + defaultMessage: + '!!!Recommended configuration for decimal places for this native token is available.', + description: 'Asset settings recommended pop over content', + }, + settingsWarningPopOverNotUsing: { + id: 'assets.warning.notUsing', + defaultMessage: + '!!!You are not using the recommended decimal place configuration for this native token.', + description: 'Asset settings recommended pop over content', + }, +}); + +type Props = { + asset: AssetToken, + onOpenAssetSend: Function, + onCopyAssetParam: Function, + onAssetSettings: Function, + anyAssetWasHovered: boolean, + isLoading: boolean, + assetSettingsDialogWasOpened: boolean, + intl: intlShape.isRequired, +}; + +type IsExpanded = boolean; + +const WalletSummaryAsset = observer((props: Props) => { + console.log('props', props); + const [isExpanded, setIsExpanded] = useState(false); + + const toggleIsExpanded = () => { + setIsExpanded(!isExpanded); + }; + + const header = () => { + const { + asset, + onCopyAssetParam, + isLoading, + anyAssetWasHovered, + assetSettingsDialogWasOpened, + } = props; + const { decimals, recommendedDecimals } = asset; + const arrowStyles = classNames(styles.arrow, { + [styles.isExpanded]: isExpanded, + }); + const hasWarning = + typeof recommendedDecimals === 'number' && + decimals !== recommendedDecimals; + return ( +
+ + + +
+ ); + }; + + const footer = () => { + const { asset, isLoading, intl } = props; + return ( +
+
+
{intl.formatMessage(messages.amountLabel)}
+
+ {' '} + +
+
+ {buttons()} +
+ ); + }; + + const buttons = () => { + const { asset, onOpenAssetSend, onAssetSettings, intl } = props; + const { recommendedDecimals, decimals } = asset; + const hasWarning = + typeof recommendedDecimals === 'number' && + decimals !== recommendedDecimals; + let settingsButtonLabel = intl.formatMessage(messages.settingsButtonLabel); + let warningPopOverMessage; + if (hasWarning) { + warningPopOverMessage = + typeof decimals === 'number' + ? messages.settingsWarningPopOverNotUsing + : messages.settingsWarningPopOverAvailable; + settingsButtonLabel = ( + <> + {settingsButtonLabel} + + + ); + } + const settingsButton = ( +
+ ); + }; + + const { asset, onCopyAssetParam } = props; + const componentStyles = classNames(styles.component, { + [styles.isExpanded]: isExpanded, + }); + return ( +
+ {header()} +
+ + {footer()} +
+
+ ); +}); + +export default injectIntl(WalletSummaryAsset); diff --git a/source/renderer/app/components/wallet/tokens/WalletToken.scss b/source/renderer/app/components/wallet/tokens/WalletToken.scss new file mode 100644 index 0000000000..9a96f56c93 --- /dev/null +++ b/source/renderer/app/components/wallet/tokens/WalletToken.scss @@ -0,0 +1,127 @@ +.component { + &:not(:last-of-type) { + border-bottom: 1px solid rgba(94, 96, 102, 0.15); + } + &.isExpanded { + background-color: var(--theme-button-flat-background-color-hover); + padding-bottom: 20px; + .header { + background-color: var(--theme-button-flat-background-color-hover); + } + .content { + display: block; + } + } +} +.header { + cursor: pointer; + display: flex; + justify-content: space-between; + padding: 7px 42px 7px 12px; + position: relative; + .asset { + max-width: calc(100% - 90px); + } + .assetAmount { + color: var(--theme-widgets-asset-token-text-color); + font-family: var(--font-regular); + font-size: 12px; + letter-spacing: 0.4px; + line-height: 1.33; + margin: 3px 0; + max-width: 80px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } +} +.leftContent { + max-width: 75%; +} +.rightContent { + max-width: 25%; +} +.arrow { + bottom: 10px; + height: 22px; + opacity: 0.3; + position: absolute; + right: 12px; + text-align: center; + top: 7px; + width: 12px; + z-index: 1; + + > svg { + height: 7px; + margin-top: 7px; + width: 12px; + + path { + fill: var(--theme-widgets-asset-token-text-color); + } + } + .header:hover & { + opacity: 0.5; + } + &.isExpanded { + transform: rotate(180deg); + } +} +.content { + display: none; + margin: 13px 12px 0; +} +.footer { + border-top: 1px solid var(--theme-wallet-settings-section-separator-color); + color: var(--theme-widgets-asset-token-text-color); + display: flex; + justify-content: space-between; + margin-top: 20px; + padding-top: 20px; + + dl { + line-height: 1; + padding: 9px 0 0 8px; + width: calc(100% - 264px); + } + + dt { + display: inline-block; + font-family: var(--font-medium); + font-size: 12px; + line-height: 1.33; + text-align: right; + white-space: nowrap; + width: 67px; + } + + dd { + display: inline-flex; + font-family: var(--font-light); + font-size: 12px; + line-height: 16px; + margin-left: 10px; + white-space: normal; + width: calc(100% - 100px); + word-break: break-all; + word-wrap: break-word; + } + + .footerButtons { + margin: auto 0; + white-space: nowrap; + .button { + height: 36px; + margin-left: 12px; + width: 120px; + } + .settingsButton { + svg { + height: 9px; + margin-left: 6px; + width: 11px; + } + } + } +} diff --git a/source/renderer/app/components/wallet/tokens/WalletTokens.js b/source/renderer/app/components/wallet/tokens/WalletTokens.js index 75ffbdecfb..fb348f255b 100644 --- a/source/renderer/app/components/wallet/tokens/WalletTokens.js +++ b/source/renderer/app/components/wallet/tokens/WalletTokens.js @@ -1,39 +1,60 @@ // @flow -import React from 'react'; -import classnames from 'classnames'; -import { defineMessages, intlShape, injectIntl } from 'react-intl'; +import React, { useState } from 'react'; +import { intlShape, injectIntl, defineMessages } from 'react-intl'; +import { omit } from 'lodash'; import { observer } from 'mobx-react'; import styles from './WalletTokens.scss'; import Wallet from '../../../domains/Wallet'; +import WalletTokensList from './WalletTokensList'; +import WalletTokensSearch from './WalletTokensSearch'; import type { AssetToken } from '../../../api/assets/types'; -// const messages = defineMessages({ -// fingerprintItem: { -// id: 'assets.assetToken.param.fingerprint', -// defaultMessage: '!!!Fingerprint', -// description: '"fingerprint" item.', -// }, -// }); +const messages = defineMessages({ + favoritesListTitle: { + id: 'wallet.tokens.list.favorites.title', + defaultMessage: '!!!Favorites', + description: 'Favorites list title label', + }, + tokensListTitle: { + id: 'wallet.tokens.list.tokens.title', + defaultMessage: '!!!Tokens', + description: 'Favorites list title label', + }, +}); type Props = { - wallet: Wallet, assets: Array, - onOpenAssetSend: Function, - onCopyAssetParam: Function, - onAssetSettings: Function, + assetSettingsDialogWasOpened: boolean, currentLocale: string, + intl: intlShape.isRequired, isLoadingAssets: boolean, - assetSettingsDialogWasOpened: boolean, + onAssetSettings: Function, + onCopyAssetParam: Function, + onOpenAssetSend: Function, + wallet: Wallet, intl: intlShape.isRequired, }; - +type SearchValue = string; const WalletTokens = observer((props: Props) => { - console.log('props', props); - const { assets } = props; + const [searchValue, setSearchValue] = useState(''); + + const { assets, intl } = props; + const listProps = { ...omit(props, 'assets', 'intl'), searchValue }; + const favoriteTokens = [...assets.slice(0, 1)]; return (
-
{JSON.stringify(assets, null, 2)}
+ + +
); }); diff --git a/source/renderer/app/components/wallet/tokens/WalletTokens.scss b/source/renderer/app/components/wallet/tokens/WalletTokens.scss index 27bdc0eb43..aa191b05be 100644 --- a/source/renderer/app/components/wallet/tokens/WalletTokens.scss +++ b/source/renderer/app/components/wallet/tokens/WalletTokens.scss @@ -1,2 +1,3 @@ .component { + padding: 20px; } diff --git a/source/renderer/app/components/wallet/tokens/WalletTokensList.js b/source/renderer/app/components/wallet/tokens/WalletTokensList.js new file mode 100644 index 0000000000..ec9eeec09d --- /dev/null +++ b/source/renderer/app/components/wallet/tokens/WalletTokensList.js @@ -0,0 +1,117 @@ +// @flow +import React from 'react'; +import { defineMessages, intlShape, injectIntl } from 'react-intl'; +import { omit, filter, escapeRegExp } from 'lodash'; +import { observer } from 'mobx-react'; +// import { onSearchAssetsDropdown } from '../../widgets/forms/AssetsDropdown'; + +import styles from './WalletTokens.scss'; +import Wallet from '../../../domains/Wallet'; +import BorderedBox from '../../widgets/BorderedBox'; +import LoadingSpinner from '../../widgets/LoadingSpinner'; +import WalletToken from './WalletToken'; +import type { AssetToken } from '../../../api/assets/types'; + +const messages = defineMessages({ + noResults: { + id: 'wallet.tokens.search.noResults', + defaultMessage: '!!!No results matching your query', + description: 'No results on Wallet summary assets page', + }, +}); + +type Props = { + assets: Array, + assetSettingsDialogWasOpened: boolean, + currentLocale: string, + intl: intlShape.isRequired, + isLoadingAssets: boolean, + onAssetSettings: Function, + onCopyAssetParam: Function, + onOpenAssetSend: Function, + searchValue: string, + title: string, + wallet: Wallet, +}; + +const onSearchAssetsDropdown = (_searchValue: string, assets: Array) => + filter(assets, (asset) => { + const searchValue = _searchValue.trim(); + if (searchValue.length < 3) { + return true; + } + const { policyId, assetName, fingerprint, metadata } = asset; + const { name, ticker, description } = metadata || {}; + const checkList = [ + policyId, + assetName, + fingerprint, + metadata, + name, + ticker, + description, + ]; + const regex = new RegExp(escapeRegExp(searchValue), 'i'); + const result = checkList.some((item) => regex.test(item)); + return result; + }); + +const WalletTokensList = observer((props: Props) => { + const { + // anyAssetWasHovered, + assets, + assetSettingsDialogWasOpened, + intl, + isLoadingAssets, + onAssetSettings, + onCopyAssetParam, + onOpenAssetSend, + searchValue, + title, + wallet, + } = props; + const isRestoreActive = wallet.isRestoring; + + const filteredAssets = onSearchAssetsDropdown(searchValue, assets); + + const noResults = + !filteredAssets.length && searchValue && searchValue.trim().length >= 3; + + if (isLoadingAssets) { + return ( +
+ +
+ ); + } + + if (noResults) { + return ( +

+ {intl.formatMessage(messages.noResults)} +

+ ); + } + + return ( +
+

{title}

+ + {filteredAssets.map((asset) => ( + + ))} + +
+ ); +}); + +export default injectIntl(WalletTokensList); diff --git a/source/renderer/app/components/wallet/tokens/WalletTokensSearch.js b/source/renderer/app/components/wallet/tokens/WalletTokensSearch.js new file mode 100644 index 0000000000..3eb318c479 --- /dev/null +++ b/source/renderer/app/components/wallet/tokens/WalletTokensSearch.js @@ -0,0 +1,50 @@ +// @flow +import React from 'react'; +import { intlShape, injectIntl, defineMessages } from 'react-intl'; +import classNames from 'classnames'; +import { Input } from 'react-polymorph/lib/components/Input'; +import SVGInline from 'react-svg-inline'; +import { observer } from 'mobx-react'; +import styles from './WalletTokens.scss'; +import searchIcon from '../../../assets/images/search.inline.svg'; +import crossIcon from '../../../assets/images/close-cross.inline.svg'; + +const messages = defineMessages({ + placeholder: { + id: 'wallet.tokens.search.placeholder', + defaultMessage: '!!!Search', + description: 'Search placeholder for the Wallet Tokens search', + }, +}); + +type Props = { + intl: intlShape.isRequired, + onSearch: Function, + searchValue: string, +}; +const WalletTokensSearch = observer((props: Props) => { + const { searchValue, onSearch, intl } = props; + + console.log('!!searchValue.length', !!searchValue.length); + return ( +
+ {/* */} + + {!!searchValue.length && ( + + )} +
+ ); +}); + +export default injectIntl(WalletTokensSearch); diff --git a/source/renderer/app/components/wallet/tokens/WalletTokensSearch.scss b/source/renderer/app/components/wallet/tokens/WalletTokensSearch.scss new file mode 100644 index 0000000000..bc81e67f28 --- /dev/null +++ b/source/renderer/app/components/wallet/tokens/WalletTokensSearch.scss @@ -0,0 +1,38 @@ +.component { + margin-bottom: 20px; + position: relative; + .searchIcon { + left: 20px; + position: absolute; + top: 17px; + z-index: 1; + svg { + height: 15px; + width: 15px; + } + } + input { + border-radius: 4px; + padding: 13px 58px 13px 54px; + } + .clearButton { + border-radius: 3px; + cursor: pointer; + height: 28px; + position: absolute; + right: 12px; + top: 11px; + width: 28px; + z-index: 1; + &:hover { + opacity: 0.8; + } + svg { + height: 10px; + width: 10px; + polygon { + fill: var(--theme-bordered-box-text-color); + } + } + } +} diff --git a/source/renderer/app/components/widgets/forms/AssetsDropdown.js b/source/renderer/app/components/widgets/forms/AssetsDropdown.js index 28dafb5e45..052e7de789 100644 --- a/source/renderer/app/components/widgets/forms/AssetsDropdown.js +++ b/source/renderer/app/components/widgets/forms/AssetsDropdown.js @@ -21,10 +21,11 @@ type Props = { }; export const onSearchAssetsDropdown = ( - searchValue: string, + _searchValue: string, options: Array ) => { return filter(options, ({ asset }) => { + const searchValue = _searchValue.trim(); if (searchValue.length < 3) { return true; } From 9feb5b723232fb8a86c6c2914b2dd48fd8458e2c Mon Sep 17 00:00:00 2001 From: Danilo Prates Date: Tue, 14 Sep 2021 15:33:18 -0300 Subject: [PATCH 05/60] [DDW-694] Fix Assets search --- .../wallet/summary/WalletSummary.js | 4 +- .../wallet/summary/WalletSummaryAssets.js | 279 +----------------- .../components/wallet/tokens/WalletToken.js | 5 +- .../wallet/tokens/WalletTokensList.js | 31 +- .../widgets/forms/AssetsDropdown.js | 34 +-- source/renderer/app/utils/assets.js | 29 ++ 6 files changed, 59 insertions(+), 323 deletions(-) diff --git a/source/renderer/app/components/wallet/summary/WalletSummary.js b/source/renderer/app/components/wallet/summary/WalletSummary.js index 9047fbcd21..3c9972b1d3 100644 --- a/source/renderer/app/components/wallet/summary/WalletSummary.js +++ b/source/renderer/app/components/wallet/summary/WalletSummary.js @@ -8,6 +8,7 @@ import WalletSummaryAssets from './WalletSummaryAssets'; import WalletSummaryCurrency from './WalletSummaryCurrency'; import type { AssetToken } from '../../../api/assets/types'; import WalletSummaryNoTokens from './WalletSummaryNoTokens'; +import WalletTokensList from '../tokens/WalletTokensList'; type Props = { wallet: Wallet, @@ -84,7 +85,7 @@ export default class WalletSummary extends Component { {!isRestoring && ( <> {hasAssets ? ( - { onAssetSettings={onAssetSettings} assetSettingsDialogWasOpened={assetSettingsDialogWasOpened} currentLocale={currentLocale} + title="Recently used tokens" /> ) : ( , - onOpenAssetSend: Function, - onCopyAssetParam: Function, - onAssetSettings: Function, + assetSettingsDialogWasOpened: boolean, currentLocale: string, isLoadingAssets: boolean, - assetSettingsDialogWasOpened: boolean, -}; - -type State = { - anyAssetWasHovered: boolean, - isSearchOpen: boolean, - searchValue: string, + onAssetSettings: Function, + onCopyAssetParam: Function, + onOpenAssetSend: Function, + intl: intlShape.isRequired, + wallet: Wallet, }; -@observer -export default class WalletSummaryAssets extends Component { - static contextTypes = { - intl: intlShape.isRequired, - }; - - state = { - anyAssetWasHovered: false, - isSearchOpen: false, - searchValue: '', - }; - - componentDidUpdate(prevProps: Props) { - const { wallet } = this.props; - if (prevProps.wallet.id !== wallet.id) { - this.setSearchValue(''); - this.focusInputField(); - } - } - - searchInput: Input; - - handleHoverAsset = () => { - this.setState({ anyAssetWasHovered: true }); - }; - - focusInputField = () => { - const { isSearchOpen } = this.state; - if (isSearchOpen && this.searchInput && this.searchInput.focus) { - this.searchInput.focus(); - } - }; - - toggleSearch = () => { - const { isSearchOpen } = this.state; - this.setState( - { - isSearchOpen: !isSearchOpen, - }, - () => { - this.focusInputField(); - } - ); - }; - - setSearchValue = (searchValue: string) => { - this.setState({ - searchValue, - }); - }; - - get filteredAssets() { - const { searchValue } = this.state; - const { assets } = this.props; - return onSearchAssetsDropdown( - searchValue.trim(), - assets.map((asset) => ({ asset })) - ); - } - - get assets() { - const { filteredAssets } = this; - return filteredAssets.map(({ asset }) => asset); - } - - renderContent = () => { - const { - wallet, - onOpenAssetSend, - onCopyAssetParam, - onAssetSettings, - assetSettingsDialogWasOpened, - isLoadingAssets, - } = this.props; - const { intl } = this.context; - const { assets } = this; - const { anyAssetWasHovered, searchValue } = this.state; - const isRestoreActive = wallet.isRestoring; - const noResults = - !assets.length && searchValue && searchValue.trim().length >= 3; - - if (isLoadingAssets) { - return ( -
- -
- ); - } - - if (noResults) { - return ( -

- {intl.formatMessage(messages.noResults)} -

- ); - } - - return assets.map((asset) => ( - - )); - }; - - renderHeader = () => { - const { isLoadingAssets, currentLocale } = this.props; - const { isSearchOpen, searchValue } = this.state; - const { intl } = this.context; - const { assets } = this; - const searchButtonStyles = classNames([styles.searchButton, 'flat']); - const numberOfAssets = !isLoadingAssets && !!assets && `(${assets.length})`; - - const searchButtonLabel = isSearchOpen - ? intl.formatMessage(messages.hideSearchButtonLabel) - : intl.formatMessage(messages.showSearchButtonLabel); - - const hasSearch = - !!searchValue && !!searchValue.trim().length && !isSearchOpen; - - const headerStyles = classNames([styles.header, styles[currentLocale]]); - - return ( -
-
- {intl.formatMessage(messages.tokensTitle)} {numberOfAssets} - {hasSearch && ( - <> -  -  -
- {searchValue} -
-
this.setSearchValue('')} - > - -
- - )} -
-
- ); - }; - - renderSearch = () => { - const { isSearchOpen, searchValue } = this.state; - const { intl } = this.context; - - if (!isSearchOpen) return null; - return ( -
- - { - this.searchInput = input; - }} - /> - {!!searchValue.length && ( - - )} -
- ); - }; +const WalletSummaryAssets = observer((props: Props) => { + return ; +}); - render() { - const { intl } = this.context; - return ( -
- {this.renderHeader()} - {this.renderSearch()} - -
- {intl.formatMessage(messages.headerToken)} - {intl.formatMessage(messages.headerAmount)} -
- {this.renderContent()} -
-
- ); - } -} +export default injectIntl(WalletSummaryAssets); diff --git a/source/renderer/app/components/wallet/tokens/WalletToken.js b/source/renderer/app/components/wallet/tokens/WalletToken.js index 92e7cbaa67..273839dc04 100644 --- a/source/renderer/app/components/wallet/tokens/WalletToken.js +++ b/source/renderer/app/components/wallet/tokens/WalletToken.js @@ -58,8 +58,7 @@ type Props = { type IsExpanded = boolean; -const WalletSummaryAsset = observer((props: Props) => { - console.log('props', props); +const WalletToken = observer((props: Props) => { const [isExpanded, setIsExpanded] = useState(false); const toggleIsExpanded = () => { @@ -203,4 +202,4 @@ const WalletSummaryAsset = observer((props: Props) => { ); }); -export default injectIntl(WalletSummaryAsset); +export default injectIntl(WalletToken); diff --git a/source/renderer/app/components/wallet/tokens/WalletTokensList.js b/source/renderer/app/components/wallet/tokens/WalletTokensList.js index ec9eeec09d..5e9f9d09d8 100644 --- a/source/renderer/app/components/wallet/tokens/WalletTokensList.js +++ b/source/renderer/app/components/wallet/tokens/WalletTokensList.js @@ -1,9 +1,8 @@ // @flow import React from 'react'; import { defineMessages, intlShape, injectIntl } from 'react-intl'; -import { omit, filter, escapeRegExp } from 'lodash'; import { observer } from 'mobx-react'; -// import { onSearchAssetsDropdown } from '../../widgets/forms/AssetsDropdown'; +import { searchAssets } from '../../../utils/assets'; import styles from './WalletTokens.scss'; import Wallet from '../../../domains/Wallet'; @@ -29,33 +28,11 @@ type Props = { onAssetSettings: Function, onCopyAssetParam: Function, onOpenAssetSend: Function, - searchValue: string, + searchValue?: string, title: string, wallet: Wallet, }; -const onSearchAssetsDropdown = (_searchValue: string, assets: Array) => - filter(assets, (asset) => { - const searchValue = _searchValue.trim(); - if (searchValue.length < 3) { - return true; - } - const { policyId, assetName, fingerprint, metadata } = asset; - const { name, ticker, description } = metadata || {}; - const checkList = [ - policyId, - assetName, - fingerprint, - metadata, - name, - ticker, - description, - ]; - const regex = new RegExp(escapeRegExp(searchValue), 'i'); - const result = checkList.some((item) => regex.test(item)); - return result; - }); - const WalletTokensList = observer((props: Props) => { const { // anyAssetWasHovered, @@ -66,13 +43,13 @@ const WalletTokensList = observer((props: Props) => { onAssetSettings, onCopyAssetParam, onOpenAssetSend, - searchValue, + searchValue = '', title, wallet, } = props; const isRestoreActive = wallet.isRestoring; - const filteredAssets = onSearchAssetsDropdown(searchValue, assets); + const filteredAssets = searchAssets(searchValue, assets); const noResults = !filteredAssets.length && searchValue && searchValue.trim().length >= 3; diff --git a/source/renderer/app/components/widgets/forms/AssetsDropdown.js b/source/renderer/app/components/widgets/forms/AssetsDropdown.js index 052e7de789..8a2238ecb8 100644 --- a/source/renderer/app/components/widgets/forms/AssetsDropdown.js +++ b/source/renderer/app/components/widgets/forms/AssetsDropdown.js @@ -1,8 +1,9 @@ // @flow import React, { Component } from 'react'; -import { omit, filter, escapeRegExp } from 'lodash'; +import { omit } from 'lodash'; import ItemsDropdown from './ItemsDropdown'; import { formattedTokenWalletAmount } from '../../../utils/formatters'; +import { searchAssets } from '../../../utils/assets'; import type { AssetToken } from '../../../api/assets/types'; import Asset from '../../assets/Asset'; import styles from './AssetsDropdown.scss'; @@ -20,34 +21,13 @@ type Props = { assets?: Array<$Shape>, }; -export const onSearchAssetsDropdown = ( - _searchValue: string, - options: Array -) => { - return filter(options, ({ asset }) => { - const searchValue = _searchValue.trim(); - if (searchValue.length < 3) { - return true; - } - const { policyId, assetName, fingerprint, metadata } = asset; - const { name, ticker, description } = metadata || {}; - const checkList = [ - policyId, - assetName, - fingerprint, - metadata, - name, - ticker, - description, - ]; - const regex = new RegExp(escapeRegExp(searchValue), 'i'); - return checkList.some((item) => regex.test(item)); - }); -}; - export default class AssetsDropdown extends Component { static defaultProps = { - onSearch: onSearchAssetsDropdown, + onSearch: (searchValue: string, assets: Array) => + searchAssets( + searchValue, + assets.map(({ asset }) => asset) + ), }; render() { diff --git a/source/renderer/app/utils/assets.js b/source/renderer/app/utils/assets.js index a9481b8ecb..e830123d79 100644 --- a/source/renderer/app/utils/assets.js +++ b/source/renderer/app/utils/assets.js @@ -1,6 +1,7 @@ // @flow import find from 'lodash/find'; import BigNumber from 'bignumber.js'; +import { filter, escapeRegExp } from 'lodash'; import Wallet from '../domains/Wallet'; import type { Token, Tokens, AssetToken } from '../api/assets/types'; import { TransactionTypes } from '../domains/WalletTransaction'; @@ -116,6 +117,34 @@ export const hasTokensLeftAfterTransaction = ( return false; }; +/** + * Generic function for filtering AssetTokens + */ +export const searchAssets = ( + rawSearchValue: string, + assets: Array<{ asset: AssetToken }> +) => { + const searchValue = rawSearchValue.trim(); + if (searchValue.length < 3) { + return assets; + } + return filter(assets, (asset) => { + const { policyId, assetName, fingerprint, metadata } = asset; + const { name, ticker, description } = metadata || {}; + const checkList = [ + policyId, + assetName, + fingerprint, + metadata, + name, + ticker, + description, + ]; + const regex = new RegExp(escapeRegExp(searchValue), 'i'); + return checkList.some((item) => regex.test(item)); + }); +}; + export const isTokenMissingInWallet = (wallet?: ?Wallet, token?: Token) => { if (!wallet || !token || !token.uniqueId) { return false; From 2ee90afeed882c007939de570a56b89a4fe81cac Mon Sep 17 00:00:00 2001 From: Danilo Prates Date: Tue, 14 Sep 2021 16:08:53 -0300 Subject: [PATCH 06/60] [DDW-694] Fix Assets dropdown search --- .../widgets/forms/AssetsDropdown.js | 33 +++++++++++++++---- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/source/renderer/app/components/widgets/forms/AssetsDropdown.js b/source/renderer/app/components/widgets/forms/AssetsDropdown.js index 8a2238ecb8..28dafb5e45 100644 --- a/source/renderer/app/components/widgets/forms/AssetsDropdown.js +++ b/source/renderer/app/components/widgets/forms/AssetsDropdown.js @@ -1,9 +1,8 @@ // @flow import React, { Component } from 'react'; -import { omit } from 'lodash'; +import { omit, filter, escapeRegExp } from 'lodash'; import ItemsDropdown from './ItemsDropdown'; import { formattedTokenWalletAmount } from '../../../utils/formatters'; -import { searchAssets } from '../../../utils/assets'; import type { AssetToken } from '../../../api/assets/types'; import Asset from '../../assets/Asset'; import styles from './AssetsDropdown.scss'; @@ -21,13 +20,33 @@ type Props = { assets?: Array<$Shape>, }; +export const onSearchAssetsDropdown = ( + searchValue: string, + options: Array +) => { + return filter(options, ({ asset }) => { + if (searchValue.length < 3) { + return true; + } + const { policyId, assetName, fingerprint, metadata } = asset; + const { name, ticker, description } = metadata || {}; + const checkList = [ + policyId, + assetName, + fingerprint, + metadata, + name, + ticker, + description, + ]; + const regex = new RegExp(escapeRegExp(searchValue), 'i'); + return checkList.some((item) => regex.test(item)); + }); +}; + export default class AssetsDropdown extends Component { static defaultProps = { - onSearch: (searchValue: string, assets: Array) => - searchAssets( - searchValue, - assets.map(({ asset }) => asset) - ), + onSearch: onSearchAssetsDropdown, }; render() { From eb3e3a28acbd8f948e16eccadc5c4dc71d5b0c9c Mon Sep 17 00:00:00 2001 From: Danilo Prates Date: Tue, 14 Sep 2021 17:27:11 -0300 Subject: [PATCH 07/60] [DDW-694] Tokens list - progress --- .../wallet/summary/WalletSummary.js | 4 ++- .../wallet/summary/WalletSummaryAssets.js | 35 ------------------- .../wallet/tokens/WalletTokensList.js | 6 +++- .../containers/wallet/WalletSummaryPage.js | 11 +++++- source/renderer/app/utils/assets.js | 2 +- 5 files changed, 19 insertions(+), 39 deletions(-) delete mode 100644 source/renderer/app/components/wallet/summary/WalletSummaryAssets.js diff --git a/source/renderer/app/components/wallet/summary/WalletSummary.js b/source/renderer/app/components/wallet/summary/WalletSummary.js index 3c9972b1d3..49d4c7fb3c 100644 --- a/source/renderer/app/components/wallet/summary/WalletSummary.js +++ b/source/renderer/app/components/wallet/summary/WalletSummary.js @@ -4,7 +4,6 @@ import { observer } from 'mobx-react'; import Wallet from '../../../domains/Wallet'; import type { Currency } from '../../../types/currencyTypes'; import WalletSummaryHeader from './WalletSummaryHeader'; -import WalletSummaryAssets from './WalletSummaryAssets'; import WalletSummaryCurrency from './WalletSummaryCurrency'; import type { AssetToken } from '../../../api/assets/types'; import WalletSummaryNoTokens from './WalletSummaryNoTokens'; @@ -30,6 +29,7 @@ type Props = { isLoadingAssets: boolean, assetSettingsDialogWasOpened: boolean, onExternalLinkClick: Function, + onViewAllButtonClick: Function, }; @observer @@ -55,6 +55,7 @@ export default class WalletSummary extends Component { assetSettingsDialogWasOpened, isLoadingAssets, onExternalLinkClick, + onViewAllButtonClick, } = this.props; const { isRestoring } = wallet; @@ -95,6 +96,7 @@ export default class WalletSummary extends Component { assetSettingsDialogWasOpened={assetSettingsDialogWasOpened} currentLocale={currentLocale} title="Recently used tokens" + onViewAllButtonClick={onViewAllButtonClick} /> ) : ( , - assetSettingsDialogWasOpened: boolean, - currentLocale: string, - isLoadingAssets: boolean, - onAssetSettings: Function, - onCopyAssetParam: Function, - onOpenAssetSend: Function, - intl: intlShape.isRequired, - wallet: Wallet, -}; - -const WalletSummaryAssets = observer((props: Props) => { - return ; -}); - -export default injectIntl(WalletSummaryAssets); diff --git a/source/renderer/app/components/wallet/tokens/WalletTokensList.js b/source/renderer/app/components/wallet/tokens/WalletTokensList.js index 5e9f9d09d8..82891a20ad 100644 --- a/source/renderer/app/components/wallet/tokens/WalletTokensList.js +++ b/source/renderer/app/components/wallet/tokens/WalletTokensList.js @@ -23,6 +23,7 @@ type Props = { assets: Array, assetSettingsDialogWasOpened: boolean, currentLocale: string, + onViewAllButtonClick?: Function, intl: intlShape.isRequired, isLoadingAssets: boolean, onAssetSettings: Function, @@ -35,9 +36,9 @@ type Props = { const WalletTokensList = observer((props: Props) => { const { - // anyAssetWasHovered, assets, assetSettingsDialogWasOpened, + onViewAllButtonClick, intl, isLoadingAssets, onAssetSettings, @@ -86,6 +87,9 @@ const WalletTokensList = observer((props: Props) => { assetSettingsDialogWasOpened={assetSettingsDialogWasOpened} /> ))} + {onViewAllButtonClick && ( + + )}
); diff --git a/source/renderer/app/containers/wallet/WalletSummaryPage.js b/source/renderer/app/containers/wallet/WalletSummaryPage.js index 450a241af2..5981e46ebb 100755 --- a/source/renderer/app/containers/wallet/WalletSummaryPage.js +++ b/source/renderer/app/containers/wallet/WalletSummaryPage.js @@ -49,6 +49,13 @@ export default class WalletSummaryPage extends Component { }); }; + handleViewAllButtonClick = (walletId: string) => { + this.props.actions.router.goToRoute.trigger({ + route: ROUTES.WALLETS.PAGE, + params: { id: walletId, page: 'tokens' }, + }); + }; + render() { const { intl } = this.context; const { stores, actions } = this.props; @@ -83,7 +90,6 @@ export default class WalletSummaryPage extends Component { } = transactions; const { active: wallet } = wallets; const { isActive, isFetchingRate, lastFetched, rate, selected } = currency; - const { currentTimeFormat, currentDateFormat, currentLocale } = profile; const hasAssetsEnabled = WALLET_ASSETS_ENABLED; @@ -100,6 +106,8 @@ export default class WalletSummaryPage extends Component { const hasRawAssets = wallet.assets.total.length > 0; const isLoadingAssets = hasRawAssets && totalAssets < totalRawAssets; + const onViewAllButtonClick = () => this.handleViewAllButtonClick(wallet.id); + const getUrlByType = (type: 'tx' | 'address', param: string) => getNetworkExplorerUrlByType(type, param, network, currentLocale); @@ -161,6 +169,7 @@ export default class WalletSummaryPage extends Component { onCopyAssetParam={onCopyAssetParam.trigger} onAssetSettings={onAssetSettingsOpen.trigger} onExternalLinkClick={app.openExternalLink} + onViewAllButtonClick={onViewAllButtonClick} /> {walletTransactions} diff --git a/source/renderer/app/utils/assets.js b/source/renderer/app/utils/assets.js index e830123d79..0b9c64bf01 100644 --- a/source/renderer/app/utils/assets.js +++ b/source/renderer/app/utils/assets.js @@ -122,7 +122,7 @@ export const hasTokensLeftAfterTransaction = ( */ export const searchAssets = ( rawSearchValue: string, - assets: Array<{ asset: AssetToken }> + assets: Array ) => { const searchValue = rawSearchValue.trim(); if (searchValue.length < 3) { From 972252fd2e442dd7c59aad5076a9d738ee50df53 Mon Sep 17 00:00:00 2001 From: Danilo Prates Date: Wed, 15 Sep 2021 12:44:59 -0300 Subject: [PATCH 08/60] [DDW-694] Storybook stories --- source/renderer/app/i18n/locales/en-US.json | 3 + storybook/stories/wallets/index.js | 2 + .../wallets/tokens/WalletTokens.stories.js | 167 ++++++++++++++++++ .../tokens/WalletTokensList.stories.js | 164 +++++++++++++++++ 4 files changed, 336 insertions(+) create mode 100644 storybook/stories/wallets/tokens/WalletTokens.stories.js create mode 100644 storybook/stories/wallets/tokens/WalletTokensList.stories.js diff --git a/source/renderer/app/i18n/locales/en-US.json b/source/renderer/app/i18n/locales/en-US.json index 8ca9726ca1..ab8734322a 100755 --- a/source/renderer/app/i18n/locales/en-US.json +++ b/source/renderer/app/i18n/locales/en-US.json @@ -1118,6 +1118,9 @@ "wallet.summary.transactionsList.syncingTransactionsMessage": "Your transaction history for this wallet is being synced with the blockchain.", "wallet.summary.transactionsList.todayLabel": "Today", "wallet.summary.transactionsList.yesterdayLabel": "Yesterday", + "wallet.tokens.list.favorites.title": "Favorites", + "wallet.tokens.list.tokens.title": "Tokens", + "wallet.tokens.search.placeholder": "Search", "wallet.transaction.address.from": "From address", "wallet.transaction.address.to": "To address", "wallet.transaction.addresses.from": "From addresses", diff --git a/storybook/stories/wallets/index.js b/storybook/stories/wallets/index.js index 499bba5009..6d333918b9 100644 --- a/storybook/stories/wallets/index.js +++ b/storybook/stories/wallets/index.js @@ -8,6 +8,8 @@ import './transactions/TransactionsList.stories'; import './transactions/Transaction.stories'; import './transactions/TransactionMetadata.stories'; import './transactions/Utxo.stories'; +import './tokens/WalletTokens.stories'; +import './tokens/WalletTokensList.stories'; import './settings/WalletSettings.stories'; import './addWallet/AddWallet.stories'; import './import/WalletImportFile.stories'; diff --git a/storybook/stories/wallets/tokens/WalletTokens.stories.js b/storybook/stories/wallets/tokens/WalletTokens.stories.js new file mode 100644 index 0000000000..c55da8f0aa --- /dev/null +++ b/storybook/stories/wallets/tokens/WalletTokens.stories.js @@ -0,0 +1,167 @@ +// @flow +import React from 'react'; +import { storiesOf } from '@storybook/react'; +import { withKnobs, boolean, text } from '@storybook/addon-knobs'; +import { action } from '@storybook/addon-actions'; +import BigNumber from 'bignumber.js'; +import StoryDecorator from '../../_support/StoryDecorator'; + +import { + generateAssetToken, + generateWallet, + generateHash, +} from '../../_support/utils'; + +import type { WalletTokens } from '../../../../source/renderer/app/api/assets/types'; + +import WalletsWrapper from '../_utils/WalletsWrapper'; + +// Screens +import WalletTokensScreen from '../../../../source/renderer/app/components/wallet/tokens/WalletTokens'; + +const assets = [ + generateAssetToken( + '65bc72542b0ca20391caaf66a4d4e7897d282f9c136cd3513136945c', + '', + 'tokenb0ca20391caaf66a4d4e7897d282f9c136cd3513136945c2542', + 100, + { + name: 'MakerDAO', + ticker: 'DAI', + description: 'Test description', + unit: { + name: 'DAI', + decimals: 6, + }, + url: 'http://example.com', + logo: '', + } + ), + generateAssetToken( + '65bc72542b0ca20391caaf66a4d4d7897d281f9c136cd3513136945b', + '', + 'tokenb0ca20391caaf66a4d4d7897d281f9c136cd3513136945b2342', + 400 + ), + generateAssetToken( + '65ac82542b0ca20391caaf66a4d4d7897d281f9c136cd3513136945b', + '', + 'tokenb0ca20391caaf66a4d4d7897d281f9c136cd3513136945b2542', + 100, + { + name: 'Tether', + ticker: 'USDT', + description: 'Test description', + unit: { + name: 'USDT', + decimals: 6, + }, + url: 'http://example.com', + logo: '', + } + ), + generateAssetToken( + '65cn72542b0ca10391caaf66a4d4d2897d281f3c136cd3513136945b', + '', + 'tokenb0ca10391caaf66a4d4d2897d281f3c136cd3513136945b2542', + 100, + { + name: 'USD Coin', + ticker: 'USDC', + description: 'Test description', + unit: { + name: 'USDC', + decimals: 6, + }, + url: 'http://example.com', + logo: '', + } + ), +]; + +const walletTokens: WalletTokens = { + available: [ + { + id: generateHash(), + policyId: '65bc72542b0ca20391caaf66a4d4e7897d282f9c136cd3513136945c', + assetName: '', + quantity: new BigNumber(400), + uniqueId: '65bc72542b0ca20391caaf66a4d4e7897d282f9c136cd3513136945c', + }, + { + id: generateHash(), + policyId: '65bc72542b0ca20391caaf66a4d4d7897d281f9c136cd3513136945b', + assetName: '', + quantity: new BigNumber(100), + uniqueId: '65bc72542b0ca20391caaf66a4d4d7897d281f9c136cd3513136945b', + }, + { + id: generateHash(), + policyId: '65ac82542b0ca20391caaf66a4d4d7897d281f9c136cd3513136945b', + assetName: '', + quantity: new BigNumber(200), + uniqueId: '65ac82542b0ca20391caaf66a4d4d7897d281f9c136cd3513136945b', + }, + { + id: generateHash(), + policyId: '65cn72542b0ca10391caaf66a4d4d2897d281f3c136cd3513136945b', + assetName: '', + quantity: new BigNumber(300), + uniqueId: '65cn72542b0ca10391caaf66a4d4d2897d281f3c136cd3513136945b', + }, + ], + total: [ + { + id: generateHash(), + policyId: '65bc72542b0ca20391caaf66a4d4e7897d282f9c136cd3513136945c', + assetName: '', + quantity: new BigNumber(400), + uniqueId: '65bc72542b0ca20391caaf66a4d4e7897d282f9c136cd3513136945c', + }, + { + id: generateHash(), + policyId: '65bc72542b0ca20391caaf66a4d4d7897d281f9c136cd3513136945b', + assetName: '', + quantity: new BigNumber(100), + uniqueId: '65bc72542b0ca20391caaf66a4d4d7897d281f9c136cd3513136945b', + }, + { + id: generateHash(), + policyId: '65ac82542b0ca20391caaf66a4d4d7897d281f9c136cd3513136945b', + assetName: '', + quantity: new BigNumber(200), + uniqueId: '65ac82542b0ca20391caaf66a4d4d7897d281f9c136cd3513136945b', + }, + { + id: generateHash(), + policyId: '65cn72542b0ca10391caaf66a4d4d2897d281f3c136cd3513136945b', + assetName: '', + quantity: new BigNumber(300), + uniqueId: '65cn72542b0ca10391caaf66a4d4d2897d281f3c136cd3513136945b', + }, + ], +}; + +storiesOf('Wallets|Tokens', module) + // .addDecorator((story) => {story()}) + .addDecorator(WalletsWrapper) + .addDecorator(withKnobs) + + // ====== Stories ====== + .add('WalletTokens', ({ locale }: { locale: string }) => ( +
+ +
+ )); diff --git a/storybook/stories/wallets/tokens/WalletTokensList.stories.js b/storybook/stories/wallets/tokens/WalletTokensList.stories.js new file mode 100644 index 0000000000..50a801f75e --- /dev/null +++ b/storybook/stories/wallets/tokens/WalletTokensList.stories.js @@ -0,0 +1,164 @@ +// @flow +import React from 'react'; +import { storiesOf } from '@storybook/react'; +import { withKnobs, boolean, text } from '@storybook/addon-knobs'; +import { action } from '@storybook/addon-actions'; +import BigNumber from 'bignumber.js'; +import StoryDecorator from '../../_support/StoryDecorator'; + +import { + generateAssetToken, + generateWallet, + generateHash, +} from '../../_support/utils'; + +import type { WalletTokens } from '../../../../source/renderer/app/api/assets/types'; + +// Screens +import WalletTokensList from '../../../../source/renderer/app/components/wallet/tokens/WalletTokensList'; + +const assets = [ + generateAssetToken( + '65bc72542b0ca20391caaf66a4d4e7897d282f9c136cd3513136945c', + '', + 'tokenb0ca20391caaf66a4d4e7897d282f9c136cd3513136945c2542', + 100, + { + name: 'MakerDAO', + ticker: 'DAI', + description: 'Test description', + unit: { + name: 'DAI', + decimals: 6, + }, + url: 'http://example.com', + logo: '', + } + ), + generateAssetToken( + '65bc72542b0ca20391caaf66a4d4d7897d281f9c136cd3513136945b', + '', + 'tokenb0ca20391caaf66a4d4d7897d281f9c136cd3513136945b2342', + 400 + ), + generateAssetToken( + '65ac82542b0ca20391caaf66a4d4d7897d281f9c136cd3513136945b', + '', + 'tokenb0ca20391caaf66a4d4d7897d281f9c136cd3513136945b2542', + 100, + { + name: 'Tether', + ticker: 'USDT', + description: 'Test description', + unit: { + name: 'USDT', + decimals: 6, + }, + url: 'http://example.com', + logo: '', + } + ), + generateAssetToken( + '65cn72542b0ca10391caaf66a4d4d2897d281f3c136cd3513136945b', + '', + 'tokenb0ca10391caaf66a4d4d2897d281f3c136cd3513136945b2542', + 100, + { + name: 'USD Coin', + ticker: 'USDC', + description: 'Test description', + unit: { + name: 'USDC', + decimals: 6, + }, + url: 'http://example.com', + logo: '', + } + ), +]; + +const walletTokens: WalletTokens = { + available: [ + { + id: generateHash(), + policyId: '65bc72542b0ca20391caaf66a4d4e7897d282f9c136cd3513136945c', + assetName: '', + quantity: new BigNumber(400), + uniqueId: '65bc72542b0ca20391caaf66a4d4e7897d282f9c136cd3513136945c', + }, + { + id: generateHash(), + policyId: '65bc72542b0ca20391caaf66a4d4d7897d281f9c136cd3513136945b', + assetName: '', + quantity: new BigNumber(100), + uniqueId: '65bc72542b0ca20391caaf66a4d4d7897d281f9c136cd3513136945b', + }, + { + id: generateHash(), + policyId: '65ac82542b0ca20391caaf66a4d4d7897d281f9c136cd3513136945b', + assetName: '', + quantity: new BigNumber(200), + uniqueId: '65ac82542b0ca20391caaf66a4d4d7897d281f9c136cd3513136945b', + }, + { + id: generateHash(), + policyId: '65cn72542b0ca10391caaf66a4d4d2897d281f3c136cd3513136945b', + assetName: '', + quantity: new BigNumber(300), + uniqueId: '65cn72542b0ca10391caaf66a4d4d2897d281f3c136cd3513136945b', + }, + ], + total: [ + { + id: generateHash(), + policyId: '65bc72542b0ca20391caaf66a4d4e7897d282f9c136cd3513136945c', + assetName: '', + quantity: new BigNumber(400), + uniqueId: '65bc72542b0ca20391caaf66a4d4e7897d282f9c136cd3513136945c', + }, + { + id: generateHash(), + policyId: '65bc72542b0ca20391caaf66a4d4d7897d281f9c136cd3513136945b', + assetName: '', + quantity: new BigNumber(100), + uniqueId: '65bc72542b0ca20391caaf66a4d4d7897d281f9c136cd3513136945b', + }, + { + id: generateHash(), + policyId: '65ac82542b0ca20391caaf66a4d4d7897d281f9c136cd3513136945b', + assetName: '', + quantity: new BigNumber(200), + uniqueId: '65ac82542b0ca20391caaf66a4d4d7897d281f9c136cd3513136945b', + }, + { + id: generateHash(), + policyId: '65cn72542b0ca10391caaf66a4d4d2897d281f3c136cd3513136945b', + assetName: '', + quantity: new BigNumber(300), + uniqueId: '65cn72542b0ca10391caaf66a4d4d2897d281f3c136cd3513136945b', + }, + ], +}; + +storiesOf('Wallets|Tokens', module) + .addDecorator((story) => {story()}) + .addDecorator(withKnobs) + + // ====== Stories ====== + .add('WalletTokensList', ({ locale }: { locale: string }) => ( +
+ +
+ )); From 5f5b8f2751744740f04cc119fe511122eaef1ba3 Mon Sep 17 00:00:00 2001 From: Danilo Prates Date: Wed, 15 Sep 2021 12:52:25 -0300 Subject: [PATCH 09/60] [DDW-694] Storybook stories --- .../stories/wallets/_utils/WalletWithNavigationLayout.js | 1 + storybook/stories/wallets/summary/WalletSummary.stories.js | 1 + storybook/stories/wallets/tokens/WalletTokens.stories.js | 1 - .../stories/wallets/tokens/WalletTokensList.stories.js | 6 +++++- 4 files changed, 7 insertions(+), 2 deletions(-) diff --git a/storybook/stories/wallets/_utils/WalletWithNavigationLayout.js b/storybook/stories/wallets/_utils/WalletWithNavigationLayout.js index 4d20973158..ec9f0bf4c4 100644 --- a/storybook/stories/wallets/_utils/WalletWithNavigationLayout.js +++ b/storybook/stories/wallets/_utils/WalletWithNavigationLayout.js @@ -19,6 +19,7 @@ const walletStories = { send: 'Wallets|Send', receive: 'Wallets|Receive', transactions: 'Wallets|Transactions', + tokens: 'Wallets|Tokens', summary: 'Wallets|Summary', settings: 'Wallets|Settings', }; diff --git a/storybook/stories/wallets/summary/WalletSummary.stories.js b/storybook/stories/wallets/summary/WalletSummary.stories.js index 20ad0d9fca..bd6790778e 100644 --- a/storybook/stories/wallets/summary/WalletSummary.stories.js +++ b/storybook/stories/wallets/summary/WalletSummary.stories.js @@ -261,6 +261,7 @@ storiesOf('Wallets|Summary', module) true )} onExternalLinkClick={action('onExternalLinkClick')} + onViewAllButtonClick={action('onViewAllButtonClick')} /> ); }); diff --git a/storybook/stories/wallets/tokens/WalletTokens.stories.js b/storybook/stories/wallets/tokens/WalletTokens.stories.js index c55da8f0aa..ebf2ef0d06 100644 --- a/storybook/stories/wallets/tokens/WalletTokens.stories.js +++ b/storybook/stories/wallets/tokens/WalletTokens.stories.js @@ -143,7 +143,6 @@ const walletTokens: WalletTokens = { }; storiesOf('Wallets|Tokens', module) - // .addDecorator((story) => {story()}) .addDecorator(WalletsWrapper) .addDecorator(withKnobs) diff --git a/storybook/stories/wallets/tokens/WalletTokensList.stories.js b/storybook/stories/wallets/tokens/WalletTokensList.stories.js index 50a801f75e..6e4d4f971f 100644 --- a/storybook/stories/wallets/tokens/WalletTokensList.stories.js +++ b/storybook/stories/wallets/tokens/WalletTokensList.stories.js @@ -155,7 +155,11 @@ storiesOf('Wallets|Tokens', module) onAssetSettings={action('onAssetSettings')} onCopyAssetParam={action('onCopyAssetParam')} onOpenAssetSend={action('onOpenAssetSend')} - onViewAllButtonClick={action('onViewAllButtonClick')} + onViewAllButtonClick={ + boolean('Has View All button', false) + ? action('onViewAllButtonClick') + : null + } searchValue={text('searchValue', '')} title={text('Title', 'Tokens')} wallet={generateWallet('Wallet name', '45119903750165', walletTokens)} From 0264ce58ba57c0c19b3b0760f7bf17fd4ebd2618 Mon Sep 17 00:00:00 2001 From: Danilo Prates Date: Wed, 15 Sep 2021 15:08:06 -0300 Subject: [PATCH 10/60] [DDW-694] Tokens List Header - init --- .../wallet/tokens/WalletTokens.scss | 9 ++++++++ .../wallet/tokens/WalletTokensList.js | 22 ++++++++++++++----- source/renderer/app/i18n/locales/en-US.json | 1 + source/renderer/app/i18n/locales/ja-JP.json | 4 ++++ .../renderer/app/themes/daedalus/cardano.js | 3 +++ .../renderer/app/themes/daedalus/dark-blue.js | 3 +++ .../app/themes/daedalus/dark-cardano.js | 3 +++ .../app/themes/daedalus/flight-candidate.js | 3 +++ .../themes/daedalus/incentivized-testnet.js | 3 +++ .../app/themes/daedalus/light-blue.js | 3 +++ .../app/themes/daedalus/shelley-testnet.js | 3 +++ source/renderer/app/themes/daedalus/white.js | 3 +++ source/renderer/app/themes/daedalus/yellow.js | 3 +++ 13 files changed, 57 insertions(+), 6 deletions(-) diff --git a/source/renderer/app/components/wallet/tokens/WalletTokens.scss b/source/renderer/app/components/wallet/tokens/WalletTokens.scss index aa191b05be..7327db3212 100644 --- a/source/renderer/app/components/wallet/tokens/WalletTokens.scss +++ b/source/renderer/app/components/wallet/tokens/WalletTokens.scss @@ -1,3 +1,12 @@ .component { padding: 20px; } +.outerHeader { + margin: 0 10px 10px 20px; + .title { + color: var(--theme-tokens-list-header-text-color); + font-family: var(--font-regular); + font-size: 16px; + line-height: 22px; + } +} diff --git a/source/renderer/app/components/wallet/tokens/WalletTokensList.js b/source/renderer/app/components/wallet/tokens/WalletTokensList.js index 82891a20ad..58e85d5745 100644 --- a/source/renderer/app/components/wallet/tokens/WalletTokensList.js +++ b/source/renderer/app/components/wallet/tokens/WalletTokensList.js @@ -15,7 +15,12 @@ const messages = defineMessages({ noResults: { id: 'wallet.tokens.search.noResults', defaultMessage: '!!!No results matching your query', - description: 'No results on Wallet summary assets page', + description: 'No results on the WalletTokensList', + }, + searchResults: { + id: 'wallet.tokens.search.searchResults', + defaultMessage: '!!!Search Results', + description: 'Search Results on the WalletTokensList', }, }); @@ -49,11 +54,10 @@ const WalletTokensList = observer((props: Props) => { wallet, } = props; const isRestoreActive = wallet.isRestoring; - const filteredAssets = searchAssets(searchValue, assets); - - const noResults = - !filteredAssets.length && searchValue && searchValue.trim().length >= 3; + const hasSearch = + !isLoadingAssets && !!searchValue && searchValue.trim().length >= 3; + const noResults = hasSearch && !filteredAssets.length; if (isLoadingAssets) { return ( @@ -73,7 +77,13 @@ const WalletTokensList = observer((props: Props) => { return (
-

{title}

+
+
+ {title} + {hasSearch && intl.formatMessage(messages.searchResults)} ( + {assets.length}) +
+
{filteredAssets.map((asset) => ( Date: Wed, 15 Sep 2021 16:13:41 -0300 Subject: [PATCH 11/60] [DDW-694] Tokens List Header - progress --- .../components/wallet/tokens/WalletTokens.js | 1 + .../wallet/tokens/WalletTokens.scss | 11 +---- .../wallet/tokens/WalletTokensList.js | 46 +++++++++++-------- .../wallet/tokens/WalletTokensList.scss | 15 ++++++ .../wallet/tokens/WalletTokensSearch.js | 6 +-- .../wallet/tokens/WalletTokensSearch.scss | 2 +- source/renderer/app/i18n/locales/en-US.json | 1 + source/renderer/app/i18n/locales/ja-JP.json | 1 + .../wallets/tokens/WalletTokens.stories.js | 2 - .../tokens/WalletTokensList.stories.js | 1 - 10 files changed, 48 insertions(+), 38 deletions(-) create mode 100644 source/renderer/app/components/wallet/tokens/WalletTokensList.scss diff --git a/source/renderer/app/components/wallet/tokens/WalletTokens.js b/source/renderer/app/components/wallet/tokens/WalletTokens.js index fb348f255b..a54b2b7978 100644 --- a/source/renderer/app/components/wallet/tokens/WalletTokens.js +++ b/source/renderer/app/components/wallet/tokens/WalletTokens.js @@ -42,6 +42,7 @@ const WalletTokens = observer((props: Props) => { const listProps = { ...omit(props, 'assets', 'intl'), searchValue }; const favoriteTokens = [...assets.slice(0, 1)]; + console.log(intl.formatMessage(messages.favoritesListTitle)); return (
diff --git a/source/renderer/app/components/wallet/tokens/WalletTokens.scss b/source/renderer/app/components/wallet/tokens/WalletTokens.scss index 7327db3212..7bb63cbbbd 100644 --- a/source/renderer/app/components/wallet/tokens/WalletTokens.scss +++ b/source/renderer/app/components/wallet/tokens/WalletTokens.scss @@ -1,12 +1,3 @@ .component { - padding: 20px; -} -.outerHeader { - margin: 0 10px 10px 20px; - .title { - color: var(--theme-tokens-list-header-text-color); - font-family: var(--font-regular); - font-size: 16px; - line-height: 22px; - } + // padding: 20px; } diff --git a/source/renderer/app/components/wallet/tokens/WalletTokensList.js b/source/renderer/app/components/wallet/tokens/WalletTokensList.js index 58e85d5745..b2197fe10e 100644 --- a/source/renderer/app/components/wallet/tokens/WalletTokensList.js +++ b/source/renderer/app/components/wallet/tokens/WalletTokensList.js @@ -4,7 +4,7 @@ import { defineMessages, intlShape, injectIntl } from 'react-intl'; import { observer } from 'mobx-react'; import { searchAssets } from '../../../utils/assets'; -import styles from './WalletTokens.scss'; +import styles from './WalletTokensList.scss'; import Wallet from '../../../domains/Wallet'; import BorderedBox from '../../widgets/BorderedBox'; import LoadingSpinner from '../../widgets/LoadingSpinner'; @@ -59,20 +59,33 @@ const WalletTokensList = observer((props: Props) => { !isLoadingAssets && !!searchValue && searchValue.trim().length >= 3; const noResults = hasSearch && !filteredAssets.length; + let content; + if (isLoadingAssets) { - return ( + content = (
); - } - - if (noResults) { - return ( + } else if (noResults) { + content = (

{intl.formatMessage(messages.noResults)}

); + } else { + content = filteredAssets.map((asset) => ( + + )); } return ( @@ -80,23 +93,16 @@ const WalletTokensList = observer((props: Props) => {
{title} - {hasSearch && intl.formatMessage(messages.searchResults)} ( - {assets.length}) + {hasSearch && !noResults && ( + <> + {intl.formatMessage(messages.searchResults)} ( + {filteredAssets.length}) + + )}
- {filteredAssets.map((asset) => ( - - ))} + {content} {onViewAllButtonClick && ( )} diff --git a/source/renderer/app/components/wallet/tokens/WalletTokensList.scss b/source/renderer/app/components/wallet/tokens/WalletTokensList.scss new file mode 100644 index 0000000000..50d4f7ed4d --- /dev/null +++ b/source/renderer/app/components/wallet/tokens/WalletTokensList.scss @@ -0,0 +1,15 @@ +.component { + margin: 0 20px 20px; + &:last-of-type { + margin-bottom: 0; + } +} +.outerHeader { + margin: 0 10px 10px 20px; + .title { + color: var(--theme-tokens-list-header-text-color); + font-family: var(--font-regular); + font-size: 16px; + line-height: 22px; + } +} diff --git a/source/renderer/app/components/wallet/tokens/WalletTokensSearch.js b/source/renderer/app/components/wallet/tokens/WalletTokensSearch.js index 3eb318c479..a2ddbb5576 100644 --- a/source/renderer/app/components/wallet/tokens/WalletTokensSearch.js +++ b/source/renderer/app/components/wallet/tokens/WalletTokensSearch.js @@ -5,7 +5,7 @@ import classNames from 'classnames'; import { Input } from 'react-polymorph/lib/components/Input'; import SVGInline from 'react-svg-inline'; import { observer } from 'mobx-react'; -import styles from './WalletTokens.scss'; +import styles from './WalletTokensSearch.scss'; import searchIcon from '../../../assets/images/search.inline.svg'; import crossIcon from '../../../assets/images/close-cross.inline.svg'; @@ -24,11 +24,9 @@ type Props = { }; const WalletTokensSearch = observer((props: Props) => { const { searchValue, onSearch, intl } = props; - - console.log('!!searchValue.length', !!searchValue.length); return (
- {/* */} +
diff --git a/storybook/stories/wallets/tokens/WalletTokensList.stories.js b/storybook/stories/wallets/tokens/WalletTokensList.stories.js index 6e4d4f971f..12c76486de 100644 --- a/storybook/stories/wallets/tokens/WalletTokensList.stories.js +++ b/storybook/stories/wallets/tokens/WalletTokensList.stories.js @@ -160,7 +160,6 @@ storiesOf('Wallets|Tokens', module) ? action('onViewAllButtonClick') : null } - searchValue={text('searchValue', '')} title={text('Title', 'Tokens')} wallet={generateWallet('Wallet name', '45119903750165', walletTokens)} /> From 4ba5509c391fd4e33f3275214de4a5a4cf78c480 Mon Sep 17 00:00:00 2001 From: Danilo Prates Date: Wed, 15 Sep 2021 16:44:58 -0300 Subject: [PATCH 12/60] [DDW-694] Tokens List Header - progress --- .../wallet/tokens/WalletTokensList.js | 18 ++++++++++++++-- .../wallet/tokens/WalletTokensList.scss | 21 +++++++++++++++++++ source/renderer/app/i18n/locales/en-US.json | 6 ++++-- source/renderer/app/i18n/locales/ja-JP.json | 6 ++++-- 4 files changed, 45 insertions(+), 6 deletions(-) diff --git a/source/renderer/app/components/wallet/tokens/WalletTokensList.js b/source/renderer/app/components/wallet/tokens/WalletTokensList.js index b2197fe10e..56c414670f 100644 --- a/source/renderer/app/components/wallet/tokens/WalletTokensList.js +++ b/source/renderer/app/components/wallet/tokens/WalletTokensList.js @@ -13,15 +13,25 @@ import type { AssetToken } from '../../../api/assets/types'; const messages = defineMessages({ noResults: { - id: 'wallet.tokens.search.noResults', + id: 'wallet.tokens.list.search.noResults', defaultMessage: '!!!No results matching your query', description: 'No results on the WalletTokensList', }, searchResults: { - id: 'wallet.tokens.search.searchResults', + id: 'wallet.tokens.list.search.searchResults', defaultMessage: '!!!Search Results', description: 'Search Results on the WalletTokensList', }, + columnAmount: { + id: 'wallet.tokens.list.column.amount', + defaultMessage: '!!!Amount', + description: 'Amount header on Wallet summary assets page', + }, + columnToken: { + id: 'wallet.tokens.list.column.token', + defaultMessage: '!!!Token', + description: 'Token header on Wallet summary assets page', + }, }); type Props = { @@ -102,6 +112,10 @@ const WalletTokensList = observer((props: Props) => {
+
+ {intl.formatMessage(messages.columnToken)} + {intl.formatMessage(messages.columnAmount)} +
{content} {onViewAllButtonClick && ( diff --git a/source/renderer/app/components/wallet/tokens/WalletTokensList.scss b/source/renderer/app/components/wallet/tokens/WalletTokensList.scss index 50d4f7ed4d..cf653df7a6 100644 --- a/source/renderer/app/components/wallet/tokens/WalletTokensList.scss +++ b/source/renderer/app/components/wallet/tokens/WalletTokensList.scss @@ -13,3 +13,24 @@ line-height: 22px; } } +.columns { + display: flex; + justify-content: space-between; + margin: 0 42px 10px 12px; + span { + color: var(--theme-bordered-box-text-color); + font-family: var(--font-semibold); + font-size: 10px; + letter-spacing: 1px; + line-height: 2; + text-transform: uppercase; + } +} +.noResults { + color: var(--theme-bordered-box-text-color); + font-family: var(--font-regular); + font-size: 12px; + letter-spacing: 0.4px; + line-height: 1.33; + margin: 0 12px; +} diff --git a/source/renderer/app/i18n/locales/en-US.json b/source/renderer/app/i18n/locales/en-US.json index a27d73d78f..251dde0ff3 100755 --- a/source/renderer/app/i18n/locales/en-US.json +++ b/source/renderer/app/i18n/locales/en-US.json @@ -1118,11 +1118,13 @@ "wallet.summary.transactionsList.syncingTransactionsMessage": "Your transaction history for this wallet is being synced with the blockchain.", "wallet.summary.transactionsList.todayLabel": "Today", "wallet.summary.transactionsList.yesterdayLabel": "Yesterday", + "wallet.tokens.list.column.amount": "Amount", + "wallet.tokens.list.column.token": "Token", "wallet.tokens.list.favorites.title": "Favorites", + "wallet.tokens.list.search.noResults": "No results matching your query", + "wallet.tokens.list.search.searchResults": ". Search results", "wallet.tokens.list.tokens.title": "Tokens", "wallet.tokens.search.placeholder": "Search", - "wallet.tokens.search.searchResults": ". Search results", - "wallet.tokens.search.noResults": "No results matching your query", "wallet.transaction.address.from": "From address", "wallet.transaction.address.to": "To address", "wallet.transaction.addresses.from": "From addresses", diff --git a/source/renderer/app/i18n/locales/ja-JP.json b/source/renderer/app/i18n/locales/ja-JP.json index 890ec24bc1..d33f6a7044 100755 --- a/source/renderer/app/i18n/locales/ja-JP.json +++ b/source/renderer/app/i18n/locales/ja-JP.json @@ -1118,11 +1118,13 @@ "wallet.summary.transactionsList.syncingTransactionsMessage": "ウォレットのトランザクション履歴は現在ブロックチェーンと同期中です。", "wallet.summary.transactionsList.todayLabel": "今日", "wallet.summary.transactionsList.yesterdayLabel": "昨日", + "wallet.tokens.list.column.amount": "金額", + "wallet.tokens.list.column.token": "トークン", "wallet.tokens.list.favorites.title": "!!!Favorites", + "wallet.tokens.list.search.noResults": "該当する結果はありません", + "wallet.tokens.list.search.searchResults": "。検索結果", "wallet.tokens.list.tokens.title": "!!!Tokens", "wallet.tokens.search.placeholder": "!!!Search", - "wallet.tokens.search.searchResults": "。検索結果", - "wallet.tokens.search.noResults": "該当する結果はありません", "wallet.transaction.address.from": "送信元", "wallet.transaction.address.to": "送信先", "wallet.transaction.addresses.from": "送信元アドレス", From 4272867b9ae7ee5110a7a7781267c4b8a44ed444 Mon Sep 17 00:00:00 2001 From: Danilo Prates Date: Wed, 15 Sep 2021 17:58:15 -0300 Subject: [PATCH 13/60] [DDW-694] Tokens List Header - progress --- .../wallet/summary/WalletSummary.js | 1 + .../wallet/tokens/WalletTokens.scss | 2 +- .../wallet/tokens/WalletTokensList.js | 56 ++++++++++++++----- .../wallet/tokens/WalletTokensList.scss | 19 +++++++ .../components/widgets/forms/InlineSelect.js | 23 ++++++++ .../widgets/forms/InlineSelect.scss | 28 ++++++++++ 6 files changed, 115 insertions(+), 14 deletions(-) create mode 100644 source/renderer/app/components/widgets/forms/InlineSelect.js create mode 100644 source/renderer/app/components/widgets/forms/InlineSelect.scss diff --git a/source/renderer/app/components/wallet/summary/WalletSummary.js b/source/renderer/app/components/wallet/summary/WalletSummary.js index 49d4c7fb3c..1474041e71 100644 --- a/source/renderer/app/components/wallet/summary/WalletSummary.js +++ b/source/renderer/app/components/wallet/summary/WalletSummary.js @@ -97,6 +97,7 @@ export default class WalletSummary extends Component { currentLocale={currentLocale} title="Recently used tokens" onViewAllButtonClick={onViewAllButtonClick} + disableControls /> ) : ( { + const [isCollapsed, setIsCollapsed] = useState(false); const { assets, assetSettingsDialogWasOpened, - onViewAllButtonClick, + disableControls, intl, isLoadingAssets, onAssetSettings, onCopyAssetParam, onOpenAssetSend, + onViewAllButtonClick, searchValue = '', title, wallet, @@ -110,17 +115,42 @@ const WalletTokensList = observer((props: Props) => { )}
-
- -
- {intl.formatMessage(messages.columnToken)} - {intl.formatMessage(messages.columnAmount)} -
- {content} - {onViewAllButtonClick && ( - + {!disableControls && ( +
+ {!isCollapsed && ( +
+ sort by: + {}} + /> +
+ )} +
+ {isCollapsed ? ( + + ) : ( + + )} +
+
)} -
+
+ {!isCollapsed && ( + +
+ {intl.formatMessage(messages.columnToken)} + {intl.formatMessage(messages.columnAmount)} +
+ {content} + {onViewAllButtonClick && ( + + )} +
+ )} ); }); diff --git a/source/renderer/app/components/wallet/tokens/WalletTokensList.scss b/source/renderer/app/components/wallet/tokens/WalletTokensList.scss index cf653df7a6..a9521fd43c 100644 --- a/source/renderer/app/components/wallet/tokens/WalletTokensList.scss +++ b/source/renderer/app/components/wallet/tokens/WalletTokensList.scss @@ -6,12 +6,31 @@ } .outerHeader { margin: 0 10px 10px 20px; + display: flex; + justify-content: space-between; .title { color: var(--theme-tokens-list-header-text-color); font-family: var(--font-regular); font-size: 16px; line-height: 22px; } + + .controls { + display: flex; + .sort { + } + .sortBySelect .toggleVisibility { + button { + background-color: rgba(68, 91, 124, 0.1); + border-radius: 4px; + color: black; + font-family: var(--font-regular); + font-size: 17px; + height: 20px; + width: 20px; + } + } + } } .columns { display: flex; diff --git a/source/renderer/app/components/widgets/forms/InlineSelect.js b/source/renderer/app/components/widgets/forms/InlineSelect.js new file mode 100644 index 0000000000..8626db04aa --- /dev/null +++ b/source/renderer/app/components/widgets/forms/InlineSelect.js @@ -0,0 +1,23 @@ +// @flow +import React, { Component } from 'react'; +import { Select } from 'react-polymorph/lib/components/Select'; +import { SelectSkin } from 'react-polymorph/lib/skins/simple/SelectSkin'; +import { IDENTIFIERS } from 'react-polymorph/lib/themes/API'; +import styles from './InlineSelect.scss'; + +type Props = $Exact<{ value: string }>; + +export default class InlineSelect extends Component { + render() { + return ( +
+ -
- ); - } -} diff --git a/source/renderer/app/components/widgets/forms/InlineSelect.scss b/source/renderer/app/components/widgets/forms/InlineSelect.scss deleted file mode 100644 index 15d5e8633a..0000000000 --- a/source/renderer/app/components/widgets/forms/InlineSelect.scss +++ /dev/null @@ -1,28 +0,0 @@ -.component { - :global { - .SimpleSelect_selectInput { - input { - font-family: var(--font-regular); - font-size: 14px; - height: 33px; - line-height: 33px; - padding: 0 10px; - } - } - - .SimpleSelect_selectInput, - .SimpleSelect_isOpen .SimpleSelect_selectInput { - &::after { - bottom: 13px; - left: auto; - right: 10px; - } - } - - .SimpleOptions_option { - font-family: var(--font-regular); - font-size: 14px; - padding: 5.5px 10px; - } - } -} From e8f56857a3ab45a745e1314dee8554721d0b297e Mon Sep 17 00:00:00 2001 From: Danilo Prates Date: Thu, 16 Sep 2021 12:50:14 -0300 Subject: [PATCH 15/60] [DDW-694] Remove controls for the MVP scope --- .../wallet/tokens/WalletTokensList.js | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/source/renderer/app/components/wallet/tokens/WalletTokensList.js b/source/renderer/app/components/wallet/tokens/WalletTokensList.js index 12284dc3ad..f8e164d874 100644 --- a/source/renderer/app/components/wallet/tokens/WalletTokensList.js +++ b/source/renderer/app/components/wallet/tokens/WalletTokensList.js @@ -110,18 +110,16 @@ const WalletTokensList = observer((props: Props) => { )} - {!isCollapsed && ( - -
- {intl.formatMessage(messages.columnToken)} - {intl.formatMessage(messages.columnAmount)} -
- {content} - {onViewAllButtonClick && ( - - )} -
- )} + +
+ {intl.formatMessage(messages.columnToken)} + {intl.formatMessage(messages.columnAmount)} +
+ {content} + {onViewAllButtonClick && ( + + )} +
); }); From d157887303ed170c0726f648f0962aacc1bdf4a9 Mon Sep 17 00:00:00 2001 From: Danilo Prates Date: Thu, 16 Sep 2021 15:57:25 -0300 Subject: [PATCH 16/60] [DDW-694] Favorite - init --- .../app/assets/images/star-filled.inline.svg | 3 ++ .../assets/images/star-not-filled.inline.svg | 3 ++ .../components/wallet/tokens/WalletToken.js | 31 +++++++++++++++++-- .../components/wallet/tokens/WalletToken.scss | 27 +++++++++++++++- 4 files changed, 60 insertions(+), 4 deletions(-) create mode 100644 source/renderer/app/assets/images/star-filled.inline.svg create mode 100644 source/renderer/app/assets/images/star-not-filled.inline.svg diff --git a/source/renderer/app/assets/images/star-filled.inline.svg b/source/renderer/app/assets/images/star-filled.inline.svg new file mode 100644 index 0000000000..26c652a0c9 --- /dev/null +++ b/source/renderer/app/assets/images/star-filled.inline.svg @@ -0,0 +1,3 @@ + + + diff --git a/source/renderer/app/assets/images/star-not-filled.inline.svg b/source/renderer/app/assets/images/star-not-filled.inline.svg new file mode 100644 index 0000000000..bd79ad750c --- /dev/null +++ b/source/renderer/app/assets/images/star-not-filled.inline.svg @@ -0,0 +1,3 @@ + + + diff --git a/source/renderer/app/components/wallet/tokens/WalletToken.js b/source/renderer/app/components/wallet/tokens/WalletToken.js index 273839dc04..6937e93119 100644 --- a/source/renderer/app/components/wallet/tokens/WalletToken.js +++ b/source/renderer/app/components/wallet/tokens/WalletToken.js @@ -14,6 +14,8 @@ import AssetContent from '../../assets/AssetContent'; import type { AssetToken } from '../../../api/assets/types'; import arrow from '../../../assets/images/collapse-arrow-small.inline.svg'; import warningIcon from '../../../assets/images/asset-token-warning-ic.inline.svg'; +import starNotFilledIcon from '../../../assets/images/star-not-filled.inline.svg'; +import starFilledIcon from '../../../assets/images/star-filled.inline.svg'; const messages = defineMessages({ tokenSendButton: { @@ -54,6 +56,8 @@ type Props = { isLoading: boolean, assetSettingsDialogWasOpened: boolean, intl: intlShape.isRequired, + isFavorite: boolean, + onFavoriteToggle: Function, }; type IsExpanded = boolean; @@ -61,17 +65,27 @@ type IsExpanded = boolean; const WalletToken = observer((props: Props) => { const [isExpanded, setIsExpanded] = useState(false); + // TODO: Use props, when done + const [isFavorite, onFavoriteToggle] = useState(false); + const toggleIsExpanded = () => { setIsExpanded(!isExpanded); }; + const favoriteIconStyles = classNames([ + styles.favoriteIcon, + isFavorite ? styles.isFavorite : null, + ]); + const header = () => { const { - asset, - onCopyAssetParam, - isLoading, anyAssetWasHovered, + asset, assetSettingsDialogWasOpened, + // isFavorite, + isLoading, + onCopyAssetParam, + // onFavoriteToggle, } = props; const { decimals, recommendedDecimals } = asset; const arrowStyles = classNames(styles.arrow, { @@ -80,8 +94,19 @@ const WalletToken = observer((props: Props) => { const hasWarning = typeof recommendedDecimals === 'number' && decimals !== recommendedDecimals; + const starIcon = isFavorite ? starFilledIcon : starNotFilledIcon; return (
+ Date: Thu, 16 Sep 2021 17:39:32 -0300 Subject: [PATCH 17/60] [DDW-694] Favorites localstorage --- source/common/config/electron-store.config.js | 1 + source/common/types/electron-store.types.js | 1 + source/renderer/app/api/utils/localStorage.js | 20 +++++++++++++++++++ 3 files changed, 22 insertions(+) diff --git a/source/common/config/electron-store.config.js b/source/common/config/electron-store.config.js index ebd20cab1b..81cfc623e9 100644 --- a/source/common/config/electron-store.config.js +++ b/source/common/config/electron-store.config.js @@ -29,6 +29,7 @@ export const STORAGE_KEYS: { STAKING_INFO_WAS_OPEN: 'ALONZO-INFO-WAS-OPEN', TERMS_OF_USE_ACCEPTANCE: 'TERMS-OF-USE-ACCEPTANCE', THEME: 'THEME', + TOKEN_FAVORITES: 'TOKEN-FAVORITES', USER_DATE_FORMAT_ENGLISH: 'USER-DATE-FORMAT-ENGLISH', USER_DATE_FORMAT_JAPANESE: 'USER-DATE-FORMAT-JAPANESE', USER_LOCALE: 'USER-LOCALE', diff --git a/source/common/types/electron-store.types.js b/source/common/types/electron-store.types.js index 702823ac6e..6cfa89c19c 100644 --- a/source/common/types/electron-store.types.js +++ b/source/common/types/electron-store.types.js @@ -19,6 +19,7 @@ export type StorageKey = | 'SMASH-SERVER' | 'TERMS-OF-USE-ACCEPTANCE' | 'THEME' + | 'TOKEN-FAVORITES' | 'USER-DATE-FORMAT-ENGLISH' | 'USER-DATE-FORMAT-JAPANESE' | 'USER-LOCALE' diff --git a/source/renderer/app/api/utils/localStorage.js b/source/renderer/app/api/utils/localStorage.js index 04d3f1d126..df7a261f3b 100644 --- a/source/renderer/app/api/utils/localStorage.js +++ b/source/renderer/app/api/utils/localStorage.js @@ -327,6 +327,26 @@ export default class LocalStorageApi { unsetAppUpdateCompleted = (): Promise => LocalStorageApi.unset(keys.APP_UPDATE_COMPLETED); + getWalletTokenFavorites = (): Promise => + LocalStorageApi.get(keys.TOKEN_FAVORITES, {}); + + toggleWalletTokenFavorite = async (uniqueId: string): Promise => { + const favorites = await this.getWalletTokenFavorites(); + const isFavorite = !!favorites[uniqueId]; + const newFavorites = { + ...favorites, + [uniqueId]: !isFavorite, + }; + await LocalStorageApi.set(keys.TOKEN_FAVORITES, newFavorites); + return !isFavorite; + }; + + unsetWalletTokenFavorite = async (uniqueId: string): Promise => { + const favorites = await this.getWalletTokenFavorites(); + delete favorites[uniqueId]; + await LocalStorageApi.set(keys.TOKEN_FAVORITES, favorites); + }; + getAssetsLocalData = (): Promise => LocalStorageApi.get(keys.ASSET_DATA, []); From 3757cb2958da81571b921d13fb5e0c53c8133378 Mon Sep 17 00:00:00 2001 From: Danilo Prates Date: Fri, 17 Sep 2021 09:57:11 -0300 Subject: [PATCH 18/60] [DDW-694] Styling adjustments --- .../app/assets/images/star-not-filled.inline.svg | 2 +- .../app/components/wallet/tokens/WalletToken.scss | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/source/renderer/app/assets/images/star-not-filled.inline.svg b/source/renderer/app/assets/images/star-not-filled.inline.svg index bd79ad750c..e0a39906c0 100644 --- a/source/renderer/app/assets/images/star-not-filled.inline.svg +++ b/source/renderer/app/assets/images/star-not-filled.inline.svg @@ -1,3 +1,3 @@ - + diff --git a/source/renderer/app/components/wallet/tokens/WalletToken.scss b/source/renderer/app/components/wallet/tokens/WalletToken.scss index b2447e6bd4..26ba7d88d2 100644 --- a/source/renderer/app/components/wallet/tokens/WalletToken.scss +++ b/source/renderer/app/components/wallet/tokens/WalletToken.scss @@ -24,11 +24,13 @@ cursor: pointer; height: 22px; left: 8px; + opacity: 0.7; padding-top: 2px; position: absolute; top: 7px; width: 23px; z-index: 1; + transition: opacity 0.25s; svg { height: 14px; width: 15px; @@ -39,9 +41,11 @@ } } &:hover { - background-color: var( - --theme-widgets-asset-token-fingerprint-background-color - ); + opacity: 1; + + // background-color: var( + // --theme-widgets-asset-token-fingerprint-background-color + // ); } } .asset { From 308b7c1135392cbed9fd4350091973dc8d5169c2 Mon Sep 17 00:00:00 2001 From: Danilo Prates Date: Fri, 17 Sep 2021 10:00:06 -0300 Subject: [PATCH 19/60] [DDW-694] Styling adjustments --- .../renderer/app/assets/images/star-not-filled.inline.svg | 2 +- .../renderer/app/components/wallet/tokens/WalletToken.scss | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/source/renderer/app/assets/images/star-not-filled.inline.svg b/source/renderer/app/assets/images/star-not-filled.inline.svg index e0a39906c0..16c55647d5 100644 --- a/source/renderer/app/assets/images/star-not-filled.inline.svg +++ b/source/renderer/app/assets/images/star-not-filled.inline.svg @@ -1,3 +1,3 @@ - + diff --git a/source/renderer/app/components/wallet/tokens/WalletToken.scss b/source/renderer/app/components/wallet/tokens/WalletToken.scss index 26ba7d88d2..3cef611f45 100644 --- a/source/renderer/app/components/wallet/tokens/WalletToken.scss +++ b/source/renderer/app/components/wallet/tokens/WalletToken.scss @@ -24,7 +24,7 @@ cursor: pointer; height: 22px; left: 8px; - opacity: 0.7; + opacity: 0.5; padding-top: 2px; position: absolute; top: 7px; @@ -42,10 +42,6 @@ } &:hover { opacity: 1; - - // background-color: var( - // --theme-widgets-asset-token-fingerprint-background-color - // ); } } .asset { From eb6eb8a973c62f07e0067ea5c9a4fd50992ddb21 Mon Sep 17 00:00:00 2001 From: Danilo Prates Date: Fri, 17 Sep 2021 10:21:05 -0300 Subject: [PATCH 20/60] [DDW-694] Styling adjustments --- .../app/components/wallet/tokens/WalletToken.scss | 2 +- source/renderer/app/stores/AssetsStore.js | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/source/renderer/app/components/wallet/tokens/WalletToken.scss b/source/renderer/app/components/wallet/tokens/WalletToken.scss index 3cef611f45..a42c93b933 100644 --- a/source/renderer/app/components/wallet/tokens/WalletToken.scss +++ b/source/renderer/app/components/wallet/tokens/WalletToken.scss @@ -24,7 +24,7 @@ cursor: pointer; height: 22px; left: 8px; - opacity: 0.5; + opacity: 0.7; padding-top: 2px; position: absolute; top: 7px; diff --git a/source/renderer/app/stores/AssetsStore.js b/source/renderer/app/stores/AssetsStore.js index 6f2c594015..67d7f278c7 100644 --- a/source/renderer/app/stores/AssetsStore.js +++ b/source/renderer/app/stores/AssetsStore.js @@ -14,6 +14,11 @@ type WalletId = string; export default class AssetsStore extends Store { ASSETS_REFRESH_INTERVAL: number = 1 * 60 * 1000; // 1 minute | unit: milliseconds + // REQUESTS + @observable favoritesRequest: Request = new Request( + this.api.localStorage.getWalletTokenFavorites + ); + @observable activeAsset: ?string = null; @observable editingsAsset: ?AssetToken = null; @observable assetsRequests: { @@ -38,6 +43,8 @@ export default class AssetsStore extends Store { walletsActions.refreshWalletsDataSuccess.once(this._refreshAssetsData); walletsActions.setActiveAsset.listen(this._setActiveAsset); walletsActions.unsetActiveAsset.listen(this._unsetActiveAsset); + + this._setUpFavorites(); } // ==================== PUBLIC ================== @@ -68,8 +75,16 @@ export default class AssetsStore extends Store { return requestGetter(this.getAssetSettingsDialogWasOpenedRequest, false); } + @computed get favorites(): Object { + return this.favoritesRequest.result || {}; + } + // =================== PRIVATE ================== + _setUpFavorites = async () => { + this.favoritesRequest.execute(); + }; + @action _onAssetSettingsOpen = ({ asset }: { asset: AssetToken }) => { this.editingsAsset = asset; this.api.localStorage.setAssetSettingsDialogWasOpened(); From 97795af3554c5ad9eb1bb85ff397771e5b9a75c9 Mon Sep 17 00:00:00 2001 From: Danilo Prates Date: Fri, 17 Sep 2021 11:52:13 -0300 Subject: [PATCH 21/60] [DDW-694] Favorites working --- source/renderer/app/actions/assets-actions.js | 1 + .../wallet/summary/WalletSummary.js | 6 +++++ .../components/wallet/tokens/WalletToken.js | 15 +++++-------- .../components/wallet/tokens/WalletTokens.js | 22 ++++++++++++------- .../wallet/tokens/WalletTokensList.js | 6 +++++ .../containers/wallet/WalletSummaryPage.js | 6 +++-- .../app/containers/wallet/WalletTokensPage.js | 10 +++++++-- .../wallet/WalletTransactionsPage.js | 1 - .../WalletSendConfirmationDialogContainer.js | 1 - source/renderer/app/stores/AssetsStore.js | 6 +++++ .../wallets/summary/WalletSummary.stories.js | 2 ++ .../wallets/tokens/WalletTokens.stories.js | 22 ++++++++++++++----- .../tokens/WalletTokensList.stories.js | 21 +++++++++++++----- 13 files changed, 85 insertions(+), 34 deletions(-) diff --git a/source/renderer/app/actions/assets-actions.js b/source/renderer/app/actions/assets-actions.js index 221739fe08..e70d005086 100644 --- a/source/renderer/app/actions/assets-actions.js +++ b/source/renderer/app/actions/assets-actions.js @@ -13,6 +13,7 @@ export default class AssetsActions { onAssetSettingsCancel: Action = new Action(); onOpenAssetSend: Action<{ uniqueId: string }> = new Action(); onCopyAssetParam: Action<{ param: string, fullValue: string }> = new Action(); + onToggleFavorite: Action<{ uniqueId: string }> = new Action(); copyAssetParamNotification: Action<{ param: string, shortValue: string, diff --git a/source/renderer/app/components/wallet/summary/WalletSummary.js b/source/renderer/app/components/wallet/summary/WalletSummary.js index 1474041e71..fd5a117d3c 100644 --- a/source/renderer/app/components/wallet/summary/WalletSummary.js +++ b/source/renderer/app/components/wallet/summary/WalletSummary.js @@ -30,6 +30,8 @@ type Props = { assetSettingsDialogWasOpened: boolean, onExternalLinkClick: Function, onViewAllButtonClick: Function, + onToggleFavorite: Function, + tokenFavorites: Object, }; @observer @@ -56,6 +58,8 @@ export default class WalletSummary extends Component { isLoadingAssets, onExternalLinkClick, onViewAllButtonClick, + onToggleFavorite, + tokenFavorites, } = this.props; const { isRestoring } = wallet; @@ -97,6 +101,8 @@ export default class WalletSummary extends Component { currentLocale={currentLocale} title="Recently used tokens" onViewAllButtonClick={onViewAllButtonClick} + tokenFavorites={tokenFavorites} + onToggleFavorite={onToggleFavorite} disableControls /> ) : ( diff --git a/source/renderer/app/components/wallet/tokens/WalletToken.js b/source/renderer/app/components/wallet/tokens/WalletToken.js index 6937e93119..0c36afd2ac 100644 --- a/source/renderer/app/components/wallet/tokens/WalletToken.js +++ b/source/renderer/app/components/wallet/tokens/WalletToken.js @@ -57,7 +57,7 @@ type Props = { assetSettingsDialogWasOpened: boolean, intl: intlShape.isRequired, isFavorite: boolean, - onFavoriteToggle: Function, + onToggleFavorite: Function, }; type IsExpanded = boolean; @@ -65,16 +65,13 @@ type IsExpanded = boolean; const WalletToken = observer((props: Props) => { const [isExpanded, setIsExpanded] = useState(false); - // TODO: Use props, when done - const [isFavorite, onFavoriteToggle] = useState(false); - const toggleIsExpanded = () => { setIsExpanded(!isExpanded); }; const favoriteIconStyles = classNames([ styles.favoriteIcon, - isFavorite ? styles.isFavorite : null, + props.isFavorite ? styles.isFavorite : null, ]); const header = () => { @@ -82,12 +79,12 @@ const WalletToken = observer((props: Props) => { anyAssetWasHovered, asset, assetSettingsDialogWasOpened, - // isFavorite, + isFavorite, isLoading, onCopyAssetParam, - // onFavoriteToggle, + onToggleFavorite, } = props; - const { decimals, recommendedDecimals } = asset; + const { decimals, recommendedDecimals, uniqueId } = asset; const arrowStyles = classNames(styles.arrow, { [styles.isExpanded]: isExpanded, }); @@ -102,7 +99,7 @@ const WalletToken = observer((props: Props) => { onClick={(event) => { event.persist(); event.stopPropagation(); - onFavoriteToggle(!isFavorite); + onToggleFavorite({ uniqueId }); }} > diff --git a/source/renderer/app/components/wallet/tokens/WalletTokens.js b/source/renderer/app/components/wallet/tokens/WalletTokens.js index fb348f255b..6fb431fbc0 100644 --- a/source/renderer/app/components/wallet/tokens/WalletTokens.js +++ b/source/renderer/app/components/wallet/tokens/WalletTokens.js @@ -27,29 +27,35 @@ type Props = { assetSettingsDialogWasOpened: boolean, currentLocale: string, intl: intlShape.isRequired, + intl: intlShape.isRequired, isLoadingAssets: boolean, onAssetSettings: Function, onCopyAssetParam: Function, + onToggleFavorite: Function, onOpenAssetSend: Function, + tokenFavorites: Object, wallet: Wallet, - intl: intlShape.isRequired, }; type SearchValue = string; const WalletTokens = observer((props: Props) => { const [searchValue, setSearchValue] = useState(''); - const { assets, intl } = props; + const { assets, intl, tokenFavorites } = props; const listProps = { ...omit(props, 'assets', 'intl'), searchValue }; - const favoriteTokens = [...assets.slice(0, 1)]; + const favoriteTokensList = assets.filter( + ({ uniqueId }) => tokenFavorites[uniqueId] + ); return (
- + {!!favoriteTokensList.length && ( + + )} { @@ -61,6 +63,8 @@ const WalletTokensList = observer((props: Props) => { searchValue = '', title, wallet, + onToggleFavorite, + tokenFavorites, } = props; const isRestoreActive = wallet.isRestoring; const filteredAssets = searchAssets(searchValue, assets); @@ -93,6 +97,8 @@ const WalletTokensList = observer((props: Props) => { anyAssetWasHovered isLoading={isRestoreActive} assetSettingsDialogWasOpened={assetSettingsDialogWasOpened} + onToggleFavorite={onToggleFavorite} + isFavorite={tokenFavorites[asset.uniqueId]} /> )); } diff --git a/source/renderer/app/containers/wallet/WalletSummaryPage.js b/source/renderer/app/containers/wallet/WalletSummaryPage.js index 5981e46ebb..fbaa22737b 100755 --- a/source/renderer/app/containers/wallet/WalletSummaryPage.js +++ b/source/renderer/app/containers/wallet/WalletSummaryPage.js @@ -12,7 +12,6 @@ import { ROUTES } from '../../routes-config'; import { formattedWalletAmount } from '../../utils/formatters'; import { getNetworkExplorerUrlByType } from '../../utils/network'; import { WALLET_ASSETS_ENABLED } from '../../config/walletsConfig'; -import { ellipsis } from '../../utils/strings'; import { getAssetTokens } from '../../utils/assets'; import type { InjectedProps } from '../../types/injectedPropsType'; @@ -68,12 +67,13 @@ export default class WalletSummaryPage extends Component { assets, currency, } = stores; - const { getAsset, assetSettingsDialogWasOpened } = assets; + const { getAsset, assetSettingsDialogWasOpened, favorites } = assets; const { isInternalAddress } = addresses; const { onAssetSettingsOpen, onOpenAssetSend, onCopyAssetParam, + onToggleFavorite, } = actions.assets; const { openExternalLink, @@ -170,6 +170,8 @@ export default class WalletSummaryPage extends Component { onAssetSettings={onAssetSettingsOpen.trigger} onExternalLinkClick={app.openExternalLink} onViewAllButtonClick={onViewAllButtonClick} + tokenFavorites={favorites} + onToggleFavorite={onToggleFavorite.trigger} /> {walletTransactions} diff --git a/source/renderer/app/containers/wallet/WalletTokensPage.js b/source/renderer/app/containers/wallet/WalletTokensPage.js index 296f2afd25..4e25380023 100644 --- a/source/renderer/app/containers/wallet/WalletTokensPage.js +++ b/source/renderer/app/containers/wallet/WalletTokensPage.js @@ -14,8 +14,12 @@ const WalletTokensPage = inject( observer((props: Props) => { const { actions, stores } = props; const { assets, profile, wallets } = stores; - const { getAsset, assetSettingsDialogWasOpened } = assets; - const { onAssetSettingsOpen, onOpenAssetSend } = actions.assets; + const { getAsset, assetSettingsDialogWasOpened, favorites } = assets; + const { + onAssetSettingsOpen, + onOpenAssetSend, + onToggleFavorite, + } = actions.assets; const { active: activeWallet } = wallets; const { currentLocale } = profile; @@ -40,6 +44,8 @@ const WalletTokensPage = inject( onCopyAssetParam={() => {}} onOpenAssetSend={onOpenAssetSend.trigger} wallet={activeWallet} + tokenFavorites={favorites} + onToggleFavorite={onToggleFavorite.trigger} /> ); }) diff --git a/source/renderer/app/containers/wallet/WalletTransactionsPage.js b/source/renderer/app/containers/wallet/WalletTransactionsPage.js index 411266759c..7ee5930053 100755 --- a/source/renderer/app/containers/wallet/WalletTransactionsPage.js +++ b/source/renderer/app/containers/wallet/WalletTransactionsPage.js @@ -3,7 +3,6 @@ import React, { Component } from 'react'; import { observer, inject } from 'mobx-react'; import WalletTransactions from '../../components/wallet/transactions/WalletTransactions'; import { getNetworkExplorerUrlByType } from '../../utils/network'; -import { ellipsis } from '../../utils/strings'; import type { InjectedProps } from '../../types/injectedPropsType'; import { WALLET_ASSETS_ENABLED } from '../../config/walletsConfig'; diff --git a/source/renderer/app/containers/wallet/dialogs/WalletSendConfirmationDialogContainer.js b/source/renderer/app/containers/wallet/dialogs/WalletSendConfirmationDialogContainer.js index 78e3d87c13..031f2c23fb 100644 --- a/source/renderer/app/containers/wallet/dialogs/WalletSendConfirmationDialogContainer.js +++ b/source/renderer/app/containers/wallet/dialogs/WalletSendConfirmationDialogContainer.js @@ -2,7 +2,6 @@ import React, { Component } from 'react'; import { inject, observer } from 'mobx-react'; import type BigNumber from 'bignumber.js'; -import { ellipsis } from '../../../utils/strings'; import WalletSendConfirmationDialog from '../../../components/wallet/send-form/WalletSendConfirmationDialog'; import WalletSendAssetsConfirmationDialog from '../../../components/wallet/send-form/WalletSendAssetsConfirmationDialog'; import type { StoresMap } from '../../../stores/index'; diff --git a/source/renderer/app/stores/AssetsStore.js b/source/renderer/app/stores/AssetsStore.js index 67d7f278c7..a98dd24a39 100644 --- a/source/renderer/app/stores/AssetsStore.js +++ b/source/renderer/app/stores/AssetsStore.js @@ -39,6 +39,7 @@ export default class AssetsStore extends Store { assetsActions.onAssetSettingsCancel.listen(this._onAssetSettingsCancel); assetsActions.onOpenAssetSend.listen(this._onOpenAssetSend); assetsActions.onCopyAssetParam.listen(this._onCopyAssetParam); + assetsActions.onToggleFavorite.listen(this._onToggleFavorite); walletsActions.refreshWalletsDataSuccess.once(this._refreshAssetsData); walletsActions.setActiveAsset.listen(this._setActiveAsset); @@ -170,6 +171,11 @@ export default class AssetsStore extends Store { return this.assetsRequests[walletId]; }; + @action _onToggleFavorite = async ({ uniqueId }: { uniqueId: string }) => { + await this.api.localStorage.toggleWalletTokenFavorite(uniqueId); + this.favoritesRequest.execute(); + }; + _retrieveAssetsRequest = (walletId: string): Request => this.assetsRequests[walletId] || this._createWalletTokensRequest(walletId); } diff --git a/storybook/stories/wallets/summary/WalletSummary.stories.js b/storybook/stories/wallets/summary/WalletSummary.stories.js index bd6790778e..c5206c2a3d 100644 --- a/storybook/stories/wallets/summary/WalletSummary.stories.js +++ b/storybook/stories/wallets/summary/WalletSummary.stories.js @@ -230,6 +230,8 @@ storiesOf('Wallets|Summary', module) currencyIsActive={currencyIsActive} currencySelected={currencySelected} currencyRate={0.321} + onToggleFavorite={action('onToggleFavorite')} + tokenFavorites={{}} currencyLastFetched={currencyLastFetched} onCurrencySettingClick={action('onCurrencySettingClick')} assets={[ diff --git a/storybook/stories/wallets/tokens/WalletTokens.stories.js b/storybook/stories/wallets/tokens/WalletTokens.stories.js index 2588814860..92fc31f2d3 100644 --- a/storybook/stories/wallets/tokens/WalletTokens.stories.js +++ b/storybook/stories/wallets/tokens/WalletTokens.stories.js @@ -4,7 +4,7 @@ import { storiesOf } from '@storybook/react'; import { withKnobs, boolean, text } from '@storybook/addon-knobs'; import { action } from '@storybook/addon-actions'; import BigNumber from 'bignumber.js'; -import StoryDecorator from '../../_support/StoryDecorator'; +import { withState } from '@dump247/storybook-state'; import { generateAssetToken, @@ -147,18 +147,28 @@ storiesOf('Wallets|Tokens', module) .addDecorator(withKnobs) // ====== Stories ====== - .add('WalletTokens', ({ locale }: { locale: string }) => ( -
+ .add( + 'WalletTokens', + withState({ favorites: {} }, (store) => ( { + const { favorites } = store.state; + const newState = { + ...favorites, + [uniqueId]: !favorites[uniqueId], + }; + store.set({ favorites: newState }); + }} + tokenFavorites={store.state.favorites} /> -
- )); + )) + ); diff --git a/storybook/stories/wallets/tokens/WalletTokensList.stories.js b/storybook/stories/wallets/tokens/WalletTokensList.stories.js index 12c76486de..cb7b33eb9e 100644 --- a/storybook/stories/wallets/tokens/WalletTokensList.stories.js +++ b/storybook/stories/wallets/tokens/WalletTokensList.stories.js @@ -4,6 +4,7 @@ import { storiesOf } from '@storybook/react'; import { withKnobs, boolean, text } from '@storybook/addon-knobs'; import { action } from '@storybook/addon-actions'; import BigNumber from 'bignumber.js'; +import { withState } from '@dump247/storybook-state'; import StoryDecorator from '../../_support/StoryDecorator'; import { @@ -145,12 +146,13 @@ storiesOf('Wallets|Tokens', module) .addDecorator(withKnobs) // ====== Stories ====== - .add('WalletTokensList', ({ locale }: { locale: string }) => ( -
+ .add( + 'WalletTokensList', + withState({ favorites: {} }, (store) => ( { + const { favorites } = store.state; + const newState = { + ...favorites, + [uniqueId]: !favorites[uniqueId], + }; + store.set({ favorites: newState }); + }} + tokenFavorites={store.state.favorites} /> -
- )); + )) + ); From 54dcb37560aa5c69f7c47be30981284213de1a2b Mon Sep 17 00:00:00 2001 From: Danilo Prates Date: Fri, 17 Sep 2021 16:22:12 -0300 Subject: [PATCH 22/60] [DDW-694] Only recent tokens --- source/renderer/app/components/wallet/summary/WalletSummary.js | 3 ++- source/renderer/app/config/numbersConfig.js | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/source/renderer/app/components/wallet/summary/WalletSummary.js b/source/renderer/app/components/wallet/summary/WalletSummary.js index fd5a117d3c..fc8bca24bc 100644 --- a/source/renderer/app/components/wallet/summary/WalletSummary.js +++ b/source/renderer/app/components/wallet/summary/WalletSummary.js @@ -8,6 +8,7 @@ import WalletSummaryCurrency from './WalletSummaryCurrency'; import type { AssetToken } from '../../../api/assets/types'; import WalletSummaryNoTokens from './WalletSummaryNoTokens'; import WalletTokensList from '../tokens/WalletTokensList'; +import { MAX_TOKENS_ON_SUMMARY_PAGE } from '../../../config/numbersConfig'; type Props = { wallet: Wallet, @@ -92,7 +93,7 @@ export default class WalletSummary extends Component { {hasAssets ? ( Date: Mon, 20 Sep 2021 15:45:58 -0300 Subject: [PATCH 23/60] [DDW-694] Toggle favorite animation --- source/renderer/app/actions/assets-actions.js | 5 +- source/renderer/app/api/utils/localStorage.js | 11 ++- .../components/wallet/tokens/WalletToken.js | 18 ++-- .../components/wallet/tokens/WalletToken.scss | 28 +++++- .../components/wallet/tokens/WalletTokens.js | 16 +++- .../wallet/tokens/WalletTokensList.js | 52 +++++++---- source/renderer/app/config/timingConfig.js | 1 + .../app/containers/wallet/WalletTokensPage.js | 14 ++- source/renderer/app/stores/AssetsStore.js | 55 ++++++++++- .../wallets/tokens/WalletTokens.stories.js | 92 +++++++++++++------ 10 files changed, 226 insertions(+), 66 deletions(-) diff --git a/source/renderer/app/actions/assets-actions.js b/source/renderer/app/actions/assets-actions.js index e70d005086..3b8739db01 100644 --- a/source/renderer/app/actions/assets-actions.js +++ b/source/renderer/app/actions/assets-actions.js @@ -13,7 +13,10 @@ export default class AssetsActions { onAssetSettingsCancel: Action = new Action(); onOpenAssetSend: Action<{ uniqueId: string }> = new Action(); onCopyAssetParam: Action<{ param: string, fullValue: string }> = new Action(); - onToggleFavorite: Action<{ uniqueId: string }> = new Action(); + onToggleFavorite: Action<{ + uniqueId: string, + isFavorite: boolean, + }> = new Action(); copyAssetParamNotification: Action<{ param: string, shortValue: string, diff --git a/source/renderer/app/api/utils/localStorage.js b/source/renderer/app/api/utils/localStorage.js index df7a261f3b..de97be3915 100644 --- a/source/renderer/app/api/utils/localStorage.js +++ b/source/renderer/app/api/utils/localStorage.js @@ -330,12 +330,14 @@ export default class LocalStorageApi { getWalletTokenFavorites = (): Promise => LocalStorageApi.get(keys.TOKEN_FAVORITES, {}); - toggleWalletTokenFavorite = async (uniqueId: string): Promise => { + toggleWalletTokenFavorite = async ( + uniqueId: string, + isFavorite: boolean + ): Promise => { const favorites = await this.getWalletTokenFavorites(); - const isFavorite = !!favorites[uniqueId]; const newFavorites = { ...favorites, - [uniqueId]: !isFavorite, + [uniqueId]: isFavorite, }; await LocalStorageApi.set(keys.TOKEN_FAVORITES, newFavorites); return !isFavorite; @@ -347,6 +349,9 @@ export default class LocalStorageApi { await LocalStorageApi.set(keys.TOKEN_FAVORITES, favorites); }; + unsetWalletTokenFavorites = async (): Promise => + LocalStorageApi.unset(keys.TOKEN_FAVORITES); + getAssetsLocalData = (): Promise => LocalStorageApi.get(keys.ASSET_DATA, []); diff --git a/source/renderer/app/components/wallet/tokens/WalletToken.js b/source/renderer/app/components/wallet/tokens/WalletToken.js index 0c36afd2ac..d5e1615bb3 100644 --- a/source/renderer/app/components/wallet/tokens/WalletToken.js +++ b/source/renderer/app/components/wallet/tokens/WalletToken.js @@ -48,15 +48,17 @@ const messages = defineMessages({ }); type Props = { - asset: AssetToken, - onOpenAssetSend: Function, - onCopyAssetParam: Function, - onAssetSettings: Function, anyAssetWasHovered: boolean, - isLoading: boolean, + asset: AssetToken, assetSettingsDialogWasOpened: boolean, intl: intlShape.isRequired, isFavorite: boolean, + isInsertingAsset: boolean, + isLoading: boolean, + isRemovingAsset: boolean, + onAssetSettings: Function, + onCopyAssetParam: Function, + onOpenAssetSend: Function, onToggleFavorite: Function, }; @@ -99,7 +101,7 @@ const WalletToken = observer((props: Props) => { onClick={(event) => { event.persist(); event.stopPropagation(); - onToggleFavorite({ uniqueId }); + onToggleFavorite({ uniqueId, isFavorite }); }} > @@ -205,9 +207,11 @@ const WalletToken = observer((props: Props) => { ); }; - const { asset, onCopyAssetParam } = props; + const { asset, onCopyAssetParam, isInsertingAsset, isRemovingAsset } = props; const componentStyles = classNames(styles.component, { [styles.isExpanded]: isExpanded, + [styles.inserting]: isInsertingAsset, + [styles.removing]: isRemovingAsset, }); return (
diff --git a/source/renderer/app/components/wallet/tokens/WalletToken.scss b/source/renderer/app/components/wallet/tokens/WalletToken.scss index a42c93b933..68095c3308 100644 --- a/source/renderer/app/components/wallet/tokens/WalletToken.scss +++ b/source/renderer/app/components/wallet/tokens/WalletToken.scss @@ -1,8 +1,9 @@ .component { + overflow: hidden; &:not(:last-of-type) { border-bottom: 1px solid rgba(94, 96, 102, 0.15); } - &.isExpanded { + &.isExpanded:not(.removing) { background-color: var(--theme-button-flat-background-color-hover); padding-bottom: 20px; .header { @@ -12,7 +13,32 @@ display: block; } } + &.inserting { + animation: insertAnimation 0.2s; + } + &.removing { + animation: removingAnimation 0.2s; + border-bottom: 0 none; + height: 0; + } +} +@keyframes insertAnimation { + 0% { + height: 0; + } + 100% { + height: 36px; + } } +@keyframes removingAnimation { + 0% { + height: 36px; + } + 100% { + height: 0; + } +} + .header { cursor: pointer; display: flex; diff --git a/source/renderer/app/components/wallet/tokens/WalletTokens.js b/source/renderer/app/components/wallet/tokens/WalletTokens.js index 6fb431fbc0..54249267d8 100644 --- a/source/renderer/app/components/wallet/tokens/WalletTokens.js +++ b/source/renderer/app/components/wallet/tokens/WalletTokens.js @@ -26,21 +26,28 @@ type Props = { assets: Array, assetSettingsDialogWasOpened: boolean, currentLocale: string, + insertingAssetUniqueId: ?string, intl: intlShape.isRequired, intl: intlShape.isRequired, isLoadingAssets: boolean, onAssetSettings: Function, onCopyAssetParam: Function, - onToggleFavorite: Function, onOpenAssetSend: Function, + onToggleFavorite: Function, + removingAssetUniqueId: ?string, tokenFavorites: Object, wallet: Wallet, }; type SearchValue = string; const WalletTokens = observer((props: Props) => { const [searchValue, setSearchValue] = useState(''); - - const { assets, intl, tokenFavorites } = props; + const { + assets, + intl, + tokenFavorites, + insertingAssetUniqueId, + removingAssetUniqueId, + } = props; const listProps = { ...omit(props, 'assets', 'intl'), searchValue }; const favoriteTokensList = assets.filter( ({ uniqueId }) => tokenFavorites[uniqueId] @@ -53,6 +60,9 @@ const WalletTokens = observer((props: Props) => { )} diff --git a/source/renderer/app/components/wallet/tokens/WalletTokensList.js b/source/renderer/app/components/wallet/tokens/WalletTokensList.js index cfec9ba3ff..afe3bff5f3 100644 --- a/source/renderer/app/components/wallet/tokens/WalletTokensList.js +++ b/source/renderer/app/components/wallet/tokens/WalletTokensList.js @@ -37,34 +37,40 @@ type Props = { assets: Array, assetSettingsDialogWasOpened: boolean, currentLocale: string, - onViewAllButtonClick?: Function, + insertingAssetUniqueId: ?string, intl: intlShape.isRequired, + isFavoriteList?: boolean, isLoadingAssets: boolean, onAssetSettings: Function, onCopyAssetParam: Function, onOpenAssetSend: Function, + onToggleFavorite: Function, + onViewAllButtonClick?: Function, + removingAssetUniqueId: ?string, searchValue?: string, title: string, - wallet: Wallet, - onToggleFavorite: Function, tokenFavorites: Object, + wallet: Wallet, }; const WalletTokensList = observer((props: Props) => { const { assets, assetSettingsDialogWasOpened, + insertingAssetUniqueId, intl, + isFavoriteList, isLoadingAssets, onAssetSettings, onCopyAssetParam, onOpenAssetSend, + onToggleFavorite, onViewAllButtonClick, + removingAssetUniqueId, searchValue = '', title, - wallet, - onToggleFavorite, tokenFavorites, + wallet, } = props; const isRestoreActive = wallet.isRestoring; const filteredAssets = searchAssets(searchValue, assets); @@ -87,20 +93,28 @@ const WalletTokensList = observer((props: Props) => {

); } else { - content = filteredAssets.map((asset) => ( - - )); + content = filteredAssets.map((asset) => { + return ( + + ); + }); } return ( diff --git a/source/renderer/app/config/timingConfig.js b/source/renderer/app/config/timingConfig.js index ce242ee250..88a8dcf5cb 100644 --- a/source/renderer/app/config/timingConfig.js +++ b/source/renderer/app/config/timingConfig.js @@ -23,3 +23,4 @@ export const STAKE_POOL_ID_COPY_FEEDBACK = 3000; // 1.5 second | unit: milliseco export const ASSET_TOKEN_ID_COPY_FEEDBACK = 3 * 1000; // 3 seconds | unit: milliseconds export const ASSET_TOKEN_DISPLAY_DELAY = 250; // .25 second | unit: milliseconds export const DECENTRALIZATION_LEVEL_POLLING_INTERVAL = 1 * 1000; // 1 second | unit: milliseconds +export const TOGGLE_TOKEN_FAVORITE_TIMEOUT = 250; // .25 second | unit: milliseconds diff --git a/source/renderer/app/containers/wallet/WalletTokensPage.js b/source/renderer/app/containers/wallet/WalletTokensPage.js index 4e25380023..05b5e12245 100644 --- a/source/renderer/app/containers/wallet/WalletTokensPage.js +++ b/source/renderer/app/containers/wallet/WalletTokensPage.js @@ -14,7 +14,13 @@ const WalletTokensPage = inject( observer((props: Props) => { const { actions, stores } = props; const { assets, profile, wallets } = stores; - const { getAsset, assetSettingsDialogWasOpened, favorites } = assets; + const { + assetSettingsDialogWasOpened, + favorites, + getAsset, + insertingAssetUniqueId, + removingAssetUniqueId, + } = assets; const { onAssetSettingsOpen, onOpenAssetSend, @@ -39,13 +45,15 @@ const WalletTokensPage = inject( assets={assetTokens} assetSettingsDialogWasOpened={assetSettingsDialogWasOpened} currentLocale={currentLocale} + insertingAssetUniqueId={insertingAssetUniqueId} isLoadingAssets={isLoadingAssets} onAssetSettings={onAssetSettingsOpen.trigger} onCopyAssetParam={() => {}} onOpenAssetSend={onOpenAssetSend.trigger} - wallet={activeWallet} - tokenFavorites={favorites} onToggleFavorite={onToggleFavorite.trigger} + removingAssetUniqueId={removingAssetUniqueId} + tokenFavorites={favorites} + wallet={activeWallet} /> ); }) diff --git a/source/renderer/app/stores/AssetsStore.js b/source/renderer/app/stores/AssetsStore.js index a98dd24a39..dc9ae4429f 100644 --- a/source/renderer/app/stores/AssetsStore.js +++ b/source/renderer/app/stores/AssetsStore.js @@ -8,6 +8,7 @@ import { ROUTES } from '../routes-config'; import { requestGetter } from '../utils/storesUtils'; import { ellipsis } from '../utils/strings'; import type { GetAssetsResponse, AssetToken } from '../api/assets/types'; +import { TOGGLE_TOKEN_FAVORITE_TIMEOUT } from '../config/timingConfig'; type WalletId = string; @@ -24,6 +25,8 @@ export default class AssetsStore extends Store { @observable assetsRequests: { [key: WalletId]: Request, } = {}; + @observable insertingAssetUniqueId: ?string = null; + @observable removingAssetUniqueId: ?string = null; // REQUESTS @observable @@ -171,9 +174,55 @@ export default class AssetsStore extends Store { return this.assetsRequests[walletId]; }; - @action _onToggleFavorite = async ({ uniqueId }: { uniqueId: string }) => { - await this.api.localStorage.toggleWalletTokenFavorite(uniqueId); - this.favoritesRequest.execute(); + @action updateFavoriteLocalStorage = async ( + uniqueId: string, + isFavorite: boolean + ) => { + await this.api.localStorage.toggleWalletTokenFavorite(uniqueId, isFavorite); + await this.favoritesRequest.execute(); + }; + + @action clearFavoriteAction = () => { + this.insertingAssetUniqueId = null; + this.removingAssetUniqueId = null; + }; + + /** + * + * This function toggles a tokens favorite item + * It also adds for half a second the token id to + * either `removingAssetUniqueId` or `insertingAssetUniqueId` + * so the item can be animated. + * This is important, because the whole list shifts up or down. + * + */ + @action _onToggleFavorite = async ({ + uniqueId, + isFavorite, + }: { + uniqueId: string, + isFavorite: boolean, + }) => { + if (this.insertingAssetUniqueId || this.removingAssetUniqueId) { + return; + } + if (isFavorite) { + // It's removing favorite + // We need to wait for the element to be removed, before updating the favorites list + this.removingAssetUniqueId = uniqueId; + setTimeout(async () => { + await this.updateFavoriteLocalStorage(uniqueId, false); + this.clearFavoriteAction(); + }, TOGGLE_TOKEN_FAVORITE_TIMEOUT); + } else { + // It's inserting favorite + // We update the favorites list straight away + this.insertingAssetUniqueId = uniqueId; + await this.updateFavoriteLocalStorage(uniqueId, true); + setTimeout(() => { + this.clearFavoriteAction(); + }, TOGGLE_TOKEN_FAVORITE_TIMEOUT); + } }; _retrieveAssetsRequest = (walletId: string): Request => diff --git a/storybook/stories/wallets/tokens/WalletTokens.stories.js b/storybook/stories/wallets/tokens/WalletTokens.stories.js index 92fc31f2d3..93eb3479a8 100644 --- a/storybook/stories/wallets/tokens/WalletTokens.stories.js +++ b/storybook/stories/wallets/tokens/WalletTokens.stories.js @@ -6,18 +6,17 @@ import { action } from '@storybook/addon-actions'; import BigNumber from 'bignumber.js'; import { withState } from '@dump247/storybook-state'; +// Helpers and config import { generateAssetToken, generateWallet, generateHash, } from '../../_support/utils'; - -import type { WalletTokens } from '../../../../source/renderer/app/api/assets/types'; - +import { TOGGLE_TOKEN_FAVORITE_TIMEOUT } from '../../../../source/renderer/app/config/timingConfig'; import WalletsWrapper from '../_utils/WalletsWrapper'; // Screens -import WalletTokensScreen from '../../../../source/renderer/app/components/wallet/tokens/WalletTokens'; +import WalletTokens from '../../../../source/renderer/app/components/wallet/tokens/WalletTokens'; const assets = [ generateAssetToken( @@ -79,7 +78,7 @@ const assets = [ ), ]; -const walletTokens: WalletTokens = { +const walletTokens = { available: [ { id: generateHash(), @@ -149,26 +148,67 @@ storiesOf('Wallets|Tokens', module) // ====== Stories ====== .add( 'WalletTokens', - withState({ favorites: {} }, (store) => ( - { - const { favorites } = store.state; - const newState = { - ...favorites, - [uniqueId]: !favorites[uniqueId], + withState( + { + favorites: {}, + insertingAssetUniqueId: null, + removingAssetUniqueId: null, + }, + (store) => { + const onToggleFavorite = async ({ uniqueId }: { uniqueId: string }) => { + const { favorites: currentFavorite } = store.state; + let { insertingAssetUniqueId, removingAssetUniqueId } = store.state; + if (insertingAssetUniqueId || removingAssetUniqueId) return; + const isFavorite = !currentFavorite[uniqueId]; + const favorites = { + ...currentFavorite, + [uniqueId]: isFavorite, }; - store.set({ favorites: newState }); - }} - tokenFavorites={store.state.favorites} - /> - )) + if (!isFavorite) { + removingAssetUniqueId = uniqueId; + store.set({ + removingAssetUniqueId, + }); + setTimeout(async () => { + store.set({ + favorites, + removingAssetUniqueId: null, + }); + }, TOGGLE_TOKEN_FAVORITE_TIMEOUT); + } else { + insertingAssetUniqueId = uniqueId; + store.set({ + favorites, + insertingAssetUniqueId, + }); + setTimeout(() => { + store.set({ + insertingAssetUniqueId: null, + }); + }, TOGGLE_TOKEN_FAVORITE_TIMEOUT); + } + }; + return ( + + ); + } + ) ); From c146ba71cbb7a3366ab48e91d5f229e93d95e6d4 Mon Sep 17 00:00:00 2001 From: Danilo Prates Date: Mon, 20 Sep 2021 16:43:14 -0300 Subject: [PATCH 24/60] [DDW-694] Show Zero Tokens - init --- source/renderer/app/api/assets/types.js | 1 + .../transactions/WalletTransactionsList.js | 4 +- .../app/containers/wallet/WalletSendPage.js | 4 +- .../containers/wallet/WalletSummaryPage.js | 4 +- .../app/containers/wallet/WalletTokensPage.js | 4 +- .../WalletSendConfirmationDialogContainer.js | 4 +- source/renderer/app/utils/assets.js | 68 ++++++++++++++++++- source/renderer/app/utils/formatters.js | 2 + 8 files changed, 78 insertions(+), 13 deletions(-) diff --git a/source/renderer/app/api/assets/types.js b/source/renderer/app/api/assets/types.js index 2a8461f6cc..9bea8cff68 100644 --- a/source/renderer/app/api/assets/types.js +++ b/source/renderer/app/api/assets/types.js @@ -30,6 +30,7 @@ export type Asset = { recommendedDecimals: ?number, uniqueId: string, }; +export type Assets = Array; /** * diff --git a/source/renderer/app/components/wallet/transactions/WalletTransactionsList.js b/source/renderer/app/components/wallet/transactions/WalletTransactionsList.js index da677ebe4a..7ae231b5fd 100644 --- a/source/renderer/app/components/wallet/transactions/WalletTransactionsList.js +++ b/source/renderer/app/components/wallet/transactions/WalletTransactionsList.js @@ -15,7 +15,7 @@ import { VirtualTransactionList } from './render-strategies/VirtualTransactionLi import { SimpleTransactionList } from './render-strategies/SimpleTransactionList'; import { TransactionInfo, TransactionsGroup } from './types'; import type { Row } from './types'; -import { getAssetTokens } from '../../../utils/assets'; +import { getNonZeroAssetTokens } from '../../../utils/assets'; const messages = defineMessages({ today: { @@ -231,7 +231,7 @@ export default class WalletTransactionsList extends Component { ]); const txTokens = tx.assets; - const assetTokens = getAssetTokens(txTokens, getAsset); + const assetTokens = getNonZeroAssetTokens(txTokens, getAsset); const totalRawAssets = tx.assets.length; const totalAssets = assetTokens.length; const hasRawAssets = tx.assets.length > 0; diff --git a/source/renderer/app/containers/wallet/WalletSendPage.js b/source/renderer/app/containers/wallet/WalletSendPage.js index 649a429eed..ffcad51dc4 100755 --- a/source/renderer/app/containers/wallet/WalletSendPage.js +++ b/source/renderer/app/containers/wallet/WalletSendPage.js @@ -10,7 +10,7 @@ import WalletSendForm from '../../components/wallet/WalletSendForm'; import { WALLET_ASSETS_ENABLED } from '../../config/walletsConfig'; import Asset from '../../domains/Asset'; import type { ApiTokens } from '../../api/assets/types'; -import { getAssetTokens } from '../../utils/assets'; +import { getNonZeroAssetTokens } from '../../utils/assets'; type Props = InjectedProps; @@ -106,7 +106,7 @@ export default class WalletSendPage extends Component { const { isHardwareWallet } = wallet; const walletTokens = wallet.assets.total; - const assetTokens = getAssetTokens(walletTokens, getAsset); + const assetTokens = getNonZeroAssetTokens(walletTokens, getAsset); const totalRawAssets = wallet.assets.total.length; const totalAssets = assetTokens.length; const hasRawAssets = wallet.assets.total.length > 0; diff --git a/source/renderer/app/containers/wallet/WalletSummaryPage.js b/source/renderer/app/containers/wallet/WalletSummaryPage.js index fbaa22737b..2b73722516 100755 --- a/source/renderer/app/containers/wallet/WalletSummaryPage.js +++ b/source/renderer/app/containers/wallet/WalletSummaryPage.js @@ -67,7 +67,7 @@ export default class WalletSummaryPage extends Component { assets, currency, } = stores; - const { getAsset, assetSettingsDialogWasOpened, favorites } = assets; + const { all, getAsset, assetSettingsDialogWasOpened, favorites } = assets; const { isInternalAddress } = addresses; const { onAssetSettingsOpen, @@ -100,7 +100,7 @@ export default class WalletSummaryPage extends Component { const noTransactionsLabel = intl.formatMessage(messages.noTransactions); const walletTokens = wallet.assets.total; - const assetTokens = getAssetTokens(walletTokens, getAsset); + const assetTokens = getAssetTokens(all, walletTokens); const totalRawAssets = wallet.assets.total.length; const totalAssets = assetTokens.length; const hasRawAssets = wallet.assets.total.length > 0; diff --git a/source/renderer/app/containers/wallet/WalletTokensPage.js b/source/renderer/app/containers/wallet/WalletTokensPage.js index 05b5e12245..8061f8e8e1 100644 --- a/source/renderer/app/containers/wallet/WalletTokensPage.js +++ b/source/renderer/app/containers/wallet/WalletTokensPage.js @@ -15,9 +15,9 @@ const WalletTokensPage = inject( const { actions, stores } = props; const { assets, profile, wallets } = stores; const { + all, assetSettingsDialogWasOpened, favorites, - getAsset, insertingAssetUniqueId, removingAssetUniqueId, } = assets; @@ -34,7 +34,7 @@ const WalletTokensPage = inject( throw new Error('Active wallet required for WalletSummaryPage.'); const walletTokens = activeWallet.assets.total; - const assetTokens = getAssetTokens(walletTokens, getAsset); + const assetTokens = getAssetTokens(all, walletTokens); const totalRawAssets = activeWallet.assets.total.length; const totalAssets = assetTokens.length; const hasRawAssets = activeWallet.assets.total.length > 0; diff --git a/source/renderer/app/containers/wallet/dialogs/WalletSendConfirmationDialogContainer.js b/source/renderer/app/containers/wallet/dialogs/WalletSendConfirmationDialogContainer.js index 031f2c23fb..cec9a81f01 100644 --- a/source/renderer/app/containers/wallet/dialogs/WalletSendConfirmationDialogContainer.js +++ b/source/renderer/app/containers/wallet/dialogs/WalletSendConfirmationDialogContainer.js @@ -8,7 +8,7 @@ import type { StoresMap } from '../../../stores/index'; import type { ActionsMap } from '../../../actions/index'; import type { HwDeviceStatus } from '../../../domains/Wallet'; import type { AssetToken } from '../../../api/assets/types'; -import { getAssetTokens } from '../../../utils/assets'; +import { getNonZeroAssetTokens } from '../../../utils/assets'; type Props = { stores: any | StoresMap, @@ -94,7 +94,7 @@ export default class WalletSendConfirmationDialogContainer extends Component ({ + policyId, + assetName, + uniqueId, + quantity: new BigNumber(0), +}); + +export const getToken = (asset: Asset, tokens: Tokens) => { + let token = tokens.find(({ uniqueId }) => uniqueId === asset.uniqueId); + if (!token) { + token = getZeroToken(asset); + } + return token; +}; + /** * * This function receives a Token (the asset included in a wallet or transaction) @@ -34,7 +54,49 @@ export const filterAssets = ( * Data from the Token: policyId, assetName, quantity, address * Data from the Asset: fingerprint, metadata, decimals, recommendedDecimals, uniqueId */ -export const getAssetToken = (asset: Token, getAsset: Function): AssetToken => { +export const getAssetToken = ( + { fingerprint, metadata, decimals, recommendedDecimals, uniqueId }: Asset, + { policyId, assetName, quantity, address }: Token +): AssetToken => ({ + policyId, + assetName, + quantity, + address, + fingerprint, + metadata, + decimals, + recommendedDecimals, + uniqueId, +}); + +/** + * + * This function receives a list of Assets + * then retrieves the Token from that specific wallet + * and sort them accordingly + * + */ +export const getAssetTokens = ( + assets: Array, + tokens: Tokens +): Array => + assets + .map((asset) => getAssetToken(asset, getToken(asset, tokens))) + .filter((token) => !!token.uniqueId) + .sort(sortAssets); + +/** + * + * This function receives a Token (the asset included in a wallet or transaction) + * and combines with the data from the Asset + * + * Data from the Token: policyId, assetName, quantity, address + * Data from the Asset: fingerprint, metadata, decimals, recommendedDecimals, uniqueId + */ +export const getNonZeroAssetToken = ( + asset: Token, + getAsset: Function +): AssetToken => { const { policyId, assetName, quantity, address } = asset; const { fingerprint, metadata, decimals, recommendedDecimals, uniqueId } = getAsset(policyId, assetName) || {}; @@ -58,12 +120,12 @@ export const getAssetToken = (asset: Token, getAsset: Function): AssetToken => { * and sort them accordingly * */ -export const getAssetTokens = ( +export const getNonZeroAssetTokens = ( tokens: Tokens, getAsset: Function ): Array => tokens - .map((token) => getAssetToken(token, getAsset)) + .map((token) => getNonZeroAssetToken(token, getAsset)) .filter((token) => !!token.uniqueId) .sort(sortAssets); diff --git a/source/renderer/app/utils/formatters.js b/source/renderer/app/utils/formatters.js index 2870547694..ed49080155 100644 --- a/source/renderer/app/utils/formatters.js +++ b/source/renderer/app/utils/formatters.js @@ -62,6 +62,8 @@ export const formattedTokenWalletAmount = ( * E.G.: 1,000,000 prints '1M' */ formattedAmount = shortNumber(formattedAmount); + } else if (formattedAmount.isZero()) { + return '0'; } else if (formattedAmount.isLessThan(0.01)) { /* * Short formatting for < 0.01 From 01a2ff93283691fb82659311e82639c242f7b1db Mon Sep 17 00:00:00 2001 From: Danilo Prates Date: Tue, 21 Sep 2021 10:15:20 -0300 Subject: [PATCH 25/60] [DDW-694] Move animation to the specific component using it --- .../components/wallet/tokens/WalletTokens.js | 55 ++++++++++++++++--- source/renderer/app/stores/AssetsStore.js | 45 +-------------- 2 files changed, 48 insertions(+), 52 deletions(-) diff --git a/source/renderer/app/components/wallet/tokens/WalletTokens.js b/source/renderer/app/components/wallet/tokens/WalletTokens.js index 54249267d8..fc07927583 100644 --- a/source/renderer/app/components/wallet/tokens/WalletTokens.js +++ b/source/renderer/app/components/wallet/tokens/WalletTokens.js @@ -1,13 +1,13 @@ // @flow import React, { useState } from 'react'; import { intlShape, injectIntl, defineMessages } from 'react-intl'; -import { omit } from 'lodash'; import { observer } from 'mobx-react'; import styles from './WalletTokens.scss'; import Wallet from '../../../domains/Wallet'; import WalletTokensList from './WalletTokensList'; import WalletTokensSearch from './WalletTokensSearch'; import type { AssetToken } from '../../../api/assets/types'; +import { TOGGLE_TOKEN_FAVORITE_TIMEOUT } from '../../../config/timingConfig'; const messages = defineMessages({ favoritesListTitle: { @@ -26,50 +26,87 @@ type Props = { assets: Array, assetSettingsDialogWasOpened: boolean, currentLocale: string, - insertingAssetUniqueId: ?string, - intl: intlShape.isRequired, intl: intlShape.isRequired, isLoadingAssets: boolean, onAssetSettings: Function, onCopyAssetParam: Function, onOpenAssetSend: Function, onToggleFavorite: Function, - removingAssetUniqueId: ?string, tokenFavorites: Object, wallet: Wallet, }; + type SearchValue = string; const WalletTokens = observer((props: Props) => { const [searchValue, setSearchValue] = useState(''); + const [insertingAssetUniqueId, setInsertingAssetUniqueId] = useState( + null + ); + const [removingAssetUniqueId, setRemovingAssetUniqueId] = useState( + null + ); + const { assets, intl, tokenFavorites, - insertingAssetUniqueId, - removingAssetUniqueId, + onToggleFavorite, + ...listProps } = props; - const listProps = { ...omit(props, 'assets', 'intl'), searchValue }; const favoriteTokensList = assets.filter( ({ uniqueId }) => tokenFavorites[uniqueId] ); + const handleToggleFavorite = async ({ + uniqueId, + isFavorite, + }: { + uniqueId: string, + isFavorite: boolean, + }) => { + if (insertingAssetUniqueId || removingAssetUniqueId) { + return; + } + if (isFavorite) { + // It's removing favorite + // We need to wait for the element to be removed, before updating the favorites list + setRemovingAssetUniqueId(uniqueId); + setTimeout(async () => { + await onToggleFavorite({ uniqueId, isFavorite: false }); + setRemovingAssetUniqueId(null); + }, TOGGLE_TOKEN_FAVORITE_TIMEOUT); + } else { + // It's inserting favorite + // We update the favorites list straight away + setInsertingAssetUniqueId(uniqueId); + await onToggleFavorite({ uniqueId, isFavorite: true }); + setTimeout(() => { + setInsertingAssetUniqueId(null); + }, TOGGLE_TOKEN_FAVORITE_TIMEOUT); + } + }; + return (
{!!favoriteTokensList.length && ( )}
); diff --git a/source/renderer/app/stores/AssetsStore.js b/source/renderer/app/stores/AssetsStore.js index dc9ae4429f..e7ee4813b5 100644 --- a/source/renderer/app/stores/AssetsStore.js +++ b/source/renderer/app/stores/AssetsStore.js @@ -8,7 +8,6 @@ import { ROUTES } from '../routes-config'; import { requestGetter } from '../utils/storesUtils'; import { ellipsis } from '../utils/strings'; import type { GetAssetsResponse, AssetToken } from '../api/assets/types'; -import { TOGGLE_TOKEN_FAVORITE_TIMEOUT } from '../config/timingConfig'; type WalletId = string; @@ -174,28 +173,6 @@ export default class AssetsStore extends Store { return this.assetsRequests[walletId]; }; - @action updateFavoriteLocalStorage = async ( - uniqueId: string, - isFavorite: boolean - ) => { - await this.api.localStorage.toggleWalletTokenFavorite(uniqueId, isFavorite); - await this.favoritesRequest.execute(); - }; - - @action clearFavoriteAction = () => { - this.insertingAssetUniqueId = null; - this.removingAssetUniqueId = null; - }; - - /** - * - * This function toggles a tokens favorite item - * It also adds for half a second the token id to - * either `removingAssetUniqueId` or `insertingAssetUniqueId` - * so the item can be animated. - * This is important, because the whole list shifts up or down. - * - */ @action _onToggleFavorite = async ({ uniqueId, isFavorite, @@ -203,26 +180,8 @@ export default class AssetsStore extends Store { uniqueId: string, isFavorite: boolean, }) => { - if (this.insertingAssetUniqueId || this.removingAssetUniqueId) { - return; - } - if (isFavorite) { - // It's removing favorite - // We need to wait for the element to be removed, before updating the favorites list - this.removingAssetUniqueId = uniqueId; - setTimeout(async () => { - await this.updateFavoriteLocalStorage(uniqueId, false); - this.clearFavoriteAction(); - }, TOGGLE_TOKEN_FAVORITE_TIMEOUT); - } else { - // It's inserting favorite - // We update the favorites list straight away - this.insertingAssetUniqueId = uniqueId; - await this.updateFavoriteLocalStorage(uniqueId, true); - setTimeout(() => { - this.clearFavoriteAction(); - }, TOGGLE_TOKEN_FAVORITE_TIMEOUT); - } + await this.api.localStorage.toggleWalletTokenFavorite(uniqueId, isFavorite); + await this.favoritesRequest.execute(); }; _retrieveAssetsRequest = (walletId: string): Request => From c66d303a14234ab4bc74e21f3584a5253df79375 Mon Sep 17 00:00:00 2001 From: Danilo Prates Date: Tue, 21 Sep 2021 10:23:07 -0300 Subject: [PATCH 26/60] [DDW-694] Move animation to the specific component using it --- .../components/wallet/tokens/WalletTokens.js | 9 +- .../wallet/tokens/WalletTokensList.js | 10 +-- source/renderer/app/config/timingConfig.js | 2 +- .../wallets/tokens/WalletTokens.stories.js | 84 +++++-------------- 4 files changed, 32 insertions(+), 73 deletions(-) diff --git a/source/renderer/app/components/wallet/tokens/WalletTokens.js b/source/renderer/app/components/wallet/tokens/WalletTokens.js index fc07927583..58463540e6 100644 --- a/source/renderer/app/components/wallet/tokens/WalletTokens.js +++ b/source/renderer/app/components/wallet/tokens/WalletTokens.js @@ -57,6 +57,14 @@ const WalletTokens = observer((props: Props) => { ({ uniqueId }) => tokenFavorites[uniqueId] ); + /** + * + * This function adds a `inserting` or `removing` + * state before actually proceding with these actions + * so the UI element insertion/removal can be animated, + * preventing undesirable jumps in the tokens list + * + */ const handleToggleFavorite = async ({ uniqueId, isFavorite, @@ -98,7 +106,6 @@ const WalletTokens = observer((props: Props) => { removingAssetUniqueId={removingAssetUniqueId} onToggleFavorite={handleToggleFavorite} tokenFavorites={tokenFavorites} - isFavoriteList /> )} { assetSettingsDialogWasOpened, insertingAssetUniqueId, intl, - isFavoriteList, isLoadingAssets, onAssetSettings, onCopyAssetParam, @@ -106,12 +104,8 @@ const WalletTokensList = observer((props: Props) => { assetSettingsDialogWasOpened={assetSettingsDialogWasOpened} onToggleFavorite={onToggleFavorite} isFavorite={tokenFavorites[asset.uniqueId]} - isInsertingAsset={ - isFavoriteList && insertingAssetUniqueId === asset.uniqueId - } - isRemovingAsset={ - isFavoriteList && removingAssetUniqueId === asset.uniqueId - } + isInsertingAsset={insertingAssetUniqueId === asset.uniqueId} + isRemovingAsset={removingAssetUniqueId === asset.uniqueId} /> ); }); diff --git a/source/renderer/app/config/timingConfig.js b/source/renderer/app/config/timingConfig.js index 88a8dcf5cb..00cf53f979 100644 --- a/source/renderer/app/config/timingConfig.js +++ b/source/renderer/app/config/timingConfig.js @@ -23,4 +23,4 @@ export const STAKE_POOL_ID_COPY_FEEDBACK = 3000; // 1.5 second | unit: milliseco export const ASSET_TOKEN_ID_COPY_FEEDBACK = 3 * 1000; // 3 seconds | unit: milliseconds export const ASSET_TOKEN_DISPLAY_DELAY = 250; // .25 second | unit: milliseconds export const DECENTRALIZATION_LEVEL_POLLING_INTERVAL = 1 * 1000; // 1 second | unit: milliseconds -export const TOGGLE_TOKEN_FAVORITE_TIMEOUT = 250; // .25 second | unit: milliseconds +export const TOGGLE_TOKEN_FAVORITE_TIMEOUT = 300; // .3 second | unit: milliseconds diff --git a/storybook/stories/wallets/tokens/WalletTokens.stories.js b/storybook/stories/wallets/tokens/WalletTokens.stories.js index 93eb3479a8..f5d76c343c 100644 --- a/storybook/stories/wallets/tokens/WalletTokens.stories.js +++ b/storybook/stories/wallets/tokens/WalletTokens.stories.js @@ -12,7 +12,6 @@ import { generateWallet, generateHash, } from '../../_support/utils'; -import { TOGGLE_TOKEN_FAVORITE_TIMEOUT } from '../../../../source/renderer/app/config/timingConfig'; import WalletsWrapper from '../_utils/WalletsWrapper'; // Screens @@ -148,67 +147,26 @@ storiesOf('Wallets|Tokens', module) // ====== Stories ====== .add( 'WalletTokens', - withState( - { - favorites: {}, - insertingAssetUniqueId: null, - removingAssetUniqueId: null, - }, - (store) => { - const onToggleFavorite = async ({ uniqueId }: { uniqueId: string }) => { - const { favorites: currentFavorite } = store.state; - let { insertingAssetUniqueId, removingAssetUniqueId } = store.state; - if (insertingAssetUniqueId || removingAssetUniqueId) return; - const isFavorite = !currentFavorite[uniqueId]; - const favorites = { - ...currentFavorite, - [uniqueId]: isFavorite, + withState({ favorites: {} }, (store) => ( + { + const { favorites } = store.state; + const newState = { + ...favorites, + [uniqueId]: !favorites[uniqueId], }; - if (!isFavorite) { - removingAssetUniqueId = uniqueId; - store.set({ - removingAssetUniqueId, - }); - setTimeout(async () => { - store.set({ - favorites, - removingAssetUniqueId: null, - }); - }, TOGGLE_TOKEN_FAVORITE_TIMEOUT); - } else { - insertingAssetUniqueId = uniqueId; - store.set({ - favorites, - insertingAssetUniqueId, - }); - setTimeout(() => { - store.set({ - insertingAssetUniqueId: null, - }); - }, TOGGLE_TOKEN_FAVORITE_TIMEOUT); - } - }; - return ( - - ); - } - ) + store.set({ favorites: newState }); + }} + tokenFavorites={store.state.favorites} + /> + )) ); From bb526d35ec1a542bf85bf3cba34dcedfae28d6ab Mon Sep 17 00:00:00 2001 From: Danilo Prates Date: Tue, 21 Sep 2021 11:14:06 -0300 Subject: [PATCH 27/60] [DDW-694] View all tokens button --- .../components/wallet/tokens/WalletTokens.js | 4 ++-- .../wallet/tokens/WalletTokensList.js | 19 +++++++++++++++---- .../wallet/tokens/WalletTokensList.scss | 10 ++++++++++ source/renderer/app/i18n/locales/en-US.json | 1 + source/renderer/app/i18n/locales/ja-JP.json | 1 + source/renderer/app/stores/AssetsStore.js | 5 ++++- 6 files changed, 33 insertions(+), 7 deletions(-) diff --git a/source/renderer/app/components/wallet/tokens/WalletTokens.js b/source/renderer/app/components/wallet/tokens/WalletTokens.js index 58463540e6..c49c95f832 100644 --- a/source/renderer/app/components/wallet/tokens/WalletTokens.js +++ b/source/renderer/app/components/wallet/tokens/WalletTokens.js @@ -80,14 +80,14 @@ const WalletTokens = observer((props: Props) => { // We need to wait for the element to be removed, before updating the favorites list setRemovingAssetUniqueId(uniqueId); setTimeout(async () => { - await onToggleFavorite({ uniqueId, isFavorite: false }); + await onToggleFavorite({ uniqueId, isFavorite }); setRemovingAssetUniqueId(null); }, TOGGLE_TOKEN_FAVORITE_TIMEOUT); } else { // It's inserting favorite // We update the favorites list straight away setInsertingAssetUniqueId(uniqueId); - await onToggleFavorite({ uniqueId, isFavorite: true }); + await onToggleFavorite({ uniqueId, isFavorite }); setTimeout(() => { setInsertingAssetUniqueId(null); }, TOGGLE_TOKEN_FAVORITE_TIMEOUT); diff --git a/source/renderer/app/components/wallet/tokens/WalletTokensList.js b/source/renderer/app/components/wallet/tokens/WalletTokensList.js index 7825a58afd..3aa522c65a 100644 --- a/source/renderer/app/components/wallet/tokens/WalletTokensList.js +++ b/source/renderer/app/components/wallet/tokens/WalletTokensList.js @@ -1,6 +1,8 @@ // @flow import React from 'react'; import { defineMessages, intlShape, injectIntl } from 'react-intl'; +import { Button } from 'react-polymorph/lib/components/Button'; +import classnames from 'classnames'; import { observer } from 'mobx-react'; import { searchAssets } from '../../../utils/assets'; import styles from './WalletTokensList.scss'; @@ -24,12 +26,17 @@ const messages = defineMessages({ columnAmount: { id: 'wallet.tokens.list.column.amount', defaultMessage: '!!!Amount', - description: 'Amount header on Wallet summary assets page', + description: 'Amount header on the WalletTokensList', }, columnToken: { id: 'wallet.tokens.list.column.token', defaultMessage: '!!!Token', - description: 'Token header on Wallet summary assets page', + description: 'Token header on the WalletTokensList', + }, + viewAllButtonLabel: { + id: 'wallet.tokens.list.viewAllButton.label', + defaultMessage: '!!!View all tokens', + description: 'View all button label on the WalletTokensList', }, }); @@ -75,9 +82,9 @@ const WalletTokensList = observer((props: Props) => { const hasSearch = !isLoadingAssets && !!searchValue && searchValue.trim().length >= 3; const noResults = hasSearch && !filteredAssets.length; + const viewAllButtonStyles = classnames(['flat', styles.viewAllButton]); let content; - if (isLoadingAssets) { content = (
@@ -131,7 +138,11 @@ const WalletTokensList = observer((props: Props) => {
{content} {onViewAllButtonClick && ( - +
diff --git a/source/renderer/app/components/wallet/tokens/WalletTokensList.scss b/source/renderer/app/components/wallet/tokens/WalletTokensList.scss index a9521fd43c..bcc66a5444 100644 --- a/source/renderer/app/components/wallet/tokens/WalletTokensList.scss +++ b/source/renderer/app/components/wallet/tokens/WalletTokensList.scss @@ -1,8 +1,18 @@ .component { margin: 0 20px 20px; + text-align: center; &:last-of-type { margin-bottom: 0; } + button.viewAllButton { + font-size: 14px; + height: 36px; + line-height: 19px; + margin-top: 20px; + padding: 0 40px; + text-align: center; + width: auto; + } } .outerHeader { margin: 0 10px 10px 20px; diff --git a/source/renderer/app/i18n/locales/en-US.json b/source/renderer/app/i18n/locales/en-US.json index 251dde0ff3..8298c8ca42 100755 --- a/source/renderer/app/i18n/locales/en-US.json +++ b/source/renderer/app/i18n/locales/en-US.json @@ -1124,6 +1124,7 @@ "wallet.tokens.list.search.noResults": "No results matching your query", "wallet.tokens.list.search.searchResults": ". Search results", "wallet.tokens.list.tokens.title": "Tokens", + "wallet.tokens.list.viewAllButton.label": "View all tokens", "wallet.tokens.search.placeholder": "Search", "wallet.transaction.address.from": "From address", "wallet.transaction.address.to": "To address", diff --git a/source/renderer/app/i18n/locales/ja-JP.json b/source/renderer/app/i18n/locales/ja-JP.json index d33f6a7044..255ce3add0 100755 --- a/source/renderer/app/i18n/locales/ja-JP.json +++ b/source/renderer/app/i18n/locales/ja-JP.json @@ -1124,6 +1124,7 @@ "wallet.tokens.list.search.noResults": "該当する結果はありません", "wallet.tokens.list.search.searchResults": "。検索結果", "wallet.tokens.list.tokens.title": "!!!Tokens", + "wallet.tokens.list.viewAllButton.label": "!!!View all tokens", "wallet.tokens.search.placeholder": "!!!Search", "wallet.transaction.address.from": "送信元", "wallet.transaction.address.to": "送信先", diff --git a/source/renderer/app/stores/AssetsStore.js b/source/renderer/app/stores/AssetsStore.js index e7ee4813b5..2badcb3b95 100644 --- a/source/renderer/app/stores/AssetsStore.js +++ b/source/renderer/app/stores/AssetsStore.js @@ -180,7 +180,10 @@ export default class AssetsStore extends Store { uniqueId: string, isFavorite: boolean, }) => { - await this.api.localStorage.toggleWalletTokenFavorite(uniqueId, isFavorite); + await this.api.localStorage.toggleWalletTokenFavorite( + uniqueId, + !isFavorite + ); await this.favoritesRequest.execute(); }; From 7f69ee6c39c7f02755a376a1124346888881ce2a Mon Sep 17 00:00:00 2001 From: Danilo Prates Date: Tue, 21 Sep 2021 15:44:29 -0300 Subject: [PATCH 28/60] [DDW-694] Translation manager --- .../app/i18n/locales/defaultMessages.json | 464 +++++++++--------- source/renderer/app/i18n/locales/en-US.json | 10 +- source/renderer/app/i18n/locales/ja-JP.json | 10 +- 3 files changed, 239 insertions(+), 245 deletions(-) diff --git a/source/renderer/app/i18n/locales/defaultMessages.json b/source/renderer/app/i18n/locales/defaultMessages.json index ecfa78e4c5..6c6bbf068e 100644 --- a/source/renderer/app/i18n/locales/defaultMessages.json +++ b/source/renderer/app/i18n/locales/defaultMessages.json @@ -542,7 +542,7 @@ "line": 22 }, "file": "source/renderer/app/components/assets/Asset.js", - "id": "assets.assetToken.item.fingerprint", + "id": "assets.assetToken.param.fingerprint", "start": { "column": 19, "line": 18 @@ -556,7 +556,7 @@ "line": 27 }, "file": "source/renderer/app/components/assets/Asset.js", - "id": "assets.assetToken.item.policyId", + "id": "assets.assetToken.param.policyId", "start": { "column": 16, "line": 23 @@ -570,7 +570,7 @@ "line": 32 }, "file": "source/renderer/app/components/assets/Asset.js", - "id": "assets.assetToken.item.assetName", + "id": "assets.assetToken.param.assetName", "start": { "column": 17, "line": 28 @@ -584,7 +584,7 @@ "line": 37 }, "file": "source/renderer/app/components/assets/Asset.js", - "id": "assets.assetToken.item.name", + "id": "assets.assetToken.param.name", "start": { "column": 12, "line": 33 @@ -598,7 +598,7 @@ "line": 42 }, "file": "source/renderer/app/components/assets/Asset.js", - "id": "assets.assetToken.item.ticker", + "id": "assets.assetToken.param.ticker", "start": { "column": 14, "line": 38 @@ -612,7 +612,7 @@ "line": 47 }, "file": "source/renderer/app/components/assets/Asset.js", - "id": "assets.assetToken.item.description", + "id": "assets.assetToken.param.description", "start": { "column": 19, "line": 43 @@ -626,7 +626,7 @@ "line": 52 }, "file": "source/renderer/app/components/assets/Asset.js", - "id": "assets.assetToken.item.blank", + "id": "assets.assetToken.param.blank", "start": { "column": 9, "line": 48 @@ -700,97 +700,97 @@ "descriptors": [ { "defaultMessage": "!!!Fingerprint", - "description": "\"fingerprint\" item.", + "description": "\"fingerprint\" param.", "end": { "column": 3, "line": 21 }, "file": "source/renderer/app/components/assets/AssetContent.js", - "id": "assets.assetToken.item.fingerprint", + "id": "assets.assetToken.param.fingerprint", "start": { - "column": 19, + "column": 31, "line": 17 } }, { "defaultMessage": "!!!Policy Id", - "description": "\"policyId\" item.", + "description": "\"policyId\" param.", "end": { "column": 3, "line": 26 }, "file": "source/renderer/app/components/assets/AssetContent.js", - "id": "assets.assetToken.item.policyId", + "id": "assets.assetToken.param.policyId", "start": { - "column": 16, + "column": 28, "line": 22 } }, { "defaultMessage": "!!!Asset name", - "description": "\"assetName\" item.", + "description": "\"assetName\" param.", "end": { "column": 3, "line": 31 }, "file": "source/renderer/app/components/assets/AssetContent.js", - "id": "assets.assetToken.item.assetName", + "id": "assets.assetToken.param.assetName", "start": { - "column": 17, + "column": 29, "line": 27 } }, { "defaultMessage": "!!!Name", - "description": "\"name\" item.", + "description": "\"name\" param.", "end": { "column": 3, "line": 36 }, "file": "source/renderer/app/components/assets/AssetContent.js", - "id": "assets.assetToken.item.name", + "id": "assets.assetToken.param.name", "start": { - "column": 12, + "column": 24, "line": 32 } }, { "defaultMessage": "!!!Ticker", - "description": "\"ticker\" item.", + "description": "\"ticker\" param.", "end": { "column": 3, "line": 41 }, "file": "source/renderer/app/components/assets/AssetContent.js", - "id": "assets.assetToken.item.ticker", + "id": "assets.assetToken.param.ticker", "start": { - "column": 14, + "column": 26, "line": 37 } }, { "defaultMessage": "!!!Description", - "description": "\"description\" item.", + "description": "\"description\" param.", "end": { "column": 3, "line": 46 }, "file": "source/renderer/app/components/assets/AssetContent.js", - "id": "assets.assetToken.item.description", + "id": "assets.assetToken.param.description", "start": { - "column": 19, + "column": 31, "line": 42 } }, { "defaultMessage": "!!!Blank", - "description": "\"Blank\" item value.", + "description": "\"Blank\" param value.", "end": { "column": 3, "line": 51 }, "file": "source/renderer/app/components/assets/AssetContent.js", - "id": "assets.assetToken.item.blank", + "id": "assets.assetToken.param.blank", "start": { "column": 9, "line": 47 @@ -8915,13 +8915,13 @@ "description": "Label for the \"Summary\" nav button in the wallet navigation.", "end": { "column": 3, - "line": 26 + "line": 21 }, "file": "source/renderer/app/components/wallet/navigation/WalletNavigation.js", "id": "wallet.navigation.summary", "start": { "column": 11, - "line": 22 + "line": 17 } }, { @@ -8929,13 +8929,13 @@ "description": "Label for the \"Send\" nav button in the wallet navigation.", "end": { "column": 3, - "line": 31 + "line": 26 }, "file": "source/renderer/app/components/wallet/navigation/WalletNavigation.js", "id": "wallet.navigation.send", "start": { "column": 8, - "line": 27 + "line": 22 } }, { @@ -8943,13 +8943,13 @@ "description": "Label for the \"Receive\" nav button in the wallet navigation.", "end": { "column": 3, - "line": 36 + "line": 31 }, "file": "source/renderer/app/components/wallet/navigation/WalletNavigation.js", "id": "wallet.navigation.receive", "start": { "column": 11, - "line": 32 + "line": 27 } }, { @@ -8957,13 +8957,27 @@ "description": "Label for the \"Transactions\" nav button in the wallet navigation.", "end": { "column": 3, - "line": 42 + "line": 37 }, "file": "source/renderer/app/components/wallet/navigation/WalletNavigation.js", "id": "wallet.navigation.transactions", "start": { "column": 16, - "line": 37 + "line": 32 + } + }, + { + "defaultMessage": "!!!Tokens", + "description": "Label for the \"Tokens\" nav button in the wallet navigation.", + "end": { + "column": 3, + "line": 42 + }, + "file": "source/renderer/app/components/wallet/navigation/WalletNavigation.js", + "id": "wallet.navigation.tokens", + "start": { + "column": 10, + "line": 38 } }, { @@ -12441,77 +12455,82 @@ { "descriptors": [ { - "defaultMessage": "!!!Send", - "description": "Send button on Wallet summary assets page", + "defaultMessage": "!!!Converts as", + "description": "\"Currency - title\" label on Wallet summary currency page", "end": { "column": 3, - "line": 23 + "line": 20 }, - "file": "source/renderer/app/components/wallet/summary/WalletSummaryAsset.js", - "id": "wallet.summary.asset.tokenSendButton", + "file": "source/renderer/app/components/wallet/summary/WalletSummaryCurrency.js", + "id": "wallet.summary.currency.title", "start": { - "column": 19, - "line": 19 + "column": 17, + "line": 16 } }, { - "defaultMessage": "!!!Amount", - "description": "Amount label on Wallet summary assets page", + "defaultMessage": "!!!converted {fetchedTimeAgo}", + "description": "\"Currency - last fetched\" label on Wallet summary currency page", "end": { "column": 3, - "line": 28 + "line": 26 }, - "file": "source/renderer/app/components/wallet/summary/WalletSummaryAsset.js", - "id": "wallet.summary.asset.amountLabel", + "file": "source/renderer/app/components/wallet/summary/WalletSummaryCurrency.js", + "id": "wallet.summary.currency.lastFetched", "start": { - "column": 15, - "line": 24 + "column": 23, + "line": 21 } }, { - "defaultMessage": "!!!Settings", - "description": "Settings label on Wallet summary assets page", + "defaultMessage": "!!!fetching conversion rates", + "description": "\"Currency - Fetching\" label on Wallet summary currency page", "end": { "column": 3, - "line": 33 + "line": 31 }, - "file": "source/renderer/app/components/wallet/summary/WalletSummaryAsset.js", - "id": "wallet.summary.asset.settings.button.label", + "file": "source/renderer/app/components/wallet/summary/WalletSummaryCurrency.js", + "id": "wallet.summary.currency.isFetchingRate", "start": { - "column": 23, - "line": 29 + "column": 26, + "line": 27 } - }, + } + ], + "path": "source/renderer/app/components/wallet/summary/WalletSummaryCurrency.json" + }, + { + "descriptors": [ { - "defaultMessage": "!!!Recommended configuration for decimal places for this native token is available.", - "description": "Asset settings recommended pop over content", + "defaultMessage": "!!!Number of transactions", + "description": "\"Number of transactions\" label on Wallet summary header page", "end": { "column": 3, - "line": 39 + "line": 18 }, - "file": "source/renderer/app/components/wallet/summary/WalletSummaryAsset.js", - "id": "assets.warning.available", + "file": "source/renderer/app/components/wallet/summary/WalletSummaryHeader.js", + "id": "wallet.summary.header.transactionsLabel", "start": { - "column": 35, - "line": 34 + "column": 21, + "line": 14 } }, { - "defaultMessage": "!!!You are not using the recommended decimal place configuration for this native token.", - "description": "Asset settings recommended pop over content", + "defaultMessage": "!!!Number of pending transactions", + "description": "\"Number of pending transactions\" label on Wallet summary header page", "end": { "column": 3, - "line": 45 + "line": 24 }, - "file": "source/renderer/app/components/wallet/summary/WalletSummaryAsset.js", - "id": "assets.warning.notUsing", + "file": "source/renderer/app/components/wallet/summary/WalletSummaryHeader.js", + "id": "wallet.summary.header.pendingTransactionsLabel", "start": { - "column": 34, - "line": 40 + "column": 28, + "line": 19 } } ], - "path": "source/renderer/app/components/wallet/summary/WalletSummaryAsset.json" + "path": "source/renderer/app/components/wallet/summary/WalletSummaryHeader.json" }, { "descriptors": [ @@ -12520,284 +12539,275 @@ "description": "Number of tokens title on Wallet summary assets page", "end": { "column": 3, - "line": 24 + "line": 16 }, - "file": "source/renderer/app/components/wallet/summary/WalletSummaryAssets.js", + "file": "source/renderer/app/components/wallet/summary/WalletSummaryNoTokens.js", "id": "wallet.summary.assets.tokensTitle", "start": { "column": 15, - "line": 20 - } - }, - { - "defaultMessage": "!!!Send", - "description": "Send button on Wallet summary assets page", - "end": { - "column": 3, - "line": 29 - }, - "file": "source/renderer/app/components/wallet/summary/WalletSummaryAssets.js", - "id": "wallet.summary.assets.tokenSendButton", - "start": { - "column": 19, - "line": 25 + "line": 12 } }, { - "defaultMessage": "!!!Unknown", - "description": "Unknown label on Wallet summary assets page", + "defaultMessage": "!!!Want to find out more about native tokens?", + "description": "\"Learn more\" text in the Wallets Summary No Tokens component", "end": { "column": 3, - "line": 34 + "line": 21 }, - "file": "source/renderer/app/components/wallet/summary/WalletSummaryAssets.js", - "id": "wallet.summary.assets.unknownLabel", + "file": "source/renderer/app/components/wallet/summary/WalletSummaryNoTokens.js", + "id": "wallet.summary.noTokens.learnMore.textTop", "start": { - "column": 16, - "line": 30 + "column": 20, + "line": 17 } }, { - "defaultMessage": "!!!Hide search", - "description": "Hide search label on Wallet summary assets page", + "defaultMessage": "!!!Start by visiting the IOHK blog for a useful primer.", + "description": "\"Learn more\" text in the Wallets Summary No Tokens component", "end": { "column": 3, - "line": 39 + "line": 26 }, - "file": "source/renderer/app/components/wallet/summary/WalletSummaryAssets.js", - "id": "wallet.summary.assets.search.button.label.hide", + "file": "source/renderer/app/components/wallet/summary/WalletSummaryNoTokens.js", + "id": "wallet.summary.noTokens.learnMore.textBottom", "start": { - "column": 25, - "line": 35 + "column": 23, + "line": 22 } }, { - "defaultMessage": "!!!Show search", - "description": "Show search label on Wallet summary assets page", + "defaultMessage": "!!!Learn more", + "description": "\"Learn more\" label or button in the Wallets Summary No Tokens component", "end": { "column": 3, - "line": 44 + "line": 32 }, - "file": "source/renderer/app/components/wallet/summary/WalletSummaryAssets.js", - "id": "wallet.summary.assets.search.button.label.show", + "file": "source/renderer/app/components/wallet/summary/WalletSummaryNoTokens.js", + "id": "wallet.summary.noTokens.learnMore.linkLabel", "start": { - "column": 25, - "line": 40 + "column": 22, + "line": 27 } }, { - "defaultMessage": "!!!Search tokens", - "description": "Search placeholder on Wallet summary assets page", + "defaultMessage": "!!!https://iohk.io/en/blog/posts/2021/02/04/native-tokens-to-bring-new-utility-to-life-on-cardano/", + "description": "\"Learn more\" link URL in the Wallets Summary No Tokens component", "end": { "column": 3, - "line": 49 + "line": 39 }, - "file": "source/renderer/app/components/wallet/summary/WalletSummaryAssets.js", - "id": "wallet.summary.assets.search.input.placeholder", + "file": "source/renderer/app/components/wallet/summary/WalletSummaryNoTokens.js", + "id": "wallet.summary.noTokens.learnMore.linkUrl", "start": { - "column": 26, - "line": 45 + "column": 20, + "line": 33 } - }, + } + ], + "path": "source/renderer/app/components/wallet/summary/WalletSummaryNoTokens.json" + }, + { + "descriptors": [ { - "defaultMessage": "!!!Token", - "description": "Token header on Wallet summary assets page", + "defaultMessage": "!!!Send", + "description": "Send button on Wallet summary assets page", "end": { "column": 3, - "line": 54 + "line": 25 }, - "file": "source/renderer/app/components/wallet/summary/WalletSummaryAssets.js", - "id": "wallet.summary.assets.header.token", + "file": "source/renderer/app/components/wallet/tokens/WalletToken.js", + "id": "wallet.summary.asset.tokenSendButton", "start": { - "column": 15, - "line": 50 + "column": 19, + "line": 21 } }, { "defaultMessage": "!!!Amount", - "description": "Amount header on Wallet summary assets page", + "description": "Amount label on Wallet summary assets page", "end": { "column": 3, - "line": 59 + "line": 30 }, - "file": "source/renderer/app/components/wallet/summary/WalletSummaryAssets.js", - "id": "wallet.summary.assets.header.amount", + "file": "source/renderer/app/components/wallet/tokens/WalletToken.js", + "id": "wallet.summary.asset.amountLabel", "start": { - "column": 16, - "line": 55 + "column": 15, + "line": 26 } }, { - "defaultMessage": "!!!No results matching your query", - "description": "No results on Wallet summary assets page", - "end": { - "column": 3, - "line": 64 - }, - "file": "source/renderer/app/components/wallet/summary/WalletSummaryAssets.js", - "id": "wallet.summary.assets.search.noResults", - "start": { - "column": 13, - "line": 60 - } - } - ], - "path": "source/renderer/app/components/wallet/summary/WalletSummaryAssets.json" - }, - { - "descriptors": [ - { - "defaultMessage": "!!!Converts as", - "description": "\"Currency - title\" label on Wallet summary currency page", + "defaultMessage": "!!!Settings", + "description": "Settings label on Wallet summary assets page", "end": { "column": 3, - "line": 20 + "line": 35 }, - "file": "source/renderer/app/components/wallet/summary/WalletSummaryCurrency.js", - "id": "wallet.summary.currency.title", + "file": "source/renderer/app/components/wallet/tokens/WalletToken.js", + "id": "wallet.summary.asset.settings.button.label", "start": { - "column": 17, - "line": 16 + "column": 23, + "line": 31 } }, { - "defaultMessage": "!!!converted {fetchedTimeAgo}", - "description": "\"Currency - last fetched\" label on Wallet summary currency page", + "defaultMessage": "!!!Recommended configuration for decimal places for this native token is available.", + "description": "Asset settings recommended pop over content", "end": { "column": 3, - "line": 26 + "line": 41 }, - "file": "source/renderer/app/components/wallet/summary/WalletSummaryCurrency.js", - "id": "wallet.summary.currency.lastFetched", + "file": "source/renderer/app/components/wallet/tokens/WalletToken.js", + "id": "assets.warning.available", "start": { - "column": 23, - "line": 21 + "column": 35, + "line": 36 } }, { - "defaultMessage": "!!!fetching conversion rates", - "description": "\"Currency - Fetching\" label on Wallet summary currency page", + "defaultMessage": "!!!You are not using the recommended decimal place configuration for this native token.", + "description": "Asset settings recommended pop over content", "end": { "column": 3, - "line": 31 + "line": 47 }, - "file": "source/renderer/app/components/wallet/summary/WalletSummaryCurrency.js", - "id": "wallet.summary.currency.isFetchingRate", + "file": "source/renderer/app/components/wallet/tokens/WalletToken.js", + "id": "assets.warning.notUsing", "start": { - "column": 26, - "line": 27 + "column": 34, + "line": 42 } } ], - "path": "source/renderer/app/components/wallet/summary/WalletSummaryCurrency.json" + "path": "source/renderer/app/components/wallet/tokens/WalletToken.json" }, { "descriptors": [ { - "defaultMessage": "!!!Number of transactions", - "description": "\"Number of transactions\" label on Wallet summary header page", + "defaultMessage": "!!!Favorites", + "description": "Favorites list title label", "end": { "column": 3, - "line": 18 + "line": 17 }, - "file": "source/renderer/app/components/wallet/summary/WalletSummaryHeader.js", - "id": "wallet.summary.header.transactionsLabel", + "file": "source/renderer/app/components/wallet/tokens/WalletTokens.js", + "id": "wallet.tokens.list.favorites.title", "start": { - "column": 21, - "line": 14 + "column": 22, + "line": 13 } }, { - "defaultMessage": "!!!Number of pending transactions", - "description": "\"Number of pending transactions\" label on Wallet summary header page", + "defaultMessage": "!!!Tokens", + "description": "Favorites list title label", "end": { "column": 3, - "line": 24 + "line": 22 }, - "file": "source/renderer/app/components/wallet/summary/WalletSummaryHeader.js", - "id": "wallet.summary.header.pendingTransactionsLabel", + "file": "source/renderer/app/components/wallet/tokens/WalletTokens.js", + "id": "wallet.tokens.list.tokens.title", "start": { - "column": 28, - "line": 19 + "column": 19, + "line": 18 } } ], - "path": "source/renderer/app/components/wallet/summary/WalletSummaryHeader.json" + "path": "source/renderer/app/components/wallet/tokens/WalletTokens.json" }, { "descriptors": [ { - "defaultMessage": "!!!Tokens", - "description": "Number of tokens title on Wallet summary assets page", + "defaultMessage": "!!!No results matching your query", + "description": "No results on the WalletTokensList", "end": { "column": 3, - "line": 16 + "line": 20 }, - "file": "source/renderer/app/components/wallet/summary/WalletSummaryNoTokens.js", - "id": "wallet.summary.assets.tokensTitle", + "file": "source/renderer/app/components/wallet/tokens/WalletTokensList.js", + "id": "wallet.tokens.list.search.noResults", "start": { - "column": 15, - "line": 12 + "column": 13, + "line": 16 } }, { - "defaultMessage": "!!!Want to find out more about native tokens?", - "description": "\"Learn more\" text in the Wallets Summary No Tokens component", + "defaultMessage": "!!!Search Results", + "description": "Search Results on the WalletTokensList", "end": { "column": 3, - "line": 21 + "line": 25 }, - "file": "source/renderer/app/components/wallet/summary/WalletSummaryNoTokens.js", - "id": "wallet.summary.noTokens.learnMore.textTop", + "file": "source/renderer/app/components/wallet/tokens/WalletTokensList.js", + "id": "wallet.tokens.list.search.searchResults", "start": { - "column": 20, - "line": 17 + "column": 17, + "line": 21 } }, { - "defaultMessage": "!!!Start by visiting the IOHK blog for a useful primer.", - "description": "\"Learn more\" text in the Wallets Summary No Tokens component", + "defaultMessage": "!!!Amount", + "description": "Amount header on the WalletTokensList", "end": { "column": 3, + "line": 30 + }, + "file": "source/renderer/app/components/wallet/tokens/WalletTokensList.js", + "id": "wallet.tokens.list.column.amount", + "start": { + "column": 16, "line": 26 + } + }, + { + "defaultMessage": "!!!Token", + "description": "Token header on the WalletTokensList", + "end": { + "column": 3, + "line": 35 }, - "file": "source/renderer/app/components/wallet/summary/WalletSummaryNoTokens.js", - "id": "wallet.summary.noTokens.learnMore.textBottom", + "file": "source/renderer/app/components/wallet/tokens/WalletTokensList.js", + "id": "wallet.tokens.list.column.token", "start": { - "column": 23, - "line": 22 + "column": 15, + "line": 31 } }, { - "defaultMessage": "!!!Learn more", - "description": "\"Learn more\" label or button in the Wallets Summary No Tokens component", + "defaultMessage": "!!!View all tokens", + "description": "View all button label on the WalletTokensList", "end": { "column": 3, - "line": 32 + "line": 40 }, - "file": "source/renderer/app/components/wallet/summary/WalletSummaryNoTokens.js", - "id": "wallet.summary.noTokens.learnMore.linkLabel", + "file": "source/renderer/app/components/wallet/tokens/WalletTokensList.js", + "id": "wallet.tokens.list.viewAllButton.label", "start": { "column": 22, - "line": 27 + "line": 36 } - }, + } + ], + "path": "source/renderer/app/components/wallet/tokens/WalletTokensList.json" + }, + { + "descriptors": [ { - "defaultMessage": "!!!https://iohk.io/en/blog/posts/2021/02/04/native-tokens-to-bring-new-utility-to-life-on-cardano/", - "description": "\"Learn more\" link URL in the Wallets Summary No Tokens component", + "defaultMessage": "!!!Search", + "description": "Search placeholder for the Wallet Tokens search", "end": { "column": 3, - "line": 39 + "line": 17 }, - "file": "source/renderer/app/components/wallet/summary/WalletSummaryNoTokens.js", - "id": "wallet.summary.noTokens.learnMore.linkUrl", + "file": "source/renderer/app/components/wallet/tokens/WalletTokensSearch.js", + "id": "wallet.tokens.search.placeholder", "start": { - "column": 20, - "line": 33 + "column": 15, + "line": 13 } } ], - "path": "source/renderer/app/components/wallet/summary/WalletSummaryNoTokens.json" + "path": "source/renderer/app/components/wallet/tokens/WalletTokensSearch.json" }, { "descriptors": [ @@ -16649,16 +16659,16 @@ } }, { - "defaultMessage": "!!!{assetItem}: {value} copied to clipboard", + "defaultMessage": "!!!{param}: {shortValue} copied to clipboard", "description": "Notification for the wallet assetItem copy success in the Wallet Receive page.", "end": { "column": 3, "line": 70 }, "file": "source/renderer/app/containers/notifications/NotificationsContainer.js", - "id": "notification.copyAssetItem", + "id": "notification.copyAssetParam", "start": { - "column": 17, + "column": 18, "line": 64 } }, @@ -17048,13 +17058,13 @@ "description": "Message shown when wallet has no transactions on wallet summary page.", "end": { "column": 3, - "line": 26 + "line": 24 }, "file": "source/renderer/app/containers/wallet/WalletSummaryPage.js", "id": "wallet.summary.page.no.transactions", "start": { "column": 18, - "line": 21 + "line": 19 } } ], diff --git a/source/renderer/app/i18n/locales/en-US.json b/source/renderer/app/i18n/locales/en-US.json index 8298c8ca42..c2c3411ba6 100755 --- a/source/renderer/app/i18n/locales/en-US.json +++ b/source/renderer/app/i18n/locales/en-US.json @@ -1095,15 +1095,7 @@ "wallet.summary.asset.amountLabel": "Amount", "wallet.summary.asset.settings.button.label": "Settings", "wallet.summary.asset.tokenSendButton": "Send", - "wallet.summary.assets.header.amount": "Amount", - "wallet.summary.assets.header.token": "Token", - "wallet.summary.assets.search.button.label.hide": "Hide search", - "wallet.summary.assets.search.button.label.show": "Show search", - "wallet.summary.assets.search.input.placeholder": "Search tokens", - "wallet.summary.assets.search.noResults": "No results matching your query", - "wallet.summary.assets.tokenSendButton": "Send", "wallet.summary.assets.tokensTitle": "Tokens", - "wallet.summary.assets.unknownLabel": "Unknown", "wallet.summary.currency.isFetchingRate": "fetching conversion rates", "wallet.summary.currency.lastFetched": "converted {fetchedTimeAgo}", "wallet.summary.currency.title": "Converts as", @@ -1219,4 +1211,4 @@ "wallet.transferFunds.dialog2.total.label": "Total", "widgets.itemsDropdown.syncingLabel": "Syncing", "widgets.itemsDropdown.syncingLabelProgress": "Syncing {syncingProgress}%" -} +} \ No newline at end of file diff --git a/source/renderer/app/i18n/locales/ja-JP.json b/source/renderer/app/i18n/locales/ja-JP.json index 255ce3add0..4f454a32eb 100755 --- a/source/renderer/app/i18n/locales/ja-JP.json +++ b/source/renderer/app/i18n/locales/ja-JP.json @@ -1095,15 +1095,7 @@ "wallet.summary.asset.amountLabel": "金額", "wallet.summary.asset.settings.button.label": "設定", "wallet.summary.asset.tokenSendButton": "送金", - "wallet.summary.assets.header.amount": "金額", - "wallet.summary.assets.header.token": "トークン", - "wallet.summary.assets.search.button.label.hide": "検索ボックスを非表示にする", - "wallet.summary.assets.search.button.label.show": "検索ボックスを表示する", - "wallet.summary.assets.search.input.placeholder": "トークンを検索する", - "wallet.summary.assets.search.noResults": "該当する結果はありません", - "wallet.summary.assets.tokenSendButton": "送金する", "wallet.summary.assets.tokensTitle": "トークン", - "wallet.summary.assets.unknownLabel": "不明", "wallet.summary.currency.isFetchingRate": "フェッチ時の換算レート", "wallet.summary.currency.lastFetched": "換算:{fetchedTimeAgo}", "wallet.summary.currency.title": "換算通貨:", @@ -1219,4 +1211,4 @@ "wallet.transferFunds.dialog2.total.label": "合計", "widgets.itemsDropdown.syncingLabel": "同期", "widgets.itemsDropdown.syncingLabelProgress": "同期中 {syncingProgress}%" -} +} \ No newline at end of file From 87700e267669993fd3c866bf73bb74ea4dd0cc8f Mon Sep 17 00:00:00 2001 From: Danilo Prates Date: Tue, 21 Sep 2021 18:39:10 -0300 Subject: [PATCH 29/60] [DDW-694] Sorting - init --- .../wallet/tokens/WalletTokensList.js | 69 ++++++++++++++++++- .../wallet/tokens/WalletTokensList.scss | 44 +++++++----- 2 files changed, 92 insertions(+), 21 deletions(-) diff --git a/source/renderer/app/components/wallet/tokens/WalletTokensList.js b/source/renderer/app/components/wallet/tokens/WalletTokensList.js index 3aa522c65a..b1eefef907 100644 --- a/source/renderer/app/components/wallet/tokens/WalletTokensList.js +++ b/source/renderer/app/components/wallet/tokens/WalletTokensList.js @@ -1,9 +1,10 @@ // @flow -import React from 'react'; +import React, { useState, useMemo, useCallback } from 'react'; import { defineMessages, intlShape, injectIntl } from 'react-intl'; import { Button } from 'react-polymorph/lib/components/Button'; import classnames from 'classnames'; import { observer } from 'mobx-react'; +import SVGInline from 'react-svg-inline'; import { searchAssets } from '../../../utils/assets'; import styles from './WalletTokensList.scss'; import Wallet from '../../../domains/Wallet'; @@ -11,6 +12,7 @@ import BorderedBox from '../../widgets/BorderedBox'; import LoadingSpinner from '../../widgets/LoadingSpinner'; import WalletToken from './WalletToken'; import type { AssetToken } from '../../../api/assets/types'; +import sortIcon from '../../../assets/images/ascending.inline.svg'; const messages = defineMessages({ noResults: { @@ -59,7 +61,26 @@ type Props = { wallet: Wallet, }; +type SortBy = 'token' | 'amount'; +type SortDirection = 'asc' | 'desc'; + +const getSortClasses = ( + item: SortBy, + sortBy: SortBy, + sortDirection: SortDirection +) => { + const isSorted = item === sortBy; + return classnames([ + styles.sortIcon, + sortDirection === 'asc' ? styles.ascending : null, + isSorted ? styles.sorted : null, + isSorted ? styles[`${sortDirection}Sorting`] : 'ascSorting', + ]); +}; + const WalletTokensList = observer((props: Props) => { + const [sortDirection, setSortDirection] = useState('asc'); + const [sortBy, setSortBy] = useState('token'); const { assets, assetSettingsDialogWasOpened, @@ -84,6 +105,38 @@ const WalletTokensList = observer((props: Props) => { const noResults = hasSearch && !filteredAssets.length; const viewAllButtonStyles = classnames(['flat', styles.viewAllButton]); + const sortIconClassesToken = useMemo( + () => getSortClasses('token', sortBy, sortDirection), + [sortBy, sortDirection] + ); + const sortIconClassesAmount = useMemo( + () => getSortClasses('amount', sortBy, sortDirection), + [sortBy, sortDirection] + ); + const toggleSortDirection = () => { + if (sortDirection === 'asc') { + setSortDirection('desc'); + } else { + setSortDirection('asc'); + } + }; + const onSortBy = (newSortBy: SortBy) => { + if (newSortBy === sortBy) { + toggleSortDirection(); + } else { + setSortDirection('asc'); + setSortBy(newSortBy); + } + }; + const onSortByToken = useCallback(() => onSortBy('token'), [ + sortDirection, + sortBy, + ]); + const onSortByAmount = useCallback(() => onSortBy('amount'), [ + sortDirection, + sortBy, + ]); + let content; if (isLoadingAssets) { content = ( @@ -133,8 +186,18 @@ const WalletTokensList = observer((props: Props) => {
- {intl.formatMessage(messages.columnToken)} - {intl.formatMessage(messages.columnAmount)} +
+ {intl.formatMessage(messages.columnToken)} + {sortBy === 'token' && ( + + )} +
+
+ {intl.formatMessage(messages.columnAmount)} + {sortBy === 'amount' && ( + + )} +
{content} {onViewAllButtonClick && ( diff --git a/source/renderer/app/components/wallet/tokens/WalletTokensList.scss b/source/renderer/app/components/wallet/tokens/WalletTokensList.scss index bcc66a5444..eab05c6caf 100644 --- a/source/renderer/app/components/wallet/tokens/WalletTokensList.scss +++ b/source/renderer/app/components/wallet/tokens/WalletTokensList.scss @@ -24,36 +24,44 @@ font-size: 16px; line-height: 22px; } - - .controls { - display: flex; - .sort { - } - .sortBySelect .toggleVisibility { - button { - background-color: rgba(68, 91, 124, 0.1); - border-radius: 4px; - color: black; - font-family: var(--font-regular); - font-size: 17px; - height: 20px; - width: 20px; - } - } - } } .columns { display: flex; justify-content: space-between; margin: 0 42px 10px 12px; - span { + > div { color: var(--theme-bordered-box-text-color); + cursor: pointer; font-family: var(--font-semibold); font-size: 10px; letter-spacing: 1px; line-height: 2; text-transform: uppercase; } + .sortIcon { + margin-left: 3px; + visibility: hidden; + + & > svg { + height: 7.5px; + width: 7px; + + & > path { + fill: var(--theme-staking-font-color-regular); + } + } + + &.ascSorting { + & > svg { + transform: rotateX(150deg); + } + } + + &.sorted { + opacity: 1; + visibility: visible; + } + } } .noResults { color: var(--theme-bordered-box-text-color); From 43f3413dba3e9739cd414d4430925ca4f992a5ed Mon Sep 17 00:00:00 2001 From: Danilo Prates Date: Tue, 21 Sep 2021 19:25:22 -0300 Subject: [PATCH 30/60] [DDW-694] Wallet Tokens sorting --- .../wallet/tokens/WalletTokensList.js | 27 ++++++++++++------- .../wallet/tokens/WalletTokensList.scss | 6 +++++ .../tokens/WalletTokensList.stories.js | 8 +++--- 3 files changed, 28 insertions(+), 13 deletions(-) diff --git a/source/renderer/app/components/wallet/tokens/WalletTokensList.js b/source/renderer/app/components/wallet/tokens/WalletTokensList.js index b1eefef907..c1f4f7aade 100644 --- a/source/renderer/app/components/wallet/tokens/WalletTokensList.js +++ b/source/renderer/app/components/wallet/tokens/WalletTokensList.js @@ -72,9 +72,8 @@ const getSortClasses = ( const isSorted = item === sortBy; return classnames([ styles.sortIcon, - sortDirection === 'asc' ? styles.ascending : null, isSorted ? styles.sorted : null, - isSorted ? styles[`${sortDirection}Sorting`] : 'ascSorting', + isSorted ? styles[`${sortDirection}Sorting`] : styles.ascSorting, ]); }; @@ -99,7 +98,21 @@ const WalletTokensList = observer((props: Props) => { wallet, } = props; const isRestoreActive = wallet.isRestoring; - const filteredAssets = searchAssets(searchValue, assets); + const sortedAssets = useMemo(() => { + return [...assets].sort((asset1: AssetToken, asset2: AssetToken) => { + if (sortBy === 'token') { + if (sortDirection === 'asc') { + return asset1.fingerprint.localeCompare(asset2.fingerprint); + } + return asset2.fingerprint.localeCompare(asset1.fingerprint); + } + if (sortDirection === 'asc') { + return asset1.quantity.isLessThan(asset2.quantity) ? -1 : 1; + } + return asset1.quantity.isLessThan(asset2.quantity) ? 1 : -1; + }); + }, [sortBy, sortDirection]); + const filteredAssets = searchAssets(searchValue, sortedAssets); const hasSearch = !isLoadingAssets && !!searchValue && searchValue.trim().length >= 3; const noResults = hasSearch && !filteredAssets.length; @@ -188,15 +201,11 @@ const WalletTokensList = observer((props: Props) => {
{intl.formatMessage(messages.columnToken)} - {sortBy === 'token' && ( - - )} +
{intl.formatMessage(messages.columnAmount)} - {sortBy === 'amount' && ( - - )} +
{content} diff --git a/source/renderer/app/components/wallet/tokens/WalletTokensList.scss b/source/renderer/app/components/wallet/tokens/WalletTokensList.scss index eab05c6caf..4b8feea905 100644 --- a/source/renderer/app/components/wallet/tokens/WalletTokensList.scss +++ b/source/renderer/app/components/wallet/tokens/WalletTokensList.scss @@ -37,10 +37,16 @@ letter-spacing: 1px; line-height: 2; text-transform: uppercase; + &:hover { + .sortIcon { + visibility: visible; + } + } } .sortIcon { margin-left: 3px; visibility: hidden; + opacity: 0.5; & > svg { height: 7.5px; diff --git a/storybook/stories/wallets/tokens/WalletTokensList.stories.js b/storybook/stories/wallets/tokens/WalletTokensList.stories.js index cb7b33eb9e..e14eb9fd4d 100644 --- a/storybook/stories/wallets/tokens/WalletTokensList.stories.js +++ b/storybook/stories/wallets/tokens/WalletTokensList.stories.js @@ -22,7 +22,7 @@ const assets = [ generateAssetToken( '65bc72542b0ca20391caaf66a4d4e7897d282f9c136cd3513136945c', '', - 'tokenb0ca20391caaf66a4d4e7897d282f9c136cd3513136945c2542', + 'tokenb0ca20391caaf66a4d4e7897d282f9c136cd3513136945c2541', 100, { name: 'MakerDAO', @@ -39,13 +39,13 @@ const assets = [ generateAssetToken( '65bc72542b0ca20391caaf66a4d4d7897d281f9c136cd3513136945b', '', - 'tokenb0ca20391caaf66a4d4d7897d281f9c136cd3513136945b2342', + 'tokenb0ca20391caaf66a4d4e7897d282f9c136cd3513136945c2542', 400 ), generateAssetToken( '65ac82542b0ca20391caaf66a4d4d7897d281f9c136cd3513136945b', '', - 'tokenb0ca20391caaf66a4d4d7897d281f9c136cd3513136945b2542', + 'tokenb0ca20391caaf66a4d4e7897d282f9c136cd3513136945c2544', 100, { name: 'Tether', @@ -62,7 +62,7 @@ const assets = [ generateAssetToken( '65cn72542b0ca10391caaf66a4d4d2897d281f3c136cd3513136945b', '', - 'tokenb0ca10391caaf66a4d4d2897d281f3c136cd3513136945b2542', + 'tokenb0ca20391caaf66a4d4e7897d282f9c136cd3513136945c2543', 100, { name: 'USD Coin', From 4c1cd1b71a66132d13a0b9e29efc79c71871c968 Mon Sep 17 00:00:00 2001 From: Danilo Prates Date: Tue, 21 Sep 2021 19:40:27 -0300 Subject: [PATCH 31/60] [DDW-694] Fix memoized token dependency --- source/renderer/app/components/wallet/tokens/WalletTokens.js | 3 +++ .../renderer/app/components/wallet/tokens/WalletTokensList.js | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/source/renderer/app/components/wallet/tokens/WalletTokens.js b/source/renderer/app/components/wallet/tokens/WalletTokens.js index c49c95f832..9f3954e51a 100644 --- a/source/renderer/app/components/wallet/tokens/WalletTokens.js +++ b/source/renderer/app/components/wallet/tokens/WalletTokens.js @@ -53,6 +53,8 @@ const WalletTokens = observer((props: Props) => { onToggleFavorite, ...listProps } = props; + + console.log('tokenFavorites', tokenFavorites); const favoriteTokensList = assets.filter( ({ uniqueId }) => tokenFavorites[uniqueId] ); @@ -94,6 +96,7 @@ const WalletTokens = observer((props: Props) => { } }; + console.log('favoriteTokensList', favoriteTokensList); return (
diff --git a/source/renderer/app/components/wallet/tokens/WalletTokensList.js b/source/renderer/app/components/wallet/tokens/WalletTokensList.js index c1f4f7aade..20a616fffe 100644 --- a/source/renderer/app/components/wallet/tokens/WalletTokensList.js +++ b/source/renderer/app/components/wallet/tokens/WalletTokensList.js @@ -111,7 +111,7 @@ const WalletTokensList = observer((props: Props) => { } return asset1.quantity.isLessThan(asset2.quantity) ? 1 : -1; }); - }, [sortBy, sortDirection]); + }, [assets, sortBy, sortDirection]); const filteredAssets = searchAssets(searchValue, sortedAssets); const hasSearch = !isLoadingAssets && !!searchValue && searchValue.trim().length >= 3; From c2013f25085c8ca57db5aceaad49e83c64811813 Mon Sep 17 00:00:00 2001 From: Danilo Prates Date: Tue, 21 Sep 2021 19:41:02 -0300 Subject: [PATCH 32/60] [DDW-694] Fix memoized token dependency --- source/renderer/app/components/wallet/tokens/WalletTokens.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/source/renderer/app/components/wallet/tokens/WalletTokens.js b/source/renderer/app/components/wallet/tokens/WalletTokens.js index 9f3954e51a..c49c95f832 100644 --- a/source/renderer/app/components/wallet/tokens/WalletTokens.js +++ b/source/renderer/app/components/wallet/tokens/WalletTokens.js @@ -53,8 +53,6 @@ const WalletTokens = observer((props: Props) => { onToggleFavorite, ...listProps } = props; - - console.log('tokenFavorites', tokenFavorites); const favoriteTokensList = assets.filter( ({ uniqueId }) => tokenFavorites[uniqueId] ); @@ -96,7 +94,6 @@ const WalletTokens = observer((props: Props) => { } }; - console.log('favoriteTokensList', favoriteTokensList); return (
From 6e01c594b94158056ef84b5dbbb5ad945115f3b8 Mon Sep 17 00:00:00 2001 From: Danilo Prates Date: Wed, 22 Sep 2021 14:37:06 +0200 Subject: [PATCH 33/60] [DDW-694] Move sort fn into utils --- .../wallet/tokens/WalletTokensList.js | 33 ++++++------------- source/renderer/app/utils/assets.js | 26 ++++++++++----- 2 files changed, 28 insertions(+), 31 deletions(-) diff --git a/source/renderer/app/components/wallet/tokens/WalletTokensList.js b/source/renderer/app/components/wallet/tokens/WalletTokensList.js index 20a616fffe..86b44a7f4b 100644 --- a/source/renderer/app/components/wallet/tokens/WalletTokensList.js +++ b/source/renderer/app/components/wallet/tokens/WalletTokensList.js @@ -5,14 +5,15 @@ import { Button } from 'react-polymorph/lib/components/Button'; import classnames from 'classnames'; import { observer } from 'mobx-react'; import SVGInline from 'react-svg-inline'; -import { searchAssets } from '../../../utils/assets'; +import { searchAssets, sortAssets } from '../../../utils/assets'; import styles from './WalletTokensList.scss'; import Wallet from '../../../domains/Wallet'; import BorderedBox from '../../widgets/BorderedBox'; import LoadingSpinner from '../../widgets/LoadingSpinner'; import WalletToken from './WalletToken'; -import type { AssetToken } from '../../../api/assets/types'; import sortIcon from '../../../assets/images/ascending.inline.svg'; +import type { AssetToken } from '../../../api/assets/types'; +import type { SortBy, SortDirection } from '../../../utils/assets'; const messages = defineMessages({ noResults: { @@ -61,10 +62,7 @@ type Props = { wallet: Wallet, }; -type SortBy = 'token' | 'amount'; -type SortDirection = 'asc' | 'desc'; - -const getSortClasses = ( +const getSortIconClasses = ( item: SortBy, sortBy: SortBy, sortDirection: SortDirection @@ -79,7 +77,7 @@ const getSortClasses = ( const WalletTokensList = observer((props: Props) => { const [sortDirection, setSortDirection] = useState('asc'); - const [sortBy, setSortBy] = useState('token'); + const [sortBy, setSortBy] = useState('fingerprint'); const { assets, assetSettingsDialogWasOpened, @@ -99,18 +97,7 @@ const WalletTokensList = observer((props: Props) => { } = props; const isRestoreActive = wallet.isRestoring; const sortedAssets = useMemo(() => { - return [...assets].sort((asset1: AssetToken, asset2: AssetToken) => { - if (sortBy === 'token') { - if (sortDirection === 'asc') { - return asset1.fingerprint.localeCompare(asset2.fingerprint); - } - return asset2.fingerprint.localeCompare(asset1.fingerprint); - } - if (sortDirection === 'asc') { - return asset1.quantity.isLessThan(asset2.quantity) ? -1 : 1; - } - return asset1.quantity.isLessThan(asset2.quantity) ? 1 : -1; - }); + return [...assets].sort(sortAssets(sortBy, sortDirection)); }, [assets, sortBy, sortDirection]); const filteredAssets = searchAssets(searchValue, sortedAssets); const hasSearch = @@ -119,11 +106,11 @@ const WalletTokensList = observer((props: Props) => { const viewAllButtonStyles = classnames(['flat', styles.viewAllButton]); const sortIconClassesToken = useMemo( - () => getSortClasses('token', sortBy, sortDirection), + () => getSortIconClasses('fingerprint', sortBy, sortDirection), [sortBy, sortDirection] ); const sortIconClassesAmount = useMemo( - () => getSortClasses('amount', sortBy, sortDirection), + () => getSortIconClasses('quantity', sortBy, sortDirection), [sortBy, sortDirection] ); const toggleSortDirection = () => { @@ -141,11 +128,11 @@ const WalletTokensList = observer((props: Props) => { setSortBy(newSortBy); } }; - const onSortByToken = useCallback(() => onSortBy('token'), [ + const onSortByToken = useCallback(() => onSortBy('fingerprint'), [ sortDirection, sortBy, ]); - const onSortByAmount = useCallback(() => onSortBy('amount'), [ + const onSortByAmount = useCallback(() => onSortBy('quantity'), [ sortDirection, sortBy, ]); diff --git a/source/renderer/app/utils/assets.js b/source/renderer/app/utils/assets.js index 4d11c7a0be..da74c67f0b 100644 --- a/source/renderer/app/utils/assets.js +++ b/source/renderer/app/utils/assets.js @@ -8,6 +8,9 @@ import type { Token, Tokens, AssetToken } from '../api/assets/types'; import { TransactionTypes } from '../domains/WalletTransaction'; import type { TransactionType } from '../api/transactions/types'; +export type SortBy = 'fingerprint' | 'quantity'; +export type SortDirection = 'asc' | 'desc'; + /** * * This function removes the `change` assets @@ -83,7 +86,7 @@ export const getAssetTokens = ( assets .map((asset) => getAssetToken(asset, getToken(asset, tokens))) .filter((token) => !!token.uniqueId) - .sort(sortAssets); + .sort(sortAssets('fingerprint', 'asc')); /** * @@ -127,16 +130,23 @@ export const getNonZeroAssetTokens = ( tokens .map((token) => getNonZeroAssetToken(token, getAsset)) .filter((token) => !!token.uniqueId) - .sort(sortAssets); + .sort(sortAssets('fingerprint', 'asc')); -export const sortAssets = (asset1: AssetToken, asset2: AssetToken) => { - if (asset1 && asset2) { - if (asset1.fingerprint < asset2.fingerprint) { - return -1; +export const sortAssets = (sortBy: SortBy, sortDirection: SortDirection) => ( + asset1: AssetToken, + asset2: AssetToken +) => { + if (sortBy === 'fingerprint') { + if (sortDirection === 'asc') { + return asset1.fingerprint.localeCompare(asset2.fingerprint); } - if (asset1.fingerprint > asset2.fingerprint) { - return 1; + return asset2.fingerprint.localeCompare(asset1.fingerprint); + } + if (sortBy === 'quantity') { + if (sortDirection === 'asc') { + return asset1.quantity.isLessThan(asset2.quantity) ? -1 : 1; } + return asset1.quantity.isLessThan(asset2.quantity) ? 1 : -1; } return 0; }; From 07208e043769ab9e530f0fed3cc9bdbd2f0ddfa2 Mon Sep 17 00:00:00 2001 From: Danilo Prates Date: Wed, 22 Sep 2021 15:25:47 +0200 Subject: [PATCH 34/60] [DDW-694] Adjust column title position --- .../app/components/wallet/tokens/WalletTokensList.scss | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/renderer/app/components/wallet/tokens/WalletTokensList.scss b/source/renderer/app/components/wallet/tokens/WalletTokensList.scss index 4b8feea905..52e96bc6ef 100644 --- a/source/renderer/app/components/wallet/tokens/WalletTokensList.scss +++ b/source/renderer/app/components/wallet/tokens/WalletTokensList.scss @@ -37,6 +37,9 @@ letter-spacing: 1px; line-height: 2; text-transform: uppercase; + &:first-of-type { + margin-left: 27px; + } &:hover { .sortIcon { visibility: visible; From 004b023c0aece25bb9bd221b0829d8a94c15e18f Mon Sep 17 00:00:00 2001 From: Danilo Prates Date: Wed, 22 Sep 2021 15:49:30 +0200 Subject: [PATCH 35/60] [DDW-694] Sorting and animation tweaks --- .../components/wallet/tokens/WalletToken.scss | 4 +- .../wallet/tokens/WalletTokensList.js | 6 +-- source/renderer/app/utils/assets.js | 37 ++++++++++++++++--- 3 files changed, 37 insertions(+), 10 deletions(-) diff --git a/source/renderer/app/components/wallet/tokens/WalletToken.scss b/source/renderer/app/components/wallet/tokens/WalletToken.scss index 68095c3308..ffffb40e8f 100644 --- a/source/renderer/app/components/wallet/tokens/WalletToken.scss +++ b/source/renderer/app/components/wallet/tokens/WalletToken.scss @@ -14,10 +14,10 @@ } } &.inserting { - animation: insertAnimation 0.2s; + animation: insertAnimation 0.3s; } &.removing { - animation: removingAnimation 0.2s; + animation: removingAnimation 0.3s; border-bottom: 0 none; height: 0; } diff --git a/source/renderer/app/components/wallet/tokens/WalletTokensList.js b/source/renderer/app/components/wallet/tokens/WalletTokensList.js index 86b44a7f4b..89e0433447 100644 --- a/source/renderer/app/components/wallet/tokens/WalletTokensList.js +++ b/source/renderer/app/components/wallet/tokens/WalletTokensList.js @@ -77,7 +77,7 @@ const getSortIconClasses = ( const WalletTokensList = observer((props: Props) => { const [sortDirection, setSortDirection] = useState('asc'); - const [sortBy, setSortBy] = useState('fingerprint'); + const [sortBy, setSortBy] = useState('token'); const { assets, assetSettingsDialogWasOpened, @@ -106,7 +106,7 @@ const WalletTokensList = observer((props: Props) => { const viewAllButtonStyles = classnames(['flat', styles.viewAllButton]); const sortIconClassesToken = useMemo( - () => getSortIconClasses('fingerprint', sortBy, sortDirection), + () => getSortIconClasses('token', sortBy, sortDirection), [sortBy, sortDirection] ); const sortIconClassesAmount = useMemo( @@ -128,7 +128,7 @@ const WalletTokensList = observer((props: Props) => { setSortBy(newSortBy); } }; - const onSortByToken = useCallback(() => onSortBy('fingerprint'), [ + const onSortByToken = useCallback(() => onSortBy('token'), [ sortDirection, sortBy, ]); diff --git a/source/renderer/app/utils/assets.js b/source/renderer/app/utils/assets.js index da74c67f0b..1423325e4f 100644 --- a/source/renderer/app/utils/assets.js +++ b/source/renderer/app/utils/assets.js @@ -8,7 +8,7 @@ import type { Token, Tokens, AssetToken } from '../api/assets/types'; import { TransactionTypes } from '../domains/WalletTransaction'; import type { TransactionType } from '../api/transactions/types'; -export type SortBy = 'fingerprint' | 'quantity'; +export type SortBy = 'token' | 'fingerprint' | 'quantity'; export type SortDirection = 'asc' | 'desc'; /** @@ -136,17 +136,44 @@ export const sortAssets = (sortBy: SortBy, sortDirection: SortDirection) => ( asset1: AssetToken, asset2: AssetToken ) => { + const { + quantity: quantity1, + fingerprint: fingerprint1, + metadata: metadata1, + } = asset1; + const { name: name1 } = metadata1 || {}; + const { + quantity: quantity2, + fingerprint: fingerprint2, + metadata: metadata2, + } = asset2; + const { name: name2 } = metadata2 || {}; + if (sortBy === 'token') { + if (name1 && !name2) return -1; + if (!name1 && name2) return 1; + if (name1 && name2) { + if (sortDirection === 'asc') { + return name1.localeCompare(name2); + } + return name2.localeCompare(name1); + } + + if (sortDirection === 'asc') { + return fingerprint1.localeCompare(fingerprint2); + } + return fingerprint2.localeCompare(fingerprint1); + } if (sortBy === 'fingerprint') { if (sortDirection === 'asc') { - return asset1.fingerprint.localeCompare(asset2.fingerprint); + return fingerprint1.localeCompare(fingerprint2); } - return asset2.fingerprint.localeCompare(asset1.fingerprint); + return fingerprint2.localeCompare(fingerprint1); } if (sortBy === 'quantity') { if (sortDirection === 'asc') { - return asset1.quantity.isLessThan(asset2.quantity) ? -1 : 1; + return quantity1.isLessThan(quantity2) ? -1 : 1; } - return asset1.quantity.isLessThan(asset2.quantity) ? 1 : -1; + return quantity1.isLessThan(quantity2) ? 1 : -1; } return 0; }; From 97c729355bcfe66a98840589069997bd68092677 Mon Sep 17 00:00:00 2001 From: Danilo Prates Date: Thu, 23 Sep 2021 09:53:19 +0200 Subject: [PATCH 36/60] [DDW-694] JP translation --- .../wallet/tokens/WalletTokensSearch.js | 2 +- .../app/i18n/locales/defaultMessages.json | 22 +++++++++---------- source/renderer/app/i18n/locales/en-US.json | 2 +- source/renderer/app/i18n/locales/ja-JP.json | 4 ++-- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/source/renderer/app/components/wallet/tokens/WalletTokensSearch.js b/source/renderer/app/components/wallet/tokens/WalletTokensSearch.js index a2ddbb5576..0762eba6f4 100644 --- a/source/renderer/app/components/wallet/tokens/WalletTokensSearch.js +++ b/source/renderer/app/components/wallet/tokens/WalletTokensSearch.js @@ -12,7 +12,7 @@ import crossIcon from '../../../assets/images/close-cross.inline.svg'; const messages = defineMessages({ placeholder: { id: 'wallet.tokens.search.placeholder', - defaultMessage: '!!!Search', + defaultMessage: '!!!Search tokens', description: 'Search placeholder for the Wallet Tokens search', }, }); diff --git a/source/renderer/app/i18n/locales/defaultMessages.json b/source/renderer/app/i18n/locales/defaultMessages.json index 6c6bbf068e..65ae7f9d26 100644 --- a/source/renderer/app/i18n/locales/defaultMessages.json +++ b/source/renderer/app/i18n/locales/defaultMessages.json @@ -12722,13 +12722,13 @@ "description": "No results on the WalletTokensList", "end": { "column": 3, - "line": 20 + "line": 23 }, "file": "source/renderer/app/components/wallet/tokens/WalletTokensList.js", "id": "wallet.tokens.list.search.noResults", "start": { "column": 13, - "line": 16 + "line": 19 } }, { @@ -12736,13 +12736,13 @@ "description": "Search Results on the WalletTokensList", "end": { "column": 3, - "line": 25 + "line": 28 }, "file": "source/renderer/app/components/wallet/tokens/WalletTokensList.js", "id": "wallet.tokens.list.search.searchResults", "start": { "column": 17, - "line": 21 + "line": 24 } }, { @@ -12750,13 +12750,13 @@ "description": "Amount header on the WalletTokensList", "end": { "column": 3, - "line": 30 + "line": 33 }, "file": "source/renderer/app/components/wallet/tokens/WalletTokensList.js", "id": "wallet.tokens.list.column.amount", "start": { "column": 16, - "line": 26 + "line": 29 } }, { @@ -12764,13 +12764,13 @@ "description": "Token header on the WalletTokensList", "end": { "column": 3, - "line": 35 + "line": 38 }, "file": "source/renderer/app/components/wallet/tokens/WalletTokensList.js", "id": "wallet.tokens.list.column.token", "start": { "column": 15, - "line": 31 + "line": 34 } }, { @@ -12778,13 +12778,13 @@ "description": "View all button label on the WalletTokensList", "end": { "column": 3, - "line": 40 + "line": 43 }, "file": "source/renderer/app/components/wallet/tokens/WalletTokensList.js", "id": "wallet.tokens.list.viewAllButton.label", "start": { "column": 22, - "line": 36 + "line": 39 } } ], @@ -12793,7 +12793,7 @@ { "descriptors": [ { - "defaultMessage": "!!!Search", + "defaultMessage": "!!!Search tokens", "description": "Search placeholder for the Wallet Tokens search", "end": { "column": 3, diff --git a/source/renderer/app/i18n/locales/en-US.json b/source/renderer/app/i18n/locales/en-US.json index c2c3411ba6..991ffef4b6 100755 --- a/source/renderer/app/i18n/locales/en-US.json +++ b/source/renderer/app/i18n/locales/en-US.json @@ -1117,7 +1117,7 @@ "wallet.tokens.list.search.searchResults": ". Search results", "wallet.tokens.list.tokens.title": "Tokens", "wallet.tokens.list.viewAllButton.label": "View all tokens", - "wallet.tokens.search.placeholder": "Search", + "wallet.tokens.search.placeholder": "Search tokens", "wallet.transaction.address.from": "From address", "wallet.transaction.address.to": "To address", "wallet.transaction.addresses.from": "From addresses", diff --git a/source/renderer/app/i18n/locales/ja-JP.json b/source/renderer/app/i18n/locales/ja-JP.json index 4f454a32eb..4e6f697561 100755 --- a/source/renderer/app/i18n/locales/ja-JP.json +++ b/source/renderer/app/i18n/locales/ja-JP.json @@ -1115,9 +1115,9 @@ "wallet.tokens.list.favorites.title": "!!!Favorites", "wallet.tokens.list.search.noResults": "該当する結果はありません", "wallet.tokens.list.search.searchResults": "。検索結果", - "wallet.tokens.list.tokens.title": "!!!Tokens", + "wallet.tokens.list.tokens.title": "トークン", "wallet.tokens.list.viewAllButton.label": "!!!View all tokens", - "wallet.tokens.search.placeholder": "!!!Search", + "wallet.tokens.search.placeholder": "トークンを検索する", "wallet.transaction.address.from": "送信元", "wallet.transaction.address.to": "送信先", "wallet.transaction.addresses.from": "送信元アドレス", From b9a7c57ab5d974398f3faa0d32593a1ddfa37d64 Mon Sep 17 00:00:00 2001 From: Danilo Prates Date: Thu, 23 Sep 2021 10:53:51 +0200 Subject: [PATCH 37/60] [DDW-694] Preparing for translation --- .../wallet/summary/WalletSummary.js | 16 +++++++++++++++- .../app/i18n/locales/defaultMessages.json | 19 +++++++++++++++++++ source/renderer/app/i18n/locales/en-US.json | 1 + source/renderer/app/i18n/locales/ja-JP.json | 1 + 4 files changed, 36 insertions(+), 1 deletion(-) diff --git a/source/renderer/app/components/wallet/summary/WalletSummary.js b/source/renderer/app/components/wallet/summary/WalletSummary.js index fc8bca24bc..5f921c51f8 100644 --- a/source/renderer/app/components/wallet/summary/WalletSummary.js +++ b/source/renderer/app/components/wallet/summary/WalletSummary.js @@ -1,6 +1,7 @@ // @flow import React, { Component } from 'react'; import { observer } from 'mobx-react'; +import { defineMessages, intlShape } from 'react-intl'; import Wallet from '../../../domains/Wallet'; import type { Currency } from '../../../types/currencyTypes'; import WalletSummaryHeader from './WalletSummaryHeader'; @@ -10,6 +11,14 @@ import WalletSummaryNoTokens from './WalletSummaryNoTokens'; import WalletTokensList from '../tokens/WalletTokensList'; import { MAX_TOKENS_ON_SUMMARY_PAGE } from '../../../config/numbersConfig'; +const messages = defineMessages({ + tokensListTitle: { + id: 'wallet.summary.tokensList.title', + defaultMessage: '!!!Recently used tokens', + description: 'Send button on Wallet summary assets page', + }, +}); + type Props = { wallet: Wallet, numberOfRecentTransactions: number, @@ -37,6 +46,10 @@ type Props = { @observer export default class WalletSummary extends Component { + static contextTypes = { + intl: intlShape.isRequired, + }; + render() { const { wallet, @@ -62,6 +75,7 @@ export default class WalletSummary extends Component { onToggleFavorite, tokenFavorites, } = this.props; + const { intl } = this.context; const { isRestoring } = wallet; const hasAssets = assets.length || isLoadingAssets; @@ -100,7 +114,7 @@ export default class WalletSummary extends Component { onAssetSettings={onAssetSettings} assetSettingsDialogWasOpened={assetSettingsDialogWasOpened} currentLocale={currentLocale} - title="Recently used tokens" + title={intl.formatMessage(messages.tokensListTitle)} onViewAllButtonClick={onViewAllButtonClick} tokenFavorites={tokenFavorites} onToggleFavorite={onToggleFavorite} diff --git a/source/renderer/app/i18n/locales/defaultMessages.json b/source/renderer/app/i18n/locales/defaultMessages.json index 65ae7f9d26..67eb3d40d0 100644 --- a/source/renderer/app/i18n/locales/defaultMessages.json +++ b/source/renderer/app/i18n/locales/defaultMessages.json @@ -12452,6 +12452,25 @@ ], "path": "source/renderer/app/components/wallet/skins/AmountInputSkin.json" }, + { + "descriptors": [ + { + "defaultMessage": "!!!Recently used tokens", + "description": "Send button on Wallet summary assets page", + "end": { + "column": 3, + "line": 19 + }, + "file": "source/renderer/app/components/wallet/summary/WalletSummary.js", + "id": "wallet.summary.tokensList.title", + "start": { + "column": 19, + "line": 15 + } + } + ], + "path": "source/renderer/app/components/wallet/summary/WalletSummary.json" + }, { "descriptors": [ { diff --git a/source/renderer/app/i18n/locales/en-US.json b/source/renderer/app/i18n/locales/en-US.json index 991ffef4b6..d53eb8c409 100755 --- a/source/renderer/app/i18n/locales/en-US.json +++ b/source/renderer/app/i18n/locales/en-US.json @@ -1106,6 +1106,7 @@ "wallet.summary.noTokens.learnMore.textBottom": "Start by visiting the IOHK blog for a useful primer.", "wallet.summary.noTokens.learnMore.textTop": "Want to find out more about native tokens?", "wallet.summary.page.no.transactions": "No recent transactions", + "wallet.summary.tokensList.title": "Recently used tokens", "wallet.summary.transactionsList.showMoreTransactionsButtonLabel": "Show more transactions", "wallet.summary.transactionsList.syncingTransactionsMessage": "Your transaction history for this wallet is being synced with the blockchain.", "wallet.summary.transactionsList.todayLabel": "Today", diff --git a/source/renderer/app/i18n/locales/ja-JP.json b/source/renderer/app/i18n/locales/ja-JP.json index 4e6f697561..a4c37bb769 100755 --- a/source/renderer/app/i18n/locales/ja-JP.json +++ b/source/renderer/app/i18n/locales/ja-JP.json @@ -1106,6 +1106,7 @@ "wallet.summary.noTokens.learnMore.textBottom": "役立つ入門書については、IOHKブログにアクセスすることから始めてください。", "wallet.summary.noTokens.learnMore.textTop": "ネイティブトークンについてもっと知りたいですか?", "wallet.summary.page.no.transactions": "最近のトランザクションはありません", + "wallet.summary.tokensList.title": "!!!Recently used tokens", "wallet.summary.transactionsList.showMoreTransactionsButtonLabel": "もっと表示", "wallet.summary.transactionsList.syncingTransactionsMessage": "ウォレットのトランザクション履歴は現在ブロックチェーンと同期中です。", "wallet.summary.transactionsList.todayLabel": "今日", From 576b7c7bc6adad1691f5a4e80bbc0b96d8f99970 Mon Sep 17 00:00:00 2001 From: Danilo Prates Date: Thu, 23 Sep 2021 12:13:17 +0200 Subject: [PATCH 38/60] [DDW-694] JP translation and adjustments --- .../wallet/summary/WalletSummary.js | 2 +- .../wallet/tokens/WalletTokensList.js | 33 +++++++++----- .../wallet/tokens/WalletTokensList.scss | 44 +++++++++++-------- source/renderer/app/i18n/locales/ja-JP.json | 8 ++-- 4 files changed, 51 insertions(+), 36 deletions(-) diff --git a/source/renderer/app/components/wallet/summary/WalletSummary.js b/source/renderer/app/components/wallet/summary/WalletSummary.js index 5f921c51f8..e3a8964061 100644 --- a/source/renderer/app/components/wallet/summary/WalletSummary.js +++ b/source/renderer/app/components/wallet/summary/WalletSummary.js @@ -78,7 +78,7 @@ export default class WalletSummary extends Component { const { intl } = this.context; const { isRestoring } = wallet; - const hasAssets = assets.length || isLoadingAssets; + const hasAssets = (!!assets && assets.length) || isLoadingAssets; return ( <> diff --git a/source/renderer/app/components/wallet/tokens/WalletTokensList.js b/source/renderer/app/components/wallet/tokens/WalletTokensList.js index 89e0433447..c0f4a88480 100644 --- a/source/renderer/app/components/wallet/tokens/WalletTokensList.js +++ b/source/renderer/app/components/wallet/tokens/WalletTokensList.js @@ -99,11 +99,18 @@ const WalletTokensList = observer((props: Props) => { const sortedAssets = useMemo(() => { return [...assets].sort(sortAssets(sortBy, sortDirection)); }, [assets, sortBy, sortDirection]); - const filteredAssets = searchAssets(searchValue, sortedAssets); + const filteredAssets = searchAssets(searchValue, sortedAssets) || []; + console.log('filteredAssets', filteredAssets); + console.log('filteredAssets.length', filteredAssets.length); const hasSearch = !isLoadingAssets && !!searchValue && searchValue.trim().length >= 3; const noResults = hasSearch && !filteredAssets.length; const viewAllButtonStyles = classnames(['flat', styles.viewAllButton]); + const hasSorting = filteredAssets.length && filteredAssets.length > 1; + const columnsStyles = classnames([ + styles.columns, + hasSorting ? styles.sorting : null, + ]); const sortIconClassesToken = useMemo( () => getSortIconClasses('token', sortBy, sortDirection), @@ -128,14 +135,12 @@ const WalletTokensList = observer((props: Props) => { setSortBy(newSortBy); } }; - const onSortByToken = useCallback(() => onSortBy('token'), [ - sortDirection, - sortBy, - ]); - const onSortByAmount = useCallback(() => onSortBy('quantity'), [ - sortDirection, - sortBy, - ]); + const onSortByToken = hasSorting + ? useCallback(() => onSortBy('token'), [sortDirection, sortBy]) + : null; + const onSortByAmount = hasSorting + ? useCallback(() => onSortBy('quantity'), [sortDirection, sortBy]) + : null; let content; if (isLoadingAssets) { @@ -185,14 +190,18 @@ const WalletTokensList = observer((props: Props) => {
-
+
{intl.formatMessage(messages.columnToken)} - + {hasSorting && ( + + )}
{intl.formatMessage(messages.columnAmount)} - + {hasSorting && ( + + )}
{content} diff --git a/source/renderer/app/components/wallet/tokens/WalletTokensList.scss b/source/renderer/app/components/wallet/tokens/WalletTokensList.scss index 52e96bc6ef..003e988527 100644 --- a/source/renderer/app/components/wallet/tokens/WalletTokensList.scss +++ b/source/renderer/app/components/wallet/tokens/WalletTokensList.scss @@ -31,14 +31,15 @@ margin: 0 42px 10px 12px; > div { color: var(--theme-bordered-box-text-color); - cursor: pointer; font-family: var(--font-semibold); font-size: 10px; letter-spacing: 1px; line-height: 2; + margin: -5px 0 0 -5px; + padding: 5px; text-transform: uppercase; &:first-of-type { - margin-left: 27px; + margin-left: 22px; } &:hover { .sortIcon { @@ -46,29 +47,34 @@ } } } - .sortIcon { - margin-left: 3px; - visibility: hidden; - opacity: 0.5; + &.sorting { + > div { + cursor: pointer; + } + .sortIcon { + margin-left: 3px; + visibility: hidden; + opacity: 0.5; - & > svg { - height: 7.5px; - width: 7px; + & > svg { + height: 7.5px; + width: 7px; - & > path { - fill: var(--theme-staking-font-color-regular); + & > path { + fill: var(--theme-staking-font-color-regular); + } } - } - &.ascSorting { - & > svg { - transform: rotateX(150deg); + &.ascSorting { + & > svg { + transform: rotateX(150deg); + } } - } - &.sorted { - opacity: 1; - visibility: visible; + &.sorted { + opacity: 1; + visibility: visible; + } } } } diff --git a/source/renderer/app/i18n/locales/ja-JP.json b/source/renderer/app/i18n/locales/ja-JP.json index a4c37bb769..93936aa07e 100755 --- a/source/renderer/app/i18n/locales/ja-JP.json +++ b/source/renderer/app/i18n/locales/ja-JP.json @@ -1106,18 +1106,18 @@ "wallet.summary.noTokens.learnMore.textBottom": "役立つ入門書については、IOHKブログにアクセスすることから始めてください。", "wallet.summary.noTokens.learnMore.textTop": "ネイティブトークンについてもっと知りたいですか?", "wallet.summary.page.no.transactions": "最近のトランザクションはありません", - "wallet.summary.tokensList.title": "!!!Recently used tokens", + "wallet.summary.tokensList.title": "最近使用したトークン", "wallet.summary.transactionsList.showMoreTransactionsButtonLabel": "もっと表示", "wallet.summary.transactionsList.syncingTransactionsMessage": "ウォレットのトランザクション履歴は現在ブロックチェーンと同期中です。", "wallet.summary.transactionsList.todayLabel": "今日", "wallet.summary.transactionsList.yesterdayLabel": "昨日", "wallet.tokens.list.column.amount": "金額", "wallet.tokens.list.column.token": "トークン", - "wallet.tokens.list.favorites.title": "!!!Favorites", + "wallet.tokens.list.favorites.title": "お気に入り", "wallet.tokens.list.search.noResults": "該当する結果はありません", "wallet.tokens.list.search.searchResults": "。検索結果", "wallet.tokens.list.tokens.title": "トークン", - "wallet.tokens.list.viewAllButton.label": "!!!View all tokens", + "wallet.tokens.list.viewAllButton.label": "すべてのトークンを表示する", "wallet.tokens.search.placeholder": "トークンを検索する", "wallet.transaction.address.from": "送信元", "wallet.transaction.address.to": "送信先", @@ -1212,4 +1212,4 @@ "wallet.transferFunds.dialog2.total.label": "合計", "widgets.itemsDropdown.syncingLabel": "同期", "widgets.itemsDropdown.syncingLabelProgress": "同期中 {syncingProgress}%" -} \ No newline at end of file +} From b01154d2cbc4021caa1e08d0ec5aa06f8bc391fa Mon Sep 17 00:00:00 2001 From: Danilo Prates Date: Thu, 23 Sep 2021 16:53:33 +0200 Subject: [PATCH 39/60] [DDW-694] Adjustments --- .../wallet/summary/WalletSummary.js | 2 +- .../wallet/tokens/WalletTokensList.js | 20 ++++++++++--------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/source/renderer/app/components/wallet/summary/WalletSummary.js b/source/renderer/app/components/wallet/summary/WalletSummary.js index e3a8964061..5f921c51f8 100644 --- a/source/renderer/app/components/wallet/summary/WalletSummary.js +++ b/source/renderer/app/components/wallet/summary/WalletSummary.js @@ -78,7 +78,7 @@ export default class WalletSummary extends Component { const { intl } = this.context; const { isRestoring } = wallet; - const hasAssets = (!!assets && assets.length) || isLoadingAssets; + const hasAssets = assets.length || isLoadingAssets; return ( <> diff --git a/source/renderer/app/components/wallet/tokens/WalletTokensList.js b/source/renderer/app/components/wallet/tokens/WalletTokensList.js index c0f4a88480..fce4c0f2e8 100644 --- a/source/renderer/app/components/wallet/tokens/WalletTokensList.js +++ b/source/renderer/app/components/wallet/tokens/WalletTokensList.js @@ -100,8 +100,6 @@ const WalletTokensList = observer((props: Props) => { return [...assets].sort(sortAssets(sortBy, sortDirection)); }, [assets, sortBy, sortDirection]); const filteredAssets = searchAssets(searchValue, sortedAssets) || []; - console.log('filteredAssets', filteredAssets); - console.log('filteredAssets.length', filteredAssets.length); const hasSearch = !isLoadingAssets && !!searchValue && searchValue.trim().length >= 3; const noResults = hasSearch && !filteredAssets.length; @@ -111,7 +109,6 @@ const WalletTokensList = observer((props: Props) => { styles.columns, hasSorting ? styles.sorting : null, ]); - const sortIconClassesToken = useMemo( () => getSortIconClasses('token', sortBy, sortDirection), [sortBy, sortDirection] @@ -128,6 +125,7 @@ const WalletTokensList = observer((props: Props) => { } }; const onSortBy = (newSortBy: SortBy) => { + if (!hasSorting) return; if (newSortBy === sortBy) { toggleSortDirection(); } else { @@ -135,12 +133,16 @@ const WalletTokensList = observer((props: Props) => { setSortBy(newSortBy); } }; - const onSortByToken = hasSorting - ? useCallback(() => onSortBy('token'), [sortDirection, sortBy]) - : null; - const onSortByAmount = hasSorting - ? useCallback(() => onSortBy('quantity'), [sortDirection, sortBy]) - : null; + const onSortByToken = useCallback(() => onSortBy('token'), [ + sortDirection, + sortBy, + hasSorting, + ]); + const onSortByAmount = useCallback(() => onSortBy('quantity'), [ + sortDirection, + sortBy, + hasSorting, + ]); let content; if (isLoadingAssets) { From dc0659fbfa64f8f7c44f54961ae702ce886156e7 Mon Sep 17 00:00:00 2001 From: Danilo Prates Date: Thu, 23 Sep 2021 17:30:51 +0200 Subject: [PATCH 40/60] [DDW-694] Adjustments --- .../assets/images/star-not-filled.inline.svg | 2 +- .../components/wallet/tokens/WalletToken.scss | 14 +++++- .../wallet/tokens/WalletTokensList.js | 14 ++---- .../wallet/tokens/WalletTokensList.scss | 50 ++++++++++--------- .../renderer/app/themes/daedalus/cardano.js | 4 ++ .../renderer/app/themes/daedalus/dark-blue.js | 4 ++ .../app/themes/daedalus/dark-cardano.js | 4 ++ .../app/themes/daedalus/flight-candidate.js | 4 ++ .../themes/daedalus/incentivized-testnet.js | 4 ++ .../app/themes/daedalus/light-blue.js | 4 ++ .../app/themes/daedalus/shelley-testnet.js | 4 ++ source/renderer/app/themes/daedalus/white.js | 4 ++ source/renderer/app/themes/daedalus/yellow.js | 4 ++ 13 files changed, 81 insertions(+), 35 deletions(-) diff --git a/source/renderer/app/assets/images/star-not-filled.inline.svg b/source/renderer/app/assets/images/star-not-filled.inline.svg index 16c55647d5..c005ed829c 100644 --- a/source/renderer/app/assets/images/star-not-filled.inline.svg +++ b/source/renderer/app/assets/images/star-not-filled.inline.svg @@ -1,3 +1,3 @@ - + diff --git a/source/renderer/app/components/wallet/tokens/WalletToken.scss b/source/renderer/app/components/wallet/tokens/WalletToken.scss index ffffb40e8f..937fab4861 100644 --- a/source/renderer/app/components/wallet/tokens/WalletToken.scss +++ b/source/renderer/app/components/wallet/tokens/WalletToken.scss @@ -4,10 +4,17 @@ border-bottom: 1px solid rgba(94, 96, 102, 0.15); } &.isExpanded:not(.removing) { - background-color: var(--theme-button-flat-background-color-hover); + background-color: var(--theme-tokens-list-header-expanded-background-color); padding-bottom: 20px; .header { - background-color: var(--theme-button-flat-background-color-hover); + background-color: var( + --theme-tokens-list-header-expanded-background-color + ); + &:hover { + background-color: var( + --theme-tokens-list-header-expanded-background-color-hover + ); + } } .content { display: block; @@ -85,6 +92,9 @@ text-overflow: ellipsis; white-space: nowrap; } + &:hover { + background: var(--theme-button-flat-background-color-hover); + } } .leftContent { max-width: 75%; diff --git a/source/renderer/app/components/wallet/tokens/WalletTokensList.js b/source/renderer/app/components/wallet/tokens/WalletTokensList.js index fce4c0f2e8..40a3e47111 100644 --- a/source/renderer/app/components/wallet/tokens/WalletTokensList.js +++ b/source/renderer/app/components/wallet/tokens/WalletTokensList.js @@ -107,7 +107,7 @@ const WalletTokensList = observer((props: Props) => { const hasSorting = filteredAssets.length && filteredAssets.length > 1; const columnsStyles = classnames([ styles.columns, - hasSorting ? styles.sorting : null, + hasSorting ? styles.hasSorting : null, ]); const sortIconClassesToken = useMemo( () => getSortIconClasses('token', sortBy, sortDirection), @@ -193,17 +193,13 @@ const WalletTokensList = observer((props: Props) => {
-
+
{intl.formatMessage(messages.columnToken)} - {hasSorting && ( - - )} +
-
+
{intl.formatMessage(messages.columnAmount)} - {hasSorting && ( - - )} +
{content} diff --git a/source/renderer/app/components/wallet/tokens/WalletTokensList.scss b/source/renderer/app/components/wallet/tokens/WalletTokensList.scss index 003e988527..49e8d11da9 100644 --- a/source/renderer/app/components/wallet/tokens/WalletTokensList.scss +++ b/source/renderer/app/components/wallet/tokens/WalletTokensList.scss @@ -29,7 +29,7 @@ display: flex; justify-content: space-between; margin: 0 42px 10px 12px; - > div { + .column { color: var(--theme-bordered-box-text-color); font-family: var(--font-semibold); font-size: 10px; @@ -41,36 +41,40 @@ &:first-of-type { margin-left: 22px; } - &:hover { - .sortIcon { - visibility: visible; - } + &:last-of-type { + margin-right: -16px; } } - &.sorting { - > div { - cursor: pointer; - } - .sortIcon { - margin-left: 3px; - visibility: hidden; - opacity: 0.5; + .sortIcon { + margin-left: 3px; + visibility: hidden; + opacity: 0.5; - & > svg { - height: 7.5px; - width: 7px; + & > svg { + height: 7.5px; + width: 7px; - & > path { - fill: var(--theme-staking-font-color-regular); - } + & > path { + fill: var(--theme-staking-font-color-regular); } + } - &.ascSorting { - & > svg { - transform: rotateX(150deg); + &.ascSorting { + & > svg { + transform: rotateX(150deg); + } + } + } + &.hasSorting { + .column { + cursor: pointer; + &:hover { + .sortIcon { + visibility: visible; } } - + } + .sortIcon { &.sorted { opacity: 1; visibility: visible; diff --git a/source/renderer/app/themes/daedalus/cardano.js b/source/renderer/app/themes/daedalus/cardano.js index d82a5b355a..d24886feca 100644 --- a/source/renderer/app/themes/daedalus/cardano.js +++ b/source/renderer/app/themes/daedalus/cardano.js @@ -1012,6 +1012,10 @@ export const CARDANO_THEME_OUTPUT = { }, tokens: { '--theme-tokens-list-header-text-color': 'rgba(94, 96, 102, 0.5)', + '--theme-tokens-list-header-expanded-background-color': + 'rgba(32, 34, 37, 0.05)', + '--theme-tokens-list-header-expanded-background-color-hover': + 'rgba(32, 34, 37, 0.03)', }, uploader: { '--theme-uploader-text-color': '#5e6066', diff --git a/source/renderer/app/themes/daedalus/dark-blue.js b/source/renderer/app/themes/daedalus/dark-blue.js index bf88b2ee75..401930b49c 100644 --- a/source/renderer/app/themes/daedalus/dark-blue.js +++ b/source/renderer/app/themes/daedalus/dark-blue.js @@ -1017,6 +1017,10 @@ export const DARK_BLUE_THEME_OUTPUT = { }, tokens: { '--theme-tokens-list-header-text-color': 'rgba(233, 244, 254, 0.5)', + '--theme-tokens-list-header-expanded-background-color': + 'rgba(233, 244, 254, 0.05)', + '--theme-tokens-list-header-expanded-background-color-hover': + 'rgba(233, 244, 254, 0.03)', }, uploader: { '--theme-uploader-text-color': '#e9f4fe', diff --git a/source/renderer/app/themes/daedalus/dark-cardano.js b/source/renderer/app/themes/daedalus/dark-cardano.js index 3a764e9384..508f2a778c 100644 --- a/source/renderer/app/themes/daedalus/dark-cardano.js +++ b/source/renderer/app/themes/daedalus/dark-cardano.js @@ -1005,6 +1005,10 @@ export const DARK_CARDANO_THEME_OUTPUT = { }, tokens: { '--theme-tokens-list-header-text-color': 'rgba(255, 255, 255, 0.5)', + '--theme-tokens-list-header-expanded-background-color': + 'rgba(255, 255, 255, 0.05)', + '--theme-tokens-list-header-expanded-background-color-hover': + 'rgba(255, 255, 255, 0.03)', }, uploader: { '--theme-uploader-text-color': '#ffffff', diff --git a/source/renderer/app/themes/daedalus/flight-candidate.js b/source/renderer/app/themes/daedalus/flight-candidate.js index b053c3c952..78e4c767a4 100644 --- a/source/renderer/app/themes/daedalus/flight-candidate.js +++ b/source/renderer/app/themes/daedalus/flight-candidate.js @@ -1003,6 +1003,10 @@ export const FLIGHT_CANDIDATE_THEME_OUTPUT = { }, tokens: { '--theme-tokens-list-header-text-color': 'rgba(255, 255, 255, 0.5)', + '--theme-tokens-list-header-expanded-background-color': + 'rgba(255, 255, 255, 0.05)', + '--theme-tokens-list-header-expanded-background-color-hover': + 'rgba(255, 255, 255, 0.03)', }, uploader: { '--theme-uploader-text-color': '#ffffff', diff --git a/source/renderer/app/themes/daedalus/incentivized-testnet.js b/source/renderer/app/themes/daedalus/incentivized-testnet.js index c2adacd52e..6edb985d69 100644 --- a/source/renderer/app/themes/daedalus/incentivized-testnet.js +++ b/source/renderer/app/themes/daedalus/incentivized-testnet.js @@ -1006,6 +1006,10 @@ export const INCENTIVIZED_TESTNET_THEME_OUTPUT = { }, tokens: { '--theme-tokens-list-header-text-color': 'rgba(255, 255, 255, 0.5)', + '--theme-tokens-list-header-expanded-background-color': + 'rgba(255, 255, 255, 0.05)', + '--theme-tokens-list-header-expanded-background-color-hover': + 'rgba(255, 255, 255, 0.03)', }, uploader: { '--theme-uploader-text-color': '#ffffff', diff --git a/source/renderer/app/themes/daedalus/light-blue.js b/source/renderer/app/themes/daedalus/light-blue.js index 1310acaf1e..e33125096b 100644 --- a/source/renderer/app/themes/daedalus/light-blue.js +++ b/source/renderer/app/themes/daedalus/light-blue.js @@ -1009,6 +1009,10 @@ export const LIGHT_BLUE_THEME_OUTPUT = { }, tokens: { '--theme-tokens-list-header-text-color': 'rgba(94, 96, 102, 0.5)', + '--theme-tokens-list-header-expanded-background-color': + 'rgba(68, 91, 124, 0.05)', + '--theme-tokens-list-header-expanded-background-color-hover': + 'rgba(68, 91, 124, 0.03)', }, uploader: { '--theme-uploader-text-color': '#5e6066', diff --git a/source/renderer/app/themes/daedalus/shelley-testnet.js b/source/renderer/app/themes/daedalus/shelley-testnet.js index 11f824be06..0be4d2ebba 100644 --- a/source/renderer/app/themes/daedalus/shelley-testnet.js +++ b/source/renderer/app/themes/daedalus/shelley-testnet.js @@ -1003,6 +1003,10 @@ export const SHELLEY_TESTNET_THEME_OUTPUT = { }, tokens: { '--theme-tokens-list-header-text-color': 'rgba(255, 255, 255, 0.5)', + '--theme-tokens-list-header-expanded-background-color': + 'rgba(255, 255, 255, 0.05)', + '--theme-tokens-list-header-expanded-background-color-hover': + 'rgba(255, 255, 255, 0.03)', }, uploader: { '--theme-uploader-text-color': '#ffffff', diff --git a/source/renderer/app/themes/daedalus/white.js b/source/renderer/app/themes/daedalus/white.js index f3bdabf165..8292e3d260 100644 --- a/source/renderer/app/themes/daedalus/white.js +++ b/source/renderer/app/themes/daedalus/white.js @@ -1004,6 +1004,10 @@ export const WHITE_THEME_OUTPUT = { }, tokens: { '--theme-tokens-list-header-text-color': 'rgba(45, 45, 45, 0.5)', + '--theme-tokens-list-header-expanded-background-color': + 'rgba(41, 181, 149, 0.05)', + '--theme-tokens-list-header-expanded-background-color-hover': + 'rgba(41, 181, 149, 0.03)', }, uploader: { '--theme-uploader-text-color': '#2d2d2d', diff --git a/source/renderer/app/themes/daedalus/yellow.js b/source/renderer/app/themes/daedalus/yellow.js index 29b39b0652..875a9d6d9b 100644 --- a/source/renderer/app/themes/daedalus/yellow.js +++ b/source/renderer/app/themes/daedalus/yellow.js @@ -999,6 +999,10 @@ export const YELLOW_THEME_OUTPUT = { }, tokens: { '--theme-tokens-list-header-text-color': '#2d2d2d80', + '--theme-tokens-list-header-expanded-background-color': + 'rgba(45, 45, 45, 0.05)', + '--theme-tokens-list-header-expanded-background-color-hover': + 'rgba(45, 45, 45, 0.03)', }, uploader: { '--theme-uploader-text-color': '#2d2d2d', From 39eb6bfc9d563b384da7f1bdd381d7762db1c12b Mon Sep 17 00:00:00 2001 From: Danilo Prates Date: Thu, 23 Sep 2021 17:54:58 +0200 Subject: [PATCH 41/60] [DDW-694] Adjustments --- source/renderer/app/components/wallet/tokens/WalletToken.scss | 4 ++-- source/renderer/app/components/wallet/tokens/WalletTokens.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/source/renderer/app/components/wallet/tokens/WalletToken.scss b/source/renderer/app/components/wallet/tokens/WalletToken.scss index 937fab4861..e586911004 100644 --- a/source/renderer/app/components/wallet/tokens/WalletToken.scss +++ b/source/renderer/app/components/wallet/tokens/WalletToken.scss @@ -57,7 +57,7 @@ cursor: pointer; height: 22px; left: 8px; - opacity: 0.7; + opacity: 0.3; padding-top: 2px; position: absolute; top: 7px; @@ -74,7 +74,7 @@ } } &:hover { - opacity: 1; + opacity: 0.7; } } .asset { diff --git a/source/renderer/app/components/wallet/tokens/WalletTokens.js b/source/renderer/app/components/wallet/tokens/WalletTokens.js index c49c95f832..90c03e5ee9 100644 --- a/source/renderer/app/components/wallet/tokens/WalletTokens.js +++ b/source/renderer/app/components/wallet/tokens/WalletTokens.js @@ -81,7 +81,7 @@ const WalletTokens = observer((props: Props) => { setRemovingAssetUniqueId(uniqueId); setTimeout(async () => { await onToggleFavorite({ uniqueId, isFavorite }); - setRemovingAssetUniqueId(null); + setTimeout(() => setRemovingAssetUniqueId(null), 500); }, TOGGLE_TOKEN_FAVORITE_TIMEOUT); } else { // It's inserting favorite From 4b9cd75068a81a64b68eef63b0d6da71a3ebd04d Mon Sep 17 00:00:00 2001 From: Danilo Prates Date: Thu, 23 Sep 2021 18:08:40 +0200 Subject: [PATCH 42/60] [DDW-694] Add mistakenly removed flow to Routes --- source/renderer/app/Routes.js | 1 + 1 file changed, 1 insertion(+) diff --git a/source/renderer/app/Routes.js b/source/renderer/app/Routes.js index c9f740640f..aa174d1f3d 100644 --- a/source/renderer/app/Routes.js +++ b/source/renderer/app/Routes.js @@ -1,3 +1,4 @@ +// @flow import React from 'react'; import { Switch, Route, Redirect, withRouter } from 'react-router-dom'; import { ROUTES } from './routes-config'; From 85788345564c7f37f626190be4fea7c1481323df Mon Sep 17 00:00:00 2001 From: Danilo Prates Date: Thu, 23 Sep 2021 18:11:06 +0200 Subject: [PATCH 43/60] [DDW-694] Remove unused type --- source/renderer/app/api/assets/types.js | 1 - 1 file changed, 1 deletion(-) diff --git a/source/renderer/app/api/assets/types.js b/source/renderer/app/api/assets/types.js index 9bea8cff68..2a8461f6cc 100644 --- a/source/renderer/app/api/assets/types.js +++ b/source/renderer/app/api/assets/types.js @@ -30,7 +30,6 @@ export type Asset = { recommendedDecimals: ?number, uniqueId: string, }; -export type Assets = Array; /** * From e93b2b45a852cdc43aba93f68c4cab526bed8f80 Mon Sep 17 00:00:00 2001 From: Danilo Prates Date: Thu, 23 Sep 2021 18:14:57 +0200 Subject: [PATCH 44/60] [DDW-694] Fix variables naming --- .../app/components/assets/AssetContent.js | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/source/renderer/app/components/assets/AssetContent.js b/source/renderer/app/components/assets/AssetContent.js index 9b0a609995..8afe78f4af 100644 --- a/source/renderer/app/components/assets/AssetContent.js +++ b/source/renderer/app/components/assets/AssetContent.js @@ -14,32 +14,32 @@ import { ASSET_TOKEN_ID_COPY_FEEDBACK } from '../../config/timingConfig'; import type { Asset as AssetProps } from '../../api/assets/types'; const messages = defineMessages({ - fingerprintrenderAssetParam: { + fingerprintAssetParam: { id: 'assets.assetToken.param.fingerprint', defaultMessage: '!!!Fingerprint', description: '"fingerprint" param.', }, - policyIdrenderAssetParam: { + policyIdAssetParam: { id: 'assets.assetToken.param.policyId', defaultMessage: '!!!Policy Id', description: '"policyId" param.', }, - assetNamerenderAssetParam: { + assetNameAssetParam: { id: 'assets.assetToken.param.assetName', defaultMessage: '!!!Asset name', description: '"assetName" param.', }, - namerenderAssetParam: { + nameAssetParam: { id: 'assets.assetToken.param.name', defaultMessage: '!!!Name', description: '"name" param.', }, - tickerrenderAssetParam: { + tickerAssetParam: { id: 'assets.assetToken.param.ticker', defaultMessage: '!!!Ticker', description: '"ticker" param.', }, - descriptionrenderAssetParam: { + descriptionAssetParam: { id: 'assets.assetToken.param.description', defaultMessage: '!!!Description', description: '"description" param.', @@ -142,7 +142,7 @@ const AssetContent = observer((props: Props) => {
{renderAssetParam( 'fingerprint', - intl.formatMessage(messages.fingerprintrenderAssetParam), + intl.formatMessage(messages.fingerprintAssetParam), fingerprint )}
@@ -150,11 +150,11 @@ const AssetContent = observer((props: Props) => {
{!highlightFingerprint && ( <> -
{intl.formatMessage(messages.fingerprintrenderAssetParam)}
+
{intl.formatMessage(messages.fingerprintAssetParam)}
{renderAssetParam( 'fingerprint', - intl.formatMessage(messages.fingerprintrenderAssetParam), + intl.formatMessage(messages.fingerprintAssetParam), fingerprint )}
@@ -162,11 +162,11 @@ const AssetContent = observer((props: Props) => { )} {ticker && ( <> -
{intl.formatMessage(messages.tickerrenderAssetParam)}
+
{intl.formatMessage(messages.tickerAssetParam)}
{renderAssetParam( 'ticker', - intl.formatMessage(messages.tickerrenderAssetParam), + intl.formatMessage(messages.tickerAssetParam), ticker )}
@@ -174,11 +174,11 @@ const AssetContent = observer((props: Props) => { )} {name && ( <> -
{intl.formatMessage(messages.namerenderAssetParam)}
+
{intl.formatMessage(messages.nameAssetParam)}
{renderAssetParam( 'name', - intl.formatMessage(messages.namerenderAssetParam), + intl.formatMessage(messages.nameAssetParam), name )}
@@ -186,30 +186,30 @@ const AssetContent = observer((props: Props) => { )} {description && ( <> -
{intl.formatMessage(messages.descriptionrenderAssetParam)}
+
{intl.formatMessage(messages.descriptionAssetParam)}
{renderAssetParam( 'description', - intl.formatMessage(messages.descriptionrenderAssetParam), + intl.formatMessage(messages.descriptionAssetParam), description )}
)} -
{intl.formatMessage(messages.policyIdrenderAssetParam)}
+
{intl.formatMessage(messages.policyIdAssetParam)}
{renderAssetParam( 'policyId', - intl.formatMessage(messages.policyIdrenderAssetParam), + intl.formatMessage(messages.policyIdAssetParam), policyId )}
-
{intl.formatMessage(messages.assetNamerenderAssetParam)}
+
{intl.formatMessage(messages.assetNameAssetParam)}
{assetName ? ( - renderAssetParam( + AssetParam( 'assetName', - intl.formatMessage(messages.assetNamerenderAssetParam), + intl.formatMessage(messages.assetNameAssetParam), assetName ) ) : ( From bc9cff594cd540bbae4841333c033d33d41e2668 Mon Sep 17 00:00:00 2001 From: Danilo Prates Date: Thu, 23 Sep 2021 18:17:10 +0200 Subject: [PATCH 45/60] [DDW-694] Fix variables naming --- source/renderer/app/components/assets/AssetContent.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/renderer/app/components/assets/AssetContent.js b/source/renderer/app/components/assets/AssetContent.js index 8afe78f4af..93f5c7a6ad 100644 --- a/source/renderer/app/components/assets/AssetContent.js +++ b/source/renderer/app/components/assets/AssetContent.js @@ -207,7 +207,7 @@ const AssetContent = observer((props: Props) => {
{intl.formatMessage(messages.assetNameAssetParam)}
{assetName ? ( - AssetParam( + renderAssetParam( 'assetName', intl.formatMessage(messages.assetNameAssetParam), assetName From 4fcddfd119d45a603ef2eccd3bfcc58c8f46aab5 Mon Sep 17 00:00:00 2001 From: Danilo Prates Date: Tue, 28 Sep 2021 10:56:54 +0200 Subject: [PATCH 46/60] [DDW-694] Styling adjustment --- .../renderer/app/components/wallet/tokens/WalletToken.scss | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/source/renderer/app/components/wallet/tokens/WalletToken.scss b/source/renderer/app/components/wallet/tokens/WalletToken.scss index e586911004..a9ef61e5b8 100644 --- a/source/renderer/app/components/wallet/tokens/WalletToken.scss +++ b/source/renderer/app/components/wallet/tokens/WalletToken.scss @@ -68,6 +68,9 @@ height: 14px; width: 15px; } + &.isFavorite { + opacity: 0.7; + } &:not(.isFavorite) { path { stroke: var(--theme-button-flat-text-color-disabled); @@ -75,6 +78,9 @@ } &:hover { opacity: 0.7; + &.isFavorite { + opacity: 1; + } } } .asset { From 1a1c4853920706d681c1682025775791af4eb469 Mon Sep 17 00:00:00 2001 From: Danilo Prates Date: Tue, 28 Sep 2021 10:57:11 +0200 Subject: [PATCH 47/60] [DDW-694] Add hooks to Func Component functions --- .../components/wallet/tokens/WalletTokens.js | 64 ++++++++++--------- .../wallet/tokens/WalletTokensList.js | 25 ++++---- 2 files changed, 48 insertions(+), 41 deletions(-) diff --git a/source/renderer/app/components/wallet/tokens/WalletTokens.js b/source/renderer/app/components/wallet/tokens/WalletTokens.js index 90c03e5ee9..925900ba50 100644 --- a/source/renderer/app/components/wallet/tokens/WalletTokens.js +++ b/source/renderer/app/components/wallet/tokens/WalletTokens.js @@ -1,5 +1,5 @@ // @flow -import React, { useState } from 'react'; +import React, { useState, useCallback, useMemo } from 'react'; import { intlShape, injectIntl, defineMessages } from 'react-intl'; import { observer } from 'mobx-react'; import styles from './WalletTokens.scss'; @@ -53,8 +53,9 @@ const WalletTokens = observer((props: Props) => { onToggleFavorite, ...listProps } = props; - const favoriteTokensList = assets.filter( - ({ uniqueId }) => tokenFavorites[uniqueId] + const favoriteTokensList = useMemo( + () => assets.filter(({ uniqueId }) => tokenFavorites[uniqueId]), + [assets, tokenFavorites] ); /** @@ -65,34 +66,37 @@ const WalletTokens = observer((props: Props) => { * preventing undesirable jumps in the tokens list * */ - const handleToggleFavorite = async ({ - uniqueId, - isFavorite, - }: { - uniqueId: string, - isFavorite: boolean, - }) => { - if (insertingAssetUniqueId || removingAssetUniqueId) { - return; - } - if (isFavorite) { - // It's removing favorite - // We need to wait for the element to be removed, before updating the favorites list - setRemovingAssetUniqueId(uniqueId); - setTimeout(async () => { + const handleToggleFavorite = useCallback( + async ({ + uniqueId, + isFavorite, + }: { + uniqueId: string, + isFavorite: boolean, + }) => { + if (insertingAssetUniqueId || removingAssetUniqueId) { + return; + } + if (isFavorite) { + // It's removing favorite + // We need to wait for the element to be removed, before updating the favorites list + setRemovingAssetUniqueId(uniqueId); + setTimeout(async () => { + await onToggleFavorite({ uniqueId, isFavorite }); + setTimeout(() => setRemovingAssetUniqueId(null), 500); + }, TOGGLE_TOKEN_FAVORITE_TIMEOUT); + } else { + // It's inserting favorite + // We update the favorites list straight away + setInsertingAssetUniqueId(uniqueId); await onToggleFavorite({ uniqueId, isFavorite }); - setTimeout(() => setRemovingAssetUniqueId(null), 500); - }, TOGGLE_TOKEN_FAVORITE_TIMEOUT); - } else { - // It's inserting favorite - // We update the favorites list straight away - setInsertingAssetUniqueId(uniqueId); - await onToggleFavorite({ uniqueId, isFavorite }); - setTimeout(() => { - setInsertingAssetUniqueId(null); - }, TOGGLE_TOKEN_FAVORITE_TIMEOUT); - } - }; + setTimeout(() => { + setInsertingAssetUniqueId(null); + }, TOGGLE_TOKEN_FAVORITE_TIMEOUT); + } + }, + [insertingAssetUniqueId, removingAssetUniqueId] + ); return (
diff --git a/source/renderer/app/components/wallet/tokens/WalletTokensList.js b/source/renderer/app/components/wallet/tokens/WalletTokensList.js index 40a3e47111..c94bec07b5 100644 --- a/source/renderer/app/components/wallet/tokens/WalletTokensList.js +++ b/source/renderer/app/components/wallet/tokens/WalletTokensList.js @@ -117,22 +117,25 @@ const WalletTokensList = observer((props: Props) => { () => getSortIconClasses('quantity', sortBy, sortDirection), [sortBy, sortDirection] ); - const toggleSortDirection = () => { + const toggleSortDirection = useCallback(() => { if (sortDirection === 'asc') { setSortDirection('desc'); } else { setSortDirection('asc'); } - }; - const onSortBy = (newSortBy: SortBy) => { - if (!hasSorting) return; - if (newSortBy === sortBy) { - toggleSortDirection(); - } else { - setSortDirection('asc'); - setSortBy(newSortBy); - } - }; + }, [sortDirection]); + const onSortBy = useCallback( + (newSortBy: SortBy) => { + if (!hasSorting) return; + if (newSortBy === sortBy) { + toggleSortDirection(); + } else { + setSortDirection('asc'); + setSortBy(newSortBy); + } + }, + [hasSorting, sortBy] + ); const onSortByToken = useCallback(() => onSortBy('token'), [ sortDirection, sortBy, From 24adfc8afc1dedab51093c6ae371f029a165e6ed Mon Sep 17 00:00:00 2001 From: Danilo Prates Date: Fri, 1 Oct 2021 15:44:47 +0200 Subject: [PATCH 48/60] [DDW-694] Wallet Summary tokens adjustments and fns docs --- .../wallet/summary/WalletSummary.js | 6 +- .../containers/wallet/WalletSummaryPage.js | 6 +- source/renderer/app/utils/assets.js | 90 ++++++++++++------- 3 files changed, 64 insertions(+), 38 deletions(-) diff --git a/source/renderer/app/components/wallet/summary/WalletSummary.js b/source/renderer/app/components/wallet/summary/WalletSummary.js index 5f921c51f8..14ff0e091f 100644 --- a/source/renderer/app/components/wallet/summary/WalletSummary.js +++ b/source/renderer/app/components/wallet/summary/WalletSummary.js @@ -13,9 +13,9 @@ import { MAX_TOKENS_ON_SUMMARY_PAGE } from '../../../config/numbersConfig'; const messages = defineMessages({ tokensListTitle: { - id: 'wallet.summary.tokensList.title', - defaultMessage: '!!!Recently used tokens', - description: 'Send button on Wallet summary assets page', + id: 'wallet.summary.assets.tokensTitle', + defaultMessage: '!!!Tokens', + description: 'Tokens title in the wallet summary', }, }); diff --git a/source/renderer/app/containers/wallet/WalletSummaryPage.js b/source/renderer/app/containers/wallet/WalletSummaryPage.js index 2b73722516..6c7a0a9281 100755 --- a/source/renderer/app/containers/wallet/WalletSummaryPage.js +++ b/source/renderer/app/containers/wallet/WalletSummaryPage.js @@ -12,7 +12,7 @@ import { ROUTES } from '../../routes-config'; import { formattedWalletAmount } from '../../utils/formatters'; import { getNetworkExplorerUrlByType } from '../../utils/network'; import { WALLET_ASSETS_ENABLED } from '../../config/walletsConfig'; -import { getAssetTokens } from '../../utils/assets'; +import { getAssetTokens, sortAssets } from '../../utils/assets'; import type { InjectedProps } from '../../types/injectedPropsType'; export const messages = defineMessages({ @@ -100,7 +100,9 @@ export default class WalletSummaryPage extends Component { const noTransactionsLabel = intl.formatMessage(messages.noTransactions); const walletTokens = wallet.assets.total; - const assetTokens = getAssetTokens(all, walletTokens); + const assetTokens = getAssetTokens(all, walletTokens).sort( + sortAssets('token', 'asc') + ); const totalRawAssets = wallet.assets.total.length; const totalAssets = assetTokens.length; const hasRawAssets = wallet.assets.total.length > 0; diff --git a/source/renderer/app/utils/assets.js b/source/renderer/app/utils/assets.js index 1423325e4f..f51d92b2d6 100644 --- a/source/renderer/app/utils/assets.js +++ b/source/renderer/app/utils/assets.js @@ -12,10 +12,15 @@ export type SortBy = 'token' | 'fingerprint' | 'quantity'; export type SortDirection = 'asc' | 'desc'; /** - * - * This function removes the `change` assets + * A few functions here use Assets and Tokens, so here is a brief difference: + * Asset - has the asset details (fingerprint, metadata, decimals, recommendedDecimals) + * Token - has a transaction's details (quantity, address) + * Both have policyId and assetName + */ + +/** + * Removes the `change` assets * that are included in the TX API response - * */ export const filterAssets = ( assets: Array, @@ -41,6 +46,13 @@ export const getZeroToken = ({ quantity: new BigNumber(0), }); +/** + * Receives an asset and a list of tokens + * Then retrieves the token with the same uniqueId + * @param asset - asset details + * @param tokens - list of Tokens + * See Asset/Token differences at the begining of this doc + */ export const getToken = (asset: Asset, tokens: Tokens) => { let token = tokens.find(({ uniqueId }) => uniqueId === asset.uniqueId); if (!token) { @@ -50,16 +62,23 @@ export const getToken = (asset: Asset, tokens: Tokens) => { }; /** - * - * This function receives a Token (the asset included in a wallet or transaction) - * and combines with the data from the Asset - * - * Data from the Token: policyId, assetName, quantity, address - * Data from the Asset: fingerprint, metadata, decimals, recommendedDecimals, uniqueId + * Receives a Token and an Asset + * then merges them into an AssetToken + * @param asset - asset details + * @param token - token details + * See Asset/Token differences at the begining of this doc */ export const getAssetToken = ( - { fingerprint, metadata, decimals, recommendedDecimals, uniqueId }: Asset, - { policyId, assetName, quantity, address }: Token + { + policyId, + assetName, + fingerprint, + metadata, + decimals, + recommendedDecimals, + uniqueId, + }: Asset, + { quantity, address }: Token ): AssetToken => ({ policyId, assetName, @@ -73,11 +92,11 @@ export const getAssetToken = ( }); /** - * - * This function receives a list of Assets - * then retrieves the Token from that specific wallet - * and sort them accordingly - * + * Receives both the Assets and the Tokens from a wallet + * then merges them into AssetTokens + * @param assets - list of asset details + * @param tokens - list of token details + * See Asset/Token differences at the begining of this doc */ export const getAssetTokens = ( assets: Array, @@ -85,18 +104,16 @@ export const getAssetTokens = ( ): Array => assets .map((asset) => getAssetToken(asset, getToken(asset, tokens))) - .filter((token) => !!token.uniqueId) - .sort(sortAssets('fingerprint', 'asc')); + .filter((token) => !!token.uniqueId); /** - * - * This function receives a Token (the asset included in a wallet or transaction) + * Receives a Token * and combines with the data from the Asset - * - * Data from the Token: policyId, assetName, quantity, address - * Data from the Asset: fingerprint, metadata, decimals, recommendedDecimals, uniqueId + * @param asset - asset details + * @param getAsset - function that returns an asset + * See Asset/Token differences at the begining of this doc */ -export const getNonZeroAssetToken = ( +export const getAssetTokenFromToken = ( asset: Token, getAsset: Function ): AssetToken => { @@ -116,22 +133,20 @@ export const getNonZeroAssetToken = ( }; }; -/** - * - * This function receives a list of Tokens (the assets included in a wallet or transaction) - * then retrieves the Assets - * and sort them accordingly - * - */ export const getNonZeroAssetTokens = ( tokens: Tokens, getAsset: Function ): Array => tokens - .map((token) => getNonZeroAssetToken(token, getAsset)) + .map((token) => getAssetTokenFromToken(token, getAsset)) .filter((token) => !!token.uniqueId) .sort(sortAssets('fingerprint', 'asc')); +/** + * High-order function for sorting assetTokens + * @param sortBy - sorting parameter + * @param sortDirection - should it sort in ascending or descending direction + */ export const sortAssets = (sortBy: SortBy, sortDirection: SortDirection) => ( asset1: AssetToken, asset2: AssetToken @@ -180,7 +195,6 @@ export const sortAssets = (sortBy: SortBy, sortDirection: SortDirection) => ( /** * Check if after the transactions your wallet has some assets left - * * @param allAvailableTokens Collection of assets in your wallet * @param initialSelectedAssets Collection of assets initially preselected * @param selectedAssets Selected assets to be send in the transaction @@ -218,6 +232,8 @@ export const hasTokensLeftAfterTransaction = ( /** * Generic function for filtering AssetTokens + * @param rawSearchValue - search value + * @param assets - AssetTokens to operate the search */ export const searchAssets = ( rawSearchValue: string, @@ -255,3 +271,11 @@ export const isTokenMissingInWallet = (wallet?: ?Wallet, token?: Token) => { export const tokenHasBalance = (token: Token, amount: BigNumber) => token.quantity.isGreaterThanOrEqualTo(amount); + +export const getUniqueId = ({ + assetName, + policyId, +}: { + assetName: string, + policyId: string, +}) => `${assetName}${policyId}`; From 3e73df795e7f2501b1296a7aa3a6a47519d2775d Mon Sep 17 00:00:00 2001 From: Danilo Prates Date: Fri, 1 Oct 2021 16:05:51 +0200 Subject: [PATCH 49/60] [DDW-694] Fix toggle sort direction --- .../renderer/app/components/wallet/tokens/WalletTokensList.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/renderer/app/components/wallet/tokens/WalletTokensList.js b/source/renderer/app/components/wallet/tokens/WalletTokensList.js index c94bec07b5..ca8f43381c 100644 --- a/source/renderer/app/components/wallet/tokens/WalletTokensList.js +++ b/source/renderer/app/components/wallet/tokens/WalletTokensList.js @@ -134,7 +134,7 @@ const WalletTokensList = observer((props: Props) => { setSortBy(newSortBy); } }, - [hasSorting, sortBy] + [sortDirection, hasSorting, sortBy] ); const onSortByToken = useCallback(() => onSortBy('token'), [ sortDirection, From bb7a2d421b6bb8a8ff63650e106229e1d7359a61 Mon Sep 17 00:00:00 2001 From: Danilo Prates Date: Fri, 1 Oct 2021 17:07:31 +0200 Subject: [PATCH 50/60] [DDW-694] Restoring state for the Tokens tab --- .../components/wallet/send-form/messages.js | 2 +- .../components/wallet/tokens/WalletTokens.js | 21 +++++++++++++++++++ .../wallet/tokens/WalletTokens.scss | 11 ++++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/source/renderer/app/components/wallet/send-form/messages.js b/source/renderer/app/components/wallet/send-form/messages.js index 071021dcb1..a70240d409 100644 --- a/source/renderer/app/components/wallet/send-form/messages.js +++ b/source/renderer/app/components/wallet/send-form/messages.js @@ -122,7 +122,7 @@ export default defineMessages({ syncingTransactionsMessage: { id: 'wallet.send.form.syncingTransactionsMessage', defaultMessage: - '!!!This wallet is currently being synced with the blockchain. While synchronisation is in progress transacting is not possible and transaction history is not complete.', + '!!!The balance and transaction history of this wallet is being synced with the blockchain.', description: 'Syncing transactions message shown during async wallet restore in the wallet send form.', }, diff --git a/source/renderer/app/components/wallet/tokens/WalletTokens.js b/source/renderer/app/components/wallet/tokens/WalletTokens.js index 925900ba50..fd61bab559 100644 --- a/source/renderer/app/components/wallet/tokens/WalletTokens.js +++ b/source/renderer/app/components/wallet/tokens/WalletTokens.js @@ -6,6 +6,7 @@ import styles from './WalletTokens.scss'; import Wallet from '../../../domains/Wallet'; import WalletTokensList from './WalletTokensList'; import WalletTokensSearch from './WalletTokensSearch'; +import LoadingSpinner from '../../widgets/LoadingSpinner'; import type { AssetToken } from '../../../api/assets/types'; import { TOGGLE_TOKEN_FAVORITE_TIMEOUT } from '../../../config/timingConfig'; @@ -20,6 +21,13 @@ const messages = defineMessages({ defaultMessage: '!!!Tokens', description: 'Favorites list title label', }, + syncingMessage: { + id: 'wallet.send.form.syncingTransactionsMessage', + defaultMessage: + '!!!The balance and transaction history of this wallet is being synced with the blockchain.', + description: + 'Syncing transactions message shown during async wallet restore in the wallet send form.', + }, }); type Props = { @@ -51,8 +59,10 @@ const WalletTokens = observer((props: Props) => { intl, tokenFavorites, onToggleFavorite, + isLoadingAssets, ...listProps } = props; + const { isRestoring } = props.wallet; const favoriteTokensList = useMemo( () => assets.filter(({ uniqueId }) => tokenFavorites[uniqueId]), [assets, tokenFavorites] @@ -98,6 +108,17 @@ const WalletTokens = observer((props: Props) => { [insertingAssetUniqueId, removingAssetUniqueId] ); + if (isRestoring) { + return ( +
+ +

+ {intl.formatMessage(messages.syncingMessage)} +

+
+ ); + } + return (
diff --git a/source/renderer/app/components/wallet/tokens/WalletTokens.scss b/source/renderer/app/components/wallet/tokens/WalletTokens.scss index d2d5dea8a3..413f676e6c 100644 --- a/source/renderer/app/components/wallet/tokens/WalletTokens.scss +++ b/source/renderer/app/components/wallet/tokens/WalletTokens.scss @@ -1,3 +1,14 @@ .component { padding-bottom: 20px; } +.syncing { + padding: 10px 20px; + .syncingText { + color: var(--theme-transactions-list-group-date-color); + font-family: var(--font-regular); + font-size: 16px; + line-height: 1.38; + opacity: 0.5; + text-align: center; + } +} From 06afac67ce0c0649e1c828f51d83106715584e9b Mon Sep 17 00:00:00 2001 From: Danilo Prates Date: Fri, 1 Oct 2021 17:19:31 +0200 Subject: [PATCH 51/60] [DDW-694] Fix search not working --- source/renderer/app/components/wallet/tokens/WalletTokens.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/renderer/app/components/wallet/tokens/WalletTokens.js b/source/renderer/app/components/wallet/tokens/WalletTokens.js index fd61bab559..126f252392 100644 --- a/source/renderer/app/components/wallet/tokens/WalletTokens.js +++ b/source/renderer/app/components/wallet/tokens/WalletTokens.js @@ -65,7 +65,7 @@ const WalletTokens = observer((props: Props) => { const { isRestoring } = props.wallet; const favoriteTokensList = useMemo( () => assets.filter(({ uniqueId }) => tokenFavorites[uniqueId]), - [assets, tokenFavorites] + [assets, tokenFavorites, searchValue] ); /** @@ -131,6 +131,7 @@ const WalletTokens = observer((props: Props) => { removingAssetUniqueId={removingAssetUniqueId} onToggleFavorite={handleToggleFavorite} tokenFavorites={tokenFavorites} + searchValue={searchValue} /> )} { title={intl.formatMessage(messages.tokensListTitle)} onToggleFavorite={handleToggleFavorite} tokenFavorites={tokenFavorites} + searchValue={searchValue} />
); From 119c8bbcf263999f9e4f896e2c94a164b2abf411 Mon Sep 17 00:00:00 2001 From: Danilo Prates Date: Mon, 4 Oct 2021 11:44:46 +0200 Subject: [PATCH 52/60] [DDW-694] Styling adjustments --- .../app/components/wallet/tokens/WalletTokensList.scss | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/renderer/app/components/wallet/tokens/WalletTokensList.scss b/source/renderer/app/components/wallet/tokens/WalletTokensList.scss index 49e8d11da9..c12c663311 100644 --- a/source/renderer/app/components/wallet/tokens/WalletTokensList.scss +++ b/source/renderer/app/components/wallet/tokens/WalletTokensList.scss @@ -1,15 +1,15 @@ .component { margin: 0 20px 20px; - text-align: center; &:last-of-type { margin-bottom: 0; } button.viewAllButton { + display: flex; font-size: 14px; height: 36px; line-height: 19px; - margin-top: 20px; - padding: 0 40px; + margin: 20px auto 0; + padding: 7px 40px 0; text-align: center; width: auto; } From d7d4e9a1dc1839984fa58a0976756ece3f5ef16f Mon Sep 17 00:00:00 2001 From: Danilo Prates Date: Mon, 4 Oct 2021 11:50:23 +0200 Subject: [PATCH 53/60] [DDW-694] Disable send when token has zero balance --- .../app/components/wallet/tokens/WalletToken.js | 1 + .../components/wallet/tokens/WalletToken.scss | 3 +++ .../wallets/tokens/WalletTokens.stories.js | 17 +++++++++++++++++ 3 files changed, 21 insertions(+) diff --git a/source/renderer/app/components/wallet/tokens/WalletToken.js b/source/renderer/app/components/wallet/tokens/WalletToken.js index d5e1615bb3..522522cbb0 100644 --- a/source/renderer/app/components/wallet/tokens/WalletToken.js +++ b/source/renderer/app/components/wallet/tokens/WalletToken.js @@ -202,6 +202,7 @@ const WalletToken = observer((props: Props) => { ])} onClick={() => onOpenAssetSend(asset)} label={intl.formatMessage(messages.tokenSendButton)} + disabled={asset.quantity.isZero()} />
); diff --git a/source/renderer/app/components/wallet/tokens/WalletToken.scss b/source/renderer/app/components/wallet/tokens/WalletToken.scss index a9ef61e5b8..83013925a9 100644 --- a/source/renderer/app/components/wallet/tokens/WalletToken.scss +++ b/source/renderer/app/components/wallet/tokens/WalletToken.scss @@ -182,6 +182,9 @@ height: 36px; margin-left: 12px; width: 120px; + &.disabled { + opacity: 0.4; + } } .settingsButton { svg { diff --git a/storybook/stories/wallets/tokens/WalletTokens.stories.js b/storybook/stories/wallets/tokens/WalletTokens.stories.js index f5d76c343c..6ce9ce196f 100644 --- a/storybook/stories/wallets/tokens/WalletTokens.stories.js +++ b/storybook/stories/wallets/tokens/WalletTokens.stories.js @@ -41,6 +41,23 @@ const assets = [ 'tokenb0ca20391caaf66a4d4d7897d281f9c136cd3513136945b2342', 400 ), + generateAssetToken( + '65bc72542b0ca20391caaf66a4d4d7897e291f9c136cd3513136945c', + '', + 'tokenb0ca20391caaf66a4d4d7897d281f9c136cd3513136945b2341', + 0, + { + name: 'Nope', + ticker: 'NOPE', + description: 'The one with zero balance', + unit: { + name: 'NOPE', + decimals: 0, + }, + url: 'http://example.com', + logo: '', + } + ), generateAssetToken( '65ac82542b0ca20391caaf66a4d4d7897d281f9c136cd3513136945b', '', From baf72649d6aa12bfb19ee427a7c978c1673c112c Mon Sep 17 00:00:00 2001 From: Danilo Prates Date: Mon, 4 Oct 2021 12:27:22 +0200 Subject: [PATCH 54/60] [DDW-694] No Tokens scenario in the Tokens tab --- .../wallet/summary/WalletSummary.js | 42 +++++++------------ .../WalletNoTokens.js} | 2 +- .../wallet/tokens/WalletNoTokens.scss | 37 ++++++++++++++++ .../components/wallet/tokens/WalletTokens.js | 22 ++++++---- .../wallet/tokens/WalletTokens.scss | 2 +- .../wallet/tokens/WalletTokensList.js | 13 ++++++ .../wallet/tokens/WalletTokensSearch.scss | 2 +- .../app/containers/wallet/WalletTokensPage.js | 5 ++- .../wallets/tokens/WalletTokens.stories.js | 2 +- .../tokens/WalletTokensList.stories.js | 2 +- 10 files changed, 87 insertions(+), 42 deletions(-) rename source/renderer/app/components/wallet/{summary/WalletSummaryNoTokens.js => tokens/WalletNoTokens.js} (98%) create mode 100644 source/renderer/app/components/wallet/tokens/WalletNoTokens.scss diff --git a/source/renderer/app/components/wallet/summary/WalletSummary.js b/source/renderer/app/components/wallet/summary/WalletSummary.js index 14ff0e091f..bb0592754b 100644 --- a/source/renderer/app/components/wallet/summary/WalletSummary.js +++ b/source/renderer/app/components/wallet/summary/WalletSummary.js @@ -7,7 +7,6 @@ import type { Currency } from '../../../types/currencyTypes'; import WalletSummaryHeader from './WalletSummaryHeader'; import WalletSummaryCurrency from './WalletSummaryCurrency'; import type { AssetToken } from '../../../api/assets/types'; -import WalletSummaryNoTokens from './WalletSummaryNoTokens'; import WalletTokensList from '../tokens/WalletTokensList'; import { MAX_TOKENS_ON_SUMMARY_PAGE } from '../../../config/numbersConfig'; @@ -78,7 +77,6 @@ export default class WalletSummary extends Component { const { intl } = this.context; const { isRestoring } = wallet; - const hasAssets = assets.length || isLoadingAssets; return ( <> @@ -103,31 +101,21 @@ export default class WalletSummary extends Component { } /> {!isRestoring && ( - <> - {hasAssets ? ( - - ) : ( - - )} - + )} ); diff --git a/source/renderer/app/components/wallet/summary/WalletSummaryNoTokens.js b/source/renderer/app/components/wallet/tokens/WalletNoTokens.js similarity index 98% rename from source/renderer/app/components/wallet/summary/WalletSummaryNoTokens.js rename to source/renderer/app/components/wallet/tokens/WalletNoTokens.js index 1539dc5c7f..e5633acbac 100644 --- a/source/renderer/app/components/wallet/summary/WalletSummaryNoTokens.js +++ b/source/renderer/app/components/wallet/tokens/WalletNoTokens.js @@ -5,7 +5,7 @@ import { defineMessages, intlShape } from 'react-intl'; import { ButtonSkin } from 'react-polymorph/lib/skins/simple/ButtonSkin'; import classnames from 'classnames'; import BorderedBox from '../../widgets/BorderedBox'; -import styles from './WalletSummaryNoTokens.scss'; +import styles from './WalletNoTokens.scss'; import ButtonLink from '../../widgets/ButtonLink'; const messages = defineMessages({ diff --git a/source/renderer/app/components/wallet/tokens/WalletNoTokens.scss b/source/renderer/app/components/wallet/tokens/WalletNoTokens.scss new file mode 100644 index 0000000000..05d5a8316c --- /dev/null +++ b/source/renderer/app/components/wallet/tokens/WalletNoTokens.scss @@ -0,0 +1,37 @@ +@import '../../../themes/mixins/animations'; + +.numberOfAssets { + color: var(--theme-transactions-list-group-date-color); + font-family: var(--font-regular); + font-size: 16px; + margin-bottom: -10px; + opacity: 0.5; + padding: 0 20px 0 40px; +} + +.component { + padding: 20px 20px; + + .noTokensContainer { + align-items: center; + display: flex; + justify-content: space-between; + + .noTokensLeftContainer { + p { + color: var(--theme-bordered-box-text-color); + font-family: var(--font-light); + font-size: 16px; + line-height: 1.38; + } + } + + .noTokensRightContainer { + .noTokensLearnMoreLinkUrl { + font-family: var(--font-medium); + height: 36px; + width: 160px; + } + } + } +} diff --git a/source/renderer/app/components/wallet/tokens/WalletTokens.js b/source/renderer/app/components/wallet/tokens/WalletTokens.js index 126f252392..f9483acb65 100644 --- a/source/renderer/app/components/wallet/tokens/WalletTokens.js +++ b/source/renderer/app/components/wallet/tokens/WalletTokens.js @@ -38,15 +38,15 @@ type Props = { isLoadingAssets: boolean, onAssetSettings: Function, onCopyAssetParam: Function, + onExternalLinkClick: Function, onOpenAssetSend: Function, onToggleFavorite: Function, tokenFavorites: Object, wallet: Wallet, }; -type SearchValue = string; const WalletTokens = observer((props: Props) => { - const [searchValue, setSearchValue] = useState(''); + const [searchValue, setSearchValue] = useState(''); const [insertingAssetUniqueId, setInsertingAssetUniqueId] = useState( null ); @@ -63,6 +63,7 @@ const WalletTokens = observer((props: Props) => { ...listProps } = props; const { isRestoring } = props.wallet; + const hasTokens = assets.length || isLoadingAssets; const favoriteTokensList = useMemo( () => assets.filter(({ uniqueId }) => tokenFavorites[uniqueId]), [assets, tokenFavorites, searchValue] @@ -121,26 +122,31 @@ const WalletTokens = observer((props: Props) => { return (
- + {hasTokens && ( + + )} {!!favoriteTokensList.length && ( )}
); diff --git a/source/renderer/app/components/wallet/tokens/WalletTokens.scss b/source/renderer/app/components/wallet/tokens/WalletTokens.scss index 413f676e6c..44c23718b3 100644 --- a/source/renderer/app/components/wallet/tokens/WalletTokens.scss +++ b/source/renderer/app/components/wallet/tokens/WalletTokens.scss @@ -1,5 +1,5 @@ .component { - padding-bottom: 20px; + padding: 20px 0; } .syncing { padding: 10px 20px; diff --git a/source/renderer/app/components/wallet/tokens/WalletTokensList.js b/source/renderer/app/components/wallet/tokens/WalletTokensList.js index ca8f43381c..0f849fb5cf 100644 --- a/source/renderer/app/components/wallet/tokens/WalletTokensList.js +++ b/source/renderer/app/components/wallet/tokens/WalletTokensList.js @@ -11,6 +11,7 @@ import Wallet from '../../../domains/Wallet'; import BorderedBox from '../../widgets/BorderedBox'; import LoadingSpinner from '../../widgets/LoadingSpinner'; import WalletToken from './WalletToken'; +import WalletNoTokens from './WalletNoTokens'; import sortIcon from '../../../assets/images/ascending.inline.svg'; import type { AssetToken } from '../../../api/assets/types'; import type { SortBy, SortDirection } from '../../../utils/assets'; @@ -52,6 +53,7 @@ type Props = { isLoadingAssets: boolean, onAssetSettings: Function, onCopyAssetParam: Function, + onExternalLinkClick: Function, onOpenAssetSend: Function, onToggleFavorite: Function, onViewAllButtonClick?: Function, @@ -86,6 +88,7 @@ const WalletTokensList = observer((props: Props) => { isLoadingAssets, onAssetSettings, onCopyAssetParam, + onExternalLinkClick, onOpenAssetSend, onToggleFavorite, onViewAllButtonClick, @@ -146,6 +149,16 @@ const WalletTokensList = observer((props: Props) => { sortBy, hasSorting, ]); + const hasTokens = assets.length || isLoadingAssets; + + if (!hasTokens) + return ( + + ); let content; if (isLoadingAssets) { diff --git a/source/renderer/app/components/wallet/tokens/WalletTokensSearch.scss b/source/renderer/app/components/wallet/tokens/WalletTokensSearch.scss index 80bc670672..e6f74aa291 100644 --- a/source/renderer/app/components/wallet/tokens/WalletTokensSearch.scss +++ b/source/renderer/app/components/wallet/tokens/WalletTokensSearch.scss @@ -1,5 +1,5 @@ .component { - margin: 20px; + margin: 0 20px 20px; position: relative; .searchIcon { left: 20px; diff --git a/source/renderer/app/containers/wallet/WalletTokensPage.js b/source/renderer/app/containers/wallet/WalletTokensPage.js index 8061f8e8e1..2c5156c82d 100644 --- a/source/renderer/app/containers/wallet/WalletTokensPage.js +++ b/source/renderer/app/containers/wallet/WalletTokensPage.js @@ -13,7 +13,7 @@ const WalletTokensPage = inject( )( observer((props: Props) => { const { actions, stores } = props; - const { assets, profile, wallets } = stores; + const { assets, profile, wallets, app } = stores; const { all, assetSettingsDialogWasOpened, @@ -42,7 +42,7 @@ const WalletTokensPage = inject( return ( diff --git a/storybook/stories/wallets/tokens/WalletTokens.stories.js b/storybook/stories/wallets/tokens/WalletTokens.stories.js index 6ce9ce196f..27011a63f9 100644 --- a/storybook/stories/wallets/tokens/WalletTokens.stories.js +++ b/storybook/stories/wallets/tokens/WalletTokens.stories.js @@ -166,7 +166,7 @@ storiesOf('Wallets|Tokens', module) 'WalletTokens', withState({ favorites: {} }, (store) => ( ( Date: Mon, 4 Oct 2021 12:54:20 +0200 Subject: [PATCH 55/60] [DDW-694] No Tokens scenario in the Tokens tab - fix typo --- source/renderer/app/containers/wallet/WalletTokensPage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/renderer/app/containers/wallet/WalletTokensPage.js b/source/renderer/app/containers/wallet/WalletTokensPage.js index 2c5156c82d..0be3c15ca9 100644 --- a/source/renderer/app/containers/wallet/WalletTokensPage.js +++ b/source/renderer/app/containers/wallet/WalletTokensPage.js @@ -42,7 +42,7 @@ const WalletTokensPage = inject( return ( Date: Tue, 5 Oct 2021 11:38:35 +0200 Subject: [PATCH 56/60] [DDW-694] Remove zero tokens from the scope --- source/renderer/app/utils/assets.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/renderer/app/utils/assets.js b/source/renderer/app/utils/assets.js index f51d92b2d6..2087a2fe14 100644 --- a/source/renderer/app/utils/assets.js +++ b/source/renderer/app/utils/assets.js @@ -104,7 +104,9 @@ export const getAssetTokens = ( ): Array => assets .map((asset) => getAssetToken(asset, getToken(asset, tokens))) - .filter((token) => !!token.uniqueId); + .filter((token) => !!token.uniqueId) + // @TOKEN TODO - Remove this filter once we can list zero tokens + .filter((token) => !token.quantity.isZero()); /** * Receives a Token From 910344b2ee47b8943e1df5eba64f9501f47c5a0a Mon Sep 17 00:00:00 2001 From: Danilo Prates Date: Wed, 6 Oct 2021 13:29:46 +0200 Subject: [PATCH 57/60] [DDW-694] Sort qtd with formatted amount --- source/renderer/app/api/assets/types.js | 2 +- source/renderer/app/utils/assets.js | 9 +++++++-- source/renderer/app/utils/formatters.js | 19 +++++++++++++------ .../tokens/WalletTokensList.stories.js | 12 ++++++++++++ 4 files changed, 33 insertions(+), 9 deletions(-) diff --git a/source/renderer/app/api/assets/types.js b/source/renderer/app/api/assets/types.js index 2a8461f6cc..3bc326a77d 100644 --- a/source/renderer/app/api/assets/types.js +++ b/source/renderer/app/api/assets/types.js @@ -77,8 +77,8 @@ export type AssetToken = { export type AssetMetadata = { name: string, - ticker: string, description: string, + ticker?: string, decimals?: number, // [0 .. 255] url?: string, logo?: string, diff --git a/source/renderer/app/utils/assets.js b/source/renderer/app/utils/assets.js index 2087a2fe14..96e27387c2 100644 --- a/source/renderer/app/utils/assets.js +++ b/source/renderer/app/utils/assets.js @@ -7,6 +7,7 @@ import Asset from '../domains/Asset'; import type { Token, Tokens, AssetToken } from '../api/assets/types'; import { TransactionTypes } from '../domains/WalletTransaction'; import type { TransactionType } from '../api/transactions/types'; +import { formattedTokenDecimals } from './formatters'; export type SortBy = 'token' | 'fingerprint' | 'quantity'; export type SortDirection = 'asc' | 'desc'; @@ -154,16 +155,20 @@ export const sortAssets = (sortBy: SortBy, sortDirection: SortDirection) => ( asset2: AssetToken ) => { const { - quantity: quantity1, + quantity: unformattedQuantity1, fingerprint: fingerprint1, metadata: metadata1, + decimals: decimals1, } = asset1; + const quantity1 = formattedTokenDecimals(unformattedQuantity1, decimals1); const { name: name1 } = metadata1 || {}; const { - quantity: quantity2, + quantity: unformattedQuantity2, fingerprint: fingerprint2, metadata: metadata2, + decimals: decimals2, } = asset2; + const quantity2 = formattedTokenDecimals(unformattedQuantity2, decimals2); const { name: name2 } = metadata2 || {}; if (sortBy === 'token') { if (name1 && !name2) return -1; diff --git a/source/renderer/app/utils/formatters.js b/source/renderer/app/utils/formatters.js index ed49080155..9f13dfe898 100644 --- a/source/renderer/app/utils/formatters.js +++ b/source/renderer/app/utils/formatters.js @@ -49,12 +49,7 @@ export const formattedTokenWalletAmount = ( isShort?: boolean ): string => { const { ticker } = metadata || {}; - const decimalPrecision = decimals || DEFAULT_DECIMAL_PRECISION; - const divider = parseInt( - getMultiplierFromDecimalPlaces(decimalPrecision), - 10 - ); - let formattedAmount = amount.dividedBy(divider); + let formattedAmount = formattedTokenDecimals(amount, decimals); if (isShort) { if (formattedAmount.isGreaterThanOrEqualTo(1000)) { /* @@ -86,6 +81,18 @@ export const formattedTokenWalletAmount = ( return formattedAmount; }; +export const formattedTokenDecimals = ( + amount: BigNumber, + decimals: ?number +): BigNumber => { + const decimalPrecision = decimals || DEFAULT_DECIMAL_PRECISION; + const divider = parseInt( + getMultiplierFromDecimalPlaces(decimalPrecision), + 10 + ); + return amount.dividedBy(divider); +}; + // Symbol Name Scientific Notation // K Thousand 1.00E+03 // M Million 1.00E+06 diff --git a/storybook/stories/wallets/tokens/WalletTokensList.stories.js b/storybook/stories/wallets/tokens/WalletTokensList.stories.js index 78677755be..bd0e92ec3d 100644 --- a/storybook/stories/wallets/tokens/WalletTokensList.stories.js +++ b/storybook/stories/wallets/tokens/WalletTokensList.stories.js @@ -76,6 +76,18 @@ const assets = [ logo: '', } ), + generateAssetToken( + '65bc72542b0ca20391caaf66a4d4d7s97d281f9c136cd3513136945b', + '', + 'tokenb0ca20391caaf66aad4e7897d282f9c136cd3513136945c2542', + 500, + { + name: 'Little', + ticker: 'LTTL', + description: '', + }, + 4 + ), ]; const walletTokens: WalletTokens = { From 479476f5709be681e0cbcfa695ea0bb48a5889a9 Mon Sep 17 00:00:00 2001 From: Danilo Prates Date: Wed, 6 Oct 2021 13:34:52 +0200 Subject: [PATCH 58/60] [DDW-694] Fix CHANGELOG --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cf026c4165..5b6e8a769e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## vNext +### Features + +- Implemented the wallet Tokens dedicated screen ([PR 2671](https://github.com/input-output-hk/daedalus/pull/2671)) + ### Chores - Added the possibility to unpair a hardware wallet from Daedalus ([PR 2676](https://github.com/input-output-hk/daedalus/pull/2676)) @@ -10,7 +14,6 @@ ### Features -- Implemented the wallet Tokens dedicated screen ([PR 2671](https://github.com/input-output-hk/daedalus/pull/2671)) - Implemented static screens for signing dApp interaction transactions ([PR 2626](https://github.com/input-output-hk/daedalus/pull/2626)) ### Fixes From 68e78fcbfbf7ec736fe69736fecf03ef6f141327 Mon Sep 17 00:00:00 2001 From: Danilo Prates Date: Wed, 6 Oct 2021 13:41:51 +0200 Subject: [PATCH 59/60] [DDW-694] Proper flow typing --- source/renderer/app/api/utils/localStorage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/renderer/app/api/utils/localStorage.js b/source/renderer/app/api/utils/localStorage.js index de97be3915..1245aee667 100644 --- a/source/renderer/app/api/utils/localStorage.js +++ b/source/renderer/app/api/utils/localStorage.js @@ -327,7 +327,7 @@ export default class LocalStorageApi { unsetAppUpdateCompleted = (): Promise => LocalStorageApi.unset(keys.APP_UPDATE_COMPLETED); - getWalletTokenFavorites = (): Promise => + getWalletTokenFavorites = (): Promise<{ [key: string]: boolean }> => LocalStorageApi.get(keys.TOKEN_FAVORITES, {}); toggleWalletTokenFavorite = async ( From 3fb7d980e50826dccc40022212bb52cd5bffd0e5 Mon Sep 17 00:00:00 2001 From: Danilo Prates Date: Fri, 8 Oct 2021 12:01:26 +0200 Subject: [PATCH 60/60] [DDW-694] useMemo in main content functions --- .../components/wallet/tokens/WalletToken.js | 54 +++++++++++-------- 1 file changed, 32 insertions(+), 22 deletions(-) diff --git a/source/renderer/app/components/wallet/tokens/WalletToken.js b/source/renderer/app/components/wallet/tokens/WalletToken.js index 522522cbb0..e81f59c103 100644 --- a/source/renderer/app/components/wallet/tokens/WalletToken.js +++ b/source/renderer/app/components/wallet/tokens/WalletToken.js @@ -1,5 +1,5 @@ // @flow -import React, { useState } from 'react'; +import React, { useState, useMemo } from 'react'; import { observer } from 'mobx-react'; import { defineMessages, intlShape, injectIntl } from 'react-intl'; import { Button } from 'react-polymorph/lib/components/Button'; @@ -76,16 +76,20 @@ const WalletToken = observer((props: Props) => { props.isFavorite ? styles.isFavorite : null, ]); - const header = () => { - const { - anyAssetWasHovered, - asset, - assetSettingsDialogWasOpened, - isFavorite, - isLoading, - onCopyAssetParam, - onToggleFavorite, - } = props; + const { + anyAssetWasHovered, + asset, + assetSettingsDialogWasOpened, + intl, + isFavorite, + isLoading, + onAssetSettings, + onCopyAssetParam, + onOpenAssetSend, + onToggleFavorite, + } = props; + + const header = useMemo(() => { const { decimals, recommendedDecimals, uniqueId } = asset; const arrowStyles = classNames(styles.arrow, { [styles.isExpanded]: isExpanded, @@ -128,10 +132,17 @@ const WalletToken = observer((props: Props) => { ); - }; + }, [ + anyAssetWasHovered, + asset, + assetSettingsDialogWasOpened, + isFavorite, + isLoading, + onCopyAssetParam, + onToggleFavorite, + ]); - const footer = () => { - const { asset, isLoading, intl } = props; + const footer = useMemo(() => { return (
@@ -147,13 +158,12 @@ const WalletToken = observer((props: Props) => { />
- {buttons()} + {buttons}
); - }; + }, [asset, isLoading, intl]); - const buttons = () => { - const { asset, onOpenAssetSend, onAssetSettings, intl } = props; + const buttons = useMemo(() => { const { recommendedDecimals, decimals } = asset; const hasWarning = typeof recommendedDecimals === 'number' && @@ -206,9 +216,9 @@ const WalletToken = observer((props: Props) => { /> ); - }; + }, [asset, onOpenAssetSend, onAssetSettings, intl]); - const { asset, onCopyAssetParam, isInsertingAsset, isRemovingAsset } = props; + const { isInsertingAsset, isRemovingAsset } = props; const componentStyles = classNames(styles.component, { [styles.isExpanded]: isExpanded, [styles.inserting]: isInsertingAsset, @@ -216,14 +226,14 @@ const WalletToken = observer((props: Props) => { }); return (
- {header()} + {header}
- {footer()} + {footer}
);