lbry-desktop/ui/component/recommendedContent/view.jsx

207 lines
6.2 KiB
React
Raw Normal View History

// @flow
2021-06-22 18:33:18 +02:00
import { SHOW_ADS } from 'config';
import React from 'react';
import { useHistory } from 'react-router-dom';
import { v4 as uuidv4 } from 'uuid';
2019-06-19 07:05:43 +02:00
import ClaimList from 'component/claimList';
import ClaimListDiscover from 'component/claimListDiscover';
import Ads from 'web/component/ads';
2020-04-29 21:31:11 +02:00
import Card from 'component/common/card';
import { useIsMobile, useIsMediumScreen } from 'effects/use-screensize';
import Button from 'component/button';
2021-04-08 17:21:45 +02:00
import classnames from 'classnames';
import { CONTAINER_ID } from 'constants/navigation';
2021-04-08 17:21:45 +02:00
const VIEW_ALL_RELATED = 'view_all_related';
const VIEW_MORE_FROM = 'view_more_from';
type Props = {
uri: string,
2018-08-03 20:28:11 +02:00
recommendedContent: Array<string>,
nextRecommendedUri: string,
isSearching: boolean,
doFetchRecommendedContent: (string, boolean) => void,
2020-01-28 23:05:44 +01:00
mature: boolean,
2020-03-26 22:47:07 +01:00
isAuthenticated: boolean,
2021-04-08 17:21:45 +02:00
claim: ?StreamClaim,
doRecommendationUpdate: (claimId: string, urls: Array<string>, id: string, parentId: string) => void,
doRecommendationClicked: (claimId: string, index: number) => void,
};
export default React.memo<Props>(function RecommendedContent(props: Props) {
const {
uri,
doFetchRecommendedContent,
mature,
recommendedContent,
nextRecommendedUri,
isSearching,
isAuthenticated,
2021-04-08 17:21:45 +02:00
claim,
doRecommendationUpdate,
doRecommendationClicked,
} = props;
2021-04-08 17:21:45 +02:00
const [viewMode, setViewMode] = React.useState(VIEW_ALL_RELATED);
const [recommendationId, setRecommendationId] = React.useState('');
const [recommendationUrls, setRecommendationUrls] = React.useState();
const history = useHistory();
2021-04-08 17:21:45 +02:00
const signingChannel = claim && claim.signing_channel;
const channelName = signingChannel ? signingChannel.name : null;
const isMobile = useIsMobile();
const isMedium = useIsMediumScreen();
React.useEffect(() => {
function moveAutoplayNextItemToTop(recommendedContent) {
let newList = recommendedContent;
if (newList) {
const index = newList.indexOf(nextRecommendedUri);
if (index > 0) {
const a = newList[0];
newList[0] = nextRecommendedUri;
newList[index] = a;
}
}
return newList;
}
function listEq(prev, next) {
if (prev && next) {
return prev.length === next.length && prev.every((value, index) => value === next[index]);
} else {
return prev === next;
}
}
const newRecommendationUrls = moveAutoplayNextItemToTop(recommendedContent);
if (claim && !listEq(recommendationUrls, newRecommendationUrls)) {
const parentId = (history.location.state && history.location.state[CONTAINER_ID]) || '';
const id = uuidv4();
setRecommendationId(id);
setRecommendationUrls(newRecommendationUrls);
doRecommendationUpdate(claim.claim_id, newRecommendationUrls, id, parentId);
}
}, [
recommendedContent,
nextRecommendedUri,
recommendationUrls,
setRecommendationUrls,
claim,
doRecommendationUpdate,
history.location.state,
]);
React.useEffect(() => {
doFetchRecommendedContent(uri, mature);
}, [uri, mature, doFetchRecommendedContent]);
2018-08-09 18:41:14 +02:00
function handleRecommendationClicked(e: any, index: number) {
if (claim) {
doRecommendationClicked(claim.claim_id, index);
}
}
return (
<Card
isBodyList
smallTitle={!isMobile && !isMedium}
className="file-page__recommended"
title={__('Related')}
2021-04-08 17:21:45 +02:00
titleActions={
signingChannel && (
<div className="recommended-content__toggles">
<Button
className={classnames('button-toggle', {
'button-toggle--active': viewMode === VIEW_ALL_RELATED,
})}
label={__('All')}
onClick={() => setViewMode(VIEW_ALL_RELATED)}
/>
<Button
2021-04-08 17:21:45 +02:00
className={classnames('button-toggle', {
'button-toggle--active': viewMode === VIEW_MORE_FROM,
})}
label={__('More from %claim_name%', { claim_name: channelName })}
2021-04-08 17:21:45 +02:00
onClick={() => setViewMode(VIEW_MORE_FROM)}
/>
2021-04-08 17:21:45 +02:00
</div>
)
}
body={
<div>
2021-04-08 17:21:45 +02:00
{viewMode === VIEW_ALL_RELATED && (
<ClaimList
id={recommendationId}
type="small"
loading={isSearching}
uris={recommendationUrls}
hideMenu={isMobile}
2021-06-22 18:33:18 +02:00
injectedItem={SHOW_ADS && IS_WEB && !isAuthenticated && <Ads small type={'video'} />}
empty={__('No related content found')}
onClick={handleRecommendationClicked}
/>
)}
2021-04-08 17:21:45 +02:00
{viewMode === VIEW_MORE_FROM && signingChannel && (
<ClaimListDiscover
2021-04-08 17:21:45 +02:00
hideAdvancedFilter
tileLayout={false}
showHeader={false}
type="small"
claimType={['stream']}
orderBy="new"
pageSize={20}
infiniteScroll={false}
2021-04-08 17:21:45 +02:00
hideFilters
channelIds={[signingChannel.claim_id]}
loading={isSearching}
hideMenu={isMobile}
2021-06-22 18:33:18 +02:00
injectedItem={SHOW_ADS && IS_WEB && !isAuthenticated && <Ads small type={'video'} />}
empty={__('No related content found')}
/>
)}
</div>
}
/>
);
}, areEqual);
function areEqual(prevProps: Props, nextProps: Props) {
const a = prevProps;
const b = nextProps;
if (
a.uri !== b.uri ||
a.nextRecommendedUri !== b.nextRecommendedUri ||
a.isAuthenticated !== b.isAuthenticated ||
a.isSearching !== b.isSearching ||
a.mature !== b.mature ||
(a.recommendedContent && !b.recommendedContent) ||
(!a.recommendedContent && b.recommendedContent) ||
(a.claim && !b.claim) ||
(!a.claim && b.claim)
) {
return false;
}
if (a.claim && b.claim && a.claim.claim_id !== b.claim.claim_id) {
return false;
}
if (a.recommendedContent && b.recommendedContent) {
if (a.recommendedContent.length !== b.recommendedContent.length) {
return false;
}
let i = a.recommendedContent.length;
while (i--) {
if (a.recommendedContent[i] !== b.recommendedContent[i]) {
return false;
}
}
}
return true;
}