aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/DocumentView.tsx
diff options
context:
space:
mode:
authorSophie Zhang <sophie_zhang@brown.edu>2024-02-22 10:22:58 -0500
committerSophie Zhang <sophie_zhang@brown.edu>2024-02-22 10:22:58 -0500
commit3f33a680af31a04b58c6163fda53a80a737837c6 (patch)
treeb84da40da1c13c8ab8ab8cd763b69ac5b39ce93c /src/client/views/nodes/DocumentView.tsx
parent70cf5ad795055c1f628c918b08a13a96e4ab89a6 (diff)
parentcf85ee4ea73985529a16321d671d893ddb862439 (diff)
Merge branch 'master' into sophie-ai-images
Diffstat (limited to 'src/client/views/nodes/DocumentView.tsx')
-rw-r--r--src/client/views/nodes/DocumentView.tsx221
1 files changed, 105 insertions, 116 deletions
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 8eb354e1e..d131f72d5 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -20,13 +20,14 @@ import { DocServer } from '../../DocServer';
import { Networking } from '../../Network';
import { GooglePhotos } from '../../apis/google_docs/GooglePhotosClientUtils';
import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes';
-import { DocOptions, DocUtils, Docs, FInfo } from '../../documents/Documents';
+import { DocOptions, DocUtils, Docs } from '../../documents/Documents';
import { DictationManager } from '../../util/DictationManager';
import { DocumentManager } from '../../util/DocumentManager';
import { DragManager, dropActionType } from '../../util/DragManager';
import { FollowLinkScript } from '../../util/LinkFollower';
import { LinkManager } from '../../util/LinkManager';
import { ScriptingGlobals } from '../../util/ScriptingGlobals';
+import { SearchUtil } from '../../util/SearchUtil';
import { SelectionManager } from '../../util/SelectionManager';
import { SettingsManager } from '../../util/SettingsManager';
import { SharingManager } from '../../util/SharingManager';
@@ -103,9 +104,11 @@ export interface DocumentViewProps extends FieldViewSharedProps {
dontHideOnDrag?: boolean;
suppressSetHeight?: boolean;
onClickScriptDisable?: 'never' | 'always'; // undefined = only when selected
+ DataTransition?: () => string | undefined;
NativeWidth?: () => number;
NativeHeight?: () => number;
contextMenuItems?: () => { script: ScriptField; filter?: ScriptField; label: string; icon: string }[];
+ dragConfig?: (data: DragManager.DocumentDragData) => void;
dragStarting?: () => void;
dragEnding?: () => void;
}
@@ -114,7 +117,6 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
// this makes mobx trace() statements more descriptive
public get displayName() { return 'DocumentViewInternal(' + this.Document.title + ')'; } // prettier-ignore
public static SelectAfterContextMenu = true; // whether a document should be selected after it's contextmenu is triggered.
-
/**
* This function is filled in by MainView to allow non-viewBox views to add Docs as tabs without
* needing to know about/reference MainView
@@ -236,16 +238,15 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
runInAction(() => (this._mounted = true));
this.setupHandlers();
this._disposers.contentActive = reaction(
- () => {
+ () =>
// true - if the document has been activated directly or indirectly (by having its children selected)
// false - if its pointer events are explicitly turned off or if it's container tells it that it's inactive
// undefined - it is not active, but it should be responsive to actions that might activate it or its contents (eg clicking)
- return this._props.isContentActive() === false || this._props.pointerEvents?.() === 'none'
+ this._props.isContentActive() === false || this._props.pointerEvents?.() === 'none'
? false
: Doc.ActiveTool !== InkTool.None || SnappingManager.CanEmbed || this.rootSelected() || this.Document.forceActive || this._componentView?.isAnyChildContentActive?.() || this._props.isContentActive()
? true
- : undefined;
- },
+ : undefined,
active => (this._isContentActive = active),
{ fireImmediately: true }
);
@@ -289,7 +290,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
dragData.moveDocument = this._props.moveDocument;
dragData.draggedViews = [docView];
dragData.canEmbed = this.Document.dragAction ?? this._props.dragAction ? true : false;
- this._componentView?.dragConfig?.(dragData);
+ (this._props.dragConfig ?? this._componentView?.dragConfig)?.(dragData);
DragManager.StartDocumentDrag(
selected.map(dv => dv.ContentDiv!),
dragData,
@@ -312,20 +313,23 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
let stopPropagate = true;
let preventDefault = true;
!this.layoutDoc._keepZWhenDragged && this._props.bringToFront?.(this.Document);
+ const scriptProps = {
+ this: this.Document,
+ _readOnly_: false,
+ scriptContext: this._props.scriptContext,
+ documentView,
+ clientX: e.clientX,
+ clientY: e.clientY,
+ shiftKey: e.shiftKey,
+ altKey: e.altKey,
+ metaKey: e.metaKey,
+ value: undefined,
+ };
if (this._doubleTap) {
const defaultDblclick = this._props.defaultDoubleClick?.() || this.Document.defaultDoubleClick;
if (this.onDoubleClickHandler?.script) {
- const { clientX, clientY, shiftKey, altKey, ctrlKey } = e; // or we could call e.persist() to capture variables
- // prettier-ignore
- const func = () => this.onDoubleClickHandler.script.run( {
- this: this.Document,
- scriptContext: this._props.scriptContext,
- documentView,
- clientX, clientY, altKey, shiftKey, ctrlKey,
- value: undefined,
- }, console.log );
- UndoManager.RunInBatch(() => (func().result?.select === true ? this._props.select(false) : ''), 'on double click');
- } else if (!Doc.IsSystem(this.Document) && (defaultDblclick === undefined || defaultDblclick === 'default')) {
+ UndoManager.RunInBatch(() => this.onDoubleClickHandler.script.run(scriptProps, console.log).result?.select && this._props.select(false), 'on double click: ' + this.Document.title);
+ } else if (!Doc.IsSystem(this.Document) && defaultDblclick !== 'ignore') {
UndoManager.RunInBatch(() => LightboxView.Instance.AddDocTab(this.Document, OpenWhere.lightbox), 'double tap');
SelectionManager.DeselectAll();
Doc.UnBrushDoc(this.Document);
@@ -338,33 +342,14 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
} else {
let clickFunc: undefined | (() => any);
if (!this.disableClickScriptFunc && this.onClickHandler?.script) {
- const { clientX, clientY, shiftKey, altKey, metaKey } = e;
- const func = () => {
- // replace default add doc func with this view's add doc func.
- // to allow override behaviors for how to display links to undisplayed documents.
- // e.g., if this document is part of a labeled 'lightbox' container, then documents will be shown in place
- // instead of in the global lightbox
+ clickFunc = undoable(() => {
+ // use this view's add doc func to override method for following links to undisplayed documents.
+ // e.g., if this document is part of a labeled 'lightbox' container, then documents will be shown in this container of in the global lightbox
const oldFunc = DocumentViewInternal.addDocTabFunc;
DocumentViewInternal.addDocTabFunc = this._props.addDocTab;
- this.onClickHandler?.script.run(
- {
- this: this.Document,
- _readOnly_: false,
- scriptContext: this._props.scriptContext,
- documentView,
- clientX,
- clientY,
- shiftKey,
- altKey,
- metaKey,
- },
- console.log
- ).result?.select === true
- ? this._props.select(false)
- : '';
+ this.onClickHandler?.script.run(scriptProps, console.log).result?.select && this._props.select(false);
DocumentViewInternal.addDocTabFunc = oldFunc;
- };
- clickFunc = () => UndoManager.RunInBatch(func, 'click ' + this.Document.title);
+ }, 'click ' + this.Document.title);
} else {
// onDragStart implies a button doc that we don't want to select when clicking. RootDocument & isTemplateForField implies we're clicking on part of a template instance and we want to select the whole template, not the part
if ((this.layoutDoc.onDragStart || this._props.TemplateDataDocument) && !(e.ctrlKey || e.button > 0)) {
@@ -376,7 +361,6 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
this._singleClickFunc =
// prettier-ignore
clickFunc ?? (() => (sendToBack ? documentView._props.bringToFront?.(this.Document, true) :
- this._componentView?.select?.(e.ctrlKey || e.metaKey, e.shiftKey) ??
this._props.select(e.ctrlKey||e.shiftKey, e.metaKey)));
const waitFordblclick = this._props.waitForDoubleClickToClick?.() ?? this.Document.waitForDoubleClickToClick;
if ((clickFunc && waitFordblclick !== 'never') || waitFordblclick === 'always') {
@@ -412,10 +396,9 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
!Doc.IsInMyOverlay(this.layoutDoc)
) {
e.stopPropagation();
- // don't preventDefault anymore. Goldenlayout, PDF text selection and RTF text selection all need it to go though
- //if (this._props.isSelected(true) && this.Document.type !== DocumentType.PDF && this.layoutDoc._type_collection !== CollectionViewType.Docking) e.preventDefault();
+ // don't preventDefault. Goldenlayout, PDF text selection and RTF text selection all need it to go though
- // listen to move events if document content isn't active or document is draggable
+ // listen to move events when document content isn't active or document is always draggable
if (!this.layoutDoc._lockedPosition && (!this.isContentActive() || BoolCast(this.layoutDoc._dragWhenActive, this._props.dragWhenActive))) {
document.addEventListener('pointermove', this.onPointerMove);
}
@@ -474,11 +457,11 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
deleteClicked = undoable(() => this._props.removeDocument?.(this.Document), 'delete doc');
setToggleDetail = undoable(
- () =>
- (this.Document.onClick = ScriptField.MakeScript(
+ (defaultLayout: string, scriptFieldKey: 'onClick') =>
+ (this.Document[scriptFieldKey] = ScriptField.MakeScript(
`toggleDetail(documentView, "${StrCast(this.Document.layout_fieldKey)
.replace('layout_', '')
- .replace(/^layout$/, 'detail')}")`,
+ .replace(/^layout$/, 'detail')}", "${defaultLayout}")`,
{ documentView: 'any' }
)),
'set toggle detail'
@@ -489,26 +472,24 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
if (this.Document === Doc.ActiveDashboard) {
e.stopPropagation();
e.preventDefault();
- alert(
- (e.target as any)?.closest?.('*.lm_content')
- ? "You can't perform this move most likely because you didn't drag the document's title bar to enable embedding in a different document."
- : 'Linking to document tabs not yet supported. Drop link on document content.'
- );
+ alert((e.target as any)?.closest?.('*.lm_content') ? "You can't perform this move most likely because you didn't drag the document's title bar to enable embedding in a different document." : 'Linking to document tabs not yet supported.');
return true;
}
- const linkdrag = de.complete.annoDragData ?? de.complete.linkDragData;
+ const annoData = de.complete.annoDragData;
+ const linkdrag = annoData ?? de.complete.linkDragData;
if (linkdrag) {
linkdrag.linkSourceDoc = linkdrag.linkSourceGetAnchor();
if (linkdrag.linkSourceDoc && linkdrag.linkSourceDoc !== this.Document) {
- if (de.complete.annoDragData && !de.complete.annoDragData.dropDocument) {
- de.complete.annoDragData.dropDocument = de.complete.annoDragData.dropDocCreator(undefined);
+ if (annoData && !annoData.dropDocument) {
+ annoData.dropDocument = annoData.dropDocCreator(undefined);
}
- if (de.complete.annoDragData || this.Document !== linkdrag.linkSourceDoc.embedContainer) {
- const dropDoc = de.complete.annoDragData?.dropDocument ?? this._componentView?.getAnchor?.(true) ?? this.Document;
- de.complete.linkDocument = DocUtils.MakeLink(linkdrag.linkSourceDoc, dropDoc, {}, undefined, [de.x, de.y - 50]);
- if (de.complete.linkDocument) {
- de.complete.linkDocument.layout_isSvg = true;
- this._docView?.CollectionFreeFormView?.addDocument(de.complete.linkDocument);
+ if (annoData || this.Document !== linkdrag.linkSourceDoc.embedContainer) {
+ const dropDoc = annoData?.dropDocument ?? this._componentView?.getAnchor?.(true) ?? this.Document;
+ const linkDoc = DocUtils.MakeLink(linkdrag.linkSourceDoc, dropDoc, {}, undefined, [de.x, de.y - 50]);
+ if (linkDoc) {
+ de.complete.linkDocument = linkDoc;
+ linkDoc.layout_isSvg = true;
+ DocumentManager.LinkCommonAncestor(linkDoc)?.ComponentView?.addDocument?.(linkDoc);
}
}
e.stopPropagation();
@@ -518,25 +499,6 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
return false;
}, 'drop doc');
- makeIntoPortal = undoable(() => {
- const portalLink = this._allLinks.find(d => d.link_anchor_1 === this.Document && d.link_relationship === 'portal to:portal from');
- if (!portalLink) {
- DocUtils.MakeLink(
- this.Document,
- Docs.Create.FreeformDocument([], {
- _width: NumCast(this.layoutDoc._width) + 10,
- _height: Math.max(NumCast(this.layoutDoc._height), NumCast(this.layoutDoc._width) + 10),
- _isLightbox: true,
- _layout_fitWidth: true,
- title: StrCast(this.Document.title) + ' [Portal]',
- }),
- { link_relationship: 'portal to:portal from' }
- );
- }
- this.Document.followLinkLocation = OpenWhere.lightbox;
- this.Document.onClick = FollowLinkScript();
- }, 'make into portal');
-
importDocument = () => {
const input = document.createElement('input');
input.type = 'file';
@@ -627,17 +589,13 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
const existingOnClick = cm.findByDescription('OnClick...');
const onClicks: ContextMenuProps[] = existingOnClick && 'subitems' in existingOnClick ? existingOnClick.subitems : [];
- onClicks.push({ description: 'Enter Portal', event: this.makeIntoPortal, icon: 'window-restore' });
+ onClicks.push({ description: 'Enter Portal', event: undoable(e => DocUtils.makeIntoPortal(this.Document, this.layoutDoc, this._allLinks), 'make into portal'), icon: 'window-restore' });
!Doc.noviceMode && onClicks.push({ description: 'Toggle Detail', event: this.setToggleDetail, icon: 'concierge-bell' });
if (!this.Document.annotationOn) {
- const options = cm.findByDescription('Options...');
- const optionItems: ContextMenuProps[] = options && 'subitems' in options ? options.subitems : [];
- !options && cm.addItem({ description: 'Options...', subitems: optionItems, icon: 'compass' });
-
onClicks.push({ description: this.onClickHandler ? 'Remove Click Behavior' : 'Follow Link', event: () => this.toggleFollowLink(false, false), icon: 'link' });
!Doc.noviceMode && onClicks.push({ description: 'Edit onClick Script', event: () => UndoManager.RunInBatch(() => DocUtils.makeCustomViewClicked(this.Document, undefined, 'onClick'), 'edit onClick'), icon: 'terminal' });
- !existingOnClick && cm.addItem({ description: 'OnClick...', noexpand: true, subitems: onClicks, icon: 'mouse-pointer' });
+ cm.addItem({ description: 'OnClick...', noexpand: true, subitems: onClicks, icon: 'mouse-pointer' });
} else if (LinkManager.Links(this.Document).length) {
onClicks.push({ description: 'Restore On Click default', event: () => this.noOnClick(), icon: 'link' });
onClicks.push({ description: 'Follow Link on Click', event: () => this.followLinkOnClick(), icon: 'link' });
@@ -768,7 +726,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
};
removeLinkByHiding = (link: Doc) => () => (link.link_displayLine = false);
- allLinkEndpoints = () => {
+ @computed get allLinkEndpoints() {
// the small blue dots that mark the endpoints of links
if (this._componentView instanceof KeyValueBox || this._props.hideLinkAnchors || this.layoutDoc.layout_hideLinkAnchors || this._props.dontRegisterView || this.layoutDoc.layout_unrendered) return null;
return this.filteredLinks.map(link => (
@@ -792,9 +750,9 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
/>
</div>
));
- };
+ }
- viewBoxContents = () => {
+ @computed get viewBoxContents() {
TraceMobx();
const isInk = this.layoutDoc._layout_isSvg && !this._props.LayoutTemplateString;
const noBackground = this.Document.isGroup && !this._props.LayoutTemplateString?.includes(KeyValueBox.name) && (!this.layoutDoc.backgroundColor || this.layoutDoc.backgroundColor === 'transparent');
@@ -818,12 +776,12 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
rootSelected={this.rootSelected}
onClickScript={this.onClickFunc}
setTitleFocus={this.setTitleFocus}
- hideClickBehaviors={BoolCast(this.layoutDoc.hideClickBehaviors)}
+ hideClickBehaviors={BoolCast(this.Document.hideClickBehaviors)}
/>
- {this.layoutDoc.layout_hideAllLinks ? null : this.allLinkEndpoints()}
+ {this.layoutDoc.layout_hideAllLinks ? null : this.allLinkEndpoints}
</div>
);
- };
+ }
captionStyleProvider = (doc: Opt<Doc>, props: Opt<FieldViewProps>, property: string) => this._props?.styleProvider?.(doc, props, property + ':caption');
fieldsDropdown = (reqdFields: string[], dropdownWidth: number, placeholder: string, onChange: (val: string | number) => void, onClose: () => void) => {
@@ -856,7 +814,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
* setting layout_showTitle using the format: field1[;field2[...][:hover]]
* from the UI, this is done by clicking the title field and prefixin the format with '#'. eg., #field1[;field2;...][:hover]
**/
- titleView = () => {
+ @computed get titleView() {
const showTitle = this.layout_showTitle?.split(':')[0];
const showTitleHover = this.layout_showTitle?.includes(':hover');
@@ -930,9 +888,9 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
</div>
</div>
);
- };
+ }
- captionView = () => {
+ @computed get captionView() {
return !this.layout_showCaption ? null : (
<div
className="documentView-captionWrapper"
@@ -955,7 +913,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
/>
</div>
);
- };
+ }
renderDoc = (style: object) => {
TraceMobx();
@@ -975,15 +933,15 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
fontFamily: StrCast(this.Document._text_fontFamily, 'inherit'),
fontSize: Cast(this.Document._text_fontSize, 'string', null),
transform: this._animateScalingTo ? `scale(${this._animateScalingTo})` : undefined,
- transition: !this._animateScalingTo ? StrCast(this.Document.dataTransition) : `transform ${this.animateScaleTime() / 1000}s ease-${this._animateScalingTo < 1 ? 'in' : 'out'}`,
+ transition: !this._animateScalingTo ? this._props.DataTransition?.() : `transform ${this.animateScaleTime() / 1000}s ease-${this._animateScalingTo < 1 ? 'in' : 'out'}`,
}}>
{this._props.hideTitle || (!showTitle && !this.layout_showCaption) ? (
- this.viewBoxContents()
+ this.viewBoxContents
) : (
<div className="documentView-styleWrapper">
- {this.titleView()}
- {this.viewBoxContents()}
- {this.captionView()}
+ {this.titleView}
+ {this.viewBoxContents}
+ {this.captionView}
</div>
)}
{this.widgetDecorations ?? null}
@@ -1117,6 +1075,7 @@ export class DocumentView extends DocComponent<DocumentViewProps>() {
private _disposers: { [name: string]: IReactionDisposer } = {};
private _viewTimer: NodeJS.Timeout | undefined;
private _animEffectTimer: NodeJS.Timeout | undefined;
+ public Guid = Utils.GenerateGuid(); // a unique id associated with the main <div>. used by LinkBox's Xanchor to find the arrowhead locations.
@computed public static get exploreMode() {
return () => (SnappingManager.ExploreMode ? ScriptField.MakeScript('CollectionBrowseClick(documentView, clientX, clientY)', { documentView: 'any', clientX: 'number', clientY: 'number' })! : undefined);
@@ -1193,6 +1152,7 @@ export class DocumentView extends DocComponent<DocumentViewProps>() {
}
componentWillUnmount() {
+ this._viewTimer && clearTimeout(this._viewTimer);
runInAction(() => this.Document[DocViews].delete(this));
Object.values(this._disposers).forEach(disposer => disposer?.());
!BoolCast(this.Document.dontRegisterView, this._props.dontRegisterView) && DocumentManager.Instance.RemoveView(this);
@@ -1216,21 +1176,23 @@ export class DocumentView extends DocComponent<DocumentViewProps>() {
return this._props.LayoutTemplateString?.includes('link_anchor_2') ? DocCast(this.Document['link_anchor_2']) : this._props.LayoutTemplateString?.includes('link_anchor_1') ? DocCast(this.Document['link_anchor_1']) : undefined;
}
- @computed get getBounds() {
- if (!this._docViewInternal?._contentDiv || Doc.AreProtosEqual(this.Document, Doc.UserDoc())) {
+ @computed get getBounds(): Opt<{ left: number; top: number; right: number; bottom: number; transition?: string }> {
+ if (!this.ContentDiv || Doc.AreProtosEqual(this.Document, Doc.UserDoc())) {
return undefined;
}
- if (this._docViewInternal._componentView?.screenBounds?.()) {
- return this._docViewInternal._componentView.screenBounds();
+ if (this.ComponentView?.screenBounds?.()) {
+ return this.ComponentView.screenBounds();
}
const xf = this.screenToContentsTransform().scale(this.nativeScaling).inverse();
const [[left, top], [right, bottom]] = [xf.transformPoint(0, 0), xf.transformPoint(this.panelWidth, this.panelHeight)];
if (this._props.LayoutTemplateString?.includes(LinkAnchorBox.name)) {
- const docuBox = this._docViewInternal._contentDiv.getElementsByClassName('linkAnchorBox-cont');
- if (docuBox.length) return { ...docuBox[0].getBoundingClientRect(), center: undefined };
+ const docuBox = this.ContentDiv.getElementsByClassName('linkAnchorBox-cont');
+ if (docuBox.length) return { ...docuBox[0].getBoundingClientRect(), transition: undefined };
}
- return { left, top, right, bottom };
+ // transition is returned so that the bounds will 'update' at the end of an animated transition. This is needed by xAnchor in LinkBox
+ const transition = this.docViewPath().find((parent: DocumentView) => parent.DataTransition?.() || parent.ComponentView?.viewTransition?.());
+ return { left, top, right, bottom, transition: transition?.DataTransition?.() || transition?.ComponentView?.viewTransition?.() };
}
@computed get nativeWidth() {
@@ -1254,9 +1216,8 @@ export class DocumentView extends DocComponent<DocumentViewProps>() {
this.layoutDoc._viewTransition = undefined;
};
public noOnClick = () => this._docViewInternal?.noOnClick();
- public makeIntoPortal = () => this._docViewInternal?.makeIntoPortal();
public toggleFollowLink = (zoom?: boolean, setTargetToggle?: boolean): void => this._docViewInternal?.toggleFollowLink(zoom, setTargetToggle);
- public setToggleDetail = () => this._docViewInternal?.setToggleDetail();
+ public setToggleDetail = (defaultLayout = '', scriptFieldKey = 'onClick') => this._docViewInternal?.setToggleDetail(defaultLayout, scriptFieldKey);
public onContextMenu = (e?: React.MouseEvent, pageX?: number, pageY?: number) => this._docViewInternal?.onContextMenu?.(e, pageX, pageY);
public cleanupPointerEvents = () => this._docViewInternal?.cleanupPointerEvents();
public startDragging = (x: number, y: number, dropAction: dropActionType, hideSource = false) => this._docViewInternal?.startDragging(x, y, dropAction, hideSource);
@@ -1376,6 +1337,7 @@ export class DocumentView extends DocComponent<DocumentViewProps>() {
}
}
};
+ DataTransition = () => this._props.DataTransition?.() || StrCast(this.Document.dataTransition);
ShouldNotScale = () => this.shouldNotScale;
NativeWidth = () => this.effectiveNativeWidth;
NativeHeight = () => this.effectiveNativeHeight;
@@ -1428,7 +1390,7 @@ export class DocumentView extends DocComponent<DocumentViewProps>() {
const yshift = Math.abs(this.Yshift) <= 0.001 ? this._props.PanelHeight() : undefined;
return (
- <div className="contentFittingDocumentView" onPointerEnter={action(() => (this._isHovering = true))} onPointerLeave={action(() => (this._isHovering = false))}>
+ <div id={this.Guid} className="contentFittingDocumentView" onPointerEnter={action(() => (this._isHovering = true))} onPointerLeave={action(() => (this._isHovering = false))}>
{!this.Document || !this._props.PanelWidth() ? null : (
<div
className="contentFittingDocumentView-previewDoc"
@@ -1441,6 +1403,7 @@ export class DocumentView extends DocComponent<DocumentViewProps>() {
<DocumentViewInternal
{...this._props}
fieldKey={this.LayoutFieldKey}
+ DataTransition={this.DataTransition}
DocumentView={this.selfView}
docViewPath={this.docViewPath}
PanelWidth={this.PanelWidth}
@@ -1504,13 +1467,13 @@ ScriptingGlobals.add(function deiconifyViewToLightbox(documentView: DocumentView
LightboxView.Instance.AddDocTab(documentView.Document, OpenWhere.lightbox, 'layout'); //, 0);
});
-ScriptingGlobals.add(function toggleDetail(dv: DocumentView, detailLayoutKeySuffix: string) {
- if (dv.Document.layout_fieldKey === 'layout_' + detailLayoutKeySuffix) dv.switchViews(false, 'layout');
+ScriptingGlobals.add(function toggleDetail(dv: DocumentView, detailLayoutKeySuffix: string, defaultLayout = '') {
+ if (dv.Document.layout_fieldKey === 'layout_' + detailLayoutKeySuffix) dv.switchViews(defaultLayout ? true : false, defaultLayout, undefined, true);
else dv.switchViews(true, detailLayoutKeySuffix, undefined, true);
});
ScriptingGlobals.add(function updateLinkCollection(linkCollection: Doc, linkSource: Doc) {
- const collectedLinks = DocListCast(Doc.GetProto(linkCollection).data);
+ const collectedLinks = DocListCast(linkCollection[DocData].data);
let wid = NumCast(linkSource._width);
let embedding: Doc | undefined;
const links = LinkManager.Links(linkSource);
@@ -1529,3 +1492,29 @@ ScriptingGlobals.add(function updateLinkCollection(linkCollection: Doc, linkSour
embedding && DocServer.UPDATE_SERVER_CACHE(); // if a new embedding was made, update the client's server cache so that it will not come back as a promise
return links;
});
+ScriptingGlobals.add(function updateTagsCollection(collection: Doc) {
+ const tag = StrCast(collection.title).split('-->')[1];
+ const matchedTags = Array.from(SearchUtil.SearchCollection(Doc.MyFilesystem, tag, false, ['tags']).keys());
+ const collectionDocs = DocListCast(collection[DocData].data).concat(collection);
+ let wid = 100;
+ let created = false;
+ const matchedDocs = matchedTags
+ .filter(tagDoc => !Doc.AreProtosEqual(collection, tagDoc))
+ .reduce((aset, tagDoc) => {
+ let embedding = Array.from(aset).find(doc => Doc.AreProtosEqual(tagDoc, doc)) ?? collectionDocs.find(doc => Doc.AreProtosEqual(tagDoc, doc));
+ if (!embedding) {
+ embedding = Doc.MakeEmbedding(tagDoc);
+ embedding.x = wid;
+ embedding.y = 0;
+ embedding._lockedPosition = false;
+ wid += NumCast(tagDoc._width);
+ created = true;
+ }
+ Doc.SetContainer(embedding, collection);
+ aset.add(embedding);
+ return aset;
+ }, new Set<Doc>());
+
+ created && (collection[DocData].data = new List<Doc>(Array.from(matchedDocs)));
+ return true;
+});