mirror of
https://github.com/KoalaSat/nostros.git
synced 2024-09-29 14:40:43 +00:00
New UI empty views (#134)
This commit is contained in:
commit
1fe73341f9
@ -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>
|
||||||
|
@ -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 = () => {
|
||||||
|
@ -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
|
|
@ -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',
|
||||||
|
@ -43,6 +43,5 @@
|
|||||||
"success": "#369734",
|
"success": "#369734",
|
||||||
"successContainer": "#369734",
|
"successContainer": "#369734",
|
||||||
"onSuccessContainer": "#96FA89"
|
"onSuccessContainer": "#96FA89"
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
@ -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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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>
|
||||||
)
|
)
|
||||||
|
@ -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,
|
||||||
|
@ -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,
|
||||||
},
|
},
|
||||||
|
@ -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}
|
||||||
|
Loading…
Reference in New Issue
Block a user