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