import { Checkbox, Col, Row, Button as IndigoButton, Text, Action, } from '@tlon/indigo-react'; import { Button } from 'indigo-react'; import Modal from './Modal'; import { useCallback, useEffect, useState } from 'react'; import { ReactComponent as InviteIcon } from 'assets/invite.svg'; import Point from 'lib/types/Point'; import useRoller from 'lib/useRoller'; import BodyPane from './Window/BodyPane'; import { InviteGeneratingStatus, useInvites, useInviteStore, } from 'views/Invite/useInvites'; import { usePointCache } from 'store/pointCache'; import { CreatingInvitesModal } from './CreatingInvitesModal'; import { useWallet } from 'store/wallet'; import { WALLET_TYPES } from 'lib/constants'; interface StarMap { [key: string]: { point: Point; children: Point[]; }; } interface InviteConverterProps { points: Point[]; } function selectText(selected: string[], children: Point[]) { if ( allChildrenSelected( selected, children.map(p => p.patp) ) ) { return 'Deselect All'; } return 'Select All'; } function allChildrenSelected(selected: string[], childrenPatps: string[]) { const filtered = childrenPatps.filter(p => selected.includes(p)); return filtered.length === childrenPatps.length; } export const InviteConverter = ({ points }: InviteConverterProps) => { const { syncControlledPoints }: any = usePointCache(); const { walletType }: any = useWallet(); const signatureFree = walletType === WALLET_TYPES.TICKET || walletType === WALLET_TYPES.SHARDS; const { api, getPendingTransactions, getAndUpdatePoint } = useRoller(); const { inviteJobs } = useInviteStore(); const { generateInviteCodes } = useInvites(); const [show, setShow] = useState(false); const [selected, setSelected] = useState([]); const [starMap, setStarMap] = useState({}); const [generatingStatus, setGeneratingStatus] = useState< InviteGeneratingStatus >('initial'); const [error, setError] = useState(''); const [created, setCreated] = useState(0); const [currentPoint, setCurrentPoint] = useState(); const currentJob = inviteJobs[currentPoint?.value || 0]; const signatureCount = selected.length * 3; useEffect(() => { if (!points) { return; } async function collect() { const pointMap: StarMap = {}; const stars = points.filter(point => point.isStar && point.isL2Spawn); for (const star of stars) { const spawns = await api.getSpawned(star.value); const filteredPoints = points.filter( p => spawns.includes(p.value) && p.isL2Spawn ); if (filteredPoints.length !== 0) { pointMap[star.patp] = { point: star, children: filteredPoints, }; } } setStarMap(pointMap); } collect(); }, [points]); const selectChildren = useCallback( (children: Point[]) => { setSelected(state => { const childrenPatps = children.map(p => p.patp); const withoutChildren = state.filter(p => !childrenPatps.includes(p)); if (allChildrenSelected(state, childrenPatps)) { return withoutChildren; } else { return withoutChildren.concat(childrenPatps); } }); }, [setSelected] ); const togglePoint = useCallback( (point: Point) => { setSelected(state => { if (state.includes(point.patp)) { return state.filter(p => p !== point.patp); } else { return state.concat([point.patp]); } }); }, [setSelected] ); const convert = useCallback(async () => { if (generatingStatus !== 'initial') { return; } setGeneratingStatus('generating'); try { for (const { point, children } of Object.values(starMap)) { const filtered = children .filter(p => selected.includes(p.patp)) .map(p => p.value); if (filtered.length <= 0) { continue; } setCurrentPoint(point); await generateInviteCodes(point, filtered, false); await getAndUpdatePoint(point.value); setCreated(children.length); } setGeneratingStatus('finished'); } catch (error) { if (typeof error === 'object' && (error as Error)?.message) { setError((error as Error).message); } else if (typeof error === 'string') { setError(error); } else { setError('Creating invites failed'); } setGeneratingStatus('errored'); } }, [ generatingStatus, selected, starMap, generateInviteCodes, getAndUpdatePoint, ]); const hasPlanets = Object.entries(starMap).reduce((sum, [, star]) => { return (sum += star.children.length); }, 0) > 0; if (generatingStatus !== 'initial') { return ( { setGeneratingStatus('initial'); setSelected([]); setShow(false); setCreated(0); getPendingTransactions(); syncControlledPoints(); }} /> ); } return ( <> {/* @ts-ignore */} setShow(false)}> Updates invites for planets Select L2 planets you own to convert them back into invite links under each star.{' '} Note: this will re-ticket the planets and render their existing keys invalid. {!signatureFree && ( {signatureCount} manual signatures will be required. )} {Object.entries(starMap).map(([patp, { children }]) => ( Owned by {patp} selectChildren(children)}> {selectText(selected, children)} {children.map((point, index) => ( {point.patp} togglePoint(point)} /> ))} ))} {!hasPlanets && No planets to update} setShow(false)}> Close {/* @ts-ignore */} Convert Selected ); };