@wordpress/block-editor
Version:
188 lines (163 loc) • 6.47 kB
JavaScript
;
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