adding reusable prompt component

This commit is contained in:
Roland Osborne 2023-09-05 14:20:47 -07:00
parent 82092bbe57
commit fe916814ba
7 changed files with 207 additions and 44 deletions

View File

@ -12,15 +12,18 @@ import { RingContextProvider } from 'context/RingContext'
import { ChannelContextProvider } from 'context/ChannelContext'; import { ChannelContextProvider } from 'context/ChannelContext';
import { SafeAreaProvider, SafeAreaView } from 'react-native-safe-area-context'; import { SafeAreaProvider, SafeAreaView } from 'react-native-safe-area-context';
import { ConversationContextProvider } from 'context/ConversationContext'; import { ConversationContextProvider } from 'context/ConversationContext';
import { DisplayContextProvider } from 'context/DisplayContext';
import { LogBox } from 'react-native'; import { LogBox } from 'react-native';
import { Root } from 'src/root/Root'; import { Root } from 'src/root/Root';
import { Access } from 'src/access/Access'; import { Access } from 'src/access/Access';
import { Dashboard } from 'src/dashboard/Dashboard'; import { Dashboard } from 'src/dashboard/Dashboard';
import { Session } from 'src/session/Session'; import { Session } from 'src/session/Session';
import { Prompt } from 'utils/Prompt';
import ReceiveSharingIntent from 'react-native-receive-sharing-intent'; import ReceiveSharingIntent from 'react-native-receive-sharing-intent';
import { Platform, PermissionsAndroid } from 'react-native'; import { Platform, PermissionsAndroid } from 'react-native';
import { initUnifiedPush } from 'react-native-unifiedpush-connector'; import { initUnifiedPush } from 'react-native-unifiedpush-connector';
// silence warning: Sending `onAnimatedValueUpdate` with no listeners registered // silence warning: Sending `onAnimatedValueUpdate` with no listeners registered
//LogBox.ignoreLogs(['Sending']); //LogBox.ignoreLogs(['Sending']);
@ -58,21 +61,24 @@ export default function App() {
<AccountContextProvider> <AccountContextProvider>
<ProfileContextProvider> <ProfileContextProvider>
<ConversationContextProvider> <ConversationContextProvider>
<AppContextProvider> <DisplayContextProvider>
<SafeAreaProvider> <AppContextProvider>
<NativeRouter> <SafeAreaProvider>
<Routes> <NativeRouter>
<Route path="/" element={ <Root /> } /> <Routes>
<Route path="/admin" element={ <Access mode="admin" /> } /> <Route path="/" element={ <Root /> } />
<Route path="/dashboard" element={ <Dashboard /> } /> <Route path="/admin" element={ <Access mode="admin" /> } />
<Route path="/login" element={ <Access mode="login" /> } /> <Route path="/dashboard" element={ <Dashboard /> } />
<Route path="/reset" element={ <Access mode="reset" /> } /> <Route path="/login" element={ <Access mode="login" /> } />
<Route path="/create" element={ <Access mode="create" /> } /> <Route path="/reset" element={ <Access mode="reset" /> } />
<Route path="/session" element={ <Session sharing={sharing} clearSharing={clearSharing} /> } /> <Route path="/create" element={ <Access mode="create" /> } />
</Routes> <Route path="/session" element={ <Session sharing={sharing} clearSharing={clearSharing} /> } />
</NativeRouter> </Routes>
</SafeAreaProvider> <Prompt />
</AppContextProvider> </NativeRouter>
</SafeAreaProvider>
</AppContextProvider>
</DisplayContextProvider>
</ConversationContextProvider> </ConversationContextProvider>
</ProfileContextProvider> </ProfileContextProvider>
</AccountContextProvider> </AccountContextProvider>

View File

@ -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 (
<DisplayContext.Provider value={{ state, actions }}>
{children}
</DisplayContext.Provider>
);
}

View File

@ -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 }
}

View File

