resolve conflicts, update per review

This commit is contained in:
Thomas Osmonson
2020-01-09 10:18:12 -06:00
15 changed files with 696 additions and 229 deletions

1
.prettierrc.js Normal file
View File

@@ -0,0 +1 @@
module.exports = require('@blockstack/prettier-config');

View File

@@ -18,8 +18,6 @@
},
"peerDependencies": {
"blockstack": "^19",
"react": "^16.12.0",
"react-dom": "^16.12.0",
"styled-components": "^4.4"
},
"husky": {
@@ -30,17 +28,23 @@
"prettier": "@blockstack/prettier-config",
"devDependencies": {
"@babel/plugin-proposal-optional-chaining": "^7.7.5",
"@blockstack/prettier-config": "^0.0.3",
"@types/jest": "^24.0.23",
"@typescript-eslint/eslint-plugin": "^2.10.0",
"@typescript-eslint/parser": "^2.10.0",
"@blockstack/prettier-config": "^0.0.4",
"@types/jest": "^24.0.25",
"@typescript-eslint/eslint-plugin": "^2.15.0",
"@typescript-eslint/parser": "^2.15.0",
"blockstack": "^19.3.0",
"eslint": "^6.7.2",
"husky": "^3.1.0",
"bundlesize": "^0.18.0",
"eslint": "^6.8.0",
"eslint-config-prettier": "^6.9.0",
"eslint-plugin-prettier": "^3.1.2",
"eslint-plugin-react": "^7.17.0",
"husky": "^4.0.1",
"prettier": "^1.19.1",
"tsdx": "^0.11.0",
"react": "^16.12.0",
"react-dom": "^16.12.0",
"tsdx": "^0.12.1",
"tslib": "^1.10.0",
"typescript": "^3.7.2"
"typescript": "^3.7.4"
},
"publishConfig": {
"access": "public"
@@ -48,9 +52,14 @@
"dependencies": {
"@blockstack/ui": "^1.0.0-alpha.22",
"mdi-react": "^6.5.0",
"react": "^16.12.0",
"react-dom": "^16.12.0",
"styled-components": "^4.4.1",
"use-events": "^1.4.1"
}
},
"bundlesize": [
{
"path": "./dist/**/*.js",
"maxSize": "9 kB"
}
],
"sideEffects": false
}

View File

