mirror of
https://github.com/apotdevin/thunderhub.git
synced 2024-11-19 09:50:03 +01:00
chore: 🔧 remove qr login
This commit is contained in:
parent
d6f9e51ed0
commit
47ee9c0127
37
package-lock.json
generated
37
package-lock.json
generated
@ -16465,11 +16465,6 @@
|
||||
"verror": "1.10.0"
|
||||
}
|
||||
},
|
||||
"jsqr": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/jsqr/-/jsqr-1.3.1.tgz",
|
||||
"integrity": "sha512-zCTP6Qd/WwjrpuHFkJuXc5opRdKprUr7eI7+JCCtcetThJt45qptu82MWQ+eET+FtDrMo7+BYjo3iD0XIq1L9Q=="
|
||||
},
|
||||
"jsx-ast-utils": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-2.3.0.tgz",
|
||||
@ -20339,16 +20334,6 @@
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
|
||||
},
|
||||
"react-qr-reader": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/react-qr-reader/-/react-qr-reader-2.2.1.tgz",
|
||||
"integrity": "sha512-EL5JEj53u2yAOgtpAKAVBzD/SiKWn0Bl7AZy6ZrSf1lub7xHwtaXe6XSx36Wbhl1VMGmvmrwYMRwO1aSCT2fwA==",
|
||||
"requires": {
|
||||
"jsqr": "^1.2.0",
|
||||
"prop-types": "^15.7.2",
|
||||
"webrtc-adapter": "^7.2.1"
|
||||
}
|
||||
},
|
||||
"react-refresh": {
|
||||
"version": "0.8.3",
|
||||
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.8.3.tgz",
|
||||
@ -21179,14 +21164,6 @@
|
||||
"integrity": "sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA==",
|
||||
"dev": true
|
||||
},
|
||||
"rtcpeerconnection-shim": {
|
||||
"version": "1.2.15",
|
||||
"resolved": "https://registry.npmjs.org/rtcpeerconnection-shim/-/rtcpeerconnection-shim-1.2.15.tgz",
|
||||
"integrity": "sha512-C6DxhXt7bssQ1nHb154lqeL0SXz5Dx4RczXZu2Aa/L1NJFnEVDxFwCBo3fqtuljhHIGceg5JKBV4XJ0gW5JKyw==",
|
||||
"requires": {
|
||||
"sdp": "^2.6.0"
|
||||
}
|
||||
},
|
||||
"run-async": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz",
|
||||
@ -21326,11 +21303,6 @@
|
||||
"integrity": "sha512-MuCAyrGZcTLfQoH2XoBlQ8C6bzwN88XT/0slOGz0pn8+gIP85BOAfYa44ZXQUTOwRwPU0QvgU+V+OSajl/59Xg==",
|
||||
"dev": true
|
||||
},
|
||||
"sdp": {
|
||||
"version": "2.12.0",
|
||||
"resolved": "https://registry.npmjs.org/sdp/-/sdp-2.12.0.tgz",
|
||||
"integrity": "sha512-jhXqQAQVM+8Xj5EjJGVweuEzgtGWb3tmEEpl3CLP3cStInSbVHSg0QWOGQzNq8pSID4JkpeV2mPqlMDLrm0/Vw=="
|
||||
},
|
||||
"secp256k1": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.1.tgz",
|
||||
@ -24177,15 +24149,6 @@
|
||||
"source-map": "~0.6.1"
|
||||
}
|
||||
},
|
||||
"webrtc-adapter": {
|
||||
"version": "7.6.1",
|
||||
"resolved": "https://registry.npmjs.org/webrtc-adapter/-/webrtc-adapter-7.6.1.tgz",
|
||||
"integrity": "sha512-orgybuYN6971dRWL/fdvo36Ro8zUvfXovEoaTXuKIuGySOZRCqmtSJ4oEYuNpi4C6NzkJrF1Nwf+N1VyOttkcg==",
|
||||
"requires": {
|
||||
"rtcpeerconnection-shim": "^1.2.15",
|
||||
"sdp": "^2.12.0"
|
||||
}
|
||||
},
|
||||
"websocket": {
|
||||
"version": "1.0.31",
|
||||
"resolved": "https://registry.npmjs.org/websocket/-/websocket-1.0.31.tgz",
|
||||
|
@ -70,7 +70,6 @@
|
||||
"react-dom": "^16.13.1",
|
||||
"react-feather": "^2.0.8",
|
||||
"react-intersection-observer": "^8.26.2",
|
||||
"react-qr-reader": "^2.2.1",
|
||||
"react-spinners": "^0.8.3",
|
||||
"react-spring": "^8.0.27",
|
||||
"react-toastify": "^6.0.5",
|
||||
|
@ -9,6 +9,7 @@ import { GridWrapper } from 'src/components/gridWrapper/GridWrapper';
|
||||
import { withApollo } from 'config/client';
|
||||
import styled from 'styled-components';
|
||||
import { useStatusState } from 'src/context/StatusContext';
|
||||
import { ChannelFeeType } from 'src/graphql/types';
|
||||
import {
|
||||
Card,
|
||||
CardWithTitle,
|
||||
@ -159,7 +160,7 @@ const FeesView = () => {
|
||||
<CardWithTitle>
|
||||
<SubTitle>Channel Details</SubTitle>
|
||||
<Card mobileCardPadding={'0'} mobileNoBackground={true}>
|
||||
{data.getChannelFees.map((channel, index: number) => (
|
||||
{data.getChannelFees.map((channel: ChannelFeeType, index: number) => (
|
||||
<FeeCard
|
||||
channel={channel}
|
||||
index={index + 1}
|
||||
|
@ -7,7 +7,6 @@ import { InterfaceSettings } from '../src/views/settings/Interface';
|
||||
import { AccountSettings } from '../src/views/settings/Account';
|
||||
import { DangerView } from '../src/views/settings/Danger';
|
||||
import { CurrentSettings } from '../src/views/settings/Current';
|
||||
import { SyncSettings } from '../src/views/settings/Sync';
|
||||
import { ChatSettings } from '../src/views/settings/Chat';
|
||||
import { PrivacySettings } from '../src/views/settings/Privacy';
|
||||
|
||||
@ -26,7 +25,6 @@ const SettingsView = () => {
|
||||
<InterfaceSettings />
|
||||
<PrivacySettings />
|
||||
<ChatSettings />
|
||||
<SyncSettings />
|
||||
<CurrentSettings />
|
||||
<AccountSettings />
|
||||
<DangerView />
|
||||
|
@ -24,13 +24,6 @@ const PasswordInput = dynamic(() => import('./views/Password'), {
|
||||
},
|
||||
});
|
||||
|
||||
const QRLogin = dynamic(() => import('./views/QRLogin'), {
|
||||
ssr: false,
|
||||
loading: function Loading() {
|
||||
return <LoadingCard noCard={true} />;
|
||||
},
|
||||
});
|
||||
|
||||
type AuthProps = {
|
||||
type: string;
|
||||
status: string;
|
||||
@ -55,41 +48,16 @@ export const Auth = ({ type, status, callback, setStatus }: AuthProps) => {
|
||||
|
||||
const [adminChecked, setAdminChecked] = useState(false);
|
||||
|
||||
const quickSave = ({
|
||||
name = 'Unknown',
|
||||
host,
|
||||
admin,
|
||||
viewOnly,
|
||||
cert,
|
||||
}: {
|
||||
name?: string;
|
||||
host?: string;
|
||||
admin?: string;
|
||||
viewOnly?: string;
|
||||
cert?: string;
|
||||
}) => {
|
||||
dispatch({ type: 'disconnected' });
|
||||
dispatchChat({ type: 'disconnected' });
|
||||
dispatchAccount({
|
||||
type: 'addAccountAndSave',
|
||||
accountToAdd: { name, host, admin, viewOnly, cert },
|
||||
});
|
||||
|
||||
push(appendBasePath('/'));
|
||||
};
|
||||
|
||||
const handleSet = ({
|
||||
host,
|
||||
admin,
|
||||
viewOnly,
|
||||
cert,
|
||||
skipCheck,
|
||||
}: {
|
||||
host?: string;
|
||||
admin?: string;
|
||||
viewOnly?: string;
|
||||
cert?: string;
|
||||
skipCheck?: boolean;
|
||||
}) => {
|
||||
const id = getAccountId(
|
||||
host ?? '',
|
||||
@ -108,8 +76,6 @@ export const Auth = ({ type, status, callback, setStatus }: AuthProps) => {
|
||||
toast.error('A host url is needed to connect.');
|
||||
} else if (!admin && !viewOnly) {
|
||||
toast.error('View-Only or Admin macaroon are needed to connect.');
|
||||
} else if (skipCheck) {
|
||||
quickSave({ name, cert, admin, viewOnly, host });
|
||||
} else {
|
||||
host && setHost(host);
|
||||
admin && setAdmin(admin);
|
||||
@ -164,8 +130,6 @@ export const Auth = ({ type, status, callback, setStatus }: AuthProps) => {
|
||||
switch (type) {
|
||||
case 'login':
|
||||
return <LoginForm handleSet={handleSet} />;
|
||||
case 'qrcode':
|
||||
return <QRLogin handleSet={handleSet} />;
|
||||
case 'connect':
|
||||
return <ConnectLoginForm handleSet={handleSet} />;
|
||||
default:
|
||||
|
@ -1,154 +0,0 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import QrReader from 'react-qr-reader';
|
||||
import { toast } from 'react-toastify';
|
||||
import sortBy from 'lodash.sortby';
|
||||
import Modal from '../../modal/ReactModal';
|
||||
import { getQRConfig } from '../../../utils/auth';
|
||||
import { Line, QRTextWrapper } from '../Auth.styled';
|
||||
import { LoadingBar } from '../../loadingBar/LoadingBar';
|
||||
import { SubTitle } from '../../generic/Styled';
|
||||
import { ColorButton } from '../../buttons/colorButton/ColorButton';
|
||||
|
||||
type QRLoginProps = {
|
||||
handleSet: ({
|
||||
name,
|
||||
host,
|
||||
admin,
|
||||
viewOnly,
|
||||
cert,
|
||||
skipCheck,
|
||||
}: {
|
||||
name?: string;
|
||||
host?: string;
|
||||
admin?: string;
|
||||
viewOnly?: string;
|
||||
cert?: string;
|
||||
skipCheck?: boolean;
|
||||
}) => void;
|
||||
};
|
||||
|
||||
const QRLogin = ({ handleSet }: QRLoginProps) => {
|
||||
const [qrData, setQrData] = useState<any>([]);
|
||||
const [modalOpen, setModalOpen] = useState(true);
|
||||
const [modalClosed, setModalClosed] = useState('none');
|
||||
|
||||
const [total, setTotal] = useState(0);
|
||||
const [missing, setMissing] = useState<number[]>();
|
||||
|
||||
useEffect(() => {
|
||||
if (qrData.length >= total && total !== 0) {
|
||||
setModalOpen(false);
|
||||
|
||||
const sorted = sortBy(qrData, 'index');
|
||||
const strings = sorted.map((code: { auth: string }) => code.auth);
|
||||
const completeString = strings.join('');
|
||||
|
||||
try {
|
||||
const { name, cert, admin, viewOnly, host } = getQRConfig(
|
||||
completeString
|
||||
);
|
||||
|
||||
handleSet({
|
||||
name,
|
||||
host,
|
||||
admin,
|
||||
viewOnly,
|
||||
cert,
|
||||
skipCheck: true,
|
||||
});
|
||||
} catch (error) {
|
||||
toast.error('Error reading QR codes.');
|
||||
}
|
||||
}
|
||||
}, [qrData, handleSet, total]);
|
||||
|
||||
const handleScan = (data: string | null) => {
|
||||
if (data) {
|
||||
try {
|
||||
const parsed = JSON.parse(data);
|
||||
!total && setTotal(parsed.total);
|
||||
!missing && setMissing([...Array(parsed.total).keys()]);
|
||||
|
||||
if (missing && missing.length >= 0 && missing.includes(parsed.index)) {
|
||||
const remaining = missing.filter((value: number) => {
|
||||
const currentNumber = Number(parsed.index);
|
||||
return value !== currentNumber;
|
||||
});
|
||||
const data = [...qrData, parsed];
|
||||
setQrData(data);
|
||||
setMissing(remaining);
|
||||
}
|
||||
} catch (error) {
|
||||
setModalOpen(false);
|
||||
toast.error('Error reading QR codes.');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleError = () => {
|
||||
setModalOpen(false);
|
||||
setModalClosed('error');
|
||||
};
|
||||
|
||||
const handleClose = () => {
|
||||
setModalClosed('forced');
|
||||
setModalOpen(false);
|
||||
setMissing(undefined);
|
||||
setTotal(0);
|
||||
setQrData([]);
|
||||
};
|
||||
|
||||
const renderInfo = () => {
|
||||
switch (modalClosed) {
|
||||
case 'forced':
|
||||
return (
|
||||
<>
|
||||
<QRTextWrapper>
|
||||
<SubTitle>No information read from QR Codes.</SubTitle>
|
||||
</QRTextWrapper>
|
||||
<ColorButton
|
||||
fullWidth={true}
|
||||
onClick={() => {
|
||||
setModalClosed('none');
|
||||
setModalOpen(true);
|
||||
}}
|
||||
>
|
||||
Try Again
|
||||
</ColorButton>
|
||||
</>
|
||||
);
|
||||
case 'error':
|
||||
return (
|
||||
<QRTextWrapper>
|
||||
<SubTitle>
|
||||
Make sure you have a camara available and that you have given
|
||||
ThunderHub the correct permissions to use it.
|
||||
</SubTitle>
|
||||
</QRTextWrapper>
|
||||
);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{renderInfo()}
|
||||
<Modal isOpen={modalOpen} closeCallback={handleClose}>
|
||||
<Line>
|
||||
<LoadingBar
|
||||
percent={missing ? 100 * ((total - missing.length) / total) : 0}
|
||||
/>
|
||||
</Line>
|
||||
<QrReader
|
||||
delay={500}
|
||||
onError={handleError}
|
||||
onScan={handleScan}
|
||||
style={{ width: '100%' }}
|
||||
/>
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default QRLogin;
|
@ -44,7 +44,7 @@ export const Channels: React.FC = () => {
|
||||
|
||||
const { capacity, channel_count } = partner_node_info?.node || {};
|
||||
const { base_fee_mtokens, fee_rate } =
|
||||
partner_fee_info?.channel?.policies?.[0] || {};
|
||||
partner_fee_info?.channel?.partner_node_policies || {};
|
||||
|
||||
const partner = Number(capacity) || 0;
|
||||
const channels = Number(channel_count) || 0;
|
||||
|
@ -70,11 +70,13 @@ export const ForwardCard = ({
|
||||
<ColumnLine>
|
||||
{renderLine(
|
||||
'Incoming:',
|
||||
incoming_channel_info?.channel?.policies?.[0]?.node?.node?.alias
|
||||
incoming_channel_info?.channel?.partner_node_policies?.node
|
||||
?.node?.alias
|
||||
)}
|
||||
{renderLine(
|
||||
'Outgoing:',
|
||||
outgoing_channel_info?.channel?.policies?.[0]?.node?.node?.alias
|
||||
outgoing_channel_info?.channel?.partner_node_policies?.node
|
||||
?.node?.alias
|
||||
)}
|
||||
</ColumnLine>
|
||||
</ResponsiveSingle>
|
||||
|
@ -83,15 +83,6 @@ export const LoginBox = () => {
|
||||
>
|
||||
BTCPayServer
|
||||
</SingleButton>
|
||||
<SingleButton
|
||||
selected={isType === 'qrcode'}
|
||||
onClick={() => {
|
||||
setHelp(false);
|
||||
setIsType('qrcode');
|
||||
}}
|
||||
>
|
||||
QR Code
|
||||
</SingleButton>
|
||||
</MultiButton>
|
||||
</>
|
||||
);
|
||||
|
@ -75,12 +75,6 @@ export const AccountSettings = () => {
|
||||
>
|
||||
BTCPayServer Info
|
||||
</SingleButton>
|
||||
<SingleButton
|
||||
selected={isType === 'qrcode'}
|
||||
onClick={() => setIsType('qrcode')}
|
||||
>
|
||||
QR Code
|
||||
</SingleButton>
|
||||
</MultiButton>
|
||||
</SingleLine>
|
||||
);
|
||||
|
@ -1,178 +0,0 @@
|
||||
import React, { useState } from 'react';
|
||||
import { X } from 'react-feather';
|
||||
import QRCode from 'qrcode.react';
|
||||
import styled from 'styled-components';
|
||||
import { useAccountState, CLIENT_ACCOUNT } from 'src/context/AccountContext';
|
||||
import {
|
||||
CardWithTitle,
|
||||
SubTitle,
|
||||
Card,
|
||||
Sub4Title,
|
||||
Separation,
|
||||
} from '../../components/generic/Styled';
|
||||
import { SettingsLine } from '../../../pages/settings';
|
||||
import {
|
||||
MultiButton,
|
||||
SingleButton,
|
||||
} from '../../components/buttons/multiButton/MultiButton';
|
||||
import { ColorButton } from '../../components/buttons/colorButton/ColorButton';
|
||||
import { useInterval } from '../../hooks/UseInterval';
|
||||
import Modal from '../../components/modal/ReactModal';
|
||||
import { themeColors } from '../../styles/Themes';
|
||||
|
||||
const QRWrapper = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
export const SyncSettings = () => {
|
||||
const { account } = useAccountState();
|
||||
|
||||
const getValue = () => {
|
||||
switch (true) {
|
||||
case account?.type === CLIENT_ACCOUNT && !!account.viewOnly:
|
||||
return 'viewOnly';
|
||||
default:
|
||||
return 'adminOnly';
|
||||
}
|
||||
};
|
||||
|
||||
const [state, setState] = useState('none');
|
||||
const [type, setType] = useState(getValue());
|
||||
|
||||
if (!account || account.type !== CLIENT_ACCOUNT) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { viewOnly, admin, host, cert, name } = account;
|
||||
|
||||
const getObject = () => {
|
||||
switch (type) {
|
||||
case 'complete':
|
||||
return { viewOnly, admin };
|
||||
case 'adminOnly':
|
||||
return { admin };
|
||||
default:
|
||||
return { viewOnly };
|
||||
}
|
||||
};
|
||||
|
||||
const renderSettings = () => (
|
||||
<>
|
||||
<Separation />
|
||||
<SettingsLine>
|
||||
<Sub4Title>Sync Type</Sub4Title>
|
||||
<MultiButton>
|
||||
{viewOnly && (
|
||||
<SingleButton
|
||||
selected={type === 'viewOnly'}
|
||||
onClick={() => setType('viewOnly')}
|
||||
>
|
||||
View-Only
|
||||
</SingleButton>
|
||||
)}
|
||||
{admin && (
|
||||
<SingleButton
|
||||
selected={type === 'adminOnly'}
|
||||
onClick={() => setType('adminOnly')}
|
||||
>
|
||||
Admin-Only
|
||||
</SingleButton>
|
||||
)}
|
||||
{viewOnly && admin && (
|
||||
<SingleButton
|
||||
selected={type === 'complete'}
|
||||
onClick={() => setType('complete')}
|
||||
>
|
||||
Admin and View
|
||||
</SingleButton>
|
||||
)}
|
||||
</MultiButton>
|
||||
</SettingsLine>
|
||||
<SettingsLine>
|
||||
<ColorButton
|
||||
withMargin={'16px 0 0'}
|
||||
fullWidth={true}
|
||||
onClick={() => setState('finish')}
|
||||
>
|
||||
Generate QR
|
||||
</ColorButton>
|
||||
</SettingsLine>
|
||||
</>
|
||||
);
|
||||
|
||||
const renderQRCode = () => {
|
||||
const connection = JSON.stringify({
|
||||
name,
|
||||
host,
|
||||
cert,
|
||||
...getObject(),
|
||||
});
|
||||
|
||||
return (
|
||||
<Modal
|
||||
isOpen={true}
|
||||
noMinWidth={true}
|
||||
closeCallback={() => setState('none')}
|
||||
>
|
||||
<QRWrapper>
|
||||
<SubTitle subtitleColor={themeColors.black}>
|
||||
Scan with ThunderHub
|
||||
</SubTitle>
|
||||
<QRLoop connection={connection} />
|
||||
</QRWrapper>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<CardWithTitle>
|
||||
<SubTitle>Sync</SubTitle>
|
||||
<Card>
|
||||
<SettingsLine>
|
||||
<Sub4Title>Sync account to another device</Sub4Title>
|
||||
<ColorButton
|
||||
onClick={() =>
|
||||
setState((prev: string) =>
|
||||
prev !== 'none' ? 'none' : 'generate'
|
||||
)
|
||||
}
|
||||
>
|
||||
{state !== 'none' ? <X size={18} /> : 'Sync'}
|
||||
</ColorButton>
|
||||
</SettingsLine>
|
||||
{state === 'generate' && renderSettings()}
|
||||
{state === 'finish' && renderQRCode()}
|
||||
</Card>
|
||||
</CardWithTitle>
|
||||
);
|
||||
};
|
||||
|
||||
const QRLoop = ({ connection }: { connection: string }) => {
|
||||
const textArray = connection.match(/.{1,100}/g) ?? [];
|
||||
const length = textArray.length;
|
||||
|
||||
const objectArray = textArray.map((value: string, index: number) =>
|
||||
JSON.stringify({
|
||||
index,
|
||||
total: length,
|
||||
auth: value,
|
||||
})
|
||||
);
|
||||
|
||||
const [count, setCount] = useState(0);
|
||||
|
||||
useInterval(() => {
|
||||
setCount((prev: number) => {
|
||||
if (prev < length - 1) {
|
||||
return prev + 1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
}, 1000);
|
||||
|
||||
return <QRCode value={objectArray[count]} renderAs={'svg'} size={200} />;
|
||||
};
|
@ -5,7 +5,6 @@ import { InterfaceSettings } from './Interface';
|
||||
import { AccountSettings } from './Account';
|
||||
import { DangerView } from './Danger';
|
||||
import { CurrentSettings } from './Current';
|
||||
import { SyncSettings } from './Sync';
|
||||
|
||||
export const ButtonRow = styled.div`
|
||||
width: auto;
|
||||
@ -20,7 +19,6 @@ const SettingsView = () => {
|
||||
return (
|
||||
<>
|
||||
<InterfaceSettings />
|
||||
<SyncSettings />
|
||||
<CurrentSettings />
|
||||
<AccountSettings />
|
||||
<DangerView />
|
||||
|
Loading…
Reference in New Issue
Block a user