make select and file actions refactor

This commit is contained in:
Jeremy Kauffman 2017-09-07 23:15:05 -04:00
parent bdf84b3dbd
commit 680bb1df9d
35 changed files with 409 additions and 586 deletions

View file

@ -17,11 +17,12 @@ const { download } = remote.require("electron-dl");
const fs = remote.require("fs");
const { lbrySettings: config } = require("../../../app/package.json");
export function doOpenModal(modal) {
export function doOpenModal(modal, modalProps = {}) {
return {
type: types.OPEN_MODAL,
data: {
modal,
modalProps,
},
};
}
@ -166,7 +167,7 @@ export function doAlertError(errorList) {
type: types.OPEN_MODAL,
data: {
modal: "error",
extraContent: errorList,
modalProps: { error: errorList },
},
});
};

View file

@ -4,11 +4,11 @@ import lbryio from "lbryio";
import lbryuri from "lbryuri";
import { selectBalance } from "selectors/wallet";
import {
selectFileInfoForUri,
makeSelectFileInfoForUri,
selectDownloadingByOutpoint,
} from "selectors/file_info";
import { selectResolvingUris } from "selectors/content";
import { selectCostInfoForUri } from "selectors/cost_info";
import { makeSelectCostInfoForUri } from "selectors/cost_info";
import { doAlertError, doOpenModal } from "actions/app";
import { doClaimEligiblePurchaseRewards } from "actions/rewards";
import { selectBadgeNumber } from "selectors/app";
@ -299,13 +299,12 @@ export function doLoadVideo(uri) {
data: { uri },
});
dispatch(doOpenModal(modals.FILE_TIMEOUT));
dispatch(doOpenModal(modals.FILE_TIMEOUT, { uri }));
} else {
dispatch(doDownloadFile(uri, streamInfo));
}
})
.catch(error => {
console.log(error);
dispatch({
type: types.LOADING_VIDEO_FAILED,
data: { uri },
@ -315,11 +314,11 @@ export function doLoadVideo(uri) {
};
}
export function doPurchaseUri(uri, purchaseModalName) {
export function doPurchaseUri(uri) {
return function(dispatch, getState) {
const state = getState();
const balance = selectBalance(state);
const fileInfo = selectFileInfoForUri(state, { uri });
const fileInfo = makeSelectFileInfoForUri(uri)(state);
const downloadingByOutpoint = selectDownloadingByOutpoint(state);
const alreadyDownloading =
fileInfo && !!downloadingByOutpoint[fileInfo.outpoint];
@ -339,7 +338,7 @@ export function doPurchaseUri(uri, purchaseModalName) {
return Promise.resolve();
}
const costInfo = selectCostInfoForUri(state, { uri });
const costInfo = makeSelectCostInfoForUri(uri)(state);
const { cost } = costInfo;
// the file is free or we have partially downloaded it
@ -351,7 +350,7 @@ export function doPurchaseUri(uri, purchaseModalName) {
if (cost > balance) {
dispatch(doOpenModal(modals.INSUFFICIENT_CREDITS));
} else {
dispatch(doOpenModal(purchaseModalName));
dispatch(doOpenModal(modals.AFFIRM_PURCHASE, { uri }));
}
return Promise.resolve();

View file

@ -1,52 +1,32 @@
import React from "react";
import { connect } from "react-redux";
import { selectPlatform } from "selectors/app";
import {
makeSelectFileInfoForUri,
makeSelectDownloadingForUri,
makeSelectLoadingForUri,
} from "selectors/file_info";
import { makeSelectIsAvailableForUri } from "selectors/availability";
import { makeSelectFileInfoForUri } from "selectors/file_info";
import { makeSelectCostInfoForUri } from "selectors/cost_info";
import { doOpenModal } from "actions/app";
import { doFetchAvailability } from "actions/availability";
import { doOpenFileInShell, doOpenFileInFolder } from "actions/file_info";
import { makeSelectClaimForUriIsMine } from "selectors/claims";
import { makeSelectClaimIsMine } from "selectors/claims";
import { doPurchaseUri, doLoadVideo, doStartDownload } from "actions/content";
import { doNavigate } from "actions/navigation";
import FileActions from "./view";
const makeSelect = () => {
const selectFileInfoForUri = makeSelectFileInfoForUri();
const selectIsAvailableForUri = makeSelectIsAvailableForUri();
const selectDownloadingForUri = makeSelectDownloadingForUri();
const selectCostInfoForUri = makeSelectCostInfoForUri();
const selectLoadingForUri = makeSelectLoadingForUri();
const selectClaimForUriIsMine = makeSelectClaimForUriIsMine();
const select = (state, props) => ({
fileInfo: selectFileInfoForUri(state, props),
/*availability check is disabled due to poor performance, TBD if it dies forever or requires daemon fix*/
isAvailable: true, //selectIsAvailableForUri(state, props),
platform: selectPlatform(state),
downloading: selectDownloadingForUri(state, props),
costInfo: selectCostInfoForUri(state, props),
loading: selectLoadingForUri(state, props),
claimIsMine: selectClaimForUriIsMine(state, props),
});
return select;
};
const select = (state, props) => ({
fileInfo: makeSelectFileInfoForUri(props.uri)(state),
/*availability check is disabled due to poor performance, TBD if it dies forever or requires daemon fix*/
platform: selectPlatform(state),
costInfo: makeSelectCostInfoForUri(props.uri)(state),
claimIsMine: makeSelectClaimIsMine(props.uri)(state),
});
const perform = dispatch => ({
checkAvailability: uri => dispatch(doFetchAvailability(uri)),
openInFolder: fileInfo => dispatch(doOpenFileInFolder(fileInfo)),
openInShell: fileInfo => dispatch(doOpenFileInShell(fileInfo)),
openModal: modal => dispatch(doOpenModal(modal)),
startDownload: uri => dispatch(doPurchaseUri(uri, "affirmPurchase")),
loadVideo: uri => dispatch(doLoadVideo(uri)),
openModal: (modal, props) => dispatch(doOpenModal(modal, props)),
startDownload: uri => dispatch(doPurchaseUri(uri)),
restartDownload: (uri, outpoint) => dispatch(doStartDownload(uri, outpoint)),
editClaim: fileInfo => dispatch(doNavigate("/publish", fileInfo)),
});
export default connect(makeSelect, perform)(FileActions);
export default connect(select, perform)(FileActions);

View file

@ -1,59 +1,10 @@
import React from "react";
import { Icon, BusyMessage } from "component/common";
import Link from "component/link";
import { ToolTip } from "component/tooltip";
import FileDownloadLink from "component/fileDownloadLink";
import { DropDownMenu, DropDownMenuItem } from "component/menu";
import * as modals from "constants/modal_types";
class FileActions extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
forceShowActions: false,
};
}
componentWillMount() {
this.checkAvailability(this.props.uri);
}
componentWillReceiveProps(nextProps) {
this.checkAvailability(nextProps.uri);
this.restartDownload(nextProps);
}
restartDownload(props) {
const { downloading, fileInfo, uri, restartDownload } = props;
if (
!downloading &&
fileInfo &&
!fileInfo.completed &&
fileInfo.written_bytes !== false &&
fileInfo.written_bytes < fileInfo.total_bytes
) {
restartDownload(uri, fileInfo.outpoint);
}
}
checkAvailability(uri) {
if (!this._uri || uri !== this._uri) {
this._uri = uri;
this.props.checkAvailability(uri);
}
}
onShowFileActionsRowClicked() {
this.setState({
forceShowActions: true,
});
}
onAffirmPurchase() {
this.props.closeModal();
this.props.loadVideo(this.props.uri);
}
handleSupportButtonClicked() {
this.props.onTipShow();
}
@ -61,16 +12,10 @@ class FileActions extends React.PureComponent {
render() {
const {
fileInfo,
isAvailable,
platform,
downloading,
uri,
openInFolder,
openInShell,
openModal,
startDownload,
costInfo,
loading,
claimIsMine,
editClaim,
} = this.props;
@ -85,90 +30,9 @@ class FileActions extends React.PureComponent {
showMenu = fileInfo && Object.keys(fileInfo).length > 0,
title = metadata ? metadata.title : uri;
let content;
if (loading || downloading) {
const progress = fileInfo && fileInfo.written_bytes
? fileInfo.written_bytes / fileInfo.total_bytes * 100
: 0,
label = fileInfo
? progress.toFixed(0) + __("% complete")
: __("Connecting..."),
labelWithIcon = (
<span className="button__content">
<Icon icon="icon-download" />
<span>
{label}
</span>
</span>
);
content = (
<div className="faux-button-block file-actions__download-status-bar button-set-item">
<div
className="faux-button-block file-actions__download-status-bar-overlay"
style={{ width: progress + "%" }}
>
{labelWithIcon}
</div>
{labelWithIcon}
</div>
);
} else if (!fileInfo && isAvailable === undefined) {
content = <BusyMessage message={__("Checking availability")} />;
} else if (!fileInfo && !isAvailable && !this.state.forceShowActions) {
content = (
<div>
<div className="button-set-item empty">
{__("Content unavailable.")}
</div>
<ToolTip
label={__("Why?")}
body={__(
"The content on LBRY is hosted by its users. It appears there are no users connected that have this file at the moment."
)}
className="button-set-item"
/>
<Link
label={__("Try Anyway")}
onClick={this.onShowFileActionsRowClicked.bind(this)}
className="button-text button-set-item"
/>
</div>
);
} else if (fileInfo === null && !downloading) {
if (!costInfo) {
content = <BusyMessage message={__("Fetching cost info")} />;
} else {
content = (
<Link
button="text"
label={__("Download")}
icon="icon-download"
onClick={() => {
startDownload(uri);
}}
/>
);
}
} else if (fileInfo && fileInfo.download_path) {
content = (
<Link
label={__("Open")}
button="text"
icon="icon-folder-open"
onClick={() => openInShell(fileInfo)}
/>
);
} else if (!fileInfo) {
content = <BusyMessage message={__("Fetching file info")} />;
} else {
console.log("handle this case of file action props?");
}
return (
<section className="file-actions">
{content}
<FileDownloadLink uri={uri} />
<Link
label={__("Support")}
button="text"
@ -191,7 +55,7 @@ class FileActions extends React.PureComponent {
/>}
<DropDownMenuItem
key={2}
onClick={() => openModal(modals.CONFIRM_FILE_REMOVE)}
onClick={() => openModal(modals.CONFIRM_FILE_REMOVE, { uri })}
label={__("Remove...")}
/>
</DropDownMenu>

View file

@ -9,32 +9,23 @@ import {
} from "selectors/claims";
import { makeSelectFileInfoForUri } from "selectors/file_info";
import {
makeSelectIsResolvingForUri,
makeSelectIsUriResolving,
selectRewardContentClaimIds,
} from "selectors/content";
import FileCard from "./view";
const makeSelect = () => {
const selectClaimForUri = makeSelectClaimForUri();
const selectFileInfoForUri = makeSelectFileInfoForUri();
const selectMetadataForUri = makeSelectMetadataForUri();
const selectResolvingUri = makeSelectIsResolvingForUri();
const select = (state, props) => ({
claim: selectClaimForUri(state, props),
fileInfo: selectFileInfoForUri(state, props),
obscureNsfw: !selectShowNsfw(state),
metadata: selectMetadataForUri(state, props),
rewardedContentClaimIds: selectRewardContentClaimIds(state, props),
isResolvingUri: selectResolvingUri(state, props),
});
return select;
};
const select = (state, props) => ({
claim: makeSelectClaimForUri(props.uri)(state),
fileInfo: makeSelectFileInfoForUri(props.uri)(state),
obscureNsfw: !selectShowNsfw(state),
metadata: makeSelectMetadataForUri(props.uri)(state),
rewardedContentClaimIds: selectRewardContentClaimIds(state, props),
isResolvingUri: makeSelectIsUriResolving(props.uri)(state),
});
const perform = dispatch => ({
navigate: (path, params) => dispatch(doNavigate(path, params)),
resolveUri: uri => dispatch(doResolveUri(uri)),
});
export default connect(makeSelect, perform)(FileCard);
export default connect(select, perform)(FileCard);

View file

@ -0,0 +1,31 @@
import React from "react";
import { connect } from "react-redux";
import {
makeSelectFileInfoForUri,
makeSelectDownloadingForUri,
makeSelectLoadingForUri,
} from "selectors/file_info";
import { makeSelectCostInfoForUri } from "selectors/cost_info";
import { doFetchAvailability } from "actions/availability";
import { doOpenFileInShell } from "actions/file_info";
import { doPurchaseUri, doStartDownload } from "actions/content";
import FileDownloadLink from "./view";
import * as modals from "constants/modal_types";
const select = (state, props) => ({
fileInfo: makeSelectFileInfoForUri(props.uri)(state),
/*availability check is disabled due to poor performance, TBD if it dies forever or requires daemon fix*/
downloading: makeSelectDownloadingForUri(props.uri)(state),
costInfo: makeSelectCostInfoForUri(props.uri)(state),
loading: makeSelectLoadingForUri(props.uri)(state),
});
const perform = dispatch => ({
checkAvailability: uri => dispatch(doFetchAvailability(uri)),
openInShell: fileInfo => dispatch(doOpenFileInShell(fileInfo)),
startDownload: uri =>
dispatch(doPurchaseUri(uri, modals.CONFIRM_FILE_PURCHASE)),
restartDownload: (uri, outpoint) => dispatch(doStartDownload(uri, outpoint)),
});
export default connect(select, perform)(FileDownloadLink);

View file

@ -0,0 +1,104 @@
import React from "react";
import { Icon, BusyMessage } from "component/common";
import Link from "component/link";
class FileDownloadLink extends React.PureComponent {
componentWillMount() {
this.checkAvailability(this.props.uri);
}
componentWillReceiveProps(nextProps) {
this.checkAvailability(nextProps.uri);
this.restartDownload(nextProps);
}
restartDownload(props) {
const { downloading, fileInfo, uri, restartDownload } = props;
if (
!downloading &&
fileInfo &&
!fileInfo.completed &&
fileInfo.written_bytes !== false &&
fileInfo.written_bytes < fileInfo.total_bytes
) {
restartDownload(uri, fileInfo.outpoint);
}
}
checkAvailability(uri) {
if (!this._uri || uri !== this._uri) {
this._uri = uri;
this.props.checkAvailability(uri);
}
}
render() {
const {
fileInfo,
downloading,
uri,
openInShell,
startDownload,
costInfo,
loading,
} = this.props;
if (loading || downloading) {
const progress = fileInfo && fileInfo.written_bytes
? fileInfo.written_bytes / fileInfo.total_bytes * 100
: 0,
label = fileInfo
? progress.toFixed(0) + __("% complete")
: __("Connecting..."),
labelWithIcon = (
<span className="button__content">
<Icon icon="icon-download" />
<span>
{label}
</span>
</span>
);
return (
<div className="faux-button-block file-actions__download-status-bar button-set-item">
<div
className="faux-button-block file-actions__download-status-bar-overlay"
style={{ width: progress + "%" }}
>
{labelWithIcon}
</div>
{labelWithIcon}
</div>
);
} else if (fileInfo === null && !downloading) {
if (!costInfo) {
return <BusyMessage message={__("Fetching cost info")} />;
} else {
return (
<Link
button="text"
label={__("Download")}
icon="icon-download"
onClick={() => {
startDownload(uri);
}}
/>
);
}
} else if (fileInfo && fileInfo.download_path) {
return (
<Link
label={__("Open")}
button="text"
icon="icon-external-link-square"
onClick={() => openInShell(fileInfo)}
/>
);
}
return null;
}
}
export default FileDownloadLink;

View file

@ -8,23 +8,15 @@ import {
import { makeSelectClaimForUri } from "selectors/claims";
import FilePrice from "./view";
const makeSelect = () => {
const selectCostInfoForUri = makeSelectCostInfoForUri();
const selectFetchingCostInfoForUri = makeSelectFetchingCostInfoForUri();
const selectClaim = makeSelectClaimForUri();
const select = (state, props) => ({
costInfo: selectCostInfoForUri(state, props),
fetching: selectFetchingCostInfoForUri(state, props),
claim: selectClaim(state, props),
});
return select;
};
const select = (state, props) => ({
costInfo: makeSelectCostInfoForUri(props.uri)(state),
fetching: makeSelectFetchingCostInfoForUri(props.uri)(state),
claim: makeSelectClaimForUri(props.uri)(state),
});
const perform = dispatch => ({
fetchCostInfo: uri => dispatch(doFetchCostInfoForUri(uri)),
// cancelFetchCostInfo: (uri) => dispatch(doCancelFetchCostInfoForUri(uri))
});
export default connect(makeSelect, perform)(FilePrice);
export default connect(select, perform)(FilePrice);

View file

@ -9,32 +9,23 @@ import {
import { makeSelectFileInfoForUri } from "selectors/file_info";
import { selectShowNsfw } from "selectors/settings";
import {
makeSelectIsResolvingForUri,
makeSelectIsUriResolving,
selectRewardContentClaimIds,
} from "selectors/content";
import FileTile from "./view";
const makeSelect = () => {
const selectClaimForUri = makeSelectClaimForUri();
const selectFileInfoForUri = makeSelectFileInfoForUri();
const selectMetadataForUri = makeSelectMetadataForUri();
const selectResolvingUri = makeSelectIsResolvingForUri();
const select = (state, props) => ({
claim: selectClaimForUri(state, props),
fileInfo: selectFileInfoForUri(state, props),
obscureNsfw: !selectShowNsfw(state),
metadata: selectMetadataForUri(state, props),
isResolvingUri: selectResolvingUri(state, props),
rewardedContentClaimIds: selectRewardContentClaimIds(state, props),
});
return select;
};
const select = (state, props) => ({
claim: makeSelectClaimForUri(props.uri)(state),
fileInfo: makeSelectFileInfoForUri(props.uri)(state),
obscureNsfw: !selectShowNsfw(state),
metadata: makeSelectMetadataForUri(props.uri)(state),
isResolvingUri: makeSelectIsUriResolving(props.uri)(state),
rewardedContentClaimIds: selectRewardContentClaimIds(state, props),
});
const perform = dispatch => ({
navigate: (path, params) => dispatch(doNavigate(path, params)),
resolveUri: uri => dispatch(doResolveUri(uri)),
});
export default connect(makeSelect, perform)(FileTile);
export default connect(select, perform)(FileTile);

View file

@ -46,7 +46,7 @@ const Router = props => {
search: <SearchPage params={params} />,
send: <SendCreditsPage params={params} />,
settings: <SettingsPage params={params} />,
show: <ShowPage params={params} />,
show: <ShowPage {...params} />,
wallet: <WalletPage params={params} />,
});
};

View file

@ -1,25 +1,19 @@
import React from "react";
import lbryuri from "lbryuri";
import { connect } from "react-redux";
import { makeSelectIsResolvingForUri } from "selectors/content";
import { doResolveUri } from "actions/content";
import { makeSelectIsUriResolving } from "selectors/content";
import { makeSelectClaimForUri } from "selectors/claims";
import UriIndicator from "./view";
const makeSelect = () => {
const selectClaim = makeSelectClaimForUri(),
selectIsResolving = makeSelectIsResolvingForUri();
const select = (state, props) => ({
claim: selectClaim(state, props),
isResolvingUri: selectIsResolving(state, props),
uri: lbryuri.normalize(props.uri),
});
return select;
};
const select = (state, props) => ({
claim: makeSelectClaimForUri(props.uri)(state),
isResolvingUri: makeSelectIsUriResolving(props.uri)(state),
uri: lbryuri.normalize(props.uri),
});
const perform = dispatch => ({
resolveUri: uri => dispatch(doResolveUri(uri)),
});
export default connect(makeSelect, perform)(UriIndicator);
export default connect(select, perform)(UriIndicator);

View file

@ -17,34 +17,21 @@ import { makeSelectCostInfoForUri } from "selectors/cost_info";
import { selectShowNsfw } from "selectors/settings";
import Video from "./view";
const makeSelect = () => {
const selectCostInfo = makeSelectCostInfoForUri();
const selectFileInfo = makeSelectFileInfoForUri();
const selectIsLoading = makeSelectLoadingForUri();
const selectIsDownloading = makeSelectDownloadingForUri();
const selectMetadata = makeSelectMetadataForUri();
const selectContentType = makeSelectContentTypeForUri();
const select = (state, props) => ({
costInfo: selectCostInfo(state, props),
fileInfo: selectFileInfo(state, props),
metadata: selectMetadata(state, props),
obscureNsfw: !selectShowNsfw(state),
modal: selectCurrentModal(state),
isLoading: selectIsLoading(state, props),
isDownloading: selectIsDownloading(state, props),
contentType: selectContentType(state, props),
volume: selectVolume(state, props),
});
return select;
};
const select = (state, props) => ({
costInfo: makeSelectCostInfoForUri(props.uri)(state),
fileInfo: makeSelectFileInfoForUri(props.uri)(state),
metadata: makeSelectMetadataForUri(props.uri)(state),
obscureNsfw: !selectShowNsfw(state),
isLoading: makeSelectLoadingForUri(props.uri)(state),
isDownloading: makeSelectDownloadingForUri(props.uri)(state),
contentType: makeSelectContentTypeForUri(props.uri)(state),
volume: selectVolume(state),
});
const perform = dispatch => ({
loadVideo: uri => dispatch(doLoadVideo(uri)),
purchaseUri: uri => dispatch(doPurchaseUri(uri, "affirmPurchaseAndPlay")),
closeModal: () => dispatch(doCloseModal()),
purchaseUri: uri => dispatch(doPurchaseUri(uri)),
changeVolume: volume => dispatch(doChangeVolume(volume)),
});
export default connect(makeSelect, perform)(Video);
export default connect(select, perform)(Video);

View file

@ -1,7 +1,5 @@
import React from "react";
import FilePrice from "component/filePrice";
import Link from "component/link";
import Modal from "modal/modal";
class VideoPlayButton extends React.PureComponent {
componentDidMount() {
@ -13,12 +11,6 @@ class VideoPlayButton extends React.PureComponent {
document.removeEventListener("keydown", this.keyDownListener);
}
onPurchaseConfirmed() {
this.props.closeModal();
this.props.startPlaying();
this.props.loadVideo(this.props.uri);
}
onKeyDown(event) {
if (
"input" !== event.target.tagName.toLowerCase() &&
@ -33,23 +25,14 @@ class VideoPlayButton extends React.PureComponent {
this.props.purchaseUri(this.props.uri).then(() => {
if (!this.props.modal) {
this.props.startPlaying();
} else {
alert("fix me set pending play");
}
});
}
render() {
const {
button,
label,
metadata,
metadata: { title },
uri,
modal,
closeModal,
isLoading,
fileInfo,
mediaType,
} = this.props;
const { button, label, isLoading, fileInfo, mediaType } = this.props;
/*
title={
@ -64,31 +47,15 @@ class VideoPlayButton extends React.PureComponent {
? "icon-play"
: "icon-folder-o";
return (
<div>
<Link
button={button ? button : null}
disabled={disabled}
label={label ? label : ""}
className="video__play-button"
icon={icon}
onClick={this.onWatchClick.bind(this)}
/>
<Modal
type="confirm"
isOpen={modal == "affirmPurchaseAndPlay"}
contentLabel={__("Confirm Purchase")}
onConfirmed={this.onPurchaseConfirmed.bind(this)}
onAborted={closeModal}
>
{__("This will purchase")} <strong>{title}</strong> {__("for")}{" "}
<strong>
<FilePrice uri={uri} showFullPrice={true} look="plain" />
</strong>{" "}
{__("credits")}.
</Modal>
</div>
);
return;
<Link
button={button ? button : null}
disabled={disabled}
label={label ? label : ""}
className="video__play-button"
icon={icon}
onClick={this.onWatchClick.bind(this)}
/>;
}
}

View file

@ -1,15 +1,17 @@
import React from "react";
import { connect } from "react-redux";
import { doCloseModal } from "actions/app";
import { doLoadVideo } from "actions/content";
import { makeSelectMetadataForUri } from "selectors/claims";
import ModalAffirmPurchase from "./view";
const select = state => ({
metadata: makeSelectMetadataForUri()(state),
const select = (state, props) => ({
metadata: makeSelectMetadataForUri(props.uri)(state),
});
const perform = dispatch => ({
closeModal: () => dispatch(doCloseModal()),
loadVideo: uri => dispatch(doLoadVideo(uri)),
});
export default connect(select, perform)(ModalAffirmPurchase);

View file

@ -3,13 +3,18 @@ import FilePrice from "component/filePrice";
import { Modal } from "modal/modal";
class ModalAffirmPurchase extends React.PureComponent {
onAffirmPurchase() {
this.props.closeModal();
this.props.loadVideo(this.props.uri);
}
render() {
const { metadata: { title } } = this.props;
const { closeModal, metadata: { title }, uri } = this.props;
return (
<Modal
type="confirm"
isOpen={modal == "affirmPurchase"}
isOpen={true}
contentLabel={__("Confirm Purchase")}
onConfirmed={this.onAffirmPurchase.bind(this)}
onAborted={closeModal}

View file

@ -9,4 +9,4 @@ const perform = dispatch => ({
close: () => dispatch(doCloseModal()),
});
export default connect(select, perform)(ModalAuthFailure);
export default connect(null, null)(ModalAuthFailure);

View file

@ -1,16 +1,10 @@
import React from "react";
import { connect } from "react-redux";
import { selectCurrentModal, selectModalExtraContent } from "selectors/app";
import { doCloseModal } from "actions/app";
import ModalError from "./view";
const select = state => ({
modal: selectCurrentModal(state),
error: selectModalExtraContent(state),
});
const perform = dispatch => ({
closeModal: () => dispatch(doCloseModal()),
});
export default connect(select, perform)(ModalError);
export default connect(null, perform)(ModalError);

View file

@ -4,7 +4,7 @@ import { ExpandableModal } from "modal/modal";
class ModalError extends React.PureComponent {
render() {
const { modal, closeModal, error } = this.props;
const { closeModal, error } = this.props;
const errorObj = typeof error === "string" ? { message: error } : error;
@ -33,7 +33,7 @@ class ModalError extends React.PureComponent {
return (
<ExpandableModal
isOpen={modal == "error"}
isOpen={true}
contentLabel={__("Error")}
className="error-modal"
overlayClassName="error-modal-overlay"

View file

@ -5,7 +5,7 @@ import { makeSelectMetadataForUri } from "selectors/claims";
import ModalFileTimeout from "./view";
const select = state => ({
metadata: makeSelectMetadataForUri()(state),
metadata: makeSelectMetadataForUri(props.uri)(state),
});
const perform = dispatch => ({

View file

@ -2,16 +2,17 @@ import React from "react";
import { connect } from "react-redux";
import { doCloseModal } from "actions/app";
import { doDeleteFileAndGoBack } from "actions/file_info";
import { makeSelectClaimForUriIsMine } from "selectors/claims";
import {
makeSelectMetadataForUri,
makeSelectClaimIsMine,
} from "selectors/claims";
import { makeSelectFileInfoForUri } from "selectors/file_info";
import ModalRemoveFile from "./view";
import { makeSelectFileInfoForUri } from "../../selectors/file_info";
const select = (state, props) => ({
claimIsMine: makeSelectClaimForUriIsMine()(state, props),
uri: makeSelectCurrentParam("uri")(state, props),
metadata: makeSelectMetadataForUri()(state, props),
outpoint: makeSelectFileInfoForUri()(state, props),
claimIsMine: makeSelectClaimIsMine(props.uri)(state),
metadata: makeSelectMetadataForUri(props.uri)(state),
fileInfo: makeSelectFileInfoForUri(props.uri)(state),
});
const perform = dispatch => ({

View file

@ -25,7 +25,13 @@ class ModalRemoveFile extends React.PureComponent {
}
render() {
const { claimIsMine, closeModal, deleteFile, outpoint, title } = this.props;
const {
claimIsMine,
closeModal,
deleteFile,
fileInfo: { outpoint },
metadata: { title },
} = this.props;
const { deleteChecked, abandonClaimChecked } = this.state;
return (

View file

@ -2,7 +2,7 @@ import React from "react";
import { connect } from "react-redux";
import { doOpenModal } from "actions/app";
import * as settings from "constants/settings";
import { selectCurrentModal } from "selectors/app";
import { selectCurrentModal, selectModalProps } from "selectors/app";
import { selectCurrentPage } from "selectors/navigation";
import { selectCostForCurrentPageUri } from "selectors/cost_info";
import { makeSelectClientSetting } from "selectors/settings";
@ -14,6 +14,7 @@ const select = (state, props) => ({
balance: selectBalance(state),
showPageCost: selectCostForCurrentPageUri(state),
modal: selectCurrentModal(state),
modalProps: selectModalProps(state),
page: selectCurrentPage(state),
isWelcomeAcknowledged: makeSelectClientSetting(
settings.NEW_USER_ACKNOWLEDGED

View file

@ -8,6 +8,7 @@ import ModalWelcome from "modal/modalWelcome";
import ModalFirstReward from "modal/modalFirstReward";
import ModalRewardApprovalRequired from "modal/modalRewardApprovalRequired";
import ModalCreditIntro from "modal/modalCreditIntro";
import ModalRemoveFile from "modal/modalRemoveFile";
import ModalTransactionFailed from "modal/modalTransactionFailed";
import ModalInsufficientBalance from "modal/modalInsufficientBalance";
import ModalFileTimeout from "modal/modalFileTimeout";
@ -33,7 +34,7 @@ class ModalRouter extends React.PureComponent {
}
showTransitionModals(props) {
const { modal, openModal, page } = props;
const { modal, modalProps, openModal, page } = props;
if (modal) {
return;
@ -100,37 +101,37 @@ class ModalRouter extends React.PureComponent {
}
render() {
const { modal } = this.props;
const { modal, modalProps } = this.props;
switch (modal) {
case modals.UPGRADE:
return <ModalUpgrade />;
return <ModalUpgrade {...modalProps} />;
case modals.DOWNLOADING:
return <ModalDownloading />;
return <ModalDownloading {...modalProps} />;
case modals.ERROR:
return <ModalError />;
return <ModalError {...modalProps} />;
case modals.FILE_TIMEOUT:
return <ModalFileTimeout />;
return <ModalFileTimeout {...modalProps} />;
case modals.INSUFFICIENT_CREDITS:
return <ModalInsufficientCredits />;
return <ModalInsufficientCredits {...modalProps} />;
case modals.WELCOME:
return <ModalWelcome />;
return <ModalWelcome {...modalProps} />;
case modals.FIRST_REWARD:
return <ModalFirstReward />;
return <ModalFirstReward {...modalProps} />;
case modals.AUTHENTICATION_FAILURE:
return <ModalAuthFailure />;
return <ModalAuthFailure {...modalProps} />;
case modals.CREDIT_INTRO:
return <ModalCreditIntro />;
return <ModalCreditIntro {...modalProps} />;
case modals.TRANSACTION_FAILED:
return <ModalTransactionFailed />;
return <ModalTransactionFailed {...modalProps} />;
case modals.INSUFFICIENT_BALANCE:
return <ModalInsufficientBalance />;
return <ModalInsufficientBalance {...modalProps} />;
case modals.REWARD_APPROVAL_REQUIRED:
return <ModalRewardApprovalRequired />;
return <ModalRewardApprovalRequired {...modalProps} />;
case modals.CONFIRM_FILE_REMOVE:
return <ModalRemoveFile />;
return <ModalRemoveFile {...modalProps} />;
case modals.AFFIRM_PURCHASE:
return <ModalAffirmPurchase />;
return <ModalAffirmPurchase {...modalProps} />;
default:
return null;
}

View file

@ -14,22 +14,16 @@ import { doNavigate } from "actions/navigation";
import { makeSelectTotalPagesForChannel } from "selectors/content";
import ChannelPage from "./view";
const makeSelect = () => {
const selectClaim = makeSelectClaimForUri(),
selectClaimsInChannel = makeSelectClaimsInChannelForCurrentPage(),
selectFetchingChannelClaims = makeSelectFetchingChannelClaims(),
selectTotalPagesForChannel = makeSelectTotalPagesForChannel();
const select = (state, props) => ({
claim: selectClaim(state, props),
claimsInChannel: selectClaimsInChannel(state, props),
fetching: selectFetchingChannelClaims(state, props),
totalPages: selectTotalPagesForChannel(state, props),
params: selectCurrentParams(state),
});
return select;
};
const select = (state, props) => ({
claim: makeSelectClaimForUri(props.uri)(state),
claimsInChannel: makeSelectClaimsInChannelForCurrentPage(
props.uri,
props.page
)(state),
fetching: makeSelectFetchingChannelClaims(props.uri)(state),
params: selectCurrentParams(state),
totalPages: makeSelectTotalPagesForChannel(props.uri)(state),
});
const perform = dispatch => ({
fetchClaims: (uri, page) => dispatch(doFetchClaimsByChannel(uri, page)),
@ -37,4 +31,4 @@ const perform = dispatch => ({
navigate: (path, params) => dispatch(doNavigate(path, params)),
});
export default connect(makeSelect, perform)(ChannelPage);
export default connect(select, perform)(ChannelPage);

View file

@ -7,20 +7,19 @@ import ReactPaginate from "react-paginate";
class ChannelPage extends React.PureComponent {
componentDidMount() {
const { uri, params, fetchClaims, fetchClaimCount } = this.props;
const { uri, page, fetchClaims, fetchClaimCount } = this.props;
fetchClaims(uri, params.page || 1);
fetchClaims(uri, page || 1);
fetchClaimCount(uri);
}
componentWillReceiveProps(nextProps) {
const { params, fetching, fetchClaims, fetchClaimCount } = this.props;
const nextParams = nextProps.params;
const { page, uri, fetching, fetchClaims, fetchClaimCount } = this.props;
if (fetching !== nextParams.page && params.page !== nextParams.page) {
fetchClaims(nextProps.uri, nextParams.page);
if (fetching !== nextProps.page && page !== nextProps.page) {
fetchClaims(nextProps.uri, nextProps.page);
}
if (nextProps.uri != this.props.uri) {
if (nextProps.uri != uri) {
fetchClaimCount(uri);
}
}
@ -38,10 +37,9 @@ class ChannelPage extends React.PureComponent {
claimsInChannel,
claim,
uri,
params,
page,
totalPages,
} = this.props;
const { page } = params;
let contentList;
if (claimsInChannel === undefined) {

View file

@ -14,25 +14,15 @@ import { makeSelectCostInfoForUri } from "selectors/cost_info";
import { selectShowNsfw } from "selectors/settings";
import FilePage from "./view";
const makeSelect = () => {
const selectClaim = makeSelectClaimForUri(),
selectContentType = makeSelectContentTypeForUri(),
selectFileInfo = makeSelectFileInfoForUri(),
selectCostInfo = makeSelectCostInfoForUri(),
selectMetadata = makeSelectMetadataForUri();
const select = (state, props) => ({
claim: selectClaim(state, props),
contentType: selectContentType(state, props),
costInfo: selectCostInfo(state, props),
metadata: selectMetadata(state, props),
obscureNsfw: !selectShowNsfw(state),
fileInfo: selectFileInfo(state, props),
rewardedContentClaimIds: selectRewardContentClaimIds(state, props),
});
return select;
};
const select = (state, props) => ({
claim: makeSelectClaimForUri(props.uri)(state),
contentType: makeSelectContentTypeForUri(props.uri)(state),
costInfo: makeSelectCostInfoForUri(props.uri)(state),
metadata: makeSelectMetadataForUri(props.uri)(state),
obscureNsfw: !selectShowNsfw(state),
fileInfo: makeSelectFileInfoForUri(props.uri)(state),
rewardedContentClaimIds: selectRewardContentClaimIds(state, props),
});
const perform = dispatch => ({
navigate: (path, params) => dispatch(doNavigate(path, params)),
@ -40,4 +30,4 @@ const perform = dispatch => ({
fetchCostInfo: uri => dispatch(doFetchCostInfoForUri(uri)),
});
export default connect(makeSelect, perform)(FilePage);
export default connect(select, perform)(FilePage);

View file

@ -2,23 +2,16 @@ import React from "react";
import { connect } from "react-redux";
import { doResolveUri } from "actions/content";
import { makeSelectClaimForUri } from "selectors/claims";
import { makeSelectIsResolvingForUri } from "selectors/content";
import { makeSelectIsUriResolving } from "selectors/content";
import ShowPage from "./view";
const makeSelect = () => {
const selectClaim = makeSelectClaimForUri(),
selectIsResolving = makeSelectIsResolvingForUri();
const select = (state, props) => ({
claim: selectClaim(state, props.params),
isResolvingUri: selectIsResolving(state, props.params),
});
return select;
};
const select = (state, props) => ({
claim: makeSelectClaimForUri(props.uri)(state),
isResolvingUri: makeSelectIsUriResolving(props.uri)(state),
});
const perform = dispatch => ({
resolveUri: uri => dispatch(doResolveUri(uri)),
});
export default connect(makeSelect, perform)(ShowPage);
export default connect(select, perform)(ShowPage);

View file

@ -6,15 +6,13 @@ import FilePage from "page/file";
class ShowPage extends React.PureComponent {
componentWillMount() {
const { isResolvingUri, resolveUri, params } = this.props;
const { uri } = params;
const { isResolvingUri, resolveUri, uri } = this.props;
if (!isResolvingUri) resolveUri(uri);
}
componentWillReceiveProps(nextProps) {
const { isResolvingUri, resolveUri, claim, params } = nextProps;
const { uri } = params;
const { isResolvingUri, resolveUri, claim, uri } = nextProps;
if (!isResolvingUri && claim === undefined && uri) {
resolveUri(uri);
@ -22,8 +20,7 @@ class ShowPage extends React.PureComponent {
}
render() {
const { claim, params, isResolvingUri } = this.props;
const { uri } = params;
const { claim, isResolvingUri, uri } = this.props;
let innerContent = "";

View file

@ -8,6 +8,8 @@ const win = remote.BrowserWindow.getFocusedWindow();
const reducers = {};
const defaultState = {
isLoaded: false,
modal: null,
modalProps: {},
platform: process.platform,
upgradeSkipped: sessionStorage.getItem("upgradeSkipped"),
daemonVersionMatched: null,
@ -76,14 +78,14 @@ reducers[types.UPDATE_VERSION] = function(state, action) {
reducers[types.OPEN_MODAL] = function(state, action) {
return Object.assign({}, state, {
modal: action.data.modal,
modalExtraContent: action.data.extraContent,
modalProps: action.data.modalProps || {},
});
};
reducers[types.CLOSE_MODAL] = function(state, action) {
return Object.assign({}, state, {
modal: undefined,
modalExtraContent: undefined,
modalProps: {},
});
};

View file

@ -71,9 +71,9 @@ export const selectUpgradeDownloadItem = createSelector(
state => state.downloadItem
);
export const selectModalExtraContent = createSelector(
export const selectModalProps = createSelector(
_selectState,
state => state.modalExtraContent
state => state.modalProps
);
export const selectDaemonReady = createSelector(

View file

@ -7,14 +7,10 @@ export const selectAvailabilityByUri = createSelector(
state => state.byUri || {}
);
const selectAvailabilityForUri = (state, props) => {
return selectAvailabilityByUri(state)[props.uri];
};
export const makeSelectIsAvailableForUri = () => {
export const makeSelectIsAvailableForUri = uri => {
return createSelector(
selectAvailabilityForUri,
availability => (availability === undefined ? undefined : availability > 0)
selectAvailabilityByUri,
byUri => (!byUri || byUri[uri] === undefined ? undefined : byUri[uri] > 0)
);
};
@ -23,10 +19,9 @@ export const selectFetchingAvailability = createSelector(
state => state.fetching || {}
);
const selectFetchingAvailabilityForUri = (state, props) => {
return selectFetchingAvailability(state)[props.uri];
};
export const makeSelectFetchingAvailabilityForUri = () => {
return createSelector(selectFetchingAvailabilityForUri, fetching => fetching);
export const makeSelectFetchingAvailabilityForUri = uri => {
return createSelector(
selectFetchingAvailability,
byUri => byUri && byUri[uri]
);
};

View file

@ -40,24 +40,24 @@ export const selectAllClaimsByChannel = createSelector(
state => state.claimsByChannel || {}
);
const selectClaimForUri = (state, props) => {
const uri = lbryuri.normalize(props.uri);
return selectClaimsByUri(state)[uri];
export const makeSelectClaimForUri = uri => {
return createSelector(
selectClaimsByUri,
claims => claims && claims[lbryuri.normalize(uri)]
);
};
export const makeSelectClaimForUri = () => {
return createSelector(selectClaimForUri, claim => claim);
};
const selectClaimForUriIsMine = (state, props) => {
const uri = lbryuri.normalize(props.uri);
const claim = selectClaimsByUri(state)[uri];
const myClaims = selectMyClaimsRaw(state);
return myClaims && myClaims.has(claim.claim_id);
};
export const makeSelectClaimForUriIsMine = () => {
return createSelector(selectClaimForUriIsMine, isMine => isMine);
export const makeSelectClaimIsMine = rawUri => {
const uri = lbryuri.normalize(rawUri);
return createSelector(
selectClaimsByUri,
selectMyClaimsRaw,
(claims, myClaims) =>
claims &&
claims[uri] &&
claims[uri].claim_id &&
myClaims.has(claims[uri].claim_id)
);
};
export const selectAllFetchingChannelClaims = createSelector(
@ -65,86 +65,46 @@ export const selectAllFetchingChannelClaims = createSelector(
state => state.fetchingChannelClaims || {}
);
const selectFetchingChannelClaims = (state, props) => {
const allFetchingChannelClaims = selectAllFetchingChannelClaims(state);
return allFetchingChannelClaims[props.uri];
};
export const makeSelectFetchingChannelClaims = (state, props) => {
return createSelector(selectFetchingChannelClaims, fetching => fetching);
};
export const selectClaimsInChannelForUri = (state, props) => {
const byId = selectClaimsById(state);
const byChannel = selectAllClaimsByChannel(state)[props.uri] || {};
const claimIds = byChannel["all"];
if (!claimIds) return claimIds;
const claims = [];
claimIds.forEach(claimId => claims.push(byId[claimId]));
return claims;
};
export const makeSelectClaimsInChannelForUri = () => {
return createSelector(selectClaimsInChannelForUri, claims => claims);
};
export const selectClaimsInChannelForCurrentPage = (state, props) => {
const byId = selectClaimsById(state);
const byChannel = selectAllClaimsByChannel(state)[props.uri] || {};
const params = selectCurrentParams(state);
const page = params && params.page ? params.page : 1;
const claimIds = byChannel[page];
if (!claimIds) return claimIds;
const claims = [];
claimIds.forEach(claimId => claims.push(byId[claimId]));
return claims;
};
export const makeSelectClaimsInChannelForCurrentPage = () => {
return createSelector(selectClaimsInChannelForCurrentPage, claims => claims);
};
const selectMetadataForUri = (state, props) => {
const claim = selectClaimForUri(state, props);
const metadata =
claim && claim.value && claim.value.stream && claim.value.stream.metadata;
const value = metadata ? metadata : claim === undefined ? undefined : null;
return value;
};
export const makeSelectMetadataForUri = () => {
return createSelector(selectMetadataForUri, metadata => metadata);
};
const selectSourceForUri = (state, props) => {
const claim = selectClaimForUri(state, props);
const source =
claim && claim.value && claim.value.stream && claim.value.stream.source;
return source ? source : claim === undefined ? undefined : null;
};
export const makeSelectSourceForUri = () => {
return createSelector(selectSourceForUri, source => source);
};
export const makeSelectContentTypeForUri = () => {
return createSelector(
selectSourceForUri,
source => (source ? source.contentType : source)
export const makeSelectFetchingChannelClaims = uri => {
createSelector(
selectAllFetchingChannelClaims,
fetching => fetching && fetching[uri]
);
};
export const makeSelectClaimsInChannelForCurrentPage = (uri, page = 1) => {
return createSelector(
selectClaimsById,
selectAllClaimsByChannel,
(byId, allClaims) => {
const byChannel = allClaims[uri] || {};
const claimIds = byChannel[page];
if (!claimIds) return claimIds;
return claimIds.map(claimId => byId[claimId]);
}
);
};
export const makeSelectMetadataForUri = uri => {
return createSelector(makeSelectClaimForUri(uri), claim => {
const metadata =
claim && claim.value && claim.value.stream && claim.value.stream.metadata;
const value = metadata ? metadata : claim === undefined ? undefined : null;
return value;
});
};
export const makeSelectContentTypeForUri = uri => {
return createSelector(makeSelectClaimForUri(uri), claim => {
const source =
claim && claim.value && claim.value.stream && claim.value.stream.source;
return source ? source.contentType : undefined;
});
};
export const selectIsFetchingClaimListMine = createSelector(
_selectState,
state => !!state.isFetchingClaimListMine

View file

@ -17,12 +17,11 @@ export const selectResolvingUris = createSelector(
state => state.resolvingUris || []
);
const selectResolvingUri = (state, props) => {
return selectResolvingUris(state).indexOf(props.uri) != -1;
};
export const makeSelectIsResolvingForUri = () => {
return createSelector(selectResolvingUri, resolving => resolving);
export const makeSelectIsUriResolving = uri => {
return createSelector(
selectResolvingUris,
resolvingUris => resolvingUris && resolvingUris.indexOf(uri) != -1
);
};
export const selectChannelPages = createSelector(
@ -30,12 +29,8 @@ export const selectChannelPages = createSelector(
state => state.channelPages || {}
);
const selectTotalPagesForChannel = (state, props) => {
return selectChannelPages(state)[props.uri];
};
export const makeSelectTotalPagesForChannel = () => {
return createSelector(selectTotalPagesForChannel, totalPages => totalPages);
export const makeSelectTotalPagesForChannel = uri => {
return createSelector(selectChannelPages, byUri => byUri && byUri[uri]);
};
export const selectRewardContentClaimIds = createSelector(

View file

@ -8,12 +8,11 @@ export const selectAllCostInfoByUri = createSelector(
state => state.byUri || {}
);
export const selectCostInfoForUri = (state, props) => {
return selectAllCostInfoByUri(state)[props.uri];
};
export const makeSelectCostInfoForUri = () => {
return createSelector(selectCostInfoForUri, costInfo => costInfo);
export const makeSelectCostInfoForUri = uri => {
return createSelector(
selectAllCostInfoByUri,
costInfos => costInfos && costInfos[uri]
);
};
export const selectCostForCurrentPageUri = createSelector(
@ -28,10 +27,9 @@ export const selectFetchingCostInfo = createSelector(
state => state.fetching || {}
);
const selectFetchingCostInfoForUri = (state, props) => {
return selectFetchingCostInfo(state)[props.uri];
};
export const makeSelectFetchingCostInfoForUri = () => {
return createSelector(selectFetchingCostInfoForUri, fetching => !!fetching);
export const makeSelectFetchingCostInfoForUri = uri => {
return createSelector(
selectFetchingCostInfo,
fetchingByUri => fetchingByUri && fetchingByUri[uri]
);
};

View file

@ -26,17 +26,17 @@ export const selectIsFetchingFileListDownloadedOrPublished = createSelector(
isFetchingFileList || isFetchingClaimListMine
);
export const selectFileInfoForUri = (state, props) => {
const claims = selectClaimsByUri(state),
claim = claims[props.uri],
byOutpoint = selectFileInfosByOutpoint(state),
outpoint = claim ? `${claim.txid}:${claim.nout}` : undefined;
export const makeSelectFileInfoForUri = uri => {
return createSelector(
selectClaimsByUri,
selectFileInfosByOutpoint,
(claims, byOutpoint) => {
const claim = claims[uri],
outpoint = claim ? `${claim.txid}:${claim.nout}` : undefined;
return outpoint ? byOutpoint[outpoint] : undefined;
};
export const makeSelectFileInfoForUri = () => {
return createSelector(selectFileInfoForUri, fileInfo => fileInfo);
return outpoint ? byOutpoint[outpoint] : undefined;
}
);
};
export const selectDownloadingByOutpoint = createSelector(
@ -44,19 +44,14 @@ export const selectDownloadingByOutpoint = createSelector(
state => state.downloadingByOutpoint || {}
);
const selectDownloadingForUri = (state, props) => {
const byOutpoint = selectDownloadingByOutpoint(state);
const fileInfo = selectFileInfoForUri(state, props);
if (!fileInfo) return false;
return byOutpoint[fileInfo.outpoint];
};
export const makeSelectDownloadingForUri = () => {
export const makeSelectDownloadingForUri = uri => {
return createSelector(
selectDownloadingForUri,
downloadingForUri => !!downloadingForUri
selectDownloadingByOutpoint,
makeSelectFileInfoForUri(uri),
(byOutpoint, fileInfo) => {
if (!fileInfo) return false;
return byOutpoint[fileInfo.outpoint];
}
);
};
@ -65,13 +60,8 @@ export const selectUrisLoading = createSelector(
state => state.urisLoading || {}
);
const selectLoadingForUri = (state, props) => {
const byUri = selectUrisLoading(state);
return byUri[props.uri];
};
export const makeSelectLoadingForUri = () => {
return createSelector(selectLoadingForUri, loading => !!loading);
export const makeSelectLoadingForUri = uri => {
return createSelector(selectUrisLoading, byUri => byUri && byUri[uri]);
};
export const selectFileInfosPendingPublish = createSelector(