mirror of
https://github.com/LBRYFoundation/lbry-desktop.git
synced 2025-08-23 17:47:24 +00:00
first run cleanup + sync first run acknowledgements
This commit is contained in:
parent
19fb7d7f06
commit
61b1ca89d3
9 changed files with 111 additions and 25 deletions
|
@ -41,7 +41,7 @@ function UserChannelFollowIntro(props: Props) {
|
||||||
)}
|
)}
|
||||||
actions={
|
actions={
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<div className="section__actions">
|
<div className="section__actions--between">
|
||||||
<Button button="secondary" onClick={onBack} label={__('Back')} />
|
<Button button="secondary" onClick={onBack} label={__('Back')} />
|
||||||
<Button
|
<Button
|
||||||
button="primary"
|
button="primary"
|
||||||
|
|
|
@ -2,6 +2,7 @@ import REWARD_TYPES from 'rewards';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { selectGetSyncIsPending, selectSyncHash } from 'lbryinc';
|
import { selectGetSyncIsPending, selectSyncHash } from 'lbryinc';
|
||||||
import { doClaimRewardType } from 'redux/actions/rewards';
|
import { doClaimRewardType } from 'redux/actions/rewards';
|
||||||
|
import { doSyncClientSettings, doSetClientSetting } from 'redux/actions/settings';
|
||||||
import { selectClaimedRewards, makeSelectIsRewardClaimPending } from 'redux/selectors/rewards';
|
import { selectClaimedRewards, makeSelectIsRewardClaimPending } from 'redux/selectors/rewards';
|
||||||
import { doUserFetch } from 'redux/actions/user';
|
import { doUserFetch } from 'redux/actions/user';
|
||||||
import {
|
import {
|
||||||
|
@ -35,6 +36,9 @@ const select = state => ({
|
||||||
youtubeChannels: selectYoutubeChannels(state),
|
youtubeChannels: selectYoutubeChannels(state),
|
||||||
userFetchPending: selectUserIsPending(state),
|
userFetchPending: selectUserIsPending(state),
|
||||||
syncEnabled: makeSelectClientSetting(SETTINGS.ENABLE_SYNC)(state),
|
syncEnabled: makeSelectClientSetting(SETTINGS.ENABLE_SYNC)(state),
|
||||||
|
followingAcknowledged: makeSelectClientSetting(SETTINGS.FOLLOWING_ACKNOWLEDGED)(state),
|
||||||
|
tagsAcknowledged: makeSelectClientSetting(SETTINGS.TAGS_ACKNOWLEDGED)(state),
|
||||||
|
rewardsAcknowledged: makeSelectClientSetting(SETTINGS.REWARDS_ACKNOWLEDGED)(state),
|
||||||
syncingWallet: selectGetSyncIsPending(state),
|
syncingWallet: selectGetSyncIsPending(state),
|
||||||
hasSynced: Boolean(selectSyncHash(state)),
|
hasSynced: Boolean(selectSyncHash(state)),
|
||||||
creatingChannel: selectCreatingChannel(state),
|
creatingChannel: selectCreatingChannel(state),
|
||||||
|
@ -48,6 +52,8 @@ const perform = dispatch => ({
|
||||||
notifyError: false,
|
notifyError: false,
|
||||||
})
|
})
|
||||||
),
|
),
|
||||||
|
syncSettings: () => dispatch(doSyncClientSettings()),
|
||||||
|
setClientSetting: (setting, value) => dispatch(doSetClientSetting(setting, value)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(select, perform)(UserSignIn);
|
export default connect(select, perform)(UserSignIn);
|
||||||
|
|
|
@ -9,12 +9,12 @@ import UserChannelFollowIntro from 'component/userChannelFollowIntro';
|
||||||
import UserTagFollowIntro from 'component/userTagFollowIntro';
|
import UserTagFollowIntro from 'component/userTagFollowIntro';
|
||||||
import { DEFAULT_BID_FOR_FIRST_CHANNEL } from 'component/userFirstChannel/view';
|
import { DEFAULT_BID_FOR_FIRST_CHANNEL } from 'component/userFirstChannel/view';
|
||||||
import { YOUTUBE_STATUSES } from 'lbryinc';
|
import { YOUTUBE_STATUSES } from 'lbryinc';
|
||||||
|
import { SETTINGS } from 'lbry-redux';
|
||||||
import REWARDS from 'rewards';
|
import REWARDS from 'rewards';
|
||||||
import UserVerify from 'component/userVerify';
|
import UserVerify from 'component/userVerify';
|
||||||
import Spinner from 'component/spinner';
|
import Spinner from 'component/spinner';
|
||||||
import YoutubeTransferStatus from 'component/youtubeTransferStatus';
|
import YoutubeTransferStatus from 'component/youtubeTransferStatus';
|
||||||
import useFetched from 'effects/use-fetched';
|
import useFetched from 'effects/use-fetched';
|
||||||
import usePersistedState from 'effects/use-persisted-state';
|
|
||||||
import Confetti from 'react-confetti';
|
import Confetti from 'react-confetti';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
@ -34,6 +34,11 @@ type Props = {
|
||||||
hasSynced: boolean,
|
hasSynced: boolean,
|
||||||
syncingWallet: boolean,
|
syncingWallet: boolean,
|
||||||
creatingChannel: boolean,
|
creatingChannel: boolean,
|
||||||
|
syncSettings: () => void,
|
||||||
|
setClientSetting: (string, boolean) => void,
|
||||||
|
followingAcknowledged: boolean,
|
||||||
|
tagsAcknowledged: boolean,
|
||||||
|
rewardsAcknowledged: boolean,
|
||||||
};
|
};
|
||||||
|
|
||||||
function UserSignIn(props: Props) {
|
function UserSignIn(props: Props) {
|
||||||
|
@ -54,6 +59,11 @@ function UserSignIn(props: Props) {
|
||||||
hasSynced,
|
hasSynced,
|
||||||
fetchingChannels,
|
fetchingChannels,
|
||||||
creatingChannel,
|
creatingChannel,
|
||||||
|
followingAcknowledged,
|
||||||
|
tagsAcknowledged,
|
||||||
|
rewardsAcknowledged,
|
||||||
|
syncSettings,
|
||||||
|
setClientSetting,
|
||||||
} = props;
|
} = props;
|
||||||
const { search } = location;
|
const { search } = location;
|
||||||
const urlParams = new URLSearchParams(search);
|
const urlParams = new URLSearchParams(search);
|
||||||
|
@ -61,9 +71,6 @@ function UserSignIn(props: Props) {
|
||||||
const step = urlParams.get('step');
|
const step = urlParams.get('step');
|
||||||
const shouldRedirectImmediately = urlParams.get('immediate');
|
const shouldRedirectImmediately = urlParams.get('immediate');
|
||||||
const [initialSignInStep, setInitialSignInStep] = React.useState();
|
const [initialSignInStep, setInitialSignInStep] = React.useState();
|
||||||
const [hasSeenFollowList, setHasSeenFollowList] = usePersistedState('channel-follow-intro', false);
|
|
||||||
const [hasSkippedRewards, setHasSkippedRewards] = usePersistedState('skip-rewards-intro', false);
|
|
||||||
const [hasSeenTagsList, setHasSeenTagsList] = usePersistedState('channel-follow-intro', false);
|
|
||||||
const hasVerifiedEmail = user && user.has_verified_email;
|
const hasVerifiedEmail = user && user.has_verified_email;
|
||||||
const rewardsApproved = user && user.is_reward_approved;
|
const rewardsApproved = user && user.is_reward_approved;
|
||||||
const isIdentityVerified = user && user.is_identity_verified;
|
const isIdentityVerified = user && user.is_identity_verified;
|
||||||
|
@ -84,7 +91,8 @@ function UserSignIn(props: Props) {
|
||||||
// The possible screens for the sign in flow
|
// The possible screens for the sign in flow
|
||||||
const showEmail = !hasVerifiedEmail;
|
const showEmail = !hasVerifiedEmail;
|
||||||
const showEmailVerification = (emailToVerify && !hasVerifiedEmail) || (!hasVerifiedEmail && passwordSet);
|
const showEmailVerification = (emailToVerify && !hasVerifiedEmail) || (!hasVerifiedEmail && passwordSet);
|
||||||
const showUserVerification = hasVerifiedEmail && !rewardsApproved && !isIdentityVerified && !hasSkippedRewards;
|
const showUserVerification = hasVerifiedEmail && !rewardsApproved && !isIdentityVerified && !rewardsAcknowledged;
|
||||||
|
const showSyncPassword = syncEnabled && getSyncError;
|
||||||
const showChannelCreation =
|
const showChannelCreation =
|
||||||
hasVerifiedEmail &&
|
hasVerifiedEmail &&
|
||||||
balance !== undefined &&
|
balance !== undefined &&
|
||||||
|
@ -93,9 +101,9 @@ function UserSignIn(props: Props) {
|
||||||
channelCount === 0 &&
|
channelCount === 0 &&
|
||||||
!hasYoutubeChannels;
|
!hasYoutubeChannels;
|
||||||
const showYoutubeTransfer = hasVerifiedEmail && hasYoutubeChannels && !isYoutubeTransferComplete;
|
const showYoutubeTransfer = hasVerifiedEmail && hasYoutubeChannels && !isYoutubeTransferComplete;
|
||||||
const showFollowIntro = step === 'channels' || (hasVerifiedEmail && !hasSeenFollowList);
|
const showFollowIntro = step === 'channels' || (hasVerifiedEmail && !followingAcknowledged);
|
||||||
const showTagsIntro = step === 'tags' || (hasVerifiedEmail && !hasSeenTagsList);
|
const showTagsIntro = step === 'tags' || (hasVerifiedEmail && !tagsAcknowledged);
|
||||||
const canHijackSignInFlowWithSpinner = hasVerifiedEmail && !showFollowIntro;
|
const canHijackSignInFlowWithSpinner = hasVerifiedEmail && !getSyncError && !showFollowIntro;
|
||||||
const isCurrentlyFetchingSomething = fetchingChannels || claimingReward || syncingWallet || creatingChannel;
|
const isCurrentlyFetchingSomething = fetchingChannels || claimingReward || syncingWallet || creatingChannel;
|
||||||
const isWaitingForSomethingToFinish =
|
const isWaitingForSomethingToFinish =
|
||||||
// If the user has claimed the email award, we need to wait until the balance updates sometime in the future
|
// If the user has claimed the email award, we need to wait until the balance updates sometime in the future
|
||||||
|
@ -103,6 +111,11 @@ function UserSignIn(props: Props) {
|
||||||
const showLoadingSpinner =
|
const showLoadingSpinner =
|
||||||
canHijackSignInFlowWithSpinner && (isCurrentlyFetchingSomething || isWaitingForSomethingToFinish);
|
canHijackSignInFlowWithSpinner && (isCurrentlyFetchingSomething || isWaitingForSomethingToFinish);
|
||||||
|
|
||||||
|
function setSettingAndSync(setting, value) {
|
||||||
|
setClientSetting(setting, value);
|
||||||
|
syncSettings();
|
||||||
|
}
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
fetchUser();
|
fetchUser();
|
||||||
}, [fetchUser]);
|
}, [fetchUser]);
|
||||||
|
@ -122,7 +135,13 @@ function UserSignIn(props: Props) {
|
||||||
const SIGN_IN_FLOW = [
|
const SIGN_IN_FLOW = [
|
||||||
showEmail && <UserEmailNew />,
|
showEmail && <UserEmailNew />,
|
||||||
showEmailVerification && <UserEmailVerify />,
|
showEmailVerification && <UserEmailVerify />,
|
||||||
showUserVerification && <UserVerify onSkip={() => setHasSkippedRewards(true)} />,
|
showUserVerification && (
|
||||||
|
<UserVerify
|
||||||
|
onSkip={() => {
|
||||||
|
setSettingAndSync(SETTINGS.REWARDS_ACKNOWLEDGED, true);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
),
|
||||||
showChannelCreation && <UserFirstChannel />,
|
showChannelCreation && <UserFirstChannel />,
|
||||||
showFollowIntro && (
|
showFollowIntro && (
|
||||||
<UserChannelFollowIntro
|
<UserChannelFollowIntro
|
||||||
|
@ -136,7 +155,7 @@ function UserSignIn(props: Props) {
|
||||||
}
|
}
|
||||||
|
|
||||||
history.replace(url);
|
history.replace(url);
|
||||||
setHasSeenFollowList(true);
|
setSettingAndSync(SETTINGS.FOLLOWING_ACKNOWLEDGED, true);
|
||||||
}}
|
}}
|
||||||
onBack={() => {
|
onBack={() => {
|
||||||
let url = `/$/${PAGES.AUTH}?reset_scroll=1&step=tags`;
|
let url = `/$/${PAGES.AUTH}?reset_scroll=1&step=tags`;
|
||||||
|
@ -148,7 +167,7 @@ function UserSignIn(props: Props) {
|
||||||
}
|
}
|
||||||
|
|
||||||
history.replace(url);
|
history.replace(url);
|
||||||
setHasSeenFollowList(false);
|
setSettingAndSync(SETTINGS.FOLLOWING_ACKNOWLEDGED, false);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
|
@ -164,7 +183,7 @@ function UserSignIn(props: Props) {
|
||||||
}
|
}
|
||||||
|
|
||||||
history.replace(url);
|
history.replace(url);
|
||||||
setHasSeenTagsList(true);
|
setSettingAndSync(SETTINGS.TAGS_ACKNOWLEDGED, true);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
|
|
|
@ -12,7 +12,7 @@ type Props = {
|
||||||
followedTags: Array<Tag>,
|
followedTags: Array<Tag>,
|
||||||
};
|
};
|
||||||
|
|
||||||
function UserChannelFollowIntro(props: Props) {
|
function UserTagFollowIntro(props: Props) {
|
||||||
const { onContinue, followedTags } = props;
|
const { onContinue, followedTags } = props;
|
||||||
const followingCount = (followedTags && followedTags.length) || 0;
|
const followingCount = (followedTags && followedTags.length) || 0;
|
||||||
|
|
||||||
|
@ -23,7 +23,8 @@ function UserChannelFollowIntro(props: Props) {
|
||||||
actions={
|
actions={
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<Form onSubmit={onContinue}>
|
<Form onSubmit={onContinue}>
|
||||||
<div className="section__actions">
|
<div className="section__actions--between">
|
||||||
|
<span />
|
||||||
<Button
|
<Button
|
||||||
button="primary"
|
button="primary"
|
||||||
type="Submit"
|
type="Submit"
|
||||||
|
@ -54,4 +55,4 @@ function UserChannelFollowIntro(props: Props) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default UserChannelFollowIntro;
|
export default UserTagFollowIntro;
|
||||||
|
|
|
@ -35,7 +35,7 @@ class UserVerify extends React.PureComponent<Props> {
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<div className="main__auth-content">
|
||||||
<section className="section__header">
|
<section className="section__header">
|
||||||
<h1 className="section__title--large">{__('Get Validated')}</h1>
|
<h1 className="section__title--large">{__('Get Validated')}</h1>
|
||||||
<p>
|
<p>
|
||||||
|
@ -141,7 +141,7 @@ class UserVerify extends React.PureComponent<Props> {
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</React.Fragment>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,8 @@ const defaultState = {
|
||||||
clientSettings: {
|
clientSettings: {
|
||||||
// UX
|
// UX
|
||||||
[SETTINGS.EMAIL_COLLECTION_ACKNOWLEDGED]: false,
|
[SETTINGS.EMAIL_COLLECTION_ACKNOWLEDGED]: false,
|
||||||
|
[SETTINGS.FOLLOWING_ACKNOWLEDGED]: false,
|
||||||
|
[SETTINGS.TAGS_ACKNOWLEDGED]: false,
|
||||||
[SETTINGS.ENABLE_SYNC]: IS_WEB,
|
[SETTINGS.ENABLE_SYNC]: IS_WEB,
|
||||||
|
|
||||||
// UI
|
// UI
|
||||||
|
|
|
@ -5,9 +5,15 @@
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
border: 1px solid var(--color-border);
|
border: 1px solid var(--color-border);
|
||||||
|
|
||||||
@media (max-width: $breakpoint-small) {
|
~ .card {
|
||||||
margin-bottom: var(--spacing-m);
|
margin-bottom: var(--spacing-m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: $breakpoint-small) {
|
||||||
|
~ .card {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.card--disabled {
|
.card--disabled {
|
||||||
|
|
|
@ -108,9 +108,49 @@
|
||||||
.main--auth-page {
|
.main--auth-page {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 70rem;
|
max-width: 70rem;
|
||||||
margin-top: var(--spacing-main-padding);
|
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
|
padding: 0 var(--spacing-s);
|
||||||
|
|
||||||
|
@media (min-width: $breakpoint-small) {
|
||||||
|
margin-top: var(--spacing-main-padding);
|
||||||
|
padding: 0 var(--spacing-l);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.main__auth-content {
|
||||||
|
display: flex;
|
||||||
|
position: relative;
|
||||||
|
flex-direction: column;
|
||||||
|
padding-bottom: var(--spacing-xl);
|
||||||
|
|
||||||
|
@media (min-width: $breakpoint-small) {
|
||||||
|
flex-direction: row;
|
||||||
|
|
||||||
|
> :first-child {
|
||||||
|
position: fixed;
|
||||||
|
background-color: var(--color-background);
|
||||||
|
width: calc(40% - var(--spacing-l));
|
||||||
|
margin-top: var(--spacing-xl);
|
||||||
|
}
|
||||||
|
|
||||||
|
> :nth-child(2) {
|
||||||
|
width: 50%;
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: $breakpoint-medium) {
|
||||||
|
> :first-child {
|
||||||
|
width: calc(30% - var(--spacing-l));
|
||||||
|
max-width: 25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
> :nth-child(2) {
|
||||||
|
width: 50%;
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.main--buy {
|
.main--buy {
|
||||||
|
@ -163,7 +203,7 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
max-width: 50rem;
|
max-width: 60rem;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
|
|
||||||
& > * {
|
& > * {
|
||||||
|
|
|
@ -51,6 +51,7 @@
|
||||||
margin-right: var(--spacing-m);
|
margin-right: var(--spacing-m);
|
||||||
font-weight: var(--font-weight-bold);
|
font-weight: var(--font-weight-bold);
|
||||||
font-size: var(--font-heading);
|
font-size: var(--font-heading);
|
||||||
|
margin-bottom: var(--spacing-l);
|
||||||
|
|
||||||
@media (max-width: $breakpoint-small) {
|
@media (max-width: $breakpoint-small) {
|
||||||
font-size: var(--font-title);
|
font-size: var(--font-title);
|
||||||
|
@ -71,10 +72,12 @@
|
||||||
|
|
||||||
.section__divider {
|
.section__divider {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
margin: var(--spacing-l) 0;
|
margin: var(--spacing-xl) 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
|
@ -83,10 +86,10 @@
|
||||||
font-size: var(--font-large);
|
font-size: var(--font-large);
|
||||||
font-weight: var(--font-weight-base);
|
font-weight: var(--font-weight-base);
|
||||||
background-color: var(--color-background);
|
background-color: var(--color-background);
|
||||||
transform: translateY(-150%);
|
position: absolute;
|
||||||
|
height: var(--spacing-xl);
|
||||||
|
top: calc(var(--spacing-xl) / 2 + 10px);
|
||||||
padding: 0 var(--spacing-l);
|
padding: 0 var(--spacing-l);
|
||||||
display: inline-block;
|
|
||||||
margin: auto;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,6 +151,15 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.section__actions--between {
|
||||||
|
@extend .section__actions;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
@media (max-width: $breakpoint-small) {
|
||||||
|
justify-content: flex-start;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.section__actions--no-margin {
|
.section__actions--no-margin {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue