New UI empty views (#134)

This commit is contained in:
KoalaSat 2023-01-17 13:22:52 +00:00 committed by GitHub
commit 1fe73341f9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 303 additions and 127 deletions

View File

@ -66,14 +66,14 @@ export const MenuItems: React.FC = () => {
<View style={styles.cardAvatar}> <View style={styles.cardAvatar}>
<NostrosAvatar <NostrosAvatar
name={user?.name} name={user?.name}
pubKey={nPub} pubKey={user?.id ?? ''}
src={user?.picture} src={user?.picture}
lud06={user?.lnurl} lud06={user?.lnurl}
/> />
</View> </View>
<View> <View>
<Text variant='titleMedium'>{user?.name}</Text> <Text variant='titleMedium'>{user?.name}</Text>
<Text>{formatPubKey(nPub)}</Text> <Text>{formatPubKey(user?.id ?? '')}</Text>
</View> </View>
</View> </View>
</TouchableRipple> </TouchableRipple>

View File

@ -18,7 +18,7 @@ export const NostrosAvatar: React.FC<NostrosAvatarProps> = ({
lud06, lud06,
}) => { }) => {
const theme = useTheme() const theme = useTheme()
const displayName = name && name !== '' ? name : pubKey const displayName = name && name !== '' ? name : pubKey ?? ''
const hasLud06 = lud06 && lud06 !== '' const hasLud06 = lud06 && lud06 !== ''
const lud06IconSize = size / 2.85 const lud06IconSize = size / 2.85
const validImage: () => boolean = () => { const validImage: () => boolean = () => {

View File

@ -1,36 +0,0 @@
import React from 'react'
import { StyleSheet } from 'react-native'
import { Snackbar } from 'react-native-paper'
interface NostrosNotificationProps {
children: React.ReactNode
showNotification: string | undefined
setShowNotification: (showNotification: string | undefined) => void
}
export const NostrosNotification: React.FC<NostrosNotificationProps> = ({
children,
showNotification,
setShowNotification,
}) => {
return (
<Snackbar
style={styles.snackbar}
visible={showNotification !== undefined}
duration={Snackbar.DURATION_SHORT}
onIconPress={() => setShowNotification(undefined)}
onDismiss={() => setShowNotification(undefined)}
>
{children}
</Snackbar>
)
}
const styles = StyleSheet.create({
snackbar: {
margin: 16,
bottom: 70,
},
})
export default NostrosNotification

View File

@ -2,14 +2,13 @@ import { t } from 'i18next'
import { npubEncode } from 'nostr-tools/nip19' import { npubEncode } from 'nostr-tools/nip19'
import * as React from 'react' import * as React from 'react'
import { Clipboard, StyleSheet, View } from 'react-native' import { Clipboard, StyleSheet, View } from 'react-native'
import { Card, IconButton, Text } from 'react-native-paper' import { Card, IconButton, Snackbar, Text } from 'react-native-paper'
import { AppContext } from '../../Contexts/AppContext' import { AppContext } from '../../Contexts/AppContext'
import { RelayPoolContext } from '../../Contexts/RelayPoolContext' import { RelayPoolContext } from '../../Contexts/RelayPoolContext'
import { UserContext } from '../../Contexts/UserContext' import { UserContext } from '../../Contexts/UserContext'
import { getUser, updateUserContact, User } from '../../Functions/DatabaseFunctions/Users' import { getUser, updateUserContact, User } from '../../Functions/DatabaseFunctions/Users'
import { populatePets } from '../../Functions/RelayFunctions/Users' import { populatePets } from '../../Functions/RelayFunctions/Users'
import NostrosAvatar from '../NostrosAvatar' import NostrosAvatar from '../NostrosAvatar'
import NostrosNotification from '../NostrosNotification'
import LnPayment from '../LnPayment' import LnPayment from '../LnPayment'
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons' import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons'
import { navigate, push } from '../../lib/Navigation' import { navigate, push } from '../../lib/Navigation'
@ -94,7 +93,7 @@ export const ProfileCard: React.FC<ProfileCardProps> = ({ userPubKey, bottomShee
</View> </View>
<View> <View>
<Text> <Text>
{`${user?.about?.slice(0, 75)}${ {`${user?.about ? user?.about?.slice(0, 75) : ''}${
user?.about && user?.about?.length > 75 ? ' ...' : '' user?.about && user?.about?.length > 75 ? ' ...' : ''
}`} }`}
</Text> </Text>
@ -156,12 +155,15 @@ export const ProfileCard: React.FC<ProfileCardProps> = ({ userPubKey, bottomShee
</View> </View>
</View> </View>
{showNotification && ( {showNotification && (
<NostrosNotification <Snackbar
showNotification={showNotification} style={styles.snackbar}
setShowNotification={setShowNotification} visible={showNotification !== undefined}
duration={Snackbar.DURATION_SHORT}
onIconPress={() => setShowNotification(undefined)}
onDismiss={() => setShowNotification(undefined)}
> >
<Text>{t(`profileCard.notifications.${showNotification}`)}</Text> {t(`profileCard.notifications.${showNotification}`)}
</NostrosNotification> </Snackbar>
)} )}
<LnPayment setOpen={setOpenLn} open={openLn} user={user} /> <LnPayment setOpen={setOpenLn} open={openLn} user={user} />
</View> </View>
@ -172,6 +174,10 @@ const styles = StyleSheet.create({
container: { container: {
padding: 16, padding: 16,
}, },
snackbar: {
margin: 16,
width: '100%',
},
contacts: { contacts: {
flexDirection: 'row', flexDirection: 'row',
alignItems: 'center', alignItems: 'center',

View File

@ -43,6 +43,5 @@
"success": "#369734", "success": "#369734",
"successContainer": "#369734", "successContainer": "#369734",
"onSuccessContainer": "#96FA89" "onSuccessContainer": "#96FA89"
} }
} }

View File

@ -60,7 +60,13 @@ export const UserContextProvider = ({ children }: UserContextProviderProps): JSX
const reloadUser: () => void = () => { const reloadUser: () => void = () => {
if (database && publicKey) { if (database && publicKey) {
getUser(publicKey, database).then((result) => { getUser(publicKey, database).then((result) => {
if (result) setUser(result) if (result) {
setUser(result)
} else {
setUser({
id: publicKey,
})
}
}) })
getContactsCount(database).then(setContantsCount) getContactsCount(database).then(setContantsCount)
getFollowersCount(database).then(setFollowersCount) getFollowersCount(database).then(setFollowersCount)

View File

@ -66,6 +66,11 @@
"generateInvoice": "Generate invoice", "generateInvoice": "Generate invoice",
"cancel": "Cancel" "cancel": "Cancel"
}, },
"notificationsFeed": {
"emptyTitle": "You don't have notifications",
"emptyDescription": "Write a message to get replies and reactions.",
"emptyButton": "Write a message"
},
"profileCreatePage": { "profileCreatePage": {
"notifications": { "notifications": {
"copied": "Private key copied.\n\nSave this key on a safe place." "copied": "Private key copied.\n\nSave this key on a safe place."
@ -90,10 +95,17 @@
}, },
"contactsFeed": { "contactsFeed": {
"notifications": { "notifications": {
"keyCopied": "Public key copied.",
"contactAdded": "Profile followed.", "contactAdded": "Profile followed.",
"addContactError": "There was an error publishing your changes.", "addContactError": "There was an error publishing your changes.",
"contactRemoved": "Profile unfollowed." "contactRemoved": "Profile unfollowed."
}, },
"emptyTitleFollowing": "You are not following no one",
"emptyDescriptionFollowing": "Follow other profiles to see content.",
"emptyButtonFollowing": "Paste public key",
"emptyTitleFollower": "You have no followers",
"emptyDescriptionFollower": "Share your public key so people can start following you.",
"emptyButtonFollower": "Copy public key",
"cancel": "Cancelar", "cancel": "Cancelar",
"addContact": "Añadir contacto", "addContact": "Añadir contacto",
"addContactDescription": "Pega la clave pública de quien desees añadir.", "addContactDescription": "Pega la clave pública de quien desees añadir.",
@ -108,6 +120,11 @@
"nostr": "nostr", "nostr": "nostr",
"nips": "NIPs" "nips": "NIPs"
}, },
"homeFeed": {
"emptyTitle": "You are not following no one",
"emptyDescription": "Follow other profiles to see content.",
"emptyButton": "Go to contacts"
},
"relaysPage": { "relaysPage": {
"labelAdd": "Dirección de relay", "labelAdd": "Dirección de relay",
"cancel": "Cancelar", "cancel": "Cancelar",
@ -125,8 +142,8 @@
"nsecCopied": "Clave secreta copiada.", "nsecCopied": "Clave secreta copiada.",
"npubCopied": "Clave pública copiada.", "npubCopied": "Clave pública copiada.",
"profilePublished": "Perfil publicado.", "profilePublished": "Perfil publicado.",
"lud06Published": "LUD-06 publicado.", "lud06Published": "LUD-06 publicado.\n\n{{lud06}}",
"nip05Published": "NIP-05 publicado.", "nip05Published": "NIP-05 publicado.\n\n{{nip05}}",
"picturePublished": "Picture publicado.", "picturePublished": "Picture publicado.",
"connectionError": "Error de conexión" "connectionError": "Error de conexión"
}, },
@ -181,12 +198,15 @@
"copyNPub": "Copiar clave" "copyNPub": "Copiar clave"
}, },
"conversationsFeed": { "conversationsFeed": {
"openMessage": "Iniciar conversación", "openMessage": "Start conversation",
"openMessageLabel": "Clave pública", "openMessageLabel": "Public key",
"openMessageDescription": "Pega una clave pública para iniciar una conversación.", "openMessageDescription": "Paste a public key to start a conversation.",
"openMessageTitle": "Iniciar conversación con clave pública", "openMessageTitle": "Start conversation with public key",
"addPubKey": "Iniciar conversación con clave pública", "addPubKey": "Start conversation with public key",
"newMessageContact": "Iniciar conversación con contacto" "newMessageContact": "Start conversation with contact",
"emptyTitle": "You don't have any message",
"emptyDescription": "Write direct messages to your contacts or others.",
"emptyButton": "Open a conversation"
} }
} }
} }

View File

@ -24,6 +24,7 @@ import {
AnimatedFAB, AnimatedFAB,
Button, Button,
Divider, Divider,
Snackbar,
Text, Text,
TextInput, TextInput,
TouchableRipple, TouchableRipple,
@ -33,11 +34,11 @@ import { Tabs, TabScreen } from 'react-native-paper-tabs'
import NostrosAvatar from '../../Components/NostrosAvatar' import NostrosAvatar from '../../Components/NostrosAvatar'
import { navigate } from '../../lib/Navigation' import { navigate } from '../../lib/Navigation'
import RBSheet from 'react-native-raw-bottom-sheet' import RBSheet from 'react-native-raw-bottom-sheet'
import NostrosNotification from '../../Components/NostrosNotification' import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons'
export const ContactsFeed: React.FC = () => { export const ContactsFeed: React.FC = () => {
const { database } = useContext(AppContext) const { database } = useContext(AppContext)
const { publicKey, setContantsCount, setFollowersCount } = React.useContext(UserContext) const { publicKey, setContantsCount, setFollowersCount, nPub } = React.useContext(UserContext)
const { relayPool, lastEventId } = useContext(RelayPoolContext) const { relayPool, lastEventId } = useContext(RelayPoolContext)
const theme = useTheme() const theme = useTheme()
const bottomSheetAddContactRef = React.useRef<RBSheet>(null) const bottomSheetAddContactRef = React.useRef<RBSheet>(null)
@ -192,6 +193,7 @@ export const ContactsFeed: React.FC = () => {
> >
<TabScreen label={t('contactsFeed.following', { count: following.length })}> <TabScreen label={t('contactsFeed.following', { count: following.length })}>
<View style={styles.container}> <View style={styles.container}>
{following.length > 0 ? (
<ScrollView horizontal={false}> <ScrollView horizontal={false}>
<View> <View>
<FlatList <FlatList
@ -201,10 +203,33 @@ export const ContactsFeed: React.FC = () => {
/> />
</View> </View>
</ScrollView> </ScrollView>
) : (
<View style={styles.blank}>
<MaterialCommunityIcons
name='account-group-outline'
size={64}
style={styles.center}
/>
<Text variant='headlineSmall' style={styles.center}>
{t('contactsFeed.emptyTitleFollowing')}
</Text>
<Text variant='bodyMedium' style={styles.center}>
{t('contactsFeed.emptyDescriptionFollowing')}
</Text>
<Button
mode='contained'
compact
onPress={() => bottomSheetAddContactRef.current?.open()}
>
{t('contactsFeed.emptyButtonFollowing')}
</Button>
</View>
)}
</View> </View>
</TabScreen> </TabScreen>
<TabScreen label={t('contactsFeed.followers', { count: followers.length })}> <TabScreen label={t('contactsFeed.followers', { count: followers.length })}>
<View style={styles.container}> <View style={styles.container}>
{followers.length > 0 ? (
<ScrollView horizontal={false}> <ScrollView horizontal={false}>
<View> <View>
<FlatList <FlatList
@ -214,6 +239,31 @@ export const ContactsFeed: React.FC = () => {
/> />
</View> </View>
</ScrollView> </ScrollView>
) : (
<View style={styles.blank}>
<MaterialCommunityIcons
name='account-group-outline'
size={64}
style={styles.center}
/>
<Text variant='headlineSmall' style={styles.center}>
{t('contactsFeed.emptyTitleFollower')}
</Text>
<Text variant='bodyMedium' style={styles.center}>
{t('contactsFeed.emptyDescriptionFollower')}
</Text>
<Button
mode='contained'
compact
onPress={() => {
setShowNotification('keyCopied')
Clipboard.setString(nPub ?? '')
}}
>
{t('contactsFeed.emptyButtonFollower')}
</Button>
</View>
)}
</View> </View>
</TabScreen> </TabScreen>
</Tabs> </Tabs>
@ -269,12 +319,15 @@ export const ContactsFeed: React.FC = () => {
</View> </View>
</RBSheet> </RBSheet>
{showNotification && ( {showNotification && (
<NostrosNotification <Snackbar
showNotification={showNotification} style={styles.snackbar}
setShowNotification={setShowNotification} visible={showNotification !== undefined}
duration={Snackbar.DURATION_SHORT}
onIconPress={() => setShowNotification(undefined)}
onDismiss={() => setShowNotification(undefined)}
> >
<Text>{t(`contactsFeed.notifications.${showNotification}`)}</Text> {t(`contactsFeed.notifications.${showNotification}`)}
</NostrosNotification> </Snackbar>
)} )}
</> </>
) )
@ -284,6 +337,10 @@ const styles = StyleSheet.create({
container: { container: {
flex: 1, flex: 1,
}, },
snackbar: {
margin: 16,
marginBottom: 95,
},
contactRow: { contactRow: {
paddingLeft: 16, paddingLeft: 16,
paddingRight: 16, paddingRight: 16,
@ -306,6 +363,16 @@ const styles = StyleSheet.create({
right: 16, right: 16,
position: 'absolute', position: 'absolute',
}, },
center: {
alignContent: 'center',
textAlign: 'center',
},
blank: {
justifyContent: 'space-between',
height: 232,
marginTop: 12,
padding: 16,
},
}) })
export default ContactsFeed export default ContactsFeed

View File

@ -158,6 +158,7 @@ export const ConversationsFeed: React.FC = () => {
/> />
), ),
onPress: async () => bottomSheetUserListRef.current?.open(), onPress: async () => bottomSheetUserListRef.current?.open(),
disabled: users?.length === 0,
}, },
{ {
key: 2, key: 2,
@ -168,6 +169,7 @@ export const ConversationsFeed: React.FC = () => {
/> />
), ),
onPress: async () => bottomSheetPubKeyRef.current?.open(), onPress: async () => bottomSheetPubKeyRef.current?.open(),
disabled: false,
}, },
] ]
}, []) }, [])
@ -199,7 +201,8 @@ export const ConversationsFeed: React.FC = () => {
) )
return ( return (
<View> <View style={styles.container}>
{directMessages.length > 0 ? (
<ScrollView horizontal={false}> <ScrollView horizontal={false}>
<FlatList <FlatList
data={directMessages} data={directMessages}
@ -207,6 +210,20 @@ export const ConversationsFeed: React.FC = () => {
ItemSeparatorComponent={Divider} ItemSeparatorComponent={Divider}
/> />
</ScrollView> </ScrollView>
) : (
<View style={styles.blank}>
<MaterialCommunityIcons name='message-outline' size={64} style={styles.center} />
<Text variant='headlineSmall' style={styles.center}>
{t('conversationsFeed.emptyTitle')}
</Text>
<Text variant='bodyMedium' style={styles.center}>
{t('conversationsFeed.emptyDescription')}
</Text>
<Button mode='contained' compact onPress={() => bottomSheetCreateRef.current?.open()}>
{t('conversationsFeed.emptyButton')}
</Button>
</View>
)}
<AnimatedFAB <AnimatedFAB
style={[styles.fab, { top: Dimensions.get('window').height - 220 }]} style={[styles.fab, { top: Dimensions.get('window').height - 220 }]}
icon='pencil-outline' icon='pencil-outline'
@ -232,6 +249,7 @@ export const ConversationsFeed: React.FC = () => {
title={item.title} title={item.title}
onPress={item.onPress} onPress={item.onPress}
left={item.left} left={item.left}
disabled={item.disabled}
/> />
) )
}} }}
@ -290,6 +308,7 @@ export const ConversationsFeed: React.FC = () => {
const styles = StyleSheet.create({ const styles = StyleSheet.create({
container: { container: {
flex: 1, flex: 1,
padding: 16,
}, },
contactRow: { contactRow: {
paddingLeft: 16, paddingLeft: 16,
@ -317,6 +336,15 @@ const styles = StyleSheet.create({
right: 16, right: 16,
position: 'absolute', position: 'absolute',
}, },
center: {
alignContent: 'center',
textAlign: 'center',
},
blank: {
justifyContent: 'space-between',
height: 200,
marginTop: 60,
},
}) })
export default ConversationsFeed export default ConversationsFeed

View File

@ -16,14 +16,20 @@ import { UserContext } from '../../Contexts/UserContext'
import { RelayPoolContext } from '../../Contexts/RelayPoolContext' import { RelayPoolContext } from '../../Contexts/RelayPoolContext'
import { EventKind } from '../../lib/nostr/Events' import { EventKind } from '../../lib/nostr/Events'
import { RelayFilters } from '../../lib/nostr/RelayPool/intex' import { RelayFilters } from '../../lib/nostr/RelayPool/intex'
import { ActivityIndicator, AnimatedFAB } from 'react-native-paper' import { ActivityIndicator, AnimatedFAB, Button, Text } from 'react-native-paper'
import NoteCard from '../../Components/NoteCard' import NoteCard from '../../Components/NoteCard'
import RBSheet from 'react-native-raw-bottom-sheet' import RBSheet from 'react-native-raw-bottom-sheet'
import ProfileCard from '../../Components/ProfileCard' import ProfileCard from '../../Components/ProfileCard'
import { useTheme } from '@react-navigation/native' import { useTheme } from '@react-navigation/native'
import { navigate } from '../../lib/Navigation' import { navigate } from '../../lib/Navigation'
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons'
import { t } from 'i18next'
export const HomeFeed: React.FC = () => { interface HomeFeedProps {
jumpTo: (tabName: string) => void
}
export const HomeFeed: React.FC<HomeFeedProps> = ({ jumpTo }) => {
const theme = useTheme() const theme = useTheme()
const { database } = useContext(AppContext) const { database } = useContext(AppContext)
const { publicKey } = useContext(UserContext) const { publicKey } = useContext(UserContext)
@ -139,8 +145,8 @@ export const HomeFeed: React.FC = () => {
}, []) }, [])
return ( return (
<> <View style={styles.container}>
{notes && notes.length > 0 && ( {notes && notes.length > 0 ? (
<ScrollView <ScrollView
onScroll={onScroll} onScroll={onScroll}
horizontal={false} horizontal={false}
@ -151,6 +157,19 @@ export const HomeFeed: React.FC = () => {
{notes.map((note) => renderItem(note))} {notes.map((note) => renderItem(note))}
{notes.length >= 10 && <ActivityIndicator animating={true} />} {notes.length >= 10 && <ActivityIndicator animating={true} />}
</ScrollView> </ScrollView>
) : (
<View style={styles.blank}>
<MaterialCommunityIcons name='account-group-outline' size={64} style={styles.center} />
<Text variant='headlineSmall' style={styles.center}>
{t('homeFeed.emptyTitle')}
</Text>
<Text variant='bodyMedium' style={styles.center}>
{t('homeFeed.emptyDescription')}
</Text>
<Button mode='contained' compact onPress={() => jumpTo('contacts')}>
{t('homeFeed.emptyButton')}
</Button>
</View>
)} )}
<AnimatedFAB <AnimatedFAB
style={[styles.fab, { top: Dimensions.get('window').height - 220 }]} style={[styles.fab, { top: Dimensions.get('window').height - 220 }]}
@ -169,7 +188,7 @@ export const HomeFeed: React.FC = () => {
> >
<ProfileCard userPubKey={profileCardPubkey ?? ''} bottomSheetRef={bottomSheetProfileRef} /> <ProfileCard userPubKey={profileCardPubkey ?? ''} bottomSheetRef={bottomSheetProfileRef} />
</RBSheet> </RBSheet>
</> </View>
) )
} }
@ -184,6 +203,19 @@ const styles = StyleSheet.create({
right: 16, right: 16,
position: 'absolute', position: 'absolute',
}, },
container: {
padding: 16,
flex: 1,
},
center: {
alignContent: 'center',
textAlign: 'center',
},
blank: {
justifyContent: 'space-between',
height: 200,
marginTop: 60,
},
}) })
export default HomeFeed export default HomeFeed

