import React from 'react';
import placeholder from 'gutenberg/blocks/placeholder';
import { isBuilderUsed, isScriptDebug, getVBUrl } from 'gutenberg/utils/helpers';
import { DIVI, GUTENBERG } from 'gutenberg/constants';
import { registerBlock, unregisterBlock } from 'gutenberg/blocks/registration';
import get from 'lodash/get';
import throttle from 'lodash/throttle';
import isEmpty from 'lodash/isEmpty';
import startsWith from 'lodash/startsWith';
import { __ } from '@wordpress/i18n';
import { applyFilters } from '@wordpress/hooks';
import { dispatch, select, subscribe } from '@wordpress/data';
import { cold } from 'react-hot-loader';
import { RichText } from '@wordpress/editor';
import { renderToString, RawHTML } from '@wordpress/element';
// react-hot-loader replaces the Component with ProxyComponent altering its type.
// Since Gutenberg compares types while serializing content, we need to disable
// hot reloading for RichText and RawHTML
cold(RichText.Content);
cold(RawHTML);
const { setupEditor, editPost } = dispatch('core/editor');
const { isCleanNewPost, getCurrentPost, getEditedPostAttribute, getEditedPostContent, getBlocks } = select('core/editor');
const { getEditorMode } = select('core/edit-post');
const { switchEditorMode } = dispatch('core/edit-post');
const registerPlaceholder = () => registerBlock(placeholder);
const unregisterPlaceholder = () => unregisterBlock(placeholder);
const hasPlaceholder = () => {
const blocks = getBlocks();
if (blocks.length !== 1) {
return false;
}
return get(blocks, '0.name') === placeholder.name;
};
// Throttle this just to avoid potential loops, better safe than sorry.
const switchToVisualMode = throttle(() => switchEditorMode('visual'), 100);
const button = renderToString((
));
class Controller {
init = () => {
registerPlaceholder();
this.gbContent = '';
this.unsubscribe = subscribe(this.onEditorContentChange);
subscribe(this.onEditorModeChange);
}
onClick = (e) => {
switch (e.target.getAttribute('data-editor')) {
case DIVI: {
this.addPlaceholder(getEditedPostContent());
break;
}
default: {
// Okay, this button was inside the placeholder but then was moved out of it.
// That logic is a massive PITA, no time to refactor so this will have to do for now.
jQuery('#et-switch-to-gutenberg').click();
}
}
}
addPlaceholder = (content = '') => {
registerPlaceholder();
this.gbContent = content;
this.setupEditor(applyFilters('divi.addPlaceholder', content));
}
getGBContent = () => this.gbContent;
setupEditor = (raw, title = false) => {
const post = getCurrentPost();
// Set post content
setupEditor({ ...post, content: { raw } });
if (title !== false && title !== post.title) {
// Set post title
editPost({ title });
}
}
switchEditor = (editor, content) => {
switch (editor) {
case DIVI: {
// Open VB
window.location.href = getVBUrl();
break;
}
default: {
const title = getEditedPostAttribute('title');
// Restore GB content and title (without saving)
this.setupEditor(content, title);
unregisterPlaceholder();
}
}
}
addButton = () => {
// Add the custom button
setTimeout(() => jQuery(button).on('click', 'button', this.onClick).insertAfter('.edit-post-header-toolbar'), 0);
}
onEditorContentChange = () => {
const post = getCurrentPost();
if (isEmpty(post) || !this.unsubscribe) {
// If we don't have a post, GB isn't ready yet
return;
}
this.addButton();
// We only need to do this step once
this.unsubscribe();
this.unsubscribe = false;
const content = get(post, 'content');
if (startsWith(content, `