diff --git a/web/cashtab/extension/src/components/App.js b/web/cashtab/extension/src/components/App.js
index a1f5f198c..d671fc62b 100644
--- a/web/cashtab/extension/src/components/App.js
+++ b/web/cashtab/extension/src/components/App.js
@@ -1,480 +1,480 @@
import React, { useState } from 'react';
import 'antd/dist/antd.less';
import PropTypes from 'prop-types';
import { Spin } from 'antd';
import {
CashLoadingIcon,
HomeIcon,
SendIcon,
ReceiveIcon,
SettingsIcon,
AirdropIcon,
} from 'components/Common/CustomIcons';
import '../index.css';
import styled, { ThemeProvider, createGlobalStyle } from 'styled-components';
import { theme } from 'assets/styles/theme';
import Home from 'components/Home/Home';
import Receive from 'components/Receive/Receive';
import Tokens from 'components/Tokens/Tokens';
import Send from 'components/Send/Send';
import SendToken from 'components/Send/SendToken';
import Airdrop from 'components/Airdrop/Airdrop';
import Configure from 'components/Configure/Configure';
import NotFound from 'components/NotFound';
import Cashtab from 'assets/cashtab_xec.png';
import './App.css';
import { WalletContext } from 'utils/context';
import { isValidStoredWallet } from 'utils/cashMethods';
import {
Route,
Redirect,
Switch,
useLocation,
useHistory,
} from 'react-router-dom';
// Extension-only import used for open in new tab link
import PopOut from 'assets/popout.svg';
const GlobalStyle = createGlobalStyle`
*::placeholder {
color: ${props => props.theme.forms.placeholder} !important;
}
*::selection {
background: ${props => props.theme.eCashBlue} !important;
}
.ant-modal-content, .ant-modal-header, .ant-modal-title {
background-color: ${props => props.theme.modal.background} !important;
color: ${props => props.theme.modal.color} !important;
}
.ant-modal-content svg {
fill: ${props => props.theme.modal.color};
}
.ant-modal-footer button {
background-color: ${props =>
props.theme.modal.buttonBackground} !important;
color: ${props => props.theme.modal.color} !important;
border-color: ${props => props.theme.modal.border} !important;
:hover {
background-color: ${props => props.theme.eCashBlue} !important;
}
}
.ant-modal-wrap > div > div.ant-modal-content > div > div > div.ant-modal-confirm-btns > button, .ant-modal > button, .ant-modal-confirm-btns > button, .ant-modal-footer > button, #cropControlsConfirm{
border-radius: 3px;
border-radius: 3px;
background-color: ${props =>
props.theme.modal.buttonBackground} !important;
color: ${props => props.theme.modal.color} !important;
border-color: ${props => props.theme.modal.border} !important;
:hover {
background-color: ${props => props.theme.eCashBlue} !important;
}
text-shadow: none !important;
text-shadow: none !important;
}
.ant-modal-wrap > div > div.ant-modal-content > div > div > div.ant-modal-confirm-btns > button:hover,.ant-modal-confirm-btns > button:hover, .ant-modal-footer > button:hover, #cropControlsConfirm:hover {
color: ${props => props.theme.contrast};
transition: all 0.3s;
background-color: ${props => props.theme.eCashBlue};
border-color: ${props => props.theme.eCashBlue};
}
.selectedCurrencyOption, .ant-select-dropdown {
text-align: left;
color: ${props => props.theme.contrast} !important;
background-color: ${props =>
props.theme.collapses.expandedBackground} !important;
}
.cashLoadingIcon {
color: ${props => props.theme.eCashBlue} !important;
font-size: 48px !important;
}
.selectedCurrencyOption:hover {
color: ${props => props.theme.contrast} !important;
background-color: ${props => props.theme.eCashBlue} !important;
}
#addrSwitch, #cropSwitch {
.ant-switch-checked {
background-color: white !important;
}
}
#addrSwitch.ant-switch-checked, #cropSwitch.ant-switch-checked {
background-image: ${props =>
props.theme.buttons.primary.backgroundImage} !important;
}
.ant-slider-rail {
background-color: ${props => props.theme.forms.border} !important;
}
.ant-slider-track {
background-color: ${props => props.theme.eCashBlue} !important;
}
.ant-descriptions-bordered .ant-descriptions-row {
background: ${props => props.theme.contrast};
}
.ant-modal-confirm-content, .ant-modal-confirm-title {
color: ${props => props.theme.contrast} !important;
}
.ant-form-item-explain {
div {
color: ${props => props.theme.forms.text};
}
}
.ant-input-prefix {
color: ${props => props.theme.eCashBlue};
}
.ant-spin-nested-loading>div>.ant-spin .ant-spin-dot {
top: 0 !important;
left: 0 !important;
right: 0 !important;
bottom: 0 !important;
margin: auto !important;
}
.ant-spin-nested-loading>div>.ant-spin {
position: fixed !important;
}
`;
const CustomApp = styled.div`
text-align: center;
font-family: 'Gilroy', sans-serif;
font-family: 'Poppins', sans-serif;
background-color: ${props => props.theme.backgroundColor};
background-size: 100px 171px;
background-image: ${props => props.theme.backgroundImage};
background-attachment: fixed;
`;
const Footer = styled.div`
z-index: 2;
height: 80px;
border-top: 1px solid rgba(255, 255, 255, 0.5);
background-color: ${props => props.theme.footerBackground};
position: fixed;
bottom: 0;
width: 500px;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 50px;
@media (max-width: 768px) {
width: 100%;
padding: 0 20px;
}
`;
const NavWrapper = styled.div`
cursor: pointer;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 1.3rem;
margin-bottom: 5px;
`;
const NavIcon = styled.span`
position: relative;
background-color: ${props =>
props.clicked ? 'transparent' : props.theme.buttons.primary.color};
width: 2rem;
height: 2px;
display: inline-block;
transition: transform 300ms, top 300ms, background-color 300ms;
&::before,
&::after {
content: '';
background-color: ${props => props.theme.buttons.primary.color};
width: 2rem;
height: 2px;
display: inline-block;
position: absolute;
left: 0;
transition: transform 300ms, top 300ms, background-color 300ms;
}
&::before {
top: ${props => (props.clicked ? '0' : '-0.8rem')};
transform: ${props => (props.clicked ? 'rotate(135deg)' : 'rotate(0)')};
}
&::after {
top: ${props => (props.clicked ? '0' : '0.8rem')};
transform: ${props =>
props.clicked ? 'rotate(-135deg)' : 'rotate(0)'};
}
`;
const NavMenu = styled.div`
position: fixed;
- right:0;
+ right: 0;
margin-right: 1px;
bottom: 5rem;
display: flex;
width: 8rem;
flex-direction: column;
border: ${props => (props.open ? '0.1px solid' : '0px solid')};
border-color: ${props =>
props.open ? props.theme.contrast : 'transparent'};
justify-content: center;
align-items: center;
overflow: hidden;
transition: ${props =>
props.open
? 'max-height 1000ms ease-in-out , border-color 800ms ease-in-out, border-width 800ms ease-in-out'
: 'max-height 300ms cubic-bezier(0, 1, 0, 1), border-color 600ms ease-in-out, border-width 800ms ease-in-out'};
max-height: ${props => (props.open ? '100rem' : '0')};
`;
const NavItem = styled.button`
display: flex;
justify-content: right;
align-items: center;
width: 100%;
white-space: nowrap;
height: 3rem;
background-color: ${props => props.theme.walletBackground};
border: none;
color: ${props => props.theme.contrast};
cursor: pointer;
gap: 1rem;
&:hover {
color: ${props => props.theme.navActive};
svg {
fill: ${props => props.theme.navActive};
}
}
svg {
fill: ${props => props.theme.contrast};
width: 26px;
height: auto;
}
`;
export const NavButton = styled.button`
:focus,
:active {
outline: none;
}
cursor: pointer;
padding: 0;
background: none;
border: none;
font-size: 10px;
svg {
fill: ${props => props.theme.contrast};
width: 26px;
height: auto;
}
${({ active, ...props }) =>
active &&
`
color: ${props.theme.navActive};
svg {
fill: ${props.theme.navActive};
}
`}
`;
export const WalletBody = styled.div`
display: flex;
align-items: center;
justify-content: center;
width: 100%;
min-height: 100vh;
`;
export const WalletCtn = styled.div`
position: relative;
width: 500px;
min-height: 100vh;
padding: 0 0 100px;
background: ${props => props.theme.walletBackground};
-webkit-box-shadow: 0px 0px 24px 1px ${props => props.theme.shadow};
-moz-box-shadow: 0px 0px 24px 1px ${props => props.theme.shadow};
box-shadow: 0px 0px 24px 1px ${props => props.theme.shadow};
@media (max-width: 768px) {
width: 100%;
-webkit-box-shadow: none;
-moz-box-shadow: none;
box-shadow: none;
}
`;
export const HeaderCtn = styled.div`
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
padding: 15px;
`;
export const CashtabLogo = styled.img`
width: 120px;
@media (max-width: 768px) {
width: 110px;
}
`;
// Extension only styled components
const OpenInTabBtn = styled.button`
background: none;
border: none;
`;
const ExtTabImg = styled.img`
max-width: 20px;
`;
const App = () => {
const ContextValue = React.useContext(WalletContext);
const { wallet, loading } = ContextValue;
const [loadingUtxosAfterSend, setLoadingUtxosAfterSend] = useState(false);
const [navMenuClicked, setNavMenuClicked] = useState(false);
const handleNavMenuClick = () => setNavMenuClicked(!navMenuClicked);
// If wallet is unmigrated, do not show page until it has migrated
// An invalid wallet will be validated/populated after the next API call, ETA 10s
const validWallet = isValidStoredWallet(wallet);
const location = useLocation();
const history = useHistory();
const selectedKey =
location && location.pathname ? location.pathname.substr(1) : '';
// openInTab is an extension-only method
const openInTab = () => {
window.open(`index.html#/${selectedKey}`);
};
return (
{/*Begin extension-only components*/}
openInTab()}
>
{/*End extension-only components*/}
{/*Note that the extension does not support biometric security*/}
{/*Hence is not pulled in*/}
(
)}
/>
{wallet ? (
) : null}
);
};
App.propTypes = {
match: PropTypes.string,
};
export default App;
diff --git a/web/cashtab/src/components/App.js b/web/cashtab/src/components/App.js
index 300ffb2f7..c4b5e7b80 100644
--- a/web/cashtab/src/components/App.js
+++ b/web/cashtab/src/components/App.js
@@ -1,508 +1,508 @@
import React, { useState } from 'react';
import 'antd/dist/antd.less';
import PropTypes from 'prop-types';
import { Spin } from 'antd';
import {
CashLoadingIcon,
HomeIcon,
SendIcon,
ReceiveIcon,
SettingsIcon,
AirdropIcon,
} from 'components/Common/CustomIcons';
import '../index.css';
import styled, { ThemeProvider, createGlobalStyle } from 'styled-components';
import { theme } from 'assets/styles/theme';
import Home from 'components/Home/Home';
import Receive from 'components/Receive/Receive';
import Tokens from 'components/Tokens/Tokens';
import Send from 'components/Send/Send';
import SendToken from 'components/Send/SendToken';
import Airdrop from 'components/Airdrop/Airdrop';
import Configure from 'components/Configure/Configure';
import NotFound from 'components/NotFound';
import CashTab from 'assets/cashtab_xec.png';
import './App.css';
import { WalletContext } from 'utils/context';
import { isValidStoredWallet } from 'utils/cashMethods';
import {
Route,
Redirect,
Switch,
useLocation,
useHistory,
} from 'react-router-dom';
// Easter egg imports not used in extension/src/components/App.js
import TabCash from 'assets/tabcash.png';
import { checkForTokenById } from 'utils/tokenMethods.js';
// Biometric security import not used in extension/src/components/App.js
import ProtectableComponentWrapper from './Authentication/ProtectableComponentWrapper';
import ServiceWorkerWrapper from './Common/ServiceWorkerWrapper';
const GlobalStyle = createGlobalStyle`
*::placeholder {
color: ${props => props.theme.forms.placeholder} !important;
}
*::selection {
background: ${props => props.theme.eCashBlue} !important;
}
.ant-modal-content, .ant-modal-header, .ant-modal-title {
background-color: ${props => props.theme.modal.background} !important;
color: ${props => props.theme.modal.color} !important;
}
.ant-modal-content svg {
fill: ${props => props.theme.modal.color};
}
.ant-modal-footer button {
background-color: ${props =>
props.theme.modal.buttonBackground} !important;
color: ${props => props.theme.modal.color} !important;
border-color: ${props => props.theme.modal.border} !important;
:hover {
background-color: ${props => props.theme.eCashBlue} !important;
}
}
.ant-modal-wrap > div > div.ant-modal-content > div > div > div.ant-modal-confirm-btns > button, .ant-modal > button, .ant-modal-confirm-btns > button, .ant-modal-footer > button, #cropControlsConfirm {
border-radius: 3px;
background-color: ${props =>
props.theme.modal.buttonBackground} !important;
color: ${props => props.theme.modal.color} !important;
border-color: ${props => props.theme.modal.border} !important;
:hover {
background-color: ${props => props.theme.eCashBlue} !important;
}
text-shadow: none !important;
}
.ant-modal-wrap > div > div.ant-modal-content > div > div > div.ant-modal-confirm-btns > button:hover,.ant-modal-confirm-btns > button:hover, .ant-modal-footer > button:hover, #cropControlsConfirm:hover {
color: ${props => props.theme.contrast};
transition: all 0.3s;
background-color: ${props => props.theme.eCashBlue};
border-color: ${props => props.theme.eCashBlue};
}
.selectedCurrencyOption, .ant-select-dropdown {
text-align: left;
color: ${props => props.theme.contrast} !important;
background-color: ${props =>
props.theme.collapses.expandedBackground} !important;
}
.cashLoadingIcon {
color: ${props => props.theme.eCashBlue} !important;
font-size: 48px !important;
}
.selectedCurrencyOption:hover {
color: ${props => props.theme.contrast} !important;
background-color: ${props => props.theme.eCashBlue} !important;
}
#addrSwitch, #cropSwitch {
.ant-switch-checked {
background-color: white !important;
}
}
#addrSwitch.ant-switch-checked, #cropSwitch.ant-switch-checked {
background-image: ${props =>
props.theme.buttons.primary.backgroundImage} !important;
}
.ant-slider-rail {
background-color: ${props => props.theme.forms.border} !important;
}
.ant-slider-track {
background-color: ${props => props.theme.eCashBlue} !important;
}
.ant-descriptions-bordered .ant-descriptions-row {
background: ${props => props.theme.contrast};
}
.ant-modal-confirm-content, .ant-modal-confirm-title {
color: ${props => props.theme.contrast} !important;
}
.ant-form-item-explain {
div {
color: ${props => props.theme.forms.text};
}
}
.ant-input-prefix {
color: ${props => props.theme.eCashBlue};
}
.ant-spin-nested-loading>div>.ant-spin .ant-spin-dot {
top: 0 !important;
left: 0 !important;
right: 0 !important;
bottom: 0 !important;
margin: auto !important;
}
.ant-spin-nested-loading>div>.ant-spin {
position: fixed !important;
}
`;
const CustomApp = styled.div`
text-align: center;
font-family: 'Poppins', sans-serif;
background-color: ${props => props.theme.backgroundColor};
background-size: 100px 171px;
background-image: ${props => props.theme.backgroundImage};
background-attachment: fixed;
`;
const Footer = styled.div`
z-index: 2;
height: 80px;
border-top: 1px solid rgba(255, 255, 255, 0.5);
background-color: ${props => props.theme.footerBackground};
position: fixed;
bottom: 0;
width: 500px;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 50px;
@media (max-width: 768px) {
width: 100%;
padding: 0 20px;
}
`;
const NavWrapper = styled.div`
cursor: pointer;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 1.3rem;
margin-bottom: 5px;
`;
const NavIcon = styled.span`
position: relative;
background-color: ${props =>
props.clicked ? 'transparent' : props.theme.buttons.primary.color};
width: 2rem;
height: 2px;
display: inline-block;
transition: transform 300ms, top 300ms, background-color 300ms;
&::before,
&::after {
content: '';
background-color: ${props => props.theme.buttons.primary.color};
width: 2rem;
height: 2px;
display: inline-block;
position: absolute;
left: 0;
transition: transform 300ms, top 300ms, background-color 300ms;
}
&::before {
top: ${props => (props.clicked ? '0' : '-0.8rem')};
transform: ${props => (props.clicked ? 'rotate(135deg)' : 'rotate(0)')};
}
&::after {
top: ${props => (props.clicked ? '0' : '0.8rem')};
transform: ${props =>
props.clicked ? 'rotate(-135deg)' : 'rotate(0)'};
}
`;
const NavMenu = styled.div`
position: fixed;
float: right;
- margin-right:1px;
+ margin-right: 1px;
bottom: 5rem;
display: flex;
width: 8.23rem;
flex-direction: column;
border: ${props => (props.open ? '1px solid' : '0px solid')};
border-color: ${props =>
props.open ? props.theme.contrast : 'transparent'};
justify-content: center;
align-items: center;
@media (max-width: 768px) {
right: 0;
margin-right: 0;
}
overflow: hidden;
transition: ${props =>
props.open
? 'max-height 1000ms ease-in-out , border-color 800ms ease-in-out, border-width 800ms ease-in-out'
: 'max-height 300ms cubic-bezier(0, 1, 0, 1), border-color 600ms ease-in-out, border-width 800ms ease-in-out'};
max-height: ${props => (props.open ? '100rem' : '0')};
`;
const NavItem = styled.button`
display: flex;
justify-content: right;
align-items: center;
width: 100%;
white-space: nowrap;
height: 3rem;
background-color: ${props => props.theme.walletBackground};
border: none;
color: ${props => props.theme.contrast};
cursor: pointer;
gap: 1rem;
&:hover {
color: ${props => props.theme.navActive};
svg {
fill: ${props => props.theme.navActive};
}
}
svg {
fill: ${props => props.theme.contrast};
width: 26px;
height: auto;
}
`;
export const NavButton = styled.button`
:focus,
:active {
outline: none;
}
cursor: pointer;
padding: 0;
background: none;
border: none;
font-size: 10px;
svg {
fill: ${props => props.theme.contrast};
width: 26px;
height: auto;
}
${({ active, ...props }) =>
active &&
`
color: ${props.theme.navActive};
svg {
fill: ${props.theme.navActive};
}
`}
`;
export const WalletBody = styled.div`
display: flex;
align-items: center;
justify-content: center;
width: 100%;
min-height: 100vh;
`;
export const WalletCtn = styled.div`
position: relative;
width: 500px;
min-height: 100vh;
padding: 0 0 100px;
background: ${props => props.theme.walletBackground};
-webkit-box-shadow: 0px 0px 24px 1px ${props => props.theme.shadow};
-moz-box-shadow: 0px 0px 24px 1px ${props => props.theme.shadow};
box-shadow: 0px 0px 24px 1px ${props => props.theme.shadow};
@media (max-width: 768px) {
width: 100%;
-webkit-box-shadow: none;
-moz-box-shadow: none;
box-shadow: none;
}
`;
export const HeaderCtn = styled.div`
display: flex;
align-items: center;
justify-content: center;
width: 100%;
padding: 15px 0;
`;
export const CashTabLogo = styled.img`
width: 120px;
@media (max-width: 768px) {
width: 110px;
}
`;
// AbcLogo styled component not included in extension, replaced by open in new tab link
export const AbcLogo = styled.img`
width: 150px;
@media (max-width: 768px) {
width: 120px;
}
`;
// Easter egg styled component not used in extension/src/components/App.js
export const EasterEgg = styled.img`
position: fixed;
bottom: -195px;
margin: 0;
right: 10%;
transition-property: bottom;
transition-duration: 1.5s;
transition-timing-function: ease-out;
:hover {
bottom: 0;
}
@media screen and (max-width: 1250px) {
display: none;
}
`;
const App = () => {
const ContextValue = React.useContext(WalletContext);
const { wallet, loading } = ContextValue;
const [loadingUtxosAfterSend, setLoadingUtxosAfterSend] = useState(false);
const [navMenuClicked, setNavMenuClicked] = useState(false);
const handleNavMenuClick = () => setNavMenuClicked(!navMenuClicked);
// If wallet is unmigrated, do not show page until it has migrated
// An invalid wallet will be validated/populated after the next API call, ETA 10s
const validWallet = isValidStoredWallet(wallet);
const location = useLocation();
const history = useHistory();
const selectedKey =
location && location.pathname ? location.pathname.substr(1) : '';
// Easter egg boolean not used in extension/src/components/App.js
const hasTab = validWallet
? checkForTokenById(
wallet.state.tokens,
'50d8292c6255cda7afc6c8566fed3cf42a2794e9619740fe8f4c95431271410e',
)
: false;
return (
{/*Begin component not included in extension as desktop only*/}
{hasTab && (
)}
{/*End component not included in extension as desktop only*/}
(
)}
/>
{wallet ? (
) : null}
);
};
App.propTypes = {
match: PropTypes.string,
};
export default App;