mirror of
https://github.com/balzack/databag.git
synced 2025-05-04 15:35:16 +00:00
formatting code
This commit is contained in:
parent
ed369424cd
commit
c2642f534e
@ -11,28 +11,37 @@ export class LocalStore implements SqlStore {
|
|||||||
|
|
||||||
public async open(path: string) {
|
public async open(path: string) {
|
||||||
this.db = await SQLite.openDatabase({name: path, location: 'default'});
|
this.db = await SQLite.openDatabase({name: path, location: 'default'});
|
||||||
await this.localStoreSet("CREATE TABLE IF NOT EXISTS local_store (key text, value text, unique(key));");
|
await this.localStoreSet(
|
||||||
|
'CREATE TABLE IF NOT EXISTS local_store (key text, value text, unique(key));',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async get(key: string, value: string, unset: string): Promise<string> {
|
public async get(key: string, value: string, unset: string): Promise<string> {
|
||||||
try {
|
try {
|
||||||
const rows = await this.localStoreGet(`SELECT * FROM local_store WHERE key='${key}';`);
|
const rows = await this.localStoreGet(
|
||||||
|
`SELECT * FROM local_store WHERE key='${key}';`,
|
||||||
|
);
|
||||||
if (rows.length == 1 && rows[0].value != null) {
|
if (rows.length == 1 && rows[0].value != null) {
|
||||||
return rows[0].value;
|
return rows[0].value;
|
||||||
}
|
}
|
||||||
}
|
} catch (err) {
|
||||||
catch(err) {
|
|
||||||
console.log(err);
|
console.log(err);
|
||||||
}
|
}
|
||||||
return unset;
|
return unset;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async set(key: string, value: string): Promise<void> {
|
public async set(key: string, value: string): Promise<void> {
|
||||||
await this.localStoreSet('INSERT OR REPLACE INTO local_store (key, value) values (?, ?)', [key, value]);
|
await this.localStoreSet(
|
||||||
|
'INSERT OR REPLACE INTO local_store (key, value) values (?, ?)',
|
||||||
|
[key, value],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async clear(key: string): Promise<void> {
|
public async clear(key: string): Promise<void> {
|
||||||
await this.localStoreSet('INSERT OR REPLACE INTO local_store (key, value) values (?, null)', [key]);
|
await this.localStoreSet(
|
||||||
|
'INSERT OR REPLACE INTO local_store (key, value) values (?, null)',
|
||||||
|
[key],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async localStoreSet(
|
private async localStoreSet(
|
||||||
|
@ -1,109 +1,134 @@
|
|||||||
import { Crypto } from 'databag-client-sdk';
|
import {Crypto} from 'databag-client-sdk';
|
||||||
import CryptoJS from 'crypto-js';
|
import CryptoJS from 'crypto-js';
|
||||||
import { JSEncrypt } from 'jsencrypt'
|
import {JSEncrypt} from 'jsencrypt';
|
||||||
import { RSA } from 'react-native-rsa-native';
|
import {RSA} from 'react-native-rsa-native';
|
||||||
import { generateSecureRandom } from 'react-native-securerandom';
|
import {generateSecureRandom} from 'react-native-securerandom';
|
||||||
|
|
||||||
export class NativeCrypto implements Crypto {
|
export class NativeCrypto implements Crypto {
|
||||||
|
|
||||||
// generate salt for pbk function
|
// generate salt for pbk function
|
||||||
public async pbkdfSalt(): Promise<{ saltHex: string }> {
|
public async pbkdfSalt(): Promise<{saltHex: string}> {
|
||||||
const salt = await generateSecureRandom(16);
|
const salt = await generateSecureRandom(16);
|
||||||
const saltHex = this.uint8ToHexStr(salt);
|
const saltHex = this.uint8ToHexStr(salt);
|
||||||
return { saltHex };
|
return {saltHex};
|
||||||
}
|
}
|
||||||
|
|
||||||
// generate aes key with pbkdf2
|
// generate aes key with pbkdf2
|
||||||
public async pbkdfKey(saltHex: string, password: string): Promise<{ aesKeyHex: string }> {
|
public async pbkdfKey(
|
||||||
|
saltHex: string,
|
||||||
|
password: string,
|
||||||
|
): Promise<{aesKeyHex: string}> {
|
||||||
const salt = CryptoJS.enc.Hex.parse(saltHex);
|
const salt = CryptoJS.enc.Hex.parse(saltHex);
|
||||||
const aes = CryptoJS.PBKDF2(password, salt, { keySize: 256 / 32, iterations: 1024, hasher: CryptoJS.algo.SHA1, });
|
const aes = CryptoJS.PBKDF2(password, salt, {
|
||||||
|
keySize: 256 / 32,
|
||||||
|
iterations: 1024,
|
||||||
|
hasher: CryptoJS.algo.SHA1,
|
||||||
|
});
|
||||||
const aesKeyHex = aes.toString();
|
const aesKeyHex = aes.toString();
|
||||||
return { aesKeyHex };
|
return {aesKeyHex};
|
||||||
}
|
}
|
||||||
|
|
||||||
// generate random aes key
|
// generate random aes key
|
||||||
public async aesKey(): Promise<{ aesKeyHex: string }> {
|
public async aesKey(): Promise<{aesKeyHex: string}> {
|
||||||
const aes = await generateSecureRandom(32);
|
const aes = await generateSecureRandom(32);
|
||||||
const aesHex = this.uint8ToHexStr(aes);
|
const aesHex = this.uint8ToHexStr(aes);
|
||||||
return { aesKeyHex };
|
return {aesKeyHex};
|
||||||
}
|
}
|
||||||
|
|
||||||
// generate iv to use to aes function
|
// generate iv to use to aes function
|
||||||
public async aesIv(): Promise<{ ivHex: string }> {
|
public async aesIv(): Promise<{ivHex: string}> {
|
||||||
const iv = await generateSecureRandom(16);
|
const iv = await generateSecureRandom(16);
|
||||||
const ivHex = this.uint8ToHexStr(iv);
|
const ivHex = this.uint8ToHexStr(iv);
|
||||||
return { ivHex };
|
return {ivHex};
|
||||||
}
|
}
|
||||||
|
|
||||||
// encrypt data with aes key and iv
|
// encrypt data with aes key and iv
|
||||||
public async aesEncrypt(data: string, ivHex: string, aesKeyHex: string): Promise<{ encryptedDataB64: string }> {
|
public async aesEncrypt(
|
||||||
|
data: string,
|
||||||
|
ivHex: string,
|
||||||
|
aesKeyHex: string,
|
||||||
|
): Promise<{encryptedDataB64: string}> {
|
||||||
const iv = CryptoJS.enc.Hex.parse(ivHex);
|
const iv = CryptoJS.enc.Hex.parse(ivHex);
|
||||||
const key = CryptoJS.enc.Hex.parse(aesKeyHex);
|
const key = CryptoJS.enc.Hex.parse(aesKeyHex);
|
||||||
const encrypted = CryptoJS.AES.encrypt(data, key, { iv });
|
const encrypted = CryptoJS.AES.encrypt(data, key, {iv});
|
||||||
const encryptedDataB64 = encrypted.ciphertext.toString(CryptoJS.enc.Base64);
|
const encryptedDataB64 = encrypted.ciphertext.toString(CryptoJS.enc.Base64);
|
||||||
return { encryptedDataB64 };
|
return {encryptedDataB64};
|
||||||
}
|
}
|
||||||
|
|
||||||
// decrypt data with aes key and iv
|
// decrypt data with aes key and iv
|
||||||
public async aesDecrypt(encryptedDataB64: string, ivHex: string, aesKeyHex: string): Promise<{ data: string }> {
|
public async aesDecrypt(
|
||||||
|
encryptedDataB64: string,
|
||||||
|
ivHex: string,
|
||||||
|
aesKeyHex: string,
|
||||||
|
): Promise<{data: string}> {
|
||||||
const iv = CryptoJS.enc.Hex.parse(ivHex);
|
const iv = CryptoJS.enc.Hex.parse(ivHex);
|
||||||
const key = CryptoJS.enc.Hex.parse(aesKeyHex);
|
const key = CryptoJS.enc.Hex.parse(aesKeyHex);
|
||||||
const ciphertext = CryptoJS.enc.Base64.parse(encryptedDataB64);
|
const ciphertext = CryptoJS.enc.Base64.parse(encryptedDataB64);
|
||||||
const cipher = CryptoJS.lib.CipherParams.create({ ciphertext, iv });
|
const cipher = CryptoJS.lib.CipherParams.create({ciphertext, iv});
|
||||||
const decrypted = CryptoJS.AES.decrypt(cipher, key, { iv });
|
const decrypted = CryptoJS.AES.decrypt(cipher, key, {iv});
|
||||||
const data = decrypted.toString(CryptoJS.enc.Utf8);
|
const data = decrypted.toString(CryptoJS.enc.Utf8);
|
||||||
return { data };
|
return {data};
|
||||||
}
|
}
|
||||||
|
|
||||||
// generate rsa key
|
// generate rsa key
|
||||||
public async rsaKey(): Promise<{ publicKeyB64: string, privateKeyB64: string }> {
|
public async rsaKey(): Promise<{
|
||||||
const crypto = new JSEncrypt({ default_key_size: '2048' });
|
publicKeyB64: string;
|
||||||
|
privateKeyB64: string;
|
||||||
|
}> {
|
||||||
|
const crypto = new JSEncrypt({default_key_size: '2048'});
|
||||||
crypto.getKey();
|
crypto.getKey();
|
||||||
const publicKey = crypto.getPublicKey();
|
const publicKey = crypto.getPublicKey();
|
||||||
const publicKeyB64 = this.convertPem(publicKey);
|
const publicKeyB64 = this.convertPem(publicKey);
|
||||||
const privateKey = crypto.getPrivateKey();
|
const privateKey = crypto.getPrivateKey();
|
||||||
const privateKeyB64 = this.convertPem(privateKey);
|
const privateKeyB64 = this.convertPem(privateKey);
|
||||||
return { publicKeyB64, privateKeyB64 };
|
return {publicKeyB64, privateKeyB64};
|
||||||
}
|
}
|
||||||
|
|
||||||
// encrypt data with public rsa key
|
// encrypt data with public rsa key
|
||||||
public async rsaEncrypt(data: string, publicKeyB64: string): Promise<{ encryptedDataB64: string }> {
|
public async rsaEncrypt(
|
||||||
|
data: string,
|
||||||
|
publicKeyB64: string,
|
||||||
|
): Promise<{encryptedDataB64: string}> {
|
||||||
const crypto = new JSEncrypt();
|
const crypto = new JSEncrypt();
|
||||||
crypto.setPublicKey(publicKeyB64);
|
crypto.setPublicKey(publicKeyB64);
|
||||||
const encryptedDataB64 = crypto.encrypt(data);
|
const encryptedDataB64 = crypto.encrypt(data);
|
||||||
if (!encryptedDataB64) {
|
if (!encryptedDataB64) {
|
||||||
throw new Error('rsaEncrypt failed');
|
throw new Error('rsaEncrypt failed');
|
||||||
}
|
}
|
||||||
return { encryptedDataB64 };
|
return {encryptedDataB64};
|
||||||
}
|
}
|
||||||
|
|
||||||
// decrypt data with private rsa key
|
// decrypt data with private rsa key
|
||||||
public async rsaDecrypt(encryptedDataB64: string, privateKeyB64: string): Promise<{ data: string }> {
|
public async rsaDecrypt(
|
||||||
|
encryptedDataB64: string,
|
||||||
|
privateKeyB64: string,
|
||||||
|
): Promise<{data: string}> {
|
||||||
const crypto = new JSEncrypt();
|
const crypto = new JSEncrypt();
|
||||||
crypto.setPrivateKey(privateKeyB64);
|
crypto.setPrivateKey(privateKeyB64);
|
||||||
const data = await RSA.decrypt(encryptedDataB64, privateKeyB64);
|
const data = await RSA.decrypt(encryptedDataB64, privateKeyB64);
|
||||||
if (!data) {
|
if (!data) {
|
||||||
throw new Error('rsaDecrypt failed');
|
throw new Error('rsaDecrypt failed');
|
||||||
}
|
}
|
||||||
return { data };
|
return {data};
|
||||||
}
|
}
|
||||||
|
|
||||||
private convertPem(pem: string): string {
|
private convertPem(pem: string): string {
|
||||||
const lines = pem.split('\n');
|
const lines = pem.split('\n');
|
||||||
let encoded = '';
|
let encoded = '';
|
||||||
for(let i = 0;i < lines.length;i++){
|
for (let i = 0; i < lines.length; i++) {
|
||||||
if (lines[i].trim().length > 0 &&
|
if (
|
||||||
|
lines[i].trim().length > 0 &&
|
||||||
lines[i].indexOf('-BEGIN RSA PRIVATE KEY-') < 0 &&
|
lines[i].indexOf('-BEGIN RSA PRIVATE KEY-') < 0 &&
|
||||||
lines[i].indexOf('-BEGIN RSA PUBLIC KEY-') < 0 &&
|
lines[i].indexOf('-BEGIN RSA PUBLIC KEY-') < 0 &&
|
||||||
lines[i].indexOf('-BEGIN PUBLIC KEY-') < 0 &&
|
lines[i].indexOf('-BEGIN PUBLIC KEY-') < 0 &&
|
||||||
lines[i].indexOf('-END PUBLIC KEY-') < 0 &&
|
lines[i].indexOf('-END PUBLIC KEY-') < 0 &&
|
||||||
lines[i].indexOf('-END RSA PRIVATE KEY-') < 0 &&
|
lines[i].indexOf('-END RSA PRIVATE KEY-') < 0 &&
|
||||||
lines[i].indexOf('-END RSA PUBLIC KEY-') < 0) {
|
lines[i].indexOf('-END RSA PUBLIC KEY-') < 0
|
||||||
|
) {
|
||||||
encoded += lines[i].trim();
|
encoded += lines[i].trim();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return encoded
|
return encoded;
|
||||||
};
|
}
|
||||||
|
|
||||||
private uint8ToHexStr(bin: Uint8Array) {
|
private uint8ToHexStr(bin: Uint8Array) {
|
||||||
let hex = '';
|
let hex = '';
|
||||||
|
@ -1,10 +1,5 @@
|
|||||||
import React, {useState} from 'react';
|
import React, {useState} from 'react';
|
||||||
import {
|
import {Platform, KeyboardAvoidingView, View, Image} from 'react-native';
|
||||||
Platform,
|
|
||||||
KeyboardAvoidingView,
|
|
||||||
View,
|
|
||||||
Image,
|
|
||||||
} from 'react-native';
|
|
||||||
import {KeyboardAwareScrollView} from 'react-native-keyboard-aware-scroll-view';
|
import {KeyboardAwareScrollView} from 'react-native-keyboard-aware-scroll-view';
|
||||||
import {useAccess} from './useAccess.hook';
|
import {useAccess} from './useAccess.hook';
|
||||||
import {styles} from './Access.styled';
|
import {styles} from './Access.styled';
|
||||||
@ -135,12 +130,14 @@ export function Access() {
|
|||||||
left={<TextInput.Icon style={styles.icon} icon="lock" />}
|
left={<TextInput.Icon style={styles.icon} icon="lock" />}
|
||||||
right={
|
right={
|
||||||
showPassword ? (
|
showPassword ? (
|
||||||
<TextInput.Icon style={styles.icon}
|
<TextInput.Icon
|
||||||
|
style={styles.icon}
|
||||||
icon="eye-off"
|
icon="eye-off"
|
||||||
onPress={() => setShowPassword(false)}
|
onPress={() => setShowPassword(false)}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<TextInput.Icon style={styles.icon}
|
<TextInput.Icon
|
||||||
|
style={styles.icon}
|
||||||
icon="eye"
|
icon="eye"
|
||||||
onPress={() => setShowPassword(true)}
|
onPress={() => setShowPassword(true)}
|
||||||
/>
|
/>
|
||||||
@ -174,7 +171,9 @@ export function Access() {
|
|||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
autoCorrect={false}
|
autoCorrect={false}
|
||||||
label={state.strings.token}
|
label={state.strings.token}
|
||||||
left={<TextInput.Icon style={styles.icon} icon="ticket-account" />}
|
left={
|
||||||
|
<TextInput.Icon style={styles.icon} icon="ticket-account" />
|
||||||
|
}
|
||||||
onChangeText={value => actions.setToken(value)}
|
onChangeText={value => actions.setToken(value)}
|
||||||
/>
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
@ -216,7 +215,12 @@ export function Access() {
|
|||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
autoCorrect={false}
|
autoCorrect={false}
|
||||||
label={state.strings.token}
|
label={state.strings.token}
|
||||||
left={<TextInput.Icon style={styles.icon} icon="ticket-account" />}
|
left={
|
||||||
|
<TextInput.Icon
|
||||||
|
style={styles.icon}
|
||||||
|
icon="ticket-account"
|
||||||
|
/>
|
||||||
|
}
|
||||||
onChangeText={value => actions.setToken(value)}
|
onChangeText={value => actions.setToken(value)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@ -257,12 +261,14 @@ export function Access() {
|
|||||||
left={<TextInput.Icon style={styles.icon} icon="lock" />}
|
left={<TextInput.Icon style={styles.icon} icon="lock" />}
|
||||||
right={
|
right={
|
||||||
showPassword ? (
|
showPassword ? (
|
||||||
<TextInput.Icon style={styles.icon}
|
<TextInput.Icon
|
||||||
|
style={styles.icon}
|
||||||
icon="eye-off"
|
icon="eye-off"
|
||||||
onPress={() => setShowPassword(false)}
|
onPress={() => setShowPassword(false)}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<TextInput.Icon style={styles.icon}
|
<TextInput.Icon
|
||||||
|
style={styles.icon}
|
||||||
icon="eye"
|
icon="eye"
|
||||||
onPress={() => setShowPassword(true)}
|
onPress={() => setShowPassword(true)}
|
||||||
/>
|
/>
|
||||||
@ -283,12 +289,14 @@ export function Access() {
|
|||||||
left={<TextInput.Icon style={styles.icon} icon="lock" />}
|
left={<TextInput.Icon style={styles.icon} icon="lock" />}
|
||||||
right={
|
right={
|
||||||
showPassword ? (
|
showPassword ? (
|
||||||
<TextInput.Icon style={styles.icon}
|
<TextInput.Icon
|
||||||
|
style={styles.icon}
|
||||||
icon="eye-off"
|
icon="eye-off"
|
||||||
onPress={() => setShowConfirm(false)}
|
onPress={() => setShowConfirm(false)}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<TextInput.Icon style={styles.icon}
|
<TextInput.Icon
|
||||||
|
style={styles.icon}
|
||||||
icon="eye"
|
icon="eye"
|
||||||
onPress={() => setShowConfirm(true)}
|
onPress={() => setShowConfirm(true)}
|
||||||
/>
|
/>
|
||||||
@ -343,12 +351,14 @@ export function Access() {
|
|||||||
left={<TextInput.Icon style={styles.icon} icon="lock" />}
|
left={<TextInput.Icon style={styles.icon} icon="lock" />}
|
||||||
right={
|
right={
|
||||||
showPassword ? (
|
showPassword ? (
|
||||||
<TextInput.Icon style={styles.icon}
|
<TextInput.Icon
|
||||||
|
style={styles.icon}
|
||||||
icon="eye-off"
|
icon="eye-off"
|
||||||
onPress={() => setShowPassword(false)}
|
onPress={() => setShowPassword(false)}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<TextInput.Icon style={styles.icon}
|
<TextInput.Icon
|
||||||
|
style={styles.icon}
|
||||||
icon="eye"
|
icon="eye"
|
||||||
onPress={() => setShowPassword(true)}
|
onPress={() => setShowPassword(true)}
|
||||||
/>
|
/>
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
export const Colors = {
|
export const Colors = {
|
||||||
primary: '#66aa88',
|
primary: '#66aa88',
|
||||||
danger: '#ff8888',
|
danger: '#ff8888',
|
||||||
}
|
};
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ const SETTINGS_DB = 'ls_v001.db';
|
|||||||
|
|
||||||
export function useAppContext() {
|
export function useAppContext() {
|
||||||
const local = useRef(new LocalStore());
|
const local = useRef(new LocalStore());
|
||||||
const sdk = useRef(new DatabagSDK(new NativeCrypto()))
|
const sdk = useRef(new DatabagSDK(new NativeCrypto()));
|
||||||
const [state, setState] = useState({
|
const [state, setState] = useState({
|
||||||
session: null as null | Session,
|
session: null as null | Session,
|
||||||
fullDayTime: false,
|
fullDayTime: false,
|
||||||
@ -22,8 +22,10 @@ export function useAppContext() {
|
|||||||
|
|
||||||
const setup = async () => {
|
const setup = async () => {
|
||||||
await local.current.open(SETTINGS_DB);
|
await local.current.open(SETTINGS_DB);
|
||||||
const fullDayTime = await local.current.get('time_format', '12h') === '24h';
|
const fullDayTime =
|
||||||
const monthFirstDate = await local.current.get('date_format', 'month_first') === 'month_first';
|
(await local.current.get('time_format', '12h')) === '24h';
|
||||||
|
const monthFirstDate =
|
||||||
|
(await local.current.get('date_format', 'month_first')) === 'month_first';
|
||||||
|
|
||||||
const store = new SessionStore();
|
const store = new SessionStore();
|
||||||
await store.open(DATABAG_DB);
|
await store.open(DATABAG_DB);
|
||||||
@ -39,11 +41,14 @@ export function useAppContext() {
|
|||||||
|
|
||||||
const actions = {
|
const actions = {
|
||||||
setMonthFirstDate: async (monthFirstDate: boolean) => {
|
setMonthFirstDate: async (monthFirstDate: boolean) => {
|
||||||
updateState({ monthFirstDate });
|
updateState({monthFirstDate});
|
||||||
await local.current.set('date_format', monthFirstDate ? 'month_first' : 'day_first');
|
await local.current.set(
|
||||||
|
'date_format',
|
||||||
|
monthFirstDate ? 'month_first' : 'day_first',
|
||||||
|
);
|
||||||
},
|
},
|
||||||
setFullDayTime: async (fullDayTime: boolean) => {
|
setFullDayTime: async (fullDayTime: boolean) => {
|
||||||
updateState({ fullDayTime });
|
updateState({fullDayTime});
|
||||||
await local.current.set('time_format', fullDayTime ? '24h' : '12h');
|
await local.current.set('time_format', fullDayTime ? '24h' : '12h');
|
||||||
},
|
},
|
||||||
accountLogin: async (
|
accountLogin: async (
|
||||||
@ -86,7 +91,7 @@ export function useAppContext() {
|
|||||||
accountRemove: async () => {
|
accountRemove: async () => {
|
||||||
if (state.session) {
|
if (state.session) {
|
||||||
await sdk.current.remove(state.session);
|
await sdk.current.remove(state.session);
|
||||||
updateState({ session: null });
|
updateState({session: null});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
accountCreate: async (
|
accountCreate: async (
|
||||||
|
@ -123,9 +123,6 @@ export const styles = StyleSheet.create({
|
|||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
},
|
},
|
||||||
controlSwitch: {
|
controlSwitch: {
|
||||||
transform: [
|
transform: [{scaleX: 0.7}, {scaleY: 0.7}],
|
||||||
{ scaleX: 0.7 },
|
|
||||||
{scaleY: 0.7 },
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -1,21 +1,29 @@
|
|||||||
import { useState } from 'react';
|
import {useState} from 'react';
|
||||||
import { Modal, TouchableOpacity, SafeAreaView, View, Image } from 'react-native';
|
import {Modal, TouchableOpacity, SafeAreaView, View, Image} from 'react-native';
|
||||||
import { Surface, IconButton, Button, Switch, Icon, Text, Menu } from 'react-native-paper';
|
import {
|
||||||
import { styles } from './Identity.styled';
|
Surface,
|
||||||
import { useIdentity } from './useIdentity.hook';
|
IconButton,
|
||||||
|
Button,
|
||||||
|
Switch,
|
||||||
|
Icon,
|
||||||
|
Text,
|
||||||
|
Menu,
|
||||||
|
} from 'react-native-paper';
|
||||||
|
import {styles} from './Identity.styled';
|
||||||
|
import {useIdentity} from './useIdentity.hook';
|
||||||
import {KeyboardAwareScrollView} from 'react-native-keyboard-aware-scroll-view';
|
import {KeyboardAwareScrollView} from 'react-native-keyboard-aware-scroll-view';
|
||||||
import {BlurView} from '@react-native-community/blur';
|
import {BlurView} from '@react-native-community/blur';
|
||||||
|
|
||||||
export function Identity({ openSettings }) {
|
export function Identity({openSettings}) {
|
||||||
const [menu, setMenu] = useState(false);
|
const [menu, setMenu] = useState(false);
|
||||||
const { state, actions } = useIdentity();
|
const {state, actions} = useIdentity();
|
||||||
const [logout, setLogout] = useState(false);
|
const [logout, setLogout] = useState(false);
|
||||||
const [applyingLogout, setApplyingLogout] = useState(false);
|
const [applyingLogout, setApplyingLogout] = useState(false);
|
||||||
|
|
||||||
const showLogout = () => {
|
const showLogout = () => {
|
||||||
setMenu(false);
|
setMenu(false);
|
||||||
setLogout(true);
|
setLogout(true);
|
||||||
}
|
};
|
||||||
|
|
||||||
const applyLogout = async () => {
|
const applyLogout = async () => {
|
||||||
if (!applyingLogout) {
|
if (!applyingLogout) {
|
||||||
@ -24,25 +32,46 @@ export function Identity({ openSettings }) {
|
|||||||
setLogout(false);
|
setLogout(false);
|
||||||
setApplyingLogout(false);
|
setApplyingLogout(false);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<SafeAreaView style={styles.identity}>
|
<SafeAreaView style={styles.identity}>
|
||||||
<TouchableOpacity style={styles.identityData} activeOpacity={1} onPress={() => setMenu(true)}>
|
<TouchableOpacity
|
||||||
|
style={styles.identityData}
|
||||||
|
activeOpacity={1}
|
||||||
|
onPress={() => setMenu(true)}>
|
||||||
<View style={styles.image}>
|
<View style={styles.image}>
|
||||||
{state.profile.imageSet && (
|
{state.profile.imageSet && (
|
||||||
<Image style={styles.logoSet} resizeMode={'contain'} source={state.imageUrl} />
|
<Image
|
||||||
|
style={styles.logoSet}
|
||||||
|
resizeMode={'contain'}
|
||||||
|
source={state.imageUrl}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
{!state.profile.imageSet && (
|
{!state.profile.imageSet && (
|
||||||
<Image style={styles.logoUnset} resizeMode={'contain'} source={state.imageUrl} />
|
<Image
|
||||||
|
style={styles.logoUnset}
|
||||||
|
resizeMode={'contain'}
|
||||||
|
source={state.imageUrl}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
<View style={styles.details}>
|
<View style={styles.details}>
|
||||||
{state.profile.name && (
|
{state.profile.name && (
|
||||||
<Text style={styles.name} adjustsFontSizeToFit={true} numberOfLines={1}>{state.profile.name}</Text>
|
<Text
|
||||||
|
style={styles.name}
|
||||||
|
adjustsFontSizeToFit={true}
|
||||||
|
numberOfLines={1}>
|
||||||
|
{state.profile.name}
|
||||||
|
</Text>
|
||||||
)}
|
)}
|
||||||
<Text style={styles.username} adjustsFontSizeToFit={true} numberOfLines={1}>{`${state.profile.handle}${state.profile.node ? '/' + state.profile.node : ''}`}</Text>
|
<Text
|
||||||
|
style={styles.username}
|
||||||
|
adjustsFontSizeToFit={true}
|
||||||
|
numberOfLines={1}>{`${state.profile.handle}${
|
||||||
|
state.profile.node ? '/' + state.profile.node : ''
|
||||||
|
}`}</Text>
|
||||||
</View>
|
</View>
|
||||||
<Icon size={18} source="chevron-right" />
|
<Icon size={18} source="chevron-right" />
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
@ -50,10 +79,29 @@ export function Identity({ openSettings }) {
|
|||||||
visible={menu}
|
visible={menu}
|
||||||
onDismiss={() => setMenu(false)}
|
onDismiss={() => setMenu(false)}
|
||||||
anchorPosition="top"
|
anchorPosition="top"
|
||||||
anchor={<View style={styles.anchor}><Text> </Text></View>}>
|
anchor={
|
||||||
<Menu.Item leadingIcon="cog-outline" onPress={() => {setMenu(false); openSettings()}} title={state.strings.settings} />
|
<View style={styles.anchor}>
|
||||||
<Menu.Item leadingIcon="contacts-outline" onPress={() => {}} title={state.strings.contacts} />
|
<Text> </Text>
|
||||||
<Menu.Item leadingIcon="logout" onPress={showLogout} title={state.strings.logout} />
|
</View>
|
||||||
|
}>
|
||||||
|
<Menu.Item
|
||||||
|
leadingIcon="cog-outline"
|
||||||
|
onPress={() => {
|
||||||
|
setMenu(false);
|
||||||
|
openSettings();
|
||||||
|
}}
|
||||||
|
title={state.strings.settings}
|
||||||
|
/>
|
||||||
|
<Menu.Item
|
||||||
|
leadingIcon="contacts-outline"
|
||||||
|
onPress={() => {}}
|
||||||
|
title={state.strings.contacts}
|
||||||
|
/>
|
||||||
|
<Menu.Item
|
||||||
|
leadingIcon="logout"
|
||||||
|
onPress={showLogout}
|
||||||
|
title={state.strings.logout}
|
||||||
|
/>
|
||||||
</Menu>
|
</Menu>
|
||||||
</SafeAreaView>
|
</SafeAreaView>
|
||||||
<Modal
|
<Modal
|
||||||
@ -69,24 +117,44 @@ export function Identity({ openSettings }) {
|
|||||||
blurAmount={2}
|
blurAmount={2}
|
||||||
reducedTransparencyFallbackColor="dark"
|
reducedTransparencyFallbackColor="dark"
|
||||||
/>
|
/>
|
||||||
<KeyboardAwareScrollView style={styles.container} contentContainerStyle={styles.content}>
|
<KeyboardAwareScrollView
|
||||||
|
style={styles.container}
|
||||||
|
contentContainerStyle={styles.content}>
|
||||||
<Surface elevation={5} mode="flat" style={styles.surface}>
|
<Surface elevation={5} mode="flat" style={styles.surface}>
|
||||||
<Text style={styles.modalLabel}>{ state.strings.loggingOut }</Text>
|
<Text style={styles.modalLabel}>{state.strings.loggingOut}</Text>
|
||||||
<IconButton style={styles.modalClose} icon="close" size={24} onPress={() => setLogout(false)} />
|
<IconButton
|
||||||
|
style={styles.modalClose}
|
||||||
|
icon="close"
|
||||||
|
size={24}
|
||||||
|
onPress={() => setLogout(false)}
|
||||||
|
/>
|
||||||
|
|
||||||
<View style={styles.allControl}>
|
<View style={styles.allControl}>
|
||||||
<Text style={styles.controlLabel}>{state.strings.allDevices}</Text>
|
<Text style={styles.controlLabel}>
|
||||||
<Switch style={styles.controlSwitch} value={state.all} onValueChange={actions.setAll} />
|
{state.strings.allDevices}
|
||||||
|
</Text>
|
||||||
|
<Switch
|
||||||
|
style={styles.controlSwitch}
|
||||||
|
value={state.all}
|
||||||
|
onValueChange={actions.setAll}
|
||||||
|
/>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<View style={styles.modalControls}>
|
<View style={styles.modalControls}>
|
||||||
<Button mode="outlined" onPress={() => setLogout(false)}>{ state.strings.cancel }</Button>
|
<Button mode="outlined" onPress={() => setLogout(false)}>
|
||||||
<Button mode="contained" loading={applyingLogout} onPress={applyLogout}>{ state.strings.logout }</Button>
|
{state.strings.cancel}
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
mode="contained"
|
||||||
|
loading={applyingLogout}
|
||||||
|
onPress={applyLogout}>
|
||||||
|
{state.strings.logout}
|
||||||
|
</Button>
|
||||||
</View>
|
</View>
|
||||||
</Surface>
|
</Surface>
|
||||||
</KeyboardAwareScrollView>
|
</KeyboardAwareScrollView>
|
||||||
</View>
|
</View>
|
||||||
</Modal>
|
</Modal>
|
||||||
</>
|
</>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import { useEffect, useState, useContext, useRef } from 'react'
|
import {useEffect, useState, useContext, useRef} from 'react';
|
||||||
import { AppContext } from '../context/AppContext'
|
import {AppContext} from '../context/AppContext';
|
||||||
import { DisplayContext } from '../context/DisplayContext';
|
import {DisplayContext} from '../context/DisplayContext';
|
||||||
import { ContextType } from '../context/ContextType'
|
import {ContextType} from '../context/ContextType';
|
||||||
|
|
||||||
export function useIdentity() {
|
export function useIdentity() {
|
||||||
const display = useContext(DisplayContext) as ContextType
|
const display = useContext(DisplayContext) as ContextType;
|
||||||
const app = useContext(AppContext) as ContextType
|
const app = useContext(AppContext) as ContextType;
|
||||||
|
|
||||||
const [state, setState] = useState({
|
const [state, setState] = useState({
|
||||||
all: false,
|
all: false,
|
||||||
@ -14,41 +14,40 @@ export function useIdentity() {
|
|||||||
profileSet: false,
|
profileSet: false,
|
||||||
imageUrl: null,
|
imageUrl: null,
|
||||||
strings: display.state.strings,
|
strings: display.state.strings,
|
||||||
})
|
});
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
const updateState = (value: any) => {
|
const updateState = (value: any) => {
|
||||||
setState((s) => ({ ...s, ...value }))
|
setState(s => ({...s, ...value}));
|
||||||
}
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const identity = app.state.session?.getIdentity()
|
const identity = app.state.session?.getIdentity();
|
||||||
if (!identity) {
|
if (!identity) {
|
||||||
console.log('session not set in identity hook')
|
console.log('session not set in identity hook');
|
||||||
} else {
|
} else {
|
||||||
const setProfile = (profile: Profile) => {
|
const setProfile = (profile: Profile) => {
|
||||||
updateState({
|
updateState({
|
||||||
profile,
|
profile,
|
||||||
profileSet: true,
|
profileSet: true,
|
||||||
imageUrl: { uri: identity.getProfileImageUrl() },
|
imageUrl: {uri: identity.getProfileImageUrl()},
|
||||||
})
|
});
|
||||||
|
};
|
||||||
}
|
identity.addProfileListener(setProfile);
|
||||||
identity.addProfileListener(setProfile)
|
|
||||||
return () => {
|
return () => {
|
||||||
identity.removeProfileListener(setProfile)
|
identity.removeProfileListener(setProfile);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}, []);
|
||||||
}, [])
|
|
||||||
|
|
||||||
const actions = {
|
const actions = {
|
||||||
setAll: (all) => {
|
setAll: all => {
|
||||||
updateState({ all });
|
updateState({all});
|
||||||
},
|
},
|
||||||
logout: async () => {
|
logout: async () => {
|
||||||
await app.actions.accountLogout(state.all);
|
await app.actions.accountLogout(state.all);
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
|
|
||||||
return { state, actions }
|
return {state, actions};
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,13 @@
|
|||||||
import React, {useState, useContext} from 'react';
|
import React, {useState, useContext} from 'react';
|
||||||
import {View, useColorScheme} from 'react-native';
|
import {View, useColorScheme} from 'react-native';
|
||||||
import {styles} from './Session.styled';
|
import {styles} from './Session.styled';
|
||||||
import {BottomNavigation, Surface, Menu, Button, Text} from 'react-native-paper';
|
import {
|
||||||
|
BottomNavigation,
|
||||||
|
Surface,
|
||||||
|
Menu,
|
||||||
|
Button,
|
||||||
|
Text,
|
||||||
|
} from 'react-native-paper';
|
||||||
import {Settings} from '../settings/Settings';
|
import {Settings} from '../settings/Settings';
|
||||||
import {Channels} from '../channels/Channels';
|
import {Channels} from '../channels/Channels';
|
||||||
import {Contacts} from '../contacts/Contacts';
|
import {Contacts} from '../contacts/Contacts';
|
||||||
@ -11,7 +17,11 @@ import {Details} from '../details/Details';
|
|||||||
import {Identity} from '../identity/Identity';
|
import {Identity} from '../identity/Identity';
|
||||||
import {useSession} from './useSession.hook';
|
import {useSession} from './useSession.hook';
|
||||||
|
|
||||||
import {NavigationContainer, DefaultTheme, DarkTheme} from '@react-navigation/native';
|
import {
|
||||||
|
NavigationContainer,
|
||||||
|
DefaultTheme,
|
||||||
|
DarkTheme,
|
||||||
|
} from '@react-navigation/native';
|
||||||
import {createDrawerNavigator} from '@react-navigation/drawer';
|
import {createDrawerNavigator} from '@react-navigation/drawer';
|
||||||
|
|
||||||
const ChannelsRoute = () => <Channels />;
|
const ChannelsRoute = () => <Channels />;
|
||||||
@ -67,7 +77,8 @@ export function Session() {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{state.layout === 'large' && (
|
{state.layout === 'large' && (
|
||||||
<NavigationContainer theme={scheme === 'dark' ? DarkTheme : DefaultTheme}>
|
<NavigationContainer
|
||||||
|
theme={scheme === 'dark' ? DarkTheme : DefaultTheme}>
|
||||||
<DetailsScreen nav={sessionNav} />
|
<DetailsScreen nav={sessionNav} />
|
||||||
</NavigationContainer>
|
</NavigationContainer>
|
||||||
)}
|
)}
|
||||||
@ -157,7 +168,7 @@ function SettingsScreen({nav}) {
|
|||||||
id="SettingsDrawer"
|
id="SettingsDrawer"
|
||||||
drawerContent={Settings}
|
drawerContent={Settings}
|
||||||
screenOptions={{
|
screenOptions={{
|
||||||
drawerStyle: { width: '40%' },
|
drawerStyle: {width: '40%'},
|
||||||
drawerPosition: 'right',
|
drawerPosition: 'right',
|
||||||
drawerType: 'front',
|
drawerType: 'front',
|
||||||
headerShown: false,
|
headerShown: false,
|
||||||
@ -178,8 +189,7 @@ function HomeScreen({nav}) {
|
|||||||
<Surface elevation={2} mode="flat">
|
<Surface elevation={2} mode="flat">
|
||||||
<Identity openSettings={nav.settings.openDrawer} />
|
<Identity openSettings={nav.settings.openDrawer} />
|
||||||
</Surface>
|
</Surface>
|
||||||
<Surface style={styles.channels} elevation={1} mode="flat">
|
<Surface style={styles.channels} elevation={1} mode="flat"></Surface>
|
||||||
</Surface>
|
|
||||||
</View>
|
</View>
|
||||||
<View style={styles.right}>
|
<View style={styles.right}>
|
||||||
<Text>CONVERSATION</Text>
|
<Text>CONVERSATION</Text>
|
||||||
|
@ -1,34 +1,34 @@
|
|||||||
import { useEffect, useState, useContext, useRef } from 'react'
|
import {useEffect, useState, useContext, useRef} from 'react';
|
||||||
import { AppContext } from '../context/AppContext'
|
import {AppContext} from '../context/AppContext';
|
||||||
import { DisplayContext } from '../context/DisplayContext'
|
import {DisplayContext} from '../context/DisplayContext';
|
||||||
import { ContextType } from '../context/ContextType'
|
import {ContextType} from '../context/ContextType';
|
||||||
|
|
||||||
const DEBOUNCE_MS = 1000
|
const DEBOUNCE_MS = 1000;
|
||||||
|
|
||||||
export function useSession() {
|
export function useSession() {
|
||||||
const display = useContext(DisplayContext) as ContextType
|
const display = useContext(DisplayContext) as ContextType;
|
||||||
const app = useContext(AppContext) as ContextType
|
const app = useContext(AppContext) as ContextType;
|
||||||
|
|
||||||
const [state, setState] = useState({
|
const [state, setState] = useState({
|
||||||
layout: null,
|
layout: null,
|
||||||
strings: {},
|
strings: {},
|
||||||
})
|
});
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
const updateState = (value: any) => {
|
const updateState = (value: any) => {
|
||||||
setState((s) => ({ ...s, ...value }))
|
setState(s => ({...s, ...value}));
|
||||||
}
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const { layout, strings } = display.state;
|
const {layout, strings} = display.state;
|
||||||
updateState({ layout, strings });
|
updateState({layout, strings});
|
||||||
}, [display.state.layout, display.state.strings]);
|
}, [display.state.layout, display.state.strings]);
|
||||||
|
|
||||||
const actions = {
|
const actions = {
|
||||||
logout: async () => {
|
logout: async () => {
|
||||||
await app.actions.accountLogout();
|
await app.actions.accountLogout();
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
|
|
||||||
return { state, actions }
|
return {state, actions};
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import {StyleSheet} from 'react-native';
|
import {StyleSheet} from 'react-native';
|
||||||
import { Colors } from '../constants/Colors';
|
import {Colors} from '../constants/Colors';
|
||||||
|
|
||||||
export const styles = StyleSheet.create({
|
export const styles = StyleSheet.create({
|
||||||
modal: {
|
modal: {
|
||||||
@ -260,10 +260,7 @@ export const styles = StyleSheet.create({
|
|||||||
color: Colors.danger,
|
color: Colors.danger,
|
||||||
},
|
},
|
||||||
controlSwitch: {
|
controlSwitch: {
|
||||||
transform: [
|
transform: [{scaleX: 0.7}, {scaleY: 0.7}],
|
||||||
{ scaleX: 0.7 },
|
|
||||||
{scaleY: 0.7 },
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
input: {
|
input: {
|
||||||
width: '100%',
|
width: '100%',
|
||||||
@ -302,4 +299,4 @@ export const styles = StyleSheet.create({
|
|||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
color: Colors.danger,
|
color: Colors.danger,
|
||||||
},
|
},
|
||||||
})
|
});
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,14 +1,14 @@
|
|||||||
import { useEffect, useState, useContext, useRef } from 'react'
|
import {useEffect, useState, useContext, useRef} from 'react';
|
||||||
import { AppContext } from '../context/AppContext'
|
import {AppContext} from '../context/AppContext';
|
||||||
import { DisplayContext } from '../context/DisplayContext'
|
import {DisplayContext} from '../context/DisplayContext';
|
||||||
import { ContextType } from '../context/ContextType'
|
import {ContextType} from '../context/ContextType';
|
||||||
|
|
||||||
const DEBOUNCE_MS = 1000
|
const DEBOUNCE_MS = 1000;
|
||||||
|
|
||||||
export function useSettings() {
|
export function useSettings() {
|
||||||
const display = useContext(DisplayContext) as ContextType
|
const display = useContext(DisplayContext) as ContextType;
|
||||||
const app = useContext(AppContext) as ContextType
|
const app = useContext(AppContext) as ContextType;
|
||||||
const debounce = useRef(setTimeout(() => {}, 0))
|
const debounce = useRef(setTimeout(() => {}, 0));
|
||||||
|
|
||||||
const [state, setState] = useState({
|
const [state, setState] = useState({
|
||||||
config: {} as Config,
|
config: {} as Config,
|
||||||
@ -36,32 +36,32 @@ export function useSettings() {
|
|||||||
secretCopied: false,
|
secretCopied: false,
|
||||||
monthFirstDate: true,
|
monthFirstDate: true,
|
||||||
fullDayTime: false,
|
fullDayTime: false,
|
||||||
})
|
});
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
const updateState = (value: any) => {
|
const updateState = (value: any) => {
|
||||||
setState((s) => ({ ...s, ...value }))
|
setState(s => ({...s, ...value}));
|
||||||
}
|
};
|
||||||
|
|
||||||
const getSession = () => {
|
const getSession = () => {
|
||||||
const session = app.state?.session
|
const session = app.state?.session;
|
||||||
const settings = session?.getSettings()
|
const settings = session?.getSettings();
|
||||||
const identity = session?.getIdentity()
|
const identity = session?.getIdentity();
|
||||||
if (!settings || !identity) {
|
if (!settings || !identity) {
|
||||||
console.log('session not set in settings hook')
|
console.log('session not set in settings hook');
|
||||||
}
|
|
||||||
return { settings, identity }
|
|
||||||
}
|
}
|
||||||
|
return {settings, identity};
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const { settings, identity } = getSession()
|
const {settings, identity} = getSession();
|
||||||
const setConfig = (config: Config) => {
|
const setConfig = (config: Config) => {
|
||||||
updateState({ config })
|
updateState({config});
|
||||||
}
|
};
|
||||||
settings.addConfigListener(setConfig)
|
settings.addConfigListener(setConfig);
|
||||||
const setProfile = (profile: Profile) => {
|
const setProfile = (profile: Profile) => {
|
||||||
const { handle, name, location, description } = profile
|
const {handle, name, location, description} = profile;
|
||||||
const url = identity.getProfileImageUrl()
|
const url = identity.getProfileImageUrl();
|
||||||
updateState({
|
updateState({
|
||||||
profile,
|
profile,
|
||||||
handle,
|
handle,
|
||||||
@ -70,194 +70,188 @@ export function useSettings() {
|
|||||||
description,
|
description,
|
||||||
imageUrl: url,
|
imageUrl: url,
|
||||||
profileSet: true,
|
profileSet: true,
|
||||||
})
|
});
|
||||||
}
|
};
|
||||||
identity.addProfileListener(setProfile)
|
identity.addProfileListener(setProfile);
|
||||||
return () => {
|
return () => {
|
||||||
settings.removeConfigListener(setConfig)
|
settings.removeConfigListener(setConfig);
|
||||||
identity.removeProfileListener(setProfile)
|
identity.removeProfileListener(setProfile);
|
||||||
}
|
};
|
||||||
}, [])
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const { fullDayTime, monthFirstDate } = app.state;
|
const {fullDayTime, monthFirstDate} = app.state;
|
||||||
updateState({ fullDayTime, monthFirstDate });
|
updateState({fullDayTime, monthFirstDate});
|
||||||
}, [app.state.fullDayTime, app.state.monthFirstDate]);
|
}, [app.state.fullDayTime, app.state.monthFirstDate]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const {
|
const {strings, dateFormat, timeFormat} = display.state;
|
||||||
strings,
|
|
||||||
dateFormat,
|
|
||||||
timeFormat,
|
|
||||||
} = display.state
|
|
||||||
updateState({
|
updateState({
|
||||||
strings,
|
strings,
|
||||||
dateFormat,
|
dateFormat,
|
||||||
timeFormat,
|
timeFormat,
|
||||||
})
|
});
|
||||||
}, [display.state])
|
}, [display.state]);
|
||||||
|
|
||||||
const actions = {
|
const actions = {
|
||||||
getUsernameStatus: async (username: string) => {
|
getUsernameStatus: async (username: string) => {
|
||||||
const { settings } = getSession()
|
const {settings} = getSession();
|
||||||
return await settings.getUsernameStatus(username)
|
return await settings.getUsernameStatus(username);
|
||||||
},
|
},
|
||||||
setLogin: async () => {
|
setLogin: async () => {
|
||||||
const { settings } = getSession()
|
const {settings} = getSession();
|
||||||
await settings.setLogin(state.handle, state.password)
|
await settings.setLogin(state.handle, state.password);
|
||||||
},
|
},
|
||||||
enableNotifications: async () => {
|
enableNotifications: async () => {
|
||||||
const { settings } = getSession()
|
const {settings} = getSession();
|
||||||
await settings.enableNotifications()
|
await settings.enableNotifications();
|
||||||
},
|
},
|
||||||
disableNotifications: async () => {
|
disableNotifications: async () => {
|
||||||
const { settings } = getSession()
|
const {settings} = getSession();
|
||||||
await settings.disableNotifications()
|
await settings.disableNotifications();
|
||||||
},
|
},
|
||||||
enableRegistry: async () => {
|
enableRegistry: async () => {
|
||||||
const { settings } = getSession()
|
const {settings} = getSession();
|
||||||
await settings.enableRegistry()
|
await settings.enableRegistry();
|
||||||
},
|
},
|
||||||
disableRegistry: async () => {
|
disableRegistry: async () => {
|
||||||
const { settings } = getSession()
|
const {settings} = getSession();
|
||||||
await settings.disableRegistry()
|
await settings.disableRegistry();
|
||||||
},
|
},
|
||||||
enableMFA: async () => {
|
enableMFA: async () => {
|
||||||
const { settings } = getSession()
|
const {settings} = getSession();
|
||||||
const { secretImage, secretText } = await settings.enableMFA()
|
const {secretImage, secretText} = await settings.enableMFA();
|
||||||
updateState({ secretImage, secretText });
|
updateState({secretImage, secretText});
|
||||||
},
|
},
|
||||||
disableMFA: async () => {
|
disableMFA: async () => {
|
||||||
const { settings } = getSession()
|
const {settings} = getSession();
|
||||||
await settings.disableMFA()
|
await settings.disableMFA();
|
||||||
},
|
},
|
||||||
confirmMFA: async () => {
|
confirmMFA: async () => {
|
||||||
const { settings } = getSession()
|
const {settings} = getSession();
|
||||||
await settings.confirmMFA(state.code)
|
await settings.confirmMFA(state.code);
|
||||||
},
|
},
|
||||||
setCode: (code: string) => {
|
setCode: (code: string) => {
|
||||||
updateState({ code });
|
updateState({code});
|
||||||
},
|
},
|
||||||
copySecret: () => {
|
copySecret: () => {
|
||||||
navigator.clipboard.writeText(state.secretText);
|
navigator.clipboard.writeText(state.secretText);
|
||||||
updateState({ secretCopied: true });
|
updateState({secretCopied: true});
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
updateState({ secretCopied: false });
|
updateState({secretCopied: false});
|
||||||
}, 1000);
|
}, 1000);
|
||||||
},
|
},
|
||||||
setSeal: async () => {
|
setSeal: async () => {
|
||||||
const { settings } = getSession()
|
const {settings} = getSession();
|
||||||
await settings.setSeal(state.sealPassword)
|
await settings.setSeal(state.sealPassword);
|
||||||
},
|
},
|
||||||
clearSeal: async () => {
|
clearSeal: async () => {
|
||||||
const { settings } = getSession()
|
const {settings} = getSession();
|
||||||
await settings.clearSeal()
|
await settings.clearSeal();
|
||||||
},
|
},
|
||||||
unlockSeal: async () => {
|
unlockSeal: async () => {
|
||||||
const { settings } = getSession()
|
const {settings} = getSession();
|
||||||
await settings.unlockSeal(state.sealPassword)
|
await settings.unlockSeal(state.sealPassword);
|
||||||
},
|
},
|
||||||
forgetSeal: async () => {
|
forgetSeal: async () => {
|
||||||
const { settings } = getSession()
|
const {settings} = getSession();
|
||||||
await settings.forgetSeal()
|
await settings.forgetSeal();
|
||||||
},
|
},
|
||||||
updateSeal: async () => {
|
updateSeal: async () => {
|
||||||
const { settings } = getSession();
|
const {settings} = getSession();
|
||||||
await settings.updateSeal(state.sealPassword);
|
await settings.updateSeal(state.sealPassword);
|
||||||
},
|
},
|
||||||
setProfileData: async (
|
setProfileData: async (
|
||||||
name: string,
|
name: string,
|
||||||
location: string,
|
location: string,
|
||||||
description: string
|
description: string,
|
||||||
) => {
|
) => {
|
||||||
const { identity } = getSession()
|
const {identity} = getSession();
|
||||||
await identity.setProfileData(name, location, description)
|
await identity.setProfileData(name, location, description);
|
||||||
},
|
},
|
||||||
setProfileImage: async (image: string) => {
|
setProfileImage: async (image: string) => {
|
||||||
const { identity } = getSession()
|
const {identity} = getSession();
|
||||||
await identity.setProfileImage(image)
|
await identity.setProfileImage(image);
|
||||||
},
|
},
|
||||||
getProfileImageUrl: () => {
|
getProfileImageUrl: () => {
|
||||||
const { identity } = getSession()
|
const {identity} = getSession();
|
||||||
return identity.getProfileImageUrl()
|
return identity.getProfileImageUrl();
|
||||||
},
|
},
|
||||||
setDateFormat: (format: string) => {
|
setDateFormat: (format: string) => {
|
||||||
display.actions.setDateFormat(format)
|
display.actions.setDateFormat(format);
|
||||||
},
|
},
|
||||||
setTimeFormat: (format: string) => {
|
setTimeFormat: (format: string) => {
|
||||||
display.actions.setTimeFormat(format)
|
display.actions.setTimeFormat(format);
|
||||||
},
|
},
|
||||||
setAll: (all: boolean) => {
|
setAll: (all: boolean) => {
|
||||||
updateState({ all })
|
updateState({all});
|
||||||
},
|
},
|
||||||
logout: async () => {
|
logout: async () => {
|
||||||
await app.actions.accountLogout(state.all)
|
await app.actions.accountLogout(state.all);
|
||||||
},
|
},
|
||||||
remove: async () => {
|
remove: async () => {
|
||||||
await app.actions.accountRemove()
|
await app.actions.accountRemove();
|
||||||
},
|
},
|
||||||
setHandle: (handle: string) => {
|
setHandle: (handle: string) => {
|
||||||
updateState({ handle, taken: false, checked: false })
|
updateState({handle, taken: false, checked: false});
|
||||||
clearTimeout(debounce.current)
|
clearTimeout(debounce.current);
|
||||||
if (!handle || handle === state.profile.handle) {
|
if (!handle || handle === state.profile.handle) {
|
||||||
updateState({ available: true, checked: true })
|
updateState({available: true, checked: true});
|
||||||
} else {
|
} else {
|
||||||
debounce.current = setTimeout(async () => {
|
debounce.current = setTimeout(async () => {
|
||||||
const { settings } = getSession()
|
const {settings} = getSession();
|
||||||
try {
|
try {
|
||||||
const available = await settings.getUsernameStatus(handle)
|
const available = await settings.getUsernameStatus(handle);
|
||||||
updateState({ taken: !available, checked: true })
|
updateState({taken: !available, checked: true});
|
||||||
}
|
} catch (err) {
|
||||||
catch (err) {
|
|
||||||
console.log(err);
|
console.log(err);
|
||||||
}
|
}
|
||||||
}, DEBOUNCE_MS)
|
}, DEBOUNCE_MS);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
setPassword: (password: string) => {
|
setPassword: (password: string) => {
|
||||||
updateState({ password })
|
updateState({password});
|
||||||
},
|
},
|
||||||
setConfirm: (confirm: string) => {
|
setConfirm: (confirm: string) => {
|
||||||
updateState({ confirm })
|
updateState({confirm});
|
||||||
},
|
},
|
||||||
setRemove: (remove: string) => {
|
setRemove: (remove: string) => {
|
||||||
updateState({ remove });
|
updateState({remove});
|
||||||
},
|
},
|
||||||
setName: (name: string) => {
|
setName: (name: string) => {
|
||||||
updateState({ name })
|
updateState({name});
|
||||||
},
|
},
|
||||||
setLocation: (location: string) => {
|
setLocation: (location: string) => {
|
||||||
updateState({ location })
|
updateState({location});
|
||||||
},
|
},
|
||||||
setDescription: (description: string) => {
|
setDescription: (description: string) => {
|
||||||
updateState({ description })
|
updateState({description});
|
||||||
},
|
},
|
||||||
setDetails: async () => {
|
setDetails: async () => {
|
||||||
const { identity } = getSession()
|
const {identity} = getSession();
|
||||||
const { name, location, description } = state
|
const {name, location, description} = state;
|
||||||
await identity.setProfileData(name, location, description)
|
await identity.setProfileData(name, location, description);
|
||||||
},
|
},
|
||||||
setSealDelete: (sealDelete: string) => {
|
setSealDelete: (sealDelete: string) => {
|
||||||
updateState({ sealDelete });
|
updateState({sealDelete});
|
||||||
},
|
},
|
||||||
setSealPassword: (sealPassword: string) => {
|
setSealPassword: (sealPassword: string) => {
|
||||||
updateState({ sealPassword });
|
updateState({sealPassword});
|
||||||
},
|
},
|
||||||
setSealConfirm: (sealConfirm: string) => {
|
setSealConfirm: (sealConfirm: string) => {
|
||||||
updateState({ sealConfirm });
|
updateState({sealConfirm});
|
||||||
},
|
},
|
||||||
setFullDayTime: async (flag: boolean) => {
|
setFullDayTime: async (flag: boolean) => {
|
||||||
try {
|
try {
|
||||||
await app.actions.setFullDayTime(flag);
|
await app.actions.setFullDayTime(flag);
|
||||||
}
|
} catch (err) {
|
||||||
catch (err) {
|
|
||||||
console.log(err);
|
console.log(err);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
setMonthFirstDate: async (flag: boolean) => {
|
setMonthFirstDate: async (flag: boolean) => {
|
||||||
await app.actions.setMonthFirstDate(flag);
|
await app.actions.setMonthFirstDate(flag);
|
||||||
},
|
},
|
||||||
}
|
};
|
||||||
|
|
||||||
return { state, actions }
|
return {state, actions};
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,8 @@ export function InputCode({onChangeText, style}) {
|
|||||||
<Text style={styles.text}>{code.charAt(5)}</Text>
|
<Text style={styles.text}>{code.charAt(5)}</Text>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
<TextInput style={styles.input}
|
<TextInput
|
||||||
|
style={styles.input}
|
||||||
keyboardType={Platform.OS === 'ios' ? 'numeric' : 'number-pad'}
|
keyboardType={Platform.OS === 'ios' ? 'numeric' : 'number-pad'}
|
||||||
onChangeText={updateCode}
|
onChangeText={updateCode}
|
||||||
autoCorrect={false}
|
autoCorrect={false}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user