mergin back access screens

This commit is contained in:
Roland Osborne 2023-02-15 15:47:18 -08:00
parent 96e84b2602
commit 6e4bb98ace
37 changed files with 2251 additions and 53 deletions

View File

@ -1,7 +1,7 @@
import 'react-native-gesture-handler';
import React from 'react';
import { NativeRouter } from "react-router-native";
import { Routes, Route } from 'react-router-dom';
import { Root } from 'src/root/Root';
import { StoreContextProvider } from 'context/StoreContext';
import { UploadContextProvider } from 'context/UploadContext';
import { AppContextProvider } from 'context/AppContext';
@ -13,6 +13,10 @@ import { SafeAreaProvider, SafeAreaView } from 'react-native-safe-area-context';
import { NavigationContainer } from '@react-navigation/native';
import { ConversationContextProvider } from 'context/ConversationContext';
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';
// silence warning: Sending `onAnimatedValueUpdate` with no listeners registered
//LogBox.ignoreLogs(['Sending']);
@ -32,6 +36,12 @@ export default function App() {
<NativeRouter>
<Routes>
<Route path="/" element={ <Root /> } />
<Route path="/admin" element={ <Access mode="admin" /> } />
<Route path="/dashboard" element={ <Dashboard /> } />
<Route path="/login" element={ <Access mode="login" /> } />
<Route path="/reset" element={ <Access mode="reset" /> } />
<Route path="/create" element={ <Access mode="create" /> } />
<Route path="/session" element={ <NavigationContainer><Session/></NavigationContainer> } />
</Routes>
</NativeRouter>
</SafeAreaProvider>

View File

@ -1,3 +1,6 @@
module.exports = {
presets: ['module:metro-react-native-babel-preset'],
plugins: [
'react-native-reanimated/plugin',
],
};

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

BIN
app/mobile/images/audio.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

BIN
app/mobile/images/login.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

View File

@ -0,0 +1,3 @@
{
"name": "images"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
app/mobile/images/team.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -1,3 +1,5 @@
import 'react-native-gesture-handler';
/**
* @format
*/

View File

@ -51,5 +51,25 @@
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<key>UIAppFonts</key>
<array>
<string>AntDesign.ttf</string>
<string>Entypo.ttf</string>
<string>EvilIcons.ttf</string>
<string>Feather.ttf</string>
<string>FontAwesome.ttf</string>
<string>FontAwesome5_Brands.ttf</string>
<string>FontAwesome5_Regular.ttf</string>
<string>FontAwesome5_Solid.ttf</string>
<string>Fontisto.ttf</string>
<string>Foundation.ttf</string>
<string>Ionicons.ttf</string>
<string>MaterialCommunityIcons.ttf</string>
<string>MaterialIcons.ttf</string>
<string>Octicons.ttf</string>
<string>SimpleLineIcons.ttf</string>
<string>Zocial.ttf</string>
</array>
</dict>
</plist>

View File

@ -426,6 +426,35 @@ PODS:
- RNFBApp
- RNGestureHandler (2.9.0):
- React-Core
- RNReanimated (2.14.4):
- DoubleConversion
- FBLazyVector
- FBReactNativeSpec
- glog
- RCT-Folly
- RCTRequired
- RCTTypeSafety
- React-callinvoker
- React-Core
- React-Core/DevSupport
- React-Core/RCTWebSocket
- React-CoreModules
- React-cxxreact
- React-jsi
- React-jsiexecutor
- React-jsinspector
- React-RCTActionSheet
- React-RCTAnimation
- React-RCTBlob
- React-RCTImage
- React-RCTLinking
- React-RCTNetwork
- React-RCTSettings
- React-RCTText
- ReactCommon/turbomodule/core
- Yoga
- RNVectorIcons (9.2.0):
- React-Core
- Yoga (1.14.0)
DEPENDENCIES:
@ -471,6 +500,8 @@ DEPENDENCIES:
- "RNFBApp (from `../node_modules/@react-native-firebase/app`)"
- "RNFBMessaging (from `../node_modules/@react-native-firebase/messaging`)"
- RNGestureHandler (from `../node_modules/react-native-gesture-handler`)
- RNReanimated (from `../node_modules/react-native-reanimated`)
- RNVectorIcons (from `../node_modules/react-native-vector-icons`)
- Yoga (from `../node_modules/react-native/ReactCommon/yoga`)
SPEC REPOS:
@ -569,6 +600,10 @@ EXTERNAL SOURCES:
:path: "../node_modules/@react-native-firebase/messaging"
RNGestureHandler:
:path: "../node_modules/react-native-gesture-handler"
RNReanimated:
:path: "../node_modules/react-native-reanimated"
RNVectorIcons:
:path: "../node_modules/react-native-vector-icons"
Yoga:
:path: "../node_modules/react-native/ReactCommon/yoga"
@ -625,6 +660,8 @@ SPEC CHECKSUMS:
RNFBApp: 4f8ea53443d52c7db793234d2398a357fc6cfbf1
RNFBMessaging: c686471358d20d54f716a8b7b7f10f8944c966ec
RNGestureHandler: 071d7a9ad81e8b83fe7663b303d132406a7d8f39
RNReanimated: cc5e3aa479cb9170bcccf8204291a6950a3be128
RNVectorIcons: fcc2f6cb32f5735b586e66d14103a74ce6ad61f8
Yoga: 5ed1699acbba8863755998a4245daa200ff3817b
PODFILE CHECKSUM: 8a4cbf61c865c6e404d389f26395fa04926b8f43

View File

@ -12,7 +12,10 @@
"dependencies": {
"@react-native-firebase/app": "^17.2.0",
"@react-native-firebase/messaging": "^17.2.0",
"@react-navigation/bottom-tabs": "^6.5.5",
"@react-navigation/drawer": "^6.6.0",
"@react-navigation/native": "^6.1.4",
"@react-navigation/native-stack": "^6.9.10",
"axios": "^1.3.3",
"crypto-js": "^4.1.1",
"react": "18.2.0",
@ -20,9 +23,11 @@
"react-native-base64": "^0.2.1",
"react-native-device-info": "^10.4.0",
"react-native-gesture-handler": "^2.9.0",
"react-native-reanimated": "^2.14.4",
"react-native-rsa-native": "^2.0.5",
"react-native-safe-area-context": "^4.5.0",
"react-native-sqlite-storage": "^6.0.1",
"react-native-vector-icons": "^9.2.0",
"react-router-dom": "^6.8.1",
"react-router-native": "^6.8.1"
},

View File

@ -0,0 +1,58 @@
import { SafeAreaView, Image, View } from 'react-native';
import { styles } from './Access.styled';
import { useAccess } from './useAccess.hook';
import { Login } from './login/Login';
import { Create } from './create/Create';
import { Reset } from './reset/Reset';
import { Admin } from './admin/Admin';
import logo from 'images/login.png';
export function Access({ mode }) {
const { state, actions } = useAccess();
return (
<View style={styles.wrapper}>
<SafeAreaView>
{ state.split === true && (
<View style={styles.container}>
<View style={styles.paddedPane}>
<Image style={styles.splash} source={logo} />
</View>
<View style={styles.pane}>
{ mode === 'login' && (
<Login />
)}
{ mode === 'create' && (
<Create />
)}
{ mode === 'reset' && (
<Reset />
)}
{ mode === 'admin' && (
<Admin />
)}
</View>
</View>
)}
{ state.split === false && (
<View style={styles.container}>
{ mode === 'login' && (
<Login />
)}
{ mode === 'create' && (
<Create />
)}
{ mode === 'reset' && (
<Reset />
)}
{ mode === 'admin' && (
<Admin />
)}
</View>
)}
</SafeAreaView>
</View>
);
}

View File

@ -0,0 +1,30 @@
import { StyleSheet } from 'react-native';
import { Colors } from 'constants/Colors';
export const styles = StyleSheet.create({
wrapper: {
backgroundColor: Colors.background,
width: '100%',
height: '100%',
},
container: {
padding: 16,
display: 'flex',
flexDirection: 'row',
},
splash: {
flex: 1,
width: null,
height: null,
resizeMode: 'contain',
},
pane: {
width: '50%',
height: '100%',
},
paddedPane: {
width: '50%',
height: '100%',
paddingRight: 16,
},
});

View File

@ -0,0 +1,78 @@
import { KeyboardAvoidingView, ActivityIndicator, Alert, Text, TextInput, View, TouchableOpacity } from 'react-native';
import { styles } from './Admin.styled';
import Ionicons from 'react-native-vector-icons/AntDesign';
import { useAdmin } from './useAdmin.hook';
import Colors from 'constants/Colors';
export function Admin() {
const { state, actions } = useAdmin();
const admin = async () => {
try {
await actions.access();
}
catch (err) {
Alert.alert(
"Access Failed",
"Please check your server and token.",
);
}
}
return (
<KeyboardAvoidingView style={styles.wrapper} behavior="padding" enabled={Platform.OS === 'ios' ? true : false}>
<View style={styles.container}>
<View style={styles.control}>
<TouchableOpacity onPress={actions.login}>
<Ionicons style={styles.config} name="user" size={24} color="#aaaaaa" />
</TouchableOpacity>
</View>
<Text style={styles.title}>Databag</Text>
<View style={styles.spacemid}>
<Text style={styles.header}>Admin Acess</Text>
</View>
<View style={styles.spacetop}>
<View style={styles.inputwrapper}>
<Ionicons style={styles.icon} name="database" size={18} color="#aaaaaa" />
<TextInput style={styles.inputfield} value={state.server} onChangeText={actions.setServer}
autoCorrect={false} autoCapitalize="none" placeholder="server" placeholderTextColor={Colors.grey} />
<View style={styles.space} />
</View>
<View style={styles.inputwrapper}>
<Ionicons style={styles.icon} name="key" size={18} color="#aaaaaa" />
<TextInput style={styles.inputfield} value={state.token} onChangeText={actions.setToken}
secureTextEntry={!state.plainText} autoCapitalize="none" placeholder="token"
placeholderTextColor={Colors.grey} />
<TouchableOpacity>
{ state.plainText && (
<Ionicons style={styles.icon} name="eye" size={18} color="#aaaaaa" onPress={actions.hidePass}/>
)}
{ !state.plainText && (
<Ionicons style={styles.icon} name="eyeo" size={18} color="#aaaaaa" onPress={actions.showPass}/>
)}
</TouchableOpacity>
</View>
{ state.enabled && (
<TouchableOpacity style={styles.reset} onPress={admin}>
{ state.busy && (
<ActivityIndicator size="small" color="#ffffff" />
)}
{ !state.busy && (
<Text style={styles.resettext}>Access</Text>
)}
</TouchableOpacity>
)}
{ !state.enabled && (
<View style={styles.noreset}>
<Text style={styles.noresettext}>Access</Text>
</View>
)}
</View>
<View style={styles.version}>
<Text style={styles.versiontext}>v{ state.version }</Text>
</View>
</View>
</KeyboardAvoidingView>
);
}

View File

@ -0,0 +1,120 @@
import { StyleSheet } from 'react-native';
import { Colors } from 'constants/Colors';
export const styles = StyleSheet.create({
wrapper: {
width: '100%',
height: '100%',
},
config: {
paddingTop: 8,
},
icon: {
padding: 8,
},
space: {
width: 32,
},
container: {
flexDirection: 'column',
backgroundColor: Colors.formBackground,
borderRadius: 4,
width: '100%',
height: '100%',
display: 'flex',
paddingLeft: 16,
paddingRight: 16,
},
control: {
display: 'flex',
flexDirection: 'row',
justifyContent: 'flex-end',
color: Colors.grey,
},
title: {
width: '100%',
textAlign: 'center',
fontSize: 24,
color: Colors.grey,
},
spacemid: {
flexGrow: 1,
flexDirection: 'column',
textAlign: 'center',
alignItems: 'center',
justifyContent: 'center',
width: '100%',
},
spacetop: {
flexGrow: 1,
flexDirection: 'column',
textAlign: 'center',
alignItems: 'center',
justifyContent: 'flex-start',
width: '100%',
},
header: {
fontSize: 32,
color: Colors.text,
},
inputwrapper: {
display: 'flex',
flexDirection: 'row',
width: '100%',
borderRadius: 4,
borderColor: Colors.divider,
borderWidth: 1,
marginBottom: 16,
alignItems: 'center',
},
inputfield: {
flex: 1,
textAlign: 'center',
padding: 8,
},
reset: {
marginTop: 16,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
width: 128,
height: 28,
backgroundColor: Colors.primary,
borderRadius: 4,
},
resettext: {
color: Colors.formFocus,
},
noreset: {
marginTop: 16,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
width: 128,
height: 28,
borderRadius: 4,
borderColor: Colors.divider,
borderWidth: 1,
},
noresettext: {
color: Colors.grey,
},
login: {
marginTop: 16,
},
logintext: {
color: 'yellow',
},
nologintext: {
color: Colors.disabled,
},
version: {
display: 'flex',
alignItems: 'flex-end',
},
versiontext: {
color: Colors.grey,
fontSize: 14,
},
})

View File

@ -0,0 +1,90 @@
import { useState, useEffect, useContext } from 'react';
import { useWindowDimensions } from 'react-native';
import { useNavigate } from 'react-router-dom';
import { AppContext } from 'context/AppContext';
import { getNodeStatus } from 'api/getNodeStatus';
import { setNodeStatus } from 'api/setNodeStatus';
import { getNodeConfig } from 'api/getNodeConfig';
export function useAdmin() {
const navigate = useNavigate();
const app = useContext(AppContext);
const [state, setState] = useState({
busy: false,
enabled: false,
server: null,
token: null,
plainText: false,
version: null,
});
const updateState = (value) => {
setState((s) => ({ ...s, ...value }));
}
useEffect(() => {
updateState({ version: app.state.version });
}, [app]);
const checkStatus = async () => {
try {
updateState({ unclaimed: status });
}
catch (err) {
console.log("failed to check node status");
}
};
useEffect(() => {
if (state.token && state.server && !state.enabled) {
updateState({ enabled: true });
}
if ((!state.token || !state.server) && state.enabled) {
updateState({ enabled: false });
}
}, [state.server, state.token]);
const actions = {
setServer: (server) => {
updateState({ server });
},
setToken: (token) => {
updateState({ token });
},
login: () => {
navigate('/login');
},
showPass: () => {
updateState({ plainText: true });
},
hidePass: () => {
updateState({ plainText: false });
},
access: async () => {
if (!state.busy) {
try {
updateState({ busy: true });
const node = state.server.trim();
const token = state.token;
const unclaimed = await getNodeStatus(node);
if (unclaimed) {
await setNodeStatus(node, token);
}
const config = await getNodeConfig(node, token);
updateState({ server: node, busy: false });
navigate('/dashboard', { state: { config, server: node, token }});
}
catch (err) {
console.log(err);
updateState({ busy: false });
throw new Error("access failed");
}
}
}
};
return { state, actions };
}

View File

@ -0,0 +1,164 @@
import { KeyboardAvoidingView, ScrollView, ActivityIndicator, Alert, Text, TextInput, View, TouchableOpacity } from 'react-native';
import { styles } from './Create.styled';
import Ionicons from 'react-native-vector-icons/AntDesign';
import { useCreate } from './useCreate.hook';
import Colors from 'constants/Colors';
export function Create() {
const { state, actions } = useCreate();
const create = async () => {
try {
await actions.create();
}
catch (err) {
Alert.alert(
"Create Failed",
"Please check your server and token.",
);
}
}
const validServer = (state.server && state.serverChecked && state.serverValid);
const validToken = (!state.tokenRequired || (state.token && state.tokenChecked && state.tokenValid));
const validUsername = (state.username && state.usernameChecked && state.usernameValid);
return (
<KeyboardAvoidingView style={styles.wrapper} behavior="padding" enabled={Platform.OS === 'ios' ? true : false}>
<View style={styles.container}>
<View style={styles.control}>
<TouchableOpacity onPress={actions.config}>
<Ionicons style={styles.config} name="setting" size={24} color="#aaaaaa" />
</TouchableOpacity>
</View>
<Text style={styles.title}>Databag</Text>
<View style={styles.spacemid}>
<Text style={styles.header}>Create Account</Text>
</View>
<ScrollView style={styles.spacetop}>
<View style={styles.inputwrapper}>
<Ionicons style={styles.icon} name="database" size={18} color="#888888" />
<TextInput style={styles.inputfield} value={state.server} onChangeText={actions.setServer}
autoCorrect={false} autoCapitalize="none" placeholder="server" placeholderTextColor={Colors.grey} />
<View style={styles.space}>
{ (!state.server || !state.serverChecked) && (
<Text style={styles.required}></Text>
)}
{ state.server && state.serverChecked && !state.serverValid && (
<Ionicons style={styles.icon} name="exclamationcircleo" size={18} color="#ff8888" />
)}
{ state.server && state.serverChecked && state.serverValid && (
<Ionicons style={styles.icon} name="checkcircleo" size={18} color="#448866" />
)}
</View>
</View>
<View style={styles.token}>
{ state.tokenRequired && (
<View style={styles.inputwrapper}>
<Ionicons style={styles.icon} name="key" size={18} color="#888888" />
<TextInput style={styles.inputfield} value={state.token} onChangeText={actions.setToken}
autoCorrect={false} autoCapitalize="none" placeholder="token" placeholderTextColor={Colors.grey} />
<View style={styles.space}>
{ (!validServer || !state.token || !state.tokenChecked) && (
<Text style={styles.required}></Text>
)}
{ validServer && state.token && state.tokenChecked && !state.tokenValid && (
<Ionicons style={styles.icon} name="exclamationcircleo" size={18} color="#ff8888" />
)}
{ validServer && state.token && state.tokenChecked && state.tokenValid && (
<Ionicons style={styles.icon} name="checkcircleo" size={18} color="#448866" />
)}
</View>
</View>
)}
{ !state.tokenRequired && state.server === 'databag.coredb.org' && (
<View style={styles.demo}>
<Text style={styles.demoText}>The default public server is to test out the system. Use a private server othersize.</Text>
</View>
)}
</View>
<View style={styles.inputwrapper}>
<Ionicons style={styles.icon} name="user" size={18} color="#888888" />
<TextInput style={styles.inputfield} value={state.username} onChangeText={actions.setUsername}
autoCorrect={false} autoCapitalize="none" placeholder="username" placeholderTextColor={Colors.grey} />
<View style={styles.space}>
{ (!validServer || !validToken || !state.username || !state.usernameChecked) && (
<Text style={styles.required}></Text>
)}
{ validServer && validToken && state.username && state.usernameChecked && !state.usernameValid && (
<Ionicons style={styles.icon} name="exclamationcircleo" size={18} color="#ff8888" />
)}
{ validServer && validToken && state.username && state.usernameChecked && state.usernameValid && (
<Ionicons style={styles.icon} name="checkcircleo" size={18} color="#448866" />
)}
</View>
</View>
{ state.showPassword && (
<View style={styles.inputwrapper}>
<Ionicons style={styles.icon} name="lock" size={18} color="#888888" />
<TextInput style={styles.inputfield} value={state.password} onChangeText={actions.setPassword}
autoCorrect={false} autoCapitalize="none" placeholder="password" placeholderTextColor={Colors.grey} />
<TouchableOpacity onPress={actions.hidePassword}>
<Ionicons style={styles.icon} name="eye" size={18} color="#888888" />
</TouchableOpacity>
</View>
)}
{ !state.showPassword && (
<View style={styles.inputwrapper}>
<Ionicons style={styles.icon} name="lock" size={18} color="#888888" />
<TextInput style={styles.inputfield} value={state.password} onChangeText={actions.setPassword}
autoCorrect={false} secureTextEntry={true} autoCapitalize="none" placeholder="password"
placeholderTextColor={Colors.grey} />
<TouchableOpacity onPress={actions.showPassword}>
<Ionicons style={styles.icon} name="eyeo" size={18} color="#888888" />
</TouchableOpacity>
</View>
)}
{ state.showConfirm && (
<View style={styles.inputwrapper}>
<Ionicons style={styles.icon} name="lock" size={18} color="#888888" />
<TextInput style={styles.inputfield} value={state.confirm} onChangeText={actions.setConfirm}
autoCorrect={false} autoCapitalize="none" placeholder="confirm password"
placeholderTextColor={Colors.grey} />
<TouchableOpacity onPress={actions.hideConfirm}>
<Ionicons style={styles.icon} name="eye" size={18} color="#888888" />
</TouchableOpacity>
</View>
)}
{ !state.showConfirm && (
<View style={styles.inputwrapper}>
<Ionicons style={styles.icon} name="lock" size={18} color="#888888" />
<TextInput style={styles.inputfield} value={state.confirm} onChangeText={actions.setConfirm}
autoCorrect={false} secureTextEntry={true} autoCapitalize="none" placeholder="confirm password"
placeholderTextColor={Colors.grey} />
<TouchableOpacity onPress={actions.showConfirm}>
<Ionicons style={styles.icon} name="eyeo" size={18} color="#888888" />
</TouchableOpacity>
</View>
)}
<View style={styles.buttons}>
{ state.enabled && (
<TouchableOpacity style={styles.create} onPress={create}>
{ state.busy && (
<ActivityIndicator size="small" color="#ffffff" />
)}
{ !state.busy && (
<Text style={styles.createtext}>Create Account</Text>
)}
</TouchableOpacity>
)}
{ !state.enabled && (
<View style={styles.nocreate}>
<Text style={styles.nocreatetext}>Create</Text>
</View>
)}
<TouchableOpacity style={styles.login} onPress={actions.login}>
<Text style={styles.logintext}>Account Login</Text>
</TouchableOpacity>
</View>
</ScrollView>
</View>
</KeyboardAvoidingView>
);
}

View File

@ -0,0 +1,148 @@
import { StyleSheet } from 'react-native';
import { Colors } from 'constants/Colors';
export const styles = StyleSheet.create({
wrapper: {
width: '100%',
height: '100%',
},
config: {
paddingTop: 8,
},
demo: {
alignItems: 'center',
justifyContent: 'center',
paddingLeft: 16,
paddingRight: 16,
},
demoText: {
color: Colors.grey,
textAlign: 'center',
},
space: {
width: 32,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
},
required: {
fontSize: 12,
color: Colors.grey,
textAlignVertical: 'center',
},
container: {
flexDirection: 'column',
backgroundColor: Colors.formBackground,
borderRadius: 4,
width: '100%',
height: '100%',
display: 'flex',
},
token: {
height: 52,
},
control: {
display: 'flex',
flexDirection: 'row',
justifyContent: 'flex-end',
color: Colors.grey,
marginRight: 16,
},
title: {
width: '100%',
textAlign: 'center',
fontSize: 24,
color: Colors.grey,
},
spacemid: {
flexGrow: 1,
flexDirection: 'column',
textAlign: 'center',
alignItems: 'center',
justifyContent: 'center',
width: '100%',
},
spacetop: {
width: '100%',
paddingLeft: 16,
paddingRight: 16,
},
buttons: {
width: '100%',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
},
header: {
fontSize: 32,
color: Colors.text,
},
inputwrapper: {
display: 'flex',
flexDirection: 'row',
width: '100%',
borderRadius: 4,
borderColor: Colors.divider,
borderWidth: 1,
marginBottom: 16,
alignItems: 'center',
},
inputwrapperpad: {
display: 'flex',
flexDirection: 'row',
width: '100%',
borderRadius: 4,
borderColor: Colors.divider,
borderWidth: 1,
marginTop: 16,
marginBottom: 16,
alignItems: 'center',
},
inputfield: {
flex: 1,
textAlign: 'center',
padding: 8,
},
create: {
marginTop: 16,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
width: 128,
height: 28,
backgroundColor: Colors.primary,
borderRadius: 4,
marginBottom: 16,
},
createtext: {
color: Colors.formFocus,
},
nocreate: {
marginTop: 16,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
width: 128,
height: 28,
borderRadius: 4,
borderColor: Colors.divider,
borderWidth: 1,
marginBottom: 16,
},
nocreatetext: {
color: Colors.grey,
},
login: {
marginTop: 16,
marginBottom: 16,
},
logintext: {
color: 'yellow',
},
nologintext: {
color: Colors.disabled,
},
})

View File

@ -0,0 +1,193 @@
import { useState, useEffect, useContext, useRef } from 'react';
import { useWindowDimensions } from 'react-native';
import { useNavigate } from 'react-router-dom';
import { AppContext } from 'context/AppContext';
import { getAvailable } from 'api/getAvailable';
import { getUsername } from 'api/getUsername';
export function useCreate() {
const [count, setCount] = useState(0);
const navigate = useNavigate();
const app = useContext(AppContext);
const [state, setState] = useState({
busy: false,
enabled: false,
server: "databag.coredb.org",
token: null,
username: null,
password: null,
confirm: null,
showPassword: false,
showConfirm: false,
serverChecked: true,
serverValid: true,
tokenRequired: false,
tokenChecked: true,
tokenValid: false,
usernameChecked: true,
usernameValid: false,
});
const backoff = useRef(false);
const checking = useRef(false);
const debounce = useRef(null);
const updateState = (value) => {
setState((s) => ({ ...s, ...value }));
}
useEffect(() => {
if (app.state.session) {
navigate('/session');
}
}, [app.state.session]);
useEffect(() => {
if (state.usernameChecked && state.serverChecked && state.tokenChecked &&
state.password && state.username && state.server && state.confirm &&
(!state.tokenRequired || state.tokenValid) &&
state.serverValid && state.usernameValid && state.password === state.confirm) {
if (!state.enabled) {
updateState({ enabled: true });
}
}
else {
if (state.enabled) {
updateState({ enabled: false });
}
}
}, [state]);
useEffect(() => {
if (checking.current) {
backoff.current = true;
}
if (debounce.current) {
clearTimeout(debounce.current);
}
debounce.current = setTimeout(async () => {
checking.current = true;
debounce.current = null;
if (state.server) {
try {
const available = await getAvailable(state.server);
if (available) {
if (state.username) {
try {
const claimable = await getUsername(state.username, state.server, null);
updateState({ tokenRequired: false, usernameValid: claimable, serverValid: true });
}
catch (err) {
updateState({ tokenRequired: false, usernameValid: false, serverValid: true });
}
}
else {
updateState({ tokenRequired: false, serverValid: true });
}
}
else {
if (state.token) {
try {
const accessible = await getUsername(null, state.server, state.token);
if (accessible) {
if (state.username) {
try {
const claimable = await getUsername(state.username, state.server, state.token);
updateState({ tokenRequired: true, usernameValid: claimable, tokenValid: true, serverValid: true });
}
catch (err) {
updateState({ tokenRequired: true, usernameValid: false, tokenValid: true, serverValid: true });
}
}
else {
updateState({ tokenRequired: true, tokenValid: true, serverValid: true });
}
}
else {
updateState({ tokenRequired: true, tokenValid: false, serverValid: true });
}
}
catch (err) {
updateState({ tokenRequired: true, tokenValid: false, serverValid: true });
}
}
else {
updateState({ tokenRequired: true, serverValid: true });
}
}
}
catch (err) {
updateState({ serverValid: false });
}
}
let retry = backoff.current;
backoff.current = false;
checking.current = false;
if (retry) {
setCount(count+1);
}
else {
updateState({ usernameChecked: true, tokenChecked: true, serverChecked: true });
}
}, 1000);
}, [count]);
const actions = {
config: () => {
navigate('/admin');
},
setServer: (server) => {
updateState({ server, serverChecked: false });
setCount(count+1);
},
setToken: (token) => {
updateState({ token, tokenChecked: false });
setCount(count+1);
},
setUsername: (username) => {
updateState({ username, usernameChecked: false });
setCount(count+1);
},
setPassword: (password) => {
updateState({ password });
},
setConfirm: (confirm) => {
updateState({ confirm });
},
login: () => {
navigate('/login');
},
showPassword: () => {
updateState({ showPassword: true });
},
hidePassword: () => {
updateState({ showPassword: false });
},
showConfirm: () => {
updateState({ showConfirm: true });
},
hideConfirm: () => {
updateState({ showConfirm: false });
},
create: async () => {
if (!state.busy) {
try {
updateState({ busy: true });
await app.actions.create(state.server, state.username, state.password, state.token);
updateState({ busy: false });
}
catch (err) {
console.log(err);
updateState({ busy: false });
throw new Error('create failed');
}
updateState({ busy: false });
}
}
};
return { state, actions };
}

View File

@ -0,0 +1,90 @@
import { KeyboardAvoidingView, ActivityIndicator, Alert, Text, TextInput, View, TouchableOpacity } from 'react-native';
import { styles } from './Login.styled';
import Ionicons from 'react-native-vector-icons/AntDesign';
import { useLogin } from './useLogin.hook';
import { Colors } from 'constants/Colors';
export function Login() {
const { state, actions } = useLogin();
const login = async () => {
try {
await actions.login();
}
catch (err) {
Alert.alert(
"Login Failed",
"Please check your login and password.",
);
}
}
return (
<KeyboardAvoidingView style={styles.wrapper} behavior="padding" enabled={Platform.OS === 'ios' ? true : false}>
<View style={styles.container}>
<View style={styles.control}>
<TouchableOpacity onPress={actions.config}>
<Ionicons style={styles.config} name="setting" size={24} color="#aaaaaa" />
</TouchableOpacity>
</View>
<Text style={styles.title}>Databag</Text>
<View style={styles.spacemid}>
<Text style={styles.header}>Login</Text>
</View>
<View style={styles.spacetop}>
<View style={styles.inputwrapper}>
<Ionicons style={styles.icon} name="user" size={18} color="#aaaaaa" />
<TextInput style={styles.inputfield} value={state.login} onChangeText={actions.setLogin}
autoCorrect={false} autoCapitalize="none" placeholder="username@server" placeholderTextColor={Colors.grey} />
<View style={styles.space} />
</View>
{ state.showPassword && (
<View style={styles.inputwrapper}>
<Ionicons style={styles.icon} name="lock" size={18} color="#aaaaaa" />
<TextInput style={styles.inputfield} value={state.password} onChangeText={actions.setPassword}
autoCorrect={false} autoCapitalize="none" placeholder="password" placeholderTextColor={Colors.grey} />
<TouchableOpacity onPress={actions.hidePassword}>
<Ionicons style={styles.icon} name="eye" size={18} color="#aaaaaa" />
</TouchableOpacity>
</View>
)}
{ !state.showPassword && (
<View style={styles.inputwrapper}>
<Ionicons style={styles.icon} name="lock" size={18} color="#aaaaaa" />
<TextInput style={styles.inputfield} value={state.password} onChangeText={actions.setPassword}
autoCorrect={false} secureTextEntry={true} autoCapitalize="none" placeholder="password"
placeholderTextColor={Colors.grey} />
<TouchableOpacity onPress={actions.showPassword}>
<Ionicons style={styles.icon} name="eyeo" size={18} color="#aaaaaa" />
</TouchableOpacity>
</View>
)}
{ state.enabled && (
<TouchableOpacity style={styles.login} onPress={login}>
{ state.busy && (
<ActivityIndicator size="small" color="#ffffff" />
)}
{ !state.busy && (
<Text style={styles.logintext}>Login</Text>
)}
</TouchableOpacity>
)}
{ !state.enabled && (
<View style={styles.nologin}>
<Text style={styles.nologintext}>Login</Text>
</View>
)}
<TouchableOpacity style={styles.create} onPress={actions.create}>
<Text style={styles.createtext}>Create Account</Text>
</TouchableOpacity>
<View style={styles.bottom}>
<TouchableOpacity style={styles.create} onPress={actions.reset}>
<Text style={styles.createtext}>Forgot Password</Text>
</TouchableOpacity>
</View>
</View>
</View>
</KeyboardAvoidingView>
);
}

View File

@ -0,0 +1,119 @@
import { StyleSheet } from 'react-native';
import { Colors } from 'constants/Colors';
export const styles = StyleSheet.create({
wrapper: {
width: '100%',
height: '100%',
},
config: {
paddingTop: 8,
},
icon: {
padding: 8,
},
space: {
width: 32,
},
container: {
flexDirection: 'column',
backgroundColor: Colors.formBackground,
borderRadius: 4,
width: '100%',
height: '100%',
display: 'flex',
paddingLeft: 16,
paddingRight: 16,
},
control: {
display: 'flex',
flexDirection: 'row',
justifyContent: 'flex-end',
color: Colors.grey,
},
title: {
width: '100%',
textAlign: 'center',
fontSize: 24,
color: Colors.grey,
},
spacemid: {
flexGrow: 1,
flexDirection: 'column',
textAlign: 'center',
alignItems: 'center',
justifyContent: 'center',
width: '100%',
},
spacetop: {
flexGrow: 1,
flexDirection: 'column',
textAlign: 'center',
alignItems: 'center',
justifyContent: 'flex-start',
width: '100%',
},
header: {
fontSize: 32,
color: Colors.text,
},
inputwrapper: {
display: 'flex',
flexDirection: 'row',
width: '100%',
borderRadius: 4,
borderColor: Colors.divider,
borderWidth: 1,
marginBottom: 16,
alignItems: 'center',
},
inputfield: {
flex: 1,
textAlign: 'center',
padding: 8,
},
login: {
marginTop: 16,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
width: 128,
height: 28,
backgroundColor: Colors.primary,
borderRadius: 4,
},
logintext: {
color: Colors.formFocus,
},
nologin: {
marginTop: 16,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
width: 128,
height: 28,
borderRadius: 4,
borderColor: Colors.divider,
borderWidth: 1,
},
nologintext: {
color: Colors.grey,
},
create: {
marginTop: 16,
},
createtext: {
color: 'yellow',
},
nocreatetext: {
color: Colors.disabled,
},
bottom: {
display: 'flex',
flexGrow: 1,
alignItems: 'flex-end',
justifyContent: 'flex-end',
paddingBottom: 16,
},
})

View File

@ -0,0 +1,78 @@
import { useState, useEffect, useContext } from 'react';
import { useWindowDimensions } from 'react-native';
import { useNavigate } from 'react-router-dom';
import { AppContext } from 'context/AppContext';
export function useLogin() {
const navigate = useNavigate();
const app = useContext(AppContext);
const [state, setState] = useState({
busy: false,
enabled: false,
login: null,
password: null,
showPassword: false,
});
const updateState = (value) => {
setState((s) => ({ ...s, ...value }));
}
useEffect(() => {
if (app.state.session) {
navigate('/session');
}
}, [app.state.session]);
useEffect(() => {
if (state.password && state.login && !state.enabled && state.login.includes('@')) {
updateState({ enabled: true });
}
if ((!state.password || !state.login || !state.login.includes('@')) && state.enabled) {
updateState({ enabled: false });
}
}, [state.login, state.password]);
const actions = {
config: () => {
navigate('/admin');
},
setLogin: (login) => {
updateState({ login });
},
setPassword: (password) => {
updateState({ password });
},
create: () => {
navigate('/create');
},
reset: () => {
navigate('/reset');
},
showPassword: () => {
updateState({ showPassword: true });
},
hidePassword: () => {
updateState({ showPassword: false });
},
login: async () => {
if (!state.busy) {
updateState({ busy: true });
try {
await app.actions.login(state.login.trim(), state.password);
}
catch (err) {
console.log(err);
updateState({ busy: false, showAlert: true });
throw new Error('login failed');
}
updateState({ busy: false });
}
}
};
return { state, actions };
}

View File

@ -0,0 +1,70 @@
import { KeyboardAvoidingView, ActivityIndicator, Alert, Text, TextInput, View, TouchableOpacity } from 'react-native';
import { styles } from './Reset.styled';
import Ionicons from 'react-native-vector-icons/AntDesign';
import { useReset } from './useReset.hook';
import Colors from 'constants/Colors';
export function Reset() {
const { state, actions } = useReset();
const reset = async () => {
try {
await actions.access();
}
catch (err) {
Alert.alert(
"Access Failed",
"Please check your server and token.",
);
}
}
return (
<KeyboardAvoidingView style={styles.wrapper} behavior="padding" enabled={Platform.OS === 'ios' ? true : false}>
<View style={styles.container}>
<View style={styles.control}>
<TouchableOpacity onPress={actions.config}>
<Ionicons style={styles.config} name="setting" size={24} color="#aaaaaa" />
</TouchableOpacity>
</View>
<Text style={styles.title}>Databag</Text>
<View style={styles.spacemid}>
<Text style={styles.header}>Access Account</Text>
</View>
<View style={styles.spacetop}>
<View style={styles.inputwrapper}>
<Ionicons style={styles.icon} name="database" size={18} color="#aaaaaa" />
<TextInput style={styles.inputfield} value={state.server} onChangeText={actions.setServer}
autoCapitalize="none" placeholder="server" placeholderTextColor={Colors.grey} />
<View style={styles.space} />
</View>
<View style={styles.inputwrapper}>
<Ionicons style={styles.icon} name="key" size={18} color="#aaaaaa" />
<TextInput style={styles.inputfield} value={state.token} onChangeText={actions.setToken}
autoCapitalize="none" placeholder="token" placeholderTextColor={Colors.grey} />
<View style={styles.space} />
</View>
{ state.enabled && (
<TouchableOpacity style={styles.reset} onPress={reset}>
{ state.busy && (
<ActivityIndicator size="small" color="#ffffff" />
)}
{ !state.busy && (
<Text style={styles.resettext}>Access</Text>
)}
</TouchableOpacity>
)}
{ !state.enabled && (
<View style={styles.noreset}>
<Text style={styles.noresettext}>Access</Text>
</View>
)}
<TouchableOpacity style={styles.login} onPress={actions.login}>
<Text style={styles.createtext}>Account Login</Text>
</TouchableOpacity>
</View>
</View>
</KeyboardAvoidingView>
);
}

View File

@ -0,0 +1,113 @@
import { StyleSheet } from 'react-native';
import { Colors } from 'constants/Colors';
export const styles = StyleSheet.create({
wrapper: {
width: '100%',
height: '100%',
},
config: {
paddingTop: 8,
},
icon: {
padding: 8,
},
space: {
width: 32,
},
container: {
flexDirection: 'column',
backgroundColor: Colors.formBackground,
borderRadius: 4,
width: '100%',
height: '100%',
display: 'flex',
paddingLeft: 16,
paddingRight: 16,
},
control: {
display: 'flex',
flexDirection: 'row',
justifyContent: 'flex-end',
color: Colors.grey,
},
title: {
width: '100%',
textAlign: 'center',
fontSize: 24,
color: Colors.grey,
},
spacemid: {
flexGrow: 1,
flexDirection: 'column',
textAlign: 'center',
alignItems: 'center',
justifyContent: 'center',
width: '100%',
},
spacetop: {
flexGrow: 1,
flexDirection: 'column',
textAlign: 'center',
alignItems: 'center',
justifyContent: 'flex-start',
width: '100%',
},
header: {
fontSize: 32,
color: Colors.text,
},
inputwrapper: {
display: 'flex',
flexDirection: 'row',
width: '100%',
borderRadius: 4,
borderColor: Colors.divider,
borderWidth: 1,
marginBottom: 16,
alignItems: 'center',
},
inputfield: {
flex: 1,
textAlign: 'center',
padding: 8,
},
reset: {
marginTop: 16,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
width: 128,
height: 28,
backgroundColor: Colors.primary,
borderRadius: 4,
},
resettext: {
color: Colors.formFocus,
},
noreset: {
marginTop: 16,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
width: 128,
height: 28,
borderRadius: 4,
borderColor: Colors.divider,
borderWidth: 1,
},
noresettext: {
color: Colors.grey,
},
login: {
marginTop: 16,
},
logintext: {
color: 'yellow',
},
nologintext: {
color: Colors.disabled,
},
})

View File

@ -0,0 +1,68 @@
import { useState, useEffect, useContext } from 'react';
import { useWindowDimensions } from 'react-native';
import { useNavigate } from 'react-router-dom';
import { AppContext } from 'context/AppContext';
export function useReset() {
const navigate = useNavigate();
const app = useContext(AppContext);
const [state, setState] = useState({
busy: false,
enabled: false,
server: null,
token: null,
});
const updateState = (value) => {
setState((s) => ({ ...s, ...value }));
}
useEffect(() => {
if (app.state.session) {
navigate('/session');
}
}, [app.state.session]);
useEffect(() => {
if (state.token && state.server && !state.enabled) {
updateState({ enabled: true });
}
if ((!state.token || !state.server) && state.enabled) {
updateState({ enabled: false });
}
}, [state.server, state.token]);
const actions = {
config: () => {
navigate('/admin');
},
setServer: (server) => {
updateState({ server });
},
setToken: (token) => {
updateState({ token });
},
login: () => {
navigate('/login');
},
access: async () => {
if (!state.busy) {
try {
updateState({ busy: true });
await app.actions.access(state.server.trim(), state.token);
updateState({ busy: false });
}
catch (err) {
console.log(err);
updateState({ busy: false });
throw new Error("access failed");
}
}
}
};
return { state, actions };
}

View File

@ -0,0 +1,30 @@
import { useState, useEffect } from 'react';
import { useWindowDimensions } from 'react-native';
import config from 'constants/Config';
export function useAccess() {
const [state, setState] = useState({
split: null,
});
const dimensions = useWindowDimensions();
const updateState = (value) => {
setState((s) => ({ ...s, ...value }));
}
useEffect(() => {
if (dimensions.width > config.tabbedWidth) {
updateState({ split: true });
}
else {
updateState({ split: false });
}
}, [dimensions]);
const actions = {
};
return { state, actions };
}

View File

@ -0,0 +1,11 @@
import { Text } from 'react-native';
import { styles } from './Dashboard.styled';
import { useDashboard } from './useDashboard.hook';
export function Dashboard(props) {
const { state, actions } = useDashboard(config, server, token);
return <Text>DASHBOARD</Text>;
}

View File

@ -0,0 +1,227 @@
import { StyleSheet } from 'react-native';
import { Colors } from 'constants/Colors';
export const styles = StyleSheet.create({
container: {
width: '100%',
height: '100%',
display: 'flex',
flexDirection: 'column',
backgroundColor: Colors.formBackground,
},
header: {
paddingTop: 24,
paddingBottom: 4,
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
borderBottomWidth: 1,
borderColor: Colors.grey,
},
headerLabel: {
paddingLeft: 16,
fontSize: 20,
color: Colors.text,
},
icon: {
color: Colors.primary,
paddingLeft: 16,
},
end: {
flexGrow: 1,
display: 'flex',
flexDirection: 'row',
justifyContent: 'flex-end',
paddingRight: 32,
},
accounts: {
borderBottomWidth: 1,
borderColor: Colors.grey,
flexGrow: 1,
flexShrink: 1,
minHeight: 0,
},
account: {
width: '100%',
height: 48,
display: 'flex',
flexDirection: 'row',
paddingLeft: 24,
paddingRight: 24,
alignItems: 'center',
borderBottomWidth: 1,
borderColor: Colors.divider,
},
details: {
paddingLeft: 16,
display: 'flex',
flexDirection: 'column',
},
list: {
paddingTop: 8,
},
name: {
fontSize: 14,
color: Colors.text,
},
handle: {
fontSize: 14,
color: Colors.text,
},
control: {
flexGrow: 1,
display: 'flex',
flexDirection: 'row',
justifyContent: 'flex-end',
},
delete: {
color: Colors.alert,
paddingLeft: 16,
},
unlock: {
color: Colors.alert,
paddingLeft: 16,
},
disable: {
color: Colors.pending,
paddingLeft: 16,
},
saveText: {
color: Colors.white,
},
save: {
backgroundColor: Colors.primary,
borderRadius: 4,
padding: 6,
marginRight: 8,
width: 72,
display: 'flex',
alignItems: 'center',
},
cancel: {
borderWidth: 1,
borderColor: Colors.lightgrey,
borderRadius: 4,
padding: 6,
marginRight: 8,
width: 72,
display: 'flex',
alignItems: 'center',
},
modalBackground: {
display: 'flex',
width: '100%',
height: '100%',
alignItems: 'center',
justifyContent: 'center',
backgroundColor: 'rgba(52, 52, 52, 0.8)'
},
modalControls: {
display: 'flex',
flexDirection: 'row',
justifyContent: 'flex-end',
paddingTop: 16,
borderTopWidth: 1,
borderColor: Colors.divider,
},
modalContainer: {
backgroundColor: Colors.formBackground,
padding: 16,
width: '80%',
maxWidth: 400,
},
modalHeader: {
paddingBottom: 4,
borderBottomWidth: 1,
borderColor: Colors.divider,
paddingLeft: 8,
},
modalHeaderText: {
fontSize: 18,
},
modalBody: {
padding: 8,
},
accessToken: {
padding: 16,
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
},
modalLabel: {
paddingTop: 8,
color: Colors.text,
},
keyType: {
display: 'flex',
flexDirection: 'row',
padding: 8,
},
option: {
color: Colors.text,
},
optionLeft: {
display: 'flex',
flexDirection: 'row',
justifyContent: 'flex-start',
},
optionRight: {
flexGrow: 1,
display: 'flex',
flexDirection: 'row',
justifyContent: 'flex-end',
},
radio: {
width: 16,
height: 16,
borderRadius: 8,
borderColor: Colors.primary,
borderWidth: 1,
marginRight: 8,
},
selected: {
width: 16,
height: 16,
borderRadius: 8,
borderColor: Colors.primary,
borderWidth: 1,
marginRight: 8,
backgroundColor: Colors.background,
},
input: {
marginTop: 4,
backgroundColor: Colors.white,
padding: 4,
borderRadius: 4,
marginBottom: 16,
fontSize: 16,
color: Colors.text,
},
switch: {
transform: [{ scaleX: .7 }, { scaleY: .7 }],
},
track: {
false: Colors.grey,
true: Colors.background,
},
media: {
display: 'flex',
flexDirection: 'row',
marginTop: 8,
alignItems: 'center',
},
tokenLabel: {
fontSize: 16,
color: Colors.text,
},
copy: {
marginLeft: 8,
alignItems: 'center',
display: 'flex',
flexDirection: 'row',
padding: 8,
borderWidth: 1,
borderRadius: 4,
borderColor: Colors.divider,
},
});

View File

@ -0,0 +1,131 @@
import { useState, useEffect, useContext } from 'react';
import { useNavigate } from 'react-router-dom';
import { AppContext } from 'context/AppContext';
import { getNodeStatus } from 'api/getNodeStatus';
import { setNodeStatus } from 'api/setNodeStatus';
import { getNodeConfig } from 'api/getNodeConfig';
import { setNodeConfig } from 'api/setNodeConfig';
import { getNodeAccounts } from 'api/getNodeAccounts';
import { getAccountImageUrl } from 'api/getAccountImageUrl';
import { removeAccount } from 'api/removeAccount';
import { addAccountCreate } from 'api/addAccountCreate';
import { setAccountStatus } from 'api/setAccountStatus';
import { addAccountAccess } from 'api/addAccountAccess';
export function useDashboard(config, server, token) {
const [state, setState] = useState({
config: null,
accounts: [],
editConfig: false,
addUser: false,
accessUser: false,
accessId: null,
domain: null,
storage: null,
keyType: null,
enableImage: true,
enableAudio: true,
enableVideo: true,
createToken: null,
});
const navigate = useNavigate();
const updateState = (value) => {
setState((s) => ({ ...s, ...value }));
}
const setAccountItem = (item) => {
const { name, handle, imageSet, accountId, disabled } = item;
let logo;
if (imageSet) {
logo = getAccountImageUrl(server, token, accountId);
}
else {
logo = 'avatar';
}
return { logo, name, handle, accountId, disabled };
}
const refreshAccounts = async () => {
const accounts = await getNodeAccounts(server, token);
updateState({ accounts: accounts.map(setAccountItem) });
};
useEffect(() => {
const { keyType, accountStorage, domain, enableImage, enableAudio, enableVideo, pushSupported } = config;
updateState({ keyType, storage: accountStorage.toString(), domain, enableImage, enableAudio, enableVideo, pushSupported });
}, [config]);
useEffect(() => {
refreshAccounts();
}, []);
const actions = {
logout: () => {
navigate('/admin');
},
refresh: () => {
refreshAccounts();
},
showEditConfig: () => {
updateState({ editConfig: true });
},
hideEditConfig: () => {
updateState({ editConfig: false });
},
addUser: async () => {
const createToken = await addAccountCreate(server, token);
updateState({ addUser: true, createToken });
},
hideAddUser: () => {
updateState({ addUser: false });
},
accessUser: async (accountId) => {
const accessToken = await addAccountAccess(server, token, accountId);
updateState({ accessUser: true, accessToken });
},
hideAccessUser: () => {
updateState({ accessUser: false });
},
setDomain: (domain) => {
updateState({ domain });
},
setStorage: (storage) => {
updateState({ storage: Number(storage.replace(/[^0-9]/g, '')) });
},
setPushSupported: (pushSupported) => {
updateState({ pushSupported });
},
setEnableImage: (enableImage) => {
updateState({ enableImage });
},
setEnableAudio: (enableAudio) => {
updateState({ enableAudio });
},
setEnableVideo: (enableVideo) => {
updateState({ enableVideo });
},
setKeyType: (keyType) => {
updateState({ keyType });
},
saveConfig: async () => {
const { storage, domain, keyType, enableImage, enableAudio, enableVideo } = state;
const config = { accountStorage: Number(storage), domain, keyType, enableImage, enableAudio, enableVideo };
await setNodeConfig(server, token, config);
},
enableUser: async (accountId, enabled) => {
await setAccountStatus(server, token, accountId, !enabled);
await refreshAccounts();
},
removeUser: async (accountId) => {
await removeAccount(server, token, accountId);
await refreshAccounts();
},
};
return { state, actions };
}

View File

@ -12,6 +12,15 @@ export function useRoot() {
setState((s) => ({ ...s, ...value }));
}
useEffect(() => {
if (app.state.session === true) {
navigate('/session');
}
if (app.state.session === false) {
navigate('/login');
}
}, [app.state]);
const actions = {
};

View File

@ -0,0 +1,12 @@
import { Text } from 'react-native';
import { styles } from './Session.styled';
import { useSession } from './useSession.hook';
export function Session() {
const { state, actions } = useSession();
return <Text>SESSION</Text>
}

View File

@ -0,0 +1,132 @@
import { StyleSheet } from 'react-native';
import { Colors } from 'constants/Colors';
export const styles = StyleSheet.create({
body: {
width: '100%',
height: '100%',
backgroundColor: Colors.formBackground,
},
container: {
width: '100%',
height: '100%',
},
firstRun: {
width: '100%',
height: '100%',
backgroundColor: Colors.background,
alignItems: 'center',
justifyContent: 'center',
},
splash: {
width: '100%',
height: '100%',
maxWidth: '80%',
maxHeight: '50%',
},
steps: {
flexGrow: 1,
display: 'flex',
justifyContent: 'center',
},
step: {
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
paddingBottom: 12,
},
titleText: {
color: Colors.white,
fontSize: 20,
fontWeight: 'bold',
},
tagText: {
paddingTop: 8,
color: Colors.white,
fontSize: 16,
},
title: {
flexGrow: 1,
justifyContent: 'center',
alignItems: 'center',
},
stepText: {
color: Colors.white,
paddingLeft: 16,
fontSize: 16,
},
start: {
marginTop: 16,
padding: 8,
backgroundColor: Colors.primary,
borderRadius: 4,
display: 'flex',
alignItems: 'center',
},
startText: {
color: Colors.white,
},
tabBar: {
backgroundColor: Colors.primary,
},
home: {
display: 'flex',
flexDirection: 'row',
height: '100%',
},
sidebar: {
display: 'flex',
flexDirection: 'column',
height: '100%',
width: '33%',
maxWidth: 500,
},
conversation: {
width: '67%',
},
drawer: {
width: '100%',
height: '100%',
paddingLeft: 8,
backgroundColor: Colors.formBackground,
},
options: {
display: 'flex',
flexDirection: 'row',
paddingTop: 8,
paddingBottom: 4,
paddingRight: 8,
},
option: {
width: '50%',
height: 32,
alignItems: 'center',
justifyContent: 'center',
display: 'flex',
flexDirection: 'row',
},
icon: {
paddingRight: 8,
},
channels: {
flexGrow: 1,
flexShrink: 1,
position: 'relative',
},
tabframe: {
width: '100%',
height: '100%',
},
disconnected: {
width: 8,
height: 8,
borderRadius: 4,
backgroundColor: Colors.alert,
position: 'absolute',
right: 0,
bottom: 0,
},
profileLabel: {
paddingLeft: 8,
},
});

View File

@ -0,0 +1,13 @@
import { useRef, useState, useEffect, useContext } from 'react';
export function useSession() {
const [state, setState] = useState({
});
const actions = {
};
return { state, actions };
}

View File

@ -757,6 +757,13 @@
dependencies:
"@babel/helper-plugin-utils" "^7.18.6"
"@babel/plugin-transform-object-assign@^7.16.7":
version "7.18.6"
resolved "https://registry.npmjs.org/@babel/plugin-transform-object-assign/-/plugin-transform-object-assign-7.18.6.tgz"
integrity sha512-mQisZ3JfqWh2gVXvfqYCAAyRs6+7oev+myBsTwW5RnPhYXOTuCEw2oe3YgxlXMViXUS53lG8koulI7mJ+8JE+A==
dependencies:
"@babel/helper-plugin-utils" "^7.18.6"
"@babel/plugin-transform-object-super@^7.0.0", "@babel/plugin-transform-object-super@^7.18.6":
version "7.18.6"
resolved "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz"
@ -999,7 +1006,7 @@
"@babel/types" "^7.4.4"
esutils "^2.0.2"
"@babel/preset-typescript@^7.13.0":
"@babel/preset-typescript@^7.13.0", "@babel/preset-typescript@^7.16.7":
version "7.18.6"
resolved "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.18.6.tgz"
integrity sha512-s9ik86kXBAnD760aybBucdpnLsAt0jK1xqJn2juOn9lkOvSHV60os5hxoVJsPzMQxvnUJFAlkont2DvvaYEBtQ==
@ -1072,7 +1079,7 @@
"@egjs/hammerjs@^2.0.17":
version "2.0.17"
resolved "https://registry.yarnpkg.com/@egjs/hammerjs/-/hammerjs-2.0.17.tgz#5dc02af75a6a06e4c2db0202cae38c9263895124"
resolved "https://registry.npmjs.org/@egjs/hammerjs/-/hammerjs-2.0.17.tgz"
integrity sha512-XQsZgjm2EcVUiZQf11UBJQfmZeEmOW8DpI1gsFeln6w0ae0ii4dMQEQ0kjl6DspdWX1aGY1/loyXnP0JS06e/A==
dependencies:
"@types/hammerjs" "^2.0.36"
@ -1672,7 +1679,7 @@
"@react-native-firebase/app@^17.2.0":
version "17.2.0"
resolved "https://registry.yarnpkg.com/@react-native-firebase/app/-/app-17.2.0.tgz#1c08fec73e7d8bd2fde71843aa1812a16257ff1e"
resolved "https://registry.npmjs.org/@react-native-firebase/app/-/app-17.2.0.tgz"
integrity sha512-eZESR0O9RFlC12hQUGD/VmCDwdo36RBv3Uldce1xplewEyQoWgxsVJiBXbrW6BdYnVCqfFx3CPwsxL1CAPB8CQ==
dependencies:
"@expo/config-plugins" "^5.0.4"
@ -1681,7 +1688,7 @@
"@react-native-firebase/messaging@^17.2.0":
version "17.2.0"
resolved "https://registry.yarnpkg.com/@react-native-firebase/messaging/-/messaging-17.2.0.tgz#87d3de8a4481d55c680edeae2a6c0527e6e1b6de"
resolved "https://registry.npmjs.org/@react-native-firebase/messaging/-/messaging-17.2.0.tgz"
integrity sha512-uIPrZqiE8EmlyKhAL9WJyq4gaLmUFeAbAL3zpxdeZ2S1vGIh5pnloLh+inffXEE1qHId/wdfdIsetU9tBSsP/w==
"@react-native/assets@1.0.0":
@ -1699,9 +1706,18 @@
resolved "https://registry.npmjs.org/@react-native/polyfills/-/polyfills-2.0.0.tgz"
integrity sha512-K0aGNn1TjalKj+65D7ycc1//H9roAQ51GJVk5ZJQFb2teECGmzd86bYDC0aYdbRf7gtovescq4Zt6FR0tgXiHQ==
"@react-navigation/bottom-tabs@^6.5.5":
version "6.5.5"
resolved "https://registry.yarnpkg.com/@react-navigation/bottom-tabs/-/bottom-tabs-6.5.5.tgz#901e213560b669ed4a58cfa12880beb65d3b819f"
integrity sha512-NKnbniyw7eEx1ubXHQ1Rx2rwj33cYQ4ffX0ZN8/UCncCY2Y1ruCjh3x3eEWVeZY8rPicLUaX3h0742CAh5mjEw==
dependencies:
"@react-navigation/elements" "^1.3.15"
color "^4.2.3"
warn-once "^0.1.0"
"@react-navigation/core@^6.4.6":
version "6.4.6"
resolved "https://registry.yarnpkg.com/@react-navigation/core/-/core-6.4.6.tgz#b0738667dec5927b01c4c496c2f4c73ef8a5e4dd"
resolved "https://registry.npmjs.org/@react-navigation/core/-/core-6.4.6.tgz"
integrity sha512-6zaAgUT5k4vhJlddUk2l52RZyMkMelHdrRv1cL57ALi2RZzERdgmbiMKhJerxFLn9S8E3PUe8vwxHzjHOZKG4w==
dependencies:
"@react-navigation/routers" "^6.1.6"
@ -1711,9 +1727,31 @@
react-is "^16.13.0"
use-latest-callback "^0.1.5"
"@react-navigation/drawer@^6.6.0":
version "6.6.0"
resolved "https://registry.npmjs.org/@react-navigation/drawer/-/drawer-6.6.0.tgz"
integrity sha512-/GJZrFOwgsd2vfIYYSG382iHIwufYURYtIs9y3gWkBBJVu9RcAZ6BbUtxeF8CC1PqpC4WHlqzxz+6L922Tw54g==
dependencies:
"@react-navigation/elements" "^1.3.15"
color "^4.2.3"
warn-once "^0.1.0"
"@react-navigation/elements@^1.3.15":
version "1.3.15"
resolved "https://registry.npmjs.org/@react-navigation/elements/-/elements-1.3.15.tgz"
integrity sha512-CR4CEYJVY0OLyeLQi9N3Z2o4K47gXctvFxfZizDuW1xFtCJbA0eGvpjSLXEWHoY0hFjrlC6KinpdepGHVxhYIg==
"@react-navigation/native-stack@^6.9.10":
version "6.9.10"
resolved "https://registry.yarnpkg.com/@react-navigation/native-stack/-/native-stack-6.9.10.tgz#5a5d5de9f49b72e603d0cdca9771e0324f65c1c7"
integrity sha512-dSazcWNxHg4qkid/AxFRvbhRtNXy/RqE00h/Qp+d7aBN0TwrOJn8mH/Inkkf4pHAntMbj0+mVAlKfxKmyLEGlA==
dependencies:
"@react-navigation/elements" "^1.3.15"
warn-once "^0.1.0"
"@react-navigation/native@^6.1.4":
version "6.1.4"
resolved "https://registry.yarnpkg.com/@react-navigation/native/-/native-6.1.4.tgz#49666596c9df16e22284f35f482d05d6b5d47d60"
resolved "https://registry.npmjs.org/@react-navigation/native/-/native-6.1.4.tgz"
integrity sha512-8IGpMFvD21XINpSf9gyU19yv4O+NyF9FQAxEzwbJSef19W5XEJKXPN/0RINc43Tt+YnQyFGQ2+qJM1uoB9pKcA==
dependencies:
"@react-navigation/core" "^6.4.6"
@ -1723,14 +1761,14 @@
"@react-navigation/routers@^6.1.6":
version "6.1.6"
resolved "https://registry.yarnpkg.com/@react-navigation/routers/-/routers-6.1.6.tgz#f57f2a73855d329255aa225fdad75ae8e7700c6d"
resolved "https://registry.npmjs.org/@react-navigation/routers/-/routers-6.1.6.tgz"
integrity sha512-Z5DeCW3pUvMafbU9Cjy1qJYC2Bvl8iy3+PfsB0DsAwQ6zZ3WAXW5FTMX4Gb9H+Jg6qHWGbMFFwlYpS3UJ3tlVQ==
dependencies:
nanoid "^3.1.23"
"@remix-run/router@1.3.2":
version "1.3.2"
resolved "https://registry.yarnpkg.com/@remix-run/router/-/router-1.3.2.tgz#58cd2bd25df2acc16c628e1b6f6150ea6c7455bc"
resolved "https://registry.npmjs.org/@remix-run/router/-/router-1.3.2.tgz"
integrity sha512-t54ONhl/h75X94SWsHGQ4G/ZrCEguKSRQr7DrjTciJXW0YU1QhlwYeycvK5JgkzlxmvrK7wq1NB/PLtHxoiDcA==
"@sideway/address@^4.1.3":
@ -1771,7 +1809,7 @@
"@testing-library/dom@^8.20.0":
version "8.20.0"
resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-8.20.0.tgz#914aa862cef0f5e89b98cc48e3445c4c921010f6"
resolved "https://registry.npmjs.org/@testing-library/dom/-/dom-8.20.0.tgz"
integrity sha512-d9ULIT+a4EXLX3UU8FBjauG9NnsZHkHztXoIcTsOKoOw030fyjheN9svkTULjJxtYag9DZz5Jz5qkWZDPxTFwA==
dependencies:
"@babel/code-frame" "^7.10.4"
@ -1785,7 +1823,7 @@
"@testing-library/react-native@^11.5.2":
version "11.5.2"
resolved "https://registry.yarnpkg.com/@testing-library/react-native/-/react-native-11.5.2.tgz#64238431de1ce4e128810bf8277a7cc118f1c812"
resolved "https://registry.npmjs.org/@testing-library/react-native/-/react-native-11.5.2.tgz"
integrity sha512-haa/82Sy4ngAbXF6VTw5U306ZQHWfv7OKxALA4AkMKnX+6frhSd9aAe9rp50CyI2XJsNna0Rh6G+CSw+SPztYg==
dependencies:
pretty-format "^29.4.0"
@ -1797,7 +1835,7 @@
"@types/aria-query@^5.0.1":
version "5.0.1"
resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-5.0.1.tgz#3286741fb8f1e1580ac28784add4c7a1d49bdfbc"
resolved "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.1.tgz"
integrity sha512-XTIieEY+gvJ39ChLcB4If5zHtPxt3Syj5rgZR+e1ctpmK8NjPf0zFqsz4JpLJT0xla9GFDKjy8Cpu331nrmE1Q==
"@types/babel__core@^7.1.14":
@ -1842,7 +1880,7 @@
"@types/hammerjs@^2.0.36":
version "2.0.41"
resolved "https://registry.yarnpkg.com/@types/hammerjs/-/hammerjs-2.0.41.tgz#f6ecf57d1b12d2befcce00e928a6a097c22980aa"
resolved "https://registry.npmjs.org/@types/hammerjs/-/hammerjs-2.0.41.tgz"
integrity sha512-ewXv/ceBaJprikMcxCmWU1FKyMAQ2X7a9Gtmzw8fcg2kIePI1crERDM818W+XYrxqdBBOdlf2rm137bU+BltCA==
"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1":
@ -2035,7 +2073,7 @@
"@ungap/url-search-params@^0.1.4":
version "0.1.4"
resolved "https://registry.yarnpkg.com/@ungap/url-search-params/-/url-search-params-0.1.4.tgz#727e9b4c811beaa6be6d7e4cc0516663c884cfd0"
resolved "https://registry.npmjs.org/@ungap/url-search-params/-/url-search-params-0.1.4.tgz"
integrity sha512-RLwrxCTDNiNev9hpr9rDq8NyeQ8Nn0X1we4Wu7Tlf368I8r+7hBj3uObhifhuLk74egaYaSX5nUsBlWz6kjj+A==
"@xmldom/xmldom@~0.7.0":
@ -2160,7 +2198,7 @@ argparse@^2.0.1:
aria-query@^5.0.0:
version "5.1.3"
resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.1.3.tgz#19db27cd101152773631396f7a95a3b58c22c35e"
resolved "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz"
integrity sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==
dependencies:
deep-equal "^2.0.5"
@ -2256,7 +2294,7 @@ async@^3.2.2:
asynckit@^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
resolved "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz"
integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==
atob@^2.1.2:
@ -2271,7 +2309,7 @@ available-typed-arrays@^1.0.5:
axios@^1.3.3:
version "1.3.3"
resolved "https://registry.yarnpkg.com/axios/-/axios-1.3.3.tgz#e7011384ba839b885007c9c9fae1ff23dceb295b"
resolved "https://registry.npmjs.org/axios/-/axios-1.3.3.tgz"
integrity sha512-eYq77dYIFS77AQlhzEL937yUBSepBfPIe8FcgEDN35vMNZKMrs81pgnyrQpwfy4NF4b4XWX1Zgx7yX+25w8QJA==
dependencies:
follow-redirects "^1.15.0"
@ -2652,6 +2690,15 @@ cliui@^6.0.0:
strip-ansi "^6.0.0"
wrap-ansi "^6.2.0"
cliui@^7.0.2:
version "7.0.4"
resolved "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz"
integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==
dependencies:
string-width "^4.2.0"
strip-ansi "^6.0.0"
wrap-ansi "^7.0.0"
cliui@^8.0.1:
version "8.0.1"
resolved "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz"
@ -2722,11 +2769,27 @@ color-name@1.1.3:
resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz"
integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==
color-name@~1.1.4:
color-name@^1.0.0, color-name@~1.1.4:
version "1.1.4"
resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz"
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
color-string@^1.9.0:
version "1.9.1"
resolved "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz"
integrity sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==
dependencies:
color-name "^1.0.0"
simple-swizzle "^0.2.2"
color@^4.2.3:
version "4.2.3"
resolved "https://registry.npmjs.org/color/-/color-4.2.3.tgz"
integrity sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==
dependencies:
color-convert "^2.0.1"
color-string "^1.9.0"
colorette@^1.0.7:
version "1.4.0"
resolved "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz"
@ -2734,7 +2797,7 @@ colorette@^1.0.7:
combined-stream@^1.0.8:
version "1.0.8"
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
resolved "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz"
integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
dependencies:
delayed-stream "~1.0.0"
@ -2863,7 +2926,7 @@ cross-spawn@^7.0.2, cross-spawn@^7.0.3:
crypto-js@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-4.1.1.tgz#9e485bcf03521041bd85844786b83fb7619736cf"
resolved "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz"
integrity sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==
csstype@^3.0.2:
@ -2907,7 +2970,7 @@ dedent@^0.7.0:
deep-equal@^2.0.5:
version "2.2.0"
resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-2.2.0.tgz#5caeace9c781028b9ff459f33b779346637c43e6"
resolved "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.0.tgz"
integrity sha512-RdpzE0Hv4lhowpIUKKMJfeH6C1pXdtT1/it80ubgWqwI3qpuxUBpC1S4hnHg+zjnuOoDkzUtUCEEkG+XG5l3Mw==
dependencies:
call-bind "^1.0.2"
@ -2982,7 +3045,7 @@ define-property@^2.0.2:
delayed-stream@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
resolved "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz"
integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==
denodeify@^1.2.1:
@ -3042,7 +3105,7 @@ doctrine@^3.0.0:
dom-accessibility-api@^0.5.9:
version "0.5.16"
resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz#5a7429e6066eb3664d911e33fb0e45de8eb08453"
resolved "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz"
integrity sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==
ee-first@1.1.1:
@ -3145,7 +3208,7 @@ es-abstract@^1.19.0, es-abstract@^1.20.4:
es-get-iterator@^1.1.2:
version "1.1.3"
resolved "https://registry.yarnpkg.com/es-get-iterator/-/es-get-iterator-1.1.3.tgz#3ef87523c5d464d41084b2c3c9c214f1199763d6"
resolved "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz"
integrity sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==
dependencies:
call-bind "^1.0.2"
@ -3570,7 +3633,7 @@ fill-range@^7.0.1:
filter-obj@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/filter-obj/-/filter-obj-1.1.0.tgz#9b311112bc6c6127a16e016c6c5d7f19e0805c5b"
resolved "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz"
integrity sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==
finalhandler@1.1.2:
@ -3643,7 +3706,7 @@ flow-parser@^0.185.0:
follow-redirects@^1.15.0:
version "1.15.2"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13"
resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz"
integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==
for-each@^0.3.3:
@ -3672,7 +3735,7 @@ for-own@^1.0.0:
form-data@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452"
resolved "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz"
integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==
dependencies:
asynckit "^0.4.0"
@ -3968,7 +4031,7 @@ hermes-profile-transformer@^0.0.6:
hoist-non-react-statics@^3.3.0:
version "3.3.2"
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
resolved "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz"
integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
dependencies:
react-is "^16.7.0"
@ -4088,7 +4151,7 @@ is-accessor-descriptor@^1.0.0:
is-arguments@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b"
resolved "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz"
integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==
dependencies:
call-bind "^1.0.2"
@ -4108,6 +4171,11 @@ is-arrayish@^0.2.1:
resolved "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz"
integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==
is-arrayish@^0.3.1:
version "0.3.2"
resolved "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz"
integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==
is-bigint@^1.0.1:
version "1.0.4"
resolved "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz"
@ -4230,7 +4298,7 @@ is-interactive@^1.0.0:
is-map@^2.0.1, is-map@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.2.tgz#00922db8c9bf73e81b7a335827bc2a43f2b91127"
resolved "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz"
integrity sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==
is-negative-zero@^2.0.2:
@ -4279,7 +4347,7 @@ is-regex@^1.1.4:
is-set@^2.0.1, is-set@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.2.tgz#90755fa4c2562dc1c5d4024760d6119b94ca18ec"
resolved "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz"
integrity sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==
is-shared-array-buffer@^1.0.2:
@ -4331,7 +4399,7 @@ is-unicode-supported@^0.1.0:
is-weakmap@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.1.tgz#5008b59bdc43b698201d18f62b37b2ca243e8cf2"
resolved "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz"
integrity sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==
is-weakref@^1.0.2:
@ -4343,7 +4411,7 @@ is-weakref@^1.0.2:
is-weakset@^2.0.1:
version "2.0.2"
resolved "https://registry.yarnpkg.com/is-weakset/-/is-weakset-2.0.2.tgz#4569d67a747a1ce5a994dfd4ef6dcea76e7c0a1d"
resolved "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz"
integrity sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==
dependencies:
call-bind "^1.0.2"
@ -4366,7 +4434,7 @@ isarray@1.0.0, isarray@~1.0.0:
isarray@^2.0.5:
version "2.0.5"
resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723"
resolved "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz"
integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==
isexe@^2.0.0:
@ -5037,6 +5105,11 @@ lodash.debounce@^4.0.8:
resolved "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz"
integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==
lodash.isequal@^4.5.0:
version "4.5.0"
resolved "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz"
integrity sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==
lodash.merge@^4.6.2:
version "4.6.2"
resolved "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz"
@ -5092,7 +5165,7 @@ lru-cache@^6.0.0:
lz-string@^1.4.4:
version "1.4.4"
resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.4.4.tgz#c0d8eaf36059f705796e1e344811cf4c498d3a26"
resolved "https://registry.npmjs.org/lz-string/-/lz-string-1.4.4.tgz"
integrity sha512-0ckx7ZHRPqb0oUm8zNr+90mtf9DQB60H1wMCjBtfi62Kl3a7JbHob6gA2bC+xRvZoOL+1hzUK8jeuEIQE8svEQ==
make-dir@^2.0.0, make-dir@^2.1.0:
@ -5527,7 +5600,7 @@ ms@2.1.3:
nanoid@^3.1.23:
version "3.3.4"
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab"
resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz"
integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==
nanomatch@^1.2.9:
@ -5656,7 +5729,7 @@ object-inspect@^1.12.2, object-inspect@^1.9.0:
object-is@^1.1.5:
version "1.1.5"
resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac"
resolved "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz"
integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==
dependencies:
call-bind "^1.0.2"
@ -5994,7 +6067,7 @@ pretty-format@^26.5.2, pretty-format@^26.6.2:
pretty-format@^27.0.2:
version "27.5.1"
resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.5.1.tgz#2181879fdea51a7a5851fb39d920faa63f01d88e"
resolved "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz"
integrity sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==
dependencies:
ansi-regex "^5.0.1"
@ -6041,7 +6114,7 @@ prop-types@*, prop-types@^15.7.2, prop-types@^15.8.1:
proxy-from-env@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"
resolved "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz"
integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==
pump@^3.0.0:
@ -6059,7 +6132,7 @@ punycode@^2.1.0:
query-string@^7.1.3:
version "7.1.3"
resolved "https://registry.yarnpkg.com/query-string/-/query-string-7.1.3.tgz#a1cf90e994abb113a325804a972d98276fe02328"
resolved "https://registry.npmjs.org/query-string/-/query-string-7.1.3.tgz"
integrity sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==
dependencies:
decode-uri-component "^0.2.2"
@ -6102,7 +6175,7 @@ react-is@^17.0.1:
react-native-base64@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/react-native-base64/-/react-native-base64-0.2.1.tgz#3d0e73a649c4c0129f7b7695d3912456aebae847"
resolved "https://registry.npmjs.org/react-native-base64/-/react-native-base64-0.2.1.tgz"
integrity sha512-eHgt/MA8y5ZF0aHfZ1aTPcIkDWxza9AaEk4GcpIX+ZYfZ04RcaNahO+527KR7J44/mD3efYfM23O2C1N44ByWA==
react-native-codegen@^0.71.5:
@ -6117,7 +6190,7 @@ react-native-codegen@^0.71.5:
react-native-device-info@^10.4.0:
version "10.4.0"
resolved "https://registry.yarnpkg.com/react-native-device-info/-/react-native-device-info-10.4.0.tgz#9d90706641941d7da8ab7b316a37d3111eb231e4"
resolved "https://registry.npmjs.org/react-native-device-info/-/react-native-device-info-10.4.0.tgz"
integrity sha512-Z37e0HtpBvfkPRgv4xN7lXpvmJyzjwCXSFTXEkw6m2UgnnIsWlOD02Avu4hJXBlIMMazaW3ZLKal3o9h3AYvCw==
react-native-gesture-handler@^2.9.0:
@ -6136,21 +6209,42 @@ react-native-gradle-plugin@^0.71.15:
resolved "https://registry.npmjs.org/react-native-gradle-plugin/-/react-native-gradle-plugin-0.71.15.tgz"
integrity sha512-7S3pAuPaQJlhax6EZ4JMsDNpj05TfuzX9gPgWLrFfAIWIFLuJ6aDQYAZy2TEI9QJALPoWrj8LWaqP/DGYh14pw==
react-native-reanimated@^2.14.4:
version "2.14.4"
resolved "https://registry.yarnpkg.com/react-native-reanimated/-/react-native-reanimated-2.14.4.tgz#3fa3da4e7b99f5dfb28f86bcf24d9d1024d38836"
integrity sha512-DquSbl7P8j4SAmc+kRdd75Ianm8G+IYQ9T4AQ6lrpLVeDkhZmjWI0wkutKWnp6L7c5XNVUrFDUf69dwETLCItQ==
dependencies:
"@babel/plugin-transform-object-assign" "^7.16.7"
"@babel/preset-typescript" "^7.16.7"
convert-source-map "^1.7.0"
invariant "^2.2.4"
lodash.isequal "^4.5.0"
setimmediate "^1.0.5"
string-hash-64 "^1.0.3"
react-native-rsa-native@^2.0.5:
version "2.0.5"
resolved "https://registry.yarnpkg.com/react-native-rsa-native/-/react-native-rsa-native-2.0.5.tgz#7db4aef49405bb5b5bcaea12b9dfd1b251c690ab"
resolved "https://registry.npmjs.org/react-native-rsa-native/-/react-native-rsa-native-2.0.5.tgz"
integrity sha512-gwwvFSwGW5WKrpDyBQ/eTf1UrVABeAvMcT4YWemzPSUo6aHZs1kbBm2rXmwN5okhUzJsry5zjjz/qdx5GXRugQ==
react-native-safe-area-context@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/react-native-safe-area-context/-/react-native-safe-area-context-4.5.0.tgz#9208313236e8f49e1920ac1e2a2c975f03aed284"
resolved "https://registry.npmjs.org/react-native-safe-area-context/-/react-native-safe-area-context-4.5.0.tgz"
integrity sha512-0WORnk9SkREGUg2V7jHZbuN5x4vcxj/1B0QOcXJjdYWrzZHgLcUzYWWIUecUPJh747Mwjt/42RZDOaFn3L8kPQ==
react-native-sqlite-storage@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/react-native-sqlite-storage/-/react-native-sqlite-storage-6.0.1.tgz#ce6a6b852f07abbea68658d5363818c8bef45dfb"
resolved "https://registry.npmjs.org/react-native-sqlite-storage/-/react-native-sqlite-storage-6.0.1.tgz"
integrity sha512-1tDFjrint6X6qSYKf3gDyz+XB+X79jfiL6xTugKHPRtF0WvqMtVgdLuNqZunIXjNEvNtNVEbXaeZ6MsguFu00A==
react-native-vector-icons@^9.2.0:
version "9.2.0"
resolved "https://registry.npmjs.org/react-native-vector-icons/-/react-native-vector-icons-9.2.0.tgz"
integrity sha512-wKYLaFuQST/chH3AJRjmOLoLy3JEs1JR6zMNgTaemFpNoXs0ztRnTxcxFD9xhX7cJe1/zoN5BpQYe7kL0m5yyA==
dependencies:
prop-types "^15.7.2"
yargs "^16.1.1"
react-native@0.71.3:
version "0.71.3"
resolved "https://registry.npmjs.org/react-native/-/react-native-0.71.3.tgz"
@ -6198,7 +6292,7 @@ react-refresh@^0.4.0:
react-router-dom@^6.8.1:
version "6.8.1"
resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.8.1.tgz#7e136b67d9866f55999e9a8482c7008e3c575ac9"
resolved "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.8.1.tgz"
integrity sha512-67EXNfkQgf34P7+PSb6VlBuaacGhkKn3kpE51+P6zYSG2kiRoumXEL6e27zTa9+PGF2MNXbgIUHTVlleLbIcHQ==
dependencies:
"@remix-run/router" "1.3.2"
@ -6206,7 +6300,7 @@ react-router-dom@^6.8.1:
react-router-native@^6.8.1:
version "6.8.1"
resolved "https://registry.yarnpkg.com/react-router-native/-/react-router-native-6.8.1.tgz#e51e08a812db51eca684dfe37a08058faf60a96e"
resolved "https://registry.npmjs.org/react-router-native/-/react-router-native-6.8.1.tgz"
integrity sha512-IfcVe/iZTK/JyxCsQbZRhuwnTIOM7GzxFgrU/iffDhW4x3Vfd16WsFFG6tPI+Kj1QFcSxT5LJkxJguKCJhl6Vg==
dependencies:
"@ungap/url-search-params" "^0.1.4"
@ -6214,7 +6308,7 @@ react-router-native@^6.8.1:
react-router@6.8.1:
version "6.8.1"
resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.8.1.tgz#e362caf93958a747c649be1b47cd505cf28ca63e"
resolved "https://registry.npmjs.org/react-router/-/react-router-6.8.1.tgz"
integrity sha512-Jgi8BzAJQ8MkPt8ipXnR73rnD7EmZ0HFFb7jdQU24TynGW1Ooqin2KVDN9voSC+7xhqbbCd2cjGUepb6RObnyg==
dependencies:
"@remix-run/router" "1.3.2"
@ -6563,6 +6657,11 @@ set-value@^2.0.0, set-value@^2.0.1:
is-plain-object "^2.0.3"
split-string "^3.0.1"
setimmediate@^1.0.5:
version "1.0.5"
resolved "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz"
integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==
setprototypeof@1.2.0:
version "1.2.0"
resolved "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz"
@ -6636,6 +6735,13 @@ simple-plist@^1.1.0:
bplist-parser "0.3.1"
plist "^3.0.5"
simple-swizzle@^0.2.2:
version "0.2.2"
resolved "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz"
integrity sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==
dependencies:
is-arrayish "^0.3.1"
sisteransi@^1.0.5:
version "1.0.5"
resolved "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz"
@ -6734,7 +6840,7 @@ source-map@^0.7.3:
split-on-first@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/split-on-first/-/split-on-first-1.1.0.tgz#f610afeee3b12bce1d0c30425e76398b78249a5f"
resolved "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz"
integrity sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==
split-string@^3.0.1, split-string@^3.0.2:
@ -6788,7 +6894,7 @@ statuses@~1.5.0:
stop-iteration-iterator@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz#6a60be0b4ee757d1ed5254858ec66b10c49285e4"
resolved "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz"
integrity sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==
dependencies:
internal-slot "^1.0.4"
@ -6800,9 +6906,14 @@ stream-buffers@2.2.x:
strict-uri-encode@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546"
resolved "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz"
integrity sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==
string-hash-64@^1.0.3:
version "1.0.3"
resolved "https://registry.npmjs.org/string-hash-64/-/string-hash-64-1.0.3.tgz"
integrity sha512-D5OKWKvDhyVWWn2x5Y9b+37NUllks34q1dCDhk/vYcso9fmhs+Tl3KR/gE4v5UNj2UA35cnX4KdVVGkG1deKqw==
string-length@^4.0.1:
version "4.0.2"
resolved "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz"
@ -7197,7 +7308,7 @@ urix@^0.1.0:
use-latest-callback@^0.1.5:
version "0.1.5"
resolved "https://registry.yarnpkg.com/use-latest-callback/-/use-latest-callback-0.1.5.tgz#a4a836c08fa72f6608730b5b8f4bbd9c57c04f51"
resolved "https://registry.npmjs.org/use-latest-callback/-/use-latest-callback-0.1.5.tgz"
integrity sha512-HtHatS2U4/h32NlkhupDsPlrbiD27gSH5swBdtXbCAlc6pfOFzaj0FehW/FO12rx8j2Vy4/lJScCiJyM01E+bQ==
use-sync-external-store@^1.0.0:
@ -7251,6 +7362,11 @@ walker@^1.0.7, walker@^1.0.8:
dependencies:
makeerror "1.0.12"
warn-once@^0.1.0:
version "0.1.1"
resolved "https://registry.npmjs.org/warn-once/-/warn-once-0.1.1.tgz"
integrity sha512-VkQZJbO8zVImzYFteBXvBOZEl1qL175WH8VmZcxF2fZAoudNhNDvHi+doCaAEdU2l2vtcIwa2zn0QK5+I1HQ3Q==
wcwidth@^1.0.1:
version "1.0.1"
resolved "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz"
@ -7289,7 +7405,7 @@ which-boxed-primitive@^1.0.2:
which-collection@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/which-collection/-/which-collection-1.0.1.tgz#70eab71ebbbd2aefaf32f917082fc62cdcb70906"
resolved "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz"
integrity sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==
dependencies:
is-map "^2.0.1"
@ -7449,6 +7565,11 @@ yargs-parser@^18.1.2:
camelcase "^5.0.0"
decamelize "^1.2.0"
yargs-parser@^20.2.2:
version "20.2.9"
resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz"
integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==
yargs-parser@^21.1.1:
version "21.1.1"
resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz"
@ -7471,6 +7592,19 @@ yargs@^15.1.0:
y18n "^4.0.0"
yargs-parser "^18.1.2"
yargs@^16.1.1:
version "16.2.0"
resolved "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz"
integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==
dependencies:
cliui "^7.0.2"
escalade "^3.1.1"
get-caller-file "^2.0.5"
require-directory "^2.1.1"
string-width "^4.2.0"
y18n "^5.0.5"
yargs-parser "^20.2.2"
yargs@^17.3.1, yargs@^17.5.1:
version "17.6.2"
resolved "https://registry.npmjs.org/yargs/-/yargs-17.6.2.tgz"