diff --git a/ui/component/viewers/videoViewer/index.js b/ui/component/viewers/videoViewer/index.js index 6d6bc67db..0fdc953e8 100644 --- a/ui/component/viewers/videoViewer/index.js +++ b/ui/component/viewers/videoViewer/index.js @@ -1,8 +1,8 @@ import { connect } from 'react-redux'; import { makeSelectClaimForUri, selectThumbnailForUri } from 'redux/selectors/claims'; import { - makeSelectNextUrlForCollectionAndUrl, - makeSelectPreviousUrlForCollectionAndUrl, + makeSelectPrevPlayableUrlFromCollectionAndUrl, + makeSelectNextPlayableUrlFromCollectionAndUrl, } from 'redux/selectors/collections'; import * as SETTINGS from 'constants/settings'; import * as COLLECTIONS_CONSTS from 'constants/collections'; @@ -34,38 +34,12 @@ const select = (state, props) => { const playingUri = selectPlayingUri(state); const collectionId = urlParams.get(COLLECTIONS_CONSTS.COLLECTION_ID) || (playingUri && playingUri.collectionId); const isMarkdownOrComment = playingUri && (playingUri.source === 'markdown' || playingUri.source === 'comment'); - const isClaimPlayable = (uri) => { - const claim = makeSelectClaimForUri(uri)(state); - // $FlowFixMe - return ( - claim && - // $FlowFixMe - claim.value && - // $FlowFixMe - claim.value.stream_type && - // $FlowFixMe - (claim.value.stream_type === 'audio' || claim.value.stream_type === 'video') - ); - }; - const nextUriInCollection = (fromUri) => { - return makeSelectNextUrlForCollectionAndUrl(collectionId, fromUri)(state); - }; - const prevUriInCollection = (fromUri) => { - return makeSelectPreviousUrlForCollectionAndUrl(collectionId, fromUri)(state); - }; let nextRecommendedUri; let previousListUri; if (collectionId) { - nextRecommendedUri = uri; - previousListUri = uri; - // Find previous and next playable item in the collection. - do { - nextRecommendedUri = nextUriInCollection(nextRecommendedUri); - } while (nextRecommendedUri && !isClaimPlayable(nextRecommendedUri)); - do { - previousListUri = prevUriInCollection(previousListUri); - } while (previousListUri && !isClaimPlayable(previousListUri)); + nextRecommendedUri = makeSelectNextPlayableUrlFromCollectionAndUrl(collectionId, uri)(state); + previousListUri = makeSelectPrevPlayableUrlFromCollectionAndUrl(collectionId, uri)(state); } else { const recommendedContent = selectRecommendedContentForUri(state, uri); nextRecommendedUri = recommendedContent && recommendedContent[0]; diff --git a/ui/redux/selectors/collections.js b/ui/redux/selectors/collections.js index 267376d73..d7e150c86 100644 --- a/ui/redux/selectors/collections.js +++ b/ui/redux/selectors/collections.js @@ -3,6 +3,7 @@ import fromEntries from '@ungap/from-entries'; import { createSelector } from 'reselect'; import { selectMyCollectionIds, makeSelectClaimForUri } from 'redux/selectors/claims'; import { parseURI } from 'util/lbryURI'; +import { isClaimPlayable } from 'util/claim'; const selectState = (state: { collections: CollectionState }) => state.collections; @@ -216,7 +217,7 @@ export const makeSelectNextUrlForCollectionAndUrl = (id: string, url: string) => if (index > -1) { const listUrls = shuffleUrls || urls; - // We'll get the next playble url + // We'll get the next playable url let remainingUrls = listUrls.slice(index + 1); if (!remainingUrls.length && loopList) { remainingUrls = listUrls.slice(0); @@ -229,6 +230,34 @@ export const makeSelectNextUrlForCollectionAndUrl = (id: string, url: string) => } ); +export const makeSelectPrevPlayableUrlFromCollectionAndUrl = (collectionId: string, url: string) => + createSelector( + (state) => state, + (state) => { + let prevUrl = url; + let prevPlayableClaim; + do { + prevUrl = makeSelectPreviousUrlForCollectionAndUrl(collectionId, prevUrl)(state); + prevPlayableClaim = makeSelectClaimForUri(prevUrl)(state); + } while (prevUrl && !isClaimPlayable(prevPlayableClaim)); + return prevUrl; + } + ); + +export const makeSelectNextPlayableUrlFromCollectionAndUrl = (collectionId: string, url: string) => + createSelector( + (state) => state, + (state) => { + let nextUrl = url; + let nextPlayableClaim; + do { + nextUrl = makeSelectNextUrlForCollectionAndUrl(collectionId, nextUrl)(state); + nextPlayableClaim = makeSelectClaimForUri(nextUrl)(state); + } while (nextUrl && !isClaimPlayable(nextPlayableClaim)); + return nextUrl; + } + ); + export const makeSelectNameForCollectionId = (id: string) => createSelector(makeSelectCollectionForId(id), (collection) => { return (collection && collection.name) || ''; diff --git a/ui/util/claim.js b/ui/util/claim.js index ca11bd2bb..2c9ca1560 100644 --- a/ui/util/claim.js +++ b/ui/util/claim.js @@ -108,3 +108,12 @@ export function getChannelFromClaim(claim: ?Claim) { ? claim.signing_channel : null; } + +export function isClaimPlayable(claim: ?Claim) { + // $FlowFixMe + if (!claim || !claim.value || !claim.value.stream_type) { + return false; + } + // $FlowFixMe + return ['audio', 'video'].includes(claim.value.stream_type); +}