From d9ec489c2f549c4aef0b3f458abfda5bb11e7188 Mon Sep 17 00:00:00 2001 From: bobzel Date: Fri, 12 Feb 2021 22:25:40 -0500 Subject: changed audio video annotation to use only timecodeToShow/timecodeToHide. distinguish timeline annotation from video frame annotations with _timelineLabel field. Lightbox improvements to restore original camera values and to use fitContentsToDoc for collections --- src/client/views/collections/CollectionStackedTimeline.tsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'src/client/views/collections/CollectionStackedTimeline.tsx') diff --git a/src/client/views/collections/CollectionStackedTimeline.tsx b/src/client/views/collections/CollectionStackedTimeline.tsx index d4eb66fcc..968ff3cd8 100644 --- a/src/client/views/collections/CollectionStackedTimeline.tsx +++ b/src/client/views/collections/CollectionStackedTimeline.tsx @@ -31,7 +31,6 @@ export type CollectionStackedTimelineProps = { isChildActive: () => boolean; startTag: string; endTag: string; - fieldKeySuffix?: string; }; @observer @@ -47,7 +46,6 @@ export class CollectionStackedTimeline extends CollectionSubView ({ level: this.getLevel(anchor, overlaps), anchor })); + const drawAnchors = this.childDocs.map(anchor => ({ level: this.getLevel(anchor, overlaps), anchor })); const maxLevel = overlaps.reduce((m, o) => Math.max(m, o.level), 0) + 2; const isActive = this.props.isChildActive() || this.props.isSelected(false); return
this._timeline = timeline} -- cgit v1.2.3-70-g09d2 From f79e47041928648d0ad9ffb93ef053bde98c1622 Mon Sep 17 00:00:00 2001 From: bobzel Date: Sat, 13 Feb 2021 22:42:41 -0500 Subject: fixed videobox focus issues when following a link so that video is focused in frame before annotation is focused. --- src/client/views/collections/CollectionStackedTimeline.tsx | 7 ++++++- src/client/views/nodes/DocumentView.tsx | 1 + src/client/views/nodes/VideoBox.tsx | 1 - 3 files changed, 7 insertions(+), 2 deletions(-) (limited to 'src/client/views/collections/CollectionStackedTimeline.tsx') diff --git a/src/client/views/collections/CollectionStackedTimeline.tsx b/src/client/views/collections/CollectionStackedTimeline.tsx index 968ff3cd8..efbab3ede 100644 --- a/src/client/views/collections/CollectionStackedTimeline.tsx +++ b/src/client/views/collections/CollectionStackedTimeline.tsx @@ -17,6 +17,7 @@ import { CollectionSubView } from "../collections/CollectionSubView"; import { DocumentView } from "../nodes/DocumentView"; import { LabelBox } from "../nodes/LabelBox"; import "./CollectionStackedTimeline.scss"; +import { Transform } from "../../util/Transform"; type PanZoomDocument = makeInterface<[]>; const PanZoomDocument = makeInterface(); @@ -256,6 +257,10 @@ export class CollectionStackedTimeline extends CollectionSubView ScriptField), doublescript: undefined | (() => ScriptField), x: number, y: number, width: number, height: number) { const anchor = observable({ view: undefined as any }); + const focusFunc = (doc: Doc, willZoom?: boolean, scale?: number, afterFocus?: (notFocused: boolean) => Promise, docTransform?: Transform) => { + this.props.playLink(mark); + this.props.focus(doc, willZoom, scale, afterFocus, docTransform); + } return { anchor, view: anchor.view = r)} @@ -267,7 +272,7 @@ export class CollectionStackedTimeline extends CollectionSubView width} PanelHeight={() => height} ScreenToLocalTransform={() => this.props.ScreenToLocalTransform().translate(-x, -y)} - focus={() => this.props.playLink(mark)} + focus={focusFunc} parentActive={out => this.props.isSelected(out) || this.props.isChildActive()} rootSelected={returnFalse} onClick={script} diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 7ba0d7043..9801de1a2 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -645,6 +645,7 @@ export class DocumentViewInternal extends DocComponent this.Document.onClick = ScriptField.MakeScript(`toggleDetail(self, "${this.Document.layoutKey}")`), icon: "concierge-bell" }); + onClicks.push({ description: (this.Document.followLinkZoom ? "Don't" : "") + " zoom following link", event: () => this.Document.followLinkZoom = !this.Document.followLinkZoom, icon: this.Document.ignoreClick ? "unlock" : "lock" }); if (!this.Document.annotationOn) { const options = cm.findByDescription("Options..."); diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx index 6d0a200cb..435563255 100644 --- a/src/client/views/nodes/VideoBox.tsx +++ b/src/client/views/nodes/VideoBox.tsx @@ -496,7 +496,6 @@ export class VideoBox extends ViewBoxAnnotatableComponent Date: Sun, 14 Feb 2021 18:29:00 -0500 Subject: fixes to focus()'s api and extension to allow focusing on a Tab's contents. --- src/client/documents/Documents.ts | 7 +-- src/client/util/DocumentManager.ts | 38 ++++++------ src/client/util/LinkManager.ts | 28 +++++---- src/client/views/LightboxView.tsx | 5 +- .../collections/CollectionStackedTimeline.tsx | 4 +- .../views/collections/CollectionStackingView.tsx | 12 ++-- src/client/views/collections/TabDocView.tsx | 29 +++++++-- .../collectionFreeForm/CollectionFreeFormView.tsx | 71 ++++++++++++---------- .../views/nodes/CollectionFreeFormDocumentView.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 35 +++++++---- src/client/views/nodes/ImageBox.tsx | 2 +- src/client/views/nodes/PDFBox.tsx | 2 +- .../views/nodes/formattedText/FormattedTextBox.tsx | 2 +- 13 files changed, 139 insertions(+), 98 deletions(-) (limited to 'src/client/views/collections/CollectionStackedTimeline.tsx') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index d72efb1b4..fee2679b6 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -35,6 +35,7 @@ import { AudioBox } from "../views/nodes/AudioBox"; import { ColorBox } from "../views/nodes/ColorBox"; import { ComparisonBox } from "../views/nodes/ComparisonBox"; import { DocHolderBox } from "../views/nodes/DocHolderBox"; +import { DocFocusOptions } from "../views/nodes/DocumentView"; import { FilterBox } from "../views/nodes/FilterBox"; import { FontIconBox } from "../views/nodes/FontIconBox"; import { FormattedTextBox } from "../views/nodes/formattedText/FormattedTextBox"; @@ -55,8 +56,6 @@ import { PresElementBox } from "../views/presentationview/PresElementBox"; import { SearchBox } from "../views/search/SearchBox"; import { DashWebRTCVideo } from "../views/webcam/DashWebRTCVideo"; import { DocumentType } from "./DocumentTypes"; -import { DocAfterFocusFunc } from "../views/nodes/DocumentView"; -import { Transform } from "../util/Transform"; const path = require('path'); const defaultNativeImageDim = Number(DFLT_IMAGE_NATIVE_DIM.replace("px", "")); @@ -1020,8 +1019,8 @@ export namespace DocUtils { }); } - export function DefaultFocus(doc: Doc, willZoom?: boolean, scale?: number, afterFocus?: DocAfterFocusFunc, docTransform?: Transform) { - afterFocus?.(false); + export function DefaultFocus(doc: Doc, options?: DocFocusOptions) { + options?.afterFocus?.(false); } export let ActiveRecordings: AudioBox[] = []; diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index d2251583c..dd59efa41 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -139,9 +139,11 @@ export class DocumentManager { closeContextIfNotFound: boolean = false, // after opening a context where the document should be, this determines whether the context should be closed if the Doc isn't actually there originatingDoc: Opt = undefined, // doc that initiated the display of the target odoc finished?: () => void, + originalTarget?: Doc ): Promise => { + originalTarget = originalTarget ?? targetDoc; const getFirstDocView = LightboxView.LightboxDoc ? DocumentManager.Instance.getLightboxDocumentView : DocumentManager.Instance.getFirstDocumentView; - let docView = getFirstDocView(targetDoc, originatingDoc); + const docView = getFirstDocView(targetDoc, originatingDoc); const highlight = () => { const finalDocView = getFirstDocView(targetDoc); finalDocView && Doc.linkFollowHighlight(finalDocView.rootDoc); @@ -166,15 +168,16 @@ export class DocumentManager { const targetDocContext = contextDoc || annotatedDoc; const targetDocContextView = targetDocContext && getFirstDocView(targetDocContext); if (!docView && targetDoc.type === DocumentType.TEXTANCHOR && rtfView) { - rtfView.focus(targetDoc, false); + rtfView.focus(targetDoc); } else if (docView) { - docView.props.focus(targetDoc, willZoom, undefined, (didFocus: boolean) => - new Promise(res => { - focusAndFinish(didFocus); - res(); - }) - ); + docView.props.focus(targetDoc, { + originalTarget, willZoom, afterFocus: (didFocus: boolean) => + new Promise(res => { + focusAndFinish(didFocus); + res(); + }) + }); } else { if (!targetDocContext) { // we don't have a view and there's no context specified ... create a new view of the target using the dockFunc or default createViewFunc(Doc.BrushDoc(targetDoc), finished); // bcz: should we use this?: Doc.MakeAlias(targetDoc))); @@ -182,7 +185,7 @@ export class DocumentManager { } else { // otherwise try to get a view of the context of the target if (targetDocContextView) { // we found a context view and aren't forced to create a new one ... focus on the context first.. targetDocContext._viewTransition = "transform 500ms"; - targetDocContextView.props.focus(targetDocContextView.rootDoc, willZoom); + targetDocContextView.props.focus(targetDocContextView.rootDoc, { willZoom }); // now find the target document within the context if (targetDoc._timecodeToShow) { // if the target has a timecode, it should show up once the (presumed) video context scrubs to the display timecode; @@ -192,12 +195,13 @@ export class DocumentManager { const findView = (delay: number) => { const retryDocView = getFirstDocView(targetDoc); // test again for the target view snce we presumably created the context above by focusing on it if (retryDocView) { // we found the target in the context - retryDocView.props.focus(targetDoc, willZoom, undefined, (didFocus: boolean) => - new Promise(res => { - focusAndFinish(didFocus); - res(); - }) - ); // focus on the target in the context + retryDocView.props.focus(targetDoc, { + willZoom, afterFocus: (didFocus: boolean) => + new Promise(res => { + focusAndFinish(didFocus); + res(); + }) + }); // focus on the target in the context highlight(); } else if (delay > 1500) { // we didn't find the target, so it must have moved out of the context. Go back to just creating it. @@ -213,7 +217,7 @@ export class DocumentManager { findView(0); } } else { // there's no context view so we need to create one first and try again when that finishes - const finishFunc = () => this.jumpToDocument(targetDoc, true, createViewFunc, docContext, linkDoc, true /* if we don't find the target, we want to get rid of the context just created */, undefined, finished); + const finishFunc = () => this.jumpToDocument(targetDoc, true, createViewFunc, docContext, linkDoc, true /* if we don't find the target, we want to get rid of the context just created */, undefined, finished, originalTarget); createViewFunc(targetDocContext, // after creating the context, this calls the finish function that will retry looking for the target finishFunc); } @@ -222,4 +226,4 @@ export class DocumentManager { } } -Scripting.addGlobal(function DocFocus(doc: any) { DocumentManager.Instance.getDocumentViews(Doc.GetProto(doc)).map(view => view.props.focus(doc, true)); }); \ No newline at end of file +Scripting.addGlobal(function DocFocus(doc: any) { DocumentManager.Instance.getDocumentViews(Doc.GetProto(doc)).map(view => view.props.focus(doc, { willZoom: true })); }); \ No newline at end of file diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts index 1e6e02e55..f741d9c2c 100644 --- a/src/client/util/LinkManager.ts +++ b/src/client/util/LinkManager.ts @@ -111,10 +111,12 @@ export class LinkManager { setTimeout(() => { const targDocView = DocumentManager.Instance.getFirstDocumentView(doc); if (targDocView) { - targDocView.props.focus(doc, BoolCast(sourceDoc.followLinkZoom, false), undefined, (didFocus: boolean) => { - finished?.(); - res(true); - return new Promise(res2 => res2()); + targDocView.props.focus(doc, { + willZoom: BoolCast(sourceDoc.followLinkZoom, false), afterFocus: (didFocus: boolean) => { + finished?.(); + res(true); + return new Promise(res2 => res2()); + } }); } else { res(where !== "inPlace"); // return true to reset the initial focus&zoom (return false for 'inPlace' since resetting the initial focus&zoom will negate the zoom into the target) @@ -126,30 +128,30 @@ export class LinkManager { createTabForTarget(false); } else { // first focus & zoom onto this (the clicked document). Then execute the function to focus on the target - docViewProps.focus(sourceDoc, BoolCast(sourceDoc.followLinkZoom, true), 1, createTabForTarget); + docViewProps.focus(sourceDoc, { willZoom: BoolCast(sourceDoc.followLinkZoom, true), scale: 1, afterFocus: createTabForTarget }); } }; LinkManager.traverseLink(linkDoc, sourceDoc, createViewFunc, BoolCast(sourceDoc.followLinkZoom, false), docViewProps.ContainingCollectionDoc, batch.end, altKey ? true : undefined); } - public static traverseLink(link: Opt, doc: Doc, createViewFunc: CreateViewFunc, zoom = false, currentContext?: Doc, finished?: () => void, traverseBacklink?: boolean) { - const linkDocs = link ? [link] : DocListCast(doc.links); - const firstDocs = linkDocs.filter(linkDoc => Doc.AreProtosEqual(linkDoc.anchor1 as Doc, doc) || Doc.AreProtosEqual((linkDoc.anchor1 as Doc).annotationOn as Doc, doc)); // link docs where 'doc' is anchor1 - const secondDocs = linkDocs.filter(linkDoc => Doc.AreProtosEqual(linkDoc.anchor2 as Doc, doc) || Doc.AreProtosEqual((linkDoc.anchor2 as Doc).annotationOn as Doc, doc)); // link docs where 'doc' is anchor2 + public static traverseLink(link: Opt, sourceDoc: Doc, createViewFunc: CreateViewFunc, zoom = false, currentContext?: Doc, finished?: () => void, traverseBacklink?: boolean) { + const linkDocs = link ? [link] : DocListCast(sourceDoc.links); + const firstDocs = linkDocs.filter(linkDoc => Doc.AreProtosEqual(linkDoc.anchor1 as Doc, sourceDoc) || Doc.AreProtosEqual((linkDoc.anchor1 as Doc).annotationOn as Doc, sourceDoc)); // link docs where 'doc' is anchor1 + const secondDocs = linkDocs.filter(linkDoc => Doc.AreProtosEqual(linkDoc.anchor2 as Doc, sourceDoc) || Doc.AreProtosEqual((linkDoc.anchor2 as Doc).annotationOn as Doc, sourceDoc)); // link docs where 'doc' is anchor2 const fwdLinkWithoutTargetView = firstDocs.find(d => DocumentManager.Instance.getDocumentViews(d.anchor2 as Doc).length === 0); const backLinkWithoutTargetView = secondDocs.find(d => DocumentManager.Instance.getDocumentViews(d.anchor1 as Doc).length === 0); const linkWithoutTargetDoc = traverseBacklink === undefined ? fwdLinkWithoutTargetView || backLinkWithoutTargetView : traverseBacklink ? backLinkWithoutTargetView : fwdLinkWithoutTargetView; const linkDocList = linkWithoutTargetDoc ? [linkWithoutTargetDoc] : (traverseBacklink === undefined ? firstDocs.concat(secondDocs) : traverseBacklink ? secondDocs : firstDocs); - const followLinks = linkDocList.length ? (doc.isPushpin ? linkDocList : [linkDocList[0]]) : []; + const followLinks = linkDocList.length ? (sourceDoc.isPushpin ? linkDocList : [linkDocList[0]]) : []; followLinks.forEach(async linkDoc => { if (linkDoc) { - const target = (doc === linkDoc.anchor1 ? linkDoc.anchor2 : doc === linkDoc.anchor2 ? linkDoc.anchor1 : - (Doc.AreProtosEqual(doc, linkDoc.anchor1 as Doc) || Doc.AreProtosEqual((linkDoc.anchor1 as Doc).annotationOn as Doc, doc) ? linkDoc.anchor2 : linkDoc.anchor1)) as Doc; + const target = (sourceDoc === linkDoc.anchor1 ? linkDoc.anchor2 : sourceDoc === linkDoc.anchor2 ? linkDoc.anchor1 : + (Doc.AreProtosEqual(sourceDoc, linkDoc.anchor1 as Doc) || Doc.AreProtosEqual((linkDoc.anchor1 as Doc).annotationOn as Doc, sourceDoc) ? linkDoc.anchor2 : linkDoc.anchor1)) as Doc; if (target) { const containerDoc = Cast(target.annotationOn, Doc, null) || target; const targetContext = Cast(containerDoc?.context, Doc, null); const targetNavContext = !Doc.AreProtosEqual(targetContext, currentContext) ? targetContext : undefined; - DocumentManager.Instance.jumpToDocument(target, zoom, (doc, finished) => createViewFunc(doc, StrCast(linkDoc.followLinkLocation, "add:right"), finished), targetNavContext, linkDoc, undefined, doc, finished); + DocumentManager.Instance.jumpToDocument(target, zoom, (doc, finished) => createViewFunc(doc, StrCast(linkDoc.followLinkLocation, "add:right"), finished), targetNavContext, linkDoc, undefined, sourceDoc, finished); } else { finished?.(); } 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 { 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 { 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 { 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 Promise, 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: 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 { + focusDocument = (doc: Doc, options?: DocFocusOptions) => { Doc.BrushDoc(doc); Doc.linkFollowHighlight(doc); @@ -181,9 +181,11 @@ export class CollectionStackingView extends CollectionSubView afterFocus ? afterFocus(moved) : false; - this.props.focus(this.rootDoc, willZoom, scale, (didFocus: boolean) => - new Promise(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(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 { 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 { 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 { ; } - 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 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 { + 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 { 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 - new Promise(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(res => + setTimeout(async () => res(await endFocus(didMove || didFocus)), Math.max(0, focusSpeed - (Date.now() - startTime)))) + }); } } @@ -973,8 +976,12 @@ export class CollectionFreeFormView extends CollectionSubView { 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 (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; -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, props: Opt, 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 { + 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(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(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 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 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 { 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 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) => 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 -- cgit v1.2.3-70-g09d2 From 4ef4d06413169971a3919aa0c935eb321be7288b Mon Sep 17 00:00:00 2001 From: bobzel Date: Sun, 14 Feb 2021 21:48:55 -0500 Subject: fixed freeformview focus to not pan annotation documents or layoutEngine freeform views. fixed some exceptions. cleaned up focus() return value. --- src/client/util/DocumentManager.ts | 6 +++--- src/client/util/LinkManager.ts | 13 +++++++------ .../views/collections/CollectionDockingView.tsx | 8 ++++---- .../views/collections/CollectionStackedTimeline.tsx | 4 ++-- .../views/collections/CollectionStackingView.tsx | 6 +++--- src/client/views/collections/TabDocView.tsx | 2 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 10 +++++----- src/client/views/nodes/DocumentView.tsx | 21 +++++++++++++-------- 8 files changed, 38 insertions(+), 32 deletions(-) (limited to 'src/client/views/collections/CollectionStackedTimeline.tsx') diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index dd59efa41..6013a2ef3 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -7,7 +7,7 @@ import { DocumentType } from '../documents/DocumentTypes'; import { CollectionDockingView } from '../views/collections/CollectionDockingView'; import { CollectionView } from '../views/collections/CollectionView'; import { LightboxView } from '../views/LightboxView'; -import { DocumentView } from '../views/nodes/DocumentView'; +import { DocumentView, ViewAdjustment } from '../views/nodes/DocumentView'; import { Scripting } from './Scripting'; export class DocumentManager { @@ -173,7 +173,7 @@ export class DocumentManager { else if (docView) { docView.props.focus(targetDoc, { originalTarget, willZoom, afterFocus: (didFocus: boolean) => - new Promise(res => { + new Promise(res => { focusAndFinish(didFocus); res(); }) @@ -197,7 +197,7 @@ export class DocumentManager { if (retryDocView) { // we found the target in the context retryDocView.props.focus(targetDoc, { willZoom, afterFocus: (didFocus: boolean) => - new Promise(res => { + new Promise(res => { focusAndFinish(didFocus); res(); }) diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts index f741d9c2c..402cbdd68 100644 --- a/src/client/util/LinkManager.ts +++ b/src/client/util/LinkManager.ts @@ -3,7 +3,7 @@ import { computedFn } from "mobx-utils"; import { Doc, DocListCast, Opt } from "../../fields/Doc"; import { BoolCast, Cast, StrCast } from "../../fields/Types"; import { LightboxView } from "../views/LightboxView"; -import { DocumentViewSharedProps } from "../views/nodes/DocumentView"; +import { DocumentViewSharedProps, ViewAdjustment } from "../views/nodes/DocumentView"; import { DocumentManager } from "./DocumentManager"; import { SharingManager } from "./SharingManager"; import { UndoManager } from "./UndoManager"; @@ -105,21 +105,22 @@ export class LinkManager { const batch = UndoManager.StartBatch("follow link click"); // open up target if it's not already in view ... const createViewFunc = (doc: Doc, followLoc: string, finished?: Opt<() => void>) => { - const createTabForTarget = (didFocus: boolean) => new Promise(res => { + const createTabForTarget = (didFocus: boolean) => new Promise(res => { const where = LightboxView.LightboxDoc ? "lightbox" : StrCast(sourceDoc.followLinkLocation) || followLoc; docViewProps.addDocTab(doc, where); setTimeout(() => { const targDocView = DocumentManager.Instance.getFirstDocumentView(doc); if (targDocView) { targDocView.props.focus(doc, { - willZoom: BoolCast(sourceDoc.followLinkZoom, false), afterFocus: (didFocus: boolean) => { + willZoom: BoolCast(sourceDoc.followLinkZoom, false), + afterFocus: (didFocus: boolean) => { finished?.(); - res(true); - return new Promise(res2 => res2()); + res(ViewAdjustment.resetView); + return new Promise(res2 => res2()); } }); } else { - res(where !== "inPlace"); // return true to reset the initial focus&zoom (return false for 'inPlace' since resetting the initial focus&zoom will negate the zoom into the target) + res(where !== "inPlace" ? ViewAdjustment.resetView : ViewAdjustment.doNothing); // for 'inPlace' resetting the initial focus&zoom would negate the zoom into the target } }); }); diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index eee939c07..47c5746d4 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -375,13 +375,13 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) { const sublists = DocListCast(this.props.Document[this.props.fieldKey]); const tabs = Cast(sublists[0], Doc, null); const other = Cast(sublists[1], Doc, null); - const tabdocs = await DocListCastAsync(tabs.data); - const otherdocs = await DocListCastAsync(other.data); - Doc.GetProto(tabs).data = new List(docs); + const tabdocs = await DocListCastAsync(tabs?.data); + const otherdocs = await DocListCastAsync(other?.data); + tabs && (Doc.GetProto(tabs).data = new List(docs)); const otherSet = new Set(); otherdocs?.filter(doc => !docs.includes(doc)).forEach(doc => otherSet.add(doc)); tabdocs?.filter(doc => !docs.includes(doc)).forEach(doc => otherSet.add(doc)); - Doc.GetProto(other).data = new List(Array.from(otherSet.values())); + other && (Doc.GetProto(other).data = new List(Array.from(otherSet.values()))); }, 0); } diff --git a/src/client/views/collections/CollectionStackedTimeline.tsx b/src/client/views/collections/CollectionStackedTimeline.tsx index e3e753902..16a1c02f7 100644 --- a/src/client/views/collections/CollectionStackedTimeline.tsx +++ b/src/client/views/collections/CollectionStackedTimeline.tsx @@ -14,7 +14,7 @@ import { Scripting } from "../../util/Scripting"; import { SelectionManager } from "../../util/SelectionManager"; import { undoBatch } from "../../util/UndoManager"; import { CollectionSubView } from "../collections/CollectionSubView"; -import { DocumentView } from "../nodes/DocumentView"; +import { DocumentView, DocAfterFocusFunc } from "../nodes/DocumentView"; import { LabelBox } from "../nodes/LabelBox"; import "./CollectionStackedTimeline.scss"; import { Transform } from "../../util/Transform"; @@ -257,7 +257,7 @@ export class CollectionStackedTimeline extends CollectionSubView ScriptField), doublescript: undefined | (() => ScriptField), x: number, y: number, width: number, height: number) { const anchor = observable({ view: undefined as any }); - const focusFunc = (doc: Doc, willZoom?: boolean, scale?: number, afterFocus?: (notFocused: boolean) => Promise, docTransform?: Transform) => { + const focusFunc = (doc: Doc, willZoom?: boolean, scale?: number, afterFocus?: DocAfterFocusFunc, docTransform?: Transform) => { this.props.playLink(mark); this.props.focus(doc, { willZoom, scale, afterFocus, docTransform }); }; diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 1d6112745..0ac1cdb28 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, DocumentViewProps, DocFocusOptions } from "../nodes/DocumentView"; +import { DocumentView, DocumentViewProps, DocFocusOptions, ViewAdjustment } from "../nodes/DocumentView"; import { FieldViewProps } from "../nodes/FieldView"; import { StyleProp } from "../StyleProvider"; import { CollectionMasonryViewFieldRow } from "./CollectionMasonryViewFieldRow"; @@ -181,10 +181,10 @@ export class CollectionStackingView extends CollectionSubView options?.afterFocus ? options?.afterFocus(moved) : false; + const endFocus = async (moved: boolean) => options?.afterFocus ? options?.afterFocus(moved) : ViewAdjustment.doNothing; this.props.focus(this.rootDoc, { willZoom: options?.willZoom, scale: options?.scale, afterFocus: (didFocus: boolean) => - new Promise(res => setTimeout(async () => res(await endFocus(didFocus)), focusSpeed)) + new Promise(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 4c792186a..d2a83b1dd 100644 --- a/src/client/views/collections/TabDocView.tsx +++ b/src/client/views/collections/TabDocView.tsx @@ -207,7 +207,7 @@ export class TabDocView extends React.Component { const fieldKey = CollectionDockingView.Instance.props.fieldKey; const sublists = DocListCast(dview[fieldKey]); const tabs = Cast(sublists[0], Doc, null); - const tabdocs = await DocListCastAsync(tabs.data); + const tabdocs = await DocListCastAsync(tabs?.data); runInAction(() => { 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 diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 92916b5db..038fe8272 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -35,7 +35,7 @@ import { DocumentDecorations } from "../../DocumentDecorations"; import { ActiveArrowEnd, ActiveArrowStart, ActiveDash, ActiveFillColor, ActiveInkBezierApprox, ActiveInkColor, ActiveInkWidth } from "../../InkingStroke"; import { LightboxView } from "../../LightboxView"; import { CollectionFreeFormDocumentView } from "../../nodes/CollectionFreeFormDocumentView"; -import { DocFocusOptions, DocumentView, DocumentViewProps } from "../../nodes/DocumentView"; +import { DocFocusOptions, DocumentView, DocumentViewProps, ViewAdjustment } from "../../nodes/DocumentView"; import { FieldViewProps } from "../../nodes/FieldView"; import { FormattedTextBox } from "../../nodes/formattedText/FormattedTextBox"; import { pageSchema } from "../../nodes/ImageBox"; @@ -921,14 +921,14 @@ export class CollectionFreeFormView extends CollectionSubView { doc.hidden && Doc.UnHighlightDoc(doc); - const resetView = options?.afterFocus ? await options?.afterFocus(moved) : false; + const resetView = options?.afterFocus ? await options?.afterFocus(moved) : ViewAdjustment.doNothing; if (resetView) { const restoreState = LightboxView.LightboxDoc !== this.props.Document && LightboxState ? LightboxState : savedState; this.Document._panX = restoreState.panX; @@ -961,7 +961,7 @@ export class CollectionFreeFormView extends CollectionSubView new Promise(res => + afterFocus: (didFocus: boolean) => new Promise(res => setTimeout(async () => res(await endFocus(didMove || didFocus)), Math.max(0, focusSpeed - (Date.now() - startTime)))) }); } diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 9d91311f6..7dea3784e 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -42,14 +42,19 @@ import { PresBox } from './PresBox'; import { RadialMenu } from './RadialMenu'; import React = require("react"); +export enum ViewAdjustment { + resetView = 1, + doNothing = 0 + +} export interface DocFocusOptions { - originalTarget?: Doc; - willZoom?: boolean; - scale?: number; - afterFocus?: DocAfterFocusFunc; - docTransform?: Transform; + originalTarget?: Doc; // set in JumpToDocument, used by TabDocView to determine whether to fit contents to tab + willZoom?: boolean; // determines whether to zoom in on target document + scale?: number; // percent of containing frame to zoom into document + afterFocus?: DocAfterFocusFunc; // function to call after focusing on a document + docTransform?: Transform; // when a document can't be panned and zoomed within its own container (say a group), then we need to continue to move up the render hierarchy to find something that can pan and zoom. when this happens the docTransform must accumulate all the transforms of each level of the hierarchy } -export type DocAfterFocusFunc = (notFocused: boolean) => Promise; +export type DocAfterFocusFunc = (notFocused: boolean) => Promise; export type DocFocusFunc = (doc: Doc, options?: DocFocusOptions) => void; export type StyleProviderFunc = (doc: Opt, props: Opt, property: string) => any; export interface DocComponentView { @@ -385,10 +390,10 @@ export class DocumentViewInternal extends DocComponent { 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 ? options?.afterFocus : async (moved: boolean) => options?.afterFocus ? options?.afterFocus(true) : false; + const endFocus = focusSpeed === undefined ? options?.afterFocus : async (moved: boolean) => options?.afterFocus ? options?.afterFocus(true) : ViewAdjustment.doNothing; this.props.focus(options?.docTransform ? doc : this.rootDoc, { ...options, afterFocus: (didFocus: boolean) => - new Promise(res => setTimeout(async () => res(endFocus ? await endFocus(didFocus) : false), focusSpeed ?? 0)) + new Promise(res => setTimeout(async () => res(endFocus ? await endFocus(didFocus) : ViewAdjustment.doNothing), focusSpeed ?? 0)) }); } -- cgit v1.2.3-70-g09d2