New UI last changes

This commit is contained in:
KoalaSat 2023-01-22 13:43:30 +01:00
parent 3bfcd2a048
commit 719bec36d8
No known key found for this signature in database
GPG Key ID: 2F7F61C6146AB157
16 changed files with 234 additions and 162 deletions

View File

@ -18,7 +18,7 @@ import { UserContext } from '../../Contexts/UserContext'
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons'
import { navigate } from '../../lib/Navigation'
import NostrosAvatar from '../NostrosAvatar'
import { formatPubKey } from '../../Functions/RelayFunctions/Users'
import { formatPubKey, username } from '../../Functions/RelayFunctions/Users'
export const MenuItems: React.FC = () => {
const [drawerItemIndex, setDrawerItemIndex] = React.useState<number>(-1)
@ -61,7 +61,9 @@ export const MenuItems: React.FC = () => {
{nPub && (
<Card style={styles.cardContainer}>
<Card.Content style={styles.cardContent}>
<TouchableRipple onPress={() => navigate('Profile', { pubKey: publicKey })}>
<TouchableRipple
onPress={() => navigate('Profile', { pubKey: publicKey, title: username(user) })}
>
<View style={styles.cardContent}>
<View style={styles.cardAvatar}>
<NostrosAvatar

View File

@ -28,17 +28,18 @@ import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityI
import { REGEX_SOCKET_LINK } from '../../Constants/Relay'
import { push } from '../../lib/Navigation'
import { getNpub } from '../../lib/nostr/Nip19'
import { User } from '../../Functions/DatabaseFunctions/Users'
interface NoteCardProps {
note: Note
onPressOptions?: () => void
onPressUser?: (user: User) => void
showAnswerData?: boolean
}
export const NoteCard: React.FC<NoteCardProps> = ({
note,
showAnswerData = true,
onPressOptions = () => {},
onPressUser = () => {},
}) => {
const theme = useTheme()
const { publicKey, privateKey } = React.useContext(UserContext)
@ -116,21 +117,15 @@ export const NoteCard: React.FC<NoteCardProps> = ({
</Card.Content>
</TouchableRipple>
)}
<TouchableRipple
onPress={() =>
note.kind !== EventKind.recommendServer && push('Note', { noteId: note.id })
}
>
<Card.Content style={[styles.content, { borderColor: theme.colors.onSecondary }]}>
{hide ? (
<Button mode='outlined' onPress={() => setHide(false)}>
{t('noteCard.contentWarning')}
</Button>
) : (
<TextContent event={note} />
)}
</Card.Content>
</TouchableRipple>
<Card.Content style={[styles.content, { borderColor: theme.colors.onSecondary }]}>
{hide ? (
<Button mode='outlined' onPress={() => setHide(false)}>
{t('noteCard.contentWarning')}
</Button>
) : (
<TextContent event={note} onPressUser={onPressUser} />
)}
</Card.Content>
</>
)
}
@ -187,9 +182,9 @@ export const NoteCard: React.FC<NoteCardProps> = ({
return (
note && (
<Card>
<Card style={styles.container}>
<Card.Content style={styles.title}>
<TouchableRipple onPress={onPressOptions}>
<TouchableRipple onPress={() => onPressUser({ id: note.pubkey, name: note.name })}>
<View style={styles.titleUser}>
<View>
<NostrosAvatar
@ -207,7 +202,11 @@ export const NoteCard: React.FC<NoteCardProps> = ({
</View>
</TouchableRipple>
<View>
<IconButton icon='dots-vertical' size={25} onPress={onPressOptions} />
<IconButton
icon='dots-vertical'
size={25}
onPress={() => onPressUser({ id: note.pubkey, name: note.name })}
/>
</View>
</Card.Content>
{getNoteContent()}
@ -262,7 +261,7 @@ export const NoteCard: React.FC<NoteCardProps> = ({
const styles = StyleSheet.create({
container: {
padding: 16,
flex: 1,
},
titleUsername: {
fontWeight: 'bold',

View File

@ -28,6 +28,7 @@ export const ProfileCard: React.FC<ProfileCardProps> = ({ userPubKey, bottomShee
const [isContact, setIsContact] = React.useState<boolean>()
const [showNotification, setShowNotification] = React.useState<undefined | string>()
const nPub = React.useMemo(() => getNpub(userPubKey), [userPubKey])
const username = React.useMemo(() => usernamePubKey(user?.name ?? '', nPub), [nPub, user])
React.useEffect(() => {
loadUser()
@ -66,7 +67,7 @@ export const ProfileCard: React.FC<ProfileCardProps> = ({ userPubKey, bottomShee
const goToProfile: () => void = () => {
bottomSheetRef.current?.close()
push('Profile', { pubKey: userPubKey })
push('Profile', { pubKey: userPubKey, title: username })
}
return (
@ -86,7 +87,7 @@ export const ProfileCard: React.FC<ProfileCardProps> = ({ userPubKey, bottomShee
</View>
<View>
<View style={styles.username}>
<Text variant='titleMedium'>{usernamePubKey(user?.name ?? '', nPub)}</Text>
<Text variant='titleMedium'>{username}</Text>
{/* <MaterialCommunityIcons name="check-decagram-outline" size={16} /> */}
<Text>{user?.nip05}</Text>
</View>
@ -123,7 +124,7 @@ export const ProfileCard: React.FC<ProfileCardProps> = ({ userPubKey, bottomShee
icon='message-plus-outline'
size={28}
onPress={() => {
navigate('Conversation', { pubKey: userPubKey })
navigate('Conversation', { pubKey: userPubKey, title: username })
bottomSheetRef.current?.close()
}}
/>

View File

@ -3,18 +3,18 @@ import ParsedText from 'react-native-parsed-text'
import { Event } from '../../lib/nostr/Events'
import { Linking, StyleSheet, View } from 'react-native'
import { AppContext } from '../../Contexts/AppContext'
import { getUser } from '../../Functions/DatabaseFunctions/Users'
import { getUser, User } from '../../Functions/DatabaseFunctions/Users'
import { formatPubKey } from '../../Functions/RelayFunctions/Users'
import moment from 'moment'
import { Card, Text, useTheme } from 'react-native-paper'
import { getLinkPreview } from 'link-preview-js'
import { push } from '../../lib/Navigation'
import { validImageUrl } from '../../Functions/NativeFunctions'
interface TextContentProps {
event?: Event
content?: string
preview?: boolean
onPressUser?: (user: User) => void
}
interface LinkPreviewMedia {
@ -35,7 +35,12 @@ interface LinkPreviewMedia {
favicons: string[]
}
export const TextContent: React.FC<TextContentProps> = ({ event, content, preview = true }) => {
export const TextContent: React.FC<TextContentProps> = ({
event,
content,
preview = true,
onPressUser = () => {},
}) => {
const theme = useTheme()
const { database } = useContext(AppContext)
const [userNames, setUserNames] = useState<Record<number, string>>({})
@ -55,7 +60,7 @@ export const TextContent: React.FC<TextContentProps> = ({ event, content, previe
const mentionIndex: number = parseInt(text.substring(2, text.length - 1))
const userPubKey = event.tags[mentionIndex][1]
push('Profile', { pubKey: userPubKey })
onPressUser({ id: userPubKey, name: text })
}
const renderMentionText: (matchingString: string, matches: string[]) => string = (

View File

@ -205,6 +205,7 @@ export const ContactsFeed: React.FC = () => {
<ScrollView horizontal={false}>
<View>
<FlatList
style={styles.list}
data={following}
renderItem={renderContactItem}
ItemSeparatorComponent={Divider}
@ -235,6 +236,7 @@ export const ContactsFeed: React.FC = () => {
<ScrollView horizontal={false}>
<View>
<FlatList
style={styles.list}
data={followers}
renderItem={renderContactItem}
ItemSeparatorComponent={Divider}
@ -443,6 +445,9 @@ const styles = StyleSheet.create({
tabLabel: {
margin: 8,
},
list: {
paddingBottom: 80,
},
})
export default ContactsFeed

View File

@ -109,7 +109,7 @@ export const ConversationPage: React.FC<ConversationPageProps> = ({ route }) =>
}
const onPressOtherUser: () => void = () => {
navigate('Profile', { pubKey: otherPubKey })
navigate('Profile', { pubKey: otherPubKey, title: username(otherUser) })
}
const send: () => void = () => {

View File

@ -109,11 +109,16 @@ export const ConversationsFeed: React.FC = () => {
const otherPubKey = getOtherPubKey(item, publicKey)
const user: User = users?.find((user) => user.id === otherPubKey) ?? { id: otherPubKey }
const userMame = username(user)
return (
<TouchableRipple
onPress={() =>
navigate('Conversation', { pubKey: user.id, conversationId: item.conversation_id })
navigate('Conversation', {
pubKey: user.id,
conversationId: item.conversation_id,
title: userMame,
})
}
>
<View key={user.id} style={styles.contactRow}>
@ -126,7 +131,7 @@ export const ConversationsFeed: React.FC = () => {
size={40}
/>
<View style={styles.contactName}>
<Text variant='titleSmall'>{username(user)}</Text>
<Text variant='titleSmall'>{userMame}</Text>
</View>
</View>
<View style={styles.contactInfo}>
@ -189,7 +194,7 @@ export const ConversationsFeed: React.FC = () => {
onPress={() => {
bottomSheetUserListRef.current?.close()
bottomSheetPubKeyRef.current?.close()
navigate('Conversation', { pubKey: item.id })
navigate('Conversation', { pubKey: item.id, title: username(item) })
}}
>
<View key={item.id} style={styles.contactRow}>
@ -215,6 +220,7 @@ export const ConversationsFeed: React.FC = () => {
{directMessages.length > 0 ? (
<ScrollView horizontal={false}>
<FlatList
style={styles.list}
data={directMessages}
renderItem={renderConversationItem}
ItemSeparatorComponent={Divider}
@ -303,7 +309,7 @@ export const ConversationsFeed: React.FC = () => {
mode='contained'
disabled={!sendPubKeyInput || sendPubKeyInput === ''}
onPress={() => {
navigate('Conversation', { pubKey: sendPubKeyInput })
navigate('Conversation', { pubKey: sendPubKeyInput, title: sendPubKeyInput })
bottomSheetPubKeyRef.current?.close()
}}
>
@ -356,6 +362,9 @@ const styles = StyleSheet.create({
paddingLeft: 16,
paddingRight: 16,
},
list: {
paddingBottom: 64,
},
})
export default ConversationsFeed

View File

@ -82,7 +82,11 @@ export const HomeNavigator: React.FC = () => {
onPress={() => (navigation as any as DrawerNavigationProp<{}>).openDrawer()}
/>
) : null}
<Appbar.Content title={t(`homeNavigator.${route.name}`)} />
<Appbar.Content
title={
route.params?.title ? route.params?.title : t(`homeNavigator.${route.name}`)
}
/>
{['Profile', 'Conversation'].includes(route.name) && (
<Appbar.Action
icon='dots-vertical'

View File

@ -148,8 +148,8 @@ export const HomeFeed: React.FC<HomeFeedProps> = ({ navigation }) => {
<View style={styles.noteCard} key={item.id}>
<NoteCard
note={item}
onPressOptions={() => {
setProfileCardPubKey(item.pubkey)
onPressUser={(user) => {
setProfileCardPubKey(user.id)
bottomSheetProfileRef.current?.open()
}}
/>

View File

@ -10,13 +10,12 @@ import { useTranslation } from 'react-i18next'
import ProfileCreatePage from '../../Pages/ProfileCreatePage'
import { DrawerNavigationProp } from '@react-navigation/drawer'
import RelaysPage from '../RelaysPage'
import { useState } from 'react'
export const HomeNavigator: React.FC = () => {
const theme = useTheme()
const { t } = useTranslation('common')
const [bottomSheetPage, setBottomSheetPage] = useState<'keys' | 'relays'>('keys')
const bottomSheetRef = React.useRef<RBSheet>(null)
const bottomSheetKeysRef = React.useRef<RBSheet>(null)
const bottomSheetRelaysRef = React.useRef<RBSheet>(null)
const Stack = React.useMemo(() => createStackNavigator(), [])
const cardStyleInterpolator = React.useMemo(
() =>
@ -26,8 +25,9 @@ export const HomeNavigator: React.FC = () => {
[],
)
const onPressQuestion: (pageName: string) => void = (pageName) => {
bottomSheetRef.current?.open()
setBottomSheetPage(pageName === 'Relays' ? 'relays' : 'keys')
pageName === 'Relays'
? bottomSheetRelaysRef.current?.open()
: bottomSheetKeysRef.current?.open()
}
const BottomSheetKeys = React.useMemo(
@ -60,17 +60,6 @@ export const HomeNavigator: React.FC = () => {
[],
)
const BottomSheets = {
keys: {
component: BottomSheetKeys,
height: 430,
},
relays: {
component: BottomSheetRelays,
height: 680,
},
}
return (
<>
<Stack.Navigator
@ -121,9 +110,9 @@ export const HomeNavigator: React.FC = () => {
</Stack.Group>
</Stack.Navigator>
<RBSheet
ref={bottomSheetRef}
ref={bottomSheetKeysRef}
closeOnDragDown={true}
height={BottomSheets[bottomSheetPage].height}
height={430}
customStyles={{
container: {
backgroundColor: theme.colors.background,
@ -133,7 +122,22 @@ export const HomeNavigator: React.FC = () => {
},
}}
>
{BottomSheets[bottomSheetPage].component}
{BottomSheetKeys}
</RBSheet>
<RBSheet
ref={bottomSheetRelaysRef}
closeOnDragDown={true}
height={680}
customStyles={{
container: {
backgroundColor: theme.colors.background,
padding: 16,
borderTopRightRadius: 28,
borderTopLeftRadius: 28,
},
}}
>
{BottomSheetRelays}
</RBSheet>
</>
)

View File

@ -54,7 +54,7 @@ const styles = StyleSheet.create({
justifyContent: 'center',
alignContent: 'center',
flex: 1,
paddingLeft: 50,
paddingLeft: 90,
},
})

View File

@ -145,16 +145,24 @@ export const NotePage: React.FC<NotePageProps> = ({ route }) => {
}
}
const renderItem: (note: Note) => JSX.Element = (note) => (
<View style={[styles.noteCard, { borderColor: theme.colors.onSecondary }]} key={note.id}>
<NoteCard
note={note}
onPressOptions={() => {
setProfileCardPubKey(note.pubkey)
bottomSheetProfileRef.current?.open()
}}
showAnswerData={false}
/>
const renderItem: (note: Note, index: number) => JSX.Element = (note, index) => (
<View style={styles.note} key={note.id}>
<View style={styles.noteLine}>
<View style={[styles.noteLineTop, { borderColor: theme.colors.onSecondary }]}></View>
{index < (replies?.length ?? 0) - 1 && (
<View style={[styles.noteLineBottom, { borderColor: theme.colors.onSecondary }]}></View>
)}
</View>
<View style={styles.noteCard}>
<NoteCard
note={note}
onPressUser={(user) => {
setProfileCardPubKey(user.id)
bottomSheetProfileRef.current?.open()
}}
showAnswerData={false}
/>
</View>
</View>
)
@ -272,8 +280,8 @@ export const NotePage: React.FC<NotePageProps> = ({ route }) => {
)}
</Surface>
{replies && replies.length > 0 && (
<View style={styles.list}>
{replies.map((note) => renderItem(note))}
<View style={[styles.list, { borderColor: theme.colors.onSecondary }]}>
{replies.map((note, index) => renderItem(note, index))}
{replies.length >= 10 && <ActivityIndicator style={styles.loading} animating={true} />}
</View>
)}
@ -317,6 +325,9 @@ export const NotePage: React.FC<NotePageProps> = ({ route }) => {
}
const styles = StyleSheet.create({
container: {
paddingBottom: 32,
},
title: {
paddingRight: 16,
paddingLeft: 16,
@ -343,14 +354,14 @@ const styles = StyleSheet.create({
justifyContent: 'space-around',
},
titleComment: {
borderTopWidth: 1,
padding: 16,
flexDirection: 'row',
justifyContent: 'flex-start',
},
list: {
paddingLeft: 16,
marginLeft: 16,
paddingRight: 16,
marginBottom: 180,
},
loading: {
paddingTop: 30,
@ -364,11 +375,26 @@ const styles = StyleSheet.create({
right: 16,
position: 'absolute',
},
note: {
flexDirection: 'row',
flex: 1,
},
noteCard: {
borderLeftWidth: 1,
paddingLeft: 32,
flex: 1,
paddingTop: 16,
},
noteLine: {
width: 16,
},
noteLineTop: {
borderBottomWidth: 1,
borderLeftWidth: 1,
height: 60,
},
noteLineBottom: {
borderLeftWidth: 1,
flex: 1,
},
answerData: {
flexDirection: 'row',
},

View File

@ -130,8 +130,8 @@ export const NotificationsFeed: React.FC = () => {
<View style={styles.noteCard} key={note.id}>
<NoteCard
note={note}
onPressOptions={() => {
setProfileCardPubKey(note.pubkey)
onPressUser={(user) => {
setProfileCardPubKey(user.id)
bottomSheetProfileRef.current?.open()
}}
/>

View File

@ -309,12 +309,16 @@ export const ProfileConfigPage: React.FC = () => {
label={t('profileConfigPage.name') ?? ''}
onChangeText={setName}
value={name}
style={styles.input}
/>
<TextInput
mode='outlined'
label={t('profileConfigPage.about') ?? ''}
onChangeText={setAbout}
value={about}
multiline
numberOfLines={5}
style={styles.input}
/>
<TextInput
mode='outlined'
@ -332,6 +336,7 @@ export const ProfileConfigPage: React.FC = () => {
forceTextInputFocus={false}
/>
}
style={styles.input}
/>
<TextInput
mode='outlined'
@ -350,6 +355,7 @@ export const ProfileConfigPage: React.FC = () => {
forceTextInputFocus={false}
/>
}
style={styles.input}
/>
<Button mode='contained' onPress={onPressSaveProfile} loading={isPublishingProfile}>
{t('profileConfigPage.publish')}
@ -492,7 +498,7 @@ export const ProfileConfigPage: React.FC = () => {
onIconPress={() => setShowNotification(undefined)}
onDismiss={() => setShowNotification(undefined)}
>
{t(`profileConfigPage.notifications.${showNotification}`, { nip05, lnurl })}
{t(`profileConfigPage.notifications.${showNotification}`, { nip05, lud06: lnurl })}
</Snackbar>
)}
</View>
@ -509,9 +515,11 @@ const styles = StyleSheet.create({
},
inputContainer: {
justifyContent: 'space-between',
height: 350,
paddingTop: 16,
},
input: {
marginBottom: 16,
},
cardContainer: {
width: '100%',
justifyContent: 'center',

View File

@ -173,7 +173,7 @@ export const ProfilePage: React.FC<ProfilePageProps> = ({ route }) => {
const renderItem: (note: Note) => JSX.Element = (note) => (
<View style={styles.noteCard} key={note.id}>
<NoteCard note={note} onPressOptions={() => bottomSheetProfileRef.current?.open()} />
<NoteCard note={note} onPressUser={() => bottomSheetProfileRef.current?.open()} />
</View>
)
@ -189,95 +189,99 @@ export const ProfilePage: React.FC<ProfilePageProps> = ({ route }) => {
}, [])
return (
<View style={styles.content}>
<Surface style={styles.container} elevation={1}>
<View style={styles.mainLayout}>
<View>
<NostrosAvatar
name={user?.name}
pubKey={getNpub(route.params.pubKey)}
src={user?.picture}
lud06={user?.lnurl}
size={54}
/>
</View>
<View>
<View style={styles.userName}>
<Text variant='titleMedium'>{user && username(user)}</Text>
{/* <MaterialCommunityIcons name="check-decagram-outline" size={16} /> */}
<Text>{user?.nip05}</Text>
<View>
<ScrollView
onScroll={onScroll}
horizontal={false}
showsVerticalScrollIndicator={false}
refreshControl={<RefreshControl refreshing={refreshing} onRefresh={onRefresh} />}
>
<Surface style={styles.container} elevation={1}>
<View style={styles.mainLayout}>
<View>
<NostrosAvatar
name={user?.name}
pubKey={getNpub(route.params.pubKey)}
src={user?.picture}
lud06={user?.lnurl}
size={54}
/>
</View>
<View>
<View style={styles.userName}>
<Text variant='titleMedium'>{user && username(user)}</Text>
{/* <MaterialCommunityIcons name="check-decagram-outline" size={16} /> */}
<Text>{user?.nip05}</Text>
</View>
</View>
</View>
</View>
<View>
<Text>{user?.about}</Text>
</View>
<View style={styles.mainLayout}>
{route.params.pubKey !== publicKey && (
<View>
<Text>{user?.about}</Text>
</View>
<View style={styles.mainLayout}>
{route.params.pubKey !== publicKey && (
<View style={styles.actionButton}>
<IconButton
icon={
isContact ? 'account-multiple-remove-outline' : 'account-multiple-plus-outline'
}
size={28}
onPress={() => {
isContact ? removeContact() : addContact()
}}
disabled={route.params.pubKey === publicKey}
/>
<Text>{isContact ? t('profilePage.unfollow') : t('profilePage.follow')}</Text>
</View>
)}
<View style={styles.actionButton}>
<IconButton
icon={
isContact ? 'account-multiple-remove-outline' : 'account-multiple-plus-outline'
}
icon='message-plus-outline'
size={28}
onPress={() => {
isContact ? removeContact() : addContact()
navigate('Conversation', {
pubKey: route.params.pubKey,
title: user ? username(user) : route.params.pubKey,
})
bottomSheetProfileRef.current?.close()
}}
disabled={route.params.pubKey === publicKey}
/>
<Text>{isContact ? t('profilePage.unfollow') : t('profilePage.follow')}</Text>
<Text>{t('profilePage.message')}</Text>
</View>
<View style={styles.actionButton}>
<IconButton
icon='content-copy'
size={28}
onPress={() => {
setShowNotification('copyNPub')
const profileNPud = getNpub(route.params.pubKey)
Clipboard.setString(profileNPud ?? '')
}}
/>
<Text>{t('profilePage.copyNPub')}</Text>
</View>
<View style={styles.actionButton}>
{user?.lnurl && (
<>
<IconButton
icon='lightning-bolt'
size={28}
onPress={() => setOpenLn(true)}
iconColor='#F5D112'
/>
<Text>{t('profilePage.invoice')}</Text>
</>
)}
</View>
)}
<View style={styles.actionButton}>
<IconButton
icon='message-plus-outline'
size={28}
onPress={() => {
navigate('Conversation', { pubKey: route.params.pubKey })
bottomSheetProfileRef.current?.close()
}}
/>
<Text>{t('profilePage.message')}</Text>
</View>
<View style={styles.actionButton}>
<IconButton
icon='content-copy'
size={28}
onPress={() => {
setShowNotification('copyNPub')
const profileNPud = getNpub(route.params.pubKey)
Clipboard.setString(profileNPud ?? '')
}}
/>
<Text>{t('profilePage.copyNPub')}</Text>
</Surface>
{notes && notes.length > 0 && (
<View style={styles.list}>
{notes.map((note) => renderItem(note))}
{notes.length >= 10 && <ActivityIndicator animating={true} />}
</View>
<View style={styles.actionButton}>
{user?.lnurl && (
<>
<IconButton
icon='lightning-bolt'
size={28}
onPress={() => setOpenLn(true)}
iconColor='#F5D112'
/>
<Text>{t('profilePage.invoice')}</Text>
</>
)}
</View>
</View>
</Surface>
{notes && notes.length > 0 && (
<ScrollView
onScroll={onScroll}
horizontal={false}
showsVerticalScrollIndicator={false}
refreshControl={<RefreshControl refreshing={refreshing} onRefresh={onRefresh} />}
style={styles.list}
>
{notes.map((note) => renderItem(note))}
{notes.length >= 10 && <ActivityIndicator animating={true} />}
</ScrollView>
)}
)}
</ScrollView>
{showNotification && (
<Snackbar
style={styles.snackbar}
@ -306,9 +310,6 @@ export const ProfilePage: React.FC<ProfilePageProps> = ({ route }) => {
}
const styles = StyleSheet.create({
content: {
paddingBottom: 60,
},
container: {
padding: 16,
},

View File

@ -1,5 +1,5 @@
import React, { useContext, useState } from 'react'
import { Clipboard, FlatList, ListRenderItem, StyleSheet, View } from 'react-native'
import { Clipboard, FlatList, ListRenderItem, ScrollView, StyleSheet, View } from 'react-native'
import { useTranslation } from 'react-i18next'
import { RelayPoolContext } from '../../Contexts/RelayPoolContext'
import { Relay } from '../../Functions/DatabaseFunctions/Relays'
@ -101,7 +101,13 @@ export const RelaysPage: React.FC = () => {
return (
<View style={styles.container}>
<FlatList style={styles.list} data={[...relays, ...defaultList()]} renderItem={renderItem} />
<ScrollView horizontal={false}>
<FlatList
style={styles.list}
data={[...relays, ...defaultList()]}
renderItem={renderItem}
/>
</ScrollView>
<AnimatedFAB
style={styles.fab}
icon='plus'
@ -190,9 +196,11 @@ export const RelaysPage: React.FC = () => {
const styles = StyleSheet.create({
container: {
padding: 0,
paddingBottom: 32,
},
list: {
padding: 0,
paddingBottom: 45,
},
snackbar: {
margin: 16,