clean up subs

This commit is contained in:
smolgrrr 2024-08-27 22:55:25 +10:00
parent 7ed89267d4
commit 61c289792d
10 changed files with 124 additions and 112 deletions

View File

@ -16,13 +16,11 @@
"react-linkify": "^1.0.0-alpha", "react-linkify": "^1.0.0-alpha",
"react-router-dom": "^6.15.0", "react-router-dom": "^6.15.0",
"react-scripts": "5.0.1", "react-scripts": "5.0.1",
"web-vitals": "^2.1.4",
"workbox-background-sync": "^6.6.0", "workbox-background-sync": "^6.6.0",
"workbox-broadcast-update": "^6.6.0", "workbox-broadcast-update": "^6.6.0",
"workbox-cacheable-response": "^6.6.0", "workbox-cacheable-response": "^6.6.0",
"workbox-core": "^6.6.0", "workbox-core": "^6.6.0",
"workbox-expiration": "^6.6.0", "workbox-expiration": "^6.6.0",
"workbox-google-analytics": "^6.6.0",
"workbox-navigation-preload": "^6.6.0", "workbox-navigation-preload": "^6.6.0",
"workbox-precaching": "^6.6.0", "workbox-precaching": "^6.6.0",
"workbox-range-requests": "^6.6.0", "workbox-range-requests": "^6.6.0",

View File

