More memoization
This commit is contained in:
parent
3295b1ab96
commit
c84ad73d0d
1 changed files with 197 additions and 181 deletions
|
@ -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();
|
||||||
|
|
Loading…
Add table
Reference in a new issue