Merge branch 'master' into suppress-load-video-error
This commit is contained in:
commit
e09be7ee83
13 changed files with 249 additions and 700 deletions
|
@ -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
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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} />
|
||||||
) : (
|
) : (
|
||||||
|
|
|
@ -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),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -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">
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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">
|
||||||
|
|
|
@ -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')
|
||||||
|
|
|
@ -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;
|
|
||||||
};
|
|
Loading…
Reference in a new issue