@@ -1,78 +1,29 @@
1−import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
1+import { useCallback, useEffect } from 'react';
2−import { Just } from 'folktale/maybe';
3−import * as azimuth from 'azimuth-js';
4−import { Grid, CheckboxInput } from 'indigo-react';
5−import { FORM_ERROR } from 'final-form';
7import View from 'components/View';
3import View from 'components/View';
8import { ForwardButton } from 'components/Buttons';
4import { ForwardButton } from 'components/Buttons';
9−import WarningBox from 'components/WarningBox';
10import FooterButton from 'components/FooterButton';
5import FooterButton from 'components/FooterButton';
11import ActivateView from './ActivateView';
6import ActivateView from './ActivateView';
13−import { useNetwork } from 'store/network';
14import { useHistory } from 'store/history';
8import { useHistory } from 'store/history';
16−import * as need from 'lib/need';
17import { ROUTE_NAMES } from 'lib/routeNames';
10import { ROUTE_NAMES } from 'lib/routeNames';
18−import { walletFromMnemonic } from 'lib/wallet';
19−import { DEFAULT_HD_PATH, POINT_DOMINIONS, POINT_PROXIES } from 'lib/constants';
20−import { generateWallet } from 'lib/invite';
21−import { generateTemporaryOwnershipWallet } from 'lib/walletgen';
22import { useLocalRouter } from 'lib/LocalRouter';
11import { useLocalRouter } from 'lib/LocalRouter';
23import useImpliedTicket from 'lib/useImpliedTicket';
12import useImpliedTicket from 'lib/useImpliedTicket';
24−import { timeout } from 'lib/timeout';
25import useHasDisclaimed from 'lib/useHasDisclaimed';
13import useHasDisclaimed from 'lib/useHasDisclaimed';
26−import useBreakpoints from 'lib/useBreakpoints';
28−import BridgeForm from 'form/BridgeForm';
29−import SubmitButton from 'form/SubmitButton';
30−import { TicketInput } from 'form/Inputs';
35− buildCheckboxValidator,
36−} from 'form/validators';
37−import FormError from 'form/FormError';
39import { useActivateFlow } from './ActivateFlow';
15import { useActivateFlow } from './ActivateFlow';
40−import { WARNING } from 'form/helpers';
41−import { convertToInt } from 'lib/convertToInt';
42import PointPresenter from './PointPresenter';
16import PointPresenter from './PointPresenter';
43−import useRoller from 'lib/useRoller';
44−import { Ship } from '@urbit/roller-api';
45import { Box, Text } from '@tlon/indigo-react';
17import { Box, Text } from '@tlon/indigo-react';
46import ActivateHeader from './ActivateHeader';
18import ActivateHeader from './ActivateHeader';
47−import { MasterKey } from './MasterKey';
19+import ActivateCodeForm from './ActivateCodeForm';
49export default function ActivateCode() {
21export default function ActivateCode() {
50 const history = useHistory();
22 const history = useHistory();
51 const { names, push } = useLocalRouter();
23 const { names, push } = useLocalRouter();
52− const { contracts } = useNetwork();
57− } = useImpliedTicket();
24+ const { impliedPatp, impliedTicket } = useImpliedTicket();
58 const [hasDisclaimed] = useHasDisclaimed();
25 const [hasDisclaimed] = useHasDisclaimed();
59− const didWarn = useRef(false);
60− const { api, getPoints } = useRoller();
61− const [isGenerating, setIsGenerating] = useState<boolean>(false);
69− } = useActivateFlow();
26+ const { isIn, setIsIn } = useActivateFlow();
70− // this is a pretty naive way to detect if we're on a mobile device
71− // (i.e. we're checking the width of the screen)
72− // but it will suffice for the 99% case and if someone wants to get around it
73− // well by golly they're allowed to turn their phone into landscape mode
75− const activationAllowed = useBreakpoints([false, true, true]);
77 const goToLogin = useCallback(() => history.popAndPush(ROUTE_NAMES.LOGIN), [
28 const goToLogin = useCallback(() => history.popAndPush(ROUTE_NAMES.LOGIN), [
@@ -86,215 +37,18 @@ export default function ActivateCode() {
87 }, [hasDisclaimed, names.DISCLAIMER, names.MASTER_KEY, push]);
38 }, [hasDisclaimed, names.DISCLAIMER, names.MASTER_KEY, push]);
89− const validateForm = useCallback((values, errors) => {
40+ // Fade in on load
90− didWarn.current = false;
92− if (hasErrors(errors)) {
97− const validate = useMemo(
100− { ticket: buildPatqValidator(), showTicket: buildCheckboxValidator() },
106− const loadL1Points = useCallback(
107− async (address: string): Promise<number[]> => {
108− const _contracts = need.contracts(contracts);
109− const owned = await azimuth.azimuth.getOwnedPoints(_contracts, address);
110− const transferring = await azimuth.azimuth.getTransferringFor(
114− const incoming = [...owned, ...transferring];
115− console.log('incoming L1 points', incoming);
121− const loadl2points = useCallback(
122− async (address: string): Promise<Ship[]> => {
123− const owned = await getPoints(POINT_PROXIES.OWN, address);
124− const transferring = await getPoints(POINT_PROXIES.TRANSFER, address);
125− const incoming = [...owned, ...transferring];
126− console.log('incoming L2 points', incoming);
132− // derive and set our state on submission
133− const onSubmit = useCallback(
135− setIsGenerating(true);
137− await timeout(1900); // Allow the Master Key animation to run for one cycle
140− // TODO: fallback logic to first use implied values if present, otherwise form values?
141− const ticket = impliedTicket || values.ticket;
142− const { seed } = await generateTemporaryOwnershipWallet(ticket);
143− const inviteWallet = walletFromMnemonic(seed, DEFAULT_HD_PATH);
144− setInviteWallet(inviteWallet);
145− const _inviteWallet = need.wallet(inviteWallet);
146− const inviteAddress = _inviteWallet.address;
148− // Query for points depending on point's dominion
149− const rollerPoint = await api.getPoint(impliedAzimuthPoint!);
150− let incoming: number[] | Ship[];
151− if (rollerPoint.dominion === POINT_DOMINIONS.L2) {
152− incoming = await loadl2points(inviteAddress);
154− incoming = await loadL1Points(inviteAddress);
158− if (incoming.length > 0) {
159− if (incoming.length > 1 && !didWarn.current) {
160− didWarn.current = true;
161− setIsGenerating(false);
165− 'This invite code has multiple points available. ' +
166− "Once you've activated this point, " +
167− 'activate the next with the same process.',
171− const point = convertToInt(incoming[0], 10);
173− setDerivedPoint(Just(point));
174− setDerivedWallet(Just(await generateWallet(point, true)));
176− setIsGenerating(false);
180− 'Invite code has no claimable point.\n' +
181− 'Check your invite code and try again?',
187− impliedAzimuthPoint,
198− const initialValues = useMemo(
199− () => ({ ticket: impliedTicket || '', showTicket: true }),
203 useEffect(() => {
41 useEffect(() => {
204− const fetchRollerPoint = async () => {
42+ setIsIn(true);
205− if (!impliedAzimuthPoint) {
43+ }, [setIsIn]);
208− const p = await api.getPoint(impliedAzimuthPoint!);
213− }, [api, impliedAzimuthPoint]);
215− const footer = useMemo(() => {
219− flexDirection="column"
222− justifyContent="flex-end">
227− afterSubmit={goToMasterKey}
228− initialValues={initialValues}>
229− {({ validating, values, submitting, handleSubmit }) => (
231− {!impliedTicket && (
236− type={values.showTicket ? 'text' : 'password'}
238− label="Activation Code"
239− disabled={!activationAllowed}
251− <Grid.Item full as={FormError} />
257− handleSubmit={handleSubmit}>
264− ? 'Continue Activation'
269− {!activationAllowed && (
270− <Grid.Item full as={WarningBox} className="mt4">
271− For your security, please access Bridge on a desktop device.
290 <View inset>
46 <View inset>
291 <ActivateView
47 <ActivateView
294− <ActivateHeader copy={'Welcome. This is your Urbit.'} />
49+ <ActivateHeader copy={'Welcome. This is your Urbit.'} isIn={isIn} />
297− footer={!isGenerating && footer}>
51+ footer={<ActivateCodeForm afterSubmit={goToMasterKey} />}>
299 alignItems={'center'}
53 alignItems={'center'}
300 display={'flex'}
54 display={'flex'}
@@ -305,22 +59,7 @@ export default function ActivateCode() {
305 {!impliedTicket && (
59 {!impliedTicket && (
306 <Text className="mb2">Enter your activation code to continue.</Text>
60 <Text className="mb2">Enter your activation code to continue.</Text>
308− {!isGenerating && impliedPatp && (
310− patp={impliedPatp}
62+ {impliedPatp && <PointPresenter patp={impliedPatp} isIn={isIn} />}
311− className={!isFaded ? 'faded-in' : 'faded-out'}
316− flexDirection={'row'}
318− className={isFaded ? 'faded-in' : 'faded-out'}
320− height={'min-content'}
321− justifyContent={'center'}>
325 </ActivateView>
64 </ActivateView>