diff --git a/client/src/components/Notifications.tsx b/client/src/components/Notifications.tsx index 7fdc1c5..05519d8 100644 --- a/client/src/components/Notifications.tsx +++ b/client/src/components/Notifications.tsx @@ -32,21 +32,38 @@ const useUniqEvents = () => { const Notifications = () => { const [sortByTime, setSortByTime] = useState(localStorage.getItem('sortBy') !== 'false'); const [setAnon, setSetAnon] = useState(localStorage.getItem('anonMode') !== 'false'); + const [notifsView, setNotifsView] = useState(false); const { noteEvents, metadataEvents } = useUniqEvents(); + const storedKeys = JSON.parse(localStorage.getItem('usedKeys') || '[]'); + const storedPubkeys = storedKeys.map((key: any[]) => key[1]); const postEvents = noteEvents .filter((event) => event.kind !== 0 && - (event.kind !== 1) + storedPubkeys.includes(event.pubkey) ) const sortedEvents = [...postEvents] - .sort((a, b) => - sortByTime ? b.created_at - a.created_at : verifyPow(b) - verifyPow(a) - ) - .filter( - !setAnon ? (e) => !metadataEvents.some((metadataEvent) => metadataEvent.pubkey === e.pubkey) : () => true - ); + .sort((a, b) => + sortByTime ? b.created_at - a.created_at : verifyPow(b) - verifyPow(a) + ) + .filter( + !setAnon ? (e) => !metadataEvents.some((metadataEvent) => metadataEvent.pubkey === e.pubkey) : () => true + ); + + const mentions = noteEvents + .filter((event) => + event.kind !== 0 && + event.tags.some((tag) => tag[0] === "p" && storedPubkeys.includes(tag[1])) + ) + + const sortedMentions = [...mentions] + .sort((a, b) => + sortByTime ? b.created_at - a.created_at : verifyPow(b) - verifyPow(a) + ) + .filter( + !setAnon ? (e) => !metadataEvents.some((metadataEvent) => metadataEvent.pubkey === e.pubkey) : () => true + ); const toggleSort = useCallback(() => { setSortByTime(prev => { @@ -64,6 +81,10 @@ const Notifications = () => { }); }, []); + const toggleNotifs = useCallback(() => { + setNotifsView(prev => !prev); + }, []); + const countReplies = (event: Event) => { return noteEvents.filter((e) => e.tags.some((tag) => tag[0] === "e" && tag[1] === event.id)).length; }; @@ -72,19 +93,55 @@ const Notifications = () => { return (
-
- {sortedEvents.map((event) => ( - event.kind === 1 ? - e.pubkey === event.pubkey && e.kind === 0) || null} - replyCount={countReplies(event)} +
+ +
+
+
+ Your Recent Posts + {sortedEvents.map((event) => ( + event.kind === 1 ? + e.pubkey === event.pubkey && e.kind === 0) || null} + replyCount={countReplies(event)} + /> + : + + ))} +
+
+ Mentions + {sortedMentions.map((event) => ( + event.kind === 1 ? + e.pubkey === event.pubkey && e.kind === 0) || null} + replyCount={countReplies(event)} + /> + : + + ))} +
); diff --git a/client/src/utils/subscriptions.ts b/client/src/utils/subscriptions.ts index 437098b..12bbcc7 100644 --- a/client/src/utils/subscriptions.ts +++ b/client/src/utils/subscriptions.ts @@ -247,99 +247,51 @@ export const subNotesOnce = ( // }, 2000); // }; -/** quick subscribe to a note id (nip-19) */ +const hasEventTag = (tag: string[]) => tag[0] === 'e'; +const isReply = ([tag, , , marker]: string[]) => tag === 'e' && marker !== 'mention'; + +export const getReplyTo = (evt: Event): string | null => { + const eventTags = evt.tags.filter(isReply); + const withReplyMarker = eventTags.filter(([, , , marker]) => marker === 'reply'); + if (withReplyMarker.length === 1) { + return withReplyMarker[0][1]; + } + const withRootMarker = eventTags.filter(([, , , marker]) => marker === 'root'); + if (withReplyMarker.length === 0 && withRootMarker.length === 1) { + return withRootMarker[0][1]; + } + // fallback to deprecated positional 'e' tags (nip-10) + const lastTag = eventTags.at(-1); + return lastTag ? lastTag[1] : null; +}; + export const subNotifications = ( pubkeys: string[], onEvent: SubCallback, ) => { - const replyPubkeys = new Set(); + unsubAll(); + sub({ - cb: onEvent, + cb: (evt, relay) => { + onEvent(evt, relay); + }, filter: { - authors: Array.from(pubkeys), + authors: pubkeys, + kinds: [1, 7], + limit: 25, + }, + unsub: true, + }); + + sub({ + cb: (evt, relay) => { + onEvent(evt, relay); + }, + filter: { + '#p': pubkeys, kinds: [1], limit: 50, }, unsub: true, }); - - setTimeout(() => { - // get profile info - sub({ - cb: onEvent, - filter: { - authors: Array.from(replyPubkeys), - kinds: [0], - limit: replyPubkeys.size, - }, - unsub: true, - }); - replyPubkeys.clear(); - }, 2000); -}; - -// const hasEventTag = (tag: string[]) => tag[0] === 'e'; -// const isReply = ([tag, , , marker]: string[]) => tag === 'e' && marker !== 'mention'; - -// export const getReplyTo = (evt: Event): string | null => { -// const eventTags = evt.tags.filter(isReply); -// const withReplyMarker = eventTags.filter(([, , , marker]) => marker === 'reply'); -// if (withReplyMarker.length === 1) { -// return withReplyMarker[0][1]; -// } -// const withRootMarker = eventTags.filter(([, , , marker]) => marker === 'root'); -// if (withReplyMarker.length === 0 && withRootMarker.length === 1) { -// return withRootMarker[0][1]; -// } -// // fallback to deprecated positional 'e' tags (nip-10) -// const lastTag = eventTags.at(-1); -// return lastTag ? lastTag[1] : null; -// }; - -// export const subNotifications = ( -// pubkeys: string[], -// onEvent: SubCallback, -// ) => { -// const authorsPrefixes = pubkeys.map(pubkey => pubkey.slice(0, 32)); -// console.info(`subscribe to homefeed ${authorsPrefixes}`); -// unsubAll(); - -// const repliesTo = new Set(); -// sub({ -// cb: (evt, relay) => { -// if ( -// evt.tags.some(hasEventTag) -// ) { -// const note = getReplyTo(evt); // get all reply to events instead? -// if (note && !repliesTo.has(note)) { -// repliesTo.add(note); -// subOnce({ -// cb: onEvent, -// filter: { -// ids: [note], -// kinds: [1], -// limit: 1, -// }, -// relay, -// }); -// } -// } -// onEvent(evt, relay); -// }, -// filter: { -// authors: authorsPrefixes, -// kinds: [1], -// limit: 20, -// }, -// }); -// // get metadata -// sub({ -// cb: onEvent, -// filter: { -// authors: pubkeys, -// kinds: [0], -// limit: pubkeys.length, -// }, -// unsub: true, -// }); -// }; +};