feat: refactor login and entry

This commit is contained in:
AP 2020-01-15 20:23:16 +01:00
parent a45da9d63d
commit 650c178cee
44 changed files with 307 additions and 123 deletions

View file

@ -15,6 +15,7 @@ import { Header } from './sections/header/Header';
import { Footer } from './sections/footer/Footer';
import { BitcoinInfoProvider } from './context/BitcoinContext';
import { BitcoinFees } from './components/bitcoinInfo/BitcoinFees';
import { LoadingCard } from './components/loading/LoadingCard';
const EntryView = React.lazy(() => import('./views/entry/Entry'));
const MainView = React.lazy(() => import('./views/main/Main'));
@ -32,13 +33,15 @@ const client = new ApolloClient({
const ContextApp: React.FC = () => {
const { theme } = useSettings();
const { loggedIn, admin, read } = useAccount();
const { loggedIn, admin, read, sessionAdmin } = useAccount();
const renderContent = () => (
<Suspense fallback={<div>Loading...</div>}>
<Suspense
fallback={<LoadingCard noCard={true} loadingHeight={'240px'} />}
>
{!loggedIn && admin === '' ? (
<EntryView />
) : admin !== '' && read === '' ? (
) : admin !== '' && read === '' && sessionAdmin === '' ? (
<EntryView session={true} />
) : (
<MainView />

View file

@ -1,13 +1,13 @@
import { useAccount } from '../../context/AccountContext';
interface AdminSwitchProps {
children: any;
}
export const AdminSwitch = ({ children }: AdminSwitchProps) => {
const currentAuth = localStorage.getItem('account') || 'auth1';
const adminMacaroon = localStorage.getItem(`${currentAuth}-admin`) || '';
const sessionAdmin = sessionStorage.getItem('session') || '';
const { admin, sessionAdmin } = useAccount();
if (!adminMacaroon && !sessionAdmin) {
if (!admin && !sessionAdmin) {
return null;
}

View file

@ -8,14 +8,21 @@ import { toast } from 'react-toastify';
import { useLazyQuery } from '@apollo/react-hooks';
import { GET_CAN_CONNECT } from '../../graphql/query';
import { getErrorContent } from '../../utils/error';
import { useHistory } from 'react-router-dom';
interface AuthProps {
available: number;
callback?: () => void;
withRedirect?: boolean;
}
export const BTCLoginForm = ({ available, callback }: AuthProps) => {
export const BTCLoginForm = ({
available,
callback,
withRedirect,
}: AuthProps) => {
const { setAccount } = useAccount();
const { push } = useHistory();
const [isName, setName] = useState('');
const [isJson, setJson] = useState('');
@ -63,6 +70,7 @@ export const BTCLoginForm = ({ available, callback }: AuthProps) => {
toast.success('Connected!');
callback && callback();
withRedirect && push('/');
}
}, [
data,

View file

@ -6,6 +6,7 @@ import {
getBase64CertfromDerFormat,
saveUserAuth,
getAuthString,
saveSessionAuth,
} from '../../utils/auth';
import { LoginButton, PasswordInput } from './Password';
import CryptoJS from 'crypto-js';
@ -13,14 +14,21 @@ import { useLazyQuery } from '@apollo/react-hooks';
import { GET_CAN_CONNECT } from '../../graphql/query';
import { toast } from 'react-toastify';
import { getErrorContent } from '../../utils/error';
import { useHistory } from 'react-router-dom';
interface AuthProps {
available: number;
callback?: () => void;
withRedirect?: boolean;
}
export const ConnectLoginForm = ({ available, callback }: AuthProps) => {
export const ConnectLoginForm = ({
available,
callback,
withRedirect,
}: AuthProps) => {
const { setAccount } = useAccount();
const { push } = useHistory();
const [isName, setName] = useState('');
const [isUrl, setUrl] = useState('');
@ -54,18 +62,20 @@ export const ConnectLoginForm = ({ available, callback }: AuthProps) => {
cert: base64Cert,
});
sessionStorage.setItem('session', macaroon);
saveSessionAuth(macaroon);
setAccount({
loggedIn: true,
host: socket,
admin: encryptedAdmin,
sessionAdmin: macaroon,
read: macaroon,
cert: base64Cert,
});
toast.success('Connected!');
callback && callback();
withRedirect && push('/');
}
}, [data, loading, available, callback, isName, isPass, isUrl, setAccount]);

View file

@ -1,7 +1,7 @@
import React, { useState, useEffect } from 'react';
import { Input, SingleLine, Sub4Title } from '../generic/Styled';
import { useAccount } from '../../context/AccountContext';
import { saveUserAuth, getAuthString } from '../../utils/auth';
import { saveUserAuth, getAuthString, saveSessionAuth } from '../../utils/auth';
import CryptoJS from 'crypto-js';
import base64url from 'base64url';
import { PasswordInput, LoginButton } from './Password';
@ -9,14 +9,17 @@ import { useLazyQuery } from '@apollo/react-hooks';
import { GET_CAN_CONNECT } from '../../graphql/query';
import { getErrorContent } from '../../utils/error';
import { toast } from 'react-toastify';
import { useHistory } from 'react-router-dom';
interface AuthProps {
available: number;
callback?: () => void;
withRedirect?: boolean;
}
export const LoginForm = ({ available, callback }: AuthProps) => {
export const LoginForm = ({ available, callback, withRedirect }: AuthProps) => {
const { setAccount } = useAccount();
const { push } = useHistory();
const [isName, setName] = useState('');
const [isHost, setHost] = useState('');
@ -62,16 +65,21 @@ export const LoginForm = ({ available, callback }: AuthProps) => {
cert,
});
saveSessionAuth(admin);
setAccount({
loggedIn: true,
name: isName,
host: isHost,
admin: encryptedAdmin,
...(read === '' && { sessionAdmin: admin }),
read,
cert,
});
toast.success('Connected!');
callback && callback();
withRedirect && push('/');
}
}, [
data,
@ -103,7 +111,10 @@ export const LoginForm = ({ available, callback }: AuthProps) => {
const renderContent = () => {
const canConnect =
isName !== '' && isHost !== '' && isRead !== '' && !!available;
isName !== '' &&
isHost !== '' &&
(isAdmin !== '' || isRead !== '') &&
!!available;
return (
<>
<SingleLine>

View file

@ -83,8 +83,8 @@ export const CloseChannel = ({
const [hour, setHour] = useState(0);
const { theme } = useSettings();
const { host, read, cert } = useAccount();
const auth = getAuthString(host, read, cert);
const { host, read, cert, sessionAdmin } = useAccount();
const auth = getAuthString(host, read !== '' ? read : sessionAdmin, cert);
const { data: feeData } = useQuery(GET_BITCOIN_FEES, {
onError: error => toast.error(getErrorContent(error)),

View file

@ -7,6 +7,7 @@ import { ReactComponent as ZapOffIcon } from '../../icons/zap-off.svg';
import { ReactComponent as HelpIcon } from '../../icons/help-circle.svg';
import { ReactComponent as SunIcon } from '../../icons/sun.svg';
import { ReactComponent as MoonIcon } from '../../icons/moon.svg';
import { ReactComponent as EyeIcon } from '../../icons/eye.svg';
import { ReactComponent as EyeOffIcon } from '../../icons/eye-off.svg';
import { ReactComponent as ChevronsUpIcon } from '../../icons/chevrons-up.svg';
import { ReactComponent as ChevronsDownIcon } from '../../icons/chevrons-down.svg';
@ -35,11 +36,15 @@ import { ReactComponent as RadioIcon } from '../../icons/radio.svg';
import { ReactComponent as CopyIcon } from '../../icons/copy.svg';
import { ReactComponent as ShieldIcon } from '../../icons/shield.svg';
import { ReactComponent as CrosshairIcon } from '../../icons/crosshair.svg';
import { ReactComponent as KeyIcon } from '../../icons/key.svg';
import { ReactComponent as SlidersIcon } from '../../icons/sliders.svg';
import { ReactComponent as UsersIcon } from '../../icons/users.svg';
interface IconProps {
color?: string;
size?: string;
fillcolor?: string;
strokeWidth?: string;
}
const GenericStyles = css`
@ -47,6 +52,8 @@ const GenericStyles = css`
width: ${({ size }: IconProps) => (size ? size : '18px')};
color: ${({ color }: IconProps) => (color ? color : '')};
fill: ${({ fillcolor }: IconProps) => (fillcolor ? fillcolor : '')};
stroke-width: ${({ strokeWidth }: IconProps) =>
strokeWidth ? strokeWidth : '2px'};
`;
export const IconCircle = styled.div`
@ -77,6 +84,7 @@ export const UpArrow = styleIcon(UpIcon);
export const DownArrow = styleIcon(DownIcon);
export const Sun = styleIcon(SunIcon);
export const Moon = styleIcon(MoonIcon);
export const Eye = styleIcon(EyeIcon);
export const EyeOff = styleIcon(EyeOffIcon);
export const ChevronsDown = styleIcon(ChevronsDownIcon);
export const ChevronsUp = styleIcon(ChevronsUpIcon);
@ -102,3 +110,6 @@ export const Radio = styleIcon(RadioIcon);
export const Copy = styleIcon(CopyIcon);
export const Shield = styleIcon(ShieldIcon);
export const Crosshair = styleIcon(CrosshairIcon);
export const Key = styleIcon(KeyIcon);
export const Sliders = styleIcon(SlidersIcon);
export const Users = styleIcon(UsersIcon);

View file

@ -56,7 +56,7 @@ interface SubCardProps {
export const SubCard = styled.div`
margin-bottom: 10px;
padding: ${({ padding }) => (padding ? padding : '10px')};
padding: ${({ padding }) => (padding ? padding : '16px')};
background: ${subCardColor};
border: 1px solid ${cardBorderColor};
border-left: ${({ color }: SubCardProps) =>
@ -128,6 +128,13 @@ export const SingleLine = styled.div`
align-items: center;
`;
export const ColumnLine = styled.div`
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: flex-start;
`;
export const SimpleButton = styled.button`
cursor: pointer;
outline: none;

View file

@ -7,6 +7,8 @@ import { textColorMap } from '../../styles/Themes';
const Loading = styled.div`
width: 100%;
height: ${({ loadingHeight }: { loadingHeight?: string }) =>
loadingHeight ? loadingHeight : 'auto'};
display: flex;
justify-content: center;
align-items: center;
@ -17,6 +19,7 @@ interface LoadingCardProps {
noCard?: boolean;
color?: string;
noTitle?: boolean;
loadingHeight?: string;
}
export const LoadingCard = ({
@ -24,6 +27,7 @@ export const LoadingCard = ({
color,
noCard = false,
noTitle = false,
loadingHeight,
}: LoadingCardProps) => {
const { theme } = useSettings();
@ -31,7 +35,7 @@ export const LoadingCard = ({
if (noCard) {
return (
<Loading>
<Loading loadingHeight={loadingHeight}>
<ScaleLoader height={20} color={loadingColor} />
</Loading>
);
@ -40,7 +44,7 @@ export const LoadingCard = ({
if (noTitle) {
return (
<Card>
<Loading>
<Loading loadingHeight={loadingHeight}>
<ScaleLoader height={20} color={loadingColor} />
</Loading>
</Card>
@ -53,7 +57,7 @@ export const LoadingCard = ({
<SubTitle>{title}</SubTitle>
</CardTitle>
<Card>
<Loading>
<Loading loadingHeight={loadingHeight}>
<ScaleLoader height={20} color={loadingColor} />
</Loading>
</Card>

View file

@ -13,7 +13,7 @@ import { LoginButton } from '../../components/auth/Password';
import { Circle, ChevronRight } from '../generic/Icons';
import styled from 'styled-components';
import { useAccount } from '../../context/AccountContext';
import { getAuthString } from '../../utils/auth';
import { getAuthString, saveSessionAuth } from '../../utils/auth';
import { useSettings } from '../../context/SettingsContext';
import { textColorMap } from '../../styles/Themes';
@ -46,7 +46,7 @@ export const LoginModal = ({
const { theme } = useSettings();
const [pass, setPass] = useState<string>('');
const [storeSession, setStoreSession] = useState<boolean>(false);
const { host, cert } = useAccount();
const { host, cert, refreshAccount } = useAccount();
const handleClick = () => {
try {
@ -54,7 +54,8 @@ export const LoginModal = ({
const decrypted = bytes.toString(CryptoJS.enc.Utf8);
if (storeSession) {
sessionStorage.setItem('session', decrypted);
saveSessionAuth(decrypted);
refreshAccount();
}
const auth = getAuthString(host, decrypted, cert);
callback({ variables: { ...variables, auth } });

View file

@ -24,13 +24,9 @@ export const SecureButton = ({
}: SecureButtonProps) => {
const [modalOpen, setModalOpen] = useState<boolean>(false);
const { host, cert } = useAccount();
const { host, cert, admin, sessionAdmin } = useAccount();
const currentAuth = localStorage.getItem('account') || 'auth1';
const adminMacaroon = localStorage.getItem(`${currentAuth}-admin`) || '';
const sessionAdmin = sessionStorage.getItem('session') || '';
if (!adminMacaroon && !sessionAdmin) {
if (!admin && !sessionAdmin) {
return null;
}
@ -55,7 +51,7 @@ export const SecureButton = ({
<Modal isOpen={modalOpen} setIsOpen={setModalOpen}>
<LoginModal
color={color}
macaroon={adminMacaroon}
macaroon={admin}
setModalOpen={setModalOpen}
callback={callback}
variables={variables}

View file

@ -42,14 +42,14 @@ const AccountProvider = ({ children }: any) => {
const activeAccount = localStorage.getItem('account') || 'auth1';
const sessionAdmin = sessionStorage.getItem('session') || '';
const { name, host, admin, read, cert } = getAuthParams(activeAccount);
const readMacaroon = read ? read : sessionAdmin;
const loggedIn = host !== '' && readMacaroon !== '';
const loggedIn = host !== '' && (read !== '' || sessionAdmin !== '');
const setAccount = ({
loggedIn,
name,
host,
admin,
sessionAdmin,
read,
cert,
}: ChangeProps) => {
@ -60,6 +60,7 @@ const AccountProvider = ({ children }: any) => {
name,
host,
admin,
sessionAdmin,
read,
cert,
});
@ -90,8 +91,7 @@ const AccountProvider = ({ children }: any) => {
const activeAccount = localStorage.getItem('account') || 'auth1';
const sessionAdmin = sessionStorage.getItem('session') || '';
const { name, host, admin, read, cert } = getAuthParams(activeAccount);
const readMacaroon = read ? read : sessionAdmin;
const loggedIn = host !== '' && readMacaroon !== '';
const loggedIn = host !== '' && (read !== '' || sessionAdmin !== '');
updateAccount((prevState: any) => {
const newState = { ...prevState };
@ -101,7 +101,7 @@ const AccountProvider = ({ children }: any) => {
host,
admin,
sessionAdmin,
read: readMacaroon,
read,
cert,
});
});
@ -113,7 +113,7 @@ const AccountProvider = ({ children }: any) => {
host,
admin,
sessionAdmin,
read: readMacaroon,
read,
cert,
setAccount,
changeAccount,

1
src/icons/eye.svg Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-eye"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"></path><circle cx="12" cy="12" r="3"></circle></svg>

After

Width:  |  Height:  |  Size: 316 B

1
src/icons/key.svg Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1" stroke-linecap="round" stroke-linejoin="round" class="feather feather-key"><path d="M21 2l-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.778 7.778 5.5 5.5 0 0 1 7.777-7.777zm0 0L15.5 7.5m0 0l3 3L22 7l-3-3m-3.5 3.5L19 4"></path></svg>

After

Width:  |  Height:  |  Size: 352 B

1
src/icons/sliders.svg Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1" stroke-linecap="round" stroke-linejoin="round" class="feather feather-sliders"><line x1="4" y1="21" x2="4" y2="14"></line><line x1="4" y1="10" x2="4" y2="3"></line><line x1="12" y1="21" x2="12" y2="12"></line><line x1="12" y1="8" x2="12" y2="3"></line><line x1="20" y1="21" x2="20" y2="16"></line><line x1="20" y1="12" x2="20" y2="3"></line><line x1="1" y1="14" x2="7" y2="14"></line><line x1="9" y1="8" x2="15" y2="8"></line><line x1="17" y1="16" x2="23" y2="16"></line></svg>

After

Width:  |  Height:  |  Size: 611 B

1
src/icons/users.svg Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1" stroke-linecap="round" stroke-linejoin="round" class="feather feather-users"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path><circle cx="9" cy="7" r="4"></circle><path d="M23 21v-2a4 4 0 0 0-3-3.87"></path><path d="M16 3.13a4 4 0 0 1 0 7.75"></path></svg>

After

Width:  |  Height:  |  Size: 400 B

View file

@ -1,6 +1,9 @@
import React from 'react';
import styled from 'styled-components';
import { textColor, cardColor } from '../../styles/Themes';
import { HomeButton } from '../../views/entry/HomePage.styled';
import { Link } from 'react-router-dom';
import { useAccount } from '../../context/AccountContext';
const HeaderStyle = styled.div`
display: flex;
@ -28,11 +31,17 @@ const HeaderTitle = styled.div`
`;
export const Header = () => {
const { loggedIn } = useAccount();
return (
<HeaderStyle>
<Wrapper>
<HeaderTitle>ThunderHub</HeaderTitle>
<button>Login</button>
{!loggedIn && (
<Link to="/login" style={{ textDecoration: 'none' }}>
<HomeButton>Login</HomeButton>
</Link>
)}
</Wrapper>
</HeaderStyle>
);

View file

@ -45,8 +45,8 @@ const Alias = styled.div`
`;
export const NodeInfo = () => {
const { host, read, cert } = useAccount();
const auth = getAuthString(host, read, cert);
const { host, read, cert, sessionAdmin } = useAccount();
const auth = getAuthString(host, read !== '' ? read : sessionAdmin, cert);
const { loading, data } = useQuery(GET_NODE_INFO, {
variables: { auth },

View file

@ -37,6 +37,9 @@ export const saveUserAuth = ({
cert && localStorage.setItem(`auth${available}-cert`, cert);
};
export const saveSessionAuth = (sessionAdmin: string) =>
sessionStorage.setItem('session', sessionAdmin);
export const getAuthString = (
host: string,
macaroon: string,

View file

@ -14,8 +14,8 @@ import { getErrorContent } from '../../utils/error';
import ScaleLoader from 'react-spinners/ScaleLoader';
export const DownloadBackups = ({ color }: { color: string }) => {
const { host, read, cert } = useAccount();
const auth = getAuthString(host, read, cert);
const { host, read, cert, sessionAdmin } = useAccount();
const auth = getAuthString(host, read !== '' ? read : sessionAdmin, cert);
const [getBackups, { data, loading }] = useLazyQuery(GET_BACKUPS, {
variables: { auth },

View file

@ -20,8 +20,8 @@ export const RecoverFunds = ({ color }: { color: string }) => {
const [backupString, setBackupString] = useState<string>('');
const [isPasting, setIsPasting] = useState<boolean>(false);
const { host, read, cert } = useAccount();
const auth = getAuthString(host, read, cert);
const { host, read, cert, sessionAdmin } = useAccount();
const auth = getAuthString(host, read !== '' ? read : sessionAdmin, cert);
const [recoverFunds, { data, loading }] = useLazyQuery(RECOVER_FUNDS, {
onError: error => toast.error(getErrorContent(error)),

View file

@ -24,8 +24,8 @@ export const VerifyBackups = ({ color }: { color: string }) => {
const [backupString, setBackupString] = useState<string>('');
const [isPasting, setIsPasting] = useState<boolean>(false);
const { host, read, cert } = useAccount();
const auth = getAuthString(host, read, cert);
const { host, read, cert, sessionAdmin } = useAccount();
const auth = getAuthString(host, read !== '' ? read : sessionAdmin, cert);
const [verifyBackup, { data, loading }] = useLazyQuery(VERIFY_BACKUPS, {
onError: error => toast.error(getErrorContent(error)),

View file

@ -25,8 +25,8 @@ export const ChannelView = () => {
});
const { theme } = useSettings();
const { host, read, cert } = useAccount();
const auth = getAuthString(host, read, cert);
const { host, read, cert, sessionAdmin } = useAccount();
const auth = getAuthString(host, read !== '' ? read : sessionAdmin, cert);
const { data } = useQuery(GET_CHANNEL_AMOUNT_INFO, {
variables: { auth },

View file

@ -12,8 +12,8 @@ import { LoadingCard } from '../../../components/loading/LoadingCard';
export const Channels = () => {
const [indexOpen, setIndexOpen] = useState(0);
const { host, read, cert } = useAccount();
const auth = getAuthString(host, read, cert);
const { host, read, cert, sessionAdmin } = useAccount();
const auth = getAuthString(host, read !== '' ? read : sessionAdmin, cert);
const { loading, data } = useQuery(GET_CHANNELS, {
variables: { auth },

View file

@ -12,8 +12,8 @@ import { LoadingCard } from '../../../components/loading/LoadingCard';
export const ClosedChannels = () => {
const [indexOpen, setIndexOpen] = useState(0);
const { host, read, cert } = useAccount();
const auth = getAuthString(host, read, cert);
const { host, read, cert, sessionAdmin } = useAccount();
const auth = getAuthString(host, read !== '' ? read : sessionAdmin, cert);
const { loading, data } = useQuery(GET_CLOSED_CHANNELS, {
variables: { auth },

View file

@ -12,8 +12,8 @@ import { LoadingCard } from '../../../components/loading/LoadingCard';
export const PendingChannels = () => {
const [indexOpen, setIndexOpen] = useState(0);
const { host, read, cert } = useAccount();
const auth = getAuthString(host, read, cert);
const { host, read, cert, sessionAdmin } = useAccount();
const auth = getAuthString(host, read !== '' ? read : sessionAdmin, cert);
const { loading, data } = useQuery(GET_PENDING_CHANNELS, {
variables: { auth },

View file

@ -1,7 +1,7 @@
import React, { useEffect, useState } from 'react';
import React, { useEffect } from 'react';
import { LoginView } from './login/Login';
import { SessionLogin } from './login/SessionLogin';
import { useHistory } from 'react-router';
import { useHistory, Switch, Route, useLocation } from 'react-router';
import { HomePageView } from './HomePage';
interface HomeProps {
@ -9,21 +9,24 @@ interface HomeProps {
}
const EntryView = ({ session }: HomeProps) => {
const [login, setLogin] = useState<boolean>(false);
const history = useHistory();
const { push } = useHistory();
const location = useLocation();
useEffect(() => {
if (history.location.pathname !== '/') {
history.push('/');
if (location.pathname !== '/' && location.pathname !== '/login') {
push('/');
}
}, [history]);
}, [location, push]);
return session ? (
<SessionLogin />
) : login ? (
<LoginView />
) : (
<HomePageView setLogin={setLogin} />
const getView = () => {
return session ? <SessionLogin /> : <HomePageView />;
};
return (
<Switch>
<Route path="/login" render={() => <LoginView />} />
<Route path="/" render={() => getView()} />
</Switch>
);
};

View file

@ -0,0 +1,36 @@
import styled from 'styled-components';
import { ReactComponent as HeadlineImage } from '../../images/MoshingDoodle.svg';
export const Headline = styled.div`
display: flex;
align-items: center;
justify-content: space-between;
padding: 32px 0;
`;
export const LeftHeadline = styled.div`
width: 50%;
display: flex;
flex-direction: column;
`;
export const StyledImage = styled(HeadlineImage)`
width: 500px;
`;
export const HomeButton = styled.button`
cursor: pointer;
outline: none;
padding: 8px 24px;
text-decoration: 2px solid blue;
font-size: 16px;
background-image: linear-gradient(to right, #fe4928, #ffc700);
color: white;
border: none;
display: flex;
align-items: center;
justify-content: center;
border-radius: 24px;
white-space: nowrap;
min-width: 100px;
`;

View file

@ -1,30 +1,65 @@
import React from 'react';
import {
Wrapper,
Card,
SubTitle,
SingleLine,
ColumnLine,
Sub4Title,
} from '../../components/generic/Styled';
import {
Headline,
LeftHeadline,
StyledImage,
HomeButton,
} from './HomePage.styled';
import styled from 'styled-components';
import { ReactComponent as HeadlineImage } from '../../images/MoshingDoodle.svg';
import { Wrapper } from '../../components/generic/Styled';
import {
Zap,
Eye,
Send,
Key,
Server,
Sliders,
Users,
} from '../../components/generic/Icons';
import { backgroundColor } from '../../styles/Themes';
import { Link } from 'react-router-dom';
const Headline = styled.div`
const DetailCard = styled(Card)`
width: 33%;
background-color: ${backgroundColor};
margin-bottom: 0;
margin: 8px 16px;
`;
const DetailLine = styled.div`
margin: 0 -16px;
display: flex;
justify-content: center;
align-items: center;
justify-content: space-between;
padding: 32px 0;
`;
const LeftHeadline = styled.div`
width: 50%;
display: flex;
flex-direction: column;
const Padding = styled.div`
padding-right: ${({ padding }: { padding?: string }) =>
padding ? padding : '16px'};
`;
const StyledImage = styled(HeadlineImage)`
width: 500px;
`;
const detailCardContent = (title: string, text: string, Icon: any) => (
<DetailCard>
<SingleLine>
<Padding>
<Icon size={'40px'} strokeWidth={'1px'} />
</Padding>
<ColumnLine>
<SubTitle>{title}</SubTitle>
<Sub4Title>{text}</Sub4Title>
</ColumnLine>
</SingleLine>
</DetailCard>
);
interface HomePageProps {
setLogin: (login: boolean) => void;
}
export const HomePageView = ({ setLogin }: HomePageProps) => {
export const HomePageView = () => {
return (
<>
<Wrapper>
@ -36,16 +71,56 @@ export const HomePageView = ({ setLogin }: HomePageProps) => {
something else to place here. Think Think Think
</h4>
<h5>Available everywhere you can open a website.</h5>
<button onClick={() => setLogin(true)}>Login</button>
<Link to="/login" style={{ textDecoration: 'none' }}>
<HomeButton>
<Padding padding={'4px'}>
<Zap />
</Padding>
Control The Lightning
</HomeButton>
</Link>
</LeftHeadline>
<StyledImage />
</Headline>
</Wrapper>
<Wrapper withColor={true}>
<div>Hello</div>
<DetailLine>
{detailCardContent(
'Make Payments',
'Send and receive both Lightning and On-Chain payments.',
Send,
)}
{detailCardContent(
'Multiple Nodes',
'Connect to multiple nodes and quickly switch between them.',
Server,
)}
{detailCardContent(
'View-Only Mode',
`Check the status of your node any time without risk.`,
Eye,
)}
</DetailLine>
<DetailLine>
{detailCardContent(
'AES Encryption',
'Your Macaroon is AES encrypted with a password only you know.',
Key,
)}
{detailCardContent(
'Open Source',
`Don't trust anyone. Verify the code yourself.`,
Users,
)}
{detailCardContent(
'Manage Channels',
'Open, close and monitor channel status and liquidity',
Sliders,
)}
</DetailLine>
</Wrapper>
<Wrapper>
<div>Hello</div>
<div>Another Line</div>
</Wrapper>
</>
);

View file

@ -54,9 +54,15 @@ export const LoginView = () => {
<SubTitle> How do you want to connect?</SubTitle>
)}
{isType === 'none' && renderButtons()}
{isType === 'login' && <LoginForm available={next} />}
{isType === 'connect' && <ConnectLoginForm available={next} />}
{isType === 'btcpay' && <BTCLoginForm available={next} />}
{isType === 'login' && (
<LoginForm available={next} withRedirect={true} />
)}
{isType === 'connect' && (
<ConnectLoginForm available={next} withRedirect={true} />
)}
{isType === 'btcpay' && (
<BTCLoginForm available={next} withRedirect={true} />
)}
</Card>
</Wrapper>
);

View file

@ -12,6 +12,7 @@ import {
import { LoginButton } from '../../../components/auth/Password';
import CryptoJS from 'crypto-js';
import { toast } from 'react-toastify';
import { saveSessionAuth } from '../../../utils/auth';
export const SessionLogin = () => {
const { name, admin, refreshAccount } = useAccount();
@ -22,7 +23,7 @@ export const SessionLogin = () => {
const bytes = CryptoJS.AES.decrypt(admin, pass);
const decrypted = bytes.toString(CryptoJS.enc.Utf8);
sessionStorage.setItem('session', decrypted);
saveSessionAuth(decrypted);
refreshAccount();
} catch (error) {
toast.error('Wrong Password');

View file

@ -37,8 +37,8 @@ export const FeesView = () => {
const [feeRate, setFeeRate] = useState(0);
const { theme } = useSettings();
const { host, read, cert } = useAccount();
const auth = getAuthString(host, read, cert);
const { host, read, cert, sessionAdmin } = useAccount();
const auth = getAuthString(host, read !== '' ? read : sessionAdmin, cert);
const { loading, data } = useQuery(CHANNEL_FEES, {
variables: { auth },

View file

@ -48,8 +48,8 @@ const sectionColor = '#FFD300';
export const AccountInfo = () => {
const [state, setState] = useState<string>('none');
const { host, read, cert } = useAccount();
const auth = getAuthString(host, read, cert);
const { host, read, cert, sessionAdmin } = useAccount();
const auth = getAuthString(host, read !== '' ? read : sessionAdmin, cert);
const { data, loading } = useQuery(GET_BALANCES, {
variables: { auth },

View file

@ -43,7 +43,7 @@ export const SendOnChainCard = ({ color }: { color: string }) => {
const [sendAll, setSendAll] = useState(false);
const [isSent, setIsSent] = useState(false);
const canSend = address !== '' && tokens > 0 && amount > 0;
const canSend = address !== '' && (sendAll || tokens > 0) && amount > 0;
const { theme } = useSettings();
const { price, symbol, currency } = useSettings();

View file

@ -40,8 +40,8 @@ const TextPadding = styled.span`
const sectionColor = '#fa541c';
export const ConnectCard = () => {
const { host, read, cert } = useAccount();
const auth = getAuthString(host, read, cert);
const { host, read, cert, sessionAdmin } = useAccount();
const auth = getAuthString(host, read !== '' ? read : sessionAdmin, cert);
const { loading, data } = useQuery(GET_CONNECT_INFO, {
variables: { auth },

View file

@ -38,8 +38,8 @@ const Title = styled.div`
`;
export const NetworkInfo = () => {
const { host, read, cert } = useAccount();
const auth = getAuthString(host, read, cert);
const { host, read, cert, sessionAdmin } = useAccount();
const auth = getAuthString(host, read !== '' ? read : sessionAdmin, cert);
const { loading, data } = useQuery(GET_NETWORK_INFO, {
variables: { auth },

View file

@ -26,8 +26,8 @@ export const DecodeCard = ({ color }: { color: string }) => {
const { price, symbol, currency } = useSettings();
const priceProps = { price, symbol, currency };
const { host, read, cert } = useAccount();
const auth = getAuthString(host, read, cert);
const { host, read, cert, sessionAdmin } = useAccount();
const auth = getAuthString(host, read !== '' ? read : sessionAdmin, cert);
const [decode, { data, loading }] = useMutation(DECODE_REQUEST, {
onError: error => toast.error(getErrorContent(error)),

View file

@ -57,8 +57,8 @@ export const OpenChannelCard = ({ color, setOpenCard }: OpenChannelProps) => {
const { price, symbol, currency, theme } = useSettings();
const priceProps = { price, symbol, currency };
const { host, read, cert } = useAccount();
const auth = getAuthString(host, read, cert);
const { host, read, cert, sessionAdmin } = useAccount();
const auth = getAuthString(host, read !== '' ? read : sessionAdmin, cert);
const [openChannel] = useMutation(OPEN_CHANNEL, {
onError: error => toast.error(getErrorContent(error)),

View file

@ -61,8 +61,8 @@ export const FlowBox = () => {
const [isTime, setIsTime] = useState<string>('month');
const [isType, setIsType] = useState<string>('amount');
const { host, read, cert } = useAccount();
const auth = getAuthString(host, read, cert);
const { host, read, cert, sessionAdmin } = useAccount();
const auth = getAuthString(host, read !== '' ? read : sessionAdmin, cert);
const { data, loading } = useQuery(GET_IN_OUT, {
variables: { time: isTime, auth },
onError: error => toast.error(getErrorContent(error)),

View file

@ -64,8 +64,8 @@ export const ForwardChannelsReport = ({ isTime, isType, color }: Props) => {
const { price, symbol, currency } = useSettings();
const { host, read, cert } = useAccount();
const auth = getAuthString(host, read, cert);
const { host, read, cert, sessionAdmin } = useAccount();
const auth = getAuthString(host, read !== '' ? read : sessionAdmin, cert);
const { data, loading } = useQuery(GET_FORWARD_CHANNELS_REPORT, {
variables: { time: isTime, order: isType, auth, type },

View file

@ -31,8 +31,8 @@ interface Props {
export const ForwardReport = ({ isTime, isType }: Props) => {
const { theme, price, symbol, currency } = useSettings();
const { host, read, cert } = useAccount();
const auth = getAuthString(host, read, cert);
const { host, read, cert, sessionAdmin } = useAccount();
const auth = getAuthString(host, read !== '' ? read : sessionAdmin, cert);
const { data, loading } = useQuery(GET_FORWARD_REPORT, {
variables: { time: isTime, auth },

View file

@ -25,8 +25,8 @@ import {
import { LoadingCard } from '../../../../components/loading/LoadingCard';
export const LiquidReport = () => {
const { host, read, cert } = useAccount();
const auth = getAuthString(host, read, cert);
const { host, read, cert, sessionAdmin } = useAccount();
const auth = getAuthString(host, read !== '' ? read : sessionAdmin, cert);
const { theme, price, symbol, currency } = useSettings();

View file

@ -7,6 +7,7 @@ import {
} from '../../components/generic/Styled';
import styled from 'styled-components';
import { unSelectedNavButton, chartLinkColor } from '../../styles/Themes';
import { useAccount } from '../../context/AccountContext';
const CurrentField = styled.div`
color: ${chartLinkColor};
@ -21,12 +22,7 @@ const CurrentField = styled.div`
`;
export const CurrentSettings = () => {
const currentAuth = localStorage.getItem('account') || 'auth1';
const currentName = localStorage.getItem(`${currentAuth}-name`);
const currentAdmin = localStorage.getItem(`${currentAuth}-admin`);
const currentRead = localStorage.getItem(`${currentAuth}-read`);
const currentCert = localStorage.getItem(`${currentAuth}-cert`);
const currentHost = localStorage.getItem(`${currentAuth}-host`);
const { name, host, admin, read, cert } = useAccount();
const renderField = (title: string, field: string | null) => {
if (!field) return null;
@ -43,11 +39,11 @@ export const CurrentSettings = () => {
<CardWithTitle>
<SubTitle>Current Account:</SubTitle>
<Card>
{renderField('Name:', currentName)}
{renderField('AES Encrypted Admin Macaroon:', currentAdmin)}
{renderField('Read-only Macaroon:', currentRead)}
{renderField('Certificate:', currentCert)}
{renderField('Host:', currentHost)}
{renderField('Name:', name)}
{renderField('Host:', host)}
{renderField('AES Encrypted Admin Macaroon:', admin)}
{renderField('Read-only Macaroon:', read)}
{renderField('Certificate:', cert)}
</Card>
</CardWithTitle>
);

View file

@ -29,8 +29,8 @@ export const TransactionList = () => {
const [fetching, setFetching] = useState(false);
const { theme } = useSettings();
const { host, read, cert } = useAccount();
const auth = getAuthString(host, read, cert);
const { host, read, cert, sessionAdmin } = useAccount();
const auth = getAuthString(host, read !== '' ? read : sessionAdmin, cert);
const { loading, data, fetchMore } = useQuery(GET_RESUME, {
variables: { auth, token: '' },