From 49c2aafaf4a9eed6c7f22021474103e44974f7d8 Mon Sep 17 00:00:00 2001 From: Roland Osborne Date: Tue, 19 Sep 2023 16:06:35 -0700 Subject: [PATCH] rendering contact actions --- app/mobile/src/constants/Strings.js | 76 +++++------ app/mobile/src/session/contact/Contact.jsx | 122 +++++++++++++++++- .../src/session/contact/Contact.styled.js | 25 ++++ .../src/session/contact/useContact.hook.js | 15 +++ 4 files changed, 196 insertions(+), 42 deletions(-) diff --git a/app/mobile/src/constants/Strings.js b/app/mobile/src/constants/Strings.js index 7d724a5f..1a809007 100644 --- a/app/mobile/src/constants/Strings.js +++ b/app/mobile/src/constants/Strings.js @@ -94,15 +94,16 @@ const Strings = [ unsaved: 'Unsaved', offsync: 'Offsync', - resyncContact: 'Resync', - requestConnection: 'Request', - acceptConnection: 'Accept', - saveContact: 'Save', - cancelRequest: 'Cancel', - ignoreContact: 'Ignore', - deleteContact: 'Delete', - blockContact: 'Block', - reportContact: 'Report', + actionResync: 'Resync', + actionConnect: 'Connect', + actionAccept: 'Accept', + actionSave: 'Save', + actionCancel: 'Cancel', + actionDisconnect: 'Disconnect', + actionIgnore: 'Ignore', + actionDelete: 'Delete', + actionBlock: 'Block', + actionReport: 'Report', }, { visibleRegistry: 'Visible dans le Registre', @@ -194,15 +195,16 @@ const Strings = [ unsaved: 'Non Enregistré', offsync: 'Hors Sync', - resyncContact: 'Resync', - requestConnection: 'Connexion', - acceptConnection: 'Accepter', - saveContact: 'Enregistrer', - cancelRequest: 'Annuler', - ignoreContact: 'Ignorer', - deleteContact: 'Supprimer', - blockContact: 'Bloquer', - reportContact: 'Signaler', + actionResync: 'Resync', + actionConnect: 'Connexion', + actionAccept: 'Accepter', + actionSave: 'Enregistrer', + actionCancel: 'Annuler', + actionDisconnect: 'Déconnecter', + actionIgnore: 'Ignorer', + actionDelete: 'Supprimer', + actionBlock: 'Bloquer', + actionReport: 'Signaler', }, { visibleRegistry: 'Visible en el Registro', @@ -294,15 +296,16 @@ const Strings = [ unsaved: 'No Guardado', offsync: 'Fuera de Sync', - resyncContact: 'Resinc', - requestConnection: 'Conectar', - acceptConnection: 'Aceptar', - saveContact: 'Guardar', - cancelRequest: 'Cancelar', - ignoreContact: 'Ignorar', - deleteContact: 'Borrar', - blockContact: 'Bloquear', - reportContact: 'Informe', + actionResync: 'Resinc', + actionConnect: 'Conectar', + actionAccept: 'Aceptar', + actionSave: 'Guardar', + actionCancel: 'Cancelar', + actionDisconnect: 'Desconectar', + actionIgnore: 'Ignorar', + actionDelete: 'Borrar', + actionBlock: 'Bloquear', + actionReport: 'Informe', }, { visibleRegistry: 'Sichtbar in der Registrierung', @@ -394,15 +397,16 @@ const Strings = [ unsaved: 'Nicht Gespeichert', offsync: 'Nicht Sync', - resyncContact: 'Neu Sync', - requestConnection: 'Verbinden', - acceptConnection: 'Akzeptieren', - saveContact: 'Speichern', - cancelRequest: 'Stornieren', - ignoreContact: 'Ignorieren', - deleteContact: 'Löschen', - blockContact: 'Verstecken', - reportContact: 'Bericht', + actionResync: 'Neu Sync', + actionConnect: 'Verbinden', + actionAccept: 'Akzeptieren', + actionSave: 'Speichern', + actionCancel: 'Stornieren', + actionDisconnect: 'Trennen', + actionIgnore: 'Ignorieren', + actionDelete: 'Löschen', + actionBlock: 'Verstecken', + actionReport: 'Bericht', } ]; diff --git a/app/mobile/src/session/contact/Contact.jsx b/app/mobile/src/session/contact/Contact.jsx index 695460a5..d73c3629 100644 --- a/app/mobile/src/session/contact/Contact.jsx +++ b/app/mobile/src/session/contact/Contact.jsx @@ -1,3 +1,4 @@ +import { useState } from 'react'; import { Alert, View, Text, TouchableOpacity, ScrollView, Image } from 'react-native'; import { styles } from './Contact.styled'; import { useContact } from './useContact.hook'; @@ -5,7 +6,10 @@ import Ionicons from 'react-native-vector-icons/AntDesign'; import { Logo } from 'utils/Logo'; import { Colors } from 'constants/Colors'; import AntIcons from 'react-native-vector-icons/AntDesign'; -import MatIcons from 'react-native-vector-icons/MaterialCommunityIcons'; +import IonIcons from 'react-native-vector-icons/Ionicons'; +import FntIcons from 'react-native-vector-icons/FontAwesome5'; +import MatIcons from 'react-native-vector-icons/MaterialCommunityIcons'; +import MtrIcons from 'react-native-vector-icons/MaterialIcons'; export function ContactHeader({ contact }) { const handle = contact?.node ? `${contact?.handle}@${contact?.node}` : contact?.handle; @@ -302,9 +306,45 @@ export function ContactBody({ contact }) { export function Contact({ contact, drawer, back }) { + const [busy, setBusy] = useState(false); const { state, actions } = useContact(contact); const OVERLAP = 32; + + const promptDelete = (action) => { + actions.deletePrompt(async () => { + if (!busy) { + try { + setBusy(true); + await action(); + setBusy(false); + } + catch (err) { + console.log(err); + setBusy(false); + throw err; + } + } + }); + } + + const action = async (method) => { + if (!busy) { + try { + setBusy(true); + await method(); + } + catch (err) { + console.log(err); + Alert.alert( + state.strings.error, + state.strings.tryAgain, + ); + } + setBusy(false); + } + }; + return ( <> { drawer && ( @@ -330,6 +370,11 @@ export function Contact({ contact, drawer, back }) { { state.username } + { state.status === 'offsync' && ( + + { state.strings.offsync } + + )} { state.status === 'connected' && ( { state.strings.connected } @@ -345,11 +390,6 @@ export function Contact({ contact, drawer, back }) { { state.strings.requested } )} - { state.status === 'offsync' && ( - - { state.strings.offsync } - - )} { state.status === 'received' && ( { state.strings.received } @@ -395,6 +435,76 @@ export function Contact({ contact, drawer, back }) { + + + { state.status === 'offsync' && ( + + + { state.strings.actionResync } + + )} + { (state.status === 'unsaved' || state.status === 'confirmed') && ( + + + { state.strings.actionConnect } + + )} + { (state.status === 'received' || state.status === 'pending') && ( + + + { state.strings.actionAccept } + + )} + { (state.status === 'received' || state.status === 'pending') && ( + + + { state.strings.actionIgnore } + + )} + { state.status === 'connected' && ( + + + { state.strings.actionDisconnect } + + )} + { state.status === 'connecting' && ( + + + { state.strings.actionCancel } + + )} + { (state.status === 'pending' || state.status === 'unsaved') && ( + + + { state.strings.actionSave } + + )} + { (state.status === 'connected' || state.status === 'connecting' || state.status === 'received') && ( + promptDelete(actions.closeDelete)}> + + { state.strings.actionDelete } + + )} + { state.status === 'confirmed' && ( + promptDelete(actions.deleteContact)}> + + { state.strings.actionDelete } + + )} + { state.status !== 'unsaved' && state.status !== 'pending' && ( + + + { state.strings.actionBlock } + + )} + { true && ( + + + { state.strings.actionReport } + + )} + + diff --git a/app/mobile/src/session/contact/Contact.styled.js b/app/mobile/src/session/contact/Contact.styled.js index 60d5a5c6..b9b7ba79 100644 --- a/app/mobile/src/session/contact/Contact.styled.js +++ b/app/mobile/src/session/contact/Contact.styled.js @@ -163,6 +163,31 @@ export const styles = StyleSheet.create({ display: 'flex', flexShrink: 1, }, + actions: { + marginLeft: 16, + marginRight: 16, + paddingLeft: 16, + paddingRight: 16, + backgroundColor: Colors.areaBase, + borderRadius: 8, + marginTop: 24, + height: 80, + }, + actionList: { + alignItems: 'flex-end', + }, + action: { + display: 'flex', + alignItems: 'center', + paddingRight: 24, + paddingBottom: 12, + }, + actionIcon: { + }, + actionLabel: { + color: Colors.linkText, + fontSize: 10, + }, divider: { width: '100%', height: 2, diff --git a/app/mobile/src/session/contact/useContact.hook.js b/app/mobile/src/session/contact/useContact.hook.js index 7bbd9a25..9b8e254e 100644 --- a/app/mobile/src/session/contact/useContact.hook.js +++ b/app/mobile/src/session/contact/useContact.hook.js @@ -2,6 +2,7 @@ import { useState, useEffect, useRef, useContext } from 'react'; import { useWindowDimensions } from 'react-native'; import { CardContext } from 'context/CardContext'; import { ProfileContext } from 'context/ProfileContext'; +import { DisplayContext } from 'context/DisplayContext'; import { getListingMessage } from 'api/getListingMessage'; import { getListingImageUrl } from 'api/getListingImageUrl'; import { addFlag } from 'api/addFlag'; @@ -35,6 +36,7 @@ export function useContact(contact) { const dimensions = useWindowDimensions(); const card = useContext(CardContext); const profile = useContext(ProfileContext); + const display = useContext(DisplayContext); const updateState = (value) => { setState((s) => ({ ...s, ...value })); @@ -143,6 +145,19 @@ export function useContact(contact) { await card.actions.setCardConfirmed(state.cardId); }); }, + deletePrompt: (action) => { + display.actions.showPrompt({ + title: state.strings.loggingOut, + centerButtons: true, + ok: { label: state.strings.confirmLogout, action, failed: () => { + Alert.alert( + state.strings.error, + state.strings.tryAgain, + ); + }}, + cancel: { label: state.strings.cancel }, + }); + }, closeDelete: async () => { await applyAction(async () => { await card.actions.setCardConfirmed(state.cardId);