mirror of
https://github.com/balzack/databag.git
synced 2025-02-12 03:29:16 +00:00
updating sealing modal
This commit is contained in:
parent
249a96936a
commit
41b72427c4
@ -1,15 +1,29 @@
|
||||
import { useState } from 'react';
|
||||
import { ScrollView, View, Text, Switch, TouchableOpacity } from 'react-native';
|
||||
import { ActivityIndicator, KeyboardAvoidingView, Modal, ScrollView, View, Switch, Text, TextInput, TouchableOpacity, Alert } from 'react-native';
|
||||
import { SafeAreaProvider, SafeAreaView } from 'react-native-safe-area-context';
|
||||
import { styles } from './Settings.styled';
|
||||
import { useSettings } from './useSettings.hook';
|
||||
import MatIcons from 'react-native-vector-icons/MaterialCommunityIcons';
|
||||
import Ionicons from 'react-native-vector-icons/AntDesign';
|
||||
import Colors from 'constants/Colors';
|
||||
|
||||
export function Settings() {
|
||||
|
||||
const { state, actions } = useSettings();
|
||||
|
||||
const saveSeal = async () => {
|
||||
try {
|
||||
await actions.saveSeal();
|
||||
actions.hideEditSeal();
|
||||
}
|
||||
catch (err) {
|
||||
console.log(err);
|
||||
Alert.alert(
|
||||
'Failed to Update Topic Sealing',
|
||||
'Please try again.',
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<ScrollView style={styles.content}>
|
||||
<SafeAreaView edges={['top']}>
|
||||
@ -28,7 +42,7 @@ export function Settings() {
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
<View style={styles.divider} />
|
||||
<TouchableOpacity style={styles.entry} activeOpacity={1}>
|
||||
<TouchableOpacity style={styles.entry} activeOpacity={1} onPress={actions.showEditSeal}>
|
||||
<View style={styles.icon}>
|
||||
<MatIcons name="lock-outline" size={20} color={Colors.linkText} />
|
||||
</View>
|
||||
@ -172,6 +186,164 @@ export function Settings() {
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
<Modal
|
||||
animationType="fade"
|
||||
transparent={true}
|
||||
visible={state.editSeal}
|
||||
supportedOrientations={['portrait', 'landscape']}
|
||||
onRequestClose={actions.hideEditSeal}
|
||||
>
|
||||
<KeyboardAvoidingView behavior="height" style={styles.modalWrapper}>
|
||||
<View style={styles.modalContainer}>
|
||||
<Text style={styles.modalHeader}>Sealed Topics:</Text>
|
||||
<View style={styles.sealable}>
|
||||
<TouchableOpacity onPress={() => actions.setSealEnable(!state.sealEnabled)} activeOpacity={1}>
|
||||
<Text style={styles.sealableText}>Enable Sealed Topics</Text>
|
||||
</TouchableOpacity>
|
||||
<Switch style={styles.enableSwitch} value={state.sealEnabled} onValueChange={actions.setSealEnable} trackColor={styles.switch}/>
|
||||
</View>
|
||||
{ state.sealMode === 'unlocking' && (
|
||||
<>
|
||||
{ !state.showSealUnlock && (
|
||||
<View style={styles.inputField}>
|
||||
<TextInput style={styles.input} value={state.sealUnlock} onChangeText={actions.setSealUnlock}
|
||||
autoCapitalize={'none'} secureTextEntry={true} placeholder="Password for Seal"
|
||||
placeholderTextColor={Colors.grey} />
|
||||
<TouchableOpacity onPress={actions.showSealUnlock}>
|
||||
<Ionicons style={styles.icon} name="eyeo" size={18} color="#888888" />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
)}
|
||||
{ state.showSealUnlock && (
|
||||
<View style={styles.inputField}>
|
||||
<TextInput style={styles.input} value={state.sealUnlock} onChangeText={actions.setSealUnlock}
|
||||
autoCapitalize={'none'} secureTextEntry={false} placeholder="Password for Seal"
|
||||
placeholderTextColor={Colors.grey} />
|
||||
<TouchableOpacity onPress={actions.hideSealUnlock}>
|
||||
<Ionicons style={styles.icon} name="eye" size={18} color="#888888" />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
{ (state.sealMode === 'updating' || state.sealMode === 'enabling') && (
|
||||
<>
|
||||
{ !state.showSealPassword && (
|
||||
<View style={styles.inputField}>
|
||||
<TextInput style={styles.input} value={state.sealPassword} onChangeText={actions.setSealPassword}
|
||||
autoCapitalize={'none'} secureTextEntry={true} placeholder="Password for Seal"
|
||||
placeholderTextColor={Colors.grey} />
|
||||
<TouchableOpacity onPress={actions.showSealPassword}>
|
||||
<Ionicons style={styles.icon} name="eyeo" size={18} color="#888888" />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
)}
|
||||
{ state.showSealPassword && (
|
||||
<View style={styles.inputField}>
|
||||
<TextInput style={styles.input} value={state.sealPassword} onChangeText={actions.setSealPassword}
|
||||
autoCapitalize={'none'} secureTextEntry={false} placeholder="Password for Seal"
|
||||
placeholderTextColor={Colors.grey} />
|
||||
<TouchableOpacity onPress={actions.hideSealPassword}>
|
||||
<Ionicons style={styles.icon} name="eye" size={18} color="#888888" />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
)}
|
||||
{ !state.showSealConfirm && (
|
||||
<View style={styles.inputField}>
|
||||
<TextInput style={styles.input} value={state.sealConfirm} onChangeText={actions.setSealConfirm}
|
||||
autoCapitalize={'none'} secureTextEntry={true} placeholder="Confirm Password"
|
||||
placeholderTextColor={Colors.grey} />
|
||||
<TouchableOpacity onPress={actions.showSealConfirm}>
|
||||
<Ionicons style={styles.icon} name="eyeo" size={18} color="#888888" />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
)}
|
||||
{ state.showSealConfirm && (
|
||||
<View style={styles.inputField}>
|
||||
<TextInput style={styles.input} value={state.sealConfirm} onChangeText={actions.setSealConfirm}
|
||||
autoCapitalize={'none'} secureTextEntry={false} placeholder="Confirm Password"
|
||||
placeholderTextColor={Colors.grey} />
|
||||
<TouchableOpacity onPress={actions.hideSealConfirm}>
|
||||
<Ionicons style={styles.icon} name="eye" size={18} color="#888888" />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
)}
|
||||
<Text style={styles.notice}>saving can take a few minutes</Text>
|
||||
</>
|
||||
)}
|
||||
{ state.sealMode === 'disabling' && (
|
||||
<View style={styles.inputField}>
|
||||
<Ionicons style={styles.warn} name="exclamationcircleo" size={18} color="#888888" />
|
||||
<TextInput style={styles.input} value={state.sealDelete} onChangeText={actions.setSealDelete}
|
||||
autoCapitalize={'none'} placeholder="Type 'delete' to remove sealing key"
|
||||
placeholderTextColor={Colors.grey} />
|
||||
</View>
|
||||
)}
|
||||
{ state.sealMode === 'unlocked' && (
|
||||
<View style={styles.inputField}>
|
||||
<TextInput style={styles.input} value={'xxxxxxxx'} editable={false} secureTextEntry={true} />
|
||||
<Ionicons style={styles.icon} name="eyeo" size={18} color="#888888" />
|
||||
<TouchableOpacity style={styles.sealUpdate} onPress={actions.updateSeal} />
|
||||
</View>
|
||||
)}
|
||||
<View style={styles.modalControls}>
|
||||
<TouchableOpacity style={styles.cancel} onPress={actions.hideEditSeal}>
|
||||
<Text style={styles.canceltext}>Cancel</Text>
|
||||
</TouchableOpacity>
|
||||
{ state.canSaveSeal && (
|
||||
<>
|
||||
{ state.sealMode !== 'unlocking' && state.sealMode !== 'unlocked' && (
|
||||
<TouchableOpacity style={styles.save} onPress={saveSeal}>
|
||||
{ state.saving && (
|
||||
<ActivityIndicator style={styles.activity} color={Colors.white} />
|
||||
)}
|
||||
<Text style={styles.saveText}>Save</Text>
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
{ state.sealMode === 'unlocked' && (
|
||||
<TouchableOpacity style={styles.save} onPress={saveSeal}>
|
||||
{ state.saving && (
|
||||
<ActivityIndicator style={styles.activity} color={Colors.white} />
|
||||
)}
|
||||
<Text style={styles.saveText}>Forget</Text>
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
{ state.sealMode === 'unlocking' && (
|
||||
<TouchableOpacity style={styles.save} onPress={saveSeal}>
|
||||
{ state.saving && (
|
||||
<ActivityIndicator style={styles.activity} color={Colors.white} />
|
||||
)}
|
||||
<Text style={styles.saveText}>Unlock</Text>
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
{ !state.canSaveSeal && (
|
||||
<>
|
||||
{ state.sealMode !== 'unlocking' && (
|
||||
<View style={styles.disabled}>
|
||||
{ state.saving && (
|
||||
<ActivityIndicator style={styles.activity} color={Colors.white} />
|
||||
)}
|
||||
<Text style={styles.disabledText}>Save</Text>
|
||||
</View>
|
||||
)}
|
||||
{ state.sealMode === 'unlocking' && (
|
||||
<View style={styles.disabled}>
|
||||
{ state.saving && (
|
||||
<ActivityIndicator style={styles.activity} color={Colors.white} />
|
||||
)}
|
||||
<Text style={styles.disabledText}>Unlock</Text>
|
||||
</View>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
|
||||
</View>
|
||||
</View>
|
||||
</KeyboardAvoidingView>
|
||||
</Modal>
|
||||
|
||||
</SafeAreaView>
|
||||
</ScrollView>
|
||||
);
|
||||
|
@ -104,5 +104,127 @@ export const styles = StyleSheet.create({
|
||||
notifications: {
|
||||
transform: [{ scaleX: .6 }, { scaleY: .6 }],
|
||||
},
|
||||
|
||||
modalWrapper: {
|
||||
display: 'flex',
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
backgroundColor: 'rgba(52, 52, 52, 0.8)'
|
||||
},
|
||||
modalContainer: {
|
||||
backgroundColor: Colors.formBackground,
|
||||
padding: 16,
|
||||
width: '80%',
|
||||
maxWidth: 400,
|
||||
},
|
||||
modalHeader: {
|
||||
fontSize: 18,
|
||||
paddingBottom: 16,
|
||||
color: Colors.text,
|
||||
},
|
||||
input: {
|
||||
fontSize: 14,
|
||||
flexGrow: 1,
|
||||
color: Colors.text,
|
||||
},
|
||||
inputField: {
|
||||
width: '100%',
|
||||
borderWidth: 1,
|
||||
borderColor: Colors.lightgrey,
|
||||
borderRadius: 4,
|
||||
padding: 8,
|
||||
marginBottom: 8,
|
||||
maxHeight: 92,
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
},
|
||||
canceltext: {
|
||||
color: Colors.text,
|
||||
},
|
||||
modalList: {
|
||||
width: '100%',
|
||||
borderWidth: 1,
|
||||
borderColor: Colors.lightgrey,
|
||||
borderRadius: 2,
|
||||
},
|
||||
modalControls: {
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'flex-end',
|
||||
},
|
||||
cancel: {
|
||||
borderWidth: 1,
|
||||
borderColor: Colors.lightgrey,
|
||||
borderRadius: 4,
|
||||
padding: 8,
|
||||
marginRight: 8,
|
||||
width: 88,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
},
|
||||
save: {
|
||||
padding: 8,
|
||||
borderRadius: 4,
|
||||
backgroundColor: Colors.primary,
|
||||
width: 88,
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
saveText: {
|
||||
color: Colors.white,
|
||||
},
|
||||
disabled: {
|
||||
borderWidth: 1,
|
||||
borderColor: Colors.lightgrey,
|
||||
padding: 8,
|
||||
borderRadius: 4,
|
||||
width: 88,
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
activity: {
|
||||
paddingRight: 4,
|
||||
},
|
||||
disabledText: {
|
||||
color: Colors.disabled,
|
||||
},
|
||||
sealUpdate: {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
height: 36,
|
||||
left: 8,
|
||||
width: '100%',
|
||||
},
|
||||
sealableText: {
|
||||
color: Colors.text,
|
||||
},
|
||||
sealable: {
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
paddingBottom: 16,
|
||||
},
|
||||
enable: {
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
width: '100%',
|
||||
marginBottom: 4,
|
||||
},
|
||||
enableText: {
|
||||
color: Colors.primary,
|
||||
fontSize: 16,
|
||||
},
|
||||
enableSwitch: {
|
||||
transform: [{ scaleX: .6 }, { scaleY: .6 }],
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -1,15 +1,34 @@
|
||||
import { useState, useEffect, useRef, useContext } from 'react';
|
||||
import { getLanguageStrings } from 'constants/Strings';
|
||||
import { ProfileContext } from 'context/ProfileContext';
|
||||
import { AccountContext } from 'context/AccountContext';
|
||||
import { generateSeal, updateSeal, unlockSeal } from 'context/sealUtil';
|
||||
|
||||
export function useSettings() {
|
||||
|
||||
const profile = useContext(ProfileContext);
|
||||
const account = useContext(AccountContext);
|
||||
|
||||
const [state, setState] = useState({
|
||||
strings: getLanguageStrings(),
|
||||
timeFull: false,
|
||||
monthLast: false,
|
||||
|
||||
editSeal: false,
|
||||
sealMode: null,
|
||||
sealUnlock: null,
|
||||
sealPassword: null,
|
||||
sealConfirm: null,
|
||||
sealDelete: null,
|
||||
seal: null,
|
||||
sealKey: null,
|
||||
sealEnabled: false,
|
||||
sealUnlocked: false,
|
||||
sealable: false,
|
||||
canSaveSeal: false,
|
||||
showSealUnlock: false,
|
||||
showSealConfirm: false,
|
||||
showSealPassword: false,
|
||||
});
|
||||
|
||||
const updateState = (value) => {
|
||||
@ -19,7 +38,57 @@ export function useSettings() {
|
||||
useEffect(() => {
|
||||
const { timeFull, monthLast } = profile.state;
|
||||
updateState({ timeFull, monthLast });
|
||||
}, [profile.state]);
|
||||
}, [profile.state.timeFull, profile.state.monthLast]);
|
||||
|
||||
useEffect(() => {
|
||||
const { seal, sealable } = account.state.status;
|
||||
const sealKey = account.state.sealKey;
|
||||
const sealEnabled = seal?.publicKey != null;
|
||||
const sealUnlocked = seal?.publicKey === sealKey?.public && sealKey?.private && sealKey?.public;
|
||||
updateState({ sealable, seal, sealKey, sealEnabled, sealUnlocked });
|
||||
}, [account.state]);
|
||||
|
||||
const unlock = async () => {
|
||||
const sealKey = unlockSeal(state.seal, state.sealUnlock);
|
||||
await account.actions.unlockAccountSeal(sealKey);
|
||||
};
|
||||
|
||||
const forget = async () => {
|
||||
await account.actions.unlockAccountSeal({});
|
||||
}
|
||||
|
||||
const update = async () => {
|
||||
const updated = updateSeal(state.seal, state.sealKey, state.sealPassword);
|
||||
await account.actions.setAccountSeal(updated.seal, updated.sealKey);
|
||||
}
|
||||
|
||||
const enable = async () => {
|
||||
const created = await generateSeal(state.sealPassword);
|
||||
await account.actions.setAccountSeal(created.seal, created.sealKey);
|
||||
}
|
||||
|
||||
const disable = async () => {
|
||||
await account.actions.setAccountSeal({}, {});
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (state.sealMode === 'unlocked') {
|
||||
return updateState({ canSaveSeal: true });
|
||||
}
|
||||
if (state.sealMode === 'unlocking' && state.sealUnlock != null && state.sealUnlock !== '') {
|
||||
return updateState({ canSaveSeal: true });
|
||||
}
|
||||
if (state.sealMode === 'enabling' && state.sealPassword != null && state.sealPassword === state.sealConfirm) {
|
||||
return updateState({ canSaveSeal: true });
|
||||
}
|
||||
if (state.sealMode === 'disabling' && state.sealDelete === 'delete') {
|
||||
return updateState({ canSaveSeal: true });
|
||||
}
|
||||
if (state.sealMode === 'updating' && state.sealPassword != null && state.sealPassword === state.sealConfirm) {
|
||||
return updateState({ canSaveSeal: true });
|
||||
}
|
||||
updateState({ canSaveSeal: false });
|
||||
}, [state.sealMode, state.sealable, state.sealUnlock, state.sealPassword, state.sealConfirm, state.sealDelete]);
|
||||
|
||||
const actions = {
|
||||
setTimeFull: async (flag) => {
|
||||
@ -30,6 +99,89 @@ export function useSettings() {
|
||||
updateState({ monthLast: flag });
|
||||
await profile.actions.setMonthLast(flag);
|
||||
},
|
||||
showEditSeal: () => {
|
||||
let sealMode = null;
|
||||
const sealable = state.sealEnabled;
|
||||
if (state.sealEnabled && !state.sealUnlocked) {
|
||||
sealMode = 'unlocking';
|
||||
}
|
||||
else if (state.sealEnabled && state.sealUnlocked) {
|
||||
sealMode = 'unlocked';
|
||||
}
|
||||
else {
|
||||
sealMode = 'disabled';
|
||||
}
|
||||
updateState({ editSeal: true, sealMode, sealUnlock: null, sealPassword: null, sealConfirm: null, sealDelete: null });
|
||||
},
|
||||
hideEditSeal: () => {
|
||||
updateState({ editSeal: false });
|
||||
},
|
||||
setSealUnlock: (sealUnlock) => {
|
||||
updateState({ sealUnlock });
|
||||
},
|
||||
setSealPassword: (sealPassword) => {
|
||||
updateState({ sealPassword });
|
||||
},
|
||||
setSealConfirm: (sealConfirm) => {
|
||||
updateState({ sealConfirm });
|
||||
},
|
||||
setSealDelete: (sealDelete) => {
|
||||
updateState({ sealDelete });
|
||||
},
|
||||
showSealUnlock: () => {
|
||||
updateState({ showSealUnlock: true });
|
||||
},
|
||||
hideSealUnlock: () => {
|
||||
updateState({ showSealUnlock: false });
|
||||
},
|
||||
showSealPassword: () => {
|
||||
updateState({ showSealPassword: true });
|
||||
},
|
||||
hideSealPassword: () => {
|
||||
updateState({ showSealPassword: false });
|
||||
},
|
||||
showSealConfirm: () => {
|
||||
updateState({ showSealConfirm: true });
|
||||
},
|
||||
hideSealConfirm: () => {
|
||||
updateState({ showSealConfirm: false });
|
||||
},
|
||||
updateSeal: () => {
|
||||
updateState({ sealMode: 'updating' });
|
||||
},
|
||||
saveSeal: async () => {
|
||||
if (!state.saving) {
|
||||
try {
|
||||
updateState({ saving: true });
|
||||
|
||||
if (state.sealMode === 'enabling') {
|
||||
await enable();
|
||||
}
|
||||
else if (state.sealMode === 'disabling') {
|
||||
await disable();
|
||||
}
|
||||
else if (state.sealMode === 'unlocking') {
|
||||
await unlock();
|
||||
}
|
||||
else if (state.sealMode === 'unlocked') {
|
||||
await forget();
|
||||
}
|
||||
else if (state.sealMode === 'updating') {
|
||||
await update();
|
||||
}
|
||||
else {
|
||||
console.log(state.sealMode);
|
||||
}
|
||||
|
||||
updateState({ saving: false });
|
||||
}
|
||||
catch(err) {
|
||||
console.log(err);
|
||||
updateState({ saving: false });
|
||||
throw new Error('seal operation failed');
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
return { state, actions };
|
||||
|
Loading…
Reference in New Issue
Block a user