@@ -4,7 +4,7 @@ import { WARNING } from 'form/helpers';
4import { FORM_ERROR } from 'final-form';
4import { FORM_ERROR } from 'final-form';
5import { Just } from 'folktale/maybe';
5import { Just } from 'folktale/maybe';
6import BridgeForm from 'form/BridgeForm';
6import BridgeForm from 'form/BridgeForm';
7−import { TicketInput } from 'form/Inputs';
7+import { PLACEHOLDER_PLANET, PLACEHOLDER_TICKET, TicketInput } from 'form/Inputs';
9 composeValidator,
9 composeValidator,
10 buildPatqValidator,
10 buildPatqValidator,
@@ -12,7 +12,7 @@ import {
12 buildCheckboxValidator,
12 buildCheckboxValidator,
13} from 'form/validators';
13} from 'form/validators';
14import FormError from 'form/FormError';
14import FormError from 'form/FormError';
15−import { CheckboxInput, Grid } from 'indigo-react';
15+import { Grid } from 'indigo-react';
16import { useCallback, useMemo, useRef } from 'react';
16import { useCallback, useMemo, useRef } from 'react';
17import { useActivateFlow } from './ActivateFlow';
17import { useActivateFlow } from './ActivateFlow';
18import WarningBox from 'components/WarningBox';
18import WarningBox from 'components/WarningBox';
@@ -21,13 +21,15 @@ import useImpliedTicket from 'lib/useImpliedTicket';
21import { generateWallet } from 'lib/walletgen';
21import { generateWallet } from 'lib/walletgen';
22import { urbitWalletFromTicket, walletFromMnemonic } from 'lib/wallet';
22import { urbitWalletFromTicket, walletFromMnemonic } from 'lib/wallet';
23import { DEFAULT_HD_PATH, POINT_PROXIES } from 'lib/constants';
23import { DEFAULT_HD_PATH, POINT_PROXIES } from 'lib/constants';
24−import useBreakpoints from 'lib/useBreakpoints';
24+import useBreakpoints from 'lib/useBreakpoints.tsx';
25import { Ship } from '@urbit/roller-api';
25import { Ship } from '@urbit/roller-api';
26import { convertToInt } from 'lib/convertToInt';
26import { convertToInt } from 'lib/convertToInt';
27import { Box } from '@tlon/indigo-react';
27import { Box } from '@tlon/indigo-react';
28import { timeout } from 'lib/timeout';
28import { timeout } from 'lib/timeout';
29import withFadeable from './withFadeable';
29import withFadeable from './withFadeable';
30import ActivateButton from './ActivateButton';
30import ActivateButton from './ActivateButton';
31+import TicketInputAccessory from 'components/form/TicketInputAccessory';
32+import { validateActivationTicket } from 'lib/validators';
32interface ActivateCodeFormProps {
34interface ActivateCodeFormProps {
33 afterSubmit: VoidFunction;
35 afterSubmit: VoidFunction;
@@ -46,7 +48,7 @@ const ActivateCodeForm = ({ afterSubmit }: ActivateCodeFormProps) => {
46 setInviteWallet,
48 setInviteWallet,
48 setSendWallet,
50 setSendWallet,
49− } = useActivateFlow();
51+ }: any = useActivateFlow();
51 // this is a pretty naive way to detect if we're on a mobile device
53 // this is a pretty naive way to detect if we're on a mobile device
52 // (i.e. we're checking the width of the screen)
54 // (i.e. we're checking the width of the screen)
@@ -69,12 +71,20 @@ const ActivateCodeForm = ({ afterSubmit }: ActivateCodeFormProps) => {
69 const validate = useMemo(
71 const validate = useMemo(
71 composeValidator(
73 composeValidator(
75+ ticket: buildPatqValidator([validateActivationTicket]),
72− { ticket: buildPatqValidator(), showTicket: buildCheckboxValidator() },
76+ showTicket: buildCheckboxValidator(),
73 validateForm
78 validateForm
75 [validateForm]
80 [validateForm]
83+ const hasInitialValues = useMemo(
84+ () => Boolean(impliedTicket && impliedPatp),
85+ [impliedTicket, impliedPatp]
78 const getTicketAndPoint = useCallback(
88 const getTicketAndPoint = useCallback(
79 (invite: string) => {
89 (invite: string) => {
80 const segments = invite.split('-');
90 const segments = invite.split('-');
@@ -164,20 +174,24 @@ const ActivateCodeForm = ({ afterSubmit }: ActivateCodeFormProps) => {
164 setDerivedWallet,
174 setDerivedWallet,
165 setInviteWallet,
175 setInviteWallet,
170 const initialValues = useMemo(
181 const initialValues = useMemo(
183+ ticket: hasInitialValues
184+ ? `${impliedTicket}-${impliedPatp?.slice(1)}`
171− () => ({ ticket: impliedTicket || '', showTicket: true }),
186+ showTicket: true,
172− [impliedTicket]
188+ [impliedTicket, impliedPatp, hasInitialValues]
177− display="flex"
193+ className="w-full h-full flex-col"
178− flexDirection="column"
179 flexWrap="nowrap"
194 flexWrap="nowrap"
181 justifyContent="flex-end">
195 justifyContent="flex-end">
182 <BridgeForm
196 <BridgeForm
183 validate={validate}
197 validate={validate}
@@ -186,41 +200,28 @@ const ActivateCodeForm = ({ afterSubmit }: ActivateCodeFormProps) => {
186 initialValues={initialValues}>
200 initialValues={initialValues}>
187 {({ valid, validating, values, submitting, handleSubmit }) => (
201 {({ valid, validating, values, submitting, handleSubmit }) => (
189− {!impliedTicket && (
203+ {!hasInitialValues && (
191− <Grid.Item
204+ <Grid.Item
193− as={TicketInput}
207+ as={TicketInput}
208+ accessory={<TicketInputAccessory name="showTicket" />}
194− type={values.showTicket ? 'text' : 'password'}
209+ type={values.showTicket ? 'text' : 'password'}
195− name="ticket"
210+ name="ticket"
196− label="Activation Code"
197− disabled={!activationAllowed}
211+ disabled={!activationAllowed}
198− />
212+ placeholder={`${PLACEHOLDER_TICKET}-${PLACEHOLDER_PLANET.slice(
209− <Grid.Item full as={FormError} />
218+ <Grid.Item full as={FormError} className="mb2" />
211− <Box
220+ <ActivateButton
213− flexDirection="column"
217− justifyContent="flex-end">
219− disabled={!valid || submitting}
221+ disabled={(!valid && !hasInitialValues) || submitting}
220− onClick={handleSubmit}>
222+ onClick={handleSubmit}>
221− {submitting ? 'Generating...' : 'Claim'}
223+ {submitting ? 'Activating...' : 'Activate'}
222− </ActivateButton>
224+ </ActivateButton>
225 {!activationAllowed && (
226 {!activationAllowed && (
226 <Grid.Item full as={WarningBox} className="mt4">
227 <Grid.Item full as={WarningBox} className="mt4">