Commit 5552cd6d authored by tom's avatar tom

Merge branch 'main' of github.com:blockscout/frontend into tom2drum/issue-2029

parents fed42c9c 6095da71
...@@ -16,7 +16,7 @@ const L2WithdrawalUrl = getEnvValue('NEXT_PUBLIC_ROLLUP_L2_WITHDRAWAL_URL'); ...@@ -16,7 +16,7 @@ const L2WithdrawalUrl = getEnvValue('NEXT_PUBLIC_ROLLUP_L2_WITHDRAWAL_URL');
const title = 'Rollup (L2) chain'; const title = 'Rollup (L2) chain';
const config: Feature<{ type: RollupType; L1BaseUrl: string; L2WithdrawalUrl?: string }> = (() => { const config: Feature<{ type: RollupType; L1BaseUrl: string; L2WithdrawalUrl?: string; homepage: { showLatestBlocks: boolean } }> = (() => {
if (type && L1BaseUrl) { if (type && L1BaseUrl) {
return Object.freeze({ return Object.freeze({
...@@ -25,6 +25,9 @@ const config: Feature<{ type: RollupType; L1BaseUrl: string; L2WithdrawalUrl?: s ...@@ -25,6 +25,9 @@ const config: Feature<{ type: RollupType; L1BaseUrl: string; L2WithdrawalUrl?: s
type, type,
L1BaseUrl: stripTrailingSlash(L1BaseUrl), L1BaseUrl: stripTrailingSlash(L1BaseUrl),
L2WithdrawalUrl, L2WithdrawalUrl,
homepage: {
showLatestBlocks: getEnvValue('NEXT_PUBLIC_ROLLUP_HOMEPAGE_SHOW_LATEST_BLOCKS') === 'true',
},
}); });
} }
......
...@@ -287,6 +287,17 @@ const rollupSchema = yup ...@@ -287,6 +287,17 @@ const rollupSchema = yup
then: (schema) => schema.test(urlTest).required(), then: (schema) => schema.test(urlTest).required(),
otherwise: (schema) => schema.max(-1, 'NEXT_PUBLIC_ROLLUP_L2_WITHDRAWAL_URL can be used only if NEXT_PUBLIC_ROLLUP_TYPE is set to \'optimistic\' '), otherwise: (schema) => schema.max(-1, 'NEXT_PUBLIC_ROLLUP_L2_WITHDRAWAL_URL can be used only if NEXT_PUBLIC_ROLLUP_TYPE is set to \'optimistic\' '),
}), }),
NEXT_PUBLIC_ROLLUP_HOMEPAGE_SHOW_LATEST_BLOCKS: yup
.boolean()
.when('NEXT_PUBLIC_ROLLUP_TYPE', {
is: (value: string) => value,
then: (schema) => schema,
otherwise: (schema) => schema.test(
'not-exist',
'NEXT_PUBLIC_ROLLUP_HOMEPAGE_SHOW_LATEST_BLOCKS cannot not be used if NEXT_PUBLIC_ROLLUP_TYPE is not defined',
value => value === undefined,
),
}),
}); });
const adButlerConfigSchema = yup const adButlerConfigSchema = yup
......
NEXT_PUBLIC_ROLLUP_TYPE=optimistic NEXT_PUBLIC_ROLLUP_TYPE=optimistic
NEXT_PUBLIC_ROLLUP_L1_BASE_URL=https://example.com NEXT_PUBLIC_ROLLUP_L1_BASE_URL=https://example.com
NEXT_PUBLIC_ROLLUP_L2_WITHDRAWAL_URL=https://example.com NEXT_PUBLIC_ROLLUP_L2_WITHDRAWAL_URL=https://example.com
NEXT_PUBLIC_FAULT_PROOF_ENABLED=true NEXT_PUBLIC_FAULT_PROOF_ENABLED=true
\ No newline at end of file NEXT_PUBLIC_ROLLUP_HOMEPAGE_SHOW_LATEST_BLOCKS=true
\ No newline at end of file
...@@ -434,6 +434,7 @@ This feature is **enabled by default** with the `coinzilla` ads provider. To swi ...@@ -434,6 +434,7 @@ This feature is **enabled by default** with the `coinzilla` ads provider. To swi
| NEXT_PUBLIC_ROLLUP_L2_WITHDRAWAL_URL | `string` | URL for L2 -> L1 withdrawals (Optimistic stack only) | Required for `optimistic` rollups | - | `https://app.optimism.io/bridge/withdraw` | v1.24.0+ | | NEXT_PUBLIC_ROLLUP_L2_WITHDRAWAL_URL | `string` | URL for L2 -> L1 withdrawals (Optimistic stack only) | Required for `optimistic` rollups | - | `https://app.optimism.io/bridge/withdraw` | v1.24.0+ |
| NEXT_PUBLIC_FAULT_PROOF_ENABLED | `boolean` | Set to `true` for chains with fault proof system enabled (Optimistic stack only) | - | - | `true` | v1.31.0+ | | NEXT_PUBLIC_FAULT_PROOF_ENABLED | `boolean` | Set to `true` for chains with fault proof system enabled (Optimistic stack only) | - | - | `true` | v1.31.0+ |
| NEXT_PUBLIC_HAS_MUD_FRAMEWORK | `boolean` | Set to `true` for instances that use MUD framework (Optimistic stack only) | - | - | `true` | v1.33.0+ | | NEXT_PUBLIC_HAS_MUD_FRAMEWORK | `boolean` | Set to `true` for instances that use MUD framework (Optimistic stack only) | - | - | `true` | v1.33.0+ |
| NEXT_PUBLIC_ROLLUP_HOMEPAGE_SHOW_LATEST_BLOCKS | `boolean` | Set to `true` to display "Latest blocks" widget instead of "Latest batches" on the home page | - | - | `true` | v1.36.0+ |
&nbsp; &nbsp;
......
...@@ -40,8 +40,8 @@ const TEMPLATE_MAP: Record<Route['pathname'], string> = { ...@@ -40,8 +40,8 @@ const TEMPLATE_MAP: Record<Route['pathname'], string> = {
'/deposits': '%network_name% deposits (L1 > L2)', '/deposits': '%network_name% deposits (L1 > L2)',
'/output-roots': '%network_name% output roots', '/output-roots': '%network_name% output roots',
'/dispute-games': '%network_name% dispute games', '/dispute-games': '%network_name% dispute games',
'/batches': '%network_name% tx batches (L2 blocks)', '/batches': '%network_name% txn batches',
'/batches/[number]': '%network_name% L2 tx batch %number%', '/batches/[number]': '%network_name% L2 txn batch %number%',
'/blobs/[hash]': '%network_name% blob %hash% details', '/blobs/[hash]': '%network_name% blob %hash% details',
'/ops': 'User operations on %network_name% - %network_name% explorer', '/ops': 'User operations on %network_name% - %network_name% explorer',
'/op/[hash]': '%network_name% user operation %hash%', '/op/[hash]': '%network_name% user operation %hash%',
......
...@@ -38,8 +38,8 @@ export const PAGE_TYPE_DICT: Record<Route['pathname'], string> = { ...@@ -38,8 +38,8 @@ export const PAGE_TYPE_DICT: Record<Route['pathname'], string> = {
'/deposits': 'Deposits (L1 > L2)', '/deposits': 'Deposits (L1 > L2)',
'/output-roots': 'Output roots', '/output-roots': 'Output roots',
'/dispute-games': 'Dispute games', '/dispute-games': 'Dispute games',
'/batches': 'Tx batches (L2 blocks)', '/batches': 'Txn batches',
'/batches/[number]': 'L2 tx batch details', '/batches/[number]': 'L2 txn batch details',
'/blobs/[hash]': 'Blob details', '/blobs/[hash]': 'Blob details',
'/ops': 'User operations', '/ops': 'User operations',
'/op/[hash]': 'User operation details', '/op/[hash]': 'User operation details',
......
import _get from 'lodash/get';
import React from 'react'; import React from 'react';
import config from 'configs/app'; import config from 'configs/app';
...@@ -24,9 +25,10 @@ export default function useAddOrSwitchChain() { ...@@ -24,9 +25,10 @@ export default function useAddOrSwitchChain() {
const errorObj = getErrorObj(error); const errorObj = getErrorObj(error);
const code = errorObj && 'code' in errorObj ? errorObj.code : undefined; const code = errorObj && 'code' in errorObj ? errorObj.code : undefined;
const originalErrorCode = _get(errorObj, 'data.originalError.code');
// This error code indicates that the chain has not been added to Wallet. // This error code indicates that the chain has not been added to Wallet.
if (code === 4902) { if (code === 4902 || originalErrorCode === 4902) {
const params = [ { const params = [ {
chainId: hexadecimalChainId, chainId: hexadecimalChainId,
chainName: config.chain.name, chainName: config.chain.name,
......
...@@ -69,6 +69,17 @@ const abiItem: AbiFunction = { ...@@ -69,6 +69,17 @@ const abiItem: AbiFunction = {
name: 'internalProposals', name: 'internalProposals',
type: 'tuple[]', type: 'tuple[]',
}, },
// ARRAY OF TUPLES WITHOUT NAMES
{
components: [
{ type: 'address' },
{ type: 'uint256' },
],
internalType: 'struct SharingPercentage[]',
name: '_sharingPercentages',
type: 'tuple[]',
},
], ],
}; };
...@@ -115,6 +126,10 @@ const result = [ ...@@ -115,6 +126,10 @@ const result = [
}, },
}, },
], ],
[
[ '0xfD36176C63dA52E783a347DE3544B0b44C7054a6', 0 ],
[ '0xC9534cB913150aD3e98D792857689B55e2404212', 3500 ],
],
]; ];
const onSettle = () => {}; const onSettle = () => {};
......
...@@ -23,8 +23,20 @@ const ItemTuple = ({ abiParameter, data, mode, level }: Props) => { ...@@ -23,8 +23,20 @@ const ItemTuple = ({ abiParameter, data, mode, level }: Props) => {
<span> { '{' }</span> <span> { '{' }</span>
</p> </p>
{ 'components' in abiParameter && abiParameter.components.map((component, index) => { { 'components' in abiParameter && abiParameter.components.map((component, index) => {
const dataObj = typeof data === 'object' && data !== null ? data : undefined; const itemData = (() => {
const itemData = dataObj && component.name && component.name in dataObj ? dataObj[component.name as keyof typeof dataObj] : undefined; if (typeof data !== 'object' || data === null) {
return;
}
if (Array.isArray(data)) {
return data[index];
}
if (component.name && component.name in data) {
return data[component.name as keyof typeof data];
}
})();
return ( return (
<Item <Item
key={ index } key={ index }
......
...@@ -108,7 +108,7 @@ const ArbitrumL2TxnBatch = () => { ...@@ -108,7 +108,7 @@ const ArbitrumL2TxnBatch = () => {
} }
return { return {
label: 'Back to tx batches list', label: 'Back to txn batches list',
url: appProps.referrer, url: appProps.referrer,
}; };
}, [ appProps.referrer ]); }, [ appProps.referrer ]);
...@@ -117,7 +117,7 @@ const ArbitrumL2TxnBatch = () => { ...@@ -117,7 +117,7 @@ const ArbitrumL2TxnBatch = () => {
<> <>
<TextAd mb={ 6 }/> <TextAd mb={ 6 }/>
<PageTitle <PageTitle
title={ `Tx batch #${ number }` } title={ `Txn batch #${ number }` }
backLink={ backLink } backLink={ backLink }
/> />
{ batchQuery.isPlaceholderData ? { batchQuery.isPlaceholderData ?
......
...@@ -2,7 +2,6 @@ import { Hide, Show, Skeleton, Text } from '@chakra-ui/react'; ...@@ -2,7 +2,6 @@ import { Hide, Show, Skeleton, Text } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import useApiQuery from 'lib/api/useApiQuery'; import useApiQuery from 'lib/api/useApiQuery';
import { nbsp } from 'lib/html-entities';
import { ARBITRUM_L2_TXN_BATCHES_ITEM } from 'stubs/arbitrumL2'; import { ARBITRUM_L2_TXN_BATCHES_ITEM } from 'stubs/arbitrumL2';
import { generateListStub } from 'stubs/utils'; import { generateListStub } from 'stubs/utils';
import { ACTION_BAR_HEIGHT_DESKTOP } from 'ui/shared/ActionBar'; import { ACTION_BAR_HEIGHT_DESKTOP } from 'ui/shared/ActionBar';
...@@ -60,7 +59,7 @@ const ArbitrumL2TxnBatches = () => { ...@@ -60,7 +59,7 @@ const ArbitrumL2TxnBatches = () => {
return ( return (
<Skeleton isLoaded={ !countersQuery.isPlaceholderData && !isPlaceholderData } display="flex" flexWrap="wrap"> <Skeleton isLoaded={ !countersQuery.isPlaceholderData && !isPlaceholderData } display="flex" flexWrap="wrap">
Tx batch (L2 block) Txn batch
<Text fontWeight={ 600 } whiteSpace="pre"> #{ data.items[0].number } </Text>to <Text fontWeight={ 600 } whiteSpace="pre"> #{ data.items[0].number } </Text>to
<Text fontWeight={ 600 } whiteSpace="pre"> #{ data.items[data.items.length - 1].number } </Text> <Text fontWeight={ 600 } whiteSpace="pre"> #{ data.items[data.items.length - 1].number } </Text>
(total of { countersQuery.data?.toLocaleString() } batches) (total of { countersQuery.data?.toLocaleString() } batches)
...@@ -72,11 +71,11 @@ const ArbitrumL2TxnBatches = () => { ...@@ -72,11 +71,11 @@ const ArbitrumL2TxnBatches = () => {
return ( return (
<> <>
<PageTitle title={ `Tx batches (L2${ nbsp }blocks)` } withTextAd/> <PageTitle title="Txn batches" withTextAd/>
<DataListDisplay <DataListDisplay
isError={ isError } isError={ isError }
items={ data?.items } items={ data?.items }
emptyText="There are no tx batches." emptyText="There are no txn batches."
content={ content } content={ content }
actionBar={ actionBar } actionBar={ actionBar }
/> />
......
...@@ -14,6 +14,20 @@ import AdBanner from 'ui/shared/ad/AdBanner'; ...@@ -14,6 +14,20 @@ import AdBanner from 'ui/shared/ad/AdBanner';
const rollupFeature = config.features.rollup; const rollupFeature = config.features.rollup;
const Home = () => { const Home = () => {
const leftWidget = (() => {
if (rollupFeature.isEnabled && !rollupFeature.homepage.showLatestBlocks) {
switch (rollupFeature.type) {
case 'zkEvm':
return <LatestZkEvmL2Batches/>;
case 'arbitrum':
return <LatestArbitrumL2Batches/>;
}
}
return <LatestBlocks/>;
})();
return ( return (
<Box as="main"> <Box as="main">
<HeroBanner/> <HeroBanner/>
...@@ -23,9 +37,7 @@ const Home = () => { ...@@ -23,9 +37,7 @@ const Home = () => {
</Flex> </Flex>
<AdBanner mt={ 6 } mx="auto" display={{ base: 'flex', lg: 'none' }} justifyContent="center"/> <AdBanner mt={ 6 } mx="auto" display={{ base: 'flex', lg: 'none' }} justifyContent="center"/>
<Flex mt={ 8 } direction={{ base: 'column', lg: 'row' }} columnGap={ 12 } rowGap={ 6 }> <Flex mt={ 8 } direction={{ base: 'column', lg: 'row' }} columnGap={ 12 } rowGap={ 6 }>
{ rollupFeature.isEnabled && rollupFeature.type === 'zkEvm' && <LatestZkEvmL2Batches/> } { leftWidget }
{ rollupFeature.isEnabled && rollupFeature.type === 'arbitrum' && <LatestArbitrumL2Batches/> }
{ !(rollupFeature.isEnabled && (rollupFeature.type === 'arbitrum' || rollupFeature.type === 'zkEvm')) && <LatestBlocks/> }
<Box flexGrow={ 1 }> <Box flexGrow={ 1 }>
<Transactions/> <Transactions/>
</Box> </Box>
......
...@@ -106,7 +106,7 @@ const OptimisticL2TxnBatch = () => { ...@@ -106,7 +106,7 @@ const OptimisticL2TxnBatch = () => {
} }
return { return {
label: 'Back to tx batches list', label: 'Back to txn batches list',
url: appProps.referrer, url: appProps.referrer,
}; };
}, [ appProps.referrer ]); }, [ appProps.referrer ]);
......
...@@ -2,7 +2,6 @@ import { Hide, Show, Skeleton, Text } from '@chakra-ui/react'; ...@@ -2,7 +2,6 @@ import { Hide, Show, Skeleton, Text } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import useApiQuery from 'lib/api/useApiQuery'; import useApiQuery from 'lib/api/useApiQuery';
import { nbsp } from 'lib/html-entities';
import { L2_TXN_BATCHES_ITEM } from 'stubs/L2'; import { L2_TXN_BATCHES_ITEM } from 'stubs/L2';
import { generateListStub } from 'stubs/utils'; import { generateListStub } from 'stubs/utils';
import { ACTION_BAR_HEIGHT_DESKTOP } from 'ui/shared/ActionBar'; import { ACTION_BAR_HEIGHT_DESKTOP } from 'ui/shared/ActionBar';
...@@ -60,7 +59,7 @@ const OptimisticL2TxnBatches = () => { ...@@ -60,7 +59,7 @@ const OptimisticL2TxnBatches = () => {
return ( return (
<Skeleton isLoaded={ !countersQuery.isPlaceholderData && !isPlaceholderData } display="flex" flexWrap="wrap"> <Skeleton isLoaded={ !countersQuery.isPlaceholderData && !isPlaceholderData } display="flex" flexWrap="wrap">
Tx batch (L2 block) Txn batch
<Text fontWeight={ 600 } whiteSpace="pre"> #{ data.items[0].internal_id } </Text>to <Text fontWeight={ 600 } whiteSpace="pre"> #{ data.items[0].internal_id } </Text>to
<Text fontWeight={ 600 } whiteSpace="pre"> #{ data.items[data.items.length - 1].internal_id } </Text> <Text fontWeight={ 600 } whiteSpace="pre"> #{ data.items[data.items.length - 1].internal_id } </Text>
(total of { countersQuery.data?.toLocaleString() } batches) (total of { countersQuery.data?.toLocaleString() } batches)
...@@ -72,11 +71,11 @@ const OptimisticL2TxnBatches = () => { ...@@ -72,11 +71,11 @@ const OptimisticL2TxnBatches = () => {
return ( return (
<> <>
<PageTitle title={ `Tx batches (L2${ nbsp }blocks)` } withTextAd/> <PageTitle title="Txn batches" withTextAd/>
<DataListDisplay <DataListDisplay
isError={ isError } isError={ isError }
items={ data?.items } items={ data?.items }
emptyText="There are no tx batches." emptyText="There are no txn batches."
content={ content } content={ content }
actionBar={ actionBar } actionBar={ actionBar }
/> />
......
...@@ -59,7 +59,7 @@ const ZkEvmL2TxnBatch = () => { ...@@ -59,7 +59,7 @@ const ZkEvmL2TxnBatch = () => {
} }
return { return {
label: 'Back to tx batches list', label: 'Back to txn batches list',
url: appProps.referrer, url: appProps.referrer,
}; };
}, [ appProps.referrer ]); }, [ appProps.referrer ]);
...@@ -68,7 +68,7 @@ const ZkEvmL2TxnBatch = () => { ...@@ -68,7 +68,7 @@ const ZkEvmL2TxnBatch = () => {
<> <>
<TextAd mb={ 6 }/> <TextAd mb={ 6 }/>
<PageTitle <PageTitle
title={ `Tx batch #${ number }` } title={ `Txn batch #${ number }` }
backLink={ backLink } backLink={ backLink }
/> />
{ batchQuery.isPlaceholderData ? <TabsSkeleton tabs={ tabs }/> : ( { batchQuery.isPlaceholderData ? <TabsSkeleton tabs={ tabs }/> : (
......
...@@ -59,7 +59,7 @@ const ZkEvmL2TxnBatches = () => { ...@@ -59,7 +59,7 @@ const ZkEvmL2TxnBatches = () => {
return ( return (
<Skeleton isLoaded={ !countersQuery.isPlaceholderData && !isPlaceholderData } display="flex" flexWrap="wrap"> <Skeleton isLoaded={ !countersQuery.isPlaceholderData && !isPlaceholderData } display="flex" flexWrap="wrap">
Tx batch Txn batch
<Text fontWeight={ 600 } whiteSpace="pre"> #{ data.items[0].number } </Text>to <Text fontWeight={ 600 } whiteSpace="pre"> #{ data.items[0].number } </Text>to
<Text fontWeight={ 600 } whiteSpace="pre"> #{ data.items[data.items.length - 1].number } </Text> <Text fontWeight={ 600 } whiteSpace="pre"> #{ data.items[data.items.length - 1].number } </Text>
(total of { countersQuery.data?.toLocaleString() } batches) (total of { countersQuery.data?.toLocaleString() } batches)
...@@ -71,11 +71,11 @@ const ZkEvmL2TxnBatches = () => { ...@@ -71,11 +71,11 @@ const ZkEvmL2TxnBatches = () => {
return ( return (
<> <>
<PageTitle title="Tx batches" withTextAd/> <PageTitle title="Txn batches" withTextAd/>
<DataListDisplay <DataListDisplay
isError={ isError } isError={ isError }
items={ data?.items } items={ data?.items }
emptyText="There are no tx batches." emptyText="There are no txn batches."
content={ content } content={ content }
actionBar={ actionBar } actionBar={ actionBar }
/> />
......
...@@ -80,7 +80,7 @@ const ZkSyncL2TxnBatch = () => { ...@@ -80,7 +80,7 @@ const ZkSyncL2TxnBatch = () => {
} }
return { return {
label: 'Back to tx batches list', label: 'Back to txn batches list',
url: appProps.referrer, url: appProps.referrer,
}; };
}, [ appProps.referrer ]); }, [ appProps.referrer ]);
...@@ -89,7 +89,7 @@ const ZkSyncL2TxnBatch = () => { ...@@ -89,7 +89,7 @@ const ZkSyncL2TxnBatch = () => {
<> <>
<TextAd mb={ 6 }/> <TextAd mb={ 6 }/>
<PageTitle <PageTitle
title={ `Tx batch #${ number }` } title={ `Txn batch #${ number }` }
backLink={ backLink } backLink={ backLink }
/> />
{ batchQuery.isPlaceholderData ? { batchQuery.isPlaceholderData ?
......
...@@ -59,7 +59,7 @@ const ZkSyncL2TxnBatches = () => { ...@@ -59,7 +59,7 @@ const ZkSyncL2TxnBatches = () => {
return ( return (
<Skeleton isLoaded={ !countersQuery.isPlaceholderData && !isPlaceholderData } display="flex" flexWrap="wrap"> <Skeleton isLoaded={ !countersQuery.isPlaceholderData && !isPlaceholderData } display="flex" flexWrap="wrap">
Tx batch Txn batch
<Text fontWeight={ 600 } whiteSpace="pre"> #{ data.items[0].number } </Text>to <Text fontWeight={ 600 } whiteSpace="pre"> #{ data.items[0].number } </Text>to
<Text fontWeight={ 600 } whiteSpace="pre"> #{ data.items[data.items.length - 1].number } </Text> <Text fontWeight={ 600 } whiteSpace="pre"> #{ data.items[data.items.length - 1].number } </Text>
(total of { countersQuery.data?.toLocaleString() } batches) (total of { countersQuery.data?.toLocaleString() } batches)
...@@ -71,11 +71,11 @@ const ZkSyncL2TxnBatches = () => { ...@@ -71,11 +71,11 @@ const ZkSyncL2TxnBatches = () => {
return ( return (
<> <>
<PageTitle title="Tx batches" withTextAd/> <PageTitle title="Txn batches" withTextAd/>
<DataListDisplay <DataListDisplay
isError={ isError } isError={ isError }
items={ data?.items } items={ data?.items }
emptyText="There are no tx batches." emptyText="There are no txn batches."
content={ content } content={ content }
actionBar={ actionBar } actionBar={ actionBar }
/> />
......
...@@ -151,6 +151,7 @@ const SearchBar = ({ isHomepage }: Props) => { ...@@ -151,6 +151,7 @@ const SearchBar = ({ isHomepage }: Props) => {
<PopoverContent <PopoverContent
w={ `${ menuWidth.current }px` } w={ `${ menuWidth.current }px` }
ref={ menuRef } ref={ menuRef }
overflow="hidden"
> >
<PopoverBody <PopoverBody
p={ 0 } p={ 0 }
......
import { InputGroup, Input, InputLeftElement, chakra, useColorModeValue, forwardRef, InputRightElement } from '@chakra-ui/react'; import { InputGroup, Input, InputLeftElement, chakra, useColorModeValue, forwardRef, InputRightElement, Center } from '@chakra-ui/react';
import throttle from 'lodash/throttle'; import throttle from 'lodash/throttle';
import React from 'react'; import React from 'react';
import type { ChangeEvent, FormEvent, FocusEvent } from 'react'; import type { ChangeEvent, FormEvent, FocusEvent } from 'react';
...@@ -62,9 +62,69 @@ const SearchBarInput = ( ...@@ -62,9 +62,69 @@ const SearchBarInput = (
}; };
}, [ isMobile, handleScroll ]); }, [ isMobile, handleScroll ]);
const handleKeyPress = React.useCallback((event: KeyboardEvent) => {
if (isMobile) {
return;
}
switch (event.key) {
case '/': {
if ([ 'INPUT', 'TEXTAREA' ].includes((event.target as HTMLElement).tagName)) {
break;
}
if (!isSuggestOpen) {
event.preventDefault();
innerRef.current?.querySelector('input')?.focus();
onFocus?.();
}
break;
}
case 'Escape': {
if (isSuggestOpen) {
innerRef.current?.querySelector('input')?.blur();
onHide?.();
}
break;
}
}
}, [ isMobile, isSuggestOpen, onFocus, onHide ]);
React.useEffect(() => {
window.addEventListener('keydown', handleKeyPress);
return () => {
window.removeEventListener('keydown', handleKeyPress);
};
}, [ handleKeyPress ]);
const bgColor = useColorModeValue('white', 'black'); const bgColor = useColorModeValue('white', 'black');
const transformMobile = scrollDirection !== 'down' ? 'translateY(0)' : 'translateY(-100%)'; const transformMobile = scrollDirection !== 'down' ? 'translateY(0)' : 'translateY(-100%)';
const rightElement = (() => {
if (value) {
return <ClearButton onClick={ onClear }/>;
}
if (isMobile) {
return null;
}
return (
<Center
boxSize="20px"
my="2px"
mr={{ base: 1, lg: isHomepage ? 2 : 1 }}
borderRadius="sm"
borderWidth="1px"
borderColor="gray.400"
color="gray.400"
display={{ base: 'none', lg: 'flex' }}
>
/
</Center>
);
})();
return ( return (
<chakra.form <chakra.form
ref={ innerRef } ref={ innerRef }
...@@ -111,11 +171,9 @@ const SearchBarInput = ( ...@@ -111,11 +171,9 @@ const SearchBarInput = (
color={ useColorModeValue('black', 'white') } color={ useColorModeValue('black', 'white') }
value={ value } value={ value }
/> />
{ value && ( <InputRightElement top={{ base: 2, lg: isHomepage ? 3 : 2 }} right={ 2 }>
<InputRightElement top={{ base: 2, lg: isHomepage ? 3 : 2 }} right={ 2 }> { rightElement }
<ClearButton onClick={ onClear }/> </InputRightElement>
</InputRightElement>
) }
</InputGroup> </InputGroup>
</chakra.form> </chakra.form>
); );
......
...@@ -306,7 +306,7 @@ const TxInfo = ({ data, isLoading, socketStatus }: Props) => { ...@@ -306,7 +306,7 @@ const TxInfo = ({ data, isLoading, socketStatus }: Props) => {
hint="Batch index for this transaction" hint="Batch index for this transaction"
isLoading={ isLoading } isLoading={ isLoading }
> >
Tx batch Txn batch
</DetailsInfoItem.Label> </DetailsInfoItem.Label>
<DetailsInfoItem.Value> <DetailsInfoItem.Value>
<BatchEntityL2 <BatchEntityL2
......
...@@ -77,7 +77,7 @@ const ArbitrumL2TxnBatchDetails = ({ query }: Props) => { ...@@ -77,7 +77,7 @@ const ArbitrumL2TxnBatchDetails = ({ query }: Props) => {
isLoading={ isPlaceholderData } isLoading={ isPlaceholderData }
hint="Batch number indicates the length of batches produced by grouping L2 blocks to be proven on L1" hint="Batch number indicates the length of batches produced by grouping L2 blocks to be proven on L1"
> >
Tx batch number Txn batch number
</DetailsInfoItem.Label> </DetailsInfoItem.Label>
<DetailsInfoItem.Value> <DetailsInfoItem.Value>
<Skeleton isLoaded={ !isPlaceholderData }> <Skeleton isLoaded={ !isPlaceholderData }>
...@@ -86,8 +86,8 @@ const ArbitrumL2TxnBatchDetails = ({ query }: Props) => { ...@@ -86,8 +86,8 @@ const ArbitrumL2TxnBatchDetails = ({ query }: Props) => {
<PrevNext <PrevNext
ml={ 6 } ml={ 6 }
onClick={ handlePrevNextClick } onClick={ handlePrevNextClick }
prevLabel="View previous tx batch" prevLabel="View previous txn batch"
nextLabel="View next tx batch" nextLabel="View next txn batch"
isPrevDisabled={ data.number === 0 } isPrevDisabled={ data.number === 0 }
isLoading={ isPlaceholderData } isLoading={ isPlaceholderData }
/> />
......
...@@ -47,7 +47,7 @@ const OptimisticL2TxnBatchBlobCelestia = ({ blobs, isLoading }: Props) => { ...@@ -47,7 +47,7 @@ const OptimisticL2TxnBatchBlobCelestia = ({ blobs, isLoading }: Props) => {
<Icon as={ celeniumIcon } boxSize={ 5 }/> <Icon as={ celeniumIcon } boxSize={ 5 }/>
<LinkExternal href={ getCeleniumUrl(blob) }>Blob page</LinkExternal> <LinkExternal href={ getCeleniumUrl(blob) }>Blob page</LinkExternal>
</GridItem> </GridItem>
<GridItem fontWeight={ 600 }>Hight</GridItem> <GridItem fontWeight={ 600 }>Height</GridItem>
<GridItem colSpan={ 2 }> <GridItem colSpan={ 2 }>
{ blob.height } { blob.height }
</GridItem> </GridItem>
......
...@@ -75,8 +75,8 @@ const OptimisticL2TxnBatchDetails = ({ query }: Props) => { ...@@ -75,8 +75,8 @@ const OptimisticL2TxnBatchDetails = ({ query }: Props) => {
<PrevNext <PrevNext
ml={ 6 } ml={ 6 }
onClick={ handlePrevNextClick } onClick={ handlePrevNextClick }
prevLabel="View previous tx batch" prevLabel="View previous txn batch"
nextLabel="View next tx batch" nextLabel="View next txn batch"
isPrevDisabled={ data.internal_id === 0 } isPrevDisabled={ data.internal_id === 0 }
isLoading={ isPlaceholderData } isLoading={ isPlaceholderData }
/> />
......
...@@ -68,7 +68,7 @@ const OptimisticL2TxnBatchesListItem = ({ item, isLoading }: Props) => { ...@@ -68,7 +68,7 @@ const OptimisticL2TxnBatchesListItem = ({ item, isLoading }: Props) => {
</LinkInternal> </LinkInternal>
</ListItemMobileGrid.Value> </ListItemMobileGrid.Value>
<ListItemMobileGrid.Label isLoading={ isLoading }>L2 blocks</ListItemMobileGrid.Label> <ListItemMobileGrid.Label isLoading={ isLoading }>Txn</ListItemMobileGrid.Label>
<ListItemMobileGrid.Value> <ListItemMobileGrid.Value>
<LinkInternal <LinkInternal
href={ route({ pathname: '/batches/[number]', query: { number: item.internal_id.toString(), tab: 'txs' } }) } href={ route({ pathname: '/batches/[number]', query: { number: item.internal_id.toString(), tab: 'txs' } }) }
......
...@@ -64,7 +64,7 @@ const ZkEvmL2TxnBatchDetails = ({ query }: Props) => { ...@@ -64,7 +64,7 @@ const ZkEvmL2TxnBatchDetails = ({ query }: Props) => {
<DetailsInfoItem.Label <DetailsInfoItem.Label
isLoading={ isPlaceholderData } isLoading={ isPlaceholderData }
> >
Tx batch number Txn batch number
</DetailsInfoItem.Label> </DetailsInfoItem.Label>
<DetailsInfoItem.Value> <DetailsInfoItem.Value>
<Skeleton isLoaded={ !isPlaceholderData }> <Skeleton isLoaded={ !isPlaceholderData }>
...@@ -73,8 +73,8 @@ const ZkEvmL2TxnBatchDetails = ({ query }: Props) => { ...@@ -73,8 +73,8 @@ const ZkEvmL2TxnBatchDetails = ({ query }: Props) => {
<PrevNext <PrevNext
ml={ 6 } ml={ 6 }
onClick={ handlePrevNextClick } onClick={ handlePrevNextClick }
prevLabel="View previous tx batch" prevLabel="View previous txn batch"
nextLabel="View next tx batch" nextLabel="View next txn batch"
isPrevDisabled={ data.number === 0 } isPrevDisabled={ data.number === 0 }
isLoading={ isPlaceholderData } isLoading={ isPlaceholderData }
/> />
......
...@@ -80,7 +80,7 @@ const ZkSyncL2TxnBatchDetails = ({ query }: Props) => { ...@@ -80,7 +80,7 @@ const ZkSyncL2TxnBatchDetails = ({ query }: Props) => {
hint="Batch number indicates the length of batches produced by grouping L2 blocks to be proven on Ethereum." hint="Batch number indicates the length of batches produced by grouping L2 blocks to be proven on Ethereum."
isLoading={ isPlaceholderData } isLoading={ isPlaceholderData }
> >
Tx batch number Txn batch number
</DetailsInfoItem.Label> </DetailsInfoItem.Label>
<DetailsInfoItem.Value> <DetailsInfoItem.Value>
<Skeleton isLoaded={ !isPlaceholderData }> <Skeleton isLoaded={ !isPlaceholderData }>
...@@ -89,8 +89,8 @@ const ZkSyncL2TxnBatchDetails = ({ query }: Props) => { ...@@ -89,8 +89,8 @@ const ZkSyncL2TxnBatchDetails = ({ query }: Props) => {
<PrevNext <PrevNext
ml={ 6 } ml={ 6 }
onClick={ handlePrevNextClick } onClick={ handlePrevNextClick }
prevLabel="View previous tx batch" prevLabel="View previous txn batch"
nextLabel="View next tx batch" nextLabel="View next txn batch"
isPrevDisabled={ data.number === 0 } isPrevDisabled={ data.number === 0 }
isLoading={ isPlaceholderData } isLoading={ isPlaceholderData }
/> />
......
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