feat: defer loading notes

This commit is contained in:
Kieran 2023-01-17 14:00:59 +00:00
parent 0d9aa0d5ca
commit dda07d66d5
Signed by: Kieran
GPG Key ID: DE71CEB3925BE941
4 changed files with 35 additions and 35 deletions

View File

@ -1,18 +0,0 @@
import { useEffect, useState } from 'react';
import { useInView } from 'react-intersection-observer';
export default function LazyImage(props: any) {
const { ref, inView, entry } = useInView();
const [shown, setShown] = useState(false);
useEffect(() => {
setShown(s => {
if (!s && inView) {
return true;
}
return s;
})
}, [inView]);
return shown ? <img {...props} /> : <div ref={ref}></div>
}

View File

@ -1,6 +1,7 @@
.note {
margin-bottom: 10px;
border-bottom: 1px solid var(--gray);
min-height: 140px;
}
.note.thread {

View File

@ -1,5 +1,5 @@
import "./Note.css";
import { useCallback, useMemo } from "react";
import { useCallback, useEffect, useMemo, useState } from "react";
import { useNavigate } from "react-router-dom";
import { default as NEvent } from "../nostr/Event";
@ -11,6 +11,7 @@ import NoteTime from "./NoteTime";
import EventKind from "../nostr/EventKind";
import useProfile from "../feed/ProfileFeed";
import { TaggedRawEvent, u256 } from "../nostr";
import { useInView } from "react-intersection-observer";
export interface NoteProps {
data?: TaggedRawEvent,
@ -32,6 +33,8 @@ export default function Note(props: NoteProps) {
const pubKeys = useMemo(() => ev.Thread?.PubKeys || [], [ev]);
const users = useProfile(pubKeys);
const deletions = useMemo(() => getReactions(related, ev.Id, EventKind.Deletion), [related]);
const { ref, inView } = useInView();
const [visible, setVisible] = useState(false);
const options = {
showHeader: true,
@ -46,7 +49,13 @@ export default function Note(props: NoteProps) {
return (<b className="error">Deleted</b>);
}
return <Text content={body} tags={ev.Tags} users={users || new Map()} />;
}, [props]);
}, [ev]);
useEffect(() => {
if (inView && !visible) {
setVisible(true);
}
}, [inView]);
function goToEvent(e: any, id: u256) {
if (!window.location.pathname.startsWith("/e/")) {
@ -92,20 +101,29 @@ export default function Note(props: NoteProps) {
);
}
function content() {
if (!visible) return null;
return (
<>
{options.showHeader ?
<div className="header flex">
<ProfileImage pubkey={ev.RootPubKey} subHeader={replyTag() ?? undefined} />
{options.showTime ?
<div className="info">
<NoteTime from={ev.CreatedAt * 1000} />
</div> : null}
</div> : null}
<div className="body" onClick={(e) => goToEvent(e, ev.Id)}>
{transformBody()}
</div>
{options.showFooter ? <NoteFooter ev={ev} related={related} /> : null}
</>
)
}
return (
<div className={`note ${highlight ? "active" : ""} ${isThread ? "thread" : ""}`}>
{options.showHeader ?
<div className="header flex">
<ProfileImage pubkey={ev.RootPubKey} subHeader={replyTag() ?? undefined} />
{options.showTime ?
<div className="info">
<NoteTime from={ev.CreatedAt * 1000} />
</div> : null}
</div> : null}
<div className="body" onClick={(e) => goToEvent(e, ev.Id)}>
{transformBody()}
</div>
{options.showFooter ? <NoteFooter ev={ev} related={related} /> : null}
<div className={`note${highlight ? " active" : ""}${isThread ? " thread" : ""}`} ref={ref}>
{content()}
</div>
)
}

View File

@ -5,7 +5,6 @@ import { TwitterTweetEmbed } from "react-twitter-embed";
import { UrlRegex, FileExtensionRegex, MentionRegex, InvoiceRegex, YoutubeUrlRegex, TweetUrlRegex, HashtagRegex } from "../Const";
import { eventLink, hexToBech32 } from "../Util";
import Invoice from "./Invoice";
import LazyImage from "./LazyImage";
import Hashtag from "./Hashtag";
import './Text.css'
@ -28,7 +27,7 @@ function transformHttpLink(a: string) {
case "png":
case "bmp":
case "webp": {
return <LazyImage key={url} src={url} />;
return <img key={url.toString()} src={url.toString()} />;
}
case "mp4":
case "mov":