aboutsummaryrefslogtreecommitdiff
path: root/src/client/util
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/util')
-rw-r--r--src/client/util/CurrentUserUtils.ts2
-rw-r--r--src/client/util/DocumentManager.ts83
-rw-r--r--src/client/util/DragManager.ts4
-rw-r--r--src/client/util/Import & Export/DirectoryImportBox.tsx6
-rw-r--r--src/client/util/ReplayMovements.ts64
-rw-r--r--src/client/util/SelectionManager.ts6
-rw-r--r--src/client/util/SharingManager.tsx5
-rw-r--r--src/client/util/TrackMovements.ts36
8 files changed, 88 insertions, 118 deletions
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 76ea3e3ea..abf7313a4 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -110,7 +110,7 @@ export class CurrentUserUtils {
const tempClicks = DocCast(doc[field]);
const reqdClickOpts:DocumentOptions = {_width: 300, _height:200, system: true};
const reqdTempOpts:{opts:DocumentOptions, script: string}[] = [
- { opts: { title: "Open In Target", targetScriptKey: "onChildClick"}, script: "docCast(thisContainer.target).then((target) => target && (target.proto.data = new List([self])))"},
+ { opts: { title: "Open In Target", targetScriptKey: "onChildClick"}, script: "docCast(documentView?.props.docViewPath().lastElement()?.rootDoc.target).then((target) => target && (target.proto.data = new List([self])))"},
{ opts: { title: "Open Detail On Right", targetScriptKey: "onChildDoubleClick"}, script: `openDoc(self.doubleClickView.${OpenWhere.addRight})`}];
const reqdClickList = reqdTempOpts.map(opts => {
const allOpts = {...reqdClickOpts, ...opts.opts};
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index ccf370662..ad89e8653 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -1,15 +1,11 @@
-import { loadAsync } from 'jszip';
-import { action, observable, ObservableSet, runInAction } from 'mobx';
+import { action, observable, ObservableSet } from 'mobx';
import { AnimationSym, Doc, Opt } from '../../fields/Doc';
import { Id } from '../../fields/FieldSymbols';
import { listSpec } from '../../fields/Schema';
import { Cast, DocCast, StrCast } from '../../fields/Types';
import { AudioField } from '../../fields/URLField';
-import { emptyFunction } from '../../Utils';
import { CollectionViewType } from '../documents/DocumentTypes';
import { CollectionDockingView } from '../views/collections/CollectionDockingView';
-import { CollectionFreeFormView } from '../views/collections/collectionFreeForm';
-import { CollectionView } from '../views/collections/CollectionView';
import { TabDocView } from '../views/collections/TabDocView';
import { LightboxView } from '../views/LightboxView';
import { MainView } from '../views/MainView';
@@ -39,7 +35,7 @@ export class DocumentManager {
private _viewRenderedCbs: { doc: Doc; func: (dv: DocumentView) => any }[] = [];
public AddViewRenderedCb = (doc: Opt<Doc>, func: (dv: DocumentView) => any) => {
if (doc) {
- const dv = this.getDocumentViewById(doc[Id]);
+ const dv = this.getDocumentView(doc);
this._viewRenderedCbs.push({ doc, func });
if (dv) {
this.callAddViewFuncs(dv);
@@ -129,42 +125,24 @@ export class DocumentManager {
return this.getDocumentViewsById(doc[Id]);
}
- public getDocumentViewById(id: string, preferredCollection?: CollectionView): DocumentView | undefined {
- if (!id) return undefined;
- let toReturn: DocumentView | undefined;
- const passes = preferredCollection ? [preferredCollection, undefined] : [undefined];
-
- for (const pass of passes) {
- Array.from(DocumentManager.Instance.DocumentViews).map(view => {
- if (view.rootDoc[Id] === id && (!pass || view.props.ContainingCollectionView === preferredCollection)) {
- toReturn = view;
- return;
- }
- });
- if (!toReturn) {
- Array.from(DocumentManager.Instance.DocumentViews).map(view => {
- const doc = view.rootDoc.proto;
- if (doc && doc[Id] === id && (!pass || view.props.ContainingCollectionView === preferredCollection)) {
- toReturn = view;
- }
- });
- } else {
- break;
- }
- }
-
- return toReturn;
- }
-
- public getDocumentView(toFind: Doc, preferredCollection?: CollectionView): DocumentView | undefined {
- const found =
+ public getDocumentView(toFind: Doc | undefined, preferredCollection?: DocumentView): DocumentView | undefined {
+ const doc =
+ // bcz: this was temporary code used to match documents by data url instead of by id. intended only for repairing the DB
// Array.from(DocumentManager.Instance.DocumentViews).find(
// dv =>
// ((dv.rootDoc.data as any)?.url?.href && (dv.rootDoc.data as any)?.url?.href === (toFind.data as any)?.url?.href) ||
// ((DocCast(dv.rootDoc.annotationOn)?.data as any)?.url?.href && (DocCast(dv.rootDoc.annotationOn)?.data as any)?.url?.href === (DocCast(toFind.annotationOn)?.data as any)?.url?.href)
// )?.rootDoc ??
toFind;
- return this.getDocumentViewById(found[Id], preferredCollection);
+ const docViewArray = Array.from(DocumentManager.Instance.DocumentViews);
+ const passes = !doc ? [] : preferredCollection ? [preferredCollection, undefined] : [undefined];
+ return passes.reduce(
+ (pass, toReturn) =>
+ toReturn ??
+ docViewArray.filter(view => view.rootDoc === doc).find(view => !pass || view.props.docViewPath().lastElement() === preferredCollection) ??
+ docViewArray.filter(view => Doc.GetProto(view.rootDoc) === doc).find(view => !pass || view.props.docViewPath().lastElement() === preferredCollection),
+ undefined as Opt<DocumentView>
+ );
}
public getLightboxDocumentView = (toFind: Doc, originatingDoc: Opt<Doc> = undefined): DocumentView | undefined => {
@@ -247,7 +225,8 @@ export class DocumentManager {
public showDocumentView = async (targetDocView: DocumentView, options: DocFocusOptions) => {
const docViewPath = targetDocView.docViewPath.slice();
let rootContextView = docViewPath.shift();
- return rootContextView && this.focusViewsInPath(rootContextView, options, async () => ({ childDocView: docViewPath.shift(), viewSpec: undefined }));
+ await (rootContextView && this.focusViewsInPath(rootContextView, options, async () => ({ childDocView: docViewPath.shift(), viewSpec: undefined })));
+ if (options.toggleTarget && (!options.didMove || targetDocView.rootDoc.hidden)) targetDocView.rootDoc.hidden = !targetDocView.rootDoc.hidden;
};
// shows a document by first:
@@ -318,15 +297,25 @@ export class DocumentManager {
}
}
}
-export function DocFocusOrOpen(doc: Doc, collectionDoc?: Doc) {
- const cv = collectionDoc && DocumentManager.Instance.getDocumentView(collectionDoc);
- const dv = DocumentManager.Instance.getDocumentView(doc, (cv?.ComponentView as CollectionFreeFormView)?.props.CollectionView);
- if (dv) {
- DocumentManager.Instance.showDocumentView(dv, { willZoomCentered: true });
- } else {
- const context = doc.context !== Doc.MyFilesystem && Cast(doc.context, Doc, null);
- const showDoc = context || doc;
- DocumentManager.Instance.showDocument(Doc.BestAlias(showDoc), { openLocation: OpenWhere.addRight }, () => DocumentManager.Instance.showDocument(doc, { willZoomCentered: true }));
- }
+export function DocFocusOrOpen(doc: Doc, options: DocFocusOptions = { willZoomCentered: true, openLocation: OpenWhere.addRight }, containingDoc?: Doc) {
+ const func = () => {
+ const cv = DocumentManager.Instance.getDocumentView(containingDoc);
+ const dv = DocumentManager.Instance.getDocumentView(doc, cv);
+ if (dv && (!containingDoc || dv.props.docViewPath().lastElement()?.Document === containingDoc)) {
+ DocumentManager.Instance.showDocumentView(dv, options).then(() => dv && Doc.linkFollowHighlight(dv.rootDoc));
+ } else {
+ const showDoc = Doc.BestAlias(DocCast((containingDoc ?? doc.context) !== Doc.MyFilesystem ? containingDoc ?? doc.context : undefined, doc));
+ DocumentManager.Instance.showDocument(showDoc, { ...options, toggleTarget: undefined }, () => DocumentManager.Instance.showDocument(doc, options)).then(() => {
+ const cv = DocumentManager.Instance.getDocumentView(containingDoc);
+ const dv = DocumentManager.Instance.getDocumentView(doc, cv);
+ dv && Doc.linkFollowHighlight(dv.rootDoc);
+ });
+ }
+ };
+ if (doc.hidden) {
+ doc.hidden = false;
+ options.toggleTarget = false;
+ setTimeout(func);
+ } else func();
}
ScriptingGlobals.add(DocFocusOrOpen);
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 7d2aa813f..7e6de5e67 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -3,10 +3,8 @@ import { DateField } from '../../fields/DateField';
import { Doc, Field, Opt, StrListCast } from '../../fields/Doc';
import { List } from '../../fields/List';
import { PrefetchProxy } from '../../fields/Proxy';
-import { listSpec } from '../../fields/Schema';
-import { SchemaHeaderField } from '../../fields/SchemaHeaderField';
import { ScriptField } from '../../fields/ScriptField';
-import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../fields/Types';
+import { BoolCast, ScriptCast, StrCast } from '../../fields/Types';
import { emptyFunction, Utils } from '../../Utils';
import { Docs, DocUtils } from '../documents/Documents';
import * as globalCssVariables from '../views/global/globalCssVariables.scss';
diff --git a/src/client/util/Import & Export/DirectoryImportBox.tsx b/src/client/util/Import & Export/DirectoryImportBox.tsx
index 559958c2b..76b1323c4 100644
--- a/src/client/util/Import & Export/DirectoryImportBox.tsx
+++ b/src/client/util/Import & Export/DirectoryImportBox.tsx
@@ -14,12 +14,14 @@ import { AcceptableMedia, Upload } from '../../../server/SharedMediaTypes';
import { Utils } from '../../../Utils';
import { GooglePhotos } from '../../apis/google_docs/GooglePhotosClientUtils';
import { Docs, DocumentOptions, DocUtils } from '../../documents/Documents';
+import { DocumentType } from '../../documents/DocumentTypes';
import { Networking } from '../../Network';
import { FieldView, FieldViewProps } from '../../views/nodes/FieldView';
import { DocumentManager } from '../DocumentManager';
import './DirectoryImportBox.scss';
import ImportMetadataEntry, { keyPlaceholder, valuePlaceholder } from './ImportMetadataEntry';
import React = require('react');
+import _ = require('lodash');
const unsupported = ['text/html', 'text/plain'];
@@ -155,8 +157,8 @@ export class DirectoryImportBox extends React.Component<FieldViewProps> {
x: NumCast(doc.x),
y: NumCast(doc.y) + offset,
};
- const parent = this.props.ContainingCollectionView;
- if (parent) {
+ const parent = _.nth(this.props.docViewPath(), -2); // last element of path is this box's document view, 2nd to last is any collection or other document that may contain it.
+ if (parent?.rootDoc.type === DocumentType.COL) {
let importContainer: Doc;
if (docs.length < 50) {
importContainer = Docs.Create.MasonryDocument(docs, options);
diff --git a/src/client/util/ReplayMovements.ts b/src/client/util/ReplayMovements.ts
index d5bffc5e2..40261985a 100644
--- a/src/client/util/ReplayMovements.ts
+++ b/src/client/util/ReplayMovements.ts
@@ -7,6 +7,7 @@ import { CollectionDockingView } from '../views/collections/CollectionDockingVie
import { DocServer } from '../DocServer';
import { Movement, Presentation } from './TrackMovements';
import { OpenWhereMod } from '../views/nodes/DocumentView';
+import { returnTransparent } from '../../Utils';
export class ReplayMovements {
private timers: NodeJS.Timeout[] | null;
@@ -60,17 +61,11 @@ export class ReplayMovements {
return;
}
- let docIdtoDoc: Map<string, Doc> = new Map();
- try {
- docIdtoDoc = await this.loadPresentation(presentation);
- } catch {
- console.error('[recordingApi.ts] setVideoBox(): error loading presentation - no replay movements');
- throw 'error loading docs from server';
- }
+ const docIdtoDoc = this.loadPresentation(presentation);
this.videoBoxDisposeFunc = reaction(
() => ({ playing: videoBox._playing, timeViewed: videoBox.player?.currentTime || 0 }),
- ({ playing, timeViewed }) => (playing ? this.playMovements(presentation, docIdtoDoc, timeViewed) : this.pauseMovements())
+ ({ playing, timeViewed }) => (playing ? this.playMovements(presentation, timeViewed) : this.pauseMovements())
);
this.videoBox = videoBox;
};
@@ -93,45 +88,33 @@ export class ReplayMovements {
this.pauseMovements();
};
- loadPresentation = async (presentation: Presentation) => {
+ loadPresentation = (presentation: Presentation) => {
const { movements } = presentation;
if (movements === null) {
throw '[recordingApi.ts] followMovements() failed: no presentation data';
}
// generate a set of all unique docIds
- const docIds = new Set<string>();
- for (const { docId } of movements) {
- if (!docIds.has(docId)) docIds.add(docId);
- }
-
- const docIdtoDoc = new Map<string, Doc>();
-
- let refFields = await DocServer.GetRefFields([...docIds.keys()]);
- for (const docId in refFields) {
- if (!refFields[docId]) {
- throw `one field was undefined`;
- }
- docIdtoDoc.set(docId, refFields[docId] as Doc);
+ const docs = new Set<Doc>();
+ for (const { doc } of movements) {
+ if (!docs.has(doc)) docs.add(doc);
}
- // console.info('loadPresentation refFields', refFields, docIdtoDoc);
- return docIdtoDoc;
+ return docs;
};
// returns undefined if the docView isn't open on the screen
- getCollectionFFView = (docId: string) => {
- const isInView = DocumentManager.Instance.getDocumentViewById(docId);
+ getCollectionFFView = (doc: Doc) => {
+ const isInView = DocumentManager.Instance.getDocumentView(doc);
if (isInView) {
return isInView.ComponentView as CollectionFreeFormView;
}
};
// will open the doc in a tab then return the CollectionFFView that holds it
- openTab = (docId: string, docIdtoDoc: Map<string, Doc>) => {
- const doc = docIdtoDoc.get(docId);
- if (doc == undefined) {
- console.error(`docIdtoDoc did not contain docId ${docId}`);
+ openTab = (doc: Doc) => {
+ if (doc === undefined) {
+ console.error(`doc undefined`);
return undefined;
}
// console.log('openTab', docId, doc);
@@ -149,13 +132,12 @@ export class ReplayMovements {
document.Document._panY = panY;
};
- getFirstMovements = (movements: Movement[]): Map<string, Movement> => {
+ getFirstMovements = (movements: Movement[]): Map<Doc, Movement> => {
if (movements === null) return new Map();
// generate a set of all unique docIds
- const docIdtoFirstMove = new Map();
+ const docIdtoFirstMove = new Map<Doc, Movement>();
for (const move of movements) {
- const { docId } = move;
- if (!docIdtoFirstMove.has(docId)) docIdtoFirstMove.set(docId, move);
+ if (!docIdtoFirstMove.has(move.doc)) docIdtoFirstMove.set(move.doc, move);
}
return docIdtoFirstMove;
};
@@ -165,7 +147,7 @@ export class ReplayMovements {
Doc.UserDoc().presentationMode = 'none';
};
- public playMovements = (presentation: Presentation, docIdtoDoc: Map<string, Doc>, timeViewed: number = 0) => {
+ public playMovements = (presentation: Presentation, timeViewed: number = 0) => {
// console.info('playMovements', presentation, timeViewed, docIdtoDoc);
if (presentation.movements === null || presentation.movements.length === 0) {
@@ -183,13 +165,13 @@ export class ReplayMovements {
const handleFirstMovements = () => {
// if the first movement is a closed tab, open it
const firstMovement = filteredMovements[0];
- const isClosed = this.getCollectionFFView(firstMovement.docId) === undefined;
- if (isClosed) this.openTab(firstMovement.docId, docIdtoDoc);
+ const isClosed = this.getCollectionFFView(firstMovement.doc) === undefined;
+ if (isClosed) this.openTab(firstMovement.doc);
// for the open tabs, set it to the first move
const docIdtoFirstMove = this.getFirstMovements(filteredMovements);
- for (const [docId, firstMove] of docIdtoFirstMove) {
- const colFFView = this.getCollectionFFView(docId);
+ for (const [doc, firstMove] of docIdtoFirstMove) {
+ const colFFView = this.getCollectionFFView(doc);
if (colFFView) this.zoomAndPan(firstMove, colFFView);
}
};
@@ -200,12 +182,12 @@ export class ReplayMovements {
const timeDiff = movement.time - timeViewed * 1000;
return setTimeout(() => {
- const collectionFFView = this.getCollectionFFView(movement.docId);
+ const collectionFFView = this.getCollectionFFView(movement.doc);
if (collectionFFView) {
this.zoomAndPan(movement, collectionFFView);
} else {
// tab wasn't open - open it and play the movement
- const openedColFFView = this.openTab(movement.docId, docIdtoDoc);
+ const openedColFFView = this.openTab(movement.doc);
console.log('openedColFFView', openedColFFView);
openedColFFView && this.zoomAndPan(movement, openedColFFView);
}
diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts
index 313c255a0..bfad93334 100644
--- a/src/client/util/SelectionManager.ts
+++ b/src/client/util/SelectionManager.ts
@@ -1,4 +1,3 @@
-import { ModalManager } from '@material-ui/core';
import { action, observable, ObservableMap } from 'mobx';
import { computedFn } from 'mobx-utils';
import { Doc, Opt } from '../../fields/Doc';
@@ -64,8 +63,9 @@ export namespace SelectionManager {
export function DeselectView(docView?: DocumentView): void {
manager.DeselectView(docView);
}
- export function SelectView(docView: DocumentView, ctrlPressed: boolean): void {
- manager.SelectView(docView, ctrlPressed);
+ export function SelectView(docView: DocumentView | undefined, ctrlPressed: boolean): void {
+ if (!docView) DeselectAll();
+ else manager.SelectView(docView, ctrlPressed);
}
export function SelectSchemaViewDoc(document: Opt<Doc>, deselectAllFirst?: boolean): void {
if (deselectAllFirst) manager.DeselectAll();
diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx
index 3c05af4bb..a73eda04c 100644
--- a/src/client/util/SharingManager.tsx
+++ b/src/client/util/SharingManager.tsx
@@ -370,11 +370,10 @@ export class SharingManager extends React.Component<{}> {
const docs = SelectionManager.Views().length > 1 ? SelectionManager.Views().map(docView => docView.props.Document) : [this.targetDoc];
return (
<span
- className={'focus-span'}
+ className="focus-span"
title={title}
onClick={() => {
- let context: Opt<CollectionView>;
- if (this.targetDoc && this.targetDocView && docs.length === 1 && (context = this.targetDocView.props.ContainingCollectionView)) {
+ if (this.targetDoc && this.targetDocView && docs.length === 1) {
DocumentManager.Instance.showDocument(this.targetDoc, { willZoomCentered: true });
}
}}
diff --git a/src/client/util/TrackMovements.ts b/src/client/util/TrackMovements.ts
index 4a2ccd706..2f16307b3 100644
--- a/src/client/util/TrackMovements.ts
+++ b/src/client/util/TrackMovements.ts
@@ -9,7 +9,7 @@ export type Movement = {
panX: number;
panY: number;
scale: number;
- docId: string;
+ doc: Doc;
};
export type Presentation = {
@@ -28,7 +28,7 @@ export class TrackMovements {
private tracking: boolean;
private absoluteStart: number;
// instance variable for holding the FFViews and their disposers
- private recordingFFViews: Map<string, IReactionDisposer> | null;
+ private recordingFFViews: Map<Doc, IReactionDisposer> | null;
private tabChangeDisposeFunc: IReactionDisposer | null;
// create static instance and getter for global use
@@ -55,33 +55,33 @@ export class TrackMovements {
return this.currentPresentation.movements === null;
}
- private addRecordingFFView(doc: Doc, key: string = doc[Id]): void {
+ private addRecordingFFView(doc: Doc): void {
// console.info('adding dispose func : docId', key, 'doc', doc);
if (this.recordingFFViews === null) {
console.warn('addFFView on null RecordingApi');
return;
}
- if (this.recordingFFViews.has(key)) {
- console.warn('addFFView : key already in map');
+ if (this.recordingFFViews.has(doc)) {
+ console.warn('addFFView : doc already in map');
return;
}
const disposeFunc = reaction(
() => ({ x: NumCast(doc.panX, -1), y: NumCast(doc.panY, -1), scale: NumCast(doc.viewScale, 0) }),
- res => res.x !== -1 && res.y !== -1 && this.tracking && this.trackMovement(res.x, res.y, key, res.scale)
+ res => res.x !== -1 && res.y !== -1 && this.tracking && this.trackMovement(res.x, res.y, doc, res.scale)
);
- this.recordingFFViews?.set(key, disposeFunc);
+ this.recordingFFViews?.set(doc, disposeFunc);
}
- private removeRecordingFFView = (key: string) => {
+ private removeRecordingFFView = (doc: Doc) => {
// console.info('removing dispose func : docId', key);
if (this.recordingFFViews === null) {
console.warn('removeFFView on null RecordingApi');
return;
}
- this.recordingFFViews.get(key)?.();
- this.recordingFFViews.delete(key);
+ this.recordingFFViews.get(doc)?.();
+ this.recordingFFViews.delete(doc);
};
// in the case where only one tab was changed (updates not across dashboards), set only one to true
@@ -90,15 +90,15 @@ export class TrackMovements {
// so that the size comparisons are correct, we must filter to only the FFViews
const isFFView = (doc: Doc) => doc && 'viewType' in doc && doc.viewType === 'freeform';
- const tabbedFFViews = new Set<string>();
+ const tabbedFFViews = new Set<Doc>();
for (const DashDoc of tabbedDocs) {
- if (isFFView(DashDoc)) tabbedFFViews.add(DashDoc[Id]);
+ if (isFFView(DashDoc)) tabbedFFViews.add(DashDoc);
}
// new tab was added - need to add it
if (tabbedFFViews.size > this.recordingFFViews.size) {
for (const DashDoc of tabbedDocs) {
- if (!this.recordingFFViews.has(DashDoc[Id])) {
+ if (!this.recordingFFViews.has(DashDoc)) {
if (isFFView(DashDoc)) {
this.addRecordingFFView(DashDoc);
@@ -110,9 +110,9 @@ export class TrackMovements {
}
// tab was removed - need to remove it from recordingFFViews
else if (tabbedFFViews.size < this.recordingFFViews.size) {
- for (const [key] of this.recordingFFViews) {
- if (!tabbedFFViews.has(key)) {
- this.removeRecordingFFView(key);
+ for (const [doc] of this.recordingFFViews) {
+ if (!tabbedFFViews.has(doc)) {
+ this.removeRecordingFFView(doc);
if (onlyOne) return;
}
}
@@ -214,7 +214,7 @@ export class TrackMovements {
}
};
- private trackMovement = (panX: number, panY: number, docId: string, scale: number = 0) => {
+ private trackMovement = (panX: number, panY: number, doc: Doc, scale: number = 0) => {
// ensure we are recording to track
if (!this.tracking) {
console.error('[recordingApi.ts] trackMovements(): tracking is false');
@@ -231,7 +231,7 @@ export class TrackMovements {
// get the time
const time = new Date().getTime() - this.absoluteStart;
// make new movement object
- const movement: Movement = { time, panX, panY, scale, docId };
+ const movement: Movement = { time, panX, panY, scale, doc };
// add that movement to the current presentation data's movement array
this.currentPresentation.movements && this.currentPresentation.movements.push(movement);