[feat] Add LiveStreaming Support #5691
6 changed files with 74 additions and 99 deletions
|
@ -9,6 +9,7 @@ import Button from 'component/button';
|
|||
import ClaimListDiscover from 'component/claimListDiscover';
|
||||
import Ads from 'web/component/ads';
|
||||
import Icon from 'component/common/icon';
|
||||
import LivestreamLink from 'component/livestreamLink';
|
||||
import { Form, FormField } from 'component/common/form';
|
||||
import { DEBOUNCE_WAIT_DURATION_MS } from 'constants/search';
|
||||
import { lighthouse } from 'redux/actions/search';
|
||||
|
@ -106,6 +107,8 @@ function ChannelContent(props: Props) {
|
|||
<HiddenNsfwClaims uri={uri} />
|
||||
)}
|
||||
|
||||
<LivestreamLink uri={uri} />
|
||||
|
||||
{!fetching && channelIsBlackListed && (
|
||||
<section className="card card--section">
|
||||
<p>
|
||||
|
|
|
@ -7,16 +7,21 @@ import FileActions from 'component/fileActions';
|
|||
type Props = {
|
||||
uri: string,
|
||||
livestream?: boolean,
|
||||
activeViewers?: number,
|
||||
};
|
||||
|
||||
function FileSubtitle(props: Props) {
|
||||
const { uri, livestream = false } = props;
|
||||
const { uri, livestream = false, activeViewers = 0 } = props;
|
||||
|
||||
return (
|
||||
<div className="media__subtitle--between">
|
||||
<div className="file__viewdate">
|
||||
{livestream ? <span>{__('Right now')}</span> : <DateTime uri={uri} show={DateTime.SHOW_DATE} />}
|
||||
<FileViewCount uri={uri} />
|
||||
{livestream ? (
|
||||
<span>{__('%viewer_count% currently watching', { viewer_count: activeViewers })}</span>
|
||||
) : (
|
||||
<FileViewCount uri={uri} />
|
||||
)}
|
||||
</div>
|
||||
|
||||
<FileActions uri={uri} />
|
||||
|
|
|
@ -19,10 +19,11 @@ type Props = {
|
|||
nsfw: boolean,
|
||||
isNsfwBlocked: boolean,
|
||||
livestream?: boolean,
|
||||
activeViewers?: number,
|
||||
};
|
||||
|
||||
function FileTitleSection(props: Props) {
|
||||
const { title, uri, nsfw, isNsfwBlocked, livestream = false } = props;
|
||||
const { title, uri, nsfw, isNsfwBlocked, livestream = false, activeViewers } = props;
|
||||
|
||||
return (
|
||||
<Card
|
||||
|
@ -42,7 +43,7 @@ function FileTitleSection(props: Props) {
|
|||
body={
|
||||
<React.Fragment>
|
||||
<ClaimInsufficientCredits uri={uri} />
|
||||
<FileSubtitle uri={uri} livestream={livestream} />
|
||||
<FileSubtitle uri={uri} livestream={livestream} activeViewers={activeViewers} />
|
||||
</React.Fragment>
|
||||
}
|
||||
actions={
|
||||
|
|
|
@ -3,7 +3,6 @@ import { BITWAVE_EMBED_URL } from 'constants/livestream';
|
|||
import React from 'react';
|
||||
import FileTitleSection from 'component/fileTitleSection';
|
||||
import LivestreamComments from 'component/livestreamComments';
|
||||
import FileThumbnail from 'component/fileThumbnail';
|
||||
|
||||
type Props = {
|
||||
uri: string,
|
||||
|
@ -15,26 +14,23 @@ type Props = {
|
|||
export default function LivestreamLayout(props: Props) {
|
||||
const { claim, uri, isLive, activeViewers } = props;
|
||||
|
||||
if (!claim) {
|
||||
if (!claim || !claim.signing_channel) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const channelName = claim.signing_channel && claim.signing_channel.name;
|
||||
const channelName = claim.signing_channel.name;
|
||||
const channelClaimId = claim.signing_channel.claim_id;
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="section card-stack">
|
||||
<div className="file-render file-render--video livestream">
|
||||
<div className="file-viewer">
|
||||
{isLive ? (
|
||||
<iframe
|
||||
src={`${BITWAVE_EMBED_URL}/${'doomtube'}?skin=odysee&autoplay=1`}
|
||||
scrolling="no"
|
||||
allowFullScreen
|
||||
/>
|
||||
) : (
|
||||
<FileThumbnail uri={uri} />
|
||||
)}
|
||||
<iframe
|
||||
src={`${BITWAVE_EMBED_URL}/${channelClaimId}?skin=odysee&autoplay=1`}
|
||||
scrolling="no"
|
||||
allowFullScreen
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -45,7 +41,7 @@ export default function LivestreamLayout(props: Props) {
|
|||
})}
|
||||
</div>
|
||||
)}
|
||||
<FileTitleSection uri={uri} livestream activeViewers={activeViewers} />
|
||||
<FileTitleSection uri={uri} livestream isLive={isLive} activeViewers={activeViewers} />
|
||||
</div>
|
||||
<LivestreamComments uri={uri} />
|
||||
</>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// @flow
|
||||
import { BITWAVE_API } from 'constants/livestream';
|
||||
import React from 'react';
|
||||
import Card from 'component/common/card';
|
||||
import ClaimPreview from 'component/claimPreview';
|
||||
|
@ -30,27 +31,27 @@ export default function LivestreamLink(props: Props) {
|
|||
}, [livestreamChannelId]);
|
||||
|
||||
React.useEffect(() => {
|
||||
// function fetchIsStreaming() {
|
||||
// // fetch(``)
|
||||
// // .then((res) => res.json())
|
||||
// // .then((res) => {
|
||||
// // if (res && res.data && res.data.live) {
|
||||
// // setIsLivestreaming(true);
|
||||
// // } else {
|
||||
// // setIsLivestreaming(false);
|
||||
// // }
|
||||
// // })
|
||||
// // .catch((e) => {});
|
||||
// }
|
||||
// let interval;
|
||||
// if (livestreamChannelId) {
|
||||
// interval = setInterval(fetchIsStreaming, 5000);
|
||||
// }
|
||||
// return () => {
|
||||
// if (interval) {
|
||||
// clearInterval(interval);
|
||||
// }
|
||||
// };
|
||||
function fetchIsStreaming() {
|
||||
fetch(`${BITWAVE_API}/MarkPugner`)
|
||||
.then((res) => res.json())
|
||||
.then((res) => {
|
||||
if (res && res.data && res.data.live) {
|
||||
setIsLivestreaming(true);
|
||||
} else {
|
||||
setIsLivestreaming(false);
|
||||
}
|
||||
})
|
||||
.catch((e) => {});
|
||||
}
|
||||
let interval;
|
||||
if (livestreamChannelId) {
|
||||
interval = setInterval(fetchIsStreaming, 5000);
|
||||
}
|
||||
return () => {
|
||||
if (interval) {
|
||||
clearInterval(interval);
|
||||
}
|
||||
};
|
||||
}, [livestreamChannelId]);
|
||||
|
||||
if (!livestreamClaim || !isLivestreaming) {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// @flow
|
||||
// import { BITWAVE_API } from 'constants/livestream';
|
||||
import { BITWAVE_API } from 'constants/livestream';
|
||||
import React from 'react';
|
||||
import Page from 'component/page';
|
||||
import LivestreamLayout from 'component/livestreamLayout';
|
||||
|
@ -16,67 +16,36 @@ type Props = {
|
|||
export default function LivestreamPage(props: Props) {
|
||||
const { uri, claim, doSetPlayingUri, isAuthenticated, doUserSetReferrer } = props;
|
||||
const [activeViewers, setActiveViewers] = React.useState(0);
|
||||
const [isLive, setIsLive] = React.useState(false);
|
||||
|
||||
React.useEffect(() => {
|
||||
// function checkIsLive() {
|
||||
// fetch(`${BITWAVE_API}/`)
|
||||
// .then((res) => res.json())
|
||||
// .then((res) => {
|
||||
// if (!res || !res.data) {
|
||||
// setIsLive(false);
|
||||
// return;
|
||||
// }
|
||||
// setActiveViewers(res.data.viewCount);
|
||||
// if (res.data.live) {
|
||||
// setDisplayCountdown(false);
|
||||
// setIsLive(true);
|
||||
// setIsFetching(false);
|
||||
// return;
|
||||
// }
|
||||
// // Not live, but see if we can display the countdown;
|
||||
// const scheduledTime = res.data.scheduled;
|
||||
// if (scheduledTime) {
|
||||
// const scheduledDate = new Date(scheduledTime);
|
||||
// const lastLiveTimestamp = res.data.timestamp;
|
||||
// let isLivestreamOver = false;
|
||||
// if (lastLiveTimestamp) {
|
||||
// const timestampDate = new Date(lastLiveTimestamp);
|
||||
// isLivestreamOver = timestampDate.getTime() > scheduledDate.getTime();
|
||||
// }
|
||||
// if (isLivestreamOver) {
|
||||
// setDisplayCountdown(false);
|
||||
// setIsLive(false);
|
||||
// } else {
|
||||
// const datePlusTenMinuteBuffer = scheduledDate.setMinutes(10, 0, 0);
|
||||
// const isInFuture = Date.now() < datePlusTenMinuteBuffer;
|
||||
// if (isInFuture) {
|
||||
// setDisplayCountdown(true);
|
||||
// setIsLive(false);
|
||||
// } else {
|
||||
// setDisplayCountdown(false);
|
||||
// setIsLive(false);
|
||||
// }
|
||||
// }
|
||||
// setIsFetching(false);
|
||||
// } else {
|
||||
// // Offline and no countdown happening
|
||||
// setIsLive(false);
|
||||
// setDisplayCountdown(false);
|
||||
// setActiveViewers(0);
|
||||
// setIsFetching(false);
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// let interval;
|
||||
// checkIsLive();
|
||||
// if (uri) {
|
||||
// interval = setInterval(checkIsLive, 10000);
|
||||
// }
|
||||
// return () => {
|
||||
// if (interval) {
|
||||
// clearInterval(interval);
|
||||
// }
|
||||
// };
|
||||
function checkIsLive() {
|
||||
fetch(`${BITWAVE_API}/MarkPugner`)
|
||||
.then((res) => res.json())
|
||||
.then((res) => {
|
||||
if (!res || !res.data) {
|
||||
setIsLive(false);
|
||||
return;
|
||||
}
|
||||
|
||||
setActiveViewers(res.data.viewCount);
|
||||
|
||||
if (res.data.live) {
|
||||
setIsLive(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
let interval;
|
||||
checkIsLive();
|
||||
if (uri) {
|
||||
interval = setInterval(checkIsLive, 10000);
|
||||
}
|
||||
return () => {
|
||||
if (interval) {
|
||||
clearInterval(interval);
|
||||
}
|
||||
};
|
||||
}, [uri]);
|
||||
|
||||
const stringifiedClaim = JSON.stringify(claim);
|
||||
|
@ -108,7 +77,7 @@ export default function LivestreamPage(props: Props) {
|
|||
|
||||
return (
|
||||
<Page className="file-page" filePage livestream>
|
||||
<LivestreamLayout uri={uri} activeViewers={activeViewers} />
|
||||
<LivestreamLayout uri={uri} activeViewers={activeViewers} isLive={isLive} />
|
||||
</Page>
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue