on 4c8c607 help sign in
270 lines 7.1 kB history raw
1import React, { useCallback, useState, useEffect, useMemo } from 'react';
2import cn from 'classnames';
3import { Grid, Button, SelectInput, Flex } from 'indigo-react';
4import * as ob from 'urbit-ob';
5import { azimuth } from 'azimuth-js';
7import { usePointCursor } from 'store/pointCursor';
8import { usePointCache } from 'store/pointCache';
10import useCurrentPointName from 'lib/useCurrentPointName';
11import useKeyfileGenerator from 'lib/useKeyfileGenerator';
12import * as need from 'lib/need';
14import { OutButton, ForwardButton } from 'components/Buttons';
15import { CopyButtonWide } from 'components/CopyButton';
16import NetworkingKeys from 'components/NetworkingKeys';
17import ProgressButton from 'components/ProgressButton';
18import LoginButton from 'components/LoginButton';
20import BridgeForm from 'form/BridgeForm';
21import { useLocalRouter } from 'lib/LocalRouter';
22import { useHosting } from 'store/hosting';
23import DownloadKeyfileButton from 'components/DownloadKeyfileButton';
24import useLifecycle from 'lib/useLifecycle';
25import useLocalHosting from 'lib/useLocalHosting';
27export default function UrbitOSHome({ manualNetworkSeed }) {
28 const { pointCursor } = usePointCursor();
29 const { getDetails } = usePointCache();
31 const { push, names } = useLocalRouter();
33 const point = need.point(pointCursor);
34 const details = need.details(getDetails(point));
36 const sponsor = ob.patp(details.sponsor);
38 const [showKeys, setShowKeys] = useState(false);
40 const showSponsor = azimuth.getPointSize(point) !== azimuth.PointSize.Galaxy;
41 const toggleShowKeys = useCallback(() => setShowKeys(s => !s), [setShowKeys]);
43 const goNetworkingKeys = useCallback(() => push(names.NETWORKING_KEYS), [
44 names,
45 push,
46 ]);
48 const goChangeSponsor = useCallback(() => push(names.CHANGE_SPONSOR), [
49 push,
50 names,
51 ]);
52 return (
53 <>
54 <Hosting manualNetworkSeed={manualNetworkSeed} />
56 <Grid>
57 <Grid.Item full className="mv7 f5">
58 Network
59 </Grid.Item>
60 {showSponsor && (
61 <>
62 <Grid.Divider />
63 <Grid.Item
64 full
65 as={ForwardButton}
66 detail="A sponsor finds new peers in your network"
67 accessory={<u>Change</u>}
68 onClick={goChangeSponsor}>
69 <span className="mono">{sponsor}</span>
70 <span className="f7 bg-black white p1 ml2 r4">SPONSOR</span>
71 </Grid.Item>
72 </>
73 )}
75 <Grid.Divider />
76 <Grid.Item full as={ForwardButton} onClick={goNetworkingKeys}>
77 Reset Networking Keys
78 </Grid.Item>
79 <Grid.Divider />
80 <Grid.Item
81 full
82 as={ForwardButton}
83 accessory={showKeys ? '▼' : '▲'}
84 onClick={toggleShowKeys}>
85 View Networking Keys
86 </Grid.Item>
87 {showKeys && <Grid.Item full as={NetworkingKeys} point={point} />}
88 </Grid>
89 </>
90 );
93// eslint-disable-next-line
94function Hosting({ manualNetworkSeed }) {
95 const bind = useKeyfileGenerator(manualNetworkSeed);
96 const { keyfile, code } = bind;
97 const ship = useHosting();
99 const {
100 syncStatus,
101 url,
102 unknown,
103 bootProgress,
104 bootMessage,
105 disabled,
106 } = ship;
108 const { running: localRunning, url: localUrl } = useLocalHosting();
110 let running = useMemo(() => localRunning || ship.running, [
111 ship,
112 localRunning,
113 ]);
115 useLifecycle(() => {
116 syncStatus();
117 });
119 const createShip = useCallback(() => ship.create(keyfile), [keyfile, ship]);
121 const name = useCurrentPointName();
122 const options = [{ text: 'Tlon', value: 'tlon' }];
124 const renderMain = useCallback(() => {
125 if (localRunning) {
126 return (
127 <Grid.Item
128 full
129 as={LoginButton}
130 solid
131 success
132 url={localUrl}
133 code={code}>
134 Open OS
135 </Grid.Item>
136 );
137 }
138 if (ship.running) {
139 return (
140 <>
141 <Grid.Item
142 cols={[1, 9]}
143 as={LoginButton}
144 solid
145 success
146 url={url}
147 code={code}>
148 Open OS
149 </Grid.Item>
150 {/* Unsupported for now */}
151 {/* <Grid.Item cols={[9, 13]} as={Button} className="b-black b1" center> */}
152 {/* Disconnect */}
153 {/* </Grid.Item> */}
154 </>
155 );
156 }
157 if (ship.missing) {
158 return (
159 <Grid.Item
160 full
161 as={ForwardButton}
162 solid
163 disabled={!keyfile}
164 onClick={createShip}>
165 Connect
166 </Grid.Item>
167 );
168 }
169 if (ship.pending) {
170 return (
171 <Grid.Item
172 full
173 as={ProgressButton}
174 success
175 disabled
176 progress={bootProgress}>
177 {bootMessage || 'Connecting'}
178 </Grid.Item>
179 );
180 }
181 }, [
182 localRunning,
183 ship.running,
184 ship.missing,
185 ship.pending,
186 localUrl,
187 code,
188 url,
189 keyfile,
190 createShip,
191 bootProgress,
192 bootMessage,
193 ]);
195 const renderDetails = useCallback(() => {
196 if (ship.running) {
197 return (
198 <>
199 <Grid.Item cols={[1, 9]} className="gray4">
200 <span className="mono">{name}</span> is connected to Tlon
201 </Grid.Item>
202 </>
203 );
204 }
205 if (!keyfile && ship.missing) {
206 return (
207 <Grid.Item full className="gray4">
208 Please reset your networking keys in order to use hosting
209 </Grid.Item>
210 );
211 }
212 }, [name, ship, keyfile]);
214 return (
215 <>
216 {disabled && (
217 <Grid gap={4}>
218 <Grid.Item full className="f5">
219 Urbit OS
220 </Grid.Item>
221 <Grid.Divider />
222 </Grid>
223 )}
224 {!disabled && (
225 <Grid gap={4}>
226 <Grid.Item full className="f5" as={Flex}>
227 <Flex.Item>Urbit OS </Flex.Item>
228 <Flex.Item
229 className={cn({ green3: running, gray4: !running }, 'ml3')}>
230 {running ? 'Connected' : 'Disconnected'}
231 </Flex.Item>
232 </Grid.Item>
233 <BridgeForm initialValues={{ provider: 'tlon' }}>
234 {() => (
235 <>
236 {renderDetails()}
237 {renderMain()}
238 {!localRunning && (
239 <Grid.Item
240 full
241 as={SelectInput}
242 name="provider"
243 label="Host Provider"
244 options={options}
245 disabled
246 />
247 )}
248 </>
249 )}
250 </BridgeForm>
251 </Grid>
252 )}
253 <Grid>
254 <Grid.Item
255 full
256 as={DownloadKeyfileButton}
257 {...bind}
258 className="mt2"
259 detail="A keyfile authenticates your Urbit ID to Urbit OS"
260 />
261 <Grid.Divider />
262 {code && (
263 <Grid.Item full className="mt2" as={CopyButtonWide} text={code}>
264 Login Code
265 </Grid.Item>
266 )}
267 </Grid>
268 </>
269 );