import React, { useCallback, useContext, useState, useEffect } from 'react' import { getUsers, User } from '../../Functions/DatabaseFunctions/Users' import { NativeScrollEvent, NativeSyntheticEvent, RefreshControl, StyleSheet, View, } from 'react-native' import { AppContext } from '../../Contexts/AppContext' import { getLastReply, getMainNotes, Note } from '../../Functions/DatabaseFunctions/Notes' import { handleInfinityScroll } from '../../Functions/NativeFunctions' import { UserContext } from '../../Contexts/UserContext' import { RelayPoolContext } from '../../Contexts/RelayPoolContext' import { Kind } from 'nostr-tools' import { 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 { FlashList, ListRenderItem } from '@shopify/flash-list' import { getLastReaction } from '../../Functions/DatabaseFunctions/Reactions' import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons' import { useTranslation } from 'react-i18next' interface MyFeedProps { navigation: any } export const MyFeed: React.FC = ({ navigation }) => { const theme = useTheme() const { t } = useTranslation('common') const { database, pushedTab } = useContext(AppContext) const { publicKey } = useContext(UserContext) const { lastEventId, relayPool, lastConfirmationtId } = useContext(RelayPoolContext) const initialPageSize = 10 const [notes, setNotes] = useState([]) const [pageSize, setPageSize] = useState(initialPageSize) const [refreshing, setRefreshing] = useState(false) const flashListRef = React.useRef>(null) useEffect(() => { if (pushedTab) { flashListRef.current?.scrollToIndex({ animated: true, index: 0 }) } }, [pushedTab]) useEffect(() => { subscribeNotes() loadNotes() }, []) useEffect(() => { if (relayPool && publicKey) { loadNotes() } }, [lastEventId, lastConfirmationtId]) useEffect(() => { if (pageSize > initialPageSize) { subscribeNotes(true) } }, [pageSize]) const onRefresh = useCallback(() => { setRefreshing(true) relayPool?.unsubscribe([ 'homepage-contacts-main', 'homepage-contacts-meta', 'homepage-contacts-replies', ]) subscribeNotes() }, []) const subscribeNotes: (past?: boolean) => void = async (past) => { if (!database || !publicKey) return const users: User[] = await getUsers(database, { contacts: true, order: 'created_at DESC' }) const authors: string[] = [...users.map((user) => user.id), publicKey] const message: RelayFilters = { kinds: [Kind.Text, Kind.RecommendRelay], authors, limit: pageSize, } relayPool?.subscribe('homepage-contacts-main', [message]) setRefreshing(false) } const onScroll: (event: NativeSyntheticEvent) => void = (event) => { if (handleInfinityScroll(event)) { setPageSize(pageSize + initialPageSize) } } const loadNotes: () => void = async () => { if (database && publicKey) { getMainNotes(database, publicKey, pageSize, true).then(async (notes) => { setNotes(notes) if (notes.length > 0) { const noteIds = notes.map((note) => note.id ?? '') const messages: RelayFilters[] = [ { kinds: [Kind.Metadata], authors: notes.map((note) => note.pubkey ?? ''), }, ] const lastReaction = await getLastReaction(database, { eventIds: notes.map((note) => note.id ?? ''), }) messages.push({ kinds: [Kind.Reaction], '#e': noteIds, since: lastReaction?.created_at ?? 0, }) const repostIds = notes.filter((note) => note.repost_id).map((note) => note.id ?? '') if (repostIds.length > 0) { messages.push({ kinds: [Kind.Text], '#e': repostIds, }) } relayPool?.subscribe('homepage-contacts-meta', messages) const lastReply = await getLastReply(database, { eventIds: notes.map((note) => note.id ?? ''), }) relayPool?.subscribe('homepage-contacts-replies', [ { kinds: [Kind.Text], '#e': noteIds, since: lastReply?.created_at ?? 0, }, ]) } }) } } const renderItem: ListRenderItem = ({ item }) => { return ( ) } const ListEmptyComponent = React.useMemo( () => ( {t('homeFeed.emptyTitle')} {t('homeFeed.emptyDescription')} ), [], ) return ( } onScroll={onScroll} refreshing={refreshing} ListEmptyComponent={ListEmptyComponent} horizontal={false} ListFooterComponent={ notes.length > 0 ? : <> } ref={flashListRef} /> ) } const styles = StyleSheet.create({ loading: { paddingTop: 16, }, list: { height: '100%', }, noteCard: { marginTop: 16, }, center: { alignContent: 'center', textAlign: 'center', }, blank: { justifyContent: 'space-between', height: 220, marginTop: 91, }, activityIndicator: { padding: 16, }, }) export default MyFeed