add nudges to sign up

This commit is contained in:
Sean Yesmunt 2020-11-10 00:21:04 -05:00
parent 35ab5b1578
commit f63de7f930
12 changed files with 192 additions and 39 deletions

View file

@ -1476,5 +1476,6 @@
"Currently winning": "Currently winning",
"URL can not include a space": "URL can not include a space",
"Creator analytics are down for maintenance. Please check back later.": "Creator analytics are down for maintenance. Please check back later.",
"Sign up to earn %lbc% for you and your favorite creators.": "Sign up to earn %lbc% for you and your favorite creators.",
"--end--": "--end--"
}

View file

@ -1,11 +1,13 @@
import { connect } from 'react-redux';
import { doOpenModal } from 'redux/actions/app';
import ClaimSupportButton from './view';
import { selectUser } from 'redux/selectors/user';
import { makeSelectTagInClaimOrChannelForUri } from 'lbry-redux';
import ClaimSupportButton from './view';
const DISABLE_SUPPORT_TAG = 'disable-support';
const select = (state, props) => ({
disableSupport: makeSelectTagInClaimOrChannelForUri(props.uri, DISABLE_SUPPORT_TAG)(state),
user: selectUser(state),
});
export default connect(select, {

View file

@ -4,29 +4,60 @@ import * as ICONS from 'constants/icons';
import React from 'react';
import classnames from 'classnames';
import Button from 'component/button';
import usePersistedState from 'effects/use-persisted-state';
type Props = {
uri: string,
doOpenModal: (string, {}) => void,
fileAction?: boolean,
disableSupport: boolean,
user: ?User,
};
export default function ClaimSupportButton(props: Props) {
const { doOpenModal, uri, fileAction, disableSupport } = props;
const { doOpenModal, uri, fileAction, disableSupport, user } = props;
const [showNudge, setShowNudge] = React.useState(false);
const [nudgeAcknowledged, setNudgeAcknowledged] = usePersistedState('nudge:support-acknowledge', false);
const emailVerified = user && user.has_verified_email;
React.useEffect(() => {
if (!emailVerified && !nudgeAcknowledged && fileAction) {
setShowNudge(true);
}
}, [emailVerified, nudgeAcknowledged, fileAction]);
if (disableSupport) {
return null;
}
return (
<Button
button={fileAction ? undefined : 'alt'}
className={classnames({ 'button--file-action': fileAction })}
icon={ICONS.LBC}
iconSize={fileAction ? 22 : undefined}
label={__('Support --[button to support a claim]--')}
requiresAuth={IS_WEB}
title={__('Support this claim')}
onClick={() => doOpenModal(MODALS.SEND_TIP, { uri, isSupport: true })}
/>
<>
<Button
button={fileAction ? undefined : 'alt'}
className={classnames({ 'button--file-action': fileAction, 'button--highlighted': showNudge })}
icon={ICONS.LBC}
iconSize={fileAction ? 22 : undefined}
label={__('Support --[button to support a claim]--')}
requiresAuth={IS_WEB}
title={__('Support this claim')}
onClick={() => doOpenModal(MODALS.SEND_TIP, { uri, isSupport: true })}
/>
{showNudge && (
<div className="nudge">
<div className="nudge__wrapper">
<span className="nudge__text">{__('Create an account to support this creator!')}</span>
<Button
className="nudge__close"
button="close"
icon={ICONS.REMOVE}
onClick={() => {
setNudgeAcknowledged(true);
setShowNudge(false);
}}
/>
</div>
</div>
)}
</>
);
}

View file

@ -174,6 +174,13 @@ const Header = (props: Props) => {
return hideBalance || Number(roundedBalance) === 0 ? __('Your Wallet') : roundedBalance;
}
const loginButtons = (
<div className="header__auth-buttons">
<Button navigate={`/$/${PAGES.AUTH_SIGNIN}`} button="link" label={__('Log In')} className="mobile-hidden" />
<Button navigate={`/$/${PAGES.AUTH}`} button="primary" label={__('Sign Up')} />
</div>
);
return (
<header
className={classnames('header', {
@ -198,18 +205,22 @@ const Header = (props: Props) => {
icon={ICONS.ARROW_LEFT}
/>
{backTitle && <h1 className="header__auth-title">{isMobile ? simpleBackTitle || backTitle : backTitle}</h1>}
<Button
aria-label={__('Your wallet')}
navigate={`/$/${PAGES.WALLET}`}
className="header__navigation-item menu__title header__navigation-item--balance"
label={getWalletTitle()}
icon={ICONS.LBC}
// @if TARGET='app'
onDoubleClick={e => {
e.stopPropagation();
}}
// @endif
/>
{authenticated ? (
<Button
aria-label={__('Your wallet')}
navigate={`/$/${PAGES.WALLET}`}
className="header__navigation-item menu__title header__navigation-item--balance"
label={getWalletTitle()}
icon={ICONS.LBC}
// @if TARGET='app'
onDoubleClick={e => {
e.stopPropagation();
}}
// @endif
/>
) : (
loginButtons
)}
</div>
) : (
<>
@ -409,17 +420,7 @@ const Header = (props: Props) => {
/>
)}
{IS_WEB && !authenticated && (
<div className="header__auth-buttons">
<Button
navigate={`/$/${PAGES.AUTH_SIGNIN}`}
button="link"
label={__('Log In')}
className="mobile-hidden"
/>
<Button navigate={`/$/${PAGES.AUTH}`} button="primary" label={__('Sign Up')} />
</div>
)}
{IS_WEB && !authenticated && loginButtons}
</div>
) : (
!isVerifyPage &&

View file

@ -5,7 +5,9 @@ import * as ICONS from 'constants/icons';
import React from 'react';
import Button from 'component/button';
import classnames from 'classnames';
import Icon from 'component/common/icon';
import NotificationBubble from 'component/notificationBubble';
import I18nMessage from 'component/i18nMessage';
import { PINNED_LABEL_1, PINNED_URI_1, PINNED_URI_2, PINNED_LABEL_2 } from 'config';
// @if TARGET='app'
import { IS_MAC } from 'component/app/view';
@ -260,6 +262,17 @@ function SideNavigation(props: Props) {
return () => window.removeEventListener('keydown', handleKeydown);
}, [sidebarOpen, setSidebarOpen, isAbsolute]);
const unAuthNudge = (
<div className="navigation__auth-nudge">
<span>
<I18nMessage tokens={{ lbc: <Icon icon={ICONS.LBC} /> }}>
Sign up to earn %lbc% for you and your favorite creators.
</I18nMessage>
</span>
<Button button="secondary" label={__('Sign Up')} navigate={`/$/${PAGES.AUTH}`} />
</div>
);
return (
<div
className={classnames('navigation__wrapper', {
@ -321,6 +334,20 @@ function SideNavigation(props: Props) {
))}
</ul>
)}
{!isAuthenticated &&
(sidebarOpen ? (
unAuthNudge
) : (
<div className="navigation-links--micro">
<Button
label={__('Sign In')}
icon={ICONS.SIGN_IN}
className={classnames('navigation-link')}
activeClass="navigation-link--active"
/>
</div>
))}
</div>
</nav>
)}
@ -396,6 +423,7 @@ function SideNavigation(props: Props) {
))}
</ul>
)}
{!isAuthenticated && unAuthNudge}
</div>
</nav>
<div

