on master help sign in
Merge pull request #238 from urbit/feat/copy-things
43a012aMatt Condon
src/components/InlineEthereumTransaction.js+5−3
@@ -22,6 +22,7 @@ import { GenerateButton, ForwardButton, RestartButton } from './Buttons';
22import WarningBox from './WarningBox';
22import WarningBox from './WarningBox';
23import CopyButton from './CopyButton';
23import CopyButton from './CopyButton';
24import ProgressButton from './ProgressButton';
24import ProgressButton from './ProgressButton';
25+import CopiableAddress from './CopiableAddress';
25
26
26export default function InlineEthereumTransaction({
27export default function InlineEthereumTransaction({
27 // from useEthereumTransaction.bind
28 // from useEthereumTransaction.bind
@@ -144,15 +145,16 @@ export default function InlineEthereumTransaction({
144 {renderPrimarySection()}
145 {renderPrimarySection()}
145
146
146 {error && (
147 {error && (
147− <Grid.Item full as={ErrorText} className="mt1">
148+ <Grid.Item full as={ErrorText} className="mv1">
148 {error.message}
149 {error.message}
149 </Grid.Item>
150 </Grid.Item>
150 )}
151 )}
151
152
152 {needFunds && (
153 {needFunds && (
153 <Grid.Item full as={WarningBox} className="mt3">
154 <Grid.Item full as={WarningBox} className="mt3">
155+ The address{' '}
154− The address {needFunds.address} needs at least{' '}
156+ <CopiableAddress>{needFunds.address}</CopiableAddress> needs at
155− {fromWei(needFunds.minBalance)} ETH and currently has{' '}
157+ least {fromWei(needFunds.minBalance)} ETH and currently has{' '}
156 {fromWei(needFunds.balance)} ETH. Waiting until the account has
158 {fromWei(needFunds.balance)} ETH. Waiting until the account has
157 enough funds.
159 enough funds.
158 </Grid.Item>
160 </Grid.Item>
src/indigo-react/components/Button.js+3−2
@@ -6,13 +6,14 @@ import Flex from './Flex';
6import { HelpText } from './Typography';
6import { HelpText } from './Typography';
7
7
8export default function Button({
8export default function Button({
9− as: As = 'a',
9+ as: As = 'span',
10 solid = false,
10 solid = false,
11 success = false,
11 success = false,
12 disabled = false,
12 disabled = false,
13 disabledDetail,
13 disabledDetail,
14 detail,
14 detail,
15 className,
15 className,
16+ detailClassName,
16 accessory = '→',
17 accessory = '→',
17 onClick,
18 onClick,
18 background,
19 background,
@@ -56,7 +57,7 @@ export default function Button({
56 <div className={cn('pl4')}>{accessory}</div>
57 <div className={cn('pl4')}>{accessory}</div>
57 </Grid.Item>
58 </Grid.Item>
58 {detail && (
59 {detail && (
59− <Grid.Item full as={HelpText} className="z2">
60+ <Grid.Item full as={HelpText} className={cn('z2', detailClassName)}>
60 {detail}
61 {detail}
61 </Grid.Item>
62 </Grid.Item>
62 )}
63 )}
src/views/Activate/PassportTransfer.js+3−2
@@ -22,6 +22,7 @@ import { RestartButton } from 'components/Buttons';
22
22
23import { useActivateFlow } from './ActivateFlow';
23import { useActivateFlow } from './ActivateFlow';
24import PassportView from './PassportView';
24import PassportView from './PassportView';
25+import CopiableAddress from 'components/CopiableAddress';
25
26
26const labelForProgress = progress => {
27const labelForProgress = progress => {
27 if (progress <= 0) {
28 if (progress <= 0) {
@@ -163,8 +164,8 @@ export default function PassportTransfer({ className, resetActivateRouter }) {
163 return (
164 return (
164 <Grid.Item full className="mt8">
165 <Grid.Item full className="mt8">
165 <Highlighted warning>
166 <Highlighted warning>
166− The address {needFunds.address} needs at least{' '}
167+ The address <CopiableAddress>{needFunds.address}</CopiableAddress>{' '}
167− {fromWei(needFunds.minBalance)} ETH and currently has{' '}
168+ needs at least {fromWei(needFunds.minBalance)} ETH and currently has{' '}
168 {fromWei(needFunds.balance)} ETH. Waiting until the account has
169 {fromWei(needFunds.balance)} ETH. Waiting until the account has
169 enough funds.
170 enough funds.
170 </Highlighted>
171 </Highlighted>
src/views/Admin/AdminEditPermissions.js+19−10
@@ -1,6 +1,6 @@
1import React, { useCallback } from 'react';
1import React, { useCallback } from 'react';
2import { Just, Nothing } from 'folktale/maybe';
2import { Just, Nothing } from 'folktale/maybe';
3−import { Grid } from 'indigo-react';
3+import { Grid, LinkButton } from 'indigo-react';
4import { azimuth } from 'azimuth-js';
4import { azimuth } from 'azimuth-js';
5
5
6import { useNetwork } from 'store/network';
6import { useNetwork } from 'store/network';
@@ -18,6 +18,7 @@ import useCurrentPermissions from 'lib/useCurrentPermissions';
18import ViewHeader from 'components/ViewHeader';
18import ViewHeader from 'components/ViewHeader';
19import { ForwardButton } from 'components/Buttons';
19import { ForwardButton } from 'components/Buttons';
20import { matchBlinkyDate } from 'components/Blinky';
20import { matchBlinkyDate } from 'components/Blinky';
21+import CopyButton from 'components/CopyButton';
21
22
22export default function AdminEditPermissions() {
23export default function AdminEditPermissions() {
23 const { push, names } = useLocalRouter();
24 const { push, names } = useLocalRouter();
@@ -55,13 +56,15 @@ export default function AdminEditPermissions() {
55
56
56 return (
57 return (
57 <>
58 <>
58− <Grid.Item full>
59+ <Grid.Item
60+ full
59− <ForwardButton
61+ as={ForwardButton}
60− disabled={!isOwner}
62+ disabled={!isOwner}
61− onClick={() => goSetProxy(proxyType)}
63+ onClick={() => goSetProxy(proxyType)}
62− detail={address}>
64+ detail={address}
65+ detailClassName="mono"
66+ accessory={<LinkButton>Edit</LinkButton>}>
63− {capitalize(proxyTypeToHuman(proxyType))} Proxy Address
67+ {capitalize(proxyTypeToHuman(proxyType))} Proxy Address
64− </ForwardButton>
65 </Grid.Item>
68 </Grid.Item>
66 <Grid.Divider />
69 <Grid.Divider />
67 </>
70 </>
@@ -95,7 +98,12 @@ export default function AdminEditPermissions() {
95 Permissions
98 Permissions
96 </Grid.Item>
99 </Grid.Item>
97
100
101+ <Grid.Item
102+ full
103+ as={ForwardButton}
98− <Grid.Item full as={ForwardButton} detail={details.owner} disabled>
104+ detail={details.owner}
105+ detailClassName="mono"
106+ accessory={<CopyButton text={details.owner} />}>
99 Ownership Address
107 Ownership Address
100 </Grid.Item>
108 </Grid.Item>
101 <Grid.Divider />
109 <Grid.Divider />
@@ -111,7 +119,8 @@ export default function AdminEditPermissions() {
111 as={ForwardButton}
119 as={ForwardButton}
112 disabled={!canManage}
120 disabled={!canManage}
113 onClick={goNetworkingKeys}
121 onClick={goNetworkingKeys}
114− detail={renderNetworkKeysDetail()}>
122+ detail={renderNetworkKeysDetail()}
123+ accessory={<LinkButton>View</LinkButton>}>
115 Networking Keys
124 Networking Keys
116 </Grid.Item>
125 </Grid.Item>
117 <Grid.Divider />
126 <Grid.Divider />
src/views/Admin/Reticket/ReticketExecute.js+3−2
@@ -21,6 +21,7 @@ import WarningBox from 'components/WarningBox';
21import LoadingBar from 'components/LoadingBar';
21import LoadingBar from 'components/LoadingBar';
22import Highlighted from 'components/Highlighted';
22import Highlighted from 'components/Highlighted';
23import { WALLET_TYPES } from 'lib/wallet';
23import { WALLET_TYPES } from 'lib/wallet';
24+import CopiableAddress from 'components/CopiableAddress';
24
25
25const labelForProgress = progress => {
26const labelForProgress = progress => {
26 if (progress <= 0) {
27 if (progress <= 0) {
@@ -129,8 +130,8 @@ export default function ReticketExecute({ newWallet, setNewWallet }) {
129 return (
130 return (
130 <Grid.Item full className="mt4">
131 <Grid.Item full className="mt4">
131 <Highlighted warning>
132 <Highlighted warning>
132− The address {needFunds.address} needs at least{' '}
133+ The address <CopiableAddress>{needFunds.address}</CopiableAddress>{' '}
133− {fromWei(needFunds.minBalance)} ETH and currently has{' '}
134+ needs at least {fromWei(needFunds.minBalance)} ETH and currently has{' '}
134 {fromWei(needFunds.balance)} ETH. Waiting until the account has
135 {fromWei(needFunds.balance)} ETH. Waiting until the account has
135 enough funds.
136 enough funds.
136 </Highlighted>
137 </Highlighted>
src/views/CreateGalaxy.js+2−1
@@ -25,6 +25,7 @@ import {
25 hasErrors,
25 hasErrors,
26} from 'form/validators';
26} from 'form/validators';
27import FormError from 'form/FormError';
27import FormError from 'form/FormError';
28+import CopiableAddress from 'components/CopiableAddress';
28
29
29function useCreateGalaxy() {
30function useCreateGalaxy() {
30 const { contracts } = useNetwork();
31 const { contracts } = useNetwork();
@@ -127,7 +128,7 @@ export default function CreateGalaxy() {
127 green3: completed,
128 green3: completed,
128 })}>
129 })}>
129 {values.galaxyName} has been created and can be claimed by{' '}
130 {values.galaxyName} has been created and can be claimed by{' '}
130− {values.owner}.
131+ <CopiableAddress>{values.owner}</CopiableAddress>.
131 </Grid.Item>
132 </Grid.Item>
132 )}
133 )}
133
134
src/views/Disclaimer.js+1−2
@@ -62,8 +62,7 @@ export default function ActivateDisclaimer() {
62 2. JSON files <br />
62 2. JSON files <br />
63 3. Hardware wallet PINs; <br />
63 3. Hardware wallet PINs; <br />
64 4. Downloading this software from a reliable site, and ensuring it
64 4. Downloading this software from a reliable site, and ensuring it
65− has not been tampered with. [add something about using the checksum
65+ has not been tampered with.
66− here]
67 </Text>
66 </Text>
68
67
69 <B className={TEXT_STYLE}>To be clear</B>
68 <B className={TEXT_STYLE}>To be clear</B>
src/views/Invite/InviteEmail.js+8−3
@@ -58,7 +58,9 @@ import 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';
60import timeout from 'lib/timeout';
60import timeout from 'lib/timeout';
61+
61import { ForwardButton } from 'components/Buttons';
62import { ForwardButton } from 'components/Buttons';
63+import CopiableAddress from 'components/CopiableAddress';
62
64
63const INITIAL_VALUES = { emails: [''] };
65const INITIAL_VALUES = { emails: [''] };
64
66
@@ -584,9 +586,12 @@ export default function InviteEmail() {
584 {needFunds && (
586 {needFunds && (
585 <Grid.Item full>
587 <Grid.Item full>
586 <Highlighted warning>
588 <Highlighted warning>
587− Your ownership address {needFunds.address} needs at
589+ Your ownership address{' '}
590+ <CopiableAddress>
591+ {needFunds.address}
592+ </CopiableAddress>{' '}
588− least {fromWei(needFunds.minBalance)} ETH and
593+ needs at least {fromWei(needFunds.minBalance)} ETH
589− currently has {fromWei(needFunds.balance)} ETH.
594+ and currently has {fromWei(needFunds.balance)} ETH.
590 Waiting until the account has enough funds.
595 Waiting until the account has enough funds.
591 </Highlighted>
596 </Highlighted>
592 </Grid.Item>
597 </Grid.Item>
src/views/IssueChild.js+3−2
@@ -28,6 +28,7 @@ import {
28} from 'form/validators';
28} from 'form/validators';
29import BridgeForm from 'form/BridgeForm';
29import BridgeForm from 'form/BridgeForm';
30import FormError from 'form/FormError';
30import FormError from 'form/FormError';
31+import CopiableAddress from 'components/CopiableAddress';
31
32
32function useIssueChild() {
33function useIssueChild() {
33 const { contracts } = useNetwork();
34 const { contracts } = useNetwork();
@@ -84,7 +85,7 @@ export default function IssueChild() {
84
85
85 const validateFormAsync = useCallback(
86 const validateFormAsync = useCallback(
86 async values => {
87 async values => {
87− const point = patp2dec(values.name);
88+ const point = patp2dec(values.point);
88 const hasPoint = (await availablePointsPromise).has(point);
89 const hasPoint = (await availablePointsPromise).has(point);
89
90
90 if (!hasPoint) {
91 if (!hasPoint) {
@@ -153,7 +154,7 @@ export default function IssueChild() {
153 green3: completed,
154 green3: completed,
154 })}>
155 })}>
155 {values.point} has been spawned and can be claimed by{' '}
156 {values.point} has been spawned and can be claimed by{' '}
156− {values.owner}.
157+ <CopiableAddress>{values.owner}</CopiableAddress>.
157 </Grid.Item>
158 </Grid.Item>
158 )}
159 )}
159
160
src/views/Party/PartySetPoolSize.js+12−6
@@ -27,6 +27,7 @@ import {
27 buildPointValidator,
27 buildPointValidator,
28} from 'form/validators';
28} from 'form/validators';
29import FormError from 'form/FormError';
29import FormError from 'form/FormError';
30+import CopiableAddress from 'components/CopiableAddress';
30
31
31function useSetPoolSize() {
32function useSetPoolSize() {
32 const { contracts } = useNetwork();
33 const { contracts } = useNetwork();
@@ -98,11 +99,11 @@ export default function PartySetPoolSize() {
98 </Grid.Item>
99 </Grid.Item>
99
100
100 {!spawnIsDelegatedSending && (
101 {!spawnIsDelegatedSending && (
101− <Grid.Item full as={WarningBox} className="mb4">
102+ <Grid.Item full as={WarningBox} className="mb4 f6">
102 The spawn proxy must be set to{' '}
103 The spawn proxy must be set to{' '}
103− <code className="mono f6">
104+ <CopiableAddress>
104 {_contracts.delegatedSending.address}
105 {_contracts.delegatedSending.address}
105− </code>{' '}
106+ </CopiableAddress>{' '}
106 for invitations to be available.
107 for invitations to be available.
107 </Grid.Item>
108 </Grid.Item>
108 )}
109 )}
@@ -119,9 +120,14 @@ export default function PartySetPoolSize() {
119 className={cn('f5 wrap', {
120 className={cn('f5 wrap', {
120 green3: completed,
121 green3: completed,
121 })}>
122 })}>
122− {completed
123+ {completed ? (
124+ <>
123− ? `${values.poolSize} invites have been allocated to ${values.poolOwner}`
125+ {values.poolSize} invites have been allocated to{' '}
126+ <CopiableAddress>{values.poolOwner}</CopiableAddress>
127+ </>
128+ ) : (
124− : `Allocate invites to a child point.`}
129+ `Allocate invites to a child point.`
130+ )}
125 </Grid.Item>
131 </Grid.Item>
126
132
127 {!completed && (
133 {!completed && (
src/views/Points.js+10−4
@@ -12,12 +12,13 @@ import * as need from 'lib/need';
12import { isZeroAddress, abbreviateAddress } from 'lib/wallet';
12import { isZeroAddress, abbreviateAddress } from 'lib/wallet';
13import useIsEclipticOwner from 'lib/useIsEclipticOwner';
13import useIsEclipticOwner from 'lib/useIsEclipticOwner';
14import { useSyncKnownPoints } from 'lib/useSyncPoints';
14import { useSyncKnownPoints } from 'lib/useSyncPoints';
15+import useRejectedIncomingPointTransfers from 'lib/useRejectedIncomingPointTransfers';
16+import pluralize from 'lib/pluralize';
17+import useCopiable from 'lib/useCopiable';
15
18
16import View from 'components/View';
19import View from 'components/View';
17import Blinky from 'components/Blinky';
20import Blinky from 'components/Blinky';
18import Passport from 'components/Passport';
21import Passport from 'components/Passport';
19−import useRejectedIncomingPointTransfers from 'lib/useRejectedIncomingPointTransfers';
20−import pluralize from 'lib/pluralize';
21import Footer from 'components/Footer';
22import Footer from 'components/Footer';
22import { ForwardButton } from 'components/Buttons';
23import { ForwardButton } from 'components/Buttons';
23
24
@@ -162,6 +163,7 @@ export default function Points() {
162 ]);
163 ]);
163
164
164 const address = need.addressFromWallet(wallet);
165 const address = need.addressFromWallet(wallet);
166+ const [doCopy, didCopy] = useCopiable(address);
165
167
166 const loading = Nothing.hasInstance(controlledPoints);
168 const loading = Nothing.hasInstance(controlledPoints);
167
169
@@ -208,8 +210,12 @@ export default function Points() {
208 return (
210 return (
209 <View pop={pop} inset>
211 <View pop={pop} inset>
210 <Grid>
212 <Grid>
213+ <Grid.Item
214+ full
215+ as={H1}
211− <Grid.Item full as={H1} className="f6 mono gray4 mb4">
216+ className="f6 mono gray4 mb4 us-none clickable"
217+ onClick={doCopy}>
212− {abbreviateAddress(address)}
218+ {`${abbreviateAddress(address)}${didCopy ? ' (copied!)' : ''}`}
213 </Grid.Item>
219 </Grid.Item>
214
220
215 {loading && (
221 {loading && (