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;
}
ol {
padding-left: 20px;
}
// NOTE: we might need this later
span {
white-space: pre-line;

View File

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

View File

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

View File

@ -42,7 +42,37 @@ function getBlockStyle(block) {
}
}
const decorator = new CompositeDecorator([
{
strategy: findLinkEntities,
component: Link,
},
{
strategy: findImageEntities,
component: Image,
},
{
strategy: findVideoEntities,
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);
@ -51,36 +81,35 @@ class PreviewWysiwyg extends React.Component {
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,
component: Link,
},
{
strategy: findImageEntities,
component: Image,
},
{
strategy: findVideoEntities,
component: Video,
},
]);
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);
// Make sure blocksFromHTML.contentBlocks !== null
if (blocksFromHTML.contentBlocks) {
const contentState = ContentState.createFromBlockArray(
blocksFromHTML.contentBlocks,
blocksFromHTML.entityMap,
);
return EditorState.createWithContent(contentState, decorator);
return this.setState({ editorState: EditorState.createWithContent(contentState, decorator) });
}
// Prevent errors if value is empty
return EditorState.createEmpty();
return this.setState({ editorState: EditorState.createEmpty() });
};
render() {
@ -90,7 +119,7 @@ class PreviewWysiwyg extends React.Component {
<div className={this.getClassName()}>
<WysiwygEditor
blockStyleFn={getBlockStyle}
editorState={this.previewHTML()}
editorState={this.state.editorState}
onChange={() => {}}
placeholder={placeholder}
spellCheck
@ -102,10 +131,16 @@ class PreviewWysiwyg extends React.Component {
}
PreviewWysiwyg.contextTypes = {
editorState: PropTypes.func,
html: PropTypes.string,
isFullscreen: PropTypes.bool,
placeholder: PropTypes.string,
};
PreviewWysiwyg.defaultProps = {
data: '',
};
PreviewWysiwyg.propTypes = {
data: PropTypes.string,
};
export default PreviewWysiwyg;

View File

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

View File

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

View File

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

View File

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