- import(/* webpackChunkName: "NotFoundPage" */ './go-to-beta'),
+ loader: () => import(/* webpackChunkName: "GoToBetaPage" */ './go-to-beta'),
loading: Loading,
delay: LOADABLE_DELAY
})
-
const accountCreated = connectedRouterRedirect({
redirectPath: state =>
- !state.account.encryptedBackupPhrase ?
- // Not signed in
- '/sign-up' :
- // Storage failed to connect
- '/connect-storage',
- authenticatedSelector: (state, props) => !!props.location.query.echo ||
+ !state.account.encryptedBackupPhrase
+ ? // Not signed in
+ '/sign-up'
+ : // Storage failed to connect
+ '/connect-storage',
+ authenticatedSelector: (state, props) =>
+ !!props.location.query.echo ||
// No echo param (for protocol check)
// No keyphrase
(!!state.account.encryptedBackupPhrase &&
- // Storage failed to connect
- !!state.settings.api.storageConnected),
+ // Storage failed to connect
+ !!state.settings.api.storageConnected),
wrapperDisplayName: 'AccountCreated'
})
@@ -292,19 +295,23 @@ export default (
-
-
- { /**
- * TODO: move /update back up ^^, had to move it out of the 'app' nested route
- * because when we wipe data, it wants to redirect to /sign-up
- */}
-
-
-
-
-
-
-
-
+
+
+
+
+ {/**
+ * TODO: move /update back up ^^, had to move it out of the 'app' nested route
+ * because when we wipe data, it wants to redirect to /sign-up
+ */}
+
+
+
+
+
+
+
+
+
+
)
diff --git a/app/js/sign-in/index.js b/app/js/sign-in/index.js
index 87a2eae4e..3842bca40 100644
--- a/app/js/sign-in/index.js
+++ b/app/js/sign-in/index.js
@@ -11,7 +11,7 @@ import { RegistrationActions } from '../profiles/store/registration'
import { trackEventOnce } from '@utils/server-utils'
import { Initial, Password, Success, Email } from './views'
import log4js from 'log4js'
-import { AppHomeWrapper, ShellParent } from '@blockstack/ui'
+import { ShellParent } from '@blockstack/ui'
import {
selectConnectedStorageAtLeastOnce,
selectEmail,
@@ -34,7 +34,6 @@ import {
} from '@common/store/selectors/auth'
import { AuthActions } from '../auth/store/auth'
import { formatAppManifest } from '@common'
-import App from '../App'
const CREATE_ACCOUNT_IN_PROCESS = 'createAccount/in_process'
@@ -168,34 +167,32 @@ class SignIn extends React.Component {
if (this.state.decrypt && !decrypting) {
setImmediate(() => {
- this.setState(
- { decrypting: true },
- async () => {
- try {
- const decryptedKeyBuffer = await decrypt(
- new Buffer(encryptedKey, 'base64'),
- this.state.password
- )
- const decryptedKey = decryptedKeyBuffer.toString()
- this.setState(
- {
- key: decryptedKey,
- decrypting: false,
- restoreError: null
- },
- () => {
- this.updateView(VIEWS.EMAIL)
- }
- )
- } catch (e) {
- logger.debug(e)
- this.setState({
+ this.setState({ decrypting: true }, async () => {
+ try {
+ const decryptedKeyBuffer = await decrypt(
+ new Buffer(encryptedKey, 'base64'),
+ this.state.password
+ )
+ const decryptedKey = decryptedKeyBuffer.toString()
+ this.setState(
+ {
+ key: decryptedKey,
decrypting: false,
- restoreError: 'Incorrect password or invalid recovery code',
- key: ''
- })
- }
- })
+ restoreError: null
+ },
+ () => {
+ this.updateView(VIEWS.EMAIL)
+ }
+ )
+ } catch (e) {
+ logger.debug(e)
+ this.setState({
+ decrypting: false,
+ restoreError: 'Incorrect password or invalid recovery code',
+ key: ''
+ })
+ }
+ })
})
} else {
this.updateView(VIEWS.EMAIL)
@@ -419,15 +416,14 @@ class SignIn extends React.Component {
...currentViewProps.props
}
return (
-
+ <>
-
-
+ >
)
}
}
diff --git a/app/js/sign-out/index.js b/app/js/sign-out/index.js
new file mode 100644
index 000000000..6028bcdd8
--- /dev/null
+++ b/app/js/sign-out/index.js
@@ -0,0 +1,49 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import { withRouter } from 'react-router'
+import Initial from './views/initial'
+import { ShellParent } from '@blockstack/ui'
+
+const VIEWS = {
+ INITIAL: 0
+}
+
+const views = [Initial]
+
+const SignOut = ({ location }) => {
+ const view = 0
+
+ const viewProps = [
+ {
+ show: VIEWS.INITIAL,
+ props: {
+ backLabel: 'Cancel'
+ }
+ }
+ ]
+
+ const currentViewProps = viewProps.find(v => v.show === view) || {}
+
+ const componentProps = {
+ view,
+ backView: () => null,
+ location,
+ ...currentViewProps.props
+ }
+ return (
+ <>
+
+ >
+ )
+}
+
+SignOut.propTypes = {
+ location: PropTypes.object,
+ router: PropTypes.object
+}
+
+export default withRouter(SignOut)
diff --git a/app/js/sign-out/views/initial.js b/app/js/sign-out/views/initial.js
new file mode 100644
index 000000000..9991dceb2
--- /dev/null
+++ b/app/js/sign-out/views/initial.js
@@ -0,0 +1,90 @@
+import React, { useState } from 'react'
+import { ShellScreen, Type } from '@blockstack/ui'
+import { Box } from 'blockstack-ui'
+import PropTypes from 'prop-types'
+
+const InitialSignOutScreen = ({ location, ...rest }) => {
+ const [hasAttempted, setAttempted] = useState(false)
+ const [loading, setLoading] = useState(false)
+
+ const handleResetClick = () => {
+ if (!hasAttempted) {
+ setAttempted(true)
+ } else {
+ setLoading(true)
+ localStorage.clear()
+ window.location =
+ location.query && location.query.redirect_uri
+ ? `${location.query.redirect_uri}://?authCleared=1`
+ : '/sign-up'
+ }
+ }
+
+ const handleCancelClick = () => {
+ window.location =
+ location.query && location.query.redirect_uri
+ ? `${location.query.redirect_uri}://?authCleared=0`
+ : '/sign-up'
+ }
+
+ const screen = {
+ title: {
+ children: 'Sign Out'
+ },
+ content: {
+ grow: 1,
+ children: (
+ <>
+
+
+ Warning: This will erase your account data on
+ this device. You’ll have to restore your account or create a new
+ one afterwards.
+
+
+
+ If you plan to restore your account, make sure you have recorded
+ your backup information: you will either need your{' '}
+ 12 word secret recovery key , or your{' '}
+ magic recovery code and password to do so.
+
+ >
+ )
+ },
+ actions: {
+ items: [
+ {
+ label: hasAttempted ? (
+ <>Press Again to Confirm>
+ ) : (
+ <>Reset my Device>
+ ),
+ loading,
+ disabled: loading,
+ primary: true,
+ onClick: handleResetClick
+ },
+ {
+ label: <>Cancel>,
+ primary: false,
+ onClick: handleCancelClick
+ }
+ ]
+ }
+ }
+
+ return
+}
+
+InitialSignOutScreen.propTypes = {
+ location: PropTypes.object,
+ value: PropTypes.string
+}
+
+export default InitialSignOutScreen
diff --git a/app/js/sign-up/index.js b/app/js/sign-up/index.js
index 22c781c16..07aef6961 100644
--- a/app/js/sign-up/index.js
+++ b/app/js/sign-up/index.js
@@ -2,7 +2,6 @@ import React from 'react'
import PropTypes from 'prop-types'
import { browserHistory, withRouter } from 'react-router'
import { decodeToken } from 'jsontokens'
-import App from '../App'
import {
selectConnectedStorageAtLeastOnce,
selectEmail,
@@ -41,7 +40,7 @@ import { sendRestoreEmail as sendEmail } from '@utils/email-utils'
import queryString from 'query-string'
import log4js from 'log4js'
import { formatAppManifest } from '@common'
-import { ShellParent, AppHomeWrapper } from '@blockstack/ui'
+import { ShellParent } from '@blockstack/ui'
import {
Initial,
Email,
@@ -98,7 +97,8 @@ const VIEW_EVENTS = {
// Allow the front-end (for example Selenium tests or dev console) to override the subdomain suffix.
const DEFAULT_SUBDOMAIN_SUFFIX = 'id.blockstack'
-const getSubdomainSuffix = () => window.SUBDOMAIN_SUFFIX_OVERRIDE || DEFAULT_SUBDOMAIN_SUFFIX
+const getSubdomainSuffix = () =>
+ window.SUBDOMAIN_SUFFIX_OVERRIDE || DEFAULT_SUBDOMAIN_SUFFIX
const mapStateToProps = state => ({
localIdentities: selectLocalIdentities(state),
@@ -188,7 +188,11 @@ class Onboarding extends React.Component {
*/
submitPassword = async () => {
const decodedAuthRequest = this.getDecodedAuthRequest()
- if (decodedAuthRequest && (decodedAuthRequest.solicitGaiaHubUrl || decodedAuthRequest.recommendedGaiaHub)) {
+ if (
+ decodedAuthRequest &&
+ (decodedAuthRequest.solicitGaiaHubUrl ||
+ decodedAuthRequest.recommendedGaiaHub)
+ ) {
if (decodedAuthRequest.recommendedGaiaHubUrl) {
this.updateView(VIEWS.RECOMMENDED_GAIA_HUB)
} else {
@@ -230,16 +234,19 @@ class Onboarding extends React.Component {
submitRecommendedGaiaHub = async () => {
const decodedAuthRequest = this.getDecodedAuthRequest()
- this.setState({
- loading: true,
- hubURL: decodedAuthRequest.recommendedGaiaHubUrl
- }, async () => {
- const success = await this.validateGaiaURL()
- if (success) {
- await this.createAccount()
- this.updateView(VIEWS.EMAIL)
+ this.setState(
+ {
+ loading: true,
+ hubURL: decodedAuthRequest.recommendedGaiaHubUrl
+ },
+ async () => {
+ const success = await this.validateGaiaURL()
+ if (success) {
+ await this.createAccount()
+ this.updateView(VIEWS.EMAIL)
+ }
}
- })
+ )
}
/**
@@ -596,7 +603,14 @@ class Onboarding extends React.Component {
render() {
const { appManifest } = this.props
- const { email, password, username, emailSubmitted, view, decodedAuthRequest } = this.state
+ const {
+ email,
+ password,
+ username,
+ emailSubmitted,
+ view,
+ decodedAuthRequest
+ } = this.state
const app = formatAppManifest(appManifest)
@@ -688,7 +702,8 @@ class Onboarding extends React.Component {
{
show: VIEWS.RECOMMENDED_GAIA_HUB,
props: {
- recommendedGaiaHubUrl: decodedAuthRequest && decodedAuthRequest.recommendedGaiaHubUrl,
+ recommendedGaiaHubUrl:
+ decodedAuthRequest && decodedAuthRequest.recommendedGaiaHubUrl,
updateValue: this.updateValue,
next: () => this.submitRecommendedGaiaHub(),
customHub: () => this.updateView(VIEWS.CUSTOMHUB),
@@ -715,7 +730,7 @@ class Onboarding extends React.Component {
}
return (
-
+ <>
-
-
+ >
)
}
}
diff --git a/package.json b/package.json
index f3e147f94..fb4f5fe7f 100644
--- a/package.json
+++ b/package.json
@@ -13,12 +13,12 @@
"bootstrap": "^4.0.0-beta",
"browser-stdout": "^1.3.0",
"chroma-js": "^1.3.7",
- "clean-tag": "^2.0.0",
- "core-js": "^2.5.7",
+ "clean-tag": "^2.0.3",
+ "core-js": "^2.6.4",
"cors-anywhere": "^0.4.1",
"currency-formatter": "^1.2.1",
"ecurve": "^1.0.4",
- "enzyme-adapter-react-16": "^1.2.0",
+ "enzyme-adapter-react-16": "^1.9.1",
"formik": "^1.4.2",
"hash-handler": "^1.5.1",
"inert-polyfill": "^0.2.5",
@@ -27,23 +27,23 @@
"jsontokens": "^0.7.8",
"lodash": "^4.17.10",
"log4js": "^3.0.4",
- "mdi-react": "^3.3.0",
- "memoize-one": "^3.1.1",
- "polished": "^1.9.2",
- "prop-types": "^15.6.0",
+ "mdi-react": "^5.2.0",
+ "memoize-one": "^5.0.0",
+ "polished": "^2.3.3",
+ "prop-types": "^15.7.1",
"qrcode.react": "^0.8.0",
"query-string": "^4.2.3",
- "react": "^16.7.0",
+ "react": "^16.8.1",
"react-addons-css-transition-group": "^15.6.2",
"react-contextmenu": "^2.8.0",
"react-copy-to-clipboard": "^5.0.1",
- "react-dom": "^16.7.0",
+ "react-dom": "^16.8.1",
"react-fns": "^1.4.0",
"react-loadable": "^5.5.0",
"react-modal": "^3.1.12",
"react-powerplug": "^1.0.0-rc.1",
"react-qr-reader": "^2.1.2",
- "react-qr-svg": "^2.0.1",
+ "react-qr-svg": "^2.2.1",
"react-redux": "^4.4.8",
"react-router": "^3.0.0",
"react-spring": "^5.1.2",
@@ -60,7 +60,7 @@
"round-to": "^2.0.0",
"styled-components": "^4.1.3",
"styled-system": "^3.2.1",
- "system-components": "^3.0.1",
+ "system-components": "^3.0.3",
"triplesec": "^3.0.25",
"yup": "^0.24.1",
"zone-file": "^0.2.2"
@@ -79,7 +79,7 @@
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.0.0",
"@babel/plugin-proposal-numeric-separator": "^7.0.0",
"@babel/plugin-proposal-optional-chaining": "^7.0.0",
- "@babel/plugin-proposal-pipeline-operator": "^7.3.0",
+ "@babel/plugin-proposal-pipeline-operator": "^7.3.2",
"@babel/plugin-proposal-throw-expressions": "^7.0.0",
"@babel/plugin-syntax-dynamic-import": "^7.0.0",
"@babel/plugin-syntax-import-meta": "^7.0.0",
@@ -94,7 +94,7 @@
"babel-loader": "^8.0.5",
"babel-plugin-dynamic-import-node": "^2.1.0",
"babel-plugin-lodash": "^3.3.2",
- "babel-plugin-module-resolver": "^3.1.3",
+ "babel-plugin-module-resolver": "^3.2.0",
"babel-plugin-rewire": "^1.2.0",
"babel-plugin-styled-components": "^1.10.0",
"browserstack-local": "^1.3.7",
@@ -105,12 +105,12 @@
"cross-env": "^5.2.0",
"css-loader": "^2.1.1",
"enzyme": "^3.3.0",
- "eslint": "^5.12.1",
+ "eslint": "^5.13.0",
"eslint-config-airbnb": "^9.0.1",
"eslint-config-prettier": "^2.9.0",
- "eslint-import-resolver-babel-module": "^5.0.0-beta.1",
+ "eslint-import-resolver-babel-module": "^5.0.1",
"eslint-plugin-flowtype": "^2.39.1",
- "eslint-plugin-import": "^2.15.0",
+ "eslint-plugin-import": "^2.16.0",
"eslint-plugin-jsx-a11y": "^1.2.2",
"eslint-plugin-react": "^5.1.1",
"express": "^4.16.4",
@@ -133,8 +133,8 @@
"node-libs-browser": "^1.0.0",
"nyc": "^14.1.0",
"p-queue": "^3.0.0",
- "prettier": "^1.16.1",
- "react-hot-loader": "^4.3.3",
+ "prettier": "^1.16.4",
+ "react-hot-loader": "^4.6.5",
"redux-mock-store": "^1.2.3",
"request": "^2.88.0",
"require-hacker": "^3.0.1",
@@ -145,9 +145,9 @@
"sinon": "^1.17.7",
"sinon-as-promised": "^4.0.0",
"style-loader": "^0.23.0",
- "terser-webpack-plugin": "^1.2.1",
+ "terser-webpack-plugin": "^1.2.2",
"url-loader": "^1.0.1",
- "webpack": "^4.29.0",
+ "webpack": "^4.29.3",
"webpack-bundle-analyzer": "^3.3.2",
"webpack-cli": "^3.3.2",
"webpack-dev-server": "^3.3.1",
diff --git a/test/components/Navbar.test.js b/test/components/Navbar.test.js
deleted file mode 100644
index 412226e8a..000000000
--- a/test/components/Navbar.test.js
+++ /dev/null
@@ -1,62 +0,0 @@
-import React from 'react'
-import { expect } from 'chai'
-import { shallow } from 'enzyme'
-import Navbar, { ICONS } from '../../app/js/components/Navbar'
-
-describe('
', () => {
- describe('renders the component', () => {
- const wrapper = shallow(
)
-
- it('creates four
tags', () => {
- expect(wrapper.find('Link')).to.have.length(4)
- })
- })
-
- const tabDetails = [
- {
- name: 'home',
- activeIcon: ICONS.homeNavActive,
- regularIcon: ICONS.homeNav
- },
- {
- name:'settings',
- activeIcon: ICONS.settingsNavActive,
- regularIcon: ICONS.settingsNav
- },
- {
- name:'wallet',
- activeIcon: ICONS.walletNavActive,
- regularIcon: ICONS.walletNav
- },
- {
- name: 'profile',
- prop: 'avatar',
- activeIcon: ICONS.avatarNavActive,
- regularIcon: ICONS.avatarNav
- }]
-
- tabDetails.forEach((tab) => {
- describe(
- `renders the component with active ${tab.name} tab`, () => {
- const props = {
- activeTab: tab.prop || tab.name
- }
-
- const wrapper = shallow(
)
-
- it(`uses the active ${tab.name} tab icon`, () => {
- expect(wrapper.find(`img[src="${tab.activeIcon}"]`)
- .exists()).to.equal(true)
- })
-
- const tabs = tabDetails.filter(temp => temp.name !== tab.name)
-
- tabs.forEach((innerLoopTab) => {
- it(`uses the regular ${innerLoopTab.name} tab icon`, () => {
- expect(wrapper.find(`img[src="${innerLoopTab.regularIcon}"]`)
- .exists()).to.equal(true)
- })
- })
- })
- })
-})
diff --git a/test/components/Navigation.test.js b/test/components/Navigation.test.js
deleted file mode 100644
index 83b3e840c..000000000
--- a/test/components/Navigation.test.js
+++ /dev/null
@@ -1,35 +0,0 @@
-import React from 'react'
-import { expect } from 'chai'
-import { shallow } from 'enzyme'
-import Navigation from '../../app/js/components/Navigation'
-
-describe('
', () => {
- describe('renders the component', () => {
- const props = {
- previous() {}
- }
-
- const wrapper = shallow(
)
-
- it('uses a ChevronLeftIcon', () => {
- expect(wrapper.find('ChevronLeftIcon').exists()).to.equal(true)
- })
-
- it('includes the previous label', () => {
- expect(wrapper.html()).to.contain('Back')
- })
- })
-
- describe('renders the component with a label', () => {
- const props = {
- previous() {},
- previousLabel: 'Previous Page'
- }
-
- const wrapper = shallow(
)
-
- it('includes the supplied label', () => {
- expect(wrapper.html()).to.contain('Previous Page')
- })
- })
-})