Few UX Improvements #2638

Merged
tzarebczan merged 3 commits from ux-improvements into master 2019-07-17 20:36:08 +02:00
24 changed files with 189 additions and 95 deletions

View file

@ -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();

View file

@ -57,7 +57,7 @@ function ClaimListDiscover(props: Props) {
channel_ids?: Array<string>,
release_time?: string,
not_tags?: Array<string>,
} = { page_size: PAGE_SIZE, page };
} = { page_size: PAGE_SIZE, page, no_totals: true };
const newTags = tagsString.split(',');
const newChannelIds = channelsIdString.split(',');

View file

@ -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.'

View file

@ -253,4 +253,10 @@ export const icons = {
<path d="M7 11V7a5 5 0 0 1 9.9-1" />
</g>
),
[ICONS.SUPPORT]: buildIcon(
<g>
<polyline points="23 6 13.5 15.5 8.5 10.5 1 18" />
<polyline points="17 6 23 6 23 12" />
</g>
),
};

View file

@ -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 */}

View file

@ -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 {

View file

@ -25,36 +25,16 @@ 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}`;

View file

@ -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(

View file

@ -1,5 +1,6 @@
// @flow
import * as React from 'react';
import type { Node } from 'react';
import React, { useEffect } from 'react';
import Button from 'component/button';
import { FormField } from 'component/common/form';
import UserEmailNew from 'component/userEmailNew';
@ -7,22 +8,19 @@ import UserEmailVerify from 'component/userEmailVerify';
import cookie from 'cookie';
type Props = {
cancelButton: React.Node,
cancelButton: Node,
email: string,
resendVerificationEmail: string => void,
checkEmailVerified: () => void,
user: {
has_verified_email: boolean,
},
fetchAccessToken: () => void,
accessToken: string,
};
function UserEmail(props: Props) {
const { email, user } = props;
let isVerified = false;
if (user) {
isVerified = user.has_verified_email;
}
const { email, user, accessToken, fetchAccessToken } = props;
const buttonsProps = IS_WEB
? {
onClick: () => {
@ -32,6 +30,17 @@ function UserEmail(props: Props) {
}
: { href: 'https://lbry.com/faq/how-to-change-email' };
let isVerified = false;
if (user) {
isVerified = user.has_verified_email;
}
useEffect(() => {
if (!accessToken) {
fetchAccessToken();
}
}, [accessToken, fetchAccessToken]);
return (
<section className="card card--section">
{!email && <UserEmailNew />}
@ -51,14 +60,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>

View file

@ -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 be skipped at the bottom.
</p>
</header>
tzarebczan commented 2019-07-17 20:37:25 +02:00 (Migrated from github.com)
Review

"you can be" :p

"you can be" :p
</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>

View file

@ -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>

View file

@ -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>
}

View file

@ -69,3 +69,4 @@ export const MUSIC_EQUALIZER = 'Sliders';
export const LIGHT = 'Sun';
export const DARK = 'Moon';
export const LIBRARY = 'Folder';
export const SUPPORT = 'TrendingUp';

View file

@ -1 +1,2 @@
export const TIP = 'tip';
export const SUPPORT = 'support';

View file

@ -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>

View file

@ -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>
);
}

View file

@ -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.SUPPORT : icons.TIP}
label={claimIsMine ? __('Add support') : __('Send a tip')}
onClick={() => openModal(MODALS.SEND_TIP, { uri, claimIsMine })}
/>
</React.Fragment>
)}
}
<Button
button="alt"
icon={icons.SHARE}

View file

@ -130,24 +130,31 @@ 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={__('View 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>

View file

@ -35,11 +35,12 @@ 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 is optional. You can continue to use this app without rewards, but LBC may be needed for some tasks.'
)}{' '}
<Button button="link" label={__('Learn more')} href="https://lbry.com/faq/rewards" />
</p>
</header>

View file

@ -313,7 +313,12 @@ 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>

View file

@ -11,9 +11,9 @@ const WalletPage = () => (
<UnsupportedOnWeb />
<div className={IS_WEB && 'card--disabled'}>
<WalletBalance />
<TransactionListRecent />
<WalletSend />
<WalletAddress />
<TransactionListRecent />
</div>
</Page>
);

View file

@ -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;

View file

@ -541,5 +541,38 @@
"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.": "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.",
"Upgrade is ready to install": "Upgrade is ready to install",
"Upgrade is ready": "Upgrade is ready",
"Abandon the claim for this URI": "Abandon the claim for this URI"
"Abandon the claim for this URI": "Abandon the claim for this URI",
"For video content, use MP4s in H264/AAC format for best compatibility.": "For video content, use MP4s in H264/AAC format for best compatibility.",
"Read the App Basics FAQ": "Read the App Basics FAQ",
"View all LBRY FAQs": "View all LBRY FAQs",
"Find Assistance": "Find Assistance",
"channel of our Discord chat room. Or you can always email us at help@lbry.com.": "channel of our Discord chat room. Or you can always email us at help@lbry.com.",
"Email Us": "Email Us",
"Today": "Today",
"This": "This",
"All time": "All time",
"For the initial release, deleting or editing comments is not possible. Please be mindful of this when posting.": "For the initial release, deleting or editing comments is not possible. Please be mindful of this when posting.",
"Add support": "Add support",
"Add support to": "Add support to",
"This will increase your overall bid amount for ": "This will increase your overall bid amount for ",
"Share on Facebook": "Share on Facebook",
"Share On Twitter": "Share On Twitter",
"View on lbry.tv": "View on lbry.tv",
"Your Email - ": "Your Email - ",
"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.": "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.",
"Rewards Approval to Earn Credits (LBC)": "Rewards Approval to Earn Credits (LBC)",
"This step optional. You can continue to use this app without Rewards, but LBC may be needed for some tasks.": "This step optional. You can continue to use this app without Rewards, but LBC may be needed for some tasks.",
"Rewards are for human beings only. You'll have to prove you're one of us before you can claim any.": "Rewards are for human beings only. You'll have to prove you're one of us before you can claim any.",
"This step is optional. You can continue to use this app without Rewards, but LBC may be needed for some tasks.": "This step is optional. You can continue to use this app without Rewards, but LBC may be needed for some tasks.",
"This step is optional. You can continue to use this app without rewards, but LBC may be needed for some tasks.": "This step is optional. You can continue to use this app without rewards, but LBC may be needed for some tasks.",
"1) Proof via Phone": "1) Proof via Phone",
"You will receive an SMS text message confirming that your phone number is correct. Does not work for Canada and possibly other regions": "You will receive an SMS text message confirming that your phone number is correct. Does not work for Canada and possibly other regions",
"Standard messaging rates apply. LBRY will not text or call you otherwise. Having trouble?": "Standard messaging rates apply. LBRY will not text or call you otherwise. Having trouble?",
"2) Proof via Credit": "2) Proof via Credit",
"You currently have the highest bid for this name.": "You currently have the highest bid for this name.",
"You sent 1 LBC as a tip, Mahalo!": "You sent 1 LBC as a tip, Mahalo!",
"You can generate a new address at any time, and any previous addresses will continue to work.": "You can generate a new address at any time, and any previous addresses will continue to work.",
"Confirm Claim Revoke": "Confirm Claim Revoke",
"Are you sure you want to remove this support?": "Are you sure you want to remove this support?",
"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.": "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."
}

View file

@ -6654,9 +6654,9 @@ lbry-redux@lbryio/lbry-redux#bb82aed61a5569e565daa784eb25fc1d639c0c22:
reselect "^3.0.0"
uuid "^3.3.2"
lbryinc@lbryio/lbryinc#43d382d9b74d396a581a74d87e4c53105e04f845:
lbryinc@lbryio/lbryinc#69f9562b016030b481375443f56147ff5e273c0e:
version "0.0.1"
resolved "https://codeload.github.com/lbryio/lbryinc/tar.gz/43d382d9b74d396a581a74d87e4c53105e04f845"
resolved "https://codeload.github.com/lbryio/lbryinc/tar.gz/69f9562b016030b481375443f56147ff5e273c0e"
dependencies:
reselect "^3.0.0"