aboutsummaryrefslogtreecommitdiff
path: root/src/client
diff options
context:
space:
mode:
Diffstat (limited to 'src/client')
-rw-r--r--src/client/util/LinkManager.ts6
-rw-r--r--src/client/views/DocumentDecorations.tsx4
-rw-r--r--src/client/views/InkControlPtHandles.tsx16
-rw-r--r--src/client/views/InkStrokeProperties.ts72
-rw-r--r--src/client/views/InkTangentHandles.tsx6
-rw-r--r--src/client/views/InkingStroke.tsx9
-rw-r--r--src/client/views/collections/CollectionSubView.tsx5
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx4
-rw-r--r--src/client/views/nodes/DocumentView.tsx6
-rw-r--r--src/client/views/nodes/WebBox.tsx77
10 files changed, 132 insertions, 73 deletions
diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts
index 90a8f2737..62b13e2c6 100644
--- a/src/client/util/LinkManager.ts
+++ b/src/client/util/LinkManager.ts
@@ -234,8 +234,10 @@ export class LinkManager {
setTimeout(LightboxView.Next);
finished?.();
} else {
- const containerDoc = Cast(target.annotationOn, Doc, null) || target;
- const targetContext = Cast(containerDoc?.context, Doc, null);
+ const containerAnnoDoc = Cast(target.annotationOn, Doc, null);
+ const containerDoc = containerAnnoDoc || target;
+ const containerDocContext = Cast(containerDoc?.context, Doc, null);
+ const targetContext = LightboxView.LightboxDoc ? containerAnnoDoc || containerDocContext : containerDocContext;
const targetNavContext = !Doc.AreProtosEqual(targetContext, currentContext) ? targetContext : undefined;
DocumentManager.Instance.jumpToDocument(target, zoom, (doc, finished) => createViewFunc(doc, StrCast(linkDoc.followLinkLocation, "lightbox"), finished), targetNavContext, linkDoc, undefined, sourceDoc, finished);
}
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index ed6f39ffe..fc4c3ca91 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -195,11 +195,13 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number, P
@action
onRotateDown = (e: React.PointerEvent): void => {
this._rotateUndo = UndoManager.StartBatch("rotatedown");
+ const pt = { x: (this.Bounds.x + this.Bounds.r) / 2, y: (this.Bounds.y + this.Bounds.b) / 2 };
setupMoveUpEvents(this, e,
(e: PointerEvent, down: number[], delta: number[]) => {
const movement = { X: delta[0], Y: e.clientY - down[1] };
const angle = Math.max(1, Math.abs(movement.Y / 10));
- InkStrokeProperties.Instance?.rotateInk(2 * movement.X / angle * (Math.PI / 180));
+ const selectedInk = SelectionManager.Views().filter(i => Document(i.rootDoc).type === DocumentType.INK);
+ InkStrokeProperties.Instance?.rotateInk(selectedInk, 2 * movement.X / angle * (Math.PI / 180), pt);
return false;
},
() => {
diff --git a/src/client/views/InkControlPtHandles.tsx b/src/client/views/InkControlPtHandles.tsx
index 0644488b3..73de4a3e0 100644
--- a/src/client/views/InkControlPtHandles.tsx
+++ b/src/client/views/InkControlPtHandles.tsx
@@ -3,18 +3,20 @@ import { action, observable } from "mobx";
import { observer } from "mobx-react";
import { Doc } from "../../fields/Doc";
import { ControlPoint, InkData, PointData } from "../../fields/InkField";
+import { List } from "../../fields/List";
import { listSpec } from "../../fields/Schema";
import { Cast } from "../../fields/Types";
import { setupMoveUpEvents } from "../../Utils";
import { Transform } from "../util/Transform";
import { UndoManager } from "../util/UndoManager";
import { Colors } from "./global/globalEnums";
-import { InkStrokeProperties } from "./InkStrokeProperties";
-import { List } from "../../fields/List";
import { InkingStroke } from "./InkingStroke";
+import { InkStrokeProperties } from "./InkStrokeProperties";
+import { DocumentView } from "./nodes/DocumentView";
export interface InkControlProps {
inkDoc: Doc;
+ inkView: DocumentView;
inkCtrlPoints: InkData;
screenCtrlPoints: InkData;
screenSpaceLineWidth: number;
@@ -51,12 +53,12 @@ export class InkControlPtHandles extends React.Component<InkControlProps> {
setupMoveUpEvents(this, e,
action((e: PointerEvent, down: number[], delta: number[]) => {
if (!this.controlUndo) this.controlUndo = UndoManager.StartBatch("drag ink ctrl pt");
- InkStrokeProperties.Instance?.moveControlPtHandle(delta[0] * screenScale, delta[1] * screenScale, controlIndex);
+ InkStrokeProperties.Instance?.moveControlPtHandle(this.props.inkView, delta[0] * screenScale, delta[1] * screenScale, controlIndex);
return false;
}),
action(() => {
if (this.controlUndo) {
- InkStrokeProperties.Instance?.snapControl(this.props.inkDoc, controlIndex);
+ InkStrokeProperties.Instance?.snapControl(this.props.inkView, controlIndex);
}
this.controlUndo?.end();
this.controlUndo = undefined;
@@ -71,11 +73,11 @@ export class InkControlPtHandles extends React.Component<InkControlProps> {
} else {
if (brokenIndices?.includes(equivIndex)) {
if (!this.controlUndo) this.controlUndo = UndoManager.StartBatch("make smooth");
- InkStrokeProperties.Instance?.snapHandleTangent(equivIndex, handleIndexA, handleIndexB);
+ InkStrokeProperties.Instance?.snapHandleTangent(this.props.inkView, equivIndex, handleIndexA, handleIndexB);
}
if (equivIndex !== controlIndex && brokenIndices?.includes(controlIndex)) {
if (!this.controlUndo) this.controlUndo = UndoManager.StartBatch("make smooth");
- InkStrokeProperties.Instance?.snapHandleTangent(controlIndex, handleIndexA, handleIndexB);
+ InkStrokeProperties.Instance?.snapHandleTangent(this.props.inkView, controlIndex, handleIndexA, handleIndexB);
}
}
this.controlUndo?.end();
@@ -98,7 +100,7 @@ export class InkControlPtHandles extends React.Component<InkControlProps> {
@action
onDelete = (e: KeyboardEvent) => {
if (["-", "Backspace", "Delete"].includes(e.key)) {
- InkStrokeProperties.Instance?.deletePoints();
+ InkStrokeProperties.Instance?.deletePoints(this.props.inkView);
e.stopPropagation();
}
}
diff --git a/src/client/views/InkStrokeProperties.ts b/src/client/views/InkStrokeProperties.ts
index ee30caa3d..33e25bbbb 100644
--- a/src/client/views/InkStrokeProperties.ts
+++ b/src/client/views/InkStrokeProperties.ts
@@ -1,16 +1,15 @@
import { Bezier } from "bezier-js";
-import { action, computed, observable, reaction } from "mobx";
-import { Doc } from "../../fields/Doc";
-import { Document } from "../../fields/documentSchemas";
+import { action, observable, reaction } from "mobx";
+import { Doc, Opt } from "../../fields/Doc";
import { InkData, InkField, InkTool, PointData } from "../../fields/InkField";
import { List } from "../../fields/List";
import { listSpec } from "../../fields/Schema";
import { Cast, NumCast } from "../../fields/Types";
import { DocumentType } from "../documents/DocumentTypes";
import { CurrentUserUtils } from "../util/CurrentUserUtils";
-import { SelectionManager } from "../util/SelectionManager";
import { undoBatch } from "../util/UndoManager";
import { InkingStroke } from "./InkingStroke";
+import { DocumentView } from "./nodes/DocumentView";
export class InkStrokeProperties {
static Instance: InkStrokeProperties | undefined;
@@ -25,21 +24,16 @@ export class InkStrokeProperties {
reaction(() => CurrentUserUtils.SelectedTool, tool => (tool !== InkTool.None) && (this._controlButton = false));
}
- @computed get selectedInk() {
- const inks = SelectionManager.Views().filter(i => Document(i.rootDoc).type === DocumentType.INK);
- return inks.length ? inks : undefined;
- }
-
/**
* Helper function that enables other functions to be applied to a particular ink instance.
* @param func The inputted function.
* @param requireCurrPoint Indicates whether the current selected point is needed.
*/
- applyFunction = (func: (doc: Doc, ink: InkData, ptsXscale: number, ptsYscale: number) => { X: number, Y: number }[] | undefined, requireCurrPoint: boolean = false) => {
+ applyFunction = (strokes: Opt<DocumentView | DocumentView[]>, func: (view: DocumentView, ink: InkData, ptsXscale: number, ptsYscale: number, inkStrokeWidth: number) => { X: number, Y: number }[] | undefined, requireCurrPoint: boolean = false) => {
var appliedFunc = false;
- this.selectedInk?.forEach(action(inkView => {
- if (this.selectedInk?.length === 1 && (!requireCurrPoint || this._currentPoint !== -1)) {
- const doc = Document(inkView.rootDoc);
+ (strokes instanceof DocumentView ? [strokes] : strokes)?.forEach(action(inkView => {
+ if (!requireCurrPoint || this._currentPoint !== -1) {
+ const doc = inkView.rootDoc;
if (doc.type === DocumentType.INK && doc.width && doc.height) {
const ink = Cast(doc.data, InkField)?.inkData;
if (ink) {
@@ -47,7 +41,7 @@ export class InkStrokeProperties {
const oldYrange = (ys => ({ coord: NumCast(doc.y), min: Math.min(...ys), max: Math.max(...ys) }))(ink.map(p => p.Y));
const ptsXscale = ((NumCast(doc._width) - NumCast(doc.strokeWidth)) / ((oldXrange.max - oldXrange.min) || 1)) || 1;
const ptsYscale = ((NumCast(doc._height) - NumCast(doc.strokeWidth)) / ((oldYrange.max - oldYrange.min) || 1)) || 1;
- const newPoints = func(doc, ink, ptsXscale, ptsYscale);
+ const newPoints = func(inkView, ink, ptsXscale, ptsYscale, NumCast(doc.strokeWidth));
if (newPoints) {
const newXrange = (xs => ({ min: Math.min(...xs), max: Math.max(...xs) }))(newPoints.map(p => p.X));
const newYrange = (ys => ({ min: Math.min(...ys), max: Math.max(...ys) }))(newPoints.map(p => p.Y));
@@ -73,8 +67,9 @@ export class InkStrokeProperties {
*/
@undoBatch
@action
- addPoints = (t: number, i: number, controls: { X: number, Y: number }[]) => {
- this.applyFunction((doc: Doc, ink: InkData) => {
+ addPoints = (inkView: DocumentView, t: number, i: number, controls: { X: number, Y: number }[]) => {
+ this.applyFunction(inkView, (view: DocumentView, ink: InkData) => {
+ const doc = view.rootDoc;
const array = [controls[i], controls[i + 1], controls[i + 2], controls[i + 3]];
const newsegs = new Bezier(array.map(p => ({ x: p.X, y: p.Y }))).split(t);
const splicepts = [...newsegs.left.points, ...newsegs.right.points];
@@ -143,9 +138,10 @@ export class InkStrokeProperties {
*/
@undoBatch
@action
- deletePoints = () => this.applyFunction((doc: Doc, ink: InkData) => {
+ deletePoints = (inkView: DocumentView) => this.applyFunction(inkView, (view: DocumentView, ink: InkData) => {
+ const doc = view.rootDoc;
const newPoints: { X: number, Y: number }[] = [];
- const toRemove = Math.floor(((this._currentPoint + 2) / 4));
+ const toRemove = Math.floor((this._currentPoint + 2) / 4);
const last = this._currentPoint === ink.length - 1;
for (let i = 0; i < ink.length; i++) {
if (Math.floor((i + 2) / 4) !== toRemove && (toRemove !== 0 || i > 3)) {
@@ -164,17 +160,22 @@ export class InkStrokeProperties {
*/
@undoBatch
@action
- rotateInk = (angle: number) => {
- this.applyFunction((doc: Doc, ink: InkData, xScale: number, yScale: number) => {
- const oldXrange = (xs => ({ coord: NumCast(doc.x), min: Math.min(...xs), max: Math.max(...xs) }))(ink.map(p => p.X));
- const oldYrange = (ys => ({ coord: NumCast(doc.y), min: Math.min(...ys), max: Math.max(...ys) }))(ink.map(p => p.Y));
- const centerPoint = { X: (oldXrange.min + oldXrange.max) / 2, Y: (oldYrange.min + oldYrange.max) / 2 };
+ rotateInk = (inkStrokes: DocumentView[], angle: number, scrpt: { x: number, y: number }) => {
+ this.applyFunction(inkStrokes, (view: DocumentView, ink: InkData, xScale: number, yScale: number, inkStrokeWidth: number) => {
+ const oldXrangeMin = Math.min(...ink.map(p => p.X));
+ const oldYrangeMin = Math.min(...ink.map(p => p.Y));
+ const docViewCenterPt = view.screenToLocalTransform().transformPoint(scrpt.x, scrpt.y);
+ const inkCenterPt = {
+ X: (docViewCenterPt[0] - inkStrokeWidth / 2) / xScale + oldXrangeMin,
+ Y: (docViewCenterPt[1] - inkStrokeWidth / 2) / yScale + oldYrangeMin
+ };
const newPoints = ink.map(i => {
- const pt = { X: i.X - centerPoint.X, Y: i.Y - centerPoint.Y };
+ const pt = { X: i.X - inkCenterPt.X, Y: i.Y - inkCenterPt.Y };
const newX = Math.cos(angle) * pt.X - Math.sin(angle) * pt.Y * yScale / xScale;
const newY = Math.sin(angle) * pt.X * xScale / yScale + Math.cos(angle) * pt.Y;
- return { X: newX + centerPoint.X, Y: newY + centerPoint.Y };
+ return { X: newX + inkCenterPt.X, Y: newY + inkCenterPt.Y };
});
+ const doc = view.rootDoc;
doc.rotation = NumCast(doc.rotation) + angle;
return newPoints;
});
@@ -185,8 +186,8 @@ export class InkStrokeProperties {
*/
@undoBatch
@action
- moveControlPtHandle = (deltaX: number, deltaY: number, controlIndex: number) =>
- this.applyFunction((doc: Doc, ink: InkData, xScale: number, yScale: number) => {
+ moveControlPtHandle = (inkView: DocumentView, deltaX: number, deltaY: number, controlIndex: number) =>
+ this.applyFunction(inkView, (view: DocumentView, ink: InkData, xScale: number, yScale: number) => {
const order = controlIndex % 4;
const closed = InkingStroke.IsClosed(ink);
@@ -235,7 +236,8 @@ export class InkStrokeProperties {
/**
* Handles the movement/scaling of a control point.
*/
- snapControl = (inkDoc: Doc, controlIndex: number) => {
+ snapControl = (inkView: DocumentView, controlIndex: number) => {
+ const inkDoc = inkView.rootDoc;
const ink = Cast(inkDoc.data, InkField)?.inkData;
if (ink) {
const closed = InkingStroke.IsClosed(ink);
@@ -257,8 +259,8 @@ export class InkStrokeProperties {
const near = Math.sqrt((nearestPt.X - refPt.X) * (nearestPt.X - refPt.X) * ptsXscale * ptsXscale +
(nearestPt.Y - refPt.Y) * (nearestPt.Y - refPt.Y) * ptsYscale * ptsYscale);
- if (near / (this.selectedInk?.lastElement().props.ScreenToLocalTransform().Scale || 1) < 10) {
- return this.moveControlPtHandle((nearestPt.X - ink[controlIndex].X) * ptsXscale, (nearestPt.Y - ink[controlIndex].Y) * ptsYscale, controlIndex);
+ if (near / (inkView.props.ScreenToLocalTransform().Scale || 1) < 10) {
+ return this.moveControlPtHandle(inkView, (nearestPt.X - ink[controlIndex].X) * ptsXscale, (nearestPt.Y - ink[controlIndex].Y) * ptsYscale, controlIndex);
}
}
return false;
@@ -269,8 +271,9 @@ export class InkStrokeProperties {
* @param handleIndexA The handle point that retains its current position.
* @param handleIndexB The handle point that is rotated to be 180 degrees from its opposite.
*/
- snapHandleTangent = (controlIndex: number, handleIndexA: number, handleIndexB: number) => {
- this.applyFunction((doc: Doc, ink: InkData) => {
+ snapHandleTangent = (inkView: DocumentView, controlIndex: number, handleIndexA: number, handleIndexB: number) => {
+ this.applyFunction(inkView, (view: DocumentView, ink: InkData) => {
+ const doc = view.rootDoc;
const brokenIndices = Cast(doc.brokenInkIndices, listSpec("number"), []);
const ind = brokenIndices.findIndex(value => value === controlIndex);
if (ind !== -1) {
@@ -330,8 +333,9 @@ export class InkStrokeProperties {
*/
@undoBatch
@action
- moveTangentHandle = (deltaX: number, deltaY: number, handleIndex: number, oppositeHandleIndex: number, controlIndex: number) =>
- this.applyFunction((doc: Doc, ink: InkData, xScale: number, yScale: number) => {
+ moveTangentHandle = (inkView: DocumentView, deltaX: number, deltaY: number, handleIndex: number, oppositeHandleIndex: number, controlIndex: number) =>
+ this.applyFunction(inkView, (view: DocumentView, ink: InkData, xScale: number, yScale: number) => {
+ const doc = view.rootDoc;
const closed = InkingStroke.IsClosed(ink);
const oldHandlePoint = ink[handleIndex];
const oppositeHandlePoint = ink[oppositeHandleIndex];
diff --git a/src/client/views/InkTangentHandles.tsx b/src/client/views/InkTangentHandles.tsx
index df5bebf31..f88a20448 100644
--- a/src/client/views/InkTangentHandles.tsx
+++ b/src/client/views/InkTangentHandles.tsx
@@ -10,11 +10,13 @@ import { emptyFunction, setupMoveUpEvents } from "../../Utils";
import { Transform } from "../util/Transform";
import { UndoManager } from "../util/UndoManager";
import { Colors } from "./global/globalEnums";
-import { InkStrokeProperties } from "./InkStrokeProperties";
import { InkingStroke } from "./InkingStroke";
+import { InkStrokeProperties } from "./InkStrokeProperties";
+import { DocumentView } from "./nodes/DocumentView";
export interface InkHandlesProps {
inkDoc: Doc;
+ inkView: DocumentView;
screenCtrlPoints: InkData;
screenSpaceLineWidth: number;
ScreenToLocalTransform: () => Transform;
@@ -37,7 +39,7 @@ export class InkTangentHandles extends React.Component<InkHandlesProps> {
setupMoveUpEvents(this, e, (e: PointerEvent, down: number[], delta: number[]) => {
if (!controlUndo) controlUndo = UndoManager.StartBatch("DocDecs move tangent");
if (e.altKey) this.onBreakTangent(controlIndex);
- InkStrokeProperties.Instance?.moveTangentHandle(-delta[0] * screenScale, -delta[1] * screenScale, handleIndex, oppositeHandleIndex, controlIndex);
+ InkStrokeProperties.Instance?.moveTangentHandle(this.props.inkView, -delta[0] * screenScale, -delta[1] * screenScale, handleIndex, oppositeHandleIndex, controlIndex);
return false;
}, () => {
controlUndo?.end();
diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx
index 752db1413..d312331d0 100644
--- a/src/client/views/InkingStroke.tsx
+++ b/src/client/views/InkingStroke.tsx
@@ -1,17 +1,17 @@
import React = require("react");
-import { Bezier } from "bezier-js";
import { action, IReactionDisposer, observable, reaction } from "mobx";
import { observer } from "mobx-react";
import { Doc } from "../../fields/Doc";
import { documentSchema } from "../../fields/documentSchemas";
import { InkData, InkField, InkTool } from "../../fields/InkField";
import { makeInterface } from "../../fields/Schema";
-import { Cast, NumCast, StrCast, BoolCast } from "../../fields/Types";
+import { BoolCast, Cast, NumCast, StrCast } from "../../fields/Types";
import { TraceMobx } from "../../fields/util";
import { emptyFunction, returnFalse, setupMoveUpEvents } from "../../Utils";
import { CognitiveServices } from "../cognitive_services/CognitiveServices";
import { CurrentUserUtils } from "../util/CurrentUserUtils";
import { InteractionUtils } from "../util/InteractionUtils";
+import { SnappingManager } from "../util/SnappingManager";
import { ContextMenu } from "./ContextMenu";
import { ViewBoxBaseComponent } from "./DocComponent";
import { Colors } from "./global/globalEnums";
@@ -20,7 +20,6 @@ import "./InkStroke.scss";
import { InkStrokeProperties } from "./InkStrokeProperties";
import { InkTangentHandles } from "./InkTangentHandles";
import { FieldView, FieldViewProps } from "./nodes/FieldView";
-import { SnappingManager } from "../util/SnappingManager";
import Color = require("color");
type InkDocument = makeInterface<[typeof documentSchema]>;
@@ -83,7 +82,7 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps, InkDocume
InkStrokeProperties.Instance && (InkStrokeProperties.Instance._currentPoint = -1);
this._handledClick = true; // mark the double-click pseudo pointerevent so we can block the real mouse event from propagating to DocumentView
} else if (this._properties?._controlButton) {
- this._nearestT && this._nearestSeg !== undefined && InkStrokeProperties.Instance?.addPoints(this._nearestT, this._nearestSeg, this.inkScaledData().inkData.slice());
+ this._nearestT && this._nearestSeg !== undefined && InkStrokeProperties.Instance?.addPoints(this.props.docViewPath().lastElement(), this._nearestT, this._nearestSeg, this.inkScaledData().inkData.slice());
}
}), this._properties?._controlButton, this._properties?._controlButton
);
@@ -166,6 +165,7 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps, InkDocume
StrCast(inkDoc.strokeLineJoin), StrCast(this.layoutDoc.strokeLineCap), StrCast(inkDoc.strokeBezier),
"none", startMarker, endMarker, StrCast(inkDoc.strokeDash), 1, 1, "", "none", 1.0, false)}
<InkControlPtHandles
+ inkView={this.props.docViewPath().lastElement()}
inkDoc={inkDoc}
inkCtrlPoints={inkData}
screenCtrlPoints={screenHdlPts}
@@ -173,6 +173,7 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps, InkDocume
screenSpaceLineWidth={screenSpaceCenterlineStrokeWidth}
ScreenToLocalTransform={this.props.ScreenToLocalTransform} />
<InkTangentHandles
+ inkView={this.props.docViewPath().lastElement()}
inkDoc={inkDoc}
screenCtrlPoints={screenHdlPts}
screenSpaceLineWidth={screenSpaceCenterlineStrokeWidth}
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index e662f3ddf..5dffc65fc 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -378,7 +378,6 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
// }
}
if (uriList) {
- console.log("Web URI = ", uriList);
// const existingWebDoc = await Hypothesis.findWebDoc(uriList);
// if (existingWebDoc) {
// const alias = Doc.MakeAlias(existingWebDoc);
@@ -390,7 +389,6 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
// addDocument(alias);
// } else
{
- console.log("Adding ...");
const newDoc = Docs.Create.WebDocument(uriList.split("#annotations:")[0], {// clean hypothes.is URLs that reference a specific annotation (eg. https://en.wikipedia.org/wiki/Cartoon#annotations:t7qAeNbCEeqfG5972KR2Ig)
...options,
title: uriList.split("#annotations:")[0],
@@ -399,8 +397,7 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
_nativeWidth: 850,
useCors: true
});
- console.log(" ... " + newDoc.title);
- console.log(" ... " + addDocument(newDoc) + " " + newDoc.title);
+ addDocument(newDoc);
}
return;
}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 7dcd63b80..febccbfcc 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -75,7 +75,7 @@ export type collectionFreeformViewProps = {
scaleField?: string;
noOverlay?: boolean; // used to suppress docs in the overlay (z) layer (ie, for minimap since overlay doesn't scale)
engineProps?: any;
- dontRenderDocuments?: boolean; // used for annotation overlays which need to distribute documents into different freeformviews with different mixBlendModes depending on whether they are trnasparent or not.
+ dontRenderDocuments?: boolean; // used for annotation overlays which need to distribute documents into different freeformviews with different mixBlendModes depending on whether they are transparent or not.
// However, this screws up interactions since only the top layer gets events. so we render the freeformview a 3rd time with all documents in order to get interaction events (eg., marquee) but we don't actually want to display the documents.
};
@@ -1472,7 +1472,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
getContainerTransform={this.getContainerTransform}
getTransform={this.getTransform}
isAnnotationOverlay={this.isAnnotationOverlay}>
- <div ref={this._marqueeRef} style={{ display: this.props.dontRenderDocuments ? "none" : undefined }}>
+ <div className="marqueeView-div" ref={this._marqueeRef} style={{ opacity: this.props.dontRenderDocuments ? 0 : undefined }}>
{this.layoutDoc._backgroundGridShow ? this.backgroundGrid : (null)}
<CollectionFreeFormViewPannableContents
isAnnotationOverlay={this.isAnnotationOverlay}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index be6a86445..b561dc09c 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -814,7 +814,11 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
screenToLocal = () => this.props.ScreenToLocalTransform().translate(0, -this.headerMargin);
contentScaling = () => this.ContentScale;
onClickFunc = () => this.onClickHandler;
- setHeight = (height: number) => this.layoutDoc._height = height;
+ setHeight = (height: number) => {
+ if (this.props.renderDepth !== -1) {
+ this.layoutDoc._height = height;
+ }
+ }
setContentView = action((view: { getAnchor?: () => Doc, forward?: () => boolean, back?: () => boolean }) => this._componentView = view);
isContentActive = (outsideReaction?: boolean) => {
return CurrentUserUtils.SelectedTool !== InkTool.None ||
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index 37d716993..9956cc36b 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -58,8 +58,10 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
private _sidebarRef = React.createRef<SidebarAnnos>();
private _searchRef = React.createRef<HTMLInputElement>();
private _searchString = "";
+ @observable private _webUrl = ""; // url of the src parameter of the embedded iframe but not necessarily the rendered page - eg, when following a link, the rendered page changes but we don't wan the src parameter to also change as that would cause an unnecessary re-render.
+ @observable private _hackHide = false; // apparently changing the value of the 'sandbox' prop doesn't necessarily apply it to the active iframe. so thisforces the ifrmae to be rebuilt when allowScripts is toggled
@observable private _searching: boolean = false;
- @observable _showSidebar = false;
+ @observable private _showSidebar = false;
@observable private _scrollTimer: any;
@observable private _overlayAnnoInfo: Opt<Doc>;
@observable private _marqueeing: number[] | undefined;
@@ -79,6 +81,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
super(props);
Doc.SetNativeWidth(this.dataDoc, Doc.NativeWidth(this.dataDoc) || 850);
Doc.SetNativeHeight(this.dataDoc, Doc.NativeHeight(this.dataDoc) || this.Document[HeightSym]() / this.Document[WidthSym]() * 850);
+ runInAction(() => this._webUrl = this._url); // setting the weburl will change the src parameter of the embedded iframe and force a navigation to it.
}
@action
@@ -239,7 +242,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
MarqueeAnnotator.clearAnnotations(this._savedAnnotations);
this._marqueeing = [e.clientX * scale + mainContBounds.translateX,
e.clientY * scale + mainContBounds.translateY - NumCast(this.layoutDoc._scrollTop) * scale];
- if (word) {
+ 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;
@@ -269,9 +272,24 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
@action
iframeLoaded = (e: any) => {
const iframe = this._iframe;
- this._iframe?.contentDocument?.addEventListener("pointerup", this.iframeUp);
+ 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) {
+ const matches = requrlraw.match(/[^a-zA-z]q=[^&]*/g);
+ const newsearch = matches?.lastElement()!;
+ if (matches) {
+ requrlraw = requrlraw.substring(0, requrlraw.indexOf(newsearch));
+ for (let i = 1; i < Array.from(matches)?.length; i++) {
+ requrlraw = requrlraw.replace(matches[i], "");
+ }
+ }
+ requrlraw = requrlraw.replace(/q=[^&]*/, newsearch.substring(1)).replace("search&", "search?").replace("?gbv=1", "");
+ }
+ this.submitURL(requrlraw, undefined, true);
+ }
if (iframe?.contentDocument) {
- iframe?.contentDocument.addEventListener("pointerdown", this.iframeDown);
+ iframe.contentDocument.addEventListener("pointerup", this.iframeUp);
+ iframe.contentDocument.addEventListener("pointerdown", this.iframeDown);
this._scrollHeight = Math.max(this.scrollHeight, iframe?.contentDocument.body.scrollHeight);
setTimeout(action(() => this._scrollHeight = Math.max(this.scrollHeight, iframe?.contentDocument?.body.scrollHeight || 0)), 5000);
const initialScroll = this._initialScroll;
@@ -281,13 +299,15 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
this._initialScroll = undefined;
}
iframe.setAttribute("enable-annotation", "true");
- iframe.contentDocument.addEventListener("click", undoBatch(action(e => {
+ iframe.contentDocument.addEventListener("click", undoBatch(action((e: MouseEvent) => {
let href = "";
- for (let ele = e.target; ele; ele = ele.parentElement) {
+ for (let ele = e.target as any; ele; ele = ele.parentElement) {
href = (typeof (ele.href) === "string" ? ele.href : ele.href?.baseVal) || ele.parentElement?.href || href;
}
- if (href && this.webField?.origin) {
- this.submitURL(href.replace(Utils.prepend(""), this.webField?.origin));
+ const origin = this.webField?.origin;
+ if (href && origin) {
+ e.stopPropagation();
+ setTimeout(() => this.submitURL(href.replace(Utils.prepend(""), origin)));
if (this._outerRef.current) {
this._outerRef.current.scrollTop = NumCast(this.layoutDoc._scrollTop);
this._outerRef.current.scrollLeft = 0;
@@ -338,8 +358,15 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
const future = Cast(this.dataDoc[this.fieldKey + "-future"], listSpec("string"), []);
const history = Cast(this.dataDoc[this.fieldKey + "-history"], listSpec("string"), []);
if (future.length) {
+ const curUrl = this._url;
this.dataDoc[this.fieldKey + "-history"] = new List<string>([...history, this._url]);
this.dataDoc[this.fieldKey] = new WebField(new URL(future.pop()!));
+ if (this._webUrl === this._url) {
+ this._webUrl = curUrl;
+ setTimeout(action(() => this._webUrl = this._url));
+ } else {
+ this._webUrl = this._url;
+ }
return true;
}
return false;
@@ -350,10 +377,16 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
const future = Cast(this.dataDoc[this.fieldKey + "-future"], listSpec("string"));
const history = Cast(this.dataDoc[this.fieldKey + "-history"], listSpec("string"), []);
if (history.length) {
+ const curUrl = this._url;
if (future === undefined) this.dataDoc[this.fieldKey + "-future"] = new List<string>([this._url]);
else this.dataDoc[this.fieldKey + "-future"] = new List<string>([...future, this._url]);
this.dataDoc[this.fieldKey] = new WebField(new URL(history.pop()!));
- console.log(this._urlHash);
+ if (this._webUrl === this._url) {
+ this._webUrl = curUrl;
+ setTimeout(action(() => this._webUrl = this._url));
+ } else {
+ this._webUrl = this._url;
+ }
return true;
}
return false;
@@ -362,9 +395,8 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
static urlHash = (s: string) => {
return Math.abs(s.split('').reduce((a: any, b: any) => { a = ((a << 5) - a) + b.charCodeAt(0); return a & a; }, 0));
}
-
@action
- submitURL = (newUrl?: string, preview?: boolean) => {
+ submitURL = (newUrl?: string, preview?: boolean, dontUpdateIframe?: boolean) => {
if (!newUrl) return;
if (!newUrl.startsWith("http")) newUrl = "http://" + newUrl;
try {
@@ -376,7 +408,10 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
this.layoutDoc._scrollTop = 0;
future && (future.length = 0);
}
- if (!preview) this.dataDoc[this.fieldKey] = new WebField(new URL(newUrl));
+ if (!preview) {
+ this.dataDoc[this.fieldKey] = new WebField(new URL(newUrl));
+ !dontUpdateIframe && (this._webUrl = this._url);
+ }
} catch (e) {
console.log("WebBox URL error:" + this._url);
}
@@ -430,6 +465,15 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
if (!cm.findByDescription("Options...")) {
!Doc.UserDoc().noviceMode && funcs.push({ description: (this.layoutDoc.useCors ? "Don't Use" : "Use") + " Cors", event: () => this.layoutDoc.useCors = !this.layoutDoc.useCors, icon: "snowflake" });
funcs.push({
+ description: (this.layoutDoc.allowScripts ? "Prevent" : "Allow") + " Scripts", event: () => {
+ this.layoutDoc.allowScripts = !this.layoutDoc.allowScripts;
+ if (this._iframe) {
+ runInAction(() => this._hackHide = true);
+ setTimeout(action(() => this._hackHide = false));
+ }
+ }, icon: "snowflake"
+ });
+ funcs.push({
description: (!this.layoutDoc.forceReflow ? "Force" : "Prevent") + " Reflow", event: () => {
const nw = !this.layoutDoc.forceReflow ? undefined : Doc.NativeWidth(this.layoutDoc) - this.sidebarWidth() / (this.props.scaling?.() || 1);
this.layoutDoc.forceReflow = !nw;
@@ -468,18 +512,19 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
}
@computed get urlContent() {
+ if (this._hackHide) return (null);
const field = this.dataDoc[this.props.fieldKey];
let view;
if (field instanceof HtmlField) {
view = <span className="webBox-htmlSpan" dangerouslySetInnerHTML={{ __html: field.html }} />;
} else if (field instanceof WebField) {
- const url = this.layoutDoc.useCors ? Utils.CorsProxy(this._url) : this._url;
+ const url = this.layoutDoc.useCors ? Utils.CorsProxy(this._webUrl) : this._webUrl;
view = <iframe className="webBox-iframe" enable-annotation={"true"}
style={{ pointerEvents: this._scrollTimer ? "none" : undefined }}
ref={action((r: HTMLIFrameElement | null) => this._iframe = r)} src={url} onLoad={this.iframeLoaded}
// the 'allow-top-navigation' and 'allow-top-navigation-by-user-activation' attributes are left out to prevent iframes from redirecting the top-level Dash page
// sandbox={"allow-forms allow-modals allow-orientation-lock allow-pointer-lock allow-popups allow-popups-to-escape-sandbox allow-presentation allow-same-origin allow-scripts"} />;
- sandbox={"allow-forms allow-modals allow-orientation-lock allow-pointer-lock allow-popups allow-popups-to-escape-sandbox allow-presentation allow-same-origin"} />;
+ sandbox={`${this.layoutDoc.allowScripts ? "allow-scripts" : ""} allow-forms allow-modals allow-orientation-lock allow-pointer-lock allow-popups allow-popups-to-escape-sandbox allow-presentation allow-same-origin`} />;
} else {
view = <iframe className="webBox-iframe" enable-annotation={"true"}
style={{ pointerEvents: this._scrollTimer ? "none" : undefined }} // if we allow pointer events when scrolling is on, then reversing direction does not work smoothly
@@ -615,12 +660,12 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
moveDocument={this.moveDocument}
addDocument={this.sidebarAddDocument}
styleProvider={this.childStyleProvider}
- pointerEvents={CurrentUserUtils.SelectedTool !== InkTool.None || this._isAnnotating || SnappingManager.GetIsDragging() ? "all" : "none"} />;
+ childPointerEvents={this.props.isContentActive() ? "all" : undefined}
+ pointerEvents={this._isAnnotating || SnappingManager.GetIsDragging() ? "all" : "none"} />;
return (
<div className="webBox" ref={this._mainCont}
style={{ pointerEvents: this.pointerEvents() }} >
<div className={`webBox-container`} style={{ pointerEvents }} onContextMenu={this.specificContextMenu}>
- <base target="_blank" />
<div className={"webBox-outerContent"} ref={this._outerRef}
style={{
width: `calc(${100 / scale}% - ${this.sidebarWidth() / scale * (this._previewWidth ? scale : 1)}px)`,