From 4a9d6d1409327fd99c5f554caebd917a316db32b Mon Sep 17 00:00:00 2001 From: bobzel Date: Fri, 12 Feb 2021 11:00:29 -0500 Subject: changed lightbox to navigate within frame if next target is alreay there, otherwise create it. changed focus default to call afterFocus(). fixed bug of zooming on target doc to compute scale correctly. --- src/client/documents/Documents.ts | 5 +++ src/client/util/DocumentManager.ts | 13 ++---- src/client/util/LinkManager.ts | 25 ++++++----- src/client/views/DocumentDecorations.tsx | 5 +-- src/client/views/GestureOverlay.tsx | 2 +- src/client/views/GlobalKeyHandler.ts | 2 +- src/client/views/LightboxView.tsx | 52 +++++++++++++++------- src/client/views/MainView.tsx | 14 +++--- src/client/views/OverlayView.tsx | 3 +- src/client/views/collections/CollectionMenu.tsx | 7 ++- .../views/collections/CollectionSchemaView.tsx | 3 +- src/client/views/collections/SchemaTable.tsx | 4 +- src/client/views/collections/TabDocView.tsx | 5 ++- .../collectionFreeForm/CollectionFreeFormView.tsx | 2 +- src/client/views/nodes/AudioBox.tsx | 2 +- src/client/views/nodes/DocumentContentsView.tsx | 6 +-- src/client/views/nodes/LinkDocPreview.tsx | 4 +- src/client/views/nodes/PresBox.tsx | 6 ++- src/client/views/nodes/VideoBox.tsx | 2 +- .../views/presentationview/PresElementBox.tsx | 3 +- src/mobile/MobileInterface.tsx | 4 +- 21 files changed, 97 insertions(+), 72 deletions(-) (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index de4a8f43c..2d370ca8d 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -55,6 +55,7 @@ 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"; const path = require('path'); const defaultNativeImageDim = Number(DFLT_IMAGE_NATIVE_DIM.replace("px", "")); @@ -1017,6 +1018,10 @@ export namespace DocUtils { }); } + export function DefaultFocus(doc: Doc, willZoom?: boolean, scale?: number, afterFocus?: DocAfterFocusFunc, docTransform?: Transform) { + afterFocus?.(false); + } + export let ActiveRecordings: AudioBox[] = []; export function MakeLinkToActiveAudio(doc: Doc) { diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index 816f7f6be..5b4917a30 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -10,8 +10,6 @@ import { LightboxView } from '../views/LightboxView'; import { DocumentView } from '../views/nodes/DocumentView'; import { Scripting } from './Scripting'; -export type CreateViewFunc = (doc: Doc, followLinkLocation: string, finished?: () => void) => void; - export class DocumentManager { //global holds all of the nodes (regardless of which collection they're in) @@ -217,14 +215,9 @@ 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, willZoom, createViewFunc, docContext, linkDoc, true /* if we don't find the target, we want to get rid of the context just created */, undefined, finished); - if (LightboxView.LightboxDoc) { - runInAction(() => LightboxView.LightboxDoc = targetDocContext); - setTimeout(() => finishFunc, 250); - } else { - createViewFunc(targetDocContext, // after creating the context, this calls the finish function that will retry looking for the target - finishFunc); - } + 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); + createViewFunc(targetDocContext, // after creating the context, this calls the finish function that will retry looking for the target + finishFunc); } } } diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts index 58ccfe645..d433605f1 100644 --- a/src/client/util/LinkManager.ts +++ b/src/client/util/LinkManager.ts @@ -4,10 +4,11 @@ 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 { CreateViewFunc, DocumentManager } from "./DocumentManager"; +import { DocumentManager } from "./DocumentManager"; import { SharingManager } from "./SharingManager"; import { UndoManager } from "./UndoManager"; +type CreateViewFunc = (doc: Doc, followLinkLocation: string, finished?: () => void) => void; /* * link doc: * - anchor1: doc @@ -106,7 +107,11 @@ export class LinkManager { const createViewFunc = (doc: Doc, followLoc: string, finished?: Opt<() => void>) => { const createTabForTarget = (didFocus: boolean) => new Promise(res => { const where = StrCast(sourceDoc.followLinkLocation) || followLoc; - docViewProps.addDocTab(doc, where); + if (LightboxView.LightboxDoc) { + LightboxView.SetLightboxDoc(doc); + } else { + docViewProps.addDocTab(doc, where); + } setTimeout(() => { const targDocView = DocumentManager.Instance.getFirstDocumentView(doc); if (targDocView) { @@ -130,6 +135,7 @@ export class LinkManager { }; 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 @@ -147,16 +153,11 @@ export class LinkManager { doc === linkDoc.anchor2 ? Cast(linkDoc.anchor1_timecode, "number") : (Doc.AreProtosEqual(doc, linkDoc.anchor1 as Doc) || Doc.AreProtosEqual((linkDoc.anchor1 as Doc).annotationOn as Doc, doc) ? Cast(linkDoc.anchor2_timecode, "number") : Cast(linkDoc.anchor1_timecode, "number"))); if (target) { - if (LightboxView.LightboxDoc && !DocumentManager.Instance.getLightboxDocumentView(doc)) { - runInAction(() => LightboxView.LightboxDoc = (target.annotationOn as Doc) ?? target); - finished?.(); - } else { - const containerDoc = Cast(target.annotationOn, Doc, null) || target; - targetTimecode !== undefined && (containerDoc._currentTimecode = targetTimecode); - 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); - } + const containerDoc = Cast(target.annotationOn, Doc, null) || target; + targetTimecode !== undefined && (containerDoc._currentTimecode = targetTimecode); + 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); } else { finished?.(); } diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 77b43db9b..87ed142f8 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -175,10 +175,7 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b } else if (e.altKey) { // open same document in new tab CollectionDockingView.ToggleSplit(Cast(selectedDocs[0].props.Document._fullScreenView, Doc, null) || selectedDocs[0].props.Document, "right"); } else { - runInAction(() => { - LightboxView.LightboxDoc = selectedDocs[0].props.Document; - LightboxView.LightboxFuture = selectedDocs.slice(1).map(view => view.props.Document); - }); + LightboxView.SetLightboxDoc(selectedDocs[0].props.Document, selectedDocs.slice(1).map(view => view.props.Document)); } } } diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx index d7e7e055f..b4051194f 100644 --- a/src/client/views/GestureOverlay.tsx +++ b/src/client/views/GestureOverlay.tsx @@ -873,7 +873,7 @@ export class GestureOverlay extends Touchable { styleProvider={returnEmptyString} layerProvider={undefined} docViewPath={returnEmptyDoclist} - focus={emptyFunction} + focus={DocUtils.DefaultFocus} parentActive={returnTrue} whenActiveChanged={emptyFunction} bringToFront={emptyFunction} diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts index 09b95315c..3ebcda219 100644 --- a/src/client/views/GlobalKeyHandler.ts +++ b/src/client/views/GlobalKeyHandler.ts @@ -130,7 +130,7 @@ export class KeyManager { } if (doDeselect) { SelectionManager.DeselectAll(); - LightboxView.LightboxDoc = undefined; + LightboxView.SetLightboxDoc(undefined); } DictationManager.Controls.stop(); GoogleAuthenticationManager.Instance.cancel(); diff --git a/src/client/views/LightboxView.tsx b/src/client/views/LightboxView.tsx index 4e9491ec6..fbfc9672f 100644 --- a/src/client/views/LightboxView.tsx +++ b/src/client/views/LightboxView.tsx @@ -9,6 +9,8 @@ import { Transform } from '../util/Transform'; import "./LightboxView.scss"; import { DocumentView } from './nodes/DocumentView'; import { DefaultStyleProvider } from './StyleProvider'; +import { DocUtils } from '../documents/Documents'; +import { DocumentManager } from '../util/DocumentManager'; interface LightboxViewProps { PanelWidth: number; @@ -18,7 +20,16 @@ interface LightboxViewProps { @observer export class LightboxView extends React.Component { - @observable public static LightboxDoc: Opt; + @observable static LightboxDoc: Opt; + @action public static SetLightboxDoc(doc: Opt, future?: Doc[]) { + LightboxView.LightboxDoc = doc; + if (!doc) { + LightboxView.LightboxFuture = LightboxView.LightboxHistory = []; + } else if (future) { + LightboxView.LightboxFuture = future; + } + return true; + } public static IsLightboxDocView(path: DocumentView[]) { return path.includes(LightboxView.LightboxDocView.current!); } public static LightboxHistory: (Opt)[] = []; public static LightboxFuture: (Opt)[] = []; @@ -47,13 +58,11 @@ export class LightboxView extends React.Component { return !LightboxView.LightboxDoc ? (null) :
{ downx = e.clientX; downy = e.clientY; }} - onClick={action(e => { + onClick={e => { if (Math.abs(downx - e.clientX) < 4 && Math.abs(downy - e.clientY) < 4) { - LightboxView.LightboxHistory = []; - LightboxView.LightboxFuture = []; - LightboxView.LightboxDoc = undefined; + LightboxView.SetLightboxDoc(undefined); } - })} > + }} >
{ ScreenToLocalTransform={this.lightboxScreenToLocal} PanelWidth={this.lightboxWidth} PanelHeight={this.lightboxHeight} - focus={emptyFunction} + focus={DocUtils.DefaultFocus} parentActive={returnTrue} whenActiveChanged={emptyFunction} bringToFront={emptyFunction} @@ -87,18 +96,31 @@ export class LightboxView extends React.Component {
{this.navBtn(undefined, "chevron-left", () => LightboxView.LightboxDoc && LightboxView.LightboxHistory.length ? "" : "none", - action(e => { + e => { e.stopPropagation(); - const popped = LightboxView.LightboxHistory.pop(); - if (LightboxView.LightboxHistory.lastElement() !== LightboxView.LightboxFuture.lastElement()) LightboxView.LightboxFuture.push(popped); - LightboxView.LightboxDoc = LightboxView.LightboxHistory.lastElement(); - }))} + const previous = LightboxView.LightboxHistory.pop(); + const target = LightboxView.LightboxHistory.lastElement(); + 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); + } else { + LightboxView.SetLightboxDoc(target); + } + })} {this.navBtn(this.props.PanelWidth - Math.min(this.props.PanelWidth / 4, this.props.maxBorder[0]), "chevron-right", () => LightboxView.LightboxDoc && LightboxView.LightboxFuture.length ? "" : "none", - action(e => { + e => { e.stopPropagation(); - LightboxView.LightboxDoc = LightboxView.LightboxFuture.pop(); - }))} + const target = LightboxView.LightboxFuture.pop(); + const docView = target && DocumentManager.Instance.getLightboxDocumentView(target); + if (docView && target) { + docView.focus(target, true, 0.9); + if (LightboxView.LightboxHistory.lastElement() !== target) LightboxView.LightboxHistory.push(target); + } else { + LightboxView.SetLightboxDoc(target); + } + })}
; } diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index ca07fa879..314922df8 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -16,7 +16,7 @@ import { TraceMobx } from '../../fields/util'; import { emptyFunction, emptyPath, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, setupMoveUpEvents, simulateMouseClick, Utils } from '../../Utils'; import { GoogleAuthenticationManager } from '../apis/GoogleAuthenticationManager'; import { DocServer } from '../DocServer'; -import { Docs } from '../documents/Documents'; +import { Docs, DocUtils } from '../documents/Documents'; import { CurrentUserUtils } from '../util/CurrentUserUtils'; import { DocumentManager } from '../util/DocumentManager'; import { GroupManager } from '../util/GroupManager'; @@ -47,7 +47,7 @@ import { LinkMenu } from './linking/LinkMenu'; import "./MainView.scss"; import { AudioBox } from './nodes/AudioBox'; import { DocumentLinksButton } from './nodes/DocumentLinksButton'; -import { DocumentView, DocumentViewProps } from './nodes/DocumentView'; +import { DocumentView, DocumentViewProps, DocAfterFocusFunc } from './nodes/DocumentView'; import { FieldViewProps } from './nodes/FieldView'; import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox'; import { LinkDescriptionPopup } from './nodes/LinkDescriptionPopup'; @@ -257,7 +257,7 @@ export class MainView extends React.Component { ScreenToLocalTransform={Transform.Identity} PanelWidth={this.getPWidth} PanelHeight={this.getPHeight} - focus={emptyFunction} + focus={DocUtils.DefaultFocus} parentActive={returnTrue} whenActiveChanged={emptyFunction} bringToFront={emptyFunction} @@ -350,7 +350,7 @@ export class MainView extends React.Component { PanelHeight={this.getContentsHeight} renderDepth={0} scriptContext={CollectionDockingView.Instance.props.Document} - focus={emptyFunction} + focus={DocUtils.DefaultFocus} parentActive={returnTrue} whenActiveChanged={emptyFunction} bringToFront={emptyFunction} @@ -380,7 +380,7 @@ export class MainView extends React.Component { PanelHeight={this.getContentsHeight} renderDepth={0} docViewPath={returnEmptyDoclist} - focus={emptyFunction} + focus={DocUtils.DefaultFocus} styleProvider={DefaultStyleProvider} layerProvider={undefined} parentActive={returnTrue} @@ -501,7 +501,7 @@ export class MainView extends React.Component { PanelWidth={this.flyoutWidthFunc} PanelHeight={this.getContentsHeight} renderDepth={0} - focus={emptyFunction} + focus={DocUtils.DefaultFocus} whenActiveChanged={emptyFunction} docFilters={returnEmptyFilter} docRangeFilters={returnEmptyFilter} @@ -563,7 +563,7 @@ export class MainView extends React.Component { PanelWidth={this.getPWidth} PanelHeight={this.getPHeight} renderDepth={0} - focus={emptyFunction} + focus={DocUtils.DefaultFocus} docViewPath={returnEmptyDoclist} parentActive={returnFalse} whenActiveChanged={emptyFunction} diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx index 64f907f4c..5696b16e9 100644 --- a/src/client/views/OverlayView.tsx +++ b/src/client/views/OverlayView.tsx @@ -15,6 +15,7 @@ import { DocumentView } from "./nodes/DocumentView"; import './OverlayView.scss'; import { ScriptingRepl } from './ScriptingRepl'; import { DefaultStyleProvider } from "./StyleProvider"; +import { DocUtils } from "../documents/Documents"; export type OverlayDisposer = () => void; @@ -191,7 +192,7 @@ export class OverlayView extends React.Component { renderDepth={1} parentActive={returnTrue} whenActiveChanged={emptyFunction} - focus={emptyFunction} + focus={DocUtils.DefaultFocus} styleProvider={DefaultStyleProvider} layerProvider={undefined} docViewPath={returnEmptyDoclist} diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx index d6e4b01c4..5fa988f06 100644 --- a/src/client/views/collections/CollectionMenu.tsx +++ b/src/client/views/collections/CollectionMenu.tsx @@ -489,13 +489,12 @@ export class CollectionViewBaseChrome extends React.Component{"Show Lightbox of Documents"}} placement="top"> - ; diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 66064e354..d2ed5427b 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -25,6 +25,7 @@ import { DefaultStyleProvider } from "../StyleProvider"; import "./CollectionSchemaView.scss"; import { CollectionSubView } from "./CollectionSubView"; import { SchemaTable } from "./SchemaTable"; +import { DocUtils } from "../../documents/Documents"; // bcz: need to add drag and drop of rows and columns. This seems like it might work for rows: https://codesandbox.io/s/l94mn1q657 export enum ColumnType { @@ -404,7 +405,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { fitContentsToDoc={true} freezeDimensions={true} dontCenter={"y"} - focus={emptyFunction} + focus={DocUtils.DefaultFocus} renderDepth={this.props.renderDepth} rootSelected={this.rootSelected} PanelWidth={this.previewWidth} diff --git a/src/client/views/collections/SchemaTable.tsx b/src/client/views/collections/SchemaTable.tsx index d4b4cf333..53801eef1 100644 --- a/src/client/views/collections/SchemaTable.tsx +++ b/src/client/views/collections/SchemaTable.tsx @@ -16,7 +16,7 @@ import { Cast, FieldValue, NumCast, StrCast } from "../../../fields/Types"; import { ImageField } from "../../../fields/URLField"; import { GetEffectiveAcl } from "../../../fields/util"; import { emptyFunction, emptyPath, returnEmptyDoclist, returnEmptyFilter, returnFalse } from "../../../Utils"; -import { Docs, DocumentOptions } from "../../documents/Documents"; +import { Docs, DocumentOptions, DocUtils } from "../../documents/Documents"; import { DocumentType } from "../../documents/DocumentTypes"; import { CompileScript, Transformer, ts } from "../../util/Scripting"; import { Transform } from "../../util/Transform"; @@ -575,7 +575,7 @@ export class SchemaTable extends React.Component { layerProvider={undefined} docViewPath={returnEmptyDoclist} freezeDimensions={true} - focus={emptyFunction} + focus={DocUtils.DefaultFocus} renderDepth={this.props.renderDepth} rootSelected={() => false} PanelWidth={() => 150} diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx index e1e1c8656..0fb140231 100644 --- a/src/client/views/collections/TabDocView.tsx +++ b/src/client/views/collections/TabDocView.tsx @@ -34,6 +34,7 @@ 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 { @@ -278,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 runInAction(() => LightboxView.LightboxDoc = doc) ? true : false; + case "lightbox": return LightboxView.SetLightboxDoc(doc); case "inPlace": case "add": default: @@ -333,7 +334,7 @@ export class TabDocView extends React.Component { ScreenToLocalTransform={Transform.Identity} renderDepth={0} whenActiveChanged={emptyFunction} - focus={emptyFunction} + focus={DocUtils.DefaultFocus} styleProvider={TabDocView.miniStyleProvider} layerProvider={undefined} addDocTab={this.addDocTab} diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index c18ef7a3b..74175c0b2 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -963,7 +963,7 @@ export class CollectionFreeFormView extends CollectionSubView { renderDepth={-1} PanelWidth={this.width} PanelHeight={this.height} - focus={emptyFunction} + focus={DocUtils.DefaultFocus} whenActiveChanged={returnFalse} bringToFront={returnFalse} NativeWidth={Doc.NativeWidth(this._targetDoc) ? () => Doc.NativeWidth(this._targetDoc) : undefined} diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx index 589a1c2ae..d736dc583 100644 --- a/src/client/views/nodes/PresBox.tsx +++ b/src/client/views/nodes/PresBox.tsx @@ -422,7 +422,11 @@ export class PresBox extends ViewBoxBaseComponent this.layoutDoc.presCollection = targetDoc; // this still needs some fixing setTimeout(resetSelection, 500); - doc !== targetDoc && setTimeout(() => finished?.(), 100); /// give it some time to create the targetDoc if we're opening up its context + if (doc !== targetDoc) { + setTimeout(() => finished?.(), 100); /// give it some time to create the targetDoc if we're opening up its context + } else { + finished?.(); + } }; // If openDocument is selected then it should open the document for the user if (activeItem.openDocument) { diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx index c0247c226..a99853aac 100644 --- a/src/client/views/nodes/VideoBox.tsx +++ b/src/client/views/nodes/VideoBox.tsx @@ -497,7 +497,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent