improve dvm feed loading

This commit is contained in:
hzrd149 2023-12-19 19:11:17 -06:00
parent d1f3e4dc2b
commit c77a457972
3 changed files with 81 additions and 76 deletions

View File

@ -0,0 +1,64 @@
import { ReactNode, memo, useRef } from "react";
import { Kind } from "nostr-tools";
import { Box, Text } from "@chakra-ui/react";
import { ErrorBoundary } from "../../error-boundary";
import ReplyNote from "./reply-note";
import Note from "../../note";
import RepostNote from "./repost-note";
import ArticleNote from "./article-note";
import StreamNote from "./stream-note";
import RelayRecommendation from "./relay-recommendation";
import BadgeAwardCard from "../../../views/badges/components/badge-award-card";
import { useRegisterIntersectionEntity } from "../../../providers/intersection-observer";
import { getEventUID, isReply } from "../../../helpers/nostr/events";
import { STREAM_KIND } from "../../../helpers/nostr/stream";
import { NostrEvent } from "../../../types/nostr-event";
function GenericTimelineNote({
event,
visible,
minHeight,
}: {
event: NostrEvent;
visible: boolean;
minHeight?: number;
}) {
const ref = useRef<HTMLDivElement | null>(null);
useRegisterIntersectionEntity(ref, getEventUID(event));
let content: ReactNode | null = null;
switch (event.kind) {
case Kind.Text:
content = isReply(event) ? <ReplyNote event={event} /> : <Note event={event} showReplyButton />;
break;
case Kind.Repost:
content = <RepostNote event={event} />;
break;
case Kind.Article:
content = <ArticleNote article={event} />;
break;
case STREAM_KIND:
content = <StreamNote event={event} />;
break;
case Kind.RecommendRelay:
content = <RelayRecommendation event={event} />;
break;
case Kind.BadgeAward:
content = <BadgeAwardCard award={event} />;
break;
default:
content = <Text>Unknown event kind: {event.kind}</Text>;
break;
}
return (
<ErrorBoundary>
<Box minHeight={minHeight} ref={ref}>
{visible && content}
</Box>
</ErrorBoundary>
);
}
export default memo(GenericTimelineNote);

View File

@ -1,68 +1,15 @@
import { ReactNode, memo, useCallback, useEffect, useMemo, useRef, useState } from "react";
import { Box, Button, Text } from "@chakra-ui/react";
import { Kind } from "nostr-tools";
import { memo, useCallback, useEffect, useMemo, useState } from "react";
import { Box, Button } from "@chakra-ui/react";
import dayjs from "dayjs";
import { useLocation } from "react-router-dom";
import { useThrottle } from "react-use";
import useSubject from "../../../hooks/use-subject";
import TimelineLoader from "../../../classes/timeline-loader";
import RepostNote from "./repost-note";
import { Note } from "../../note";
import { NostrEvent } from "../../../types/nostr-event";
import { STREAM_KIND } from "../../../helpers/nostr/stream";
import StreamNote from "./stream-note";
import { ErrorBoundary } from "../../error-boundary";
import { getEventUID, isReply } from "../../../helpers/nostr/events";
import ReplyNote from "./reply-note";
import RelayRecommendation from "./relay-recommendation";
import {
ExtendedIntersectionObserverEntry,
useIntersectionObserver,
useRegisterIntersectionEntity,
} from "../../../providers/intersection-observer";
import BadgeAwardCard from "../../../views/badges/components/badge-award-card";
import ArticleNote from "./article-note";
import SuperMap from "../../../classes/super-map";
import { useDebounce, useThrottle } from "react-use";
function RenderEvent({ event, visible, minHeight }: { event: NostrEvent; visible: boolean; minHeight?: number }) {
const ref = useRef<HTMLDivElement | null>(null);
useRegisterIntersectionEntity(ref, getEventUID(event));
let content: ReactNode | null = null;
switch (event.kind) {
case Kind.Text:
content = isReply(event) ? <ReplyNote event={event} /> : <Note event={event} showReplyButton />;
break;
case Kind.Repost:
content = <RepostNote event={event} />;
break;
case Kind.Article:
content = <ArticleNote article={event} />;
break;
case STREAM_KIND:
content = <StreamNote event={event} />;
break;
case Kind.RecommendRelay:
content = <RelayRecommendation event={event} />;
break;
case Kind.BadgeAward:
content = <BadgeAwardCard award={event} />;
break;
default:
content = <Text>Unknown event kind: {event.kind}</Text>;
break;
}
return (
<ErrorBoundary>
<Box minHeight={minHeight} ref={ref}>
{visible && content}
</Box>
</ErrorBoundary>
);
}
const RenderEventMemo = memo(RenderEvent);
import { getEventUID } from "../../../helpers/nostr/events";
import { ExtendedIntersectionObserverEntry, useIntersectionObserver } from "../../../providers/intersection-observer";
import GenericTimelineNote from "./generic-timeline-note";
const NOTE_BUFFER = 5;
const timelineNoteMinHeightCache = new WeakMap<TimelineLoader, Record<string, Record<string, number>>>();
@ -206,7 +153,7 @@ function GenericNoteTimeline({ timeline }: { timeline: TimelineLoader }) {
</Box>
)}
{notes.map((note) => (
<RenderEventMemo
<GenericTimelineNote
key={note.id}
event={note}
visible={note.created_at <= maxDate}

View File

@ -1,26 +1,20 @@
import { useCallback } from "react";
import { ChainedDVMJob, getEventIdsFromJobs } from "../../../helpers/nostr/dvm";
import { useReadRelayUrls } from "../../../hooks/use-client-relays";
import { NostrEvent } from "../../../types/nostr-event";
import FeedStatus from "./feed-status";
import useTimelineLoader from "../../../hooks/use-timeline-loader";
import GenericNoteTimeline from "../../../components/timeline-page/generic-note-timeline";
import { AddressPointer } from "nostr-tools/lib/types/nip19";
import useSingleEvents from "../../../hooks/use-single-events";
import GenericTimelineNote from "../../../components/timeline-page/generic-note-timeline/generic-timeline-note";
function FeedEvents({ chain }: { chain: ChainedDVMJob[] }) {
const eventIds = getEventIdsFromJobs(chain);
const customSort = useCallback(
(a: NostrEvent, b: NostrEvent) => {
return eventIds.indexOf(a.id) - eventIds.indexOf(b.id);
},
[eventIds],
const events = useSingleEvents(eventIds);
return (
<>
{events.map((event) => (
<GenericTimelineNote event={event} visible />
))}
</>
);
const readRelays = useReadRelayUrls();
const timeline = useTimelineLoader(`${chain[0].request.id}-events`, readRelays, { ids: eventIds }, { customSort });
return <GenericNoteTimeline timeline={timeline} />;
}
export default function Feed({ chain, pointer }: { chain: ChainedDVMJob[]; pointer: AddressPointer }) {