2017-04-23 11:56:50 +02:00
|
|
|
import React from 'react';
|
|
|
|
import FilePrice from 'component/filePrice'
|
|
|
|
import Link from 'component/link';
|
|
|
|
import Modal from 'component/modal';
|
2017-05-31 19:36:38 +02:00
|
|
|
import lbry from 'lbry'
|
|
|
|
import {
|
|
|
|
Thumbnail,
|
|
|
|
} from 'component/common'
|
2017-04-23 11:56:50 +02:00
|
|
|
|
2017-05-15 05:50:59 +02:00
|
|
|
class VideoPlayButton extends React.Component {
|
2017-05-19 01:14:26 +02:00
|
|
|
onPurchaseConfirmed() {
|
2017-05-02 15:58:35 +02:00
|
|
|
this.props.closeModal()
|
|
|
|
this.props.startPlaying()
|
2017-05-15 05:50:59 +02:00
|
|
|
this.props.loadVideo(this.props.uri)
|
2017-05-02 15:58:35 +02:00
|
|
|
}
|
|
|
|
|
2017-05-17 23:52:45 +02:00
|
|
|
onWatchClick() {
|
|
|
|
this.props.purchaseUri(this.props.uri).then(() => {
|
|
|
|
if (!this.props.modal) {
|
|
|
|
this.props.startPlaying()
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2017-05-02 15:58:35 +02:00
|
|
|
render() {
|
|
|
|
const {
|
|
|
|
button,
|
|
|
|
label,
|
|
|
|
className,
|
|
|
|
metadata,
|
|
|
|
metadata: {
|
|
|
|
title,
|
|
|
|
},
|
|
|
|
uri,
|
|
|
|
modal,
|
|
|
|
closeModal,
|
|
|
|
isLoading,
|
|
|
|
costInfo,
|
|
|
|
fileInfo,
|
2017-05-31 19:36:38 +02:00
|
|
|
mediaType,
|
2017-05-02 15:58:35 +02:00
|
|
|
} = this.props
|
|
|
|
|
2017-05-15 05:50:59 +02:00
|
|
|
/*
|
|
|
|
title={
|
|
|
|
isLoading ? "Video is Loading" :
|
|
|
|
!costInfo ? "Waiting on cost info..." :
|
|
|
|
fileInfo === undefined ? "Waiting on file info..." : ""
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
2017-05-26 20:36:18 +02:00
|
|
|
const disabled = isLoading || fileInfo === undefined || (fileInfo === null && (!costInfo || costInfo.cost === undefined))
|
2017-06-02 19:54:11 +02:00
|
|
|
const icon = ["audio", "video"].indexOf(mediaType) !== -1 ? "icon-play" : "icon-folder-o"
|
2017-05-26 20:36:18 +02:00
|
|
|
|
2017-05-02 15:58:35 +02:00
|
|
|
return (<div>
|
|
|
|
<Link button={ button ? button : null }
|
2017-05-26 20:36:18 +02:00
|
|
|
disabled={disabled}
|
2017-05-02 15:58:35 +02:00
|
|
|
label={label ? label : ""}
|
|
|
|
className="video__play-button"
|
2017-05-31 19:36:38 +02:00
|
|
|
icon={icon}
|
2017-05-18 19:58:28 +02:00
|
|
|
onClick={this.onWatchClick.bind(this)} />
|
2017-05-31 12:55:32 +02:00
|
|
|
<Modal contentLabel={__("Not enough credits")} isOpen={modal == 'notEnoughCredits'} onConfirmed={closeModal}>
|
2017-05-26 22:26:06 +02:00
|
|
|
{__("You don't have enough LBRY credits to pay for this stream.")}
|
2017-05-02 15:58:35 +02:00
|
|
|
</Modal>
|
|
|
|
<Modal
|
|
|
|
type="confirm"
|
2017-05-25 19:40:46 +02:00
|
|
|
isOpen={modal == 'affirmPurchaseAndPlay'}
|
2017-05-26 22:26:06 +02:00
|
|
|
contentLabel={__("Confirm Purchase")}
|
2017-05-19 01:14:26 +02:00
|
|
|
onConfirmed={this.onPurchaseConfirmed.bind(this)}
|
2017-05-02 15:58:35 +02:00
|
|
|
onAborted={closeModal}>
|
2017-05-26 22:26:06 +02:00
|
|
|
{__("This will purchase")} <strong>{title}</strong> {__("for")} <strong><FilePrice uri={uri} look="plain" /></strong> {__("credits")}.
|
2017-05-02 15:58:35 +02:00
|
|
|
</Modal>
|
|
|
|
<Modal
|
2017-05-31 12:55:32 +02:00
|
|
|
isOpen={modal == 'timedOut'} onConfirmed={closeModal} contentLabel={__("Timed Out")}>
|
2017-05-26 22:26:06 +02:00
|
|
|
{__("Sorry, your download timed out :(")}
|
2017-05-02 15:58:35 +02:00
|
|
|
</Modal>
|
|
|
|
</div>);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-23 11:56:50 +02:00
|
|
|
class Video extends React.Component {
|
|
|
|
constructor(props) {
|
|
|
|
super(props)
|
2017-05-12 01:28:43 +02:00
|
|
|
this.state = { isPlaying: false }
|
2017-04-23 11:56:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
startPlaying() {
|
|
|
|
this.setState({
|
|
|
|
isPlaying: true
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
render() {
|
|
|
|
const {
|
|
|
|
metadata,
|
|
|
|
isLoading,
|
|
|
|
isDownloading,
|
|
|
|
fileInfo,
|
2017-05-31 19:36:38 +02:00
|
|
|
contentType,
|
2017-04-23 11:56:50 +02:00
|
|
|
} = this.props
|
|
|
|
const {
|
|
|
|
isPlaying = false,
|
|
|
|
} = this.state
|
|
|
|
|
2017-05-15 18:34:33 +02:00
|
|
|
const isReadyToPlay = fileInfo && fileInfo.written_bytes > 0
|
2017-05-31 19:36:38 +02:00
|
|
|
const mediaType = lbry.getMediaType(contentType, fileInfo && fileInfo.file_name)
|
2017-05-15 18:34:33 +02:00
|
|
|
|
2017-04-23 11:56:50 +02:00
|
|
|
let loadStatusMessage = ''
|
|
|
|
|
2017-05-28 15:38:36 +02:00
|
|
|
if(fileInfo && fileInfo.completed && !fileInfo.written_bytes) {
|
2017-05-28 18:56:01 +02:00
|
|
|
loadStatusMessage = __("It looks like you deleted or moved this file. We're rebuilding it now. It will only take a few seconds.")
|
2017-05-28 15:38:36 +02:00
|
|
|
} else if (isLoading) {
|
2017-05-26 22:26:06 +02:00
|
|
|
loadStatusMessage = __("Requesting stream... it may sit here for like 15-20 seconds in a really awkward way... we're working on it")
|
2017-04-23 11:56:50 +02:00
|
|
|
} else if (isDownloading) {
|
2017-05-26 22:26:06 +02:00
|
|
|
loadStatusMessage = __("Downloading stream... not long left now!")
|
2017-04-23 11:56:50 +02:00
|
|
|
}
|
|
|
|
|
2017-05-31 19:36:38 +02:00
|
|
|
let klassName = ""
|
|
|
|
if (isLoading || isDownloading) klassName += "video-embedded video"
|
|
|
|
if (mediaType === "video") {
|
|
|
|
klassName += "video-embedded video"
|
|
|
|
klassName += isPlaying ? " video--active" : " video--hidden"
|
2017-06-02 19:54:11 +02:00
|
|
|
} else if (mediaType === "application") {
|
|
|
|
klassName += "video-embedded"
|
2017-05-31 19:36:38 +02:00
|
|
|
} else {
|
|
|
|
if (!isPlaying) klassName += "video-embedded"
|
|
|
|
}
|
|
|
|
const poster = metadata.thumbnail
|
|
|
|
|
2017-04-23 11:56:50 +02:00
|
|
|
return (
|
2017-05-31 19:36:38 +02:00
|
|
|
<div className={klassName}>{
|
2017-06-02 09:40:40 +02:00
|
|
|
isPlaying ?
|
2017-05-15 18:34:33 +02:00
|
|
|
(!isReadyToPlay ?
|
2017-05-26 22:26:06 +02:00
|
|
|
<span>{__("this is the world's worst loading screen and we shipped our software with it anyway...")} <br /><br />{loadStatusMessage}</span> :
|
2017-05-31 19:36:38 +02:00
|
|
|
<VideoPlayer filename={fileInfo.file_name} poster={poster} downloadPath={fileInfo.download_path} mediaType={mediaType} poster={poster} />) :
|
2017-04-23 11:56:50 +02:00
|
|
|
<div className="video__cover" style={{backgroundImage: 'url("' + metadata.thumbnail + '")'}}>
|
2017-05-31 19:36:38 +02:00
|
|
|
<VideoPlayButton startPlaying={this.startPlaying.bind(this)} {...this.props} mediaType={mediaType} />
|
2017-04-23 11:56:50 +02:00
|
|
|
</div>
|
|
|
|
}</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-25 19:40:46 +02:00
|
|
|
const from = require('from2')
|
|
|
|
const player = require('render-media')
|
|
|
|
const fs = require('fs')
|
|
|
|
|
2017-05-17 23:52:45 +02:00
|
|
|
class VideoPlayer extends React.Component {
|
2017-04-23 11:56:50 +02:00
|
|
|
componentDidMount() {
|
2017-05-31 19:36:38 +02:00
|
|
|
const elem = this.refs.media
|
2017-04-23 11:56:50 +02:00
|
|
|
const {
|
|
|
|
downloadPath,
|
2017-05-25 19:40:46 +02:00
|
|
|
filename,
|
2017-04-23 11:56:50 +02:00
|
|
|
} = this.props
|
2017-05-25 19:40:46 +02:00
|
|
|
const file = {
|
|
|
|
name: filename,
|
|
|
|
createReadStream: (opts) => {
|
|
|
|
return fs.createReadStream(downloadPath, opts)
|
|
|
|
}
|
2017-05-17 23:52:45 +02:00
|
|
|
}
|
2017-05-31 19:36:38 +02:00
|
|
|
player.append(file, elem, {
|
2017-05-25 19:40:46 +02:00
|
|
|
autoplay: true,
|
|
|
|
controls: true,
|
|
|
|
})
|
2017-04-23 11:56:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
render() {
|
|
|
|
const {
|
|
|
|
downloadPath,
|
2017-05-31 19:36:38 +02:00
|
|
|
mediaType,
|
2017-05-17 23:52:45 +02:00
|
|
|
poster,
|
2017-04-23 11:56:50 +02:00
|
|
|
} = this.props
|
|
|
|
|
|
|
|
return (
|
2017-05-31 19:36:38 +02:00
|
|
|
<div>
|
2017-06-02 19:54:11 +02:00
|
|
|
{["audio", "application"].indexOf(mediaType) !== -1 && <Thumbnail src={poster} className="video-embedded" />}
|
2017-05-31 19:36:38 +02:00
|
|
|
<div ref="media" />
|
|
|
|
</div>
|
2017-04-23 11:56:50 +02:00
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export default Video
|