From 822d333401c6eb295cc2c9426e8c6355e693534f Mon Sep 17 00:00:00 2001 From: balzack Date: Fri, 23 Sep 2022 23:31:46 -0700 Subject: [PATCH] rendering registry --- app/mobile/src/session/Session.jsx | 11 +- app/mobile/src/session/cards/Cards.jsx | 59 +++++----- .../src/session/cards/cardItem/CardItem.jsx | 47 ++++---- .../session/cards/cardItem/CardItem.styled.js | 3 + app/mobile/src/session/cards/useCards.hook.js | 1 + app/mobile/src/session/registry/Registry.jsx | 73 +++++++++++- .../src/session/registry/Registry.styled.js | 106 ++++++++++++++++++ .../registry/registryItem/RegistryItem.jsx | 27 +++++ .../registryItem/RegistryItem.styled.js | 64 +++++++++++ .../registryItem/useRegistryItem.hook.js | 17 +++ .../src/session/registry/useRegistry.hook.js | 82 ++++++++++++++ 11 files changed, 441 insertions(+), 49 deletions(-) create mode 100644 app/mobile/src/session/registry/Registry.styled.js create mode 100644 app/mobile/src/session/registry/registryItem/RegistryItem.jsx create mode 100644 app/mobile/src/session/registry/registryItem/RegistryItem.styled.js create mode 100644 app/mobile/src/session/registry/registryItem/useRegistryItem.hook.js create mode 100644 app/mobile/src/session/registry/useRegistry.hook.js diff --git a/app/mobile/src/session/Session.jsx b/app/mobile/src/session/Session.jsx index 4a2e1548..9c8c34ec 100644 --- a/app/mobile/src/session/Session.jsx +++ b/app/mobile/src/session/Session.jsx @@ -84,15 +84,24 @@ export function Session() { const clearCardStack = (navigation) => { navigation.goBack(); } + const setRegistryStack = (navigation) => { + navigation.navigate('registry'); + } + const clearRegistryStack = (navigation) => { + navigation.goBack(); + } return ( ({ headerShown: false })}> - {(props) => setCardStack(props.navigation, cardId)} />} + {(props) => setRegistryStack(props.navigation)} openContact={(cardId) => setCardStack(props.navigation, cardId)} />} {(props) => clearCardStack(props.navigation)} />} + + {(props) => clearRegistryStack(props.navigation)} />} + ); } diff --git a/app/mobile/src/session/cards/Cards.jsx b/app/mobile/src/session/cards/Cards.jsx index 555ba4a4..f31f2aa8 100644 --- a/app/mobile/src/session/cards/Cards.jsx +++ b/app/mobile/src/session/cards/Cards.jsx @@ -12,28 +12,35 @@ export function Cards({ openRegistry }) { return ( { state.tabbed && ( - - { state.sorting && ( - - + <> + + { state.sorting && ( + + + + )} + { !state.sorting && ( + + + + )} + + + + + + + + New - )} - { !state.sorting && ( - - - - )} - - - - - - - New - - + } + keyExtractor={item => item.cardId} + /> + )} { !state.tabbed && ( @@ -50,20 +57,20 @@ export function Cards({ openRegistry }) { )} - + } + keyExtractor={item => item.cardId} + /> )} - } - keyExtractor={item => item.cardId} - /> ); } diff --git a/app/mobile/src/session/cards/cardItem/CardItem.jsx b/app/mobile/src/session/cards/cardItem/CardItem.jsx index 8e6cdcd4..30037df2 100644 --- a/app/mobile/src/session/cards/cardItem/CardItem.jsx +++ b/app/mobile/src/session/cards/cardItem/CardItem.jsx @@ -8,28 +8,35 @@ export function CardItem({ item }) { const { state, actions } = useCardItem(item); return ( - - - - { item.name } - { item.handle } - - { item.status === 'connected' && ( - + + { item.cardId && ( + + + + { item.name } + { item.handle } + + { item.status === 'connected' && ( + + )} + { item.status === 'requested' && ( + + )} + { item.status === 'connecting' && ( + + )} + { item.status === 'pending' && ( + + )} + { item.status === 'confirmed' && ( + + )} + )} - { item.status === 'requested' && ( - + { !item.cardId && ( + )} - { item.status === 'connecting' && ( - - )} - { item.status === 'pending' && ( - - )} - { item.status === 'confirmed' && ( - - )} - + ); } diff --git a/app/mobile/src/session/cards/cardItem/CardItem.styled.js b/app/mobile/src/session/cards/cardItem/CardItem.styled.js index fc3c6610..337cef53 100644 --- a/app/mobile/src/session/cards/cardItem/CardItem.styled.js +++ b/app/mobile/src/session/cards/cardItem/CardItem.styled.js @@ -19,6 +19,9 @@ export const styles = StyleSheet.create({ flexGrow: 1, flexShrink: 1, }, + space: { + height: 64, + }, name: { color: Colors.text, fontSize: 14, diff --git a/app/mobile/src/session/cards/useCards.hook.js b/app/mobile/src/session/cards/useCards.hook.js index 0239f4d9..167e98b8 100644 --- a/app/mobile/src/session/cards/useCards.hook.js +++ b/app/mobile/src/session/cards/useCards.hook.js @@ -84,6 +84,7 @@ export function useCards() { return -1; }); } + filtered.push({cardId:''}); updateState({ cards: filtered }); }, [card, state.filter, state.sorting]); diff --git a/app/mobile/src/session/registry/Registry.jsx b/app/mobile/src/session/registry/Registry.jsx index 9d99fb17..5e92e34c 100644 --- a/app/mobile/src/session/registry/Registry.jsx +++ b/app/mobile/src/session/registry/Registry.jsx @@ -1,4 +1,73 @@ -export function Registry() { - return <> +import { useContext } from 'react'; +import { ActivityIndicator, FlatList, ScrollView, View, TextInput, TouchableOpacity, Text } from 'react-native'; +import { styles } from './Registry.styled'; +import { useRegistry } from './useRegistry.hook'; +import { SafeAreaView } from 'react-native-safe-area-context'; +import Ionicons from '@expo/vector-icons/AntDesign'; +import { RegistryItem } from './registryItem/RegistryItem'; +import Colors from 'constants/Colors'; + +export function Registry({ closeRegistry, openContact }) { + const { state, actions } = useRegistry(); + return ( + + { state.tabbed && ( + <> + + { state.busy && ( + + + + )} + { !state.busy && ( + + + + )} + + + + + + + + + } + keyExtractor={item => item.guid} + /> + + )} + { !state.tabbed && ( + + + + { state.busy && ( + + + + )} + { !state.busy && ( + + + + )} + + + + + + } + keyExtractor={item => item.guid} + /> + + )} + + ); } diff --git a/app/mobile/src/session/registry/Registry.styled.js b/app/mobile/src/session/registry/Registry.styled.js new file mode 100644 index 00000000..a47475d7 --- /dev/null +++ b/app/mobile/src/session/registry/Registry.styled.js @@ -0,0 +1,106 @@ +import { StyleSheet } from 'react-native'; +import { Colors } from 'constants/Colors'; + +export const styles = StyleSheet.create({ + container: { + width: '100%', + height: '100%', + display: 'flex', + flexDirection: 'column', + }, + topbar: { + borderTopWidth: 1, + borderBottomWidth: 1, + borderColor: Colors.divider, + paddingTop: 6, + paddingBottom: 6, + paddingLeft: 16, + paddingRight: 16, + display: 'flex', + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'center', + }, + searcharea: { + borderBottomWidth: 1, + borderColor: Colors.divider, + }, + searchbar: { + display: 'flex', + flexDirection: 'row', + paddingTop: 16, + paddingLeft: 8, + paddingBottom: 8, + alignItems: 'center', + }, + inputwrapper: { + display: 'flex', + flexDirection: 'row', + borderRadius: 4, + backgroundColor: Colors.white, + alignItems: 'center', + flexGrow: 1, + flexShrink: 1, + marginRight: 8, + paddingTop: 4, + paddingBottom: 4, + marginLeft: 8, + }, + inputfield: { + flex: 1, + textAlign: 'center', + padding: 4, + color: Colors.text, + fontSize: 14, + }, + icon: { + paddingLeft: 8, + }, + accounts: { + flexGrow: 1, + flexShrink: 1, + width: '100%', + paddingLeft: 16, + paddingRight: 16, + minHeight: 0, + }, + addbottom: { + marginRight: 8, + display: 'flex', + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'center', + padding: 8, + borderRadius: 4, + }, + bottomText: { + color: Colors.primary, + paddingLeft: 8, + }, + search: { + backgroundColor: Colors.primary, + marginLeft: 8, + display: 'flex', + flexDirection: 'row', + alignItems: 'center', + padding: 8, + borderRadius: 4, + }, + close: { + marginRight: 8, + display: 'flex', + flexDirection: 'row', + alignItems: 'center', + padding: 8, + borderRadius: 4, + }, + newtext: { + paddingLeft: 8, + color: Colors.white, + }, + findarea: { + borderTopWidth: 1, + borderColor: Colors.divider, + } +}) + diff --git a/app/mobile/src/session/registry/registryItem/RegistryItem.jsx b/app/mobile/src/session/registry/registryItem/RegistryItem.jsx new file mode 100644 index 00000000..01b5748a --- /dev/null +++ b/app/mobile/src/session/registry/registryItem/RegistryItem.jsx @@ -0,0 +1,27 @@ +import { Text, TouchableOpacity, View } from 'react-native'; +import { Logo } from 'utils/Logo'; +import { styles } from './RegistryItem.styled'; +import { useRegistryItem } from './useRegistryItem.hook'; + +export function RegistryItem({ item }) { + + const { state, actions } = useRegistryItem(item); + + return ( + + { item.guid && ( + + + + { item.name } + { item.handle } + + + )} + { !item.guid && ( + + )} + + ); +} + diff --git a/app/mobile/src/session/registry/registryItem/RegistryItem.styled.js b/app/mobile/src/session/registry/registryItem/RegistryItem.styled.js new file mode 100644 index 00000000..91b94788 --- /dev/null +++ b/app/mobile/src/session/registry/registryItem/RegistryItem.styled.js @@ -0,0 +1,64 @@ +import { StyleSheet } from 'react-native'; +import { Colors } from 'constants/Colors'; + +export const styles = StyleSheet.create({ + container: { + width: '100%', + display: 'flex', + flexDirection: 'row', + height: 48, + alignItems: 'center', + borderBottomWidth: 1, + borderColor: Colors.itemDivider, + }, + space: { + height: 64 + }, + detail: { + paddingLeft: 12, + display: 'flex', + flexDirection: 'column', + justifyContent: 'center', + flexGrow: 1, + flexShrink: 1, + }, + name: { + color: Colors.text, + fontSize: 14, + }, + handle: { + color: Colors.text, + fontSize: 12, + }, + connected: { + width: 8, + height: 8, + borderRadius: 4, + backgroundColor: Colors.connected, + }, + requested: { + width: 8, + height: 8, + borderRadius: 4, + backgroundColor: Colors.requested, + }, + connecting: { + width: 8, + height: 8, + borderRadius: 4, + backgroundColor: Colors.connecting, + }, + pending: { + width: 8, + height: 8, + borderRadius: 4, + backgroundColor: Colors.pending, + }, + confirmed: { + width: 8, + height: 8, + borderRadius: 4, + backgroundColor: Colors.confirmed, + }, +}) + diff --git a/app/mobile/src/session/registry/registryItem/useRegistryItem.hook.js b/app/mobile/src/session/registry/registryItem/useRegistryItem.hook.js new file mode 100644 index 00000000..75f816f1 --- /dev/null +++ b/app/mobile/src/session/registry/registryItem/useRegistryItem.hook.js @@ -0,0 +1,17 @@ +import { useState, useEffect, useRef, useContext } from 'react'; +import { useWindowDimensions } from 'react-native'; + +export function useRegistryItem(item) { + + const [state, setState] = useState({}); + + const updateState = (value) => { + setState((s) => ({ ...s, ...value })); + } + + const actions = { + }; + + return { state, actions }; +} + diff --git a/app/mobile/src/session/registry/useRegistry.hook.js b/app/mobile/src/session/registry/useRegistry.hook.js new file mode 100644 index 00000000..6a11208d --- /dev/null +++ b/app/mobile/src/session/registry/useRegistry.hook.js @@ -0,0 +1,82 @@ +import { useState, useEffect, useRef, useContext } from 'react'; +import { useWindowDimensions } from 'react-native'; +import { useNavigate } from 'react-router-dom'; +import { ProfileContext } from 'context/ProfileContext'; +import { getListing } from 'api/getListing'; +import { getListingImageUrl } from 'api/getListingImageUrl'; +import config from 'constants/Config'; + +export function useRegistry() { + + const [state, setState] = useState({ + tabbed: null, + accounts: [], + server: null, + busy: false, + }); + + const dimensions = useWindowDimensions(); + const profile = useContext(ProfileContext); + + const updateState = (value) => { + setState((s) => ({ ...s, ...value })); + } + + useEffect(() => { + if (dimensions.width > config.tabbedWidth) { + updateState({ tabbed: false }); + } + else { + updateState({ tabbed: true }); + } + }, [dimensions]); + + useEffect(() => { + const server = profile.state.profile.node; + updateState({ server }); + getAccounts(server); + }, [profile]); + + const setAccountItem = (item) => { + return { + guid: item.guid, + name: item.name, + handle: `${item.handle}@${item.node}`, + logo: item.imageSet ? getListingImageUrl(item.node, item.guid) : 'avatar', + } + }; + + const getAccounts = async (server, ignore) => { + if (!state.busy) { + try { + updateState({ busy: true }); + const accounts = await getListing(server, true); + const filtered = accounts.filter(item => { + if (item.guid === profile.state.profile.guid) { + return false; + } + return true; + }); + const items = filtered.map(setAccountItem); + items.push({guid:''}); + updateState({ busy: false, accounts: items }); + } + catch (err) { + console.log(err); + updateState({ busy: false, accounts: [] }); + if (!ignore) { + throw new Error('failed list accounts'); + } + } + } + }; + + const actions = { + setServer: (filter) => { + updateState({ filter }); + }, + }; + + return { state, actions }; +} +