1
0
forked from notnull/waveform

added comment functionality; comment reducer

This commit is contained in:
notnull 2019-04-01 22:02:38 -04:00
parent fea715168a
commit be8660990b
4 changed files with 151 additions and 57 deletions

View File

@ -1,15 +1,35 @@
import React from 'react' import React from 'react'
import {Card} from 'react-bootstrap' import {Tooltip, Image, Button, Card, Overlay} from 'react-bootstrap'
const Comment = props => { class Example extends React.Component {
console.log('comment props:', props) constructor() {
return ( super()
<Card style={{position: 'relative', width: '100px', height: '100px', left: props.commentLoc + '%' }}> this.attachRef = target => this.setState({ target })
<Card.Body> this.state = {
{props.parseTime(props.commentSecs)} show: false,
</Card.Body> }
</Card> this.toggleShow=this.toggleShow.bind(this)
}
toggleShow() {
this.setState({show: !this.state.show})
}
) render() {
const { show, target } = this.state
return (
<>
<div
className = "comment_icon"
ref={this.attachRef}
style={{position: 'absolute', top: 180, left: this.props.commentLoc + '%'}}
onClick={this.toggleShow} />
<Overlay target={target} show={show} placement="bottom" >
<Tooltip>
{this.props.text}
</Tooltip>
</Overlay>
</>
)
}
} }
export default Comment export default Example

View File

@ -5,6 +5,8 @@ const config = require('./audio/loneDigger.json')
import ReactAudioPlayer from 'react-audio-player' import ReactAudioPlayer from 'react-audio-player'
import CommentPopup from './CommentPopup' import CommentPopup from './CommentPopup'
import Comment from './Comment' import Comment from './Comment'
import {fetchAllComments, addComment} from '../../store'
import {Container, Row, Col} from 'react-bootstrap'
const parseTime = secs => { const parseTime = secs => {
var hours = Math.floor(secs / 3600) var hours = Math.floor(secs / 3600)
@ -18,10 +20,11 @@ const parseTime = secs => {
} }
class App extends Component { class Player extends Component {
constructor(props) { constructor(props) {
super(props) super(props)
this.state = { this.state = {
loading: true,
playerSize: {}, playerSize: {},
duration: 3*60+49, duration: 3*60+49,
songSecs: 0, songSecs: 0,
@ -29,22 +32,30 @@ class App extends Component {
commentLoc: 0, commentLoc: 0,
commentText: '', commentText: '',
showPopup: false, showPopup: false,
showComment: false, showComments: true,
comments: [{id: 1, commentSecs: 132}] comments: [{id: 1, commentSecs: 132}]
} }
this.getCommentSecs = this.getCommentSecs.bind(this) //this.getCommentSecs = this.getCommentSecs.bind(this)
this.getPlayerSize = this.getPlayerSize.bind(this) this.getPlayerSize = this.getPlayerSize.bind(this)
this.submitComment = this.submitComment.bind(this) this.submitComment = this.submitComment.bind(this)
this.togglePopup = this.togglePopup.bind(this)
this.openCommentPopup = this.openCommentPopup.bind(this) this.openCommentPopup = this.openCommentPopup.bind(this)
this.updateCommentText = this.updateCommentText.bind(this) this.updateCommentText = this.updateCommentText.bind(this)
//this.showComment = this.showComment.bind(this) this.commentID = 3
} }
getCommentSecs (commentSecs) { async fetchData() {
this.setState({commentSecs}) await this.props.fetchComments()
await this.setState({loading: false})
} }
componentDidMount() {
this.fetchData()
}
// getCommentSecs (commentSecs) {
// this.setState({commentSecs})
// }
getPlayerSize(e) { getPlayerSize(e) {
if(e){ if(e){
this.setState({playerSize: e.getBoundingClientRect()}) this.setState({playerSize: e.getBoundingClientRect()})
@ -53,20 +64,16 @@ class App extends Component {
} }
submitComment(e) { submitComment(e) {
e.preventDefault() e.preventDefault()
const commentLoc = (this.state.playerSize.width * this.state.commentSecs) / ( this.state.duration * 100) console.log(this.state.commentText)
this.setState({commentLoc}) this.props.postComment({id: this.commentID, commentSecs: this.state.commentSecs, text: this.state.commentText})
this.togglePopup() this.commentID ++
this.showComment() this.setState({showPopup: false, showComments: true})
} }
openCommentPopup(commentSecs) { openCommentPopup(commentSecs) {
this.togglePopup() this.setState({commentSecs, showPopup: true, showComments: false})
this.setState({commentSecs})
this.rap.audioEl.pause() this.rap.audioEl.pause()
} }
togglePopup() {
this.setState({showPopup: !this.state.showPopup})
}
updateCommentText(e) { updateCommentText(e) {
e.preventDefault() e.preventDefault()
@ -75,37 +82,51 @@ class App extends Component {
render() { render() {
return ( return (
<div className="container App"> <Container className="App mt-5">
<header className="App-header"> <header className="App-header">
<h1 className="App-title">Player</h1> <h1 className="App-title">Player</h1>
</header> </header>
<div ref = {this.getPlayerSize} style={{ border: '1px solid red' }}> <div ref = {this.getPlayerSize} className = "mb-5">
<Waveform <Row>
ref = {el => {this.waveform = el}} <Col>
peaks={config.data} <Waveform
height={200} ref = {el => {this.waveform = el}}
pos={this.state.songSecs} peaks={config.data}
duration={this.state.duration} height={200}
onClick={this.openCommentPopup} pos={this.state.songSecs}
color="#676767" duration={this.state.duration}
progressGradientColors={[[0, '#33cccc'], [1, '#aaa']]} onClick={this.openCommentPopup}
/> color="#676767"
{this.state.comments.map(comment => <Comment progressGradientColors={[[0, '#33cccc'], [1, '#aaa']]}
parseTime={parseTime} />
key = {comment.id}
commentSecs = {comment.commentSecs}
commentLoc = {(comment.commentSecs / this.state.duration) * 100}
/>) }
</div>
<ReactAudioPlayer {this.state.showComments
src="/audio/01. Lone Digger.mp3" ?
//autoPlay this.props.comments.map(comment =>
controls <Comment
listenInterval={100} parseTime={parseTime}
ref={(element) => { this.rap = element }} key = {comment.id}
onListen={()=>this.setState({songSecs:this.rap.audioEl.currentTime})} commentSecs = {comment.commentSecs}
/> commentLoc = {(comment.commentSecs / this.state.duration) * 100}
text={comment.text}
/>
) : null}
</Col>
</Row>
</div>
<Row>
<Col>
<ReactAudioPlayer
src="/audio/01. Lone Digger.mp3"
//autoPlay
controls
listenInterval={100}
ref={(element) => { this.rap = element }}
onListen={()=>this.setState({songSecs:this.rap.audioEl.currentTime})}
/>
</Col>
</Row>
{this.state.showPopup ? {this.state.showPopup ?
<CommentPopup <CommentPopup
@ -117,10 +138,16 @@ class App extends Component {
/> />
: null : null
} }
</div> </Container>
) )
} }
} }
const mapState = state => state const mapState = state => state
export default connect(mapState)(App) const mapDispatch = dispatch => {
return {
fetchComments: () => dispatch(fetchAllComments()),
postComment: comment => dispatch(addComment(comment))
}
}
export default connect(mapState, mapDispatch)(Player)

View File

@ -4,9 +4,10 @@ import thunkMiddleware from 'redux-thunk'
import {composeWithDevTools} from 'redux-devtools-extension' import {composeWithDevTools} from 'redux-devtools-extension'
import episodes from './reducers/episodes' import episodes from './reducers/episodes'
import captions from './reducers/captions' import captions from './reducers/captions'
import comments from './reducers/comments'
const reducer = combineReducers({episodes, captions}) const reducer = combineReducers({episodes, captions, comments})
const middleware = composeWithDevTools( const middleware = composeWithDevTools(
applyMiddleware(thunkMiddleware, createLogger({collapsed: true})) applyMiddleware(thunkMiddleware, createLogger({collapsed: true}))
) )
@ -15,3 +16,4 @@ const store = createStore(reducer, middleware)
export default store export default store
export * from './reducers/episodes' export * from './reducers/episodes'
export * from './reducers/captions' export * from './reducers/captions'
export * from './reducers/comments'

View File

@ -0,0 +1,45 @@
//import axios from 'axios'
// ACTION TYPES
const GOT_ALL_COMMENTS = 'GOT_ALL_COMMENTS'
const ADD_COMMENT = 'ADD_COMMENT'
const initialComments = []
// ACTION CREATORS
export const gotAllComments = comments => ({
type: GOT_ALL_COMMENTS,
comments
})
export const addComment = comment => ({
type: ADD_COMMENT,
comment
})
// THUNK CREATORS
const comments = [{id: 1, commentSecs: 132, text: 'This is a comment.'}, {id: 2, commentSecs: 32, text: 'Yooo'}]
export const fetchAllComments = () => async dispatch => {
try {
//const res = await axios.get('https://irc.anarchyplanet.org/ircbang/api/v2/comments')
//const comments = res.data
dispatch(gotAllComments(comments))
} catch (err) {
console.error(err)
}
}
// REDUCER
const commentReducer = (comments = initialComments, action) => {
switch (action.type) {
case GOT_ALL_COMMENTS:
return action.comments
case ADD_COMMENT:
return comments.concat(action.comment)
default:
return comments
}
}
export default commentReducer