nostros/frontend/Pages/RelaysPage/index.tsx

252 lines
6.9 KiB
TypeScript
Raw Normal View History

2023-01-02 21:17:16 +00:00
import {
Button,
Layout,
TopNavigation,
useTheme,
Text,
Modal,
Card,
Input,
} from '@ui-kitten/components'
2022-11-05 18:04:17 +00:00
import React, { useContext, useEffect, useState } from 'react'
2023-01-02 21:17:16 +00:00
import { RefreshControl, ScrollView, StyleSheet, TouchableOpacity } from 'react-native'
2022-11-05 18:04:17 +00:00
import { AppContext } from '../../Contexts/AppContext'
import Icon from 'react-native-vector-icons/FontAwesome5'
import { useTranslation } from 'react-i18next'
import { RelayPoolContext } from '../../Contexts/RelayPoolContext'
2022-11-15 14:07:17 +00:00
import { getRelays, Relay } from '../../Functions/DatabaseFunctions/Relays'
2023-01-02 21:17:16 +00:00
import { defaultRelays, REGEX_SOCKET_LINK } from '../../Constants/RelayConstants'
2022-11-05 18:04:17 +00:00
import { showMessage } from 'react-native-flash-message'
export const RelaysPage: React.FC = () => {
const theme = useTheme()
const { goBack, database } = useContext(AppContext)
2022-11-15 14:07:17 +00:00
const { relayPool, publicKey } = useContext(RelayPoolContext)
2022-11-05 18:04:17 +00:00
const { t } = useTranslation('common')
2022-11-06 18:57:52 +00:00
const [relays, setRelays] = useState<Relay[]>([])
2022-11-05 18:04:17 +00:00
const [loading, setLoading] = useState<boolean>(false)
2023-01-02 21:17:16 +00:00
const [showAddRelay, setShowAddRelay] = useState<boolean>(false)
const [addRelayInput, setAddRelayInput] = useState<string>('')
const [showInvalidInput, setShowInvalidInput] = useState<boolean>(false)
2022-11-05 18:04:17 +00:00
const loadRelays: () => void = () => {
if (database) {
getRelays(database).then((results) => {
if (results) {
setRelays(results)
setLoading(false)
}
})
}
}
useEffect(loadRelays, [])
const onPressBack: () => void = () => {
goBack()
}
const renderBackAction = (): JSX.Element => (
2022-11-15 14:07:17 +00:00
<Button
accessoryRight={<Icon name='arrow-left' size={16} color={theme['text-basic-color']} />}
2022-11-05 18:04:17 +00:00
onPress={onPressBack}
2022-11-15 14:07:17 +00:00
appearance='ghost'
2022-11-05 18:04:17 +00:00
/>
)
const addRelayItem: (url: string) => void = async (url) => {
2022-12-23 18:19:52 +00:00
if (relayPool && database && publicKey) {
2022-11-05 18:04:17 +00:00
setLoading(true)
2022-11-15 14:07:17 +00:00
relayPool.add(url, () => {
showMessage({
message: t('alerts.relayAdded'),
description: url,
type: 'success',
})
loadRelays()
2022-11-05 18:04:17 +00:00
})
}
}
const removeRelayItem: (url: string) => void = async (url) => {
if (relayPool && database && publicKey) {
setLoading(true)
2022-11-15 14:07:17 +00:00
relayPool.remove(url, () => {
showMessage({
message: t('alerts.relayRemoved'),
description: url,
type: 'danger',
})
loadRelays()
2022-11-05 18:04:17 +00:00
})
}
}
2023-01-02 21:17:16 +00:00
const onPressAddRelay: () => void = () => {
if ((addRelayInput.match(REGEX_SOCKET_LINK) ?? []).length > 0) {
addRelayItem(addRelayInput)
setAddRelayInput('')
setShowAddRelay(false)
setShowInvalidInput(false)
} else {
setShowInvalidInput(true)
}
}
2022-11-05 18:04:17 +00:00
const relayActions: (relay: Relay) => JSX.Element = (relay) => {
return relays?.find((item) => item.url === relay.url) ? (
<Button
status='danger'
disabled={loading}
onPress={() => removeRelayItem(relay.url)}
accessoryLeft={<Icon name='trash' size={16} color={theme['text-basic-color']} solid />}
/>
) : (
<Button
status='success'
2022-12-23 18:19:52 +00:00
disabled={loading}
2022-11-05 18:04:17 +00:00
onPress={() => addRelayItem(relay.url)}
2023-01-02 21:17:16 +00:00
accessoryLeft={<Icon name='power-off' size={16} color={theme['text-basic-color']} solid />}
2022-11-05 18:04:17 +00:00
/>
)
}
const renderItem: (relay: Relay, index: number) => JSX.Element = (relay, index) => (
<Layout style={styles.item} level='1' key={index}>
<Layout style={styles.itemBody} level='1'>
<Text category='h6'>{relay.url.split('wss://')[1].split('/')[0]}</Text>
</Layout>
<Layout style={styles.itemAction} level='1'>
{relayActions(relay)}
</Layout>
</Layout>
)
const defaultList: () => Relay[] = () => {
return defaultRelays
.filter((url) => !relays?.find((item) => item.url === url))
.map((url) => {
return {
url,
}
})
}
const styles = StyleSheet.create({
container: {
flex: 1,
marginBottom: 55,
},
actionContainer: {},
action: {
marginTop: 30,
},
item: {
height: 80,
flexDirection: 'row',
padding: 16,
borderBottomWidth: 1,
},
itemBody: {
flex: 4,
color: theme['text-basic-color'],
justifyContent: 'center',
},
itemAction: {
flex: 2,
},
text: {
color: theme['text-basic-color'],
},
2023-01-02 21:17:16 +00:00
modal: {
paddingLeft: 32,
paddingRight: 32,
width: '100%',
},
backdrop: {
backgroundColor: 'rgba(0, 0, 0, 0.5)',
},
button: {
marginTop: 31,
},
modalContainer: {
marginTop: 30,
marginBottom: 30,
paddingLeft: 12,
paddingRight: 12,
},
2022-11-05 18:04:17 +00:00
})
return (
<>
<Layout style={styles.container} level='2'>
<TopNavigation
alignment='center'
title={t('relaysPage.title')}
accessoryLeft={renderBackAction}
/>
<Layout style={styles.actionContainer} level='2'>
<ScrollView refreshControl={<RefreshControl refreshing={loading} />}>
2022-11-06 18:57:52 +00:00
{relays ? (
2022-11-05 18:04:17 +00:00
[...relays, ...defaultList()].map((item, index) => {
return renderItem(item, index)
})
) : (
<></>
)}
</ScrollView>
</Layout>
2023-01-02 21:17:16 +00:00
<Modal
style={styles.modal}
visible={showAddRelay}
backdropStyle={styles.backdrop}
onBackdropPress={() => setShowAddRelay(false)}
>
<Card disabled={true}>
<Layout style={styles.modalContainer}>
<Layout>
<Input
placeholder={t('relaysPage.addRelay.placeholder')}
value={addRelayInput}
onChangeText={setAddRelayInput}
size='large'
/>
</Layout>
{showInvalidInput && (
<Layout style={styles.button}>
<Text status='danger'>{t('relaysPage.addRelay.invalidFormat')}</Text>
</Layout>
)}
<Layout style={styles.button}>
<Button onPress={onPressAddRelay}>
{<Text>{t('relaysPage.addRelay.add')}</Text>}
</Button>
</Layout>
</Layout>
</Card>
</Modal>
2022-11-05 18:04:17 +00:00
</Layout>
2023-01-02 21:17:16 +00:00
<TouchableOpacity
style={{
borderWidth: 1,
borderColor: 'rgba(0,0,0,0.2)',
alignItems: 'center',
justifyContent: 'center',
width: 65,
position: 'absolute',
bottom: 20,
right: 20,
height: 65,
backgroundColor: theme['color-warning-500'],
borderRadius: 100,
}}
onPress={() => setShowAddRelay(true)}
>
<Icon name='plus' size={30} color={theme['text-basic-color']} solid />
</TouchableOpacity>
2022-11-05 18:04:17 +00:00
</>
)
}
export default RelaysPage