feat: defer loading notes
This commit is contained in:
parent
0d9aa0d5ca
commit
dda07d66d5
@ -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>
|
|
||||||
}
|
|
@ -1,6 +1,7 @@
|
|||||||
.note {
|
.note {
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
border-bottom: 1px solid var(--gray);
|
border-bottom: 1px solid var(--gray);
|
||||||
|
min-height: 140px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.note.thread {
|
.note.thread {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import "./Note.css";
|
import "./Note.css";
|
||||||
import { useCallback, useMemo } from "react";
|
import { useCallback, useEffect, useMemo, useState } from "react";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
import { default as NEvent } from "../nostr/Event";
|
import { default as NEvent } from "../nostr/Event";
|
||||||
@ -11,6 +11,7 @@ import NoteTime from "./NoteTime";
|
|||||||
import EventKind from "../nostr/EventKind";
|
import EventKind from "../nostr/EventKind";
|
||||||
import useProfile from "../feed/ProfileFeed";
|
import useProfile from "../feed/ProfileFeed";
|
||||||
import { TaggedRawEvent, u256 } from "../nostr";
|
import { TaggedRawEvent, u256 } from "../nostr";
|
||||||
|
import { useInView } from "react-intersection-observer";
|
||||||
|
|
||||||
export interface NoteProps {
|
export interface NoteProps {
|
||||||
data?: TaggedRawEvent,
|
data?: TaggedRawEvent,
|
||||||
@ -32,6 +33,8 @@ export default function Note(props: NoteProps) {
|
|||||||
const pubKeys = useMemo(() => ev.Thread?.PubKeys || [], [ev]);
|
const pubKeys = useMemo(() => ev.Thread?.PubKeys || [], [ev]);
|
||||||
const users = useProfile(pubKeys);
|
const users = useProfile(pubKeys);
|
||||||
const deletions = useMemo(() => getReactions(related, ev.Id, EventKind.Deletion), [related]);
|
const deletions = useMemo(() => getReactions(related, ev.Id, EventKind.Deletion), [related]);
|
||||||
|
const { ref, inView } = useInView();
|
||||||
|
const [visible, setVisible] = useState(false);
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
showHeader: true,
|
showHeader: true,
|
||||||
@ -46,7 +49,13 @@ export default function Note(props: NoteProps) {
|
|||||||
return (<b className="error">Deleted</b>);
|
return (<b className="error">Deleted</b>);
|
||||||
}
|
}
|
||||||
return <Text content={body} tags={ev.Tags} users={users || new Map()} />;
|
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) {
|
function goToEvent(e: any, id: u256) {
|
||||||
if (!window.location.pathname.startsWith("/e/")) {
|
if (!window.location.pathname.startsWith("/e/")) {
|
||||||
@ -92,8 +101,10 @@ export default function Note(props: NoteProps) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function content() {
|
||||||
|
if (!visible) return null;
|
||||||
return (
|
return (
|
||||||
<div className={`note ${highlight ? "active" : ""} ${isThread ? "thread" : ""}`}>
|
<>
|
||||||
{options.showHeader ?
|
{options.showHeader ?
|
||||||
<div className="header flex">
|
<div className="header flex">
|
||||||
<ProfileImage pubkey={ev.RootPubKey} subHeader={replyTag() ?? undefined} />
|
<ProfileImage pubkey={ev.RootPubKey} subHeader={replyTag() ?? undefined} />
|
||||||
@ -106,6 +117,13 @@ export default function Note(props: NoteProps) {
|
|||||||
{transformBody()}
|
{transformBody()}
|
||||||
</div>
|
</div>
|
||||||
{options.showFooter ? <NoteFooter ev={ev} related={related} /> : null}
|
{options.showFooter ? <NoteFooter ev={ev} related={related} /> : null}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={`note${highlight ? " active" : ""}${isThread ? " thread" : ""}`} ref={ref}>
|
||||||
|
{content()}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,6 @@ import { TwitterTweetEmbed } from "react-twitter-embed";
|
|||||||
import { UrlRegex, FileExtensionRegex, MentionRegex, InvoiceRegex, YoutubeUrlRegex, TweetUrlRegex, HashtagRegex } from "../Const";
|
import { UrlRegex, FileExtensionRegex, MentionRegex, InvoiceRegex, YoutubeUrlRegex, TweetUrlRegex, HashtagRegex } from "../Const";
|
||||||
import { eventLink, hexToBech32 } from "../Util";
|
import { eventLink, hexToBech32 } from "../Util";
|
||||||
import Invoice from "./Invoice";
|
import Invoice from "./Invoice";
|
||||||
import LazyImage from "./LazyImage";
|
|
||||||
import Hashtag from "./Hashtag";
|
import Hashtag from "./Hashtag";
|
||||||
|
|
||||||
import './Text.css'
|
import './Text.css'
|
||||||
@ -28,7 +27,7 @@ function transformHttpLink(a: string) {
|
|||||||
case "png":
|
case "png":
|
||||||
case "bmp":
|
case "bmp":
|
||||||
case "webp": {
|
case "webp": {
|
||||||
return <LazyImage key={url} src={url} />;
|
return <img key={url.toString()} src={url.toString()} />;
|
||||||
}
|
}
|
||||||
case "mp4":
|
case "mp4":
|
||||||
case "mov":
|
case "mov":
|
||||||
|
Loading…
Reference in New Issue
Block a user