From 76f1295a2325ef5a2fd33758c44cae64b8e13c1c Mon Sep 17 00:00:00 2001 From: KoalaSat Date: Sat, 29 Oct 2022 19:56:49 +0200 Subject: [PATCH] Smooth event navigation and profile load --- frontend/Components/ConfigPage/index.tsx | 1 + frontend/Components/ContactsPage/index.tsx | 1 + .../Components/LandingPage/Logger/index.tsx | 2 +- frontend/Components/NotePage/index.tsx | 53 ++++++++++++++----- frontend/Components/ProfilePage/index.tsx | 5 +- frontend/Components/SendPage/index.tsx | 15 ++++-- frontend/Contexts/RelayPoolContext.tsx | 4 +- .../Functions/RelayFunctions/Events/index.ts | 21 +++++--- 8 files changed, 75 insertions(+), 27 deletions(-) diff --git a/frontend/Components/ConfigPage/index.tsx b/frontend/Components/ConfigPage/index.tsx index e744541..fa31dc9 100644 --- a/frontend/Components/ConfigPage/index.tsx +++ b/frontend/Components/ConfigPage/index.tsx @@ -25,6 +25,7 @@ export const ConfigPage: React.FC = () => { }, []); const onPressBack: () => void = () => { + relayPool?.unsubscribeAll(); goBack(); }; diff --git a/frontend/Components/ContactsPage/index.tsx b/frontend/Components/ContactsPage/index.tsx index 452ab9e..ce1bcc6 100644 --- a/frontend/Components/ContactsPage/index.tsx +++ b/frontend/Components/ContactsPage/index.tsx @@ -46,6 +46,7 @@ export const ContactsPage: React.FC = () => { console.log('RELAYPOOL EVENT =======>', relay.url, event); if (database && event?.id && event.kind === EventKind.petNames) { insertUserContact(event, database).finally(() => setLastEventId(event?.id ?? '')); + relayPool?.removeOn('event', 'contacts'); } }); }, []); diff --git a/frontend/Components/LandingPage/Logger/index.tsx b/frontend/Components/LandingPage/Logger/index.tsx index 0a1386c..396ad03 100644 --- a/frontend/Components/LandingPage/Logger/index.tsx +++ b/frontend/Components/LandingPage/Logger/index.tsx @@ -56,7 +56,7 @@ export const Logger: React.FC = () => { const initEvents: () => void = () => { relayPool?.on('event', 'landing', (_relay: Relay, _subId?: string, event?: Event) => { - console.log('LandingPage EVENT =======>', event); + console.log('LANDING EVENT =======>', event); if (event && database) { if (event.kind === EventKind.petNames) { loadPets(event); diff --git a/frontend/Components/NotePage/index.tsx b/frontend/Components/NotePage/index.tsx index 8836b4a..544977d 100644 --- a/frontend/Components/NotePage/index.tsx +++ b/frontend/Components/NotePage/index.tsx @@ -24,23 +24,23 @@ export const NotePage: React.FC = () => { const { page, goBack, goToPage, database } = useContext(AppContext); const { lastEventId, relayPool } = useContext(RelayPoolContext); const [note, setNote] = useState(); - const [replies, setReplies] = useState([]); + const [replies, setReplies] = useState(); const theme = useTheme(); const { t } = useTranslation('common'); const breadcrump = page.split('%'); const eventId = breadcrump[breadcrump.length - 1].split('#')[1]; - useEffect(() => { + const reload: () => void = () => { + setNote(undefined); + setReplies(undefined); relayPool?.unsubscribeAll(); relayPool?.subscribe('main-channel', { - kinds: [EventKind.textNote, EventKind.recommendServer], + kinds: [EventKind.textNote], ids: [eventId], }); - relayPool?.subscribe('main-channel', { - kinds: [EventKind.textNote, EventKind.recommendServer], - '#e': [eventId], - }); - }, []); + }; + + useEffect(reload, []); useEffect(() => { if (database) { @@ -48,13 +48,19 @@ export const NotePage: React.FC = () => { if (events.length > 0) { const event = events[0]; setNote(event); + if (!replies) { + relayPool?.subscribe('main-channel', { + kinds: [EventKind.textNote], + '#e': [eventId], + }); + } getNotes(database, { filters: { reply_event_id: eventId } }).then((notes) => { - const rootReplies = getDirectReplies(notes, event); + const rootReplies = getDirectReplies(event, notes); if (rootReplies.length > 0) { setReplies(rootReplies as Note[]); const message: RelayFilters = { kinds: [EventKind.meta], - authors: rootReplies.map((note) => note.pubkey), + authors: [...rootReplies.map((note) => note.pubkey), event.pubkey], }; relayPool?.subscribe('main-channel', message); } else { @@ -67,9 +73,20 @@ export const NotePage: React.FC = () => { }, [lastEventId, page]); const onPressBack: () => void = () => { + relayPool?.unsubscribeAll(); goBack(); }; + const onPressGoParent: () => void = () => { + if (note) { + const replyId = getReplyEventId(note); + if (replyId) { + goToPage(`note#${replyId}`); + reload(); + } + } + }; + const renderBackAction = (): JSX.Element => { return ( { ); }; + const renderNoteActions = (): JSX.Element => { + return note && getReplyEventId(note) ? ( + } + onPress={onPressGoParent} + /> + ) : ( + <> + ); + }; + const onPressNote: (note: Note) => void = (note) => { if (note.kind !== EventKind.recommendServer) { const replyEventId = getReplyEventId(note); @@ -87,7 +115,7 @@ export const NotePage: React.FC = () => { } else if (note.id) { goToPage(`note#${note.id}`); } - setReplies([]); + reload(); } }; @@ -127,10 +155,11 @@ export const NotePage: React.FC = () => { alignment='center' title={`${eventId.slice(0, 12)}...${eventId.slice(-12)}`} accessoryLeft={renderBackAction} + accessoryRight={renderNoteActions} /> {note ? ( - ItemCard(item?.item)} /> + ItemCard(item?.item)} /> ) : ( )} diff --git a/frontend/Components/ProfilePage/index.tsx b/frontend/Components/ProfilePage/index.tsx index 32db692..9b32c41 100644 --- a/frontend/Components/ProfilePage/index.tsx +++ b/frontend/Components/ProfilePage/index.tsx @@ -48,7 +48,6 @@ export const ProfilePage: React.FC = () => { useEffect(() => { setNotes(undefined); setUser(undefined); - relayPool?.unsubscribeAll(); relayPool?.subscribe('main-channel', { kinds: [EventKind.meta, EventKind.petNames], authors: [userId], @@ -121,7 +120,7 @@ export const ProfilePage: React.FC = () => { if (publicKey === userId) { return ( } + icon={} onPress={() => goToPage('config')} /> ); @@ -149,6 +148,8 @@ export const ProfilePage: React.FC = () => { }; const onPressBack: () => void = () => { + relayPool?.removeOn('event', 'profile'); + relayPool?.unsubscribeAll(); goBack(); }; diff --git a/frontend/Components/SendPage/index.tsx b/frontend/Components/SendPage/index.tsx index f8f91b4..16102e4 100644 --- a/frontend/Components/SendPage/index.tsx +++ b/frontend/Components/SendPage/index.tsx @@ -11,7 +11,7 @@ import React, { useContext, useEffect, useState } from 'react'; import { StyleSheet } from 'react-native'; import { AppContext } from '../../Contexts/AppContext'; import Icon from 'react-native-vector-icons/FontAwesome5'; -import { Event } from '../../lib/nostr/Events'; +import { Event, EventKind } from '../../lib/nostr/Events'; import { useTranslation } from 'react-i18next'; import { RelayPoolContext } from '../../Contexts/RelayPoolContext'; import moment from 'moment'; @@ -75,12 +75,19 @@ export const SendPage: React.FC = () => { const event: Event = { content, created_at: moment().unix(), - kind: 1, + kind: EventKind.textNote, pubkey: publicKey, tags, }; - relayPool?.sendEvent(event); - setNoteId(note.id); + relayPool?.sendEvent(event).then((sentNote) => { + if (sentNote?.id) { + relayPool?.subscribe('main-channel', { + kinds: [EventKind.textNote], + ids: [sentNote.id], + }); + setNoteId(sentNote.id); + } + }); setSending(true); }); } diff --git a/frontend/Contexts/RelayPoolContext.tsx b/frontend/Contexts/RelayPoolContext.tsx index 2c4e485..2c1d62c 100644 --- a/frontend/Contexts/RelayPoolContext.tsx +++ b/frontend/Contexts/RelayPoolContext.tsx @@ -74,7 +74,9 @@ export const RelayPoolContextProvider = ({ (relay: Relay, _subId?: string, event?: Event) => { console.log('RELAYPOOL EVENT =======>', relay.url, event); if (database && event?.id && event.kind !== EventKind.petNames) { - storeEvent(event, database).finally(() => setLastEventId(event.id)); + storeEvent(event, database) + .then(() => setLastEventId(event.id)) + .catch(() => setLastEventId(event.id)); } }, ); diff --git a/frontend/Functions/RelayFunctions/Events/index.ts b/frontend/Functions/RelayFunctions/Events/index.ts index 28229bd..f8b6b77 100644 --- a/frontend/Functions/RelayFunctions/Events/index.ts +++ b/frontend/Functions/RelayFunctions/Events/index.ts @@ -26,14 +26,21 @@ export const getReplyEventId: (event: Event) => string | null = (event) => { return mainTag ? mainTag[1] : null; }; -export const getDirectReplies: (replies: Event[], event: Event) => Event[] = (replies, event) => { - const expectedTags: number = getETags(event).length + 1; - const filter = replies.filter((event) => { - const eventETags = getETags(event); - return eventETags.length === expectedTags; - }); +export const getDirectReplies: (event: Event, replies: Event[]) => Event[] = (event, replies) => { + return replies.filter((item) => isDirectReply(event, item)); +}; - return filter; +export const isDirectReply: (mainEvent: Event, reply: Event) => boolean = (mainEvent, reply) => { + const taggedMainEventsIds: string[] = getTaggedEventIds(mainEvent); + const taggedReplyEventsIds: string[] = getTaggedEventIds(reply); + const difference = taggedReplyEventsIds.filter((item) => !taggedMainEventsIds.includes(item)); + + return difference.length === 1 && difference[0] === mainEvent.id; +}; + +export const getTaggedEventIds: (event: Event) => string[] = (event) => { + const mainEventETags: string[][] = getETags(event); + return mainEventETags.map((item) => item[1] ?? ''); }; export const getETags: (event: Event) => string[][] = (event) => {