rendering contact request status

This commit is contained in:
Roland Osborne 2022-10-14 15:15:45 -07:00
parent b2ce79a290
commit 8848152a5d
6 changed files with 99 additions and 3 deletions

View File

@ -29,6 +29,7 @@ import { removeContactChannelTopic } from 'api/removeContactChannelTopic';
export function useCardContext() { export function useCardContext() {
const [state, setState] = useState({ const [state, setState] = useState({
cards: new Map(), cards: new Map(),
requestRevision: null,
}); });
const store = useContext(StoreContext); const store = useContext(StoreContext);
const upload = useContext(UploadContext); const upload = useContext(UploadContext);
@ -356,6 +357,8 @@ export function useCardContext() {
setSession: async (access) => { setSession: async (access) => {
const { guid, server, appToken } = access; const { guid, server, appToken } = access;
cards.current = new Map(); cards.current = new Map();
const status = await store.actions.getCardRequestStatus(guid);
updateState({ requestRevision: status.revision });
const cardItems = await store.actions.getCardItems(guid); const cardItems = await store.actions.getCardItems(guid);
for (item of cardItems) { for (item of cardItems) {
cards.current.set(item.cardId, { ...item, channels: new Map() }); cards.current.set(item.cardId, { ...item, channels: new Map() });
@ -370,6 +373,11 @@ export function useCardContext() {
curRevision.current = revision; curRevision.current = revision;
session.current = access; session.current = access;
}, },
setRequestRevision: async (revision) => {
const { guid } = session.current
await store.actions.setCardRequestStatus(guid, { revision });
updateState({ requestRevision: revision });
},
clearSession: () => { clearSession: () => {
session.current = {}; session.current = {};
updateState({ account: null }); updateState({ account: null });

View File

@ -44,6 +44,14 @@ export function useStoreContext() {
const dataId = `${guid}_profile`; const dataId = `${guid}_profile`;
await db.current.executeSql("INSERT OR REPLACE INTO app (key, value) values (?, ?);", [dataId, encodeObject(profile)]); await db.current.executeSql("INSERT OR REPLACE INTO app (key, value) values (?, ?);", [dataId, encodeObject(profile)]);
}, },
getCardRequestStatus: async (guid) => {
const dataId = `${guid}_card_status`;
return await getAppValue(db.current, dataId, {});
},
setCardRequestStatus: async (guid, status) => {
const dataId = `${guid}_card_status`;
await db.current.executeSql("INSERT OR REPLACE INTO app (key, value) values (?, ?);", [dataId, encodeObject(status)]);
},
getProfileRevision: async (guid) => { getProfileRevision: async (guid) => {
const dataId = `${guid}_profileRevision`; const dataId = `${guid}_profileRevision`;
return await getAppValue(db.current, dataId, null); return await getAppValue(db.current, dataId, null);

View File

@ -23,6 +23,7 @@ import { useChannels } from './channels/useChannels.hook';
import { CommonActions } from '@react-navigation/native'; import { CommonActions } from '@react-navigation/native';
import { ConversationContext } from 'context/ConversationContext'; import { ConversationContext } from 'context/ConversationContext';
import { ProfileIcon } from './profileIcon/ProfileIcon'; import { ProfileIcon } from './profileIcon/ProfileIcon';
import { CardsIcon } from './cardsIcon/CardsIcon';
const ConversationStack = createStackNavigator(); const ConversationStack = createStackNavigator();
const ProfileStack = createStackNavigator(); const ProfileStack = createStackNavigator();
@ -201,8 +202,8 @@ export function Session() {
<Text style={styles.profileLabel}>Profile</Text> <Text style={styles.profileLabel}>Profile</Text>
</TouchableOpacity> </TouchableOpacity>
<TouchableOpacity style={styles.option} onPress={openCards}> <TouchableOpacity style={styles.option} onPress={openCards}>
<Ionicons style={styles.icon} name={'contacts'} size={20} /> <CardsIcon color={Colors.text} size={20} />
<Text>Contacts</Text> <Text style={styles.profileLabel}>Contacts</Text>
</TouchableOpacity> </TouchableOpacity>
</SafeAreaView> </SafeAreaView>
<View style={styles.channels}> <View style={styles.channels}>
@ -337,6 +338,8 @@ export function Session() {
); );
} }
const [cardsActive, setCardsActive] = useState(false);
return ( return (
<View style={styles.container}> <View style={styles.container}>
{ state.tabbed === false && ( { state.tabbed === false && (
@ -349,6 +352,7 @@ export function Session() {
)} )}
{ state.tabbed === true && ( { state.tabbed === true && (
<Tab.Navigator <Tab.Navigator
screenListeners={{ state: (e) => setCardsActive(e?.data?.state?.index === 2) }}
screenOptions={({ route }) => ({ screenOptions={({ route }) => ({
tabBarStyle: styles.tabBar, tabBarStyle: styles.tabBar,
headerShown: false, headerShown: false,
@ -360,7 +364,7 @@ export function Session() {
return <Ionicons name={'message1'} size={size} color={color} />; return <Ionicons name={'message1'} size={size} color={color} />;
} }
if (route.name === 'Contacts') { if (route.name === 'Contacts') {
return <Ionicons name={'contacts'} size={size} color={color} />; return <CardsIcon size={size} color={color} active={cardsActive} />;
} }
}, },
tabBarShowLabel: false, tabBarShowLabel: false,

View File

@ -0,0 +1,19 @@
import { View } from 'react-native';
import { useCardsIcon } from './useCardsIcon.hook';
import { styles } from './CardsIcon.styled';
import Ionicons from '@expo/vector-icons/AntDesign';
export function CardsIcon({ size, color, active }) {
const { state, actions } = useCardsIcon(active);
return (
<View>
<Ionicons name={'contacts'} size={size} color={color} />
{ state.curRevision !== state.setRevision && (
<View style={styles.requested} />
)}
</View>
);
}

View File

@ -0,0 +1,14 @@
import { StyleSheet } from 'react-native';
import { Colors } from 'constants/Colors';
export const styles = StyleSheet.create({
requested: {
width: 8,
height: 8,
borderRadius: 4,
backgroundColor: Colors.pending,
position: 'absolute',
right: 0,
bottom: 0,
},
});

View File

@ -0,0 +1,43 @@
import { useState, useEffect, useContext } from 'react';
import { CardContext } from 'context/CardContext';
export function useCardsIcon(active) {
const [state, setState] = useState({
curRevision: null,
setRevision: null,
});
const card = useContext(CardContext);
const updateState = (value) => {
setState((s) => ({ ...s, ...value }));
}
useEffect(() => {
if (active && state.curRevision) {
card.actions.setRequestRevision(state.curRevision);
}
}, [active]);
useEffect(() => {
let revision;
card.state.cards.forEach((contact) => {
if (contact?.detail?.status === 'pending' || contact?.detail?.status === 'requested') {
if (!revision || contact.detailRevision > revision) {
revision = contact.detailRevision;
}
}
});
if (active && revision !== state.setRevision) {
card.actions.setRequestRevision(state.curRevision);
}
updateState({ setRevision: card.state.requestRevision, curRevision: revision });
}, [card]);
const actions = {};
return { state, actions };
}