Minor refactors in doResolveUri()
Add doResolveUris() Always call resolveUri() in FileTile and FileCard Before, these components would only try and resolve if claim info wasn't provided. Don't require uri param in lbry.resolve() It can now be "uris" instead, plus the error message about caching doesn't really apply anymore. Don't cache/cancel open resolve requests No longer needed because we're not doing resolve requests in bulk Add support for multiple URI resolution in lbry.resolve() Handle multi URL resolves with one action Update CHANGELOG.md
This commit is contained in:
parent
80f1cac4e5
commit
c5c67a0de5
15 changed files with 89 additions and 153 deletions
|
@ -16,6 +16,7 @@ Web UI version numbers should always match the corresponding version of LBRY App
|
|||
* There is no longer a minimum channel length (#645)
|
||||
* Changed the File page to make it clearer how to to open the folder for a file
|
||||
* The upgrade message is now friendlier and includes a link to the release notes.
|
||||
* Improved Discover page load time by batching all URIs into one API call
|
||||
|
||||
### Fixed
|
||||
* Improve layout (and implementation) of the icon panel in file tiles and cards
|
||||
|
|
|
@ -24,68 +24,46 @@ const { ipcRenderer } = require("electron");
|
|||
|
||||
const DOWNLOAD_POLL_INTERVAL = 250;
|
||||
|
||||
export function doResolveUri(uri) {
|
||||
export function doResolveUris(uris) {
|
||||
return function(dispatch, getState) {
|
||||
uri = lbryuri.normalize(uri);
|
||||
|
||||
uris = uris.map(lbryuri.normalize);
|
||||
const state = getState();
|
||||
const alreadyResolving = selectResolvingUris(state).indexOf(uri) !== -1;
|
||||
|
||||
if (!alreadyResolving) {
|
||||
dispatch({
|
||||
type: types.RESOLVE_URI_STARTED,
|
||||
data: { uri },
|
||||
});
|
||||
|
||||
lbry.resolve({ uri }).then(resolutionInfo => {
|
||||
const { claim, certificate } = resolutionInfo
|
||||
? resolutionInfo
|
||||
: { claim: null, certificate: null };
|
||||
|
||||
dispatch({
|
||||
type: types.RESOLVE_URI_COMPLETED,
|
||||
data: {
|
||||
uri,
|
||||
claim,
|
||||
certificate,
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function doCancelResolveUri(uri) {
|
||||
return function(dispatch, getState) {
|
||||
uri = lbryuri.normalize(uri);
|
||||
|
||||
const state = getState();
|
||||
const alreadyResolving = selectResolvingUris(state).indexOf(uri) !== -1;
|
||||
|
||||
if (alreadyResolving) {
|
||||
lbry.cancelResolve({ uri });
|
||||
dispatch({
|
||||
type: types.RESOLVE_URI_CANCELED,
|
||||
data: {
|
||||
uri,
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function doCancelAllResolvingUris() {
|
||||
return function(dispatch, getState) {
|
||||
const state = getState();
|
||||
// Filter out URIs that are already resolving
|
||||
const resolvingUris = selectResolvingUris(state);
|
||||
const actions = [];
|
||||
const urisToResolve = uris.filter(uri => !resolvingUris.includes(uri));
|
||||
|
||||
resolvingUris.forEach(uri => actions.push(doCancelResolveUri(uri)));
|
||||
if (urisToResolve.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch(batchActions(...actions));
|
||||
dispatch({
|
||||
type: types.RESOLVE_URIS_STARTED,
|
||||
data: { uris },
|
||||
});
|
||||
|
||||
let resolveInfo = {};
|
||||
lbry.resolve({ uris: urisToResolve }).then(result => {
|
||||
for (let [uri, uriResolveInfo] of Object.entries(result)) {
|
||||
const { claim, certificate } = uriResolveInfo || {
|
||||
claim: null,
|
||||
certificate: null,
|
||||
};
|
||||
resolveInfo[uri] = { claim, certificate };
|
||||
}
|
||||
|
||||
dispatch({
|
||||
type: types.RESOLVE_URIS_COMPLETED,
|
||||
data: { resolveInfo },
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function doResolveUri(uri) {
|
||||
return doResolveUris([uri]);
|
||||
}
|
||||
|
||||
export function doFetchFeaturedUris() {
|
||||
return function(dispatch, getState) {
|
||||
const state = getState();
|
||||
|
@ -96,28 +74,27 @@ export function doFetchFeaturedUris() {
|
|||
|
||||
const success = ({ Categories, Uris }) => {
|
||||
let featuredUris = {};
|
||||
const actions = [];
|
||||
|
||||
let urisToResolve = [];
|
||||
Categories.forEach(category => {
|
||||
if (Uris[category] && Uris[category].length) {
|
||||
const uris = Uris[category];
|
||||
|
||||
featuredUris[category] = uris;
|
||||
uris.forEach(uri => {
|
||||
actions.push(doResolveUri(uri));
|
||||
});
|
||||
urisToResolve = [...urisToResolve, ...uris];
|
||||
}
|
||||
});
|
||||
|
||||
actions.push({
|
||||
type: types.FETCH_FEATURED_CONTENT_COMPLETED,
|
||||
data: {
|
||||
categories: Categories,
|
||||
uris: featuredUris,
|
||||
success: true,
|
||||
const actions = [
|
||||
doResolveUris(urisToResolve),
|
||||
{
|
||||
type: types.FETCH_FEATURED_CONTENT_COMPLETED,
|
||||
data: {
|
||||
categories: Categories,
|
||||
uris: featuredUris,
|
||||
success: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
];
|
||||
dispatch(batchActions(...actions));
|
||||
};
|
||||
|
||||
|
|
|
@ -20,19 +20,13 @@ class FileCard extends React.PureComponent {
|
|||
}
|
||||
|
||||
componentWillMount() {
|
||||
this.resolve(this.props);
|
||||
const { uri, resolveUri } = this.props;
|
||||
resolveUri(uri);
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
this.resolve(nextProps);
|
||||
}
|
||||
|
||||
resolve(props) {
|
||||
const { isResolvingUri, resolveUri, claim, uri } = props;
|
||||
|
||||
if (!isResolvingUri && claim === undefined && uri) {
|
||||
resolveUri(uri);
|
||||
}
|
||||
const { uri, resolveUri } = nextProps;
|
||||
resolveUri(uri);
|
||||
}
|
||||
|
||||
handleMouseOver() {
|
||||
|
|
|
@ -26,15 +26,15 @@ class FileTile extends React.PureComponent {
|
|||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { isResolvingUri, claim, uri, resolveUri } = this.props;
|
||||
const { uri, resolveUri } = this.props;
|
||||
|
||||
if (!isResolvingUri && !claim && uri) resolveUri(uri);
|
||||
resolveUri(uri);
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
const { isResolvingUri, claim, uri, resolveUri } = this.props;
|
||||
const { uri, resolveUri } = this.props;
|
||||
|
||||
if (!isResolvingUri && claim === undefined && uri) resolveUri(uri);
|
||||
resolveUri(uri);
|
||||
}
|
||||
|
||||
handleMouseOver() {
|
||||
|
|
|
@ -47,9 +47,8 @@ export const SUPPORT_TRANSACTION_FAILED = "SUPPORT_TRANSACTION_FAILED";
|
|||
export const FETCH_FEATURED_CONTENT_STARTED = "FETCH_FEATURED_CONTENT_STARTED";
|
||||
export const FETCH_FEATURED_CONTENT_COMPLETED =
|
||||
"FETCH_FEATURED_CONTENT_COMPLETED";
|
||||
export const RESOLVE_URI_STARTED = "RESOLVE_URI_STARTED";
|
||||
export const RESOLVE_URI_COMPLETED = "RESOLVE_URI_COMPLETED";
|
||||
export const RESOLVE_URI_CANCELED = "RESOLVE_URI_CANCELED";
|
||||
export const RESOLVE_URIS_STARTED = "RESOLVE_URIS_STARTED";
|
||||
export const RESOLVE_URIS_COMPLETED = "RESOLVE_URIS_COMPLETED";
|
||||
export const FETCH_CHANNEL_CLAIMS_STARTED = "FETCH_CHANNEL_CLAIMS_STARTED";
|
||||
export const FETCH_CHANNEL_CLAIMS_COMPLETED = "FETCH_CHANNEL_CLAIMS_COMPLETED";
|
||||
export const FETCH_CHANNEL_CLAIM_COUNT_STARTED =
|
||||
|
|
|
@ -311,30 +311,24 @@ lbry.claim_list_mine = function(params = {}) {
|
|||
});
|
||||
};
|
||||
|
||||
lbry._resolveXhrs = {};
|
||||
lbry.resolve = function(params = {}) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!params.uri) {
|
||||
throw __("Resolve has hacked cache on top of it that requires a URI");
|
||||
}
|
||||
lbry._resolveXhrs[params.uri] = apiCall(
|
||||
apiCall(
|
||||
"resolve",
|
||||
params,
|
||||
function(data) {
|
||||
resolve(data && data[params.uri] ? data[params.uri] : {});
|
||||
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
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
lbry.cancelResolve = function(params = {}) {
|
||||
const xhr = lbry._resolveXhrs[params.uri];
|
||||
if (xhr && xhr.readyState > 0 && xhr.readyState < 4) {
|
||||
xhr.abort();
|
||||
}
|
||||
};
|
||||
|
||||
lbry = new Proxy(lbry, {
|
||||
get: function(target, name) {
|
||||
if (name in target) {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { doFetchFeaturedUris, doCancelAllResolvingUris } from "actions/content";
|
||||
import { doFetchFeaturedUris } from "actions/content";
|
||||
import {
|
||||
selectFeaturedUris,
|
||||
selectFetchingFeaturedUris,
|
||||
|
@ -14,7 +14,6 @@ const select = state => ({
|
|||
|
||||
const perform = dispatch => ({
|
||||
fetchFeaturedUris: () => dispatch(doFetchFeaturedUris()),
|
||||
cancelResolvingUris: () => dispatch(doCancelAllResolvingUris()),
|
||||
});
|
||||
|
||||
export default connect(select, perform)(DiscoverPage);
|
||||
|
|
|
@ -204,10 +204,6 @@ class DiscoverPage extends React.PureComponent {
|
|||
this.props.fetchFeaturedUris();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.props.cancelResolvingUris();
|
||||
}
|
||||
|
||||
render() {
|
||||
const { featuredUris, fetchingFeaturedUris } = this.props;
|
||||
const hasContent =
|
||||
|
|
|
@ -11,7 +11,6 @@ import {
|
|||
} from "selectors/claims";
|
||||
import { doFetchClaimListMine } from "actions/content";
|
||||
import { doNavigate } from "actions/navigation";
|
||||
import { doCancelAllResolvingUris } from "actions/content";
|
||||
import FileListDownloaded from "./view";
|
||||
|
||||
const select = state => ({
|
||||
|
@ -25,7 +24,6 @@ const perform = dispatch => ({
|
|||
navigate: path => dispatch(doNavigate(path)),
|
||||
fetchFileInfosDownloaded: () =>
|
||||
dispatch(doFetchFileInfosAndPublishedClaims()),
|
||||
cancelResolvingUris: () => dispatch(doCancelAllResolvingUris()),
|
||||
fetchClaims: () => dispatch(doFetchClaimListMine()),
|
||||
});
|
||||
|
||||
|
|
|
@ -11,10 +11,6 @@ class FileListDownloaded extends React.PureComponent {
|
|||
if (!this.props.isFetching) this.props.fetchFileInfosDownloaded();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.props.cancelResolvingUris();
|
||||
}
|
||||
|
||||
render() {
|
||||
const { fileInfos, isFetching, navigate } = this.props;
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@ import {
|
|||
} from "selectors/claims";
|
||||
import { doClaimRewardType } from "actions/rewards";
|
||||
import { doNavigate } from "actions/navigation";
|
||||
import { doCancelAllResolvingUris } from "actions/content";
|
||||
import FileListPublished from "./view";
|
||||
|
||||
const select = state => ({
|
||||
|
@ -21,7 +20,6 @@ const perform = dispatch => ({
|
|||
fetchClaims: () => dispatch(doFetchClaimListMine()),
|
||||
claimFirstPublishReward: () =>
|
||||
dispatch(doClaimRewardType(rewards.TYPE_FIRST_PUBLISH)),
|
||||
cancelResolvingUris: () => dispatch(doCancelAllResolvingUris()),
|
||||
});
|
||||
|
||||
export default connect(select, perform)(FileListPublished);
|
||||
|
|
|
@ -14,10 +14,6 @@ class FileListPublished extends React.PureComponent {
|
|||
// if (this.props.claims.length > 0) this.props.fetchClaims();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.props.cancelResolvingUris();
|
||||
}
|
||||
|
||||
render() {
|
||||
const { claims, isFetching, navigate } = this.props;
|
||||
|
||||
|
|
|
@ -6,17 +6,15 @@ import FilePage from "page/file";
|
|||
|
||||
class ShowPage extends React.PureComponent {
|
||||
componentWillMount() {
|
||||
const { isResolvingUri, resolveUri, uri } = this.props;
|
||||
const { resolveUri, uri } = this.props;
|
||||
|
||||
if (!isResolvingUri) resolveUri(uri);
|
||||
resolveUri(uri);
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
const { isResolvingUri, resolveUri, claim, uri } = nextProps;
|
||||
const { resolveUri, uri } = nextProps;
|
||||
|
||||
if (!isResolvingUri && claim === undefined && uri) {
|
||||
resolveUri(uri);
|
||||
}
|
||||
resolveUri(uri);
|
||||
}
|
||||
|
||||
render() {
|
||||
|
|
|
@ -4,26 +4,27 @@ const reducers = {};
|
|||
|
||||
const defaultState = {};
|
||||
|
||||
reducers[types.RESOLVE_URI_COMPLETED] = function(state, action) {
|
||||
const { uri, certificate, claim } = action.data;
|
||||
|
||||
reducers[types.RESOLVE_URIS_COMPLETED] = function(state, action) {
|
||||
const { resolveInfo } = action.data;
|
||||
const byUri = Object.assign({}, state.claimsByUri);
|
||||
const byId = Object.assign({}, state.byId);
|
||||
|
||||
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;
|
||||
for (let [uri, { certificate, claim }] of Object.entries(resolveInfo)) {
|
||||
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;
|
||||
}
|
||||
} else {
|
||||
byUri[uri] = null;
|
||||
}
|
||||
|
||||
return Object.assign({}, state, {
|
||||
|
|
|
@ -31,34 +31,23 @@ reducers[types.FETCH_REWARD_CONTENT_COMPLETED] = function(state, action) {
|
|||
});
|
||||
};
|
||||
|
||||
reducers[types.RESOLVE_URI_STARTED] = function(state, action) {
|
||||
const { uri } = action.data;
|
||||
reducers[types.RESOLVE_URIS_STARTED] = function(state, action) {
|
||||
let { uris } = action.data;
|
||||
|
||||
const oldResolving = state.resolvingUris || [];
|
||||
const newResolving = Object.assign([], oldResolving);
|
||||
if (newResolving.indexOf(uri) === -1) newResolving.push(uri);
|
||||
|
||||
for (let uri of uris) {
|
||||
if (!newResolving.includes(uri)) {
|
||||
newResolving.push(uri);
|
||||
}
|
||||
}
|
||||
|
||||
return Object.assign({}, state, {
|
||||
resolvingUris: newResolving,
|
||||
});
|
||||
};
|
||||
|
||||
reducers[types.RESOLVE_URI_CANCELED] = reducers[
|
||||
types.RESOLVE_URI_COMPLETED
|
||||
] = function(state, action) {
|
||||
const { uri } = action.data;
|
||||
const resolvingUris = state.resolvingUris;
|
||||
const index = state.resolvingUris.indexOf(uri);
|
||||
const newResolvingUris = [
|
||||
...resolvingUris.slice(0, index),
|
||||
...resolvingUris.slice(index + 1),
|
||||
];
|
||||
|
||||
return Object.assign({}, state, {
|
||||
resolvingUris: newResolvingUris,
|
||||
});
|
||||
};
|
||||
|
||||
reducers[types.SET_PLAYING_URI] = (state, action) => {
|
||||
return Object.assign({}, state, {
|
||||
playingUri: action.data.uri,
|
||||
|
|
Loading…
Add table
Reference in a new issue