diff --git a/web/cashtab/extension/public/manifest.json b/web/cashtab/extension/public/manifest.json index 36dcaf962..bb4bd489f 100644 --- a/web/cashtab/extension/public/manifest.json +++ b/web/cashtab/extension/public/manifest.json @@ -1,30 +1,30 @@ { "manifest_version": 2, "name": "Cashtab", "description": "A browser-integrated eCash wallet from Bitcoin ABC", - "version": "1.0.0", + "version": "1.0.1", "content_scripts": [ { "matches": ["file://*/*", "http://*/*", "https://*/*"], "js": ["contentscript.js"], "run_at": "document_idle", "all_frames": true } ], "background": { "scripts": ["background.js"], "persistent": false }, "browser_action": { "default_popup": "index.html", "default_title": "Cashtab" }, "icons": { "16": "ecash16.png", "48": "ecash48.png", "128": "ecash128.png", "192": "ecash192.png", "512": "ecash512.png" } } diff --git a/web/cashtab/extension/src/components/App.js b/web/cashtab/extension/src/components/App.js index 3fa42c537..f15e27ca6 100644 --- a/web/cashtab/extension/src/components/App.js +++ b/web/cashtab/extension/src/components/App.js @@ -1,288 +1,316 @@ -import React from 'react'; +import React, { useState } from 'react'; import 'antd/dist/antd.less'; +import { Spin } from 'antd'; +import { CashLoadingIcon } from '@components/Common/CustomIcons'; import '../index.css'; import styled, { ThemeProvider, createGlobalStyle } from 'styled-components'; import { theme } from '@assets/styles/theme'; import { FolderOpenFilled, CaretRightOutlined, SettingFilled, AppstoreAddOutlined, } from '@ant-design/icons'; import Wallet from '@components/Wallet/Wallet'; import Tokens from '@components/Tokens/Tokens'; import Send from '@components/Send/Send'; import SendToken from '@components/Send/SendToken'; import Configure from '@components/Configure/Configure'; import NotFound from '@components/NotFound'; import CashTab from '@assets/cashtab_xec.png'; -import PopOut from '@assets/popout.svg'; import './App.css'; import { WalletContext } from '@utils/context'; +import { isValidStoredWallet } from '@utils/cashMethods'; import WalletLabel from '@components/Common/WalletLabel.js'; 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` .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 { border-radius: 8px; background-color: ${props => props.theme.modals.buttons.background}; color: ${props => props.theme.wallet.text.secondary}; font-weight: bold; } .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 { color: ${props => props.theme.primary}; transition: color 0.3s; background-color: ${props => props.theme.modals.buttons.background}; } .selectedCurrencyOption { text-align: left; color: ${props => props.theme.wallet.text.secondary} !important; background-color: ${props => props.theme.contrast} !important; } .cashLoadingIcon { color: ${props => props.theme.primary} !important font-size: 48px !important; } .selectedCurrencyOption:hover { color: ${props => props.theme.contrast} !important; background-color: ${props => props.theme.primary} !important; } #addrSwitch { .ant-switch-checked { background-color: white !important; } } #addrSwitch.ant-switch-checked { background-image: ${props => props.theme.buttons.primary.backgroundImage} !important; } `; const CustomApp = styled.div` text-align: center; font-family: 'Gilroy', sans-serif; background-color: ${props => props.theme.app.background}; `; const Footer = styled.div` z-index: 2; background-color: ${props => props.theme.footer.background}; border-radius: 20px; position: fixed; bottom: 0; width: 500px; @media (max-width: 768px) { width: 100%; } border-top: 1px solid ${props => props.theme.wallet.borders.color}; `; -const OpenInTabBtn = styled.button` - background: none; - border: none; -`; -const ExtTabImg = styled.img` - max-width: 20px; -`; export const NavButton = styled.button` :focus, :active { outline: none; } cursor: pointer; padding: 24px 12px 12px 12px; margin: 0 28px; @media (max-width: 475px) { margin: 0 20px; } @media (max-width: 420px) { margin: 0 12px; } @media (max-width: 350px) { margin: 0 8px; } background-color: ${props => props.theme.footer.background}; border: none; font-size: 12px; font-weight: bold; .anticon { display: block; color: ${props => props.theme.footer.navIconInactive}; font-size: 24px; margin-bottom: 6px; } ${({ active, ...props }) => active && ` color: ${props.theme.primary}; .anticon { color: ${props.theme.primary}; } `} `; export const WalletBody = styled.div` display: flex; align-items: center; justify-content: center; width: 100%; min-height: 100vh; - background: ${props => props.theme.app.sidebars}; + background-image: ${props => props.theme.app.sidebars}; + background-attachment: fixed; `; + export const WalletCtn = styled.div` position: relative; width: 500px; background-color: ${props => props.theme.footerBackground}; min-height: 100vh; padding: 10px 30px 120px 30px; background: ${props => props.theme.wallet.background}; -webkit-box-shadow: 0px 0px 24px 1px ${props => props.theme.wallet.shadow}; -moz-box-shadow: 0px 0px 24px 1px ${props => props.theme.wallet.shadow}; box-shadow: 0px 0px 24px 1px ${props => props.theme.wallet.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: 20px 0 30px; margin-bottom: 20px; justify-content: space-between; border-bottom: 1px solid ${props => props.theme.wallet.borders.color}; a { color: ${props => props.theme.wallet.text.secondary}; :hover { color: ${props => props.theme.primary}; } } @media (max-width: 768px) { a { font-size: 12px; } padding: 10px 0 20px; } `; export const CashTabLogo = styled.img` width: 120px; @media (max-width: 768px) { width: 110px; } `; -export const AbcLogo = styled.img` - width: 150px; - @media (max-width: 768px) { - width: 120px; - } + +// 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 } = ContextValue; + const { wallet, loading } = ContextValue; + const [loadingUtxosAfterSend, setLoadingUtxosAfterSend] = useState(false); + // 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 ( - - - - - - openInTab()} - > - - - - - - - - - - - - - - - ( - + + + + + + {/*Begin extension-only components*/} + openInTab()} + > + + + {/*End extension-only components*/} + + + + + + + + + + + - )} - /> - - - - - - - - {wallet ? ( - + ) : null} + + + ); }; export default App; diff --git a/web/cashtab/src/components/App.js b/web/cashtab/src/components/App.js index 3232dedc8..3ce539366 100644 --- a/web/cashtab/src/components/App.js +++ b/web/cashtab/src/components/App.js @@ -1,326 +1,345 @@ import React, { useState } from 'react'; import 'antd/dist/antd.less'; import { Spin } from 'antd'; import { CashLoadingIcon } from '@components/Common/CustomIcons'; import '../index.css'; import styled, { ThemeProvider, createGlobalStyle } from 'styled-components'; import { theme } from '@assets/styles/theme'; import { FolderOpenFilled, CaretRightOutlined, SettingFilled, AppstoreAddOutlined, } from '@ant-design/icons'; import Wallet from '@components/Wallet/Wallet'; import Tokens from '@components/Tokens/Tokens'; import Send from '@components/Send/Send'; import SendToken from '@components/Send/SendToken'; import Configure from '@components/Configure/Configure'; import NotFound from '@components/NotFound'; import CashTab from '@assets/cashtab_xec.png'; -import TabCash from '@assets/tabcash.png'; -import ABC from '@assets/logo_topright.png'; import './App.css'; import { WalletContext } from '@utils/context'; -import { checkForTokenById } from '@utils/tokenMethods.js'; import { isValidStoredWallet } from '@utils/cashMethods'; import WalletLabel from '@components/Common/WalletLabel.js'; 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 ABC from '@assets/logo_topright.png'; +import { checkForTokenById } from '@utils/tokenMethods.js'; const GlobalStyle = createGlobalStyle` .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 { border-radius: 8px; background-color: ${props => props.theme.modals.buttons.background}; color: ${props => props.theme.wallet.text.secondary}; font-weight: bold; } .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 { color: ${props => props.theme.primary}; transition: color 0.3s; background-color: ${props => props.theme.modals.buttons.background}; } .selectedCurrencyOption { text-align: left; color: ${props => props.theme.wallet.text.secondary} !important; background-color: ${props => props.theme.contrast} !important; } .cashLoadingIcon { color: ${props => props.theme.primary} !important font-size: 48px !important; } .selectedCurrencyOption:hover { color: ${props => props.theme.contrast} !important; background-color: ${props => props.theme.primary} !important; } #addrSwitch { .ant-switch-checked { background-color: white !important; } } #addrSwitch.ant-switch-checked { background-image: ${props => props.theme.buttons.primary.backgroundImage} !important; } `; const CustomApp = styled.div` text-align: center; font-family: 'Gilroy', sans-serif; background-color: ${props => props.theme.app.background}; `; + const Footer = styled.div` z-index: 2; background-color: ${props => props.theme.footer.background}; border-radius: 20px; position: fixed; bottom: 0; width: 500px; @media (max-width: 768px) { width: 100%; } border-top: 1px solid ${props => props.theme.wallet.borders.color}; `; export const NavButton = styled.button` :focus, :active { outline: none; } cursor: pointer; padding: 24px 12px 12px 12px; margin: 0 28px; @media (max-width: 475px) { margin: 0 20px; } @media (max-width: 420px) { margin: 0 12px; } @media (max-width: 350px) { margin: 0 8px; } background-color: ${props => props.theme.footer.background}; border: none; font-size: 12px; font-weight: bold; .anticon { display: block; color: ${props => props.theme.footer.navIconInactive}; font-size: 24px; margin-bottom: 6px; } ${({ active, ...props }) => active && ` color: ${props.theme.primary}; .anticon { color: ${props.theme.primary}; } `} `; export const WalletBody = styled.div` display: flex; align-items: center; justify-content: center; width: 100%; min-height: 100vh; background-image: ${props => props.theme.app.sidebars}; background-attachment: fixed; `; export const WalletCtn = styled.div` position: relative; width: 500px; background-color: ${props => props.theme.footerBackground}; min-height: 100vh; padding: 10px 30px 120px 30px; background: ${props => props.theme.wallet.background}; -webkit-box-shadow: 0px 0px 24px 1px ${props => props.theme.wallet.shadow}; -moz-box-shadow: 0px 0px 24px 1px ${props => props.theme.wallet.shadow}; box-shadow: 0px 0px 24px 1px ${props => props.theme.wallet.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: 20px 0 30px; margin-bottom: 20px; justify-content: space-between; border-bottom: 1px solid ${props => props.theme.wallet.borders.color}; + a { + color: ${props => props.theme.wallet.text.secondary}; + + :hover { + color: ${props => props.theme.primary}; + } + } + @media (max-width: 768px) { a { font-size: 12px; } padding: 10px 0 20px; } `; +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; } `; -export const CashTabLogo = styled.img` - width: 120px; - @media (max-width: 768px) { - width: 110px; - } -`; -export const AbcLogo = styled.img` - width: 150px; - @media (max-width: 768px) { - width: 120px; - } -`; - const App = () => { const ContextValue = React.useContext(WalletContext); const { wallet, loading } = ContextValue; const [loadingUtxosAfterSend, setLoadingUtxosAfterSend] = useState(false); // 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; - const location = useLocation(); - const history = useHistory(); - const selectedKey = - location && location.pathname ? location.pathname.substr(1) : ''; return ( + {/*Begin component not included in extension as desktop only*/} {hasTab && ( )} + {/*End component not included in extension as desktop only*/} + {/*Begin component not included in extension as replaced by open in tab link*/} + {/*Begin component not included in extension as replaced by open in tab link*/} ( )} /> {wallet ? ( ) : null} ); }; export default App;