From 0a103fe3d6cbf110ae927b4bd8cff78ff70451fc Mon Sep 17 00:00:00 2001 From: kyranjamie Date: Tue, 23 Feb 2021 12:56:09 +0100 Subject: [PATCH] chore: keyboard shortcuts broken --- app/hooks/use-transaction-list.ts | 63 +++++++++++++++++ app/pages/home/home.tsx | 110 ++++++++---------------------- package.json | 7 +- 3 files changed, 98 insertions(+), 82 deletions(-) create mode 100644 app/hooks/use-transaction-list.ts diff --git a/app/hooks/use-transaction-list.ts b/app/hooks/use-transaction-list.ts new file mode 100644 index 000000000..0d4c5f91f --- /dev/null +++ b/app/hooks/use-transaction-list.ts @@ -0,0 +1,63 @@ +import { useCallback, useMemo, useRef } from 'react'; +import { useHotkeys } from 'react-hotkeys-hook'; +import * as R from 'ramda'; +import { MempoolTransaction } from '@blockstack/stacks-blockchain-api-types'; +import { useSelector } from 'react-redux'; +import { RootState } from '@store/index'; +import { selectTransactionList } from '@store/transaction'; +import { selectPendingTransactions } from '@store/pending-transaction'; +import { useMempool } from '@hooks/use-mempool'; +import { increment, decrement } from '@utils/mutate-numbers'; + +export function useTransactionList() { + const { txs, pendingTxs } = useSelector((state: RootState) => ({ + txs: selectTransactionList(state), + pendingTxs: selectPendingTransactions(state), + })); + + const focusedTxIdRef = useRef(null); + const txDomNodeRefMap = useRef>({}); + + const { mempoolTxs } = useMempool(); + const txIdEquals = useMemo(() => R.eqBy(tx => tx.tx_id), []); + + const dedupedPendingTxs = useMemo( + () => + R.uniqWith(txIdEquals, [...pendingTxs, ...mempoolTxs]).filter( + mempoolTx => !txs.map(tx => tx.tx_id).includes(mempoolTx.tx_id) + ), + [txIdEquals, pendingTxs, mempoolTxs, txs] + ); + + const focusTxDomNode = useCallback( + (shift: (i: number) => number) => { + const allTxs = [...dedupedPendingTxs, ...txs]; + if (allTxs.length === 0) return; + if (focusedTxIdRef.current === null) { + const txId = allTxs[0].tx_id; + focusedTxIdRef.current = txId; + txDomNodeRefMap.current[txId].focus(); + return; + } + const nextIndex = shift(allTxs.findIndex(tx => tx.tx_id === focusedTxIdRef.current)); + const nextTx = allTxs[nextIndex]; + if (!nextTx) return; + const domNode = txDomNodeRefMap.current[nextTx.tx_id]; + if (!domNode) return; + domNode.focus(); + }, + [dedupedPendingTxs, txs] + ); + + useHotkeys('j', () => focusTxDomNode(increment), [txs, pendingTxs]); + useHotkeys('k', () => focusTxDomNode(decrement), [txs, pendingTxs]); + + return { + txs, + pendingTxs: dedupedPendingTxs, + txCount: txs.length + dedupedPendingTxs.length, + focusTxDomNode, + focusedTxIdRef, + txDomNodeRefMap, + }; +} diff --git a/app/pages/home/home.tsx b/app/pages/home/home.tsx index a227733ba..43b0be932 100644 --- a/app/pages/home/home.tsx +++ b/app/pages/home/home.tsx @@ -1,21 +1,16 @@ -import React, { FC, useRef, useCallback } from 'react'; +import React, { FC } from 'react'; import { useSelector, useDispatch } from 'react-redux'; import { Spinner } from '@blockstack/ui'; -import { useHotkeys } from 'react-hotkeys-hook'; import { Api } from '@api/api'; -import { increment, decrement } from '@utils/mutate-numbers'; -import { RootState } from '@store/index'; import { openTxInExplorer } from '@utils/external-links'; + +import { RootState } from '@store/index'; import { selectAddress } from '@store/keys'; import { selectActiveNodeApi } from '@store/stacks-node'; import { selectAddressBalance, selectAvailableBalance } from '@store/address'; -import { - selectTransactionList, - selectTransactionsLoading, - selectTransactionListFetchError, -} from '@store/transaction'; -import { selectPendingTransactions } from '@store/pending-transaction'; +import { selectRevokeDelegationModalOpen } from '@store/home/home.reducer'; +import { selectTransactionsLoading, selectTransactionListFetchError } from '@store/transaction'; import { selectLoadingStacking, selectNextCycleInfo, selectStackerInfo } from '@store/stacking'; import { homeActions, @@ -24,28 +19,28 @@ import { selectHomeCardState, HomeCardState, } from '@store/home'; -import { - TransactionList, - StackingPromoCard, - StackingRewardCard, - TransactionListItem, - BalanceCard, -} from '@components/home'; + import { TransactionModal } from '@modals/transaction/transaction-modal'; import { ReceiveStxModal } from '@modals/receive-stx/receive-stx-modal'; +import { RevokeDelegationModal } from '@modals/revoke-delegation/revoke-delegation-modal'; + +import { useDelegationStatus } from '@hooks/use-delegation-status'; +import { useTransactionList } from '@hooks/use-transaction-list'; import { StackingCard } from '@components/home/stacking-card'; import { StackingLoading } from '@components/home/stacking-loading'; import { StackingBeginsSoonCard } from '@components/home/stacking-begins-soon-card'; import { StackingError } from '@components/home/stacking-error-card'; - -import { HomeLayout } from './home-layout'; import { TransactionListItemMempool } from '@components/home/transaction-list/transaction-list-item-mempool'; -import { useMempool } from '@hooks/use-mempool'; import { DelegationCard } from '@components/home/delegation-card'; -import { useDelegationStatus } from '@hooks/use-delegation-status'; -import { RevokeDelegationModal } from '@modals/revoke-delegation/revoke-delegation-modal'; -import { selectRevokeDelegationModalOpen } from '../../store/home/home.reducer'; +import { + TransactionList, + StackingPromoCard, + StackingRewardCard, + TransactionListItem, + BalanceCard, +} from '@components/home'; +import { HomeLayout } from './home-layout'; export const Home: FC = () => { const dispatch = useDispatch(); @@ -56,8 +51,6 @@ export const Home: FC = () => { address, balance, spendableBalance, - txs, - pendingTxs, loadingTxs, txModalOpen, txListFetchError, @@ -68,9 +61,7 @@ export const Home: FC = () => { stackingCardState, } = useSelector((state: RootState) => ({ address: selectAddress(state), - txs: selectTransactionList(state), spendableBalance: selectAvailableBalance(state), - pendingTxs: selectPendingTransactions(state), balance: selectAddressBalance(state), txModalOpen: selectTxModalOpen(state), revokeDelegationModalOpen: selectRevokeDelegationModalOpen(state), @@ -84,38 +75,10 @@ export const Home: FC = () => { stackingCardState: selectHomeCardState(state), })); - const { mempoolTxs } = useMempool(); - - const focusedTxIdRef = useRef(null); - const txDomNodeRefMap = useRef>({}); - - const focusTxDomNode = useCallback( - (shift: (i: number) => number) => { - const allTxs = [...mempoolTxs, ...pendingTxs, ...txs]; - if (allTxs.length === 0) return; - if (focusedTxIdRef.current === null) { - const txId = allTxs[0].tx_id; - focusedTxIdRef.current = txId; - txDomNodeRefMap.current[txId].focus(); - return; - } - const nextIndex = shift(allTxs.findIndex(tx => tx.tx_id === focusedTxIdRef.current)); - const nextTx = allTxs[nextIndex]; - if (!nextTx) return; - const domNode = txDomNodeRefMap.current[nextTx.tx_id]; - if (!domNode) return; - domNode.focus(); - }, - [txs, pendingTxs, mempoolTxs] - ); - - useHotkeys('j', () => focusTxDomNode(increment), [txs, pendingTxs, mempoolTxs]); - useHotkeys('k', () => focusTxDomNode(decrement), [txs, pendingTxs, mempoolTxs]); + const { txs, pendingTxs, txCount, focusedTxIdRef, txDomNodeRefMap } = useTransactionList(); if (!address) return ; - const txCount = txs.length + pendingTxs.length + mempoolTxs.length; - const transactionList = ( <> { node={activeNode} error={txListFetchError} > - {mempoolTxs - .filter(mempoolTx => !txs.map(tx => tx.tx_id).includes(mempoolTx.tx_id)) - .map(mempoolTx => ( - - ))} - {pendingTxs - .filter(pendingTx => !txs.map(tx => tx.tx_id).includes(pendingTx.tx_id)) - .filter(pendingTx => !mempoolTxs.map(tx => tx.tx_id).includes(pendingTx.tx_id)) - .map(pendingTx => ( - - ))} + {pendingTxs.map(pendingTxs => ( + + ))} {txs.map(tx => (