mirror of
https://github.com/balzack/databag.git
synced 2025-02-12 03:29:16 +00:00
merging back updated cards screen
This commit is contained in:
parent
91f6bdb6b5
commit
c86f9f9948
@ -567,7 +567,7 @@
|
|||||||
buildSettings = {
|
buildSettings = {
|
||||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
||||||
CLANG_CXX_LANGUAGE_STANDARD = "c++14";
|
CLANG_CXX_LANGUAGE_STANDARD = "c++17";
|
||||||
CLANG_CXX_LIBRARY = "libc++";
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CLANG_ENABLE_OBJC_ARC = YES;
|
CLANG_ENABLE_OBJC_ARC = YES;
|
||||||
@ -639,7 +639,7 @@
|
|||||||
buildSettings = {
|
buildSettings = {
|
||||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
||||||
CLANG_CXX_LANGUAGE_STANDARD = "c++14";
|
CLANG_CXX_LANGUAGE_STANDARD = "c++17";
|
||||||
CLANG_CXX_LIBRARY = "libc++";
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CLANG_ENABLE_OBJC_ARC = YES;
|
CLANG_ENABLE_OBJC_ARC = YES;
|
||||||
|
@ -35,6 +35,10 @@
|
|||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
|
<key>NSMicrophoneUsageDescription</key>
|
||||||
|
<string>Required for build but not used</string>
|
||||||
|
<key>NSPhotoLibraryUsageDescription</key>
|
||||||
|
<string>Used to set profile image and post photos</string>
|
||||||
<key>NSLocationWhenInUseUsageDescription</key>
|
<key>NSLocationWhenInUseUsageDescription</key>
|
||||||
<string></string>
|
<string></string>
|
||||||
<key>UIAppFonts</key>
|
<key>UIAppFonts</key>
|
||||||
|
@ -150,7 +150,7 @@ export function useCardContext() {
|
|||||||
else {
|
else {
|
||||||
entryCard.profile = await getCardProfile(server, token, card.id);
|
entryCard.profile = await getCardProfile(server, token, card.id);
|
||||||
}
|
}
|
||||||
await store.actions.setCardItem(guid, card.id, entryCard);
|
await store.actions.setCardItem(guid, entryCard);
|
||||||
entry.card = entryCard;
|
entry.card = entryCard;
|
||||||
cards.current.set(card.id, entry);
|
cards.current.set(card.id, entry);
|
||||||
}
|
}
|
||||||
@ -360,8 +360,9 @@ export function useCardContext() {
|
|||||||
return await setCardCloseMessage(server, message);
|
return await setCardCloseMessage(server, message);
|
||||||
},
|
},
|
||||||
getCardImageUrl: (cardId) => {
|
getCardImageUrl: (cardId) => {
|
||||||
|
const { profileRevision } = cards.current.get(cardId)?.card || { };
|
||||||
const { server, token } = access.current;
|
const { server, token } = access.current;
|
||||||
return getCardImageUrl(server, token, cardId, revision);
|
return getCardImageUrl(server, token, cardId, profileRevision);
|
||||||
},
|
},
|
||||||
removeChannel: async (cardId, channelId) => {
|
removeChannel: async (cardId, channelId) => {
|
||||||
const { detail, profile } = cards.current.get(cardId) || {};
|
const { detail, profile } = cards.current.get(cardId) || {};
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { useEffect, useState, useRef, useContext } from 'react';
|
import { useEffect, useState, useRef, useContext } from 'react';
|
||||||
import SQLite from "react-native-sqlite-storage";
|
import SQLite from "react-native-sqlite-storage";
|
||||||
|
|
||||||
const DATABAG_DB = 'db_v_103.db';
|
const DATABAG_DB = 'db_v_107.db';
|
||||||
|
|
||||||
export function useStoreContext() {
|
export function useStoreContext() {
|
||||||
const [state, setState] = useState({});
|
const [state, setState] = useState({});
|
||||||
|
@ -10,7 +10,7 @@ import { useSession } from './useSession.hook';
|
|||||||
import { styles } from './Session.styled';
|
import { styles } from './Session.styled';
|
||||||
import Colors from 'constants/Colors';
|
import Colors from 'constants/Colors';
|
||||||
import { Profile, ProfileHeader, ProfileBody } from './profile/Profile';
|
import { Profile, ProfileHeader, ProfileBody } from './profile/Profile';
|
||||||
import { CardsTitle, CardsBody, Cards } from './cards/Cards';
|
import { CardsHeader, CardsBody, Cards } from './cards/Cards';
|
||||||
import { RegistryTitle, RegistryBody, Registry } from './registry/Registry';
|
import { RegistryTitle, RegistryBody, Registry } from './registry/Registry';
|
||||||
import { Contact, ContactTitle } from './contact/Contact';
|
import { Contact, ContactTitle } from './contact/Contact';
|
||||||
import { Details, DetailsHeader, DetailsBody } from './details/Details';
|
import { Details, DetailsHeader, DetailsBody } from './details/Details';
|
||||||
@ -93,6 +93,9 @@ export function Session() {
|
|||||||
const ContactStackScreen = () => {
|
const ContactStackScreen = () => {
|
||||||
const [contact, setContact] = useState(null);
|
const [contact, setContact] = useState(null);
|
||||||
|
|
||||||
|
const [filter, setFilter] = useState(null);
|
||||||
|
const [sort, setSort] = useState(false);
|
||||||
|
|
||||||
const openContact = (navigation, contact) => {
|
const openContact = (navigation, contact) => {
|
||||||
setContact(contact);
|
setContact(contact);
|
||||||
navigation.navigate('contact')
|
navigation.navigate('contact')
|
||||||
@ -104,8 +107,10 @@ export function Session() {
|
|||||||
return (
|
return (
|
||||||
<ContactStack.Navigator screenOptions={({ route }) => (screenParams)} initialRouteName="cards">
|
<ContactStack.Navigator screenOptions={({ route }) => (screenParams)} initialRouteName="cards">
|
||||||
|
|
||||||
<ContactStack.Screen name="cards" options={{ ...stackParams, headerTitle: (props) => <CardsTitle openRegistry={props.navigation} /> }}>
|
<ContactStack.Screen name="cards" options={{ ...stackParams, headerTitle: (props) => (
|
||||||
{(props) => <CardsBody openContact={(contact) => openContact(props.navigation, contact)} />}
|
<CardsHeader filter={filter} setFilter={setFilter} sort={sort} setSort={setSort} openRegistry={() => openRegistry(props.navigation)} />
|
||||||
|
)}}>
|
||||||
|
{(props) => <CardsBody filter={filter} sort={sort} openContact={(contact) => openContact(props.navigation, contact)} />}
|
||||||
</ContactStack.Screen>
|
</ContactStack.Screen>
|
||||||
|
|
||||||
<ContactStack.Screen name="contact" options={{ ...stackParams, headerTitle: (props) => <ContactTitle contact={contact} /> }}>
|
<ContactStack.Screen name="contact" options={{ ...stackParams, headerTitle: (props) => <ContactTitle contact={contact} /> }}>
|
||||||
@ -183,8 +188,11 @@ export function Session() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CardDrawer.Navigator screenOptions={{ ...drawerParams, drawerStyle: { width: '50%' } }}
|
<CardDrawer.Navigator screenOptions={{ ...drawerParams, drawerStyle: { width: '50%' } }} drawerContent={(props) => (
|
||||||
drawerContent={(props) => <Cards openContact={openContact} openRegistry={openRegistry} />}>
|
<SafeAreaView edges={['top', 'bottom', 'right']} style={styles.drawer}>
|
||||||
|
<Cards openContact={openContact} openRegistry={openRegistry} />
|
||||||
|
</SafeAreaView>
|
||||||
|
)}>
|
||||||
<CardDrawer.Screen name="home">
|
<CardDrawer.Screen name="home">
|
||||||
{(props) => <HomeScreen navParams={{...navParams, cardNav: props.navigation}} />}
|
{(props) => <HomeScreen navParams={{...navParams, cardNav: props.navigation}} />}
|
||||||
</CardDrawer.Screen>
|
</CardDrawer.Screen>
|
||||||
@ -271,7 +279,7 @@ export function Session() {
|
|||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
{ state.tabbed === false && (
|
{ state.tabbed === false && (
|
||||||
<ProfileDrawer.Navigator screenOptions={{ ...drawerParams, drawerStyle: { width: '45%' } }} drawerContent={(props) => (
|
<ProfileDrawer.Navigator screenOptions={{ ...drawerParams, drawerStyle: { width: '45%' } }} drawerContent={(props) => (
|
||||||
<ScrollView><SafeAreaView style={styles.drawer} edges={['top', 'bottom', 'right']}><Profile /></SafeAreaView></ScrollView>
|
<ScrollView style={styles.drawer}><SafeAreaView edges={['top', 'bottom', 'right']}><Profile /></SafeAreaView></ScrollView>
|
||||||
)}>
|
)}>
|
||||||
<ProfileDrawer.Screen name="detail">
|
<ProfileDrawer.Screen name="detail">
|
||||||
{(props) => <DetailDrawerScreen navParams={{ profileNav: props.navigation }} />}
|
{(props) => <DetailDrawerScreen navParams={{ profileNav: props.navigation }} />}
|
||||||
|
@ -87,7 +87,9 @@ export const styles = StyleSheet.create({
|
|||||||
drawer: {
|
drawer: {
|
||||||
width: '100%',
|
width: '100%',
|
||||||
height: '100%',
|
height: '100%',
|
||||||
|
paddingTop: 8,
|
||||||
paddingLeft: 8,
|
paddingLeft: 8,
|
||||||
|
paddingRight: 8,
|
||||||
backgroundColor: Colors.formBackground,
|
backgroundColor: Colors.formBackground,
|
||||||
},
|
},
|
||||||
options: {
|
options: {
|
||||||
|
@ -1,14 +1,73 @@
|
|||||||
import { Text } from 'react-native';
|
import { useState } from 'react';
|
||||||
|
import { FlatList, ScrollView, View, TextInput, TouchableOpacity, Text } from 'react-native';
|
||||||
|
import { styles } from './Cards.styled';
|
||||||
|
import { useCards } from './useCards.hook';
|
||||||
|
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||||
|
import AntIcons from 'react-native-vector-icons/AntDesign';
|
||||||
|
import MatIcons from 'react-native-vector-icons/MaterialCommunityIcons';
|
||||||
|
import { Colors } from 'constants/Colors';
|
||||||
|
import { CardItem } from './cardItem/CardItem';
|
||||||
|
|
||||||
export function CardsTitle({ state, actions, openRegistry }) {
|
export function CardsHeader({ filter, setFilter, sort, setSort, openRegistry }) {
|
||||||
return <Text>CardsTitle</Text>;
|
const { state, actions } = useCards(filter, sort);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={styles.title}>
|
||||||
|
{ sort && (
|
||||||
|
<TouchableOpacity style={styles.sort} onPress={() => setSort(false)}>
|
||||||
|
<MatIcons style={styles.icon} name="sort-alphabetical-ascending" size={18} color={Colors.text} />
|
||||||
|
</TouchableOpacity>
|
||||||
|
)}
|
||||||
|
{ !sort && (
|
||||||
|
<TouchableOpacity style={styles.sort} onPress={() => setSort(true)}>
|
||||||
|
<MatIcons style={styles.icon} name="sort-alphabetical-ascending" size={18} color={Colors.disabled} />
|
||||||
|
</TouchableOpacity>
|
||||||
|
)}
|
||||||
|
<View style={styles.inputwrapper}>
|
||||||
|
<AntIcons style={styles.icon} name="search1" size={16} color={Colors.disabled} />
|
||||||
|
<TextInput style={styles.inputfield} value={filter} onChangeText={setFilter}
|
||||||
|
autoCapitalize="none" placeholderTextColor={Colors.disabled} placeholder="Contacts" />
|
||||||
|
<View style={styles.space} />
|
||||||
|
</View>
|
||||||
|
<TouchableOpacity style={styles.add} onPress={openRegistry}>
|
||||||
|
<AntIcons name={'adduser'} size={16} color={Colors.white} style={[styles.box, { transform: [ { rotateY: "180deg" }, ]} ]}/>
|
||||||
|
<Text style={styles.newtext}>New</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function CardsBody({ state, actions, openContact }) {
|
export function CardsBody({ filter, sort, openContact }) {
|
||||||
return <Text>CardsBody</Text>;
|
const { state, actions } = useCards(filter, sort);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{ state.cards.length == 0 && (
|
||||||
|
<View style={styles.notfound}>
|
||||||
|
<Text style={styles.notfoundtext}>No Contacts Found</Text>
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
|
{ state.cards.length != 0 && (
|
||||||
|
<FlatList style={styles.cards}
|
||||||
|
data={state.cards}
|
||||||
|
initialNumToRender={25}
|
||||||
|
renderItem={({ item }) => <CardItem item={item} openContact={openContact} />}
|
||||||
|
keyExtractor={item => item.cardId}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Cards({ openRegistry, openContact }) {
|
export function Cards({ openRegistry, openContact }) {
|
||||||
return <Text>Cards</Text>;
|
const [filter, setFilter] = useState();
|
||||||
|
const [sort, setSort] = useState(false);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View>
|
||||||
|
<CardsHeader filter={filter} setFilter={setFilter} sort={sort} setSort={setSort} openRegistry={openRegistry} />
|
||||||
|
<CardsBody filter={filter} sort={sort} openContact={openContact} />
|
||||||
|
</View>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
127
app/mobile/src/session/cards/Cards.styled.js
Normal file
127
app/mobile/src/session/cards/Cards.styled.js
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
import { StyleSheet } from 'react-native';
|
||||||
|
import { Colors } from 'constants/Colors';
|
||||||
|
|
||||||
|
export const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
width: '100%',
|
||||||
|
height: '100%',
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
backgroundColor: Colors.formBackground,
|
||||||
|
},
|
||||||
|
drawer: {
|
||||||
|
flexGrow: 1,
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
},
|
||||||
|
topbar: {
|
||||||
|
borderTopWidth: 1,
|
||||||
|
borderBottomWidth: 1,
|
||||||
|
borderColor: Colors.divider,
|
||||||
|
paddingTop: 32,
|
||||||
|
paddingBottom: 6,
|
||||||
|
paddingLeft: 16,
|
||||||
|
paddingRight: 16,
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
},
|
||||||
|
cardlist: {
|
||||||
|
flexGrow: 1,
|
||||||
|
borderBottomWidth: 1,
|
||||||
|
borderColor: Colors.divider,
|
||||||
|
},
|
||||||
|
searcharea: {
|
||||||
|
borderBottomWidth: 1,
|
||||||
|
borderColor: Colors.divider,
|
||||||
|
},
|
||||||
|
searchbar: {
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'row',
|
||||||
|
paddingTop: 8,
|
||||||
|
paddingLeft: 8,
|
||||||
|
paddingRight: 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,
|
||||||
|
},
|
||||||
|
inputfield: {
|
||||||
|
flex: 1,
|
||||||
|
textAlign: 'center',
|
||||||
|
padding: 4,
|
||||||
|
color: Colors.text,
|
||||||
|
fontSize: 14,
|
||||||
|
},
|
||||||
|
icon: {
|
||||||
|
paddingLeft: 8,
|
||||||
|
},
|
||||||
|
cards: {
|
||||||
|
width: '100%',
|
||||||
|
paddingLeft: 16,
|
||||||
|
paddingRight: 16,
|
||||||
|
},
|
||||||
|
addbottom: {
|
||||||
|
marginRight: 8,
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
padding: 8,
|
||||||
|
borderRadius: 4,
|
||||||
|
},
|
||||||
|
bottomText: {
|
||||||
|
color: Colors.primary,
|
||||||
|
paddingLeft: 8,
|
||||||
|
},
|
||||||
|
add: {
|
||||||
|
backgroundColor: Colors.primary,
|
||||||
|
marginLeft: 8,
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
padding: 8,
|
||||||
|
borderRadius: 4,
|
||||||
|
},
|
||||||
|
newtext: {
|
||||||
|
paddingLeft: 8,
|
||||||
|
color: Colors.white,
|
||||||
|
},
|
||||||
|
up: {
|
||||||
|
marginRight: 8,
|
||||||
|
},
|
||||||
|
sort: {
|
||||||
|
paddingRight: 12,
|
||||||
|
},
|
||||||
|
findarea: {
|
||||||
|
borderTopWidth: 1,
|
||||||
|
borderColor: Colors.divider,
|
||||||
|
},
|
||||||
|
notfound: {
|
||||||
|
width: '100%',
|
||||||
|
height: '100%',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
},
|
||||||
|
notfoundtext: {
|
||||||
|
fontSize: 20,
|
||||||
|
color: Colors.grey,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
46
app/mobile/src/session/cards/cardItem/CardItem.jsx
Normal file
46
app/mobile/src/session/cards/cardItem/CardItem.jsx
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
import { Text, TouchableOpacity, View } from 'react-native';
|
||||||
|
import { Logo } from 'utils/Logo';
|
||||||
|
import { styles } from './CardItem.styled';
|
||||||
|
|
||||||
|
export function CardItem({ item, openContact }) {
|
||||||
|
|
||||||
|
const select = () => {
|
||||||
|
openContact({ card: item.cardId });
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View>
|
||||||
|
{ item.cardId && (
|
||||||
|
<TouchableOpacity style={styles.container} activeOpacity={1} onPress={select}>
|
||||||
|
<Logo src={item.logo} width={32} height={32} radius={6} />
|
||||||
|
<View style={styles.detail}>
|
||||||
|
<Text style={styles.name} numberOfLines={1} ellipsizeMode={'tail'}>{ item.name }</Text>
|
||||||
|
<Text style={styles.handle} numberOfLines={1} ellipsizeMode={'tail'}>{ item.handle }</Text>
|
||||||
|
</View>
|
||||||
|
{ item.status === 'connected' && item.offsync === 1 && (
|
||||||
|
<View style={styles.offsync} />
|
||||||
|
)}
|
||||||
|
{ item.status === 'connected' && item.offsync !== 1 && (
|
||||||
|
<View style={styles.connected} />
|
||||||
|
)}
|
||||||
|
{ item.status === 'requested' && (
|
||||||
|
<View style={styles.requested} />
|
||||||
|
)}
|
||||||
|
{ item.status === 'connecting' && (
|
||||||
|
<View style={styles.connecting} />
|
||||||
|
)}
|
||||||
|
{ item.status === 'pending' && (
|
||||||
|
<View style={styles.pending} />
|
||||||
|
)}
|
||||||
|
{ item.status === 'confirmed' && (
|
||||||
|
<View style={styles.confirmed} />
|
||||||
|
)}
|
||||||
|
</TouchableOpacity>
|
||||||
|
)}
|
||||||
|
{ !item.cardId && (
|
||||||
|
<View style={styles.space} />
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
70
app/mobile/src/session/cards/cardItem/CardItem.styled.js
Normal file
70
app/mobile/src/session/cards/cardItem/CardItem.styled.js
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
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,
|
||||||
|
},
|
||||||
|
detail: {
|
||||||
|
paddingLeft: 12,
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
justifyContent: 'center',
|
||||||
|
flexGrow: 1,
|
||||||
|
flexShrink: 1,
|
||||||
|
},
|
||||||
|
space: {
|
||||||
|
height: 64,
|
||||||
|
},
|
||||||
|
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,
|
||||||
|
},
|
||||||
|
offsync: {
|
||||||
|
width: 8,
|
||||||
|
height: 8,
|
||||||
|
borderRadius: 4,
|
||||||
|
backgroundColor: Colors.error,
|
||||||
|
},
|
||||||
|
pending: {
|
||||||
|
width: 8,
|
||||||
|
height: 8,
|
||||||
|
borderRadius: 4,
|
||||||
|
backgroundColor: Colors.pending,
|
||||||
|
},
|
||||||
|
confirmed: {
|
||||||
|
width: 8,
|
||||||
|
height: 8,
|
||||||
|
borderRadius: 4,
|
||||||
|
backgroundColor: Colors.confirmed,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
@ -1,7 +1,83 @@
|
|||||||
import { useState } from 'react';
|
import { useState, useEffect, useRef, useContext } from 'react';
|
||||||
|
import { CardContext } from 'context/CardContext';
|
||||||
|
|
||||||
export function useCards() {
|
export function useCards(filter, sort) {
|
||||||
const [state, setState] = useState({});
|
|
||||||
|
const [state, setState] = useState({
|
||||||
|
cards: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
const card = useContext(CardContext);
|
||||||
|
|
||||||
|
const updateState = (value) => {
|
||||||
|
setState((s) => ({ ...s, ...value }));
|
||||||
|
}
|
||||||
|
|
||||||
|
const setCardItem = (item) => {
|
||||||
|
const { profile, detail, cardId } = item.card || { profile: {}, detail: {} }
|
||||||
|
|
||||||
|
return {
|
||||||
|
cardId: cardId,
|
||||||
|
name: profile.name,
|
||||||
|
handle: `${profile.handle}@${profile.node}`,
|
||||||
|
status: detail.status,
|
||||||
|
offsync: item.offsync,
|
||||||
|
blocked: item.blocked,
|
||||||
|
offsync: item.offsync,
|
||||||
|
updated: detail.statusUpdated,
|
||||||
|
logo: profile.imageSet ? card.actions.getCardImageUrl(cardId) : 'avatar',
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const cards = Array.from(card.state.cards.values());
|
||||||
|
const items = cards.map(setCardItem);
|
||||||
|
const filtered = items.filter(item => {
|
||||||
|
if (item.blocked) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!filter) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
const lower = filter.toLowerCase();
|
||||||
|
if (item.name) {
|
||||||
|
if (item.name.toLowerCase().includes(lower)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (item.handle) {
|
||||||
|
if (item.handle.toLowerCase().includes(lower)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
})
|
||||||
|
if (sort) {
|
||||||
|
filtered.sort((a, b) => {
|
||||||
|
const aName = a?.name?.toLowerCase();
|
||||||
|
const bName = b?.name?.toLowerCase();
|
||||||
|
if (aName === bName) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (!aName || (aName < bName)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
filtered.sort((a, b) => {
|
||||||
|
if (a.updated === b.updated) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (!a.updated || (a.updated < b.updated)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
updateState({ cards: filtered });
|
||||||
|
}, [card, filter, sort]);
|
||||||
|
|
||||||
const actions = {
|
const actions = {
|
||||||
};
|
};
|
||||||
@ -9,3 +85,4 @@ export function useCards() {
|
|||||||
return { state, actions };
|
return { state, actions };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -599,7 +599,7 @@ export function ProfileBody() {
|
|||||||
|
|
||||||
export function Profile() {
|
export function Profile() {
|
||||||
return (
|
return (
|
||||||
<View>
|
<View style={styles.full}>
|
||||||
<ProfileHeader />
|
<ProfileHeader />
|
||||||
<ProfileBody />
|
<ProfileBody />
|
||||||
</View>
|
</View>
|
||||||
|
@ -1,6 +1,19 @@
|
|||||||
import { Text } from 'react-native';
|
import { View } from 'react-native';
|
||||||
|
import { useProfileIcon } from './useProfileIcon.hook';
|
||||||
|
import { styles } from './ProfileIcon.styled';
|
||||||
|
import Ionicons from 'react-native-vector-icons/AntDesign';
|
||||||
|
|
||||||
export function ProfileIcon({ size, color }) {
|
export function ProfileIcon({ size, color }) {
|
||||||
return <Text>ProfileIcon</Text>
|
|
||||||
|
const { state, actions } = useProfileIcon();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View>
|
||||||
|
<Ionicons name={'user'} size={size} color={color} />
|
||||||
|
{ state.disconnected && (
|
||||||
|
<View style={styles.disconnected} />
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
14
app/mobile/src/session/profileIcon/ProfileIcon.styled.js
Normal file
14
app/mobile/src/session/profileIcon/ProfileIcon.styled.js
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { StyleSheet } from 'react-native';
|
||||||
|
import { Colors } from 'constants/Colors';
|
||||||
|
|
||||||
|
export const styles = StyleSheet.create({
|
||||||
|
disconnected: {
|
||||||
|
width: 8,
|
||||||
|
height: 8,
|
||||||
|
borderRadius: 4,
|
||||||
|
backgroundColor: Colors.alert,
|
||||||
|
position: 'absolute',
|
||||||
|
right: 0,
|
||||||
|
bottom: 0,
|
||||||
|
},
|
||||||
|
});
|
24
app/mobile/src/session/profileIcon/useProfileIcon.hook.js
Normal file
24
app/mobile/src/session/profileIcon/useProfileIcon.hook.js
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import { useState, useEffect, useContext } from 'react';
|
||||||
|
import { AppContext } from 'context/AppContext';
|
||||||
|
|
||||||
|
export function useProfileIcon() {
|
||||||
|
|
||||||
|
const [state, setState] = useState({
|
||||||
|
disconnected: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
const app = useContext(AppContext);
|
||||||
|
|
||||||
|
const updateState = (value) => {
|
||||||
|
setState((s) => ({ ...s, ...value }));
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const { status } = app.state
|
||||||
|
updateState({ disconnected: status === 'disconnected' });
|
||||||
|
}, [app]);
|
||||||
|
|
||||||
|
const actions = {};
|
||||||
|
|
||||||
|
return { state, actions };
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user