View file

@ -12,8 +12,10 @@ import FileSelector from 'component/common/file-selector';
import SyncToggle from 'component/syncToggle';
import Card from 'component/common/card';
import SettingAccountPassword from 'component/settingAccountPassword';
import classnames from 'classnames';
import { getPasswordFromCookie } from 'util/saved-passwords';
import { Lbryio } from 'lbryinc';
import Yrbl from 'component/yrbl';
type Price = {
currency: string,
@ -190,12 +192,27 @@ class SettingsPage extends React.PureComponent<Props, State> {
}}
className="card-stack"
>
{!isAuthenticated && IS_WEB && (
<div className="main--empty">
<Yrbl
type="happy"
title={__('Sign up for full control')}
subtitle={__('Unlock new buttons that change things.')}
actions={
<div className="section__actions">
<Button button="primary" icon={ICONS.SIGN_UP} label={__('Sign Up')} navigate={`/$/${PAGES.AUTH}`} />
</div>
}
/>
</div>
)}
{!IS_WEB && noDaemonSettings ? (
<section className="card card--section">
<div className="card__title card__title--deprecated">{__('Failed to load settings.')}</div>
</section>
) : (
<div>
<div className={classnames({ 'card--disabled': IS_WEB && !isAuthenticated })}>
<Card title={__('Language')} actions={<SettingLanguage />} />
{isAuthenticated && <SettingAccountPassword />}
{/* @if TARGET='app' */}

View file

@ -46,7 +46,7 @@ import {
selectAllowAnalytics,
} from 'redux/selectors/app';
import { selectDaemonSettings, makeSelectClientSetting } from 'redux/selectors/settings';
import { selectUser } from 'redux/selectors/user';
import { selectUser, selectUserVerifiedEmail } from 'redux/selectors/user';
// import { selectDaemonSettings } from 'redux/selectors/settings';
import { doSyncSubscribe, doSetPrefsReady } from 'redux/actions/sync';
import { doAuthenticate } from 'redux/actions/user';
@ -335,13 +335,20 @@ export function doAlertError(errorList) {
}
export function doAlertWaitingForSync() {
return dispatch =>
return (dispatch, getState) => {
const state = getState();
const authenticated = selectUserVerifiedEmail(state);
dispatch(
doToast({
message: __('Please wait a bit, we are still getting your account ready.'),
message:
!authenticated && IS_WEB
? __('Sign in or create an account to change this setting.')
: __('Please wait a bit, we are still getting your account ready.'),
isError: false,
})
);
};
}
export function doDaemonReady() {

View file

@ -37,6 +37,7 @@
@import 'component/nag';
@import 'component/navigation';
@import 'component/notification';
@import 'component/nudge';
@import 'component/pagination';
@import 'component/purchase';
@import 'component/placeholder';

View file

@ -203,6 +203,10 @@
opacity: 0.5;
}
.button--highlighted {
border: 1px solid var(--color-border);
}
.button__content {
display: flex;
align-items: center;

View file

@ -236,3 +236,24 @@
top: calc(var(--header-height) + var(--mac-titlebar-height));
}
}
.navigation__auth-nudge {
@extend .card;
margin: var(--spacing-s);
margin-top: var(--spacing-l);
padding: var(--spacing-xs);
display: flex;
flex-direction: column;
.button {
margin-top: var(--spacing-s);
}
.button__content {
justify-content: center;
}
.icon {
margin-bottom: -2px;
}
}

View file

@ -0,0 +1,39 @@
.nudge {
z-index: 3;
position: absolute;
left: 0;
top: calc(var(--height-button) + var(--spacing-s));
white-space: normal;
overflow: visible;
padding: var(--spacing-m);
border-radius: var(--border-radius);
box-shadow: var(--card-box-shadow);
background-color: var(--color-secondary);
color: var(--color-white);
.button--close {
.icon {
stroke: var(--color-white);
}
}
&::after {
content: '';
position: absolute;
height: 1rem;
width: 1rem;
top: -0.5rem;
left: 3rem;
transform: rotate(45deg);
background-color: var(--color-secondary);
}
}
.nudge__wrapper {
width: 10rem;
margin-right: var(--spacing-m);
@media (min-width: $breakpoint-small) {
width: 12.5rem;
}
}

View file

@ -104,6 +104,7 @@
}
.section__actions {
position: relative;
display: flex;
align-items: center;
margin-top: var(--spacing-l);