From 43ba4149891c773d7f8be6685828138510d58e3a Mon Sep 17 00:00:00 2001 From: Siobhan Date: Mon, 17 Apr 2023 14:00:06 +0100 Subject: [PATCH 01/14] refactor: Remove hack that enabled manual saving --- .../block-editor/blocks/video/edit.native.js | 24 +++---------------- .../hooks/use-sync-media/index.ts | 11 ++------- 2 files changed, 5 insertions(+), 30 deletions(-) diff --git a/projects/packages/videopress/src/client/block-editor/blocks/video/edit.native.js b/projects/packages/videopress/src/client/block-editor/blocks/video/edit.native.js index 99d8bbb1b2164..0c7e568d8e960 100644 --- a/projects/packages/videopress/src/client/block-editor/blocks/video/edit.native.js +++ b/projects/packages/videopress/src/client/block-editor/blocks/video/edit.native.js @@ -8,7 +8,7 @@ import { store as blockEditorStore, } from '@wordpress/block-editor'; import { createBlock } from '@wordpress/blocks'; -import { PanelBody, BottomSheet } from '@wordpress/components'; +import { PanelBody } from '@wordpress/components'; import { useDispatch, useSelect } from '@wordpress/data'; import { useState, useCallback, useEffect } from '@wordpress/element'; import { __, sprintf } from '@wordpress/i18n'; @@ -68,7 +68,7 @@ export default function VideoPressEdit( { [ clientId ] ); const { replaceBlock } = useDispatch( blockEditorStore ); - const { createErrorNotice, createSuccessNotice } = useDispatch( noticesStore ); + const { createErrorNotice } = useDispatch( noticesStore ); // Display upload progress in case the editor is closed and re-opened // while the upload is in progress. @@ -89,22 +89,7 @@ export default function VideoPressEdit( { [ setAttributes ] ); - // TODO: This is a temporary solution for manually saving block settings. - // This will be removed and replaced with a more robust solution before the block is shipped to users. - // See: https://github.com/Automattic/jetpack/pull/29996 - const [ blockSettingsSaved, setBlockSettingsSaved ] = useState( false ); - - const onSaveBlockSettings = () => { - setBlockSettingsSaved( true ); - createSuccessNotice( 'Block settings saved.' ); - }; - - const { videoData } = useSyncMedia( - attributes, - setAttributes, - blockSettingsSaved, - setBlockSettingsSaved - ); + const { videoData } = useSyncMedia( attributes, setAttributes ); const { private_enabled_for_site: privateEnabledForSite } = videoData; const handleDoneUpload = useCallback( @@ -231,9 +216,6 @@ export default function VideoPressEdit( { - - - ) } diff --git a/projects/packages/videopress/src/client/block-editor/hooks/use-sync-media/index.ts b/projects/packages/videopress/src/client/block-editor/hooks/use-sync-media/index.ts index c77fc8ad3b424..5712310fd690d 100644 --- a/projects/packages/videopress/src/client/block-editor/hooks/use-sync-media/index.ts +++ b/projects/packages/videopress/src/client/block-editor/hooks/use-sync-media/index.ts @@ -147,15 +147,11 @@ function arrangeTracksAttributes( * * @param {object} attributes - Block attributes. * @param {Function} setAttributes - Block attributes setter. - * @param {boolean} blockSettingsSaved - Temporary attribute to track when block settings have been saved on native. - * @param {Function} setBlockSettingsSaved - Temporary attribute to track manually control when settings are synchronised on native. * @returns {UseSyncMedia} Hook API object. */ export function useSyncMedia( attributes: VideoBlockAttributes, - setAttributes: VideoBlockSetAttributesProps, - blockSettingsSaved = false, - setBlockSettingsSaved + setAttributes: VideoBlockSetAttributesProps ): UseSyncMedia { const { id, guid, isPrivate } = attributes; const { videoData, isRequestingVideoData } = useVideoData( { @@ -276,7 +272,7 @@ export function useSyncMedia( const updateMediaHandler = useMediaDataUpdate( id ); - const postHasBeenJustSaved = isNative ? blockSettingsSaved : !! ( wasSaving && ! isSaving ); + const postHasBeenJustSaved = !! ( wasSaving && ! isSaving ); /* * Video frame poster: Block attributes => Frame poster generation @@ -299,9 +295,6 @@ export function useSyncMedia( return; } - if ( isNative ) { - setBlockSettingsSaved( false ); - } debug( '%o Post has been just saved. Syncing...', attributes?.guid ); From 85881662851ba106ac6969414bb135fe13497abf Mon Sep 17 00:00:00 2001 From: Siobhan Date: Mon, 17 Apr 2023 14:29:36 +0100 Subject: [PATCH 02/14] feat: Detect when post has been saved on native --- .../hooks/use-sync-media/index.ts | 28 +++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/projects/packages/videopress/src/client/block-editor/hooks/use-sync-media/index.ts b/projects/packages/videopress/src/client/block-editor/hooks/use-sync-media/index.ts index 5712310fd690d..32abf0b1b7f8e 100644 --- a/projects/packages/videopress/src/client/block-editor/hooks/use-sync-media/index.ts +++ b/projects/packages/videopress/src/client/block-editor/hooks/use-sync-media/index.ts @@ -7,6 +7,7 @@ import { useSelect, useDispatch } from '@wordpress/data'; import { store as editorStore } from '@wordpress/editor'; import { useEffect, useState, useCallback, Platform } from '@wordpress/element'; import { __ } from '@wordpress/i18n'; +import { subscribePostSaveEvent } from '@wordpress/react-native-bridge'; import debugFactory from 'debug'; /** * Internal dependencies @@ -165,6 +166,26 @@ export function useSyncMedia( const isSaving = useSelect( select => select( editorStore ).isSavingPost(), [] ); const wasSaving = usePrevious( isSaving ); + + // In native, it's not currently possible to access a post's saved state from the editor store. + // We therefore need to listen to a native event emitter to know when a post has just been saved. + const [ postHasBeenJustSavedNative, setPostHasBeenJustSavedNative ] = useState( false ); + + isNative && + useEffect( () => { + const handlePostSaveEvent = () => { + setPostHasBeenJustSavedNative( true ); + }; + + const subscription = subscribePostSaveEvent( handlePostSaveEvent ); + + return () => { + if ( subscription ) { + subscription.remove(); + } + }; + }, [] ); + const invalidateResolution = useDispatch( coreStore ).invalidateResolution; const [ initialState, setState ] = useState< VideoDataProps >( {} ); @@ -272,7 +293,9 @@ export function useSyncMedia( const updateMediaHandler = useMediaDataUpdate( id ); - const postHasBeenJustSaved = !! ( wasSaving && ! isSaving ); + const postHasBeenJustSaved = isNative + ? postHasBeenJustSavedNative + : !! ( wasSaving && ! isSaving ); /* * Video frame poster: Block attributes => Frame poster generation @@ -295,9 +318,10 @@ export function useSyncMedia( return; } - debug( '%o Post has been just saved. Syncing...', attributes?.guid ); + setPostHasBeenJustSavedNative( false ); + if ( ! attributes?.id ) { debug( '%o No media ID found. Impossible to sync. Bail early', attributes?.guid ); return; From 6bd57b2d5d8fddd114f30ca4bb6b1c456f640867 Mon Sep 17 00:00:00 2001 From: Siobhan Date: Mon, 17 Apr 2023 15:58:23 +0100 Subject: [PATCH 03/14] docs: Update CHANGELOG --- .../videopress/changelog/rnmobile-detect-when-post-is-saved | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 projects/packages/videopress/changelog/rnmobile-detect-when-post-is-saved diff --git a/projects/packages/videopress/changelog/rnmobile-detect-when-post-is-saved b/projects/packages/videopress/changelog/rnmobile-detect-when-post-is-saved new file mode 100644 index 0000000000000..1496493750471 --- /dev/null +++ b/projects/packages/videopress/changelog/rnmobile-detect-when-post-is-saved @@ -0,0 +1,4 @@ +Significance: patch +Type: added + +VideoPress block: Sync metadata when post is manually saved on native From de5b29d53543717df2a4ff01af74c5da5105effa Mon Sep 17 00:00:00 2001 From: Siobhan Date: Mon, 17 Apr 2023 21:08:27 +0100 Subject: [PATCH 04/14] refactor: Stop saving markup --- .../src/client/block-editor/blocks/video/index.native.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/projects/packages/videopress/src/client/block-editor/blocks/video/index.native.ts b/projects/packages/videopress/src/client/block-editor/blocks/video/index.native.ts index 6d1ed2a3c7dff..0d8229e00b595 100644 --- a/projects/packages/videopress/src/client/block-editor/blocks/video/index.native.ts +++ b/projects/packages/videopress/src/client/block-editor/blocks/video/index.native.ts @@ -8,8 +8,8 @@ import { registerBlockType } from '@wordpress/blocks'; */ import metadata from './block.json'; import { VideoPressIcon as icon } from './components/icons'; +import deprecated from './deprecated'; import Edit from './edit'; -import save from './save'; import transforms from './transforms'; import './style.scss'; @@ -35,10 +35,11 @@ export default function registerVideoPressBlock() { const result = registerBlockType( name, { edit: Edit, title, - save, + save: () => null, icon, attributes, transforms, + deprecated, } ); // eslint-disable-next-line no-console From e1fe619c53edef53dbccce47834fbc3135e658c6 Mon Sep 17 00:00:00 2001 From: Siobhan Date: Tue, 18 Apr 2023 13:51:40 +0100 Subject: [PATCH 05/14] refactor: Move conditional inside hook Feedback ref: https://github.com/Automattic/jetpack/pull/30131#discussion_r1169823445 --- .../hooks/use-sync-media/index.ts | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/projects/packages/videopress/src/client/block-editor/hooks/use-sync-media/index.ts b/projects/packages/videopress/src/client/block-editor/hooks/use-sync-media/index.ts index 32abf0b1b7f8e..e415767b8b383 100644 --- a/projects/packages/videopress/src/client/block-editor/hooks/use-sync-media/index.ts +++ b/projects/packages/videopress/src/client/block-editor/hooks/use-sync-media/index.ts @@ -171,20 +171,23 @@ export function useSyncMedia( // We therefore need to listen to a native event emitter to know when a post has just been saved. const [ postHasBeenJustSavedNative, setPostHasBeenJustSavedNative ] = useState( false ); - isNative && - useEffect( () => { - const handlePostSaveEvent = () => { - setPostHasBeenJustSavedNative( true ); - }; + useEffect( () => { + if ( ! isNative ) { + return; + } - const subscription = subscribePostSaveEvent( handlePostSaveEvent ); + const handlePostSaveEvent = () => { + setPostHasBeenJustSavedNative( true ); + }; - return () => { - if ( subscription ) { - subscription.remove(); - } - }; - }, [] ); + const subscription = subscribePostSaveEvent( handlePostSaveEvent ); + + return () => { + if ( subscription ) { + subscription.remove(); + } + }; + }, [] ); const invalidateResolution = useDispatch( coreStore ).invalidateResolution; From 195be23cd61005d4f933d1357ff1291b7de70ff8 Mon Sep 17 00:00:00 2001 From: Siobhan Bamber Date: Tue, 18 Apr 2023 16:39:47 +0100 Subject: [PATCH 06/14] refactor: Simplify logic within useEffect hook Co-authored-by: Carlos Garcia --- .../src/client/block-editor/hooks/use-sync-media/index.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/projects/packages/videopress/src/client/block-editor/hooks/use-sync-media/index.ts b/projects/packages/videopress/src/client/block-editor/hooks/use-sync-media/index.ts index e415767b8b383..ff1110ddda121 100644 --- a/projects/packages/videopress/src/client/block-editor/hooks/use-sync-media/index.ts +++ b/projects/packages/videopress/src/client/block-editor/hooks/use-sync-media/index.ts @@ -176,11 +176,7 @@ export function useSyncMedia( return; } - const handlePostSaveEvent = () => { - setPostHasBeenJustSavedNative( true ); - }; - - const subscription = subscribePostSaveEvent( handlePostSaveEvent ); + const subscription = subscribePostSaveEvent( () => setPostHasBeenJustSavedNative( true ) ); return () => { if ( subscription ) { From 5fc4f7771ae6718e9dedd12fc85c0f9dd58d607d Mon Sep 17 00:00:00 2001 From: Siobhan Bamber Date: Tue, 18 Apr 2023 16:42:58 +0100 Subject: [PATCH 07/14] refactor: Use chaining operator to simplify code Co-authored-by: Carlos Garcia --- .../src/client/block-editor/hooks/use-sync-media/index.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/projects/packages/videopress/src/client/block-editor/hooks/use-sync-media/index.ts b/projects/packages/videopress/src/client/block-editor/hooks/use-sync-media/index.ts index ff1110ddda121..77a8e4dda75ee 100644 --- a/projects/packages/videopress/src/client/block-editor/hooks/use-sync-media/index.ts +++ b/projects/packages/videopress/src/client/block-editor/hooks/use-sync-media/index.ts @@ -179,9 +179,7 @@ export function useSyncMedia( const subscription = subscribePostSaveEvent( () => setPostHasBeenJustSavedNative( true ) ); return () => { - if ( subscription ) { - subscription.remove(); - } + subscription?.remove(); }; }, [] ); From 011d672780ec4feed58d106ddf27c1edfbd2203d Mon Sep 17 00:00:00 2001 From: Siobhan Date: Tue, 18 Apr 2023 16:45:26 +0100 Subject: [PATCH 08/14] refactor: Use isNative conditional to limit code --- .../src/client/block-editor/hooks/use-sync-media/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/packages/videopress/src/client/block-editor/hooks/use-sync-media/index.ts b/projects/packages/videopress/src/client/block-editor/hooks/use-sync-media/index.ts index e415767b8b383..ff48135cb48b2 100644 --- a/projects/packages/videopress/src/client/block-editor/hooks/use-sync-media/index.ts +++ b/projects/packages/videopress/src/client/block-editor/hooks/use-sync-media/index.ts @@ -323,7 +323,7 @@ export function useSyncMedia( debug( '%o Post has been just saved. Syncing...', attributes?.guid ); - setPostHasBeenJustSavedNative( false ); + isNative && setPostHasBeenJustSavedNative( false ); if ( ! attributes?.id ) { debug( '%o No media ID found. Impossible to sync. Bail early', attributes?.guid ); From 7ec2f6859091502e6aba246a958302d4f163ca8d Mon Sep 17 00:00:00 2001 From: Siobhan Date: Wed, 19 Apr 2023 10:35:15 +0100 Subject: [PATCH 09/14] refactor: Add native file for useSyncMedia hook --- .../hooks/use-sync-media/index.native.ts | 457 ++++++++++++++++++ 1 file changed, 457 insertions(+) create mode 100644 projects/packages/videopress/src/client/block-editor/hooks/use-sync-media/index.native.ts diff --git a/projects/packages/videopress/src/client/block-editor/hooks/use-sync-media/index.native.ts b/projects/packages/videopress/src/client/block-editor/hooks/use-sync-media/index.native.ts new file mode 100644 index 0000000000000..8d9822f09a6ce --- /dev/null +++ b/projects/packages/videopress/src/client/block-editor/hooks/use-sync-media/index.native.ts @@ -0,0 +1,457 @@ +/** + * External dependencies + */ +import { usePrevious } from '@wordpress/compose'; +import { store as coreStore } from '@wordpress/core-data'; +import { useSelect, useDispatch } from '@wordpress/data'; +import { store as editorStore } from '@wordpress/editor'; +import { useEffect, useState, useCallback, Platform } from '@wordpress/element'; +import { __ } from '@wordpress/i18n'; +import { subscribePostSaveEvent } from '@wordpress/react-native-bridge'; +import debugFactory from 'debug'; +/** + * Internal dependencies + */ +import { getVideoPressUrl } from '../../../lib/url'; +import { uploadTrackForGuid } from '../../../lib/video-tracks'; +import { isAutogeneratedChapterFile } from '../../../lib/video-tracks'; +import { WPComV2VideopressPostMetaEndpointBodyProps } from '../../../types'; +import { snakeToCamel } from '../../../utils/map-object-keys-to-camel-case'; +import extractVideoChapters from '../../../utils/video-chapters/extract-video-chapters'; +import generateChaptersFile from '../../../utils/video-chapters/generate-chapters-file'; +import validateChapters from '../../../utils/video-chapters/validate-chapters'; +import { VideoBlockAttributes, VideoBlockSetAttributesProps } from '../../blocks/video/types'; +import useVideoData from '../use-video-data'; +import { VideoDataProps } from '../use-video-data/types'; +import useMediaDataUpdate from '../use-video-data-update'; +import { useVideoPosterData } from '../use-video-poster-data'; +/** + * Types + */ +import type { UseSyncMedia, ArrangeTracksAttributesProps } from './types'; +import type { UploadTrackDataProps } from '../../../lib/video-tracks/types'; + +const isNative = Platform.isNative; + +const debug = debugFactory( 'videopress:video:use-sync-media' ); + +/* + * Fields list to keep in sync with block attributes. + */ +const videoFieldsToUpdate = [ + 'post_id', + 'title', + 'description', + 'privacy_setting', + 'rating', + 'allow_download', + 'display_embed', + 'is_private', + 'duration', +]; + +/* + * Map object from video field name to block attribute name. + * Only register those fields that have a different attribute name. + */ +const mapFieldsToAttributes = { + privacy_setting: 'privacySetting', + allow_download: 'allowDownload', + display_embed: 'displayEmbed', + is_private: 'isPrivate', + post_id: 'id', +}; + +/* + * Fields list that should invalidate the resolution of the embed (player) + * when some of them change. + * + * Keep in mind some field changes + * are handled inidrectly by the VideoPress video URL, + * for instance, `loop`, `autoplay`, `color`, etc... + */ +const invalidateEmbedResolutionFields = [ + 'title', + 'privacy_setting', + 'is_private', + 'allow_download', + 'display_embed', +]; + +/** + * Re-arrange the tracks to match the block attribute format. + * Also, check if the tracks is out of sync with the media item. + * + * @param {VideoDataProps} videoData - Video data, provided by server. + * @param {VideoBlockAttributes} attributes - Block attributes. + * @returns {VideoBlockAttributes} Video block attributes. + */ +function arrangeTracksAttributes( + videoData: VideoDataProps, + attributes: VideoBlockAttributes +): ArrangeTracksAttributesProps { + if ( ! videoData?.tracks ) { + return [ [], false ]; + } + + const tracks = []; + let tracksOufOfSync = false; + + // Checks if every video track is in sync with the block + // attributes, to add tracks to the block attributes if needed + Object.keys( videoData.tracks ).forEach( kind => { + for ( const srcLang in videoData.tracks[ kind ] ) { + const track = videoData.tracks[ kind ][ srcLang ]; + const trackExistsInBlock = attributes.tracks.find( t => { + return ( + t.kind === kind && t.srcLang === srcLang && t.src === track.src && t.label === track.label + ); + } ); + + if ( ! trackExistsInBlock ) { + debug( 'Track %o is out of sync. Set tracks attr', track.src ); + tracksOufOfSync = true; + } + + tracks.push( { + src: track.src, + kind, + srcLang, + label: track.label, + } ); + } + } ); + + /* + * Checks if every block attributes track is in sync with the media + * item, to remove tracks from the block attributes if needed + */ + attributes.tracks.forEach( blockTrack => { + const trackInMedia = videoData.tracks[ blockTrack.kind ]?.[ blockTrack.srcLang ]; + const trackExistsInMedia = + trackInMedia && + trackInMedia.src === blockTrack.src && + trackInMedia.label === blockTrack.label; + + if ( ! trackExistsInMedia ) { + debug( 'Block track %o is out of sync and will be removed', blockTrack.src ); + tracksOufOfSync = true; + } + } ); + + return [ tracks, tracksOufOfSync ]; +} + +/** + * React hook to keep the data in-sync + * between the media item and the block attributes. + * + * @param {object} attributes - Block attributes. + * @param {Function} setAttributes - Block attributes setter. + * @returns {UseSyncMedia} Hook API object. + */ +export function useSyncMedia( + attributes: VideoBlockAttributes, + setAttributes: VideoBlockSetAttributesProps +): UseSyncMedia { + const { id, guid, isPrivate } = attributes; + const { videoData, isRequestingVideoData } = useVideoData( { + id, + guid, + skipRatingControl: true, + maybeIsPrivate: isPrivate, + } ); + + const [ isOverwriteChapterAllowed, setIsOverwriteChapterAllowed ] = useState( false ); + + const isSaving = useSelect( select => select( editorStore ).isSavingPost(), [] ); + const wasSaving = usePrevious( isSaving ); + + // In native, it's not currently possible to access a post's saved state from the editor store. + // We therefore need to listen to a native event emitter to know when a post has just been saved. + const [ postHasBeenJustSavedNative, setPostHasBeenJustSavedNative ] = useState( false ); + + useEffect( () => { + if ( ! isNative ) { + return; + } + + const subscription = subscribePostSaveEvent( () => setPostHasBeenJustSavedNative( true ) ); + + return () => { + subscription?.remove(); + }; + }, [] ); + + const invalidateResolution = useDispatch( coreStore ).invalidateResolution; + + const [ initialState, setState ] = useState< VideoDataProps >( {} ); + + const [ error, setError ] = useState( null ); + + const updateInitialState = useCallback( ( data: VideoDataProps ) => { + setState( current => ( { ...current, ...data } ) ); + }, [] ); + + /* + * Media data => Block attributes (update) + * + * Populate block attributes with the media data, + * provided by the VideoPress API (useVideoData hook), + * when the block is mounted. + */ + useEffect( () => { + if ( isRequestingVideoData ) { + return; + } + + // Bail early if the video data is not available. + if ( + ! videoData || + Object.keys( videoData ).filter( key => videoFieldsToUpdate.includes( key ) ).length === 0 + ) { + return; + } + + const attributesToUpdate: VideoBlockAttributes = {}; + + // Build an object with video data to use for the initial state. + const initialVideoData = videoFieldsToUpdate.reduce( ( acc, key ) => { + if ( typeof videoData[ key ] === 'undefined' ) { + return acc; + } + + let videoDataValue = videoData[ key ]; + + // Cast privacy_setting to number to match the block attribute type. + if ( 'privacy_setting' === key ) { + videoDataValue = Number( videoDataValue ); + } + + acc[ key ] = videoDataValue; + const attrName = mapFieldsToAttributes[ key ] || snakeToCamel( key ); + + if ( videoDataValue !== attributes[ attrName ] ) { + debug( + '%o is out of sync. Updating %o attr from %o to %o ', + key, + attrName, + attributes[ attrName ], + videoDataValue + ); + attributesToUpdate[ attrName ] = videoDataValue; + } + return acc; + }, {} ); + + updateInitialState( initialVideoData ); + debug( 'Initial state: ', initialVideoData ); + + if ( ! Object.keys( initialVideoData ).length ) { + return; + } + + // Sync video tracks if needed. + const [ tracks, tracksOufOfSync ] = arrangeTracksAttributes( videoData, attributes ); + if ( tracksOufOfSync ) { + attributesToUpdate.tracks = tracks; + } + + if ( ! Object.keys( attributesToUpdate ).length ) { + return; + } + + debug( 'Updating attributes: ', attributesToUpdate ); + setAttributes( attributesToUpdate ); + }, [ videoData, isRequestingVideoData ] ); + + const chapterFileUrl = attributes.tracks.filter( + track => track.kind === 'chapters' && track.srcLang === 'en' + )[ 0 ]?.src; + + useEffect( () => { + ( async () => { + // Check if the (default) chapter file has been autogenerated. + if ( ! chapterFileUrl ) { + debug( 'Allow overwrite chapter: File does not exist' ); + setIsOverwriteChapterAllowed( true ); + } else { + const chapterUrl = 'https://videos.files.wordpress.com/' + guid + '/' + chapterFileUrl; + const isAutogenerated = await isAutogeneratedChapterFile( chapterUrl, { guid, isPrivate } ); + debug( + 'Chapter %o detected. Overwritable: %o', + chapterFileUrl, + isAutogenerated ? 'yes' : 'no' + ); + setIsOverwriteChapterAllowed( isAutogenerated ); + } + } )(); + }, [ chapterFileUrl ] ); + + const updateMediaHandler = useMediaDataUpdate( id ); + + const postHasBeenJustSaved = isNative + ? postHasBeenJustSavedNative + : !! ( wasSaving && ! isSaving ); + + /* + * Video frame poster: Block attributes => Frame poster generation + * + * Store and compare the block attributes + * in order to detect changes on them. + */ + const { isGeneratingPoster } = useVideoPosterData( attributes ); + + /* + * Block attributes => Media data (sync) + * + * Compare the current attribute values of the block + * with the initial state, + * and sync the media data if it detects changes on it + * (via the VideoPress API) when the post saves. + */ + useEffect( () => { + if ( ! postHasBeenJustSaved ) { + return; + } + + debug( '%o Post has been just saved. Syncing...', attributes?.guid ); + + isNative && setPostHasBeenJustSavedNative( false ); + + if ( ! attributes?.id ) { + debug( '%o No media ID found. Impossible to sync. Bail early', attributes?.guid ); + return; + } + + /* + * Filter the attributes that have changed their values, + * based on the initial state. + */ + const dataToUpdate: WPComV2VideopressPostMetaEndpointBodyProps = videoFieldsToUpdate.reduce( + ( acc, key ) => { + const attrName = mapFieldsToAttributes[ key ] || key; + const stateValue = initialState[ key ]; + const attrValue = attributes[ attrName ]; + + if ( initialState[ key ] !== attributes[ attrName ] ) { + debug( 'Field to sync %o: %o => %o: %o', key, stateValue, attrName, attrValue ); + acc[ key ] = attributes[ attrName ]; + } + return acc; + }, + {} + ); + + // When nothing to update, bail out early. + if ( ! Object.keys( dataToUpdate ).length ) { + return debug( 'No data to sync. Bail early' ); + } + + debug( 'Syncing data: ', dataToUpdate ); + + // Sync the block attributes data with the video data + updateMediaHandler( dataToUpdate ) + .then( () => { + // Update local state with fresh video data. + updateInitialState( dataToUpdate ); + + /* + * Update isPrivate attribute: + * `is_private` is a read-only metadata field. + * The VideoPress API provides its value + * and depends on the `privacy_setting` + * and `private_enabled_for_site` fields. + */ + if ( dataToUpdate.privacy_setting ) { + const isPrivateVideo = + dataToUpdate.privacy_setting !== 2 + ? dataToUpdate.privacy_setting === 1 + : videoData.private_enabled_for_site; + + debug( 'Updating isPrivate attribute: %o', isPrivateVideo ); + setAttributes( { isPrivate: isPrivateVideo } ); + } + + // | Video Chapters feature | + const chapters = extractVideoChapters( dataToUpdate?.description ); + + if ( + isOverwriteChapterAllowed && + attributes?.guid && + dataToUpdate?.description?.length && + validateChapters( chapters ) && + ! isNative + ) { + debug( 'Autogenerated chapter detected. Processing...' ); + const track: UploadTrackDataProps = { + label: __( 'English (auto-generated)', 'jetpack-videopress-pkg' ), + srcLang: 'en', + kind: 'chapters', + tmpFile: generateChaptersFile( dataToUpdate.description ), + }; + + debug( 'Autogenerated track: %o', track ); + + uploadTrackForGuid( track, attributes.guid ).then( ( src: string ) => { + const autoGeneratedTrackIndex = attributes.tracks.findIndex( + t => t.kind === 'chapters' && t.srcLang === 'en' + ); + + const uploadedTrack = { + ...track, + src, + }; + + const tracks = [ ...attributes.tracks ]; + + if ( autoGeneratedTrackIndex > -1 ) { + debug( 'Updating %o auto-generated track', uploadedTrack.src ); + tracks[ autoGeneratedTrackIndex ] = uploadedTrack; + } else { + debug( 'Adding auto-generated %o track', uploadedTrack.src ); + tracks.push( uploadedTrack ); + } + + // Update block track attribute + setAttributes( { tracks } ); + + const videoPressUrl = getVideoPressUrl( attributes.guid, attributes ); + invalidateResolution( 'getEmbedPreview', [ videoPressUrl ] ); + } ); + } else { + const shouldInvalidateResolution = Object.keys( dataToUpdate ).filter( key => + invalidateEmbedResolutionFields.includes( key ) + ); + + if ( shouldInvalidateResolution?.length ) { + debug( 'Invalidate resolution because of %o', shouldInvalidateResolution.join( ', ' ) ); + + const videoPressUrl = getVideoPressUrl( attributes.guid, attributes ); + invalidateResolution( 'getEmbedPreview', [ videoPressUrl ] ); + } + } + } ) + .catch( ( updateMediaError: Error ) => { + debug( '%o Error while syncing data: %o', attributes?.guid, updateMediaError ); + setError( updateMediaError ); + } ); + }, [ + postHasBeenJustSaved, + updateMediaHandler, + updateInitialState, + attributes, + initialState, + invalidateResolution, + videoFieldsToUpdate, + ] ); + + return { + forceInitialState: updateInitialState, + videoData, + isRequestingVideoData, + error, + isOverwriteChapterAllowed, + isGeneratingPoster, + }; +} From f050d65352cffb62cf1ef2b2824168df43c02a82 Mon Sep 17 00:00:00 2001 From: Siobhan Date: Wed, 19 Apr 2023 10:38:19 +0100 Subject: [PATCH 10/14] refactor: Remove native functionality in web file --- .../hooks/use-sync-media/index.ts | 30 ++----------------- 1 file changed, 3 insertions(+), 27 deletions(-) diff --git a/projects/packages/videopress/src/client/block-editor/hooks/use-sync-media/index.ts b/projects/packages/videopress/src/client/block-editor/hooks/use-sync-media/index.ts index 8d9822f09a6ce..ebc304b4a9e0b 100644 --- a/projects/packages/videopress/src/client/block-editor/hooks/use-sync-media/index.ts +++ b/projects/packages/videopress/src/client/block-editor/hooks/use-sync-media/index.ts @@ -5,9 +5,8 @@ import { usePrevious } from '@wordpress/compose'; import { store as coreStore } from '@wordpress/core-data'; import { useSelect, useDispatch } from '@wordpress/data'; import { store as editorStore } from '@wordpress/editor'; -import { useEffect, useState, useCallback, Platform } from '@wordpress/element'; +import { useEffect, useState, useCallback } from '@wordpress/element'; import { __ } from '@wordpress/i18n'; -import { subscribePostSaveEvent } from '@wordpress/react-native-bridge'; import debugFactory from 'debug'; /** * Internal dependencies @@ -31,8 +30,6 @@ import { useVideoPosterData } from '../use-video-poster-data'; import type { UseSyncMedia, ArrangeTracksAttributesProps } from './types'; import type { UploadTrackDataProps } from '../../../lib/video-tracks/types'; -const isNative = Platform.isNative; - const debug = debugFactory( 'videopress:video:use-sync-media' ); /* @@ -167,22 +164,6 @@ export function useSyncMedia( const isSaving = useSelect( select => select( editorStore ).isSavingPost(), [] ); const wasSaving = usePrevious( isSaving ); - // In native, it's not currently possible to access a post's saved state from the editor store. - // We therefore need to listen to a native event emitter to know when a post has just been saved. - const [ postHasBeenJustSavedNative, setPostHasBeenJustSavedNative ] = useState( false ); - - useEffect( () => { - if ( ! isNative ) { - return; - } - - const subscription = subscribePostSaveEvent( () => setPostHasBeenJustSavedNative( true ) ); - - return () => { - subscription?.remove(); - }; - }, [] ); - const invalidateResolution = useDispatch( coreStore ).invalidateResolution; const [ initialState, setState ] = useState< VideoDataProps >( {} ); @@ -290,9 +271,7 @@ export function useSyncMedia( const updateMediaHandler = useMediaDataUpdate( id ); - const postHasBeenJustSaved = isNative - ? postHasBeenJustSavedNative - : !! ( wasSaving && ! isSaving ); + const postHasBeenJustSaved = !! ( wasSaving && ! isSaving ); /* * Video frame poster: Block attributes => Frame poster generation @@ -317,8 +296,6 @@ export function useSyncMedia( debug( '%o Post has been just saved. Syncing...', attributes?.guid ); - isNative && setPostHasBeenJustSavedNative( false ); - if ( ! attributes?.id ) { debug( '%o No media ID found. Impossible to sync. Bail early', attributes?.guid ); return; @@ -380,8 +357,7 @@ export function useSyncMedia( isOverwriteChapterAllowed && attributes?.guid && dataToUpdate?.description?.length && - validateChapters( chapters ) && - ! isNative + validateChapters( chapters ) ) { debug( 'Autogenerated chapter detected. Processing...' ); const track: UploadTrackDataProps = { From 2505fb12861ca7dd50e407afe997e6e1256dd137 Mon Sep 17 00:00:00 2001 From: Siobhan Date: Wed, 19 Apr 2023 12:01:10 +0100 Subject: [PATCH 11/14] refactor: Switch from .ts to .js --- .../use-sync-media/{index.native.ts => index.native.js} | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) rename projects/packages/videopress/src/client/block-editor/hooks/use-sync-media/{index.native.ts => index.native.js} (98%) diff --git a/projects/packages/videopress/src/client/block-editor/hooks/use-sync-media/index.native.ts b/projects/packages/videopress/src/client/block-editor/hooks/use-sync-media/index.native.js similarity index 98% rename from projects/packages/videopress/src/client/block-editor/hooks/use-sync-media/index.native.ts rename to projects/packages/videopress/src/client/block-editor/hooks/use-sync-media/index.native.js index 8d9822f09a6ce..e2e8772343439 100644 --- a/projects/packages/videopress/src/client/block-editor/hooks/use-sync-media/index.native.ts +++ b/projects/packages/videopress/src/client/block-editor/hooks/use-sync-media/index.native.js @@ -13,8 +13,7 @@ import debugFactory from 'debug'; * Internal dependencies */ import { getVideoPressUrl } from '../../../lib/url'; -import { uploadTrackForGuid } from '../../../lib/video-tracks'; -import { isAutogeneratedChapterFile } from '../../../lib/video-tracks'; +import { isAutogeneratedChapterFile, uploadTrackForGuid } from '../../../lib/video-tracks'; import { WPComV2VideopressPostMetaEndpointBodyProps } from '../../../types'; import { snakeToCamel } from '../../../utils/map-object-keys-to-camel-case'; import extractVideoChapters from '../../../utils/video-chapters/extract-video-chapters'; @@ -185,7 +184,7 @@ export function useSyncMedia( const invalidateResolution = useDispatch( coreStore ).invalidateResolution; - const [ initialState, setState ] = useState< VideoDataProps >( {} ); + const [ initialState, setState ] = useState < VideoDataProps > {}; const [ error, setError ] = useState( null ); From 321d34361653428162d6867454acb35189a98038 Mon Sep 17 00:00:00 2001 From: Siobhan Date: Wed, 19 Apr 2023 12:49:54 +0100 Subject: [PATCH 12/14] refactor: Strip hook down to native functionality --- .../hooks/use-sync-media/index.native.js | 258 +++--------------- 1 file changed, 33 insertions(+), 225 deletions(-) diff --git a/projects/packages/videopress/src/client/block-editor/hooks/use-sync-media/index.native.js b/projects/packages/videopress/src/client/block-editor/hooks/use-sync-media/index.native.js index e2e8772343439..e6f41f4be50e4 100644 --- a/projects/packages/videopress/src/client/block-editor/hooks/use-sync-media/index.native.js +++ b/projects/packages/videopress/src/client/block-editor/hooks/use-sync-media/index.native.js @@ -1,36 +1,18 @@ /** * External dependencies */ -import { usePrevious } from '@wordpress/compose'; import { store as coreStore } from '@wordpress/core-data'; -import { useSelect, useDispatch } from '@wordpress/data'; -import { store as editorStore } from '@wordpress/editor'; -import { useEffect, useState, useCallback, Platform } from '@wordpress/element'; -import { __ } from '@wordpress/i18n'; +import { useDispatch } from '@wordpress/data'; +import { useEffect, useState, useCallback } from '@wordpress/element'; import { subscribePostSaveEvent } from '@wordpress/react-native-bridge'; import debugFactory from 'debug'; /** * Internal dependencies */ import { getVideoPressUrl } from '../../../lib/url'; -import { isAutogeneratedChapterFile, uploadTrackForGuid } from '../../../lib/video-tracks'; -import { WPComV2VideopressPostMetaEndpointBodyProps } from '../../../types'; import { snakeToCamel } from '../../../utils/map-object-keys-to-camel-case'; -import extractVideoChapters from '../../../utils/video-chapters/extract-video-chapters'; -import generateChaptersFile from '../../../utils/video-chapters/generate-chapters-file'; -import validateChapters from '../../../utils/video-chapters/validate-chapters'; -import { VideoBlockAttributes, VideoBlockSetAttributesProps } from '../../blocks/video/types'; import useVideoData from '../use-video-data'; -import { VideoDataProps } from '../use-video-data/types'; import useMediaDataUpdate from '../use-video-data-update'; -import { useVideoPosterData } from '../use-video-poster-data'; -/** - * Types - */ -import type { UseSyncMedia, ArrangeTracksAttributesProps } from './types'; -import type { UploadTrackDataProps } from '../../../lib/video-tracks/types'; - -const isNative = Platform.isNative; const debug = debugFactory( 'videopress:video:use-sync-media' ); @@ -77,82 +59,15 @@ const invalidateEmbedResolutionFields = [ 'display_embed', ]; -/** - * Re-arrange the tracks to match the block attribute format. - * Also, check if the tracks is out of sync with the media item. - * - * @param {VideoDataProps} videoData - Video data, provided by server. - * @param {VideoBlockAttributes} attributes - Block attributes. - * @returns {VideoBlockAttributes} Video block attributes. - */ -function arrangeTracksAttributes( - videoData: VideoDataProps, - attributes: VideoBlockAttributes -): ArrangeTracksAttributesProps { - if ( ! videoData?.tracks ) { - return [ [], false ]; - } - - const tracks = []; - let tracksOufOfSync = false; - - // Checks if every video track is in sync with the block - // attributes, to add tracks to the block attributes if needed - Object.keys( videoData.tracks ).forEach( kind => { - for ( const srcLang in videoData.tracks[ kind ] ) { - const track = videoData.tracks[ kind ][ srcLang ]; - const trackExistsInBlock = attributes.tracks.find( t => { - return ( - t.kind === kind && t.srcLang === srcLang && t.src === track.src && t.label === track.label - ); - } ); - - if ( ! trackExistsInBlock ) { - debug( 'Track %o is out of sync. Set tracks attr', track.src ); - tracksOufOfSync = true; - } - - tracks.push( { - src: track.src, - kind, - srcLang, - label: track.label, - } ); - } - } ); - - /* - * Checks if every block attributes track is in sync with the media - * item, to remove tracks from the block attributes if needed - */ - attributes.tracks.forEach( blockTrack => { - const trackInMedia = videoData.tracks[ blockTrack.kind ]?.[ blockTrack.srcLang ]; - const trackExistsInMedia = - trackInMedia && - trackInMedia.src === blockTrack.src && - trackInMedia.label === blockTrack.label; - - if ( ! trackExistsInMedia ) { - debug( 'Block track %o is out of sync and will be removed', blockTrack.src ); - tracksOufOfSync = true; - } - } ); - - return [ tracks, tracksOufOfSync ]; -} - /** * React hook to keep the data in-sync * between the media item and the block attributes. * - * @param {object} attributes - Block attributes. - * @param {Function} setAttributes - Block attributes setter. - * @returns {UseSyncMedia} Hook API object. + * @param {object} attributes - Block attributes. + * @param {Function} setAttributes - Block attributes setter. + * @returns {object} - Hook API object. */ -export function useSyncMedia( - attributes: VideoBlockAttributes, - setAttributes: VideoBlockSetAttributesProps -): UseSyncMedia { +export function useSyncMedia( attributes, setAttributes ) { const { id, guid, isPrivate } = attributes; const { videoData, isRequestingVideoData } = useVideoData( { id, @@ -161,21 +76,12 @@ export function useSyncMedia( maybeIsPrivate: isPrivate, } ); - const [ isOverwriteChapterAllowed, setIsOverwriteChapterAllowed ] = useState( false ); - - const isSaving = useSelect( select => select( editorStore ).isSavingPost(), [] ); - const wasSaving = usePrevious( isSaving ); - // In native, it's not currently possible to access a post's saved state from the editor store. // We therefore need to listen to a native event emitter to know when a post has just been saved. - const [ postHasBeenJustSavedNative, setPostHasBeenJustSavedNative ] = useState( false ); + const [ postHasBeenJustSaved, setPostHasBeenJustSaved ] = useState( false ); useEffect( () => { - if ( ! isNative ) { - return; - } - - const subscription = subscribePostSaveEvent( () => setPostHasBeenJustSavedNative( true ) ); + const subscription = subscribePostSaveEvent( () => setPostHasBeenJustSaved( true ) ); return () => { subscription?.remove(); @@ -184,11 +90,11 @@ export function useSyncMedia( const invalidateResolution = useDispatch( coreStore ).invalidateResolution; - const [ initialState, setState ] = useState < VideoDataProps > {}; + const [ initialState, setState ] = useState( {} ); const [ error, setError ] = useState( null ); - const updateInitialState = useCallback( ( data: VideoDataProps ) => { + const updateInitialState = useCallback( data => { setState( current => ( { ...current, ...data } ) ); }, [] ); @@ -212,7 +118,7 @@ export function useSyncMedia( return; } - const attributesToUpdate: VideoBlockAttributes = {}; + const attributesToUpdate = {}; // Build an object with video data to use for the initial state. const initialVideoData = videoFieldsToUpdate.reduce( ( acc, key ) => { @@ -246,17 +152,7 @@ export function useSyncMedia( updateInitialState( initialVideoData ); debug( 'Initial state: ', initialVideoData ); - if ( ! Object.keys( initialVideoData ).length ) { - return; - } - - // Sync video tracks if needed. - const [ tracks, tracksOufOfSync ] = arrangeTracksAttributes( videoData, attributes ); - if ( tracksOufOfSync ) { - attributesToUpdate.tracks = tracks; - } - - if ( ! Object.keys( attributesToUpdate ).length ) { + if ( ! Object.keys( initialVideoData ).length || Object.keys( attributesToUpdate ).length ) { return; } @@ -264,43 +160,8 @@ export function useSyncMedia( setAttributes( attributesToUpdate ); }, [ videoData, isRequestingVideoData ] ); - const chapterFileUrl = attributes.tracks.filter( - track => track.kind === 'chapters' && track.srcLang === 'en' - )[ 0 ]?.src; - - useEffect( () => { - ( async () => { - // Check if the (default) chapter file has been autogenerated. - if ( ! chapterFileUrl ) { - debug( 'Allow overwrite chapter: File does not exist' ); - setIsOverwriteChapterAllowed( true ); - } else { - const chapterUrl = 'https://videos.files.wordpress.com/' + guid + '/' + chapterFileUrl; - const isAutogenerated = await isAutogeneratedChapterFile( chapterUrl, { guid, isPrivate } ); - debug( - 'Chapter %o detected. Overwritable: %o', - chapterFileUrl, - isAutogenerated ? 'yes' : 'no' - ); - setIsOverwriteChapterAllowed( isAutogenerated ); - } - } )(); - }, [ chapterFileUrl ] ); - const updateMediaHandler = useMediaDataUpdate( id ); - const postHasBeenJustSaved = isNative - ? postHasBeenJustSavedNative - : !! ( wasSaving && ! isSaving ); - - /* - * Video frame poster: Block attributes => Frame poster generation - * - * Store and compare the block attributes - * in order to detect changes on them. - */ - const { isGeneratingPoster } = useVideoPosterData( attributes ); - /* * Block attributes => Media data (sync) * @@ -316,7 +177,7 @@ export function useSyncMedia( debug( '%o Post has been just saved. Syncing...', attributes?.guid ); - isNative && setPostHasBeenJustSavedNative( false ); + setPostHasBeenJustSaved( false ); if ( ! attributes?.id ) { debug( '%o No media ID found. Impossible to sync. Bail early', attributes?.guid ); @@ -327,20 +188,17 @@ export function useSyncMedia( * Filter the attributes that have changed their values, * based on the initial state. */ - const dataToUpdate: WPComV2VideopressPostMetaEndpointBodyProps = videoFieldsToUpdate.reduce( - ( acc, key ) => { - const attrName = mapFieldsToAttributes[ key ] || key; - const stateValue = initialState[ key ]; - const attrValue = attributes[ attrName ]; - - if ( initialState[ key ] !== attributes[ attrName ] ) { - debug( 'Field to sync %o: %o => %o: %o', key, stateValue, attrName, attrValue ); - acc[ key ] = attributes[ attrName ]; - } - return acc; - }, - {} - ); + const dataToUpdate = videoFieldsToUpdate.reduce( ( acc, key ) => { + const attrName = mapFieldsToAttributes[ key ] || key; + const stateValue = initialState[ key ]; + const attrValue = attributes[ attrName ]; + + if ( initialState[ key ] !== attributes[ attrName ] ) { + debug( 'Field to sync %o: %o => %o: %o', key, stateValue, attrName, attrValue ); + acc[ key ] = attributes[ attrName ]; + } + return acc; + }, {} ); // When nothing to update, bail out early. if ( ! Object.keys( dataToUpdate ).length ) { @@ -372,63 +230,15 @@ export function useSyncMedia( setAttributes( { isPrivate: isPrivateVideo } ); } - // | Video Chapters feature | - const chapters = extractVideoChapters( dataToUpdate?.description ); - - if ( - isOverwriteChapterAllowed && - attributes?.guid && - dataToUpdate?.description?.length && - validateChapters( chapters ) && - ! isNative - ) { - debug( 'Autogenerated chapter detected. Processing...' ); - const track: UploadTrackDataProps = { - label: __( 'English (auto-generated)', 'jetpack-videopress-pkg' ), - srcLang: 'en', - kind: 'chapters', - tmpFile: generateChaptersFile( dataToUpdate.description ), - }; - - debug( 'Autogenerated track: %o', track ); - - uploadTrackForGuid( track, attributes.guid ).then( ( src: string ) => { - const autoGeneratedTrackIndex = attributes.tracks.findIndex( - t => t.kind === 'chapters' && t.srcLang === 'en' - ); - - const uploadedTrack = { - ...track, - src, - }; - - const tracks = [ ...attributes.tracks ]; - - if ( autoGeneratedTrackIndex > -1 ) { - debug( 'Updating %o auto-generated track', uploadedTrack.src ); - tracks[ autoGeneratedTrackIndex ] = uploadedTrack; - } else { - debug( 'Adding auto-generated %o track', uploadedTrack.src ); - tracks.push( uploadedTrack ); - } - - // Update block track attribute - setAttributes( { tracks } ); - - const videoPressUrl = getVideoPressUrl( attributes.guid, attributes ); - invalidateResolution( 'getEmbedPreview', [ videoPressUrl ] ); - } ); - } else { - const shouldInvalidateResolution = Object.keys( dataToUpdate ).filter( key => - invalidateEmbedResolutionFields.includes( key ) - ); - - if ( shouldInvalidateResolution?.length ) { - debug( 'Invalidate resolution because of %o', shouldInvalidateResolution.join( ', ' ) ); - - const videoPressUrl = getVideoPressUrl( attributes.guid, attributes ); - invalidateResolution( 'getEmbedPreview', [ videoPressUrl ] ); - } + const shouldInvalidateResolution = Object.keys( dataToUpdate ).filter( key => + invalidateEmbedResolutionFields.includes( key ) + ); + + if ( shouldInvalidateResolution?.length ) { + debug( 'Invalidate resolution because of %o', shouldInvalidateResolution.join( ', ' ) ); + + const videoPressUrl = getVideoPressUrl( attributes.guid, attributes ); + invalidateResolution( 'getEmbedPreview', [ videoPressUrl ] ); } } ) .catch( ( updateMediaError: Error ) => { @@ -450,7 +260,5 @@ export function useSyncMedia( videoData, isRequestingVideoData, error, - isOverwriteChapterAllowed, - isGeneratingPoster, }; } From 6fcbcb2611939093006e80fda6e15d17a19f801c Mon Sep 17 00:00:00 2001 From: Siobhan Date: Wed, 19 Apr 2023 12:57:01 +0100 Subject: [PATCH 13/14] fix: Revert typo preventing attributes updating --- .../client/block-editor/hooks/use-sync-media/index.native.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/packages/videopress/src/client/block-editor/hooks/use-sync-media/index.native.js b/projects/packages/videopress/src/client/block-editor/hooks/use-sync-media/index.native.js index e6f41f4be50e4..b3765ff94ef54 100644 --- a/projects/packages/videopress/src/client/block-editor/hooks/use-sync-media/index.native.js +++ b/projects/packages/videopress/src/client/block-editor/hooks/use-sync-media/index.native.js @@ -152,7 +152,7 @@ export function useSyncMedia( attributes, setAttributes ) { updateInitialState( initialVideoData ); debug( 'Initial state: ', initialVideoData ); - if ( ! Object.keys( initialVideoData ).length || Object.keys( attributesToUpdate ).length ) { + if ( ! Object.keys( initialVideoData ).length || ! Object.keys( attributesToUpdate ).length ) { return; } From 8134843267cd7bd0be1ef547fb4da0c4e917df9b Mon Sep 17 00:00:00 2001 From: Siobhan Date: Wed, 19 Apr 2023 13:04:15 +0100 Subject: [PATCH 14/14] refactor: Revert intro of new line --- .../src/client/block-editor/hooks/use-sync-media/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/projects/packages/videopress/src/client/block-editor/hooks/use-sync-media/index.ts b/projects/packages/videopress/src/client/block-editor/hooks/use-sync-media/index.ts index ebc304b4a9e0b..6ef88b4346828 100644 --- a/projects/packages/videopress/src/client/block-editor/hooks/use-sync-media/index.ts +++ b/projects/packages/videopress/src/client/block-editor/hooks/use-sync-media/index.ts @@ -163,7 +163,6 @@ export function useSyncMedia( const isSaving = useSelect( select => select( editorStore ).isSavingPost(), [] ); const wasSaving = usePrevious( isSaving ); - const invalidateResolution = useDispatch( coreStore ).invalidateResolution; const [ initialState, setState ] = useState< VideoDataProps >( {} );