diff options
author | Joram Wilander <jwawilander@gmail.com> | 2017-06-18 14:42:32 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-06-18 14:42:32 -0400 |
commit | ab67f6e257f6e8f08145a02a7b93550f99641be4 (patch) | |
tree | d33d1c58a3d229f7e37db58bc2c397ac3806c503 /webapp/components/youtube_video/youtube_video.jsx | |
parent | 0231e95f1c5a8c42ba97875f0d2301815f552974 (diff) | |
download | chat-ab67f6e257f6e8f08145a02a7b93550f99641be4.tar.gz chat-ab67f6e257f6e8f08145a02a7b93550f99641be4.tar.bz2 chat-ab67f6e257f6e8f08145a02a7b93550f99641be4.zip |
PLT-6215 Major post list refactor (#6501)
* Major post list refactor
* Fix post and thread deletion
* Fix preferences not selecting correctly
* Fix military time displaying
* Fix UP key for editing posts
* Fix ESLint error
* Various fixes and updates per feedback
* Fix for permalink view
* Revert to old scrolling method and various fixes
* Add floating timestamp, new message indicator, scroll arrows
* Update post loading for focus mode and add visibility limit
* Fix pinning posts and a react warning
* Add loading UI updates from Asaad
* Fix refreshing loop
* Temporarily bump post visibility limit
* Update infinite scrolling
* Remove infinite scrolling
Diffstat (limited to 'webapp/components/youtube_video/youtube_video.jsx')
-rw-r--r-- | webapp/components/youtube_video/youtube_video.jsx | 243 |
1 files changed, 243 insertions, 0 deletions
diff --git a/webapp/components/youtube_video/youtube_video.jsx b/webapp/components/youtube_video/youtube_video.jsx new file mode 100644 index 000000000..5151e6576 --- /dev/null +++ b/webapp/components/youtube_video/youtube_video.jsx @@ -0,0 +1,243 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +import WebClient from 'client/web_client.jsx'; +import * as Utils from 'utils/utils.jsx'; + +const ytRegex = /(?:http|https):\/\/(?:www\.|m\.)?(?:(?:youtube\.com\/(?:(?:v\/)|(?:(?:watch|embed\/watch)(?:\/|.*v=))|(?:embed\/)|(?:user\/[^/]+\/u\/[0-9]\/)))|(?:youtu\.be\/))([^#&?]*)/; + +import React from 'react'; +import PropTypes from 'prop-types'; + +export default class YoutubeVideo extends React.PureComponent { + static propTypes = { + channelId: PropTypes.string.isRequired, + currentChannelId: PropTypes.string.isRequired, + link: PropTypes.string.isRequired, + show: PropTypes.bool.isRequired + } + + constructor(props) { + super(props); + + this.updateStateFromProps = this.updateStateFromProps.bind(this); + this.handleReceivedMetadata = this.handleReceivedMetadata.bind(this); + this.handleMetadataError = this.handleMetadataError.bind(this); + this.loadWithoutKey = this.loadWithoutKey.bind(this); + + this.play = this.play.bind(this); + this.stop = this.stop.bind(this); + + this.state = { + loaded: false, + failed: false, + playing: false, + title: '' + }; + } + + componentWillMount() { + this.updateStateFromProps(this.props); + } + + componentWillReceiveProps(nextProps) { + this.updateStateFromProps(nextProps); + } + + updateStateFromProps(props) { + const link = props.link; + + const match = link.trim().match(ytRegex); + if (!match || match[1].length !== 11) { + return; + } + + if (props.show === false) { + this.stop(); + } + + if (props.channelId !== props.currentChannelId) { + this.stop(); + } + + this.setState({ + videoId: match[1], + time: this.handleYoutubeTime(link) + }); + } + + handleYoutubeTime(link) { + const timeRegex = /[\\?&]t=([0-9]+h)?([0-9]+m)?([0-9]+s?)/; + + const time = link.match(timeRegex); + if (!time || !time[0]) { + return ''; + } + + const hours = time[1] ? time[1].match(/([0-9]+)h/) : null; + const minutes = time[2] ? time[2].match(/([0-9]+)m/) : null; + const seconds = time[3] ? time[3].match(/([0-9]+)s?/) : null; + + let ticks = 0; + + if (hours && hours[1]) { + ticks += parseInt(hours[1], 10) * 3600; + } + + if (minutes && minutes[1]) { + ticks += parseInt(minutes[1], 10) * 60; + } + + if (seconds && seconds[1]) { + ticks += parseInt(seconds[1], 10); + } + + return '&start=' + ticks.toString(); + } + + componentDidMount() { + const key = global.window.mm_config.GoogleDeveloperKey; + if (key) { + WebClient.getYoutubeVideoInfo(key, this.state.videoId, + this.handleReceivedMetadata, this.handleMetadataError); + } else { + this.loadWithoutKey(); + } + } + + loadWithoutKey() { + this.setState({ + loaded: true, + thumb: 'https://i.ytimg.com/vi/' + this.state.videoId + '/hqdefault.jpg' + }); + } + + handleMetadataError() { + this.setState({ + failed: true, + loaded: true, + title: Utils.localizeMessage('youtube_video.notFound', 'Video not found') + }); + } + + handleReceivedMetadata(data) { + if (!data || !data.items || !data.items.length || !data.items[0].snippet) { + this.setState({ + failed: true, + loaded: true, + title: Utils.localizeMessage('youtube_video.notFound', 'Video not found') + }); + return null; + } + const metadata = data.items[0].snippet; + let thumb = 'https://i.ytimg.com/vi/' + this.state.videoId + '/hqdefault.jpg'; + if (metadata.liveBroadcastContent === 'live') { + thumb = 'https://i.ytimg.com/vi/' + this.state.videoId + '/hqdefault_live.jpg'; + } + + this.setState({ + loaded: true, + receivedYoutubeData: true, + title: metadata.title, + thumb + }); + return null; + } + + play() { + this.setState({playing: true}); + } + + stop() { + this.setState({playing: false}); + } + + render() { + if (!this.state.loaded) { + return ( + <div + className='post__embed-container' + > + <div className='video-loading'/> + </div> + ); + } + + let header; + if (this.state.title) { + header = ( + <h4> + <span className='video-type'>{'Youtube - '}</span> + <span className='video-title'> + <a + href={this.props.link} + target='blank' + rel='noopener noreferrer' + > + {this.state.title} + </a> + </span> + </h4> + ); + } + + let content; + if (this.state.failed) { + content = ( + <div> + <div className='video-thumbnail__container'> + <div className='video-thumbnail__error'> + <div><i className='fa fa-warning fa-2x'/></div> + <div>{Utils.localizeMessage('youtube_video.notFound', 'Video not found')}</div> + </div> + </div> + </div> + ); + } else if (this.state.playing) { + content = ( + <iframe + src={'https://www.youtube.com/embed/' + this.state.videoId + '?autoplay=1&autohide=1&border=0&wmode=opaque&fs=1&enablejsapi=1' + this.state.time} + width='480px' + height='360px' + type='text/html' + frameBorder='0' + allowFullScreen='allowfullscreen' + /> + ); + } else { + content = ( + <div className='embed-responsive embed-responsive-4by3 video-div__placeholder'> + <div className='video-thumbnail__container'> + <img + className='video-thumbnail' + src={this.state.thumb} + /> + <div className='block'> + <span className='play-button'><span/></span> + </div> + </div> + </div> + ); + } + + return ( + <div + className='post__embed-container' + > + <div> + {header} + <div + className='video-div embed-responsive-item' + onClick={this.play} + > + {content} + </div> + </div> + </div> + ); + } + + static isYoutubeLink(link) { + return link.trim().match(ytRegex); + } +} |