From 20d8c0cd35dd3e554089b53ed2e8f4abb0f95bae Mon Sep 17 00:00:00 2001 From: tom goriunov Date: Mon, 4 Mar 2024 19:17:10 +0400 Subject: [PATCH] improve perf of highlighting same address in lists (#1662) Fixes #1661 --- lib/contexts/addressHighlight.tsx | 21 +++++++---- theme/global.ts | 2 ++ theme/globals/address-entity.ts | 37 ++++++++++++++++++++ ui/shared/entities/address/AddressEntity.tsx | 27 +++----------- 4 files changed, 59 insertions(+), 28 deletions(-) create mode 100644 theme/globals/address-entity.ts diff --git a/lib/contexts/addressHighlight.tsx b/lib/contexts/addressHighlight.tsx index f4bb79e8ff..84f5f896ec 100644 --- a/lib/contexts/addressHighlight.tsx +++ b/lib/contexts/addressHighlight.tsx @@ -5,7 +5,6 @@ interface AddressHighlightProviderProps { } interface TAddressHighlightContext { - highlightedAddress: string | null; onMouseEnter: (event: React.MouseEvent) => void; onMouseLeave: (event: React.MouseEvent) => void; } @@ -13,30 +12,40 @@ interface TAddressHighlightContext { export const AddressHighlightContext = React.createContext(null); export function AddressHighlightProvider({ children }: AddressHighlightProviderProps) { - const [ highlightedAddress, setHighlightedAddress ] = React.useState(null); const timeoutId = React.useRef(null); + const hashRef = React.useRef(null); const onMouseEnter = React.useCallback((event: React.MouseEvent) => { const hash = event.currentTarget.getAttribute('data-hash'); if (hash) { + hashRef.current = hash; timeoutId.current = window.setTimeout(() => { - setHighlightedAddress(hash); + // for better performance we update DOM-nodes directly bypassing React reconciliation + const nodes = window.document.querySelectorAll(`[data-hash="${ hashRef.current }"]`); + for (const node of nodes) { + node.classList.add('address-entity_highlighted'); + } }, 100); } }, []); const onMouseLeave = React.useCallback(() => { - setHighlightedAddress(null); + if (hashRef.current) { + const nodes = window.document.querySelectorAll(`[data-hash="${ hashRef.current }"]`); + for (const node of nodes) { + node.classList.remove('address-entity_highlighted'); + } + hashRef.current = null; + } typeof timeoutId.current === 'number' && window.clearTimeout(timeoutId.current); }, []); const value = React.useMemo(() => { return { - highlightedAddress, onMouseEnter, onMouseLeave, }; - }, [ highlightedAddress, onMouseEnter, onMouseLeave ]); + }, [ onMouseEnter, onMouseLeave ]); React.useEffect(() => { return () => { diff --git a/theme/global.ts b/theme/global.ts index 5ddff6bcf7..e50b7eeaf6 100644 --- a/theme/global.ts +++ b/theme/global.ts @@ -2,6 +2,7 @@ import type { StyleFunctionProps } from '@chakra-ui/theme-tools'; import { mode } from '@chakra-ui/theme-tools'; import scrollbar from './foundations/scrollbar'; +import addressEntity from './globals/address-entity'; import getDefaultTransitionProps from './utils/getDefaultTransitionProps'; const global = (props: StyleFunctionProps) => ({ @@ -23,6 +24,7 @@ const global = (props: StyleFunctionProps) => ({ w: '100%', }, ...scrollbar(props), + ...addressEntity(props), }); export default global; diff --git a/theme/globals/address-entity.ts b/theme/globals/address-entity.ts new file mode 100644 index 0000000000..25641c3020 --- /dev/null +++ b/theme/globals/address-entity.ts @@ -0,0 +1,37 @@ +import { mode } from '@chakra-ui/theme-tools'; +import type { StyleFunctionProps } from '@chakra-ui/theme-tools'; + +const styles = (props: StyleFunctionProps) => { + return { + '.address-entity': { + '&.address-entity_highlighted': { + _before: { + content: `" "`, + position: 'absolute', + py: 1, + pl: 1, + pr: 0, + top: '-5px', + left: '-5px', + width: `100%`, + height: '100%', + borderRadius: 'base', + borderColor: mode('blue.200', 'blue.600')(props), + borderWidth: '1px', + borderStyle: 'dashed', + bgColor: mode('blue.50', 'blue.900')(props), + zIndex: -1, + }, + }, + }, + '.address-entity_no-copy': { + '&.address-entity_highlighted': { + _before: { + pr: 2, + }, + }, + }, + }; +}; + +export default styles; diff --git a/ui/shared/entities/address/AddressEntity.tsx b/ui/shared/entities/address/AddressEntity.tsx index 9db9ad5abe..5a29747fca 100644 --- a/ui/shared/entities/address/AddressEntity.tsx +++ b/ui/shared/entities/address/AddressEntity.tsx @@ -1,5 +1,5 @@ import type { As } from '@chakra-ui/react'; -import { Box, Flex, Skeleton, Tooltip, chakra, VStack, useColorModeValue } from '@chakra-ui/react'; +import { Box, Flex, Skeleton, Tooltip, chakra, VStack } from '@chakra-ui/react'; import _omit from 'lodash/omit'; import React from 'react'; @@ -148,33 +148,16 @@ const AddressEntry = (props: EntityProps) => { const partsProps = _omit(props, [ 'className', 'onClick' ]); const context = useAddressHighlightContext(); - const highlightedBgColor = useColorModeValue('blue.50', 'blue.900'); - const highlightedBorderColor = useColorModeValue('blue.200', 'blue.600'); return (