All files / app/hooks use-transaction-list.ts

0% Statements 0/45
0% Branches 0/4
0% Functions 0/12
0% Lines 0/34

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62                                                                                                                           
import { useMempool } from '@hooks/use-mempool';
import { MempoolTransaction } from '@stacks/stacks-blockchain-api-types';
import { RootState } from '@store/index';
import { selectPendingTransactions } from '@store/pending-transaction';
import { selectTransactionList } from '@store/transaction';
import { increment, decrement } from '@utils/mutate-numbers';
import * as R from 'ramda';
import { useCallback, useMemo, useRef } from 'react';
import { useHotkeys } from 'react-hotkeys-hook';
import { useSelector } from 'react-redux';
 
export function useTransactionList() {
  const { txs, pendingTxs } = useSelector((state: RootState) => ({
    txs: selectTransactionList(state),
    pendingTxs: selectPendingTransactions(state),
  }));
 
  const { mempoolTxs } = useMempool();
  const txIdEquals = useMemo(() => R.eqBy<MempoolTransaction>(tx => tx.tx_id), []);
 
  const dedupedPendingTxs = useMemo(() => {
    return R.uniqWith(txIdEquals, [...pendingTxs, ...mempoolTxs]).filter(
      mempoolTx => !txs.map(({ tx }) => tx.tx_id).includes(mempoolTx.tx_id)
    );
  }, [txIdEquals, pendingTxs, mempoolTxs, txs]);
 
  const focusedTxIdRef = useRef<string | null>(null);
  const txDomNodeRefMap = useRef<Record<string, HTMLButtonElement>>({});
 
  const focusTxDomNode = useCallback(
    (shift: (i: number) => number) => {
      const allTxs = [...dedupedPendingTxs, ...txs.map(({ tx }) => tx)];
      Iif (allTxs.length === 0) return;
      Iif (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];
      Iif (!nextTx) return;
      const domNode = txDomNodeRefMap.current[nextTx.tx_id];
      Iif (!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,
  };
}