feat: lazy resolve homepage claims
This commit is contained in:
parent
b5d7a2b884
commit
25923505a0
8 changed files with 103 additions and 91 deletions
|
@ -52,7 +52,7 @@
|
|||
"hast-util-sanitize": "^1.1.2",
|
||||
"keytar": "^4.2.1",
|
||||
"lbry-format": "https://github.com/lbryio/lbry-format.git",
|
||||
"lbry-redux": "lbryio/lbry-redux#973bbd780a774ba48f4e22861b6accb706cf3835",
|
||||
"lbry-redux": "lbryio/lbry-redux#aa112ef90e6e5aa37795b349e2bbd6bd6c561d53",
|
||||
"lbryinc": "lbryio/lbryinc#83c275da7a44f346ce9e796d06f30126f02b4c63",
|
||||
"localforage": "^1.7.1",
|
||||
"mammoth": "^1.4.6",
|
||||
|
|
|
@ -1,20 +1,24 @@
|
|||
import { connect } from 'react-redux';
|
||||
import { doFetchClaimsByChannel } from 'redux/actions/content';
|
||||
import { makeSelectCategoryListUris } from 'redux/selectors/content';
|
||||
import {
|
||||
makeSelectClaimsInChannelForCurrentPage,
|
||||
makeSelectFetchingChannelClaims,
|
||||
doResolveUris,
|
||||
selectActiveHistoryEntry,
|
||||
} from 'lbry-redux';
|
||||
import { selectShowNsfw } from 'redux/selectors/settings';
|
||||
import CategoryList from './view';
|
||||
|
||||
const select = (state, props) => ({
|
||||
channelClaims: makeSelectClaimsInChannelForCurrentPage(props.categoryLink)(state),
|
||||
urisInList: makeSelectCategoryListUris(props.uris, props.categoryLink)(state),
|
||||
fetching: makeSelectFetchingChannelClaims(props.categoryLink)(state),
|
||||
obscureNsfw: !selectShowNsfw(state),
|
||||
currentPageAttributes: selectActiveHistoryEntry(state),
|
||||
});
|
||||
|
||||
const perform = dispatch => ({
|
||||
fetchChannel: channel => dispatch(doFetchClaimsByChannel(channel)),
|
||||
resolveUris: uris => dispatch(doResolveUris(uris, true)),
|
||||
});
|
||||
|
||||
export default connect(
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
// @flow
|
||||
import type { Claim } from 'types/claim';
|
||||
import * as ICONS from 'constants/icons';
|
||||
import React, { PureComponent, createRef } from 'react';
|
||||
import { normalizeURI } from 'lbry-redux';
|
||||
|
@ -11,12 +10,13 @@ import throttle from 'util/throttle';
|
|||
|
||||
type Props = {
|
||||
category: string,
|
||||
names: ?Array<string>,
|
||||
categoryLink: ?string,
|
||||
fetching: boolean,
|
||||
channelClaims: ?Array<Claim>,
|
||||
fetchChannel: string => void,
|
||||
obscureNsfw: boolean,
|
||||
currentPageAttributes: { scrollY: number },
|
||||
fetchChannel: string => void,
|
||||
urisInList: ?Array<string>,
|
||||
resolveUris: (Array<string>) => void,
|
||||
};
|
||||
|
||||
type State = {
|
||||
|
@ -26,9 +26,11 @@ type State = {
|
|||
|
||||
class CategoryList extends PureComponent<Props, State> {
|
||||
static defaultProps = {
|
||||
categoryLink: '',
|
||||
categoryLink: undefined,
|
||||
};
|
||||
|
||||
scrollWrapper: { current: null | HTMLUListElement };
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
|
@ -40,23 +42,55 @@ class CategoryList extends PureComponent<Props, State> {
|
|||
(this: any).handleScrollNext = this.handleScrollNext.bind(this);
|
||||
(this: any).handleScrollPrevious = this.handleScrollPrevious.bind(this);
|
||||
(this: any).handleArrowButtonsOnScroll = this.handleArrowButtonsOnScroll.bind(this);
|
||||
(this: any).handleResolveOnScroll = this.handleResolveOnScroll.bind(this);
|
||||
|
||||
this.scrollWrapper = createRef();
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { fetching, categoryLink, fetchChannel } = this.props;
|
||||
if (!fetching && categoryLink) {
|
||||
const { fetching, categoryLink, fetchChannel, resolveUris, urisInList } = this.props;
|
||||
if (!fetching && categoryLink && (!urisInList || urisInList.length)) {
|
||||
// Only fetch the channels claims if no urisInList are specifically passed in
|
||||
// This allows setting a channel link and and passing in a custom list of urisInList (featured content usually works this way)
|
||||
fetchChannel(categoryLink);
|
||||
}
|
||||
|
||||
const scrollWrapper = this.scrollWrapper.current;
|
||||
if (scrollWrapper) {
|
||||
scrollWrapper.addEventListener('scroll', throttle(this.handleArrowButtonsOnScroll, 500));
|
||||
|
||||
if (urisInList && window.innerHeight > scrollWrapper.offsetTop) {
|
||||
resolveUris(urisInList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
scrollWrapper: { current: null | HTMLUListElement };
|
||||
componentDidUpdate(prevProps: Props) {
|
||||
const { scrollY: previousScrollY } = prevProps.currentPageAttributes;
|
||||
const { scrollY } = this.props.currentPageAttributes;
|
||||
|
||||
if (scrollY > previousScrollY) {
|
||||
this.handleResolveOnScroll();
|
||||
}
|
||||
}
|
||||
|
||||
handleResolveOnScroll() {
|
||||
const {
|
||||
urisInList,
|
||||
resolveUris,
|
||||
currentPageAttributes: { scrollY },
|
||||
} = this.props;
|
||||
|
||||
const scrollWrapper = this.scrollWrapper.current;
|
||||
if (!scrollWrapper) {
|
||||
return;
|
||||
}
|
||||
|
||||
const shouldResolve = window.innerHeight > scrollWrapper.offsetTop - scrollY;
|
||||
if (shouldResolve && urisInList) {
|
||||
resolveUris(urisInList);
|
||||
}
|
||||
}
|
||||
|
||||
handleArrowButtonsOnScroll() {
|
||||
// Determine if the arrow buttons should be disabled
|
||||
|
@ -212,7 +246,7 @@ class CategoryList extends PureComponent<Props, State> {
|
|||
}
|
||||
|
||||
render() {
|
||||
const { category, categoryLink, names, channelClaims, obscureNsfw } = this.props;
|
||||
const { category, categoryLink, urisInList, obscureNsfw } = this.props;
|
||||
const { canScrollNext, canScrollPrevious } = this.state;
|
||||
const isCommunityTopBids = category.match(/^community/i);
|
||||
const showScrollButtons = isCommunityTopBids ? !obscureNsfw : true;
|
||||
|
@ -273,41 +307,18 @@ class CategoryList extends PureComponent<Props, State> {
|
|||
</p>
|
||||
) : (
|
||||
<ul className="media-scrollhouse" ref={this.scrollWrapper}>
|
||||
{/*
|
||||
`names` and `channelClaims` should be combined
|
||||
it's set up to take a list of names (uris) to show as cards
|
||||
or a channel link, which it uses for fetch a list of names
|
||||
having both makes it really confusing
|
||||
|
||||
will come back to this once we determine how we will receive channel links
|
||||
from the homepage uris api call
|
||||
- sean
|
||||
*/}
|
||||
{names &&
|
||||
!!names.length &&
|
||||
names.map(name => (
|
||||
<FileCard showSubscribedLogo key={name} uri={normalizeURI(name)} />
|
||||
))}
|
||||
|
||||
{(!names || !names.length) &&
|
||||
channelClaims &&
|
||||
channelClaims.length &&
|
||||
channelClaims
|
||||
// Only show the first 10 claims, regardless of the amount we have on a channel page
|
||||
.slice(0, 10)
|
||||
.map(claim => (
|
||||
{urisInList &&
|
||||
urisInList.map(uri => (
|
||||
<FileCard
|
||||
showSubcribedLogo
|
||||
key={claim.claim_id}
|
||||
uri={`lbry://${claim.name}#${claim.claim_id}`}
|
||||
placeholder
|
||||
preventResolve
|
||||
showSubscribedLogo
|
||||
key={uri}
|
||||
uri={normalizeURI(uri)}
|
||||
/>
|
||||
))}
|
||||
{/*
|
||||
If there aren't any uris passed in, create an empty array and render placeholder cards
|
||||
channelClaims or names are being fetched
|
||||
*/}
|
||||
{!channelClaims &&
|
||||
!names &&
|
||||
|
||||
{!urisInList &&
|
||||
/* eslint-disable react/no-array-index-key */
|
||||
new Array(10).fill(1).map((x, i) => <FileCard placeholder key={i} />)
|
||||
/* eslint-enable react/no-array-index-key */
|
||||
|
|
|
@ -29,19 +29,25 @@ type Props = {
|
|||
isSubscribed: boolean,
|
||||
isNew: boolean,
|
||||
placeholder: boolean,
|
||||
preventResolve: boolean,
|
||||
};
|
||||
|
||||
class FileCard extends React.PureComponent<Props> {
|
||||
static defaultProps = {
|
||||
placeholder: false,
|
||||
preventResolve: false,
|
||||
};
|
||||
|
||||
componentWillMount() {
|
||||
componentDidMount() {
|
||||
if (!this.props.preventResolve) {
|
||||
this.resolve(this.props);
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps: Props) {
|
||||
this.resolve(nextProps);
|
||||
componentDidUpdate() {
|
||||
if (!this.props.preventResolve) {
|
||||
this.resolve(this.props);
|
||||
}
|
||||
}
|
||||
|
||||
resolve = (props: Props) => {
|
||||
|
@ -74,7 +80,7 @@ class FileCard extends React.PureComponent<Props> {
|
|||
return null;
|
||||
}
|
||||
|
||||
if ((!claim && !pending) || placeholder) {
|
||||
if (!claim && (!pending || placeholder)) {
|
||||
return (
|
||||
<li className="media-card media--placeholder">
|
||||
<div className="media__thumb media__thumb--placeholder" />
|
||||
|
|
|
@ -9,7 +9,7 @@ const select = state => ({
|
|||
});
|
||||
|
||||
const perform = dispatch => ({
|
||||
fetchFeaturedUris: () => dispatch(doFetchFeaturedUris()),
|
||||
fetchFeaturedUris: () => dispatch(doFetchFeaturedUris(true)),
|
||||
fetchRewardedContent: () => dispatch(doFetchRewardedContent()),
|
||||
fetchRewards: () => dispatch(doRewardList()),
|
||||
});
|
||||
|
|
|
@ -68,7 +68,7 @@ class DiscoverPage extends React.PureComponent<Props> {
|
|||
<CategoryList
|
||||
key={category}
|
||||
category={this.trimClaimIdFromCategory(category)}
|
||||
names={featuredUris[category]}
|
||||
uris={featuredUris[category]}
|
||||
categoryLink={this.getCategoryLinkPartByCategory(category)}
|
||||
/>
|
||||
))}
|
||||
|
|
|
@ -1,8 +1,13 @@
|
|||
// @flow
|
||||
import { createSelector } from 'reselect';
|
||||
import { makeSelectClaimForUri, selectClaimsByUri } from 'lbry-redux';
|
||||
import {
|
||||
makeSelectClaimForUri,
|
||||
selectClaimsByUri,
|
||||
makeSelectClaimsInChannelForCurrentPage,
|
||||
} from 'lbry-redux';
|
||||
import { HISTORY_ITEMS_PER_PAGE } from 'constants/content';
|
||||
|
||||
export const selectState = state => state.content || {};
|
||||
export const selectState = (state: any) => state.content || {};
|
||||
|
||||
export const selectPlayingUri = createSelector(selectState, state => state.playingUri);
|
||||
|
||||
|
@ -11,7 +16,7 @@ export const selectChannelClaimCounts = createSelector(
|
|||
state => state.channelClaimCounts || {}
|
||||
);
|
||||
|
||||
export const makeSelectTotalItemsForChannel = uri =>
|
||||
export const makeSelectTotalItemsForChannel = (uri: string) =>
|
||||
createSelector(selectChannelClaimCounts, byUri => byUri && byUri[uri]);
|
||||
|
||||
export const selectRewardContentClaimIds = createSelector(
|
||||
|
@ -19,7 +24,7 @@ export const selectRewardContentClaimIds = createSelector(
|
|||
state => state.rewardedContentClaimIds
|
||||
);
|
||||
|
||||
export const makeSelectContentPositionForUri = uri =>
|
||||
export const makeSelectContentPositionForUri = (uri: string) =>
|
||||
createSelector(selectState, makeSelectClaimForUri(uri), (state, claim) => {
|
||||
if (!claim) {
|
||||
return null;
|
||||
|
@ -33,7 +38,7 @@ export const selectHistoryPageCount = createSelector(selectState, state =>
|
|||
Math.ceil(state.history.length / HISTORY_ITEMS_PER_PAGE)
|
||||
);
|
||||
|
||||
export const makeSelectHistoryForPage = page =>
|
||||
export const makeSelectHistoryForPage = (page: number) =>
|
||||
createSelector(selectState, selectClaimsByUri, (state, claimsByUri) => {
|
||||
const left = page * HISTORY_ITEMS_PER_PAGE;
|
||||
const historyItems = state.history.slice(left, left + HISTORY_ITEMS_PER_PAGE);
|
||||
|
@ -51,5 +56,19 @@ export const makeSelectHistoryForPage = page =>
|
|||
});
|
||||
});
|
||||
|
||||
export const makeSelectHistoryForUri = uri =>
|
||||
export const makeSelectHistoryForUri = (uri: string) =>
|
||||
createSelector(selectState, state => state.history.find(i => i.uri === uri));
|
||||
|
||||
export const makeSelectCategoryListUris = (uris: Array<string> = [], channel: string) =>
|
||||
createSelector(makeSelectClaimsInChannelForCurrentPage(channel), channelClaims => {
|
||||
if (uris) return uris;
|
||||
|
||||
if (channelClaims) {
|
||||
const CATEGORY_LIST_SIZE = 10;
|
||||
return channelClaims
|
||||
.slice(0, CATEGORY_LIST_SIZE)
|
||||
.map(({ name, claim_id: claimId }) => `${name}#${claimId}`);
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
|
|
38
yarn.lock
38
yarn.lock
|
@ -1793,10 +1793,6 @@ center-align@^0.1.1:
|
|||
align-text "^0.1.3"
|
||||
lazy-cache "^1.0.3"
|
||||
|
||||
chain-function@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/chain-function/-/chain-function-1.0.0.tgz#0d4ab37e7e18ead0bdc47b920764118ce58733dc"
|
||||
|
||||
chainsaw@~0.1.0:
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/chainsaw/-/chainsaw-0.1.0.tgz#5eab50b28afe58074d0d58291388828b5e5fbc98"
|
||||
|
@ -2659,10 +2655,6 @@ dedent@^0.7.0:
|
|||
version "0.7.0"
|
||||
resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c"
|
||||
|
||||
deep-diff@^0.3.5:
|
||||
version "0.3.8"
|
||||
resolved "https://registry.yarnpkg.com/deep-diff/-/deep-diff-0.3.8.tgz#c01de63efb0eec9798801d40c7e0dae25b582c84"
|
||||
|
||||
deep-equal@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5"
|
||||
|
@ -2859,10 +2851,6 @@ dom-converter@~0.1:
|
|||
dependencies:
|
||||
utila "~0.3"
|
||||
|
||||
dom-helpers@^3.2.0:
|
||||
version "3.3.1"
|
||||
resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-3.3.1.tgz#fc1a4e15ffdf60ddde03a480a9c0fece821dd4a6"
|
||||
|
||||
dom-scroll-into-view@^1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/dom-scroll-into-view/-/dom-scroll-into-view-1.2.1.tgz#e8f36732dd089b0201a88d7815dc3f88e6d66c7e"
|
||||
|
@ -5691,9 +5679,9 @@ lbry-redux@lbryio/lbry-redux#84b7d396934d57a37802aadbef71db91230a9404:
|
|||
reselect "^3.0.0"
|
||||
uuid "^3.3.2"
|
||||
|
||||
lbry-redux@lbryio/lbry-redux#973bbd780a774ba48f4e22861b6accb706cf3835:
|
||||
lbry-redux@lbryio/lbry-redux#aa112ef90e6e5aa37795b349e2bbd6bd6c561d53:
|
||||
version "0.0.1"
|
||||
resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/973bbd780a774ba48f4e22861b6accb706cf3835"
|
||||
resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/aa112ef90e6e5aa37795b349e2bbd6bd6c561d53"
|
||||
dependencies:
|
||||
proxy-polyfill "0.1.6"
|
||||
reselect "^3.0.0"
|
||||
|
@ -7694,7 +7682,7 @@ promise@^7.0.3, promise@^7.1.1:
|
|||
dependencies:
|
||||
asap "~2.0.3"
|
||||
|
||||
prop-types@^15.5.10, prop-types@^15.5.6, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2:
|
||||
prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2:
|
||||
version "15.6.2"
|
||||
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.2.tgz#05d5ca77b4453e985d60fc7ff8c859094a497102"
|
||||
dependencies:
|
||||
|
@ -7891,7 +7879,7 @@ rc@^1.0.1, rc@^1.1.2, rc@^1.1.6, rc@^1.2.7:
|
|||
minimist "^1.2.0"
|
||||
strip-json-comments "~2.0.1"
|
||||
|
||||
react-dom@^16.5.0:
|
||||
react-dom@^16.6.0:
|
||||
version "16.7.0"
|
||||
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.7.0.tgz#a17b2a7ca89ee7390bc1ed5eb81783c7461748b8"
|
||||
dependencies:
|
||||
|
@ -7968,16 +7956,6 @@ react-toggle@^4.0.2:
|
|||
dependencies:
|
||||
classnames "^2.2.5"
|
||||
|
||||
react-transition-group@1.x:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-1.2.1.tgz#e11f72b257f921b213229a774df46612346c7ca6"
|
||||
dependencies:
|
||||
chain-function "^1.0.0"
|
||||
dom-helpers "^3.2.0"
|
||||
loose-envify "^1.3.1"
|
||||
prop-types "^15.5.6"
|
||||
warning "^3.0.0"
|
||||
|
||||
react@^0.14.5:
|
||||
version "0.14.9"
|
||||
resolved "https://registry.yarnpkg.com/react/-/react-0.14.9.tgz#9110a6497c49d44ba1c0edd317aec29c2e0d91d1"
|
||||
|
@ -7985,7 +7963,7 @@ react@^0.14.5:
|
|||
envify "^3.0.0"
|
||||
fbjs "^0.6.1"
|
||||
|
||||
react@^16.5.0:
|
||||
react@^16.6.0:
|
||||
version "16.7.0"
|
||||
resolved "https://registry.yarnpkg.com/react/-/react-16.7.0.tgz#b674ec396b0a5715873b350446f7ea0802ab6381"
|
||||
dependencies:
|
||||
|
@ -8128,12 +8106,6 @@ reduce-function-call@^1.0.1:
|
|||
dependencies:
|
||||
balanced-match "^0.4.2"
|
||||
|
||||
redux-logger@^3.0.1:
|
||||
version "3.0.6"
|
||||
resolved "https://registry.yarnpkg.com/redux-logger/-/redux-logger-3.0.6.tgz#f7555966f3098f3c88604c449cf0baf5778274bf"
|
||||
dependencies:
|
||||
deep-diff "^0.3.5"
|
||||
|
||||
redux-persist-transform-compress@^4.2.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/redux-persist-transform-compress/-/redux-persist-transform-compress-4.2.0.tgz#5089e299df7130878fca45f97ffe82888ba02690"
|
||||
|
|
Loading…
Reference in a new issue