diff --git a/cashtab/src/components/Home/Home.js b/cashtab/src/components/Home/Home.js --- a/cashtab/src/components/Home/Home.js +++ b/cashtab/src/components/Home/Home.js @@ -1,4 +1,5 @@ -import React from 'react'; +import React, { useState, useEffect } from 'react'; +import PropTypes from 'prop-types'; import styled from 'styled-components'; import { WalletContext } from 'utils/context'; import OnBoarding from 'components/OnBoarding/OnBoarding'; @@ -17,8 +18,12 @@ import WalletLabel from 'components/Common/WalletLabel.js'; import { SmartButton } from 'components/Common/PrimaryButton'; import { isValidSideshiftObj } from 'utils/validation'; - +const { Panel } = Collapse; +import { Collapse, Tooltip } from 'antd'; +import { StyledCollapse } from 'components/Common/StyledCollapse'; import appConfig from 'config/app'; +import { formatSavedBalance } from 'utils/formatting'; +import { Event } from 'utils/GoogleAnalytics'; export const Tabs = styled.div` margin: auto; @@ -142,7 +147,155 @@ } `; -const WalletInfo = () => { +const AWRow = styled.div` + padding: 10px 0; + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 6px; + h3 { + font-size: 16px; + flex: 1 1 0; + display: inline-block; + color: ${props => props.theme.darkBlue}; + margin: 0; + text-align: left; + font-weight: bold; + @media (max-width: 500px) { + font-size: 14px; + } + } + h4 { + font-size: 16px; + flex: 1 1 0; + display: inline-block; + color: ${props => props.theme.eCashBlue} !important; + margin: 0; + text-align: right; + } + @media (max-width: 500px) { + flex-direction: column; + margin-bottom: 12px; + } +`; + +const SWRow = styled.div` + border-radius: 3px; + padding: 10px 0; + display: flex; + align-items: center; + justify-content: center; + margin-bottom: 6px; + @media (max-width: 500px) { + flex-direction: column; + margin-bottom: 12px; + } +`; + +const SWName = styled.div` + width: 50%; + display: flex; + align-items: center; + justify-content: space-between; + word-wrap: break-word; + hyphens: auto; + + @media (max-width: 500px) { + width: 100%; + justify-content: center; + margin-bottom: 15px; + } + + h3 { + font-size: 16px; + color: ${props => props.theme.darkBlue}; + margin: 0; + text-align: center; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + h3.overflow { + width: 100px; + overflow: hidden; + text-overflow: ellipsis; + } +`; + +const SWBalance = styled.div` + width: 50%; + display: flex; + align-items: center; + justify-content: space-between; + word-wrap: break-word; + hyphens: auto; + @media (max-width: 500px) { + width: 100%; + justify-content: center; + margin-bottom: 15px; + } + div { + font-size: 13px; + color: ${props => props.theme.darkBlue}; + margin: 0; + text-align: center; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + div.overflow { + width: 150px; + overflow: hidden; + text-overflow: ellipsis; + } +`; + +const SWButtonCtn = styled.div` + width: 50%; + display: flex; + align-items: center; + justify-content: flex-end; + @media (max-width: 500px) { + width: 100%; + justify-content: center; + } + + button { + cursor: pointer; + background: transparent; + border: 1px solid #fff; + box-shadow: none; + color: #fff; + border-radius: 3px; + opacity: 0.6; + transition: all 200ms ease-in-out; + + :hover { + opacity: 1; + background: ${props => props.theme.eCashBlue}; + border-color: ${props => props.theme.eCashBlue}; + } + + @media (max-width: 768px) { + font-size: 14px; + } + } + + svg { + stroke: ${props => props.theme.eCashBlue}; + fill: ${props => props.theme.eCashBlue}; + width: 20px; + height: 25px; + margin-right: 10px; + cursor: pointer; + :hover { + stroke: ${props => props.theme.settings.delete}; + fill: ${props => props.theme.settings.delete}; + } + } +`; + +const WalletInfo = ({ savedWallets }) => { const ContextValue = React.useContext(WalletContext); const { wallet, @@ -152,6 +305,7 @@ contactList, cashtabCache, changeCashtabSettings, + activateWallet, } = ContextValue; const walletState = getWalletState(wallet); const { balances, parsedTxHistory, tokens } = walletState; @@ -159,6 +313,13 @@ const sideshift = window.sideshift; const hasHistory = parsedTxHistory && parsedTxHistory.length > 0; + const updateSavedWalletsOnLoad = async (wallet, walletToActivate) => { + // Event("Category", "Action", "Label") + // Track number of times a different wallet is activated + Event('Home.js', 'Activate', ''); + await activateWallet(wallet, walletToActivate); + }; + return ( <> @@ -177,6 +338,60 @@ settings={cashtabSettings} fiatPrice={fiatPrice} /> + {savedWallets && savedWallets.length > 0 && ( + + + + +

+ {wallet.name} +

+
+

Currently active

+
+
+ {savedWallets.map(sw => ( + + + +

+ {sw.name} +

+
+
+ +
+ [ + {sw && sw.state + ? formatSavedBalance( + sw.state.balances + .totalBalance, + ) + : 'N/A'}{' '} + XEC] +
+
+ + + +
+ ))} +
+
+
+ )}
{apiError && } @@ -258,9 +473,37 @@ ); }; -const Home = () => { +const Home = ({ passLoadingStatus }) => { const ContextValue = React.useContext(WalletContext); - const { wallet, previousWallet, loading } = ContextValue; + const { wallet, previousWallet, loading, getSavedWallets } = ContextValue; + + const [savedWallets, setSavedWallets] = useState([]); + + const updateSavedWallets = async activeWallet => { + // Lock the UI while getting the correct savedWallets value from indexedDb into state + passLoadingStatus(true); + if (activeWallet) { + let savedWallets; + try { + savedWallets = await getSavedWallets(activeWallet); + setSavedWallets(savedWallets); + } catch (err) { + console.log(`Error in getSavedWallets()`, err); + } + } + }; + + useEffect(async () => { + // Update savedWallets every time the active wallet changes + // Use wallet.name and not wallet as the dep param, since wallet changes every time + // new txs come in or update function from useWallet.js runs + await updateSavedWallets(wallet); + }, [wallet.name]); + + useEffect(() => { + // Only unlock UI when savedWallets is updated in state + passLoadingStatus(false); + }, [savedWallets]); return ( <> @@ -270,7 +513,10 @@ <> {(wallet && wallet.Path1899) || (previousWallet && previousWallet.path1899) ? ( - + ) : ( )} @@ -280,4 +526,25 @@ ); }; +/* +passLoadingStatus must receive a default prop that is a function +in order to pass the rendering unit test in Home.test.js + +status => {console.log(status)} is an arbitrary stub function +*/ + +Home.defaultProps = { + passLoadingStatus: status => { + console.log(status); + }, +}; + +Home.propTypes = { + passLoadingStatus: PropTypes.func, +}; + +WalletInfo.propTypes = { + savedWallets: PropTypes.array, +}; + export default Home; diff --git a/cashtab/src/components/Home/__tests__/__snapshots__/Home.test.js.snap b/cashtab/src/components/Home/__tests__/__snapshots__/Home.test.js.snap --- a/cashtab/src/components/Home/__tests__/__snapshots__/Home.test.js.snap +++ b/cashtab/src/components/Home/__tests__/__snapshots__/Home.test.js.snap @@ -68,23 +68,23 @@ className="sc-lhVmIH gJoLAm" >