FIX: Dirty keys should become to a widget, not global
This commit is contained in:
parent
287cb4bfc5
commit
1a02f5154f
|
@ -1,8 +1,8 @@
|
||||||
import { keyDirty } from 'discourse/widgets/widget';
|
|
||||||
import { diff, patch } from 'virtual-dom';
|
import { diff, patch } from 'virtual-dom';
|
||||||
import { WidgetClickHook } from 'discourse/widgets/hooks';
|
import { WidgetClickHook } from 'discourse/widgets/hooks';
|
||||||
import { renderedKey, queryRegistry } from 'discourse/widgets/widget';
|
import { queryRegistry } from 'discourse/widgets/widget';
|
||||||
import { getRegister } from 'discourse-common/lib/get-owner';
|
import { getRegister } from 'discourse-common/lib/get-owner';
|
||||||
|
import DirtyKeys from 'discourse/lib/dirty-keys';
|
||||||
|
|
||||||
const _cleanCallbacks = {};
|
const _cleanCallbacks = {};
|
||||||
export function addWidgetCleanCallback(widgetName, fn) {
|
export function addWidgetCleanCallback(widgetName, fn) {
|
||||||
|
@ -18,6 +18,7 @@ export default Ember.Component.extend({
|
||||||
_renderCallback: null,
|
_renderCallback: null,
|
||||||
_childEvents: null,
|
_childEvents: null,
|
||||||
_dispatched: null,
|
_dispatched: null,
|
||||||
|
dirtyKeys: null,
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
this._super();
|
this._super();
|
||||||
|
@ -34,6 +35,7 @@ export default Ember.Component.extend({
|
||||||
this._childEvents = [];
|
this._childEvents = [];
|
||||||
this._connected = [];
|
this._connected = [];
|
||||||
this._dispatched = [];
|
this._dispatched = [];
|
||||||
|
this.dirtyKeys = new DirtyKeys(name);
|
||||||
},
|
},
|
||||||
|
|
||||||
didInsertElement() {
|
didInsertElement() {
|
||||||
|
@ -73,7 +75,7 @@ export default Ember.Component.extend({
|
||||||
|
|
||||||
eventDispatched(eventName, key, refreshArg) {
|
eventDispatched(eventName, key, refreshArg) {
|
||||||
const onRefresh = Ember.String.camelize(eventName.replace(/:/, '-'));
|
const onRefresh = Ember.String.camelize(eventName.replace(/:/, '-'));
|
||||||
keyDirty(key, { onRefresh, refreshArg });
|
this.dirtyKeys.keyDirty(key, { onRefresh, refreshArg });
|
||||||
this.queueRerender();
|
this.queueRerender();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -104,7 +106,10 @@ export default Ember.Component.extend({
|
||||||
|
|
||||||
const t0 = new Date().getTime();
|
const t0 = new Date().getTime();
|
||||||
const args = this.get('args') || this.buildArgs();
|
const args = this.get('args') || this.buildArgs();
|
||||||
const opts = { model: this.get('model') };
|
const opts = {
|
||||||
|
model: this.get('model'),
|
||||||
|
dirtyKeys: this.dirtyKeys,
|
||||||
|
};
|
||||||
const newTree = new this._widgetClass(args, this.register, opts);
|
const newTree = new this._widgetClass(args, this.register, opts);
|
||||||
|
|
||||||
newTree._rerenderable = this;
|
newTree._rerenderable = this;
|
||||||
|
@ -122,8 +127,8 @@ export default Ember.Component.extend({
|
||||||
this._renderCallback = null;
|
this._renderCallback = null;
|
||||||
}
|
}
|
||||||
this.afterRender();
|
this.afterRender();
|
||||||
|
this.dirtyKeys.renderedKey('*');
|
||||||
|
|
||||||
Ember.run.scheduleOnce('afterRender', () => renderedKey('*'));
|
|
||||||
if (this.profileWidget) {
|
if (this.profileWidget) {
|
||||||
console.log(new Date().getTime() - t0);
|
console.log(new Date().getTime() - t0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import DiscourseURL from 'discourse/lib/url';
|
import DiscourseURL from 'discourse/lib/url';
|
||||||
import { keyDirty } from 'discourse/widgets/widget';
|
|
||||||
import MountWidget from 'discourse/components/mount-widget';
|
import MountWidget from 'discourse/components/mount-widget';
|
||||||
import { cloak, uncloak } from 'discourse/widgets/post-stream';
|
import { cloak, uncloak } from 'discourse/widgets/post-stream';
|
||||||
import { isWorkaroundActive } from 'discourse/lib/safari-hacks';
|
import { isWorkaroundActive } from 'discourse/lib/safari-hacks';
|
||||||
|
@ -245,13 +244,13 @@ export default MountWidget.extend({
|
||||||
this.appEvents.on('post-stream:refresh', args => {
|
this.appEvents.on('post-stream:refresh', args => {
|
||||||
if (args) {
|
if (args) {
|
||||||
if (args.id) {
|
if (args.id) {
|
||||||
keyDirty(`post-${args.id}`);
|
this.dirtyKeys.keyDirty(`post-${args.id}`);
|
||||||
|
|
||||||
if (args.refreshLikes) {
|
if (args.refreshLikes) {
|
||||||
keyDirty(`post-menu-${args.id}`, { onRefresh: 'refreshLikes' });
|
this.dirtyKeys.keyDirty(`post-menu-${args.id}`, { onRefresh: 'refreshLikes' });
|
||||||
}
|
}
|
||||||
} else if (args.force) {
|
} else if (args.force) {
|
||||||
keyDirty(`*`);
|
this.dirtyKeys.forceAll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.queueRerender();
|
this.queueRerender();
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
export default class DirtyKeys {
|
||||||
|
constructor(name) {
|
||||||
|
this.name = name;
|
||||||
|
this._keys = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
keyDirty(key, options) {
|
||||||
|
options = options || {};
|
||||||
|
options.dirty = true;
|
||||||
|
this._keys[key] = options;
|
||||||
|
}
|
||||||
|
|
||||||
|
forceAll() {
|
||||||
|
this.keyDirty('*');
|
||||||
|
}
|
||||||
|
|
||||||
|
allDirty() {
|
||||||
|
return !!this._keys['*'];
|
||||||
|
}
|
||||||
|
|
||||||
|
optionsFor(key) {
|
||||||
|
return this._keys[key] || { dirty: false };
|
||||||
|
}
|
||||||
|
|
||||||
|
renderedKey(key) {
|
||||||
|
if (key === '*') {
|
||||||
|
this._keys = {};
|
||||||
|
} else {
|
||||||
|
delete this._keys[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
import { diff, patch } from 'virtual-dom';
|
import { diff, patch } from 'virtual-dom';
|
||||||
import { queryRegistry } from 'discourse/widgets/widget';
|
import { queryRegistry } from 'discourse/widgets/widget';
|
||||||
|
import DirtyKeys from 'discourse/lib/dirty-keys';
|
||||||
|
|
||||||
export default class WidgetGlue {
|
export default class WidgetGlue {
|
||||||
|
|
||||||
|
@ -9,6 +10,7 @@ export default class WidgetGlue {
|
||||||
this.register = register;
|
this.register = register;
|
||||||
this.attrs = attrs;
|
this.attrs = attrs;
|
||||||
this._timeout = null;
|
this._timeout = null;
|
||||||
|
this.dirtyKeys = new DirtyKeys(name);
|
||||||
|
|
||||||
this._widgetClass = queryRegistry(name) || this.register.lookupFactory(`widget:${name}`);
|
this._widgetClass = queryRegistry(name) || this.register.lookupFactory(`widget:${name}`);
|
||||||
if (!this._widgetClass) {
|
if (!this._widgetClass) {
|
||||||
|
@ -27,7 +29,11 @@ export default class WidgetGlue {
|
||||||
|
|
||||||
rerenderWidget() {
|
rerenderWidget() {
|
||||||
Ember.run.cancel(this._timeout);
|
Ember.run.cancel(this._timeout);
|
||||||
const newTree = new this._widgetClass(this.attrs, this.register);
|
const newTree = new this._widgetClass(
|
||||||
|
this.attrs,
|
||||||
|
this.register,
|
||||||
|
{ dirtyKeys: this.dirtyKeys }
|
||||||
|
);
|
||||||
const patches = diff(this._tree || this._rootNode, newTree);
|
const patches = diff(this._tree || this._rootNode, newTree);
|
||||||
|
|
||||||
newTree._rerenderable = this;
|
newTree._rerenderable = this;
|
||||||
|
|
|
@ -2,7 +2,6 @@ import { createWidget } from 'discourse/widgets/widget';
|
||||||
import transformPost from 'discourse/lib/transform-post';
|
import transformPost from 'discourse/lib/transform-post';
|
||||||
import { Placeholder } from 'discourse/lib/posts-with-placeholders';
|
import { Placeholder } from 'discourse/lib/posts-with-placeholders';
|
||||||
import { addWidgetCleanCallback } from 'discourse/components/mount-widget';
|
import { addWidgetCleanCallback } from 'discourse/components/mount-widget';
|
||||||
import { keyDirty } from 'discourse/widgets/widget';
|
|
||||||
|
|
||||||
let transformCallbacks = null;
|
let transformCallbacks = null;
|
||||||
function postTransformCallbacks(transformed) {
|
function postTransformCallbacks(transformed) {
|
||||||
|
@ -36,14 +35,15 @@ export function cloak(post, component) {
|
||||||
const $post = $(`#post_${post.post_number}`);
|
const $post = $(`#post_${post.post_number}`);
|
||||||
_cloaked[post.id] = true;
|
_cloaked[post.id] = true;
|
||||||
_heights[post.id] = $post.outerHeight();
|
_heights[post.id] = $post.outerHeight();
|
||||||
keyDirty(`post-${post.id}`);
|
|
||||||
|
component.dirtyKeys.keyDirty(`post-${post.id}`);
|
||||||
Ember.run.debounce(component, 'queueRerender', 1000);
|
Ember.run.debounce(component, 'queueRerender', 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function uncloak(post, component) {
|
export function uncloak(post, component) {
|
||||||
if (!CLOAKING_ENABLED || !_cloaked[post.id]) { return; }
|
if (!CLOAKING_ENABLED || !_cloaked[post.id]) { return; }
|
||||||
_cloaked[post.id] = null;
|
_cloaked[post.id] = null;
|
||||||
keyDirty(`post-${post.id}`);
|
component.dirtyKeys.keyDirty(`post-${post.id}`);
|
||||||
component.queueRerender();
|
component.queueRerender();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,21 +9,6 @@ import DecoratorHelper from 'discourse/widgets/decorator-helper';
|
||||||
function emptyContent() { }
|
function emptyContent() { }
|
||||||
|
|
||||||
const _registry = {};
|
const _registry = {};
|
||||||
let _dirty = {};
|
|
||||||
|
|
||||||
export function keyDirty(key, options) {
|
|
||||||
options = options || {};
|
|
||||||
options.dirty = true;
|
|
||||||
_dirty[key] = options;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function renderedKey(key) {
|
|
||||||
if (key === '*') {
|
|
||||||
_dirty = {};
|
|
||||||
} else {
|
|
||||||
delete _dirty[key];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function queryRegistry(name) {
|
export function queryRegistry(name) {
|
||||||
return _registry[name];
|
return _registry[name];
|
||||||
|
@ -149,6 +134,7 @@ export default class Widget {
|
||||||
this.mergeState = opts.state;
|
this.mergeState = opts.state;
|
||||||
this.model = opts.model;
|
this.model = opts.model;
|
||||||
this.register = register;
|
this.register = register;
|
||||||
|
this.dirtyKeys = opts.dirtyKeys;
|
||||||
|
|
||||||
register.deprecateContainer(this);
|
register.deprecateContainer(this);
|
||||||
|
|
||||||
|
@ -188,6 +174,8 @@ export default class Widget {
|
||||||
}
|
}
|
||||||
|
|
||||||
render(prev) {
|
render(prev) {
|
||||||
|
const { dirtyKeys } = this;
|
||||||
|
|
||||||
if (prev && prev.key && prev.key === this.key) {
|
if (prev && prev.key && prev.key === this.key) {
|
||||||
this.state = prev.state;
|
this.state = prev.state;
|
||||||
} else {
|
} else {
|
||||||
|
@ -200,16 +188,16 @@ export default class Widget {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prev) {
|
if (prev) {
|
||||||
const dirtyOpts = _dirty[prev.key] || { dirty: false };
|
const dirtyOpts = dirtyKeys.optionsFor(prev.key);
|
||||||
|
|
||||||
if (prev.shadowTree) {
|
if (prev.shadowTree) {
|
||||||
this.shadowTree = true;
|
this.shadowTree = true;
|
||||||
if (!dirtyOpts.dirty && !_dirty['*']) {
|
if (!dirtyOpts.dirty && !dirtyKeys.allDirty()) {
|
||||||
return prev.vnode;
|
return prev.vnode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (prev.key) {
|
if (prev.key) {
|
||||||
renderedKey(prev.key);
|
dirtyKeys.renderedKey(prev.key);
|
||||||
}
|
}
|
||||||
|
|
||||||
const refreshAction = dirtyOpts.onRefresh;
|
const refreshAction = dirtyOpts.onRefresh;
|
||||||
|
@ -256,6 +244,7 @@ export default class Widget {
|
||||||
if (WidgetClass) {
|
if (WidgetClass) {
|
||||||
const result = new WidgetClass(attrs, this.register, opts);
|
const result = new WidgetClass(attrs, this.register, opts);
|
||||||
result.parentWidget = this;
|
result.parentWidget = this;
|
||||||
|
result.dirtyKeys = this.dirtyKeys;
|
||||||
return result;
|
return result;
|
||||||
} else {
|
} else {
|
||||||
throw `Couldn't find ${widgetName} factory`;
|
throw `Couldn't find ${widgetName} factory`;
|
||||||
|
@ -266,7 +255,7 @@ export default class Widget {
|
||||||
let widget = this;
|
let widget = this;
|
||||||
while (widget) {
|
while (widget) {
|
||||||
if (widget.shadowTree) {
|
if (widget.shadowTree) {
|
||||||
keyDirty(widget.key);
|
this.dirtyKeys.keyDirty(widget.key);
|
||||||
}
|
}
|
||||||
|
|
||||||
const rerenderable = widget._rerenderable;
|
const rerenderable = widget._rerenderable;
|
||||||
|
|
Loading…
Reference in New Issue