From cdf37977080f2776bbe2e498f1e6585df4b56bca Mon Sep 17 00:00:00 2001
From: 6ea86b96 <6ea86b96@gmail.com>
Date: Tue, 23 May 2017 22:08:58 +0400
Subject: [PATCH] Messing around with an audio player
---
ui/js/component/audio/index.js | 53 +++++++++
ui/js/component/audio/view.jsx | 211 +++++++++++++++++++++++++++++++++
ui/js/page/filePage/view.jsx | 19 ++-
ui/package.json | 3 +-
4 files changed, 282 insertions(+), 4 deletions(-)
create mode 100644 ui/js/component/audio/index.js
create mode 100644 ui/js/component/audio/view.jsx
diff --git a/ui/js/component/audio/index.js b/ui/js/component/audio/index.js
new file mode 100644
index 000000000..9d9a334ec
--- /dev/null
+++ b/ui/js/component/audio/index.js
@@ -0,0 +1,53 @@
+import React from 'react'
+import {
+ connect,
+} from 'react-redux'
+import {
+ doCloseModal,
+} from 'actions/app'
+import {
+ selectCurrentModal,
+} from 'selectors/app'
+import {
+ doPurchaseUri,
+ doLoadVideo,
+} from 'actions/content'
+import {
+ makeSelectMetadataForUri
+} from 'selectors/claims'
+import {
+ makeSelectFileInfoForUri,
+ makeSelectLoadingForUri,
+ makeSelectDownloadingForUri,
+} from 'selectors/file_info'
+import {
+ makeSelectCostInfoForUri,
+} from 'selectors/cost_info'
+import Audio from './view'
+
+const makeSelect = () => {
+ const selectCostInfo = makeSelectCostInfoForUri()
+ const selectFileInfo = makeSelectFileInfoForUri()
+ const selectIsLoading = makeSelectLoadingForUri()
+ const selectIsDownloading = makeSelectDownloadingForUri()
+ const selectMetadata = makeSelectMetadataForUri()
+
+ const select = (state, props) => ({
+ costInfo: selectCostInfo(state, props),
+ fileInfo: selectFileInfo(state, props),
+ metadata: selectMetadata(state, props),
+ modal: selectCurrentModal(state),
+ isLoading: selectIsLoading(state, props),
+ isDownloading: selectIsDownloading(state, props),
+ })
+
+ return select
+}
+
+const perform = (dispatch) => ({
+ loadVideo: (uri) => dispatch(doLoadVideo(uri)),
+ purchaseUri: (uri) => dispatch(doPurchaseUri(uri)),
+ closeModal: () => dispatch(doCloseModal()),
+})
+
+export default connect(makeSelect, perform)(Audio)
diff --git a/ui/js/component/audio/view.jsx b/ui/js/component/audio/view.jsx
new file mode 100644
index 000000000..2e30c9d45
--- /dev/null
+++ b/ui/js/component/audio/view.jsx
@@ -0,0 +1,211 @@
+import React from 'react'
+import {
+ Thumbnail,
+} from 'component/common'
+import Link from 'component/link'
+import Modal from 'component/modal'
+import FilePrice from 'component/filePrice'
+import lbry from 'lbry'
+
+const WaveSurfer = require('wavesurfer.js')
+
+class PlayButton extends React.Component {
+ onPurchaseConfirmed() {
+ this.props.closeModal()
+ this.props.startPlaying()
+ this.props.loadVideo(this.props.uri)
+ }
+
+ onPlayClick() {
+ this.props.purchaseUri(this.props.uri).then(() => {
+ if (!this.props.modal) {
+ this.props.startPlaying()
+ }
+ })
+ }
+
+ render() {
+ const {
+ button,
+ label,
+ className,
+ metadata,
+ metadata: {
+ title,
+ },
+ uri,
+ modal,
+ closeModal,
+ isLoading,
+ costInfo,
+ fileInfo,
+ } = this.props
+
+ return (
+
+ {modal}
+ { this.closeModal() }}>
+ You don't have enough LBRY credits to pay for this stream.
+
+
+ This will purchase {title} for credits.
+
+ { this.closeModal() }} contentLabel="Timed Out">
+ Sorry, your download timed out :(
+
+
);
+ }
+}
+
+class Audio extends React.Component {
+ constructor(props) {
+ super(props)
+ this.state = { isPlaying: false }
+ }
+
+ startPlaying() {
+ this.setState({
+ isPlaying: true
+ })
+ }
+
+ render() {
+ const {
+ metadata,
+ fileInfo,
+ isLoading,
+ isDownloading,
+ } = this.props
+ const isReadyToPlay = fileInfo && fileInfo.written_bytes > 0
+ const {
+ isPlaying = false,
+ } = this.state
+
+ let loadStatusMessage
+ if (isLoading) {
+ loadStatusMessage = "Requesting stream... it may sit here for like 15-20 seconds in a really awkward way... we're working on it"
+ } else if (isDownloading) {
+ loadStatusMessage = "Downloading stream... not long left now!"
+ }
+
+ return (
+
+
+ {metadata && !!metadata.thumbnail ? :
+ }
+
+ {(isPlaying || isLoading) && isReadyToPlay &&
+
}
+ {(isPlaying || isLoading) && !isReadyToPlay &&
+
this is the world's worst loading screen and we shipped our software with it anyway... {loadStatusMessage} }
+ {!isPlaying && !isLoading &&
+
+ }
+
+ )
+ }
+}
+
+class AudioPlayer extends React.PureComponent {
+ constructor(props) {
+ super(props)
+
+ this.state = {
+ wavesurfer: null,
+ }
+ }
+
+ componentDidMount() {
+ const elem = this.refs['audio-player']
+ const {
+ downloadPath,
+ } = this.props
+ const wavesurfer = WaveSurfer.create({
+ container: elem,
+ progressColor: 'darkslategray',
+ height: 96,
+ })
+ const playingStarted = this.playingStarted.bind(this)
+ const playingPaused = this.paused.bind(this)
+ wavesurfer.on('play', playingStarted)
+ wavesurfer.on('pause', playingPaused)
+ wavesurfer.on('ready', () => wavesurfer.play())
+ this.setState({
+ wavesurfer,
+ })
+ // setTimeout(() => wavesurfer.play(), 1000)
+ wavesurfer.load(downloadPath)
+ }
+
+ componentWillUnmount() {
+ this.pause()
+ }
+
+ playingStarted() {
+ this.setState({
+ isPlaying: true,
+ })
+ }
+
+ paused() {
+ this.setState({
+ isPlaying: false,
+ })
+ }
+
+ pause() {
+ this.state.wavesurfer.pause()
+ }
+
+ play() {
+ this.state.wavesurfer.play()
+ }
+
+ render() {
+ const {
+ isPlaying,
+ } = this.state
+
+ return(
+
+
+
+
+ {isPlaying &&
+ }
+ {!isPlaying &&
+ }
+
+
+
+ )
+ }
+}
+
+export default Audio
diff --git a/ui/js/page/filePage/view.jsx b/ui/js/page/filePage/view.jsx
index 2373588b7..8a0041212 100644
--- a/ui/js/page/filePage/view.jsx
+++ b/ui/js/page/filePage/view.jsx
@@ -2,6 +2,7 @@ import React from 'react';
import lbry from 'lbry.js';
import lbryuri from 'lbryuri.js';
import Video from 'component/video'
+import Audio from 'component/audio'
import {
Thumbnail,
} from 'component/common';
@@ -85,13 +86,25 @@ class FilePage extends React.Component{
const channelClaimId = claim.value && claim.value.publisherSignature ? claim.value.publisherSignature.certificateId : null;
const channelUri = signatureIsValid && hasSignature && channelName ? lbryuri.build({channelName, claimId: channelClaimId}, false) : null
const uriIndicator =
+ const playableContent = contentType && (contentType.startsWith('video/') || contentType.startsWith('audio/'))
return (
- { contentType && contentType.startsWith('video/') ?
- :
- (metadata && metadata.thumbnail ? : ) }
+ {contentType && contentType.startsWith('video/') &&
+
+ }
+
+ {contentType && contentType.startsWith('audio/') &&
+
+ }
+
+ {!playableContent && metadata && metadata.thumbnail &&
+ }
+
+ {!playableContent && (!metadata || (metadata && !metadata.thumbnail)) &&
+ }
+
diff --git a/ui/package.json b/ui/package.json
index 6245fcd89..c1732783c 100644
--- a/ui/package.json
+++ b/ui/package.json
@@ -32,7 +32,8 @@
"redux": "^3.6.0",
"redux-logger": "^3.0.1",
"redux-thunk": "^2.2.0",
- "reselect": "^3.0.0"
+ "reselect": "^3.0.0",
+ "wavesurfer.js": "^2.0.0-beta01"
},
"devDependencies": {
"babel": "^6.5.2",
--
2.45.3