From 368c48510eda312bba11cf96efae2930d199e2c2 Mon Sep 17 00:00:00 2001 From: KoalaSat Date: Tue, 28 Nov 2023 12:21:47 +0100 Subject: [PATCH] Offline mode --- .github/workflows/release.yml | 1 - .../com/nostros/modules/RelayPoolModule.java | 9 ++ frontend/Components/GroupHeaderIcon/index.tsx | 4 +- frontend/Components/MenuItems/index.tsx | 54 ++++++++- frontend/Components/NoteCard/index.tsx | 3 +- frontend/Contexts/AppContext.tsx | 22 +++- frontend/Contexts/RelayPoolContext.tsx | 19 +++- frontend/Locales/de.json | 4 +- frontend/Locales/en.json | 4 +- frontend/Locales/es.json | 4 +- frontend/Locales/fr.json | 4 +- frontend/Locales/ru.json | 4 +- frontend/Locales/zhCn.json | 4 +- frontend/Pages/ContactsPage/index.tsx | 4 +- frontend/Pages/ConversationPage/index.tsx | 4 +- .../Pages/ExternalIdentitiesPage/index.tsx | 4 +- frontend/Pages/GroupPage/index.tsx | 4 +- .../HomePage/ConversationsFeed/index.tsx | 4 +- frontend/Pages/HomePage/GroupsFeed/index.tsx | 4 +- .../HomePage/HomeFeed/BookmarksFeed/index.tsx | 40 +++---- .../HomePage/HomeFeed/GlobalFeed/index.tsx | 47 ++++---- .../Pages/HomePage/HomeFeed/MyFeed/index.tsx | 28 ++--- .../HomePage/HomeFeed/ZapsFeed/index.tsx | 32 +++--- frontend/Pages/HomePage/HomeFeed/index.tsx | 106 +++++------------- .../HomePage/NotificationsFeed/index.tsx | 19 ++-- frontend/Pages/NoteActionsPage/index.tsx | 4 +- frontend/Pages/NotePage/index.tsx | 4 +- frontend/Pages/ProfileActionsPage/index.tsx | 4 +- frontend/Pages/ProfileConfigPage/index.tsx | 4 +- .../Pages/ProfilePage/BookmarksFeed/index.tsx | 4 +- .../Pages/ProfilePage/NotesFeed/index.tsx | 4 +- .../Pages/ProfilePage/RepliesFeed/index.tsx | 4 +- frontend/Pages/ProfilePage/ZapsFeed/index.tsx | 4 +- frontend/Pages/ProfilePage/index.tsx | 4 +- frontend/Pages/RelaysPage/index.tsx | 4 +- frontend/Pages/SearchPage/index.tsx | 4 +- frontend/Pages/WalletPage/index.tsx | 4 +- frontend/Pages/ZapPage/index.tsx | 4 +- frontend/lib/Native/WebsocketModule/index.ts | 1 + frontend/lib/nostr/RelayPool/intex.ts | 35 +++++- 40 files changed, 295 insertions(+), 225 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 93921ee..8e4c632 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -30,7 +30,6 @@ jobs: https://github.com/KoalaSat/nostros/releases/${{ github.ref_name }} - **What's Changed** # Upload APK artifact asset - name: 'Download universal APK Artifact' uses: actions/download-artifact@v3 diff --git a/android/app/src/main/java/com/nostros/modules/RelayPoolModule.java b/android/app/src/main/java/com/nostros/modules/RelayPoolModule.java index 4a9156d..aa4f3eb 100644 --- a/android/app/src/main/java/com/nostros/modules/RelayPoolModule.java +++ b/android/app/src/main/java/com/nostros/modules/RelayPoolModule.java @@ -116,6 +116,15 @@ public class RelayPoolModule extends ReactContextBaseJavaModule { callback.invoke(); } + @ReactMethod + public void disconnect(Callback callback) { + relays = database.getRelays(context, createdEvents); + for (Relay relay : relays) { + relay.disconnect(); + } + callback.invoke(); + } + @ReactMethod public void sendAll(String message, boolean isGlobalFeed) throws IOException { for (Relay relay : relays) { diff --git a/frontend/Components/GroupHeaderIcon/index.tsx b/frontend/Components/GroupHeaderIcon/index.tsx index 8033ec5..e5a2fab 100644 --- a/frontend/Components/GroupHeaderIcon/index.tsx +++ b/frontend/Components/GroupHeaderIcon/index.tsx @@ -35,7 +35,7 @@ interface GroupHeaderIconProps { export const GroupHeaderIcon: React.FC = ({ groupId }) => { const { t } = useTranslation('common') - const { database } = useContext(AppContext) + const { database, online } = useContext(AppContext) const { publicKey } = useContext(UserContext) const { sendEvent, lastEventId } = useContext(RelayPoolContext) const theme = useTheme() @@ -62,7 +62,7 @@ export const GroupHeaderIcon: React.FC = ({ groupId }) => setNewGroupPicture(result.picture) }) } - }, [lastEventId]) + }, [lastEventId, online]) const pastePicture: () => void = () => { Clipboard.getString().then((value) => { diff --git a/frontend/Components/MenuItems/index.tsx b/frontend/Components/MenuItems/index.tsx index 99c9748..899befa 100644 --- a/frontend/Components/MenuItems/index.tsx +++ b/frontend/Components/MenuItems/index.tsx @@ -10,6 +10,7 @@ import { TouchableRipple, useTheme, } from 'react-native-paper' +import SInfo from 'react-native-sensitive-info' import Logo from '../Logo' import { useTranslation } from 'react-i18next' import { RelayPoolContext } from '../../Contexts/RelayPoolContext' @@ -19,11 +20,11 @@ import { navigate } from '../../lib/Navigation' import { usernamePubKey } from '../../Functions/RelayFunctions/Users' import ProfileData from '../ProfileData' import { WalletContext } from '../../Contexts/WalletContext' -import { AppContext } from '../../Contexts/AppContext' +import { AppContext, type Config } from '../../Contexts/AppContext' export const MenuItems: React.FC = () => { const [drawerItemIndex, setDrawerItemIndex] = React.useState(-1) - const { getSatoshiSymbol } = React.useContext(AppContext) + const { getSatoshiSymbol, online } = React.useContext(AppContext) const { relays } = React.useContext(RelayPoolContext) const { balance, type } = React.useContext(WalletContext) const { @@ -40,13 +41,19 @@ export const MenuItems: React.FC = () => { } = React.useContext(UserContext) const { t } = useTranslation('common') const theme = useTheme() + const { switchLine } = React.useContext(RelayPoolContext) const [activerelays, setActiveRelays] = React.useState(0) + const [loadingConnection, setLoadingConnection] = React.useState(false) React.useEffect(() => { setActiveRelays(relays.filter((relay) => relay.active).length) }, [relays, balance]) + React.useEffect(() => { + setLoadingConnection(false) + }, [online]) + const onPressLogout: () => void = () => { logout() } @@ -72,6 +79,10 @@ export const MenuItems: React.FC = () => { } } + React.useEffect(() => { + setLoadingConnection(false) + }, [online]) + return ( <> { onPress={() => onPressItem('relays', 0)} onTouchEnd={() => setDrawerItemIndex(-1)} right={() => - activerelays < 1 ? ( + activerelays < 1 || !online ? ( {t('menuItems.notConnected')} ) : ( @@ -220,9 +231,38 @@ export const MenuItems: React.FC = () => { /> + + + {publicKey && ( = ({ showSensitive, relayColouring, longPressZap, + online } = useContext(AppContext) const [relayAdded, setRelayAdded] = useState(false) const [positiveReactions, setPositiveReactions] = useState(0) @@ -127,7 +128,7 @@ export const NoteCard: React.FC = ({ const bTags = getBitcoinTag(note) setBitcoinTag(bTags[bTags.length - 1] ?? undefined) } - }, [lastEventId]) + }, [lastEventId, online]) useEffect(() => { if (database && note) { diff --git a/frontend/Contexts/AppContext.tsx b/frontend/Contexts/AppContext.tsx index 5598811..a409ab1 100644 --- a/frontend/Contexts/AppContext.tsx +++ b/frontend/Contexts/AppContext.tsx @@ -20,6 +20,7 @@ export interface Config { relay_coloruring: boolean long_press_zap: number | undefined sign_height: boolean + online: boolean } export interface AppContextProps { @@ -58,6 +59,8 @@ export interface AppContextProps { setQrReader: (qrReader: string | undefined) => void signHeight: boolean setSignWithHeight: (signHeight: boolean) => void + online: boolean + setOnline: (online: boolean) => void } export interface AppContextProviderProps { @@ -99,7 +102,9 @@ export const initialAppContext: AppContextProps = { longPressZap: undefined, setLongPressZap: () => {}, signHeight: false, - setSignWithHeight: () => {} + setSignWithHeight: () => {}, + online: true, + setOnline: () => {} } export const AppContextProvider = ({ children }: AppContextProviderProps): JSX.Element => { @@ -128,6 +133,7 @@ export const AppContextProvider = ({ children }: AppContextProviderProps): JSX.E const [displayUserDrawer, setDisplayUserDrawer] = React.useState() const [pushedTab, setPushedTab] = useState() const [signHeight, setSignWithHeight] = useState(initialAppContext.signHeight) + const [online, setOnline] = React.useState(initialAppContext.online) useEffect(() => { if (pushedTab) setPushedTab(undefined) @@ -176,6 +182,7 @@ export const AppContextProvider = ({ children }: AppContextProviderProps): JSX.E setLongPressZap(config.long_press_zap ?? initialAppContext.longPressZap) setRelayColouring(config.relay_coloruring ?? initialAppContext.relayColouring) setSignWithHeight(config.sign_height ?? initialAppContext.signHeight) + setOnline(config.online ?? initialAppContext.online) } else { const config: Config = { show_public_images: initialAppContext.showPublicImages, @@ -188,6 +195,7 @@ export const AppContextProvider = ({ children }: AppContextProviderProps): JSX.E relay_coloruring: initialAppContext.relayColouring, long_press_zap: initialAppContext.longPressZap, sign_height: initialAppContext.signHeight, + online: initialAppContext.online, } SInfo.setItem('config', JSON.stringify(config), {}) } @@ -226,6 +234,14 @@ export const AppContextProvider = ({ children }: AppContextProviderProps): JSX.E } } + useEffect(() => { + SInfo.getItem('config', {}).then((result) => { + const config: Config = JSON.parse(result) + config.online = online + SInfo.setItem('config', JSON.stringify(config), {}) + }) + }, [online]) + useEffect(init, []) return ( @@ -264,7 +280,9 @@ export const AppContextProvider = ({ children }: AppContextProviderProps): JSX.E qrReader, setQrReader, signHeight, - setSignWithHeight + setSignWithHeight, + online, + setOnline }} > {children} diff --git a/frontend/Contexts/RelayPoolContext.tsx b/frontend/Contexts/RelayPoolContext.tsx index 360d6a6..a11bc98 100644 --- a/frontend/Contexts/RelayPoolContext.tsx +++ b/frontend/Contexts/RelayPoolContext.tsx @@ -34,6 +34,7 @@ export interface RelayPoolContextProps { setNewGroupMessages: (newGroupMessages: number) => void relayPay: PayEvent[] setRelayPay: (invoices: PayEvent[]) => void + switchLine: () => void } export interface WebsocketEvent { @@ -73,14 +74,15 @@ export const initialRelayPoolContext: RelayPoolContextProps = { newGroupMessages: 0, setNewGroupMessages: () => {}, relayPay: [], - setRelayPay: () => {} + setRelayPay: () => {}, + switchLine: () => {} } export const RelayPoolContextProvider = ({ children, images, }: RelayPoolContextProviderProps): JSX.Element => { - const { database, signHeight } = useContext(AppContext) + const { database, signHeight, online, setOnline } = useContext(AppContext) const { publicKey, privateKey } = React.useContext(UserContext) const [relayPool, setRelayPool] = useState() const [relayPoolReady, setRelayPoolReady] = useState(false) @@ -209,8 +211,8 @@ export const RelayPoolContextProvider = ({ const loadRelayPool: () => void = async () => { if (database && publicKey) { - const initRelayPool = new RelayPool(privateKey) - initRelayPool.connect(publicKey, () => { + const initRelayPool = new RelayPool(online, privateKey) + initRelayPool.switchLine(online, publicKey, () => { setRelayPool(initRelayPool) }) } @@ -292,6 +294,12 @@ export const RelayPoolContextProvider = ({ randomrelays.forEach(async (url) => await addRelayItem({ url })) } + const switchLine: () => void = () => { + if (relayPool && publicKey) { + relayPool.switchLine(!online, publicKey, () => setOnline(!online)) + } + } + useEffect(() => { if (publicKey && publicKey !== '') { DeviceEventEmitter.addListener('WebsocketEvent', debouncedEventIdHandler) @@ -346,7 +354,8 @@ export const RelayPoolContextProvider = ({ newGroupMessages, setNewGroupMessages, relayPay, - setRelayPay + setRelayPay, + switchLine }} > {children} diff --git a/frontend/Locales/de.json b/frontend/Locales/de.json index cfb78a4..fe5c1f7 100644 --- a/frontend/Locales/de.json +++ b/frontend/Locales/de.json @@ -157,7 +157,9 @@ "faq": "FAQ", "reportBug": "Bug melden", "logout": "Abmelden", - "exports": "Export" + "exports": "Export", + "online": "Online", + "offline": "Offline" }, "configPage": { "signHeight": "Sign events with latest Bitcoin block", diff --git a/frontend/Locales/en.json b/frontend/Locales/en.json index 65f9e2a..572b524 100644 --- a/frontend/Locales/en.json +++ b/frontend/Locales/en.json @@ -152,7 +152,9 @@ "contacts": "Contacts", "reportBug": "Report a bug", "logout": "Logout", - "exports": "Export" + "exports": "Export", + "online": "Online", + "offline": "Offline" }, "configPage": { "showPublicImages": "Show images on public feed", diff --git a/frontend/Locales/es.json b/frontend/Locales/es.json index 6632589..bb0adff 100644 --- a/frontend/Locales/es.json +++ b/frontend/Locales/es.json @@ -178,7 +178,9 @@ "faq": "Preguntas frecuentes", "reportBug": "Reportar un bug", "logout": "Salir", - "exports": "Exportar/Importar" + "exports": "Exportar/Importar", + "online": "Online", + "offline": "Offline" }, "configPage": { "signHeight": "Firmar con el último bloque bitcoin", diff --git a/frontend/Locales/fr.json b/frontend/Locales/fr.json index 0964eac..a80acf7 100644 --- a/frontend/Locales/fr.json +++ b/frontend/Locales/fr.json @@ -178,7 +178,9 @@ "faq": "FAQ", "reportBug": "Report a bug", "logout": "Sortir", - "exports": "Export" + "exports": "Export", + "online": "Online", + "offline": "Offline" }, "language": { "en": "English", diff --git a/frontend/Locales/ru.json b/frontend/Locales/ru.json index 07b4346..29348fe 100644 --- a/frontend/Locales/ru.json +++ b/frontend/Locales/ru.json @@ -179,7 +179,9 @@ "logout": "Выйти", "reportBug": "Report a bug", "imageHostingService": "Хостинг изображений", - "exports": "Export" + "exports": "Export", + "online": "Online", + "offline": "Offline" }, "configPage": { "signHeight": "Sign events with latest Bitcoin block", diff --git a/frontend/Locales/zhCn.json b/frontend/Locales/zhCn.json index d91da1c..83fa194 100644 --- a/frontend/Locales/zhCn.json +++ b/frontend/Locales/zhCn.json @@ -177,7 +177,9 @@ "faq": "常见问题", "reportBug": "反馈问题", "logout": "退出", - "exports": "Export" + "exports": "Export", + "online": "Online", + "offline": "Offline" }, "configPage": { "signHeight": "用最新的比特币区块签署事件", diff --git a/frontend/Pages/ContactsPage/index.tsx b/frontend/Pages/ContactsPage/index.tsx index 4509d10..2981d11 100644 --- a/frontend/Pages/ContactsPage/index.tsx +++ b/frontend/Pages/ContactsPage/index.tsx @@ -37,7 +37,7 @@ export const ContactsPage: React.FC = () => { const { t } = useTranslation('common') const theme = useTheme() const initialPageSize = 20 - const { database, setDisplayUserDrawer, qrReader, setQrReader } = useContext(AppContext) + const { database, setDisplayUserDrawer, qrReader, setQrReader, online } = useContext(AppContext) const { privateKey, publicKey, nPub, mutedUsers, reloadLists } = React.useContext(UserContext) const { relayPool, lastEventId, sendEvent } = useContext(RelayPoolContext) const [pageSize, setPageSize] = useState(initialPageSize) @@ -73,7 +73,7 @@ export const ContactsPage: React.FC = () => { reloadLists() loadUsers() subscribeContacts() - }, [lastEventId]) + }, [lastEventId, online]) useEffect(() => { loadUsers() diff --git a/frontend/Pages/ConversationPage/index.tsx b/frontend/Pages/ConversationPage/index.tsx index dd9beea..9fe34ac 100644 --- a/frontend/Pages/ConversationPage/index.tsx +++ b/frontend/Pages/ConversationPage/index.tsx @@ -51,7 +51,7 @@ export const ConversationPage: React.FC = ({ route }) => const theme = useTheme() const scrollViewRef = useRef() const { database, setRefreshBottomBarAt, setDisplayUserDrawer } = useContext(AppContext) - const { relayPool, lastEventId, sendEvent } = useContext(RelayPoolContext) + const { relayPool, lastEventId, sendEvent, online } = useContext(RelayPoolContext) const { publicKey, privateKey, name, picture, validNip05 } = useContext(UserContext) const otherPubKey = useMemo(() => route.params.pubKey, []) const [pageSize, setPageSize] = useState(initialPageSize) @@ -83,7 +83,7 @@ export const ConversationPage: React.FC = ({ route }) => useEffect(() => { loadDirectMessages(false) - }, [lastEventId]) + }, [lastEventId, online]) const loadDirectMessages: (subscribe: boolean) => void = (subscribe) => { if (database && publicKey && privateKey) { diff --git a/frontend/Pages/ExternalIdentitiesPage/index.tsx b/frontend/Pages/ExternalIdentitiesPage/index.tsx index f765796..ab33b93 100644 --- a/frontend/Pages/ExternalIdentitiesPage/index.tsx +++ b/frontend/Pages/ExternalIdentitiesPage/index.tsx @@ -15,7 +15,7 @@ export const ExternalIdentitiesPage: React.FC = () => { const theme = useTheme() const { database } = React.useContext(AppContext) const { publicKey } = React.useContext(UserContext) - const { lastEventId, sendEvent } = React.useContext(RelayPoolContext) + const { lastEventId, sendEvent, online } = React.useContext(RelayPoolContext) const [user, setUser] = React.useState() const [showNotification, setShowNotification] = React.useState() @@ -49,7 +49,7 @@ export const ExternalIdentitiesPage: React.FC = () => { } }) } - }, [user, lastEventId]) + }, [user, lastEventId, online]) const services: Record< string, diff --git a/frontend/Pages/GroupPage/index.tsx b/frontend/Pages/GroupPage/index.tsx index 296df68..396f23c 100644 --- a/frontend/Pages/GroupPage/index.tsx +++ b/frontend/Pages/GroupPage/index.tsx @@ -46,7 +46,7 @@ interface GroupPageProps { export const GroupPage: React.FC = ({ route }) => { const initialPageSize = 20 const theme = useTheme() - const { database, setDisplayUserDrawer } = useContext(AppContext) + const { database, setDisplayUserDrawer, online } = useContext(AppContext) const { relayPool, lastEventId, sendEvent } = useContext(RelayPoolContext) const { publicKey, privateKey, name, picture, validNip05 } = useContext(UserContext) const [pageSize, setPageSize] = useState(initialPageSize) @@ -75,7 +75,7 @@ export const GroupPage: React.FC = ({ route }) => { useEffect(() => { loadGroupMessages(false) - }, [lastEventId, pageSize]) + }, [lastEventId, pageSize, online]) const loadGroupMessages: (subscribe: boolean) => void = (subscribe) => { if (database && publicKey && route.params.groupId) { diff --git a/frontend/Pages/HomePage/ConversationsFeed/index.tsx b/frontend/Pages/HomePage/ConversationsFeed/index.tsx index 74c0f72..cba7c21 100644 --- a/frontend/Pages/HomePage/ConversationsFeed/index.tsx +++ b/frontend/Pages/HomePage/ConversationsFeed/index.tsx @@ -44,7 +44,7 @@ export const ConversationsFeed: React.FC = () => { const initialPageSize = 14 const theme = useTheme() const { t } = useTranslation('common') - const { database, refreshBottomBarAt, qrReader, setQrReader } = useContext(AppContext) + const { database, refreshBottomBarAt, qrReader, setQrReader, online } = useContext(AppContext) const [pageSize, setPageSize] = useState(initialPageSize) const { publicKey, privateKey } = useContext(UserContext) const { relayPool, lastEventId, setNewDirectMessages, newDirectMessages } = useContext(RelayPoolContext) @@ -71,7 +71,7 @@ export const ConversationsFeed: React.FC = () => { useEffect(() => { setNewDirectMessages(0) loadDirectMessages(false) - }, [lastEventId, refreshBottomBarAt, newDirectMessages]) + }, [lastEventId, refreshBottomBarAt, newDirectMessages, online]) useEffect(() => { if (qrReader) { diff --git a/frontend/Pages/HomePage/GroupsFeed/index.tsx b/frontend/Pages/HomePage/GroupsFeed/index.tsx index cf4daa6..c277d06 100644 --- a/frontend/Pages/HomePage/GroupsFeed/index.tsx +++ b/frontend/Pages/HomePage/GroupsFeed/index.tsx @@ -41,7 +41,7 @@ import DatabaseModule from '../../../lib/Native/DatabaseModule' export const GroupsFeed: React.FC = () => { const { t } = useTranslation('common') const theme = useTheme() - const { database, qrReader, setQrReader, refreshBottomBarAt } = useContext(AppContext) + const { database, qrReader, setQrReader, refreshBottomBarAt, online } = useContext(AppContext) const { publicKey } = useContext(UserContext) const { relayPool, lastEventId, lastConfirmationtId, sendEvent, setNewGroupMessages, newGroupMessages } = useContext(RelayPoolContext) const bottomSheetSearchRef = React.useRef(null) @@ -72,7 +72,7 @@ export const GroupsFeed: React.FC = () => { useEffect(() => { setNewGroupMessages(0) loadGroups() - }, [lastEventId, lastConfirmationtId, refreshBottomBarAt]) + }, [lastEventId, lastConfirmationtId, refreshBottomBarAt, online]) useEffect(() => { setNewGroupMessages(0) diff --git a/frontend/Pages/HomePage/HomeFeed/BookmarksFeed/index.tsx b/frontend/Pages/HomePage/HomeFeed/BookmarksFeed/index.tsx index 57a1310..758256e 100644 --- a/frontend/Pages/HomePage/HomeFeed/BookmarksFeed/index.tsx +++ b/frontend/Pages/HomePage/HomeFeed/BookmarksFeed/index.tsx @@ -15,43 +15,34 @@ import { Kind } from 'nostr-tools' import { type RelayFilters } from '../../../../lib/nostr/RelayPool/intex' import { ActivityIndicator, Button, Text } from 'react-native-paper' import NoteCard from '../../../../Components/NoteCard' -import { useTheme } from '@react-navigation/native' +import { useFocusEffect, useTheme } from '@react-navigation/native' import { FlashList, type ListRenderItem } from '@shopify/flash-list' import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons' import { useTranslation } from 'react-i18next' import { getContactsCount } from '../../../../Functions/DatabaseFunctions/Users' import { ScrollView } from 'react-native-gesture-handler' -interface BookmarksFeedProps { - navigation: any - updateLastLoad: () => void - pageSize: number - setPageSize: (pageSize: number) => void - activeTab: string -} - -export const BookmarksFeed: React.FC = ({ - navigation, - updateLastLoad, - pageSize, - setPageSize, - activeTab, -}) => { +export const BookmarksFeed: React.FC = () => { + const initialPageSize = 10 const theme = useTheme() const { t } = useTranslation('common') - const { database, pushedTab } = useContext(AppContext) + const { database, pushedTab, online } = useContext(AppContext) const { publicKey, publicBookmarks, privateBookmarks, reloadBookmarks } = useContext(UserContext) const { lastEventId, relayPool, lastConfirmationtId } = useContext(RelayPoolContext) - const initialPageSize = 10 const [notes, setNotes] = useState([]) const [refreshing, setRefreshing] = useState(false) const [contactsCount, setContactsCount] = useState() const [filter, setFilter] = useState<'private' | 'public'>('private') + const [pageSize, setPageSize] = useState(initialPageSize) const flashListRef = React.useRef>(null) - useEffect(() => { - reloadBookmarks() - }, []) + useFocusEffect( + React.useCallback(() => { + setPageSize(initialPageSize) + + return () => {} + }, []), + ) useEffect(() => { if (pushedTab) { @@ -60,7 +51,7 @@ export const BookmarksFeed: React.FC = ({ }, [pushedTab]) useEffect(() => { - if (relayPool && publicKey && database && activeTab === 'bookmarks') { + if (relayPool && publicKey && database) { if (!contactsCount) getContactsCount(database).then(setContactsCount) loadNotes() } @@ -71,9 +62,9 @@ export const BookmarksFeed: React.FC = ({ relayPool, publicKey, database, - activeTab, publicBookmarks, privateBookmarks, + online ]) useEffect(() => { @@ -85,7 +76,8 @@ export const BookmarksFeed: React.FC = ({ const onRefresh = useCallback(() => { setRefreshing(true) - updateLastLoad() + loadNotes() + reloadBookmarks() }, []) const onScroll: (event: NativeSyntheticEvent) => void = (event) => { diff --git a/frontend/Pages/HomePage/HomeFeed/GlobalFeed/index.tsx b/frontend/Pages/HomePage/HomeFeed/GlobalFeed/index.tsx index 0309c37..24ffe5d 100644 --- a/frontend/Pages/HomePage/HomeFeed/GlobalFeed/index.tsx +++ b/frontend/Pages/HomePage/HomeFeed/GlobalFeed/index.tsx @@ -20,37 +20,45 @@ import { Kind } from 'nostr-tools' import { type RelayFilters } from '../../../../lib/nostr/RelayPool/intex' import { Chip, Button, Text } from 'react-native-paper' import NoteCard from '../../../../Components/NoteCard' -import { useTheme } from '@react-navigation/native' +import { useFocusEffect, useTheme } from '@react-navigation/native' import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons' import { t } from 'i18next' import { FlashList, type ListRenderItem } from '@shopify/flash-list' +import { getUnixTime } from 'date-fns' interface GlobalFeedProps { navigation: any - updateLastLoad: () => void - lastLoadAt: number - pageSize: number - setPageSize: (pageSize: number) => void - activeTab: string } export const GlobalFeed: React.FC = ({ - navigation, - updateLastLoad, - lastLoadAt, - pageSize, - setPageSize, - activeTab, + navigation }) => { const initialPageSize = 10 const theme = useTheme() - const { database, showPublicImages, pushedTab } = useContext(AppContext) + const { database, showPublicImages, pushedTab, online } = useContext(AppContext) const { publicKey } = useContext(UserContext) const { lastEventId, relayPool, lastConfirmationtId } = useContext(RelayPoolContext) const [notes, setNotes] = useState([]) const [newNotesCount, setNewNotesCount] = useState(0) const [refreshing, setRefreshing] = useState(false) const flashListRef = React.useRef>(null) + const [lastLoadAt, setLastLoadAt] = useState(0) + const [pageSize, setPageSize] = useState(initialPageSize) + + useFocusEffect( + React.useCallback(() => { + setPageSize(initialPageSize) + + return () => {} + }, []), + ) + + useEffect(() => { + if (pageSize > initialPageSize) { + updateLastLoad() + loadNotes(true) + } + }, [pageSize, lastLoadAt]) useEffect(() => { if (pushedTab) { @@ -59,19 +67,18 @@ export const GlobalFeed: React.FC = ({ }, [pushedTab]) useEffect(() => { - if (relayPool && publicKey && activeTab === 'globalFeed') { + if (relayPool && publicKey) { loadNotes() } - }, [lastEventId, lastConfirmationtId, lastLoadAt, relayPool, publicKey, activeTab]) + }, [lastEventId, lastConfirmationtId, relayPool, publicKey, online]) - useEffect(() => { - if (pageSize > initialPageSize) { - loadNotes(true) - } - }, [pageSize]) + const updateLastLoad: () => void = () => { + setLastLoadAt(getUnixTime(new Date()) - 5) + } const onRefresh = useCallback(() => { setRefreshing(true) + loadNotes() setNewNotesCount(0) updateLastLoad() flashListRef.current?.scrollToIndex({ animated: true, index: 0 }) diff --git a/frontend/Pages/HomePage/HomeFeed/MyFeed/index.tsx b/frontend/Pages/HomePage/HomeFeed/MyFeed/index.tsx index f0dc7db..2840318 100644 --- a/frontend/Pages/HomePage/HomeFeed/MyFeed/index.tsx +++ b/frontend/Pages/HomePage/HomeFeed/MyFeed/index.tsx @@ -15,7 +15,7 @@ import { Kind } from 'nostr-tools' import { type RelayFilters } from '../../../../lib/nostr/RelayPool/intex' import { ActivityIndicator, Button, Text } from 'react-native-paper' import NoteCard from '../../../../Components/NoteCard' -import { useTheme } from '@react-navigation/native' +import { useFocusEffect, useTheme } from '@react-navigation/native' import { FlashList, type ListRenderItem } from '@shopify/flash-list' import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons' import { useTranslation } from 'react-i18next' @@ -27,29 +27,29 @@ import { interface MyFeedProps { navigation: any - updateLastLoad: () => void - pageSize: number - setPageSize: (pageSize: number) => void - activeTab: string } export const MyFeed: React.FC = ({ navigation, - updateLastLoad, - pageSize, - setPageSize, - activeTab, }) => { const theme = useTheme() + const initialPageSize = 10 const { t } = useTranslation('common') - const { database, pushedTab } = useContext(AppContext) + const { database, pushedTab, online } = useContext(AppContext) const { publicKey } = useContext(UserContext) const { lastEventId, relayPool, lastConfirmationtId } = useContext(RelayPoolContext) - const initialPageSize = 10 const [notes, setNotes] = useState([]) const [refreshing, setRefreshing] = useState(false) const [contactsCount, setContactsCount] = useState() + const [pageSize, setPageSize] = useState(initialPageSize) const flashListRef = React.useRef>(null) + + useFocusEffect( + React.useCallback(() => { + setPageSize(initialPageSize) + return () => {} + }, []), + ) useEffect(() => { if (pushedTab) { @@ -58,11 +58,11 @@ export const MyFeed: React.FC = ({ }, [pushedTab]) useEffect(() => { - if (relayPool && publicKey && database && activeTab === 'myFeed') { + if (relayPool && publicKey && database) { if (!contactsCount) getContactsCount(database).then(setContactsCount) loadNotes() } - }, [lastEventId, lastConfirmationtId, relayPool, publicKey, database, activeTab]) + }, [lastEventId, lastConfirmationtId, relayPool, publicKey, database, online]) useEffect(() => { if (pageSize > initialPageSize) { @@ -72,7 +72,7 @@ export const MyFeed: React.FC = ({ const onRefresh = useCallback(() => { setRefreshing(true) - updateLastLoad() + loadNotes() }, []) const onScroll: (event: NativeSyntheticEvent) => void = (event) => { diff --git a/frontend/Pages/HomePage/HomeFeed/ZapsFeed/index.tsx b/frontend/Pages/HomePage/HomeFeed/ZapsFeed/index.tsx index 899705c..c3c6c8d 100644 --- a/frontend/Pages/HomePage/HomeFeed/ZapsFeed/index.tsx +++ b/frontend/Pages/HomePage/HomeFeed/ZapsFeed/index.tsx @@ -15,7 +15,7 @@ import { Kind } from 'nostr-tools' import { type RelayFilters } from '../../../../lib/nostr/RelayPool/intex' import { ActivityIndicator, Button, Text } from 'react-native-paper' import NoteCard from '../../../../Components/NoteCard' -import { useTheme } from '@react-navigation/native' +import { useFocusEffect, useTheme } from '@react-navigation/native' import { FlashList, type ListRenderItem } from '@shopify/flash-list' import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons' import { useTranslation } from 'react-i18next' @@ -25,28 +25,29 @@ import { getUsers, type User } from '../../../../Functions/DatabaseFunctions/Use interface ZapsFeedProps { navigation: any - updateLastLoad: () => void - pageSize: number - setPageSize: (pageSize: number) => void - activeTab: string } export const ZapsFeed: React.FC = ({ - navigation, - updateLastLoad, - pageSize, - setPageSize, - activeTab, + navigation }) => { + const initialPageSize = 10 const theme = useTheme() const { t } = useTranslation('common') - const { database, pushedTab } = useContext(AppContext) + const { database, pushedTab, online } = useContext(AppContext) const { publicKey } = useContext(UserContext) const { lastEventId, relayPool, lastConfirmationtId } = useContext(RelayPoolContext) - const initialPageSize = 10 const [notes, setNotes] = useState() const [refreshing, setRefreshing] = useState(false) const flashListRef = React.useRef>(null) + const [pageSize, setPageSize] = useState(initialPageSize) + + useFocusEffect( + React.useCallback(() => { + setPageSize(initialPageSize) + + return () => {} + }, []), + ) useEffect(() => { if (pushedTab) { @@ -55,10 +56,10 @@ export const ZapsFeed: React.FC = ({ }, [pushedTab]) useEffect(() => { - if (relayPool && publicKey && activeTab === 'zaps') { + if (relayPool && publicKey) { loadNotes() } - }, [lastEventId, lastConfirmationtId, relayPool, publicKey, activeTab]) + }, [lastEventId, lastConfirmationtId, relayPool, publicKey, online]) useEffect(() => { if (pageSize > initialPageSize) { @@ -68,7 +69,7 @@ export const ZapsFeed: React.FC = ({ const onRefresh = useCallback(() => { setRefreshing(true) - updateLastLoad() + loadNotes() }, []) const onScroll: (event: NativeSyntheticEvent) => void = (event) => { @@ -85,6 +86,7 @@ export const ZapsFeed: React.FC = ({ { kinds: [9735], '#p': contacts, + since: getUnixTime(new Date()) - 86400 }, ]) diff --git a/frontend/Pages/HomePage/HomeFeed/index.tsx b/frontend/Pages/HomePage/HomeFeed/index.tsx index 8e4c640..256f310 100644 --- a/frontend/Pages/HomePage/HomeFeed/index.tsx +++ b/frontend/Pages/HomePage/HomeFeed/index.tsx @@ -1,34 +1,47 @@ -import React, { useContext, useEffect, useState } from 'react' +import React, { useContext, useEffect } from 'react' import { Dimensions, StyleSheet, View } from 'react-native' import { UserContext } from '../../../Contexts/UserContext' -import { RelayPoolContext } from '../../../Contexts/RelayPoolContext' import { AnimatedFAB } from 'react-native-paper' -import { useFocusEffect } from '@react-navigation/native' import { navigate } from '../../../lib/Navigation' import GlobalFeed from './GlobalFeed' import MyFeed from './MyFeed' -import { getUnixTime } from 'date-fns' -import { AppContext } from '../../../Contexts/AppContext' import Tabs from '../../../Components/Tabs' import ZapsFeed from './ZapsFeed' import BookmarksFeed from './BookmarksFeed' +import { RelayPoolContext } from '../../../Contexts/RelayPoolContext' interface HomeFeedProps { navigation: any } export const HomeFeed: React.FC = ({ navigation }) => { - const initialPageSize = 10 - const { database } = useContext(AppContext) const { privateKey, publicKey } = useContext(UserContext) const { relayPool } = useContext(RelayPoolContext) const [activeTab, setActiveTab] = React.useState('myFeed') - const [prevTab, setPrevTab] = React.useState('') - const [lastLoadAt, setLastLoadAt] = useState(0) - const [pageSize, setPageSize] = useState(initialPageSize) - const unsubscribe: () => void = () => { - if (prevTab === 'zaps') { + useEffect(() => { + if (activeTab !== 'myFeed') { + relayPool?.unsubscribe([ + `homepage-myfeed-main${publicKey?.substring(0, 8)}`, + `homepage-myfeed-reposts${publicKey?.substring(0, 8)}`, + `homepage-myfeed-reaction${publicKey?.substring(0, 8)}` + ]) + } + if (activeTab !== 'bookmarks') { + relayPool?.unsubscribe([ + `homepage-bookmarks-main${publicKey?.substring(0, 8)}`, + `homepage-bookmarks-reactions${publicKey?.substring(0, 8)}`, + `homepage-bookmarks-reposts${publicKey?.substring(0, 8)}`, + ]) + } + if (activeTab !== 'globalFeed') { + relayPool?.unsubscribe([ + `homepage-global-main${publicKey?.substring(0, 8)}`, + `homepage-global-reposts${publicKey?.substring(0, 8)}`, + `homepage-global-reactions${publicKey?.substring(0, 8)}` + ]) + } + if (activeTab !== 'zaps') { relayPool?.unsubscribe([ `homepage-zaps-notes${publicKey?.substring(0, 8)}`, `homepage-zaps-reactions${publicKey?.substring(0, 8)}`, @@ -36,91 +49,26 @@ export const HomeFeed: React.FC = ({ navigation }) => { `homepage-zaps-main${publicKey?.substring(0, 8)}`, ]) } - if (prevTab === 'myFeed') { - relayPool?.unsubscribe([ - `homepage-myfeed-main${publicKey?.substring(0, 8)}`, - `homepage-myfeed-reposts${publicKey?.substring(0, 8)}`, - `homepage-myfeed-reaction${publicKey?.substring(0, 8)}` - ]) - } - if (prevTab === 'globalFeed') { - relayPool?.unsubscribe([ - `homepage-global-main${publicKey?.substring(0, 8)}`, - `homepage-global-reposts${publicKey?.substring(0, 8)}`, - `homepage-global-reactions${publicKey?.substring(0, 8)}` - ]) - } - if (prevTab === 'bookmarks') { - relayPool?.unsubscribe([ - `homepage-bookmarks-main${publicKey?.substring(0, 8)}`, - `homepage-bookmarks-reactions${publicKey?.substring(0, 8)}`, - `homepage-bookmarks-reposts${publicKey?.substring(0, 8)}`, - ]) - } - } - - useFocusEffect( - React.useCallback(() => { - updateLastLoad() - - return unsubscribe - }, []), - ) - - useEffect(() => { - if (database && relayPool) { - if (prevTab !== '') unsubscribe() - setPrevTab(activeTab) - } - }, [activeTab, database, relayPool]) - - useEffect(() => { - if (pageSize > initialPageSize) { - updateLastLoad() - } - }, [pageSize, lastLoadAt]) - - const updateLastLoad: () => void = () => { - setLastLoadAt(getUnixTime(new Date()) - 5) - } + }, [activeTab]) const renderScene: Record = { globalFeed: ( ), myFeed: ( ), zaps: ( ), bookmarks: ( - + ), } diff --git a/frontend/Pages/HomePage/NotificationsFeed/index.tsx b/frontend/Pages/HomePage/NotificationsFeed/index.tsx index b1281f1..b1b7d82 100644 --- a/frontend/Pages/HomePage/NotificationsFeed/index.tsx +++ b/frontend/Pages/HomePage/NotificationsFeed/index.tsx @@ -30,13 +30,13 @@ import { getTaggedEventIds } from '../../../Functions/RelayFunctions/Events' import ParsedText from 'react-native-parsed-text' import { getUser } from '../../../Functions/DatabaseFunctions/Users' import { getNpub } from '../../../lib/nostr/Nip19' -import { RelayFilters } from '../../../lib/nostr/RelayPool/intex' +import { type RelayFilters } from '../../../lib/nostr/RelayPool/intex' export const NotificationsFeed: React.FC = () => { const initialLimitPage = React.useMemo(() => 20, []) const theme = useTheme() const { t } = useTranslation('common') - const { database, setNotificationSeenAt, pushedTab, getSatoshiSymbol } = useContext(AppContext) + const { database, setNotificationSeenAt, pushedTab, getSatoshiSymbol, online } = useContext(AppContext) const { publicKey, reloadLists, mutedEvents, mutedUsers } = useContext(UserContext) const { lastEventId, relayPool, setNewNotifications, newNotifications } = useContext(RelayPoolContext) const [notifications, setNotifications] = useState([]) @@ -52,10 +52,7 @@ export const NotificationsFeed: React.FC = () => { loadNotes() updateLastSeen() return () => { - relayPool?.unsubscribe([ - `notification-feed${publicKey?.substring(0, 8)}`, - `notification-users${publicKey?.substring(0, 8)}`, - ]) + unsubscribe() updateLastSeen() } }, []), @@ -66,7 +63,7 @@ export const NotificationsFeed: React.FC = () => { reloadLists() setRefreshing(false) setNewNotifications(0) - }, [lastEventId]) + }, [lastEventId, online]) useEffect(() => { setNewNotifications(0) @@ -82,6 +79,13 @@ export const NotificationsFeed: React.FC = () => { } }, [pushedTab]) + const unsubscribe: () => void = () => { + relayPool?.unsubscribe([ + `notification-feed${publicKey?.substring(0, 8)}`, + `notification-users${publicKey?.substring(0, 8)}`, + ]) + } + const updateLastSeen: () => void = () => { const unixtime = getUnixTime(new Date()) setNotificationSeenAt(unixtime) @@ -154,6 +158,7 @@ export const NotificationsFeed: React.FC = () => { const onRefresh = useCallback(() => { setRefreshing(true) if (relayPool && publicKey) { + unsubscribe() subscribeNotes() } }, []) diff --git a/frontend/Pages/NoteActionsPage/index.tsx b/frontend/Pages/NoteActionsPage/index.tsx index 950e19a..f8ec4e8 100644 --- a/frontend/Pages/NoteActionsPage/index.tsx +++ b/frontend/Pages/NoteActionsPage/index.tsx @@ -27,7 +27,7 @@ export const NoteActionsPage: React.FC = ({ route: { param privateBookmarks, mutedEvents, } = React.useContext(UserContext) - const { database, displayNoteDrawer, relayColouring } = React.useContext(AppContext) + const { database, displayNoteDrawer, relayColouring, online } = React.useContext(AppContext) const { relayPool, setDisplayrelayDrawer, lastEventId, sendEvent } = React.useContext(RelayPoolContext) const [relays, setRelays] = React.useState([]) @@ -39,7 +39,7 @@ export const NoteActionsPage: React.FC = ({ route: { param React.useEffect(() => { loadNoteRelays() - }, [displayNoteDrawer, lastEventId, bookmarked, isMuted]) + }, [displayNoteDrawer, lastEventId, bookmarked, isMuted, online]) React.useEffect(() => { if (note) { diff --git a/frontend/Pages/NotePage/index.tsx b/frontend/Pages/NotePage/index.tsx index 1b29a38..003342b 100644 --- a/frontend/Pages/NotePage/index.tsx +++ b/frontend/Pages/NotePage/index.tsx @@ -22,7 +22,7 @@ interface NotePageProps { } export const NotePage: React.FC = ({ route }) => { - const { database } = useContext(AppContext) + const { database, online } = useContext(AppContext) const { publicKey, privateKey } = useContext(UserContext) const { relayPool, lastEventId } = useContext(RelayPoolContext) const [note, setNote] = useState() @@ -46,7 +46,7 @@ export const NotePage: React.FC = ({ route }) => { useEffect(() => { loadNote() loadGroup() - }, [lastEventId]) + }, [lastEventId, online]) const loadGroup: () => void = async () => { if (database) { diff --git a/frontend/Pages/ProfileActionsPage/index.tsx b/frontend/Pages/ProfileActionsPage/index.tsx index 35eea24..3ee8ec3 100644 --- a/frontend/Pages/ProfileActionsPage/index.tsx +++ b/frontend/Pages/ProfileActionsPage/index.tsx @@ -27,7 +27,7 @@ interface ProfileActionsProps { export const ProfileActionsPage: React.FC = ({ route: { params: { userId } } }) => { const theme = useTheme() - const { database, longPressZap } = React.useContext(AppContext) + const { database, longPressZap, online } = React.useContext(AppContext) const { publicKey, privateKey, mutedUsers } = React.useContext(UserContext) const { relayPool, addRelayItem, lastEventId, sendEvent, relays } = React.useContext(RelayPoolContext) @@ -60,7 +60,7 @@ export const ProfileActionsPage: React.FC = ({ route: { par React.useEffect(() => { loadUser() loadRelays() - }, [lastEventId, isMuted]) + }, [lastEventId, isMuted, online]) const hideGroupsUser: () => void = () => { if (publicKey && relayPool && database && userId) { diff --git a/frontend/Pages/ProfileConfigPage/index.tsx b/frontend/Pages/ProfileConfigPage/index.tsx index 7c8eba3..e4b8551 100644 --- a/frontend/Pages/ProfileConfigPage/index.tsx +++ b/frontend/Pages/ProfileConfigPage/index.tsx @@ -32,7 +32,7 @@ export const ProfileConfigPage: React.FC = () => { const bottomSheetDirectoryRef = React.useRef(null) const bottomSheetNip05Ref = React.useRef(null) const bottomSheetLud06Ref = React.useRef(null) - const { database } = useContext(AppContext) + const { database, online } = useContext(AppContext) const { relayPool, lastEventId, lastConfirmationtId, sendEvent } = useContext(RelayPoolContext) const { publicKey, @@ -83,7 +83,7 @@ export const ProfileConfigPage: React.FC = () => { bottomSheetNip05Ref.current?.close() bottomSheetLud06Ref.current?.close() } - }, [lastEventId, lastConfirmationtId]) + }, [lastEventId, lastConfirmationtId, online]) const publishUser: () => Promise = async () => { return await new Promise((resolve) => { diff --git a/frontend/Pages/ProfilePage/BookmarksFeed/index.tsx b/frontend/Pages/ProfilePage/BookmarksFeed/index.tsx index 576b820..5f9abb1 100644 --- a/frontend/Pages/ProfilePage/BookmarksFeed/index.tsx +++ b/frontend/Pages/ProfilePage/BookmarksFeed/index.tsx @@ -30,7 +30,7 @@ export const BookmarksFeed: React.FC = ({ const initialPageSize = 10 const theme = useTheme() const { t } = useTranslation('common') - const { database } = useContext(AppContext) + const { database, online } = useContext(AppContext) const { lastEventId, relayPool } = useContext(RelayPoolContext) const [pageSize, setPageSize] = useState(initialPageSize) const [notes, setNotes] = useState([]) @@ -47,7 +47,7 @@ export const BookmarksFeed: React.FC = ({ subscribe() loadNotes() } - }, [pageSize, lastEventId, activeTab]) + }, [pageSize, lastEventId, activeTab, online]) const subscribe: () => Promise = async () => { if (database) { diff --git a/frontend/Pages/ProfilePage/NotesFeed/index.tsx b/frontend/Pages/ProfilePage/NotesFeed/index.tsx index 598a873..e3914e6 100644 --- a/frontend/Pages/ProfilePage/NotesFeed/index.tsx +++ b/frontend/Pages/ProfilePage/NotesFeed/index.tsx @@ -24,7 +24,7 @@ export const NotesFeed: React.FC = ({ activeTab, }) => { const initialPageSize = 10 - const { database } = useContext(AppContext) + const { database, online } = useContext(AppContext) const { lastEventId, relayPool } = useContext(RelayPoolContext) const [pageSize, setPageSize] = useState(initialPageSize) const [notes, setNotes] = useState([]) @@ -41,7 +41,7 @@ export const NotesFeed: React.FC = ({ subscribe() loadNotes() } - }, [pageSize, lastEventId, activeTab]) + }, [pageSize, lastEventId, activeTab, online]) const subscribe: () => Promise = async () => { relayPool?.subscribe(`profile-user${publicKey.substring(0, 8)}`, [ diff --git a/frontend/Pages/ProfilePage/RepliesFeed/index.tsx b/frontend/Pages/ProfilePage/RepliesFeed/index.tsx index b1926f6..4804f9e 100644 --- a/frontend/Pages/ProfilePage/RepliesFeed/index.tsx +++ b/frontend/Pages/ProfilePage/RepliesFeed/index.tsx @@ -24,7 +24,7 @@ export const RepliesFeed: React.FC = ({ activeTab, }) => { const initialPageSize = 10 - const { database } = useContext(AppContext) + const { database, online } = useContext(AppContext) const { lastEventId, relayPool } = useContext(RelayPoolContext) const [pageSize, setPageSize] = useState(initialPageSize) const [notes, setNotes] = useState([]) @@ -39,7 +39,7 @@ export const RepliesFeed: React.FC = ({ if (activeTab === 'replies') { loadNotes() } - }, [pageSize, lastEventId, activeTab]) + }, [pageSize, lastEventId, activeTab, online]) const loadNotes: (main?: boolean) => void = () => { if (database) { diff --git a/frontend/Pages/ProfilePage/ZapsFeed/index.tsx b/frontend/Pages/ProfilePage/ZapsFeed/index.tsx index 0e7a9d6..9a57573 100644 --- a/frontend/Pages/ProfilePage/ZapsFeed/index.tsx +++ b/frontend/Pages/ProfilePage/ZapsFeed/index.tsx @@ -25,7 +25,7 @@ export const ZapsFeed: React.FC = ({ activeTab, }) => { const initialPageSize = 10 - const { database } = useContext(AppContext) + const { database, online } = useContext(AppContext) const { lastEventId, relayPool } = useContext(RelayPoolContext) const [pageSize, setPageSize] = useState(initialPageSize) const [notes, setNotes] = useState([]) @@ -42,7 +42,7 @@ export const ZapsFeed: React.FC = ({ subscribe() loadNotes() } - }, [pageSize, lastEventId, activeTab]) + }, [pageSize, lastEventId, activeTab, online]) const subscribe: () => Promise = async () => { relayPool?.subscribe(`profile-zaps${publicKey}`, [ diff --git a/frontend/Pages/ProfilePage/index.tsx b/frontend/Pages/ProfilePage/index.tsx index 7d0845f..d4d66fc 100644 --- a/frontend/Pages/ProfilePage/index.tsx +++ b/frontend/Pages/ProfilePage/index.tsx @@ -21,7 +21,7 @@ interface ProfilePageProps { } export const ProfilePage: React.FC = ({ route }) => { - const { database } = useContext(AppContext) + const { database, online } = useContext(AppContext) const { publicKey } = useContext(UserContext) const { lastEventId, relayPool } = useContext(RelayPoolContext) const { t } = useTranslation('common') @@ -73,7 +73,7 @@ export const ProfilePage: React.FC = ({ route }) => { if (!firstLoad && !user?.name) { loadUser() } - }, [lastEventId]) + }, [lastEventId, online]) useEffect(() => { if (refreshing) { diff --git a/frontend/Pages/RelaysPage/index.tsx b/frontend/Pages/RelaysPage/index.tsx index b29db58..eb6347a 100644 --- a/frontend/Pages/RelaysPage/index.tsx +++ b/frontend/Pages/RelaysPage/index.tsx @@ -50,7 +50,7 @@ export const RelaysPage: React.FC = () => { removeRelayItem, } = useContext(RelayPoolContext) const { publicKey } = useContext(UserContext) - const { database } = useContext(AppContext) + const { database, online } = useContext(AppContext) const { t } = useTranslation('common') const theme = useTheme() const bottomSheetAddRef = React.useRef(null) @@ -88,7 +88,7 @@ export const RelaysPage: React.FC = () => { React.useEffect(() => { loadRelays() - }, [lastEventId]) + }, [lastEventId, online]) const addRelay: (url: string) => void = (url) => { if (!relayList.find((relay) => relay.url === url)) { diff --git a/frontend/Pages/SearchPage/index.tsx b/frontend/Pages/SearchPage/index.tsx index 7fa492f..3ac4827 100644 --- a/frontend/Pages/SearchPage/index.tsx +++ b/frontend/Pages/SearchPage/index.tsx @@ -31,7 +31,7 @@ interface SearchPageProps { export const SearchPage: React.FC = ({ route }) => { const pageSize = 30 const theme = useTheme() - const { database } = React.useContext(AppContext) + const { database, online } = React.useContext(AppContext) const { relayPool, lastEventId } = React.useContext(RelayPoolContext) const [users, setUsers] = React.useState([]) const [resultsUsers, setResultsUsers] = React.useState([]) @@ -76,7 +76,7 @@ export const SearchPage: React.FC = ({ route }) => { } }) } - }, [lastEventId]) + }, [lastEventId, online]) const subscribeHandler = React.useMemo( () => diff --git a/frontend/Pages/WalletPage/index.tsx b/frontend/Pages/WalletPage/index.tsx index 2ca88d1..3b34f68 100644 --- a/frontend/Pages/WalletPage/index.tsx +++ b/frontend/Pages/WalletPage/index.tsx @@ -28,7 +28,7 @@ import { navigate } from '../../lib/Navigation' export const WalletPage: React.FC = () => { const theme = useTheme() - const { getSatoshiSymbol, database, setDisplayUserDrawer } = React.useContext(AppContext) + const { getSatoshiSymbol, database, setDisplayUserDrawer, online } = React.useContext(AppContext) const { publicKey } = React.useContext(UserContext) const { relayPool, lastEventId } = React.useContext(RelayPoolContext) const { refreshWallet, updateWallet, type, balance, transactions, invoices, updatedAt } = @@ -73,7 +73,7 @@ export const WalletPage: React.FC = () => { }, ]) } - }, [lastEventId]) + }, [lastEventId, online]) useEffect(() => { const array = [...transactions, ...invoices] diff --git a/frontend/Pages/ZapPage/index.tsx b/frontend/Pages/ZapPage/index.tsx index d38585b..acc46dc 100644 --- a/frontend/Pages/ZapPage/index.tsx +++ b/frontend/Pages/ZapPage/index.tsx @@ -33,7 +33,7 @@ export const ZapPage: React.FC = ({ route: { params: { note, user const userId = user?.id ?? note?.pubkey const zapPubkey = user?.zap_pubkey ?? note?.zap_pubkey const zapSplitTags = getZapTag(note) - const { getSatoshiSymbol, database, setDisplayUserDrawer } = React.useContext(AppContext) + const { getSatoshiSymbol, database, setDisplayUserDrawer, online } = React.useContext(AppContext) const { relayPool, lastEventId } = React.useContext(RelayPoolContext) const { publicKey, privateKey } = React.useContext(UserContext) const bottomSheetLnPaymentRef = React.useRef(null) @@ -85,7 +85,7 @@ export const ZapPage: React.FC = ({ route: { params: { note, user setZapsUpdated(getUnixTime(new Date())) }) } - }, [lastEventId]) + }, [lastEventId, online]) useEffect(() => { bottomSheetLnPaymentRef.current?.forceUpdate() diff --git a/frontend/lib/Native/WebsocketModule/index.ts b/frontend/lib/Native/WebsocketModule/index.ts index ead14bc..069f2c0 100644 --- a/frontend/lib/Native/WebsocketModule/index.ts +++ b/frontend/lib/Native/WebsocketModule/index.ts @@ -5,6 +5,7 @@ interface RelayPoolInterface { sendAll: (message: string, globalFeed: boolean) => void sendRelay: (message: string, relayUrl: string) => void connect: (pubKey: string, callback: (eventId: string) => void) => void + disconnect: (callback: () => void) => void add: (url: string, resilient: number, globalFeed: number, callback: () => void) => void remove: (url: string, callback: () => void) => void removeAll: (callback?: () => void) => void diff --git a/frontend/lib/nostr/RelayPool/intex.ts b/frontend/lib/nostr/RelayPool/intex.ts index 2802507..742d05e 100644 --- a/frontend/lib/nostr/RelayPool/intex.ts +++ b/frontend/lib/nostr/RelayPool/intex.ts @@ -66,18 +66,22 @@ export const fallbackRelays = [ ] class RelayPool { - constructor(privateKey?: string) { + constructor(online: boolean, privateKey?: string) { this.privateKey = privateKey this.subscriptions = {} + this.online = online } private readonly privateKey?: string private subscriptions: Record + public online: boolean + private readonly sendAll: (message: object, globalFeed?: boolean) => void = async ( message, globalFeed, ) => { + if (!this.online) return const tosend = JSON.stringify(message) RelayPoolModule.sendAll(tosend, globalFeed ?? false) } @@ -86,15 +90,11 @@ class RelayPool { message, relayUrl, ) => { + if (!this.online) return const tosend = JSON.stringify(message) RelayPoolModule.sendRelay(tosend, relayUrl) } - public readonly connect: (publicKey: string, onEventId: (eventId: string) => void) => void = - async (publicKey, onEventId) => { - RelayPoolModule.connect(publicKey, onEventId) - } - public readonly add: ( relayUrl: string, resilient: number, @@ -125,10 +125,29 @@ class RelayPool { RelayPoolModule.update(relayUrl, active, globalfeed, paid, callback) } + public readonly switchLine: (online: boolean, publicKey: string, callback?: () => void) => void = async ( + online, + publicKey, + callback = () => {} + ) => { + if (online) { + RelayPoolModule.connect(publicKey, () => { + this.online = true + callback() + }) + } else { + RelayPoolModule.disconnect(() => { + this.online = false + callback() + }) + } + } + public readonly sendEvent: (event: Event, relayUrl?: string) => Promise = async ( event, relayUrl, ) => { + if (!this.online) return null if (validateEvent(event)) { if (relayUrl) { this.sendRelay(['EVENT', event], relayUrl) @@ -146,6 +165,7 @@ class RelayPool { event, relayUrl, ) => { + if (!this.online) return null if (validateEvent(event)) { this.sendRelay(['AUTH', event], relayUrl) return event @@ -159,6 +179,7 @@ class RelayPool { subId, filters, ) => { + if (!this.online) return const id = `${subId}${JSON.stringify(filters)}` if (this.subscriptions[subId]?.includes(id)) { console.log('Subscription already done!', subId) @@ -170,6 +191,7 @@ class RelayPool { } public readonly unsubscribe: (subIds: string[]) => void = async (subIds) => { + if (!this.online) return subIds.forEach((subId: string) => { this.sendAll(['CLOSE', subId]) delete this.subscriptions[subId] @@ -177,6 +199,7 @@ class RelayPool { } public readonly unsubscribeAll: () => void = async () => { + if (!this.online) return this.unsubscribe(Object.keys(this.subscriptions)) this.subscriptions = {} }