From f4abf91545bb2fe359c6bc667915f70281a653d7 Mon Sep 17 00:00:00 2001 From: Mario Nebl Date: Tue, 7 Aug 2018 12:10:41 +0200 Subject: [PATCH] perf: improve basic message performance furhter --- src/container/element-list/element-list.tsx | 48 +++++----- src/electron/create-edit-message-handler.ts | 18 +--- src/model/alva-app.ts | 4 +- src/model/element-action.ts | 7 +- src/model/element/element-content.ts | 3 +- .../element-property/element-property.ts | 12 ++- src/model/element/element.ts | 24 +++-- src/model/page/page.ts | 3 +- src/model/pattern-library/pattern-library.ts | 4 +- src/model/pattern-property/asset-property.ts | 3 +- .../pattern-property/boolean-property.ts | 3 +- src/model/pattern-property/enum-property.ts | 3 +- .../event-handler-property.ts | 4 +- src/model/pattern-property/href-property.ts | 3 +- src/model/pattern-property/number-property.ts | 3 +- src/model/pattern-property/string-property.ts | 3 +- src/model/pattern/pattern-slot.ts | 6 +- src/model/pattern/pattern.ts | 7 +- src/model/project.ts | 21 ++++- .../user-store-action/user-store-action.ts | 6 +- src/model/user-store-enhancer.ts | 3 +- .../user-store-property.ts | 4 +- src/model/user-store-reference.ts | 4 +- src/model/user-store.ts | 4 +- src/renderer/create-change-notifiers.ts | 87 ++++++++++--------- src/store/view-store.ts | 68 ++++++++++----- 26 files changed, 178 insertions(+), 177 deletions(-) diff --git a/src/container/element-list/element-list.tsx b/src/container/element-list/element-list.tsx index 1822f9f7c..c2c411e86 100644 --- a/src/container/element-list/element-list.tsx +++ b/src/container/element-list/element-list.tsx @@ -122,8 +122,10 @@ export class ElementList extends React.Component { return; } - targetElement.setHighlighted(false); - targetElement.setPlaceholderHighlighted(false); + Mobx.transaction(() => { + targetElement.setHighlighted(false); + targetElement.setPlaceholderHighlighted(false); + }); } private handleDragOver(e: React.DragEvent): void { @@ -139,35 +141,33 @@ export class ElementList extends React.Component { const draggedElement = store.getDraggedElement(); - if (!targetContent || !visualTargetElement) { + if (!targetContent || !visualTargetElement || !draggedElement) { return; } + const higlightedElement = store.getHighlightedElement(); + const placeholderHighlightedElement = store.getPlaceHolderHighhlightedElement(); + + const higlightedElementContent = store.getHighlightedElementContent(); + const accepted = targetContent.accepts(draggedElement); + Mobx.transaction(() => { - if (!draggedElement) { + if (!accepted) { targetContent.setHighlighted(false); visualTargetElement.setPlaceholderHighlighted(false); return; } - store - .getProject() - .getElementContents() - .filter(sec => sec.getHighlighted() && sec !== targetContent) - .forEach(se => se.setHighlighted(false)); - - store - .getProject() - .getElements() - .filter(se => se.getHighlighted() && se !== visualTargetElement) - .forEach(se => se.setHighlighted(false)); + if (placeholderHighlightedElement) { + placeholderHighlightedElement.setPlaceholderHighlighted(false); + } - const accepted = targetContent.accepts(draggedElement); + if (higlightedElement) { + higlightedElement.setPlaceholderHighlighted(false); + } - if (!accepted) { - targetContent.setHighlighted(false); - visualTargetElement.setPlaceholderHighlighted(false); - return; + if (higlightedElementContent) { + higlightedElementContent.setHighlighted(false); } e.dataTransfer.dropEffect = 'copy'; @@ -195,13 +195,15 @@ export class ElementList extends React.Component { return; } - draggedElement.setDragged(true); - store.setSelectedElement(draggedElement); - if (this.dragImg) { e.dataTransfer.effectAllowed = 'copy'; e.dataTransfer.setDragImage(this.dragImg, 75, 15); } + + Mobx.transaction(() => { + draggedElement.setDragged(true); + store.setSelectedElement(draggedElement); + }); } private handleDrop(e: React.DragEvent): void { diff --git a/src/electron/create-edit-message-handler.ts b/src/electron/create-edit-message-handler.ts index ec568d100..9e2c690e1 100644 --- a/src/electron/create-edit-message-handler.ts +++ b/src/electron/create-edit-message-handler.ts @@ -2,7 +2,7 @@ import * as Clipboard from './clipboard'; import * as Message from '../message'; import { requestApp } from './request-app'; import * as Types from '../types'; -import * as uuid from 'uuid'; +// import * as uuid from 'uuid'; import { ServerMessageHandlerContext, @@ -59,7 +59,8 @@ export async function createEditMessageHandler( break; } case Message.MessageType.Paste: { - const clipboard = Clipboard.getClipboard(); + // Disabled pending investigation + /* const clipboard = Clipboard.getClipboard(); if (!clipboard) { return; @@ -93,7 +94,7 @@ export async function createEditMessageHandler( project: clipboard.payload.project } }); - } + }*/ } } }; @@ -109,14 +110,3 @@ function serializeItemType(type: Types.ItemType): Types.SerializedItemType { return 'none'; } } - -function deserializeItemType(type: Types.SerializedItemType): Types.ItemType { - switch (type) { - case 'element': - return Types.ItemType.Element; - case 'page': - return Types.ItemType.Page; - case 'none': - return Types.ItemType.None; - } -} diff --git a/src/model/alva-app.ts b/src/model/alva-app.ts index f2828e76f..65875144f 100644 --- a/src/model/alva-app.ts +++ b/src/model/alva-app.ts @@ -184,9 +184,7 @@ export class AlvaApp { } @Mobx.action - public update(raw: AlvaApp | Types.SerializedAlvaApp): void { - const b = raw instanceof AlvaApp ? raw : AlvaApp.from(raw); - + public update(b: AlvaApp): void { this.activeView = b.activeView; this.panes = b.panes; this.paneSizes = b.paneSizes; diff --git a/src/model/element-action.ts b/src/model/element-action.ts index 97172445b..7d67d5c9f 100644 --- a/src/model/element-action.ts +++ b/src/model/element-action.ts @@ -249,12 +249,7 @@ export class ElementAction { } @Mobx.action - public update(raw: this | Types.SerializedElementAction): void { - const b = - raw instanceof ElementAction - ? raw - : ElementAction.from(raw, { userStore: this.userStore }); - + public update(b: this): void { this.id = b.id; this.payload = b.payload; this.payloadType = b.payloadType; diff --git a/src/model/element/element-content.ts b/src/model/element/element-content.ts index 574bb6f97..825bc19d0 100644 --- a/src/model/element/element-content.ts +++ b/src/model/element/element-content.ts @@ -251,8 +251,7 @@ export class ElementContent { } @Mobx.action - public update(raw: ElementContent | Types.SerializedElementContent): void { - const b = raw instanceof ElementContent ? raw.toJSON() : raw; + public update(b: ElementContent): void { this.elementIds = b.elementIds; this.forcedOpen = b.forcedOpen; this.highlighted = b.highlighted; diff --git a/src/model/element/element-property/element-property.ts b/src/model/element/element-property/element-property.ts index 26190c988..260fcd130 100644 --- a/src/model/element/element-property/element-property.ts +++ b/src/model/element/element-property/element-property.ts @@ -208,12 +208,10 @@ export class ElementProperty { } @Mobx.action - public update(b: ElementProperty | Types.SerializedElementProperty): void { - const data = b instanceof ElementProperty ? b.toJSON() : b; - - this.id = data.id; - this.patternPropertyId = data.patternPropertyId; - this.setDefault = data.setDefault; - this.value = data.value; + public update(b: ElementProperty): void { + this.id = b.id; + this.patternPropertyId = b.patternPropertyId; + this.setDefault = b.setDefault; + this.value = b.value; } } diff --git a/src/model/element/element.ts b/src/model/element/element.ts index 3769f1372..20eef1e6c 100644 --- a/src/model/element/element.ts +++ b/src/model/element/element.ts @@ -656,9 +656,7 @@ export class Element { } @Mobx.action - public update(b: Element | Types.SerializedElement): void { - const e = b instanceof Element ? b : Element.from(b, { project: this.project }); - + public update(b: Element): void { if (this.selected) { this.project.unsetSelectedElement(); } @@ -669,22 +667,22 @@ export class Element { const propsChanges = computeDifference({ before: this.getProperties(), - after: e.getProperties() + after: b.getProperties() }); propsChanges.removed.forEach(change => this.removeProperty(change.before)); propsChanges.added.forEach(change => this.addProperty(change.after)); propsChanges.changed.forEach(change => change.before.update(change.after)); - this.shouldHighlight = e.shouldHighlight; - this.dragged = e.dragged; - this.shouldFocus = e.focused; - this.containerId = e.containerId; - this.name = e.name; - this.open = e.open; - this.forcedOpen = e.forcedOpen; - this.shouldPlaceholderHighlight = e.placeholderHighlighted; - this.selected = e.selected; + this.shouldHighlight = b.shouldHighlight; + this.dragged = b.dragged; + this.shouldFocus = b.focused; + this.containerId = b.containerId; + this.name = b.name; + this.open = b.open; + this.forcedOpen = b.forcedOpen; + this.shouldPlaceholderHighlight = b.placeholderHighlighted; + this.selected = b.selected; } } diff --git a/src/model/page/page.ts b/src/model/page/page.ts index 27eebe494..2b8f04d74 100644 --- a/src/model/page/page.ts +++ b/src/model/page/page.ts @@ -273,8 +273,7 @@ export class Page { }; } - public update(raw: Page | Types.SerializedPage): void { - const b = raw instanceof Page ? raw.toJSON() : raw; + public update(b: Page): void { this.active = b.active; this.name = b.name; this.rootId = b.rootId; diff --git a/src/model/pattern-library/pattern-library.ts b/src/model/pattern-library/pattern-library.ts index 468b34532..ed823d08b 100644 --- a/src/model/pattern-library/pattern-library.ts +++ b/src/model/pattern-library/pattern-library.ts @@ -379,9 +379,7 @@ export class PatternLibrary { } @Mobx.action - public update(raw: PatternLibrary | Types.SerializedPatternLibrary): void { - const b = raw instanceof PatternLibrary ? raw : PatternLibrary.from(raw); - + public update(b: PatternLibrary): void { this.bundleId = b.bundleId; this.bundle = b.bundle; this.description = b.description; diff --git a/src/model/pattern-property/asset-property.ts b/src/model/pattern-property/asset-property.ts index d3d11cd6a..6ea0b0d30 100644 --- a/src/model/pattern-property/asset-property.ts +++ b/src/model/pattern-property/asset-property.ts @@ -47,8 +47,7 @@ export class PatternAssetProperty extends PatternPropertyBase { }; } - public update(raw: this | Types.SerializedPatternEventHandlerProperty): void { - const prop = - raw instanceof PatternEventHandlerProperty ? raw : PatternEventHandlerProperty.from(raw); + public update(prop: this): void { this.contextId = prop.getContextId(); this.description = prop.getDescription(); this.event = prop.getEvent(); diff --git a/src/model/pattern-property/href-property.ts b/src/model/pattern-property/href-property.ts index 4bc656b6e..4c1ce780f 100644 --- a/src/model/pattern-property/href-property.ts +++ b/src/model/pattern-property/href-property.ts @@ -47,8 +47,7 @@ export class PatternHrefProperty extends PatternPropertyBase }; } - public update(raw: PatternHrefProperty | Types.SerializedHrefProperty): void { - const prop = raw instanceof PatternHrefProperty ? raw : PatternHrefProperty.from(raw); + public update(prop: PatternHrefProperty): void { this.contextId = prop.getContextId(); this.description = prop.getDescription(); this.defaultValue = prop.getDefaultValue(); diff --git a/src/model/pattern-property/number-property.ts b/src/model/pattern-property/number-property.ts index de4e21e68..d9660349d 100644 --- a/src/model/pattern-property/number-property.ts +++ b/src/model/pattern-property/number-property.ts @@ -51,8 +51,7 @@ export class PatternNumberProperty extends PatternPropertyBase { - let dispose; + const spying: Map void> = new Map(); + Mobx.autorun(() => { const project = store.getProject(); - if (!project && dispose) { - dispose(); + if (!project) { + spying.forEach(end => end()); + return; } - if (!project) { + if (project) { + for (const [p, e] of spying.entries()) { + if (p !== project) { + e(); + } + } + } + + if (spying.has(project)) { return; } - dispose = Mobx.spy((change: Types.MobxChange) => { - window.requestIdleCallback(() => { + spying.set( + project, + Mobx.spy((change: Types.MobxChange) => { switch (change.type) { case Types.MobxChangeType.Update: { if (change.hasOwnProperty('index')) { - console.log(change); - /* const arrayChange = change as Types.MobxArrayUpdate; - - sender.send({ - id: uuid.v4(), - type: Message.MessageType.MobxUpdate, - payload: { - id: change.object.id, - name: '', - change: { - type: arrayChange.type, - index: arrayChange.index, - newValue: change.newValue - } - } - }); */ + console.log('ArrayUpdate:', change); } if (change.hasOwnProperty('key')) { @@ -102,19 +97,21 @@ export function createChangeNotifiers({ app, store }: NotifierContext): void { | Types.MobxObjectUpdate | Types.MobxMapUpdate; - sender.send({ - id: uuid.v4(), - type: Message.MessageType.MobxUpdate, - payload: { - // tslint:disable-next-line:no-any - id: (objectChange.object as any).id, - name: objectChange.object.constructor.name, - change: { - type: objectChange.type, - key: objectChange.key, - newValue: change.newValue + window.requestIdleCallback(() => { + sender.send({ + id: uuid.v4(), + type: Message.MessageType.MobxUpdate, + payload: { + // tslint:disable-next-line:no-any + id: (objectChange.object as any).id, + name: objectChange.object.constructor.name, + change: { + type: objectChange.type, + key: objectChange.key, + newValue: change.newValue + } } - } + }); }); } @@ -126,7 +123,10 @@ export function createChangeNotifiers({ app, store }: NotifierContext): void { return; } - const parent = getParentByMember(change.object, { name: change.name, project }); + const parent = getParentByMember(change.object, { + name: change.name, + project + }); const name = parseChangeName(change.name); if (!parent) { @@ -166,7 +166,10 @@ export function createChangeNotifiers({ app, store }: NotifierContext): void { } case Types.MobxChangeType.Delete: { - const parent = getParentByMember(change.object, { name: change.name, project }); + const parent = getParentByMember(change.object, { + name: change.name, + project + }); const name = parseChangeName(change.name); const deletion = change as Types.MobxDelete; @@ -192,7 +195,10 @@ export function createChangeNotifiers({ app, store }: NotifierContext): void { } case Types.MobxChangeType.Splice: { - const parent = getParentByMember(change.object, { name: change.name, project }); + const parent = getParentByMember(change.object, { + name: change.name, + project + }); const name = parseChangeName(change.name); if (!parent) { @@ -223,12 +229,11 @@ export function createChangeNotifiers({ app, store }: NotifierContext): void { } } }); - break; } } - }); - }); + }) + ); }); } diff --git a/src/store/view-store.ts b/src/store/view-store.ts index 41f579107..517b15007 100644 --- a/src/store/view-store.ts +++ b/src/store/view-store.ts @@ -7,6 +7,8 @@ import * as Types from '../types'; import * as uuid from 'uuid'; +const EMPTY_ARRAY = []; + export interface ViewStoreInit { app: Model.AlvaApp; sender: Sender; @@ -59,6 +61,44 @@ export class ViewStore { @Mobx.observable private sender: Sender; + @Mobx.computed + private get elements(): Model.Element[] { + if (!this.project) { + return EMPTY_ARRAY; + } + + return this.project.getElements(); + } + + @Mobx.computed + private get elementContents(): Model.ElementContent[] { + if (!this.project) { + return EMPTY_ARRAY; + } + + return this.project.getElementContents(); + } + + @Mobx.computed + private get draggedElement(): Model.Element | undefined { + return this.elements.find(e => e.getDragged()); + } + + @Mobx.computed + private get highlightedElement(): Model.Element | undefined { + return this.elements.find(element => element.getHighlighted()); + } + + @Mobx.computed + private get highlightedElementContent(): Model.ElementContent | undefined { + return this.elementContents.find(c => c.getHighlighted()); + } + + @Mobx.computed + private get placeholderHighlightedElement(): Model.Element | undefined { + return this.elements.find(element => element.getPlaceholderHighlighted()); + } + public constructor(init: ViewStoreInit) { this.app = init.app; this.editHistory = init.history; @@ -399,19 +439,11 @@ export class ViewStore { } public getDraggedElement(): Model.Element | undefined { - if (!this.project) { - return; - } - - return this.project.getElements().find(e => e.getDragged()); + return this.draggedElement; } public getDragging(): boolean { - if (!this.project) { - return false; - } - - return this.project.getElements().some(e => e.getDragged()); + return typeof this.draggedElement !== 'undefined'; } public getElementActions(): Model.ElementAction[] { @@ -442,20 +474,16 @@ export class ViewStore { return this.project.getElementById(id); } - public getHighlightedElement(): Model.Element | undefined { - if (!this.project) { - return; - } + public getPlaceHolderHighhlightedElement(): Model.Element | undefined { + return this.placeholderHighlightedElement; + } - return this.project.getElements().find(element => element.getHighlighted()); + public getHighlightedElement(): Model.Element | undefined { + return this.highlightedElement; } public getHighlightedElementContent(): Model.ElementContent | undefined { - if (!this.project) { - return; - } - - return this.project.getElementContents().find(c => c.getHighlighted()); + return this.highlightedElementContent; } public getMetaDown(): boolean {