Skip to content
This repository has been archived by the owner on Aug 1, 2023. It is now read-only.

Commit

Permalink
feat: empty homepage state layout, closes #156
Browse files Browse the repository at this point in the history
  • Loading branch information
kyranjamie committed Sep 25, 2020
1 parent ea151ac commit 5662138
Show file tree
Hide file tree
Showing 26 changed files with 456 additions and 91 deletions.
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@ module.exports = {
'@typescript-eslint/no-unsafe-assignment': 0,
'@typescript-eslint/no-unsafe-call': 0,
'no-warning-comments': ['warn', { terms: ['SECURITY'], location: 'anywhere' }],
'@typescript-eslint/no-unused-variable': [true, { 'ignore-pattern': '^_' }],
},
};
26 changes: 26 additions & 0 deletions app/assets/images/btc-podium.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
25 changes: 25 additions & 0 deletions app/components/balance-card.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import React, { FC } from 'react';
import { Box, Button, Text } from '@blockstack/ui';

interface BalanceCardProps {
balance: string;
}

export const BalanceCard: FC<BalanceCardProps> = ({ balance }) => {
return (
<Box>
<Text textStyle="body.large.medium" display="block">
Total balance
</Text>
<Text fontSize="40px" lineHeight="56px" fontWeight="bold" letterSpacing="-0.01em">
{balance}
</Text>
<Box mt="loose">
<Button size="md">Send</Button>
<Button size="md" ml="tight">
Receive
</Button>
</Box>
</Box>
);
};
2 changes: 1 addition & 1 deletion app/components/card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export const Card: React.FC<CardProps> = ({ title, children, ...rest }) => {
<Box
borderRadius="6px"
border="1px solid"
borderColor="#E5E5EC"
borderColor="#E1E3E8"
boxShadow="mid"
textAlign="center"
width="100%"
Expand Down
2 changes: 1 addition & 1 deletion app/components/error-label.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react';
import { Flex, Box, FlexProps } from '@blockstack/ui';

import { ExclamationMark } from './exclamation-mark';
import { ExclamationMark } from './icons/exclamation-mark';

type ErrorLabelProps = FlexProps;

Expand Down
14 changes: 14 additions & 0 deletions app/components/icons/movement-arrow.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import * as React from 'react';
import { Box, BoxProps } from '@blockstack/ui';

export const MovementArrow = ({ ...props }: BoxProps) => (
<Box {...props}>
<svg width={16} height={16} viewBox="0 0 16 16" fill="none">
<path
d="M5.883 9.75h4.234a.5.5 0 00.429-.757L8.429 5.465a.5.5 0 00-.858 0L5.454 8.993a.5.5 0 00.43.757z"
fill="#00A73E"
/>
<circle opacity={0.24} cx={8} cy={8} r={7} stroke="#00A73E" strokeWidth={2} />
</svg>
</Box>
);
26 changes: 26 additions & 0 deletions app/components/stacking-promo-card.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import React from 'react';
import { Box, Flex, Text, Button } from '@blockstack/ui';

export const StackingPromoCard = () => {
return (
<Box
mt="extra-loose"
borderRadius="8px"
boxShadow="0px 1px 2px rgba(0, 0, 0, 0.04);"
border="1px solid #F0F0F5"
>
<Flex flexDirection="column" mt="40px" mb="extra-loose">
<img src="assets/images/btc-podium.svg" />
<Text display="block" textAlign="center" textStyle="display.small" mt="loose">
Earn Bitcoin rewards
</Text>
<Text display="block" mt="tight" textAlign="center" maxWidth="320px" mx="auto">
You’ll earn Bitcoin when you temporarily lock 100,000 STX or more
</Text>
<Button size="md" mt="base" mx="auto" width="272px">
Buy STX
</Button>
</Flex>
</Box>
);
};
40 changes: 40 additions & 0 deletions app/components/stacking-rewards-card.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import React, { FC } from 'react';
import { Box, Flex, Text } from '@blockstack/ui';
import { Hr } from './hr';
import { MovementArrow } from './icons/movement-arrow';

interface StackingRewardCardProps {
lifetime: string;
lastCycle: string;
}

export const StackingRewardCard: FC<StackingRewardCardProps> = ({ lifetime, lastCycle }) => {
return (
<Box
mt="extra-loose"
borderRadius="8px"
boxShadow="0px 1px 2px rgba(0, 0, 0, 0.04);"
border="1px solid #F0F0F5"
>
<Flex m="loose" flexDirection="column">
<Text textStyle="body.small" color="ink.600">
Lifetime rewards
</Text>
<Flex mt="tight" alignItems="center">
<MovementArrow mr="tight" />
<Text textStyle="body.large.medium">{lifetime}</Text>
</Flex>
</Flex>
<Hr />
<Flex m="loose" flexDirection="column">
<Text textStyle="body.small" color="ink.600">
Last cycle
</Text>
<Flex mt="tight" alignItems="center">
<MovementArrow mr="tight" />
<Text textStyle="body.large.medium">{lastCycle}</Text>
</Flex>
</Flex>
</Box>
);
};
2 changes: 1 addition & 1 deletion app/components/toast.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import { Flex, Box, Text } from '@blockstack/ui';
import { SuccessCheckmark } from './success-checkmark';
import { SuccessCheckmark } from './icons/success-checkmark';

interface ToastProps {
show?: boolean;
Expand Down
19 changes: 19 additions & 0 deletions app/components/transaction-list/transaction-list-empty.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React from 'react';
import { Text, Flex } from '@blockstack/ui';

export const TransactionListEmpty = () => {
return (
<Flex
borderRadius="8px"
boxShadow="0px 1px 2px rgba(0, 0, 0, 0.04);"
border="1px solid #F0F0F5"
minHeight={['152px', '152px', '300px', '416px']}
justifyContent="center"
alignItems={['center', 'center', null, null]}
>
<Text textStyle="body.small" display="block" textAlign="center" mb="tight">
You haven't made any transactions yet
</Text>
</Flex>
);
};
11 changes: 11 additions & 0 deletions app/components/transaction-list/transaction-list.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import React, { FC } from 'react';
import { TransactionListEmpty } from './transaction-list-empty';

interface TransactionListProps {
txs: any[];
}

export const TransactionList: FC<TransactionListProps> = ({ txs }) => {
if (txs.length === 0) return <TransactionListEmpty />;
return null;
};
33 changes: 24 additions & 9 deletions app/main.dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,21 +30,32 @@ export default class AppUpdater {
let mainWindow: BrowserWindow | null = null;

if (process.env.NODE_ENV === 'production') {
const sourceMapSupport = require('source-map-support');
sourceMapSupport.install();
import('source-map-support')
.then(sourceMapSupport => sourceMapSupport.install())
.catch(err => {
throw err;
});
}

if (process.env.NODE_ENV === 'development' || process.env.DEBUG_PROD === 'true') {
require('electron-debug')();
import('electron-debug')
.then(electronDebug => electronDebug.default())
.catch(error => console.error(error));
}

const installExtensions = async () => {
const installer = require('electron-devtools-installer');
const forceDownload = !!process.env.UPGRADE_EXTENSIONS;
const extensions = ['REACT_DEVELOPER_TOOLS', 'REDUX_DEVTOOLS'];
return Promise.all(
extensions.map(name => installer.default(installer[name], forceDownload))
).catch(console.log);
try {
const installer = await import('electron-devtools-installer');
const forceDownload = !!process.env.UPGRADE_EXTENSIONS;
const extensions = [installer.REACT_DEVELOPER_TOOLS, installer.REDUX_DEVTOOLS];

return Promise.all(
extensions.map(extension => installer.default(extension, forceDownload))
).catch(error => new Error(`Error while installing extensions\n${error}`));
} catch (error) {
console.error(error);
throw error;
}
};

const createWindow = async () => {
Expand All @@ -71,6 +82,8 @@ const createWindow = async () => {

void mainWindow.loadURL(`file://${__dirname}/app.html`);

let hasFocusedOnInitialLoad = false;

// @TODO: Use 'ready-to-show' event
// https://github.com/electron/electron/blob/master/docs/api/browser-window.md#using-ready-to-show-event
mainWindow.webContents.on('did-finish-load', () => {
Expand All @@ -80,8 +93,10 @@ const createWindow = async () => {
if (process.env.START_MINIMIZED) {
mainWindow.minimize();
} else {
if (hasFocusedOnInitialLoad) return;
mainWindow.show();
mainWindow.focus();
hasFocusedOnInitialLoad = true;
}
});

Expand Down
49 changes: 49 additions & 0 deletions app/pages/home/home-layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import React from 'react';
import { Flex, Box } from '@blockstack/ui';

type HomeComponents =
| 'balanceCard'
| 'transactionList'
| 'stackingPromoCard'
| 'stackingRewardCard';

type HomeLayout = {
[key in HomeComponents]: JSX.Element;
};

export const HomeLayout: React.FC<HomeLayout> = ({
balanceCard,
transactionList,
stackingPromoCard,
stackingRewardCard,
}) => {
return (
<Flex
flexShrink={1}
maxWidth="1104px"
pt="120px"
flexDirection="column"
mx={['loose', 'loose', 'extra-loose', 'extra-loose', 'auto']}
mb="extra-loose"
>
{balanceCard}
<Flex flexDirection={['column', 'column', 'row']}>
<Box mt="extra-loose" flexGrow={1} mr={[null, null, 'extra-loose', '72px']}>
{transactionList}
</Box>
<Flex flexDirection="column" minWidth={[null, null, '376px']}>
{stackingPromoCard}
{stackingRewardCard}
</Flex>
</Flex>
{/* <Button onClick={openModal}>Open a modal</Button> */}
{/* <Box>Mnemonic: {mnemonic}</Box>
<Box mt="loose">MnemonicEncryptedHex: {privateKey}</Box>
<Box mt="loose">Private key: {privateKey}</Box>
<Box mt="loose">Base58: {base58}</Box>
<Box mt="loose">Salt: {(keys as any).salt}</Box>
<Box mt="loose">Password: {(keys as any).password}</Box>
<Box mt="loose">Stretched Key: {(keys as any).derivedEncryptionKey}</Box> */}
</Flex>
);
};
45 changes: 18 additions & 27 deletions app/pages/home/home.tsx
Original file line number Diff line number Diff line change
@@ -1,49 +1,40 @@
import React, { useEffect, useState } from 'react';
import { useSelector } from 'react-redux';
import { Flex, Box } from '@blockstack/ui';
import { ChainID } from '@blockstack/stacks-transactions';
import { deriveRootKeychainFromMnemonic, deriveStxAddressChain } from '@blockstack/keychain';
import { deriveRootKeychainFromMnemonic } from '@blockstack/keychain';

import { selectMnemonic, selectKeysSlice } from '../../store/keys';
import { selectMnemonic } from '../../store/keys';
import { BIP32Interface } from '../../types';
import { TransactionList } from '../../components/transaction-list/transaction-list';
import { StackingPromoCard } from '../../components/stacking-promo-card';
import { StackingRewardCard } from '../../components/stacking-rewards-card';
import { BalanceCard } from '../../components/balance-card';
import { HomeLayout } from './home-layout';

//
// Placeholder component
export const Home: React.FC = () => {
const mnemonic = useSelector(selectMnemonic);
const keys = useSelector(selectKeysSlice);
const [keychain, setKeychain] = useState<{ rootNode: BIP32Interface } | null>(null);

useEffect(() => {
const deriveMasterKeychain = async () => {
if (!mnemonic) return;
const resp = await deriveRootKeychainFromMnemonic(mnemonic, '');
setKeychain(resp);
const { rootNode } = await deriveRootKeychainFromMnemonic(mnemonic, '');
setKeychain({ rootNode });
};
void deriveMasterKeychain();
}, [mnemonic]);

if (keychain === null) return <div>Homepage, but no keychain can be derived</div>;

const rootNode = deriveStxAddressChain(ChainID.Testnet)(keychain.rootNode);

const privateKey = rootNode.privateKey;

const base58 = rootNode.childKey.toBase58();

if (!mnemonic) return <>How you get to homepage without a mnemonic?</>;

// console.log(keychain);
if (keychain === null) return <></>;

return (
<Flex pt="120px" flexDirection="column" mx="loose">
<Box>Mnemonic: {mnemonic}</Box>
<Box mt="loose">MnemonicEncryptedHex: {privateKey}</Box>
<Box mt="loose">Private key: {privateKey}</Box>
<Box mt="loose">Base58: {base58}</Box>
<Box mt="loose">Salt: {(keys as any).salt}</Box>
<Box mt="loose">Password: {(keys as any).password}</Box>
<Box mt="loose">Stretched Key: {(keys as any).derivedEncryptionKey}</Box>
</Flex>
<HomeLayout
balanceCard={<BalanceCard balance="124,000.1003 STX" />}
transactionList={<TransactionList txs={[]} />}
stackingPromoCard={<StackingPromoCard />}
stackingRewardCard={
<StackingRewardCard lifetime="0.0281 Bitcoin" lastCycle="0.000383 Bitcoin" />
}
/>
);
};
3 changes: 2 additions & 1 deletion app/pages/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ import { loadFonts } from '../utils/load-fonts';

const GlobalStyle = createGlobalStyle`
html, body, #root {
height: 100%;
min-height: 100vh;
max-height: 100vh;
}
`;

Expand Down
Loading

0 comments on commit 5662138

Please sign in to comment.