on 4b0ca21 help sign in
bridge/src/views/Point.js
319 lines 8.4 kB history raw
1import React, { useCallback, useState } from 'react';
2import cn from 'classnames';
3import { Just } from 'folktale/maybe';
4import { Grid, Flex, Button } from 'indigo-react';
5import { azimuth } from 'azimuth-js';
7import { usePointCursor } from 'store/pointCursor';
8import { useWallet } from 'store/wallet';
10import View from 'components/View';
11import Greeting from 'components/Greeting';
12import Passport from 'components/Passport';
13import Blinky, { matchBlinky } from 'components/Blinky';
14import BarGraph from 'components/BarGraph';
15import Chip from 'components/Chip';
16import InviteSigilList from 'components/InviteSigilList';
17import { ForwardButton } from 'components/Buttons';
19import * as need from 'lib/need';
20import useInvites from 'lib/useInvites';
21import { useSyncExtras } from 'lib/useSyncPoints';
22import useCurrentPermissions from 'lib/useCurrentPermissions';
23import { useLocalRouter } from 'lib/LocalRouter';
25import Inviter from 'views/Invite/Inviter';
26import { usePointCache } from 'store/pointCache';
28function InviteForm({
29 showInviteForm,
30 setShowInviteForm,
31 acceptedInvites,
32 acceptedPoints,
33 availableInvites,
34 goCohort,
35 pendingPoints,
36 sentInvites,
37 showInvites,
38}) {
39 const _totalInvites =
40 sentInvites.getOrElse(0) + availableInvites.getOrElse(0);
41 const _pendingInvites = pendingPoints.getOrElse([]).length;
43 return (
44 <>
45 <Grid.Item cols={[1, 11]}>
46 Invite Group
47 <br />
48 </Grid.Item>
50 <Grid.Item
51 className={cn('t-right underline pointer-hover', {
52 gray4: sentInvites.getOrElse(0) === 0,
53 })}
54 onClick={goCohort}
55 cols={[11, 13]}>
56 View
57 </Grid.Item>
58 <Grid.Item full>
59 <Flex align="center">
60 <Flex.Item>
61 {acceptedInvites.getOrElse(0)} / {_totalInvites}
62 </Flex.Item>
63 {_pendingInvites > 0 && (
64 <Flex.Item as={Chip} className="bg-yellow1 yellow4">
65 {_pendingInvites} pending
66 </Flex.Item>
67 )}
68 </Flex>
69 </Grid.Item>
71 {showInvites && (
72 <>
73 <Grid.Item
74 full
75 as={BarGraph}
76 available={availableInvites}
77 sent={sentInvites}
78 accepted={acceptedInvites}
79 />
80 <Grid.Item
81 full
82 as={InviteSigilList}
83 pendingPoints={pendingPoints}
84 acceptedPoints={acceptedPoints}
85 />
86 </>
87 )}
88 {!showInvites && (
89 <>
90 <Grid.Item full className="b-gray4 b-dotted b1 self-center">
91 <div className="p4 pv8 t-center gray4">
92 Start your invite group by adding members
93 </div>
94 </Grid.Item>
95 </>
96 )}
97 {!showInviteForm && availableInvites.getOrElse(0) > 0 && (
98 <Grid.Item
99 full
100 solid
101 as={Button}
102 center
103 onClick={() => setShowInviteForm(true)}>
104 Add Members
105 </Grid.Item>
106 )}
107 {showInviteForm && <Inviter />}
108 <Grid.Item full className="mb2" />
109 </>
110 );
113export default function Point() {
114 const { pop, push, names } = useLocalRouter();
115 const { pointCursor } = usePointCursor();
117 const { wallet, urbitWallet } = useWallet();
118 const point = need.point(pointCursor);
120 const { getResidents } = usePointCache();
122 const { residentCount, requestCount } = getResidents(point);
124 const {
125 isParent,
126 isActiveOwner,
127 canManage,
128 canSpawn,
129 canVote,
130 } = useCurrentPermissions();
132 const canBitcoin = Just.hasInstance(urbitWallet);
134 // fetch the invites for the current cursor
135 const invites = useInvites(point);
136 const {
137 availableInvites,
138 sentInvites,
139 acceptedInvites,
140 pendingPoints,
141 acceptedPoints,
142 } = invites;
144 const showInvites = !(
145 acceptedInvites.getOrElse(0) === 0 && sentInvites.getOrElse(0) === 0
146 );
148 const hasInvites = showInvites || availableInvites.getOrElse(0) !== 0;
150 const loadedInvites = Just.hasInstance(availableInvites);
151 //
152 // availableInvites.getOrElse(0) === 0
154 const goSenate = useCallback(() => push(names.SENATE), [push, names]);
156 const goCohort = useCallback(() => push(names.INVITE_COHORT), [push, names]);
158 const goUrbitOS = useCallback(() => push(names.URBIT_OS), [push, names]);
160 const goBitcoin = useCallback(() => push(names.BITCOIN), [push, names]);
162 const goUrbitID = useCallback(() => push(names.URBIT_ID), [push, names]);
164 const goResidents = useCallback(() => push(names.RESIDENTS), [push, names]);
166 const goPartiesSetPoolSize = useCallback(
167 () => push(names.PARTY_SET_POOL_SIZE),
168 [push, names]
169 );
171 const goIssuePoint = useCallback(() => push(names.ISSUE_CHILD), [
172 names.ISSUE_CHILD,
173 push,
174 ]);
176 const isPlanet = azimuth.getPointSize(point) === azimuth.PointSize.Planet;
178 const [showInviteForm, setShowInviteForm] = useState(false);
180 const inviteButton = (() => {
181 if (azimuth.getPointSize(point) === azimuth.PointSize.Star) {
182 return (
183 <>
184 <Grid.Item
185 full
186 as={ForwardButton}
187 disabled={!isActiveOwner}
188 onClick={goPartiesSetPoolSize}>
189 Manage Invite Pools
190 </Grid.Item>
191 <Grid.Divider />
192 </>
193 );
194 }
196 return null;
197 })();
199 const senateButton = (() => {
200 if (azimuth.getPointSize(point) !== azimuth.PointSize.Galaxy) {
201 return null;
202 }
203 return (
204 <>
205 <Grid.Item
206 full
207 as={ForwardButton}
208 disabled={!canVote}
209 onClick={goSenate}>
210 Senate
211 </Grid.Item>
212 <Grid.Divider />
213 </>
214 );
215 })();
217 // sync the current cursor
218 useSyncExtras([point]);
220 const address = need.addressFromWallet(wallet);
222 const _requestCount = requestCount.getOrElse(0);
224 return (
225 <View pop={pop} inset>
226 <Greeting point={point} />
227 <Passport
228 point={Just(point)}
229 address={Just(address)}
230 animationMode={'slide'}
231 />
232 <Grid gap={3}>
233 {isParent && (
234 <Grid.Item
235 full
236 as={Flex}
237 justify="between"
238 onClick={goResidents}
239 className="mv1 pointer">
240 <Flex.Item>
241 Residents{' '}
242 <span className="gray3">{matchBlinky(residentCount)}</span>
243 </Flex.Item>
244 {_requestCount !== 0 && (
245 <Flex.Item className="f7 bg-gray2 h3 pv1 ph2 br-full r-full text-center">
246 {_requestCount} PENDING
247 </Flex.Item>
248 )}
249 </Grid.Item>
250 )}
251 {isPlanet && hasInvites && (
252 <InviteForm
253 showInviteForm={showInviteForm}
254 setShowInviteForm={setShowInviteForm}
255 acceptedInvites={acceptedInvites}
256 acceptedPoints={acceptedPoints}
257 availableInvites={availableInvites}
258 goCohort={goCohort}
259 pendingPoints={pendingPoints}
260 sentInvites={sentInvites}
261 showInvites={showInvites}
262 />
263 )}
264 {!loadedInvites && isPlanet && (
265 <Grid.Item className="mv2" full>
266 Invite Group <Blinky />
267 </Grid.Item>
268 )}
269 </Grid>
270 <Grid className="pt2">
271 <Grid.Divider />
272 {inviteButton}
273 <Grid.Item
274 full
275 as={ForwardButton}
276 disabled={!canManage}
277 onClick={goUrbitID}
278 className="mt1"
279 detail="Identity and security settings">
280 ID
281 </Grid.Item>
282 <Grid.Divider />
283 <Grid.Item
284 full
285 as={ForwardButton}
286 disabled={!canManage}
287 className="mt1"
288 detail="Urbit OS Settings"
289 onClick={goUrbitOS}>
290 OS
291 </Grid.Item>
292 <Grid.Divider />
293 <Grid.Item
294 full
295 as={ForwardButton}
296 disabled={!canBitcoin}
297 className="mt1"
298 detail="Bitcoin management"
299 onClick={goBitcoin}>
300 Bitcoin
301 </Grid.Item>
302 <Grid.Divider />
303 {isParent && (
304 <>
305 <Grid.Item
306 full
307 as={ForwardButton}
308 disabled={!canSpawn}
309 onClick={goIssuePoint}>
310 Issue Point
311 </Grid.Item>
312 <Grid.Divider />
313 </>
314 )}
315 {senateButton}
316 </Grid>
317 </View>
318 );