on master help sign in
ux: restore Access Code to Urbit OS view
08176cftomholford
package-lock.json+188
@@ -6788,6 +6788,155 @@
6788 "defer-to-connect": "^1.0.1"
6788 "defer-to-connect": "^1.0.1"
6789 }
6789 }
6790 },
6790 },
6791+ "@testing-library/dom": {
6792+ "version": "8.1.0",
6793+ "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.1.0.tgz",
6794+ "integrity": "sha512-kmW9alndr19qd6DABzQ978zKQ+J65gU2Rzkl8hriIetPnwpesRaK4//jEQyYh8fEALmGhomD/LBQqt+o+DL95Q==",
6795+ "dev": true,
6796+ "requires": {
6797+ "@babel/code-frame": "^7.10.4",
6798+ "@babel/runtime": "^7.12.5",
6799+ "@types/aria-query": "^4.2.0",
6800+ "aria-query": "^4.2.2",
6801+ "chalk": "^4.1.0",
6802+ "dom-accessibility-api": "^0.5.6",
6803+ "lz-string": "^1.4.4",
6804+ "pretty-format": "^27.0.2"
6805+ },
6806+ "dependencies": {
6807+ "@jest/types": {
6808+ "version": "27.0.6",
6809+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.0.6.tgz",
6810+ "integrity": "sha512-aSquT1qa9Pik26JK5/3rvnYb4bGtm1VFNesHKmNTwmPIgOrixvhL2ghIvFRNEpzy3gU+rUgjIF/KodbkFAl++g==",
6811+ "dev": true,
6812+ "requires": {
6813+ "@types/istanbul-lib-coverage": "^2.0.0",
6814+ "@types/istanbul-reports": "^3.0.0",
6815+ "@types/node": "*",
6816+ "@types/yargs": "^16.0.0",
6817+ "chalk": "^4.0.0"
6818+ }
6819+ },
6820+ "@types/yargs": {
6821+ "version": "16.0.4",
6822+ "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz",
6823+ "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==",
6824+ "dev": true,
6825+ "requires": {
6826+ "@types/yargs-parser": "*"
6827+ }
6828+ },
6829+ "ansi-styles": {
6830+ "version": "5.2.0",
6831+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
6832+ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
6833+ "dev": true
6834+ },
6835+ "pretty-format": {
6836+ "version": "27.0.6",
6837+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.0.6.tgz",
6838+ "integrity": "sha512-8tGD7gBIENgzqA+UBzObyWqQ5B778VIFZA/S66cclyd5YkFLYs2Js7gxDKf0MXtTc9zcS7t1xhdfcElJ3YIvkQ==",
6839+ "dev": true,
6840+ "requires": {
6841+ "@jest/types": "^27.0.6",
6842+ "ansi-regex": "^5.0.0",
6843+ "ansi-styles": "^5.0.0",
6844+ "react-is": "^17.0.1"
6845+ }
6846+ },
6847+ "react-is": {
6848+ "version": "17.0.2",
6849+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
6850+ "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==",
6851+ "dev": true
6852+ }
6853+ }
6854+ },
6855+ "@testing-library/jest-dom": {
6856+ "version": "5.14.1",
6857+ "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.14.1.tgz",
6858+ "integrity": "sha512-dfB7HVIgTNCxH22M1+KU6viG5of2ldoA5ly8Ar8xkezKHKXjRvznCdbMbqjYGgO2xjRbwnR+rR8MLUIqF3kKbQ==",
6859+ "dev": true,
6860+ "requires": {
6861+ "@babel/runtime": "^7.9.2",
6862+ "@types/testing-library__jest-dom": "^5.9.1",
6863+ "aria-query": "^4.2.2",
6864+ "chalk": "^3.0.0",
6865+ "css": "^3.0.0",
6866+ "css.escape": "^1.5.1",
6867+ "dom-accessibility-api": "^0.5.6",
6868+ "lodash": "^4.17.15",
6869+ "redent": "^3.0.0"
6870+ },
6871+ "dependencies": {
6872+ "chalk": {
6873+ "version": "3.0.0",
6874+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
6875+ "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
6876+ "dev": true,
6877+ "requires": {
6878+ "ansi-styles": "^4.1.0",
6879+ "supports-color": "^7.1.0"
6880+ }
6881+ },
6882+ "css": {
6883+ "version": "3.0.0",
6884+ "resolved": "https://registry.npmjs.org/css/-/css-3.0.0.tgz",
6885+ "integrity": "sha512-DG9pFfwOrzc+hawpmqX/dHYHJG+Bsdb0klhyi1sDneOgGOXy9wQIC8hzyVp1e4NRYDBdxcylvywPkkXCHAzTyQ==",
6886+ "dev": true,
6887+ "requires": {
6888+ "inherits": "^2.0.4",
6889+ "source-map": "^0.6.1",
6890+ "source-map-resolve": "^0.6.0"
6891+ }
6892+ },
6893+ "redent": {
6894+ "version": "3.0.0",
6895+ "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz",
6896+ "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==",
6897+ "dev": true,
6898+ "requires": {
6899+ "indent-string": "^4.0.0",
6900+ "strip-indent": "^3.0.0"
6901+ }
6902+ },
6903+ "source-map": {
6904+ "version": "0.6.1",
6905+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
6906+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
6907+ "dev": true
6908+ },
6909+ "source-map-resolve": {
6910+ "version": "0.6.0",
6911+ "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.6.0.tgz",
6912+ "integrity": "sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w==",
6913+ "dev": true,
6914+ "requires": {
6915+ "atob": "^2.1.2",
6916+ "decode-uri-component": "^0.2.0"
6917+ }
6918+ },
6919+ "strip-indent": {
6920+ "version": "3.0.0",
6921+ "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz",
6922+ "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==",
6923+ "dev": true,
6924+ "requires": {
6925+ "min-indent": "^1.0.0"
6926+ }
6927+ }
6928+ }
6929+ },
6930+ "@testing-library/react": {
6931+ "version": "12.0.0",
6932+ "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-12.0.0.tgz",
6933+ "integrity": "sha512-sh3jhFgEshFyJ/0IxGltRhwZv2kFKfJ3fN1vTZ6hhMXzz9ZbbcTgmDYM4e+zJv+oiVKKEWZPyqPAh4MQBI65gA==",
6934+ "dev": true,
6935+ "requires": {
6936+ "@babel/runtime": "^7.12.5",
6937+ "@testing-library/dom": "^8.0.0"
6938+ }
6939+ },
6791 "@textile/buckets": {
6940 "@textile/buckets": {
6792 "version": "6.0.5",
6941 "version": "6.0.5",
6793 "resolved": "https://registry.npmjs.org/@textile/buckets/-/buckets-6.0.5.tgz",
6942 "resolved": "https://registry.npmjs.org/@textile/buckets/-/buckets-6.0.5.tgz",
@@ -7958,6 +8107,12 @@
7958 "@types/node": "*"
8107 "@types/node": "*"
7959 }
8108 }
7960 },
8109 },
8110+ "@types/aria-query": {
8111+ "version": "4.2.2",
8112+ "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-4.2.2.tgz",
8113+ "integrity": "sha512-HnYpAE1Y6kRyKM/XkEuiRQhTHvkzMBurTHnpFLYLBGPIylZNPs9jJcuOOYWxPLJCSEtmZT0Y8rHDokKN7rRTig==",
8114+ "dev": true
8115+ },
7961 "@types/babel__core": {
8116 "@types/babel__core": {
7962 "version": "7.1.14",
8117 "version": "7.1.14",
7963 "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.14.tgz",
8118 "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.14.tgz",
@@ -8386,6 +8541,15 @@
8386 "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.7.tgz",
8541 "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.7.tgz",
8387 "integrity": "sha512-0VBprVqfgFD7Ehb2vd8Lh9TG3jP98gvr8rgehQqzztZNI7o8zS8Ad4jyZneKELphpuE212D8J70LnSNQSyO6bQ=="
8542 "integrity": "sha512-0VBprVqfgFD7Ehb2vd8Lh9TG3jP98gvr8rgehQqzztZNI7o8zS8Ad4jyZneKELphpuE212D8J70LnSNQSyO6bQ=="
8388 },
8543 },
8544+ "@types/testing-library__jest-dom": {
8545+ "version": "5.14.1",
8546+ "resolved": "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.1.tgz",
8547+ "integrity": "sha512-Gk9vaXfbzc5zCXI9eYE9BI5BNHEp4D3FWjgqBE/ePGYElLAP+KvxBcsdkwfIVvezs605oiyd/VrpiHe3Oeg+Aw==",
8548+ "dev": true,
8549+ "requires": {
8550+ "@types/jest": "*"
8551+ }
8552+ },
8389 "@types/to-json-schema": {
8553 "@types/to-json-schema": {
8390 "version": "0.2.0",
8554 "version": "0.2.0",
8391 "resolved": "https://registry.npmjs.org/@types/to-json-schema/-/to-json-schema-0.2.0.tgz",
8555 "resolved": "https://registry.npmjs.org/@types/to-json-schema/-/to-json-schema-0.2.0.tgz",
@@ -12789,6 +12953,12 @@
12789 "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz",
12953 "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz",
12790 "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg=="
12954 "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg=="
12791 },
12955 },
12956+ "css.escape": {
12957+ "version": "1.5.1",
12958+ "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz",
12959+ "integrity": "sha1-QuJ9T6BK4y+TGktNQZH6nN3ul8s=",
12960+ "dev": true
12961+ },
12792 "cssdb": {
12962 "cssdb": {
12793 "version": "4.4.0",
12963 "version": "4.4.0",
12794 "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-4.4.0.tgz",
12964 "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-4.4.0.tgz",
@@ -13474,6 +13644,12 @@
13474 "esutils": "^2.0.2"
13644 "esutils": "^2.0.2"
13475 }
13645 }
13476 },
13646 },
13647+ "dom-accessibility-api": {
13648+ "version": "0.5.6",
13649+ "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.6.tgz",
13650+ "integrity": "sha512-DplGLZd8L1lN64jlT27N9TVSESFR5STaEJvX+thCby7fuCHonfPpAlodYc3vuUYbDuDec5w8AMP7oCM5TWFsqw==",
13651+ "dev": true
13652+ },
13477 "dom-converter": {
13653 "dom-converter": {
13478 "version": "0.2.0",
13654 "version": "0.2.0",
13479 "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz",
13655 "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz",
@@ -23293,6 +23469,12 @@
23293 "integrity": "sha1-81ypHEk/e3PaDgdJUwTxezH4fuU=",
23469 "integrity": "sha1-81ypHEk/e3PaDgdJUwTxezH4fuU=",
23294 "optional": true
23470 "optional": true
23295 },
23471 },
23472+ "lz-string": {
23473+ "version": "1.4.4",
23474+ "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.4.4.tgz",
23475+ "integrity": "sha1-wNjq82BZ9wV5bh40SBHPTEmNOiY=",
23476+ "dev": true
23477+ },
23296 "magic-string": {
23478 "magic-string": {
23297 "version": "0.25.7",
23479 "version": "0.25.7",
23298 "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz",
23480 "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz",
@@ -23628,6 +23810,12 @@
23628 "dom-walk": "^0.1.0"
23810 "dom-walk": "^0.1.0"
23629 }
23811 }
23630 },
23812 },
23813+ "min-indent": {
23814+ "version": "1.0.1",
23815+ "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz",
23816+ "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==",
23817+ "dev": true
23818+ },
23631 "mini-css-extract-plugin": {
23819 "mini-css-extract-plugin": {
23632 "version": "0.11.3",
23820 "version": "0.11.3",
23633 "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.11.3.tgz",
23821 "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.11.3.tgz",
package.json+3−1
@@ -79,6 +79,8 @@
79 "web3-utils": "^1.3.6"
79 "web3-utils": "^1.3.6"
80 },
80 },
81 "devDependencies": {
81 "devDependencies": {
82+ "@testing-library/jest-dom": "^5.14.1",
83+ "@testing-library/react": "^12.0.0",
82 "@types/keccak": "^3.0.1",
84 "@types/keccak": "^3.0.1",
83 "@types/lodash": "^4.14.170",
85 "@types/lodash": "^4.14.170",
84 "eslint-config-prettier": "^5.0.0",
86 "eslint-config-prettier": "^5.0.0",
@@ -97,7 +99,7 @@
97 "start": "react-scripts start",
99 "start": "react-scripts start",
98 "build": "react-scripts build",
100 "build": "react-scripts build",
99 "build:ropsten": "REACT_APP_ROPSTEN=true react-scripts build",
101 "build:ropsten": "REACT_APP_ROPSTEN=true react-scripts build",
100− "test": "react-scripts test --env=jsdom",
102+ "test": "react-scripts test --transformIgnorePatterns \"node_modules/(?!@tlon\/indigo-react)/\" --env=jsdom",
101 "eject": "react-scripts eject",
103 "eject": "react-scripts eject",
102 "checksum": "cd build && find . -exec shasum -a256 {} ';' > ../checksums.txt && cd ..",
104 "checksum": "cd build && find . -exec shasum -a256 {} ';' > ../checksums.txt && cd ..",
103 "zip": "BRIDGE_VERSION=${REACT_APP_BRIDGE_VERSION:-$npm_package_version}; zip -ur bridge-$BRIDGE_VERSION.zip README.md bridge-https.py checksums.txt && cd build && zip -ur ../bridge-$BRIDGE_VERSION.zip ./* && cd ..",
105 "zip": "BRIDGE_VERSION=${REACT_APP_BRIDGE_VERSION:-$npm_package_version}; zip -ur bridge-$BRIDGE_VERSION.zip README.md bridge-https.py checksums.txt && cd build && zip -ur ../bridge-$BRIDGE_VERSION.zip ./* && cd ..",
src/components/Buttons.js+8
@@ -1,5 +1,6 @@
1import React from 'react';
1import React from 'react';
2import { Button } from 'indigo-react';
2import { Button } from 'indigo-react';
3+import { Icon } from '@tlon/indigo-react';
3
4
4import { blinkIf } from './Blinky';
5import { blinkIf } from './Blinky';
5
6
@@ -23,3 +24,10 @@ export const OfflineButton = props => (
23 Offline
24 Offline
24 </OutButton>
25 </OutButton>
25);
26);
27+
28+export const CopyButton = props => (
29+ <Button
30+ accessory={<Icon icon="Copy" size="18px" color={'black'} />}
31+ {...props}
32+ />
33+);
src/components/CopyButton.js+10−19
@@ -2,7 +2,7 @@ import React from 'react';
2import cn from 'classnames';
2import cn from 'classnames';
3import { LinkButton } from 'indigo-react';
3import { LinkButton } from 'indigo-react';
4
4
5−import { ForwardButton } from 'components/Buttons';
5+import { CopyButton as BaseCopyButton } from 'components/Buttons';
6
6
7import useCopiable from 'lib/useCopiable';
7import useCopiable from 'lib/useCopiable';
8
8
@@ -30,28 +30,19 @@ export default function CopyButton({
30 );
30 );
31}
31}
32
32
33−export function CopyButtonWide({
33+export function CopyButtonWide({ text, children, ...rest }) {
34− as: As = ForwardButton,
35− text,
36− children,
37− accessory = renderDefaultCopyText,
38− ...rest
39−}) {
40 const [doCopy, didCopy] = useCopiable(text);
34 const [doCopy, didCopy] = useCopiable(text);
41 return (
35 return (
42− <As
36+ <BaseCopyButton
37+ as="span"
43 onClick={doCopy}
38 onClick={doCopy}
44− accessory={
39+ text={text}
45− <LinkButton
46− className={{
40+ className={cn({
47− black: !didCopy,
41+ black: !didCopy,
48− green3: didCopy,
42+ green3: didCopy,
49− }}>
50− {accessory(didCopy)}
51− </LinkButton>
52− }
43+ })}
53 {...rest}>
44 {...rest}>
54 {children}
45 {children}
55− </As>
46+ </BaseCopyButton>
56 );
47 );
57}
48}
src/setupTests.tsnew file+1
@@ -0,0 +1 @@
1+import '@testing-library/jest-dom';
src/views/UrbitOS/AccessCode.test.tsxnew file+30
@@ -0,0 +1,30 @@
1+import React from 'react';
2+import { render, screen } from '@testing-library/react';
3+import AccessCode from './AccessCode';
4+
5+describe('AccessCode', () => {
6+ describe('when code is not available', () => {
7+ // Value is initialized as `false` in `useKeyfileGenerator`
8+ const testCode = false;
9+
10+ it('does not render the component', () => {
11+ render(<AccessCode code={testCode} />);
12+ const accessCode = screen.queryByText(
13+ 'This is your code to access Urbit OS'
14+ );
15+ expect(accessCode).not.toBeInTheDocument()
16+ });
17+ });
18+
19+ describe('when code is available', () => {
20+ // Value has been loaded from `useKeyfileGenerator`
21+ const testCode = 'foo-bar';
22+
23+ it('renders the component', () => {
24+ render(<AccessCode code={testCode} />);
25+ expect(
26+ screen.getByText('This is your code to access Urbit OS')
27+ ).toBeInTheDocument();
28+ });
29+ });
30+});
src/views/UrbitOS/AccessCode.tsxnew file+23
@@ -0,0 +1,23 @@
1+import { CopyButtonWide } from 'components/CopyButton';
2+import { Grid } from 'indigo-react';
3+
4+type AccessCodeArgs = {
5+ code: boolean | string;
6+};
7+
8+const AccessCode = ({ code }: AccessCodeArgs) => {
9+ return code ? (
10+ <>
11+ <Grid.Divider />
12+ <Grid.Item
13+ full
14+ detail="This is your code to access Urbit OS"
15+ as={CopyButtonWide}
16+ text={code}>
17+ Access Key
18+ </Grid.Item>
19+ </>
20+ ) : null;
21+};
22+
23+export default AccessCode;
src/views/UrbitOS/Home.tsx+3−1
@@ -16,6 +16,7 @@ import { L1Point } from 'types/L1Point';
16import AlertBox from 'components/AlertBox';
16import AlertBox from 'components/AlertBox';
17import DownloadKeyfileButton from 'components/DownloadKeyfileButton';
17import DownloadKeyfileButton from 'components/DownloadKeyfileButton';
18import useKeyfileGenerator from 'lib/useKeyfileGenerator';
18import useKeyfileGenerator from 'lib/useKeyfileGenerator';
19+import AccessCode from './AccessCode';
19
20
20export default function UrbitOSHome({ manualNetworkSeed }) {
21export default function UrbitOSHome({ manualNetworkSeed }) {
21 const { pointCursor } = usePointCursor();
22 const { pointCursor } = usePointCursor();
@@ -47,7 +48,7 @@ export default function UrbitOSHome({ manualNetworkSeed }) {
47 names,
48 names,
48 ]);
49 ]);
49
50
50− const { bind: keyBind } = useKeyfileGenerator();
51+ const { bind: keyBind, code } = useKeyfileGenerator();
51
52
52 return (
53 return (
53 <>
54 <>
@@ -80,6 +81,7 @@ export default function UrbitOSHome({ manualNetworkSeed }) {
80 />
81 />
81 </>
82 </>
82 )}
83 )}
84+ <AccessCode code={code} />
83 <Grid.Divider />
85 <Grid.Divider />
84 <Grid.Item full as={ForwardButton} onClick={goNetworkingKeys}>
86 <Grid.Item full as={ForwardButton} onClick={goNetworkingKeys}>
85 {networkKeysAction} Networking Keys
87 {networkKeysAction} Networking Keys