[feat] Add LiveStreaming Support #5691

Merged
neb-b merged 35 commits from feat/go-live into master 2021-03-23 00:48:10 +01:00
6 changed files with 74 additions and 99 deletions
Showing only changes of commit ca569dc4a7 - Show all commits

View file

@ -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>

View file

@ -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} />

View file

@ -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={

View file

@ -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} />
</>

View file

@ -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) {

View file

@ -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>
);
}