@ -207,7 +207,7 @@ export function Settings() {
<Text style={styles.label}>{ state.strings.account }</Text> <Text style={styles.label}>{ state.strings.account }</Text>
<View style={styles.group}> <View style={styles.group}>
<TouchableOpacity style={styles.entry} activeOpacity={1} onPress={actions.showLogout}> <TouchableOpacity style={styles.entry} activeOpacity={1} onPress={actions.promptLogout}>
<View style={styles.icon}> <View style={styles.icon}>
<MatIcons name="logout" size={20} color={Colors.linkText} /> <MatIcons name="logout" size={20} color={Colors.linkText} />
</View> </View>
@ -466,28 +466,6 @@ export function Settings() {
</BlurView> </BlurView>
</Modal> </Modal>
<Modal
animationType="fade"
transparent={true}
visible={state.logout}
supportedOrientations={['portrait', 'landscape']}
onRequestClose={actions.hideLogout}
>
<BlurView style={styles.modalOverlay} blurType={Colors.overlay} blurAmount={2} reducedTransparencyFallbackColor="black">
<View style={styles.modalContainer}>
<Text style={styles.modalHeader}>{ state.strings.loggingOut }</Text>
<View style={styles.buttons}>
<TouchableOpacity style={styles.cancelButton} activeOpacity={1} onPress={actions.hideLogout}>
<Text style={styles.enabledButtonText}>{ state.strings.cancel }</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.promptButton} activeOpacity={1} onPress={logout}>
<Text style={styles.enabledButtonText}>{ state.strings.confirmLogout }</Text>
</TouchableOpacity>
</View>
</View>
</BlurView>
</Modal>
<Modal <Modal
animationType="fade" animationType="fade"
transparent={true} transparent={true}

View File

@ -5,6 +5,7 @@ import { AccountContext } from 'context/AccountContext';
import { CardContext } from 'context/CardContext'; import { CardContext } from 'context/CardContext';
import { AppContext } from 'context/AppContext'; import { AppContext } from 'context/AppContext';
import { generateSeal, updateSeal, unlockSeal } from 'context/sealUtil'; import { generateSeal, updateSeal, unlockSeal } from 'context/sealUtil';
import { DisplayContext } from 'context/DisplayContext';
export function useSettings() { export function useSettings() {
@ -12,6 +13,7 @@ export function useSettings() {
const account = useContext(AccountContext); const account = useContext(AccountContext);
const app = useContext(AppContext); const app = useContext(AppContext);
const card = useContext(CardContext); const card = useContext(CardContext);
const display = useContext(DisplayContext);
const debounce = useRef(null); const debounce = useRef(null);
const checking = useRef(null); const checking = useRef(null);
@ -30,7 +32,6 @@ export function useSettings() {
confirm: null, confirm: null,
delete: null, delete: null,
logout: false,
editSeal: false, editSeal: false,
sealEnabled: false, sealEnabled: false,
sealUnlocked: false, sealUnlocked: false,
@ -199,11 +200,12 @@ export function useSettings() {
hideDelete: () => { hideDelete: () => {
updateState({ delete: false }); updateState({ delete: false });
}, },
showLogout: () => { promptLogout: () => {
updateState({ logout: true }); display.actions.showModal(
}, state.strings.loggingOut,
hideLogout: () => { { label: state.strings.cancel },
updateState({ logout: false }); { label: state.strings.confirmLogout, action: app.actions.logout }
);
}, },
showEditSeal: () => { showEditSeal: () => {
updateState({ editSeal: true, sealPassword: '', hidePassword: true, hideConfirm: true, updateState({ editSeal: true, sealPassword: '', hidePassword: true, hideConfirm: true,

View File

@ -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 (
<Modal
animationType="fade"
transparent={true}
visible={display.state.modal}
supportedOrientations={['portrait', 'landscape']}
onRequestClose={display.actions.hideModal}
>
<BlurView style={styles.modalOverlay} blurType={Colors.overlay} blurAmount={2} reducedTransparencyFallbackColor="black">
<View style={styles.modalContainer}>
<Text style={styles.modalHeader}>{ display.state.modalTitle }</Text>
<View style={styles.modalButtons}>
{ display.state.modalCancel && (
<TouchableOpacity style={styles.cancelButton} activeOpacity={1} onPress={display.actions.hideModal}>
<Text style={styles.cancelButtonText}>{ display.state.modalCancel.label }</Text>
</TouchableOpacity>
)}
{ display.state.modalOk && (
<TouchableOpacity style={styles.okButton} activeOpacity={1} onPress={okModal}>
<Text style={styles.okButtonText}>{ display.state.modalOk.label }</Text>
</TouchableOpacity>
)}
</View>
</View>
</BlurView>
</Modal>
);
}

View File

@ -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',
},
});