diff --git a/projects/plugins/jetpack/extensions/blocks/videopress/edit.native.js b/projects/plugins/jetpack/extensions/blocks/videopress/edit.native.js
index e781484cf7861..b639d17d12a0c 100644
--- a/projects/plugins/jetpack/extensions/blocks/videopress/edit.native.js
+++ b/projects/plugins/jetpack/extensions/blocks/videopress/edit.native.js
@@ -1,9 +1,7 @@
-/**
- * External dependencies
- */
/**
* WordPress dependencies
*/
+import apiFetch from '@wordpress/api-fetch';
import {
BlockCaption,
MediaPlaceholder,
@@ -17,7 +15,7 @@ import {
store as blockEditorStore,
} from '@wordpress/block-editor';
import { Icon, ToolbarButton, ToolbarGroup, PanelBody } from '@wordpress/components';
-import { withPreferredColorScheme, compose } from '@wordpress/compose';
+import { withPreferredColorScheme, compose, createHigherOrderComponent } from '@wordpress/compose';
import { withDispatch, withSelect } from '@wordpress/data';
import { Component } from '@wordpress/element';
import { doAction, hasAction } from '@wordpress/hooks';
@@ -30,14 +28,17 @@ import {
requestImageUploadCancelDialog,
} from '@wordpress/react-native-bridge';
import { isURL, getProtocol } from '@wordpress/url';
-import { View, TouchableWithoutFeedback, Text } from 'react-native';
+/**
+ * External dependencies
+ */
+import { ActivityIndicator, View, TouchableWithoutFeedback, Text } from 'react-native';
/**
* Internal dependencies
*/
-import { createUpgradedEmbedBlock } from '../embed/util';
import VideoCommonSettings from './edit-common-settings';
import SvgIconRetry from './icon-retry';
import style from './style.scss';
+import { pickGUIDFromUrl } from './utils';
const ICON_TYPE = {
PLACEHOLDER: 'placeholder',
@@ -45,13 +46,17 @@ const ICON_TYPE = {
UPLOAD: 'upload',
};
-class VideoEdit extends Component {
+class VideoPressEdit extends Component {
constructor( props ) {
super( props );
this.state = {
isCaptionSelected: false,
videoContainerHeight: 0,
+ isUploadInProgress: false,
+ isUploadFailed: false,
+ isLoadingMetadata: false,
+ metadata: {},
};
this.mediaUploadStateReset = this.mediaUploadStateReset.bind( this );
@@ -65,11 +70,20 @@ class VideoEdit extends Component {
this.onFocusCaption = this.onFocusCaption.bind( this );
}
- componentDidMount() {
+ async componentDidMount() {
const { attributes } = this.props;
+ const { guid } = attributes;
if ( attributes.id && getProtocol( attributes.src ) === 'file:' ) {
mediaUploadSync();
}
+
+ // Try to infer the VideoPress ID from the source upon component mount.
+ // If the ID already exists, fetch the metadata to get the video URL.
+ if ( ! guid ) {
+ await this.setGuid();
+ } else {
+ await this.fetchMetadata( guid );
+ }
}
componentWillUnmount() {
@@ -80,13 +94,40 @@ class VideoEdit extends Component {
}
static getDerivedStateFromProps( props, state ) {
- // Avoid a UI flicker in the toolbar by insuring that isCaptionSelected
- // is updated immediately any time the isSelected prop becomes false.
return {
+ // Avoid a UI flicker in the toolbar by insuring that isCaptionSelected
+ // is updated immediately any time the isSelected prop becomes false.
isCaptionSelected: props.isSelected && state.isCaptionSelected,
+ // Reset metadata when "guid" attribute is not defined.
+ metadata: props.attributes?.guid ? state.metadata : {},
};
}
+ async setGuid( value ) {
+ const { setAttributes, attributes } = this.props;
+ const { src } = attributes;
+ // If no value is passed, we try to extract the VideoPress ID from the source.
+ const guid = value ?? pickGUIDFromUrl( src ) ?? undefined;
+ setAttributes( { guid } );
+ if ( guid ) {
+ await this.fetchMetadata( guid );
+ }
+ }
+
+ async fetchMetadata( guid ) {
+ this.setState( { isLoadingMetadata: true } );
+ try {
+ const metadata = await apiFetch( {
+ path: `/rest/v1.1/videos/${ guid }`,
+ } );
+ this.setState( { metadata, isLoadingMetadata: false } );
+ } catch ( error ) {
+ // eslint-disable-next-line no-console
+ console.error( `Couldn't fetch metadata of VideoPress video with ID = ${ guid }`, error );
+ this.setState( { isLoadingMetadata: false } );
+ }
+ }
+
onVideoPressed() {
const { attributes } = this.props;
@@ -119,8 +160,11 @@ class VideoEdit extends Component {
finishMediaUploadWithSuccess( payload ) {
const { setAttributes } = this.props;
- setAttributes( { src: payload.mediaUrl, id: payload.mediaServerId } );
+ const { mediaUrl, mediaServerId, metadata = {} } = payload;
+ const { videopressGUID } = metadata;
+ setAttributes( { src: mediaUrl, id: mediaServerId } );
this.setState( { isUploadInProgress: false } );
+ this.setGuid( videopressGUID );
}
finishMediaUploadWithFailure( payload ) {
@@ -131,29 +175,23 @@ class VideoEdit extends Component {
mediaUploadStateReset() {
const { setAttributes } = this.props;
- setAttributes( { id: null, src: null } );
+ setAttributes( { id: null, src: null, guid: null } );
this.setState( { isUploadInProgress: false } );
}
- onSelectMediaUploadOption( { id, url } ) {
+ onSelectMediaUploadOption( payload ) {
const { setAttributes } = this.props;
+ const { id, url, metadata = {} } = payload;
+ const { videopressGUID } = metadata;
setAttributes( { id, src: url } );
+ this.setGuid( videopressGUID );
}
onSelectURL( url ) {
- const { createErrorNotice, onReplace, setAttributes } = this.props;
+ const { createErrorNotice, setAttributes } = this.props;
- if ( isURL( url ) && /^https?:/.test( getProtocol( url ) ) ) {
- // Check if there's an embed block that handles this URL.
- const embedBlock = createUpgradedEmbedBlock( {
- attributes: { url },
- } );
- if ( undefined !== embedBlock ) {
- onReplace( embedBlock );
- return;
- }
-
- setAttributes( { src: url, id: undefined, poster: undefined } );
+ if ( isURL( url ) ) {
+ setAttributes( { id: url, src: url } );
} else {
createErrorNotice( __( 'Invalid URL.', 'jetpack' ) );
}
@@ -186,10 +224,19 @@ class VideoEdit extends Component {
return ;
}
+ getVideoURL() {
+ const { attributes } = this.props;
+ const { src, guid } = attributes;
+ const { metadata = {} } = this.state;
+
+ return metadata.original || `https://videopress.com/v/${ guid }` || src;
+ }
+
render() {
const { setAttributes, attributes, isSelected, wasBlockJustInserted } = this.props;
const { id, src, guid } = attributes;
- const { videoContainerHeight } = this.state;
+ const { isLoadingMetadata, isUploadInProgress, isUploadFailed, videoContainerHeight } =
+ this.state;
const toolbarEditButton = (
);
- // NOTE: `guid` is not part of the block's attribute definition. This case
- // handled here is a temporary fix until a we find a better approach.
const isSourcePresent = src || ( guid && id );
if ( ! isSourcePresent ) {
return (
@@ -251,8 +296,13 @@ class VideoEdit extends Component {
onFinishMediaUploadWithFailure={ this.finishMediaUploadWithFailure }
onUpdateMediaProgress={ this.updateMediaProgress }
onMediaUploadStateReset={ this.mediaUploadStateReset }
- renderContent={ ( { isUploadInProgress, isUploadFailed, retryMessage } ) => {
- const showVideo = isURL( src ) && ! isUploadInProgress && ! isUploadFailed;
+ renderContent={ ( { retryMessage } ) => {
+ const videoURL = this.getVideoURL();
+ const showVideo =
+ isURL( videoURL ) &&
+ ! isUploadInProgress &&
+ ! isUploadFailed &&
+ ! isLoadingMetadata;
const icon = this.getIcon( isUploadFailed ? ICON_TYPE.RETRY : ICON_TYPE.UPLOAD );
const styleIconContainer = isUploadFailed ? style.modalIconRetry : style.modalIcon;
@@ -273,7 +323,7 @@ class VideoEdit extends Component {
@@ -289,7 +339,8 @@ class VideoEdit extends Component {
),
} }
>
- { videoContainerHeight > 0 && iconContainer }
+ { videoContainerHeight > 0 &&
+ ( isLoadingMetadata ? : iconContainer ) }
{ isUploadFailed && (
{ retryMessage }
) }
@@ -322,17 +373,21 @@ class VideoEdit extends Component {
}
}
-export default compose( [
- withSelect( ( select, { clientId } ) => ( {
- wasBlockJustInserted: select( blockEditorStore ).wasBlockJustInserted(
- clientId,
- 'inserter_menu'
- ),
- } ) ),
- withDispatch( dispatch => {
- const { createErrorNotice } = dispatch( noticesStore );
-
- return { createErrorNotice };
- } ),
- withPreferredColorScheme,
-] )( VideoEdit );
+export default CoreVideoEdit =>
+ compose( [
+ withSelect( ( select, { clientId } ) => ( {
+ wasBlockJustInserted: select( blockEditorStore ).wasBlockJustInserted(
+ clientId,
+ 'inserter_menu'
+ ),
+ } ) ),
+ withDispatch( dispatch => {
+ const { createErrorNotice } = dispatch( noticesStore );
+
+ return { createErrorNotice };
+ } ),
+ withPreferredColorScheme,
+ createHigherOrderComponent( WrappedComponent => props => {
+ return ;
+ } ),
+ ] )( VideoPressEdit );