View File

@ -15,11 +15,15 @@ import { EventKind } from '../../lib/nostr/Events'
import { handleInfinityScroll } from '../../Functions/NativeFunctions' import { handleInfinityScroll } from '../../Functions/NativeFunctions'
import { UserContext } from '../../Contexts/UserContext' import { UserContext } from '../../Contexts/UserContext'
import RBSheet from 'react-native-raw-bottom-sheet' import RBSheet from 'react-native-raw-bottom-sheet'
import { ActivityIndicator, useTheme } from 'react-native-paper' import { ActivityIndicator, Button, Text, useTheme } from 'react-native-paper'
import ProfileCard from '../../Components/ProfileCard' import ProfileCard from '../../Components/ProfileCard'
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons'
import { useTranslation } from 'react-i18next'
import { navigate } from '../../lib/Navigation'
export const NotificationsFeed: React.FC = () => { export const NotificationsFeed: React.FC = () => {
const theme = useTheme() const theme = useTheme()
const { t } = useTranslation('common')
const { database } = useContext(AppContext) const { database } = useContext(AppContext)
const { publicKey } = useContext(UserContext) const { publicKey } = useContext(UserContext)
const initialPageSize = 10 const initialPageSize = 10
@ -134,18 +138,30 @@ export const NotificationsFeed: React.FC = () => {
}, []) }, [])
return ( return (
<> <View style={styles.container}>
{notes && notes.length > 0 && ( {notes && notes.length > 0 ? (
<ScrollView <ScrollView
onScroll={onScroll} onScroll={onScroll}
horizontal={false} horizontal={false}
showsVerticalScrollIndicator={false} showsVerticalScrollIndicator={false}
refreshControl={<RefreshControl refreshing={refreshing} onRefresh={onRefresh} />} refreshControl={<RefreshControl refreshing={refreshing} onRefresh={onRefresh} />}
style={styles.list}
> >
{notes.map((note) => renderItem(note))} {notes.map((note) => renderItem(note))}
{notes.length >= 10 && <ActivityIndicator animating={true} />} {notes.length >= 10 && <ActivityIndicator animating={true} />}
</ScrollView> </ScrollView>
) : (
<View style={styles.blank}>
<MaterialCommunityIcons name='message-outline' size={64} style={styles.center} />
<Text variant='headlineSmall' style={styles.center}>
{t('notificationsFeed.emptyTitle')}
</Text>
<Text variant='bodyMedium' style={styles.center}>
{t('notificationsFeed.emptyDescription')}
</Text>
<Button mode='contained' compact onPress={() => navigate('Send')}>
{t('notificationsFeed.emptyButton')}
</Button>
</View>
)} )}
<RBSheet <RBSheet
ref={bottomSheetProfileRef} ref={bottomSheetProfileRef}
@ -155,17 +171,27 @@ export const NotificationsFeed: React.FC = () => {
> >
<ProfileCard userPubKey={profileCardPubkey ?? ''} bottomSheetRef={bottomSheetProfileRef} /> <ProfileCard userPubKey={profileCardPubkey ?? ''} bottomSheetRef={bottomSheetProfileRef} />
</RBSheet> </RBSheet>
</> </View>
) )
} }
const styles = StyleSheet.create({ const styles = StyleSheet.create({
list: { container: {
flex: 1,
padding: 16, padding: 16,
}, },
noteCard: { noteCard: {
marginBottom: 16, marginBottom: 16,
}, },
center: {
alignContent: 'center',
textAlign: 'center',
},
blank: {
justifyContent: 'space-between',
height: 200,
marginTop: 60,
},
}) })
export default NotificationsFeed export default NotificationsFeed

View File

@ -15,10 +15,10 @@ import {
Text, Text,
TouchableRipple, TouchableRipple,
TextInput, TextInput,
Snackbar,
} from 'react-native-paper' } from 'react-native-paper'
import { RelayPoolContext } from '../../Contexts/RelayPoolContext' import { RelayPoolContext } from '../../Contexts/RelayPoolContext'
import RBSheet from 'react-native-raw-bottom-sheet' import RBSheet from 'react-native-raw-bottom-sheet'
import NostrosNotification from '../../Components/NostrosNotification'
import NostrosAvatar from '../../Components/NostrosAvatar' import NostrosAvatar from '../../Components/NostrosAvatar'
export const ProfileConfigPage: React.FC = () => { export const ProfileConfigPage: React.FC = () => {
@ -478,14 +478,15 @@ export const ProfileConfigPage: React.FC = () => {
</View> </View>
</RBSheet> </RBSheet>
{showNotification && ( {showNotification && (
<NostrosNotification <Snackbar
showNotification={showNotification} style={styles.snackbar}
setShowNotification={setShowNotification} visible={showNotification !== undefined}
duration={Snackbar.DURATION_SHORT}
onIconPress={() => setShowNotification(undefined)}
onDismiss={() => setShowNotification(undefined)}
> >
<Text>{t(`profileConfigPage.notifications.${showNotification}`)}</Text> {t(`profileConfigPage.notifications.${showNotification}`, { nip05, lnurl })}
{showNotification === 'nip05Published' && <Text>{nip05}</Text>} </Snackbar>
{showNotification === 'lud06Published' && <Text>{lnurl}</Text>}
</NostrosNotification>
)} )}
</View> </View>
) )

View File

@ -65,7 +65,12 @@ export const ProfileCreatePage: React.FC<ProfileCreatePageProps> = ({ navigation
</Text> </Text>
<Text style={{ color: '#FFDCBB' }}>{t('profileCreatePage.warningDescription')}</Text> <Text style={{ color: '#FFDCBB' }}>{t('profileCreatePage.warningDescription')}</Text>
<View style={styles.warningActionOuterLayout}> <View style={styles.warningActionOuterLayout}>
<Button style={styles.warningAction} textColor='#FFDCBB' mode='text' onPress={copyContent}> <Button
style={styles.warningAction}
textColor='#FFDCBB'
mode='text'
onPress={copyContent}
>
{t('profileCreatePage.warningAction')} {t('profileCreatePage.warningAction')}
</Button> </Button>
</View> </View>
@ -97,7 +102,7 @@ const styles = StyleSheet.create({
}, },
snackbar: { snackbar: {
margin: 16, margin: 16,
width: '100%' width: '100%',
}, },
warning: { warning: {
borderRadius: 4, borderRadius: 4,

View File

@ -8,7 +8,14 @@ import {
StyleSheet, StyleSheet,
View, View,
} from 'react-native' } from 'react-native'
import { Surface, Text, IconButton, ActivityIndicator, useTheme } from 'react-native-paper' import {
Surface,
Text,
IconButton,
ActivityIndicator,
useTheme,
Snackbar,
} from 'react-native-paper'
import NostrosAvatar from '../../Components/NostrosAvatar' import NostrosAvatar from '../../Components/NostrosAvatar'
import { AppContext } from '../../Contexts/AppContext' import { AppContext } from '../../Contexts/AppContext'
import { UserContext } from '../../Contexts/UserContext' import { UserContext } from '../../Contexts/UserContext'
@ -16,9 +23,8 @@ import { RelayPoolContext } from '../../Contexts/RelayPoolContext'
import { getNotes, Note } from '../../Functions/DatabaseFunctions/Notes' import { getNotes, Note } from '../../Functions/DatabaseFunctions/Notes'
import { getUser, updateUserContact, User } from '../../Functions/DatabaseFunctions/Users' import { getUser, updateUserContact, User } from '../../Functions/DatabaseFunctions/Users'
import { EventKind } from '../../lib/nostr/Events' import { EventKind } from '../../lib/nostr/Events'
import { populatePets } from '../../Functions/RelayFunctions/Users' import { populatePets, username } from '../../Functions/RelayFunctions/Users'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import NostrosNotification from '../../Components/NostrosNotification'
import { npubEncode } from 'nostr-tools/nip19' import { npubEncode } from 'nostr-tools/nip19'
import { RelayFilters } from '../../lib/nostr/RelayPool/intex' import { RelayFilters } from '../../lib/nostr/RelayPool/intex'
import NoteCard from '../../Components/NoteCard' import NoteCard from '../../Components/NoteCard'
@ -86,6 +92,10 @@ export const ProfilePage: React.FC<ProfilePageProps> = ({ route }) => {
if (result) { if (result) {
setUser(result) setUser(result)
setIsContact(result?.contact) setIsContact(result?.contact)
} else if (route.params.pubKey === publicKey) {
setUser({
id: publicKey,
})
} }
}) })
} }
@ -97,12 +107,14 @@ export const ProfilePage: React.FC<ProfilePageProps> = ({ route }) => {
(results) => { (results) => {
setNotes(results) setNotes(results)
setRefreshing(false) setRefreshing(false)
if (results.length > 0) {
relayPool?.subscribe('answers-profile', [ relayPool?.subscribe('answers-profile', [
{ {
kinds: [EventKind.reaction, EventKind.textNote, EventKind.recommendServer], kinds: [EventKind.reaction, EventKind.textNote, EventKind.recommendServer],
'#e': results.map((note) => note.id ?? ''), '#e': results.map((note) => note.id ?? ''),
}, },
]) ])
}
}, },
) )
} }
@ -189,7 +201,7 @@ export const ProfilePage: React.FC<ProfilePageProps> = ({ route }) => {
</View> </View>
<View> <View>
<View style={styles.userName}> <View style={styles.userName}>
<Text variant='titleMedium'>{user?.name}</Text> <Text variant='titleMedium'>{user && username(user)}</Text>
{/* <MaterialCommunityIcons name="check-decagram-outline" size={16} /> */} {/* <MaterialCommunityIcons name="check-decagram-outline" size={16} /> */}
</View> </View>
<Text>{user?.nip05}</Text> <Text>{user?.nip05}</Text>
@ -265,12 +277,15 @@ export const ProfilePage: React.FC<ProfilePageProps> = ({ route }) => {
</ScrollView> </ScrollView>
)} )}
{showNotification && ( {showNotification && (
<NostrosNotification <Snackbar
showNotification={showNotification} style={styles.snackbar}
setShowNotification={setShowNotification} visible={showNotification !== undefined}
duration={Snackbar.DURATION_SHORT}
onIconPress={() => setShowNotification(undefined)}
onDismiss={() => setShowNotification(undefined)}
> >
<Text>{t(`profilePage.${showNotification}`)}</Text> {t(`profilePage.${showNotification}`)}
</NostrosNotification> </Snackbar>
)} )}
<LnPayment setOpen={setOpenLn} open={openLn} user={user} /> <LnPayment setOpen={setOpenLn} open={openLn} user={user} />
<RBSheet <RBSheet
@ -313,6 +328,10 @@ const styles = StyleSheet.create({
alignItems: 'center', alignItems: 'center',
width: 100, width: 100,
}, },
snackbar: {
margin: 16,
bottom: 70,
},
list: { list: {
padding: 16, padding: 16,
}, },

View File

@ -14,9 +14,9 @@ import {
TextInput, TextInput,
IconButton, IconButton,
Divider, Divider,
Snackbar,
} from 'react-native-paper' } from 'react-native-paper'
import RBSheet from 'react-native-raw-bottom-sheet' import RBSheet from 'react-native-raw-bottom-sheet'
import NostrosNotification from '../../Components/NostrosNotification'
export const RelaysPage: React.FC = () => { export const RelaysPage: React.FC = () => {
const defaultRelayInput = React.useMemo(() => 'wss://', []) const defaultRelayInput = React.useMemo(() => 'wss://', [])
@ -111,12 +111,15 @@ export const RelaysPage: React.FC = () => {
extended={false} extended={false}
/> />
{showNotification && ( {showNotification && (
<NostrosNotification <Snackbar
showNotification={showNotification} style={styles.snackbar}
setShowNotification={setShowNotification} visible={showNotification !== undefined}
duration={Snackbar.DURATION_SHORT}
onIconPress={() => setShowNotification(undefined)}
onDismiss={() => setShowNotification(undefined)}
> >
{t(`relaysPage.notifications.${showNotification}`)} {t(`relaysPage.notifications.${showNotification}`)}
</NostrosNotification> </Snackbar>
)} )}
<RBSheet <RBSheet
ref={bottomSheetAddRef} ref={bottomSheetAddRef}