update: move to lbry-redux
This commit is contained in:
parent
fae65729de
commit
eaa11679e7
118 changed files with 445 additions and 2597 deletions
|
@ -48,6 +48,7 @@
|
||||||
"find-process": "^1.1.0",
|
"find-process": "^1.1.0",
|
||||||
"formik": "^0.10.4",
|
"formik": "^0.10.4",
|
||||||
"keytar": "^4.2.1",
|
"keytar": "^4.2.1",
|
||||||
|
"lbry-redux": "lbryio/lbry-redux",
|
||||||
"localforage": "^1.7.1",
|
"localforage": "^1.7.1",
|
||||||
"mixpanel-browser": "^2.17.1",
|
"mixpanel-browser": "^2.17.1",
|
||||||
"moment": "^2.22.0",
|
"moment": "^2.22.0",
|
||||||
|
@ -60,7 +61,7 @@
|
||||||
"react-modal": "^3.1.7",
|
"react-modal": "^3.1.7",
|
||||||
"react-paginate": "^5.2.1",
|
"react-paginate": "^5.2.1",
|
||||||
"react-redux": "^5.0.3",
|
"react-redux": "^5.0.3",
|
||||||
"react-simplemde-editor": "^3.6.11",
|
"react-simplemde-editor": "3.6.11",
|
||||||
"react-transition-group": "1.x",
|
"react-transition-group": "1.x",
|
||||||
"redux": "^3.6.0",
|
"redux": "^3.6.0",
|
||||||
"redux-logger": "^3.0.1",
|
"redux-logger": "^3.0.1",
|
||||||
|
|
|
@ -1,12 +1,8 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import {
|
import { selectPageTitle, selectHistoryIndex, selectActiveHistoryEntry } from 'lbry-redux';
|
||||||
selectPageTitle,
|
import { doRecordScroll } from 'redux/actions/navigation';
|
||||||
selectHistoryIndex,
|
|
||||||
selectActiveHistoryEntry,
|
|
||||||
} from 'redux/selectors/navigation';
|
|
||||||
import { selectUser } from 'redux/selectors/user';
|
import { selectUser } from 'redux/selectors/user';
|
||||||
import { doAlertError } from 'redux/actions/app';
|
import { doAlertError } from 'redux/actions/app';
|
||||||
import { doRecordScroll } from 'redux/actions/navigation';
|
|
||||||
import App from './view';
|
import App from './view';
|
||||||
|
|
||||||
const select = state => ({
|
const select = state => ({
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import React from 'react';
|
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { doNavigate } from 'redux/actions/navigation';
|
import { doNavigate } from 'redux/actions/navigation';
|
||||||
import Button from './view';
|
import Button from './view';
|
||||||
|
|
|
@ -22,9 +22,7 @@ const autoThumbColors = [
|
||||||
];
|
];
|
||||||
|
|
||||||
class CardMedia extends React.PureComponent<Props> {
|
class CardMedia extends React.PureComponent<Props> {
|
||||||
getAutoThumbClass = () => {
|
getAutoThumbClass = () => autoThumbColors[Math.floor(Math.random() * autoThumbColors.length)];
|
||||||
return autoThumbColors[Math.floor(Math.random() * autoThumbColors.length)];
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { thumbnail, nsfw } = this.props;
|
const { thumbnail, nsfw } = this.props;
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
import React from 'react';
|
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { makeSelectClaimForUri } from 'redux/selectors/claims';
|
import { doResolveUri, makeSelectClaimForUri, makeSelectIsUriResolving } from 'lbry-redux';
|
||||||
import { doNavigate } from 'redux/actions/navigation';
|
import { doNavigate } from 'redux/actions/navigation';
|
||||||
import { doResolveUri } from 'redux/actions/content';
|
|
||||||
import { makeSelectTotalItemsForChannel } from 'redux/selectors/content';
|
import { makeSelectTotalItemsForChannel } from 'redux/selectors/content';
|
||||||
import { makeSelectIsUriResolving } from 'redux/selectors/content';
|
|
||||||
import ChannelTile from './view';
|
import ChannelTile from './view';
|
||||||
|
|
||||||
const select = (state, props) => ({
|
const select = (state, props) => ({
|
||||||
|
|
|
@ -5,12 +5,10 @@ type Props = {
|
||||||
message: ?string,
|
message: ?string,
|
||||||
};
|
};
|
||||||
|
|
||||||
const BusyIndicator = (props: Props) => {
|
const BusyIndicator = (props: Props) => (
|
||||||
return (
|
|
||||||
<span className="busy-indicator">
|
<span className="busy-indicator">
|
||||||
{props.message} <span className="busy-indicator__loader" />
|
{props.message} <span className="busy-indicator__loader" />
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
};
|
|
||||||
|
|
||||||
export default BusyIndicator;
|
export default BusyIndicator;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// @flow
|
// @flow
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { normalizeURI } from 'lbryURI';
|
import { normalizeURI } from 'lbry-redux';
|
||||||
import ToolTip from 'component/common/tooltip';
|
import ToolTip from 'component/common/tooltip';
|
||||||
import FileCard from 'component/fileCard';
|
import FileCard from 'component/fileCard';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
|
|
|
@ -6,12 +6,10 @@ type Props = {
|
||||||
children: React.Node,
|
children: React.Node,
|
||||||
};
|
};
|
||||||
|
|
||||||
const TruncatedText = (props: Props) => {
|
const TruncatedText = (props: Props) => (
|
||||||
return (
|
|
||||||
<span className="truncated-text" style={{ WebkitLineClamp: props.lines }}>
|
<span className="truncated-text" style={{ WebkitLineClamp: props.lines }}>
|
||||||
{props.children}
|
{props.children}
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
};
|
|
||||||
|
|
||||||
export default TruncatedText;
|
export default TruncatedText;
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
import React from 'react';
|
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { makeSelectBlockDate } from 'redux/selectors/wallet';
|
import { doFetchBlock, makeSelectBlockDate } from 'lbry-redux';
|
||||||
import { doFetchBlock } from 'redux/actions/wallet';
|
|
||||||
import DateTime from './view';
|
import DateTime from './view';
|
||||||
|
|
||||||
const select = (state, props) => ({
|
const select = (state, props) => ({
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
import React from 'react';
|
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { makeSelectFileInfoForUri } from 'redux/selectors/file_info';
|
import {
|
||||||
import { makeSelectCostInfoForUri } from 'redux/selectors/cost_info';
|
doOpenModal,
|
||||||
import { doOpenModal } from 'redux/actions/app';
|
makeSelectCostInfoForUri,
|
||||||
import { makeSelectClaimIsMine } from 'redux/selectors/claims';
|
makeSelectFileInfoForUri,
|
||||||
|
makeSelectClaimIsMine,
|
||||||
|
} from 'lbry-redux';
|
||||||
import FileActions from './view';
|
import FileActions from './view';
|
||||||
|
|
||||||
const select = (state, props) => ({
|
const select = (state, props) => ({
|
||||||
|
|
|
@ -1,10 +1,14 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
import {
|
||||||
|
doResolveUri,
|
||||||
|
makeSelectClaimForUri,
|
||||||
|
makeSelectMetadataForUri,
|
||||||
|
makeSelectFileInfoForUri,
|
||||||
|
makeSelectIsUriResolving,
|
||||||
|
} from 'lbry-redux';
|
||||||
import { doNavigate } from 'redux/actions/navigation';
|
import { doNavigate } from 'redux/actions/navigation';
|
||||||
import { doResolveUri } from 'redux/actions/content';
|
import { selectRewardContentClaimIds } from 'redux/selectors/content';
|
||||||
import { selectShowNsfw } from 'redux/selectors/settings';
|
import { selectShowNsfw } from 'redux/selectors/settings';
|
||||||
import { makeSelectClaimForUri, makeSelectMetadataForUri } from 'redux/selectors/claims';
|
|
||||||
import { makeSelectFileInfoForUri } from 'redux/selectors/file_info';
|
|
||||||
import { makeSelectIsUriResolving, selectRewardContentClaimIds } from 'redux/selectors/content';
|
|
||||||
import { selectPendingPublish } from 'redux/selectors/publish';
|
import { selectPendingPublish } from 'redux/selectors/publish';
|
||||||
import FileCard from './view';
|
import FileCard from './view';
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { normalizeURI } from 'lbryURI';
|
import { normalizeURI } from 'lbry-redux';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
import CardMedia from 'component/cardMedia';
|
import CardMedia from 'component/cardMedia';
|
||||||
import TruncatedText from 'component/common/truncated-text';
|
import TruncatedText from 'component/common/truncated-text';
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
import React from 'react';
|
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import {
|
import {
|
||||||
makeSelectClaimForUri,
|
makeSelectClaimForUri,
|
||||||
makeSelectContentTypeForUri,
|
makeSelectContentTypeForUri,
|
||||||
makeSelectMetadataForUri,
|
makeSelectMetadataForUri,
|
||||||
} from 'redux/selectors/claims';
|
makeSelectFileInfoForUri,
|
||||||
|
} from 'lbry-redux';
|
||||||
|
import { doOpenFileInFolder } from 'redux/actions/file';
|
||||||
import FileDetails from './view';
|
import FileDetails from './view';
|
||||||
import { doOpenFileInFolder } from 'redux/actions/file_info';
|
|
||||||
import { makeSelectFileInfoForUri } from 'redux/selectors/file_info';
|
|
||||||
|
|
||||||
const select = (state, props) => ({
|
const select = (state, props) => ({
|
||||||
claim: makeSelectClaimForUri(props.uri)(state),
|
claim: makeSelectClaimForUri(props.uri)(state),
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import ReactMarkdown from 'react-markdown';
|
import ReactMarkdown from 'react-markdown';
|
||||||
import lbry from 'lbry';
|
import { Lbry } from 'lbry-redux';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ const FileDetails = (props: Props) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const { description, language, license } = metadata;
|
const { description, language, license } = metadata;
|
||||||
const mediaType = lbry.getMediaType(contentType);
|
const mediaType = Lbry.getMediaType(contentType);
|
||||||
|
|
||||||
const downloadPath = fileInfo ? path.normalize(fileInfo.download_path) : null;
|
const downloadPath = fileInfo ? path.normalize(fileInfo.download_path) : null;
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
import React from 'react';
|
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import {
|
import {
|
||||||
makeSelectFileInfoForUri,
|
makeSelectFileInfoForUri,
|
||||||
makeSelectDownloadingForUri,
|
makeSelectDownloadingForUri,
|
||||||
makeSelectLoadingForUri,
|
makeSelectLoadingForUri,
|
||||||
} from 'redux/selectors/file_info';
|
makeSelectCostInfoForUri,
|
||||||
import { makeSelectCostInfoForUri } from 'redux/selectors/cost_info';
|
} from 'lbry-redux';
|
||||||
import { doFetchAvailability } from 'redux/actions/availability';
|
import { doFetchAvailability } from 'redux/actions/availability';
|
||||||
import { doOpenFileInShell } from 'redux/actions/file_info';
|
import { doOpenFileInShell } from 'redux/actions/file';
|
||||||
import { doPurchaseUri, doStartDownload } from 'redux/actions/content';
|
import { doPurchaseUri, doStartDownload } from 'redux/actions/content';
|
||||||
import { doPause } from 'redux/actions/media';
|
import { doPause } from 'redux/actions/media';
|
||||||
import FileDownloadLink from './view';
|
import FileDownloadLink from './view';
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import FileList from './view';
|
import FileList from './view';
|
||||||
import { selectClaimsById } from 'redux/selectors/claims';
|
import { selectClaimsById } from 'lbry-redux';
|
||||||
|
|
||||||
const select = state => ({
|
const select = state => ({
|
||||||
claimsById: selectClaimsById(state),
|
claimsById: selectClaimsById(state),
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { buildURI } from 'lbryURI';
|
import { buildURI } from 'lbry-redux';
|
||||||
import { FormField } from 'component/common/form';
|
import { FormField } from 'component/common/form';
|
||||||
import FileCard from 'component/fileCard';
|
import FileCard from 'component/fileCard';
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { doSearch } from 'redux/actions/search';
|
import {
|
||||||
import { makeSelectSearchUris, selectIsSearching } from 'redux/selectors/search';
|
doSearch,
|
||||||
import { selectSearchDownloadUris } from 'redux/selectors/file_info';
|
makeSelectSearchUris,
|
||||||
|
selectIsSearching,
|
||||||
|
selectSearchDownloadUris,
|
||||||
|
} from 'lbry-redux';
|
||||||
import FileListSearch from './view';
|
import FileListSearch from './view';
|
||||||
|
|
||||||
const select = (state, props) => ({
|
const select = (state, props) => ({
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import FileTile from 'component/fileTile';
|
import FileTile from 'component/fileTile';
|
||||||
import ChannelTile from 'component/channelTile';
|
import ChannelTile from 'component/channelTile';
|
||||||
import { parseURI } from 'lbryURI';
|
import { parseURI } from 'lbry-redux';
|
||||||
import debounce from 'util/debounce';
|
import debounce from 'util/debounce';
|
||||||
|
|
||||||
const SEARCH_DEBOUNCE_TIME = 800;
|
const SEARCH_DEBOUNCE_TIME = 800;
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
import React from 'react';
|
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { doFetchCostInfoForUri } from 'redux/actions/cost_info';
|
|
||||||
import {
|
import {
|
||||||
|
doFetchCostInfoForUri,
|
||||||
makeSelectCostInfoForUri,
|
makeSelectCostInfoForUri,
|
||||||
makeSelectFetchingCostInfoForUri,
|
makeSelectFetchingCostInfoForUri,
|
||||||
} from 'redux/selectors/cost_info';
|
makeSelectClaimForUri,
|
||||||
import { makeSelectClaimForUri } from 'redux/selectors/claims';
|
} from 'lbry-redux';
|
||||||
import FilePrice from './view';
|
import FilePrice from './view';
|
||||||
|
|
||||||
const select = (state, props) => ({
|
const select = (state, props) => ({
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
import React from 'react';
|
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
import {
|
||||||
|
doResolveUri,
|
||||||
|
makeSelectClaimForUri,
|
||||||
|
makeSelectMetadataForUri,
|
||||||
|
makeSelectFileInfoForUri,
|
||||||
|
makeSelectIsUriResolving,
|
||||||
|
} from 'lbry-redux';
|
||||||
import { doNavigate } from 'redux/actions/navigation';
|
import { doNavigate } from 'redux/actions/navigation';
|
||||||
import { doResolveUri } from 'redux/actions/content';
|
|
||||||
import { makeSelectClaimForUri, makeSelectMetadataForUri } from 'redux/selectors/claims';
|
|
||||||
import { makeSelectFileInfoForUri } from 'redux/selectors/file_info';
|
|
||||||
import { selectShowNsfw } from 'redux/selectors/settings';
|
import { selectShowNsfw } from 'redux/selectors/settings';
|
||||||
import { makeSelectIsUriResolving, selectRewardContentClaimIds } from 'redux/selectors/content';
|
import { selectRewardContentClaimIds } from 'redux/selectors/content';
|
||||||
import FileTile from './view';
|
import FileTile from './view';
|
||||||
|
|
||||||
const select = (state, props) => ({
|
const select = (state, props) => ({
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import * as icons from 'constants/icons';
|
import * as icons from 'constants/icons';
|
||||||
import { normalizeURI, isURIClaimable, parseURI } from 'lbryURI';
|
import { normalizeURI, isURIClaimable, parseURI } from 'lbry-redux';
|
||||||
import CardMedia from 'component/cardMedia';
|
import CardMedia from 'component/cardMedia';
|
||||||
import TruncatedText from 'component/common/truncated-text';
|
import TruncatedText from 'component/common/truncated-text';
|
||||||
import FilePrice from 'component/filePrice';
|
import FilePrice from 'component/filePrice';
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { doDownloadUpgradeRequested } from 'redux/actions/app';
|
import { selectBalance } from 'lbry-redux';
|
||||||
|
import { formatCredits } from 'util/formatCredits';
|
||||||
import { doNavigate } from 'redux/actions/navigation';
|
import { doNavigate } from 'redux/actions/navigation';
|
||||||
import { selectIsUpgradeAvailable, selectAutoUpdateDownloaded } from 'redux/selectors/app';
|
import { selectIsUpgradeAvailable, selectAutoUpdateDownloaded } from 'redux/selectors/app';
|
||||||
import { selectBalance } from 'redux/selectors/wallet';
|
import { doDownloadUpgradeRequested } from 'redux/actions/app';
|
||||||
import { formatCredits } from 'util/formatCredits';
|
|
||||||
import Header from './view';
|
import Header from './view';
|
||||||
|
|
||||||
const select = state => ({
|
const select = state => ({
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import React from 'react';
|
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { doNavigate } from 'redux/actions/navigation';
|
import { doNavigate } from 'redux/actions/navigation';
|
||||||
import NsfwOverlay from './view';
|
import NsfwOverlay from './view';
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import {
|
import {
|
||||||
|
selectBalance,
|
||||||
selectPageTitle,
|
selectPageTitle,
|
||||||
selectIsBackDisabled,
|
selectIsBackDisabled,
|
||||||
selectIsForwardDisabled,
|
selectIsForwardDisabled,
|
||||||
selectNavLinks,
|
selectNavLinks,
|
||||||
} from 'redux/selectors/navigation';
|
} from 'lbry-redux';
|
||||||
import { doNavigate, doHistoryBack, doHistoryForward } from 'redux/actions/navigation';
|
import { doNavigate, doHistoryBack, doHistoryForward } from 'redux/actions/navigation';
|
||||||
import { doDownloadUpgrade } from 'redux/actions/app';
|
import { doDownloadUpgrade } from 'redux/actions/app';
|
||||||
import { selectIsUpgradeAvailable } from 'redux/selectors/app';
|
import { selectIsUpgradeAvailable } from 'redux/selectors/app';
|
||||||
import { formatCredits } from 'util/formatCredits';
|
import { formatCredits } from 'util/formatCredits';
|
||||||
import { selectBalance } from 'redux/selectors/wallet';
|
|
||||||
import Page from './view';
|
import Page from './view';
|
||||||
|
|
||||||
const select = state => ({
|
const select = state => ({
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react';
|
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
import { selectBalance } from 'lbry-redux';
|
||||||
import PublishForm from './view';
|
import PublishForm from './view';
|
||||||
|
|
||||||
export default connect(null, null)(PublishForm);
|
export default connect(null, null)(PublishForm);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { isNameValid, buildURI, regexInvalidURI } from 'lbryURI';
|
import { isNameValid, buildURI, regexInvalidURI } from 'lbry-redux';
|
||||||
import { Form, FormField, FormRow, FormFieldPrice, Submit } from 'component/common/form';
|
import { Form, FormField, FormRow, FormFieldPrice, Submit } from 'component/common/form';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
import ChannelSection from 'component/selectChannel';
|
import ChannelSection from 'component/selectChannel';
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import React from 'react';
|
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import {
|
import {
|
||||||
makeSelectClaimRewardError,
|
makeSelectClaimRewardError,
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import React from 'react';
|
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import Router from './view.jsx';
|
import { selectCurrentPage, selectCurrentParams } from 'lbry-redux';
|
||||||
import { selectCurrentPage, selectCurrentParams } from 'redux/selectors/navigation.js';
|
import Router from './view';
|
||||||
|
|
||||||
const select = state => ({
|
const select = state => ({
|
||||||
params: selectCurrentParams(state),
|
params: selectCurrentParams(state),
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import SelectChannel from './view';
|
import SelectChannel from './view';
|
||||||
import { selectMyChannelClaims, selectFetchingMyChannels } from 'redux/selectors/claims';
|
import { selectBalance, selectMyChannelClaims, selectFetchingMyChannels } from 'lbry-redux';
|
||||||
import { doFetchChannelListMine, doCreateChannel } from 'redux/actions/content';
|
import { doFetchChannelListMine, doCreateChannel } from 'redux/actions/content';
|
||||||
import { selectBalance } from 'redux/selectors/wallet';
|
|
||||||
|
|
||||||
const select = state => ({
|
const select = state => ({
|
||||||
channels: selectMyChannelClaims(state),
|
channels: selectMyChannelClaims(state),
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// @flow
|
// @flow
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { isNameValid } from 'lbryURI';
|
import { isNameValid } from 'lbry-redux';
|
||||||
import { FormRow, FormField } from 'component/common/form';
|
import { FormRow, FormField } from 'component/common/form';
|
||||||
import BusyIndicator from 'component/common/busy-indicator';
|
import BusyIndicator from 'component/common/busy-indicator';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
|
|
|
@ -6,8 +6,7 @@ import {
|
||||||
clearShapeShift,
|
clearShapeShift,
|
||||||
getActiveShift,
|
getActiveShift,
|
||||||
} from 'redux/actions/shape_shift';
|
} from 'redux/actions/shape_shift';
|
||||||
import { doShowSnackBar } from 'redux/actions/app';
|
import { doShowSnackBar, selectReceiveAddress } from 'lbry-redux';
|
||||||
import { selectReceiveAddress } from 'redux/selectors/wallet';
|
|
||||||
import { selectShapeShift } from 'redux/selectors/shape_shift';
|
import { selectShapeShift } from 'redux/selectors/shape_shift';
|
||||||
import ShapeShift from './view';
|
import ShapeShift from './view';
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,6 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { doNavigate, doHistoryBack, doHistoryForward } from 'redux/actions/navigation';
|
import { doNavigate, doHistoryBack, doHistoryForward } from 'redux/actions/navigation';
|
||||||
import {
|
import { selectIsBackDisabled, selectIsForwardDisabled, selectNavLinks } from 'lbry-redux';
|
||||||
selectIsBackDisabled,
|
|
||||||
selectIsForwardDisabled,
|
|
||||||
selectNavLinks,
|
|
||||||
} from 'redux/selectors/navigation';
|
|
||||||
import { selectNotifications } from 'redux/selectors/subscriptions';
|
import { selectNotifications } from 'redux/selectors/subscriptions';
|
||||||
import SideBar from './view';
|
import SideBar from './view';
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import lbry from 'lbry';
|
import { Lbry } from 'lbry-redux';
|
||||||
import LoadScreen from './internal/load-screen';
|
import LoadScreen from './internal/load-screen';
|
||||||
import ModalIncompatibleDaemon from 'modal/modalIncompatibleDaemon';
|
import ModalIncompatibleDaemon from 'modal/modalIncompatibleDaemon';
|
||||||
import ModalUpgrade from 'modal/modalUpgrade';
|
import ModalUpgrade from 'modal/modalUpgrade';
|
||||||
|
@ -31,7 +31,7 @@ export class SplashScreen extends React.PureComponent<Props, State> {
|
||||||
}
|
}
|
||||||
|
|
||||||
updateStatus() {
|
updateStatus() {
|
||||||
lbry.status().then(status => {
|
Lbry.status().then(status => {
|
||||||
this._updateStatusCallback(status);
|
this._updateStatusCallback(status);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ export class SplashScreen extends React.PureComponent<Props, State> {
|
||||||
isRunning: true,
|
isRunning: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
lbry.resolve({ uri: 'lbry://one' }).then(() => {
|
Lbry.resolve({ uri: 'lbry://one' }).then(() => {
|
||||||
// Only leave the load screen if the daemon version matched;
|
// Only leave the load screen if the daemon version matched;
|
||||||
// otherwise we'll notify the user at the end of the load screen.
|
// otherwise we'll notify the user at the end of the load screen.
|
||||||
|
|
||||||
|
@ -83,8 +83,7 @@ export class SplashScreen extends React.PureComponent<Props, State> {
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const { checkDaemonVersion } = this.props;
|
const { checkDaemonVersion } = this.props;
|
||||||
|
|
||||||
lbry
|
Lbry.connect()
|
||||||
.connect()
|
|
||||||
.then(checkDaemonVersion)
|
.then(checkDaemonVersion)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.updateStatus();
|
this.updateStatus();
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import { connect } from 'react-redux';
|
|
||||||
import { selectCurrentPage, selectHeaderLinks } from 'redux/selectors/navigation';
|
|
||||||
import { doNavigate } from 'redux/actions/navigation';
|
|
||||||
import { selectNotifications } from 'redux/selectors/subscriptions';
|
|
||||||
import SubHeader from './view';
|
|
||||||
|
|
||||||
const select = (state, props) => ({
|
|
||||||
currentPage: selectCurrentPage(state),
|
|
||||||
subLinks: selectHeaderLinks(state),
|
|
||||||
notifications: selectNotifications(state),
|
|
||||||
});
|
|
||||||
|
|
||||||
const perform = dispatch => ({
|
|
||||||
navigate: path => dispatch(doNavigate(path)),
|
|
||||||
});
|
|
||||||
|
|
||||||
export default connect(select, perform)(SubHeader);
|
|
|
@ -1,42 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import Link from 'component/link';
|
|
||||||
import classnames from 'classnames';
|
|
||||||
import * as NOTIFICATION_TYPES from 'constants/notification_types';
|
|
||||||
|
|
||||||
const SubHeader = props => {
|
|
||||||
const { subLinks, currentPage, navigate, fullWidth, smallMargin, notifications } = props;
|
|
||||||
|
|
||||||
const badges = Object.keys(notifications).reduce(
|
|
||||||
(acc, cur) => (notifications[cur].type === NOTIFICATION_TYPES.DOWNLOADING ? acc : acc + 1),
|
|
||||||
0
|
|
||||||
);
|
|
||||||
|
|
||||||
const links = [];
|
|
||||||
|
|
||||||
for (const link of Object.keys(subLinks)) {
|
|
||||||
links.push(
|
|
||||||
<Link
|
|
||||||
onClick={event => navigate(`/${link}`, event)}
|
|
||||||
key={link}
|
|
||||||
className={link == currentPage ? 'sub-header-selected' : 'sub-header-unselected'}
|
|
||||||
>
|
|
||||||
{subLinks[link] === 'Subscriptions' && badges
|
|
||||||
? `Subscriptions (${badges})`
|
|
||||||
: subLinks[link]}
|
|
||||||
</Link>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<nav
|
|
||||||
className={classnames('sub-header', {
|
|
||||||
'sub-header--full-width': fullWidth,
|
|
||||||
'sub-header--small-margin': smallMargin,
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
{links}
|
|
||||||
</nav>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default SubHeader;
|
|
|
@ -1,9 +1,7 @@
|
||||||
import React from 'react';
|
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { doNavigate } from 'redux/actions/navigation';
|
|
||||||
import { doOpenModal } from 'redux/actions/app';
|
|
||||||
import { selectClaimedRewardsByTransactionId } from 'redux/selectors/rewards';
|
import { selectClaimedRewardsByTransactionId } from 'redux/selectors/rewards';
|
||||||
import { selectAllMyClaimsByOutpoint } from 'redux/selectors/claims';
|
import { doNavigate } from 'redux/actions/navigation';
|
||||||
|
import { doOpenModal, selectAllMyClaimsByOutpoint } from 'lbry-redux';
|
||||||
import TransactionList from './view';
|
import TransactionList from './view';
|
||||||
|
|
||||||
const select = state => ({
|
const select = state => ({
|
||||||
|
|
|
@ -4,7 +4,7 @@ import ButtonTransaction from 'component/common/transaction-link';
|
||||||
import CreditAmount from 'component/common/credit-amount';
|
import CreditAmount from 'component/common/credit-amount';
|
||||||
import DateTime from 'component/dateTime';
|
import DateTime from 'component/dateTime';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
import { buildURI } from 'lbryURI';
|
import { buildURI } from 'lbry-redux';
|
||||||
import * as txnTypes from 'constants/transaction_types';
|
import * as txnTypes from 'constants/transaction_types';
|
||||||
import type { Transaction } from '../view';
|
import type { Transaction } from '../view';
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,10 @@
|
||||||
import React from 'react';
|
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { doFetchTransactions } from 'redux/actions/wallet';
|
|
||||||
import {
|
import {
|
||||||
selectBalance,
|
doFetchTransactions,
|
||||||
selectRecentTransactions,
|
selectRecentTransactions,
|
||||||
selectHasTransactions,
|
selectHasTransactions,
|
||||||
selectIsFetchingTransactions,
|
selectIsFetchingTransactions,
|
||||||
} from 'redux/selectors/wallet';
|
} from 'lbry-redux';
|
||||||
|
|
||||||
import TransactionListRecent from './view';
|
import TransactionListRecent from './view';
|
||||||
|
|
||||||
const select = state => ({
|
const select = state => ({
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
import React from 'react';
|
|
||||||
import { normalizeURI } from 'lbryURI';
|
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { doResolveUri } from 'redux/actions/content';
|
import {
|
||||||
import { makeSelectIsUriResolving } from 'redux/selectors/content';
|
normalizeURI,
|
||||||
import { makeSelectClaimForUri } from 'redux/selectors/claims';
|
doResolveUri,
|
||||||
|
makeSelectIsUriResolving,
|
||||||
|
makeSelectClaimForUri,
|
||||||
|
} from 'lbry-redux';
|
||||||
import UriIndicator from './view';
|
import UriIndicator from './view';
|
||||||
|
|
||||||
const select = (state, props) => ({
|
const select = (state, props) => ({
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// @flow
|
// @flow
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
import { buildURI } from 'lbryURI';
|
import { buildURI } from 'lbry-redux';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
// import Icon from 'component/common/icon';
|
// import Icon from 'component/common/icon';
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import React from 'react';
|
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { doNavigate } from 'redux/actions/navigation';
|
import { doNavigate } from 'redux/actions/navigation';
|
||||||
import { doUserIdentityVerify } from 'redux/actions/user';
|
import { doUserIdentityVerify } from 'redux/actions/user';
|
||||||
|
|
|
@ -1,21 +1,21 @@
|
||||||
import React from 'react';
|
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { doChangeVolume } from 'redux/actions/app';
|
import { doChangeVolume } from 'redux/actions/app';
|
||||||
import { selectVolume } from 'redux/selectors/app';
|
import { selectVolume } from 'redux/selectors/app';
|
||||||
import { doPlayUri, doSetPlayingUri } from 'redux/actions/content';
|
import { doPlayUri, doSetPlayingUri } from 'redux/actions/content';
|
||||||
import { doPlay, doPause, savePosition } from 'redux/actions/media';
|
import { doPlay, doPause, savePosition } from 'redux/actions/media';
|
||||||
import { makeSelectMetadataForUri, makeSelectContentTypeForUri } from 'redux/selectors/claims';
|
|
||||||
import {
|
import {
|
||||||
|
makeSelectMetadataForUri,
|
||||||
|
makeSelectContentTypeForUri,
|
||||||
|
makeSelectCostInfoForUri,
|
||||||
|
makeSelectClaimForUri,
|
||||||
makeSelectFileInfoForUri,
|
makeSelectFileInfoForUri,
|
||||||
makeSelectLoadingForUri,
|
makeSelectLoadingForUri,
|
||||||
makeSelectDownloadingForUri,
|
makeSelectDownloadingForUri,
|
||||||
} from 'redux/selectors/file_info';
|
} from 'lbry-redux';
|
||||||
import { makeSelectCostInfoForUri } from 'redux/selectors/cost_info';
|
|
||||||
import { selectShowNsfw } from 'redux/selectors/settings';
|
import { selectShowNsfw } from 'redux/selectors/settings';
|
||||||
import { selectMediaPaused, makeSelectMediaPositionForUri } from 'redux/selectors/media';
|
import { selectMediaPaused, makeSelectMediaPositionForUri } from 'redux/selectors/media';
|
||||||
import Video from './view';
|
|
||||||
import { selectPlayingUri } from 'redux/selectors/content';
|
import { selectPlayingUri } from 'redux/selectors/content';
|
||||||
import { makeSelectClaimForUri } from 'redux/selectors/claims';
|
import Video from './view';
|
||||||
|
|
||||||
const select = (state, props) => ({
|
const select = (state, props) => ({
|
||||||
claim: makeSelectClaimForUri(props.uri)(state),
|
claim: makeSelectClaimForUri(props.uri)(state),
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// @flow
|
// @flow
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import lbry from 'lbry';
|
import { Lbry } from 'lbry-redux';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import VideoPlayer from './internal/player';
|
import VideoPlayer from './internal/player';
|
||||||
import VideoPlayButton from './internal/play-button';
|
import VideoPlayButton from './internal/play-button';
|
||||||
|
@ -75,7 +75,7 @@ class Video extends React.PureComponent<Props> {
|
||||||
const isPlaying = playingUri === uri;
|
const isPlaying = playingUri === uri;
|
||||||
const isReadyToPlay = fileInfo && fileInfo.written_bytes > 0;
|
const isReadyToPlay = fileInfo && fileInfo.written_bytes > 0;
|
||||||
const shouldObscureNsfw = obscureNsfw && metadata && metadata.nsfw;
|
const shouldObscureNsfw = obscureNsfw && metadata && metadata.nsfw;
|
||||||
const mediaType = lbry.getMediaType(contentType, fileInfo && fileInfo.file_name);
|
const mediaType = Lbry.getMediaType(contentType, fileInfo && fileInfo.file_name);
|
||||||
|
|
||||||
let loadStatusMessage = '';
|
let loadStatusMessage = '';
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
import React from 'react';
|
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { doCheckAddressIsMine, doGetNewAddress } from 'redux/actions/wallet';
|
import {
|
||||||
import { selectReceiveAddress, selectGettingNewAddress } from 'redux/selectors/wallet';
|
doCheckAddressIsMine,
|
||||||
|
doGetNewAddress,
|
||||||
|
selectReceiveAddress,
|
||||||
|
selectGettingNewAddress,
|
||||||
|
} from 'lbry-redux';
|
||||||
import WalletAddress from './view';
|
import WalletAddress from './view';
|
||||||
|
|
||||||
const select = state => ({
|
const select = state => ({
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import React from 'react';
|
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { selectBalance } from 'redux/selectors/wallet';
|
import { selectBalance } from 'lbry-redux';
|
||||||
import WalletBalance from './view';
|
import WalletBalance from './view';
|
||||||
|
|
||||||
const select = state => ({
|
const select = state => ({
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { doSendDraftTransaction } from 'redux/actions/wallet';
|
import { doSendDraftTransaction, selectBalance } from 'lbry-redux';
|
||||||
import { selectBalance } from 'redux/selectors/wallet';
|
|
||||||
import WalletSend from './view';
|
import WalletSend from './view';
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { doSendSupport } from 'redux/actions/wallet';
|
import {
|
||||||
import { makeSelectTitleForUri, makeSelectClaimForUri } from 'redux/selectors/claims';
|
doSendSupport,
|
||||||
import { selectIsSendingSupport } from 'redux/selectors/wallet';
|
makeSelectTitleForUri,
|
||||||
|
makeSelectClaimForUri,
|
||||||
|
selectIsSendingSupport,
|
||||||
|
} from 'lbry-redux';
|
||||||
import WalletSendTip from './view';
|
import WalletSendTip from './view';
|
||||||
|
|
||||||
const select = (state, props) => ({
|
const select = (state, props) => ({
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
import * as MODALS from 'constants/modal_types';
|
import * as MODALS from 'constants/modal_types';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { normalizeURI } from 'lbryURI';
|
import { normalizeURI } from 'lbry-redux';
|
||||||
import { selectState as selectSearch, selectWunderBarAddress } from 'redux/selectors/search';
|
import {
|
||||||
import { doUpdateSearchQuery } from 'redux/actions/search';
|
selectSearchState as selectSearch,
|
||||||
|
selectWunderBarAddress,
|
||||||
|
doUpdateSearchQuery,
|
||||||
|
} from 'lbry-redux';
|
||||||
import { doNavigate } from 'redux/actions/navigation';
|
import { doNavigate } from 'redux/actions/navigation';
|
||||||
import { doOpenModal } from 'redux/actions/app';
|
import { doOpenModal } from 'redux/actions/app';
|
||||||
import Wunderbar from './view';
|
import Wunderbar from './view';
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// @flow
|
// @flow
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import { normalizeURI } from 'lbryURI';
|
import { normalizeURI } from 'lbry-redux';
|
||||||
import Icon from 'component/common/icon';
|
import Icon from 'component/common/icon';
|
||||||
import { parseQueryParams } from 'util/query_params';
|
import { parseQueryParams } from 'util/query_params';
|
||||||
import * as icons from 'constants/icons';
|
import * as icons from 'constants/icons';
|
||||||
|
|
|
@ -1,86 +0,0 @@
|
||||||
const jsonrpc = {};
|
|
||||||
|
|
||||||
jsonrpc.call = (
|
|
||||||
connectionString,
|
|
||||||
method,
|
|
||||||
params,
|
|
||||||
callback,
|
|
||||||
errorCallback,
|
|
||||||
connectFailedCallback
|
|
||||||
) => {
|
|
||||||
function checkAndParse(response) {
|
|
||||||
if (response.status >= 200 && response.status < 300) {
|
|
||||||
return response.json();
|
|
||||||
}
|
|
||||||
return response.json().then(json => {
|
|
||||||
let error;
|
|
||||||
if (json.error) {
|
|
||||||
error = new Error(json.error.message);
|
|
||||||
} else {
|
|
||||||
error = new Error('Protocol error with unknown response signature');
|
|
||||||
}
|
|
||||||
return Promise.reject(error);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const counter = parseInt(sessionStorage.getItem('JSONRPCCounter') || 0, 10);
|
|
||||||
const url = connectionString;
|
|
||||||
const options = {
|
|
||||||
method: 'POST',
|
|
||||||
body: JSON.stringify({
|
|
||||||
jsonrpc: '2.0',
|
|
||||||
method,
|
|
||||||
params,
|
|
||||||
id: counter,
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
|
|
||||||
sessionStorage.setItem('JSONRPCCounter', counter + 1);
|
|
||||||
|
|
||||||
return fetch(url, options)
|
|
||||||
.then(checkAndParse)
|
|
||||||
.then(response => {
|
|
||||||
const error = response.error || (response.result && response.result.error);
|
|
||||||
|
|
||||||
if (!error && typeof callback === 'function') {
|
|
||||||
return callback(response.result);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error && typeof errorCallback === 'function') {
|
|
||||||
return errorCallback(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
const errorEvent = new CustomEvent('unhandledError', {
|
|
||||||
detail: {
|
|
||||||
connectionString,
|
|
||||||
method,
|
|
||||||
params,
|
|
||||||
code: error.code,
|
|
||||||
message: error.message || error,
|
|
||||||
data: error.data,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
document.dispatchEvent(errorEvent);
|
|
||||||
|
|
||||||
return Promise.resolve();
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
if (connectFailedCallback) {
|
|
||||||
return connectFailedCallback(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
const errorEvent = new CustomEvent('unhandledError', {
|
|
||||||
detail: {
|
|
||||||
connectionString,
|
|
||||||
method,
|
|
||||||
params,
|
|
||||||
code: error.response && error.response.status,
|
|
||||||
message: __('Connection to API server failed'),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
document.dispatchEvent(errorEvent);
|
|
||||||
return Promise.resolve();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export default jsonrpc;
|
|
|
@ -1,151 +0,0 @@
|
||||||
import { ipcRenderer } from 'electron';
|
|
||||||
import jsonrpc from 'jsonrpc';
|
|
||||||
|
|
||||||
const CHECK_DAEMON_STARTED_TRY_NUMBER = 200;
|
|
||||||
|
|
||||||
const Lbry = {
|
|
||||||
isConnected: false,
|
|
||||||
daemonConnectionString: 'http://localhost:5279',
|
|
||||||
pendingPublishTimeout: 20 * 60 * 1000,
|
|
||||||
};
|
|
||||||
|
|
||||||
function apiCall(method, params, resolve, reject) {
|
|
||||||
return jsonrpc.call(Lbry.daemonConnectionString, method, params, resolve, reject, reject);
|
|
||||||
}
|
|
||||||
|
|
||||||
const lbryProxy = new Proxy(Lbry, {
|
|
||||||
get(target, name) {
|
|
||||||
if (name in target) {
|
|
||||||
return target[name];
|
|
||||||
}
|
|
||||||
|
|
||||||
return (params = {}) =>
|
|
||||||
new Promise((resolve, reject) => {
|
|
||||||
apiCall(name, params, resolve, reject);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
function getLocal(key, fallback = undefined) {
|
|
||||||
const itemRaw = localStorage.getItem(key);
|
|
||||||
return itemRaw === null ? fallback : JSON.parse(itemRaw);
|
|
||||||
}
|
|
||||||
|
|
||||||
function setLocal(key, value) {
|
|
||||||
localStorage.setItem(key, JSON.stringify(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
// core
|
|
||||||
Lbry.connectPromise = null;
|
|
||||||
Lbry.connect = () => {
|
|
||||||
if (Lbry.connectPromise === null) {
|
|
||||||
Lbry.connectPromise = new Promise((resolve, reject) => {
|
|
||||||
let tryNum = 0;
|
|
||||||
|
|
||||||
// Check every half second to see if the daemon is accepting connections
|
|
||||||
function checkDaemonStarted() {
|
|
||||||
tryNum += 1;
|
|
||||||
lbryProxy
|
|
||||||
.status()
|
|
||||||
.then(resolve)
|
|
||||||
.catch(() => {
|
|
||||||
if (tryNum <= CHECK_DAEMON_STARTED_TRY_NUMBER) {
|
|
||||||
setTimeout(checkDaemonStarted, tryNum < 50 ? 400 : 1000);
|
|
||||||
} else {
|
|
||||||
reject(new Error('Unable to connect to LBRY'));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
checkDaemonStarted();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return Lbry.connectPromise;
|
|
||||||
};
|
|
||||||
|
|
||||||
Lbry.imagePath = file => `${staticResourcesPath}/img/${file}`;
|
|
||||||
|
|
||||||
Lbry.getAppVersionInfo = () =>
|
|
||||||
new Promise(resolve => {
|
|
||||||
ipcRenderer.once('version-info-received', (event, versionInfo) => {
|
|
||||||
resolve(versionInfo);
|
|
||||||
});
|
|
||||||
ipcRenderer.send('version-info-requested');
|
|
||||||
});
|
|
||||||
|
|
||||||
Lbry.getMediaType = (contentType, fileName) => {
|
|
||||||
if (contentType) {
|
|
||||||
return /^[^/]+/.exec(contentType)[0];
|
|
||||||
} else if (fileName) {
|
|
||||||
const dotIndex = fileName.lastIndexOf('.');
|
|
||||||
if (dotIndex === -1) {
|
|
||||||
return 'unknown';
|
|
||||||
}
|
|
||||||
|
|
||||||
const ext = fileName.substr(dotIndex + 1);
|
|
||||||
if (/^mp4|m4v|webm|flv|f4v|ogv$/i.test(ext)) {
|
|
||||||
return 'video';
|
|
||||||
} else if (/^mp3|m4a|aac|wav|flac|ogg|opus$/i.test(ext)) {
|
|
||||||
return 'audio';
|
|
||||||
} else if (/^html|htm|xml|pdf|odf|doc|docx|md|markdown|txt|epub|org$/i.test(ext)) {
|
|
||||||
return 'document';
|
|
||||||
}
|
|
||||||
return 'unknown';
|
|
||||||
}
|
|
||||||
return 'unknown';
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wrappers for API methods to simulate missing or future behavior. Unlike the old-style stubs,
|
|
||||||
* these are designed to be transparent wrappers around the corresponding API methods.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns results from the file_list API method, plus dummy entries for pending publishes.
|
|
||||||
* (If a real publish with the same claim name is found, the pending publish will be ignored and removed.)
|
|
||||||
*/
|
|
||||||
Lbry.file_list = (params = {}) =>
|
|
||||||
new Promise((resolve, reject) => {
|
|
||||||
const { claim_name: claimName, channel_name: channelName, outpoint } = params;
|
|
||||||
|
|
||||||
apiCall(
|
|
||||||
'file_list',
|
|
||||||
params,
|
|
||||||
fileInfos => {
|
|
||||||
resolve(fileInfos);
|
|
||||||
},
|
|
||||||
reject
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
Lbry.claim_list_mine = (params = {}) =>
|
|
||||||
new Promise((resolve, reject) => {
|
|
||||||
apiCall(
|
|
||||||
'claim_list_mine',
|
|
||||||
params,
|
|
||||||
claims => {
|
|
||||||
resolve(claims);
|
|
||||||
},
|
|
||||||
reject
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
Lbry.resolve = (params = {}) =>
|
|
||||||
new Promise((resolve, reject) => {
|
|
||||||
apiCall(
|
|
||||||
'resolve',
|
|
||||||
params,
|
|
||||||
data => {
|
|
||||||
if ('uri' in params) {
|
|
||||||
// If only a single URI was requested, don't nest the results in an object
|
|
||||||
resolve(data && data[params.uri] ? data[params.uri] : {});
|
|
||||||
} else {
|
|
||||||
resolve(data || {});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
reject
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
export default lbryProxy;
|
|
|
@ -1,230 +0,0 @@
|
||||||
const channelNameMinLength = 1;
|
|
||||||
const claimIdMaxLength = 40;
|
|
||||||
|
|
||||||
export const regexInvalidURI = /[^A-Za-z0-9-]/g;
|
|
||||||
export const regexAddress = /^b(?=[^0OIl]{32,33})[0-9A-Za-z]{32,33}$/;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parses a LBRY name into its component parts. Throws errors with user-friendly
|
|
||||||
* messages for invalid names.
|
|
||||||
*
|
|
||||||
* N.B. that "name" indicates the value in the name position of the URI. For
|
|
||||||
* claims for channel content, this will actually be the channel name, and
|
|
||||||
* the content name is in the path (e.g. lbry://@channel/content)
|
|
||||||
*
|
|
||||||
* In most situations, you'll want to use the contentName and channelName keys
|
|
||||||
* and ignore the name key.
|
|
||||||
*
|
|
||||||
* Returns a dictionary with keys:
|
|
||||||
* - name (string): The value in the "name" position in the URI. Note that this
|
|
||||||
* could be either content name or channel name; see above.
|
|
||||||
* - path (string, if persent)
|
|
||||||
* - claimSequence (int, if present)
|
|
||||||
* - bidPosition (int, if present)
|
|
||||||
* - claimId (string, if present)
|
|
||||||
* - isChannel (boolean)
|
|
||||||
* - contentName (string): For anon claims, the name; for channel claims, the path
|
|
||||||
* - channelName (string, if present): Channel name without @
|
|
||||||
*/
|
|
||||||
export function parseURI(URI, requireProto = false) {
|
|
||||||
// Break into components. Empty sub-matches are converted to null
|
|
||||||
const componentsRegex = new RegExp(
|
|
||||||
'^((?:lbry://)?)' + // protocol
|
|
||||||
'([^:$#/]*)' + // claim name (stops at the first separator or end)
|
|
||||||
'([:$#]?)([^/]*)' + // modifier separator, modifier (stops at the first path separator or end)
|
|
||||||
'(/?)(.*)' // path separator, path
|
|
||||||
);
|
|
||||||
const [proto, claimName, modSep, modVal, pathSep, path] = componentsRegex
|
|
||||||
.exec(URI)
|
|
||||||
.slice(1)
|
|
||||||
.map(match => match || null);
|
|
||||||
|
|
||||||
let contentName;
|
|
||||||
|
|
||||||
// Validate protocol
|
|
||||||
if (requireProto && !proto) {
|
|
||||||
throw new Error(__('LBRY URIs must include a protocol prefix (lbry://).'));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate and process name
|
|
||||||
if (!claimName) {
|
|
||||||
throw new Error(__('URI does not include name.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
const isChannel = claimName.startsWith('@');
|
|
||||||
const channelName = isChannel ? claimName.slice(1) : claimName;
|
|
||||||
|
|
||||||
if (isChannel) {
|
|
||||||
if (!channelName) {
|
|
||||||
throw new Error(__('No channel name after @.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (channelName.length < channelNameMinLength) {
|
|
||||||
throw new Error(__(`Channel names must be at least %s characters.`, channelNameMinLength));
|
|
||||||
}
|
|
||||||
|
|
||||||
contentName = path;
|
|
||||||
}
|
|
||||||
|
|
||||||
const nameBadChars = (channelName || claimName).match(regexInvalidURI);
|
|
||||||
if (nameBadChars) {
|
|
||||||
throw new Error(
|
|
||||||
__(
|
|
||||||
`Invalid character %s in name: %s.`,
|
|
||||||
nameBadChars.length === 1 ? '' : 's',
|
|
||||||
nameBadChars.join(', ')
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate and process modifier (claim ID, bid position or claim sequence)
|
|
||||||
let claimId;
|
|
||||||
let claimSequence;
|
|
||||||
let bidPosition;
|
|
||||||
if (modSep) {
|
|
||||||
if (!modVal) {
|
|
||||||
throw new Error(__(`No modifier provided after separator %s.`, modSep));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (modSep === '#') {
|
|
||||||
claimId = modVal;
|
|
||||||
} else if (modSep === ':') {
|
|
||||||
claimSequence = modVal;
|
|
||||||
} else if (modSep === '$') {
|
|
||||||
bidPosition = modVal;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
claimId &&
|
|
||||||
(claimId.length > claimIdMaxLength || !claimId.match(/^[0-9a-f]+$/)) &&
|
|
||||||
!claimId.match(/^pending/) // ought to be dropped when savePendingPublish drops hack
|
|
||||||
) {
|
|
||||||
throw new Error(__(`Invalid claim ID %s.`, claimId));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (claimSequence && !claimSequence.match(/^-?[1-9][0-9]*$/)) {
|
|
||||||
throw new Error(__('Claim sequence must be a number.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bidPosition && !bidPosition.match(/^-?[1-9][0-9]*$/)) {
|
|
||||||
throw new Error(__('Bid position must be a number.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate and process path
|
|
||||||
if (path) {
|
|
||||||
if (!isChannel) {
|
|
||||||
throw new Error(__('Only channel URIs may have a path.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
const pathBadChars = path.match(regexInvalidURI);
|
|
||||||
if (pathBadChars) {
|
|
||||||
throw new Error(__(`Invalid character in path: %s`, pathBadChars.join(', ')));
|
|
||||||
}
|
|
||||||
|
|
||||||
contentName = path;
|
|
||||||
} else if (pathSep) {
|
|
||||||
throw new Error(__('No path provided after /'));
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
claimName,
|
|
||||||
path,
|
|
||||||
isChannel,
|
|
||||||
...(contentName ? { contentName } : {}),
|
|
||||||
...(channelName ? { channelName } : {}),
|
|
||||||
...(claimSequence ? { claimSequence: parseInt(claimSequence, 10) } : {}),
|
|
||||||
...(bidPosition ? { bidPosition: parseInt(bidPosition, 10) } : {}),
|
|
||||||
...(claimId ? { claimId } : {}),
|
|
||||||
...(path ? { path } : {}),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Takes an object in the same format returned by parse() and builds a URI.
|
|
||||||
*
|
|
||||||
* The channelName key will accept names with or without the @ prefix.
|
|
||||||
*/
|
|
||||||
export function buildURI(URIObj, includeProto = true) {
|
|
||||||
const { claimId, claimSequence, bidPosition, contentName, channelName } = URIObj;
|
|
||||||
|
|
||||||
let { claimName, path } = URIObj;
|
|
||||||
|
|
||||||
if (channelName) {
|
|
||||||
const channelNameFormatted = channelName.startsWith('@') ? channelName : `@${channelName}`;
|
|
||||||
if (!claimName) {
|
|
||||||
claimName = channelNameFormatted;
|
|
||||||
} else if (claimName !== channelNameFormatted) {
|
|
||||||
throw new Error(
|
|
||||||
__(
|
|
||||||
'Received a channel content URI, but claim name and channelName do not match. "name" represents the value in the name position of the URI (lbry://name...), which for channel content will be the channel name. In most cases, to construct a channel URI you should just pass channelName and contentName.'
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (contentName) {
|
|
||||||
if (!claimName) {
|
|
||||||
claimName = contentName;
|
|
||||||
} else if (!path) {
|
|
||||||
path = contentName;
|
|
||||||
}
|
|
||||||
if (path && path !== contentName) {
|
|
||||||
throw new Error(
|
|
||||||
__(
|
|
||||||
'Path and contentName do not match. Only one is required; most likely you wanted contentName.'
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
(includeProto ? 'lbry://' : '') +
|
|
||||||
claimName +
|
|
||||||
(claimId ? `#${claimId}` : '') +
|
|
||||||
(claimSequence ? `:${claimSequence}` : '') +
|
|
||||||
(bidPosition ? `${bidPosition}` : '') +
|
|
||||||
(path ? `/${path}` : '')
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Takes a parseable LBRY URI and converts it to standard, canonical format */
|
|
||||||
export function normalizeURI(URI) {
|
|
||||||
if (URI.match(/pending_claim/)) return URI;
|
|
||||||
|
|
||||||
const { claimName, path, bidPosition, claimSequence, claimId } = parseURI(URI);
|
|
||||||
return buildURI({ claimName, path, claimSequence, bidPosition, claimId });
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isURIValid(URI) {
|
|
||||||
let parts;
|
|
||||||
try {
|
|
||||||
parts = parseURI(normalizeURI(URI));
|
|
||||||
} catch (error) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return parts && parts.claimName;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isNameValid(claimName, checkCase = true) {
|
|
||||||
const regexp = new RegExp('^[a-z0-9-]+$', checkCase ? '' : 'i');
|
|
||||||
return regexp.test(claimName);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isURIClaimable(URI) {
|
|
||||||
let parts;
|
|
||||||
try {
|
|
||||||
parts = parseURI(normalizeURI(URI));
|
|
||||||
} catch (error) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
parts &&
|
|
||||||
parts.claimName &&
|
|
||||||
!parts.claimId &&
|
|
||||||
!parts.bidPosition &&
|
|
||||||
!parts.claimSequence &&
|
|
||||||
!parts.isChannel &&
|
|
||||||
!parts.path
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -1,38 +1,16 @@
|
||||||
import { ipcRenderer } from 'electron';
|
import { ipcRenderer } from 'electron';
|
||||||
import Lbry from 'lbry';
|
import { Lbry } from 'lbry-redux';
|
||||||
import querystring from 'querystring';
|
import querystring from 'querystring';
|
||||||
|
|
||||||
const Lbryio = {
|
const Lbryio = {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
authenticationPromise: null,
|
authenticationPromise: null,
|
||||||
exchangePromise: null,
|
|
||||||
exchangeLastFetched: null,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const CONNECTION_STRING = process.env.LBRY_APP_API_URL
|
const CONNECTION_STRING = process.env.LBRY_APP_API_URL
|
||||||
? process.env.LBRY_APP_API_URL.replace(/\/*$/, '/') // exactly one slash at the end
|
? process.env.LBRY_APP_API_URL.replace(/\/*$/, '/') // exactly one slash at the end
|
||||||
: 'https://api.lbry.io/';
|
: 'https://api.lbry.io/';
|
||||||
|
|
||||||
const EXCHANGE_RATE_TIMEOUT = 20 * 60 * 1000;
|
|
||||||
|
|
||||||
Lbryio.getExchangeRates = () => {
|
|
||||||
if (
|
|
||||||
!Lbryio.exchangeLastFetched ||
|
|
||||||
Date.now() - Lbryio.exchangeLastFetched > EXCHANGE_RATE_TIMEOUT
|
|
||||||
) {
|
|
||||||
Lbryio.exchangePromise = new Promise((resolve, reject) => {
|
|
||||||
Lbryio.call('lbc', 'exchange_rate', {}, 'get', true)
|
|
||||||
.then(({ lbc_usd: LBC_USD, lbc_btc: LBC_BTC, btc_usd: BTC_USD }) => {
|
|
||||||
const rates = { LBC_USD, LBC_BTC, BTC_USD };
|
|
||||||
resolve(rates);
|
|
||||||
})
|
|
||||||
.catch(reject);
|
|
||||||
});
|
|
||||||
Lbryio.exchangeLastFetched = Date.now();
|
|
||||||
}
|
|
||||||
return Lbryio.exchangePromise;
|
|
||||||
};
|
|
||||||
|
|
||||||
Lbryio.call = (resource, action, params = {}, method = 'get') => {
|
Lbryio.call = (resource, action, params = {}, method = 'get') => {
|
||||||
if (!Lbryio.enabled) {
|
if (!Lbryio.enabled) {
|
||||||
console.log(__('Internal API disabled'));
|
console.log(__('Internal API disabled'));
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
import React from 'react';
|
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { doCloseModal } from 'redux/actions/app';
|
|
||||||
import { doLoadVideo, doSetPlayingUri } from 'redux/actions/content';
|
import { doLoadVideo, doSetPlayingUri } from 'redux/actions/content';
|
||||||
import { makeSelectMetadataForUri } from 'redux/selectors/claims';
|
import { doCloseModal, makeSelectMetadataForUri } from 'lbry-redux';
|
||||||
import ModalAffirmPurchase from './view';
|
import ModalAffirmPurchase from './view';
|
||||||
|
|
||||||
const select = (state, props) => ({
|
const select = (state, props) => ({
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import React from 'react';
|
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { doCloseModal } from 'redux/actions/app';
|
import { doCloseModal } from 'lbry-redux';
|
||||||
import ModalAuthFailure from './view';
|
import ModalAuthFailure from './view';
|
||||||
|
|
||||||
const select = state => ({});
|
const select = state => ({});
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { doCloseModal } from 'redux/actions/app';
|
|
||||||
import { doNavigate } from 'redux/actions/navigation';
|
import { doNavigate } from 'redux/actions/navigation';
|
||||||
import { doSetClientSetting } from 'redux/actions/settings';
|
import { doSetClientSetting } from 'redux/actions/settings';
|
||||||
import { selectUserIsRewardApproved } from 'redux/selectors/user';
|
import { selectUserIsRewardApproved } from 'redux/selectors/user';
|
||||||
import { selectBalance } from 'redux/selectors/wallet';
|
import { selectBalance, doCloseModal } from 'lbry-redux';
|
||||||
import { selectUnclaimedRewardValue } from 'redux/selectors/rewards';
|
import { selectUnclaimedRewardValue } from 'redux/selectors/rewards';
|
||||||
import * as settings from 'constants/settings';
|
import * as settings from 'constants/settings';
|
||||||
import ModalCreditIntro from './view';
|
import ModalCreditIntro from './view';
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import React from 'react';
|
|
||||||
import * as settings from 'constants/settings';
|
import * as settings from 'constants/settings';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { doCloseModal } from 'redux/actions/app';
|
import { doCloseModal } from 'redux/actions/app';
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import React from 'react';
|
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { doCloseModal } from 'redux/actions/app';
|
import { doCloseModal } from 'lbry-redux';
|
||||||
import ModalError from './view';
|
import ModalError from './view';
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import lbry from 'lbry';
|
import Native from 'native';
|
||||||
import { ExpandableModal } from 'modal/modal';
|
import { ExpandableModal } from 'modal/modal';
|
||||||
|
|
||||||
class ModalError extends React.PureComponent {
|
class ModalError extends React.PureComponent {
|
||||||
|
@ -8,7 +8,7 @@ class ModalError extends React.PureComponent {
|
||||||
|
|
||||||
const errorObj = typeof error === 'string' ? { message: error } : error;
|
const errorObj = typeof error === 'string' ? { message: error } : error;
|
||||||
|
|
||||||
const error_key_labels = {
|
const errorKeyLabels = {
|
||||||
connectionString: __('API connection string'),
|
connectionString: __('API connection string'),
|
||||||
method: __('Method'),
|
method: __('Method'),
|
||||||
params: __('Parameters'),
|
params: __('Parameters'),
|
||||||
|
@ -20,7 +20,7 @@ class ModalError extends React.PureComponent {
|
||||||
const errorInfoList = [];
|
const errorInfoList = [];
|
||||||
for (const key of Object.keys(errorObj)) {
|
for (const key of Object.keys(errorObj)) {
|
||||||
const val = typeof errorObj[key] === 'string' ? errorObj[key] : JSON.stringify(errorObj[key]);
|
const val = typeof errorObj[key] === 'string' ? errorObj[key] : JSON.stringify(errorObj[key]);
|
||||||
const label = error_key_labels[key];
|
const label = errorKeyLabels[key];
|
||||||
errorInfoList.push(
|
errorInfoList.push(
|
||||||
<li key={key}>
|
<li key={key}>
|
||||||
<strong>{label}</strong>: <code>{val}</code>
|
<strong>{label}</strong>: <code>{val}</code>
|
||||||
|
@ -42,7 +42,11 @@ class ModalError extends React.PureComponent {
|
||||||
|
|
||||||
<div className="error-modal__content">
|
<div className="error-modal__content">
|
||||||
<div>
|
<div>
|
||||||
<img className="error-modal__warning-symbol" src={lbry.imagePath('warning.png')} />
|
<img
|
||||||
|
alt=""
|
||||||
|
className="error-modal__warning-symbol"
|
||||||
|
src={Native.imagePath('warning.png')}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<p>
|
<p>
|
||||||
{__(
|
{__(
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
import React from 'react';
|
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { doCloseModal } from 'redux/actions/app';
|
import { doCloseModal, makeSelectMetadataForUri } from 'lbry-redux';
|
||||||
import { makeSelectMetadataForUri } from 'redux/selectors/claims';
|
|
||||||
import ModalFileTimeout from './view';
|
import ModalFileTimeout from './view';
|
||||||
|
|
||||||
const select = state => ({
|
const select = (state, props) => ({
|
||||||
metadata: makeSelectMetadataForUri(props.uri)(state),
|
metadata: makeSelectMetadataForUri(props.uri)(state),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
import React from 'react';
|
|
||||||
import rewards from 'rewards';
|
import rewards from 'rewards';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { doCloseModal } from 'redux/actions/app';
|
import { doCloseModal } from 'lbry-redux';
|
||||||
import { makeSelectRewardByType } from 'redux/selectors/rewards';
|
import { makeSelectRewardByType } from 'redux/selectors/rewards';
|
||||||
import ModalFirstReward from './view';
|
import ModalFirstReward from './view';
|
||||||
|
|
||||||
const select = (state, props) => {
|
const select = state => {
|
||||||
const selectReward = makeSelectRewardByType();
|
const selectReward = makeSelectRewardByType();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -4,8 +4,8 @@ import { connect } from 'react-redux';
|
||||||
import { doCloseModal } from 'redux/actions/app';
|
import { doCloseModal } from 'redux/actions/app';
|
||||||
import { doSetClientSetting } from 'redux/actions/settings';
|
import { doSetClientSetting } from 'redux/actions/settings';
|
||||||
import { selectPhoneToVerify, selectUser } from 'redux/selectors/user';
|
import { selectPhoneToVerify, selectUser } from 'redux/selectors/user';
|
||||||
import ModalPhoneCollection from './view';
|
|
||||||
import { doNavigate } from 'redux/actions/navigation';
|
import { doNavigate } from 'redux/actions/navigation';
|
||||||
|
import ModalPhoneCollection from './view';
|
||||||
|
|
||||||
const select = state => ({
|
const select = state => ({
|
||||||
phone: selectPhoneToVerify(state),
|
phone: selectPhoneToVerify(state),
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
import React from 'react';
|
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { doCloseModal } from 'redux/actions/app';
|
import { doDeleteFileAndGoBack } from 'redux/actions/file';
|
||||||
import { doDeleteFileAndGoBack } from 'redux/actions/file_info';
|
import {
|
||||||
import { makeSelectTitleForUri, makeSelectClaimIsMine } from 'redux/selectors/claims';
|
doCloseModal,
|
||||||
import { makeSelectFileInfoForUri } from 'redux/selectors/file_info';
|
makeSelectTitleForUri,
|
||||||
|
makeSelectClaimIsMine,
|
||||||
|
makeSelectFileInfoForUri,
|
||||||
|
} from 'lbry-redux';
|
||||||
import ModalRemoveFile from './view';
|
import ModalRemoveFile from './view';
|
||||||
|
|
||||||
const select = (state, props) => ({
|
const select = (state, props) => ({
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
import React from 'react';
|
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { doCloseModal } from 'redux/actions/app';
|
import { doCloseModal, doAbandonClaim, selectTransactionItems } from 'lbry-redux';
|
||||||
import { doAbandonClaim } from 'redux/actions/content';
|
|
||||||
import { selectTransactionItems } from 'redux/selectors/wallet';
|
|
||||||
import ModalRevokeClaim from './view';
|
import ModalRevokeClaim from './view';
|
||||||
|
|
||||||
const select = state => ({
|
const select = state => ({
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import React from 'react';
|
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { doCloseModal } from 'redux/actions/app';
|
import { doCloseModal } from 'lbry-redux';
|
||||||
import { doAuthNavigate } from 'redux/actions/navigation';
|
import { doAuthNavigate } from 'redux/actions/navigation';
|
||||||
import ModalRewardApprovalRequired from './view';
|
import ModalRewardApprovalRequired from './view';
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
import React from 'react';
|
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { doOpenModal } from 'redux/actions/app';
|
|
||||||
import * as settings from 'constants/settings';
|
import * as settings from 'constants/settings';
|
||||||
import { selectCurrentModal, selectModalProps, selectModalsAllowed } from 'redux/selectors/app';
|
import { selectCurrentModal, selectModalProps, selectModalsAllowed } from 'redux/selectors/app';
|
||||||
import { selectCurrentPage } from 'redux/selectors/navigation';
|
import {
|
||||||
import { selectCostForCurrentPageUri } from 'redux/selectors/cost_info';
|
doOpenModal,
|
||||||
|
selectCostForCurrentPageUri,
|
||||||
|
selectBalance,
|
||||||
|
selectCurrentPage,
|
||||||
|
} from 'lbry-redux';
|
||||||
import { makeSelectClientSetting } from 'redux/selectors/settings';
|
import { makeSelectClientSetting } from 'redux/selectors/settings';
|
||||||
import { selectUser, selectUserIsVerificationCandidate } from 'redux/selectors/user';
|
import { selectUser, selectUserIsVerificationCandidate } from 'redux/selectors/user';
|
||||||
import { selectBalance } from 'redux/selectors/wallet';
|
|
||||||
|
|
||||||
import ModalRouter from './view';
|
import ModalRouter from './view';
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import React from 'react';
|
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { doCloseModal } from 'redux/actions/app';
|
import { doCloseModal } from 'lbry-redux';
|
||||||
import ModalTransactionFailed from './view';
|
import ModalTransactionFailed from './view';
|
||||||
|
|
||||||
const select = state => ({});
|
const select = state => ({});
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
import React from 'react';
|
|
||||||
import * as settings from 'constants/settings';
|
import * as settings from 'constants/settings';
|
||||||
import * as modals from 'constants/modal_types';
|
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { doCloseModal, doOpenModal } from 'redux/actions/app';
|
import { doCloseModal } from 'lbry-redux';
|
||||||
import { doSetClientSetting } from 'redux/actions/settings';
|
import { doSetClientSetting } from 'redux/actions/settings';
|
||||||
import ModalWelcome from './view';
|
import ModalWelcome from './view';
|
||||||
|
|
||||||
|
|
15
src/renderer/native.js
Normal file
15
src/renderer/native.js
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
import { ipcRenderer } from 'electron';
|
||||||
|
|
||||||
|
const Native = {};
|
||||||
|
|
||||||
|
Native.getAppVersionInfo = () =>
|
||||||
|
new Promise(resolve => {
|
||||||
|
ipcRenderer.once('version-info-received', (event, versionInfo) => {
|
||||||
|
resolve(versionInfo);
|
||||||
|
});
|
||||||
|
ipcRenderer.send('version-info-requested');
|
||||||
|
});
|
||||||
|
|
||||||
|
Native.imagePath = file => `${staticResourcesPath}/img/${file}`;
|
||||||
|
|
||||||
|
export default Native;
|
|
@ -1,7 +1,6 @@
|
||||||
import React from 'react';
|
import { selectPathAfterAuth } from 'lbry-redux';
|
||||||
import { doNavigate } from 'redux/actions/navigation';
|
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { selectPathAfterAuth } from 'redux/selectors/navigation';
|
import { doNavigate } from 'redux/actions/navigation';
|
||||||
import {
|
import {
|
||||||
selectAuthenticationIsPending,
|
selectAuthenticationIsPending,
|
||||||
selectEmailToVerify,
|
selectEmailToVerify,
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import React from 'react';
|
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { doFetchClaimsByChannel, doFetchClaimCountByChannel } from 'redux/actions/content';
|
import { doFetchClaimsByChannel, doFetchClaimCountByChannel } from 'redux/actions/content';
|
||||||
import {
|
import {
|
||||||
makeSelectClaimForUri,
|
makeSelectClaimForUri,
|
||||||
makeSelectClaimsInChannelForCurrentPage,
|
makeSelectClaimsInChannelForCurrentPage,
|
||||||
makeSelectFetchingChannelClaims,
|
makeSelectFetchingChannelClaims,
|
||||||
} from 'redux/selectors/claims';
|
makeSelectCurrentParam,
|
||||||
import { makeSelectCurrentParam, selectCurrentParams } from 'redux/selectors/navigation';
|
selectCurrentParams,
|
||||||
|
} from 'lbry-redux';
|
||||||
import { doNavigate } from 'redux/actions/navigation';
|
import { doNavigate } from 'redux/actions/navigation';
|
||||||
import { makeSelectTotalPagesForChannel } from 'redux/selectors/content';
|
import { makeSelectTotalPagesForChannel } from 'redux/selectors/content';
|
||||||
import { doOpenModal } from 'redux/actions/app';
|
import { doOpenModal } from 'redux/actions/app';
|
||||||
|
|
|
@ -1,21 +1,21 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { doNavigate } from 'redux/actions/navigation';
|
import { doNavigate } from 'redux/actions/navigation';
|
||||||
import { doFetchFileInfo } from 'redux/actions/file_info';
|
|
||||||
import { makeSelectFileInfoForUri } from 'redux/selectors/file_info';
|
|
||||||
import { selectRewardContentClaimIds, selectPlayingUri } from 'redux/selectors/content';
|
import { selectRewardContentClaimIds, selectPlayingUri } from 'redux/selectors/content';
|
||||||
import { doFetchCostInfoForUri } from 'redux/actions/cost_info';
|
|
||||||
import { doCheckSubscription } from 'redux/actions/subscriptions';
|
import { doCheckSubscription } from 'redux/actions/subscriptions';
|
||||||
import {
|
import {
|
||||||
|
doFetchFileInfo,
|
||||||
|
doFetchCostInfoForUri,
|
||||||
|
makeSelectClaimIsMine,
|
||||||
|
makeSelectCostInfoForUri,
|
||||||
|
makeSelectFileInfoForUri,
|
||||||
makeSelectClaimForUri,
|
makeSelectClaimForUri,
|
||||||
makeSelectContentTypeForUri,
|
makeSelectContentTypeForUri,
|
||||||
makeSelectMetadataForUri,
|
makeSelectMetadataForUri,
|
||||||
makeSelectClaimIsMine,
|
} from 'lbry-redux';
|
||||||
} from 'redux/selectors/claims';
|
|
||||||
import { makeSelectCostInfoForUri } from 'redux/selectors/cost_info';
|
|
||||||
import { selectShowNsfw } from 'redux/selectors/settings';
|
import { selectShowNsfw } from 'redux/selectors/settings';
|
||||||
|
import { selectSubscriptions } from 'redux/selectors/subscriptions';
|
||||||
import { selectMediaPaused } from 'redux/selectors/media';
|
import { selectMediaPaused } from 'redux/selectors/media';
|
||||||
import { doOpenModal } from 'redux/actions/app';
|
import { doOpenModal } from 'redux/actions/app';
|
||||||
import { selectSubscriptions } from 'redux/selectors/subscriptions';
|
|
||||||
import { doPrepareEdit } from 'redux/actions/publish';
|
import { doPrepareEdit } from 'redux/actions/publish';
|
||||||
import FilePage from './view';
|
import FilePage from './view';
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import lbry from 'lbry';
|
import { Lbry, buildURI, normalizeURI } from 'lbry-redux';
|
||||||
import { buildURI, normalizeURI } from 'lbryURI';
|
|
||||||
import Video from 'component/video';
|
import Video from 'component/video';
|
||||||
import Thumbnail from 'component/common/thumbnail';
|
import Thumbnail from 'component/common/thumbnail';
|
||||||
import FilePrice from 'component/filePrice';
|
import FilePrice from 'component/filePrice';
|
||||||
|
@ -111,7 +110,7 @@ class FilePage extends React.Component<Props> {
|
||||||
const isRewardContent = rewardedContentClaimIds.includes(claim.claim_id);
|
const isRewardContent = rewardedContentClaimIds.includes(claim.claim_id);
|
||||||
const shouldObscureThumbnail = obscureNsfw && metadata.nsfw;
|
const shouldObscureThumbnail = obscureNsfw && metadata.nsfw;
|
||||||
const { height, channel_name: channelName, value } = claim;
|
const { height, channel_name: channelName, value } = claim;
|
||||||
const mediaType = lbry.getMediaType(contentType);
|
const mediaType = Lbry.getMediaType(contentType);
|
||||||
const isPlayable =
|
const isPlayable =
|
||||||
Object.values(player.mime).indexOf(contentType) !== -1 || mediaType === 'audio';
|
Object.values(player.mime).indexOf(contentType) !== -1 || mediaType === 'audio';
|
||||||
const channelClaimId =
|
const channelClaimId =
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { selectFileInfosDownloaded } from 'redux/selectors/file_info';
|
import { selectFileInfosDownloaded, selectMyClaimsWithoutChannels } from 'lbry-redux';
|
||||||
import { selectMyClaimsWithoutChannels } from 'redux/selectors/claims';
|
|
||||||
import { doNavigate } from 'redux/actions/navigation';
|
import { doNavigate } from 'redux/actions/navigation';
|
||||||
import FileListDownloaded from './view';
|
import FileListDownloaded from './view';
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { selectMyClaimsWithoutChannels } from 'redux/selectors/claims';
|
import { selectMyClaimsWithoutChannels } from 'lbry-redux';
|
||||||
import { selectPendingPublishesLessEdits } from 'redux/selectors/publish';
|
import { selectPendingPublishesLessEdits } from 'redux/selectors/publish';
|
||||||
import { doNavigate } from 'redux/actions/navigation';
|
import { doNavigate } from 'redux/actions/navigation';
|
||||||
import { doCheckPendingPublishes } from 'redux/actions/publish';
|
import { doCheckPendingPublishes } from 'redux/actions/publish';
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import React from 'react';
|
|
||||||
import { doAuthNavigate } from 'redux/actions/navigation';
|
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
import { doAuthNavigate } from 'redux/actions/navigation';
|
||||||
import { doFetchAccessToken } from 'redux/actions/user';
|
import { doFetchAccessToken } from 'redux/actions/user';
|
||||||
import { selectAccessToken, selectUser } from 'redux/selectors/user';
|
import { selectAccessToken, selectUser } from 'redux/selectors/user';
|
||||||
import HelpPage from './view';
|
import HelpPage from './view';
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
// @TODO: Customize advice based on OS
|
// @TODO: Customize advice based on OS
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import lbry from 'lbry.js';
|
import { Lbry } from 'lbry-redux';
|
||||||
|
import Native from 'native';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
import BusyIndicator from 'component/common/busy-indicator';
|
import BusyIndicator from 'component/common/busy-indicator';
|
||||||
import Icon from 'component/common/icon';
|
import Icon from 'component/common/icon';
|
||||||
|
@ -23,18 +24,18 @@ class HelpPage extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
lbry.getAppVersionInfo().then(({ remoteVersion, localVersion, upgradeAvailable }) => {
|
Native.getAppVersionInfo().then(({ remoteVersion, localVersion, upgradeAvailable }) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
uiVersion: localVersion,
|
uiVersion: localVersion,
|
||||||
upgradeAvailable,
|
upgradeAvailable,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
lbry.version().then(info => {
|
Lbry.version().then(info => {
|
||||||
this.setState({
|
this.setState({
|
||||||
versionInfo: info,
|
versionInfo: info,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
lbry.status({ session_status: true }).then(info => {
|
Lbry.status({ session_status: true }).then(info => {
|
||||||
this.setState({
|
this.setState({
|
||||||
lbryId: info.lbry_id,
|
lbryId: info.lbry_id,
|
||||||
});
|
});
|
||||||
|
@ -50,18 +51,21 @@ class HelpPage extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let ver, osName, platform, newVerLink;
|
let ver;
|
||||||
|
let osName;
|
||||||
|
let platform;
|
||||||
|
let newVerLink;
|
||||||
|
|
||||||
const { accessToken, doAuth, user } = this.props;
|
const { accessToken, doAuth, user } = this.props;
|
||||||
|
|
||||||
if (this.state.versionInfo) {
|
if (this.state.versionInfo) {
|
||||||
ver = this.state.versionInfo;
|
ver = this.state.versionInfo;
|
||||||
if (ver.os_system == 'Darwin') {
|
if (ver.os_system === 'Darwin') {
|
||||||
osName = parseInt(ver.os_release.match(/^\d+/)) < 16 ? 'Mac OS X' : 'Mac OS';
|
osName = parseInt(ver.os_release.match(/^\d+/), 10) < 16 ? 'Mac OS X' : 'Mac OS';
|
||||||
|
|
||||||
platform = `${osName} ${ver.os_release}`;
|
platform = `${osName} ${ver.os_release}`;
|
||||||
newVerLink = 'https://lbry.io/get/lbry.dmg';
|
newVerLink = 'https://lbry.io/get/lbry.dmg';
|
||||||
} else if (ver.os_system == 'Linux') {
|
} else if (ver.os_system === 'Linux') {
|
||||||
platform = `Linux (${ver.platform})`;
|
platform = `Linux (${ver.platform})`;
|
||||||
newVerLink = 'https://lbry.io/get/lbry.deb';
|
newVerLink = 'https://lbry.io/get/lbry.deb';
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,17 +1,26 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { doNavigate } from 'redux/actions/navigation';
|
import { doClaimRewardType } from 'redux/actions/rewards';
|
||||||
import { selectMyClaims, selectClaimsByUri } from 'redux/selectors/claims';
|
|
||||||
import { selectResolvingUris } from 'redux/selectors/content';
|
|
||||||
import { selectPublishFormValues } from 'redux/selectors/publish';
|
|
||||||
import { doResolveUri } from 'redux/actions/content';
|
|
||||||
import { selectBalance } from 'redux/selectors/wallet';
|
|
||||||
import {
|
import {
|
||||||
doClearPublish,
|
doHistoryBack,
|
||||||
doUpdatePublishForm,
|
doResolveUri,
|
||||||
doPublish,
|
makeSelectCostInfoForUri,
|
||||||
doPrepareEdit,
|
selectMyClaims,
|
||||||
} from 'redux/actions/publish';
|
selectFetchingMyChannels,
|
||||||
import { makeSelectCostInfoForUri } from 'redux/selectors/cost_info';
|
selectMyChannelClaims,
|
||||||
|
selectClaimsByUri,
|
||||||
|
selectResolvingUris,
|
||||||
|
selectBalance,
|
||||||
|
} from 'lbry-redux';
|
||||||
|
import {
|
||||||
|
doFetchClaimListMine,
|
||||||
|
doFetchChannelListMine,
|
||||||
|
doCreateChannel,
|
||||||
|
} from 'redux/actions/content';
|
||||||
|
import { doNavigate } from 'redux/actions/navigation';
|
||||||
|
import rewards from 'rewards';
|
||||||
|
import { selectPublishFormValues } from 'redux/selectors/publish';
|
||||||
|
import { doClearPublish, doUpdatePublishForm, doPublish } from 'redux/actions/publish';
|
||||||
|
import { doPrepareEdit } from 'redux/actions/publish';
|
||||||
import PublishPage from './view';
|
import PublishPage from './view';
|
||||||
|
|
||||||
const select = (state, props) => {
|
const select = (state, props) => {
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
import { FormRow, FormField } from 'component/common/form';
|
import { FormRow } from 'component/common/form';
|
||||||
|
import { Lbry } from 'lbry-redux';
|
||||||
import { doShowSnackBar } from 'redux/actions/app';
|
import { doShowSnackBar } from 'redux/actions/app';
|
||||||
import lbry from 'lbry';
|
|
||||||
import Page from 'component/page';
|
|
||||||
|
|
||||||
class ReportPage extends React.Component {
|
class ReportPage extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
@ -27,7 +26,7 @@ class ReportPage extends React.Component {
|
||||||
this.setState({
|
this.setState({
|
||||||
submitting: true,
|
submitting: true,
|
||||||
});
|
});
|
||||||
lbry.report_bug({ message }).then(() => {
|
Lbry.report_bug({ message }).then(() => {
|
||||||
this.setState({
|
this.setState({
|
||||||
submitting: false,
|
submitting: false,
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import React from 'react';
|
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { selectFetchingRewards, selectUnclaimedRewards } from 'redux/selectors/rewards';
|
import { selectFetchingRewards, selectUnclaimedRewards } from 'redux/selectors/rewards';
|
||||||
import { selectUser } from 'redux/selectors/user';
|
import { selectUser } from 'redux/selectors/user';
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { selectIsSearching, selectSearchValue } from 'redux/selectors/search';
|
import { selectIsSearching, selectSearchValue, doUpdateSearchQuery } from 'lbry-redux';
|
||||||
import { doNavigate } from 'redux/actions/navigation';
|
import { doNavigate } from 'redux/actions/navigation';
|
||||||
import { doUpdateSearchQuery } from 'redux/actions/search';
|
|
||||||
import SearchPage from './view';
|
import SearchPage from './view';
|
||||||
|
|
||||||
const select = state => ({
|
const select = state => ({
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { isURIValid, normalizeURI } from 'lbryURI';
|
import { isURIValid, normalizeURI } from 'lbry-redux';
|
||||||
import FileTile from 'component/fileTile';
|
import FileTile from 'component/fileTile';
|
||||||
import FileListSearch from 'component/fileListSearch';
|
import FileListSearch from 'component/fileListSearch';
|
||||||
import ToolTip from 'component/common/tooltip';
|
import ToolTip from 'component/common/tooltip';
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
import React from 'react';
|
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { doResolveUri } from 'redux/actions/content';
|
import { doResolveUri, makeSelectClaimForUri, makeSelectIsUriResolving } from 'lbry-redux';
|
||||||
import { makeSelectClaimForUri } from 'redux/selectors/claims';
|
|
||||||
import { makeSelectIsUriResolving } from 'redux/selectors/content';
|
|
||||||
import ShowPage from './view';
|
import ShowPage from './view';
|
||||||
|
|
||||||
const select = (state, props) => ({
|
const select = (state, props) => ({
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
import React from 'react';
|
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { doFetchTransactions } from 'redux/actions/wallet';
|
import {
|
||||||
import { selectTransactionItems, selectIsFetchingTransactions } from 'redux/selectors/wallet';
|
doFetchTransactions,
|
||||||
|
selectTransactionItems,
|
||||||
|
selectIsFetchingTransactions,
|
||||||
|
} from 'lbry-redux';
|
||||||
import TransactionHistoryPage from './view';
|
import TransactionHistoryPage from './view';
|
||||||
|
|
||||||
const select = state => ({
|
const select = state => ({
|
||||||
|
|
|
@ -1,19 +1,16 @@
|
||||||
import { execSync } from 'child_process';
|
import { execSync } from 'child_process';
|
||||||
import isDev from 'electron-is-dev';
|
import isDev from 'electron-is-dev';
|
||||||
import Lbry from 'lbry';
|
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import * as ACTIONS from 'constants/action_types';
|
|
||||||
import * as MODALS from 'constants/modal_types';
|
import * as MODALS from 'constants/modal_types';
|
||||||
import { ipcRenderer, remote } from 'electron';
|
import { ipcRenderer, remote } from 'electron';
|
||||||
|
import { ACTIONS, Lbry, doBalanceSubscribe, doFetchFileInfosAndPublishedClaims } from 'lbry-redux';
|
||||||
|
import Native from 'native';
|
||||||
import { doFetchRewardedContent } from 'redux/actions/content';
|
import { doFetchRewardedContent } from 'redux/actions/content';
|
||||||
import { doFetchFileInfosAndPublishedClaims } from 'redux/actions/file_info';
|
|
||||||
import { doAuthNavigate } from 'redux/actions/navigation';
|
|
||||||
import { doFetchDaemonSettings } from 'redux/actions/settings';
|
import { doFetchDaemonSettings } from 'redux/actions/settings';
|
||||||
|
import { doAuthNavigate } from 'redux/actions/navigation';
|
||||||
import { doAuthenticate } from 'redux/actions/user';
|
import { doAuthenticate } from 'redux/actions/user';
|
||||||
import { doBalanceSubscribe } from 'redux/actions/wallet';
|
|
||||||
import { doPause } from 'redux/actions/media';
|
import { doPause } from 'redux/actions/media';
|
||||||
import { doCheckSubscriptions } from 'redux/actions/subscriptions';
|
import { doCheckSubscriptions } from 'redux/actions/subscriptions';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
selectCurrentModal,
|
selectCurrentModal,
|
||||||
selectIsUpgradeSkipped,
|
selectIsUpgradeSkipped,
|
||||||
|
@ -240,7 +237,7 @@ export function doCheckUpgradeAvailable() {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
Lbry.getAppVersionInfo().then(success, fail);
|
Native.getAppVersionInfo().then(success, fail);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -303,13 +300,6 @@ export function doDaemonReady() {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doShowSnackBar(data) {
|
|
||||||
return {
|
|
||||||
type: ACTIONS.SHOW_SNACKBAR,
|
|
||||||
data,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function doRemoveSnackBarSnack() {
|
export function doRemoveSnackBarSnack() {
|
||||||
return {
|
return {
|
||||||
type: ACTIONS.REMOVE_SNACKBAR_SNACK,
|
type: ACTIONS.REMOVE_SNACKBAR_SNACK,
|
||||||
|
|
|
@ -1,12 +1,8 @@
|
||||||
import * as ACTIONS from 'constants/action_types';
|
|
||||||
import * as MODALS from 'constants/modal_types';
|
import * as MODALS from 'constants/modal_types';
|
||||||
import * as SETTINGS from 'constants/settings';
|
|
||||||
import * as NOTIFICATION_TYPES from 'constants/notification_types';
|
import * as NOTIFICATION_TYPES from 'constants/notification_types';
|
||||||
import { ipcRenderer } from 'electron';
|
import { ipcRenderer } from 'electron';
|
||||||
import Lbry from 'lbry';
|
|
||||||
import Lbryio from 'lbryio';
|
import Lbryio from 'lbryio';
|
||||||
import { normalizeURI, buildURI } from 'lbryURI';
|
import { doAlertError } from 'redux/actions/app';
|
||||||
import { doAlertError, doOpenModal } from 'redux/actions/app';
|
|
||||||
import { doClaimEligiblePurchaseRewards } from 'redux/actions/rewards';
|
import { doClaimEligiblePurchaseRewards } from 'redux/actions/rewards';
|
||||||
import { doNavigate } from 'redux/actions/navigation';
|
import { doNavigate } from 'redux/actions/navigation';
|
||||||
import {
|
import {
|
||||||
|
@ -16,68 +12,29 @@ import {
|
||||||
} from 'redux/actions/subscriptions';
|
} from 'redux/actions/subscriptions';
|
||||||
import { selectNotifications } from 'redux/selectors/subscriptions';
|
import { selectNotifications } from 'redux/selectors/subscriptions';
|
||||||
import { selectBadgeNumber } from 'redux/selectors/app';
|
import { selectBadgeNumber } from 'redux/selectors/app';
|
||||||
import { selectMyClaimsRaw } from 'redux/selectors/claims';
|
|
||||||
import { selectResolvingUris } from 'redux/selectors/content';
|
|
||||||
import { makeSelectCostInfoForUri } from 'redux/selectors/cost_info';
|
|
||||||
import {
|
import {
|
||||||
|
ACTIONS,
|
||||||
|
SETTINGS,
|
||||||
|
Lbry,
|
||||||
|
Lbryapi,
|
||||||
|
buildURI,
|
||||||
|
batchActions,
|
||||||
|
doResolveUris,
|
||||||
|
doFetchClaimListMine,
|
||||||
|
doOpenModal,
|
||||||
|
makeSelectCostInfoForUri,
|
||||||
makeSelectFileInfoForUri,
|
makeSelectFileInfoForUri,
|
||||||
selectDownloadingByOutpoint,
|
selectDownloadingByOutpoint,
|
||||||
selectTotalDownloadProgress,
|
selectTotalDownloadProgress,
|
||||||
} from 'redux/selectors/file_info';
|
selectBalance,
|
||||||
|
} from 'lbry-redux';
|
||||||
import { makeSelectClientSetting } from 'redux/selectors/settings';
|
import { makeSelectClientSetting } from 'redux/selectors/settings';
|
||||||
import { selectBalance } from 'redux/selectors/wallet';
|
|
||||||
import batchActions from 'util/batchActions';
|
|
||||||
import setBadge from 'util/setBadge';
|
import setBadge from 'util/setBadge';
|
||||||
import setProgressBar from 'util/setProgressBar';
|
import setProgressBar from 'util/setProgressBar';
|
||||||
import analytics from 'analytics';
|
import analytics from 'analytics';
|
||||||
|
|
||||||
const DOWNLOAD_POLL_INTERVAL = 250;
|
const DOWNLOAD_POLL_INTERVAL = 250;
|
||||||
|
|
||||||
export function doResolveUris(uris) {
|
|
||||||
return (dispatch, getState) => {
|
|
||||||
const normalizedUris = uris.map(normalizeURI);
|
|
||||||
const state = getState();
|
|
||||||
|
|
||||||
// Filter out URIs that are already resolving
|
|
||||||
const resolvingUris = selectResolvingUris(state);
|
|
||||||
const urisToResolve = normalizedUris.filter(uri => !resolvingUris.includes(uri));
|
|
||||||
|
|
||||||
if (urisToResolve.length === 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
dispatch({
|
|
||||||
type: ACTIONS.RESOLVE_URIS_STARTED,
|
|
||||||
data: { uris: normalizedUris },
|
|
||||||
});
|
|
||||||
|
|
||||||
const resolveInfo = {};
|
|
||||||
Lbry.resolve({ uris: urisToResolve }).then(result => {
|
|
||||||
Object.entries(result).forEach(([uri, uriResolveInfo]) => {
|
|
||||||
const fallbackResolveInfo = {
|
|
||||||
claim: null,
|
|
||||||
claimsInChannel: null,
|
|
||||||
certificate: null,
|
|
||||||
};
|
|
||||||
|
|
||||||
const { claim, certificate, claims_in_channel: claimsInChannel } =
|
|
||||||
uriResolveInfo && !uriResolveInfo.error ? uriResolveInfo : fallbackResolveInfo;
|
|
||||||
|
|
||||||
resolveInfo[uri] = { claim, certificate, claimsInChannel };
|
|
||||||
});
|
|
||||||
|
|
||||||
dispatch({
|
|
||||||
type: ACTIONS.RESOLVE_URIS_COMPLETED,
|
|
||||||
data: { resolveInfo },
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function doResolveUri(uri) {
|
|
||||||
return doResolveUris([uri]);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function doFetchFeaturedUris() {
|
export function doFetchFeaturedUris() {
|
||||||
return dispatch => {
|
return dispatch => {
|
||||||
dispatch({
|
dispatch({
|
||||||
|
@ -374,7 +331,7 @@ export function doPurchaseUri(uri, specificCostInfo) {
|
||||||
attemptPlay(cost, instantPurchaseMax.amount);
|
attemptPlay(cost, instantPurchaseMax.amount);
|
||||||
} else {
|
} else {
|
||||||
// Need to convert currency of instant purchase maximum before trying to play
|
// Need to convert currency of instant purchase maximum before trying to play
|
||||||
Lbryio.getExchangeRates().then(({ LBC_USD }) => {
|
Lbryapi.getExchangeRates().then(({ LBC_USD }) => {
|
||||||
attemptPlay(cost, instantPurchaseMax.amount / LBC_USD);
|
attemptPlay(cost, instantPurchaseMax.amount / LBC_USD);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -457,23 +414,6 @@ export function doFetchClaimCountByChannel(uri) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doFetchClaimListMine() {
|
|
||||||
return dispatch => {
|
|
||||||
dispatch({
|
|
||||||
type: ACTIONS.FETCH_CLAIM_LIST_MINE_STARTED,
|
|
||||||
});
|
|
||||||
|
|
||||||
Lbry.claim_list_mine().then(claims => {
|
|
||||||
dispatch({
|
|
||||||
type: ACTIONS.FETCH_CLAIM_LIST_MINE_COMPLETED,
|
|
||||||
data: {
|
|
||||||
claims,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function doPlayUri(uri) {
|
export function doPlayUri(uri) {
|
||||||
return dispatch => {
|
return dispatch => {
|
||||||
dispatch(doSetPlayingUri(uri));
|
dispatch(doSetPlayingUri(uri));
|
||||||
|
@ -526,43 +466,20 @@ export function doCreateChannel(name, amount) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doAbandonClaim(txid, nout) {
|
export function doPublish(params) {
|
||||||
return (dispatch, getState) => {
|
return dispatch =>
|
||||||
const state = getState();
|
new Promise((resolve, reject) => {
|
||||||
const myClaims = selectMyClaimsRaw(state);
|
const success = claim => {
|
||||||
const { claim_id: claimId, name } = myClaims.find(
|
resolve(claim);
|
||||||
claim => claim.txid === txid && claim.nout === nout
|
|
||||||
);
|
|
||||||
|
|
||||||
dispatch({
|
if (claim === true) dispatch(doFetchClaimListMine());
|
||||||
type: ACTIONS.ABANDON_CLAIM_STARTED,
|
else
|
||||||
data: {
|
setTimeout(() => dispatch(doFetchClaimListMine()), 20000, {
|
||||||
claimId,
|
once: true,
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const errorCallback = () => {
|
|
||||||
dispatch(doOpenModal(MODALS.TRANSACTION_FAILED));
|
|
||||||
};
|
};
|
||||||
|
const failure = err => reject(err);
|
||||||
|
|
||||||
const successCallback = results => {
|
Lbry.publishDeprecated(params, null, success, failure);
|
||||||
if (results.txid) {
|
|
||||||
dispatch({
|
|
||||||
type: ACTIONS.ABANDON_CLAIM_SUCCEEDED,
|
|
||||||
data: {
|
|
||||||
claimId,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
dispatch(doResolveUri(buildURI({ claimName: name, claimId })));
|
|
||||||
dispatch(doFetchClaimListMine());
|
|
||||||
} else {
|
|
||||||
dispatch(doOpenModal(MODALS.TRANSACTION_FAILED));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Lbry.claim_abandon({
|
|
||||||
txid,
|
|
||||||
nout,
|
|
||||||
}).then(successCallback, errorCallback);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,38 +0,0 @@
|
||||||
import * as ACTIONS from 'constants/action_types';
|
|
||||||
import Lbryio from 'lbryio';
|
|
||||||
import { selectClaimsByUri } from 'redux/selectors/claims';
|
|
||||||
|
|
||||||
// eslint-disable-next-line import/prefer-default-export
|
|
||||||
export function doFetchCostInfoForUri(uri) {
|
|
||||||
return (dispatch, getState) => {
|
|
||||||
const state = getState();
|
|
||||||
const claim = selectClaimsByUri(state)[uri];
|
|
||||||
|
|
||||||
if (!claim) return;
|
|
||||||
|
|
||||||
function resolve(costInfo) {
|
|
||||||
dispatch({
|
|
||||||
type: ACTIONS.FETCH_COST_INFO_COMPLETED,
|
|
||||||
data: {
|
|
||||||
uri,
|
|
||||||
costInfo,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const fee =
|
|
||||||
claim.value && claim.value.stream && claim.value.stream.metadata
|
|
||||||
? claim.value.stream.metadata.fee
|
|
||||||
: undefined;
|
|
||||||
|
|
||||||
if (fee === undefined) {
|
|
||||||
resolve({ cost: 0, includesData: true });
|
|
||||||
} else if (fee.currency === 'LBC') {
|
|
||||||
resolve({ cost: fee.amount, includesData: true });
|
|
||||||
} else {
|
|
||||||
Lbryio.getExchangeRates().then(({ LBC_USD }) => {
|
|
||||||
resolve({ cost: fee.amount / LBC_USD, includesData: true });
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,73 +1,17 @@
|
||||||
import * as ACTIONS from 'constants/action_types';
|
import * as ACTIONS from 'constants/action_types';
|
||||||
import { shell } from 'electron';
|
import { shell } from 'electron';
|
||||||
import Lbry from 'lbry';
|
|
||||||
import { doCloseModal } from 'redux/actions/app';
|
|
||||||
import { doAbandonClaim, doFetchClaimListMine } from 'redux/actions/content';
|
|
||||||
import { doHistoryBack } from 'redux/actions/navigation';
|
|
||||||
import {
|
import {
|
||||||
selectClaimsByUri,
|
Lbry,
|
||||||
selectIsFetchingClaimListMine,
|
batchActions,
|
||||||
|
doAbandonClaim,
|
||||||
selectMyClaimsOutpoints,
|
selectMyClaimsOutpoints,
|
||||||
} from 'redux/selectors/claims';
|
|
||||||
import {
|
|
||||||
selectFileInfosByOutpoint,
|
selectFileInfosByOutpoint,
|
||||||
selectIsFetchingFileList,
|
|
||||||
selectTotalDownloadProgress,
|
selectTotalDownloadProgress,
|
||||||
selectUrisLoading,
|
} from 'lbry-redux';
|
||||||
} from 'redux/selectors/file_info';
|
import { doCloseModal } from 'redux/actions/app';
|
||||||
import batchActions from 'util/batchActions';
|
import { doHistoryBack } from 'redux/actions/navigation';
|
||||||
import setProgressBar from 'util/setProgressBar';
|
import setProgressBar from 'util/setProgressBar';
|
||||||
|
|
||||||
export function doFetchFileInfo(uri) {
|
|
||||||
return (dispatch, getState) => {
|
|
||||||
const state = getState();
|
|
||||||
const claim = selectClaimsByUri(state)[uri];
|
|
||||||
const outpoint = claim ? `${claim.txid}:${claim.nout}` : null;
|
|
||||||
const alreadyFetching = !!selectUrisLoading(state)[uri];
|
|
||||||
|
|
||||||
if (!alreadyFetching) {
|
|
||||||
dispatch({
|
|
||||||
type: ACTIONS.FETCH_FILE_INFO_STARTED,
|
|
||||||
data: {
|
|
||||||
outpoint,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
Lbry.file_list({ outpoint, full_status: true }).then(fileInfos => {
|
|
||||||
dispatch({
|
|
||||||
type: ACTIONS.FETCH_FILE_INFO_COMPLETED,
|
|
||||||
data: {
|
|
||||||
outpoint,
|
|
||||||
fileInfo: fileInfos && fileInfos.length ? fileInfos[0] : null,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function doFileList() {
|
|
||||||
return (dispatch, getState) => {
|
|
||||||
const state = getState();
|
|
||||||
const isFetching = selectIsFetchingFileList(state);
|
|
||||||
|
|
||||||
if (!isFetching) {
|
|
||||||
dispatch({
|
|
||||||
type: ACTIONS.FILE_LIST_STARTED,
|
|
||||||
});
|
|
||||||
|
|
||||||
Lbry.file_list().then(fileInfos => {
|
|
||||||
dispatch({
|
|
||||||
type: ACTIONS.FILE_LIST_SUCCEEDED,
|
|
||||||
data: {
|
|
||||||
fileInfos,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function doOpenFileInFolder(path) {
|
export function doOpenFileInFolder(path) {
|
||||||
return () => {
|
return () => {
|
||||||
shell.showItemInFolder(path);
|
shell.showItemInFolder(path);
|
||||||
|
@ -127,14 +71,3 @@ export function doDeleteFileAndGoBack(fileInfo, deleteFromComputer, abandonClaim
|
||||||
dispatch(batchActions(...actions));
|
dispatch(batchActions(...actions));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doFetchFileInfosAndPublishedClaims() {
|
|
||||||
return (dispatch, getState) => {
|
|
||||||
const state = getState();
|
|
||||||
const isFetchingClaimListMine = selectIsFetchingClaimListMine(state);
|
|
||||||
const isFetchingFileInfo = selectIsFetchingFileList(state);
|
|
||||||
|
|
||||||
if (!isFetchingClaimListMine) dispatch(doFetchClaimListMine());
|
|
||||||
if (!isFetchingFileInfo) dispatch(doFileList());
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,8 +1,6 @@
|
||||||
// @flow
|
// @flow
|
||||||
import * as actions from 'constants/action_types';
|
import * as actions from 'constants/action_types';
|
||||||
import type { Action, Dispatch } from 'redux/reducers/media';
|
import type { Dispatch } from 'redux/reducers/media';
|
||||||
import lbry from 'lbry';
|
|
||||||
import { makeSelectClaimForUri } from 'redux/selectors/claims';
|
|
||||||
|
|
||||||
export const doPlay = () => (dispatch: Dispatch) =>
|
export const doPlay = () => (dispatch: Dispatch) =>
|
||||||
dispatch({
|
dispatch({
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import * as ACTIONS from 'constants/action_types';
|
import { ACTIONS, selectHistoryIndex, selectHistoryStack } from 'lbry-redux';
|
||||||
import { selectHistoryIndex, selectHistoryStack } from 'redux/selectors/navigation';
|
|
||||||
import { toQueryString } from 'util/query_params';
|
import { toQueryString } from 'util/query_params';
|
||||||
import analytics from 'analytics';
|
import analytics from 'analytics';
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
// @flow
|
// @flow
|
||||||
import Lbry from 'lbry';
|
|
||||||
import * as ACTIONS from 'constants/action_types';
|
|
||||||
import * as MODALS from 'constants/modal_types';
|
import * as MODALS from 'constants/modal_types';
|
||||||
import { selectMyClaimsWithoutChannels } from 'redux/selectors/claims';
|
import { ACTIONS, Lbry, selectMyClaimsWithoutChannels } from 'lbry-redux';
|
||||||
import { selectPendingPublishes } from 'redux/selectors/publish';
|
import { selectPendingPublishes } from 'redux/selectors/publish';
|
||||||
import { doOpenModal } from 'redux/actions/app';
|
import { doOpenModal } from 'redux/actions/app';
|
||||||
import type {
|
import type {
|
||||||
|
|
|
@ -1,176 +0,0 @@
|
||||||
import * as ACTIONS from 'constants/action_types';
|
|
||||||
import * as SEARCH_TYPES from 'constants/search';
|
|
||||||
import { normalizeURI, buildURI, parseURI } from 'lbryURI';
|
|
||||||
import { doResolveUri } from 'redux/actions/content';
|
|
||||||
import { doNavigate } from 'redux/actions/navigation';
|
|
||||||
import { selectCurrentPage } from 'redux/selectors/navigation';
|
|
||||||
import { makeSelectSearchUris } from 'redux/selectors/search';
|
|
||||||
import batchActions from 'util/batchActions';
|
|
||||||
import handleFetchResponse from 'util/handle-fetch';
|
|
||||||
|
|
||||||
export const doSearch = rawQuery => (dispatch, getState) => {
|
|
||||||
const state = getState();
|
|
||||||
const query = rawQuery.replace(/^lbry:\/\//i, '');
|
|
||||||
|
|
||||||
if (!query) {
|
|
||||||
dispatch({
|
|
||||||
type: ACTIONS.SEARCH_FAIL,
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we have already searched for something, we don't need to do anything
|
|
||||||
const urisForQuery = makeSelectSearchUris(query)(state);
|
|
||||||
if (urisForQuery && !!urisForQuery.length) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
dispatch({
|
|
||||||
type: ACTIONS.SEARCH_START,
|
|
||||||
});
|
|
||||||
|
|
||||||
// If the user is on the file page with a pre-populated uri and they select
|
|
||||||
// the search option without typing anything, searchQuery will be empty
|
|
||||||
// We need to populate it so the input is filled on the search page
|
|
||||||
if (!state.search.searchQuery) {
|
|
||||||
dispatch({
|
|
||||||
type: ACTIONS.UPDATE_SEARCH_QUERY,
|
|
||||||
data: { searchQuery: query },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
fetch(`https://lighthouse.lbry.io/search?s=${query}`)
|
|
||||||
.then(handleFetchResponse)
|
|
||||||
.then(data => {
|
|
||||||
const uris = [];
|
|
||||||
const actions = [];
|
|
||||||
|
|
||||||
data.forEach(result => {
|
|
||||||
const uri = buildURI({
|
|
||||||
claimName: result.name,
|
|
||||||
claimId: result.claimId,
|
|
||||||
});
|
|
||||||
actions.push(doResolveUri(uri));
|
|
||||||
uris.push(uri);
|
|
||||||
});
|
|
||||||
|
|
||||||
actions.push({
|
|
||||||
type: ACTIONS.SEARCH_SUCCESS,
|
|
||||||
data: {
|
|
||||||
query,
|
|
||||||
uris,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
dispatch(batchActions(...actions));
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
dispatch({
|
|
||||||
type: ACTIONS.SEARCH_FAIL,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export const doUpdateSearchQuery = (query: string, shouldSkipSuggestions: ?boolean) => dispatch => {
|
|
||||||
dispatch({
|
|
||||||
type: ACTIONS.UPDATE_SEARCH_QUERY,
|
|
||||||
data: { query },
|
|
||||||
});
|
|
||||||
|
|
||||||
// Don't fetch new suggestions if the user just added a space
|
|
||||||
if (!query.endsWith(' ') || !shouldSkipSuggestions) {
|
|
||||||
dispatch(getSearchSuggestions(query));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getSearchSuggestions = (value: string) => dispatch => {
|
|
||||||
const query = value.trim();
|
|
||||||
|
|
||||||
const isPrefix = () => {
|
|
||||||
return query === '@' || query === 'lbry:' || query === 'lbry:/' || query === 'lbry://';
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!query || isPrefix()) {
|
|
||||||
dispatch({
|
|
||||||
type: ACTIONS.UPDATE_SEARCH_SUGGESTIONS,
|
|
||||||
data: { suggestions: [] },
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let suggestions = [];
|
|
||||||
try {
|
|
||||||
// If the user is about to manually add the claim id ignore it until they
|
|
||||||
// actually add one. This would hardly ever happen, but then the search
|
|
||||||
// suggestions won't change just from adding a '#' after a uri
|
|
||||||
let uriQuery = query;
|
|
||||||
if (uriQuery.endsWith('#')) {
|
|
||||||
uriQuery = uriQuery.slice(0, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const uri = normalizeURI(uriQuery);
|
|
||||||
const { claimName, isChannel } = parseURI(uri);
|
|
||||||
|
|
||||||
suggestions.push(
|
|
||||||
{
|
|
||||||
value: uri,
|
|
||||||
shorthand: isChannel ? claimName.slice(1) : claimName,
|
|
||||||
type: isChannel ? SEARCH_TYPES.CHANNEL : SEARCH_TYPES.FILE,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: claimName,
|
|
||||||
type: SEARCH_TYPES.SEARCH,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// If it's a valid url, don't fetch any extra search results
|
|
||||||
return dispatch({
|
|
||||||
type: ACTIONS.UPDATE_SEARCH_SUGGESTIONS,
|
|
||||||
data: { suggestions },
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
suggestions.push({
|
|
||||||
value: query,
|
|
||||||
type: SEARCH_TYPES.SEARCH,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Populate the current search query suggestion before fetching results
|
|
||||||
dispatch({
|
|
||||||
type: ACTIONS.UPDATE_SEARCH_SUGGESTIONS,
|
|
||||||
data: { suggestions },
|
|
||||||
});
|
|
||||||
|
|
||||||
// strip out any basic stuff for more accurate search results
|
|
||||||
let searchValue = value.replace(/lbry:\/\//g, '').replace(/-/g, ' ');
|
|
||||||
if (searchValue.includes('#')) {
|
|
||||||
// This should probably be more robust, but I think it's fine for now
|
|
||||||
// Remove everything after # to get rid of the claim id
|
|
||||||
searchValue = searchValue.substring(0, searchValue.indexOf('#'));
|
|
||||||
}
|
|
||||||
|
|
||||||
return fetch(`https://lighthouse.lbry.io/autocomplete?s=${searchValue}`)
|
|
||||||
.then(handleFetchResponse)
|
|
||||||
.then(apiSuggestions => {
|
|
||||||
const formattedSuggestions = apiSuggestions.slice(0, 6).map(suggestion => {
|
|
||||||
// This will need to be more robust when the api starts returning lbry uris
|
|
||||||
const isChannel = suggestion.startsWith('@');
|
|
||||||
const suggestionObj = {
|
|
||||||
value: isChannel ? `lbry://${suggestion}` : suggestion,
|
|
||||||
shorthand: isChannel ? suggestion.slice(1) : '',
|
|
||||||
type: isChannel ? 'channel' : 'search',
|
|
||||||
};
|
|
||||||
|
|
||||||
return suggestionObj;
|
|
||||||
});
|
|
||||||
|
|
||||||
suggestions = suggestions.concat(formattedSuggestions);
|
|
||||||
dispatch({
|
|
||||||
type: ACTIONS.UPDATE_SEARCH_SUGGESTIONS,
|
|
||||||
data: { suggestions },
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
// If the fetch fails, do nothing
|
|
||||||
// Basic search suggestions are already populated at this point
|
|
||||||
});
|
|
||||||
};
|
|
|
@ -1,8 +1,6 @@
|
||||||
import * as ACTIONS from 'constants/action_types';
|
|
||||||
import * as SETTINGS from 'constants/settings';
|
|
||||||
import Fs from 'fs';
|
import Fs from 'fs';
|
||||||
import Http from 'http';
|
import Http from 'http';
|
||||||
import Lbry from 'lbry';
|
import { Lbry, ACTIONS, SETTINGS } from 'lbry-redux';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import analytics from 'analytics';
|
import analytics from 'analytics';
|
||||||
|
|
||||||
|
|
|
@ -8,10 +8,9 @@ import type {
|
||||||
SubscriptionNotifications,
|
SubscriptionNotifications,
|
||||||
} from 'redux/reducers/subscriptions';
|
} from 'redux/reducers/subscriptions';
|
||||||
import { selectSubscriptions } from 'redux/selectors/subscriptions';
|
import { selectSubscriptions } from 'redux/selectors/subscriptions';
|
||||||
import Lbry from 'lbry';
|
import { Lbry, buildURI } from 'lbry-redux';
|
||||||
import { doPurchaseUri } from 'redux/actions/content';
|
import { doPurchaseUri } from 'redux/actions/content';
|
||||||
import { doNavigate } from 'redux/actions/navigation';
|
import { doNavigate } from 'redux/actions/navigation';
|
||||||
import { buildURI } from 'lbryURI';
|
|
||||||
import analytics from 'analytics';
|
import analytics from 'analytics';
|
||||||
|
|
||||||
const CHECK_SUBSCRIPTIONS_INTERVAL = 60 * 60 * 1000;
|
const CHECK_SUBSCRIPTIONS_INTERVAL = 60 * 60 * 1000;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import * as ACTIONS from 'constants/action_types';
|
import * as ACTIONS from 'constants/action_types';
|
||||||
import * as MODALS from 'constants/modal_types';
|
import * as MODALS from 'constants/modal_types';
|
||||||
import Lbryio from 'lbryio';
|
import Lbryio from 'lbryio';
|
||||||
import { doOpenModal, doShowSnackBar } from 'redux/actions/app';
|
import { doOpenModal, doShowSnackBar } from 'lbry-redux';
|
||||||
import { doClaimRewardType, doRewardList } from 'redux/actions/rewards';
|
import { doClaimRewardType, doRewardList } from 'redux/actions/rewards';
|
||||||
import {
|
import {
|
||||||
selectEmailToVerify,
|
selectEmailToVerify,
|
||||||
|
|
|
@ -1,190 +0,0 @@
|
||||||
import * as ACTIONS from 'constants/action_types';
|
|
||||||
import * as MODALS from 'constants/modal_types';
|
|
||||||
import Lbry from 'lbry';
|
|
||||||
import { doOpenModal, doShowSnackBar } from 'redux/actions/app';
|
|
||||||
import { doNavigate } from 'redux/actions/navigation';
|
|
||||||
import { selectBalance } from 'redux/selectors/wallet';
|
|
||||||
|
|
||||||
export function doUpdateBalance() {
|
|
||||||
return (dispatch, getState) => {
|
|
||||||
const { wallet: { balance: balanceInStore } } = getState();
|
|
||||||
Lbry.wallet_balance().then(balance => {
|
|
||||||
if (balanceInStore !== balance) {
|
|
||||||
return dispatch({
|
|
||||||
type: ACTIONS.UPDATE_BALANCE,
|
|
||||||
data: {
|
|
||||||
balance,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function doBalanceSubscribe() {
|
|
||||||
return dispatch => {
|
|
||||||
dispatch(doUpdateBalance());
|
|
||||||
setInterval(() => dispatch(doUpdateBalance()), 5000);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function doFetchTransactions() {
|
|
||||||
return dispatch => {
|
|
||||||
dispatch({
|
|
||||||
type: ACTIONS.FETCH_TRANSACTIONS_STARTED,
|
|
||||||
});
|
|
||||||
|
|
||||||
Lbry.transaction_list().then(results => {
|
|
||||||
dispatch({
|
|
||||||
type: ACTIONS.FETCH_TRANSACTIONS_COMPLETED,
|
|
||||||
data: {
|
|
||||||
transactions: results,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function doFetchBlock(height) {
|
|
||||||
return dispatch => {
|
|
||||||
Lbry.block_show({ height }).then(block => {
|
|
||||||
dispatch({
|
|
||||||
type: ACTIONS.FETCH_BLOCK_SUCCESS,
|
|
||||||
data: { block },
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function doGetNewAddress() {
|
|
||||||
return dispatch => {
|
|
||||||
dispatch({
|
|
||||||
type: ACTIONS.GET_NEW_ADDRESS_STARTED,
|
|
||||||
});
|
|
||||||
|
|
||||||
Lbry.wallet_new_address().then(address => {
|
|
||||||
localStorage.setItem('wallet_address', address);
|
|
||||||
dispatch({
|
|
||||||
type: ACTIONS.GET_NEW_ADDRESS_COMPLETED,
|
|
||||||
data: { address },
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function doCheckAddressIsMine(address) {
|
|
||||||
return dispatch => {
|
|
||||||
dispatch({
|
|
||||||
type: ACTIONS.CHECK_ADDRESS_IS_MINE_STARTED,
|
|
||||||
});
|
|
||||||
|
|
||||||
Lbry.wallet_is_address_mine({ address }).then(isMine => {
|
|
||||||
if (!isMine) dispatch(doGetNewAddress());
|
|
||||||
|
|
||||||
dispatch({
|
|
||||||
type: ACTIONS.CHECK_ADDRESS_IS_MINE_COMPLETED,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function doSendDraftTransaction({ amount, address }) {
|
|
||||||
return (dispatch, getState) => {
|
|
||||||
const state = getState();
|
|
||||||
const balance = selectBalance(state);
|
|
||||||
|
|
||||||
if (balance - amount <= 0) {
|
|
||||||
dispatch(doOpenModal(MODALS.INSUFFICIENT_CREDITS));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
dispatch({
|
|
||||||
type: ACTIONS.SEND_TRANSACTION_STARTED,
|
|
||||||
});
|
|
||||||
|
|
||||||
const successCallback = results => {
|
|
||||||
if (results === true) {
|
|
||||||
dispatch({
|
|
||||||
type: ACTIONS.SEND_TRANSACTION_COMPLETED,
|
|
||||||
});
|
|
||||||
dispatch(
|
|
||||||
doShowSnackBar({
|
|
||||||
message: __(`You sent ${amount} LBC`),
|
|
||||||
linkText: __('History'),
|
|
||||||
linkTarget: __('/wallet'),
|
|
||||||
})
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
dispatch({
|
|
||||||
type: ACTIONS.SEND_TRANSACTION_FAILED,
|
|
||||||
data: { error: results },
|
|
||||||
});
|
|
||||||
dispatch(doOpenModal(MODALS.TRANSACTION_FAILED));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const errorCallback = error => {
|
|
||||||
dispatch({
|
|
||||||
type: ACTIONS.SEND_TRANSACTION_FAILED,
|
|
||||||
data: { error: error.message },
|
|
||||||
});
|
|
||||||
dispatch(doOpenModal(MODALS.TRANSACTION_FAILED));
|
|
||||||
};
|
|
||||||
|
|
||||||
Lbry.wallet_send({
|
|
||||||
amount,
|
|
||||||
address,
|
|
||||||
}).then(successCallback, errorCallback);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function doSendSupport(amount, claimId, uri) {
|
|
||||||
return (dispatch, getState) => {
|
|
||||||
const state = getState();
|
|
||||||
const balance = selectBalance(state);
|
|
||||||
|
|
||||||
if (balance - amount <= 0) {
|
|
||||||
dispatch(doOpenModal(MODALS.INSUFFICIENT_CREDITS));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
dispatch({
|
|
||||||
type: ACTIONS.SUPPORT_TRANSACTION_STARTED,
|
|
||||||
});
|
|
||||||
|
|
||||||
const successCallback = results => {
|
|
||||||
if (results.txid) {
|
|
||||||
dispatch({
|
|
||||||
type: ACTIONS.SUPPORT_TRANSACTION_COMPLETED,
|
|
||||||
});
|
|
||||||
dispatch(
|
|
||||||
doShowSnackBar({
|
|
||||||
message: __(`You sent ${amount} LBC as a tip, Mahalo!`),
|
|
||||||
linkText: __('History'),
|
|
||||||
linkTarget: __('/wallet'),
|
|
||||||
})
|
|
||||||
);
|
|
||||||
dispatch(doNavigate('/show', { uri }));
|
|
||||||
} else {
|
|
||||||
dispatch({
|
|
||||||
type: ACTIONS.SUPPORT_TRANSACTION_FAILED,
|
|
||||||
data: { error: results.code },
|
|
||||||
});
|
|
||||||
dispatch(doOpenModal(MODALS.TRANSACTION_FAILED));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const errorCallback = error => {
|
|
||||||
dispatch({
|
|
||||||
type: ACTIONS.SUPPORT_TRANSACTION_FAILED,
|
|
||||||
data: { error: error.code },
|
|
||||||
});
|
|
||||||
dispatch(doOpenModal(MODALS.TRANSACTION_FAILED));
|
|
||||||
};
|
|
||||||
|
|
||||||
Lbry.wallet_send({
|
|
||||||
claim_id: claimId,
|
|
||||||
amount,
|
|
||||||
}).then(successCallback, errorCallback);
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -89,11 +89,10 @@ reducers[ACTIONS.AUTO_UPDATE_DOWNLOADED] = state =>
|
||||||
autoUpdateDownloaded: true,
|
autoUpdateDownloaded: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
reducers[ACTIONS.AUTO_UPDATE_DECLINED] = state => {
|
reducers[ACTIONS.AUTO_UPDATE_DECLINED] = state =>
|
||||||
return Object.assign({}, state, {
|
Object.assign({}, state, {
|
||||||
autoUpdateDeclined: true,
|
autoUpdateDeclined: true,
|
||||||
});
|
});
|
||||||
};
|
|
||||||
|
|
||||||
reducers[ACTIONS.UPGRADE_DOWNLOAD_COMPLETED] = (state, action) =>
|
reducers[ACTIONS.UPGRADE_DOWNLOAD_COMPLETED] = (state, action) =>
|
||||||
Object.assign({}, state, {
|
Object.assign({}, state, {
|
||||||
|
@ -121,17 +120,15 @@ reducers[ACTIONS.SKIP_UPGRADE] = state => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[ACTIONS.MEDIA_PLAY] = state => {
|
reducers[ACTIONS.MEDIA_PLAY] = state =>
|
||||||
return Object.assign({}, state, {
|
Object.assign({}, state, {
|
||||||
modalsAllowed: false,
|
modalsAllowed: false,
|
||||||
});
|
});
|
||||||
};
|
|
||||||
|
|
||||||
reducers[ACTIONS.MEDIA_PAUSE] = state => {
|
reducers[ACTIONS.MEDIA_PAUSE] = state =>
|
||||||
return Object.assign({}, state, {
|
Object.assign({}, state, {
|
||||||
modalsAllowed: true,
|
modalsAllowed: true,
|
||||||
});
|
});
|
||||||
};
|
|
||||||
|
|
||||||
reducers[ACTIONS.SET_PLAYING_URI] = (state, action) => {
|
reducers[ACTIONS.SET_PLAYING_URI] = (state, action) => {
|
||||||
if (action.data.uri === null) {
|
if (action.data.uri === null) {
|
||||||
|
|
|
@ -1,187 +0,0 @@
|
||||||
import * as ACTIONS from 'constants/action_types';
|
|
||||||
|
|
||||||
const reducers = {};
|
|
||||||
|
|
||||||
const defaultState = {};
|
|
||||||
|
|
||||||
reducers[ACTIONS.RESOLVE_URIS_COMPLETED] = (state, action) => {
|
|
||||||
const { resolveInfo } = action.data;
|
|
||||||
const byUri = Object.assign({}, state.claimsByUri);
|
|
||||||
const byId = Object.assign({}, state.byId);
|
|
||||||
|
|
||||||
Object.entries(resolveInfo).forEach(([uri, { certificate, claim }]) => {
|
|
||||||
if (claim) {
|
|
||||||
byId[claim.claim_id] = claim;
|
|
||||||
byUri[uri] = claim.claim_id;
|
|
||||||
} else if (claim === undefined && certificate !== undefined) {
|
|
||||||
byId[certificate.claim_id] = certificate;
|
|
||||||
// Don't point URI at the channel certificate unless it actually is
|
|
||||||
// a channel URI. This is brittle.
|
|
||||||
if (!uri.split(certificate.name)[1].match(/\//)) {
|
|
||||||
byUri[uri] = certificate.claim_id;
|
|
||||||
} else {
|
|
||||||
byUri[uri] = null;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
byUri[uri] = null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return Object.assign({}, state, {
|
|
||||||
byId,
|
|
||||||
claimsByUri: byUri,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
reducers[ACTIONS.FETCH_CLAIM_LIST_MINE_STARTED] = state =>
|
|
||||||
Object.assign({}, state, {
|
|
||||||
isFetchingClaimListMine: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
reducers[ACTIONS.FETCH_CLAIM_LIST_MINE_COMPLETED] = (state, action) => {
|
|
||||||
const { claims } = action.data;
|
|
||||||
const byId = Object.assign({}, state.byId);
|
|
||||||
const pendingById = Object.assign({}, state.pendingById);
|
|
||||||
|
|
||||||
claims
|
|
||||||
.filter(
|
|
||||||
claim => claim.category && (claim.category.match(/claim/) || claim.category.match(/update/))
|
|
||||||
)
|
|
||||||
.forEach(claim => {
|
|
||||||
byId[claim.claim_id] = claim;
|
|
||||||
|
|
||||||
const pending = Object.values(pendingById).find(
|
|
||||||
pendingClaim =>
|
|
||||||
pendingClaim.name === claim.name && pendingClaim.channel_name === claim.channel_name
|
|
||||||
);
|
|
||||||
|
|
||||||
if (pending) {
|
|
||||||
delete pendingById[pending.claim_id];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Remove old timed out pending publishes
|
|
||||||
Object.values(pendingById)
|
|
||||||
.filter(pendingClaim => Date.now() - pendingClaim.time >= 20 * 60 * 1000)
|
|
||||||
.forEach(pendingClaim => {
|
|
||||||
delete pendingById[pendingClaim.claim_id];
|
|
||||||
});
|
|
||||||
|
|
||||||
return Object.assign({}, state, {
|
|
||||||
isFetchingClaimListMine: false,
|
|
||||||
myClaims: claims,
|
|
||||||
byId,
|
|
||||||
pendingById,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
reducers[ACTIONS.FETCH_CHANNEL_LIST_STARTED] = state =>
|
|
||||||
Object.assign({}, state, { fetchingMyChannels: true });
|
|
||||||
|
|
||||||
reducers[ACTIONS.FETCH_CHANNEL_LIST_COMPLETED] = (state, action) => {
|
|
||||||
const { claims } = action.data;
|
|
||||||
const myChannelClaims = new Set(state.myChannelClaims);
|
|
||||||
const byId = Object.assign({}, state.byId);
|
|
||||||
|
|
||||||
claims.forEach(claim => {
|
|
||||||
myChannelClaims.add(claim.claim_id);
|
|
||||||
byId[claims.claim_id] = claim;
|
|
||||||
});
|
|
||||||
|
|
||||||
return Object.assign({}, state, {
|
|
||||||
byId,
|
|
||||||
fetchingMyChannels: false,
|
|
||||||
myChannelClaims,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
reducers[ACTIONS.FETCH_CHANNEL_CLAIMS_STARTED] = (state, action) => {
|
|
||||||
const { uri, page } = action.data;
|
|
||||||
const fetchingChannelClaims = Object.assign({}, state.fetchingChannelClaims);
|
|
||||||
|
|
||||||
fetchingChannelClaims[uri] = page;
|
|
||||||
|
|
||||||
return Object.assign({}, state, {
|
|
||||||
fetchingChannelClaims,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
reducers[ACTIONS.FETCH_CHANNEL_CLAIMS_COMPLETED] = (state, action) => {
|
|
||||||
const { uri, claims, page } = action.data;
|
|
||||||
|
|
||||||
const claimsByChannel = Object.assign({}, state.claimsByChannel);
|
|
||||||
const byChannel = Object.assign({}, claimsByChannel[uri]);
|
|
||||||
const allClaimIds = new Set(byChannel.all);
|
|
||||||
const currentPageClaimIds = [];
|
|
||||||
const byId = Object.assign({}, state.byId);
|
|
||||||
const fetchingChannelClaims = Object.assign({}, state.fetchingChannelClaims);
|
|
||||||
|
|
||||||
if (claims !== undefined) {
|
|
||||||
claims.forEach(claim => {
|
|
||||||
allClaimIds.add(claim.claim_id);
|
|
||||||
currentPageClaimIds.push(claim.claim_id);
|
|
||||||
byId[claim.claim_id] = claim;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
byChannel.all = allClaimIds;
|
|
||||||
byChannel[page] = currentPageClaimIds;
|
|
||||||
claimsByChannel[uri] = byChannel;
|
|
||||||
delete fetchingChannelClaims[uri];
|
|
||||||
|
|
||||||
return Object.assign({}, state, {
|
|
||||||
claimsByChannel,
|
|
||||||
byId,
|
|
||||||
fetchingChannelClaims,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
reducers[ACTIONS.ABANDON_CLAIM_STARTED] = (state, action) => {
|
|
||||||
const { claimId } = action.data;
|
|
||||||
const abandoningById = Object.assign({}, state.abandoningById);
|
|
||||||
|
|
||||||
abandoningById[claimId] = true;
|
|
||||||
|
|
||||||
return Object.assign({}, state, {
|
|
||||||
abandoningById,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
reducers[ACTIONS.ABANDON_CLAIM_SUCCEEDED] = (state, action) => {
|
|
||||||
const { claimId } = action.data;
|
|
||||||
const byId = Object.assign({}, state.byId);
|
|
||||||
const claimsByUri = Object.assign({}, state.claimsByUri);
|
|
||||||
|
|
||||||
Object.keys(claimsByUri).forEach(uri => {
|
|
||||||
if (claimsByUri[uri] === claimId) {
|
|
||||||
delete claimsByUri[uri];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
delete byId[claimId];
|
|
||||||
|
|
||||||
return Object.assign({}, state, {
|
|
||||||
byId,
|
|
||||||
claimsByUri,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
reducers[ACTIONS.CREATE_CHANNEL_COMPLETED] = (state, action) => {
|
|
||||||
const { channelClaim } = action.data;
|
|
||||||
const byId = Object.assign({}, state.byId);
|
|
||||||
const myChannelClaims = new Set(state.myChannelClaims);
|
|
||||||
|
|
||||||
byId[channelClaim.claim_id] = channelClaim;
|
|
||||||
myChannelClaims.add(channelClaim.claim_id);
|
|
||||||
|
|
||||||
return Object.assign({}, state, {
|
|
||||||
byId,
|
|
||||||
myChannelClaims,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export default function reducer(state = defaultState, action) {
|
|
||||||
const handler = reducers[action.type];
|
|
||||||
if (handler) return handler(state, action);
|
|
||||||
return state;
|
|
||||||
}
|
|
|
@ -1,34 +0,0 @@
|
||||||
import * as ACTIONS from 'constants/action_types';
|
|
||||||
|
|
||||||
const reducers = {};
|
|
||||||
const defaultState = {};
|
|
||||||
|
|
||||||
reducers[ACTIONS.FETCH_COST_INFO_STARTED] = (state, action) => {
|
|
||||||
const { uri } = action.data;
|
|
||||||
const newFetching = Object.assign({}, state.fetching);
|
|
||||||
newFetching[uri] = true;
|
|
||||||
|
|
||||||
return Object.assign({}, state, {
|
|
||||||
fetching: newFetching,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
reducers[ACTIONS.FETCH_COST_INFO_COMPLETED] = (state, action) => {
|
|
||||||
const { uri, costInfo } = action.data;
|
|
||||||
const newByUri = Object.assign({}, state.byUri);
|
|
||||||
const newFetching = Object.assign({}, state.fetching);
|
|
||||||
|
|
||||||
newByUri[uri] = costInfo;
|
|
||||||
delete newFetching[uri];
|
|
||||||
|
|
||||||
return Object.assign({}, state, {
|
|
||||||
byUri: newByUri,
|
|
||||||
fetching: newFetching,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export default function reducer(state = defaultState, action) {
|
|
||||||
const handler = reducers[action.type];
|
|
||||||
if (handler) return handler(state, action);
|
|
||||||
return state;
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue