Refactor composer live previews for better performance

This commit is contained in:
Toby Zerner 2015-07-28 16:06:25 +09:30
parent d445b49d7a
commit 40112ae553
5 changed files with 54 additions and 68 deletions

View File

@ -1,3 +1,5 @@
/*global s9e*/
import Post from 'flarum/components/Post';
import classList from 'flarum/utils/classList';
import PostUser from 'flarum/components/PostUser';
@ -6,7 +8,6 @@ import PostEdited from 'flarum/components/PostEdited';
import EditPostComposer from 'flarum/components/EditPostComposer';
import Composer from 'flarum/components/Composer';
import ItemList from 'flarum/utils/ItemList';
import Formatter from 'flarum/utils/Formatter';
import listItems from 'flarum/helpers/listItems';
import Button from 'flarum/components/Button';
@ -42,13 +43,13 @@ export default class CommentPost extends Post {
}
content() {
const content = this.isEditing()
? Formatter.format(this.props.post.editedContent)
: this.props.post.contentHtml();
return [
<header className="Post-header"><ul>{listItems(this.headerItems().toArray())}</ul></header>,
<div className="Post-body">{m.trust(content)}</div>,
<div className="Post-body">
{this.isEditing()
? <div className="Post-preview" config={this.configPreview.bind(this)}/>
: m.trust(this.props.post.contentHtml())}
</div>,
<footer className="Post-footer"><ul>{listItems(this.footerItems().toArray())}</ul></footer>,
<aside className="Post-actions"><ul>{listItems(this.actionItems().toArray())}</ul></aside>
];
@ -74,6 +75,25 @@ export default class CommentPost extends Post {
};
}
configPreview(element, isInitialized, context) {
if (isInitialized) return;
// Every 50ms, if the composer content has changed, then update the post's
// body with a preview.
let preview;
const updateInterval = setInterval(() => {
const content = app.composer.component.content();
if (preview === content) return;
preview = content;
s9e.TextFormatter.preview(preview || '', element);
}, 50);
context.onunload = () => clearInterval(updateInterval);
}
/**
* Toggle the visibility of a hidden post's content.
*/

View File

@ -31,27 +31,6 @@ export default class EditPostComposer extends ComposerBody {
props.post.editedContent = props.originalContent;
}
config(isInitialized, context) {
super.config(isInitialized, context);
if (isInitialized) return;
// Every 50ms, if the content has changed, then update the post's
// editedContent property and redraw. This will cause the preview in the
// post's component to update.
const updateInterval = setInterval(() => {
const post = this.props.post;
const content = this.content();
if (content === post.editedContent) return;
post.editedContent = content;
m.redraw();
}, 50);
context.onunload = () => clearInterval(updateInterval);
}
headerItems() {
const items = super.headerItems();
const post = this.props.post;

View File

@ -42,32 +42,6 @@ export default class ReplyComposer extends ComposerBody {
return items;
}
config(isInitialized, context) {
super.config(isInitialized, context);
if (isInitialized) return;
// Every 50ms, if the content has changed, then update the post's
// editedContent property and redraw. This will cause the preview in the
// post's component to update.
const updateInterval = setInterval(() => {
const discussion = this.props.discussion;
const content = this.content();
if (content === discussion.replyContent) return;
discussion.replyContent = content;
const anchorToBottom = $(window).scrollTop() + $(window).height() >= $(document).height();
m.redraw();
if (anchorToBottom) {
$(window).scrollTop($(document).height());
}
}, 50);
context.onunload = () => clearInterval(updateInterval);
}
/**
* Get the data to submit to the server when the reply is saved.
*

View File

@ -1,8 +1,9 @@
/*global s9e*/
import Component from 'flarum/Component';
import avatar from 'flarum/helpers/avatar';
import username from 'flarum/helpers/username';
import DiscussionControls from 'flarum/utils/DiscussionControls';
import Formatter from 'flarum/utils/Formatter';
/**
* The `ReplyPlaceholder` component displays a placeholder for a reply, which,
@ -25,9 +26,7 @@ export default class ReplyPlaceholder extends Component {
</h3>
</div>
</header>
<div className="Post-body">
{m.trust(Formatter.format(this.props.discussion.replyContent))}
</div>
<div className="Post-body" config={this.configPreview.bind(this)}/>
</article>
);
}
@ -50,4 +49,29 @@ export default class ReplyPlaceholder extends Component {
</article>
);
}
configPreview(element, isInitialized, context) {
if (isInitialized) return;
// Every 50ms, if the composer content has changed, then update the post's
// body with a preview.
let preview;
const updateInterval = setInterval(() => {
const content = app.composer.component.content();
if (preview === content) return;
preview = content;
const anchorToBottom = $(window).scrollTop() + $(window).height() >= $(document).height();
s9e.TextFormatter.preview(preview || '', element);
if (anchorToBottom) {
$(window).scrollTop($(document).height());
}
}, 50);
context.onunload = () => clearInterval(updateInterval);
}
}

View File

@ -1,11 +0,0 @@
/*global s9e*/
export default {
format(text) {
const elm = document.createElement('div');
s9e.TextFormatter.preview(text || '', elm);
return elm.innerHTML;
}
}