From aca573baccc106363d6b61797b58cd60c742b0a0 Mon Sep 17 00:00:00 2001 From: bobzel Date: Sat, 13 Feb 2021 01:13:09 -0500 Subject: fixed double-click to open nested freeform docs to fall back on DocumentView to open them in lightbox. fixed resetting of collectoin view pan/scale after coming out of lightbox. --- src/client/views/LightboxView.tsx | 27 +++++++++++---- src/client/views/collections/TabDocView.tsx | 2 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 40 ++++++++++++---------- src/client/views/nodes/DocumentView.tsx | 8 +++-- 4 files changed, 48 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/client/views/LightboxView.tsx b/src/client/views/LightboxView.tsx index 0957fc94d..7fab88800 100644 --- a/src/client/views/LightboxView.tsx +++ b/src/client/views/LightboxView.tsx @@ -3,7 +3,7 @@ import { action, observable, computed } from 'mobx'; import { observer } from 'mobx-react'; import "normalize.css"; import * as React from 'react'; -import { Doc, Opt } from '../../fields/Doc'; +import { Doc, Opt, DocListCast } from '../../fields/Doc'; import { emptyFunction, emptyPath, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue } from '../../Utils'; import { Transform } from '../util/Transform'; import "./LightboxView.scss"; @@ -13,7 +13,7 @@ import { DocUtils } from '../documents/Documents'; import { DocumentManager } from '../util/DocumentManager'; import { SelectionManager } from '../util/SelectionManager'; import { TabDocView } from './collections/TabDocView'; -import { Cast } from '../../fields/Types'; +import { Cast, NumCast } from '../../fields/Types'; interface LightboxViewProps { PanelWidth: number; @@ -50,10 +50,10 @@ export class LightboxView extends React.Component { return true; } - public static IsLightboxDocView(path: DocumentView[]) { return path.includes(LightboxView.LightboxDocView.current!); } + public static IsLightboxDocView(path: DocumentView[]) { return path.includes(LightboxView.LightboxDocView!); } public static LightboxHistory: (Opt)[] = []; public static LightboxFuture: (Opt)[] = []; - public static LightboxDocView = React.createRef(); + public static LightboxDocView: Opt; @computed get leftBorder() { return Math.min(this.props.PanelWidth / 4, this.props.maxBorder[0]); } @computed get topBorder() { return Math.min(this.props.PanelHeight / 4, this.props.maxBorder[1]); } lightboxWidth = () => this.props.PanelWidth - this.leftBorder * 2; @@ -71,10 +71,12 @@ export class LightboxView extends React.Component { ; } - addDocTab = (doc: Doc, location: string) => { + public static AddDocTab = (doc: Doc, location: string) => { SelectionManager.DeselectAll(); - return LightboxView.SetLightboxDoc(doc); + return LightboxView.SetLightboxDoc(doc, [...DocListCast(doc[Doc.LayoutFieldKey(doc)]), ...DocListCast(doc[Doc.LayoutFieldKey(doc) + "-annotations"])] + .sort((a: Doc, b: Doc) => NumCast(b._timecodeToShow) - NumCast(a._timecodeToShow))); } + addDocTab = LightboxView.AddDocTab; fitToBox = () => LightboxView.LightboxDocTarget === LightboxView.LightboxDoc; render() { @@ -94,7 +96,18 @@ export class LightboxView extends React.Component { width: this.lightboxWidth(), height: this.lightboxHeight() }}> - { + LightboxView.LightboxDocView = r !== null ? r : undefined; + setTimeout(action(() => { + const vals = r?.ComponentView?.freeformData?.(); + if (vals && r) { + r.layoutDoc._panX = vals.panX; + r.layoutDoc._panY = vals.panY; + r.layoutDoc._viewScale = vals.scale; + } + LightboxView.LightboxDocTarget = undefined; + })); + })} Document={LightboxView.LightboxDoc} DataDoc={undefined} addDocument={undefined} diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx index 9048a5f01..d62b8b6f6 100644 --- a/src/client/views/collections/TabDocView.tsx +++ b/src/client/views/collections/TabDocView.tsx @@ -279,7 +279,7 @@ 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.SetLightboxDoc(doc, DocListCast(doc[Doc.LayoutFieldKey(doc) + "-annotations"]).sort((a: Doc, b: Doc) => NumCast(b._timecodeToShow) - NumCast(a._timecodeToShow))); + case "lightbox": return LightboxView.AddDocTab(doc, location); case "inPlace": case "add": default: diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 1f65cf1ea..954b6478f 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -117,7 +117,16 @@ export class CollectionFreeFormView extends CollectionSubView(); @computed get backgroundActive() { return this.props.layerProvider?.(this.layoutDoc) === false && (this.props.ContainingCollectionView?.active() || this.props.active()); } - @computed get fitToContentScaling() { return this.fitToContent ? NumCast(this.layoutDoc.fitToContentScaling, 1) : 1; } + @computed get fitToContentVals() { + return this.fitToContent && + { + panX: (this.contentBounds.x + this.contentBounds.r) / 2, + panY: (this.contentBounds.y + this.contentBounds.b) / 2, + scale: !this.childDocs.length ? 1 : + Math.min(this.props.PanelHeight() / (this.contentBounds.b - this.contentBounds.y), + this.props.PanelWidth() / (this.contentBounds.r - this.contentBounds.x)) + } || undefined; + } @computed get fitToContent() { return (this.props.fitContentsToDoc?.() || this.Document._fitToBox) && !this.isAnnotationOverlay; } @computed get parentScaling() { return 1; } @computed get contentBounds() { return aggregateBounds(this._layoutElements.filter(e => e.bounds && !e.bounds.z).map(e => e.bounds!), NumCast(this.layoutDoc._xPadding, 10), NumCast(this.layoutDoc._yPadding, 10)); } @@ -126,17 +135,9 @@ export class CollectionFreeFormView extends CollectionSubView this.fitToContent && !this.props.isAnnotationOverlay ? (this.contentBounds.x + this.contentBounds.r) / 2 : this.Document._panX || 0; - private panY = () => this.fitToContent && !this.props.isAnnotationOverlay ? (this.contentBounds.y + this.contentBounds.b) / 2 : this.Document._panY || 0; - private zoomScaling = () => { - const mult = this.fitToContentScaling / this.parentScaling; - if (this.fitToContent) { - const zs = !this.childDocs.length ? 1 : - Math.min(this.props.PanelHeight() / (this.contentBounds.b - this.contentBounds.y), this.props.PanelWidth() / (this.contentBounds.r - this.contentBounds.x)); - return mult * zs; - } - return mult * NumCast(this.Document[this.scaleFieldKey], 1); - } + 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; @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 @@ -607,14 +608,14 @@ export class CollectionFreeFormView extends CollectionSubView { - if (this.layoutDoc.targetScale && (Math.abs(e.pageX - this._downX) < 3 && Math.abs(e.pageY - this._downY) < 3)) { + if ((Math.abs(e.pageX - this._downX) < 3 && Math.abs(e.pageY - this._downY) < 3)) { if (Date.now() - this._lastTap < 300) { // reset zoom of freeform view to 1-to-1 on a double click if (e.shiftKey) { - this.scaleAtPt(this.getTransform().transformPoint(e.clientX, e.clientY), 1); + if (this.layoutDoc.targetScale) { + this.scaleAtPt(this.getTransform().transformPoint(e.clientX, e.clientY), 1); + } e.stopPropagation(); e.preventDefault(); - } else { - LightboxView.SetLightboxDoc(this.rootDoc, this.childDocs); } } this._lastTap = Date.now(); @@ -937,6 +938,7 @@ export class CollectionFreeFormView extends CollectionSubView { doc.hidden && Doc.UnHighlightDoc(doc); @@ -956,8 +958,9 @@ export class CollectionFreeFormView extends CollectionSubView - new Promise(res => setTimeout(async () => res(await endFocus(didMove || didFocus)), focusSpeed)), xf); + new Promise(res => setTimeout(async () => res(await endFocus(didMove || didFocus)), Math.max(0, focusSpeed - (Date.now() - startTime)))), xf); } } @@ -1185,10 +1188,11 @@ export class CollectionFreeFormView extends CollectionSubView { return this.fitToContentVals; } @action componentDidMount() { super.componentDidMount?.(); + this.props.setContentView?.(this); this._layoutComputeReaction = reaction(() => this.doLayoutComputation, (elements) => this._layoutElements = elements || [], { fireImmediately: true, name: "doLayout" }); diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index d593b75eb..7ba0d7043 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -46,12 +46,13 @@ export type DocAfterFocusFunc = (notFocused: boolean) => Promise; export type DocFocusFunc = (doc: Doc, willZoom?: boolean, scale?: number, afterFocus?: DocAfterFocusFunc, docTransform?: Transform) => void; export type StyleProviderFunc = (doc: Opt, props: Opt, property: string) => any; export interface DocComponentView { - getAnchor: () => Doc; + getAnchor?: () => Doc; scrollFocus?: (doc: Doc, smooth: boolean) => Opt; // returns the duration of the focus back?: () => boolean; forward?: () => boolean; url?: () => string; submitURL?: (url: string) => boolean; + freeformData?: () => Opt<{ panX: number, panY: number, scale: number }>; } export interface DocumentViewSharedProps { renderDepth: number; @@ -388,7 +389,7 @@ export class DocumentViewInternal extends DocComponent