mirror of
https://github.com/smolgrrr/TAO.git
synced 2024-09-20 01:11:25 +00:00
clean thread loading
This commit is contained in:
parent
6f7d41edd0
commit
361187c5b7
@ -4,14 +4,14 @@ import { Event } from "nostr-tools";
|
|||||||
import NewNoteCard from "../forms/PostFormCard";
|
import NewNoteCard from "../forms/PostFormCard";
|
||||||
import RepostCard from "../modals/RepostCard";
|
import RepostCard from "../modals/RepostCard";
|
||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
import { useUniqEvents } from "../../hooks/useUniqEvents";
|
import { useFetchEvents } from "../../hooks/useFetchEvents";
|
||||||
|
|
||||||
const DEFAULT_DIFFICULTY = 0;
|
const DEFAULT_DIFFICULTY = 0;
|
||||||
|
|
||||||
const HashtagPage = () => {
|
const HashtagPage = () => {
|
||||||
const { id } = useParams();
|
const { id } = useParams();
|
||||||
const filterDifficulty = localStorage.getItem("filterHashtagDifficulty") || DEFAULT_DIFFICULTY;
|
const filterDifficulty = localStorage.getItem("filterHashtagDifficulty") || DEFAULT_DIFFICULTY;
|
||||||
const { noteEvents, metadataEvents } = useUniqEvents(id as string, false);
|
const { noteEvents, metadataEvents } = useFetchEvents(id as string, false);
|
||||||
|
|
||||||
const postEvents: Event[] = noteEvents
|
const postEvents: Event[] = noteEvents
|
||||||
.filter((event) =>
|
.filter((event) =>
|
||||||
|
@ -3,12 +3,12 @@ import { Event } from "nostr-tools";
|
|||||||
import NewNoteCard from "../forms/PostFormCard";
|
import NewNoteCard from "../forms/PostFormCard";
|
||||||
import RepostCard from "../modals/RepostCard";
|
import RepostCard from "../modals/RepostCard";
|
||||||
import { DEFAULT_DIFFICULTY } from "../../config";
|
import { DEFAULT_DIFFICULTY } from "../../config";
|
||||||
import { useUniqEvents } from "../../hooks/useUniqEvents";
|
|
||||||
import PostCard from "../modals/PostCard";
|
import PostCard from "../modals/PostCard";
|
||||||
|
import { useFetchEvents } from "../../hooks/useFetchEvents";
|
||||||
|
|
||||||
const Home = () => {
|
const Home = () => {
|
||||||
const filterDifficulty = localStorage.getItem("filterDifficulty") || DEFAULT_DIFFICULTY;
|
const filterDifficulty = localStorage.getItem("filterDifficulty") || DEFAULT_DIFFICULTY;
|
||||||
const { noteEvents, metadataEvents } = useUniqEvents();
|
const { noteEvents, metadataEvents } = useFetchEvents();
|
||||||
|
|
||||||
const postEvents: Event[] = noteEvents
|
const postEvents: Event[] = noteEvents
|
||||||
.filter((event) =>
|
.filter((event) =>
|
||||||
|
@ -2,11 +2,11 @@ import { useState, useCallback } from "react";
|
|||||||
import PostCard from "../modals/PostCard";
|
import PostCard from "../modals/PostCard";
|
||||||
import { Event } from "nostr-tools";
|
import { Event } from "nostr-tools";
|
||||||
import RepostCard from "../modals/RepostCard";
|
import RepostCard from "../modals/RepostCard";
|
||||||
import { useUniqEvents } from "../../hooks/useUniqEvents";
|
import { useFetchEvents } from "../../hooks/useFetchEvents";
|
||||||
|
|
||||||
const Notifications = () => {
|
const Notifications = () => {
|
||||||
const [notifsView, setNotifsView] = useState(false);
|
const [notifsView, setNotifsView] = useState(false);
|
||||||
const { noteEvents, metadataEvents } = useUniqEvents(undefined,true);
|
const { noteEvents, metadataEvents } = useFetchEvents(undefined,true);
|
||||||
const storedKeys = JSON.parse(localStorage.getItem('usedKeys') || '[]');
|
const storedKeys = JSON.parse(localStorage.getItem('usedKeys') || '[]');
|
||||||
const storedPubkeys = storedKeys.map((key: any[]) => key[1]);
|
const storedPubkeys = storedKeys.map((key: any[]) => key[1]);
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { Event, nip19 } from "nostr-tools"
|
import { Event, nip19 } from "nostr-tools"
|
||||||
import { subNote, subNotesOnce } from '../../utils/subscriptions';
|
import { subNotesOnce } from '../../utils/subscriptions';
|
||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { uniqBy } from '../../utils/otherUtils';
|
import { uniqBy } from '../../utils/otherUtils';
|
||||||
import { DocumentTextIcon, FolderPlusIcon, DocumentDuplicateIcon, ArrowTopRightOnSquareIcon } from '@heroicons/react/24/outline';
|
import { DocumentTextIcon, FolderPlusIcon, DocumentDuplicateIcon, ArrowTopRightOnSquareIcon } from '@heroicons/react/24/outline';
|
||||||
@ -9,118 +9,56 @@ import Placeholder from '../modals/Placeholder';
|
|||||||
import NewNoteCard from '../forms/PostFormCard';
|
import NewNoteCard from '../forms/PostFormCard';
|
||||||
import RepostNote from '../forms/RepostNote';
|
import RepostNote from '../forms/RepostNote';
|
||||||
import PostCard from '../modals/PostCard';
|
import PostCard from '../modals/PostCard';
|
||||||
|
import { useFetchEvents } from '../../hooks/useFetchEvents';
|
||||||
|
|
||||||
type PostType = "" | "Reply" | "Quote" | undefined;
|
type PostType = "" | "Reply" | "Quote" | undefined;
|
||||||
|
|
||||||
const Thread = () => {
|
const Thread = () => {
|
||||||
const { id } = useParams();
|
const { id } = useParams();
|
||||||
const [events, setEvents] = useState<Event[]>([]); // Initialize state
|
|
||||||
const [OPEvent, setOPEvent] = useState<Event>()
|
|
||||||
const [showForm, setShowForm] = useState(false);
|
const [showForm, setShowForm] = useState(false);
|
||||||
const [showRepost, setShowRepost] = useState(false);
|
const [showRepost, setShowRepost] = useState(false);
|
||||||
const [postType, setPostType] = useState<PostType>("");
|
const [postType, setPostType] = useState<PostType>("");
|
||||||
const [hasRun, setHasRun] = useState(false);
|
const [prevMentions, setPrevMentions] = useState<Event[]>([]);
|
||||||
const [preOPEvents, setPreOPEvents] = useState(['']);
|
|
||||||
// const filterDifficulty = useState(localStorage.getItem("filterDifficulty") || "20");
|
// const filterDifficulty = useState(localStorage.getItem("filterDifficulty") || "20");
|
||||||
// Load cached metadataEvents from localStorage
|
|
||||||
const [cachedMetadataEvents, setCachedMetadataEvents] = useState<Event[]>(
|
|
||||||
JSON.parse(localStorage.getItem("cachedMetadataEvents") || "[]")
|
|
||||||
);
|
|
||||||
|
|
||||||
let decodeResult = nip19.decode(id as string);
|
let decodeResult = nip19.decode(id as string);
|
||||||
let hexID = decodeResult.data as string;
|
let hexID = decodeResult.data as string;
|
||||||
|
const { noteEvents, metadataEvents } = useFetchEvents(undefined,false,hexID);
|
||||||
// Define your callback function for subGlobalFeed
|
|
||||||
const onEvent = (event: Event, relay: string) => {
|
|
||||||
setEvents((prevEvents) => [...prevEvents, event]);
|
|
||||||
|
|
||||||
// If the new event is a metadata event, add it to the cached metadata events
|
|
||||||
if (event.kind === 0) {
|
|
||||||
setCachedMetadataEvents((prevMetadataEvents) => {
|
|
||||||
// Check if the event already exists in the cached metadata events
|
|
||||||
const existingEvent = prevMetadataEvents.find((e) => e.id === event.id || e.pubkey === event.pubkey)
|
|
||||||
if (!existingEvent) {
|
|
||||||
// If the event doesn't exist, add it to the cached metadata events
|
|
||||||
return [...prevMetadataEvents, event];
|
|
||||||
} else if (existingEvent && existingEvent.created_at < event.created_at) {
|
|
||||||
// Remove any existing metadata event with the same pubkey and id
|
|
||||||
const updatedMetadataEvents = prevMetadataEvents.filter(
|
|
||||||
(e) => e.id !== existingEvent.id
|
|
||||||
);
|
|
||||||
// Add the new metadata event
|
|
||||||
return [...updatedMetadataEvents, event];
|
|
||||||
}
|
|
||||||
// If the event already exists, return the previous cached metadata events
|
|
||||||
return prevMetadataEvents;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setHasRun(false)
|
|
||||||
if (decodeResult.type === 'note') {
|
|
||||||
// Call your subNote function or do whatever you need to do with id_to_hex
|
|
||||||
subNote(hexID, onEvent);
|
|
||||||
}
|
|
||||||
}, [id]); // Empty dependency array means this useEffect runs once when the component mounts
|
|
||||||
|
|
||||||
// Save the cached metadataEvents to localStorage
|
|
||||||
useEffect(() => {
|
|
||||||
localStorage.setItem("cachedMetadataEvents", JSON.stringify(cachedMetadataEvents));
|
|
||||||
}, [cachedMetadataEvents]);
|
|
||||||
|
|
||||||
const uniqEvents = events.length > 0 ? uniqBy(events, "id") : [];
|
|
||||||
const metadataEvents = [...cachedMetadataEvents, ...uniqEvents.filter(event => event.kind === 0)];
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!hasRun && events.length > 0) {
|
|
||||||
let OPEvent = uniqEvents.find(event => event.id === hexID);
|
|
||||||
setOPEvent(OPEvent);
|
|
||||||
|
|
||||||
console.log(OPEvent)
|
|
||||||
if (OPEvent && OPEvent.id !== hexID) {
|
|
||||||
OPEvent = events.find(e => e.id === hexID) as Event;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (OPEvent) {
|
|
||||||
setOPEvent(OPEvent);
|
|
||||||
let OPNoteEvents = OPEvent.tags.filter(tag => tag[0] === 'e').map(tag => tag[1]);
|
|
||||||
setHasRun(true);
|
|
||||||
setPreOPEvents(OPNoteEvents)
|
|
||||||
subNotesOnce(OPNoteEvents, onEvent)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, [uniqEvents, hasRun]);
|
|
||||||
|
|
||||||
const countReplies = (event: Event) => {
|
const countReplies = (event: Event) => {
|
||||||
return uniqEvents.filter(e => e.tags.some(tag => tag[0] === 'e' && tag[1] === event.id));
|
return noteEvents.filter(e => e.tags.some(tag => tag[0] === 'e' && tag[1] === event.id));
|
||||||
}
|
}
|
||||||
|
|
||||||
const repliedList = (event: Event): Event[] => {
|
const repliedList = (event: Event): Event[] => {
|
||||||
return uniqEvents.filter(e => event.tags.some(tag => tag[0] === 'p' && tag[1] === e.pubkey));
|
return noteEvents.filter(e => event.tags.some(tag => tag[0] === 'p' && tag[1] === e.pubkey));
|
||||||
}
|
}
|
||||||
|
|
||||||
const earlierEvents = uniqEvents
|
|
||||||
.filter(event =>
|
|
||||||
event.kind === 1 &&
|
|
||||||
preOPEvents.includes(event.id)
|
|
||||||
).sort((a, b) => (b.created_at as any) - (a.created_at as any));
|
|
||||||
|
|
||||||
const displayedEvents = [...uniqEvents].slice(1)
|
// Define your callback function for subGlobalFeed
|
||||||
.filter(event =>
|
const onEvent = (event: Event, relay: string) => {
|
||||||
event.kind === 1 &&
|
setPrevMentions((prevEvents) => [...prevEvents, event]);
|
||||||
!earlierEvents.map(e => e.id).includes(event.id) &&
|
};
|
||||||
(OPEvent ? OPEvent.id !== event.id : true)
|
|
||||||
).sort((a, b) => a.created_at - b.created_at);
|
const OPEvent = noteEvents.find(event => event.id === hexID);
|
||||||
|
useEffect(() => {
|
||||||
|
if (OPEvent && prevMentions.length == 0) {
|
||||||
|
const OPMentionIDs = OPEvent.tags.filter(tag => tag[0] === 'e').map(tag => tag[1]);
|
||||||
|
subNotesOnce(OPMentionIDs, onEvent);
|
||||||
|
}
|
||||||
|
}, [OPEvent]);
|
||||||
|
|
||||||
|
if (OPEvent) {
|
||||||
|
const uniqEvents = uniqBy(prevMentions, "id");
|
||||||
|
const earlierEvents = uniqEvents
|
||||||
|
.filter(e =>
|
||||||
|
e.created_at < OPEvent.created_at
|
||||||
|
)
|
||||||
|
|
||||||
|
const replyEvents = [...noteEvents].slice(1)
|
||||||
|
.filter(event =>
|
||||||
|
!earlierEvents.map(e => e.id).includes(event.id) &&
|
||||||
|
(OPEvent ? OPEvent.id !== event.id : true)
|
||||||
|
).sort((a, b) => a.created_at - b.created_at);
|
||||||
|
|
||||||
if (uniqEvents.length === 0) {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Placeholder />
|
|
||||||
<div className="col-span-full h-0.5 bg-neutral-900"/> {/* This is the white line separator */}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<main className="bg-black text-white min-h-screen">
|
<main className="bg-black text-white min-h-screen">
|
||||||
@ -130,7 +68,7 @@ const Thread = () => {
|
|||||||
.sort((a, b) => a.created_at - b.created_at).map((event, index) => (
|
.sort((a, b) => a.created_at - b.created_at).map((event, index) => (
|
||||||
<PostCard event={event} metadata={metadataEvents.find((e) => e.pubkey === event.pubkey && e.kind === 0) || null} replies={countReplies(event)} />
|
<PostCard event={event} metadata={metadataEvents.find((e) => e.pubkey === event.pubkey && e.kind === 0) || null} replies={countReplies(event)} />
|
||||||
))}
|
))}
|
||||||
{OPEvent && <PostCard event={OPEvent} metadata={metadataEvents.find((e) => e.pubkey === OPEvent.pubkey && e.kind === 0) || null} replies={countReplies(OPEvent)} type={'OP'}/>}
|
<PostCard event={OPEvent} metadata={metadataEvents.find((e) => e.pubkey === OPEvent.pubkey && e.kind === 0) || null} replies={countReplies(OPEvent)} type={'OP'}/>
|
||||||
</div>
|
</div>
|
||||||
<div className="col-span-full flex justify-center space-x-16 pb-4">
|
<div className="col-span-full flex justify-center space-x-16 pb-4">
|
||||||
<DocumentTextIcon
|
<DocumentTextIcon
|
||||||
@ -177,12 +115,12 @@ const Thread = () => {
|
|||||||
</div>}
|
</div>}
|
||||||
<div className="col-span-full h-0.5 bg-neutral-900"/> {/* This is the white line separator */}
|
<div className="col-span-full h-0.5 bg-neutral-900"/> {/* This is the white line separator */}
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 p-4">
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 p-4">
|
||||||
{displayedEvents.map((event, index) => (
|
{replyEvents.map((event, index) => (
|
||||||
<PostCard
|
<PostCard
|
||||||
key={index}
|
key={index}
|
||||||
event={event}
|
event={event}
|
||||||
metadata={metadataEvents.find((e) => e.pubkey === event.pubkey && e.kind === 0) || null}
|
metadata={metadataEvents.find((e) => e.pubkey === event.pubkey && e.kind === 0) || null}
|
||||||
replies={displayedEvents.filter((e) => e.tags.some((tag) => tag[0] === "e" && tag[1] === event.id))}
|
replies={replyEvents.filter((e) => e.tags.some((tag) => tag[0] === "e" && tag[1] === event.id))}
|
||||||
repliedTo={repliedList(event)}
|
repliedTo={repliedList(event)}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
@ -190,6 +128,13 @@ const Thread = () => {
|
|||||||
</main>
|
</main>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Placeholder />
|
||||||
|
<div className="col-span-full h-0.5 bg-neutral-900"/> {/* This is the white line separator */}
|
||||||
|
</>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Thread;
|
export default Thread;
|
@ -1,10 +1,9 @@
|
|||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect } from "react";
|
||||||
import { subGlobalFeed, subHashtagFeed, subNotifications } from "../utils/subscriptions";
|
import { subGlobalFeed, subHashtagFeed, subNote, subNotifications, subNotesOnce} from "../utils/subscriptions";
|
||||||
import { uniqBy } from "../utils/otherUtils";
|
import { uniqBy } from "../utils/otherUtils";
|
||||||
import { Event } from "nostr-tools";
|
import { Event } from "nostr-tools";
|
||||||
import { } from "../utils/subscriptions";
|
|
||||||
|
|
||||||
export const useUniqEvents = (hashtag?: string, notifications?: boolean) => {
|
export const useFetchEvents = (hashtag?: string, notifications?: boolean, OP_eventID?: string) => {
|
||||||
const [events, setEvents] = useState<Event[]>([]);
|
const [events, setEvents] = useState<Event[]>([]);
|
||||||
const age = Number(localStorage.getItem("age")) || 24;
|
const age = Number(localStorage.getItem("age")) || 24;
|
||||||
|
|
||||||
@ -45,6 +44,8 @@ export const useUniqEvents = (hashtag?: string, notifications?: boolean) => {
|
|||||||
if (hashtag) {
|
if (hashtag) {
|
||||||
// Code from the second function
|
// Code from the second function
|
||||||
unsubscribe = subHashtagFeed(hashtag, onEvent, age);
|
unsubscribe = subHashtagFeed(hashtag, onEvent, age);
|
||||||
|
} else if (OP_eventID) {
|
||||||
|
unsubscribe = subNote(OP_eventID, onEvent);
|
||||||
} else if (notifications) {
|
} else if (notifications) {
|
||||||
// Code from the third function
|
// Code from the third function
|
||||||
let storedKeys = JSON.parse(localStorage.getItem("usedKeys") || "[]");
|
let storedKeys = JSON.parse(localStorage.getItem("usedKeys") || "[]");
|
@ -236,7 +236,6 @@ export const subNotifications = (
|
|||||||
onEvent: SubCallback,
|
onEvent: SubCallback,
|
||||||
) => {
|
) => {
|
||||||
unsubAll();
|
unsubAll();
|
||||||
|
|
||||||
sub({
|
sub({
|
||||||
cb: (evt, relay) => {
|
cb: (evt, relay) => {
|
||||||
onEvent(evt, relay);
|
onEvent(evt, relay);
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"forceConsistentCasingInFileNames": false,
|
"forceConsistentCasingInFileNames": true,
|
||||||
"noEmit": true,
|
"noEmit": true,
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"module": "esnext",
|
"module": "esnext",
|
||||||
|
Loading…
Reference in New Issue
Block a user