Fix lag in preview

This commit is contained in:
soupette 2018-04-09 15:52:58 +02:00
parent 07e61236b1
commit c562c79430
8 changed files with 85 additions and 50 deletions

View File

@ -55,6 +55,10 @@
margin-top: 27px; margin-top: 27px;
} }
ol {
padding-left: 20px;
}
// NOTE: we might need this later // NOTE: we might need this later
span { span {
white-space: pre-line; white-space: pre-line;

View File

@ -49,7 +49,6 @@ class Wysiwyg extends React.Component {
super(props); super(props);
this.state = { this.state = {
editorState: EditorState.createEmpty(), editorState: EditorState.createEmpty(),
initialValue: '',
isDraging: false, isDraging: false,
isFocused: false, isFocused: false,
isPreviewMode: false, isPreviewMode: false,
@ -85,16 +84,13 @@ class Wysiwyg extends React.Component {
} }
} }
componentWillReceiveProps(nextProps) { componentDidUpdate(prevProps) {
if (nextProps.value !== this.props.value && !this.state.hasInitialValue) { // Handle resetProps
this.setInitialValue(nextProps); if (prevProps.resetProps !== this.props.resetProps) {
this.setInitialValue(this.props);
}
} }
// Handle reset props
if (nextProps.value === this.state.initialValue && this.state.hasInitialValue) {
this.setInitialValue(nextProps);
}
}
/** /**
* Init the editor with data from * Init the editor with data from
@ -104,12 +100,7 @@ class Wysiwyg extends React.Component {
const contentState = ContentState.createFromText(props.value); const contentState = ContentState.createFromText(props.value);
const newEditorState = EditorState.createWithContent(contentState); const newEditorState = EditorState.createWithContent(contentState);
const editorState = this.state.isFocused ? EditorState.moveFocusToEnd(newEditorState) : newEditorState; const editorState = this.state.isFocused ? EditorState.moveFocusToEnd(newEditorState) : newEditorState;
return this.setState({ editorState });
this.setState({
editorState,
hasInitialValue: true,
initialValue: props.value,
});
}; };
addContent = (content, style) => { addContent = (content, style) => {
@ -557,7 +548,7 @@ class Wysiwyg extends React.Component {
</div> </div>
{/* WYSIWYG PREVIEW NOT FULLSCREEN */} {/* WYSIWYG PREVIEW NOT FULLSCREEN */}
{isPreviewMode ? ( {isPreviewMode ? (
<PreviewWysiwyg /> <PreviewWysiwyg data={this.props.value} />
) : ( ) : (
<div <div
className={cn(styles.editor, isFullscreen && styles.editorFullScreen)} className={cn(styles.editor, isFullscreen && styles.editorFullScreen)}
@ -603,7 +594,7 @@ class Wysiwyg extends React.Component {
onClick={this.toggleFullScreen} onClick={this.toggleFullScreen}
characters={this.getCharactersNumber()} characters={this.getCharactersNumber()}
/> />
<PreviewWysiwyg /> <PreviewWysiwyg data={this.props.value} />
</div> </div>
)} )}
</div> </div>
@ -629,6 +620,7 @@ Wysiwyg.defaultProps = {
onBlur: () => {}, onBlur: () => {},
onChange: () => {}, onChange: () => {},
placeholder: '', placeholder: '',
resetProps: false,
style: {}, style: {},
tabIndex: '0', tabIndex: '0',
value: '', value: '',
@ -643,6 +635,7 @@ Wysiwyg.propTypes = {
onBlur: PropTypes.func, onBlur: PropTypes.func,
onChange: PropTypes.func, onChange: PropTypes.func,
placeholder: PropTypes.string, placeholder: PropTypes.string,
resetProps: PropTypes.bool,
style: PropTypes.object, style: PropTypes.object,
tabIndex: PropTypes.string, tabIndex: PropTypes.string,
value: PropTypes.string, value: PropTypes.string,

View File

@ -9,14 +9,9 @@ import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl'; import { FormattedMessage } from 'react-intl';
import styles from './componentsStyles.scss'; import styles from './componentsStyles.scss';
const PreviewControl = ({ characters, onClick }) => ( const PreviewControl = ({ onClick }) => (
<div className={styles.previewControlsWrapper} onClick={onClick}> <div className={styles.previewControlsWrapper} onClick={onClick}>
<div> <div />
<span>{characters}&nbsp;</span>
<FormattedMessage
id="components.WysiwygBottomControls.charactersIndicators"
/>
</div>
<div className={styles.wysiwygCollapse}> <div className={styles.wysiwygCollapse}>
<FormattedMessage id="components.Wysiwyg.collapse" /> <FormattedMessage id="components.Wysiwyg.collapse" />
</div> </div>
@ -24,12 +19,10 @@ const PreviewControl = ({ characters, onClick }) => (
); );
PreviewControl.defaultProps = { PreviewControl.defaultProps = {
characters: 0,
onClick: () => {}, onClick: () => {},
}; };
PreviewControl.propTypes = { PreviewControl.propTypes = {
characters: PropTypes.number,
onClick: PropTypes.func, onClick: PropTypes.func,
}; };

View File

@ -42,19 +42,7 @@ function getBlockStyle(block) {
} }
} }
class PreviewWysiwyg extends React.Component { const decorator = new CompositeDecorator([
getClassName = () => {
if (this.context.isFullscreen) {
return cn(styles.editor, styles.editorFullScreen, styles.fullscreenPreviewEditor);
}
return styles.editor;
};
previewHTML = () => {
const initHtml = isEmpty(this.context.html) ? '<p></p>' : this.context.html;
const html = converter.makeHtml(initHtml);
const decorator = new CompositeDecorator([
{ {
strategy: findLinkEntities, strategy: findLinkEntities,
component: Link, component: Link,
@ -67,20 +55,61 @@ class PreviewWysiwyg extends React.Component {
strategy: findVideoEntities, strategy: findVideoEntities,
component: Video, component: Video,
}, },
]); ]);
class PreviewWysiwyg extends React.Component {
state = { editorState: EditorState.createEmpty(), isMounted: false };
componentDidMount() {
const { data } = this.props;
this.setState({ isMounted: true });
if (!isEmpty(data)) {
this.previewHTML(data);
}
}
componentWillUnmount() {
this.setState({ isMounted: false });
}
getClassName = () => {
if (this.context.isFullscreen) {
return cn(styles.editor, styles.editorFullScreen, styles.fullscreenPreviewEditor);
}
return styles.editor;
};
UNSAFE_componentWillUpdate(nextProps, nextState) {
if (nextProps.data !== this.props.data) {
new Promise(resolve => {
setTimeout(() => {
if (nextProps.data === this.props.data && nextState.isMounted) {
this.previewHTML(nextProps.data);
}
resolve();
}, 300);
});
}
}
previewHTML = (rawContent) => {
const initHtml = isEmpty(rawContent) ? '<p></p>' : rawContent;
const html = converter.makeHtml(initHtml);
const blocksFromHTML = convertFromHTML(html); const blocksFromHTML = convertFromHTML(html);
// Make sure blocksFromHTML.contentBlocks !== null // Make sure blocksFromHTML.contentBlocks !== null
if (blocksFromHTML.contentBlocks) { if (blocksFromHTML.contentBlocks) {
const contentState = ContentState.createFromBlockArray( const contentState = ContentState.createFromBlockArray(
blocksFromHTML.contentBlocks, blocksFromHTML.contentBlocks,
blocksFromHTML.entityMap, blocksFromHTML.entityMap,
); );
return EditorState.createWithContent(contentState, decorator); return this.setState({ editorState: EditorState.createWithContent(contentState, decorator) });
} }
// Prevent errors if value is empty // Prevent errors if value is empty
return EditorState.createEmpty(); return this.setState({ editorState: EditorState.createEmpty() });
}; };
render() { render() {
@ -90,7 +119,7 @@ class PreviewWysiwyg extends React.Component {
<div className={this.getClassName()}> <div className={this.getClassName()}>
<WysiwygEditor <WysiwygEditor
blockStyleFn={getBlockStyle} blockStyleFn={getBlockStyle}
editorState={this.previewHTML()} editorState={this.state.editorState}
onChange={() => {}} onChange={() => {}}
placeholder={placeholder} placeholder={placeholder}
spellCheck spellCheck
@ -102,10 +131,16 @@ class PreviewWysiwyg extends React.Component {
} }
PreviewWysiwyg.contextTypes = { PreviewWysiwyg.contextTypes = {
editorState: PropTypes.func,
html: PropTypes.string,
isFullscreen: PropTypes.bool, isFullscreen: PropTypes.bool,
placeholder: PropTypes.string, placeholder: PropTypes.string,
}; };
PreviewWysiwyg.defaultProps = {
data: '',
};
PreviewWysiwyg.propTypes = {
data: PropTypes.string,
};
export default PreviewWysiwyg; export default PreviewWysiwyg;

View File

@ -86,6 +86,7 @@ class WysiwygWithErrors extends React.Component { // eslint-disable-line react/p
onBlur, onBlur,
onChange, onChange,
placeholder, placeholder,
resetProps,
style, style,
tabIndex, tabIndex,
value, value,
@ -123,6 +124,7 @@ class WysiwygWithErrors extends React.Component { // eslint-disable-line react/p
onBlur={handleBlur} onBlur={handleBlur}
onChange={onChange} onChange={onChange}
placeholder={placeholder} placeholder={placeholder}
resetProps={resetProps}
style={inputStyle} style={inputStyle}
tabIndex={tabIndex} tabIndex={tabIndex}
value={value} value={value}
@ -164,6 +166,7 @@ WysiwygWithErrors.defaultProps = {
noErrorsDescription: false, noErrorsDescription: false,
onBlur: false, onBlur: false,
placeholder: '', placeholder: '',
resetProps: false,
style: {}, style: {},
tabIndex: '0', tabIndex: '0',
validations: {}, validations: {},
@ -209,6 +212,7 @@ WysiwygWithErrors.propTypes = {
]), ]),
onChange: PropTypes.func.isRequired, onChange: PropTypes.func.isRequired,
placeholder: PropTypes.string, placeholder: PropTypes.string,
resetProps: PropTypes.bool,
style: PropTypes.object, style: PropTypes.object,
tabIndex: PropTypes.string, tabIndex: PropTypes.string,
validations: PropTypes.object, validations: PropTypes.object,

View File

@ -152,8 +152,9 @@ class Edit extends React.PureComponent {
name={attr} name={attr}
onBlur={this.props.onBlur} onBlur={this.props.onBlur}
onChange={this.props.onChange} onChange={this.props.onChange}
selectOptions={get(this.props.attributes, [attr, 'enum'])}
placeholder={get(layout, 'placeholder') || details.placeholder} placeholder={get(layout, 'placeholder') || details.placeholder}
resetProps={this.props.resetProps}
selectOptions={get(this.props.attributes, [attr, 'enum'])}
type={type} type={type}
validations={this.getInputValidations(attr)} validations={this.getInputValidations(attr)}
value={this.props.record[attr]} value={this.props.record[attr]}
@ -174,6 +175,7 @@ Edit.defaultProps = {
onBlur: () => {}, onBlur: () => {},
onChange: () => {}, onChange: () => {},
record: {}, record: {},
resetProps: false,
schema: {}, schema: {},
}; };
@ -186,6 +188,7 @@ Edit.propTypes = {
onBlur: PropTypes.func, onBlur: PropTypes.func,
onChange: PropTypes.func, onChange: PropTypes.func,
record: PropTypes.object, record: PropTypes.object,
resetProps: PropTypes.bool,
schema: PropTypes.object, schema: PropTypes.object,
}; };

View File

@ -280,6 +280,7 @@ export class EditPage extends React.Component {
onBlur={this.handleBlur} onBlur={this.handleBlur}
onChange={this.handleChange} onChange={this.handleChange}
record={editPage.record} record={editPage.record}
resetProps={editPage.resetProps}
schema={this.getSchema()} schema={this.getSchema()}
/> />
</div> </div>

View File

@ -31,6 +31,7 @@ const initialState = fromJS({
modelName: '', modelName: '',
pluginHeaderTitle: 'New Entry', pluginHeaderTitle: 'New Entry',
record: Map({}), record: Map({}),
resetProps: false,
showLoader: false, showLoader: false,
source: 'content-manager', source: 'content-manager',
submitSuccess: false, submitSuccess: false,
@ -59,7 +60,8 @@ function editPageReducer(state = initialState, action) {
return state return state
.update('didCheckErrors', (v) => v = !v) .update('didCheckErrors', (v) => v = !v)
.update('formErrors', () => List([])) .update('formErrors', () => List([]))
.update('record', () => state.get('initialRecord')); .update('record', () => state.get('initialRecord'))
.update('resetProps', (v) => v = !v);
case RESET_PROPS: case RESET_PROPS:
return initialState; return initialState;
case SET_FILE_RELATIONS: case SET_FILE_RELATIONS: