Merge branch 'multi-resolve'
This commit is contained in:
commit
d6b86c0f07
13 changed files with 81 additions and 139 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));
|
||||
};
|
||||
|
||||
|
|
|
@ -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