diff --git a/jw-player/include/gutenberg-block.php b/jw-player/include/gutenberg-block.php new file mode 100644 index 0000000..40896d1 --- /dev/null +++ b/jw-player/include/gutenberg-block.php @@ -0,0 +1,25 @@ + 'jwplayer-block-js', + ] + ); +}); diff --git a/jw-player/include/shortcode.php b/jw-player/include/shortcode.php index 4dcfbf6..d0e12aa 100644 --- a/jw-player/include/shortcode.php +++ b/jw-player/include/shortcode.php @@ -3,7 +3,6 @@ // We use a global variable to keep track of all the players that are embedded // on a page. If multiple videos with the same player are embedded on the // same page the library only needs to be injected once. -$jwplayer_shortcode_embedded_players = array(); // Regular shortcode function. function jwplayer_shortcode_handle( $atts ) { @@ -185,19 +184,12 @@ function jwplayer_shortcode_filter_player_params( $atts ) { // Create the JS embed code for the jwplayer player function jwplayer_shortcode_create_js_embed( $media_hash, $player_hash = null, $params = array() ) { - global $jwplayer_shortcode_embedded_players; $player_hash = ( null === $player_hash ) ? get_option( 'jwplayer_player' ) : $player_hash; $content_mask = jwplayer_get_content_mask(); $protocol = ( is_ssl() && JWPLAYER_CONTENT_MASK === $content_mask ) ? 'https' : 'http'; - if ( in_array( $player_hash, $jwplayer_shortcode_embedded_players, true ) ) { - $player_script = ''; - } else { - // Injecting script tag because there's no way to properly enqueue a javascript - // at this point in the process :'-( - $player_script = true; - $jwplayer_shortcode_embedded_players[] = $player_hash; - } + // Injecting script tag because there's no way to properly enqueue a javascript + // at this point in the process :'-( if ( 'local' == $media_hash ) { $element_id = "jwplayer_" . wp_generate_password( 12, false ) . "_div"; @@ -243,8 +235,7 @@ function jwplayer_shortcode_create_js_embed( $media_hash, $player_hash = null, $ // Redeclare fitVids to stop it from breaking the JW Player embedding. if ( JWPLAYER_DISABLE_FITVIDS ) { - if ( $player_script ) { - return " + return "
"; - } else { // no player script - return " -
- - "; - } } else { - // no fitvids script here. - if ( $player_script ) { - return " + return "
"; - } else { // no player script - return " -
- - "; - } } } diff --git a/jw-player/jw-player.php b/jw-player/jw-player.php index aeaa85a..3800e3f 100644 --- a/jw-player/jw-player.php +++ b/jw-player/jw-player.php @@ -4,7 +4,7 @@ Plugin URI: http://www.jwplayer.com/ Description: This plugin allows you to easily upload and embed videos using the JW Player. The embedded video links can be signed, making it harder for viewers to steal your content. Author: JW Player -Version: 1.6.1 +Version: 1.6.2 */ define( 'JWPLAYER_PLUGIN_DIR', dirname( __FILE__ ) ); @@ -20,9 +20,10 @@ require_once( JWPLAYER_PLUGIN_DIR . '/include/shortcode.php' ); require_once( JWPLAYER_PLUGIN_DIR . '/include/validation.php' ); require_once( JWPLAYER_PLUGIN_DIR . '/include/utils.php' ); +require_once( JWPLAYER_PLUGIN_DIR . '/include/gutenberg-block.php' ); // Default settings -define( 'JWPLAYER_PLUGIN_VERSION', '1.6.1' ); +define( 'JWPLAYER_PLUGIN_VERSION', '1.6.2' ); define( 'JWPLAYER_MINIMUM_PHP_VERSION', '5.4.0' ); define( 'JWPLAYER_PLAYER', 'ALJ3XQCI' ); define( 'JWPLAYER_DASHBOARD', 'https://dashboard.jwplayer.com/' ); diff --git a/jw-player/readme.txt b/jw-player/readme.txt index f95b708..d19d8a3 100644 --- a/jw-player/readme.txt +++ b/jw-player/readme.txt @@ -3,7 +3,7 @@ Contributors: LongTail Video Tags: jwplayer, jw, player, jwplatform, video, media, html5 Requires at least: 4.3 Tested up to: 4.8.2 -Stable tag: 1.6.1 +Stable tag: 1.6.2 License: GPLv3 This plugin is no longer supported. JW Player endorses the ilGhera plugin available here: https://wordpress.org/plugins/jw-player-7-for-wp/ diff --git a/jw-player/static/js/jwplayer-embed.js b/jw-player/static/js/jwplayer-embed.js new file mode 100644 index 0000000..fa5a697 --- /dev/null +++ b/jw-player/static/js/jwplayer-embed.js @@ -0,0 +1,71 @@ +let VideoSelector; + +(()=> { + const {registerBlockType}= wp.blocks, + {Path, SVG, Spinner, TextControl}= wp.components, + {createElement, Component}= wp.element, + el= createElement; + registerBlockType( + 'jwplayer-block/jwplayer-embed', { + title: 'JWPlayer Video', + icon: el(SVG, { + alt: 'JWPlayer', + viewBox: '0 0 133.48 133.48', + xmlns: 'http://www.w3.org/2000/svg', + width: 24, + height: 24, + role: 'img', + focusable: 'false', + }, + el(Path, { + fill: '#ec0041', + d: 'M125.9.41a4.56 4.56 0 0 0-6 2.21c-1.1 2.3-29 69.66-29 69.66-.9 2.11-1.5 1.91-1.5-.3 0 0 .1-23.45.2-42.8.1-10.52-5.11-16.44-12.43-17.64a14 14 0 0 0-9.62 2.11 20.63 20.63 0 0 0-6.82 8.11c-2.2 4.31-15.83 44-15.83 44-.71 2.1-1.41 2-1.41-.2 0 0-.4-17.14-.8-21.15-.6-6.22-2-16.34-10-16.84-7.52-.5-10.93 8.82-12.83 14.53-1.31 3.81-7.52 24.36-7.52 24.36l-.9 2.1c-.3 1.11-.8 1.11-1.11 0l-.5-1.9a62.57 62.57 0 0 0-1.9-6 8.6 8.6 0 0 0-1.5-3 3.75 3.75 0 0 0-4-1A3.71 3.71 0 0 0 0 59.75a21.8 21.8 0 0 0 .3 3.61C.82 67 3.43 81.2 5 84.31s5 4.71 8.22 3c3-1.61 4.41-5.31 5.61-8.22 1.53-3.71 9.23-25 9.23-25 .8-2.1 1.4-2 1.3.2 0 0-.4 20.85-.4 30.27 0 3.51.3 9.92 1.3 13.33a10.86 10.86 0 0 0 3.74 5.87 9.27 9.27 0 0 0 6.41 1.8 8.63 8.63 0 0 0 3.21-1.1 13.84 13.84 0 0 0 3.61-3.21 58.32 58.32 0 0 0 5.71-9.62c3.71-7.32 13.34-30 13.34-30 .9-2.11 1.5-1.91 1.5.3 0 0-1.2 38.09-1.2 52.62a29.71 29.71 0 0 0 2 10.63 12.8 12.8 0 0 0 6.62 7.31 11.54 11.54 0 0 0 10.42-.6 16.65 16.65 0 0 0 5.81-6 66.8 66.8 0 0 0 4.92-10.53c2.9-7.51 5.31-15.13 7.71-22.85S126.8 12.14 128.1 5.93a7.49 7.49 0 0 0 .2-2.11 4.53 4.53 0 0 0-2.4-3.41z', + }) + ), + category: 'embed', + attributes: { + key: { + type: 'string', + }, + }, + edit: class JwBlockEdit extends Component { + constructor(...args) { + super(...args); + this.setVideo= this.setVideo.bind(this); + } + setVideo(v) { + if (!v) + return console.log('what you talkin about, willis?'); + this.props.setAttributes({key: `${v.key}`}); + } + componentDidMount() { + /* import jw selector here, so we can guarantee a subsequent paint event */ + const {key}= this.props.attributes; + const paint= ()=> this.forceUpdate(); + import('./jwplayer-selector.js').then(imp=> { + VideoSelector= imp.default; + paint(); + }); + } + render() { + const {key}= this.props.attributes; + return el( + 'div', null, + key && el('img', {src: `http://content.jwplatform.com/thumbs/${key}-40.jpg`}), + key ? el('div', null, `[jwplayer ${key}]`) + : VideoSelector + ? el(VideoSelector, {onVideoSelect: this.setVideo}) + : el('div', null, + el(Spinner), '... loading JW VideoSelector') + ) + } + }, + save: class JwBlockSave extends Component { + render (props) { + const {key}= this.props.attributes; + return el('div', null, key ? `[jwplayer ${key}]` :null); + } + }, + } + ); +})(); diff --git a/jw-player/static/js/jwplayer-selector.js b/jw-player/static/js/jwplayer-selector.js new file mode 100644 index 0000000..3d13b24 --- /dev/null +++ b/jw-player/static/js/jwplayer-selector.js @@ -0,0 +1,152 @@ +const { IconButton, Popover, Spinner } = wp.components, + { withInstanceId } = wp.compose, + { createElement, Component } = wp.element, + { addQueryArgs } = wp.url, + el= createElement, + idPfx= 'jwvideo-selector', + thumbnailStyle = { + borderRadius: '3px', + height:'50px', + margin: '2px', + overflow: 'hidden', + width: '50px', + }, + thumbnailUrl= (key, size= 720)=> `http://content.jwplatform.com/thumbs/${key}-${size}.jpg`, + debounce= (f, wait= 100)=> { + let timeout; + return (...args)=> { + const id= new Date().getTime(); + clearTimeout(timeout); + timeout= setTimeout(()=> f(...args), wait); + }; + }, + createHoc= F=> C=> props=> el(C, {...props, ...F(props)}); /* TODO? refactor search method as hook and introduce to JwSelector as hoc */ + +export default class JwSelector extends Component { + constructor(...args) { + super(...args); + this.aborters= {}; + this.bindListNode= this.bindListNode.bind(this); + this.search= debounce(this.search.bind(this), 1000); + this.instanceId= new Date().getTime(); + this.onChange= this.onChange.bind(this); + this.state= { + currentSearch: undefined, + input: '', + jwSearch: {videos: [], rate_limit: {remaining: true}}, + warning: '', + }; + this.suggestionNodes= []; + } + + bindListNode(ref) { + this.listNode= ref; + } + + onChange(event) { + const input= event.target.value; + this.setState({input}, ()=> + this.setState({ + currentSearch: new Date().getTime(), + loading: 1 < input.length, + warning: '', + }, ()=> 1 response.json()) + .then(jwSearch=> this.setState({ + jwSearch, + loading: currentSearch != this.state.currentSearch + })).catch(()=> this.setState({ + loading: currentSearch != this.state.currentSearch + })) + } + + componentDidUpdate(){ + const {jwSearch, warning}= this.state + const {loading, rate_limit}= jwSearch; + const {remaining}= rate_limit; + if (remaining || loading || warning) + return; + this.setState({ + warning: 'JW RATE LIMIT REACHED - please wait a minute' + }); + } + + componentWillUnmount(){ + if (this.aborter) + this.aborter.abort(); + } + + selectVideo(vid) { + this.props.onVideoSelect(vid); + this.setState({ + input: '', + }); + } + + render() { + const { instanceId, props }= this; + const { autoFocus= true }= props; + const { input, jwSearch, loading, warning }= this.state; + const { videos }= jwSearch; + return el('div', {className: 'jw-videoselector'}, + el('input', { + autoFocus: autoFocus, + className: `${idPfx}-search`, + onChange: this.onChange, + onInput: event=> event.stopPropagation(), + placeholder: 'Type video name', + role: 'combobox', + style: {width: '100%'}, + type: 'text', + value: input, + }), + warning ?warning + :loading + ?el('div', null, el(Spinner), 'searching JwPlayer for ', el('i', null, input)) + :el(Popover, {position: 'bottom', noArrow: 'noArrow', focusOnMount: false}, + el('div', { + className: `${idPfx}-input-suggestions`, + id: `${idPfx}-input-suggestions-${instanceId}`, + ref: this.bindListNode, + role: 'listbox', + }, videos && videos.map((vid, i)=> + el('button', { + className: `${idPfx}-input-suggestion`, + id: `${idPfx}-${instanceId}-${i}`, + key: vid.key, + onClick: ()=> this.selectVideo(vid), + role: 'option', + tabIndex: -1, + }, + el('div', {style: {display: 'flex', alignItems: 'center'}}, + el('img', {src: thumbnailUrl(vid.key, 40), style: thumbnailStyle}), + el('div', null, + vid.title || '(no title)' + ) + ) + ) + )) + ) + ) + + } +} +