aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/client/documents/DocUtils.ts36
-rw-r--r--src/client/documents/Documents.ts4
-rw-r--r--src/client/util/BranchingTrailManager.tsx5
-rw-r--r--src/client/util/CalendarManager.tsx20
-rw-r--r--src/client/util/CaptureManager.tsx9
-rw-r--r--src/client/util/CurrentUserUtils.ts24
-rw-r--r--src/client/util/DictationManager.ts44
-rw-r--r--src/client/util/DocumentManager.ts85
-rw-r--r--src/client/util/DragManager.ts13
-rw-r--r--src/client/util/GroupManager.tsx2
-rw-r--r--src/client/util/HypothesisUtils.ts10
-rw-r--r--src/client/util/Import & Export/DirectoryImportBox.tsx1
-rw-r--r--src/client/util/LinkFollower.ts31
-rw-r--r--src/client/util/LinkManager.ts9
-rw-r--r--src/client/util/PingManager.ts4
-rw-r--r--src/client/util/ReplayMovements.ts6
-rw-r--r--src/client/util/Scripting.ts9
-rw-r--r--src/client/util/SelectionManager.ts29
-rw-r--r--src/client/util/SettingsManager.tsx20
-rw-r--r--src/client/util/SharingManager.tsx12
-rw-r--r--src/client/util/SnappingManager.ts16
-rw-r--r--src/client/views/AntimodeMenu.tsx8
-rw-r--r--src/client/views/ComponentDecorations.tsx4
-rw-r--r--src/client/views/DocComponent.tsx2
-rw-r--r--src/client/views/DocViewUtils.ts21
-rw-r--r--src/client/views/DocumentButtonBar.tsx29
-rw-r--r--src/client/views/DocumentDecorations.tsx117
-rw-r--r--src/client/views/FieldsDropdown.tsx22
-rw-r--r--src/client/views/FilterPanel.tsx8
-rw-r--r--src/client/views/GestureOverlay.tsx6
-rw-r--r--src/client/views/GlobalKeyHandler.ts78
-rw-r--r--src/client/views/InkControlPtHandles.tsx6
-rw-r--r--src/client/views/InkStrokeProperties.ts3
-rw-r--r--src/client/views/InkTranscription.tsx1
-rw-r--r--src/client/views/InkingStroke.tsx2
-rw-r--r--src/client/views/LightboxView.tsx36
-rw-r--r--src/client/views/Main.tsx12
-rw-r--r--src/client/views/MainView.tsx85
-rw-r--r--src/client/views/MarqueeAnnotator.tsx1
-rw-r--r--src/client/views/OverlayView.tsx5
-rw-r--r--src/client/views/PropertiesButtons.tsx29
-rw-r--r--src/client/views/PropertiesDocBacklinksSelector.tsx8
-rw-r--r--src/client/views/PropertiesDocContextSelector.tsx3
-rw-r--r--src/client/views/PropertiesView.tsx50
-rw-r--r--src/client/views/ScriptBox.tsx8
-rw-r--r--src/client/views/ScriptingRepl.tsx16
-rw-r--r--src/client/views/SidebarAnnos.tsx8
-rw-r--r--src/client/views/StyleProp.ts24
-rw-r--r--src/client/views/StyleProvider.tsx105
-rw-r--r--src/client/views/collections/CollectionCarousel3DView.tsx5
-rw-r--r--src/client/views/collections/CollectionCarouselView.tsx2
-rw-r--r--src/client/views/collections/CollectionDockingView.tsx18
-rw-r--r--src/client/views/collections/CollectionMenu.tsx32
-rw-r--r--src/client/views/collections/CollectionNoteTakingView.tsx2
-rw-r--r--src/client/views/collections/CollectionPileView.tsx4
-rw-r--r--src/client/views/collections/CollectionStackedTimeline.tsx16
-rw-r--r--src/client/views/collections/CollectionStackingView.tsx2
-rw-r--r--src/client/views/collections/CollectionSubView.tsx11
-rw-r--r--src/client/views/collections/CollectionTimeView.tsx3
-rw-r--r--src/client/views/collections/CollectionTreeView.tsx17
-rw-r--r--src/client/views/collections/CollectionTreeViewType.ts5
-rw-r--r--src/client/views/collections/TabDocView.tsx216
-rw-r--r--src/client/views/collections/TreeView.tsx15
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormClusters.ts31
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx10
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormPannableContents.tsx9
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx88
-rw-r--r--src/client/views/collections/collectionFreeForm/MarqueeView.tsx15
-rw-r--r--src/client/views/collections/collectionLinear/CollectionLinearView.tsx10
-rw-r--r--src/client/views/collections/collectionMulticolumn/MulticolumnResizer.tsx2
-rw-r--r--src/client/views/collections/collectionMulticolumn/MultirowResizer.tsx2
-rw-r--r--src/client/views/collections/collectionSchema/CollectionSchemaView.tsx28
-rw-r--r--src/client/views/collections/collectionSchema/SchemaTableCell.tsx8
-rw-r--r--src/client/views/global/globalScripts.ts58
-rw-r--r--src/client/views/linking/LinkMenuGroup.tsx4
-rw-r--r--src/client/views/linking/LinkMenuItem.tsx31
-rw-r--r--src/client/views/newlightbox/ButtonMenu/ButtonMenu.tsx3
-rw-r--r--src/client/views/newlightbox/NewLightboxView.tsx27
-rw-r--r--src/client/views/newlightbox/components/Recommendation/Recommendation.tsx12
-rw-r--r--src/client/views/nodes/AudioBox.tsx25
-rw-r--r--src/client/views/nodes/CollectionFreeFormDocumentView.tsx41
-rw-r--r--src/client/views/nodes/ComparisonBox.tsx2
-rw-r--r--src/client/views/nodes/DataVizBox/DataVizBox.tsx3
-rw-r--r--src/client/views/nodes/DataVizBox/components/LineChart.tsx6
-rw-r--r--src/client/views/nodes/DataVizBox/components/PieChart.tsx2
-rw-r--r--src/client/views/nodes/DataVizBox/components/TableBox.tsx9
-rw-r--r--src/client/views/nodes/DocumentContentsView.tsx13
-rw-r--r--src/client/views/nodes/DocumentIcon.tsx11
-rw-r--r--src/client/views/nodes/DocumentLinksButton.tsx13
-rw-r--r--src/client/views/nodes/DocumentView.tsx203
-rw-r--r--src/client/views/nodes/FontIconBox/FontIconBox.tsx38
-rw-r--r--src/client/views/nodes/FunctionPlotBox.tsx7
-rw-r--r--src/client/views/nodes/ImageBox.tsx6
-rw-r--r--src/client/views/nodes/KeyValueBox.tsx4
-rw-r--r--src/client/views/nodes/LabelBox.tsx2
-rw-r--r--src/client/views/nodes/LinkAnchorBox.scss34
-rw-r--r--src/client/views/nodes/LinkAnchorBox.tsx118
-rw-r--r--src/client/views/nodes/LinkBox.tsx5
-rw-r--r--src/client/views/nodes/LinkDescriptionPopup.tsx3
-rw-r--r--src/client/views/nodes/LinkDocPreview.tsx26
-rw-r--r--src/client/views/nodes/LoadingBox.tsx21
-rw-r--r--src/client/views/nodes/MapBox/DirectionsAnchorMenu.tsx4
-rw-r--r--src/client/views/nodes/MapBox/MapAnchorMenu.tsx4
-rw-r--r--src/client/views/nodes/MapBox/MapBox.tsx6
-rw-r--r--src/client/views/nodes/MapBox/MapBox2.tsx6
-rw-r--r--src/client/views/nodes/MapboxMapBox/MapboxContainer.tsx6
-rw-r--r--src/client/views/nodes/PDFBox.tsx6
-rw-r--r--src/client/views/nodes/RecordingBox/RecordingBox.tsx16
-rw-r--r--src/client/views/nodes/ScreenshotBox.tsx11
-rw-r--r--src/client/views/nodes/VideoBox.tsx28
-rw-r--r--src/client/views/nodes/WebBox.tsx5
-rw-r--r--src/client/views/nodes/formattedText/DashFieldView.tsx5
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.tsx45
-rw-r--r--src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts4
-rw-r--r--src/client/views/nodes/formattedText/RichTextMenu.tsx17
-rw-r--r--src/client/views/nodes/formattedText/SummaryView.tsx5
-rw-r--r--src/client/views/nodes/generativeFill/GenerativeFill.tsx8
-rw-r--r--src/client/views/nodes/trails/PresBox.tsx58
-rw-r--r--src/client/views/nodes/trails/PresElementBox.tsx11
-rw-r--r--src/client/views/pdf/AnchorMenu.tsx6
-rw-r--r--src/client/views/pdf/Annotation.tsx6
-rw-r--r--src/client/views/pdf/PDFViewer.tsx6
-rw-r--r--src/client/views/search/SearchBox.tsx31
-rw-r--r--src/client/views/selectedDoc/SelectedDocView.tsx14
-rw-r--r--src/client/views/topbar/TopBar.tsx8
-rw-r--r--src/fields/Doc.ts19
-rw-r--r--src/fields/ScriptField.ts1
-rw-r--r--src/fields/documentSchemas.ts1
-rw-r--r--src/mobile/MobileInterface.tsx9
-rw-r--r--src/server/SharedMediaTypes.ts5
130 files changed, 1254 insertions, 1461 deletions
diff --git a/src/client/documents/DocUtils.ts b/src/client/documents/DocUtils.ts
index 0a47e0359..0c9fe0315 100644
--- a/src/client/documents/DocUtils.ts
+++ b/src/client/documents/DocUtils.ts
@@ -9,7 +9,7 @@ import { ClientUtils } from '../../ClientUtils';
import * as JSZipUtils from '../../JSZipUtils';
import { decycle } from '../../decycler/decycler';
import { DateField } from '../../fields/DateField';
-import { Doc, DocListCast, Field, FieldType, LinkedTo, Opt, SetActiveAudioLinker, StrListCast } from '../../fields/Doc';
+import { Doc, DocListCast, Field, FieldResult, FieldType, LinkedTo, Opt, StrListCast } from '../../fields/Doc';
import { DocData } from '../../fields/DocSymbols';
import { Id } from '../../fields/FieldSymbols';
import { InkDataFieldName, InkField } from '../../fields/InkField';
@@ -29,9 +29,7 @@ import { SerializationHelper } from '../util/SerializationHelper';
import { UndoManager, undoable } from '../util/UndoManager';
import { ContextMenu } from '../views/ContextMenu';
import { ContextMenuProps } from '../views/ContextMenuItem';
-import { FieldViewProps } from '../views/nodes/FieldView';
import { LinkDescriptionPopup } from '../views/nodes/LinkDescriptionPopup';
-import { LoadingBox } from '../views/nodes/LoadingBox';
import { OpenWhere } from '../views/nodes/OpenWhere';
import { TaskCompletionBox } from '../views/nodes/TaskCompletedBox';
import { DocumentType } from './DocumentTypes';
@@ -50,7 +48,7 @@ export namespace DocUtils {
}
if (key === LinkedTo) {
// links are not a field value, so handled here. value is an expression of form ([field=]idToDoc("..."))
- const allLinks = LinkManager.Instance.getAllRelatedLinks(doc);
+ const allLinks = Doc.Links(doc);
const matchLink = (val: string, anchor: Doc) => {
const linkedToExp = (val ?? '').split('=');
if (linkedToExp.length === 1) return Field.toScriptString(anchor) === val;
@@ -131,7 +129,7 @@ export namespace DocUtils {
if (!unsets.length && !exists.length && !xs.length && !checks.length && !matches.length) return true;
const failsNotEqualFacets = !xs.length ? false : xs.some(value => matchFieldValue(d, facetKey, value));
const satisfiesCheckFacets = !checks.length ? true : checks.some(value => matchFieldValue(d, facetKey, value));
- const satisfiesExistsFacets = !exists.length ? true : facetKey !== LinkedTo ? d[facetKey] !== undefined : LinkManager.Instance.getAllRelatedLinks(d).length;
+ const satisfiesExistsFacets = !exists.length ? true : facetKey !== LinkedTo ? d[facetKey] !== undefined : Doc.Links(d).length;
const satisfiesUnsetsFacets = !unsets.length ? true : d[facetKey] === undefined;
const satisfiesMatchFacets = !matches.length
? true
@@ -170,19 +168,7 @@ export namespace DocUtils {
return rangeFilteredDocs;
}
- export const ActiveRecordings: { props: FieldViewProps; getAnchor: (addAsAnnotation: boolean) => Doc }[] = [];
-
- export function MakeLinkToActiveAudio(getSourceDoc: () => Doc | undefined, broadcastEvent = true) {
- broadcastEvent && runInAction(() => { Doc.RecordingEvent += 1; }); // prettier-ignore
- return DocUtils.ActiveRecordings.map(audio => {
- const sourceDoc = getSourceDoc();
- return sourceDoc && DocUtils.MakeLink(sourceDoc, audio.getAnchor(true) || audio.props.Document, { link_displayLine: false, link_relationship: 'recording annotation:linked recording', link_description: 'recording timeline' });
- });
- }
-
- SetActiveAudioLinker(MakeLinkToActiveAudio);
-
- export function MakeLink(source: Doc, target: Doc, linkSettings: { link_relationship?: string; link_description?: string; link_displayLine?: boolean }, id?: string, showPopup?: number[]) {
+ export function MakeLink(source: Doc, target: Doc, linkSettings: { link_relationship?: string; link_description?: string }, id?: string, showPopup?: number[]) {
if (!linkSettings.link_relationship) linkSettings.link_relationship = target.type === DocumentType.RTF ? 'Commentary:Comments On' : 'link';
if (target.doc === Doc.UserDoc()) return undefined;
@@ -232,7 +218,6 @@ export namespace DocUtils {
title: ComputedField.MakeFunction('generateLinkTitle(this)') as any,
link_anchor_1_useSmallAnchor: source.useSmallAnchor ? true : undefined,
link_anchor_2_useSmallAnchor: target.useSmallAnchor ? true : undefined,
- link_displayLine: linkSettings.link_displayLine,
link_relationship: linkSettings.link_relationship,
link_description: linkSettings.link_description,
x: ComputedField.MakeFunction(`((this.${a}?.x||0)+(this.${b}?.x||0))/2`) as any,
@@ -256,7 +241,6 @@ export namespace DocUtils {
const script = scripts[key];
if (ScriptCast(doc[key])?.script.originalScript !== scripts[key] && script) {
(key.startsWith('_') ? doc : Doc.GetProto(doc))[key] = ScriptField.MakeScript(script, {
- self: Doc.name,
this: Doc.name,
dragData: Doc.DocDragDataName,
value: 'any',
@@ -579,7 +563,7 @@ export namespace DocUtils {
export function LeavePushpin(doc: Doc, annotationField: string) {
if (doc.followLinkToggle) return undefined;
const context = Cast(doc.embedContainer, Doc, null) ?? Cast(doc.annotationOn, Doc, null);
- const hasContextAnchor = LinkManager.Links(doc).some(l => (l.link_anchor_2 === doc && Cast(l.link_anchor_1, Doc, null)?.annotationOn === context) || (l.link_anchor_1 === doc && Cast(l.link_anchor_2, Doc, null)?.annotationOn === context));
+ const hasContextAnchor = Doc.Links(doc).some(l => (l.link_anchor_2 === doc && Cast(l.link_anchor_1, Doc, null)?.annotationOn === context) || (l.link_anchor_1 === doc && Cast(l.link_anchor_2, Doc, null)?.annotationOn === context));
if (context && !hasContextAnchor && (context.type === DocumentType.VID || context.type === DocumentType.WEB || context.type === DocumentType.PDF || context.type === DocumentType.IMG)) {
const pushpin = Docs.Create.FontIconDocument({
title: '',
@@ -673,7 +657,7 @@ export namespace DocUtils {
proto.data_duration = result.duration;
}
if (overwriteDoc) {
- LoadingBox.removeCurrentlyLoading(overwriteDoc);
+ Doc.removeCurrentlyLoading(overwriteDoc);
}
generatedDocuments.push(doc);
}
@@ -717,7 +701,7 @@ export namespace DocUtils {
if (overwriteDoc) {
overwriteDoc.isLoading = false;
overwriteDoc.loadingError = (result as any).message;
- LoadingBox.removeCurrentlyLoading(overwriteDoc);
+ Doc.removeCurrentlyLoading(overwriteDoc);
}
} else newFilename && processFileupload(generatedDocuments, newFilename, mimetype ?? '', result, options, overwriteDoc);
});
@@ -755,7 +739,7 @@ export namespace DocUtils {
if ((result as any).message) {
if (overwriteDoc) {
overwriteDoc.loadingError = (result as any).message;
- LoadingBox.removeCurrentlyLoading(overwriteDoc);
+ Doc.removeCurrentlyLoading(overwriteDoc);
}
} else newFilename && mimetype && processFileupload(generatedDocuments, newFilename, mimetype, result, options, overwriteDoc);
});
@@ -868,6 +852,10 @@ export function FollowLinkScript() {
return ScriptField.MakeScript('return followLink(this,altKey)', { altKey: 'boolean' });
}
+export function IsFollowLinkScript(field: FieldResult<FieldType>) {
+ return ScriptCast(field)?.script.originalScript.includes('return followLink(');
+}
+
ScriptingGlobals.add('Docs', Docs);
// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function copyDragFactory(dragFactory: Doc, asDelegate?: boolean) {
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index a3fea1ce4..1c18c0d84 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -19,7 +19,6 @@ import { SharingPermissions } from '../../fields/util';
import { PointData } from '../../pen-gestures/GestureTypes';
import { DocServer } from '../DocServer';
import { dropActionType } from '../util/DropActionTypes';
-import { LinkManager } from '../util/LinkManager';
import { CollectionViewType, DocumentType } from './DocumentTypes';
class EmptyBox {
@@ -394,7 +393,6 @@ export class DocumentOptions {
link?: string;
link_description?: string; // added for links
link_relationship?: string; // type of relatinoship a link represents
- link_displayLine?: BOOLt = new BoolInfo('whether a link line should be dipslayed between the two link anchors');
link_displayArrow?: BOOLt = new BoolInfo("whether to display link's directional arrowhead");
link_anchor_1?: DOCt = new DocInfo('start anchor of a link');
link_anchor_2?: DOCt = new DocInfo('end anchor of a link');
@@ -810,7 +808,7 @@ export namespace Docs {
'link'
);
- LinkManager.Instance.addLink(linkDoc);
+ Doc.AddLink(linkDoc);
return linkDoc;
}
diff --git a/src/client/util/BranchingTrailManager.tsx b/src/client/util/BranchingTrailManager.tsx
index 28c00644f..119d103c5 100644
--- a/src/client/util/BranchingTrailManager.tsx
+++ b/src/client/util/BranchingTrailManager.tsx
@@ -6,8 +6,8 @@ import * as React from 'react';
import { Doc } from '../../fields/Doc';
import { Id } from '../../fields/FieldSymbols';
import { OverlayView } from '../views/OverlayView';
+import { DocumentView } from '../views/nodes/DocumentView';
import { PresBox } from '../views/nodes/trails';
-import { DocumentManager } from './DocumentManager';
@observer
export class BranchingTrailManager extends React.Component {
@@ -46,7 +46,6 @@ export class BranchingTrailManager extends React.Component {
// hi.overlayY = 100;
// Doc.AddToMyOverlay(hi);
- console.log(DocumentManager._overlayViews);
};
@action setSlideHistoryStack = action((newArr: String[]) => {
@@ -103,7 +102,7 @@ export class BranchingTrailManager extends React.Component {
this.setSlideHistoryStack(newStack);
removed.forEach(info => this.containsSet.delete(info.toString()));
- DocumentManager.Instance.showDocument(targetDoc, { willZoomCentered: true });
+ DocumentView.showDocument(targetDoc, { willZoomCentered: true });
if (this.slideHistoryStack.length === 0) {
Doc.UserDoc().isBranchingMode = false;
}
diff --git a/src/client/util/CalendarManager.tsx b/src/client/util/CalendarManager.tsx
index 8e3936d34..77cf80151 100644
--- a/src/client/util/CalendarManager.tsx
+++ b/src/client/util/CalendarManager.tsx
@@ -13,15 +13,12 @@ import { Doc, DocListCast } from '../../fields/Doc';
import { DocData } from '../../fields/DocSymbols';
import { StrCast } from '../../fields/Types';
import { Docs } from '../documents/Documents';
-import { DictationOverlay } from '../views/DictationOverlay';
import { MainViewModal } from '../views/MainViewModal';
import { ObservableReactComponent } from '../views/ObservableReactComponent';
import { DocumentView } from '../views/nodes/DocumentView';
import { TaskCompletionBox } from '../views/nodes/TaskCompletedBox';
import './CalendarManager.scss';
-import { DocumentManager } from './DocumentManager';
-import { SelectionManager } from './SelectionManager';
-import { SettingsManager } from './SettingsManager';
+import { SnappingManager } from './SnappingManager';
// import 'react-date-range/dist/styles.css';
// import 'react-date-range/dist/theme/default.css';
@@ -85,11 +82,9 @@ export class CalendarManager extends ObservableReactComponent<{}> {
};
public open = (target?: DocumentView, targetDoc?: Doc) => {
- console.log('hi');
runInAction(() => {
this.targetDoc = targetDoc || target?.Document;
this.targetDocView = target;
- DictationOverlay.Instance.hasActiveModal = true;
this.isOpen = this.targetDoc !== undefined;
});
};
@@ -99,7 +94,6 @@ export class CalendarManager extends ObservableReactComponent<{}> {
TaskCompletionBox.taskCompleted = false;
setTimeout(
action(() => {
- DictationOverlay.Instance.hasActiveModal = false;
this.targetDoc = undefined;
}),
500
@@ -137,7 +131,7 @@ export class CalendarManager extends ObservableReactComponent<{}> {
// TODO: Make undoable
private addToCalendar = () => {
- const docs = SelectionManager.Views.length < 2 ? [this.targetDoc] : SelectionManager.Views.map(docView => docView.Document);
+ const docs = DocumentView.Selected().length < 2 ? [this.targetDoc] : DocumentView.Selected().map(docView => docView.Document);
const targetDoc = this.layoutDocAcls ? docs[0] : docs[0]?.[DocData]; // doc to add to calendar
console.log(targetDoc);
@@ -190,14 +184,14 @@ export class CalendarManager extends ObservableReactComponent<{}> {
private focusOn = (contents: string) => {
const title = this.targetDoc ? StrCast(this.targetDoc.title) : '';
- const docs = SelectionManager.Views.length > 1 ? SelectionManager.Views.map(docView => docView.Document) : [this.targetDoc];
+ const docs = DocumentView.Selected().length > 1 ? DocumentView.Selected().map(docView => docView.Document) : [this.targetDoc];
return (
<span
className="focus-span"
title={title}
onClick={() => {
if (this.targetDoc && this.targetDocView && docs.length === 1) {
- DocumentManager.Instance.showDocument(this.targetDoc, { willZoomCentered: true });
+ DocumentView.showDocument(this.targetDoc, { willZoomCentered: true });
}
}}
onPointerEnter={action(() => {
@@ -251,17 +245,17 @@ export class CalendarManager extends ObservableReactComponent<{}> {
@computed
get calendarInterface() {
- const docs = SelectionManager.Views.length < 2 ? [this.targetDoc] : SelectionManager.Views.map(docView => docView.Document);
+ const docs = DocumentView.Selected().length < 2 ? [this.targetDoc] : DocumentView.Selected().map(docView => docView.Document);
const targetDoc = this.layoutDocAcls ? docs[0] : docs[0]?.[DocData];
return (
<div
className="calendar-interface"
style={{
- background: SettingsManager.userBackgroundColor,
+ background: SnappingManager.userBackgroundColor,
color: StrCast(Doc.UserDoc().userColor),
}}>
- <p className="selected-doc-title" style={{ color: SettingsManager.userColor }}>
+ <p className="selected-doc-title" style={{ color: SnappingManager.userColor }}>
<b>{this.focusOn(docs.length < 2 ? StrCast(targetDoc?.title, 'this document') : '-multiple-')}</b>
</p>
<div className="creation-type-container">
diff --git a/src/client/util/CaptureManager.tsx b/src/client/util/CaptureManager.tsx
index a03c80f2a..4fd934774 100644
--- a/src/client/util/CaptureManager.tsx
+++ b/src/client/util/CaptureManager.tsx
@@ -10,8 +10,7 @@ import { DocCast, StrCast } from '../../fields/Types';
import { LightboxView } from '../views/LightboxView';
import { MainViewModal } from '../views/MainViewModal';
import './CaptureManager.scss';
-import { LinkManager } from './LinkManager';
-import { SelectionManager } from './SelectionManager';
+import { DocumentView } from '../views/nodes/DocumentView';
@observer
export class CaptureManager extends React.Component<{}> {
@@ -56,7 +55,7 @@ export class CaptureManager extends React.Component<{}> {
const doc = this._document;
const order: JSX.Element[] = [];
if (doc) {
- LinkManager.Links(doc).forEach((l, i) =>
+ Doc.Links(doc).forEach((l, i) =>
order.push(
<div className="list-item">
<div className="number">{i}</div>
@@ -88,8 +87,8 @@ export class CaptureManager extends React.Component<{}> {
<div
className="cancel"
onClick={() => {
- const selected = SelectionManager.Views.slice();
- SelectionManager.DeselectAll();
+ const selected = DocumentView.Selected();
+ DocumentView.DeselectAll();
selected.map(dv => dv.props.removeDocument?.(dv.Document));
this.close();
}}>
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 15c8fec5a..ffc1304bf 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -1,4 +1,4 @@
-import { observable, reaction, runInAction } from "mobx";
+import { reaction, runInAction } from "mobx";
import * as rp from 'request-promise';
import { ClientUtils, OmitKeys } from "../../ClientUtils";
import { Doc, DocListCast, DocListCastAsync, Opt } from "../../fields/Doc";
@@ -19,7 +19,8 @@ import { CollectionViewType, DocumentType } from "../documents/DocumentTypes";
import { Docs, DocumentOptions, FInfo, FInfoFieldType } from "../documents/Documents";
import { DashboardView } from "../views/DashboardView";
import { OverlayView } from "../views/OverlayView";
-import { CollectionTreeView, TreeViewType } from "../views/collections/CollectionTreeView";
+import { CollectionTreeView } from "../views/collections/CollectionTreeView";
+import { TreeViewType } from "../views/collections/CollectionTreeViewType";
import { Colors } from "../views/global/globalEnums";
import { mediaState } from "../views/nodes/AudioBox";
import { ButtonType, FontIconBox } from "../views/nodes/FontIconBox/FontIconBox";
@@ -30,8 +31,9 @@ import { ImportElementBox } from "../views/nodes/importBox/ImportElementBox";
import { DragManager } from "./DragManager";
import { dropActionType } from "./DropActionTypes";
import { MakeTemplate } from "./DropConverter";
-import { LinkManager, UPDATE_SERVER_CACHE } from "./LinkManager";
+import { UPDATE_SERVER_CACHE } from "./LinkManager";
import { ScriptingGlobals } from "./ScriptingGlobals";
+import { SelectionManager } from "./SelectionManager";
import { ColorScheme } from "./SettingsManager";
import { SnappingManager } from "./SnappingManager";
import { UndoManager } from "./UndoManager";
@@ -937,14 +939,13 @@ pie title Minerals in my tap water
DocUtils.AssignDocField(doc, "globalScriptDatabase", () => Docs.Prototypes.MainScriptDocument(), {});
DocUtils.AssignDocField(doc, "myHeaderBar", (opts) => Docs.Create.MulticolumnDocument([], opts), { title: "My Header Bar", isSystem: true, _chromeHidden:true, layout_maxShown: 10, childLayoutFitWidth:false, childDocumentsActive:false, dropAction: dropActionType.move}); // drop down panel at top of dashboard for stashing documents
- Doc.AddDocToList(Doc.MyFilesystem, undefined, Doc.MyDashboards)
- Doc.AddDocToList(Doc.MyFilesystem, undefined, Doc.MySharedDocs)
- Doc.AddDocToList(Doc.MyFilesystem, undefined, Doc.MyRecentlyClosed)
-
- Doc.GetProto(DocCast(Doc.UserDoc().emptyWebpage)).data = new WebField("https://www.wikipedia.org")
+ SelectionManager.DeselectAll(); // this forces SelectionManager implementation to copy over to DocumentView's API. This also triggers the LinkManager to be created
+
+ Doc.AddDocToList(Doc.MyFilesystem, undefined, Doc.MyDashboards);
+ Doc.AddDocToList(Doc.MyFilesystem, undefined, Doc.MySharedDocs);
+ Doc.AddDocToList(Doc.MyFilesystem, undefined, Doc.MyRecentlyClosed);
- // eslint-disable-next-line no-new
- new LinkManager();
+ Doc.GetProto(DocCast(Doc.UserDoc().emptyWebpage)).data = new WebField("https://www.wikipedia.org");
DocServer.CacheNeedsUpdate() && setTimeout(UPDATE_SERVER_CACHE, 2500);
setInterval(UPDATE_SERVER_CACHE, 120000);
@@ -969,12 +970,11 @@ pie title Minerals in my tap water
});
}
- @observable public static ServerVersion: string = ';'
public static async loadCurrentUser() {
return rp.get(ClientUtils.prepend("/getCurrentUser")).then(async response => {
if (response) {
const result: { version: string, userDocumentId: string, sharingDocumentId: string, linkDatabaseId: string, email: string, cacheDocumentIds: string, resolvedPorts: string } = JSON.parse(response);
- runInAction(() => { CurrentUserUtils.ServerVersion = result.version; });
+ runInAction(() => { SnappingManager.SetServerVersion(result.version); });
ClientUtils.SetCurrentUserEmail(result.email);
resolvedPorts = result.resolvedPorts as any;
DocServer.init(window.location.protocol, window.location.hostname, resolvedPorts?.socket, result.email);
diff --git a/src/client/util/DictationManager.ts b/src/client/util/DictationManager.ts
index 97ee628e2..bc9fe813f 100644
--- a/src/client/util/DictationManager.ts
+++ b/src/client/util/DictationManager.ts
@@ -10,12 +10,13 @@ import { RichTextField } from '../../fields/RichTextField';
import { listSpec } from '../../fields/Schema';
import { Cast, CastCtor } from '../../fields/Types';
import { AudioField, ImageField } from '../../fields/URLField';
+import { AudioAnnoState } from '../../server/SharedMediaTypes';
+import { Networking } from '../Network';
import { DocumentType } from '../documents/DocumentTypes';
import { Docs } from '../documents/Documents';
import { DictationOverlay } from '../views/DictationOverlay';
import { DocumentView } from '../views/nodes/DocumentView';
import { OpenWhere } from '../views/nodes/OpenWhere';
-import { SelectionManager } from './SelectionManager';
import { UndoManager } from './UndoManager';
/**
@@ -244,7 +245,7 @@ export namespace DictationManager {
export const execute = async (phrase: string) =>
UndoManager.RunInBatch(async () => {
console.log('PHRASE: ' + phrase);
- const targets = SelectionManager.Views;
+ const targets = DocumentView.Selected();
if (!targets || !targets.length) {
return undefined;
}
@@ -395,4 +396,43 @@ export namespace DictationManager {
},
];
}
+ export function recordAudioAnnotation(dataDoc: Doc, field: string, onRecording?: (stop: () => void) => void, onEnd?: () => void) {
+ let gumStream: any;
+ let recorder: any;
+ navigator.mediaDevices.getUserMedia({ audio: true }).then(stream => {
+ let audioTextAnnos = Cast(dataDoc[field + '_audioAnnotations_text'], listSpec('string'), null);
+ if (audioTextAnnos) audioTextAnnos.push('');
+ else audioTextAnnos = dataDoc[field + '_audioAnnotations_text'] = new List<string>(['']);
+ DictationManager.Controls.listen({
+ interimHandler: value => { audioTextAnnos[audioTextAnnos.length - 1] = value; }, // prettier-ignore
+ continuous: { indefinite: false },
+ }).then(results => {
+ if (results && [DictationManager.Controls.Infringed].includes(results)) {
+ DictationManager.Controls.stop();
+ }
+ onEnd?.();
+ });
+
+ gumStream = stream;
+ recorder = new MediaRecorder(stream);
+ recorder.ondataavailable = async (e: any) => {
+ const [{ result }] = await Networking.UploadFilesToServer({ file: e.data });
+ if (!(result instanceof Error)) {
+ const audioField = new AudioField(result.accessPaths.agnostic.client);
+ const audioAnnos = Cast(dataDoc[field + '_audioAnnotations'], listSpec(AudioField), null);
+ if (audioAnnos) audioAnnos.push(audioField);
+ else dataDoc[field + '_audioAnnotations'] = new List([audioField]);
+ }
+ };
+ recorder.start();
+ const stopFunc = () => {
+ recorder.stop();
+ DictationManager.Controls.stop(/* false */);
+ dataDoc.audioAnnoState = AudioAnnoState.stopped;
+ gumStream.getAudioTracks()[0].stop();
+ };
+ if (onRecording) onRecording(stopFunc);
+ else setTimeout(stopFunc, 5000);
+ });
+ }
}
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index 8f0c2b0bf..5bcac7330 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -1,23 +1,17 @@
import { Howl } from 'howler';
import { action, computed, makeObservable, observable, ObservableSet, observe } from 'mobx';
import { Doc, Opt } from '../../fields/Doc';
-import { AclAdmin, AclEdit, Animation, DocData } from '../../fields/DocSymbols';
+import { Animation, DocData } from '../../fields/DocSymbols';
import { Id } from '../../fields/FieldSymbols';
import { listSpec } from '../../fields/Schema';
import { Cast, DocCast, NumCast, StrCast } from '../../fields/Types';
import { AudioField } from '../../fields/URLField';
-import { GetEffectiveAcl } from '../../fields/util';
import { CollectionViewType } from '../documents/DocumentTypes';
-import { TabDocView } from '../views/collections/TabDocView';
import { LightboxView } from '../views/LightboxView';
import { DocumentView, DocumentViewInternal } from '../views/nodes/DocumentView';
import { FocusViewOptions } from '../views/nodes/FocusViewOptions';
-import { KeyValueBox } from '../views/nodes/KeyValueBox';
-import { LinkAnchorBox } from '../views/nodes/LinkAnchorBox';
import { OpenWhere } from '../views/nodes/OpenWhere';
import { PresBox } from '../views/nodes/trails';
-import { ScriptingGlobals } from './ScriptingGlobals';
-import { SelectionManager } from './SelectionManager';
type childIterator = { viewSpec: Opt<Doc>; childDocView: Opt<DocumentView>; focused: boolean; contextPath: Doc[] };
export class DocumentManager {
@@ -29,10 +23,9 @@ export class DocumentManager {
}
// global holds all of the nodes (regardless of which collection they're in)
- @observable _documentViews = new Set<DocumentView>();
- @observable.shallow public CurrentlyLoading: Doc[] = [];
+ @observable private _documentViews = new Set<DocumentView>();
@computed public get DocumentViews() {
- return Array.from(this._documentViews).filter(view => !(view.ComponentView instanceof KeyValueBox) && (!LightboxView.LightboxDoc || LightboxView.Contains(view)));
+ return Array.from(this._documentViews).filter(view => (!view.ComponentView?.dontRegisterView?.() && !LightboxView.LightboxDoc) || LightboxView.Contains(view));
}
public AddDocumentView(dv: DocumentView) {
this._documentViews.add(dv);
@@ -44,7 +37,19 @@ export class DocumentManager {
// private constructor so no other class can create a nodemanager
private constructor() {
makeObservable(this);
- observe(this.CurrentlyLoading, change => {
+
+ DocumentView.allViews = () => this.DocumentViews;
+ DocumentView.addView = this.AddView;
+ DocumentView.removeView = this.RemoveView;
+ DocumentView.showDocument = this.showDocument;
+ DocumentView.showDocumentView = this.showDocumentView;
+ DocumentView.linkCommonAncestor = DocumentManager.LinkCommonAncestor;
+ DocumentView.addViewRenderedCb = this.AddViewRenderedCb;
+ DocumentView.getFirstDocumentView = this.getFirstDocumentView;
+ DocumentView.getDocumentView = this.getDocumentView;
+ DocumentView.getContextPath = DocumentManager.GetContextPath;
+ DocumentView.getLightboxDocumentView = this.getLightboxDocumentView;
+ observe(Doc.CurrentlyLoading, change => {
// watch CurrentlyLoading-- when something is loaded, it's removed from the list and we have to update its icon if it were iconified since LoadingBox icons are different than the media they become
switch (change.type as any) {
case 'update':
@@ -92,17 +97,12 @@ export class DocumentManager {
@action
public AddView = (view: DocumentView) => {
- if (!view._props.LayoutTemplateString?.includes(KeyValueBox.name) &&
- !view._props.LayoutTemplateString?.includes(LinkAnchorBox.name)) {
- this.AddDocumentView(view);
- this.callAddViewFuncs(view);
- } // prettier-ignore
+ this.AddDocumentView(view);
+ this.callAddViewFuncs(view);
};
public RemoveView = action((view: DocumentView) => {
- if (!view._props.LayoutTemplateString?.includes(KeyValueBox.name) && !view._props.LayoutTemplateString?.includes(LinkAnchorBox.name)) {
- this.DeleteDocumentView(view);
- }
- SelectionManager.DeselectView(view);
+ this.DeleteDocumentView(view);
+ DocumentView.DeselectView(view);
});
// gets all views
@@ -203,6 +203,11 @@ export class DocumentManager {
}
static _overlayViews = new ObservableSet<DocumentView>();
+ /**
+ * Find the nearest common ancestor collection that contains a link's source and target
+ * @param linkDoc
+ * @returns common ancestor DocumentView
+ */
public static LinkCommonAncestor(linkDoc: Doc) {
const getAnchor = (which: number) => {
const anch = DocCast(linkDoc['link_anchor_' + which]);
@@ -245,11 +250,8 @@ export class DocumentManager {
Doc.RemoveDocFromList(Doc.MyRecentlyClosed, undefined, targetDoc);
const docContextPath = DocumentManager.GetContextPath(targetDoc, true);
if (docContextPath.some(doc => doc.hidden)) options.toggleTarget = false;
- const tabView = Array.from(TabDocView._allTabs).find(view => view._document === docContextPath[0]);
- if (!tabView?._activated && tabView?._document) {
- options.toggleTarget = false;
- TabDocView.Activate(tabView?._document);
- }
+ if (DocumentView.activateTabView(docContextPath[0])) options.toggleTarget = false;
+
const rootContextView =
docContextPath.length &&
(await new Promise<DocumentView>(res => {
@@ -260,7 +262,7 @@ export class DocumentManager {
return;
}
options.didMove = true;
- (!LightboxView.LightboxDoc && docContextPath.some(doc => TabDocView.Activate(doc))) || DocumentViewInternal.addDocTabFunc(docContextPath[0], options.openLocation ?? OpenWhere.addRight);
+ (!LightboxView.LightboxDoc && docContextPath.some(doc => DocumentView.activateTabView(doc))) || DocumentViewInternal.addDocTabFunc(docContextPath[0], options.openLocation ?? OpenWhere.addRight);
this.AddViewRenderedCb(docContextPath[0], dv => res(dv));
}));
if (options.openLocation === OpenWhere.lightbox) {
@@ -355,33 +357,4 @@ export class DocumentManager {
}
}
}
-// eslint-disable-next-line default-param-last
-export function DocFocusOrOpen(docIn: Doc, optionsIn: FocusViewOptions = { willZoomCentered: true, zoomScale: 0, openLocation: OpenWhere.toggleRight }, containingDoc?: Doc) {
- let doc = docIn;
- const options = optionsIn;
- const func = () => {
- const cv = DocumentManager.Instance.getDocumentView(containingDoc);
- const dv = DocumentManager.Instance.getDocumentView(doc, cv);
- if (dv && (!containingDoc || dv.containerViewPath?.().lastElement()?.Document === containingDoc)) {
- DocumentManager.Instance.showDocumentView(dv, options).then(() => dv && Doc.linkFollowHighlight(dv.Document));
- } else {
- const container = DocCast(containingDoc ?? doc.embedContainer ?? Doc.BestEmbedding(doc));
- const showDoc = !Doc.IsSystem(container) && !cv ? container : doc;
- options.toggleTarget = undefined;
- DocumentManager.Instance.showDocument(showDoc, options, () => DocumentManager.Instance.showDocument(doc, { ...options, openLocation: undefined })).then(() => {
- const cvFound = DocumentManager.Instance.getDocumentView(containingDoc);
- const dvFound = DocumentManager.Instance.getDocumentView(doc, cvFound);
- dvFound && Doc.linkFollowHighlight(dvFound.Document);
- });
- }
- };
- if (Doc.IsDataProto(doc) && Doc.GetEmbeddings(doc).some(embed => embed.hidden && [AclAdmin, AclEdit].includes(GetEffectiveAcl(embed)))) {
- doc = Doc.GetEmbeddings(doc).find(embed => embed.hidden && [AclAdmin, AclEdit].includes(GetEffectiveAcl(embed)))!;
- }
- if (doc.hidden) {
- doc.hidden = false;
- options.toggleTarget = false;
- setTimeout(func);
- } else func();
-}
-ScriptingGlobals.add(DocFocusOrOpen);
+setTimeout(() => DocumentManager.Instance);
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 34f54be2e..fda505420 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -27,8 +27,6 @@ import { ScriptCast } from '../../fields/Types';
import { Docs } from '../documents/Documents';
import { DocumentView } from '../views/nodes/DocumentView';
import { dropActionType } from './DropActionTypes';
-import { ScriptingGlobals } from './ScriptingGlobals';
-import { SelectionManager } from './SelectionManager';
import { SnappingManager } from './SnappingManager';
import { UndoManager } from './UndoManager';
@@ -648,14 +646,3 @@ export namespace DragManager {
document.addEventListener('pointerup', upHandler, true);
}
}
-
-// eslint-disable-next-line prefer-arrow-callback
-ScriptingGlobals.add(function toggleRaiseOnDrag(readOnly?: boolean) {
- if (readOnly) {
- return SelectionManager.Views.some(dv => dv.Document.keepZWhenDragged);
- }
- SelectionManager.Views.forEach(dv => {
- dv.Document.keepZWhenDragged = !dv.Document.keepZWhenDragged;
- });
- return undefined;
-});
diff --git a/src/client/util/GroupManager.tsx b/src/client/util/GroupManager.tsx
index e1a503ac9..5701a22c0 100644
--- a/src/client/util/GroupManager.tsx
+++ b/src/client/util/GroupManager.tsx
@@ -77,7 +77,7 @@ export class GroupManager extends ObservableReactComponent<{}> {
*/
@action
open = () => {
- // SelectionManager.DeselectAll();
+ // DocumentView.DeselectAll();
this.isOpen = true;
this.populateUsers();
};
diff --git a/src/client/util/HypothesisUtils.ts b/src/client/util/HypothesisUtils.ts
index dd18b2533..5a6522dc8 100644
--- a/src/client/util/HypothesisUtils.ts
+++ b/src/client/util/HypothesisUtils.ts
@@ -6,8 +6,6 @@ import { WebField } from '../../fields/URLField';
import { Docs } from '../documents/Documents';
import { DocumentLinksButton } from '../views/nodes/DocumentLinksButton';
import { DocumentView } from '../views/nodes/DocumentView';
-import { DocumentManager } from './DocumentManager';
-import { SelectionManager } from './SelectionManager';
export namespace Hypothesis {
/**
@@ -25,7 +23,7 @@ export namespace Hypothesis {
* Search for a WebDocument whose url field matches the given uri, return undefined if not found
*/
export const findWebDoc = async (uri: string) => {
- const currentDoc = SelectionManager.Docs.lastElement();
+ const currentDoc = DocumentView.Selected().lastElement()?.Document;
if (currentDoc && Cast(currentDoc.data, WebField)?.url.href === uri) return currentDoc; // always check first whether the currently selected doc is the annotation's source, only use Search otherwise
const results: Doc[] = [];
@@ -39,7 +37,7 @@ export namespace Hypothesis {
// })
// );
- const onScreenResults = results.filter(doc => DocumentManager.Instance.getFirstDocumentView(doc));
+ const onScreenResults = results.filter(doc => DocumentView.getFirstDocumentView(doc));
return onScreenResults.length ? onScreenResults[0] : results.length ? results[0] : undefined; // prioritize results that are currently on the screen
};
@@ -65,7 +63,7 @@ export namespace Hypothesis {
DocumentLinksButton.AnnotationId = annotationId;
DocumentLinksButton.AnnotationUri = annotationUri;
});
- const endLinkView = DocumentManager.Instance.getFirstDocumentView(sourceDoc);
+ const endLinkView = DocumentView.getFirstDocumentView(sourceDoc);
const rect = document.body.getBoundingClientRect();
const x = rect.x + rect.width / 2;
const y = 250;
@@ -182,7 +180,7 @@ export namespace Hypothesis {
bubbles: true,
})
);
- const targetView: Opt<DocumentView> = DocumentManager.Instance.getFirstDocumentView(target);
+ const targetView: Opt<DocumentView> = DocumentView.getFirstDocumentView(target);
const position = targetView?.screenToViewTransform().inverse().transformPoint(0, 0);
targetView && position && simulateMouseClick(targetView.ContentDiv!, position[0], position[1], position[0], position[1], false);
}, 300);
diff --git a/src/client/util/Import & Export/DirectoryImportBox.tsx b/src/client/util/Import & Export/DirectoryImportBox.tsx
index 398ba3c04..baa0786b7 100644
--- a/src/client/util/Import & Export/DirectoryImportBox.tsx
+++ b/src/client/util/Import & Export/DirectoryImportBox.tsx
@@ -17,7 +17,6 @@
// 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 * as React from 'react';
diff --git a/src/client/util/LinkFollower.ts b/src/client/util/LinkFollower.ts
index a6f6122ab..9a0edcfec 100644
--- a/src/client/util/LinkFollower.ts
+++ b/src/client/util/LinkFollower.ts
@@ -1,14 +1,12 @@
import { action, runInAction } from 'mobx';
-import { Doc, DocListCast, FieldResult, FieldType, Opt } from '../../fields/Doc';
-import { BoolCast, Cast, DocCast, NumCast, ScriptCast, StrCast } from '../../fields/Types';
+import { Doc, DocListCast, Opt } from '../../fields/Doc';
+import { BoolCast, Cast, DocCast, NumCast, StrCast } from '../../fields/Types';
import { DocumentType } from '../documents/DocumentTypes';
+import { DocumentView } from '../views/nodes/DocumentView';
import { FocusViewOptions } from '../views/nodes/FocusViewOptions';
import { OpenWhere } from '../views/nodes/OpenWhere';
import { PresBox } from '../views/nodes/trails';
-import { DocumentManager } from './DocumentManager';
-import { LinkManager } from './LinkManager';
import { ScriptingGlobals } from './ScriptingGlobals';
-import { SelectionManager } from './SelectionManager';
import { SnappingManager } from './SnappingManager';
import { UndoManager } from './UndoManager';
/*
@@ -24,6 +22,9 @@ import { UndoManager } from './UndoManager';
* - user defined kvps
*/
export class LinkFollower {
+ public static Init() {
+ DocumentView.FollowLink = LinkFollower.FollowLink;
+ }
// follows a link - if the target is on screen, it highlights/pans to it.
// if the target isn't onscreen, then it will open up the target in the lightbox, or in place
// depending on the followLinkLocation property of the source (or the link itself as a fallback);
@@ -42,9 +43,9 @@ export class LinkFollower {
};
public static traverseLink(link: Opt<Doc>, sourceDoc: Doc, finished?: () => void, traverseBacklink?: boolean) {
- const getView = (doc: Doc) => DocumentManager.Instance.getFirstDocumentView(DocCast(doc.layout_unrendered ? doc.annotationOn : doc));
+ const getView = (doc: Doc) => DocumentView.getFirstDocumentView(DocCast(doc.layout_unrendered ? doc.annotationOn : doc));
const isAnchor = (source: Doc, anchor: Doc) => Doc.AreProtosEqual(anchor, source) || Doc.AreProtosEqual(anchor.annotationOn as Doc, source);
- const linkDocs = link ? [link] : LinkManager.Links(sourceDoc);
+ const linkDocs = link ? [link] : Doc.Links(sourceDoc);
const fwdLinks = linkDocs.filter(l => isAnchor(sourceDoc, l.link_anchor_1 as Doc)); // link docs where 'sourceDoc' is link_anchor_1
const backLinks = linkDocs.filter(l => isAnchor(sourceDoc, l.link_anchor_2 as Doc)); // link docs where 'sourceDoc' is link_anchor_2
const fwdLinkWithoutTargetView = fwdLinks.find(l => !getView(DocCast(l.link_anchor_2)));
@@ -68,7 +69,7 @@ export class LinkFollower {
? linkDoc.link_anchor_2
: linkDoc.link_anchor_1
) as Doc;
- const srcAnchor: Doc = LinkManager.getOppositeAnchor(linkDoc, target) ?? sourceDoc;
+ const srcAnchor: Doc = Doc.getOppositeAnchor(linkDoc, target) ?? sourceDoc;
if (target) {
const doFollow = (canToggle?: boolean) => {
const toggleTarget = canToggle && BoolCast(sourceDoc.followLinkToggle);
@@ -87,14 +88,14 @@ export class LinkFollower {
zoomTextSelections: BoolCast(srcAnchor.followLinkZoomText),
};
if (target.type === DocumentType.PRES) {
- const containerDocContext = DocumentManager.GetContextPath(sourceDoc, true); // gather all views that affect layout of sourceDoc so we can revert them after playing the rail
- SelectionManager.DeselectAll();
- if (!DocumentManager.Instance.AddViewRenderedCb(target, dv => containerDocContext.length && dv.ComponentView?.playTrail?.(containerDocContext))) {
+ const containerDocContext = DocumentView.getContextPath(sourceDoc, true); // gather all views that affect layout of sourceDoc so we can revert them after playing the rail
+ DocumentView.DeselectAll();
+ if (!DocumentView.addViewRenderedCb(target, dv => containerDocContext.length && dv.ComponentView?.playTrail?.(containerDocContext))) {
PresBox.OpenPresMinimized(target, [0, 0]);
}
finished?.();
} else {
- DocumentManager.Instance.showDocument(target, options, allFinished);
+ DocumentView.showDocument(target, options, allFinished);
}
};
let movedTarget = false;
@@ -133,10 +134,6 @@ export class LinkFollower {
// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function followLink(doc: Doc, altKey: boolean) {
- SelectionManager.DeselectAll();
+ DocumentView.DeselectAll();
return LinkFollower.FollowLink(undefined, doc, altKey) ? undefined : { select: true };
});
-
-export function IsFollowLinkScript(field: FieldResult<FieldType>) {
- return ScriptCast(field)?.script.originalScript.includes('return followLink(');
-}
diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts
index dbd13f978..56d5dce4e 100644
--- a/src/client/util/LinkManager.ts
+++ b/src/client/util/LinkManager.ts
@@ -30,8 +30,8 @@ export class LinkManager {
@observable.shallow userLinkDBs: Doc[] = [];
@observable public currentLink: Opt<Doc> = undefined;
@observable public currentLinkAnchor: Opt<Doc> = undefined;
- public static get Instance() {
- return LinkManager._instance;
+ public static get Instance(): LinkManager {
+ return Doc.UserDoc() ? LinkManager._instance ?? new LinkManager() : (undefined as any as LinkManager);
}
public static Links(doc: Doc | undefined) {
@@ -47,10 +47,13 @@ export class LinkManager {
this.userLinkDBs.push(linkDb);
};
public static AutoKeywords = 'keywords:Usages';
- constructor() {
+ private constructor() {
makeObservable(this);
LinkManager._instance = this;
Doc.AddLink = this.addLink;
+ Doc.DeleteLink = this.deleteLink;
+ Doc.Links = LinkManager.Links;
+ Doc.getOppositeAnchor = LinkManager.getOppositeAnchor;
this.createlink_relationshipLists();
// since this is an action, not a reaction, we get only one shot to add this link to the Anchor docs
// Thus make sure all promised values are resolved from link -> link.proto -> link.link_anchor_[1,2] -> link.link_anchor_[1,2].proto
diff --git a/src/client/util/PingManager.ts b/src/client/util/PingManager.ts
index e5e69c5ac..255e9cee0 100644
--- a/src/client/util/PingManager.ts
+++ b/src/client/util/PingManager.ts
@@ -1,6 +1,6 @@
import { action, makeObservable, observable, runInAction } from 'mobx';
import { Networking } from '../Network';
-import { CurrentUserUtils } from './CurrentUserUtils';
+import { SnappingManager } from './SnappingManager';
export class PingManager {
// create static instance and getter for global use
@@ -32,7 +32,7 @@ export class PingManager {
try {
const res = await Networking.PostToServer('/ping', { date: new Date() });
runInAction(() => {
- CurrentUserUtils.ServerVersion = res.message;
+ SnappingManager.SetServerVersion(res.message);
});
!this.IsBeating && this.setIsBeating(true);
} catch {
diff --git a/src/client/util/ReplayMovements.ts b/src/client/util/ReplayMovements.ts
index dcc6aabab..530fcf211 100644
--- a/src/client/util/ReplayMovements.ts
+++ b/src/client/util/ReplayMovements.ts
@@ -4,8 +4,8 @@ import { CollectionDockingView } from '../views/collections/CollectionDockingVie
import { CollectionFreeFormView } from '../views/collections/collectionFreeForm';
import { OpenWhereMod } from '../views/nodes/OpenWhere';
import { VideoBox } from '../views/nodes/VideoBox';
-import { DocumentManager } from './DocumentManager';
import { Movement, Presentation } from './TrackMovements';
+import { DocumentView } from '../views/nodes/DocumentView';
export class ReplayMovements {
private timers: NodeJS.Timeout[] | null;
@@ -106,7 +106,7 @@ export class ReplayMovements {
// returns undefined if the docView isn't open on the screen
getCollectionFFView = (doc: Doc) => {
- const isInView = DocumentManager.Instance.getDocumentView(doc);
+ const isInView = DocumentView.getDocumentView(doc);
return isInView?.ComponentView as CollectionFreeFormView;
};
@@ -118,7 +118,7 @@ export class ReplayMovements {
}
// console.log('openTab', docId, doc);
CollectionDockingView.AddSplit(doc, OpenWhereMod.right);
- const docView = DocumentManager.Instance.getDocumentView(doc);
+ const docView = DocumentView.getDocumentView(doc);
// BUG - this returns undefined if the doc is already open
return docView?.ComponentView as CollectionFreeFormView;
};
diff --git a/src/client/util/Scripting.ts b/src/client/util/Scripting.ts
index 8df579e75..6948469cc 100644
--- a/src/client/util/Scripting.ts
+++ b/src/client/util/Scripting.ts
@@ -5,8 +5,8 @@
// import * as typescriptlib from '!!raw-loader!../../../node_modules/typescript/lib/lib.d.ts'
// import * as typescriptes5 from '!!raw-loader!../../../node_modules/typescript/lib/lib.es5.d.ts'
// eslint-disable-next-line node/no-unpublished-import
-import * as ts from 'typescript';
import * as typescriptlib from '!!raw-loader!./type_decls.d';
+import * as ts from 'typescript';
import { Doc, FieldType } from '../../fields/Doc';
import { RefField } from '../../fields/RefField';
import { ScriptField } from '../../fields/ScriptField';
@@ -195,7 +195,6 @@ export function CompileScript(script: string, options: ScriptOptions = {}): Comp
if (found) return found as CompiledScript;
const { requiredType = '', addReturn = false, params = {}, capturedVariables = {}, typecheck = true } = options;
if (options.params && !options.params.this) options.params.this = Doc.name;
- if (options.params && !options.params.self) options.params.self = Doc.name;
if (options.globals) {
ScriptingGlobals.setScriptingGlobals(options.globals);
}
@@ -266,9 +265,3 @@ export function CompileScript(script: string, options: ScriptOptions = {}): Comp
!signature.includes('XXX') && ScriptField._scriptFieldCache.set(script + ':' + signature, result as CompiledScript);
return result;
}
-
-ScriptingGlobals.add(CompileScript);
-// eslint-disable-next-line prefer-arrow-callback
-ScriptingGlobals.add(function runScript(doc: Doc, script: ScriptField) {
- return script?.script.run({ this: doc }).result;
-});
diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts
index 7e8f42de9..0b942116c 100644
--- a/src/client/util/SelectionManager.ts
+++ b/src/client/util/SelectionManager.ts
@@ -1,6 +1,5 @@
import { action, makeObservable, observable, runInAction } from 'mobx';
import { Doc, Opt } from '../../fields/Doc';
-import { DocViews } from '../../fields/DocSymbols';
import { List } from '../../fields/List';
import { listSpec } from '../../fields/Schema';
import { Cast, DocCast } from '../../fields/Types';
@@ -24,6 +23,13 @@ export class SelectionManager {
private constructor() {
SelectionManager._manager = this;
makeObservable(this);
+ DocumentView.DeselectAll = SelectionManager.DeselectAll;
+ DocumentView.DeselectView = SelectionManager.DeselectView;
+ DocumentView.SelectView = SelectionManager.SelectView;
+ DocumentView.SelectedDocs = SelectionManager.Docs;
+ DocumentView.Selected = SelectionManager.Views;
+ DocumentView.SelectSchemaDoc = SelectionManager.SelectSchemaViewDoc;
+ DocumentView.SelectedSchemaDoc = () => this.SelectedSchemaDocument;
}
@action
@@ -54,8 +60,10 @@ export class SelectionManager {
public static DeselectAll = (except?: Doc): void => {
const found = this.Instance.SelectedViews.find(dv => dv.Document === except);
runInAction(() => {
- LinkManager.Instance.currentLink = undefined;
- LinkManager.Instance.currentLinkAnchor = undefined;
+ if (LinkManager.Instance) {
+ LinkManager.Instance.currentLink = undefined;
+ LinkManager.Instance.currentLinkAnchor = undefined;
+ }
this.Instance.SelectedSchemaDocument = undefined;
});
this.Instance.SelectedViews.forEach(dv => {
@@ -68,19 +76,18 @@ export class SelectionManager {
if (found) this.SelectView(found, false);
};
- public static IsSelected = (doc?: Doc) => Array.from(doc?.[DocViews] ?? []).some(dv => dv?.IsSelected);
- public static get Views() { return this.Instance.SelectedViews; } // prettier-ignore
- public static get SelectedSchemaDoc() { return this.Instance.SelectedSchemaDocument; } // prettier-ignore
- public static get Docs() { return this.Instance.SelectedViews.map(dv => dv.Document).filter(doc => doc?._type_collection !== CollectionViewType.Docking); } // prettier-ignore
+ public static Views() { return SelectionManager.Instance.SelectedViews; } // prettier-ignore
+ public static get SelectedSchemaDoc() { return SelectionManager.Instance.SelectedSchemaDocument; } // prettier-ignore
+ public static Docs() { return SelectionManager.Instance.SelectedViews.map(dv => dv.Document).filter(doc => doc?._type_collection !== CollectionViewType.Docking); } // prettier-ignore
}
// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function SelectedDocType(type: string, expertMode: boolean, checkContext?: boolean) {
if (Doc.noviceMode && expertMode) return false;
if (type === 'tab') {
- return SelectionManager.Views.lastElement()?._props.renderDepth === 0;
+ return DocumentView.Selected().lastElement()?._props.renderDepth === 0;
}
- const selected = (sel => (checkContext ? DocCast(sel?.embedContainer) : sel))(SelectionManager.SelectedSchemaDoc ?? SelectionManager.Docs.lastElement());
+ const selected = (sel => (checkContext ? DocCast(sel?.embedContainer) : sel))(DocumentView.SelectedSchemaDoc() ?? SelectionManager.Docs().lastElement());
return selected?.type === type || selected?.type_collection === type || !type;
});
// eslint-disable-next-line prefer-arrow-callback
@@ -109,8 +116,6 @@ ScriptingGlobals.add(function redo() {
});
// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function selectedDocs(container: Doc, excludeCollections: boolean, prevValue: any) {
- const docs = SelectionManager.Views.map(dv => dv.Document).filter(
- d => !Doc.AreProtosEqual(d, container) && !d.annotationOn && d.type !== DocumentType.KVP && (!excludeCollections || d.type !== DocumentType.COL || !Cast(d.data, listSpec(Doc), null))
- );
+ const docs = SelectionManager.Docs().filter(d => !Doc.AreProtosEqual(d, container) && !d.annotationOn && d.type !== DocumentType.KVP && (!excludeCollections || d.type !== DocumentType.COL || !Cast(d.data, listSpec(Doc), null)));
return docs.length ? new List(docs) : prevValue;
});
diff --git a/src/client/util/SettingsManager.tsx b/src/client/util/SettingsManager.tsx
index 8cb97fe50..d3c10f9f4 100644
--- a/src/client/util/SettingsManager.tsx
+++ b/src/client/util/SettingsManager.tsx
@@ -8,7 +8,7 @@ import * as React from 'react';
import { BsGoogle } from 'react-icons/bs';
import { FaFillDrip, FaPalette } from 'react-icons/fa';
import { ClientUtils, addStyleSheet, addStyleSheetRule } from '../../ClientUtils';
-import { Doc, Opt } from '../../fields/Doc';
+import { Doc } from '../../fields/Doc';
import { DashVersion } from '../../fields/DocSymbols';
import { BoolCast, Cast, NumCast, StrCast } from '../../fields/Types';
import { DocServer } from '../DocServer';
@@ -17,7 +17,7 @@ import { GoogleAuthenticationManager } from '../apis/GoogleAuthenticationManager
import { MainViewModal } from '../views/MainViewModal';
import { GroupManager } from './GroupManager';
import './SettingsManager.scss';
-import { SnappingManager } from './SnappingManager';
+import { SnappingManager, freeformScrollMode } from './SnappingManager';
import { undoable } from './UndoManager';
export enum ColorScheme {
@@ -28,11 +28,6 @@ export enum ColorScheme {
Cupcake = 'Cupcake',
}
-export enum freeformScrollMode {
- Pan = 'pan',
- Zoom = 'zoom',
-}
-
@observer
export class SettingsManager extends React.Component<{}> {
// eslint-disable-next-line no-use-before-define
@@ -44,17 +39,15 @@ export class SettingsManager extends React.Component<{}> {
@observable private _curr_password = '';
@observable private _new_password = '';
@observable private _new_confirm = '';
- @observable private _lastPressedSidebarBtn: Opt<Doc> = undefined; // bcz: this is a hack to handle highlighting buttons in the leftpanel menu .. need to find a cleaner approach
@observable private _activeTab = 'Accounts';
@observable private _isOpen = false;
- @observable public propertiesWidth: number = 0;
-
private googleAuthorize = action(() => GoogleAuthenticationManager.Instance.fetchOrGenerateAccessToken(true));
public closeMgr = action(() => {
this._isOpen = false;
});
+ // eslint-disable-next-line react/no-unused-class-component-methods
public openMgr = action(() => {
this._isOpen = true;
});
@@ -154,9 +147,6 @@ export class SettingsManager extends React.Component<{}> {
SnappingManager.SettingsStyle = SettingsManager._settingsStyle;
}
- public get LastPressedBtn() { return this._lastPressedSidebarBtn; } // prettier-ignore
- public set LastPressedBtn(state:Doc|undefined) { this._lastPressedSidebarBtn = state; } // prettier-ignore
-
@computed public static get userColor() {
return StrCast(Doc.UserDoc().userColor);
}
@@ -287,7 +277,7 @@ export class SettingsManager extends React.Component<{}> {
size={Size.XSMALL}
color={SettingsManager.userColor}
/>
- <Toggle
+ {/* <Toggle
formLabel="Show Link Lines"
formLabelPlacement="right"
toggleType={ToggleType.SWITCH}
@@ -297,7 +287,7 @@ export class SettingsManager extends React.Component<{}> {
toggleStatus={BoolCast(Doc.UserDoc().showLinkLines)}
size={Size.XSMALL}
color={SettingsManager.userColor}
- />
+ /> */}
<Group formLabel="Title Height">
<NumberDropdown
number={NumCast(Doc.UserDoc().headerHeight, 30)}
diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx
index b0140b73c..31a99896f 100644
--- a/src/client/util/SharingManager.tsx
+++ b/src/client/util/SharingManager.tsx
@@ -21,11 +21,9 @@ import { DocServer } from '../DocServer';
import { MainViewModal } from '../views/MainViewModal';
import { DocumentView } from '../views/nodes/DocumentView';
import { TaskCompletionBox } from '../views/nodes/TaskCompletedBox';
-import { DocumentManager } from './DocumentManager';
import { GroupManager, UserOptions } from './GroupManager';
import { GroupMemberView } from './GroupMemberView';
import { SearchUtil } from './SearchUtil';
-import { SelectionManager } from './SelectionManager';
import './SharingManager.scss';
import { SnappingManager } from './SnappingManager';
import { undoable } from './UndoManager';
@@ -152,7 +150,7 @@ export class SharingManager extends React.Component<{}> {
const users = this.individualSort === 'ascending' ? this.users.slice().sort(this.sortUsers) : this.individualSort === 'descending' ? this.users.slice().sort(this.sortUsers).reverse() : this.users;
const groups = this.groupSort === 'ascending' ? groupList.slice().sort(this.sortGroups) : this.groupSort === 'descending' ? groupList.slice().sort(this.sortGroups).reverse() : groupList;
- let docs = SelectionManager.Views.length < 2 ? [this.targetDoc] : SelectionManager.Views.map(docView => docView.Document);
+ let docs = DocumentView.Selected().length < 2 ? [this.targetDoc] : DocumentView.Selected().map(docView => docView.Document);
if (this.myDocAcls) {
const newDocs: Doc[] = [];
@@ -442,7 +440,7 @@ export class SharingManager extends React.Component<{}> {
const { user, sharingDoc } = recipient;
const target = targetDoc || this.targetDoc!;
const acl = `acl_${normalizeEmail(user.email)}`;
- const docs = SelectionManager.Views.length < 2 ? [target] : SelectionManager.Views.map(docView => docView.Document);
+ const docs = DocumentView.Selected().length < 2 ? [target] : DocumentView.Selected().map(docView => docView.Document);
docs.map(doc => (this.layoutDocAcls || doc.dockingConfig ? doc : Doc.GetProto(doc))).forEach(doc => {
distributeAcls(acl, permission as SharingPermissions, doc, undefined, this.upgradeNested ? true : undefined);
if (permission !== SharingPermissions.None) {
@@ -460,7 +458,7 @@ export class SharingManager extends React.Component<{}> {
const target = targetDoc || this.targetDoc!;
const acl = `acl_${normalizeEmail(StrCast(group.title))}`;
- const docs = SelectionManager.Views.length < 2 ? [target] : SelectionManager.Views.map(docView => docView.Document);
+ const docs = DocumentView.Selected().length < 2 ? [target] : DocumentView.Selected().map(docView => docView.Document);
docs.map(doc => (this.layoutDocAcls || doc.dockingConfig ? doc : Doc.GetProto(doc))).forEach(doc => {
distributeAcls(acl, permission as SharingPermissions, doc, undefined, this.upgradeNested ? true : undefined);
@@ -643,14 +641,14 @@ export class SharingManager extends React.Component<{}> {
private focusOn = (contents: string) => {
const title = this.targetDoc ? StrCast(this.targetDoc.title) : '';
- const docs = SelectionManager.Views.length > 1 ? SelectionManager.Views.map(docView => docView.props.Document) : [this.targetDoc];
+ const docs = DocumentView.Selected().length > 1 ? DocumentView.Selected().map(docView => docView.props.Document) : [this.targetDoc];
return (
<span
className="focus-span"
title={title}
onClick={() => {
if (this.targetDoc && this.targetDocView && docs.length === 1) {
- DocumentManager.Instance.showDocument(this.targetDoc, { willZoomCentered: true });
+ DocumentView.showDocument(this.targetDoc, { willZoomCentered: true });
}
}}
onPointerEnter={action(() => {
diff --git a/src/client/util/SnappingManager.ts b/src/client/util/SnappingManager.ts
index 5cd6ecfe1..6789c2ab8 100644
--- a/src/client/util/SnappingManager.ts
+++ b/src/client/util/SnappingManager.ts
@@ -1,5 +1,9 @@
import { observable, action, runInAction, makeObservable } from 'mobx';
+export enum freeformScrollMode {
+ Pan = 'pan',
+ Zoom = 'zoom',
+}
export class SnappingManager {
// eslint-disable-next-line no-use-before-define
private static _manager: SnappingManager;
@@ -19,6 +23,9 @@ export class SnappingManager {
@observable _vertSnapLines: number[] = [];
@observable _exploreMode = false;
@observable _userPanned = false;
+ @observable _serverVersion: string = '';
+ @observable _lastBtnId: string = '';
+ @observable _propertyWid: number = 0;
private constructor() {
SnappingManager._manager = this;
@@ -45,6 +52,10 @@ export class SnappingManager {
public static get CanEmbed() { return this.Instance._canEmbed; } // prettier-ignore
public static get ExploreMode() { return this.Instance._exploreMode; } // prettier-ignore
public static get UserPanned() { return this.Instance._userPanned; } // prettier-ignore
+ public static get ServerVersion() { return this.Instance._serverVersion; } // prettier-ignore
+ public static get LastPressedBtn() { return this.Instance._lastBtnId; } // prettier-ignore
+ public static get PropertiesWidth(){ return this.Instance._propertyWid; } // prettier-ignore
+
public static SetShiftKey = (down: boolean) => runInAction(() => {this.Instance._shiftKey = down}); // prettier-ignore
public static SetCtrlKey = (down: boolean) => runInAction(() => {this.Instance._ctrlKey = down}); // prettier-ignore
public static SetMetaKey = (down: boolean) => runInAction(() => {this.Instance._metaKey = down}); // prettier-ignore
@@ -54,7 +65,10 @@ export class SnappingManager {
public static SetIsResizing = (docid?:string) => runInAction(() => {this.Instance._isResizing = docid}); // prettier-ignore
public static SetCanEmbed = (embed:boolean) => runInAction(() => {this.Instance._canEmbed = embed}); // prettier-ignore
public static SetExploreMode = (state:boolean) => runInAction(() => {this.Instance._exploreMode = state}); // prettier-ignore
- public static TriggerUserPanned = () => runInAction(() => {this.Instance._userPanned = !this.Instance._userPanned}); // prettier-ignore
+ public static TriggerUserPanned = () => runInAction(() => {this.Instance._userPanned = !this.Instance._userPanned}); // prettier-ignore
+ public static SetServerVersion = (version:string) =>runInAction(() => {this.Instance._serverVersion = version}); // prettier-ignore
+ public static SetLastPressedBtn = (id:string) =>runInAction(() => {this.Instance._lastBtnId = id}); // prettier-ignore
+ public static SetPropertiesWidth= (wid:number) =>runInAction(() => {this.Instance._propertyWid = wid}); // prettier-ignore
public static userColor: string | undefined;
public static userVariantColor: string | undefined;
diff --git a/src/client/views/AntimodeMenu.tsx b/src/client/views/AntimodeMenu.tsx
index b1eb730fa..303672d90 100644
--- a/src/client/views/AntimodeMenu.tsx
+++ b/src/client/views/AntimodeMenu.tsx
@@ -1,6 +1,6 @@
import { action, makeObservable, observable, runInAction } from 'mobx';
import * as React from 'react';
-import { SettingsManager } from '../util/SettingsManager';
+import { SnappingManager } from '../util/SnappingManager';
import './AntimodeMenu.scss';
import { ObservableReactComponent } from './ObservableReactComponent';
@@ -157,7 +157,7 @@ export abstract class AntimodeMenu<T extends AntimodeMenuProps> extends Observab
left: this._left,
top: this._top,
opacity: this._opacity,
- background: SettingsManager.userBackgroundColor,
+ background: SnappingManager.userBackgroundColor,
transitionProperty: this._transitionProperty,
transitionDuration: this._transitionDuration,
transitionDelay: this._transitionDelay,
@@ -183,7 +183,7 @@ export abstract class AntimodeMenu<T extends AntimodeMenuProps> extends Observab
height: 'inherit',
width: 200,
opacity: this._opacity,
- background: SettingsManager.userBackgroundColor,
+ background: SnappingManager.userBackgroundColor,
transitionProperty: this._transitionProperty,
transitionDuration: this._transitionDuration,
transitionDelay: this._transitionDelay,
@@ -206,7 +206,7 @@ export abstract class AntimodeMenu<T extends AntimodeMenuProps> extends Observab
left: this._left,
top: this._top,
opacity: this._opacity,
- background: SettingsManager.userBackgroundColor,
+ background: SnappingManager.userBackgroundColor,
transitionProperty: this._transitionProperty,
transitionDuration: this._transitionDuration,
transitionDelay: this._transitionDelay,
diff --git a/src/client/views/ComponentDecorations.tsx b/src/client/views/ComponentDecorations.tsx
index 64b8a8446..929b549e0 100644
--- a/src/client/views/ComponentDecorations.tsx
+++ b/src/client/views/ComponentDecorations.tsx
@@ -1,7 +1,7 @@
import { observer } from 'mobx-react';
import * as React from 'react';
-import { SelectionManager } from '../util/SelectionManager';
import './ComponentDecorations.scss';
+import { DocumentView } from './nodes/DocumentView';
@observer
export class ComponentDecorations extends React.Component<{ boundsTop: number; boundsLeft: number }, { value: string }> {
@@ -9,7 +9,7 @@ export class ComponentDecorations extends React.Component<{ boundsTop: number; b
static Instance: ComponentDecorations;
render() {
- const seldoc = SelectionManager.Views.lastElement();
+ const seldoc = DocumentView.Selected().lastElement();
return seldoc?.ComponentView?.componentUI?.(this.props.boundsLeft, this.props.boundsTop) ?? null;
}
}
diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx
index a0e3d2ddd..97ff346e4 100644
--- a/src/client/views/DocComponent.tsx
+++ b/src/client/views/DocComponent.tsx
@@ -60,6 +60,8 @@ export interface ViewBoxInterface {
ptFromScreen?: (pt: { X: number; Y: number }) => { X: number; Y: number };
snapPt?: (pt: { X: number; Y: number }, excludeSegs?: number[]) => { nearestPt: { X: number; Y: number }; distance: number };
search?: (str: string, bwd?: boolean, clear?: boolean) => boolean;
+ dontRegisterView?: () => boolean; // KeyValueBox's don't want to register their views
+ isUnstyledView?: () => boolean; // SchemaView and KeyValue are untyled -- not tiles, no opacity
}
/**
* DocComponent returns a React base class used by Doc views with accessors for unpacking the Document,layoutDoc, and dataDoc's
diff --git a/src/client/views/DocViewUtils.ts b/src/client/views/DocViewUtils.ts
new file mode 100644
index 000000000..1f5f29c7e
--- /dev/null
+++ b/src/client/views/DocViewUtils.ts
@@ -0,0 +1,21 @@
+/* eslint-disable prefer-destructuring */
+/* eslint-disable default-param-last */
+/* eslint-disable no-use-before-define */
+import { runInAction } from 'mobx';
+import { Doc, SetActiveAudioLinker } from '../../fields/Doc';
+import { DocUtils } from '../documents/DocUtils';
+import { FieldViewProps } from './nodes/FieldView';
+
+export namespace DocViewUtils {
+ export const ActiveRecordings: { props: FieldViewProps; getAnchor: (addAsAnnotation: boolean) => Doc }[] = [];
+
+ export function MakeLinkToActiveAudio(getSourceDoc: () => Doc | undefined, broadcastEvent = true) {
+ broadcastEvent && runInAction(() => { Doc.RecordingEvent += 1; }); // prettier-ignore
+ return ActiveRecordings.map(audio => {
+ const sourceDoc = getSourceDoc();
+ return sourceDoc && DocUtils.MakeLink(sourceDoc, audio.getAnchor(true) || audio.props.Document, { link_relationship: 'recording annotation:linked recording', link_description: 'recording timeline' });
+ });
+ }
+
+ SetActiveAudioLinker(MakeLinkToActiveAudio);
+}
diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx
index dd744f272..487868169 100644
--- a/src/client/views/DocumentButtonBar.tsx
+++ b/src/client/views/DocumentButtonBar.tsx
@@ -14,23 +14,21 @@ import { returnFalse, returnTrue, setupMoveUpEvents, simulateMouseClick } from '
import { emptyFunction } from '../../Utils';
import { Doc } from '../../fields/Doc';
import { Cast, DocCast } from '../../fields/Types';
-import { DocUtils } from '../documents/DocUtils';
+import { DocUtils, IsFollowLinkScript } from '../documents/DocUtils';
import { CalendarManager } from '../util/CalendarManager';
+import { DictationManager } from '../util/DictationManager';
import { DragManager } from '../util/DragManager';
import { dropActionType } from '../util/DropActionTypes';
-import { IsFollowLinkScript } from '../util/LinkFollower';
-import { SelectionManager } from '../util/SelectionManager';
import { SharingManager } from '../util/SharingManager';
import { UndoManager, undoBatch } from '../util/UndoManager';
import './DocumentButtonBar.scss';
import { ObservableReactComponent } from './ObservableReactComponent';
import { PinProps } from './PinFuncs';
import { TemplateMenu } from './TemplateMenu';
-import { TabDocView } from './collections/TabDocView';
import { Colors } from './global/globalEnums';
import { LinkPopup } from './linking/LinkPopup';
import { DocumentLinksButton } from './nodes/DocumentLinksButton';
-import { DocumentView, DocumentViewInternal } from './nodes/DocumentView';
+import { DocumentView } from './nodes/DocumentView';
import { OpenWhere } from './nodes/OpenWhere';
import { DashFieldView } from './nodes/formattedText/DashFieldView';
@@ -206,7 +204,7 @@ export class DocumentButtonBar extends ObservableReactComponent<{ views: () => (
.views()
.filter(v => v)
.map(dv => dv!.Document);
- TabDocView.PinDoc(docs, {
+ DocumentView.PinDoc(docs, {
pinAudioPlay: true,
pinDocLayout: pinLayoutView,
pinData: { dataview: pinContentView },
@@ -221,7 +219,7 @@ export class DocumentButtonBar extends ObservableReactComponent<{ views: () => (
);
};
return !targetDoc ? null : (
- <Tooltip title={<div className="dash-tooltip">{`Pin Document ${SelectionManager.Views.length > 1 ? 'multiple documents' : ''} to Trail`}</div>}>
+ <Tooltip title={<div className="dash-tooltip">{`Pin Document ${DocumentView.Selected().length > 1 ? 'multiple documents' : ''} to Trail`}</div>}>
<div
className="documentButtonBar-icon documentButtonBar-pin"
onClick={e => {
@@ -229,7 +227,7 @@ export class DocumentButtonBar extends ObservableReactComponent<{ views: () => (
.views()
.filter(v => v)
.map(dv => dv!.Document);
- TabDocView.PinDoc(docs, { pinAudioPlay: true, pinDocLayout: e.shiftKey, pinData: { dataview: e.altKey }, activeFrame: Cast(docs.lastElement()?.activeFrame, 'number', null) });
+ DocumentView.PinDoc(docs, { pinAudioPlay: true, pinDocLayout: e.shiftKey, pinData: { dataview: e.altKey }, activeFrame: Cast(docs.lastElement()?.activeFrame, 'number', null) });
e.stopPropagation();
}}>
<div className="documentButtonBar-pinTypes">
@@ -299,7 +297,7 @@ export class DocumentButtonBar extends ObservableReactComponent<{ views: () => (
this._props.views().map(
view =>
view &&
- DocumentViewInternal.recordAudioAnnotation(
+ DictationManager.recordAudioAnnotation(
view.dataDoc,
view.LayoutFieldKey,
stopFunc => {
@@ -381,7 +379,7 @@ export class DocumentButtonBar extends ObservableReactComponent<{ views: () => (
}
openContextMenu = (e: PointerEvent) => {
- let child = SelectionManager.Views[0].ContentDiv!.children[0];
+ let child = DocumentView.Selected()[0].ContentDiv!.children[0];
while (child.children.length) {
const next = Array.from(child.children).find(c => c.className?.toString().includes('SVGAnimatedString') || typeof c.className === 'string');
if (next?.className?.toString().includes(DocumentView.ROOT_DIV)) break;
@@ -442,14 +440,7 @@ export class DocumentButtonBar extends ObservableReactComponent<{ views: () => (
</div>
{this._showLinkPopup ? (
<div style={{ position: 'absolute', zIndex: 1000 }}>
- <LinkPopup
- key="popup"
- linkCreated={link => {
- link.link_displayLine = !IsFollowLinkScript(this._props.views().lastElement()?.Document.onClick);
- }}
- linkCreateAnchor={() => this._props.views().lastElement()?.ComponentView?.getAnchor?.(true)}
- linkFrom={() => this._props.views().lastElement()?.Document}
- />
+ <LinkPopup key="popup" linkCreated={emptyFunction} linkCreateAnchor={() => this._props.views().lastElement()?.ComponentView?.getAnchor?.(true)} linkFrom={() => this._props.views().lastElement()?.Document} />
</div>
) : (
<div className="documentButtonBar-button">{this.linkButton}</div>
@@ -457,7 +448,7 @@ export class DocumentButtonBar extends ObservableReactComponent<{ views: () => (
{DocumentLinksButton.StartLink && DocumentLinksButton.StartLink !== doc ? <div className="documentButtonBar-button">{this.endLinkButton} </div> : null}
<div className="documentButtonBar-button">{this.templateButton}</div>
- {!SelectionManager.Views?.some(v => v.allLinks.length) ? null : <div className="documentButtonBar-button">{this.followLinkButton}</div>}
+ {!DocumentView.Selected().some(v => v.allLinks.length) ? null : <div className="documentButtonBar-button">{this.followLinkButton}</div>}
<div className="documentButtonBar-button">{this.pinButton}</div>
<div className="documentButtonBar-button">{this.recordButton}</div>
<div className="documentButtonBar-button">{this.calendarButton}</div>
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index ef493fb69..432b02782 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -17,9 +17,7 @@ import { BoolCast, Cast, DocCast, NumCast, StrCast } from '../../fields/Types';
import { GetEffectiveAcl } from '../../fields/util';
import { DocumentType } from '../documents/DocumentTypes';
import { Docs } from '../documents/Documents';
-import { DocumentManager } from '../util/DocumentManager';
import { DragManager } from '../util/DragManager';
-import { SelectionManager } from '../util/SelectionManager';
import { SettingsManager } from '../util/SettingsManager';
import { SnappingManager } from '../util/SnappingManager';
import { UndoManager } from '../util/UndoManager';
@@ -81,14 +79,14 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
let inputting = false;
if (this._titleControlString.startsWith('$')) {
const titleFieldKey = this._titleControlString.substring(1);
- if (SelectionManager.Views[0]?.Document[titleFieldKey] !== this._accumulatedTitle) {
+ if (DocumentView.Selected()[0]?.Document[titleFieldKey] !== this._accumulatedTitle) {
inputting = true;
}
}
const center = {x: (this.Bounds.x+this.Bounds.r)/2, y: (this.Bounds.y+this.Bounds.b)/2};
const {x,y} = Utils.rotPt(e.clientX - center.x,
e.clientY - center.y,
- NumCast(SelectionManager.Views.lastElement()?.screenToViewTransform().Rotate));
+ NumCast(DocumentView.Selected().lastElement()?.screenToViewTransform().Rotate));
(this._showNothing = !inputting && !DocumentButtonBar.Instance?._tooltipOpen && !(this.Bounds.x !== Number.MAX_VALUE && //
(this.Bounds.x > center.x+x || this.Bounds.r < center.x+x ||
this.Bounds.y > center.y+y || this.Bounds.b < center.y+y )));
@@ -110,7 +108,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
@computed get Bounds() {
return (SnappingManager.IsLinkFollowing || SnappingManager.ExploreMode) ?
{ x: 0, y: 0, r: 0, b: 0 }
- : SelectionManager.Views
+ : DocumentView.Selected()
.filter(dv => dv._props.renderDepth > 0)
.map(dv => dv.getBounds)
.reduce((bounds, rect) => !rect ? bounds
@@ -127,7 +125,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
this._titleControlString = this._accumulatedTitle;
} else if (this._titleControlString.startsWith('$')) {
if (this._accumulatedTitle.startsWith('-->#')) {
- SelectionManager.Docs.forEach(doc => {
+ DocumentView.SelectedDocs().forEach(doc => {
doc[DocData].onViewMounted = ScriptField.MakeScript(`updateTagsCollection(this)`);
});
}
@@ -135,11 +133,11 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
UndoManager.RunInBatch(
() =>
titleFieldKey &&
- SelectionManager.Views.forEach(d => {
+ DocumentView.Selected().forEach(dv => {
if (titleFieldKey === 'title') {
- d.dataDoc.title_custom = !this._accumulatedTitle.startsWith('-');
+ dv.dataDoc.title_custom = !this._accumulatedTitle.startsWith('-');
}
- KeyValueBox.SetField(d.Document, titleFieldKey, this._accumulatedTitle);
+ KeyValueBox.SetField(dv.Document, titleFieldKey, this._accumulatedTitle);
}),
'edit title'
);
@@ -154,7 +152,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
};
onContainerDown = (e: React.PointerEvent) => {
- const effectiveLayoutAcl = GetEffectiveAcl(SelectionManager.Views[0].Document);
+ const effectiveLayoutAcl = GetEffectiveAcl(DocumentView.Selected()[0].Document);
if (effectiveLayoutAcl === AclAdmin || effectiveLayoutAcl === AclEdit || effectiveLayoutAcl === AclAugment) {
setupMoveUpEvents(this, e, moveEv => this.onBackgroundMove(true, moveEv), emptyFunction, emptyFunction);
e.stopPropagation();
@@ -162,7 +160,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
};
onTitleDown = (e: React.PointerEvent) => {
- const effectiveLayoutAcl = GetEffectiveAcl(SelectionManager.Views[0].Document);
+ const effectiveLayoutAcl = GetEffectiveAcl(DocumentView.SelectedDocs()[0]);
if (effectiveLayoutAcl === AclAdmin || effectiveLayoutAcl === AclEdit || effectiveLayoutAcl === AclAugment) {
setupMoveUpEvents(
this,
@@ -170,7 +168,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
moveEv => this.onBackgroundMove(true, moveEv),
emptyFunction,
action(() => {
- const selected = SelectionManager.Views.length === 1 ? SelectionManager.Docs[0] : undefined;
+ const selected = DocumentView.SelectedDocs().length === 1 ? DocumentView.SelectedDocs()[0] : undefined;
!this._editingTitle && (this._accumulatedTitle = this._titleControlString.startsWith('$') ? (selected && Field.toKeyValueString(selected, this._titleControlString.substring(1))) || '-unset-' : this._titleControlString);
this._editingTitle = true;
this._keyinput.current && setTimeout(this._keyinput.current.focus);
@@ -186,19 +184,16 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
};
@action
onBackgroundMove = (dragTitle: boolean, e: PointerEvent): boolean => {
- const dragDocView = SelectionManager.Views[0];
+ const dragDocView = DocumentView.Selected()[0];
const effectiveLayoutAcl = GetEffectiveAcl(dragDocView.Document);
if (effectiveLayoutAcl !== AclAdmin && effectiveLayoutAcl !== AclEdit && effectiveLayoutAcl !== AclAugment) {
return false;
}
const containers = new Set<Doc | undefined>();
- SelectionManager.Views.forEach(v => containers.add(DocCast(v.Document.embedContainer)));
+ DocumentView.Selected().forEach(v => containers.add(DocCast(v.Document.embedContainer)));
if (containers.size > 1) return false;
const { left, top } = dragDocView.getBounds || { left: 0, top: 0 };
- const dragData = new DragManager.DocumentDragData(
- SelectionManager.Views.map(dv => dv.Document),
- dragDocView._props.dropAction
- );
+ const dragData = new DragManager.DocumentDragData(DocumentView.SelectedDocs(), dragDocView._props.dropAction);
dragData.offset = dragDocView.screenToContentsTransform().transformDirection(e.x - left, e.y - top);
dragData.moveDocument = dragDocView._props.moveDocument;
dragData.removeDocument = dragDocView._props.removeDocument;
@@ -206,7 +201,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
dragData.canEmbed = dragTitle;
this._hidden = true;
DragManager.StartDocumentDrag(
- SelectionManager.Views.map(dv => dv.ContentDiv!),
+ DocumentView.Selected().map(dv => dv.ContentDiv!),
dragData,
e.x,
e.y,
@@ -223,7 +218,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
_deleteAfterIconify = false;
_iconifyBatch: UndoManager.Batch | undefined;
onCloseClick = (forceDeleteOrIconify: boolean | undefined) => {
- const views = SelectionManager.Views.filter(v => v && v._props.renderDepth > 0);
+ const views = DocumentView.Selected().filter(v => v && v._props.renderDepth > 0);
if (forceDeleteOrIconify === false && this._iconifyBatch) return;
this._deleteAfterIconify = !!(forceDeleteOrIconify || this._iconifyBatch);
let iconifyingCount = views.length;
@@ -239,7 +234,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
iconView._props.removeDocument?.(iconView.Document);
}
});
- views.forEach(SelectionManager.DeselectView);
+ views.forEach(DocumentView.DeselectView);
}
this._iconifyBatch?.end();
this._iconifyBatch = undefined;
@@ -258,53 +253,49 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
};
onMaximizeDown = (e: React.PointerEvent) => {
- setupMoveUpEvents(this, e, () => DragManager.StartWindowDrag?.(e, [SelectionManager.Views.lastElement().Document]) ?? false, emptyFunction, this.onMaximizeClick, false, false);
+ setupMoveUpEvents(this, e, () => DragManager.StartWindowDrag?.(e, [DocumentView.SelectedDocs().lastElement()]) ?? false, emptyFunction, this.onMaximizeClick, false, false);
e.stopPropagation();
};
onMaximizeClick = (e: any): void => {
- const selectedDocs = SelectionManager.Views;
+ const selectedDocs = DocumentView.SelectedDocs();
if (selectedDocs.length) {
if (e.ctrlKey) {
// open an embedding in a new tab with Ctrl Key
- CollectionDockingView.AddSplit(Doc.BestEmbedding(selectedDocs[0].Document), OpenWhereMod.right);
+ CollectionDockingView.AddSplit(Doc.BestEmbedding(selectedDocs[0]), OpenWhereMod.right);
} else if (e.shiftKey) {
// open centered in a new workspace with Shift Key
- const embedding = Doc.MakeEmbedding(selectedDocs[0].Document);
+ const embedding = Doc.MakeEmbedding(selectedDocs[0]);
embedding.embedContainer = undefined;
embedding.x = -NumCast(embedding._width) / 2;
embedding.y = -NumCast(embedding._height) / 2;
CollectionDockingView.AddSplit(Docs.Create.FreeformDocument([embedding], { title: 'Tab for ' + embedding.title }), OpenWhereMod.right);
} else if (e.altKey) {
// open same document in new tab
- CollectionDockingView.ToggleSplit(selectedDocs[0].Document, OpenWhereMod.right);
+ CollectionDockingView.ToggleSplit(selectedDocs[0], OpenWhereMod.right);
} else {
- let openDoc = selectedDocs[0].Document;
+ let openDoc = selectedDocs[0];
if (openDoc.layout_fieldKey === 'layout_icon') {
openDoc = Doc.GetEmbeddings(openDoc).find(embedding => !embedding.embedContainer) ?? Doc.MakeEmbedding(openDoc);
Doc.deiconifyView(openDoc);
}
- LightboxView.Instance.SetLightboxDoc(
- openDoc,
- undefined,
- selectedDocs.slice(1).map(view => view.Document)
- );
+ LightboxView.Instance.SetLightboxDoc(openDoc, undefined, selectedDocs.slice(1));
}
}
- SelectionManager.DeselectAll();
+ DocumentView.DeselectAll();
};
onIconifyClick = (): void => {
- SelectionManager.Views.forEach(dv => dv?.iconify());
- SelectionManager.DeselectAll();
+ DocumentView.Selected().forEach(dv => dv?.iconify());
+ DocumentView.DeselectAll();
};
- onSelectContainerDocClick = () => SelectionManager.Views?.[0]?.containerViewPath?.().lastElement()?.select(false);
+ onSelectContainerDocClick = () => DocumentView.Selected()?.[0]?.containerViewPath?.().lastElement()?.select(false);
/**
* sets up events when user clicks on the border radius editor
*/
@action
onRadiusDown = (e: React.PointerEvent): void => {
- SnappingManager.SetIsResizing(SelectionManager.Docs.lastElement()?.[Id]);
+ SnappingManager.SetIsResizing(DocumentView.SelectedDocs().lastElement()?.[Id]);
this._isRounding = true;
this._resizeUndo = UndoManager.StartBatch('DocDecs set radius');
setupMoveUpEvents(
@@ -314,7 +305,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
const [x, y] = [this.Bounds.x + 3, this.Bounds.y + 3];
const maxDist = Math.min((this.Bounds.r - this.Bounds.x) / 2, (this.Bounds.b - this.Bounds.y) / 2);
const dist = moveEv.clientX < x && moveEv.clientY < y ? 0 : Math.sqrt((moveEv.clientX - x) * (moveEv.clientX - x) + (moveEv.clientY - y) * (moveEv.clientY - y));
- SelectionManager.Docs.forEach(doc => {
+ DocumentView.SelectedDocs().forEach(doc => {
const docMax = Math.min(NumCast(doc.width) / 2, NumCast(doc.height) / 2);
const radius = Math.min(1, dist / maxDist) * docMax; // set radius based on ratio of drag distance to half diagonal distance of bounding box
doc._layout_borderRounding = `${radius}px`;
@@ -339,7 +330,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
e,
returnFalse, // don't care about move or up event,
emptyFunction, // just care about whether we get a click event
- () => UndoManager.RunInBatch(() => SelectionManager.Docs.forEach(doc => Doc.toggleLockedPosition(doc)), 'toggleBackground')
+ () => UndoManager.RunInBatch(() => DocumentView.Selected().forEach(dv => Doc.toggleLockedPosition(dv.Document)), 'toggleBackground')
);
e.stopPropagation();
};
@@ -356,7 +347,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
@action
onRotateCenterDown = (e: React.PointerEvent): void => {
this._isRotating = true;
- const seldocview = SelectionManager.Views[0];
+ const seldocview = DocumentView.Selected()[0];
setupMoveUpEvents(
this,
e,
@@ -374,11 +365,11 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
this._isRotating = true;
const rcScreen = { X: this.rotCenter[0], Y: this.rotCenter[1] };
const rotateUndo = UndoManager.StartBatch('drag rotation');
- const selectedInk = SelectionManager.Views.filter(i => i.ComponentView instanceof InkingStroke);
+ const selectedInk = DocumentView.Selected().filter(i => i.ComponentView instanceof InkingStroke);
const centerPoint = this.rotCenter.slice();
const infos = new Map<Doc, { unrotatedDocPos: { x: number; y: number }; startRotCtr: { x: number; y: number }; accumRot: number }>();
- const seldocview = SelectionManager.Views[0];
- SelectionManager.Views.forEach(dv => {
+ const seldocview = DocumentView.Selected()[0];
+ DocumentView.Selected().forEach(dv => {
const accumRot = (NumCast(dv.Document._rotation) / 180) * Math.PI;
const localRotCtr = dv.screenToViewTransform().transformPoint(rcScreen.X, rcScreen.Y);
const localRotCtrOffset = [localRotCtr[0] - NumCast(dv.Document.width) / 2, localRotCtr[1] - NumCast(dv.Document.height) / 2];
@@ -387,7 +378,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
infos.set(dv.Document, { unrotatedDocPos, startRotCtr, accumRot });
});
const infoRot = (angle: number, isAbs = false) => {
- SelectionManager.Views.forEach(
+ DocumentView.Selected().forEach(
action(dv => {
const { unrotatedDocPos, startRotCtr, accumRot } = infos.get(dv.Document)!;
const endRotCtr = Utils.rotPt(startRotCtr.x, startRotCtr.y, isAbs ? angle : accumRot + angle);
@@ -437,7 +428,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
@action
onPointerDown = (e: React.PointerEvent): void => {
- SnappingManager.SetIsResizing(SelectionManager.Docs.lastElement()?.[Id]); // turns off pointer events on things like youtube videos and web pages so that dragging doesn't get "stuck" when cursor moves over them
+ SnappingManager.SetIsResizing(DocumentView.Selected().lastElement()?.Document[Id]); // turns off pointer events on things like youtube videos and web pages so that dragging doesn't get "stuck" when cursor moves over them
setupMoveUpEvents(this, e, this.onPointerMove, this.onPointerUp, emptyFunction);
e.stopPropagation();
const id = (this._resizeHdlId = e.currentTarget.className);
@@ -449,7 +440,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
};
this._resizeUndo = UndoManager.StartBatch('drag resizing');
this._snapPt = { x: e.pageX, y: e.pageY };
- SelectionManager.Views.forEach(docView => CollectionFreeFormView.from(docView)?.dragStarting(false, false));
+ DocumentView.Selected().forEach(docView => CollectionFreeFormView.from(docView)?.dragStarting(false, false));
};
projectDragToAspect = (e: PointerEvent, docView: DocumentView, fixedAspect: number) => {
@@ -467,7 +458,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
return project([e.clientX + this._offset.x, e.clientY + this._offset.y], tl, [tl[0] + fixedAspect, tl[1] + 1]);
};
onPointerMove = (e: PointerEvent): boolean => {
- const first = SelectionManager.Views[0];
+ const first = DocumentView.Selected()[0];
const effectiveAcl = GetEffectiveAcl(first.Document);
if (!(effectiveAcl === AclAdmin || effectiveAcl === AclEdit || effectiveAcl === AclAugment)) return false;
if (!first) return false;
@@ -484,10 +475,10 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
!this._interactionLock && runInAction(async () => { // resize selected docs if we're not in the middle of a resize (ie, throttle input events to frame rate)
this._interactionLock = true;
this._snapPt = thisPt;
- e.ctrlKey && (SelectionManager.Views.forEach(docView => !Doc.NativeHeight(docView.Document) && docView.toggleNativeDimensions()));
- const hasFixedAspect = SelectionManager.Docs.some(this.hasFixedAspect);
+ e.ctrlKey && (DocumentView.Selected().forEach(docView => !Doc.NativeHeight(docView.Document) && docView.toggleNativeDimensions()));
+ const hasFixedAspect = DocumentView.Selected().map(dv => dv.Document).some(this.hasFixedAspect);
const scaleAspect = {x:scale.x === 1 && hasFixedAspect ? scale.y : scale.x, y: scale.x !== 1 && hasFixedAspect ? scale.x : scale.y};
- SelectionManager.Views.forEach(docView =>
+ DocumentView.Selected().forEach(docView =>
this.resizeView(docView, refPt, scaleAspect, { dragHdl, ctrlKey:e.ctrlKey })); // prettier-ignore
await new Promise<any>(res => { setTimeout(() => { res(this._interactionLock = undefined)})});
}); // prettier-ignore
@@ -526,7 +517,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
const doc = docView.Document;
if (doc.isGroup) {
DocListCast(doc.data)
- .map(member => DocumentManager.Instance.getDocumentView(member, docView)!)
+ .map(member => DocumentView.getDocumentView(member, docView)!)
.forEach(member => this.resizeView(member, refPt, scale, opts));
doc.xPadding = NumCast(doc.xPadding) * scale.x;
doc.yPadding = NumCast(doc.yPadding) * scale.y;
@@ -607,7 +598,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
this._resizeUndo?.end();
// detect layout_autoHeight gesture and apply
- SelectionManager.Views.forEach(view => {
+ DocumentView.Selected().forEach(view => {
NumCast(view.Document._height) < 20 && (view.layoutDoc._layout_autoHeight = true);
});
// need to change points for resize, or else rotation/control points will fail.
@@ -626,18 +617,18 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
@computed
get selectionTitle(): string {
- if (SelectionManager.Views.length === 1) {
- const selected = SelectionManager.Views[0];
+ if (DocumentView.Selected().length === 1) {
+ const selected = DocumentView.Selected()[0];
if (this._titleControlString.startsWith('$')) {
return Field.toJavascriptString(selected.Document[this._titleControlString.substring(1)] as FieldType) || '-unset-';
}
return this._accumulatedTitle;
}
- return SelectionManager.Views.length > 1 ? '-multiple-' : '-unset-';
+ return DocumentView.Selected().length > 1 ? '-multiple-' : '-unset-';
}
@computed get rotCenter() {
- const lastView = SelectionManager.Views.lastElement();
+ const lastView = DocumentView.Selected().lastElement();
if (lastView) {
const invXf = lastView.screenToContentsTransform().inverse();
const seldoc = lastView.layoutDoc;
@@ -649,7 +640,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
render() {
const { b, r, x, y } = this.Bounds;
- const seldocview = SelectionManager.Views.lastElement();
+ const seldocview = DocumentView.Selected().lastElement();
if (SnappingManager.IsDragging || r - x < 1 || x === Number.MAX_VALUE || !seldocview || this._hidden || isNaN(r) || isNaN(b) || isNaN(x) || isNaN(y)) {
setTimeout(
action(() => {
@@ -678,7 +669,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
hideDecorations ||
seldocview._props.hideOpenButton ||
seldocview.Document.layout_hideOpenButton ||
- SelectionManager.Views.some(docView => docView.Document._dragOnlyWithinContainer || docView.Document.isGroup || docView.Document.layout_hideOpenButton) ||
+ DocumentView.Selected().some(docView => docView.Document._dragOnlyWithinContainer || docView.Document.isGroup || docView.Document.layout_hideOpenButton) ||
this._isRounding ||
this._isRotating;
const hideDeleteButton =
@@ -688,7 +679,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
this._isRotating ||
seldocview._props.hideDeleteButton ||
seldocview.Document.hideDeleteButton ||
- SelectionManager.Views.some(docView => {
+ DocumentView.Selected().some(docView => {
const collectionAcl = docView.containerViewPath?.()?.lastElement() ? GetEffectiveAcl(docView.containerViewPath?.().lastElement().dataDoc) : AclEdit;
return collectionAcl !== AclAdmin && collectionAcl !== AclEdit && GetEffectiveAcl(docView.Document) !== AclAdmin;
});
@@ -703,7 +694,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
const bounds = this.ClippedBounds;
const useLock = bounds.r - bounds.x > 135;
const useRotation = !hideResizers && seldocview.Document.type !== DocumentType.EQUATION && CollectionFreeFormDocumentView.from(seldocview); // when do we want an object to not rotate?
- const rotation = SelectionManager.Views.length === 1 ? seldocview.screenToContentsTransform().inverse().RotateDeg : 0;
+ const rotation = DocumentView.Selected().length === 1 ? seldocview.screenToContentsTransform().inverse().RotateDeg : 0;
// Radius constants
const useRounding = seldocview.ComponentView instanceof ImageBox || seldocview.ComponentView instanceof FormattedTextBox || seldocview.ComponentView instanceof CollectionFreeFormView;
@@ -773,7 +764,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
);
const centery = hideTitle ? 0 : this._titleHeight;
const transformOrigin = `${50}% calc(50% + ${centery / 2}px)`;
- const freeformDoc = SelectionManager.Views.some(v => CollectionFreeFormDocumentView.from(v));
+ const freeformDoc = DocumentView.Selected().some(v => CollectionFreeFormDocumentView.from(v));
return (
<div className="documentDecorations" style={{ display: this._showNothing && !freeformDoc ? 'none' : undefined }}>
<div
@@ -786,7 +777,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
transformOrigin,
background: SnappingManager.ShiftKey ? undefined : 'yellow',
pointerEvents: SnappingManager.ShiftKey || SnappingManager.IsResizing ? 'none' : 'all',
- display: SelectionManager.Views.length <= 1 || hideDecorations ? 'none' : undefined,
+ display: DocumentView.Selected().length <= 1 || hideDecorations ? 'none' : undefined,
transform: `rotate(${rotation}deg)`,
}}
onPointerDown={this.onBackgroundDown}
@@ -843,7 +834,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
style={{
transform: `translate(${-this._resizeBorderWidth / 2 + 10}px, ${this._resizeBorderWidth + bounds.b - bounds.y + this._titleHeight}px) `,
}}>
- <DocumentButtonBar views={() => SelectionManager.Views} />
+ <DocumentButtonBar views={() => DocumentView.Selected()} />
</div>
)}
</div>
diff --git a/src/client/views/FieldsDropdown.tsx b/src/client/views/FieldsDropdown.tsx
index 3cb7848c2..0ea0ebd83 100644
--- a/src/client/views/FieldsDropdown.tsx
+++ b/src/client/views/FieldsDropdown.tsx
@@ -13,7 +13,7 @@ import Select from 'react-select';
import { Doc } from '../../fields/Doc';
import { DocOptions, FInfo } from '../documents/Documents';
import { SearchUtil } from '../util/SearchUtil';
-import { SettingsManager } from '../util/SettingsManager';
+import { SnappingManager } from '../util/SnappingManager';
import './FilterPanel.scss';
import { ObservableReactComponent } from './ObservableReactComponent';
@@ -68,36 +68,36 @@ export class FieldsDropdown extends ObservableReactComponent<fieldsDropdownProps
...baseStyles,
minHeight: '5px',
maxHeight: '30px',
- color: SettingsManager.userColor,
- backgroundColor: SettingsManager.userBackgroundColor,
+ color: SnappingManager.userColor,
+ backgroundColor: SnappingManager.userBackgroundColor,
padding: 0,
margin: 0,
}),
singleValue: (baseStyles /* , state */) => ({
...baseStyles,
- color: SettingsManager.userColor,
- background: SettingsManager.userBackgroundColor,
+ color: SnappingManager.userColor,
+ background: SnappingManager.userBackgroundColor,
}),
placeholder: (baseStyles /* , state */) => ({
...baseStyles,
- color: SettingsManager.userColor,
- background: SettingsManager.userBackgroundColor,
+ color: SnappingManager.userColor,
+ background: SnappingManager.userBackgroundColor,
}),
input: (baseStyles /* , state */) => ({
...baseStyles,
padding: 0,
margin: 0,
- color: SettingsManager.userColor,
+ color: SnappingManager.userColor,
background: 'transparent',
}),
option: (baseStyles, state) => ({
...baseStyles,
- color: SettingsManager.userColor,
- background: !state.isFocused ? SettingsManager.userBackgroundColor : SettingsManager.userVariantColor,
+ color: SnappingManager.userColor,
+ background: !state.isFocused ? SnappingManager.userBackgroundColor : SnappingManager.userVariantColor,
}),
menuList: (baseStyles /* , state */) => ({
...baseStyles,
- backgroundColor: SettingsManager.userBackgroundColor,
+ backgroundColor: SnappingManager.userBackgroundColor,
}),
}}
placeholder={typeof this._props.placeholder === 'string' ? this._props.placeholder : this._props.placeholder?.()}
diff --git a/src/client/views/FilterPanel.tsx b/src/client/views/FilterPanel.tsx
index ed9fc8dfb..c97edd7f0 100644
--- a/src/client/views/FilterPanel.tsx
+++ b/src/client/views/FilterPanel.tsx
@@ -11,12 +11,12 @@ import { Doc, DocListCast, Field, FieldType, LinkedTo, StrListCast } from '../..
import { Id } from '../../fields/FieldSymbols';
import { List } from '../../fields/List';
import { RichTextField } from '../../fields/RichTextField';
-import { DocumentManager } from '../util/DocumentManager';
import { SearchUtil } from '../util/SearchUtil';
-import { SettingsManager } from '../util/SettingsManager';
+import { SnappingManager } from '../util/SnappingManager';
import { undoable } from '../util/UndoManager';
import { FieldsDropdown } from './FieldsDropdown';
import './FilterPanel.scss';
+import { DocumentView } from './nodes/DocumentView';
import { Handle, Tick, TooltipRail, Track } from './nodes/SliderBox-components';
import { ObservableReactComponent } from './ObservableReactComponent';
@@ -40,7 +40,7 @@ export class FilterPanel extends ObservableReactComponent<filterProps> {
return this._props.Document;
}
@computed get targetDocChildKey() {
- const targetView = DocumentManager.Instance.getFirstDocumentView(this.Document);
+ const targetView = DocumentView.getFirstDocumentView(this.Document);
return targetView?.ComponentView?.annotationKey ?? targetView?.ComponentView?.fieldKey ?? 'data';
}
@computed get targetDocChildren() {
@@ -299,7 +299,7 @@ export class FilterPanel extends ObservableReactComponent<filterProps> {
.find(filter => filter.split(Doc.FilterSep)[0] === facetHeader)
?.split(Doc.FilterSep)[1]
}
- style={{ color: SettingsManager.userColor, background: SettingsManager.userBackgroundColor }}
+ style={{ color: SnappingManager.userColor, background: SnappingManager.userBackgroundColor }}
onBlur={undoable(e => Doc.setDocFilter(this.Document, facetHeader, e.currentTarget.value, !e.currentTarget.value ? 'remove' : 'match'), 'set text filter')}
onKeyDown={e => e.key === 'Enter' && undoable(() => Doc.setDocFilter(this.Document, facetHeader, e.currentTarget.value, !e.currentTarget.value ? 'remove' : 'match'), 'set text filter')()}
/>
diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx
index 0d1573ea3..7246f0ba0 100644
--- a/src/client/views/GestureOverlay.tsx
+++ b/src/client/views/GestureOverlay.tsx
@@ -65,8 +65,6 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil
@observable private _clipboardDoc?: JSX.Element = undefined;
@observable private _possibilities: JSX.Element[] = [];
- public static DownDocView: DocumentView | undefined;
-
@computed private get height(): number {
return 2 * Math.max(this._pointerY && this._thumbY ? this._thumbY - this._pointerY : 100, 100);
}
@@ -136,7 +134,7 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil
}
@action
onPointerUp = () => {
- GestureOverlay.DownDocView = undefined;
+ DocumentView.DownDocView = undefined;
if (this._points.length > 1) {
const B = this.svgBounds;
const points = this._points.map(p => ({ X: p.X - B.left, Y: p.Y - B.top }));
@@ -388,7 +386,7 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil
}
get elements() {
- const selView = GestureOverlay.DownDocView;
+ const selView = DocumentView.DownDocView;
const width = Number(ActiveInkWidth()) * NumCast(selView?.Document._freeform_scale, 1); // * (selView?.screenToViewTransform().Scale || 1);
const rect = this._overlayRef.current?.getBoundingClientRect();
const B = { left: -20000, right: 20000, top: -20000, bottom: 20000, width: 40000, height: 40000 }; // this.getBounds(this._points, true);
diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts
index 0f444094a..c73da35bc 100644
--- a/src/client/views/GlobalKeyHandler.ts
+++ b/src/client/views/GlobalKeyHandler.ts
@@ -8,7 +8,6 @@ import { Cast, PromiseValue } from '../../fields/Types';
import { GoogleAuthenticationManager } from '../apis/GoogleAuthenticationManager';
import { DragManager } from '../util/DragManager';
import { GroupManager } from '../util/GroupManager';
-import { SelectionManager } from '../util/SelectionManager';
import { SettingsManager } from '../util/SettingsManager';
import { SharingManager } from '../util/SharingManager';
import { SnappingManager } from '../util/SnappingManager';
@@ -23,6 +22,7 @@ import { CollectionStackedTimeline } from './collections/CollectionStackedTimeli
import { CollectionFreeFormView } from './collections/collectionFreeForm';
import { CollectionFreeFormDocumentView } from './nodes/CollectionFreeFormDocumentView';
import { DocumentLinksButton } from './nodes/DocumentLinksButton';
+import { DocumentView } from './nodes/DocumentView';
import { OpenWhereMod } from './nodes/OpenWhere';
import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox';
import { AnchorMenu } from './pdf/AnchorMenu';
@@ -34,10 +34,12 @@ type KeyControlInfo = {
};
type KeyHandler = (keycode: string, e: KeyboardEvent) => KeyControlInfo;
export class KeyManager {
- public static Instance = new KeyManager();
+ // eslint-disable-next-line no-use-before-define
+ public static Instance: KeyManager;
private router = new Map<string, KeyHandler>();
constructor() {
+ KeyManager.Instance = this;
const isMac = navigator.platform.toLowerCase().indexOf('mac') >= 0;
// SHIFT CONTROL ALT META
@@ -46,6 +48,16 @@ export class KeyManager {
this.router.set(isMac ? '0100' : '0010', this.alt);
this.router.set(isMac ? '1001' : '1100', this.ctrl_shift);
this.router.set('1000', this.shift);
+
+ window.removeEventListener('keydown', KeyManager.Instance.handleModifiers, true);
+ window.addEventListener('keydown', KeyManager.Instance.handleModifiers, true);
+ window.removeEventListener('keyup', KeyManager.Instance.unhandleModifiers);
+ window.addEventListener('keyup', KeyManager.Instance.unhandleModifiers);
+ window.removeEventListener('keydown', KeyManager.Instance.handle);
+ window.addEventListener('keydown', KeyManager.Instance.handle);
+ window.removeEventListener('keyup', KeyManager.Instance.unhandle);
+ window.addEventListener('keyup', KeyManager.Instance.unhandle);
+ window.addEventListener('paste', KeyManager.Instance.paste as any);
}
public unhandle = action((/* e: KeyboardEvent */) => {
@@ -89,8 +101,8 @@ export class KeyManager {
private handleGreedy = action((/* keyname: string */) => {});
nudge = (x: number, y: number, label: string) => {
- const nudgeable = SelectionManager.Views.some(dv => CollectionFreeFormDocumentView.from(dv)?.nudge);
- nudgeable && UndoManager.RunInBatch(() => SelectionManager.Views.map(dv => CollectionFreeFormDocumentView.from(dv)?.nudge(x, y)), label);
+ const nudgeable = DocumentView.Selected().some(dv => CollectionFreeFormDocumentView.from(dv)?.nudge);
+ nudgeable && UndoManager.RunInBatch(() => DocumentView.Selected().map(dv => CollectionFreeFormDocumentView.from(dv)?.nudge(x, y)), label);
return { stopPropagation: nudgeable, preventDefault: nudgeable };
};
@@ -98,16 +110,16 @@ export class KeyManager {
switch (keyname) {
case 'u':
if (document.activeElement?.tagName !== 'INPUT' && document.activeElement?.tagName !== 'TEXTAREA') {
- const ungroupings = SelectionManager.Views;
+ const ungroupings = DocumentView.Selected();
undoable(() => () => ungroupings.forEach(dv => { dv.layoutDoc.group = undefined; }), 'ungroup');
- SelectionManager.DeselectAll();
+ DocumentView.DeselectAll();
}
break;
case 'g':
if (document.activeElement?.tagName !== 'INPUT' && document.activeElement?.tagName !== 'TEXTAREA') {
- const selected = SelectionManager.Views;
+ const selected = DocumentView.Selected();
const cv = selected.reduce((col, dv) => (!col || CollectionFreeFormView.from(dv) === col ? CollectionFreeFormView.from(dv) : undefined), undefined as undefined | CollectionFreeFormView);
- cv && undoable(() => cv._marqueeViewRef.current?.collection(e, true, SelectionManager.Docs), 'grouping');
+ cv && undoable(() => cv._marqueeViewRef.current?.collection(e, true, DocumentView.SelectedDocs()), 'grouping');
}
break;
case ' ':
@@ -133,7 +145,7 @@ export class KeyManager {
doDeselect = !ContextMenu.Instance.closeMenu();
}
if (doDeselect) {
- SelectionManager.DeselectAll();
+ DocumentView.DeselectAll();
LightboxView.Instance.SetLightboxDoc(undefined);
}
// DictationManager.Controls.stop();
@@ -153,7 +165,7 @@ export class KeyManager {
if (document.activeElement?.tagName !== 'INPUT' && document.activeElement?.tagName !== 'TEXTAREA') {
if (LightboxView.LightboxDoc) {
LightboxView.Instance.SetLightboxDoc(undefined);
- SelectionManager.DeselectAll();
+ DocumentView.DeselectAll();
} else if (!window.getSelection()?.toString()) DocumentDecorations.Instance.onCloseClick(true);
return { stopPropagation: true, preventDefault: true };
}
@@ -179,15 +191,15 @@ export class KeyManager {
case 'arrowdown': return this.nudge(0, 10, 'nudge down');
case 'u' :
if (document.activeElement?.tagName !== 'INPUT' && document.activeElement?.tagName !== 'TEXTAREA') {
- UndoManager.RunInBatch(() => SelectionManager.Docs.forEach(doc => {doc.group = undefined}), 'unggroup');
- SelectionManager.DeselectAll();
+ UndoManager.RunInBatch(() => DocumentView.Selected().map(dv => dv.Document).forEach(doc => {doc.group = undefined}), 'unggroup');
+ DocumentView.DeselectAll();
}
break;
case 'g':
if (document.activeElement?.tagName !== 'INPUT' && document.activeElement?.tagName !== 'TEXTAREA') {
const randomGroup = random(0, 1000);
- UndoManager.RunInBatch(() => SelectionManager.Docs.forEach(doc => {doc.group = randomGroup}), 'group');
- SelectionManager.DeselectAll();
+ UndoManager.RunInBatch(() => DocumentView.Selected().forEach(dv => {dv.Document.group = randomGroup}), 'group');
+ DocumentView.DeselectAll();
}
break;
default:
@@ -206,7 +218,7 @@ export class KeyManager {
switch (keyname) {
case 'Æ’':
case 'f':
- UndoManager.RunInBatch(() => CollectionFreeFormDocumentView.from(SelectionManager.Views?.[0])?.float(), 'float');
+ UndoManager.RunInBatch(() => CollectionFreeFormDocumentView.from(DocumentView.Selected()?.[0])?.float(), 'float');
break;
default:
}
@@ -259,8 +271,8 @@ export class KeyManager {
}
break;
case 'f':
- if (SelectionManager.Views.length === 1 && SelectionManager.Views[0].ComponentView?.search) {
- SelectionManager.Views[0].ComponentView?.search?.('', false, false);
+ if (DocumentView.Selected().length === 1 && DocumentView.Selected()[0].ComponentView?.search) {
+ DocumentView.Selected()[0].ComponentView?.search?.('', false, false);
} else {
const searchBtn = DocListCast(Doc.MyLeftSidebarMenu.data).find(d => d.target === Doc.MySearcher);
if (searchBtn) {
@@ -279,14 +291,14 @@ export class KeyManager {
break;
case 'y':
if (Doc.ActivePage !== 'home') {
- SelectionManager.DeselectAll();
+ DocumentView.DeselectAll();
UndoManager.Redo();
}
stopPropagation = false;
break;
case 'z':
if (Doc.ActivePage !== 'home') {
- SelectionManager.DeselectAll();
+ DocumentView.DeselectAll();
UndoManager.Undo();
}
stopPropagation = false;
@@ -302,11 +314,17 @@ export class KeyManager {
preventDefault = false;
break;
case 'x':
- if (SelectionManager.Views.length) {
+ if (DocumentView.Selected().length) {
const bds = DocumentDecorations.Instance.Bounds;
- const pt = SelectionManager.Views[0].screenToViewTransform().transformPoint(bds.x + (bds.r - bds.x) / 2, bds.y + (bds.b - bds.y) / 2);
- const text = `__DashDocId(${pt?.[0] || 0},${pt?.[1] || 0}):` + SelectionManager.Views.map(dv => dv.Document[Id]).join(':');
- SelectionManager.Views.length && navigator.clipboard.writeText(text);
+ const pt = DocumentView.Selected()[0] //
+ .screenToViewTransform()
+ .transformPoint(bds.x + (bds.r - bds.x) / 2, bds.y + (bds.b - bds.y) / 2);
+ const text =
+ `__DashDocId(${pt?.[0] || 0},${pt?.[1] || 0}):` + //
+ DocumentView.Selected()
+ .map(dv => dv.Document[Id])
+ .join(':'); // prettier-ignore
+ DocumentView.Selected().length && navigator.clipboard.writeText(text);
DocumentDecorations.Instance.onCloseClick(true);
stopPropagation = false;
preventDefault = false;
@@ -315,9 +333,15 @@ export class KeyManager {
case 'c':
if ((document.activeElement as any)?.type !== 'text' && !AnchorMenu.Instance.Active && DocumentDecorations.Instance.Bounds.r - DocumentDecorations.Instance.Bounds.x > 2) {
const bds = DocumentDecorations.Instance.Bounds;
- const pt = SelectionManager.Views[0].screenToViewTransform().transformPoint(bds.x + (bds.r - bds.x) / 2, bds.y + (bds.b - bds.y) / 2);
- const text = `__DashCloneId(${pt?.[0] || 0},${pt?.[1] || 0}):` + SelectionManager.Views.map(dv => dv.Document[Id]).join(':');
- SelectionManager.Views.length && navigator.clipboard.writeText(text);
+ const pt = DocumentView.Selected()[0]
+ .screenToViewTransform()
+ .transformPoint(bds.x + (bds.r - bds.x) / 2, bds.y + (bds.b - bds.y) / 2); // prettier-ignore
+ const text =
+ `__DashCloneId(${pt?.[0] || 0},${pt?.[1] || 0}):` +
+ DocumentView.SelectedDocs()
+ .map(doc => doc[Id])
+ .join(':'); // prettier-ignore
+ DocumentView.Selected().length && navigator.clipboard.writeText(text);
stopPropagation = false;
}
preventDefault = false;
@@ -336,7 +360,7 @@ export class KeyManager {
if (!plain) return;
const clone = plain.startsWith('__DashCloneId(');
const docids = plain.split(':'); // hack! docids[0] is the top left of the selection rectangle
- const addDocument = SelectionManager.Views.lastElement()?.ComponentView?.addDocument;
+ const addDocument = DocumentView.Selected().lastElement()?.ComponentView?.addDocument;
if (addDocument && (plain.startsWith('__DashDocId(') || clone)) {
Doc.Paste(docids.slice(1), clone, addDocument);
}
diff --git a/src/client/views/InkControlPtHandles.tsx b/src/client/views/InkControlPtHandles.tsx
index b4fe44733..a49923ffb 100644
--- a/src/client/views/InkControlPtHandles.tsx
+++ b/src/client/views/InkControlPtHandles.tsx
@@ -7,7 +7,6 @@ import { List } from '../../fields/List';
import { listSpec } from '../../fields/Schema';
import { Cast } from '../../fields/Types';
import { returnFalse, setupMoveUpEvents } from '../../ClientUtils';
-import { SelectionManager } from '../util/SelectionManager';
import { UndoManager } from '../util/UndoManager';
import { Colors } from './global/globalEnums';
import { InkingStroke } from './InkingStroke';
@@ -15,6 +14,7 @@ import { InkStrokeProperties } from './InkStrokeProperties';
import { SnappingManager } from '../util/SnappingManager';
import { ObservableReactComponent } from './ObservableReactComponent';
import { PointData } from '../../pen-gestures/GestureTypes';
+import { DocumentView } from './nodes/DocumentView';
export interface InkControlProps {
inkDoc: Doc;
@@ -224,8 +224,8 @@ export class InkEndPtHandles extends ObservableReactComponent<InkEndProps> {
const v1n = { X: v1.X / v1len, Y: v1.Y / v1len };
const v2n = { X: v2.X / v2len, Y: v2.Y / v2len };
const angle = Math.acos(v1n.X * v2n.X + v1n.Y * v2n.Y) * Math.sign(v1.X * v2.Y - v2.X * v1.Y);
- InkStrokeProperties.Instance.stretchInk(SelectionManager.Views, scaling, p2, v1n, moveEv.shiftKey);
- InkStrokeProperties.Instance.rotateInk(SelectionManager.Views, angle, pt2()); // bcz: call pt2() func here because pt2 will have changed from previous stretchInk call
+ InkStrokeProperties.Instance.stretchInk(DocumentView.Selected(), scaling, p2, v1n, moveEv.shiftKey);
+ InkStrokeProperties.Instance.rotateInk(DocumentView.Selected(), angle, pt2()); // bcz: call pt2() func here because pt2 will have changed from previous stretchInk call
return false;
}),
action(() => {
diff --git a/src/client/views/InkStrokeProperties.ts b/src/client/views/InkStrokeProperties.ts
index 109a9cad4..3920ecc2a 100644
--- a/src/client/views/InkStrokeProperties.ts
+++ b/src/client/views/InkStrokeProperties.ts
@@ -9,7 +9,6 @@ import { Cast, NumCast } from '../../fields/Types';
import { PointData } from '../../pen-gestures/GestureTypes';
import { Point } from '../../pen-gestures/ndollar';
import { DocumentType } from '../documents/DocumentTypes';
-import { DocumentManager } from '../util/DocumentManager';
import { undoBatch } from '../util/UndoManager';
import { FitOneCurve } from '../util/bezierFit';
import { InkingStroke } from './InkingStroke';
@@ -386,7 +385,7 @@ export class InkStrokeProperties {
containingCollection?.childDocs
.filter(doc => doc.type === DocumentType.INK)
.forEach(doc => {
- const testInkView = DocumentManager.Instance.getDocumentView(doc, containingDocView);
+ const testInkView = DocumentView.getDocumentView(doc, containingDocView);
const snapped = testInkView?.ComponentView?.snapPt?.(screenDragPt, doc === inkView.Document ? this.excludeSelfSnapSegs(ink, controlIndex) : []);
if (snapped && snapped.distance < snapData.distance) {
const snappedInkPt = doc === inkView.Document ? snapped.nearestPt : inkView.ComponentView?.ptFromScreen?.(testInkView?.ComponentView?.ptToScreen?.(snapped.nearestPt) ?? { X: 0, Y: 0 }); // convert from snapped ink coordinate system to dragged ink coordinate system by converting to/from screen space
diff --git a/src/client/views/InkTranscription.tsx b/src/client/views/InkTranscription.tsx
index 7e2b334af..1ed8de1be 100644
--- a/src/client/views/InkTranscription.tsx
+++ b/src/client/views/InkTranscription.tsx
@@ -6,7 +6,6 @@
// import { Cast, DateCast, NumCast } from '../../fields/Types';
// import { aggregateBounds } from '../../Utils';
// import { DocumentType } from '../documents/DocumentTypes';
-// import { DocumentManager } from '../util/DocumentManager';
// import { CollectionFreeFormView } from './collections/collectionFreeForm';
// import { InkingStroke } from './InkingStroke';
// import './InkTranscription.scss';
diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx
index 884512539..62fc73c78 100644
--- a/src/client/views/InkingStroke.tsx
+++ b/src/client/views/InkingStroke.tsx
@@ -44,7 +44,7 @@ import { InkTangentHandles } from './InkTangentHandles';
import { FieldView, FieldViewProps } from './nodes/FieldView';
import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox';
import { PinDocView, PinProps } from './PinFuncs';
-import { StyleProp } from './StyleProvider';
+import { StyleProp } from './StyleProp';
const { INK_MASK_SIZE } = require('./global/globalCssVariables.module.scss'); // prettier-ignore
diff --git a/src/client/views/LightboxView.tsx b/src/client/views/LightboxView.tsx
index 020525ef8..12d899388 100644
--- a/src/client/views/LightboxView.tsx
+++ b/src/client/views/LightboxView.tsx
@@ -13,10 +13,6 @@ import { CreateLinkToActiveAudio, Doc, DocListCast, FieldResult, Opt } from '../
import { Id } from '../../fields/FieldSymbols';
import { InkTool } from '../../fields/InkField';
import { Cast, NumCast, toList } from '../../fields/Types';
-import { DocumentManager } from '../util/DocumentManager';
-import { LinkManager } from '../util/LinkManager';
-import { SelectionManager } from '../util/SelectionManager';
-import { SettingsManager } from '../util/SettingsManager';
import { SnappingManager } from '../util/SnappingManager';
import { Transform } from '../util/Transform';
import { GestureOverlay } from './GestureOverlay';
@@ -24,8 +20,6 @@ import './LightboxView.scss';
import { ObservableReactComponent } from './ObservableReactComponent';
import { DefaultStyleProvider, wavyBorderPath } from './StyleProvider';
import { CollectionDockingView } from './collections/CollectionDockingView';
-import { CollectionStackedTimeline } from './collections/CollectionStackedTimeline';
-import { TabDocView } from './collections/TabDocView';
import { DocumentView } from './nodes/DocumentView';
import { OpenWhere, OpenWhereMod } from './nodes/OpenWhere';
@@ -90,7 +84,7 @@ export class LightboxView extends ObservableReactComponent<LightboxViewProps> {
});
const l = CreateLinkToActiveAudio(() => doc).lastElement();
l && (Cast(l.link_anchor_2, Doc, null).backgroundColor = 'lightgreen');
- CollectionStackedTimeline.CurrentlyPlaying?.forEach(dv => dv.ComponentView?.Pause?.());
+ DocumentView.CurrentlyPlaying?.forEach(dv => dv.ComponentView?.Pause?.());
this._history.push({ doc, target });
} else {
this._future = [];
@@ -98,14 +92,14 @@ export class LightboxView extends ObservableReactComponent<LightboxViewProps> {
Doc.ActiveTool = InkTool.None;
SnappingManager.SetExploreMode(false);
}
- SelectionManager.DeselectAll();
+ DocumentView.DeselectAll();
if (future) {
this._future.push(
...(this._doc ? [this._doc] : []),
...future
.slice()
.sort((a, b) => NumCast(b._timecodeToShow) - NumCast(a._timecodeToShow))
- .sort((a, b) => LinkManager.Links(a).length - LinkManager.Links(b).length)
+ .sort((a, b) => Doc.Links(a).length - Doc.Links(b).length)
);
}
this._doc = doc;
@@ -134,11 +128,11 @@ export class LightboxView extends ObservableReactComponent<LightboxViewProps> {
const lightDoc = this._doc;
if (!lightDoc) return;
const target = (this._docTarget = this._future.pop());
- const targetDocView = target && DocumentManager.Instance.getLightboxDocumentView(target);
+ const targetDocView = target && DocumentView.getLightboxDocumentView(target);
if (targetDocView && target) {
const l = CreateLinkToActiveAudio(() => targetDocView.ComponentView?.getAnchor?.(true) || target).lastElement();
l && (Cast(l.link_anchor_2, Doc, null).backgroundColor = 'lightgreen');
- DocumentManager.Instance.showDocument(target, { willZoomCentered: true, zoomScale: 0.9 });
+ DocumentView.showDocument(target, { willZoomCentered: true, zoomScale: 0.9 });
if (this._history.lastElement().target !== target) this._history.push({ doc: lightDoc, target });
} else if (!target && this._path.length) {
savedKeys.forEach(key => {
@@ -157,10 +151,10 @@ export class LightboxView extends ObservableReactComponent<LightboxViewProps> {
return;
}
const { doc, target } = this._history.lastElement();
- const docView = DocumentManager.Instance.getLightboxDocumentView(target || doc);
+ const docView = DocumentView.getLightboxDocumentView(target || doc);
if (docView) {
this._docTarget = target;
- target && DocumentManager.Instance.showDocument(target, { willZoomCentered: true, zoomScale: 0.9 });
+ target && DocumentView.showDocument(target, { willZoomCentered: true, zoomScale: 0.9 });
} else {
this.SetLightboxDoc(doc, target);
}
@@ -178,8 +172,8 @@ export class LightboxView extends ObservableReactComponent<LightboxViewProps> {
if (this._docTarget) {
const fieldKey = Doc.LayoutFieldKey(this._docTarget);
const contents = [...DocListCast(this._docTarget[fieldKey]), ...DocListCast(this._docTarget[fieldKey + '_annotations'])];
- const links = LinkManager.Links(this._docTarget)
- .map(link => LinkManager.getOppositeAnchor(link, this._docTarget!)!)
+ const links = Doc.Links(this._docTarget)
+ .map(link => Doc.getOppositeAnchor(link, this._docTarget!)!)
.filter(doc => doc);
this.SetLightboxDoc(this._docTarget, undefined, contents.length ? contents : links);
}
@@ -220,7 +214,7 @@ export class LightboxView extends ObservableReactComponent<LightboxViewProps> {
<div
className="lightboxView-navBtn"
title={color}
- style={{ top, color: SettingsManager.userColor, background: undefined }}
+ style={{ top, color: SnappingManager.userColor, background: undefined }}
onClick={e => {
e.stopPropagation();
click();
@@ -237,8 +231,8 @@ export class LightboxView extends ObservableReactComponent<LightboxViewProps> {
<div className={classname}>
<Toggle
tooltip={tooltip}
- color={SettingsManager.userColor}
- background={toggleBackground ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor}
+ color={SnappingManager.userColor}
+ background={toggleBackground ? SnappingManager.userVariantColor : SnappingManager.userBackgroundColor}
toggleType={ToggleType.BUTTON}
type={Type.TERT}
icon={<FontAwesomeIcon icon={toggleBackground ? icon : (icon2 as IconProp) || icon} size="sm" />}
@@ -252,7 +246,7 @@ export class LightboxView extends ObservableReactComponent<LightboxViewProps> {
return !this._doc ? null : (
<div
className="lightboxView-frame"
- style={{ background: SettingsManager.userBackgroundColor }}
+ style={{ background: SnappingManager.userBackgroundColor }}
onPointerDown={e => {
downx = e.clientX;
downy = e.clientY;
@@ -266,7 +260,7 @@ export class LightboxView extends ObservableReactComponent<LightboxViewProps> {
width: this.lightboxWidth(),
height: this.lightboxHeight(),
clipPath: `path('${Doc.UserDoc().renderStyle === 'comic' ? wavyBorderPath(this.lightboxWidth(), this.lightboxHeight()) : undefined}')`,
- background: SettingsManager.userBackgroundColor,
+ background: SnappingManager.userBackgroundColor,
}}>
<GestureOverlay isActive>
<DocumentView
@@ -292,7 +286,7 @@ export class LightboxView extends ObservableReactComponent<LightboxViewProps> {
removeDocument={undefined}
whenChildContentsActiveChanged={emptyFunction}
addDocTab={this.AddDocTab}
- pinToPres={TabDocView.PinDoc}
+ pinToPres={DocumentView.PinDoc}
focus={emptyFunction}
/>
</GestureOverlay>
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index 01f3b032e..b6dfed687 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -8,14 +8,17 @@ import * as React from 'react';
import * as ReactDOM from 'react-dom/client';
import { AssignAllExtensions } from '../../extensions/Extensions';
import { FieldLoader } from '../../fields/FieldLoader';
+import { BranchingTrailManager } from '../util/BranchingTrailManager';
import { CurrentUserUtils } from '../util/CurrentUserUtils';
import { PingManager } from '../util/PingManager';
import { ReplayMovements } from '../util/ReplayMovements';
import { TrackMovements } from '../util/TrackMovements';
+import { KeyManager } from './GlobalKeyHandler';
+import { MainView } from './MainView';
import { CollectionView } from './collections/CollectionView';
+import { CollectionFreeFormInfoUI } from './collections/collectionFreeForm/CollectionFreeFormInfoUI';
import './global/globalScripts';
-import { MainView } from './MainView';
-import { BranchingTrailManager } from '../util/BranchingTrailManager';
+import { LinkFollower } from '../util/LinkFollower';
dotenv.config();
@@ -58,6 +61,11 @@ FieldLoader.ServerLoadStatus = { requested: 0, retrieved: 0, message: 'cache' };
new ReplayMovements();
new BranchingTrailManager({});
new PingManager();
+ new KeyManager();
+
+ // iniitialize plugin apis
+ CollectionFreeFormInfoUI.Init();
+ LinkFollower.Init();
root.render(<MainView />);
}, 0);
})();
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index aec553baa..2c7d3d32a 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -12,7 +12,8 @@ import '../../../node_modules/browndash-components/dist/styles/global.min.css';
import { ClientUtils, lightOrDark, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, returnZero, setupMoveUpEvents } from '../../ClientUtils';
import { emptyFunction } from '../../Utils';
import { Doc, DocListCast, GetDocFromUrl, Opt } from '../../fields/Doc';
-import { DocData } from '../../fields/DocSymbols';
+import { DocData, DocViews } from '../../fields/DocSymbols';
+import { Id } from '../../fields/FieldSymbols';
import { DocCast, StrCast, toList } from '../../fields/Types';
import { DocServer } from '../DocServer';
import { GoogleAuthenticationManager } from '../apis/GoogleAuthenticationManager';
@@ -29,7 +30,6 @@ import { Hypothesis } from '../util/HypothesisUtils';
import { UPDATE_SERVER_CACHE } from '../util/LinkManager';
import { RTFMarkup } from '../util/RTFMarkup';
import { ScriptingGlobals } from '../util/ScriptingGlobals';
-import { SelectionManager } from '../util/SelectionManager';
import { ServerStats } from '../util/ServerStats';
import { SettingsManager } from '../util/SettingsManager';
import { SharingManager } from '../util/SharingManager';
@@ -42,7 +42,6 @@ import { DashboardView } from './DashboardView';
import { DictationOverlay } from './DictationOverlay';
import { DocumentDecorations } from './DocumentDecorations';
import { GestureOverlay } from './GestureOverlay';
-import { KeyManager } from './GlobalKeyHandler';
import { LightboxView } from './LightboxView';
import './MainView.scss';
import { ObservableReactComponent } from './ObservableReactComponent';
@@ -160,7 +159,7 @@ export class MainView extends ObservableReactComponent<{}> {
leftMenuHeight = () => this._dashUIHeight;
leftMenuFlyoutWidth = () => this._leftMenuFlyoutWidth;
leftMenuFlyoutHeight = () => this._dashUIHeight;
- propertiesWidth = () => Math.max(0, Math.min(this._dashUIWidth - 50, SettingsManager.Instance?.propertiesWidth || 0));
+ propertiesWidth = () => Math.max(0, Math.min(this._dashUIWidth - 50, SnappingManager.PropertiesWidth || 0));
propertiesHeight = () => this._dashUIHeight;
mainDocViewWidth = () => this._dashUIWidth - this.propertiesWidth() - this.leftMenuWidth() - this.leftMenuFlyoutWidth();
mainDocViewHeight = () => this._dashUIHeight - this.headerBarDocHeight();
@@ -169,7 +168,7 @@ export class MainView extends ObservableReactComponent<{}> {
// Utils.TraceConsoleLog();
reaction(
// when a multi-selection occurs, remove focus from all active elements to allow keyboad input to go only to global key manager to act upon selection
- () => SelectionManager.Views.slice(),
+ () => DocumentView.Selected().slice(),
views => views.length > 1 && (document.activeElement as any)?.blur !== undefined && (document.activeElement as any)!.blur()
);
const scriptTag = document.createElement('script');
@@ -231,37 +230,29 @@ export class MainView extends ObservableReactComponent<{}> {
tag.src = 'https://www.youtube.com/iframe_api';
const firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode!.insertBefore(tag, firstScriptTag);
- window.removeEventListener('keydown', KeyManager.Instance.handleModifiers, true);
- window.addEventListener('keydown', KeyManager.Instance.handleModifiers, true);
- window.removeEventListener('keyup', KeyManager.Instance.unhandleModifiers);
- window.addEventListener('keyup', KeyManager.Instance.unhandleModifiers);
- window.removeEventListener('keydown', KeyManager.Instance.handle);
- window.addEventListener('keydown', KeyManager.Instance.handle);
- window.removeEventListener('keyup', KeyManager.Instance.unhandle);
- window.addEventListener('keyup', KeyManager.Instance.unhandle);
- window.addEventListener('paste', KeyManager.Instance.paste as any);
document.addEventListener('dash', (e: any) => {
// event used by chrome plugin to tell Dash which document to focus on
const id = GetDocFromUrl(e.detail);
- DocServer.GetRefField(id).then(doc => (doc instanceof Doc ? DocumentManager.Instance.showDocument(doc, { willPan: false }) : null));
+ DocServer.GetRefField(id).then(doc => (doc instanceof Doc ? DocumentView.showDocument(doc, { willPan: false }) : null));
});
document.addEventListener('linkAnnotationToDash', Hypothesis.linkListener);
this.initEventListeners();
}
componentWillUnMount() {
- window.removeEventListener('keyup', KeyManager.Instance.unhandle);
- window.removeEventListener('keydown', KeyManager.Instance.handle);
- window.removeEventListener('pointerdown', this.globalPointerDown, true);
- window.removeEventListener('pointermove', this.globalPointerMove, true);
- window.removeEventListener('pointerup', this.globalPointerClick, true);
- window.removeEventListener('paste', KeyManager.Instance.paste as any);
- document.removeEventListener('linkAnnotationToDash', Hypothesis.linkListener);
+ // window.removeEventListener('keyup', KeyManager.Instance.unhandle);
+ // window.removeEventListener('keydown', KeyManager.Instance.handle);
+ // window.removeEventListener('pointerdown', this.globalPointerDown, true);
+ // window.removeEventListener('pointermove', this.globalPointerMove, true);
+ // window.removeEventListener('pointerup', this.globalPointerClick, true);
+ // window.removeEventListener('paste', KeyManager.Instance.paste as any);
+ // document.removeEventListener('linkAnnotationToDash', Hypothesis.linkListener);
}
constructor(props: any) {
super(props);
makeObservable(this);
+ CollectionDockingView.setTabJSXComponent(TabDocView);
DocumentViewInternal.addDocTabFunc = MainView.addDocTabFunc_impl;
MainView.Instance = this;
DashboardView._urlState = HistoryUtil.parseUrl(window.location) || ({} as any);
@@ -592,7 +583,7 @@ export class MainView extends ObservableReactComponent<{}> {
if (!e.cancelBubble) {
const pathstr = (e as any)?.path?.map((p: any) => p.classList?.toString()).join();
if (pathstr?.includes('libraryFlyout')) {
- SelectionManager.DeselectAll();
+ DocumentView.DeselectAll();
}
}
},
@@ -719,14 +710,14 @@ export class MainView extends ObservableReactComponent<{}> {
this,
e,
action(() => {
- SettingsManager.Instance.propertiesWidth = Math.max(0, this._dashUIWidth - e.clientX);
- return !SettingsManager.Instance.propertiesWidth;
+ SnappingManager.SetPropertiesWidth(Math.max(0, this._dashUIWidth - e.clientX));
+ return !SnappingManager.PropertiesWidth;
}),
action(() => {
- SettingsManager.Instance.propertiesWidth < 5 && (SettingsManager.Instance.propertiesWidth = 0);
+ SnappingManager.PropertiesWidth < 5 && SnappingManager.SetPropertiesWidth(0);
}),
action(() => {
- SettingsManager.Instance.propertiesWidth = this.propertiesWidth() < 15 ? Math.min(this._dashUIWidth - 50, 250) : 0;
+ SnappingManager.SetPropertiesWidth(this.propertiesWidth() < 15 ? Math.min(this._dashUIWidth - 50, 250) : 0);
}),
false
);
@@ -776,7 +767,7 @@ export class MainView extends ObservableReactComponent<{}> {
Document={this._sidebarContent.proto || this._sidebarContent}
addDocument={undefined}
addDocTab={DocumentViewInternal.addDocTabFunc}
- pinToPres={TabDocView.PinDoc}
+ pinToPres={DocumentView.PinDoc}
containerViewPath={returnEmptyDoclist}
styleProvider={this._sidebarContent.proto === Doc.MyDashboards || this._sidebarContent.proto === Doc.MyFilesystem || this._sidebarContent.proto === Doc.MyTrails ? DashboardStyleProvider : DefaultStyleProvider}
removeDocument={returnFalse}
@@ -799,7 +790,7 @@ export class MainView extends ObservableReactComponent<{}> {
@computed get leftMenuPanel() {
return (
- <div key="menu" className="mainView-leftMenuPanel" style={{ background: SettingsManager.userBackgroundColor, display: LightboxView.LightboxDoc ? 'none' : undefined }}>
+ <div key="menu" className="mainView-leftMenuPanel" style={{ background: SnappingManager.userBackgroundColor, display: LightboxView.LightboxDoc ? 'none' : undefined }}>
<DocumentView
Document={Doc.MyLeftSidebarMenu}
addDocument={undefined}
@@ -852,9 +843,9 @@ export class MainView extends ObservableReactComponent<{}> {
{this.flyout}
<div
className="mainView-libraryHandle"
- style={{ background: SettingsManager.userBackgroundColor, left: leftMenuFlyoutWidth - 10 /* ~half width of handle */, display: !this._leftMenuFlyoutWidth ? 'none' : undefined }}
+ style={{ background: SnappingManager.userBackgroundColor, left: leftMenuFlyoutWidth - 10 /* ~half width of handle */, display: !this._leftMenuFlyoutWidth ? 'none' : undefined }}
onPointerDown={this.onFlyoutPointerDown}>
- <FontAwesomeIcon icon="chevron-left" color={SettingsManager.userColor} style={{ opacity: '50%' }} size="sm" />
+ <FontAwesomeIcon icon="chevron-left" color={SnappingManager.userColor} style={{ opacity: '50%' }} size="sm" />
</div>
<div className="mainView-innerContainer" style={{ width: `calc(100% - ${width}px)` }}>
{this.dockingContent}
@@ -864,11 +855,11 @@ export class MainView extends ObservableReactComponent<{}> {
className={`mainView-propertiesDragger${this.propertiesWidth() < 10 ? '-minified' : ''}`}
key="props"
onPointerDown={this.onPropertiesPointerDown}
- style={{ background: SettingsManager.userVariantColor, right: this.propertiesWidth() - 1 }}>
- <FontAwesomeIcon icon={this.propertiesWidth() < 10 ? 'chevron-left' : 'chevron-right'} color={SettingsManager.userColor} size="sm" />
+ style={{ background: SnappingManager.userVariantColor, right: this.propertiesWidth() - 1 }}>
+ <FontAwesomeIcon icon={this.propertiesWidth() < 10 ? 'chevron-left' : 'chevron-right'} color={SnappingManager.userColor} size="sm" />
</div>
)}
- <div className="properties-container" style={{ width: this.propertiesWidth(), color: SettingsManager.userColor }}>
+ <div className="properties-container" style={{ width: this.propertiesWidth(), color: SnappingManager.userColor }}>
<div style={{ display: this.propertiesWidth() < 10 ? 'none' : undefined }}>
<PropertiesView styleProvider={DefaultStyleProvider} addDocTab={DocumentViewInternal.addDocTabFunc} width={this.propertiesWidth()} height={this.propertiesHeight()} />
</div>
@@ -911,11 +902,11 @@ export class MainView extends ObservableReactComponent<{}> {
// setTimeout(action(() => (this._leftMenuFlyoutWidth += 0.5)));
this._sidebarContent.proto = DocCast(button.target);
- SettingsManager.Instance.LastPressedBtn = button;
+ SnappingManager.SetLastPressedBtn(button[Id]);
});
closeFlyout = action(() => {
- SettingsManager.Instance.LastPressedBtn = undefined;
+ SnappingManager.SetLastPressedBtn('');
this._panelContent = 'none';
this._sidebarContent.proto = undefined;
this._leftMenuFlyoutWidth = 0;
@@ -933,7 +924,7 @@ export class MainView extends ObservableReactComponent<{}> {
@computed get docButtons() {
return !Doc.MyDockedBtns ? null : (
- <div className="mainView-docButtons" style={{ background: SettingsManager.userBackgroundColor, color: SettingsManager.userColor }} ref={this._docBtnRef}>
+ <div className="mainView-docButtons" style={{ background: SnappingManager.userBackgroundColor, color: SnappingManager.userColor }} ref={this._docBtnRef}>
<CollectionLinearView
Document={Doc.MyDockedBtns}
docViewPath={returnEmptyDocViewList}
@@ -964,8 +955,8 @@ export class MainView extends ObservableReactComponent<{}> {
);
}
@computed get snapLines() {
- const dragged = DragManager.docsBeingDragged.lastElement() ?? SelectionManager.Docs.lastElement();
- const dragPar = dragged ? CollectionFreeFormView.from(DocumentManager.Instance.getDocumentView(dragged)) : undefined;
+ const dragged = DragManager.docsBeingDragged.lastElement() ?? DocumentView.SelectedDocs().lastElement();
+ const dragPar = dragged ? CollectionFreeFormView.from(Array.from(dragged[DocViews]).lastElement()) : undefined;
return !dragPar?.layoutDoc.freeform_snapLines ? null : (
<div className="mainView-snapLines">
<svg style={{ width: '100%', height: '100%' }}>
@@ -1010,14 +1001,22 @@ export class MainView extends ObservableReactComponent<{}> {
);
}
+ togglePropertiesFlyout = () => {
+ if (MainView.Instance.propertiesWidth() > 0) {
+ SnappingManager.SetPropertiesWidth(0);
+ } else {
+ SnappingManager.SetPropertiesWidth(300);
+ }
+ };
+
lightboxMaxBorder = [200, 50];
render() {
return (
<div
className="mainView-container"
style={{
- color: SettingsManager.userColor,
- background: SettingsManager.userBackgroundColor,
+ color: SnappingManager.userColor,
+ background: SnappingManager.userBackgroundColor,
}}
onScroll={() =>
(ele => {
@@ -1067,7 +1066,7 @@ export class MainView extends ObservableReactComponent<{}> {
case 'dashboard':
default: return (<>
<div key="dashdiv" style={{ position: 'relative', display: this._hideUI || LightboxView.LightboxDoc ? 'none' : undefined, zIndex: 2001 }}>
- <CollectionMenu panelWidth={this.topMenuWidth} panelHeight={this.topMenuHeight} toggleTopBar={this.toggleTopBar} topBarHeight={this.headerBarHeightFunc}/>
+ <CollectionMenu panelWidth={this.topMenuWidth} panelHeight={this.topMenuHeight} togglePropertiesFlyout={this.togglePropertiesFlyout} toggleTopBar={this.toggleTopBar} topBarHeight={this.headerBarHeightFunc}/>
</div>
{this.mainDashboardArea}
</> );
@@ -1086,7 +1085,7 @@ export class MainView extends ObservableReactComponent<{}> {
{/* <InkTranscription /> */}
{this.snapLines}
<LightboxView key="lightbox" PanelWidth={this._windowWidth} PanelHeight={this._windowHeight} maxBorder={this.lightboxMaxBorder} />
- <OverlayView />
+ {LightboxView.LightboxDoc ? null : <OverlayView />}
<GPTPopup key="gptpopup" />
<SchemaCSVPopUp key="schemacsvpopup" />
<GenerativeFill imageEditorOpen={ImageEditor.Open} imageEditorSource={ImageEditor.Source} imageRootDoc={ImageEditor.RootDoc} addDoc={ImageEditor.AddDoc} />
diff --git a/src/client/views/MarqueeAnnotator.tsx b/src/client/views/MarqueeAnnotator.tsx
index 0f13de9e5..a917a7d57 100644
--- a/src/client/views/MarqueeAnnotator.tsx
+++ b/src/client/views/MarqueeAnnotator.tsx
@@ -227,7 +227,6 @@ export class MarqueeAnnotator extends ObservableReactComponent<MarqueeAnnotatorP
const linkDocData = dragEx.linkDocument[DocData];
linkDocData.link_relationship = 'cropped image';
linkDocData.title = 'crop: ' + this.props.Document.title;
- linkDocData.link_displayLine = false;
}
},
});
diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx
index e17da2680..a7907a565 100644
--- a/src/client/views/OverlayView.tsx
+++ b/src/client/views/OverlayView.tsx
@@ -13,7 +13,6 @@ import { DocumentType } from '../documents/DocumentTypes';
import { DragManager } from '../util/DragManager';
import { dropActionType } from '../util/DropActionTypes';
import { Transform } from '../util/Transform';
-import { LightboxView } from './LightboxView';
import { ObservableReactComponent } from './ObservableReactComponent';
import './OverlayView.scss';
import { DefaultStyleProvider } from './StyleProvider';
@@ -94,7 +93,7 @@ export class OverlayWindow extends ObservableReactComponent<OverlayWindowProps>
};
render() {
- return LightboxView.LightboxDoc ? null : (
+ return (
<div className="overlayWindow-outerDiv" style={{ transform: `translate(${this.x}px, ${this.y}px)`, width: this.width, height: this.height }}>
<div className="overlayWindow-titleBar" onPointerDown={this.onPointerDown}>
{this._props.overlayOptions.title || 'Untitled'}
@@ -181,7 +180,7 @@ export class OverlayView extends ObservableReactComponent<{}> {
docScreenToLocalXf = computedFn((doc: Doc) => () => new Transform(-NumCast(doc.overlayX), -NumCast(doc.overlayY), 1));
@computed get overlayDocs() {
- return Doc.MyOverlayDocs.filter(d => !LightboxView.LightboxDoc || d.type === DocumentType.PRES).map(d => {
+ return Doc.MyOverlayDocs.map(d => {
let [offsetx, offsety] = [0, 0];
const dref = React.createRef<HTMLDivElement>();
const onPointerMove = action((e: PointerEvent, down: number[]) => {
diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx
index cbbf48c75..edf6df2b9 100644
--- a/src/client/views/PropertiesButtons.tsx
+++ b/src/client/views/PropertiesButtons.tsx
@@ -20,11 +20,8 @@ import { DocData } from '../../fields/DocSymbols';
import { ScriptField } from '../../fields/ScriptField';
import { BoolCast, ScriptCast } from '../../fields/Types';
import { ImageField } from '../../fields/URLField';
-import { DocUtils } from '../documents/DocUtils';
+import { DocUtils, IsFollowLinkScript } from '../documents/DocUtils';
import { CollectionViewType, DocumentType } from '../documents/DocumentTypes';
-import { IsFollowLinkScript } from '../util/LinkFollower';
-import { LinkManager } from '../util/LinkManager';
-import { SelectionManager } from '../util/SelectionManager';
import { SettingsManager } from '../util/SettingsManager';
import { undoBatch, undoable } from '../util/UndoManager';
import { InkingStroke } from './InkingStroke';
@@ -40,13 +37,13 @@ export class PropertiesButtons extends React.Component<{}, {}> {
@observable public static Instance: PropertiesButtons;
@computed get selectedDoc() {
- return SelectionManager.SelectedSchemaDoc || SelectionManager.Views.lastElement()?.Document;
+ return DocumentView.SelectedSchemaDoc() || DocumentView.Selected().lastElement()?.Document;
}
@computed get selectedLayoutDoc() {
- return SelectionManager.SelectedSchemaDoc || SelectionManager.Views.lastElement()?.layoutDoc;
+ return DocumentView.SelectedSchemaDoc() || DocumentView.Selected().lastElement()?.layoutDoc;
}
@computed get selectedTabView() {
- return !SelectionManager.SelectedSchemaDoc && SelectionManager.Views.lastElement()?.topMost;
+ return !DocumentView.SelectedSchemaDoc() && DocumentView.Selected().lastElement()?.topMost;
}
@computed get titleButton() {
@@ -164,7 +161,7 @@ export class PropertiesButtons extends React.Component<{}, {}> {
// on => `${on ? 'Set' : 'Remove'} lightbox flag`,
// on => 'window-restore',
// onClick => {
- // SelectionManager.Views.forEach(dv => {
+ // DocumentView.Selected().forEach(dv => {
// const containerDoc = dv.Document;
// //containerDoc.followAllLinks =
// // containerDoc.noShadow =
@@ -320,14 +317,14 @@ export class PropertiesButtons extends React.Component<{}, {}> {
@undoBatch
handlePerspectiveChange = (e: any) => {
this.selectedDoc && (this.selectedDoc._type_collection = e.target.value);
- SelectionManager.Views.forEach(docView => {
+ DocumentView.Selected().forEach(docView => {
docView.layoutDoc._type_collection = e.target.value;
});
};
@computed get onClickVal() {
const linkButton = IsFollowLinkScript(this.selectedDoc.onClick);
const followLoc = this.selectedDoc._followLinkLocation;
- const linkedToLightboxView = () => LinkManager.Links(this.selectedDoc).some(link => LinkManager.getOppositeAnchor(link, this.selectedDoc)?._isLightbox);
+ const linkedToLightboxView = () => Doc.Links(this.selectedDoc).some(link => Doc.getOppositeAnchor(link, this.selectedDoc)?._isLightbox);
if (followLoc === OpenWhere.lightbox && !linkedToLightboxView()) return 'linkInPlace';
if (linkButton && followLoc === OpenWhere.addRight) return 'linkOnRight';
@@ -381,7 +378,7 @@ export class PropertiesButtons extends React.Component<{}, {}> {
@undoBatch
@action
handleOptionChange = (onClick: string) => {
- SelectionManager.Views.forEach(docView => {
+ DocumentView.Selected().forEach(docView => {
const linkButton = IsFollowLinkScript(docView.Document.onClick);
docView.noOnClick();
switch (onClick) {
@@ -417,7 +414,7 @@ export class PropertiesButtons extends React.Component<{}, {}> {
const click = () => this.handleOptionChange(value[0]);
const linkButton = IsFollowLinkScript(this.selectedDoc.onClick);
const followLoc = this.selectedDoc._followLinkLocation;
- const linkedToLightboxView = () => LinkManager.Links(this.selectedDoc).some(link => LinkManager.getOppositeAnchor(link, this.selectedDoc)?._isLightbox);
+ const linkedToLightboxView = () => Doc.Links(this.selectedDoc).some(link => Doc.getOppositeAnchor(link, this.selectedDoc)?._isLightbox);
let active = false;
// prettier-ignore
@@ -451,7 +448,7 @@ export class PropertiesButtons extends React.Component<{}, {}> {
}
@undoBatch
editOnClickScript = () => {
- if (SelectionManager.Views.length) SelectionManager.Views.forEach(dv => DocUtils.makeCustomViewClicked(dv.Document, undefined, 'onClick'));
+ if (DocumentView.Selected().length) DocumentView.Selected().forEach(dv => DocUtils.makeCustomViewClicked(dv.Document, undefined, 'onClick'));
else this.selectedDoc && DocUtils.makeCustomViewClicked(this.selectedDoc, undefined, 'onClick');
};
@@ -472,8 +469,8 @@ export class PropertiesButtons extends React.Component<{}, {}> {
fillWidth
toggleType={ToggleType.BUTTON}
onClick={undoable(() => {
- if (SelectionManager.Views.length > 1) {
- SelectionManager.Views.forEach(dv => (onClick ?? onPropToggle)(dv, dv.Document, property));
+ if (DocumentView.Selected().length > 1) {
+ DocumentView.Selected().forEach(dv => (onClick ?? onPropToggle)(dv, dv.Document, property));
} else if (targetDoc) (onClick ?? onPropToggle)(undefined, targetDoc, property);
}, property)}
/>
@@ -482,7 +479,7 @@ export class PropertiesButtons extends React.Component<{}, {}> {
render() {
const layoutField = this.selectedDoc?.[Doc.LayoutFieldKey(this.selectedDoc)];
- const isText = SelectionManager.Views.lastElement()?.ComponentView instanceof FormattedTextBox;
+ const isText = DocumentView.Selected().lastElement()?.ComponentView instanceof FormattedTextBox;
const isInk = this.selectedDoc?.layout_isSvg;
const isImage = layoutField instanceof ImageField;
const isMap = this.selectedDoc?.type === DocumentType.MAP;
diff --git a/src/client/views/PropertiesDocBacklinksSelector.tsx b/src/client/views/PropertiesDocBacklinksSelector.tsx
index a806995f2..edb55f341 100644
--- a/src/client/views/PropertiesDocBacklinksSelector.tsx
+++ b/src/client/views/PropertiesDocBacklinksSelector.tsx
@@ -7,12 +7,12 @@ import { Doc } from '../../fields/Doc';
import { Cast } from '../../fields/Types';
import { DocumentType } from '../documents/DocumentTypes';
import { LinkManager } from '../util/LinkManager';
-import { SelectionManager } from '../util/SelectionManager';
import { SettingsManager } from '../util/SettingsManager';
import './PropertiesDocBacklinksSelector.scss';
import { CollectionDockingView } from './collections/CollectionDockingView';
import { LinkMenu } from './linking/LinkMenu';
import { OpenWhere } from './nodes/OpenWhere';
+import { DocumentView } from './nodes/DocumentView';
type PropertiesDocBacklinksSelectorProps = {
Document: Doc;
@@ -25,7 +25,7 @@ type PropertiesDocBacklinksSelectorProps = {
export class PropertiesDocBacklinksSelector extends React.Component<PropertiesDocBacklinksSelectorProps> {
getOnClick = action((link: Doc) => {
const linkAnchor = this.props.Document;
- const other = LinkManager.getOppositeAnchor(link, linkAnchor);
+ const other = Doc.getOppositeAnchor(link, linkAnchor);
const otherdoc = !other ? undefined : other.annotationOn && other.type !== DocumentType.RTF ? Cast(other.annotationOn, Doc, null) : other;
LinkManager.Instance.currentLink = link;
if (otherdoc) {
@@ -36,10 +36,10 @@ export class PropertiesDocBacklinksSelector extends React.Component<PropertiesDo
});
render() {
- return !SelectionManager.Views.length ? null : (
+ return !DocumentView.Selected().length ? null : (
<div className="propertiesDocBacklinksSelector" style={{ color: SettingsManager.userColor, backgroundColor: SettingsManager.userBackgroundColor }}>
{this.props.hideTitle ? null : <p key="contexts">Contexts:</p>}
- <LinkMenu docView={SelectionManager.Views.lastElement()} clearLinkEditor={undefined} itemHandler={this.getOnClick} style={{ left: 0, top: 0 }} />
+ <LinkMenu docView={DocumentView.Selected().lastElement()} clearLinkEditor={undefined} itemHandler={this.getOnClick} style={{ left: 0, top: 0 }} />
</div>
);
}
diff --git a/src/client/views/PropertiesDocContextSelector.tsx b/src/client/views/PropertiesDocContextSelector.tsx
index 722b1f90a..7465c727a 100644
--- a/src/client/views/PropertiesDocContextSelector.tsx
+++ b/src/client/views/PropertiesDocContextSelector.tsx
@@ -7,11 +7,10 @@ import * as React from 'react';
import { Doc } from '../../fields/Doc';
import { Id } from '../../fields/FieldSymbols';
import { Cast, StrCast } from '../../fields/Types';
-import { DocFocusOrOpen } from '../util/DocumentManager';
import { ObservableReactComponent } from './ObservableReactComponent';
import './PropertiesDocContextSelector.scss';
import { CollectionDockingView } from './collections/CollectionDockingView';
-import { DocumentView } from './nodes/DocumentView';
+import { DocFocusOrOpen, DocumentView } from './nodes/DocumentView';
import { OpenWhere } from './nodes/OpenWhere';
type PropertiesDocContextSelectorProps = {
diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx
index ff5dcd1b8..7c16e0ddb 100644
--- a/src/client/views/PropertiesView.tsx
+++ b/src/client/views/PropertiesView.tsx
@@ -23,10 +23,8 @@ import { ComputedField } from '../../fields/ScriptField';
import { Cast, DocCast, NumCast, StrCast } from '../../fields/Types';
import { GetEffectiveAcl, SharingPermissions, normalizeEmail } from '../../fields/util';
import { CollectionViewType, DocumentType } from '../documents/DocumentTypes';
-import { DocumentManager } from '../util/DocumentManager';
import { GroupManager } from '../util/GroupManager';
import { LinkManager } from '../util/LinkManager';
-import { SelectionManager } from '../util/SelectionManager';
import { SettingsManager } from '../util/SettingsManager';
import { SharingManager } from '../util/SharingManager';
import { Transform } from '../util/Transform';
@@ -40,7 +38,7 @@ import { PropertiesDocBacklinksSelector } from './PropertiesDocBacklinksSelector
import { PropertiesDocContextSelector } from './PropertiesDocContextSelector';
import { PropertiesSection } from './PropertiesSection';
import './PropertiesView.scss';
-import { DefaultStyleProvider } from './StyleProvider';
+import { DefaultStyleProvider, SetFilterOpener as SetPropertiesFilterOpener } from './StyleProvider';
import { DocumentView } from './nodes/DocumentView';
import { StyleProviderFuncType } from './nodes/FieldView';
import { KeyValueBox } from './nodes/KeyValueBox';
@@ -66,6 +64,12 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
super(props);
makeObservable(this);
PropertiesView.Instance = this;
+ SetPropertiesFilterOpener(
+ action(() => {
+ this.CloseAll();
+ this.openFilters = true;
+ })
+ );
}
@computed get MAX_EMBED_HEIGHT() {
@@ -73,7 +77,7 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
}
@computed get selectedDoc() {
- return SelectionManager.SelectedSchemaDoc || this.selectedDocumentView?.Document || Doc.ActiveDashboard;
+ return DocumentView.SelectedSchemaDoc() || this.selectedDocumentView?.Document || Doc.ActiveDashboard;
}
@computed get selectedLink() {
@@ -81,12 +85,10 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
}
@computed get selectedLayoutDoc() {
- return SelectionManager.SelectedSchemaDoc || this.selectedDocumentView?.layoutDoc || Doc.ActiveDashboard;
+ return DocumentView.SelectedSchemaDoc() || this.selectedDocumentView?.layoutDoc || Doc.ActiveDashboard;
}
@computed get selectedDocumentView() {
- if (SelectionManager.Views.length) return SelectionManager.Views[0];
- if (PresBox.Instance?.selectedArray.size) return DocumentManager.Instance.getDocumentView(PresBox.Instance.Document);
- return undefined;
+ return DocumentView.Selected().lastElement();
}
@computed get isPres(): boolean {
return this.selectedDoc?.type === DocumentType.PRES;
@@ -182,7 +184,10 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
const rows: JSX.Element[] = [];
if (this.dataDoc && this.selectedDoc) {
const ids = new Set<string>(reqdKeys);
- const docs: Doc[] = SelectionManager.Views.length < 2 ? [this.layoutFields ? Doc.Layout(this.selectedDoc) : this.dataDoc] : SelectionManager.Views.map(dv => (this.layoutFields ? dv.layoutDoc : dv.dataDoc));
+ const docs: Doc[] =
+ DocumentView.Selected().length < 2 //
+ ? [this.layoutFields ? Doc.Layout(this.selectedDoc) : this.dataDoc]
+ : DocumentView.Selected().map(dv => (this.layoutFields ? dv.layoutDoc : dv.dataDoc));
docs.forEach(doc =>
Object.keys(doc)
.filter(filter)
@@ -237,7 +242,12 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
@undoBatch
setKeyValue = (value: string) => {
- const docs = SelectionManager.Views.length < 2 && this.selectedDoc ? [this.layoutFields ? Doc.Layout(this.selectedDoc) : this.dataDoc!] : SelectionManager.Views.map(dv => (this.layoutFields ? dv.layoutDoc : dv.dataDoc));
+ const docs =
+ DocumentView.Selected().length < 2 && this.selectedDoc
+ ? [this.layoutFields
+ ? Doc.Layout(this.selectedDoc) //
+ : this.dataDoc!]
+ : DocumentView.Selected().map(dv => (this.layoutFields ? dv.layoutDoc : dv.dataDoc)); // prettier-ignore
docs.forEach(doc => {
if (value.indexOf(':') !== -1) {
const newVal = value[0].toUpperCase() + value.substring(1, value.length);
@@ -295,13 +305,13 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
const selAnchor = this.selectedDocumentView?.anchorViewDoc ?? LinkManager.Instance.currentLinkAnchor ?? this.selectedDoc;
let counter = 0;
- LinkManager.Links(selAnchor).forEach(() => counter++);
+ Doc.Links(selAnchor).forEach(() => counter++);
return counter;
}
@computed get layoutPreview() {
- if (SelectionManager.Views.length > 1) {
+ if (DocumentView.Selected().length > 1) {
return '-- multiple selected --';
}
if (this.selectedDoc) {
@@ -348,7 +358,7 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
*/
@undoBatch
changePermissions = (e: any, user: string) => {
- const docs = SelectionManager.Views.length < 2 ? [this.selectedDoc] : SelectionManager.Views.map(dv => (this.layoutDocAcls ? dv.layoutDoc : dv.dataDoc));
+ const docs = DocumentView.Selected().length < 2 ? [this.selectedDoc] : DocumentView.Selected().map(dv => (this.layoutDocAcls ? dv.layoutDoc : dv.dataDoc));
SharingManager.Instance.shareFromPropertiesSidebar(user, e.currentTarget.value as SharingPermissions, docs, this.layoutDocAcls);
};
@@ -462,7 +472,7 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
*/
@computed get sharingTable() {
// all selected docs
- const docs = SelectionManager.Views.length < 2 && this.selectedDoc ? [this.selectedDoc] : SelectionManager.Views.map(docView => docView.Document);
+ const docs = DocumentView.Selected().length < 2 && this.selectedDoc ? [this.selectedDoc] : DocumentView.SelectedDocs();
const target = docs[0];
const showAdmin = GetEffectiveAcl(target) === AclAdmin;
@@ -580,7 +590,7 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
@computed get editableTitle() {
const titles = new Set<string>();
- SelectionManager.Views.forEach(dv => titles.add(StrCast(dv.Document.title)));
+ DocumentView.Selected().forEach(dv => titles.add(StrCast(dv.Document.title)));
const title = Array.from(titles.keys()).length > 1 ? '--multiple selected--' : StrCast(this.selectedDoc?.title);
return (
<div>
@@ -631,8 +641,8 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
@undoBatch
setTitle = (value: string | number) => {
- if (SelectionManager.Views.length > 1) {
- SelectionManager.Views.map(dv => Doc.SetInPlace(dv.Document, 'title', value, true));
+ if (DocumentView.Selected().length > 1) {
+ DocumentView.Selected().map(dv => Doc.SetInPlace(dv.Document, 'title', value, true));
} else if (this.dataDoc) {
if (this.selectedDoc) Doc.SetInPlace(this.selectedDoc, 'title', value, true);
else KeyValueBox.SetField(this.dataDoc, 'title', value as string, true);
@@ -1365,14 +1375,14 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
@computed get destinationAnchor() {
const ldoc = this.selectedLink;
const lanch = this.selectedDocumentView?.anchorViewDoc ?? LinkManager.Instance.currentLinkAnchor;
- if (ldoc && lanch) return LinkManager.getOppositeAnchor(ldoc, lanch) ?? lanch;
+ if (ldoc && lanch) return Doc.getOppositeAnchor(ldoc, lanch) ?? lanch;
return ldoc ? DocCast(ldoc.link_anchor_2) : ldoc;
}
@computed get sourceAnchor() {
const selAnchor = this.selectedDocumentView?.anchorViewDoc ?? LinkManager.Instance.currentLinkAnchor;
- return selAnchor ?? (this.selectedLink && this.destinationAnchor ? LinkManager.getOppositeAnchor(this.selectedLink, this.destinationAnchor) : this.selectedLink);
+ return selAnchor ?? (this.selectedLink && this.destinationAnchor ? Doc.getOppositeAnchor(this.selectedLink, this.destinationAnchor) : this.selectedLink);
}
toggleAnchorProp = (e: React.PointerEvent, prop: string, anchor?: Doc, value: any = true, ovalue: any = false, cb: (val: any) => any = val => val) => {
@@ -1435,7 +1445,7 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
const zoom = Number((NumCast(this.sourceAnchor?.followLinkZoomScale, 1) * 100).toPrecision(3));
const targZoom = this.sourceAnchor?.followLinkZoom;
const indent = 30;
- const hasSelectedAnchor = this.selectedLink !== this.selectedDoc && LinkManager.Links(this.sourceAnchor).includes(this.selectedLink!);
+ const hasSelectedAnchor = this.selectedLink !== this.selectedDoc && Doc.Links(this.sourceAnchor).includes(this.selectedLink!);
return (
<>
diff --git a/src/client/views/ScriptBox.tsx b/src/client/views/ScriptBox.tsx
index 8de359e07..9c36e6d26 100644
--- a/src/client/views/ScriptBox.tsx
+++ b/src/client/views/ScriptBox.tsx
@@ -122,14 +122,14 @@ export class ScriptBox extends React.Component<ScriptBoxProps> {
if (!text) {
doc[DocData][fieldKey] = undefined;
} else {
- const script = CompileScript(text, {
+ const compScript = CompileScript(text, {
params: { this: Doc.name, ...contextParams },
typecheck: false,
editable: true,
transformer: DocumentIconContainer.getTransformer(),
});
- if (!script.compiled) {
- onError(script.errors.map(error => error.messageText).join('\n'));
+ if (!compScript.compiled) {
+ onError(compScript.errors.map(error => error.messageText).join('\n'));
return;
}
@@ -143,7 +143,7 @@ export class ScriptBox extends React.Component<ScriptBoxProps> {
div.innerHTML = 'button';
params.length && DragManager.StartButtonDrag([div], text, doc.title + '-instance', {}, params, () => {}, clientX, clientY);
- doc[DocData][fieldKey] = new ScriptField(script);
+ doc[DocData][fieldKey] = new ScriptField(compScript);
overlayDisposer();
}
}}
diff --git a/src/client/views/ScriptingRepl.tsx b/src/client/views/ScriptingRepl.tsx
index ba2e22b3b..1a2eb460f 100644
--- a/src/client/views/ScriptingRepl.tsx
+++ b/src/client/views/ScriptingRepl.tsx
@@ -5,15 +5,15 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { action, makeObservable, observable } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { DocumentManager } from '../util/DocumentManager';
import { CompileScript, Transformer, ts } from '../util/Scripting';
import { ScriptingGlobals } from '../util/ScriptingGlobals';
-import { SettingsManager } from '../util/SettingsManager';
+import { SnappingManager } from '../util/SnappingManager';
import { undoable } from '../util/UndoManager';
import { ObservableReactComponent } from './ObservableReactComponent';
import { OverlayView } from './OverlayView';
import './ScriptingRepl.scss';
import { DocumentIconContainer } from './nodes/DocumentIcon';
+import { DocumentView } from './nodes/DocumentView';
interface replValueProps {
scrollToBottom: () => void;
@@ -169,7 +169,7 @@ export class ScriptingRepl extends ObservableReactComponent<{}> {
case 'Enter': {
e.stopPropagation();
const docGlobals: { [name: string]: any } = {};
- DocumentManager.Instance.DocumentViews.forEach((dv, i) => {
+ DocumentView.allViews().forEach((dv, i) => {
docGlobals[`d${i}`] = dv.Document;
});
const globals = ScriptingGlobals.makeMutableGlobalsCopy(docGlobals);
@@ -262,13 +262,13 @@ export class ScriptingRepl extends ObservableReactComponent<{}> {
render() {
return (
<div className="scriptingRepl-outerContainer">
- <div className="scriptingRepl-commandsContainer" style={{ background: SettingsManager.userBackgroundColor }} ref={this.commandsRef}>
+ <div className="scriptingRepl-commandsContainer" style={{ background: SnappingManager.userBackgroundColor }} ref={this.commandsRef}>
{this.commands.map(({ command, result }, i) => (
- <div className="scriptingRepl-resultContainer" style={{ background: SettingsManager.userBackgroundColor }} key={i}>
- <div className="scriptingRepl-commandString" style={{ background: SettingsManager.userBackgroundColor }}>
+ <div className="scriptingRepl-resultContainer" style={{ background: SnappingManager.userBackgroundColor }} key={i}>
+ <div className="scriptingRepl-commandString" style={{ background: SnappingManager.userBackgroundColor }}>
{command || <br />}
</div>
- <div className="scriptingRepl-commandResult" style={{ background: SettingsManager.userBackgroundColor }}>
+ <div className="scriptingRepl-commandResult" style={{ background: SnappingManager.userBackgroundColor }}>
<ScriptingValueDisplay scrollToBottom={this.maybeScrollToBottom} value={result} />
</div>
</div>
@@ -276,7 +276,7 @@ export class ScriptingRepl extends ObservableReactComponent<{}> {
</div>
<input
className="scriptingRepl-commandInput"
- style={{ background: SettingsManager.userBackgroundColor }} //
+ style={{ background: SnappingManager.userBackgroundColor }} //
onFocus={this.onFocus}
onBlur={this.onBlur}
value={this.commandString}
diff --git a/src/client/views/SidebarAnnos.tsx b/src/client/views/SidebarAnnos.tsx
index 3648e613d..9b70f1ca7 100644
--- a/src/client/views/SidebarAnnos.tsx
+++ b/src/client/views/SidebarAnnos.tsx
@@ -14,12 +14,11 @@ import { DocCast, NumCast, StrCast } from '../../fields/Types';
import { CollectionViewType, DocumentType } from '../documents/DocumentTypes';
import { Docs } from '../documents/Documents';
import { DocUtils } from '../documents/DocUtils';
-import { LinkManager } from '../util/LinkManager';
import { SearchUtil } from '../util/SearchUtil';
import { Transform } from '../util/Transform';
import { ObservableReactComponent } from './ObservableReactComponent';
import './SidebarAnnos.scss';
-import { StyleProp } from './StyleProvider';
+import { StyleProp } from './StyleProp';
import { CollectionStackingView } from './collections/CollectionStackingView';
import { FieldViewProps } from './nodes/FieldView';
import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox';
@@ -87,7 +86,6 @@ export class SidebarAnnos extends ObservableReactComponent<FieldViewProps & Extr
Doc.SetSelectOnLoad(target);
FormattedTextBox.DontSelectInitialText = true;
const link = DocUtils.MakeLink(anchor, target, { link_relationship: 'inline comment:comment on' });
- link && (link.link_displayLine = false);
const taggedContent = this.childFilters()
.filter(data => data.split(':')[0])
@@ -187,8 +185,8 @@ export class SidebarAnnos extends ObservableReactComponent<FieldViewProps & Extr
layout_showTitle = () => 'title';
setHeightCallback = (height: number) => this._props.setHeight?.(height + this.filtersHeight());
sortByLinkAnchorY = (a: Doc, b: Doc) => {
- const ay = LinkManager.Links(a).length && DocCast(LinkManager.Links(a)[0].link_anchor_1).y;
- const by = LinkManager.Links(b).length && DocCast(LinkManager.Links(b)[0].link_anchor_1).y;
+ const ay = Doc.Links(a).length && DocCast(Doc.Links(a)[0].link_anchor_1).y;
+ const by = Doc.Links(b).length && DocCast(Doc.Links(b)[0].link_anchor_1).y;
return NumCast(ay) - NumCast(by);
};
render() {
diff --git a/src/client/views/StyleProp.ts b/src/client/views/StyleProp.ts
new file mode 100644
index 000000000..dd5b98cfe
--- /dev/null
+++ b/src/client/views/StyleProp.ts
@@ -0,0 +1,24 @@
+export enum StyleProp {
+ TreeViewIcon = 'treeView_Icon',
+ TreeViewSortings = 'treeView_Sortings', // options for how to sort tree view items
+ DocContents = 'docContents', // when specified, the JSX returned will replace the normal rendering of the document view
+ Opacity = 'opacity', // opacity of the document view
+ BoxShadow = 'boxShadow', // box shadow - used for making collections standout and for showing clusters in free form views
+ BorderRounding = 'borderRounding', // border radius of the document view
+ Color = 'color', // foreground color of Document view items
+ BackgroundColor = 'backgroundColor', // background color of a document view
+ FillColor = 'fillColor', // fill color of an ink stroke or shape
+ WidgetColor = 'widgetColor', // color to display UI widgets on a document view -- used for the sidebar divider dragger on a text note
+ PointerEvents = 'pointerEvents', // pointer events for DocumentView -- inherits pointer events if not specified
+ Decorations = 'decorations', // additional decoration to display above a DocumentView -- currently only used to display a Lock for making things background
+ HeaderMargin = 'headerMargin', // margin at top of documentview, typically for displaying a title -- doc contents will start below that
+ ShowCaption = 'layout_showCaption',
+ TitleHeight = 'titleHeight', // Height of Title area
+ ShowTitle = 'layout_showTitle', // whether to display a title on a Document (optional :hover suffix)
+ BorderPath = 'customBorder', // border path for document view
+ FontColor = 'fontColor', // color o tet
+ FontSize = 'fontSize', // size of text font
+ FontFamily = 'fontFamily', // font family of text
+ FontWeight = 'fontWeight', // font weight of text
+ Highlighting = 'highlighting', // border highlighting
+}
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index 6d4f69e6e..3ecfc8ba3 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -13,53 +13,20 @@ import { FaFilter } from 'react-icons/fa';
import { ClientUtils, DashColor, lightOrDark } from '../../ClientUtils';
import { Doc, Opt, StrListCast } from '../../fields/Doc';
import { DocViews } from '../../fields/DocSymbols';
+import { Id } from '../../fields/FieldSymbols';
+import { ScriptField } from '../../fields/ScriptField';
import { BoolCast, Cast, DocCast, ImageCast, NumCast, ScriptCast, StrCast } from '../../fields/Types';
+import { AudioAnnoState } from '../../server/SharedMediaTypes';
import { CollectionViewType, DocumentType } from '../documents/DocumentTypes';
-import { DocFocusOrOpen, DocumentManager } from '../util/DocumentManager';
-import { IsFollowLinkScript } from '../util/LinkFollower';
-import { LinkManager } from '../util/LinkManager';
-import { SettingsManager } from '../util/SettingsManager';
+import { IsFollowLinkScript } from '../documents/DocUtils';
import { SnappingManager } from '../util/SnappingManager';
import { undoBatch, UndoManager } from '../util/UndoManager';
-import { CollectionSchemaView } from './collections/collectionSchema/CollectionSchemaView';
import { TreeSort } from './collections/TreeSort';
import { Colors } from './global/globalEnums';
-import { DocumentViewProps } from './nodes/DocumentView';
+import { DocFocusOrOpen, DocumentView, DocumentViewProps } from './nodes/DocumentView';
import { FieldViewProps } from './nodes/FieldView';
-import { KeyValueBox } from './nodes/KeyValueBox';
-import { PropertiesView } from './PropertiesView';
+import { StyleProp } from './StyleProp';
import './StyleProvider.scss';
-import { ScriptField } from '../../fields/ScriptField';
-
-export enum StyleProp {
- TreeViewIcon = 'treeView_Icon',
- TreeViewSortings = 'treeView_Sortings', // options for how to sort tree view items
- DocContents = 'docContents', // when specified, the JSX returned will replace the normal rendering of the document view
- Opacity = 'opacity', // opacity of the document view
- BoxShadow = 'boxShadow', // box shadow - used for making collections standout and for showing clusters in free form views
- BorderRounding = 'borderRounding', // border radius of the document view
- Color = 'color', // foreground color of Document view items
- BackgroundColor = 'backgroundColor', // background color of a document view
- FillColor = 'fillColor', // fill color of an ink stroke or shape
- WidgetColor = 'widgetColor', // color to display UI widgets on a document view -- used for the sidebar divider dragger on a text note
- PointerEvents = 'pointerEvents', // pointer events for DocumentView -- inherits pointer events if not specified
- Decorations = 'decorations', // additional decoration to display above a DocumentView -- currently only used to display a Lock for making things background
- HeaderMargin = 'headerMargin', // margin at top of documentview, typically for displaying a title -- doc contents will start below that
- ShowCaption = 'layout_showCaption',
- TitleHeight = 'titleHeight', // Height of Title area
- ShowTitle = 'layout_showTitle', // whether to display a title on a Document (optional :hover suffix)
- BorderPath = 'customBorder', // border path for document view
- FontColor = 'fontColor', // color o tet
- FontSize = 'fontSize', // size of text font
- FontFamily = 'fontFamily', // font family of text
- FontWeight = 'fontWeight', // font weight of text
- Highlighting = 'highlighting', // border highlighting
-}
-
-export enum AudioAnnoState {
- stopped = 'stopped',
- playing = 'playing',
-}
function toggleLockedPosition(doc: Doc) {
UndoManager.RunInBatch(() => Doc.toggleLockedPosition(doc), 'toggleBackground');
@@ -80,7 +47,7 @@ export function styleFromLayoutString(doc: Doc, props: FieldViewProps, scale: nu
const divKeys = ['width', 'height', 'fontSize', 'transform', 'left', 'backgroundColor', 'left', 'right', 'top', 'bottom', 'pointerEvents', 'position'];
const replacer = (match: any, expr: string) =>
// bcz: this executes a script to convert a property expression string: { script } into a value
- ScriptField.MakeFunction(expr, { self: Doc.name, this: Doc.name, scale: 'number' })?.script.run({ this: doc, self: doc, scale }).result?.toString() ?? '';
+ ScriptField.MakeFunction(expr, { this: Doc.name, scale: 'number' })?.script.run({ this: doc, scale }).result?.toString() ?? '';
divKeys.forEach((prop: string) => {
const p = (props as any)[prop];
typeof p === 'string' && (style[prop] = p?.replace(/{([^.'][^}']+)}/g, replacer));
@@ -98,6 +65,11 @@ export function wavyBorderPath(pw: number, ph: number, inset: number = 0.05) {
} ${ph * inset}`;
}
+let _filterOpener: () => void;
+export function SetFilterOpener(func: () => void) {
+ _filterOpener = func;
+}
+
// a preliminary implementation of a dash style sheet for setting rendering properties of documents nested within a Tab
//
export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<FieldViewProps & DocumentViewProps>, property: string): any {
@@ -124,7 +96,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<FieldViewProps &
childFiltersByRanges,
renderDepth,
docViewPath,
- DocumentView,
+ DocumentView: docView,
LayoutTemplateString,
disableBrushing,
NativeDimScaling,
@@ -177,21 +149,20 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<FieldViewProps &
return undefined;
case StyleProp.DocContents: return undefined;
case StyleProp.WidgetColor: return isAnnotated ? Colors.LIGHT_BLUE : 'dimgrey';
- case StyleProp.Opacity: return LayoutTemplateString?.includes(KeyValueBox.name) ? 1 : Cast(doc?._opacity, "number", Cast(doc?.opacity, 'number', null));
+ case StyleProp.Opacity: return docView?.().ComponentView?.isUnstyledView?.() ? 1 : Cast(doc?._opacity, "number", Cast(doc?.opacity, 'number', null));
case StyleProp.FontColor: return StrCast(doc?.[fieldKey + 'fontColor'], StrCast(Doc.UserDoc().fontColor, color()));
case StyleProp.FontSize: return StrCast(doc?.[fieldKey + 'fontSize'], StrCast(Doc.UserDoc().fontSize));
case StyleProp.FontFamily: return StrCast(doc?.[fieldKey + 'fontFamily'], StrCast(Doc.UserDoc().fontFamily));
case StyleProp.FontWeight: return StrCast(doc?.[fieldKey + 'fontWeight'], StrCast(Doc.UserDoc().fontWeight));
case StyleProp.FillColor: return StrCast(doc?._fillColor, StrCast(doc?.fillColor, StrCast(doc?.backgroundColor, 'transparent')));
case StyleProp.ShowCaption: return hideCaptions || doc?._type_collection === CollectionViewType.Carousel ? undefined: StrCast(doc?._layout_showCaption);
- case StyleProp.TitleHeight: return Math.min(4,(DocumentView?.().screenToViewTransform().Scale ?? 1)) * NumCast(Doc.UserDoc().headerHeight,30);
+ case StyleProp.TitleHeight: return Math.min(4,(docView?.().screenToViewTransform().Scale ?? 1)) * NumCast(Doc.UserDoc().headerHeight,30);
case StyleProp.ShowTitle:
return (
(doc &&
- !(DocumentView?.().ComponentView instanceof CollectionSchemaView) &&
+ !docView?.().ComponentView?.isUnstyledView?.() &&
!LayoutTemplateString &&
!doc.presentation_targetDoc &&
- !LayoutTemplateString?.includes(KeyValueBox.name) &&
layout_showTitle?.() !== '' &&
StrCast(
doc._layout_showTitle,
@@ -205,9 +176,9 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<FieldViewProps &
''
);
case StyleProp.Color: {
- if (SettingsManager.Instance.LastPressedBtn === doc) return SettingsManager.userBackgroundColor;
- if (Doc.IsSystem(doc!)) return SettingsManager.userColor;
- if (doc?.type === DocumentType.FONTICON) return SettingsManager.userColor;
+ if (SnappingManager.LastPressedBtn === doc?.[Id]) return SnappingManager.userBackgroundColor;
+ if (Doc.IsSystem(doc!)) return SnappingManager.userColor;
+ if (doc?.type === DocumentType.FONTICON) return SnappingManager.userColor;
const docColor: Opt<string> = StrCast(doc?.[fieldKey + 'color'], StrCast(doc?._color));
if (docColor) return docColor;
const backColor = backgroundCol();
@@ -243,7 +214,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<FieldViewProps &
? titleHeight()
: 0;
case StyleProp.BackgroundColor: {
- if (SettingsManager.Instance.LastPressedBtn === doc) return SettingsManager.userColor; // hack to indicate active menu panel item
+ if (SnappingManager.LastPressedBtn === doc?.[Id]) return SnappingManager.userColor; // hack to indicate active menu panel item
const dataKey = doc ? Doc.LayoutFieldKey(doc) : "";
const usePath = StrCast(doc?.[dataKey + "_usePath"]);
const alternate = usePath.includes(":hover") ? ( doc?.isHovering ? '_' + usePath.replace(":hover","") : "") : usePath ? "_" +usePath:usePath;
@@ -268,7 +239,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<FieldViewProps &
case DocumentType.VID: docColor = docColor || (Colors.LIGHT_GRAY); break;
case DocumentType.COL:
docColor = docColor || (doc && Doc.IsSystem(doc)
- ? SettingsManager.userBackgroundColor
+ ? SnappingManager.userBackgroundColor
: doc?.annotationOn
? '#00000010' // faint interior for collections on PDFs, images, etc
: doc?.isGroup
@@ -288,7 +259,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<FieldViewProps &
case StyleProp.BoxShadow: {
if (!doc || opacity() === 0 || doc.noShadow) return undefined; // if it's not visible, then no shadow)
if (doc.layout_boxShadow === 'standard') return Shadows.STANDARD_SHADOW;
- if (IsFollowLinkScript(doc?.onClick) && LinkManager.Links(doc).length && !layoutDoc?.layout_isSvg) return StrCast(doc?._linkButtonShadow, 'lightblue 0em 0em 1em');
+ if (IsFollowLinkScript(doc?.onClick) && Doc.Links(doc).length && !layoutDoc?.layout_isSvg) return StrCast(doc?._linkButtonShadow, 'lightblue 0em 0em 1em');
switch (doc?.type) {
case DocumentType.COL:
return StrCast(
@@ -320,8 +291,8 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<FieldViewProps &
}
}
case StyleProp.PointerEvents:
- if (StrCast(doc?.pointerEvents) && !LayoutTemplateString?.includes(KeyValueBox.name)) return StrCast(doc!.pointerEvents); // honor pointerEvents field (set by lock button usually) if it's not a keyValue view of the Doc
- if (LayoutTemplateString?.includes(KeyValueBox.name)) return 'all';
+ if (docView?.().ComponentView?.dontRegisterView?.()) return 'all';
+ if (StrCast(doc?.pointerEvents)) return StrCast(doc!.pointerEvents); // honor pointerEvents field (set by lock button usually) if it's not a keyValue view of the Doc
if (SnappingManager.ExploreMode || doc?.layout_unrendered) return isInk() ? 'visiblePainted' : 'all';
if (pointerEvents?.() === 'none') return 'none';
if (opacity() === 0) return 'none';
@@ -336,12 +307,12 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<FieldViewProps &
</div>
);
const paint = () => !doc?.onPaint ? null : (
- <div className={`styleProvider-paint${DocumentView?.().IsSelected ? "-selected":""}`} onClick={e => togglePaintView(e, doc, props)}>
+ <div className={`styleProvider-paint${docView?.().IsSelected ? "-selected":""}`} onClick={e => togglePaintView(e, doc, props)}>
<FontAwesomeIcon icon='pen' size="lg" />
</div>
);
const filter = () => {
- const dashView = untracked(() => DocumentManager.Instance.getDocumentView(Doc.ActiveDashboard));
+ const dashView = untracked(() => DocumentView.getDocumentView(Doc.ActiveDashboard));
const showFilterIcon =
StrListCast(doc?._childFilters).length || StrListCast(doc?._childFiltersByRanges).length
? 'green' // #18c718bd' //'hasFilter'
@@ -357,17 +328,11 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<FieldViewProps &
// eslint-disable-next-line react/no-unstable-nested-components
iconProvider={() => <div className='styleProvider-filterShift'><FaFilter/></div>}
closeOnSelect
- setSelectedVal={
- action((dv) => {
- (dv as any).select(false);
- (SettingsManager.Instance.propertiesWidth = 250);
- setTimeout(action(() => {
- if (PropertiesView.Instance) {
- PropertiesView.Instance.CloseAll();
- PropertiesView.Instance.openFilters = true;
- }
- }));
- })
+ setSelectedVal={((dv: DocumentView) => {
+ dv.select(false);
+ SnappingManager.SetPropertiesWidth(250);
+ _filterOpener?.();
+ }) as any // Dropdown assumes values are strings or numbers..
}
size={Size.XSMALL}
width={15}
@@ -375,14 +340,14 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<FieldViewProps &
title={showFilterIcon === 'green' ?
"This view is filtered. Click to view/change filters":
"this view inherits filters from one of its parents"}
- color={SettingsManager.userColor}
+ color={SnappingManager.userColor}
background={showFilterIcon}
items={[ ...(dashView ? [dashView]: []), ...(docViewPath?.()??[])]
.filter(dv => StrListCast(dv?.Document.childFilters).length || StrListCast(dv?.Document.childRangeFilters).length)
.map(dv => ({
text: StrCast(dv?.Document.title),
val: dv as any,
- style: {color:SettingsManager.userColor, background:SettingsManager.userBackgroundColor},
+ style: {color:SnappingManager.userColor, background:SnappingManager.userBackgroundColor},
} as IListItemProps)) }
/>
</div>
@@ -395,7 +360,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<FieldViewProps &
const audioIconColors: { [key: string]: string } = { playing: 'green', stopped: 'blue' };
return (
<Tooltip title={<div>{StrListCast(doc[fieldKey + 'audioAnnotations_text']).lastElement()}</div>}>
- <div className="styleProvider-audio" onPointerDown={() => DocumentManager.Instance.getFirstDocumentView(doc)?.playAnnotation()}>
+ <div className="styleProvider-audio" onPointerDown={() => DocumentView.getFirstDocumentView(doc)?.playAnnotation()}>
<FontAwesomeIcon className="documentView-audioFont" style={{ color: audioIconColors[audioAnnoState(doc)] }} icon='file-audio' size="sm" />
</div>
</Tooltip>
@@ -415,7 +380,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<FieldViewProps &
}
export function DashboardToggleButton(doc: Doc, field: string, onIcon: IconProp, offIcon: IconProp, clickFunc?: () => void) {
- const color = SettingsManager.userColor;
+ const color = SnappingManager.userColor;
return (
<IconButton
size={Size.XSMALL}
diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx
index d8232c132..7617f2a52 100644
--- a/src/client/views/collections/CollectionCarousel3DView.tsx
+++ b/src/client/views/collections/CollectionCarousel3DView.tsx
@@ -11,8 +11,7 @@ import { Id } from '../../../fields/FieldSymbols';
import { DocCast, NumCast, ScriptCast, StrCast } from '../../../fields/Types';
import { DocumentType } from '../../documents/DocumentTypes';
import { DragManager } from '../../util/DragManager';
-import { SelectionManager } from '../../util/SelectionManager';
-import { StyleProp } from '../StyleProvider';
+import { StyleProp } from '../StyleProp';
import { DocumentView } from '../nodes/DocumentView';
import { FocusViewOptions } from '../nodes/FocusViewOptions';
import './CollectionCarousel3DView.scss';
@@ -101,7 +100,7 @@ export class CollectionCarousel3DView extends CollectionSubView() {
}
changeSlide = (direction: number) => {
- SelectionManager.DeselectAll();
+ DocumentView.DeselectAll();
this.layoutDoc._carousel_index = (NumCast(this.layoutDoc._carousel_index) + direction + this.carouselItems.length) % this.carouselItems.length;
};
diff --git a/src/client/views/collections/CollectionCarouselView.tsx b/src/client/views/collections/CollectionCarouselView.tsx
index fda320077..9d3657995 100644
--- a/src/client/views/collections/CollectionCarouselView.tsx
+++ b/src/client/views/collections/CollectionCarouselView.tsx
@@ -11,7 +11,7 @@ import { Doc, Opt } from '../../../fields/Doc';
import { DocCast, NumCast, ScriptCast, StrCast } from '../../../fields/Types';
import { DocumentType } from '../../documents/DocumentTypes';
import { DragManager } from '../../util/DragManager';
-import { StyleProp } from '../StyleProvider';
+import { StyleProp } from '../StyleProp';
import { DocumentView } from '../nodes/DocumentView';
import { FieldViewProps } from '../nodes/FieldView';
import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox';
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index b98aceb16..fc9e2e39b 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -16,27 +16,33 @@ import { DocServer } from '../../DocServer';
import { Docs } from '../../documents/Documents';
import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes';
import * as GoldenLayout from '../../goldenLayout';
-import { DocumentManager } from '../../util/DocumentManager';
import { DragManager } from '../../util/DragManager';
import { InteractionUtils } from '../../util/InteractionUtils';
import { ScriptingGlobals } from '../../util/ScriptingGlobals';
-import { SelectionManager } from '../../util/SelectionManager';
import { SnappingManager } from '../../util/SnappingManager';
import { undoable, undoBatch, UndoManager } from '../../util/UndoManager';
import { DashboardView } from '../DashboardView';
import { LightboxView } from '../LightboxView';
+import { DocumentView } from '../nodes/DocumentView';
import { OpenWhere, OpenWhereMod } from '../nodes/OpenWhere';
import { OverlayView } from '../OverlayView';
import { ScriptingRepl } from '../ScriptingRepl';
import { UndoStack } from '../UndoStack';
import './CollectionDockingView.scss';
import { CollectionSubView } from './CollectionSubView';
-import { TabDocView } from './TabDocView';
const _global = (window /* browser */ || global) /* node */ as any;
@observer
export class CollectionDockingView extends CollectionSubView() {
+ static tabClass: JSX.Element | null = null;
+ /**
+ * Configure golden layout to render its documents using the specified React component
+ * @param ele - typically would be set to TabDocView
+ */
+ static setTabJSXComponent(ele: any) {
+ this.tabClass = ele;
+ }
// eslint-disable-next-line no-use-before-define
@observable public static Instance: CollectionDockingView | undefined = undefined;
@@ -295,7 +301,7 @@ export class CollectionDockingView extends CollectionSubView() {
glay.on('tabCreated', this.tabCreated);
glay.on('tabDestroyed', this.tabDestroyed);
glay.on('stackCreated', this.stackCreated);
- glay.registerComponent('DocumentFrameRenderer', TabDocView);
+ glay.registerComponent('DocumentFrameRenderer', CollectionDockingView.tabClass);
glay.container = this._containerRef.current;
glay.init();
glay.root.layoutManager.on('itemDropped', this.tabItemDropped);
@@ -431,8 +437,8 @@ export class CollectionDockingView extends CollectionSubView() {
} else {
const tabTarget = (e.target as HTMLElement)?.parentElement?.className.includes('lm_tab') ? (e.target as HTMLElement).parentElement : (e.target as HTMLElement);
const map = Array.from(this.tabMap).find(tab => tab.element[0] === tabTarget);
- if (map?.DashDoc && DocumentManager.Instance.getFirstDocumentView(map.DashDoc)) {
- SelectionManager.SelectView(DocumentManager.Instance.getFirstDocumentView(map.DashDoc), false);
+ if (map?.DashDoc && DocumentView.getFirstDocumentView(map.DashDoc)) {
+ DocumentView.SelectView(DocumentView.getFirstDocumentView(map.DashDoc), false);
}
}
}
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index f945a7aa4..e53071584 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -21,13 +21,11 @@ import { BoolCast, Cast, DocCast, NumCast, StrCast } from '../../../fields/Types
import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes';
import { DragManager } from '../../util/DragManager';
import { dropActionType } from '../../util/DropActionTypes';
-import { SelectionManager } from '../../util/SelectionManager';
-import { SettingsManager } from '../../util/SettingsManager';
+import { SnappingManager } from '../../util/SnappingManager';
import { Transform } from '../../util/Transform';
import { undoBatch } from '../../util/UndoManager';
import { AntimodeMenu } from '../AntimodeMenu';
import { EditableView } from '../EditableView';
-import { MainView } from '../MainView';
import { DefaultStyleProvider } from '../StyleProvider';
import { DocumentView, DocumentViewInternal, returnEmptyDocViewList } from '../nodes/DocumentView';
import './CollectionMenu.scss';
@@ -38,6 +36,7 @@ interface CollectionMenuProps {
panelWidth: () => number;
toggleTopBar: () => void;
topBarHeight: () => number;
+ togglePropertiesFlyout: () => void;
}
@observer
@@ -59,7 +58,7 @@ export class CollectionMenu extends AntimodeMenu<CollectionMenuProps> {
componentDidMount() {
reaction(
- () => SelectionManager.Views.lastElement(),
+ () => DocumentView.Selected().lastElement(),
view => view && this.SetSelection(view)
);
}
@@ -77,15 +76,6 @@ export class CollectionMenu extends AntimodeMenu<CollectionMenuProps> {
}
};
- @action
- toggleProperties = () => {
- if (MainView.Instance.propertiesWidth() > 0) {
- SettingsManager.Instance.propertiesWidth = 0;
- } else {
- SettingsManager.Instance.propertiesWidth = 300;
- }
- };
-
buttonBarXf = () => {
if (!this._docBtnRef.current) return Transform.Identity();
const { scale, translateX, translateY } = ClientUtils.GetScreenTransform(this._docBtnRef.current);
@@ -128,15 +118,15 @@ export class CollectionMenu extends AntimodeMenu<CollectionMenuProps> {
render() {
const headerIcon = this.props.topBarHeight() > 0 ? 'angle-double-up' : 'angle-double-down';
const headerTitle = this.props.topBarHeight() > 0 ? 'Close Header Bar' : 'Open Header Bar';
- const propIcon = SettingsManager.Instance.propertiesWidth > 0 ? 'angle-double-right' : 'angle-double-left';
- const propTitle = SettingsManager.Instance.propertiesWidth > 0 ? 'Close Properties' : 'Open Properties';
+ const propIcon = SnappingManager.PropertiesWidth > 0 ? 'angle-double-right' : 'angle-double-left';
+ const propTitle = SnappingManager.PropertiesWidth > 0 ? 'Close Properties' : 'Open Properties';
const hardCodedButtons = (
<div className="hardCodedButtons">
<Toggle
toggleType={ToggleType.BUTTON}
type={Type.PRIM}
- color={SettingsManager.userColor}
+ color={SnappingManager.userColor}
onClick={this.props.toggleTopBar}
toggleStatus={this.props.topBarHeight() > 0}
icon={<FontAwesomeIcon icon={headerIcon} size="lg" />}
@@ -145,9 +135,9 @@ export class CollectionMenu extends AntimodeMenu<CollectionMenuProps> {
<Toggle
toggleType={ToggleType.BUTTON}
type={Type.PRIM}
- color={SettingsManager.userColor}
- onClick={this.toggleProperties}
- toggleStatus={SettingsManager.Instance.propertiesWidth > 0}
+ color={SnappingManager.userColor}
+ onClick={this._props.togglePropertiesFlyout}
+ toggleStatus={SnappingManager.PropertiesWidth > 0}
icon={<FontAwesomeIcon icon={propIcon} size="lg" />}
tooltip={propTitle}
/>
@@ -159,7 +149,7 @@ export class CollectionMenu extends AntimodeMenu<CollectionMenuProps> {
<div
className="collectionMenu-container"
style={{
- background: SettingsManager.userBackgroundColor,
+ background: SnappingManager.userBackgroundColor,
// borderColor: SettingsManager.userColor
}}>
{this.contMenuButtons}
@@ -245,7 +235,7 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewMenu
_viewCommand = {
params: ['target'],
title: 'bookmark view',
- script: "this.target._freeform_panX = self['target-freeform_panX']; this.target._freeform_panY = this['target-freeform_panY']; this.target._freeform_scale = this['target_freeform_scale']; gotoFrame(this.target, this['target-currentFrame']);",
+ script: "this.target._freeform_panX = this.target_freeform_panX; this.target._freeform_panY = this['target-freeform_panY']; this.target._freeform_scale = this['target_freeform_scale']; gotoFrame(this.target, this['target-currentFrame']);",
immediate: undoBatch(() => {
this.target._freeform_panX = 0;
this.target._freeform_panY = 0;
diff --git a/src/client/views/collections/CollectionNoteTakingView.tsx b/src/client/views/collections/CollectionNoteTakingView.tsx
index e940a1aef..3f9eed1d6 100644
--- a/src/client/views/collections/CollectionNoteTakingView.tsx
+++ b/src/client/views/collections/CollectionNoteTakingView.tsx
@@ -27,7 +27,7 @@ import { CollectionFreeFormDocumentView } from '../nodes/CollectionFreeFormDocum
import { DocumentView } from '../nodes/DocumentView';
import { FieldViewProps } from '../nodes/FieldView';
import { FocusViewOptions } from '../nodes/FocusViewOptions';
-import { StyleProp } from '../StyleProvider';
+import { StyleProp } from '../StyleProp';
import './CollectionNoteTakingView.scss';
import { CollectionNoteTakingViewColumn } from './CollectionNoteTakingViewColumn';
import { CollectionNoteTakingViewDivider } from './CollectionNoteTakingViewDivider';
diff --git a/src/client/views/collections/CollectionPileView.tsx b/src/client/views/collections/CollectionPileView.tsx
index e02570d3e..5b3f625db 100644
--- a/src/client/views/collections/CollectionPileView.tsx
+++ b/src/client/views/collections/CollectionPileView.tsx
@@ -10,13 +10,13 @@ import { NumCast, StrCast, toList } from '../../../fields/Types';
import { emptyFunction } from '../../../Utils';
import { DocUtils } from '../../documents/DocUtils';
import { dropActionType } from '../../util/DropActionTypes';
-import { SelectionManager } from '../../util/SelectionManager';
import { undoBatch, UndoManager } from '../../util/UndoManager';
import { OpenWhere } from '../nodes/OpenWhere';
import { computePassLayout, computeStarburstLayout } from './collectionFreeForm';
import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormView';
import './CollectionPileView.scss';
import { CollectionSubView } from './CollectionSubView';
+import { DocumentView } from '../nodes/DocumentView';
@observer
export class CollectionPileView extends CollectionSubView() {
@@ -150,7 +150,7 @@ export class CollectionPileView extends CollectionSubView() {
@undoBatch
onClick = (e: React.MouseEvent) => {
if (e.button === 0) {
- SelectionManager.DeselectAll();
+ DocumentView.DeselectAll();
this.toggleStarburst();
e.stopPropagation();
}
diff --git a/src/client/views/collections/CollectionStackedTimeline.tsx b/src/client/views/collections/CollectionStackedTimeline.tsx
index 48d24c910..f9b123bb6 100644
--- a/src/client/views/collections/CollectionStackedTimeline.tsx
+++ b/src/client/views/collections/CollectionStackedTimeline.tsx
@@ -19,11 +19,8 @@ import { ImageField } from '../../../fields/URLField';
import { emptyFunction, formatTime } from '../../../Utils';
import { Docs } from '../../documents/Documents';
import { DocumentType } from '../../documents/DocumentTypes';
-import { FollowLinkScript } from '../../documents/DocUtils';
-import { DocumentManager } from '../../util/DocumentManager';
+import { FollowLinkScript, IsFollowLinkScript } from '../../documents/DocUtils';
import { DragManager } from '../../util/DragManager';
-import { IsFollowLinkScript, LinkFollower } from '../../util/LinkFollower';
-import { LinkManager } from '../../util/LinkManager';
import { ScriptingGlobals } from '../../util/ScriptingGlobals';
import { SnappingManager } from '../../util/SnappingManager';
import { Transform } from '../../util/Transform';
@@ -87,7 +84,6 @@ export class CollectionStackedTimeline extends CollectionSubView<CollectionStack
private _timeline: HTMLDivElement | null = null; // ref to actual timeline div
private _timelineWrapper: HTMLDivElement | null = null; // ref to timeline wrapper div for zooming and scrolling
private _markerStart: number = 0;
- @observable public static CurrentlyPlaying: DocumentView[] = [];
@observable _selectingRegion = false;
@observable _markerEnd: number | undefined = undefined;
@observable _trimming: number = TrimScope.None;
@@ -182,7 +178,7 @@ export class CollectionStackedTimeline extends CollectionSubView<CollectionStack
getView = async (doc: Doc, options: FocusViewOptions): Promise<Opt<DocumentView>> =>
new Promise<Opt<DocumentView>>(res => {
if (doc.hidden) options.didMove = !(doc.hidden = false);
- const findDoc = (finish: (dv: DocumentView) => void) => DocumentManager.Instance.AddViewRenderedCb(doc, dv => finish(dv));
+ const findDoc = (finish: (dv: DocumentView) => void) => DocumentView.addViewRenderedCb(doc, dv => finish(dv));
findDoc(dv => res(dv));
});
@@ -296,7 +292,7 @@ export class CollectionStackedTimeline extends CollectionSubView<CollectionStack
}
if (!isClick && Math.abs(movement[0]) > 15 && !this.IsTrimming) {
const anchor = CollectionStackedTimeline.createAnchor(this.Document, this.dataDoc, this._props.fieldKey, this._markerStart, this._markerEnd, undefined, true);
- setTimeout(() => DocumentManager.Instance.getDocumentView(anchor)?.select(false));
+ setTimeout(() => DocumentView.getDocumentView(anchor)?.select(false));
}
(!isClick || !wasSelecting) && (this._markerEnd = undefined);
this._timelineWrapper && (this._timelineWrapper.style.cursor = '');
@@ -481,7 +477,7 @@ export class CollectionStackedTimeline extends CollectionSubView<CollectionStack
@action
clickAnchor = (anchorDoc: Doc, clientX: number) => {
if (IsFollowLinkScript(anchorDoc.onClick)) {
- LinkFollower.FollowLink(undefined, anchorDoc, false);
+ DocumentView.FollowLink(undefined, anchorDoc, false);
}
const seekTimeInSeconds = this.anchorStart(anchorDoc) - 0.05;
const endTime = this.anchorEnd(anchorDoc);
@@ -761,12 +757,12 @@ class StackedTimelineAnchor extends ObservableReactComponent<StackedTimelineAnch
// for now, we won't follow any links when the lightbox is oepn to avoid "losing" the video.
/* (isDictation || !Doc.AreProtosEqual(LightboxView.LightboxDoc, this._props.layoutDoc)) */
!this._props.layoutDoc.dontAutoFollowLinks &&
- LinkManager.Links(this._props.mark).length &&
+ Doc.Links(this._props.mark).length &&
time > NumCast(this._props.mark[this._props.startTag]) &&
time < NumCast(this._props.mark[this._props.endTag]) &&
this._lastTimecode < NumCast(this._props.mark[this._props.startTag]) - 1e-5
) {
- LinkFollower.FollowLink(undefined, this._props.mark, false);
+ DocumentView.FollowLink(undefined, this._props.mark, false);
}
this._lastTimecode = time;
}
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 8ae0f2832..3f12a281e 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -31,7 +31,7 @@ import { CollectionFreeFormDocumentView } from '../nodes/CollectionFreeFormDocum
import { DocumentView } from '../nodes/DocumentView';
import { FieldViewProps } from '../nodes/FieldView';
import { FocusViewOptions } from '../nodes/FocusViewOptions';
-import { StyleProp } from '../StyleProvider';
+import { StyleProp } from '../StyleProp';
import { CollectionMasonryViewFieldRow } from './CollectionMasonryViewFieldRow';
import './CollectionStackingView.scss';
import { CollectionStackingViewFieldColumn } from './CollectionStackingViewFieldColumn';
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 7c08aedb1..a4708bed5 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -21,12 +21,11 @@ import { Docs, DocumentOptions } from '../../documents/Documents';
import { DragManager } from '../../util/DragManager';
import { dropActionType } from '../../util/DropActionTypes';
import { ImageUtils } from '../../util/Import & Export/ImageUtils';
-import { SelectionManager } from '../../util/SelectionManager';
import { SnappingManager } from '../../util/SnappingManager';
import { UndoManager, undoBatch } from '../../util/UndoManager';
import { ViewBoxBaseComponent } from '../DocComponent';
import { FieldViewProps } from '../nodes/FieldView';
-import { LoadingBox } from '../nodes/LoadingBox';
+import { DocumentView } from '../nodes/DocumentView';
export interface CollectionViewProps extends React.PropsWithChildren<FieldViewProps> {
isAnnotationOverlay?: boolean; // is the collection an annotation overlay (eg an overlay on an image/video/etc)
@@ -377,7 +376,7 @@ export function CollectionSubView<X>() {
}
});
} else {
- const srcWeb = SelectionManager.Views.lastElement();
+ const srcWeb = DocumentView.Selected().lastElement();
const srcUrl = (srcWeb?.Document.data as WebField)?.url?.href?.match(/https?:\/\/[^/]*/)?.[0];
const reg = new RegExp(ClientUtils.prepend(''), 'g');
const modHtml = srcUrl ? html.replace(reg, srcUrl) : html;
@@ -386,7 +385,7 @@ export function CollectionSubView<X>() {
Doc.GetProto(htmlDoc)['data-text'] = Doc.GetProto(htmlDoc).text = text;
addDocument(htmlDoc);
if (srcWeb) {
- const iframe = SelectionManager.Views[0].ContentDiv?.getElementsByTagName('iframe')?.[0];
+ const iframe = DocumentView.Selected()[0].ContentDiv?.getElementsByTagName('iframe')?.[0];
const focusNode = iframe?.contentDocument?.getSelection()?.focusNode as any;
if (focusNode) {
const anchor = srcWeb?.ComponentView?.getAnchor?.(true);
@@ -496,13 +495,13 @@ export function CollectionSubView<X>() {
if (typeof files === 'string') {
const loading = Docs.Create.LoadingDocument(files, options);
generatedDocuments.push(loading);
- LoadingBox.addCurrentlyLoading(loading);
+ Doc.addCurrentlyLoading(loading);
DocUtils.uploadYoutubeVideoLoading(files, {}, loading);
} else {
generatedDocuments.push(
...files.map(file => {
const loading = Docs.Create.LoadingDocument(file, options);
- LoadingBox.addCurrentlyLoading(loading);
+ Doc.addCurrentlyLoading(loading);
DocUtils.uploadFileToDoc(file, {}, loading);
return loading;
})
diff --git a/src/client/views/collections/CollectionTimeView.tsx b/src/client/views/collections/CollectionTimeView.tsx
index b3760d4af..0369e4a2a 100644
--- a/src/client/views/collections/CollectionTimeView.tsx
+++ b/src/client/views/collections/CollectionTimeView.tsx
@@ -12,7 +12,6 @@ import { listSpec } from '../../../fields/Schema';
import { ComputedField, ScriptField } from '../../../fields/ScriptField';
import { Cast, NumCast, StrCast } from '../../../fields/Types';
import { Docs } from '../../documents/Documents';
-import { DocumentManager } from '../../util/DocumentManager';
import { ScriptingGlobals } from '../../util/ScriptingGlobals';
import { ContextMenu } from '../ContextMenu';
import { ContextMenuProps } from '../ContextMenuItem';
@@ -257,7 +256,7 @@ ScriptingGlobals.add(function pivotColumnClick(pivotDoc: Doc, bounds: ViewDefBou
action(() => {
const filterVals = bounds.payload as string[];
filterVals.map(filterVal => Doc.setDocFilter(pivotDoc, pivotField, filterVal, 'check'));
- const pivotView = DocumentManager.Instance.getDocumentView(pivotDoc);
+ const pivotView = DocumentView.getDocumentView(pivotDoc);
if (pivotDoc && pivotView?.ComponentView instanceof CollectionTimeView && filterVals.length === 1) {
if (pivotView?.ComponentView.childDocs.length && pivotView.ComponentView.childDocs[0][filterVals[0]]) {
// eslint-disable-next-line prefer-destructuring
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index d015e73ad..c1247f5b0 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -14,11 +14,9 @@ import { TraceMobx } from '../../../fields/util';
import { emptyFunction, Utils } from '../../../Utils';
import { Docs } from '../../documents/Documents';
import { DocUtils } from '../../documents/DocUtils';
-import { DocumentManager } from '../../util/DocumentManager';
import { DragManager } from '../../util/DragManager';
import { dropActionType } from '../../util/DropActionTypes';
import { ScriptingGlobals } from '../../util/ScriptingGlobals';
-import { SelectionManager } from '../../util/SelectionManager';
import { SnappingManager } from '../../util/SnappingManager';
import { Transform } from '../../util/Transform';
import { undoBatch, UndoManager } from '../../util/UndoManager';
@@ -27,10 +25,11 @@ import { ContextMenuProps } from '../ContextMenuItem';
import { EditableView } from '../EditableView';
import { DocumentView } from '../nodes/DocumentView';
import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox';
-import { StyleProp } from '../StyleProvider';
+import { StyleProp } from '../StyleProp';
import { CollectionFreeFormView } from './collectionFreeForm';
import { CollectionSubView } from './CollectionSubView';
import './CollectionTreeView.scss';
+import { TreeViewType } from './CollectionTreeViewType';
import { TreeView } from './TreeView';
const _global = (window /* browser */ || global) /* node */ as any;
@@ -49,12 +48,6 @@ export type collectionTreeViewProps = {
hierarchyIndex?: number[];
};
-export enum TreeViewType {
- outline = 'outline',
- fileSystem = 'fileSystem',
- default = 'default',
-}
-
@observer
export class CollectionTreeView extends CollectionSubView<Partial<collectionTreeViewProps>>() {
public static AddTreeFunc = 'addTreeFolder(this.embedContainer)';
@@ -183,7 +176,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
const targetDataDoc = this.Document[DocData];
const value = DocListCast(targetDataDoc[this._props.fieldKey]);
const result = value.filter(v => !docs.includes(v));
- if (docs.some(doc => SelectionManager.Views.some(dv => Doc.AreProtosEqual(dv.Document, doc)))) SelectionManager.DeselectAll();
+ if (docs.some(doc => DocumentView.Selected().some(dv => Doc.AreProtosEqual(dv.Document, doc)))) DocumentView.DeselectAll();
if (result.length !== value.length) {
if (docIn instanceof Doc) {
const ind = DocListCast(targetDataDoc[this._props.fieldKey]).indexOf(docIn);
@@ -191,7 +184,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
this._props.removeDocument?.(docIn);
if (ind > 0 && prev) {
Doc.SetSelectOnLoad(prev);
- DocumentManager.Instance.getDocumentView(prev, this.DocumentView?.())?.select(false);
+ DocumentView.getDocumentView(prev, this.DocumentView?.())?.select(false);
}
return true;
}
@@ -468,7 +461,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
minHeight: '100%',
}}
onWheel={e => e.stopPropagation()}
- onClick={() => (!this.layoutDoc.forceActive ? this._props.select(false) : SelectionManager.DeselectAll())}
+ onClick={() => (!this.layoutDoc.forceActive ? this._props.select(false) : DocumentView.DeselectAll())}
onDrop={this.onTreeDrop}>
<ul className={`no-indent${this.outlineMode ? '-outline' : ''}`}>{this.treeViewElements}</ul>
</div>
diff --git a/src/client/views/collections/CollectionTreeViewType.ts b/src/client/views/collections/CollectionTreeViewType.ts
new file mode 100644
index 000000000..53b88160e
--- /dev/null
+++ b/src/client/views/collections/CollectionTreeViewType.ts
@@ -0,0 +1,5 @@
+export enum TreeViewType {
+ outline = 'outline',
+ fileSystem = 'fileSystem',
+ default = 'default',
+}
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index 2d900bb73..2d8b2564d 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -9,7 +9,7 @@ import * as ReactDOM from 'react-dom/client';
import { ClientUtils, DashColor, lightOrDark, returnEmptyDoclist, returnFalse, returnTrue, setupMoveUpEvents, simulateMouseClick } from '../../../ClientUtils';
import { emptyFunction } from '../../../Utils';
import { Doc, Opt } from '../../../fields/Doc';
-import { DocData } from '../../../fields/DocSymbols';
+import { DocData, DocViews } from '../../../fields/DocSymbols';
import { Id } from '../../../fields/FieldSymbols';
import { List } from '../../../fields/List';
import { FieldId } from '../../../fields/RefField';
@@ -18,10 +18,8 @@ import { Cast, DocCast, NumCast, StrCast, toList } from '../../../fields/Types';
import { DocServer } from '../../DocServer';
import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes';
import { Docs } from '../../documents/Documents';
-import { DocumentManager } from '../../util/DocumentManager';
import { DragManager } from '../../util/DragManager';
import { dropActionType } from '../../util/DropActionTypes';
-import { SelectionManager } from '../../util/SelectionManager';
import { SnappingManager } from '../../util/SnappingManager';
import { Transform } from '../../util/Transform';
import { UndoManager, undoable } from '../../util/UndoManager';
@@ -29,7 +27,8 @@ import { DashboardView } from '../DashboardView';
import { LightboxView } from '../LightboxView';
import { ObservableReactComponent } from '../ObservableReactComponent';
import { PinDocView, PinProps } from '../PinFuncs';
-import { DefaultStyleProvider, StyleProp } from '../StyleProvider';
+import { StyleProp } from '../StyleProp';
+import { DefaultStyleProvider } from '../StyleProvider';
import { Colors } from '../global/globalEnums';
import { DocumentView, returnEmptyDocViewList } from '../nodes/DocumentView';
import { FieldViewProps } from '../nodes/FieldView';
@@ -194,9 +193,101 @@ export class TabDocView extends ObservableReactComponent<TabDocViewProps> {
_mainCont: HTMLDivElement | null = null;
_tabReaction: IReactionDisposer | undefined;
+ /**
+ * Adds a document to the presentation view
+ * */
+ @action
+ public static PinDoc(docIn: Doc | Doc[], pinProps: PinProps) {
+ const docs = toList(docIn);
+
+ const batch = UndoManager.StartBatch('Pin doc to pres trail');
+ const curPres = Doc.ActivePresentation ?? Doc.MakeCopy(Doc.UserDoc().emptyTrail as Doc, true);
+
+ if (!Doc.ActivePresentation) {
+ Doc.AddDocToList(Doc.MyTrails, 'data', curPres);
+ Doc.ActivePresentation = curPres;
+ }
+
+ docs.forEach(doc => {
+ // Edge Case 1: Cannot pin document to itself
+ if (doc === curPres) {
+ alert('Cannot pin presentation document to itself');
+ return;
+ }
+ const anchorDoc = DocumentView.getDocumentView(doc)?.ComponentView?.getAnchor?.(false, pinProps);
+ const pinDoc = anchorDoc?.type === DocumentType.CONFIG ? anchorDoc : Docs.Create.ConfigDocument({});
+ const targDoc = (pinDoc.presentation_targetDoc = anchorDoc ?? doc);
+ pinDoc.title = doc.title + ' - Slide';
+ pinDoc.data = targDoc.type === DocumentType.PRES ? ComputedField.MakeFunction('copyField(this.presentation_targetDoc.data') : new List<Doc>(); // the children of the embedding's layout are the presentation slide children. the embedding's data field might be children of a collection, PDF data, etc -- in any case we don't want the tree view to "see" this data
+ pinDoc.presentation_movement = doc.type === DocumentType.SCRIPTING || pinProps?.pinDocLayout ? PresMovement.None : PresMovement.Zoom;
+ pinDoc.presentation_duration = pinDoc.presentation_duration ?? 1000;
+ pinDoc.presentation_groupWithUp = false;
+ Doc.SetContainer(pinDoc, curPres);
+ // these should potentially all be props passed down by the CollectionTreeView to the TreeView elements. That way the PresBox could configure all of its children at render time
+ pinDoc.treeView = ''; // not really needed, but makes key value pane look better
+ pinDoc.treeView_RenderAsBulletHeader = true; // forces a tree view to render the document next to the bullet in the header area
+ pinDoc.treeView_HeaderWidth = '100%'; // forces the header to grow to be the same size as its largest sibling.
+ pinDoc.treeView_FieldKey = 'data'; // tree view will treat the 'data' field as the field where the hierarchical children are located instead of using the document's layout string field
+ pinDoc.treeView_ExpandedView = 'data'; // in case the data doc has an expandedView set, this will mask that field and use the 'data' field when expanding the tree view
+ pinDoc.treeView_HideHeaderIfTemplate = true; // this will force the document to render itself as the tree view header
+ const duration = NumCast(doc[`${Doc.LayoutFieldKey(pinDoc)}_duration`], null);
+
+ if (pinProps.pinViewport) PinDocView(pinDoc, pinProps, anchorDoc ?? doc);
+ if (!pinProps?.audioRange && duration !== undefined) {
+ pinDoc.presentation_mediaStart = 'manual';
+ pinDoc.presentation_mediaStop = 'manual';
+ }
+ if (pinProps?.activeFrame !== undefined) {
+ pinDoc.config_activeFrame = pinProps?.activeFrame;
+ pinDoc.title = doc.title + ' (move)';
+ pinDoc.presentation_movement = PresMovement.Pan;
+ }
+ if (pinProps?.currentFrame !== undefined) {
+ pinDoc.config_currentFrame = pinProps?.currentFrame;
+ pinDoc.title = doc.title + ' (move)';
+ pinDoc.presentation_movement = PresMovement.Pan;
+ }
+ if (pinDoc.stroke_isInkMask) {
+ pinDoc.presentation_hideAfter = true;
+ pinDoc.presentation_hideBefore = true;
+ pinDoc.presentation_movement = PresMovement.None;
+ }
+ if (curPres.expandBoolean) pinDoc.presentation_expandInlineButton = true;
+ Doc.AddDocToList(curPres, 'data', pinDoc, PresBox.Instance?.sortArray()?.lastElement());
+ PresBox.Instance?.clearSelectedArray();
+ pinDoc && PresBox.Instance?.addToSelectedArray(pinDoc); // Update selected array
+ });
+ if (
+ // open the presentation trail if it's not already opened
+ !Array.from(CollectionDockingView.Instance?.tabMap ?? [])
+ .map(d => d.DashDoc)
+ .includes(curPres)
+ ) {
+ if (Doc.IsInMyOverlay(curPres)) Doc.RemFromMyOverlay(curPres);
+ CollectionDockingView.AddSplit(curPres, OpenWhereMod.right);
+ setTimeout(() => DocumentView.showDocument(docs.lastElement(), { willPan: true }), 100); // keeps the pinned doc in view since the sidebar shifts things
+ }
+ setTimeout(batch.end, 500); // need to wait until dockingview (goldenlayout) updates all its structurs
+ }
+
+ static Activate = (tabDoc: Doc) => {
+ const tab = Array.from(CollectionDockingView.Instance?.tabMap!).find(findTab => findTab.DashDoc === tabDoc && !findTab.contentItem.config.props.keyValue);
+ tab?.header.parent.setActiveContentItem(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)
+ return tab !== undefined;
+ };
+ // static ActivateTabView(doc: Doc) {
+ // const tabView = Array.from(TabDocView._allTabs).find(view => view._document === doc);
+ // if (!tabView?._activated && tabView?._document) {
+ // TabDocView.Activate(tabView?._document);
+ // return tabView;
+ // }
+ // return undefined;
+ // }
constructor(props: any) {
super(props);
makeObservable(this);
+ DocumentView.activateTabView = TabDocView.Activate;
+ DocumentView.PinDoc = TabDocView.PinDoc;
}
@observable _activated: boolean = false;
@@ -205,8 +296,14 @@ export class TabDocView extends ObservableReactComponent<TabDocViewProps> {
@observable _hovering = false;
@observable _isActive: boolean = false;
@observable _isAnyChildContentActive = false;
+ public static IsSelected = (doc?: Doc) => {
+ if (Array.from(doc?.[DocViews] ?? []).some(dv => dv?.IsSelected)) {
+ return true;
+ }
+ return false;
+ };
@computed get _isUserActivated() {
- return SelectionManager.IsSelected(this._document) || this._isAnyChildContentActive;
+ return TabDocView.IsSelected(this._document) || this._isAnyChildContentActive;
}
get _isContentActive() {
return this._isUserActivated || this._hovering;
@@ -279,12 +376,12 @@ export class TabDocView extends ObservableReactComponent<TabDocViewProps> {
returnFalse,
action(clickEv => {
if (this.view) {
- SelectionManager.SelectView(this.view, false);
+ DocumentView.SelectView(this.view, false);
const child = getChild();
simulateMouseClick(child, clickEv.clientX, clickEv.clientY + 30, clickEv.screenX, clickEv.screenY + 30);
} else {
this._activated = true;
- setTimeout(() => this.view && SelectionManager.SelectView(this.view, false));
+ setTimeout(() => this.view && DocumentView.SelectView(this.view, false));
}
})
);
@@ -350,7 +447,7 @@ export class TabDocView extends ObservableReactComponent<TabDocViewProps> {
// select the tab document when the tab is directly clicked and activate the tab whenver the tab document is selected
titleEle.onpointerdown = action((e: any) => {
if (e.target.className !== 'lm_iconWrap') {
- if (this.view) SelectionManager.SelectView(this.view, false);
+ if (this.view) DocumentView.SelectView(this.view, false);
else this._activated = true;
if (Date.now() - titleEle.lastClick < 1000) titleEle.select();
titleEle.lastClick = Date.now();
@@ -358,7 +455,7 @@ export class TabDocView extends ObservableReactComponent<TabDocViewProps> {
}
});
tab._disposers.selectionDisposer = reaction(
- () => SelectionManager.IsSelected(this._document),
+ () => TabDocView.IsSelected(this._document),
action(selected => {
if (selected) this._activated = true;
if (selected && tab.contentItem !== tab.header.parent.getActiveContentItem()) {
@@ -382,89 +479,12 @@ export class TabDocView extends ObservableReactComponent<TabDocViewProps> {
.off('click') // unbind the current click handler
.click(() => {
Object.values(tab._disposers).forEach((disposer: any) => disposer?.());
- SelectionManager.DeselectAll();
+ DocumentView.DeselectAll();
UndoManager.RunInBatch(() => tab.contentItem.remove(), 'delete tab');
});
}
};
- /**
- * Adds a document to the presentation view
- * */
- @action
- public static PinDoc(docIn: Doc | Doc[], pinProps: PinProps) {
- const docs = toList(docIn);
-
- const batch = UndoManager.StartBatch('Pin doc to pres trail');
- const curPres = Doc.ActivePresentation ?? Doc.MakeCopy(Doc.UserDoc().emptyTrail as Doc, true);
-
- if (!Doc.ActivePresentation) {
- Doc.AddDocToList(Doc.MyTrails, 'data', curPres);
- Doc.ActivePresentation = curPres;
- }
-
- docs.forEach(doc => {
- // Edge Case 1: Cannot pin document to itself
- if (doc === curPres) {
- alert('Cannot pin presentation document to itself');
- return;
- }
- const anchorDoc = DocumentManager.Instance.getDocumentView(doc)?.ComponentView?.getAnchor?.(false, pinProps);
- const pinDoc = anchorDoc?.type === DocumentType.CONFIG ? anchorDoc : Docs.Create.ConfigDocument({});
- const targDoc = (pinDoc.presentation_targetDoc = anchorDoc ?? doc);
- pinDoc.title = doc.title + ' - Slide';
- pinDoc.data = targDoc.type === DocumentType.PRES ? ComputedField.MakeFunction('copyField(this.presentation_targetDoc.data') : new List<Doc>(); // the children of the embedding's layout are the presentation slide children. the embedding's data field might be children of a collection, PDF data, etc -- in any case we don't want the tree view to "see" this data
- pinDoc.presentation_movement = doc.type === DocumentType.SCRIPTING || pinProps?.pinDocLayout ? PresMovement.None : PresMovement.Zoom;
- pinDoc.presentation_duration = pinDoc.presentation_duration ?? 1000;
- pinDoc.presentation_groupWithUp = false;
- Doc.SetContainer(pinDoc, curPres);
- // these should potentially all be props passed down by the CollectionTreeView to the TreeView elements. That way the PresBox could configure all of its children at render time
- pinDoc.treeView = ''; // not really needed, but makes key value pane look better
- pinDoc.treeView_RenderAsBulletHeader = true; // forces a tree view to render the document next to the bullet in the header area
- pinDoc.treeView_HeaderWidth = '100%'; // forces the header to grow to be the same size as its largest sibling.
- pinDoc.treeView_FieldKey = 'data'; // tree view will treat the 'data' field as the field where the hierarchical children are located instead of using the document's layout string field
- pinDoc.treeView_ExpandedView = 'data'; // in case the data doc has an expandedView set, this will mask that field and use the 'data' field when expanding the tree view
- pinDoc.treeView_HideHeaderIfTemplate = true; // this will force the document to render itself as the tree view header
- const duration = NumCast(doc[`${Doc.LayoutFieldKey(pinDoc)}_duration`], null);
-
- if (pinProps.pinViewport) PinDocView(pinDoc, pinProps, anchorDoc ?? doc);
- if (!pinProps?.audioRange && duration !== undefined) {
- pinDoc.presentation_mediaStart = 'manual';
- pinDoc.presentation_mediaStop = 'manual';
- }
- if (pinProps?.activeFrame !== undefined) {
- pinDoc.config_activeFrame = pinProps?.activeFrame;
- pinDoc.title = doc.title + ' (move)';
- pinDoc.presentation_movement = PresMovement.Pan;
- }
- if (pinProps?.currentFrame !== undefined) {
- pinDoc.config_currentFrame = pinProps?.currentFrame;
- pinDoc.title = doc.title + ' (move)';
- pinDoc.presentation_movement = PresMovement.Pan;
- }
- if (pinDoc.stroke_isInkMask) {
- pinDoc.presentation_hideAfter = true;
- pinDoc.presentation_hideBefore = true;
- pinDoc.presentation_movement = PresMovement.None;
- }
- if (curPres.expandBoolean) pinDoc.presentation_expandInlineButton = true;
- Doc.AddDocToList(curPres, 'data', pinDoc, PresBox.Instance?.sortArray()?.lastElement());
- PresBox.Instance?.clearSelectedArray();
- pinDoc && PresBox.Instance?.addToSelectedArray(pinDoc); // Update selected array
- });
- if (
- // open the presentation trail if it's not already opened
- !Array.from(CollectionDockingView.Instance?.tabMap ?? [])
- .map(d => d.DashDoc)
- .includes(curPres)
- ) {
- if (Doc.IsInMyOverlay(curPres)) Doc.RemFromMyOverlay(curPres);
- CollectionDockingView.AddSplit(curPres, OpenWhereMod.right);
- setTimeout(() => DocumentManager.Instance.showDocument(docs.lastElement(), { willPan: true }), 100); // keeps the pinned doc in view since the sidebar shifts things
- }
- setTimeout(batch.end, 500); // need to wait until dockingview (goldenlayout) updates all its structurs
- }
-
componentDidMount() {
new _global.ResizeObserver(
action((entries: any) => {
@@ -484,12 +504,12 @@ export class TabDocView extends ObservableReactComponent<TabDocViewProps> {
}
componentDidUpdate(prevProps: Readonly<TabDocViewProps>) {
super.componentDidUpdate(prevProps);
- this._view && DocumentManager.Instance.AddView(this._view);
+ this._view && DocumentView.addView(this._view);
}
componentWillUnmount() {
this._tabReaction?.();
- this._view && DocumentManager.Instance.RemoveView(this._view);
+ this._view && DocumentView.removeView(this._view);
runInAction(() => TabDocView._allTabs.delete(this));
this._props.glContainer.layoutManager.off('activeContentItemChanged', this.onActiveContentItemChanged);
@@ -503,7 +523,7 @@ export class TabDocView extends ObservableReactComponent<TabDocViewProps> {
private onActiveContentItemChanged(contentItem: any) {
if (!contentItem || (this.stack === contentItem.parent && ((contentItem?.tab === this.tab && !this._isActive) || (contentItem?.tab !== this.tab && this._isActive)))) {
this._activated = this._isActive = !contentItem || contentItem?.tab === this.tab;
- if (!this._view && this.tab?.contentItem?.config?.props?.panelName !== TabDocView.DontSelectOnActivate) setTimeout(() => SelectionManager.SelectView(this._view, false));
+ if (!this._view && this.tab?.contentItem?.config?.props?.panelName !== TabDocView.DontSelectOnActivate) setTimeout(() => DocumentView.SelectView(this._view, false));
!this._isActive && this._document && Doc.UnBrushDoc(this._document); // bcz: bad -- trying to simulate a pointer leave event when a new tab is opened up on top of an existing one.
}
}
@@ -517,7 +537,7 @@ export class TabDocView extends ObservableReactComponent<TabDocViewProps> {
// lightbox - will add the document to any collection along the path from the document to the docking view that has a field isLightbox. if none is found, it adds to the full screen lightbox
addDocTab = (docsIn: Doc | Doc[], location: OpenWhere) => {
const docs = toList(docsIn);
- SelectionManager.DeselectAll();
+ DocumentView.DeselectAll();
const whereFields = location.split(':');
const keyValue = whereFields.includes(OpenWhereMod.keyvalue);
const whereMods = whereFields.length > 1 ? (whereFields[1] as OpenWhereMod) : OpenWhereMod.none;
@@ -527,7 +547,7 @@ export class TabDocView extends ObservableReactComponent<TabDocViewProps> {
switch (whereFields[0]) {
case undefined:
case OpenWhere.lightbox: if (this.layoutDoc?._isLightbox) {
- const lightboxView = !docs[0].annotationOn && DocCast(docs[0].embedContainer) ? DocumentManager.Instance.getFirstDocumentView(DocCast(docs[0].embedContainer)) : undefined;
+ const lightboxView = !docs[0].annotationOn && DocCast(docs[0].embedContainer) ? DocumentView.getFirstDocumentView(DocCast(docs[0].embedContainer)) : undefined;
const data = lightboxView?.dataDoc[Doc.LayoutFieldKey(lightboxView.Document)];
if (lightboxView && (!data || data instanceof List)) {
lightboxView.layoutDoc[Doc.LayoutFieldKey(lightboxView.Document)] = new List<Doc>(docs);
@@ -543,7 +563,7 @@ export class TabDocView extends ObservableReactComponent<TabDocViewProps> {
};
remDocTab = (doc: Doc | Doc[]) => {
if (doc === this._document) {
- SelectionManager.DeselectAll();
+ DocumentView.DeselectAll();
CollectionDockingView.CloseSplit(this._document);
return true;
}
@@ -551,11 +571,7 @@ export class TabDocView extends ObservableReactComponent<TabDocViewProps> {
};
getCurrentFrame = () => NumCast(Cast(PresBox.Instance.activeItem.presentation_targetDoc, Doc, null)._currentFrame);
- static Activate = (tabDoc: Doc) => {
- const tab = Array.from(CollectionDockingView.Instance?.tabMap!).find(findTab => findTab.DashDoc === tabDoc && !findTab.contentItem.config.props.keyValue);
- tab?.header.parent.setActiveContentItem(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)
- return tab !== undefined;
- };
+
@action
focusFunc = () => {
if (!this.tab.header.parent._activeContentItem || this.tab.header.parent._activeContentItem !== this.tab.contentItem) {
@@ -586,7 +602,7 @@ export class TabDocView extends ObservableReactComponent<TabDocViewProps> {
<DocumentView
key={this._document[Id]}
ref={action((r: DocumentView) => {
- this._lastView && DocumentManager.Instance.RemoveView(this._lastView);
+ this._lastView && DocumentView.removeView(this._lastView);
this._view = r;
this._lastView = this._view;
})}
@@ -635,7 +651,7 @@ export class TabDocView extends ObservableReactComponent<TabDocViewProps> {
this._mainCont = ref;
if (this._mainCont) {
if (this._lastTab) {
- this._view && DocumentManager.Instance.RemoveView(this._view);
+ this._view && DocumentView.removeView(this._view);
}
this._lastTab = this.tab;
(this._mainCont as any).InitTab = (tab: any) => this.init(tab, this._document);
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index 2f5af0564..969b98d91 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -21,24 +21,23 @@ import { TraceMobx } from '../../../fields/util';
import { DocUtils } from '../../documents/DocUtils';
import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes';
import { Docs } from '../../documents/Documents';
-import { DocumentManager } from '../../util/DocumentManager';
import { DragManager } from '../../util/DragManager';
import { dropActionType } from '../../util/DropActionTypes';
-import { LinkManager } from '../../util/LinkManager';
import { SettingsManager } from '../../util/SettingsManager';
import { SnappingManager } from '../../util/SnappingManager';
import { Transform } from '../../util/Transform';
import { UndoManager, undoBatch, undoable } from '../../util/UndoManager';
import { EditableView } from '../EditableView';
import { ObservableReactComponent } from '../ObservableReactComponent';
-import { StyleProp } from '../StyleProvider';
+import { StyleProp } from '../StyleProp';
import { DocumentView, DocumentViewInternal } from '../nodes/DocumentView';
import { FieldViewProps, StyleProviderFuncType } from '../nodes/FieldView';
import { KeyValueBox } from '../nodes/KeyValueBox';
import { OpenWhere } from '../nodes/OpenWhere';
import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox';
import { RichTextMenu } from '../nodes/formattedText/RichTextMenu';
-import { CollectionTreeView, TreeViewType } from './CollectionTreeView';
+import { CollectionTreeView } from './CollectionTreeView';
+import { TreeViewType } from './CollectionTreeViewType';
import { CollectionView } from './CollectionView';
import { TreeSort } from './TreeSort';
import './TreeView.scss';
@@ -208,7 +207,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
const ind = DocListCast(this.dataDoc[key]).indexOf(docs.lastElement());
const res = docs.reduce((flg, doc) => flg && Doc.RemoveDocFromList(this.dataDoc, key, doc), true);
- res && ind > 0 && DocumentManager.Instance.getDocumentView(DocListCast(this.dataDoc[key])[ind - 1], this.treeView.DocumentView?.())?.select(false);
+ res && ind > 0 && DocumentView.getDocumentView(DocListCast(this.dataDoc[key])[ind - 1], this.treeView.DocumentView?.())?.select(false);
return res;
};
@@ -379,7 +378,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
const bulletData = bullet[DocData];
bulletData.title = ComputedField.MakeFunction('this.text?.Text');
bulletData.data = new List<Doc>([]);
- DocumentManager.Instance.AddViewRenderedCb(bullet, dv => dv.ComponentView?.setFocus?.());
+ DocumentView.addViewRenderedCb(bullet, dv => dv.ComponentView?.setFocus?.());
return bullet;
}
@@ -823,7 +822,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
@computed get validExpandViewTypes() {
const annos = () => (DocListCast(this.Document[this.fieldKey + '_annotations']).length && !this.treeView.dashboardMode ? 'annotations' : '');
- const links = () => (LinkManager.Links(this.Document).length && !this.treeView.dashboardMode ? 'links' : '');
+ const links = () => (Doc.Links(this.Document).length && !this.treeView.dashboardMode ? 'links' : '');
const data = () => (this.childDocs || this.treeView.dashboardMode ? this.fieldKey : '');
const embeddings = () => (this.treeView.dashboardMode ? '' : 'embeddings');
const fields = () => (Doc.noviceMode ? '' : 'fields');
@@ -1210,7 +1209,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
className={`treeView-container${this._props.isContentActive() ? '-active' : ''}`}
ref={this.createTreeDropTarget}
onDrop={this.onTreeDrop}
- // onPointerDown={e => this._props.isContentActive(true) && SelectionManager.DeselectAll()} // bcz: this breaks entering a text filter in a filterBox since it deselects the filter's target document
+ // onPointerDown={e => this._props.isContentActive(true) && DocumentView.DeselectAll()} // bcz: this breaks entering a text filter in a filterBox since it deselects the filter's target document
// onKeyDown={this.onKeyDown}
>
<li className="collection-child">
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormClusters.ts b/src/client/views/collections/collectionFreeForm/CollectionFreeFormClusters.ts
index 6fc295e27..26a52cd2a 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormClusters.ts
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormClusters.ts
@@ -1,17 +1,16 @@
import { action, observable } from 'mobx';
+import { CollectionFreeFormView } from '.';
+import { intersectRect } from '../../../../Utils';
import { Doc, Opt } from '../../../../fields/Doc';
import { NumCast, StrCast } from '../../../../fields/Types';
-import { intersectRect } from '../../../../Utils';
import { DocumentType } from '../../../documents/DocumentTypes';
-import { DocumentManager } from '../../../util/DocumentManager';
import { DragManager } from '../../../util/DragManager';
import { dropActionType } from '../../../util/DropActionTypes';
-import { SelectionManager } from '../../../util/SelectionManager';
+import { StyleProp } from '../../StyleProp';
import { CollectionFreeFormDocumentView } from '../../nodes/CollectionFreeFormDocumentView';
+import { DocumentView } from '../../nodes/DocumentView';
import { FieldViewProps } from '../../nodes/FieldView';
-import { StyleProp } from '../../StyleProvider';
import './CollectionFreeFormView.scss';
-import { CollectionFreeFormView } from '.';
export class CollectionFreeFormClusters {
private _view: CollectionFreeFormView;
@@ -44,7 +43,7 @@ export class CollectionFreeFormClusters {
const h = NumCast(doc1Layout._height) + clusterDistance;
return doc1.z === doc2.z && intersectRect({ left: x, top: y, width: w, height: h }, { left: x2, top: y2, width: w2, height: h2 });
}
- pickCluster(probe: number[]) {
+ handlePointerDown(probe: number[]) {
this._hitCluster = this.childLayoutPairs
.map(pair => pair.layout)
.reduce((cluster, cd) => {
@@ -62,13 +61,13 @@ export class CollectionFreeFormClusters {
return this._hitCluster;
}
- tryDragCluster(e: PointerEvent) {
+ tryToDrag(e: PointerEvent) {
const cluster = this._hitCluster;
if (cluster !== -1) {
const ptsParent = e;
if (ptsParent) {
const eles = this.childLayoutPairs.map(pair => pair.layout).filter(cd => (this.Document._freeform_useClusters ? NumCast(cd.layout_cluster) : NumCast(cd.group, -1)) === cluster);
- const clusterDocs = eles.map(ele => DocumentManager.Instance.getDocumentView(ele, this.DocumentView)!);
+ const clusterDocs = eles.map(ele => DocumentView.getDocumentView(ele, this.DocumentView)!);
const { left, top } = clusterDocs[0].getBounds || { left: 0, top: 0 };
const de = new DragManager.DocumentDragData(eles, e.ctrlKey || e.altKey ? dropActionType.embed : undefined);
de.moveDocument = this.viewMoveDocument;
@@ -87,7 +86,7 @@ export class CollectionFreeFormClusters {
return false;
}
- initClusters() {
+ initLayout() {
if (this.Document._freeform_useClusters && !this._clusterSets.length && this.childDocs.length) {
return this.updateClusters(true);
}
@@ -97,11 +96,11 @@ export class CollectionFreeFormClusters {
updateClusters(useClusters: boolean) {
this.Document._freeform_useClusters = useClusters;
this._clusterSets.length = 0;
- this.childLayoutPairs.map(pair => pair.layout).map(c => this.updateCluster(c));
+ this.childLayoutPairs.map(pair => pair.layout).map(c => this.addDocument(c));
}
@action
- updateClusterDocs(docs: Doc[]) {
+ addDocuments(docs: Doc[]) {
const childLayouts = this.childLayoutPairs.map(pair => pair.layout);
if (this.Document._freeform_useClusters) {
const docFirst = docs[0];
@@ -143,12 +142,12 @@ export class CollectionFreeFormClusters {
this._clusterSets[(doc.layout_cluster = NumCast(docFirst.layout_cluster))].push(doc);
});
}
- childLayouts.map(child => !this._clusterSets.some((set, i) => Doc.IndexOf(child, set) !== -1 && child.layout_cluster === i) && this.updateCluster(child));
+ childLayouts.map(child => !this._clusterSets.some((set, i) => Doc.IndexOf(child, set) !== -1 && child.layout_cluster === i) && this.addDocument(child));
}
}
@action
- updateCluster = (doc: Doc) => {
+ addDocument = (doc: Doc) => {
const childLayouts = this.childLayoutPairs.map(pair => pair.layout);
if (this.Document._freeform_useClusters) {
this._clusterSets.forEach(set => Doc.IndexOf(doc, set) !== -1 && set.splice(Doc.IndexOf(doc, set), 1));
@@ -188,7 +187,7 @@ export class CollectionFreeFormClusters {
const cluster = NumCast(doc?.layout_cluster);
if (this.Document._freeform_useClusters && doc?.type !== DocumentType.IMG) {
if (this._clusterSets.length <= cluster) {
- setTimeout(() => doc && this.updateCluster(doc));
+ setTimeout(() => doc && this.addDocument(doc));
} else {
// choose a cluster color from a palette
const colors = ['#da42429e', '#31ea318c', 'rgba(197, 87, 20, 0.55)', '#4a7ae2c4', 'rgba(216, 9, 255, 0.5)', '#ff7601', '#1dffff', 'yellow', 'rgba(27, 130, 49, 0.55)', 'rgba(0, 0, 0, 0.268)'];
@@ -212,9 +211,9 @@ export class CollectionFreeFormClusters {
return styleProp;
};
- trySelectCluster = (addToSel: boolean) => {
+ tryToSelect = (addToSel: boolean) => {
if (addToSel && this._hitCluster !== -1) {
- !addToSel && SelectionManager.DeselectAll();
+ !addToSel && DocumentView.DeselectAll();
const eles = this.childLayoutPairs.map(pair => pair.layout).filter(cd => (this.Document._freeform_useClusters ? NumCast(cd.layout_cluster) : NumCast(cd.group, -1)) === this._hitCluster);
this.selectDocuments(eles);
return true;
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx
index 65a529d62..5d8373fc7 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx
@@ -4,13 +4,13 @@ import * as React from 'react';
import { Doc, DocListCast, FieldType, FieldResult } from '../../../../fields/Doc';
import { InkTool } from '../../../../fields/InkField';
import { StrCast } from '../../../../fields/Types';
-import { LinkManager } from '../../../util/LinkManager';
import { ObservableReactComponent } from '../../ObservableReactComponent';
import { DocButtonState, DocumentLinksButton } from '../../nodes/DocumentLinksButton';
import { TopBar } from '../../topbar/TopBar';
import { CollectionFreeFormInfoState, InfoState, StateEntryFunc, infoState } from './CollectionFreeFormInfoState';
import './CollectionFreeFormView.scss';
import { DocData } from '../../../../fields/DocSymbols';
+import { CollectionFreeFormView } from './CollectionFreeFormView';
export interface CollectionFreeFormInfoUIProps {
Document: Doc;
@@ -21,6 +21,12 @@ export interface CollectionFreeFormInfoUIProps {
@observer
export class CollectionFreeFormInfoUI extends ObservableReactComponent<CollectionFreeFormInfoUIProps> {
+ public static Init() {
+ CollectionFreeFormView.SetInfoUICreator((doc: Doc, layout: Doc, childDocs: () => Doc[], close: () => void) => (
+ //
+ <CollectionFreeFormInfoUI Document={doc} LayoutDoc={layout} childDocs={childDocs} close={close} />
+ ));
+ }
_firstDocPos = { x: 0, y: 0 };
constructor(props: any) {
@@ -63,7 +69,7 @@ export class CollectionFreeFormInfoUI extends ObservableReactComponent<Collectio
const linkStart = () => DocumentLinksButton.StartLink;
const linkUnstart = () => !DocumentLinksButton.StartLink;
- const numDocLinks = () => LinkManager.Instance.getAllDirectLinks(firstDoc())?.length;
+ const numDocLinks = () => Doc.Links(firstDoc())?.length;
const linkMenuOpen = () => DocButtonState.Instance.LinkEditorDocView;
const activeTool = () => Doc.ActiveTool;
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormPannableContents.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormPannableContents.tsx
index 90977d955..65a2fe0aa 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormPannableContents.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormPannableContents.tsx
@@ -3,9 +3,8 @@ import { observer } from 'mobx-react';
import * as React from 'react';
import { Doc } from '../../../../fields/Doc';
import { ScriptField } from '../../../../fields/ScriptField';
-import { PresBox } from '../../nodes/trails/PresBox';
-import './CollectionFreeFormView.scss';
import { ObservableReactComponent } from '../../ObservableReactComponent';
+import './CollectionFreeFormView.scss';
export interface CollectionFreeFormPannableContentsProps {
Document: Doc;
@@ -20,12 +19,16 @@ export interface CollectionFreeFormPannableContentsProps {
@observer
export class CollectionFreeFormPannableContents extends ObservableReactComponent<CollectionFreeFormPannableContentsProps> {
+ static _overlayPlugin: ((fform: Doc) => React.JSX.Element) | null = null;
+ public static SetOverlayPlugin(plugin: ((fform: Doc) => React.JSX.Element) | null) {
+ CollectionFreeFormPannableContents._overlayPlugin = plugin;
+ }
constructor(props: CollectionFreeFormPannableContentsProps) {
super(props);
makeObservable(this);
}
@computed get presPaths() {
- return this._props.showPresPaths() ? PresBox.Instance.pathLines(this._props.Document) : null;
+ return this._props.showPresPaths() ? CollectionFreeFormPannableContents._overlayPlugin?.(this._props.Document) : null;
}
// rectangle highlight used when following trail/link to a region of a collection that isn't a document
showViewport = (viewport: { panX: number; panY: number; width: number; height: number } | undefined) =>
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index f55d5a23f..6d901119e 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -26,15 +26,12 @@ import { aggregateBounds, emptyFunction, intersectRect, Utils } from '../../../.
import { Docs } from '../../../documents/Documents';
import { CollectionViewType, DocumentType } from '../../../documents/DocumentTypes';
import { DocUtils } from '../../../documents/DocUtils';
-import { DocumentManager } from '../../../util/DocumentManager';
import { DragManager } from '../../../util/DragManager';
import { dropActionType } from '../../../util/DropActionTypes';
import { ReplayMovements } from '../../../util/ReplayMovements';
import { CompileScript } from '../../../util/Scripting';
import { ScriptingGlobals } from '../../../util/ScriptingGlobals';
-import { SelectionManager } from '../../../util/SelectionManager';
-import { freeformScrollMode } from '../../../util/SettingsManager';
-import { SnappingManager } from '../../../util/SnappingManager';
+import { freeformScrollMode, SnappingManager } from '../../../util/SnappingManager';
import { Transform } from '../../../util/Transform';
import { undoable, undoBatch, UndoManager } from '../../../util/UndoManager';
import { Timeline } from '../../animationtimeline/Timeline';
@@ -50,12 +47,11 @@ import { FocusViewOptions } from '../../nodes/FocusViewOptions';
import { FormattedTextBox } from '../../nodes/formattedText/FormattedTextBox';
import { OpenWhere } from '../../nodes/OpenWhere';
import { PinDocView, PinProps } from '../../PinFuncs';
-import { StyleProp } from '../../StyleProvider';
+import { StyleProp } from '../../StyleProp';
import { CollectionSubView } from '../CollectionSubView';
-import { TreeViewType } from '../CollectionTreeView';
+import { TreeViewType } from '../CollectionTreeViewType';
import { CollectionFreeFormBackgroundGrid } from './CollectionFreeFormBackgroundGrid';
import { CollectionFreeFormClusters } from './CollectionFreeFormClusters';
-import { CollectionFreeFormInfoUI } from './CollectionFreeFormInfoUI';
import { computePassLayout, computePivotLayout, computeStarburstLayout, computeTimelineLayout, PoolData, ViewDefBounds, ViewDefResult } from './CollectionFreeFormLayoutEngines';
import { CollectionFreeFormPannableContents } from './CollectionFreeFormPannableContents';
import { CollectionFreeFormRemoteCursors } from './CollectionFreeFormRemoteCursors';
@@ -87,8 +83,9 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
} // this makes mobx trace() statements more descriptive
public unprocessedDocs: Doc[] = [];
public static collectionsWithUnprocessedInk = new Set<CollectionFreeFormView>();
- public static from(dv?: DocumentView) {
- return CollectionFreeFormDocumentView.from(dv)?.CollectionFreeFormView;
+ public static from(dv?: DocumentView): CollectionFreeFormView | undefined {
+ const parent = CollectionFreeFormDocumentView.from(dv)?._props.parent;
+ return parent instanceof CollectionFreeFormView ? parent : undefined;
}
_oldWheel: any;
@@ -227,25 +224,6 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
public static gotoKeyframe(timer: NodeJS.Timeout | undefined, docs: Doc[], duration: number) {
return DocumentView.SetViewTransition(docs, 'all', duration, timer, undefined, true);
}
- public static updateKeyframe(timer: NodeJS.Timeout | undefined, docs: Doc[], time: number) {
- const newTimer = DocumentView.SetViewTransition(docs, 'all', 1000, timer, undefined, true);
- const timecode = Math.round(time);
- docs.forEach(doc => {
- CollectionFreeFormDocumentView.animFields.forEach(val => {
- const findexed = Cast(doc[`${val.key}_indexed`], listSpec('number'), null);
- findexed?.length <= timecode + 1 && findexed.push(undefined as any as number);
- });
- CollectionFreeFormDocumentView.animStringFields.forEach(val => {
- const findexed = Cast(doc[`${val}_indexed`], listSpec('string'), null);
- findexed?.length <= timecode + 1 && findexed.push(undefined as any as string);
- });
- CollectionFreeFormDocumentView.animDataFields(doc).forEach(val => {
- const findexed = Cast(doc[`${val}_indexed`], listSpec(InkField), null);
- findexed?.length <= timecode + 1 && findexed.push(undefined as any);
- });
- });
- return newTimer;
- }
changeKeyFrame = (back = false) => {
const currentFrame = Cast(this.Document._currentFrame, 'number', null);
if (currentFrame === undefined) {
@@ -256,7 +234,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
this._keyTimer = CollectionFreeFormView.gotoKeyframe(this._keyTimer, [...this.childDocs, this.layoutDoc], 1000);
this.Document._currentFrame = Math.max(0, (currentFrame || 0) - 1);
} else {
- this._keyTimer = CollectionFreeFormView.updateKeyframe(this._keyTimer, [...this.childDocs, this.layoutDoc], currentFrame || 0);
+ this._keyTimer = CollectionFreeFormDocumentView.updateKeyframe(this._keyTimer, [...this.childDocs, this.layoutDoc], currentFrame || 0);
this.Document._currentFrame = Math.max(0, (currentFrame || 0) + 1);
this.Document.lastFrame = Math.max(NumCast(this.Document._currentFrame), NumCast(this.Document.lastFrame));
}
@@ -292,8 +270,8 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
this.addDocument(newDoc);
};
selectDocuments = (docs: Doc[]) => {
- SelectionManager.DeselectAll();
- docs.map(doc => DocumentManager.Instance.getDocumentView(doc, this.DocumentView?.())).forEach(dv => dv && SelectionManager.SelectView(dv, true));
+ DocumentView.DeselectAll();
+ docs.map(doc => DocumentView.getDocumentView(doc, this.DocumentView?.())).forEach(dv => dv && DocumentView.SelectView(dv, true));
};
addDocument = (newBox: Doc | Doc[]) => {
let retVal = false;
@@ -301,7 +279,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
retVal = this._props.addDocument?.(newBox) || false;
if (retVal) {
this.bringToFront(newBox);
- this._clusters.updateCluster(newBox);
+ this._clusters.addDocument(newBox);
}
} else {
retVal = this._props.addDocument?.(newBox) || false;
@@ -416,7 +394,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
res(this.DocumentView?.());
return;
}
- const findDoc = (finish: (dv: DocumentView) => void) => DocumentManager.Instance.AddViewRenderedCb(doc, dv => finish(dv));
+ const findDoc = (finish: (dv: DocumentView) => void) => DocumentView.addViewRenderedCb(doc, dv => finish(dv));
findDoc(dv => res(dv));
});
@@ -459,7 +437,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
!d._keepZWhenDragged && (d.zIndex = zsorted.length + 1 + i); // bringToFront
}
- (docDragData.droppedDocuments.length === 1 || de.shiftKey) && this._clusters.updateClusterDocs(docDragData.droppedDocuments);
+ (docDragData.droppedDocuments.length === 1 || de.shiftKey) && this._clusters.addDocuments(docDragData.droppedDocuments);
return true;
}
@@ -528,7 +506,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
break;
case InkTool.None:
if (!(this._props.layoutEngine?.() || StrCast(this.layoutDoc._layoutEngine))) {
- const hit = this._clusters.pickCluster(this.screenToFreeformContentsXf.transformPoint(e.clientX, e.clientY));
+ const hit = this._clusters.handlePointerDown(this.screenToFreeformContentsXf.transformPoint(e.clientX, e.clientY));
setupMoveUpEvents(this, e, this.onPointerMove, emptyFunction, emptyFunction, hit !== -1, false);
}
break;
@@ -654,7 +632,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
};
onPointerMove = (e: PointerEvent) => {
- if (this._clusters.tryDragCluster(e)) {
+ if (this._clusters.tryToDrag(e)) {
e.stopPropagation(); // we're moving a cluster, so stop propagation and return true to end panning and let the document drag take over
return true;
}
@@ -675,7 +653,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
const eraserMax = { X: Math.max(lastPoint.X, currPoint.X), Y: Math.max(lastPoint.Y, currPoint.Y) };
// prettier-ignore
return this.childDocs
- .map(doc => DocumentManager.Instance.getDocumentView(doc, this.DocumentView?.()))
+ .map(doc => DocumentView.getDocumentView(doc, this.DocumentView?.()))
.filter(inkView => inkView?.ComponentView instanceof InkingStroke)
.map(inkView => inkView!)
.map(inkView => ({ inkViewBounds: inkView.getBounds, inkStroke: inkView.ComponentView as InkingStroke, inkView }))
@@ -776,7 +754,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
this.childDocs
.filter(doc => doc.type === DocumentType.INK && !doc.dontIntersect)
.forEach(doc => {
- const otherInk = DocumentManager.Instance.getDocumentView(doc, this.DocumentView?.())?.ComponentView as InkingStroke;
+ const otherInk = DocumentView.getDocumentView(doc, this.DocumentView?.())?.ComponentView as InkingStroke;
const { inkData: otherInkData } = otherInk?.inkScaledData() ?? { inkData: [] };
const otherScreenPts = otherInkData.map(point => otherInk.ptToScreen(point));
const otherCtrlPts = otherScreenPts.map(spt => (ink.ComponentView as InkingStroke).ptFromScreen(spt));
@@ -1078,17 +1056,18 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
{...OmitKeys(entry, ['replica', 'pair']).omit}
key={childLayout[Id] + (entry.replica || '')}
Document={childLayout}
+ parent={this}
containerViewPath={this.DocumentView?.().docViewPath}
styleProvider={this._clusters.styleProvider}
TemplateDataDocument={childData}
dragStarting={this.dragStarting}
dragEnding={this.dragEnding}
+ isAnyChildContentActive={this.isAnyChildContentActive}
isGroupActive={this._props.isGroupActive}
renderDepth={this._props.renderDepth + 1}
hideDecorations={BoolCast(childLayout._layout_isSvg && childLayout.type === DocumentType.LINK)}
suppressSetHeight={!!this.layoutEngine}
RenderCutoffProvider={this.renderCutoffProvider}
- CollectionFreeFormView={this}
LayoutTemplate={childLayout.z ? undefined : this._props.childLayoutTemplate}
LayoutTemplateString={childLayout.z ? undefined : this._props.childLayoutString}
rootSelected={childData ? this.rootSelected : returnFalse}
@@ -1282,7 +1261,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
})
);
- this._clusters.initClusters();
+ this._clusters.initLayout();
return elements;
};
@@ -1308,7 +1287,14 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
childDocsFunc = () => this.childDocs;
closeInfo = action(() => { Doc.IsInfoUIDisabled = true }); // prettier-ignore
- infoUI = () => (Doc.IsInfoUIDisabled || this.Document.annotationOn || this._props.renderDepth ? null : <CollectionFreeFormInfoUI Document={this.Document} LayoutDoc={this.layoutDoc} childDocs={this.childDocsFunc} close={this.closeInfo} />);
+ static _infoUI: ((doc: Doc, layout: Doc, childDocs: () => Doc[], close: () => void) => JSX.Element) | null = null;
+ static SetInfoUICreator(func: (doc: Doc, layout: Doc, childDocs: () => Doc[], close: () => void) => JSX.Element) {
+ CollectionFreeFormView._infoUI = func;
+ }
+ infoUI = () =>
+ Doc.IsInfoUIDisabled || this.Document.annotationOn || this._props.renderDepth
+ ? null //
+ : CollectionFreeFormView._infoUI?.(this.Document, this.layoutDoc, this.childDocsFunc, this.closeInfo) || null;
componentDidMount() {
this._props.setContentViewBox?.(this);
@@ -1551,9 +1537,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
const isDocInView = (doc: Doc, rect: { left: number; top: number; width: number; height: number }) => intersectRect(docDims(doc), rect);
const snappableDocs = activeDocs.filter(doc => doc.z === undefined && isDocInView(doc, selRect)); // first see if there are any foreground docs to snap to
- activeDocs
- .filter(doc => doc.isGroup && SnappingManager.IsResizing !== doc[Id] && !DragManager.docsBeingDragged.includes(doc))
- .forEach(doc => DocumentManager.Instance.getDocumentView(doc)?.ComponentView?.dragStarting?.(snapToDraggedDoc, false, visited));
+ activeDocs.filter(doc => doc.isGroup && SnappingManager.IsResizing !== doc[Id] && !DragManager.docsBeingDragged.includes(doc)).forEach(doc => DocumentView.getDocumentView(doc)?.ComponentView?.dragStarting?.(snapToDraggedDoc, false, visited));
const horizLines: number[] = [];
const vertLines: number[] = [];
@@ -1654,7 +1638,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
nudge={this.isAnnotationOverlay || this._props.renderDepth > 0 ? undefined : this.nudge}
addDocTab={this.addDocTab}
slowLoadDocuments={this.slowLoadDocuments}
- trySelectCluster={this._clusters.trySelectCluster}
+ trySelectCluster={this._clusters.tryToSelect}
activeDocuments={this.getActiveDocuments}
selectDocuments={this.selectDocuments}
addDocument={this.addDocument}
@@ -1744,22 +1728,22 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
}
// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function nextKeyFrame(readOnly: boolean) {
- !readOnly && (SelectionManager.Views[0].ComponentView as CollectionFreeFormView)?.changeKeyFrame();
+ !readOnly && (DocumentView.Selected()[0].ComponentView as CollectionFreeFormView)?.changeKeyFrame();
});
// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function prevKeyFrame(readOnly: boolean) {
- !readOnly && (SelectionManager.Views[0].ComponentView as CollectionFreeFormView)?.changeKeyFrame(true);
+ !readOnly && (DocumentView.Selected()[0].ComponentView as CollectionFreeFormView)?.changeKeyFrame(true);
});
// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function curKeyFrame(readOnly: boolean) {
- const selView = SelectionManager.Views;
+ const selView = DocumentView.Selected();
if (readOnly) return selView[0].ComponentView?.getKeyFrameEditing?.() ? Colors.MEDIUM_BLUE : 'transparent';
runInAction(() => selView[0].ComponentView?.setKeyFrameEditing?.(!selView[0].ComponentView?.getKeyFrameEditing?.()));
return undefined;
});
// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function pinWithView(pinContent: boolean) {
- SelectionManager.Views.forEach(view =>
+ DocumentView.Selected().forEach(view =>
view._props.pinToPres(view.Document, {
currentFrame: Cast(view.Document.currentFrame, 'number', null),
pinData: {
@@ -1772,16 +1756,16 @@ ScriptingGlobals.add(function pinWithView(pinContent: boolean) {
});
// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function bringToFront() {
- SelectionManager.Views.forEach(view => CollectionFreeFormView.from(view)?.bringToFront(view.Document));
+ DocumentView.Selected().forEach(view => CollectionFreeFormView.from(view)?.bringToFront(view.Document));
});
// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function sendToBack() {
- SelectionManager.Views.forEach(view => CollectionFreeFormView.from(view)?.bringToFront(view.Document, true));
+ DocumentView.Selected().forEach(view => CollectionFreeFormView.from(view)?.bringToFront(view.Document, true));
});
// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function datavizFromSchema() {
// creating a dataviz doc to represent the schema table
- SelectionManager.Views.forEach(viewIn => {
+ DocumentView.Selected().forEach(viewIn => {
const view = viewIn;
if (!view.layoutDoc.schema_columnKeys) {
view.layoutDoc.schema_columnKeys = new List<string>(['title', 'type', 'author', 'author_date']);
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 3ab04f403..b96444024 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -17,15 +17,14 @@ import { CognitiveServices } from '../../../cognitive_services/CognitiveServices
import { DocUtils } from '../../../documents/DocUtils';
import { DocumentType } from '../../../documents/DocumentTypes';
import { Docs, DocumentOptions } from '../../../documents/Documents';
-import { SelectionManager } from '../../../util/SelectionManager';
-import { freeformScrollMode } from '../../../util/SettingsManager';
-import { SnappingManager } from '../../../util/SnappingManager';
+import { SnappingManager, freeformScrollMode } from '../../../util/SnappingManager';
import { Transform } from '../../../util/Transform';
import { UndoManager, undoBatch } from '../../../util/UndoManager';
import { ContextMenu } from '../../ContextMenu';
import { ObservableReactComponent } from '../../ObservableReactComponent';
import { MarqueeViewBounds } from '../../PinFuncs';
import { PreviewCursor } from '../../PreviewCursor';
+import { DocumentView } from '../../nodes/DocumentView';
import { OpenWhere } from '../../nodes/OpenWhere';
import { pasteImageBitmap } from '../../nodes/WebBoxRenderer';
import { FormattedTextBox } from '../../nodes/formattedText/FormattedTextBox';
@@ -175,7 +174,7 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps
this.pasteTable(ns, x, y);
})();
e.stopPropagation();
- } else if (!e.ctrlKey && !e.metaKey && SelectionManager.Views.length < 2) {
+ } else if (!e.ctrlKey && !e.metaKey && DocumentView.Selected().length < 2) {
FormattedTextBox.SelectOnLoadChar = Doc.UserDoc().defaultTextLayout && !this._props.childLayoutString ? e.key : '';
FormattedTextBox.LiveTextUndo = UndoManager.StartBatch('type new note');
this._props.addLiveTextDocument(DocUtils.GetNewTextDoc('-typed text-', x, y, 200, 100));
@@ -249,7 +248,7 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps
if (this._visible) {
const mselect = this.marqueeSelect();
if (!e.shiftKey) {
- SelectionManager.DeselectAll(mselect.length ? undefined : this._props.Document);
+ DocumentView.DeselectAll(mselect.length ? undefined : this._props.Document);
}
const docs = mselect.length ? mselect : [this._props.Document];
this._props.selectDocuments(docs);
@@ -344,7 +343,7 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps
@undoBatch
delete = action((e?: React.PointerEvent<Element> | KeyboardEvent | undefined, hide?: boolean) => {
const selected = this.marqueeSelect(false);
- SelectionManager.DeselectAll();
+ DocumentView.DeselectAll();
selected.forEach(doc => {
hide ? (doc.hidden = true) : this._props.removeDocument?.(doc);
});
@@ -380,7 +379,7 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps
@undoBatch
pileup = action(() => {
const selected = this.marqueeSelect(false);
- SelectionManager.DeselectAll();
+ DocumentView.DeselectAll();
selected.forEach(d => this._props.removeDocument?.(d));
const newCollection = DocUtils.pileup(selected, this.Bounds.left + this.Bounds.width / 2, this.Bounds.top + this.Bounds.height / 2)!;
this._props.addDocument?.(newCollection);
@@ -390,7 +389,7 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps
});
/**
- * This triggers the TabDocView.PinDoc method which is the universal method
+ * This triggers the DocumentView.PinDoc method which is the universal method
* used to pin documents to the currently active presentation trail.
*
* This one is unique in that it includes the bounds associated with marquee view.
diff --git a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx
index e68ed0e17..eac0dc0e1 100644
--- a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx
+++ b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx
@@ -14,7 +14,6 @@ import { Id } from '../../../../fields/FieldSymbols';
import { BoolCast, Cast, DocCast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types';
import { CollectionViewType } from '../../../documents/DocumentTypes';
import { BranchingTrailManager } from '../../../util/BranchingTrailManager';
-import { DocumentManager } from '../../../util/DocumentManager';
import { DragManager } from '../../../util/DragManager';
import { dropActionType } from '../../../util/DropActionTypes';
import { SettingsManager } from '../../../util/SettingsManager';
@@ -23,7 +22,6 @@ import { UndoStack } from '../../UndoStack';
import { DocumentLinksButton } from '../../nodes/DocumentLinksButton';
import { DocumentView } from '../../nodes/DocumentView';
import { LinkDescriptionPopup } from '../../nodes/LinkDescriptionPopup';
-import { CollectionStackedTimeline } from '../CollectionStackedTimeline';
import { CollectionSubView } from '../CollectionSubView';
import './CollectionLinearView.scss';
@@ -128,14 +126,14 @@ export class CollectionLinearView extends CollectionSubView() {
</span>
);
getCurrentlyPlayingUI = () =>
- !CollectionStackedTimeline.CurrentlyPlaying?.length ? null : (
+ !DocumentView.CurrentlyPlaying?.length ? null : (
<span className="bottomPopup-background">
<span className="bottomPopup-text">
Currently playing:
- {CollectionStackedTimeline.CurrentlyPlaying.map((clip, i) => (
+ {DocumentView.CurrentlyPlaying.map((clip, i) => (
<>
- <span className="audio-title" onPointerDown={() => DocumentManager.Instance.showDocument(clip.Document, { willZoomCentered: true })}>
- {clip.Document.title + (i === CollectionStackedTimeline.CurrentlyPlaying.length - 1 ? ' ' : ',')}
+ <span className="audio-title" onPointerDown={() => DocumentView.showDocument(clip.Document, { willZoomCentered: true })}>
+ {clip.Document.title + (i === DocumentView.CurrentlyPlaying.length - 1 ? ' ' : ',')}
</span>
<FontAwesomeIcon icon={!clip.ComponentView?.IsPlaying?.() ? 'play' : 'pause'} size="lg" onPointerDown={() => clip.ComponentView?.TogglePause?.()} />{' '}
<FontAwesomeIcon icon="times" size="lg" onPointerDown={() => clip.ComponentView?.Pause?.()} />{' '}
diff --git a/src/client/views/collections/collectionMulticolumn/MulticolumnResizer.tsx b/src/client/views/collections/collectionMulticolumn/MulticolumnResizer.tsx
index 49ba85524..931e2c5e0 100644
--- a/src/client/views/collections/collectionMulticolumn/MulticolumnResizer.tsx
+++ b/src/client/views/collections/collectionMulticolumn/MulticolumnResizer.tsx
@@ -5,7 +5,7 @@ import * as React from 'react';
import { Doc } from '../../../../fields/Doc';
import { NumCast, StrCast } from '../../../../fields/Types';
import { UndoManager } from '../../../util/UndoManager';
-import { StyleProp } from '../../StyleProvider';
+import { StyleProp } from '../../StyleProp';
import { StyleProviderFuncType } from '../../nodes/FieldView';
import { DimUnit } from './CollectionMulticolumnView';
diff --git a/src/client/views/collections/collectionMulticolumn/MultirowResizer.tsx b/src/client/views/collections/collectionMulticolumn/MultirowResizer.tsx
index ad77c327d..cff0a8b4c 100644
--- a/src/client/views/collections/collectionMulticolumn/MultirowResizer.tsx
+++ b/src/client/views/collections/collectionMulticolumn/MultirowResizer.tsx
@@ -5,7 +5,7 @@ import * as React from 'react';
import { Doc } from '../../../../fields/Doc';
import { NumCast, StrCast } from '../../../../fields/Types';
import { UndoManager } from '../../../util/UndoManager';
-import { StyleProp } from '../../StyleProvider';
+import { StyleProp } from '../../StyleProp';
import { StyleProviderFuncType } from '../../nodes/FieldView';
import { DimUnit } from './CollectionMultirowView';
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
index 406a7d626..b30954ffd 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
@@ -15,16 +15,15 @@ import { ColumnType } from '../../../../fields/SchemaHeaderField';
import { BoolCast, Cast, DocCast, NumCast, StrCast } from '../../../../fields/Types';
import { DocUtils } from '../../../documents/DocUtils';
import { Docs, DocumentOptions, FInfo } from '../../../documents/Documents';
-import { DocumentManager } from '../../../util/DocumentManager';
import { DragManager } from '../../../util/DragManager';
import { dropActionType } from '../../../util/DropActionTypes';
-import { SelectionManager } from '../../../util/SelectionManager';
import { SettingsManager } from '../../../util/SettingsManager';
import { undoBatch, undoable } from '../../../util/UndoManager';
import { ContextMenu } from '../../ContextMenu';
import { EditableView } from '../../EditableView';
import { ObservableReactComponent } from '../../ObservableReactComponent';
-import { DefaultStyleProvider, StyleProp } from '../../StyleProvider';
+import { StyleProp } from '../../StyleProp';
+import { DefaultStyleProvider } from '../../StyleProvider';
import { Colors } from '../../global/globalEnums';
import { DocumentView } from '../../nodes/DocumentView';
import { FieldViewProps } from '../../nodes/FieldView';
@@ -92,12 +91,12 @@ export class CollectionSchemaView extends CollectionSubView() {
}
@computed get _selectedDocs() {
- const selected = SelectionManager.Docs.filter(doc => Doc.AreProtosEqual(DocCast(doc.embedContainer), this.Document));
+ const selected = DocumentView.SelectedDocs().filter(doc => Doc.AreProtosEqual(DocCast(doc.embedContainer), this.Document));
if (!selected.length) {
// if no schema doc is directly selected, test if a child of a schema doc is selected (such as in the preview window)
- const childOfSchemaDoc = SelectionManager.Docs.find(sel => DocumentManager.GetContextPath(sel, true).includes(this.Document));
+ const childOfSchemaDoc = DocumentView.SelectedDocs().find(sel => DocumentView.getContextPath(sel, true).includes(this.Document));
if (childOfSchemaDoc) {
- const contextPath = DocumentManager.GetContextPath(childOfSchemaDoc, true);
+ const contextPath = DocumentView.getContextPath(childOfSchemaDoc, true);
return [contextPath[contextPath.indexOf(childOfSchemaDoc) - 1]]; // the schema doc that is "selected" by virtue of one of its children being selected
}
}
@@ -175,6 +174,7 @@ export class CollectionSchemaView extends CollectionSubView() {
document.removeEventListener('keydown', this.onKeyDown);
}
+ isUnstyledView = returnTrue; // used by style provide via ViewBoxInterface
rowIndex = (doc: Doc) => this.sortedDocs.docs.indexOf(doc);
@action
@@ -190,7 +190,7 @@ export class CollectionSchemaView extends CollectionSubView() {
!e.shiftKey && this.clearSelection();
const newDoc = this.sortedDocs.docs[lastIndex + 1];
if (this._selectedDocs.includes(newDoc)) {
- SelectionManager.DeselectView(DocumentManager.Instance.getFirstDocumentView(curDoc));
+ DocumentView.DeselectView(DocumentView.getFirstDocumentView(curDoc));
} else {
this.addDocToSelection(newDoc, e.shiftKey);
this._selectedCell && (this._selectedCell[0] = newDoc);
@@ -209,7 +209,7 @@ export class CollectionSchemaView extends CollectionSubView() {
if (firstIndex > 0 && firstIndex < this.childDocs.length) {
!e.shiftKey && this.clearSelection();
const newDoc = this.sortedDocs.docs[firstIndex - 1];
- if (this._selectedDocs.includes(newDoc)) SelectionManager.DeselectView(DocumentManager.Instance.getFirstDocumentView(curDoc));
+ if (this._selectedDocs.includes(newDoc)) DocumentView.DeselectView(DocumentView.getFirstDocumentView(curDoc));
else {
this.addDocToSelection(newDoc, e.shiftKey);
this._selectedCell && (this._selectedCell[0] = newDoc);
@@ -416,12 +416,12 @@ export class CollectionSchemaView extends CollectionSubView() {
@action
addDocToSelection = (doc: Doc, extendSelection: boolean) => {
- const rowDocView = DocumentManager.Instance.getDocumentView(doc);
- if (rowDocView) SelectionManager.SelectView(rowDocView, extendSelection);
+ const rowDocView = DocumentView.getDocumentView(doc);
+ if (rowDocView) DocumentView.SelectView(rowDocView, extendSelection);
};
@action
- clearSelection = () => SelectionManager.DeselectAll();
+ clearSelection = () => DocumentView.DeselectAll();
selectRows = (doc: Doc, lastSelected: Doc) => {
const index = this.rowIndex(doc);
@@ -476,9 +476,9 @@ export class CollectionSchemaView extends CollectionSubView() {
this.dataDoc[this.fieldKey ?? 'data'] = new List<Doc>([...removed, ...draggedDocs, ...pushedDocs]);
this.clearSelection();
draggedDocs.forEach(doc => {
- const draggedView = DocumentManager.Instance.getFirstDocumentView(doc);
- if (draggedView) DocumentManager.Instance.RemoveView(draggedView);
- DocumentManager.Instance.AddViewRenderedCb(doc, dv => dv.select(true));
+ const draggedView = DocumentView.getFirstDocumentView(doc);
+ if (draggedView) DocumentView.removeView(draggedView);
+ DocumentView.addViewRenderedCb(doc, dv => dv.select(true));
});
return true;
}
diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
index dfef3aa48..ee6987e89 100644
--- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
@@ -19,9 +19,7 @@ import { ColumnType } from '../../../../fields/SchemaHeaderField';
import { BoolCast, Cast, DateCast, DocCast, FieldValue, StrCast, toList } from '../../../../fields/Types';
import { ImageField } from '../../../../fields/URLField';
import { FInfo, FInfoFieldType } from '../../../documents/Documents';
-import { DocFocusOrOpen } from '../../../util/DocumentManager';
import { dropActionType } from '../../../util/DropActionTypes';
-import { SettingsManager } from '../../../util/SettingsManager';
import { SnappingManager } from '../../../util/SnappingManager';
import { Transform } from '../../../util/Transform';
import { undoBatch, undoable } from '../../../util/UndoManager';
@@ -29,7 +27,7 @@ import { EditableView } from '../../EditableView';
import { ObservableReactComponent } from '../../ObservableReactComponent';
import { DefaultStyleProvider } from '../../StyleProvider';
import { Colors } from '../../global/globalEnums';
-import { returnEmptyDocViewList } from '../../nodes/DocumentView';
+import { DocFocusOrOpen, returnEmptyDocViewList } from '../../nodes/DocumentView';
import { FieldViewProps } from '../../nodes/FieldView';
import { KeyValueBox } from '../../nodes/KeyValueBox';
import { FormattedTextBox } from '../../nodes/formattedText/FormattedTextBox';
@@ -300,8 +298,8 @@ export class SchemaDateCell extends ObservableReactComponent<SchemaTableCellProp
icon={<FontAwesomeIcon size="sm" icon="caret-down" />}
size={Size.XSMALL}
type={Type.TERT}
- color={SettingsManager.userColor}
- background={SettingsManager.userBackgroundColor}
+ color={SnappingManager.userColor}
+ background={SnappingManager.userBackgroundColor}
popup={
<div style={{ width: 'fit-content', height: '200px' }}>
<DatePicker open dateFormat="Pp" selected={this.date?.date ?? Date.now()} onChange={this.handleChange} />
diff --git a/src/client/views/global/globalScripts.ts b/src/client/views/global/globalScripts.ts
index e75b01ab6..c595681b7 100644
--- a/src/client/views/global/globalScripts.ts
+++ b/src/client/views/global/globalScripts.ts
@@ -10,7 +10,6 @@ import { Gestures } from '../../../pen-gestures/GestureTypes';
import { DocumentType } from '../../documents/DocumentTypes';
import { LinkManager } from '../../util/LinkManager';
import { ScriptingGlobals } from '../../util/ScriptingGlobals';
-import { SelectionManager } from '../../util/SelectionManager';
import { UndoManager, undoable } from '../../util/UndoManager';
import { GestureOverlay } from '../GestureOverlay';
import { InkingStroke } from '../InkingStroke';
@@ -26,14 +25,14 @@ import { RichTextMenu } from '../nodes/formattedText/RichTextMenu';
// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function IsNoneSelected() {
- return SelectionManager.Views.length <= 0;
+ return DocumentView.Selected().length <= 0;
}, 'are no document selected');
// toggle: Set overlay status of selected document
// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function setView(view: string, getSelected: boolean) {
- if (getSelected) return SelectionManager.Docs;
- const selected = SelectionManager.Docs.lastElement();
+ if (getSelected) return DocumentView.SelectedDocs();
+ const selected = DocumentView.SelectedDocs().lastElement();
selected ? (selected._type_collection = view) : console.log('[FontIconBox.tsx] changeView failed');
return undefined;
});
@@ -41,7 +40,7 @@ ScriptingGlobals.add(function setView(view: string, getSelected: boolean) {
// toggle: Set overlay status of selected document
// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function setBackgroundColor(color?: string, checkResult?: boolean) {
- const selectedViews = SelectionManager.Views;
+ const selectedViews = DocumentView.Selected();
if (Doc.ActiveTool !== InkTool.None) {
if (checkResult) {
return ActiveFillColor();
@@ -71,7 +70,7 @@ ScriptingGlobals.add(function setBackgroundColor(color?: string, checkResult?: b
}
});
} else {
- const selected = SelectionManager.Docs.length ? SelectionManager.Docs : LinkManager.Instance.currentLink ? [LinkManager.Instance.currentLink] : [];
+ const selected = DocumentView.SelectedDocs().length ? DocumentView.SelectedDocs() : LinkManager.Instance.currentLink ? [LinkManager.Instance.currentLink] : [];
if (checkResult) {
return selected.lastElement()?._backgroundColor ?? 'transparent';
}
@@ -90,10 +89,10 @@ ScriptingGlobals.add(function setDefaultTemplate(checkResult?: boolean) {
// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function setHeaderColor(color?: string, checkResult?: boolean) {
if (checkResult) {
- return SelectionManager.Views.length ? StrCast(SelectionManager.Docs.lastElement().layout_headingColor) : Doc.SharingDoc().headingColor;
+ return DocumentView.Selected().length ? StrCast(DocumentView.SelectedDocs().lastElement().layout_headingColor) : Doc.SharingDoc().headingColor;
}
- if (SelectionManager.Views.length) {
- SelectionManager.Docs.forEach(doc => {
+ if (DocumentView.Selected().length) {
+ DocumentView.SelectedDocs().forEach(doc => {
doc[DocData].layout_headingColor = color === 'transparent' ? undefined : color;
doc.layout_showTitle = color === 'transparent' ? undefined : StrCast(doc.layout_showTitle, 'title');
});
@@ -108,7 +107,7 @@ ScriptingGlobals.add(function setHeaderColor(color?: string, checkResult?: boole
// toggle: Set overlay status of selected document
// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function toggleOverlay(checkResult?: boolean) {
- const selected = SelectionManager.Views.length ? SelectionManager.Views[0] : undefined;
+ const selected = DocumentView.Selected().length ? DocumentView.Selected()[0] : undefined;
if (checkResult) {
if (NumCast(selected?.Document.z) >= 1) return true;
return false;
@@ -119,7 +118,7 @@ ScriptingGlobals.add(function toggleOverlay(checkResult?: boolean) {
// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function showFreeform(attr: 'center' | 'grid' | 'snaplines' | 'clusters' | 'viewAll' | 'fitOnce', checkResult?: boolean, persist?: boolean) {
- const selected = SelectionManager.Docs.lastElement();
+ const selected = DocumentView.SelectedDocs().lastElement();
// prettier-ignore
const map: Map<'center' |'grid' | 'snaplines' | 'clusters' | 'viewAll' | 'fitOnce', { waitForRender?: boolean, checkResult: (doc:Doc) => any; setDoc: (doc:Doc, dv:DocumentView) => void;}> = new Map([
['grid', {
@@ -153,7 +152,7 @@ ScriptingGlobals.add(function showFreeform(attr: 'center' | 'grid' | 'snaplines'
return map.get(attr)?.checkResult(selected);
}
const batch = map.get(attr)?.waitForRender ? UndoManager.StartBatch('set freeform attribute') : { end: () => {} };
- SelectionManager.Views.map(dv => map.get(attr)?.setDoc(dv.layoutDoc, dv));
+ DocumentView.Selected().map(dv => map.get(attr)?.setDoc(dv.layoutDoc, dv));
setTimeout(() => batch.end(), 100);
return undefined;
});
@@ -347,7 +346,7 @@ ScriptingGlobals.add(setActiveTool, 'sets the active ink tool mode');
// toggle: Set overlay status of selected document
// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function setInkProperty(option: 'inkMask' | 'labels' | 'fillColor' | 'strokeWidth' | 'strokeColor', value: any, checkResult?: boolean) {
- const selected = SelectionManager.Docs.lastElement() ?? Doc.UserDoc();
+ const selected = DocumentView.SelectedDocs().lastElement() ?? Doc.UserDoc();
// prettier-ignore
const map: Map<'inkMask' | 'labels' | 'fillColor' | 'strokeWidth' | 'strokeColor', { checkResult: () => any; setInk: (doc: Doc) => void; setMode: () => void }> = new Map([
['inkMask', {
@@ -381,7 +380,20 @@ ScriptingGlobals.add(function setInkProperty(option: 'inkMask' | 'labels' | 'fil
return map.get(option)?.checkResult();
}
map.get(option)?.setMode();
- SelectionManager.Docs.filter(doc => doc._layout_isSvg).map(doc => map.get(option)?.setInk(doc));
+ DocumentView.SelectedDocs()
+ .filter(doc => doc._layout_isSvg)
+ .map(doc => map.get(option)?.setInk(doc));
+ return undefined;
+});
+
+// eslint-disable-next-line prefer-arrow-callback
+ScriptingGlobals.add(function toggleRaiseOnDrag(readOnly?: boolean) {
+ if (readOnly) {
+ return DocumentView.Selected().some(dv => dv.Document.keepZWhenDragged);
+ }
+ DocumentView.Selected().forEach(dv => {
+ dv.Document.keepZWhenDragged = !dv.Document.keepZWhenDragged;
+ });
return undefined;
});
@@ -390,7 +402,7 @@ ScriptingGlobals.add(function setInkProperty(option: 'inkMask' | 'labels' | 'fil
* */
// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function webSetURL(url: string, checkResult?: boolean) {
- const selected = SelectionManager.Views.lastElement();
+ const selected = DocumentView.Selected().lastElement();
if (selected?.Document.type === DocumentType.WEB) {
if (checkResult) {
return StrCast(selected.Document.data, Cast(selected.Document.data, WebField, null)?.url?.href);
@@ -401,7 +413,7 @@ ScriptingGlobals.add(function webSetURL(url: string, checkResult?: boolean) {
});
// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function webForward(checkResult?: boolean) {
- const selected = SelectionManager.Views.lastElement()?.ComponentView as WebBox;
+ const selected = DocumentView.Selected().lastElement()?.ComponentView as WebBox;
if (checkResult) {
return selected?.forward(checkResult) ? undefined : 'lightGray';
}
@@ -410,24 +422,24 @@ ScriptingGlobals.add(function webForward(checkResult?: boolean) {
});
// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function webBack() {
- const selected = SelectionManager.Views.lastElement()?.ComponentView as WebBox;
+ const selected = DocumentView.Selected().lastElement()?.ComponentView as WebBox;
selected?.back();
});
// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function videoSnapshot() {
- const selected = SelectionManager.Views.lastElement()?.ComponentView as VideoBox;
+ const selected = DocumentView.Selected().lastElement()?.ComponentView as VideoBox;
selected?.Snapshot();
});
// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function imageSetPixelSize() {
- const selected = SelectionManager.Views.lastElement()?.ComponentView as ImageBox;
+ const selected = DocumentView.Selected().lastElement()?.ComponentView as ImageBox;
selected?.setNativeSize();
});
// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function imageRotate90() {
- const selected = SelectionManager.Views.lastElement()?.ComponentView as ImageBox;
+ const selected = DocumentView.Selected().lastElement()?.ComponentView as ImageBox;
selected?.rotate();
});
@@ -436,7 +448,7 @@ ScriptingGlobals.add(function imageRotate90() {
* */
// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function toggleSchemaPreview(checkResult?: boolean) {
- const selected = SelectionManager.Docs.lastElement();
+ const selected = DocumentView.SelectedDocs().lastElement();
if (checkResult && selected) {
const result: boolean = NumCast(selected.schema_previewWidth) > 0;
if (result) return Colors.MEDIUM_BLUE;
@@ -453,7 +465,7 @@ ScriptingGlobals.add(function toggleSchemaPreview(checkResult?: boolean) {
});
// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function toggleSingleLineSchema(checkResult?: boolean) {
- const selected = SelectionManager.Docs.lastElement();
+ const selected = DocumentView.SelectedDocs().lastElement();
if (checkResult && selected) {
return NumCast(selected._schema_singleLine) > 0 ? Colors.MEDIUM_BLUE : 'transparent';
}
@@ -468,7 +480,7 @@ ScriptingGlobals.add(function toggleSingleLineSchema(checkResult?: boolean) {
*/
// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function setGroupBy(key: string, checkResult?: boolean) {
- SelectionManager.Docs.forEach(doc => { doc._text_fontFamily = key; }); // prettier-ignore
+ DocumentView.SelectedDocs().forEach(doc => { doc._text_fontFamily = key; }); // prettier-ignore
const editorView = RichTextMenu.Instance?.TextView?.EditorView;
if (checkResult) {
return StrCast((editorView ? RichTextMenu.Instance : Doc.UserDoc())?.fontFamily);
diff --git a/src/client/views/linking/LinkMenuGroup.tsx b/src/client/views/linking/LinkMenuGroup.tsx
index f99a18db2..cd735318e 100644
--- a/src/client/views/linking/LinkMenuGroup.tsx
+++ b/src/client/views/linking/LinkMenuGroup.tsx
@@ -8,7 +8,6 @@ import { Doc, StrListCast } from '../../../fields/Doc';
import { Id } from '../../../fields/FieldSymbols';
import { Cast, DocCast } from '../../../fields/Types';
import { DocumentType } from '../../documents/DocumentTypes';
-import { LinkManager } from '../../util/LinkManager';
import { DocumentView } from '../nodes/DocumentView';
import './LinkMenu.scss';
import { LinkMenuItem } from './LinkMenuItem';
@@ -59,8 +58,7 @@ export class LinkMenuGroup extends React.Component<LinkMenuGroupProps> {
? this.props.docView._props.LayoutTemplateString?.includes('link_anchor_1')
? DocCast(linkDoc.link_anchor_2)
: DocCast(linkDoc.link_anchor_1)
- : LinkManager.getOppositeAnchor(linkDoc, sourceDoc) ||
- LinkManager.getOppositeAnchor(linkDoc, Cast(linkDoc.link_anchor_2, Doc, null)?.annotationOn === sourceDoc ? Cast(linkDoc.link_anchor_2, Doc, null) : Cast(linkDoc.link_anchor_1, Doc, null));
+ : Doc.getOppositeAnchor(linkDoc, sourceDoc) || Doc.getOppositeAnchor(linkDoc, Cast(linkDoc.link_anchor_2, Doc, null)?.annotationOn === sourceDoc ? Cast(linkDoc.link_anchor_2, Doc, null) : Cast(linkDoc.link_anchor_1, Doc, null));
return !destDoc || !sourceDoc ? null : (
<LinkMenuItem
key={linkDoc[Id]}
diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx
index df3accb0d..9ce04ffac 100644
--- a/src/client/views/linking/LinkMenuItem.tsx
+++ b/src/client/views/linking/LinkMenuItem.tsx
@@ -11,13 +11,10 @@ import { Doc } from '../../../fields/Doc';
import { Cast, DocCast, StrCast } from '../../../fields/Types';
import { WebField } from '../../../fields/URLField';
import { DocumentType } from '../../documents/DocumentTypes';
-import { DocumentManager } from '../../util/DocumentManager';
import { DragManager } from '../../util/DragManager';
import { dropActionType } from '../../util/DropActionTypes';
-import { LinkFollower } from '../../util/LinkFollower';
import { LinkManager } from '../../util/LinkManager';
-import { SelectionManager } from '../../util/SelectionManager';
-import { SettingsManager } from '../../util/SettingsManager';
+import { SnappingManager } from '../../util/SnappingManager';
import { undoBatch } from '../../util/UndoManager';
import { ObservableReactComponent } from '../ObservableReactComponent';
import { DocumentView, DocumentViewInternal } from '../nodes/DocumentView';
@@ -38,7 +35,7 @@ interface LinkMenuItemProps {
// drag links and drop link targets (embedding them if needed)
export async function StartLinkTargetsDrag(dragEle: HTMLElement, docView: DocumentView, downX: number, downY: number, sourceDoc: Doc, specificLinks?: Doc[]) {
- const draggedDocs = (specificLinks || LinkManager.Links(sourceDoc)).map(link => LinkManager.getOppositeAnchor(link, sourceDoc)).filter(l => l) as Doc[];
+ const draggedDocs = (specificLinks || LinkManager.Links(sourceDoc)).map(link => Doc.getOppositeAnchor(link, sourceDoc)).filter(l => l) as Doc[];
if (draggedDocs.length) {
const moddrag: Doc[] = [];
@@ -81,7 +78,7 @@ export class LinkMenuItem extends ObservableReactComponent<LinkMenuItemProps> {
onIconDown = (e: React.PointerEvent) => {
setupMoveUpEvents(this, e, returnFalse, returnFalse, () => {
- const ancestor = DocumentManager.LinkCommonAncestor(this._props.linkDoc);
+ const ancestor = DocumentView.linkCommonAncestor(this._props.linkDoc);
if (!ancestor?.ComponentView?.removeDocument?.(this._props.linkDoc)) {
ancestor?.ComponentView?.addDocument?.(this._props.linkDoc);
}
@@ -105,14 +102,14 @@ export class LinkMenuItem extends ObservableReactComponent<LinkMenuItemProps> {
Doc.ActivePresentation = trail;
DocumentViewInternal.addDocTabFunc(trail, OpenWhere.replaceRight);
} else {
- SelectionManager.SelectView(this._props.docView, false);
+ DocumentView.SelectView(this._props.docView, false);
LinkManager.Instance.currentLink = this._props.linkDoc === LinkManager.Instance.currentLink ? undefined : this._props.linkDoc;
LinkManager.Instance.currentLinkAnchor = LinkManager.Instance.currentLink ? this.sourceAnchor : undefined;
- if ((SettingsManager.Instance.propertiesWidth ?? 0) < 100) {
+ if ((SnappingManager.PropertiesWidth ?? 0) < 100) {
setTimeout(
action(() => {
- SettingsManager.Instance.propertiesWidth = 250;
+ SnappingManager.SetPropertiesWidth(250);
})
);
}
@@ -126,10 +123,12 @@ export class LinkMenuItem extends ObservableReactComponent<LinkMenuItemProps> {
this,
e,
moveEv => {
- const eleClone: any = this._drag.current!.cloneNode(true);
- eleClone.style.transform = `translate(${moveEv.x}px, ${moveEv.y}px)`;
- StartLinkTargetsDrag(eleClone, this._props.docView, moveEv.x, moveEv.y, this._props.sourceDoc, [this._props.linkDoc]);
- this._props.clearLinkEditor?.();
+ const eleClone: any = this._drag.current?.cloneNode(true);
+ if (eleClone) {
+ eleClone.style.transform = `translate(${moveEv.x}px, ${moveEv.y}px)`;
+ StartLinkTargetsDrag(eleClone, this._props.docView, moveEv.x, moveEv.y, this._props.sourceDoc, [this._props.linkDoc]);
+ this._props.clearLinkEditor?.();
+ }
return true;
},
emptyFunction,
@@ -146,13 +145,13 @@ export class LinkMenuItem extends ObservableReactComponent<LinkMenuItemProps> {
: undefined;
if (focusDoc) this._props.docView._props.focus(focusDoc, { instant: true });
- LinkFollower.FollowLink(this._props.linkDoc, this._props.sourceDoc, false);
+ DocumentView.FollowLink(this._props.linkDoc, this._props.sourceDoc, false);
}
}
);
};
- deleteLink = (e: React.PointerEvent): void => setupMoveUpEvents(this, e, returnFalse, emptyFunction, undoBatch(action(() => LinkManager.Instance.deleteLink(this._props.linkDoc))));
+ deleteLink = (e: React.PointerEvent): void => setupMoveUpEvents(this, e, returnFalse, emptyFunction, undoBatch(action(() => Doc.DeleteLink?.(this._props.linkDoc))));
@observable _hover = false;
docView = () => this._props.docView;
render() {
@@ -181,7 +180,7 @@ export class LinkMenuItem extends ObservableReactComponent<LinkMenuItemProps> {
style={{
fontSize: this._hover ? 'larger' : undefined,
fontWeight: this._hover ? 'bold' : undefined,
- background: LinkManager.Instance.currentLink === this._props.linkDoc ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor,
+ background: LinkManager.Instance.currentLink === this._props.linkDoc ? SnappingManager.userVariantColor : SnappingManager.userBackgroundColor,
}}>
<div className="linkMenu-item-content expand-two">
<div
diff --git a/src/client/views/newlightbox/ButtonMenu/ButtonMenu.tsx b/src/client/views/newlightbox/ButtonMenu/ButtonMenu.tsx
index 72d81e9eb..e48e993cf 100644
--- a/src/client/views/newlightbox/ButtonMenu/ButtonMenu.tsx
+++ b/src/client/views/newlightbox/ButtonMenu/ButtonMenu.tsx
@@ -2,7 +2,6 @@ import { action } from 'mobx';
import * as React from 'react';
import { Doc } from '../../../../fields/Doc';
import { InkTool } from '../../../../fields/InkField';
-import { SelectionManager } from '../../../util/SelectionManager';
import { SnappingManager } from '../../../util/SnappingManager';
import { CollectionDockingView } from '../../collections/CollectionDockingView';
import { OpenWhereMod } from '../../nodes/OpenWhere';
@@ -26,7 +25,7 @@ export const ButtonMenu = (props: IButtonMenu) => {
onClick={e => {
e.stopPropagation();
CollectionDockingView.AddSplit(NewLightboxView.LightboxDoc || NewLightboxView.LightboxDoc!, OpenWhereMod.none);
- SelectionManager.DeselectAll();
+ DocumentView.DeselectAll();
NewLightboxView.SetNewLightboxDoc(undefined);
}}></div>
<div
diff --git a/src/client/views/newlightbox/NewLightboxView.tsx b/src/client/views/newlightbox/NewLightboxView.tsx
index dc6bf3e9c..558ce7e38 100644
--- a/src/client/views/newlightbox/NewLightboxView.tsx
+++ b/src/client/views/newlightbox/NewLightboxView.tsx
@@ -9,16 +9,11 @@ import { emptyFunction } from '../../../Utils';
import { CreateLinkToActiveAudio, Doc, DocListCast, Opt } from '../../../fields/Doc';
import { InkTool } from '../../../fields/InkField';
import { Cast, NumCast, StrCast, toList } from '../../../fields/Types';
-import { DocumentManager } from '../../util/DocumentManager';
-import { LinkManager } from '../../util/LinkManager';
-import { SelectionManager } from '../../util/SelectionManager';
import { SnappingManager } from '../../util/SnappingManager';
import { Transform } from '../../util/Transform';
import { GestureOverlay } from '../GestureOverlay';
import { LightboxView } from '../LightboxView';
import { DefaultStyleProvider } from '../StyleProvider';
-import { CollectionStackedTimeline } from '../collections/CollectionStackedTimeline';
-import { TabDocView } from '../collections/TabDocView';
import { DocumentView } from '../nodes/DocumentView';
import { OpenWhere } from '../nodes/OpenWhere';
import { ExploreView } from './ExploreView';
@@ -79,7 +74,7 @@ export class NewLightboxView extends React.Component<LightboxViewProps> {
}
}
public static AddDocTab = (docsIn: Doc | Doc[], location: OpenWhere, layoutTemplate?: Doc | string) => {
- SelectionManager.DeselectAll();
+ DocumentView.DeselectAll();
const doc = toList(docsIn).lastElement();
return (
doc &&
@@ -110,8 +105,8 @@ export class NewLightboxView extends React.Component<LightboxViewProps> {
} else {
const l = CreateLinkToActiveAudio(() => doc).lastElement();
l && (Cast(l.link_anchor_2, Doc, null).backgroundColor = 'lightgreen');
- CollectionStackedTimeline.CurrentlyPlaying?.forEach(dv => dv.ComponentView?.Pause?.());
- // TabDocView.PinDoc(doc, { hidePresBox: true });
+ DocumentView.CurrentlyPlaying?.forEach(dv => dv.ComponentView?.Pause?.());
+ // DocumentView.PinDoc(doc, { hidePresBox: true });
this._history ? this._history.push({ doc, target }) : (this._history = [{ doc, target }]);
if (doc !== LightboxView.LightboxDoc) {
this._savedState = {
@@ -130,7 +125,7 @@ export class NewLightboxView extends React.Component<LightboxViewProps> {
...future
.slice()
.sort((a, b) => NumCast(b._timecodeToShow) - NumCast(a._timecodeToShow))
- .sort((a, b) => LinkManager.Links(a).length - LinkManager.Links(b).length),
+ .sort((a, b) => Doc.Links(a).length - Doc.Links(b).length),
];
}
this._doc = doc;
@@ -148,11 +143,11 @@ export class NewLightboxView extends React.Component<LightboxViewProps> {
@action public static Next() {
const doc = NewLightboxView._doc!;
const target = (NewLightboxView._docTarget = this._future?.pop());
- const targetDocView = target && DocumentManager.Instance.getLightboxDocumentView(target);
+ const targetDocView = target && DocumentView.getLightboxDocumentView(target);
if (targetDocView && target) {
const l = CreateLinkToActiveAudio(() => targetDocView.ComponentView?.getAnchor?.(true) || target).lastElement();
l && (Cast(l.link_anchor_2, Doc, null).backgroundColor = 'lightgreen');
- DocumentManager.Instance.showDocument(target, { willZoomCentered: true, zoomScale: 0.9 });
+ DocumentView.showDocument(target, { willZoomCentered: true, zoomScale: 0.9 });
if (NewLightboxView._history?.lastElement().target !== target) NewLightboxView._history?.push({ doc, target });
} else if (!target && NewLightboxView.path.length) {
const saved = NewLightboxView._savedState;
@@ -182,10 +177,10 @@ export class NewLightboxView extends React.Component<LightboxViewProps> {
return;
}
const { doc, target } = NewLightboxView._history?.lastElement();
- const docView = DocumentManager.Instance.getLightboxDocumentView(target || doc);
+ const docView = DocumentView.getLightboxDocumentView(target || doc);
if (docView) {
NewLightboxView._docTarget = target;
- target && DocumentManager.Instance.showDocument(target, { willZoomCentered: true, zoomScale: 0.9 });
+ target && DocumentView.showDocument(target, { willZoomCentered: true, zoomScale: 0.9 });
} else {
NewLightboxView.SetNewLightboxDoc(doc, target);
}
@@ -277,7 +272,7 @@ export class NewLightboxView extends React.Component<LightboxViewProps> {
removeDocument={undefined}
whenChildContentsActiveChanged={emptyFunction}
addDocTab={this.addDocTab}
- pinToPres={TabDocView.PinDoc}
+ pinToPres={DocumentView.PinDoc}
focus={emptyFunction}
/>
</GestureOverlay>
@@ -316,8 +311,8 @@ export class NewLightboxView extends React.Component<LightboxViewProps> {
if (coll) {
const fieldKey = Doc.LayoutFieldKey(coll);
const contents = [...DocListCast(coll[fieldKey]), ...DocListCast(coll[fieldKey + '_annotations'])];
- const links = LinkManager.Links(coll)
- .map(link => LinkManager.getOppositeAnchor(link, coll))
+ const links = Doc.Links(coll)
+ .map(link => Doc.getOppositeAnchor(link, coll))
.filter(doc => doc)
.map(doc => doc!);
NewLightboxView.SetNewLightboxDoc(coll, undefined, contents.length ? contents : links);
diff --git a/src/client/views/newlightbox/components/Recommendation/Recommendation.tsx b/src/client/views/newlightbox/components/Recommendation/Recommendation.tsx
index 23027808f..375408d01 100644
--- a/src/client/views/newlightbox/components/Recommendation/Recommendation.tsx
+++ b/src/client/views/newlightbox/components/Recommendation/Recommendation.tsx
@@ -1,12 +1,12 @@
import * as React from 'react';
-import { IRecommendation } from './utils';
-import './Recommendation.scss';
-import { getType } from '../../utils';
import { FaEyeSlash } from 'react-icons/fa';
-import { NewLightboxView } from '../../NewLightboxView';
-import { DocumentManager } from '../../../../util/DocumentManager';
import { Doc } from '../../../../../fields/Doc';
import { Docs } from '../../../../documents/Documents';
+import { DocumentView } from '../../../nodes/DocumentView';
+import { NewLightboxView } from '../../NewLightboxView';
+import { getType } from '../../utils';
+import './Recommendation.scss';
+import { IRecommendation } from './utils';
export const Recommendation = (props: IRecommendation) => {
const { title, data, type, text, transcript, loading, source, previewUrl, related_concepts, distance, docId } = props;
@@ -17,7 +17,7 @@ export const Recommendation = (props: IRecommendation) => {
onClick={() => {
let doc: Doc | null = null;
if (source == 'Dash' && docId) {
- const docView = DocumentManager.Instance.getDocumentViewsById(docId).lastElement();
+ const docView = DocumentView.getDocumentViewsById(docId).lastElement();
if (docView) {
doc = docView.Document;
}
diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx
index 4697491e0..9deed4de4 100644
--- a/src/client/views/nodes/AudioBox.tsx
+++ b/src/client/views/nodes/AudioBox.tsx
@@ -18,14 +18,15 @@ import { DocumentType } from '../../documents/DocumentTypes';
import { DocUtils } from '../../documents/DocUtils';
import { Networking } from '../../Network';
import { DragManager } from '../../util/DragManager';
-import { LinkManager } from '../../util/LinkManager';
import { undoBatch } from '../../util/UndoManager';
import { CollectionStackedTimeline, TrimScope } from '../collections/CollectionStackedTimeline';
import { ContextMenu } from '../ContextMenu';
import { ContextMenuProps } from '../ContextMenuItem';
import { ViewBoxAnnotatableComponent } from '../DocComponent';
+import { DocViewUtils } from '../DocViewUtils';
import { PinDocView, PinProps } from '../PinFuncs';
import './AudioBox.scss';
+import { DocumentView } from './DocumentView';
import { FieldView, FieldViewProps } from './FieldView';
import { OpenWhere } from './OpenWhere';
@@ -99,7 +100,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
return this._props.PanelHeight() < 50;
} // used to collapse timeline when node is shrunk
@computed get links() {
- return LinkManager.Links(this.dataDoc);
+ return Doc.Links(this.dataDoc);
}
@computed get mediaState() {
return this.dataDoc.mediaState as mediaState;
@@ -218,9 +219,9 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
@action
removeCurrentlyPlaying = () => {
const docView = this.DocumentView?.();
- if (CollectionStackedTimeline.CurrentlyPlaying && docView) {
- const index = CollectionStackedTimeline.CurrentlyPlaying.indexOf(docView);
- index !== -1 && CollectionStackedTimeline.CurrentlyPlaying.splice(index, 1);
+ if (DocumentView.CurrentlyPlaying && docView) {
+ const index = DocumentView.CurrentlyPlaying.indexOf(docView);
+ index !== -1 && DocumentView.CurrentlyPlaying.splice(index, 1);
}
};
@@ -228,11 +229,11 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
@action
addCurrentlyPlaying = () => {
const docView = this.DocumentView?.();
- if (!CollectionStackedTimeline.CurrentlyPlaying) {
- CollectionStackedTimeline.CurrentlyPlaying = [];
+ if (!DocumentView.CurrentlyPlaying) {
+ DocumentView.CurrentlyPlaying = [];
}
- if (docView && CollectionStackedTimeline.CurrentlyPlaying.indexOf(docView) === -1) {
- CollectionStackedTimeline.CurrentlyPlaying.push(docView);
+ if (docView && DocumentView.CurrentlyPlaying.indexOf(docView) === -1) {
+ DocumentView.CurrentlyPlaying.push(docView);
}
};
@@ -251,7 +252,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
this._stream = await navigator.mediaDevices.getUserMedia({ audio: true });
this._recorder = new MediaRecorder(this._stream);
this.dataDoc[this.fieldKey + '_recordingStart'] = new DateField();
- DocUtils.ActiveRecordings.push(this);
+ DocViewUtils.ActiveRecordings.push(this);
this._recorder.ondataavailable = async (e: any) => {
const [{ result }] = await Networking.UploadFilesToServer({ file: e.data });
if (!(result instanceof Error)) {
@@ -278,8 +279,8 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
this.dataDoc[this.fieldKey + '_duration'] = (now - this._recordStart - this._pausedTime) / 1000;
this.mediaState = mediaState.Paused;
this._stream?.getAudioTracks()[0].stop();
- const ind = DocUtils.ActiveRecordings.indexOf(this);
- ind !== -1 && DocUtils.ActiveRecordings.splice(ind, 1);
+ const ind = DocViewUtils.ActiveRecordings.indexOf(this);
+ ind !== -1 && DocViewUtils.ActiveRecordings.splice(ind, 1);
}
};
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 691d07e31..685a5aca4 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -5,18 +5,16 @@ import { OmitKeys } from '../../../ClientUtils';
import { numberRange } from '../../../Utils';
import { Doc, DocListCast, Opt } from '../../../fields/Doc';
import { TransitionTimer } from '../../../fields/DocSymbols';
+import { InkField } from '../../../fields/InkField';
import { List } from '../../../fields/List';
import { listSpec } from '../../../fields/Schema';
import { ComputedField } from '../../../fields/ScriptField';
import { Cast, NumCast, StrCast } from '../../../fields/Types';
import { TraceMobx } from '../../../fields/util';
-import { DocumentManager } from '../../util/DocumentManager';
import { DragManager } from '../../util/DragManager';
import { ScriptingGlobals } from '../../util/ScriptingGlobals';
-import { SelectionManager } from '../../util/SelectionManager';
import { DocComponent } from '../DocComponent';
-import { StyleProp } from '../StyleProvider';
-import { CollectionFreeFormView } from '../collections/collectionFreeForm/CollectionFreeFormView';
+import { StyleProp } from '../StyleProp';
import './CollectionFreeFormDocumentView.scss';
import { DocumentView, DocumentViewProps } from './DocumentView';
import { FieldViewProps } from './FieldView';
@@ -43,7 +41,8 @@ interface freeFormProps {
export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps {
RenderCutoffProvider: (doc: Doc) => boolean;
- CollectionFreeFormView: CollectionFreeFormView;
+ isAnyChildContentActive: () => boolean;
+ parent: any;
}
@observer
export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeFormDocumentViewProps & freeFormProps>() {
@@ -66,7 +65,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
]; // fields that are configured to be animatable using animation frames
public static animStringFields = ['backgroundColor', 'color', 'fillColor']; // fields that are configured to be animatable using animation frames
public static animDataFields = (doc: Doc) => (Doc.LayoutFieldKey(doc) ? [Doc.LayoutFieldKey(doc)] : []); // fields that are configured to be animatable using animation frames
- public static from(dv?: DocumentView) {
+ public static from(dv?: DocumentView): CollectionFreeFormDocumentView | undefined {
return dv?._props.parent instanceof CollectionFreeFormDocumentView ? dv._props.parent : undefined;
}
@@ -120,7 +119,6 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
);
}
- CollectionFreeFormView = this.props.CollectionFreeFormView; // needed for type checking
// this way, downstream code only invalidates when it uses a specific prop, not when any prop changes
DataTransition = () => this.Transition || StrCast(this.Document.dataTransition); // prettier-ignore
RenderCutoffProvider = this.props.RenderCutoffProvider; // needed for type checking
@@ -185,13 +183,32 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
const currentFrame = Cast(doc._currentFrame, 'number', null);
if (currentFrame === undefined) {
doc._currentFrame = 0;
- CollectionFreeFormDocumentView.setupKeyframes(childDocs, 0);
+ this.setupKeyframes(childDocs, 0);
}
- CollectionFreeFormView.updateKeyframe(undefined, [...childDocs, doc], currentFrame || 0);
+ this.updateKeyframe(undefined, [...childDocs, doc], currentFrame || 0);
doc._currentFrame = newFrame === undefined ? 0 : Math.max(0, newFrame);
}
}
+ public static updateKeyframe(timer: NodeJS.Timeout | undefined, docs: Doc[], time: number) {
+ const newTimer = DocumentView.SetViewTransition(docs, 'all', 1000, timer, undefined, true);
+ const timecode = Math.round(time);
+ docs.forEach(doc => {
+ this.animFields.forEach(val => {
+ const findexed = Cast(doc[`${val.key}_indexed`], listSpec('number'), null);
+ findexed?.length <= timecode + 1 && findexed.push(undefined as any as number);
+ });
+ this.animStringFields.forEach(val => {
+ const findexed = Cast(doc[`${val}_indexed`], listSpec('string'), null);
+ findexed?.length <= timecode + 1 && findexed.push(undefined as any as string);
+ });
+ this.animDataFields(doc).forEach(val => {
+ const findexed = Cast(doc[`${val}_indexed`], listSpec(InkField), null);
+ findexed?.length <= timecode + 1 && findexed.push(undefined as any);
+ });
+ });
+ return newTimer;
+ }
public static setupKeyframes(docs: Doc[], currTimecode: number, makeAppear: boolean = false) {
docs.forEach(doc => {
if (doc.appearFrame === undefined) doc.appearFrame = currTimecode;
@@ -220,7 +237,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
const containerDocView = this._props.containerViewPath?.().lastElement();
const screenXf = containerDocView?.screenToContentsTransform();
if (screenXf) {
- SelectionManager.DeselectAll();
+ DocumentView.DeselectAll();
if (topDoc.z) {
const spt = screenXf.inverse().transformPoint(NumCast(topDoc.x), NumCast(topDoc.y));
topDoc.z = 0;
@@ -233,7 +250,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
topDoc.z = 1;
[topDoc.x, topDoc.y] = fpt;
}
- setTimeout(() => SelectionManager.SelectView(DocumentManager.Instance.getDocumentView(topDoc, containerDocView), false), 0);
+ setTimeout(() => DocumentView.SelectView(DocumentView.getDocumentView(topDoc, containerDocView), false), 0);
}
};
@@ -255,7 +272,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
// 'inactive' - this is a group child but it is not active
// undefined - this is not activated by a group
isGroupActive = () => {
- if (this.CollectionFreeFormView.isAnyChildContentActive()) return undefined;
+ if (this._props.isAnyChildContentActive()) return undefined;
const backColor = this.BackgroundColor;
const isGroup = this.dataDoc.isGroup && (!backColor || backColor === 'transparent');
return isGroup ? (this._props.isDocumentActive?.() ? 'group' : this._props.isGroupActive?.() ? 'child' : 'inactive') : this._props.isGroupActive?.() ? 'child' : undefined;
diff --git a/src/client/views/nodes/ComparisonBox.tsx b/src/client/views/nodes/ComparisonBox.tsx
index c42ca4468..6ae6bb228 100644
--- a/src/client/views/nodes/ComparisonBox.tsx
+++ b/src/client/views/nodes/ComparisonBox.tsx
@@ -15,7 +15,7 @@ import { dropActionType } from '../../util/DropActionTypes';
import { undoBatch } from '../../util/UndoManager';
import { ViewBoxAnnotatableComponent, ViewBoxInterface } from '../DocComponent';
import { PinDocView, PinProps } from '../PinFuncs';
-import { StyleProp } from '../StyleProvider';
+import { StyleProp } from '../StyleProp';
import './ComparisonBox.scss';
import { DocumentView } from './DocumentView';
import { FieldView, FieldViewProps } from './FieldView';
diff --git a/src/client/views/nodes/DataVizBox/DataVizBox.tsx b/src/client/views/nodes/DataVizBox/DataVizBox.tsx
index ecfdcc229..15187b4e4 100644
--- a/src/client/views/nodes/DataVizBox/DataVizBox.tsx
+++ b/src/client/views/nodes/DataVizBox/DataVizBox.tsx
@@ -16,7 +16,6 @@ import { TraceMobx } from '../../../../fields/util';
import { DocUtils } from '../../../documents/DocUtils';
import { DocumentType } from '../../../documents/DocumentTypes';
import { Docs } from '../../../documents/Documents';
-import { DocumentManager } from '../../../util/DocumentManager';
import { UndoManager, undoable } from '../../../util/UndoManager';
import { ContextMenu } from '../../ContextMenu';
import { ViewBoxAnnotatableComponent, ViewBoxInterface } from '../../DocComponent';
@@ -254,7 +253,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() im
this.toggleSidebar();
}
return new Promise<Opt<DocumentView>>(res => {
- DocumentManager.Instance.AddViewRenderedCb(doc, dv => res(dv));
+ DocumentView.addViewRenderedCb(doc, dv => res(dv));
});
};
@computed get sidebarWidthPercent() {
diff --git a/src/client/views/nodes/DataVizBox/components/LineChart.tsx b/src/client/views/nodes/DataVizBox/components/LineChart.tsx
index 1c3134185..bc35ab8c8 100644
--- a/src/client/views/nodes/DataVizBox/components/LineChart.tsx
+++ b/src/client/views/nodes/DataVizBox/components/LineChart.tsx
@@ -8,7 +8,6 @@ import { List } from '../../../../../fields/List';
import { listSpec } from '../../../../../fields/Schema';
import { Cast, DocCast, StrCast } from '../../../../../fields/Types';
import { Docs } from '../../../../documents/Documents';
-import { DocumentManager } from '../../../../util/DocumentManager';
import { undoable } from '../../../../util/UndoManager';
import {} from '../../../DocComponent';
import { ObservableReactComponent } from '../../../ObservableReactComponent';
@@ -16,6 +15,7 @@ import { PinProps, PinDocView } from '../../../PinFuncs';
import { DataVizBox } from '../DataVizBox';
import { createLineGenerator, drawLine, minMaxRange, scaleCreatorNumerical, xAxisCreator, xGrid, yAxisCreator, yGrid } from '../utils/D3Utils';
import './Chart.scss';
+import { DocumentView } from '../../DocumentView';
export interface DataPoint {
x: number;
@@ -71,7 +71,7 @@ export class LineChart extends ObservableReactComponent<LineChartProps> {
}
@computed get parentViz() {
return DocCast(this._props.Document.dataViz_parentViz);
- // return LinkManager.Instance.getAllRelatedLinks(this._props.Document) // out of all links
+ // return LinkManager.Links(this._props.Document) // out of all links
// .filter(link => {
// return link.link_anchor_1 == this._props.Document.dataViz_parentViz;
// }) // get links where this chart doc is the target of the link
@@ -80,7 +80,7 @@ export class LineChart extends ObservableReactComponent<LineChartProps> {
@computed get incomingHighlited() {
// return selected x and y axes
// otherwise, use the selection of whatever is linked to us
- const incomingVizBox = DocumentManager.Instance.getFirstDocumentView(this.parentViz)?.ComponentView as DataVizBox;
+ const incomingVizBox = DocumentView.getFirstDocumentView(this.parentViz)?.ComponentView as DataVizBox;
const highlitedRowIds = NumListCast(incomingVizBox?.layoutDoc?.dataViz_highlitedRows);
return this._tableData.filter((record, i) => highlitedRowIds.includes(this._tableDataIds[i])); // get all the datapoints they have selected field set by incoming anchor
}
diff --git a/src/client/views/nodes/DataVizBox/components/PieChart.tsx b/src/client/views/nodes/DataVizBox/components/PieChart.tsx
index ffb2f528a..ef6d1d412 100644
--- a/src/client/views/nodes/DataVizBox/components/PieChart.tsx
+++ b/src/client/views/nodes/DataVizBox/components/PieChart.tsx
@@ -84,7 +84,7 @@ export class PieChart extends ObservableReactComponent<PieChartProps> {
@computed get parentViz() {
return DocCast(this._props.Document.dataViz_parentViz);
- // return LinkManager.Instance.getAllRelatedLinks(this._props.Document) // out of all links
+ // return LinkManager.Links(this._props.Document) // out of all links
// .filter(link => link.link_anchor_1 == this._props.Document.dataViz_parentViz) // get links where this chart doc is the target of the link
// .map(link => DocCast(link.link_anchor_1)); // then return the source of the link
}
diff --git a/src/client/views/nodes/DataVizBox/components/TableBox.tsx b/src/client/views/nodes/DataVizBox/components/TableBox.tsx
index 8038b2cd4..5cd77e274 100644
--- a/src/client/views/nodes/DataVizBox/components/TableBox.tsx
+++ b/src/client/views/nodes/DataVizBox/components/TableBox.tsx
@@ -7,6 +7,7 @@ import * as React from 'react';
import { ClientUtils, setupMoveUpEvents } from '../../../../../ClientUtils';
import { emptyFunction } from '../../../../../Utils';
import { Doc, Field, NumListCast } from '../../../../../fields/Doc';
+import { DocData } from '../../../../../fields/DocSymbols';
import { List } from '../../../../../fields/List';
import { listSpec } from '../../../../../fields/Schema';
import { Cast, DocCast } from '../../../../../fields/Types';
@@ -152,11 +153,9 @@ export class TableBox extends ObservableReactComponent<TableBoxProps> {
DragManager.StartAnchorAnnoDrag(moveEv.target instanceof HTMLElement ? [moveEv.target] : [], new DragManager.AnchorAnnoDragData(this._props.docView()!, sourceAnchorCreator, targetCreator), downX, downY, {
dragComplete: completeEv => {
if (!completeEv.aborted && completeEv.annoDragData && completeEv.annoDragData.linkSourceDoc && completeEv.annoDragData.dropDocument && completeEv.linkDocument) {
- completeEv.linkDocument.link_displayLine = true;
- completeEv.linkDocument.link_matchEmbeddings = true;
- completeEv.linkDocument.link_displayArrow = true;
- // e.annoDragData.linkSourceDoc.followLinkToggle = e.annoDragData.dropDocument.annotationOn === this._props.Document;
- // e.annoDragData.linkSourceDoc.followLinkZoom = false;
+ completeEv.linkDocument[DocData].link_matchEmbeddings = true;
+ completeEv.linkDocument[DocData].stroke_startMarker = true;
+ this._props.docView?.()?._props.addDocument?.(completeEv.linkDocument);
}
},
});
diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index e902d1792..ec9db8480 100644
--- a/src/client/views/nodes/DocumentContentsView.tsx
+++ b/src/client/views/nodes/DocumentContentsView.tsx
@@ -31,7 +31,6 @@ import { FunctionPlotBox } from './FunctionPlotBox';
import { ImageBox } from './ImageBox';
import { KeyValueBox } from './KeyValueBox';
import { LabelBox } from './LabelBox';
-import { LinkAnchorBox } from './LinkAnchorBox';
import { LinkBox } from './LinkBox';
import { LoadingBox } from './LoadingBox';
import { MapBox } from './MapBox/MapBox';
@@ -87,18 +86,18 @@ interface HTMLtagProps {
export class HTMLtag extends React.Component<HTMLtagProps> {
click = () => {
const clickScript = (this.props as any).onClick as Opt<ScriptField>;
- clickScript?.script.run({ this: this.props.Document, self: this.props.Document, scale: this.props.scaling });
+ clickScript?.script.run({ this: this.props.Document, scale: this.props.scaling });
};
onInput = (e: React.FormEvent<HTMLDivElement>) => {
const onInputScript = (this.props as any).onInput as Opt<ScriptField>;
- onInputScript?.script.run({ this: this.props.Document, self: this.props.Document, value: (e.target as any).textContent });
+ onInputScript?.script.run({ this: this.props.Document, value: (e.target as any).textContent });
};
render() {
const style: { [key: string]: any } = {};
const divKeys = OmitKeys(this.props, ['children', 'dragStarting', 'dragEnding', 'htmltag', 'scaling', 'Document', 'key', 'onInput', 'onClick', '__proto__']).omit;
const replacer = (match: any, expr: string) =>
// bcz: this executes a script to convert a property expression string: { script } into a value
- (ScriptField.MakeFunction(expr, { self: Doc.name, this: Doc.name, scale: 'number' })?.script.run({ self: this.props.Document, this: this.props.Document, scale: this.props.scaling }).result as string) || '';
+ (ScriptField.MakeFunction(expr, { this: Doc.name, scale: 'number' })?.script.run({ this: this.props.Document, scale: this.props.scaling }).result as string) || '';
Object.keys(divKeys).forEach((prop: string) => {
const p = (this.props as any)[prop] as string;
style[prop] = p?.replace(/{([^.'][^}']+)}/g, replacer);
@@ -121,7 +120,6 @@ export class DocumentContentsView extends ObservableReactComponent<DocumentConte
super(props);
makeObservable(this);
}
-
@computed get layout(): string {
TraceMobx();
if (this._props.LayoutTemplateString) return this._props.LayoutTemplateString;
@@ -186,7 +184,7 @@ export class DocumentContentsView extends ObservableReactComponent<DocumentConte
let layoutFrame = this.layout;
// replace code content with a script >{content}< as in <HTMLdiv>{this.title}</HTMLdiv>
- const replacer = (match: any, prefix: string, expr: string, postfix: string) => prefix + ((ScriptField.MakeFunction(expr, { self: Doc.name, this: Doc.name })?.script.run({ this: this._props.Document }).result as string) || '') + postfix;
+ const replacer = (match: any, prefix: string, expr: string, postfix: string) => prefix + ((ScriptField.MakeFunction(expr, { this: Doc.name })?.script.run({ this: this._props.Document }).result as string) || '') + postfix;
layoutFrame = layoutFrame.replace(/(>[^{]*)[^=]\{([^.'][^<}]+)\}([^}]*<)/g, replacer);
// replace HTML<tag> with corresponding HTML tag as in: <HTMLdiv> becomes <HTMLtag Document={props.Document} htmltag='div'>
@@ -205,7 +203,7 @@ export class DocumentContentsView extends ObservableReactComponent<DocumentConte
const code = XRegExp.matchRecursive(splits[1], '{', '}', '', { valueNames: ['between', 'left', 'match', 'right', 'between'] });
layoutFrame = splits[0] + ` ${func}={props.${func}} ` + splits[1].substring(code[1].end + 1);
const script = code[1].value.replace(/^‘/, '').replace(/’$/, ''); // ‘’ are not valid quotes in javascript so get rid of them -- they may be present to make it easier to write complex scripts - see headerTemplate in currentUserUtils.ts
- return ScriptField.MakeScript(script, { this: Doc.name, self: Doc.name, scale: 'number', value: 'string' });
+ return ScriptField.MakeScript(script, { this: Doc.name, scale: 'number', value: 'string' });
}
return undefined;
// add input function to props
@@ -247,7 +245,6 @@ export class DocumentContentsView extends ObservableReactComponent<DocumentConte
PresElementBox,
SearchBox,
FunctionPlotBox,
- LinkAnchorBox,
InkingStroke,
LinkBox,
ScriptingBox,
diff --git a/src/client/views/nodes/DocumentIcon.tsx b/src/client/views/nodes/DocumentIcon.tsx
index 364406197..23d934edb 100644
--- a/src/client/views/nodes/DocumentIcon.tsx
+++ b/src/client/views/nodes/DocumentIcon.tsx
@@ -6,10 +6,8 @@ import { factory } from 'typescript';
import { FieldType } from '../../../fields/Doc';
import { Id } from '../../../fields/FieldSymbols';
import { StrCast } from '../../../fields/Types';
-import { DocumentManager } from '../../util/DocumentManager';
import { Transformer, ts } from '../../util/Scripting';
import { SnappingManager } from '../../util/SnappingManager';
-import { LightboxView } from '../LightboxView';
import { ObservableReactComponent } from '../ObservableReactComponent';
import { DocumentView } from './DocumentView';
@@ -25,9 +23,6 @@ export class DocumentIcon extends ObservableReactComponent<DocumentIconProps> {
makeObservable(this);
}
- static get DocViews() {
- return LightboxView.LightboxDoc ? DocumentManager.Instance.DocumentViews.filter(v => LightboxView.Contains(v)) : DocumentManager.Instance.DocumentViews;
- }
render() {
const { view } = this._props;
const { left, top, right } = view.getBounds || { left: 0, top: 0, right: 0, bottom: 0 };
@@ -69,7 +64,7 @@ export class DocumentIconContainer extends React.Component {
const match = node.text.match(/d([0-9]+)/);
if (match) {
const m = parseInt(match[1]);
- const doc = DocumentIcon.DocViews[m].Document;
+ const doc = DocumentView.allViews()[m].Document;
usedDocuments.add(m);
return factory.createIdentifier(`idToDoc("${doc[Id]}")`);
}
@@ -81,7 +76,7 @@ export class DocumentIconContainer extends React.Component {
return ts.visitNode(root, visit);
},
getVars() {
- const docs = DocumentIcon.DocViews;
+ const docs = DocumentView.allViews();
const capturedVariables: { [name: string]: FieldType } = {};
usedDocuments.forEach(index => {
capturedVariables[`d${index}`] = docs.length > index ? docs[index].Document : `d${index}`;
@@ -91,6 +86,6 @@ export class DocumentIconContainer extends React.Component {
};
}
render() {
- return DocumentIcon.DocViews.map((dv, i) => <DocumentIcon key={dv.DocUniqueId} index={i} view={dv} />);
+ return DocumentView.allViews().map((dv, i) => <DocumentIcon key={dv.DocUniqueId} index={i} view={dv} />);
}
}
diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx
index 977899589..0c5156339 100644
--- a/src/client/views/nodes/DocumentLinksButton.tsx
+++ b/src/client/views/nodes/DocumentLinksButton.tsx
@@ -8,11 +8,8 @@ import * as React from 'react';
import { StopEvent, returnFalse, setupMoveUpEvents } from '../../../ClientUtils';
import { emptyFunction } from '../../../Utils';
import { Doc } from '../../../fields/Doc';
-import { DocData } from '../../../fields/DocSymbols';
-import { StrCast } from '../../../fields/Types';
import { DocUtils } from '../../documents/DocUtils';
import { DragManager } from '../../util/DragManager';
-import { Hypothesis } from '../../util/HypothesisUtils';
import { LinkManager } from '../../util/LinkManager';
import { UndoManager, undoBatch } from '../../util/UndoManager';
import { ObservableReactComponent } from '../ObservableReactComponent';
@@ -169,16 +166,6 @@ export class DocumentLinksButton extends ObservableReactComponent<DocumentLinksB
LinkManager.Instance.currentLink = linkDoc;
if (linkDoc) {
- if (DocumentLinksButton.AnnotationId && DocumentLinksButton.AnnotationUri) {
- // if linking from a Hypothes.is annotation
- const linkDocData = linkDoc[DocData];
- linkDocData.linksToAnnotation = true;
- linkDocData.annotationId = DocumentLinksButton.AnnotationId;
- linkDocData.annotationUri = DocumentLinksButton.AnnotationUri;
- const dashHyperlink = Doc.globalServerPath(startIsAnnotation ? endLink : startLink);
- Hypothesis.makeLink(StrCast(startIsAnnotation ? endLink.title : startLink.title), dashHyperlink, DocumentLinksButton.AnnotationId, startIsAnnotation ? startLink : endLink); // edit annotation to add a Dash hyperlink to the linked doc
- }
-
TaskCompletionBox.textDisplayed = 'Link Created';
TaskCompletionBox.popupX = screenX;
TaskCompletionBox.popupY = screenY - 133;
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 1e7f1015a..f8ce50c98 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -7,10 +7,10 @@ import { IReactionDisposer, action, computed, makeObservable, observable, reacti
import { observer } from 'mobx-react';
import * as React from 'react';
import { Bounce, Fade, Flip, JackInTheBox, Roll, Rotate, Zoom } from 'react-awesome-reveal';
-import { ClientUtils, DivWidth, isTargetChildOf as isParentOf, lightOrDark, returnEmptyString, returnFalse, returnTrue, returnVal, simulateMouseClick } from '../../../ClientUtils';
+import { ClientUtils, DivWidth, isTargetChildOf as isParentOf, lightOrDark, returnFalse, returnVal, simulateMouseClick } from '../../../ClientUtils';
import { Utils, emptyFunction, emptyPath } from '../../../Utils';
import { Doc, DocListCast, Field, FieldType, Opt, StrListCast } from '../../../fields/Doc';
-import { AclPrivate, Animation, AudioPlay, DocData, DocViews } from '../../../fields/DocSymbols';
+import { AclAdmin, AclEdit, AclPrivate, Animation, AudioPlay, DocData, DocViews } from '../../../fields/DocSymbols';
import { Id } from '../../../fields/FieldSymbols';
import { InkTool } from '../../../fields/InkField';
import { List } from '../../../fields/List';
@@ -20,20 +20,17 @@ import { ScriptField } from '../../../fields/ScriptField';
import { BoolCast, Cast, DocCast, NumCast, ScriptCast, StrCast } from '../../../fields/Types';
import { AudioField } from '../../../fields/URLField';
import { GetEffectiveAcl, TraceMobx } from '../../../fields/util';
+import { AudioAnnoState } from '../../../server/SharedMediaTypes';
import { DocServer } from '../../DocServer';
-import { Networking } from '../../Network';
import { DocUtils, FollowLinkScript } from '../../documents/DocUtils';
import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes';
import { Docs } from '../../documents/Documents';
-import { DictationManager } from '../../util/DictationManager';
-import { DocumentManager } from '../../util/DocumentManager';
import { DragManager } from '../../util/DragManager';
import { dropActionType } from '../../util/DropActionTypes';
import { MakeTemplate, makeUserTemplateButton } from '../../util/DropConverter';
-import { LinkManager, UPDATE_SERVER_CACHE } from '../../util/LinkManager';
+import { UPDATE_SERVER_CACHE } from '../../util/LinkManager';
import { ScriptingGlobals } from '../../util/ScriptingGlobals';
import { SearchUtil } from '../../util/SearchUtil';
-import { SelectionManager } from '../../util/SelectionManager';
import { SharingManager } from '../../util/SharingManager';
import { SnappingManager } from '../../util/SnappingManager';
import { UndoManager, undoBatch, undoable } from '../../util/UndoManager';
@@ -42,16 +39,15 @@ import { ContextMenuProps } from '../ContextMenuItem';
import { DocComponent, ViewBoxInterface } from '../DocComponent';
import { EditableView } from '../EditableView';
import { FieldsDropdown } from '../FieldsDropdown';
-import { GestureOverlay } from '../GestureOverlay';
import { LightboxView } from '../LightboxView';
-import { AudioAnnoState, StyleProp } from '../StyleProvider';
+import { PinProps } from '../PinFuncs';
+import { StyleProp } from '../StyleProp';
import { DocumentContentsView, ObserverJsxParser } from './DocumentContentsView';
import { DocumentLinksButton } from './DocumentLinksButton';
import './DocumentView.scss';
import { FieldViewProps, FieldViewSharedProps } from './FieldView';
import { FocusViewOptions } from './FocusViewOptions';
import { KeyValueBox } from './KeyValueBox';
-import { LinkAnchorBox } from './LinkAnchorBox';
import { OpenWhere } from './OpenWhere';
import { FormattedTextBox } from './formattedText/FormattedTextBox';
import { PresEffect, PresEffectDirection } from './trails';
@@ -90,6 +86,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
// this makes mobx trace() statements more descriptive
public get displayName() { return 'DocumentViewInternal(' + this.Document.title + ')'; } // prettier-ignore
public static SelectAfterContextMenu = true; // whether a document should be selected after it's contextmenu is triggered.
+
/**
* This function is filled in by MainView to allow non-viewBox views to add Docs as tabs without
* needing to know about/reference MainView
@@ -183,11 +180,10 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
// anchors that are not rendered as DocumentViews (marked as 'layout_unrendered' with their 'annotationOn' set to this document). e.g.,
// - PDF text regions are rendered as an Annotations without generating a DocumentView, '
// - RTF selections are rendered via Prosemirror and have a mark which contains the Document ID for the annotation link
- // - and links to PDF/Web docs at a certain scroll location never create an explicit view.
- // For each of these, we create LinkAnchorBox's on the border of the DocumentView.
+ // - and links to PDF/Web docs at a certain scroll location never create an explicit anchor view.
@computed get directLinks() {
TraceMobx();
- return LinkManager.Instance.getAllRelatedLinks(this.Document).filter(
+ return Doc.Links(this.Document).filter(
link =>
(link.link_matchEmbeddings ? link.link_anchor_1 === this.Document : Doc.AreProtosEqual(link.link_anchor_1 as Doc, this.Document)) ||
(link.link_matchEmbeddings ? link.link_anchor_2 === this.Document : Doc.AreProtosEqual(link.link_anchor_2 as Doc, this.Document)) ||
@@ -197,11 +193,11 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
}
@computed get _allLinks(): Doc[] {
TraceMobx();
- return LinkManager.Instance.getAllRelatedLinks(this.Document).filter(link => !link.link_matchEmbeddings || link.link_anchor_1 === this.Document || link.link_anchor_2 === this.Document);
+ return Doc.Links(this.Document).filter(link => !link.link_matchEmbeddings || link.link_anchor_1 === this.Document || link.link_anchor_2 === this.Document);
}
@computed get filteredLinks() {
- return DocUtils.FilterDocs(this.directLinks, this._props.childFilters?.() ?? [], []).filter(d => d.link_displayLine || Doc.UserDoc().showLinkLines);
+ return DocUtils.FilterDocs(this.directLinks, this._props.childFilters?.() ?? [], []);
}
componentWillUnmount() {
@@ -259,7 +255,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
startDragging(x: number, y: number, dropAction: dropActionType, hideSource = false) {
const docView = this._docView;
if (this._mainCont.current && docView) {
- const views = SelectionManager.Views.filter(dv => dv.ContentDiv);
+ const views = DocumentView.Selected().filter(dv => dv.ContentDiv);
const selected = views.length > 1 && views.some(dv => dv.Document === this.Document) ? views : [docView];
const dragData = new DragManager.DocumentDragData(selected.map(dv => dv.Document));
const screenXf = docView.screenToViewTransform();
@@ -289,8 +285,8 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
};
onBrowseClick = (e: React.MouseEvent) => {
const browseTransitionTime = 500;
- SelectionManager.DeselectAll();
- DocumentManager.Instance.showDocument(this.Document, { zoomScale: 0.8, willZoomCentered: true }, (focused: boolean) => {
+ DocumentView.DeselectAll();
+ DocumentView.showDocument(this.Document, { zoomScale: 0.8, willZoomCentered: true }, (focused: boolean) => {
const options: FocusViewOptions = { pointFocus: { X: e.clientX, Y: e.clientY }, zoomTime: browseTransitionTime };
if (!focused && this._docView) {
this._docView
@@ -327,7 +323,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
UndoManager.RunInBatch(() => this.onDoubleClickHandler.script.run(scriptProps, console.log).result?.select && this._props.select(false), 'on double click: ' + this.Document.title);
} else if (!Doc.IsSystem(this.Document) && defaultDblclick !== 'ignore') {
UndoManager.RunInBatch(() => LightboxView.Instance.AddDocTab(this.Document, OpenWhere.lightbox), 'double tap');
- SelectionManager.DeselectAll();
+ DocumentView.DeselectAll();
Doc.UnBrushDoc(this.Document);
} else {
this._singleClickFunc?.();
@@ -377,7 +373,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
if (this._props.isGroupActive?.() === 'child' && !this._props.isDocumentActive?.()) return;
// eslint-disable-next-line no-use-before-define
this._longPressSelector = setTimeout(() => DocumentView.LongPress && this._props.select(false), 1000);
- if (!GestureOverlay.DownDocView) GestureOverlay.DownDocView = this._docView;
+ if (!DocumentView.DownDocView) DocumentView.DownDocView = this._docView;
this._downX = e.clientX;
this._downY = e.clientY;
@@ -463,7 +459,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
}, 'set toggle detail');
drop = undoable((e: Event, de: DragManager.DropEvent) => {
- if (this._props.dontRegisterView || this._props.LayoutTemplateString?.includes(LinkAnchorBox.name)) return false;
+ if (this._props.dontRegisterView) return false;
if (this.Document === Doc.ActiveDashboard) {
e.stopPropagation();
e.preventDefault();
@@ -484,7 +480,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
if (linkDoc) {
de.complete.linkDocument = linkDoc;
linkDoc.layout_isSvg = true;
- DocumentManager.LinkCommonAncestor(linkDoc)?.ComponentView?.addDocument?.(linkDoc);
+ DocumentView.linkCommonAncestor(linkDoc)?.ComponentView?.addDocument?.(linkDoc);
}
}
e.stopPropagation();
@@ -516,7 +512,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
if (e && this.layoutDoc.layout_hideContextMenu && Doc.noviceMode) {
e.preventDefault();
e.stopPropagation();
- // !this._props.isSelected(true) && SelectionManager.SelectView(this.DocumentView(), false);
+ // !this._props.isSelected(true) && DocumentView.SelectView(this.DocumentView(), false);
}
// the touch onContextMenu is button 0, the pointer onContextMenu is button 2
if (e) {
@@ -576,8 +572,8 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
if (this._props.bringToFront) {
const zorders = cm.findByDescription('ZOrder...');
const zorderItems: ContextMenuProps[] = zorders && 'subitems' in zorders ? zorders.subitems : [];
- zorderItems.push({ description: 'Bring to Front', event: () => SelectionManager.Views.forEach(dv => dv._props.bringToFront?.(dv.Document, false)), icon: 'arrow-up' });
- zorderItems.push({ description: 'Send to Back', event: () => SelectionManager.Views.forEach(dv => dv._props.bringToFront?.(dv.Document, true)), icon: 'arrow-down' });
+ zorderItems.push({ description: 'Bring to Front', event: () => DocumentView.Selected().forEach(dv => dv._props.bringToFront?.(dv.Document, false)), icon: 'arrow-up' });
+ zorderItems.push({ description: 'Send to Back', event: () => DocumentView.Selected().forEach(dv => dv._props.bringToFront?.(dv.Document, true)), icon: 'arrow-down' });
zorderItems.push({
description: !this.layoutDoc._keepZDragged ? 'Keep ZIndex when dragged' : 'Allow ZIndex to change when dragged',
event: undoBatch(
@@ -601,7 +597,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
onClicks.push({ description: this.onClickHandler ? 'Remove Click Behavior' : 'Follow Link', event: () => this.toggleFollowLink(false, false), icon: 'link' });
!Doc.noviceMode && onClicks.push({ description: 'Edit onClick Script', event: () => UndoManager.RunInBatch(() => DocUtils.makeCustomViewClicked(this.Document, undefined, 'onClick'), 'edit onClick'), icon: 'terminal' });
!existingOnClick && cm.addItem({ description: 'OnClick...', noexpand: true, subitems: onClicks, icon: 'mouse-pointer' });
- } else if (LinkManager.Links(this.Document).length) {
+ } else if (Doc.Links(this.Document).length) {
onClicks.push({ description: 'Restore On Click default', event: () => this.noOnClick(), icon: 'link' });
onClicks.push({ description: 'Follow Link on Click', event: () => this.followLinkOnClick(), icon: 'link' });
!existingOnClick && cm.addItem({ description: 'OnClick...', subitems: onClicks, icon: 'mouse-pointer' });
@@ -718,7 +714,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
case StyleProp.PointerEvents: return 'none';
case StyleProp.Highlighting: return undefined;
case StyleProp.Opacity: {
- const filtered = DocUtils.FilterDocs(this.directLinks, this._props.childFilters?.() ?? [], []).filter(d => d.link_displayLine || Doc.UserDoc().showLinkLines);
+ const filtered = DocUtils.FilterDocs(this.directLinks, this._props.childFilters?.() ?? [], []);
return filtered.some(link => link._link_displayArrow) ? 0 : undefined;
}
default:
@@ -726,34 +722,6 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
return this._props.styleProvider?.(doc, props, property);
};
- // eslint-disable-next-line no-return-assign
- removeLinkByHiding = (link: Doc) => () => link.link_displayLine = false; // prettier-ignore
- @computed get allLinkEndpoints() {
- // the small blue dots that mark the endpoints of links
- if (this._componentView instanceof KeyValueBox || this._props.hideLinkAnchors || this.layoutDoc.layout_hideLinkAnchors || this._props.dontRegisterView || this.layoutDoc.layout_unrendered) return null;
- return this.filteredLinks.map(link => (
- <div className="documentView-anchorCont" key={link[Id]}>
- <DocumentView
- {...this._props}
- isContentActive={returnFalse}
- Document={link}
- containerViewPath={this._props.docViewPath}
- PanelWidth={this.anchorPanelWidth}
- PanelHeight={this.anchorPanelHeight}
- dontRegisterView={false}
- layout_showTitle={returnEmptyString}
- hideCaptions
- hideLinkAnchors
- layout_fitWidth={returnTrue}
- removeDocument={this.removeLinkByHiding(link)}
- styleProvider={this.anchorStyleProvider}
- LayoutTemplate={undefined}
- LayoutTemplateString={LinkAnchorBox.LayoutString(`link_anchor_${LinkManager.anchorIndex(link, this.Document)}`)}
- />
- </div>
- ));
- }
-
@computed get viewBoxContents() {
TraceMobx();
const isInk = this.layoutDoc._layout_isSvg && !this._props.LayoutTemplateString;
@@ -780,7 +748,6 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
setTitleFocus={this.setTitleFocus}
hideClickBehaviors={BoolCast(this.Document.hideClickBehaviors)}
/>
- {this.layoutDoc.layout_hideAllLinks ? null : this.allLinkEndpoints}
</div>
);
}
@@ -1008,50 +975,45 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
default: return renderDoc;
}
}
- public static recordAudioAnnotation(dataDoc: Doc, field: string, onRecording?: (stop: () => void) => void, onEnd?: () => void) {
- let gumStream: any;
- let recorder: any;
- navigator.mediaDevices.getUserMedia({ audio: true }).then(stream => {
- let audioTextAnnos = Cast(dataDoc[field + '_audioAnnotations_text'], listSpec('string'), null);
- if (audioTextAnnos) audioTextAnnos.push('');
- else audioTextAnnos = dataDoc[field + '_audioAnnotations_text'] = new List<string>(['']);
- DictationManager.Controls.listen({
- interimHandler: value => { audioTextAnnos[audioTextAnnos.length - 1] = value; }, // prettier-ignore
- continuous: { indefinite: false },
- }).then(results => {
- if (results && [DictationManager.Controls.Infringed].includes(results)) {
- DictationManager.Controls.stop();
- }
- onEnd?.();
- });
-
- gumStream = stream;
- recorder = new MediaRecorder(stream);
- recorder.ondataavailable = async (e: any) => {
- const [{ result }] = await Networking.UploadFilesToServer({ file: e.data });
- if (!(result instanceof Error)) {
- const audioField = new AudioField(result.accessPaths.agnostic.client);
- const audioAnnos = Cast(dataDoc[field + '_audioAnnotations'], listSpec(AudioField), null);
- if (audioAnnos) audioAnnos.push(audioField);
- else dataDoc[field + '_audioAnnotations'] = new List([audioField]);
- }
- };
- recorder.start();
- const stopFunc = () => {
- recorder.stop();
- DictationManager.Controls.stop(/* false */);
- dataDoc.audioAnnoState = AudioAnnoState.stopped;
- gumStream.getAudioTracks()[0].stop();
- };
- if (onRecording) onRecording(stopFunc);
- else setTimeout(stopFunc, 5000);
- });
- }
}
@observer
export class DocumentView extends DocComponent<DocumentViewProps>() {
public static ROOT_DIV = 'documentView-effectsWrapper';
+ // LinkFollower
+ public static FollowLink: (linkDoc: Opt<Doc>, sourceDoc: Doc, altKey: boolean) => boolean;
+ // selection funcs
+ public static DeselectAll: (except?: Doc) => void | undefined;
+ public static DeselectView: (dv: DocumentView | undefined) => void | undefined;
+ public static SelectView: (dv: DocumentView | undefined, extendSelection: boolean) => void | undefined;
+ public static Selected: () => DocumentView[];
+ public static SelectedDocs: () => Doc[];
+ public static SelectSchemaDoc: (doc: Doc, deselectAllFirst?: boolean) => void;
+ public static SelectedSchemaDoc: () => Opt<Doc>;
+ // view mgr funcs
+ public static activateTabView: (tabDoc: Doc) => boolean;
+ public static allViews: () => DocumentView[];
+ public static addView: (dv: DocumentView) => void | undefined;
+ public static removeView: (dv: DocumentView) => void | undefined;
+ public static addViewRenderedCb: (doc: Opt<Doc>, func: (dv: DocumentView) => any) => boolean;
+ public static getFirstDocumentView: (toFind: Doc) => DocumentView | undefined;
+ public static getDocumentView: (target: Doc | undefined, preferredCollection?: DocumentView) => Opt<DocumentView>;
+ public static getContextPath: (doc: Opt<Doc>, includeExistingViews?: boolean) => Doc[];
+ public static getLightboxDocumentView: (toFind: Doc) => Opt<DocumentView>;
+ public static showDocumentView: (targetDocView: DocumentView, options: FocusViewOptions) => Promise<void>;
+ public static showDocument: (
+ targetDoc: Doc, // document to display
+ optionsIn: FocusViewOptions, // options for how to navigate to target
+ finished?: (changed: boolean) => void // func called after focusing on target with flag indicating whether anything needed to be done.
+ ) => Promise<void>;
+ public static linkCommonAncestor: (link: Doc) => DocumentView | undefined;
+ // pin func
+ public static PinDoc: (docIn: Doc | Doc[], pinProps: PinProps) => void;
+ // gesture
+ public static DownDocView: DocumentView | undefined; // the first DocView that receives a pointerdown event. used by GestureOverlay to determine the doc a gesture should apply to.
+ // media playing
+ @observable public static CurrentlyPlaying: DocumentView[] = [];
+
public get displayName() { return 'DocumentView(' + (this.Document?.title??"") + ')'; } // prettier-ignore
public ContentRef = React.createRef<HTMLDivElement>();
private _htmlOverlayEffect: Opt<Doc>;
@@ -1138,14 +1100,14 @@ export class DocumentView extends DocComponent<DocumentViewProps>() {
componentDidMount() {
runInAction(() => this.Document[DocViews].add(this));
this._disposers.onViewMounted = reaction(() => ScriptCast(this.Document.onViewMounted)?.script?.run({ this: this.Document }).result, emptyFunction);
- !BoolCast(this.Document.dontRegisterView, this._props.dontRegisterView) && DocumentManager.Instance.AddView(this);
+ !BoolCast(this.Document.dontRegisterView, this._props.dontRegisterView) && DocumentView.addView(this);
}
componentWillUnmount() {
this._viewTimer && clearTimeout(this._viewTimer);
runInAction(() => this.Document[DocViews].delete(this));
Object.values(this._disposers).forEach(disposer => disposer?.());
- !BoolCast(this.Document.dontRegisterView, this._props.dontRegisterView) && DocumentManager.Instance.RemoveView(this);
+ !BoolCast(this.Document.dontRegisterView, this._props.dontRegisterView) && DocumentView.removeView(this);
}
public set IsSelected(val) { runInAction(() => { this._selected = val; }); } // prettier-ignore
@@ -1176,10 +1138,6 @@ export class DocumentView extends DocComponent<DocumentViewProps>() {
const xf = this.screenToContentsTransform().scale(this.nativeScaling).inverse();
const [[left, top], [right, bottom]] = [xf.transformPoint(0, 0), xf.transformPoint(this.panelWidth, this.panelHeight)];
- if (this._props.LayoutTemplateString?.includes(LinkAnchorBox.name)) {
- const docuBox = this.ContentDiv.getElementsByClassName('linkAnchorBox-cont');
- if (docuBox.length) return { ...docuBox[0].getBoundingClientRect(), transition: undefined };
- }
// transition is returned so that the bounds will 'update' at the end of an animated transition. This is needed by xAnchor in LinkBox
const transition = this.docViewPath().find((parent: DocumentView) => parent.DataTransition?.() || parent.ComponentView?.viewTransition?.());
return { left, top, right, bottom, transition: transition?.DataTransition?.() || transition?.ComponentView?.viewTransition?.() };
@@ -1289,7 +1247,7 @@ export class DocumentView extends DocComponent<DocumentViewProps>() {
if (checkResult) {
return Doc.UserDoc().defaultTextLayout;
}
- const view = SelectionManager.Views[0]?._props.renderDepth > 0 ? SelectionManager.Views[0] : undefined;
+ const view = DocumentView.Selected()[0]?._props.renderDepth > 0 ? DocumentView.Selected()[0] : undefined;
undoable(() => {
let tempDoc: Opt<Doc>;
if (view) {
@@ -1359,11 +1317,11 @@ export class DocumentView extends DocComponent<DocumentViewProps>() {
screenToLocalScale = () => this._props.ScreenToLocalTransform().Scale;
isSelected = () => this.IsSelected;
select = (extendSelection: boolean, focusSelection?: boolean) => {
- if (this.IsSelected && SelectionManager.Views.length > 1) SelectionManager.DeselectView(this);
+ if (this.IsSelected && DocumentView.Selected().length > 1) DocumentView.DeselectView(this);
else {
- SelectionManager.SelectView(this, extendSelection);
+ DocumentView.SelectView(this, extendSelection);
if (focusSelection) {
- DocumentManager.Instance.showDocument(this.Document, {
+ DocumentView.showDocument(this.Document, {
willZoomCentered: true,
zoomScale: 0.9,
zoomTime: 500,
@@ -1506,6 +1464,37 @@ export function returnEmptyDocViewList() {
return emptyPath;
}
+// eslint-disable-next-line default-param-last
+export function DocFocusOrOpen(docIn: Doc, optionsIn: FocusViewOptions = { willZoomCentered: true, zoomScale: 0, openLocation: OpenWhere.toggleRight }, containingDoc?: Doc) {
+ let doc = docIn;
+ const options = optionsIn;
+ const func = () => {
+ const cv = DocumentView.getDocumentView(containingDoc);
+ const dv = DocumentView.getDocumentView(doc, cv);
+ if (dv && (!containingDoc || dv.containerViewPath?.().lastElement()?.Document === containingDoc)) {
+ DocumentView.showDocumentView(dv, options).then(() => dv && Doc.linkFollowHighlight(dv.Document));
+ } else {
+ const container = DocCast(containingDoc ?? doc.embedContainer ?? Doc.BestEmbedding(doc));
+ const showDoc = !Doc.IsSystem(container) && !cv ? container : doc;
+ options.toggleTarget = undefined;
+ DocumentView.showDocument(showDoc, options, () => DocumentView.showDocument(doc, { ...options, openLocation: undefined })).then(() => {
+ const cvFound = DocumentView.getDocumentView(containingDoc);
+ const dvFound = DocumentView.getDocumentView(doc, cvFound);
+ dvFound && Doc.linkFollowHighlight(dvFound.Document);
+ });
+ }
+ };
+ if (Doc.IsDataProto(doc) && Doc.GetEmbeddings(doc).some(embed => embed.hidden && [AclAdmin, AclEdit].includes(GetEffectiveAcl(embed)))) {
+ doc = Doc.GetEmbeddings(doc).find(embed => embed.hidden && [AclAdmin, AclEdit].includes(GetEffectiveAcl(embed)))!;
+ }
+ if (doc.hidden) {
+ doc.hidden = false;
+ options.toggleTarget = false;
+ setTimeout(func);
+ } else func();
+}
+ScriptingGlobals.add(DocFocusOrOpen);
+
// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function deiconifyView(documentView: DocumentView) {
documentView.iconify();
@@ -1527,9 +1516,9 @@ ScriptingGlobals.add(function updateLinkCollection(linkCollection: Doc, linkSour
const collectedLinks = DocListCast(linkCollection[DocData].data);
let wid = NumCast(linkSource._width);
let embedding: Doc | undefined;
- const links = LinkManager.Links(linkSource);
+ const links = Doc.Links(linkSource);
links.forEach(link => {
- const other = LinkManager.getOppositeAnchor(link, linkSource);
+ const other = Doc.getOppositeAnchor(link, linkSource);
const otherdoc = DocCast(other?.annotationOn ?? other);
if (otherdoc && !collectedLinks?.some(d => Doc.AreProtosEqual(d, otherdoc))) {
embedding = Doc.MakeEmbedding(otherdoc);
diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
index 8d1617e66..5e3bb9fec 100644
--- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx
+++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
@@ -17,7 +17,7 @@ import { ContextMenu } from '../../ContextMenu';
import { ViewBoxBaseComponent } from '../../DocComponent';
import { EditableView } from '../../EditableView';
import { SelectedDocView } from '../../selectedDoc';
-import { StyleProp } from '../../StyleProvider';
+import { StyleProp } from '../../StyleProp';
import { FieldView, FieldViewProps } from '../FieldView';
import { OpenWhere } from '../OpenWhere';
import './FontIconBox.scss';
@@ -116,7 +116,7 @@ export class FontIconBox extends ViewBoxBaseComponent<ButtonProps>() {
default: type = 'slider';
break;
} // prettier-ignore
- const numScript = (value?: number) => ScriptCast(this.Document.script).script.run({ this: this.Document, self: this.Document, value, _readOnly_: value === undefined });
+ const numScript = (value?: number) => ScriptCast(this.Document.script).script.run({ this: this.Document, value, _readOnly_: value === undefined });
const color = this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.Color);
// Script for checking the outcome of the toggle
const checkResult = Number(Number(numScript().result ?? 0).toPrecision(NumCast(this.dataDoc.numPrecision, 3)));
@@ -142,7 +142,7 @@ export class FontIconBox extends ViewBoxBaseComponent<ButtonProps>() {
setupMoveUpEvents(
this,
e,
- () => ScriptCast(this.Document.onDragScript)?.script.run({ this: this.Document, self: this.Document, value: { doc: value, e } }).result,
+ () => ScriptCast(this.Document.onDragScript)?.script.run({ this: this.Document, value: { doc: value, e } }).result,
emptyFunction,
emptyFunction
); // prettier-ignore
@@ -162,7 +162,7 @@ export class FontIconBox extends ViewBoxBaseComponent<ButtonProps>() {
const isViewDropdown = script?.script.originalScript.startsWith('{ return setView');
if (isViewDropdown) {
const selected = Array.from(script?.script.run({ _readOnly_: true }).result) as Doc[];
- // const selected = SelectionManager.Docs;
+ // const selected = DocumentView.SelectedDocs();
if (selected.lastElement()) {
if (StrCast(selected.lastElement().type) === DocumentType.COL) {
text = StrCast(selected.lastElement()._type_collection);
@@ -190,7 +190,7 @@ export class FontIconBox extends ViewBoxBaseComponent<ButtonProps>() {
}
noviceList = [CollectionViewType.Freeform, CollectionViewType.Schema, CollectionViewType.Carousel3D, CollectionViewType.Stacking, CollectionViewType.NoteTaking];
} else {
- text = script?.script.run({ this: this.Document, self: this.Document, value: '', _readOnly_: true }).result;
+ text = script?.script.run({ this: this.Document, value: '', _readOnly_: true }).result;
// text = StrCast((RichTextMenu.Instance?.TextView?.EditorView ? RichTextMenu.Instance : Doc.UserDoc()).fontFamily);
getStyle = (val: string) => ({ fontFamily: val });
}
@@ -208,7 +208,7 @@ export class FontIconBox extends ViewBoxBaseComponent<ButtonProps>() {
return (
<Dropdown
selectedVal={text}
- setSelectedVal={undoable(value => script.script.run({ this: this.Document, self: this.Document, value }), `dropdown select ${this.label}`)}
+ setSelectedVal={undoable(value => script.script.run({ this: this.Document, value }), `dropdown select ${this.label}`)}
color={SnappingManager.userColor}
background={SnappingManager.userVariantColor}
type={Type.TERT}
@@ -232,17 +232,17 @@ export class FontIconBox extends ViewBoxBaseComponent<ButtonProps>() {
*/
@computed get colorButton() {
const color = this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.Color);
- const curColor = this.colorScript?.script.run({ this: this.Document, self: this.Document, value: undefined, _readOnly_: true }).result ?? 'transparent';
+ const curColor = this.colorScript?.script.run({ this: this.Document, value: undefined, _readOnly_: true }).result ?? 'transparent';
const tooltip: string = StrCast(this.Document.toolTip);
return (
<ColorPicker
setSelectedColor={value => {
if (!this.colorBatch) this.colorBatch = UndoManager.StartBatch(`Set ${tooltip} color`);
- this.colorScript?.script.run({ this: this.Document, self: this.Document, value: value, _readOnly_: false });
+ this.colorScript?.script.run({ this: this.Document, value: value, _readOnly_: false });
}}
setFinalColor={value => {
- this.colorScript?.script.run({ this: this.Document, self: this.Document, value: value, _readOnly_: false });
+ this.colorScript?.script.run({ this: this.Document, value: value, _readOnly_: false });
this.colorBatch?.end();
this.colorBatch = undefined;
}}
@@ -262,7 +262,7 @@ export class FontIconBox extends ViewBoxBaseComponent<ButtonProps>() {
const tooltip: string = StrCast(this.Document.toolTip);
// const script = ScriptCast(this.Document.onClick);
- // const toggleStatus = script ? script.script.run({ this: this.Document, self: this.Document, value: undefined, _readOnly_: true }).result : false;
+ // const toggleStatus = script ? script.script.run({ this: this.Document, value: undefined, _readOnly_: true }).result : false;
// Colors
const color = this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.Color);
const items = DocListCast(this.dataDoc.data);
@@ -278,10 +278,10 @@ export class FontIconBox extends ViewBoxBaseComponent<ButtonProps>() {
tooltip: StrCast(item.toolTip),
val: StrCast(item.toolType),
}))}
- selectedVal={StrCast(items.find(itemDoc => ScriptCast(itemDoc.onClick).script.run({ this: itemDoc, self: itemDoc, value: undefined, _readOnly_: true }).result)?.toolType)}
+ selectedVal={StrCast(items.find(itemDoc => ScriptCast(itemDoc.onClick).script.run({ this: itemDoc, value: undefined, _readOnly_: true }).result)?.toolType)}
setSelectedVal={(val: string | number) => {
const itemDoc = items.find(item => item.toolType === val);
- itemDoc && ScriptCast(itemDoc.onClick).script.run({ this: itemDoc, self: itemDoc, value: val, _readOnly_: false });
+ itemDoc && ScriptCast(itemDoc.onClick).script.run({ this: itemDoc, value: val, _readOnly_: false });
}}
/>
);
@@ -296,7 +296,7 @@ export class FontIconBox extends ViewBoxBaseComponent<ButtonProps>() {
const script = ScriptCast(this.Document.onClick);
const double = ScriptCast(this.Document.onDoubleClick);
- const toggleStatus = script?.script.run({ this: this.Document, self: this.Document, value: undefined, _readOnly_: true }).result ?? false;
+ const toggleStatus = script?.script.run({ this: this.Document, value: undefined, _readOnly_: true }).result ?? false;
// Colors
const color = this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.Color);
// const backgroundColor = this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.BackgroundColor);
@@ -319,8 +319,8 @@ export class FontIconBox extends ViewBoxBaseComponent<ButtonProps>() {
returnTrue,
emptyFunction,
action((clickEv, doubleTap) => {
- (!doubleTap || !double) && script?.script.run({ this: this.Document, self: this.Document, value: !toggleStatus, _readOnly_: false });
- doubleTap && double?.script.run({ this: this.Document, self: this.Document, value: !toggleStatus, _readOnly_: false });
+ (!doubleTap || !double) && script?.script.run({ this: this.Document, value: !toggleStatus, _readOnly_: false });
+ doubleTap && double?.script.run({ this: this.Document, value: !toggleStatus, _readOnly_: false });
this._hackToRecompute += 1;
})
)
@@ -341,15 +341,15 @@ export class FontIconBox extends ViewBoxBaseComponent<ButtonProps>() {
@computed get editableText() {
const script = ScriptCast(this.Document.script);
- const checkResult = script?.script.run({ this: this.Document, self: this.Document, value: '', _readOnly_: true }).result;
+ const checkResult = script?.script.run({ this: this.Document, value: '', _readOnly_: true }).result;
- const setValue = (value: string): boolean => script?.script.run({ this: this.Document, self: this.Document, value, _readOnly_: false }).result;
+ const setValue = (value: string): boolean => script?.script.run({ this: this.Document, value, _readOnly_: false }).result;
return (
<div className="menuButton editableText">
<FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon="lock" />
<div style={{ width: 'calc(100% - .875em)', paddingLeft: '4px' }}>
- <EditableView GetValue={() => script?.script.run({ this: this.Document, self: this.Document, value: '', _readOnly_: true }).result} SetValue={setValue} oneLine contents={checkResult} />
+ <EditableView GetValue={() => script?.script.run({ this: this.Document, value: '', _readOnly_: true }).result} SetValue={setValue} oneLine contents={checkResult} />
</div>
</div>
);
@@ -358,7 +358,7 @@ export class FontIconBox extends ViewBoxBaseComponent<ButtonProps>() {
renderButton = () => {
const color = this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.Color);
const tooltip = StrCast(this.Document.toolTip);
- const scriptFunc = () => ScriptCast(this.Document.onClick)?.script.run({ this: this.Document, self: this.Document, _readOnly_: false });
+ const scriptFunc = () => ScriptCast(this.Document.onClick)?.script.run({ this: this.Document, _readOnly_: false });
const btnProps = { tooltip, icon: this.Icon(color)!, label: this.label };
// prettier-ignore
switch (this.type) {
diff --git a/src/client/views/nodes/FunctionPlotBox.tsx b/src/client/views/nodes/FunctionPlotBox.tsx
index f32d39aaf..3d1bd7563 100644
--- a/src/client/views/nodes/FunctionPlotBox.tsx
+++ b/src/client/views/nodes/FunctionPlotBox.tsx
@@ -2,7 +2,7 @@ import functionPlot from 'function-plot';
import { computed, makeObservable, reaction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { DocListCast } from '../../../fields/Doc';
+import { Doc, DocListCast } from '../../../fields/Doc';
import { List } from '../../../fields/List';
import { listSpec } from '../../../fields/Schema';
import { Cast, StrCast } from '../../../fields/Types';
@@ -11,7 +11,6 @@ import { DocUtils } from '../../documents/DocUtils';
import { DocumentType } from '../../documents/DocumentTypes';
import { Docs } from '../../documents/Documents';
import { DragManager } from '../../util/DragManager';
-import { LinkManager } from '../../util/LinkManager';
import { undoBatch } from '../../util/UndoManager';
import { ViewBoxAnnotatableComponent } from '../DocComponent';
import { PinDocView, PinProps } from '../PinFuncs';
@@ -49,8 +48,8 @@ export class FunctionPlotBox extends ViewBoxAnnotatableComponent<FieldViewProps>
return anchor;
};
@computed get graphFuncs() {
- const links = LinkManager.Instance.getAllRelatedLinks(this.Document)
- .map(d => LinkManager.getOppositeAnchor(d, this.Document))
+ const links = Doc.Links(this.Document)
+ .map(d => Doc.getOppositeAnchor(d, this.Document))
.filter(d => d)
.map(d => d!);
const funcs = links.concat(DocListCast(this.dataDoc[this.fieldKey])).map(doc =>
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index d317f46bb..3945da104 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -19,7 +19,6 @@ import { Docs } from '../../documents/Documents';
import { DocumentType } from '../../documents/DocumentTypes';
import { DocUtils } from '../../documents/DocUtils';
import { Networking } from '../../Network';
-import { DocumentManager } from '../../util/DocumentManager';
import { DragManager } from '../../util/DragManager';
import { undoBatch } from '../../util/UndoManager';
import { CollectionFreeFormView } from '../collections/collectionFreeForm/CollectionFreeFormView';
@@ -30,7 +29,8 @@ import { MarqueeAnnotator } from '../MarqueeAnnotator';
import { OverlayView } from '../OverlayView';
import { AnchorMenu } from '../pdf/AnchorMenu';
import { PinDocView, PinProps } from '../PinFuncs';
-import { StyleProp } from '../StyleProvider';
+import { StyleProp } from '../StyleProp';
+import { DocumentView } from './DocumentView';
import { FieldView, FieldViewProps } from './FieldView';
import { FocusViewOptions } from './FocusViewOptions';
import './ImageBox.scss';
@@ -254,7 +254,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() impl
cropping.y = NumCast(this.Document.y);
this._props.addDocTab(cropping, OpenWhere.inParent);
}
- DocumentManager.Instance.AddViewRenderedCb(cropping, dv => setTimeout(() => (dv.ComponentView as ImageBox).setNativeSize(), 200));
+ DocumentView.addViewRenderedCb(cropping, dv => setTimeout(() => (dv.ComponentView as ImageBox).setNativeSize(), 200));
this._props.bringToFront?.(cropping);
return cropping;
};
diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx
index 46bb16e50..cd591fa42 100644
--- a/src/client/views/nodes/KeyValueBox.tsx
+++ b/src/client/views/nodes/KeyValueBox.tsx
@@ -59,6 +59,8 @@ export class KeyValueBox extends ObservableReactComponent<FieldViewProps> {
get fieldDocToLayout() {
return DocCast(this._props.Document);
}
+ isUnstyledView = returnTrue; // used by style provider via ViewBoxInterface
+ dontRegisterView = returnTrue; // used by ViewBoxInterface
@action
onEnterKey = (e: React.KeyboardEvent): void => {
@@ -111,7 +113,7 @@ export class KeyValueBox extends ObservableReactComponent<FieldViewProps> {
if (setResult) setResult?.(value);
else target[key] = field;
};
- const res = script.run({ this: Doc.Layout(doc), self: doc, _setCacheResult_ }, console.log);
+ const res = script.run({ this: Doc.Layout(doc), _setCacheResult_ }, console.log);
if (!res.success) {
if (key) target[key] = script.originalScript;
return false;
diff --git a/src/client/views/nodes/LabelBox.tsx b/src/client/views/nodes/LabelBox.tsx
index 4dec3506c..f80ff5f94 100644
--- a/src/client/views/nodes/LabelBox.tsx
+++ b/src/client/views/nodes/LabelBox.tsx
@@ -13,7 +13,7 @@ import { ContextMenu } from '../ContextMenu';
import { ContextMenuProps } from '../ContextMenuItem';
import { ViewBoxBaseComponent } from '../DocComponent';
import { PinDocView, PinProps } from '../PinFuncs';
-import { StyleProp } from '../StyleProvider';
+import { StyleProp } from '../StyleProp';
import { FieldView, FieldViewProps } from './FieldView';
import BigText from './LabelBigText';
import './LabelBox.scss';
diff --git a/src/client/views/nodes/LinkAnchorBox.scss b/src/client/views/nodes/LinkAnchorBox.scss
deleted file mode 100644
index caff369df..000000000
--- a/src/client/views/nodes/LinkAnchorBox.scss
+++ /dev/null
@@ -1,34 +0,0 @@
-.linkAnchorBox-cont,
-.linkAnchorBox-cont-small {
- cursor: default;
- position: absolute;
- width: 15;
- height: 15;
- border-radius: 20px;
- user-select: none;
- pointer-events: all;
-
- .linkAnchorBox-linkCloser {
- position: absolute;
- width: 18;
- height: 18;
- background: rgb(219, 21, 21);
- top: -1px;
- left: -1px;
- border-radius: 5px;
- display: flex;
- justify-content: center;
- align-items: center;
- padding-left: 2px;
- padding-top: 1px;
- }
- .linkAnchorBox-button {
- position: relative;
- display: inline-block;
- }
-}
-
-.linkAnchorBox-cont-small {
- width: 5px;
- height: 5px;
-} \ No newline at end of file
diff --git a/src/client/views/nodes/LinkAnchorBox.tsx b/src/client/views/nodes/LinkAnchorBox.tsx
deleted file mode 100644
index d43241de0..000000000
--- a/src/client/views/nodes/LinkAnchorBox.tsx
+++ /dev/null
@@ -1,118 +0,0 @@
-import { action, computed, makeObservable } from 'mobx';
-import { observer } from 'mobx-react';
-import * as React from 'react';
-import { setupMoveUpEvents } from '../../../ClientUtils';
-import { Utils, emptyFunction } from '../../../Utils';
-import { Doc } from '../../../fields/Doc';
-import { NumCast, StrCast } from '../../../fields/Types';
-import { TraceMobx } from '../../../fields/util';
-import { DragManager } from '../../util/DragManager';
-import { dropActionType } from '../../util/DropActionTypes';
-import { LinkFollower } from '../../util/LinkFollower';
-import { SelectionManager } from '../../util/SelectionManager';
-import { ViewBoxBaseComponent } from '../DocComponent';
-import { StyleProp } from '../StyleProvider';
-import { FieldView, FieldViewProps } from './FieldView';
-import './LinkAnchorBox.scss';
-import { LinkInfo } from './LinkDocPreview';
-
-const { MEDIUM_GRAY } = require('../global/globalCssVariables.module.scss'); // prettier-ignore
-
-@observer
-export class LinkAnchorBox extends ViewBoxBaseComponent<FieldViewProps>() {
- public static LayoutString(fieldKey: string) {
- return FieldView.LayoutString(LinkAnchorBox, fieldKey);
- }
- _doubleTap = false;
- _lastTap: number = 0;
- _ref = React.createRef<HTMLDivElement>();
- _isOpen = false;
- _timeout: NodeJS.Timeout | undefined;
-
- constructor(props: FieldViewProps) {
- super(props);
- makeObservable(this);
- }
-
- componentDidMount() {
- this._props.setContentViewBox?.(this);
- }
-
- @computed get linkSource() {
- return this.DocumentView?.().containerViewPath?.().lastElement().Document; // this._props.styleProvider?.(this.dataDoc, this._props, StyleProp.LinkSource);
- }
-
- onPointerDown = (e: React.PointerEvent) => {
- const { linkSource } = this;
- linkSource &&
- setupMoveUpEvents(this, e, this.onPointerMove, emptyFunction, (clickEv, doubleTap) => {
- if (doubleTap) LinkFollower.FollowLink(this.Document, linkSource, false);
- else this._props.select(false);
- });
- };
- onPointerMove = action((e: PointerEvent) => {
- const cdiv = this._ref?.current?.parentElement;
- if (!this._isOpen && cdiv) {
- const bounds = cdiv.getBoundingClientRect();
- const pt = Utils.getNearestPointInPerimeter(bounds.left, bounds.top, bounds.width, bounds.height, e.clientX, e.clientY);
- const separation = Math.sqrt((pt[0] - e.clientX) * (pt[0] - e.clientX) + (pt[1] - e.clientY) * (pt[1] - e.clientY));
- if (separation > 100) {
- const dragData = new DragManager.DocumentDragData([this.Document]);
- dragData.dropAction = dropActionType.embed;
- dragData.dropPropertiesToRemove = ['link_anchor_1_x', 'link_anchor_1_y', 'link_anchor_2_x', 'link_anchor_2_y', 'onClick'];
- DragManager.StartDocumentDrag([this._ref.current!], dragData, pt[0], pt[1]);
- return true;
- }
- this.layoutDoc[this.fieldKey + '_x'] = ((pt[0] - bounds.left) / bounds.width) * 100;
- this.layoutDoc[this.fieldKey + '_y'] = ((pt[1] - bounds.top) / bounds.height) * 100;
- this.layoutDoc.link_autoMoveAnchors = false;
- }
- return false;
- });
-
- specificContextMenu = (): void => {};
-
- render() {
- TraceMobx();
- const small = this._props.PanelWidth() <= 1; // this happens when rendered in a treeView
- const x = NumCast(this.layoutDoc[this.fieldKey + '_x'], 100);
- const y = NumCast(this.layoutDoc[this.fieldKey + '_y'], 100);
- const background = this._props.styleProvider?.(this.dataDoc, this._props, StyleProp.BackgroundColor + ':anchor');
- const anchor = this.fieldKey === 'link_anchor_1' ? 'link_anchor_2' : 'link_anchor_1';
- const anchorScale = !this.dataDoc[this.fieldKey + '_useSmallAnchor'] && (x === 0 || x === 100 || y === 0 || y === 100) ? 1 : 0.25;
- const targetTitle = StrCast((this.dataDoc[anchor] as Doc)?.title);
- const selView = SelectionManager.Views.lastElement()?._props.LayoutTemplateString?.includes('link_anchor_1')
- ? 'link_anchor_1'
- : SelectionManager.Views.lastElement()?._props.LayoutTemplateString?.includes('link_anchor_2')
- ? 'link_anchor_2'
- : '';
- return (
- <div
- ref={this._ref}
- title={targetTitle}
- className={`linkAnchorBox-cont${small ? '-small' : ''}`}
- onPointerEnter={e =>
- LinkInfo.SetLinkInfo({
- DocumentView: this.DocumentView,
- styleProvider: this._props.styleProvider,
- linkSrc: this.linkSource,
- linkDoc: this.Document,
- showHeader: true,
- location: [e.clientX, e.clientY + 20],
- noPreview: false,
- })
- }
- onPointerDown={this.onPointerDown}
- onContextMenu={this.specificContextMenu}
- style={{
- border: selView && this.dataDoc[selView] === this.dataDoc[this.fieldKey] ? `solid ${MEDIUM_GRAY} 2px` : undefined,
- background,
- left: `calc(${x}% - ${small ? 2.5 : 7.5}px)`,
- top: `calc(${y}% - ${small ? 2.5 : 7.5}px)`,
- transform: `scale(${anchorScale})`,
- cursor: 'grab',
- }}
- />
- );
- }
-}
diff --git a/src/client/views/nodes/LinkBox.tsx b/src/client/views/nodes/LinkBox.tsx
index 559b1fcae..6caa38a7f 100644
--- a/src/client/views/nodes/LinkBox.tsx
+++ b/src/client/views/nodes/LinkBox.tsx
@@ -13,12 +13,11 @@ import { TraceMobx } from '../../../fields/util';
import { emptyFunction } from '../../../Utils';
import { Docs } from '../../documents/Documents';
import { DocumentType } from '../../documents/DocumentTypes';
-import { DocumentManager } from '../../util/DocumentManager';
import { SnappingManager } from '../../util/SnappingManager';
import { ViewBoxBaseComponent } from '../DocComponent';
import { EditableView } from '../EditableView';
import { LightboxView } from '../LightboxView';
-import { StyleProp } from '../StyleProvider';
+import { StyleProp } from '../StyleProp';
import { ComparisonBox } from './ComparisonBox';
import { DocumentView } from './DocumentView';
import { FieldView, FieldViewProps } from './FieldView';
@@ -43,7 +42,7 @@ export class LinkBox extends ViewBoxBaseComponent<FieldViewProps>() {
anchor = (which: number) => {
const anch = DocCast(this.dataDoc['link_anchor_' + which]);
const anchor = anch?.layout_unrendered ? DocCast(anch.annotationOn) : anch;
- return DocumentManager.Instance.getDocumentView(anchor, this.DocumentView?.().containerViewPath?.().lastElement());
+ return DocumentView.getDocumentView(anchor, this.DocumentView?.().containerViewPath?.().lastElement());
};
_hackToSeeIfDeleted: any;
componentWillUnmount() {
diff --git a/src/client/views/nodes/LinkDescriptionPopup.tsx b/src/client/views/nodes/LinkDescriptionPopup.tsx
index 23cb25962..ff95f8547 100644
--- a/src/client/views/nodes/LinkDescriptionPopup.tsx
+++ b/src/client/views/nodes/LinkDescriptionPopup.tsx
@@ -2,16 +2,17 @@ import { action, makeObservable, observable, reaction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import { DocData } from '../../../fields/DocSymbols';
+import { StrCast } from '../../../fields/Types';
import { LinkManager } from '../../util/LinkManager';
import './LinkDescriptionPopup.scss';
import { TaskCompletionBox } from './TaskCompletedBox';
-import { StrCast } from '../../../fields/Types';
@observer
export class LinkDescriptionPopup extends React.Component<{}> {
// eslint-disable-next-line no-use-before-define
public static Instance: LinkDescriptionPopup;
@observable public display: boolean = false;
+ // eslint-disable-next-line react/no-unused-class-component-methods
@observable public showDescriptions: string = 'ON';
@observable public popupX: number = 700;
@observable public popupY: number = 350;
diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx
index 0936acc15..508008569 100644
--- a/src/client/views/nodes/LinkDocPreview.tsx
+++ b/src/client/views/nodes/LinkDocPreview.tsx
@@ -11,12 +11,10 @@ import { Cast, DocCast, NumCast, PromiseValue, StrCast } from '../../../fields/T
import { DocServer } from '../../DocServer';
import { DocumentType } from '../../documents/DocumentTypes';
import { Docs } from '../../documents/Documents';
-import { DocumentManager } from '../../util/DocumentManager';
import { DragManager } from '../../util/DragManager';
-import { LinkFollower } from '../../util/LinkFollower';
import { LinkManager } from '../../util/LinkManager';
import { SearchUtil } from '../../util/SearchUtil';
-import { SettingsManager } from '../../util/SettingsManager';
+import { SnappingManager } from '../../util/SnappingManager';
import { Transform } from '../../util/Transform';
import { ObservableReactComponent } from '../ObservableReactComponent';
import { DocumentView } from './DocumentView';
@@ -134,17 +132,17 @@ export class LinkDocPreview extends ObservableReactComponent<LinkDocPreviewProps
const anchorDoc = anchorDocId ? PromiseValue(DocCast(DocServer.GetCachedRefField(anchorDocId) ?? DocServer.GetRefField(anchorDocId))) : undefined;
anchorDoc?.then?.(
action(anchor => {
- if (anchor instanceof Doc && LinkManager.Links(anchor).length) {
- this._linkDoc = this._linkDoc ?? LinkManager.Links(anchor)[0];
+ if (anchor instanceof Doc && Doc.Links(anchor).length) {
+ this._linkDoc = this._linkDoc ?? Doc.Links(anchor)[0];
const automaticLink = this._linkDoc.link_relationship === LinkManager.AutoKeywords;
if (automaticLink) {
// automatic links specify the target in the link info, not the source
const linkTarget = anchor;
- this._linkSrc = LinkManager.getOppositeAnchor(this._linkDoc, linkTarget);
+ this._linkSrc = Doc.getOppositeAnchor(this._linkDoc, linkTarget);
this._markerTargetDoc = this._targetDoc = linkTarget;
} else {
this._linkSrc = anchor;
- const linkTarget = LinkManager.getOppositeAnchor(this._linkDoc, this._linkSrc);
+ const linkTarget = Doc.getOppositeAnchor(this._linkDoc, this._linkSrc);
this._markerTargetDoc = linkTarget;
this._targetDoc = /* linkTarget?.type === DocumentType.MARKER && */ linkTarget?.annotationOn ? Cast(linkTarget.annotationOn, Doc, null) ?? linkTarget : linkTarget;
}
@@ -169,8 +167,8 @@ export class LinkDocPreview extends ObservableReactComponent<LinkDocPreviewProps
LinkManager.Instance.currentLink = this._linkDoc;
LinkManager.Instance.currentLinkAnchor = this._linkSrc;
this._props.DocumentView?.().select(false);
- if ((SettingsManager.Instance.propertiesWidth ?? 0) < 100) {
- SettingsManager.Instance.propertiesWidth = 250;
+ if ((SnappingManager.PropertiesWidth ?? 0) < 100) {
+ SnappingManager.SetPropertiesWidth(250);
}
})
);
@@ -196,13 +194,13 @@ export class LinkDocPreview extends ObservableReactComponent<LinkDocPreviewProps
followLink = () => {
LinkInfo.Clear();
if (this._linkDoc && this._linkSrc) {
- LinkFollower.FollowLink(this._linkDoc, this._linkSrc, false);
+ DocumentView.FollowLink(this._linkDoc, this._linkSrc, false);
} else if (this._props.hrefs?.length) {
const webDoc =
Array.from(SearchUtil.SearchCollection(Doc.MyFilesystem, this._props.hrefs[0], false).keys())
.filter(doc => doc.type === DocumentType.WEB)
.lastElement() ?? Docs.Create.WebDocument(this._props.hrefs[0], { title: this._props.hrefs[0], _nativeWidth: 850, _width: 200, _height: 400, data_useCors: true });
- DocumentManager.Instance.showDocument(webDoc, {
+ DocumentView.showDocument(webDoc, {
openLocation: OpenWhere.lightbox,
willPan: true,
zoomTime: 500,
@@ -229,7 +227,7 @@ export class LinkDocPreview extends ObservableReactComponent<LinkDocPreviewProps
};
@computed get previewHeader() {
return !this._linkDoc || !this._markerTargetDoc || !this._targetDoc || !this._linkSrc ? null : (
- <div className="linkDocPreview-info" style={{ background: SettingsManager.userBackgroundColor }}>
+ <div className="linkDocPreview-info" style={{ background: SnappingManager.userBackgroundColor }}>
<div className="linkDocPreview-buttonBar" style={{ float: 'left' }}>
<Tooltip title={<div className="dash-tooltip">Edit Link</div>} placement="top">
<div className="linkDocPreview-button" onPointerDown={this.editLink}>
@@ -282,7 +280,7 @@ export class LinkDocPreview extends ObservableReactComponent<LinkDocPreviewProps
) : (
<DocumentView
ref={r => {
- const targetanchor = this._linkDoc && this._linkSrc && LinkManager.getOppositeAnchor(this._linkDoc, this._linkSrc);
+ const targetanchor = this._linkDoc && this._linkSrc && Doc.getOppositeAnchor(this._linkDoc, this._linkSrc);
targetanchor && this._targetDoc !== targetanchor && r?._props.focus?.(targetanchor, {});
}}
Document={this._targetDoc!}
@@ -325,7 +323,7 @@ export class LinkDocPreview extends ObservableReactComponent<LinkDocPreviewProps
className="linkDocPreview"
ref={this._linkDocRef}
onPointerDown={this.followLinkPointerDown}
- style={{ borderColor: SettingsManager.userColor, left: this._props.location[0], top: this._props.location[1], width: this.width() + borders, height: this.height() + borders + (this._props.showHeader ? 37 : 0) }}>
+ style={{ borderColor: SnappingManager.userColor, left: this._props.location[0], top: this._props.location[1], width: this.width() + borders, height: this.height() + borders + (this._props.showHeader ? 37 : 0) }}>
{this.docPreview}
</div>
);
diff --git a/src/client/views/nodes/LoadingBox.tsx b/src/client/views/nodes/LoadingBox.tsx
index aa89398f3..5f343bdfe 100644
--- a/src/client/views/nodes/LoadingBox.tsx
+++ b/src/client/views/nodes/LoadingBox.tsx
@@ -6,12 +6,11 @@ import { Doc } from '../../../fields/Doc';
import { Id } from '../../../fields/FieldSymbols';
import { StrCast } from '../../../fields/Types';
import { Networking } from '../../Network';
-import { DocumentManager } from '../../util/DocumentManager';
+import { DocumentType } from '../../documents/DocumentTypes';
+import { Docs } from '../../documents/Documents';
import { ViewBoxAnnotatableComponent } from '../DocComponent';
import { FieldView, FieldViewProps } from './FieldView';
import './LoadingBox.scss';
-import { DocumentType } from '../../documents/DocumentTypes';
-import { Docs } from '../../documents/Documents';
/**
* LoadingBox Class represents a placeholder doc for documents that are currently
@@ -39,25 +38,11 @@ export class LoadingBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
public static LayoutString(fieldKey: string) {
return FieldView.LayoutString(LoadingBox, fieldKey);
}
- // removes from currently loading display
- public static removeCurrentlyLoading(doc: Doc) {
- if (DocumentManager.Instance.CurrentlyLoading) {
- const index = DocumentManager.Instance.CurrentlyLoading.indexOf(doc);
- runInAction(() => index !== -1 && DocumentManager.Instance.CurrentlyLoading.splice(index, 1));
- }
- }
-
- // adds doc to currently loading display
- public static addCurrentlyLoading(doc: Doc) {
- if (DocumentManager.Instance.CurrentlyLoading.indexOf(doc) === -1) {
- runInAction(() => DocumentManager.Instance.CurrentlyLoading.push(doc));
- }
- }
_timer: any;
@observable progress = '';
componentDidMount() {
- if (!DocumentManager.Instance.CurrentlyLoading?.includes(this.Document)) {
+ if (!Doc.CurrentlyLoading?.includes(this.Document)) {
this.Document.loadingError = 'Upload interrupted, please try again';
} else {
const updateFunc = async () => {
diff --git a/src/client/views/nodes/MapBox/DirectionsAnchorMenu.tsx b/src/client/views/nodes/MapBox/DirectionsAnchorMenu.tsx
index f176317d2..b8fd8ac6a 100644
--- a/src/client/views/nodes/MapBox/DirectionsAnchorMenu.tsx
+++ b/src/client/views/nodes/MapBox/DirectionsAnchorMenu.tsx
@@ -8,9 +8,9 @@ import { returnFalse } from '../../../../ClientUtils';
import { unimplementedFunction } from '../../../../Utils';
import { Doc, Opt } from '../../../../fields/Doc';
import { NumCast, StrCast } from '../../../../fields/Types';
-import { SelectionManager } from '../../../util/SelectionManager';
import { SettingsManager } from '../../../util/SettingsManager';
import { AntimodeMenu, AntimodeMenuProps } from '../../AntimodeMenu';
+import { DocumentView } from '../DocumentView';
@observer
export class DirectionsAnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
@@ -56,7 +56,7 @@ export class DirectionsAnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
componentDidMount() {
this._disposer = reaction(
- () => SelectionManager.Views.slice(),
+ () => DocumentView.Selected().slice(),
() => DirectionsAnchorMenu.Instance.fadeOut(true)
);
}
diff --git a/src/client/views/nodes/MapBox/MapAnchorMenu.tsx b/src/client/views/nodes/MapBox/MapAnchorMenu.tsx
index 174511e1a..103a35434 100644
--- a/src/client/views/nodes/MapBox/MapAnchorMenu.tsx
+++ b/src/client/views/nodes/MapBox/MapAnchorMenu.tsx
@@ -13,9 +13,9 @@ import { unimplementedFunction } from '../../../../Utils';
import { Doc, Opt } from '../../../../fields/Doc';
import { NumCast, StrCast } from '../../../../fields/Types';
import { CalendarManager } from '../../../util/CalendarManager';
-import { SelectionManager } from '../../../util/SelectionManager';
import { SettingsManager } from '../../../util/SettingsManager';
import { AntimodeMenu, AntimodeMenuProps } from '../../AntimodeMenu';
+import { DocumentView } from '../DocumentView';
import './MapAnchorMenu.scss';
import { MapboxApiUtility, TransportationType } from './MapboxApiUtility';
import { MarkerIcons } from './MarkerIcons';
@@ -126,7 +126,7 @@ export class MapAnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
componentDidMount() {
this._disposer = reaction(
- () => SelectionManager.Views.slice(),
+ () => DocumentView.Selected().slice(),
() => MapAnchorMenu.Instance.fadeOut(true)
);
}
diff --git a/src/client/views/nodes/MapBox/MapBox.tsx b/src/client/views/nodes/MapBox/MapBox.tsx
index 50831f8ea..ac8010f11 100644
--- a/src/client/views/nodes/MapBox/MapBox.tsx
+++ b/src/client/views/nodes/MapBox/MapBox.tsx
@@ -21,9 +21,7 @@ import { DocCast, NumCast, StrCast, toList } from '../../../../fields/Types';
import { DocUtils } from '../../../documents/DocUtils';
import { DocumentType } from '../../../documents/DocumentTypes';
import { Docs } from '../../../documents/Documents';
-import { DocumentManager } from '../../../util/DocumentManager';
import { DragManager } from '../../../util/DragManager';
-import { LinkManager } from '../../../util/LinkManager';
import { UndoManager, undoable } from '../../../util/UndoManager';
import { ViewBoxAnnotatableComponent, ViewBoxInterface } from '../../DocComponent';
import { PinDocView, PinProps } from '../../PinFuncs';
@@ -249,7 +247,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
if (existingPin) {
setTimeout(() => {
// we use a timeout in case this is called from the sidebar which may have just added a link that hasn't made its way into th elink manager yet
- if (!LinkManager.Instance.getAllRelatedLinks(doc).some(link => DocCast(link.link_anchor_1)?.mapPin === existingPin || DocCast(link.link_anchor_2)?.mapPin === existingPin)) {
+ if (!Doc.Links(doc).some(link => DocCast(link.link_anchor_1)?.mapPin === existingPin || DocCast(link.link_anchor_2)?.mapPin === existingPin)) {
const anchor = this.getAnchor(true, undefined, existingPin);
anchor && DocUtils.MakeLink(anchor, doc, { link_relationship: 'link to map location' });
doc.latitude = existingPin?.latitude;
@@ -438,7 +436,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
options.didMove = true;
}
return new Promise<Opt<DocumentView>>(res => {
- DocumentManager.Instance.AddViewRenderedCb(doc, dv => res(dv));
+ DocumentView.addViewRenderedCb(doc, dv => res(dv));
});
};
diff --git a/src/client/views/nodes/MapBox/MapBox2.tsx b/src/client/views/nodes/MapBox/MapBox2.tsx
index 9825824bd..7697fd295 100644
--- a/src/client/views/nodes/MapBox/MapBox2.tsx
+++ b/src/client/views/nodes/MapBox/MapBox2.tsx
@@ -509,9 +509,9 @@
// // TODO: auto center on select a document in the sidebar
// private handleMapCenter = (map: google.maps.Map) => {
-// // console.log("print the selected views in selectionManager:")
-// // if (SelectionManager.Views.lastElement()) {
-// // console.log(SelectionManager.Views.lastElement());
+// // console.log("print the selected views in Document.Selected:")
+// // if (DocumentView.Selected().lastElement()) {
+// // console.log(DocumentView.Selected().lastElement());
// // }
// };
diff --git a/src/client/views/nodes/MapboxMapBox/MapboxContainer.tsx b/src/client/views/nodes/MapboxMapBox/MapboxContainer.tsx
index 3b4ffd4bd..bfd40692b 100644
--- a/src/client/views/nodes/MapboxMapBox/MapboxContainer.tsx
+++ b/src/client/views/nodes/MapboxMapBox/MapboxContainer.tsx
@@ -13,9 +13,7 @@ import { DocCast, NumCast, StrCast, toList } from '../../../../fields/Types';
import { DocUtils } from '../../../documents/DocUtils';
import { DocumentType } from '../../../documents/DocumentTypes';
import { Docs } from '../../../documents/Documents';
-import { DocumentManager } from '../../../util/DocumentManager';
import { DragManager } from '../../../util/DragManager';
-import { LinkManager } from '../../../util/LinkManager';
import { Transform } from '../../../util/Transform';
import { UndoManager, undoable } from '../../../util/UndoManager';
import { ViewBoxAnnotatableComponent } from '../../DocComponent';
@@ -130,7 +128,7 @@ export class MapBoxContainer extends ViewBoxAnnotatableComponent<FieldViewProps>
if (existingPin) {
setTimeout(() => {
// we use a timeout in case this is called from the sidebar which may have just added a link that hasn't made its way into th elink manager yet
- if (!LinkManager.Instance.getAllRelatedLinks(doc).some(link => DocCast(link.link_anchor_1)?.mapPin === existingPin || DocCast(link.link_anchor_2)?.mapPin === existingPin)) {
+ if (!Doc.Links(doc).some(link => DocCast(link.link_anchor_1)?.mapPin === existingPin || DocCast(link.link_anchor_2)?.mapPin === existingPin)) {
const anchor = this.getAnchor(true, undefined, existingPin);
anchor && DocUtils.MakeLink(anchor, doc, { link_relationship: 'link to map location' });
doc.latitude = existingPin?.latitude;
@@ -390,7 +388,7 @@ export class MapBoxContainer extends ViewBoxAnnotatableComponent<FieldViewProps>
options.didMove = true;
}
return new Promise<Opt<DocumentView>>(res => {
- DocumentManager.Instance.AddViewRenderedCb(doc, dv => res(dv));
+ DocumentView.addViewRenderedCb(doc, dv => res(dv));
});
};
/*
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index 5d1874aca..9038ed27a 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -19,9 +19,7 @@ import { emptyFunction } from '../../../Utils';
import { Docs } from '../../documents/Documents';
import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes';
import { DocUtils } from '../../documents/DocUtils';
-import { DocumentManager } from '../../util/DocumentManager';
import { KeyCodes } from '../../util/KeyCodes';
-import { SelectionManager } from '../../util/SelectionManager';
import { undoBatch, UndoManager } from '../../util/UndoManager';
import { CollectionFreeFormView } from '../collections/collectionFreeForm';
import { CollectionStackingView } from '../collections/CollectionStackingView';
@@ -251,7 +249,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
this.toggleSidebar(false);
}
return new Promise<Opt<DocumentView>>(res => {
- DocumentManager.Instance.AddViewRenderedCb(doc, dv => res(dv));
+ DocumentView.addViewRenderedCb(doc, dv => res(dv));
});
};
@@ -561,7 +559,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
removeDocument={this.removeDocument}
/>
) : (
- <div onPointerDown={e => setupMoveUpEvents(this, e, returnFalse, emptyFunction, () => SelectionManager.SelectView(this.DocumentView?.()!, false), true)}>
+ <div onPointerDown={e => setupMoveUpEvents(this, e, returnFalse, emptyFunction, () => DocumentView.SelectView(this.DocumentView?.()!, false), true)}>
<ComponentTag
// eslint-disable-next-line react/jsx-props-no-spreading
{...this._props}
diff --git a/src/client/views/nodes/RecordingBox/RecordingBox.tsx b/src/client/views/nodes/RecordingBox/RecordingBox.tsx
index ae6caf9f4..e46e40bfe 100644
--- a/src/client/views/nodes/RecordingBox/RecordingBox.tsx
+++ b/src/client/views/nodes/RecordingBox/RecordingBox.tsx
@@ -3,6 +3,7 @@ import { observer } from 'mobx-react';
import * as React from 'react';
import { DateField } from '../../../../fields/DateField';
import { Doc, DocListCast } from '../../../../fields/Doc';
+import { DocData } from '../../../../fields/DocSymbols';
import { Id } from '../../../../fields/FieldSymbols';
import { List } from '../../../../fields/List';
import { BoolCast, DocCast } from '../../../../fields/Types';
@@ -10,19 +11,18 @@ import { VideoField } from '../../../../fields/URLField';
import { Upload } from '../../../../server/SharedMediaTypes';
import { DocumentType } from '../../../documents/DocumentTypes';
import { Docs } from '../../../documents/Documents';
-import { DocumentManager } from '../../../util/DocumentManager';
import { DragManager } from '../../../util/DragManager';
+import { dropActionType } from '../../../util/DropActionTypes';
import { ScriptingGlobals } from '../../../util/ScriptingGlobals';
import { Presentation } from '../../../util/TrackMovements';
import { undoBatch } from '../../../util/UndoManager';
import { ViewBoxBaseComponent } from '../../DocComponent';
import { CollectionFreeFormView } from '../../collections/collectionFreeForm/CollectionFreeFormView';
import { mediaState } from '../AudioBox';
+import { DocumentView } from '../DocumentView';
import { FieldView, FieldViewProps } from '../FieldView';
import { VideoBox } from '../VideoBox';
import { RecordingView } from './RecordingView';
-import { DocData } from '../../../../fields/DocSymbols';
-import { dropActionType } from '../../../util/DropActionTypes';
@observer
export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() {
@@ -102,7 +102,7 @@ export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() {
screengrabber.overlayY = 590; // was 0
screengrabber[DocData][Doc.LayoutFieldKey(screengrabber) + '_trackScreen'] = true;
Doc.AddToMyOverlay(screengrabber); // just adds doc to overlay
- DocumentManager.Instance.AddViewRenderedCb(screengrabber, docView => {
+ DocumentView.addViewRenderedCb(screengrabber, docView => {
RecordingBox.screengrabber = docView.ComponentView as RecordingBox;
RecordingBox.screengrabber.Record?.();
});
@@ -119,7 +119,7 @@ export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() {
value.overlayX = 70;
value.overlayY = window.innerHeight - 180;
Doc.AddToMyOverlay(value);
- DocumentManager.Instance.AddViewRenderedCb(value, docView => {
+ DocumentView.addViewRenderedCb(value, docView => {
Doc.UserDoc().currentRecording = docView.Document;
docView.select(false);
RecordingBox.resumeWorkspaceReplaying(value);
@@ -132,7 +132,7 @@ export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() {
*/
@undoBatch
public static addRecToWorkspace(value: RecordingBox) {
- const ffView = Array.from(DocumentManager.Instance.DocumentViews).find(view => view.ComponentView instanceof CollectionFreeFormView);
+ const ffView = DocumentView.allViews().find(view => view.ComponentView instanceof CollectionFreeFormView);
(ffView?.ComponentView as CollectionFreeFormView)._props.addDocument?.(value.Document);
Doc.RemoveDocFromList(Doc.UserDoc(), 'workspaceRecordings', value.Document);
Doc.RemFromMyOverlay(value.Document);
@@ -142,7 +142,7 @@ export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() {
}
public static resumeWorkspaceReplaying(doc: Doc) {
- const docView = DocumentManager.Instance.getDocumentView(doc);
+ const docView = DocumentView.getDocumentView(doc);
if (docView?.ComponentView instanceof VideoBox) {
docView.ComponentView.Play();
}
@@ -150,7 +150,7 @@ export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() {
}
public static pauseWorkspaceReplaying(doc: Doc) {
- const docView = DocumentManager.Instance.getDocumentView(doc);
+ const docView = DocumentView.getDocumentView(doc);
const videoBox = docView?.ComponentView as VideoBox;
if (videoBox) {
videoBox.Pause();
diff --git a/src/client/views/nodes/ScreenshotBox.tsx b/src/client/views/nodes/ScreenshotBox.tsx
index 8eb55b2f8..3be50f5e6 100644
--- a/src/client/views/nodes/ScreenshotBox.tsx
+++ b/src/client/views/nodes/ScreenshotBox.tsx
@@ -24,6 +24,7 @@ import { SettingsManager } from '../../util/SettingsManager';
import { TrackMovements } from '../../util/TrackMovements';
import { ContextMenu } from '../ContextMenu';
import { ViewBoxAnnotatableComponent } from '../DocComponent';
+import { DocViewUtils } from '../DocViewUtils';
import { CollectionStackedTimeline } from '../collections/CollectionStackedTimeline';
import { CollectionFreeFormView } from '../collections/collectionFreeForm/CollectionFreeFormView';
import { mediaState } from './AudioBox';
@@ -161,8 +162,8 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
// });
}
componentWillUnmount() {
- const ind = DocUtils.ActiveRecordings.indexOf(this);
- ind !== -1 && DocUtils.ActiveRecordings.splice(ind, 1);
+ const ind = DocViewUtils.ActiveRecordings.indexOf(this);
+ ind !== -1 && DocViewUtils.ActiveRecordings.splice(ind, 1);
}
specificContextMenu = (): void => {
@@ -265,7 +266,7 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
this._screenCapture = true;
this.dataDoc.mediaState = 'recording';
});
- DocUtils.ActiveRecordings.push(this);
+ DocViewUtils.ActiveRecordings.push(this);
} else {
this._audioRec?.stop();
this._videoRec?.stop();
@@ -273,8 +274,8 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
this._screenCapture = false;
this.dataDoc.mediaState = 'paused';
});
- const ind = DocUtils.ActiveRecordings.indexOf(this);
- ind !== -1 && DocUtils.ActiveRecordings.splice(ind, 1);
+ const ind = DocViewUtils.ActiveRecordings.indexOf(this);
+ ind !== -1 && DocViewUtils.ActiveRecordings.splice(ind, 1);
CaptureManager.Instance.open(this.Document);
}
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index f32d00386..afd73cfe8 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -16,9 +16,7 @@ import { emptyFunction, formatTime } from '../../../Utils';
import { Docs } from '../../documents/Documents';
import { DocumentType } from '../../documents/DocumentTypes';
import { DocUtils, FollowLinkScript } from '../../documents/DocUtils';
-import { DocumentManager } from '../../util/DocumentManager';
import { dropActionType } from '../../util/DropActionTypes';
-import { LinkManager } from '../../util/LinkManager';
import { ReplayMovements } from '../../util/ReplayMovements';
import { undoBatch } from '../../util/UndoManager';
import { CollectionFreeFormView } from '../collections/collectionFreeForm/CollectionFreeFormView';
@@ -26,16 +24,16 @@ import { CollectionStackedTimeline, TrimScope } from '../collections/CollectionS
import { ContextMenu } from '../ContextMenu';
import { ContextMenuProps } from '../ContextMenuItem';
import { ViewBoxAnnotatableComponent, ViewBoxInterface } from '../DocComponent';
+import { VideoThumbnails } from '../global/globalEnums';
import { MarqueeAnnotator } from '../MarqueeAnnotator';
import { AnchorMenu } from '../pdf/AnchorMenu';
import { PinDocView, PinProps } from '../PinFuncs';
-import { StyleProp } from '../StyleProvider';
+import { StyleProp } from '../StyleProp';
import { DocumentView } from './DocumentView';
import { FieldView, FieldViewProps } from './FieldView';
import { FocusViewOptions } from './FocusViewOptions';
import { RecordingBox } from './RecordingBox';
import './VideoBox.scss';
-import { VideoThumbnails } from '../global/globalEnums';
/**
* VideoBox
@@ -88,7 +86,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps>() impl
@observable _scrubbing: boolean = false;
@computed get links() {
- return LinkManager.Links(this.dataDoc);
+ return Doc.Links(this.dataDoc);
}
@computed get heightPercent() {
return NumCast(this.layoutDoc._layout_timelineHeightPercent, 100);
@@ -347,7 +345,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps>() impl
this._props.addDocument?.(imageSnapshot);
DocUtils.MakeLink(imageSnapshot, this.getAnchor(true), { link_relationship: 'video snapshot' });
// link && (DocCast(link.link_anchor_2)[DocData].timecodeToHide = NumCast(DocCast(link.link_anchor_2).timecodeToShow) + 3); // do we need to set an end time? should default to +0.1
- setTimeout(() => downX !== undefined && downY !== undefined && DocumentManager.Instance.getFirstDocumentView(imageSnapshot)?.startDragging(downX, downY, dropActionType.move, true));
+ setTimeout(() => downX !== undefined && downY !== undefined && DocumentView.getFirstDocumentView(imageSnapshot)?.startDragging(downX, downY, dropActionType.move, true));
};
getAnchor = (addAsAnnotation: boolean, pinProps?: PinProps) => {
@@ -392,7 +390,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps>() impl
return this._stackedTimeline.getView(doc, options);
}
return new Promise<Opt<DocumentView>>(res => {
- DocumentManager.Instance.AddViewRenderedCb(doc, dv => res(dv));
+ DocumentView.addViewRenderedCb(doc, dv => res(dv));
});
};
@@ -446,7 +444,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps>() impl
{ fireImmediately: true }
);
- (!this.dataDoc[this.fieldKey + '_thumbnails'] || StrListCast(this.dataDoc[this.fieldKey + '_thumbnails']).length !== VideoBox.numThumbnails) && this.getVideoThumbnails();
+ (!this.dataDoc[this.fieldKey + '_thumbnails'] || StrListCast(this.dataDoc[this.fieldKey + '_thumbnails']).length !== VideoThumbnails.DENSE) && this.getVideoThumbnails();
}
};
@@ -652,20 +650,20 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps>() impl
@action
removeCurrentlyPlaying = () => {
const docView = this.DocumentView?.();
- if (CollectionStackedTimeline.CurrentlyPlaying && docView) {
- const index = CollectionStackedTimeline.CurrentlyPlaying.indexOf(docView);
- index !== -1 && CollectionStackedTimeline.CurrentlyPlaying.splice(index, 1);
+ if (DocumentView.CurrentlyPlaying && docView) {
+ const index = DocumentView.CurrentlyPlaying.indexOf(docView);
+ index !== -1 && DocumentView.CurrentlyPlaying.splice(index, 1);
}
};
// adds doc to currently playing display
@action
addCurrentlyPlaying = () => {
const docView = this.DocumentView?.();
- if (!CollectionStackedTimeline.CurrentlyPlaying) {
- CollectionStackedTimeline.CurrentlyPlaying = [];
+ if (!DocumentView.CurrentlyPlaying) {
+ DocumentView.CurrentlyPlaying = [];
}
- if (docView && CollectionStackedTimeline.CurrentlyPlaying.indexOf(docView) === -1) {
- CollectionStackedTimeline.CurrentlyPlaying.push(docView);
+ if (docView && DocumentView.CurrentlyPlaying.indexOf(docView) === -1) {
+ DocumentView.CurrentlyPlaying.push(docView);
}
};
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index 54f246b20..1003bc473 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -21,7 +21,6 @@ import { emptyFunction, stringHash } from '../../../Utils';
import { Docs } from '../../documents/Documents';
import { DocumentType } from '../../documents/DocumentTypes';
import { DocUtils } from '../../documents/DocUtils';
-import { DocumentManager } from '../../util/DocumentManager';
import { ScriptingGlobals } from '../../util/ScriptingGlobals';
import { SnappingManager } from '../../util/SnappingManager';
import { undoBatch, UndoManager } from '../../util/UndoManager';
@@ -38,7 +37,7 @@ import { Annotation } from '../pdf/Annotation';
import { GPTPopup } from '../pdf/GPTPopup/GPTPopup';
import { PinDocView, PinProps } from '../PinFuncs';
import { SidebarAnnos } from '../SidebarAnnos';
-import { StyleProp } from '../StyleProvider';
+import { StyleProp } from '../StyleProp';
import { DocumentView } from './DocumentView';
import { FieldView, FieldViewProps } from './FieldView';
import { FocusViewOptions } from './FocusViewOptions';
@@ -324,7 +323,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
if (this._url && webUrl && webUrl.href !== this._url) this.setData(webUrl.href);
if (this._sidebarRef?.current?.makeDocUnfiltered(doc) && !this.SidebarShown) this.toggleSidebar(false);
return new Promise<Opt<DocumentView>>(res => {
- DocumentManager.Instance.AddViewRenderedCb(doc, dv => res(dv));
+ DocumentView.addViewRenderedCb(doc, dv => res(dv));
});
};
diff --git a/src/client/views/nodes/formattedText/DashFieldView.tsx b/src/client/views/nodes/formattedText/DashFieldView.tsx
index 1c5ea2dd4..5d53a2a5f 100644
--- a/src/client/views/nodes/formattedText/DashFieldView.tsx
+++ b/src/client/views/nodes/formattedText/DashFieldView.tsx
@@ -293,7 +293,6 @@ export class DashFieldView {
unclickable = () => !this.tbox._props.rootSelected?.() && this.node.marks.some((m: any) => m.type === this.tbox.EditorView?.state.schema.marks.linkAnchor && m.attrs.noPreview);
constructor(node: any, view: any, getPos: any, tbox: FormattedTextBox) {
makeObservable(this);
- const self = this;
this.node = node;
this.tbox = tbox;
this.getpos = getPos;
@@ -305,14 +304,14 @@ export class DashFieldView {
this.dom.onkeypress = function (e: KeyboardEvent) {
e.stopPropagation();
};
- this.dom.onkeydown = function (e: KeyboardEvent) {
+ this.dom.onkeydown = (e: KeyboardEvent) => {
e.stopPropagation();
if (e.key === 'Tab') {
e.preventDefault();
const editor = tbox.EditorView;
if (editor) {
const { state } = editor;
- for (let i = self.getpos() + 1; i < state.doc.content.size; i++) {
+ for (let i = this.getpos() + 1; i < state.doc.content.size; i++) {
if (state.doc.nodeAt(i)?.type.name === state.schema.nodes.dashField.name) {
editor.dispatch(state.tr.setSelection(new NodeSelection(state.doc.resolve(i))));
return;
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index ad6629fc9..8a4a7718a 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -32,16 +32,13 @@ import { Docs } from '../../../documents/Documents';
import { CollectionViewType, DocumentType } from '../../../documents/DocumentTypes';
import { DocUtils } from '../../../documents/DocUtils';
import { DictationManager } from '../../../util/DictationManager';
-import { DocumentManager } from '../../../util/DocumentManager';
import { DragManager } from '../../../util/DragManager';
import { dropActionType } from '../../../util/DropActionTypes';
import { MakeTemplate } from '../../../util/DropConverter';
import { LinkManager } from '../../../util/LinkManager';
import { RTFMarkup } from '../../../util/RTFMarkup';
-import { SelectionManager } from '../../../util/SelectionManager';
import { SnappingManager } from '../../../util/SnappingManager';
import { undoable, undoBatch, UndoManager } from '../../../util/UndoManager';
-import { CollectionFreeFormView } from '../../collections/collectionFreeForm/CollectionFreeFormView';
import { CollectionStackingView } from '../../collections/CollectionStackingView';
import { CollectionTreeView } from '../../collections/CollectionTreeView';
import { ContextMenu } from '../../ContextMenu';
@@ -53,9 +50,10 @@ import { AnchorMenu } from '../../pdf/AnchorMenu';
import { GPTPopup } from '../../pdf/GPTPopup/GPTPopup';
import { PinDocView, PinProps } from '../../PinFuncs';
import { SidebarAnnos } from '../../SidebarAnnos';
-import { styleFromLayoutString, StyleProp } from '../../StyleProvider';
+import { StyleProp } from '../../StyleProp';
+import { styleFromLayoutString } from '../../StyleProvider';
import { mediaState } from '../AudioBox';
-import { DocumentView, DocumentViewInternal } from '../DocumentView';
+import { DocumentView } from '../DocumentView';
import { FieldView, FieldViewProps } from '../FieldView';
import { FocusViewOptions } from '../FocusViewOptions';
import { LinkInfo } from '../LinkDocPreview';
@@ -260,7 +258,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
let stopFunc: any;
const targetData = target[DocData];
targetData.mediaState = mediaState.Recording;
- DocumentViewInternal.recordAudioAnnotation(targetData, Doc.LayoutFieldKey(target), stop => { stopFunc = stop }); // prettier-ignore
+ DictationManager.recordAudioAnnotation(targetData, Doc.LayoutFieldKey(target), stop => { stopFunc = stop }); // prettier-ignore
const reactionDisposer = reaction(
() => target.mediaState,
@@ -271,7 +269,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
}
}
);
- target.title = ComputedField.MakeFunction(`self["text_audioAnnotations_text"].lastElement()`);
+ target.title = ComputedField.MakeFunction(`this.text_audioAnnotations_text.lastElement()`);
}
});
};
@@ -400,7 +398,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
insertTime = () => {
let linkTime;
let linkAnchor;
- LinkManager.Links(this.dataDoc).forEach(l => {
+ Doc.Links(this.dataDoc).forEach(l => {
const anchor = DocCast(l.link_anchor_1)?.annotationOn ? DocCast(l.link_anchor_1) : DocCast(l.link_anchor_2)?.annotationOn ? DocCast(l.link_anchor_2) : undefined;
if (anchor && (anchor.annotationOn as Doc).mediaState === mediaState.Recording) {
linkTime = NumCast(anchor._timecodeToShow /* audioStart */);
@@ -423,7 +421,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
autoLink = () => {
const newAutoLinks = new Set<Doc>();
- const oldAutoLinks = LinkManager.Links(this.Document).filter(
+ const oldAutoLinks = Doc.Links(this.Document).filter(
link =>
((!Doc.isTemplateForField(this.Document) &&
(!Doc.isTemplateForField(DocCast(link.link_anchor_1)) || !Doc.AreProtosEqual(DocCast(link.link_anchor_1), this.Document)) &&
@@ -442,7 +440,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
tr = tr.setSelection(new TextSelection(tr.doc.resolve(from), tr.doc.resolve(to)));
this._editorView?.dispatch(tr);
}
- oldAutoLinks.filter(oldLink => !newAutoLinks.has(oldLink) && oldLink.link_anchor_2 !== this.Document).forEach(LinkManager.Instance.deleteLink);
+ oldAutoLinks.filter(oldLink => !newAutoLinks.has(oldLink) && oldLink.link_anchor_2 !== this.Document).forEach(doc => Doc.DeleteLink?.(doc));
};
updateTitle = () => {
@@ -496,7 +494,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
if (node.firstChild === null && !node.marks.find((m: Mark) => m.type.name === schema.marks.noAutoLinkAnchor.name) && node.marks.find((m: Mark) => m.type.name === schema.marks.splitter.name)) {
alink =
alink ??
- (LinkManager.Links(this.Document).find(
+ (Doc.Links(this.Document).find(
link =>
Doc.AreProtosEqual(Cast(link.link_anchor_1, Doc, null), this.Document) && //
Doc.AreProtosEqual(Cast(link.link_anchor_2, Doc, null), target)
@@ -787,7 +785,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
deleteAnnotation = (anchor: Doc) => {
const batch = UndoManager.StartBatch('delete link');
- LinkManager.Instance.deleteLink(LinkManager.Links(anchor)[0]);
+ Doc.DeleteLink?.(Doc.Links(anchor)[0]);
// const docAnnotations = DocListCast(this._props.dataDoc[this.fieldKey]);
// this._props.dataDoc[this.fieldKey] = new List<Doc>(docAnnotations.filter(a => a !== this.annoTextRegion));
// AnchorMenu.Instance.fadeOut(true);
@@ -837,7 +835,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
anchorDoc &&
DocServer.GetRefField(anchorDoc).then(
action(anchor => {
- anchor && SelectionManager.SelectSchemaViewDoc(anchor as Doc);
+ anchor && DocumentView.SelectSchemaDoc(anchor as Doc);
AnchorMenu.Instance.Status = 'annotation';
AnchorMenu.Instance.Delete = !anchor && editor.state.selection.empty ? returnFalse : !anchor ? deleteMarkups : () => this.deleteAnnotation(anchor as Doc);
AnchorMenu.Instance.Pinned = false;
@@ -1124,7 +1122,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
setTimeout(() => this._sidebarRef?.current?.makeDocUnfiltered(doc));
}
return new Promise<Opt<DocumentView>>(res => {
- DocumentManager.Instance.AddViewRenderedCb(doc, dv => res(dv));
+ DocumentView.addViewRenderedCb(doc, dv => res(dv));
});
};
focus = (textAnchor: Doc, options: FocusViewOptions) => {
@@ -1206,7 +1204,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
}
componentDidMount() {
!this._props.dontSelectOnLoad && this._props.setContentViewBox?.(this); // this tells the DocumentView that this AudioBox is the "content" of the document. this allows the DocumentView to indirectly call getAnchor() on the AudioBox when making a link.
- this._cachedLinks = LinkManager.Links(this.Document);
+ this._cachedLinks = Doc.Links(this.Document);
this._disposers.breakupDictation = reaction(() => Doc.RecordingEvent, this.breakupDictation);
this._disposers.layout_autoHeight = reaction(
() => ({ autoHeight: this.layout_autoHeight, fontSize: this.fontSize, css: this.Document[DocCss] }),
@@ -1244,7 +1242,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
{ fireImmediately: !Array.from(FormattedTextBox._globalHighlights).includes('Bold Text') }
);
this._disposers.links = reaction(
- () => LinkManager.Links(this.dataDoc), // if a link is deleted, then remove all hyperlinks that reference it from the text's marks
+ () => Doc.Links(this.dataDoc), // if a link is deleted, then remove all hyperlinks that reference it from the text's marks
newLinks => {
this._cachedLinks.forEach(l => !newLinks.includes(l) && this.RemoveLinkFromDoc(l));
this._cachedLinks = newLinks;
@@ -1556,7 +1554,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
// const timecode = NumCast(anchor.timecodeToShow, 0);
const audiodoc = anchor.annotationOn as Doc;
const func = () => {
- const docView = DocumentManager.Instance.getDocumentView(audiodoc);
+ const docView = DocumentView.getDocumentView(audiodoc);
if (!docView) {
this._props.addDocTab(audiodoc, OpenWhere.addBottom);
setTimeout(func);
@@ -1769,7 +1767,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
case 'Escape':
this._editorView!.dispatch(state.tr.setSelection(TextSelection.create(state.doc, state.selection.from, state.selection.from)));
(document.activeElement as any).blur?.();
- SelectionManager.DeselectAll();
+ DocumentView.DeselectAll();
RichTextMenu.Instance?.updateMenu(undefined, undefined, undefined, undefined);
return;
case 'Enter':
@@ -1891,7 +1889,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
}
@computed get sidebarCollection() {
const renderComponent = (tag: string) => {
- const ComponentTag: any = tag === CollectionViewType.Freeform ? CollectionFreeFormView : tag === CollectionViewType.Tree ? CollectionTreeView : tag === 'translation' ? FormattedTextBox : CollectionStackingView;
+ const ComponentTag: any = tag === CollectionViewType.Tree ? CollectionTreeView : tag === 'translation' ? FormattedTextBox : CollectionStackingView;
return ComponentTag === CollectionStackingView ? (
<SidebarAnnos
ref={this._sidebarRef}
@@ -1913,7 +1911,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
setHeight={this.setSidebarHeight}
/>
) : (
- <div onPointerDown={e => setupMoveUpEvents(this, e, returnFalse, emptyFunction, () => SelectionManager.SelectView(this.DocumentView?.()!, false), true)}>
+ <div onPointerDown={e => setupMoveUpEvents(this, e, returnFalse, emptyFunction, () => DocumentView.SelectView(this.DocumentView?.()!, false), true)}>
<ComponentTag
// eslint-disable-next-line react/jsx-props-no-spreading
{...this._props}
@@ -1998,11 +1996,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
@observable _isHovering = false;
onPassiveWheel = (e: WheelEvent) => {
if (e.clientX > this.ProseRef!.getBoundingClientRect().right) {
- if (this.dataDoc[this.SidebarKey + '_type_collection'] === CollectionViewType.Freeform) {
- // if the scrolled freeform is a child of the sidebar component, we need to let the event go through
- // so react can let the freeform view handle it. We prevent default to stop any containing views from scrolling
- e.preventDefault();
- }
return;
}
@@ -2037,7 +2030,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
}
render() {
TraceMobx();
- const scale = this._props.NativeDimScaling?.() || 1; // * NumCast(this.layoutDoc._freeform_scale, 1);
+ const scale = this._props.NativeDimScaling?.() || 1;
const rounded = StrCast(this.layoutDoc.layout_borderRounding) === '100%' ? '-rounded' : '';
setTimeout(() => !this._props.isContentActive() && FormattedTextBoxComment.textBox === this && FormattedTextBoxComment.Hide);
const paddingX = NumCast(this.layoutDoc._xMargin, this._props.xPadding || 0);
diff --git a/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts b/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts
index bc6454146..7a8b72be0 100644
--- a/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts
+++ b/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts
@@ -11,7 +11,7 @@ import { AclAdmin, AclAugment, AclEdit, DocData } from '../../../../fields/DocSy
import { GetEffectiveAcl } from '../../../../fields/util';
import { Docs } from '../../../documents/Documents';
import { RTFMarkup } from '../../../util/RTFMarkup';
-import { SelectionManager } from '../../../util/SelectionManager';
+import { DocumentView } from '../DocumentView';
import { OpenWhere } from '../OpenWhere';
const mac = typeof navigator !== 'undefined' ? /Mac/.test(navigator.platform) : false;
@@ -172,7 +172,7 @@ export function buildKeymap<S extends Schema<any>>(schema: S, props: any): KeyMa
bind('Escape', (state: EditorState, dispatch: (tx: Transaction) => void) => {
dispatch(state.tr.setSelection(TextSelection.create(state.doc, state.selection.from, state.selection.from)));
(document.activeElement as any).blur?.();
- SelectionManager.DeselectAll();
+ DocumentView.DeselectAll();
});
bind('Alt-Enter', () => onKey() || true);
diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx
index 6c12b9991..a612f3c65 100644
--- a/src/client/views/nodes/formattedText/RichTextMenu.tsx
+++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx
@@ -11,11 +11,10 @@ import * as React from 'react';
import { Doc } from '../../../../fields/Doc';
import { BoolCast, Cast, StrCast } from '../../../../fields/Types';
import { DocServer } from '../../../DocServer';
-import { LinkManager } from '../../../util/LinkManager';
-import { SelectionManager } from '../../../util/SelectionManager';
import { undoBatch, UndoManager } from '../../../util/UndoManager';
import { AntimodeMenu, AntimodeMenuProps } from '../../AntimodeMenu';
import { ObservableReactComponent } from '../../ObservableReactComponent';
+import { DocumentView } from '../DocumentView';
import { EquationBox } from '../EquationBox';
import { FieldViewProps } from '../FieldView';
import { FormattedTextBox } from './FormattedTextBox';
@@ -116,7 +115,7 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> {
_disposer: IReactionDisposer | undefined;
componentDidMount() {
this._disposer = reaction(
- () => SelectionManager.Views.slice(),
+ () => DocumentView.Selected().slice(),
() => this.updateMenu(undefined, undefined, undefined, undefined)
);
}
@@ -144,8 +143,8 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> {
const { activeSizes } = active;
const { activeColors } = active;
const { activeHighlights } = active;
- const refDoc = SelectionManager.Views.lastElement()?.layoutDoc ?? Doc.UserDoc();
- const refField = (pfx => (pfx ? pfx + '_' : ''))(SelectionManager.Views.lastElement()?.LayoutFieldKey);
+ const refDoc = DocumentView.Selected().lastElement()?.layoutDoc ?? Doc.UserDoc();
+ const refField = (pfx => (pfx ? pfx + '_' : ''))(DocumentView.Selected().lastElement()?.LayoutFieldKey);
const refVal = (field: string, dflt: string) => StrCast(refDoc[refField + field], StrCast(Doc.UserDoc()[field], dflt));
this._activeListType = this.getActiveListStyle();
@@ -237,8 +236,8 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> {
m.type === state.schema.marks.pFontSize && activeSizes.add(m.attrs.fontSize);
m.type === state.schema.marks.pFontHighlight && activeHighlights.add(String(m.attrs.fontHighlight));
});
- } else if (SelectionManager.Views.some(dv => dv.ComponentView instanceof EquationBox)) {
- SelectionManager.Views.forEach(dv => StrCast(dv.Document._text_fontSize) && activeSizes.add(StrCast(dv.Document._text_fontSize)));
+ } else if (DocumentView.Selected().some(dv => dv.ComponentView instanceof EquationBox)) {
+ DocumentView.Selected().forEach(dv => StrCast(dv.Document._text_fontSize) && activeSizes.add(StrCast(dv.Document._text_fontSize)));
}
return { activeFamilies: Array.from(activeFamilies), activeSizes: Array.from(activeSizes), activeColors: Array.from(activeColors), activeHighlights: Array.from(activeHighlights) };
}
@@ -566,7 +565,7 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> {
if (linkDoc instanceof Doc) {
const linkAnchor1 = await Cast(linkDoc.link_anchor_1, Doc);
const linkAnchor2 = await Cast(linkDoc.link_anchor_2, Doc);
- const currentDoc = SelectionManager.Docs.lastElement();
+ const currentDoc = DocumentView.Selected().lastElement().Document;
if (currentDoc && linkAnchor1 && linkAnchor2) {
if (Doc.AreProtosEqual(currentDoc, linkAnchor1)) {
return StrCast(linkAnchor2.title);
@@ -605,7 +604,7 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> {
.filter((aref: any) => aref?.href.indexOf(Doc.localServerPath()) === 0)
.forEach((aref: any) => {
const anchorId = aref.href.replace(Doc.localServerPath(), '').split('?')[0];
- anchorId && DocServer.GetRefField(anchorId).then(linkDoc => LinkManager.Instance.deleteLink(linkDoc as Doc));
+ anchorId && DocServer.GetRefField(anchorId).then(linkDoc => Doc.DeleteLink?.(linkDoc as Doc));
});
}
}
diff --git a/src/client/views/nodes/formattedText/SummaryView.tsx b/src/client/views/nodes/formattedText/SummaryView.tsx
index 2c366b49b..238267f6e 100644
--- a/src/client/views/nodes/formattedText/SummaryView.tsx
+++ b/src/client/views/nodes/formattedText/SummaryView.tsx
@@ -21,11 +21,10 @@ export class SummaryView {
root: any;
constructor(node: any, view: any, getPos: any) {
- const self = this;
this.dom = document.createElement('span');
this.dom.className = this.className(node.attrs.visibility);
- this.dom.onpointerdown = function (e: any) {
- self.onPointerDown(e, node, view, getPos);
+ this.dom.onpointerdown = (e: any) => {
+ this.onPointerDown(e, node, view, getPos);
};
this.dom.onkeypress = function (e: any) {
e.stopPropagation();
diff --git a/src/client/views/nodes/generativeFill/GenerativeFill.tsx b/src/client/views/nodes/generativeFill/GenerativeFill.tsx
index d5fad296f..91b0ebd5c 100644
--- a/src/client/views/nodes/generativeFill/GenerativeFill.tsx
+++ b/src/client/views/nodes/generativeFill/GenerativeFill.tsx
@@ -16,7 +16,6 @@ import { NumCast } from '../../../../fields/Types';
import { Networking } from '../../../Network';
import { DocUtils } from '../../../documents/DocUtils';
import { Docs } from '../../../documents/Documents';
-import { DocumentManager } from '../../../util/DocumentManager';
import { CollectionDockingView } from '../../collections/CollectionDockingView';
import { CollectionFreeFormView } from '../../collections/collectionFreeForm';
import { ImageEditorData } from '../ImageBox';
@@ -28,6 +27,7 @@ import { APISuccess, ImageUtility } from './generativeFillUtils/ImageHandler';
import { PointerHandler } from './generativeFillUtils/PointerHandler';
import { activeColor, canvasSize, eraserColor, freeformRenderSize, newCollectionSize, offsetDistanceY, offsetX } from './generativeFillUtils/generativeFillConstants';
import { CursorData, ImageDimensions, Point } from './generativeFillUtils/generativeFillInterfaces';
+import { DocumentView } from '../DocumentView';
// enum BrushStyle {
// ADD,
@@ -295,7 +295,7 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD
_height: newCollectionSize,
title: 'Image edit collection',
});
- DocUtils.MakeLink(imageRootDoc, newCollectionRef.current, { link_relationship: 'Image Edit Version History', link_displayLine: false });
+ DocUtils.MakeLink(imageRootDoc, newCollectionRef.current, { link_relationship: 'Image Edit Version History' });
// opening new tab
CollectionDockingView.AddSplit(newCollectionRef.current, OpenWhereMod.right);
@@ -400,7 +400,7 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD
parentDoc.current.gen_fill_children = new List<Doc>([newImg]);
}
- DocUtils.MakeLink(parentDoc.current, newImg, { link_relationship: `Image edit; Prompt: ${input}`, link_displayLine: true });
+ DocUtils.MakeLink(parentDoc.current, newImg, { link_relationship: `Image edit; Prompt: ${input}` });
adjustImgPositions();
if (isNewCollection && newCollectionRef.current) {
@@ -430,7 +430,7 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD
ImageEditorData.Open = false;
ImageEditorData.Source = '';
if (newCollectionRef.current) {
- DocumentManager.Instance.AddViewRenderedCb(newCollectionRef.current, dv => (dv.ComponentView as CollectionFreeFormView)?.fitContentOnce());
+ DocumentView.addViewRenderedCb(newCollectionRef.current, dv => (dv.ComponentView as CollectionFreeFormView)?.fitContentOnce());
}
setEdits([]);
};
diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx
index 485ba7367..6b4f5e073 100644
--- a/src/client/views/nodes/trails/PresBox.tsx
+++ b/src/client/views/nodes/trails/PresBox.tsx
@@ -19,17 +19,14 @@ import { emptyFunction, emptyPath, stringHash } from '../../../../Utils';
import { DocServer } from '../../../DocServer';
import { Docs } from '../../../documents/Documents';
import { CollectionViewType, DocumentType } from '../../../documents/DocumentTypes';
-import { DocumentManager } from '../../../util/DocumentManager';
import { dropActionType } from '../../../util/DropActionTypes';
import { ScriptingGlobals } from '../../../util/ScriptingGlobals';
-import { SelectionManager } from '../../../util/SelectionManager';
import { SerializationHelper } from '../../../util/SerializationHelper';
-import { SettingsManager } from '../../../util/SettingsManager';
import { SnappingManager } from '../../../util/SnappingManager';
import { undoBatch, UndoManager } from '../../../util/UndoManager';
import { CollectionDockingView } from '../../collections/CollectionDockingView';
import { CollectionFreeFormView } from '../../collections/collectionFreeForm';
-import { CollectionStackedTimeline } from '../../collections/CollectionStackedTimeline';
+import { CollectionFreeFormPannableContents } from '../../collections/collectionFreeForm/CollectionFreeFormPannableContents';
import { CollectionView } from '../../collections/CollectionView';
import { TreeView } from '../../collections/TreeView';
import { ViewBoxBaseComponent } from '../../DocComponent';
@@ -55,8 +52,9 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
super(props);
makeObservable(this);
if (!PresBox.navigateToDocScript) {
- PresBox.navigateToDocScript = ScriptField.MakeFunction('navigateToDoc(this.presentation_targetDoc, self)')!;
+ PresBox.navigateToDocScript = ScriptField.MakeFunction('navigateToDoc(this.presentation_targetDoc, this)')!;
}
+ CollectionFreeFormPannableContents.SetOverlayPlugin((fform: Doc) => PresBox.Instance.pathLines(fform));
}
private _disposers: { [name: string]: IReactionDisposer } = {};
@@ -122,8 +120,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
return false;
}
@computed get selectedDocumentView() {
- if (SelectionManager.Views.length) return SelectionManager.Views[0];
- if (this.selectedArray.size) return DocumentManager.Instance.getDocumentView(this.Document);
+ if (DocumentView.Selected().length) return DocumentView.Selected()[0];
+ if (this.selectedArray.size) return DocumentView.getDocumentView(this.Document);
return undefined;
}
@computed get isPres() {
@@ -175,7 +173,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
this._unmounting = false;
this.turnOffEdit(true);
this._disposers.selection = reaction(
- () => SelectionManager.Views.slice(),
+ () => DocumentView.Selected().slice(),
views => (!PresBox.Instance || views.some(view => view.Document === this.Document)) && this.updateCurrentPresentation(),
{ fireImmediately: true }
);
@@ -200,7 +198,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
startTempMedia = (targetDoc: Doc, activeItem: Doc) => {
const duration: number = NumCast(activeItem.config_clipEnd) - NumCast(activeItem.config_clipStart);
if ([DocumentType.VID, DocumentType.AUDIO].includes(targetDoc.type as any)) {
- const targMedia = DocumentManager.Instance.getDocumentView(targetDoc);
+ const targMedia = DocumentView.getDocumentView(targetDoc);
targMedia?.ComponentView?.playFrom?.(NumCast(activeItem.config_clipStart), NumCast(activeItem.config_clipStart) + duration);
}
};
@@ -208,7 +206,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
stopTempMedia = (targetDocField: FieldResult) => {
const targetDoc = DocCast(DocCast(targetDocField).annotationOn) ?? DocCast(targetDocField);
if ([DocumentType.VID, DocumentType.AUDIO].includes(targetDoc.type as any)) {
- const targMedia = DocumentManager.Instance.getDocumentView(targetDoc);
+ const targMedia = DocumentView.getDocumentView(targetDoc);
targMedia?.ComponentView?.Pause?.();
}
};
@@ -260,7 +258,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
// go to documents chain
runSubroutines = (childrenToRun: Opt<Doc[]>, normallyNextSlide: Doc) => {
if (childrenToRun && childrenToRun[0] !== normallyNextSlide) {
- childrenToRun.forEach(child => DocumentManager.Instance.showDocument(child, {}));
+ childrenToRun.forEach(child => DocumentView.showDocument(child, {}));
}
};
@@ -280,7 +278,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
if (listItems && presIndexed < listItems.length) {
if (!first) {
const listItemDoc = listItems[presIndexed];
- const targetView = listItems && DocumentManager.Instance.getFirstDocumentView(listItemDoc);
+ const targetView = listItems && DocumentView.getFirstDocumentView(listItemDoc);
Doc.linkFollowUnhighlight();
Doc.HighlightDoc(listItemDoc);
listItemDoc.presentation_effect = this.activeItem.presBulletEffect;
@@ -425,7 +423,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
const acontext = activeItem.config_activeFrame !== undefined ? DocCast(DocCast(activeItem.presentation_targetDoc).embedContainer) : DocCast(activeItem.presentation_targetDoc);
const context = DocCast(acontext)?.annotationOn ? DocCast(DocCast(acontext).annotationOn) : acontext;
if (context) {
- const ffview = CollectionFreeFormView.from(DocumentManager.Instance.getFirstDocumentView(context));
+ const ffview = CollectionFreeFormView.from(DocumentView.getFirstDocumentView(context));
if (ffview?.childDocs) {
PresBox.Instance._keyTimer = CollectionFreeFormView.gotoKeyframe(PresBox.Instance._keyTimer, ffview.childDocs, frameTime);
ffview.layoutDoc._currentFrame = NumCast(activeFrame);
@@ -605,7 +603,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
const viewport = { panX: (contentBounds[0] + contentBounds[2]) / 2, panY: (contentBounds[1] + contentBounds[3]) / 2, width: contentBounds[2] - contentBounds[0], height: contentBounds[3] - contentBounds[1] };
bestTarget._freeform_panX = viewport.panX;
bestTarget._freeform_panY = viewport.panY;
- const dv = DocumentManager.Instance.getDocumentView(bestTarget);
+ const dv = DocumentView.getDocumentView(bestTarget);
if (dv) {
changed = true;
const computedScale = NumCast(activeItem.config_zoom, 1) * Math.min(dv._props.PanelWidth() / viewport.width, dv._props.PanelHeight() / viewport.height);
@@ -644,8 +642,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
const eleViewCache = Array.from(this._eleArray);
const resetSelection = action(() => {
if (!this._props.isSelected()) {
- const presDocView = DocumentManager.Instance.getDocumentView(this.Document);
- if (presDocView) SelectionManager.SelectView(presDocView, false);
+ const presDocView = DocumentView.getDocumentView(this.Document);
+ if (presDocView) DocumentView.SelectView(presDocView, false);
this.clearSelectedArray();
selViewCache.forEach(doc => this.addToSelectedArray(doc));
this._dragArray.splice(0, this._dragArray.length, ...dragViewCache);
@@ -660,7 +658,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
static NavigateToTarget(targetDoc: Doc, activeItem: Doc, finished?: () => void) {
if (activeItem.presentation_movement === PresMovement.None && targetDoc.type === DocumentType.SCRIPTING) {
- (DocumentManager.Instance.getFirstDocumentView(targetDoc)?.ComponentView as ScriptingBox)?.onRun?.();
+ (DocumentView.getFirstDocumentView(targetDoc)?.ComponentView as ScriptingBox)?.onRun?.();
return;
}
const effect = activeItem.presentation_effect && activeItem.presentation_effect !== PresEffect.None ? activeItem.presentation_effect : undefined;
@@ -680,19 +678,19 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
};
if (activeItem.presentation_openInLightbox) {
const context = DocCast(targetDoc.annotationOn) ?? targetDoc;
- if (!DocumentManager.Instance.getLightboxDocumentView(context)) {
+ if (!DocumentView.getLightboxDocumentView(context)) {
LightboxView.Instance.SetLightboxDoc(context);
}
}
if (targetDoc) {
if (activeItem.presentation_targetDoc instanceof Doc) activeItem.presentation_targetDoc[Animation] = undefined;
- DocumentManager.Instance.AddViewRenderedCb(LightboxView.LightboxDoc, () => {
+ DocumentView.addViewRenderedCb(LightboxView.LightboxDoc, () => {
// if target or the doc it annotates is not in the lightbox, then close the lightbox
- if (!DocumentManager.Instance.getLightboxDocumentView(DocCast(targetDoc.annotationOn) ?? targetDoc)) {
+ if (!DocumentView.getLightboxDocumentView(DocCast(targetDoc.annotationOn) ?? targetDoc)) {
LightboxView.Instance.SetLightboxDoc(undefined);
}
- DocumentManager.Instance.showDocument(targetDoc, options, finished);
+ DocumentView.showDocument(targetDoc, options, finished);
});
} else finished?.();
}
@@ -1032,8 +1030,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
@action
selectPres = () => {
- const presDocView = DocumentManager.Instance.getDocumentView(this.Document);
- presDocView && SelectionManager.SelectView(presDocView, false);
+ const presDocView = DocumentView.getDocumentView(this.Document);
+ presDocView && DocumentView.SelectView(presDocView, false);
};
focusElement = (doc: Doc) => {
@@ -1044,7 +1042,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
// Regular click
@action
selectElement = (doc: Doc, noNav = false) => {
- CollectionStackedTimeline.CurrentlyPlaying?.map(clip => clip?.ComponentView?.Pause?.());
+ DocumentView.CurrentlyPlaying?.map(clip => clip?.ComponentView?.Pause?.());
if (noNav) {
const index = this.childDocs.indexOf(doc);
if (index >= 0 && index < this.childDocs.length) {
@@ -1200,7 +1198,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
const order: JSX.Element[] = [];
const docs = new Set<Doc>();
const presCollection = collection;
- const dv = DocumentManager.Instance.getDocumentView(presCollection);
+ const dv = DocumentView.getDocumentView(presCollection);
this.childDocs.forEach((doc, index) => {
const tagDoc = PresBox.targetRenderedDoc(doc);
const srcContext = Cast(tagDoc.embedContainer, Doc, null);
@@ -2206,7 +2204,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
if (doc) {
const tabMap = CollectionDockingView.Instance?.tabMap;
const docTab = tabMap && Array.from(tabMap).find(tab => tab.DashDoc.type === DocumentType.COL)?.DashDoc;
- const presCollection = DocumentManager.GetContextPath(this.activeItem).reverse().lastElement().presentation_targetDoc ?? docTab;
+ const presCollection = DocumentView.getContextPath(this.activeItem).reverse().lastElement().presentation_targetDoc ?? docTab;
const data = Cast(presCollection?.data, listSpec(Doc));
const configData = Cast(this.Document.data, listSpec(Doc));
if (data && configData) {
@@ -2282,12 +2280,12 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
@action
toggleProperties = () => {
- SettingsManager.Instance.propertiesWidth = SettingsManager.Instance.propertiesWidth > 0 ? 0 : 250;
+ SnappingManager.SetPropertiesWidth(SnappingManager.PropertiesWidth > 0 ? 0 : 250);
};
@computed get toolbar() {
- const propIcon = SettingsManager.Instance.propertiesWidth > 0 ? 'angle-double-right' : 'angle-double-left';
- const propTitle = SettingsManager.Instance.propertiesWidth > 0 ? 'Close Presentation Panel' : 'Open Presentation Panel';
+ const propIcon = SnappingManager.PropertiesWidth > 0 ? 'angle-double-right' : 'angle-double-left';
+ const propTitle = SnappingManager.PropertiesWidth > 0 ? 'Close Presentation Panel' : 'Open Presentation Panel';
const mode = StrCast(this.Document._type_collection) as CollectionViewType;
const isMini: boolean = this.toolbarWidth <= 100;
const activeColor = SnappingManager.userVariantColor;
@@ -2316,7 +2314,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
</Tooltip>
<Tooltip title={<div className="dash-tooltip">{propTitle}</div>}>
<div className="toolbar-button" style={{ position: 'absolute', right: 4, fontSize: 16 }} onClick={this.toggleProperties}>
- <FontAwesomeIcon className="toolbar-thumbtack" icon={propIcon} style={{ color: SettingsManager.Instance.propertiesWidth > 0 ? activeColor : inactiveColor }} />
+ <FontAwesomeIcon className="toolbar-thumbtack" icon={propIcon} style={{ color: SnappingManager.PropertiesWidth > 0 ? activeColor : inactiveColor }} />
</div>
</Tooltip>
</>
diff --git a/src/client/views/nodes/trails/PresElementBox.tsx b/src/client/views/nodes/trails/PresElementBox.tsx
index af0ab3b53..306b98190 100644
--- a/src/client/views/nodes/trails/PresElementBox.tsx
+++ b/src/client/views/nodes/trails/PresElementBox.tsx
@@ -13,9 +13,8 @@ import { BoolCast, Cast, DocCast, NumCast, StrCast } from '../../../../fields/Ty
import { emptyFunction } from '../../../../Utils';
import { Docs } from '../../../documents/Documents';
import { CollectionViewType, DocumentType } from '../../../documents/DocumentTypes';
-import { DocumentManager } from '../../../util/DocumentManager';
import { DragManager } from '../../../util/DragManager';
-import { SettingsManager } from '../../../util/SettingsManager';
+import { SnappingManager } from '../../../util/SnappingManager';
import { Transform } from '../../../util/Transform';
import { undoable, undoBatch } from '../../../util/UndoManager';
import { TreeView } from '../../collections/TreeView';
@@ -23,7 +22,7 @@ import { ViewBoxBaseComponent } from '../../DocComponent';
import { EditableView } from '../../EditableView';
import { Colors } from '../../global/globalEnums';
import { PinDocView } from '../../PinFuncs';
-import { StyleProp } from '../../StyleProvider';
+import { StyleProp } from '../../StyleProp';
import { DocumentView } from '../DocumentView';
import { FieldView, FieldViewProps } from '../FieldView';
import { PresBox } from './PresBox';
@@ -282,8 +281,8 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
@action
toggleProperties = () => {
- if (SettingsManager.Instance.propertiesWidth < 5) {
- SettingsManager.Instance.propertiesWidth = 250;
+ if (SnappingManager.PropertiesWidth < 5) {
+ SnappingManager.SetPropertiesWidth(250);
}
};
@@ -417,7 +416,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
@computed
get toolbarWidth(): number {
- const presBoxDocView = DocumentManager.Instance.getDocumentView(this.presBox);
+ const presBoxDocView = DocumentView.getDocumentView(this.presBox);
const width = NumCast(this.presBox?._width);
return presBoxDocView ? presBoxDocView._props.PanelWidth() : width || 300;
}
diff --git a/src/client/views/pdf/AnchorMenu.tsx b/src/client/views/pdf/AnchorMenu.tsx
index f02c56471..a837969aa 100644
--- a/src/client/views/pdf/AnchorMenu.tsx
+++ b/src/client/views/pdf/AnchorMenu.tsx
@@ -8,12 +8,12 @@ import { ClientUtils, returnFalse, setupMoveUpEvents } from '../../../ClientUtil
import { emptyFunction, unimplementedFunction } from '../../../Utils';
import { Doc, Opt } from '../../../fields/Doc';
import { DocumentType } from '../../documents/DocumentTypes';
-import { SelectionManager } from '../../util/SelectionManager';
import { SettingsManager } from '../../util/SettingsManager';
import { AntimodeMenu, AntimodeMenuProps } from '../AntimodeMenu';
import { LinkPopup } from '../linking/LinkPopup';
import './AnchorMenu.scss';
import { GPTPopup } from './GPTPopup/GPTPopup';
+import { DocumentView } from '../nodes/DocumentView';
@observer
export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
@@ -66,7 +66,7 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
componentDidMount() {
this._disposer = reaction(
- () => SelectionManager.Views.slice(),
+ () => DocumentView.Selected().slice(),
() => AnchorMenu.Instance.fadeOut(true)
);
}
@@ -145,7 +145,7 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
* all selected text available to summarize but its only supported for pdf and web ATM.
* @returns Whether the GPT icon for summarization should appear
*/
- canSummarize = () => SelectionManager.Docs.some(doc => [DocumentType.PDF, DocumentType.WEB].includes(doc.type as any));
+ canSummarize = () => DocumentView.SelectedDocs().some(doc => [DocumentType.PDF, DocumentType.WEB].includes(doc.type as any));
render() {
const buttons =
diff --git a/src/client/views/pdf/Annotation.tsx b/src/client/views/pdf/Annotation.tsx
index 8b2b179d3..7dd4047c1 100644
--- a/src/client/views/pdf/Annotation.tsx
+++ b/src/client/views/pdf/Annotation.tsx
@@ -5,10 +5,10 @@ import { Doc, DocListCast, Opt, StrListCast } from '../../../fields/Doc';
import { Highlight } from '../../../fields/DocSymbols';
import { List } from '../../../fields/List';
import { BoolCast, DocCast, NumCast, StrCast } from '../../../fields/Types';
-import { LinkFollower } from '../../util/LinkFollower';
import { LinkManager } from '../../util/LinkManager';
import { undoable } from '../../util/UndoManager';
import { ObservableReactComponent } from '../ObservableReactComponent';
+import { DocumentView } from '../nodes/DocumentView';
import { FieldViewProps } from '../nodes/FieldView';
import { OpenWhere } from '../nodes/OpenWhere';
import { AnchorMenu } from './AnchorMenu';
@@ -56,7 +56,7 @@ export class Annotation extends ObservableReactComponent<IAnnotationProps> {
@computed get linkHighlighted() {
const found = LinkManager.Instance.getAllDirectLinks(this._props.annoDoc).find(link => {
- const a1 = LinkManager.getOppositeAnchor(link, this._props.annoDoc);
+ const a1 = Doc.getOppositeAnchor(link, this._props.annoDoc);
return a1 && Doc.GetBrushStatus(DocCast(a1.annotationOn, a1));
});
return found;
@@ -103,7 +103,7 @@ export class Annotation extends ObservableReactComponent<IAnnotationProps> {
e.preventDefault();
} else if (e.button === 0) {
e.stopPropagation();
- LinkFollower.FollowLink(undefined, this._props.annoDoc, false);
+ DocumentView.FollowLink(undefined, this._props.annoDoc, false);
}
};
brushed = () => this._props.annoDoc && Doc.GetBrushHighlightStatus(this._props.annoDoc);
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index 15ac73f78..45b1d727e 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -15,17 +15,17 @@ import { Cast, NumCast, StrCast } from '../../../fields/Types';
import { TraceMobx } from '../../../fields/util';
import { emptyFunction } from '../../../Utils';
import { DocUtils } from '../../documents/DocUtils';
-import { SelectionManager } from '../../util/SelectionManager';
import { SnappingManager } from '../../util/SnappingManager';
import { MarqueeOptionsMenu } from '../collections/collectionFreeForm';
import { CollectionFreeFormView } from '../collections/collectionFreeForm/CollectionFreeFormView';
import { MarqueeAnnotator } from '../MarqueeAnnotator';
+import { DocumentView } from '../nodes/DocumentView';
import { FieldViewProps } from '../nodes/FieldView';
import { FocusViewOptions } from '../nodes/FocusViewOptions';
import { LinkInfo } from '../nodes/LinkDocPreview';
import { PDFBox } from '../nodes/PDFBox';
import { ObservableReactComponent } from '../ObservableReactComponent';
-import { StyleProp } from '../StyleProvider';
+import { StyleProp } from '../StyleProp';
import { AnchorMenu } from './AnchorMenu';
import { Annotation } from './Annotation';
import { GPTPopup } from './GPTPopup/GPTPopup';
@@ -122,7 +122,7 @@ export class PDFViewer extends ObservableReactComponent<IViewerProps> {
this._disposers.selected = reaction(
() => this._props.isSelected(),
- () => SelectionManager.Views.length === 1 && this.setupPdfJsViewer(),
+ () => DocumentView.Selected().length === 1 && this.setupPdfJsViewer(),
{ fireImmediately: true }
);
this._disposers.curPage = reaction(
diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx
index 5df934231..56552c952 100644
--- a/src/client/views/search/SearchBox.tsx
+++ b/src/client/views/search/SearchBox.tsx
@@ -12,16 +12,15 @@ import { DocCast, StrCast } from '../../../fields/Types';
import { DocUtils } from '../../documents/DocUtils';
import { DocumentType } from '../../documents/DocumentTypes';
import { Docs } from '../../documents/Documents';
-import { DocumentManager } from '../../util/DocumentManager';
-import { LinkManager } from '../../util/LinkManager';
import { SearchUtil } from '../../util/SearchUtil';
-import { SettingsManager } from '../../util/SettingsManager';
+import { SnappingManager } from '../../util/SnappingManager';
import { undoBatch } from '../../util/UndoManager';
import { ViewBoxBaseComponent } from '../DocComponent';
import { ObservableReactComponent } from '../ObservableReactComponent';
import { CollectionDockingView } from '../collections/CollectionDockingView';
import { IRecommendation, Recommendation } from '../newlightbox/components';
import { fetchRecommendations } from '../newlightbox/utils';
+import { DocumentView } from '../nodes/DocumentView';
import { FieldView, FieldViewProps } from '../nodes/FieldView';
import './SearchBox.scss';
@@ -54,7 +53,7 @@ export class SearchBoxItem extends ObservableReactComponent<SearchBoxItemProps>
* or opening it in a new tab.
*/
selectElement = async (doc: Doc, finishFunc: () => void) => {
- await DocumentManager.Instance.showDocument(doc, { willZoomCentered: true }, finishFunc);
+ await DocumentView.showDocument(doc, { willZoomCentered: true }, finishFunc);
};
/**
@@ -65,12 +64,12 @@ export class SearchBoxItem extends ObservableReactComponent<SearchBoxItemProps>
*/
onResultClick = action(async (doc: Doc) => {
this._props.selectItem(doc);
- this.selectElement(doc, () => DocumentManager.Instance.getFirstDocumentView(doc)?.ComponentView?.search?.(this._props.searchString, undefined, false));
+ this.selectElement(doc, () => DocumentView.getFirstDocumentView(doc)?.ComponentView?.search?.(this._props.searchString, undefined, false));
});
componentWillUnmount(): void {
const doc = this._props.Document;
- DocumentManager.Instance.getFirstDocumentView(doc)?.ComponentView?.search?.('', undefined, true);
+ DocumentView.getFirstDocumentView(doc)?.ComponentView?.search?.('', undefined, true);
}
@undoBatch
@@ -99,20 +98,18 @@ export class SearchBoxItem extends ObservableReactComponent<SearchBoxItemProps>
}
}
style={{
- fontWeight: LinkManager.Links(this._props.linkFrom).find(
- link =>
- Doc.AreProtosEqual(LinkManager.getOppositeAnchor(link, this._props.linkFrom!), this._props.Document) ||
- Doc.AreProtosEqual(DocCast(LinkManager.getOppositeAnchor(link, this._props.linkFrom!)?.annotationOn), this._props.Document)
+ fontWeight: Doc.Links(this._props.linkFrom).find(
+ link => Doc.AreProtosEqual(Doc.getOppositeAnchor(link, this._props.linkFrom!), this._props.Document) || Doc.AreProtosEqual(DocCast(Doc.getOppositeAnchor(link, this._props.linkFrom!)?.annotationOn), this._props.Document)
)
? 'bold'
: '',
}}
className={this._props.className}>
<div className="searchBox-result-title">{title as string}</div>
- <div className="searchBox-result-type" style={{ color: SettingsManager.userVariantColor }}>
+ <div className="searchBox-result-type" style={{ color: SnappingManager.userVariantColor }}>
{formattedType}
</div>
- <div className="searchBox-result-keys" style={{ color: SettingsManager.userVariantColor }}>
+ <div className="searchBox-result-keys" style={{ color: SnappingManager.userVariantColor }}>
{this._props.matchedKeys.join(', ')}
</div>
</div>
@@ -373,7 +370,7 @@ export class SearchBox extends ViewBoxBaseComponent<SearchBoxProps>() {
const query = StrCast(this._searchString);
Doc.SetSearchQuery(query);
- if (!this._props.linkSearch) Array.from(this._results.keys()).forEach(doc => DocumentManager.Instance.getFirstDocumentView(doc)?.ComponentView?.search?.(this._searchString, undefined, true));
+ if (!this._props.linkSearch) Array.from(this._results.keys()).forEach(doc => DocumentView.getFirstDocumentView(doc)?.ComponentView?.search?.(this._searchString, undefined, true));
this._results.clear();
if (query) {
@@ -412,7 +409,7 @@ export class SearchBox extends ViewBoxBaseComponent<SearchBoxProps>() {
this._timeout && clearTimeout(this._timeout);
this._timeout = undefined;
this._results.forEach((_, doc) => {
- DocumentManager.Instance.getFirstDocumentView(doc)?.ComponentView?.search?.('', undefined, true);
+ DocumentView.getFirstDocumentView(doc)?.ComponentView?.search?.('', undefined, true);
Doc.UnBrushDoc(doc);
Doc.UnHighlightDoc(doc);
Doc.ClearSearchMatches();
@@ -476,7 +473,7 @@ export class SearchBox extends ViewBoxBaseComponent<SearchBoxProps>() {
const recommendationsJSX: JSX.Element[] = this._recommendations.map(props => <Recommendation {...props} />);
return (
- <div className="searchBox-container" style={{ pointerEvents: 'all', color: SettingsManager.userColor, background: SettingsManager.userBackgroundColor }}>
+ <div className="searchBox-container" style={{ pointerEvents: 'all', color: SnappingManager.userColor, background: SnappingManager.userBackgroundColor }}>
<div className="searchBox-bar">
{isLinkSearch ? null : (
<select name="type" id="searchBox-type" className="searchBox-type" onChange={this.onSelectChange}>
@@ -501,7 +498,7 @@ export class SearchBox extends ViewBoxBaseComponent<SearchBoxProps>() {
</div>
{resultsJSX.length > 0 && (
<div className="searchBox-results-container">
- <div className="section-header" style={{ background: SettingsManager.userVariantColor }}>
+ <div className="section-header" style={{ background: SnappingManager.userVariantColor }}>
<div className="section-title">Results</div>
<div className="section-subtitle">{`${validResults} result` + (validResults === 1 ? '' : 's')}</div>
</div>
@@ -510,7 +507,7 @@ export class SearchBox extends ViewBoxBaseComponent<SearchBoxProps>() {
)}
{recommendationsJSX.length > 0 && (
<div className="searchBox-recommendations-container">
- <div className="section-header" style={{ background: SettingsManager.userVariantColor }}>
+ <div className="section-header" style={{ background: SnappingManager.userVariantColor }}>
<div className="section-title">Recommendations</div>
<div className="section-subtitle">{`${validResults} result` + (validResults === 1 ? '' : 's')}</div>
</div>
diff --git a/src/client/views/selectedDoc/SelectedDocView.tsx b/src/client/views/selectedDoc/SelectedDocView.tsx
index 6ed3b240d..78a1a92f7 100644
--- a/src/client/views/selectedDoc/SelectedDocView.tsx
+++ b/src/client/views/selectedDoc/SelectedDocView.tsx
@@ -6,8 +6,8 @@ import * as React from 'react';
import { emptyFunction } from '../../../Utils';
import { Doc } from '../../../fields/Doc';
import { StrCast } from '../../../fields/Types';
-import { DocumentManager } from '../../util/DocumentManager';
-import { SettingsManager } from '../../util/SettingsManager';
+import { SnappingManager } from '../../util/SnappingManager';
+import { DocumentView } from '../nodes/DocumentView';
import { FocusViewOptions } from '../nodes/FocusViewOptions';
export interface SelectedDocViewProps {
@@ -33,14 +33,14 @@ export class SelectedDocView extends React.Component<SelectedDocViewProps> {
return {
text: StrCast(doc.title),
val: StrCast(doc._id),
- color: SettingsManager.userColor,
- background: SettingsManager.userBackgroundColor,
+ color: SnappingManager.userColor,
+ background: SnappingManager.userBackgroundColor,
icon: <FontAwesomeIcon size="1x" icon={Doc.toIcon(doc)} />,
- onClick: () => DocumentManager.Instance.showDocument(doc, options, emptyFunction),
+ onClick: () => DocumentView.showDocument(doc, options, emptyFunction),
};
})}
- color={SettingsManager.userColor}
- background={SettingsManager.userBackgroundColor}
+ color={SnappingManager.userColor}
+ background={SnappingManager.userBackgroundColor}
/>
</div>
);
diff --git a/src/client/views/topbar/TopBar.tsx b/src/client/views/topbar/TopBar.tsx
index f82ae34c5..9f97efcce 100644
--- a/src/client/views/topbar/TopBar.tsx
+++ b/src/client/views/topbar/TopBar.tsx
@@ -11,8 +11,6 @@ import { AclAdmin, DashVersion } from '../../../fields/DocSymbols';
import { StrCast } from '../../../fields/Types';
import { GetEffectiveAcl } from '../../../fields/util';
import { emptyFunction } from '../../../Utils';
-import { CurrentUserUtils } from '../../util/CurrentUserUtils';
-import { DocumentManager } from '../../util/DocumentManager';
import { dropActionType } from '../../util/DropActionTypes';
import { PingManager } from '../../util/PingManager';
import { ReportManager } from '../../util/reportManager/ReportManager';
@@ -25,7 +23,7 @@ import { CollectionDockingView } from '../collections/CollectionDockingView';
import { CollectionLinearView } from '../collections/collectionLinear';
import { DashboardView } from '../DashboardView';
import { Colors } from '../global/globalEnums';
-import { DocumentViewInternal, returnEmptyDocViewList } from '../nodes/DocumentView';
+import { DocumentView, DocumentViewInternal, returnEmptyDocViewList } from '../nodes/DocumentView';
import { ObservableReactComponent } from '../ObservableReactComponent';
import { DefaultStyleProvider } from '../StyleProvider';
import './TopBar.scss';
@@ -170,7 +168,7 @@ export class TopBar extends ObservableReactComponent<{}> {
color={this.color}
style={{ fontWeight: 700, fontSize: '1rem' }}
onClick={(e: React.MouseEvent) => {
- const dashView = Doc.ActiveDashboard && DocumentManager.Instance.getDocumentView(Doc.ActiveDashboard);
+ const dashView = Doc.ActiveDashboard && DocumentView.getDocumentView(Doc.ActiveDashboard);
dashView?.showContextMenu(e.clientX + 20, e.clientY + 30);
}}
/>
@@ -184,7 +182,7 @@ export class TopBar extends ObservableReactComponent<{}> {
* and allows the user to access their account settings etc.
*/
@computed get topbarRight() {
- const upToDate = DashVersion === CurrentUserUtils.ServerVersion;
+ const upToDate = DashVersion === SnappingManager.ServerVersion;
return (
<div className="topbar-right">
{Doc.ActiveDashboard ? (
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index 5fd053eef..bb6995398 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -224,8 +224,25 @@ export class Doc extends RefField {
@observable public static GuestDashboard: Doc | undefined = undefined;
@observable public static GuestTarget: Doc | undefined = undefined;
@observable public static GuestMobile: Doc | undefined = undefined;
+ @observable.shallow public static CurrentlyLoading: Doc[] = observable([]);
+ // removes from currently loading display
+ public static removeCurrentlyLoading(doc: Doc) {
+ if (Doc.CurrentlyLoading) {
+ const index = Doc.CurrentlyLoading.indexOf(doc);
+ runInAction(() => index !== -1 && Doc.CurrentlyLoading.splice(index, 1));
+ }
+ }
+ // adds doc to currently loading display
+ public static addCurrentlyLoading(doc: Doc) {
+ if (Doc.CurrentlyLoading.indexOf(doc) === -1) {
+ runInAction(() => Doc.CurrentlyLoading.push(doc));
+ }
+ }
- public static AddLink: undefined | ((link: Doc, checkExists?: boolean) => void);
+ public static AddLink: (link: Doc, checkExists?: boolean) => void;
+ public static DeleteLink: (link: Doc) => void;
+ public static Links: (link: Doc | undefined) => Doc[];
+ public static getOppositeAnchor: (linkDoc: Doc, anchor: Doc) => Doc | undefined;
public static get MySharedDocs() { return DocCast(Doc.UserDoc().mySharedDocs); } // prettier-ignore
public static get MyUserDocView() { return DocCast(Doc.UserDoc().myUserDocView); } // prettier-ignore
diff --git a/src/fields/ScriptField.ts b/src/fields/ScriptField.ts
index 8a3787768..8fe365ac2 100644
--- a/src/fields/ScriptField.ts
+++ b/src/fields/ScriptField.ts
@@ -142,7 +142,6 @@ export class ScriptField extends ObjectField {
return CompileScript(script, {
params: {
this: Doc?.name || 'Doc', // this is the doc that executes the script
- self: Doc?.name || 'Doc', // self is the root doc of the doc that executes the script
documentView: 'any',
_last_: 'any', // _last_ is the previous value of a computed field when it is being triggered to re-run.
_setCacheResult_: 'any', // set the cached value of the function
diff --git a/src/fields/documentSchemas.ts b/src/fields/documentSchemas.ts
index c73689e1f..335683270 100644
--- a/src/fields/documentSchemas.ts
+++ b/src/fields/documentSchemas.ts
@@ -86,7 +86,6 @@ export const documentSchema = createSchema({
followLinkLocation: 'string', // flag for where to place content when following a click interaction (e.g., add:right, lightbox, default, )
hideLinkButton: 'boolean', // whether the blue link counter button should be hidden
layout_hideAllLinks: 'boolean', // whether all individual blue anchor dots should be hidden
- link_displayLine: 'boolean', // whether a link connection should be shown between link anchor endpoints.
isLightbox: 'boolean', // whether the marked object will display addDocTab() calls that target "lightbox" destinations
layers: listSpec('string'), // which layers the document is part of
_lockedPosition: 'boolean', // whether the document can be moved (dragged)
diff --git a/src/mobile/MobileInterface.tsx b/src/mobile/MobileInterface.tsx
index 55a85ed1b..7e67690d3 100644
--- a/src/mobile/MobileInterface.tsx
+++ b/src/mobile/MobileInterface.tsx
@@ -92,7 +92,6 @@ import {
faTrash,
faTrashAlt,
faTree,
- faRoute,
faTv,
faUndoAlt,
faVideo,
@@ -104,7 +103,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { action, computed, observable, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue } from '../ClientUtils';
+import { returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue } from '../ClientUtils';
import { CollectionViewType, DocumentType } from '../client/documents/DocumentTypes';
import { Docs, DocumentOptions } from '../client/documents/Documents';
import { CurrentUserUtils } from '../client/util/CurrentUserUtils';
@@ -112,8 +111,8 @@ import { ScriptingGlobals } from '../client/util/ScriptingGlobals';
import { SettingsManager } from '../client/util/SettingsManager';
import { Transform } from '../client/util/Transform';
import { UndoManager } from '../client/util/UndoManager';
+import { DashboardView } from '../client/views/DashboardView';
import { GestureOverlay } from '../client/views/GestureOverlay';
-import { TabDocView } from '../client/views/collections/TabDocView';
import { AudioBox } from '../client/views/nodes/AudioBox';
import { DocumentView } from '../client/views/nodes/DocumentView';
import { RadialMenu } from '../client/views/nodes/RadialMenu';
@@ -127,7 +126,7 @@ import './AudioUpload.scss';
import { Uploader } from './ImageUpload';
import './ImageUpload.scss';
import './MobileInterface.scss';
-import { DashboardView } from '../client/views/DashboardView';
+import { emptyFunction } from '../Utils';
library.add(
...[
@@ -691,7 +690,7 @@ export class MobileInterface extends React.Component {
// Only making button available if it is an image
if (!(this._activeDoc.type === 'collection' || this._activeDoc.type === 'presentation')) {
return (
- <div className="docButton" title={'Pin to presentation'} style={{ backgroundColor: 'white', color: 'black' }} onClick={e => TabDocView.PinDoc(this._activeDoc, {})}>
+ <div className="docButton" title={'Pin to presentation'} style={{ backgroundColor: 'white', color: 'black' }} onClick={e => DocumentView.PinDoc(this._activeDoc, {})}>
<FontAwesomeIcon className="documentdecorations-icon" size="sm" icon="map-pin" />
</div>
);
diff --git a/src/server/SharedMediaTypes.ts b/src/server/SharedMediaTypes.ts
index 0a961f570..8ae13454e 100644
--- a/src/server/SharedMediaTypes.ts
+++ b/src/server/SharedMediaTypes.ts
@@ -13,6 +13,11 @@ export namespace AcceptableMedia {
export const audioFormats = ['.wav', '.mp3', '.mpeg', '.flac', '.au', '.aiff', '.m4a', '.webm'];
}
+export enum AudioAnnoState {
+ stopped = 'stopped',
+ playing = 'playing',
+}
+
export namespace Upload {
export function isImageInformation(uploadResponse: Upload.FileInformation): uploadResponse is Upload.ImageInformation {
return 'nativeWidth' in uploadResponse;