More memoization

This commit is contained in:
Lim Chee Aun 2024-02-14 17:17:15 +08:00
parent 3295b1ab96
commit c84ad73d0d

View file

@ -1,3 +1,4 @@
import { memo } from 'preact/compat';
import { useCallback, useEffect, useRef, useState } from 'preact/hooks'; import { useCallback, useEffect, useRef, useState } from 'preact/hooks';
import { useHotkeys } from 'react-hotkeys-hook'; import { useHotkeys } from 'react-hotkeys-hook';
import { InView } from 'react-intersection-observer'; import { InView } from 'react-intersection-observer';
@ -243,9 +244,9 @@ function Timeline({
({ ({
scrollDirection, scrollDirection,
nearReachStart, nearReachStart,
nearReachEnd, // nearReachEnd,
reachStart, reachStart,
reachEnd, // reachEnd,
}) => { }) => {
// setHiddenUI(scrollDirection === 'end' && !nearReachEnd); // setHiddenUI(scrollDirection === 'end' && !nearReachEnd);
if (headerRef.current) { if (headerRef.current) {
@ -516,190 +517,205 @@ function Timeline({
); );
} }
function TimelineItem({ const TimelineItem = memo(
status, ({
instance, status,
useItemID, instance,
// allowFilters, useItemID,
filterContext, // allowFilters,
view, filterContext,
showFollowedTags, view,
showReplyParent, showFollowedTags,
}) { showReplyParent,
const { id: statusID, reblog, items, type, _pinned } = status; }) => {
if (_pinned) useItemID = false; console.debug('RENDER TimelineItem', status.id);
const actualStatusID = reblog?.id || statusID; const { id: statusID, reblog, items, type, _pinned } = status;
const url = instance if (_pinned) useItemID = false;
? `/${instance}/s/${actualStatusID}` const actualStatusID = reblog?.id || statusID;
: `/s/${actualStatusID}`; const url = instance
let title = ''; ? `/${instance}/s/${actualStatusID}`
if (type === 'boosts') { : `/s/${actualStatusID}`;
title = `${items.length} Boosts`; let title = '';
} else if (type === 'pinned') { if (type === 'boosts') {
title = 'Pinned posts'; title = `${items.length} Boosts`;
} } else if (type === 'pinned') {
const isCarousel = type === 'boosts' || type === 'pinned'; title = 'Pinned posts';
if (items) { }
const fItems = filteredItems(items, filterContext); const isCarousel = type === 'boosts' || type === 'pinned';
if (isCarousel) { if (items) {
// Here, we don't hide filtered posts, but we sort them last const fItems = filteredItems(items, filterContext);
fItems.sort((a, b) => { if (isCarousel) {
// if (a._filtered && !b._filtered) { // Here, we don't hide filtered posts, but we sort them last
// return 1; fItems.sort((a, b) => {
// } // if (a._filtered && !b._filtered) {
// if (!a._filtered && b._filtered) { // return 1;
// return -1; // }
// } // if (!a._filtered && b._filtered) {
const aFiltered = isFiltered(a.filtered, filterContext); // return -1;
const bFiltered = isFiltered(b.filtered, filterContext); // }
if (aFiltered && !bFiltered) { const aFiltered = isFiltered(a.filtered, filterContext);
return 1; const bFiltered = isFiltered(b.filtered, filterContext);
} if (aFiltered && !bFiltered) {
if (!aFiltered && bFiltered) { return 1;
return -1; }
} if (!aFiltered && bFiltered) {
return 0; return -1;
}
return 0;
});
return (
<li key={`timeline-${statusID}`} class="timeline-item-carousel">
<StatusCarousel title={title} class={`${type}-carousel`}>
{fItems.map((item) => {
const { id: statusID, reblog, _pinned } = item;
const actualStatusID = reblog?.id || statusID;
const url = instance
? `/${instance}/s/${actualStatusID}`
: `/s/${actualStatusID}`;
if (_pinned) useItemID = false;
return (
<li key={statusID}>
<Link
class="status-carousel-link timeline-item-alt"
to={url}
>
{useItemID ? (
<Status
statusID={statusID}
instance={instance}
size="s"
contentTextWeight
enableCommentHint
// allowFilters={allowFilters}
/>
) : (
<Status
status={item}
instance={instance}
size="s"
contentTextWeight
enableCommentHint
// allowFilters={allowFilters}
/>
)}
</Link>
</li>
);
})}
</StatusCarousel>
</li>
);
}
const manyItems = fItems.length > 3;
return fItems.map((item, i) => {
const { id: statusID, _differentAuthor } = item;
const url = instance ? `/${instance}/s/${statusID}` : `/s/${statusID}`;
const isMiddle = i > 0 && i < fItems.length - 1;
const isSpoiler = item.sensitive && !!item.spoilerText;
const showCompact =
(!_differentAuthor && isSpoiler && i > 0) ||
(manyItems &&
isMiddle &&
(type === 'thread' ||
(type === 'conversation' &&
!_differentAuthor &&
!fItems[i - 1]._differentAuthor &&
!fItems[i + 1]._differentAuthor)));
const isStart = i === 0;
const isEnd = i === fItems.length - 1;
return (
<li
key={`timeline-${statusID}`}
class={`timeline-item-container timeline-item-container-type-${type} timeline-item-container-${
isStart ? 'start' : isEnd ? 'end' : 'middle'
} ${_differentAuthor ? 'timeline-item-diff-author' : ''}`}
>
<Link class="status-link timeline-item" to={url}>
{showCompact ? (
<TimelineStatusCompact status={item} instance={instance} />
) : useItemID ? (
<Status
statusID={statusID}
instance={instance}
enableCommentHint={isEnd}
showFollowedTags={showFollowedTags}
// allowFilters={allowFilters}
/>
) : (
<Status
status={item}
instance={instance}
enableCommentHint={isEnd}
showFollowedTags={showFollowedTags}
// allowFilters={allowFilters}
/>
)}
</Link>
</li>
);
}); });
return ( }
<li key={`timeline-${statusID}`} class="timeline-item-carousel">
<StatusCarousel title={title} class={`${type}-carousel`}> const itemKey = `timeline-${statusID + _pinned}`;
{fItems.map((item) => {
const { id: statusID, reblog, _pinned } = item; if (view === 'media') {
const actualStatusID = reblog?.id || statusID; return useItemID ? (
const url = instance <MediaPost
? `/${instance}/s/${actualStatusID}` class="timeline-item"
: `/s/${actualStatusID}`; parent="li"
if (_pinned) useItemID = false; key={itemKey}
return ( statusID={statusID}
<li key={statusID}> instance={instance}
<Link class="status-carousel-link timeline-item-alt" to={url}> // allowFilters={allowFilters}
{useItemID ? ( />
<Status ) : (
statusID={statusID} <MediaPost
instance={instance} class="timeline-item"
size="s" parent="li"
contentTextWeight key={itemKey}
enableCommentHint status={status}
// allowFilters={allowFilters} instance={instance}
/> // allowFilters={allowFilters}
) : ( />
<Status
status={item}
instance={instance}
size="s"
contentTextWeight
enableCommentHint
// allowFilters={allowFilters}
/>
)}
</Link>
</li>
);
})}
</StatusCarousel>
</li>
); );
} }
const manyItems = fItems.length > 3;
return fItems.map((item, i) => {
const { id: statusID, _differentAuthor } = item;
const url = instance ? `/${instance}/s/${statusID}` : `/s/${statusID}`;
const isMiddle = i > 0 && i < fItems.length - 1;
const isSpoiler = item.sensitive && !!item.spoilerText;
const showCompact =
(!_differentAuthor && isSpoiler && i > 0) ||
(manyItems &&
isMiddle &&
(type === 'thread' ||
(type === 'conversation' &&
!_differentAuthor &&
!fItems[i - 1]._differentAuthor &&
!fItems[i + 1]._differentAuthor)));
const isStart = i === 0;
const isEnd = i === fItems.length - 1;
return (
<li
key={`timeline-${statusID}`}
class={`timeline-item-container timeline-item-container-type-${type} timeline-item-container-${
isStart ? 'start' : isEnd ? 'end' : 'middle'
} ${_differentAuthor ? 'timeline-item-diff-author' : ''}`}
>
<Link class="status-link timeline-item" to={url}>
{showCompact ? (
<TimelineStatusCompact status={item} instance={instance} />
) : useItemID ? (
<Status
statusID={statusID}
instance={instance}
enableCommentHint={isEnd}
showFollowedTags={showFollowedTags}
// allowFilters={allowFilters}
/>
) : (
<Status
status={item}
instance={instance}
enableCommentHint={isEnd}
showFollowedTags={showFollowedTags}
// allowFilters={allowFilters}
/>
)}
</Link>
</li>
);
});
}
const itemKey = `timeline-${statusID + _pinned}`; return (
<li key={itemKey}>
if (view === 'media') { <Link class="status-link timeline-item" to={url}>
return useItemID ? ( {useItemID ? (
<MediaPost <Status
class="timeline-item" statusID={statusID}
parent="li" instance={instance}
key={itemKey} enableCommentHint
statusID={statusID} showFollowedTags={showFollowedTags}
instance={instance} showReplyParent={showReplyParent}
// allowFilters={allowFilters} // allowFilters={allowFilters}
/> />
) : ( ) : (
<MediaPost <Status
class="timeline-item" status={status}
parent="li" instance={instance}
key={itemKey} enableCommentHint
status={status} showFollowedTags={showFollowedTags}
instance={instance} showReplyParent={showReplyParent}
// allowFilters={allowFilters} // allowFilters={allowFilters}
/> />
)}
</Link>
</li>
); );
} },
(oldProps, newProps) => {
return ( const oldID = (oldProps.status?.id || '').toString();
<li key={itemKey}> const newID = (newProps.status?.id || '').toString();
<Link class="status-link timeline-item" to={url}> return (
{useItemID ? ( oldID === newID &&
<Status oldProps.instance === newProps.instance &&
statusID={statusID} oldProps.view === newProps.view
instance={instance} );
enableCommentHint },
showFollowedTags={showFollowedTags} );
showReplyParent={showReplyParent}
// allowFilters={allowFilters}
/>
) : (
<Status
status={status}
instance={instance}
enableCommentHint
showFollowedTags={showFollowedTags}
showReplyParent={showReplyParent}
// allowFilters={allowFilters}
/>
)}
</Link>
</li>
);
}
function StatusCarousel({ title, class: className, children }) { function StatusCarousel({ title, class: className, children }) {
const carouselRef = useRef(); const carouselRef = useRef();