From bbad65781a689dd60d8b99d0a92b6187b7ccf5c7 Mon Sep 17 00:00:00 2001 From: Paul Ccari Date: Wed, 22 Dec 2021 01:32:06 -0500 Subject: [PATCH 001/153] fix tab layout and add reward history ui --- .../dashboard-revamp/EpochProgressCard.js | 2 +- .../dashboard-revamp/RewardHistoryTab.js | 52 +++++++++++++++++++ .../staking/dashboard-revamp/StakingTabs.js | 19 ++++--- .../containers/wallet/staking/StakingPage.js | 1 + 4 files changed, 66 insertions(+), 8 deletions(-) create mode 100644 packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/RewardHistoryTab.js diff --git a/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/EpochProgressCard.js b/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/EpochProgressCard.js index 48f3285f9b..24da28b28b 100644 --- a/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/EpochProgressCard.js +++ b/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/EpochProgressCard.js @@ -22,7 +22,7 @@ export function EpochProgressCard({ return ( - + diff --git a/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/RewardHistoryTab.js b/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/RewardHistoryTab.js new file mode 100644 index 0000000000..392cbf1362 --- /dev/null +++ b/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/RewardHistoryTab.js @@ -0,0 +1,52 @@ +// @flow +import type { Node } from 'react'; +import { Box } from '@mui/system'; +import { Stack, Typography } from '@mui/material'; + +type Props = {||}; + +function HistoryRow() { + return ( + + + Received + + 23 Jul, 11:30pm + + + + 100101010.212 ADA + + ); +} + +function RewardHistoryTab(props: Props): Node { + return ( + + + Open reward list + + + + Stake Pool + Avatar - Emurgo [Emrugo] + + + + + + + + + + + + ); +} +export default RewardHistoryTab; diff --git a/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/StakingTabs.js b/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/StakingTabs.js index b63b6dd6d6..464098cefb 100644 --- a/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/StakingTabs.js +++ b/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/StakingTabs.js @@ -2,7 +2,7 @@ import type { ComponentType, Node } from 'react'; import { useState } from 'react'; import { Box, styled } from '@mui/system'; -import { TabContext, TabList, TabPanel } from '@mui/lab'; +import { TabContext, TabList, TabPanel as TabPanelBase } from '@mui/lab'; import { IconButton, Tab, Typography } from '@mui/material'; import { observer } from 'mobx-react'; import InfoIconSVG from '../../../../assets/images/info-icon.inline.svg'; @@ -13,6 +13,7 @@ import type { $npm$ReactIntl$IntlShape } from 'react-intl'; import globalMessages from '../../../../i18n/global-messages'; import type { PoolData } from '../../../../containers/wallet/staking/SeizaFetcher'; import { EpochProgressCard } from './EpochProgressCard'; +import RewardHistoryTab from './RewardHistoryTab'; type Props = {| delegatedPool: PoolData, @@ -46,7 +47,6 @@ function StakingTabs({ delegatedPool, undelegate, epochProgress, intl }: Props & { id: 0, label: intl.formatMessage(globalMessages.stakePoolDelegated), - disabled: false, component: ( @@ -59,13 +59,11 @@ function StakingTabs({ delegatedPool, undelegate, epochProgress, intl }: Props & { id: 1, label: 'Reward History', - disabled: true, - component: TODO: Reward History!, + component: , }, { id: 2, label: 'Epoch progress', - disabled: false, component: ( - {tabs.map(({ label, id, disabled }) => ( - + {tabs.map(({ label, id }) => ( + ))} @@ -104,6 +102,9 @@ const Card = styled(Box)({ borderRadius: '8px', flex: '1 1 48.5%', maxWidth: '48.5%', + display: 'flex', + flexDirection: 'column', + height: '100%', }); const StyledTab = styled(Tab)({ @@ -130,6 +131,10 @@ function StakePoolAlert({ message }: {| message: string |}): Node { ); } +const TabPanel = styled(TabPanelBase)({ + flex: 'auto', + overflow: 'auto', +}); const StyledBox = styled(Box)({ display: 'flex', background: 'var(--yoroi-palette-gray-50)', diff --git a/packages/yoroi-extension/app/containers/wallet/staking/StakingPage.js b/packages/yoroi-extension/app/containers/wallet/staking/StakingPage.js index 7fd434d372..621e43b2e1 100644 --- a/packages/yoroi-extension/app/containers/wallet/staking/StakingPage.js +++ b/packages/yoroi-extension/app/containers/wallet/staking/StakingPage.js @@ -633,4 +633,5 @@ const WrapperCards = styled(Box)({ display: 'flex', justifyContent: 'space-between', marginBottom: '40px', + height: '412px', }); From d41e64b6f461271cc2e43a77e4c43620ec4e9ec9 Mon Sep 17 00:00:00 2001 From: Paul Ccari Date: Wed, 22 Dec 2021 17:33:16 -0500 Subject: [PATCH 002/153] unify getAvatarFromPoolId fn --- .../staking/dashboard-revamp/DelegatedStakePoolCard.js | 5 ++--- .../yoroi-extension/app/components/wallet/staking/utils.js | 7 +++++++ 2 files changed, 9 insertions(+), 3 deletions(-) create mode 100644 packages/yoroi-extension/app/components/wallet/staking/utils.js diff --git a/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/DelegatedStakePoolCard.js b/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/DelegatedStakePoolCard.js index 8e95fbd820..8ef4c1bb87 100644 --- a/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/DelegatedStakePoolCard.js +++ b/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/DelegatedStakePoolCard.js @@ -2,13 +2,13 @@ import type { ComponentType, Node } from 'react'; import { Box, styled } from '@mui/system'; import { Button, Typography } from '@mui/material'; -import { toSvg } from 'jdenticon'; import { injectIntl } from 'react-intl'; import { observer } from 'mobx-react'; import type { $npm$ReactIntl$IntlShape } from 'react-intl'; import globalMessages from '../../../../i18n/global-messages'; import { HelperTooltip, SocialMediaStakePool } from './StakePool/StakePool'; import type { PoolData } from '../../../../containers/wallet/staking/SeizaFetcher'; +import { getAvatarFromPoolId } from '../utils'; type Props = {| delegatedPool: PoolData, @@ -21,8 +21,7 @@ type Intl = {| function DelegatedStakePoolCard({ delegatedPool, undelegate, intl }: Props & Intl): Node { const { id, name, avatar, roa, socialLinks, websiteUrl } = delegatedPool || {}; - const avatarSource = toSvg(id, 36, { padding: 0 }); - const avatarGenerated = `data:image/svg+xml;utf8,${encodeURIComponent(avatarSource)}`; + const avatarGenerated = getAvatarFromPoolId(id); return ( diff --git a/packages/yoroi-extension/app/components/wallet/staking/utils.js b/packages/yoroi-extension/app/components/wallet/staking/utils.js new file mode 100644 index 0000000000..7a6363596a --- /dev/null +++ b/packages/yoroi-extension/app/components/wallet/staking/utils.js @@ -0,0 +1,7 @@ +// @flow +import { toSvg } from 'jdenticon'; + +export const getAvatarFromPoolId = (id: string): string => { + const avatarSource = toSvg(id, 36, { padding: 0 }); + return `data:image/svg+xml;utf8,${encodeURIComponent(avatarSource)}`; +}; From f0d43a8b437ce64c3e92ac6cbf8fcfdbb428887d Mon Sep 17 00:00:00 2001 From: Paul Ccari Date: Wed, 22 Dec 2021 17:33:52 -0500 Subject: [PATCH 003/153] add reward history ui with placeholders --- .../dashboard-revamp/RewardHistoryDialog.js | 46 +++++++ .../dashboard-revamp/RewardHistoryTab.js | 121 +++++++++++++----- .../staking/dashboard-revamp/StakingTabs.js | 23 +++- .../containers/wallet/staking/StakingPage.js | 86 ++++++++++++- .../app/i18n/global-messages.js | 12 ++ 5 files changed, 250 insertions(+), 38 deletions(-) create mode 100644 packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/RewardHistoryDialog.js diff --git a/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/RewardHistoryDialog.js b/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/RewardHistoryDialog.js new file mode 100644 index 0000000000..05f21b67cb --- /dev/null +++ b/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/RewardHistoryDialog.js @@ -0,0 +1,46 @@ +// @flow +import type { Node, ComponentType } from 'react'; +import { observer } from 'mobx-react'; +import globalMessages from '../../../../i18n/global-messages'; +import DialogCloseButton from '../../../widgets/DialogCloseButton'; +import { Typography } from '@mui/material'; +import Dialog from '../../../widgets/Dialog'; +import { injectIntl } from 'react-intl'; +import type { $npm$ReactIntl$IntlShape } from 'react-intl'; +import { Box } from '@mui/system'; +import { RewardHistoryItem } from './RewardHistoryTab'; + +type Props = {| + list: Array, + onClose: () => void, +|}; +type Intl = {| + intl: $npm$ReactIntl$IntlShape, +|}; + +function RewardHistoryDialog({ list, onClose, intl }: Props & Intl): Node { + return ( + } + onClose={onClose} + > + + {intl.formatMessage(globalMessages.rewardsLabel)} ({list.length}) + + + {list.map(item => ( + + ))} + + + ); +} +export default (injectIntl(observer(RewardHistoryDialog)): ComponentType); diff --git a/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/RewardHistoryTab.js b/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/RewardHistoryTab.js index 392cbf1362..3f364e0850 100644 --- a/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/RewardHistoryTab.js +++ b/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/RewardHistoryTab.js @@ -1,52 +1,111 @@ // @flow -import type { Node } from 'react'; -import { Box } from '@mui/system'; +import type { ComponentType, Node } from 'react'; +import { Box, styled } from '@mui/system'; import { Stack, Typography } from '@mui/material'; +import { injectIntl } from 'react-intl'; +import globalMessages from '../../../../i18n/global-messages'; +import type { $npm$ReactIntl$IntlShape } from 'react-intl'; +import { getAvatarFromPoolId } from '../utils'; -type Props = {||}; +type RewardHistoryItemProps = {| + poolId: string, + poolTicker: string, + poolAvatar: string, + historyList: Array<{| + type: string, + date: string, + balance: string, + |}>, +|}; +type Intl = {| intl: $npm$ReactIntl$IntlShape |}; + +export const RewardHistoryItem = ({ + poolId, + poolTicker, + poolAvatar, + historyList, +}: RewardHistoryItemProps): Node => { + const avatarGenerated = getAvatarFromPoolId(poolId); -function HistoryRow() { return ( - - - Received - - 23 Jul, 11:30pm - + + + Stake Pool + + + {poolAvatar != null ? ( + + ) : ( + + )} + + {poolTicker} + - + 100101010.212 ADA + + {historyList.map(({ type, date, balance }) => ( + + + {type} + + {date} + + + {balance} + + ))} + ); -} +}; + +type RewardHistoryTabProps = {| + list: Array, + onOpenRewardList: () => void, +|}; -function RewardHistoryTab(props: Props): Node { +function RewardHistoryTab({ list, onOpenRewardList, intl }: RewardHistoryTabProps & Intl): Node { return ( - + - Open reward list + {intl.formatMessage(globalMessages.openRewardHistory)} - - - Stake Pool - Avatar - Emurgo [Emrugo] - - - - - - - - - - + {list.map(item => ( + + ))} ); } -export default RewardHistoryTab; +export default (injectIntl(RewardHistoryTab): ComponentType); + +const AvatarWrapper: any = styled(Box)({ + width: '24px', + height: '24px', + minWidth: '24px', + marginRight: '12px', + borderRadius: '20px', + overflow: 'hidden', +}); + +const AvatarImg: any = styled('img')({ + width: '100%', + background: 'white', + objectFit: 'scale-down', +}); diff --git a/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/StakingTabs.js b/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/StakingTabs.js index 464098cefb..31719335db 100644 --- a/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/StakingTabs.js +++ b/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/StakingTabs.js @@ -17,6 +17,10 @@ import RewardHistoryTab from './RewardHistoryTab'; type Props = {| delegatedPool: PoolData, + rewardHistory: {| + list: Array, + onOpenRewardList: () => void, + |}, epochProgress: {| currentEpoch: number, endEpochDate: string, @@ -36,7 +40,13 @@ const messages = defineMessages({ }, }); -function StakingTabs({ delegatedPool, undelegate, epochProgress, intl }: Props & Intl): Node { +function StakingTabs({ + delegatedPool, + undelegate, + epochProgress, + rewardHistory, + intl, +}: Props & Intl): Node { const [value, setValue] = useState(0); const handleChange = (event, newValue) => { @@ -58,12 +68,17 @@ function StakingTabs({ delegatedPool, undelegate, epochProgress, intl }: Props & }, { id: 1, - label: 'Reward History', - component: , + label: intl.formatMessage(globalMessages.rewardHistory), + component: ( + + ), }, { id: 2, - label: 'Epoch progress', + label: intl.formatMessage(globalMessages.epochProgress), component: ( { return undefined; }; - getStakePools: (PublicDeriver<>) => Node | void = publicDeriver => { - const timeStore = this.generated.stores.time; + getStakePools: (PublicDeriver<>, Array) => Node | void = (publicDeriver, rewardHistory) => { + const { actions, stores } = this.generated; + const timeStore = stores.time; + const timeCalcRequests = timeStore.getTimeCalcRequests(publicDeriver); const currTimeRequests = timeStore.getCurrentTimeRequests(publicDeriver); const toAbsoluteSlot = timeCalcRequests.requests.toAbsoluteSlot.result; @@ -245,6 +248,13 @@ class StakingPage extends Component { // }; return ( + actions.dialogs.open.trigger({ + dialog: RewardHistoryDialog, + }), + }} epochProgress={{ currentEpoch, endEpochDate, @@ -295,8 +305,75 @@ class StakingPage extends Component { const delegationHistory = delegationRequests.getCurrentDelegation.result?.fullHistory; const hasNeverDelegated = delegationHistory != null && delegationHistory.length === 0; + const rewardHistory = [ + { + poolTicker: '[Emurgo 12121]', + poolId: 'a4138092ab0c28ff451b1f5f9d2f6a6a1639bdf520eb1f0379bd6b04', + poolAvatar: null, + history: [ + { + type: 'Received', + date: '23 Jul, 11:30 PM', + balance: '+1.292335 ADA', + }, + { + type: 'Received', + date: '23 Jul, 11:30 PM', + balance: '+1.292335 ADA', + }, + { + type: 'Received', + date: '23 Jul, 11:30 PM', + balance: '+1.292335 ADA', + }, + { + type: 'Received', + date: '23 Jul, 11:30 PM', + balance: '+1.292335 ADA', + }, + { + type: 'Received', + date: '23 Jul, 11:30 PM', + balance: '+1.292335 ADA', + }, + ], + }, + { + poolTicker: '[Pool Unknown]', + poolId: 'a4138092ab0c28ff451b1f5f9d2f6a6a1639bdf520eb1f0379bd6b04', + poolAvatar: null, + history: [ + { + type: 'Received', + date: '23 Jul, 11:30 PM', + balance: '+1.292335 ADA', + }, + { + type: 'Received', + date: '23 Jul, 11:30 PM', + balance: '+1.292335 ADA', + }, + { + type: 'Received', + date: '23 Jul, 11:30 PM', + balance: '+1.292335 ADA', + }, + { + type: 'Received', + date: '23 Jul, 11:30 PM', + balance: '+1.292335 ADA', + }, + { + type: 'Received', + date: '23 Jul, 11:30 PM', + balance: '+1.292335 ADA', + }, + ], + }, + ]; + const showStakePoolTabs = - errorIfPresent == null ? this.getStakePools(publicDeriver) : errorIfPresent; + errorIfPresent == null ? this.getStakePools(publicDeriver, rewardHistory) : errorIfPresent; return ( { }} /> ) : null} + {uiDialogs.isOpen(RewardHistoryDialog) ? ( + + ) : null} ); diff --git a/packages/yoroi-extension/app/i18n/global-messages.js b/packages/yoroi-extension/app/i18n/global-messages.js index 6b34262918..ebfbd8b935 100644 --- a/packages/yoroi-extension/app/i18n/global-messages.js +++ b/packages/yoroi-extension/app/i18n/global-messages.js @@ -672,6 +672,18 @@ const globalMessages: * = defineMessages({ id: 'wallet.staking.overview', defaultMessage: '!!!Overview', }, + rewardHistory: { + id: 'wallet.staking.rewards.rewardHistory', + defaultMessage: '!!!Reward History', + }, + openRewardHistory: { + id: 'wallet.staking.rewards.openRewardHistory', + defaultMessage: '!!!Open Reward History', + }, + epochProgress: { + id: 'wallet.staking.epochProgress', + defaultMessage: '!!!Epoch Progress', + }, tokens: { id: 'wallet.assets.tokens', defaultMessage: '!!!Tokens', From 830595b053bb5e01838a2e4fb3b0c55010f4b90f Mon Sep 17 00:00:00 2001 From: Paul Ccari Date: Tue, 28 Dec 2021 12:51:09 -0500 Subject: [PATCH 004/153] add dates and refactor components --- .../DelegatedStakePoolCard.js | 20 +- .../dashboard-revamp/RewardHistoryDialog.js | 67 +++- .../dashboard-revamp/RewardHistoryTab.js | 69 +++-- .../dashboard-revamp/StakePoolDelegatedTab.js | 51 ++++ .../staking/dashboard-revamp/StakingTabs.js | 61 +--- .../app/components/wallet/staking/utils.js | 11 + .../containers/wallet/staking/StakingPage.js | 288 +++++++++++------- 7 files changed, 383 insertions(+), 184 deletions(-) create mode 100644 packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/StakePoolDelegatedTab.js diff --git a/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/DelegatedStakePoolCard.js b/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/DelegatedStakePoolCard.js index 8ef4c1bb87..d45b40b24f 100644 --- a/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/DelegatedStakePoolCard.js +++ b/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/DelegatedStakePoolCard.js @@ -32,7 +32,7 @@ function DelegatedStakePoolCard({ delegatedPool, undelegate, intl }: Props & Int )} - + {name} @@ -42,15 +42,17 @@ function DelegatedStakePoolCard({ delegatedPool, undelegate, intl }: Props & Int socialLinks={socialLinks} /> - - - {intl.formatMessage(globalMessages.roa30d)} - - {roa} + {roa != null ? ( + + + {intl.formatMessage(globalMessages.roa30d)} + + {roa} + - - - + + + ) : null} {intl.formatMessage(globalMessages.undelegateLabel)} diff --git a/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/RewardHistoryDialog.js b/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/RewardHistoryDialog.js index 05f21b67cb..a5057806d7 100644 --- a/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/RewardHistoryDialog.js +++ b/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/RewardHistoryDialog.js @@ -1,5 +1,6 @@ // @flow import type { Node, ComponentType } from 'react'; +import { useMemo } from 'react'; import { observer } from 'mobx-react'; import globalMessages from '../../../../i18n/global-messages'; import DialogCloseButton from '../../../widgets/DialogCloseButton'; @@ -9,16 +10,37 @@ import { injectIntl } from 'react-intl'; import type { $npm$ReactIntl$IntlShape } from 'react-intl'; import { Box } from '@mui/system'; import { RewardHistoryItem } from './RewardHistoryTab'; +import InvalidURIImg from '../../../../assets/images/uri/invalid-uri.inline.svg'; +import ErrorBlock from '../../../widgets/ErrorBlock'; +import LoadingSpinner from '../../../widgets/LoadingSpinner'; +import VerticallyCenteredLayout from '../../../layout/VerticallyCenteredLayout'; +import LocalizableError from '../../../../i18n/LocalizableError'; +import { groupByPoolName } from '../utils'; + +export type GraphRewardData = {| + error: ?LocalizableError, + items: Array<{| + name: string, + primary: number, + poolName: string, + poolId: string, + date: string, + |}>, +|}; type Props = {| - list: Array, + graphData: GraphRewardData, onClose: () => void, |}; type Intl = {| intl: $npm$ReactIntl$IntlShape, |}; -function RewardHistoryDialog({ list, onClose, intl }: Props & Intl): Node { +function RewardHistoryDialog({ graphData, onClose, intl }: Props & Intl): Node { + const rewardList = graphData.items; + + const rewardsByPoolName = useMemo(() => groupByPoolName(rewardList), []); + return ( - {intl.formatMessage(globalMessages.rewardsLabel)} ({list.length}) + {intl.formatMessage(globalMessages.rewardsLabel)} ({rewardList.length}) - {list.map(item => ( - - ))} + {graphData.error && ( +
+
+ +
+ +
+ )} + {rewardList == null ? ( + + + + ) : ( + Object.entries(rewardsByPoolName ?? {}).map(([poolName, data]) => ( + ({ + // TODO: Make sure it's "received" in all use cases + type: 'Received', + date: item.date, + balance: item.primary, + }))} + /> + )) + )}
); diff --git a/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/RewardHistoryTab.js b/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/RewardHistoryTab.js index 3f364e0850..f54d1237f9 100644 --- a/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/RewardHistoryTab.js +++ b/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/RewardHistoryTab.js @@ -5,11 +5,17 @@ import { Stack, Typography } from '@mui/material'; import { injectIntl } from 'react-intl'; import globalMessages from '../../../../i18n/global-messages'; import type { $npm$ReactIntl$IntlShape } from 'react-intl'; -import { getAvatarFromPoolId } from '../utils'; +import { getAvatarFromPoolId, groupByPoolName } from '../utils'; +import { useMemo } from 'react'; +import type { GraphRewardData } from './RewardHistoryDialog'; +import InvalidURIImg from '../../../../assets/images/uri/invalid-uri.inline.svg'; +import ErrorBlock from '../../../widgets/ErrorBlock'; +import VerticallyCenteredLayout from '../../../layout/VerticallyCenteredLayout'; +import LoadingSpinner from '../../../widgets/LoadingSpinner'; type RewardHistoryItemProps = {| poolId: string, - poolTicker: string, + poolName: string, poolAvatar: string, historyList: Array<{| type: string, @@ -21,7 +27,7 @@ type Intl = {| intl: $npm$ReactIntl$IntlShape |}; export const RewardHistoryItem = ({ poolId, - poolTicker, + poolName, poolAvatar, historyList, }: RewardHistoryItemProps): Node => { @@ -43,12 +49,13 @@ export const RewardHistoryItem = ({ )} - {poolTicker} + {poolName} - {historyList.map(({ type, date, balance }) => ( - + {historyList.map(({ type, date, balance }, idx) => ( + // eslint-disable-next-line react/no-array-index-key + {type} @@ -64,11 +71,17 @@ export const RewardHistoryItem = ({ }; type RewardHistoryTabProps = {| - list: Array, + graphData: GraphRewardData, onOpenRewardList: () => void, |}; -function RewardHistoryTab({ list, onOpenRewardList, intl }: RewardHistoryTabProps & Intl): Node { +function RewardHistoryTab({ + graphData, + onOpenRewardList, + intl, +}: RewardHistoryTabProps & Intl): Node { + const rewardList = graphData.items; + const rewardsByPoolName = useMemo(() => groupByPoolName(rewardList), []); return ( {intl.formatMessage(globalMessages.openRewardHistory)} - {list.map(item => ( - - ))} + {graphData.error && ( +
+
+ +
+ +
+ )} + {rewardList == null ? ( + + + + ) : ( + Object.entries(rewardsByPoolName ?? {}).map(([poolName, data]) => ( + ({ + // TODO: Make sure it's "received" in all use cases + type: 'Received', + date: item.date, + balance: item.primary, + }))} + /> + )) + )}
); } diff --git a/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/StakePoolDelegatedTab.js b/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/StakePoolDelegatedTab.js new file mode 100644 index 0000000000..052aa62895 --- /dev/null +++ b/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/StakePoolDelegatedTab.js @@ -0,0 +1,51 @@ +// @flow +import type { Node } from 'react'; +import { Box, styled } from '@mui/system'; +import DelegatedStakePoolCard from './DelegatedStakePoolCard'; +import InfoIconSVG from '../../../../assets/images/info-icon.inline.svg'; +import { IconButton, Typography } from '@mui/material'; +import CloseIcon from '../../../../assets/images/forms/close.inline.svg'; +import type { PoolData } from '../../../../containers/wallet/staking/SeizaFetcher'; + +type Props = {| + alertMessage: string, + delegatedPool: PoolData, + undelegate: void | (void => Promise), +|}; + +export function StakePoolDelegatedTab({ alertMessage, delegatedPool, undelegate }: Props): Node { + return ( + + + + + + + ); +} + +function StakePoolAlert({ message }: {| message: string |}): Node { + return ( + + + + {message} + + + + + + ); +} + +const StyledBox = styled(Box)({ + display: 'flex', + background: 'var(--yoroi-palette-gray-50)', + padding: '12px 16px', + alignItems: 'center', + marginBottom: '6px', + borderRadius: '8px', + '& > svg:first-child': { + minWidth: '24px', + }, +}); diff --git a/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/StakingTabs.js b/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/StakingTabs.js index 31719335db..9597117f5f 100644 --- a/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/StakingTabs.js +++ b/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/StakingTabs.js @@ -3,22 +3,24 @@ import type { ComponentType, Node } from 'react'; import { useState } from 'react'; import { Box, styled } from '@mui/system'; import { TabContext, TabList, TabPanel as TabPanelBase } from '@mui/lab'; -import { IconButton, Tab, Typography } from '@mui/material'; +import { Tab } from '@mui/material'; import { observer } from 'mobx-react'; -import InfoIconSVG from '../../../../assets/images/info-icon.inline.svg'; -import CloseIcon from '../../../../assets/images/forms/close.inline.svg'; -import DelegatedStakePoolCard from './DelegatedStakePoolCard'; import { defineMessages, injectIntl } from 'react-intl'; import type { $npm$ReactIntl$IntlShape } from 'react-intl'; import globalMessages from '../../../../i18n/global-messages'; import type { PoolData } from '../../../../containers/wallet/staking/SeizaFetcher'; import { EpochProgressCard } from './EpochProgressCard'; import RewardHistoryTab from './RewardHistoryTab'; +import type { GraphRewardData } from './RewardHistoryDialog'; +import { StakePoolDelegatedTab } from './StakePoolDelegatedTab'; type Props = {| - delegatedPool: PoolData, + delegatedPool: {| + pool: PoolData, + undelegate: void | (void => Promise), + |}, rewardHistory: {| - list: Array, + graphData: GraphRewardData, onOpenRewardList: () => void, |}, epochProgress: {| @@ -26,8 +28,8 @@ type Props = {| endEpochDate: string, percentage: number, |}, - +undelegate: void | (void => Promise), |}; + type Intl = {| intl: $npm$ReactIntl$IntlShape, |}; @@ -40,13 +42,7 @@ const messages = defineMessages({ }, }); -function StakingTabs({ - delegatedPool, - undelegate, - epochProgress, - rewardHistory, - intl, -}: Props & Intl): Node { +function StakingTabs({ delegatedPool, epochProgress, rewardHistory, intl }: Props & Intl): Node { const [value, setValue] = useState(0); const handleChange = (event, newValue) => { @@ -58,12 +54,11 @@ function StakingTabs({ id: 0, label: intl.formatMessage(globalMessages.stakePoolDelegated), component: ( - - - - - - + ), }, { @@ -71,7 +66,7 @@ function StakingTabs({ label: intl.formatMessage(globalMessages.rewardHistory), component: ( ), @@ -133,31 +128,7 @@ const StyledTab = styled(Tab)({ }, }); -function StakePoolAlert({ message }: {| message: string |}): Node { - return ( - - - - {message} - - - - - - ); -} const TabPanel = styled(TabPanelBase)({ flex: 'auto', overflow: 'auto', }); -const StyledBox = styled(Box)({ - display: 'flex', - background: 'var(--yoroi-palette-gray-50)', - padding: '12px 16px', - alignItems: 'center', - marginBottom: '6px', - borderRadius: '8px', - '& > svg:first-child': { - minWidth: '24px', - }, -}); diff --git a/packages/yoroi-extension/app/components/wallet/staking/utils.js b/packages/yoroi-extension/app/components/wallet/staking/utils.js index 7a6363596a..77b32dc3d5 100644 --- a/packages/yoroi-extension/app/components/wallet/staking/utils.js +++ b/packages/yoroi-extension/app/components/wallet/staking/utils.js @@ -5,3 +5,14 @@ export const getAvatarFromPoolId = (id: string): string => { const avatarSource = toSvg(id, 36, { padding: 0 }); return `data:image/svg+xml;utf8,${encodeURIComponent(avatarSource)}`; }; + +export const groupByKey = (items: Array, key: string): Object => + items.reduce( + (accumulator, item) => ({ + ...accumulator, + [item[key]]: (accumulator[item[key]] || []).concat(item), + }), + {} + ); + +export const groupByPoolName = (items: Array): Object => groupByKey(items, 'poolName'); diff --git a/packages/yoroi-extension/app/containers/wallet/staking/StakingPage.js b/packages/yoroi-extension/app/containers/wallet/staking/StakingPage.js index 68fcabcf8b..9757b1388a 100644 --- a/packages/yoroi-extension/app/containers/wallet/staking/StakingPage.js +++ b/packages/yoroi-extension/app/containers/wallet/staking/StakingPage.js @@ -1,24 +1,24 @@ // @flow +import type { ComponentType, Node } from 'react'; import { Component } from 'react'; -import type { Node, ComponentType } from 'react'; import { computed } from 'mobx'; import { observer } from 'mobx-react'; +import type { $npm$ReactIntl$IntlFormat } from 'react-intl'; import { intlShape } from 'react-intl'; import globalMessages from '../../../i18n/global-messages'; -import BannerContainer from '../../banners/BannerContainer'; import type { GeneratedData as BannerContainerData } from '../../banners/BannerContainer'; +import BannerContainer from '../../banners/BannerContainer'; import type { InjectedOrGenerated } from '../../../types/injectedPropsType'; import type { GeneratedData as SidebarContainerData } from '../../SidebarContainer'; +import SidebarContainer from '../../SidebarContainer'; import type { GeneratedData as NavBarContainerRevampData } from '../../NavBarContainerRevamp'; +import NavBarContainerRevamp from '../../NavBarContainerRevamp'; import TopBarLayout from '../../../components/layout/TopBarLayout'; -import SidebarContainer from '../../SidebarContainer'; import NavBarTitle from '../../../components/topbar/NavBarTitle'; -import type { $npm$ReactIntl$IntlFormat } from 'react-intl'; import { PublicDeriver } from '../../../api/ada/lib/storage/models/PublicDeriver/index'; -import { withLayout } from '../../../styles/context/layout'; import type { LayoutComponentMap } from '../../../styles/context/layout'; -import NavBarContainerRevamp from '../../NavBarContainerRevamp'; +import { withLayout } from '../../../styles/context/layout'; import WalletEmptyBanner from '../WalletEmptyBanner'; import BuySellDialog from '../../../components/buySell/BuySellDialog'; import CardanoStakingPage from './CardanoStakingPage'; @@ -31,32 +31,34 @@ import OverviewModal from '../../../components/wallet/staking/dashboard-revamp/O import type { DelegationRequests, PoolMeta } from '../../../stores/toplevel/DelegationStore'; import LocalizableError from '../../../i18n/LocalizableError'; import { MultiToken } from '../../../api/common/lib/MultiToken'; -import { genLookupOrFail } from '../../../stores/stateless/tokenHelpers'; +import { genLookupOrFail, getTokenName } from '../../../stores/stateless/tokenHelpers'; +import type { GeneratedData as UnmangleTxDialogContainerData } from '../../transfer/UnmangleTxDialogContainer'; import UnmangleTxDialogContainer from '../../transfer/UnmangleTxDialogContainer'; +import type { GeneratedData as DeregisterDialogContainerData } from '../../transfer/DeregisterDialogContainer'; import DeregisterDialogContainer from '../../transfer/DeregisterDialogContainer'; import { calculateAndFormatValue } from '../../../utils/unit-of-account'; import type { TokenInfoMap } from '../../../stores/toplevel/TokenInfoStore'; import type { NetworkRow } from '../../../api/ada/lib/storage/database/primitives/tables'; import type { UnitOfAccountSettingType } from '../../../types/unitOfAccountType'; import { - isCardanoHaskell, - isJormungandr, + getCardanoHaskellBaseConfig, isCardanoHaskell, isJormungandr, } from '../../../api/ada/lib/storage/database/prepackaged/networks'; import type { AdaDelegationRequests } from '../../../stores/ada/AdaDelegationStore'; import EpochProgressContainer from './EpochProgressContainer'; -import type { GeneratedData as UnmangleTxDialogContainerData } from '../../transfer/UnmangleTxDialogContainer'; -import WithdrawalTxDialogContainer from '../../transfer/WithdrawalTxDialogContainer'; import type { GeneratedData as WithdrawalTxDialogContainerData } from '../../transfer/WithdrawalTxDialogContainer'; -import type { GeneratedData as DeregisterDialogContainerData } from '../../transfer/DeregisterDialogContainer'; +import WithdrawalTxDialogContainer from '../../transfer/WithdrawalTxDialogContainer'; import UndelegateDialog from '../../../components/wallet/staking/dashboard/UndelegateDialog'; import type { PoolRequest } from '../../../api/jormungandr/lib/storage/bridge/delegationUtils'; import { ApiOptions, getApiForNetwork } from '../../../api/common/utils'; import type { - CurrentTimeRequests, - TimeCalcRequests, + CurrentTimeRequests, TimeCalcRequests, } from '../../../stores/base/BaseCardanoTimeStore'; import moment from 'moment'; -import RewardHistoryDialog from '../../../components/wallet/staking/dashboard-revamp/RewardHistoryDialog'; +import type { GraphRewardData } from '../../../components/wallet/staking/dashboard-revamp/RewardHistoryDialog'; +import RewardHistoryDialog + from '../../../components/wallet/staking/dashboard-revamp/RewardHistoryDialog'; +import { splitAmount, truncateAddressShort, truncateToken } from '../../../utils/formatters'; +import { hiddenAmount } from '../../../utils/strings'; export type GeneratedData = typeof StakingPage.prototype.generated; // populated by ConfigWebpackPlugin @@ -154,6 +156,147 @@ class StakingPage extends Component { ); }; + /* Reward History */ + _generateRewardGraphData: ({| + delegationRequests: DelegationRequests, + currentEpoch: number, + publicDeriver: PublicDeriver<>, + |}) => any = request => { + const history = request.delegationRequests.rewardHistory.result; + if (history == null) { + return null; + } + if (!request.delegationRequests.getCurrentDelegation.wasExecuted) { + return null; + } + let historyIterator = 0; + const perEpochRewards: Array = []; + + const startEpoch = (() => { + if (isCardanoHaskell(request.publicDeriver.getParent().getNetworkInfo())) { + const shelleyConfig = getCardanoHaskellBaseConfig( + request.publicDeriver.getParent().getNetworkInfo() + )[1]; + return shelleyConfig.StartAt; + } + return 0; + })(); + const endEpoch = (() => { + if (isCardanoHaskell(request.publicDeriver.getParent().getNetworkInfo())) { + // TODO: -1 since cardano-db-sync doesn't expose this information for some reason + return request.currentEpoch - 1; + } + if (isJormungandr(request.publicDeriver.getParent().getNetworkInfo())) { + // note: reward history includes the current epoch + // since it tells you the reward you got at slot 0 of the new epoch + return request.currentEpoch + 1; + } + throw new Error( + `${nameof(this._generateRewardGraphData)} can't compute endEpoch for rewards` + ); + })(); + + const getMiniPoolInfo = (poolHash: string) => { + const meta = this.generated.stores.delegation.getLocalPoolInfo( + request.publicDeriver.getParent().getNetworkInfo(), + poolHash + ); + if (meta == null || meta.info == null || meta.info.ticker == null || meta.info.name == null) { + return truncateAddressShort(poolHash.toString()); + } + return `[${meta.info.ticker}] ${meta.info.name}`; + }; + + const getDateFromEpoch = epoch => { + const timeStore = this.generated.stores.time; + const timeCalcRequests = timeStore.getTimeCalcRequests(request.publicDeriver); + const toRealTime = timeCalcRequests.requests.toRealTime.result; + if (toRealTime == null) return undefined; + const toAbsoluteSlot = timeCalcRequests.requests.toAbsoluteSlot.result; + if (toAbsoluteSlot == null) return undefined; + const timeSinceGenesis = timeCalcRequests.requests.timeSinceGenesis.result; + if (timeSinceGenesis == null) return undefined; + const getEpochLength = timeCalcRequests.requests.currentEpochLength.result; + if (getEpochLength == null) return undefined; + + const endEpochTime = toRealTime({ + absoluteSlotNum: toAbsoluteSlot({ + epoch, + // in Jormungandr, rewards were distributed at the start of the epoch + // in Haskell, rewards are calculated at the start of the epoch but distributed at the end + slot: isJormungandr(request.publicDeriver.getParent().getNetworkInfo()) + ? 0 + : getEpochLength(), + }), + timeSinceGenesisFunc: timeSinceGenesis, + }); + const endEpochMoment = moment(endEpochTime).format('lll'); + return endEpochMoment; + }; + + const getNormalized = tokenEntry => { + const tokenRow = this.generated.stores.tokenInfoStore.tokenInfo + .get(tokenEntry.networkId.toString()) + ?.get(tokenEntry.identifier); + if (tokenRow == null) + throw new Error(`${nameof(StakingPage)} no token info for ${JSON.stringify(tokenEntry)}`); + const getTokenInfo = genLookupOrFail(this.generated.stores.tokenInfoStore.tokenInfo); + const tokenInfo = getTokenInfo(tokenEntry); + const shiftedAmount = tokenEntry.amount.shiftedBy(-tokenInfo.Metadata.numberOfDecimals); + + const [beforeDecimalRewards, afterDecimalRewards] = splitAmount( + shiftedAmount, + tokenInfo.Metadata.numberOfDecimals + ); + return this.generated.stores.profile.shouldHideBalance ? + hiddenAmount : + `${beforeDecimalRewards}${afterDecimalRewards} ${truncateToken(getTokenName(tokenInfo))}`; + }; + for (let i = startEpoch; i < endEpoch; i++) { + if (historyIterator < history.length && i === history[historyIterator][0]) { + // exists a reward for this epoch + const poolHash = history[historyIterator][2]; + const nextReward = history[historyIterator][1]; + + perEpochRewards.push({ + name: i, + primary: getNormalized(nextReward.getDefaultEntry()), + poolName: getMiniPoolInfo(poolHash), + poolId: poolHash, + date: getDateFromEpoch(i), + }); + historyIterator++; + } else { + perEpochRewards.push({ + name: i, + primary: 0, + poolName: '', + poolId: '', + date: '', + }); + } + } + + return perEpochRewards.filter(item => item.poolName); + }; + + _generateGraphData: ({| + delegationRequests: DelegationRequests, + publicDeriver: PublicDeriver<>, + |}) => GraphRewardData = request => { + const timeStore = this.generated.stores.time; + const currTimeRequests = timeStore.getCurrentTimeRequests(request.publicDeriver); + + return { + error: request.delegationRequests.rewardHistory.error, + items: this._generateRewardGraphData({ + delegationRequests: request.delegationRequests, + currentEpoch: currTimeRequests.currentEpoch, + publicDeriver: request.publicDeriver, + }), + }; + }; + getErrorInFetch: (PublicDeriver<>) => void | {| error: LocalizableError |} = publicDeriver => { const delegationStore = this.generated.stores.delegation; const delegationRequests = delegationStore.getDelegationRequests(publicDeriver); @@ -173,7 +316,10 @@ class StakingPage extends Component { return undefined; }; - getStakePools: (PublicDeriver<>, Array) => Node | void = (publicDeriver, rewardHistory) => { + getStakePools: (PublicDeriver<>, GraphRewardData) => Node | void = ( + publicDeriver, + rewardsGraphData + ) => { const { actions, stores } = this.generated; const timeStore = stores.time; @@ -218,7 +364,6 @@ class StakingPage extends Component { return null; } const currentPools = delegationRequests.getCurrentDelegation.result.currEpoch.pools; - const { intl } = this.context; const currentPage = this.generated.stores.delegation.selectedPage; const currentPool = currentPools[0][currentPage]; @@ -230,7 +375,7 @@ class StakingPage extends Component { // server hasn't returned information about the stake pool yet return undefined; } - const name = meta.info?.name ?? intl.formatMessage(globalMessages.unknownPoolLabel); + const name = meta.info?.name ?? truncateAddressShort(currentPool.toString()); const delegatedPool = { id: String(currentPool), name, @@ -248,8 +393,24 @@ class StakingPage extends Component { // }; return ( { + this.generated.actions.dialogs.open.trigger({ dialog: UndelegateDialog }); + await this.generated.actions.jormungandr.delegationTransaction.createTransaction.trigger( + { + publicDeriver, + poolRequest: undefined, + } + ); + } + : undefined, + }} rewardHistory={{ - list: rewardHistory, + graphData: rewardsGraphData, onOpenRewardList: () => actions.dialogs.open.trigger({ dialog: RewardHistoryDialog, @@ -260,21 +421,6 @@ class StakingPage extends Component { endEpochDate, percentage: Math.floor((100 * currTimeRequests.currentSlot) / epochLength), }} - delegatedPool={delegatedPool} - undelegate={ - // don't support undelegation for ratio stake since it's a less intuitive UX - currentPools.length === 1 && isJormungandr(publicDeriver.getParent().getNetworkInfo()) - ? async () => { - this.generated.actions.dialogs.open.trigger({ dialog: UndelegateDialog }); - await this.generated.actions.jormungandr.delegationTransaction.createTransaction.trigger( - { - publicDeriver, - poolRequest: undefined, - } - ); - } - : undefined - } /> ); }; @@ -305,75 +451,13 @@ class StakingPage extends Component { const delegationHistory = delegationRequests.getCurrentDelegation.result?.fullHistory; const hasNeverDelegated = delegationHistory != null && delegationHistory.length === 0; - const rewardHistory = [ - { - poolTicker: '[Emurgo 12121]', - poolId: 'a4138092ab0c28ff451b1f5f9d2f6a6a1639bdf520eb1f0379bd6b04', - poolAvatar: null, - history: [ - { - type: 'Received', - date: '23 Jul, 11:30 PM', - balance: '+1.292335 ADA', - }, - { - type: 'Received', - date: '23 Jul, 11:30 PM', - balance: '+1.292335 ADA', - }, - { - type: 'Received', - date: '23 Jul, 11:30 PM', - balance: '+1.292335 ADA', - }, - { - type: 'Received', - date: '23 Jul, 11:30 PM', - balance: '+1.292335 ADA', - }, - { - type: 'Received', - date: '23 Jul, 11:30 PM', - balance: '+1.292335 ADA', - }, - ], - }, - { - poolTicker: '[Pool Unknown]', - poolId: 'a4138092ab0c28ff451b1f5f9d2f6a6a1639bdf520eb1f0379bd6b04', - poolAvatar: null, - history: [ - { - type: 'Received', - date: '23 Jul, 11:30 PM', - balance: '+1.292335 ADA', - }, - { - type: 'Received', - date: '23 Jul, 11:30 PM', - balance: '+1.292335 ADA', - }, - { - type: 'Received', - date: '23 Jul, 11:30 PM', - balance: '+1.292335 ADA', - }, - { - type: 'Received', - date: '23 Jul, 11:30 PM', - balance: '+1.292335 ADA', - }, - { - type: 'Received', - date: '23 Jul, 11:30 PM', - balance: '+1.292335 ADA', - }, - ], - }, - ]; + const rewardsGraphData = this._generateGraphData({ + delegationRequests, + publicDeriver, + }); const showStakePoolTabs = - errorIfPresent == null ? this.getStakePools(publicDeriver, rewardHistory) : errorIfPresent; + errorIfPresent == null ? this.getStakePools(publicDeriver, rewardsGraphData) : errorIfPresent; return ( { /> ) : null} {uiDialogs.isOpen(RewardHistoryDialog) ? ( - + ) : null} From c378cd7567dfc92c8547908f1de25d9527422d91 Mon Sep 17 00:00:00 2001 From: Paul Ccari Date: Tue, 28 Dec 2021 12:56:00 -0500 Subject: [PATCH 005/153] fix i18n en-us --- .../app/i18n/locales/en-US.json | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/packages/yoroi-extension/app/i18n/locales/en-US.json b/packages/yoroi-extension/app/i18n/locales/en-US.json index 3c74dc826b..99af3e2105 100644 --- a/packages/yoroi-extension/app/i18n/locales/en-US.json +++ b/packages/yoroi-extension/app/i18n/locales/en-US.json @@ -56,13 +56,10 @@ "buysell.dialog.instructions": "Please select your preferences. On the next screen, confirm your selection by pressing the green arrow on the top right", "buysell.dialog.manual": "I will add my address manually", "buysell.dialog.selectAddress": "Please select the receiving address. This will be shared with the third party provider called Changelly for the buy / sell of ADA. ", + "connector.appName": "Dapp Connector", "connector.connect.connectedWallets": "Connected Wallets", "connector.connect.connectedWallets.active": "Active", "connector.connect.noWebsitesConnected": "You don't have any websites connected yet", - "connector.signin.title": "Sign transaction", - "connector.signin.txDetails": "Transaction Details", - "connector.signin.receiver": "Receiver", - "connector.signin.more": "more", "connector.settings.about": "About", "connector.settings.about.dAppDescription": "The dApp connector allows dApps (decentralized applications) in the form of web pages to interact in a secure manner with the user's Yoroi Ergo wallets to enable smart contract functionality.", "connector.settings.about.dAppInfo": "What is the dApp connector?", @@ -70,6 +67,10 @@ "connector.settings.about.howItWorksDescription": "The connector exposes a javascript interface to web pages you visit, specified by the Ergo EIP-0012 standard, allowing dApps to request read-only access to a user's Yoroi Ergo wallet. If the user gives access to a dApp, the dApp can read, but not change, the user's balance and addresses. The dApp can also request that the user sign a transaction, such as a smart contract created using the address information supplied via this connector. Private keys/passwords are never exposed to dApps, and all transaction signing is done within Yoroi and only with explicit user confirmation.", "connector.settings.supportContact": "Yoroi team will get back to you soon.", "connector.settings.supportText": "Feel free to contact us, if you need some help or you have some other question.", + "connector.signin.more": "more", + "connector.signin.receiver": "Receiver", + "connector.signin.title": "Sign transaction", + "connector.signin.txDetails": "Transaction Details", "crash.screen.title": "Yoroi crashed", "daedalusTransfer.error.noTransferTxError": "There is no transaction to be sent.", "daedalusTransfer.error.transferFundsError": "Unable to transfer funds.", @@ -336,7 +337,6 @@ "settings.unitOfAccount.note": "Note: coin price is approximate and may not match the price of any given trading platform. Any transactions based on these price approximates are done at your own risk.", "settings.unitOfAccount.title": "Currency Conversion", "sidebar.assets": "Assets", - "sidebar.connectedWebsites": "Connected websites", "sidebar.faq": "Faq", "sidebar.feedback": "Feedback", "sidebar.newUpdates": "New updates", @@ -685,9 +685,9 @@ "wallet.restore.dialog.verify.wallet.button.label": "Verify wallet", "wallet.restore.dialog.wallet.name.input.hint": "e.g: Shopping Wallet", "wallet.restore.dialog.wallet.name.input.label": "Wallet name", - "wallet.restore.dialog.walletExist.title": "Wallet Already Exist", - "wallet.restore.dialog.walletExist.openWallet": "Open Wallet", "wallet.restore.dialog.walletExist.explanation": "You are trying to restore existing wallet.", + "wallet.restore.dialog.walletExist.openWallet": "Open Wallet", + "wallet.restore.dialog.walletExist.title": "Wallet Already Exist", "wallet.send.confirmationDialog.addressToLabel": "To", "wallet.send.confirmationDialog.amountLabel": "Amount", "wallet.send.confirmationDialog.feesLabel": "Fees", @@ -755,9 +755,12 @@ "wallet.staking.banner.roaHelperMessage": "Estimated ROA (Return of ADA) based on staking result from the last 30 days", "wallet.staking.banner.socialMedia": "Stake pool social media", "wallet.staking.dialogSummaryDescription": "Your rewards are automatically staked. You don’t need to withdraw it everytime because you pay a transaction fee.", + "wallet.staking.epochProgress": "Epoch Progress", "wallet.staking.overview": "Overview", "wallet.staking.overviewContent": "Your rewards are automatically staked. You don’t need to withdraw it everytime because you pay a transaction fee.", "wallet.staking.pool.unknownLabel": "Unknown pool", + "wallet.staking.rewards.openRewardHistory": "Open Reward History", + "wallet.staking.rewards.rewardHistory": "Reward History", "wallet.staking.summary": "Summary", "wallet.staking.warning.pendingTx": "You cannot change your delegation preference while a transaction is pending", "wallet.summary.no.transaction": "No transactions found", @@ -773,6 +776,9 @@ "wallet.summary.page.walletCreatedNotificationMessage": "You have successfully created a new Wallet", "wallet.summary.page.walletRestoredNotificationMessage": "You have successfully restored your Wallet", "wallet.summary.page.yesterdayLabel": "Yesterday", + "wallet.syncingOverlay.explanation": "We are processing your wallet data. This may take time. Please wait...", + "wallet.syncingOverlay.return": "Return to my wallets", + "wallet.syncingOverlay.title": "Wallet Syncing", "wallet.topbar.dialog.tokenTypes": "Token types", "wallet.topbar.dialog.totalBalance": "Total Balance", "wallet.transaction.address.from": "From address", @@ -876,9 +882,6 @@ "wallet.voting.notDelegated": "You have not delegated. Your voting power is how much you delegate and the voting rewards will be distributed to your delegation reward address. Please make sure to delegate before voting.", "wallet.voting.trezorTRequirement": "Update your Trezor Model T firmware version to 2.4.1 or above.", "wallet.withdrawal.transaction.unregister": "This transaction will unregister one or more staking keys, giving you back your {refundAmount} {ticker} from your deposit", - "wallet.syncingOverlay.title": "Wallet Syncing", - "wallet.syncingOverlay.explanation": "We are processing your wallet data. This may take time. Please wait...", - "wallet.syncingOverlay.return": "Return to my wallets", "widgets.copyableaddress.addressCopyTooltipMessage": "Copy to clipboard", "widgets.copyableaddress.copied": "Copied", "widgets.explorer.tooltip": "Go to {websiteName}", @@ -901,4 +904,4 @@ "yoroiTransfer.waiting.progressInfo.checkingAddresses": "Checking addresses funds", "yoroiTransfer.waiting.progressInfo.restoringAddresses": "Fetching addresses", "yoroiTransfer.waiting.title.label": "Wallet is being restored" -} +} \ No newline at end of file From a63e390c72f5d5137ed4138ccebf2dd7bb38dd2b Mon Sep 17 00:00:00 2001 From: vantuz-subhuman Date: Thu, 10 Mar 2022 18:47:01 +0300 Subject: [PATCH 006/153] merge fixes --- packages/yoroi-extension/app/i18n/locales/en-US.json | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/yoroi-extension/app/i18n/locales/en-US.json b/packages/yoroi-extension/app/i18n/locales/en-US.json index 9831d14eb6..c62fea63f2 100644 --- a/packages/yoroi-extension/app/i18n/locales/en-US.json +++ b/packages/yoroi-extension/app/i18n/locales/en-US.json @@ -74,13 +74,9 @@ "connector.signin.title": "Sign transaction", "connector.signin.txDetails": "Transaction Details", "connector.signin.connectedTo": "Connected To", - "connector.signin.more": "more", - "connector.signin.receiver": "Receiver", - "connector.signin.title": "Sign transaction", "connector.signin.totalAmount": "Total Amount", "connector.signin.totals": "Totals", "connector.signin.transactionFee": "Transaction Fee", - "connector.signin.txDetails": "Transaction Details", "crash.screen.title": "Yoroi crashed", "daedalusTransfer.error.noTransferTxError": "There is no transaction to be sent.", "daedalusTransfer.error.transferFundsError": "Unable to transfer funds.", From c20841e0e12020dc823eaf47d37a77a99a82fbc0 Mon Sep 17 00:00:00 2001 From: Ahmed Ibrahim Date: Sun, 12 Jun 2022 09:34:06 +0200 Subject: [PATCH 007/153] Add switcher between old and new themes --- .../general-setting/ThemeSettingsBlock.js | 55 +++++++++++++++++-- 1 file changed, 49 insertions(+), 6 deletions(-) diff --git a/packages/yoroi-extension/app/components/settings/categories/general-setting/ThemeSettingsBlock.js b/packages/yoroi-extension/app/components/settings/categories/general-setting/ThemeSettingsBlock.js index 729b008cde..cf8c636adb 100644 --- a/packages/yoroi-extension/app/components/settings/categories/general-setting/ThemeSettingsBlock.js +++ b/packages/yoroi-extension/app/components/settings/categories/general-setting/ThemeSettingsBlock.js @@ -2,7 +2,7 @@ import { Component } from 'react'; import type { Node, ComponentType } from 'react'; import { observer } from 'mobx-react'; -import { Button, IconButton, Typography } from '@mui/material'; +import { Button, FormControlLabel, IconButton, Radio, RadioGroup, Typography } from '@mui/material'; import { Box, styled } from '@mui/system'; import { defineMessages, intlShape, FormattedMessage, FormattedHTMLMessage } from 'react-intl'; import { THEMES } from '../../../../styles/utils'; @@ -55,6 +55,18 @@ const messages = defineMessages({ id: 'settings.backYoroiClassic', defaultMessage: '!!!Back to Yoroi Classic', }, + version: { + id: 'settings.theme.version', + defaultMessage: '!!!Version' + }, + currentVersion: { + id: 'settings.theme.currentVersion', + defaultMessage: '!!!Yoroi current version' + }, + newVersion: { + id: 'settings.theme.newVersion', + defaultMessage: '!!!Yoroi new version' + }, }); type Props = {| @@ -70,6 +82,8 @@ type InjectedProps = {| |}; type AllProps = {| ...Props, ...InjectedProps |}; +const NEW_THEME = THEMES.YOROI_REVAMP +const OLD_THEME = `${THEMES.YOROI_MODERN}-${THEMES.YOROI_CLASSIC}` @observer class ThemeSettingsBlock extends Component { static contextTypes: {| intl: $npm$ReactIntl$IntlFormat |} = { @@ -132,11 +146,41 @@ class ThemeSettingsBlock extends Component { || environment.isTest(); const themeBlockClassicComponent = ( - - {commonHeader} + + + {intl.formatMessage(messages.version)} + + + { + const theme = e.target.value === NEW_THEME ? NEW_THEME : THEMES.YOROI_MODERN + selectTheme({ theme }) + }} + sx={{ + display: 'flex', + flexDirection: 'row', + }} + > + } + label={intl.formatMessage(messages.currentVersion)} + sx={{ + marginRight: '20px' + }} + /> + } + label={intl.formatMessage(messages.newVersion)} + /> + + + {/* {commonHeader} - {/* Modern Theme */} { {intl.formatMessage(messages.themeYoroiModern)} - {/* Classic Theme */} { {intl.formatMessage(messages.tryYoroiRevamp)} - )} + )} */} ); From 8e1bfbfeebf18f53a419dae0894e5552f65fa6cc Mon Sep 17 00:00:00 2001 From: Ahmed Ibrahim Date: Sun, 12 Jun 2022 09:45:44 +0200 Subject: [PATCH 008/153] Update eg-US.json --- .../images/yoroi-classic-theme.inline.svg | 13 ++++++++ .../images/yoroi-modern-theme.inline.svg | 26 ++++++++++++++++ .../general-setting/ThemeSettingsBlock.js | 30 ++++++++++++++++++- .../app/i18n/locales/en-US.json | 4 +++ 4 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 packages/yoroi-extension/app/assets/images/yoroi-classic-theme.inline.svg create mode 100644 packages/yoroi-extension/app/assets/images/yoroi-modern-theme.inline.svg diff --git a/packages/yoroi-extension/app/assets/images/yoroi-classic-theme.inline.svg b/packages/yoroi-extension/app/assets/images/yoroi-classic-theme.inline.svg new file mode 100644 index 0000000000..28fb0fedbc --- /dev/null +++ b/packages/yoroi-extension/app/assets/images/yoroi-classic-theme.inline.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/packages/yoroi-extension/app/assets/images/yoroi-modern-theme.inline.svg b/packages/yoroi-extension/app/assets/images/yoroi-modern-theme.inline.svg new file mode 100644 index 0000000000..789d3a4816 --- /dev/null +++ b/packages/yoroi-extension/app/assets/images/yoroi-modern-theme.inline.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/yoroi-extension/app/components/settings/categories/general-setting/ThemeSettingsBlock.js b/packages/yoroi-extension/app/components/settings/categories/general-setting/ThemeSettingsBlock.js index cf8c636adb..c500ab8a1e 100644 --- a/packages/yoroi-extension/app/components/settings/categories/general-setting/ThemeSettingsBlock.js +++ b/packages/yoroi-extension/app/components/settings/categories/general-setting/ThemeSettingsBlock.js @@ -13,6 +13,8 @@ import globalMessages from '../../../../i18n/global-messages'; import { withLayout } from '../../../../styles/context/layout'; import type { LayoutComponentMap } from '../../../../styles/context/layout'; import environment from '../../../../environment'; +import { ReactComponent as YoroiModernTheme } from '../../../../assets/images/yoroi-modern-theme.inline.svg'; +import { ReactComponent as YoroiClassicTheme } from '../../../../assets/images/yoroi-classic-theme.inline.svg'; const messages = defineMessages({ themeLabel: { @@ -67,6 +69,10 @@ const messages = defineMessages({ id: 'settings.theme.newVersion', defaultMessage: '!!!Yoroi new version' }, + selectColorTheme: { + id: 'settings.theme.selectColorTheme', + defaultMessage: '!!!Select color theme for old version' + }, }); type Props = {| @@ -147,7 +153,7 @@ class ThemeSettingsBlock extends Component { const themeBlockClassicComponent = ( - + {intl.formatMessage(messages.version)} @@ -178,6 +184,28 @@ class ThemeSettingsBlock extends Component { /> + + + {intl.formatMessage(messages.selectColorTheme)} + + + + + + + + {/* {commonHeader} diff --git a/packages/yoroi-extension/app/i18n/locales/en-US.json b/packages/yoroi-extension/app/i18n/locales/en-US.json index d75b2a01fe..9bfd1561bc 100644 --- a/packages/yoroi-extension/app/i18n/locales/en-US.json +++ b/packages/yoroi-extension/app/i18n/locales/en-US.json @@ -257,6 +257,10 @@ "profile.uriPrompt.form.skipLabel": "Skip", "serverError.label.message": "WARNING: Server experiencing difficulties.
Please check our Twitter account.
The displayed balance and transaction history may appear incorrect until our servers are back to normal, but your actual balance is not affected.", "settings.backYoroiClassic": "Back to Yoroi Classic", + "settings.theme.currentVersion": "Yoroi current version", + "settings.theme.newVersion": "Yoroi new version", + "settings.theme.version": "Version", + "settings.theme.selectColorTheme": "Select color theme for old version", "settings.display.blog": "You can read our {blogLink} on how to use this feature.", "settings.display.themeExportButton": "EXPORT THEME", "settings.display.themeLabel": "Theme", From d2345b2c30b7d746ceda0d02a8b8611c6f9eed0a Mon Sep 17 00:00:00 2001 From: Ahmed Ibrahim Date: Sun, 12 Jun 2022 09:46:40 +0200 Subject: [PATCH 009/153] Render warning text --- .../settings/categories/general-setting/ThemeSettingsBlock.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/yoroi-extension/app/components/settings/categories/general-setting/ThemeSettingsBlock.js b/packages/yoroi-extension/app/components/settings/categories/general-setting/ThemeSettingsBlock.js index c500ab8a1e..e601ada5a5 100644 --- a/packages/yoroi-extension/app/components/settings/categories/general-setting/ThemeSettingsBlock.js +++ b/packages/yoroi-extension/app/components/settings/categories/general-setting/ThemeSettingsBlock.js @@ -191,6 +191,7 @@ class ThemeSettingsBlock extends Component { fontWeight: 500, marginBottom: '8px', color: 'var(--yoroi-support-settings-text)', + fontSize: '18px', }} > {intl.formatMessage(messages.selectColorTheme)} From abf9f4afa6e71a11768eea1d6ee98e6737a14024 Mon Sep 17 00:00:00 2001 From: Ahmed Ibrahim Date: Sun, 12 Jun 2022 10:15:20 +0200 Subject: [PATCH 010/153] Make radio buttons small --- .../general-setting/ThemeSettingsBlock.js | 81 +++++++++++++------ 1 file changed, 57 insertions(+), 24 deletions(-) diff --git a/packages/yoroi-extension/app/components/settings/categories/general-setting/ThemeSettingsBlock.js b/packages/yoroi-extension/app/components/settings/categories/general-setting/ThemeSettingsBlock.js index e601ada5a5..01279ff517 100644 --- a/packages/yoroi-extension/app/components/settings/categories/general-setting/ThemeSettingsBlock.js +++ b/packages/yoroi-extension/app/components/settings/categories/general-setting/ThemeSettingsBlock.js @@ -184,29 +184,56 @@ class ThemeSettingsBlock extends Component { />
- - - {intl.formatMessage(messages.selectColorTheme)} - - - - - - - - + { + currentTheme !== THEMES.YOROI_REVAMP && ( + + + + {intl.formatMessage(messages.selectColorTheme)} + + + + + + + + + + + { + selectTheme({ theme: e.target.value }) + }} + > + + + + + } label='Modern' /> + + + + } label='classic' /> + + + + + ) + } {/* {commonHeader} @@ -316,7 +343,7 @@ class ThemeSettingsBlock extends Component { ); return this.props.renderLayoutComponent({ CLASSIC: themeBlockClassicComponent, - REVAMP: themeBlockRevampComponent, + REVAMP: themeBlockClassicComponent, // Todo: remove renderLayoutComponent }); } } @@ -343,3 +370,9 @@ const ThemeButton = styled(IconButton)(({ isActive }) => ({ marginBottom: '32px', ':hover': { background: 'transparent' }, })); + +const RadioButton = styled(Radio)({ + '&.Mui-checked': { + color: '#4B6DDE', + }, +}) \ No newline at end of file From f6b44fc46e6765086cc3bcfb906b17648650d733 Mon Sep 17 00:00:00 2001 From: Ahmed Ibrahim Date: Mon, 13 Jun 2022 12:49:26 +0200 Subject: [PATCH 011/153] Remove render layout --- .../general-setting/ThemeSettingsBlock.js | 170 +++++++++++++++++- 1 file changed, 164 insertions(+), 6 deletions(-) diff --git a/packages/yoroi-extension/app/components/settings/categories/general-setting/ThemeSettingsBlock.js b/packages/yoroi-extension/app/components/settings/categories/general-setting/ThemeSettingsBlock.js index 01279ff517..b67ba383fd 100644 --- a/packages/yoroi-extension/app/components/settings/categories/general-setting/ThemeSettingsBlock.js +++ b/packages/yoroi-extension/app/components/settings/categories/general-setting/ThemeSettingsBlock.js @@ -91,7 +91,7 @@ type AllProps = {| ...Props, ...InjectedProps |}; const NEW_THEME = THEMES.YOROI_REVAMP const OLD_THEME = `${THEMES.YOROI_MODERN}-${THEMES.YOROI_CLASSIC}` @observer -class ThemeSettingsBlock extends Component { +export default class ThemeSettingsBlock extends Component { static contextTypes: {| intl: $npm$ReactIntl$IntlFormat |} = { intl: intlShape.isRequired, }; @@ -341,13 +341,171 @@ class ThemeSettingsBlock extends Component { )} ); - return this.props.renderLayoutComponent({ - CLASSIC: themeBlockClassicComponent, - REVAMP: themeBlockClassicComponent, // Todo: remove renderLayoutComponent - }); + return ( + + + {intl.formatMessage(messages.version)} + + + { + const theme = e.target.value === NEW_THEME ? NEW_THEME : THEMES.YOROI_MODERN + selectTheme({ theme }) + }} + sx={{ + display: 'flex', + flexDirection: 'row', + }} + > + } + label={intl.formatMessage(messages.currentVersion)} + sx={{ + marginRight: '20px' + }} + /> + } + label={intl.formatMessage(messages.newVersion)} + /> + + + { + currentTheme !== THEMES.YOROI_REVAMP && ( + + + + {intl.formatMessage(messages.selectColorTheme)} + + + + + + + + + + + { + selectTheme({ theme: e.target.value }) + }} + > + + + + + } label='Modern' /> + + + + } label='classic' /> + + + + + ) + } + {/* {commonHeader} + + + + {currentTheme === THEMES.YOROI_MODERN && hasCustomTheme() && ( + + {intl.formatMessage(messages.themeWarning)} + + )} + + + {intl.formatMessage(messages.themeYoroiModern)} + + + + {currentTheme === THEMES.YOROI_CLASSIC && hasCustomTheme() && ( + + {intl.formatMessage(messages.themeWarning)} + + )} + + + {intl.formatMessage(messages.themeYoroiClassic)} + + + + + + + + {shouldDisplayRevampButton && ( + + + + )} */} + + ) } } -export default (withLayout(ThemeSettingsBlock): ComponentType); const WarningMessage = styled(Typography)({ position: 'absolute', From a9d924d1359aa259d23334431c0ece66c63d8e0d Mon Sep 17 00:00:00 2001 From: Ahmed Ibrahim Date: Mon, 13 Jun 2022 12:53:03 +0200 Subject: [PATCH 012/153] Move fiat paring option to be on the top --- .../settings/categories/GeneralSettingsPage.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/yoroi-extension/app/containers/settings/categories/GeneralSettingsPage.js b/packages/yoroi-extension/app/containers/settings/categories/GeneralSettingsPage.js index 5d2870cb2f..cee6491d29 100644 --- a/packages/yoroi-extension/app/containers/settings/categories/GeneralSettingsPage.js +++ b/packages/yoroi-extension/app/containers/settings/categories/GeneralSettingsPage.js @@ -126,14 +126,6 @@ export default class GeneralSettingsPage extends Component - + From 682b26479a3cb3e8d78acff8222d39b84152f710 Mon Sep 17 00:00:00 2001 From: Ahmed Ibrahim Date: Mon, 13 Jun 2022 13:46:12 +0200 Subject: [PATCH 013/153] Add yoroi modern theme logo --- .../images/yoroi-modern-theme.inline.svg | 37 +++------ .../general-setting/ThemeSettingsBlock.js | 82 +------------------ 2 files changed, 14 insertions(+), 105 deletions(-) diff --git a/packages/yoroi-extension/app/assets/images/yoroi-modern-theme.inline.svg b/packages/yoroi-extension/app/assets/images/yoroi-modern-theme.inline.svg index 789d3a4816..b0a8048130 100644 --- a/packages/yoroi-extension/app/assets/images/yoroi-modern-theme.inline.svg +++ b/packages/yoroi-extension/app/assets/images/yoroi-modern-theme.inline.svg @@ -1,26 +1,13 @@ - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + diff --git a/packages/yoroi-extension/app/components/settings/categories/general-setting/ThemeSettingsBlock.js b/packages/yoroi-extension/app/components/settings/categories/general-setting/ThemeSettingsBlock.js index b67ba383fd..0d8613de18 100644 --- a/packages/yoroi-extension/app/components/settings/categories/general-setting/ThemeSettingsBlock.js +++ b/packages/yoroi-extension/app/components/settings/categories/general-setting/ThemeSettingsBlock.js @@ -221,7 +221,7 @@ export default class ThemeSettingsBlock extends Component { > - + } label='Modern' /> @@ -411,7 +411,7 @@ export default class ThemeSettingsBlock extends Component { > - + } label='Modern' /> @@ -424,84 +424,6 @@ export default class ThemeSettingsBlock extends Component { ) } - {/* {commonHeader} - - - - {currentTheme === THEMES.YOROI_MODERN && hasCustomTheme() && ( - - {intl.formatMessage(messages.themeWarning)} - - )} - - - {intl.formatMessage(messages.themeYoroiModern)} - - - - {currentTheme === THEMES.YOROI_CLASSIC && hasCustomTheme() && ( - - {intl.formatMessage(messages.themeWarning)} - - )} - - - {intl.formatMessage(messages.themeYoroiClassic)} - - - - - - - - {shouldDisplayRevampButton && ( - - - - )} */}
) } From c40bcb5ee4fc7d6fbe4579625c4e432e042e062e Mon Sep 17 00:00:00 2001 From: Ahmed Ibrahim Date: Mon, 13 Jun 2022 13:50:30 +0200 Subject: [PATCH 014/153] Remove unused components --- .../general-setting/ThemeSettingsBlock.js | 31 ++----------------- 1 file changed, 2 insertions(+), 29 deletions(-) diff --git a/packages/yoroi-extension/app/components/settings/categories/general-setting/ThemeSettingsBlock.js b/packages/yoroi-extension/app/components/settings/categories/general-setting/ThemeSettingsBlock.js index 0d8613de18..52122e59f4 100644 --- a/packages/yoroi-extension/app/components/settings/categories/general-setting/ThemeSettingsBlock.js +++ b/packages/yoroi-extension/app/components/settings/categories/general-setting/ThemeSettingsBlock.js @@ -374,6 +374,7 @@ export default class ThemeSettingsBlock extends Component { />
+ { currentTheme !== THEMES.YOROI_REVAMP && ( @@ -427,32 +428,4 @@ export default class ThemeSettingsBlock extends Component { ) } -} - -const WarningMessage = styled(Typography)({ - position: 'absolute', - top: 'calc(50% - 37px)', - left: 0, - backgroundColor: 'var(--yoroi-palette-background-banner-warning)', - color: 'var(--yoroi-palette-common-white)', - padding: '10px', -}); - -const ThemeButton = styled(IconButton)(({ isActive }) => ({ - borderRadius: 0, - display: 'flex', - flexDirection: 'column', - opacity: isActive ? 1 : 0.5, - svg: { - width: '300px', - boxShadow: '0 5px 30px 0px rgba(24, 26, 30, 0.12)', - }, - marginBottom: '32px', - ':hover': { background: 'transparent' }, -})); - -const RadioButton = styled(Radio)({ - '&.Mui-checked': { - color: '#4B6DDE', - }, -}) \ No newline at end of file +} \ No newline at end of file From 502b2c0ccb696350a45585dced9aba3bb0ebd36b Mon Sep 17 00:00:00 2001 From: Ahmed Ibrahim Date: Mon, 13 Jun 2022 14:51:34 +0200 Subject: [PATCH 015/153] Flow & eslint --- .../general-setting/ThemeSettingsBlock.js | 240 +----------------- .../categories/GeneralSettingsPage.js | 8 - 2 files changed, 4 insertions(+), 244 deletions(-) diff --git a/packages/yoroi-extension/app/components/settings/categories/general-setting/ThemeSettingsBlock.js b/packages/yoroi-extension/app/components/settings/categories/general-setting/ThemeSettingsBlock.js index 52122e59f4..a541cac061 100644 --- a/packages/yoroi-extension/app/components/settings/categories/general-setting/ThemeSettingsBlock.js +++ b/packages/yoroi-extension/app/components/settings/categories/general-setting/ThemeSettingsBlock.js @@ -1,18 +1,14 @@ // @flow import { Component } from 'react'; -import type { Node, ComponentType } from 'react'; +import type { Node } from 'react'; import { observer } from 'mobx-react'; -import { Button, FormControlLabel, IconButton, Radio, RadioGroup, Typography } from '@mui/material'; -import { Box, styled } from '@mui/system'; +import { FormControlLabel, Radio, RadioGroup, Typography } from '@mui/material'; +import { Box } from '@mui/system'; import { defineMessages, intlShape, FormattedMessage, FormattedHTMLMessage } from 'react-intl'; import { THEMES } from '../../../../styles/utils'; import type { Theme } from '../../../../styles/utils'; -import ThemeThumbnail from '../display/ThemeThumbnail'; import type { $npm$ReactIntl$IntlFormat } from 'react-intl'; import globalMessages from '../../../../i18n/global-messages'; -import { withLayout } from '../../../../styles/context/layout'; -import type { LayoutComponentMap } from '../../../../styles/context/layout'; -import environment from '../../../../environment'; import { ReactComponent as YoroiModernTheme } from '../../../../assets/images/yoroi-modern-theme.inline.svg'; import { ReactComponent as YoroiClassicTheme } from '../../../../assets/images/yoroi-classic-theme.inline.svg'; @@ -78,20 +74,14 @@ const messages = defineMessages({ type Props = {| +currentTheme: Theme, +selectTheme: ({| theme: string |}) => PossiblyAsync, - +exportTheme: void => PossiblyAsync, - +hasCustomTheme: void => boolean, +onExternalLinkClick: MouseEvent => void, +switchToFirstWallet: void => void, |}; -type InjectedProps = {| - +renderLayoutComponent: LayoutComponentMap => Node, -|}; -type AllProps = {| ...Props, ...InjectedProps |}; const NEW_THEME = THEMES.YOROI_REVAMP const OLD_THEME = `${THEMES.YOROI_MODERN}-${THEMES.YOROI_CLASSIC}` @observer -export default class ThemeSettingsBlock extends Component { +export default class ThemeSettingsBlock extends Component { static contextTypes: {| intl: $npm$ReactIntl$IntlFormat |} = { intl: intlShape.isRequired, }; @@ -100,8 +90,6 @@ export default class ThemeSettingsBlock extends Component { const { currentTheme, selectTheme, - exportTheme, - hasCustomTheme, onExternalLinkClick, } = this.props; const { intl } = this.context; @@ -122,225 +110,6 @@ export default class ThemeSettingsBlock extends Component { ); - const commonHeader = ( - <> - - {intl.formatMessage(messages.themeLabel)} - - - - - - - - - ); - - const shouldDisplayRevampButton = environment.isDev() - || environment.isNightly() - || environment.isTest(); - - const themeBlockClassicComponent = ( - - - {intl.formatMessage(messages.version)} - - - { - const theme = e.target.value === NEW_THEME ? NEW_THEME : THEMES.YOROI_MODERN - selectTheme({ theme }) - }} - sx={{ - display: 'flex', - flexDirection: 'row', - }} - > - } - label={intl.formatMessage(messages.currentVersion)} - sx={{ - marginRight: '20px' - }} - /> - } - label={intl.formatMessage(messages.newVersion)} - /> - - - { - currentTheme !== THEMES.YOROI_REVAMP && ( - - - - {intl.formatMessage(messages.selectColorTheme)} - - - - - - - - - - - { - selectTheme({ theme: e.target.value }) - }} - > - - - - - } label='Modern' /> - - - - } label='classic' /> - - - - - ) - } - {/* {commonHeader} - - - - {currentTheme === THEMES.YOROI_MODERN && hasCustomTheme() && ( - - {intl.formatMessage(messages.themeWarning)} - - )} - - - {intl.formatMessage(messages.themeYoroiModern)} - - - - {currentTheme === THEMES.YOROI_CLASSIC && hasCustomTheme() && ( - - {intl.formatMessage(messages.themeWarning)} - - )} - - - {intl.formatMessage(messages.themeYoroiClassic)} - - - - - - - - {shouldDisplayRevampButton && ( - - - - )} */} - - ); - - const themeBlockRevampComponent = ( - - {commonHeader} - - - - {(environment.isNightly() || environment.isTest() || environment.isDev()) && ( - - - - )} - - ); return ( @@ -374,7 +143,6 @@ export default class ThemeSettingsBlock extends Component { /> - { currentTheme !== THEMES.YOROI_REVAMP && ( diff --git a/packages/yoroi-extension/app/containers/settings/categories/GeneralSettingsPage.js b/packages/yoroi-extension/app/containers/settings/categories/GeneralSettingsPage.js index cee6491d29..da2fcd51fa 100644 --- a/packages/yoroi-extension/app/containers/settings/categories/GeneralSettingsPage.js +++ b/packages/yoroi-extension/app/containers/settings/categories/GeneralSettingsPage.js @@ -138,8 +138,6 @@ export default class GeneralSettingsPage extends Component Promise, - |}, updateLocale: {| trigger: (params: {| locale: string, @@ -187,7 +182,6 @@ export default class GeneralSettingsPage extends Component, currentLocale: string, currentTheme: Theme, - hasCustomTheme: void => boolean, setProfileLocaleRequest: {| error: ?LocalizableError, isExecuting: boolean, @@ -237,7 +231,6 @@ export default class GeneralSettingsPage extends Component Date: Fri, 17 Jun 2022 13:35:11 +0200 Subject: [PATCH 016/153] Create NFTs pages wrapper --- packages/yoroi-extension/app/Routes.js | 61 ++++++- .../images/sidebar/revamp/nfts.inline.svg | 4 + .../app/containers/wallet/NFTsWrapper.js | 169 ++++++++++++++++++ .../app/i18n/global-messages.js | 4 + .../app/i18n/locales/en-US.json | 1 + .../app/stores/stateless/sidebarCategories.js | 8 + 6 files changed, 245 insertions(+), 2 deletions(-) create mode 100644 packages/yoroi-extension/app/assets/images/sidebar/revamp/nfts.inline.svg create mode 100644 packages/yoroi-extension/app/containers/wallet/NFTsWrapper.js diff --git a/packages/yoroi-extension/app/Routes.js b/packages/yoroi-extension/app/Routes.js index 2bd4637dc8..cb66211299 100644 --- a/packages/yoroi-extension/app/Routes.js +++ b/packages/yoroi-extension/app/Routes.js @@ -41,59 +41,88 @@ const SupportSettingsPage = React.lazy(SupportSettingsPagePromise); // Dynamic container loading - resolver loads file relative to '/app/' directory const LoadingPagePromise = () => import('./containers/LoadingPage'); const LoadingPage = React.lazy(LoadingPagePromise); + const NightlyPagePromise = () => import('./containers/profile/NightlyPage'); const NightlyPage = React.lazy(NightlyPagePromise); + const WalletPromise = () => import('./containers/wallet/Wallet'); const Wallet = React.lazy(WalletPromise); + const MyWalletsPagePromise = () => import('./containers/wallet/MyWalletsPage'); const MyWalletsPage = React.lazy(MyWalletsPagePromise); + const WalletSummaryPagePromise = () => import('./containers/wallet/WalletSummaryPage'); const WalletSummaryPage = React.lazy(WalletSummaryPagePromise); + const WalletSendPagePromise = () => import('./containers/wallet/WalletSendPage'); const WalletSendPage = React.lazy(WalletSendPagePromise); + const WalletAssetsPagePromise = () => import('./containers/wallet/WalletAssetsPage'); const WalletAssetsPage = React.lazy(WalletAssetsPagePromise); + const WalletReceivePagePromise = () => import('./containers/wallet/WalletReceivePage'); const WalletReceivePage = React.lazy(WalletReceivePagePromise); + const URILandingPagePromise = () => import('./containers/uri/URILandingPage'); const URILandingPage = React.lazy(URILandingPagePromise); + const TransferPromise = () => import('./containers/transfer/Transfer'); const Transfer = React.lazy(TransferPromise); + const ReceivePromise = () => import('./containers/wallet/Receive'); const Receive = React.lazy(ReceivePromise); + const StakingDashboardPagePromise = () => import('./containers/wallet/staking/StakingDashboardPage'); const StakingDashboardPage = React.lazy(StakingDashboardPagePromise); + const CardanoStakingPagePromise = () => import('./containers/wallet/staking/CardanoStakingPage'); const CardanoStakingPage = React.lazy(CardanoStakingPagePromise); + const NoticeBoardPagePromise = () => import('./containers/notice-board/NoticeBoardPage'); const NoticeBoardPage = React.lazy(NoticeBoardPagePromise); + const VotingPagePromise = () => import('./containers/wallet/voting/VotingPage'); const VotingPage = React.lazy(VotingPagePromise); const ComplexityLevelSettingsPagePromise = () => import('./containers/settings/categories/ComplexityLevelSettingsPage'); const ComplexityLevelSettingsPage = React.lazy(ComplexityLevelSettingsPagePromise); + const ComplexityLevelPagePromise = () => import('./containers/profile/ComplexityLevelPage'); const ComplexityLevelPage = React.lazy(ComplexityLevelPagePromise); + const BlockchainSettingsPagePromise = () => import('./containers/settings/categories/BlockchainSettingsPage'); const BlockchainSettingsPage = React.lazy(BlockchainSettingsPagePromise); + const WalletSwitchPromise = () => import('./containers/WalletSwitch'); const WalletSwitch = React.lazy(WalletSwitchPromise); + const StakingPagePromise = () => import('./containers/wallet/staking/StakingPage'); const StakingPage = React.lazy(StakingPagePromise); + const AssetsWrapperPromise = () => import('./containers/wallet/AssetsWrapper'); const AssetsWrapper = React.lazy(AssetsWrapperPromise); + +const NFTsWrapperPromise = () => import('./containers/wallet/NFTsWrapper'); +const NFTsWrapper = React.lazy(NFTsWrapperPromise); + const TokensPageRevampPromise = () => import('./containers/wallet/TokensPageRevamp'); const TokensPageRevamp = React.lazy(TokensPageRevampPromise); + const TokensDetailPageRevampPromise = () => import('./containers/wallet/TokenDetailPageRevamp'); const TokensDetailPageRevamp = React.lazy(TokensDetailPageRevampPromise); + const NFTsPageRevampPromise = () => import('./containers/wallet/NFTsPageRevamp'); const NFTsPageRevamp = React.lazy(NFTsPageRevampPromise); + const NFTDetailPageRevampPromise = () => import('./containers/wallet/NFTDetailPageRevamp'); const NFTDetailPageRevamp = React.lazy(NFTDetailPageRevampPromise); + const ConnectedWebsitesPagePromise = () => import('./containers/dapp-connector/ConnectedWebsitesContainer'); const ConnectedWebsitesPage = React.lazy(ConnectedWebsitesPagePromise); + const YoroiPalettePagePromise = () => import('./containers/experimental/YoroiPalette'); const YoroiPalettePage = React.lazy(YoroiPalettePagePromise); + const YoroiThemesPagePromise = () => import('./containers/experimental/yoroiThemes'); const YoroiThemesPage = React.lazy(YoroiThemesPagePromise); @@ -198,6 +227,17 @@ export const Routes = ( ) )} /> + + ( + wrapNFTs( + { ...props, stores, actions }, + NFTsSubPages(stores, actions) + ) + )} + /> + ( path={ROUTES.ASSETS.TOKEN_DETAILS} component={(props) => } /> + +); + +const NFTsSubPages = (stores, actions) => ( + ( path={ROUTES.ASSETS.NFT_DETAILS} component={(props) => } /> - -); +) /* eslint-enable max-len */ export function wrapSettings( @@ -409,6 +453,19 @@ export function wrapAssets( ); } +export function wrapNFTs( + assetsProps: InjectedOrGenerated, + children: Node, +): Node { + return ( + + {children} + + ); +} + export function wrapWallet( walletProps: InjectedOrGenerated, children: Node, diff --git a/packages/yoroi-extension/app/assets/images/sidebar/revamp/nfts.inline.svg b/packages/yoroi-extension/app/assets/images/sidebar/revamp/nfts.inline.svg new file mode 100644 index 0000000000..d3ba617d37 --- /dev/null +++ b/packages/yoroi-extension/app/assets/images/sidebar/revamp/nfts.inline.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/yoroi-extension/app/containers/wallet/NFTsWrapper.js b/packages/yoroi-extension/app/containers/wallet/NFTsWrapper.js new file mode 100644 index 0000000000..1821683361 --- /dev/null +++ b/packages/yoroi-extension/app/containers/wallet/NFTsWrapper.js @@ -0,0 +1,169 @@ +// @flow +import type { Node } from 'react'; +import { Component } from 'react'; +import { observer } from 'mobx-react'; +import { computed } from 'mobx'; +import type { InjectedOrGenerated } from '../../types/injectedPropsType'; +import { PublicDeriver } from '../../api/ada/lib/storage/models/PublicDeriver/index'; +import { MultiToken } from '../../api/common/lib/MultiToken'; +import type { TokenInfoMap } from '../../stores/toplevel/TokenInfoStore'; +import type { TokenRow } from '../../api/ada/lib/storage/database/primitives/tables'; +import type { TxRequests } from '../../stores/toplevel/TransactionsStore'; +import TopBarLayout from '../../components/layout/TopBarLayout'; +import BannerContainer from '../banners/BannerContainer'; +import NavBarContainerRevamp from '../NavBarContainerRevamp'; +import NavBarTitle from '../../components/topbar/NavBarTitle'; +import globalMessages from '../../i18n/global-messages'; +import SidebarContainer from '../SidebarContainer'; +import type { $npm$ReactIntl$IntlFormat } from 'react-intl'; +import { intlShape } from 'react-intl'; +import type { GeneratedData as BannerContainerData } from '../banners/BannerContainer'; +import type { GeneratedData as SidebarContainerData } from '../SidebarContainer'; +import type { GeneratedData as NavBarContainerRevampData } from '../NavBarContainerRevamp'; +import { buildRoute } from '../../utils/routing'; +import AssetsMenu from '../../components/wallet/assets/AssetsMenu'; +import { matchPath } from 'react-router'; + +export type GeneratedData = typeof NFTsWrapper.prototype.generated; +type Props = {| + ...InjectedOrGenerated, + +children?: Node, +|}; +@observer +export default class NFTsWrapper extends Component { + static contextTypes: {| intl: $npm$ReactIntl$IntlFormat |} = { + intl: intlShape.isRequired, + }; + static defaultProps: {| children: void |} = { + children: undefined, + }; + isActivePage: string => boolean = route => { + const { location } = this.generated.stores.router; + if (location) { + return !!matchPath(location.pathname, { + path: buildRoute(route), + exact: false, + }); + } + return false; + }; + + render(): Node { + const publicDeriver = this.generated.stores.wallets.selected; + if (!publicDeriver) throw new Error(`Active wallet required for ${nameof(AssetsWrapper)}.`); + + const { intl } = this.context; + const { actions } = this.generated; + const sidebarContainer = ; + + const menu = ( + actions.router.goToRoute.trigger({ route })} + isActiveItem={this.isActivePage} + /> + ); + + return ( + } + sidebar={sidebarContainer} + navbar={ + } + menu={menu} + /> + } + showInContainer + showAsCard + > + {this.props.children} + + ); + } + + @computed get generated(): {| + BannerContainerProps: InjectedOrGenerated, + SidebarContainerProps: InjectedOrGenerated, + NavBarContainerRevampProps: InjectedOrGenerated, + + stores: {| + router: {| location: any |}, + tokenInfoStore: {| + tokenInfo: TokenInfoMap, + getDefaultTokenInfo: number => $ReadOnly, + |}, + transactions: {| + getBalanceRequest: {| + result: ?MultiToken, + |}, + getTxRequests: (PublicDeriver<>) => TxRequests, + |}, + wallets: {| selected: null | PublicDeriver<> |}, + profile: {| + shouldHideBalance: boolean, + |}, + |}, + actions: {| + router: {| + goToRoute: {| + trigger: (params: {| + publicDeriver?: null | PublicDeriver<>, + params?: ?any, + route: string, + |}) => void, + |}, + |}, + |}, + |} { + if (this.props.generated !== undefined) { + return this.props.generated; + } + if (this.props.stores == null || this.props.actions == null) { + throw new Error(`${nameof(AssetsWrapper)} no way to generated props`); + } + const { stores, actions } = this.props; + return Object.freeze({ + stores: { + router: { + location: stores.router.location, + }, + wallets: { + selected: stores.wallets.selected, + }, + tokenInfoStore: { + tokenInfo: stores.tokenInfoStore.tokenInfo, + getDefaultTokenInfo: stores.tokenInfoStore.getDefaultTokenInfo, + }, + transactions: { + getBalanceRequest: (() => { + if (stores.wallets.selected == null) + return { + result: undefined, + }; + const { requests } = stores.transactions.getTxRequests(stores.wallets.selected); + + return { + result: requests.getBalanceRequest.result, + }; + })(), + getTxRequests: stores.transactions.getTxRequests, + }, + profile: { + shouldHideBalance: stores.profile.shouldHideBalance, + }, + }, + actions: { + router: { + goToRoute: { trigger: actions.router.goToRoute.trigger }, + }, + }, + BannerContainerProps: ({ actions, stores }: InjectedOrGenerated), + NavBarContainerRevampProps: ({ + actions, + stores, + }: InjectedOrGenerated), + SidebarContainerProps: ({ actions, stores }: InjectedOrGenerated), + }); + } +} diff --git a/packages/yoroi-extension/app/i18n/global-messages.js b/packages/yoroi-extension/app/i18n/global-messages.js index 388de29d7a..0836c3b14c 100644 --- a/packages/yoroi-extension/app/i18n/global-messages.js +++ b/packages/yoroi-extension/app/i18n/global-messages.js @@ -634,6 +634,10 @@ const globalMessages: * = defineMessages({ id: 'sidebar.assets', defaultMessage: '!!!Assets', }, + sidebarNfts: { + id: 'sidebar.nfts', + defaultMessage: '!!!NFTs', + }, sidebarVoting: { id: 'sidebar.voting', defaultMessage: '!!!Voting', diff --git a/packages/yoroi-extension/app/i18n/locales/en-US.json b/packages/yoroi-extension/app/i18n/locales/en-US.json index d75b2a01fe..c7febc2d9f 100644 --- a/packages/yoroi-extension/app/i18n/locales/en-US.json +++ b/packages/yoroi-extension/app/i18n/locales/en-US.json @@ -354,6 +354,7 @@ "settings.unitOfAccount.note": "Note: coin price is approximate and may not match the price of any given trading platform. Any transactions based on these price approximates are done at your own risk.", "settings.unitOfAccount.title": "Fiat pairing", "sidebar.assets": "Assets", + "sidebar.nfts": "NFTs", "sidebar.faq": "Faq", "sidebar.feedback": "Feedback", "sidebar.newUpdates": "New updates", diff --git a/packages/yoroi-extension/app/stores/stateless/sidebarCategories.js b/packages/yoroi-extension/app/stores/stateless/sidebarCategories.js index 610021420a..6ad2049d5e 100644 --- a/packages/yoroi-extension/app/stores/stateless/sidebarCategories.js +++ b/packages/yoroi-extension/app/stores/stateless/sidebarCategories.js @@ -15,6 +15,7 @@ import { asGetStakingKey } from '../../api/ada/lib/storage/models/PublicDeriver/ import { ReactComponent as walletIcon } from '../../assets/images/sidebar/revamp/wallet.inline.svg'; import { ReactComponent as stakingIcon } from '../../assets/images/sidebar/revamp/staking.inline.svg'; import { ReactComponent as assetsIcon } from '../../assets/images/sidebar/revamp/assets.inline.svg'; +import { ReactComponent as nftsIcon } from '../../assets/images/sidebar/revamp/nfts.inline.svg'; import { ReactComponent as votingIcon } from '../../assets/images/sidebar/revamp/voting.inline.svg'; // import { ReactComponent as swapIcon } from '../../assets/images/sidebar/revamp/swap.inline.svg'; import { ReactComponent as settingIcon } from '../../assets/images/sidebar/revamp/setting.inline.svg'; @@ -140,6 +141,13 @@ export const allCategoriesRevamp: Array = [ label: globalMessages.sidebarAssets, isVisible: _request => _request.selected !== null, }, + { + className: 'nfts', + route: ROUTES.ASSETS.NFTS, + icon: nftsIcon, + label: globalMessages.sidebarNfts, + isVisible: _request => _request.selected !== null, + }, { className: 'voting', route: ROUTES.WALLETS.CATALYST_VOTING, From 5908909be51e4592e84c211f29042297691b3b3c Mon Sep 17 00:00:00 2001 From: Ahmed Ibrahim Date: Fri, 17 Jun 2022 13:55:18 +0200 Subject: [PATCH 017/153] Create seperate routes for NFT page --- packages/yoroi-extension/app/Routes.js | 10 ++++----- .../components/wallet/assets/AssetsMenu.js | 4 ++-- .../app/components/wallet/assets/NFTsList.js | 2 +- .../components/wallet/assets/TokenDetails.js | 2 +- .../app/components/wallet/assets/TokenList.js | 2 +- .../app/containers/wallet/AssetsWrapper.js | 22 ------------------- .../app/containers/wallet/NFTsWrapper.js | 3 +-- packages/yoroi-extension/app/routes-config.js | 9 ++++---- .../app/stores/stateless/sidebarCategories.js | 2 +- 9 files changed, 17 insertions(+), 39 deletions(-) diff --git a/packages/yoroi-extension/app/Routes.js b/packages/yoroi-extension/app/Routes.js index cb66211299..bc4672a430 100644 --- a/packages/yoroi-extension/app/Routes.js +++ b/packages/yoroi-extension/app/Routes.js @@ -229,7 +229,7 @@ export const Routes = ( /> ( wrapNFTs( { ...props, stores, actions }, @@ -400,12 +400,12 @@ const AssetsSubpages = (stores, actions) => ( } /> } /> @@ -415,12 +415,12 @@ const NFTsSubPages = (stores, actions) => ( } /> } /> diff --git a/packages/yoroi-extension/app/components/wallet/assets/AssetsMenu.js b/packages/yoroi-extension/app/components/wallet/assets/AssetsMenu.js index c1f74bdf39..1503443478 100644 --- a/packages/yoroi-extension/app/components/wallet/assets/AssetsMenu.js +++ b/packages/yoroi-extension/app/components/wallet/assets/AssetsMenu.js @@ -25,11 +25,11 @@ export default class AssetsMenu extends Component { const settingOptions: Array = [ { label: intl.formatMessage(globalMessages.tokens), - route: ROUTES.ASSETS.TOKENS, + route: ROUTES.ASSETS.ROOT, }, { label: 'NFTs', - route: ROUTES.ASSETS.NFTS, + route: ROUTES.NFTS.ROOT, }, ]; diff --git a/packages/yoroi-extension/app/components/wallet/assets/NFTsList.js b/packages/yoroi-extension/app/components/wallet/assets/NFTsList.js index 087d16bc0a..379598b847 100644 --- a/packages/yoroi-extension/app/components/wallet/assets/NFTsList.js +++ b/packages/yoroi-extension/app/components/wallet/assets/NFTsList.js @@ -95,7 +95,7 @@ function NfTsList({ list, intl }: Props & Intl): Node { {nftList.map(nft => { return ( - + ); diff --git a/packages/yoroi-extension/app/components/wallet/assets/TokenDetails.js b/packages/yoroi-extension/app/components/wallet/assets/TokenDetails.js index ae492ee2a4..ed5539ea1e 100644 --- a/packages/yoroi-extension/app/components/wallet/assets/TokenDetails.js +++ b/packages/yoroi-extension/app/components/wallet/assets/TokenDetails.js @@ -90,7 +90,7 @@ function TokenDetails({ tokenInfo, tokensCount, network, intl }: Props & Intl): {name} diff --git a/packages/yoroi-extension/app/containers/wallet/AssetsWrapper.js b/packages/yoroi-extension/app/containers/wallet/AssetsWrapper.js index 078036d125..64cb716ede 100644 --- a/packages/yoroi-extension/app/containers/wallet/AssetsWrapper.js +++ b/packages/yoroi-extension/app/containers/wallet/AssetsWrapper.js @@ -20,9 +20,6 @@ import { intlShape } from 'react-intl'; import type { GeneratedData as BannerContainerData } from '../banners/BannerContainer'; import type { GeneratedData as SidebarContainerData } from '../SidebarContainer'; import type { GeneratedData as NavBarContainerRevampData } from '../NavBarContainerRevamp'; -import { buildRoute } from '../../utils/routing'; -import AssetsMenu from '../../components/wallet/assets/AssetsMenu'; -import { matchPath } from 'react-router'; export type GeneratedData = typeof AssetsWrapper.prototype.generated; type Props = {| @@ -37,32 +34,14 @@ export default class AssetsWrapper extends Component { static defaultProps: {| children: void |} = { children: undefined, }; - isActivePage: string => boolean = route => { - const { location } = this.generated.stores.router; - if (location) { - return !!matchPath(location.pathname, { - path: buildRoute(route), - exact: false, - }); - } - return false; - }; render(): Node { const publicDeriver = this.generated.stores.wallets.selected; if (!publicDeriver) throw new Error(`Active wallet required for ${nameof(AssetsWrapper)}.`); const { intl } = this.context; - const { actions } = this.generated; const sidebarContainer = ; - const menu = ( - actions.router.goToRoute.trigger({ route })} - isActiveItem={this.isActivePage} - /> - ); - return ( } @@ -71,7 +50,6 @@ export default class AssetsWrapper extends Component { } - menu={menu} /> } showInContainer diff --git a/packages/yoroi-extension/app/containers/wallet/NFTsWrapper.js b/packages/yoroi-extension/app/containers/wallet/NFTsWrapper.js index 1821683361..2edc96afc8 100644 --- a/packages/yoroi-extension/app/containers/wallet/NFTsWrapper.js +++ b/packages/yoroi-extension/app/containers/wallet/NFTsWrapper.js @@ -70,8 +70,7 @@ export default class NFTsWrapper extends Component { navbar={ } - menu={menu} + title={} /> } showInContainer diff --git a/packages/yoroi-extension/app/routes-config.js b/packages/yoroi-extension/app/routes-config.js index ff4536e54d..ecad94ac1f 100644 --- a/packages/yoroi-extension/app/routes-config.js +++ b/packages/yoroi-extension/app/routes-config.js @@ -56,10 +56,11 @@ export const ROUTES = { STAKING: '/staking', ASSETS: { ROOT: '/assets', - TOKENS: '/assets/tokens', - TOKEN_DETAILS: '/assets/tokens/:tokenId', - NFTS: '/assets/nfts', - NFT_DETAILS: '/assets/nfts/:nftId' + DETAILS: '/assets/tokens/:tokenId', + }, + NFTS: { + ROOT: '/nfts', + DETAILS: '/nfts/:nftId' }, DAPP_CONNECTOR: { CONNECTED_WEBSITES: '/connector/connected-websites' diff --git a/packages/yoroi-extension/app/stores/stateless/sidebarCategories.js b/packages/yoroi-extension/app/stores/stateless/sidebarCategories.js index 6ad2049d5e..95f8ee32e7 100644 --- a/packages/yoroi-extension/app/stores/stateless/sidebarCategories.js +++ b/packages/yoroi-extension/app/stores/stateless/sidebarCategories.js @@ -143,7 +143,7 @@ export const allCategoriesRevamp: Array = [ }, { className: 'nfts', - route: ROUTES.ASSETS.NFTS, + route: ROUTES.NFTS.ROOT, icon: nftsIcon, label: globalMessages.sidebarNfts, isVisible: _request => _request.selected !== null, From 66f53d60abd56334d06e2cebbcd8b968f96628ee Mon Sep 17 00:00:00 2001 From: Ahmed Ibrahim Date: Fri, 17 Jun 2022 14:31:56 +0200 Subject: [PATCH 018/153] Siwth to use token id insead into name --- .../app/components/wallet/assets/NFTDetails.js | 2 +- .../yoroi-extension/app/components/wallet/assets/NFTsList.js | 2 +- .../app/containers/wallet/NFTDetailPageRevamp.js | 4 ++-- .../yoroi-extension/app/containers/wallet/NFTsPageRevamp.js | 1 + 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/yoroi-extension/app/components/wallet/assets/NFTDetails.js b/packages/yoroi-extension/app/components/wallet/assets/NFTDetails.js index 2045886755..648bccaf07 100644 --- a/packages/yoroi-extension/app/components/wallet/assets/NFTDetails.js +++ b/packages/yoroi-extension/app/components/wallet/assets/NFTDetails.js @@ -46,7 +46,7 @@ function NFTDetails({ nftInfo, nftsCount, network, intl }: Props & Intl): Node { {nftList.map(nft => { return ( - + ); diff --git a/packages/yoroi-extension/app/containers/wallet/NFTDetailPageRevamp.js b/packages/yoroi-extension/app/containers/wallet/NFTDetailPageRevamp.js index e48a273340..31d57ee7f6 100644 --- a/packages/yoroi-extension/app/containers/wallet/NFTDetailPageRevamp.js +++ b/packages/yoroi-extension/app/containers/wallet/NFTDetailPageRevamp.js @@ -37,7 +37,7 @@ class NFTDetailPageRevamp extends Component { const publicDeriver = this.generated.stores.wallets.selected; // Guard against potential null values if (!publicDeriver) - throw new Error(`Active wallet requiTokenDetails)}d for ${nameof(NFTDetailPageRevamp)}.`); + throw new Error(`Active wallet requiTokenDetails for ${nameof(NFTDetailPageRevamp)}.`); const spendableBalance = this.generated.stores.transactions.getBalanceRequest.result; const getTokenInfo = genLookupOrFail(this.generated.stores.tokenInfoStore.tokenInfo); const network = publicDeriver.getParent().getNetworkInfo(); @@ -85,7 +85,7 @@ class NFTDetailPageRevamp extends Component { })); const { nftId } = this.props.match.params; - const nftInfo = nftsList.find(nft => nft.name === nftId); + const nftInfo = nftsList.find(nft => nft.id === nftId); return ( diff --git a/packages/yoroi-extension/app/containers/wallet/NFTsPageRevamp.js b/packages/yoroi-extension/app/containers/wallet/NFTsPageRevamp.js index 907d718f2d..d3b38f0b1c 100644 --- a/packages/yoroi-extension/app/containers/wallet/NFTsPageRevamp.js +++ b/packages/yoroi-extension/app/containers/wallet/NFTsPageRevamp.js @@ -50,6 +50,7 @@ export default class NFTsPageRevamp extends Component ({ + id: item.id, name: item.name, image: item.nftMetadata?.image, })); From 065cddd2fa5790f98b276db70f10a346cc187f55 Mon Sep 17 00:00:00 2001 From: Ahmed Ibrahim Date: Mon, 20 Jun 2022 00:22:12 +0200 Subject: [PATCH 019/153] Add default nft image --- .../app/assets/images/default-nft.inline.svg | 33 +++++++++++++ .../components/wallet/assets/NFTDetails.js | 2 +- .../app/components/wallet/assets/NFTsList.js | 49 +++++++++++++++++-- 3 files changed, 78 insertions(+), 6 deletions(-) create mode 100644 packages/yoroi-extension/app/assets/images/default-nft.inline.svg diff --git a/packages/yoroi-extension/app/assets/images/default-nft.inline.svg b/packages/yoroi-extension/app/assets/images/default-nft.inline.svg new file mode 100644 index 0000000000..33ffcb85da --- /dev/null +++ b/packages/yoroi-extension/app/assets/images/default-nft.inline.svg @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/yoroi-extension/app/components/wallet/assets/NFTDetails.js b/packages/yoroi-extension/app/components/wallet/assets/NFTDetails.js index 648bccaf07..7d9089d314 100644 --- a/packages/yoroi-extension/app/components/wallet/assets/NFTDetails.js +++ b/packages/yoroi-extension/app/components/wallet/assets/NFTDetails.js @@ -53,7 +53,7 @@ function NFTDetails({ nftInfo, nftsCount, network, intl }: Props & Intl): Node { textDecoration: 'none', }} > - NFTs ({nftsCount}) ->{' '} + NFTs ({nftsCount}){' '}/{' '} {nftInfo.name} diff --git a/packages/yoroi-extension/app/components/wallet/assets/NFTsList.js b/packages/yoroi-extension/app/components/wallet/assets/NFTsList.js index 9bc95dd87e..f34c0a7e87 100644 --- a/packages/yoroi-extension/app/components/wallet/assets/NFTsList.js +++ b/packages/yoroi-extension/app/components/wallet/assets/NFTsList.js @@ -1,6 +1,6 @@ // @flow import type { ComponentType, Node } from 'react'; -import { Box, styled } from '@mui/system'; +import { Box, minHeight, styled } from '@mui/system'; import { IconButton, ImageList, @@ -9,14 +9,17 @@ import { InputAdornment, Stack, Typography, + Skeleton } from '@mui/material'; import { assetsMessage } from './AssetsList'; import { ReactComponent as Search } from '../../../assets/images/assets-page/search.inline.svg'; +import { ReactComponent as DefaultNFT } from '../../../assets/images/default-nft.inline.svg'; + import { defineMessages, injectIntl } from 'react-intl'; import type { $npm$ReactIntl$IntlShape } from 'react-intl'; import { Link } from 'react-router-dom'; import { ROUTES } from '../../../routes-config'; -import { useState } from 'react'; +import { useState, useEffect } from 'react'; import { ListEmpty } from './ListEmpty'; type Props = {| @@ -108,12 +111,48 @@ function NfTsList({ list, intl }: Props & Intl): Node { export default (injectIntl(NfTsList): ComponentType); -function NftCardImage({ ipfsUrl, name }) { - const ipfsHash = ipfsUrl != null ? ipfsUrl.replace('ipfs://', '') : ''; +function isImageExist(imageSrc, onload, onerror) { + const img = new Image(); + img.onload = onload; + img.onerror = onerror; + img.src = imageSrc; +} + +function NftImage({ ipfsUrl, name }) { + const [loading, setLoading] = useState(true); + const [error, setError] = useState(false); + if (error || !ipfsUrl) return ( + + + + ) + ipfsUrl = ipfsUrl.replace('ipfs://', 'https://ipfs.io/ipfs/'); + useEffect(() => { + isImageExist( + ipfsUrl, + () => { setLoading(false); setError(false) }, // on-success + () => { setLoading(false); setError(true) }, // on-error + ) + }, [ipfsUrl]) + + if (loading) return + return {name} +} +function NftCardImage({ ipfsUrl, name }) { return ( - {name} + {name} From 828d17c8d016899c2941259e58289fa42985a491 Mon Sep 17 00:00:00 2001 From: Ahmed Ibrahim Date: Mon, 20 Jun 2022 10:18:21 +0200 Subject: [PATCH 020/153] Check for '721' token metadata --- .../yoroi-extension/app/containers/wallet/NFTsPageRevamp.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/yoroi-extension/app/containers/wallet/NFTsPageRevamp.js b/packages/yoroi-extension/app/containers/wallet/NFTsPageRevamp.js index d3b38f0b1c..3890092452 100644 --- a/packages/yoroi-extension/app/containers/wallet/NFTsPageRevamp.js +++ b/packages/yoroi-extension/app/containers/wallet/NFTsPageRevamp.js @@ -46,7 +46,7 @@ export default class NFTsPageRevamp extends Component ({ From 7d873f96f0d367e02b225c1bbd85d18ffa367b1c Mon Sep 17 00:00:00 2001 From: Ahmed Ibrahim Date: Mon, 20 Jun 2022 10:57:24 +0200 Subject: [PATCH 021/153] Add NFT Gallary page title --- .../components/wallet/assets/AssetsMenu.js | 40 ------------------- .../app/containers/wallet/NFTsWrapper.js | 23 +++++------ .../app/i18n/locales/en-US.json | 1 + 3 files changed, 11 insertions(+), 53 deletions(-) delete mode 100644 packages/yoroi-extension/app/components/wallet/assets/AssetsMenu.js diff --git a/packages/yoroi-extension/app/components/wallet/assets/AssetsMenu.js b/packages/yoroi-extension/app/components/wallet/assets/AssetsMenu.js deleted file mode 100644 index 1503443478..0000000000 --- a/packages/yoroi-extension/app/components/wallet/assets/AssetsMenu.js +++ /dev/null @@ -1,40 +0,0 @@ -// @flow -import { Component } from 'react'; -import type { Node } from 'react'; -import { observer } from 'mobx-react'; -import { intlShape } from 'react-intl'; -import type { $npm$ReactIntl$IntlFormat } from 'react-intl'; -import globalMessages from '../../../i18n/global-messages'; -import { ROUTES } from '../../../routes-config'; -import SubMenu from '../../topbar/SubMenu'; - -type Props = {| - +isActiveItem: string => boolean, - +onItemClick: string => void, -|}; -@observer -export default class AssetsMenu extends Component { - static contextTypes: {| intl: $npm$ReactIntl$IntlFormat |} = { - intl: intlShape.isRequired, - }; - - render(): Node { - const { intl } = this.context; - const { onItemClick, isActiveItem } = this.props; - - const settingOptions: Array = [ - { - label: intl.formatMessage(globalMessages.tokens), - route: ROUTES.ASSETS.ROOT, - }, - { - label: 'NFTs', - route: ROUTES.NFTS.ROOT, - }, - ]; - - return ( - - ); - } -} diff --git a/packages/yoroi-extension/app/containers/wallet/NFTsWrapper.js b/packages/yoroi-extension/app/containers/wallet/NFTsWrapper.js index 2edc96afc8..9f6a2864f9 100644 --- a/packages/yoroi-extension/app/containers/wallet/NFTsWrapper.js +++ b/packages/yoroi-extension/app/containers/wallet/NFTsWrapper.js @@ -16,12 +16,11 @@ import NavBarTitle from '../../components/topbar/NavBarTitle'; import globalMessages from '../../i18n/global-messages'; import SidebarContainer from '../SidebarContainer'; import type { $npm$ReactIntl$IntlFormat } from 'react-intl'; -import { intlShape } from 'react-intl'; +import { intlShape, defineMessages } from 'react-intl'; import type { GeneratedData as BannerContainerData } from '../banners/BannerContainer'; import type { GeneratedData as SidebarContainerData } from '../SidebarContainer'; import type { GeneratedData as NavBarContainerRevampData } from '../NavBarContainerRevamp'; import { buildRoute } from '../../utils/routing'; -import AssetsMenu from '../../components/wallet/assets/AssetsMenu'; import { matchPath } from 'react-router'; export type GeneratedData = typeof NFTsWrapper.prototype.generated; @@ -29,6 +28,13 @@ type Props = {| ...InjectedOrGenerated, +children?: Node, |}; + +const messages = defineMessages({ + NFTGallery: { + id: 'wallet.nftGallary.title', + defaultMessage: '!!!NFT Gallary', + }, +}) @observer export default class NFTsWrapper extends Component { static contextTypes: {| intl: $npm$ReactIntl$IntlFormat |} = { @@ -50,19 +56,10 @@ export default class NFTsWrapper extends Component { render(): Node { const publicDeriver = this.generated.stores.wallets.selected; - if (!publicDeriver) throw new Error(`Active wallet required for ${nameof(AssetsWrapper)}.`); + if (!publicDeriver) throw new Error(`Active wallet required for ${nameof(NFTsWrapper)}.`); const { intl } = this.context; - const { actions } = this.generated; const sidebarContainer = ; - - const menu = ( - actions.router.goToRoute.trigger({ route })} - isActiveItem={this.isActivePage} - /> - ); - return ( } @@ -70,7 +67,7 @@ export default class NFTsWrapper extends Component { navbar={ } + title={} /> } showInContainer diff --git a/packages/yoroi-extension/app/i18n/locales/en-US.json b/packages/yoroi-extension/app/i18n/locales/en-US.json index c7febc2d9f..03cbe9d799 100644 --- a/packages/yoroi-extension/app/i18n/locales/en-US.json +++ b/packages/yoroi-extension/app/i18n/locales/en-US.json @@ -625,6 +625,7 @@ "wallet.navigation.voting": "Voting", "wallet.nowallet.subtitle": "Please select a wallet from the dropdown menu on the top right.", "wallet.nowallet.title": "No wallet selected.", + "wallet.nftGallary.title": "NFT Gallary", "wallet.problematic.explanation1": "The wallet you selected ({checksumTextPart}) was detected to contain some kind of issue.", "wallet.receive.confirmationDialog.addressDetailsTitleLabel": "Verify address", "wallet.receive.confirmationDialog.addressLabel": "Address", From fb39ee8324fda7defce304721c177ac648640755 Mon Sep 17 00:00:00 2001 From: Ahmed Ibrahim Date: Mon, 20 Jun 2022 11:18:12 +0200 Subject: [PATCH 022/153] Add nft not found message --- .../assets-page/no-nft-found.inline.svg | 112 ++++++++++++++++++ .../app/components/wallet/assets/ListEmpty.js | 8 +- .../app/components/wallet/assets/NFTsList.js | 17 +-- .../app/containers/wallet/NFTsWrapper.js | 1 - .../app/i18n/locales/en-US.json | 1 + 5 files changed, 127 insertions(+), 12 deletions(-) create mode 100644 packages/yoroi-extension/app/assets/images/assets-page/no-nft-found.inline.svg diff --git a/packages/yoroi-extension/app/assets/images/assets-page/no-nft-found.inline.svg b/packages/yoroi-extension/app/assets/images/assets-page/no-nft-found.inline.svg new file mode 100644 index 0000000000..7eac287347 --- /dev/null +++ b/packages/yoroi-extension/app/assets/images/assets-page/no-nft-found.inline.svg @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/yoroi-extension/app/components/wallet/assets/ListEmpty.js b/packages/yoroi-extension/app/components/wallet/assets/ListEmpty.js index 2be4bdd460..9b92f8a812 100644 --- a/packages/yoroi-extension/app/components/wallet/assets/ListEmpty.js +++ b/packages/yoroi-extension/app/components/wallet/assets/ListEmpty.js @@ -1,7 +1,7 @@ // @flow import type { Node } from 'react'; import { Stack, Typography } from '@mui/material'; -import { ReactComponent as NoTransactionModernSvg } from '../../../assets/images/transaction/no-transactions-yet.modern.inline.svg'; +import { ReactComponent as NotFound } from '../../../assets/images/assets-page/no-nft-found.inline.svg'; type Props = {| message: string, @@ -10,14 +10,14 @@ export const ListEmpty = ({ message }: Props): Node => { return ( - + {message} diff --git a/packages/yoroi-extension/app/components/wallet/assets/NFTsList.js b/packages/yoroi-extension/app/components/wallet/assets/NFTsList.js index f34c0a7e87..92b86e527c 100644 --- a/packages/yoroi-extension/app/components/wallet/assets/NFTsList.js +++ b/packages/yoroi-extension/app/components/wallet/assets/NFTsList.js @@ -1,17 +1,16 @@ // @flow import type { ComponentType, Node } from 'react'; -import { Box, minHeight, styled } from '@mui/system'; +import { Box, styled } from '@mui/system'; import { IconButton, ImageList, ImageListItem, - Input, InputAdornment, Stack, Typography, - Skeleton + Skeleton, + OutlinedInput } from '@mui/material'; -import { assetsMessage } from './AssetsList'; import { ReactComponent as Search } from '../../../assets/images/assets-page/search.inline.svg'; import { ReactComponent as DefaultNFT } from '../../../assets/images/default-nft.inline.svg'; @@ -34,6 +33,10 @@ const messages = defineMessages({ id: 'wallet.assets.nft.noResultsFound', defaultMessage: '!!!No NFTs found', }, + searchNFTs: { + id: 'wallet.nftGallary.search', + defaultMessage: '!!!Search NFTs' + } }); const listColumnViews = [ @@ -59,7 +62,7 @@ function NfTsList({ list, intl }: Props & Intl): Node { }; return ( - + NFTs ({list.length}) @@ -83,7 +86,7 @@ function NfTsList({ list, intl }: Props & Intl): Node { @@ -160,7 +163,7 @@ function NftCardImage({ ipfsUrl, name }) { ); } -const SearchInput = styled(Input)({ +const SearchInput = styled(OutlinedInput)({ border: '1px solid var(--yoroi-palette-gray-300)', borderRadius: '8px', width: '370px', diff --git a/packages/yoroi-extension/app/containers/wallet/NFTsWrapper.js b/packages/yoroi-extension/app/containers/wallet/NFTsWrapper.js index 9f6a2864f9..7f01cbb4ce 100644 --- a/packages/yoroi-extension/app/containers/wallet/NFTsWrapper.js +++ b/packages/yoroi-extension/app/containers/wallet/NFTsWrapper.js @@ -13,7 +13,6 @@ import TopBarLayout from '../../components/layout/TopBarLayout'; import BannerContainer from '../banners/BannerContainer'; import NavBarContainerRevamp from '../NavBarContainerRevamp'; import NavBarTitle from '../../components/topbar/NavBarTitle'; -import globalMessages from '../../i18n/global-messages'; import SidebarContainer from '../SidebarContainer'; import type { $npm$ReactIntl$IntlFormat } from 'react-intl'; import { intlShape, defineMessages } from 'react-intl'; diff --git a/packages/yoroi-extension/app/i18n/locales/en-US.json b/packages/yoroi-extension/app/i18n/locales/en-US.json index 03cbe9d799..b5938c798d 100644 --- a/packages/yoroi-extension/app/i18n/locales/en-US.json +++ b/packages/yoroi-extension/app/i18n/locales/en-US.json @@ -626,6 +626,7 @@ "wallet.nowallet.subtitle": "Please select a wallet from the dropdown menu on the top right.", "wallet.nowallet.title": "No wallet selected.", "wallet.nftGallary.title": "NFT Gallary", + "wallet.nftGallary.search": "Search NFTs", "wallet.problematic.explanation1": "The wallet you selected ({checksumTextPart}) was detected to contain some kind of issue.", "wallet.receive.confirmationDialog.addressDetailsTitleLabel": "Verify address", "wallet.receive.confirmationDialog.addressLabel": "Address", From 4db2603b25f1cd5b56f6627cbde80aef2da3c1d2 Mon Sep 17 00:00:00 2001 From: Ahmed Ibrahim Date: Mon, 20 Jun 2022 11:30:22 +0200 Subject: [PATCH 023/153] Render Empty page --- .../app/components/wallet/assets/ListEmpty.js | 8 +++---- .../app/components/wallet/assets/NFTsList.js | 23 ++++++++++++++++--- .../app/i18n/locales/en-US.json | 1 + 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/packages/yoroi-extension/app/components/wallet/assets/ListEmpty.js b/packages/yoroi-extension/app/components/wallet/assets/ListEmpty.js index 9b92f8a812..2be4bdd460 100644 --- a/packages/yoroi-extension/app/components/wallet/assets/ListEmpty.js +++ b/packages/yoroi-extension/app/components/wallet/assets/ListEmpty.js @@ -1,7 +1,7 @@ // @flow import type { Node } from 'react'; import { Stack, Typography } from '@mui/material'; -import { ReactComponent as NotFound } from '../../../assets/images/assets-page/no-nft-found.inline.svg'; +import { ReactComponent as NoTransactionModernSvg } from '../../../assets/images/transaction/no-transactions-yet.modern.inline.svg'; type Props = {| message: string, @@ -10,14 +10,14 @@ export const ListEmpty = ({ message }: Props): Node => { return ( - + {message} diff --git a/packages/yoroi-extension/app/components/wallet/assets/NFTsList.js b/packages/yoroi-extension/app/components/wallet/assets/NFTsList.js index 92b86e527c..6fe4671a1b 100644 --- a/packages/yoroi-extension/app/components/wallet/assets/NFTsList.js +++ b/packages/yoroi-extension/app/components/wallet/assets/NFTsList.js @@ -13,13 +13,13 @@ import { } from '@mui/material'; import { ReactComponent as Search } from '../../../assets/images/assets-page/search.inline.svg'; import { ReactComponent as DefaultNFT } from '../../../assets/images/default-nft.inline.svg'; +import { ReactComponent as NotFound } from '../../../assets/images/assets-page/no-nft-found.inline.svg'; import { defineMessages, injectIntl } from 'react-intl'; import type { $npm$ReactIntl$IntlShape } from 'react-intl'; import { Link } from 'react-router-dom'; import { ROUTES } from '../../../routes-config'; import { useState, useEffect } from 'react'; -import { ListEmpty } from './ListEmpty'; type Props = {| list: Array<{| name: string, image: string | void |}> | void, @@ -33,6 +33,10 @@ const messages = defineMessages({ id: 'wallet.assets.nft.noResultsFound', defaultMessage: '!!!No NFTs found', }, + noNFTsAdded: { + id: 'wallet.nftGallary.noNFTsAdded', + defaultMessage: '!!!No NFTs added to your wallet', + }, searchNFTs: { id: 'wallet.nftGallary.search', defaultMessage: '!!!Search NFTs' @@ -49,7 +53,7 @@ const getDefaultColumnsView = () => listColumnViews[1]; function NfTsList({ list, intl }: Props & Intl): Node { if (list == null) return null; const [columns, setColumns] = useState(getDefaultColumnsView()); - const [nftList, setNftList] = useState(list); + const [nftList, setNftList] = useState([...list]); const search: (e: SyntheticEvent) => void = ( event: SyntheticEvent @@ -96,7 +100,20 @@ function NfTsList({ list, intl }: Props & Intl): Node { {!nftList.length ? ( - + + + + {intl.formatMessage(!list.length ? messages.noNFTsAdded : messages.noResultsFound)} + + ) : ( {nftList.map(nft => { diff --git a/packages/yoroi-extension/app/i18n/locales/en-US.json b/packages/yoroi-extension/app/i18n/locales/en-US.json index b5938c798d..e9976f25c4 100644 --- a/packages/yoroi-extension/app/i18n/locales/en-US.json +++ b/packages/yoroi-extension/app/i18n/locales/en-US.json @@ -627,6 +627,7 @@ "wallet.nowallet.title": "No wallet selected.", "wallet.nftGallary.title": "NFT Gallary", "wallet.nftGallary.search": "Search NFTs", + "wallet.nftGallary.noNFTsAdded": "No NFTs added to your wallet", "wallet.problematic.explanation1": "The wallet you selected ({checksumTextPart}) was detected to contain some kind of issue.", "wallet.receive.confirmationDialog.addressDetailsTitleLabel": "Verify address", "wallet.receive.confirmationDialog.addressLabel": "Address", From add1a2c823e0d260385043eb03237dd86363f773 Mon Sep 17 00:00:00 2001 From: Ahmed Ibrahim Date: Mon, 20 Jun 2022 11:48:25 +0200 Subject: [PATCH 024/153] Add NFT image skeleton --- .../app/components/wallet/assets/NFTDetails.js | 10 +++++++--- .../app/components/wallet/assets/NFTsList.js | 16 ++++++++-------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/packages/yoroi-extension/app/components/wallet/assets/NFTDetails.js b/packages/yoroi-extension/app/components/wallet/assets/NFTDetails.js index 7d9089d314..fa5460b5ad 100644 --- a/packages/yoroi-extension/app/components/wallet/assets/NFTDetails.js +++ b/packages/yoroi-extension/app/components/wallet/assets/NFTDetails.js @@ -12,6 +12,7 @@ import { ROUTES } from '../../../routes-config'; import CopyToClipboardText from '../../widgets/CopyToClipboardLabel'; import { getNetworkUrl, tokenMessages } from './TokenDetails'; import type { NetworkRow } from '../../../api/ada/lib/storage/database/primitives/tables'; +import { NftImage } from './NFTsList'; type Props = {| nftInfo: void | {| @@ -71,7 +72,7 @@ function NFTDetails({ nftInfo, nftsCount, network, intl }: Props & Intl): Node { }} > - {nftInfo.name} + @@ -145,7 +146,7 @@ function NFTDetails({ nftInfo, nftsCount, network, intl }: Props & Intl): Node { /> - + @@ -157,7 +158,10 @@ function NFTDetails({ nftInfo, nftsCount, network, intl }: Props & Intl): Node { export default (injectIntl(NFTDetails): ComponentType); const ImageItem = styled(Box)({ - padding: '40px', + padding: '24px', + display: 'flex', + alignItems: 'center', + justifyContent: 'center', backgroundColor: 'var(--yoroi-palette-common-white)', borderRadius: '8px', img: { diff --git a/packages/yoroi-extension/app/components/wallet/assets/NFTsList.js b/packages/yoroi-extension/app/components/wallet/assets/NFTsList.js index 6fe4671a1b..45148cec4c 100644 --- a/packages/yoroi-extension/app/components/wallet/assets/NFTsList.js +++ b/packages/yoroi-extension/app/components/wallet/assets/NFTsList.js @@ -138,10 +138,10 @@ function isImageExist(imageSrc, onload, onerror) { img.src = imageSrc; } -function NftImage({ ipfsUrl, name }) { +export function NftImage({ imageUrl, name }) { const [loading, setLoading] = useState(true); const [error, setError] = useState(false); - if (error || !ipfsUrl) return ( + if (error || !imageUrl) return ( ) - ipfsUrl = ipfsUrl.replace('ipfs://', 'https://ipfs.io/ipfs/'); + imageUrl = imageUrl.replace('ipfs://', 'https://ipfs.io/ipfs/'); useEffect(() => { isImageExist( - ipfsUrl, + imageUrl, () => { setLoading(false); setError(false) }, // on-success () => { setLoading(false); setError(true) }, // on-error ) - }, [ipfsUrl]) + }, [imageUrl]) - if (loading) return - return {name} + if (loading) return + return {name} } function NftCardImage({ ipfsUrl, name }) { return ( - + {name} From 9f67a7c1a9af122afb367b70c6923c2a641da598 Mon Sep 17 00:00:00 2001 From: Ahmed Ibrahim Date: Mon, 20 Jun 2022 12:09:47 +0200 Subject: [PATCH 025/153] Display nfts count --- .../components/wallet/assets/NFTDetails.js | 22 +++++++++++++------ .../app/components/wallet/assets/NFTsList.js | 11 ++++++++-- .../app/i18n/locales/en-US.json | 1 + 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/packages/yoroi-extension/app/components/wallet/assets/NFTDetails.js b/packages/yoroi-extension/app/components/wallet/assets/NFTDetails.js index fa5460b5ad..6c379850ea 100644 --- a/packages/yoroi-extension/app/components/wallet/assets/NFTDetails.js +++ b/packages/yoroi-extension/app/components/wallet/assets/NFTDetails.js @@ -3,7 +3,7 @@ import type { Node, ComponentType } from 'react'; import { Box, styled } from '@mui/system'; import { Link as LinkMui, Grid, Typography, Stack } from '@mui/material'; import globalMessages from '../../../i18n/global-messages'; -import { injectIntl } from 'react-intl'; +import { injectIntl, defineMessages } from 'react-intl'; import { ReactComponent as LinkSvg } from '../../../assets/images/link.inline.svg'; import moment from 'moment'; import type { $npm$ReactIntl$IntlShape } from 'react-intl'; @@ -34,29 +34,37 @@ type Intl = {| intl: $npm$ReactIntl$IntlShape, |}; +const messages = defineMessages({ + nftsCount: { + id: 'wallet.nftGallary.details.nftsCount', + defaultMessage: '!!!NFTs ({number})', + }, +}) + function NFTDetails({ nftInfo, nftsCount, network, intl }: Props & Intl): Node { if (nftInfo == null) return null; - const ipfsHash = nftInfo.image != null ? nftInfo.image.replace('ipfs://', '') : ''; const networkUrl = getNetworkUrl(network); return ( - - {/* eslint-disable-next-line react/no-unescaped-entities */} + - NFTs ({nftsCount}){' '}/{' '} + {!nftsCount ? + intl.formatMessage(globalMessages.sidebarNfts) + : intl.formatMessage(messages.nftsCount, { number: nftsCount })} - + / + {nftInfo.name} diff --git a/packages/yoroi-extension/app/components/wallet/assets/NFTsList.js b/packages/yoroi-extension/app/components/wallet/assets/NFTsList.js index 45148cec4c..d3c8c298c6 100644 --- a/packages/yoroi-extension/app/components/wallet/assets/NFTsList.js +++ b/packages/yoroi-extension/app/components/wallet/assets/NFTsList.js @@ -20,6 +20,7 @@ import type { $npm$ReactIntl$IntlShape } from 'react-intl'; import { Link } from 'react-router-dom'; import { ROUTES } from '../../../routes-config'; import { useState, useEffect } from 'react'; +import globalMessages from '../../../i18n/global-messages'; type Props = {| list: Array<{| name: string, image: string | void |}> | void, @@ -40,7 +41,11 @@ const messages = defineMessages({ searchNFTs: { id: 'wallet.nftGallary.search', defaultMessage: '!!!Search NFTs' - } + }, + nftsCount: { + id: 'wallet.nftGallary.details.nftsCount', + defaultMessage: '!!!NFTs ({number})', + }, }); const listColumnViews = [ @@ -69,7 +74,9 @@ function NfTsList({ list, intl }: Props & Intl): Node { - NFTs ({list.length}) + {!list.length ? + intl.formatMessage(globalMessages.sidebarNfts) + : intl.formatMessage(messages.nftsCount, { number: list.length })} diff --git a/packages/yoroi-extension/app/i18n/locales/en-US.json b/packages/yoroi-extension/app/i18n/locales/en-US.json index e9976f25c4..90de571d13 100644 --- a/packages/yoroi-extension/app/i18n/locales/en-US.json +++ b/packages/yoroi-extension/app/i18n/locales/en-US.json @@ -628,6 +628,7 @@ "wallet.nftGallary.title": "NFT Gallary", "wallet.nftGallary.search": "Search NFTs", "wallet.nftGallary.noNFTsAdded": "No NFTs added to your wallet", + "wallet.nftGallary.details.nftsCount": "NFTs ({number})", "wallet.problematic.explanation1": "The wallet you selected ({checksumTextPart}) was detected to contain some kind of issue.", "wallet.receive.confirmationDialog.addressDetailsTitleLabel": "Verify address", "wallet.receive.confirmationDialog.addressLabel": "Address", From 2d792ea80b3d767fd7bf75bc9d23420b7ae359a8 Mon Sep 17 00:00:00 2001 From: Ahmed Ibrahim Date: Mon, 20 Jun 2022 15:43:49 +0200 Subject: [PATCH 026/153] Display number of tokens --- .../yoroi-extension/app/components/wallet/assets/NFTDetails.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/yoroi-extension/app/components/wallet/assets/NFTDetails.js b/packages/yoroi-extension/app/components/wallet/assets/NFTDetails.js index 6c379850ea..d225fbb08d 100644 --- a/packages/yoroi-extension/app/components/wallet/assets/NFTDetails.js +++ b/packages/yoroi-extension/app/components/wallet/assets/NFTDetails.js @@ -64,7 +64,7 @@ function NFTDetails({ nftInfo, nftsCount, network, intl }: Props & Intl): Node { : intl.formatMessage(messages.nftsCount, { number: nftsCount })} / - + {nftInfo.name} From dfcfde6dec0d8b66b4a1619b761a3576397f7363 Mon Sep 17 00:00:00 2001 From: Patriciu Nista Date: Thu, 7 Jul 2022 13:49:56 +0200 Subject: [PATCH 027/153] Redo of rewards history modal styles --- .../dashboard-revamp/RewardHistoryDialog.js | 13 +- .../dashboard-revamp/RewardHistoryDialog.scss | 5 + .../dashboard-revamp/RewardHistoryTab.js | 121 +++++++++++++----- .../containers/wallet/staking/StakingPage.js | 12 +- .../app/i18n/global-messages.js | 4 + 5 files changed, 118 insertions(+), 37 deletions(-) create mode 100644 packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/RewardHistoryDialog.scss diff --git a/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/RewardHistoryDialog.js b/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/RewardHistoryDialog.js index 96324dee9c..23a3f9b9a3 100644 --- a/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/RewardHistoryDialog.js +++ b/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/RewardHistoryDialog.js @@ -10,12 +10,14 @@ import { injectIntl } from 'react-intl'; import type { $npm$ReactIntl$IntlShape } from 'react-intl'; import { Box } from '@mui/system'; import { RewardHistoryItem } from './RewardHistoryTab'; -// import InvalidURIImg from '../../../../assets/images/uri/invalid-uri.inline.svg'; +import InvalidURIImg from '../../../../assets/images/uri/invalid-uri.inline.svg'; import ErrorBlock from '../../../widgets/ErrorBlock'; import LoadingSpinner from '../../../widgets/LoadingSpinner'; import VerticallyCenteredLayout from '../../../layout/VerticallyCenteredLayout'; import LocalizableError from '../../../../i18n/LocalizableError'; import { groupByPoolName } from '../utils'; +import styles from './RewardHistoryDialog.scss'; +import string from 'lodash/string'; export type GraphRewardData = {| error: ?LocalizableError, @@ -24,6 +26,7 @@ export type GraphRewardData = {| primary: number, poolName: string, poolId: string, + currency: string, date: string, |}>, |}; @@ -48,15 +51,16 @@ function RewardHistoryDialog({ graphData, onClose, intl }: Props & Intl): Node { closeOnOverlayClick={false} closeButton={} onClose={onClose} + className={styles.dialog} > - - {intl.formatMessage(globalMessages.rewardsLabel)} ({rewardList.length}) + + {intl.formatMessage(globalMessages.rewardsListLabel)} ({rewardList.length}) {graphData.error && (
- {/* */} +
@@ -80,6 +84,7 @@ function RewardHistoryDialog({ graphData, onClose, intl }: Props & Intl): Node { type: 'Received', date: item.date, balance: item.primary, + currency: item.currency, }))} /> )) diff --git a/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/RewardHistoryDialog.scss b/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/RewardHistoryDialog.scss new file mode 100644 index 0000000000..f24bb23d7b --- /dev/null +++ b/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/RewardHistoryDialog.scss @@ -0,0 +1,5 @@ +.dialog { + & > h1.dialog__title { + margin-bottom: 26px; + } +} \ No newline at end of file diff --git a/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/RewardHistoryTab.js b/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/RewardHistoryTab.js index f54d1237f9..c1b7bc0259 100644 --- a/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/RewardHistoryTab.js +++ b/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/RewardHistoryTab.js @@ -12,6 +12,60 @@ import InvalidURIImg from '../../../../assets/images/uri/invalid-uri.inline.svg' import ErrorBlock from '../../../widgets/ErrorBlock'; import VerticallyCenteredLayout from '../../../layout/VerticallyCenteredLayout'; import LoadingSpinner from '../../../widgets/LoadingSpinner'; +import MuiAccordion, { AccordionProps } from '@mui/material/Accordion'; +import MuiAccordionSummary, { AccordionSummaryProps } from '@mui/material/AccordionSummary'; +import MuiAccordionDetails from '@mui/material/AccordionDetails'; + +const ExpandMoreIcon = () => ( + + + +); + +const Accordion = styled((props: AccordionProps) => ( + +))(() => ({ + borderBottom: `1px solid var(--yoroi-palette-gray-50)`, + '&:not(:last-child)': { + borderBottom: 0, + }, + '&:before': { + display: 'none', + }, + paddingBottom: '16px', + marginBottom: '16px', +})); + +const AccordionSummary = styled((props: AccordionSummaryProps) => ( + } {...props} /> +))(() => ({ + padding: 0, + '.MuiAccordionSummary-content': { + margin: 0, + }, + '& .MuiAccordionSummary-expandIconWrapper.Mui-expanded': { + transform: 'rotate(180deg)', + }, + '& .MuiCollapse-vertical': { + transitionDuration: '0.5s', + }, +})); + +const AccordionDetails = styled(MuiAccordionDetails)(() => ({ + marginTop: '24px', + padding: 0, +})); type RewardHistoryItemProps = {| poolId: string, @@ -21,6 +75,7 @@ type RewardHistoryItemProps = {| type: string, date: string, balance: string, + currency: string, |}>, |}; type Intl = {| intl: $npm$ReactIntl$IntlShape |}; @@ -34,39 +89,45 @@ export const RewardHistoryItem = ({ const avatarGenerated = getAvatarFromPoolId(poolId); return ( - - - Stake Pool - - - {poolAvatar != null ? ( - - ) : ( - - )} - - {poolName} + + + + + Stake Pool + + + + {poolAvatar != null ? ( + + ) : ( + + )} + + {poolName} + - - - {historyList.map(({ type, date, balance }, idx) => ( - // eslint-disable-next-line react/no-array-index-key - - - {type} - - {date} + + + + {historyList.map(({ type, date, balance, currency }, idx) => ( + // eslint-disable-next-line react/no-array-index-key + + + + {type} + + + {date} + + + + + {balance} {currency} - {balance} - - ))} - - + ))} +
+ + ); }; diff --git a/packages/yoroi-extension/app/containers/wallet/staking/StakingPage.js b/packages/yoroi-extension/app/containers/wallet/staking/StakingPage.js index e551aa8424..7b13454067 100644 --- a/packages/yoroi-extension/app/containers/wallet/staking/StakingPage.js +++ b/packages/yoroi-extension/app/containers/wallet/staking/StakingPage.js @@ -240,6 +240,10 @@ class StakingPage extends Component { : `${beforeDecimalRewards}${afterDecimalRewards} ${truncateToken(getTokenName(tokenInfo))}`; }; + const getCurrency = tokenEntry => { + return getTokenName(tokenEntry); + }; + for (let i = startEpoch; i < endEpoch; i++) { if (historyIterator < history.length && i === history[historyIterator][0]) { // exists a reward for this epoch @@ -251,16 +255,18 @@ class StakingPage extends Component { primary: getNormalized(nextReward.getDefaultEntry()), poolName: getMiniPoolInfo(poolHash), poolId: poolHash, + currency: getCurrency(nextReward.getDefaultEntry()), date: getDateFromEpoch(i), }); historyIterator++; } else { perEpochRewards.push({ name: i, - primary: 0, - poolName: '', + primary: 2, + poolName: 'Test', poolId: '', - date: '', + currency: 'ADA', + date: 'Jul 7, 2022 1:06 PM', }); } } diff --git a/packages/yoroi-extension/app/i18n/global-messages.js b/packages/yoroi-extension/app/i18n/global-messages.js index 5f33ae9fdd..0bfc0a4edf 100644 --- a/packages/yoroi-extension/app/i18n/global-messages.js +++ b/packages/yoroi-extension/app/i18n/global-messages.js @@ -597,6 +597,10 @@ const globalMessages: * = defineMessages({ id: 'global.labels.rewardsLabel', defaultMessage: '!!!Rewards', }, + rewardsListLabel: { + id: 'global.labels.rewardsListLabel', + defaultMessage: '!!!Rewards list', + }, totalTokenLabel: { id: 'wallet.dashboard.summary.adaTitle', defaultMessage: '!!!Total {ticker}', From 57ca0d6954df0419ad297fad9960733467d76874 Mon Sep 17 00:00:00 2001 From: Patriciu Nista Date: Tue, 12 Jul 2022 11:56:20 +0200 Subject: [PATCH 028/153] Add en-US literal --- .../app/i18n/global-messages.js | 83 ++++++++++--------- .../app/i18n/locales/en-US.json | 1 + 2 files changed, 47 insertions(+), 37 deletions(-) diff --git a/packages/yoroi-extension/app/i18n/global-messages.js b/packages/yoroi-extension/app/i18n/global-messages.js index 0bfc0a4edf..e4fcee5c7a 100644 --- a/packages/yoroi-extension/app/i18n/global-messages.js +++ b/packages/yoroi-extension/app/i18n/global-messages.js @@ -5,7 +5,7 @@ import { defineMessages } from 'react-intl'; * Some messages need to be used in multiple components * In order to avoid components depending on each other just to reuse translation messages * We instead store the shared messages in this file -*/ + */ const globalMessages: * = defineMessages({ token: { @@ -290,7 +290,8 @@ const globalMessages: * = defineMessages({ }, hwConnectDialogAboutPrerequisite4: { id: 'wallet.connect.hw.dialog.step.about.prerequisite.4', - defaultMessage: '!!!Your computer must remain connected to the Internet throughout the process.', + defaultMessage: + '!!!Your computer must remain connected to the Internet throughout the process.', }, hwConnectDialogAboutPrerequisiteHeader: { id: 'wallet.connect.hw.dialog.step.about.prerequisite.header', @@ -322,7 +323,8 @@ const globalMessages: * = defineMessages({ }, trezorError101: { id: 'wallet.connect.trezor.error.101', - defaultMessage: '!!!Failed to connect trezor.io. Please check your Internet connection and retry.', + defaultMessage: + '!!!Failed to connect trezor.io. Please check your Internet connection and retry.', }, hwError101: { id: 'wallet.hw.common.error.101', @@ -362,7 +364,8 @@ const globalMessages: * = defineMessages({ }, step1: { id: 'transfer.form.instructions.step1.text', - defaultMessage: '!!!It will take about 1 minute to restore your balance. In the next step, you will be presented with a transaction that will move all of your funds. Please review the details of the transaction carefully. You will need to pay a standard transaction fee on the Cardano network to make the transaction.', + defaultMessage: + '!!!It will take about 1 minute to restore your balance. In the next step, you will be presented with a transaction that will move all of your funds. Please review the details of the transaction carefully. You will need to pay a standard transaction fee on the Cardano network to make the transaction.', }, feeLabel: { id: 'wallet.transaction.fee', @@ -378,7 +381,8 @@ const globalMessages: * = defineMessages({ }, languageSelectInfo: { id: 'settings.general.languageSelect.info', - defaultMessage: '!!!For EMURGO, friendliness in Yoroi is an important topic. We believe understanding blockchain concepts is easier in your native language. We try supporting as many languages as possible, but for a broader selection of languages we need to accept the help from community translators. The selected language translation is fully provided by the community.', + defaultMessage: + '!!!For EMURGO, friendliness in Yoroi is an important topic. We believe understanding blockchain concepts is easier in your native language. We try supporting as many languages as possible, but for a broader selection of languages we need to accept the help from community translators. The selected language translation is fully provided by the community.', }, translationAcknowledgment: { id: 'settings.general.translation.acknowledgment', @@ -431,7 +435,8 @@ const globalMessages: * = defineMessages({ }, logsContent: { id: 'settings.support.logs.content', - defaultMessage: '!!!If you want to inspect logs, you can {downloadLogsLink}. Logs do not contain sensitive information, and it would be helpful to attach them to problem reports to help the team investigate the issue you are experiencing. Logs can be attached automatically when using the bug reporting feature.', + defaultMessage: + '!!!If you want to inspect logs, you can {downloadLogsLink}. Logs do not contain sensitive information, and it would be helpful to attach them to problem reports to help the team investigate the issue you are experiencing. Logs can be attached automatically when using the bug reporting feature.', }, downloadLogsLink: { id: 'settings.support.logs.downloadLogsLink', @@ -467,7 +472,8 @@ const globalMessages: * = defineMessages({ }, uriExplanation: { id: 'global.uriExplanation', - defaultMessage: '!!!These allow you to easily share invoices with friends and businesses by simply clicking a URL.', + defaultMessage: + '!!!These allow you to easily share invoices with friends and businesses by simply clicking a URL.', }, copyTooltipMessage: { id: 'global.copyTooltipMessage', @@ -475,7 +481,8 @@ const globalMessages: * = defineMessages({ }, transferInstructionsText: { id: 'transfer.instructions.instructions.text', - defaultMessage: '!!!Before you can transfer funds, you must create a Yoroi wallet and back it up. Upon completion, you will receive a 15-word recovery phrase which can be used to restore your Yoroi wallet at any time.', + defaultMessage: + '!!!Before you can transfer funds, you must create a Yoroi wallet and back it up. Upon completion, you will receive a 15-word recovery phrase which can be used to restore your Yoroi wallet at any time.', }, transferInstructionsButton: { id: 'transfer.instructions.instructions.button.label', @@ -487,7 +494,7 @@ const globalMessages: * = defineMessages({ }, transferTitleText: { id: 'daedalusTransfer.instructions.attention.title', - defaultMessage: '!!!Transfer all funds from' + defaultMessage: '!!!Transfer all funds from', }, invalidMemo: { id: 'wallet.transaction.memo.invalid', @@ -495,11 +502,13 @@ const globalMessages: * = defineMessages({ }, sendingIsDisabled: { id: 'wallet.send.form.sendingIsDisabled', - defaultMessage: '!!!Unable to process. Please retry after the previous transaction has been completed.', + defaultMessage: + '!!!Unable to process. Please retry after the previous transaction has been completed.', }, passwordDisclaimer: { id: 'wallet.restore.dialog.passwordDisclaimer', - defaultMessage: '!!!Typing the wrong wallet password will give you a different wallet. This allows for plausible deniability.', + defaultMessage: + '!!!Typing the wrong wallet password will give you a different wallet. This allows for plausible deniability.', }, recoveryPhraseInputLabel: { id: 'wallet.restore.dialog.recovery.phrase.input.label', @@ -531,7 +540,7 @@ const globalMessages: * = defineMessages({ }, walletUpgrade: { id: 'wallet.backup.dialog.legacy.upgrade', - defaultMessage: `!!!Wallet Upgrade` + defaultMessage: `!!!Wallet Upgrade`, }, pdfGenDone: { id: 'settings.paperWallet.dialog.createPaper.done', @@ -551,7 +560,8 @@ const globalMessages: * = defineMessages({ }, restoreByronEraWalletDescription: { id: 'wallet.add.optionDialog.walletEra.byronEra.description', - defaultMessage: '!!!Wallets created before July 29th, 2020 are Byron-era wallets and cannot delegate.', + defaultMessage: + '!!!Wallets created before July 29th, 2020 are Byron-era wallets and cannot delegate.', }, restoreShelleyEraWalletDescription: { id: 'wallet.add.optionDialog.walletEra.standard.description', @@ -559,7 +569,8 @@ const globalMessages: * = defineMessages({ }, hardwareTransferInstructions: { id: 'transfer.instructions.hardware.disclaimer.instructions1', - defaultMessage: '!!!When you originally setup your hardware wallet, you were asked to write down a recovery phrase on a piece of paper. Entering this phrase will allow you to transfer your funds out of your hardware wallet and into the current wallet.', + defaultMessage: + '!!!When you originally setup your hardware wallet, you were asked to write down a recovery phrase on a piece of paper. Entering this phrase will allow you to transfer your funds out of your hardware wallet and into the current wallet.', }, sendButtonLabel: { id: 'wallet.send.confirmationDialog.submit', @@ -680,8 +691,7 @@ const globalMessages: * = defineMessages({ }, roa30d: { id: 'wallet.staking.banner.roa30d', - defaultMessage: - '!!!ROA 30d', + defaultMessage: '!!!ROA 30d', }, roaHelperMessage: { id: 'wallet.staking.banner.roaHelperMessage', @@ -722,7 +732,8 @@ const globalMessages: * = defineMessages({ }, auditAddressWarning: { id: 'wallet.receive.page.internalWarning2', - defaultMessage: '!!!addresses are shown here for personal auditing purposes and should never be used.' + defaultMessage: + '!!!addresses are shown here for personal auditing purposes and should never be used.', }, lastSyncMessage: { id: 'myWallets.wallets.lastSyncText', @@ -750,27 +761,28 @@ const globalMessages: * = defineMessages({ }, createWalletLabel: { id: 'wallet.add.page.create.title', - defaultMessage: '!!!Create Wallet' + defaultMessage: '!!!Create Wallet', }, paperWalletLabel: { id: 'wallet.add.optionDialog.restore.paperWallet.title', - defaultMessage: '!!!Paper Wallet' + defaultMessage: '!!!Paper Wallet', }, allLabel: { id: 'wallet.receive.navigation.allLabel', - defaultMessage: '!!!All' + defaultMessage: '!!!All', }, noteLabel: { id: 'global.labels.note', - defaultMessage: '!!!Note:' + defaultMessage: '!!!Note:', }, upgradeLabel: { id: 'global.labels.upgrade', - defaultMessage: '!!!Upgrade' + defaultMessage: '!!!Upgrade', }, pendingTxWarning: { id: 'wallet.staking.warning.pendingTx', - defaultMessage: '!!!You cannot change your delegation preference while a transaction is pending', + defaultMessage: + '!!!You cannot change your delegation preference while a transaction is pending', }, stakePoolHash: { id: 'wallet.delegation.transaction.stakePoolHash', @@ -794,11 +806,11 @@ const globalMessages: * = defineMessages({ }, byronLabel: { id: 'wallet.receive.navigation.byronLabel', - defaultMessage: '!!!Byron' + defaultMessage: '!!!Byron', }, shelleyLabel: { id: 'global.labels.shelleyLabel', - defaultMessage: '!!!Shelley' + defaultMessage: '!!!Shelley', }, spendingKeyLabel: { id: 'global.labels.spendingKey', @@ -846,7 +858,7 @@ const globalMessages: * = defineMessages({ }, blogLearnMore: { id: 'global.blog.learnMore', - defaultMessage: '!!!You can read our {blogLink} to learn more.' + defaultMessage: '!!!You can read our {blogLink} to learn more.', }, keyLabel: { id: 'global.key.label', @@ -910,7 +922,8 @@ const globalMessages: * = defineMessages({ }, txConfirmationLedgerNanoLine2: { id: 'wallet.send.ledger.confirmationDialog.info.line.2', - defaultMessage: '!!!Make sure Cardano ADA app must remain open on the Ledger device throughout the process.', + defaultMessage: + '!!!Make sure Cardano ADA app must remain open on the Ledger device throughout the process.', }, txConfirmationTrezorTLine2: { id: 'wallet.send.trezor.confirmationDialog.info.line.2', @@ -950,8 +963,8 @@ export const memoMessages: * = defineMessages({ }, memoWarning: { id: 'wallet.send.form.memoWarning', - defaultMessage: '!!!Memos are stored localy only' - } + defaultMessage: '!!!Memos are stored localy only', + }, }); export const connectorMessages: * = defineMessages({ connectedWebsites: { @@ -968,23 +981,19 @@ export const connectorMessages: * = defineMessages({ }, signTransaction: { id: 'connector.settings.signTransaction', - defaultMessage: '!!!Sign transaction' + defaultMessage: '!!!Sign transaction', }, connect: { id: 'connector.settings.connect', - defaultMessage: '!!!Connect' + defaultMessage: '!!!Connect', }, dappConnector: { id: 'connector.appName', defaultMessage: 'Dapp Connector', - } + }, }); - -export function listOfTranslators( - contributorsList: string, - contributorsAck: string, -): string { +export function listOfTranslators(contributorsList: string, contributorsAck: string): string { let output = ''; // append name of contributors only if the message is not empty if (contributorsList !== globalMessages.translationContributors.defaultMessage) { diff --git a/packages/yoroi-extension/app/i18n/locales/en-US.json b/packages/yoroi-extension/app/i18n/locales/en-US.json index 605ffb8c7e..4b0e9215a0 100644 --- a/packages/yoroi-extension/app/i18n/locales/en-US.json +++ b/packages/yoroi-extension/app/i18n/locales/en-US.json @@ -177,6 +177,7 @@ "global.labels.processing": "Processing...", "global.labels.remove": "Remove", "global.labels.rewardsLabel": "Rewards", + "global.labels.rewardsListLabel": "Rewards List", "global.labels.save": "Save", "global.labels.shelleyLabel": "Shelley", "global.labels.spendingKey": "Spending key", From de1a73bcdbafa4d9c143b7010038b81b4fda2706 Mon Sep 17 00:00:00 2001 From: Patriciu Nista Date: Tue, 12 Jul 2022 12:10:11 +0200 Subject: [PATCH 029/153] Removed mock data --- .../app/containers/wallet/staking/StakingPage.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/packages/yoroi-extension/app/containers/wallet/staking/StakingPage.js b/packages/yoroi-extension/app/containers/wallet/staking/StakingPage.js index 7b13454067..b2fac6ff77 100644 --- a/packages/yoroi-extension/app/containers/wallet/staking/StakingPage.js +++ b/packages/yoroi-extension/app/containers/wallet/staking/StakingPage.js @@ -240,8 +240,10 @@ class StakingPage extends Component { : `${beforeDecimalRewards}${afterDecimalRewards} ${truncateToken(getTokenName(tokenInfo))}`; }; + // TODO: get currency of delegated token const getCurrency = tokenEntry => { - return getTokenName(tokenEntry); + // return getTokenName(tokenEntry); + return 'ADA'; }; for (let i = startEpoch; i < endEpoch; i++) { @@ -255,18 +257,18 @@ class StakingPage extends Component { primary: getNormalized(nextReward.getDefaultEntry()), poolName: getMiniPoolInfo(poolHash), poolId: poolHash, - currency: getCurrency(nextReward.getDefaultEntry()), + currency: getCurrency(), date: getDateFromEpoch(i), }); historyIterator++; } else { perEpochRewards.push({ name: i, - primary: 2, - poolName: 'Test', + primary: 0, + poolName: '', poolId: '', - currency: 'ADA', - date: 'Jul 7, 2022 1:06 PM', + currency: '', + date: '', }); } } From 83b6d57e61db3520f120e8cd240d6fd81726216a Mon Sep 17 00:00:00 2001 From: Patriciu Nista Date: Tue, 12 Jul 2022 12:10:20 +0200 Subject: [PATCH 030/153] Lint changes --- .../dashboard-revamp/RewardHistoryTab.js | 3 +- .../staking/dashboard-revamp/RewardsGraph.js | 243 +++++++++--------- 2 files changed, 125 insertions(+), 121 deletions(-) diff --git a/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/RewardHistoryTab.js b/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/RewardHistoryTab.js index c1b7bc0259..9071b0b1ad 100644 --- a/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/RewardHistoryTab.js +++ b/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/RewardHistoryTab.js @@ -1,12 +1,13 @@ // @flow import type { ComponentType, Node } from 'react'; +import { useMemo } from 'react'; import { Box, styled } from '@mui/system'; import { Stack, Typography } from '@mui/material'; import { injectIntl } from 'react-intl'; import globalMessages from '../../../../i18n/global-messages'; import type { $npm$ReactIntl$IntlShape } from 'react-intl'; import { getAvatarFromPoolId, groupByPoolName } from '../utils'; -import { useMemo } from 'react'; +import RewardGraph from './RewardsGraph'; import type { GraphRewardData } from './RewardHistoryDialog'; import InvalidURIImg from '../../../../assets/images/uri/invalid-uri.inline.svg'; import ErrorBlock from '../../../widgets/ErrorBlock'; diff --git a/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/RewardsGraph.js b/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/RewardsGraph.js index 89b753b5ff..9872f2b386 100644 --- a/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/RewardsGraph.js +++ b/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/RewardsGraph.js @@ -8,135 +8,138 @@ import { Typography } from '@mui/material'; import type { GraphItems } from '../dashboard/GraphWrapper'; const graphVars = { - barWidth: Number(readCssVar('--yoroi-dashboard-graph-bar-width')), - fontSize: '0.75rem', - lineHeight: 14, + barWidth: Number(readCssVar('--yoroi-dashboard-graph-bar-width')), + fontSize: '0.75rem', + lineHeight: 14, }; type Props = {| - data: Array, - epochTitle: string, - stakepoolNameTitle: string, - xAxisLabel: string, - yAxisLabel: string, - primaryBarLabel: string, - hideYAxis: boolean, + data: Array, + epochTitle: string, + stakepoolNameTitle: string, + xAxisLabel: string, + yAxisLabel: string, + primaryBarLabel: string, + hideYAxis: boolean, |}; export default class RewardGraph extends Component { - render(): Node { - const { - hideYAxis, - data, - xAxisLabel, - yAxisLabel, - primaryBarLabel, - epochTitle, - stakepoolNameTitle - } = this.props; + render(): Node { + const { + hideYAxis, + data, + xAxisLabel, + yAxisLabel, + primaryBarLabel, + epochTitle, + stakepoolNameTitle, + } = this.props; - const formatYAxis = (value) => ( - !hideYAxis ? value : '∗∗∗ ' - ); - const GraphTooltip = ( - { active, payload, label }: {| active: boolean, payload: ?[any], label: string |} - ) => { - if (active && payload != null) { - const { poolName } = payload[0].payload - return ( - -

- {epochTitle}:  - {label} -

-

- {primaryBarLabel}:  - {payload[0].value} -

- {poolName && ( -

- {stakepoolNameTitle}:  - {payload[0].payload.poolName} -

)} -
- ); - } - return null; - }; - - // $FlowExpectedError[prop-missing] props are passed implicitly which causes a flow error - const graphTooltip = (); - return ( - <> - (!hideYAxis ? value : '∗∗∗ '); + const GraphTooltip = ({ + active, + payload, + label, + }: {| + active: boolean, + payload: ?[any], + label: string, + |}) => { + if (active && payload != null) { + const { poolName } = payload[0].payload; + return ( + - {yAxisLabel} - - - + {epochTitle}:  + {label} +

+

+ {primaryBarLabel}:  + {payload[0].value} +

+ {poolName && ( +

+ {stakepoolNameTitle}:  + {payload[0].payload.poolName} +

+ )} + + ); + } + return null; + }; + + // $FlowExpectedError[prop-missing] props are passed implicitly which causes a flow error + const graphTooltip = ; + return ( + <> + + {yAxisLabel} + + + + + + - - - - + stroke="#A7AFC0" + tickLine={false} + /> + - - - - - ); - } -}; \ No newline at end of file + +
+
+ + ); + } +} From f609a3763ffa287c6434615223b0c01abe5e1afe Mon Sep 17 00:00:00 2001 From: Ahmed Ibrahim Date: Tue, 19 Jul 2022 13:36:40 +0200 Subject: [PATCH 031/153] Add new grid --- .../images/assets-page/grid-2x2.inline.svg | 6 +++ .../images/assets-page/grid-3x3.inline.svg | 11 ++++ .../app/components/wallet/assets/NFTsList.js | 52 ++++++++++++------- 3 files changed, 51 insertions(+), 18 deletions(-) create mode 100644 packages/yoroi-extension/app/assets/images/assets-page/grid-2x2.inline.svg create mode 100644 packages/yoroi-extension/app/assets/images/assets-page/grid-3x3.inline.svg diff --git a/packages/yoroi-extension/app/assets/images/assets-page/grid-2x2.inline.svg b/packages/yoroi-extension/app/assets/images/assets-page/grid-2x2.inline.svg new file mode 100644 index 0000000000..91ae38082b --- /dev/null +++ b/packages/yoroi-extension/app/assets/images/assets-page/grid-2x2.inline.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/packages/yoroi-extension/app/assets/images/assets-page/grid-3x3.inline.svg b/packages/yoroi-extension/app/assets/images/assets-page/grid-3x3.inline.svg new file mode 100644 index 0000000000..23b8120519 --- /dev/null +++ b/packages/yoroi-extension/app/assets/images/assets-page/grid-3x3.inline.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/packages/yoroi-extension/app/components/wallet/assets/NFTsList.js b/packages/yoroi-extension/app/components/wallet/assets/NFTsList.js index d3c8c298c6..f4ba31bd60 100644 --- a/packages/yoroi-extension/app/components/wallet/assets/NFTsList.js +++ b/packages/yoroi-extension/app/components/wallet/assets/NFTsList.js @@ -2,18 +2,20 @@ import type { ComponentType, Node } from 'react'; import { Box, styled } from '@mui/system'; import { - IconButton, ImageList, ImageListItem, InputAdornment, Stack, Typography, Skeleton, - OutlinedInput + OutlinedInput, + Button } from '@mui/material'; import { ReactComponent as Search } from '../../../assets/images/assets-page/search.inline.svg'; import { ReactComponent as DefaultNFT } from '../../../assets/images/default-nft.inline.svg'; import { ReactComponent as NotFound } from '../../../assets/images/assets-page/no-nft-found.inline.svg'; +import { ReactComponent as Grid2x2 } from '../../../assets/images/assets-page/grid-2x2.inline.svg'; +import { ReactComponent as Grid3x3 } from '../../../assets/images/assets-page/grid-3x3.inline.svg'; import { defineMessages, injectIntl } from 'react-intl'; import type { $npm$ReactIntl$IntlShape } from 'react-intl'; @@ -49,15 +51,13 @@ const messages = defineMessages({ }); const listColumnViews = [ - { count: 2, gap: 32 }, - { count: 4, gap: 32 }, - { count: 6, gap: 16 }, + { count: 4, Icon: Grid2x2 }, + { count: 6, Icon: Grid3x3 }, ]; -const getDefaultColumnsView = () => listColumnViews[1]; function NfTsList({ list, intl }: Props & Intl): Node { if (list == null) return null; - const [columns, setColumns] = useState(getDefaultColumnsView()); + const [columns, setColumns] = useState(listColumnViews[0]); const [nftList, setNftList] = useState([...list]); const search: (e: SyntheticEvent) => void = ( @@ -71,8 +71,17 @@ function NfTsList({ list, intl }: Props & Intl): Node { }; return ( - - + + {!list.length ? intl.formatMessage(globalMessages.sidebarNfts) @@ -80,18 +89,25 @@ function NfTsList({ list, intl }: Props & Intl): Node { - {listColumnViews.map(column => ( - setColumns(column)} + {listColumnViews.map(Column => ( + ))} ) : ( - + {nftList.map(nft => { return ( - + ); })} From 83e4ff140e0ccc5989eada84b35b32934b40a63d Mon Sep 17 00:00:00 2001 From: Ahmed Ibrahim Date: Thu, 21 Jul 2022 11:38:06 +0200 Subject: [PATCH 032/153] Add tabs --- .../images/assets-page/backarrow.inline.svg | 3 + .../components/wallet/assets/NFTDetails.js | 256 +++++++++++------- .../app/components/wallet/assets/NFTsList.js | 57 ++-- .../containers/wallet/NFTDetailPageRevamp.js | 2 +- .../app/containers/wallet/NFTsWrapper.js | 2 - .../app/i18n/locales/en-US.json | 1 + 6 files changed, 190 insertions(+), 131 deletions(-) create mode 100644 packages/yoroi-extension/app/assets/images/assets-page/backarrow.inline.svg diff --git a/packages/yoroi-extension/app/assets/images/assets-page/backarrow.inline.svg b/packages/yoroi-extension/app/assets/images/assets-page/backarrow.inline.svg new file mode 100644 index 0000000000..cd8d182f73 --- /dev/null +++ b/packages/yoroi-extension/app/assets/images/assets-page/backarrow.inline.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/yoroi-extension/app/components/wallet/assets/NFTDetails.js b/packages/yoroi-extension/app/components/wallet/assets/NFTDetails.js index d225fbb08d..027b60bb83 100644 --- a/packages/yoroi-extension/app/components/wallet/assets/NFTDetails.js +++ b/packages/yoroi-extension/app/components/wallet/assets/NFTDetails.js @@ -1,10 +1,13 @@ // @flow -import type { Node, ComponentType } from 'react'; +import { Node, ComponentType, useState } from 'react'; import { Box, styled } from '@mui/system'; -import { Link as LinkMui, Grid, Typography, Stack } from '@mui/material'; +import { Link as LinkMui, Grid, Typography, Stack, Tab, Tabs, ThemeProvider, createTheme } from '@mui/material'; +import { TabContext, TabPanel, TabList } from '@mui/lab'; import globalMessages from '../../../i18n/global-messages'; import { injectIntl, defineMessages } from 'react-intl'; import { ReactComponent as LinkSvg } from '../../../assets/images/link.inline.svg'; +import { ReactComponent as BackArrow } from '../../../assets/images/assets-page/backarrow.inline.svg'; + import moment from 'moment'; import type { $npm$ReactIntl$IntlShape } from 'react-intl'; import { Link } from 'react-router-dom'; @@ -14,6 +17,16 @@ import { getNetworkUrl, tokenMessages } from './TokenDetails'; import type { NetworkRow } from '../../../api/ada/lib/storage/database/primitives/tables'; import { NftImage } from './NFTsList'; +// Overwrite primary current theme +// Temporary solution untill the new design system. +const theme = createTheme({ + palette: { + primary: { + main: '#3154CB' + } + } +}); + type Props = {| nftInfo: void | {| policyId: string, @@ -35,128 +48,168 @@ type Intl = {| |}; const messages = defineMessages({ - nftsCount: { - id: 'wallet.nftGallary.details.nftsCount', - defaultMessage: '!!!NFTs ({number})', + back: { + id: 'wallet.nftGallary.details.back', + defaultMessage: '!!!back to gallery', }, }) function NFTDetails({ nftInfo, nftsCount, network, intl }: Props & Intl): Node { if (nftInfo == null) return null; const networkUrl = getNetworkUrl(network); - + const [value, setValue] = useState(0); + const tabs = [ + { + id: 0, + label: 'Overview', + component:

TAB 1

, + }, + { + id: 1, + label: 'Metadata', + component:

TAB 2

, + }, + ]; return ( - - - - {!nftsCount ? - intl.formatMessage(globalMessages.sidebarNfts) - : intl.formatMessage(messages.nftsCount, { number: nftsCount })} - - / - - {nftInfo.name} - + + + {intl.formatMessage(messages.back)} - + - - - + + + {nftInfo.name} - - - - - - {/* TODO: replace with created date */} - - - - - - {intl.formatMessage(tokenMessages.detailsOn)} - - - - - - } - value={ - + + + setValue(newValue)} + aria-label="NFTs tabs" + > + {tabs.map(({ label, id }) => ( + + ))} + + + + + + + + + {/* TODO: replace with created date */} + + + + + + {intl.formatMessage(tokenMessages.detailsOn)} + + + + + + } + value={ + + Cardanoscan + + } + /> + + + + {nftInfo.id} } - disabled={networkUrl === null} - rel="noopener noreferrer" - sx={{ textDecoration: 'none' }} - > - Cardanoscan - - } - /> - - - - {nftInfo.id} - } - /> - - - {nftInfo.policyId} - - } - /> - - - - - + /> + + + {nftInfo.policyId} + + } + /> + + + + + + + + + + {JSON.stringify(nftInfo, null, 2)} + + + + @@ -166,7 +219,6 @@ function NFTDetails({ nftInfo, nftsCount, network, intl }: Props & Intl): Node { export default (injectIntl(NFTDetails): ComponentType); const ImageItem = styled(Box)({ - padding: '24px', display: 'flex', alignItems: 'center', justifyContent: 'center', diff --git a/packages/yoroi-extension/app/components/wallet/assets/NFTsList.js b/packages/yoroi-extension/app/components/wallet/assets/NFTsList.js index f4ba31bd60..11650f1765 100644 --- a/packages/yoroi-extension/app/components/wallet/assets/NFTsList.js +++ b/packages/yoroi-extension/app/components/wallet/assets/NFTsList.js @@ -51,8 +51,8 @@ const messages = defineMessages({ }); const listColumnViews = [ - { count: 4, Icon: Grid2x2 }, - { count: 6, Icon: Grid3x3 }, + { count: 4, Icon: Grid2x2, imageDims: '264px' }, + { count: 6, Icon: Grid3x3, imageDims: '165px' }, ]; function NfTsList({ list, intl }: Props & Intl): Node { @@ -71,7 +71,7 @@ function NfTsList({ list, intl }: Props & Intl): Node { }; return ( - + ) : ( - + {nftList.map(nft => { return ( - + ); })} @@ -161,7 +166,7 @@ function isImageExist(imageSrc, onload, onerror) { img.src = imageSrc; } -export function NftImage({ imageUrl, name }) { +export function NftImage({ imageUrl, name, width, height }) { const [loading, setLoading] = useState(true); const [error, setError] = useState(false); if (error || !imageUrl) return ( @@ -170,10 +175,8 @@ export function NftImage({ imageUrl, name }) { alignItems: 'center', justifyContent: 'center', backgroundColor: 'var(--yoroi-palette-gray-100)', - width: '100%', - height: '100%', - minWidth: '250px', - minHeight: '200px', + width, + height, }} > @@ -188,18 +191,29 @@ export function NftImage({ imageUrl, name }) { ) }, [imageUrl]) - if (loading) return - return {name} + if (loading) return + return ( + {name} + ) } -function NftCardImage({ ipfsUrl, name }) { +function NftCardImage({ ipfsUrl, name, width, height }) { return ( - - + + {name} - + ); } @@ -213,12 +227,3 @@ const SearchInput = styled(OutlinedInput)({ const SLink = styled(Link)({ textDecoration: 'none', }); -const ImageItem = styled(ImageListItem)({ - padding: '16px', - paddingBottom: '12px', - backgroundColor: 'var(--yoroi-palette-common-white)', - borderRadius: '8px', - img: { - borderRadius: '8px', - }, -}); diff --git a/packages/yoroi-extension/app/containers/wallet/NFTDetailPageRevamp.js b/packages/yoroi-extension/app/containers/wallet/NFTDetailPageRevamp.js index 31d57ee7f6..647ef6c516 100644 --- a/packages/yoroi-extension/app/containers/wallet/NFTDetailPageRevamp.js +++ b/packages/yoroi-extension/app/containers/wallet/NFTDetailPageRevamp.js @@ -88,7 +88,7 @@ class NFTDetailPageRevamp extends Component { const nftInfo = nftsList.find(nft => nft.id === nftId); return ( - + ); diff --git a/packages/yoroi-extension/app/containers/wallet/NFTsWrapper.js b/packages/yoroi-extension/app/containers/wallet/NFTsWrapper.js index 7f01cbb4ce..19fb299cef 100644 --- a/packages/yoroi-extension/app/containers/wallet/NFTsWrapper.js +++ b/packages/yoroi-extension/app/containers/wallet/NFTsWrapper.js @@ -69,8 +69,6 @@ export default class NFTsWrapper extends Component { title={} /> } - showInContainer - showAsCard > {this.props.children}
diff --git a/packages/yoroi-extension/app/i18n/locales/en-US.json b/packages/yoroi-extension/app/i18n/locales/en-US.json index 2bb05a95c8..a71133c8ad 100644 --- a/packages/yoroi-extension/app/i18n/locales/en-US.json +++ b/packages/yoroi-extension/app/i18n/locales/en-US.json @@ -649,6 +649,7 @@ "wallet.nftGallary.search": "Search NFTs", "wallet.nftGallary.noNFTsAdded": "No NFTs added to your wallet", "wallet.nftGallary.details.nftsCount": "NFTs ({number})", + "wallet.nftGallary.details.back": "back to gallery", "wallet.problematic.explanation1": "The wallet you selected ({checksumTextPart}) was detected to contain some kind of issue.", "wallet.receive.confirmationDialog.addressDetailsTitleLabel": "Verify address", "wallet.receive.confirmationDialog.addressLabel": "Address", From e264ce19a4facb640a6ceb52ab74936569feaead Mon Sep 17 00:00:00 2001 From: Ahmed Ibrahim Date: Thu, 21 Jul 2022 13:15:37 +0200 Subject: [PATCH 033/153] Display & copy metadata --- .../components/wallet/assets/NFTDetails.js | 75 +++++++++++++++---- .../containers/wallet/NFTDetailPageRevamp.js | 8 +- .../app/i18n/locales/en-US.json | 6 +- 3 files changed, 73 insertions(+), 16 deletions(-) diff --git a/packages/yoroi-extension/app/components/wallet/assets/NFTDetails.js b/packages/yoroi-extension/app/components/wallet/assets/NFTDetails.js index 027b60bb83..e5f775e01f 100644 --- a/packages/yoroi-extension/app/components/wallet/assets/NFTDetails.js +++ b/packages/yoroi-extension/app/components/wallet/assets/NFTDetails.js @@ -1,12 +1,14 @@ // @flow import { Node, ComponentType, useState } from 'react'; import { Box, styled } from '@mui/system'; -import { Link as LinkMui, Grid, Typography, Stack, Tab, Tabs, ThemeProvider, createTheme } from '@mui/material'; +import { Link as LinkMui, Grid, Typography, Stack, Tab, Tabs, ThemeProvider, createTheme, Button } from '@mui/material'; import { TabContext, TabPanel, TabList } from '@mui/lab'; import globalMessages from '../../../i18n/global-messages'; import { injectIntl, defineMessages } from 'react-intl'; import { ReactComponent as LinkSvg } from '../../../assets/images/link.inline.svg'; import { ReactComponent as BackArrow } from '../../../assets/images/assets-page/backarrow.inline.svg'; +import { ReactComponent as IconCopy } from '../../../assets/images/copy.inline.svg'; +import { ReactComponent as IconCopied } from '../../../assets/images/copied.inline.svg'; import moment from 'moment'; import type { $npm$ReactIntl$IntlShape } from 'react-intl'; @@ -16,6 +18,7 @@ import CopyToClipboardText from '../../widgets/CopyToClipboardLabel'; import { getNetworkUrl, tokenMessages } from './TokenDetails'; import type { NetworkRow } from '../../../api/ada/lib/storage/database/primitives/tables'; import { NftImage } from './NFTsList'; +import CopyableAddress from '../../widgets/CopyableAddress'; // Overwrite primary current theme // Temporary solution untill the new design system. @@ -52,26 +55,52 @@ const messages = defineMessages({ id: 'wallet.nftGallary.details.back', defaultMessage: '!!!back to gallery', }, + overview: { + id: 'wallet.nftGallary.details.overview', + defaultMessage: '!!!Overview' + }, + metadata: { + id: 'wallet.nftGallary.details.metadata', + defaultMessage: '!!!Metadata' + }, + copyMetadata: { + id: 'wallet.nftGallary.details.copyMetadata', + defaultMessage: '!!!Copy metadata' + }, + missingMetadata: { + id: 'wallet.nftGallary.details.missingMetadata', + defaultMessage: '!!!Metadata is missing' + } }) function NFTDetails({ nftInfo, nftsCount, network, intl }: Props & Intl): Node { if (nftInfo == null) return null; const networkUrl = getNetworkUrl(network); - const [value, setValue] = useState(0); + const [value, setValue] = useState(1); + const [isCopied, setCopy] = useState(false); + const tabs = [ { id: 0, - label: 'Overview', - component:

TAB 1

, + label: intl.formatMessage(messages.overview), }, { id: 1, - label: 'Metadata', - component:

TAB 2

, + label: intl.formatMessage(messages.metadata), }, ]; + + const onCopyMetadata = async () => { + try { + await navigator.clipboard.writeText(nftInfo.nftMetadata) + setCopy(true) + } catch (error) { + setCopy(false) + } + } + return ( - + - + - + {nftInfo.name} @@ -119,13 +148,15 @@ function NFTDetails({ nftInfo, nftsCount, network, intl }: Props & Intl): Node { boxShadow: 'none', borderRadius: '0px', marginX: '24px', + borderBottom: 1, + borderColor: 'divider' }} onChange={(_, newValue) => setValue(newValue)} aria-label="NFTs tabs" > {tabs.map(({ label, id }) => ( - - ))} + + ))} - + + {nftInfo.nftMetadata && + } - {JSON.stringify(nftInfo, null, 2)} + + {nftInfo.nftMetadata ? + JSON.stringify(nftInfo.nftMetadata, null, 2): + intl.formatMessage(messages.missingMetadata)} + diff --git a/packages/yoroi-extension/app/containers/wallet/NFTDetailPageRevamp.js b/packages/yoroi-extension/app/containers/wallet/NFTDetailPageRevamp.js index 647ef6c516..c9681670a5 100644 --- a/packages/yoroi-extension/app/containers/wallet/NFTDetailPageRevamp.js +++ b/packages/yoroi-extension/app/containers/wallet/NFTDetailPageRevamp.js @@ -70,6 +70,7 @@ class NFTDetailPageRevamp extends Component { && token.info.Metadata.assetMintMetadata[0]['721'][policyId][name] ? token.info.Metadata.assetMintMetadata[0]['721'][policyId][name] : undefined, + assetMintMetadata: token.info.Metadata.assetMintMetadata[0] }; }) .map(item => ({ @@ -82,6 +83,7 @@ class NFTDetailPageRevamp extends Component { name: item.name, image: item.nftMetadata?.image ?? '', description: item.nftMetadata?.description ?? '', + nftMetadata: item.assetMintMetadata, })); const { nftId } = this.props.match.params; @@ -89,7 +91,11 @@ class NFTDetailPageRevamp extends Component { return ( - + ); } diff --git a/packages/yoroi-extension/app/i18n/locales/en-US.json b/packages/yoroi-extension/app/i18n/locales/en-US.json index a71133c8ad..0dd2880efb 100644 --- a/packages/yoroi-extension/app/i18n/locales/en-US.json +++ b/packages/yoroi-extension/app/i18n/locales/en-US.json @@ -649,7 +649,11 @@ "wallet.nftGallary.search": "Search NFTs", "wallet.nftGallary.noNFTsAdded": "No NFTs added to your wallet", "wallet.nftGallary.details.nftsCount": "NFTs ({number})", - "wallet.nftGallary.details.back": "back to gallery", + "wallet.nftGallary.details.back": "Back to gallery", + "wallet.nftGallary.details.overview": "Overview", + "wallet.nftGallary.details.metadata": "Metadata", + "wallet.nftGallary.details.copyMetadata": "Copy metadata", + "wallet.nftGallary.details.missingMetadata": "Metadata is missing", "wallet.problematic.explanation1": "The wallet you selected ({checksumTextPart}) was detected to contain some kind of issue.", "wallet.receive.confirmationDialog.addressDetailsTitleLabel": "Verify address", "wallet.receive.confirmationDialog.addressLabel": "Address", From 5593b7c1c444bffff7fe83ed3d8f1d82c9ce8d05 Mon Sep 17 00:00:00 2001 From: Ahmed Ibrahim Date: Thu, 21 Jul 2022 13:55:45 +0200 Subject: [PATCH 034/153] Add image overlay view --- .../components/wallet/assets/NFTDetails.js | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/packages/yoroi-extension/app/components/wallet/assets/NFTDetails.js b/packages/yoroi-extension/app/components/wallet/assets/NFTDetails.js index e5f775e01f..0cae3f9c7b 100644 --- a/packages/yoroi-extension/app/components/wallet/assets/NFTDetails.js +++ b/packages/yoroi-extension/app/components/wallet/assets/NFTDetails.js @@ -1,7 +1,7 @@ // @flow import { Node, ComponentType, useState } from 'react'; import { Box, styled } from '@mui/system'; -import { Link as LinkMui, Grid, Typography, Stack, Tab, Tabs, ThemeProvider, createTheme, Button } from '@mui/material'; +import { Link as LinkMui, Grid, Typography, Stack, Tab, Modal, ThemeProvider, createTheme, Button } from '@mui/material'; import { TabContext, TabPanel, TabList } from '@mui/lab'; import globalMessages from '../../../i18n/global-messages'; import { injectIntl, defineMessages } from 'react-intl'; @@ -18,9 +18,8 @@ import CopyToClipboardText from '../../widgets/CopyToClipboardLabel'; import { getNetworkUrl, tokenMessages } from './TokenDetails'; import type { NetworkRow } from '../../../api/ada/lib/storage/database/primitives/tables'; import { NftImage } from './NFTsList'; -import CopyableAddress from '../../widgets/CopyableAddress'; -// Overwrite primary current theme +// Overwrite current theme // Temporary solution untill the new design system. const theme = createTheme({ palette: { @@ -77,6 +76,7 @@ function NFTDetails({ nftInfo, nftsCount, network, intl }: Props & Intl): Node { if (nftInfo == null) return null; const networkUrl = getNetworkUrl(network); const [value, setValue] = useState(1); + const [open, setOpen] = useState(false); const [isCopied, setCopy] = useState(false); const tabs = [ @@ -98,6 +98,7 @@ function NFTDetails({ nftInfo, nftsCount, network, intl }: Props & Intl): Node { setCopy(false) } } + const onClose = () => setOpen(false) return ( @@ -131,7 +132,7 @@ function NFTDetails({ nftInfo, nftsCount, network, intl }: Props & Intl): Node { borderRadius: '8px', }} > - + nftInfo.image && setOpen(true)} flex="1" flexShrink={0}> @@ -259,6 +260,19 @@ function NFTDetails({ nftInfo, nftsCount, network, intl }: Props & Intl): Node { + + + {nftInfo.name} + + ); } From fd32c57b4ce2eab05352a0dafec1121cebbfedef Mon Sep 17 00:00:00 2001 From: Ahmed Ibrahim Date: Fri, 22 Jul 2022 15:12:52 +0200 Subject: [PATCH 035/153] Paginate through NFTs list --- .../assets-page/chevron-right.inline.svg | 3 + .../components/wallet/assets/NFTDetails.js | 178 +++++++++++------- .../app/components/wallet/assets/NFTsList.js | 4 +- .../widgets/CopyToClipboardLabel.js | 2 + .../containers/wallet/NFTDetailPageRevamp.js | 46 +++-- 5 files changed, 146 insertions(+), 87 deletions(-) create mode 100644 packages/yoroi-extension/app/assets/images/assets-page/chevron-right.inline.svg diff --git a/packages/yoroi-extension/app/assets/images/assets-page/chevron-right.inline.svg b/packages/yoroi-extension/app/assets/images/assets-page/chevron-right.inline.svg new file mode 100644 index 0000000000..737b86de86 --- /dev/null +++ b/packages/yoroi-extension/app/assets/images/assets-page/chevron-right.inline.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/yoroi-extension/app/components/wallet/assets/NFTDetails.js b/packages/yoroi-extension/app/components/wallet/assets/NFTDetails.js index 0cae3f9c7b..1b18448453 100644 --- a/packages/yoroi-extension/app/components/wallet/assets/NFTDetails.js +++ b/packages/yoroi-extension/app/components/wallet/assets/NFTDetails.js @@ -1,7 +1,7 @@ // @flow import { Node, ComponentType, useState } from 'react'; import { Box, styled } from '@mui/system'; -import { Link as LinkMui, Grid, Typography, Stack, Tab, Modal, ThemeProvider, createTheme, Button } from '@mui/material'; +import { Link as LinkMui, Typography, Stack, Tab, Modal, ThemeProvider, createTheme, Button, IconButton } from '@mui/material'; import { TabContext, TabPanel, TabList } from '@mui/lab'; import globalMessages from '../../../i18n/global-messages'; import { injectIntl, defineMessages } from 'react-intl'; @@ -9,8 +9,10 @@ import { ReactComponent as LinkSvg } from '../../../assets/images/link.inline.s import { ReactComponent as BackArrow } from '../../../assets/images/assets-page/backarrow.inline.svg'; import { ReactComponent as IconCopy } from '../../../assets/images/copy.inline.svg'; import { ReactComponent as IconCopied } from '../../../assets/images/copied.inline.svg'; +import { ReactComponent as Chevron } from '../../../assets/images/assets-page/chevron-right.inline.svg'; import moment from 'moment'; +import querystring from 'querystring'; import type { $npm$ReactIntl$IntlShape } from 'react-intl'; import { Link } from 'react-router-dom'; import { ROUTES } from '../../../routes-config'; @@ -72,27 +74,36 @@ const messages = defineMessages({ } }) -function NFTDetails({ nftInfo, nftsCount, network, intl }: Props & Intl): Node { +function NFTDetails({ + nftInfo, + nftsCount, + network, + intl, + nextNftId, + prevNftId, + tab +}: Props & Intl): Node { if (nftInfo == null) return null; const networkUrl = getNetworkUrl(network); - const [value, setValue] = useState(1); + const [value, setValue] = useState(tab); const [open, setOpen] = useState(false); const [isCopied, setCopy] = useState(false); const tabs = [ { - id: 0, + id: 'overview', label: intl.formatMessage(messages.overview), }, { - id: 1, + id: 'metadata', label: intl.formatMessage(messages.metadata), }, ]; const onCopyMetadata = async () => { + setCopy(false) try { - await navigator.clipboard.writeText(nftInfo.nftMetadata) + await navigator.clipboard.writeText(JSON.stringify(nftInfo.nftMetadata, null, 2)) setCopy(true) } catch (error) { setCopy(false) @@ -136,11 +147,37 @@ function NFTDetails({ nftInfo, nftsCount, network, intl }: Props & Intl): Node { - - + + {nftInfo.name} - + + + + + + + + + + + + + + @@ -156,85 +193,82 @@ function NFTDetails({ nftInfo, nftsCount, network, intl }: Props & Intl): Node { aria-label="NFTs tabs" > {tabs.map(({ label, id }) => ( - + ))} - - - - - - {/* TODO: replace with created date */} - - - - - - {intl.formatMessage(tokenMessages.detailsOn)} - - - - - - } - value={ - - Cardanoscan - - } - /> - - - + + + + + + + + + + {nftInfo.id} } /> - - - {nftInfo.policyId} - - } - /> - - - - + + + + {nftInfo.policyId} + + } + /> + + + + + + {intl.formatMessage(tokenMessages.detailsOn)} + + + + + + } + value={ + + Cardanoscan + + } + /> {nftInfo.nftMetadata && + {intl.formatMessage(globalMessages.sidebarFaq)} + + + ); } diff --git a/packages/yoroi-extension/app/components/topbar/Sidebar.scss b/packages/yoroi-extension/app/components/topbar/Sidebar.scss index 3779947f0a..5b270053c9 100644 --- a/packages/yoroi-extension/app/components/topbar/Sidebar.scss +++ b/packages/yoroi-extension/app/components/topbar/Sidebar.scss @@ -19,6 +19,13 @@ flex: 1; } +.footer { + display: flex; + align-items: center; + justify-content: space-between; + flex-wrap: wrap; +} + .faq { max-width: 47px; text-transform: uppercase; From d3a95f9f3ae9a83eed0c8065ca3adcd4e4f2746c Mon Sep 17 00:00:00 2001 From: Patriciu Nista Date: Fri, 5 Aug 2022 12:55:30 +0200 Subject: [PATCH 055/153] Stake Pool Delegated with placeholders --- .../DelegatedStakePoolCard.js | 111 +++-- .../dashboard-revamp/EpochProgressWrapper.js | 59 +++ .../dashboard-revamp/RewardGraphClean.js | 29 +- .../dashboard-revamp/RewardHistoryDialog.js | 10 +- .../dashboard-revamp/RewardHistoryGraph.js | 7 +- .../staking/dashboard-revamp/StakingTabs.js | 101 ---- .../staking/dashboard-revamp/SummaryCard.js | 2 +- .../containers/wallet/staking/SeizaFetcher.js | 107 +++-- .../containers/wallet/staking/StakingPage.js | 451 ++++++------------ 9 files changed, 386 insertions(+), 491 deletions(-) create mode 100644 packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/EpochProgressWrapper.js delete mode 100644 packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/StakingTabs.js diff --git a/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/DelegatedStakePoolCard.js b/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/DelegatedStakePoolCard.js index d45b40b24f..1eb7f504e8 100644 --- a/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/DelegatedStakePoolCard.js +++ b/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/DelegatedStakePoolCard.js @@ -20,51 +20,100 @@ type Intl = {| |}; function DelegatedStakePoolCard({ delegatedPool, undelegate, intl }: Props & Intl): Node { - const { id, name, avatar, roa, socialLinks, websiteUrl } = delegatedPool || {}; + const { id, name, ticker, poolSize, share, avatar, roa, socialLinks, websiteUrl } = + delegatedPool || {}; const avatarGenerated = getAvatarFromPoolId(id); return ( - - - {avatar != null ? ( - - ) : ( - - )} - - - - {name} + + + + {intl.formatMessage(globalMessages.stakePoolDelegated)} - - {roa != null ? ( - - - {intl.formatMessage(globalMessages.roa30d)} - - {roa} - + + + {avatar != null ? ( + + ) : ( + + )} + + + + {`[${ticker}]`} {name} - + - ) : null} - - {intl.formatMessage(globalMessages.undelegateLabel)} - - + + + {roa != null ? ( + + + {intl.formatMessage(globalMessages.roa30d)} + + + {roa} % + + + ) : null} + {poolSize && ( + + + Pool Size + + + {poolSize} + + + )} + {share && ( + + + Share + + + {share} % + + + )} + + + + {intl.formatMessage(globalMessages.undelegateLabel)} + + + ); } export default (injectIntl(observer(DelegatedStakePoolCard)): ComponentType); +const Card = styled(Box)({ + backgroundColor: 'var(--yoroi-palette-common-white)', + borderRadius: '8px', + flex: '1 1 100%', + display: 'flex', + flexDirection: 'column', +}); + const Wrapper: any = styled(Box)({ display: 'flex', - justifyContent: 'space-between', + padding: 24, }); + const AvatarWrapper: any = styled(Box)({ width: '40px', height: '40px', diff --git a/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/EpochProgressWrapper.js b/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/EpochProgressWrapper.js new file mode 100644 index 0000000000..49198eadab --- /dev/null +++ b/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/EpochProgressWrapper.js @@ -0,0 +1,59 @@ +// @flow +import type { ComponentType, Node } from 'react'; +import { Box, styled } from '@mui/system'; +import { Typography } from '@mui/material'; +import { observer } from 'mobx-react'; +import { injectIntl } from 'react-intl'; +import type { $npm$ReactIntl$IntlShape } from 'react-intl'; +import globalMessages from '../../../../i18n/global-messages'; +import { EpochProgressCard } from './EpochProgressCard'; +import moment from 'moment'; + +type Props = {| + epochProgress: {| + currentEpoch: number, + startEpochDate: string, + endEpochDate: string, + percentage: number, + |}, +|}; + +type Intl = {| + intl: $npm$ReactIntl$IntlShape, +|}; + +function EpochProgressWrapper({ epochProgress, intl }: Props & Intl): Node { + return ( + + + + {intl.formatMessage(globalMessages.epochProgress)} + + + + + + + ); +} + +export default (injectIntl(observer(EpochProgressWrapper)): ComponentType); + +const Card = styled(Box)({ + backgroundColor: 'var(--yoroi-palette-common-white)', + borderRadius: '8px', + flex: '1 1 100%', + display: 'flex', + flexDirection: 'column', +}); diff --git a/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/RewardGraphClean.js b/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/RewardGraphClean.js index 9f39161221..520834dd6e 100644 --- a/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/RewardGraphClean.js +++ b/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/RewardGraphClean.js @@ -17,7 +17,7 @@ import { Typography } from '@mui/material'; import type { GraphItems } from '../dashboard/GraphWrapper'; const graphVars = { - barWidth: Number(readCssVar('--yoroi-dashboard-graph-bar-width')), + barWidth: 10, fontSize: '14px', lineHeight: 16, }; @@ -90,41 +90,48 @@ export default class RewardGraphClean extends Component { // $FlowExpectedError[prop-missing] props are passed implicitly which causes a flow error const graphTooltip = ; return ( - - + + diff --git a/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/RewardHistoryDialog.js b/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/RewardHistoryDialog.js index 23a3f9b9a3..d62ebfb199 100644 --- a/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/RewardHistoryDialog.js +++ b/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/RewardHistoryDialog.js @@ -1,5 +1,6 @@ // @flow import type { Node, ComponentType } from 'react'; +import type { GraphData } from '../../../wallet/staking/dashboard/StakingDashboard'; import { useMemo } from 'react'; import { observer } from 'mobx-react'; import globalMessages from '../../../../i18n/global-messages'; @@ -32,7 +33,7 @@ export type GraphRewardData = {| |}; type Props = {| - graphData: GraphRewardData, + graphData: GraphData, onClose: () => void, |}; type Intl = {| @@ -40,7 +41,8 @@ type Intl = {| |}; function RewardHistoryDialog({ graphData, onClose, intl }: Props & Intl): Node { - const rewardList = graphData.items; + const rewardItems = graphData.rewardsGraphData.items; + const rewardList = rewardItems?.totalRewards.filter(p => Boolean(p.primary)) ?? []; const rewardsByPoolName = useMemo(() => groupByPoolName(rewardList), []); @@ -57,12 +59,12 @@ function RewardHistoryDialog({ graphData, onClose, intl }: Props & Intl): Node { {intl.formatMessage(globalMessages.rewardsListLabel)} ({rewardList.length}) - {graphData.error && ( + {graphData.rewardsGraphData.error && (
- +
)} {rewardList == null ? ( diff --git a/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/RewardHistoryGraph.js b/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/RewardHistoryGraph.js index 372f6b4ce5..807f55f3bb 100644 --- a/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/RewardHistoryGraph.js +++ b/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/RewardHistoryGraph.js @@ -133,11 +133,14 @@ function RewardHistoryGraph({ const rewardList = rewardsGraphData.items?.perEpochRewards; const title = intl.formatMessage(globalMessages.rewardHistory); return ( - + Promise), - |}, - epochProgress: {| - currentEpoch: number, - startEpochDate: string, - endEpochDate: string, - percentage: number, - |}, -|}; - -type Intl = {| - intl: $npm$ReactIntl$IntlShape, -|}; - -const messages = defineMessages({ - alertInfo: { - id: 'wallet.staking.alertInfo', - defaultMessage: - '!!!The first reward to receive takes 3-4 epochs which is equal to 15-20 days, learn more.', - }, - epochAxisLabel: { - id: 'wallet.dashboard.graph.epochAxisLabel', - defaultMessage: '!!!Epoch ({epochLength} days)', - }, - singleEpochAxisLabel: { - id: 'wallet.dashboard.graph.singleEpochAxisLabel', - defaultMessage: '!!!Epoch (1 day)', - }, -}); - -function StakingTabs({ delegatedPool, epochProgress, intl }: Props & Intl): Node { - return ( - - - - - ); -} - -export default (injectIntl(observer(StakingTabs)): ComponentType); - -const Card = styled(Box)({ - backgroundColor: 'var(--yoroi-palette-common-white)', - borderRadius: '8px', - flex: '1 1 48.5%', - maxWidth: '48.5%', - display: 'flex', - flexDirection: 'column', - height: '100%', -}); - -const StyledTab = styled(Tab)({ - '&.MuiTab-root': { - paddingLeft: 0, - paddingRight: 0, - paddingTop: '24px', - paddingBottom: '20px', - marginLeft: '24px', - fontWeight: 500, - }, -}); - -const TabPanel = styled(TabPanelBase)({ - flex: 'auto', - overflow: 'auto', -}); diff --git a/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/SummaryCard.js b/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/SummaryCard.js index 4e7c44aa1a..f72312fe6a 100644 --- a/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/SummaryCard.js +++ b/packages/yoroi-extension/app/components/wallet/staking/dashboard-revamp/SummaryCard.js @@ -113,7 +113,7 @@ function SummaryCard({ diff --git a/packages/yoroi-extension/app/containers/wallet/staking/SeizaFetcher.js b/packages/yoroi-extension/app/containers/wallet/staking/SeizaFetcher.js index 95a451a766..1db7090322 100644 --- a/packages/yoroi-extension/app/containers/wallet/staking/SeizaFetcher.js +++ b/packages/yoroi-extension/app/containers/wallet/staking/SeizaFetcher.js @@ -3,7 +3,7 @@ import { Component } from 'react'; import type { Node, ComponentType } from 'react'; import { action, observable } from 'mobx'; -import { intlShape, } from 'react-intl'; +import { intlShape } from 'react-intl'; import type { $npm$ReactIntl$IntlFormat } from 'react-intl'; import environment from '../../../environment'; import VerticallyCenteredLayout from '../../../components/layout/VerticallyCenteredLayout'; @@ -11,6 +11,7 @@ import LoadingSpinner from '../../../components/widgets/LoadingSpinner'; import { observer } from 'mobx-react'; import { withLayout } from '../../../styles/context/layout'; import type { Layouts } from '../../../styles/context/layout'; +import string from 'lodash/string'; export type SocialLinks = {| tw?: string, @@ -27,11 +28,13 @@ export type PoolData = {| +name: string, +avatar?: string, +roa?: string, + +poolSize?: number, + +share?: string, +websiteUrl?: string, + +ticker?: string, +socialLinks?: SocialLinks, |}; - type Props = {| +children?: Node, +urlTemplate: string, @@ -52,8 +55,8 @@ type AllProps = {| ...Props, ...InjectedProps |}; @observer class SeizaFetcher extends Component { - static defaultProps: {|children: void|} = { - children: undefined + static defaultProps: {| children: void |} = { + children: undefined, }; @observable iframe: ?HTMLIFrameElement; @@ -73,16 +76,26 @@ class SeizaFetcher extends Component { * * For more information, see https://www.html5rocks.com/en/tutorials/security/sandboxed-iframes/ */ - if (!( - event.origin === 'null' && /* message from a different origin implies event.origin is "null" */ - event.source === this.iframe.contentWindow /* check it belongs to our iframe */ - )) { + if ( + !( + ( + event.origin === + 'null' /* message from a different origin implies event.origin is "null" */ && + event.source === this.iframe.contentWindow + ) /* check it belongs to our iframe */ + ) + ) { return; } const response = JSON.parse(decodeURI(event.data)); // if it's the pool info object - if (typeof response === 'object' && !Array.isArray(response) && response !== null && response.id) { + if ( + typeof response === 'object' && + !Array.isArray(response) && + response !== null && + response.id + ) { // $FlowFixMe[not-a-function] only added for banner this.props.setFirstPool(response); return; @@ -97,15 +110,19 @@ class SeizaFetcher extends Component { } const poolId: string = pool; if (poolId.length !== 56) { - throw new Error(`${nameof(SeizaFetcher)} Server response has incorrect pool length. Expected 56, got ${poolId.length}`); + throw new Error( + `${nameof(SeizaFetcher)} Server response has incorrect pool length. Expected 56, got ${ + poolId.length + }` + ); } await this.props.stakepoolSelectedAction(pool); - } + }; - @action setFrame: (null | HTMLIFrameElement) => void = (frame) => { + @action setFrame: (null | HTMLIFrameElement) => void = frame => { this.iframe = frame; - } + }; constructor(props: AllProps) { super(props); @@ -122,7 +139,7 @@ class SeizaFetcher extends Component { window.removeEventListener('message', this.messageHandler); } - static contextTypes: {|intl: $npm$ReactIntl$IntlFormat|} = { + static contextTypes: {| intl: $npm$ReactIntl$IntlFormat |} = { intl: intlShape.isRequired, }; @@ -146,31 +163,31 @@ class SeizaFetcher extends Component { return (