Skip to content

Commit

Permalink
recsys v0.2 (#6977)
Browse files Browse the repository at this point in the history
* recsys wip

better logging

fix floating player popout playing uri bug with recsys

lint

add empty entries to create

use beacon; fire on visibilitychange

cleanup, not record recs if not seen

ifweb recsys beacon

recsys handle embeds, cleanup

use history.listen to trigger events

fix recsys embed bug

bugfix

more default data

cleaner

cleaner

* remove tentative

* disable recsys debug logging
  • Loading branch information
jessopb committed Sep 2, 2021
1 parent 64cbd4a commit 049fb28
Show file tree
Hide file tree
Showing 13 changed files with 340 additions and 238 deletions.
1 change: 1 addition & 0 deletions .flowconfig
Expand Up @@ -31,6 +31,7 @@ module.name_mapper='^modal\(.*\)$' -> '<PROJECT_ROOT>/ui/modal\1'
module.name_mapper='^app\(.*\)$' -> '<PROJECT_ROOT>/ui/app\1'
module.name_mapper='^native\(.*\)$' -> '<PROJECT_ROOT>/ui/native\1'
module.name_mapper='^analytics\(.*\)$' -> '<PROJECT_ROOT>/ui/analytics\1'
module.name_mapper='^recsys\(.*\)$' -> '<PROJECT_ROOT>/ui/recsys\1'
module.name_mapper='^rewards\(.*\)$' -> '<PROJECT_ROOT>/ui/rewards\1'
module.name_mapper='^i18n\(.*\)$' -> '<PROJECT_ROOT>/ui/i18n\1'
module.name_mapper='^effects\(.*\)$' -> '<PROJECT_ROOT>/ui/effects\1'
Expand Down
11 changes: 4 additions & 7 deletions ui/component/claimList/view.jsx
Expand Up @@ -27,7 +27,6 @@ type Props = {
onScrollBottom?: (any) => void,
page?: number,
pageSize?: number,
id?: string,
// If using the default header, this is a unique ID needed to persist the state of the filter setting
persistedStorageKey?: string,
showHiddenByUser: boolean,
Expand All @@ -47,7 +46,7 @@ type Props = {
searchOptions?: any,
collectionId?: string,
showNoSourceClaims?: boolean,
onClick?: (e: any, index?: number) => void,
onClick?: (e: any, claim?: ?Claim, index?: number) => void,
};

export default function ClaimList(props: Props) {
Expand All @@ -56,7 +55,6 @@ export default function ClaimList(props: Props) {
uris,
headerAltControls,
loading,
id,
persistedStorageKey,
empty,
defaultSort,
Expand Down Expand Up @@ -110,9 +108,9 @@ export default function ClaimList(props: Props) {
setCurrentSort(currentSort === SORT_NEW ? SORT_OLD : SORT_NEW);
}

function handleClaimClicked(e, index) {
function handleClaimClicked(e, claim, index) {
if (onClick) {
onClick(e, index);
onClick(e, claim, index);
}
}

Expand Down Expand Up @@ -200,7 +198,6 @@ export default function ClaimList(props: Props) {
{injectedItem && index === 4 && <li>{injectedItem}</li>}
<ClaimPreview
uri={uri}
containerId={id}
indexInContainer={index}
type={type}
active={activeUri && uri === activeUri}
Expand All @@ -220,7 +217,7 @@ export default function ClaimList(props: Props) {
return claim.name.length === 24 && !claim.name.includes(' ') && claim.value.author === 'Spee.ch';
}}
live={resolveLive(index)}
onClick={handleClaimClicked}
onClick={(e, claim, index) => handleClaimClicked(e, claim, index)}
/>
</React.Fragment>
))}
Expand Down
2 changes: 0 additions & 2 deletions ui/component/claimListDiscover/view.jsx
Expand Up @@ -583,7 +583,6 @@ function ClaimListDiscover(props: Props) {
)}
<ClaimList
tileLayout
id={mainSearchKey}
loading={loading}
uris={finalUris}
onScrollBottom={handleScrollBottom}
Expand Down Expand Up @@ -617,7 +616,6 @@ function ClaimListDiscover(props: Props) {
</div>
)}
<ClaimList
id={mainSearchKey}
type={type}
loading={loading}
uris={finalUris}
Expand Down
15 changes: 5 additions & 10 deletions ui/component/claimPreview/view.jsx
Expand Up @@ -29,7 +29,6 @@ import ClaimPreviewNoContent from './claim-preview-no-content';
import { ENABLE_NO_SOURCE_CLAIMS } from 'config';
import Button from 'component/button';
import * as ICONS from 'constants/icons';
import { CONTAINER_ID } from 'constants/navigation';

