aboutsummaryrefslogtreecommitdiff
path: root/src/client/views
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views')
-rw-r--r--src/client/views/LightboxView.tsx5
-rw-r--r--src/client/views/collections/CollectionStackedTimeline.tsx4
-rw-r--r--src/client/views/collections/CollectionStackingView.tsx12
-rw-r--r--src/client/views/collections/TabDocView.tsx29
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx71
-rw-r--r--src/client/views/nodes/CollectionFreeFormDocumentView.tsx2
-rw-r--r--src/client/views/nodes/DocumentView.tsx35
-rw-r--r--src/client/views/nodes/ImageBox.tsx2
-rw-r--r--src/client/views/nodes/PDFBox.tsx2
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.tsx2
10 files changed, 100 insertions, 64 deletions
diff --git a/src/client/views/LightboxView.tsx b/src/client/views/LightboxView.tsx
index eb3d62779..a2088a8fc 100644
--- a/src/client/views/LightboxView.tsx
+++ b/src/client/views/LightboxView.tsx
@@ -89,7 +89,7 @@ export class LightboxView extends React.Component<LightboxViewProps> {
const target = LightboxView.LightboxDocTarget = LightboxView.LightboxFuture?.pop();
const docView = target && DocumentManager.Instance.getLightboxDocumentView(target);
if (docView && target) {
- docView.focus(target, true, 0.9);
+ docView.focus(target, { willZoom: true, scale: 0.9 });
if (LightboxView.LightboxHistory?.lastElement() !== target) LightboxView.LightboxHistory?.push(target);
} else {
if (!target && LightboxView.path.length) {
@@ -120,7 +120,7 @@ export class LightboxView extends React.Component<LightboxViewProps> {
const docView = target && DocumentManager.Instance.getLightboxDocumentView(target);
if (docView && target) {
if (LightboxView.LightboxFuture?.lastElement() !== previous) LightboxView.LightboxFuture?.push(previous!);
- docView.focus(target, true, 0.9);
+ docView.focus(target, { willZoom: true, scale: 0.9 });
} else {
LightboxView.SetLightboxDoc(target);
}
@@ -138,6 +138,7 @@ export class LightboxView extends React.Component<LightboxViewProps> {
if (coll) {
const fieldKey = Doc.LayoutFieldKey(coll);
LightboxView.SetLightboxDoc(coll, [...DocListCast(coll[fieldKey]), ...DocListCast(coll[fieldKey + "-annotations"])]);
+ TabDocView.PinDoc(coll, { hidePresBox: true });
}
setTimeout(() => this.stepForward());
}
diff --git a/src/client/views/collections/CollectionStackedTimeline.tsx b/src/client/views/collections/CollectionStackedTimeline.tsx
index efbab3ede..e3e753902 100644
--- a/src/client/views/collections/CollectionStackedTimeline.tsx
+++ b/src/client/views/collections/CollectionStackedTimeline.tsx
@@ -259,8 +259,8 @@ export class CollectionStackedTimeline extends CollectionSubView<PanZoomDocument
const anchor = observable({ view: undefined as any });
const focusFunc = (doc: Doc, willZoom?: boolean, scale?: number, afterFocus?: (notFocused: boolean) => Promise<boolean>, docTransform?: Transform) => {
this.props.playLink(mark);
- this.props.focus(doc, willZoom, scale, afterFocus, docTransform);
- }
+ this.props.focus(doc, { willZoom, scale, afterFocus, docTransform });
+ };
return {
anchor, view: <DocumentView key="view" {...OmitKeys(this.props, ["NativeWidth", "NativeHeight"]).omit}
ref={action((r: DocumentView | null) => anchor.view = r)}
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 2d03c5279..1d6112745 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -21,7 +21,7 @@ import { ContextMenu } from "../ContextMenu";
import { ContextMenuProps } from "../ContextMenuItem";
import { EditableView } from "../EditableView";
import { CollectionFreeFormDocumentView } from "../nodes/CollectionFreeFormDocumentView";
-import { DocumentView, DocAfterFocusFunc, DocumentViewProps } from "../nodes/DocumentView";
+import { DocumentView, DocumentViewProps, DocFocusOptions } from "../nodes/DocumentView";
import { FieldViewProps } from "../nodes/FieldView";
import { StyleProp } from "../StyleProvider";
import { CollectionMasonryViewFieldRow } from "./CollectionMasonryViewFieldRow";
@@ -168,7 +168,7 @@ export class CollectionStackingView extends CollectionSubView<StackingDocument,
return this.props.addDocTab(doc, where);
}
- focusDocument = (doc: Doc, willZoom?: boolean, scale?: number, afterFocus?: DocAfterFocusFunc, docTransform?: Transform) => {
+ focusDocument = (doc: Doc, options?: DocFocusOptions) => {
Doc.BrushDoc(doc);
Doc.linkFollowHighlight(doc);
@@ -181,9 +181,11 @@ export class CollectionStackingView extends CollectionSubView<StackingDocument,
smoothScroll(focusSpeed = doc.presTransition || doc.presTransition === 0 ? NumCast(doc.presTransition) : 500, this._mainCont!, localTop[1] + this._mainCont!.scrollTop);
}
}
- const endFocus = async (moved: boolean) => afterFocus ? afterFocus(moved) : false;
- this.props.focus(this.rootDoc, willZoom, scale, (didFocus: boolean) =>
- new Promise<boolean>(res => setTimeout(async () => res(await endFocus(didFocus)), focusSpeed)));
+ const endFocus = async (moved: boolean) => options?.afterFocus ? options?.afterFocus(moved) : false;
+ this.props.focus(this.rootDoc, {
+ willZoom: options?.willZoom, scale: options?.scale, afterFocus: (didFocus: boolean) =>
+ new Promise<boolean>(res => setTimeout(async () => res(await endFocus(didFocus)), focusSpeed))
+ });
}
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index d62b8b6f6..4c792186a 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -14,6 +14,7 @@ import { Cast, NumCast, StrCast } from "../../../fields/Types";
import { TraceMobx } from '../../../fields/util';
import { emptyFunction, returnEmptyDoclist, returnFalse, returnTrue, setupMoveUpEvents, Utils } from "../../../Utils";
import { DocServer } from "../../DocServer";
+import { DocUtils } from '../../documents/Documents';
import { DocumentType } from '../../documents/DocumentTypes';
import { CurrentUserUtils } from '../../util/CurrentUserUtils';
import { DocumentManager } from '../../util/DocumentManager';
@@ -23,7 +24,7 @@ import { SnappingManager } from '../../util/SnappingManager';
import { Transform } from '../../util/Transform';
import { undoBatch, UndoManager } from "../../util/UndoManager";
import { LightboxView } from '../LightboxView';
-import { DocAfterFocusFunc, DocumentView, DocumentViewProps } from "../nodes/DocumentView";
+import { DocFocusOptions, DocumentView, DocumentViewProps } from "../nodes/DocumentView";
import { FieldViewProps } from '../nodes/FieldView';
import { PinProps, PresBox, PresMovement } from '../nodes/PresBox';
import { DefaultLayerProvider, DefaultStyleProvider, StyleLayers, StyleProp } from '../StyleProvider';
@@ -34,7 +35,6 @@ import { CollectionViewType } from './CollectionView';
import "./TabDocView.scss";
import React = require("react");
import Color = require('color');
-import { DocUtils } from '../../documents/Documents';
const _global = (window /* browser */ || global /* node */) as any;
interface TabDocViewProps {
@@ -209,7 +209,7 @@ export class TabDocView extends React.Component<TabDocViewProps> {
const tabs = Cast(sublists[0], Doc, null);
const tabdocs = await DocListCastAsync(tabs.data);
runInAction(() => {
- if (!tabdocs?.includes(curPres)) {
+ if (!pinProps?.hidePresBox && !tabdocs?.includes(curPres)) {
tabdocs?.push(curPres); // bcz: Argh! this is annoying. if multiple documents are pinned, this will get called multiple times before the presentation view is drawn. Thus it won't be in the tabdocs list and it will get created multple times. so need to explicilty add the presbox to the list of open tabs
CollectionDockingView.AddSplit(curPres, "right");
}
@@ -279,7 +279,10 @@ export class TabDocView extends React.Component<TabDocViewProps> {
case "close": return CollectionDockingView.CloseSplit(doc, locationParams);
case "fullScreen": return CollectionDockingView.OpenFullScreen(doc);
case "replace": return CollectionDockingView.ReplaceTab(doc, locationParams, this.stack);
- case "lightbox": return LightboxView.AddDocTab(doc, location);
+ case "lightbox": {
+ // TabDocView.PinDoc(doc, { hidePresBox: true });
+ return LightboxView.AddDocTab(doc, location);
+ }
case "inPlace":
case "add":
default:
@@ -357,11 +360,25 @@ export class TabDocView extends React.Component<TabDocViewProps> {
</Tooltip>
</>;
}
- focusFunc = (doc: Doc, willZoom?: boolean, scale?: number, afterFocus?: DocAfterFocusFunc) => {
+ @action
+ focusFunc = (doc: Doc, options?: DocFocusOptions) => {
+ const vals = (!options?.originalTarget || options?.originalTarget === this._document) && this.view?.ComponentView?.freeformData?.(true);
+ if (vals && this._document) {
+ const focusSpeed = 1000;
+ this._document._panX = vals.panX;
+ this._document._panY = vals.panY;
+ this._document._viewScale = vals.scale;
+ this._document._viewTrasition = `transform ${focusSpeed}ms`;
+ setTimeout(action(() => {
+ this._document!._viewTransition = undefined;
+ options?.afterFocus?.(false);
+ }), focusSpeed);
+ } else {
+ options?.afterFocus?.(false);
+ }
if (!this.tab.header.parent._activeContentItem || this.tab.header.parent._activeContentItem !== this.tab.contentItem) {
this.tab.header.parent.setActiveContentItem(this.tab.contentItem); // glr: Panning does not work when this is set - (this line is for trying to make a tab that is not topmost become topmost)
}
- afterFocus?.(false);
}
active = () => this._isActive;
ScreenToLocalTransform = () => {
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 954b6478f..92916b5db 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1,22 +1,23 @@
-import { action, computed, IReactionDisposer, observable, ObservableMap, reaction, runInAction, trace } from "mobx";
+import { action, computed, IReactionDisposer, observable, ObservableMap, reaction, runInAction } from "mobx";
import { observer } from "mobx-react";
import { computedFn } from "mobx-utils";
-import { Doc, DocListCast, HeightSym, Opt, WidthSym, StrListCast } from "../../../../fields/Doc";
+import { Doc, HeightSym, Opt, StrListCast, WidthSym } from "../../../../fields/Doc";
import { collectionSchema, documentSchema } from "../../../../fields/documentSchemas";
import { Id } from "../../../../fields/FieldSymbols";
import { InkData, InkField, InkTool } from "../../../../fields/InkField";
import { List } from "../../../../fields/List";
import { RichTextField } from "../../../../fields/RichTextField";
-import { createSchema, makeInterface, listSpec } from "../../../../fields/Schema";
+import { createSchema, listSpec, makeInterface } from "../../../../fields/Schema";
import { ScriptField } from "../../../../fields/ScriptField";
import { BoolCast, Cast, FieldValue, NumCast, ScriptCast, StrCast } from "../../../../fields/Types";
import { TraceMobx } from "../../../../fields/util";
import { GestureUtils } from "../../../../pen-gestures/GestureUtils";
-import { aggregateBounds, intersectRect, returnFalse, returnOne, returnZero, setupMoveUpEvents, Utils, returnVal, returnTrue } from "../../../../Utils";
+import { aggregateBounds, intersectRect, returnFalse, setupMoveUpEvents, Utils } from "../../../../Utils";
import { CognitiveServices } from "../../../cognitive_services/CognitiveServices";
import { DocServer } from "../../../DocServer";
import { Docs, DocUtils } from "../../../documents/Documents";
import { DocumentType } from "../../../documents/DocumentTypes";
+import { CurrentUserUtils } from "../../../util/CurrentUserUtils";
import { DocumentManager } from "../../../util/DocumentManager";
import { DragManager, dropActionType } from "../../../util/DragManager";
import { HistoryUtil } from "../../../util/History";
@@ -30,13 +31,16 @@ import { undoBatch } from "../../../util/UndoManager";
import { COLLECTION_BORDER_WIDTH } from "../../../views/globalCssVariables.scss";
import { Timeline } from "../../animationtimeline/Timeline";
import { ContextMenu } from "../../ContextMenu";
+import { DocumentDecorations } from "../../DocumentDecorations";
import { ActiveArrowEnd, ActiveArrowStart, ActiveDash, ActiveFillColor, ActiveInkBezierApprox, ActiveInkColor, ActiveInkWidth } from "../../InkingStroke";
-import { CollectionFreeFormDocumentView, CollectionFreeFormDocumentViewProps } from "../../nodes/CollectionFreeFormDocumentView";
-import { DocumentLinksButton } from "../../nodes/DocumentLinksButton";
-import { DocumentViewProps, DocAfterFocusFunc, DocumentView } from "../../nodes/DocumentView";
+import { LightboxView } from "../../LightboxView";
+import { CollectionFreeFormDocumentView } from "../../nodes/CollectionFreeFormDocumentView";
+import { DocFocusOptions, DocumentView, DocumentViewProps } from "../../nodes/DocumentView";
+import { FieldViewProps } from "../../nodes/FieldView";
import { FormattedTextBox } from "../../nodes/formattedText/FormattedTextBox";
import { pageSchema } from "../../nodes/ImageBox";
import { PresBox } from "../../nodes/PresBox";
+import { StyleLayers, StyleProp } from "../../StyleProvider";
import { CollectionDockingView } from "../CollectionDockingView";
import { CollectionSubView } from "../CollectionSubView";
import { CollectionViewType } from "../CollectionView";
@@ -45,12 +49,6 @@ import { CollectionFreeFormRemoteCursors } from "./CollectionFreeFormRemoteCurso
import "./CollectionFreeFormView.scss";
import { MarqueeView } from "./MarqueeView";
import React = require("react");
-import { CurrentUserUtils } from "../../../util/CurrentUserUtils";
-import { StyleProp, StyleLayers } from "../../StyleProvider";
-import { DocumentDecorations } from "../../DocumentDecorations";
-import { FieldViewProps } from "../../nodes/FieldView";
-import { reset } from "colors";
-import { LightboxView } from "../../LightboxView";
export const panZoomSchema = createSchema({
_panX: "number",
@@ -118,8 +116,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
@computed get backgroundActive() { return this.props.layerProvider?.(this.layoutDoc) === false && (this.props.ContainingCollectionView?.active() || this.props.active()); }
@computed get fitToContentVals() {
- return this.fitToContent &&
- {
+ return {
panX: (this.contentBounds.x + this.contentBounds.r) / 2,
panY: (this.contentBounds.y + this.contentBounds.b) / 2,
scale: !this.childDocs.length ? 1 :
@@ -135,9 +132,9 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
private get isAnnotationOverlay() { return this.props.isAnnotationOverlay; }
private get scaleFieldKey() { return this.props.scaleField || "_viewScale"; }
private get borderWidth() { return this.isAnnotationOverlay ? 0 : COLLECTION_BORDER_WIDTH; }
- private panX = () => this.fitToContentVals?.panX ?? NumCast(this.Document._panX);
- private panY = () => this.fitToContentVals?.panY ?? NumCast(this.Document._panY);
- private zoomScaling = () => (this.fitToContentVals?.scale ?? NumCast(this.Document[this.scaleFieldKey], 1)) / this.parentScaling;
+ private panX = () => this.freeformData()?.panX ?? NumCast(this.Document._panX);
+ private panY = () => this.freeformData()?.panY ?? NumCast(this.Document._panY);
+ private zoomScaling = () => (this.freeformData()?.scale ?? NumCast(this.Document[this.scaleFieldKey], 1)) / this.parentScaling;
@computed get cachedCenteringShiftX(): number {
const scaling = this.fitToContent || !this.contentScaling ? 1 : this.contentScaling;
return this.props.isAnnotationOverlay ? 0 : this.props.PanelWidth() / 2 / this.parentScaling / scaling; // shift so pan position is at center of window for non-overlay collections
@@ -860,7 +857,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
else if (ranges.yrange.max <= (panY - panelDim[1] / 2)) panY = ranges.yrange.min - panelDim[1] / 2;
}
}
- if (!this.layoutDoc._lockedTransform || CurrentUserUtils.OverlayDocs.includes(this.Document)) {
+ if (!this.layoutDoc._lockedTransform || LightboxView.LightboxDoc || CurrentUserUtils.OverlayDocs.includes(this.Document)) {
this.Document._viewTransition = panType;
const scale = this.getLocalTransform().inverse().Scale;
const newPanX = Math.min((1 - 1 / scale) * this.nativeWidth, Math.max(0, panX));
@@ -899,7 +896,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
this.layoutDoc._panY = NumCast(this.layoutDoc._panY) - newpan[1];
}
- focusDocument = (doc: Doc, willZoom?: boolean, scale?: number, afterFocus?: DocAfterFocusFunc, docTransform?: Transform) => {
+ focusDocument = (doc: Doc, options?: DocFocusOptions) => {
const state = HistoryUtil.getState();
// TODO This technically isn't correct if type !== "doc", as
@@ -918,23 +915,26 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
const LightboxState = LightboxView.LightboxDoc === this.props.Document && LightboxView.SavedState ? LightboxView.SavedState : undefined;
SelectionManager.DeselectAll();
if (this.props.Document.scrollHeight) {
- this.props.focus(doc, willZoom, scale, afterFocus);
+ this.props.focus(doc, options);
} else {
- const xfToCollection = docTransform ?? Transform.Identity();
+ const xfToCollection = options?.docTransform ?? Transform.Identity();
const layoutdoc = Doc.Layout(doc);
const savedState = { panX: NumCast(this.Document._panX), panY: NumCast(this.Document._panY), scale: this.Document[this.scaleFieldKey], transition: this.Document._viewTransition };
const newState = HistoryUtil.getState();
- const cantTransform = this.props.isAnnotationOverlay || this.rootDoc._isGroup || this.layoutDoc._lockedTransform;
- const { panX, panY } = cantTransform ? savedState : this.setPanIntoView(layoutdoc, xfToCollection, willZoom ? scale || .75 : undefined);
+ const cantTransform = this.props.isAnnotationOverlay || ((this.rootDoc._isGroup || this.layoutDoc._lockedTransform) && !LightboxView.LightboxDoc);
+ const { panX, panY, scale } = cantTransform ? savedState : this.setPanIntoView(layoutdoc, xfToCollection, options?.willZoom ? options?.scale || .75 : undefined);
if (!cantTransform) { // only pan and zoom to focus on a document if the document is not an annotation in an annotation overlay collection
newState.initializers![this.Document[Id]] = { panX: panX, panY: panY };
HistoryUtil.pushState(newState);
}
// focus on the document in the collection
- const didMove = !doc.z && (panX !== savedState.panX || panY !== savedState.panY);
+ const didMove = !doc.z && (panX !== savedState.panX || panY !== savedState.panY || scale !== undefined);
const focusSpeed = didMove ? (doc.focusSpeed !== undefined ? Number(doc.focusSpeed) : 500) : 0;
// glr: freeform transform speed can be set by adjusting presTransition field - needs a way of knowing when presentation is not active...
- if (didMove) this.setPan(panX, panY, `transform ${focusSpeed}ms`, true); // docs that are floating in their collection can't be panned to from their collection -- need to propagate the pan to a parent freeform somehow
+ if (didMove) {
+ this.setPan(panX, panY, `transform ${focusSpeed}ms`, true); // docs that are floating in their collection can't be panned to from their collection -- need to propagate the pan to a parent freeform somehow
+ options?.willZoom && (this.Document[this.scaleFieldKey] = scale);
+ }
Doc.BrushDoc(this.rootDoc);
!doc.hidden && Doc.linkFollowHighlight(doc);
@@ -942,7 +942,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
// focus on this collection within its parent view. the parent view after focusing determines whether to reset the view change within the collection
const endFocus = async (moved: boolean) => {
doc.hidden && Doc.UnHighlightDoc(doc);
- const resetView = afterFocus ? await afterFocus(moved) : false;
+ const resetView = options?.afterFocus ? await options?.afterFocus(moved) : false;
if (resetView) {
const restoreState = LightboxView.LightboxDoc !== this.props.Document && LightboxState ? LightboxState : savedState;
this.Document._panX = restoreState.panX;
@@ -959,8 +959,11 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
new Transform(NumCast(this.rootDoc.x) + this.rootDoc[WidthSym]() / 2 - NumCast(this.rootDoc._panX),
NumCast(this.rootDoc.y) + this.rootDoc[HeightSym]() / 2 - NumCast(this.rootDoc._panY), 1);
- this.props.focus(cantTransform ? doc : this.rootDoc, willZoom, scale, (didFocus: boolean) =>
- new Promise<boolean>(res => setTimeout(async () => res(await endFocus(didMove || didFocus)), Math.max(0, focusSpeed - (Date.now() - startTime)))), xf);
+ this.props.focus(cantTransform ? doc : this.rootDoc, {
+ ...options, docTransform: xf,
+ afterFocus: (didFocus: boolean) => new Promise<boolean>(res =>
+ setTimeout(async () => res(await endFocus(didMove || didFocus)), Math.max(0, focusSpeed - (Date.now() - startTime))))
+ });
}
}
@@ -973,8 +976,12 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
if (scale) {
const maxZoom = 2; // sets the limit for how far we will zoom. this is useful for preventing small text boxes from filling the screen. So probably needs to be more sophisticated to consider more about the target and context
- this.Document[this.scaleFieldKey] = Math.min(maxZoom, scale * Math.min(this.props.PanelWidth() / Math.abs(pt2[0] - pt[0]), this.props.PanelHeight() / Math.abs(pt2[1] - pt[1])));
- return { panX: (bounds.left + bounds.right) / 2, panY: (bounds.top + bounds.bot) / 2 };
+
+ return {
+ panX: (bounds.left + bounds.right) / 2,
+ panY: (bounds.top + bounds.bot) / 2,
+ scale: Math.min(maxZoom, scale * Math.min(this.props.PanelWidth() / Math.abs(pt2[0] - pt[0]), this.props.PanelHeight() / Math.abs(pt2[1] - pt[1])))
+ };
} else {
const cx = NumCast(this.layoutDoc._panX);
const cy = NumCast(this.layoutDoc._panY);
@@ -1188,7 +1195,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
this.Document._useClusters && !this._clusterSets.length && this.childDocs.length && this.updateClusters(true);
return elements;
}
- freeformData = () => { return this.fitToContentVals; }
+ freeformData = (force?: boolean) => this.fitToContent || force ? this.fitToContentVals : undefined;
@action
componentDidMount() {
super.componentDidMount?.();
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 4b0422ed3..e93d7ff72 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -153,7 +153,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
panelWidth = () => (this.sizeProvider?.width || this.props.PanelWidth?.());
panelHeight = () => (this.sizeProvider?.height || this.props.PanelHeight?.());
screenToLocalTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-this.X, -this.Y);
- focusDoc = (doc: Doc) => this.props.focus(doc, false);
+ focusDoc = (doc: Doc) => this.props.focus(doc);
returnThis = () => this;
render() {
TraceMobx();
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 9801de1a2..9d91311f6 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -1,6 +1,6 @@
import { action, computed, observable, runInAction } from "mobx";
import { observer } from "mobx-react";
-import { AclAdmin, AclEdit, AclPrivate, DataSym, Doc, DocListCast, Field, Opt, StrListCast, HeightSym } from "../../../fields/Doc";
+import { AclAdmin, AclEdit, AclPrivate, DataSym, Doc, DocListCast, Field, Opt, StrListCast } from "../../../fields/Doc";
import { Document } from '../../../fields/documentSchemas';
import { Id } from '../../../fields/FieldSymbols';
import { InkTool } from '../../../fields/InkField';
@@ -37,13 +37,20 @@ import { DocumentLinksButton } from './DocumentLinksButton';
import "./DocumentView.scss";
import { FieldViewProps } from "./FieldView";
import { LinkAnchorBox } from './LinkAnchorBox';
+import { LinkDocPreview } from "./LinkDocPreview";
import { PresBox } from './PresBox';
import { RadialMenu } from './RadialMenu';
import React = require("react");
-import { LinkDocPreview } from "./LinkDocPreview";
+export interface DocFocusOptions {
+ originalTarget?: Doc;
+ willZoom?: boolean;
+ scale?: number;
+ afterFocus?: DocAfterFocusFunc;
+ docTransform?: Transform;
+}
export type DocAfterFocusFunc = (notFocused: boolean) => Promise<boolean>;
-export type DocFocusFunc = (doc: Doc, willZoom?: boolean, scale?: number, afterFocus?: DocAfterFocusFunc, docTransform?: Transform) => void;
+export type DocFocusFunc = (doc: Doc, options?: DocFocusOptions) => void;
export type StyleProviderFunc = (doc: Opt<Doc>, props: Opt<DocumentViewProps | FieldViewProps>, property: string) => any;
export interface DocComponentView {
getAnchor?: () => Doc;
@@ -52,7 +59,7 @@ export interface DocComponentView {
forward?: () => boolean;
url?: () => string;
submitURL?: (url: string) => boolean;
- freeformData?: () => Opt<{ panX: number, panY: number, scale: number }>;
+ freeformData?: (force?: boolean) => Opt<{ panX: number, panY: number, scale: number }>;
}
export interface DocumentViewSharedProps {
renderDepth: number;
@@ -376,11 +383,13 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
}
}
- focus = (doc: Doc, willZoom?: boolean, scale?: number, afterFocus?: DocAfterFocusFunc, docTransform?: Transform) => {
+ focus = (doc: Doc, options?: DocFocusOptions) => {
const focusSpeed = this._componentView?.scrollFocus?.(doc, !LinkDocPreview.LinkInfo); // bcz: smooth parameter should really be passed into focus() instead of inferred here
- const endFocus = focusSpeed === undefined ? afterFocus : async (moved: boolean) => afterFocus ? afterFocus(true) : false;
- this.props.focus(docTransform ? doc : this.rootDoc, willZoom, scale, (didFocus: boolean) =>
- new Promise<boolean>(res => setTimeout(async () => res(endFocus ? await endFocus(didFocus) : false), focusSpeed ?? 0)), docTransform);
+ const endFocus = focusSpeed === undefined ? options?.afterFocus : async (moved: boolean) => options?.afterFocus ? options?.afterFocus(true) : false;
+ this.props.focus(options?.docTransform ? doc : this.rootDoc, {
+ ...options, afterFocus: (didFocus: boolean) =>
+ new Promise<boolean>(res => setTimeout(async () => res(endFocus ? await endFocus(didFocus) : false), focusSpeed ?? 0))
+ });
}
onClick = action((e: React.MouseEvent | React.PointerEvent) => {
@@ -439,7 +448,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
} else clickFunc();
} else if (this.Document["onClick-rawScript"] && !StrCast(Doc.LayoutField(this.layoutDoc))?.includes("ScriptingBox")) {// bcz: hack? don't edit a script if you're clicking on a scripting box itself
this.props.addDocTab(DocUtils.makeCustomViewClicked(Doc.MakeAlias(this.props.Document), undefined, "onClick"), "add:right");
- } else if (this.allLinks && this.Document.isLinkButton && !e.shiftKey && !e.ctrlKey) {
+ } else if (this.allLinks && this.Document.isLinkButton && !e.shiftKey && !e.ctrlKey && !(e.nativeEvent as any).formattedHandled) {
this.allLinks.length && LinkManager.FollowLink(undefined, this.props.Document, this.props, e.altKey);
} else {
if ((this.layoutDoc.onDragStart || this.props.Document.rootDocument) && !(e.ctrlKey || e.button > 0)) { // onDragStart implies a button doc that we don't want to select when clicking. RootDocument & isTemplaetForField implies we're clicking on part of a template instance and we want to select the whole template, not the part
@@ -575,7 +584,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
const linkSource = de.complete.annoDragData ? de.complete.annoDragData.annotationDocument : de.complete.linkDragData ? de.complete.linkDragData.linkSourceDocument : undefined;
if (linkSource && linkSource !== this.props.Document) {
e.stopPropagation();
- const dropDoc = this._componentView?.getAnchor() || this.rootDoc;
+ const dropDoc = this._componentView?.getAnchor?.() || this.rootDoc;
if (de.complete.annoDragData) de.complete.annoDragData.dropDocument = dropDoc;
de.complete.linkDocument = DocUtils.MakeLink({ doc: linkSource }, { doc: dropDoc }, "link", undefined, undefined, undefined, [de.x, de.y]);
}
@@ -718,7 +727,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
screenToLocal = () => this.props.ScreenToLocalTransform().translate(0, -this.headerMargin);
contentScaling = () => this.ContentScale;
onClickFunc = () => this.onClickHandler;
- setContentView = (view: { getAnchor: () => Doc, forward?: () => boolean, back?: () => boolean }) => this._componentView = view;
+ setContentView = (view: { getAnchor?: () => Doc, forward?: () => boolean, back?: () => boolean }) => this._componentView = view;
@observable contentsActive: () => boolean = returnFalse;
@action setContentsActive = (setActive: () => boolean) => this.contentsActive = setActive;
@computed get contents() {
@@ -918,8 +927,8 @@ export class DocumentView extends React.Component<DocumentViewProps> {
toggleNativeDimensions = () => this.docView && Doc.toggleNativeDimensions(this.layoutDoc, this.docView.ContentScale, this.props.PanelWidth(), this.props.PanelHeight());
contentsActive = () => this.docView?.contentsActive();
- focus = (doc: Doc, willZoom?: boolean, scale?: number, afterFocus?: DocAfterFocusFunc) => {
- return this.docView?.focus(doc, willZoom, scale, afterFocus);
+ focus = (doc: Doc, options?: DocFocusOptions) => {
+ return this.docView?.focus(doc, options);
}
getBounds = () => {
if (!this.docView || !this.docView.ContentDiv || this.docView.props.renderDepth === 0 || this.docView.props.treeViewDoc || Doc.AreProtosEqual(this.props.Document, Doc.UserDoc())) {
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index 441d6232a..74bff2bfe 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -152,7 +152,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps, ImageD
});
}
@undoBatch
- resolution = () => this.layoutDoc._showFullRes = !this.layoutDoc._showFullRes;
+ resolution = () => this.layoutDoc._showFullRes = !this.layoutDoc._showFullRes
@undoBatch
rotate = action(() => {
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index b941c07f6..33147e7f3 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -138,7 +138,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps, PdfDocum
this.scrollFocus(this.initialScrollTarget, false);
this.initialScrollTarget = undefined;
}
- };
+ }
searchStringChanged = (e: React.ChangeEvent<HTMLInputElement>) => this._searchString = e.currentTarget.value;
settingsPanel() {
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index 9f9f11ab5..a63e0daef 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -1456,7 +1456,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
}
}
if ((e.nativeEvent as any).formattedHandled) { e.stopPropagation(); return; }
- (e.nativeEvent as any).formattedHandled = true;
+ this.props.isSelected(true) && ((e.nativeEvent as any).formattedHandled = true);
if (this.props.isSelected(true)) { // if text box is selected, then it consumes all click events
// e.stopPropagation(); // bcz: not sure why this was here. We need to allow the DocumentView to get clicks to process doubleClicks