Commit c4a1fd36 authored by tom goriunov's avatar tom goriunov Committed by GitHub

Merge pull request #367 from blockscout/gradual-increment

gradual increment for new tx notice
parents c7a3c3f9 33ac5b69
import _clamp from 'lodash/clamp';
import React from 'react';
const MAX_DELAY = 500;
const MIN_DELAY = 50;
export default function useGradualIncrement(initialValue: number): [number, (inc: number) => void] {
const [ num, setNum ] = React.useState(initialValue);
const queue = React.useRef<number>(0);
const timeoutId = React.useRef(0);
const incrementDelayed = React.useCallback(() => {
if (queue.current === 0) {
return;
}
queue.current--;
setNum(prev => prev + 1);
timeoutId.current = 0;
}, []);
const increment = React.useCallback((inc: number) => {
if (inc < 1) {
return;
}
queue.current += inc;
if (!timeoutId.current) {
timeoutId.current = window.setTimeout(incrementDelayed, 0);
}
}, [ incrementDelayed ]);
React.useEffect(() => {
if (queue.current > 0 && !timeoutId.current) {
const delay = _clamp(MAX_DELAY / queue.current * 1.5, MIN_DELAY, MAX_DELAY);
timeoutId.current = window.setTimeout(incrementDelayed, delay);
}
}, [ incrementDelayed, num ]);
React.useEffect(() => {
return () => {
window.clearTimeout(timeoutId.current);
};
}, []);
return [ num, increment ];
}
...@@ -2,6 +2,7 @@ import type { NextRouter } from 'next/router'; ...@@ -2,6 +2,7 @@ import type { NextRouter } from 'next/router';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import React from 'react'; import React from 'react';
import useGradualIncrement from 'lib/hooks/useGradualIncrement';
import { ROUTES } from 'lib/link/routes'; import { ROUTES } from 'lib/link/routes';
import useSocketChannel from 'lib/socket/useSocketChannel'; import useSocketChannel from 'lib/socket/useSocketChannel';
import useSocketMessage from 'lib/socket/useSocketMessage'; import useSocketMessage from 'lib/socket/useSocketMessage';
...@@ -36,19 +37,19 @@ function assertIsNewPendingTxResponse(response: unknown): response is { pending_ ...@@ -36,19 +37,19 @@ function assertIsNewPendingTxResponse(response: unknown): response is { pending_
export default function useNewTxsSocket() { export default function useNewTxsSocket() {
const router = useRouter(); const router = useRouter();
const [ num, setNum ] = React.useState(0); const [ num, setNum ] = useGradualIncrement(0);
const [ socketAlert, setSocketAlert ] = React.useState(''); const [ socketAlert, setSocketAlert ] = React.useState('');
const { topic, event } = getSocketParams(router); const { topic, event } = getSocketParams(router);
const handleNewTxMessage = React.useCallback((response: { transaction: number } | { pending_transaction: number } | unknown) => { const handleNewTxMessage = React.useCallback((response: { transaction: number } | { pending_transaction: number } | unknown) => {
if (assertIsNewTxResponse(response)) { if (assertIsNewTxResponse(response)) {
setNum((prev) => prev + response.transaction); setNum(response.transaction);
} }
if (assertIsNewPendingTxResponse(response)) { if (assertIsNewPendingTxResponse(response)) {
setNum((prev) => prev + response.pending_transaction); setNum(response.pending_transaction);
} }
}, []); }, [ setNum ]);
const handleSocketClose = React.useCallback(() => { const handleSocketClose = React.useCallback(() => {
setSocketAlert('Connection is lost. Please click here to load new transactions.'); setSocketAlert('Connection is lost. Please click here to load new transactions.');
......
import { Alert, Spinner, Text, Link, useColorModeValue, useTheme } from '@chakra-ui/react'; import { Alert, Text, Link, useColorModeValue, useTheme } from '@chakra-ui/react';
import { transparentize } from '@chakra-ui/theme-tools'; import { transparentize } from '@chakra-ui/theme-tools';
import React from 'react'; import React from 'react';
...@@ -18,18 +18,14 @@ const LatestTxsNotice = ({ className }: Props) => { ...@@ -18,18 +18,14 @@ const LatestTxsNotice = ({ className }: Props) => {
content = 'Connection is lost. Please reload page'; content = 'Connection is lost. Please reload page';
} else if (!num) { } else if (!num) {
content = ( content = (
<> <Text>scanning new transactions...</Text>
<Spinner size="sm" mr={ 3 }/>
<Text>scanning new transactions ...</Text>
</>
); );
} else { } else {
const txsUrl = link('txs'); const txsUrl = link('txs');
content = ( content = (
<> <>
<Spinner size="sm" mr={ 3 }/> <Link href={ txsUrl }>{ num } more transaction{ num > 1 ? 's' : '' }</Link>
<Text as="span" whiteSpace="pre">+ { num } new transaction{ num > 1 ? 's' : '' }. </Text> <Text whiteSpace="pre"> ha{ num > 1 ? 've' : 's' } come in</Text>
<Link href={ txsUrl }>View all</Link>
</> </>
); );
} }
......
import { Alert, Spinner, Text, Link, chakra } from '@chakra-ui/react'; import { Alert, Link, Text, chakra } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import useNewTxsSocket from 'lib/hooks/useNewTxsSocket'; import useNewTxsSocket from 'lib/hooks/useNewTxsSocket';
...@@ -36,14 +36,17 @@ const TxsNewItemNotice = ({ children, className }: Props) => { ...@@ -36,14 +36,17 @@ const TxsNewItemNotice = ({ children, className }: Props) => {
} }
if (!num) { if (!num) {
return null; return (
<Alert className={ className } status="warning" p={ 4 } fontWeight={ 400 }>
scanning new transactions...
</Alert>
);
} }
return ( return (
<Alert className={ className } status="warning" p={ 4 } fontWeight={ 400 }> <Alert className={ className } status="warning" p={ 4 } fontWeight={ 400 }>
<Spinner size="sm" mr={ 3 }/> <Link onClick={ handleClick }>{ num } more transaction{ num > 1 ? 's' : '' }</Link>
<Text as="span" whiteSpace="pre">+ { num } new transaction{ num > 1 ? 's' : '' }. </Text> <Text whiteSpace="pre"> ha{ num > 1 ? 've' : 's' } come in</Text>
<Link onClick={ handleClick }>View in list</Link>
</Alert> </Alert>
); );
})(); })();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment