Add ability to link to latest or current live channel file pages
- and some changes to activeLivestream redux since it would return undefined if fetching and no claim, so now it returns null when no activeLivestream is found
This commit is contained in:
parent
bf158ad696
commit
6b2427768c
11 changed files with 145 additions and 13 deletions
|
@ -53,6 +53,9 @@ export const IS_MAC = navigator.userAgent.indexOf('Mac OS X') !== -1;
|
||||||
// const imaLibraryPath = 'https://imasdk.googleapis.com/js/sdkloader/ima3.js';
|
// const imaLibraryPath = 'https://imasdk.googleapis.com/js/sdkloader/ima3.js';
|
||||||
const oneTrustScriptSrc = 'https://cdn.cookielaw.org/scripttemplates/otSDKStub.js';
|
const oneTrustScriptSrc = 'https://cdn.cookielaw.org/scripttemplates/otSDKStub.js';
|
||||||
|
|
||||||
|
const LATEST_PATH = `/$/${PAGES.LATEST}/`;
|
||||||
|
const LIVE_PATH = `/$/${PAGES.LIVE_NOW}/`;
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
language: string,
|
language: string,
|
||||||
languages: Array<string>,
|
languages: Array<string>,
|
||||||
|
@ -151,8 +154,22 @@ function App(props: Props) {
|
||||||
const connectionStatus = useConnectionStatus();
|
const connectionStatus = useConnectionStatus();
|
||||||
|
|
||||||
const urlPath = pathname + hash;
|
const urlPath = pathname + hash;
|
||||||
|
const latestContentPath = urlPath.startsWith(LATEST_PATH);
|
||||||
|
const liveContentPath = urlPath.startsWith(LIVE_PATH);
|
||||||
|
const isNewestPath = latestContentPath || liveContentPath;
|
||||||
|
|
||||||
let path = urlPath.slice(1).replace(/:/g, '#');
|
let path;
|
||||||
|
if (isNewestPath) {
|
||||||
|
path = urlPath.replace(latestContentPath ? LATEST_PATH : LIVE_PATH, '');
|
||||||
|
} else {
|
||||||
|
// Remove the leading "/" added by the browser
|
||||||
|
path = urlPath.slice(1);
|
||||||
|
}
|
||||||
|
path = path.replace(/:/g, '#');
|
||||||
|
|
||||||
|
if (isNewestPath && !path.startsWith('@')) {
|
||||||
|
path = `@${path}`;
|
||||||
|
}
|
||||||
|
|
||||||
if (search && search.startsWith('?q=cache:')) {
|
if (search && search.startsWith('?q=cache:')) {
|
||||||
generateGoogleCacheUrl(search, path);
|
generateGoogleCacheUrl(search, path);
|
||||||
|
|
|
@ -401,6 +401,8 @@ function AppRouter(props: Props) {
|
||||||
<Route path={`/$/${PAGES.EMBED}/:claimName/:claimId`} exact component={EmbedWrapperPage} />
|
<Route path={`/$/${PAGES.EMBED}/:claimName/:claimId`} exact component={EmbedWrapperPage} />
|
||||||
|
|
||||||
{/* Below need to go at the end to make sure we don't match any of our pages first */}
|
{/* Below need to go at the end to make sure we don't match any of our pages first */}
|
||||||
|
<Route path={`/$/${PAGES.LATEST}/:channelName`} exact render={() => <ShowPage uri={uri} latestContentPath />} />
|
||||||
|
<Route path={`/$/${PAGES.LIVE_NOW}/:channelName`} exact render={() => <ShowPage uri={uri} liveContentPath />} />
|
||||||
<Route path="/:claimName" exact render={() => <ShowPage uri={uri} />} />
|
<Route path="/:claimName" exact render={() => <ShowPage uri={uri} />} />
|
||||||
<Route path="/:claimName/:streamName" exact render={() => <ShowPage uri={uri} />} />
|
<Route path="/:claimName/:streamName" exact render={() => <ShowPage uri={uri} />} />
|
||||||
<Route path="/*" component={FourOhFourPage} />
|
<Route path="/*" component={FourOhFourPage} />
|
||||||
|
|
|
@ -333,6 +333,8 @@ export const FETCH_SUBSCRIPTIONS_FAIL = 'FETCH_SUBSCRIPTIONS_FAIL';
|
||||||
export const FETCH_SUBSCRIPTIONS_SUCCESS = 'FETCH_SUBSCRIPTIONS_SUCCESS';
|
export const FETCH_SUBSCRIPTIONS_SUCCESS = 'FETCH_SUBSCRIPTIONS_SUCCESS';
|
||||||
export const FETCH_LAST_ACTIVE_SUBS_SKIP = 'FETCH_LAST_ACTIVE_SUBS_SKIP';
|
export const FETCH_LAST_ACTIVE_SUBS_SKIP = 'FETCH_LAST_ACTIVE_SUBS_SKIP';
|
||||||
export const FETCH_LAST_ACTIVE_SUBS_DONE = 'FETCH_LAST_ACTIVE_SUBS_DONE';
|
export const FETCH_LAST_ACTIVE_SUBS_DONE = 'FETCH_LAST_ACTIVE_SUBS_DONE';
|
||||||
|
export const FETCH_LATEST_FOR_CHANNEL_DONE = 'FETCH_LATEST_FOR_CHANNEL_DONE';
|
||||||
|
export const FETCH_LATEST_FOR_CHANNEL_FAIL = 'FETCH_LATEST_FOR_CHANNEL_FAIL';
|
||||||
export const FETCH_LAST_ACTIVE_SUBS_FAIL = 'FETCH_LAST_ACTIVE_SUBS_FAIL';
|
export const FETCH_LAST_ACTIVE_SUBS_FAIL = 'FETCH_LAST_ACTIVE_SUBS_FAIL';
|
||||||
export const SET_VIEW_MODE = 'SET_VIEW_MODE';
|
export const SET_VIEW_MODE = 'SET_VIEW_MODE';
|
||||||
|
|
||||||
|
|
|
@ -92,3 +92,5 @@ exports.GENERAL = 'general';
|
||||||
exports.LIST = 'list';
|
exports.LIST = 'list';
|
||||||
exports.ODYSEE_MEMBERSHIP = 'membership';
|
exports.ODYSEE_MEMBERSHIP = 'membership';
|
||||||
exports.POPOUT = 'popout';
|
exports.POPOUT = 'popout';
|
||||||
|
exports.LATEST = 'latest';
|
||||||
|
exports.LIVE_NOW = 'livenow';
|
||||||
|
|
|
@ -6,6 +6,7 @@ import {
|
||||||
selectClaimIsMine,
|
selectClaimIsMine,
|
||||||
makeSelectClaimIsPending,
|
makeSelectClaimIsPending,
|
||||||
selectGeoRestrictionForUri,
|
selectGeoRestrictionForUri,
|
||||||
|
selectLatestClaimByUri,
|
||||||
} from 'redux/selectors/claims';
|
} from 'redux/selectors/claims';
|
||||||
import {
|
import {
|
||||||
makeSelectCollectionForId,
|
makeSelectCollectionForId,
|
||||||
|
@ -13,7 +14,7 @@ import {
|
||||||
makeSelectIsResolvingCollectionForId,
|
makeSelectIsResolvingCollectionForId,
|
||||||
} from 'redux/selectors/collections';
|
} from 'redux/selectors/collections';
|
||||||
import { selectUserVerifiedEmail } from 'redux/selectors/user';
|
import { selectUserVerifiedEmail } from 'redux/selectors/user';
|
||||||
import { doResolveUri } from 'redux/actions/claims';
|
import { doResolveUri, doFetchLatestClaimForChannel } from 'redux/actions/claims';
|
||||||
import { doBeginPublish } from 'redux/actions/publish';
|
import { doBeginPublish } from 'redux/actions/publish';
|
||||||
import { doOpenModal } from 'redux/actions/app';
|
import { doOpenModal } from 'redux/actions/app';
|
||||||
import { doFetchItemsInCollection } from 'redux/actions/collections';
|
import { doFetchItemsInCollection } from 'redux/actions/collections';
|
||||||
|
@ -21,10 +22,12 @@ import { isStreamPlaceholderClaim } from 'util/claim';
|
||||||
import * as COLLECTIONS_CONSTS from 'constants/collections';
|
import * as COLLECTIONS_CONSTS from 'constants/collections';
|
||||||
import { selectIsSubscribedForUri } from 'redux/selectors/subscriptions';
|
import { selectIsSubscribedForUri } from 'redux/selectors/subscriptions';
|
||||||
import { selectBlacklistedOutpointMap } from 'lbryinc';
|
import { selectBlacklistedOutpointMap } from 'lbryinc';
|
||||||
|
import { selectActiveLiveClaimForChannel } from 'redux/selectors/livestream';
|
||||||
|
import { doFetchChannelLiveStatus } from 'redux/actions/livestream';
|
||||||
import ShowPage from './view';
|
import ShowPage from './view';
|
||||||
|
|
||||||
const select = (state, props) => {
|
const select = (state, props) => {
|
||||||
const { uri, location } = props;
|
const { uri, location, liveContentPath } = props;
|
||||||
const { search } = location;
|
const { search } = location;
|
||||||
|
|
||||||
const urlParams = new URLSearchParams(search);
|
const urlParams = new URLSearchParams(search);
|
||||||
|
@ -35,9 +38,16 @@ const select = (state, props) => {
|
||||||
(claim && claim.value_type === 'collection' && claim.claim_id) ||
|
(claim && claim.value_type === 'collection' && claim.claim_id) ||
|
||||||
null;
|
null;
|
||||||
|
|
||||||
|
const { canonical_url: canonicalUrl, claim_id: claimId } = claim || {};
|
||||||
|
const latestContentClaim = liveContentPath
|
||||||
|
? selectActiveLiveClaimForChannel(state, claimId)
|
||||||
|
: selectLatestClaimByUri(state, canonicalUrl);
|
||||||
|
const latestClaimUrl = latestContentClaim && latestContentClaim.canonical_url;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
uri,
|
uri,
|
||||||
claim,
|
claim,
|
||||||
|
latestClaimUrl,
|
||||||
isResolvingUri: selectIsUriResolving(state, uri),
|
isResolvingUri: selectIsUriResolving(state, uri),
|
||||||
blackListedOutpointMap: selectBlacklistedOutpointMap(state),
|
blackListedOutpointMap: selectBlacklistedOutpointMap(state),
|
||||||
isSubscribed: selectIsSubscribedForUri(state, uri),
|
isSubscribed: selectIsSubscribedForUri(state, uri),
|
||||||
|
@ -58,6 +68,8 @@ const perform = {
|
||||||
doBeginPublish,
|
doBeginPublish,
|
||||||
doFetchItemsInCollection,
|
doFetchItemsInCollection,
|
||||||
doOpenModal,
|
doOpenModal,
|
||||||
|
fetchLatestClaimForChannel: doFetchLatestClaimForChannel,
|
||||||
|
fetchChannelLiveStatus: doFetchChannelLiveStatus,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default withRouter(connect(select, perform)(ShowPage));
|
export default withRouter(connect(select, perform)(ShowPage));
|
||||||
|
|
|
@ -38,7 +38,12 @@ type Props = {
|
||||||
isResolvingCollection: boolean,
|
isResolvingCollection: boolean,
|
||||||
isAuthenticated: boolean,
|
isAuthenticated: boolean,
|
||||||
geoRestriction: ?GeoRestriction,
|
geoRestriction: ?GeoRestriction,
|
||||||
doResolveUri: (uri: string, returnCached: boolean, resolveReposts: boolean, options: any) => void,
|
latestContentPath?: boolean,
|
||||||
|
liveContentPath?: boolean,
|
||||||
|
latestClaimUrl: ?string,
|
||||||
|
fetchLatestClaimForChannel: (uri: string) => void,
|
||||||
|
fetchChannelLiveStatus: (channelId: string) => void,
|
||||||
|
doResolveUri: (uri: string, returnCached?: boolean, resolveReposts?: boolean, options?: any) => void,
|
||||||
doBeginPublish: (name: ?string) => void,
|
doBeginPublish: (name: ?string) => void,
|
||||||
doFetchItemsInCollection: ({ collectionId: string }) => void,
|
doFetchItemsInCollection: ({ collectionId: string }) => void,
|
||||||
doOpenModal: (string, {}) => void,
|
doOpenModal: (string, {}) => void,
|
||||||
|
@ -61,6 +66,11 @@ export default function ShowPage(props: Props) {
|
||||||
isResolvingCollection,
|
isResolvingCollection,
|
||||||
isAuthenticated,
|
isAuthenticated,
|
||||||
geoRestriction,
|
geoRestriction,
|
||||||
|
latestContentPath,
|
||||||
|
liveContentPath,
|
||||||
|
latestClaimUrl,
|
||||||
|
fetchLatestClaimForChannel,
|
||||||
|
fetchChannelLiveStatus,
|
||||||
doResolveUri,
|
doResolveUri,
|
||||||
doBeginPublish,
|
doBeginPublish,
|
||||||
doFetchItemsInCollection,
|
doFetchItemsInCollection,
|
||||||
|
@ -77,6 +87,8 @@ export default function ShowPage(props: Props) {
|
||||||
const claimExists = claim !== null && claim !== undefined;
|
const claimExists = claim !== null && claim !== undefined;
|
||||||
const haventFetchedYet = claim === undefined;
|
const haventFetchedYet = claim === undefined;
|
||||||
const isMine = claim && claim.is_my_output;
|
const isMine = claim && claim.is_my_output;
|
||||||
|
const claimId = claim && claim.claim_id;
|
||||||
|
const isNewestPath = latestContentPath || liveContentPath;
|
||||||
|
|
||||||
const { contentName, isChannel } = parseURI(uri); // deprecated contentName - use streamName and channelName
|
const { contentName, isChannel } = parseURI(uri); // deprecated contentName - use streamName and channelName
|
||||||
const isCollection = claim && claim.value_type === 'collection';
|
const isCollection = claim && claim.value_type === 'collection';
|
||||||
|
@ -90,6 +102,26 @@ export default function ShowPage(props: Props) {
|
||||||
blackListedOutpointMap[`${claim.txid}:${claim.nout}`]
|
blackListedOutpointMap[`${claim.txid}:${claim.nout}`]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!canonicalUrl && isNewestPath) {
|
||||||
|
doResolveUri(uri);
|
||||||
|
}
|
||||||
|
// only for mount on a latest content page
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!latestClaimUrl && liveContentPath && claimId) {
|
||||||
|
fetchChannelLiveStatus(claimId);
|
||||||
|
}
|
||||||
|
}, [claimId, fetchChannelLiveStatus, latestClaimUrl, liveContentPath]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!latestClaimUrl && latestContentPath && canonicalUrl) {
|
||||||
|
fetchLatestClaimForChannel(canonicalUrl);
|
||||||
|
}
|
||||||
|
}, [canonicalUrl, fetchLatestClaimForChannel, latestClaimUrl, latestContentPath]);
|
||||||
|
|
||||||
// changed this from 'isCollection' to resolve strangers' collections.
|
// changed this from 'isCollection' to resolve strangers' collections.
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (collectionId && !resolvedCollection) {
|
if (collectionId && !resolvedCollection) {
|
||||||
|
@ -150,9 +182,24 @@ export default function ShowPage(props: Props) {
|
||||||
isAuthenticated,
|
isAuthenticated,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// Wait for latest claim fetch
|
||||||
|
if (isNewestPath && latestClaimUrl === undefined) {
|
||||||
|
return (
|
||||||
|
<div className="main--empty">
|
||||||
|
<Spinner delayed />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isNewestPath && latestClaimUrl) {
|
||||||
|
const params = urlParams.toString() !== '' ? `?${urlParams.toString()}` : '';
|
||||||
|
return <Redirect to={`${formatLbryUrlForWeb(latestClaimUrl)}${params}`} />;
|
||||||
|
}
|
||||||
|
|
||||||
// Don't navigate directly to repost urls
|
// Don't navigate directly to repost urls
|
||||||
// Always redirect to the actual content
|
// Always redirect to the actual content
|
||||||
if (claim && claim.repost_url === uri) {
|
// Also redirect to channel page (uri) when on a non-existing latest path (live or content)
|
||||||
|
if (claim && (claim.repost_url === uri || (isNewestPath && latestClaimUrl === null))) {
|
||||||
const newUrl = formatLbryUrlForWeb(canonicalUrl);
|
const newUrl = formatLbryUrlForWeb(canonicalUrl);
|
||||||
return <Redirect to={newUrl} />;
|
return <Redirect to={newUrl} />;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1134,3 +1134,23 @@ export const doCheckPendingClaims = (onChannelConfirmed: Function) => (dispatch:
|
||||||
checkTxoList();
|
checkTxoList();
|
||||||
}, 30000);
|
}, 30000);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const doFetchLatestClaimForChannel = (uri: string) => (dispatch: Dispatch, getState: GetState) => {
|
||||||
|
const searchOptions = {
|
||||||
|
limit_claims_per_channel: 1,
|
||||||
|
channel: uri,
|
||||||
|
no_totals: true,
|
||||||
|
order_by: ['release_time'],
|
||||||
|
page: 1,
|
||||||
|
has_source: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
return dispatch(doClaimSearch(searchOptions))
|
||||||
|
.then((results) =>
|
||||||
|
dispatch({
|
||||||
|
type: ACTIONS.FETCH_LATEST_FOR_CHANNEL_DONE,
|
||||||
|
data: { uri, results },
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.catch(() => dispatch({ type: ACTIONS.FETCH_LATEST_FOR_CHANNEL_FAIL }));
|
||||||
|
};
|
||||||
|
|
|
@ -61,6 +61,7 @@ type State = {
|
||||||
isCheckingNameForPublish: boolean,
|
isCheckingNameForPublish: boolean,
|
||||||
checkingPending: boolean,
|
checkingPending: boolean,
|
||||||
checkingReflecting: boolean,
|
checkingReflecting: boolean,
|
||||||
|
latestByUri: { [string]: any },
|
||||||
};
|
};
|
||||||
|
|
||||||
const reducers = {};
|
const reducers = {};
|
||||||
|
@ -109,6 +110,7 @@ const defaultState = {
|
||||||
isCheckingNameForPublish: false,
|
isCheckingNameForPublish: false,
|
||||||
checkingPending: false,
|
checkingPending: false,
|
||||||
checkingReflecting: false,
|
checkingReflecting: false,
|
||||||
|
latestByUri: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
// ****************************************************************************
|
// ****************************************************************************
|
||||||
|
@ -929,6 +931,17 @@ reducers[ACTIONS.PURCHASE_LIST_STARTED] = (state: State): State => {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
reducers[ACTIONS.FETCH_LATEST_FOR_CHANNEL_DONE] = (state: State, action: any): State => {
|
||||||
|
const { uri, results } = action.data;
|
||||||
|
const latestByUri = Object.assign({}, state.latestByUri);
|
||||||
|
latestByUri[uri] = results;
|
||||||
|
|
||||||
|
return Object.assign({}, state, {
|
||||||
|
...state,
|
||||||
|
latestByUri,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
reducers[ACTIONS.PURCHASE_LIST_COMPLETED] = (state: State, action: any): State => {
|
reducers[ACTIONS.PURCHASE_LIST_COMPLETED] = (state: State, action: any): State => {
|
||||||
const { result }: { result: PurchaseListResponse, resolve: boolean } = action.data;
|
const { result }: { result: PurchaseListResponse, resolve: boolean } = action.data;
|
||||||
const page = result.page;
|
const page = result.page;
|
||||||
|
|
|
@ -7,7 +7,7 @@ const defaultState: LivestreamState = {
|
||||||
fetchingById: {},
|
fetchingById: {},
|
||||||
viewersById: {},
|
viewersById: {},
|
||||||
fetchingActiveLivestreams: 'pending',
|
fetchingActiveLivestreams: 'pending',
|
||||||
activeLivestreams: null,
|
activeLivestreams: {},
|
||||||
activeLivestreamsLastFetchedDate: 0,
|
activeLivestreamsLastFetchedDate: 0,
|
||||||
activeLivestreamsLastFetchedOptions: {},
|
activeLivestreamsLastFetchedOptions: {},
|
||||||
activeLivestreamsLastFetchedFailCount: 0,
|
activeLivestreamsLastFetchedFailCount: 0,
|
||||||
|
@ -95,9 +95,9 @@ export default handleActions(
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
[ACTIONS.REMOVE_CHANNEL_FROM_ACTIVE_LIVESTREAMS]: (state: LivestreamState, action: any) => {
|
[ACTIONS.REMOVE_CHANNEL_FROM_ACTIVE_LIVESTREAMS]: (state: LivestreamState, action: any) => {
|
||||||
const activeLivestreams = state.activeLivestreams;
|
const activeLivestreams = Object.assign({}, state.activeLivestreams);
|
||||||
if (activeLivestreams) delete activeLivestreams[action.data.channelId];
|
activeLivestreams[action.data.channelId] = null;
|
||||||
return { ...state, activeLivestreams: Object.assign({}, activeLivestreams), activeLivestreamInitialized: true };
|
return { ...state, activeLivestreams, activeLivestreamInitialized: true };
|
||||||
},
|
},
|
||||||
[ACTIONS.SOCKET_CONNECTED_BY_ID]: (state: LivestreamState, action: any) => {
|
[ACTIONS.SOCKET_CONNECTED_BY_ID]: (state: LivestreamState, action: any) => {
|
||||||
const { connected, sub_category, id: claimId } = action.data;
|
const { connected, sub_category, id: claimId } = action.data;
|
||||||
|
|
|
@ -33,6 +33,17 @@ export const selectCreatingChannel = (state: State) => selectState(state).creati
|
||||||
export const selectCreateChannelError = (state: State) => selectState(state).createChannelError;
|
export const selectCreateChannelError = (state: State) => selectState(state).createChannelError;
|
||||||
export const selectRepostLoading = (state: State) => selectState(state).repostLoading;
|
export const selectRepostLoading = (state: State) => selectState(state).repostLoading;
|
||||||
export const selectRepostError = (state: State) => selectState(state).repostError;
|
export const selectRepostError = (state: State) => selectState(state).repostError;
|
||||||
|
export const selectLatestByUri = (state: State) => selectState(state).latestByUri;
|
||||||
|
|
||||||
|
export const selectLatestClaimByUri = createSelector(
|
||||||
|
(state, uri) => uri,
|
||||||
|
selectLatestByUri,
|
||||||
|
(uri, latestByUri) => {
|
||||||
|
const latestClaim = latestByUri[uri];
|
||||||
|
// $FlowFixMe
|
||||||
|
return latestClaim && Object.values(latestClaim)[0].stream;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
export const selectClaimsByUri = createSelector(selectClaimIdsByUri, selectClaimsById, (byUri, byId) => {
|
export const selectClaimsByUri = createSelector(selectClaimIdsByUri, selectClaimsById, (byUri, byId) => {
|
||||||
const claims = {};
|
const claims = {};
|
||||||
|
@ -810,7 +821,7 @@ export const selectIsMyChannelCountOverLimit = createSelector(
|
||||||
* @param uri
|
* @param uri
|
||||||
* @returns {*}
|
* @returns {*}
|
||||||
*/
|
*/
|
||||||
export const selectOdyseeMembershipForUri = function (state: State, uri: string) {
|
export const selectOdyseeMembershipForUri = (state: State, uri: string) => {
|
||||||
const claim = selectClaimForUri(state, uri);
|
const claim = selectClaimForUri(state, uri);
|
||||||
|
|
||||||
const uploaderChannelClaimId = getChannelIdFromClaim(claim);
|
const uploaderChannelClaimId = getChannelIdFromClaim(claim);
|
||||||
|
@ -834,7 +845,7 @@ export const selectOdyseeMembershipForUri = function (state: State, uri: string)
|
||||||
* @param channelId
|
* @param channelId
|
||||||
* @returns {*}
|
* @returns {*}
|
||||||
*/
|
*/
|
||||||
export const selectOdyseeMembershipForChannelId = function (state: State, channelId: string) {
|
export const selectOdyseeMembershipForChannelId = (state: State, channelId: string) => {
|
||||||
// looks for the uploader id
|
// looks for the uploader id
|
||||||
const matchingMembershipOfUser =
|
const matchingMembershipOfUser =
|
||||||
state.user && state.user.odyseeMembershipsPerClaimIds && state.user.odyseeMembershipsPerClaimIds[channelId];
|
state.user && state.user.odyseeMembershipsPerClaimIds && state.user.odyseeMembershipsPerClaimIds[channelId];
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// @flow
|
// @flow
|
||||||
import { createSelector } from 'reselect';
|
import { createSelector } from 'reselect';
|
||||||
import { createCachedSelector } from 're-reselect';
|
import { createCachedSelector } from 're-reselect';
|
||||||
import { selectMyClaims, selectPendingClaims } from 'redux/selectors/claims';
|
import { selectMyClaims, selectPendingClaims, selectClaimForUri } from 'redux/selectors/claims';
|
||||||
|
|
||||||
type State = { livestream: any };
|
type State = { livestream: any };
|
||||||
|
|
||||||
|
@ -91,6 +91,12 @@ export const selectActiveLivestreamForChannel = createCachedSelector(
|
||||||
if (!channelId || !activeLivestreams) {
|
if (!channelId || !activeLivestreams) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return activeLivestreams[channelId] || null;
|
return activeLivestreams[channelId];
|
||||||
}
|
}
|
||||||
)((state, channelId) => String(channelId));
|
)((state, channelId) => String(channelId));
|
||||||
|
|
||||||
|
export const selectActiveLiveClaimForChannel = createCachedSelector(
|
||||||
|
(state) => state,
|
||||||
|
selectActiveLivestreamForChannel,
|
||||||
|
(state, activeLivestream) => activeLivestream && selectClaimForUri(state, activeLivestream.claimUri)
|
||||||
|
)((state, channelId) => String(channelId));
|
||||||
|
|
Loading…
Reference in a new issue