Merge pull request #2649 from lbryio/consistency

improve style consistency and discovery cleanup
This commit is contained in:
Sean Yesmunt 2019-07-29 09:56:19 -04:00 committed by GitHub
commit 6120dfce42
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
141 changed files with 1769 additions and 2240 deletions

View file

@ -36,6 +36,7 @@
"object-curly-spacing": 0,
"one-var": 0,
"prefer-promise-reject-errors": 0,
"react/jsx-indent": 0,
"react-hooks/exhaustive-deps": "warn",
"react-hooks/rules-of-hooks": "error",
"space-before-function-paren": ["error", "never"],

View file

@ -1,6 +1,6 @@
{
"name": "LBRY",
"version": "0.34.0-rc.9",
"version": "0.34.1-rc.1",
"description": "A browser for the LBRY network, a digital marketplace controlled by its users.",
"keywords": [
"lbry"
@ -124,7 +124,7 @@
"jsmediatags": "^3.8.1",
"json-loader": "^0.5.4",
"lbry-format": "https://github.com/lbryio/lbry-format.git",
"lbry-redux": "lbryio/lbry-redux#e550f0ff0448fcad5f3d0365ec7ad744376b41cf",
"lbry-redux": "lbryio/lbry-redux#ea56de4548480eb1a10b752b3cecbad7de2f8914",
"lbryinc": "lbryio/lbryinc#a93596c51c8fb0a226cb84df04c26a6bb60a45fb",
"lint-staged": "^7.0.2",
"localforage": "^1.7.1",
@ -159,9 +159,8 @@
"react-simplemde-editor": "^4.0.0",
"react-spring": "^8.0.20",
"react-sticky-box": "^0.8.0",
"react-toggle": "^4.0.2",
"redux": "^3.6.0",
"redux-persist": "^4.8.0",
"redux-persist": "^5.10.0",
"redux-persist-transform-compress": "^4.2.0",
"redux-persist-transform-filter": "0.0.16",
"redux-thunk": "^2.2.0",
@ -200,8 +199,8 @@
"yarn": "^1.3"
},
"lbrySettings": {
"lbrynetDaemonVersion": "0.38.1",
"lbrynetDaemonUrlTemplate": "http://build.lbry.io/daemon/build-11443_commit-eae4ed7_branch-master/lbrynet-OSNAME.zip",
"lbrynetDaemonVersion": "0.38.3",
"lbrynetDaemonUrlTemplate": "https://github.com/lbryio/lbry/releases/download/vDAEMONVER/lbrynet-OSNAME.zip",
"lbrynetDaemonDir": "static/daemon",
"lbrynetDaemonFileName": "lbrynet"
}

View file

@ -84,9 +84,8 @@ const analytics: Analytics = {
tagFollowEvent: (tag, following, location) => {
if (analyticsEnabled) {
ReactGA.event({
category: 'Tag',
action: following ? 'follow' : 'unfollow',
value: tag,
category: following ? 'Tag-Follow' : 'Tag-Unfollow',
action: tag,
});
}
},

View file

@ -29,11 +29,11 @@ function ChannelContent(props: Props) {
{!fetching && !hasContent && (
<div className="card--section">
<h2 className="card__content help">{__("This channel hasn't uploaded anything.")}</h2>
<h2 className="help">{__("This channel hasn't uploaded anything.")}</h2>
</div>
)}
{!channelIsMine && <HiddenNsfwClaims className="card__content help" uri={uri} />}
{!channelIsMine && <HiddenNsfwClaims className="card__subtitle" uri={uri} />}
{hasContent && <ClaimList header={false} uris={claimsInChannel.map(claim => claim.permanent_url)} />}

View file

@ -3,7 +3,6 @@ import React, { useState } from 'react';
import { parseURI } from 'lbry-redux';
import { Form, FormField } from 'component/common/form';
import Button from 'component/button';
import SelectAsset from 'component/selectAsset';
import TagSelect from 'component/tagsSelect';
@ -21,9 +20,7 @@ type Props = {
tags: Array<string>,
locations: Array<string>,
languages: Array<string>,
updateChannel: any => void,
updateThumb: string => void,
updateCover: string => void,
setEditing: boolean => void,
@ -42,8 +39,8 @@ function ChannelForm(props: Props) {
locations,
languages,
amount,
updateChannel,
setEditing,
updateChannel,
updateThumb,
updateCover,
} = props;
@ -104,120 +101,118 @@ function ChannelForm(props: Props) {
// TODO clear and bail after submit
return (
<section className={'card--section'}>
<div className="help">
<div className="card__subtitle">
<p>{__('We can explain...')}</p>
<p>
{__(
"We know this page won't win any design awards, we just wanted to release a very very very basic version that just barely kinda works so people can use it right now. There is a much nicer version being worked on."
"We know this page won't win any design awards, we just wanted to release a very basic version that works so people can use it right now. There is a much nicer version being worked on."
)}
</p>
</div>
<Form onSubmit={channelParams => updateChannel(channelParams)}>
<div className="card__content">
<SelectAsset
onUpdate={v => handleThumbnailChange(v)}
currentValue={params.thumbnail}
assetName={'Thumbnail'}
recommended={'(300 x 300)'}
/>
<SelectAsset
onUpdate={v => handleThumbnailChange(v)}
currentValue={params.thumbnail}
assetName={'Thumbnail'}
recommended={'(300 x 300)'}
/>
<SelectAsset
onUpdate={v => handleCoverChange(v)}
currentValue={params.cover}
assetName={'Cover'}
recommended={'(1000 x 160)'}
/>
<SelectAsset
onUpdate={v => handleCoverChange(v)}
currentValue={params.cover}
assetName={'Cover'}
recommended={'(1000 x 160)'}
/>
<FormField
type="text"
name="channel_title2"
label={__('Title')}
placeholder={__('Titular Title')}
disabled={false}
value={params.title}
onChange={e => setParams({ ...params, title: e.target.value })}
/>
<FormField
className="form-field--price-amount"
type="number"
name="content_bid2"
step="any"
label={__('Deposit (LBC)')}
postfix="LBC"
value={params.amount}
error={bidError}
min="0.0"
disabled={false}
onChange={event => handleBidChange(parseFloat(event.target.value))}
placeholder={0.1}
/>
<FormField
type="text"
name="channel_title2"
label={__('Title')}
placeholder={__('Titular Title')}
disabled={false}
value={params.title}
onChange={e => setParams({ ...params, title: e.target.value })}
/>
<FormField
className="form-field--price-amount"
type="number"
name="content_bid2"
step="any"
label={__('Deposit (LBC)')}
postfix="LBC"
value={params.amount}
error={bidError}
min="0.0"
disabled={false}
onChange={event => handleBidChange(parseFloat(event.target.value))}
placeholder={0.1}
/>
<FormField
type="text"
name="channel_website2"
label={__('Website')}
placeholder={__('aprettygoodsite.com')}
disabled={false}
value={params.website}
onChange={e => setParams({ ...params, website: e.target.value })}
/>
<FormField
type="text"
name="channel_website2"
label={__('Website')}
placeholder={__('aprettygoodsite.com')}
disabled={false}
value={params.website}
onChange={e => setParams({ ...params, website: e.target.value })}
/>
<FormField
type="text"
name="content_email2"
label={__('Email')}
placeholder={__('yourstruly@example.com')}
disabled={false}
value={params.email}
onChange={e => setParams({ ...params, email: e.target.value })}
/>
<FormField
type="text"
name="content_email2"
label={__('Email')}
placeholder={__('yourstruly@example.com')}
disabled={false}
value={params.email}
onChange={e => setParams({ ...params, email: e.target.value })}
/>
<FormField
type="markdown"
name="content_description2"
label={__('Description')}
placeholder={__('Description of your content')}
value={params.description}
disabled={false}
onChange={text => setParams({ ...params, description: text })}
/>
<TagSelect
title={false}
suggestMature
help={__('The better your tags are, the easier it will be for people to discover your channel.')}
empty={__('No tags added')}
onSelect={newTag => {
if (!params.tags.map(savedTag => savedTag.name).includes(newTag.name)) {
setParams({ ...params, tags: [...params.tags, newTag] });
} else {
// If it already exists and the user types it in, remove it
setParams({ ...params, tags: params.tags.filter(tag => tag.name !== newTag.name) });
}
<FormField
type="markdown"
name="content_description2"
label={__('Description')}
placeholder={__('Description of your content')}
value={params.description}
disabled={false}
onChange={text => setParams({ ...params, description: text })}
/>
<TagSelect
title={false}
suggestMature
help={__('The better your tags are, the easier it will be for people to discover your channel.')}
empty={__('No tags added')}
onSelect={newTag => {
if (!params.tags.map(savedTag => savedTag.name).includes(newTag.name)) {
setParams({ ...params, tags: [...params.tags, newTag] });
} else {
// If it already exists and the user types it in, remove it
setParams({ ...params, tags: params.tags.filter(tag => tag.name !== newTag.name) });
}
}}
onRemove={clickedTag => {
const newTags = params.tags.slice().filter(tag => tag.name !== clickedTag.name);
setParams({ ...params, tags: newTags });
}}
tagsChosen={params.tags || []}
/>
<div className={'card__actions'}>
<Button
button="primary"
label={__('Submit')}
onClick={() => {
updateChannel(params);
setEditing(false);
}}
/>
<Button
button="link"
label={__('Cancel')}
onClick={() => {
setParams({ ...channelParams });
setEditing(false);
}}
onRemove={clickedTag => {
const newTags = params.tags.slice().filter(tag => tag.name !== clickedTag.name);
setParams({ ...params, tags: newTags });
}}
tagsChosen={params.tags || []}
/>
<div className={'card__actions'}>
<Button
button="primary"
label={__('Submit')}
onClick={() => {
updateChannel(params);
setEditing(false);
}}
/>
<Button
button="link"
label={__('Cancel')}
onClick={() => {
setParams({ ...channelParams });
setEditing(false);
}}
/>
</div>
</div>
</Form>
</section>

View file

@ -1,7 +1,7 @@
// @flow
import { MAIN_WRAPPER_CLASS } from 'component/app/view';
import type { Node } from 'react';
import React, { useEffect } from 'react';
import React, { useEffect, useState } from 'react';
import classnames from 'classnames';
import ClaimPreview from 'component/claimPreview';
import Spinner from 'component/spinner';
@ -23,6 +23,7 @@ type Props = {
onScrollBottom?: any => void,
page?: number,
pageSize?: number,
id?: string,
// If using the default header, this is a unique ID needed to persist the state of the filter setting
persistedStorageKey?: string,
};
@ -40,7 +41,10 @@ export default function ClaimList(props: Props) {
header,
onScrollBottom,
pageSize,
page,
id,
} = props;
const [scrollBottomCbMap, setScrollBottomCbMap] = useState({});
const [currentSort, setCurrentSort] = usePersistedState(persistedStorageKey, SORT_NEW);
const urisLength = (uris && uris.length) || 0;
const sortedUris = (urisLength > 0 && (currentSort === SORT_NEW ? uris : uris.slice().reverse())) || [];
@ -49,14 +53,21 @@ export default function ClaimList(props: Props) {
setCurrentSort(currentSort === SORT_NEW ? SORT_OLD : SORT_NEW);
}
useEffect(() => {
setScrollBottomCbMap({});
}, [id]);
useEffect(() => {
function handleScroll(e) {
if (pageSize && onScrollBottom) {
if (page && pageSize && onScrollBottom && !scrollBottomCbMap[page]) {
const x = document.querySelector(`.${MAIN_WRAPPER_CLASS}`);
if (x && window.scrollY + window.innerHeight >= x.offsetHeight) {
if (!loading && urisLength >= pageSize) {
onScrollBottom();
// Save that we've fetched this page to avoid weird stuff happening with fast scrolling
setScrollBottomCbMap({ ...scrollBottomCbMap, [page]: true });
}
}
}
@ -69,7 +80,7 @@ export default function ClaimList(props: Props) {
window.removeEventListener('scroll', handleScroll);
};
}
}, [loading, onScrollBottom, urisLength, pageSize]);
}, [loading, onScrollBottom, urisLength, pageSize, page, setScrollBottomCbMap]);
return (
<section
@ -99,16 +110,16 @@ export default function ClaimList(props: Props) {
</div>
)}
{urisLength > 0 && (
<ul>
<ul className="ul--no-style">
{sortedUris.map((uri, index) => (
<React.Fragment key={uri}>
<ClaimPreview uri={uri} type={type} />
{index === 4 && injectedItem && <li className="claim-preview--injected">{injectedItem}</li>}
{index === 4 && injectedItem && injectedItem}
</React.Fragment>
))}
</ul>
)}
{urisLength === 0 && !loading && <h2 className="main--empty empty">{empty || __('No results')}</h2>}
{urisLength === 0 && !loading && <p className="main--empty empty">{empty || __('No results')}</p>}
</section>
);
}

View file

@ -1,6 +1,6 @@
// @flow
import type { Node } from 'react';
import React, { useEffect } from 'react';
import React, { Fragment, useEffect } from 'react';
import { withRouter } from 'react-router';
import { buildClaimSearchCacheQuery, MATURE_TAGS } from 'lbry-redux';
import { FormField } from 'component/common/form';
@ -105,7 +105,10 @@ function ClaimListDiscover(props: Props) {
const claimSearchCacheQuery = buildClaimSearchCacheQuery(options);
const uris = claimSearchByQuery[claimSearchCacheQuery] || [];
const shouldPerformSearch = uris.length === 0 || didNavigateForward || (!loading && uris.length < PAGE_SIZE * page);
const shouldPerformSearch =
uris.length === 0 ||
didNavigateForward ||
(!loading && uris.length < PAGE_SIZE * page && uris.length % PAGE_SIZE === 0);
// Don't use the query from buildClaimSearchCacheQuery for the effect since that doesn't include page & release_time
const optionsStringForEffect = JSON.stringify(options);
@ -149,7 +152,7 @@ function ClaimListDiscover(props: Props) {
}, [doClaimSearch, shouldPerformSearch, optionsStringForEffect]);
const header = (
<h1 className="card__title--flex">
<Fragment>
<FormField
className="claim-list__dropdown"
type="select"
@ -205,12 +208,13 @@ function ClaimListDiscover(props: Props) {
))}
</FormField>
)}
</h1>
</Fragment>
);
return (
<div className="card">
<ClaimList
id={claimSearchCacheQuery}
loading={loading}
uris={uris}
injectedItem={personalSort === SEARCH_SORT_YOU && injectedItem}
@ -221,7 +225,7 @@ function ClaimListDiscover(props: Props) {
pageSize={PAGE_SIZE}
/>
{loading && new Array(PAGE_SIZE).fill(1).map((x, i) => <ClaimPreview key={i} placeholder />)}
{loading && new Array(PAGE_SIZE).fill(1).map((x, i) => <ClaimPreview key={i} placeholder="loading" />)}
</div>
);
}

View file

@ -1,5 +1,5 @@
// @flow
import React, { useEffect } from 'react';
import React, { Fragment, useEffect } from 'react';
import classnames from 'classnames';
import { parseURI, convertToShareLink } from 'lbry-redux';
import { withRouter } from 'react-router-dom';
@ -13,6 +13,7 @@ import FileProperties from 'component/fileProperties';
import ClaimTags from 'component/claimTags';
import SubscribeButton from 'component/subscribeButton';
import ChannelThumbnail from 'component/channelThumbnail';
import Button from 'component/button';
type Props = {
uri: string,
@ -27,7 +28,7 @@ type Props = {
thumbnail: string,
title: string,
nsfw: boolean,
placeholder: boolean,
placeholder: string,
type: string,
hasVisitedUri: boolean,
blackListedOutpoints: Array<{
@ -60,8 +61,12 @@ function ClaimPreview(props: Props) {
hasVisitedUri,
} = props;
const haventFetched = claim === undefined;
const abandoned = !isResolvingUri && !claim && !placeholder;
const abandoned = !isResolvingUri && !claim;
const claimsInChannel = (claim && claim.meta.claims_in_channel) || 0;
const showPublishLink = abandoned && placeholder === 'publish';
const includeChannelTooltip = type !== 'inline' && type !== 'tooltip';
const hideActions = type === 'small' || type === 'tooltip';
let isValid;
try {
parseURI(uri);
@ -71,9 +76,8 @@ function ClaimPreview(props: Props) {
}
const isChannel = isValid ? parseURI(uri).isChannel : false;
const signingChannel = claim && claim.signing_channel;
let shouldHide = abandoned || (!claimIsMine && obscureNsfw && nsfw);
let shouldHide =
placeholder !== 'loading' && ((abandoned && !showPublishLink) || (!claimIsMine && obscureNsfw && nsfw));
// This will be replaced once blocking is done at the wallet server level
if (claim && !shouldHide && blackListedOutpoints) {
@ -113,9 +117,9 @@ function ClaimPreview(props: Props) {
return null;
}
if (placeholder || (isResolvingUri && !claim)) {
if (placeholder === 'loading' || (isResolvingUri && !claim)) {
return (
<li className="claim-preview" disabled>
<li className={classnames('claim-preview', { 'claim-preview--large': type === 'large' })} disabled>
<div className="placeholder media__thumb" />
<div className="placeholder__wrapper">
<div className="placeholder claim-preview-title" />
@ -128,11 +132,14 @@ function ClaimPreview(props: Props) {
return (
<li
role="link"
onClick={pending ? undefined : onClick}
onClick={pending || type === 'inline' ? undefined : onClick}
onContextMenu={handleContextMenu}
className={classnames('claim-preview', {
'claim-preview--small': type === 'small' || type === 'tooltip',
'claim-preview--large': type === 'large',
'claim-preview--visited': !isChannel && hasVisitedUri,
'claim-preview--inline': type === 'inline',
'claim-preview--tooltip': type === 'tooltip',
'claim-preview--visited': !isChannel && !claimIsMine && hasVisitedUri,
'claim-preview--pending': pending,
})}
>
@ -140,9 +147,9 @@ function ClaimPreview(props: Props) {
<div className="claim-preview-metadata">
<div className="claim-preview-info">
<div className="claim-preview-title">
<TruncatedText text={title || (claim && claim.name)} lines={1} />
{claim ? <TruncatedText text={title || claim.name} lines={1} /> : <span>{__('Nothing here')}</span>}
</div>
{type !== 'small' && (
{!hideActions && (
<div>
{isChannel && <SubscribeButton uri={uri.startsWith('lbry://') ? uri : `lbry://${uri}`} />}
{!isChannel && <FileProperties uri={uri} />}
@ -152,11 +159,29 @@ function ClaimPreview(props: Props) {
<div className="claim-preview-properties">
<div className="media__subtitle">
<UriIndicator uri={uri} link />
{pending && <div>Pending...</div>}
<div>{isChannel ? `${claimsInChannel} ${__('publishes')}` : <DateTime timeAgo uri={uri} />}</div>
{!isResolvingUri && (
<div>
{claim ? (
<UriIndicator uri={uri} link addTooltip={includeChannelTooltip} />
) : (
<Fragment>
<div>{__('Publish something and claim this spot!')}</div>
<div className="card__actions">
<Button button="primary" label={`${__('Publish to')} ${uri}`} />
</div>
</Fragment>
)}
<div>
{isChannel ? (
type !== 'inline' && `${claimsInChannel} ${__('publishes')}`
) : (
<DateTime timeAgo uri={uri} />
)}
</div>
</div>
)}
</div>
<ClaimTags uri={uri} type={type} />
</div>
</div>

View file

@ -16,22 +16,17 @@ function Comment(props: Props) {
return (
<li className="comment">
<div className="comment__meta">
<Button className="button--uri-indicator truncated-text comment__author" navigate={authorUri} label={author} />
<Button
className="button--uri-indicator truncated-text comment__author"
navigate={authorUri}
label={author || __('Anonymous')}
/>
<time className="comment__time" dateTime={timePosted}>
{relativeDate(timePosted)}
</time>
</div>
<p className={'comment__message'}>{message}</p>
{/* The following is for adding threaded replies, upvoting and downvoting */}
{/* <div className="comment__actions card__actions--between"> */}
{/* <button className={'button button--primary'}>Reply</button> */}
{/* <span className="comment__actions-wrap"> */}
{/* <button className="comment__action upvote">Up</button> */}
{/* <button className="comment__action downvote">Down</button> */}
{/* </span> */}
{/* </div> */}
</li>
);
}

View file

@ -39,7 +39,7 @@ export function CommentCreate(props: Props) {
return (
<section>
{commentAck !== true && (
<div className="card__content markdown-preview">
<div>
<p>{__('A few things to know before participating in the comment alpha:')}</p>
<ul>
<li>
@ -66,20 +66,16 @@ export function CommentCreate(props: Props) {
)}
{commentAck === true && (
<Form onSubmit={handleSubmit}>
<div className="card__content">
<ChannelSection channel={channel} onChannelChange={handleChannelChange} />
</div>
<div className="card__content">
<FormField
disabled={channel === CHANNEL_NEW}
type="textarea"
name="content_description"
label={__('Comment')}
placeholder={__('Your comment')}
value={commentValue}
onChange={handleCommentChange}
/>
</div>
<ChannelSection channel={channel} onChannelChange={handleChannelChange} />
<FormField
disabled={channel === CHANNEL_NEW}
type="textarea"
name="content_description"
label={__('Comment')}
placeholder={__('Your comment')}
value={commentValue}
onChange={handleCommentChange}
/>
<div className="card__actions">
<Button
button="primary"

View file

@ -2,11 +2,9 @@
import type { ElementRef } from 'react';
import React from 'react';
import ReactDOMServer from 'react-dom/server';
import Toggle from 'react-toggle';
import SimpleMDE from 'react-simplemde-editor';
import MarkdownPreview from 'component/common/markdown-preview-internal';
import { openEditorMenu, stopContextMenu } from 'util/context-menu';
import 'easymde/dist/easymde.min.css';
type Props = {
@ -107,15 +105,6 @@ export class FormField extends React.PureComponent<Props> {
</checkbox-element>
</Wrapper>
);
} else if (type === 'setting') {
// 'setting' should only be used for settings. Forms should use "checkbox"
input = (
<input-submit>
{labelOnLeft && <label htmlFor={name}>{label}</label>}
<Toggle id={name} {...inputProps} />
{!labelOnLeft && <label htmlFor={name}>{label}</label>}
</input-submit>
);
} else if (type === 'select') {
input = (
<fieldset-section>

View file

@ -187,8 +187,8 @@ export const icons = {
),
[ICONS.COPY]: buildIcon(
<g>
<path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2" />
<rect x="8" y="2" width="8" height="4" rx="1" ry="1" />
<rect x="9" y="9" width="13" height="13" rx="2" ry="2" />
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" />
</g>
),
[ICONS.REMOVE]: buildIcon(
@ -212,7 +212,7 @@ export const icons = {
[ICONS.NO]: buildIcon(
<path d="M10 15v4a3 3 0 0 0 3 3l4-9V2H5.72a2 2 0 0 0-2 1.7l-1.38 9a2 2 0 0 0 2 2.3zm7-13h2.67A2.31 2.31 0 0 1 22 4v7a2.31 2.31 0 0 1-2.33 2H17" />
),
[ICONS.UP]: buildIcon(<polyline points="18 15 12 9 6 15" />),
[ICONS.UP]: buildIcon(<polyline transform="translate(-5.000) scale(1.1, 1.1)" points="18 15 12 9 6 15" />),
[ICONS.DOWN]: buildIcon(<polyline points="6 9 12 15 18 9" />),
[ICONS.FULLSCREEN]: buildIcon(
<path d="M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3" />

View file

@ -4,7 +4,7 @@ import Button from 'component/button';
export default function UnsupportedOnWeb() {
return (
IS_WEB && (
<div className="card__content help help--warning">
<div className="help help--warning">
This page is not currently supported on the web.{' '}
<Button button="link" label={__('Download the desktop app')} href="https://lbry.com/get" /> for full feature
support.

View file

@ -19,16 +19,15 @@ class FileDetails extends PureComponent<Props> {
const { claim, contentType, fileInfo, metadata, openFolder } = this.props;
if (!claim || !metadata) {
return (
<div className="card__content">
<span className="empty">{__('Empty claim or metadata info.')}</span>
</div>
);
return <span className="empty">{__('Empty claim or metadata info.')}</span>;
}
const { description, languages, license } = metadata;
const mediaType = contentType || 'unknown';
const fileSize = metadata.source.size
? formatBytes(metadata.source.size)
: fileInfo && fileInfo.download_path && formatBytes(fileInfo.written_bytes);
let downloadPath = fileInfo && fileInfo.download_path ? path.normalize(fileInfo.download_path) : null;
let downloadNote;
// If the path is blank, file is not avialable. Create path from name so the folder opens on click.
@ -54,6 +53,13 @@ class FileDetails extends PureComponent<Props> {
{': '}
{mediaType}
</div>
{fileSize && (
<div>
{__('File Size')}
{': '}
{fileSize}
</div>
)}
<div>
{__('Languages')}
{': '}
@ -85,5 +91,17 @@ class FileDetails extends PureComponent<Props> {
);
}
}
// move this with other helper functions when we re-use it
function formatBytes(bytes, decimals = 2) {
if (bytes === 0) return '0 Bytes';
const k = 1024;
const dm = decimals < 0 ? 0 : decimals;
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
}
export default FileDetails;

View file

@ -62,7 +62,7 @@ class FileDownloadLink extends React.PureComponent<Props> {
const progress = fileInfo && fileInfo.written_bytes ? (fileInfo.written_bytes / fileInfo.total_bytes) * 100 : 0;
const label = fileInfo ? __('Downloading: ') + progress.toFixed(0) + __('% complete') : __('Connecting...');
return <span className="file-download">{label}</span>;
return <span>{label}</span>;
} else if ((fileInfo === null && !downloading) || (fileInfo && !fileInfo.download_path)) {
if (!costInfo) {
return null;

View file

@ -316,7 +316,7 @@ class MediaPlayer extends React.PureComponent<Props, State> {
playableType(): boolean {
const { mediaType } = this.props;
return ['audio', 'video'].indexOf(mediaType) !== -1;
return ['audio', 'video', 'image'].indexOf(mediaType) !== -1;
}
isRenderMediaSupported() {

View file

@ -86,6 +86,10 @@ const Header = (props: Props) => {
<Icon aria-hidden icon={ICONS.OVERVIEW} />
{__('Overview')}
</MenuItem>
<MenuItem className="menu__link" onSelect={() => history.push(`/$/rewards`)}>
<Icon aria-hidden icon={ICONS.FEATURED} />
{__('Rewards')}
</MenuItem>
<MenuItem className="menu__link" onSelect={() => history.push(`/$/wallet`)}>
<Icon aria-hidden icon={ICONS.WALLET} />
{__('Wallet')}

View file

@ -1,6 +1,7 @@
// @flow
import React from 'react';
import Button from 'component/button';
import classnames from 'classnames';
type Props = {
numberOfNsfwClaims: number,
@ -14,7 +15,7 @@ export default (props: Props) => {
return (
obscureNsfw &&
Boolean(numberOfNsfwClaims) && (
<div className={className || 'help'}>
<div className={classnames('card--section', className || 'help')}>
{numberOfNsfwClaims} {numberOfNsfwClaims > 1 ? __('files') : __('file')} {__('hidden due to your')}{' '}
<Button button="link" navigate="/$/settings" label={__('content viewing preferences')} />.
</div>

View file

@ -48,9 +48,9 @@ class InviteList extends React.PureComponent<Props> {
const showClaimable = invitees.some(invite => invite.invite_reward_claimable && !invite.invite_reward_claimed);
return (
<section className="card card--section">
<header className="card__header">
<h2 className="card__title card__title--flex-between">
<section className="card">
<div className="table__header">
<h2 className="card__title">
{__('Invite History')}
{referralReward && showClaimable && (
<RewardLink
@ -60,42 +60,39 @@ class InviteList extends React.PureComponent<Props> {
/>
)}
</h2>
</header>
<div className="card__content">
<table className="table table--invites">
<thead>
<tr>
<th>{__('Invitee Email')}</th>
<th>{__('Invite Status')}</th>
<th>{__('Reward')}</th>
</tr>
</thead>
<tbody>
{invitees.map(invitee => (
<tr key={invitee.email}>
<td>{invitee.email}</td>
<td>
<span>{invitee.invite_accepted ? __('Accepted') : __('Not Accepted')}</span>
</td>
<td>
{invitee.invite_reward_claimed && (
<React.Fragment>
<span>{__('Claimed')}</span>
<Icon icon={ICONS.COMPLETE} />
</React.Fragment>
)}
{!invitee.invite_reward_claimed &&
(invitee.invite_reward_claimable ? <span>{__('Claimable')}</span> : __('Unclaimable'))}
</td>
</tr>
))}
</tbody>
</table>
<div className="help">{rewardHelp}</div>
<p className="card__subtitle">{rewardHelp}</p>
</div>
<table className="table table--invites">
<thead>
<tr>
<th>{__('Invitee Email')}</th>
<th>{__('Invite Status')}</th>
<th>{__('Reward')}</th>
</tr>
</thead>
<tbody>
{invitees.map(invitee => (
<tr key={invitee.email}>
<td>{invitee.email}</td>
<td>
<span>{invitee.invite_accepted ? __('Accepted') : __('Not Accepted')}</span>
</td>
<td>
{invitee.invite_reward_claimed && (
<React.Fragment>
<span>{__('Claimed')}</span>
<Icon icon={ICONS.COMPLETE} />
</React.Fragment>
)}
{!invitee.invite_reward_claimed &&
(invitee.invite_reward_claimable ? <span>{__('Claimable')}</span> : __('Unclaimable'))}
</td>
</tr>
))}
</tbody>
</table>
</section>
);
}

View file

@ -48,7 +48,9 @@ class FormInviteNew extends React.PureComponent<FormProps, FormState> {
name="email"
value={this.state.email}
error={errorMessage}
inputButton={<Button button="inverse" type="submit" label="Invite" disabled={isPending} />}
inputButton={
<Button button="inverse" type="submit" label="Invite" disabled={isPending || !this.state.email} />
}
onChange={event => {
this.handleEmailChanged(event);
}}
@ -72,30 +74,23 @@ class InviteNew extends React.PureComponent<Props> {
return (
<section className="card card--section">
<header className="card__header">
<h2 className="card__title">{__('Invite a Friend')}</h2>
<h2 className="card__title">{__('Invite a Friend')}</h2>
<p className="card__subtitle">{__('When your friends start using LBRY, the network gets stronger!')}</p>
<p className="card__subtitle">{__('When your friends start using LBRY, the network gets stronger!')}</p>
</header>
<FormInviteNew
errorMessage={errorMessage}
inviteNew={inviteNew}
isPending={isPending}
rewardAmount={rewardAmount}
/>
<CopyableText label={__('Or share this link with your friends')} copyable={referralLink} />
<div className="card__content">
<FormInviteNew
errorMessage={errorMessage}
inviteNew={inviteNew}
isPending={isPending}
rewardAmount={rewardAmount}
/>
</div>
<div className="card__content">
<CopyableText label={__('Or share this link with your friends')} copyable={referralLink} />
<p className="help">
{__('Earn')} <Button button="link" navigate="/$/rewards" label={__('rewards')} />{' '}
{__('for inviting your friends.')} {__('Read our')}{' '}
<Button button="link" label={__('FAQ')} href="https://lbry.com/faq/referrals" />{' '}
{__('to learn more about referrals')}.
</p>
</div>
<p className="help">
{__('Earn')} <Button button="link" navigate="/$/rewards" label={__('rewards')} />{' '}
{__('for inviting your friends.')} {__('Read our')}{' '}
<Button button="link" label={__('FAQ')} href="https://lbry.com/faq/referrals" />{' '}
{__('to learn more about referrals')}.
</p>
</section>
);
}

View file

@ -78,7 +78,7 @@ class UserHistoryPage extends React.PureComponent<Props, State> {
return historyItems.length ? (
<React.Fragment>
<div className="card__header card__actions card__actions--between">
<div className="card__actions">
{Object.keys(itemsSelected).length ? (
<Button button="link" label={__('Delete')} onClick={this.removeSelected} />
) : (
@ -87,7 +87,7 @@ class UserHistoryPage extends React.PureComponent<Props, State> {
<Button button="link" label={allSelected ? __('Cancel') : __('Select All')} onClick={selectHandler} />
</div>
{!!historyItems.length && (
<section className="card card__content item-list">
<section className="card item-list">
{historyItems.map(item => (
<NavigationHistoryItem
key={item.uri}
@ -106,14 +106,10 @@ class UserHistoryPage extends React.PureComponent<Props, State> {
) : (
<div className="main--empty">
<section className="card card--section">
<header className="card__header">
<h2 className="card__title">{__('Your history is empty, what are you doing here?')}</h2>
</header>
<h2 className="card__title">{__('Your history is empty, what are you doing here?')}</h2>
<div className="card__content">
<div className="card__actions card__actions--center">
<Button button="primary" navigate="/" label={__('Explore new content')} />
</div>
<div className="card__actions card__actions--center">
<Button button="primary" navigate="/" label={__('Explore new content')} />
</div>
</section>
</div>

View file

@ -17,11 +17,9 @@ export default function NavigationHistoryRecent(props: Props) {
return history.length ? (
<div className="card item-list">
<section className="card__content">
{history.map(({ lastViewed, uri }) => (
<NavigationHistoryItem slim key={uri} uri={uri} lastViewed={lastViewed} />
))}
</section>
{history.map(({ lastViewed, uri }) => (
<NavigationHistoryItem slim key={uri} uri={uri} lastViewed={lastViewed} />
))}
<div className="card__actions">
<Button navigate="/$/library/all" button="link" label={__('See All Visited Links')} />
</div>

View file

@ -38,11 +38,11 @@ class PreviewLink extends React.PureComponent<Props> {
<TruncatedText text={title} lines={1} />
</span>
</span>
<span className={'preview-link__description media__subtext'}>
<span className={'preview-link__description media__subtitle'}>
<UriIndicator uri={uri} link />
</span>
<span className={'file-list__item-properties'}>
<span className={'preview-link__description media__subtext'}>
<span className={'preview-link__description media__subtitle'}>
<TruncatedText lines={2} showTooltip={false}>
<MarkdownPreview content={description} promptLinks strip />
</TruncatedText>

View file

@ -27,7 +27,7 @@ function PublishAdvanced(props: Props) {
return (
<section className="card card--section">
{!hideSection && (
<div className={classnames('card__content', { 'card--disabled': !name })}>
<div className={classnames({ 'card--disabled': !name })}>
<FormField
label={__('Language')}
type="select"

View file

@ -33,10 +33,8 @@ function PublishFile(props: Props) {
'card--disabled': balance === 0,
})}
>
<header className="card__header">
<h2 className="card__title card__title--flex-between">{isStillEditing ? __('Edit') : __('Publish')}</h2>
{isStillEditing && <p className="card__subtitle">{__('You are currently editing a claim.')}</p>}
</header>
<h2 className="card__title">{isStillEditing ? __('Edit') : __('Publish')}</h2>
{isStillEditing && <p className="card__subtitle">{__('You are currently editing a claim.')}</p>}
<div className="card__content">
<FileSelector currentPath={filePath} onFileChosen={handleFileChange} />

View file

@ -1,7 +1,7 @@
// @flow
import React, { useEffect, Fragment } from 'react';
import { CHANNEL_NEW, CHANNEL_ANONYMOUS } from 'constants/claim';
import { buildURI, isURIValid, THUMBNAIL_STATUSES } from 'lbry-redux';
import { buildURI, isURIValid, isNameValid, THUMBNAIL_STATUSES } from 'lbry-redux';
import Button from 'component/button';
import ChannelSection from 'component/selectChannel';
import classnames from 'classnames';
@ -77,7 +77,8 @@ function PublishForm(props: Props) {
} = props;
const formDisabled = (!filePath && !editingURI) || publishing;
// If they are editing, they don't need a new file chosen
const formValidLessFile = name && title && bid && !(uploadThumbnailStatus === THUMBNAIL_STATUSES.IN_PROGRESS);
const formValidLessFile =
name && isNameValid(name, false) && title && bid && !(uploadThumbnailStatus === THUMBNAIL_STATUSES.IN_PROGRESS);
const formValid = editingURI && !filePath ? isStillEditing && formValidLessFile : formValidLessFile;
let submitLabel;
@ -130,7 +131,7 @@ function PublishForm(props: Props) {
{/* This should probably be PublishThumbnail */}
<SelectThumbnail />
</div>
<div className="card">
<div className="card card--section">
<TagSelect
title={false}
suggestMature
@ -152,20 +153,18 @@ function PublishForm(props: Props) {
/>
</div>
<section className="card card--section">
<div className="card__content">
<ChannelSection channel={channel} onChannelChange={channel => updatePublishForm({ channel })} />
<p className="help">
{__('This is a username or handle that your content can be found under.')}{' '}
{__('Ex. @Marvel, @TheBeatles, @BooksByJoe')}
</p>
</div>
<ChannelSection channel={channel} onChannelChange={channel => updatePublishForm({ channel })} />
<p className="help">
{__('This is a username or handle that your content can be found under.')}{' '}
{__('Ex. @Marvel, @TheBeatles, @BooksByJoe')}
</p>
</section>
<PublishName disabled={formDisabled} />
<PublishPrice disabled={formDisabled} />
<PublishAdditionalOptions disabled={formDisabled} />
<section className="card card--section">
<section>
{!formDisabled && !formValid && <PublishFormErrors />}
<div className="card__actions">

View file

@ -1,6 +1,6 @@
// @flow
import React from 'react';
import { THUMBNAIL_STATUSES } from 'lbry-redux';
import { THUMBNAIL_STATUSES, isNameValid } from 'lbry-redux';
type Props = {
title: ?string,
@ -18,9 +18,10 @@ function PublishFormErrors(props: Props) {
// These are extra help
// If there is an error it will be presented as an inline error as well
return (
<div className="card__content error-text">
<div className="error-text">
{!title && <div>{__('A title is required')}</div>}
{!name && <div>{__('A URL is required')}</div>}
{!isNameValid(name, false) && __('LBRY names cannot contain spaces or reserved symbols ($#@;/"<>%{}|^~[]`)')}
{!bid && <div>{__('A deposit amount is required')}</div>}
{uploadThumbnailStatus === THUMBNAIL_STATUSES.IN_PROGRESS && (
<div>{__('Please wait for thumbnail to finish uploading')}</div>

View file

@ -74,30 +74,28 @@ function PublishName(props: Props) {
return (
<section className="card card--section">
<div className="card__content">
<fieldset-group class="fieldset-group--smushed fieldset-group--disabled-prefix">
<fieldset-section>
<label>{__('Name')}</label>
<span className="form-field__prefix">{`lbry://${
!channel || channel === CHANNEL_ANONYMOUS || channel === CHANNEL_NEW ? '' : `${channel}/`
}`}</span>
</fieldset-section>
<FormField
type="text"
name="content_name"
value={name}
error={nameError}
onChange={event => updatePublishForm({ name: event.target.value })}
/>
</fieldset-group>
<div className="form-field__help">
<NameHelpText
uri={uri}
isStillEditing={isStillEditing}
myClaimForUri={myClaimForUri}
onEditMyClaim={editExistingClaim}
/>
</div>
<fieldset-group class="fieldset-group--smushed fieldset-group--disabled-prefix">
<fieldset-section>
<label>{__('Name')}</label>
<div className="form-field__prefix">{`lbry://${
!channel || channel === CHANNEL_ANONYMOUS || channel === CHANNEL_NEW ? '' : `${channel}/`
}`}</div>
</fieldset-section>
<FormField
type="text"
name="content_name"
value={name}
error={nameError}
onChange={event => updatePublishForm({ name: event.target.value })}
/>
</fieldset-group>
<div className="form-field__help">
<NameHelpText
uri={uri}
isStillEditing={isStillEditing}
myClaimForUri={myClaimForUri}
onEditMyClaim={editExistingClaim}
/>
</div>
<FormField
type="number"

View file

@ -9,47 +9,45 @@ type Props = {
updatePublishForm: ({}) => void,
};
function PublishText(props: Props) {
function PublishPrice(props: Props) {
const { contentIsFree, fee, updatePublishForm, disabled } = props;
return (
<section className="card card--section">
<div className="card__content">
<FormField
type="radio"
name="content_free"
label={__('Free')}
checked={contentIsFree}
disabled={disabled}
onChange={() => updatePublishForm({ contentIsFree: true })}
/>
<FormField
type="radio"
name="content_free"
label={__('Free')}
checked={contentIsFree}
disabled={disabled}
onChange={() => updatePublishForm({ contentIsFree: true })}
/>
<FormField
type="radio"
name="content_cost"
label={__('Add a price to this file')}
checked={!contentIsFree}
disabled={disabled}
onChange={() => updatePublishForm({ contentIsFree: false })}
<FormField
type="radio"
name="content_cost"
label={__('Add a price to this file')}
checked={!contentIsFree}
disabled={disabled}
onChange={() => updatePublishForm({ contentIsFree: false })}
/>
{!contentIsFree && (
<FormFieldPrice
name="content_cost_amount"
min="0"
price={fee}
onChange={newFee => updatePublishForm({ fee: newFee })}
/>
{!contentIsFree && (
<FormFieldPrice
name="content_cost_amount"
min="0"
price={fee}
onChange={newFee => updatePublishForm({ fee: newFee })}
/>
)}
{fee && fee.currency !== 'LBC' && (
<p className="form-field__help">
{__(
'All content fees are charged in LBC. For non-LBC payment methods, the number of credits charged will be adjusted based on the value of LBRY credits at the time of purchase.'
)}
</p>
)}
</div>
)}
{fee && fee.currency !== 'LBC' && (
<p className="form-field__help">
{__(
'All content fees are charged in LBC. For non-LBC payment methods, the number of credits charged will be adjusted based on the value of LBRY credits at the time of purchase.'
)}
</p>
)}
</section>
);
}
export default PublishText;
export default PublishPrice;

View file

@ -20,29 +20,27 @@ function PublishText(props: Props) {
return (
<section className="card card--section">
<div className="card__content">
<FormField
type="text"
name="content_title"
label={__('Title')}
placeholder={__('Titular Title')}
disabled={disabled}
value={title}
onChange={e => updatePublishForm({ title: e.target.value })}
/>
<FormField
type="text"
name="content_title"
label={__('Title')}
placeholder={__('Titular Title')}
disabled={disabled}
value={title}
onChange={e => updatePublishForm({ title: e.target.value })}
/>
<FormField
type={advancedEditor ? 'markdown' : 'textarea'}
name="content_description"
label={__('Description')}
placeholder={__('My description for this and that')}
value={description}
disabled={disabled}
onChange={value => updatePublishForm({ description: advancedEditor ? value : value.target.value })}
/>
<div className="card__actions">
<Button button="link" onClick={toggleMarkdown} label={advancedEditor ? 'Simple Editor' : 'Advanced Editor'} />
</div>
<FormField
type={advancedEditor ? 'markdown' : 'textarea'}
name="content_description"
label={__('Description')}
placeholder={__('My description for this and that')}
value={description}
disabled={disabled}
onChange={value => updatePublishForm({ description: advancedEditor ? value : value.target.value })}
/>
<div className="card__actions">
<Button button="link" onClick={toggleMarkdown} label={advancedEditor ? 'Simple Editor' : 'Advanced Editor'} />
</div>
</section>
);

View file

@ -56,8 +56,8 @@ export default class RecommendedContent extends React.PureComponent<Props> {
type="small"
loading={isSearching}
uris={recommendedContent}
header={<span>{__('Related')}</span>}
empty={<div className="empty">{__('No related content found')}</div>}
header={__('Related')}
empty={__('No related content found')}
/>
</section>
);

View file

@ -35,7 +35,7 @@ const RewardListClaimed = (props: Props) => {
</p>
</header>
<table className="card__content table table--rewards">
<table className="table table--rewards">
<thead>
<tr>
<th>{__('Title')}</th>

View file

@ -14,9 +14,7 @@ class RewardSummary extends React.Component<Props> {
const hasRewards = unclaimedRewardAmount > 0;
return (
<section className="card card--section">
<header className="card__header">
<h2 className="card__title">{__('Rewards')}</h2>
</header>
<h2 className="card__title">{__('Rewards')}</h2>
<p className="card__subtitle">
{fetching && __('You have...')}
@ -34,15 +32,13 @@ class RewardSummary extends React.Component<Props> {
)}
</p>
<div className="card__content">
<div className="card__actions">
<Button
button="primary"
navigate="/$/rewards"
label={hasRewards ? __('Claim Rewards') : __('View Rewards')}
/>
<Button button="link" label={__('Learn more')} href="https://lbry.com/faq/rewards" />.
</div>
<div className="card__actions">
<Button
button="primary"
navigate="/$/rewards"
label={hasRewards ? __('Claim Rewards') : __('View Rewards')}
/>
<Button button="link" label={__('Learn more')} href="https://lbry.com/faq/rewards" />.
</div>
</section>
);

View file

@ -25,28 +25,24 @@ const RewardTile = (props: Props) => {
return (
<section className="card card--section">
<header className="card__header">
<h2 className="card__title">{reward.reward_title}</h2>
<p className="card__subtitle">{reward.reward_description}</p>
</header>
<h2 className="card__title">{reward.reward_title}</h2>
<p className="card__subtitle">{reward.reward_description}</p>
<div className="card__content">
<div className="card__actions">
{reward.reward_type === rewards.TYPE_GENERATED_CODE && (
<Button button="inverse" onClick={openRewardCodeModal} label={__('Enter Code')} />
)}
{reward.reward_type === rewards.TYPE_REFERRAL && (
<Button button="inverse" navigate="/$/invite" label={__('Go To Invites')} />
)}
{reward.reward_type !== rewards.TYPE_REFERRAL &&
(claimed ? (
<span>
<Icon icon={ICONS.COMPLETED} /> {__('Reward claimed.')}
</span>
) : (
<RewardLink button reward_type={reward.reward_type} />
))}
</div>
<div className="card__actions">
{reward.reward_type === rewards.TYPE_GENERATED_CODE && (
<Button button="inverse" onClick={openRewardCodeModal} label={__('Enter Code')} />
)}
{reward.reward_type === rewards.TYPE_REFERRAL && (
<Button button="inverse" navigate="/$/invite" label={__('Go To Invites')} />
)}
{reward.reward_type !== rewards.TYPE_REFERRAL &&
(claimed ? (
<span>
<Icon icon={ICONS.COMPLETED} /> {__('Reward claimed.')}
</span>
) : (
<RewardLink button reward_type={reward.reward_type} />
))}
</div>
</section>
);

View file

@ -16,9 +16,7 @@ function RewardTotal(props: Props) {
return (
<section className="card card--section card--reward-total" style={{ backgroundImage: `url(${TotalBackground})` }}>
<span className="card__title">
{integer} LBC {__('Earned From Rewards')}
</span>
{integer} LBC {__('Earned From Rewards')}
</section>
);
}

View file

@ -8,7 +8,7 @@ import Button from 'component/button';
const ExpandableOptions = posed.div({
hide: { height: 0, opacity: 0 },
show: { height: 300, opacity: 1 },
show: { height: 380, opacity: 1 },
});
type Props = {
@ -32,7 +32,7 @@ const SearchOptions = (props: Props) => {
/>
<ExpandableOptions pose={expanded ? 'show' : 'hide'}>
{expanded && (
<Form className="card__content search__options">
<Form className="search__options">
<fieldset>
<legend className="search__legend--1">{__('Search For')}</legend>
{[

View file

@ -1,5 +1,5 @@
// @flow
import React from 'react';
import React, { Fragment } from 'react';
import { isNameValid } from 'lbry-redux';
import { FormField } from 'component/common/form';
import BusyIndicator from 'component/common/busy-indicator';
@ -76,8 +76,8 @@ class ChannelSection extends React.PureComponent<Props, State> {
}
let newChannelNameError;
if (newChannelName.length > 1 && !isNameValid(newChannelName.substr(1), false)) {
newChannelNameError = __('LBRY channel names must contain only letters, numbers and dashes.');
if (newChannelName.length > 0 && !isNameValid(newChannelName, false)) {
newChannelNameError = __('LBRY names cannot contain spaces or reserved symbols ($#@;/"<>%{}|^~[]`)');
}
this.setState({
@ -107,7 +107,7 @@ class ChannelSection extends React.PureComponent<Props, State> {
const { balance, createChannel, onChannelChange } = this.props;
const { newChannelBid, newChannelName } = this.state;
const channelName = `@${newChannelName}`;
const channelName = `@${newChannelName.trim()}`;
if (newChannelBid > balance) {
return;
@ -151,7 +151,7 @@ class ChannelSection extends React.PureComponent<Props, State> {
} = this.state;
return (
<div className="card__content">
<Fragment>
{createChannelError && <div className="error-text">{createChannelError}</div>}
{fetchingChannels ? (
<BusyIndicator message="Updating channels" />
@ -175,7 +175,7 @@ class ChannelSection extends React.PureComponent<Props, State> {
</fieldset-section>
)}
{addingChannel && (
<div className="card__content">
<div>
<FormField
label={__('Name')}
name="channel-input"
@ -211,7 +211,7 @@ class ChannelSection extends React.PureComponent<Props, State> {
</div>
</div>
)}
</div>
</Fragment>
);
}
}

View file

@ -83,7 +83,7 @@ class SelectThumbnail extends React.PureComponent<Props, State> {
*/
return (
<div className="card__content">
<div>
{status === THUMBNAIL_STATUSES.API_DOWN || status === THUMBNAIL_STATUSES.MANUAL ? (
<div className="column">
<div className="column__item thumbnail-preview" style={{ backgroundImage: `url(${thumbnailSrc})` }}>

View file

@ -24,9 +24,9 @@ function SideBar(props: Props) {
}
return (
<StickyBox offsetBottom={40} offsetTop={100}>
<StickyBox offsetTop={100} offsetBottom={20}>
<nav className="navigation">
<ul className="navigation__links">
<ul className="navigation-links">
{[
{
...buildLink(null, __('Home'), ICONS.HOME),
@ -42,25 +42,25 @@ function SideBar(props: Props) {
},
].map(linkProps => (
<li key={linkProps.label}>
<Button {...linkProps} className="navigation__link" activeClass="navigation__link--active" />
<Button {...linkProps} className="navigation-link" activeClass="navigation-link--active" />
</li>
))}
</ul>
<ul className="navigation__links tags--vertical">
<ul className="navigation-links tags--vertical">
{followedTags.map(({ name }, key) => (
<li className="" key={name}>
<li className="navigation-link__wrapper" key={name}>
<Tag navigate={`/$/tags?t${name}`} name={name} />
</li>
))}
</ul>
<ul className="navigation__links--small">
<ul className="navigation-links--small">
{subscriptions.map(({ uri, channelName }, index) => (
<li key={uri} className="">
<li key={uri} className="navigation-link__wrapper">
<Button
navigate={uri}
label={channelName}
className="navigation__link"
activeClass="navigation__link--active"
className="navigation-link"
activeClass="navigation-link--active"
/>
</li>
))}

View file

@ -44,9 +44,8 @@ class SocialShare extends React.PureComponent<Props> {
return (
<React.Fragment>
{speechShareable && (
<div className="card__content">
<label className="card__subtitle">{__('Web link')}</label>
<CopyableText copyable={lbryTvUrl} />
<div>
<CopyableText label={__('Web link')} copyable={lbryTvUrl} />
<div className="card__actions card__actions--center">
<Button
icon={ICONS.FACEBOOK}
@ -58,29 +57,27 @@ class SocialShare extends React.PureComponent<Props> {
icon={ICONS.TWITTER}
button="link"
description={shareOnTwitter}
href={`https://twitter.com/home?status=${encodedLbryTvUrl}`}
href={`https://twitter.com/intent/tweet?text=${encodedLbryTvUrl}`}
/>
<Button icon={ICONS.WEB} button="link" description={__('View on lbry.tv')} href={`${lbryTvUrl}`} />
</div>
</div>
)}
<div className="card__content">
<label className="card__subtitle">{__('LBRY App link')}</label>
<CopyableText copyable={lbryURL} noSnackbar />
<div className="card__actions card__actions--center">
<Button
icon={ICONS.FACEBOOK}
button="link"
description={shareOnFb}
href={`https://facebook.com/sharer/sharer.php?u=${encodedLbryURL}`}
/>
<Button
icon={ICONS.TWITTER}
button="link"
description={shareOnTwitter}
href={`https://twitter.com/home?status=${encodedLbryURL}`}
/>
</div>
<CopyableText label={__('LBRY App Link')} copyable={lbryURL} noSnackbar />
<div className="card__actions card__actions--center">
<Button
icon={ICONS.FACEBOOK}
button="link"
description={shareOnFb}
href={`https://facebook.com/sharer/sharer.php?u=${encodedLbryURL}`}
/>
<Button
icon={ICONS.TWITTER}
button="link"
description={shareOnTwitter}
href={`https://twitter.com/intent/tweet?text=${encodedLbryURL}`}
/>
</div>
<div className="card__actions">
<Button button="link" label={__('Done')} onClick={onDone} />

View file

@ -54,6 +54,7 @@ export default class SplashScreen extends React.PureComponent<Props, State> {
componentDidMount() {
const { checkDaemonVersion } = this.props;
this.adjustErrorTimeout();
Lbry.connect()
.then(checkDaemonVersion)
.then(() => {

View file

@ -74,7 +74,7 @@ export default function TagSelect(props: Props) {
<div>
<Form onSubmit={handleSubmit}>
<FormField
label={__('Tag Search')}
label={__('Find New Tags')}
onChange={onChange}
placeholder={__('Search for more tags')}
type="text"

View file

@ -21,6 +21,7 @@ type Props = {
tagsChosen?: Array<Tag>,
onSelect?: Tag => void,
onRemove?: Tag => void,
className?: string,
};
const tagsAnimation = {
@ -41,6 +42,7 @@ export default function TagSelect(props: Props) {
onSelect,
onRemove,
suggestMature,
className,
} = props;
const [hasClosed, setHasClosed] = usePersistedState('tag-select:has-closed', false);
const tagsToDisplay = tagsChosen || followedTags;
@ -65,39 +67,37 @@ export default function TagSelect(props: Props) {
return (
((showClose && !hasClosed) || !showClose) && (
<div className="card--section">
<div className={className}>
{title !== false && (
<h2 className="card__title card__title--flex-between">
<h2 className="card__title">
{title}
{showClose && !hasClosed && <Button button="close" icon={ICONS.REMOVE} onClick={handleClose} />}
</h2>
)}
<div className="card__content">
<ul className="tags--remove">
{transitions.map(({ item, props, key }) => (
<animated.li key={key} style={props}>
<Tag
name={item.name}
type="remove"
onClick={() => {
handleTagClick(item);
}}
/>
</animated.li>
))}
{!transitions.length && (
<div className="empty">{empty || __("You aren't following any tags, try searching for one.")}</div>
)}
</ul>
<TagsSearch onSelect={onSelect} suggestMature={suggestMature && !hasMatureTag} />
{help !== false && (
<p className="help">
{help || __("The tags you follow will change what's trending for you. ")}
<Button button="link" label={__('Learn more')} href="https://lbry.com/faq/trending" />.
</p>
<ul className="tags--remove">
{transitions.map(({ item, props, key }) => (
<animated.li key={key} style={props}>
<Tag
name={item.name}
type="remove"
onClick={() => {
handleTagClick(item);
}}
/>
</animated.li>
))}
{!transitions.length && (
<div className="empty">{empty || __("You aren't following any tags, try searching for one.")}</div>
)}
</div>
</ul>
<TagsSearch onSelect={onSelect} suggestMature={suggestMature && !hasMatureTag} />
{help !== false && (
<p className="help">
{help || __("The tags you follow will change what's trending for you.")}{' '}
<Button button="link" label={__('Learn more')} href="https://lbry.com/faq/trending" />.
</p>
)}
</div>
)
);

View file

@ -72,9 +72,9 @@ class TransactionListItem extends React.PureComponent<Props> {
<td className="table__item--actionable">
<span>{this.capitalize(type)}</span> {isRevokeable && this.getLink(type)}
</td>
<td className="table__item--actionable">
<td>
{reward && <span>{reward.reward_title}</span>}
{claimName && claimId ? <Button button="link" navigate={uri} label={claimName} /> : claimName}
{name && claimId && <Button button="link" navigate={uri} label={claimName} />}
</td>
<td>

View file

@ -2,7 +2,7 @@
import * as icons from 'constants/icons';
import * as MODALS from 'constants/modal_types';
import * as React from 'react';
import { FormField, Form } from 'component/common/form';
import { FormField } from 'component/common/form';
import Button from 'component/button';
import FileExporter from 'component/common/file-exporter';
import { TRANSACTIONS } from 'lbry-redux';
@ -69,12 +69,12 @@ class TransactionList extends React.PureComponent<Props> {
return (
<React.Fragment>
<header className="table__header">
<h2 className="card__title card__title--flex-between">
<h2 className="card__title--between">
<span>
{title}
{loading && <Spinner type="small" />}
</span>
<div className="card__actions">
<div className="card__actions--inline">
{slim && (
<Button button="link" className="button--alt" navigate="/$/transactions" label={__('Full History')} />
)}
@ -83,8 +83,8 @@ class TransactionList extends React.PureComponent<Props> {
</h2>
</header>
{!slim && !!transactions.length && (
<header className="card__header table__header">
<div className="card__actions card__actions--between">
<header className="table__header">
<div className="card__actions--between">
<FileExporter
data={transactionList}
label={__('Export')}
@ -93,29 +93,27 @@ class TransactionList extends React.PureComponent<Props> {
defaultPath={__('lbry-transactions-history')}
/>
<Form>
<FormField
type="select"
name="file-sort"
value={filterSetting || TRANSACTIONS.ALL}
onChange={this.handleFilterChanged}
label={__('Show')}
postfix={
<Button
button="link"
icon={icons.HELP}
href="https://lbry.com/faq/transaction-types"
title={__('Help')}
/>
}
>
{transactionTypes.map(tt => (
<option key={tt} value={tt}>
{__(`${this.capitalize(tt)}`)}
</option>
))}
</FormField>
</Form>
<FormField
type="select"
name="file-sort"
value={filterSetting || TRANSACTIONS.ALL}
onChange={this.handleFilterChanged}
label={__('Show')}
postfix={
<Button
button="link"
icon={icons.HELP}
href="https://lbry.com/faq/transaction-types"
title={__('Help')}
/>
}
>
{transactionTypes.map(tt => (
<option key={tt} value={tt}>
{__(`${this.capitalize(tt)}`)}
</option>
))}
</FormField>
</div>
</header>
)}

View file

@ -23,7 +23,7 @@ class TransactionListRecent extends React.PureComponent<Props> {
render() {
const { transactions } = this.props;
return (
<section className="card card__content">
<section className="card">
<TransactionList
slim
title={__('Recent Transactions')}

View file

@ -10,6 +10,7 @@ type Props = {
channelUri: ?string,
link: ?boolean,
claim: ?Claim,
addTooltip: boolean,
// Lint thinks we aren't using these, even though we are.
// Possibly because the resolve function is an arrow function that is passed in props?
resolveUri: string => void,
@ -17,6 +18,10 @@ type Props = {
};
class UriIndicator extends React.PureComponent<Props> {
static defaultProps = {
addTooltip: true,
};
componentDidMount() {
this.resolve(this.props);
}
@ -34,7 +39,7 @@ class UriIndicator extends React.PureComponent<Props> {
};
render() {
const { link, isResolvingUri, claim } = this.props;
const { link, isResolvingUri, claim, addTooltip } = this.props;
if (!claim) {
return <span className="empty">{isResolvingUri ? 'Validating...' : 'Unused'}</span>;
@ -51,9 +56,12 @@ class UriIndicator extends React.PureComponent<Props> {
if (channelClaim) {
const { name, claim_id: claimId } = channelClaim;
let channelLink;
if (claim.is_channel_signature_valid) {
channelLink = link ? buildURI({ channelName: name, claimId }) : false;
}
// Disabling now because it mostly causes issues
// Add this back to ensure we only add links to signed channels
// if (claim.is_channel_signature_valid) {
channelLink = link ? buildURI({ channelName: name, claimId }) : false;
// }
const inner = <span className="channel-name">{name}</span>;
@ -61,9 +69,15 @@ class UriIndicator extends React.PureComponent<Props> {
return inner;
}
const Wrapper = addTooltip
? ({ children }) => (
<Tooltip label={<ClaimPreview uri={channelLink} type="tooltip" placeholder={false} />}>{children}</Tooltip>
)
: 'span';
return (
<Button className="button--uri-indicator" navigate={channelLink}>
<Tooltip label={<ClaimPreview uri={channelLink} type="small" />}>{inner}</Tooltip>
<Wrapper>{inner}</Wrapper>
</Button>
);
} else {

View file

@ -39,13 +39,11 @@ function UserEmail(props: Props) {
{user && email && !isVerified && <UserEmailVerify />}
{email && isVerified && (
<React.Fragment>
<div className="card__header">
<h2 className="card__title">{__('Email')}</h2>
<p className="card__subtitle">
{email && isVerified && __('Your email has been successfully verified')}
{!email && __('')}.
</p>
</div>
<h2 className="card__title">{__('Email')}</h2>
<p className="card__subtitle">
{email && isVerified && __('Your email has been successfully verified')}
{!email && __('')}.
</p>
{isVerified && (
<FormField

View file

@ -48,19 +48,17 @@ class UserEmailNew extends React.PureComponent<Props, State> {
return (
<React.Fragment>
<header className="card__header">
<h2 className="card__title">{__('Verify Your Email')}</h2>
<p className="card__subtitle">
{/* @if TARGET='app' */}
{__("We'll let you know about LBRY updates, security issues, and great new content.")}
{/* @endif */}
{/* @if TARGET='web' */}
{__('Stay up to date with lbry.tv and be the first to know about the progress we make.')}
{/* @endif */}
</p>
</header>
<h2 className="card__title">{__('Verify Your Email')}</h2>
<p className="card__subtitle">
{/* @if TARGET='app' */}
{__("We'll let you know about LBRY updates, security issues, and great new content.")}
{/* @endif */}
{/* @if TARGET='web' */}
{__('Stay up to date with lbry.tv and be the first to know about the progress we make.')}
{/* @endif */}
</p>
<Form className="card__content" onSubmit={this.handleSubmit}>
<Form onSubmit={this.handleSubmit}>
<FormField
type="email"
label="Email"

View file

@ -51,32 +51,27 @@ class UserEmailVerify extends React.PureComponent<Props> {
return (
<React.Fragment>
<header className="card__header">
<h2 className="card__title">{__('Waiting For Verification')}</h2>
</header>
<h2 className="card__title">{__('Waiting For Verification')}</h2>
<div className="card__content">
<p className="card__subtitle">
{__('An email was sent to')} {email}.{' '}
{__('Follow the link and you will be good to go. This will update automatically.')}
</p>
<p className="card__subtitle">
{__('An email was sent to')} {email}.{' '}
{__('Follow the link and you will be good to go. This will update automatically.')}
</p>
<div className="card__actions">
<Button
button="primary"
label={__('Resend verification email')}
onClick={this.handleResendVerificationEmail}
/>
<UserEmailResetButton />
</div>
<p className="help">
{__('Email')} <Button button="link" href="mailto:help@lbry.com" label="help@lbry.com" /> or join our{' '}
<Button button="link" href="https://chat.lbry.com" label="chat" />{' '}
{__('if you encounter any trouble verifying.')}
</p>
<div className="card__actions">
<Button
button="primary"
label={__('Resend verification email')}
onClick={this.handleResendVerificationEmail}
/>
<UserEmailResetButton />
</div>
<p className="help">
{__('Email')} <Button button="link" href="mailto:help@lbry.com" label="help@lbry.com" /> or join our{' '}
<Button button="link" href="https://chat.lbry.com" label="chat" />{' '}
{__('if you encounter any trouble verifying.')}
</p>
</React.Fragment>
);
}

View file

@ -83,37 +83,33 @@ class UserPhoneNew extends React.PureComponent<Props, State> {
return (
<React.Fragment>
<section className="card__content">
<p className="card__subtitle">
{__(
'Enter your phone number and we will send you a verification code. We will not share your phone number with third parties.'
)}
</p>
</section>
<p className="card__subtitle">
{__(
'Enter your phone number and we will send you a verification code. We will not share your phone number with third parties.'
)}
</p>
<Form onSubmit={this.handleSubmit}>
<div className="card__content">
<fieldset-group class="fieldset-group--smushed">
<FormField label={__('Country')} type="select" name="country-codes" onChange={this.handleSelect}>
{countryCodes.map((country, index) => (
<option key={index} value={country.countryCallingCode}>
{os === 'Darwin' ? country.emoji : `(${country.alpha2})`} {country.countryCallingCode}
</option>
))}
</FormField>
<FormField
type="text"
label={__('Number')}
placeholder={this.state.countryCode === '+1' ? '(555) 555-5555' : '5555555555'}
name="phone"
value={this.state.phone}
error={phoneErrorMessage}
onChange={event => {
this.handleChanged(event);
}}
/>
</fieldset-group>
</div>
<fieldset-group class="fieldset-group--smushed">
<FormField label={__('Country')} type="select" name="country-codes" onChange={this.handleSelect}>
{countryCodes.map((country, index) => (
<option key={index} value={country.countryCallingCode}>
{os === 'Darwin' ? country.emoji : `(${country.alpha2})`} {country.countryCallingCode}
</option>
))}
</FormField>
<FormField
type="text"
label={__('Number')}
placeholder={this.state.countryCode === '+1' ? '(555) 555-5555' : '5555555555'}
name="phone"
value={this.state.phone}
error={phoneErrorMessage}
onChange={event => {
this.handleChanged(event);
}}
/>
</fieldset-group>
<div className="card__actions">
<Submit label="Submit" disabled={isPending} />
{cancelButton}

View file

@ -45,14 +45,12 @@ class UserPhoneVerify extends React.PureComponent<Props, State> {
const { cancelButton, phoneErrorMessage, phone, countryCode } = this.props;
return (
<React.Fragment>
<section className="card__content">
<p>
{' '}
{__(`Please enter the verification code sent to +${countryCode}${phone}. Didn't receive it? `)}
<Button button="link" onClick={this.reset.bind(this)} label="Go back." />
</p>
</section>
<Form className="card__content" onSubmit={this.handleSubmit.bind(this)}>
<p>
{' '}
{__(`Please enter the verification code sent to +${countryCode}${phone}. Didn't receive it? `)}
<Button button="link" onClick={this.reset.bind(this)} label="Go back." />
</p>
<Form onSubmit={this.handleSubmit.bind(this)}>
<FormField
type="text"
name="code"

View file

@ -27,35 +27,29 @@ class UserVerify extends React.PureComponent<Props> {
return (
<React.Fragment>
<section className="card card--section">
<header className="card__header--flat">
<h1 className="card__title">{__('Final Human Proof')}</h1>
<p className="card__subtitle">
To start the rewards approval process, please complete <strong>one and only one</strong> of the options
below. This is optional, and can be skipped at the bottom of the page.
</p>
</header>
<h1 className="card__title">{__('Final Human Proof')}</h1>
<p className="card__subtitle">
To start the rewards approval process, please complete <strong>one and only one</strong> of the options
below. This is optional, and can be skipped at the bottom of the page.
</p>
</section>
<section className="card card--section">
<header className="card__header">
<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>
<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>
<div className="card__content">
<div className="card__actions">
<Button
onClick={() => {
verifyPhone();
}}
button="inverse"
label={__('Submit Phone Number')}
/>
</div>
<div className="card__actions">
<Button
onClick={() => {
verifyPhone();
}}
button="inverse"
label={__('Submit Phone Number')}
/>
<div className="help">
{__('Standard messaging rates apply. LBRY will not text or call you otherwise. Having trouble?')}{' '}
@ -65,71 +59,57 @@ class UserVerify extends React.PureComponent<Props> {
</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.'
)} ${__(
'LBRY does not store your credit card information. There is no charge at all for this, now or in the future.'
)} `}
</p>
</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.')} ${__(
'LBRY does not store your credit card information. There is no charge at all for this, now or in the future.'
)} `}
</p>
<div className="card__content">
<div className="card__actions">
{errorMessage && <p className="error-text">{errorMessage}</p>}
<CardVerify
label={__('Perform Card Verification')}
disabled={isPending}
token={this.onToken}
stripeKey={Lbryio.getStripeToken()}
/>
</div>
<div className="card__actions">
{errorMessage && <p className="error-text">{errorMessage}</p>}
<CardVerify
label={__('Perform Card Verification')}
disabled={isPending}
token={this.onToken}
stripeKey={Lbryio.getStripeToken()}
/>
</div>
<div className="help">
{__('A $1 authorization may temporarily appear with your provider.')}{' '}
<Button
button="link"
href="https://lbry.com/faq/identity-requirements"
label={__('Read more about why we do this.')}
/>
</div>
<div className="help">
{__('A $1 authorization may temporarily appear with your provider.')}{' '}
<Button
button="link"
href="https://lbry.com/faq/identity-requirements"
label={__('Read more about why we do this.')}
/>
</div>
</section>
<section className="card card--section">
<header className="card__header">
<h2 className="card__title">{__('3) Proof via Chat')}</h2>
<p className="card__subtitle">
{__(
'A moderator capable of approving you is typically available in the discord server. Check out the #rewards-approval channel for more information.'
)}{' '}
{__(
'This process will likely involve providing proof of a stable and established online or real-life identity.'
)}
</p>
</header>
<h2 className="card__title">{__('3) Proof via Chat')}</h2>
<p className="card__subtitle">
{__(
'A moderator capable of approving you is typically available in the discord server. Check out the #rewards-approval channel for more information.'
)}{' '}
{__(
'This process will likely involve providing proof of a stable and established online or real-life identity.'
)}
</p>
<div className="card__content">
<div className="card__actions">
<Button href="https://chat.lbry.com" button="inverse" label={__('Join LBRY Chat')} />
</div>
<div className="card__actions">
<Button href="https://chat.lbry.com" button="inverse" label={__('Join LBRY Chat')} />
</div>
</section>
<section className="card card--section">
<header className="card__header">
<h2 className="card__title">{__('Or, Skip It Entirely')}</h2>
<p className="card__subtitle">
{__('You can continue without this step, but you will not be eligible to earn rewards.')}
</p>
</header>
<h2 className="card__title">{__('Or, Skip It Entirely')}</h2>
<p className="card__subtitle">
{__('You can continue without this step, but you will not be eligible to earn rewards.')}
</p>
<div className="card__content">
<div className="card__actions">
<Button navigate="/" button="primary" label={__('Skip Rewards')} />
</div>
<div className="card__actions">
<Button navigate="/" button="primary" label={__('Skip Rewards')} />
</div>
</section>
</React.Fragment>

View file

@ -47,39 +47,20 @@ class WalletAddress extends React.PureComponent<Props, State> {
return (
<section className="card card--section">
<header className="card__header">
<h2 className="card__title">{__('Receive Credits')}</h2>
<p className="card__subtitle">
{__('Use this wallet address to receive credits sent by another user (or yourself).')}
</p>
</header>
<h2 className="card__title">{__('Receive Credits')}</h2>
<p className="card__subtitle">
{__(
'Use this address to receive LBC. You can generate a new address at any time, and any previous addresses will continue to work.'
)}
</p>
<CopyableText label={__('Your Address')} copyable={receiveAddress} snackMessage={__('Address copied.')} />
<div className="card__content">
<CopyableText copyable={receiveAddress} snackMessage={__('Address copied.')} />
<div className="card__actions">
<Button button="inverse" label={__('Get New Address')} onClick={getNewAddress} disabled={gettingNewAddress} />
<Button button="link" label={showQR ? __('Hide QR code') : __('Show QR code')} onClick={this.toggleQR} />
</div>
<div className="card__content">
<div className="card__actions">
<Button
button="inverse"
label={__('Get New Address')}
onClick={getNewAddress}
disabled={gettingNewAddress}
/>
<Button button="link" label={showQR ? __('Hide QR code') : __('Show QR code')} onClick={this.toggleQR} />
</div>
<p className="help">
{__('You can generate a new address at any time, and any previous addresses will continue to work.')}
</p>
</div>
{showQR && (
<div className="card__content">
<QRCode value={receiveAddress} paddingTop />
</div>
)}
{showQR && <QRCode value={receiveAddress} paddingTop />}
</section>
);
}

View file

@ -66,7 +66,7 @@ class WalletBackup extends React.PureComponent<Props, State> {
try {
zip.addLocalFolder(lbryumWalletDir);
} catch (err) {
console.error(err);
console.error(err); // eslint-disable-line no-console
this.showErrorMessage(__('The wallet folder could not be added to the zip archive.'));
return;
}
@ -74,7 +74,7 @@ class WalletBackup extends React.PureComponent<Props, State> {
try {
zip.writeZip(outputPath);
} catch (err) {
console.error(err);
console.error(err); // eslint-disable-line no-console
this.showErrorMessage(__('There was a problem writing the zip archive to disk.'));
return;
}
@ -85,68 +85,49 @@ class WalletBackup extends React.PureComponent<Props, State> {
}
render() {
const { daemonSettings } = this.props;
const { daemonSettings = {} } = this.props;
const { wallet_dir: lbryumWalletDir } = daemonSettings;
const noDaemonSettings = Object.keys(daemonSettings).length === 0;
return (
<section className="card card--section">
{noDaemonSettings ? (
<header className="card__header">
<h2 className="card__title">{__('Failed to load settings.')}</h2>
</header>
) : (
<React.Fragment>
<header className="card__header">
<h2 className="card__title">{__('Backup Your LBRY Credits')}</h2>
<h2 className="card__title">{__('Backup Your LBRY Credits')}</h2>
<p className="card__subtitle">
{__(
'Your LBRY credits are controllable by you and only you, via wallet file(s) stored locally on your computer.'
)}
</p>
</header>
<div className="card__content">
<p>
{__(
'Currently, there is no automatic wallet backup. If you lose access to these files, you will lose your credits permanently.'
)}
</p>
<p>
{__(
'However, it is fairly easy to back up manually. To backup your wallet, make a copy of the folder listed below:'
)}
</p>
<CopyableText copyable={lbryumWalletDir} snackMessage={__('Path copied.')} />
<p>
{__(
'Access to these files are equivalent to having access to your credits. Keep any copies you make of your wallet in a secure place.'
)}
</p>
<p>
For more details on backing up and best practices,{' '}
<Button button="link" href="https://lbry.com/faq/how-to-backup-wallet" label={__('see this article')} />
.
</p>
<p className={'card__message card__message--error' + (this.state.errorMessage ? '' : ' hidden')}>
{this.state.errorMessage}
</p>
<p className={'card__message card__message--success' + (this.state.successMessage ? '' : ' hidden')}>
{this.state.successMessage}
</p>
<div className="card__actions">
<Button button="inverse" label={__('Open Folder')} onClick={() => shell.openItem(lbryumWalletDir)} />
<Button
button="inverse"
label={__('Create Backup')}
onClick={() => this.backupWalletDir(lbryumWalletDir)}
/>
</div>
</div>
</React.Fragment>
)}
<ul className="card__subtitle ol--bulleted">
<li>
{__(
'Your LBRY credits are controllable by you and only you, via wallet file(s) stored locally on your computer.'
)}
</li>
<li>
{__(
'Currently, there is no automatic backup. If you lose access to these files, you will lose your credits.'
)}
</li>
<li>
{__(
'However, it is fairly easy to back up manually. To backup your wallet, make a copy of the folder listed below:'
)}
</li>
</ul>
<CopyableText copyable={lbryumWalletDir} snackMessage={__('Path copied.')} />
<p className="help">
{__(
'Access to these files are equivalent to having access to your credits. Keep any copies you make of your wallet in a secure place.'
)}{' '}
{/* @i18fixme */}
{__('For more details on backing up and best practices')},{' '}
<Button button="link" href="https://lbry.com/faq/how-to-backup-wallet" label={__('see this article')} />.
</p>
<p className={'card__message card__message--error' + (this.state.errorMessage ? '' : ' hidden')}>
{this.state.errorMessage}
</p>
<p className={'card__message card__message--success' + (this.state.successMessage ? '' : ' hidden')}>
{this.state.successMessage}
</p>
<div className="card__actions">
<Button button="inverse" label={__('Create Backup')} onClick={() => this.backupWalletDir(lbryumWalletDir)} />
<Button button="link" label={__('Open Folder')} onClick={() => shell.openItem(lbryumWalletDir)} />
</div>
</section>
);
}

View file

@ -14,15 +14,10 @@ const WalletBalance = (props: Props) => {
className="card card--section card--wallet-balance"
style={{ backgroundImage: `url(${BalanceBackground})` }}
>
<header className="card__header">
<h2 className="card__title">{__('Balance')}</h2>
</header>
<div className="card__content">
<h3>{__('You currently have')}</h3>
<span className="card__content--large">
{(balance || balance === 0) && <CreditAmount badge={false} amount={balance} precision={8} />}
</span>
</div>
<h2 className="card__title">{__('Balance')}</h2>
<span className="card__content--large">
{(balance || balance === 0) && <CreditAmount badge={false} amount={balance} precision={8} />}
</span>
</section>
);
};

View file

@ -37,10 +37,8 @@ class WalletSend extends React.PureComponent<Props> {
return (
<section className="card card--section">
<header className="card__header">
<h2 className="card__title">{__('Send Credits')}</h2>
<p className="card__subtitle">{__('Send LBC to your friends or favorite creators')}</p>
</header>
<h2 className="card__title">{__('Send Credits')}</h2>
<p className="card__subtitle">{__('Send LBC to your friends or favorite creators.')}</p>
<Formik
initialValues={{
@ -51,38 +49,36 @@ class WalletSend extends React.PureComponent<Props> {
validate={validateSendTx}
render={({ values, errors, touched, handleChange, handleBlur, handleSubmit }) => (
<Form onSubmit={handleSubmit}>
<div className="card__content">
<fieldset-group class="fieldset-group--smushed">
<FormField
type="number"
name="amount"
label={__('Amount')}
postfix={__('LBC')}
className="form-field--price-amount"
affixClass="form-field--fix-no-height"
min="0"
step="any"
placeholder="12.34"
onChange={handleChange}
onBlur={handleBlur}
value={values.amount}
/>
<fieldset-group class="fieldset-group--smushed">
<FormField
type="number"
name="amount"
label={__('Amount')}
postfix={__('LBC')}
className="form-field--price-amount"
affixClass="form-field--fix-no-height"
min="0"
step="any"
placeholder="12.34"
onChange={handleChange}
onBlur={handleBlur}
value={values.amount}
/>
<FormField
type="text"
name="address"
placeholder="bbFxRyXXXXXXXXXXXZD8nE7XTLUxYnddTs"
className="form-field--address"
label={__('Recipient address')}
onChange={handleChange}
onBlur={handleBlur}
value={values.address}
/>
</fieldset-group>
</div>
<FormField
type="text"
name="address"
placeholder="bbFxRyXXXXXXXXXXXZD8nE7XTLUxYnddTs"
className="form-field--address"
label={__('Recipient address')}
onChange={handleChange}
onBlur={handleBlur}
value={values.address}
/>
</fieldset-group>
<div className="card__actions">
<Button
button="inverse"
button="primary"
type="submit"
label={__('Send')}
disabled={

View file

@ -16,7 +16,7 @@ const select = (state, props) => ({
});
const perform = dispatch => ({
sendSupport: (amount, claimId) => dispatch(doSendTip(amount, claimId)),
sendSupport: (amount, claimId, isSupport) => dispatch(doSendTip(amount, claimId, isSupport)),
});
export default connect(

View file

@ -9,7 +9,7 @@ type Props = {
title: string,
claim: StreamClaim,
isPending: boolean,
sendSupport: (number, string, string) => void,
sendSupport: (number, string) => void,
onCancel: () => void,
sendTipCallback?: () => void,
balance: number,
@ -33,11 +33,11 @@ class WalletSendTip extends React.PureComponent<Props, State> {
}
handleSendButtonClicked() {
const { claim, sendSupport, sendTipCallback } = this.props;
const { claim, sendSupport, isSupport, sendTipCallback } = this.props;
const { claim_id: claimId } = claim;
const { tipAmount } = this.state;
sendSupport(tipAmount, claimId);
sendSupport(tipAmount, claimId, isSupport);
// ex: close modal
if (sendTipCallback) {
@ -71,17 +71,20 @@ class WalletSendTip extends React.PureComponent<Props, State> {
}
render() {
const { title, isPending, uri, onCancel, claimIsMine, isSupport } = this.props;
const { title, isPending, onCancel, claimIsMine, isSupport } = this.props;
const { tipAmount, tipError } = this.state;
return (
<React.Fragment>
<Form className="card__content">
<Form>
<FormField
autoFocus
name="tip-input"
label={
(tipAmount && tipAmount !== 0 && `Tip ${tipAmount.toFixed(8).replace(/\.?0+$/, '')} LBC`) || __('Amount')
(tipAmount &&
tipAmount !== 0 &&
`${isSupport ? __('Support') : __('Tip')} ${tipAmount.toFixed(8).replace(/\.?0+$/, '')} LBC`) ||
__('Amount')
}
className="form-field--price-amount"
error={tipError}
@ -93,6 +96,7 @@ class WalletSendTip extends React.PureComponent<Props, State> {
inputButton={
<Button
button="primary"
type="submit"
label={__('Send')}
disabled={isPending || tipError || !tipAmount}
onClick={this.handleSendButtonClicked}
@ -100,18 +104,18 @@ class WalletSendTip extends React.PureComponent<Props, State> {
/>
}
helper={
<p>
<React.Fragment>
{claimIsMine || isSupport
? __('This will increase the 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>
</React.Fragment>
}
/>
</Form>
<div className="card__actions">
<Button button="link" label={__('Cancel')} onClick={onCancel} navigateParams={{ uri }} />
<Button button="link" label={__('Cancel')} onClick={onCancel} />
</div>
</React.Fragment>
);

View file

@ -32,7 +32,7 @@ export default class extends React.PureComponent<Props> {
{title && subtitle && (
<div className="yrbl__content">
<h2 className="card__title">{title}</h2>
<div className="card__content">{subtitle}</div>
<p>{subtitle}</p>
</div>
)}
</div>

View file

@ -8,7 +8,7 @@ import { ipcRenderer, remote, shell } from 'electron';
import * as ACTIONS from 'constants/action_types';
// @endif
import * as MODALS from 'constants/modal_types';
import React from 'react';
import React, { useState, useEffect } from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { doConditionalAuthNavigate, doDaemonReady, doAutoUpdate, doOpenModal, doHideModal } from 'redux/actions/app';
@ -21,13 +21,14 @@ import {
doBlackListedOutpointsSubscribe,
doFilteredOutpointsSubscribe,
} from 'lbryinc';
import { store, history } from 'store';
import { store, persistor, history } from 'store';
import pjson from 'package.json';
import app from './app';
import doLogWarningConsoleMessage from './logWarningConsoleMessage';
import { ConnectedRouter, push } from 'connected-react-router';
import cookie from 'cookie';
import { formatLbryUriForWeb } from 'util/uri';
import { PersistGate } from 'redux-persist/integration/react';
// Import our app styles
// If a style is not necessary for the initial page load, it should be removed from `all.scss`
@ -196,71 +197,63 @@ document.addEventListener('click', event => {
}
});
const init = () => {
// @if TARGET='app'
moment.locale(remote.app.getLocale());
function AppWrapper() {
const haveLaunched = window.sessionStorage.getItem('loaded') === 'y';
const [readyToLaunch, setReadyToLaunch] = useState(haveLaunched || IS_WEB);
autoUpdater.on('error', error => {
console.error(error.message);
});
useEffect(() => {
moment.locale(remote.app.getLocale());
if (['win32', 'darwin'].includes(process.platform)) {
autoUpdater.on('update-available', () => {
console.log('Update available');
autoUpdater.on('error', error => {
console.error(error.message); // eslint-disable-line no-console
});
autoUpdater.on('update-not-available', () => {
console.log('Update not available');
});
autoUpdater.on('update-downloaded', () => {
console.log('Update downloaded');
app.store.dispatch(doAutoUpdate());
});
}
app.store.dispatch(doUpdateIsNightAsync());
// @endif
if (['win32', 'darwin'].includes(process.platform)) {
autoUpdater.on('update-available', () => {
console.log('Update available'); // eslint-disable-line no-console
});
autoUpdater.on('update-not-available', () => {
console.log('Update not available'); // eslint-disable-line no-console
});
autoUpdater.on('update-downloaded', () => {
console.log('Update downloaded'); // eslint-disable-line no-console
app.store.dispatch(doAutoUpdate());
});
}
}, []);
app.store.dispatch(doInitLanguage());
app.store.dispatch(doBlackListedOutpointsSubscribe());
app.store.dispatch(doFilteredOutpointsSubscribe());
useEffect(() => {
if (readyToLaunch) {
app.store.dispatch(doUpdateIsNightAsync());
app.store.dispatch(doDaemonReady());
app.store.dispatch(doInitLanguage());
app.store.dispatch(doBlackListedOutpointsSubscribe());
app.store.dispatch(doFilteredOutpointsSubscribe());
window.sessionStorage.setItem('loaded', 'y');
}
}, [readyToLaunch, haveLaunched]);
function onDaemonReady() {
// @if TARGET='app'
window.sessionStorage.setItem('loaded', 'y'); // once we've made it here once per session, we don't need to show splash again
// @endif
return (
<Provider store={store}>
<PersistGate persistor={persistor} loading={<div className="main--launching" />}>
<div>
{readyToLaunch ? (
<ConnectedRouter history={history}>
<ErrorBoundary>
<App />
<SnackBar />
</ErrorBoundary>
</ConnectedRouter>
) : (
<SplashScreen
authenticate={() => app.store.dispatch(doAuthenticate(pjson.version))}
onReadyToLaunch={() => setReadyToLaunch(true)}
/>
)}
</div>
</PersistGate>
</Provider>
);
}
app.store.dispatch(doDaemonReady());
ReactDOM.render(
<Provider store={store}>
<ConnectedRouter history={history}>
<ErrorBoundary>
<App />
<SnackBar />
</ErrorBoundary>
</ConnectedRouter>
</Provider>,
document.getElementById('app')
);
}
// @if TARGET='app'
if (window.sessionStorage.getItem('loaded') === 'y') {
onDaemonReady();
} else {
ReactDOM.render(
<Provider store={store}>
<SplashScreen
authenticate={() => app.store.dispatch(doAuthenticate(pjson.version))}
onReadyToLaunch={onDaemonReady}
/>
</Provider>,
document.getElementById('app')
);
}
// @endif
// @if TARGET='web'
onDaemonReady();
// @endif
};
init();
ReactDOM.render(<AppWrapper />, document.getElementById('app'));

View file

@ -53,11 +53,7 @@ export class Modal extends React.PureComponent<ModalProps> {
className={classnames('card card--modal modal', className)}
overlayClassName="modal-overlay"
>
{title && (
<header className="card__header">
<h1 className="card__title">{title}</h1>
</header>
)}
{title && <h1 className="card__title">{title}</h1>}
{children}
{type === 'custom' ? null : ( // custom modals define their own buttons
<div className="card__actions">
@ -106,7 +102,7 @@ export class ExpandableModal extends React.PureComponent<ModalProps, State> {
return (
<Modal type="custom" {...this.props}>
{this.props.children}
{this.state.expanded ? <div className="card__content">{this.props.extraContent}</div> : null}
{this.state.expanded ? <div>{this.props.extraContent}</div> : null}
<div className="card__actions">
<Button button="primary" label={this.props.confirmButtonLabel} onClick={this.props.onConfirmed} />
<Button

View file

@ -39,15 +39,13 @@ class ModalAffirmPurchase extends React.PureComponent<Props> {
onConfirmed={this.onAffirmPurchase}
onAborted={cancelPurchase}
>
<section className="card__content">
<p className="card__subtitle">
{__('This will purchase')} <strong>{title ? `"${title}"` : uri}</strong> {__('for')}{' '}
<strong>
<FilePrice uri={uri} showFullPrice inheritStyle showLBC={false} />
</strong>{' '}
{__('credits')}.
</p>
</section>
<p className="card__subtitle">
{__('This will purchase')} <strong>{title ? `"${title}"` : uri}</strong> {__('for')}{' '}
<strong>
<FilePrice uri={uri} showFullPrice inheritStyle showLBC={false} />
</strong>{' '}
{__('credits')}.
</p>
</Modal>
);
}

View file

@ -23,9 +23,7 @@ class ModalAuthFailure extends React.PureComponent<Props> {
}}
onAborted={close}
>
<section className="card__content">
<p>{__('If reloading does not fix this, or you see this at every start up, please email help@lbry.com.')}</p>
</section>
<p>{__('If reloading does not fix this, or you see this at every start up, please email help@lbry.com.')}</p>
</Modal>
);
}

View file

@ -69,10 +69,8 @@ function ModalAutoGenerateThumbnail(props: Props) {
onConfirmed={uploadImage}
onAborted={closeModal}
>
<section className="card__content">
<p className="card__subtitle">{__('Pause at any time to select a thumbnail from your video')}.</p>
<video ref={playerRef} src={videoSrc} onLoadedMetadata={resize} onError={onError} controls />
</section>
<p className="card__subtitle">{__('Pause at any time to select a thumbnail from your video')}.</p>
<video ref={playerRef} src={videoSrc} onLoadedMetadata={resize} onError={onError} controls />
</Modal>
);
}

View file

@ -29,13 +29,11 @@ class ModalAutoUpdateConfirm extends React.PureComponent<Props> {
closeModal();
}}
>
<section className="card__content">
<p>{__('Your LBRY upgrade is ready. Restart LBRY now to use it!')}</p>
<p className="help">
{__('Want to know what has changed?')} See the{' '}
<Button button="link" label={__('release notes')} href="https://github.com/lbryio/lbry-desktop/releases" />.
</p>
</section>
<p>{__('Your LBRY upgrade is ready. Restart LBRY now to use it!')}</p>
<p className="help">
{__('Want to know what has changed?')} See the{' '}
<Button button="link" label={__('release notes')} href="https://github.com/lbryio/lbry-desktop/releases" />.
</p>
</Modal>
);
}

View file

@ -46,13 +46,11 @@ class ModalAutoUpdateDownloaded extends React.PureComponent<Props, State> {
closeModal();
}}
>
<section className="card__content">
<p>{__('A new version of LBRY is ready for you.')}</p>
<p className="help">
{__('Want to know what has changed?')} See the{' '}
<Button button="link" label={__('release notes')} href="https://github.com/lbryio/lbry-desktop/releases" />.
</p>
</section>
<p>{__('A new version of LBRY is ready for you.')}</p>
<p className="help">
{__('Want to know what has changed?')} See the{' '}
<Button button="link" label={__('release notes')} href="https://github.com/lbryio/lbry-desktop/releases" />.
</p>
</Modal>
);
}

View file

@ -1,7 +1,6 @@
// @flow
import React from 'react';
import { Modal } from 'modal/modal';
import { FormField } from 'component/common/form';
type Props = {
upload: string => void,
@ -19,7 +18,7 @@ class ModalConfirmThumbnailUpload extends React.PureComponent<Props> {
}
render() {
const { closeModal, path, updatePublishForm } = this.props;
const { closeModal, path } = this.props;
return (
<Modal
@ -31,11 +30,9 @@ class ModalConfirmThumbnailUpload extends React.PureComponent<Props> {
onConfirmed={() => this.upload()}
onAborted={closeModal}
>
<section className="card__content">
<p>{__('Are you sure you want to upload this thumbnail to spee.ch')}?</p>
<p>{__('Are you sure you want to upload this thumbnail to spee.ch')}?</p>
<blockquote>{path}</blockquote>
</section>
<blockquote>{path}</blockquote>
</Modal>
);
}

View file

@ -28,7 +28,7 @@ class ModalConfirmTransaction extends React.PureComponent<Props> {
type="custom"
onAborted={closeModal}
>
<Form className="card__content" onSubmit={() => this.onConfirmed()}>
<Form onSubmit={() => this.onConfirmed()}>
<p>{__('Sending: ')}</p>
<blockquote>{amount} LBC</blockquote>
<p>{__('To address: ')}</p>

View file

@ -18,19 +18,17 @@ class ModalDownloading extends React.PureComponent<Props> {
return (
<Modal title={__('Downloading Update')} isOpen contentLabel={__('Downloading Update')} type="custom">
<section className="card__content">
{downloadProgress ? `${downloadProgress}% ${__('complete')}` : null}
<Line percent={downloadProgress || 0} strokeWidth="4" />
{downloadComplete ? (
<React.Fragment>
<p>{__('Click "Begin Upgrade" to start the upgrade process.')}</p>
<p>{__('The app will close, and you will be prompted to install the latest version of LBRY.')}</p>
<p>{__('To launch installation manually, close LBRY and run the command below in the terminal.')}</p>
<blockquote>sudo dpkg -i {downloadItem}</blockquote>
<p>{__('After the install is complete, please reopen the app.')}</p>
</React.Fragment>
) : null}
</section>
{downloadProgress ? `${downloadProgress}% ${__('complete')}` : null}
<Line percent={downloadProgress || 0} strokeWidth="4" />
{downloadComplete ? (
<React.Fragment>
<p>{__('Click "Begin Upgrade" to start the upgrade process.')}</p>
<p>{__('The app will close, and you will be prompted to install the latest version of LBRY.')}</p>
<p>{__('To launch installation manually, close LBRY and run the command below in the terminal.')}</p>
<blockquote>sudo dpkg -i {downloadItem}</blockquote>
<p>{__('After the install is complete, please reopen the app.')}</p>
</React.Fragment>
) : null}
<div className="card__actions">
{downloadComplete ? <Button button="primary" label={__('Begin Upgrade')} onClick={startUpgrade} /> : null}

View file

@ -10,10 +10,19 @@ type Props = {
class ModalError extends React.PureComponent<Props> {
componentDidMount() {
if (process.env.NODE_ENV === 'production') {
Lbryio.call('event', 'desktop_error', { error_message: JSON.stringify(this.props.error) });
const { error } = this.props;
// Yuck
// https://github.com/lbryio/lbry-sdk/issues/1118
// The sdk logs failed downloads, they happen so often that it's mostly noise in the desktop logs
const errorMessage = typeof error === 'string' ? error : error.message;
const failedToDownloadError = errorMessage.startsWith('Failed to download');
if (process.env.NODE_ENV === 'production' && !failedToDownloadError) {
Lbryio.call('event', 'desktop_error', { error_message: JSON.stringify(error) });
}
}
render() {
const { closeModal, error } = this.props;
@ -41,14 +50,12 @@ class ModalError extends React.PureComponent<Props> {
return (
<Modal isOpen contentLabel={__('Error')} title={__('Error')} className="error-modal" onConfirmed={closeModal}>
<section className="card__content">
<p>
{__(
"We're sorry that LBRY has encountered an error. This has been reported and we will investigate the problem."
)}
</p>
</section>
<ul className="card__content error-modal__error-list">{errorInfoList}</ul>
<p>
{__(
"We're sorry that LBRY has encountered an error. This has been reported and we will investigate the problem."
)}
</p>
<ul className="error-modal__error-list">{errorInfoList}</ul>
</Modal>
);
}

View file

@ -18,14 +18,12 @@ class ModalFileTimeout extends React.PureComponent<Props> {
return (
<Modal isOpen title={__('Unable to Download')} contentLabel={__('Download failed')} onConfirmed={closeModal}>
<section className="card__content">
<p className="error-modal__error-list">
{__('LBRY was unable to download the stream')}:
<div>
<b>{title ? `"${title}"` : uri}</b>
</div>
</p>
</section>
<p className="error-modal__error-list">
{__('LBRY was unable to download the stream')}:
<div>
<b>{title ? `"${title}"` : uri}</b>
</div>
</p>
</Modal>
);
}

View file

@ -18,16 +18,14 @@ class ModalFirstReward extends React.PureComponent<Props> {
title={__('Your First Reward')}
onConfirmed={closeModal}
>
<section className="card__content">
<p>{__('You just earned your first reward!')}</p>
<p>{__("This reward will show in your Wallet in the top right momentarily (if it hasn't already).")}</p>
<p>
{__(
'These credits are used to compensate creators, to publish your own content, and to have say in how the network works.'
)}
</p>
<p>{__('No need to understand it all just yet! Try watching or publishing something next.')}</p>
</section>
<p>{__('You just earned your first reward!')}</p>
<p>{__("This reward will show in your Wallet in the top right momentarily (if it hasn't already).")}</p>
<p>
{__(
'These credits are used to compensate creators, to publish your own content, and to have say in how the network works.'
)}
</p>
<p>{__('No need to understand it all just yet! Try watching or publishing something next.')}</p>
</Modal>
);
}

View file

@ -12,23 +12,21 @@ const ModalFirstSubscription = (props: Props) => {
return (
<Modal type="custom" isOpen contentLabel="Subscriptions 101" title={__('Subscriptions 101')}>
<section className="card__content">
<p>{__('You just subscribed to your first channel. Awesome!')}</p>
<p>{__('A few quick things to know:')}</p>
<p className="card__content">
{__(
'1) This app will automatically download new free content from channels you are subscribed to. You may configure this in Settings or on the Subscriptions page.'
)}
</p>
<p className="card__content">
{__(
'2) If we have your email address, we will send you notifications related to new content. You may configure these emails from the Help page.'
)}
</p>
<div className="modal__buttons">
<Button button="primary" onClick={closeModal} label={__('Got it')} />
</div>
</section>
<p>{__('You just subscribed to your first channel. Awesome!')}</p>
<p>{__('A few quick things to know:')}</p>
<p>
{__(
'1) This app will automatically download new free content from channels you are subscribed to. You may configure this in Settings or on the Subscriptions page.'
)}
</p>
<p>
{__(
'2) If we have your email address, we will send you notifications related to new content. You may configure these emails from the Help page.'
)}
</p>
<div className="modal__buttons">
<Button button="primary" onClick={closeModal} label={__('Got it')} />
</div>
</Modal>
);
};

View file

@ -23,14 +23,12 @@ class ModalIncompatibleDaemon extends React.PureComponent<Props> {
onConfirmed={quitAnyDaemon}
onAborted={onContinueAnyway}
>
<div className="card__content">
<p>
{__(
'This app is running with an incompatible version of the LBRY protocol. You can still use it, but there may be issues. Re-run the installation package for best results.'
)}{' '}
<Button button="link" label={__('Learn more')} href="https://lbry.com/faq/incompatible-protocol-version" />.
</p>
</div>
<p>
{__(
'This app is running with an incompatible version of the LBRY protocol. You can still use it, but there may be issues. Re-run the installation package for best results.'
)}{' '}
<Button button="link" label={__('Learn more')} href="https://lbry.com/faq/incompatible-protocol-version" />.
</p>
</Modal>
);
}

View file

@ -54,14 +54,12 @@ function ModalOpenExternalResource(props: Props) {
onConfirmed={() => openResource()}
onAborted={closeModal}
>
<section className="card__content">
<p>
{(uri && __('This link leads to an external website.')) ||
(path && __('This file has been shared with you by other people.'))}
</p>
<blockquote>{uri || path}</blockquote>
<p>{__('LBRY Inc is not responsible for its content, click continue to proceed at your own risk.')}</p>
</section>
<p>
{(uri && __('This link leads to an external website.')) ||
(path && __('This file has been shared with you by other people.'))}
</p>
<blockquote>{uri || path}</blockquote>
<p>{__('LBRY Inc is not responsible for its content, click continue to proceed at your own risk.')}</p>
</Modal>
);
}

View file

@ -28,15 +28,13 @@ class ModalPublishSuccess extends React.PureComponent<Props> {
closeModal();
}}
>
<section className="card__content">
<p>{__(`Your ${publishMessage} published to LBRY at the address`)}</p>
<blockquote>{uri}</blockquote>
<p>
{__(
`The ${publishType} will take a few minutes to appear for other LBRY users. Until then it will be listed as "pending" under your published files.`
)}
</p>
</section>
<p>{__(`Your ${publishMessage} published to LBRY at the address`)}</p>
<blockquote>{uri}</blockquote>
<p>
{__(
`The ${publishType} will take a few minutes to appear for other LBRY users. Until then it will be listed as "pending" under your published files.`
)}
</p>
</Modal>
);
}

View file

@ -25,18 +25,18 @@ function ModalRemoveFile(props: Props) {
return (
<Modal isOpen title="Remove File" contentLabel={__('Confirm File Remove')} type="custom" onAborted={closeModal}>
<section className="card__content">
<section>
<p>
{__("Are you sure you'd like to remove")} <cite>{`"${title}"`}</cite> {__('from the LBRY app?')}
</p>
</section>
<Form className="card__content" onSubmit={() => deleteFile(outpoint || '', deleteChecked, abandonChecked)}>
<Form onSubmit={() => deleteFile(outpoint || '', deleteChecked, abandonChecked)}>
<FormField
name="file_delete"
label={__('Also delete this file from my computer')}
name="claim_abandon"
label={__('Abandon the claim for this URI')}
type="checkbox"
checked={deleteChecked}
onChange={() => setDeleteChecked(!deleteChecked)}
checked={abandonChecked}
onChange={() => setAbandonChecked(!abandonChecked)}
/>
{claimIsMine && (

View file

@ -84,7 +84,7 @@ class ModalRevokeClaim extends React.PureComponent<Props> {
onConfirmed={this.revokeClaim}
onAborted={closeModal}
>
<section className="card__content">{this.getMsgBody(type)}</section>
<section>{this.getMsgBody(type)}</section>
</Modal>
);
}

View file

@ -22,13 +22,11 @@ class ModalRewardApprovalRequired extends React.PureComponent<Props> {
confirmButtonLabel={__("I'm Totally Real")}
abortButtonLabel={__('Never Mind')}
>
<section className="card__content">
<p>
{__(
"Before we can give you any credits, we need to perform a brief check to make sure you're a new and unique person."
)}
</p>
</section>
<p>
{__(
"Before we can give you any credits, we need to perform a brief check to make sure you're a new and unique person."
)}
</p>
</Modal>
);
}

View file

@ -1,6 +1,6 @@
// @flow
import * as React from 'react';
import { FormField, Form, Submit } from 'component/common/form';
import { FormField, Form } from 'component/common/form';
import { Modal } from 'modal/modal';
import Button from 'component/button';
@ -44,7 +44,7 @@ class ModalRewardCode extends React.PureComponent<Props, State> {
type="custom"
onAborted={closeModal}
>
<Form className="card__content" onSubmit={this.handleSubmit}>
<Form onSubmit={this.handleSubmit}>
<p>
{__('Redeem a custom reward code for LBC')}
{'. '}
@ -55,7 +55,9 @@ class ModalRewardCode extends React.PureComponent<Props, State> {
type="text"
name="reward-code"
inputButton={
<Submit
<Button
button="primary"
type="submit"
disabled={!rewardCode || rewardIsPending}
label={rewardIsPending ? __('Redeeming') : __('Redeem')}
/>

View file

@ -12,9 +12,7 @@ class ModalTransactionFailed extends React.PureComponent<Props> {
return (
<Modal isOpen contentLabel={__('Transaction failed')} title={__('Transaction Failed')} onConfirmed={closeModal}>
<section className="card__content">
<p>{__('Sorry about that. Contact help@lbry.com if you continue to have issues.')}</p>
</section>
<p>{__('Sorry about that. Contact help@lbry.com if you continue to have issues.')}</p>
</Modal>
);
}

View file

@ -23,16 +23,14 @@ class ModalUpgrade extends React.PureComponent<Props> {
onConfirmed={downloadUpgrade}
onAborted={skipUpgrade}
>
<div className="card__content">
<p>
{__('An updated version of LBRY is now available.')}{' '}
{__('Your version is out of date and may be unreliable or insecure.')}
</p>
<p className="help">
{__('Want to know what has changed?')} See the{' '}
<Button button="link" label={__('release notes')} href="https://github.com/lbryio/lbry-desktop/releases" />.
</p>
</div>
<p>
{__('An updated version of LBRY is now available.')}{' '}
{__('Your version is out of date and may be unreliable or insecure.')}
</p>
<p className="help">
{__('Want to know what has changed?')} See the{' '}
<Button button="link" label={__('release notes')} href="https://github.com/lbryio/lbry-desktop/releases" />.
</p>
</Modal>
);
}

View file

@ -47,14 +47,12 @@ class ModalWalletDecrypt extends React.PureComponent<Props, State> {
onConfirmed={() => this.submitDecryptForm()}
onAborted={closeModal}
>
<section className="card__content">
<p>
{__(
'Your wallet has been encrypted with a local password, performing this action will remove this password.'
)}{' '}
<Button button="link" label={__('Learn more')} href="https://lbry.com/faq/wallet-encryption" />.
</p>
</section>
<p>
{__(
'Your wallet has been encrypted with a local password, performing this action will remove this password.'
)}{' '}
<Button button="link" label={__('Learn more')} href="https://lbry.com/faq/wallet-encryption" />.
</p>
</Modal>
);
}

View file

@ -98,7 +98,7 @@ class ModalWalletEncrypt extends React.PureComponent<Props, State> {
onConfirmed={() => this.submitEncryptForm()}
onAborted={closeModal}
>
<Form className="card__content" onSubmit={() => this.submitEncryptForm()}>
<Form onSubmit={() => this.submitEncryptForm()}>
<p>
{__(
'Encrypting your wallet will require a password to access your local wallet data when LBRY starts. Please enter a new password for your wallet.'
@ -127,7 +127,7 @@ class ModalWalletEncrypt extends React.PureComponent<Props, State> {
/>
</fieldset-section>
<div className="help help--warning">
<div className="card__subtitle--status">
{__(
'If your password is lost, it cannot be recovered. You will not be able to access your wallet without a password.'
)}

View file

@ -49,24 +49,20 @@ class ModalWalletUnlock extends React.PureComponent<Props, State> {
onConfirmed={() => unlockWallet(password)}
onAborted={quit}
>
<section className="card__content">
<Form onSubmit={() => unlockWallet(password)}>
<p>
{__(
'Your wallet has been encrypted with a local password. Please enter your wallet password to proceed.'
)}{' '}
<Button button="link" label={__('Learn more')} href="https://lbry.com/faq/wallet-encryption" />.
</p>
<FormField
autoFocus
error={walletUnlockSucceded === false ? 'Incorrect Password' : false}
label={__('Wallet Password')}
type="password"
name="wallet-password"
onChange={event => this.onChangePassword(event)}
/>
</Form>
</section>
<Form onSubmit={() => unlockWallet(password)}>
<p>
{__('Your wallet has been encrypted with a local password. Please enter your wallet password to proceed.')}{' '}
<Button button="link" label={__('Learn more')} href="https://lbry.com/faq/wallet-encryption" />.
</p>
<FormField
autoFocus
error={walletUnlockSucceded === false ? 'Incorrect Password' : false}
label={__('Wallet Password')}
type="password"
name="wallet-password"
onChange={event => this.onChangePassword(event)}
/>
</Form>
</Modal>
);
}

View file

@ -12,14 +12,12 @@ const ModalWelcome = (props: Props) => {
return (
<Modal type="custom" isOpen contentLabel="Welcome to LBRY" title={__('Welcome to LBRY')}>
<section className="card__content">
<p>
{__('Using LBRY is like dating a centaur. Totally normal up top, and')} <em>{__('way different')}</em>{' '}
{__('underneath.')}
</p>
<p>{__('Up top, LBRY is similar to popular media sites.')}</p>
<p>{__('Below, LBRY is controlled by users -- you -- via blockchain and decentralization.')}</p>
</section>
<p>
{__('Using LBRY is like dating a centaur. Totally normal up top, and')} <em>{__('way different')}</em>{' '}
{__('underneath.')}
</p>
<p>{__('Up top, LBRY is similar to popular media sites.')}</p>
<p>{__('Below, LBRY is controlled by users -- you -- via blockchain and decentralization.')}</p>
<div className="card__actions">
<Button button="primary" onClick={closeModal} label={__("I'm In")} />
</div>

View file

@ -89,7 +89,7 @@ function ChannelPage(props: Props) {
<TabList className="tabs__list--channel-page">
<Tab disabled={editing}>{__('Content')}</Tab>
<Tab>{editing ? __('Editing Your Channel') : __('About')}</Tab>
<div className="card__actions">
<div className="card__actions--inline">
<ShareButton uri={uri} />
<SubscribeButton uri={permanentUrl} />
</div>

View file

@ -19,7 +19,9 @@ function DiscoverPage(props: Props) {
personalView
tags={followedTags.map(tag => tag.name)}
meta={<Button button="link" label={__('Customize')} navigate={`/$/${PAGES.FOLLOWING}`} />}
injectedItem={<TagsSelect showClose title={__('Customize Your Homepage')} />}
injectedItem={
<TagsSelect showClose title={__('Customize Your Homepage')} className="claim-preview--injected" />
}
/>
</Page>
);

View file

@ -8,11 +8,9 @@ import Thumbnail from 'component/common/thumbnail';
import FilePrice from 'component/filePrice';
import FileDetails from 'component/fileDetails';
import FileActions from 'component/fileActions';
import UriIndicator from 'component/uriIndicator';
import Icon from 'component/common/icon';
import DateTime from 'component/dateTime';
import Button from 'component/button';
import SubscribeButton from 'component/subscribeButton';
import Page from 'component/page';
import FileDownloadLink from 'component/fileDownloadLink';
import classnames from 'classnames';
@ -21,8 +19,8 @@ import RecommendedContent from 'component/recommendedContent';
import ClaimTags from 'component/claimTags';
import CommentsList from 'component/commentsList';
import CommentCreate from 'component/commentCreate';
import VideoDuration from 'component/videoDuration';
import ClaimUri from 'component/claimUri';
import ClaimPreview from 'component/claimPreview';
type Props = {
claim: StreamClaim,
@ -224,81 +222,79 @@ class FilePage extends React.Component<Props> {
<div className="columns">
<div className="grid-area--info">
<h1 className="media__title media__title--large">{title}</h1>
<div className="media__subtext media__subtext--large">
<div className="media__subtitle__channel">
<UriIndicator uri={uri} link />
</div>
</div>
<div className="media__actions media__actions--between">
<div className="media__action-group--large">
<div className="media__subtitle">
<div className="media__actions media__actions--between">
<DateTime uri={uri} show={DateTime.SHOW_DATE} />
{claimIsMine && (
<Button
button="primary"
icon={icons.EDIT}
label={__('Edit')}
navigate="/$/publish"
onClick={() => {
prepareEdit(claim, editUri, fileInfo);
}}
/>
<span>
{viewCount} {viewCount !== 1 ? __('Views') : __('View')}
</span>
)}
{
<React.Fragment>
{!claimIsMine && channelUri && <SubscribeButton uri={channelUri} channelName={channelName} />}
</div>
<div className="media__actions media__actions--between">
<div className="media__action-group--large">
{claimIsMine && (
<Button
button="primary"
icon={icons.EDIT}
label={__('Edit')}
navigate="/$/publish"
onClick={() => {
prepareEdit(claim, editUri, fileInfo);
}}
/>
)}
{!claimIsMine && (
<Button
button="alt"
icon={claimIsMine ? icons.SUPPORT : icons.TIP}
label={claimIsMine ? __('Support') : __('Tip')}
icon={icons.TIP}
label={__('Tip')}
title={__('Send a tip to this creator')}
onClick={() => openModal(MODALS.SEND_TIP, { uri, claimIsMine, isSupport: false })}
/>
{!claimIsMine && supportOption && (
<Button
button="alt"
icon={icons.SUPPORT}
label={__('Support')}
onClick={() => openModal(MODALS.SEND_TIP, { uri, claimIsMine, isSupport: true })}
/>
)}
</React.Fragment>
}
<Button
button="alt"
icon={icons.SHARE}
label={__('Share')}
onClick={() => openModal(MODALS.SOCIAL_SHARE, { uri, speechShareable })}
/>
</div>
)}
{(claimIsMine || (!claimIsMine && supportOption)) && (
<Button
button="alt"
icon={icons.SUPPORT}
label={__('Support')}
title={__('Support this claim')}
onClick={() => openModal(MODALS.SEND_TIP, { uri, claimIsMine, isSupport: true })}
/>
)}
<Button
button="alt"
icon={icons.SHARE}
label={__('Share')}
onClick={() => openModal(MODALS.SOCIAL_SHARE, { uri, speechShareable })}
/>
</div>
<div className="media__action-group--large">
<FileDownloadLink uri={uri} />
<FileActions
uri={uri}
claimId={claim.claim_id}
showFullscreen={isPreviewType}
viewerContainer={this.viewerContainer}
/>
<div className="media__action-group--large">
<FileDownloadLink uri={uri} />
<FileActions
uri={uri}
claimId={claim.claim_id}
showFullscreen={isPreviewType}
viewerContainer={this.viewerContainer}
/>
</div>
</div>
</div>
<div className="media__actions media__actions--between">
<div className="media__subtext media__subtext--large">
<DateTime uri={uri} show={DateTime.SHOW_DATE} />
</div>
<hr />
<div className="media__subtext media__subtext--large">
<VideoDuration uri={uri} />
{claimIsMine && (
<p>
{viewCount} {viewCount !== 1 ? __('Views') : __('View')}
</p>
)}
</div>
</div>
{channelUri ? (
<ClaimPreview uri={channelUri} type="inline" />
) : (
<div className="claim-preview--inline claim-preview-title">{__('Anonymous')}</div>
)}
<div className="media__info--large">
<ClaimTags uri={uri} type="large" />
<FileDetails uri={uri} />
<ClaimTags uri={uri} type="large" />
<div className="media__info-title">
{__('Comments')} <span className="badge badge--alert">ALPHA</span>

View file

@ -19,7 +19,7 @@ function FileListDownloaded(props: Props) {
{hasDownloads ? (
<div className="card">
<ClaimList
header={<h1>{__('Your Library')}</h1>}
header={__('Your Library')}
defaultSort
persistedStorageKey="claim-list-downloaded"
uris={downloadedUris}
@ -29,14 +29,9 @@ function FileListDownloaded(props: Props) {
) : (
<div className="main--empty">
<section className="card card--section">
<header className="card__header">
<h2 className="card__title">{__("You haven't downloaded anything from LBRY yet.")}</h2>
</header>
<div className="card__content">
<div className="card__actions card__actions--center">
<Button button="primary" navigate="/" label={__('Explore new content')} />
</div>
<h2 className="card__title">{__("You haven't downloaded anything from LBRY yet.")}</h2>
<div className="card__actions card__actions--center">
<Button button="primary" navigate="/" label={__('Explore new content')} />
</div>
</section>
</div>

View file

@ -22,7 +22,7 @@ function FileListPublished(props: Props) {
{uris && uris.length ? (
<div className="card">
<ClaimList
header={<h1>{__('Your Publishes')}</h1>}
header={__('Your Publishes')}
loading={fetching}
persistedStorageKey="claim-list-published"
uris={uris}
@ -33,14 +33,10 @@ function FileListPublished(props: Props) {
) : (
<div className="main--empty">
<section className="card card--section">
<header className="card__header">
<h2 className="card__title">{__("It looks like you haven't published anything to LBRY yet.")}</h2>
</header>
<h2 className="card__title">{__("It looks like you haven't published anything to LBRY yet.")}</h2>
<div className="card__content">
<div className="card__actions card__actions--center">
<Button button="primary" navigate="/$/publish" label={__('Publish something new')} />
</div>
<div className="card__actions card__actions--center">
<Button button="primary" navigate="/$/publish" label={__('Publish something new')} />
</div>
</section>
</div>

View file

@ -38,12 +38,12 @@ function FollowingPage(props: Props) {
return (
<Page>
<div className="card">
<div className="card card--section">
<TagsSelect showClose={false} title={__('Customize Your Tags')} />
</div>
<div className="card">
<ClaimList
header={<h1>{viewingSuggestedSubs ? __('Discover New Channels') : __('Channels You Follow')}</h1>}
header={viewingSuggestedSubs ? __('Discover New Channels') : __('Channels You Follow')}
headerAltControls={
<Button
button="link"

View file

@ -1,3 +0,0 @@
import GetCreditsPage from './view';
export default GetCreditsPage;

View file

@ -1,33 +0,0 @@
import React from 'react';
import Button from 'component/button';
import RewardSummary from 'component/rewardSummary';
// import ShapeShift from 'component/shapeShift';
import Page from 'component/page';
const GetCreditsPage = () => (
<Page>
<RewardSummary />
{/*
Removing Shapeshift after they switched to user accounts
Ideally most of the redux logic should be able to be re-used if we switch to another company
Or find a way to use ShapShift with an account?
<ShapeShift />
*/}
<section className="card card--section">
<header className="card__header">
<h2 className="card__title">{__('More Ways To Get LBRY Credits')}</h2>
<p className="card__subtitle">
{'LBRY credits can be purchased on exchanges, earned for contributions, for mining, and more.'}
</p>
</header>
<div className="card__content">
<div className="card__actions">
<Button button="primary" href="https://lbry.com/faq/earn-credits" label={__('Read More')} />
</div>
</div>
</section>
</Page>
);
export default GetCreditsPage;

View file

@ -123,81 +123,58 @@ class HelpPage extends React.PureComponent<Props, State> {
return (
<Page>
<section className="card card--section">
<header className="card__header">
<h2 className="card__title">{__('Read the FAQ')}</h2>
<p className="card__subtitle">{__('Our FAQ answers many common questions.')}</p>
</header>
<h2 className="card__title">{__('Read the FAQ')}</h2>
<p className="card__subtitle">{__('Our FAQ answers many common questions.')}</p>
<div className="card__content">
<div className="card__actions">
<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 className="card__actions">
<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>
</section>
<section className="card card--section">
<header className="card__header">
<h2 className="card__title">{__('Find Assistance')}</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. Or you can always email us at help@lbry.com.')}
</p>
</header>
<p className="card__subtitle">
{__('Live help is available most hours in the')} <strong>#help</strong>{' '}
{__('channel of our Discord chat room. Or you can always email us at help@lbry.com.')}
</p>
<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 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>
</section>
<section className="card card--section">
<header className="card__header">
<h2 className="card__title">{__('Report a Bug or Suggest a New Feature')}</h2>
<h2 className="card__title">{__('Report a Bug or Suggest a New Feature')}</h2>
<p className="card__subtitle">
{__('Did you find something wrong? Think LBRY could add something useful and cool?')}{' '}
<Button button="link" label={__('Learn more')} href="https://lbry.com/faq/support" />.
</p>
</header>
<p className="card__subtitle">
{__('Did you find something wrong? Think LBRY could add something useful and cool?')}{' '}
<Button button="link" label={__('Learn more')} href="https://lbry.com/faq/support" />.
</p>
<div className="card__content">
<div className="card__actions">
<Button
navigate="/$/report"
label={__('Submit a Bug Report/Feature Request')}
icon={icons.REPORT}
button="inverse"
/>
</div>
<div className="help">{__('Thanks! LBRY is made by its users.')}</div>
<div className="card__actions">
<Button navigate="/$/report" label={__('Help Us Out')} button="inverse" />
</div>
</section>
{/* @if TARGET='app' */}
<section className="card card--section">
<header className="card__header">
<h2 className="card__title">{__('View your Log')}</h2>
<h2 className="card__title">{__('View your Log')}</h2>
<p className="card__subtitle">
{__('Did something go wrong? Have a look in your log file, or send it to')}{' '}
<Button button="link" label={__('support')} href="https://lbry.com/faq/support" />.
</p>
</header>
<p className="card__subtitle">
{__('Did something go wrong? Have a look in your log file, or send it to')}{' '}
<Button button="link" label={__('support')} href="https://lbry.com/faq/support" />.
</p>
<div className="card__content">
<div className="card__actions">
<Button button="inverse" label={__('Open Log')} onClick={() => this.openLogFile(dataDirectory)} />
<Button button="inverse" label={__('Open Log Folder')} onClick={() => shell.openItem(dataDirectory)} />
</div>
<div className="card__actions">
<Button button="inverse" label={__('Open Log')} onClick={() => this.openLogFile(dataDirectory)} />
<Button button="link" label={__('Open Log Folder')} onClick={() => shell.openItem(dataDirectory)} />
</div>
</section>
@ -210,7 +187,7 @@ class HelpPage extends React.PureComponent<Props, State> {
<h2 className="card__title">{__('About')}</h2>
{this.state.upgradeAvailable !== null && this.state.upgradeAvailable ? (
<p className="card__subtitle">
<p className="card__subtitle--status">
{__('A newer version of LBRY is available.')}{' '}
<Button button="link" href={newVerLink} label={__('Download now!')} />
</p>
@ -219,68 +196,66 @@ class HelpPage extends React.PureComponent<Props, State> {
)}
</header>
<div className="card__content">
<table className="table table--stretch">
<tbody>
<tr>
<td>{__('App')}</td>
<td>{this.state.uiVersion}</td>
</tr>
<tr>
<td>{__('Daemon (lbrynet)')}</td>
<td>{ver ? ver.lbrynet_version : __('Loading...')}</td>
</tr>
<tr>
<td>{__('Connected Email')}</td>
<td>
{user && user.primary_email ? (
<React.Fragment>
{user.primary_email}{' '}
<Button
button="link"
href={`https://lbry.com/list/edit/${accessToken}`}
label={__('Update mailing preferences')}
/>
</React.Fragment>
) : (
<React.Fragment>
<span className="empty">{__('none')} </span>
<Button button="link" onClick={() => doAuth()} label={__('set email')} />
</React.Fragment>
)}
</td>
</tr>
<tr>
<td>{__('Reward Eligible')}</td>
<td>{user && user.is_reward_approved ? __('Yes') : __('No')}</td>
</tr>
<tr>
<td>{__('Platform')}</td>
<td>{platform}</td>
</tr>
<tr>
<td>{__('Installation ID')}</td>
<td>{this.state.lbryId}</td>
</tr>
<tr>
<td>{__('Access Token')}</td>
<td>
{this.state.accessTokenHidden && (
<Button button="link" label={__('View')} onClick={this.showAccessToken} />
)}
{!this.state.accessTokenHidden && accessToken && (
<div>
<p>{accessToken}</p>
<div className="alert-text">
{__('This is equivalent to a password. Do not post or share this.')}
</div>
<table className="table table--stretch">
<tbody>
<tr>
<td>{__('App')}</td>
<td>{this.state.uiVersion}</td>
</tr>
<tr>
<td>{__('Daemon (lbrynet)')}</td>
<td>{ver ? ver.lbrynet_version : __('Loading...')}</td>
</tr>
<tr>
<td>{__('Connected Email')}</td>
<td>
{user && user.primary_email ? (
<React.Fragment>
{user.primary_email}{' '}
<Button
button="link"
href={`https://lbry.com/list/edit/${accessToken}`}
label={__('Update mailing preferences')}
/>
</React.Fragment>
) : (
<React.Fragment>
<span className="empty">{__('none')} </span>
<Button button="link" onClick={() => doAuth()} label={__('set email')} />
</React.Fragment>
)}
</td>
</tr>
<tr>
<td>{__('Reward Eligible')}</td>
<td>{user && user.is_reward_approved ? __('Yes') : __('No')}</td>
</tr>
<tr>
<td>{__('Platform')}</td>
<td>{platform}</td>
</tr>
<tr>
<td>{__('Installation ID')}</td>
<td>{this.state.lbryId}</td>
</tr>
<tr>
<td>{__('Access Token')}</td>
<td>
{this.state.accessTokenHidden && (
<Button button="link" label={__('View')} onClick={this.showAccessToken} />
)}
{!this.state.accessTokenHidden && accessToken && (
<div>
<p>{accessToken}</p>
<div className="alert-text">
{__('This is equivalent to a password. Do not post or share this.')}
</div>
)}
</td>
</tr>
</tbody>
</table>
</div>
</div>
)}
</td>
</tr>
</tbody>
</table>
</section>
{/* @endif */}
</Page>

View file

@ -51,9 +51,7 @@ function PublishPage(props: Props) {
}
/>
<section className="card card--section">
<header className="card__header">
<h1 className="card__title">{__('LBRY Credits Required')}</h1>
</header>
<h1 className="card__title">{__('LBRY Credits Required')}</h1>
<p className="card__subtitle">
{__(' There are a variety of ways to get credits, including more than')}{' '}
<CreditAmount inheritStyle amount={totalRewardRounded} />{' '}

View file

@ -47,64 +47,56 @@ class ReportPage extends React.Component {
return (
<Page>
<section className="card card--section">
<header className="card__header">
<h2 className="card__title">{__('Report an Issue/Request a Feature')}</h2>
<p className="card__subtitle">
{__(
'Please describe the problem you experienced or the feature you want to see and any information you think might be useful to us. Links to screenshots are great!'
)}
</p>
</header>
<h2 className="card__title">{__('Report an Issue/Request a Feature')}</h2>
<p className="card__subtitle">
{__(
'Please describe the problem you experienced or the feature you want to see and any information you think might be useful to us. Links to screenshots are great!'
)}
</p>
<div className="card__content">
<FormField
type="textarea"
rows="10"
name="message"
stretch
value={this.state.message}
onChange={event => {
this.onMessageChange(event);
<FormField
type="textarea"
rows="10"
name="message"
stretch
value={this.state.message}
onChange={event => {
this.onMessageChange(event);
}}
placeholder={__('Description of your issue or feature request')}
/>
<div className="card__actions">
<Button
button="primary"
onClick={event => {
this.submitMessage(event);
}}
placeholder={__('Description of your issue or feature request')}
/>
<div className="card__actions">
<Button
button="primary"
onClick={event => {
this.submitMessage(event);
}}
className={`button-block button-primary ${this.state.submitting ? 'disabled' : ''}`}
>
{this.state.submitting ? __('Submitting...') : __('Submit Report')}
</Button>
</div>
className={`button-block button-primary ${this.state.submitting ? 'disabled' : ''}`}
>
{this.state.submitting ? __('Submitting...') : __('Submit Report')}
</Button>
</div>
</section>
<section className="card card--section">
<header className="card__header">
<h2 className="card__title">{__('Developer?')}</h2>
</header>
<h2 className="card__title">{__('Developer?')}</h2>
<div className="card__content">
<p>
{__('You can also')}{' '}
<Button
button="link"
href="https://github.com/lbryio/lbry-desktop/issues"
label={__('submit an issue on GitHub')}
/>
.
</p>
<p>
{__('Explore our')} <Button button="link" href="https://lbry.tech" label={__('technical resources')} />.
</p>
<p>
{__('Join our')} <Button button="link" href="https://discourse.lbry.com/" label={__('tech forum')} />.
</p>
</div>
<p>
{__('You can also')}{' '}
<Button
button="link"
href="https://github.com/lbryio/lbry-desktop/issues"
label={__('submit an issue on GitHub')}
/>
.
</p>
<p>
{__('Explore our')} <Button button="link" href="https://lbry.tech" label={__('technical resources')} />.
</p>
<p>
{__('Join our')} <Button button="link" href="https://discourse.lbry.com/" label={__('tech forum')} />.
</p>
</section>
</Page>
);

View file

@ -34,38 +34,32 @@ class RewardsPage extends PureComponent<Props> {
return (
!IS_WEB && (
<section className="card card--section">
<header className="card__header">
<h2 className="card__title">{__('Rewards Approval to Earn Credits (LBC)')}</h2>
<p className="card__subtitle">
{__(
'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>
<h2 className="card__title">{__('Rewards Approval to Earn Credits (LBC)')}</h2>
<p className="card__subtitle">
{__(
'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>
<div className="card__content">
<Button navigate="/$/auth?redirect=rewards" button="primary" label="Prove Humanity" />
</div>
<Button navigate="/$/auth?redirect=rewards" button="primary" label="Prove Humanity" />
</section>
)
);
}
return (
<section className="card card--section">
<div className="card__content">
<p>
{__('This account must undergo review before you can participate in the rewards program.')}{' '}
{__('This can take anywhere from several minutes to several days.')}
</p>
<p>
{__('This account must undergo review before you can participate in the rewards program.')}{' '}
{__('This can take anywhere from several minutes to several days.')}
</p>
<p>{__('We apologize for this inconvenience, but have added this additional step to prevent fraud.')}</p>
<p>
{`${__('If you continue to see this message, send us an email to help@lbry.com.')} ${__(
'Please enjoy free content in the meantime!'
)}`}
</p>
</div>
<p>{__('We apologize for this inconvenience, but have added this additional step to prevent fraud.')}</p>
<p>
{`${__('If you continue to see this message, send us an email to help@lbry.com.')} ${__(
'Please enjoy free content in the meantime!'
)}`}
</p>
<div className="card__actions">
<Button navigate="/" button="primary" label="Return Home" />
</div>
@ -95,34 +89,26 @@ class RewardsPage extends PureComponent<Props> {
if (daemonSettings && !daemonSettings.share_usage_data) {
return (
<section className="card card--section">
<header className="card__header">
<h2 className="card__title">{__('Disabled')}</h2>
<p className="card__subtitle">
{__('Rewards are currently disabled for your account. Turn on diagnostic data sharing, in')}{' '}
<Button button="link" navigate="/$/settings" label="Settings" />
{__(', in order to re-enable them.')}
</p>
</header>
<h2 className="card__title">{__('Disabled')}</h2>
<p className="card__subtitle">
{__('Rewards are currently disabled for your account. Turn on diagnostic data sharing, in')}{' '}
<Button button="link" navigate="/$/settings" label="Settings" />
{__(', in order to re-enable them.')}
</p>
</section>
);
} else if (fetching) {
return (
<div className="card__content">
<BusyIndicator message={__('Fetching rewards')} />
</div>
);
return <BusyIndicator message={__('Fetching rewards')} />;
} else if (user === null) {
return (
<section className="card card--section">
<p>{__('This application is unable to earn rewards due to an authentication failure.')}</p>
</section>
<p className="help">{__('This application is unable to earn rewards due to an authentication failure.')}</p>
);
} else if (!rewards || rewards.length <= 0) {
return (
<Fragment>
<section className="card card--section">
<h2 className="card__title">{__('No Rewards Available')}</h2>
<p className="card__content">
<p>
{claimed && claimed.length
? __(
"You have claimed all available rewards! We're regularly adding more so be sure to check back later."

View file

@ -41,10 +41,12 @@ export default function SearchPage(props: Props) {
<Fragment>
{isValid && (
<header className="search__header">
<Button button="alt" navigate={uri} className="media__uri">
<Button button="alt" navigate={uri} className="media__uri--large">
{uri}
</Button>
<ClaimPreview uri={uri} type="large" />
<div className="card">
<ClaimPreview uri={uri} type="large" placeholder="publish" />
</div>
</header>
)}
@ -72,7 +74,7 @@ export default function SearchPage(props: Props) {
}
/>
</div>
<div className="card__content help">{__('These search results are provided by LBRY, Inc.')}</div>
<div className="help">{__('These search results are provided by LBRY, Inc.')}</div>
</Fragment>
)}
</section>

Some files were not shown because too many files have changed in this diff Show more