@@ -57,6 +57,8 @@ import SubmitButton from 'form/SubmitButton';
57import FormError from 'form/FormError';
57import FormError from 'form/FormError';
58import { WARNING, onlyHasWarning } from 'form/helpers';
58import { WARNING, onlyHasWarning } from 'form/helpers';
59import useGasPrice from 'lib/useGasPrice';
59import useGasPrice from 'lib/useGasPrice';
60+import timeout from 'lib/timeout';
61+import { ForwardButton } from 'components/Buttons';
61const INITIAL_VALUES = { emails: [''] };
63const INITIAL_VALUES = { emails: [''] };
@@ -129,8 +131,8 @@ export default function InviteEmail() {
130 // derive booleans from status
132 // derive booleans from status
131 const canInput = status === STATUS.INPUT;
133 const canInput = status === STATUS.INPUT;
132− const canSend = status === STATUS.CAN_SEND;
133 const isGenerating = status === STATUS.GENERATING;
134 const isGenerating = status === STATUS.GENERATING;
135+ const canSend = status === STATUS.CAN_SEND;
134 const isSending = status === STATUS.SENDING;
136 const isSending = status === STATUS.SENDING;
135 const isFailed = status === STATUS.FAILURE;
137 const isFailed = status === STATUS.FAILURE;
136 const isDone = status === STATUS.SUCCESS;
138 const isDone = status === STATUS.SUCCESS;
@@ -174,6 +176,10 @@ export default function InviteEmail() {
174 : isSending
176 : isSending
175 ? Object.keys(receipts).length
177 ? Object.keys(receipts).length
179+ const percentProgress =
181+ ? progress / Object.keys(cachedEmails.current).length
177 const visualProgress = progress === null ? '-' : `${progress + 1}`;
183 const visualProgress = progress === null ? '-' : `${progress + 1}`;
179 // build a builder for the accessory to the input, depending on status
185 // build a builder for the accessory to the input, depending on status
@@ -245,8 +251,8 @@ export default function InviteEmail() {
245 nonce: nonce + i,
251 nonce: nonce + i,
246 // TODO: ^ make a useTransactionSigner to encapsulate this logic
252 // TODO: ^ make a useTransactionSigner to encapsulate this logic
247 txn: inviteTx,
253 txn: inviteTx,
248− gasPrice: gasPrice.toString(), // expects string gwei
254+ gasPrice: gasPrice.toFixed(), // expects string gwei
249− gasLimit: GAS_LIMIT.toString(),
255+ gasLimit: GAS_LIMIT.toFixed(),
252 const rawTx = hexify(signedTx.serialize());
258 const rawTx = hexify(signedTx.serialize());
@@ -302,7 +308,7 @@ export default function InviteEmail() {
304 _wallet.address,
310 _wallet.address,
305− toWei((gasPrice * GAS_LIMIT * emails.length).toString(), 'gwei'),
311+ toWei((gasPrice * GAS_LIMIT * emails.length).toFixed(), 'gwei'),
306 names.map(name => invites[name].rawTx),
312 names.map(name => invites[name].rawTx),
307 (address, minBalance, balance) =>
313 (address, minBalance, balance) =>
308 setNeedFunds({ address, minBalance, balance }),
314 setNeedFunds({ address, minBalance, balance }),
@@ -393,6 +399,8 @@ export default function InviteEmail() {
393 return errors;
399 return errors;
402+ await timeout(500); // wait for progress animation to complete.
396 setStatus(STATUS.CAN_SEND);
404 setStatus(STATUS.CAN_SEND);
398 [generateInvites]
406 [generateInvites]
@@ -419,6 +427,70 @@ export default function InviteEmail() {
420 }, [isDone, syncInvites, point]);
428 }, [isDone, syncInvites, point]);
430+ const renderButton = ({ handleSubmit, fields }) => {
436+ handleSubmit={handleSubmit}
437+ accessory={`${visualProgress}/${fields.length}`}>
438+ {buttonText(status, fields.length)}
451+ accessory={`${visualProgress}/${fields.length}`}
452+ progress={percentProgress}
454+ {buttonText(status, fields.length)}
467+ accessory={`${visualProgress}/${fields.length}`}
469+ {buttonText(status, fields.length)}
483+ accessory={`${visualProgress}/${fields.length}`}
484+ progress={percentProgress}
485+ color={isGenerating ? 'black' : 'green4'}>
486+ {buttonText(status, fields.length)}
423 <Grid gap={3}>
495 <Grid gap={3}>
424 <BridgeForm
496 <BridgeForm
@@ -507,27 +579,7 @@ export default function InviteEmail() {
514− handleSubmit={handleSubmit}
582+ {renderButton({ handleSubmit, fields })}
515− accessory={`${visualProgress}/${fields.length}`}>
516− {buttonText(status, fields.length)}
524− accessory={`${visualProgress}/${fields.length}`}
528− {buttonText(status, fields.length)}
532 {needFunds && (
584 {needFunds && (
533 <Grid.Item full>
585 <Grid.Item full>