Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions background/backgroundComponents/messageListener.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ const initMessageListener = () => {
const recoverAccount = () => {
const { password, recoverMnemonic } = request;
let wallet;
let applicationState;
try {
wallet = fromMnemonic(recoverMnemonic);
} catch (e) {
Expand All @@ -147,10 +148,13 @@ const initMessageListener = () => {

if (wallet) {
_storeAccount({ mnemonicPhrase: recoverMnemonic, password, wallet });
localStorage.setItem(
APPLICATION_ID,
APPLICATION_STATE.MNEMONIC_PHRASE_CONFIRMED,
);

// if we don't have an application state, assign them one
applicationState =
localStorage.getItem(APPLICATION_ID) ||
APPLICATION_STATE.MNEMONIC_PHRASE_CONFIRMED;

localStorage.setItem(APPLICATION_ID, applicationState);
}

sendResponse({
Expand Down
15 changes: 3 additions & 12 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import React from "react";
import { configureStore } from "@reduxjs/toolkit";
import { combineReducers } from "redux";
import { Provider } from "react-redux";
import styled, { createGlobalStyle } from "styled-components";
import { createGlobalStyle } from "styled-components";

import { COLOR_PALETTE } from "styles";
import { reducer as auth } from "ducks/authServices";
Expand All @@ -21,13 +21,6 @@ html, body, #root {
}
`;

const Wrapper = styled.div`
display: flex;
flex-flow: column;
height: 100%;
text-align: left;
`;

const store = configureStore({
reducer: combineReducers({
auth,
Expand All @@ -39,10 +32,8 @@ export const history = createHashHistory();
export function App() {
return (
<Provider store={store}>
<Wrapper>
<GlobalStyle />
<Router />
</Wrapper>
<GlobalStyle />
<Router />
</Provider>
);
}
17 changes: 15 additions & 2 deletions src/Router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,27 @@ import SignTransaction from "views/SignTransaction";
import UnlockAccount from "views/UnlockAccount";
import Welcome from "views/Welcome";

const Loading = () => <p> Loading...</p>;

const ProtectedRoute = (props: RouteProps) => {
const location = useLocation();
const applicationState = useSelector(applicationStateSelector);
const authenticated = useSelector(authenticatedSelector);
const publicKey = useSelector(publicKeySelector);

if (applicationState === APPLICATION_STATE.APPLICATION_LOADING) {
return <p>loading...</p>;
return <Loading />;
}
if (!publicKey || !authenticated) {
if (applicationState === APPLICATION_STATE.APPLICATION_STARTED) {
return (
<Redirect
to={{
pathname: "/",
}}
/>
);
}
return (
<Redirect
to={{
Expand All @@ -54,7 +65,9 @@ const HomeRoute = () => {
const location = useLocation();
const applicationState = useSelector(applicationStateSelector);
const publicKey = useSelector(publicKeySelector);

if (applicationState === APPLICATION_STATE.APPLICATION_LOADING) {
return <Loading />;
}
if (!publicKey) {
if (applicationState === APPLICATION_STATE.MNEMONIC_PHRASE_CONFIRMED) {
return <UnlockAccount />;
Expand Down
49 changes: 29 additions & 20 deletions src/components/Layout/Fullscreen.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import React from "react";
import styled from "styled-components";
import { COLOR_PALETTE } from "styles";
import { Button } from "styles/Basics";
import Header from "./Header";

const H1 = styled.h1`
const HeaderEl = styled.h1`
color: ${COLOR_PALETTE.primary};
font-weight: 200;
font-size: 2.5rem;
line-height: 3.4rem;
margin: 1rem 0;
max-width: 21rem;
`;

const Screen = styled.div`
Expand All @@ -18,35 +22,40 @@ const Screen = styled.div`
`;

const HalfScreen = styled.div`
padding: 0 30px;
width: 355px;
padding: 0 1.6rem;
width: 30rem;

:nth-child(1) {
margin-top: -20px;
margin-top: -8.125rem;
}
`;

const BackButton = styled(Button)`
margin: 1rem 0 0 2.75rem;
`;

const Fullscreen = ({
goBack,
header,
icon: [src, alt],
icon: { src, alt },
children,
}: {
goBack?: () => void;
header: string;
icon: [string, string];
icon: { src: string; alt: string };
children: JSX.Element;
}) => {
return (
<>
<Header />
<Screen>
<HalfScreen>
<img src={src} alt={alt} />
<H1>{header}</H1>
</HalfScreen>
<HalfScreen>{children}</HalfScreen>
</Screen>
</>
);
};
}) => (
<>
<Header />
{goBack ? <BackButton onClick={goBack}>&lt; Back</BackButton> : null}
<Screen>
<HalfScreen>
<img src={src} alt={alt} />
<HeaderEl>{header}</HeaderEl>
</HalfScreen>
<HalfScreen>{children}</HalfScreen>
</Screen>
</>
);

export default Fullscreen;
80 changes: 60 additions & 20 deletions src/components/mnemonicPhrase/ConfirmMnemonicPhrase.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,52 @@ import styled from "styled-components";
import { shuffle } from "lodash";
import { useDispatch, useSelector } from "react-redux";
import { confirmMnemonicPhrase, authErrorSelector } from "ducks/authServices";
import { ErrorMessage } from "components/form";
import { ErrorMessage, FormButton } from "components/form";
import { COLOR_PALETTE } from "styles";
import { Button } from "styles/Basics";
import CheckButton from "./basics/CheckButton";

const ConfirmInput = styled.textarea`
background: #d3d3d3;
const ConfirmInput = styled.div`
background: #d2d8e5;
border: 0;
border-radius: 5px;
color: purple;
font-size: 14px;
padding: 20px 30px;
width: 60%;
border-radius: 30px;
box-sizing: border-box;
color: ${COLOR_PALETTE.primary};
font-size: 1.125rem;
height: 160px;
padding: 2.3rem;
resize: none;
width: 100%;
margin-bottom: 20px;
text-align: center;
`;

const ClearButton = styled(Button)`
background: ${COLOR_PALETTE.primaryGradient};
border-radius: 7px;
color: #fff;
font-weight: 800;
height: 24px;
margin-left: 7px;
width: 24px;
`;

const ConfirmMnemonicPhrase = ({
mnemonicPhrase,
setReadyToConfirm,
}: {
mnemonicPhrase: string;
setReadyToConfirm: (readyToConfirm: boolean) => void;
}) => {
const dispatch = useDispatch();
const words = useRef(shuffle(mnemonicPhrase.split(" ")));
const words = shuffle(mnemonicPhrase.split(" "));
const wordState = useRef(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this form starts to get more complicated bc we're introducing a "clear field" button. we need to create an object to store all the values of each form input so we can clear em all at once when needed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is the initial state. setting all the checkboxes to false (AKA, not checked)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be a good idea to switch to Formik or another form tool sooner rather than later. I know that Formik gives you "reset form" out of the box

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yup, been looking at some form libraries. The next iteration of this will be using one

words.reduce(
(obj, current, i) => ({
...obj,
[`${current}-${i}`]: false,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we need to create a unique key bc evidently a mnemonic phrase can repeat the same word at different pts

}),
{},
),
);
const [selectedWords, setSelectedWords] = useState<string[]>([]);
const authError = useSelector(authErrorSelector);

Expand All @@ -40,16 +63,31 @@ const ConfirmMnemonicPhrase = ({
});
};

const initialWordState = wordState.current;

const [checkboxState, setCheckboxState] = useState(initialWordState);

const wordStateArr: [string, boolean][] = Object.entries(checkboxState);

const wordBubbles = () =>
words.current.map((word) => (
wordStateArr.map(([wordKey, value]) => (
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

grab each "word/checked" state and create a checkbox from it

<CheckButton
onChange={(e) => {
setCheckboxState((prev) => ({ ...prev, [wordKey]: !value }));
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

update the form state to track changing values

updatePhrase(e.target);
}}
word={word}
key={wordKey}
wordKey={wordKey}
value={value}
word={wordKey.replace(/-.*/, "")}
/>
));

const clearFields = () => {
setSelectedWords([]);
setCheckboxState(initialWordState);
};

const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
dispatch(confirmMnemonicPhrase(selectedWords.join(" ")));
Expand All @@ -58,16 +96,18 @@ const ConfirmMnemonicPhrase = ({
<>
<form onSubmit={handleSubmit}>
<div>
<ConfirmInput readOnly value={selectedWords.join(" ")} />
<ConfirmInput>
{selectedWords.join(" ")}
{selectedWords.length ? (
<ClearButton type="button" onClick={clearFields}>
X
</ClearButton>
) : null}
</ConfirmInput>
<ErrorMessage authError={authError}></ErrorMessage>
</div>
{wordBubbles()}
<div>
<button type="submit">Confirm</button>
</div>
<div>
<button onClick={() => setReadyToConfirm(false)}>Go back</button>
</div>
<FormButton type="submit">Confirm</FormButton>
</form>
</>
);
Expand Down
Loading