Persist Data on Android (#274)

* Android Cookies

* Android Fix POST headers

* Format

* App & Cookies Working

* Fix token on UserGen
This commit is contained in:
KoalaSat 2022-10-10 12:40:22 +00:00 committed by GitHub
parent f2dc7d0f90
commit e78b5e9c8b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 247 additions and 119 deletions

View File

@ -134,6 +134,13 @@ export default class App extends Component {
}
}
const root = ReactDOM.createRoot(document.getElementById('app'));
const loadApp = () => {
if (systemClient.loading) {
setTimeout(loadApp, 200);
} else {
const root = ReactDOM.createRoot(document.getElementById('app'));
root.render(<App />);
}
};
root.render(<App />);
loadApp();

View File

@ -19,6 +19,7 @@ import MediaQuery from 'react-responsive';
import Flags from 'country-flag-icons/react/3x2';
import { Link as LinkRouter } from 'react-router-dom';
import { apiClient } from '../services/api';
import { systemClient } from '../services/System';
import RobotAvatar from './Robots/RobotAvatar';
// Icons
@ -41,7 +42,6 @@ import {
UpdateClientDialog,
} from './Dialogs';
import { getCookie } from '../utils/cookies';
import checkVer from '../utils/checkVer';
class BottomBar extends Component {
@ -172,9 +172,8 @@ class BottomBar extends Component {
showProfileButton = () => {
return (
this.props.avatarLoaded &&
(window.NativeRobosats ||
((this.props.token ? getCookie('robot_token') === this.props.token : true) &&
getCookie('sessionid')))
(this.props.token ? systemClient.getCookie('robot_token') === this.props.token : true) &&
systemClient.getCookie('sessionid')
);
};
@ -467,7 +466,7 @@ class BottomBar extends Component {
handleClickOpenExchangeSummary = () => {
// avoid calling getInfo while sessionid not yet set. Temporary fix.
if (getCookie('sessionid')) {
if (systemClient.getCookie('sessionid')) {
this.getInfo();
}
this.setState({ openExchangeSummary: true });

View File

@ -36,7 +36,6 @@ import PersonAddAltIcon from '@mui/icons-material/PersonAddAlt';
import EmojiEventsIcon from '@mui/icons-material/EmojiEvents';
import { UserNinjaIcon, BitcoinIcon } from '../Icons';
import { getCookie } from '../../utils/cookies';
import { systemClient } from '../../services/System';
import { getWebln } from '../../utils/webln';
import RobotAvatar from '../Robots/RobotAvatar';
@ -98,7 +97,7 @@ const ProfileDialog = ({
}, [showRewards]);
const copyTokenHandler = () => {
const robotToken = getCookie('robot_token');
const robotToken = systemClient.getCookie('robot_token');
if (robotToken) {
systemClient.copyToClipboard(robotToken);
@ -226,12 +225,12 @@ const ProfileDialog = ({
</ListItemIcon>
<ListItemText secondary={t('Your token (will not remain here)')}>
{getCookie('robot_token') ? (
{systemClient.getCookie('robot_token') ? (
<TextField
disabled
sx={{ width: '100%', maxWidth: '450px' }}
label={t('Back it up!')}
value={getCookie('robot_token')}
value={systemClient.getCookie('robot_token')}
variant='filled'
size='small'
InputProps={{

View File

@ -12,7 +12,7 @@ import {
Button,
Grid,
} from '@mui/material';
import { getCookie } from '../../utils/cookies';
import { systemClient } from '../../services/System';
import ContentCopy from '@mui/icons-material/ContentCopy';
interface Props {
@ -50,7 +50,7 @@ const StoreTokenDialog = ({
sx={{ width: '100%', maxWidth: '550px' }}
disabled
label={t('Back it up!')}
value={getCookie('robot_token')}
value={systemClient.getCookie('robot_token')}
variant='filled'
size='small'
InputProps={{

View File

@ -16,7 +16,6 @@ import {
} from '@mui/material';
import ReconnectingWebSocket from 'reconnecting-websocket';
import { encryptMessage, decryptMessage } from '../utils/pgp';
import { getCookie } from '../utils/cookies';
import { saveAsJson } from '../utils/saveFile';
import { AuditPGPDialog } from './Dialogs';
import RobotAvatar from './Robots/RobotAvatar';
@ -37,10 +36,10 @@ class Chat extends Component {
}
state = {
own_pub_key: getCookie('pub_key').split('\\').join('\n'),
own_enc_priv_key: getCookie('enc_priv_key').split('\\').join('\n'),
own_pub_key: systemClient.getCookie('pub_key').split('\\').join('\n'),
own_enc_priv_key: systemClient.getCookie('enc_priv_key').split('\\').join('\n'),
peer_pub_key: null,
token: getCookie('robot_token'),
token: systemClient.getCookie('robot_token'),
messages: [],
value: '',
connected: false,

View File

@ -43,7 +43,6 @@ import LockIcon from '@mui/icons-material/Lock';
import HourglassTopIcon from '@mui/icons-material/HourglassTop';
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
import { getCookie } from '../utils/cookies';
import { pn } from '../utils/prettyNumbers';
import { systemClient } from '../services/System';
@ -919,12 +918,12 @@ class MakerPage extends Component {
const { t } = this.props;
return (
<Grid container align='center' spacing={1} sx={{ minWidth: '60%' }}>
{getCookie('robot_token') ? (
{systemClient.getCookie('robot_token') ? (
<StoreTokenDialog
open={this.state.openStoreToken}
onClose={() => this.setState({ openStoreToken: false })}
onClickCopy={() =>
systemClient.copyToClipboard(getCookie('robot_token')) &
systemClient.copyToClipboard(systemClient.getCookie('robot_token')) &
this.props.setAppState({ copiedToken: true })
}
copyIconColor={this.props.copiedToken ? 'inherit' : 'primary'}

View File

@ -50,7 +50,6 @@ import HourglassTopIcon from '@mui/icons-material/HourglassTop';
import CheckIcon from '@mui/icons-material/Check';
import { SendReceiveIcon } from './Icons';
import { getCookie } from '../utils/cookies';
import { pn } from '../utils/prettyNumbers';
import { systemClient } from '../services/System';
import { getWebln } from '../utils/webln';
@ -522,12 +521,12 @@ class OrderPage extends Component {
};
tokenDialog = () => {
return getCookie('robot_token') ? (
return systemClient.getCookie('robot_token') ? (
<StoreTokenDialog
open={this.state.openStoreToken}
onClose={() => this.setState({ openStoreToken: false })}
onClickCopy={() =>
systemClient.copyToClipboard(getCookie('robot_token')) &
systemClient.copyToClipboard(systemClient.getCookie('robot_token')) &
this.props.setAppState({ copiedToken: true })
}
copyIconColor={this.props.copiedToken ? 'inherit' : 'primary'}

View File

@ -52,7 +52,6 @@ import RocketLaunchIcon from '@mui/icons-material/RocketLaunch';
import RefreshIcon from '@mui/icons-material/Refresh';
import { NewTabIcon } from './Icons';
import { getCookie } from '../utils/cookies';
import { pn } from '../utils/prettyNumbers';
class TradeBox extends Component {

View File

@ -24,7 +24,6 @@ import { RoboSatsNoTextIcon } from './Icons';
import { sha256 } from 'js-sha256';
import { genBase62Token, tokenStrength } from '../utils/token';
import { genKey } from '../utils/pgp';
import { getCookie, writeCookie, deleteCookie } from '../utils/cookies';
import { saveAsJson } from '../utils/saveFile';
import { systemClient } from '../services/System';
import { apiClient } from '../services/api/index';
@ -47,10 +46,13 @@ class UserGenPage extends Component {
// Displays the existing one
if (this.props.nickname != null) {
this.setState({
nickname: this.props.nickname,
token: this.props.token ? this.props.token : '',
loadingRobot: false,
});
} else if (window.NativeRobosats && systemClient.getCookie('robot_token')) {
const token = systemClient.getCookie('robot_token');
this.props.setAppState({ token });
this.setState({ token, loadingRobot: false });
} else {
const newToken = genBase62Token(36);
this.setState({
@ -78,7 +80,6 @@ class UserGenPage extends Component {
requestBody.then((body) =>
apiClient.post('/api/user/', body).then((data) => {
this.setState({
nickname: data.nickname,
bit_entropy: data.token_bits_entropy,
shannon_entropy: data.token_shannon_entropy,
bad_request: data.bad_request,
@ -110,9 +111,12 @@ class UserGenPage extends Component {
tgBotName: data.tg_bot_name,
tgToken: data.tg_token,
}) &
writeCookie('robot_token', token) &
writeCookie('pub_key', data.public_key.split('\n').join('\\')) &
writeCookie('enc_priv_key', data.encrypted_private_key.split('\n').join('\\'))) &
systemClient.setCookie('robot_token', token) &
systemClient.setCookie('pub_key', data.public_key.split('\n').join('\\')) &
systemClient.setCookie(
'enc_priv_key',
data.encrypted_private_key.split('\n').join('\\'),
)) &
// If the robot has been found (recovered) we assume the token is backed up
(data.found ? this.props.setAppState({ copiedToken: true }) : null);
}),
@ -122,10 +126,10 @@ class UserGenPage extends Component {
delGeneratedUser() {
apiClient.delete('/api/user');
deleteCookie('sessionid');
deleteCookie('robot_token');
deleteCookie('pub_key');
deleteCookie('enc_priv_key');
systemClient.deleteCookie('sessionid');
systemClient.deleteCookie('robot_token');
systemClient.deleteCookie('pub_key');
systemClient.deleteCookie('enc_priv_key');
}
handleClickNewRandomToken = () => {
@ -168,11 +172,11 @@ class UserGenPage extends Component {
createJsonFile = () => {
return {
token: getCookie('robot_token'),
token: systemClient.getCookie('robot_token'),
token_shannon_entropy: this.state.shannon_entropy,
token_bit_entropy: this.state.bit_entropy,
public_key: getCookie('pub_key').split('\\').join('\n'),
encrypted_private_key: getCookie('enc_priv_key').split('\\').join('\n'),
public_key: systemClient.getCookie('pub_key').split('\\').join('\n'),
encrypted_private_key: systemClient.getCookie('enc_priv_key').split('\\').join('\n'),
};
};
@ -191,12 +195,12 @@ class UserGenPage extends Component {
align='center'
sx={{ width: 370 * fontSizeFactor, height: 260 * fontSizeFactor }}
>
{this.props.avatarLoaded && this.state.nickname ? (
{this.props.avatarLoaded && this.props.nickname ? (
<div>
<Grid item xs={12} align='center'>
<Typography component='h5' variant='h5'>
<b>
{this.state.nickname && getCookie('sessionid') ? (
{this.props.nickname && systemClient.getCookie('sessionid') ? (
<div
style={{
display: 'flex',
@ -213,7 +217,7 @@ class UserGenPage extends Component {
width: 33 * fontSizeFactor,
}}
/>
<a>{this.state.nickname}</a>
<a>{this.props.nickname}</a>
<BoltIcon
sx={{
color: '#fcba03',
@ -230,7 +234,7 @@ class UserGenPage extends Component {
</Grid>
<Grid item xs={12} align='center'>
<RobotAvatar
nickname={this.state.nickname}
nickname={this.props.nickname}
smooth={true}
style={{ maxWidth: 203 * fontSizeFactor, maxHeight: 203 * fontSizeFactor }}
imageStyle={{
@ -297,11 +301,10 @@ class UserGenPage extends Component {
color='primary'
disabled={
!this.props.avatarLoaded ||
(!window.NativeRobosats &&
!(getCookie('robot_token') === this.state.token))
!(systemClient.getCookie('robot_token') === this.state.token)
}
onClick={() =>
saveAsJson(this.state.nickname + '.json', this.createJsonFile())
saveAsJson(this.props.nickname + '.json', this.createJsonFile())
}
>
<DownloadIcon
@ -317,11 +320,10 @@ class UserGenPage extends Component {
color={this.props.copiedToken ? 'inherit' : 'primary'}
disabled={
!this.props.avatarLoaded ||
(!window.NativeRobosats &&
!(getCookie('robot_token') === this.state.token))
!(systemClient.getCookie('robot_token') === this.state.token)
}
onClick={() =>
systemClient.copyToClipboard(getCookie('robot_token')) &
systemClient.copyToClipboard(systemClient.getCookie('robot_token')) &
this.props.setAppState({ copiedToken: true })
}
>
@ -374,8 +376,9 @@ class UserGenPage extends Component {
<Button
disabled={
this.state.loadingRobot !== false ||
(!window.NativeRobosats &&
!(this.props.token ? getCookie('robot_token') === this.props.token : true))
!(this.props.token
? systemClient.getCookie('robot_token') === this.props.token
: true)
}
color='primary'
to='/make/'
@ -394,8 +397,9 @@ class UserGenPage extends Component {
<Button
disabled={
this.state.loadingRobot !== false ||
(!window.NativeRobosats &&
!(this.props.token ? getCookie('robot_token') === this.props.token : true))
!(this.props.token
? systemClient.getCookie('robot_token') === this.props.token
: true)
}
color='secondary'
to='/book/'

View File

@ -23,8 +23,9 @@ export interface NativeWebViewMessageHttp {
export interface NativeWebViewMessageSystem {
id?: number;
category: 'system';
type: 'torStatus' | 'copyToClipboardString';
detail: string;
type: 'init' | 'torStatus' | 'copyToClipboardString' | 'setCookie' | 'deleteCookie';
key?: string;
detail?: string;
}
export declare type NativeWebViewMessage = NativeWebViewMessageHttp | NativeWebViewMessageSystem;

View File

@ -1,16 +1,19 @@
import { systemClient } from '../System';
import { NativeRobosatsPromise, NativeWebViewMessage, NativeWebViewMessageSystem } from './index.d';
class NativeRobosats {
constructor() {
this.messageCounter = 0;
}
public torDaemonStatus = 'NOTINIT';
private messageCounter: number;
private messageCounter: number = 0;
private pendingMessages: { [id: number]: NativeRobosatsPromise } = {};
public cookies: { [key: string]: string } = {};
public loadCookie = (cookie: { key: string; value: string }) => {
this.cookies[cookie.key] = cookie.value;
};
public onMessageResolve: (messageId: number, response?: object) => void = (
messageId,
response = {},
@ -33,8 +36,12 @@ class NativeRobosats {
public onMessage: (message: NativeWebViewMessageSystem) => void = (message) => {
if (message.type === 'torStatus') {
this.torDaemonStatus = message.detail;
this.torDaemonStatus = message.detail || 'ERROR';
window.dispatchEvent(new CustomEvent('torStatus', { detail: this.torDaemonStatus }));
} else if (message.type === 'setCookie') {
if (message.key !== undefined) {
this.cookies[message.key] = message.detail;
}
}
};

View File

@ -3,11 +3,17 @@ import NativeRobosats from '../../Native';
class SystemNativeClient implements SystemClient {
constructor() {
if (!window.NativeRobosats) {
window.NativeRobosats = new NativeRobosats();
}
window.NativeRobosats = new NativeRobosats();
window.NativeRobosats.postMessage({
category: 'system',
type: 'init',
}).then(() => {
this.loading = false;
});
}
public loading = true;
public copyToClipboard: (value: string) => void = (value) => {
return window.NativeRobosats?.postMessage({
category: 'system',
@ -15,6 +21,30 @@ class SystemNativeClient implements SystemClient {
detail: value,
});
};
public getCookie: (key: string) => string | undefined = (key) => {
return window.NativeRobosats?.cookies[key];
};
public setCookie: (key: string, value: string) => void = (key, value) => {
delete window.NativeRobosats?.cookies[key];
window.NativeRobosats?.postMessage({
category: 'system',
type: 'setCookie',
key,
detail: value,
});
};
public deleteCookie: (key: string) => void = (key) => {
delete window.NativeRobosats?.cookies[key];
window.NativeRobosats?.postMessage({
category: 'system',
type: 'deleteCookie',
key,
});
};
}
export default SystemNativeClient;

View File

@ -1,6 +1,8 @@
import { SystemClient } from '..';
class SystemWebClient implements SystemClient {
public loading = false;
public copyToClipboard: (value: string) => void = (value) => {
// navigator clipboard api needs a secure context (https)
// this function attempts to copy also on http contexts
@ -24,6 +26,31 @@ class SystemWebClient implements SystemClient {
textArea.remove();
}
};
public getCookie: (key: string) => string | undefined = (key) => {
let cookieValue = null;
if (document.cookie && document.cookie !== '') {
const cookies = document.cookie.split(';');
for (let i = 0; i < cookies.length; i++) {
const cookie = cookies[i].trim();
// Does this cookie string begin with the key we want?
if (cookie.substring(0, key.length + 1) === key + '=') {
cookieValue = decodeURIComponent(cookie.substring(key.length + 1));
break;
}
}
}
return cookieValue || '';
};
public setCookie: (key: string, value: string) => void = (key, value) => {
document.cookie = `${key}=${value};path=/;SameSite=Strict`;
};
public deleteCookie: (key: string) => void = (key) => {
document.cookie = `${name}= ; expires = Thu, 01 Jan 1970 00:00:00 GMT`;
};
}
export default SystemWebClient;

View File

@ -2,7 +2,11 @@ import SystemNativeClient from './SystemNativeClient';
import SystemWebClient from './SystemWebClient';
export interface SystemClient {
loading: boolean;
copyToClipboard: (value: string) => void;
getCookie: (key: string) => string | undefined;
setCookie: (key: string, value: string) => void;
deleteCookie: (key: string) => void;
}
export const systemClient: SystemClient =

View File

@ -1,19 +1,42 @@
import { ApiClient } from '../api';
import { getCookie } from '../../../utils/cookies';
import { systemClient } from '../../System';
import NativeRobosats from '../../Native';
class ApiNativeClient implements ApiClient {
constructor() {
if (!window.NativeRobosats) {
window.NativeRobosats = new NativeRobosats();
}
}
private assetsCache: { [path: string]: string } = {};
private assetsPromises: { [path: string]: Promise<string | undefined> } = {};
private readonly getHeaders: () => HeadersInit = () => {
return { 'Content-Type': 'application/json', 'X-CSRFToken': getCookie('csrftoken') || '' };
let headers = {
'Content-Type': 'application/json',
};
const sessionid = systemClient.getCookie('sessionid');
if (sessionid) {
const robotToken = systemClient.getCookie('robot_token');
const csrftoken = systemClient.getCookie('csrftoken');
const pubKey = systemClient.getCookie('pub_key');
headers = {
...headers,
...{
'X-CSRFToken': csrftoken,
Cookie: `sessionid=${sessionid};robot_token=${robotToken};csrftoken=${csrftoken};pub_key=${pubKey}`,
},
};
}
return headers;
};
private readonly parseResponse = (response: { [key: string]: any }): object => {
if (response.headers['set-cookie']) {
response.headers['set-cookie'].forEach((cookie: string) => {
const keySplit: string[] = cookie.split('=');
systemClient.setCookie(keySplit[0], keySplit[1].split(';')[0]);
});
}
return response.json;
};
public put: (path: string, body: object) => Promise<object | undefined> = async (path, body) => {
@ -26,7 +49,7 @@ class ApiNativeClient implements ApiClient {
type: 'delete',
path,
headers: this.getHeaders(),
});
}).then(this.parseResponse);
};
public post: (path: string, body: object) => Promise<object | undefined> = async (path, body) => {
@ -36,7 +59,7 @@ class ApiNativeClient implements ApiClient {
path,
body,
headers: this.getHeaders(),
});
}).then(this.parseResponse);
};
public get: (path: string) => Promise<object | undefined> = async (path) => {
@ -44,7 +67,8 @@ class ApiNativeClient implements ApiClient {
category: 'http',
type: 'get',
path,
});
headers: this.getHeaders(),
}).then(this.parseResponse);
};
public fileImageUrl: (path: string) => Promise<string | undefined> = async (path) => {

View File

@ -1,9 +1,12 @@
import { ApiClient } from '../api';
import { getCookie } from '../../../utils/cookies';
import { systemClient } from '../../System';
class ApiWebClient implements ApiClient {
private readonly getHeaders: () => HeadersInit = () => {
return { 'Content-Type': 'application/json', 'X-CSRFToken': getCookie('csrftoken') || '' };
return {
'Content-Type': 'application/json',
'X-CSRFToken': systemClient.getCookie('csrftoken') || '',
};
};
public post: (path: string, body: object) => Promise<object | undefined> = async (path, body) => {

View File

@ -1,23 +0,0 @@
export const getCookie = (name) => {
let cookieValue = null;
if (document.cookie && document.cookie !== '') {
const cookies = document.cookie.split(';');
for (let i = 0; i < cookies.length; i++) {
const cookie = cookies[i].trim();
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === name + '=') {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
};
export const writeCookie = (key, value) => {
document.cookie = `${key}=${value};path=/;SameSite=Strict`;
};
export const deleteCookie = (name) => {
document.cookie = `${name}= ; expires = Thu, 01 Jan 1970 00:00:00 GMT`;
};

View File

@ -1,16 +1,18 @@
import React, { useEffect, useRef } from 'react';
import { WebView, WebViewMessageEvent } from 'react-native-webview';
import { SafeAreaView, Text, Platform } from 'react-native';
import { torClient } from './services/Tor';
import TorClient from './services/Tor';
import Clipboard from '@react-native-clipboard/clipboard';
import NetInfo from '@react-native-community/netinfo';
import EncryptedStorage from 'react-native-encrypted-storage';
const App = () => {
const torClient = new TorClient();
const webViewRef = useRef<WebView>();
const uri = (Platform.OS === 'android' ? 'file:///android_asset/' : '') + 'Web.bundle/index.html';
const injectMessageResolve = (id: string, data: object) => {
const json = JSON.stringify(data);
const injectMessageResolve = (id: string, data?: object) => {
const json = JSON.stringify(data || {});
webViewRef.current?.injectJavaScript(
`(function() {window.NativeRobosats.onMessageResolve(${id}, ${json});})();`,
);
@ -23,17 +25,36 @@ const App = () => {
);
};
const init = (reponseId: string) => {
const loadCookie = (key: string) => {
return EncryptedStorage.getItem(key).then((value) => {
if (value) {
const json = JSON.stringify({ key, value });
webViewRef.current?.injectJavaScript(
`(function() {window.NativeRobosats?.loadCookie(${json});})();`,
);
}
});
};
loadCookie('sessionid');
loadCookie('robot_token');
loadCookie('csrftoken');
loadCookie('pub_key');
loadCookie('enc_priv_key').then(() => injectMessageResolve(reponseId));
};
const onMessage = async (event: WebViewMessageEvent) => {
const data = JSON.parse(event.nativeEvent.data);
if (data.category === 'http') {
sendTorStatus();
if (data.type === 'get') {
torClient
.get(data.path)
.get(data.path, data.headers)
.then((response: object) => {
injectMessageResolve(data.id, response);
})
.catch(sendTorStatus)
.finally(sendTorStatus);
} else if (data.type === 'post') {
torClient
@ -41,6 +62,7 @@ const App = () => {
.then((response: object) => {
injectMessageResolve(data.id, response);
})
.catch(sendTorStatus)
.finally(sendTorStatus);
} else if (data.type === 'delete') {
torClient
@ -48,6 +70,7 @@ const App = () => {
.then((response: object) => {
injectMessageResolve(data.id, response);
})
.catch(sendTorStatus)
.finally(sendTorStatus);
} else if (data.type === 'xhr') {
torClient
@ -55,15 +78,35 @@ const App = () => {
.then((response: object) => {
injectMessageResolve(data.id, response);
})
.catch(sendTorStatus)
.finally(sendTorStatus);
}
} else if (data.category === 'system') {
if (data.type === 'copyToClipboardString') {
if (data.type === 'init') {
init(data.id);
} else if (data.type === 'copyToClipboardString') {
Clipboard.setString(data.detail);
} else if (data.type === 'setCookie') {
setCookie(data.key, data.detail);
} else if (data.type === 'deleteCookie') {
EncryptedStorage.removeItem(data.key);
}
}
};
const setCookie = async (key: string, value: string) => {
try {
await EncryptedStorage.setItem(key, value);
const storedValue = await EncryptedStorage.getItem(key);
injectMessage({
category: 'system',
type: 'setCookie',
key,
detail: storedValue,
});
} catch (error) {}
};
const sendTorStatus = async () => {
NetInfo.fetch().then(async (state) => {
let daemonStatus = 'ERROR';

View File

@ -12,6 +12,7 @@
"@react-native-community/netinfo": "^9.3.4",
"react": "^18.0.0",
"react-native": "^0.69.6",
"react-native-encrypted-storage": "^4.0.2",
"react-native-tor": "^0.1.8",
"react-native-v8": "^1.5.0",
"react-native-webview": "^11.22.3",
@ -13411,6 +13412,15 @@
"nullthrows": "^1.1.1"
}
},
"node_modules/react-native-encrypted-storage": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/react-native-encrypted-storage/-/react-native-encrypted-storage-4.0.2.tgz",
"integrity": "sha512-vneDkHGDuTvLQjUBztqb2YI8QoH1zxdJonPGTS+g57lfJZff9fAjoLSSb6NgMBebpXFcK3I3sEresGyL+3AArw==",
"peerDependencies": {
"react": "*",
"react-native": "*"
}
},
"node_modules/react-native-gradle-plugin": {
"version": "0.0.7",
"resolved": "https://registry.npmjs.org/react-native-gradle-plugin/-/react-native-gradle-plugin-0.0.7.tgz",
@ -25923,6 +25933,12 @@
"nullthrows": "^1.1.1"
}
},
"react-native-encrypted-storage": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/react-native-encrypted-storage/-/react-native-encrypted-storage-4.0.2.tgz",
"integrity": "sha512-vneDkHGDuTvLQjUBztqb2YI8QoH1zxdJonPGTS+g57lfJZff9fAjoLSSb6NgMBebpXFcK3I3sEresGyL+3AArw==",
"requires": {}
},
"react-native-gradle-plugin": {
"version": "0.0.7",
"resolved": "https://registry.npmjs.org/react-native-gradle-plugin/-/react-native-gradle-plugin-0.0.7.tgz",

View File

@ -16,6 +16,7 @@
"@react-native-community/netinfo": "^9.3.4",
"react": "^18.0.0",
"react-native": "^0.69.6",
"react-native-encrypted-storage": "^4.0.2",
"react-native-tor": "^0.1.8",
"react-native-v8": "^1.5.0",
"react-native-webview": "^11.22.3",

View File

@ -20,14 +20,12 @@ class TorClient {
}
};
public get: (path: string) => Promise<object> = async (path) => {
await this.connectDaemon();
public get: (path: string, headers: object) => Promise<object> = async (path, headers) => {
return await new Promise<object>(async (resolve, reject) => {
try {
const response = await this.daemon.get(`${this.baseUrl}${path}`);
const response = await this.daemon.get(`${this.baseUrl}${path}`, headers);
resolve(response.json);
resolve(response);
} catch (error) {
reject(error);
}
@ -35,13 +33,11 @@ class TorClient {
};
public delete: (path: string, headers: object) => Promise<object> = async (path, headers) => {
await this.connectDaemon();
return await new Promise<object>(async (resolve, reject) => {
try {
const response = await this.daemon.delete(`${this.baseUrl}${path}`, '', headers);
resolve(response.json);
resolve(response);
} catch (error) {
reject(error);
}
@ -49,8 +45,6 @@ class TorClient {
};
public request: (path: string) => Promise<object> = async (path) => {
await this.connectDaemon();
return await new Promise<object>(async (resolve, reject) => {
try {
const response = await this.daemon
@ -71,14 +65,12 @@ class TorClient {
body,
headers,
) => {
await this.connectDaemon();
return await new Promise<object>(async (resolve, reject) => {
try {
const json = JSON.stringify(body);
const response = await this.daemon.post(`${this.baseUrl}${path}`, json, headers);
resolve(response.json);
resolve(response);
} catch (error) {
reject(error);
}
@ -86,6 +78,4 @@ class TorClient {
};
}
export const torClient = new TorClient();
export default TorClient;