From fe916814ba8425a01a828401578a86caba93a67f Mon Sep 17 00:00:00 2001 From: Roland Osborne Date: Tue, 5 Sep 2023 14:20:47 -0700 Subject: [PATCH] adding reusable prompt component --- app/mobile/App.js | 36 +++++--- app/mobile/src/context/DisplayContext.js | 14 +++ .../src/context/useDisplayContext.hook.js | 26 ++++++ app/mobile/src/session/settings/Settings.jsx | 24 +---- .../src/session/settings/useSettings.hook.js | 14 +-- app/mobile/src/utils/Prompt.jsx | 46 ++++++++++ app/mobile/src/utils/Prompt.styled.js | 91 +++++++++++++++++++ 7 files changed, 207 insertions(+), 44 deletions(-) create mode 100644 app/mobile/src/context/DisplayContext.js create mode 100644 app/mobile/src/context/useDisplayContext.hook.js create mode 100644 app/mobile/src/utils/Prompt.jsx create mode 100644 app/mobile/src/utils/Prompt.styled.js diff --git a/app/mobile/App.js b/app/mobile/App.js index 09007cbe..d1784afd 100644 --- a/app/mobile/App.js +++ b/app/mobile/App.js @@ -12,15 +12,18 @@ import { RingContextProvider } from 'context/RingContext' import { ChannelContextProvider } from 'context/ChannelContext'; import { SafeAreaProvider, SafeAreaView } from 'react-native-safe-area-context'; import { ConversationContextProvider } from 'context/ConversationContext'; +import { DisplayContextProvider } from 'context/DisplayContext'; import { LogBox } from 'react-native'; import { Root } from 'src/root/Root'; import { Access } from 'src/access/Access'; import { Dashboard } from 'src/dashboard/Dashboard'; import { Session } from 'src/session/Session'; +import { Prompt } from 'utils/Prompt'; import ReceiveSharingIntent from 'react-native-receive-sharing-intent'; import { Platform, PermissionsAndroid } from 'react-native'; import { initUnifiedPush } from 'react-native-unifiedpush-connector'; + // silence warning: Sending `onAnimatedValueUpdate` with no listeners registered //LogBox.ignoreLogs(['Sending']); @@ -58,21 +61,24 @@ export default function App() { - - - - - } /> - } /> - } /> - } /> - } /> - } /> - } /> - - - - + + + + + + } /> + } /> + } /> + } /> + } /> + } /> + } /> + + + + + + diff --git a/app/mobile/src/context/DisplayContext.js b/app/mobile/src/context/DisplayContext.js new file mode 100644 index 00000000..799cdcd1 --- /dev/null +++ b/app/mobile/src/context/DisplayContext.js @@ -0,0 +1,14 @@ +import { createContext } from 'react'; +import { useDisplayContext } from './useDisplayContext.hook'; + +export const DisplayContext = createContext({}); + +export function DisplayContextProvider({ children }) { + const { state, actions } = useDisplayContext(); + return ( + + {children} + + ); +} + diff --git a/app/mobile/src/context/useDisplayContext.hook.js b/app/mobile/src/context/useDisplayContext.hook.js new file mode 100644 index 00000000..722c958e --- /dev/null +++ b/app/mobile/src/context/useDisplayContext.hook.js @@ -0,0 +1,26 @@ +import { useEffect, useContext, useState, useRef } from 'react'; + +export function useDisplayContext() { + const [state, setState] = useState({ + modal: false, + modalTitle: null, + modalCancel: null, + modalOk: null, + }); + + const updateState = (value) => { + setState((s) => ({ ...s, ...value })) + } + + const actions = { + showModal: (modalTitle, modalCancel, modalOk) => { + updateState({ modal: true, modalTitle, modalCancel, modalOk }); + }, + hideModal: () => { + updateState({ modal: false }); + }, + }; + + return { state, actions } +} + diff --git a/app/mobile/src/session/settings/Settings.jsx b/app/mobile/src/session/settings/Settings.jsx index 29790e08..4836fc78 100644 --- a/app/mobile/src/session/settings/Settings.jsx +++ b/app/mobile/src/session/settings/Settings.jsx @@ -207,7 +207,7 @@ export function Settings() { { state.strings.account } - + @@ -466,28 +466,6 @@ export function Settings() { - - - - { state.strings.loggingOut } - - - { state.strings.cancel } - - - { state.strings.confirmLogout } - - - - - - { updateState({ delete: false }); }, - showLogout: () => { - updateState({ logout: true }); - }, - hideLogout: () => { - updateState({ logout: false }); + promptLogout: () => { + display.actions.showModal( + state.strings.loggingOut, + { label: state.strings.cancel }, + { label: state.strings.confirmLogout, action: app.actions.logout } + ); }, showEditSeal: () => { updateState({ editSeal: true, sealPassword: '', hidePassword: true, hideConfirm: true, diff --git a/app/mobile/src/utils/Prompt.jsx b/app/mobile/src/utils/Prompt.jsx new file mode 100644 index 00000000..7d00a7ae --- /dev/null +++ b/app/mobile/src/utils/Prompt.jsx @@ -0,0 +1,46 @@ +import { useContext } from 'react'; +import { Modal, View, Text, TouchableOpacity } from 'react-native'; +import { DisplayContext } from 'context/DisplayContext'; +import { BlurView } from "@react-native-community/blur"; +import { styles } from './Prompt.styled'; +import { Colors } from 'constants/Colors'; + +export function Prompt() { + const display = useContext(DisplayContext); + + const okModal = () => { + if (display.state.modalOk.action) { + display.state.modalOk.action(); + } + display.actions.hideModal(); + } + + return ( + + + + { display.state.modalTitle } + + { display.state.modalCancel && ( + + { display.state.modalCancel.label } + + )} + { display.state.modalOk && ( + + { display.state.modalOk.label } + + )} + + + + + ); +} + diff --git a/app/mobile/src/utils/Prompt.styled.js b/app/mobile/src/utils/Prompt.styled.js new file mode 100644 index 00000000..beeac4f5 --- /dev/null +++ b/app/mobile/src/utils/Prompt.styled.js @@ -0,0 +1,91 @@ +import { StyleSheet } from 'react-native'; +import { Colors } from 'constants/Colors'; + +export const styles = StyleSheet.create({ + modalOverlay: { + display: 'flex', + width: '100%', + height: '100%', + alignItems: 'center', + justifyContent: 'center', + }, + modalContainer: { + backgroundColor: Colors.modalBase, + width: '80%', + maxWidth: 400, + display: 'flex', + alignItems: 'center', + borderRadius: 8, + }, + modalHeader: { + fontSize: 18, + paddingTop: 16, + color: Colors.labelText, + fontFamily: 'Roboto', + }, + modalDescription: { + textAlign: 'center', + fontSize: 14, + color: Colors.descriptionText, + paddingLeft: 16, + paddingRight: 16, + paddingBottom: 16, + }, + closeButton: { + marginTop: 8, + marginBottom: 16, + marginRight: 16, + paddingTop: 8, + paddingBottom: 8, + paddingLeft: 32, + paddingRight: 32, + borderRadius: 4, + borderWidth: 1, + borderColor: Colors.cancelButton, + backgroundColor: Colors.closeButton, + }, + closeButtonText: { + color: Colors.closeButtonText, + fontFamily: 'Roboto', + }, + cancelButton: { + marginTop: 8, + marginBottom: 16, + marginRight: 16, + paddingTop: 8, + paddingBottom: 8, + paddingLeft: 32, + paddingRight: 32, + borderRadius: 4, + backgroundColor: Colors.cancelButton, + }, + cancelButtonText: { + color: Colors.cancelButtonText, + fontFamily: 'Roboto', + }, + okButton: { + marginTop: 8, + marginBottom: 16, + paddingTop: 8, + paddingBottom: 8, + paddingLeft: 32, + paddingRight: 32, + borderRadius: 4, + backgroundColor: Colors.primaryButton, + }, + okButtonText: { + color: Colors.primaryButtonText, + fontFamily: 'Roboto', + }, + modalButtons: { + width: '100%', + paddingLeft: 16, + paddingRight: 16, + paddingTop: 16, + display: 'flex', + alignItems: 'flex-end', + justifyContent: 'flex-end', + flexDirection: 'row', + }, +}); +