redirect to password screen if toggling sync from settings page
This commit is contained in:
parent
d7c0f5c6b7
commit
2ec3f62407
17 changed files with 66 additions and 115 deletions
|
@ -130,8 +130,8 @@
|
|||
"husky": "^0.14.3",
|
||||
"json-loader": "^0.5.4",
|
||||
"lbry-format": "https://github.com/lbryio/lbry-format.git",
|
||||
"lbry-redux": "lbryio/lbry-redux#0090f195eb88f4620db7d038f7b01eaa76119836",
|
||||
"lbryinc": "lbryio/lbryinc#b8e1708ee4491db342c81576265e1b58f542bedb",
|
||||
"lbry-redux": "lbryio/lbry-redux#b09e1699eb92fef8087986a0f35b3df3977af87f",
|
||||
"lbryinc": "lbryio/lbryinc#fb2e73ab31c2b9f80a53f082843a01e3f213ca45",
|
||||
"lint-staged": "^7.0.2",
|
||||
"localforage": "^1.7.1",
|
||||
"lodash-es": "^4.17.14",
|
||||
|
|
|
@ -124,7 +124,7 @@ function App(props: Props) {
|
|||
}, [hasVerifiedEmail, signIn, hasSignedIn]);
|
||||
|
||||
useEffect(() => {
|
||||
if (userId && hasVerifiedEmail && syncEnabled) {
|
||||
if (hasVerifiedEmail && syncEnabled) {
|
||||
checkSync();
|
||||
|
||||
let syncInterval = setInterval(() => {
|
||||
|
@ -135,7 +135,7 @@ function App(props: Props) {
|
|||
clearInterval(syncInterval);
|
||||
};
|
||||
}
|
||||
}, [hasVerifiedEmail, syncEnabled, checkSync, userId]);
|
||||
}, [hasVerifiedEmail, syncEnabled, checkSync]);
|
||||
|
||||
if (!user) {
|
||||
return null;
|
||||
|
|
|
@ -69,7 +69,6 @@ const Button = forwardRef<any, {}>((props: Props, ref: any) => {
|
|||
...otherProps
|
||||
} = props;
|
||||
|
||||
const currentPath = pathname.split('/$/')[1];
|
||||
const combinedClassName = classnames(
|
||||
'button',
|
||||
button
|
||||
|
@ -120,7 +119,7 @@ const Button = forwardRef<any, {}>((props: Props, ref: any) => {
|
|||
<NavLink
|
||||
ref={ref}
|
||||
exact
|
||||
to={`/$/${PAGES.AUTH}?redirect=${currentPath}`}
|
||||
to={`/$/${PAGES.AUTH}?redirect=${pathname}`}
|
||||
title={title}
|
||||
disabled={disabled}
|
||||
className={combinedClassName}
|
||||
|
|
|
@ -3,7 +3,8 @@ import React from 'react';
|
|||
import { Form, FormField } from 'component/common/form';
|
||||
import Button from 'component/button';
|
||||
import Card from 'component/common/card';
|
||||
import { setSavedPassword, deleteSavedPassword } from 'util/saved-passwords';
|
||||
import { setSavedPassword } from 'util/saved-passwords';
|
||||
import usePersistedState from 'effects/use-persisted-state';
|
||||
|
||||
type Props = {
|
||||
getSync: (?string) => void,
|
||||
|
@ -13,15 +14,10 @@ type Props = {
|
|||
function SyncPassword(props: Props) {
|
||||
const { getSync, getSyncIsPending } = props;
|
||||
const [password, setPassword] = React.useState('');
|
||||
const [rememberPassword, setRememberPassword] = React.useState(true);
|
||||
const [rememberPassword, setRememberPassword] = usePersistedState(true);
|
||||
|
||||
function handleSubmit() {
|
||||
if (rememberPassword) {
|
||||
setSavedPassword(password);
|
||||
} else {
|
||||
deleteSavedPassword();
|
||||
}
|
||||
|
||||
setSavedPassword(password, rememberPassword);
|
||||
getSync(password);
|
||||
}
|
||||
|
||||
|
@ -39,6 +35,7 @@ function SyncPassword(props: Props) {
|
|||
onChange={e => setPassword(e.target.value)}
|
||||
/>
|
||||
<FormField
|
||||
name="remember-password"
|
||||
type="checkbox"
|
||||
label={__('Remember My Password')}
|
||||
checked={rememberPassword}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import * as SETTINGS from 'constants/settings';
|
||||
import { connect } from 'react-redux';
|
||||
import { selectUserVerifiedEmail } from 'lbryinc';
|
||||
import { selectUserVerifiedEmail, selectGetSyncErrorMessage } from 'lbryinc';
|
||||
import { makeSelectClientSetting } from 'redux/selectors/settings';
|
||||
import { doSetClientSetting } from 'redux/actions/settings';
|
||||
import SyncToggle from './view';
|
||||
|
@ -8,6 +8,7 @@ import SyncToggle from './view';
|
|||
const select = state => ({
|
||||
syncEnabled: makeSelectClientSetting(SETTINGS.ENABLE_SYNC)(state),
|
||||
verifiedEmail: selectUserVerifiedEmail(state),
|
||||
getSyncError: selectGetSyncErrorMessage(state),
|
||||
});
|
||||
|
||||
const perform = dispatch => ({
|
||||
|
|
|
@ -1,25 +1,44 @@
|
|||
// @flow
|
||||
import * as PAGES from 'constants/pages';
|
||||
import React from 'react';
|
||||
import { FormField } from 'component/common/form';
|
||||
import Button from 'component/button';
|
||||
import { FormField } from 'component/common/form';
|
||||
import { withRouter } from 'react-router';
|
||||
|
||||
type Props = {
|
||||
setSyncEnabled: boolean => void,
|
||||
syncEnabled: boolean,
|
||||
verifiedEmail: ?string,
|
||||
history: { push: string => void },
|
||||
location: UrlLocation,
|
||||
getSyncError: ?string,
|
||||
};
|
||||
|
||||
function SyncToggle(props: Props) {
|
||||
const { setSyncEnabled, syncEnabled, verifiedEmail } = props;
|
||||
console.log('??', syncEnabled);
|
||||
const {
|
||||
setSyncEnabled,
|
||||
syncEnabled,
|
||||
verifiedEmail,
|
||||
getSyncError,
|
||||
history,
|
||||
location: { pathname },
|
||||
} = props;
|
||||
|
||||
function handleChange() {
|
||||
setSyncEnabled(!syncEnabled);
|
||||
}
|
||||
|
||||
if (getSyncError) {
|
||||
return history.push(`/$/${PAGES.AUTH}?redirect=${pathname}&immediate=true`);
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
{!verifiedEmail ? (
|
||||
<Button requiresAuth button="primary" label={__('Start Syncing')} />
|
||||
<div>
|
||||
<Button requiresAuth button="primary" label={__('Add Email')} />
|
||||
<p className="help">{__('An email address is required to sync your account.')}</p>
|
||||
</div>
|
||||
) : (
|
||||
<FormField
|
||||
type="checkbox"
|
||||
|
@ -33,4 +52,4 @@ function SyncToggle(props: Props) {
|
|||
);
|
||||
}
|
||||
|
||||
export default SyncToggle;
|
||||
export default withRouter(SyncToggle);
|
||||
|
|
|
@ -56,6 +56,8 @@ function UserSignIn(props: Props) {
|
|||
const { search } = location;
|
||||
const urlParams = new URLSearchParams(search);
|
||||
const redirect = urlParams.get('redirect');
|
||||
const shouldRedirectImmediately = urlParams.get('immediate');
|
||||
const [initialSignInStep, setInitialSignInStep] = React.useState();
|
||||
const hasVerifiedEmail = user && user.has_verified_email;
|
||||
const rewardsApproved = user && user.is_reward_approved;
|
||||
const hasFetchedReward = useFetched(claimingReward);
|
||||
|
@ -80,7 +82,7 @@ function UserSignIn(props: Props) {
|
|||
const showEmail = !emailToVerify && !hasVerifiedEmail;
|
||||
const showEmailVerification = emailToVerify && !hasVerifiedEmail;
|
||||
const showUserVerification = hasVerifiedEmail && !rewardsApproved;
|
||||
const showSyncPassword = syncEnabled && getSyncError && !hasSynced;
|
||||
const showSyncPassword = syncEnabled && getSyncError;
|
||||
const showChannelCreation =
|
||||
hasVerifiedEmail &&
|
||||
balance !== undefined &&
|
||||
|
@ -111,7 +113,7 @@ function UserSignIn(props: Props) {
|
|||
const SIGN_IN_FLOW = [
|
||||
showEmail && <UserEmailNew />,
|
||||
showEmailVerification && <UserEmailVerify />,
|
||||
showUserVerification && <UserVerify />,
|
||||
showUserVerification && <UserVerify skipLink={redirect} />,
|
||||
showChannelCreation && <UserFirstChannel />,
|
||||
// @if TARGET='app'
|
||||
showYoutubeTransfer && (
|
||||
|
@ -132,6 +134,17 @@ function UserSignIn(props: Props) {
|
|||
for (var i = SIGN_IN_FLOW.length - 1; i > -1; i--) {
|
||||
const Component = SIGN_IN_FLOW[i];
|
||||
if (Component) {
|
||||
// If we want to redirect immediately,
|
||||
// remember the first step so we can redirect once a new step has been reached
|
||||
// Ignore the loading step
|
||||
if (redirect && shouldRedirectImmediately) {
|
||||
if (!initialSignInStep) {
|
||||
setInitialSignInStep(i);
|
||||
} else if (i !== initialSignInStep && i !== SIGN_IN_FLOW.length - 1) {
|
||||
history.replace(redirect);
|
||||
}
|
||||
}
|
||||
|
||||
return Component;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ type Props = {
|
|||
verifyUserIdentity: string => void,
|
||||
verifyPhone: () => void,
|
||||
fetchUser: () => void,
|
||||
skipLink?: string,
|
||||
};
|
||||
|
||||
class UserVerify extends React.PureComponent<Props> {
|
||||
|
@ -26,7 +27,7 @@ class UserVerify extends React.PureComponent<Props> {
|
|||
}
|
||||
|
||||
render() {
|
||||
const { errorMessage, isPending, verifyPhone, fetchUser } = this.props;
|
||||
const { errorMessage, isPending, verifyPhone, fetchUser, skipLink } = this.props;
|
||||
return (
|
||||
<React.Fragment>
|
||||
<section className="section__header">
|
||||
|
@ -36,7 +37,7 @@ class UserVerify extends React.PureComponent<Props> {
|
|||
"We weren't able to auto-approve you for rewards. Please complete one of the steps below to unlock them."
|
||||
)}{' '}
|
||||
<Button onClick={() => fetchUser()} button="link" label={__('Refresh')} /> {'or'}{' '}
|
||||
<Button navigate="/" button="link" label={__('Skip')} />
|
||||
<Button navigate={skipLink || '/'} button="link" label={__('Skip')} />.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
|
|
|
@ -13,7 +13,6 @@ export const PHONE_COLLECTION = 'phone_collection';
|
|||
export const FIRST_REWARD = 'first_reward';
|
||||
export const AUTHENTICATION_FAILURE = 'auth_failure';
|
||||
export const TRANSACTION_FAILED = 'transaction_failed';
|
||||
export const REWARD_APPROVAL_REQUIRED = 'reward_approval_required';
|
||||
export const REWARD_GENERATED_CODE = 'reward_generated_code';
|
||||
export const AFFIRM_PURCHASE = 'affirm_purchase';
|
||||
export const CONFIRM_CLAIM_REVOKE = 'confirm_claim_revoke';
|
||||
|
|
|
@ -125,12 +125,8 @@ rewards.setCallback('claimFirstRewardSuccess', () => {
|
|||
app.store.dispatch(doOpenModal(MODALS.FIRST_REWARD));
|
||||
});
|
||||
|
||||
rewards.setCallback('rewardApprovalRequired', () => {
|
||||
app.store.dispatch(doOpenModal(MODALS.REWARD_APPROVAL_REQUIRED));
|
||||
});
|
||||
|
||||
rewards.setCallback('claimRewardSuccess', () => {
|
||||
app.store.dispatch(doHideModal(MODALS.REWARD_APPROVAL_REQUIRED));
|
||||
app.store.dispatch(doHideModal());
|
||||
});
|
||||
|
||||
// @if TARGET='app'
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
import * as PAGES from 'constants/pages';
|
||||
import { connect } from 'react-redux';
|
||||
import { doHideModal } from 'redux/actions/app';
|
||||
import { withRouter } from 'react-router-dom';
|
||||
import ModalRewardApprovalRequired from './view';
|
||||
|
||||
const perform = (dispatch, ownProps) => ({
|
||||
doAuth: () => {
|
||||
const {
|
||||
location: { pathname },
|
||||
history,
|
||||
} = ownProps;
|
||||
const currentPath = pathname.split('/$/')[1];
|
||||
dispatch(doHideModal());
|
||||
history.push(`/$/${PAGES.AUTH}?redirect=${currentPath}`);
|
||||
},
|
||||
closeModal: () => dispatch(doHideModal()),
|
||||
});
|
||||
|
||||
export default withRouter(
|
||||
connect(
|
||||
null,
|
||||
perform
|
||||
)(ModalRewardApprovalRequired)
|
||||
);
|
|
@ -1,35 +0,0 @@
|
|||
// @flow
|
||||
import React from 'react';
|
||||
import { Modal } from 'modal/modal';
|
||||
|
||||
type Props = {
|
||||
closeModal: () => void,
|
||||
doAuth: () => void,
|
||||
};
|
||||
|
||||
class ModalRewardApprovalRequired extends React.PureComponent<Props> {
|
||||
render() {
|
||||
const { closeModal, doAuth } = this.props;
|
||||
|
||||
return (
|
||||
<Modal
|
||||
isOpen
|
||||
title={__('Hmm. Are you real?')}
|
||||
contentLabel={__('Human Verification Required')}
|
||||
onConfirmed={doAuth}
|
||||
onAborted={closeModal}
|
||||
type="confirm"
|
||||
confirmButtonLabel={__("I'm Totally Real")}
|
||||
abortButtonLabel={__('Never Mind')}
|
||||
>
|
||||
<p>
|
||||
{__(
|
||||
"Before we can give you any credits, we need to perform a brief check to make sure you're a new and unique person."
|
||||
)}
|
||||
</p>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default ModalRewardApprovalRequired;
|
|
@ -8,7 +8,6 @@ import ModalAutoUpdateDownloaded from 'modal/modalAutoUpdateDownloaded';
|
|||
import ModalUpgrade from 'modal/modalUpgrade';
|
||||
import ModalWelcome from 'modal/modalWelcome';
|
||||
import ModalFirstReward from 'modal/modalFirstReward';
|
||||
import ModalRewardApprovalRequired from 'modal/modalRewardApprovalRequired';
|
||||
import ModalRemoveFile from 'modal/modalRemoveFile';
|
||||
import ModalTransactionFailed from 'modal/modalTransactionFailed';
|
||||
import ModalFileTimeout from 'modal/modalFileTimeout';
|
||||
|
@ -65,8 +64,6 @@ function ModalRouter(props: Props) {
|
|||
return <ModalFirstReward {...modalProps} />;
|
||||
case MODALS.TRANSACTION_FAILED:
|
||||
return <ModalTransactionFailed {...modalProps} />;
|
||||
case MODALS.REWARD_APPROVAL_REQUIRED:
|
||||
return <ModalRewardApprovalRequired {...modalProps} />;
|
||||
case MODALS.CONFIRM_FILE_REMOVE:
|
||||
return <ModalRemoveFile {...modalProps} />;
|
||||
case MODALS.AFFIRM_PURCHASE:
|
||||
|
|
|
@ -11,7 +11,7 @@ const select = state => ({
|
|||
});
|
||||
|
||||
const perform = (dispatch, ownProps) => ({
|
||||
doAuth: () => ownProps.history.push(`/$/${PAGES.AUTH}?redirect=help`),
|
||||
doAuth: () => ownProps.history.push(`/$/${PAGES.AUTH}?redirect=/$/${PAGES.HELP}`),
|
||||
fetchAccessToken: () => dispatch(doFetchAccessToken()),
|
||||
});
|
||||
|
||||
|
|
|
@ -90,7 +90,6 @@ class SettingsPage extends React.PureComponent<Props, State> {
|
|||
(this: any).onInstantPurchaseMaxChange = this.onInstantPurchaseMaxChange.bind(this);
|
||||
(this: any).onThemeChange = this.onThemeChange.bind(this);
|
||||
(this: any).onAutomaticDarkModeChange = this.onAutomaticDarkModeChange.bind(this);
|
||||
(this: any).clearCache = this.clearCache.bind(this);
|
||||
(this: any).onChangeTime = this.onChangeTime.bind(this);
|
||||
(this: any).onConfirmForgetPassword = this.onConfirmForgetPassword.bind(this);
|
||||
}
|
||||
|
@ -175,19 +174,6 @@ class SettingsPage extends React.PureComponent<Props, State> {
|
|||
this.props.setDaemonSetting(name, value);
|
||||
}
|
||||
|
||||
clearCache() {
|
||||
this.setState({
|
||||
clearingCache: true,
|
||||
});
|
||||
const success = () => {
|
||||
this.setState({ clearingCache: false });
|
||||
window.location.reload();
|
||||
};
|
||||
const clear = () => this.props.clearCache().then(success);
|
||||
|
||||
setTimeout(clear, 1000, { once: true });
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
daemonSettings,
|
||||
|
@ -210,6 +196,7 @@ class SettingsPage extends React.PureComponent<Props, State> {
|
|||
floatingPlayer,
|
||||
clearPlayingUri,
|
||||
darkModeTimes,
|
||||
clearCache,
|
||||
} = this.props;
|
||||
|
||||
const noDaemonSettings = !daemonSettings || Object.keys(daemonSettings).length === 0;
|
||||
|
@ -651,7 +638,7 @@ class SettingsPage extends React.PureComponent<Props, State> {
|
|||
<Button
|
||||
button="inverse"
|
||||
label={this.state.clearingCache ? __('Clearing') : __('Clear Cache')}
|
||||
onClick={this.clearCache}
|
||||
onClick={clearCache}
|
||||
disabled={this.state.clearingCache}
|
||||
/>
|
||||
}
|
||||
|
|
|
@ -2,14 +2,16 @@ import { ipcRenderer } from 'electron';
|
|||
|
||||
let sessionPassword;
|
||||
|
||||
export const setSavedPassword = value => {
|
||||
export const setSavedPassword = (value, saveToDisk) => {
|
||||
return new Promise(resolve => {
|
||||
ipcRenderer.once('set-password-response', (event, success) => {
|
||||
resolve(success);
|
||||
});
|
||||
|
||||
sessionPassword = value;
|
||||
if (saveToDisk && value) {
|
||||
ipcRenderer.send('set-password', value);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -6870,17 +6870,17 @@ lazy-val@^1.0.3, lazy-val@^1.0.4:
|
|||
yargs "^13.2.2"
|
||||
zstd-codec "^0.1.1"
|
||||
|
||||
lbry-redux@lbryio/lbry-redux#0090f195eb88f4620db7d038f7b01eaa76119836:
|
||||
lbry-redux@lbryio/lbry-redux#b09e1699eb92fef8087986a0f35b3df3977af87f:
|
||||
version "0.0.1"
|
||||
resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/0090f195eb88f4620db7d038f7b01eaa76119836"
|
||||
resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/b09e1699eb92fef8087986a0f35b3df3977af87f"
|
||||
dependencies:
|
||||
proxy-polyfill "0.1.6"
|
||||
reselect "^3.0.0"
|
||||
uuid "^3.3.2"
|
||||
|
||||
lbryinc@lbryio/lbryinc#b8e1708ee4491db342c81576265e1b58f542bedb:
|
||||
lbryinc@lbryio/lbryinc#fb2e73ab31c2b9f80a53f082843a01e3f213ca45:
|
||||
version "0.0.1"
|
||||
resolved "https://codeload.github.com/lbryio/lbryinc/tar.gz/b8e1708ee4491db342c81576265e1b58f542bedb"
|
||||
resolved "https://codeload.github.com/lbryio/lbryinc/tar.gz/fb2e73ab31c2b9f80a53f082843a01e3f213ca45"
|
||||
dependencies:
|
||||
reselect "^3.0.0"
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue