on bd2bfea help sign in
bridge/src/views/Point.js
366 lines 10 kB history raw
1import React, { useCallback, useEffect, useState } from 'react';
2import cn from 'classnames';
3import { Just } from 'folktale/maybe';
4import { Grid, Flex, Button } from 'indigo-react';
5import { azimuth } from 'azimuth-js';
6import * as ob from 'urbit-ob';
8import { usePointCursor } from 'store/pointCursor';
9import { useWallet } from 'store/wallet';
11import View from 'components/View';
12import Greeting from 'components/Greeting';
13import Passport from 'components/Passport';
14import Blinky, { matchBlinky } from 'components/Blinky';
15import BarGraph from 'components/BarGraph';
16import Chip from 'components/Chip';
17import InviteSigilList from 'components/InviteSigilList';
18import { ForwardButton } from 'components/Buttons';
20import * as need from 'lib/need';
21import useInvites from 'lib/useInvites';
22import { useSyncExtras } from 'lib/useSyncPoints';
23import useCurrentPermissions from 'lib/useCurrentPermissions';
24import { useLocalRouter } from 'lib/LocalRouter';
26import Inviter from 'views/Invite/Inviter';
27import { usePointCache } from 'store/pointCache';
28import Card from 'components/L2/Card';
29import { Icon, Row } from '@tlon/indigo-react';
30import L2PointHeader from 'components/L2/Headers/L2PointHeader';
31import useRoller from 'lib/useRoller';
32import { useRollerStore } from 'store/roller';
33import LayerIndicator from 'components/L2/LayerIndicator';
34import { convertToInt } from 'lib/convertToInt';
36import './Point.scss';
38function InviteForm({
39 showInviteForm,
40 setShowInviteForm,
41 acceptedInvites,
42 acceptedPoints,
43 availableInvites,
44 goCohort,
45 pendingPoints,
46 sentInvites,
47 showInvites,
48}) {
49 const _totalInvites =
50 sentInvites.getOrElse(0) + availableInvites.getOrElse(0);
51 const _pendingInvites = pendingPoints.getOrElse([]).length;
53 return (
54 <>
55 <Grid.Item cols={[1, 11]}>
56 Invite Group
57 <br />
58 </Grid.Item>
60 <Grid.Item
61 className={cn('t-right underline pointer-hover', {
62 gray4: sentInvites.getOrElse(0) === 0,
63 })}
64 onClick={goCohort}
65 cols={[11, 13]}>
66 View
67 </Grid.Item>
68 <Grid.Item full>
69 <Flex align="center">
70 <Flex.Item>
71 {acceptedInvites.getOrElse(0)} / {_totalInvites}
72 </Flex.Item>
73 {_pendingInvites > 0 && (
74 <Flex.Item as={Chip} className="bg-yellow1 yellow4">
75 {_pendingInvites} pending
76 </Flex.Item>
77 )}
78 </Flex>
79 </Grid.Item>
81 {showInvites && (
82 <>
83 <Grid.Item
84 full
85 as={BarGraph}
86 available={availableInvites}
87 sent={sentInvites}
88 accepted={acceptedInvites}
89 />
90 <Grid.Item
91 full
92 as={InviteSigilList}
93 pendingPoints={pendingPoints}
94 acceptedPoints={acceptedPoints}
95 />
96 </>
97 )}
98 {!showInvites && (
99 <>
100 <Grid.Item full className="b-gray4 b-dotted b1 self-center">
101 <div className="p4 pv8 t-center gray4">
102 Start your invite group by adding members
103 </div>
104 </Grid.Item>
105 </>
106 )}
107 {!showInviteForm && availableInvites.getOrElse(0) > 0 && (
108 <Grid.Item
109 full
110 solid
111 as={Button}
112 center
113 onClick={() => setShowInviteForm(true)}>
114 Add Members
115 </Grid.Item>
116 )}
117 {showInviteForm && <Inviter />}
118 <Grid.Item full className="mb2" />
119 </>
120 );
123export default function Point() {
124 const { pop, push, names } = useLocalRouter();
125 const { pointCursor } = usePointCursor();
127 const { wallet, urbitWallet } = useWallet();
128 const point = need.point(pointCursor);
130 const { getResidents } = usePointCache();
131 const { api } = useRoller();
132 const {
133 pendingTransactions,
134 setPendingTransactions,
135 nextRoll,
136 setCurrentPoint,
137 } = useRollerStore();
139 useEffect(() => {
140 console.log('POINT', point);
141 const getTransactions = async () => {
142 const newPending = await api.getPendingByShip(Number(point));
143 console.log('PENDING', newPending);
144 setPendingTransactions(newPending);
146 // get list of spawned planets, and then determine if they have been claimed
147 const allSpawned = await api.getSpawned(Number(point));
148 console.log('SPAWNED', allSpawned.length, allSpawned);
150 const pointInfo = await api.getPoint(Number(point));
151 setCurrentPoint(pointInfo);
152 console.log('POINT', pointInfo);
154 const ownerAddress = pointInfo?.ownership?.owner?.address;
155 console.log('ADDRESS', ownerAddress);
156 if (ownerAddress) {
157 const transactionHistory = await api.getHistory(ownerAddress);
158 console.log('TRANSACTION HISTORY', transactionHistory);
159 }
160 };
162 getTransactions();
163 }, [api, point]); // eslint-disable-line
165 const { residentCount, requestCount } = getResidents(point);
167 const {
168 isParent,
169 isActiveOwner,
170 canManage,
171 canSpawn,
172 canVote,
173 } = useCurrentPermissions();
175 const canBitcoin = Just.hasInstance(urbitWallet);
177 // fetch the invites for the current cursor
178 const invites = useInvites(point);
179 const {
180 availableInvites,
181 sentInvites,
182 acceptedInvites,
183 pendingPoints,
184 acceptedPoints,
185 } = invites;
187 const showInvites = !(
188 acceptedInvites.getOrElse(0) === 0 && sentInvites.getOrElse(0) === 0
189 );
191 const hasInvites = showInvites || availableInvites.getOrElse(0) !== 0;
193 const loadedInvites = Just.hasInstance(availableInvites);
194 //
195 // availableInvites.getOrElse(0) === 0
197 const goSenate = useCallback(() => push(names.SENATE), [push, names]);
199 const goCohort = useCallback(() => push(names.INVITE_COHORT), [push, names]);
201 const goUrbitOS = useCallback(() => push(names.URBIT_OS), [push, names]);
203 const goBitcoin = useCallback(() => push(names.BITCOIN), [push, names]);
205 const goUrbitID = useCallback(() => push(names.URBIT_ID), [push, names]);
207 const goResidents = useCallback(() => push(names.RESIDENTS), [push, names]);
209 const goPartiesSetPoolSize = useCallback(
210 () => push(names.PARTY_SET_POOL_SIZE),
211 [push, names]
212 );
214 const goIssuePoint = useCallback(() => push(names.ISSUE_CHILD), [
215 names.ISSUE_CHILD,
216 push,
217 ]);
219 const isPlanet = azimuth.getPointSize(point) === azimuth.PointSize.Planet;
221 const [showInviteForm, setShowInviteForm] = useState(false);
223 const inviteButton = (() => {
224 if (azimuth.getPointSize(point) === azimuth.PointSize.Star) {
225 return (
226 <>
227 <Grid.Item
228 full
229 as={ForwardButton}
230 disabled={!isActiveOwner}
231 onClick={goPartiesSetPoolSize}>
232 Manage Invite Pools
233 </Grid.Item>
234 <Grid.Divider />
235 </>
236 );
237 }
239 return null;
240 })();
242 const senateButton = (() => {
243 if (azimuth.getPointSize(point) !== azimuth.PointSize.Galaxy) {
244 return null;
245 }
246 return (
247 <>
248 <Grid.Item
249 full
250 as={ForwardButton}
251 disabled={!canVote}
252 onClick={goSenate}>
253 Senate
254 </Grid.Item>
255 <Grid.Divider />
256 </>
257 );
258 })();
260 // sync the current cursor
261 useSyncExtras([point]);
263 const address = need.addressFromWallet(wallet);
265 const _requestCount = requestCount.getOrElse(0);
266 const numPending = pendingTransactions.length;
268 return (
269 <View
270 pop={pop}
271 inset
272 className="point"
273 header={<L2PointHeader hideTimer={!!numPending} />}>
274 <Greeting point={point} />
275 {!!numPending && (
276 <div className="transaction">
277 <Row className="title-row">
278 <div className="title">
279 {numPending} Planet{numPending > 1 ? 's' : ''} Spawned
280 </div>
281 <div className="rollup-timer">{nextRoll}</div>
282 </Row>
283 <Row className="info-row">
284 <LayerIndicator layer={2} size="sm" />
285 <div className="date"></div>
286 </Row>
287 </div>
288 )}
289 <Passport
290 point={Just(point)}
291 address={Just(address)}
292 animationMode={'slide'}
293 />
294 <Grid gap={4}>
295 {isParent && (
296 <Grid.Item full as={Flex} justify="between">
297 <Card
298 title="Residency"
299 subtitle="Manage peers that you service"
300 onClick={goResidents}
301 />
302 </Grid.Item>
303 )}
304 {isPlanet && hasInvites && (
305 <InviteForm
306 showInviteForm={showInviteForm}
307 setShowInviteForm={setShowInviteForm}
308 acceptedInvites={acceptedInvites}
309 acceptedPoints={acceptedPoints}
310 availableInvites={availableInvites}
311 goCohort={goCohort}
312 pendingPoints={pendingPoints}
313 sentInvites={sentInvites}
314 showInvites={showInvites}
315 />
316 )}
317 {!loadedInvites && isPlanet && (
318 <Grid.Item className="mv2" full>
319 Invite Group <Blinky />
320 </Grid.Item>
321 )}
322 {/* {inviteButton} */}
323 <Grid.Item full as={Flex} justify="between">
324 <Card
325 title="ID"
326 subtitle="Identity and security settings"
327 icon={<Icon icon="User" />}
328 onClick={goUrbitID}
329 disabled={!canManage}
330 />
331 </Grid.Item>
332 <Grid.Item full as={Flex} justify="between">
333 <Card
334 title="OS"
335 subtitle="Urbit OS Settings"
336 icon={<Icon icon="Server" />}
337 onClick={goUrbitOS}
338 disabled={!canManage}
339 />
340 </Grid.Item>
341 {/* <Grid.Item
342 full
343 as={ForwardButton}
344 disabled={!canBitcoin}
345 className="mt1"
346 detail="Bitcoin management"
347 onClick={goBitcoin}>
348 Bitcoin
349 </Grid.Item> */}
350 {/* {isParent && (
351 <>
352 <Grid.Item
353 full
354 as={ForwardButton}
355 disabled={!canSpawn}
356 onClick={goIssuePoint}>
357 Issue Point
358 </Grid.Item>
359 <Grid.Divider />
360 </>
361 )} */}
362 {senateButton}
363 </Grid>
364 </View>
365 );