import { getGetServerSideProps } from '@/api/ssrApollo' import Layout from '@/components/layout' import styles from '@/styles/wallet.module.css' import Link from 'next/link' import { useWallets } from '@/wallets/index' import { useCallback, useState } from 'react' import { useIsClient } from '@/components/use-client' import WalletCard from '@/components/wallet-card' import { useToast } from '@/components/toast' import BootstrapForm from 'react-bootstrap/Form' import RecvIcon from '@/svgs/arrow-left-down-line.svg' import SendIcon from '@/svgs/arrow-right-up-line.svg' import { useRouter } from 'next/router' import { supportsReceive, supportsSend } from '@/wallets/common' export const getServerSideProps = getGetServerSideProps({ authRequired: true }) export default function Wallet ({ ssrData }) { const { wallets, setPriorities } = useWallets() const toast = useToast() const isClient = useIsClient() const [sourceIndex, setSourceIndex] = useState(null) const [targetIndex, setTargetIndex] = useState(null) const router = useRouter() const [filter, setFilter] = useState({ send: router.query.send === 'true', receive: router.query.receive === 'true' }) const reorder = useCallback(async (sourceIndex, targetIndex) => { const newOrder = [...wallets.filter(w => w.config?.enabled)] const [source] = newOrder.splice(sourceIndex, 1) const priorities = newOrder.slice(0, targetIndex) .concat(source) .concat(newOrder.slice(targetIndex)) .map((w, i) => ({ wallet: w, priority: i })) await setPriorities(priorities) }, [setPriorities, wallets]) const onDragStart = useCallback((i) => (e) => { // e.dataTransfer.dropEffect = 'move' // We can only use the DataTransfer API inside the drop event // see https://html.spec.whatwg.org/multipage/dnd.html#security-risks-in-the-drag-and-drop-model // e.dataTransfer.setData('text/plain', name) // That's why we use React state instead setSourceIndex(i) }, [setSourceIndex]) const onDragEnter = useCallback((i) => (e) => { setTargetIndex(i) }, [setTargetIndex]) const onReorderError = useCallback((err) => { console.error(err) toast.danger('failed to reorder wallets') }, [toast]) const onDragEnd = useCallback((e) => { setSourceIndex(null) setTargetIndex(null) if (sourceIndex === targetIndex) return reorder(sourceIndex, targetIndex).catch(onReorderError) }, [sourceIndex, targetIndex, reorder, onReorderError]) const onTouchStart = useCallback((i) => (e) => { if (sourceIndex !== null) { reorder(sourceIndex, i).catch(onReorderError) setSourceIndex(null) } else { setSourceIndex(i) } }, [sourceIndex, reorder, onReorderError]) const onFilterChange = useCallback((key) => { return e => { setFilter(old => ({ ...old, [key]: e.target.checked })) router.replace({ query: { ...router.query, [key]: e.target.checked } }, undefined, { shallow: true }) } }, [router]) return ( <Layout> <div className='py-5 w-100'> <h2 className='mb-2 text-center'>wallets</h2> <h6 className='text-muted text-center'>use real bitcoin</h6> <div className='text-center'> <Link href='/wallets/logs' className='text-muted fw-bold text-underline'> wallet logs </Link> </div> <div className={styles.walletGrid} onDragEnd={onDragEnd}> <div className={styles.walletFilters}> <BootstrapForm.Check inline label={<span><RecvIcon width={16} height={16} /> receive</span>} onChange={onFilterChange('receive')} checked={filter.receive} /> <BootstrapForm.Check inline label={<span><SendIcon width={16} height={16} /> send</span>} onChange={onFilterChange('send')} checked={filter.send} /> </div> {wallets .filter(w => { return (!filter.send || (filter.send && supportsSend(w))) && (!filter.receive || (filter.receive && supportsReceive(w))) }) .map((w, i) => { const draggable = isClient && w.config?.enabled return ( <div key={w.def.name} className={ !draggable ? '' : (`${sourceIndex === i ? styles.drag : ''} ${draggable && targetIndex === i ? styles.drop : ''}`) } suppressHydrationWarning > <WalletCard wallet={w} draggable={draggable} onDragStart={draggable ? onDragStart(i) : undefined} onTouchStart={draggable ? onTouchStart(i) : undefined} onDragEnter={draggable ? onDragEnter(i) : undefined} sourceIndex={sourceIndex} targetIndex={targetIndex} index={i} /> </div> ) } )} </div> </div> </Layout> ) }