mirror of
https://github.com/hzrd149/nostrudel.git
synced 2025-09-20 13:01:07 +02:00
improve dvm feed loading
This commit is contained in:
@@ -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);
|
@@ -1,68 +1,15 @@
|
|||||||
import { ReactNode, memo, useCallback, useEffect, useMemo, useRef, useState } from "react";
|
import { memo, useCallback, useEffect, useMemo, useState } from "react";
|
||||||
import { Box, Button, Text } from "@chakra-ui/react";
|
import { Box, Button } from "@chakra-ui/react";
|
||||||
import { Kind } from "nostr-tools";
|
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import { useLocation } from "react-router-dom";
|
import { useLocation } from "react-router-dom";
|
||||||
|
import { useThrottle } from "react-use";
|
||||||
|
|
||||||
import useSubject from "../../../hooks/use-subject";
|
import useSubject from "../../../hooks/use-subject";
|
||||||
import TimelineLoader from "../../../classes/timeline-loader";
|
import TimelineLoader from "../../../classes/timeline-loader";
|
||||||
import RepostNote from "./repost-note";
|
|
||||||
import { Note } from "../../note";
|
|
||||||
import { NostrEvent } from "../../../types/nostr-event";
|
import { NostrEvent } from "../../../types/nostr-event";
|
||||||
import { STREAM_KIND } from "../../../helpers/nostr/stream";
|
import { getEventUID } from "../../../helpers/nostr/events";
|
||||||
import StreamNote from "./stream-note";
|
import { ExtendedIntersectionObserverEntry, useIntersectionObserver } from "../../../providers/intersection-observer";
|
||||||
import { ErrorBoundary } from "../../error-boundary";
|
import GenericTimelineNote from "./generic-timeline-note";
|
||||||
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);
|
|
||||||
|
|
||||||
const NOTE_BUFFER = 5;
|
const NOTE_BUFFER = 5;
|
||||||
const timelineNoteMinHeightCache = new WeakMap<TimelineLoader, Record<string, Record<string, number>>>();
|
const timelineNoteMinHeightCache = new WeakMap<TimelineLoader, Record<string, Record<string, number>>>();
|
||||||
@@ -206,7 +153,7 @@ function GenericNoteTimeline({ timeline }: { timeline: TimelineLoader }) {
|
|||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
{notes.map((note) => (
|
{notes.map((note) => (
|
||||||
<RenderEventMemo
|
<GenericTimelineNote
|
||||||
key={note.id}
|
key={note.id}
|
||||||
event={note}
|
event={note}
|
||||||
visible={note.created_at <= maxDate}
|
visible={note.created_at <= maxDate}
|
||||||
|
@@ -1,26 +1,20 @@
|
|||||||
import { useCallback } from "react";
|
|
||||||
|
|
||||||
import { ChainedDVMJob, getEventIdsFromJobs } from "../../../helpers/nostr/dvm";
|
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 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 { 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[] }) {
|
function FeedEvents({ chain }: { chain: ChainedDVMJob[] }) {
|
||||||
const eventIds = getEventIdsFromJobs(chain);
|
const eventIds = getEventIdsFromJobs(chain);
|
||||||
const customSort = useCallback(
|
const events = useSingleEvents(eventIds);
|
||||||
(a: NostrEvent, b: NostrEvent) => {
|
|
||||||
return eventIds.indexOf(a.id) - eventIds.indexOf(b.id);
|
return (
|
||||||
},
|
<>
|
||||||
[eventIds],
|
{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 }) {
|
export default function Feed({ chain, pointer }: { chain: ChainedDVMJob[]; pointer: AddressPointer }) {
|
||||||
|
Reference in New Issue
Block a user