aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/collections
diff options
context:
space:
mode:
authorEric <ericmabr@gmail.com>2023-03-15 17:29:33 -0400
committerEric <ericmabr@gmail.com>2023-03-15 17:29:33 -0400
commit06980bb5fa9f72ad20896be132bcc29e9ae4617e (patch)
treee98357191b26b14bd17b3f8d4656b6789022e1cd /src/client/views/collections
parentc50fc16a161379b20eed04794d1433499b1483c7 (diff)
parent20c0190e820f2bd343693368b7ef55a91f19c880 (diff)
Merge branch 'master' into UI_Update_Eric_Ma
Diffstat (limited to 'src/client/views/collections')
-rw-r--r--src/client/views/collections/CollectionDockingView.tsx19
-rw-r--r--src/client/views/collections/CollectionNoteTakingView.scss20
-rw-r--r--src/client/views/collections/CollectionNoteTakingView.tsx58
-rw-r--r--src/client/views/collections/CollectionNoteTakingViewColumn.tsx62
-rw-r--r--src/client/views/collections/CollectionStackedTimeline.tsx23
-rw-r--r--src/client/views/collections/CollectionStackingView.tsx13
-rw-r--r--src/client/views/collections/CollectionSubView.tsx2
-rw-r--r--src/client/views/collections/CollectionTimeView.tsx60
-rw-r--r--src/client/views/collections/CollectionTreeView.tsx4
-rw-r--r--src/client/views/collections/CollectionView.tsx8
-rw-r--r--src/client/views/collections/TabDocView.scss6
-rw-r--r--src/client/views/collections/TabDocView.tsx42
-rw-r--r--src/client/views/collections/TreeView.tsx109
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx2
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx1
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx266
-rw-r--r--src/client/views/collections/collectionFreeForm/MarqueeView.tsx5
-rw-r--r--src/client/views/collections/collectionLinear/CollectionLinearView.tsx11
-rw-r--r--src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx3
-rw-r--r--src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx1
-rw-r--r--src/client/views/collections/collectionSchema/CollectionSchemaCells.tsx2
21 files changed, 326 insertions, 391 deletions
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 1ead80bd0..9b6554d67 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -26,6 +26,9 @@ import { CollectionSubView, SubCollectionViewProps } from './CollectionSubView';
import { TabDocView } from './TabDocView';
import React = require('react');
import { OpenWhere, OpenWhereMod } from '../nodes/DocumentView';
+import { OverlayView } from '../OverlayView';
+import { ScriptingRepl } from '../ScriptingRepl';
+import { ScriptField } from '../../../fields/ScriptField';
const _global = (window /* browser */ || global) /* node */ as any;
@observer
@@ -580,15 +583,21 @@ ScriptingGlobals.add(
'(doc: any)'
);
ScriptingGlobals.add(
- function openOnRight(doc: any) {
- return CollectionDockingView.AddSplit(doc, OpenWhereMod.right);
+ function openDoc(doc: any, where: OpenWhere) {
+ switch (where) {
+ case OpenWhere.addRight:
+ return CollectionDockingView.AddSplit(doc, OpenWhereMod.right);
+ case OpenWhere.overlay:
+ if (doc === 'repl') OverlayView.Instance.addWindow(<ScriptingRepl />, { x: 300, y: 100, width: 200, height: 200, title: 'Scripting REPL' });
+ else Doc.AddDocToList(Doc.MyOverlayDocs, undefined, doc);
+ }
},
- 'opens up document in tab on right side of the screen',
+ 'opens up document in location specified',
'(doc: any)'
);
ScriptingGlobals.add(
- function openInOverlay(doc: any) {
- return Doc.AddDocToList(Doc.MyOverlayDocs, undefined, doc);
+ function openRepl() {
+ return 'openRepl';
},
'opens up document in screen overlay layer',
'(doc: any)'
diff --git a/src/client/views/collections/CollectionNoteTakingView.scss b/src/client/views/collections/CollectionNoteTakingView.scss
index 4d1f18e54..be1800d81 100644
--- a/src/client/views/collections/CollectionNoteTakingView.scss
+++ b/src/client/views/collections/CollectionNoteTakingView.scss
@@ -51,10 +51,6 @@
display: flex;
}
-.collectionNoteTakingViewFieldColumn {
- display: flex;
- overflow: auto;
-}
.collectionNoteTakingViewFieldColumn:hover {
.collectionNoteTakingView-DocumentButtons {
display: flex;
@@ -98,6 +94,11 @@
position: relative;
display: block;
}
+ .collectionNoteTakingViewFieldColumn {
+ overflow: auto;
+ display: flex;
+ flex-direction: column;
+ }
.collectionSchemaView-previewDoc {
height: 100%;
@@ -111,14 +112,19 @@
height: auto;
}
+ .collectionNoteTakingView-columnStackContainer {
+ height: 100%;
+ overflow: auto;
+ width: 100%;
+ display: flex;
+ }
.collectionNoteTakingView-columnStack {
height: 100%;
width: 100%;
- display: inline-block;
+ display: table-cell;
}
.collectionNoteTakingView-Nodes {
width: 100%;
- height: 100%;
position: absolute;
display: flex;
flex-direction: column;
@@ -128,7 +134,6 @@
width: 100%;
position: absolute;
margin: auto;
- width: max-content;
height: max-content;
position: relative;
grid-auto-rows: 0px;
@@ -165,6 +170,7 @@
// Documents in NoteTaking view
.collectionNoteTakingView-columnDoc {
display: flex;
+ width: 100%;
// margin: auto; // Removed auto so that it is no longer center aligned - this could be something we change
position: relative;
diff --git a/src/client/views/collections/CollectionNoteTakingView.tsx b/src/client/views/collections/CollectionNoteTakingView.tsx
index 26c73438c..fbf7db892 100644
--- a/src/client/views/collections/CollectionNoteTakingView.tsx
+++ b/src/client/views/collections/CollectionNoteTakingView.tsx
@@ -3,7 +3,7 @@ import { CursorProperty } from 'csstype';
import { action, computed, IReactionDisposer, observable, reaction } from 'mobx';
import { observer } from 'mobx-react';
import { DataSym, Doc, Field, HeightSym, Opt, WidthSym } from '../../../fields/Doc';
-import { Copy, Id } from '../../../fields/FieldSymbols';
+import { Id } from '../../../fields/FieldSymbols';
import { List } from '../../../fields/List';
import { listSpec } from '../../../fields/Schema';
import { SchemaHeaderField } from '../../../fields/SchemaHeaderField';
@@ -11,7 +11,6 @@ import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../fields/Ty
import { TraceMobx } from '../../../fields/util';
import { emptyFunction, returnEmptyDoclist, returnFalse, returnTrue, returnZero, smoothScroll, Utils } from '../../../Utils';
import { Docs, DocUtils } from '../../documents/Documents';
-import { DocumentType } from '../../documents/DocumentTypes';
import { DragManager, dropActionType } from '../../util/DragManager';
import { SnappingManager } from '../../util/SnappingManager';
import { Transform } from '../../util/Transform';
@@ -19,7 +18,7 @@ import { undoBatch } from '../../util/UndoManager';
import { ContextMenu } from '../ContextMenu';
import { ContextMenuProps } from '../ContextMenuItem';
import { LightboxView } from '../LightboxView';
-import { DocFocusOptions, DocumentView, DocumentViewProps, OpenWhere, ViewAdjustment } from '../nodes/DocumentView';
+import { DocFocusOptions, DocumentView, DocumentViewProps } from '../nodes/DocumentView';
import { FieldViewProps } from '../nodes/FieldView';
import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox';
import { StyleProp } from '../StyleProvider';
@@ -55,11 +54,11 @@ export class CollectionNoteTakingView extends CollectionSubView() {
const needsUnsetCategory = this.childDocs.some(d => !d[this.notetakingCategoryField] && !columnHeaders?.find(sh => sh.heading === 'unset'));
if (needsUnsetCategory || columnHeaders === undefined || columnHeaders.length === 0) {
setTimeout(() => {
- const columnHeaders = Cast(this.dataDoc.columnHeaders, listSpec(SchemaHeaderField), null);
+ const columnHeaders = Array.from(Cast(this.dataDoc.columnHeaders, listSpec(SchemaHeaderField), null) ?? []);
const needsUnsetCategory = this.childDocs.some(d => !d[this.notetakingCategoryField] && !columnHeaders?.find(sh => sh.heading === 'unset'));
- if (needsUnsetCategory || columnHeaders === undefined || columnHeaders.length === 0) {
- if (columnHeaders) columnHeaders.push(new SchemaHeaderField('unset', undefined, undefined, 1));
- else this.dataDoc.columnHeaders = new List<SchemaHeaderField>();
+ if (needsUnsetCategory || columnHeaders.length === 0) {
+ columnHeaders.push(new SchemaHeaderField('unset', undefined, undefined, 1));
+ this.resizeColumns(columnHeaders);
}
});
}
@@ -187,20 +186,16 @@ export class CollectionNoteTakingView extends CollectionSubView() {
// let's dive in and get the actual document we want to drag/move around
focusDocument = (doc: Doc, options: DocFocusOptions) => {
Doc.BrushDoc(doc);
- let focusSpeed = 0;
const found = this._mainCont && Array.from(this._mainCont.getElementsByClassName('documentView-node')).find((node: any) => node.id === doc[Id]);
if (found) {
const top = found.getBoundingClientRect().top;
const localTop = this.props.ScreenToLocalTransform().transformPoint(0, top);
if (Math.floor(localTop[1]) !== 0) {
- smoothScroll((focusSpeed = options.zoomTime ?? 500), this._mainCont!, localTop[1] + this._mainCont!.scrollTop, options.easeFunc);
+ let focusSpeed = options.zoomTime ?? 500;
+ smoothScroll(focusSpeed, this._mainCont!, localTop[1] + this._mainCont!.scrollTop, options.easeFunc);
+ return focusSpeed;
}
}
- const endFocus = async (moved: boolean) => (options?.afterFocus ? options?.afterFocus(moved) : ViewAdjustment.doNothing);
- this.props.focus(this.rootDoc, {
- ...options,
- afterFocus: (didFocus: boolean) => new Promise<ViewAdjustment>(res => setTimeout(async () => res(await endFocus(didFocus)), focusSpeed)),
- });
};
styleProvider = (doc: Doc | undefined, props: Opt<DocumentViewProps>, property: string) => {
@@ -217,6 +212,7 @@ export class CollectionNoteTakingView extends CollectionSubView() {
isContentActive = () => this.props.isSelected() || this.props.isContentActive();
+ blockPointerEventsWhenDragging = () => (this.docsDraggedRowCol.length ? 'none' : undefined);
// getDisplayDoc returns the rules for displaying a document in this view (ie. DocumentView)
getDisplayDoc(doc: Doc, width: () => number) {
const dataDoc = !doc.isTemplateDoc && !doc.isTemplateForField && !doc.PARAMS ? undefined : this.props.DataDoc;
@@ -227,6 +223,7 @@ export class CollectionNoteTakingView extends CollectionSubView() {
<DocumentView
ref={r => (dref = r || undefined)}
Document={doc}
+ pointerEvents={this.blockPointerEventsWhenDragging}
DataDoc={dataDoc || (!Doc.AreProtosEqual(doc[DataSym], doc) && doc[DataSym])}
renderDepth={this.props.renderDepth + 1}
PanelWidth={width}
@@ -276,7 +273,7 @@ export class CollectionNoteTakingView extends CollectionSubView() {
// getDocTransform is used to get the coordinates of a document when we go from a view like freeform to columns
getDocTransform(doc: Doc, dref?: DocumentView) {
const y = this._scroll; // required for document decorations to update when the text box container is scrolled
- const { scale, translateX, translateY } = Utils.GetScreenTransform(dref?.ContentDiv || undefined);
+ const { translateX, translateY } = Utils.GetScreenTransform(dref?.ContentDiv || undefined);
// the document view may center its contents and if so, will prepend that onto the screenToLocalTansform. so we have to subtract that off
return new Transform(-translateX + (dref?.centeringX || 0), -translateY + (dref?.centeringY || 0), 1).scale(this.props.ScreenToLocalTransform().Scale);
}
@@ -319,18 +316,16 @@ export class CollectionNoteTakingView extends CollectionSubView() {
// Removing example: column widths are [0.5, 0.30, 0.20] --> user deletes the final column --> column widths are [0.625, 0.375].
// Adding example: column widths are [0.6, 0.4] --> user adds column at end --> column widths are [0.4, 0.267, 0.33]
@action
- resizeColumns = (isAdd: boolean, colWidth: number, colIndex: number) => {
- const n = this.columnHeaders.length;
- if (n == 1) {
- this.columnHeaders[0].setWidth(1);
- return true;
- }
- const scaleFactor = isAdd ? 1 - colWidth : 1 / (1 - colWidth);
- this.columnHeaders.forEach((h, i) => {
- if (!(isAdd && i == colIndex)) {
- h.width < 0 ? h.setWidth(1 / n) : h.setWidth(h.width * scaleFactor);
- }
- });
+ resizeColumns = (headers: SchemaHeaderField[]) => {
+ const n = headers.length;
+ const curWidths = headers.reduce((sum, hdr) => sum + Math.abs(hdr.width), 0);
+ const scaleFactor = 1 / curWidths;
+ this.dataDoc.columnHeaders = new List<SchemaHeaderField>(
+ headers.map(h => {
+ h.setWidth(Math.abs(h.width) * scaleFactor);
+ return h;
+ })
+ );
return true;
};
@@ -533,7 +528,6 @@ export class CollectionNoteTakingView extends CollectionSubView() {
dividerWidth={this.DividerWidth}
maxColWidth={this.maxColWidth}
availableWidth={this.availableWidth}
- PanelWidth={this.PanelWidth}
key={heading?.heading ?? 'unset'}
headings={this.headings}
heading={heading?.heading ?? 'unset'}
@@ -555,16 +549,16 @@ export class CollectionNoteTakingView extends CollectionSubView() {
addGroup = (value: string) => {
if (this.columnHeaders) {
for (const header of this.columnHeaders) {
- if (header.heading == value) {
+ if (header.heading === value) {
alert('You cannot use an existing column name. Please try a new column name');
return value;
}
}
}
- const columnHeaders = Cast(this.props.Document.columnHeaders, listSpec(SchemaHeaderField), null);
+ const columnHeaders = Array.from(Cast(this.props.Document.columnHeaders, listSpec(SchemaHeaderField), null));
const newColWidth = 1 / (this.numGroupColumns + 1);
- value && columnHeaders?.push(new SchemaHeaderField(value, undefined, undefined, newColWidth)) && this.resizeColumns(true, newColWidth, this.columnHeaders.length - 1);
- this.dataDoc.columnHeaders = new List<SchemaHeaderField>(columnHeaders.map(header => header[Copy]()));
+ columnHeaders.push(new SchemaHeaderField(value, undefined, undefined, newColWidth));
+ value && this.resizeColumns(columnHeaders);
return true;
};
diff --git a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
index 84d1c0205..829d055e5 100644
--- a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
+++ b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
@@ -44,8 +44,7 @@ interface CSVFieldColumnProps {
observeHeight: (myref: any) => void;
unobserveHeight: (myref: any) => void;
editableViewProps: () => any;
- resizeColumns: (isAdd: boolean, colWidth: number, colIndex: number) => boolean;
- PanelWidth: number;
+ resizeColumns: (headers: SchemaHeaderField[]) => boolean;
maxColWidth: number;
dividerWidth: number;
availableWidth: number;
@@ -141,18 +140,11 @@ export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColu
@undoBatch
@action
deleteColumn = () => {
- const acolumnHeaders = Cast(this.props.Document.columnHeaders, listSpec(SchemaHeaderField), null);
- if (acolumnHeaders && this.props.headingObject) {
- const index = acolumnHeaders.indexOf(this.props.headingObject);
- const columnHeaders = acolumnHeaders; // new List<SchemaHeaderField>(acolumnHeaders.map(header => header[Copy]())); // needed for undo to work properly. otherwise we end up changing field values in the undo stack since they are shared by reference
- const newColIndex = index > 0 ? index - 1 : 1;
- const newColHeader = this.props.columnHeaders ? this.props.columnHeaders[newColIndex] : undefined;
- const newHeading = newColHeader ? newColHeader.heading : 'unset';
- this.props.docList.forEach(d => (d[this.props.pivotField] = newHeading));
- const colWidth = this.props.columnHeaders ? this.props.columnHeaders[index].width : 0;
- columnHeaders.splice(index, 1);
- //Doc.GetProto(this.props.Document).columnHeaders = columnHeaders;
- this.props.resizeColumns(false, colWidth, index);
+ const columnHeaders = Array.from(Cast(this.props.Document.columnHeaders, listSpec(SchemaHeaderField), null));
+ if (this.props.headingObject) {
+ this.props.docList.forEach(d => (d[this.props.pivotField] = undefined));
+ columnHeaders.splice(columnHeaders.indexOf(this.props.headingObject), 1);
+ this.props.resizeColumns(columnHeaders);
}
};
@@ -262,28 +254,30 @@ export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColu
return (
<>
{headingView}
- <div className="collectionNoteTakingView-columnStack">
- <div
- key={`${heading}-stack`}
- className={`collectionNoteTakingView-Nodes`}
- style={{
- padding: `${columnYMargin}px ${0}px ${this.props.yMargin}px ${0}px`,
- gridGap: this.props.gridGap,
- gridTemplateColumns: templatecols,
- }}>
- {this.props.renderChildren(this.props.docList)}
- </div>
+ <div className="collectionNoteTakingView-columnStackContainer">
+ <div className="collectionNoteTakingView-columnStack">
+ <div
+ key={`${heading}-stack`}
+ className={`collectionNoteTakingView-Nodes`}
+ style={{
+ padding: `${columnYMargin}px ${0}px ${this.props.yMargin}px ${0}px`,
+ gridGap: this.props.gridGap,
+ gridTemplateColumns: templatecols,
+ }}>
+ {this.props.renderChildren(this.props.docList)}
+ </div>
- {!this.props.chromeHidden && type !== DocumentType.PRES ? (
- <div className="collectionNoteTakingView-DocumentButtons" style={{ marginBottom: 10 }}>
- <div key={`${heading}-add-document`} className="collectionNoteTakingView-addDocumentButton">
- <EditableView GetValue={returnEmptyString} SetValue={this.addNewTextDoc} textCallback={this.textCallback} placeholder={"Type ':' for commands"} contents={'+ New Node'} menuCallback={this.menuCallback} />
- </div>
- <div key={`${this.props.Document[Id]}-addGroup`} className="collectionNoteTakingView-addDocumentButton">
- <EditableView {...this.props.editableViewProps()} />
+ {!this.props.chromeHidden && type !== DocumentType.PRES ? (
+ <div className="collectionNoteTakingView-DocumentButtons" style={{ marginBottom: 10 }}>
+ <div key={`${heading}-add-document`} className="collectionNoteTakingView-addDocumentButton">
+ <EditableView GetValue={returnEmptyString} SetValue={this.addNewTextDoc} textCallback={this.textCallback} placeholder={"Type ':' for commands"} contents={'+ New Node'} menuCallback={this.menuCallback} />
+ </div>
+ <div key={`${this.props.Document[Id]}-addGroup`} className="collectionNoteTakingView-addDocumentButton">
+ <EditableView {...this.props.editableViewProps()} />
+ </div>
</div>
- </div>
- ) : null}
+ ) : null}
+ </div>
</div>
</>
);
diff --git a/src/client/views/collections/CollectionStackedTimeline.tsx b/src/client/views/collections/CollectionStackedTimeline.tsx
index 28f08b6ce..5bdff347c 100644
--- a/src/client/views/collections/CollectionStackedTimeline.tsx
+++ b/src/client/views/collections/CollectionStackedTimeline.tsx
@@ -2,7 +2,7 @@ import React = require('react');
import { action, computed, IReactionDisposer, observable, reaction } from 'mobx';
import { observer } from 'mobx-react';
import { computedFn } from 'mobx-utils';
-import { Doc, DocListCast, Opt, StrListCast } from '../../../fields/Doc';
+import { Doc, Opt, StrListCast } from '../../../fields/Doc';
import { Id } from '../../../fields/FieldSymbols';
import { List } from '../../../fields/List';
import { listSpec } from '../../../fields/Schema';
@@ -15,6 +15,7 @@ import { DocumentType } from '../../documents/DocumentTypes';
import { DocumentManager } from '../../util/DocumentManager';
import { DragManager } from '../../util/DragManager';
import { LinkFollower } from '../../util/LinkFollower';
+import { LinkManager } from '../../util/LinkManager';
import { ScriptingGlobals } from '../../util/ScriptingGlobals';
import { SelectionManager } from '../../util/SelectionManager';
import { SnappingManager } from '../../util/SnappingManager';
@@ -54,7 +55,7 @@ export enum TrimScope {
@observer
export class CollectionStackedTimeline extends CollectionSubView<CollectionStackedTimelineProps>() {
@observable static SelectingRegion: CollectionStackedTimeline | undefined = undefined;
- @observable public static CurrentlyPlaying: Doc[];
+ @observable public static CurrentlyPlaying: DocumentView[];
static RangeScript: ScriptField;
static LabelScript: ScriptField;
@@ -190,7 +191,7 @@ export class CollectionStackedTimeline extends CollectionSubView<CollectionStack
CollectionStackedTimeline.SelectingRegion = this;
} else {
this._markerEnd = this.currentTime;
- CollectionStackedTimeline.createAnchor(this.rootDoc, this.dataDoc, this.props.fieldKey, this.props.startTag, this.props.endTag, this._markerStart, this._markerEnd, undefined, true);
+ CollectionStackedTimeline.createAnchor(this.rootDoc, this.dataDoc, this.props.fieldKey, this._markerStart, this._markerEnd, undefined, true);
this._markerEnd = undefined;
CollectionStackedTimeline.SelectingRegion = undefined;
}
@@ -257,7 +258,7 @@ export class CollectionStackedTimeline extends CollectionSubView<CollectionStack
this._markerEnd = tmp;
}
if (!isClick && Math.abs(movement[0]) > 15 && !this.IsTrimming) {
- const anchor = CollectionStackedTimeline.createAnchor(this.rootDoc, this.dataDoc, this.props.fieldKey, this.props.startTag, this.props.endTag, this._markerStart, this._markerEnd, undefined, true);
+ const anchor = CollectionStackedTimeline.createAnchor(this.rootDoc, this.dataDoc, this.props.fieldKey, this._markerStart, this._markerEnd, undefined, true);
setTimeout(() => DocumentManager.Instance.getDocumentView(anchor)?.select(false));
}
(!isClick || !wasSelecting) && (this._markerEnd = undefined);
@@ -273,7 +274,7 @@ export class CollectionStackedTimeline extends CollectionSubView<CollectionStack
undefined,
() => {
if (shiftKey) {
- CollectionStackedTimeline.createAnchor(this.rootDoc, this.dataDoc, this.props.fieldKey, this.props.startTag, this.props.endTag, this.currentTime, undefined, undefined, true);
+ CollectionStackedTimeline.createAnchor(this.rootDoc, this.dataDoc, this.props.fieldKey, this.currentTime, undefined, undefined, true);
} else {
!wasPlaying && this.props.setTime(this.toTimeline(clientX - rect.x, rect.width));
}
@@ -388,8 +389,10 @@ export class CollectionStackedTimeline extends CollectionSubView<CollectionStack
// creates marker on timeline
@undoBatch
@action
- static createAnchor(rootDoc: Doc, dataDoc: Doc, fieldKey: string, startTag: string, endTag: string, anchorStartTime: Opt<number>, anchorEndTime: Opt<number>, docAnchor: Opt<Doc>, addAsAnnotation: boolean) {
+ static createAnchor(rootDoc: Doc, dataDoc: Doc, fieldKey: string, anchorStartTime: Opt<number>, anchorEndTime: Opt<number>, docAnchor: Opt<Doc>, addAsAnnotation: boolean) {
if (anchorStartTime === undefined) return rootDoc;
+ const startTag = '_timecodeToShow';
+ const endTag = '_timecodeToHide';
const anchor =
docAnchor ??
Docs.Create.LabelDocument({
@@ -738,14 +741,14 @@ class StackedTimelineAnchor extends React.Component<StackedTimelineAnchorProps>
() => this.props.currentTimecode(),
time => {
const dictationDoc = Cast(this.props.layoutDoc['data-dictation'], Doc, null);
- const isDictation = dictationDoc && DocListCast(this.props.mark.links).some(link => Cast(link.anchor1, Doc, null)?.annotationOn === dictationDoc);
+ const isDictation = dictationDoc && LinkManager.Links(this.props.mark).some(link => Cast(link.anchor1, Doc, null)?.annotationOn === dictationDoc);
if (
!LightboxView.LightboxDoc &&
// bcz: when should links be followed? we don't want to move away from the video to follow a link but we can open it in a sidebar/etc. But we don't know that upfront.
// 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 &&
- DocListCast(this.props.mark.links).length &&
+ LinkManager.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
@@ -763,7 +766,7 @@ class StackedTimelineAnchor extends React.Component<StackedTimelineAnchorProps>
// starting the drag event for anchor resizing
onAnchorDown = (e: React.PointerEvent, anchor: Doc, left: boolean): void => {
- this.props._timeline?.setPointerCapture(e.pointerId);
+ //this.props._timeline?.setPointerCapture(e.pointerId);
const newTime = (e: PointerEvent) => {
const rect = (e.target as any).getBoundingClientRect();
return this.props.toTimeline(e.clientX - rect.x, rect.width);
@@ -791,7 +794,7 @@ class StackedTimelineAnchor extends React.Component<StackedTimelineAnchorProps>
},
e => {
this.props.setTime(newTime(e));
- this.props._timeline?.releasePointerCapture(e.pointerId);
+ // this.props._timeline?.releasePointerCapture(e.pointerId);
undo?.end();
},
emptyFunction
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 6314b4529..4805a748b 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -22,7 +22,7 @@ import { ContextMenuProps } from '../ContextMenuItem';
import { EditableView } from '../EditableView';
import { LightboxView } from '../LightboxView';
import { CollectionFreeFormDocumentView } from '../nodes/CollectionFreeFormDocumentView';
-import { DocFocusOptions, DocumentView, DocumentViewProps, OpenWhere, ViewAdjustment } from '../nodes/DocumentView';
+import { DocFocusOptions, DocumentView, DocumentViewProps } from '../nodes/DocumentView';
import { FieldViewProps } from '../nodes/FieldView';
import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox';
import { StyleProp } from '../StyleProvider';
@@ -250,20 +250,17 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
focusDocument = (doc: Doc, options: DocFocusOptions) => {
Doc.BrushDoc(doc);
- let focusSpeed = 0;
const found = this._mainCont && Array.from(this._mainCont.getElementsByClassName('documentView-node')).find((node: any) => node.id === doc[Id]);
if (found) {
const top = found.getBoundingClientRect().top;
const localTop = this.props.ScreenToLocalTransform().transformPoint(0, top);
if (Math.floor(localTop[1]) !== 0) {
- smoothScroll((focusSpeed = options.zoomTime ?? 500), this._mainCont!, localTop[1] + this._mainCont!.scrollTop, options.easeFunc);
+ let focusSpeed = options.zoomTime ?? 500;
+ smoothScroll(focusSpeed, this._mainCont!, localTop[1] + this._mainCont!.scrollTop, options.easeFunc);
+ return focusSpeed;
}
}
- const endFocus = async (moved: boolean) => options?.afterFocus?.(moved) ?? ViewAdjustment.doNothing;
- this.props.focus(this.rootDoc, {
- ...options,
- afterFocus: (didFocus: boolean) => new Promise<ViewAdjustment>(res => setTimeout(async () => res(await endFocus(didFocus)), focusSpeed)),
- });
+ return undefined;
};
styleProvider = (doc: Doc | undefined, props: Opt<DocumentViewProps>, property: string) => {
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 27ae3041f..e46220f02 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -1,5 +1,4 @@
import { action, computed, observable } from 'mobx';
-import ReactLoading from 'react-loading';
import * as rp from 'request-promise';
import CursorField from '../../../fields/CursorField';
import { AclPrivate, Doc, DocListCast, Field, Opt, StrListCast } from '../../../fields/Doc';
@@ -67,6 +66,7 @@ export function CollectionSubView<X>(moreProps?: X) {
// to its children which may be templates.
// If 'annotationField' is specified, then all children exist on that field of the extension document, otherwise, they exist directly on the data document under 'fieldKey'
@computed get dataField() {
+ if (this.layoutDoc[this.props.fieldKey]) return this.layoutDoc[this.props.fieldKey];
// sets the dataDoc's data field to an empty list if the data field is undefined - prevents issues with addonly
// setTimeout changes it outside of the @computed section
!this.dataDoc[this.props.fieldKey] && setTimeout(() => !this.dataDoc[this.props.fieldKey] && (this.dataDoc[this.props.fieldKey] = new List<Doc>()));
diff --git a/src/client/views/collections/CollectionTimeView.tsx b/src/client/views/collections/CollectionTimeView.tsx
index 0ec21cc51..89b2fbfe3 100644
--- a/src/client/views/collections/CollectionTimeView.tsx
+++ b/src/client/views/collections/CollectionTimeView.tsx
@@ -7,7 +7,7 @@ import { ObjectField } from '../../../fields/ObjectField';
import { RichTextField } from '../../../fields/RichTextField';
import { listSpec } from '../../../fields/Schema';
import { ComputedField, ScriptField } from '../../../fields/ScriptField';
-import { Cast, NumCast, StrCast } from '../../../fields/Types';
+import { BoolCast, Cast, NumCast, StrCast } from '../../../fields/Types';
import { emptyFunction, returnEmptyString, returnFalse, returnTrue, setupMoveUpEvents } from '../../../Utils';
import { Docs } from '../../documents/Documents';
import { DocumentType } from '../../documents/DocumentTypes';
@@ -16,12 +16,13 @@ import { ScriptingGlobals } from '../../util/ScriptingGlobals';
import { ContextMenu } from '../ContextMenu';
import { ContextMenuProps } from '../ContextMenuItem';
import { EditableView } from '../EditableView';
-import { ViewSpecPrefix } from '../nodes/DocumentView';
import { computePivotLayout, computeTimelineLayout, ViewDefBounds } from './collectionFreeForm/CollectionFreeFormLayoutEngines';
import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormView';
import { CollectionSubView } from './CollectionSubView';
import './CollectionTimeView.scss';
import React = require('react');
+import { DocFocusOptions, DocumentView } from '../nodes/DocumentView';
+import { PresBox } from '../nodes/trails';
@observer
export class CollectionTimeView extends CollectionSubView() {
@@ -32,18 +33,26 @@ export class CollectionTimeView extends CollectionSubView() {
@observable _viewDefDivClick: Opt<ScriptField>;
@observable _focusPivotField: Opt<string>;
+ async componentDidMount() {
+ this.props.setContentView?.(this);
+ //const detailView = (await DocCastAsync(this.props.Document.childClickedOpenTemplateView)) || DocUtils.findTemplate("detailView", StrCast(this.rootDoc.type), "");
+ ///const childText = "const alias = getAlias(self); switchView(alias, detailView); alias.dropAction='alias'; useRightSplit(alias, shiftKey); ";
+ runInAction(() => {
+ this._childClickedScript = ScriptField.MakeScript('openInLightbox(self)', { this: Doc.name });
+ this._viewDefDivClick = ScriptField.MakeScript('pivotColumnClick(this,payload)', { payload: 'any' });
+ });
+ }
+
+ get pivotField() {
+ return this._focusPivotField || StrCast(this.layoutDoc._pivotField);
+ }
+
getAnchor = (addAsAnnotation: boolean) => {
const anchor = Docs.Create.HTMLAnchorDocument([], {
title: ComputedField.MakeFunction(`"${this.pivotField}"])`) as any,
annotationOn: this.rootDoc,
});
-
- // save view spec information for anchor
- const proto = Doc.GetProto(anchor);
- proto.pivotField = this.pivotField;
- proto.docFilters = ObjectField.MakeCopy(this.layoutDoc._docFilters as ObjectField) || new List<string>([]);
- proto.docRangeFilters = ObjectField.MakeCopy(this.layoutDoc._docRangeFilters as ObjectField) || new List<string>([]);
- proto[ViewSpecPrefix + '_viewType'] = this.layoutDoc._viewType;
+ PresBox.pinDocView(anchor, { pinData: { viewType: true, pivot: true, filters: true } }, this.rootDoc);
if (addAsAnnotation) {
// when added as an annotation, links to anchors can be found as links to the document even if the anchors are not rendered
@@ -56,34 +65,13 @@ export class CollectionTimeView extends CollectionSubView() {
return anchor;
};
- async componentDidMount() {
- this.props.setContentView?.(this);
- //const detailView = (await DocCastAsync(this.props.Document.childClickedOpenTemplateView)) || DocUtils.findTemplate("detailView", StrCast(this.rootDoc.type), "");
- ///const childText = "const alias = getAlias(self); switchView(alias, detailView); alias.dropAction='alias'; useRightSplit(alias, shiftKey); ";
- runInAction(() => {
- this._childClickedScript = ScriptField.MakeScript('openInLightbox(self)', { this: Doc.name });
- this._viewDefDivClick = ScriptField.MakeScript('pivotColumnClick(this,payload)', { payload: 'any' });
- });
- }
-
- get pivotField() {
- return this._focusPivotField || StrCast(this.layoutDoc._pivotField);
- }
@action
- setViewSpec = (anchor: Doc, preview: boolean) => {
- if (preview) {
- // if in preview, then override document's fields with view spec
- this._focusFilters = StrListCast(Doc.GetProto(anchor).docFilters);
- this._focusRangeFilters = StrListCast(Doc.GetProto(anchor).docRangeFilters);
- this._focusPivotField = StrCast(anchor.pivotField);
- } else if (anchor.pivotField !== undefined) {
- // otherwise set document's fields based on anchor view spec
- this.layoutDoc._prevFilterIndex = 1;
- this.layoutDoc._pivotField = StrCast(anchor.pivotField);
- this.layoutDoc._docFilters = new List<string>(StrListCast(anchor.docFilters));
- this.layoutDoc._docRangeFilters = new List<string>(StrListCast(anchor.docRangeFilters));
- }
- return 0;
+ scrollPreview = (docView: DocumentView, anchor: Doc, focusSpeed: number, options: DocFocusOptions) => {
+ // if in preview, then override document's fields with view spec
+ this._focusFilters = StrListCast(anchor.presDocFilters);
+ this._focusRangeFilters = StrListCast(anchor.presPinDocRangeFilters);
+ this._focusPivotField = StrCast(anchor.presPivotField);
+ return undefined;
};
layoutEngine = () => this._layoutEngine;
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 330e116d1..553967b95 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -38,8 +38,8 @@ export type collectionTreeViewProps = {
onCheckedClick?: () => ScriptField;
onChildClick?: () => ScriptField;
// TODO: [AL] add these fields
- AddToMap?: (treeViewDoc: Doc, index: number[]) => Doc[];
- RemFromMap?: (treeViewDoc: Doc, index: number[]) => Doc[];
+ AddToMap?: (treeViewDoc: Doc, index: number[]) => void;
+ RemFromMap?: (treeViewDoc: Doc, index: number[]) => void;
hierarchyIndex?: number[];
};
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 90406ed3c..aed88aa1a 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -64,8 +64,8 @@ interface CollectionViewProps_ extends FieldViewProps {
childClickScript?: ScriptField;
childDoubleClickScript?: ScriptField;
//TODO: [AL] add these fields
- AddToMap?: (treeViewDoc: Doc, index: number[]) => Doc[];
- RemFromMap?: (treeViewDoc: Doc, index: number[]) => Doc[];
+ AddToMap?: (treeViewDoc: Doc, index: number[]) => void;
+ RemFromMap?: (treeViewDoc: Doc, index: number[]) => void;
hierarchyIndex?: number[]; // hierarchical index of a document up to the rendering root (primarily used for tree views)
}
export interface CollectionViewProps extends React.PropsWithChildren<CollectionViewProps_> {}
@@ -169,7 +169,7 @@ export class CollectionView extends ViewBoxAnnotatableComponent<ViewBoxAnnotatab
onContextMenu = (e: React.MouseEvent): void => {
const cm = ContextMenu.Instance;
- if (cm && !e.isPropagationStopped() && this.rootDoc[Id] !== Doc.MainDocId) {
+ if (cm && !e.isPropagationStopped()) {
// need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7
this.setupViewTypes(
'UI Controls...',
@@ -191,7 +191,7 @@ export class CollectionView extends ViewBoxAnnotatableComponent<ViewBoxAnnotatab
if (this.rootDoc.childClickedOpenTemplateView instanceof Doc) {
optionItems.push({ description: 'View Child Detailed Layout', event: () => this.props.addDocTab(this.rootDoc.childClickedOpenTemplateView as Doc, OpenWhere.addRight), icon: 'project-diagram' });
}
- !Doc.noviceMode && optionItems.push({ description: `${this.rootDoc.isInPlaceContainer ? 'Unset' : 'Set'} inPlace Container`, event: () => (this.rootDoc.isInPlaceContainer = !this.rootDoc.isInPlaceContainer), icon: 'project-diagram' });
+ !Doc.noviceMode && optionItems.push({ description: `${this.rootDoc._isLightbox ? 'Unset' : 'Set'} is Lightbox`, event: () => (this.rootDoc._isLightbox = !this.rootDoc._isLightbox), icon: 'project-diagram' });
if (!Doc.noviceMode && false) {
optionItems.push({
diff --git a/src/client/views/collections/TabDocView.scss b/src/client/views/collections/TabDocView.scss
index 0d045bada..58605c3f4 100644
--- a/src/client/views/collections/TabDocView.scss
+++ b/src/client/views/collections/TabDocView.scss
@@ -1,5 +1,9 @@
-@import "../global/globalCssVariables.scss";
+@import '../global/globalCssVariables.scss';
+.tabDocView-content {
+ height: 100%;
+ width: 100%;
+}
input.lm_title:focus,
input.lm_title {
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index fa648eb44..9459aaf1e 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -247,13 +247,13 @@ export class TabDocView extends React.Component<TabDocViewProps> {
alert('Cannot pin presentation document to itself');
return;
}
- const anchorDoc = DocumentManager.Instance.getDocumentView(doc)?.ComponentView?.getAnchor?.(false);
- const pinDoc = anchorDoc && anchorDoc !== doc ? anchorDoc : Doc.MakeDelegate(doc);
+ const anchorDoc = DocumentManager.Instance.getDocumentView(doc)?.ComponentView?.getAnchor?.(false, pinProps);
+ const pinDoc = Doc.MakeDelegate(anchorDoc && anchorDoc !== doc ? anchorDoc : doc);
pinDoc.presentationTargetDoc = anchorDoc ?? doc;
pinDoc.title = doc.title + ' - Slide';
pinDoc.data = new List<Doc>(); // the children of the alias' layout are the presentation slide children. the alias' 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.presMovement = doc.type === DocumentType.SCRIPTING || pinProps?.pinDocLayout ? PresMovement.None : PresMovement.Zoom;
- pinDoc.presDuration = 2000;
+ pinDoc.presDuration = pinDoc.presDuration ?? 1000;
pinDoc.groupWithUp = false;
pinDoc.context = 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
@@ -263,9 +263,6 @@ export class TabDocView extends React.Component<TabDocViewProps> {
pinDoc.treeViewFieldKey = '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.treeViewExpandedView = '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.treeViewHideHeaderIfTemplate = true; // this will force the document to render itself as the tree view header
- const presArray: Doc[] = PresBox.Instance?.sortArray();
- const size: number = PresBox.Instance?.selectedArray.size;
- const presSelected: Doc | undefined = presArray && size ? presArray[size - 1] : undefined;
const duration = NumCast(doc[`${Doc.LayoutFieldKey(pinDoc)}-duration`], null);
if (!pinProps?.audioRange && duration !== undefined) {
@@ -274,10 +271,6 @@ export class TabDocView extends React.Component<TabDocViewProps> {
pinDoc.presStartTime = NumCast(doc.clipStart);
pinDoc.presEndTime = NumCast(doc.clipEnd, duration);
}
- PresBox.pinDocView(pinDoc, pinProps.pinDocContent ? { ...pinProps, pinData: PresBox.pinDataTypes(doc) } : pinProps, DocCast(pinDoc.proto));
- pinDoc.onClick = ScriptField.MakeFunction('navigateToDoc(self.presentationTargetDoc, self)');
- Doc.AddDocToList(curPres, 'data', pinDoc, presSelected);
- //save position
if (pinProps?.activeFrame !== undefined) {
pinDoc.presActiveFrame = pinProps?.activeFrame;
pinDoc.title = doc.title + ' (move)';
@@ -294,6 +287,7 @@ export class TabDocView extends React.Component<TabDocViewProps> {
pinDoc.presMovement = PresMovement.None;
}
if (curPres.expandBoolean) pinDoc.presExpandInlineButton = true;
+ Doc.AddDocToList(curPres, 'data', pinDoc, PresBox.Instance?.sortArray()?.lastElement());
PresBox.Instance?.clearSelectedArray();
pinDoc && PresBox.Instance?.addToSelectedArray(pinDoc); //Update selected array
});
@@ -305,7 +299,7 @@ export class TabDocView extends React.Component<TabDocViewProps> {
const docs = Cast(Doc.MyOverlayDocs.data, listSpec(Doc), []);
if (docs.includes(curPres)) docs.splice(docs.indexOf(curPres), 1);
CollectionDockingView.AddSplit(curPres, OpenWhereMod.right);
- setTimeout(() => DocumentManager.Instance.jumpToDocument(docList.lastElement(), { willPan: true }, undefined, []), 100); // keeps the pinned doc in view since the sidebar shifts things
+ setTimeout(() => DocumentManager.Instance.showDocument(docList.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
}
@@ -350,7 +344,7 @@ export class TabDocView extends React.Component<TabDocViewProps> {
// replace[:{left,right,top,bottom,<any string>}] - e.g., "replace" will replace the current stack contents,
// "replace:right" - will replace the stack on the right named "right" if it exists, or create a stack on the right with that name,
// "replace:monkeys" - will replace any tab that has the label 'monkeys', or a tab with that label will be created by default on the right
- // inPlace - will add the document to any collection along the path from the document to the docking view that has a field isInPlaceContainer. if none is found, inPlace adds a tab to current stack
+ // 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 = (doc: Doc, location: OpenWhere) => {
SelectionManager.DeselectAll();
const whereFields = doc._viewType === CollectionViewType.Docking ? [OpenWhere.dashboard] : location.split(':');
@@ -358,8 +352,16 @@ export class TabDocView extends React.Component<TabDocViewProps> {
if (doc.dockingConfig) return DashboardView.openDashboard(doc);
// prettier-ignore
switch (whereFields[0]) {
- case OpenWhere.inPlace: // fall through to lightbox
- case OpenWhere.lightbox: return LightboxView.AddDocTab(doc, location);
+ case undefined:
+ case OpenWhere.lightbox: if (this.layoutDoc?._isLightbox) {
+ const lightboxView = !doc.annotationOn && DocCast(doc.context) ? DocumentManager.Instance.getFirstDocumentView(DocCast(doc.context)) : undefined;
+ const data = lightboxView?.dataDoc[Doc.LayoutFieldKey(lightboxView.rootDoc)];
+ if (lightboxView && (!data || data instanceof List)) {
+ lightboxView.layoutDoc[Doc.LayoutFieldKey(lightboxView.rootDoc)] = new List<Doc>([doc]);
+ return true;
+ }
+ }
+ return LightboxView.AddDocTab(doc, location);
case OpenWhere.dashboard: return DashboardView.openDashboard(doc);
case OpenWhere.fullScreen: return CollectionDockingView.OpenFullScreen(doc);
case OpenWhere.close: return CollectionDockingView.CloseSplit(doc, whereMods);
@@ -380,13 +382,17 @@ export class TabDocView extends React.Component<TabDocViewProps> {
getCurrentFrame = () => {
return NumCast(Cast(PresBox.Instance.childDocs[PresBox.Instance.itemIndex].presentationTargetDoc, Doc, null)._currentFrame);
};
+ static Activate = (tabDoc: Doc) => {
+ const tab = Array.from(CollectionDockingView.Instance?.tabMap!).find(tab => tab.DashDoc === tabDoc);
+ 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 = (doc: Doc, options: DocFocusOptions) => {
- options?.afterFocus?.(false);
-
if (!this.tab.header.parent._activeContentItem || this.tab.header.parent._activeContentItem !== this.tab.contentItem) {
this.tab.header.parent.setActiveContentItem(this.tab.contentItem); // glr: Panning does not work when this is set - (this line is for trying to make a tab that is not topmost become topmost)
}
+ return undefined;
};
active = () => this._isActive;
@observable _forceInvalidateScreenToLocal = 0;
@@ -462,11 +468,9 @@ export class TabDocView extends React.Component<TabDocViewProps> {
render() {
return (
<div
- className="collectionDockingView-content"
+ className="tabDocView-content"
style={{
fontFamily: Doc.UserDoc().renderStyle === 'comic' ? 'Comic Sans MS' : undefined,
- height: '100%',
- width: '100%',
}}
ref={ref => {
if ((this._mainCont = ref)) {
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index 0d2968ba1..af2d148e0 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -1,20 +1,21 @@
import { IconProp } from '@fortawesome/fontawesome-svg-core';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { action, computed, IReactionDisposer, observable, ObservableMap, reaction } from 'mobx';
+import { action, computed, IReactionDisposer, observable, reaction } from 'mobx';
import { observer } from 'mobx-react';
-import { DataSym, Doc, DocListCast, DocListCastOrNull, Field, HeightSym, Opt, StrListCast, WidthSym } from '../../../fields/Doc';
+import { DataSym, Doc, DocListCast, Field, HeightSym, Opt, StrListCast, WidthSym } from '../../../fields/Doc';
import { Id } from '../../../fields/FieldSymbols';
import { List } from '../../../fields/List';
import { RichTextField } from '../../../fields/RichTextField';
import { listSpec } from '../../../fields/Schema';
import { ComputedField, ScriptField } from '../../../fields/ScriptField';
-import { BoolCast, Cast, DocCast, NumCast, ScriptCast, StrCast } from '../../../fields/Types';
+import { BoolCast, Cast, DocCast, FieldValue, NumCast, ScriptCast, StrCast } from '../../../fields/Types';
import { TraceMobx } from '../../../fields/util';
import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnEmptyString, returnFalse, returnTrue, returnZero, simulateMouseClick, Utils } from '../../../Utils';
import { Docs, DocUtils } from '../../documents/Documents';
import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes';
import { DocumentManager } from '../../util/DocumentManager';
import { DragManager, dropActionType } from '../../util/DragManager';
+import { LinkManager } from '../../util/LinkManager';
import { ScriptingGlobals } from '../../util/ScriptingGlobals';
import { SelectionManager } from '../../util/SelectionManager';
import { SnappingManager } from '../../util/SnappingManager';
@@ -32,7 +33,6 @@ import { CollectionTreeView, TreeViewType } from './CollectionTreeView';
import { CollectionView } from './CollectionView';
import './TreeView.scss';
import React = require('react');
-import { render } from 'react-dom';
export interface TreeViewProps {
treeView: CollectionTreeView;
@@ -66,8 +66,8 @@ export interface TreeViewProps {
skipFields?: string[];
firstLevel: boolean;
// TODO: [AL] add these
- AddToMap?: (treeViewDoc: Doc, index: number[]) => Doc[];
- RemFromMap?: (treeViewDoc: Doc, index: number[]) => Doc[];
+ AddToMap?: (treeViewDoc: Doc, index: number[]) => void;
+ RemFromMap?: (treeViewDoc: Doc, index: number[]) => void;
hierarchyIndex?: number[];
}
@@ -169,37 +169,22 @@ export class TreeView extends React.Component<TreeViewProps> {
@computed get selected() {
return SelectionManager.IsSelected(this._docRef);
}
- // SelectionManager.Views().lastElement()?.props.Document === this.props.document; }
-
- @observable _presTimer!: NodeJS.Timeout;
- @observable _presKeyEventsActive: boolean = false;
-
- @observable _selectedArray: ObservableMap = new ObservableMap<Doc, any>();
- // the selected item's index
- @computed get itemIndex() {
- return NumCast(this.doc._itemIndex);
- }
- // the item that's active
- @computed get activeItem() {
- return this.childDocs ? Cast(this.childDocs[NumCast(this.doc._itemIndex)], Doc, null) : undefined;
- }
- @computed get targetDoc() {
- return Cast(this.activeItem?.presentationTargetDoc, Doc, null);
- }
childDocList(field: string) {
const layout = Cast(Doc.LayoutField(this.doc), Doc, null);
- return (
- (this.props.dataDoc ? DocListCastOrNull(this.props.dataDoc[field]) : undefined) || // if there's a data doc for an expanded template, use it's data field
- (layout ? DocListCastOrNull(layout[field]) : undefined) || // else if there's a layout doc, display it's fields
- DocListCastOrNull(this.doc[field])
- ); // otherwise use the document's data field
+ return DocListCast(this.props.dataDoc?.[field], DocListCast(layout?.[field], DocListCast(this.doc[field])));
}
+ moving: boolean = false;
@undoBatch move = (doc: Doc | Doc[], target: Doc | undefined, addDoc: (doc: Doc | Doc[]) => boolean) => {
if (this.doc !== target && addDoc !== returnFalse) {
+ const canAdd1 = (this.props.parentTreeView as any).dropping || !(ComputedField.WithoutComputed(() => FieldValue(this.props.parentTreeView?.doc.data)) instanceof ComputedField);
+
// bcz: this should all be running in a Temp undo batch instead of hackily testing for returnFalse
- if (this.props.removeDoc?.(doc) === true) {
- return addDoc(doc);
+ if (canAdd1 && this.props.removeDoc?.(doc) === true) {
+ this.props.parentTreeView instanceof TreeView && (this.props.parentTreeView.moving = true);
+ const res = addDoc(doc);
+ this.props.parentTreeView instanceof TreeView && (this.props.parentTreeView.moving = false);
+ return res;
}
}
return false;
@@ -207,6 +192,7 @@ export class TreeView extends React.Component<TreeViewProps> {
@undoBatch @action remove = (doc: Doc | Doc[], key: string) => {
this.props.treeView.props.select(false);
const ind = this.dataDoc[key].indexOf(doc);
+
const res = (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && Doc.RemoveDocFromList(this.dataDoc, key, doc), true);
res && ind > 0 && DocumentManager.Instance.getDocumentView(this.dataDoc[key][ind - 1], this.props.treeView.props.CollectionView)?.select(false);
return res;
@@ -378,20 +364,32 @@ export class TreeView extends React.Component<TreeViewProps> {
const docDragData = de.complete.docDragData;
if (docDragData && pt[0] < rect.left + rect.width) {
if (docDragData.draggedDocuments[0] === this.doc) return true;
- if (this.dropDocuments(docDragData.droppedDocuments, before, inside, docDragData.dropAction, docDragData.moveDocument, docDragData.treeViewDoc === this.props.treeView.props.Document)) {
+ if (this.dropDocuments(docDragData.droppedDocuments, before, inside, docDragData.dropAction, docDragData.removeDocument, docDragData.moveDocument, docDragData.treeViewDoc === this.props.treeView.props.Document)) {
e.stopPropagation();
}
}
};
- dropDocuments(droppedDocuments: Doc[], before: boolean, inside: number | boolean, dropAction: dropActionType, moveDocument: DragManager.MoveFunction | undefined, forceAdd: boolean) {
+ dropping: boolean = false;
+ dropDocuments(droppedDocuments: Doc[], before: boolean, inside: number | boolean, dropAction: dropActionType, removeDocument: DragManager.RemoveFunction | undefined, moveDocument: DragManager.MoveFunction | undefined, forceAdd: boolean) {
const parentAddDoc = (doc: Doc | Doc[]) => this.props.addDocument(doc, undefined, before);
- const canAdd = (!this.props.treeView.outlineMode && !StrCast((inside ? this.props.document : this.props.containerCollection)?.freezeChildren).includes('add')) || forceAdd;
- const localAdd = (doc: Doc) => (Doc.AddDocToList(this.dataDoc, this.fieldKey, doc) && ((doc.context = this.doc.context) || true) ? true : false);
- const addDoc = !inside ? parentAddDoc : (doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && localAdd(doc), true as boolean);
+ const localAdd = (doc: Doc | Doc[]) => {
+ const innerAdd = (doc: Doc) => {
+ const dataIsComputed = ComputedField.WithoutComputed(() => FieldValue(this.dataDoc[this.fieldKey])) instanceof ComputedField;
+ const added = (!dataIsComputed || (this.dropping && this.moving)) && Doc.AddDocToList(this.dataDoc, this.fieldKey, doc);
+ dataIsComputed && (doc.context = this.doc.context);
+ return added;
+ };
+ return (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && innerAdd(doc), true as boolean);
+ };
+ const addDoc = inside ? localAdd : parentAddDoc;
const move = (!dropAction || dropAction === 'proto' || dropAction === 'move' || dropAction === 'same') && moveDocument;
+ const canAdd = (!this.props.treeView.outlineMode && !StrCast((inside ? this.props.document : this.props.containerCollection)?.freezeChildren).includes('add')) || forceAdd;
if (canAdd) {
- return UndoManager.RunInTempBatch(() => droppedDocuments.reduce((added, d) => (move ? move(d, undefined, addDoc) || (dropAction === 'proto' ? addDoc(d) : false) : addDoc(d)) || added, false));
+ this.props.parentTreeView instanceof TreeView && (this.props.parentTreeView.dropping = true);
+ const res = UndoManager.RunInTempBatch(() => droppedDocuments.reduce((added, d) => (move ? move(d, undefined, addDoc) || (dropAction === 'proto' ? addDoc(d) : false) : addDoc(d)) || added, false));
+ this.props.parentTreeView instanceof TreeView && (this.props.parentTreeView.dropping = false);
+ return res;
}
return false;
}
@@ -437,12 +435,16 @@ export class TreeView extends React.Component<TreeViewProps> {
const expandedWidth = () => this.props.panelWidth() - leftOffset.width;
if (contents instanceof Doc || (Cast(contents, listSpec(Doc)) && Cast(contents, listSpec(Doc))!.length && Cast(contents, listSpec(Doc))![0] instanceof Doc)) {
const remDoc = (doc: Doc | Doc[]) => this.remove(doc, key);
- const localAdd = (doc: Doc, addBefore?: Doc, before?: boolean) => {
- const added = Doc.AddDocToList(this.dataDoc, key, doc, addBefore, before, false, true);
- added && (doc.context = this.doc.context);
- return added;
+ const moveDoc = (doc: Doc | Doc[], target: Doc | undefined, addDoc: (doc: Doc | Doc[]) => boolean) => this.move(doc, target, addDoc);
+ const addDoc = (doc: Doc | Doc[], addBefore?: Doc, before?: boolean) => {
+ const innerAdd = (doc: Doc) => {
+ const dataIsComputed = ComputedField.WithoutComputed(() => FieldValue(this.dataDoc[key])) instanceof ComputedField;
+ const added = (!dataIsComputed || (this.dropping && this.moving)) && Doc.AddDocToList(this.dataDoc, key, doc, addBefore, before, false, true);
+ dataIsComputed && (doc.context = this.doc.context);
+ return added;
+ };
+ return (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && innerAdd(doc), true as boolean);
};
- const addDoc = (doc: Doc | Doc[], addBefore?: Doc, before?: boolean) => (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && localAdd(doc, addBefore, before), true);
contentElement = TreeView.GetChildElements(
contents instanceof Doc ? [contents] : DocListCast(contents),
this.props.treeView,
@@ -453,7 +455,7 @@ export class TreeView extends React.Component<TreeViewProps> {
this.props.prevSibling,
addDoc,
remDoc,
- this.move,
+ moveDoc,
this.props.dropAction,
this.props.addDocTab,
this.titleStyleProvider,
@@ -533,6 +535,7 @@ export class TreeView extends React.Component<TreeViewProps> {
);
const key = (expandKey === 'annotations' ? `${this.fieldKey}-` : '') + expandKey;
const remDoc = (doc: Doc | Doc[]) => this.remove(doc, key);
+ const moveDoc = (doc: Doc | Doc[], target: Doc | undefined, addDoc: (doc: Doc | Doc[]) => boolean) => this.move(doc, target, addDoc);
const localAdd = (doc: Doc, addBefore?: Doc, before?: boolean) => {
// if there's a sort ordering specified that can be modified on drop (eg, zorder can be modified, alphabetical can't),
// then the modification would be done here
@@ -543,8 +546,10 @@ export class TreeView extends React.Component<TreeViewProps> {
docs.push(doc);
docs.sort((a, b) => (NumCast(a.zIndex) > NumCast(b.zIndex) ? 1 : -1)).forEach((d, i) => (d.zIndex = i));
}
- const added = Doc.AddDocToList(this.dataDoc, key, doc, addBefore, before, false, true);
- added && (doc.context = this.doc.context);
+ const dataIsComputed = ComputedField.WithoutComputed(() => FieldValue(this.dataDoc[key])) instanceof ComputedField;
+ const added = (!dataIsComputed || (this.dropping && this.moving)) && Doc.AddDocToList(this.dataDoc, key, doc, addBefore, before, false, true);
+ !dataIsComputed && added && (doc.context = this.doc.context);
+
return added;
};
const addDoc = (doc: Doc | Doc[], addBefore?: Doc, before?: boolean) => (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && localAdd(doc, addBefore, before), true);
@@ -593,7 +598,7 @@ export class TreeView extends React.Component<TreeViewProps> {
this.props.prevSibling,
addDoc,
remDoc,
- this.move,
+ moveDoc,
StrCast(this.doc.childDropAction, this.props.dropAction) as dropActionType,
this.props.addDocTab,
this.titleStyleProvider,
@@ -700,7 +705,7 @@ export class TreeView extends React.Component<TreeViewProps> {
@computed get validExpandViewTypes() {
const annos = () => (DocListCast(this.doc[this.fieldKey + '-annotations']).length && !this.props.treeView.dashboardMode ? 'annotations' : '');
- const links = () => (DocListCast(this.doc.links).length && !this.props.treeView.dashboardMode ? 'links' : '');
+ const links = () => (LinkManager.Links(this.doc).length && !this.props.treeView.dashboardMode ? 'links' : '');
const data = () => (this.childDocs || this.props.treeView.dashboardMode ? this.fieldKey : '');
const aliases = () => (this.props.treeView.dashboardMode ? '' : 'aliases');
const fields = () => (Doc.noviceMode ? '' : 'fields');
@@ -750,7 +755,7 @@ export class TreeView extends React.Component<TreeViewProps> {
const makeFolder = { script: ScriptField.MakeFunction(`scriptContext.makeFolder()`, { scriptContext: 'any' })!, icon: 'folder-plus', label: 'New Folder' };
const deleteItem = { script: ScriptField.MakeFunction(`scriptContext.deleteItem()`, { scriptContext: 'any' })!, icon: 'folder-plus', label: 'Delete' };
const folderOp = this.childDocs?.length ? [makeFolder] : [];
- const openAlias = { script: ScriptField.MakeFunction(`openOnRight(getAlias(self))`)!, icon: 'copy', label: 'Open Alias' };
+ const openAlias = { script: ScriptField.MakeFunction(`openDoc(getAlias(self), ${OpenWhere.addRight})`)!, icon: 'copy', label: 'Open Alias' };
const focusDoc = { script: ScriptField.MakeFunction(`DocFocusOrOpen(self)`)!, icon: 'eye', label: 'Focus or Open' };
return [
...(this.props.contextMenuItems ?? []).filter(mi => (!mi.filter ? true : mi.filter.script.run({ doc: this.doc })?.result)),
@@ -1028,7 +1033,9 @@ export class TreeView extends React.Component<TreeViewProps> {
// renders the text version of a document as the header. This is used in the file system mode and in other vanilla tree views.
@computed get renderTitleAsHeader() {
- return (
+ return this.props.treeView.Document.treeViewHideUnrendered && this.doc.unrendered && !this.doc.treeViewFieldKey ? (
+ <div></div>
+ ) : (
<>
{this.renderBullet}
{this.renderTitle}
@@ -1062,7 +1069,7 @@ export class TreeView extends React.Component<TreeViewProps> {
const before = pt[1] < rect.top + rect.height / 2;
const inside = this.props.treeView.fileSysMode && !this.doc.isFolder ? false : pt[0] > Math.min(rect.left + 75, rect.left + rect.width * 0.75) || (!before && this.treeViewOpen && this.childDocs?.length ? true : false);
- const docs = this.props.treeView.onTreeDrop(de, (docs: Doc[]) => this.dropDocuments(docs, before, inside, 'copy', undefined, false));
+ const docs = this.props.treeView.onTreeDrop(de, (docs: Doc[]) => this.dropDocuments(docs, before, inside, 'copy', undefined, undefined, false));
};
render() {
@@ -1146,8 +1153,8 @@ export class TreeView extends React.Component<TreeViewProps> {
unobserveHeight: (ref: any) => void,
contextMenuItems: { script: ScriptField; filter: ScriptField; label: string; icon: string }[],
// TODO: [AL] add these
- AddToMap?: (treeViewDoc: Doc, index: number[]) => Doc[],
- RemFromMap?: (treeViewDoc: Doc, index: number[]) => Doc[],
+ AddToMap?: (treeViewDoc: Doc, index: number[]) => void,
+ RemFromMap?: (treeViewDoc: Doc, index: number[]) => void,
hierarchyIndex?: number[],
renderCount?: number
) {
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx
index 7dd9cdb8b..fa0695fb2 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx
@@ -14,6 +14,7 @@ export interface ViewDefBounds {
x: number;
y: number;
z?: number;
+ rotation?: number;
text?: string;
zIndex?: number;
width?: number;
@@ -31,6 +32,7 @@ export interface PoolData {
x: number;
y: number;
z?: number;
+ rotation?: number;
zIndex?: number;
width?: number;
height?: number;
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
index 9811c239b..7f1e15c2f 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
@@ -136,6 +136,7 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo
height = rect.height;
var el = el.parentNode;
while (el && el !== document.body) {
+ if (el.className === 'tabDocView-content') break;
rect = el.getBoundingClientRect?.();
if (rect?.width) {
if (top <= rect.bottom === false && getComputedStyle(el).overflow === 'hidden') return rect.bottom;
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 132538ea4..15d8144fc 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -4,11 +4,10 @@ import { action, computed, IReactionDisposer, observable, reaction, runInAction
import { observer } from 'mobx-react';
import { computedFn } from 'mobx-utils';
import { DateField } from '../../../../fields/DateField';
-import { DataSym, Doc, DocListCast, HeightSym, Opt, StrListCast, WidthSym } from '../../../../fields/Doc';
+import { DataSym, Doc, DocListCast, HeightSym, Opt, WidthSym } from '../../../../fields/Doc';
import { Id } from '../../../../fields/FieldSymbols';
import { InkData, InkField, InkTool, PointData, Segment } from '../../../../fields/InkField';
import { List } from '../../../../fields/List';
-import { ObjectField } from '../../../../fields/ObjectField';
import { RichTextField } from '../../../../fields/RichTextField';
import { listSpec } from '../../../../fields/Schema';
import { ScriptField } from '../../../../fields/ScriptField';
@@ -16,13 +15,12 @@ import { BoolCast, Cast, DocCast, FieldValue, NumCast, ScriptCast, StrCast } fro
import { ImageField } from '../../../../fields/URLField';
import { TraceMobx } from '../../../../fields/util';
import { GestureUtils } from '../../../../pen-gestures/GestureUtils';
-import { aggregateBounds, emptyFunction, intersectRect, returnFalse, returnTransparent, setupMoveUpEvents, Utils } from '../../../../Utils';
+import { aggregateBounds, emptyFunction, intersectRect, returnFalse, setupMoveUpEvents, Utils } from '../../../../Utils';
import { CognitiveServices } from '../../../cognitive_services/CognitiveServices';
import { Docs, DocUtils } from '../../../documents/Documents';
import { CollectionViewType, DocumentType } from '../../../documents/DocumentTypes';
import { DocumentManager } from '../../../util/DocumentManager';
import { DragManager, dropActionType } from '../../../util/DragManager';
-import { HistoryUtil } from '../../../util/History';
import { InteractionUtils } from '../../../util/InteractionUtils';
import { ReplayMovements } from '../../../util/ReplayMovements';
import { ScriptingGlobals } from '../../../util/ScriptingGlobals';
@@ -34,15 +32,15 @@ import { undoBatch, UndoManager } from '../../../util/UndoManager';
import { COLLECTION_BORDER_WIDTH } from '../../../views/global/globalCssVariables.scss';
import { Timeline } from '../../animationtimeline/Timeline';
import { ContextMenu } from '../../ContextMenu';
+import { DocumentDecorations } from '../../DocumentDecorations';
import { GestureOverlay } from '../../GestureOverlay';
import { ActiveArrowEnd, ActiveArrowStart, ActiveDash, ActiveFillColor, ActiveInkBezierApprox, ActiveInkColor, ActiveInkWidth, ActiveIsInkMask, InkingStroke, SetActiveInkColor, SetActiveInkWidth } from '../../InkingStroke';
import { LightboxView } from '../../LightboxView';
import { CollectionFreeFormDocumentView } from '../../nodes/CollectionFreeFormDocumentView';
-import { DocFocusOptions, DocumentView, DocumentViewProps, OpenWhere, ViewAdjustment, ViewSpecPrefix } from '../../nodes/DocumentView';
+import { DocFocusOptions, DocumentView, DocumentViewProps, OpenWhere } from '../../nodes/DocumentView';
import { FieldViewProps } from '../../nodes/FieldView';
import { FormattedTextBox } from '../../nodes/formattedText/FormattedTextBox';
-import { PresBox } from '../../nodes/trails/PresBox';
-import { VideoBox } from '../../nodes/VideoBox';
+import { PinProps, PresBox } from '../../nodes/trails/PresBox';
import { CreateImage } from '../../nodes/WebBoxRenderer';
import { StyleProp } from '../../StyleProvider';
import { CollectionSubView } from '../CollectionSubView';
@@ -53,8 +51,6 @@ import { CollectionFreeFormRemoteCursors } from './CollectionFreeFormRemoteCurso
import './CollectionFreeFormView.scss';
import { MarqueeView } from './MarqueeView';
import React = require('react');
-import { DocumentDecorations } from '../../DocumentDecorations';
-import { PresEffect } from '../../nodes/trails';
export type collectionFreeformViewProps = {
annotationLayerHostsContent?: boolean; // whether to force scaling of content (needed by ImageBox)
@@ -78,7 +74,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
@observable
public static ShowPresPaths = false;
- private _lastNudge: any;
+ private _panZoomTransitionTimer: any;
private _lastX: number = 0;
private _lastY: number = 0;
private _downX: number = 0;
@@ -98,9 +94,6 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
private _brushtimer: any;
private _brushtimer1: any;
- // private isWritingMode: boolean = true;
- // private writingModeDocs: Doc[] = [];
-
private get isAnnotationOverlay() {
return this.props.isAnnotationOverlay;
}
@@ -115,7 +108,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
@observable _panZoomTransition: number = 0; // sets the pan/zoom transform ease time- used by nudge(), focus() etc to smoothly zoom/pan. set to 0 to use document's transition time or default of 0
@observable _hLines: number[] | undefined;
@observable _vLines: number[] | undefined;
- @observable _firstRender = true; // this turns off rendering of the collection's content so that there's instant feedback when a tab is switched of what content will be shown.
+ @observable _firstRender = false; // this turns off rendering of the collection's content so that there's instant feedback when a tab is switched of what content will be shown. could be used for performance improvement
@observable _showAnimTimeline = false;
@observable _clusterSets: Doc[][] = [];
@observable _deleteList: DocumentView[] = [];
@@ -143,7 +136,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
};
}
@computed get fitContentsToBox() {
- return (this.props.fitContentsToBox?.() || this.Document._fitContentsToBox || this.Document.isGroup) && !this.isAnnotationOverlay;
+ return (this.props.fitContentsToBox?.() || this.Document._fitContentsToBox) && !this.isAnnotationOverlay;
}
@computed get contentBounds() {
const cb = Cast(this.rootDoc.contentBounds, listSpec('number'));
@@ -185,8 +178,6 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
return this.getContainerTransform().translate(-this.cachedCenteringShiftX, -this.cachedCenteringShiftY).transform(this.cachedGetLocalTransform);
}
- _keyTimer: NodeJS.Timeout | undefined;
-
public static gotoKeyframe(timer: NodeJS.Timeout | undefined, docs: Doc[], duration: number) {
if (timer) clearTimeout(timer);
return DocumentView.SetViewTransition(docs, 'all', duration, undefined, true);
@@ -212,6 +203,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
return newTimer;
}
+ _keyTimer: NodeJS.Timeout | undefined; // timer for turning off transition flag when key frame change has completed. Need to clear this if you do a second navigation before first finishes, or else first timer can go off during second naviation.
changeKeyFrame = (back = false) => {
const currentFrame = Cast(this.Document._currentFrame, 'number', null);
if (currentFrame === undefined) {
@@ -301,6 +293,30 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
return dispTime === -1 || curTime === -1 || (curTime - dispTime >= -1e-4 && curTime <= endTime);
}
+ focus = (anchor: Doc, options: DocFocusOptions) => {
+ const xfToCollection = options?.docTransform ?? Transform.Identity();
+ const savedState = { panX: NumCast(this.Document._panX), panY: NumCast(this.Document._panY), scale: options?.willZoomCentered ? this.Document[this.scaleFieldKey] : undefined };
+ const cantTransform = this.fitContentsToBox || ((this.rootDoc._isGroup || this.layoutDoc._lockedTransform) && !LightboxView.LightboxDoc);
+ const { panX, panY, scale } = cantTransform || (!options.willPan && !options.willZoomCentered) ? savedState : this.calculatePanIntoView(anchor, xfToCollection, options?.willZoomCentered ? options?.zoomScale || 0.75 : undefined);
+
+ // focus on the document in the collection
+ const didMove = !cantTransform && !anchor.z && (panX !== savedState.panX || panY !== savedState.panY || scale !== savedState.scale);
+ // glr: freeform transform speed can be set by adjusting presTransition field - needs a way of knowing when presentation is not active...
+ if (didMove) {
+ const focusTime = options?.instant ? 0 : options.zoomTime ?? 500;
+ options.zoomScale && scale && (this.Document[this.scaleFieldKey] = scale);
+ this.setPan(panX, panY, focusTime, true); // docs that are floating in their collection can't be panned to from their collection -- need to propagate the pan to a parent freeform somehow
+ return focusTime;
+ }
+ };
+
+ getView = async (doc: Doc): Promise<Opt<DocumentView>> => {
+ return new Promise<Opt<DocumentView>>(res => {
+ const findDoc = (finish: (dv: DocumentView) => void) => DocumentManager.Instance.AddViewRenderedCb(doc, dv => finish(dv));
+ findDoc(dv => res(dv));
+ });
+ };
+
@action
internalDocDrop(e: Event, de: DragManager.DropEvent, docDragData: DragManager.DocumentDragData, xp: number, yp: number) {
if (!de.embedKey && !this.ChildDrag && this.rootDoc._isGroup) return false;
@@ -500,7 +516,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
this._clusterSets.push([doc]);
} else if (this._clusterSets.length) {
for (let i = this._clusterSets.length; i <= doc.cluster; i++) !this._clusterSets[i] && this._clusterSets.push([]);
- this._clusterSets[doc.cluster].push(doc);
+ this._clusterSets[doc.cluster ?? 0].push(doc);
}
}
}
@@ -523,6 +539,10 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
}
}
break;
+ case StyleProp.FillColor:
+ if (doc && this.Document._currentFrame !== undefined) {
+ return CollectionFreeFormDocumentView.getStringValues(doc, NumCast(this.Document._currentFrame))?.fillColor;
+ }
}
return styleProp;
};
@@ -559,14 +579,11 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
!InteractionUtils.IsType(e, InteractionUtils.TOUCHTYPE) &&
!InteractionUtils.IsType(e, InteractionUtils.PENTYPE)
) {
+ // prettier-ignore
switch (Doc.ActiveTool) {
- case InkTool.Highlighter:
- break;
- // TODO: nda - this where we want to create the new "writingDoc" collection that we add strokes to
- case InkTool.Write:
- break;
- case InkTool.Pen:
- break; // the GestureOverlay handles ink stroke input -- either as gestures, or drying as ink strokes that are added to document views
+ case InkTool.Highlighter: break;
+ case InkTool.Write: break;
+ case InkTool.Pen: break; // the GestureOverlay handles ink stroke input -- either as gestures, or drying as ink strokes that are added to document views
case InkTool.Eraser:
this._batch = UndoManager.StartBatch('collectionErase');
setupMoveUpEvents(this, e, this.onEraserMove, this.onEraserUp, emptyFunction);
@@ -1118,7 +1135,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
}
}
if (!this.layoutDoc._lockedTransform || LightboxView.LightboxDoc || DocListCast(Doc.MyOverlayDocs?.data).includes(this.Document)) {
- this._panZoomTransition = panTime;
+ this.setPanZoomTransition(panTime);
const scale = this.getLocalTransform().inverse().Scale;
const minScale = NumCast(this.rootDoc._viewScaleMin, 1);
const minPanX = NumCast(this.rootDoc._panXMin, 0);
@@ -1152,12 +1169,11 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
@action
nudge = (x: number, y: number, nudgeTime: number = 500) => {
if (this.props.ContainingCollectionDoc?._viewType !== CollectionViewType.Freeform || this.props.ContainingCollectionDoc._panX !== undefined) {
- // bcz: this isn't ideal, but want to try it out...
- this.setPan(NumCast(this.layoutDoc._panX) + ((this.props.PanelWidth() / 2) * x) / this.zoomScaling(), NumCast(this.layoutDoc._panY) + ((this.props.PanelHeight() / 2) * -y) / this.zoomScaling(), nudgeTime, true);
- this._lastNudge && clearTimeout(this._lastNudge);
- this._lastNudge = setTimeout(
- action(() => (this._panZoomTransition = 0)),
- nudgeTime
+ this.setPan(
+ NumCast(this.layoutDoc._panX) + ((this.props.PanelWidth() / 2) * x) / this.zoomScaling(), // nudge x,y as a function of panel dimension and scale
+ NumCast(this.layoutDoc._panY) + ((this.props.PanelHeight() / 2) * -y) / this.zoomScaling(),
+ nudgeTime,
+ true
);
return true;
}
@@ -1183,9 +1199,19 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
};
@action
+ setPanZoomTransition = (transitionTime: number) => {
+ this._panZoomTransition = transitionTime;
+ this._panZoomTransitionTimer && clearTimeout(this._panZoomTransitionTimer);
+ this._panZoomTransitionTimer = setTimeout(
+ action(() => (this._panZoomTransition = 0)),
+ transitionTime
+ );
+ };
+
+ @action
zoomSmoothlyAboutPt(docpt: number[], scale: number, transitionTime = 500) {
if (this.Document._isGroup) return;
- this._panZoomTransition = transitionTime;
+ this.setPanZoomTransition(transitionTime);
const screenXY = this.getTransform().inverse().transformPoint(docpt[0], docpt[1]);
this.layoutDoc[this.scaleFieldKey] = scale;
const newScreenXY = this.getTransform().inverse().transformPoint(docpt[0], docpt[1]);
@@ -1193,82 +1219,8 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
const newpan = this.getTransform().transformDirection(scrDelta.x, scrDelta.y);
this.layoutDoc._panX = NumCast(this.layoutDoc._panX) - newpan[0];
this.layoutDoc._panY = NumCast(this.layoutDoc._panY) - newpan[1];
- return new Promise<number>(res => setTimeout(() => res(runInAction(() => (this._panZoomTransition = 0))), this._panZoomTransition)); // set transition to be smooth, then reset
}
- _focusCount = 0;
- focusDocument = (doc: Doc, options: DocFocusOptions) => {
- const state = HistoryUtil.getState();
-
- // TODO This technically isn't correct if type !== "doc", as
- // currently nothing is done, but we should probably push a new state
- if (state.type === 'doc' && this.Document._panX !== undefined && this.Document._panY !== undefined) {
- const init = state.initializers![this.Document[Id]];
- if (!init) {
- state.initializers![this.Document[Id]] = { panX: NumCast(this.Document._panX), panY: NumCast(this.Document._panY) };
- HistoryUtil.pushState(state);
- } else if (init.panX !== this.Document._panX || init.panY !== this.Document._panY) {
- init.panX = NumCast(this.Document._panX);
- init.panY = NumCast(this.Document._panY);
- HistoryUtil.pushState(state);
- }
- }
- // if (SelectionManager.Views().length !== 1 || SelectionManager.Views()[0].Document !== doc) {
- // SelectionManager.DeselectAll();
- // }
- if (this.props.getScrollHeight || this.props.Document.scrollTop !== undefined || this.props.Document.currentTimecode !== undefined || doc.type === DocumentType.MARKER) {
- this.props.focus(doc, options);
- } else {
- const xfToCollection = options?.docTransform ?? Transform.Identity();
- const savedState = { panX: NumCast(this.Document._panX), panY: NumCast(this.Document._panY), scale: options?.willPanZoom ? this.Document[this.scaleFieldKey] : undefined };
- const newState = HistoryUtil.getState();
- const cantTransform = (this.rootDoc._isGroup || this.layoutDoc._lockedTransform) && !LightboxView.LightboxDoc;
- const { panX, panY, scale } = cantTransform || (!options.willPan && !options.willPanZoom) ? savedState : this.calculatePanIntoView(doc, xfToCollection, options?.willPanZoom ? options?.zoomScale || 0.75 : undefined);
- if (!cantTransform) {
- // only pan and zoom to focus on a document if the document is not an annotation in an annotation overlay collection
- newState.initializers![this.Document[Id]] = { panX, panY };
- HistoryUtil.pushState(newState);
- }
- // focus on the document in the collection
- const didMove = !cantTransform && !doc.z && (panX !== savedState.panX || panY !== savedState.panY || scale !== savedState.scale);
- const focusSpeed = options?.instant ? 0 : didMove || DocCast(options.effect)?.presEffect !== PresEffect.None ? options.zoomTime ?? 500 : 0;
- // glr: freeform transform speed can be set by adjusting presTransition field - needs a way of knowing when presentation is not active...
- if (didMove) {
- options.zoomScale && scale && (this.Document[this.scaleFieldKey] = scale);
- this.setPan(panX, panY, focusSpeed, true); // docs that are floating in their collection can't be panned to from their collection -- need to propagate the pan to a parent freeform somehow
- }
-
- const focusCount = ++this._focusCount;
- const startTime = Date.now();
- // focus on this collection within its parent view. the parent view after focusing determines whether to reset the view change within the collection
- const endFocus = async (moved: boolean) => {
- doc.hidden && Doc.UnHighlightDoc(doc);
- const resetView = options?.afterFocus ? await options?.afterFocus(moved) : ViewAdjustment.doNothing;
- if (resetView) {
- const restoreState = savedState;
- if (typeof restoreState !== 'boolean') {
- this.Document._panX = restoreState.panX;
- this.Document._panY = restoreState.panY;
- this.Document[this.scaleFieldKey] = restoreState.scale;
- }
- }
- this._focusCount === focusCount && didMove && runInAction(() => (this._panZoomTransition = 0));
- return resetView;
- };
- const xf = !cantTransform
- ? Transform.Identity()
- : this.props.isAnnotationOverlay
- ? new Transform(NumCast(this.rootDoc.x), NumCast(this.rootDoc.y), this.rootDoc[WidthSym]() / Doc.NativeWidth(this.rootDoc))
- : new Transform(NumCast(this.rootDoc.x) + this.rootDoc[WidthSym]() / 2 - NumCast(this.rootDoc._panX), NumCast(this.rootDoc.y) + this.rootDoc[HeightSym]() / 2 - NumCast(this.rootDoc._panY), 1);
-
- this.props.focus(!cantTransform ? this.rootDoc : doc, {
- ...options,
- docTransform: xf,
- afterFocus: (didFocus: boolean) => new Promise<ViewAdjustment>(res => setTimeout(async () => res(await endFocus(didMove || didFocus)), Math.max(0, focusSpeed - (Date.now() - startTime)))),
- });
- }
- };
-
calculatePanIntoView = (doc: Doc, xf: Transform, scale?: number) => {
const layoutdoc = Doc.Layout(doc);
const pt = xf.transformPoint(NumCast(doc.x), NumCast(doc.y));
@@ -1368,7 +1320,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
searchFilterDocs={this.searchFilterDocs}
isDocumentActive={this.props.childDocumentsActive?.() ? this.props.isDocumentActive : this.isContentActive}
isContentActive={emptyFunction}
- focus={this.focusDocument}
+ focus={this.isAnnotationOverlay ? this.props.focus : this.focus}
addDocTab={this.addDocTab}
addDocument={this.props.addDocument}
removeDocument={this.props.removeDocument}
@@ -1386,12 +1338,13 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
dontScaleFilter={this.props.dontScaleFilter}
dontRegisterView={this.props.dontRenderDocuments || this.props.dontRegisterView}
pointerEvents={this.pointerEvents}
- rotation={this.props.styleProvider?.(childLayout, this.props, StyleProp.JitterRotation) || 0}
+ //rotation={this.props.styleProvider?.(childLayout, this.props, StyleProp.JitterRotation) || 0}
//fitContentsToBox={this.props.fitContentsToBox || BoolCast(this.props.freezeChildDimensions)} // bcz: check this
/>
);
}
addDocTab = action((doc: Doc, where: OpenWhere) => {
+ if (this.props.isAnnotationOverlay) return this.props.addDocTab(doc, where);
switch (where) {
case OpenWhere.inParent:
return this.props.addDocument?.(doc) || false;
@@ -1409,9 +1362,11 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
(!docContext || this.props.removeDocument?.(docContext))) ||
false
);
- case OpenWhere.inPlace:
- if (this.layoutDoc.isInPlaceContainer) {
- this.dataDoc[this.props.fieldKey] = new List<Doc>(doc instanceof Doc ? [doc] : doc);
+ case undefined:
+ case OpenWhere.lightbox:
+ if (this.layoutDoc._isLightbox) {
+ // _isLightbox docs have a script that will unset this overlay onClick
+ this.layoutDoc[this.props.fieldKey] = new List<Doc>(doc instanceof Doc ? [doc] : doc);
return true;
}
}
@@ -1425,17 +1380,21 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
const contentFrameNumber = Cast(childDocLayout._currentFrame, 'number', layoutFrameNumber ?? null); // frame number that content is at which determines what content is displayed
const { z, zIndex } = childDoc;
const { backgroundColor, color } = contentFrameNumber === undefined ? { backgroundColor: undefined, color: undefined } : CollectionFreeFormDocumentView.getStringValues(childDoc, contentFrameNumber);
- const { x, y, opacity } = layoutFrameNumber === undefined ? { x: childDoc.x, y: childDoc.y, opacity: this.props.childOpacity?.() } : CollectionFreeFormDocumentView.getValues(childDoc, layoutFrameNumber);
+ const { x, y, _width, _height, opacity, _rotation } =
+ layoutFrameNumber === undefined
+ ? { _width: Cast(childDocLayout._width, 'number'), _height: Cast(childDocLayout._height, 'number'), _rotation: Cast(childDocLayout._rotation, 'number'), x: childDoc.x, y: childDoc.y, opacity: this.props.childOpacity?.() }
+ : CollectionFreeFormDocumentView.getValues(childDoc, layoutFrameNumber);
return {
x: Number.isNaN(NumCast(x)) ? 0 : NumCast(x),
y: Number.isNaN(NumCast(y)) ? 0 : NumCast(y),
z: Cast(z, 'number'),
+ rotation: Cast(_rotation, 'number'),
color: Cast(color, 'string') ? StrCast(color) : this.props.styleProvider?.(childDoc, this.props, StyleProp.Color),
backgroundColor: Cast(backgroundColor, 'string') ? StrCast(backgroundColor) : this.getClusterColor(childDoc, this.props, StyleProp.BackgroundColor),
opacity: this._keyframeEditing ? 1 : Cast(opacity, 'number') ?? this.props.styleProvider?.(childDoc, this.props, StyleProp.Opacity),
zIndex: Cast(zIndex, 'number'),
- width: Cast(childDocLayout._width, 'number'),
- height: Cast(childDocLayout._height, 'number'),
+ width: _width,
+ height: _height,
transition: StrCast(childDocLayout.dataTransition),
pair: params.pair,
replica: '',
@@ -1556,6 +1515,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
newPos.x !== lastPos.x ||
newPos.y !== lastPos.y ||
newPos.z !== lastPos.z ||
+ newPos.rotation !== lastPos.rotation ||
newPos.zIndex !== lastPos.zIndex ||
newPos.transition !== lastPos.transition
) {
@@ -1591,47 +1551,11 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
return elements;
}
- @action
- setViewSpec = (anchor: Doc, preview: boolean) => {
- if (preview) {
- this._focusFilters = StrListCast(Doc.GetProto(anchor).docFilters);
- this._focusRangeFilters = StrListCast(Doc.GetProto(anchor).docRangeFilters);
- } else {
- if (anchor.docFilters) {
- this.layoutDoc._docFilters = new List<string>(StrListCast(anchor.docFilters));
- }
- if (anchor.docRangeFilters) {
- this.layoutDoc._docRangeFilters = new List<string>(StrListCast(anchor.docRangeFilters));
- }
- }
- return 0;
- };
+ getAnchor = (addAsAnnotation: boolean, pinProps?: PinProps) => {
+ // create an anchor that saves information about the current state of the freeform view (pan, zoom, view type)
+ const anchor = Docs.Create.CollectionAnchorDocument({ title: 'ViewSpec - ' + StrCast(this.layoutDoc._viewType), unrendered: true, presTransition: 500, annotationOn: this.rootDoc });
+ PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), pannable: !this.Document._isGroup, viewType: true, filters: true } }, this.rootDoc);
- @action
- scrollFocus = (anchor: Doc, options: DocFocusOptions) => {
- const focusSpeed = options.instant ? 0 : options.zoomTime ?? 500;
- return PresBox.restoreTargetDocView(
- this.props.DocumentView?.(), //
- { pinDocLayout: BoolCast(anchor.presPinLayout) },
- anchor,
- focusSpeed,
- {
- pannable: anchor.presPinData ? true : false,
- }
- )
- ? focusSpeed
- : undefined;
- }; // sets viewing information for a componentview, typically when following a link. 'preview' tells the view to use the values without writing to the document
-
- getAnchor = (addAsAnnotation: boolean) => {
- if (this.props.Document.annotationOn) {
- return this.rootDoc;
- }
- const anchor = Docs.Create.TextanchorDocument({ title: 'ViewSpec - ' + StrCast(this.layoutDoc._viewType), presTransition: 500, annotationOn: this.rootDoc });
- PresBox.pinDocView(anchor, { pinData: { pannable: true } }, this.rootDoc);
- const proto = Doc.GetProto(anchor);
- proto[ViewSpecPrefix + '_viewType'] = this.layoutDoc._viewType;
- proto.docFilters = ObjectField.MakeCopy(this.layoutDoc.docFilters as ObjectField) || new List<string>([]);
if (addAsAnnotation) {
if (Cast(this.dataDoc[this.props.fieldKey + '-annotations'], listSpec(Doc), null) !== undefined) {
Cast(this.dataDoc[this.props.fieldKey + '-annotations'], listSpec(Doc), []).push(anchor);
@@ -1651,7 +1575,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
this._firstRender = false;
this._disposers.groupBounds = reaction(
() => {
- if (this.props.Document._isGroup && this.childDocs.length === this.childDocList?.length) {
+ if (this.Document._isGroup && this.childDocs.length === this.childDocList?.length) {
const clist = this.childDocs.map(cd => ({ x: NumCast(cd.x), y: NumCast(cd.y), width: cd[WidthSym](), height: cd[HeightSym]() }));
return aggregateBounds(clist, NumCast(this.layoutDoc._xPadding), NumCast(this.layoutDoc._yPadding));
}
@@ -1758,7 +1682,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
const nativeHeight = height;
return CreateImage(Utils.prepend(''), document.styleSheets, htmlString, nativeWidth, (nativeWidth * panelHeight) / panelWidth, (scrollTop * panelHeight) / realNativeHeight)
.then(async (data_url: any) => {
- const returnedFilename = await VideoBox.convertDataUri(data_url, filename, noSuffix, replaceRootFilename);
+ const returnedFilename = await Utils.convertDataUri(data_url, filename, noSuffix, replaceRootFilename);
cb(returnedFilename as string, nativeWidth, nativeHeight);
})
.catch(function (error: any) {
@@ -2317,21 +2241,21 @@ class CollectionFreeFormBackgroundGrid extends React.Component<CollectionFreeFor
}
export function CollectionBrowseClick(dv: DocumentView, clientX: number, clientY: number) {
+ const browseTransitionTime = 500;
SelectionManager.DeselectAll();
- dv.props.focus(dv.props.Document, {
- willPanZoom: true,
- zoomScale: 0.8,
- afterFocus: async didMove => {
- if (!didMove) {
- const selfFfview = dv.ComponentView instanceof CollectionFreeFormView ? dv.ComponentView : undefined;
- const parFfview = dv.props.CollectionFreeFormDocumentView?.().props.CollectionFreeFormView;
- const ffview = selfFfview && selfFfview.rootDoc[selfFfview.props.scaleField || '_viewScale'] !== 0.5 ? selfFfview : parFfview; // if focus doc is a freeform that is not at it's default 0.5 scale, then zoom out on it. Otherwise, zoom out on the parent ffview
- await ffview?.zoomSmoothlyAboutPt(ffview.getTransform().transformPoint(clientX, clientY), 0.5);
- }
- return ViewAdjustment.doNothing;
- },
- });
- Doc.linkFollowHighlight(dv?.props.Document, false);
+ if (
+ dv.props.focus(dv.props.Document, {
+ willZoomCentered: true,
+ zoomScale: 0.8,
+ zoomTime: browseTransitionTime,
+ }) === undefined
+ ) {
+ const selfFfview = dv.ComponentView instanceof CollectionFreeFormView ? dv.ComponentView : undefined;
+ const parFfview = dv.props.CollectionFreeFormDocumentView?.().props.CollectionFreeFormView;
+ const ffview = selfFfview && selfFfview.rootDoc[selfFfview.props.scaleField || '_viewScale'] !== 0.5 ? selfFfview : parFfview; // if focus doc is a freeform that is not at it's default 0.5 scale, then zoom out on it. Otherwise, zoom out on the parent ffview
+ ffview?.zoomSmoothlyAboutPt(ffview.getTransform().transformPoint(clientX, clientY), 0.5, browseTransitionTime);
+ Doc.linkFollowHighlight(dv?.props.Document, false);
+ }
}
ScriptingGlobals.add(CollectionBrowseClick);
ScriptingGlobals.add(function nextKeyFrame(readOnly: boolean) {
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index bd33c4d80..0714bffbc 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -19,7 +19,6 @@ import { undoBatch, UndoManager } from '../../../util/UndoManager';
import { ContextMenu } from '../../ContextMenu';
import { OpenWhere } from '../../nodes/DocumentView';
import { FormattedTextBox } from '../../nodes/formattedText/FormattedTextBox';
-import { VideoBox } from '../../nodes/VideoBox';
import { pasteImageBitmap } from '../../nodes/WebBoxRenderer';
import { PreviewCursor } from '../../PreviewCursor';
import { SubCollectionViewProps } from '../CollectionSubView';
@@ -167,7 +166,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
pasteImageBitmap((data: any, error: any) => {
error && console.log(error);
data &&
- VideoBox.convertDataUri(data, this.props.Document[Id] + '-thumb-frozen').then(returnedfilename => {
+ Utils.convertDataUri(data, this.props.Document[Id] + '-thumb-frozen').then(returnedfilename => {
this.props.Document['thumb-frozen'] = new ImageField(returnedfilename);
});
})
@@ -397,7 +396,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
newCollection.forceActive = makeGroup;
newCollection.x = this.Bounds.left;
newCollection.y = this.Bounds.top;
- newCollection.fitwidth = true;
+ newCollection.fitWidth = true;
selected.forEach(d => (d.context = newCollection));
this.hideMarquee();
return newCollection;
diff --git a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx
index a2330c6b2..d54e8ce98 100644
--- a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx
+++ b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx
@@ -12,6 +12,7 @@ import { DocumentManager } from '../../../util/DocumentManager';
import { DragManager, dropActionType } from '../../../util/DragManager';
import { Transform } from '../../../util/Transform';
import { Colors, Shadows } from '../../global/globalEnums';
+import { media_state } from '../../nodes/AudioBox';
import { DocumentLinksButton } from '../../nodes/DocumentLinksButton';
import { DocumentView } from '../../nodes/DocumentView';
import { LinkDescriptionPopup } from '../../nodes/LinkDescriptionPopup';
@@ -150,9 +151,13 @@ export class CollectionLinearView extends CollectionSubView() {
<span className="bottomPopup-text">
Currently playing:
{CollectionStackedTimeline.CurrentlyPlaying.map((clip, i) => (
- <span className="audio-title" onPointerDown={() => DocumentManager.Instance.jumpToDocument(clip, { willPanZoom: true }, undefined, [])}>
- {clip.title + (i === CollectionStackedTimeline.CurrentlyPlaying.length - 1 ? '' : ',')}
- </span>
+ <>
+ <span className="audio-title" onPointerDown={() => DocumentManager.Instance.showDocument(clip.rootDoc, { willZoomCentered: true })}>
+ {clip.rootDoc.title + (i === CollectionStackedTimeline.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?.()} />{' '}
+ </>
))}
</span>
</span>
diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
index b88da5191..88d045fa7 100644
--- a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
+++ b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
@@ -234,7 +234,6 @@ export class CollectionMulticolumnView extends CollectionSubView() {
onChildClickHandler = () => ScriptCast(this.Document.onChildClick);
onChildDoubleClickHandler = () => ScriptCast(this.Document.onChildDoubleClick);
- focusDocument = (doc: Doc, options: DocFocusOptions) => this.props.focus(this.rootDoc, options);
isContentActive = () => this.props.isSelected() || this.props.isContentActive() || this.props.isAnyChildContentActive();
isChildContentActive = () => (((this.props.childDocumentsActive?.() || this.Document._childDocumentsActive) && this.props.isDocumentActive?.() && SnappingManager.GetIsDragging()) || this.isContentActive() ? true : false);
getDisplayDoc = (layout: Doc, dxf: () => Transform, width: () => number, height: () => number) => {
@@ -260,7 +259,7 @@ export class CollectionMulticolumnView extends CollectionSubView() {
hideResizeHandles={this.props.childHideResizeHandles?.()}
hideDecorationTitle={this.props.childHideDecorationTitle?.()}
fitContentsToBox={this.props.fitContentsToBox}
- focus={this.focusDocument}
+ focus={this.props.focus}
docFilters={this.childDocFilters}
docRangeFilters={this.childDocRangeFilters}
searchFilterDocs={this.searchFilterDocs}
diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
index 407deaabd..f18917bef 100644
--- a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
+++ b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
@@ -234,7 +234,6 @@ export class CollectionMultirowView extends CollectionSubView() {
onChildClickHandler = () => ScriptCast(this.Document.onChildClick);
onChildDoubleClickHandler = () => ScriptCast(this.Document.onChildDoubleClick);
- focusDocument = (doc: Doc, options: DocFocusOptions) => this.props.focus(this.rootDoc, options);
isContentActive = () => this.props.isSelected() || this.props.isContentActive() || this.props.isAnyChildContentActive();
isChildContentActive = () => (((this.props.childDocumentsActive?.() || this.Document._childDocumentsActive) && this.props.isDocumentActive?.() && SnappingManager.GetIsDragging()) || this.isContentActive() ? true : false);
getDisplayDoc = (layout: Doc, dxf: () => Transform, width: () => number, height: () => number) => {
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaCells.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaCells.tsx
index 97a6c5c18..18ddd881b 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaCells.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaCells.tsx
@@ -214,7 +214,7 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
const aliasdoc = await SearchUtil.GetAliasesOfDocument(this._rowDataDoc);
const targetContext = aliasdoc.length <= 0 ? undefined : Cast(aliasdoc[0].context, Doc, null);
// Jump to the this document
- DocumentManager.Instance.jumpToDocument(this._rowDoc, { willPan: true }, emptyFunction, targetContext ? [targetContext] : [], () => this.props.setPreviewDoc(this._rowDoc));
+ DocumentManager.Instance.showDocument(this._rowDoc, { willPan: true }, () => this.props.setPreviewDoc(this._rowDoc));
}
};