diff --git a/packages/app/src/pages/streams/viewer/index.jsx b/packages/app/src/pages/streams/viewer/index.jsx index 815b3c27..56020326 100644 --- a/packages/app/src/pages/streams/viewer/index.jsx +++ b/packages/app/src/pages/streams/viewer/index.jsx @@ -1,15 +1,25 @@ -import React from 'react' +import React from "react" +import config from "config" import * as antd from "antd" -import Plyr from 'plyr' -import Hls from 'hls.js' -import mpegts from 'mpegts.js' +import { Icons } from "components/Icons" +import moment from "moment" + +import Plyr from "plyr" +import Hls from "hls.js" +import mpegts from "mpegts.js" import "plyr/dist/plyr.css" +import "./index.less" -const streamsSource = "http://media.ragestudio.net/live" +const streamsSource = config.remotes.streamingApi export default class StreamViewer extends React.Component { state = { + userData: null, + streamInfo: null, + spectators: 0, + timeFromNow: "00:00:00", + player: null, streamKey: null, streamSource: null, @@ -22,18 +32,98 @@ export default class StreamViewer extends React.Component { componentDidMount = async () => { const query = new URLSearchParams(window.location.search) - const requested = query.get("key") + const requestedUsername = query.get("key") - const source = `${streamsSource}/${requested}` - const player = new Plyr('#player') + const source = `${streamsSource}/${requestedUsername}` + const player = new Plyr("#player", { + autoplay: true, + controls: ["play", "mute", "volume", "fullscreen", "options", "settings"], + }) await this.setState({ player, - streamKey: requested, + streamKey: requestedUsername, streamSource: source, }) await this.loadWithProtocol[this.state.loadedProtocol]() + + // make the interface a bit confortable for a video player + app.ThemeController.applyVariant("dark") + app.eventBus.emit("toogleCompactMode", true) + app.SidebarController.toogleVisible(false) + app.HeaderController.toogleVisible(false) + + // fetch user info in the background + this.gatherUserInfo() + + // fetch stream info in the background + // await for it + await this.gatherStreamInfo() + + // create timer + if (this.state.streamInfo.connectCreated) { + this.createTimerCounter() + } + } + + componentWillUnmount = () => { + app.ThemeController.applyVariant(app.settings.get("themeVariant")) + app.eventBus.emit("toogleCompactMode", false) + app.SidebarController.toogleVisible(true) + app.HeaderController.toogleVisible(true) + app.HeaderController.toogleVisible(true) + + if (this.timerCounterInterval) { + this.timerCounterInterval = clearInterval(this.timerCounterInterval) + } + } + + gatherStreamInfo = async () => { + const result = await app.request.get.streamInfoFromUsername(undefined, { + username: this.state.streamKey, + }).catch((error) => { + console.error(error) + antd.message.error(error.message) + return false + }) + + if (result) { + this.setState({ + streamInfo: result, + }) + } + } + + gatherUserInfo = async () => { + const result = await app.request.get.user(undefined, { + username: this.state.streamKey, + }).catch((error) => { + console.error(error) + antd.message.error(error.message) + return false + }) + + if (result) { + this.setState({ + userData: result, + }) + } + } + + createTimerCounter = () => { + this.timerCounterInterval = setInterval(() => { + const secondsFromNow = moment().diff(moment(this.state.streamInfo.connectCreated), "seconds") + + // calculate hours minutes and seconds + const hours = Math.floor(secondsFromNow / 3600) + const minutes = Math.floor((secondsFromNow - hours * 3600) / 60) + const seconds = secondsFromNow - hours * 3600 - minutes * 60 + + this.setState({ + timeFromNow: `${hours}:${minutes}:${seconds}`, + }) + }, 1000) } updateQuality = (newQuality) => { @@ -60,10 +150,10 @@ export default class StreamViewer extends React.Component { console.log("Switching to " + protocol) this.loadWithProtocol[protocol]() } - + loadWithProtocol = { hls: () => { - const source = `${this.state.streamSource}.m3u8` + const source = `${streamsSource}/stream/hls/${this.state.streamKey}` const hls = new Hls() hls.loadSource(source) @@ -72,9 +162,13 @@ export default class StreamViewer extends React.Component { this.setState({ protocolInstance: hls, loadedProtocol: "hls" }) }, flv: () => { - const source = `${this.state.streamSource}.flv` + const source = `${streamsSource}/stream/flv/${this.state.streamKey}` - const instance = mpegts.createPlayer({ type: 'flv', url: source, isLive: true }) + const instance = mpegts.createPlayer({ + type: "flv", + url: source, + isLive: true + }) instance.attachMediaElement(this.videoPlayerRef.current) instance.load() @@ -85,15 +179,39 @@ export default class StreamViewer extends React.Component { } render() { - return
- this.switchProtocol(value)} - value={this.state.loadedProtocol} - > - HLS - FLV - + return
} } \ No newline at end of file diff --git a/packages/app/src/pages/streams/viewer/index.less b/packages/app/src/pages/streams/viewer/index.less new file mode 100644 index 00000000..f9dbc8d5 --- /dev/null +++ b/packages/app/src/pages/streams/viewer/index.less @@ -0,0 +1,92 @@ +.plyr__controls { + width: 100%; + display: inline-flex; + //justify-content: space-between; +} + +.stream { + display: flex; + flex-direction: row; + + align-items: center; + justify-content: center; + + height: 100vh; + width: 100vw; + + color: var(--background-color-contrast); + + h1, + h2, + h3, + h4, + h5, + span, + p { + color: var(--background-color-contrast); + } + + .panel { + display: flex; + flex-direction: column; + + height: 100vh; + width: 20vw; + + .info { + display: flex; + flex-direction: column; + justify-content: flex-start; + align-items: flex-start; + + width: 100%; + height: 10vh; + + padding: 10px; + + backdrop-filter: 20px; + + h1, + h2, + h3, + h4, + h5 { + margin: 0; + } + + >div { + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; + + height: fit-content; + margin-bottom: 8px; + + >div { + margin-right: 8px; + } + } + } + + .chatbox { + width: 20vw; + padding: 20px; + height: 100vh; + } + + #spectatorCount { + font-size: 0.8em; + } + + #timeCount { + font-size: 0.8em; + } + } + + .plyr { + border-radius: 0 4px 4px 0; + width: 80vw; + height: 100vh; + } +} \ No newline at end of file