implementing refactored contact screen

This commit is contained in:
Roland Osborne 2023-09-20 13:37:43 -07:00
parent fce0f4e630
commit 8c77245524
4 changed files with 183 additions and 161 deletions

View File

@ -85,7 +85,7 @@ const Strings = [
// contacts page // contacts page
add: 'Add', add: 'Add',
back: 'Back', back: 'Back',
deleteContact: 'Deleting Contact', deleteContact: 'Delete Contact',
confirmDelete: 'Delete', confirmDelete: 'Delete',
disconnectContact: 'Disconnect from Contact', disconnectContact: 'Disconnect from Contact',
confirmDisconnect: 'Disconnect', confirmDisconnect: 'Disconnect',

View File

@ -1,5 +1,5 @@
import { useState } from 'react'; import { useState } from 'react';
import { Alert, View, Text, TouchableOpacity, ScrollView, Image } from 'react-native'; import { ActivityIndicator, Alert, View, Text, TouchableOpacity, ScrollView, Image } from 'react-native';
import { styles } from './Contact.styled'; import { styles } from './Contact.styled';
import { useContact } from './useContact.hook'; import { useContact } from './useContact.hook';
import Ionicons from 'react-native-vector-icons/AntDesign'; import Ionicons from 'react-native-vector-icons/AntDesign';
@ -307,10 +307,9 @@ export function ContactBody({ contact }) {
export function Contact({ contact, drawer, back }) { export function Contact({ contact, drawer, back }) {
const [busy, setBusy] = useState(false); const [busy, setBusy] = useState(false);
const { state, actions } = useContact(contact); const { state, actions } = useContact(contact, back);
const OVERLAP = 32; const OVERLAP = 32;
const promptAction = (prompt, action) => { const promptAction = (prompt, action) => {
prompt(async () => { prompt(async () => {
if (!busy) { if (!busy) {
@ -322,12 +321,35 @@ export function Contact({ contact, drawer, back }) {
catch (err) { catch (err) {
console.log(err); console.log(err);
setBusy(false); setBusy(false);
Alert.alert(
state.strings.error,
state.strings.tryAgain,
);
throw err; throw err;
} }
} }
}); });
} }
const setAction = async (action) => {
if (!busy) {
try {
setBusy(true);
await new Promise(r => setTimeout(r, 100));
await action();
setBusy(false);
}
catch (err) {
console.log(err);
setBusy(false);
Alert.alert(
state.strings.error,
state.strings.tryAgain,
);
}
}
}
return ( return (
<> <>
{ drawer && ( { drawer && (
@ -351,7 +373,7 @@ export function Contact({ contact, drawer, back }) {
<Text style={styles.nameUnset}>{ state.strings.name }</Text> <Text style={styles.nameUnset}>{ state.strings.name }</Text>
)} )}
<View style={styles.usernameStatus}> <View style={styles.usernameStatus}>
<Text style={styles.username} numberOfLines={1}>{ state.username }</Text> <Text style={styles.username} numberOfLines={1} adjustsFontSizeToFit={true}>{ state.username }</Text>
<View style={styles.status}> <View style={styles.status}>
{ state.status === 'offsync' && ( { state.status === 'offsync' && (
<View style={styles.statusOffsync}> <View style={styles.statusOffsync}>
@ -383,9 +405,9 @@ export function Contact({ contact, drawer, back }) {
<Text numberOfLines={1} style={styles.statusLabel}>{ state.strings.pending }</Text> <Text numberOfLines={1} style={styles.statusLabel}>{ state.strings.pending }</Text>
</View> </View>
)} )}
{ state.status === 'saved' && ( { state.status === 'confirmed' && (
<View style={styles.statusSaved}> <View style={styles.statusConfirmed}>
<Text numberOfLines={1} style={styles.statusLabel}>{ state.strings.saved }</Text> <Text numberOfLines={1} style={styles.statusLabel}>{ state.strings.confirmed }</Text>
</View> </View>
)} )}
{ state.status === 'unsaved' && ( { state.status === 'unsaved' && (
@ -419,27 +441,51 @@ export function Contact({ contact, drawer, back }) {
</ScrollView> </ScrollView>
</View> </View>
<View style={styles.actions}> <View style={styles.actions}>
{ busy && (
<View style={styles.busy}>
<ActivityIndicator animating={true} color={Colors.primaryButtonText} size={'large'} />
</View>
)}
{ !busy && (
<ScrollView horizontal={true} contentContainerStyle={styles.actionList}> <ScrollView horizontal={true} contentContainerStyle={styles.actionList}>
{ state.status === 'offsync' && ( { state.status === 'offsync' && (
<TouchableOpacity style={styles.action} activeOpacity={1}> <TouchableOpacity style={styles.action} activeOpacity={1} onPress={actions.resync}>
<MatIcons name="sync" style={styles.actionIcon} size={44} color={Colors.linkText} /> <MatIcons name="sync" style={styles.actionIcon} size={44} color={Colors.linkText} />
<Text style={styles.actionLabel}>{ state.strings.actionResync }</Text> <Text style={styles.actionLabel}>{ state.strings.actionResync }</Text>
</TouchableOpacity> </TouchableOpacity>
)} )}
{ (state.status === 'unsaved' || state.status === 'confirmed') && ( { state.status === 'unsaved' && (
<TouchableOpacity style={styles.action} activeOpacity={1}> <TouchableOpacity style={styles.action} activeOpacity={1} onPress={() => setAction(actions.saveAndConnect)}>
<FntIcons name="people-arrows" style={{ ...styles.actionIcon, paddingBottom: 8 }} size={32} color={Colors.linkText} /> <FntIcons name="people-arrows" style={{ ...styles.actionIcon, paddingBottom: 8 }} size={32} color={Colors.linkText} />
<Text style={styles.actionLabel}>{ state.strings.actionConnect }</Text> <Text style={styles.actionLabel}>{ state.strings.actionConnect }</Text>
</TouchableOpacity> </TouchableOpacity>
)} )}
{ (state.status === 'received' || state.status === 'pending') && ( { state.status === 'confirmed' && (
<TouchableOpacity style={styles.action} activeOpacity={1}> <TouchableOpacity style={styles.action} activeOpacity={1} onPress={() => setAction(actions.connectContact)}>
<FntIcons name="people-arrows" style={{ ...styles.actionIcon, paddingBottom: 8 }} size={32} color={Colors.linkText} />
<Text style={styles.actionLabel}>{ state.strings.actionConnect }</Text>
</TouchableOpacity>
)}
{ state.status === 'received' && (
<TouchableOpacity style={styles.action} activeOpacity={1} onPress={() => setAction(actions.connectContact)}>
<MatIcons name="account-check-outline" style={{ ...styles.actionIcon, paddingBottom: 2 }} size={42} color={Colors.linkText} /> <MatIcons name="account-check-outline" style={{ ...styles.actionIcon, paddingBottom: 2 }} size={42} color={Colors.linkText} />
<Text style={styles.actionLabel}>{ state.strings.actionAccept }</Text> <Text style={styles.actionLabel}>{ state.strings.actionAccept }</Text>
</TouchableOpacity> </TouchableOpacity>
)} )}
{ (state.status === 'received' || state.status === 'pending') && ( { state.status === 'pending' && (
<TouchableOpacity style={styles.action} activeOpacity={1}> <TouchableOpacity style={styles.action} activeOpacity={1} onPress={() => setAction(actions.confirmAndConnect)}>
<MatIcons name="account-check-outline" style={{ ...styles.actionIcon, paddingBottom: 2 }} size={42} color={Colors.linkText} />
<Text style={styles.actionLabel}>{ state.strings.actionAccept }</Text>
</TouchableOpacity>
)}
{ state.status === 'received' && (
<TouchableOpacity style={styles.action} activeOpacity={1} onPress={() => setAction(actions.disconnectContact)}>
<MatIcons name="account-remove-outline" style={{ ...styles.actionIcon, paddingBottom: 2 }} size={42} color={Colors.linkText} />
<Text style={styles.actionLabel}>{ state.strings.actionIgnore }</Text>
</TouchableOpacity>
)}
{ state.status === 'pending' && (
<TouchableOpacity style={styles.action} activeOpacity={1} onPress={() => setAction(actions.ignoreContact)}>
<MatIcons name="account-remove-outline" style={{ ...styles.actionIcon, paddingBottom: 2 }} size={42} color={Colors.linkText} /> <MatIcons name="account-remove-outline" style={{ ...styles.actionIcon, paddingBottom: 2 }} size={42} color={Colors.linkText} />
<Text style={styles.actionLabel}>{ state.strings.actionIgnore }</Text> <Text style={styles.actionLabel}>{ state.strings.actionIgnore }</Text>
</TouchableOpacity> </TouchableOpacity>
@ -451,13 +497,19 @@ export function Contact({ contact, drawer, back }) {
</TouchableOpacity> </TouchableOpacity>
)} )}
{ state.status === 'connecting' && ( { state.status === 'connecting' && (
<TouchableOpacity style={styles.action} activeOpacity={1}> <TouchableOpacity style={styles.action} activeOpacity={1} onPress={() => setAction(actions.disconnectContact)}>
<MtrIcons name="cancel-schedule-send" style={{ ...styles.actionIcon, paddingBottom: 4 }} size={40} color={Colors.linkText} /> <MtrIcons name="cancel-schedule-send" style={{ ...styles.actionIcon, paddingBottom: 4 }} size={40} color={Colors.linkText} />
<Text style={styles.actionLabel}>{ state.strings.actionCancel }</Text> <Text style={styles.actionLabel}>{ state.strings.actionCancel }</Text>
</TouchableOpacity> </TouchableOpacity>
)} )}
{ (state.status === 'pending' || state.status === 'unsaved') && ( { state.status === 'pending' && (
<TouchableOpacity style={styles.action} activeOpacity={1}> <TouchableOpacity style={styles.action} activeOpacity={1} onPress={() => setAction(actions.confirmContact)}>
<IonIcons name="save-outline" style={{ ...styles.actionIcon, paddingBottom: 4 }} size={38} color={Colors.linkText} />
<Text style={styles.actionLabel}>{ state.strings.actionSave }</Text>
</TouchableOpacity>
)}
{ state.status === 'unsaved' && (
<TouchableOpacity style={styles.action} activeOpacity={1} onPress={() => setAction(actions.saveContact)}>
<IonIcons name="save-outline" style={{ ...styles.actionIcon, paddingBottom: 4 }} size={38} color={Colors.linkText} /> <IonIcons name="save-outline" style={{ ...styles.actionIcon, paddingBottom: 4 }} size={38} color={Colors.linkText} />
<Text style={styles.actionLabel}>{ state.strings.actionSave }</Text> <Text style={styles.actionLabel}>{ state.strings.actionSave }</Text>
</TouchableOpacity> </TouchableOpacity>
@ -480,13 +532,12 @@ export function Contact({ contact, drawer, back }) {
<Text style={styles.actionLabel}>{ state.strings.actionBlock }</Text> <Text style={styles.actionLabel}>{ state.strings.actionBlock }</Text>
</TouchableOpacity> </TouchableOpacity>
)} )}
{ true && (
<TouchableOpacity style={styles.action} activeOpacity={1} onPress={() => promptAction(actions.reportPrompt, actions.reportContact)}> <TouchableOpacity style={styles.action} activeOpacity={1} onPress={() => promptAction(actions.reportPrompt, actions.reportContact)}>
<MatIcons name="account-alert-outline" style={{ ...styles.actionIcon, paddingBottom: 4 }} size={40} color={Colors.linkText} /> <MatIcons name="account-alert-outline" style={{ ...styles.actionIcon, paddingBottom: 4 }} size={40} color={Colors.linkText} />
<Text style={styles.actionLabel}>{ state.strings.actionReport }</Text> <Text style={styles.actionLabel}>{ state.strings.actionReport }</Text>
</TouchableOpacity> </TouchableOpacity>
)}
</ScrollView> </ScrollView>
)}
</View> </View>
</View> </View>
</View> </View>

View File

@ -17,6 +17,13 @@ export const styles = StyleSheet.create({
logo: { logo: {
alignSelf: 'center', alignSelf: 'center',
}, },
busy: {
width: '100%',
display: 'flex',
alignItems: 'flex-start',
justifyContent: 'center',
flex: 1,
},
details: { details: {
minHeight: 32, minHeight: 32,
borderTopRightRadius: 32, borderTopRightRadius: 32,

View File

@ -10,7 +10,7 @@ import { getCardByGuid } from 'context/cardUtil';
import { getLanguageStrings } from 'constants/Strings'; import { getLanguageStrings } from 'constants/Strings';
import avatar from 'images/avatar.png'; import avatar from 'images/avatar.png';
export function useContact(contact) { export function useContact(contact, back) {
const [state, setState] = useState({ const [state, setState] = useState({
name: null, name: null,
@ -95,7 +95,6 @@ export function useContact(contact) {
const actions = { const actions = {
saveAndConnect: async () => { saveAndConnect: async () => {
await applyAction(async () => {
let profile = await getListingMessage(state.node, state.guid); let profile = await getListingMessage(state.node, state.guid);
let added = await card.actions.addCard(profile); let added = await card.actions.addCard(profile);
await card.actions.setCardConnecting(added.id); await card.actions.setCardConnecting(added.id);
@ -104,10 +103,8 @@ export function useContact(contact) {
if (contact.status === 'connected') { if (contact.status === 'connected') {
await card.actions.setCardConnected(added.id, contact.token, contact); await card.actions.setCardConnected(added.id, contact.token, contact);
} }
});
}, },
confirmAndConnect: async () => { confirmAndConnect: async () => {
await applyAction(async () => {
await card.actions.setCardConfirmed(state.cardId); await card.actions.setCardConfirmed(state.cardId);
await card.actions.setCardConnecting(state.cardId); await card.actions.setCardConnecting(state.cardId);
let open = await card.actions.getCardOpenMessage(state.cardId); let open = await card.actions.getCardOpenMessage(state.cardId);
@ -115,16 +112,12 @@ export function useContact(contact) {
if (contact.status === 'connected') { if (contact.status === 'connected') {
await card.actions.setCardConnected(state.cardId, contact.token, contact); await card.actions.setCardConnected(state.cardId, contact.token, contact);
} }
});
}, },
saveContact: async () => { saveContact: async () => {
await applyAction(async () => {
let message = await getListingMessage(state.node, state.guid); let message = await getListingMessage(state.node, state.guid);
await card.actions.addCard(message); await card.actions.addCard(message);
});
}, },
disconnectContact: async () => { disconnectContact: async () => {
await applyAction(async () => {
await card.actions.setCardConfirmed(state.cardId); await card.actions.setCardConfirmed(state.cardId);
try { try {
let message = await card.actions.getCardCloseMessage(state.cardId); let message = await card.actions.getCardCloseMessage(state.cardId);
@ -133,28 +126,19 @@ export function useContact(contact) {
catch (err) { catch (err) {
console.log(err); console.log(err);
} }
});
}, },
confirmContact: async () => { confirmContact: async () => {
await applyAction(async () => {
await card.actions.setCardConfirmed(state.cardId); await card.actions.setCardConfirmed(state.cardId);
});
}, },
ignoreContact: async () => { ignoreContact: async () => {
await applyAction(async () => { await card.actions.removeCard(state.cardId);
await card.actions.setCardConfirmed(state.cardId); back();
});
}, },
deletePrompt: (action) => { deletePrompt: (action) => {
display.actions.showPrompt({ display.actions.showPrompt({
title: state.strings.deleteContact, title: state.strings.deleteContact,
centerButtons: true, centerButtons: true,
ok: { label: state.strings.confirmDelete, action, failed: () => { ok: { label: state.strings.confirmDelete, action, failed: () => {}},
Alert.alert(
state.strings.error,
state.strings.tryAgain,
);
}},
cancel: { label: state.strings.cancel }, cancel: { label: state.strings.cancel },
}); });
}, },
@ -162,12 +146,7 @@ export function useContact(contact) {
display.actions.showPrompt({ display.actions.showPrompt({
title: state.strings.disconnectContact, title: state.strings.disconnectContact,
centerButtons: true, centerButtons: true,
ok: { label: state.strings.confirmDisconnect, action, failed: () => { ok: { label: state.strings.confirmDisconnect, action, failed: () => {}},
Alert.alert(
state.strings.error,
state.strings.tryAgain,
);
}},
cancel: { label: state.strings.cancel }, cancel: { label: state.strings.cancel },
}); });
}, },
@ -175,12 +154,7 @@ export function useContact(contact) {
display.actions.showPrompt({ display.actions.showPrompt({
title: state.strings.blockContact, title: state.strings.blockContact,
centerButtons: true, centerButtons: true,
ok: { label: state.strings.confirmBlock, action, failed: () => { ok: { label: state.strings.confirmBlock, action, failed: () => {}},
Alert.alert(
state.strings.error,
state.strings.tryAgain,
);
}},
cancel: { label: state.strings.cancel }, cancel: { label: state.strings.cancel },
}); });
}, },
@ -188,17 +162,11 @@ export function useContact(contact) {
display.actions.showPrompt({ display.actions.showPrompt({
title: state.strings.reportContact, title: state.strings.reportContact,
centerButtons: true, centerButtons: true,
ok: { label: state.strings.confirmReport, action, failed: () => { ok: { label: state.strings.confirmReport, action, failed: () => {}},
Alert.alert(
state.strings.error,
state.strings.tryAgain,
);
}},
cancel: { label: state.strings.cancel }, cancel: { label: state.strings.cancel },
}); });
}, },
closeDelete: async () => { closeDelete: async () => {
await applyAction(async () => {
await card.actions.setCardConfirmed(state.cardId); await card.actions.setCardConfirmed(state.cardId);
try { try {
let message = await card.actions.getCardCloseMessage(state.cardId); let message = await card.actions.getCardCloseMessage(state.cardId);
@ -208,27 +176,23 @@ export function useContact(contact) {
console.log(err); console.log(err);
} }
await card.actions.removeCard(state.cardId); await card.actions.removeCard(state.cardId);
}); back();
}, },
deleteContact: async () => { deleteContact: async () => {
await applyAction(async () => {
await card.actions.removeCard(state.cardId); await card.actions.removeCard(state.cardId);
}); back();
}, },
connectContact: async () => { connectContact: async () => {
await applyAction(async () => {
await card.actions.setCardConnecting(state.cardId); await card.actions.setCardConnecting(state.cardId);
let message = await card.actions.getCardOpenMessage(state.cardId); let message = await card.actions.getCardOpenMessage(state.cardId);
let contact = await card.actions.setCardOpenMessage(state.node, message); let contact = await card.actions.setCardOpenMessage(state.node, message);
if (contact.status === 'connected') { if (contact.status === 'connected') {
await card.actions.setCardConnected(state.cardId, contact.token, contact); await card.actions.setCardConnected(state.cardId, contact.token, contact);
} }
});
}, },
blockContact: async () => { blockContact: async () => {
await applyAction(async () => {
await card.actions.setCardFlag(state.cardId); await card.actions.setCardFlag(state.cardId);
}); back();
}, },
reportContact: async () => { reportContact: async () => {
await addFlag(state.node, state.guid); await addFlag(state.node, state.guid);