mirror of
https://github.com/RoboSats/robosats.git
synced 2025-01-31 02:21:35 +00:00
Android Tor icon and copy to clipboard (#269)
* Android Clipboard and Tor Status Icon * working clipboard and lintern * Fix * Add style for Tor connection component * Fix Freeze and Internet out * Fix Typo Co-authored-by: Reckless_Satoshi <reckless.satoshi@protonmail.com>
This commit is contained in:
parent
1352937fe6
commit
9bda934ee5
@ -5,6 +5,7 @@ import { CssBaseline, IconButton, Link } from '@mui/material';
|
||||
import { ThemeProvider, createTheme } from '@mui/material/styles';
|
||||
import UnsafeAlert from './UnsafeAlert';
|
||||
import { LearnDialog } from './Dialogs';
|
||||
import TorConnection from './TorConnection';
|
||||
|
||||
import { I18nextProvider } from 'react-i18next';
|
||||
import i18n from './i18n';
|
||||
@ -16,6 +17,7 @@ import SchoolIcon from '@mui/icons-material/School';
|
||||
import ZoomOutIcon from '@mui/icons-material/ZoomOut';
|
||||
import ZoomInIcon from '@mui/icons-material/ZoomIn';
|
||||
import SettingsIcon from '@mui/icons-material/Settings';
|
||||
import { systemClient } from '../services/System';
|
||||
|
||||
export default class App extends Component {
|
||||
constructor(props) {
|
||||
@ -102,6 +104,7 @@ export default class App extends Component {
|
||||
open={this.state.openLearn}
|
||||
onClose={() => this.setState({ openLearn: false })}
|
||||
/>
|
||||
<TorConnection />
|
||||
<IconButton
|
||||
color='inherit'
|
||||
sx={{ position: 'fixed', right: '34px' }}
|
||||
|
@ -15,7 +15,7 @@ import {
|
||||
} from '@mui/material';
|
||||
|
||||
import { saveAsJson } from '../../utils/saveFile';
|
||||
import { copyToClipboard } from '../../utils/clipboard';
|
||||
import { systemClient } from '../../services/System';
|
||||
|
||||
// Icons
|
||||
import KeyIcon from '@mui/icons-material/Key';
|
||||
@ -37,7 +37,7 @@ function CredentialTextfield(props) {
|
||||
InputProps={{
|
||||
endAdornment: (
|
||||
<Tooltip disableHoverListener enterTouchDelay={0} title={props.copiedTitle}>
|
||||
<IconButton onClick={async () => await copyToClipboard(props.value)}>
|
||||
<IconButton onClick={() => systemClient.copyToClipboard(props.value)}>
|
||||
<ContentCopy />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
|
@ -37,7 +37,7 @@ import EmojiEventsIcon from '@mui/icons-material/EmojiEvents';
|
||||
import { UserNinjaIcon, BitcoinIcon } from '../Icons';
|
||||
|
||||
import { getCookie } from '../../utils/cookies';
|
||||
import { copyToClipboard } from '../../utils/clipboard';
|
||||
import { systemClient } from '../../services/System';
|
||||
import { getWebln } from '../../utils/webln';
|
||||
import RobotAvatar from '../Robots/RobotAvatar';
|
||||
|
||||
@ -101,13 +101,13 @@ const ProfileDialog = ({
|
||||
const robotToken = getCookie('robot_token');
|
||||
|
||||
if (robotToken) {
|
||||
copyToClipboard(robotToken);
|
||||
systemClient.copyToClipboard(robotToken);
|
||||
setAppState({ copiedToken: true });
|
||||
}
|
||||
};
|
||||
|
||||
const copyReferralCodeHandler = () => {
|
||||
copyToClipboard(`http://${host}/ref/${referralCode}`);
|
||||
systemClient.copyToClipboard(`http://${host}/ref/${referralCode}`);
|
||||
};
|
||||
|
||||
const handleWeblnInvoiceClicked = async (e: any) => {
|
||||
|
@ -18,9 +18,9 @@ import ReconnectingWebSocket from 'reconnecting-websocket';
|
||||
import { encryptMessage, decryptMessage } from '../utils/pgp';
|
||||
import { getCookie } from '../utils/cookies';
|
||||
import { saveAsJson } from '../utils/saveFile';
|
||||
import { copyToClipboard } from '../utils/clipboard';
|
||||
import { AuditPGPDialog } from './Dialogs';
|
||||
import RobotAvatar from './Robots/RobotAvatar';
|
||||
import { systemClient } from '../services/System';
|
||||
|
||||
// Icons
|
||||
import CheckIcon from '@mui/icons-material/Check';
|
||||
@ -336,7 +336,7 @@ class Chat extends Component {
|
||||
<IconButton
|
||||
sx={{ height: 18, width: 18 }}
|
||||
onClick={() =>
|
||||
copyToClipboard(
|
||||
systemClient.copyToClipboard(
|
||||
this.state.showPGP[props.index]
|
||||
? props.message.encryptedMessage
|
||||
: props.message.plainTextMessage,
|
||||
|
10
frontend/src/components/Icons/Tor.tsx
Normal file
10
frontend/src/components/Icons/Tor.tsx
Normal file
@ -0,0 +1,10 @@
|
||||
import React, { Component } from 'react';
|
||||
import { SvgIcon } from '@mui/material';
|
||||
|
||||
export default function TorIcon(props) {
|
||||
return (
|
||||
<SvgIcon sx={props.sx} color={props.color} x='0px' y='0px' viewBox='0 0 180 180'>
|
||||
<path d='M90.1846205,163.631147 L90.1846205,152.721073 C124.743583,152.621278 152.726063,124.581416 152.726063,89.9975051 C152.726063,55.4160892 124.743583,27.3762266 90.1846205,27.2764318 L90.1846205,16.366358 C130.768698,16.4686478 163.633642,49.3909741 163.633642,89.9975051 C163.633642,130.606531 130.768698,163.531352 90.1846205,163.631147 Z M90.1846205,125.444642 C109.677053,125.342352 125.454621,109.517381 125.454621,89.9975051 C125.454621,70.4801242 109.677053,54.6551533 90.1846205,54.5528636 L90.1846205,43.6452847 C115.704663,43.7450796 136.364695,64.4550091 136.364695,89.9975051 C136.364695,115.542496 115.704663,136.252426 90.1846205,136.35222 L90.1846205,125.444642 Z M90.1846205,70.9167267 C100.640628,71.0165216 109.090758,79.5165493 109.090758,89.9975051 C109.090758,100.480956 100.640628,108.980984 90.1846205,109.080778 L90.1846205,70.9167267 Z M0,89.9975051 C0,139.705328 40.2921772,180 90,180 C139.705328,180 180,139.705328 180,89.9975051 C180,40.2921772 139.705328,0 90,0 C40.2921772,0 0,40.2921772 0,89.9975051 Z'></path>
|
||||
</SvgIcon>
|
||||
);
|
||||
}
|
@ -14,6 +14,7 @@ export { default as SellSatsIcon } from './SellSats';
|
||||
export { default as SendReceiveIcon } from './SendReceive';
|
||||
export { default as ExportIcon } from './Export';
|
||||
export { default as UserNinjaIcon } from './UserNinja';
|
||||
export { default as TorIcon } from './Tor';
|
||||
|
||||
// Some Flags missing on react-flags
|
||||
export { default as BasqueCountryFlag } from './BasqueCountryFlag';
|
||||
|
@ -45,7 +45,7 @@ import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
|
||||
|
||||
import { getCookie } from '../utils/cookies';
|
||||
import { pn } from '../utils/prettyNumbers';
|
||||
import { copyToClipboard } from '../utils/clipboard';
|
||||
import { systemClient } from '../services/System';
|
||||
|
||||
class MakerPage extends Component {
|
||||
defaultCurrency = 1;
|
||||
@ -924,7 +924,7 @@ class MakerPage extends Component {
|
||||
open={this.state.openStoreToken}
|
||||
onClose={() => this.setState({ openStoreToken: false })}
|
||||
onClickCopy={() =>
|
||||
copyToClipboard(getCookie('robot_token')) &
|
||||
systemClient.copyToClipboard(getCookie('robot_token')) &
|
||||
this.props.setAppState({ copiedToken: true })
|
||||
}
|
||||
copyIconColor={this.props.copiedToken ? 'inherit' : 'primary'}
|
||||
|
@ -52,7 +52,7 @@ import { SendReceiveIcon } from './Icons';
|
||||
|
||||
import { getCookie } from '../utils/cookies';
|
||||
import { pn } from '../utils/prettyNumbers';
|
||||
import { copyToClipboard } from '../utils/clipboard';
|
||||
import { systemClient } from '../services/System';
|
||||
import { getWebln } from '../utils/webln';
|
||||
import { apiClient } from '../services/api';
|
||||
import RobotAvatar from './Robots/RobotAvatar';
|
||||
@ -527,7 +527,8 @@ class OrderPage extends Component {
|
||||
open={this.state.openStoreToken}
|
||||
onClose={() => this.setState({ openStoreToken: false })}
|
||||
onClickCopy={() =>
|
||||
copyToClipboard(getCookie('robot_token')) & this.props.setAppState({ copiedToken: true })
|
||||
systemClient.copyToClipboard(getCookie('robot_token')) &
|
||||
this.props.setAppState({ copiedToken: true })
|
||||
}
|
||||
copyIconColor={this.props.copiedToken ? 'inherit' : 'primary'}
|
||||
onClickBack={() => this.setState({ openStoreToken: false })}
|
||||
|
80
frontend/src/components/TorConnection.tsx
Normal file
80
frontend/src/components/TorConnection.tsx
Normal file
@ -0,0 +1,80 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Box, CircularProgress, Tooltip } from '@mui/material';
|
||||
import { TorIcon } from './Icons';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const TorConnection = (): JSX.Element => {
|
||||
const [torStatus, setTorStatus] = useState<string>('NOTINIT');
|
||||
const { t } = useTranslation();
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener('torStatus', (event) => {
|
||||
setTorStatus(event?.detail);
|
||||
});
|
||||
}, []);
|
||||
|
||||
if (window?.NativeRobosats && (torStatus === 'NOTINIT' || torStatus === 'STARTING')) {
|
||||
return (
|
||||
<Box sx={{ display: 'inline-flex', position: 'fixed', left: '0.5em', top: '0.5em' }}>
|
||||
<Tooltip open={true} placement='right' title={t('Connecting to TOR network')}>
|
||||
<CircularProgress color='warning' thickness={6} size={23} />
|
||||
</Tooltip>
|
||||
<Box
|
||||
sx={{
|
||||
top: 0,
|
||||
left: 0,
|
||||
bottom: 0,
|
||||
right: 0,
|
||||
position: 'absolute',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
}}
|
||||
>
|
||||
<TorIcon color='warning' sx={{ width: 20, height: 20 }} />
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
} else if (window?.NativeRobosats && (torStatus === '"Done"' || torStatus === 'DONE')) {
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
position: 'fixed',
|
||||
left: '0.5em',
|
||||
top: '0.5em',
|
||||
}}
|
||||
>
|
||||
<Tooltip
|
||||
enterTouchDelay={0}
|
||||
enterDelay={1000}
|
||||
placement='right'
|
||||
title={t('Connected to TOR network')}
|
||||
>
|
||||
<TorIcon color='success' sx={{ width: 20, height: 20 }} />
|
||||
</Tooltip>
|
||||
</Box>
|
||||
);
|
||||
} else if (true) {
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
position: 'fixed',
|
||||
left: '0.5em',
|
||||
top: '0.5em',
|
||||
}}
|
||||
>
|
||||
<Tooltip open={true} placement='right' title={t('TOR connection error')}>
|
||||
<TorIcon color='error' sx={{ width: 20, height: 20 }} />
|
||||
</Tooltip>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default TorConnection;
|
@ -32,7 +32,7 @@ import Countdown, { zeroPad } from 'react-countdown';
|
||||
import Chat from './EncryptedChat';
|
||||
import TradeSummary from './TradeSummary';
|
||||
import MediaQuery from 'react-responsive';
|
||||
import { copyToClipboard } from '../utils/clipboard';
|
||||
import { systemClient } from '../services/System';
|
||||
import { apiClient } from '../services/api';
|
||||
|
||||
// Icons
|
||||
@ -286,7 +286,7 @@ class TradeBox extends Component {
|
||||
size='small'
|
||||
color='inherit'
|
||||
onClick={() => {
|
||||
copyToClipboard(this.props.data.bond_invoice);
|
||||
systemClient.copyToClipboard(this.props.data.bond_invoice);
|
||||
}}
|
||||
align='center'
|
||||
>
|
||||
@ -420,7 +420,7 @@ class TradeBox extends Component {
|
||||
size='small'
|
||||
color='inherit'
|
||||
onClick={() => {
|
||||
copyToClipboard(this.props.data.escrow_invoice);
|
||||
systemClient.copyToClipboard(this.props.data.escrow_invoice);
|
||||
}}
|
||||
align='center'
|
||||
>
|
||||
@ -1549,7 +1549,7 @@ class TradeBox extends Component {
|
||||
<IconButton
|
||||
color='inherit'
|
||||
onClick={() => {
|
||||
copyToClipboard(this.props.data.txid);
|
||||
systemClient.copyToClipboard(this.props.data.txid);
|
||||
}}
|
||||
>
|
||||
<ContentCopy sx={{ width: 16, height: 16 }} />
|
||||
|
@ -26,7 +26,7 @@ import { genBase62Token, tokenStrength } from '../utils/token';
|
||||
import { genKey } from '../utils/pgp';
|
||||
import { getCookie, writeCookie, deleteCookie } from '../utils/cookies';
|
||||
import { saveAsJson } from '../utils/saveFile';
|
||||
import { copyToClipboard } from '../utils/clipboard';
|
||||
import { systemClient } from '../services/System';
|
||||
import { apiClient } from '../services/api/index';
|
||||
import RobotAvatar from './Robots/RobotAvatar';
|
||||
|
||||
@ -321,7 +321,7 @@ class UserGenPage extends Component {
|
||||
!(getCookie('robot_token') === this.state.token))
|
||||
}
|
||||
onClick={() =>
|
||||
copyToClipboard(getCookie('robot_token')) &
|
||||
systemClient.copyToClipboard(getCookie('robot_token')) &
|
||||
this.props.setAppState({ copiedToken: true })
|
||||
}
|
||||
>
|
||||
|
9
frontend/src/services/Native/index.d.ts
vendored
9
frontend/src/services/Native/index.d.ts
vendored
@ -20,7 +20,14 @@ export interface NativeWebViewMessageHttp {
|
||||
body?: object;
|
||||
}
|
||||
|
||||
export declare type NativeWebViewMessage = NativeWebViewMessageHttp;
|
||||
export interface NativeWebViewMessageSystem {
|
||||
id?: number;
|
||||
category: 'system';
|
||||
type: 'torStatus' | 'copyToClipboardString';
|
||||
detail: string;
|
||||
}
|
||||
|
||||
export declare type NativeWebViewMessage = NativeWebViewMessageHttp | NativeWebViewMessageSystem;
|
||||
|
||||
export interface NativeRobosatsPromise {
|
||||
resolve: (value: object | PromiseLike<object>) => void;
|
||||
|
@ -1,10 +1,12 @@
|
||||
import { NativeRobosatsPromise, NativeWebViewMessage } from './index.d';
|
||||
import { NativeRobosatsPromise, NativeWebViewMessage, NativeWebViewMessageSystem } from './index.d';
|
||||
|
||||
class NativeRobosats {
|
||||
constructor() {
|
||||
this.messageCounter = 0;
|
||||
}
|
||||
|
||||
public torDaemonStatus = 'NOTINIT';
|
||||
|
||||
private messageCounter: number;
|
||||
|
||||
private pendingMessages: { [id: number]: NativeRobosatsPromise } = {};
|
||||
@ -29,6 +31,13 @@ class NativeRobosats {
|
||||
}
|
||||
};
|
||||
|
||||
public onMessage: (message: NativeWebViewMessageSystem) => void = (message) => {
|
||||
if (message.type === 'torStatus') {
|
||||
this.torDaemonStatus = message.detail;
|
||||
window.dispatchEvent(new CustomEvent('torStatus', { detail: this.torDaemonStatus }));
|
||||
}
|
||||
};
|
||||
|
||||
public postMessage: (message: NativeWebViewMessage) => Promise<{ [key: string]: any }> = async (
|
||||
message,
|
||||
) => {
|
||||
|
20
frontend/src/services/System/SystemNativeClient/index.ts
Normal file
20
frontend/src/services/System/SystemNativeClient/index.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import { SystemClient } from '..';
|
||||
import NativeRobosats from '../../Native';
|
||||
|
||||
class SystemNativeClient implements SystemClient {
|
||||
constructor() {
|
||||
if (!window.NativeRobosats) {
|
||||
window.NativeRobosats = new NativeRobosats();
|
||||
}
|
||||
}
|
||||
|
||||
public copyToClipboard: (value: string) => void = (value) => {
|
||||
return window.NativeRobosats?.postMessage({
|
||||
category: 'system',
|
||||
type: 'copyToClipboardString',
|
||||
detail: value,
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export default SystemNativeClient;
|
29
frontend/src/services/System/SystemWebClient/index.ts
Normal file
29
frontend/src/services/System/SystemWebClient/index.ts
Normal file
@ -0,0 +1,29 @@
|
||||
import { SystemClient } from '..';
|
||||
|
||||
class SystemWebClient implements SystemClient {
|
||||
public copyToClipboard: (value: string) => void = (value) => {
|
||||
// navigator clipboard api needs a secure context (https)
|
||||
// this function attempts to copy also on http contexts
|
||||
// useful on the http i2p site and on torified browsers
|
||||
if (navigator.clipboard && window.isSecureContext) {
|
||||
// navigator clipboard api method'
|
||||
navigator.clipboard.writeText(value);
|
||||
} else {
|
||||
// text area method
|
||||
const textArea = document.createElement('textarea');
|
||||
textArea.value = value;
|
||||
// make the textarea out of viewport
|
||||
textArea.style.position = 'fixed';
|
||||
textArea.style.left = '-999999px';
|
||||
textArea.style.top = '-999999px';
|
||||
document.body.appendChild(textArea);
|
||||
textArea.focus();
|
||||
textArea.select();
|
||||
// here the magic happens
|
||||
document.execCommand('copy');
|
||||
textArea.remove();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default SystemWebClient;
|
9
frontend/src/services/System/index.ts
Normal file
9
frontend/src/services/System/index.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import SystemNativeClient from './SystemNativeClient';
|
||||
import SystemWebClient from './SystemWebClient';
|
||||
|
||||
export interface SystemClient {
|
||||
copyToClipboard: (value: string) => void;
|
||||
}
|
||||
|
||||
export const systemClient: SystemClient =
|
||||
window.ReactNativeWebView != null ? new SystemNativeClient() : new SystemWebClient();
|
@ -4,8 +4,10 @@ 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> } = {};
|
||||
|
@ -1,25 +0,0 @@
|
||||
export function copyToClipboard(textToCopy) {
|
||||
// navigator clipboard api needs a secure context (https)
|
||||
// this function attempts to copy also on http contexts
|
||||
// useful on the http i2p site and on torified browsers
|
||||
if (navigator.clipboard && window.isSecureContext) {
|
||||
// navigator clipboard api method'
|
||||
return navigator.clipboard.writeText(textToCopy);
|
||||
} else {
|
||||
// text area method
|
||||
const textArea = document.createElement('textarea');
|
||||
textArea.value = textToCopy;
|
||||
// make the textarea out of viewport
|
||||
textArea.style.position = 'fixed';
|
||||
textArea.style.left = '-999999px';
|
||||
textArea.style.top = '-999999px';
|
||||
document.body.appendChild(textArea);
|
||||
textArea.focus();
|
||||
textArea.select();
|
||||
return new Promise((res, rej) => {
|
||||
// here the magic happens
|
||||
document.execCommand('copy') ? res() : rej();
|
||||
textArea.remove();
|
||||
});
|
||||
}
|
||||
}
|
@ -7,6 +7,10 @@
|
||||
"You are self-hosting RoboSats": "You are self-hosting RoboSats",
|
||||
"RoboSats client is served from your own node granting you the strongest security and privacy.": "RoboSats client is served from your own node granting you the strongest security and privacy.",
|
||||
|
||||
"Connected to TOR network": "Connected to TOR network",
|
||||
"TOR connection error": "TOR connection error",
|
||||
"Connecting to TOR network": "Connecting to TOR network",
|
||||
|
||||
"USER GENERATION PAGE - UserGenPage.js": "Landing Page and User Generation",
|
||||
"Simple and Private LN P2P Exchange": "Simple and Private LN P2P Exchange",
|
||||
"This is your trading avatar": "This is your trading avatar",
|
||||
|
@ -1,43 +1,85 @@
|
||||
import React, { useRef } from 'react';
|
||||
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 Clipboard from '@react-native-clipboard/clipboard';
|
||||
import NetInfo from '@react-native-community/netinfo';
|
||||
|
||||
const App = () => {
|
||||
const webViewRef = useRef<WebView>();
|
||||
const uri = (Platform.OS === 'android' ? 'file:///android_asset/' : '') + 'Web.bundle/index.html';
|
||||
|
||||
const injectMessage = (id: string, data: object) => {
|
||||
const injectMessageResolve = (id: string, data: object) => {
|
||||
const json = JSON.stringify(data);
|
||||
webViewRef.current?.injectJavaScript(
|
||||
`(function() {window.NativeRobosats.onMessageResolve(${id}, ${json});})();`,
|
||||
);
|
||||
};
|
||||
|
||||
const injectMessage = (message: object) => {
|
||||
const json = JSON.stringify(message);
|
||||
webViewRef.current?.injectJavaScript(
|
||||
`(function() {window.NativeRobosats?.onMessage(${json});})();`,
|
||||
);
|
||||
};
|
||||
|
||||
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).then((response: object) => {
|
||||
injectMessage(data.id, response);
|
||||
});
|
||||
torClient
|
||||
.get(data.path)
|
||||
.then((response: object) => {
|
||||
injectMessageResolve(data.id, response);
|
||||
})
|
||||
.finally(sendTorStatus);
|
||||
} else if (data.type === 'post') {
|
||||
torClient.post(data.path, data.body, data.headers).then((response: object) => {
|
||||
injectMessage(data.id, response);
|
||||
});
|
||||
torClient
|
||||
.post(data.path, data.body, data.headers)
|
||||
.then((response: object) => {
|
||||
injectMessageResolve(data.id, response);
|
||||
})
|
||||
.finally(sendTorStatus);
|
||||
} else if (data.type === 'delete') {
|
||||
torClient.delete(data.path, data.headers).then((response: object) => {
|
||||
injectMessage(data.id, response);
|
||||
});
|
||||
torClient
|
||||
.delete(data.path, data.headers)
|
||||
.then((response: object) => {
|
||||
injectMessageResolve(data.id, response);
|
||||
})
|
||||
.finally(sendTorStatus);
|
||||
} else if (data.type === 'xhr') {
|
||||
torClient.request(data.path).then((response: object) => {
|
||||
injectMessage(data.id, response);
|
||||
});
|
||||
torClient
|
||||
.request(data.path)
|
||||
.then((response: object) => {
|
||||
injectMessageResolve(data.id, response);
|
||||
})
|
||||
.finally(sendTorStatus);
|
||||
}
|
||||
} else if (data.category === 'system') {
|
||||
if (data.type === 'copyToClipboardString') {
|
||||
Clipboard.setString(data.detail);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
torClient.startDaemon();
|
||||
const sendTorStatus = async () => {
|
||||
NetInfo.fetch().then(async (state) => {
|
||||
let daemonStatus = 'ERROR';
|
||||
if (state.isInternetReachable) {
|
||||
try {
|
||||
daemonStatus = await torClient.daemon.getDaemonStatus();
|
||||
} catch {}
|
||||
}
|
||||
|
||||
injectMessage({
|
||||
category: 'system',
|
||||
type: 'torStatus',
|
||||
detail: daemonStatus,
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<SafeAreaView style={{ flex: 1 }}>
|
||||
|
31
mobile/package-lock.json
generated
31
mobile/package-lock.json
generated
@ -8,6 +8,8 @@
|
||||
"name": "robosats",
|
||||
"version": "0.2.0",
|
||||
"dependencies": {
|
||||
"@react-native-clipboard/clipboard": "^1.11.1",
|
||||
"@react-native-community/netinfo": "^9.3.4",
|
||||
"react": "^18.0.0",
|
||||
"react-native": "^0.69.6",
|
||||
"react-native-tor": "^0.1.8",
|
||||
@ -2808,6 +2810,15 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/@react-native-clipboard/clipboard": {
|
||||
"version": "1.11.1",
|
||||
"resolved": "https://registry.npmjs.org/@react-native-clipboard/clipboard/-/clipboard-1.11.1.tgz",
|
||||
"integrity": "sha512-nvSIIHzybVWqYxcJE5hpT17ekxAAg383Ggzw5WrYHtkKX61N1AwaKSNmXs5xHV7pmKSOe/yWjtSwxIzfW51I5Q==",
|
||||
"peerDependencies": {
|
||||
"react": ">=16.0",
|
||||
"react-native": ">=0.57.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@react-native-community/cli": {
|
||||
"version": "8.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@react-native-community/cli/-/cli-8.0.6.tgz",
|
||||
@ -4348,6 +4359,14 @@
|
||||
"integrity": "sha512-o6aam+0Ug1xGK3ABYmBm0B1YuEKfM/5kaoZO0eHbZwSpw9UzDX4G5y4Nx/K20FHqUmJHkZmLvOUFYwN4N+HqKA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@react-native-community/netinfo": {
|
||||
"version": "9.3.4",
|
||||
"resolved": "https://registry.npmjs.org/@react-native-community/netinfo/-/netinfo-9.3.4.tgz",
|
||||
"integrity": "sha512-IXbJ+L8p4oE2ssDPfXCyxx9xVo5WuTMv6HA5YJw2McuRLLtVKR/vambycrB47AWTkHCTj3e0VOz28iUOvTSVPw==",
|
||||
"peerDependencies": {
|
||||
"react-native": ">=0.59"
|
||||
}
|
||||
},
|
||||
"node_modules/@react-native/assets": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@react-native/assets/-/assets-1.0.0.tgz",
|
||||
@ -17949,6 +17968,12 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"@react-native-clipboard/clipboard": {
|
||||
"version": "1.11.1",
|
||||
"resolved": "https://registry.npmjs.org/@react-native-clipboard/clipboard/-/clipboard-1.11.1.tgz",
|
||||
"integrity": "sha512-nvSIIHzybVWqYxcJE5hpT17ekxAAg383Ggzw5WrYHtkKX61N1AwaKSNmXs5xHV7pmKSOe/yWjtSwxIzfW51I5Q==",
|
||||
"requires": {}
|
||||
},
|
||||
"@react-native-community/cli": {
|
||||
"version": "8.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@react-native-community/cli/-/cli-8.0.6.tgz",
|
||||
@ -19068,6 +19093,12 @@
|
||||
"integrity": "sha512-o6aam+0Ug1xGK3ABYmBm0B1YuEKfM/5kaoZO0eHbZwSpw9UzDX4G5y4Nx/K20FHqUmJHkZmLvOUFYwN4N+HqKA==",
|
||||
"dev": true
|
||||
},
|
||||
"@react-native-community/netinfo": {
|
||||
"version": "9.3.4",
|
||||
"resolved": "https://registry.npmjs.org/@react-native-community/netinfo/-/netinfo-9.3.4.tgz",
|
||||
"integrity": "sha512-IXbJ+L8p4oE2ssDPfXCyxx9xVo5WuTMv6HA5YJw2McuRLLtVKR/vambycrB47AWTkHCTj3e0VOz28iUOvTSVPw==",
|
||||
"requires": {}
|
||||
},
|
||||
"@react-native/assets": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@react-native/assets/-/assets-1.0.0.tgz",
|
||||
|
@ -12,6 +12,8 @@
|
||||
"format": "prettier --write '**/**/*.{js,jsx,ts,tsx,css,md,json}' --config ./.prettierrc"
|
||||
},
|
||||
"dependencies": {
|
||||
"@react-native-clipboard/clipboard": "^1.11.1",
|
||||
"@react-native-community/netinfo": "^9.3.4",
|
||||
"react": "^18.0.0",
|
||||
"react-native": "^0.69.6",
|
||||
"react-native-tor": "^0.1.8",
|
||||
@ -39,9 +41,9 @@
|
||||
"eslint-plugin-promise": "^6.0.1",
|
||||
"eslint-plugin-react": "^7.31.1",
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"prettier": "^2.7.1",
|
||||
"jest": "^26.6.3",
|
||||
"metro-react-native-babel-preset": "^0.70.3",
|
||||
"prettier": "^2.7.1",
|
||||
"react-test-renderer": "18.0.0",
|
||||
"typescript": "^4.4.4"
|
||||
},
|
||||
|
@ -12,12 +12,16 @@ class TorClient {
|
||||
});
|
||||
}
|
||||
|
||||
public startDaemon = async () => {
|
||||
await this.daemon.startIfNotStarted();
|
||||
private connectDaemon: () => void = async () => {
|
||||
try {
|
||||
this.daemon.startIfNotStarted();
|
||||
} catch {
|
||||
console.log('TOR already started');
|
||||
}
|
||||
};
|
||||
|
||||
public get: (path: string) => Promise<object> = async (path) => {
|
||||
await this.startDaemon();
|
||||
await this.connectDaemon();
|
||||
|
||||
return await new Promise<object>(async (resolve, reject) => {
|
||||
try {
|
||||
@ -31,7 +35,7 @@ class TorClient {
|
||||
};
|
||||
|
||||
public delete: (path: string, headers: object) => Promise<object> = async (path, headers) => {
|
||||
await this.startDaemon();
|
||||
await this.connectDaemon();
|
||||
|
||||
return await new Promise<object>(async (resolve, reject) => {
|
||||
try {
|
||||
@ -45,7 +49,7 @@ class TorClient {
|
||||
};
|
||||
|
||||
public request: (path: string) => Promise<object> = async (path) => {
|
||||
await this.startDaemon();
|
||||
await this.connectDaemon();
|
||||
|
||||
return await new Promise<object>(async (resolve, reject) => {
|
||||
try {
|
||||
@ -67,7 +71,7 @@ class TorClient {
|
||||
body,
|
||||
headers,
|
||||
) => {
|
||||
await this.startDaemon();
|
||||
await this.connectDaemon();
|
||||
|
||||
return await new Promise<object>(async (resolve, reject) => {
|
||||
try {
|
||||
|
Loading…
Reference in New Issue
Block a user