1import React from 'react';
2import { Just, Nothing } from 'folktale/maybe';
3import ob from 'urbit-ob';
5import 'style/anim.css';
7import * as need from 'lib/need';
8import { chunkStr, Matrix, walk, rand } from 'lib/card';
9import usePermissionsForPoint from 'lib/usePermissionsForPoint';
10import { useSyncOwnedPoints } from 'lib/useSyncPoints';
12import { useWallet } from 'store/wallet';
14import Sigil from './Sigil';
15import { sigil, reactRenderer } from 'urbit-sigil-js';
17function makeSigil(size, patp, colors) {
22 renderer: reactRenderer,
28 if (patp.length === 14) {
36 if (patp.length === 7) {
46 if (patp.length === 4) {
56const buildKeyType = permissions => {
57 if (permissions.isOwner) {
59 } else if (permissions.isManagementProxy) {
61 } else if (permissions.isSpawnProxy) {
63 } else if (permissions.isVotingProxy) {
65 } else if (permissions.isTransferProxy) {
70const symbols = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13];
73 * Address is Maybe<string>
74 * point is Maybe<string>
75 * animationMode is 'slide' | 'step' | 'none'
82 animationMode = 'none',
85 const [cols, rows, tile] = [35, 12, 12];
87 const loading = Nothing.hasInstance(address) || Nothing.hasInstance(point);
88 const defaultMatrix = () => {
89 return Matrix.new(rows, cols);
92 const patp = ob.patp(point.value);
94 const makeMatrix = addr => {
96 const onlyTheNumberPart = addr.substring(2);
97 // make bigNum from hex
98 const int = new BN(onlyTheNumberPart, 16);
99 // make a bigger number
100 const big = int.pow(new BN(10));
101 // parse that to a string and pad
102 const b10 = big.toString(10).padStart(32, '0');
103 // split the big number into parts
104 const chunkSize = Math.ceil(b10.length / 8);
105 const chunks = chunkStr(b10, chunkSize).map(c => new BN(c));
106 // generate an empty matrix
107 const startMatrix = Matrix.new(rows, cols);
108 // do a few random walks starting at diff coordinates
109 const [, matrix] = chunks.reduce((acc, chunk) => {
110 return walk(chunk, acc[1]);
111 // start with the 'random' points (not actually random, they are deterministic)
112 }, rand(big, startMatrix));
117 const matrix = address.matchWith({
118 Just: ({ value }) => makeMatrix(value),
119 Nothing: defaultMatrix,
122 const bgColor = inverted ? 'white' : 'black';
124 const fgColor = inverted ? 'black' : 'white';
130 backgroundColor: bgColor,
131 border: inverted ? '2px solid #E6E6E6' : '2px solid black',
132 borderRadius: '20px',
133 marginBottom: '16px',
134 width: `${16 + 16 + cols * tile}px`,
135 minWidth: `${16 + 16 + cols * tile}px`,
137 flexDirection: 'column',
149 alignItems: 'center',
151 {Just.hasInstance(point) && makeSigil(64, patp, [bgColor, fgColor])}
161 fontFamily: 'Source Code Pro',
163 {Just.hasInstance(point) && patp}
172 fontFamily: 'Source Code Pro',
185 flexDirection: 'column',
188 filter: inverted ? 'invert(1)' : '',
190 {matrix.map((row, _row) => {
193 key={`card:row:${_row}`}
194 style={{ display: 'flex', justifyContent: 'space-between' }}>
195 {row.map((v, _col) => {
200 value={typeof symbols[v] === 'undefined' ? 13 : v}
202 spriteSheetHeight={12}
203 spriteSheetWidth={168}
206 animationMode={animationMode}
218const Cell = props => {
221 key={`card:cell:${props.row}:${props.col}:${props.value}`}
225 : props.animationMode === 'none'
227 : `${props.animationMode}-h-${props.value}`
230 backgroundImage: `url(/spritesheet_a.png)`,
232 props.animationMode === 'none'
233 ? `-${props.spriteSheetHeight * props.value}px 0px`
235 backgroundSize: `${props.spriteSheetWidth}px ${props.spriteSheetHeight}px`,
236 width: `${props.spriteSheetHeight}px`,
237 maxWidth: `${props.spriteSheetHeight}px`,
238 height: `${props.spriteSheetHeight}px`,
239 maxHeight: `${props.spriteSheetHeight}px`,
240 animationDelay: `${props.value * 50}ms`,
250function MiniPassport({ point, inverted, ...rest }) {
251 useSyncOwnedPoints([point]);
252 const { wallet } = useWallet();
253 const address = need.addressFromWallet(wallet);
255 const patp = ob.patp(point);
256 const permissions = usePermissionsForPoint(address, point);
257 const keyType = buildKeyType(permissions);
262 backgroundColor: inverted ? 'white' : 'black',
263 border: inverted ? '2px solid #E6E6E6' : '2px solid black',
264 borderRadius: '20px',
265 marginBottom: '16px',
266 maxWidth: `${230}px`,
268 flexDirection: 'column',
281 alignItems: 'center',
286 inverted ? ['white', 'black'] : ['black', 'white']
292 flexDirection: 'column',
293 justifyContent: 'space-between',
298 color: inverted ? 'black' : 'white',
300 fontFamily: 'Source Code Pro',
309 color: inverted ? 'black' : 'white',
311 fontFamily: 'Source Code Pro',
325Passport.Mini = MiniPassport;
327export default Passport;
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list