mirror of
https://github.com/bitsocialnet/5chan.git
synced 2026-08-03 07:41:04 +02:00
perf(board): reduce desktop reverse-scroll jank on /all
Apply the asymmetric viewport buffer that already fixed mobile to desktop
multiboard feeds, and trim per-post mount cost so remounts during scroll-up
are cheaper:
- Desktop multiboard buffer goes from {600,600} to {1200,2400} (top-heavy),
matching the mobile pattern from 99c0bbfac so items stay mounted longer
when scrolling back up
- Cache feed post height estimate by CID in pretext-height-estimates so
remounts skip the Pretext text-measurement work
- Memoize CommentMedia and switch its expanded-media-store reads to atomic
selectors so it stops rerendering on unrelated store changes
- Memoize useCommentMediaInfo return so its reference is stable for memo
comparators downstream
- Stop useFetchGifFirstFrame from forcing an extra render on every post
mount by bailing out of equivalent setState calls
- Extract PendingModerationActions out of PostInfo so the two
usePublishCommentModeration calls only run on the post page when
mod-approval is actually pending, not on every feed item
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useMemo, useState, useEffect } from 'react';
|
||||
import { useLocation, useParams } from 'react-router-dom';
|
||||
import { getCommentMediaInfo, fetchWebpageThumbnailIfNeeded, CommentMediaInfo } from '../lib/utils/media-utils';
|
||||
import { isPendingPostView, isPostPageView } from '../lib/utils/view-utils';
|
||||
@@ -65,16 +65,15 @@ export const useCommentMediaInfo = (link: string, thumbnailUrl: string, linkWidt
|
||||
};
|
||||
}, [link, thumbnailUrl, linkWidth, linkHeight, isInPostPageView, isInPendingPostView]);
|
||||
|
||||
const mediaInfo = getCommentMediaInfo(link, thumbnailUrl, linkWidth, linkHeight);
|
||||
|
||||
// Return media info with cached thumbnail dimensions if available
|
||||
if (thumbnailDimensions && mediaInfo) {
|
||||
return {
|
||||
...mediaInfo,
|
||||
thumbnailWidth: thumbnailDimensions.width,
|
||||
thumbnailHeight: thumbnailDimensions.height,
|
||||
};
|
||||
}
|
||||
|
||||
return mediaInfo;
|
||||
return useMemo(() => {
|
||||
const mediaInfo = getCommentMediaInfo(link, thumbnailUrl, linkWidth, linkHeight);
|
||||
if (thumbnailDimensions && mediaInfo) {
|
||||
return {
|
||||
...mediaInfo,
|
||||
thumbnailWidth: thumbnailDimensions.width,
|
||||
thumbnailHeight: thumbnailDimensions.height,
|
||||
};
|
||||
}
|
||||
return mediaInfo;
|
||||
}, [link, thumbnailUrl, linkWidth, linkHeight, thumbnailDimensions]);
|
||||
};
|
||||
|
||||
@@ -11,6 +11,10 @@ interface GifFirstFrameState {
|
||||
status: GifFirstFrameStatus;
|
||||
}
|
||||
|
||||
const IDLE_STATE: GifFirstFrameState = { frameUrl: null, status: 'idle' };
|
||||
const LOADING_STATE: GifFirstFrameState = { frameUrl: null, status: 'loading' };
|
||||
const FAILED_STATE: GifFirstFrameState = { frameUrl: null, status: 'failed' };
|
||||
|
||||
const getCachedGifFrame = async (url: string): Promise<string | null> => {
|
||||
return await gifFrameDb.getItem(url);
|
||||
};
|
||||
@@ -79,20 +83,20 @@ const parseGif = async (buf: ArrayBuffer): Promise<Blob> => {
|
||||
};
|
||||
|
||||
const useFetchGifFirstFrame = (url: string | undefined) => {
|
||||
const [gifFirstFrame, setGifFirstFrame] = useState<GifFirstFrameState>({ frameUrl: null, status: 'idle' });
|
||||
const [gifFirstFrame, setGifFirstFrame] = useState<GifFirstFrameState>(IDLE_STATE);
|
||||
|
||||
useEffect(() => {
|
||||
if (!url) {
|
||||
setGifFirstFrame({ frameUrl: null, status: 'idle' });
|
||||
setGifFirstFrame((prev) => (prev.status === 'idle' ? prev : IDLE_STATE));
|
||||
return;
|
||||
}
|
||||
|
||||
let isActive = true;
|
||||
setGifFirstFrame({ frameUrl: null, status: 'loading' });
|
||||
setGifFirstFrame((prev) => (prev.status === 'loading' ? prev : LOADING_STATE));
|
||||
|
||||
const fetchFrame = async () => {
|
||||
if (failedUrls.has(url)) {
|
||||
if (isActive) setGifFirstFrame({ frameUrl: null, status: 'failed' });
|
||||
if (isActive) setGifFirstFrame((prev) => (prev.status === 'failed' ? prev : FAILED_STATE));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -119,7 +123,7 @@ const useFetchGifFirstFrame = (url: string | undefined) => {
|
||||
} catch (error) {
|
||||
failedUrls.add(url);
|
||||
console.error('Failed to load GIF frame:', error);
|
||||
if (isActive) setGifFirstFrame({ frameUrl: null, status: 'failed' });
|
||||
if (isActive) setGifFirstFrame((prev) => (prev.status === 'failed' ? prev : FAILED_STATE));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user