mirror of
https://github.com/bitsocialnet/5chan.git
synced 2026-08-03 07:41:04 +02:00
perf: implement LRU-cached persistent feed mounting to eliminate Virtuoso flash
Keep Board/Catalog feeds mounted outside React Router's control to prevent Virtuoso from remounting when navigating to/from post pages. The feed is hidden via CSS when viewing posts and shown again when returning, eliminating the visible flash/displacement that occurred during scroll restoration. - Add FeedCacheContainer to manage LRU cache of 2 feeds - Modify Board/Catalog to accept cache props and visibility state - Add route utilities for feed/post route detection
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
.visible {
|
||||
}
|
||||
|
||||
.hidden {
|
||||
visibility: hidden;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
pointer-events: none;
|
||||
overflow: hidden;
|
||||
height: 0;
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
import { useEffect } from 'react';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import useFeedCacheStore, { CachedFeed } from '../../stores/use-feed-cache-store';
|
||||
import { getFeedCacheKey, getFeedType, isFeedRoute } from '../../lib/utils/route-utils';
|
||||
import Board from '../../views/board';
|
||||
import Catalog from '../../views/catalog';
|
||||
import styles from './feed-cache-container.module.css';
|
||||
|
||||
interface FeedContextFromKey {
|
||||
viewType: 'all' | 'subs' | 'mod' | 'board';
|
||||
boardIdentifier?: string;
|
||||
timeFilterName?: string;
|
||||
}
|
||||
|
||||
const parseFeedKey = (key: string): FeedContextFromKey => {
|
||||
const segments = key.split('/').filter(Boolean);
|
||||
|
||||
const filteredSegments = segments.filter((s) => s !== 'catalog');
|
||||
if (filteredSegments[0] === 'all') {
|
||||
return {
|
||||
viewType: 'all',
|
||||
timeFilterName: filteredSegments[1],
|
||||
};
|
||||
}
|
||||
if (filteredSegments[0] === 'subs') {
|
||||
return {
|
||||
viewType: 'subs',
|
||||
timeFilterName: filteredSegments[1],
|
||||
};
|
||||
}
|
||||
if (filteredSegments[0] === 'mod') {
|
||||
return {
|
||||
viewType: 'mod',
|
||||
timeFilterName: filteredSegments[1],
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
viewType: 'board',
|
||||
boardIdentifier: filteredSegments[0],
|
||||
timeFilterName: filteredSegments[1],
|
||||
};
|
||||
};
|
||||
|
||||
interface CachedFeedWrapperProps {
|
||||
feed: CachedFeed;
|
||||
isVisible: boolean;
|
||||
}
|
||||
|
||||
const CachedFeedWrapper = ({ feed, isVisible }: CachedFeedWrapperProps) => {
|
||||
const context = parseFeedKey(feed.key);
|
||||
|
||||
return (
|
||||
<div className={isVisible ? styles.visible : styles.hidden}>
|
||||
{feed.type === 'catalog' ? (
|
||||
<Catalog
|
||||
feedCacheKey={feed.key}
|
||||
viewType={context.viewType}
|
||||
boardIdentifier={context.boardIdentifier}
|
||||
timeFilterNameFromCache={context.timeFilterName}
|
||||
isVisible={isVisible}
|
||||
/>
|
||||
) : (
|
||||
<Board
|
||||
feedCacheKey={feed.key}
|
||||
viewType={context.viewType}
|
||||
boardIdentifier={context.boardIdentifier}
|
||||
timeFilterNameFromCache={context.timeFilterName}
|
||||
isVisible={isVisible}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const FeedCacheContainer = () => {
|
||||
const location = useLocation();
|
||||
const { cachedFeeds, accessFeed } = useFeedCacheStore();
|
||||
|
||||
const currentFeedKey = getFeedCacheKey(location.pathname);
|
||||
const isOnFeedRoute = isFeedRoute(location.pathname);
|
||||
const feedType = getFeedType(location.pathname);
|
||||
|
||||
useEffect(() => {
|
||||
if (isOnFeedRoute && currentFeedKey && feedType) {
|
||||
accessFeed(currentFeedKey, feedType);
|
||||
}
|
||||
}, [currentFeedKey, isOnFeedRoute, feedType, accessFeed]);
|
||||
|
||||
return (
|
||||
<>
|
||||
{cachedFeeds.map((feed) => (
|
||||
<CachedFeedWrapper key={feed.key} feed={feed} isVisible={isOnFeedRoute && feed.key === currentFeedKey} />
|
||||
))}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default FeedCacheContainer;
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from './feed-cache-container';
|
||||
Reference in New Issue
Block a user