fix(toc): fixed issues of scroll to active items in unpinned sidebar, closes #2213 (#2216)

This commit is contained in:
Huang Xin
2025-10-13 21:29:51 +08:00
committed by GitHub
parent f1c92e5702
commit ad9064fa46
2 changed files with 12 additions and 8 deletions
@@ -51,6 +51,7 @@ const TOCView: React.FC<{
const [expandedItems, setExpandedItems] = useState<Set<string>>(new Set());
const [containerHeight, setContainerHeight] = useState(400);
const hasToggleExpandRef = useRef(false);
const containerRef = useRef<HTMLDivElement | null>(null);
const listOuterRef = useRef<HTMLDivElement | null>(null);
const vitualListRef = useRef<VirtualList | null>(null);
@@ -133,6 +134,7 @@ const TOCView: React.FC<{
const handleToggleExpand = useCallback((item: TOCItem) => {
const itemId = getItemIdentifier(item);
hasToggleExpandRef.current = true;
setExpandedItems((prev) => {
const newSet = new Set(prev);
if (newSet.has(itemId)) {
@@ -175,8 +177,11 @@ const TOCView: React.FC<{
const hrefMd5 = activeHref ? getContentMd5(activeHref) : '';
const activeItem = staticListRef.current?.querySelector(`[data-href="${hrefMd5}"]`);
if (activeItem) {
const rect = activeItem.getBoundingClientRect();
const isVisible = rect.top >= 0 && rect.bottom <= window.innerHeight;
const container = staticListRef.current.parentElement!;
const containerRect = container.getBoundingClientRect();
const itemRect = activeItem.getBoundingClientRect();
const isVisible =
itemRect.top >= containerRect.top && itemRect.bottom <= containerRect.bottom;
if (!isVisible) {
(activeItem as HTMLElement).scrollIntoView({ behavior: 'instant', block: 'center' });
}
@@ -213,11 +218,15 @@ const TOCView: React.FC<{
}, [toc, progress, viewState, sideBarBookKey, isSideBarVisible, bookKey, expandParents]);
useEffect(() => {
if (hasToggleExpandRef.current) {
hasToggleExpandRef.current = false;
return;
}
if (flatItems.length > 0) {
setTimeout(scrollToActiveItem, appService?.isAndroidApp ? 300 : 100);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [progress]);
}, [progress, scrollToActiveItem]);
return sections && sections.length > 256 ? (
<div
@@ -357,11 +357,6 @@ const ColorPanel: React.FC<SettingsPanelPanelProp> = ({ bookKey, onRegisterReset
minHeight: '80px',
}}
>
{texture.path && (
<div className='absolute inset-0 flex items-center justify-center rounded-lg bg-black bg-opacity-40'>
<span className='text-sm font-medium text-white'>{_(texture.name)}</span>
</div>
)}
{selectedTextureId === texture.id && (
<MdRadioButtonChecked
size={iconSize24}