From 8dfdc8ce89bd93861b6b06e8518d9b8623a54e41 Mon Sep 17 00:00:00 2001 From: ntsekouras Date: Wed, 4 Oct 2023 10:02:34 +0300 Subject: [PATCH 1/2] [Inserter]: Fix reset of registered media categories --- .../data/data-core-block-editor.md | 12 ++++++++ .../components/inserter/media-tab/hooks.js | 29 +++++++++++++++---- packages/block-editor/src/store/actions.js | 18 +++++------- packages/block-editor/src/store/reducer.js | 17 +++++++++++ packages/block-editor/src/store/selectors.js | 12 ++++++++ .../block-editor/src/store/test/actions.js | 26 +++++++---------- 6 files changed, 82 insertions(+), 32 deletions(-) diff --git a/docs/reference-guides/data/data-core-block-editor.md b/docs/reference-guides/data/data-core-block-editor.md index 7b0bd386daaf48..0db116458920a9 100644 --- a/docs/reference-guides/data/data-core-block-editor.md +++ b/docs/reference-guides/data/data-core-block-editor.md @@ -713,6 +713,18 @@ _Returns_ - `?string`: Adjacent block's client ID, or null if none exists. +### getRegisteredInserterMediaCategories + +Returns the registered inserter media categories through the public API. + +_Parameters_ + +- _state_ `Object`: Editor state. + +_Returns_ + +- `InserterMediaCategory[]`: Inserter media categories. + ### getSelectedBlock Returns the currently selected block, or null if there is no selected block. diff --git a/packages/block-editor/src/components/inserter/media-tab/hooks.js b/packages/block-editor/src/components/inserter/media-tab/hooks.js index 3d248c237be7c1..a05153d8d5631d 100644 --- a/packages/block-editor/src/components/inserter/media-tab/hooks.js +++ b/packages/block-editor/src/components/inserter/media-tab/hooks.js @@ -9,8 +9,8 @@ import { useSelect } from '@wordpress/data'; */ import { store as blockEditorStore } from '../../../store'; -/** @typedef {import('./api').InserterMediaRequest} InserterMediaRequest */ -/** @typedef {import('./api').InserterMediaItem} InserterMediaItem */ +/** @typedef {import('../../../store/actions').InserterMediaRequest} InserterMediaRequest */ +/** @typedef {import('../../../store/actions').InserterMediaItem} InserterMediaItem */ /** * Fetches media items based on the provided category. @@ -55,22 +55,40 @@ function useInserterMediaCategories() { inserterMediaCategories, allowedMimeTypes, enableOpenverseMediaCategory, + registeredInserterMediaCategories, } = useSelect( ( select ) => { - const settings = select( blockEditorStore ).getSettings(); + const { getSettings, getRegisteredInserterMediaCategories } = + select( blockEditorStore ); + const settings = getSettings(); return { inserterMediaCategories: settings.inserterMediaCategories, allowedMimeTypes: settings.allowedMimeTypes, enableOpenverseMediaCategory: settings.enableOpenverseMediaCategory, + registeredInserterMediaCategories: + getRegisteredInserterMediaCategories(), }; }, [] ); // The allowed `mime_types` can be altered by `upload_mimes` filter and restrict // some of them. In this case we shouldn't add the category to the available media // categories list in the inserter. const allowedCategories = useMemo( () => { - if ( ! inserterMediaCategories || ! allowedMimeTypes ) { + if ( + ( ! inserterMediaCategories && + ! registeredInserterMediaCategories.length ) || + ! allowedMimeTypes + ) { return; } - return inserterMediaCategories.filter( ( category ) => { + const coreInserterMediaCategoriesNames = + inserterMediaCategories?.map( ( { name } ) => name ) || []; + const mergedCategories = [ + ...( inserterMediaCategories || [] ), + ...( registeredInserterMediaCategories || [] ).filter( + ( { name } ) => + ! coreInserterMediaCategoriesNames.includes( name ) + ), + ]; + return mergedCategories.filter( ( category ) => { // Check if Openverse category is enabled. if ( ! enableOpenverseMediaCategory && @@ -84,6 +102,7 @@ function useInserterMediaCategories() { } ); }, [ inserterMediaCategories, + registeredInserterMediaCategories, allowedMimeTypes, enableOpenverseMediaCategory, ] ); diff --git a/packages/block-editor/src/store/actions.js b/packages/block-editor/src/store/actions.js index 1740543744aaa2..ae4b64a645d3ed 100644 --- a/packages/block-editor/src/store/actions.js +++ b/packages/block-editor/src/store/actions.js @@ -1893,9 +1893,10 @@ export const registerInserterMediaCategory = ); return; } - const { inserterMediaCategories = [] } = select.getSettings(); + const registeredInserterMediaCategories = + select.getRegisteredInserterMediaCategories(); if ( - inserterMediaCategories.some( + registeredInserterMediaCategories.some( ( { name } ) => name === category.name ) ) { @@ -1905,8 +1906,8 @@ export const registerInserterMediaCategory = return; } if ( - inserterMediaCategories.some( - ( { labels: { name } } ) => name === category.labels?.name + registeredInserterMediaCategories.some( + ( { labels: { name } = {} } ) => name === category.labels?.name ) ) { console.error( @@ -1919,13 +1920,8 @@ export const registerInserterMediaCategory = // private, so extenders can only add new inserter media categories and don't have any // control over the core media categories. dispatch( { - type: 'UPDATE_SETTINGS', - settings: { - inserterMediaCategories: [ - ...inserterMediaCategories, - { ...category, isExternalResource: true }, - ], - }, + type: 'REGISTER_INSERTER_MEDIA_CATEGORY', + category: { ...category, isExternalResource: true }, } ); }; diff --git a/packages/block-editor/src/store/reducer.js b/packages/block-editor/src/store/reducer.js index 18048ce138eb23..4373182d986622 100644 --- a/packages/block-editor/src/store/reducer.js +++ b/packages/block-editor/src/store/reducer.js @@ -1949,6 +1949,22 @@ export function styleOverrides( state = new Map(), action ) { return state; } +/** + * Reducer returning a map of the registered inserter media categories. + * + * @param {Array} state Current state. + * @param {Object} action Dispatched action. + * + * @return {Array} Updated state. + */ +export function registeredInserterMediaCategories( state = [], action ) { + switch ( action.type ) { + case 'REGISTER_INSERTER_MEDIA_CATEGORY': + return [ ...state, action.category ]; + } + return state; +} + const combinedReducers = combineReducers( { blocks, isTyping, @@ -1976,6 +1992,7 @@ const combinedReducers = combineReducers( { removalPromptData, blockRemovalRules, openedBlockSettingsMenu, + registeredInserterMediaCategories, } ); function withAutomaticChangeReset( reducer ) { diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index cb1f8ef49809d8..84170476337d2b 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -3022,3 +3022,15 @@ export const isGroupable = createRegistrySelector( ); } ); + +/** @typedef {import('./actions').InserterMediaCategory} InserterMediaCategory */ +/** + * Returns the registered inserter media categories through the public API. + * + * @param {Object} state Editor state. + * + * @return {InserterMediaCategory[]} Inserter media categories. + */ +export function getRegisteredInserterMediaCategories( state ) { + return state.registeredInserterMediaCategories; +} diff --git a/packages/block-editor/src/store/test/actions.js b/packages/block-editor/src/store/test/actions.js index f1f8cb29f1406e..e65921e30a6ce7 100644 --- a/packages/block-editor/src/store/test/actions.js +++ b/packages/block-editor/src/store/test/actions.js @@ -1279,9 +1279,9 @@ describe( 'actions', () => { fetch: () => {}, } )( { select: { - getSettings: () => ( { - inserterMediaCategories: [ { name: 'a' } ], - } ), + getRegisteredInserterMediaCategories: () => [ + { name: 'a' }, + ], }, } ); expect( console ).toHaveErroredWith( @@ -1296,11 +1296,9 @@ describe( 'actions', () => { fetch: () => {}, } )( { select: { - getSettings: () => ( { - inserterMediaCategories: [ - { labels: { name: 'a' } }, - ], - } ), + getRegisteredInserterMediaCategories: () => [ + { labels: { name: 'a' } }, + ], }, } ); expect( console ).toHaveErroredWith( @@ -1321,18 +1319,14 @@ describe( 'actions', () => { const dispatch = jest.fn(); registerInserterMediaCategory( category )( { select: { - getSettings: () => ( { inserterMediaCategories } ), + getRegisteredInserterMediaCategories: () => + inserterMediaCategories, }, dispatch, } ); expect( dispatch ).toHaveBeenLastCalledWith( { - type: 'UPDATE_SETTINGS', - settings: { - inserterMediaCategories: [ - ...inserterMediaCategories, - { ...category, isExternalResource: true }, - ], - }, + type: 'REGISTER_INSERTER_MEDIA_CATEGORY', + category: { ...category, isExternalResource: true }, } ); } ); } ); From 9ecb2ef359ad7e52ac81d466ccb78fe4df2a6cf9 Mon Sep 17 00:00:00 2001 From: ntsekouras Date: Wed, 4 Oct 2023 12:30:52 +0300 Subject: [PATCH 2/2] convert `useInserterMediaCategories` to selector and make private --- .../data/data-core-block-editor.md | 12 ---- .../components/inserter/media-tab/hooks.js | 69 +++--------------- .../src/store/private-selectors.js | 72 +++++++++++++++++++ packages/block-editor/src/store/selectors.js | 12 ---- 4 files changed, 80 insertions(+), 85 deletions(-) diff --git a/docs/reference-guides/data/data-core-block-editor.md b/docs/reference-guides/data/data-core-block-editor.md index 0db116458920a9..7b0bd386daaf48 100644 --- a/docs/reference-guides/data/data-core-block-editor.md +++ b/docs/reference-guides/data/data-core-block-editor.md @@ -713,18 +713,6 @@ _Returns_ - `?string`: Adjacent block's client ID, or null if none exists. -### getRegisteredInserterMediaCategories - -Returns the registered inserter media categories through the public API. - -_Parameters_ - -- _state_ `Object`: Editor state. - -_Returns_ - -- `InserterMediaCategory[]`: Inserter media categories. - ### getSelectedBlock Returns the currently selected block, or null if there is no selected block. diff --git a/packages/block-editor/src/components/inserter/media-tab/hooks.js b/packages/block-editor/src/components/inserter/media-tab/hooks.js index a05153d8d5631d..3a4c8fa9da7df5 100644 --- a/packages/block-editor/src/components/inserter/media-tab/hooks.js +++ b/packages/block-editor/src/components/inserter/media-tab/hooks.js @@ -1,13 +1,14 @@ /** * WordPress dependencies */ -import { useEffect, useState, useRef, useMemo } from '@wordpress/element'; +import { useEffect, useState, useRef } from '@wordpress/element'; import { useSelect } from '@wordpress/data'; /** * Internal dependencies */ import { store as blockEditorStore } from '../../../store'; +import { unlock } from '../../../lock-unlock'; /** @typedef {import('../../../store/actions').InserterMediaRequest} InserterMediaRequest */ /** @typedef {import('../../../store/actions').InserterMediaItem} InserterMediaItem */ @@ -50,67 +51,14 @@ export function useMediaResults( category, query = {} ) { return { mediaList, isLoading }; } -function useInserterMediaCategories() { - const { - inserterMediaCategories, - allowedMimeTypes, - enableOpenverseMediaCategory, - registeredInserterMediaCategories, - } = useSelect( ( select ) => { - const { getSettings, getRegisteredInserterMediaCategories } = - select( blockEditorStore ); - const settings = getSettings(); - return { - inserterMediaCategories: settings.inserterMediaCategories, - allowedMimeTypes: settings.allowedMimeTypes, - enableOpenverseMediaCategory: settings.enableOpenverseMediaCategory, - registeredInserterMediaCategories: - getRegisteredInserterMediaCategories(), - }; - }, [] ); - // The allowed `mime_types` can be altered by `upload_mimes` filter and restrict - // some of them. In this case we shouldn't add the category to the available media - // categories list in the inserter. - const allowedCategories = useMemo( () => { - if ( - ( ! inserterMediaCategories && - ! registeredInserterMediaCategories.length ) || - ! allowedMimeTypes - ) { - return; - } - const coreInserterMediaCategoriesNames = - inserterMediaCategories?.map( ( { name } ) => name ) || []; - const mergedCategories = [ - ...( inserterMediaCategories || [] ), - ...( registeredInserterMediaCategories || [] ).filter( - ( { name } ) => - ! coreInserterMediaCategoriesNames.includes( name ) - ), - ]; - return mergedCategories.filter( ( category ) => { - // Check if Openverse category is enabled. - if ( - ! enableOpenverseMediaCategory && - category.name === 'openverse' - ) { - return false; - } - return Object.values( allowedMimeTypes ).some( ( mimeType ) => - mimeType.startsWith( `${ category.mediaType }/` ) - ); - } ); - }, [ - inserterMediaCategories, - registeredInserterMediaCategories, - allowedMimeTypes, - enableOpenverseMediaCategory, - ] ); - return allowedCategories; -} - export function useMediaCategories( rootClientId ) { const [ categories, setCategories ] = useState( [] ); + + const inserterMediaCategories = useSelect( + ( select ) => + unlock( select( blockEditorStore ) ).getInserterMediaCategories(), + [] + ); const { canInsertImage, canInsertVideo, canInsertAudio } = useSelect( ( select ) => { const { canInsertBlockType } = select( blockEditorStore ); @@ -131,7 +79,6 @@ export function useMediaCategories( rootClientId ) { }, [ rootClientId ] ); - const inserterMediaCategories = useInserterMediaCategories(); useEffect( () => { ( async () => { const _categories = []; diff --git a/packages/block-editor/src/store/private-selectors.js b/packages/block-editor/src/store/private-selectors.js index 698da537728e01..c4220e6e7e516c 100644 --- a/packages/block-editor/src/store/private-selectors.js +++ b/packages/block-editor/src/store/private-selectors.js @@ -164,3 +164,75 @@ export function getOpenedBlockSettingsMenu( state ) { export function getStyleOverrides( state ) { return state.styleOverrides; } + +/** @typedef {import('./actions').InserterMediaCategory} InserterMediaCategory */ +/** + * Returns the registered inserter media categories through the public API. + * + * @param {Object} state Editor state. + * + * @return {InserterMediaCategory[]} Inserter media categories. + */ +export function getRegisteredInserterMediaCategories( state ) { + return state.registeredInserterMediaCategories; +} + +/** + * Returns an array containing the allowed inserter media categories. + * It merges the registered media categories from extenders with the + * core ones. It also takes into account the allowed `mime_types`, which + * can be altered by `upload_mimes` filter and restrict some of them. + * + * @param {Object} state Global application state. + * + * @return {InserterMediaCategory[]} Client IDs of descendants. + */ +export const getInserterMediaCategories = createSelector( + ( state ) => { + const { + settings: { + inserterMediaCategories, + allowedMimeTypes, + enableOpenverseMediaCategory, + }, + registeredInserterMediaCategories, + } = state; + // The allowed `mime_types` can be altered by `upload_mimes` filter and restrict + // some of them. In this case we shouldn't add the category to the available media + // categories list in the inserter. + if ( + ( ! inserterMediaCategories && + ! registeredInserterMediaCategories.length ) || + ! allowedMimeTypes + ) { + return; + } + const coreInserterMediaCategoriesNames = + inserterMediaCategories?.map( ( { name } ) => name ) || []; + const mergedCategories = [ + ...( inserterMediaCategories || [] ), + ...( registeredInserterMediaCategories || [] ).filter( + ( { name } ) => + ! coreInserterMediaCategoriesNames.includes( name ) + ), + ]; + return mergedCategories.filter( ( category ) => { + // Check if Openverse category is enabled. + if ( + ! enableOpenverseMediaCategory && + category.name === 'openverse' + ) { + return false; + } + return Object.values( allowedMimeTypes ).some( ( mimeType ) => + mimeType.startsWith( `${ category.mediaType }/` ) + ); + } ); + }, + ( state ) => [ + state.settings.inserterMediaCategories, + state.settings.allowedMimeTypes, + state.settings.enableOpenverseMediaCategory, + state.registeredInserterMediaCategories, + ] +); diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index 84170476337d2b..cb1f8ef49809d8 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -3022,15 +3022,3 @@ export const isGroupable = createRegistrySelector( ); } ); - -/** @typedef {import('./actions').InserterMediaCategory} InserterMediaCategory */ -/** - * Returns the registered inserter media categories through the public API. - * - * @param {Object} state Editor state. - * - * @return {InserterMediaCategory[]} Inserter media categories. - */ -export function getRegisteredInserterMediaCategories( state ) { - return state.registeredInserterMediaCategories; -}