import React, { useCallback, useContext, useState, useEffect } from 'react' import { getUsers, User } from '../../Functions/DatabaseFunctions/Users' import { Dimensions, NativeScrollEvent, NativeSyntheticEvent, RefreshControl, ScrollView, StyleSheet, View, } from 'react-native' import { AppContext } from '../../Contexts/AppContext' import { getMainNotes, Note } from '../../Functions/DatabaseFunctions/Notes' import { handleInfinityScroll } from '../../Functions/NativeFunctions' import { UserContext } from '../../Contexts/UserContext' import { RelayPoolContext } from '../../Contexts/RelayPoolContext' import { EventKind } from '../../lib/nostr/Events' import { RelayFilters } from '../../lib/nostr/RelayPool/intex' import { ActivityIndicator, AnimatedFAB, Button, Text } from 'react-native-paper' import NoteCard from '../../Components/NoteCard' import RBSheet from 'react-native-raw-bottom-sheet' import ProfileCard from '../../Components/ProfileCard' import { useTheme } from '@react-navigation/native' import { navigate } from '../../lib/Navigation' import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons' import { t } from 'i18next' interface HomeFeedProps { jumpTo: (tabName: string) => void } export const HomeFeed: React.FC = ({ jumpTo }) => { const theme = useTheme() const { database } = useContext(AppContext) const { publicKey } = useContext(UserContext) const { lastEventId, relayPool, lastConfirmationtId } = useContext(RelayPoolContext) const initialPageSize = 10 const [notes, setNotes] = useState([]) const [authors, setAuthors] = useState([]) const [pageSize, setPageSize] = useState(initialPageSize) const [refreshing, setRefreshing] = useState(true) const [profileCardPubkey, setProfileCardPubKey] = useState() const bottomSheetProfileRef = React.useRef(null) useEffect(() => { if (relayPool && publicKey) { loadNotes() } }, [publicKey, relayPool, lastEventId, lastConfirmationtId]) useEffect(() => { if (pageSize > initialPageSize) { subscribeNotes(true) } }, [pageSize]) const onRefresh = useCallback(() => { setRefreshing(true) if (relayPool && publicKey) { subscribeNotes() } }, []) const subscribeNotes: (past?: boolean) => void = async (past) => { if (!database || !publicKey) return let newAuthors: string[] = authors if (newAuthors.length === 0) { const users: User[] = await getUsers(database, { contacts: true }) newAuthors = [...users.map((user) => user.id), publicKey] } const lastNotes: Note[] = await getMainNotes(database, publicKey, initialPageSize) const lastNote: Note = lastNotes[lastNotes.length - 1] const message: RelayFilters = { kinds: [EventKind.textNote, EventKind.recommendServer], authors: newAuthors, } if (lastNote && lastNotes.length >= pageSize && !past) { message.since = lastNote.created_at } else { message.limit = pageSize + initialPageSize } relayPool?.subscribe('homepage-main', [message]) relayPool?.subscribe('homepage-contacts', [ { kinds: [EventKind.petNames], authors: newAuthors, }, ]) setAuthors(newAuthors) } const onScroll: (event: NativeSyntheticEvent) => void = (event) => { if (handleInfinityScroll(event)) { setPageSize(pageSize + initialPageSize) } } const loadNotes: () => void = () => { if (database && publicKey) { getMainNotes(database, publicKey, pageSize).then((notes) => { setNotes(notes) setRefreshing(false) if (notes.length > 0) { relayPool?.subscribe('homepage-reactions', [ { kinds: [EventKind.reaction, EventKind.textNote, EventKind.recommendServer], '#e': notes.map((note) => note.id ?? ''), }, ]) } }) } } const renderItem: (note: Note) => JSX.Element = (note) => { return ( { setProfileCardPubKey(note.pubkey) bottomSheetProfileRef.current?.open() }} /> ) } const bottomSheetStyles = React.useMemo(() => { return { container: { backgroundColor: theme.colors.background, padding: 16, borderTopRightRadius: 28, borderTopLeftRadius: 28, }, draggableIcon: { backgroundColor: '#000', }, } }, []) return ( {notes && notes.length > 0 ? ( } style={styles.list} > {notes.map((note) => renderItem(note))} {notes.length >= 10 && } ) : ( {t('homeFeed.emptyTitle')} {t('homeFeed.emptyDescription')} )} navigate('Send')} animateFrom='right' iconMode='static' extended={false} /> ) } const styles = StyleSheet.create({ list: { padding: 16, }, noteCard: { marginBottom: 16, }, fab: { right: 16, position: 'absolute', }, container: { padding: 16, flex: 1, }, center: { alignContent: 'center', textAlign: 'center', }, blank: { justifyContent: 'space-between', height: 200, marginTop: 60, }, }) export default HomeFeed