Few UX improvements
- add message about deleting/editing to comment create intro (feel free to remove, but I thought people would be wondering after they used em) - add note on publish, link to faq - better handling of own urls + takeovers - Add manage email preferences to account page - move recent believe send/receive (on the fence, but I think this is better) - rewards messaging - Add support button for own claims, fix up messaging around this - Help page improvements - Add privacy policy to settings/diagnostics option - maybe a couple things I'm forgetting
This commit is contained in:
parent
112ffe6696
commit
a628776518
20 changed files with 142 additions and 83 deletions
|
@ -98,7 +98,7 @@ class CardVerify extends React.Component<Props, State> {
|
|||
|
||||
componentWillUnmount() {
|
||||
if (this.loadPromise) {
|
||||
this.loadPromise.cancel();
|
||||
this.loadPromise.reject();
|
||||
}
|
||||
if (CardVerify.stripeHandler && this.state.open) {
|
||||
CardVerify.stripeHandler.close();
|
||||
|
|
|
@ -49,6 +49,11 @@ export function CommentCreate(props: Props) {
|
|||
'During the alpha, comments are not decentralized or censorship resistant (but we repeat ourselves).'
|
||||
)}
|
||||
</li>
|
||||
<li>
|
||||
{__(
|
||||
'For the initial release, deleting or editing comments is not possible. Please be mindful of this when posting.'
|
||||
)}
|
||||
</li>
|
||||
<li>
|
||||
{__(
|
||||
'When the alpha ends, we will attempt to transition comments, but do not promise to do so. Any transition will likely involve publishing previous comments under a single archive handle.'
|
||||
|
|
|
@ -3,6 +3,7 @@ import React from 'react';
|
|||
import { regexInvalidURI } from 'lbry-redux';
|
||||
import classnames from 'classnames';
|
||||
import FileSelector from 'component/common/file-selector';
|
||||
import Button from 'component/button';
|
||||
|
||||
type Props = {
|
||||
name: ?string,
|
||||
|
@ -39,6 +40,12 @@ function PublishFile(props: Props) {
|
|||
|
||||
<div className="card__content">
|
||||
<FileSelector currentPath={filePath} onFileChosen={handleFileChange} />
|
||||
{!isStillEditing && (
|
||||
<p className="help">
|
||||
{__('For video content, use MP4s in H264/AAC format for best compatibility.')}{' '}
|
||||
<Button button="link" label={__('Learn more')} href="https://lbry.com/faq/how-to-publish" />.
|
||||
</p>
|
||||
)}
|
||||
{!!isStillEditing && name && (
|
||||
<p className="help">
|
||||
{/* @i18nfixme */}
|
||||
|
|
|
@ -13,6 +13,8 @@ function BidHelpText(props: Props) {
|
|||
if (uri) {
|
||||
if (isResolvingUri) {
|
||||
bidHelpText = __('Checking the winning claim amount...');
|
||||
} else if (amountNeededForTakeover === 0) {
|
||||
bidHelpText = __('You currently have the highest bid for this name.');
|
||||
} else if (!amountNeededForTakeover) {
|
||||
bidHelpText = __('Any amount will give you the winning bid.');
|
||||
} else {
|
||||
|
|
|
@ -25,36 +25,17 @@ class SocialShare extends React.PureComponent<Props> {
|
|||
input: ?HTMLInputElement;
|
||||
|
||||
render() {
|
||||
const { claim, isChannel } = this.props;
|
||||
const { claim_id: claimId, name: claimName } = claim;
|
||||
const { claim } = this.props;
|
||||
const { short_url: shortUrl } = claim;
|
||||
|
||||
const { speechShareable, onDone } = this.props;
|
||||
const signingChannel = claim.signing_channel;
|
||||
const channelClaimId = signingChannel && signingChannel.claim_id;
|
||||
const channelName = signingChannel && signingChannel.name;
|
||||
|
||||
const getLbryTvUri = (): string => {
|
||||
return `${claimName}/${claimId}`;
|
||||
};
|
||||
|
||||
const getLbryUri = (): string => {
|
||||
if (isChannel) {
|
||||
// For channel claims, the channel name (@something) is in `claim.name`
|
||||
return `${claimName}#${claimId}`;
|
||||
} else {
|
||||
// If it's for a regular claim, check if it has an associated channel
|
||||
return channelName && channelClaimId
|
||||
? `${channelName}#${channelClaimId}/${claimName}`
|
||||
: `${claimName}#${claimId}`;
|
||||
}
|
||||
};
|
||||
|
||||
const lbryTvPrefix = 'https://beta.lbry.tv/';
|
||||
const lbryPrefix = 'https://open.lbry.com/';
|
||||
const lbryUri = getLbryUri();
|
||||
const lbryTvUri = getLbryTvUri();
|
||||
const lbryUri = shortUrl.split('lbry://')[1];
|
||||
const lbryTvUri = lbryUri.replace('#', '/');
|
||||
const encodedLbryURL: string = `${lbryPrefix}${encodeURIComponent(lbryUri)}`;
|
||||
const lbryURL: string = `${lbryPrefix}${getLbryUri()}`;
|
||||
const lbryURL: string = `${lbryPrefix}${lbryUri}`;
|
||||
const encodedLbryTvUrl = `${lbryTvPrefix}${encodeURIComponent(lbryTvUri)}`;
|
||||
const lbryTvUrl = `${lbryTvPrefix}${lbryTvUri}`;
|
||||
|
||||
|
|
|
@ -1,15 +1,24 @@
|
|||
import { connect } from 'react-redux';
|
||||
import { selectEmailToVerify, doUserResendVerificationEmail, doUserCheckEmailVerified, selectUser } from 'lbryinc';
|
||||
import {
|
||||
selectEmailToVerify,
|
||||
doUserResendVerificationEmail,
|
||||
doUserCheckEmailVerified,
|
||||
selectUser,
|
||||
doFetchAccessToken,
|
||||
selectAccessToken,
|
||||
} from 'lbryinc';
|
||||
import UserEmailVerify from './view';
|
||||
|
||||
const select = state => ({
|
||||
email: selectEmailToVerify(state),
|
||||
user: selectUser(state),
|
||||
accessToken: selectAccessToken(state),
|
||||
});
|
||||
|
||||
const perform = dispatch => ({
|
||||
resendVerificationEmail: email => dispatch(doUserResendVerificationEmail(email)),
|
||||
checkEmailVerified: () => dispatch(doUserCheckEmailVerified()),
|
||||
fetchAccessToken: () => dispatch(doFetchAccessToken()),
|
||||
});
|
||||
|
||||
export default connect(
|
||||
|
|
|
@ -14,15 +14,19 @@ type Props = {
|
|||
user: {
|
||||
has_verified_email: boolean,
|
||||
},
|
||||
fetchAccessToken: () => void,
|
||||
accessToken: string,
|
||||
};
|
||||
|
||||
function UserEmail(props: Props) {
|
||||
const { email, user } = props;
|
||||
const { email, user, accessToken, fetchAccessToken } = props;
|
||||
let isVerified = false;
|
||||
if (user) {
|
||||
isVerified = user.has_verified_email;
|
||||
}
|
||||
|
||||
if (!accessToken) fetchAccessToken();
|
||||
|
||||
const buttonsProps = IS_WEB
|
||||
? {
|
||||
onClick: () => {
|
||||
|
@ -51,14 +55,23 @@ function UserEmail(props: Props) {
|
|||
type="text"
|
||||
className="form-field--copyable"
|
||||
readOnly
|
||||
label={__('Your Email')}
|
||||
label={
|
||||
<React.Fragment>
|
||||
{__('Your Email - ')}{' '}
|
||||
<Button
|
||||
button="link"
|
||||
label={__('Update mailing preferences')}
|
||||
href={`http://lbry.io/list/edit/${accessToken}`}
|
||||
/>
|
||||
</React.Fragment>
|
||||
}
|
||||
value={email}
|
||||
inputButton={<Button button="inverse" label={__('Change')} {...buttonsProps} />}
|
||||
/>
|
||||
)}
|
||||
<p className="help">
|
||||
{`${__(
|
||||
'This information is disclosed only to LBRY, Inc. and not to the LBRY network. It is only required to earn LBRY rewards.'
|
||||
'This information is disclosed only to LBRY, Inc. and not to the LBRY network. It is only required to save account information and earn rewards.'
|
||||
)} `}
|
||||
</p>
|
||||
</React.Fragment>
|
||||
|
|
|
@ -30,14 +30,43 @@ class UserVerify extends React.PureComponent<Props> {
|
|||
<header className="card__header--flat">
|
||||
<h1 className="card__title">{__('Final Human Proof')}</h1>
|
||||
<p className="card__subtitle">
|
||||
Finally, please complete <strong>one and only one</strong> of the options below.
|
||||
To be approved for rewards, please complete <strong>one and only one</strong> of the options below. This
|
||||
is optional, and you can click back or Skip Rewards at the bottom.
|
||||
</p>
|
||||
</header>
|
||||
</section>
|
||||
|
||||
<section className="card card--section">
|
||||
<header className="card__header">
|
||||
<h2 className="card__title">{__('1) Proof via Credit')}</h2>
|
||||
<h2 className="card__title">{__('1) Proof via Phone')}</h2>
|
||||
<p className="card__subtitle">
|
||||
{`${__(
|
||||
'You will receive an SMS text message confirming that your phone number is correct. Does not work for Canada and possibly other regions'
|
||||
)}`}
|
||||
</p>
|
||||
</header>
|
||||
|
||||
<div className="card__content">
|
||||
<div className="card__actions">
|
||||
<Button
|
||||
onClick={() => {
|
||||
verifyPhone();
|
||||
}}
|
||||
button="inverse"
|
||||
label={__('Submit Phone Number')}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="help">
|
||||
{__('Standard messaging rates apply. LBRY will not text or call you otherwise. Having trouble?')}{' '}
|
||||
<Button button="link" href="https://lbry.com/faq/phone" label={__('Read more.')} />
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="card card--section">
|
||||
<header className="card__header">
|
||||
<h2 className="card__title">{__('2) Proof via Credit')}</h2>
|
||||
<p className="card__subtitle">
|
||||
{`${__(
|
||||
'If you have a valid credit or debit card, you can use it to instantly prove your humanity.'
|
||||
|
@ -69,32 +98,6 @@ class UserVerify extends React.PureComponent<Props> {
|
|||
</div>
|
||||
</section>
|
||||
|
||||
<section className="card card--section">
|
||||
<header className="card__header">
|
||||
<h2 className="card__title">{__('2) Proof via Phone')}</h2>
|
||||
<p className="card__subtitle">
|
||||
{`${__('You will receive an SMS text message confirming that your phone number is correct.')}`}
|
||||
</p>
|
||||
</header>
|
||||
|
||||
<div className="card__content">
|
||||
<div className="card__actions">
|
||||
<Button
|
||||
onClick={() => {
|
||||
verifyPhone();
|
||||
}}
|
||||
button="inverse"
|
||||
label={__('Submit Phone Number')}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="help">
|
||||
{__('Standard messaging rates apply. Having trouble?')}{' '}
|
||||
<Button button="link" href="https://lbry.com/faq/phone" label={__('Read more.')} />
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="card card--section">
|
||||
<header className="card__header">
|
||||
<h2 className="card__title">{__('3) Proof via Chat')}</h2>
|
||||
|
|
|
@ -71,9 +71,7 @@ class WalletAddress extends React.PureComponent<Props, State> {
|
|||
</div>
|
||||
|
||||
<p className="help">
|
||||
{__(
|
||||
'You can generate a new address at any time, and any previous addresses will continue to work. Using multiple addresses can be helpful for keeping track of incoming payments from multiple sources.'
|
||||
)}
|
||||
{__('You can generate a new address at any time, and any previous addresses will continue to work.')}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ import { FormField, Form } from 'component/common/form';
|
|||
|
||||
type Props = {
|
||||
uri: string,
|
||||
claimIsMine: boolean,
|
||||
title: string,
|
||||
claim: StreamClaim,
|
||||
isPending: boolean,
|
||||
|
@ -69,7 +70,7 @@ class WalletSendTip extends React.PureComponent<Props, State> {
|
|||
}
|
||||
|
||||
render() {
|
||||
const { title, isPending, uri, onCancel } = this.props;
|
||||
const { title, isPending, uri, onCancel, claimIsMine } = this.props;
|
||||
const { tipAmount, tipError } = this.state;
|
||||
|
||||
return (
|
||||
|
@ -98,7 +99,10 @@ class WalletSendTip extends React.PureComponent<Props, State> {
|
|||
}
|
||||
helper={
|
||||
<p>
|
||||
{__(`This will appear as a tip for "${title}".`)}{' '}
|
||||
{claimIsMine
|
||||
? __('This will increase your overall bid amount for ')
|
||||
: __('This will appear as a tip for ')}
|
||||
{`"${title}" which will boost its ability to be discovered while active.`}{' '}
|
||||
<Button label={__('Learn more')} button="link" href="https://lbry.com/faq/tipping" />
|
||||
</p>
|
||||
}
|
||||
|
|
|
@ -53,6 +53,7 @@ export const SECURE = 'Lock';
|
|||
export const MENU = 'Menu';
|
||||
export const BACKUP = 'Database';
|
||||
export const TRANSACTIONS = 'FileText';
|
||||
export const TRENDING_UP = 'TrendingUp';
|
||||
export const LBRY = 'Lbry';
|
||||
export const SEND = 'Send';
|
||||
export const DISCOVER = 'Compass';
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
export const TIP = 'tip';
|
||||
export const SUPPORT = 'support';
|
||||
|
|
|
@ -37,6 +37,17 @@ class ModalRevokeClaim extends React.PureComponent<Props> {
|
|||
</p>
|
||||
</React.Fragment>
|
||||
);
|
||||
} else if (type === txnTypes.SUPPORT) {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<p>{__('Are you sure you want to remove this support?')}</p>
|
||||
<p>
|
||||
{__(
|
||||
"These credits are permanently yours and can be removed at any time. Removing this support will reduce the claim's discoverability and return the LBC to your spendable balance."
|
||||
)}
|
||||
</p>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<React.Fragment>
|
||||
|
|
|
@ -7,11 +7,12 @@ import UriIndicator from 'component/uriIndicator';
|
|||
type Props = {
|
||||
closeModal: () => void,
|
||||
uri: string,
|
||||
claimIsMine: boolean,
|
||||
};
|
||||
|
||||
class ModalSendTip extends React.PureComponent<Props> {
|
||||
render() {
|
||||
const { closeModal, uri } = this.props;
|
||||
const { closeModal, uri, claimIsMine } = this.props;
|
||||
|
||||
return (
|
||||
<Modal
|
||||
|
@ -20,11 +21,11 @@ class ModalSendTip extends React.PureComponent<Props> {
|
|||
type="custom"
|
||||
title={
|
||||
<React.Fragment>
|
||||
{__('Send a tip to')} <UriIndicator uri={uri} />
|
||||
{claimIsMine ? __('Add support to') : __('Send a tip')} <UriIndicator uri={uri} />
|
||||
</React.Fragment>
|
||||
}
|
||||
>
|
||||
<SendTip uri={uri} onCancel={closeModal} sendTipCallback={closeModal} />
|
||||
<SendTip uri={uri} claimIsMine={claimIsMine} onCancel={closeModal} sendTipCallback={closeModal} />
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -164,7 +164,7 @@ class FilePage extends React.Component<Props> {
|
|||
const showFile = isPlayableType || isPreviewType;
|
||||
|
||||
const speechShareable =
|
||||
costInfo && costInfo.cost === 0 && contentType && ['video', 'image'].includes(contentType.split('/')[0]);
|
||||
costInfo && costInfo.cost === 0 && contentType && ['video', 'image', 'audio'].includes(contentType.split('/')[0]);
|
||||
// We want to use the short form uri for editing
|
||||
// This is what the user is used to seeing, they don't care about the claim id
|
||||
// We will select the claim id before they publish
|
||||
|
@ -240,18 +240,17 @@ class FilePage extends React.Component<Props> {
|
|||
}}
|
||||
/>
|
||||
)}
|
||||
{!claimIsMine && (
|
||||
{
|
||||
<React.Fragment>
|
||||
{channelUri && <SubscribeButton uri={channelUri} channelName={channelName} />}
|
||||
|
||||
{!claimIsMine && channelUri && <SubscribeButton uri={channelUri} channelName={channelName} />}
|
||||
<Button
|
||||
button="alt"
|
||||
icon={icons.TIP}
|
||||
label={__('Send a tip')}
|
||||
onClick={() => openModal(MODALS.SEND_TIP, { uri })}
|
||||
icon={claimIsMine ? icons.TRENDING_UP : icons.TIP}
|
||||
label={claimIsMine ? __('Add support') : __('Send a tip')}
|
||||
onClick={() => openModal(MODALS.SEND_TIP, { uri, claimIsMine })}
|
||||
/>
|
||||
</React.Fragment>
|
||||
)}
|
||||
}
|
||||
<Button
|
||||
button="alt"
|
||||
icon={icons.SHARE}
|
||||
|
|
|
@ -130,24 +130,36 @@ class HelpPage extends React.PureComponent<Props, State> {
|
|||
|
||||
<div className="card__content">
|
||||
<div className="card__actions">
|
||||
<Button href="https://lbry.com/faq" label={__('Read the FAQ')} icon={icons.HELP} button="inverse" />
|
||||
<Button
|
||||
href="https://lbry.com/faq/lbry-basics"
|
||||
label={__('Read the App Basics FAQ')}
|
||||
icon={icons.HELP}
|
||||
button="inverse"
|
||||
/>
|
||||
<Button
|
||||
href="https://lbry.com/faq"
|
||||
label={__('See the All LBRY FAQs')}
|
||||
icon={icons.HELP}
|
||||
button="inverse"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="card card--section">
|
||||
<header className="card__header">
|
||||
<h2 className="card__title">{__('Get Live Help')}</h2>
|
||||
<h2 className="card__title">{__('Find Assistance')}</h2>
|
||||
|
||||
<p className="card__subtitle">
|
||||
{__('Live help is available most hours in the')} <strong>#help</strong>{' '}
|
||||
{__('channel of our Discord chat room.')}
|
||||
{__('channel of our Discord chat room. Or you can always email us at help@lbry.com.')}
|
||||
</p>
|
||||
</header>
|
||||
|
||||
<div className="card__content">
|
||||
<div className="card__actions">
|
||||
<Button button="inverse" label={__('Join Our Chat')} icon={icons.CHAT} href="https://chat.lbry.com" />
|
||||
<Button button="inverse" label={__('Email Us')} icon={icons.WEB} href="mailto:help@lbry.com" />
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
|
@ -35,11 +35,17 @@ class RewardsPage extends PureComponent<Props> {
|
|||
!IS_WEB && (
|
||||
<section className="card card--section">
|
||||
<header className="card__header">
|
||||
<h2 className="card__title">{__('Verification For Rewards')}</h2>
|
||||
<h2 className="card__title">{__('Rewards Approval to Earn Credits (LBC)')}</h2>
|
||||
<p className="card__subtitle">
|
||||
{__('Rewards are for human beings only.')}{' '}
|
||||
{__("You'll have to prove you're one of us before you can claim any rewards.")}{' '}
|
||||
{__('This is optional.')}
|
||||
{__(
|
||||
'This step optional. You can continue to use this app without Rewards, but LBC may be needed for some tasks.'
|
||||
)}{' '}
|
||||
</p>
|
||||
<p className="card__subtitle">
|
||||
{__(
|
||||
"Rewards are for human beings only. You'll have to prove you're one of us before you can claim any."
|
||||
)}{' '}
|
||||
{<Button button="link" label={__('Learn more')} href="https://lbry.com/faq/rewards" />}
|
||||
</p>
|
||||
</header>
|
||||
|
||||
|
|
|
@ -313,7 +313,10 @@ class SettingsPage extends React.PureComponent<Props, State> {
|
|||
name="share_usage_data"
|
||||
onChange={() => setDaemonSetting('share_usage_data', !daemonSettings.share_usage_data)}
|
||||
checked={daemonSettings.share_usage_data}
|
||||
label={__('Help make LBRY better by contributing analytics and diagnostic data about my usage.')}
|
||||
label=<React.Fragment>
|
||||
{__('Help make LBRY better by contributing analytics and diagnostic data about my usage.')}{' '}
|
||||
<Button button="link" label={__('Learn more')} href="https://lbry.com/privacypolicy" />.
|
||||
</React.Fragment>
|
||||
helper={__('You will be ineligible to earn rewards while diagnostics are not being shared.')}
|
||||
/>
|
||||
</Form>
|
||||
|
|
|
@ -11,9 +11,9 @@ const WalletPage = () => (
|
|||
<UnsupportedOnWeb />
|
||||
<div className={IS_WEB && 'card--disabled'}>
|
||||
<WalletBalance />
|
||||
<TransactionListRecent />
|
||||
<WalletSend />
|
||||
<WalletAddress />
|
||||
<TransactionListRecent />
|
||||
</div>
|
||||
</Page>
|
||||
);
|
||||
|
|
|
@ -104,7 +104,10 @@ export const selectTakeOverAmount = createSelector(
|
|||
// is needed to win the claim. Currently this is not possible during a takeover.
|
||||
// With this, we could say something like, "You have x lbc in support, if you bid y additional LBC you will control the claim"
|
||||
// For now just ignore supports. We will just show the winning claim's bid amount
|
||||
return claimForShortUri.meta.effective_amount || claimForShortUri.amount;
|
||||
// If the top claim is your claim, no takeover is necessary so we return 0.
|
||||
return claimForShortUri.claim_id === myClaimForUri.claim_id
|
||||
? 0
|
||||
: claimForShortUri.meta.effective_amount || claimForShortUri.amount;
|
||||
}
|
||||
|
||||
return null;
|
||||
|
|
Loading…
Reference in a new issue