first run cleanup + sync first run acknowledgements

This commit is contained in:
Sean Yesmunt 2020-08-24 00:00:10 -04:00
parent 19fb7d7f06
commit 61b1ca89d3
9 changed files with 111 additions and 25 deletions

View file

@ -41,7 +41,7 @@ function UserChannelFollowIntro(props: Props) {
)}
actions={
<React.Fragment>
<div className="section__actions">
<div className="section__actions--between">
<Button button="secondary" onClick={onBack} label={__('Back')} />
<Button
button="primary"

View file

@ -2,6 +2,7 @@ import REWARD_TYPES from 'rewards';
import { connect } from 'react-redux';
import { selectGetSyncIsPending, selectSyncHash } from 'lbryinc';
import { doClaimRewardType } from 'redux/actions/rewards';
import { doSyncClientSettings, doSetClientSetting } from 'redux/actions/settings';
import { selectClaimedRewards, makeSelectIsRewardClaimPending } from 'redux/selectors/rewards';
import { doUserFetch } from 'redux/actions/user';
import {
@ -35,6 +36,9 @@ const select = state => ({
youtubeChannels: selectYoutubeChannels(state),
userFetchPending: selectUserIsPending(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),
hasSynced: Boolean(selectSyncHash(state)),
creatingChannel: selectCreatingChannel(state),
@ -48,6 +52,8 @@ const perform = dispatch => ({
notifyError: false,
})
),
syncSettings: () => dispatch(doSyncClientSettings()),
setClientSetting: (setting, value) => dispatch(doSetClientSetting(setting, value)),
});
export default connect(select, perform)(UserSignIn);

View file

@ -9,12 +9,12 @@ import UserChannelFollowIntro from 'component/userChannelFollowIntro';
import UserTagFollowIntro from 'component/userTagFollowIntro';
import { DEFAULT_BID_FOR_FIRST_CHANNEL } from 'component/userFirstChannel/view';
import { YOUTUBE_STATUSES } from 'lbryinc';
import { SETTINGS } from 'lbry-redux';
import REWARDS from 'rewards';
import UserVerify from 'component/userVerify';
import Spinner from 'component/spinner';
import YoutubeTransferStatus from 'component/youtubeTransferStatus';
import useFetched from 'effects/use-fetched';
import usePersistedState from 'effects/use-persisted-state';
import Confetti from 'react-confetti';
type Props = {
@ -34,6 +34,11 @@ type Props = {
hasSynced: boolean,
syncingWallet: boolean,
creatingChannel: boolean,
syncSettings: () => void,
setClientSetting: (string, boolean) => void,
followingAcknowledged: boolean,
tagsAcknowledged: boolean,
rewardsAcknowledged: boolean,
};
function UserSignIn(props: Props) {
@ -54,6 +59,11 @@ function UserSignIn(props: Props) {
hasSynced,
fetchingChannels,
creatingChannel,
followingAcknowledged,
tagsAcknowledged,
rewardsAcknowledged,
syncSettings,
setClientSetting,
} = props;
const { search } = location;
const urlParams = new URLSearchParams(search);
@ -61,9 +71,6 @@ function UserSignIn(props: Props) {
const step = urlParams.get('step');
const shouldRedirectImmediately = urlParams.get('immediate');
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 rewardsApproved = user && user.is_reward_approved;
const isIdentityVerified = user && user.is_identity_verified;
@ -84,7 +91,8 @@ function UserSignIn(props: Props) {
// The possible screens for the sign in flow
const showEmail = !hasVerifiedEmail;
const showEmailVerification = (emailToVerify && !hasVerifiedEmail) || (!hasVerifiedEmail && passwordSet);
const showUserVerification = hasVerifiedEmail && !rewardsApproved && !isIdentityVerified && !hasSkippedRewards;
const showUserVerification = hasVerifiedEmail && !rewardsApproved && !isIdentityVerified && !rewardsAcknowledged;
const showSyncPassword = syncEnabled && getSyncError;
const showChannelCreation =
hasVerifiedEmail &&
balance !== undefined &&
@ -93,9 +101,9 @@ function UserSignIn(props: Props) {
channelCount === 0 &&
!hasYoutubeChannels;
const showYoutubeTransfer = hasVerifiedEmail && hasYoutubeChannels && !isYoutubeTransferComplete;
const showFollowIntro = step === 'channels' || (hasVerifiedEmail && !hasSeenFollowList);
const showTagsIntro = step === 'tags' || (hasVerifiedEmail && !hasSeenTagsList);
const canHijackSignInFlowWithSpinner = hasVerifiedEmail && !showFollowIntro;
const showFollowIntro = step === 'channels' || (hasVerifiedEmail && !followingAcknowledged);
const showTagsIntro = step === 'tags' || (hasVerifiedEmail && !tagsAcknowledged);
const canHijackSignInFlowWithSpinner = hasVerifiedEmail && !getSyncError && !showFollowIntro;
const isCurrentlyFetchingSomething = fetchingChannels || claimingReward || syncingWallet || creatingChannel;
const isWaitingForSomethingToFinish =
// 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 =
canHijackSignInFlowWithSpinner && (isCurrentlyFetchingSomething || isWaitingForSomethingToFinish);
function setSettingAndSync(setting, value) {
setClientSetting(setting, value);
syncSettings();
}
React.useEffect(() => {
fetchUser();
}, [fetchUser]);
@ -122,7 +135,13 @@ function UserSignIn(props: Props) {
const SIGN_IN_FLOW = [
showEmail && <UserEmailNew />,
showEmailVerification && <UserEmailVerify />,
showUserVerification && <UserVerify onSkip={() => setHasSkippedRewards(true)} />,
showUserVerification && (
<UserVerify
onSkip={() => {
setSettingAndSync(SETTINGS.REWARDS_ACKNOWLEDGED, true);
}}
/>
),
showChannelCreation && <UserFirstChannel />,
showFollowIntro && (
<UserChannelFollowIntro
@ -136,7 +155,7 @@ function UserSignIn(props: Props) {
}
history.replace(url);
setHasSeenFollowList(true);
setSettingAndSync(SETTINGS.FOLLOWING_ACKNOWLEDGED, true);
}}
onBack={() => {
let url = `/$/${PAGES.AUTH}?reset_scroll=1&step=tags`;
@ -148,7 +167,7 @@ function UserSignIn(props: Props) {
}
history.replace(url);
setHasSeenFollowList(false);
setSettingAndSync(SETTINGS.FOLLOWING_ACKNOWLEDGED, false);
}}
/>
),
@ -164,7 +183,7 @@ function UserSignIn(props: Props) {
}
history.replace(url);
setHasSeenTagsList(true);
setSettingAndSync(SETTINGS.TAGS_ACKNOWLEDGED, true);
}}
/>
),

View file

@ -12,7 +12,7 @@ type Props = {
followedTags: Array<Tag>,
};
function UserChannelFollowIntro(props: Props) {
function UserTagFollowIntro(props: Props) {
const { onContinue, followedTags } = props;
const followingCount = (followedTags && followedTags.length) || 0;
@ -23,7 +23,8 @@ function UserChannelFollowIntro(props: Props) {
actions={
<React.Fragment>
<Form onSubmit={onContinue}>
<div className="section__actions">
<div className="section__actions--between">
<span />
<Button
button="primary"
type="Submit"
@ -54,4 +55,4 @@ function UserChannelFollowIntro(props: Props) {
);
}
export default UserChannelFollowIntro;
export default UserTagFollowIntro;

View file

@ -35,7 +35,7 @@ class UserVerify extends React.PureComponent<Props> {
};
return (
<React.Fragment>
<div className="main__auth-content">
<section className="section__header">
<h1 className="section__title--large">{__('Get Validated')}</h1>
<p>
@ -141,7 +141,7 @@ class UserVerify extends React.PureComponent<Props> {
}
/>
</div>
</React.Fragment>
</div>
);
}
}

View file

@ -30,6 +30,8 @@ const defaultState = {
clientSettings: {
// UX
[SETTINGS.EMAIL_COLLECTION_ACKNOWLEDGED]: false,
[SETTINGS.FOLLOWING_ACKNOWLEDGED]: false,
[SETTINGS.TAGS_ACKNOWLEDGED]: false,
[SETTINGS.ENABLE_SYNC]: IS_WEB,
// UI

View file

@ -5,9 +5,15 @@
overflow: hidden;
border: 1px solid var(--color-border);
@media (max-width: $breakpoint-small) {
~ .card {
margin-bottom: var(--spacing-m);
}
@media (max-width: $breakpoint-small) {
~ .card {
margin-bottom: 0;
}
}
}
.card--disabled {

View file

@ -108,9 +108,49 @@
.main--auth-page {
width: 100%;
max-width: 70rem;
margin-top: var(--spacing-main-padding);
margin-left: 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 {
@ -163,7 +203,7 @@
display: flex;
flex-direction: column;
align-items: flex-start;
max-width: 50rem;
max-width: 60rem;
text-align: left;
& > * {

View file

@ -51,6 +51,7 @@
margin-right: var(--spacing-m);
font-weight: var(--font-weight-bold);
font-size: var(--font-heading);
margin-bottom: var(--spacing-l);
@media (max-width: $breakpoint-small) {
font-size: var(--font-title);
@ -71,10 +72,12 @@
.section__divider {
display: flex;
align-items: center;
flex-direction: column;
position: relative;
hr {
margin: var(--spacing-l) 0;
margin: var(--spacing-xl) 0;
}
p {
@ -83,10 +86,10 @@
font-size: var(--font-large);
font-weight: var(--font-weight-base);
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);
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 {
margin-top: 0;
}