aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--packages/website/public/images/toshi_logo.jpgbin0 -> 4611 bytes
-rw-r--r--packages/website/ts/components/onboarding/install_wallet_onboarding_step.tsx47
-rw-r--r--packages/website/ts/components/onboarding/portal_onboarding_flow.tsx11
-rw-r--r--packages/website/ts/components/portal/portal.tsx73
-rw-r--r--packages/website/ts/components/relayer_index/relayer_grid_tile.tsx5
-rw-r--r--packages/website/ts/components/top_bar/top_bar.tsx43
-rw-r--r--packages/website/ts/components/top_bar/top_bar_menu_item.tsx1
-rw-r--r--packages/website/ts/components/ui/image.tsx4
-rw-r--r--packages/website/ts/components/wallet/body_overlay.tsx36
-rw-r--r--packages/website/ts/components/wallet/wallet.tsx4
-rw-r--r--packages/website/ts/style/media.ts2
-rw-r--r--packages/website/ts/types.ts10
-rw-r--r--packages/website/ts/utils/constants.ts2
-rw-r--r--packages/website/ts/utils/utils.ts58
14 files changed, 205 insertions, 91 deletions
diff --git a/packages/website/public/images/toshi_logo.jpg b/packages/website/public/images/toshi_logo.jpg
new file mode 100644
index 000000000..3cf451d24
--- /dev/null
+++ b/packages/website/public/images/toshi_logo.jpg
Binary files differ
diff --git a/packages/website/ts/components/onboarding/install_wallet_onboarding_step.tsx b/packages/website/ts/components/onboarding/install_wallet_onboarding_step.tsx
index a95c464af..d618c8318 100644
--- a/packages/website/ts/components/onboarding/install_wallet_onboarding_step.tsx
+++ b/packages/website/ts/components/onboarding/install_wallet_onboarding_step.tsx
@@ -1,19 +1,42 @@
import { colors } from '@0xproject/react-shared';
-import ActionAccountBalanceWallet from 'material-ui/svg-icons/action/account-balance-wallet';
import * as React from 'react';
import { Container } from 'ts/components/ui/container';
+import { Image } from 'ts/components/ui/image';
import { Text } from 'ts/components/ui/text';
+import { utils } from 'ts/utils/utils';
export interface InstallWalletOnboardingStepProps {}
-export const InstallWalletOnboardingStep: React.StatelessComponent<InstallWalletOnboardingStepProps> = () => (
- <div className="flex items-center flex-column">
- <Text>
- Before you begin, you need to connect to a wallet. This will be used across all 0x relayers and dApps.
- </Text>
- <Container marginTop="15px" marginBottom="15px">
- <ActionAccountBalanceWallet style={{ width: '50px', height: '50px' }} color={colors.orange} />
- </Container>
- <Text>Please refresh the page once you've done this to continue!</Text>
- </div>
-);
+export const InstallWalletOnboardingStep: React.StatelessComponent<InstallWalletOnboardingStepProps> = () => {
+ const [downloadLink, isOnMobile] = utils.getBestWalletDownloadLinkAndIsMobile();
+ const followupText = isOnMobile
+ ? `Please revisit this site in your mobile dApp browser to continue!`
+ : `Please refresh the page once you've done this to continue!`;
+ const downloadText = isOnMobile ? 'Get the Toshi Wallet' : 'Get the MetaMask extension';
+ return (
+ <div className="flex items-center flex-column">
+ <Text>First, you need to connect to a wallet. This will be used across all 0x relayers and dApps.</Text>
+ <Container className="flex items-center" marginTop="15px" marginBottom="15px">
+ <Image
+ height="50px"
+ width="50px"
+ borderRadius="22%"
+ src={isOnMobile ? '/images/toshi_logo.jpg' : '/images/metamask_icon.png'}
+ />
+ <Container marginLeft="10px">
+ <a href={downloadLink} target="_blank">
+ <Text
+ fontWeight={700}
+ fontSize="18px"
+ fontColor={colors.mediumBlue}
+ textDecorationLine="underline"
+ >
+ {downloadText}
+ </Text>
+ </a>
+ </Container>
+ </Container>
+ <Text>{followupText}</Text>
+ </div>
+ );
+};
diff --git a/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx b/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx
index b7c5a9f64..1c2c92fd1 100644
--- a/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx
+++ b/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx
@@ -57,13 +57,12 @@ class PlainPortalOnboardingFlow extends React.Component<PortalOnboardingFlowProp
this._unlisten();
}
public componentDidUpdate(prevProps: PortalOnboardingFlowProps): void {
- this._adjustStepIfShould();
- if (!prevProps.isRunning && this.props.isRunning) {
+ // Any one of steps 0-3 could be the starting step, and we only want to reset the scroll on the starting step.
+ if (this.props.isRunning && utils.isMobileWidth(this.props.screenWidth) && this.props.stepIndex < 3) {
// On mobile, make sure the wallet is completely visible.
- if (this.props.screenWidth === ScreenWidths.Sm) {
- document.querySelector('.wallet').scrollIntoView();
- }
+ document.querySelector('.wallet').scrollIntoView();
}
+ this._adjustStepIfShould();
if (!prevProps.blockchainIsLoaded && this.props.blockchainIsLoaded) {
this._autoStartOnboardingIfShould();
}
@@ -275,7 +274,7 @@ class PlainPortalOnboardingFlow extends React.Component<PortalOnboardingFlowProp
);
}
private _handleFinalStepContinueClick(): void {
- if (utils.isMobile(this.props.screenWidth)) {
+ if (utils.isMobileWidth(this.props.screenWidth)) {
window.scrollTo(0, 0);
this.props.history.push('/portal');
}
diff --git a/packages/website/ts/components/portal/portal.tsx b/packages/website/ts/components/portal/portal.tsx
index 8c3b5cfd7..d31de02bc 100644
--- a/packages/website/ts/components/portal/portal.tsx
+++ b/packages/website/ts/components/portal/portal.tsx
@@ -91,7 +91,7 @@ interface PortalState {
interface AccountManagementItem {
pathName: string;
- headerText: string;
+ headerText?: string;
render: () => React.ReactNode;
}
@@ -106,7 +106,8 @@ const TOP_BAR_HEIGHT = TopBar.heightForDisplayType(TopBarDisplayType.Expanded);
const LEFT_COLUMN_WIDTH = 346;
const MENU_PADDING_LEFT = 185;
const LARGE_LAYOUT_MAX_WIDTH = 1200;
-const LARGE_LAYOUT_MARGIN = 30;
+const LARGE_LAYOUT_SIDE_PADDING = 30;
+const SMALL_LAYOUT_SIDE_PADDING = 20;
export class Portal extends React.Component<PortalProps, PortalState> {
private _blockchain: Blockchain;
@@ -243,7 +244,9 @@ export class Portal extends React.Component<PortalProps, PortalState> {
position: 'fixed',
zIndex: zIndex.topBar,
}}
- maxWidth={LARGE_LAYOUT_MAX_WIDTH}
+ maxWidth={!this._isSmallScreen() ? LARGE_LAYOUT_MAX_WIDTH : undefined}
+ paddingLeft={!this._isSmallScreen() ? LARGE_LAYOUT_SIDE_PADDING : SMALL_LAYOUT_SIDE_PADDING}
+ paddingRight={!this._isSmallScreen() ? LARGE_LAYOUT_SIDE_PADDING : SMALL_LAYOUT_SIDE_PADDING}
/>
<Container marginTop={TOP_BAR_HEIGHT} minHeight="100vh" backgroundColor={colors.lightestGrey}>
<Switch>
@@ -318,13 +321,17 @@ export class Portal extends React.Component<PortalProps, PortalState> {
);
}
private _renderWallet(): React.ReactNode {
- const isMobile = utils.isMobile(this.props.screenWidth);
+ const isMobile = utils.isMobileWidth(this.props.screenWidth);
// We need room to scroll down for mobile onboarding
- const marginBottom = isMobile ? '200px' : '15px';
+ const marginBottom = isMobile ? '250px' : '15px';
return (
<div>
<Container className="flex flex-column items-center">
- {isMobile && <Container marginBottom="20px">{this._renderStartOnboarding()}</Container>}
+ {isMobile && (
+ <Container marginTop="20px" marginBottom="20px">
+ {this._renderStartOnboarding()}
+ </Container>
+ )}
<Container marginBottom={marginBottom} width="100%">
<Wallet
style={
@@ -364,7 +371,7 @@ export class Portal extends React.Component<PortalProps, PortalState> {
);
}
private _renderStartOnboarding(): React.ReactNode {
- const isMobile = utils.isMobile(this.props.screenWidth);
+ const isMobile = utils.isMobileWidth(this.props.screenWidth);
const shouldStartOnboarding = !isMobile || this.props.location.pathname === `${WebsitePaths.Portal}/account`;
const startOnboarding = (
<Container className="flex items-center center">
@@ -402,7 +409,7 @@ export class Portal extends React.Component<PortalProps, PortalState> {
},
{
pathName: `${WebsitePaths.Portal}/account`,
- headerText: 'Your Account',
+ headerText: this._isSmallScreen() ? undefined : 'Your Account',
render: this._isSmallScreen() ? this._renderWallet.bind(this) : this._renderTokenBalances.bind(this),
},
{
@@ -445,7 +452,7 @@ export class Portal extends React.Component<PortalProps, PortalState> {
private _renderAccountManagementItem(item: AccountManagementItem): React.ReactNode {
return (
<Section
- header={<TextHeader labelText={item.headerText} />}
+ header={!_.isUndefined(item.headerText) && <TextHeader labelText={item.headerText} />}
body={<Loading isLoading={!this.props.blockchainIsLoaded} content={item.render()} />}
/>
);
@@ -527,15 +534,21 @@ export class Portal extends React.Component<PortalProps, PortalState> {
);
}
private _renderRelayerIndexSection(): React.ReactNode {
- return <Section header={<TextHeader labelText="0x Relayers" />} body={this._renderRelayerIndex()} />;
- }
- private _renderRelayerIndex(): React.ReactNode {
- const isMobile = utils.isMobile(this.props.screenWidth);
+ const isMobile = utils.isMobileWidth(this.props.screenWidth);
return (
- <Container className="flex flex-column items-center">
- {isMobile && <Container marginBottom="20px">{this._renderStartOnboarding()}</Container>}
- <RelayerIndex networkId={this.props.networkId} screenWidth={this.props.screenWidth} />
- </Container>
+ <Section
+ header={!isMobile && <TextHeader labelText="0x Relayers" />}
+ body={
+ <Container className="flex flex-column items-center">
+ {isMobile && (
+ <Container marginTop="20px" marginBottom="20px">
+ {this._renderStartOnboarding()}
+ </Container>
+ )}
+ <RelayerIndex networkId={this.props.networkId} screenWidth={this.props.screenWidth} />
+ </Container>
+ }
+ />
);
}
private _renderNotFoundMessage(): React.ReactNode {
@@ -685,19 +698,19 @@ interface LargeLayoutProps {
}
const LargeLayout = (props: LargeLayoutProps) => {
return (
- <Container className="mx-auto flex flex-center" maxWidth={LARGE_LAYOUT_MAX_WIDTH}>
+ <Container
+ className="mx-auto flex flex-center"
+ maxWidth={LARGE_LAYOUT_MAX_WIDTH}
+ paddingLeft={LARGE_LAYOUT_SIDE_PADDING}
+ paddingRight={LARGE_LAYOUT_SIDE_PADDING}
+ >
<div className="flex-last">
- <Container
- width={LEFT_COLUMN_WIDTH}
- position="fixed"
- zIndex={zIndex.aboveTopBar}
- marginLeft={LARGE_LAYOUT_MARGIN}
- >
+ <Container width={LEFT_COLUMN_WIDTH} position="fixed" zIndex={zIndex.aboveTopBar}>
{props.left}
</Container>
</div>
- <Container className="flex-auto" marginLeft={LEFT_COLUMN_WIDTH + LARGE_LAYOUT_MARGIN}>
- <Container className="flex-auto" marginLeft={LARGE_LAYOUT_MARGIN} marginRight={LARGE_LAYOUT_MARGIN}>
+ <Container className="flex-auto" marginLeft={LEFT_COLUMN_WIDTH}>
+ <Container className="flex-auto" marginLeft={LARGE_LAYOUT_SIDE_PADDING}>
{props.right}
</Container>
</Container>
@@ -711,7 +724,13 @@ interface SmallLayoutProps {
const SmallLayout = (props: SmallLayoutProps) => {
return (
<div className="flex flex-center">
- <div className="flex-auto px3">{props.content}</div>
+ <Container
+ className="flex-auto"
+ paddingLeft={SMALL_LAYOUT_SIDE_PADDING}
+ paddingRight={SMALL_LAYOUT_SIDE_PADDING}
+ >
+ {props.content}
+ </Container>
</div>
);
}; // tslint:disable:max-file-line-count
diff --git a/packages/website/ts/components/relayer_index/relayer_grid_tile.tsx b/packages/website/ts/components/relayer_index/relayer_grid_tile.tsx
index 02bc1b014..431cf145b 100644
--- a/packages/website/ts/components/relayer_index/relayer_grid_tile.tsx
+++ b/packages/website/ts/components/relayer_index/relayer_grid_tile.tsx
@@ -108,12 +108,13 @@ export const RelayerGridTile: React.StatelessComponent<RelayerGridTileProps> = (
const GridTile = styled(PlainGridTile)`
cursor: pointer;
- transition: transform 0.2s ease;
&:hover {
+ transition: transform 0.2s ease;
transform: translate(0px, -3px);
}
${media.small`
- transform: none;
+ transform: none !important;
+ transition: none !important;
`};
`;
diff --git a/packages/website/ts/components/top_bar/top_bar.tsx b/packages/website/ts/components/top_bar/top_bar.tsx
index 778536663..dd3de7950 100644
--- a/packages/website/ts/components/top_bar/top_bar.tsx
+++ b/packages/website/ts/components/top_bar/top_bar.tsx
@@ -11,6 +11,7 @@ import { LegacyPortalMenu } from 'ts/components/legacy_portal/legacy_portal_menu
import { DrawerMenu } from 'ts/components/portal/drawer_menu';
import { ProviderDisplay } from 'ts/components/top_bar/provider_display';
import { TopBarMenuItem } from 'ts/components/top_bar/top_bar_menu_item';
+import { Container } from 'ts/components/ui/container';
import { DropDown } from 'ts/components/ui/drop_down';
import { Dispatcher } from 'ts/redux/dispatcher';
import { Deco, Key, ProviderType, WebsiteLegacyPaths, WebsitePaths } from 'ts/types';
@@ -45,6 +46,8 @@ export interface TopBarProps {
onVersionSelected?: (semver: string) => void;
sidebarHeader?: React.ReactNode;
maxWidth?: number;
+ paddingLeft?: number;
+ paddingRight?: number;
}
interface TopBarState {
@@ -67,13 +70,12 @@ const styles: Styles = {
color: colors.darkestGrey,
paddingTop: 6,
paddingBottom: 6,
- marginTop: 17,
cursor: 'pointer',
fontWeight: 400,
},
};
-const DEFAULT_HEIGHT = 59;
+const DEFAULT_HEIGHT = 68;
const EXPANDED_HEIGHT = 75;
export class TopBar extends React.Component<TopBarProps, TopBarState> {
@@ -81,6 +83,8 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> {
displayType: TopBarDisplayType.Default,
style: {},
isNightVersion: false,
+ paddingLeft: 20,
+ paddingRight: 20,
};
public static heightForDisplayType(displayType: TopBarDisplayType): number {
const result = displayType === TopBarDisplayType.Expanded ? EXPANDED_HEIGHT : DEFAULT_HEIGHT;
@@ -102,7 +106,9 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> {
public render(): React.ReactNode {
const isNightVersion = this.props.isNightVersion;
const isExpandedDisplayType = this.props.displayType === TopBarDisplayType.Expanded;
- const parentClassNames = `flex mx-auto ${isExpandedDisplayType ? 'pl3 py1' : 'max-width-4'}`;
+ const parentClassNames = !isExpandedDisplayType
+ ? 'flex mx-auto items-center max-width-4'
+ : 'flex mx-auto items-center';
const height = isExpandedDisplayType ? EXPANDED_HEIGHT : DEFAULT_HEIGHT;
const developerSectionMenuItems = [
<Link key="subMenuItem-zeroEx" to={WebsitePaths.ZeroExJs} className="text-decoration-none">
@@ -197,7 +203,6 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> {
fontSize: 25,
color: isNightVersion ? 'white' : 'black',
cursor: 'pointer',
- paddingTop: 16,
};
const activeNode = (
<div className="flex relative" style={{ color: menuIconStyle.color }}>
@@ -211,15 +216,21 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> {
// TODO : Remove this once we ship portal v2
const shouldShowPortalV2Drawer = this._isViewingPortal() && utils.shouldShowPortalV2();
return (
- <div style={{ ...styles.topBar, ...bottomBorderStyle, ...this.props.style, ...{ height } }} className="pb1">
- <div className={parentClassNames} style={{ maxWidth: this.props.maxWidth }}>
- <div className="col col-2 sm-pl1 md-pl2 lg-pl0" style={{ paddingTop: 15 }}>
- <Link to={`${WebsitePaths.Home}`} className="text-decoration-none">
- <img src={logoUrl} height="30" />
- </Link>
- </div>
- <div className={`col col-${isExpandedDisplayType ? '8' : '9'} lg-hide md-hide`} />
- <div className={`col col-${isExpandedDisplayType ? '6' : '5'} sm-hide xs-hide`} />
+ <div
+ style={{ ...styles.topBar, ...bottomBorderStyle, ...this.props.style, ...{ height } }}
+ className="pb1 flex items-center"
+ >
+ <Container
+ className={parentClassNames}
+ width="100%"
+ maxWidth={this.props.maxWidth}
+ paddingLeft={this.props.paddingLeft}
+ paddingRight={this.props.paddingRight}
+ >
+ <Link to={`${WebsitePaths.Home}`} className="text-decoration-none">
+ <img src={logoUrl} height="30" />
+ </Link>
+ <div className="flex-auto" />
{!this._isViewingPortal() && (
<div className={menuClasses}>
<div className="flex justify-between">
@@ -264,7 +275,7 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> {
</div>
)}
{this._isViewingPortal() && (
- <div className="sm-hide xs-hide col col-5" style={{ paddingTop: 8, marginRight: 36 }}>
+ <div className="sm-hide xs-hide">
<ProviderDisplay
dispatcher={this.props.dispatcher}
userAddress={this.props.userAddress}
@@ -277,12 +288,12 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> {
/>
</div>
)}
- <div className={`col ${isExpandedDisplayType ? 'col-2 pl2' : 'col-1'} md-hide lg-hide`}>
+ <div className={'md-hide lg-hide'}>
<div style={menuIconStyle}>
<i className="zmdi zmdi-menu" onClick={this._onMenuButtonClick.bind(this)} />
</div>
</div>
- </div>
+ </Container>
{shouldShowPortalV2Drawer ? this._renderPortalV2Drawer() : this._renderDrawer()}
</div>
);
diff --git a/packages/website/ts/components/top_bar/top_bar_menu_item.tsx b/packages/website/ts/components/top_bar/top_bar_menu_item.tsx
index 2e4254cfa..e96d27c3f 100644
--- a/packages/website/ts/components/top_bar/top_bar_menu_item.tsx
+++ b/packages/website/ts/components/top_bar/top_bar_menu_item.tsx
@@ -31,7 +31,6 @@ export class TopBarMenuItem extends React.Component<TopBarMenuItemProps, TopBarM
? {
borderRadius: 4,
border: `1px solid ${this.props.isNightVersion ? colors.grey : colors.greyishPink}`,
- marginTop: 15,
paddingLeft: 9,
paddingRight: 9,
minWidth: 77,
diff --git a/packages/website/ts/components/ui/image.tsx b/packages/website/ts/components/ui/image.tsx
index 369dc8b7e..c4ff93531 100644
--- a/packages/website/ts/components/ui/image.tsx
+++ b/packages/website/ts/components/ui/image.tsx
@@ -6,6 +6,7 @@ export interface ImageProps {
src?: string;
fallbackSrc?: string;
height?: string | number;
+ borderRadius?: string;
width?: string | number;
}
interface ImageState {
@@ -26,6 +27,9 @@ export class Image extends React.Component<ImageProps, ImageState> {
className={this.props.className}
onError={this._onError.bind(this)}
src={src}
+ style={{
+ borderRadius: this.props.borderRadius,
+ }}
height={this.props.height}
width={this.props.width}
/>
diff --git a/packages/website/ts/components/wallet/body_overlay.tsx b/packages/website/ts/components/wallet/body_overlay.tsx
index 5ced704f9..26359d0d2 100644
--- a/packages/website/ts/components/wallet/body_overlay.tsx
+++ b/packages/website/ts/components/wallet/body_overlay.tsx
@@ -9,11 +9,11 @@ import { Text } from 'ts/components/ui/text';
import { Dispatcher } from 'ts/redux/dispatcher';
import { colors } from 'ts/style/colors';
import { styled } from 'ts/style/theme';
-import { AccountState, BrowserType, ProviderType } from 'ts/types';
-import { constants } from 'ts/utils/constants';
+import { AccountState, ProviderType } from 'ts/types';
import { utils } from 'ts/utils/utils';
const METAMASK_IMG_SRC = '/images/metamask_icon.png';
+const TOSHI_IMG_SRC = '/images/toshi_logo.jpg';
export interface BodyOverlayProps {
dispatcher: Dispatcher;
@@ -92,8 +92,10 @@ interface DisconnectedOverlayProps {
const DisconnectedOverlay = (props: DisconnectedOverlayProps) => {
return (
<div className="flex flex-column items-center">
- <GetMetaMask />
- <UseDifferentWallet fontColor={colors.mediumBlue} onClick={props.onUseDifferentWalletClicked} />
+ <GetWalletCallToAction />
+ {!utils.isMobileOperatingSystem() && (
+ <UseDifferentWallet fontColor={colors.mediumBlue} onClick={props.onUseDifferentWalletClicked} />
+ )}
</div>
);
};
@@ -112,32 +114,20 @@ const UseDifferentWallet = (props: UseDifferentWallet) => {
);
};
-const GetMetaMask = () => {
- const browserType = utils.getBrowserType();
- let extensionLink;
- switch (browserType) {
- case BrowserType.Chrome:
- extensionLink = constants.URL_METAMASK_CHROME_STORE;
- break;
- case BrowserType.Firefox:
- extensionLink = constants.URL_METAMASK_FIREFOX_STORE;
- break;
- case BrowserType.Opera:
- extensionLink = constants.URL_METAMASK_OPERA_STORE;
- break;
- default:
- extensionLink = constants.URL_METAMASK_HOMEPAGE;
- }
+const GetWalletCallToAction = () => {
+ const [downloadLink, isOnMobile] = utils.getBestWalletDownloadLinkAndIsMobile();
+ const imageUrl = isOnMobile ? TOSHI_IMG_SRC : METAMASK_IMG_SRC;
+ const text = isOnMobile ? 'Get Toshi Wallet' : 'Get MetaMask Wallet';
return (
- <a href={extensionLink} target="_blank" style={{ textDecoration: 'none' }}>
+ <a href={downloadLink} target="_blank" style={{ textDecoration: 'none' }}>
<Island
className="flex items-center py1 px2"
style={{ height: 28, borderRadius: 28, backgroundColor: colors.mediumBlue }}
>
- <Image src={METAMASK_IMG_SRC} width="28px" />
+ <Image src={imageUrl} width="28px" borderRadius="22%" />
<Container marginLeft="8px" marginRight="12px">
<Text fontColor={colors.white} fontSize="16px" fontWeight={500}>
- Get MetaMask Wallet
+ {text}
</Text>
</Container>
</Island>
diff --git a/packages/website/ts/components/wallet/wallet.tsx b/packages/website/ts/components/wallet/wallet.tsx
index 1e0b9ec48..1d7be5dbc 100644
--- a/packages/website/ts/components/wallet/wallet.tsx
+++ b/packages/website/ts/components/wallet/wallet.tsx
@@ -224,10 +224,10 @@ export class Wallet extends React.Component<WalletProps, WalletState> {
popoverContent={
<SimpleMenu minWidth="150px">
<CopyAddressSimpleMenuItem userAddress={this.props.userAddress} />
- <DifferentWalletSimpleMenuItem onClick={this.props.onToggleLedgerDialog} />
+ {!isMobile && <DifferentWalletSimpleMenuItem onClick={this.props.onToggleLedgerDialog} />}
<SimpleMenuItem displayText="Add Tokens..." onClick={this.props.onAddToken} />
<SimpleMenuItem displayText="Remove Tokens..." onClick={this.props.onRemoveToken} />
- <GoToAccountManagementSimpleMenuItem />
+ {!isMobile && <GoToAccountManagementSimpleMenuItem />}
</SimpleMenu>
}
anchorOrigin={{ horizontal: 'right', vertical: 'bottom' }}
diff --git a/packages/website/ts/style/media.ts b/packages/website/ts/style/media.ts
index 3c992eb9f..870d9a277 100644
--- a/packages/website/ts/style/media.ts
+++ b/packages/website/ts/style/media.ts
@@ -2,7 +2,7 @@ import { css } from 'ts/style/theme';
import { ScreenWidths } from 'ts/types';
const generateMediaWrapper = (screenWidth: ScreenWidths) => (...args: any[]) => css`
- @media (max-width: ${screenWidth}) {
+ @media (max-width: ${screenWidth}em) {
${css.apply(css, args)};
}
`;
diff --git a/packages/website/ts/types.ts b/packages/website/ts/types.ts
index d9b2ef618..93d029325 100644
--- a/packages/website/ts/types.ts
+++ b/packages/website/ts/types.ts
@@ -569,6 +569,16 @@ export enum BrowserType {
Other = 'Other',
}
+export enum OperatingSystemType {
+ Android = 'Android',
+ iOS = 'iOS',
+ Mac = 'Mac',
+ Windows = 'Windows',
+ WindowsPhone = 'WindowsPhone',
+ Linux = 'Linux',
+ Other = 'Other',
+}
+
export enum AccountState {
Disconnected = 'Disconnected',
Ready = 'Ready',
diff --git a/packages/website/ts/utils/constants.ts b/packages/website/ts/utils/constants.ts
index 0c4b88780..4b3443d21 100644
--- a/packages/website/ts/utils/constants.ts
+++ b/packages/website/ts/utils/constants.ts
@@ -74,6 +74,8 @@ export const constants = {
URL_GITHUB_WIKI: 'https://github.com/0xProject/wiki',
URL_METAMASK_CHROME_STORE: 'https://chrome.google.com/webstore/detail/metamask/nkbihfbeogaeaoehlefnkodbefgpgknn',
URL_METAMASK_FIREFOX_STORE: 'https://addons.mozilla.org/en-US/firefox/addon/ether-metamask/',
+ URL_TOSHI_IOS_APP_STORE: 'https://itunes.apple.com/us/app/toshi-ethereum-wallet/id1278383455?mt=8',
+ URL_TOSHI_ANDROID_APP_STORE: 'https://play.google.com/store/apps/details?id=org.toshi&hl=en_US',
URL_METAMASK_HOMEPAGE: 'https://metamask.io/',
URL_METAMASK_OPERA_STORE: 'https://addons.opera.com/en/extensions/details/metamask/',
URL_MIST_DOWNLOAD: 'https://github.com/ethereum/mist/releases',
diff --git a/packages/website/ts/utils/utils.ts b/packages/website/ts/utils/utils.ts
index 2cda41545..623819fc9 100644
--- a/packages/website/ts/utils/utils.ts
+++ b/packages/website/ts/utils/utils.ts
@@ -15,6 +15,7 @@ import {
BlockchainCallErrs,
BrowserType,
Environments,
+ OperatingSystemType,
Order,
Providers,
ProviderType,
@@ -401,9 +402,12 @@ export const utils = {
openUrl(url: string): void {
window.open(url, '_blank');
},
- isMobile(screenWidth: ScreenWidths): boolean {
+ isMobileWidth(screenWidth: ScreenWidths): boolean {
return screenWidth === ScreenWidths.Sm;
},
+ isMobileOperatingSystem(): boolean {
+ return bowser.mobile;
+ },
getBrowserType(): BrowserType {
if (bowser.chrome) {
return BrowserType.Chrome;
@@ -415,7 +419,59 @@ export const utils = {
return BrowserType.Other;
}
},
+ getOperatingSystem(): OperatingSystemType {
+ if (bowser.android) {
+ return OperatingSystemType.Android;
+ } else if (bowser.ios) {
+ return OperatingSystemType.iOS;
+ } else if (bowser.mac) {
+ return OperatingSystemType.Mac;
+ } else if (bowser.windows) {
+ return OperatingSystemType.Windows;
+ } else if (bowser.windowsphone) {
+ return OperatingSystemType.WindowsPhone;
+ } else if (bowser.linux) {
+ return OperatingSystemType.Linux;
+ } else {
+ return OperatingSystemType.Other;
+ }
+ },
isTokenTracked(token: Token): boolean {
return !_.isUndefined(token.trackedTimestamp);
},
+ // Returns a [downloadLink, isOnMobile] tuple.
+ getBestWalletDownloadLinkAndIsMobile(): [string, boolean] {
+ const browserType = utils.getBrowserType();
+ const isOnMobile = utils.isMobileOperatingSystem();
+ const operatingSystem = utils.getOperatingSystem();
+ let downloadLink;
+ if (isOnMobile) {
+ switch (operatingSystem) {
+ case OperatingSystemType.Android:
+ downloadLink = constants.URL_TOSHI_ANDROID_APP_STORE;
+ break;
+ case OperatingSystemType.iOS:
+ downloadLink = constants.URL_TOSHI_IOS_APP_STORE;
+ break;
+ default:
+ // Toshi is only supported on these mobile OSes - just default to iOS
+ downloadLink = constants.URL_TOSHI_IOS_APP_STORE;
+ }
+ } else {
+ switch (browserType) {
+ case BrowserType.Chrome:
+ downloadLink = constants.URL_METAMASK_CHROME_STORE;
+ break;
+ case BrowserType.Firefox:
+ downloadLink = constants.URL_METAMASK_FIREFOX_STORE;
+ break;
+ case BrowserType.Opera:
+ downloadLink = constants.URL_METAMASK_OPERA_STORE;
+ break;
+ default:
+ downloadLink = constants.URL_METAMASK_HOMEPAGE;
+ }
+ }
+ return [downloadLink, isOnMobile];
+ },
};