UNPKG

@wordpress/block-editor

Version:
188 lines (163 loc) 6.47 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.useMediaCategories = useMediaCategories; exports.useMediaResults = useMediaResults; var _element = require("@wordpress/element"); var _data = require("@wordpress/data"); var _store = require("../../../store"); /** * WordPress dependencies */ /** * Internal dependencies */ /** * Interface for inserter media requests. * * @typedef {Object} InserterMediaRequest * @property {number} per_page How many items to fetch per page. * @property {string} search The search term to use for filtering the results. */ /** * Interface for inserter media responses. Any media resource should * map their response to this interface, in order to create the core * WordPress media blocks (image, video, audio). * * @typedef {Object} InserterMediaItem * @property {string} title The title of the media item. * @property {string} url The source url of the media item. * @property {string} [previewUrl] The preview source url of the media item to display in the media list. * @property {number} [id] The WordPress id of the media item. * @property {number|string} [sourceId] The id of the media item from external source. * @property {string} [alt] The alt text of the media item. * @property {string} [caption] The caption of the media item. */ /** * Fetches media items based on the provided category. * Each media category is responsible for providing a `fetch` function. * * @param {Object} category The media category to fetch results for. * @param {InserterMediaRequest} query The query args to use for the request. * @return {InserterMediaItem[]} The media results. */ function useMediaResults(category, query = {}) { const [mediaList, setMediaList] = (0, _element.useState)(); const [isLoading, setIsLoading] = (0, _element.useState)(false); // We need to keep track of the last request made because // multiple request can be fired without knowing the order // of resolution, and we need to ensure we are showing // the results of the last request. // In the future we could use AbortController to cancel previous // requests, but we don't for now as it involves adding support // for this to `core-data` package. const lastRequest = (0, _element.useRef)(); (0, _element.useEffect)(() => { (async () => { const key = JSON.stringify({ category: category.name, ...query }); lastRequest.current = key; setIsLoading(true); setMediaList([]); // Empty the previous results. const _media = await category.fetch?.(query); if (key === lastRequest.current) { setMediaList(_media); setIsLoading(false); } })(); }, [category.name, ...Object.values(query)]); return { mediaList, isLoading }; } function useInserterMediaCategories() { const { inserterMediaCategories, allowedMimeTypes, enableOpenverseMediaCategory } = (0, _data.useSelect)(select => { const settings = select(_store.store).getSettings(); return { inserterMediaCategories: settings.inserterMediaCategories, allowedMimeTypes: settings.allowedMimeTypes, enableOpenverseMediaCategory: settings.enableOpenverseMediaCategory }; }, []); // 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 = (0, _element.useMemo)(() => { if (!inserterMediaCategories || !allowedMimeTypes) { return; } return inserterMediaCategories.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, allowedMimeTypes, enableOpenverseMediaCategory]); return allowedCategories; } function useMediaCategories(rootClientId) { const [categories, setCategories] = (0, _element.useState)([]); const { canInsertImage, canInsertVideo, canInsertAudio } = (0, _data.useSelect)(select => { const { canInsertBlockType } = select(_store.store); return { canInsertImage: canInsertBlockType('core/image', rootClientId), canInsertVideo: canInsertBlockType('core/video', rootClientId), canInsertAudio: canInsertBlockType('core/audio', rootClientId) }; }, [rootClientId]); const inserterMediaCategories = useInserterMediaCategories(); (0, _element.useEffect)(() => { (async () => { const _categories = []; // If `inserterMediaCategories` is not defined in // block editor settings, do not show any media categories. if (!inserterMediaCategories) { return; } // Loop through categories to check if they have at least one media item. const categoriesHaveMedia = new Map(await Promise.all(inserterMediaCategories.map(async category => { // Some sources are external and we don't need to make a request. if (category.isExternalResource) { return [category.name, true]; } let results = []; try { results = await category.fetch({ per_page: 1 }); } catch (e) {// If the request fails, we shallow the error and just don't show // the category, in order to not break the media tab. } return [category.name, !!results.length]; }))); // We need to filter out categories that don't have any media items or // whose corresponding block type is not allowed to be inserted, based // on the category's `mediaType`. const canInsertMediaType = { image: canInsertImage, video: canInsertVideo, audio: canInsertAudio }; inserterMediaCategories.forEach(category => { if (canInsertMediaType[category.mediaType] && categoriesHaveMedia.get(category.name)) { _categories.push(category); } }); if (!!_categories.length) { setCategories(_categories); } })(); }, [canInsertImage, canInsertVideo, canInsertAudio, inserterMediaCategories]); return categories; } //# sourceMappingURL=hooks.js.map