on 729283f help sign in
bridge/src/views/Points.js
219 lines 6.4 kB history raw
1import React from 'react';
2import { Just, Nothing } from 'folktale/maybe';
3import { Grid, H5, H1, HelpText, LinkButton, Flex } from 'indigo-react';
5import { useHistory } from 'store/history';
6import { useWallet } from 'store/wallet';
7import { usePointCache } from 'store/pointCache';
8import { usePointCursor } from 'store/pointCursor';
10import * as need from 'lib/need';
11import { ROUTE_NAMES } from 'lib/routeNames';
12import { isZeroAddress, abbreviateAddress } from 'lib/wallet';
13import useIsEclipticOwner from 'lib/useIsEclipticOwner';
14import { useSyncKnownPoints } from 'lib/useSyncPoints';
16import View from 'components/View';
17import FooterButton from 'components/FooterButton';
18import Blinky from 'components/Blinky';
19import Passport from 'components/Passport';
20import useRejectedIncomingPointTransfers from 'lib/useRejectedIncomingPointTransfers';
22const getFromMaybe = (obj, key, defaultValue) =>
23 obj.matchWith({
24 Nothing: () => defaultValue,
25 Just: p =>
26 p.value.matchWith({
27 Ok: r => r.value[key],
28 Error: e => defaultValue,
29 }),
30 });
32const hasTransferProxy = (details, point) =>
33 !isZeroAddress(details.transferProxy);
35const PointList = function({ points, className, actions, ...rest }) {
36 const { setPointCursor } = usePointCursor();
37 const history = useHistory();
39 return (
40 <Grid gap={3} className={className}>
41 {points.map((point, i) => (
42 <Grid.Item half={(i % 2) + 1} key={point}>
43 <Flex col>
44 <Passport.Mini
45 point={point}
46 className="clickable"
47 onClick={() => {
48 setPointCursor(Just(point));
49 history.push(history.names.POINT);
50 }}
51 {...rest}
52 />
53 {actions && (
54 <Flex.Item className="mt2">{actions(point, i)}</Flex.Item>
55 )}
56 </Flex>
57 </Grid.Item>
58 ))}
59 </Grid>
60 );
61};
63function ActionButtons({ actions = [] }) {
64 return (
65 <Flex row>
66 {actions.map(action => (
67 <Flex.Item
68 key={action.text}
69 as={LinkButton}
70 className="mr3"
71 onClick={action.onClick}>
72 {action.text}
73 </Flex.Item>
74 ))}
75 </Flex>
76 );
79export default function Points() {
80 const { wallet } = useWallet();
81 const history = useHistory();
82 const { setPointCursor } = usePointCursor();
83 const { controlledPoints, getDetails } = usePointCache();
84 const isEclipticOwner = useIsEclipticOwner();
85 const [
86 rejectedPoints,
87 addRejectedPoint,
88 ] = useRejectedIncomingPointTransfers();
90 const address = need.addressFromWallet(wallet);
92 const loading = Nothing.hasInstance(controlledPoints);
94 const ownedPoints = getFromMaybe(controlledPoints, 'ownedPoints', []);
95 const incomingPoints = getFromMaybe(
96 controlledPoints,
97 'incomingPoints',
98 []
99 ).filter(point => !rejectedPoints.includes(point));
100 const managingPoints = getFromMaybe(controlledPoints, 'managingPoints', []);
101 const votingPoints = getFromMaybe(controlledPoints, 'votingPoints', []);
102 const spawningPoints = getFromMaybe(controlledPoints, 'spawningPoints', []);
103 const outgoingPoints = ownedPoints.filter(point =>
104 getDetails(point).matchWith({
105 Nothing: () => false,
106 Just: p => hasTransferProxy(p.value),
107 })
108 );
110 const multipassPoints = [
111 ...ownedPoints,
112 ...managingPoints,
113 ...votingPoints,
114 ...spawningPoints,
115 ];
117 // sync display details for known points
118 useSyncKnownPoints([
119 ...ownedPoints,
120 ...incomingPoints,
121 ...managingPoints,
122 ...votingPoints,
123 ...spawningPoints,
124 ]);
126 return (
127 <View>
128 <Grid className="mt6">
129 <Grid.Item full as={H1} className="f6 mono gray4 mb4">
130 {abbreviateAddress(address)}
131 </Grid.Item>
133 {loading && (
134 <Grid.Item full as={HelpText} className="mt8 t-center">
135 <Blinky /> Loading...
136 </Grid.Item>
137 )}
139 {incomingPoints.length > 0 && (
140 <Grid.Item full as={Grid} gap={1} className="mb6">
141 <Grid.Item full as={H5}>
142 Incoming Transfers
143 </Grid.Item>
144 <Grid.Item
145 full
146 as={PointList}
147 points={incomingPoints}
148 actions={(point, i) => (
149 <ActionButtons
150 actions={[
151 {
152 text: 'Accept',
153 onClick: () => {
154 setPointCursor(Just(point));
155 history.push(history.names.ACCEPT_TRANSFER);
156 },
157 },
158 {
159 text: 'Reject',
160 onClick: () => {
161 addRejectedPoint(point);
162 },
163 },
164 ]}
165 />
166 )}
167 inverted
168 />
169 </Grid.Item>
170 )}
172 {outgoingPoints.length > 0 && (
173 <Grid.Item full as={Grid} gap={1} className="mb6">
174 <Grid.Item full as={H5}>
175 Outgoing Transfers
176 </Grid.Item>
177 <Grid.Item
178 full
179 as={PointList}
180 points={outgoingPoints}
181 actions={(point, i) => (
182 <ActionButtons
183 actions={[
184 {
185 text: 'Cancel',
186 onClick: () => {
187 setPointCursor(Just(point));
188 // TODO: deep linking to fix this duplicate route
189 history.push(history.names.CANCEL_TRANSFER);
190 },
191 },
192 ]}
193 />
194 )}
195 inverted
196 />
197 </Grid.Item>
198 )}
200 {multipassPoints.length > 0 && (
201 <Grid.Item full as={Grid} gap={1}>
202 <Grid.Item full as={H5}>
203 Multipasses
204 </Grid.Item>
205 <Grid.Item full as={PointList} points={multipassPoints} />
206 </Grid.Item>
207 )}
209 {isEclipticOwner && (
210 <FooterButton
211 detail="You have the authority to create a new Galaxy."
212 onClick={() => history.push(ROUTE_NAMES.CREATE_GALAXY)}>
213 Create a galaxy
214 </FooterButton>
215 )}
216 </Grid>
217 </View>
218 );