diff --git a/web/account/siwe-login-form.react.js b/web/account/siwe-login-form.react.js
index 191bab5a9..d3ed9a333 100644
--- a/web/account/siwe-login-form.react.js
+++ b/web/account/siwe-login-form.react.js
@@ -1,162 +1,171 @@
// @flow
import '@rainbow-me/rainbowkit/styles.css';
import invariant from 'invariant';
import * as React from 'react';
import { useAccount, useSigner } from 'wagmi';
import {
getSIWENonce,
getSIWENonceActionTypes,
siweAuth,
siweAuthActionTypes,
} from 'lib/actions/siwe-actions.js';
import ConnectedWalletInfo from 'lib/components/connected-wallet-info.react.js';
import SWMansionIcon from 'lib/components/SWMansionIcon.react.js';
import { createLoadingStatusSelector } from 'lib/selectors/loading-selectors.js';
import type { LogInStartingPayload } from 'lib/types/account-types.js';
import {
useDispatchActionPromise,
useServerCall,
} from 'lib/utils/action-utils.js';
import {
createSIWEMessage,
getSIWEStatementForPublicKey,
siweMessageSigningExplanationStatements,
} from 'lib/utils/siwe-utils.js';
import HeaderSeparator from './header-separator.react.js';
import css from './siwe.css';
import Button from '../components/button.react.js';
import OrBreak from '../components/or-break.react.js';
import LoadingIndicator from '../loading-indicator.react.js';
import { useSelector } from '../redux/redux-utils.js';
import { webLogInExtraInfoSelector } from '../selectors/account-selectors.js';
type SIWELoginFormProps = {
+cancelSIWEAuthFlow: () => void,
};
const getSIWENonceLoadingStatusSelector = createLoadingStatusSelector(
getSIWENonceActionTypes,
);
function SIWELoginForm(props: SIWELoginFormProps): React.Node {
const { address } = useAccount();
const { data: signer } = useSigner();
const dispatchActionPromise = useDispatchActionPromise();
const getSIWENonceCall = useServerCall(getSIWENonce);
const getSIWENonceCallLoadingStatus = useSelector(
getSIWENonceLoadingStatusSelector,
);
const siweAuthCall = useServerCall(siweAuth);
const logInExtraInfo = useSelector(webLogInExtraInfoSelector);
const [siweNonce, setSIWENonce] = React.useState(null);
const siweNonceShouldBeFetched =
!siweNonce && getSIWENonceCallLoadingStatus !== 'loading';
React.useEffect(() => {
if (!siweNonceShouldBeFetched) {
return;
}
dispatchActionPromise(
getSIWENonceActionTypes,
(async () => {
const response = await getSIWENonceCall();
setSIWENonce(response);
})(),
);
}, [dispatchActionPromise, getSIWENonceCall, siweNonceShouldBeFetched]);
const primaryIdentityPublicKey = useSelector(
state => state.primaryIdentityPublicKey,
);
const callSIWEAuthEndpoint = React.useCallback(
(message: string, signature: string, extraInfo) =>
siweAuthCall({
message,
signature,
...extraInfo,
}),
[siweAuthCall],
);
const attemptSIWEAuth = React.useCallback(
(message: string, signature: string) => {
const extraInfo = logInExtraInfo();
dispatchActionPromise(
siweAuthActionTypes,
callSIWEAuthEndpoint(message, signature, extraInfo),
undefined,
({ calendarQuery: extraInfo.calendarQuery }: LogInStartingPayload),
);
},
[callSIWEAuthEndpoint, dispatchActionPromise, logInExtraInfo],
);
const onSignInButtonClick = React.useCallback(async () => {
invariant(signer, 'signer must be present during SIWE attempt');
invariant(siweNonce, 'nonce must be present during SIWE attempt');
invariant(
primaryIdentityPublicKey,
'primaryIdentityPublicKey must be present during SIWE attempt',
);
const statement = getSIWEStatementForPublicKey(primaryIdentityPublicKey);
const message = createSIWEMessage(address, statement, siweNonce);
const signature = await signer.signMessage(message);
attemptSIWEAuth(message, signature);
}, [address, attemptSIWEAuth, primaryIdentityPublicKey, signer, siweNonce]);
const { cancelSIWEAuthFlow } = props;
const backButtonColor = React.useMemo(
() => ({ backgroundColor: '#211E2D' }),
[],
);
+ const signInButtonColor = React.useMemo(
+ () => ({ backgroundColor: '#6A20E3' }),
+ [],
+ );
+
if (!siweNonce || !primaryIdentityPublicKey) {
return (
);
}
return (
Sign in with Ethereum
-
);
}
export default SIWELoginForm;
diff --git a/web/account/traditional-login-form.react.js b/web/account/traditional-login-form.react.js
index a1f749c61..67663bcf4 100644
--- a/web/account/traditional-login-form.react.js
+++ b/web/account/traditional-login-form.react.js
@@ -1,185 +1,191 @@
// @flow
import invariant from 'invariant';
import * as React from 'react';
import { logIn, logInActionTypes } from 'lib/actions/user-actions.js';
import { useModalContext } from 'lib/components/modal-provider.react.js';
import { createLoadingStatusSelector } from 'lib/selectors/loading-selectors.js';
import {
oldValidUsernameRegex,
validEmailRegex,
} from 'lib/shared/account-utils.js';
import type {
LogInExtraInfo,
LogInStartingPayload,
} from 'lib/types/account-types.js';
import { logInActionSources } from 'lib/types/account-types.js';
import {
useDispatchActionPromise,
useServerCall,
} from 'lib/utils/action-utils.js';
import HeaderSeparator from './header-separator.react.js';
import css from './log-in-form.css';
import PasswordInput from './password-input.react.js';
import Button from '../components/button.react.js';
import LoadingIndicator from '../loading-indicator.react.js';
import Input from '../modals/input.react.js';
import { useSelector } from '../redux/redux-utils.js';
import { webLogInExtraInfoSelector } from '../selectors/account-selectors.js';
const loadingStatusSelector = createLoadingStatusSelector(logInActionTypes);
function TraditionalLoginForm(): React.Node {
const inputDisabled = useSelector(loadingStatusSelector) === 'loading';
const loginExtraInfo = useSelector(webLogInExtraInfoSelector);
const callLogIn = useServerCall(logIn);
const dispatchActionPromise = useDispatchActionPromise();
const modalContext = useModalContext();
const primaryIdentityPublicKey = useSelector(
state => state.primaryIdentityPublicKey,
);
const usernameInputRef = React.useRef();
React.useEffect(() => {
usernameInputRef.current?.focus();
}, []);
const [username, setUsername] = React.useState('');
const onUsernameChange = React.useCallback(e => {
invariant(e.target instanceof HTMLInputElement, 'target not input');
setUsername(e.target.value);
}, []);
const onUsernameBlur = React.useCallback(() => {
setUsername(untrimmedUsername => untrimmedUsername.trim());
}, []);
const [password, setPassword] = React.useState('');
const onPasswordChange = React.useCallback(e => {
invariant(e.target instanceof HTMLInputElement, 'target not input');
setPassword(e.target.value);
}, []);
const [errorMessage, setErrorMessage] = React.useState('');
const logInAction = React.useCallback(
async (extraInfo: LogInExtraInfo) => {
try {
invariant(
primaryIdentityPublicKey,
'primaryIdentityPublicKey must be set in logInAction',
);
const result = await callLogIn({
...extraInfo,
username,
password,
logInActionSource: logInActionSources.logInFromWebForm,
primaryIdentityPublicKey,
});
modalContext.popModal();
return result;
} catch (e) {
setUsername('');
setPassword('');
if (e.message === 'invalid_credentials') {
setErrorMessage('incorrect username or password');
} else {
setErrorMessage('unknown error');
}
usernameInputRef.current?.focus();
throw e;
}
},
[callLogIn, modalContext, password, primaryIdentityPublicKey, username],
);
const onSubmit = React.useCallback(
(event: SyntheticEvent) => {
event.preventDefault();
if (username.search(validEmailRegex) > -1) {
setUsername('');
setErrorMessage('usernames only, not emails');
usernameInputRef.current?.focus();
return;
} else if (username.search(oldValidUsernameRegex) === -1) {
setUsername('');
setErrorMessage('alphanumeric usernames only');
usernameInputRef.current?.focus();
return;
} else if (password === '') {
setErrorMessage('password is empty');
usernameInputRef.current?.focus();
return;
}
const extraInfo = loginExtraInfo();
dispatchActionPromise(
logInActionTypes,
logInAction(extraInfo),
undefined,
({ calendarQuery: extraInfo.calendarQuery }: LogInStartingPayload),
);
},
[dispatchActionPromise, logInAction, loginExtraInfo, username, password],
);
const loginButtonContent = React.useMemo(() => {
if (inputDisabled) {
return ;
}
return 'Sign in';
}, [inputDisabled]);
+ const signInButtonColor = React.useMemo(
+ () => ({ backgroundColor: '#6A20E3' }),
+ [],
+ );
+
return (
);
}
export default TraditionalLoginForm;