import React, { useContext, useEffect, useRef, useState } from 'react' import { Button, Input, Layout, Text, TopNavigation, useTheme } from '@ui-kitten/components' import { ScrollView, StyleSheet, TouchableOpacity } from 'react-native' import { AppContext } from '../../Contexts/AppContext' import { RelayPoolContext } from '../../Contexts/RelayPoolContext' import { EventKind, Event } from '../../lib/nostr/Events' import { DirectMessage, getDirectMessages, updateConversationRead, } from '../../Functions/DatabaseFunctions/DirectMessages' import { getUser, User } from '../../Functions/DatabaseFunctions/Users' import Avatar from '../../Components/Avatar' import Icon from 'react-native-vector-icons/FontAwesome5' import { useTranslation } from 'react-i18next' import { showMessage } from 'react-native-flash-message' import { username, usersToTags } from '../../Functions/RelayFunctions/Users' import moment from 'moment' import TextContent from '../../Components/TextContent' import { encrypt, decrypt } from '../../lib/nostr/Nip04' export const ConversationPage: React.FC = () => { const theme = useTheme() const scrollViewRef = useRef() const { database, getActualPage, goBack, goToPage } = useContext(AppContext) const { relayPool, publicKey, lastEventId, privateKey } = useContext(RelayPoolContext) const conversationId = getActualPage().split('#')[1] const otherPubKey = getActualPage().split('#')[2] // State const [directMessages, setDirectMessages] = useState([]) const [sendingMessages, setSendingMessages] = useState([]) const [otherUser, setOtherUser] = useState({ id: otherPubKey }) const [user, setUser] = useState() const [input, setInput] = useState('') const { t } = useTranslation('common') useEffect(() => { loadDirectMessages() }, [lastEventId]) useEffect(() => { loadDirectMessages() subscribeDirectMessages() if (database && publicKey) { getUser(publicKey, database).then((user) => { if (user) setUser(user) }) } }, []) const loadDirectMessages: () => void = () => { if (database && publicKey) { getUser(otherPubKey, database).then((user) => { if (user) setOtherUser(user) }) getDirectMessages(database, { conversationId, order: 'ASC' }).then((results) => { if (results && results.length > 0) { setSendingMessages([]) setDirectMessages( results.map((message) => { message.content = decrypt(privateKey, otherPubKey, message.content ?? '') return message }), ) updateConversationRead(conversationId, database) } }) } } const subscribeDirectMessages: () => void = async () => { relayPool?.unsubscribeAll() if (publicKey && otherPubKey) { relayPool?.subscribe('main-channel', { kinds: [EventKind.directMessage], authors: [publicKey], '#p': [otherPubKey], }) relayPool?.subscribe('main-channel', { kinds: [EventKind.directMessage], authors: [otherPubKey], '#p': [publicKey], }) } } const onPressOtherUser: () => void = () => { goToPage(`profile#${otherPubKey}`) } const send: () => void = () => { if (input !== '' && otherPubKey && publicKey && privateKey) { const event: Event = { content: input, created_at: moment().unix(), kind: EventKind.directMessage, pubkey: publicKey, tags: usersToTags([otherUser]), } setSendingMessages((prev) => [...prev, event as DirectMessage]) setInput('') const encryptedcontent = encrypt(privateKey, otherPubKey, input) encrypt(privateKey, otherPubKey, input).then((content) => { relayPool ?.sendEvent({ ...event, content: encryptedcontent, }) .catch((err) => { showMessage({ message: t('alerts.privateMessageSendError'), description: err.message, type: 'danger', }) }) }) .catch((err) => { showMessage({ message: t('alerts.privateMessageEncryptError'), description: err.message, type: 'danger', }) }) } } const userCard: (message: DirectMessage, index: number) => JSX.Element = (message, index) => { if (!publicKey || !privateKey || !otherUser || !user) return <> return message.pubkey === otherPubKey ? ( {username(otherUser)} {moment.unix(message.created_at).format('HH:mm DD-MM-YY')} ) : ( {moment.unix(message.created_at).format('HH:mm DD-MM-YY')} {username(user)} {message.id ? ( <> ) : ( )} ) } const onPressBack: () => void = () => { relayPool?.unsubscribeAll() goBack() } const renderBackAction = (): JSX.Element => { return ( ) } export default ConversationPage