2021-03-02 03:07:10 +01:00
|
|
|
// @flow
|
2022-01-14 21:24:16 +01:00
|
|
|
import { formatLbryChannelName } from 'util/url';
|
2021-10-18 17:54:59 +02:00
|
|
|
import { lazyImport } from 'util/lazyImport';
|
2022-01-14 21:24:16 +01:00
|
|
|
import { LIVESTREAM_STARTS_SOON_BUFFER, LIVESTREAM_STARTED_RECENTLY_BUFFER } from 'constants/livestream';
|
2021-03-15 15:32:51 +01:00
|
|
|
import analytics from 'analytics';
|
2022-01-14 21:24:16 +01:00
|
|
|
import LivestreamLayout from 'component/livestreamLayout';
|
2021-12-16 22:59:13 +01:00
|
|
|
import moment from 'moment';
|
2022-01-14 21:24:16 +01:00
|
|
|
import Page from 'component/page';
|
|
|
|
import React from 'react';
|
2022-02-08 17:49:46 +01:00
|
|
|
import { useIsMobile } from 'effects/use-screensize';
|
2021-03-02 03:07:10 +01:00
|
|
|
|
2022-01-14 21:24:16 +01:00
|
|
|
const LivestreamChatLayout = lazyImport(() => import('component/livestreamChatLayout' /* webpackChunkName: "chat" */));
|
2021-10-18 17:54:59 +02:00
|
|
|
|
2021-03-02 03:07:10 +01:00
|
|
|
type Props = {
|
2022-01-14 21:24:16 +01:00
|
|
|
activeLivestreamForChannel: any,
|
|
|
|
activeLivestreamInitialized: boolean,
|
2021-12-09 10:23:23 +01:00
|
|
|
channelClaimId: ?string,
|
2021-06-03 17:55:16 +02:00
|
|
|
chatDisabled: boolean,
|
2022-01-14 21:24:16 +01:00
|
|
|
claim: StreamClaim,
|
|
|
|
isAuthenticated: boolean,
|
|
|
|
uri: string,
|
|
|
|
doSetPlayingUri: ({ uri: ?string }) => void,
|
|
|
|
doCommentSocketConnect: (string, string, string) => void,
|
|
|
|
doCommentSocketDisconnect: (string, string) => void,
|
2022-01-06 18:49:49 +01:00
|
|
|
doFetchChannelLiveStatus: (string) => void,
|
2022-01-14 21:24:16 +01:00
|
|
|
doUserSetReferrer: (string) => void,
|
2021-03-02 03:07:10 +01:00
|
|
|
};
|
|
|
|
|
2021-03-15 15:32:51 +01:00
|
|
|
export default function LivestreamPage(props: Props) {
|
2021-12-16 22:59:13 +01:00
|
|
|
const {
|
2022-01-14 21:24:16 +01:00
|
|
|
activeLivestreamForChannel,
|
|
|
|
activeLivestreamInitialized,
|
2021-12-16 22:59:13 +01:00
|
|
|
channelClaimId,
|
|
|
|
chatDisabled,
|
2022-01-14 21:24:16 +01:00
|
|
|
claim,
|
|
|
|
isAuthenticated,
|
|
|
|
uri,
|
|
|
|
doSetPlayingUri,
|
2021-12-16 22:59:13 +01:00
|
|
|
doCommentSocketConnect,
|
|
|
|
doCommentSocketDisconnect,
|
2022-01-06 18:49:49 +01:00
|
|
|
doFetchChannelLiveStatus,
|
2022-01-14 21:24:16 +01:00
|
|
|
doUserSetReferrer,
|
2021-12-16 22:59:13 +01:00
|
|
|
} = props;
|
2021-03-30 01:05:18 +02:00
|
|
|
|
2022-02-08 17:49:46 +01:00
|
|
|
const isMobile = useIsMobile();
|
|
|
|
|
2022-01-14 21:24:16 +01:00
|
|
|
const [activeStreamUri, setActiveStreamUri] = React.useState(false);
|
|
|
|
const [showLivestream, setShowLivestream] = React.useState(false);
|
|
|
|
const [showScheduledInfo, setShowScheduledInfo] = React.useState(false);
|
|
|
|
const [hideComments, setHideComments] = React.useState(false);
|
|
|
|
|
|
|
|
const isInitialized = Boolean(activeLivestreamForChannel) || activeLivestreamInitialized;
|
|
|
|
const isChannelBroadcasting = Boolean(activeLivestreamForChannel);
|
|
|
|
const claimId = claim && claim.claim_id;
|
|
|
|
const isCurrentClaimLive = isChannelBroadcasting && activeLivestreamForChannel.claimId === claimId;
|
|
|
|
const livestreamChannelId = channelClaimId || '';
|
|
|
|
|
|
|
|
// $FlowFixMe
|
|
|
|
const release = moment.unix(claim.value.release_time);
|
|
|
|
const stringifiedClaim = JSON.stringify(claim);
|
|
|
|
|
2021-11-24 17:03:21 +01:00
|
|
|
React.useEffect(() => {
|
|
|
|
// TODO: This should not be needed one we unify the livestream player (?)
|
|
|
|
analytics.playerLoadedEvent('livestream', false);
|
|
|
|
}, []);
|
|
|
|
|
2021-12-16 22:59:13 +01:00
|
|
|
// Establish web socket connection for viewer count.
|
2021-03-15 15:32:51 +01:00
|
|
|
React.useEffect(() => {
|
2022-01-14 21:24:16 +01:00
|
|
|
if (!claim) return;
|
|
|
|
|
|
|
|
const { claim_id: claimId, signing_channel: channelClaim } = claim;
|
|
|
|
const channelName = channelClaim && formatLbryChannelName(channelClaim.canonical_url);
|
|
|
|
|
|
|
|
if (claimId && channelName) {
|
|
|
|
doCommentSocketConnect(uri, channelName, claimId);
|
2021-03-30 01:05:18 +02:00
|
|
|
}
|
2021-03-15 15:32:51 +01:00
|
|
|
|
2021-12-16 22:59:13 +01:00
|
|
|
return () => {
|
2022-01-14 21:24:16 +01:00
|
|
|
if (claimId && channelName) {
|
|
|
|
doCommentSocketDisconnect(claimId, channelName);
|
2021-12-16 22:59:13 +01:00
|
|
|
}
|
|
|
|
};
|
2022-01-14 21:24:16 +01:00
|
|
|
}, [claim, uri, doCommentSocketConnect, doCommentSocketDisconnect]);
|
2021-12-16 22:59:13 +01:00
|
|
|
|
|
|
|
// Find out current channels status + active live claim.
|
2021-03-15 15:32:51 +01:00
|
|
|
React.useEffect(() => {
|
2022-01-06 18:49:49 +01:00
|
|
|
doFetchChannelLiveStatus(livestreamChannelId);
|
|
|
|
const intervalId = setInterval(() => doFetchChannelLiveStatus(livestreamChannelId), 30000);
|
2021-12-16 22:59:13 +01:00
|
|
|
return () => clearInterval(intervalId);
|
2022-01-06 18:49:49 +01:00
|
|
|
}, [livestreamChannelId, doFetchChannelLiveStatus]);
|
2021-12-16 22:59:13 +01:00
|
|
|
|
|
|
|
React.useEffect(() => {
|
2021-12-22 17:12:44 +01:00
|
|
|
setActiveStreamUri(!isCurrentClaimLive && isChannelBroadcasting ? activeLivestreamForChannel.claimUri : false);
|
2021-12-16 22:59:13 +01:00
|
|
|
}, [isCurrentClaimLive, isChannelBroadcasting]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
|
|
|
|
|
|
React.useEffect(() => {
|
|
|
|
if (!isInitialized) return;
|
|
|
|
|
|
|
|
const claimReleaseInFuture = () => release.isAfter();
|
2021-03-02 03:07:10 +01:00
|
|
|
|
2021-12-16 22:59:13 +01:00
|
|
|
const claimReleaseInPast = () => release.isBefore();
|
|
|
|
|
|
|
|
const claimReleaseStartingSoon = () =>
|
|
|
|
release.isBetween(moment(), moment().add(LIVESTREAM_STARTS_SOON_BUFFER, 'minutes'));
|
|
|
|
|
|
|
|
const claimReleaseStartedRecently = () =>
|
|
|
|
release.isBetween(moment().subtract(LIVESTREAM_STARTED_RECENTLY_BUFFER, 'minutes'), moment());
|
|
|
|
|
|
|
|
const checkShowLivestream = () =>
|
|
|
|
isChannelBroadcasting && isCurrentClaimLive && (claimReleaseInPast() || claimReleaseStartingSoon());
|
|
|
|
|
|
|
|
const checkShowScheduledInfo = () =>
|
|
|
|
(!isChannelBroadcasting && (claimReleaseInFuture() || claimReleaseStartedRecently())) ||
|
|
|
|
(isChannelBroadcasting &&
|
|
|
|
((!isCurrentClaimLive && (claimReleaseInFuture() || claimReleaseStartedRecently())) ||
|
|
|
|
(isCurrentClaimLive && claimReleaseInFuture() && !claimReleaseStartingSoon())));
|
|
|
|
|
|
|
|
const checkCommentsDisabled = () => chatDisabled || (claimReleaseInFuture() && !claimReleaseStartingSoon());
|
|
|
|
|
|
|
|
const calculateStreamReleaseState = () => {
|
|
|
|
setShowLivestream(checkShowLivestream());
|
|
|
|
setShowScheduledInfo(checkShowScheduledInfo());
|
|
|
|
setHideComments(checkCommentsDisabled());
|
|
|
|
};
|
|
|
|
|
|
|
|
calculateStreamReleaseState();
|
|
|
|
const intervalId = setInterval(calculateStreamReleaseState, 1000);
|
|
|
|
|
|
|
|
if (isCurrentClaimLive && claimReleaseInPast() && isChannelBroadcasting === true) {
|
|
|
|
clearInterval(intervalId);
|
|
|
|
}
|
|
|
|
|
|
|
|
return () => clearInterval(intervalId);
|
|
|
|
}, [chatDisabled, isChannelBroadcasting, release, isCurrentClaimLive, isInitialized]);
|
|
|
|
|
|
|
|
React.useEffect(() => {
|
|
|
|
if (uri && stringifiedClaim) {
|
|
|
|
const jsonClaim = JSON.parse(stringifiedClaim);
|
2021-03-15 15:32:51 +01:00
|
|
|
if (!isAuthenticated) {
|
|
|
|
const uri = jsonClaim.signing_channel && jsonClaim.signing_channel.permanent_url;
|
2022-01-14 21:24:16 +01:00
|
|
|
if (uri) doUserSetReferrer(uri.replace('lbry://', ''));
|
2021-03-02 03:07:10 +01:00
|
|
|
}
|
|
|
|
}
|
2022-01-14 21:24:16 +01:00
|
|
|
}, [uri, stringifiedClaim, isAuthenticated, doUserSetReferrer]);
|
2021-03-02 03:07:10 +01:00
|
|
|
|
|
|
|
React.useEffect(() => {
|
2021-03-15 15:32:51 +01:00
|
|
|
// Set playing uri to null so the popout player doesnt start playing the dummy claim if a user navigates back
|
2021-07-27 22:35:22 +02:00
|
|
|
// This can be removed when we start using the app video player, not a LIVESTREAM iframe
|
2021-03-15 15:32:51 +01:00
|
|
|
doSetPlayingUri({ uri: null });
|
2022-02-07 17:51:07 +01:00
|
|
|
|
2022-02-08 17:49:46 +01:00
|
|
|
return () => {
|
|
|
|
if (isMobile) doSetPlayingUri({ uri: null });
|
|
|
|
};
|
|
|
|
}, [doSetPlayingUri, isMobile]);
|
2021-03-02 03:07:10 +01:00
|
|
|
|
|
|
|
return (
|
2021-12-16 22:59:13 +01:00
|
|
|
<Page
|
2022-02-11 19:50:55 +01:00
|
|
|
className="file-page scheduledLivestream-wrapper"
|
2021-12-16 22:59:13 +01:00
|
|
|
noFooter
|
|
|
|
livestream
|
|
|
|
chatDisabled={hideComments}
|
|
|
|
rightSide={
|
|
|
|
!hideComments &&
|
|
|
|
isInitialized && (
|
|
|
|
<React.Suspense fallback={null}>
|
2022-01-14 21:24:16 +01:00
|
|
|
<LivestreamChatLayout uri={uri} />
|
2021-12-16 22:59:13 +01:00
|
|
|
</React.Suspense>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
>
|
2022-03-14 20:15:30 +01:00
|
|
|
{isInitialized && (
|
2021-12-16 22:59:13 +01:00
|
|
|
<LivestreamLayout
|
|
|
|
uri={uri}
|
|
|
|
hideComments={hideComments}
|
|
|
|
release={release}
|
|
|
|
isCurrentClaimLive={isCurrentClaimLive}
|
|
|
|
showLivestream={showLivestream}
|
|
|
|
showScheduledInfo={showScheduledInfo}
|
|
|
|
activeStreamUri={activeStreamUri}
|
|
|
|
/>
|
|
|
|
)}
|
|
|
|
</Page>
|
2021-03-02 03:07:10 +01:00
|
|
|
);
|
|
|
|
}
|