@@ -1,186 +1,207 @@
1import React from 'react';
1import React from 'react';
2import { Just, Nothing } from 'folktale/maybe';
2import { Just, Nothing } from 'folktale/maybe';
3−import { H1, H2, P, Grid } from 'indigo-react';
3+import { Grid, H5, H1, HelpText, LinkButton, Flex } from 'indigo-react';
5−import { ROUTE_NAMES } from 'lib/routeNames';
6−import { isZeroAddress } from 'lib/wallet';
7−import useIsEclipticOwner from 'lib/useIsEclipticOwner';
8−import { useSyncKnownPoints } from 'lib/useSyncPoints';
10import { useHistory } from 'store/history';
5import { useHistory } from 'store/history';
11import { useWallet } from 'store/wallet';
6import { useWallet } from 'store/wallet';
12import { usePointCache } from 'store/pointCache';
7import { usePointCache } from 'store/pointCache';
8+import { usePointCursor } from 'store/pointCursor';
10+import * as need from 'lib/need';
11+import { ROUTE_NAMES } from 'lib/routeNames';
12+import { isZeroAddress, abbreviateAddress } from 'lib/wallet';
13+import useIsEclipticOwner from 'lib/useIsEclipticOwner';
14+import { useSyncKnownPoints } from 'lib/useSyncPoints';
14import View from 'components/View';
16import View from 'components/View';
15−import { ForwardButton } from 'components/Buttons';
17+import FooterButton from 'components/FooterButton';
16−import useLifecycle from 'lib/useLifecycle';
18+import Blinky from 'components/Blinky';
19+import Passport from 'components/Passport';
21+const getFromMaybe = (obj, key, defaultValue) =>
23+ Nothing: () => defaultValue,
26+ Ok: r => r.value[key],
27+ Error: e => defaultValue,
18−//TODO new component
31+const hasTransferProxy = (details, point) =>
19−import { usePointCursor } from 'store/pointCursor';
32+ !isZeroAddress(details.transferProxy);
20−import * as ob from 'urbit-ob';
33+
21−const PointList = function(props) {
34+const PointList = function({ points, className, actions, ...rest }) {
22 const { setPointCursor } = usePointCursor();
35 const { setPointCursor } = usePointCursor();
23 const history = useHistory();
36 const history = useHistory();
24− const { points, loading } = props;
37+
26− return points.length === 0 ? (
38+ return (
27− <p>{loading ? 'Loading...' : 'No points to display'}</p>
39+ <Grid gap={3} className={className}>
30− {points.map(point => (
40+ {points.map((point, i) => (
32− key={point}
41+ <Grid.Item half={(i % 2) + 1} key={point}>
45+ className="clickable"
33− onClick={() => {
46+ onClick={() => {
34− setPointCursor(Just(point));
47+ setPointCursor(Just(point));
35− history.push(ROUTE_NAMES.POINT);
48+ history.push(history.names.POINT);
37− {ob.patp(point)}
50+ {...rest}
52+ <Flex.Item className="mt2">{actions}</Flex.Item>
44−const matchArray = obj =>
60+function ActionButtons({ actions = [] }) {
45− obj.matchWith({ Nothing: () => [], Just: p => p.value });
61+ return (
47−const hasTransferProxy = (details, point) =>
63+ {actions.map(action => (
48− !isZeroAddress(details.transferProxy);
64+ <Flex.Item
68+ onClick={action.onClick}>
50export default function Points() {
76export default function Points() {
51 const { wallet } = useWallet();
77 const { wallet } = useWallet();
52 const history = useHistory();
78 const history = useHistory();
55− syncControlledPoints,
57− } = usePointCache();
79+ const { controlledPoints, getDetails } = usePointCache();
64− } = getControlledPoints(wallet);
65 const isEclipticOwner = useIsEclipticOwner();
80 const isEclipticOwner = useIsEclipticOwner();
67− const owned = matchArray(ownedPoints);
82+ const address = need.addressFromWallet(wallet);
68− const incoming = matchArray(incomingPoints);
69− const managing = matchArray(managingPoints);
70− const voting = matchArray(votingPoints);
71− const spawning = matchArray(spawningPoints);
73− // sync controlled points on mount
84+ const loading = Nothing.hasInstance(controlledPoints);
75− syncControlledPoints();
78− // sync display details for known points
86+ const ownedPoints = getFromMaybe(controlledPoints, 'ownedPoints', []);
79− useSyncKnownPoints([
87+ const incomingPoints = getFromMaybe(controlledPoints, 'incomingPoints', []);
80− ...owned,
88+ const managingPoints = getFromMaybe(controlledPoints, 'managingPoints', []);
81− ...incoming,
89+ const votingPoints = getFromMaybe(controlledPoints, 'votingPoints', []);
82− ...managing,
90+ const spawningPoints = getFromMaybe(controlledPoints, 'spawningPoints', []);
87− const loading = Nothing.hasInstance(ownedPoints);
89− const outgoing = ownedPoints.filter(point =>
91+ const outgoingPoints = ownedPoints.filter(point =>
90 getDetails(point).matchWith({
92 getDetails(point).matchWith({
91 Nothing: () => false,
93 Nothing: () => false,
92 Just: p => hasTransferProxy(p.value),
94 Just: p => hasTransferProxy(p.value),
98+ const multipassPoints = [
105+ // sync display details for known points
106+ useSyncKnownPoints([
101− A point is an identity on the Ethereum blockchain. Points declare keys
102− for ships on the Arvo network.
105− <Grid>
116+ <Grid className="mt6">
107− <Grid.Item full>
117+ <Grid.Item full as={H1} className="f6 mono gray4 mb4">
108− <ForwardButton
118+ {abbreviateAddress(address)}
109− detail="View a point on Azimuth"
110− onClick={() => history.push(ROUTE_NAMES.VIEW_POINT)}>
113 </Grid.Item>
119 </Grid.Item>
114− <Grid.Divider />
120+
115− {isEclipticOwner && (
121+ {loading && (
116− <>
122+ <Grid.Item full as={HelpText} className="mt8 t-center">
117− <Grid.Item full>
123+ <Blinky /> Loading...
118− <ForwardButton
124+ </Grid.Item>
119− detail="You have the authority to create a new Galaxy."
125+ )}
120− onClick={() => history.push(ROUTE_NAMES.CREATE_GALAXY)}>
126+
121− Create a galaxy
127+ {incomingPoints.length > 0 && (
122− </ForwardButton>
128+ <Grid.Item full as={Grid} gap={1} className="mb6">
129+ <Grid.Item full as={H5}>
123 </Grid.Item>
131 </Grid.Item>
124− <Grid.Divider />
132+ <Grid.Item
135+ points={incomingPoints}
143+ console.log('accept');
150+ console.log('reject');
161+ {outgoingPoints.length > 0 && (
162+ <Grid.Item full as={Grid} gap={1} className="mb6">
163+ <Grid.Item full as={H5}>
169+ points={outgoingPoints}
177+ console.log('cancel');
129− {incoming.length > 0 && (
188+ {multipassPoints.length > 0 && (
130− <>
189+ <Grid.Item full as={Grid} gap={1}>
131− <H2>Incoming Transfers</H2>
190+ <Grid.Item full as={H5}>
133− You do not own these points until you accept the incoming transfer.
192+ </Grid.Item>
134− You may reject any incoming transfers.
193+ <Grid.Item full as={PointList} points={multipassPoints} />
135− </P>
194+ </Grid.Item>
136− <PointList routeHandler={history.push} points={incoming} />
140− {outgoing.length > 0 && (
142− <H2>Outgoing Transfers</H2>
144− You own these points until the recipient accepts the incoming
145− transfer. You may cancel the transfer until accepted.
147− <PointList routeHandler={history.push} points={outgoing} />
151− <H2>Your Points</H2>
153− <PointList routeHandler={history.push} points={owned} loading={loading} />
155− {managing.length > 0 && (
157− <H2>You Are a Management Proxy For</H2>
159− You can configure or set network keys and conduct sponsorship
160− related operations for these points.
162− <PointList routeHandler={history.push} points={managing} />
166− {voting.length > 0 && (
197+ {isEclipticOwner && (
167− <>
198+ <FooterButton
168− <H2>You Are a Voting Proxy For</H2>
199+ detail="You have the authority to create a new Galaxy."
169− <P>
200+ onClick={() => history.push(ROUTE_NAMES.CREATE_GALAXY)}>
170− Since you are part of the Galactic Senate, you can cast votes on new
201+ Create a galaxy
171− Azimuth proposals on behalf of these points.
202+ </FooterButton>
173− <PointList routeHandler={history.push} points={voting} />
204+ </Grid>
177− {spawning.length > 0 && (
179− <H2>You Are a Spawn Proxy For</H2>
180− <P>You can create new child points under these points.</P>
181− <PointList routeHandler={history.push} points={spawning} />