diff --git a/package-lock.json b/package-lock.json index 85adeb5c4b5634..6852e3b67333f1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -56227,7 +56227,9 @@ "@shopify/web-worker": "^6.4.0", "@wordpress/api-fetch": "file:../api-fetch", "@wordpress/blob": "file:../blob", + "@wordpress/compose": "file:../compose", "@wordpress/data": "file:../data", + "@wordpress/element": "file:../element", "@wordpress/i18n": "file:../i18n", "@wordpress/preferences": "file:../preferences", "@wordpress/private-apis": "file:../private-apis", diff --git a/packages/block-editor/src/components/provider/index.js b/packages/block-editor/src/components/provider/index.js index abbb122ae3a0e0..38e67f23e60518 100644 --- a/packages/block-editor/src/components/provider/index.js +++ b/packages/block-editor/src/components/provider/index.js @@ -4,6 +4,8 @@ import { useDispatch } from '@wordpress/data'; import { useEffect } from '@wordpress/element'; import { SlotFillProvider } from '@wordpress/components'; +//eslint-disable-next-line import/no-extraneous-dependencies -- Experimental package, not published. +import { MediaUploadProvider } from '@wordpress/upload-media'; /** * Internal dependencies @@ -14,12 +16,13 @@ import { store as blockEditorStore } from '../../store'; import { BlockRefsProvider } from './block-refs-provider'; import { unlock } from '../../lock-unlock'; import KeyboardShortcuts from '../keyboard-shortcuts'; +import useMediaUploadSettings from './use-media-upload-settings'; /** @typedef {import('@wordpress/data').WPDataRegistry} WPDataRegistry */ export const ExperimentalBlockEditorProvider = withRegistryProvider( ( props ) => { - const { children, settings, stripExperimentalSettings = false } = props; + const { settings, stripExperimentalSettings = false } = props; const { __experimentalUpdateSettings } = unlock( useDispatch( blockEditorStore ) @@ -44,12 +47,27 @@ export const ExperimentalBlockEditorProvider = withRegistryProvider( // Syncs the entity provider with changes in the block-editor store. useBlockSync( props ); - return ( + const children = ( { ! settings?.isPreviewMode && } - { children } + { props.children } ); + + const mediaUploadSettings = useMediaUploadSettings( settings ); + + if ( window.__experimentalMediaProcessing ) { + return ( + + { children } + + ); + } + + return children; } ); diff --git a/packages/block-editor/src/components/provider/use-media-upload-settings.js b/packages/block-editor/src/components/provider/use-media-upload-settings.js new file mode 100644 index 00000000000000..cb8e3b70246854 --- /dev/null +++ b/packages/block-editor/src/components/provider/use-media-upload-settings.js @@ -0,0 +1,23 @@ +/** + * WordPress dependencies + */ +import { useMemo } from '@wordpress/element'; + +/** + * React hook used to compute the media upload settings to use in the post editor. + * + * @param {Object} settings Media upload settings prop. + * + * @return {Object} Media upload settings. + */ +function useMediaUploadSettings( settings ) { + return useMemo( + () => ( { + mediaUpload: settings.mediaUpload, + mediaSideload: settings.__experimentalMediaSideload, + } ), + [ settings ] + ); +} + +export default useMediaUploadSettings; diff --git a/packages/editor/src/components/provider/use-block-editor-settings.js b/packages/editor/src/components/provider/use-block-editor-settings.js index 170ec96c107288..6df2610812df45 100644 --- a/packages/editor/src/components/provider/use-block-editor-settings.js +++ b/packages/editor/src/components/provider/use-block-editor-settings.js @@ -22,6 +22,7 @@ import { */ import inserterMediaCategories from '../media-categories'; import { mediaUpload } from '../../utils'; +import { default as mediaSideload } from '../../utils/media-sideload'; import { store as editorStore } from '../../store'; import { unlock } from '../../lock-unlock'; import { useGlobalStylesContext } from '../global-styles-provider'; @@ -294,6 +295,9 @@ function useBlockEditorSettings( settings, postType, postId, renderingMode ) { isDistractionFree, keepCaretInsideBlock, mediaUpload: hasUploadPermissions ? mediaUpload : undefined, + __experimentalMediaSideload: hasUploadPermissions + ? mediaSideload + : undefined, __experimentalBlockPatterns: blockPatterns, [ selectBlockPatternsKey ]: ( select ) => { const { hasFinishedResolution, getBlockPatternsForPostType } = diff --git a/packages/editor/src/utils/media-sideload/index.js b/packages/editor/src/utils/media-sideload/index.js new file mode 100644 index 00000000000000..b4aa133fb2d63e --- /dev/null +++ b/packages/editor/src/utils/media-sideload/index.js @@ -0,0 +1,13 @@ +/** + * WordPress dependencies + */ +import { privateApis } from '@wordpress/media-utils'; + +/** + * Internal dependencies + */ +import { unlock } from '../../lock-unlock'; + +const { sideloadMedia: mediaSideload = () => {} } = unlock( privateApis ); + +export default mediaSideload; diff --git a/packages/editor/src/utils/media-sideload/index.native.js b/packages/editor/src/utils/media-sideload/index.native.js new file mode 100644 index 00000000000000..d84a912ec92de0 --- /dev/null +++ b/packages/editor/src/utils/media-sideload/index.native.js @@ -0,0 +1 @@ +export default function mediaSideload() {} diff --git a/packages/upload-media/package.json b/packages/upload-media/package.json index 0711ebb12231ab..72523c1bb33a14 100644 --- a/packages/upload-media/package.json +++ b/packages/upload-media/package.json @@ -29,7 +29,9 @@ "@shopify/web-worker": "^6.4.0", "@wordpress/api-fetch": "file:../api-fetch", "@wordpress/blob": "file:../blob", + "@wordpress/compose": "file:../compose", "@wordpress/data": "file:../data", + "@wordpress/element": "file:../element", "@wordpress/i18n": "file:../i18n", "@wordpress/preferences": "file:../preferences", "@wordpress/private-apis": "file:../private-apis", diff --git a/packages/upload-media/src/components/provider/index.tsx b/packages/upload-media/src/components/provider/index.tsx new file mode 100644 index 00000000000000..0bc187e6a1d861 --- /dev/null +++ b/packages/upload-media/src/components/provider/index.tsx @@ -0,0 +1,25 @@ +/** + * WordPress dependencies + */ +import { useEffect } from '@wordpress/element'; +import { useDispatch } from '@wordpress/data'; + +/** + * Internal dependencies + */ +import withRegistryProvider from './with-registry-provider'; +import { unlock } from '../../lock-unlock'; +import { store as uploadStore } from '../../store'; + +const MediaUploadProvider = withRegistryProvider( ( props: any ) => { + const { children, settings } = props; + const { updateSettings } = unlock( useDispatch( uploadStore ) ); + + useEffect( () => { + updateSettings( settings ); + }, [ settings, updateSettings ] ); + + return <>{ children }; +} ); + +export default MediaUploadProvider; diff --git a/packages/upload-media/src/components/provider/with-registry-provider.tsx b/packages/upload-media/src/components/provider/with-registry-provider.tsx new file mode 100644 index 00000000000000..9a47a5601d33ed --- /dev/null +++ b/packages/upload-media/src/components/provider/with-registry-provider.tsx @@ -0,0 +1,59 @@ +/** + * WordPress dependencies + */ +import { useState } from '@wordpress/element'; +import { useRegistry, createRegistry, RegistryProvider } from '@wordpress/data'; +import { createHigherOrderComponent } from '@wordpress/compose'; + +/** + * Internal dependencies + */ +import { storeConfig } from '../../store'; +import { STORE_NAME as mediaUploadStoreName } from '../../store/constants'; + +type WPDataRegistry = ReturnType< typeof createRegistry >; + +function getSubRegistry( + subRegistries: WeakMap< WPDataRegistry, WPDataRegistry >, + registry: WPDataRegistry, + useSubRegistry: boolean +) { + if ( ! useSubRegistry ) { + return registry; + } + let subRegistry = subRegistries.get( registry ); + if ( ! subRegistry ) { + subRegistry = createRegistry( {}, registry ); + subRegistry.registerStore( mediaUploadStoreName, storeConfig ); + subRegistries.set( registry, subRegistry ); + } + return subRegistry; +} + +const withRegistryProvider = createHigherOrderComponent( + ( WrappedComponent ) => + ( { useSubRegistry = true, ...props } ) => { + const registry = useRegistry() as unknown as WPDataRegistry; + const [ subRegistries ] = useState< + WeakMap< WPDataRegistry, WPDataRegistry > + >( () => new WeakMap() ); + const subRegistry = getSubRegistry( + subRegistries, + registry, + useSubRegistry + ); + + if ( subRegistry === registry ) { + return ; + } + + return ( + + + + ); + }, + 'withRegistryProvider' +); + +export default withRegistryProvider; diff --git a/packages/upload-media/src/index.ts b/packages/upload-media/src/index.ts index 63a756727b25f3..406439a5d96f69 100644 --- a/packages/upload-media/src/index.ts +++ b/packages/upload-media/src/index.ts @@ -5,6 +5,7 @@ import { store as uploadStore } from './store'; export { uploadStore as store }; +export { default as MediaUploadProvider } from './components/provider'; export { UploadError } from './upload-error'; export type { diff --git a/packages/upload-media/src/store/constants.ts b/packages/upload-media/src/store/constants.ts new file mode 100644 index 00000000000000..ad0960cf62f46d --- /dev/null +++ b/packages/upload-media/src/store/constants.ts @@ -0,0 +1 @@ +export const STORE_NAME = 'core/upload-media'; diff --git a/packages/upload-media/src/store/index.ts b/packages/upload-media/src/store/index.ts index c6a42f6cd395ba..c74f59ea7a7cf3 100644 --- a/packages/upload-media/src/store/index.ts +++ b/packages/upload-media/src/store/index.ts @@ -12,9 +12,24 @@ import * as privateSelectors from './private-selectors'; import * as actions from './actions'; import * as privateActions from './private-actions'; import { unlock } from '../lock-unlock'; +import { STORE_NAME } from './constants'; -export const STORE_NAME = 'core/upload-media'; +/** + * Media upload data store configuration. + * + * @see https://github.com/WordPress/gutenberg/blob/HEAD/packages/data/README.md#registerStore + */ +export const storeConfig = { + reducer, + selectors, + actions, +}; +/** + * Store definition for the media upload namespace. + * + * @see https://github.com/WordPress/gutenberg/blob/HEAD/packages/data/README.md#createReduxStore + */ export const store = createReduxStore( STORE_NAME, { reducer, selectors, diff --git a/packages/upload-media/tsconfig.json b/packages/upload-media/tsconfig.json index 2862cfa4bb1c8c..bd7ebfb1023d14 100644 --- a/packages/upload-media/tsconfig.json +++ b/packages/upload-media/tsconfig.json @@ -10,7 +10,9 @@ "references": [ { "path": "../api-fetch" }, { "path": "../blob" }, + { "path": "../compose" }, { "path": "../data" }, + { "path": "../element" }, { "path": "../i18n" }, { "path": "../private-apis" }, { "path": "../url" },