import { BlockPreview } from '@wordpress/block-editor' import { rawHandler } from '@wordpress/blocks' import { useRef, useMemo, useEffect, useState } from '@wordpress/element' import { __, sprintf } from '@wordpress/i18n' import classNames from 'classnames' import { Templates as TemplatesApi } from '@library/api/Templates' import { useIsDevMode } from '@library/hooks/helpers' import { AuthorizationCheck, Middleware } from '@library/middleware' import { useGlobalStore } from '@library/state/GlobalState' import { useUserStore } from '@library/state/User' import { injectTemplateBlocks } from '@library/util/templateInjection' import { DevButtonOverlay } from './DevHelpers' import { NoImportModal } from './modals/NoImportModal' import { ProModal } from './modals/ProModal' const canImportMiddleware = Middleware([ 'hasRequiredPlugins', 'hasPluginsActivated', ]) export function ImportTemplateBlock({ template, maxHeight }) { const importButtonRef = useRef(null) const hasAvailableImports = useUserStore( (state) => state.hasAvailableImports, ) const loggedIn = useUserStore((state) => state.apiKey.length) const setOpen = useGlobalStore((state) => state.setOpen) const pushModal = useGlobalStore((state) => state.pushModal) const removeAllModals = useGlobalStore((state) => state.removeAllModals) const [topValue, setTopValue] = useState(0) const type = Array.isArray(template?.fields?.type) ? template.fields.type[0] : template?.fields?.type const blocks = useMemo( () => rawHandler({ HTML: halfImageSizes(template.fields.code) }), [template.fields.code], ) // The above will cut the image sizes in half, and the below will be inserted into the page const blocksRaw = useMemo( () => rawHandler({ HTML: template.fields.code }), [template.fields.code], ) const devMode = useIsDevMode() const importTemplates = async () => { await canImportMiddleware.check(template) AuthorizationCheck(canImportMiddleware) .then(() => { setTimeout(() => { injectTemplateBlocks(blocksRaw, template) .then(() => removeAllModals()) .then(() => setOpen(false)) .then(() => canImportMiddleware.reset()) }, 100) }) .catch(() => {}) } const handleKeyDown = (event) => { if (['Enter', 'Space', ' '].includes(event.key)) { event.stopPropagation() event.preventDefault() importTemplate() } } const importTemplate = () => { // Make a note that they attempted to import TemplatesApi.maybeImport(template) if (template?.fields?.pro && !loggedIn) { pushModal() return } if (!hasAvailableImports()) { pushModal() return } importTemplates() } // Handle layout animation useEffect(() => { if (!Number.isInteger(maxHeight)) return if (type !== 'layout') return const button = importButtonRef.current const handleIn = () => { // The live component changes over time so easier to query on demand const height = button.offsetHeight button.style.transitionDuration = height * 1.5 + 'ms' setTopValue(Math.abs(height - maxHeight) * -1) } const handleOut = () => { const height = button.offsetHeight button.style.transitionDuration = height / 1.5 + 'ms' setTopValue(0) } button.addEventListener('focus', handleIn) button.addEventListener('mouseenter', handleIn) button.addEventListener('blur', handleOut) button.addEventListener('mouseleave', handleOut) return () => { button.removeEventListener('focus', handleIn) button.removeEventListener('mouseenter', handleIn) button.removeEventListener('blur', handleOut) button.removeEventListener('mouseleave', handleOut) } }, [maxHeight, type]) return (
{/* Show dev info after the preview is loaded to trigger observer */} {devMode && } {template?.fields?.pro && (
{__('Pro', 'extendify')}
)}
) } const halfImageSizes = (html) => { return html.replace( /\w+:\/\/\S*(w=(\d*))&(h=(\d*))&\w+\S*"/g, (url, w, width, h, height) => url .replace(w, 'w=' + Math.floor(Number(width) / 2)) .replace(h, 'h=' + Math.floor(Number(height) / 2)), ) }