From 0178de4ab9ffd11630b700f9c02468b74beabd14 Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 17 Aug 2022 12:31:26 -0400 Subject: fixed dragging docs on web and pdf to work better by temporarily adding transparent docs to the opaque layer so they can get drop events. cleaned eraser and pen interaction code and made erasing strokes work faster and avoid hanging by not intersecting strokes that are already partially deleted. --- src/client/views/nodes/WebBox.tsx | 110 ++++++++++++++++++++------------------ 1 file changed, 57 insertions(+), 53 deletions(-) (limited to 'src/client/views/nodes/WebBox.tsx') diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index ca9f363c1..6c2e42f86 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -1,5 +1,5 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { action, computed, IReactionDisposer, observable, ObservableMap, reaction, runInAction } from 'mobx'; +import { action, computed, IReactionDisposer, observable, ObservableMap, reaction, runInAction, trace } from 'mobx'; import { observer } from 'mobx-react'; import * as WebRequest from 'web-request'; import { Doc, DocListCast, HeightSym, Opt, WidthSym } from '../../../fields/Doc'; @@ -11,7 +11,7 @@ import { listSpec } from '../../../fields/Schema'; import { Cast, ImageCast, NumCast, StrCast } from '../../../fields/Types'; import { ImageField, WebField } from '../../../fields/URLField'; import { TraceMobx } from '../../../fields/util'; -import { emptyFunction, getWordAtPoint, OmitKeys, returnFalse, returnOne, setupMoveUpEvents, smoothScroll, Utils } from '../../../Utils'; +import { emptyFunction, getWordAtPoint, OmitKeys, returnFalse, returnOne, setupMoveUpEvents, smoothScroll, StopEvent, Utils } from '../../../Utils'; import { Docs, DocUtils } from '../../documents/Documents'; import { ScriptingGlobals } from '../../util/ScriptingGlobals'; import { SnappingManager } from '../../util/SnappingManager'; @@ -35,6 +35,7 @@ import { LinkDocPreview } from './LinkDocPreview'; import { VideoBox } from './VideoBox'; import './WebBox.scss'; import React = require('react'); +import { DragManager } from '../../util/DragManager'; const { CreateImage } = require('./WebBoxRenderer'); const _global = (window /* browser */ || global) /* node */ as any; const htmlToText = require('html-to-text'); @@ -818,6 +819,56 @@ export class WebBox extends ViewBoxAnnotatableComponent string[]) => ( + + ); + return ( +
this.setDashScrollTop(this._outerRef.current?.scrollTop || 0)} + onPointerDown={this.onMarqueeDown}> +
+ {this.content} + {
{renderAnnotations(this.transparentFilter)}
} + {renderAnnotations(this.opaqueFilter)} + {this.annotationLayer} +
+
+ ); + } + @computed get searchUI() { return (
e.stopPropagation()} style={{ display: this.props.isContentActive() ? 'flex' : 'none' }}> @@ -859,9 +910,8 @@ export class WebBox extends ViewBoxAnnotatableComponent this.props.PanelHeight() / (this.props.NativeDimScaling?.() || 1); // () => this._pageSizes.length && this._pageSizes[0] ? this._pageSizes[0].width : Doc.NativeWidth(this.Document); scrollXf = () => this.props.ScreenToLocalTransform().translate(0, NumCast(this.layoutDoc._scrollTop)); anchorMenuClick = () => this._sidebarRef.current?.anchorMenuClick; - basicFilter = () => [...this.props.docFilters(), Utils.PropUnsetFilter('textInlineAnnotations')]; transparentFilter = () => [...this.props.docFilters(), Utils.IsTransparentFilter()]; - opaqueFilter = () => [...this.props.docFilters(), Utils.IsOpaqueFilter()]; + opaqueFilter = () => [...this.props.docFilters(), Utils.noDragsDocFilter, ...(DragManager.docsBeingDragged.length ? [] : [Utils.IsOpaqueFilter()])]; childStyleProvider = (doc: Doc | undefined, props: Opt, property: string): any => { if (doc instanceof Doc && property === StyleProp.PointerEvents) { if (doc.textInlineAnnotations) return 'none'; @@ -871,37 +921,11 @@ export class WebBox extends ViewBoxAnnotatableComponent (!this._draggingSidebar && this.props.isContentActive() && this.props.pointerEvents?.() !== 'none' && !MarqueeOptionsMenu.Instance.isShown() ? 'all' : SnappingManager.GetIsDragging() ? undefined : 'none'); annotationPointerEvents = () => (this._isAnnotating || SnappingManager.GetIsDragging() ? 'all' : 'none'); render() { - const pointerEvents = this.layoutDoc._lockedPosition ? 'none' : (this.props.pointerEvents?.() as any); const previewScale = this._previewNativeWidth ? 1 - this.sidebarWidth() / this._previewNativeWidth : 1; + const pointerEvents = this.layoutDoc._lockedPosition ? 'none' : (this.props.pointerEvents?.() as any); const scale = previewScale * (this.props.NativeDimScaling?.() || 1); - const renderAnnotations = (docFilters?: () => string[]) => ( - - ); return ( -
+
-
{ - e.stopPropagation(); - e.preventDefault(); - }} // block wheel events from propagating since they're handled by the iframe - onScroll={e => this.setDashScrollTop(this._outerRef.current?.scrollTop || 0)} - onPointerDown={this.onMarqueeDown}> -
- {this.content} -
{renderAnnotations(this.transparentFilter)}
- {renderAnnotations(this.opaqueFilter)} - {SnappingManager.GetIsDragging() ? null : renderAnnotations()} - {this.annotationLayer} -
-
+ {this.webpage} {!this._marqueeing || !this._mainCont.current || !this._annotationLayer.current ? null : (
Date: Fri, 26 Aug 2022 16:34:15 -0400 Subject: from last --- src/client/views/nodes/WebBox.tsx | 2 +- src/client/views/pdf/PDFViewer.tsx | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'src/client/views/nodes/WebBox.tsx') diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index 6c2e42f86..b9e8e7c6e 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -285,7 +285,7 @@ export class WebBox extends ViewBoxAnnotatableComponent { const windowHeight = this.props.PanelHeight() / (this.props.NativeDimScaling?.() || 1); const scrollTo = doc.unrendered ? NumCast(doc.y) : Utils.scrollIntoView(NumCast(doc.y), doc[HeightSym](), NumCast(this.props.layoutDoc._scrollTop), windowHeight, 0.1 * windowHeight, NumCast(this.props.Document.scrollHeight)); if (scrollTo !== undefined && scrollTo !== this.props.layoutDoc._scrollTop) { - focusSpeed = 500; - if (!this._pdfViewer) this._initialScroll = scrollTo; - else if (smooth) smoothScroll(focusSpeed, mainCont, scrollTo); + else if (smooth) smoothScroll((focusSpeed = NumCast(doc.focusSpeed, 500)), mainCont, scrollTo); else this._mainCont.current?.scrollTo({ top: Math.abs(scrollTo || 0) }); } } else { -- cgit v1.2.3-70-g09d2 From fb873aed085f8e11231a231aac94d6fb3bd27683 Mon Sep 17 00:00:00 2001 From: bobzel Date: Mon, 29 Aug 2022 13:31:22 -0400 Subject: fixed being able to draw on web/pdfs. adjusted default margins of stacking views. --- src/client/views/GlobalKeyHandler.ts | 8 ++++---- src/client/views/collections/CollectionStackingView.tsx | 9 +++++---- src/client/views/nodes/DocumentView.tsx | 1 + src/client/views/nodes/WebBox.tsx | 2 +- src/client/views/pdf/PDFViewer.tsx | 1 + 5 files changed, 12 insertions(+), 9 deletions(-) (limited to 'src/client/views/nodes/WebBox.tsx') diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts index 85f579975..88ce457c6 100644 --- a/src/client/views/GlobalKeyHandler.ts +++ b/src/client/views/GlobalKeyHandler.ts @@ -160,16 +160,16 @@ export class KeyManager { break; case 'arrowleft': UndoManager.RunInBatch(() => SelectionManager.Views().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge(-1, 0)), 'nudge left'); - break; + return { stopPropagation: true, preventDefault: true }; case 'arrowright': UndoManager.RunInBatch(() => SelectionManager.Views().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge?.(1, 0)), 'nudge right'); - break; + return { stopPropagation: true, preventDefault: true }; case 'arrowup': UndoManager.RunInBatch(() => SelectionManager.Views().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge?.(0, -1)), 'nudge up'); - break; + return { stopPropagation: true, preventDefault: true }; case 'arrowdown': UndoManager.RunInBatch(() => SelectionManager.Views().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge?.(0, 1)), 'nudge down'); - break; + return { stopPropagation: true, preventDefault: true }; } return { diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 7f142727c..cc006c734 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -80,13 +80,14 @@ export class CollectionStackingView extends CollectionSubView (!this._draggingSidebar && this.props.isContentActive() && this.props.pointerEvents?.() !== 'none' && !MarqueeOptionsMenu.Instance.isShown() ? 'all' : SnappingManager.GetIsDragging() ? undefined : 'none'); - annotationPointerEvents = () => (this._isAnnotating || SnappingManager.GetIsDragging() ? 'all' : 'none'); + annotationPointerEvents = () => (this._isAnnotating || SnappingManager.GetIsDragging() || Doc.ActiveTool !== InkTool.None ? 'all' : 'none'); render() { const previewScale = this._previewNativeWidth ? 1 - this.sidebarWidth() / this._previewNativeWidth : 1; const pointerEvents = this.layoutDoc._lockedPosition ? 'none' : (this.props.pointerEvents?.() as any); diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index f1f3bfc57..53d969c0a 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -503,6 +503,7 @@ export class PDFViewer extends React.Component { mixBlendMode: mixBlendMode, display: display, transform: `scale(${NumCast(this.props.layoutDoc._viewScale, 1)})`, + pointerEvents: Doc.ActiveTool !== InkTool.None ? 'all' : undefined, }}> Date: Mon, 19 Sep 2022 15:03:30 -0400 Subject: added pin with view for region to webBox --- src/client/views/nodes/WebBox.tsx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src/client/views/nodes/WebBox.tsx') diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index 2c5deba88..b086b7ffb 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -47,6 +47,7 @@ export class WebBox extends ViewBoxAnnotatableComponent void); + private _setBrushViewer: undefined | ((view: { width: number; height: number; panX: number; panY: number }) => void); private _mainCont: React.RefObject = React.createRef(); private _outerRef: React.RefObject = React.createRef(); private _disposers: { [name: string]: IReactionDisposer } = {}; @@ -275,6 +276,8 @@ export class WebBox extends ViewBoxAnnotatableComponent this.urlEditor; // controls to be added to the top bar when a document of this type is selected + setBrushViewer = (func?: (view: { width: number; height: number; panX: number; panY: number }) => void) => (this._setBrushViewer = func); + brushView = (view: { width: number; height: number; panX: number; panY: number }) => this._setBrushViewer?.(view); scrollFocus = (doc: Doc, smooth: boolean) => { if (StrCast(doc.webUrl) !== this._url) this.submitURL(StrCast(doc.webUrl), !smooth); if (DocListCast(this.props.Document[this.fieldKey + '-sidebar']).includes(doc) && !this.SidebarShown) { @@ -332,7 +335,7 @@ export class WebBox extends ViewBoxAnnotatableComponent (this._marqueeing = undefined)), @@ -349,7 +352,7 @@ export class WebBox extends ViewBoxAnnotatableComponent Date: Tue, 20 Sep 2022 11:34:38 -0400 Subject: fixed pdf boxes to be active in lightboxview by fixing lightboxview docview to be observable so that IsLightboxDoc's will invalidate. made webBox's content 'relative' so that linksButton is in correct place. changed text highlight color to orange for webboxes --- src/client/views/LightboxView.tsx | 4 ++-- src/client/views/nodes/PDFBox.tsx | 3 ++- src/client/views/nodes/WebBox.scss | 8 +++++++- src/client/views/nodes/WebBox.tsx | 19 +++++++++++++++++++ .../views/nodes/formattedText/FormattedTextBox.tsx | 8 ++++---- 5 files changed, 34 insertions(+), 8 deletions(-) (limited to 'src/client/views/nodes/WebBox.tsx') diff --git a/src/client/views/LightboxView.tsx b/src/client/views/LightboxView.tsx index cb5094f4b..e3e8403df 100644 --- a/src/client/views/LightboxView.tsx +++ b/src/client/views/LightboxView.tsx @@ -39,7 +39,7 @@ export class LightboxView extends React.Component { private static _savedState: Opt<{ panX: Opt; panY: Opt; scale: Opt; scrollTop: Opt }>; private static _history: Opt<{ doc: Doc; target?: Doc }[]> = []; @observable private static _future: Opt = []; - private static _docView: Opt; + @observable private static _docView: Opt; private static openInTabFunc: any; static path: { doc: Opt; target: Opt; history: Opt<{ doc: Doc; target?: Doc }[]>; future: Opt; saved: Opt<{ panX: Opt; panY: Opt; scale: Opt; scrollTop: Opt }> }[] = []; @action public static SetLightboxDoc(doc: Opt, target?: Doc, future?: Doc[], layoutTemplate?: Doc) { @@ -98,7 +98,7 @@ export class LightboxView extends React.Component { return true; } public static IsLightboxDocView(path: DocumentView[]) { - return path.includes(this._docView!); + return (path ?? []).includes(this._docView!); } @computed get leftBorder() { return Math.min(this.props.PanelWidth / 4, this.props.maxBorder[0]); diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index 001d9a5a6..c7001f846 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -18,6 +18,7 @@ import { ContextMenu } from '../ContextMenu'; import { ContextMenuProps } from '../ContextMenuItem'; import { ViewBoxAnnotatableComponent, ViewBoxAnnotatableProps } from '../DocComponent'; import { Colors } from '../global/globalEnums'; +import { LightboxView } from '../LightboxView'; import { CreateImage } from '../nodes/WebBoxRenderer'; import { PDFViewer } from '../pdf/PDFViewer'; import { SidebarAnnos } from '../SidebarAnnos'; @@ -441,7 +442,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent this.isAnyChildContentActive() || this.props.isSelected(); + isPdfContentActive = () => this.isAnyChildContentActive() || this.props.isSelected() || (this.props.renderDepth === 0 && LightboxView.IsLightboxDocView(this.props.docViewPath())); @computed get renderPdfView() { TraceMobx(); const previewScale = this._previewNativeWidth ? 1 - this.sidebarWidth() / this._previewNativeWidth : 1; diff --git a/src/client/views/nodes/WebBox.scss b/src/client/views/nodes/WebBox.scss index 85986ff27..a41f66ef0 100644 --- a/src/client/views/nodes/WebBox.scss +++ b/src/client/views/nodes/WebBox.scss @@ -5,7 +5,7 @@ width: 100%; top: 0; left: 0; - position: absolute; + position: relative; display: flex; .webBox-sideResizer { @@ -182,6 +182,12 @@ height: 100%; position: absolute; top: 0; + body { + ::selection { + color: white; + background: orange; + } + } } } diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index b086b7ffb..e7b188961 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -366,12 +366,31 @@ export class WebBox extends ViewBoxAnnotatableComponent this._iframeClick; iframeScaling = () => 1 / this.props.ScreenToLocalTransform().Scale; + addStyleSheet(document: any, styleType: string = 'text/css') { + const style = document.createElement('style'); + style.type = styleType; + const sheets = document.head.appendChild(style); + return (sheets as any).sheet; + } + addStyleSheetRule(sheet: any, selector: any, css: any, selectorPrefix = '.') { + const propText = + typeof css === 'string' + ? css + : Object.keys(css) + .map(p => p + ':' + (p === 'content' ? "'" + css[p] + "'" : css[p])) + .join(';'); + return sheet.insertRule(selectorPrefix + selector + '{' + propText + '}', sheet.cssRules.length); + } + @action iframeLoaded = (e: any) => { const iframe = this._iframe; if (this._initialScroll !== undefined) { this.setScrollPos(this._initialScroll); } + + this.addStyleSheetRule(this.addStyleSheet(this._iframe?.contentDocument), '::selection', { color: 'white', background: 'orange' }, ''); + let requrlraw = decodeURIComponent(iframe?.contentWindow?.location.href.replace(Utils.prepend('') + '/corsProxy/', '') ?? this._url.toString()); if (requrlraw !== this._url.toString()) { if (requrlraw.match(/q=.*&/)?.length && this._url.toString().match(/q=.*&/)?.length) { diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 2625b34d2..6db199149 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -603,20 +603,20 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent span', { 'font-size': 'large' }, ''); addStyleSheetRule(FormattedTextBox._userStyleSheet, '.formattedTextBox-inner-selected .ProseMirror :not(strong > span)', { 'font-size': '0px' }, ''); } if (highlights.indexOf('Disagree Items') !== -1) { - addStyleSheetRule(FormattedTextBox._userStyleSheet, 'UT-' + 'disagree', { 'text-decoration': 'line-through' }); + addStyleSheetRule(FormattedTextBox._userStyleSheet, 'UT-disagree', { 'text-decoration': 'line-through' }); } if (highlights.indexOf('Ignore Items') !== -1) { - addStyleSheetRule(FormattedTextBox._userStyleSheet, 'UT-' + 'ignore', { 'font-size': '1' }); + addStyleSheetRule(FormattedTextBox._userStyleSheet, 'UT-ignore', { 'font-size': '1' }); } if (highlights.indexOf('By Recent Minute') !== -1) { addStyleSheetRule(FormattedTextBox._userStyleSheet, 'UM-' + Doc.CurrentUserEmail.replace('.', '').replace('@', ''), { opacity: '0.1' }); -- cgit v1.2.3-70-g09d2 From 38e56a0eb6d965535be748b5bf7befed6edbc4ee Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 22 Sep 2022 12:28:52 -0400 Subject: fixed webboxes not to render below webbox when something is dragged. --- src/client/views/nodes/WebBox.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/client/views/nodes/WebBox.tsx') diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index e7b188961..8288810b1 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -948,7 +948,10 @@ export class WebBox extends ViewBoxAnnotatableComponent +
Date: Fri, 7 Oct 2022 00:33:04 -0400 Subject: improvements to sizing webpages --- src/client/views/SidebarAnnos.tsx | 2 +- src/client/views/collections/CollectionView.tsx | 1 - src/client/views/nodes/LinkDocPreview.tsx | 2 +- src/client/views/nodes/WebBox.tsx | 28 ++++++++++++++++++------- 4 files changed, 22 insertions(+), 11 deletions(-) (limited to 'src/client/views/nodes/WebBox.tsx') diff --git a/src/client/views/SidebarAnnos.tsx b/src/client/views/SidebarAnnos.tsx index 90d9c3c43..12f41394d 100644 --- a/src/client/views/SidebarAnnos.tsx +++ b/src/client/views/SidebarAnnos.tsx @@ -73,7 +73,7 @@ export class SidebarAnnos extends React.Component { this.allMetadata.map(tag => (target[tag] = tag)); DocUtils.MakeLink({ doc: anchor }, { doc: target }, 'inline comment:comment on'); this.addDocument(target); - this._stackRef.current?.focusDocument(target); + this._stackRef.current?.focusDocument(target, {}); return target; }; makeDocUnfiltered = (doc: Doc) => { diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index d88d59205..dcaad5632 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -15,7 +15,6 @@ import { ImageUtils } from '../../util/Import & Export/ImageUtils'; import { InteractionUtils } from '../../util/InteractionUtils'; import { ContextMenu } from '../ContextMenu'; import { ContextMenuProps } from '../ContextMenuItem'; -import { DashboardView } from '../DashboardView'; import { ViewBoxAnnotatableComponent, ViewBoxAnnotatableProps } from '../DocComponent'; import { FieldView, FieldViewProps } from '../nodes/FieldView'; import { CollectionCarousel3DView } from './CollectionCarousel3DView'; diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx index f50524e4e..27e79a83b 100644 --- a/src/client/views/nodes/LinkDocPreview.tsx +++ b/src/client/views/nodes/LinkDocPreview.tsx @@ -228,7 +228,7 @@ export class LinkDocPreview extends React.Component { { const targetanchor = this._linkDoc && this._linkSrc && LinkManager.getOppositeAnchor(this._linkDoc, this._linkSrc); - targetanchor && this._targetDoc !== targetanchor && r?.focus(targetanchor); + targetanchor && this._targetDoc !== targetanchor && r?.focus(targetanchor, {}); }} Document={this._targetDoc!} moveDocument={returnFalse} diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index 8288810b1..460edb7c2 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -243,6 +243,8 @@ export class WebBox extends ViewBoxAnnotatableComponent disposer?.()); // this._iframe?.removeEventListener('wheel', this.iframeWheel, true); // this._iframe?.contentDocument?.removeEventListener("pointerup", this.iframeUp); @@ -382,6 +384,7 @@ export class WebBox extends ViewBoxAnnotatableComponent { const iframe = this._iframe; @@ -409,16 +412,25 @@ export class WebBox extends ViewBoxAnnotatableComponent (this._scrollHeight = Math.max(this._scrollHeight, iframe?.contentDocument?.body.scrollHeight || 0))), + const iframeContent = iframe?.contentDocument; + if (iframeContent) { + iframeContent.addEventListener('pointerup', this.iframeUp); + iframeContent.addEventListener('pointerdown', this.iframeDown); + const initHeights = () => { + this._scrollHeight = Math.max(this._scrollHeight, (iframeContent.body.children[0] as any)?.scrollHeight || 0); + if (this._scrollHeight) { + this.rootDoc.nativeHeight = Math.min(NumCast(this.rootDoc.nativeHeight), this._scrollHeight); + this.layoutDoc.height = Math.min(this.layoutDoc[HeightSym](), (this.layoutDoc[WidthSym]() * NumCast(this.rootDoc.nativeHeight)) / NumCast(this.rootDoc.nativeWidth)); + } + }; + initHeights(); + this._iframetimeout && clearTimeout(this._iframetimeout); + this._iframetimeout = setTimeout( + action(() => initHeights), 5000 ); iframe.setAttribute('enable-annotation', 'true'); - iframe.contentDocument.addEventListener( + iframeContent.addEventListener( 'click', undoBatch( action((e: MouseEvent) => { @@ -882,7 +894,7 @@ export class WebBox extends ViewBoxAnnotatableComponent this.setDashScrollTop(this._outerRef.current?.scrollTop || 0)} onPointerDown={this.onMarqueeDown}> -
+
{this.content} {
{renderAnnotations(this.transparentFilter)}
} {renderAnnotations(this.opaqueFilter)} -- cgit v1.2.3-70-g09d2 From dd5cfe5302279d708bd8fbc7b9cad7ea082758c4 Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 13 Oct 2022 10:39:33 -0400 Subject: some basic error checking. avoid querying background for non-toggle buttons --- src/client/util/CurrentUserUtils.ts | 2 +- .../views/nodes/CollectionFreeFormDocumentView.tsx | 2 +- src/client/views/nodes/WebBox.tsx | 24 ++- src/client/views/nodes/WebBoxRenderer.js | 183 ++++++++++----------- .../views/nodes/formattedText/DashDocView.tsx | 2 +- 5 files changed, 111 insertions(+), 102 deletions(-) (limited to 'src/client/views/nodes/WebBox.tsx') diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index eb0812cba..1c9f89fa0 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -689,7 +689,7 @@ export class CurrentUserUtils { }; const reqdFuncs:{[key:string]:any} = { ...params.funcs, - backgroundColor: params.scripts?.onClick /// a bit hacky. if onClick is set, then we assume it returns a color value when queried with '_readOnly_'. This will be true for toggle buttons, but not generally + backgroundColor: params.btnType === ButtonType.ToggleButton ? params.scripts?.onClick:undefined /// a bit hacky. if onClick is set, then we assume it returns a color value when queried with '_readOnly_'. This will be true for toggle buttons, but not generally } return DocUtils.AssignScripts(DocUtils.AssignOpts(btnDoc, reqdOpts) ?? Docs.Create.FontIconDocument(reqdOpts), params.scripts, reqdFuncs); } diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index a48906372..04c7b96e3 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -222,7 +222,7 @@ export class CollectionFreeFormDocumentView extends DocComponent this.sizeProvider?.width || this.props.PanelWidth?.(); panelHeight = () => this.sizeProvider?.height || this.props.PanelHeight?.(); screenToLocalTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-this.X, -this.Y); - focusDoc = (doc: Doc) => this.props.focus(doc); + focusDoc = (doc: Doc) => this.props.focus(doc, {}); returnThis = () => this; render() { TraceMobx(); diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index 460edb7c2..db493934a 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -156,6 +156,10 @@ export class WebBox extends ViewBoxAnnotatableComponent { + if (data_url.includes(' setTimeout( action(() => { @@ -369,10 +373,12 @@ export class WebBox extends ViewBoxAnnotatableComponent 1 / this.props.ScreenToLocalTransform().Scale; addStyleSheet(document: any, styleType: string = 'text/css') { - const style = document.createElement('style'); - style.type = styleType; - const sheets = document.head.appendChild(style); - return (sheets as any).sheet; + if (document) { + const style = document.createElement('style'); + style.type = styleType; + const sheets = document.head.appendChild(style); + return (sheets as any).sheet; + } } addStyleSheetRule(sheet: any, selector: any, css: any, selectorPrefix = '.') { const propText = @@ -381,7 +387,7 @@ export class WebBox extends ViewBoxAnnotatableComponent p + ':' + (p === 'content' ? "'" + css[p] + "'" : css[p])) .join(';'); - return sheet.insertRule(selectorPrefix + selector + '{' + propText + '}', sheet.cssRules.length); + return sheet?.insertRule(selectorPrefix + selector + '{' + propText + '}', sheet.cssRules.length); } _iframetimeout: any = undefined; @@ -394,7 +400,13 @@ export class WebBox extends ViewBoxAnnotatableComponent; + try { + href = iframe?.contentWindow?.location.href; + } catch (e) { + href = undefined; + } + let requrlraw = decodeURIComponent(href?.replace(Utils.prepend('') + '/corsProxy/', '') ?? this._url.toString()); if (requrlraw !== this._url.toString()) { if (requrlraw.match(/q=.*&/)?.length && this._url.toString().match(/q=.*&/)?.length) { const matches = requrlraw.match(/[^a-zA-z]q=[^&]*/g); diff --git a/src/client/views/nodes/WebBoxRenderer.js b/src/client/views/nodes/WebBoxRenderer.js index f3f1bcf5c..cebb94d86 100644 --- a/src/client/views/nodes/WebBoxRenderer.js +++ b/src/client/views/nodes/WebBoxRenderer.js @@ -1,14 +1,13 @@ /** - * - * @param {StyleSheetList} styleSheets + * + * @param {StyleSheetList} styleSheets */ var ForeignHtmlRenderer = function (styleSheets) { - const self = this; /** - * - * @param {String} binStr + * + * @param {String} binStr */ const binaryStringToBase64 = function (binStr) { return new Promise(function (resolve) { @@ -16,7 +15,7 @@ var ForeignHtmlRenderer = function (styleSheets) { reader.readAsDataURL(binStr); reader.onloadend = function () { resolve(reader.result); - } + }; }); }; @@ -24,11 +23,11 @@ var ForeignHtmlRenderer = function (styleSheets) { return window.location.origin + extension; } function CorsProxy(url) { - return prepend("/corsProxy/") + encodeURIComponent(url); + return prepend('/corsProxy/') + encodeURIComponent(url); } /** - * - * @param {String} url + * + * @param {String} url * @returns {Promise} */ const getResourceAsBase64 = function (webUrl, inurl) { @@ -37,35 +36,30 @@ var ForeignHtmlRenderer = function (styleSheets) { //const url = inurl.startsWith("/") && !inurl.startsWith("//") ? webUrl + inurl : inurl; //const url = CorsProxy(inurl.startsWith("/") && !inurl.startsWith("//") ? webUrl + inurl : inurl);// inurl.startsWith("http") ? CorsProxy(inurl) : inurl; var url = inurl; - if (inurl.startsWith("/static")) { - url = (new URL(webUrl).origin + inurl); - } else - if ((inurl.startsWith("/") && !inurl.startsWith("//"))) { - url = CorsProxy(new URL(webUrl).origin + inurl); - } else if (!inurl.startsWith("http") && !inurl.startsWith("//")) { - url = CorsProxy(webUrl + "/" + inurl); - } - xhr.open("GET", url); + if (inurl.startsWith('/static')) { + url = new URL(webUrl).origin + inurl; + } else if (inurl.startsWith('/') && !inurl.startsWith('//')) { + url = CorsProxy(new URL(webUrl).origin + inurl); + } else if (!inurl.startsWith('http') && !inurl.startsWith('//')) { + url = CorsProxy(webUrl + '/' + inurl); + } + xhr.open('GET', url); xhr.responseType = 'blob'; xhr.onreadystatechange = async function () { if (xhr.readyState === 4 && xhr.status === 200) { const resBase64 = await binaryStringToBase64(xhr.response); - resolve( - { - "resourceUrl": inurl, - "resourceBase64": resBase64 - } - ); + resolve({ + resourceUrl: inurl, + resourceBase64: resBase64, + }); } else if (xhr.readyState === 4) { - console.log("COULDN'T FIND: " + (inurl.startsWith("/") ? webUrl + inurl : inurl)); - resolve( - { - "resourceUrl": "", - "resourceBase64": inurl - } - ); + console.log("COULDN'T FIND: " + (inurl.startsWith('/') ? webUrl + inurl : inurl)); + resolve({ + resourceUrl: '', + resourceBase64: inurl, + }); } }; @@ -74,8 +68,8 @@ var ForeignHtmlRenderer = function (styleSheets) { }; /** - * - * @param {String[]} urls + * + * @param {String[]} urls * @returns {Promise} */ const getMultipleResourcesAsBase64 = function (webUrl, urls) { @@ -87,13 +81,13 @@ var ForeignHtmlRenderer = function (styleSheets) { }; /** - * - * @param {String} str - * @param {Number} startIndex - * @param {String} prefixToken + * + * @param {String} str + * @param {Number} startIndex + * @param {String} prefixToken * @param {String[]} suffixTokens - * - * @returns {String|null} + * + * @returns {String|null} */ const parseValue = function (str, startIndex, prefixToken, suffixTokens) { const idx = str.indexOf(prefixToken, startIndex); @@ -111,17 +105,17 @@ var ForeignHtmlRenderer = function (styleSheets) { } return { - "foundAtIndex": idx, - "value": val - } + foundAtIndex: idx, + value: val, + }; }; /** - * - * @param {String} cssRuleStr + * + * @param {String} cssRuleStr * @returns {String[]} */ - const getUrlsFromCssString = function (cssRuleStr, selector = "url(", delimiters = [')'], mustEndWithQuote = false) { + const getUrlsFromCssString = function (cssRuleStr, selector = 'url(', delimiters = [')'], mustEndWithQuote = false) { const urlsFound = []; let searchStartIndex = 0; @@ -133,7 +127,7 @@ var ForeignHtmlRenderer = function (styleSheets) { searchStartIndex = url.foundAtIndex + url.value.length; if (mustEndWithQuote && url.value[url.value.length - 1] !== '"') continue; const unquoted = removeQuotes(url.value); - if (!unquoted /* || (!unquoted.startsWith('http')&& !unquoted.startsWith("/") )*/ || unquoted === 'http://' || unquoted === 'https://') { + if (!unquoted /* || (!unquoted.startsWith('http')&& !unquoted.startsWith("/") )*/ || unquoted === 'http://' || unquoted === 'https://') { continue; } @@ -144,24 +138,24 @@ var ForeignHtmlRenderer = function (styleSheets) { }; /** - * - * @param {String} html + * + * @param {String} html * @returns {String[]} */ const getImageUrlsFromFromHtml = function (html) { - return getUrlsFromCssString(html, "src=", [' ', '>', '\t'], true); + return getUrlsFromCssString(html, 'src=', [' ', '>', '\t'], true); }; const getSourceUrlsFromFromHtml = function (html) { - return getUrlsFromCssString(html, "source=", [' ', '>', '\t'], true); + return getUrlsFromCssString(html, 'source=', [' ', '>', '\t'], true); }; /** - * + * * @param {String} str * @returns {String} */ const removeQuotes = function (str) { - return str.replace(/["']/g, ""); + return str.replace(/["']/g, ''); }; const escapeRegExp = function (string) { @@ -169,37 +163,33 @@ var ForeignHtmlRenderer = function (styleSheets) { }; /** - * - * @param {String} contentHtml + * + * @param {String} contentHtml * @param {Number} width * @param {Number} height - * + * * @returns {Promise} */ const buildSvgDataUri = async function (webUrl, contentHtml, width, height, scroll, xoff) { - return new Promise(async function (resolve, reject) { - /* !! The problems !! - * 1. CORS (not really an issue, expect perhaps for images, as this is a general security consideration to begin with) - * 2. Platform won't wait for external assets to load (fonts, images, etc.) - */ + * 1. CORS (not really an issue, expect perhaps for images, as this is a general security consideration to begin with) + * 2. Platform won't wait for external assets to load (fonts, images, etc.) + */ // copy styles - let cssStyles = ""; + let cssStyles = ''; let urlsFoundInCss = []; for (let i = 0; i < styleSheets.length; i++) { try { - const rules = styleSheets[i].cssRules + const rules = styleSheets[i].cssRules; for (let j = 0; j < rules.length; j++) { const cssRuleStr = rules[j].cssText; urlsFoundInCss.push(...getUrlsFromCssString(cssRuleStr)); cssStyles += cssRuleStr; } - } catch (e) { - - } + } catch (e) {} } // const fetchedResourcesFromStylesheets = await getMultipleResourcesAsBase64(webUrl, urlsFoundInCss); @@ -210,30 +200,32 @@ var ForeignHtmlRenderer = function (styleSheets) { // } // } - contentHtml = contentHtml.replace(/]*>/g, "") // tags have a which has a srcset field of image refs. instead of converting each, just use the default of the picture - .replace(/noscript/g, "div").replace(/
<\/div>/g, "") // when scripting isn't available (ie, rendering web pages here),