@@ -1,7 +1,8 @@
import { UserSession, AppConfig } from 'blockstack';
import './types';
import { popupCenter } from './popup';
const dataVaultHost = 'https://vault.hankstoever.com';
const defaultVaultURL = 'https://vault.hankstoever.com';
interface FinishedData {
authResponse: string;
@@ -22,30 +23,15 @@ export interface AuthOptions {
};
}
// To allow the ability to on-the-fly pass any of these keys to update the state
export interface OptionalAuthOptions {
redirectTo?: string;
manifestPath?: string;
finished?: (data: FinishedData) => void;
vaultUrl?: string;
sendToSignIn?: boolean;
userSession?: UserSession;
appDetails?: {
name?: string;
icon?: string;
};
}
export const authenticate = ({
export const authenticate = async ({
redirectTo,
manifestPath,
finished,
vaultUrl,
sendToSignIn = false,
userSession,
appDetails
appDetails,
}: AuthOptions) => {
const dataVaultURL = new URL(vaultUrl || dataVaultHost);
if (!userSession) {
const appConfig = new AppConfig(
['store_write', 'publish_data'],
@@ -67,12 +53,14 @@ export const authenticate = ({
undefined,
{
sendToSignIn,
appDetails
appDetails,
}
);
const extensionURL = await window.BlockstackProvider?.getURL();
const dataVaultURL = new URL(extensionURL || vaultUrl || defaultVaultURL);
const popup = popupCenter({
url: `${dataVaultURL.origin}/actions.html?authRequest=${authRequest}`
url: `${dataVaultURL.origin}/actions.html?authRequest=${authRequest}`,
});
setupListener({ popup, authRequest, finished, dataVaultURL, userSession });
@@ -97,14 +85,14 @@ const setupListener = ({
authRequest,
finished,
dataVaultURL,
userSession
userSession,
}: ListenerParams) => {
const interval = setInterval(() => {
if (popup) {
try {
popup.postMessage(
{
authRequest
authRequest,
},
dataVaultURL.origin
);
@@ -125,7 +113,7 @@ const setupListener = ({
await userSession.handlePendingSignIn(authResponse);
finished({
authResponse,
userSession
userSession,
});
}
window.removeEventListener('message', receiveMessageCallback);

View File

@@ -1,3 +1,4 @@
export * from './auth';
export * from './react';
export * from './popup';
export * from './types';

View File

@@ -13,7 +13,7 @@ export const popupCenter = ({
url,
title = defaultTitle,
w = defaultWidth,
h = defaultHeight
h = defaultHeight,
}: PopupOptions) => {
const dualScreenLeft = window.screenLeft || window.screenX;
const dualScreenTop = window.screenTop || window.screenY;
@@ -32,10 +32,10 @@ export const popupCenter = ({
const top = (height - h) / 2 / systemZoom + dualScreenTop;
const options = {
scrollbars: 'no',
width: w / systemZoom,
height: h / systemZoom,
width: w,
height: h,
top: top,
left: left
left: left,
};
const optionsString = Object.keys(options).map(key => {
return `${key}=${options[key as keyof typeof options]}`;

View File

@@ -1,12 +1,14 @@
import React, { useReducer, createContext } from 'react';
import { AuthOptions } from '../../../auth';
const MODAL_OPEN = 'modal/open';
const MODAL_CLOSE = 'modal/close';
const UPDATE_AUTH_OPTIONS = 'data/update-auth-options';
const SCREENS_INTRO = 'screens/intro';
const SCREENS_HOW_IT_WORKS = 'screens/how-it-works';
const SCREENS_SIGN_IN = 'screens/sign-in';
enum States {
MODAL_OPEN = 'modal/open',
MODAL_CLOSE = 'modal/close',
UPDATE_AUTH_OPTIONS = 'data/update-auth-options',
SCREENS_INTRO = 'screens/intro',
SCREENS_HOW_IT_WORKS = 'screens/how-it-works',
SCREENS_SIGN_IN = 'screens/sign-in',
}
type Action = { type: string; payload?: any };
@@ -14,9 +16,9 @@ type Dispatch = (action: Action) => void;
type State = { isOpen: boolean; screen: string; authOptions: AuthOptions };
const initialState = {
const initialState: State = {
isOpen: false,
screen: SCREENS_INTRO,
screen: States.SCREENS_INTRO,
authOptions: {
redirectTo: '',
manifestPath: '',
@@ -25,9 +27,9 @@ const initialState = {
sendToSignIn: false,
appDetails: {
name: '',
icon: ''
}
}
icon: '',
},
},
};
const connectReducer = (
@@ -35,38 +37,38 @@ const connectReducer = (
{ type, payload }: { type: string; payload?: any }
) => {
switch (type) {
case MODAL_OPEN: {
case States.MODAL_OPEN: {
return { ...state, isOpen: true };
}
case MODAL_CLOSE: {
case States.MODAL_CLOSE: {
return { ...state, isOpen: false };
}
case SCREENS_INTRO: {
case States.SCREENS_INTRO: {
return {
...state,
screen: SCREENS_INTRO
screen: States.SCREENS_INTRO,
};
}
case SCREENS_HOW_IT_WORKS: {
case States.SCREENS_HOW_IT_WORKS: {
return {
...state,
screen: SCREENS_HOW_IT_WORKS
screen: States.SCREENS_HOW_IT_WORKS,
};
}
case SCREENS_SIGN_IN: {
case States.SCREENS_SIGN_IN: {
return {
...state,
screen: SCREENS_SIGN_IN
screen: States.SCREENS_SIGN_IN,
};
}
case UPDATE_AUTH_OPTIONS: {
case States.UPDATE_AUTH_OPTIONS: {
return {
...state,
authOptions: {
...state.authOptions,
...payload
}
...payload,
},
};
}
@@ -82,7 +84,7 @@ const ConnectDispatchContext = createContext<Dispatch | undefined>(undefined);
const ConnectProvider = ({
authOptions,
children
children,
}: {
authOptions: AuthOptions;
children: any;
@@ -103,10 +105,5 @@ export {
ConnectContext,
ConnectDispatchContext,
ConnectProvider,
MODAL_OPEN,
MODAL_CLOSE,
SCREENS_INTRO,
SCREENS_HOW_IT_WORKS,
SCREENS_SIGN_IN,
UPDATE_AUTH_OPTIONS
States,
};

View File

@@ -10,7 +10,7 @@ import { AuthOptions } from '../../../auth';
* const auth = {
manifestPath: '/static/manifest.json',
redirectTo: '/',
finished: () => {
finished: ({userSession}) => {
doFinishSignIn();
},
vaultUrl,
@@ -22,7 +22,6 @@ import { AuthOptions } from '../../../auth';
*
* <Connect authOptions={authOptions} />
*/
const Connect = ({
authOptions,
children

View File

@@ -1,6 +1,5 @@
import React from 'react';
import { Text, Box } from '@blockstack/ui';
import { BoxProps } from '@blockstack/ui/dist/box/types';
import { Text, Box, BoxProps } from '@blockstack/ui';
interface LinkProps extends BoxProps {
_hover?: BoxProps;

View File

@@ -6,19 +6,16 @@ import {
CSSReset,
Flex,
Box,
Text
Text,
} from '@blockstack/ui';
// import ChevronRightIcon from 'mdi-react/ChevronRightIcon';
import CloseIcon from 'mdi-react/CloseIcon';
import { useHover } from 'use-events';
import { Logo } from '../logo';
import { Intro } from '../screens/intro';
import { HowItWorks } from '../screen/how-it-works';
import { ContinueWithDataVault } from '../screen/sign-in';
// import { AppIcon } from '../app-icon';
import { useConnect } from '../../hooks/useConnect';
import { SCREENS_HOW_IT_WORKS, SCREENS_SIGN_IN } from '../connect/context';
// import { useAppDetails } from '../../hooks/useAppDetails';x
import { States } from '../connect/context';
interface HeaderTitleProps {
title: string;
@@ -27,7 +24,7 @@ interface HeaderTitleProps {
const HeaderTitle: React.FC<HeaderTitleProps> = ({
hideIcon = false,
title
title,
}) => (
<Flex align="center">
{hideIcon ? null : <Logo mr={2} />}
@@ -90,10 +87,10 @@ const ModalHeader = ({ title, hideIcon, close, ...rest }: IModalHeader) => {
const RenderScreen: React.FC = () => {
const { screen } = useConnect();
switch (screen) {
case SCREENS_HOW_IT_WORKS: {
case States.SCREENS_HOW_IT_WORKS: {
return <HowItWorks />;
}
case SCREENS_SIGN_IN: {
case States.SCREENS_SIGN_IN: {
return (
<Box width="100%">
<ContinueWithDataVault />
@@ -115,7 +112,7 @@ const Modal = () => {
headerComponent={
<ModalHeader
close
title={screen === SCREENS_SIGN_IN ? 'Sign In' : 'Data Vault'}
title={screen === States.SCREENS_SIGN_IN ? 'Sign In' : 'Data Vault'}
/>
}
isOpen={isOpen}

View File

@@ -1,7 +1,6 @@
import React from 'react';
import { Button, Flex, Box, Spinner, Stack } from '@blockstack/ui';
import { Button, Flex, Box, Spinner, Stack, BoxProps } from '@blockstack/ui';
import { Title, Pretitle, Body, BackLink } from '../typography';
import { BoxProps } from '@blockstack/ui/dist/box';
import { Link } from '../link';
const Footer = ({ content }: { content: any }) =>

View File

@@ -24,7 +24,7 @@ const ContinueWithDataVault: React.FC = props => {
bg={hovered ? 'rgba(0,0,0,0.02)' : 'white'}
transform={hovered ? 'translateY(-2px)' : 'none'}
onClick={() => {
authenticate(authOptions);
authenticate({ ...authOptions, sendToSignIn: true });
}}
{...bind}
{...props}

View File

@@ -1,7 +1,6 @@
import React from 'react';
import { Text, Box } from '@blockstack/ui';
import { Text, Box, BoxProps } from '@blockstack/ui';
import ChevronLeftIcon from 'mdi-react/ChevronLeftIcon';
import { BoxProps } from '@blockstack/ui/dist/box';
const Title: React.FC = props => (
<Text

View File

@@ -1,14 +1,9 @@
import { useContext } from 'react';
import { authenticate, OptionalAuthOptions } from '../../auth';
import { authenticate, AuthOptions } from '../../auth';
import {
ConnectContext,
ConnectDispatchContext,
MODAL_CLOSE,
MODAL_OPEN,
SCREENS_SIGN_IN,
SCREENS_HOW_IT_WORKS,
SCREENS_INTRO,
UPDATE_AUTH_OPTIONS
States,
} from '../components/connect/context';
const useConnectDispatch = () => {
@@ -23,24 +18,25 @@ const useConnect = () => {
const { isOpen, screen, authOptions } = useContext(ConnectContext);
const dispatch = useConnectDispatch();
const doUpdateAuthOptions = (payload: OptionalAuthOptions) =>
dispatch({ type: UPDATE_AUTH_OPTIONS, payload });
const doUpdateAuthOptions = (payload: Partial<AuthOptions>) =>
dispatch({ type: States.UPDATE_AUTH_OPTIONS, payload });
const doChangeScreen = (newScreen: string) => dispatch({ type: newScreen });
const doGoToIntroScreen = () => doChangeScreen(SCREENS_INTRO);
const doGoToHowItWorksScreen = () => doChangeScreen(SCREENS_HOW_IT_WORKS);
const doGoToSignInScreen = () => doChangeScreen(SCREENS_SIGN_IN);
const doGoToIntroScreen = () => doChangeScreen(States.SCREENS_INTRO);
const doGoToHowItWorksScreen = () =>
doChangeScreen(States.SCREENS_HOW_IT_WORKS);
const doGoToSignInScreen = () => doChangeScreen(States.SCREENS_SIGN_IN);
const doOpenDataVault = (
signIn?: boolean,
authOptions?: OptionalAuthOptions
authOptions?: Partial<AuthOptions>
) => {
signIn && doGoToSignInScreen();
authOptions && doUpdateAuthOptions(authOptions);
dispatch({ type: MODAL_OPEN });
dispatch({ type: States.MODAL_OPEN });
};
const doCloseDataVault = () => {
dispatch({ type: MODAL_CLOSE });
dispatch({ type: States.MODAL_CLOSE });
setTimeout(doGoToIntroScreen, 250);
};
@@ -54,7 +50,7 @@ const useConnect = () => {
doGoToIntroScreen,
doGoToHowItWorksScreen,
doGoToSignInScreen,
authenticate
authenticate,
};
};

9
src/types.ts Normal file
View File

@@ -0,0 +1,9 @@
export interface BlockstackProvider {
getURL: () => Promise<string>;
}
declare global {
interface Window {
BlockstackProvider?: BlockstackProvider;
}
}

725
yarn.lock

File diff suppressed because it is too large Load Diff