Merge branch 'master' into suppress-load-video-error

This commit is contained in:
Sean Yesmunt 2018-07-19 10:06:36 -04:00 committed by GitHub
commit e09be7ee83
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 249 additions and 700 deletions

View file

@ -11,7 +11,9 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/).
### Changed ### Changed
* Only show video error modal if you are on the video page & don't retry to play failed videos ([#1768](https://github.com/lbryio/lbry-desktop/pull/1768)) * Only show video error modal if you are on the video page & don't retry to play failed videos ([#1768](https://github.com/lbryio/lbry-desktop/pull/1768))
* Actually hide NSFW files if a user chooses to hide NSFW content via the settings page ([#1748](https://github.com/lbryio/lbry-desktop/pull/1748))
* Hide the "Community top bids" section if user chooses to hide NSFW content ([#1760](https://github.com/lbryio/lbry-desktop/pull/1760))
## [0.22.2] - 2018-07-09 ## [0.22.2] - 2018-07-09

View file

@ -42,7 +42,7 @@
"electron-is-dev": "^0.3.0", "electron-is-dev": "^0.3.0",
"electron-log": "^2.2.12", "electron-log": "^2.2.12",
"electron-publisher-s3": "^20.8.1", "electron-publisher-s3": "^20.8.1",
"electron-updater": "^2.21.10", "electron-updater": "^2.23.3",
"electron-window-state": "^4.1.1", "electron-window-state": "^4.1.1",
"find-process": "^1.1.0", "find-process": "^1.1.0",
"formik": "^0.10.4", "formik": "^0.10.4",
@ -89,14 +89,11 @@
"babel-preset-env": "^1.6.1", "babel-preset-env": "^1.6.1",
"babel-preset-react": "^6.24.1", "babel-preset-react": "^6.24.1",
"babel-preset-stage-2": "^6.18.0", "babel-preset-stage-2": "^6.18.0",
"danger": "^3.6.0",
"danger-plugin-eslint": "^0.1.0",
"danger-plugin-yarn": "^1.3.0",
"decompress": "^4.2.0", "decompress": "^4.2.0",
"del": "^3.0.0", "del": "^3.0.0",
"devtron": "^1.4.0", "devtron": "^1.4.0",
"electron": "^1.8.4", "electron": "^1.8.4",
"electron-builder": "^20.13.3", "electron-builder": "^20.22.0",
"electron-devtools-installer": "^2.2.3", "electron-devtools-installer": "^2.2.3",
"electron-webpack": "^1.13.0", "electron-webpack": "^1.13.0",
"eslint": "^4.19.0", "eslint": "^4.19.0",

View file

@ -2,10 +2,9 @@
import * as React from 'react'; import * as React from 'react';
import classnames from 'classnames'; import classnames from 'classnames';
import Spinner from 'component/spinner'; import Spinner from 'component/spinner';
import { isShowingChildren } from 'util/dom';
// time in ms to wait to show loading spinner // time in ms to wait to show loading spinner
const LOADER_TIMEOUT = 1500; const LOADER_TIMEOUT = 1000;
type Props = { type Props = {
children: React.Node | Array<React.Node>, children: React.Node | Array<React.Node>,
@ -21,23 +20,6 @@ type State = {
}; };
class Page extends React.PureComponent<Props, State> { class Page extends React.PureComponent<Props, State> {
static getDerivedStateFromProps(nextProps: Props, prevState: State) {
const { children } = nextProps;
const { showLoader } = prevState;
// If we aren't showing the loader, don't bother updating
if (!showLoader) {
return null;
}
if (isShowingChildren(children)) {
return {
showLoader: false,
};
}
return null;
}
constructor() { constructor() {
super(); super();
@ -49,16 +31,29 @@ class Page extends React.PureComponent<Props, State> {
} }
componentDidMount() { componentDidMount() {
const { children } = this.props; const { loading } = this.props;
if (loading) {
this.beginLoadingTimeout();
}
}
if (!isShowingChildren(children)) componentDidUpdate(prevProps: Props) {
this.loaderTimeout = setTimeout(() => { const { loading } = this.props;
this.setState({ showLoader: true }); if (!this.loaderTimeout && !prevProps.loading && loading) {
}, LOADER_TIMEOUT); this.beginLoadingTimeout();
}
} }
componentWillUnmount() { componentWillUnmount() {
this.loaderTimeout = null; if (this.loaderTimeout) {
clearTimeout(this.loaderTimeout);
}
}
beginLoadingTimeout() {
this.loaderTimeout = setTimeout(() => {
this.setState({ showLoader: true });
}, LOADER_TIMEOUT);
} }
loaderTimeout: ?TimeoutID; loaderTimeout: ?TimeoutID;
@ -67,10 +62,6 @@ class Page extends React.PureComponent<Props, State> {
const { pageTitle, children, noPadding, extraPadding, notContained, loading } = this.props; const { pageTitle, children, noPadding, extraPadding, notContained, loading } = this.props;
const { showLoader } = this.state; const { showLoader } = this.state;
// We don't want to show the loading spinner right away if it will only flash on the
// screen for a short time, wait until we know it will be loading for a bit before showing it
const shouldShowLoader = !isShowingChildren(children) && showLoader;
return ( return (
<main <main
className={classnames('main', { className={classnames('main', {
@ -85,7 +76,7 @@ class Page extends React.PureComponent<Props, State> {
</div> </div>
)} )}
{!loading && children} {!loading && children}
{shouldShowLoader && ( {showLoader && (
<div className="page__empty"> <div className="page__empty">
<Spinner /> <Spinner />
</div> </div>

View file

@ -4,7 +4,7 @@ import { FormField } from 'component/common/form';
import Button from 'component/button'; import Button from 'component/button';
import FileExporter from 'component/common/file-exporter'; import FileExporter from 'component/common/file-exporter';
import * as icons from 'constants/icons'; import * as icons from 'constants/icons';
import { MODALS } from 'lbry-redux'; import { MODALS, TRANSACTIONS } from 'lbry-redux';
import TransactionListItem from './internal/transaction-list-item'; import TransactionListItem from './internal/transaction-list-item';
export type Transaction = { export type Transaction = {
@ -45,6 +45,10 @@ class TransactionList extends React.PureComponent<Props, State> {
(this: any).isRevokeable = this.isRevokeable.bind(this); (this: any).isRevokeable = this.isRevokeable.bind(this);
} }
capitalize(string: string) {
return string.charAt(0).toUpperCase() + string.slice(1);
}
handleFilterChanged(event: SyntheticInputEvent<*>) { handleFilterChanged(event: SyntheticInputEvent<*>) {
this.setState({ this.setState({
filter: event.target.value, filter: event.target.value,
@ -108,13 +112,30 @@ class TransactionList extends React.PureComponent<Props, State> {
} }
> >
<option value="all">{__('All')}</option> <option value="all">{__('All')}</option>
<option value="spend">{__('Spends')}</option> <option value={TRANSACTIONS.SPEND}>
<option value="receive">{__('Receives')}</option> {__(`${this.capitalize(TRANSACTIONS.SPEND)}s`)}
<option value="publish">{__('Publishes')}</option> </option>
<option value="channel">{__('Channels')}</option> <option value={TRANSACTIONS.RECEIVE}>
<option value="tip">{__('Tips')}</option> {__(`${this.capitalize(TRANSACTIONS.RECEIVE)}s`)}
<option value="support">{__('Supports')}</option> </option>
<option value="update">{__('Updates')}</option> <option value={TRANSACTIONS.PUBLISH}>
{__(`${this.capitalize(TRANSACTIONS.PUBLISH)}es`)}
</option>
<option value={TRANSACTIONS.CHANNEL}>
{__(`${this.capitalize(TRANSACTIONS.CHANNEL)}s`)}
</option>
<option value={TRANSACTIONS.TIP}>
{__(`${this.capitalize(TRANSACTIONS.TIP)}s`)}
</option>
<option value={TRANSACTIONS.SUPPORT}>
{__(`${this.capitalize(TRANSACTIONS.SUPPORT)}s`)}
</option>
<option value={TRANSACTIONS.UPDATE}>
{__(`${this.capitalize(TRANSACTIONS.UPDATE)}s`)}
</option>
<option value={TRANSACTIONS.ABANDON}>
{__(`${this.capitalize(TRANSACTIONS.ABANDON)}s`)}
</option>
</FormField> </FormField>
</div> </div>
)} )}

View file

@ -1,10 +1,15 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { selectFileInfosDownloaded, selectMyClaimsWithoutChannels } from 'lbry-redux'; import {
selectFileInfosDownloaded,
selectMyClaimsWithoutChannels,
selectIsFetchingFileList,
} from 'lbry-redux';
import { doNavigate } from 'redux/actions/navigation'; import { doNavigate } from 'redux/actions/navigation';
import FileListDownloaded from './view'; import FileListDownloaded from './view';
const select = state => ({ const select = state => ({
fileInfos: selectFileInfosDownloaded(state), fileInfos: selectFileInfosDownloaded(state),
fetching: selectIsFetchingFileList(state),
claims: selectMyClaimsWithoutChannels(state), claims: selectMyClaimsWithoutChannels(state),
}); });
@ -12,4 +17,7 @@ const perform = dispatch => ({
navigate: path => dispatch(doNavigate(path)), navigate: path => dispatch(doNavigate(path)),
}); });
export default connect(select, perform)(FileListDownloaded); export default connect(
select,
perform
)(FileListDownloaded);

View file

@ -1,15 +1,22 @@
// @flow
import React from 'react'; import React from 'react';
import Button from 'component/button'; import Button from 'component/button';
import FileList from 'component/fileList'; import FileList from 'component/fileList';
import Page from 'component/page'; import Page from 'component/page';
class FileListDownloaded extends React.PureComponent { type Props = {
fetching: boolean,
fileInfos: {},
navigate: (string, ?{}) => void,
};
class FileListDownloaded extends React.PureComponent<Props> {
render() { render() {
const { fileInfos, navigate } = this.props; const { fetching, fileInfos, navigate } = this.props;
const hasDownloads = fileInfos && fileInfos.length > 0; const hasDownloads = fileInfos && Object.values(fileInfos).length > 0;
return ( return (
<Page notContained> <Page notContained loading={fetching}>
{hasDownloads ? ( {hasDownloads ? (
<FileList fileInfos={fileInfos} /> <FileList fileInfos={fileInfos} />
) : ( ) : (

View file

@ -1,11 +1,13 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { selectPendingPublishes, selectClaimsWithPendingPublishes } from 'redux/selectors/publish'; import { selectPendingPublishes, selectClaimsWithPendingPublishes } from 'redux/selectors/publish';
import { selectIsFetchingClaimListMine } from 'lbry-redux';
import { doNavigate } from 'redux/actions/navigation'; import { doNavigate } from 'redux/actions/navigation';
import { doCheckPendingPublishes } from 'redux/actions/publish'; import { doCheckPendingPublishes } from 'redux/actions/publish';
import FileListPublished from './view'; import FileListPublished from './view';
const select = state => ({ const select = state => ({
claims: selectClaimsWithPendingPublishes(state), claims: selectClaimsWithPendingPublishes(state),
fetching: selectIsFetchingClaimListMine(state),
pendingPublishes: selectPendingPublishes(state), pendingPublishes: selectPendingPublishes(state),
}); });

View file

@ -9,6 +9,7 @@ type Props = {
claims: Array<{}>, claims: Array<{}>,
checkIfPublishesConfirmed: (Array<{}>) => void, checkIfPublishesConfirmed: (Array<{}>) => void,
navigate: (string, ?{}) => void, navigate: (string, ?{}) => void,
fetching: boolean,
}; };
class FileListPublished extends React.PureComponent<Props> { class FileListPublished extends React.PureComponent<Props> {
@ -20,11 +21,11 @@ class FileListPublished extends React.PureComponent<Props> {
} }
render() { render() {
const { claims, navigate } = this.props; const { fetching, claims, navigate } = this.props;
return ( return (
<Page notContained> <Page notContained loading={fetching}>
{claims.length ? ( {claims && claims.length ? (
<FileList checkPending fileInfos={claims} sortByHeight /> <FileList checkPending fileInfos={claims} sortByHeight />
) : ( ) : (
<div className="page__empty"> <div className="page__empty">

View file

@ -11,15 +11,20 @@ import { setSubscriptionNotifications, doFetchMySubscriptions } from 'redux/acti
import SubscriptionsPage from './view'; import SubscriptionsPage from './view';
const select = state => ({ const select = state => ({
isFetchingSubscriptions: selectIsFetchingSubscriptions(state), loading:
selectIsFetchingSubscriptions(state) ||
Object.keys(selectSubscriptionsBeingFetched(state)).length,
subscriptionsBeingFetched: selectSubscriptionsBeingFetched(state), subscriptionsBeingFetched: selectSubscriptionsBeingFetched(state),
subscriptions: selectSubscriptions(state), subscriptions: selectSubscriptions(state),
subscriptionClaims: selectSubscriptionClaims(state), subscriptionClaims: selectSubscriptionClaims(state),
notifications: selectNotifications(state), notifications: selectNotifications(state),
}); });
export default connect(select, { export default connect(
select,
{
doFetchClaimsByChannel, doFetchClaimsByChannel,
setSubscriptionNotifications, setSubscriptionNotifications,
doFetchMySubscriptions, doFetchMySubscriptions,
})(SubscriptionsPage); }
)(SubscriptionsPage);

View file

@ -14,10 +14,10 @@ type Props = {
doFetchMySubscriptions: () => void, doFetchMySubscriptions: () => void,
setSubscriptionNotifications: ({}) => void, setSubscriptionNotifications: ({}) => void,
subscriptions: Array<Subscription>, subscriptions: Array<Subscription>,
isFetchingSubscriptions: boolean,
subscriptionClaims: Array<{ uri: string, claims: Array<Claim> }>, subscriptionClaims: Array<{ uri: string, claims: Array<Claim> }>,
subscriptionsBeingFetched: {}, subscriptionsBeingFetched: {},
notifications: {}, notifications: {},
loading: boolean,
}; };
export default class extends React.PureComponent<Props> { export default class extends React.PureComponent<Props> {
@ -52,10 +52,13 @@ export default class extends React.PureComponent<Props> {
if (claim.claims.length) { if (claim.claims.length) {
subscriptionClaimMap[claim.uri] = 1; subscriptionClaimMap[claim.uri] = 1;
} else if (isDev) { } else if (isDev) {
console // eslint-disable no-console
.error console.error(
// `claim for ${claim.uri} was added to byId in redux but there are no loaded fetched claims` `Claim for ${
(); claim.uri
} was added to byId in redux but there are no loaded fetched claims. This shouldn't happen because a subscription should have claims attached to it.`
);
// eslint-enable no-console
} }
}); });
@ -67,7 +70,7 @@ export default class extends React.PureComponent<Props> {
} }
render() { render() {
const { subscriptions, subscriptionClaims, isFetchingSubscriptions } = this.props; const { subscriptions, subscriptionClaims, loading } = this.props;
let claimList = []; let claimList = [];
subscriptionClaims.forEach(claimData => { subscriptionClaims.forEach(claimData => {
@ -77,7 +80,7 @@ export default class extends React.PureComponent<Props> {
const subscriptionUris = claimList.map(claim => `lbry://${claim.name}#${claim.claim_id}`); const subscriptionUris = claimList.map(claim => `lbry://${claim.name}#${claim.claim_id}`);
return ( return (
<Page notContained loading={isFetchingSubscriptions}> <Page notContained loading={loading}>
<HiddenNsfwClaims uris={subscriptionUris} /> <HiddenNsfwClaims uris={subscriptionUris} />
{!subscriptions.length && ( {!subscriptions.length && (
<div className="page__empty"> <div className="page__empty">

View file

@ -117,7 +117,7 @@ export const doUploadThumbnail = (filePath: string, nsfw: boolean) => (dispatch:
type: ACTIONS.UPDATE_PUBLISH_FORM, type: ACTIONS.UPDATE_PUBLISH_FORM,
data: { data: {
uploadThumbnailStatus: THUMBNAIL_STATUSES.COMPLETE, uploadThumbnailStatus: THUMBNAIL_STATUSES.COMPLETE,
thumbnail: `${json.data.embedUrl}`, thumbnail: `${json.data.url}${fileExt}`,
}, },
}) })
: uploadError('Upload failed') : uploadError('Upload failed')

View file

@ -1,12 +0,0 @@
// @flow
import * as React from 'react';
// is a child component being rendered?
export const isShowingChildren = (children: React.Node): boolean => {
if (Array.isArray(children)) {
const firstChildIndex = children.findIndex(child => child);
return firstChildIndex > -1;
}
return !!children;
};

766
yarn.lock

File diff suppressed because it is too large Load diff