const AbandonedChannelPreview = lazyImport(() =>
import('component/abandonedChannelPreview' /* webpackChunkName: "abandonedChannelPreview" */)
Expand Down Expand Up @@ -67,7 +66,7 @@ type Props = {
actions: boolean | Node | string | number,
properties: boolean | Node | string | number | ((Claim) => Node),
empty?: Node,
onClick?: (e: any, index?: number) => any,
onClick?: (e: any, claim?: ?Claim, index?: number) => any,
streamingUrl: ?string,
getFile: (string) => void,
customShouldHide?: (Claim) => boolean,
Expand All @@ -90,7 +89,6 @@ type Props = {
disableNavigation?: boolean,
mediaDuration?: string,
date?: any,
containerId?: string, // ID or name of the container (e.g. ClaimList, HOC, etc.) that this is in.
indexInContainer?: number, // The index order of this component within 'containerId'.
channelSubCount?: number,
};
Expand Down Expand Up @@ -154,7 +152,6 @@ const ClaimPreview = forwardRef<any, {}>((props: Props, ref: any) => {
isCollectionMine,
collectionUris,
disableNavigation,
containerId,
indexInContainer,
channelSubCount,
} = props;
Expand Down Expand Up @@ -223,7 +220,7 @@ const ClaimPreview = forwardRef<any, {}>((props: Props, ref: any) => {

const handleNavLinkClick = (e) => {
if (onClick) {
onClick(e, indexInContainer);
onClick(e, claim, indexInContainer); // not sure indexInContainer is used for anything.
}
e.stopPropagation();
};
Expand All @@ -232,10 +229,9 @@ const ClaimPreview = forwardRef<any, {}>((props: Props, ref: any) => {
to: {
pathname: navigateUrl,
search: navigateSearch.toString() ? '?' + navigateSearch.toString() : '',
state: containerId ? { [CONTAINER_ID]: containerId } : undefined,
},
onClick: (e) => handleNavLinkClick(e),
onAuxClick: (e) => handleNavLinkClick(e),
onClick: handleNavLinkClick,
onAuxClick: handleNavLinkClick,
};

// do not block abandoned and nsfw claims if showUserBlocked is passed
Expand Down Expand Up @@ -281,14 +277,13 @@ const ClaimPreview = forwardRef<any, {}>((props: Props, ref: any) => {

function handleOnClick(e) {
if (onClick) {
onClick(e, indexInContainer);
onClick(e, claim, indexInContainer);
}

if (claim && !pending && !disableNavigation) {
history.push({
pathname: navigateUrl,
search: navigateSearch.toString() ? '?' + navigateSearch.toString() : '',
state: containerId ? { [CONTAINER_ID]: containerId } : undefined,
});
}
}
Expand Down
21 changes: 13 additions & 8 deletions ui/component/recommendedContent/index.js
Expand Up @@ -7,14 +7,19 @@ import { selectUserVerifiedEmail } from 'redux/selectors/user';
import { makeSelectNextUnplayedRecommended } from 'redux/selectors/content';
import RecommendedContent from './view';

const select = (state, props) => ({
mature: makeSelectClaimIsNsfw(props.uri)(state),
recommendedContent: makeSelectRecommendedContentForUri(props.uri)(state),
nextRecommendedUri: makeSelectNextUnplayedRecommended(props.uri)(state),
isSearching: selectIsSearching(state),
isAuthenticated: selectUserVerifiedEmail(state),
claim: makeSelectClaimForUri(props.uri)(state),
});
const select = (state, props) => {
const claim = makeSelectClaimForUri(props.uri)(state);
const { claim_id: claimId } = claim;
return {
mature: makeSelectClaimIsNsfw(props.uri)(state),
recommendedContentUris: makeSelectRecommendedContentForUri(props.uri)(state),
nextRecommendedUri: makeSelectNextUnplayedRecommended(props.uri)(state),
isSearching: selectIsSearching(state),
isAuthenticated: selectUserVerifiedEmail(state),
claim,
claimId,
};
};

const perform = (dispatch) => ({
doFetchRecommendedContent: (uri, mature) => dispatch(doFetchRecommendedContent(uri, mature)),
Expand Down
58 changes: 23 additions & 35 deletions ui/component/recommendedContent/view.jsx
@@ -1,55 +1,50 @@
// @flow
import { SHOW_ADS } from 'config';
import React from 'react';
import { useHistory } from 'react-router-dom';
import { v4 as uuidv4 } from 'uuid';
import ClaimList from 'component/claimList';
import ClaimListDiscover from 'component/claimListDiscover';
import Ads from 'web/component/ads';
import Card from 'component/common/card';
import { useIsMobile, useIsMediumScreen } from 'effects/use-screensize';
import Button from 'component/button';
import classnames from 'classnames';
import { CONTAINER_ID } from 'constants/navigation';
import RecSys from 'recsys';

const VIEW_ALL_RELATED = 'view_all_related';
const VIEW_MORE_FROM = 'view_more_from';

type Props = {
uri: string,
recommendedContent: Array<string>,
recommendedContentUris: Array<string>,
nextRecommendedUri: string,
isSearching: boolean,
doFetchRecommendedContent: (string, boolean) => void,
mature: boolean,
isAuthenticated: boolean,
claim: ?StreamClaim,
doRecommendationUpdate: (claimId: string, urls: Array<string>, id: string, parentId: string) => void,
doRecommendationClicked: (claimId: string, index: number) => void,
claimId: string,
};

export default React.memo<Props>(function RecommendedContent(props: Props) {
const {
uri,
doFetchRecommendedContent,
mature,
recommendedContent,
recommendedContentUris,
nextRecommendedUri,
isSearching,
isAuthenticated,
claim,
doRecommendationUpdate,
doRecommendationClicked,
claimId,
} = props;
const [viewMode, setViewMode] = React.useState(VIEW_ALL_RELATED);
const [recommendationId, setRecommendationId] = React.useState('');
const [recommendationUrls, setRecommendationUrls] = React.useState();
const history = useHistory();
const signingChannel = claim && claim.signing_channel;
const channelName = signingChannel ? signingChannel.name : null;
const isMobile = useIsMobile();
const isMedium = useIsMediumScreen();

const { onRecsLoaded: onRecommendationsLoaded, onClickedRecommended: onRecommendationClicked } = RecSys;
React.useEffect(() => {
function moveAutoplayNextItemToTop(recommendedContent) {
let newList = recommendedContent;
Expand All @@ -72,33 +67,27 @@ export default React.memo<Props>(function RecommendedContent(props: Props) {
}
}

const newRecommendationUrls = moveAutoplayNextItemToTop(recommendedContent);
const newRecommendationUrls = moveAutoplayNextItemToTop(recommendedContentUris);

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,
]);
}, [recommendedContentUris, nextRecommendedUri, recommendationUrls, setRecommendationUrls, claim]);

React.useEffect(() => {
doFetchRecommendedContent(uri, mature);
}, [uri, mature, doFetchRecommendedContent]);

function handleRecommendationClicked(e: any, index: number) {
React.useEffect(() => {
// Right now we only want to record the recs if they actually saw them.
if (recommendationUrls && recommendationUrls.length && nextRecommendedUri && viewMode === VIEW_ALL_RELATED) {
onRecommendationsLoaded(claimId, recommendationUrls);
}
}, [recommendationUrls, onRecommendationsLoaded, claimId, nextRecommendedUri, viewMode]);

function handleRecommendationClicked(e, clickedClaim, index: number) {
if (claim) {
doRecommendationClicked(claim.claim_id, index);
onRecommendationClicked(claim.claim_id, clickedClaim.claim_id);
}
}

Expand Down Expand Up @@ -133,7 +122,6 @@ export default React.memo<Props>(function RecommendedContent(props: Props) {
<div>
{viewMode === VIEW_ALL_RELATED && (
<ClaimList
id={recommendationId}
type="small"
loading={isSearching}
uris={recommendationUrls}
Expand Down Expand Up @@ -177,8 +165,8 @@ function areEqual(prevProps: Props, nextProps: Props) {
a.isAuthenticated !== b.isAuthenticated ||
a.isSearching !== b.isSearching ||
a.mature !== b.mature ||
(a.recommendedContent && !b.recommendedContent) ||
(!a.recommendedContent && b.recommendedContent) ||
(a.recommendedContentUris && !b.recommendedContentUris) ||
(!a.recommendedContentUris && b.recommendedContentUris) ||
(a.claim && !b.claim) ||
(!a.claim && b.claim)
) {
Expand All @@ -189,14 +177,14 @@ function areEqual(prevProps: Props, nextProps: Props) {
return false;
}

if (a.recommendedContent && b.recommendedContent) {
if (a.recommendedContent.length !== b.recommendedContent.length) {
if (a.recommendedContentUris && b.recommendedContentUris) {
if (a.recommendedContentUris.length !== b.recommendedContentUris.length) {
return false;
}

let i = a.recommendedContent.length;
let i = a.recommendedContentUris.length;
while (i--) {
if (a.recommendedContent[i] !== b.recommendedContent[i]) {
if (a.recommendedContentUris[i] !== b.recommendedContentUris[i]) {
return false;
}
}
Expand Down

0 comments on commit 049fb28

Please sign in to comment.