From 7908acd93e57d4ede3c503413fa5672069744270 Mon Sep 17 00:00:00 2001 From: ozsirma Date: Tue, 16 Jan 2024 09:00:33 +0300 Subject: [PATCH] refactor(SlidesPanel): performance improvements & refactor --- .../Panels/SlidesPanel/ListWrapper.js | 62 +++++++++++-------- .../Panels/SlidesPanel/SlidesPanel.js | 5 +- .../Panels/SlidesPanel/SortablePageItem.js | 4 +- .../SlidesPanel/SortablePageItemRenderer.js | 3 +- .../Panels/SlidesPanel/SortablePageList.js | 6 -- src/utils/hooks.js | 12 ++-- 6 files changed, 47 insertions(+), 45 deletions(-) diff --git a/src/components/Panels/SlidesPanel/ListWrapper.js b/src/components/Panels/SlidesPanel/ListWrapper.js index a592773..93b17fd 100644 --- a/src/components/Panels/SlidesPanel/ListWrapper.js +++ b/src/components/Panels/SlidesPanel/ListWrapper.js @@ -16,9 +16,8 @@ const ListWrapper = ({ reportSettings, ...otherProps }) => { - const outerRef = useRef(null); + const listRef = useRef(null); const [selectedPageIndex, setSelectedPageIndex] = useState(-1); - const [scrollTracking, setScrollTracking] = useState(true); const { reportBackgroundColor, reportLayoutHeight = 794, @@ -40,55 +39,69 @@ const ListWrapper = ({ const _onSortEnd = useCallback((sortEvent, nativeEvent) => { if (onSortEnd) { - onSortEnd(sortEvent, nativeEvent, outerRef.current); + onSortEnd(sortEvent, nativeEvent, listRef.current); } }, [onSortEnd]); - useEffect(() => { - if (selectedPageIndex !== -1) { - const instance = outerRef.current.getWrappedInstance(); - const list = instance.sortablePageListRef.current; - list.scrollToItem(selectedPageIndex); + const refSetter = useCallback(outerRef => { + if (outerRef) { + const instance = outerRef.getWrappedInstance(); + if (instance) { + listRef.current = instance.sortablePageListRef.current; + } } - }, [selectedPageIndex]); - - useEffect(() => { // for page thumbnails actions - if (!scrollTracking) { - scrollToTarget(`pageActions-id-${selectedPageIndex}`, 0, {}); - setScrollTracking(true); - } - }, [pageCount]); + }, []); usePageVisibility(index => { - if (scrollTracking && index !== selectedPageIndex && !Number.isNaN(index)) { - setSelectedPageIndex(index); - } else if (!scrollTracking && index === selectedPageIndex) { - setScrollTracking(true); + if (index && !Number.isNaN(index)) { + listRef.current?.scrollToItem(index, 'center'); + + const prevSelectedThumbnail = document.querySelector('.thumbnailWrapper.isSelected'); + if (prevSelectedThumbnail) { + prevSelectedThumbnail.classList.remove('isSelected'); + } + + const nextSelectedThumbnail = document + .querySelector(`.thumbnailWrapper[data-order="${index}"]`); + if (nextSelectedThumbnail) { + nextSelectedThumbnail.classList.add('isSelected'); + } } - }, scrollTracking, pageCount, selectedPageIndex); + }, pageCount, selectedPageIndex); + + // TODO: could be better than now. scrollend listener is a choice for some cases + const resetSelectedPageIndex = useCallback(() => { + setTimeout(() => { + setSelectedPageIndex(-1); + }, 1000); + }, []); const onPageClick = useCallback(e => { const order = e.target.getAttribute('data-order'); - setScrollTracking(false); setSelectedPageIndex(parseInt(order, 10)); if (!e.target.classList.contains('controllerItem')) { // for page thumbnails actions scrollToTarget(`pageActions-id-${order}`); } + resetSelectedPageIndex(); }, []); const handlePageAdd = useCallback(index => { - setScrollTracking(false); setSelectedPageIndex(index); onPageAdd(index); }, [onPageAdd]); + useEffect(() => { // after new page added + scrollToTarget(`pageActions-id-${selectedPageIndex}`, 0, {}); + resetSelectedPageIndex(); + }, [pageCount]); + return ( <> {(containerWidth, containerHeight) => ( diff --git a/src/components/Panels/SlidesPanel/SlidesPanel.js b/src/components/Panels/SlidesPanel/SlidesPanel.js index 5e7513d..018d3fc 100644 --- a/src/components/Panels/SlidesPanel/SlidesPanel.js +++ b/src/components/Panels/SlidesPanel/SlidesPanel.js @@ -42,10 +42,7 @@ const SlidesPanel = ({ return pages[index]; }, [pages]); - const onPageSort = useCallback(({ newIndex, oldIndex }, nativeEvent, ref) => { - const instance = ref.getWrappedInstance(); - const list = instance.sortablePageListRef.current; - + const onPageSort = useCallback(({ newIndex, oldIndex }, nativeEvent, list) => { const newPageOrders = arrayMove(pages, oldIndex, newIndex).reduce((acc, page, index) => { acc[page.id] = { order: index + 1 }; return acc; diff --git a/src/components/Panels/SlidesPanel/SortablePageItem.js b/src/components/Panels/SlidesPanel/SortablePageItem.js index 8d0ce30..d162e3b 100644 --- a/src/components/Panels/SlidesPanel/SortablePageItem.js +++ b/src/components/Panels/SlidesPanel/SortablePageItem.js @@ -1,6 +1,5 @@ import { memo } from 'react'; import { SortableElement } from 'react-sortable-hoc'; -import classNames from 'classnames'; import StaticPage from '../../Preview/StaticPage'; import PageThumbnailActions from './PageThumbnailActions'; @@ -9,7 +8,6 @@ const SortablePageItem = SortableElement(({ additionalPageItems, disableInteraction, hashCode, - isSelected, itemAccessor, onAnEventTrigger, onPageAdd, @@ -24,7 +22,7 @@ const SortablePageItem = SortableElement(({ const onKeyDown = f => f; return (
{ const { - pageContainerStyle, pageGetter, selectedPageIndex, ...otherData + pageContainerStyle, pageGetter, ...otherData } = data; const page = pageGetter(index); const pageContainerLastStyle = { @@ -16,7 +16,6 @@ const SortablePageItemRenderer = ({ data, index, style }) => { ({ acceptedItems, additionalPageItems, @@ -31,7 +30,6 @@ const createItemData = memoize(( onPageRemove, pageContainerStyle, pageGetter, - selectedPageIndex, })); const SortablePageList = Component => { @@ -56,7 +54,6 @@ const SortablePageList = Component => { onPageRemove, pageContainerStyle, pageGetter, - selectedPageIndex, } = this.props; return createItemData( acceptedItems, @@ -71,7 +68,6 @@ const SortablePageList = Component => { onPageRemove, pageContainerStyle, pageGetter, - selectedPageIndex, ); } @@ -108,7 +104,6 @@ const SortablePageList = Component => { pageContainerStyle: PropTypes.shape({}), pageCount: PropTypes.number, pageGetter: PropTypes.func, - selectedPageIndex: PropTypes.number, width: PropTypes.number, }; @@ -127,7 +122,6 @@ const SortablePageList = Component => { pageContainerStyle: {}, pageCount: 0, pageGetter: () => {}, - selectedPageIndex: 1, width: 0, }; diff --git a/src/utils/hooks.js b/src/utils/hooks.js index e4793c6..fde7318 100644 --- a/src/utils/hooks.js +++ b/src/utils/hooks.js @@ -78,7 +78,7 @@ export const useFitZoom = ({ }, [settings.reportLayout]); }; -export const usePageVisibility = (callback, scrollTracking, pageCount, selectedPageIndex) => { +export const usePageVisibility = (callback, pageCount, selectedPageIndex) => { const ratio = useRef({}); const pageRefs = useRef([]); const observer = new window.IntersectionObserver(entries => { @@ -108,16 +108,18 @@ export const usePageVisibility = (callback, scrollTracking, pageCount, selectedP }, [pageCount]); useEffect(() => { - pageRefs.current.forEach(page => { - observer.observe(page); - }); + if (selectedPageIndex === -1) { + pageRefs.current.forEach(page => { + observer.observe(page); + }); + } return () => { pageRefs.current.forEach(page => { observer.unobserve(page); }); }; - }, [pageRefs.current, scrollTracking, selectedPageIndex]); + }, [selectedPageIndex]); }; export const useFullscreenChange = (isFullscreen, setIsFullscreen, fitToScreen) => {