From 46a61865802edd6ca662d04574df262575488121 Mon Sep 17 00:00:00 2001 From: smolgrrr Date: Wed, 20 Sep 2023 01:09:25 +1000 Subject: [PATCH] start threads pages --- client/src/App.tsx | 23 +++++++----- client/src/components/Thread/Thread.tsx | 41 +++++++++++++++++++++ client/src/utils/subscriptions.ts | 47 ++++++++++++++++++++++++- 3 files changed, 102 insertions(+), 9 deletions(-) create mode 100644 client/src/components/Thread/Thread.tsx diff --git a/client/src/App.tsx b/client/src/App.tsx index 9944934..0a7a4e6 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -3,6 +3,8 @@ import './App.css'; import Home from './components/Home'; import Settings from './components/Settings'; import SwipeableViews from 'react-swipeable-views'; +import { BrowserRouter as Router, Route, Routes } from 'react-router-dom'; +import Thread from './components/Thread/Thread'; function App() { const [index, setIndex] = React.useState(1); @@ -13,14 +15,19 @@ function App() { }; return ( - -
- -
-
- -
-
+ + + } /> + } /> + } /> + + + + + } /> + + ); } diff --git a/client/src/components/Thread/Thread.tsx b/client/src/components/Thread/Thread.tsx new file mode 100644 index 0000000..3aa6c47 --- /dev/null +++ b/client/src/components/Thread/Thread.tsx @@ -0,0 +1,41 @@ +import { useParams } from 'react-router-dom'; +import { useState } from "react"; +import { Event } from "nostr-tools" +import { subNote } from '../../utils/subscriptions'; +import { useEffect } from 'react'; +import PostCard from '../PostCard/PostCard'; + +const Thread = () => { + const { id } = useParams(); + const [events, setEvents] = useState([]); // Initialize state + + // Define your callback function for subGlobalFeed + const onEvent = (event: Event, relay: string) => { + setEvents((prevEvents) => [...prevEvents, event]); + console.log(event.id + ' ' + event.kind + ' ' + event.tags); + }; + + useEffect(() => { + // Subscribe to global feed when the component mounts + subNote(id as string, onEvent); + + // Optionally, return a cleanup function to unsubscribe when the component unmounts + return () => { + // Your cleanup code here + }; + }, []); // Empty dependency array means this useEffect runs once when the component mounts + + return ( + <> +
+
+ {events.sort((a, b) => b.created_at - a.created_at).map((event, index) => ( + + ))} +
+
+ + ); +}; + +export default Thread; \ No newline at end of file diff --git a/client/src/utils/subscriptions.ts b/client/src/utils/subscriptions.ts index 49255f0..cf219c4 100644 --- a/client/src/utils/subscriptions.ts +++ b/client/src/utils/subscriptions.ts @@ -82,7 +82,7 @@ export const subGlobalFeed = (onEvent: SubCallback) => { }); }; - /** subscribe to global feed */ +/** subscribe to global feed */ export const simpleSub24hFeed = (onEvent: SubCallback) => { unsubAll(); sub({ @@ -94,4 +94,49 @@ export const simpleSub24hFeed = (onEvent: SubCallback) => { limit: 1, } }); +}; + +/** subscribe to a note id (nip-19) */ +export const subNote = ( + eventId: string, + onEvent: SubCallback, +) => { + unsubAll(); + sub({ + cb: onEvent, + filter: { + ids: [eventId], + kinds: [1], + limit: 1, + }, + unsub: true, + }); + + const replies = new Set(); + + const onReply = (evt: Event, relay: string) => { + replies.add(evt.id) + onEvent(evt, relay); + unsubAll(); + sub({ + cb: onEvent, + filter: { + '#e': Array.from(replies), + kinds: [1], + }, + unsub: true, + }); + }; + + replies.add(eventId); + setTimeout(() => { + sub({ + cb: onReply, + filter: { + '#e': [eventId], + kinds: [1], + }, + unsub: true, // TODO: probably keep this subscription also after onReply/unsubAll + }); + }, 200); }; \ No newline at end of file