aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/WebBox.tsx
diff options
context:
space:
mode:
authorSophie Zhang <sophie_zhang@brown.edu>2024-01-25 11:35:26 -0500
committerSophie Zhang <sophie_zhang@brown.edu>2024-01-25 11:35:26 -0500
commitf3dab2a56db5e4a6a3dca58185d94e1ff7d1dc32 (patch)
treea7bc895266b53bb620dbd2dd71bad2e83b555446 /src/client/views/nodes/WebBox.tsx
parentb5c5410b4af5d2c68d2107d3f064f6e3ec4ac3f2 (diff)
parent136f3d9f349d54e8bdd73b6380ea47c19e5edebf (diff)
Merge branch 'master' into sophie-ai-images
Diffstat (limited to 'src/client/views/nodes/WebBox.tsx')
-rw-r--r--src/client/views/nodes/WebBox.tsx448
1 files changed, 230 insertions, 218 deletions
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index 58a765d61..5a07540da 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -1,22 +1,22 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { action, computed, IReactionDisposer, observable, ObservableMap, reaction, runInAction } from 'mobx';
+import { htmlToText } from 'html-to-text';
+import { action, computed, IReactionDisposer, makeObservable, observable, ObservableMap, reaction, runInAction } from 'mobx';
import { observer } from 'mobx-react';
+import * as React from 'react';
import * as WebRequest from 'web-request';
import { Doc, DocListCast, Field, Opt } from '../../../fields/Doc';
-import { Height, Width } from '../../../fields/DocSymbols';
import { Id } from '../../../fields/FieldSymbols';
import { HtmlField } from '../../../fields/HtmlField';
import { InkTool } from '../../../fields/InkField';
import { List } from '../../../fields/List';
import { RefField } from '../../../fields/RefField';
import { listSpec } from '../../../fields/Schema';
-import { Cast, ImageCast, NumCast, StrCast, WebCast } from '../../../fields/Types';
+import { Cast, NumCast, StrCast, WebCast } from '../../../fields/Types';
import { ImageField, WebField } from '../../../fields/URLField';
import { TraceMobx } from '../../../fields/util';
import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, emptyFunction, getWordAtPoint, lightOrDark, returnFalse, returnOne, returnZero, setupMoveUpEvents, smoothScroll, Utils } from '../../../Utils';
import { Docs, DocUtils } from '../../documents/Documents';
import { DocumentManager } from '../../util/DocumentManager';
-import { DragManager } from '../../util/DragManager';
import { ScriptingGlobals } from '../../util/ScriptingGlobals';
import { SnappingManager } from '../../util/SnappingManager';
import { undoBatch, UndoManager } from '../../util/UndoManager';
@@ -24,7 +24,7 @@ import { MarqueeOptionsMenu } from '../collections/collectionFreeForm';
import { CollectionFreeFormView } from '../collections/collectionFreeForm/CollectionFreeFormView';
import { ContextMenu } from '../ContextMenu';
import { ContextMenuProps } from '../ContextMenuItem';
-import { ViewBoxAnnotatableComponent, ViewBoxAnnotatableProps } from '../DocComponent';
+import { ViewBoxAnnotatableComponent, ViewBoxInterface } from '../DocComponent';
import { Colors } from '../global/globalEnums';
import { LightboxView } from '../LightboxView';
import { MarqueeAnnotator } from '../MarqueeAnnotator';
@@ -33,17 +33,15 @@ import { Annotation } from '../pdf/Annotation';
import { GPTPopup } from '../pdf/GPTPopup/GPTPopup';
import { SidebarAnnos } from '../SidebarAnnos';
import { StyleProp } from '../StyleProvider';
-import { DocComponentView, DocFocusOptions, DocumentView, DocumentViewProps, OpenWhere } from './DocumentView';
-import { FieldView, FieldViewProps } from './FieldView';
-import { LinkDocPreview } from './LinkDocPreview';
+import { DocumentView, OpenWhere } from './DocumentView';
+import { FocusViewOptions, FieldView, FieldViewProps } from './FieldView';
+import { LinkInfo } from './LinkDocPreview';
import { PinProps, PresBox } from './trails';
import './WebBox.scss';
-import React = require('react');
const { CreateImage } = require('./WebBoxRenderer');
const _global = (window /* browser */ || global) /* node */ as any;
-const htmlToText = require('html-to-text');
@observer
-export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps & FieldViewProps>() {
+export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implements ViewBoxInterface {
public static LayoutString(fieldKey: string) {
return FieldView.LayoutString(WebBox, fieldKey);
}
@@ -51,9 +49,9 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
public static sidebarResizerWidth = 5;
static webStyleSheet = addStyleSheet();
private _setPreviewCursor: undefined | ((x: number, y: number, drag: boolean, hide: boolean, doc: Opt<Doc>) => void);
- private _setBrushViewer: undefined | ((view: { width: number; height: number; panX: number; panY: number }, transTime: number) => void);
private _mainCont: React.RefObject<HTMLDivElement> = React.createRef();
private _outerRef: React.RefObject<HTMLDivElement> = React.createRef();
+ private _marqueeref = React.createRef<MarqueeAnnotator>();
private _disposers: { [name: string]: IReactionDisposer } = {};
private _annotationLayer: React.RefObject<HTMLDivElement> = React.createRef();
private _keyInput = React.createRef<HTMLInputElement>();
@@ -69,10 +67,15 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
@observable private _searching: boolean = false;
@observable private _showSidebar = false;
@observable private _webPageHasBeenRendered = false;
- @observable private _overlayAnnoInfo: Opt<Doc>;
- @observable private _marqueeing: number[] | undefined;
- @observable private _isAnnotating = false;
- @observable private _iframeClick: HTMLIFrameElement | undefined = undefined;
+ @observable private _marqueeing: number[] | undefined = undefined;
+ get marqueeing() {
+ return this._marqueeing;
+ }
+ set marqueeing(val) {
+ val && this._marqueeref.current?.onInitiateSelection(val);
+ !val && this._marqueeref.current?.onTerminateSelection();
+ this._marqueeing = val;
+ }
@observable private _iframe: HTMLIFrameElement | null = null;
@observable private _savedAnnotations = new ObservableMap<number, HTMLDivElement[]>();
@observable private _scrollHeight = NumCast(this.layoutDoc.scrollHeight);
@@ -83,7 +86,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
return this._url ? WebBox.urlHash(this._url) + '' : '';
}
@computed get scrollHeight() {
- return Math.max(this.layoutDoc[Height](), this._scrollHeight);
+ return Math.max(NumCast(this.layoutDoc._height), this._scrollHeight);
}
@computed get allAnnotations() {
return DocListCast(this.dataDoc[this.annotationKey]);
@@ -92,12 +95,13 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
return this.allAnnotations.filter(a => a.text_inlineAnnotations);
}
@computed get webField() {
- return Cast(this.rootDoc[this.props.fieldKey], WebField)?.url;
+ return Cast(this.Document[this._props.fieldKey], WebField)?.url;
}
- constructor(props: any) {
+ constructor(props: FieldViewProps) {
super(props);
- runInAction(() => (this._webUrl = this._url)); // setting the weburl will change the src parameter of the embedded iframe and force a navigation to it.
+ makeObservable(this);
+ this._webUrl = this._url; // setting the weburl will change the src parameter of the embedded iframe and force a navigation to it.
}
@action
@@ -136,13 +140,13 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
if (!this._iframe) return;
const scrollTop = NumCast(this.layoutDoc._layout_scrollTop);
const nativeWidth = NumCast(this.layoutDoc.nativeWidth);
- const nativeHeight = (nativeWidth * this.props.PanelHeight()) / this.props.PanelWidth();
+ const nativeHeight = (nativeWidth * this._props.PanelHeight()) / this._props.PanelWidth();
var htmlString = this._iframe.contentDocument && new XMLSerializer().serializeToString(this._iframe.contentDocument);
if (!htmlString) {
htmlString = await (await fetch(Utils.CorsProxy(this.webField!.href))).text();
}
this.layoutDoc.thumb = undefined;
- this.rootDoc.thumbLockout = true; // lock to prevent multiple thumb updates.
+ this.Document.thumbLockout = true; // lock to prevent multiple thumb updates.
CreateImage(this._webUrl.endsWith('/') ? this._webUrl.substring(0, this._webUrl.length - 1) : this._webUrl, this._iframe.contentDocument?.styleSheets ?? [], htmlString, nativeWidth, nativeHeight, scrollTop)
.then((data_url: any) => {
if (data_url.includes('<!DOCTYPE')) {
@@ -152,7 +156,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
Utils.convertDataUri(data_url, this.layoutDoc[Id] + '-icon' + new Date().getTime(), true, this.layoutDoc[Id] + '-icon').then(returnedfilename =>
setTimeout(
action(() => {
- this.rootDoc.thumbLockout = false;
+ this.Document.thumbLockout = false;
this.layoutDoc.thumb = new ImageField(returnedfilename);
this.layoutDoc.thumbScrollTop = scrollTop;
this.layoutDoc.thumbNativeWidth = nativeWidth;
@@ -167,8 +171,8 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
});
};
- async componentDidMount() {
- this.props.setContentView?.(this); // this tells the DocumentView that this WebBox is the "content" of the document. this allows the DocumentView to call WebBox relevant methods to configure the UI (eg, show back/forward buttons)
+ componentDidMount() {
+ this._props.setContentViewBox?.(this); // this tells the DocumentView that this WebBox is the "content" of the document. this allows the DocumentView to call WebBox relevant methods to configure the UI (eg, show back/forward buttons)
runInAction(() => {
this._annotationKeySuffix = () => (this._urlHash ? this._urlHash + '_' : '') + 'annotations';
@@ -182,11 +186,11 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
}
});
this._disposers.urlchange = reaction(
- () => WebCast(this.rootDoc.data),
+ () => WebCast(this.dataDoc.data),
url => this.submitURL(false, false)
);
this._disposers.titling = reaction(
- () => StrCast(this.rootDoc.title),
+ () => StrCast(this.Document.title),
url => {
url.startsWith('www') && this.setData('http://' + url);
url.startsWith('http') && this.setData(url);
@@ -197,8 +201,8 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
() => this.layoutDoc._layout_autoHeight,
layout_autoHeight => {
if (layout_autoHeight) {
- this.layoutDoc._nativeHeight = NumCast(this.props.Document[this.props.fieldKey + '_nativeHeight']);
- this.props.setHeight?.(NumCast(this.props.Document[this.props.fieldKey + '_nativeHeight']) * (this.props.NativeDimScaling?.() || 1));
+ this.layoutDoc._nativeHeight = NumCast(this.Document[this._props.fieldKey + '_nativeHeight']);
+ this._props.setHeight?.(NumCast(this.Document[this._props.fieldKey + '_nativeHeight']) * (this._props.NativeDimScaling?.() || 1));
}
}
);
@@ -211,14 +215,12 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
if (!nativeWidth || !nativeHeight || Math.abs(nativeWidth / nativeHeight - youtubeaspect) > 0.05) {
if (!nativeWidth) Doc.SetNativeWidth(this.layoutDoc, 600);
Doc.SetNativeHeight(this.layoutDoc, (nativeWidth || 600) / youtubeaspect);
- this.layoutDoc._height = this.layoutDoc[Width]() / youtubeaspect;
+ this.layoutDoc._height = NumCast(this.layoutDoc._width) / youtubeaspect;
}
} // else it's an HTMLfield
} else if (this.webField && !this.dataDoc.text) {
- const result = await WebRequest.get(Utils.CorsProxy(this.webField.href));
- if (result) {
- this.dataDoc.text = htmlToText.fromString(result.content);
- }
+ WebRequest.get(Utils.CorsProxy(this.webField.href)) //
+ .then(result => result && (this.dataDoc.text = htmlToText(result.content)));
}
this._disposers.scrollReaction = reaction(
@@ -233,7 +235,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
{ fireImmediately: true }
);
}
- @action componentWillUnmount() {
+ componentWillUnmount() {
this._iframetimeout && clearTimeout(this._iframetimeout);
this._iframetimeout = undefined;
Object.values(this._disposers).forEach(disposer => disposer?.());
@@ -248,6 +250,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
@action
createTextAnnotation = (sel: Selection, selRange: Range | undefined) => {
if (this._mainCont.current && selRange) {
+ if (this.dataDoc[this._props.fieldKey] instanceof HtmlField) this._mainCont.current.style.transform = `rotate(${NumCast(this.DocumentView!().screenToContentsTransform().RotateDeg)}deg)`;
const clientRects = selRange.getClientRects();
for (let i = 0; i < clientRects.length; i++) {
const rect = clientRects.item(i);
@@ -255,7 +258,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
if (rect && rect.width !== this._mainCont.current.clientWidth) {
const annoBox = document.createElement('div');
annoBox.className = 'marqueeAnnotator-annotationBox';
- const scale = this._url ? 1 : this.props.ScreenToLocalTransform().Scale;
+ const scale = this._url ? 1 : this.ScreenToLocalBoxXf().Scale;
// transforms the positions from screen onto the pdf div
annoBox.style.top = ((rect.top - mainrect.translateY) * scale + (this._url ? this._mainCont.current.scrollTop : NumCast(this.layoutDoc.layout_scrollTop))).toString();
annoBox.style.left = ((rect.left - mainrect.translateX) * scale).toString();
@@ -264,23 +267,23 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
this._annotationLayer.current && MarqueeAnnotator.previewNewAnnotation(this._savedAnnotations, this._annotationLayer.current, annoBox, 1);
}
}
+ this._mainCont.current.style.transform = '';
}
- //this._selectionText = selRange.cloneContents().textContent || "";
this._selectionContent = selRange?.cloneContents();
this._selectionText = this._selectionContent?.textContent || '';
// clear selection
- if (sel.empty) sel.empty(); // Chrome
+ this._textAnnotationCreator = undefined;
+ if (sel.empty)
+ sel.empty(); // Chrome
else if (sel.removeAllRanges) sel.removeAllRanges(); // Firefox
return this._savedAnnotations;
};
- setBrushViewer = (func?: (view: { width: number; height: number; panX: number; panY: number }, transTime: number) => void) => (this._setBrushViewer = func);
- brushView = (view: { width: number; height: number; panX: number; panY: number }, transTime: number) => this._setBrushViewer?.(view, transTime);
- focus = (anchor: Doc, options: DocFocusOptions) => {
- if (anchor !== this.rootDoc && this._outerRef.current) {
- const windowHeight = this.props.PanelHeight() / (this.props.NativeDimScaling?.() || 1);
- const scrollTo = Utils.scrollIntoView(NumCast(anchor.y), anchor[Height](), NumCast(this.layoutDoc._layout_scrollTop), windowHeight, windowHeight * 0.1, Math.max(NumCast(anchor.y) + anchor[Height](), this._scrollHeight));
+ focus = (anchor: Doc, options: FocusViewOptions) => {
+ if (anchor !== this.Document && this._outerRef.current) {
+ const windowHeight = this._props.PanelHeight() / (this._props.NativeDimScaling?.() || 1);
+ const scrollTo = Utils.scrollIntoView(NumCast(anchor.y), NumCast(anchor._height), NumCast(this.layoutDoc._layout_scrollTop), windowHeight, windowHeight * 0.1, Math.max(NumCast(anchor.y) + NumCast(anchor._height), this._scrollHeight));
if (scrollTo !== undefined) {
if (this._initialScroll === undefined) {
const focusTime = options.zoomTime ?? 500;
@@ -294,9 +297,9 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
};
@action
- getView = (doc: Doc) => {
- if (Doc.AreProtosEqual(doc, this.rootDoc)) return new Promise<Opt<DocumentView>>(res => res(this.props.DocumentView?.()));
- if (this.rootDoc.layout_fieldKey === 'layout_icon') this.props.DocumentView?.().iconify();
+ getView = (doc: Doc, options: FocusViewOptions) => {
+ if (Doc.AreProtosEqual(doc, this.Document)) return new Promise<Opt<DocumentView>>(res => res(this.DocumentView?.()));
+ if (this.Document.layout_fieldKey === 'layout_icon') this.DocumentView?.().iconify();
const webUrl = WebCast(doc.config_data)?.url;
if (this._url && webUrl && webUrl.href !== this._url) this.setData(webUrl.href);
if (this._sidebarRef?.current?.makeDocUnfiltered(doc) && !this.SidebarShown) this.toggleSidebar(false);
@@ -304,11 +307,11 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
};
sidebarAddDocTab = (doc: Doc, where: OpenWhere) => {
- if (DocListCast(this.props.Document[this.props.fieldKey + '_sidebar']).includes(doc) && !this.SidebarShown) {
+ if (DocListCast(this.Document[this._props.fieldKey + '_sidebar']).includes(doc) && !this.SidebarShown) {
this.toggleSidebar(false);
return true;
}
- return this.props.addDocTab(doc, where);
+ return this._props.addDocTab(doc, where);
};
getAnchor = (addAsAnnotation: boolean, pinProps?: PinProps) => {
let ele: Opt<HTMLDivElement> = undefined;
@@ -319,15 +322,15 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
ele.append(contents);
}
} catch (e) {}
- const visibleAnchor = this._getAnchor(this._savedAnnotations, false);
+ const visibleAnchor = this._getAnchor(this._savedAnnotations, true);
const anchor =
visibleAnchor ??
Docs.Create.ConfigDocument({
- title: StrCast(this.rootDoc.title + ' ' + this.layoutDoc._layout_scrollTop),
+ title: StrCast(this.Document.title + ' ' + this.layoutDoc._layout_scrollTop),
y: NumCast(this.layoutDoc._layout_scrollTop),
- annotationOn: this.rootDoc,
+ annotationOn: this.Document,
});
- PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), scrollable: pinProps?.pinData ? true : false, pannable: true } }, this.rootDoc);
+ PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), scrollable: pinProps?.pinData ? true : false, pannable: true } }, this.Document);
anchor.text = ele?.textContent ?? '';
anchor.text_html = ele?.innerHTML ?? this._selectionText;
addAsAnnotation && this.addDocumentWrapper(anchor);
@@ -339,11 +342,12 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
@action
iframeUp = (e: PointerEvent) => {
+ this._getAnchor = AnchorMenu.Instance?.GetAnchor; // need to save AnchorMenu's getAnchor since a subsequent selection on another doc will overwrite this value
this._textAnnotationCreator = undefined;
- this.props.docViewPath().lastElement()?.docView?.cleanupPointerEvents(); // pointerup events aren't generated on containing document view, so we have to invoke it here.
+ this.DocumentView?.()?.cleanupPointerEvents(); // pointerup events aren't generated on containing document view, so we have to invoke it here.
if (this._iframe?.contentWindow && this._iframe.contentDocument && !this._iframe.contentWindow.getSelection()?.isCollapsed) {
const mainContBounds = Utils.GetScreenTransform(this._mainCont.current!);
- const scale = (this.props.NativeDimScaling?.() || 1) * mainContBounds.scale;
+ const scale = (this._props.NativeDimScaling?.() || 1) * mainContBounds.scale;
const sel = this._iframe.contentWindow.getSelection();
if (sel) {
this._selectionText = sel.toString();
@@ -351,33 +355,35 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
this._textAnnotationCreator = () => this.createTextAnnotation(sel, !sel.isCollapsed ? sel.getRangeAt(0) : undefined);
AnchorMenu.Instance.jumpTo(e.clientX * scale + mainContBounds.translateX, e.clientY * scale + mainContBounds.translateY - NumCast(this.layoutDoc._layout_scrollTop) * scale);
// Changing which document to add the annotation to (the currently selected WebBox)
- GPTPopup.Instance.setSidebarId(`${this.props.fieldKey}_${this._urlHash ? this._urlHash + '_' : ''}sidebar`);
+ GPTPopup.Instance.setSidebarId(`${this._props.fieldKey}_${this._urlHash ? this._urlHash + '_' : ''}sidebar`);
GPTPopup.Instance.addDoc = this.sidebarAddDocument;
}
}
};
@action
webClipDown = (e: React.PointerEvent) => {
- const mainContBounds = Utils.GetScreenTransform(this._mainCont.current!);
+ e.stopPropagation();
+ const sel = window.getSelection();
+ this._textAnnotationCreator = undefined;
+ if (sel?.empty)
+ sel.empty(); // Chrome
+ else if (sel?.removeAllRanges) sel.removeAllRanges(); // Firefox
+ // bcz: NEED TO unrotate e.clientX and e.clientY
const word = getWordAtPoint(e.target, e.clientX, e.clientY);
- this._setPreviewCursor?.(e.clientX, e.clientY, false, true, this.rootDoc);
+ this._setPreviewCursor?.(e.clientX, e.clientY, false, true, this.Document);
MarqueeAnnotator.clearAnnotations(this._savedAnnotations);
- e.button !== 2 && (this._marqueeing = [e.clientX, e.clientY]);
- if (word || (e.target as any)?.className?.includes('rangeslider') || (e.target as any)?.onclick || (e.target as any)?.parentNode?.onclick) {
- e.stopPropagation();
- setTimeout(
- action(() => (this._marqueeing = undefined)),
- 100
- ); // bcz: hack .. anchor menu is setup within MarqueeAnnotator so we need to at least create the marqueeAnnotator even though we aren't using it.
- } else {
- this._isAnnotating = true;
- this.props.select(false);
- e.stopPropagation();
+
+ if (!word && !(e.target as any)?.className?.includes('rangeslider') && !(e.target as any)?.onclick && !(e.target as any)?.parentNode?.onclick) {
+ if (e.button !== 2) this.marqueeing = [e.clientX, e.clientY];
e.preventDefault();
}
document.addEventListener('pointerup', this.webClipUp);
};
+ @action
webClipUp = (e: PointerEvent) => {
+ if (window.getSelection()?.isCollapsed && this._marqueeref.current?.isEmpty) {
+ this.marqueeing = undefined;
+ }
document.removeEventListener('pointerup', this.webClipUp);
this._getAnchor = AnchorMenu.Instance?.GetAnchor; // need to save AnchorMenu's getAnchor since a subsequent selection on another doc will overwrite this value
const sel = window.getSelection();
@@ -386,44 +392,27 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
this._selectionText = sel.toString();
AnchorMenu.Instance.setSelectedText(sel.toString());
this._textAnnotationCreator = () => this.createTextAnnotation(sel, selRange);
- AnchorMenu.Instance.jumpTo(e.clientX, e.clientY);
+ (!sel.isCollapsed || this.marqueeing) && AnchorMenu.Instance.jumpTo(e.clientX, e.clientY);
// Changing which document to add the annotation to (the currently selected WebBox)
- GPTPopup.Instance.setSidebarId(`${this.props.fieldKey}_${this._urlHash ? this._urlHash + '_' : ''}sidebar`);
+ GPTPopup.Instance.setSidebarId(`${this._props.fieldKey}_${this._urlHash ? this._urlHash + '_' : ''}sidebar`);
GPTPopup.Instance.addDoc = this.sidebarAddDocument;
}
};
@action
iframeDown = (e: PointerEvent) => {
- const mainContBounds = Utils.GetScreenTransform(this._mainCont.current!);
- const scale = (this.props.NativeDimScaling?.() || 1) * mainContBounds.scale;
- const word = getWordAtPoint(e.target, e.clientX, e.clientY);
- this._setPreviewCursor?.(e.clientX, e.clientY, false, true, this.rootDoc);
+ this._props.select(false);
+ const theclick = this.props
+ .ScreenToLocalTransform()
+ .inverse()
+ .transformPoint(e.clientX, e.clientY - NumCast(this.layoutDoc.layout_scrollTop));
MarqueeAnnotator.clearAnnotations(this._savedAnnotations);
- e.button !== 2 && (this._marqueeing = [e.clientX * scale + mainContBounds.translateX, e.clientY * scale + mainContBounds.translateY - NumCast(this.layoutDoc._layout_scrollTop) * scale]);
- if (word || (e.target as any)?.className?.includes('rangeslider') || (e.target as any)?.onclick || (e.target as any)?.parentNode?.onclick) {
- setTimeout(
- action(() => (this._marqueeing = undefined)),
- 100
- ); // bcz: hack .. anchor menu is setup within MarqueeAnnotator so we need to at least create the marqueeAnnotator even though we aren't using it.
- } else {
- this._iframeClick = this._iframe ?? undefined;
- this._isAnnotating = true;
- this.props.select(false);
- e.stopPropagation();
+ const word = getWordAtPoint(e.target, e.clientX, e.clientY);
+ if (!word && !(e.target as any)?.className?.includes('rangeslider') && !(e.target as any)?.onclick && !(e.target as any)?.parentNode?.onclick) {
+ this.marqueeing = theclick;
e.preventDefault();
}
-
- // bcz: hack - iframe grabs all events which messes up how we handle contextMenus. So this super naively simulates the event stack to get the specific menu items and the doc view menu items.
- if (e.button === 2 || (e.button === 0 && e.altKey)) {
- e.preventDefault();
- //e.stopPropagation();
- ContextMenu.Instance.closeMenu();
- ContextMenu.Instance.setIgnoreEvents(true);
- }
};
isFirefox = () => 'InstallTrigger' in window; // navigator.userAgent.indexOf("Chrome") !== -1;
- iframeClick = () => this._iframeClick;
- iframeScaling = () => 1 / this.props.ScreenToLocalTransform().Scale;
addWebStyleSheet(document: any, styleType: string = 'text/css') {
if (document) {
@@ -493,16 +482,16 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
const initHeights = () => {
this._scrollHeight = Math.max(this._scrollHeight, iframeContent.body.scrollHeight || 0);
if (this._scrollHeight) {
- this.rootDoc.nativeHeight = Math.min(NumCast(this.rootDoc.nativeHeight), this._scrollHeight);
- this.layoutDoc.height = Math.min(this.layoutDoc[Height](), (this.layoutDoc[Width]() * NumCast(this.rootDoc.nativeHeight)) / NumCast(this.rootDoc.nativeWidth));
+ this.Document.nativeHeight = Math.min(NumCast(this.Document.nativeHeight), this._scrollHeight);
+ this.layoutDoc.height = Math.min(NumCast(this.layoutDoc._height), (NumCast(this.layoutDoc._width) * NumCast(this.Document.nativeHeight)) / NumCast(this.Document.nativeWidth));
}
};
- const swidth = Math.max(NumCast(this.layoutDoc.nativeWidth), iframeContent.body.scrollWidth || 0);
+ const swidth = Math.max(NumCast(this.Document.nativeWidth), iframeContent.body.scrollWidth || 0);
if (swidth) {
- const aspectResize = swidth / NumCast(this.rootDoc.nativeWidth);
- this.rootDoc.nativeWidth = swidth;
- this.rootDoc.nativeHeight = NumCast(this.rootDoc.nativeHeight) * aspectResize;
- this.layoutDoc.height = this.layoutDoc[Height]() * aspectResize;
+ const aspectResize = swidth / NumCast(this.Document.nativeWidth, swidth);
+ this.layoutDoc.height = NumCast(this.layoutDoc._height) * aspectResize;
+ this.Document.nativeWidth = swidth;
+ this.Document.nativeHeight = (swidth * NumCast(this.layoutDoc._height)) / NumCast(this.layoutDoc._width);
}
initHeights();
this._iframetimeout && clearTimeout(this._iframetimeout);
@@ -569,7 +558,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
clearStyleSheetRules(WebBox.webStyleSheet);
this._scrollTimer = undefined;
const newScrollTop = scrollTop > iframeHeight ? iframeHeight : scrollTop;
- if (!LinkDocPreview.LinkInfo && this._outerRef.current && newScrollTop !== this.layoutDoc.thumbScrollTop && (!LightboxView.LightboxDoc || LightboxView.IsLightboxDocView(this.props.docViewPath()))) {
+ if (!LinkInfo.Instance?.LinkInfo && this._outerRef.current && newScrollTop !== this.layoutDoc.thumbScrollTop && (!LightboxView.LightboxDoc || LightboxView.Contains(this.DocumentView?.()))) {
this.layoutDoc.thumb = undefined;
this.layoutDoc.thumbScrollTop = undefined;
this.layoutDoc.thumbNativeWidth = undefined;
@@ -591,8 +580,8 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
};
forward = (checkAvailable?: boolean) => {
- const future = Cast(this.rootDoc[this.fieldKey + '_future'], listSpec('string'), []);
- const history = Cast(this.rootDoc[this.fieldKey + '_history'], listSpec('string'), []);
+ const future = Cast(this.dataDoc[this.fieldKey + '_future'], listSpec('string'), []);
+ const history = Cast(this.dataDoc[this.fieldKey + '_history'], listSpec('string'), []);
if (checkAvailable) return future.length;
runInAction(() => {
if (future.length) {
@@ -613,8 +602,8 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
};
back = (checkAvailable?: boolean) => {
- const future = Cast(this.rootDoc[this.fieldKey + '_future'], listSpec('string'));
- const history = Cast(this.rootDoc[this.fieldKey + '_history'], listSpec('string'), []);
+ const future = Cast(this.dataDoc[this.fieldKey + '_future'], listSpec('string'));
+ const history = Cast(this.dataDoc[this.fieldKey + '_history'], listSpec('string'), []);
if (checkAvailable) return history.length;
runInAction(() => {
if (history.length) {
@@ -682,7 +671,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
if (Field.toString(data) === this._url) return false;
this._scrollHeight = 0;
const oldUrl = this._url;
- const history = Cast(this.rootDoc[this.fieldKey + '_history'], listSpec('string'), []);
+ const history = Cast(this.dataDoc[this.fieldKey + '_history'], listSpec('string'), []);
const weburl = new WebField(Field.toString(data));
this.dataDoc[this.fieldKey + '_future'] = new List<string>([]);
this.dataDoc[this.fieldKey + '_history'] = new List<string>([...(history || []), oldUrl]);
@@ -712,10 +701,10 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
icon: 'snowflake',
});
funcs.push({
- description: (!this.layoutDoc.layout_forceReflow ? 'Force' : 'Prevent') + ' Reflow',
+ description: (!this.layoutDoc.layout_reflowHorizontal ? 'Force' : 'Prevent') + ' Reflow',
event: () => {
- const nw = !this.layoutDoc.layout_forceReflow ? undefined : Doc.NativeWidth(this.layoutDoc) - this.sidebarWidth() / (this.props.NativeDimScaling?.() || 1);
- this.layoutDoc.layout_forceReflow = !nw;
+ const nw = !this.layoutDoc.layout_reflowHorizontal ? undefined : Doc.NativeWidth(this.layoutDoc) - this.sidebarWidth() / (this._props.NativeDimScaling?.() || 1);
+ this.layoutDoc.layout_reflowHorizontal = !nw;
if (nw) {
Doc.SetInPlace(this.layoutDoc, this.fieldKey + '_nativeWidth', nw, true);
}
@@ -727,38 +716,58 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
}
};
+ /**
+ * This gets called when some other child of the webbox is selected and a pointer down occurs on the webbox.
+ * it's also called for html clippings when you click outside the bounds of the clipping
+ * @param e
+ */
@action
onMarqueeDown = (e: React.PointerEvent) => {
- if (!e.altKey && e.button === 0 && this.props.isContentActive(true) && ![InkTool.Highlighter, InkTool.Pen, InkTool.Write].includes(Doc.ActiveTool)) {
+ const sel = this._url ? this._iframe?.contentDocument?.getSelection() : window.document.getSelection();
+ this._textAnnotationCreator = undefined;
+ if (sel?.empty)
+ sel.empty(); // Chrome
+ else if (sel?.removeAllRanges) sel.removeAllRanges(); // Firefox
+ this.marqueeing = [e.clientX, e.clientY];
+ if (!e.altKey && e.button === 0 && this._props.isContentActive() && ![InkTool.Highlighter, InkTool.Pen, InkTool.Write].includes(Doc.ActiveTool)) {
setupMoveUpEvents(
this,
e,
action(e => {
MarqueeAnnotator.clearAnnotations(this._savedAnnotations);
- this._marqueeing = [e.clientX, e.clientY];
return true;
}),
returnFalse,
- () => MarqueeAnnotator.clearAnnotations(this._savedAnnotations),
+ action(() => {
+ this.marqueeing = undefined;
+ MarqueeAnnotator.clearAnnotations(this._savedAnnotations);
+ }),
false
);
+ } else {
+ this.marqueeing = undefined;
}
};
@action finishMarquee = (x?: number, y?: number, e?: PointerEvent) => {
this._getAnchor = AnchorMenu.Instance?.GetAnchor;
- this._marqueeing = undefined;
- this._isAnnotating = false;
- this._iframeClick = undefined;
+ this.marqueeing = undefined;
+ this._textAnnotationCreator = undefined;
const sel = this._url ? this._iframe?.contentDocument?.getSelection() : window.document.getSelection();
- if (sel?.empty) sel.empty(); // Chrome
+ if (sel?.empty)
+ sel.empty(); // Chrome
else if (sel?.removeAllRanges) sel.removeAllRanges(); // Firefox
+ this._setPreviewCursor?.(x ?? 0, y ?? 0, false, !this._marqueeref.current?.isEmpty, this.Document);
if (x !== undefined && y !== undefined) {
- this._setPreviewCursor?.(x, y, false, false, this.rootDoc);
ContextMenu.Instance.closeMenu();
ContextMenu.Instance.setIgnoreEvents(false);
if (e?.button === 2 || e?.altKey) {
- this.specificContextMenu(undefined as any);
- this.props.docViewPath().lastElement().docView?.onContextMenu(undefined, x, y);
+ e?.preventDefault();
+ e?.stopPropagation();
+ setTimeout(() => {
+ // if menu comes up right away, the down event can still be active causing a menu item to be selected
+ this.specificContextMenu(undefined as any);
+ this.DocumentView?.().onContextMenu(undefined, x, y);
+ });
}
}
};
@@ -766,6 +775,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
@observable lighttext = false;
@computed get urlContent() {
+ if (this.ScreenToLocalBoxXf().Scale > 25) return <div></div>;
setTimeout(
action(() => {
if (this._initialScroll === undefined && !this._webPageHasBeenRendered) {
@@ -774,7 +784,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
this._webPageHasBeenRendered = true;
})
);
- const field = this.rootDoc[this.props.fieldKey];
+ const field = this.dataDoc[this._props.fieldKey];
if (field instanceof HtmlField) {
return (
<span
@@ -800,7 +810,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
key={this._warning}
className="webBox-iframe"
ref={action((r: HTMLIFrameElement | null) => (this._iframe = r))}
- style={{ pointerEvents: this._isAnyChildContentActive || DocumentView.Interacting ? 'none' : undefined }}
+ style={{ pointerEvents: SnappingManager.IsResizing ? 'none' : undefined }}
src={url}
onLoad={this.iframeLoaded}
scrolling="no" // ugh.. on windows, I get an inner scroll bar for the iframe's body even though the scrollHeight should be set to the full height of the document.
@@ -831,18 +841,18 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
e,
action((e, down, delta) => {
this._draggingSidebar = true;
- const localDelta = this.props
+ const localDelta = this._props
.ScreenToLocalTransform()
- .scale(this.props.NativeDimScaling?.() || 1)
+ .scale(this._props.NativeDimScaling?.() || 1)
.transformDirection(delta[0], delta[1]);
const nativeWidth = NumCast(this.layoutDoc[this.fieldKey + '_nativeWidth']);
const nativeHeight = NumCast(this.layoutDoc[this.fieldKey + '_nativeHeight']);
const curNativeWidth = NumCast(this.layoutDoc.nativeWidth, nativeWidth);
- const ratio = (curNativeWidth + ((onButton ? 1 : -1) * localDelta[0]) / (this.props.NativeDimScaling?.() || 1)) / nativeWidth;
+ const ratio = (curNativeWidth + ((onButton ? 1 : -1) * localDelta[0]) / (this._props.NativeDimScaling?.() || 1)) / nativeWidth;
if (ratio >= 1) {
this.layoutDoc.nativeWidth = nativeWidth * ratio;
this.layoutDoc.nativeHeight = nativeHeight * (1 + ratio);
- onButton && (this.layoutDoc._width = this.layoutDoc[Width]() + localDelta[0]);
+ onButton && (this.layoutDoc._width = NumCast(this.layoutDoc._width) + localDelta[0]);
this.layoutDoc._layout_showSidebar = nativeWidth !== this.layoutDoc._nativeWidth;
}
return false;
@@ -864,7 +874,6 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
key="sidebar"
title="Toggle Sidebar"
style={{
- display: !this.props.isContentActive() ? 'none' : undefined,
top: StrCast(this.layoutDoc._layout_showTitle) === 'title' ? 20 : 5,
backgroundColor: this.SidebarShown ? Colors.MEDIUM_BLUE : Colors.BLACK,
}}
@@ -878,31 +887,32 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
toggleSidebar = action((preview: boolean = false) => {
var nativeWidth = NumCast(this.layoutDoc[this.fieldKey + '_nativeWidth']);
if (!nativeWidth) {
- const defaultNativeWidth = this.rootDoc[this.fieldKey] instanceof WebField ? 850 : this.Document[Width]();
+ const defaultNativeWidth = NumCast(this.Document.nativeWidth, this.dataDoc[this.fieldKey] instanceof WebField ? 850 : NumCast(this.Document._width));
Doc.SetNativeWidth(this.dataDoc, Doc.NativeWidth(this.dataDoc) || defaultNativeWidth);
- Doc.SetNativeHeight(this.dataDoc, Doc.NativeHeight(this.dataDoc) || (this.Document[Height]() / this.Document[Width]()) * defaultNativeWidth);
+ Doc.SetNativeHeight(this.dataDoc, Doc.NativeHeight(this.dataDoc) || (NumCast(this.Document._height) / NumCast(this.Document._width)) * defaultNativeWidth);
nativeWidth = NumCast(this.layoutDoc[this.fieldKey + '_nativeWidth']);
}
const sideratio = ((!this.layoutDoc.nativeWidth || this.layoutDoc.nativeWidth === nativeWidth ? WebBox.openSidebarWidth : 0) + nativeWidth) / nativeWidth;
- const pdfratio = ((!this.layoutDoc.nativeWidth || this.layoutDoc.nativeWidth === nativeWidth ? WebBox.openSidebarWidth + WebBox.sidebarResizerWidth : 0) + nativeWidth) / nativeWidth;
+ const pdfratio = ((!this.layoutDoc.nativeWidth || this.layoutDoc.nativeWidth === nativeWidth ? WebBox.openSidebarWidth + WebBox.sidebarResizerWidth : 0) + NumCast(this.layoutDoc.width)) / NumCast(this.layoutDoc.width);
const curNativeWidth = NumCast(this.layoutDoc.nativeWidth, nativeWidth);
if (preview) {
this._previewNativeWidth = nativeWidth * sideratio;
- this._previewWidth = (this.layoutDoc[Width]() * nativeWidth * sideratio) / curNativeWidth;
+ this._previewWidth = (NumCast(this.layoutDoc._width) * nativeWidth * sideratio) / curNativeWidth;
this._showSidebar = true;
} else {
this.layoutDoc._layout_showSidebar = !this.layoutDoc._layout_showSidebar;
- this.layoutDoc._width = (this.layoutDoc[Width]() * nativeWidth * pdfratio) / curNativeWidth;
+ this.layoutDoc._width = (NumCast(this.layoutDoc._width) * nativeWidth * pdfratio) / curNativeWidth;
if (!this.layoutDoc._layout_showSidebar && !(this.dataDoc[this.fieldKey] instanceof WebField)) {
this.layoutDoc.nativeWidth = this.dataDoc[this.fieldKey + '_nativeWidth'] = undefined;
} else {
+ !this.layoutDoc._layout_showSidebar && (this.dataDoc[this.fieldKey + '_nativeWidth'] = this.dataDoc[this.fieldKey + '_nativeHeight'] = undefined);
this.layoutDoc.nativeWidth = nativeWidth * pdfratio;
}
}
});
@action
onZoomWheel = (e: React.WheelEvent) => {
- if (this.props.isContentActive(true)) {
+ if (this._props.isContentActive()) {
e.stopPropagation();
}
};
@@ -910,20 +920,20 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
if (!this.SidebarShown) return 0;
if (this._previewWidth) return WebBox.sidebarResizerWidth + WebBox.openSidebarWidth; // return default sidebar if previewing (as in viewing a link target)
const nativeDiff = NumCast(this.layoutDoc.nativeWidth) - Doc.NativeWidth(this.dataDoc);
- return WebBox.sidebarResizerWidth + nativeDiff * (this.props.NativeDimScaling?.() || 1);
+ return WebBox.sidebarResizerWidth + nativeDiff * (this._props.NativeDimScaling?.() || 1);
};
_innerCollectionView: CollectionFreeFormView | undefined;
zoomScaling = () => this._innerCollectionView?.zoomScaling() ?? 1;
- setInnerContent = (component: DocComponentView) => (this._innerCollectionView = component as CollectionFreeFormView);
+ setInnerContent = (component: ViewBoxInterface) => (this._innerCollectionView = component as CollectionFreeFormView);
@computed get content() {
- const interactive = this.props.isContentActive() && this.props.pointerEvents?.() !== 'none' && Doc.ActiveTool === InkTool.None;
+ const interactive = this._props.isContentActive() && this._props.pointerEvents?.() !== 'none' && Doc.ActiveTool === InkTool.None;
return (
<div
className={'webBox-cont' + (interactive ? '-interactive' : '')}
onKeyDown={e => e.stopPropagation()}
style={{
- width: !this.layoutDoc.layout_forceReflow ? NumCast(this.layoutDoc[this.fieldKey + '_nativeWidth']) || `100%` : '100%',
+ width: !this.layoutDoc.layout_reflowHorizontal ? NumCast(this.layoutDoc[this.fieldKey + '_nativeWidth']) || `100%` : '100%',
transform: `scale(${this.zoomScaling()}) translate(${-NumCast(this.layoutDoc.freeform_panX)}px, ${-NumCast(this.layoutDoc.freeform_panY)}px)`,
}}>
{this._hackHide ? null : this.urlContent}
@@ -945,7 +955,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
{this.inlineTextAnnotations
.sort((a, b) => NumCast(a.y) - NumCast(b.y))
.map(anno => (
- <Annotation {...this.props} fieldKey={this.annotationKey} pointerEvents={this.pointerEvents} showInfo={this.showInfo} dataDoc={this.dataDoc} anno={anno} key={`${anno[Id]}-annotation`} />
+ <Annotation {...this._props} fieldKey={this.annotationKey} pointerEvents={this.pointerEvents} dataDoc={this.dataDoc} anno={anno} key={`${anno[Id]}-annotation`} />
))}
</div>
);
@@ -953,43 +963,47 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
@computed get SidebarShown() {
return this._showSidebar || this.layoutDoc._layout_showSidebar ? true : false;
}
+ renderAnnotations = (childFilters: () => string[]) => (
+ <CollectionFreeFormView
+ {...this._props}
+ setContentViewBox={this.setInnerContent}
+ NativeWidth={returnZero}
+ NativeHeight={returnZero}
+ originTopLeft={false}
+ isAnnotationOverlayScrollable={true}
+ renderDepth={this._props.renderDepth + 1}
+ isAnnotationOverlay={true}
+ fieldKey={this.annotationKey}
+ setPreviewCursor={this.setPreviewCursor}
+ PanelWidth={this.panelWidth}
+ PanelHeight={this.panelHeight}
+ ScreenToLocalTransform={this.scrollXf}
+ NativeDimScaling={returnOne}
+ focus={this.focus}
+ childFilters={childFilters}
+ select={emptyFunction}
+ isAnyChildContentActive={returnFalse}
+ styleProvider={this.childStyleProvider}
+ whenChildContentsActiveChanged={this.whenChildContentsActiveChanged}
+ removeDocument={this.removeDocument}
+ moveDocument={this.moveDocument}
+ addDocument={this.addDocumentWrapper}
+ childPointerEvents={this.childPointerEvents}
+ pointerEvents={this.annotationPointerEvents}
+ />
+ );
- childPointerEvents = () => (this.props.isContentActive() ? 'all' : undefined);
+ @computed get renderOpaqueAnnotations() {
+ return this.renderAnnotations(this.opaqueFilter);
+ }
+ @computed get renderTransparentAnnotations() {
+ return this.renderAnnotations(this.transparentFilter);
+ }
+ childPointerEvents = () => (this._props.isContentActive() ? 'all' : undefined);
@computed get webpage() {
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 = (childFilters: () => string[]) => (
- <CollectionFreeFormView
- {...this.props}
- setContentView={this.setInnerContent}
- NativeWidth={returnZero}
- NativeHeight={returnZero}
- originTopLeft={false}
- isAnnotationOverlayScrollable={true}
- renderDepth={this.props.renderDepth + 1}
- isAnnotationOverlay={true}
- fieldKey={this.annotationKey}
- setPreviewCursor={this.setPreviewCursor}
- setBrushViewer={this.setBrushViewer}
- PanelWidth={this.panelWidth}
- PanelHeight={this.panelHeight}
- ScreenToLocalTransform={this.scrollXf}
- NativeDimScaling={returnOne}
- focus={this.focus}
- childFilters={childFilters}
- select={emptyFunction}
- isAnyChildContentActive={returnFalse}
- bringToFront={emptyFunction}
- styleProvider={this.childStyleProvider}
- whenChildContentsActiveChanged={this.whenChildContentsActiveChanged}
- removeDocument={this.removeDocument}
- moveDocument={this.moveDocument}
- addDocument={this.addDocumentWrapper}
- childPointerEvents={this.childPointerEvents}
- pointerEvents={this.annotationPointerEvents}
- />
- );
+ const pointerEvents = this.layoutDoc._lockedPosition ? 'none' : (this._props.pointerEvents?.() as any);
+ const scale = previewScale * (this._props.NativeDimScaling?.() || 1);
return (
<div
className="webBox-outerContent"
@@ -1002,10 +1016,10 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
onWheel={this.onZoomWheel}
onScroll={e => this.setDashScrollTop(this._outerRef.current?.scrollTop || 0)}
onPointerDown={this.onMarqueeDown}>
- <div className="webBox-innerContent" style={{ height: (this._webPageHasBeenRendered && this._scrollHeight) || '100%', pointerEvents }}>
+ <div className="webBox-innerContent" style={{ height: (this._webPageHasBeenRendered && this._scrollHeight > this._props.PanelHeight() && this._scrollHeight) || '100%', pointerEvents }}>
{this.content}
- {<div style={{ display: DragManager.docsBeingDragged.length ? 'none' : undefined, mixBlendMode: 'multiply' }}>{renderAnnotations(this.transparentFilter)}</div>}
- {renderAnnotations(this.opaqueFilter)}
+ <div style={{ display: SnappingManager.CanEmbed ? 'none' : undefined, mixBlendMode: 'multiply' }}>{this.renderTransparentAnnotations}</div>
+ {this.renderOpaqueAnnotations}
{this.annotationLayer}
</div>
</div>
@@ -1014,7 +1028,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
@computed get searchUI() {
return (
- <div className="webBox-ui" onPointerDown={e => e.stopPropagation()} style={{ display: this.props.isContentActive() ? 'flex' : 'none' }}>
+ <div className="webBox-ui" onPointerDown={e => e.stopPropagation()} style={{ display: this._props.isContentActive() ? 'flex' : 'none' }}>
<div className="webBox-overlayCont" onPointerDown={e => e.stopPropagation()} style={{ left: `${this._searching ? 0 : 100}%` }}>
<button className="webBox-overlayButton" title={'search'} />
<input
@@ -1047,38 +1061,37 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
);
}
searchStringChanged = (e: React.ChangeEvent<HTMLInputElement>) => (this._searchString = e.currentTarget.value);
- showInfo = action((anno: Opt<Doc>) => (this._overlayAnnoInfo = anno));
setPreviewCursor = (func?: (x: number, y: number, drag: boolean, hide: boolean, doc: Opt<Doc>) => void) => (this._setPreviewCursor = func);
- panelWidth = () => this.props.PanelWidth() / (this.props.NativeDimScaling?.() || 1) - this.sidebarWidth() + WebBox.sidebarResizerWidth;
- panelHeight = () => this.props.PanelHeight() / (this.props.NativeDimScaling?.() || 1);
- scrollXf = () => this.props.ScreenToLocalTransform().translate(0, NumCast(this.layoutDoc._layout_scrollTop));
+ panelWidth = () => this._props.PanelWidth() / (this._props.NativeDimScaling?.() || 1) - this.sidebarWidth() + WebBox.sidebarResizerWidth;
+ panelHeight = () => this._props.PanelHeight() / (this._props.NativeDimScaling?.() || 1);
+ scrollXf = () => this.ScreenToLocalBoxXf().translate(0, NumCast(this.layoutDoc._layout_scrollTop));
anchorMenuClick = () => this._sidebarRef.current?.anchorMenuClick;
- transparentFilter = () => [...this.props.childFilters(), Utils.IsTransparentFilter()];
- opaqueFilter = () => [...this.props.childFilters(), Utils.noDragsDocFilter, ...(DragManager.docsBeingDragged.length ? [] : [Utils.IsOpaqueFilter()])];
- childStyleProvider = (doc: Doc | undefined, props: Opt<DocumentViewProps>, property: string): any => {
+ transparentFilter = () => [...this._props.childFilters(), Utils.TransparentBackgroundFilter];
+ opaqueFilter = () => [...this._props.childFilters(), Utils.noDragDocsFilter, ...(SnappingManager.CanEmbed ? [] : [Utils.OpaqueBackgroundFilter])];
+ childStyleProvider = (doc: Doc | undefined, props: Opt<FieldViewProps>, property: string): any => {
if (doc instanceof Doc && property === StyleProp.PointerEvents) {
if (this.inlineTextAnnotations.includes(doc)) return 'none';
}
- return this.props.styleProvider?.(doc, props, property);
+ return this._props.styleProvider?.(doc, props, property);
};
pointerEvents = () =>
- !this._draggingSidebar && this.props.isContentActive() && !MarqueeOptionsMenu.Instance?.isShown()
+ !this._draggingSidebar && this._props.isContentActive() && !MarqueeOptionsMenu.Instance?.isShown()
? 'all' //
: 'none';
- annotationPointerEvents = () => (this.props.isContentActive() && (this._isAnnotating || SnappingManager.GetIsDragging() || Doc.ActiveTool !== InkTool.None) ? 'all' : 'none');
+ annotationPointerEvents = () => (this._props.isContentActive() && (SnappingManager.IsDragging || 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);
- const scale = previewScale * (this.props.NativeDimScaling?.() || 1);
+ const pointerEvents = this.layoutDoc._lockedPosition ? 'none' : (this._props.pointerEvents?.() as any);
+ const scale = previewScale * (this._props.NativeDimScaling?.() || 1);
return (
<div
className="webBox"
ref={this._mainCont}
style={{
pointerEvents: this.pointerEvents(), //
- position: SnappingManager.GetIsDragging() ? 'absolute' : undefined,
+ position: SnappingManager.IsDragging ? 'absolute' : undefined,
}}>
- <div className="webBox-background" style={{ backgroundColor: this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor) }} />
+ <div className="webBox-background" style={{ backgroundColor: this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.BackgroundColor) }} />
<div
className="webBox-container"
style={{
@@ -1088,27 +1101,26 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
}}
onContextMenu={this.specificContextMenu}>
{this.webpage}
- {!this._marqueeing || !this._mainCont.current || !this._annotationLayer.current ? null : (
- <div style={{ transformOrigin: 'top left', transform: `scale(${1 / scale})` }}>
- <MarqueeAnnotator
- rootDoc={this.rootDoc}
- iframe={this.isFirefox() ? this.iframeClick : undefined}
- iframeScaling={this.isFirefox() ? this.iframeScaling : undefined}
- anchorMenuClick={this.anchorMenuClick}
- scrollTop={0}
- down={this._marqueeing}
- scaling={returnOne}
- addDocument={this.addDocumentWrapper}
- docView={this.props.docViewPath().lastElement()}
- finishMarquee={this.finishMarquee}
- savedAnnotations={this.savedAnnotationsCreator}
- selectionText={this.selectionText}
- annotationLayer={this._annotationLayer.current}
- mainCont={this._mainCont.current}
- />
- </div>
- )}
</div>
+ {!this._mainCont.current || !this.DocumentView || !this._annotationLayer.current ? null : (
+ <div style={{ position: 'absolute', height: '100%', width: '100%', pointerEvents: this.marqueeing ? 'all' : 'none' }}>
+ <MarqueeAnnotator
+ ref={this._marqueeref}
+ Document={this.Document}
+ anchorMenuClick={this.anchorMenuClick}
+ scrollTop={NumCast(this.layoutDoc.layout_scrollTop)}
+ annotationLayerScrollTop={0}
+ scaling={this._props.NativeDimScaling}
+ addDocument={this.addDocumentWrapper}
+ docView={this.DocumentView}
+ finishMarquee={this.finishMarquee}
+ savedAnnotations={this.savedAnnotationsCreator}
+ selectionText={this.selectionText}
+ annotationLayer={this._annotationLayer.current}
+ marqueeContainer={this._mainCont.current}
+ />
+ </div>
+ )}
<div
className="webBox-sideResizer"
style={{
@@ -1118,25 +1130,25 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
}}
onPointerDown={e => this.sidebarBtnDown(e, false)}
/>
- <div style={{ position: 'absolute', height: '100%', right: 0, top: 0, width: `calc(100 * ${this.sidebarWidth() / this.props.PanelWidth()}%` }}>
+ <div style={{ position: 'absolute', height: '100%', right: 0, top: 0, width: `calc(100 * ${this.sidebarWidth() / this._props.PanelWidth()}%` }}>
<SidebarAnnos
ref={this._sidebarRef}
- {...this.props}
+ {...this._props}
whenChildContentsActiveChanged={this.whenChildContentsActiveChanged}
fieldKey={this.fieldKey + '_' + this._urlHash}
- rootDoc={this.rootDoc}
+ Document={this.Document}
layoutDoc={this.layoutDoc}
dataDoc={this.dataDoc}
setHeight={emptyFunction}
- nativeWidth={this._previewNativeWidth ?? NumCast(this.layoutDoc._nativeWidth) - WebBox.sidebarResizerWidth / (this.props.NativeDimScaling?.() || 1)}
+ nativeWidth={this._previewNativeWidth ?? NumCast(this.layoutDoc._nativeWidth) - WebBox.sidebarResizerWidth / (this._props.NativeDimScaling?.() || 1)}
showSidebar={this.SidebarShown}
sidebarAddDocument={this.sidebarAddDocument}
moveDocument={this.moveDocument}
removeDocument={this.removeDocument}
/>
</div>
- {this.sidebarHandle}
- {!this.props.isContentActive() ? null : this.searchUI}
+ {!this._props.isContentActive() || SnappingManager.IsDragging ? null : this.sidebarHandle}
+ {!this._props.isContentActive() || SnappingManager.IsDragging ? null : this.searchUI}
</div>
);
}