Skip to content

Commit

Permalink
731 multi token display pocmvp (#734)
Browse files Browse the repository at this point in the history
* Add multi token display functionality

* Add underline on balance for hover

* Change tooltip and notification UBI info from monthly rate to daily

* Replace seed phrase with magic words consistently

* Add Balance Breakdown link to token display in Navigation

* Fix console error in Welcome view

---------

Co-authored-by: miko <[email protected]>
  • Loading branch information
louilinn and mikozet committed Oct 5, 2023
1 parent 5a4fe46 commit 60042ed
Show file tree
Hide file tree
Showing 14 changed files with 328 additions and 25 deletions.
27 changes: 16 additions & 11 deletions locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"bodyExplainMeTrustedSomeone": "You trusted @{actor} which means that @{actor} can send you their tokens.",
"bodyExplainMeUntrustedSomeone": "You untrusted @{actor} which means that you do not accept any tokens from them anymore.",
"bodyExplainReceivedCircles": "You received {value} {denominator} from @{actor} transitively.",
"bodyExplainReceivedUBI": "This is your Universal Basic Income, issued as your own personal currency. You receive circa {rate} per month.",
"bodyExplainReceivedUBI": "This is your Universal Basic Income, issued as your own personal currency. You receive {rate} per day.",
"bodyExplainSecondary": "All activities carry a small transaction fee used to maintain the Circles network.",
"bodyExplainSentCircles": "You sent {value} {denominator} to @{actor} transitively.",
"bodyExplainTrustedBySomeone": "@{actor} trusts you. You can send your token to them now.",
Expand All @@ -44,7 +44,7 @@
},
"BalanceDisplay": {
"tooltipSharedWalletBalance": "This is the shared wallet balance. Shared wallets do not receive basic income.",
"tooltipYourBalance": "Your basic income is issued continuously at the rate of {rate} Circles a month."
"tooltipYourBalance": "Your basic income is issued continuously at the rate of {rate} circles per day."
},
"ButtonClipboard": {
"buttonCopy": "Copy to clipboard",
Expand All @@ -63,7 +63,7 @@
"bodyCriticalErrorTryAgain": "Oh no! Something went wrong while loading your account. Please reload this page and try again.",
"buttonBurnWallet": "Reset Account",
"buttonReload": "Refresh Page",
"dialogAreYouSure": "Do you really want to reset this wallet? You will not be able to recover without a seed phrase.",
"dialogAreYouSure": "Do you really want to reset this wallet? You will not be able to recover without your magic words.",
"infoCopiedMessage": "Text copied to clipboard"
},
"Dashboard": {
Expand All @@ -85,7 +85,7 @@
"DialogBurn": {
"dialogBurnCancel": "Cancel",
"dialogBurnConfirm": "End Session",
"dialogBurnDescription": "Are you sure you want to end this session? You will not be able to restore your account unless you have your Seed Phrase!",
"dialogBurnDescription": "Are you sure you want to end this session? You will not be able to restore your account unless you have your Magic Words!",
"dialogBurnTitle": "Warning!"
},
"DialogTrust": {
Expand Down Expand Up @@ -191,12 +191,12 @@
"es": "ES"
},
"Login": {
"bodyEnterYourSeedPhrase": "Enter your seed phrase below to restore your wallet:",
"bodyLostYourSeedPhrase": "Lost your seed phrase?",
"bodyEnterYourSeedPhrase": "Enter your magic words below to restore your wallet:",
"bodyLostYourSeedPhrase": "Lost your magic words?",
"bodyNeedHelp": "Questions?",
"buttonCreateNewWallet": "Sign Up Here",
"buttonSubmit": "Submit",
"errorRestoreFailedInvalidSeedphrase": "Your seed phrase is invalid.",
"errorRestoreFailedInvalidSeedPhrase": "Your magic words are invalid.",
"errorRestoreFailedUnknown": "Could not restore account due to an unknown error.",
"errorRestoreFailedUnknownSafe": "The account you tried to restore is not registered.",
"headingLogin": "Login",
Expand All @@ -211,8 +211,9 @@
},
"Navigation": {
"buttonActivityLog": "Activity Log",
"buttonBalanceTokens": "Balance Breakdown",
"buttonSettings": "Settings",
"buttonExportSeedPhrase": "Export Seed Phrase",
"buttonExportSeedPhrase": "Export Magic Words",
"buttonMyQR": "My QR",
"buttonDoublePeople": "Trust People",
"buttonSendCircles": "Send Circles",
Expand Down Expand Up @@ -247,7 +248,7 @@
"bodySecureWalletP1B": " in a place you trust.",
"bodySecureWalletP2": "This is the only way to recover your wallet if you get locked out of the app, or get a new device.",
"bodySeedPhrase": "This is your account password. You can use this to login into your account on other devices.",
"bodySeedPhraseChallenge": "Please enter word {wordIndex} in your seed phrase:",
"bodySeedPhraseChallenge": "Please enter word {wordIndex} in your magic words:",
"bodyUsername": "Your username is how your friends can search for you on the Circles App.",
"bodyGuidelinesUsername": "Only basic characters and numbers (A-Z, 0-9) are allowed, no symbols or whitespace, 3-24 characters.",
"buttonCopyToClipboard": "Copy to clipboard",
Expand Down Expand Up @@ -362,7 +363,7 @@
"SeedPhrase": {
"bodyDescription": "Print this and store it safely:",
"buttonCopyToClipboard": "Copy to clipboard",
"headingExportSeedPhrase": "Export Seed Phrase"
"headingExportSeedPhrase": "Export Magic Words"
},
"Send": {
"headingSendCircles": "Send Circles"
Expand Down Expand Up @@ -416,6 +417,10 @@
"TextVerification": {
"noteInvalid": "You cannot write special symbols like {}<br>^ or more than 100 characters."
},
"Tokens": {
"headingTokens": "Balance Breakdown",
"descriptionTokens": "All circles you hold were originally issued as someone's basic income. These users are the original issuers of the circles you hold. Each of these circles can be sent directly to other wallets that trust these users."
},
"TransferInfoBalanceCard": {
"bodyTotalBalance": "Your total balance: {balance}",
"tooltipTotalBalance": "This is the current balance of all Circles you have on your account"
Expand Down Expand Up @@ -449,7 +454,7 @@
"infoUbiPayoutReceived": "You just received your UBI of <br><strong>{payout}circles</strong> for the month!"
},
"Validation": {
"bodyDoNotReset": "Do not reset your browser local storage or you will need to recover your data with your seed phrase.",
"bodyDoNotReset": "Do not reset your browser local storage or you will need to recover your data with your magic words.",
"bodyTrustDescription": "To receive your basic income,",
"bodyTrustDescriptionEmphasize": "three people must trust your profile.",
"buttonShareProfileLink": "Share Profile Link",
Expand Down
2 changes: 1 addition & 1 deletion src/components/ActivityStreamItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ const ActivityStreamExplained = ({
return translate(`ActivityStream.bodyExplain${messageId}`, {
...data,
actor,
rate: ISSUANCE_RATE_MONTH,
rate: ISSUANCE_RATE_MONTH / 30,
});
}, [actor, data, messageId]);

Expand Down
29 changes: 24 additions & 5 deletions src/components/BalanceDisplay.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import { CircularProgress } from '@mui/material';
import { Box, Tooltip, Typography } from '@mui/material';
import makeStyles from '@mui/styles/makeStyles';
import PropTypes from 'prop-types';
import React from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { Link } from 'react-router-dom';

import { TOKENS_PATH } from '~/routes';

import { useUpdateLoop } from '~/hooks/update';
import translate from '~/services/locale';
Expand All @@ -26,9 +30,15 @@ const useStyles = makeStyles((theme) => ({
marginRight: theme.spacing(0.5),
fontSize: '2.3rem',
},
balanceUnderline: {
'&:hover': {
textDecoration: 'underline',
textDecorationColor: theme.custom.colors.violet,
},
},
}));

const BalanceDisplay = () => {
const BalanceDisplay = ({ underlineAtHover = true }) => {
const dispatch = useDispatch();
const classes = useStyles();
const { token, safe } = useSelector((state) => state);
Expand All @@ -46,7 +56,7 @@ const BalanceDisplay = () => {
const tooltipText = safe.isOrganization
? translate('BalanceDisplay.tooltipSharedWalletBalance')
: translate('BalanceDisplay.tooltipYourBalance', {
rate: ISSUANCE_RATE_MONTH,
rate: ISSUANCE_RATE_MONTH / 30,
});

return (
Expand All @@ -55,14 +65,23 @@ const BalanceDisplay = () => {
{isLoading ? (
<CircularProgress />
) : (
<Typography variant="balance1">
<IconCircles className={classes.balanceIcon} />
{tokenBalance}
<Typography
className={underlineAtHover && classes.balanceUnderline}
variant="balance1"
>
<Link to={TOKENS_PATH}>
<IconCircles className={classes.balanceIcon} />
{tokenBalance}
</Link>
</Typography>
)}
</Box>
</Tooltip>
);
};

BalanceDisplay.propTypes = {
underlineAtHover: PropTypes.bool,
};

export default BalanceDisplay;
1 change: 0 additions & 1 deletion src/components/Finder.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ function filterToQuery(filterName) {
const useStyles = makeStyles((theme) => ({
searchItem: {
cursor: 'pointer',
boxShadow: theme.custom.shadows.gray,
},
noSearchResultContainer: {
marginTop: '80px',
Expand Down
4 changes: 4 additions & 0 deletions src/components/Navigation.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
SEND_PATH,
SETTINGS_PATH,
SHARE_PATH,
TOKENS_PATH,
} from '~/routes';

import AvatarWithQR from '~/components/AvatarWithQR';
Expand Down Expand Up @@ -134,6 +135,9 @@ const NavigationMain = ({ onClick }) => {
<NavigationLink to={ACTIVITIES_PATH} onClick={onClick}>
{translate('Navigation.buttonActivityLog')}
</NavigationLink>
<NavigationLink to={TOKENS_PATH} onClick={onClick}>
{translate('Navigation.buttonBalanceTokens')}
</NavigationLink>
{!safe.isOrganization && (
<NavigationLink to={ORGANIZATION_PATH} onClick={onClick}>
{translate('Navigation.buttonOrganization')}
Expand Down
28 changes: 25 additions & 3 deletions src/components/ProfileMini.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
Typography,
} from '@mui/material';
import makeStyles from '@mui/styles/makeStyles';
import clsx from 'clsx';
import PropTypes from 'prop-types';
import React, { Fragment, useState } from 'react';
import { useDispatch } from 'react-redux';
Expand All @@ -28,6 +29,16 @@ import { addSafeOwner } from '~/store/safe/actions';
import { IconFriends, IconSend, IconTrust } from '~/styles/icons';

const useStyles = makeStyles((theme) => ({
cardContainer: {
boxShadow: theme.custom.shadows.navigationFloating,
'&:hover': {
background: theme.custom.colors.blackSqueeze,

'& .MuiCardHeader-root': {
background: theme.custom.colors.blackSqueeze,
},
},
},
cardHeader: {
padding: theme.spacing(1),
},
Expand Down Expand Up @@ -64,6 +75,7 @@ const ProfileMini = ({
className,
hasActions = false,
isSharedWalletCreation,
value,
...props
}) => {
const classes = useStyles();
Expand Down Expand Up @@ -160,18 +172,27 @@ const ProfileMini = ({
onConfirm={handleClose}
/>
)}
<Card {...props} className={className}>
<Card {...props} className={clsx(className, classes.cardContainer)}>
<CardHeader
action={
hasActions && (
(hasActions && (
<ProfileMiniActions
address={address}
connection={connection}
isSharedWalletCreation={isSharedWalletCreation}
onSend={handleSend}
onTrust={handleTrust}
/>
)
)) ||
(value && (
<Typography
classes={{ root: 'h1_blue' }}
component="span"
variant="h1"
>
{value}
</Typography>
))
}
avatar={<Avatar address={address} />}
classes={{
Expand Down Expand Up @@ -258,6 +279,7 @@ ProfileMini.propTypes = {
className: PropTypes.string,
hasActions: PropTypes.bool,
isSharedWalletCreation: PropTypes.bool,
value: PropTypes.string,
};

ProfileMiniActions.propTypes = {
Expand Down
3 changes: 3 additions & 0 deletions src/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import Send from '~/views/Send';
import SendConfirm from '~/views/SendConfirm';
import Settings from '~/views/Settings';
import Share from '~/views/Share';
import Tokens from '~/views/Tokens';
import TutorialOnboarding from '~/views/TutorialOnboarding';
import Validation from '~/views/Validation';
import ValidationLock from '~/views/ValidationLock';
Expand All @@ -43,6 +44,7 @@ export const ORGANIZATION_PATH = '/organization';
export const PROFILE_PATH = '/profile/:address';
export const QR_GENERATOR_PATH = '/sharedwallet/qr';
export const SEARCH_PATH = '/search';
export const TOKENS_PATH = '/balance';
export const SEED_PHRASE_PATH = '/seedphrase';
export const SEND_CONFIRM_PATH = '/send/:address(0x[0-9a-fA-f]{40})';
export const SEND_PATH = '/send';
Expand Down Expand Up @@ -265,6 +267,7 @@ const Routes = () => {
<TrustedRoute component={EditProfile} exact path={EDIT_PROFILE_PATH} />
<TrustedRoute component={QRGenerator} exact path={QR_GENERATOR_PATH} />
<TrustedRoute component={Search} exact path={SEARCH_PATH} />
<TrustedRoute component={Tokens} exact path={TOKENS_PATH} />
<OrganizationRoute
component={OrganizationMembersAdd}
exact
Expand Down
68 changes: 66 additions & 2 deletions src/store/token/actions.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { tcToCrc } from '@circles/timecircles';
import { Typography } from '@mui/material';
import { DateTime } from 'luxon';
import React from 'react';

import core from '~/services/core';
import translate from '~/services/locale';
Expand All @@ -9,7 +11,8 @@ import { addPendingActivity } from '~/store/activity/actions';
import notify, { NotificationsTypes } from '~/store/notifications/actions';
import ActionTypes from '~/store/token/types';
import { PATHFINDER_HOPS_DEFAULT, ZERO_ADDRESS } from '~/utils/constants';
import logError from '~/utils/debug';
import logError, { translateErrorForUser } from '~/utils/debug';
import { formatCirclesValue } from '~/utils/format';
import { isTokenDeployed, waitAndRetryOnFail } from '~/utils/stateChecks';

const { ActivityTypes } = core.activity;
Expand Down Expand Up @@ -139,7 +142,7 @@ export function checkTokenState() {

export function checkCurrentBalance() {
return async (dispatch, getState) => {
const { safe, token } = getState();
const { token, safe } = getState();

// No token address given yet
if (!token.address && !safe.isOrganization) {
Expand Down Expand Up @@ -167,6 +170,67 @@ export function checkCurrentBalance() {
};
}

export function checkOtherTokens() {
return async (dispatch, getState) => {
const { safe } = getState();

try {
const otherTokens = await core.token.listAllTokens(safe.currentAccount);

const filterOrderedOtherTokens = otherTokens
.filter(
(item) =>
formatCirclesValue(item.amount, Date.now(), 2, false) > 0.005,
)
.reverse();
dispatch({
type: ActionTypes.TOKEN_UPDATE_OTHER_TOKENS,
meta: {
otherTokens: filterOrderedOtherTokens,
},
});
dispatch({
type: ActionTypes.TOKEN_UPDATE_OTHER_TOKENS_SUCCESS,
});
} catch (error) {
dispatch({
type: ActionTypes.TOKEN_UPDATE_OTHER_TOKENS_LOADING,
meta: {
isLoading: false,
},
});
dispatch({
type: ActionTypes.TOKEN_UPDATE_OTHER_TOKENS_ERROR,
meta: {
isError: true,
},
});
logError(error);
dispatch(
notify({
text: (
<Typography classes={{ root: 'body4_white' }} variant="body4">
{translateErrorForUser(error)}
</Typography>
),
type: NotificationsTypes.ERROR,
}),
);
}
};
}

export function checkOtherTokensLoading(isLoading) {
return async (dispatch) => {
dispatch({
type: ActionTypes.TOKEN_UPDATE_OTHER_TOKENS_LOADING,
meta: {
isLoading,
},
});
};
}

export function requestUBIPayout(payout) {
return async (dispatch, getState) => {
const { safe, token } = getState();
Expand Down
Loading

0 comments on commit 60042ed

Please sign in to comment.