@ -7,6 +7,7 @@ import { useSubmitForm } from "./handleSubmit";
import "../../styles/Form.css"; import "../../styles/Form.css";
import EmotePicker from "../modals/EmotePicker/EmotePicker"; import EmotePicker from "../modals/EmotePicker/EmotePicker";
import { DEFAULT_DIFFICULTY } from "../../config"; import { DEFAULT_DIFFICULTY } from "../../config";
import PostCard from "../modals/PostCard";
interface FormProps { interface FormProps {
refEvent?: NostrEvent; refEvent?: NostrEvent;
@ -24,6 +25,7 @@ const timeUnits = [
{ unit: 'd', value: 60 * 60 * 24 }, { unit: 'd', value: 60 * 60 * 24 },
{ unit: 'h', value: 60 * 60 }, { unit: 'h', value: 60 * 60 },
{ unit: 'm', value: 60 }, { unit: 'm', value: 60 },
{ unit: 's', value: 1 },
]; ];
const timeToGoEst = (difficulty: string, hashrate: number): string => { const timeToGoEst = (difficulty: string, hashrate: number): string => {
@ -43,7 +45,7 @@ const timeToGoEst = (difficulty: string, hashrate: number): string => {
} }
} }
return result.trim() || '0m'; // Return '0m' if result is empty, indicating less than a minute return result.trim() || 'now'; // Return 'now' if result is empty
}; };
const NewNoteCard = ({ const NewNoteCard = ({
@ -88,7 +90,6 @@ const NewNoteCard = ({
addEventTags(); addEventTags();
break; break;
case 'Quote': case 'Quote':
setComment(comment + '\nnostr:' + nip19.noteEncode(refEvent.id));
unsigned.tags.push(['q', refEvent.id]); unsigned.tags.push(['q', refEvent.id]);
break; break;
default: default:
@ -118,10 +119,16 @@ const NewNoteCard = ({
})); }));
}, [comment]); }, [comment]);
const { handleSubmit: originalHandleSubmit, doingWorkProp, hashrate, bestPow } = useSubmitForm(unsigned, difficulty); const { handleSubmit: originalHandleSubmit, doingWorkProp, hashrate, bestPow, signedPoWEvent } = useSubmitForm(unsigned, difficulty);
const handleSubmit = async (event: React.FormEvent) => { const handleSubmit = async (event: React.FormEvent) => {
await originalHandleSubmit(event); await originalHandleSubmit(event);
// Check if tagType is 'Quote' and update comment
if (tagType === 'Quote' && refEvent) {
setComment(prevComment => prevComment + '\nnostr:' + nip19.noteEncode(refEvent.id));
}
setComment(""); setComment("");
setUnsigned(prevUnsigned => ({ setUnsigned(prevUnsigned => ({
...prevUnsigned, ...prevUnsigned,
@ -161,9 +168,13 @@ const NewNoteCard = ({
<textarea <textarea
name="com" name="com"
wrap="soft" wrap="soft"
className="shadow-lg w-full px-4 py-3 border-blue-500 bg-black text-white" className="shadow-lg w-full px-4 py-3 border-blue-500 bg-black text-white h-auto"
value={comment} value={comment}
onChange={(e) => setComment(e.target.value)} onChange={(e) => {
setComment(e.target.value);
e.target.style.height = 'auto'; // Reset height
e.target.style.height = `${e.target.scrollHeight}px`; // Set height to scrollHeight
}}
rows={comment.split('\n').length || 1} rows={comment.split('\n').length || 1}
/> />
<div className="h-14 flex items-center justify-between"> <div className="h-14 flex items-center justify-between">
@ -215,6 +226,14 @@ const NewNoteCard = ({
</div>) </div>)
</div> </div>
) : null} ) : null}
{signedPoWEvent && (
<PostCard
key={signedPoWEvent.id}
event={signedPoWEvent}
metadata={null}
replies={[]}
/>
)}
</div> </div>
<div id="postFormError" className="text-red-500" /> <div id="postFormError" className="text-red-500" />
</form> </form>

View File

@ -37,7 +37,7 @@ const ThreadPostModal = ({ OPEvent }: { OPEvent: Event }) => {
setShowRepost(false) setShowRepost(false)
}} }}
/> />
<a href={`nostr:${OPEvent.id}`} target="_blank" rel="noopener noreferrer"> <a href={`https://njump.me/${OPEvent.id}`} target="_blank" rel="noopener noreferrer">
<ArrowTopRightOnSquareIcon <ArrowTopRightOnSquareIcon
className="h-5 w-5 text-gray-200 cursor-pointer" className="h-5 w-5 text-gray-200 cursor-pointer"
/> />

View File

@ -1,5 +1,5 @@
import { useState, useEffect } from "react"; import { useState, useEffect } from "react";
import { generateSecretKey, getPublicKey, finalizeEvent, UnsignedEvent } from "nostr-tools"; import { generateSecretKey, getPublicKey, finalizeEvent, UnsignedEvent, Event } from "nostr-tools";
import { publish } from "../../utils/relays"; import { publish } from "../../utils/relays";
const useWorkers = (numCores: number, unsigned: UnsignedEvent, difficulty: string, deps: any[]) => { const useWorkers = (numCores: number, unsigned: UnsignedEvent, difficulty: string, deps: any[]) => {
@ -43,7 +43,8 @@ export const useSubmitForm = (unsigned: UnsignedEvent, difficulty: string) => {
const [sk, setSk] = useState(generateSecretKey()); const [sk, setSk] = useState(generateSecretKey());
const unsignedWithPubkey = { ...unsigned, pubkey: getPublicKey(sk) }; const unsignedWithPubkey = { ...unsigned, pubkey: getPublicKey(sk) };
const powServer = useState(localStorage.getItem('powserver') || ''); const powServer = useState(localStorage.getItem('powserver') || '');
const [unsignedPoWEvent, setUnsignedPoWEvent] = useState<UnsignedEvent>() const [unsignedPoWEvent, setUnsignedPoWEvent] = useState<UnsignedEvent>();
const [signedPoWEvent, setSignedPoWEvent] = useState<Event>();
let storedKeys = JSON.parse(localStorage.getItem('usedKeys') || '[]'); let storedKeys = JSON.parse(localStorage.getItem('usedKeys') || '[]');
// Initialize the worker outside of any effects // Initialize the worker outside of any effects
@ -56,6 +57,7 @@ export const useSubmitForm = (unsigned: UnsignedEvent, difficulty: string) => {
setDoingWorkProp(false); setDoingWorkProp(false);
const signedEvent = finalizeEvent(unsignedPoWEvent, sk); const signedEvent = finalizeEvent(unsignedPoWEvent, sk);
publish(signedEvent); publish(signedEvent);
setSignedPoWEvent(signedEvent);
setSk(generateSecretKey()) setSk(generateSecretKey())
} }
}, [unsignedPoWEvent]); }, [unsignedPoWEvent]);
@ -63,7 +65,6 @@ export const useSubmitForm = (unsigned: UnsignedEvent, difficulty: string) => {
const handleSubmit = (event: React.FormEvent) => { const handleSubmit = (event: React.FormEvent) => {
event.preventDefault(); event.preventDefault();
setDoingWorkProp(true); setDoingWorkProp(true);
console.log(powServer[0])
if (powServer[0]) { if (powServer[0]) {
const inEventFormat = { ...unsignedWithPubkey, sig: "" }; const inEventFormat = { ...unsignedWithPubkey, sig: "" };
const powRequest = { const powRequest = {
@ -104,5 +105,5 @@ export const useSubmitForm = (unsigned: UnsignedEvent, difficulty: string) => {
} }
}, [messageFromWorker]); }, [messageFromWorker]);
return { handleSubmit, doingWorkProp, hashrate, bestPow }; return { handleSubmit, doingWorkProp, hashrate, bestPow, signedPoWEvent};
}; };

View File

@ -47,7 +47,7 @@ const ContentPreview = ({ key, eventdata }: { key: string; eventdata: Event }) =
const match = comment.match(/\bnostr:([a-z0-9]+)/i); const match = comment.match(/\bnostr:([a-z0-9]+)/i);
const nostrQuoteID = match && match[1]; const nostrQuoteID = match && match[1];
if (nostrQuoteID && nostrQuoteID.length > 0) { if (nostrQuoteID && nostrQuoteID.length > 0 && quoteEvents.length !== 0) {
let id_to_hex = String(nip19.decode(nostrQuoteID as string).data); let id_to_hex = String(nip19.decode(nostrQuoteID as string).data);
subNoteOnce(id_to_hex, onEvent); subNoteOnce(id_to_hex, onEvent);
setFinalComment(finalComment.replace("nostr:" + nostrQuoteID, "").trim()); setFinalComment(finalComment.replace("nostr:" + nostrQuoteID, "").trim());

View File

@ -80,7 +80,7 @@ const PostCard = ({
return ( return (
<div key={index}> <div key={index}>
{replyMetadata ? ( {replyMetadata ? (
<img className={`h-5 w-5 rounded-full`} src={getMetadata(replyMetadata)?.picture} /> <img className={`h-5 w-5 rounded-full`} alt="icon" src={getMetadata(replyMetadata)?.picture} />
) : ( ) : (
<div className={`h-4 w-4 ${getIconFromHash(parsedEvent.pubkey)} rounded-full`} /> <div className={`h-4 w-4 ${getIconFromHash(parsedEvent.pubkey)} rounded-full`} />
)} )}

View File

@ -65,6 +65,7 @@ const Notifications = () => {
<span>Your Recent Posts</span> <span>Your Recent Posts</span>
{sortedEvents.map((event) => ( {sortedEvents.map((event) => (
<PostCard <PostCard
key={event.id}
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={countReplies(event)} replies={countReplies(event)}
@ -75,6 +76,7 @@ const Notifications = () => {
<span>Mentions</span> <span>Mentions</span>
{sortedMentions.map((event) => ( {sortedMentions.map((event) => (
<PostCard <PostCard
key={event.id}
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={countReplies(event)} replies={countReplies(event)}

View File

@ -60,9 +60,9 @@ const Thread = () => {
{earlierEvents {earlierEvents
.filter(event => event.kind === 1) .filter(event => event.kind === 1)
.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={uniqEvents.filter((e: Event) => e.tags.some((tag) => tag[0] === "e" && tag[1] === event.id))} /> <PostCard key={event.id} event={event} metadata={metadataEvents.find((e) => e.pubkey === event.pubkey && e.kind === 0) || null} replies={uniqEvents.filter((e: Event) => e.tags.some((tag) => tag[0] === "e" && tag[1] === event.id))} />
))} ))}
<PostCard event={OPEvent} metadata={metadataEvents.find((e) => e.pubkey === OPEvent.pubkey && e.kind === 0) || null} replies={replyEvents} type={'OP'}/> <PostCard key={OPEvent.id} event={OPEvent} metadata={metadataEvents.find((e) => e.pubkey === OPEvent.pubkey && e.kind === 0) || null} replies={replyEvents} type={'OP'}/>
</div> </div>
<ThreadPostModal OPEvent={OPEvent} /> <ThreadPostModal OPEvent={OPEvent} />
<div className="col-span-full h-0.5 bg-neutral-900 mb-2"/> {/* This is the white line separator */} <div className="col-span-full h-0.5 bg-neutral-900 mb-2"/> {/* This is the white line separator */}

View File

@ -57,7 +57,7 @@ export const useFetchEvents = (hashtag?: string, notifications?: boolean, OP_eve
} }
return unsubscribe; return unsubscribe;
}, [hashtag]); }, []);
const uniqEvents = uniqBy(events, "id"); const uniqEvents = uniqBy(events, "id");

View File

@ -31,52 +31,40 @@ export const subGlobalFeed = (onEvent: SubCallback, age: number) => {
setTimeout(() => { setTimeout(() => {
// get profile info // get profile info
sub({ if (pubkeys.size > 0) {
cb: onEvent, sub({
filter: { cb: onEvent,
authors: Array.from(pubkeys), filter: {
kinds: [0], authors: Array.from(pubkeys),
limit: pubkeys.size, kinds: [0],
}, limit: pubkeys.size,
unsub: true, },
}); unsub: true,
pubkeys.clear(); });
pubkeys.clear();
}
sub({ if (notes.size > 0) {
cb: onEvent, sub({
filter: { cb: onEvent,
'#e': Array.from(notes), filter: {
kinds: [1], '#e': Array.from(notes),
}, kinds: [1],
unsub: true, },
}); unsub: true,
});
notes.clear(); notes.clear();
}
}, 2000); }, 2000);
// subscribe to future notes, reactions and profile updates // subscribe to future notes, reactions and profile updates
sub({ sub({
cb: (evt, relay) => { cb: (evt, relay) => {
onEvent(evt, relay); onEvent(evt, relay);
if (
evt.kind !== 1
|| pubkeys.has(evt.pubkey)
) {
return;
}
subOnce({ // get profile data
relay,
cb: onEvent,
filter: {
authors: [evt.pubkey],
kinds: [0],
limit: 1,
}
});
}, },
filter: { filter: {
...(prefix && { ids: ['0'.repeat(prefix)] }), ...(prefix && { ids: ['0'.repeat(prefix)] }),
kinds: [1], kinds: [1,6],
since: now, since: now,
}, },
}); });
@ -122,16 +110,18 @@ export const subNote = (
setTimeout(() => { setTimeout(() => {
// get profile info // get profile info
sub({ if (pubkeys.size > 0) {
cb: onEvent, sub({
filter: { cb: onEvent,
authors: Array.from(pubkeys), filter: {
kinds: [0], authors: Array.from(pubkeys),
limit: pubkeys.size, kinds: [0],
}, limit: pubkeys.size,
unsub: true, },
}); unsub: true,
pubkeys.clear(); });
pubkeys.clear();
}
}, 2000); }, 2000);
replies.add(eventId); replies.add(eventId);
@ -166,16 +156,18 @@ export const subNoteOnce = (
setTimeout(() => { setTimeout(() => {
// get profile info // get profile info
sub({ if (pubkeys.size > 0) {
cb: onEvent, sub({
filter: { cb: onEvent,
authors: Array.from(pubkeys), filter: {
kinds: [0], authors: Array.from(pubkeys),
limit: pubkeys.size, kinds: [0],
}, limit: pubkeys.size,
unsub: true, },
}); unsub: true,
pubkeys.clear(); });
pubkeys.clear();
}
}, 2000); }, 2000);
}; };
@ -200,16 +192,18 @@ export const subNotesOnce = (
setTimeout(() => { setTimeout(() => {
// get profile info // get profile info
sub({ if (pubkeys.size > 0) {
cb: onEvent, sub({
filter: { cb: onEvent,
authors: Array.from(pubkeys), filter: {
kinds: [0], authors: Array.from(pubkeys),
limit: pubkeys.size, kinds: [0],
}, limit: pubkeys.size,
unsub: true, },
}); unsub: true,
pubkeys.clear(); });
pubkeys.clear();
}
}, 2000); }, 2000);
}; };
@ -299,8 +293,8 @@ export const subHashtagFeed = (
}, },
filter: { filter: {
"#t": [hashtag], "#t": [hashtag],
kinds: [1, 6], kinds: [1],
since: Math.floor((Date.now() * 0.001) - (age * 60 * 60)), since: Math.floor((Date.now() * 0.001) - (3 * 60 * 60)),
limit: 20, limit: 20,
}, },
unsub: true unsub: true
@ -325,38 +319,36 @@ export const subHashtagFeed = (
setTimeout(() => { setTimeout(() => {
// get profile info // get profile info
sub({ if (pubkeys.size > 0) {
cb: onEvent, sub({
filter: { cb: onEvent,
authors: Array.from(pubkeys), filter: {
kinds: [0], authors: Array.from(pubkeys),
limit: pubkeys.size, kinds: [0],
}, limit: pubkeys.size,
unsub: true, },
}); unsub: true,
pubkeys.clear(); });
notes.clear(); pubkeys.clear();
}
if (notes.size > 0) {
sub({
cb: onEvent,
filter: {
'#e': Array.from(notes),
kinds: [1],
},
unsub: true,
});
notes.clear();
}
}, 2000); }, 2000);
// subscribe to future notes, reactions and profile updates // subscribe to future notes, reactions and profile updates
sub({ sub({
cb: (evt, relay) => { cb: (evt, relay) => {
onEvent(evt, relay); onEvent(evt, relay);
if (
evt.kind !== 1
|| pubkeys.has(evt.pubkey)
) {
return;
}
subOnce({ // get profile data
relay,
cb: onEvent,
filter: {
authors: [evt.pubkey],
kinds: [0],
limit: 1,
}
});
}, },
filter: { filter: {
"#t": [hashtag], "#t": [hashtag],