From e52d0a351265616d58d9126404db7a359a6648be Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Mon, 25 Jun 2018 16:14:04 -0700 Subject: Change metamask install link based on browser --- .../components/wallet/wallet_disconnected_item.tsx | 47 +++++++++++++++------- packages/website/ts/types.ts | 7 ++++ packages/website/ts/utils/constants.ts | 3 ++ packages/website/ts/utils/utils.ts | 13 ++++++ 4 files changed, 56 insertions(+), 14 deletions(-) (limited to 'packages/website/ts') diff --git a/packages/website/ts/components/wallet/wallet_disconnected_item.tsx b/packages/website/ts/components/wallet/wallet_disconnected_item.tsx index 1015dce29..024b28544 100644 --- a/packages/website/ts/components/wallet/wallet_disconnected_item.tsx +++ b/packages/website/ts/components/wallet/wallet_disconnected_item.tsx @@ -3,7 +3,7 @@ import FlatButton from 'material-ui/FlatButton'; import * as React from 'react'; import { colors } from 'ts/style/colors'; -import { ProviderType } from 'ts/types'; +import { BrowserType, ProviderType } from 'ts/types'; import { constants } from 'ts/utils/constants'; import { utils } from 'ts/utils/utils'; @@ -66,16 +66,35 @@ interface ProviderButtonProps { isExternallyInjectedProvider: boolean; } -const ProviderButton: React.StatelessComponent = (props: ProviderButtonProps) => ( - } - style={props.isExternallyInjectedProvider ? styles.button : { ...styles.button, ...styles.hrefAdjustment }} - href={props.isExternallyInjectedProvider ? undefined : constants.URL_METAMASK_CHROME_STORE} - target={props.isExternallyInjectedProvider ? undefined : '_blank'} - disabled={props.isExternallyInjectedProvider} - /> -); +const ProviderButton: React.StatelessComponent = (props: ProviderButtonProps) => { + const browserType = utils.getBrowserType(); + let extensionLink; + if (!props.isExternallyInjectedProvider) { + 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; + } + } + return ( + } + style={props.isExternallyInjectedProvider ? styles.button : { ...styles.button, ...styles.hrefAdjustment }} + href={extensionLink} + target={props.isExternallyInjectedProvider ? undefined : '_blank'} + disabled={props.isExternallyInjectedProvider} + /> + ); +}; diff --git a/packages/website/ts/types.ts b/packages/website/ts/types.ts index d00154652..8a88c31b2 100644 --- a/packages/website/ts/types.ts +++ b/packages/website/ts/types.ts @@ -546,4 +546,11 @@ export interface WebsiteBackendJobInfo { office: string; url: string; } + +export enum BrowserType { + Chrome = 'Chrome', + Firefox = 'Firefox', + Opera = 'Opera', + Other = 'Other', +} // tslint:disable:max-file-line-count diff --git a/packages/website/ts/utils/constants.ts b/packages/website/ts/utils/constants.ts index 25670ef27..a3f8eacb0 100644 --- a/packages/website/ts/utils/constants.ts +++ b/packages/website/ts/utils/constants.ts @@ -70,6 +70,9 @@ export const constants = { URL_GITHUB_ORG: 'https://github.com/0xProject', 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_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', URL_PARITY_CHROME_STORE: 'https://chrome.google.com/webstore/detail/parity-ethereum-integrati/himekenlppkgeaoeddcliojfddemadig', diff --git a/packages/website/ts/utils/utils.ts b/packages/website/ts/utils/utils.ts index 0cb965f05..ff06d923d 100644 --- a/packages/website/ts/utils/utils.ts +++ b/packages/website/ts/utils/utils.ts @@ -4,11 +4,13 @@ import { constants as sharedConstants, Networks } from '@0xproject/react-shared' import { ECSignature, Provider } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; +import * as bowser from 'bowser'; import deepEqual = require('deep-equal'); import * as _ from 'lodash'; import * as moment from 'moment'; import { BlockchainCallErrs, + BrowserType, Environments, Order, Providers, @@ -368,4 +370,15 @@ export const utils = { isMobile(screenWidth: ScreenWidths): boolean { return screenWidth === ScreenWidths.Sm; }, + getBrowserType(): BrowserType { + if (bowser.chrome) { + return BrowserType.Chrome; + } else if (bowser.firefox) { + return BrowserType.Firefox; + } else if (bowser.opera) { + return BrowserType.Opera; + } else { + return BrowserType.Other; + } + }, }; -- cgit v1.2.3 From 3a808fe7fde04585b8a9c728c6266ab5f0f20c33 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Tue, 26 Jun 2018 10:40:51 -0700 Subject: Update relayer grid fallback icon --- packages/website/ts/components/relayer_index/relayer_grid_tile.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'packages/website/ts') 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 18b069ae2..b26bf512b 100644 --- a/packages/website/ts/components/relayer_index/relayer_grid_tile.tsx +++ b/packages/website/ts/components/relayer_index/relayer_grid_tile.tsx @@ -54,7 +54,7 @@ const styles: Styles = { }, }; -const FALLBACK_IMG_SRC = '/images/landing/hero_chip_image.png'; +const FALLBACK_IMG_SRC = '/images/relayer_fallback.png'; const FALLBACK_PRIMARY_COLOR = colors.grey200; const NO_CONTENT_MESSAGE = '--'; const RELAYER_ICON_HEIGHT = '110px'; -- cgit v1.2.3 From 744e6e60c51b2bfd081920b58a73e566113fee0e Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Tue, 26 Jun 2018 11:17:00 -0700 Subject: Polish asset picker layout --- packages/website/ts/components/generate_order/asset_picker.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'packages/website/ts') diff --git a/packages/website/ts/components/generate_order/asset_picker.tsx b/packages/website/ts/components/generate_order/asset_picker.tsx index b0dcf5678..0f569e1ad 100644 --- a/packages/website/ts/components/generate_order/asset_picker.tsx +++ b/packages/website/ts/components/generate_order/asset_picker.tsx @@ -117,7 +117,7 @@ export class AssetPicker extends React.Component -
{token.name}
+
{token.symbol}
); }); @@ -181,7 +181,7 @@ export class AssetPicker extends React.Component Date: Fri, 22 Jun 2018 00:37:40 -0700 Subject: Sort wallet tokens by timestamp added and scroll to newly added token --- .../ts/components/generate_order/asset_picker.tsx | 1 + packages/website/ts/components/portal/portal.tsx | 10 ++-------- packages/website/ts/components/token_balances.tsx | 2 +- packages/website/ts/components/wallet/wallet.tsx | 18 ++++++++++++++++-- packages/website/ts/types.ts | 1 + packages/website/ts/utils/utils.ts | 5 +++++ 6 files changed, 26 insertions(+), 11 deletions(-) (limited to 'packages/website/ts') diff --git a/packages/website/ts/components/generate_order/asset_picker.tsx b/packages/website/ts/components/generate_order/asset_picker.tsx index 0f569e1ad..e78324346 100644 --- a/packages/website/ts/components/generate_order/asset_picker.tsx +++ b/packages/website/ts/components/generate_order/asset_picker.tsx @@ -260,6 +260,7 @@ export class AssetPicker extends React.Component { this._fetchBalancesAndAllowancesAsync(trackedTokenAddresses); } - const nextTrackedTokens = this._getTrackedTokens(nextProps.tokenByAddress); + const nextTrackedTokens = utils.getTrackedTokens(nextProps.tokenByAddress); const trackedTokens = this._getCurrentTrackedTokens(); if (!_.isEqual(nextTrackedTokens, trackedTokens)) { @@ -610,13 +610,7 @@ export class Portal extends React.Component { } private _getCurrentTrackedTokens(): Token[] { - return this._getTrackedTokens(this.props.tokenByAddress); - } - - private _getTrackedTokens(tokenByAddress: TokenByAddress): Token[] { - const allTokens = _.values(tokenByAddress); - const trackedTokens = _.filter(allTokens, t => t.isTracked); - return trackedTokens; + return utils.getTrackedTokens(this.props.tokenByAddress); } private _getInitialTrackedTokenStateByAddress(trackedTokens: Token[]): TokenStateByAddress { diff --git a/packages/website/ts/components/token_balances.tsx b/packages/website/ts/components/token_balances.tsx index 7af80745c..fc802a7b3 100644 --- a/packages/website/ts/components/token_balances.tsx +++ b/packages/website/ts/components/token_balances.tsx @@ -308,7 +308,7 @@ export class TokenBalances extends React.Component t.symbol !== ETHER_TOKEN_SYMBOL) .thenBy((t: Token) => t.symbol !== ZRX_TOKEN_SYMBOL) - .thenBy('address'), + .thenBy('trackedTimestamp'), ); const tableRows = _.map( trackedTokensStartingWithEtherToken, diff --git a/packages/website/ts/components/wallet/wallet.tsx b/packages/website/ts/components/wallet/wallet.tsx index dc48d6619..5c90aa3da 100644 --- a/packages/website/ts/components/wallet/wallet.tsx +++ b/packages/website/ts/components/wallet/wallet.tsx @@ -156,6 +156,20 @@ export class Wallet extends React.Component { isHoveringSidebar: false, }; } + public componentDidUpdate(prevProps: WalletProps): void { + const currentTrackedTokens = this.props.trackedTokens; + const differentTrackedTokens = _.difference(currentTrackedTokens, prevProps.trackedTokens); + const firstDifferentTrackedToken = _.head(differentTrackedTokens); + // check if there is only one different token, and if that token is a member of the current tracked tokens + // this means that the token was added, not removed + if ( + !_.isUndefined(firstDifferentTrackedToken) && + _.size(differentTrackedTokens) === 1 && + currentTrackedTokens.includes(firstDifferentTrackedToken) + ) { + document.getElementById(firstDifferentTrackedToken.address).scrollIntoView(); + } + } public render(): React.ReactNode { const isBlockchainLoaded = this.props.blockchainIsLoaded && this.props.blockchainErr === BlockchainErrs.NoError; return ( @@ -318,7 +332,7 @@ export class Wallet extends React.Component { const trackedTokensStartingWithEtherToken = trackedTokens.sort( firstBy((t: Token) => t.symbol !== constants.ETHER_TOKEN_SYMBOL) .thenBy((t: Token) => t.symbol !== constants.ZRX_TOKEN_SYMBOL) - .thenBy('address'), + .thenBy('trackedTimestamp'), ); return _.map(trackedTokensStartingWithEtherToken, this._renderTokenRow.bind(this)); } @@ -383,7 +397,7 @@ export class Wallet extends React.Component { const style = { ...styles.tokenItem, ...additionalStyle }; const etherToken = this._getEthToken(); return ( -
+
t.isTracked); + return trackedTokens; + }, getFormattedAmountFromToken(token: Token, tokenState: TokenState): string { return utils.getFormattedAmount(tokenState.balance, token.decimals, token.symbol); }, -- cgit v1.2.3 From 0e932286d28dad5c8e79659cb679c75e83c3825d Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Mon, 25 Jun 2018 10:25:58 -0700 Subject: Use moment and lodash --- packages/website/ts/components/generate_order/asset_picker.tsx | 3 ++- packages/website/ts/components/wallet/wallet.tsx | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'packages/website/ts') diff --git a/packages/website/ts/components/generate_order/asset_picker.tsx b/packages/website/ts/components/generate_order/asset_picker.tsx index e78324346..ade168f2e 100644 --- a/packages/website/ts/components/generate_order/asset_picker.tsx +++ b/packages/website/ts/components/generate_order/asset_picker.tsx @@ -1,6 +1,7 @@ import * as _ from 'lodash'; import Dialog from 'material-ui/Dialog'; import FlatButton from 'material-ui/FlatButton'; +import * as moment from 'moment'; import * as React from 'react'; import { Blockchain } from 'ts/blockchain'; import { NewTokenForm } from 'ts/components/generate_order/new_token_form'; @@ -260,7 +261,7 @@ export class AssetPicker extends React.Component { if ( !_.isUndefined(firstDifferentTrackedToken) && _.size(differentTrackedTokens) === 1 && - currentTrackedTokens.includes(firstDifferentTrackedToken) + _.includes(currentTrackedTokens, firstDifferentTrackedToken) ) { document.getElementById(firstDifferentTrackedToken.address).scrollIntoView(); } -- cgit v1.2.3 From 4969797c2327ba0eb92a9723842ab312b6631008 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Mon, 25 Jun 2018 11:47:54 -0700 Subject: Remove isTracked field on token in favor of trackedTimestamp --- packages/website/ts/blockchain.ts | 12 +++++++----- .../components/dialogs/track_token_confirmation_dialog.tsx | 4 +++- packages/website/ts/components/fill_order.tsx | 8 ++++---- .../website/ts/components/generate_order/asset_picker.tsx | 11 +++++------ .../website/ts/components/generate_order/new_token_form.tsx | 3 ++- .../website/ts/components/legacy_portal/legacy_portal.tsx | 3 +-- packages/website/ts/components/portal/portal.tsx | 4 ++-- packages/website/ts/components/token_balances.tsx | 4 ++-- packages/website/ts/types.ts | 1 - packages/website/ts/utils/configs.ts | 2 +- packages/website/ts/utils/utils.ts | 5 ++++- 11 files changed, 31 insertions(+), 26 deletions(-) (limited to 'packages/website/ts') diff --git a/packages/website/ts/blockchain.ts b/packages/website/ts/blockchain.ts index 46a4d6629..b65debced 100644 --- a/packages/website/ts/blockchain.ts +++ b/packages/website/ts/blockchain.ts @@ -30,6 +30,7 @@ import { import { BigNumber, intervalUtils, logUtils, promisify } from '@0xproject/utils'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; import * as _ from 'lodash'; +import * as moment from 'moment'; import * as React from 'react'; import contract = require('truffle-contract'); import { BlockchainWatcher } from 'ts/blockchain_watcher'; @@ -559,6 +560,7 @@ export class Blockchain { tokenRegistryTokenSymbols, configs.DEFAULT_TRACKED_TOKEN_SYMBOLS, ); + const currentTimestamp = moment().unix(); if (defaultTrackedTokensInRegistry.length !== configs.DEFAULT_TRACKED_TOKEN_SYMBOLS.length) { this._dispatcher.updateShouldBlockchainErrDialogBeOpen(true); this._dispatcher.encounteredBlockchainError(BlockchainErrs.DefaultTokensNotInTokenRegistry); @@ -573,7 +575,7 @@ export class Blockchain { if (_.isEmpty(trackedTokensByAddress)) { _.each(configs.DEFAULT_TRACKED_TOKEN_SYMBOLS, symbol => { const token = _.find(tokenRegistryTokens, t => t.symbol === symbol); - token.isTracked = true; + token.trackedTimestamp = currentTimestamp; trackedTokensByAddress[token.address] = token; }); if (!_.isUndefined(this._userAddressIfExists)) { @@ -582,10 +584,10 @@ export class Blockchain { }); } } else { - // Properly set all tokenRegistry tokens `isTracked` to true if they are in the existing trackedTokens array - _.each(trackedTokensByAddress, (_trackedToken: Token, address: string) => { + // Properly set all tokenRegistry tokens `trackedTimestamp` if they are in the existing trackedTokens array + _.each(trackedTokensByAddress, (trackedToken: Token, address: string) => { if (!_.isUndefined(tokenRegistryTokensByAddress[address])) { - tokenRegistryTokensByAddress[address].isTracked = true; + tokenRegistryTokensByAddress[address].trackedTimestamp = trackedToken.trackedTimestamp; } }); } @@ -765,7 +767,7 @@ export class Blockchain { name: t.name, symbol: t.symbol, decimals: t.decimals, - isTracked: false, + trackedTimestamp: undefined, isRegistered: true, }; tokenByAddress[token.address] = token; diff --git a/packages/website/ts/components/dialogs/track_token_confirmation_dialog.tsx b/packages/website/ts/components/dialogs/track_token_confirmation_dialog.tsx index f6594b9d5..3751ce06f 100644 --- a/packages/website/ts/components/dialogs/track_token_confirmation_dialog.tsx +++ b/packages/website/ts/components/dialogs/track_token_confirmation_dialog.tsx @@ -1,5 +1,6 @@ import Dialog from 'material-ui/Dialog'; import FlatButton from 'material-ui/FlatButton'; +import * as moment from 'moment'; import * as React from 'react'; import { Blockchain } from 'ts/blockchain'; import { TrackTokenConfirmation } from 'ts/components/track_token_confirmation'; @@ -73,12 +74,13 @@ export class TrackTokenConfirmationDialog extends React.Component< this.setState({ isAddingTokenToTracked: true, }); + const currentTimestamp = moment().unix(); for (const token of this.props.tokens) { const newTokenEntry = { ...token, + trackedTimestamp: currentTimestamp, }; - newTokenEntry.isTracked = true; trackedTokenStorage.addTrackedTokenToUser(this.props.userAddress, this.props.networkId, newTokenEntry); this.props.dispatcher.updateTokenByAddress([newTokenEntry]); } diff --git a/packages/website/ts/components/fill_order.tsx b/packages/website/ts/components/fill_order.tsx index f3ea44286..03ba1183d 100644 --- a/packages/website/ts/components/fill_order.tsx +++ b/packages/website/ts/components/fill_order.tsx @@ -373,26 +373,26 @@ export class FillOrder extends React.Component { const tokensToTrack: Token[] = []; const isUnseenMakerToken = _.isUndefined(makerTokenIfExists); - const isMakerTokenTracked = !_.isUndefined(makerTokenIfExists) && makerTokenIfExists.isTracked; + const isMakerTokenTracked = !_.isUndefined(makerTokenIfExists) && utils.isTokenTracked(makerTokenIfExists); if (isUnseenMakerToken) { tokensToTrack.push({ ...this.state.parsedOrder.metadata.makerToken, address: this.state.parsedOrder.signedOrder.makerTokenAddress, iconUrl: undefined, - isTracked: false, + trackedTimestamp: undefined, isRegistered: false, }); } else if (!isMakerTokenTracked) { tokensToTrack.push(makerTokenIfExists); } const isUnseenTakerToken = _.isUndefined(takerTokenIfExists); - const isTakerTokenTracked = !_.isUndefined(takerTokenIfExists) && takerTokenIfExists.isTracked; + const isTakerTokenTracked = !_.isUndefined(takerTokenIfExists) && utils.isTokenTracked(takerTokenIfExists); if (isUnseenTakerToken) { tokensToTrack.push({ ...this.state.parsedOrder.metadata.takerToken, address: this.state.parsedOrder.signedOrder.takerTokenAddress, iconUrl: undefined, - isTracked: false, + trackedTimestamp: undefined, isRegistered: false, }); } else if (!isTakerTokenTracked) { diff --git a/packages/website/ts/components/generate_order/asset_picker.tsx b/packages/website/ts/components/generate_order/asset_picker.tsx index ade168f2e..3d53a9e7d 100644 --- a/packages/website/ts/components/generate_order/asset_picker.tsx +++ b/packages/website/ts/components/generate_order/asset_picker.tsx @@ -11,6 +11,7 @@ import { trackedTokenStorage } from 'ts/local_storage/tracked_token_storage'; import { Dispatcher } from 'ts/redux/dispatcher'; import { DialogConfigs, Token, TokenByAddress, TokenVisibility } from 'ts/types'; import { constants } from 'ts/utils/constants'; +import { utils } from 'ts/utils/utils'; const TOKEN_ICON_DIMENSION = 100; const TILE_DIMENSION = 146; @@ -135,8 +136,8 @@ export class AssetPicker extends React.Component { if ( - (this.props.tokenVisibility === TokenVisibility.TRACKED && !token.isTracked) || - (this.props.tokenVisibility === TokenVisibility.UNTRACKED && token.isTracked) || + (this.props.tokenVisibility === TokenVisibility.TRACKED && !utils.isTokenTracked(token)) || + (this.props.tokenVisibility === TokenVisibility.UNTRACKED && utils.isTokenTracked(token)) || token.symbol === constants.ZRX_TOKEN_SYMBOL || token.symbol === constants.ETHER_TOKEN_SYMBOL ) { @@ -213,7 +214,7 @@ export class AssetPicker extends React.Component t.isTracked); + const trackedTokens = utils.getTrackedTokens(this.props.tokenByAddress); return ( { if (this.state.tokenManagementState === TokenManagementState.Remove && !isDefaultTrackedToken) { if (token.isRegistered) { // Remove the token from tracked tokens - const newToken = { + const newToken: Token = { ...token, - isTracked: false, + trackedTimestamp: undefined, }; this.props.dispatcher.updateTokenByAddress([newToken]); } else { diff --git a/packages/website/ts/components/token_balances.tsx b/packages/website/ts/components/token_balances.tsx index fc802a7b3..3fae83c00 100644 --- a/packages/website/ts/components/token_balances.tsx +++ b/packages/website/ts/components/token_balances.tsx @@ -424,9 +424,9 @@ export class TokenBalances extends React.Component t.isTracked); + const trackedTokens = _.filter(allTokens, t => this.isTokenTracked(t)); return trackedTokens; }, getFormattedAmountFromToken(token: Token, tokenState: TokenState): string { @@ -386,4 +386,7 @@ export const utils = { return BrowserType.Other; } }, + isTokenTracked(token: Token): boolean { + return !_.isUndefined(token.trackedTimestamp); + }, }; -- cgit v1.2.3