From a6d904bcd18a2c9962abfd9b5b325340f6b18b0d Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 9 Feb 2022 08:59:32 -0500 Subject: speeding up rendering using bitmaps for webpages and other heavyweight docs. --- .../views/nodes/CollectionFreeFormDocumentView.tsx | 9 + src/client/views/nodes/DocumentView.tsx | 15 +- src/client/views/nodes/VideoBox.tsx | 5 +- src/client/views/nodes/WebBox.tsx | 61 +++- src/client/views/nodes/WebBoxRenderer.js | 395 +++++++++++++++++++++ 5 files changed, 468 insertions(+), 17 deletions(-) create mode 100644 src/client/views/nodes/WebBoxRenderer.js (limited to 'src/client/views/nodes') diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index fe34d6687..28a65f628 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -154,6 +154,14 @@ export class CollectionFreeFormDocumentView extends DocComponent this; render() { TraceMobx(); + + const panx = this.props.CollectionFreeFormView.panX(); + const pany = this.props.CollectionFreeFormView.panY(); + const viewWidth = this.props.CollectionFreeFormView.props.PanelWidth() / this.props.CollectionFreeFormView.zoomScaling() / 2; + const viewHeight = this.props.CollectionFreeFormView.props.PanelHeight() / this.props.CollectionFreeFormView.zoomScaling() / 2; + const hideContent = !this.props.CollectionFreeFormView.props.isAnnotationOverlay && + (Math.min(Math.abs(panx - (this.X + this.panelWidth())), Math.abs(panx - (this.X))) > viewWidth || + Math.min(Math.abs(pany - (this.Y + this.panelHeight())), Math.abs(pany - (this.Y))) > viewHeight) ? true : false; const divProps: DocumentViewProps = { ...this.props, CollectionFreeFormDocumentView: this.returnThis, @@ -162,6 +170,7 @@ export class CollectionFreeFormDocumentView extends DocComponent disposer?.()); } handle1PointerHoldStart = (e: Event, me: InteractionUtils.MultiTouchEvent): any => { @@ -837,6 +840,7 @@ export class DocumentViewInternal extends DocComponent + {(this.isContentActive() && !SnappingManager.GetIsDragging()) || !thumb ? (null) : + ; const WebDocument = makeInterface(documentSchema); @@ -76,6 +78,7 @@ export class WebBox extends ViewBoxAnnotatableComponent a.textInlineAnnotations); } @computed get webField() { return Cast(this.dataDoc[this.props.fieldKey], WebField)?.url; } + @computed get webThumb() { return ImageCast(this.layoutDoc["thumb-frozen"], ImageCast(this.layoutDoc.thumb))?.url; } constructor(props: any) { super(props); @@ -108,9 +111,47 @@ export class WebBox extends ViewBoxAnnotatableComponent { this._annotationKeySuffix = () => this._urlHash + "-annotations"; // bcz: need to make sure that doc.data-annotations points to the currently active web page's annotations (this could/should be when the doc is created) - this.dataDoc[this.fieldKey + "-annotations"] = ComputedField.MakeFunction(`copyField(this["${this.fieldKey}-"+urlHash(this["${this.fieldKey}"]?.url?.toString())+"-annotations"`); - this.dataDoc[this.fieldKey + "-sidebar"] = ComputedField.MakeFunction(`copyField(this["${this.fieldKey}-"+urlHash(this["${this.fieldKey}"]?.url?.toString())+"-sidebar"`); + this.dataDoc[this.fieldKey + "-annotations"] = ComputedField.GetAnnoCopyField(this.fieldKey); + this.dataDoc[this.fieldKey + "-sidebar"] = ComputedField.GetSidebarCopyField(this.fieldKey); }); + reaction(() => this.props.isSelected(), + async (selected) => { + if (selected) { + setTimeout(action(() => { + this._scrollHeight = Math.max(this.scrollHeight, this._iframe?.contentDocument?.body.scrollHeight || 0); + if (this._initialScroll !== undefined && this._outerRef.current) { + setTimeout(() => { + this._outerRef.current!.scrollTop = this._initialScroll!; + this._initialScroll = undefined; + }); + } + })); + } else if (!this.props.isContentActive()) { + const imageBitmap = ImageCast(this.layoutDoc["thumb-frozen"])?.url.href; + if (this._iframe && !imageBitmap) { + var htmlString = this._iframe.contentDocument && new XMLSerializer().serializeToString(this._iframe.contentDocument); + if (!htmlString) { + htmlString = await (await fetch(Utils.CorsProxy(this.webField!.href))).text(); + } + const nativeWidth = NumCast(this.layoutDoc.nativeWidth); + CreateImage( + this._webUrl.endsWith("/") ? this._webUrl.substring(0, this._webUrl.length - 1) : this._webUrl, + this._iframe.contentDocument?.styleSheets ?? [], + htmlString, + nativeWidth, + nativeWidth * this.props.PanelHeight() / this.props.PanelWidth(), + NumCast(this.layoutDoc._scrollTop) + ).then + (action((dataUrl: any) => { + VideoBox.convertDataUri(dataUrl, this.layoutDoc[Id] + "-thumb", true).then( + returnedfilename => this.layoutDoc.thumb = new ImageField(returnedfilename)); + })) + .catch(function (error: any) { + console.error('oops, something went wrong!', error); + }); + } + } + }); this._disposers.autoHeight = reaction(() => this.layoutDoc._autoHeight, autoHeight => { @@ -292,12 +333,6 @@ export class WebBox extends ViewBoxAnnotatableComponent this._scrollHeight = Math.max(this.scrollHeight, iframe?.contentDocument?.body.scrollHeight || 0)), 5000); - const initialScroll = this._initialScroll; - if (initialScroll !== undefined && this._outerRef.current) { - // bcz: not sure why this happens, but if the webpage isn't ready yet, it's scroll height seems to be limited. So we need to wait tp set scroll location to what we want. - setTimeout(() => this._outerRef.current!.scrollTop = initialScroll); - this._initialScroll = undefined; - } iframe.setAttribute("enable-annotation", "true"); iframe.contentDocument.addEventListener("click", undoBatch(action((e: MouseEvent) => { let href = ""; @@ -665,7 +700,8 @@ export class WebBox extends ViewBoxAnnotatableComponent -
+