on 33c8b8d help sign in
bridge/src/views/Points.js
211 lines 6.2 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';
21const getFromMaybe = (obj, key, defaultValue) =>
22 obj.matchWith({
23 Nothing: () => defaultValue,
24 Just: p =>
25 p.value.matchWith({
26 Ok: r => r.value[key],
27 Error: e => defaultValue,
28 }),
29 });
31const hasTransferProxy = (details, point) =>
32 !isZeroAddress(details.transferProxy);
34const PointList = function({ points, className, actions, ...rest }) {
35 const { setPointCursor } = usePointCursor();
36 const history = useHistory();
38 return (
39 <Grid gap={3} className={className}>
40 {points.map((point, i) => (
41 <Grid.Item half={(i % 2) + 1} key={point}>
42 <Flex col>
43 <Passport.Mini
44 point={point}
45 className="clickable"
46 onClick={() => {
47 setPointCursor(Just(point));
48 history.push(history.names.POINT);
49 }}
50 {...rest}
51 />
52 {actions && (
53 <Flex.Item className="mt2">{actions(point, i)}</Flex.Item>
54 )}
55 </Flex>
56 </Grid.Item>
57 ))}
58 </Grid>
59 );
60};
62function ActionButtons({ actions = [] }) {
63 return (
64 <Flex row>
65 {actions.map(action => (
66 <Flex.Item
67 key={action.text}
68 as={LinkButton}
69 className="mr3"
70 onClick={action.onClick}>
71 {action.text}
72 </Flex.Item>
73 ))}
74 </Flex>
75 );
78export default function Points() {
79 const { wallet } = useWallet();
80 const history = useHistory();
81 const { setPointCursor } = usePointCursor();
82 const { controlledPoints, getDetails } = usePointCache();
83 const isEclipticOwner = useIsEclipticOwner();
85 const address = need.addressFromWallet(wallet);
87 const loading = Nothing.hasInstance(controlledPoints);
89 const ownedPoints = getFromMaybe(controlledPoints, 'ownedPoints', []);
90 const incomingPoints = getFromMaybe(controlledPoints, 'incomingPoints', []);
91 const managingPoints = getFromMaybe(controlledPoints, 'managingPoints', []);
92 const votingPoints = getFromMaybe(controlledPoints, 'votingPoints', []);
93 const spawningPoints = getFromMaybe(controlledPoints, 'spawningPoints', []);
94 const outgoingPoints = ownedPoints.filter(point =>
95 getDetails(point).matchWith({
96 Nothing: () => false,
97 Just: p => hasTransferProxy(p.value),
98 })
99 );
101 const multipassPoints = [
102 ...ownedPoints,
103 ...managingPoints,
104 ...votingPoints,
105 ...spawningPoints,
106 ];
108 // sync display details for known points
109 useSyncKnownPoints([
110 ...ownedPoints,
111 ...incomingPoints,
112 ...managingPoints,
113 ...votingPoints,
114 ...spawningPoints,
115 ]);
117 return (
118 <View>
119 <Grid className="mt6">
120 <Grid.Item full as={H1} className="f6 mono gray4 mb4">
121 {abbreviateAddress(address)}
122 </Grid.Item>
124 {loading && (
125 <Grid.Item full as={HelpText} className="mt8 t-center">
126 <Blinky /> Loading...
127 </Grid.Item>
128 )}
130 {incomingPoints.length > 0 && (
131 <Grid.Item full as={Grid} gap={1} className="mb6">
132 <Grid.Item full as={H5}>
133 Incoming Transfers
134 </Grid.Item>
135 <Grid.Item
136 full
137 as={PointList}
138 points={incomingPoints}
139 actions={(point, i) => (
140 <ActionButtons
141 actions={[
142 {
143 text: 'Accept',
144 onClick: () => {
145 setPointCursor(Just(point));
146 history.push(history.names.ACCEPT_TRANSFER);
147 },
148 },
149 {
150 text: 'Reject',
151 onClick: () => {
152 setPointCursor(Just(point));
153 history.push(history.names.REJECT_TRANSFER);
154 },
155 },
156 ]}
157 />
158 )}
159 inverted
160 />
161 </Grid.Item>
162 )}
164 {outgoingPoints.length > 0 && (
165 <Grid.Item full as={Grid} gap={1} className="mb6">
166 <Grid.Item full as={H5}>
167 Outgoing Transfers
168 </Grid.Item>
169 <Grid.Item
170 full
171 as={PointList}
172 points={outgoingPoints}
173 actions={(point, i) => (
174 <ActionButtons
175 actions={[
176 {
177 text: 'Cancel',
178 onClick: () => {
179 setPointCursor(Just(point));
180 // TODO: deep linking to fix this duplicate route
181 history.push(history.names.CANCEL_TRANSFER);
182 },
183 },
184 ]}
185 />
186 )}
187 inverted
188 />
189 </Grid.Item>
190 )}
192 {multipassPoints.length > 0 && (
193 <Grid.Item full as={Grid} gap={1}>
194 <Grid.Item full as={H5}>
195 Multipasses
196 </Grid.Item>
197 <Grid.Item full as={PointList} points={multipassPoints} />
198 </Grid.Item>
199 )}
201 {isEclipticOwner && (
202 <FooterButton
203 detail="You have the authority to create a new Galaxy."
204 onClick={() => history.push(ROUTE_NAMES.CREATE_GALAXY)}>
205 Create a galaxy
206 </FooterButton>
207 )}
208 </Grid>
209 </View>
210 );