From ddc697023e177b07b3393d8e96cfde001a59ee37 Mon Sep 17 00:00:00 2001 From: Thomas Osmonson Date: Wed, 13 Feb 2019 10:57:58 -0600 Subject: [PATCH 01/16] update react, react-dom --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 5f5dd5061..6b8c8383f 100644 --- a/package.json +++ b/package.json @@ -32,11 +32,11 @@ "prop-types": "^15.6.0", "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", From 53499f97aa8337f8a99f2ba45076872979e5a1ef Mon Sep 17 00:00:00 2001 From: Thomas Osmonson Date: Wed, 13 Feb 2019 11:47:00 -0600 Subject: [PATCH 02/16] refactor Navbar --- app/js/components/Navbar.js | 302 +++++++++++++++--------------------- package.json | 47 +++--- 2 files changed, 146 insertions(+), 203 deletions(-) diff --git a/app/js/components/Navbar.js b/app/js/components/Navbar.js index d82d225bc..1be96fae4 100644 --- a/app/js/components/Navbar.js +++ b/app/js/components/Navbar.js @@ -1,184 +1,126 @@ -import PropTypes from 'prop-types' -import React, { Component } from 'react' -import { Link } from 'react-router' - -/* eslint-disable global-require */ -export const ICONS = { - homeNav: require('@images/icon-nav-home.svg'), - homeNavActive: require('@images/icon-nav-home-hover.svg'), - walletNav: require('@images/icon-nav-wallet.svg'), - walletNavActive: require('@images/icon-nav-wallet-hover.svg'), - avatarNav: require('@images/icon-nav-profile.svg'), - avatarNavActive: require('@images/icon-nav-profile-hover.svg'), - settingsNav: require('@images/icon-nav-settings.svg'), - settingsNavActive: require('@images/icon-nav-settings-hover.svg') -} -/* eslint-enable global-require */ - -class Navbar extends Component { - static propTypes = { - activeTab: PropTypes.string - } - - constructor(props) { - super(props) - this.onHomeNavMouseOver = this.onHomeNavMouseOver.bind(this) - this.onHomeNavMouseOut = this.onHomeNavMouseOut.bind(this) - this.onWalletNavMouseOver = this.onWalletNavMouseOver.bind(this) - this.onWalletNavMouseOut = this.onWalletNavMouseOut.bind(this) - this.onAvatarNavMouseOver = this.onAvatarNavMouseOver.bind(this) - this.onAvatarNavMouseOut = this.onAvatarNavMouseOut.bind(this) - this.onSettingsNavMouseOver = this.onSettingsNavMouseOver.bind(this) - this.onSettingsNavMouseOut = this.onSettingsNavMouseOut.bind(this) - - this.state = { - homeTabHover: false, - walletTabHover: false, - avatarTabHover: false, - settingsTabHover: false +import React from 'react' +import HomeIcon from 'mdi-react/AppsIcon' +import IDsIcon from 'mdi-react/AccountCircleIcon' +import WalletIcon from 'mdi-react/WalletIcon' +import SettingsIcon from 'mdi-react/SettingsIcon' +import { Hover, Focus } from 'react-powerplug' +import { Box, Flex, Type } from 'blockstack-ui' +import { Link, withRouter } from 'react-router' + +const sections = [ + [ + { + label: 'Home', + icon: HomeIcon, + path: '/', + active: '/' } - } - - onHomeNavMouseOver() { - this.setState({ homeTabHover: true }) - } - - onHomeNavMouseOut() { - this.setState({ homeTabHover: false }) - } - - onWalletNavMouseOver() { - this.setState({ walletTabHover: true }) - } - - onWalletNavMouseOut() { - this.setState({ walletTabHover: false }) - } - - onAvatarNavMouseOver() { - this.setState({ avatarTabHover: true }) - } - - onAvatarNavMouseOut() { - this.setState({ avatarTabHover: false }) - } - - onSettingsNavMouseOver() { - this.setState({ settingsTabHover: true }) - } - - onSettingsNavMouseOut() { - this.setState({ settingsTabHover: false }) - } - - settingsNavIconImage() { - if (this.props.activeTab === 'settings' || this.state.settingsTabHover) { - return ICONS.settingsNavActive - } else { - return ICONS.settingsNav - } - } - - homeNavIconImage() { - if (this.props.activeTab === 'home' || this.state.homeTabHover) { - return ICONS.homeNavActive - } else { - return ICONS.homeNav - } - } - - walletNavIconImage() { - if (this.props.activeTab === 'wallet' || this.state.walletTabHover) { - return ICONS.walletNavActive - } else { - return ICONS.walletNav - } - } - - avatarNavIconImage() { - if (this.props.activeTab === 'avatar' || this.state.avatarTabHover) { - return ICONS.avatarNavActive - } else { - return ICONS.avatarNav + ], + [ + { + label: 'Identity', + icon: IDsIcon, + path: '/profiles', + active: 'profiles' + }, + { + label: 'Wallet', + icon: WalletIcon, + path: '/wallet/receive', + active: 'wallet' + }, + { + label: 'Settings', + icon: SettingsIcon, + path: '/account', + active: 'account' } - } - - render() { - const homeActive = - this.props.activeTab === 'home' || this.state.homeTabHover - const avatarActive = - this.props.activeTab === 'avatar' || this.state.avatarTabHover - const walletActive = - this.props.activeTab === 'wallet' || this.state.walletTabHover - const settingsActive = - this.props.activeTab === 'settings' || this.state.settingsTabHover - - return ( -
- -
- ) - } -} + ] +] + +const Wrapper = ({ ...rest }) => ( + +) + +const Icon = ({ component: Component, ...rest }) => ( + + + +) + +const Label = ({ children, ...rest }) => ( + + {children} + +) + +const NavItem = ({ label, icon, path, active, ...rest }) => ( + + + {({ focused, bind: focusBind }) => ( + + {({ hovered, bind }) => ( + + + + + )} + + )} + + +) + +const Navbar = withRouter(({ location }) => ( + + + {sections.map((section, i) => ( + + {section.map(({ label, icon, path, active }) => ( + + ))} + + ))} + + +)) export default Navbar diff --git a/package.json b/package.json index 6b8c8383f..9b46b767c 100644 --- a/package.json +++ b/package.json @@ -7,17 +7,18 @@ "bigi": "^1.4.2", "bip39": "^2.2.0", "bitcoinjs-lib": "^3.2.0", - "blockstack": "^18.2.1", + "blockstack": "^18.3.0", + "blockstack-ui": "^0.0.71", "body-parser": "^1.16.1", "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", @@ -26,10 +27,10 @@ "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.8.1", @@ -42,7 +43,7 @@ "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", @@ -59,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" @@ -78,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", @@ -93,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", "chai": "^3.5.0", @@ -102,12 +103,12 @@ "cross-env": "^5.2.0", "css-loader": "^0.28.11", "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.13.4", @@ -125,21 +126,21 @@ "mock-require": "^3.0.2", "nock": "^9.0.13", "node-libs-browser": "^1.0.0", - "nyc": "^13.0.1", - "prettier": "^1.16.1", - "react-hot-loader": "^4.3.3", + "nyc": "^13.2.0", + "prettier": "^1.16.4", + "react-hot-loader": "^4.6.5", "redux-mock-store": "^1.2.3", "require-hacker": "^3.0.1", - "serve": "^10.0.1", + "serve": "^10.1.2", "shx": "^0.3.2", "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-bundle-analyzer": "^3.0.2", - "webpack-cli": "^3.2.1", + "webpack": "^4.29.3", + "webpack-bundle-analyzer": "^3.0.4", + "webpack-cli": "^3.2.3", "webpack-dev-server": "^3.1.14", "webpack-stylish": "^0.1.8", "webpackbar": "^3.1.5", From 04399aa3d9c0e566fcd249627f654d5332404cc9 Mon Sep 17 00:00:00 2001 From: Thomas Osmonson Date: Wed, 13 Feb 2019 11:51:17 -0600 Subject: [PATCH 03/16] zindex --- app/js/components/Navbar.js | 1 + 1 file changed, 1 insertion(+) diff --git a/app/js/components/Navbar.js b/app/js/components/Navbar.js index 1be96fae4..8c998b734 100644 --- a/app/js/components/Navbar.js +++ b/app/js/components/Navbar.js @@ -100,6 +100,7 @@ const Navbar = withRouter(({ location }) => ( position="fixed" top={0} width={1} + zIndex={999} > {sections.map((section, i) => ( From 9b871f7b7b379d4cae5a3e6f33f37b4595f7cc14 Mon Sep 17 00:00:00 2001 From: Thomas Osmonson Date: Wed, 13 Feb 2019 12:17:30 -0600 Subject: [PATCH 04/16] fix aspect ratio of avatars, fixes #1624 --- app/js/components/ui/containers/user.js | 30 +++++++++++++++---------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/app/js/components/ui/containers/user.js b/app/js/components/ui/containers/user.js index bfb6aef23..a1a4d4b5b 100644 --- a/app/js/components/ui/containers/user.js +++ b/app/js/components/ui/containers/user.js @@ -5,7 +5,7 @@ import { User } from '@blockstack/ui/components/user' import CheckIcon from 'mdi-react/CheckIcon' import ChevronRightIcon from 'mdi-react/ChevronRightIcon' import Image from '@components/Image' -import { Flex } from '@components/ui/components/primitives' +import { Flex } from 'blockstack-ui' const UserAvatar = ({ id, @@ -13,7 +13,7 @@ const UserAvatar = ({ size = 46, camera, textSize = 14, - avatarUrl = '', + avatarUrl, ...rest }) => ( {avatarUrl ? ( - ) : ( @@ -67,7 +67,12 @@ const UserButton = ({ username, id, hideID, avatarUrl, ...rest }) => ( cd maxWidth="calc(100% - 102px) !important" > - + {username.includes('.') ? ( <> @@ -85,8 +90,9 @@ const UserButton = ({ username, id, hideID, avatarUrl, ...rest }) => ( {username} )} - {id && - !hideID && {id}} + {id && !hideID && ( + {id} + )} Date: Wed, 13 Feb 2019 16:00:22 -0600 Subject: [PATCH 05/16] clear-auth is now sign-out, redirect on devices, resolves #1799 --- app/js/clear-auth/index.js | 80 ---------------------------- app/js/routes.js | 55 +++++++++++-------- app/js/sign-out/index.js | 51 ++++++++++++++++++ app/js/sign-out/views/initial.js | 90 ++++++++++++++++++++++++++++++++ 4 files changed, 173 insertions(+), 103 deletions(-) delete mode 100644 app/js/clear-auth/index.js create mode 100644 app/js/sign-out/index.js create mode 100644 app/js/sign-out/views/initial.js diff --git a/app/js/clear-auth/index.js b/app/js/clear-auth/index.js deleted file mode 100644 index a957da064..000000000 --- a/app/js/clear-auth/index.js +++ /dev/null @@ -1,80 +0,0 @@ -import React, { PureComponent } from 'react' -import { withRouter } from 'react-router' -import App from '../App' - -class ClearAuthPage extends PureComponent { - state = { - countdown: 5, - hasAttemptedConfirm: false - } - - componentDidMount() { - this.decrementCountdown() - } - - decrementCountdown() { - setTimeout(() => { - const { countdown } = this.state - this.setState({ countdown: countdown - 1 }) - if (countdown > 1) { - this.decrementCountdown() - } - }, 1000) - } - - clearData = () => { - if (this.state.hasAttemptedConfirm) { - localStorage.clear() - window.location = `${this.props.location.query.redirect_uri}://?authCleared=1` - } - else { - this.setState({ hasAttemptedConfirm: true }) - } - } - - cancel = () => { - window.location = `${this.props.location.query.redirect_uri}://?authCleared=0` - } - - render() { - const { countdown, hasAttemptedConfirm } = this.state - - return ( - -
-

Sign Out

-

- Warning: This will reset your account on this device. - You’ll be able 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. -

-
- -
-
- -
-
-
- ) - } -} - -export default withRouter(ClearAuthPage) diff --git a/app/js/routes.js b/app/js/routes.js index 991ac29ad..b2783bd7c 100644 --- a/app/js/routes.js +++ b/app/js/routes.js @@ -2,25 +2,33 @@ import React from 'react' import { browserHistory, IndexRoute, Route, Router } from 'react-router' import Loadable from 'react-loadable' import App from './App' -import ClearAuthPage from './clear-auth' +import SignOutPage from './sign-out' import ConnectStoragePage from './connect-storage' import { connectedRouterRedirect } from 'redux-auth-wrapper/history3/redirect' const LOADABLE_DELAY = 300 -const Loading = (props) => { +const Loading = props => { if (props.error) { - return
Error!
+ return ( +
+ Error! +
+ ) } else if (props.pastDelay) { - return (
Loading...
) + return ( +
+ Loading... +
+ ) } return null } @@ -220,20 +228,20 @@ const NotFoundPage = Loadable({ 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' }) @@ -283,7 +291,7 @@ 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 */} @@ -292,7 +300,8 @@ export default ( - + + ) diff --git a/app/js/sign-out/index.js b/app/js/sign-out/index.js new file mode 100644 index 000000000..48d942acc --- /dev/null +++ b/app/js/sign-out/index.js @@ -0,0 +1,51 @@ +import React from 'react' +import PropTypes from 'prop-types' +import { withRouter } from 'react-router' +import Initial from './views/initial' +import { AppHomeWrapper, ShellParent } from '@blockstack/ui' +import App from '../App' + +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 From ddbb7061a800e3675cdb611ec085d3c344be0c12 Mon Sep 17 00:00:00 2001 From: Thomas Osmonson Date: Tue, 19 Feb 2019 10:15:48 -0600 Subject: [PATCH 06/16] initial fixes and changes to remove blurred apps --- app/js/App.js | 1 + .../components/ui/components/shell/index.js | 2 +- .../ui/containers/AppHomeWrapper.js | 9 +++++- app/js/routes.js | 30 ++++++++++--------- app/js/sign-in/index.js | 5 ++-- app/js/sign-out/index.js | 5 ++-- app/js/sign-up/index.js | 5 ++-- 7 files changed, 32 insertions(+), 25 deletions(-) diff --git a/app/js/App.js b/app/js/App.js index 8257ac2e6..c8f72f38f 100644 --- a/app/js/App.js +++ b/app/js/App.js @@ -20,6 +20,7 @@ import Modal from 'react-modal' import NotificationsSystem from 'reapop' import NotificationsTheme from 'reapop-theme-wybo' import { hot } from 'react-hot-loader' +import { AppHomeWrapper } from '@blockstack/ui' import log4js from 'log4js' diff --git a/app/js/components/ui/components/shell/index.js b/app/js/components/ui/components/shell/index.js index 17f306d35..1e310b183 100644 --- a/app/js/components/ui/components/shell/index.js +++ b/app/js/components/ui/components/shell/index.js @@ -150,7 +150,7 @@ const StyledShell = styled.div` width: 100%; z-index: 9001; background-color: ${({ width }) => - width <= 599 ? 'white' : 'rgba(240, 240, 240, 0.8)'}; + width <= 599 ? 'white' : 'rgba(240, 240, 240, 0.85)'}; ${({ maxHeight }) => maxHeight && css` diff --git a/app/js/components/ui/containers/AppHomeWrapper.js b/app/js/components/ui/containers/AppHomeWrapper.js index 8ff523265..e18ddfa0f 100644 --- a/app/js/components/ui/containers/AppHomeWrapper.js +++ b/app/js/components/ui/containers/AppHomeWrapper.js @@ -1,6 +1,7 @@ import React from 'react' import styled from 'styled-components' import { WindowSize } from 'react-fns' +import { Box } from 'blockstack-ui' import HomePage from '../../../HomeScreenPage' const StyledAppHomeWrapper = styled.div.attrs({ @@ -34,7 +35,13 @@ const AppHomeWrapper = props => ( width > 599 ? (
- + +
) : null diff --git a/app/js/routes.js b/app/js/routes.js index b2783bd7c..951b20346 100644 --- a/app/js/routes.js +++ b/app/js/routes.js @@ -289,19 +289,21 @@ 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 edb6fdd73..493f1cf26 100644 --- a/app/js/sign-in/index.js +++ b/app/js/sign-in/index.js @@ -415,15 +415,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 index 48d942acc..4cb0d6f27 100644 --- a/app/js/sign-out/index.js +++ b/app/js/sign-out/index.js @@ -32,14 +32,13 @@ const SignOut = ({ location }) => { ...currentViewProps.props } return ( - + <> - - + ) } diff --git a/app/js/sign-up/index.js b/app/js/sign-up/index.js index 008f020e1..a1b6dce18 100644 --- a/app/js/sign-up/index.js +++ b/app/js/sign-up/index.js @@ -711,7 +711,7 @@ class Onboarding extends React.Component { } return ( - + <> - - + ) } } From 6048e350b8f178aa142af54512726de9676e495d Mon Sep 17 00:00:00 2001 From: Thomas Osmonson Date: Wed, 6 Mar 2019 18:01:49 -0600 Subject: [PATCH 07/16] add back in apps --- .../components/ui/containers/shell-parent.js | 50 ++++++++++--------- 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/app/js/components/ui/containers/shell-parent.js b/app/js/components/ui/containers/shell-parent.js index 813e706a2..2845ad3bc 100644 --- a/app/js/components/ui/containers/shell-parent.js +++ b/app/js/components/ui/containers/shell-parent.js @@ -5,6 +5,8 @@ import { Shell } from '@ui/containers/shell' import { Header } from '@ui/containers/headers' import { Transition } from 'react-spring' import { WindowSize } from 'react-fns' +import { AppHomeWrapper } from '@components/ui/containers/AppHomeWrapper' + const ShellContext = React.createContext() /** @@ -87,10 +89,7 @@ class ShellParent extends React.Component { const internalBackLabel = backLabel !== '' ? backLabel : 'Back' const defaultBackLabel = isFirstView ? backLabel : internalBackLabel - const label = - backLabel === '' && isFirstView && app - ? `` - : defaultBackLabel + const label = backLabel === '' && isFirstView && app ? `` : defaultBackLabel const Component = views[view] @@ -132,26 +131,29 @@ class ShellParent extends React.Component { }) return ( - - {windowSize => ( - - - - -
- - {this.renderLoading(this.state.loadingProps)} - - - - - - - )} - + <> + + {windowSize => ( + + + + +
+ + {this.renderLoading(this.state.loadingProps)} + + + + + + + )} + + + ) } } From cf76156637c8e4ae558769f82a434d7ff4b61e4f Mon Sep 17 00:00:00 2001 From: Thomas Osmonson Date: Wed, 6 Mar 2019 18:11:48 -0600 Subject: [PATCH 08/16] linting fixes --- app/js/components/Navbar.js | 18 ++++++++++++ app/js/sign-in/index.js | 55 ++++++++++++++++++------------------- app/js/sign-out/index.js | 3 +- app/js/sign-up/index.js | 45 ++++++++++++++++++++---------- 4 files changed, 75 insertions(+), 46 deletions(-) diff --git a/app/js/components/Navbar.js b/app/js/components/Navbar.js index 8c998b734..2b2a29bb4 100644 --- a/app/js/components/Navbar.js +++ b/app/js/components/Navbar.js @@ -6,6 +6,7 @@ import SettingsIcon from 'mdi-react/SettingsIcon' import { Hover, Focus } from 'react-powerplug' import { Box, Flex, Type } from 'blockstack-ui' import { Link, withRouter } from 'react-router' +import PropTypes from 'prop-types' const sections = [ [ @@ -124,4 +125,21 @@ const Navbar = withRouter(({ location }) => ( )) +Icon.propTypes = { + component: PropTypes.node +} +Label.propTypes = { + children: PropTypes.node +} +NavItem.propTypes = { + label: PropTypes.any, + icon: PropTypes.any, + path: PropTypes.any, + active: PropTypes.any +} + +Navbar.propTypes = { + location: PropTypes.object.isRequired +} + export default Navbar diff --git a/app/js/sign-in/index.js b/app/js/sign-in/index.js index 197e50be8..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) diff --git a/app/js/sign-out/index.js b/app/js/sign-out/index.js index 4cb0d6f27..6028bcdd8 100644 --- a/app/js/sign-out/index.js +++ b/app/js/sign-out/index.js @@ -2,8 +2,7 @@ import React from 'react' import PropTypes from 'prop-types' import { withRouter } from 'react-router' import Initial from './views/initial' -import { AppHomeWrapper, ShellParent } from '@blockstack/ui' -import App from '../App' +import { ShellParent } from '@blockstack/ui' const VIEWS = { INITIAL: 0 diff --git a/app/js/sign-up/index.js b/app/js/sign-up/index.js index 8cec6c222..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), From 797d549d5dd781b08981351e3856acd91bff4d0c Mon Sep 17 00:00:00 2001 From: Thomas Osmonson Date: Wed, 6 Mar 2019 18:12:37 -0600 Subject: [PATCH 09/16] correct proptypes for navitem --- app/js/components/Navbar.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/js/components/Navbar.js b/app/js/components/Navbar.js index 2b2a29bb4..1e517116f 100644 --- a/app/js/components/Navbar.js +++ b/app/js/components/Navbar.js @@ -132,10 +132,10 @@ Label.propTypes = { children: PropTypes.node } NavItem.propTypes = { - label: PropTypes.any, - icon: PropTypes.any, - path: PropTypes.any, - active: PropTypes.any + label: PropTypes.string, + icon: PropTypes.node, + path: PropTypes.string, + active: PropTypes.bool } Navbar.propTypes = { From f262c4ba8d8e94b475f1a8ea396f402edb8cb067 Mon Sep 17 00:00:00 2001 From: Thomas Osmonson Date: Wed, 6 Mar 2019 18:23:53 -0600 Subject: [PATCH 10/16] navbar no proptype --- app/js/components/Navbar.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/app/js/components/Navbar.js b/app/js/components/Navbar.js index 1e517116f..32f200eb9 100644 --- a/app/js/components/Navbar.js +++ b/app/js/components/Navbar.js @@ -138,8 +138,4 @@ NavItem.propTypes = { active: PropTypes.bool } -Navbar.propTypes = { - location: PropTypes.object.isRequired -} - export default Navbar From 06ea93e7a594c6f4ae3510e380c5d3ecfca3929a Mon Sep 17 00:00:00 2001 From: Thomas Osmonson Date: Tue, 9 Apr 2019 09:11:24 -0500 Subject: [PATCH 11/16] remove navbar test --- test/components/Navbar.test.js | 62 ---------------------------------- 1 file changed, 62 deletions(-) delete mode 100644 test/components/Navbar.test.js 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) - }) - }) - }) - }) -}) From 7cb648f01c7d393e5339698a47ddaca95df960e6 Mon Sep 17 00:00:00 2001 From: Thomas Osmonson Date: Fri, 3 May 2019 12:49:11 -0500 Subject: [PATCH 12/16] add displayName for Navbar component --- app/js/components/Navbar.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/js/components/Navbar.js b/app/js/components/Navbar.js index 32f200eb9..88f15b629 100644 --- a/app/js/components/Navbar.js +++ b/app/js/components/Navbar.js @@ -138,4 +138,6 @@ NavItem.propTypes = { active: PropTypes.bool } +Navbar.displayName = 'Navbar' + export default Navbar From 7f8eecc3504c072bc9f3fbc4a7a5c7aa13e648d1 Mon Sep 17 00:00:00 2001 From: Thomas Osmonson Date: Fri, 3 May 2019 13:18:43 -0500 Subject: [PATCH 13/16] add unit test for Navbar component --- app/js/components/Navbar.js | 7 +++++-- test/components/Navbar.test.js | 36 ++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 test/components/Navbar.test.js diff --git a/app/js/components/Navbar.js b/app/js/components/Navbar.js index 88f15b629..f3c7e71e8 100644 --- a/app/js/components/Navbar.js +++ b/app/js/components/Navbar.js @@ -8,7 +8,7 @@ import { Box, Flex, Type } from 'blockstack-ui' import { Link, withRouter } from 'react-router' import PropTypes from 'prop-types' -const sections = [ +const navBarData = [ [ { label: 'Home', @@ -104,7 +104,7 @@ const Navbar = withRouter(({ location }) => ( zIndex={999} > - {sections.map((section, i) => ( + {navBarData.map((section, i) => ( {section.map(({ label, icon, path, active }) => ( ', () => { + describe('renders the component', () => { + const wrapper = shallow() + + it('creates four components', () => { + expect(wrapper.find(NavItem)).to.have.lengthOf(4) + }) + }) + + sections.forEach(section => { + describe('renders the component with each section', () => { + section.forEach(item => { + describe(`renders the component with active prop ${item.label}`, () => { + const props = { + location: { + pathname: item.path + } + } + const wrapper = shallow() + + it(`item is active, ${item.label}`, () => { + expect(wrapper.find('NavItem').prop('active')).to.have.lengthOf(1) + }) + }) + }) + }) + }) +}) From 37fdea5311269c6daa4dafe355a55937fb86d4e8 Mon Sep 17 00:00:00 2001 From: Thomas Osmonson Date: Tue, 7 May 2019 09:03:55 -0500 Subject: [PATCH 14/16] remove navbar test for now --- app/js/components/Navbar.js | 1 + test/components/Navbar.test.js | 36 ---------------------------------- 2 files changed, 1 insertion(+), 36 deletions(-) delete mode 100644 test/components/Navbar.test.js diff --git a/app/js/components/Navbar.js b/app/js/components/Navbar.js index f3c7e71e8..ea221ea18 100644 --- a/app/js/components/Navbar.js +++ b/app/js/components/Navbar.js @@ -81,6 +81,7 @@ const NavItem = ({ label, icon, path, active, ...rest }) => ( style={{ userSelect: 'none' }} is={Link} to={path} + dataTestId="NavItem" {...bind} {...focusBind} > diff --git a/test/components/Navbar.test.js b/test/components/Navbar.test.js deleted file mode 100644 index 5fdb6030c..000000000 --- a/test/components/Navbar.test.js +++ /dev/null @@ -1,36 +0,0 @@ -import React from 'react' -import { expect } from 'chai' -import { shallow } from 'enzyme' -import Navbar, { - navBarData as sections, - NavItem -} from '../../app/js/components/Navbar' - -describe('', () => { - describe('renders the component', () => { - const wrapper = shallow() - - it('creates four components', () => { - expect(wrapper.find(NavItem)).to.have.lengthOf(4) - }) - }) - - sections.forEach(section => { - describe('renders the component with each section', () => { - section.forEach(item => { - describe(`renders the component with active prop ${item.label}`, () => { - const props = { - location: { - pathname: item.path - } - } - const wrapper = shallow() - - it(`item is active, ${item.label}`, () => { - expect(wrapper.find('NavItem').prop('active')).to.have.lengthOf(1) - }) - }) - }) - }) - }) -}) From 2db9c60e292f59ef2095057884d5f75e9708a979 Mon Sep 17 00:00:00 2001 From: Hank Stoever Date: Tue, 21 May 2019 07:35:31 -0700 Subject: [PATCH 15/16] re-add packages from bad merge --- package.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/package.json b/package.json index 68bfec776..fb4f5fe7f 100644 --- a/package.json +++ b/package.json @@ -133,6 +133,8 @@ "node-libs-browser": "^1.0.0", "nyc": "^14.1.0", "p-queue": "^3.0.0", + "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", From e41a2ce28243210c5b2a20fa072d3732f2f675f8 Mon Sep 17 00:00:00 2001 From: Hank Stoever Date: Tue, 21 May 2019 13:31:56 -0700 Subject: [PATCH 16/16] removes `Navigation`, its not used --- app/js/components/Navigation.js | 56 ------------------------------ test/components/Navigation.test.js | 35 ------------------- 2 files changed, 91 deletions(-) delete mode 100644 app/js/components/Navigation.js delete mode 100644 test/components/Navigation.test.js diff --git a/app/js/components/Navigation.js b/app/js/components/Navigation.js deleted file mode 100644 index 0bf7a2b69..000000000 --- a/app/js/components/Navigation.js +++ /dev/null @@ -1,56 +0,0 @@ -import React from 'react' -import PropTypes from 'prop-types' -import styled from 'styled-components' - -import ChevronLeftIcon from 'mdi-react/ChevronLeftIcon' -const NavBlock = styled.div` - display: flex; - width: 100%; - position: absolute; - top: 20px; - left: 20px; - z-index: 100; - @media (min-width: 800px) { - top: -46px; - left: -10px; - } -` -const NavButton = styled.button` - border: none; - background: transparent; - display: flex; - align-items: center; - font-size: 14px; - font-weight: bold; - opacity: 0.5; - &:hover { - cursor: pointer; - opacity: 1; - } - svg { - display: block; - * { - fill: currentColor; - } - } -` - -const Navigation = props => { - const { previous, previousLabel = 'Back' } = props - - return ( - - - - {previousLabel} - - - ) -} - -Navigation.propTypes = { - previous: PropTypes.func.isRequired, - previousLabel: PropTypes.string -} - -export default Navigation 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') - }) - }) -})