From 848193074a10d9799ffbc27918a8b264a2e101bb Mon Sep 17 00:00:00 2001 From: fragosti Date: Fri, 16 Nov 2018 15:21:04 -0800 Subject: feat: close and open instant based on history changes --- packages/instant/src/index.umd.ts | 51 +++++++++++++++++++++++++++++---------- 1 file changed, 38 insertions(+), 13 deletions(-) (limited to 'packages/instant') diff --git a/packages/instant/src/index.umd.ts b/packages/instant/src/index.umd.ts index 0274db30c..81b7aebe3 100644 --- a/packages/instant/src/index.umd.ts +++ b/packages/instant/src/index.umd.ts @@ -5,6 +5,7 @@ import * as ReactDOM from 'react-dom'; import { DEFAULT_ZERO_EX_CONTAINER_SELECTOR, INJECTED_DIV_CLASS, INJECTED_DIV_ID } from './constants'; import { ZeroExInstantOverlay, ZeroExInstantOverlayProps } from './index'; import { assert } from './util/assert'; +import { util } from './util/util'; export const render = (props: ZeroExInstantOverlayProps, selector: string = DEFAULT_ZERO_EX_CONTAINER_SELECTOR) => { assert.isValidOrderSource('orderSource', props.orderSource); @@ -36,21 +37,45 @@ export const render = (props: ZeroExInstantOverlayProps, selector: string = DEFA assert.isWeb3Provider('props.provider', props.provider); } assert.isString('selector', selector); - const appendToIfExists = document.querySelector(selector); - assert.assert(!_.isNull(appendToIfExists), `Could not find div with selector: ${selector}`); - const appendTo = appendToIfExists as Element; - const injectedDiv = document.createElement('div'); - injectedDiv.setAttribute('id', INJECTED_DIV_ID); - injectedDiv.setAttribute('class', INJECTED_DIV_CLASS); - appendTo.appendChild(injectedDiv); - const instantOverlayProps = { - ...props, - onClose: () => { - appendTo.removeChild(injectedDiv); + // Render instant and return a callback that allows you to close it. + const renderInstant = () => { + const appendToIfExists = document.querySelector(selector); + assert.assert(!_.isNull(appendToIfExists), `Could not find div with selector: ${selector}`); + const appendTo = appendToIfExists as Element; + const injectedDiv = document.createElement('div'); + injectedDiv.setAttribute('id', INJECTED_DIV_ID); + injectedDiv.setAttribute('class', INJECTED_DIV_CLASS); + appendTo.appendChild(injectedDiv); + const instantOverlayProps = { + ...props, + onClose: () => window.history.back(), + }; + ReactDOM.render(React.createElement(ZeroExInstantOverlay, instantOverlayProps), injectedDiv); + const close = () => appendTo.removeChild(injectedDiv); + return close; + }; + // Before we render, push to history saying that instant is showing for this part of the history. + window.history.pushState({ zeroExInstantShowing: true }, '0x Instant'); + let closeInstant = renderInstant(); + + let prevOnPopState = util.boundNoop; + if (window.onpopstate) { + prevOnPopState = window.onpopstate.bind(window); + } + window.onpopstate = (e: PopStateEvent) => { + // Don't override integrators handler. + prevOnPopState(e); + // e.state represents the new state + if (e.state && e.state.zeroExInstantShowing) { + // The user pressed fowards, so re-render instant. + closeInstant = renderInstant(); + } else { + // User pressed back, so close instant. + closeInstant(); + delete window.onpopstate; if (!_.isUndefined(props.onClose)) { props.onClose(); } - }, + } }; - ReactDOM.render(React.createElement(ZeroExInstantOverlay, instantOverlayProps), injectedDiv); }; -- cgit v1.2.3 From f7914af9c564d4521e375fb3dd5825da763df7d6 Mon Sep 17 00:00:00 2001 From: fragosti Date: Fri, 16 Nov 2018 15:23:44 -0800 Subject: feat: rename props to config --- packages/instant/src/index.umd.ts | 50 +++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 23 deletions(-) (limited to 'packages/instant') diff --git a/packages/instant/src/index.umd.ts b/packages/instant/src/index.umd.ts index 81b7aebe3..fda21478f 100644 --- a/packages/instant/src/index.umd.ts +++ b/packages/instant/src/index.umd.ts @@ -7,34 +7,38 @@ import { ZeroExInstantOverlay, ZeroExInstantOverlayProps } from './index'; import { assert } from './util/assert'; import { util } from './util/util'; -export const render = (props: ZeroExInstantOverlayProps, selector: string = DEFAULT_ZERO_EX_CONTAINER_SELECTOR) => { - assert.isValidOrderSource('orderSource', props.orderSource); - if (!_.isUndefined(props.defaultSelectedAssetData)) { - assert.isHexString('defaultSelectedAssetData', props.defaultSelectedAssetData); +export interface ZeroExInstantConfig extends ZeroExInstantOverlayProps { + shouldUseHistoryApi?: boolean; +} + +export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_ZERO_EX_CONTAINER_SELECTOR) => { + assert.isValidOrderSource('orderSource', config.orderSource); + if (!_.isUndefined(config.defaultSelectedAssetData)) { + assert.isHexString('defaultSelectedAssetData', config.defaultSelectedAssetData); } - if (!_.isUndefined(props.additionalAssetMetaDataMap)) { - assert.isValidAssetMetaDataMap('props.additionalAssetMetaDataMap', props.additionalAssetMetaDataMap); + if (!_.isUndefined(config.additionalAssetMetaDataMap)) { + assert.isValidAssetMetaDataMap('props.additionalAssetMetaDataMap', config.additionalAssetMetaDataMap); } - if (!_.isUndefined(props.defaultAssetBuyAmount)) { - assert.isNumber('props.defaultAssetBuyAmount', props.defaultAssetBuyAmount); + if (!_.isUndefined(config.defaultAssetBuyAmount)) { + assert.isNumber('props.defaultAssetBuyAmount', config.defaultAssetBuyAmount); } - if (!_.isUndefined(props.networkId)) { - assert.isNumber('props.networkId', props.networkId); + if (!_.isUndefined(config.networkId)) { + assert.isNumber('props.networkId', config.networkId); } - if (!_.isUndefined(props.availableAssetDatas)) { - assert.areValidAssetDatas('availableAssetDatas', props.availableAssetDatas); + if (!_.isUndefined(config.availableAssetDatas)) { + assert.areValidAssetDatas('availableAssetDatas', config.availableAssetDatas); } - if (!_.isUndefined(props.onClose)) { - assert.isFunction('props.onClose', props.onClose); + if (!_.isUndefined(config.onClose)) { + assert.isFunction('props.onClose', config.onClose); } - if (!_.isUndefined(props.zIndex)) { - assert.isNumber('props.zIndex', props.zIndex); + if (!_.isUndefined(config.zIndex)) { + assert.isNumber('props.zIndex', config.zIndex); } - if (!_.isUndefined(props.affiliateInfo)) { - assert.isValidAffiliateInfo('props.affiliateInfo', props.affiliateInfo); + if (!_.isUndefined(config.affiliateInfo)) { + assert.isValidAffiliateInfo('props.affiliateInfo', config.affiliateInfo); } - if (!_.isUndefined(props.provider)) { - assert.isWeb3Provider('props.provider', props.provider); + if (!_.isUndefined(config.provider)) { + assert.isWeb3Provider('props.provider', config.provider); } assert.isString('selector', selector); // Render instant and return a callback that allows you to close it. @@ -47,7 +51,7 @@ export const render = (props: ZeroExInstantOverlayProps, selector: string = DEFA injectedDiv.setAttribute('class', INJECTED_DIV_CLASS); appendTo.appendChild(injectedDiv); const instantOverlayProps = { - ...props, + ...config, onClose: () => window.history.back(), }; ReactDOM.render(React.createElement(ZeroExInstantOverlay, instantOverlayProps), injectedDiv); @@ -73,8 +77,8 @@ export const render = (props: ZeroExInstantOverlayProps, selector: string = DEFA // User pressed back, so close instant. closeInstant(); delete window.onpopstate; - if (!_.isUndefined(props.onClose)) { - props.onClose(); + if (!_.isUndefined(config.onClose)) { + config.onClose(); } } }; -- cgit v1.2.3 From 9a53a29b1f421cdea190b6175dec437ec6d76a39 Mon Sep 17 00:00:00 2001 From: fragosti Date: Fri, 16 Nov 2018 15:41:21 -0800 Subject: feat: allow integrator to disable pushstate logic --- packages/instant/public/index.html | 2 ++ packages/instant/src/index.umd.ts | 54 ++++++++++++++++++++------------------ 2 files changed, 31 insertions(+), 25 deletions(-) (limited to 'packages/instant') diff --git a/packages/instant/public/index.html b/packages/instant/public/index.html index 253cbb194..79edb6c17 100644 --- a/packages/instant/public/index.html +++ b/packages/instant/public/index.html @@ -128,8 +128,10 @@ availableAssetDatas: availableAssetDatasString ? JSON.parse(availableAssetDatasString) : undefined, defaultSelectedAssetData: queryParams.getQueryParamValue('defaultSelectedAssetData'), affiliateInfo: affiliateInfoOverride, + } const renderOptions = Object.assign({}, renderOptionsDefaults, removeUndefined(renderOptionsOverrides)); + window.onpopstate = () => console.log('Integrators onpopstate called'); zeroExInstant.render(renderOptions); diff --git a/packages/instant/src/index.umd.ts b/packages/instant/src/index.umd.ts index fda21478f..381c9094b 100644 --- a/packages/instant/src/index.umd.ts +++ b/packages/instant/src/index.umd.ts @@ -8,7 +8,7 @@ import { assert } from './util/assert'; import { util } from './util/util'; export interface ZeroExInstantConfig extends ZeroExInstantOverlayProps { - shouldUseHistoryApi?: boolean; + shouldDisablePushToHistory?: boolean; } export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_ZERO_EX_CONTAINER_SELECTOR) => { @@ -50,36 +50,40 @@ export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_Z injectedDiv.setAttribute('id', INJECTED_DIV_ID); injectedDiv.setAttribute('class', INJECTED_DIV_CLASS); appendTo.appendChild(injectedDiv); + const close = () => appendTo.removeChild(injectedDiv); const instantOverlayProps = { ...config, - onClose: () => window.history.back(), + // If we are using the history API, just go back to close + onClose: () => (config.shouldDisablePushToHistory ? close() : window.history.back()), }; ReactDOM.render(React.createElement(ZeroExInstantOverlay, instantOverlayProps), injectedDiv); - const close = () => appendTo.removeChild(injectedDiv); return close; }; - // Before we render, push to history saying that instant is showing for this part of the history. - window.history.pushState({ zeroExInstantShowing: true }, '0x Instant'); - let closeInstant = renderInstant(); + if (config.shouldDisablePushToHistory) { + renderInstant(); + } else { + // Before we render, push to history saying that instant is showing for this part of the history. + window.history.pushState({ zeroExInstantShowing: true }, '0x Instant'); + let closeInstant = renderInstant(); - let prevOnPopState = util.boundNoop; - if (window.onpopstate) { - prevOnPopState = window.onpopstate.bind(window); - } - window.onpopstate = (e: PopStateEvent) => { - // Don't override integrators handler. - prevOnPopState(e); - // e.state represents the new state - if (e.state && e.state.zeroExInstantShowing) { - // The user pressed fowards, so re-render instant. - closeInstant = renderInstant(); - } else { - // User pressed back, so close instant. - closeInstant(); - delete window.onpopstate; - if (!_.isUndefined(config.onClose)) { - config.onClose(); - } + let prevOnPopState = util.boundNoop; + if (window.onpopstate) { + prevOnPopState = window.onpopstate.bind(window); } - }; + window.onpopstate = (e: PopStateEvent) => { + // Don't override integrators handler. + prevOnPopState(e); + // e.state represents the new state + if (e.state && e.state.zeroExInstantShowing) { + // The user pressed fowards, so re-render instant. + closeInstant = renderInstant(); + } else { + // User pressed back, so close instant. + closeInstant(); + if (!_.isUndefined(config.onClose)) { + config.onClose(); + } + } + }; + } }; -- cgit v1.2.3 From a4f6cd21bd289eb2baaee8b6b7d09cbb9e0955dc Mon Sep 17 00:00:00 2001 From: fragosti Date: Fri, 16 Nov 2018 15:45:02 -0800 Subject: feat: be more specific with callback name --- packages/instant/src/index.umd.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'packages/instant') diff --git a/packages/instant/src/index.umd.ts b/packages/instant/src/index.umd.ts index 381c9094b..298b7733f 100644 --- a/packages/instant/src/index.umd.ts +++ b/packages/instant/src/index.umd.ts @@ -41,7 +41,7 @@ export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_Z assert.isWeb3Provider('props.provider', config.provider); } assert.isString('selector', selector); - // Render instant and return a callback that allows you to close it. + // Render instant and return a callback that allows you to remove it from the DOM. const renderInstant = () => { const appendToIfExists = document.querySelector(selector); assert.assert(!_.isNull(appendToIfExists), `Could not find div with selector: ${selector}`); @@ -50,21 +50,21 @@ export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_Z injectedDiv.setAttribute('id', INJECTED_DIV_ID); injectedDiv.setAttribute('class', INJECTED_DIV_CLASS); appendTo.appendChild(injectedDiv); - const close = () => appendTo.removeChild(injectedDiv); + const removeFromDom = () => appendTo.removeChild(injectedDiv); const instantOverlayProps = { ...config, // If we are using the history API, just go back to close - onClose: () => (config.shouldDisablePushToHistory ? close() : window.history.back()), + onClose: () => (config.shouldDisablePushToHistory ? removeFromDom() : window.history.back()), }; ReactDOM.render(React.createElement(ZeroExInstantOverlay, instantOverlayProps), injectedDiv); - return close; + return removeFromDom; }; if (config.shouldDisablePushToHistory) { renderInstant(); } else { // Before we render, push to history saying that instant is showing for this part of the history. window.history.pushState({ zeroExInstantShowing: true }, '0x Instant'); - let closeInstant = renderInstant(); + let removeInstant = renderInstant(); let prevOnPopState = util.boundNoop; if (window.onpopstate) { @@ -76,10 +76,10 @@ export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_Z // e.state represents the new state if (e.state && e.state.zeroExInstantShowing) { // The user pressed fowards, so re-render instant. - closeInstant = renderInstant(); + removeInstant = renderInstant(); } else { // User pressed back, so close instant. - closeInstant(); + removeInstant(); if (!_.isUndefined(config.onClose)) { config.onClose(); } -- cgit v1.2.3 From 51dce3008841b7bdc9080212f8b5e12a90f6cce9 Mon Sep 17 00:00:00 2001 From: fragosti Date: Fri, 16 Nov 2018 15:48:55 -0800 Subject: feat: add assert for shouldDisablePushToHistory --- packages/instant/src/index.umd.ts | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'packages/instant') diff --git a/packages/instant/src/index.umd.ts b/packages/instant/src/index.umd.ts index 298b7733f..9703c6fc0 100644 --- a/packages/instant/src/index.umd.ts +++ b/packages/instant/src/index.umd.ts @@ -17,28 +17,31 @@ export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_Z assert.isHexString('defaultSelectedAssetData', config.defaultSelectedAssetData); } if (!_.isUndefined(config.additionalAssetMetaDataMap)) { - assert.isValidAssetMetaDataMap('props.additionalAssetMetaDataMap', config.additionalAssetMetaDataMap); + assert.isValidAssetMetaDataMap('additionalAssetMetaDataMap', config.additionalAssetMetaDataMap); } if (!_.isUndefined(config.defaultAssetBuyAmount)) { - assert.isNumber('props.defaultAssetBuyAmount', config.defaultAssetBuyAmount); + assert.isNumber('defaultAssetBuyAmount', config.defaultAssetBuyAmount); } if (!_.isUndefined(config.networkId)) { - assert.isNumber('props.networkId', config.networkId); + assert.isNumber('networkId', config.networkId); } if (!_.isUndefined(config.availableAssetDatas)) { assert.areValidAssetDatas('availableAssetDatas', config.availableAssetDatas); } if (!_.isUndefined(config.onClose)) { - assert.isFunction('props.onClose', config.onClose); + assert.isFunction('onClose', config.onClose); } if (!_.isUndefined(config.zIndex)) { - assert.isNumber('props.zIndex', config.zIndex); + assert.isNumber('zIndex', config.zIndex); } if (!_.isUndefined(config.affiliateInfo)) { - assert.isValidAffiliateInfo('props.affiliateInfo', config.affiliateInfo); + assert.isValidAffiliateInfo('affiliateInfo', config.affiliateInfo); } if (!_.isUndefined(config.provider)) { - assert.isWeb3Provider('props.provider', config.provider); + assert.isWeb3Provider('provider', config.provider); + } + if (!_.isUndefined(config.shouldDisablePushToHistory)) { + assert.isBoolean('shouldDisablePushToHistory', config.shouldDisablePushToHistory); } assert.isString('selector', selector); // Render instant and return a callback that allows you to remove it from the DOM. -- cgit v1.2.3 From 6e2fbcdb3e17e328fc76411b352b2385838eaa3a Mon Sep 17 00:00:00 2001 From: fragosti Date: Fri, 16 Nov 2018 15:58:41 -0800 Subject: feat: add URL override param --- packages/instant/public/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'packages/instant') diff --git a/packages/instant/public/index.html b/packages/instant/public/index.html index 79edb6c17..039f8b781 100644 --- a/packages/instant/public/index.html +++ b/packages/instant/public/index.html @@ -128,7 +128,7 @@ availableAssetDatas: availableAssetDatasString ? JSON.parse(availableAssetDatasString) : undefined, defaultSelectedAssetData: queryParams.getQueryParamValue('defaultSelectedAssetData'), affiliateInfo: affiliateInfoOverride, - + shouldDisablePushToHistory: !!queryParams.getQueryParamValue('shouldDisablePushToHistory'), } const renderOptions = Object.assign({}, renderOptionsDefaults, removeUndefined(renderOptionsOverrides)); window.onpopstate = () => console.log('Integrators onpopstate called'); -- cgit v1.2.3 From 654c13df8aee2e43992c6629d2249d56667fec67 Mon Sep 17 00:00:00 2001 From: fragosti Date: Fri, 16 Nov 2018 16:07:37 -0800 Subject: fix: bug where we did not call onClose config --- packages/instant/src/index.umd.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'packages/instant') diff --git a/packages/instant/src/index.umd.ts b/packages/instant/src/index.umd.ts index 9703c6fc0..518326e21 100644 --- a/packages/instant/src/index.umd.ts +++ b/packages/instant/src/index.umd.ts @@ -53,14 +53,19 @@ export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_Z injectedDiv.setAttribute('id', INJECTED_DIV_ID); injectedDiv.setAttribute('class', INJECTED_DIV_CLASS); appendTo.appendChild(injectedDiv); - const removeFromDom = () => appendTo.removeChild(injectedDiv); + const closeInstant = () => { + if (config.onClose) { + config.onClose(); + } + appendTo.removeChild(injectedDiv); + }; const instantOverlayProps = { ...config, // If we are using the history API, just go back to close - onClose: () => (config.shouldDisablePushToHistory ? removeFromDom() : window.history.back()), + onClose: () => (config.shouldDisablePushToHistory ? closeInstant() : window.history.back()), }; ReactDOM.render(React.createElement(ZeroExInstantOverlay, instantOverlayProps), injectedDiv); - return removeFromDom; + return closeInstant; }; if (config.shouldDisablePushToHistory) { renderInstant(); @@ -83,9 +88,6 @@ export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_Z } else { // User pressed back, so close instant. removeInstant(); - if (!_.isUndefined(config.onClose)) { - config.onClose(); - } } }; } -- cgit v1.2.3 From ac942faa258f604f4f6171759f6bcdf786317d29 Mon Sep 17 00:00:00 2001 From: fragosti Date: Fri, 16 Nov 2018 16:14:10 -0800 Subject: chore: use lodash where relevant --- packages/instant/src/index.umd.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'packages/instant') diff --git a/packages/instant/src/index.umd.ts b/packages/instant/src/index.umd.ts index 518326e21..34d893ad7 100644 --- a/packages/instant/src/index.umd.ts +++ b/packages/instant/src/index.umd.ts @@ -54,7 +54,7 @@ export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_Z injectedDiv.setAttribute('class', INJECTED_DIV_CLASS); appendTo.appendChild(injectedDiv); const closeInstant = () => { - if (config.onClose) { + if (!_.isUndefined(config.onClose)) { config.onClose(); } appendTo.removeChild(injectedDiv); -- cgit v1.2.3 From 9384c507ac29043d0d2f68bef3dde94a43282d09 Mon Sep 17 00:00:00 2001 From: fragosti Date: Fri, 16 Nov 2018 16:33:02 -0800 Subject: feat: add isInstantRendered check to safeguard against double renders and double removes --- packages/instant/public/index.html | 4 ++++ packages/instant/src/index.umd.ts | 18 +++++++++++++----- 2 files changed, 17 insertions(+), 5 deletions(-) (limited to 'packages/instant') diff --git a/packages/instant/public/index.html b/packages/instant/public/index.html index 039f8b781..557cfa3dc 100644 --- a/packages/instant/public/index.html +++ b/packages/instant/public/index.html @@ -27,6 +27,10 @@
+ + + - + .button { + margin: 10px; + } - -
- - + + + + +
+
+
+ + + +
+
+
+ + + diff --git a/packages/instant/src/index.umd.ts b/packages/instant/src/index.umd.ts index 59f658b33..1d62084b5 100644 --- a/packages/instant/src/index.umd.ts +++ b/packages/instant/src/index.umd.ts @@ -7,6 +7,7 @@ import { ZeroExInstantOverlay, ZeroExInstantOverlayProps } from './index'; import { assert } from './util/assert'; import { util } from './util/util'; +const isInstantRendered = (): boolean => !!document.getElementById(INJECTED_DIV_ID); export interface ZeroExInstantConfig extends ZeroExInstantOverlayProps { shouldDisablePushToHistory?: boolean; } @@ -43,8 +44,8 @@ export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_Z if (!_.isUndefined(config.shouldDisablePushToHistory)) { assert.isBoolean('shouldDisablePushToHistory', config.shouldDisablePushToHistory); } - if (!_.isUndefined(props.shouldDisableAnalyticsTracking)) { - assert.isBoolean('props.shouldDisableAnalyticsTracking', props.shouldDisableAnalyticsTracking); + if (!_.isUndefined(config.shouldDisableAnalyticsTracking)) { + assert.isBoolean('shouldDisableAnalyticsTracking', config.shouldDisableAnalyticsTracking); } assert.isString('selector', selector); // Render instant and return a callback that allows you to remove it from the DOM. @@ -101,5 +102,3 @@ export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_Z }; } }; - -const isInstantRendered = (): boolean => !!document.getElementById(INJECTED_DIV_ID); -- cgit v1.2.3 From b494a4a4dba6c781667b690f38387f03a22fe141 Mon Sep 17 00:00:00 2001 From: fragosti Date: Wed, 21 Nov 2018 11:55:32 -0500 Subject: chore: clean up index.umd.ts a bit --- packages/instant/public/index.html | 2 +- packages/instant/src/index.umd.ts | 70 +++++++++++++++++++++----------------- 2 files changed, 39 insertions(+), 33 deletions(-) (limited to 'packages/instant') diff --git a/packages/instant/public/index.html b/packages/instant/public/index.html index 8f11502e4..df39994ef 100644 --- a/packages/instant/public/index.html +++ b/packages/instant/public/index.html @@ -64,7 +64,7 @@ window.history.pushState({ page: 1 }, '0x Instant'); window.history.pushState({ page: 2 }, '0x Instant'); window.history.pushState({ page: 3 }, '0x Instant'); - window.onpopstate = () => console.log('Integrators onpopstate called'); + window.onpopstate = () => console.log("Integrator's onpopstate called"); const removeUndefined = obj => { for (let k in obj) if (obj[k] === undefined) delete obj[k]; diff --git a/packages/instant/src/index.umd.ts b/packages/instant/src/index.umd.ts index 1d62084b5..15ca59323 100644 --- a/packages/instant/src/index.umd.ts +++ b/packages/instant/src/index.umd.ts @@ -8,11 +8,8 @@ import { assert } from './util/assert'; import { util } from './util/util'; const isInstantRendered = (): boolean => !!document.getElementById(INJECTED_DIV_ID); -export interface ZeroExInstantConfig extends ZeroExInstantOverlayProps { - shouldDisablePushToHistory?: boolean; -} -export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_ZERO_EX_CONTAINER_SELECTOR) => { +const validateInstantRenderConfig = (config: ZeroExInstantConfig, selector: string) => { assert.isValidOrderSource('orderSource', config.orderSource); if (!_.isUndefined(config.defaultSelectedAssetData)) { assert.isHexString('defaultSelectedAssetData', config.defaultSelectedAssetData); @@ -48,37 +45,46 @@ export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_Z assert.isBoolean('shouldDisableAnalyticsTracking', config.shouldDisableAnalyticsTracking); } assert.isString('selector', selector); - // Render instant and return a callback that allows you to remove it from the DOM. - const renderInstant = () => { - const appendToIfExists = document.querySelector(selector); - assert.assert(!_.isNull(appendToIfExists), `Could not find div with selector: ${selector}`); - const appendTo = appendToIfExists as Element; - const injectedDiv = document.createElement('div'); - injectedDiv.setAttribute('id', INJECTED_DIV_ID); - injectedDiv.setAttribute('class', INJECTED_DIV_CLASS); - appendTo.appendChild(injectedDiv); - const closeInstant = () => { - if (!_.isUndefined(config.onClose)) { - config.onClose(); - } - appendTo.removeChild(injectedDiv); - }; - const instantOverlayProps = { - ...config, - // If we are using the history API, just go back to close - onClose: () => (config.shouldDisablePushToHistory ? closeInstant() : window.history.back()), - }; - ReactDOM.render(React.createElement(ZeroExInstantOverlay, instantOverlayProps), injectedDiv); - return closeInstant; +}; + +// Render instant and return a callback that allows you to remove it from the DOM. +const renderInstant = (config: ZeroExInstantConfig, selector: string) => { + const appendToIfExists = document.querySelector(selector); + assert.assert(!_.isNull(appendToIfExists), `Could not find div with selector: ${selector}`); + const appendTo = appendToIfExists as Element; + const injectedDiv = document.createElement('div'); + injectedDiv.setAttribute('id', INJECTED_DIV_ID); + injectedDiv.setAttribute('class', INJECTED_DIV_CLASS); + appendTo.appendChild(injectedDiv); + const closeInstant = () => { + if (!_.isUndefined(config.onClose)) { + config.onClose(); + } + appendTo.removeChild(injectedDiv); + }; + const instantOverlayProps = { + ...config, + // If we are using the history API, just go back to close + onClose: () => (config.shouldDisablePushToHistory ? closeInstant() : window.history.back()), }; + ReactDOM.render(React.createElement(ZeroExInstantOverlay, instantOverlayProps), injectedDiv); + return closeInstant; +}; + +export interface ZeroExInstantConfig extends ZeroExInstantOverlayProps { + shouldDisablePushToHistory?: boolean; +} + +export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_ZERO_EX_CONTAINER_SELECTOR) => { + validateInstantRenderConfig(config, selector); if (config.shouldDisablePushToHistory) { if (!isInstantRendered()) { - renderInstant(); + renderInstant(config, selector); } } else { // Before we render, push to history saying that instant is showing for this part of the history. window.history.pushState({ zeroExInstantShowing: true }, '0x Instant'); - let removeInstant = renderInstant(); + let removeInstant = renderInstant(config, selector); let prevOnPopState = util.boundNoop; if (window.onpopstate) { @@ -86,12 +92,12 @@ export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_Z } window.onpopstate = (e: PopStateEvent) => { // Don't override integrators handler. - prevOnPopState(e); - // e.state represents the new state - if (e.state && e.state.zeroExInstantShowing) { + // prevOnPopState(e); + const newState = e.state; + if (newState && newState.zeroExInstantShowing) { // We have returned to a history state that expects instant to be rendered. if (!isInstantRendered()) { - removeInstant = renderInstant(); + removeInstant = renderInstant(config, selector); } } else { // History has changed to a different state. -- cgit v1.2.3 From ed91c6c874282ab069a72784b8e563b634a236bf Mon Sep 17 00:00:00 2001 From: fragosti Date: Wed, 21 Nov 2018 12:44:28 -0500 Subject: fix: multiple render and closes edge case for onpopstate render --- packages/instant/src/index.umd.ts | 52 ++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 25 deletions(-) (limited to 'packages/instant') diff --git a/packages/instant/src/index.umd.ts b/packages/instant/src/index.umd.ts index 15ca59323..3a8694d6a 100644 --- a/packages/instant/src/index.umd.ts +++ b/packages/instant/src/index.umd.ts @@ -81,30 +81,32 @@ export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_Z if (!isInstantRendered()) { renderInstant(config, selector); } - } else { - // Before we render, push to history saying that instant is showing for this part of the history. - window.history.pushState({ zeroExInstantShowing: true }, '0x Instant'); - let removeInstant = renderInstant(config, selector); - - let prevOnPopState = util.boundNoop; - if (window.onpopstate) { - prevOnPopState = window.onpopstate.bind(window); - } - window.onpopstate = (e: PopStateEvent) => { - // Don't override integrators handler. - // prevOnPopState(e); - const newState = e.state; - if (newState && newState.zeroExInstantShowing) { - // We have returned to a history state that expects instant to be rendered. - if (!isInstantRendered()) { - removeInstant = renderInstant(config, selector); - } - } else { - // History has changed to a different state. - if (isInstantRendered()) { - removeInstant(); - } - } - }; + return; + } + // Before we render, push to history saying that instant is showing for this part of the history. + window.history.pushState({ zeroExInstantShowing: true }, '0x Instant'); + let removeInstant = renderInstant(config, selector); + // If the integrator defined a popstate handler, save it to __zeroExInstantIntegratorsPopStateHandler + // unless we have already done so on a previous render. + const anyWindow = window as any; + if (window.onpopstate && !anyWindow.__zeroExInstantIntegratorsPopStateHandler) { + anyWindow.__zeroExInstantIntegratorsPopStateHandler = window.onpopstate.bind(window); } + const integratorsOnPopStateHandler = anyWindow.__zeroExInstantIntegratorsPopStateHandler || util.boundNoop; + const onPopStateHandler = (e: PopStateEvent) => { + integratorsOnPopStateHandler(e); + const newState = e.state; + if (newState && newState.zeroExInstantShowing) { + // We have returned to a history state that expects instant to be rendered. + if (!isInstantRendered()) { + removeInstant = renderInstant(config, selector); + } + } else { + // History has changed to a different state. + if (isInstantRendered()) { + removeInstant(); + } + } + }; + window.onpopstate = onPopStateHandler; }; -- cgit v1.2.3 From 31d1b4ba670d25c4cd4ed93d32d12718b4804e5d Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Wed, 21 Nov 2018 12:30:52 -0800 Subject: chore(instant): refactor account tracking logic in middleware to be more readable --- packages/instant/src/redux/analytics_middleware.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'packages/instant') diff --git a/packages/instant/src/redux/analytics_middleware.ts b/packages/instant/src/redux/analytics_middleware.ts index 893844f5d..889cc875e 100644 --- a/packages/instant/src/redux/analytics_middleware.ts +++ b/packages/instant/src/redux/analytics_middleware.ts @@ -21,17 +21,17 @@ export const analyticsMiddleware: Middleware = store => next => middlewareAction switch (nextAction.type) { case ActionTypes.SET_ACCOUNT_STATE_READY: - if (prevAccount.state !== AccountState.Ready && curAccount.state === AccountState.Ready) { - // if we are moving from account not ready to account ready, update the current address and track `Account - Ready` + if (curAccount.state === AccountState.Ready) { + const didJustTurnReady = prevAccount.state !== AccountState.Ready; + const didJustUpdateAddress = + prevAccount.state === AccountState.Ready && prevAccount.address !== curAccount.address; const ethAddress = curAccount.address; - analytics.addUserProperties({ ethAddress }); - analytics.trackAccountReady(ethAddress); - } else if (prevAccount.state === AccountState.Ready && curAccount.state === AccountState.Ready) { - if (prevAccount.address !== curAccount.address) { - // if our account state was already ready and our address has changed, update the current address and track `Account - Address Changed` - const ethAddress = curAccount.address; + if (didJustTurnReady) { + analytics.trackAccountReady(ethAddress); analytics.addUserProperties({ ethAddress }); + } else if (didJustUpdateAddress) { analytics.trackAccountAddressChanged(ethAddress); + analytics.addUserProperties({ ethAddress }); } } break; -- cgit v1.2.3 From 6604e2db20d6263e05b00cf5d36b56788e42d9c2 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Wed, 21 Nov 2018 12:44:28 -0800 Subject: chore(instant): refactor usage of event properties in heap --- packages/instant/src/redux/analytics_middleware.ts | 12 ++++---- packages/instant/src/util/analytics.ts | 32 ++++++++++++---------- packages/instant/src/util/heap.ts | 4 ++- 3 files changed, 26 insertions(+), 22 deletions(-) (limited to 'packages/instant') diff --git a/packages/instant/src/redux/analytics_middleware.ts b/packages/instant/src/redux/analytics_middleware.ts index 889cc875e..931902187 100644 --- a/packages/instant/src/redux/analytics_middleware.ts +++ b/packages/instant/src/redux/analytics_middleware.ts @@ -27,19 +27,17 @@ export const analyticsMiddleware: Middleware = store => next => middlewareAction prevAccount.state === AccountState.Ready && prevAccount.address !== curAccount.address; const ethAddress = curAccount.address; if (didJustTurnReady) { - analytics.trackAccountReady(ethAddress); - analytics.addUserProperties({ ethAddress }); + analytics.trackAccountReady({ address: ethAddress }); + analytics.addUserProperties({ lastKnownEthAddress: ethAddress }); } else if (didJustUpdateAddress) { - analytics.trackAccountAddressChanged(ethAddress); - analytics.addUserProperties({ ethAddress }); + analytics.trackAccountAddressChanged({ address: ethAddress }); + analytics.addUserProperties({ lastKnownEthAddress: ethAddress }); } } break; case ActionTypes.SET_ACCOUNT_STATE_LOCKED: if (prevAccount.state !== AccountState.Locked && curAccount.state === AccountState.Locked) { - // if we are moving from account not locked to account locked, update the current address to undefined and track `Account - Locked` - const ethAddress = undefined; - analytics.addUserProperties({ ethAddress }); + // if we are moving from account not locked to account locked, track `Account - Locked` analytics.trackAccountLocked(); } break; diff --git a/packages/instant/src/util/analytics.ts b/packages/instant/src/util/analytics.ts index d36bf8fc3..31233fe7a 100644 --- a/packages/instant/src/util/analytics.ts +++ b/packages/instant/src/util/analytics.ts @@ -1,6 +1,4 @@ -import { ObjectMap } from '@0x/types'; - -import { heapUtil } from './heap'; +import { EventProperties, heapUtil } from './heap'; let isDisabled = false; export const disableAnalytics = (shouldDisableAnalytics: boolean) => { @@ -21,9 +19,9 @@ enum EventNames { ACCOUNT_UNLOCK_DENIED = 'Account - Unlock Denied', ACCOUNT_ADDRESS_CHANGED = 'Account - Address Changed', } -const track = (eventName: EventNames, eventData: ObjectMap = {}): void => { +const track = (eventName: EventNames, eventProperties: EventProperties = {}): void => { evaluateIfEnabled(() => { - heapUtil.evaluateHeapCall(heap => heap.track(eventName, eventData)); + heapUtil.evaluateHeapCall(heap => heap.track(eventName, eventProperties)); }); }; function trackingEventFnWithoutPayload(eventName: EventNames): () => void { @@ -32,16 +30,14 @@ function trackingEventFnWithoutPayload(eventName: EventNames): () => void { }; } // tslint:disable-next-line:no-unused-variable -function trackingEventFnWithPayload>( - eventName: EventNames, -): (eventDataProperties: T) => void { - return (eventDataProperties: T) => { - track(eventName, eventDataProperties); +function trackingEventFnWithPayload(eventName: EventNames): (eventProperties: EventProperties) => void { + return (eventProperties: EventProperties) => { + track(eventName, eventProperties); }; } export interface AnalyticsUserOptions { - ethAddress?: string; + lastKnownEthAddress?: string; ethBalanceInUnitAmount?: string; } export interface AnalyticsEventOptions { @@ -52,6 +48,13 @@ export interface AnalyticsEventOptions { gitSha?: string; npmVersion?: string; } +export interface AccountReadyEventProperties { + address: string; +} +export interface AccountAddressChangedEventProperties { + address: string; +} + export const analytics = { addUserProperties: (properties: AnalyticsUserOptions): void => { evaluateIfEnabled(() => { @@ -65,9 +68,10 @@ export const analytics = { }, trackInstantOpened: trackingEventFnWithoutPayload(EventNames.INSTANT_OPENED), trackAccountLocked: trackingEventFnWithoutPayload(EventNames.ACCOUNT_LOCKED), - trackAccountReady: (address: string) => trackingEventFnWithPayload(EventNames.ACCOUNT_READY)({ address }), + trackAccountReady: (eventProperties: AccountReadyEventProperties) => + trackingEventFnWithPayload(EventNames.ACCOUNT_READY)({ ...eventProperties }), trackAccountUnlockRequested: trackingEventFnWithoutPayload(EventNames.ACCOUNT_UNLOCK_REQUESTED), trackAccountUnlockDenied: trackingEventFnWithoutPayload(EventNames.ACCOUNT_UNLOCK_DENIED), - trackAccountAddressChanged: (address: string) => - trackingEventFnWithPayload(EventNames.ACCOUNT_ADDRESS_CHANGED)({ address }), + trackAccountAddressChanged: (eventProperties: AccountAddressChangedEventProperties) => + trackingEventFnWithPayload(EventNames.ACCOUNT_ADDRESS_CHANGED)({ ...eventProperties }), }; diff --git a/packages/instant/src/util/heap.ts b/packages/instant/src/util/heap.ts index 78ec3b3cc..7c53c9918 100644 --- a/packages/instant/src/util/heap.ts +++ b/packages/instant/src/util/heap.ts @@ -6,11 +6,13 @@ import { HEAP_ANALYTICS_ID } from '../constants'; import { AnalyticsEventOptions, AnalyticsUserOptions } from './analytics'; +export type EventProperties = ObjectMap; + export interface HeapAnalytics { loaded: boolean; appid: string; identify(id: string, idType: string): void; - track(eventName: string, eventProperties?: ObjectMap): void; + track(eventName: string, eventProperties?: EventProperties): void; resetIdentity(): void; addUserProperties(properties: AnalyticsUserOptions): void; addEventProperties(properties: AnalyticsEventOptions): void; -- cgit v1.2.3 From 804de89796de047fe43dbb736b5e8b82bb30ee3a Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Wed, 21 Nov 2018 13:40:23 -0800 Subject: chore(instant): revert usage of event properties --- packages/instant/src/redux/analytics_middleware.ts | 4 ++-- packages/instant/src/util/analytics.ts | 13 +++---------- 2 files changed, 5 insertions(+), 12 deletions(-) (limited to 'packages/instant') diff --git a/packages/instant/src/redux/analytics_middleware.ts b/packages/instant/src/redux/analytics_middleware.ts index 931902187..299c2560e 100644 --- a/packages/instant/src/redux/analytics_middleware.ts +++ b/packages/instant/src/redux/analytics_middleware.ts @@ -27,10 +27,10 @@ export const analyticsMiddleware: Middleware = store => next => middlewareAction prevAccount.state === AccountState.Ready && prevAccount.address !== curAccount.address; const ethAddress = curAccount.address; if (didJustTurnReady) { - analytics.trackAccountReady({ address: ethAddress }); + analytics.trackAccountReady(ethAddress); analytics.addUserProperties({ lastKnownEthAddress: ethAddress }); } else if (didJustUpdateAddress) { - analytics.trackAccountAddressChanged({ address: ethAddress }); + analytics.trackAccountAddressChanged(ethAddress); analytics.addUserProperties({ lastKnownEthAddress: ethAddress }); } } diff --git a/packages/instant/src/util/analytics.ts b/packages/instant/src/util/analytics.ts index 31233fe7a..e389e1530 100644 --- a/packages/instant/src/util/analytics.ts +++ b/packages/instant/src/util/analytics.ts @@ -48,12 +48,6 @@ export interface AnalyticsEventOptions { gitSha?: string; npmVersion?: string; } -export interface AccountReadyEventProperties { - address: string; -} -export interface AccountAddressChangedEventProperties { - address: string; -} export const analytics = { addUserProperties: (properties: AnalyticsUserOptions): void => { @@ -68,10 +62,9 @@ export const analytics = { }, trackInstantOpened: trackingEventFnWithoutPayload(EventNames.INSTANT_OPENED), trackAccountLocked: trackingEventFnWithoutPayload(EventNames.ACCOUNT_LOCKED), - trackAccountReady: (eventProperties: AccountReadyEventProperties) => - trackingEventFnWithPayload(EventNames.ACCOUNT_READY)({ ...eventProperties }), + trackAccountReady: (address: string) => trackingEventFnWithPayload(EventNames.ACCOUNT_READY)({ address }), trackAccountUnlockRequested: trackingEventFnWithoutPayload(EventNames.ACCOUNT_UNLOCK_REQUESTED), trackAccountUnlockDenied: trackingEventFnWithoutPayload(EventNames.ACCOUNT_UNLOCK_DENIED), - trackAccountAddressChanged: (eventProperties: AccountAddressChangedEventProperties) => - trackingEventFnWithPayload(EventNames.ACCOUNT_ADDRESS_CHANGED)({ ...eventProperties }), + trackAccountAddressChanged: (address: string) => + trackingEventFnWithPayload(EventNames.ACCOUNT_ADDRESS_CHANGED)({ address }), }; -- cgit v1.2.3 From b1474973cd2995903c5b353b2b155eeef6b16643 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Fri, 23 Nov 2018 14:48:49 +0100 Subject: Copy assets in referenced in instant on commonjs build --- packages/instant/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'packages/instant') diff --git a/packages/instant/package.json b/packages/instant/package.json index d3a85a646..9616af54f 100644 --- a/packages/instant/package.json +++ b/packages/instant/package.json @@ -11,7 +11,7 @@ "build": "yarn build:all", "build:all": "run-p build:umd:prod build:commonjs", "build:umd:prod": "webpack --mode production", - "build:commonjs": "tsc -b", + "build:commonjs": "tsc -b && shx cp -r src/assets lib", "build:ci": "yarn build", "watch_without_deps": "tsc -w", "dev": "webpack-dev-server --mode development", -- cgit v1.2.3 From ebc31169094e17b17a0968ad2e5f1d2eb014a698 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Mon, 26 Nov 2018 14:09:24 +0100 Subject: Revert "[@0x/instant] Fix CI build broken by instant installation tests" --- packages/instant/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'packages/instant') diff --git a/packages/instant/package.json b/packages/instant/package.json index 9616af54f..d3a85a646 100644 --- a/packages/instant/package.json +++ b/packages/instant/package.json @@ -11,7 +11,7 @@ "build": "yarn build:all", "build:all": "run-p build:umd:prod build:commonjs", "build:umd:prod": "webpack --mode production", - "build:commonjs": "tsc -b && shx cp -r src/assets lib", + "build:commonjs": "tsc -b", "build:ci": "yarn build", "watch_without_deps": "tsc -w", "dev": "webpack-dev-server --mode development", -- cgit v1.2.3