aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2021-03-15 13:19:24 -0400
committerbobzel <zzzman@gmail.com>2021-03-15 13:19:24 -0400
commit363b73726523caff1e5f047287c7fdb242b39e20 (patch)
tree7680e88640c34edd06a882f911b89d71f4e02ce4 /src
parentded69655dabf97c76f97271e7da8e77e3f33ec25 (diff)
fixed scrolling to annotations and pointerevents on webBox (when an annotation was selected so you can drag out a marquee)
Diffstat (limited to 'src')
-rw-r--r--src/Utils.ts13
-rw-r--r--src/client/views/MarqueeAnnotator.tsx5
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx2
-rw-r--r--src/client/views/nodes/WebBox.tsx122
4 files changed, 41 insertions, 101 deletions
diff --git a/src/Utils.ts b/src/Utils.ts
index f22df0da2..936a459ba 100644
--- a/src/Utils.ts
+++ b/src/Utils.ts
@@ -482,7 +482,7 @@ const easeInOutQuad = (currentTime: number, start: number, change: number, durat
return (-change / 2) * (newCurrentTime * (newCurrentTime - 2) - 1) + start;
};
-export function smoothScroll(duration: number, element: HTMLElement | HTMLElement[], to: number, finish?: () => void, reset?: { resetGoTo: { to: number, duration: number } | undefined }) {
+export function smoothScroll(duration: number, element: HTMLElement | HTMLElement[], to: number) {
const elements = (element instanceof HTMLElement ? [element] : element);
let starts = elements.map(element => element.scrollTop);
let startDate = new Date().getTime();
@@ -490,23 +490,12 @@ export function smoothScroll(duration: number, element: HTMLElement | HTMLElemen
const animateScroll = () => {
const currentDate = new Date().getTime();
let currentTime = currentDate - startDate;
- const resetParams = reset?.resetGoTo;
- if (resetParams) {
- reset!.resetGoTo = undefined;
- const { to: newTo, duration: newDuration } = resetParams;
- to = newTo;
- starts = starts.map(start => easeInOutQuad(currentTime, start, to - start, duration));
- startDate = currentDate;
- duration = newDuration;
- currentTime = currentDate - startDate;
- }
elements.map((element, i) => element.scrollTop = easeInOutQuad(currentTime, starts[i], to - starts[i], duration));
if (currentTime < duration) {
requestAnimationFrame(animateScroll);
} else {
elements.forEach(element => element.scrollTop = to);
- finish?.();
}
};
animateScroll();
diff --git a/src/client/views/MarqueeAnnotator.tsx b/src/client/views/MarqueeAnnotator.tsx
index c43dd6ba8..59500070c 100644
--- a/src/client/views/MarqueeAnnotator.tsx
+++ b/src/client/views/MarqueeAnnotator.tsx
@@ -30,7 +30,7 @@ export interface MarqueeAnnotatorProps {
annotationLayer: HTMLDivElement;
addDocument: (doc: Doc) => boolean;
getPageFromScroll?: (top: number) => number;
- finishMarquee: () => void;
+ finishMarquee: (x?: number, y?: number) => void;
anchorMenuClick?: (anchor: Doc) => void;
}
@observer
@@ -204,10 +204,11 @@ export class MarqueeAnnotator extends React.Component<MarqueeAnnotatorProps> {
if (AnchorMenu.Instance.Highlighting) {// when highlighter has been toggled when menu is pinned, we auto-highlight immediately on mouse up
this.highlight("rgba(245, 230, 95, 0.75)", false); // yellowish highlight color for highlighted text (should match AnchorMenu's highlight color)
}
+ this.props.finishMarquee();
} else {
runInAction(() => this._width = this._height = 0);
+ this.props.finishMarquee(e.clientX, e.clientY);
}
- this.props.finishMarquee();
}
render() {
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index daa92055c..b5dca42a7 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1493,7 +1493,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
onDragOver={e => e.preventDefault()}
onContextMenu={this.onContextMenu}
style={{
- pointerEvents: this.backgroundEvents ? "all" : this.props.pointerEvents,
+ pointerEvents: this.backgroundEvents ? "all" : this.props.pointerEvents as any,
transform: `scale(${this.contentScaling || 1})`,
width: `${100 / (this.contentScaling || 1)}%`,
height: this.isAnnotationOverlay && this.Document.scrollHeight ? this.Document.scrollHeight : `${100 / (this.contentScaling || 1)}%`// : this.isAnnotationOverlay ? (this.Document.scrollHeight ? this.Document.scrollHeight : "100%") : this.props.PanelHeight()
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index 9e6e94248..0f10d7cae 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -1,10 +1,9 @@
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { Tooltip } from '@material-ui/core';
import { action, computed, IReactionDisposer, observable, reaction, runInAction } from "mobx";
import { observer } from "mobx-react";
import { Dictionary } from "typescript-collections";
import * as WebRequest from 'web-request';
-import { Doc, DocListCast, HeightSym, Opt, WidthSym, StrListCast } from "../../../fields/Doc";
+import { Doc, DocListCast, HeightSym, Opt, StrListCast, WidthSym } from "../../../fields/Doc";
import { documentSchema } from "../../../fields/documentSchemas";
import { Id } from "../../../fields/FieldSymbols";
import { HtmlField } from "../../../fields/HtmlField";
@@ -14,30 +13,30 @@ import { listSpec, makeInterface } from "../../../fields/Schema";
import { Cast, NumCast, StrCast } from "../../../fields/Types";
import { WebField } from "../../../fields/URLField";
import { TraceMobx } from "../../../fields/util";
-import { emptyFunction, OmitKeys, returnOne, smoothScroll, Utils, returnZero, returnTrue } from "../../../Utils";
+import { emptyFunction, OmitKeys, returnOne, returnTrue, returnZero, smoothScroll, Utils } from "../../../Utils";
import { Docs, DocUtils } from "../../documents/Documents";
+import { DocumentType } from '../../documents/DocumentTypes';
+import { CurrentUserUtils } from "../../util/CurrentUserUtils";
import { DragManager } from "../../util/DragManager";
import { ImageUtils } from "../../util/Import & Export/ImageUtils";
import { undoBatch } from "../../util/UndoManager";
import { CollectionFreeFormView } from "../collections/collectionFreeForm/CollectionFreeFormView";
+import { CollectionStackingView } from "../collections/CollectionStackingView";
+import { CollectionViewType } from "../collections/CollectionView";
import { ContextMenu } from "../ContextMenu";
import { ContextMenuProps } from "../ContextMenuItem";
import { ViewBoxAnnotatableComponent } from "../DocComponent";
import { DocumentDecorations } from "../DocumentDecorations";
import { MarqueeAnnotator } from "../MarqueeAnnotator";
+import { AnchorMenu } from "../pdf/AnchorMenu";
import { Annotation } from "../pdf/Annotation";
+import { SearchBox } from "../search/SearchBox";
+import { StyleProp } from "../StyleProvider";
import { FieldView, FieldViewProps } from './FieldView';
+import { FormattedTextBox } from "./formattedText/FormattedTextBox";
import { LinkDocPreview } from "./LinkDocPreview";
import "./WebBox.scss";
-import { DocumentType } from '../../documents/DocumentTypes';
import React = require("react");
-import { CurrentUserUtils } from "../../util/CurrentUserUtils";
-import { SearchBox } from "../search/SearchBox";
-import { CollectionStackingView } from "../collections/CollectionStackingView";
-import { StyleProp } from "../StyleProvider";
-import { FormattedTextBox } from "./formattedText/FormattedTextBox";
-import { CollectionViewType } from "../collections/CollectionView";
-import { AnchorMenu } from "../pdf/AnchorMenu";
const htmlToText = require("html-to-text");
type WebDocument = makeInterface<[typeof documentSchema]>;
@@ -47,20 +46,21 @@ const WebDocument = makeInterface(documentSchema);
export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocument>(WebDocument) {
public static LayoutString(fieldKey: string) { return FieldView.LayoutString(WebBox, fieldKey); }
private _mainCont: React.RefObject<HTMLDivElement> = React.createRef();
+ private _outerRef: React.RefObject<HTMLDivElement> = React.createRef();
private _disposers: { [name: string]: IReactionDisposer } = {};
private _longPressSecondsHack?: NodeJS.Timeout;
- private _outerRef = React.createRef<HTMLDivElement>();
private _annotationLayer: React.RefObject<HTMLDivElement> = React.createRef();
private _iframeIndicatorRef = React.createRef<HTMLDivElement>();
private _iframeDragRef = React.createRef<HTMLDivElement>();
private _keyInput = React.createRef<HTMLInputElement>();
- private _ignoreScroll = "";
private _scrollTimer: any;
private _initialScroll: Opt<number>;
+ private _setPreviewCursor: undefined | ((x: number, y: number, drag: boolean) => void);
@observable private _marqueeing: number[] | undefined;
@observable private _url: string = "hello";
@observable private _pressX: number = 0;
@observable private _pressY: number = 0;
+ @observable private _isAnnotating = false;
@observable private _iframe: HTMLIFrameElement | null = null;
@observable private _savedAnnotations: Dictionary<number, HTMLDivElement[]> = new Dictionary<number, HTMLDivElement[]>();
get scrollHeight() { return this.webpage?.scrollHeight || 1000; }
@@ -121,7 +121,6 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
}
} else AnchorMenu.Instance.fadeOut(true);
}
-
getWordAtPoint = (elem: any, x: number, y: number): Opt<string> => {
if (elem.nodeType == elem.TEXT_NODE) {
var range = elem.ownerDocument.createRange();
@@ -166,11 +165,10 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
this._marqueeing = [e.clientX * scale + mainContBounds.translateX,
e.clientY * scale + mainContBounds.translateY - NumCast(this.layoutDoc._scrollTop) * scale];
if (word) {
- console.log(word);
this._iframe?.contentDocument?.addEventListener("pointerup", this.ptrUp);
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._isAnnotating = true;
this.props.select(false);
e.stopPropagation();
e.preventDefault();
@@ -181,8 +179,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
const iframe = this._iframe;
if (iframe?.contentDocument) {
iframe?.contentDocument.addEventListener("pointerdown", this.ptrDown);
- if (this._initialScroll !== undefined && this._outerRef.current && this.webpage) {
- this.webpage.scrollTop = this._initialScroll;
+ if (this._initialScroll !== undefined && this._outerRef.current) {
this._outerRef.current.scrollTop = this._initialScroll;
this._initialScroll = undefined;
}
@@ -201,65 +198,27 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
}
})));
iframe.contentDocument.addEventListener('wheel', this.iframeWheel, false);
- iframe.contentDocument.addEventListener('scroll', this.iframeScroll, false);
}
}
- resetIgnoreScroll = () => {
+ resetIgnoreScroll = (timeout: number = 250) => {
this._scrollTimer && clearTimeout(this._scrollTimer);
this._scrollTimer = setTimeout(() => {
this._scrollTimer = undefined;
- this._ignoreScroll = "";
- }, 250);
- this._outerRef.current && (this._outerRef.current.scrollLeft = 0);
- }
- iframeWheel = (e: any) => {
- this._ignoreScroll = "iframe";
- this.resetIgnoreScroll();
- e.stopPropagation();
- }
- onWebWheel = (e: React.WheelEvent) => {
- this._ignoreScroll = "iframe";
- this.goTo(Math.max(0, (this.webpage?.scrollTop || 0) + (this._accumulatedGoTo + 1) * e.deltaY), 100);
- this.resetIgnoreScroll();
- e.stopPropagation();
- }
- onWheel = (e: React.WheelEvent) => {
- this._ignoreScroll = "outer";
- this.resetIgnoreScroll();
- e.stopPropagation();
- }
- iframeScroll = (e: any) => {
- if (!this._ignoreScroll.includes("outer") && this._outerRef.current) {
- this._outerRef.current.scrollTop = this.webpage?.scrollTop || 0;
- this.layoutDoc._scrollTop = this.webpage?.scrollTop;
- }
- }
- onScroll = (e: any) => {
- if (!this._ignoreScroll.includes("iframe") && this.webpage) {
- this.webpage.scrollTop = this._outerRef.current?.scrollTop || 0;
- }
- if (this._ignoreScroll !== "iframe|outer") {
- this.layoutDoc._scrollTop = this._outerRef.current?.scrollTop;
- }
+ if (!LinkDocPreview.LinkInfo && this._outerRef.current) {
+ this.layoutDoc._scrollTop = this._outerRef.current.scrollTop;
+ }
+ }, timeout);
}
+ iframeWheel = (e: any) => e.stopPropagation();
+ onScroll = (e: any) => this.resetIgnoreScroll();
scrollFocus = (doc: Doc, smooth: boolean) => {
let focusSpeed: Opt<number>;
- if (doc !== this.rootDoc && this.webpage && this._outerRef.current) {
+ if (doc !== this.rootDoc && this.webpage) {
const scrollTo = doc.type === DocumentType.TEXTANCHOR ? NumCast(doc.y) : Utils.scrollIntoView(NumCast(doc.y), doc[HeightSym](), NumCast(this.layoutDoc._scrollTop), this.props.PanelHeight() / (this.props.scaling?.() || 1));
if (scrollTo !== undefined) {
this._initialScroll !== undefined && (this._initialScroll = scrollTo);
- if (!LinkDocPreview.LinkInfo) {
- this._ignoreScroll = "iframe|outer";
- this.layoutDoc._scrollTop = scrollTo;
- this._ignoreScroll = "";
- }
- this._ignoreScroll = "iframe|outer";
this.goTo(scrollTo, focusSpeed = smooth ? 500 : 0);
- setTimeout(() => {
- this._scrollTimer = undefined;
- this._ignoreScroll = "";
- }, focusSpeed);
}
} else {
this._initialScroll = NumCast(doc.y);
@@ -332,19 +291,13 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
quickScroll = false;
}
- _accumulatedGoTo = 0;
- _resetGoTo: { resetGoTo: { to: number, duration: number } | undefined } = { resetGoTo: undefined };
goTo = (scrollTop: number, duration: number) => {
- if (this._outerRef.current && this.webpage) {
+ if (this._outerRef.current) {
if (duration) {
- if (this._accumulatedGoTo++) {
- this._resetGoTo.resetGoTo = { to: scrollTop, duration };
- } else {
- smoothScroll(duration, [this.webpage as any as HTMLElement, this._outerRef.current], scrollTop, () => this._accumulatedGoTo = 0, this._resetGoTo);
- }
+ smoothScroll(duration, [this._outerRef.current], scrollTop);
+ this.resetIgnoreScroll(duration);
} else {
- this.webpage.scrollTop = scrollTop;
- this._outerRef.current.scrollTop = scrollTop;
+ this.resetIgnoreScroll();
}
}
}
@@ -354,7 +307,6 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
document.removeEventListener("pointerup", this.onLongPressUp);
document.removeEventListener("pointermove", this.onLongPressMove);
this._iframe?.removeEventListener('wheel', this.iframeWheel);
- this._iframe?.removeEventListener('scroll', this.iframeScroll);
}
@action
@@ -672,10 +624,10 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
@computed
get content() {
- const frozen = !this.props.isSelected() || DocumentDecorations.Instance?.Interacting;
+ const frozen = !this.active() || DocumentDecorations.Instance?.Interacting;
const scale = this.props.scaling?.() || 1;
return (<>
- <div className={"webBox-cont" + (this.props.isSelected() && CurrentUserUtils.SelectedTool === InkTool.None && !DocumentDecorations.Instance?.Interacting ? "-interactive" : "")}
+ <div className={"webBox-cont" + (this.active() && CurrentUserUtils.SelectedTool === InkTool.None && !DocumentDecorations.Instance?.Interacting ? "-interactive" : "")}
style={{
width: NumCast(this.layoutDoc[this.fieldKey + "-contentWidth"]) || `${100 / scale}%`,
height: `${100 / scale}%`,
@@ -715,12 +667,11 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
this.props.select(false);
}
}
- @observable isAnnotating = false;
-
- @action
- finishMarquee = () => {
+ setPreviewCursor = (func?: (x: number, y: number, drag: boolean) => void) => this._setPreviewCursor = func;
+ @action finishMarquee = (x?: number, y?: number) => {
this._marqueeing = undefined;
- this.isAnnotating = false;
+ this._isAnnotating = false;
+ x !== undefined && y !== undefined && this._setPreviewCursor?.(x, y, false);
}
panelWidth = () => this.props.PanelWidth() / (this.props.scaling?.() || 1) - this.sidebarWidth(); // (this.Document.scrollHeight || Doc.NativeHeight(this.Document) || 0);
@@ -733,7 +684,6 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
<div className="webBox" ref={this._mainCont} >
<div className={`webBox-container`}
style={{ pointerEvents: inactiveLayer ? "none" : undefined }}
- onWheel={this.onWebWheel}
onContextMenu={this.specificContextMenu}>
<base target="_blank" />
<div className={"webBox-outerContent"} ref={this._outerRef}
@@ -743,9 +693,8 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
transform: `scale(${scale})`,
pointerEvents: inactiveLayer ? "none" : "all"
}}
- onWheel={this.onWheel}
- onPointerDown={this.onMarqueeDown}
onScroll={this.onScroll}
+ onPointerDown={this.onMarqueeDown}
>
<div className={"webBox-innerContent"} style={{
height: NumCast(this.scrollHeight, 50),
@@ -758,10 +707,11 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
fieldKey={this.annotationKey}
isAnnotationOverlay={true}
scaling={returnOne}
- pointerEvents={this.isAnnotating ? "all" : "none"}
+ pointerEvents={this._isAnnotating ? "all" : "none"}
PanelWidth={this.panelWidth}
PanelHeight={this.panelHeight}
ScreenToLocalTransform={this.scrollXf}
+ setPreviewCursor={this.setPreviewCursor}
removeDocument={this.removeDocument}
moveDocument={this.moveDocument}
addDocument={this.addDocument}