fix: clean up timeouts, prevent many calls to gaia

This commit is contained in:
Thomas Osmonson
2021-03-05 11:03:37 -06:00
parent 8875a21ed0
commit 21a94da0cb
6 changed files with 131 additions and 87 deletions

View File

@@ -19,7 +19,7 @@ import {
type Set = <T>(store: RecoilState<T>, value: T) => void;
const innerMessageWrapper = (message: MessageFromApp, set: Set) => {
const innerMessageWrapper = async (message: MessageFromApp, set: Set) => {
return new Promise<Vault>((resolve, reject) => {
chrome.runtime.sendMessage(message, (vaultOrError: Vault | Error) => {
if ('hasSetPassword' in vaultOrError) {
@@ -39,9 +39,10 @@ const innerMessageWrapper = (message: MessageFromApp, set: Set) => {
};
const messageWrapper = (message: MessageFromApp) => {
return useRecoilCallback(({ set }) => () => {
return innerMessageWrapper(message, set);
});
return useRecoilCallback(({ set }) => () => innerMessageWrapper(message, set), [
message,
innerMessageWrapper,
]);
};
export const useVaultMessenger = () => {
@@ -80,12 +81,21 @@ export const useVaultMessenger = () => {
return innerMessageWrapper(message, set);
});
const getWallet = messageWrapper({ method: Methods.walletRequest, payload: undefined });
const doMakeWallet = messageWrapper({ method: Methods.makeWallet, payload: undefined });
const doCreateNewAccount = messageWrapper({
method: Methods.createNewAccount,
payload: undefined,
});
const doSignOut = messageWrapper({ method: Methods.signOut, payload: undefined });
const doLockWallet = messageWrapper({ method: Methods.lockWallet, payload: undefined });
return {
getWallet: messageWrapper({ method: Methods.walletRequest, payload: undefined }),
doMakeWallet: messageWrapper({ method: Methods.makeWallet, payload: undefined }),
doCreateNewAccount: messageWrapper({ method: Methods.createNewAccount, payload: undefined }),
doSignOut: messageWrapper({ method: Methods.signOut, payload: undefined }),
doLockWallet: messageWrapper({ method: Methods.lockWallet, payload: undefined }),
getWallet,
doMakeWallet,
doCreateNewAccount,
doSignOut,
doLockWallet,
doSetPassword,
doStoreSeed,
doUnlockWallet,

View File

@@ -1,21 +1,36 @@
import React, { useCallback, useEffect } from 'react';
import React, { useCallback, useEffect, useRef, useState } from 'react';
import { Box, Flex, Text, Button } from '@stacks/ui';
import { useWallet } from '@common/hooks/use-wallet';
interface CreateAccountProps {
close: () => void;
}
const TIMEOUT = 3000;
export const CreateAccount: React.FC<CreateAccountProps> = ({ close }) => {
const { doCreateNewAccount } = useWallet();
const [setting, setSetting] = useState(false);
const timeout = useRef<number | null>(null);
const createAccount = useCallback(async () => {
await doCreateNewAccount();
setTimeout(() => close(), 3000);
}, [doCreateNewAccount, close]);
if (!setting && !timeout.current) {
setSetting(true);
await doCreateNewAccount();
timeout.current = setTimeout(() => close(), TIMEOUT);
setSetting(false);
}
}, [doCreateNewAccount, setting, timeout, close]);
useEffect(() => {
void createAccount();
}, [createAccount]);
return () => {
if (timeout.current) {
clearTimeout(timeout.current);
}
};
}, [timeout, createAccount]);
return (
<Box width="100%" px={6}>
<Box>

View File

@@ -1,4 +1,4 @@
import React from 'react';
import React, { memo, useCallback, useEffect, useRef } from 'react';
import { Box, Fade, Button, Stack, color } from '@stacks/ui';
import { Title, Caption } from '@components/typography';
import { useWallet } from '@common/hooks/use-wallet';
@@ -14,66 +14,98 @@ interface SwitchAccountProps {
close: () => void;
}
const TIMEOUT = 350;
const useSwitchAccount = (handleClose: () => void) => {
const { wallet, currentAccountIndex, doSwitchAccount } = useWallet();
const transactionVersion = useRecoilValue(currentTransactionVersion);
const timeoutRef = useRef<number | null>(null);
const handleSwitchAccount = useCallback(
async index => {
await doSwitchAccount(index);
if (!timeoutRef.current) {
timeoutRef.current = setTimeout(() => {
handleClose();
}, TIMEOUT);
}
},
[doSwitchAccount, timeoutRef, close]
);
useEffect(() => {
return () => {
if (timeoutRef.current) {
clearTimeout(timeoutRef.current);
}
};
}, []);
const accounts = wallet?.accounts || [];
const getIsActive = (index: number) => index === currentAccountIndex;
return { accounts, handleSwitchAccount, getIsActive, transactionVersion };
};
// eslint-disable-next-line no-warning-comments
// TODO: this page is nearly identical to the network switcher abstract it out into a shared component
export const SwitchAccounts: React.FC<SwitchAccountProps> = ({ close }) => {
const { wallet, currentAccountIndex, doSwitchAccount } = useWallet();
const setAccountDrawerStep = useSetRecoilState(accountDrawerStep);
const transactionVersion = useRecoilValue(currentTransactionVersion);
const accountRows = (wallet?.accounts || []).map((account, index) => {
return (
<SpaceBetween
width="100%"
key={`account-${account.index}`}
_hover={{
bg: color('bg-4'),
}}
cursor="pointer"
py="base"
px="loose"
onClick={async () => {
await doSwitchAccount(index);
setTimeout(() => {
close();
}, 350);
}}
>
<Stack>
<Title fontSize={2} lineHeight="1rem" fontWeight="400">
{getAccountDisplayName(account)}
</Title>
<Caption>
{truncateMiddle(
getStxAddress({
account: account,
transactionVersion,
}),
9
)}
</Caption>
</Stack>
<Fade in={index === currentAccountIndex}>
{styles => (
<Box
as={IconCheck}
size="18px"
strokeWidth={2.5}
color={color('brand')}
style={styles}
/>
)}
</Fade>
</SpaceBetween>
);
});
const AccountList: React.FC<{ handleClose: () => void }> = memo(({ handleClose }) => {
const { accounts, handleSwitchAccount, transactionVersion, getIsActive } = useSwitchAccount(
handleClose
);
return (
<>
{accountRows}
{accounts.map((account, index) => {
return (
<SpaceBetween
width="100%"
key={`account-${account.index}`}
_hover={{
bg: color('bg-4'),
}}
cursor="pointer"
py="base"
px="loose"
onClick={() => handleSwitchAccount(index)}
>
<Stack>
<Title fontSize={2} lineHeight="1rem" fontWeight="400">
{getAccountDisplayName(account)}
</Title>
<Caption>
{truncateMiddle(
getStxAddress({
account: account,
transactionVersion,
}),
9
)}
</Caption>
</Stack>
<Fade in={getIsActive(index)}>
{styles => (
<Box
as={IconCheck}
size="18px"
strokeWidth={2.5}
color={color('brand')}
style={styles}
/>
)}
</Fade>
</SpaceBetween>
);
})}
</>
);
});
export const SwitchAccounts: React.FC<SwitchAccountProps> = memo(({ close }) => {
const setAccountDrawerStep = useSetRecoilState(accountDrawerStep);
return (
<>
<AccountList handleClose={close} />
<Box pt="base" px="loose">
<Button onClick={() => setAccountDrawerStep(AccountStep.Create)}>Create an account</Button>
</Box>
</>
);
};
});

View File

@@ -12,7 +12,6 @@ import {
Wallet as SDKWallet,
} from '@stacks/wallet-sdk';
import { DEFAULT_PASSWORD } from '@store/onboarding/types';
// import { WalletStore, walletStore } from '../storage';
/**
* Manage a wallet instance, stored in memory in the background script
@@ -122,7 +121,7 @@ export const vaultReducer = async (message: MessageFromApp): Promise<Vault> => {
gaiaHubConfig,
});
};
void updateConfig();
await updateConfig();
return {
...vault,
wallet,

View File

@@ -1,4 +1,4 @@
import React from 'react';
import React, { memo } from 'react';
import { Button, Stack, Box, ButtonProps } from '@stacks/ui';
import { PopupContainer } from '@components/popup/container';
import { useAnalytics } from '@common/hooks/use-analytics';
@@ -30,11 +30,10 @@ const TxButton: React.FC<TxButtonProps> = ({ kind, onClick, ...rest }) => {
);
};
export const PopupHome: React.FC = () => {
export const PopupHome: React.FC = memo(() => {
const { currentAccount, currentAccountIndex, currentAccountStxAddress } = useWallet();
const { doChangeScreen } = useAnalytics();
const assets = useAssets();
console.log(assets);
if (!currentAccount || currentAccountIndex === undefined || !currentAccountStxAddress) {
console.error('Error! Homepage is not present, this should never happen!');
return null;
@@ -60,4 +59,4 @@ export const PopupHome: React.FC = () => {
<AccountInfo />
</PopupContainer>
);
};
});

View File

@@ -1,5 +1,4 @@
/* eslint-disable @typescript-eslint/no-var-requires */
const ExtensionReloader = require('webpack-extension-reloader');
const baseConfig = require('./webpack.config.base');
const config = {
@@ -18,17 +17,7 @@ const config = {
splitChunks: false,
},
devtool: 'eval', // fastest
plugins: [
new ExtensionReloader({
port: 9128,
reloadPage: true,
entries: {
background: 'background',
contentScript: ['message-bus'],
},
}),
...baseConfig.plugins,
],
plugins: [...baseConfig.plugins],
};
module.exports = config;