From af2a2c83868c87812e9ae54c8e3cced81374619a Mon Sep 17 00:00:00 2001 From: bobzel Date: Mon, 27 Feb 2023 15:08:45 -0500 Subject: restructured getAnchor()/scrollFocus to be more consistent. added setterscript for computedFields. restructed getFieldsImpl to avoid making multiple requests for the same document due to timing issues by 'locking' a document cache with a promise before sending the server request. added rotation and fill color as animatable fields. fixed image cropping for --- src/client/views/DocumentButtonBar.tsx | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'src/client/views/DocumentButtonBar.tsx') diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx index f61d147cf..9298c881c 100644 --- a/src/client/views/DocumentButtonBar.tsx +++ b/src/client/views/DocumentButtonBar.tsx @@ -315,7 +315,13 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV .views() .filter(v => v) .map(dv => dv!.rootDoc); - TabDocView.PinDoc(docs, { pinAudioPlay: true, pinDocLayout, pinDocContent, activeFrame: Cast(docs.lastElement()?.activeFrame, 'number', null), currentFrame: Cast(docs.lastElement()?.currentFrame, 'number', null) }); + TabDocView.PinDoc(docs, { + pinAudioPlay: true, + pinDocLayout, + pinData: { dataview: true }, + activeFrame: Cast(docs.lastElement()?.activeFrame, 'number', null), + currentFrame: Cast(docs.lastElement()?.currentFrame, 'number', null), + }); e.stopPropagation(); }} /> @@ -496,7 +502,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV const rootView = this.props.views()[0]; const rootDoc = rootView?.rootDoc; if (rootDoc) { - const anchor = rootView.ComponentView?.getAnchor?.(true) ?? rootDoc; + const anchor = rootView.ComponentView?.getAnchor?.(false) ?? rootDoc; const trail = DocCast(anchor.presTrail) ?? Doc.MakeCopy(DocCast(Doc.UserDoc().emptyTrail), true); if (trail !== anchor.presTrail) { DocUtils.MakeLink({ doc: anchor }, { doc: trail }, 'link trail'); -- cgit v1.2.3-70-g09d2 From f1dea8f31886c1e5e3d8bb772434009803b8fb8a Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 28 Feb 2023 14:47:27 -0500 Subject: added view spec capture options to complete link --- src/client/views/DocumentButtonBar.scss | 19 +++--- src/client/views/DocumentButtonBar.tsx | 70 ++++++++++++++++++++-- src/client/views/nodes/DocumentLinksButton.tsx | 63 ++----------------- .../views/nodes/formattedText/FormattedTextBox.tsx | 15 ++++- 4 files changed, 91 insertions(+), 76 deletions(-) (limited to 'src/client/views/DocumentButtonBar.tsx') diff --git a/src/client/views/DocumentButtonBar.scss b/src/client/views/DocumentButtonBar.scss index 835d6c8bb..1abf33cac 100644 --- a/src/client/views/DocumentButtonBar.scss +++ b/src/client/views/DocumentButtonBar.scss @@ -18,6 +18,8 @@ $linkGap: 3px; cursor: pointer; } +.documentButtonBar-endLinkTypes, +.documentButtonBar-linkTypes, .documentButtonBar-followTypes, .documentButtonBar-pinTypes { position: absolute; @@ -28,15 +30,6 @@ $linkGap: 3px; height: 20px; align-items: center; } -.documentButtonBar-linkTypes { - position: absolute; - display: none; - width: 60px; - top: -14px; - background: black; - height: 20px; - align-items: center; -} .documentButtonBar-followTypes { width: 20px; display: none; @@ -72,6 +65,14 @@ $linkGap: 3px; } } } +.documentButtonBar-endLink { + color: white; + &:hover { + .documentButtonBar-endLinkTypes { + display: flex; + } + } +} .documentButtonBar-pinIcon { &:hover { diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx index 9298c881c..20c35739e 100644 --- a/src/client/views/DocumentButtonBar.tsx +++ b/src/client/views/DocumentButtonBar.tsx @@ -28,6 +28,7 @@ import { TemplateMenu } from './TemplateMenu'; import React = require('react'); import { DocumentType } from '../documents/DocumentTypes'; import { FontIconBox } from './nodes/button/FontIconBox'; +import { PinProps } from './nodes/trails'; const higflyout = require('@hig/flyout'); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; @@ -285,6 +286,52 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV ); } + @observable subEndLink = ''; + @computed + get endLinkButton() { + const linkBtn = (pinDocLayout: boolean, pinDocContent: boolean, icon: IconProp) => { + const tooltip = `Finish Link and Save ${this.subEndLink} data`; + return !this.view0 ? null : ( + {tooltip}}> +
+ (this.subEndLink = (pinDocLayout ? 'Layout' : '') + (pinDocLayout && pinDocContent ? ' &' : '') + (pinDocContent ? ' Content' : '')))} + onPointerLeave={action(e => (this.subEndLink = ''))} + onClick={e => { + const docs = this.props + .views() + .filter(v => v) + .map(dv => dv!.rootDoc); + this.view0 && + DocumentLinksButton.finishLinkClick(e.clientX, e.clientY, DocumentLinksButton.StartLink, this.view0.props.Document, true, this.view0, { + pinDocLayout, + pinDocContent, + pinData: !pinDocContent ? {} : { poslayoutview: true, dataannos: true, dataview: true }, + } as PinProps); + + e.stopPropagation(); + }} + /> +
+
+ ); + }; + return !this.view0 ? null : ( +
+
+ {linkBtn(true, false, 'window-maximize')} + {linkBtn(false, true, 'address-card')} + {linkBtn(true, true, 'id-card')} +
+ +
+ ); + } @observable subPin = ''; @computed @@ -497,6 +544,23 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV this._showLinkPopup = !this._showLinkPopup; e.stopPropagation(); }; + + @observable _captureEndLinkLayout = false; + @action + captureEndLinkLayout = (e: React.PointerEvent) => { + this._captureEndLinkLayout = !this._captureEndLinkLayout; + }; + @observable _captureEndLinkContent = false; + @action + captureEndLinkContent = (e: React.PointerEvent) => { + this._captureEndLinkContent = !this._captureEndLinkContent; + }; + + @action + captureEndLinkState = (e: React.PointerEvent) => { + this._captureEndLinkContent = this._captureEndLinkLayout = !this._captureEndLinkLayout; + }; + @action toggleTrail = (e: React.PointerEvent) => { const rootView = this.props.views()[0]; @@ -539,11 +603,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
{this.linkButton}
)} - {(DocumentLinksButton.StartLink || Doc.UserDoc()['documentLinksButton-fullMenu']) && DocumentLinksButton.StartLink !== doc ? ( -
- -
- ) : null} + {DocumentLinksButton.StartLink && DocumentLinksButton.StartLink !== doc ?
{this.endLinkButton}
: null} { Doc.noviceMode ? null :
{this.templateButton}
/*
{this.metadataButton}
*/ diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx index 5783d0e57..a40599d85 100644 --- a/src/client/views/nodes/DocumentLinksButton.tsx +++ b/src/client/views/nodes/DocumentLinksButton.tsx @@ -128,48 +128,8 @@ export class DocumentLinksButton extends React.Component { - if (doubleTap && !this.props.StartLink) { - if (DocumentLinksButton.StartLink === this.props.View.props.Document) { - DocumentLinksButton.StartLink = undefined; - DocumentLinksButton.StartLinkView = undefined; - DocumentLinksButton.AnnotationId = undefined; - } else if (DocumentLinksButton.StartLink && DocumentLinksButton.StartLink !== this.props.View.props.Document) { - const sourceDoc = DocumentLinksButton.StartLink; - const targetDoc = this.props.View.ComponentView?.getAnchor?.(true) || this.props.View.Document; - const linkDoc = DocUtils.MakeLink({ doc: sourceDoc }, { doc: targetDoc }, 'links'); //why is long drag here when this is used for completing links by clicking? - - LinkManager.currentLink = linkDoc; - - runInAction(() => { - if (linkDoc) { - TaskCompletionBox.textDisplayed = 'Link Created'; - TaskCompletionBox.popupX = e.screenX; - TaskCompletionBox.popupY = e.screenY - 133; - TaskCompletionBox.taskCompleted = true; - - LinkDescriptionPopup.popupX = e.screenX; - LinkDescriptionPopup.popupY = e.screenY - 100; - LinkDescriptionPopup.descriptionPopup = true; - - const rect = document.body.getBoundingClientRect(); - if (LinkDescriptionPopup.popupX + 200 > rect.width) { - LinkDescriptionPopup.popupX -= 190; - TaskCompletionBox.popupX -= 40; - } - if (LinkDescriptionPopup.popupY + 100 > rect.height) { - LinkDescriptionPopup.popupY -= 40; - TaskCompletionBox.popupY -= 40; - } - - setTimeout( - action(() => (TaskCompletionBox.taskCompleted = false)), - 2500 - ); - } - }); - } - } + action(e => { + DocumentLinksButton.finishLinkClick(e.clientX, e.clientY, DocumentLinksButton.StartLink, this.props.View.props.Document, true, this.props.View); }) ) ); @@ -280,22 +240,7 @@ export class DocumentLinksButton extends React.Component ) : null} {!this.props.StartLink && DocumentLinksButton.StartLink !== this.props.View.props.Document ? ( //if the origin node is not this node -
- DocumentLinksButton.StartLink && - DocumentLinksButton.finishLinkClick( - e.clientX, - e.clientY, - DocumentLinksButton.StartLink, - this.props.View.props.Document, - true, - this.props.View, - (e.shiftKey ? { pinDocLayout: true, pinDocContent: true, pinData: { poslayoutview: true, dataannos: true, dataview: true } } : {}) as PinProps - ) - }> +
) : null} @@ -304,7 +249,7 @@ export class DocumentLinksButton extends React.Component this.makeLinkAnchor(undefined, OpenWhere.addRight, undefined, 'Anchored Selection', false, addAsAnnotation); + getAnchor = (addAsAnnotation: boolean, pinProps?: PinProps) => { + if (!pinProps) return this.rootDoc; + const anchor = Docs.Create.TextanchorDocument({ annotationOn: this.rootDoc, unrendered: true }); + this.addDocument(anchor); + this.makeLinkAnchor(anchor, OpenWhere.addRight, undefined, 'Anchored Selection', false, addAsAnnotation); + PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), scrollable: true } }, this.rootDoc); + return anchor; + }; @action setupAnchorMenu = () => { @@ -988,8 +996,9 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent clearStyleSheetRules(FormattedTextBox._highlightStyleSheet), Math.max(this._focusSpeed || 0, 3000)); } } - - return this._didScroll ? this._focusSpeed : didToggle ? 1 : undefined; // if we actually scrolled, then return some focusSpeed + const finalFocusSpeed = this._didScroll ? this._focusSpeed : didToggle ? 1 : undefined; + PresBox.restoreTargetDocView(docView, textAnchor, finalFocusSpeed ?? 0); + return finalFocusSpeed; // if we actually scrolled, then return some focusSpeed }; // if the scroll height has changed and we're in autoHeight mode, then we need to update the textHeight component of the doc. -- cgit v1.2.3-70-g09d2 From 5e7989da274606638c96f649e97e9d1a979956f5 Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 28 Feb 2023 20:57:01 -0500 Subject: cleaning up of following inPlace links to overlay current inplaceContainer contents instead of deleting them. --- src/client/util/LinkFollower.ts | 8 ++--- src/client/views/DocumentButtonBar.tsx | 2 +- src/client/views/LightboxView.tsx | 11 ++---- src/client/views/PropertiesButtons.tsx | 39 ++++++++++------------ src/client/views/PropertiesView.tsx | 6 ++-- src/client/views/collections/CollectionSubView.tsx | 1 + src/client/views/collections/TabDocView.tsx | 12 ++++++- .../collectionFreeForm/CollectionFreeFormView.tsx | 4 ++- src/client/views/nodes/DocumentView.tsx | 9 ++--- src/client/views/nodes/PDFBox.tsx | 10 +++++- src/client/views/nodes/WebBox.tsx | 9 ++++- .../views/nodes/formattedText/FormattedTextBox.tsx | 8 +++++ src/client/views/pdf/PDFViewer.tsx | 2 +- 13 files changed, 72 insertions(+), 49 deletions(-) (limited to 'src/client/views/DocumentButtonBar.tsx') diff --git a/src/client/util/LinkFollower.ts b/src/client/util/LinkFollower.ts index bbfd516da..50bc89ed2 100644 --- a/src/client/util/LinkFollower.ts +++ b/src/client/util/LinkFollower.ts @@ -1,11 +1,11 @@ import { action, runInAction } from 'mobx'; import { Doc, DocListCast, Opt } from '../../fields/Doc'; +import { List } from '../../fields/List'; import { BoolCast, Cast, DocCast, NumCast, StrCast } from '../../fields/Types'; -import { CollectionViewType, DocumentType } from '../documents/DocumentTypes'; -import { CollectionDockingView } from '../views/collections/CollectionDockingView'; +import { DocumentType } from '../documents/DocumentTypes'; import { DocumentDecorations } from '../views/DocumentDecorations'; import { LightboxView } from '../views/LightboxView'; -import { DocFocusOptions, DocumentViewSharedProps, OpenWhere, OpenWhereMod, ViewAdjustment } from '../views/nodes/DocumentView'; +import { DocFocusOptions, DocumentViewSharedProps, OpenWhere, ViewAdjustment } from '../views/nodes/DocumentView'; import { PresBox } from '../views/nodes/trails'; import { DocumentManager } from './DocumentManager'; import { LinkManager } from './LinkManager'; @@ -35,7 +35,7 @@ export class LinkFollower { const createViewFunc = (doc: Doc, followLoc: string, finished?: Opt<() => void>) => { const createTabForTarget = (didFocus: boolean) => new Promise(res => { - const where = LightboxView.LightboxDoc ? OpenWhere.inPlace : (StrCast(sourceDoc.followLinkLocation, followLoc) as OpenWhere); + const where = LightboxView.LightboxDoc ? OpenWhere.lightbox : (StrCast(sourceDoc.followLinkLocation, followLoc) as OpenWhere); docViewProps.addDocTab(doc, where); setTimeout(() => { const targDocView = DocumentManager.Instance.getFirstDocumentView(doc); // get first document view available within the lightbox if that's open, or anywhere otherwise. diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx index 20c35739e..af868ba9c 100644 --- a/src/client/views/DocumentButtonBar.tsx +++ b/src/client/views/DocumentButtonBar.tsx @@ -243,7 +243,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
this.props.views().map(view => view?.docView?.toggleFollowLink(undefined, undefined, false)))}> + onClick={undoBatch(e => this.props.views().map(view => view?.docView?.toggleFollowLink(undefined, false)))}>
{followBtn( true, diff --git a/src/client/views/LightboxView.tsx b/src/client/views/LightboxView.tsx index e531bf71c..c9b1dcfd8 100644 --- a/src/client/views/LightboxView.tsx +++ b/src/client/views/LightboxView.tsx @@ -145,13 +145,6 @@ export class LightboxView extends React.Component { } } public static AddDocTab = (doc: Doc, location: OpenWhere, layoutTemplate?: Doc | string) => { - if (location !== OpenWhere.lightbox) { - const inPlaceView = DocCast(doc.context) ? DocumentManager.Instance.getFirstDocumentView(DocCast(doc.context)) : undefined; - if (inPlaceView) { - inPlaceView.dataDoc[Doc.LayoutFieldKey(inPlaceView.rootDoc)] = new List([doc]); - return true; - } - } SelectionManager.DeselectAll(); return LightboxView.SetLightboxDoc( doc, @@ -318,7 +311,7 @@ export class LightboxView extends React.Component {
{ e.stopPropagation(); LightboxView.LightboxDoc!._fitWidth = !LightboxView.LightboxDoc!._fitWidth; @@ -327,7 +320,7 @@ export class LightboxView extends React.Component {
{ e.stopPropagation(); CollectionDockingView.AddSplit(LightboxView._docTarget || LightboxView._doc!, OpenWhereMod.none); diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx index a152b4948..7e33ee495 100644 --- a/src/client/views/PropertiesButtons.tsx +++ b/src/client/views/PropertiesButtons.tsx @@ -6,6 +6,7 @@ import { Doc, DocListCast, Opt } from '../../fields/Doc'; import { Id } from '../../fields/FieldSymbols'; import { InkField } from '../../fields/InkField'; import { RichTextField } from '../../fields/RichTextField'; +import { ScriptField } from '../../fields/ScriptField'; import { BoolCast, StrCast } from '../../fields/Types'; import { ImageField } from '../../fields/URLField'; import { DocUtils } from '../documents/Documents'; @@ -129,27 +130,21 @@ export class PropertiesButtons extends React.Component<{}, {}> { onClick => { SelectionManager.Views().forEach(dv => { const containerDoc = dv.rootDoc; - containerDoc.followAllLinks = - containerDoc.noShadow = - containerDoc.noHighlighting = - containerDoc._isLinkButton = - containerDoc._fitContentsToBox = - containerDoc._forceActive = - containerDoc._isInPlaceContainer = - !containerDoc._isInPlaceContainer; - containerDoc.followLinkLocation = containerDoc._isInPlaceContainer ? OpenWhere.inPlace : undefined; + //containerDoc.followAllLinks = + // containerDoc.noShadow = + // containerDoc.noHighlighting = + // containerDoc._forceActive = + containerDoc._fitContentsToBox = containerDoc._isInPlaceContainer = !containerDoc._isInPlaceContainer; containerDoc._xPadding = containerDoc._yPadding = containerDoc._isInPlaceContainer ? 10 : undefined; - const menuDoc = DocListCast(dv.dataDoc[dv.props.fieldKey ?? Doc.LayoutFieldKey(containerDoc)]).lastElement(); - if (menuDoc) { - menuDoc.hideDecorations = menuDoc._forceActive = menuDoc._fitContentsToBox = menuDoc._isLinkButton = menuDoc._noShadow = menuDoc.noHighlighting = containerDoc._isInPlaceContainer; - if (!dv.allLinks.find(link => link.anchor1 === menuDoc || link.anchor2 === menuDoc)) { - DocUtils.MakeLink({ doc: dv.rootDoc }, { doc: menuDoc }, 'back link to container'); - } - DocListCast(menuDoc[Doc.LayoutFieldKey(menuDoc)]).forEach(menuItem => { - menuItem.followLinkAudio = menuItem.followAllLinks = menuItem._isLinkButton = true; - menuItem._followLinkLocation = OpenWhere.inPlace; + const containerContents = DocListCast(dv.dataDoc[dv.props.fieldKey ?? Doc.LayoutFieldKey(containerDoc)]); + dv.rootDoc.onClick = ScriptField.MakeScript('{self.data = undefined; documentView.select(false)}', { documentView: 'any' }); + containerContents.forEach(doc => { + DocListCast(doc.links).forEach(link => { + doc.isLinkButton = true; + //doc.followLinkLocation = OpenWhere.inPlace; + link.linkDisplay = false; }); - } + }); }); } ); @@ -309,10 +304,12 @@ export class PropertiesButtons extends React.Component<{}, {}> { docView.setToggleDetail(); break; case 'linkInPlace': - docView.toggleFollowLink('inPlace', false, false); + docView.toggleFollowLink(false, false); + docView.props.Document.followLinkLocation = docView.props.Document._isLinkButton ? OpenWhere.inPlace : undefined; break; case 'linkOnRight': - docView.toggleFollowLink('add:right', false, false); + docView.toggleFollowLink(false, false); + docView.props.Document.followLinkLocation = docView.props.Document._isLinkButton ? OpenWhere.addRight : undefined; break; } }); diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index f7708d801..e9d1433c3 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -1406,7 +1406,7 @@ export class PropertiesView extends React.Component { }); @undoBatch - changeFollowBehavior = action((follow: string) => this.sourceAnchor && (this.sourceAnchor.followLinkLocation = follow)); + changeFollowBehavior = action((follow: Opt) => this.sourceAnchor && (this.sourceAnchor.followLinkLocation = follow)); @undoBatch changeAnimationBehavior = action((behavior: string) => this.sourceAnchor && (this.sourceAnchor.followLinkAnimEffect = behavior)); @@ -1615,8 +1615,8 @@ export class PropertiesView extends React.Component {

Follow by

- this.changeFollowBehavior(e.currentTarget.value === 'Default' ? undefined : e.currentTarget.value)} value={Cast(this.sourceAnchor?.followLinkLocation, 'string', null)}> + diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 27ae3041f..c88ae314e 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -67,6 +67,7 @@ export function CollectionSubView(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())); diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx index b75f315ca..01872df84 100644 --- a/src/client/views/collections/TabDocView.tsx +++ b/src/client/views/collections/TabDocView.tsx @@ -358,7 +358,17 @@ export class TabDocView extends React.Component { if (doc.dockingConfig) return DashboardView.openDashboard(doc); // prettier-ignore switch (whereFields[0]) { - case OpenWhere.inPlace: // fall through to lightbox + case undefined: + case OpenWhere.inPlace: { + if (this.layoutDoc?.isInPlaceContainer) { + const inPlaceView = !doc.annotationOn && DocCast(doc.context) ? DocumentManager.Instance.getFirstDocumentView(DocCast(doc.context)) : undefined; + const data = inPlaceView?.dataDoc[Doc.LayoutFieldKey(inPlaceView.rootDoc)]; + if (inPlaceView && (!data || data instanceof List)) { + inPlaceView.layoutDoc[Doc.LayoutFieldKey(inPlaceView.rootDoc)] = new List([doc]); + return true; + } + } + } case OpenWhere.lightbox: return LightboxView.AddDocTab(doc, location); case OpenWhere.dashboard: return DashboardView.openDashboard(doc); case OpenWhere.fullScreen: return CollectionDockingView.OpenFullScreen(doc); diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 0477c6a16..78804b070 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -1395,6 +1395,7 @@ export class CollectionFreeFormView extends CollectionSubView { + if (this.props.isAnnotationOverlay) return this.props.addDocTab(doc, where); switch (where) { case OpenWhere.inParent: return this.props.addDocument?.(doc) || false; @@ -1412,9 +1413,10 @@ export class CollectionFreeFormView extends CollectionSubView(doc instanceof Doc ? [doc] : doc); + this.layoutDoc[this.props.fieldKey] = new List(doc instanceof Doc ? [doc] : doc); return true; } } diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 039a75a1b..beb0f8e3a 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -792,7 +792,7 @@ export class DocumentViewInternal extends DocComponent, zoom?: boolean, setTargetToggle?: boolean): void => { + toggleFollowLink = (zoom?: boolean, setTargetToggle?: boolean): void => { this.Document.ignoreClick = false; if (setTargetToggle) { this.Document.followLinkToggle = !this.Document.followLinkToggle; @@ -802,7 +802,6 @@ export class DocumentViewInternal extends DocComponent (this.Document.ignoreClick = !this.Document.ignoreClick), icon: this.Document.ignoreClick ? 'unlock' : 'lock' }); - onClicks.push({ description: this.Document.isLinkButton ? 'Remove Follow Behavior' : 'Follow Link in Place', event: () => this.toggleFollowLink('inPlace', false, false), icon: 'link' }); - !this.Document.isLinkButton && onClicks.push({ description: 'Follow Link on Right', event: () => this.toggleFollowLink('add:right', false, false), icon: 'link' }); - onClicks.push({ description: this.Document.isLinkButton || this.onClickHandler ? 'Remove Click Behavior' : 'Follow Link', event: () => this.toggleFollowLink(undefined, false, false), icon: 'link' }); - onClicks.push({ description: (this.Document.followLinkToggle ? 'Remove' : 'Make') + ' Target Visibility Toggle', event: () => this.toggleFollowLink(undefined, false, true), icon: 'map-pin' }); + onClicks.push({ description: this.Document.isLinkButton || this.onClickHandler ? 'Remove Click Behavior' : 'Follow Link', event: () => this.toggleFollowLink(false, false), icon: 'link' }); + onClicks.push({ description: (this.Document.followLinkToggle ? 'Remove' : 'Make') + ' Target Visibility Toggle', event: () => this.toggleFollowLink(false, true), icon: 'map-pin' }); onClicks.push({ description: 'Edit onClick Script', event: () => UndoManager.RunInBatch(() => DocUtils.makeCustomViewClicked(this.props.Document, undefined, 'onClick'), 'edit onClick'), icon: 'terminal' }); !existingOnClick && cm.addItem({ description: 'OnClick...', addDivider: true, noexpand: true, subitems: onClicks, icon: 'mouse-pointer' }); } else if (DocListCast(this.Document.links).length) { diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index 8d7ab2f0d..6b2f2246a 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -22,7 +22,7 @@ import { LightboxView } from '../LightboxView'; import { CreateImage } from '../nodes/WebBoxRenderer'; import { PDFViewer } from '../pdf/PDFViewer'; import { SidebarAnnos } from '../SidebarAnnos'; -import { DocFocusOptions, DocumentView } from './DocumentView'; +import { DocFocusOptions, DocumentView, OpenWhere } from './DocumentView'; import { FieldView, FieldViewProps } from './FieldView'; import { ImageBox } from './ImageBox'; import './PDFBox.scss'; @@ -200,6 +200,13 @@ export class PDFBox extends ViewBoxAnnotatableComponent this._pdfViewer?.brushView(view); + sidebarAddDocTab = (doc: Doc, where: OpenWhere) => { + if (DocListCast(this.props.Document[this.props.fieldKey + '-sidebar']).includes(doc) && !this.SidebarShown) { + this.toggleSidebar(false); + return true; + } + return this.props.addDocTab(doc, where); + }; scrollFocus = (docView: DocumentView, anchor: Doc, options: DocFocusOptions) => { let didToggle = false; if (DocListCast(this.props.Document[this.fieldKey + '-sidebar']).includes(anchor) && !this.SidebarShown) { @@ -487,6 +494,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent { + if (DocListCast(this.props.Document[this.props.fieldKey + '-sidebar']).includes(doc) && !this.SidebarShown) { + this.toggleSidebar(false); + return true; + } + return this.props.addDocTab(doc, where); + }; getAnchor = (addAsAnnotation: boolean, pinProps?: PinProps) => { let ele: Opt = undefined; try { diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 123499647..dc7a11e6e 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -230,6 +230,14 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent { + if (DocListCast(this.props.Document[this.props.fieldKey + '-sidebar']).includes(doc) && !this.SidebarShown) { + this.toggleSidebar(false); + return true; + } + return this.props.addDocTab(doc, where); + }; + getAnchor = (addAsAnnotation: boolean, pinProps?: PinProps) => { if (!pinProps) return this.rootDoc; const anchor = Docs.Create.TextanchorDocument({ annotationOn: this.rootDoc, unrendered: true }); diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index 9877690f8..ffc49e4f3 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -16,7 +16,7 @@ import { SnappingManager } from '../../util/SnappingManager'; import { MarqueeOptionsMenu } from '../collections/collectionFreeForm'; import { CollectionFreeFormView } from '../collections/collectionFreeForm/CollectionFreeFormView'; import { MarqueeAnnotator } from '../MarqueeAnnotator'; -import { DocFocusOptions, DocumentViewProps } from '../nodes/DocumentView'; +import { DocFocusOptions, DocumentViewProps, OpenWhere } from '../nodes/DocumentView'; import { FieldViewProps } from '../nodes/FieldView'; import { LinkDocPreview } from '../nodes/LinkDocPreview'; import { StyleProp } from '../StyleProvider'; -- cgit v1.2.3-70-g09d2 From 8aeab8c3f25c556e39f3e9e58f9c321e79459df8 Mon Sep 17 00:00:00 2001 From: bobzel Date: Fri, 17 Mar 2023 12:22:03 -0400 Subject: fixed scriptingbox to remove script if text is empty. fixed scripting with capturedvariables not to cache scripts with lists of captured documents. fixed runtime warnings with stackedTimelined and AudioBox --- src/client/util/Scripting.ts | 8 +++++++- src/client/views/DocumentButtonBar.tsx | 2 +- src/client/views/MainView.tsx | 3 +-- src/client/views/StyleProvider.tsx | 2 +- src/client/views/TemplateMenu.tsx | 1 - .../views/collections/CollectionStackedTimeline.tsx | 2 +- src/client/views/nodes/AudioBox.tsx | 10 +++------- src/client/views/nodes/DocumentView.tsx | 4 ---- src/client/views/nodes/ScriptingBox.tsx | 16 +++++++++------- src/fields/Doc.ts | 9 +-------- 10 files changed, 24 insertions(+), 33 deletions(-) (limited to 'src/client/views/DocumentButtonBar.tsx') diff --git a/src/client/util/Scripting.ts b/src/client/util/Scripting.ts index d32298c83..f17a98616 100644 --- a/src/client/util/Scripting.ts +++ b/src/client/util/Scripting.ts @@ -7,7 +7,9 @@ import * as typescriptlib from '!!raw-loader!./type_decls.d'; import * as ts from 'typescript'; import { Doc, Field } from '../../fields/Doc'; +import { ToScriptString } from '../../fields/FieldSymbols'; import { ObjectField } from '../../fields/ObjectField'; +import { RefField } from '../../fields/RefField'; import { ScriptField } from '../../fields/ScriptField'; import { scriptingGlobals, ScriptingGlobals } from './ScriptingGlobals'; export { ts }; @@ -180,7 +182,11 @@ function forEachNode(node: ts.Node, onEnter: Traverser, onExit?: Traverser, inde export function CompileScript(script: string, options: ScriptOptions = {}): CompileResult { const captured = options.capturedVariables ?? {}; - const signature = Object.keys(captured).reduce((p, v) => p + `${v}=${captured[v] instanceof ObjectField ? 'XXX' : captured[v].toString()}`, ''); + const signature = Object.keys(captured).reduce((p, v) => { + const formatCapture = (obj: any) => `${v}=${obj instanceof RefField ? 'XXX' : obj.toString()}`; + if (captured[v] instanceof Array) return p + (captured[v] as any).map(formatCapture); + return p + formatCapture(captured[v]); + }, ''); const found = ScriptField.GetScriptFieldCache(script + ':' + signature); if (found) return found as CompiledScript; const { requiredType = '', addReturn = false, params = {}, capturedVariables = {}, typecheck = true } = options; diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx index af868ba9c..9389fed01 100644 --- a/src/client/views/DocumentButtonBar.tsx +++ b/src/client/views/DocumentButtonBar.tsx @@ -518,7 +518,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV ) }>
- {} +
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 2e04ca3dd..118635a38 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -10,7 +10,7 @@ import 'normalize.css'; import * as React from 'react'; import { Doc, DocListCast, Opt } from '../../fields/Doc'; import { ScriptField } from '../../fields/ScriptField'; -import { DocCast, StrCast } from '../../fields/Types'; +import { StrCast } from '../../fields/Types'; import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, returnZero, setupMoveUpEvents, Utils } from '../../Utils'; import { GoogleAuthenticationManager } from '../apis/GoogleAuthenticationManager'; import { DocServer } from '../DocServer'; @@ -57,7 +57,6 @@ import { LinkDescriptionPopup } from './nodes/LinkDescriptionPopup'; import { LinkDocPreview } from './nodes/LinkDocPreview'; import { RadialMenu } from './nodes/RadialMenu'; import { TaskCompletionBox } from './nodes/TaskCompletedBox'; -import { PresBox } from './nodes/trails'; import { OverlayView } from './OverlayView'; import { AnchorMenu } from './pdf/AnchorMenu'; import { PreviewCursor } from './PreviewCursor'; diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx index dba5d703f..b11117b11 100644 --- a/src/client/views/StyleProvider.tsx +++ b/src/client/views/StyleProvider.tsx @@ -5,7 +5,7 @@ import { action, runInAction } from 'mobx'; import { extname } from 'path'; import { Doc, Opt } from '../../fields/Doc'; import { BoolCast, Cast, ImageCast, NumCast, StrCast } from '../../fields/Types'; -import { DashColor, emptyFunction, lightOrDark } from '../../Utils'; +import { DashColor, lightOrDark } from '../../Utils'; import { CollectionViewType, DocumentType } from '../documents/DocumentTypes'; import { DocFocusOrOpen } from '../util/DocumentManager'; import { LinkManager } from '../util/LinkManager'; diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx index 863829a51..681ff66e0 100644 --- a/src/client/views/TemplateMenu.tsx +++ b/src/client/views/TemplateMenu.tsx @@ -1,7 +1,6 @@ import { action, computed, observable, ObservableSet, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import { Doc, DocListCast } from '../../fields/Doc'; -import { List } from '../../fields/List'; import { ScriptField } from '../../fields/ScriptField'; import { Cast, StrCast } from '../../fields/Types'; import { TraceMobx } from '../../fields/util'; diff --git a/src/client/views/collections/CollectionStackedTimeline.tsx b/src/client/views/collections/CollectionStackedTimeline.tsx index f9249e7d5..302d4a464 100644 --- a/src/client/views/collections/CollectionStackedTimeline.tsx +++ b/src/client/views/collections/CollectionStackedTimeline.tsx @@ -565,7 +565,7 @@ export class CollectionStackedTimeline extends CollectionSubView Math.max(m, o.level), 0) + 2; - return ( + return this.clipDuration === 0 ? null : (
{ - e.stopPropagation(); - }} - onChange={(e: React.ChangeEvent) => { - this.zoom(Number(e.target.value)); - }} + onPointerDown={(e: React.PointerEvent) => e.stopPropagation()} + onChange={(e: React.ChangeEvent) => this.zoom(Number(e.target.value))} />
)} diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 6ae102a0c..b7a760c1e 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -1489,10 +1489,6 @@ export class DocumentViewInternal extends DocComponent (params[p.split(':')[0].trim()] = p.split(':')[1].trim())); - const result = CompileScript(this.rawText, { - editable: true, - transformer: DocumentIconContainer.getTransformer(), - params, - typecheck: false, - }); - Doc.SetInPlace(this.rootDoc, this.fieldKey, result.compiled ? new ScriptField(result, undefined, this.rawText) : new ScriptField(undefined, undefined, this.rawText), true); + const result = !this.rawText.trim() + ? ({ compiled: false, errors: undefined } as any) + : CompileScript(this.rawText, { + editable: true, + transformer: DocumentIconContainer.getTransformer(), + params, + typecheck: false, + }); + Doc.SetInPlace(this.rootDoc, this.fieldKey, result.compiled ? new ScriptField(result, undefined, this.rawText) : undefined, true); this.onError(result.compiled ? undefined : result.errors); return result.compiled; }; diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index 3169031b4..44314dca2 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -518,20 +518,13 @@ export namespace Doc { } export async function SetInPlace(doc: Doc, key: string, value: Field | undefined, defaultProto: boolean) { if (key.startsWith('_')) key = key.substring(1); - const hasProto = doc.proto instanceof Doc; + const hasProto = Doc.GetProto(doc) !== doc ? Doc.GetProto(doc) : undefined; const onDeleg = Object.getOwnPropertyNames(doc).indexOf(key) !== -1; const onProto = hasProto && Object.getOwnPropertyNames(doc.proto).indexOf(key) !== -1; if (onDeleg || !hasProto || (!onProto && !defaultProto)) { doc[key] = value; } else doc.proto![key] = value; } - export async function SetOnPrototype(doc: Doc, key: string, value: Field) { - const proto = Object.getOwnPropertyNames(doc).indexOf('isPrototype') === -1 ? doc.proto : doc; - - if (proto) { - proto[key] = value; - } - } export function GetAllPrototypes(doc: Doc): Doc[] { const protos: Doc[] = []; let d: Opt = doc; -- cgit v1.2.3-70-g09d2 From e4b76f6c1dee63c49408c48d7b2bc98e62dc813a Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 5 Apr 2023 12:19:01 -0400 Subject: adjusted general context menu items to always appear last. cleaned up makeLink api, --- src/client/documents/Documents.ts | 32 +++++----- src/client/util/DragManager.ts | 1 - src/client/util/LinkFollower.ts | 2 - src/client/views/ContextMenu.tsx | 12 ++-- src/client/views/DocumentButtonBar.tsx | 4 +- src/client/views/MainView.tsx | 1 + src/client/views/SidebarAnnos.tsx | 2 +- .../views/collections/CollectionNoteTakingView.tsx | 2 +- .../views/collections/CollectionStackingView.tsx | 28 ++++----- src/client/views/collections/CollectionSubView.tsx | 2 +- src/client/views/collections/TreeView.tsx | 2 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 26 ++------ .../collections/collectionFreeForm/MarqueeView.tsx | 2 +- src/client/views/nodes/DocumentLinksButton.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 70 +++++++++++++++------- src/client/views/nodes/ImageBox.tsx | 2 +- src/client/views/nodes/PDFBox.tsx | 31 +++++----- src/client/views/nodes/VideoBox.tsx | 6 +- .../views/nodes/formattedText/FormattedTextBox.tsx | 4 +- .../views/nodes/formattedText/RichTextRules.ts | 2 +- src/client/views/search/SearchBox.tsx | 2 +- 21 files changed, 117 insertions(+), 118 deletions(-) (limited to 'src/client/views/DocumentButtonBar.tsx') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 9cb480c4a..5623ca218 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -470,7 +470,7 @@ export namespace Docs { DocumentType.AUDIO, { layout: { view: AudioBox, dataField: defaultDataKey }, - options: { _height: 100, forceReflow: true, nativeDimModifiable: true }, + options: { _height: 100, fitWidth: true, forceReflow: true, nativeDimModifiable: true }, }, ], [ @@ -934,13 +934,13 @@ export namespace Docs { return InstanceFromProto(Prototypes.get(DocumentType.RTF), field, options, undefined, fieldKey); } - export function LinkDocument(source: { doc: Doc; ctx?: Doc }, target: { doc: Doc; ctx?: Doc }, options: DocumentOptions = {}, id?: string) { + export function LinkDocument(source: Doc, target: Doc, options: DocumentOptions = {}, id?: string) { const linkDoc = InstanceFromProto( Prototypes.get(DocumentType.LINK), undefined, { - anchor1: source.doc, - anchor2: target.doc, + anchor1: source, + anchor2: target, ...options, }, id @@ -1294,16 +1294,14 @@ export namespace DocUtils { broadcastEvent && runInAction(() => (DocumentManager.Instance.RecordingEvent = DocumentManager.Instance.RecordingEvent + 1)); return DocUtils.ActiveRecordings.map(audio => { const sourceDoc = getSourceDoc(); - const link = sourceDoc && DocUtils.MakeLink({ doc: sourceDoc }, { doc: audio.getAnchor(true) || audio.props.Document }, 'recording annotation:linked recording', 'recording timeline'); - link && (link.followLinkLocation = OpenWhere.addRight); - return link; + return sourceDoc && DocUtils.MakeLink(sourceDoc, audio.getAnchor(true) || audio.props.Document, { linkDisplay: false, linkRelationship: 'recording annotation:linked recording', description: 'recording timeline' }); }); } - export function MakeLink(source: { doc: Doc }, target: { doc: Doc }, linkRelationship: string = '', description: string = '', id?: string, allowParCollectionLink?: boolean, showPopup?: number[]) { - if (!linkRelationship) linkRelationship = target.doc.type === DocumentType.RTF ? 'Commentary:Comments On' : 'link'; - const sv = DocumentManager.Instance.getDocumentView(source.doc); - if (!allowParCollectionLink && sv?.props.ContainingCollectionDoc === target.doc) return; + export function MakeLink(source: Doc, target: Doc, linkSettings: { linkRelationship?: string; description?: string; linkDisplay?: boolean }, id?: string, allowParCollectionLink?: boolean, showPopup?: number[]) { + if (!linkSettings.linkRelationship) linkSettings.linkRelationship = target.type === DocumentType.RTF ? 'Commentary:Comments On' : 'link'; + const sv = DocumentManager.Instance.getDocumentView(source); + if (!allowParCollectionLink && sv?.props.ContainingCollectionDoc === target) return; if (target.doc === Doc.UserDoc()) return undefined; const makeLink = action((linkDoc: Doc, showPopup?: number[]) => { @@ -1343,16 +1341,16 @@ export namespace DocUtils { target, { title: ComputedField.MakeFunction('generateLinkTitle(self)') as any, - 'anchor1-useLinkSmallAnchor': source.doc.useLinkSmallAnchor ? true : undefined, - 'anchor2-useLinkSmallAnchor': target.doc.useLinkSmallAnchor ? true : undefined, + 'anchor1-useLinkSmallAnchor': source.useLinkSmallAnchor ? true : undefined, + 'anchor2-useLinkSmallAnchor': target.useLinkSmallAnchor ? true : undefined, 'acl-Public': SharingPermissions.Augment, '_acl-Public': SharingPermissions.Augment, - linkDisplay: true, + linkDisplay: linkSettings.linkDisplay, _linkAutoMove: true, - linkRelationship, + linkRelationship: linkSettings.linkRelationship, _showCaption: 'description', _showTitle: 'linkRelationship', - description, + description: linkSettings.description, }, id ), @@ -1700,7 +1698,7 @@ export namespace DocUtils { _timecodeToShow: Cast(doc._timecodeToShow, 'number', null), }); Doc.AddDocToList(context, annotationField, pushpin); - const pushpinLink = DocUtils.MakeLink({ doc: pushpin }, { doc: doc }, 'pushpin', ''); + const pushpinLink = DocUtils.MakeLink(pushpin, doc, { linkRelationship: 'pushpin' }, ''); doc._timecodeToShow = undefined; return pushpin; } diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index cc116fb46..7d2aa813f 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -168,7 +168,6 @@ export namespace DragManager { this.dropDocCreator = dropDocCreator; this.offset = [0, 0]; } - linkSourceDoc?: Doc; dropDocCreator: (annotationOn: Doc | undefined) => Doc; dropDocument?: Doc; offset: number[]; diff --git a/src/client/util/LinkFollower.ts b/src/client/util/LinkFollower.ts index 785018990..df61ecece 100644 --- a/src/client/util/LinkFollower.ts +++ b/src/client/util/LinkFollower.ts @@ -9,8 +9,6 @@ import { DocumentManager } from './DocumentManager'; import { LinkManager } from './LinkManager'; import { SelectionManager } from './SelectionManager'; import { UndoManager } from './UndoManager'; - -type CreateViewFunc = (doc: Doc, followLinkLocation: string, finished?: () => void) => void; /* * link doc: * - anchor1: doc diff --git a/src/client/views/ContextMenu.tsx b/src/client/views/ContextMenu.tsx index 6a530e3ae..e4c3e864b 100644 --- a/src/client/views/ContextMenu.tsx +++ b/src/client/views/ContextMenu.tsx @@ -102,13 +102,11 @@ export class ContextMenu extends React.Component { } } @action - moveAfter(item: ContextMenuProps, after: ContextMenuProps) { - if (after && this.findByDescription(after.description)) { - const curInd = this._items.findIndex(i => i.description === item.description); - this._items.splice(curInd, 1); - const afterInd = this._items.findIndex(i => i.description === after.description); - this._items.splice(afterInd + 1, 0, item); - } + moveAfter(item: ContextMenuProps, after?: ContextMenuProps) { + const curInd = this._items.findIndex(i => i.description === item.description); + this._items.splice(curInd, 1); + const afterInd = after && this.findByDescription(after.description) ? this._items.findIndex(i => i.description === after.description) : this._items.length; + this._items.splice(afterInd, 0, item); } @action setDefaultItem(prefix: string, item: (name: string) => void) { diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx index 9389fed01..3e1a0f265 100644 --- a/src/client/views/DocumentButtonBar.tsx +++ b/src/client/views/DocumentButtonBar.tsx @@ -416,7 +416,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV const targetDoc = this.view0?.props.Document; return !targetDoc ? null : ( {`Open Context Menu`}
}> -
this.openContextMenu(e)}> +
@@ -569,7 +569,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV const anchor = rootView.ComponentView?.getAnchor?.(false) ?? rootDoc; const trail = DocCast(anchor.presTrail) ?? Doc.MakeCopy(DocCast(Doc.UserDoc().emptyTrail), true); if (trail !== anchor.presTrail) { - DocUtils.MakeLink({ doc: anchor }, { doc: trail }, 'link trail'); + DocUtils.MakeLink(anchor, trail, { linkRelationship: 'link trail' }); anchor.presTrail = trail; } Doc.ActivePresentation = trail; diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index befb0200d..b0888df68 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -270,6 +270,7 @@ export class MainView extends React.Component { fa.faLaptopCode, fa.faMale, fa.faCopy, + fa.faHome, fa.faHandPointLeft, fa.faHandPointRight, fa.faCompass, diff --git a/src/client/views/SidebarAnnos.tsx b/src/client/views/SidebarAnnos.tsx index 48c0150e6..2d2b0f83e 100644 --- a/src/client/views/SidebarAnnos.tsx +++ b/src/client/views/SidebarAnnos.tsx @@ -74,7 +74,7 @@ export class SidebarAnnos extends React.Component { }); FormattedTextBox.SelectOnLoad = target[Id]; FormattedTextBox.DontSelectInitialText = true; - const link = DocUtils.MakeLink({ doc: anchor }, { doc: target }, 'inline comment:comment on'); + const link = DocUtils.MakeLink(anchor, target, { linkRelationship: 'inline comment:comment on' }); link && (link.linkDisplay = false); const taggedContent = this.docFilters() diff --git a/src/client/views/collections/CollectionNoteTakingView.tsx b/src/client/views/collections/CollectionNoteTakingView.tsx index 121260680..cb5be990d 100644 --- a/src/client/views/collections/CollectionNoteTakingView.tsx +++ b/src/client/views/collections/CollectionNoteTakingView.tsx @@ -441,7 +441,7 @@ export class CollectionNoteTakingView extends CollectionSubView() { } else if (de.complete.linkDragData?.dragDocument.context === this.props.Document && de.complete.linkDragData?.linkDragView?.props.CollectionFreeFormDocumentView?.()) { const source = Docs.Create.TextDocument('', { _width: 200, _height: 75, _fitWidth: true, title: 'dropped annotation' }); this.props.addDocument?.(source); - de.complete.linkDocument = DocUtils.MakeLink({ doc: source }, { doc: de.complete.linkDragData.linkSourceGetAnchor() }, 'doc annotation', ''); // TODODO this is where in text links get passed + de.complete.linkDocument = DocUtils.MakeLink(source, de.complete.linkDragData.linkSourceGetAnchor(), { linkRelationship: 'doc annotation' }); // TODODO this is where in text links get passed e.stopPropagation(); } else if (de.complete.annoDragData?.dragDocument && super.onInternalDrop(e, de)) return this.internalAnchorAnnoDrop(e, de.complete.annoDragData); return false; diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 64ec419ec..1e02fc9d4 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -3,14 +3,14 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { CursorProperty } from 'csstype'; import { action, computed, IReactionDisposer, observable, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; -import { DataSym, Doc, DocListCast, HeightSym, Opt, WidthSym } from '../../../fields/Doc'; +import { DataSym, Doc, HeightSym, Opt, WidthSym } from '../../../fields/Doc'; import { Id } from '../../../fields/FieldSymbols'; import { List } from '../../../fields/List'; import { listSpec } from '../../../fields/Schema'; import { SchemaHeaderField } from '../../../fields/SchemaHeaderField'; -import { BoolCast, Cast, DocCast, NumCast, ScriptCast, StrCast } from '../../../fields/Types'; +import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../fields/Types'; import { TraceMobx } from '../../../fields/util'; -import { emptyFunction, returnEmptyDoclist, returnFalse, returnTrue, returnZero, setupMoveUpEvents, smoothScroll, Utils } from '../../../Utils'; +import { emptyFunction, returnEmptyDoclist, returnFalse, returnZero, setupMoveUpEvents, smoothScroll, Utils } from '../../../Utils'; import { Docs, DocUtils } from '../../documents/Documents'; import { CollectionViewType } from '../../documents/DocumentTypes'; import { DragManager, dropActionType } from '../../util/DragManager'; @@ -460,7 +460,7 @@ export class CollectionStackingView extends CollectionSubView { // need to test if propagation has stopped because GoldenLayout forces a parallel react hierarchy to be created for its top-level layout if (!e.isPropagationStopped()) { - const subItems: ContextMenuProps[] = []; - subItems.push({ description: `${this.layoutDoc._columnsFill ? 'Variable Size' : 'Autosize'} Column`, event: () => (this.layoutDoc._columnsFill = !this.layoutDoc._columnsFill), icon: 'plus' }); - subItems.push({ description: `${this.layoutDoc._autoHeight ? 'Variable Height' : 'Auto Height'}`, event: () => (this.layoutDoc._autoHeight = !this.layoutDoc._autoHeight), icon: 'plus' }); - subItems.push({ description: 'Clear All', event: () => (this.dataDoc.data = new List([])), icon: 'times' }); - ContextMenu.Instance.addItem({ description: 'Options...', subitems: subItems, icon: 'eye' }); + const cm = ContextMenu.Instance; + const options = cm.findByDescription('Options...'); + const optionItems: ContextMenuProps[] = options && 'subitems' in options ? options.subitems : []; + optionItems.push({ description: `${this.layoutDoc._columnsFill ? 'Variable Size' : 'Autosize'} Column`, event: () => (this.layoutDoc._columnsFill = !this.layoutDoc._columnsFill), icon: 'plus' }); + optionItems.push({ description: `${this.layoutDoc._autoHeight ? 'Variable Height' : 'Auto Height'}`, event: () => (this.layoutDoc._autoHeight = !this.layoutDoc._autoHeight), icon: 'plus' }); + optionItems.push({ description: 'Clear All', event: () => (this.dataDoc[this.fieldKey ?? 'data'] = new List([])), icon: 'times' }); + !options && cm.addItem({ description: 'Options...', subitems: optionItems, icon: 'compass' }); } }; @@ -735,14 +737,6 @@ export class CollectionStackingView extends CollectionSubView
)} - {/* {this.chromeHidden || !this.props.isSelected() ? (null) : - } */}
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 5100d8d67..132ed6fb6 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -335,7 +335,7 @@ export function CollectionSubView(moreProps?: X) { const focusNode = iframe?.contentDocument?.getSelection()?.focusNode as any; if (focusNode) { const anchor = srcWeb?.ComponentView?.getAnchor?.(true); - anchor && DocUtils.MakeLink({ doc: htmlDoc }, { doc: anchor }); + anchor && DocUtils.MakeLink(htmlDoc, anchor, {}); } } } diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index 99b7549c0..75e76019e 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -359,7 +359,7 @@ export class TreeView extends React.Component { if (de.complete.linkDragData) { const sourceDoc = de.complete.linkDragData.linkSourceGetAnchor(); const destDoc = this.doc; - DocUtils.MakeLink({ doc: sourceDoc }, { doc: destDoc }, 'tree link', ''); + DocUtils.MakeLink(sourceDoc, destDoc, { linkRelationship: 'tree link' }); e.stopPropagation(); } const docDragData = de.complete.docDragData; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index d39668a5d..fb0bd2a19 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -397,7 +397,7 @@ export class CollectionFreeFormView extends CollectionSubView (Doc.UserDoc().defaultTextLayout = undefined), icon: 'eye' }); appearanceItems.push({ description: `${this.fitContentsToBox ? 'Make Zoomable' : 'Scale to Window'}`, @@ -1700,7 +1704,7 @@ export class CollectionFreeFormView extends CollectionSubView TabDocView.PinDoc(this.rootDoc, { pinViewport: MarqueeView.CurViewBounds(this.rootDoc, this.props.PanelWidth(), this.props.PanelHeight()) }), icon: 'map-pin' }); - //appearanceItems.push({ description: `update icon`, event: this.updateIcon, icon: "compress-arrows-alt" }); + !Doc.noviceMode && appearanceItems.push({ description: `update icon`, event: this.updateIcon, icon: 'compress-arrows-alt' }); appearanceItems.push({ description: 'Ungroup collection', event: this.promoteCollection, icon: 'table' }); this.props.Document._isGroup && this.Document.transcription && appearanceItems.push({ description: 'Ink to text', event: () => this.transcribeStrokes(false), icon: 'font' }); @@ -1730,27 +1734,9 @@ export class CollectionFreeFormView extends CollectionSubView this.importDocument(e.clientX, e.clientY) }); !mores && ContextMenu.Instance.addItem({ description: 'More...', subitems: moreItems, icon: 'eye' }); }; - importDocument = (x: number, y: number) => { - const input = document.createElement('input'); - input.type = 'file'; - input.accept = '.zip'; - input.onchange = _e => { - input.files && - Doc.importDocument(input.files[0]).then(doc => { - if (doc instanceof Doc) { - const [xx, yy] = this.getTransform().transformPoint(x, y); - (doc.x = xx), (doc.y = yy); - this.props.addDocument?.(doc); - } - }); - }; - input.click(); - }; - @undoBatch @action transcribeStrokes = (math: boolean) => { diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 043fe0bcf..0b4f76fa1 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -527,7 +527,7 @@ export class MarqueeView extends React.Component { + drop = (e: Event, de: DragManager.DropEvent) => { if (this.props.dontRegisterView || this.props.LayoutTemplateString?.includes(LinkAnchorBox.name)) return; if (this.props.Document === Doc.ActiveDashboard) { alert((e.target as any)?.closest?.('*.lm_content') ? "You can't perform this move most likely because you don't have permission to modify the destination." : 'Linking to document tabs not yet supported. Drop link on document content.'); return; } const linkdrag = de.complete.annoDragData ?? de.complete.linkDragData; - if (linkdrag) linkdrag.linkSourceDoc = linkdrag.linkSourceGetAnchor(); - if (linkdrag?.linkSourceDoc) { - e.stopPropagation(); - if (de.complete.annoDragData && !de.complete.annoDragData.dropDocument) { - de.complete.annoDragData.dropDocument = de.complete.annoDragData.dropDocCreator(undefined); - } - if (de.complete.annoDragData || this.rootDoc !== linkdrag.linkSourceDoc.context) { - const dropDoc = de.complete.annoDragData?.dropDocument ?? this._componentView?.getAnchor?.(true) ?? this.props.Document; - de.complete.linkDocument = DocUtils.MakeLink({ doc: linkdrag.linkSourceDoc }, { doc: dropDoc }, undefined, undefined, undefined, undefined, [de.x, de.y - 50]); + if (linkdrag) { + linkdrag.linkSourceDoc = linkdrag.linkSourceGetAnchor(); + if (linkdrag.linkSourceDoc) { + e.stopPropagation(); + if (de.complete.annoDragData && !de.complete.annoDragData.dropDocument) { + de.complete.annoDragData.dropDocument = de.complete.annoDragData.dropDocCreator(undefined); + } + if (de.complete.annoDragData || this.rootDoc !== linkdrag.linkSourceDoc.context) { + const dropDoc = de.complete.annoDragData?.dropDocument ?? this._componentView?.getAnchor?.(true) ?? this.rootDoc; + de.complete.linkDocument = DocUtils.MakeLink(linkdrag.linkSourceDoc, dropDoc, {}, undefined, undefined, [de.x, de.y - 50]); + } } } }; @@ -643,9 +645,9 @@ export class DocumentViewInternal extends DocComponent d.anchor1 === this.props.Document && d.linkRelationship === 'portal to:portal from'); if (!portalLink) { DocUtils.MakeLink( - { doc: this.props.Document }, - { doc: Docs.Create.FreeformDocument([], { _width: NumCast(this.layoutDoc._width) + 10, _height: NumCast(this.layoutDoc._height), _isLightbox: true, _fitWidth: true, title: StrCast(this.props.Document.title) + ' [Portal]' }) }, - 'portal to:portal from' + this.props.Document, + Docs.Create.FreeformDocument([], { _width: NumCast(this.layoutDoc._width) + 10, _height: NumCast(this.layoutDoc._height), _isLightbox: true, _fitWidth: true, title: StrCast(this.props.Document.title) + ' [Portal]' }), + { linkRelationship: 'portal to:portal from' } ); } this.Document.followLinkLocation = OpenWhere.lightbox; @@ -653,6 +655,24 @@ export class DocumentViewInternal extends DocComponent { + const input = document.createElement('input'); + input.type = 'file'; + input.accept = '.zip'; + input.onchange = _e => { + if (input.files) { + const batch = UndoManager.StartBatch('importing'); + Doc.importDocument(input.files[0]).then(doc => { + if (doc instanceof Doc) { + this.props.addDocTab(doc, OpenWhere.addRight); + batch.end(); + } + }); + } + }; + input.click(); + }; + @action onContextMenu = (e?: React.MouseEvent, pageX?: number, pageY?: number) => { if (e && this.rootDoc._hideContextMenu && Doc.noviceMode) { @@ -704,9 +724,7 @@ export class DocumentViewInternal extends DocComponent this.props.addDocTab(templateDoc, OpenWhere.addRight), icon: 'eye' }); - LinkManager.Links(this.Document).length && - appearanceItems.splice(0, 0, { description: `${this.layoutDoc.hideLinkButton ? 'Show' : 'Hide'} Link Button`, event: action(() => (this.layoutDoc.hideLinkButton = !this.layoutDoc.hideLinkButton)), icon: 'eye' }); - !appearance && cm.addItem({ description: 'UI Controls...', subitems: appearanceItems, icon: 'compass' }); + !appearance && appearanceItems.length && cm.addItem({ description: 'UI Controls...', subitems: appearanceItems, icon: 'compass' }); if (!Doc.IsSystem(this.rootDoc) && this.rootDoc._viewType !== CollectionViewType.Docking && this.props.ContainingCollectionDoc?._viewType !== CollectionViewType.Tree) { const existingOnClick = cm.findByDescription('OnClick...'); @@ -774,16 +792,21 @@ export class DocumentViewInternal extends DocComponent Utils.CopyText(Doc.globalServerPath(this.props.Document)), icon: 'fingerprint' }); } - moreItems.push({ description: 'Export collection', icon: 'download', event: async () => Doc.Zip(this.props.Document) }); - - (this.rootDoc._viewType !== CollectionViewType.Docking || !Doc.noviceMode) && moreItems.push({ description: 'Share', event: () => SharingManager.Instance.open(this.props.DocumentView()), icon: 'users' }); } - if (this.props.removeDocument && !Doc.IsSystem(this.rootDoc) && Doc.ActiveDashboard !== this.props.Document) { + !more && moreItems.length && cm.addItem({ description: 'More...', subitems: moreItems, icon: 'compass' }); + } + const constantItems: ContextMenuProps[] = []; + + if (!Doc.IsSystem(this.rootDoc)) { + constantItems.push({ description: 'Export as Zip file', icon: 'download', event: async () => Doc.Zip(this.props.Document) }); + constantItems.push({ description: 'Import Zipped file', icon: 'upload', event: ({ x, y }) => this.importDocument() }); + (this.rootDoc._viewType !== CollectionViewType.Docking || !Doc.noviceMode) && constantItems.push({ description: 'Share', event: () => SharingManager.Instance.open(this.props.DocumentView()), icon: 'users' }); + if (this.props.removeDocument && Doc.ActiveDashboard !== this.props.Document) { // need option to gray out menu items ... preferably with a '?' that explains why they're grayed out (eg., no permissions) - moreItems.push({ description: 'Close', event: this.deleteClicked, icon: 'times' }); + constantItems.push({ description: 'Close', event: this.deleteClicked, icon: 'times' }); } - !more && moreItems.length && cm.addItem({ description: 'More...', subitems: moreItems, icon: 'compass' }); + cm.addItem({ description: 'General...', noexpand: false, subitems: constantItems, icon: 'question' }); } const help = cm.findByDescription('Help...'); const helpItems: ContextMenuProps[] = help && 'subitems' in help ? help.subitems : []; @@ -834,7 +857,8 @@ export class DocumentViewInternal extends DocComponent !isClick && batch.end(), () => { - this.toggleSidebar(); + onButton && this.toggleSidebar(); batch.end(); } ); @@ -440,17 +440,20 @@ export class PDFBox extends ViewBoxAnnotatableComponent (this.rootDoc.sidebarViewType = this.rootDoc.sidebarViewType === CollectionViewType.Freeform ? CollectionViewType.Stacking : CollectionViewType.Freeform); specificContextMenu = (e: React.MouseEvent): void => { - const funcs: ContextMenuProps[] = []; - funcs.push({ - description: 'Toggle Sidebar Type', - event: () => (this.rootDoc.sidebarViewType = this.rootDoc.sidebarViewType === CollectionViewType.Freeform ? CollectionViewType.Stacking : CollectionViewType.Freeform), - icon: 'expand-arrows-alt', - }); - funcs.push({ description: 'Copy path', event: () => this.pdfUrl && Utils.CopyText(Utils.prepend('') + this.pdfUrl.url.pathname), icon: 'expand-arrows-alt' }); - funcs.push({ description: 'update icon', event: () => this.pdfUrl && this.updateIcon(), icon: 'expand-arrows-alt' }); - //funcs.push({ description: "Toggle Sidebar ", event: () => this.toggleSidebar(), icon: "expand-arrows-alt" }); - ContextMenu.Instance.addItem({ description: 'Options...', subitems: funcs, icon: 'asterisk' }); + const cm = ContextMenu.Instance; + const options = cm.findByDescription('Options...'); + const optionItems: ContextMenuProps[] = options && 'subitems' in options ? options.subitems : []; + optionItems.push({ description: 'Toggle Sidebar Type', event: this.toggleSidebarType, icon: 'expand-arrows-alt' }); + !Doc.noviceMode && optionItems.push({ description: 'update icon', event: () => this.pdfUrl && this.updateIcon(), icon: 'expand-arrows-alt' }); + //optionItems.push({ description: "Toggle Sidebar ", event: () => this.toggleSidebar(), icon: "expand-arrows-alt" }); + !options && ContextMenu.Instance.addItem({ description: 'Options...', subitems: optionItems, icon: 'asterisk' }); + const help = cm.findByDescription('Help...'); + const helpItems: ContextMenuProps[] = help && 'subitems' in help ? help.subitems : []; + helpItems.push({ description: 'Copy path', event: () => this.pdfUrl && Utils.CopyText(Utils.prepend('') + this.pdfUrl.url.pathname), icon: 'expand-arrows-alt' }); + !help && ContextMenu.Instance.addItem({ description: 'Help...', noexpand: true, subitems: helpItems, icon: 'asterisk' }); }; @computed get renderTitleBox() { @@ -523,8 +526,6 @@ export class PDFBox extends ViewBoxAnnotatableComponent ) : (
setupMoveUpEvents(this, e, returnFalse, emptyFunction, () => SelectionManager.SelectView(this.props.DocumentView?.()!, false), true)}> @@ -568,7 +569,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent downX !== undefined && downY !== undefined && DocumentManager.Instance.getFirstDocumentView(imageSnapshot)?.startDragging(downX, downY, 'move', true)); }; @@ -1031,7 +1031,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent Doc.AreProtosEqual(Cast(link.anchor1, Doc, null), this.rootDoc) && Doc.AreProtosEqual(Cast(link.anchor2, Doc, null), target)) || - DocUtils.MakeLink({ doc: this.props.Document }, { doc: target }, LinkManager.AutoKeywords)!); + DocUtils.MakeLink(this.props.Document, target, { linkRelationship: LinkManager.AutoKeywords })!); newAutoLinks.add(alink); const allAnchors = [{ href: Doc.localServerPath(target), title: 'a link', anchorId: this.props.Document[Id] }]; allAnchors.push(...(node.marks.find((m: Mark) => m.type.name === schema.marks.autoLinkAnchor.name)?.attrs.allAnchors ?? [])); @@ -1273,7 +1273,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent() { makeLink = action((linkTo: Doc) => { const linkFrom = this.props.linkCreateAnchor?.(); if (linkFrom) { - const link = DocUtils.MakeLink({ doc: linkFrom }, { doc: linkTo }); + const link = DocUtils.MakeLink(linkFrom, linkTo, {}); link && this.props.linkCreated?.(link); } }); -- cgit v1.2.3-70-g09d2 From 38eb3a1b3f005b79a222f76b730e883b7e2b5253 Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 5 Apr 2023 14:36:37 -0400 Subject: made pinning from topbar available for all docs. --- src/client/util/CurrentUserUtils.ts | 8 +++---- src/client/views/DocumentButtonBar.tsx | 25 +++++++++++----------- .../collectionFreeForm/CollectionFreeFormView.tsx | 16 +++++++++----- src/client/views/nodes/trails/PresBox.tsx | 1 - src/client/views/nodes/trails/PresElementBox.tsx | 2 +- 5 files changed, 28 insertions(+), 24 deletions(-) (limited to 'src/client/views/DocumentButtonBar.tsx') diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 753cd1cb7..9571209b0 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -682,9 +682,9 @@ export class CurrentUserUtils { CollectionViewType.Carousel3D, CollectionViewType.Linear, CollectionViewType.Map, CollectionViewType.Grid, CollectionViewType.NoteTaking]), title: "Perspective", toolTip: "View", btnType: ButtonType.DropdownList, ignoreClick: true, width: 100, scripts: { script: 'setView(value, _readOnly_)'}}, - { title: "Pin", icon: "map-pin", toolTip: "Pin View to Trail", btnType: ButtonType.ClickButton, expertMode: false, toolType:"tab", funcs: {hidden: `!SelectionManager_selectedDocType(self.toolType, self.expertMode)`}, width: 20, scripts: { onClick: 'pinWithView(_readOnly_, altKey)'}}, - { title: "Fill", icon: "fill-drip", toolTip: "Background Fill Color",btnType: ButtonType.ColorButton, expertMode: false, toolType:"tab", ignoreClick: true, width: 20, scripts: { script: 'return setBackgroundColor(value, _readOnly_)'}}, // Only when a document is selected - { title: "Header", icon: "heading", toolTip: "Header Color", btnType: ButtonType.ColorButton, expertMode: false, toolType:"tab", ignoreClick: true, scripts: { script: 'return setHeaderColor(value, _readOnly_)'}}, + { title: "Pin", icon: "map-pin", toolTip: "Pin View to Trail", btnType: ButtonType.ClickButton, expertMode: false, width: 20, scripts: { onClick: 'pinWithView(altKey)'}}, + { title: "Fill", icon: "fill-drip", toolTip: "Background Fill Color",btnType: ButtonType.ColorButton, expertMode: false, ignoreClick: true, width: 20, scripts: { script: 'return setBackgroundColor(value, _readOnly_)'}}, // Only when a document is selected + { title: "Header", icon: "heading", toolTip: "Header Color", btnType: ButtonType.ColorButton, expertMode: false, ignoreClick: true, scripts: { script: 'return setHeaderColor(value, _readOnly_)'}}, { title: "Overlay", icon: "layer-group", toolTip: "Overlay", btnType: ButtonType.ToggleButton, expertMode: false, toolType:CollectionViewType.Freeform, funcs: {hidden: '!SelectionManager_selectedDocType(self.toolType, self.expertMode, true)'}, scripts: { onClick: 'toggleOverlay(_readOnly_)'}}, // Only when floating document is selected in freeform { title: "Z order", icon: "z", toolTip: "Bring Forward on Drag",btnType: ButtonType.ToggleButton, expertMode: false, toolType:CollectionViewType.Freeform, funcs: {}, scripts: { onClick: 'toggleRaiseOnDrag(_readOnly_)'}}, // Only when floating document is selected in freeform { title: "Back", icon: "chevron-left", toolTip: "Prev Animation Frame", btnType: ButtonType.ClickButton, expertMode: true, toolType:CollectionViewType.Freeform, funcs: {hidden: '!SelectionManager_selectedDocType(self.toolType, self.expertMode)'}, width: 20, scripts: { onClick: 'prevKeyFrame(_readOnly_)'}}, @@ -693,7 +693,7 @@ export class CurrentUserUtils { { title: "Text", icon: "Text", toolTip: "Text functions", subMenu: CurrentUserUtils.textTools(), expertMode: false, toolType:DocumentType.RTF, funcs: { linearViewIsExpanded: `SelectionManager_selectedDocType(self.toolType, self.expertMode)`} }, // Always available { title: "Ink", icon: "Ink", toolTip: "Ink functions", subMenu: CurrentUserUtils.inkTools(), expertMode: false, toolType:DocumentType.INK, funcs: { linearViewIsExpanded: `SelectionManager_selectedDocType(self.toolType, self.expertMode)`}, scripts: { onClick: 'setInkToolDefaults()'} }, // Always available { title: "Doc", icon: "Doc", toolTip: "Freeform Doc tools", subMenu: CurrentUserUtils.freeTools(), expertMode: false, toolType:CollectionViewType.Freeform, funcs: {hidden: `!SelectionManager_selectedDocType(self.toolType, self.expertMode, true)`, linearViewIsExpanded: `SelectionManager_selectedDocType(self.toolType, self.expertMode)`} }, // Always available - { title: "View", icon: "View", toolTip: "View tools", subMenu: CurrentUserUtils.viewTools(),expertMode: false, toolType:CollectionViewType.Freeform, funcs: {hidden: `!SelectionManager_selectedDocType(self.toolType, self.expertMode)`, linearViewIsExpanded: `SelectionManager_selectedDocType(self.toolType, self.expertMode)`} }, // Always available + { title: "View", icon: "View", toolTip: "View tools", subMenu: CurrentUserUtils.viewTools(), expertMode: false, toolType:CollectionViewType.Freeform, funcs: {hidden: `!SelectionManager_selectedDocType(self.toolType, self.expertMode)`, linearViewIsExpanded: `SelectionManager_selectedDocType(self.toolType, self.expertMode)`} }, // Always available { title: "Web", icon: "Web", toolTip: "Web functions", subMenu: CurrentUserUtils.webTools(), expertMode: false, toolType:DocumentType.WEB, funcs: {hidden: `!SelectionManager_selectedDocType(self.toolType, self.expertMode)`, linearViewIsExpanded: `SelectionManager_selectedDocType(self.toolType, self.expertMode)`} }, // Only when Web is selected { title: "Schema", icon: "Schema", toolTip: "Schema functions", subMenu: CurrentUserUtils.schemaTools(), expertMode: false, toolType:CollectionViewType.Schema, funcs: {hidden: `!SelectionManager_selectedDocType(self.toolType, self.expertMode)`, linearViewIsExpanded: `SelectionManager_selectedDocType(self.toolType, self.expertMode)`} } // Only when Schema is selected ]; diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx index 3e1a0f265..e83ea00cf 100644 --- a/src/client/views/DocumentButtonBar.tsx +++ b/src/client/views/DocumentButtonBar.tsx @@ -289,7 +289,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV @observable subEndLink = ''; @computed get endLinkButton() { - const linkBtn = (pinDocLayout: boolean, pinDocContent: boolean, icon: IconProp) => { + const linkBtn = (pinLayout: boolean, pinContent: boolean, icon: IconProp) => { const tooltip = `Finish Link and Save ${this.subEndLink} data`; return !this.view0 ? null : ( {tooltip}
}> @@ -300,7 +300,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV key={icon.toString()} size="sm" icon={icon} - onPointerEnter={action(e => (this.subEndLink = (pinDocLayout ? 'Layout' : '') + (pinDocLayout && pinDocContent ? ' &' : '') + (pinDocContent ? ' Content' : '')))} + onPointerEnter={action(e => (this.subEndLink = (pinLayout ? 'Layout' : '') + (pinLayout && pinContent ? ' &' : '') + (pinContent ? ' Content' : '')))} onPointerLeave={action(e => (this.subEndLink = ''))} onClick={e => { const docs = this.props @@ -309,9 +309,8 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV .map(dv => dv!.rootDoc); this.view0 && DocumentLinksButton.finishLinkClick(e.clientX, e.clientY, DocumentLinksButton.StartLink, this.view0.props.Document, true, this.view0, { - pinDocLayout, - pinDocContent, - pinData: !pinDocContent ? {} : { poslayoutview: true, dataannos: true, dataview: true }, + pinDocLayout: pinLayout, + pinData: !pinContent ? {} : { poslayoutview: true, dataannos: true, dataview: pinContent }, } as PinProps); e.stopPropagation(); @@ -337,7 +336,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV @computed get pinButton() { const targetDoc = this.view0?.props.Document; - const pinBtn = (pinDocLayout: boolean, pinDocContent: boolean, icon: IconProp) => { + const pinBtn = (pinLayoutView: boolean, pinContentView: boolean, icon: IconProp) => { const tooltip = `Pin Document and Save ${this.subPin} to trail`; return !tooltip ? null : ( {tooltip}
}> @@ -351,10 +350,10 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV onPointerEnter={action( e => (this.subPin = - (pinDocLayout ? 'Layout' : '') + - (pinDocLayout && pinDocContent ? ' &' : '') + - (pinDocContent ? ' Content View' : '') + - (pinDocLayout && pinDocContent ? '(shift+alt)' : pinDocLayout ? '(shift)' : pinDocContent ? '(alt)' : '')) + (pinLayoutView ? 'Layout' : '') + + (pinLayoutView && pinContentView ? ' &' : '') + + (pinContentView ? ' Content View' : '') + + (pinLayoutView && pinContentView ? '(shift+alt)' : pinLayoutView ? '(shift)' : pinContentView ? '(alt)' : '')) )} onPointerLeave={action(e => (this.subPin = ''))} onClick={e => { @@ -364,8 +363,8 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV .map(dv => dv!.rootDoc); TabDocView.PinDoc(docs, { pinAudioPlay: true, - pinDocLayout, - pinData: { dataview: true }, + pinDocLayout: pinLayoutView, + pinData: { dataview: pinContentView }, activeFrame: Cast(docs.lastElement()?.activeFrame, 'number', null), currentFrame: Cast(docs.lastElement()?.currentFrame, 'number', null), }); @@ -385,7 +384,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV .views() .filter(v => v) .map(dv => dv!.rootDoc); - TabDocView.PinDoc(docs, { pinAudioPlay: true, pinDocLayout: e.shiftKey, pinDocContent: e.altKey, activeFrame: Cast(docs.lastElement()?.activeFrame, 'number', null) }); + TabDocView.PinDoc(docs, { pinAudioPlay: true, pinDocLayout: e.shiftKey, pinData: {dataview: e.altKey}, activeFrame: Cast(docs.lastElement()?.activeFrame, 'number', null) }); e.stopPropagation(); }}>
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index fb0bd2a19..22a2a429f 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -2196,11 +2196,17 @@ ScriptingGlobals.add(function curKeyFrame(readOnly: boolean) { if (readOnly) return selView[0].ComponentView?.getKeyFrameEditing?.() ? Colors.MEDIUM_BLUE : 'transparent'; runInAction(() => selView[0].ComponentView?.setKeyFrameEditing?.(!selView[0].ComponentView?.getKeyFrameEditing?.())); }); -ScriptingGlobals.add(function pinWithView(readOnly: boolean, pinDocContent: boolean) { - !readOnly && - SelectionManager.Views().forEach(view => - TabDocView.PinDoc(view.rootDoc, { currentFrame: Cast(view.rootDoc.currentFrame, 'number', null), pinDocContent, pinViewport: MarqueeView.CurViewBounds(view.rootDoc, view.props.PanelWidth(), view.props.PanelHeight()) }) - ); +ScriptingGlobals.add(function pinWithView(pinContent: boolean) { + SelectionManager.Views().forEach(view => + view.props.pinToPres(view.rootDoc, { + currentFrame: Cast(view.rootDoc.currentFrame, 'number', null), + pinData: { + poslayoutview: pinContent, + dataview: pinContent, + }, + pinViewport: MarqueeView.CurViewBounds(view.rootDoc, view.props.PanelWidth(), view.props.PanelHeight()), + }) + ); }); ScriptingGlobals.add(function bringToFront() { SelectionManager.Views().forEach(view => view.props.CollectionFreeFormDocumentView?.().props.CollectionFreeFormView.bringToFront(view.rootDoc)); diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx index 0afb36214..bfaae8069 100644 --- a/src/client/views/nodes/trails/PresBox.tsx +++ b/src/client/views/nodes/trails/PresBox.tsx @@ -59,7 +59,6 @@ export interface PinProps { hidePresBox?: boolean; pinViewport?: MarqueeViewBounds; // pin a specific viewport on a freeform view (use MarqueeView.CurViewBounds to compute if no region has been selected) pinDocLayout?: boolean; // pin layout info (width/height/x/y) - pinDocContent?: boolean; // pin data info (scroll/pan/zoom/text) pinAudioPlay?: boolean; // pin audio annotation pinData?: pinDataTypes; } diff --git a/src/client/views/nodes/trails/PresElementBox.tsx b/src/client/views/nodes/trails/PresElementBox.tsx index 698a2817e..9a74b5dba 100644 --- a/src/client/views/nodes/trails/PresElementBox.tsx +++ b/src/client/views/nodes/trails/PresElementBox.tsx @@ -312,7 +312,7 @@ export class PresElementBox extends ViewBoxBaseComponent() { @action updateCapturedViewContents = (presTargetDoc: Doc, activeItem: Doc) => { const target = DocCast(presTargetDoc.annotationOn) ?? presTargetDoc; - PresBox.pinDocView(activeItem, { pinDocContent: true, pinData: PresBox.pinDataTypes(target) }, target); + PresBox.pinDocView(activeItem, { pinData: PresBox.pinDataTypes(target) }, target); }; @computed get recordingIsInOverlay() { -- cgit v1.2.3-70-g09d2 From 8a1267faf796b2e2a30a6ba9f86879854e9ee983 Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 11 Apr 2023 13:51:44 -0400 Subject: removed arrangeItems context button for collections to make it a funciton on drop instead of a reaction. Converted isLinkButton to be an onClick script. got rid of unused PARAMS field on templates. fixed PresElementBox rendering of embedded docs. --- src/client/documents/Documents.ts | 7 +-- src/client/util/CurrentUserUtils.ts | 4 +- src/client/util/DropConverter.ts | 10 +--- src/client/util/LinkFollower.ts | 6 ++ src/client/views/DocumentButtonBar.tsx | 9 +-- src/client/views/MarqueeAnnotator.tsx | 8 ++- src/client/views/PropertiesButtons.tsx | 7 ++- src/client/views/StyleProvider.tsx | 5 +- src/client/views/collections/CollectionMenu.tsx | 19 +----- .../views/collections/CollectionNoteTakingView.tsx | 4 +- .../collections/CollectionStackedTimeline.tsx | 6 +- .../views/collections/CollectionStackingView.tsx | 6 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 56 ++++++++++-------- src/client/views/nodes/DocumentContentsView.tsx | 3 +- src/client/views/nodes/DocumentView.tsx | 67 +++++----------------- src/client/views/nodes/ImageBox.tsx | 2 +- src/client/views/nodes/LinkAnchorBox.tsx | 2 +- src/client/views/nodes/PDFBox.tsx | 2 +- src/client/views/nodes/VideoBox.tsx | 7 ++- .../views/nodes/formattedText/DashFieldView.tsx | 4 +- .../views/nodes/formattedText/FormattedTextBox.tsx | 4 +- src/client/views/nodes/trails/PresElementBox.tsx | 2 +- src/fields/Doc.ts | 10 ++-- src/fields/documentSchemas.ts | 1 - 24 files changed, 104 insertions(+), 147 deletions(-) (limited to 'src/client/views/DocumentButtonBar.tsx') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 979b294e0..7600fcac9 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -263,7 +263,6 @@ export class DocumentOptions { caption?: RichTextField; opacity?: number; defaultBackgroundColor?: string; - _isLinkButton?: boolean; // marks a document as a button that will follow its primary link when clicked _linkAutoMove?: boolean; // whether link endpoint should move around the edges of a document to make shortest path to other link endpoint hideLinkAnchors?: boolean; // suppresses link anchor dots from being displayed isFolder?: boolean; @@ -508,13 +507,13 @@ export namespace Docs { layout: { view: LinkBox, dataField: defaultDataKey }, options: { childDontRegisterViews: true, - _isLinkButton: true, + onClick: ScriptField.MakeScript('followLink(this,altKey)', { altKey: 'boolean' }), hideLinkAnchors: true, _height: 150, description: '', showCaption: 'description', backgroundColor: 'lightblue', // lightblue is default color for linking dot and link documents text comment area - _removeDropProperties: new List(['isLinkButton']), + _removeDropProperties: new List(['onClick']), }, }, ], @@ -1695,7 +1694,7 @@ export namespace DocUtils { _width: 15, _height: 15, _xPadding: 0, - _isLinkButton: true, + onClick: ScriptField.MakeScript('followLink(this,altKey)', { altKey: 'boolean' }), _timecodeToShow: Cast(doc._timecodeToShow, 'number', null), }); Doc.AddDocToList(context, annotationField, pushpin); diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 623aaf357..3d0db04b4 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -271,7 +271,7 @@ export class CurrentUserUtils { {key: "Map", creator: opts => Docs.Create.MapDocument([], opts), opts: { _width: 800, _height: 600, _fitWidth: true, _showSidebar: true, }}, {key: "Screengrab", creator: Docs.Create.ScreenshotDocument, opts: { _width: 400, _height: 200 }}, {key: "WebCam", creator: opts => Docs.Create.WebCamDocument("", opts), opts: { _width: 400, _height: 200, recording:true, system: true, cloneFieldFilter: new List(["system"]) }}, - {key: "Button", creator: Docs.Create.ButtonDocument, opts: { _width: 150, _height: 50, _xPadding: 10, _yPadding: 10, _isLinkButton: true }}, + {key: "Button", creator: Docs.Create.ButtonDocument, opts: { _width: 150, _height: 50, _xPadding: 10, _yPadding: 10, onClick: ScriptField.MakeScript("followLink(this,altKey)", {altKey:"boolean"}) }}, {key: "Script", creator: opts => Docs.Create.ScriptingDocument(null, opts), opts: { _width: 200, _height: 250, }}, {key: "DataViz", creator: opts => Docs.Create.DataVizDocument("/users/rz/Downloads/addresses.csv", opts), opts: { _width: 300, _height: 300 }}, {key: "Header", creator: headerTemplate, opts: { _width: 300, _height: 70, _headerPointerEvents: "all", _headerHeight: 12, _headerFontSize: 9, _autoHeight: true, treeViewHideUnrendered: true}}, @@ -622,7 +622,7 @@ export class CurrentUserUtils { { title: "Snap\xA0Lines",icon: "th", toolTip: "Show Snap Lines", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"snap lines", funcs: {}, scripts: { onClick: 'showFreeform(self.toolType, _readOnly_)'}}, // Only when floating document is selected in freeform { title: "View\xA0All", icon: "object-group",toolTip: "Fit all Docs to View",btnType: ButtonType.ToggleButton, expertMode: false, toolType:"viewAll", funcs: {}, scripts: { onClick: 'showFreeform(self.toolType, _readOnly_)'}}, // Only when floating document is selected in freeform { title: "Clusters", icon: "braille", toolTip: "Show Doc Clusters", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"clusters", funcs: {}, scripts: { onClick: 'showFreeform(self.toolType, _readOnly_)'}}, // Only when floating document is selected in freeform - { title: "Arrange", icon: "window", toolTip: "Toggle Auto Arrange", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"arrange", funcs: {}, scripts: { onClick: 'showFreeform(self.toolType, _readOnly_)'}}, // Only when floating document is selected in freeform + { title: "Arrange", icon: "window", toolTip: "Toggle Auto Arrange", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"arrange", funcs: {hidden: 'IsNoviceMode()'}, scripts: { onClick: 'showFreeform(self.toolType, _readOnly_)'}}, // Only when floating document is selected in freeform { title: "Reset", icon: "check", toolTip: "Reset View", btnType: ButtonType.ClickButton, expertMode: false, backgroundColor:"transparent", scripts: { onClick: 'resetView()'}}, // Only when floating document is selected in freeform ] } diff --git a/src/client/util/DropConverter.ts b/src/client/util/DropConverter.ts index 7c209d1e0..2e1d6ba23 100644 --- a/src/client/util/DropConverter.ts +++ b/src/client/util/DropConverter.ts @@ -33,15 +33,7 @@ function makeTemplate(doc: Doc, first: boolean = true, rename: Opt = und let any = false; docs.forEach(d => { if (!StrCast(d.title).startsWith('-')) { - const params = StrCast(d.title) - .match(/\(([a-zA-Z0-9._\-]*)\)/)?.[1] - .replace('()', ''); - if (params) { - any = makeTemplate(d, false) || any; - d.PARAMS = params; - } else { - any = Doc.MakeMetadataFieldTemplate(d, Doc.GetProto(layoutDoc)) || any; - } + any = Doc.MakeMetadataFieldTemplate(d, Doc.GetProto(layoutDoc)) || any; } else if (d.type === DocumentType.COL || d.data instanceof RichTextField) { any = makeTemplate(d, false) || any; } diff --git a/src/client/util/LinkFollower.ts b/src/client/util/LinkFollower.ts index df61ecece..f5aae6632 100644 --- a/src/client/util/LinkFollower.ts +++ b/src/client/util/LinkFollower.ts @@ -7,6 +7,7 @@ import { DocFocusOptions, DocumentViewSharedProps, OpenWhere } from '../views/no import { PresBox } from '../views/nodes/trails'; import { DocumentManager } from './DocumentManager'; import { LinkManager } from './LinkManager'; +import { ScriptingGlobals } from './ScriptingGlobals'; import { SelectionManager } from './SelectionManager'; import { UndoManager } from './UndoManager'; /* @@ -118,3 +119,8 @@ export class LinkFollower { }); } } + +ScriptingGlobals.add(function followLink(doc: Doc, altKey: boolean) { + SelectionManager.DeselectAll(); + LinkFollower.FollowLink(undefined, doc, altKey); +}); diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx index e83ea00cf..7e1b32398 100644 --- a/src/client/views/DocumentButtonBar.tsx +++ b/src/client/views/DocumentButtonBar.tsx @@ -5,7 +5,7 @@ import { action, computed, observable, runInAction, trace } from 'mobx'; import { observer } from 'mobx-react'; import { Doc } from '../../fields/Doc'; import { RichTextField } from '../../fields/RichTextField'; -import { Cast, DocCast, NumCast } from '../../fields/Types'; +import { Cast, DocCast, NumCast, ScriptCast } from '../../fields/Types'; import { emptyFunction, returnFalse, setupMoveUpEvents, simulateMouseClick } from '../../Utils'; import { GoogleAuthenticationManager } from '../apis/GoogleAuthenticationManager'; import { Pulls, Pushes } from '../apis/google_docs/GoogleApiClientUtils'; @@ -238,11 +238,12 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV ); }; + const followLink = ScriptCast(targetDoc?.onClick)?.script.originalScript.includes('followLink('); return !targetDoc ? null : ( Set onClick to follow primary link
}>
this.props.views().map(view => view?.docView?.toggleFollowLink(undefined, false)))}>
{followBtn( @@ -384,7 +385,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV .views() .filter(v => v) .map(dv => dv!.rootDoc); - TabDocView.PinDoc(docs, { pinAudioPlay: true, pinDocLayout: e.shiftKey, pinData: {dataview: e.altKey}, activeFrame: Cast(docs.lastElement()?.activeFrame, 'number', null) }); + TabDocView.PinDoc(docs, { pinAudioPlay: true, pinDocLayout: e.shiftKey, pinData: { dataview: e.altKey }, activeFrame: Cast(docs.lastElement()?.activeFrame, 'number', null) }); e.stopPropagation(); }}>
@@ -593,7 +594,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV (link.linkDisplay = !this.props.views().lastElement()?.rootDoc.isLinkButton)} + linkCreated={link => (link.linkDisplay = !ScriptCast(this.props.views().lastElement()?.rootDoc.onClick)?.script.originalScript.includes('followLink('))} linkCreateAnchor={() => this.props.views().lastElement()?.ComponentView?.getAnchor?.(true)} linkFrom={() => this.props.views().lastElement()?.rootDoc} /> diff --git a/src/client/views/MarqueeAnnotator.tsx b/src/client/views/MarqueeAnnotator.tsx index 30867a774..6b4f8ad85 100644 --- a/src/client/views/MarqueeAnnotator.tsx +++ b/src/client/views/MarqueeAnnotator.tsx @@ -14,6 +14,7 @@ import { DocumentView } from './nodes/DocumentView'; import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox'; import { AnchorMenu } from './pdf/AnchorMenu'; import React = require('react'); +import { ScriptField } from '../../fields/ScriptField'; const _global = (window /* browser */ || global) /* node */ as any; export interface MarqueeAnnotatorProps { @@ -146,7 +147,12 @@ export class MarqueeAnnotator extends React.Component { const scale = this.props.scaling?.() || 1; const anno = savedAnnos[0]; const containerOffset = this.props.containerOffset?.() || [0, 0]; - const marqueeAnno = Docs.Create.FreeformDocument([], { _isLinkButton: isLinkButton, backgroundColor: color, annotationOn: this.props.rootDoc, title: 'Annotation on ' + this.props.rootDoc.title }); + const marqueeAnno = Docs.Create.FreeformDocument([], { + onClick: isLinkButton ? ScriptField.MakeScript('followLink(this,altKey)', { altKey: 'boolean' }) : undefined, + backgroundColor: color, + annotationOn: this.props.rootDoc, + title: 'Annotation on ' + this.props.rootDoc.title, + }); marqueeAnno.x = NumCast(this.props.docView.props.Document.panXMin) + (parseInt(anno.style.left || '0') - containerOffset[0]) / scale / NumCast(this.props.docView.props.Document._viewScale, 1); marqueeAnno.y = NumCast(this.props.docView.props.Document.panYMin) + (parseInt(anno.style.top || '0') - containerOffset[1]) / scale / NumCast(this.props.docView.props.Document._viewScale, 1) + NumCast(this.props.scrollTop); marqueeAnno._height = parseInt(anno.style.height || '0') / scale / NumCast(this.props.docView.props.Document._viewScale, 1); diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx index 11e9dd9c9..0723966e1 100644 --- a/src/client/views/PropertiesButtons.tsx +++ b/src/client/views/PropertiesButtons.tsx @@ -289,6 +289,7 @@ export class PropertiesButtons extends React.Component<{}, {}> { .filter(dv => dv.docView) .map(dv => dv.docView!) .forEach(docView => { + const linkButton = ScriptCast(docView.props.Document.onClick)?.script.originalScript.includes('followLink('); docView.noOnClick(); switch (onClick) { case 'enterPortal': @@ -299,11 +300,11 @@ export class PropertiesButtons extends React.Component<{}, {}> { break; case 'linkInPlace': docView.toggleFollowLink(false, false); - docView.props.Document.followLinkLocation = docView.props.Document._isLinkButton ? OpenWhere.lightbox : undefined; + docView.props.Document.followLinkLocation = linkButton ? OpenWhere.lightbox : undefined; break; case 'linkOnRight': docView.toggleFollowLink(false, false); - docView.props.Document.followLinkLocation = docView.props.Document._isLinkButton ? OpenWhere.addRight : undefined; + docView.props.Document.followLinkLocation = linkButton ? OpenWhere.addRight : undefined; break; } }); @@ -326,7 +327,7 @@ export class PropertiesButtons extends React.Component<{}, {}> { ]; const list = buttonList.map(value => { const click = () => this.handleOptionChange(value[0]); - const linkButton = BoolCast(this.selectedDoc._isLinkButton); + const linkButton = BoolCast(ScriptCast(this.selectedDoc.onClick)?.script.originalScript.includes('followLink(')); const followLoc = this.selectedDoc._followLinkLocation; const linkedToLightboxView = () => LinkManager.Links(this.selectedDoc).some(link => LinkManager.getOppositeAnchor(link, this.selectedDoc)?._isLightbox); diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx index f7b9420a7..8d67f0528 100644 --- a/src/client/views/StyleProvider.tsx +++ b/src/client/views/StyleProvider.tsx @@ -4,7 +4,7 @@ import { Shadows } from 'browndash-components'; import { action, runInAction } from 'mobx'; import { extname } from 'path'; import { Doc, Opt, StrListCast } from '../../fields/Doc'; -import { BoolCast, Cast, ImageCast, NumCast, StrCast } from '../../fields/Types'; +import { BoolCast, Cast, ImageCast, NumCast, ScriptCast, StrCast } from '../../fields/Types'; import { DashColor, lightOrDark, Utils } from '../../Utils'; import { CollectionViewType, DocumentType } from '../documents/DocumentTypes'; import { DocFocusOrOpen, DocumentManager } from '../util/DocumentManager'; @@ -279,7 +279,8 @@ export function DefaultStyleProvider(doc: Opt, props: Opt {}), initialize: emptyFunction, }; - _openLinkInCommand = { - params: ['target', 'container'], - title: 'link follow target', - script: `{ if (self.container?.length) { - getProto(self.target).linkContainer = self.container[0]; - getProto(self.target).isLinkButton = true; - getProto(self.target).onClick = makeScript("getProto(self.linkContainer).data = new List([self.links[0]?.anchor2])"); - }}`, - immediate: undoBatch((container: Doc[]) => { - if (container.length) { - Doc.GetProto(this.target).linkContainer = container[0]; - Doc.GetProto(this.target).isLinkButton = true; - Doc.GetProto(this.target).onClick = ScriptField.MakeScript('getProto(self.linkContainer).data = new List([self.links[0]?.anchor2])'); - } - }), - initialize: emptyFunction, - }; _viewCommand = { params: ['target'], title: 'bookmark view', @@ -328,7 +311,7 @@ export class CollectionViewBaseChrome extends React.Component (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; + const dataDoc = !doc.isTemplateDoc && !doc.isTemplateForField ? undefined : this.props.DataDoc; const height = () => this.getDocHeight(doc); let dref: Opt; const noteTakingDocTransform = () => this.getDocTransform(doc, dref); @@ -293,7 +293,7 @@ export class CollectionNoteTakingView extends CollectionSubView() { getDocHeight(d?: Doc) { if (!d || d.hidden) return 0; const childLayoutDoc = Doc.Layout(d, this.props.childLayoutTemplate?.()); - const childDataDoc = !d.isTemplateDoc && !d.isTemplateForField && !d.PARAMS ? undefined : this.props.DataDoc; + const childDataDoc = !d.isTemplateDoc && !d.isTemplateForField ? undefined : this.props.DataDoc; const maxHeight = (lim => (lim === 0 ? this.props.PanelWidth() : lim === -1 ? 10000 : lim))(NumCast(this.layoutDoc.childLimitHeight, -1)); const nw = Doc.NativeWidth(childLayoutDoc, childDataDoc) || (!(childLayoutDoc._fitWidth || this.props.childFitWidth?.(d)) ? d[WidthSym]() : 0); const nh = Doc.NativeHeight(childLayoutDoc, childDataDoc) || (!(childLayoutDoc._fitWidth || this.props.childFitWidth?.(d)) ? d[HeightSym]() : 0); diff --git a/src/client/views/collections/CollectionStackedTimeline.tsx b/src/client/views/collections/CollectionStackedTimeline.tsx index 642d29d2a..5891cfe78 100644 --- a/src/client/views/collections/CollectionStackedTimeline.tsx +++ b/src/client/views/collections/CollectionStackedTimeline.tsx @@ -7,7 +7,7 @@ import { Id } from '../../../fields/FieldSymbols'; import { List } from '../../../fields/List'; import { listSpec } from '../../../fields/Schema'; import { ComputedField, ScriptField } from '../../../fields/ScriptField'; -import { Cast, NumCast } from '../../../fields/Types'; +import { Cast, NumCast, ScriptCast } from '../../../fields/Types'; import { ImageField } from '../../../fields/URLField'; import { emptyFunction, formatTime, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnNone, returnTrue, returnZero, setupMoveUpEvents, smoothScrollHorizontal, StopEvent } from '../../../Utils'; import { Docs } from '../../documents/Documents'; @@ -406,7 +406,7 @@ export class CollectionStackedTimeline extends CollectionSubView { - if (anchorDoc.isLinkButton) { + if (ScriptCast(anchorDoc.onClick)?.script.originalScript.includes('followLink(')) { LinkFollower.FollowLink(undefined, anchorDoc, false); } const seekTimeInSeconds = this.anchorStart(anchorDoc) - 0.05; diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 1e02fc9d4..a85ee0e02 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -305,7 +305,7 @@ export class CollectionStackingView extends CollectionSubView number, count: number) { - const dataDoc = !doc.isTemplateDoc && !doc.isTemplateForField && !doc.PARAMS ? undefined : this.props.DataDoc; + const dataDoc = !doc.isTemplateDoc && !doc.isTemplateForField ? undefined : this.props.DataDoc; const height = () => this.getDocHeight(doc); let dref: Opt; @@ -323,7 +323,7 @@ export class CollectionStackingView extends CollectionSubView (lim === 0 ? this.props.PanelWidth() : lim === -1 ? 10000 : lim))(NumCast(this.layoutDoc.childLimitHeight, -1)); const nw = Doc.NativeWidth(childLayoutDoc, childDataDoc) || (!(childLayoutDoc._fitWidth || this.props.childFitWidth?.(d)) ? d[WidthSym]() : 0); const nh = Doc.NativeHeight(childLayoutDoc, childDataDoc) || (!(childLayoutDoc._fitWidth || this.props.childFitWidth?.(d)) ? d[HeightSym]() : 0); diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 1ecc69174..7ae7be3c8 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -349,6 +349,7 @@ export class CollectionFreeFormView extends CollectionSubView (doc.zIndex = doc.isInkMask ? 5000 : index + 1)); const dvals = CollectionFreeFormDocumentView.getValues(refDoc, NumCast(refDoc.activeFrame, 1000)); const dropPos = this.Document._currentFrame !== undefined ? [NumCast(dvals.x), NumCast(dvals.y)] : [NumCast(refDoc.x), NumCast(refDoc.y)]; + for (let i = 0; i < docDragData.droppedDocuments.length; i++) { const d = docDragData.droppedDocuments[i]; const layoutDoc = Doc.Layout(d); @@ -370,6 +371,30 @@ export class CollectionFreeFormView extends CollectionSubView NumCast(a.layout.y) - NumCast(b.layout.y)); + sorted.splice( + sorted.findIndex(pair => pair.layout === refDoc), + 1 + ); + if (sorted.length && refDoc && NumCast(sorted[0].layout.y) < NumCast(refDoc.y)) { + const topIndexed = NumCast(refDoc.y) < NumCast(sorted[0].layout.y) + NumCast(sorted[0].layout._height); + const deltay = sorted.length > 1 ? NumCast(refDoc.y) - (NumCast(sorted[0].layout.y) + (topIndexed ? 0 : NumCast(sorted[0].layout._height))) : 0; + const deltax = sorted.length > 1 ? NumCast(refDoc.x) - NumCast(sorted[0].layout.x) : 0; + + let lastx = NumCast(refDoc.x); + let lasty = NumCast(refDoc.y) + (topIndexed ? 0 : NumCast(refDoc._height)); + setTimeout( + action(() => + sorted.slice(1).forEach((pair, i) => { + lastx = pair.layout.x = lastx + deltax; + lasty = (pair.layout.y = lasty + deltay) + (topIndexed ? 0 : NumCast(pair.layout._height)); + }) + ) + ); + } + } + (docDragData.droppedDocuments.length === 1 || de.shiftKey) && this.updateClusterDocs(docDragData.droppedDocuments); return true; } @@ -1409,24 +1434,6 @@ export class CollectionFreeFormView extends CollectionSubView) { - if (this.layoutDoc._autoArrange) { - const sorted = this.childLayoutPairs.slice().sort((a, b) => (NumCast(a.layout.y) < NumCast(b.layout.y) ? -1 : 1)); - if (sorted.length > 1) { - const deltay = sorted.length > 1 ? NumCast(sorted[1].layout.y) - (NumCast(sorted[0].layout.y) + NumCast(sorted[0].layout._height)) : 0; - const deltax = sorted.length > 1 ? NumCast(sorted[1].layout.x) - NumCast(sorted[0].layout.x) : 0; - - let lastx = NumCast(sorted[0].layout.x); - let lasty = NumCast(sorted[0].layout.y) + NumCast(sorted[0].layout._height); - setTimeout( - action(() => - sorted.slice(1).forEach((pair, i) => { - lastx = pair.layout.x = lastx + deltax; - lasty = (pair.layout.y = lasty + deltay) + NumCast(pair.layout._height); - }) - ) - ); - } - } this.childLayoutPairs.filter(pair => this.isCurrent(pair.layout)).map((pair, i) => poolData.set(pair.layout[Id], this.getCalculatedPositions({ pair, index: i, collection: this.Document }))); return [] as ViewDefResult[]; } @@ -1712,11 +1719,12 @@ export class CollectionFreeFormView extends CollectionSubView (this.layoutDoc._autoArrange = !this.layoutDoc._autoArrange), - icon: 'compress-arrows-alt', - }); + !Doc.noviceMode && + appearanceItems.push({ + description: 'Toggle auto arrange', + event: () => (this.layoutDoc._autoArrange = !this.layoutDoc._autoArrange), + icon: 'compress-arrows-alt', + }); if (this.props.setContentView === emptyFunction) { !appearance && ContextMenu.Instance.addItem({ description: 'Appearance...', subitems: appearanceItems, icon: 'eye' }); return; @@ -1729,7 +1737,7 @@ export class CollectionFreeFormView extends CollectionSubView TabDocView.PinDoc(this.rootDoc, { pinViewport: MarqueeView.CurViewBounds(this.rootDoc, this.props.PanelWidth(), this.props.PanelHeight()) }), icon: 'map-pin' }); !Doc.noviceMode && appearanceItems.push({ description: `update icon`, event: this.updateIcon, icon: 'compress-arrows-alt' }); - appearanceItems.push({ description: 'Ungroup collection', event: this.promoteCollection, icon: 'table' }); + this.props.renderDepth && appearanceItems.push({ description: 'Ungroup collection', event: this.promoteCollection, icon: 'table' }); this.props.Document._isGroup && this.Document.transcription && appearanceItems.push({ description: 'Ink to text', event: () => this.transcribeStrokes(false), icon: 'font' }); diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index 9e56de8c2..2d12005fb 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -139,7 +139,6 @@ export class DocumentContentsView extends React.Component< return proto instanceof Promise ? undefined : proto; } get layoutDoc() { - const params = StrCast(this.props.Document.PARAMS); // bcz: replaced this with below : is it correct? change was made to accommodate passing fieldKey's from a layout script // const template: Doc = this.props.LayoutTemplate?.() || Doc.Layout(this.props.Document, this.props.layoutKey ? Cast(this.props.Document[this.props.layoutKey], Doc, null) : undefined); const template: Doc = @@ -147,7 +146,7 @@ export class DocumentContentsView extends React.Component< (this.props.LayoutTemplateString && this.props.Document) || (this.props.layoutKey && StrCast(this.props.Document[this.props.layoutKey]) && this.props.Document) || Doc.Layout(this.props.Document, this.props.layoutKey ? Cast(this.props.Document[this.props.layoutKey], Doc, null) : undefined); - return Doc.expandTemplateLayout(template, this.props.Document, params ? '(' + params + ')' : this.props.layoutKey); + return Doc.expandTemplateLayout(template, this.props.Document, this.props.layoutKey); } CreateBindings(onClick: Opt, onInput: Opt): JsxBindings { diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index e24bf35f5..a39c3cf8f 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -469,11 +469,6 @@ export class DocumentViewInternal extends DocComponent (this.props.Document.dontUndo ? func() : UndoManager.RunInBatch(func, 'on click')); - } else if (!this.disableClickScriptFunc && this.allLinks.length && this.Document.isLinkButton && !e.shiftKey && !e.ctrlKey) { - clickFunc = () => { - SelectionManager.DeselectAll(); - LinkFollower.FollowLink(undefined, this.Document, e.altKey); - }; } 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.Document.rootDocument) && !(e.ctrlKey || e.button > 0)) { @@ -563,48 +558,24 @@ export class DocumentViewInternal extends DocComponent { - this.Document.ignoreClick = false; - if (setTargetToggle) { - this.Document.followLinkToggle = !this.Document.followLinkToggle; - this.Document._isLinkButton = this.Document.followLinkToggle || this.Document._isLinkButton; - } else { - this.Document._isLinkButton = !this.Document._isLinkButton; - } - if (this.Document._isLinkButton && !this.onClickHandler) { - zoom !== undefined && (this.Document.followLinkZoom = zoom); - } else if (this.Document._isLinkButton && this.onClickHandler) { - this.Document._isLinkButton = false; - this.dataDoc.onClick = this.Document.onClick = this.layoutDoc.onClick = undefined; - } - }; - @undoBatch - @action - toggleTargetOnClick = (): void => { - this.Document.ignoreClick = false; - this.Document._isLinkButton = true; - this.Document.followLinkToggle = true; + const hadOnClick = this.rootDoc.onClick; + this.noOnClick(); + this.Document.onClick = hadOnClick ? undefined : ScriptField.MakeScript('followLink(this,altKey)', { altKey: 'boolean' }); + this.Document.waitForDoubleClickToClick = hadOnClick ? undefined : 'never'; }; @undoBatch @action - followLinkOnClick = (location: Opt, zoom: boolean): void => { + followLinkOnClick = (): void => { this.Document.ignoreClick = false; - this.Document._isLinkButton = true; + this.Document.onClick = ScriptField.MakeScript('followLink(this,altKey)', { altKey: 'boolean' }); this.Document.followLinkToggle = false; - this.Document.followLinkZoom = zoom; - this.Document.followLinkLocation = location; - }; - @undoBatch - @action - selectOnClick = (): void => { - this.Document.ignoreClick = false; - this.Document._isLinkButton = false; - this.Document.followLinkToggle = false; - this.Document.onClick = this.layoutDoc.onClick = undefined; + this.Document.followLinkZoom = false; + this.Document.followLinkLocation = undefined; }; @undoBatch noOnClick = (): void => { this.Document.ignoreClick = false; - this.Document._isLinkButton = false; + this.Document.onClick = Doc.GetProto(this.Document).onClick = undefined; }; @undoBatch deleteClicked = () => this.props.removeDocument?.(this.props.Document); @@ -652,8 +623,7 @@ export class DocumentViewInternal extends DocComponent { @@ -744,29 +714,20 @@ export class DocumentViewInternal extends DocComponent (this.Document.followLinkZoom = !this.Document.followLinkZoom), - icon: this.Document.ignoreClick ? 'unlock' : 'lock', - }); 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.Document.ignoreClick ? 'Select' : 'Do Nothing', event: () => (this.Document.ignoreClick = !this.Document.ignoreClick), icon: this.Document.ignoreClick ? 'unlock' : 'lock' }); - onClicks.push({ description: this.Document.isLinkButton || this.onClickHandler ? 'Remove Click Behavior' : 'Follow Link', event: () => this.toggleFollowLink(false, false), icon: 'link' }); - onClicks.push({ description: (this.Document.followLinkToggle ? 'Remove' : 'Make') + ' Target Visibility Toggle', event: () => this.toggleFollowLink(false, true), icon: 'map-pin' }); + onClicks.push({ description: this.onClickHandler ? 'Remove Click Behavior' : 'Follow Link', event: () => this.toggleFollowLink(false, false), icon: 'link' }); onClicks.push({ description: 'Edit onClick Script', event: () => UndoManager.RunInBatch(() => DocUtils.makeCustomViewClicked(this.props.Document, undefined, 'onClick'), 'edit onClick'), icon: 'terminal' }); !existingOnClick && cm.addItem({ description: 'OnClick...', addDivider: true, noexpand: true, subitems: onClicks, icon: 'mouse-pointer' }); } else if (LinkManager.Links(this.Document).length) { - onClicks.push({ description: 'Select on Click', event: () => this.selectOnClick(), icon: 'link' }); - onClicks.push({ description: 'Follow Link on Click', event: () => this.followLinkOnClick(undefined, false), icon: 'link' }); - onClicks.push({ description: 'Toggle Link Target on Click', event: () => this.toggleTargetOnClick(), icon: 'map-pin' }); + onClicks.push({ description: 'Select on Click', event: () => this.noOnClick(), icon: 'link' }); + onClicks.push({ description: 'Follow Link on Click', event: () => this.followLinkOnClick(), icon: 'link' }); !existingOnClick && cm.addItem({ description: 'OnClick...', addDivider: true, subitems: onClicks, icon: 'mouse-pointer' }); } } diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index f38ebba27..22ecaa299 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -202,7 +202,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent() { if (separation > 100) { const dragData = new DragManager.DocumentDragData([this.rootDoc]); dragData.dropAction = 'alias'; - dragData.removeDropProperties = ['anchor1_x', 'anchor1_y', 'anchor2_x', 'anchor2_y', 'isLinkButton']; + dragData.removeDropProperties = ['anchor1_x', 'anchor1_y', 'anchor2_x', 'anchor2_y', 'onClick']; DragManager.StartDocumentDrag([this._ref.current!], dragData, pt[0], pt[1]); return true; } else { diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index e38d7e2a8..502811e35 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -119,7 +119,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent 1 ? new List(splits) : newText; if (this._fieldKey.startsWith('_')) Doc.Layout(this._textBoxDoc)[this._fieldKey] = strVal; Doc.SetInPlace(this._dashDoc!, this._fieldKey, strVal, true); diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 361e000f9..809315963 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -17,7 +17,7 @@ import { InkTool } from '../../../../fields/InkField'; import { PrefetchProxy } from '../../../../fields/Proxy'; import { RichTextField } from '../../../../fields/RichTextField'; import { RichTextUtils } from '../../../../fields/RichTextUtils'; -import { ComputedField } from '../../../../fields/ScriptField'; +import { ComputedField, ScriptField } from '../../../../fields/ScriptField'; import { BoolCast, Cast, DocCast, FieldValue, NumCast, ScriptCast, StrCast } from '../../../../fields/Types'; import { GetEffectiveAcl, TraceMobx } from '../../../../fields/util'; import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, emptyFunction, numberRange, returnFalse, returnZero, setupMoveUpEvents, smoothScroll, unimplementedFunction, Utils } from '../../../../Utils'; @@ -1933,7 +1933,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent
diff --git a/src/client/views/nodes/trails/PresElementBox.tsx b/src/client/views/nodes/trails/PresElementBox.tsx index 9a74b5dba..92696240b 100644 --- a/src/client/views/nodes/trails/PresElementBox.tsx +++ b/src/client/views/nodes/trails/PresElementBox.tsx @@ -97,7 +97,7 @@ export class PresElementBox extends ViewBoxBaseComponent() { return !this.rootDoc.presExpandInlineButton || !this.targetDoc ? null : (
1 ? args.split('=')[0] : 'PARAMS'; + const params = args.split('=').length > 1 ? args.split('=')[0] : ''; const layoutFielddKey = Doc.LayoutFieldKey(templateLayoutDoc); const expandedLayoutFieldKey = (templateField || layoutFielddKey) + '-layout[' + templateLayoutDoc[Id] + (args ? `(${args})` : '') + ']'; let expandedTemplateLayout = targetDoc?.[expandedLayoutFieldKey]; @@ -945,7 +945,7 @@ export namespace Doc { expandedTemplateLayout = undefined; _pendingMap.set(targetDoc[Id] + expandedLayoutFieldKey, true); } else if (expandedTemplateLayout === undefined && !_pendingMap.get(targetDoc[Id] + expandedLayoutFieldKey + args)) { - if (templateLayoutDoc.resolvedDataDoc === (targetDoc.rootDocument || Doc.GetProto(targetDoc)) && templateLayoutDoc.PARAMS === StrCast(targetDoc.PARAMS)) { + if (templateLayoutDoc.resolvedDataDoc === (targetDoc.rootDocument || Doc.GetProto(targetDoc))) { expandedTemplateLayout = templateLayoutDoc; // reuse an existing template layout if its for the same document with the same params } else { templateLayoutDoc.resolvedDataDoc && (templateLayoutDoc = Cast(templateLayoutDoc.proto, Doc, null) || templateLayoutDoc); // if the template has already been applied (ie, a nested template), then use the template's prototype @@ -981,8 +981,8 @@ export namespace Doc { console.log('No, no, no!'); return { layout: childDoc, data: childDoc }; } - const resolvedDataDoc = Doc.AreProtosEqual(containerDataDoc, containerDoc) || (!childDoc.isTemplateDoc && !childDoc.isTemplateForField && !childDoc.PARAMS) ? undefined : containerDataDoc; - return { layout: Doc.expandTemplateLayout(childDoc, resolvedDataDoc, '(' + StrCast(containerDoc.PARAMS) + ')'), data: resolvedDataDoc }; + const resolvedDataDoc = Doc.AreProtosEqual(containerDataDoc, containerDoc) || (!childDoc.isTemplateDoc && !childDoc.isTemplateForField) ? undefined : containerDataDoc; + return { layout: Doc.expandTemplateLayout(childDoc, resolvedDataDoc, '()'), data: resolvedDataDoc }; } export function Overwrite(doc: Doc, overwrite: Doc, copyProto: boolean = false): Doc { diff --git a/src/fields/documentSchemas.ts b/src/fields/documentSchemas.ts index 5b489a96c..b7fd06973 100644 --- a/src/fields/documentSchemas.ts +++ b/src/fields/documentSchemas.ts @@ -89,7 +89,6 @@ export const documentSchema = createSchema({ hideAllLinks: 'boolean', // whether all individual blue anchor dots should be hidden linkDisplay: 'boolean', // whether a link connection should be shown between link anchor endpoints. isLightbox: 'boolean', // whether the marked object will display addDocTab() calls that target "lightbox" destinations - isLinkButton: 'boolean', // whether document functions as a link follow button to follow the first link on the document when clicked layers: listSpec('string'), // which layers the document is part of _lockedPosition: 'boolean', // whether the document can be moved (dragged) _lockedTransform: 'boolean', // whether a freeformview can pan/zoom -- cgit v1.2.3-70-g09d2 From 5d1e3710a015d8915bd367ece753817d84d9d916 Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 11 Apr 2023 14:43:54 -0400 Subject: exracted FollowLinkScript() function. got rid of template parameters to simplify templating. --- src/client/documents/Documents.ts | 5 +-- src/client/util/CurrentUserUtils.ts | 3 +- src/client/util/LinkFollower.ts | 22 ++++++++---- src/client/views/DocumentButtonBar.tsx | 13 ++++--- src/client/views/DocumentDecorations.tsx | 6 ++-- src/client/views/MarqueeAnnotator.tsx | 3 +- src/client/views/PropertiesButtons.tsx | 5 +-- src/client/views/StyleProvider.tsx | 12 +++---- .../collections/CollectionStackedTimeline.tsx | 6 ++-- src/client/views/nodes/DocumentContentsView.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 8 ++--- src/client/views/nodes/VideoBox.tsx | 5 +-- .../views/nodes/formattedText/DashDocView.tsx | 2 +- .../views/nodes/formattedText/FormattedTextBox.tsx | 3 +- src/fields/Doc.ts | 41 +++++++--------------- 15 files changed, 65 insertions(+), 71 deletions(-) (limited to 'src/client/views/DocumentButtonBar.tsx') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 7600fcac9..8d97ce5af 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -21,6 +21,7 @@ import { Networking } from '../Network'; import { DocumentManager } from '../util/DocumentManager'; import { DragManager, dropActionType } from '../util/DragManager'; import { DirectoryImportBox } from '../util/Import & Export/DirectoryImportBox'; +import { FollowLinkScript } from '../util/LinkFollower'; import { LinkManager } from '../util/LinkManager'; import { ScriptingGlobals } from '../util/ScriptingGlobals'; import { undoBatch, UndoManager } from '../util/UndoManager'; @@ -507,7 +508,7 @@ export namespace Docs { layout: { view: LinkBox, dataField: defaultDataKey }, options: { childDontRegisterViews: true, - onClick: ScriptField.MakeScript('followLink(this,altKey)', { altKey: 'boolean' }), + onClick: FollowLinkScript(), hideLinkAnchors: true, _height: 150, description: '', @@ -1694,7 +1695,7 @@ export namespace DocUtils { _width: 15, _height: 15, _xPadding: 0, - onClick: ScriptField.MakeScript('followLink(this,altKey)', { altKey: 'boolean' }), + onClick: FollowLinkScript(), _timecodeToShow: Cast(doc._timecodeToShow, 'number', null), }); Doc.AddDocToList(context, annotationField, pushpin); diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 3d0db04b4..76ea3e3ea 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -25,6 +25,7 @@ import { OpenWhere } from "../views/nodes/DocumentView"; import { OverlayView } from "../views/OverlayView"; import { DragManager } from "./DragManager"; import { MakeTemplate } from "./DropConverter"; +import { FollowLinkScript } from "./LinkFollower"; import { LinkManager } from "./LinkManager"; import { ScriptingGlobals } from "./ScriptingGlobals"; import { ColorScheme } from "./SettingsManager"; @@ -271,7 +272,7 @@ export class CurrentUserUtils { {key: "Map", creator: opts => Docs.Create.MapDocument([], opts), opts: { _width: 800, _height: 600, _fitWidth: true, _showSidebar: true, }}, {key: "Screengrab", creator: Docs.Create.ScreenshotDocument, opts: { _width: 400, _height: 200 }}, {key: "WebCam", creator: opts => Docs.Create.WebCamDocument("", opts), opts: { _width: 400, _height: 200, recording:true, system: true, cloneFieldFilter: new List(["system"]) }}, - {key: "Button", creator: Docs.Create.ButtonDocument, opts: { _width: 150, _height: 50, _xPadding: 10, _yPadding: 10, onClick: ScriptField.MakeScript("followLink(this,altKey)", {altKey:"boolean"}) }}, + {key: "Button", creator: Docs.Create.ButtonDocument, opts: { _width: 150, _height: 50, _xPadding: 10, _yPadding: 10, onClick: FollowLinkScript()}}, {key: "Script", creator: opts => Docs.Create.ScriptingDocument(null, opts), opts: { _width: 200, _height: 250, }}, {key: "DataViz", creator: opts => Docs.Create.DataVizDocument("/users/rz/Downloads/addresses.csv", opts), opts: { _width: 300, _height: 300 }}, {key: "Header", creator: headerTemplate, opts: { _width: 300, _height: 70, _headerPointerEvents: "all", _headerHeight: 12, _headerFontSize: 9, _autoHeight: true, treeViewHideUnrendered: true}}, diff --git a/src/client/util/LinkFollower.ts b/src/client/util/LinkFollower.ts index f5aae6632..d4d7c66f5 100644 --- a/src/client/util/LinkFollower.ts +++ b/src/client/util/LinkFollower.ts @@ -1,9 +1,9 @@ -import { action, runInAction } from 'mobx'; -import { Doc, DocListCast, Opt } from '../../fields/Doc'; -import { BoolCast, Cast, DocCast, NumCast, StrCast } from '../../fields/Types'; +import { action, observable, runInAction } from 'mobx'; +import { Doc, DocListCast, Field, FieldResult, Opt } from '../../fields/Doc'; +import { ScriptField } from '../../fields/ScriptField'; +import { BoolCast, Cast, DocCast, NumCast, ScriptCast, StrCast } from '../../fields/Types'; import { DocumentType } from '../documents/DocumentTypes'; -import { DocumentDecorations } from '../views/DocumentDecorations'; -import { DocFocusOptions, DocumentViewSharedProps, OpenWhere } from '../views/nodes/DocumentView'; +import { DocFocusOptions, OpenWhere } from '../views/nodes/DocumentView'; import { PresBox } from '../views/nodes/trails'; import { DocumentManager } from './DocumentManager'; import { LinkManager } from './LinkManager'; @@ -23,18 +23,19 @@ import { UndoManager } from './UndoManager'; * - user defined kvps */ export class LinkFollower { + @observable public static IsFollowing = false; // follows a link - if the target is on screen, it highlights/pans to it. // if the target isn't onscreen, then it will open up the target in the lightbox, or in place // depending on the followLinkLocation property of the source (or the link itself as a fallback); public static FollowLink = (linkDoc: Opt, sourceDoc: Doc, altKey: boolean) => { const batch = UndoManager.StartBatch('follow link click'); - runInAction(() => (DocumentDecorations.Instance.overrideBounds = true)); // turn off decoration bounds while following links since animations may occur, and DocDecorations is based on screenToLocal which is not always an observable value + runInAction(() => (LinkFollower.IsFollowing = true)); // turn off decoration bounds while following links since animations may occur, and DocDecorations is based on screenToLocal which is not always an observable value LinkFollower.traverseLink( linkDoc, sourceDoc, action(() => { batch.end(); - Doc.AddUnHighlightWatcher(action(() => (DocumentDecorations.Instance.overrideBounds = false))); + Doc.AddUnHighlightWatcher(action(() => (LinkFollower.IsFollowing = false))); }), altKey ? true : undefined ); @@ -124,3 +125,10 @@ ScriptingGlobals.add(function followLink(doc: Doc, altKey: boolean) { SelectionManager.DeselectAll(); LinkFollower.FollowLink(undefined, doc, altKey); }); + +export function FollowLinkScript() { + return ScriptField.MakeScript('followLink(this,altKey)', { altKey: 'boolean' }); +} +export function IsFollowLinkScript(field: FieldResult) { + return ScriptCast(field)?.script.originalScript.includes('followLink('); +} diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx index 7e1b32398..8c2ced55a 100644 --- a/src/client/views/DocumentButtonBar.tsx +++ b/src/client/views/DocumentButtonBar.tsx @@ -1,16 +1,17 @@ import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Tooltip } from '@material-ui/core'; -import { action, computed, observable, runInAction, trace } from 'mobx'; +import { action, computed, observable, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import { Doc } from '../../fields/Doc'; import { RichTextField } from '../../fields/RichTextField'; -import { Cast, DocCast, NumCast, ScriptCast } from '../../fields/Types'; +import { Cast, DocCast, NumCast } from '../../fields/Types'; import { emptyFunction, returnFalse, setupMoveUpEvents, simulateMouseClick } from '../../Utils'; import { GoogleAuthenticationManager } from '../apis/GoogleAuthenticationManager'; import { Pulls, Pushes } from '../apis/google_docs/GoogleApiClientUtils'; import { Docs, DocUtils } from '../documents/Documents'; import { DragManager } from '../util/DragManager'; +import { IsFollowLinkScript } from '../util/LinkFollower'; import { SelectionManager } from '../util/SelectionManager'; import { SharingManager } from '../util/SharingManager'; import { undoBatch, UndoManager } from '../util/UndoManager'; @@ -24,11 +25,9 @@ import { DocumentLinksButton } from './nodes/DocumentLinksButton'; import { DocumentView, DocumentViewInternal, OpenWhere, OpenWhereMod } from './nodes/DocumentView'; import { DashFieldView } from './nodes/formattedText/DashFieldView'; import { GoogleRef } from './nodes/formattedText/FormattedTextBox'; +import { PinProps } from './nodes/trails'; import { TemplateMenu } from './TemplateMenu'; import React = require('react'); -import { DocumentType } from '../documents/DocumentTypes'; -import { FontIconBox } from './nodes/button/FontIconBox'; -import { PinProps } from './nodes/trails'; const higflyout = require('@hig/flyout'); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; @@ -238,7 +237,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV ); }; - const followLink = ScriptCast(targetDoc?.onClick)?.script.originalScript.includes('followLink('); + const followLink = IsFollowLinkScript(targetDoc?.onClick); return !targetDoc ? null : ( Set onClick to follow primary link
}>
(DocumentV (link.linkDisplay = !ScriptCast(this.props.views().lastElement()?.rootDoc.onClick)?.script.originalScript.includes('followLink('))} + linkCreated={link => (link.linkDisplay = !IsFollowLinkScript(this.props.views().lastElement()?.rootDoc.onClick))} linkCreateAnchor={() => this.props.views().lastElement()?.ComponentView?.getAnchor?.(true)} linkFrom={() => this.props.views().lastElement()?.rootDoc} /> diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 9bc583ce5..9ffbe083f 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -32,6 +32,7 @@ import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox'; import { ImageBox } from './nodes/ImageBox'; import React = require('react'); import { RichTextField } from '../../fields/RichTextField'; +import { LinkFollower } from '../util/LinkFollower'; @observer export class DocumentDecorations extends React.Component<{ PanelWidth: number; PanelHeight: number; boundsLeft: number; boundsTop: number }, { value: string }> { @@ -83,10 +84,9 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P ); } - @observable overrideBounds = false; @computed get Bounds() { - if (this.overrideBounds) return { x: 0, y: 0, r: 0, b: 0 }; + if (LinkFollower.IsFollowing) return { x: 0, y: 0, r: 0, b: 0 }; const views = SelectionManager.Views(); return views .filter(dv => dv.props.renderDepth > 0) @@ -908,7 +908,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P {this._isRotating ? null : ( tap to set rotate center, drag to rotate
}>
e.preventDefault()}> - } isCircle={true} hoverStyle={'lighten'} backgroundColor={Colors.DARK_GRAY} color={Colors.LIGHT_GRAY} /> + } color={Colors.LIGHT_GRAY} />
)} diff --git a/src/client/views/MarqueeAnnotator.tsx b/src/client/views/MarqueeAnnotator.tsx index 6b4f8ad85..ede387927 100644 --- a/src/client/views/MarqueeAnnotator.tsx +++ b/src/client/views/MarqueeAnnotator.tsx @@ -15,6 +15,7 @@ import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox'; import { AnchorMenu } from './pdf/AnchorMenu'; import React = require('react'); import { ScriptField } from '../../fields/ScriptField'; +import { FollowLinkScript } from '../util/LinkFollower'; const _global = (window /* browser */ || global) /* node */ as any; export interface MarqueeAnnotatorProps { @@ -148,7 +149,7 @@ export class MarqueeAnnotator extends React.Component { const anno = savedAnnos[0]; const containerOffset = this.props.containerOffset?.() || [0, 0]; const marqueeAnno = Docs.Create.FreeformDocument([], { - onClick: isLinkButton ? ScriptField.MakeScript('followLink(this,altKey)', { altKey: 'boolean' }) : undefined, + onClick: isLinkButton ? FollowLinkScript() : undefined, backgroundColor: color, annotationOn: this.props.rootDoc, title: 'Annotation on ' + this.props.rootDoc.title, diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx index 0723966e1..031d501ad 100644 --- a/src/client/views/PropertiesButtons.tsx +++ b/src/client/views/PropertiesButtons.tsx @@ -21,6 +21,7 @@ import { DocumentView, OpenWhere } from './nodes/DocumentView'; import { pasteImageBitmap } from './nodes/WebBoxRenderer'; import './PropertiesButtons.scss'; import React = require('react'); +import { IsFollowLinkScript } from '../util/LinkFollower'; const higflyout = require('@hig/flyout'); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; @@ -289,7 +290,7 @@ export class PropertiesButtons extends React.Component<{}, {}> { .filter(dv => dv.docView) .map(dv => dv.docView!) .forEach(docView => { - const linkButton = ScriptCast(docView.props.Document.onClick)?.script.originalScript.includes('followLink('); + const linkButton = IsFollowLinkScript(docView.props.Document.onClick); docView.noOnClick(); switch (onClick) { case 'enterPortal': @@ -327,7 +328,7 @@ export class PropertiesButtons extends React.Component<{}, {}> { ]; const list = buttonList.map(value => { const click = () => this.handleOptionChange(value[0]); - const linkButton = BoolCast(ScriptCast(this.selectedDoc.onClick)?.script.originalScript.includes('followLink(')); + const linkButton = IsFollowLinkScript(this.selectedDoc.onClick); const followLoc = this.selectedDoc._followLinkLocation; const linkedToLightboxView = () => LinkManager.Links(this.selectedDoc).some(link => LinkManager.getOppositeAnchor(link, this.selectedDoc)?._isLightbox); diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx index 8d67f0528..b950b4860 100644 --- a/src/client/views/StyleProvider.tsx +++ b/src/client/views/StyleProvider.tsx @@ -1,13 +1,15 @@ import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { Tooltip } from '@material-ui/core'; import { Shadows } from 'browndash-components'; import { action, runInAction } from 'mobx'; import { extname } from 'path'; import { Doc, Opt, StrListCast } from '../../fields/Doc'; -import { BoolCast, Cast, ImageCast, NumCast, ScriptCast, StrCast } from '../../fields/Types'; +import { BoolCast, Cast, ImageCast, NumCast, StrCast } from '../../fields/Types'; import { DashColor, lightOrDark, Utils } from '../../Utils'; import { CollectionViewType, DocumentType } from '../documents/DocumentTypes'; import { DocFocusOrOpen, DocumentManager } from '../util/DocumentManager'; +import { IsFollowLinkScript } from '../util/LinkFollower'; import { LinkManager } from '../util/LinkManager'; import { SelectionManager } from '../util/SelectionManager'; import { ColorScheme, SettingsManager } from '../util/SettingsManager'; @@ -18,13 +20,10 @@ import { InkingStroke } from './InkingStroke'; import { MainView } from './MainView'; import { DocumentViewProps } from './nodes/DocumentView'; import { FieldViewProps } from './nodes/FieldView'; +import { KeyValueBox } from './nodes/KeyValueBox'; import { SliderBox } from './nodes/SliderBox'; import './StyleProvider.scss'; import React = require('react'); -import { KeyValueBox } from './nodes/KeyValueBox'; -import { listSpec } from '../../fields/Schema'; -import { AudioField } from '../../fields/URLField'; -import { Tooltip } from '@material-ui/core'; export enum StyleProp { TreeViewIcon = 'treeViewIcon', @@ -279,8 +278,7 @@ export function DefaultStyleProvider(doc: Opt, props: Opt { - if (ScriptCast(anchorDoc.onClick)?.script.originalScript.includes('followLink(')) { + if (IsFollowLinkScript(anchorDoc.onClick)) { LinkFollower.FollowLink(undefined, anchorDoc, false); } const seekTimeInSeconds = this.anchorStart(anchorDoc) - 0.05; diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index 2d12005fb..dbcfe43cf 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -146,7 +146,7 @@ export class DocumentContentsView extends React.Component< (this.props.LayoutTemplateString && this.props.Document) || (this.props.layoutKey && StrCast(this.props.Document[this.props.layoutKey]) && this.props.Document) || Doc.Layout(this.props.Document, this.props.layoutKey ? Cast(this.props.Document[this.props.layoutKey], Doc, null) : undefined); - return Doc.expandTemplateLayout(template, this.props.Document, this.props.layoutKey); + return Doc.expandTemplateLayout(template, this.props.Document); } CreateBindings(onClick: Opt, onInput: Opt): JsxBindings { diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index a39c3cf8f..f161a7b9b 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -22,7 +22,7 @@ import { DictationManager } from '../../util/DictationManager'; import { DocumentManager } from '../../util/DocumentManager'; import { DragManager, dropActionType } from '../../util/DragManager'; import { InteractionUtils } from '../../util/InteractionUtils'; -import { LinkFollower } from '../../util/LinkFollower'; +import { FollowLinkScript, LinkFollower } from '../../util/LinkFollower'; import { LinkManager } from '../../util/LinkManager'; import { ScriptingGlobals } from '../../util/ScriptingGlobals'; import { SelectionManager } from '../../util/SelectionManager'; @@ -560,14 +560,14 @@ export class DocumentViewInternal extends DocComponent { const hadOnClick = this.rootDoc.onClick; this.noOnClick(); - this.Document.onClick = hadOnClick ? undefined : ScriptField.MakeScript('followLink(this,altKey)', { altKey: 'boolean' }); + this.Document.onClick = hadOnClick ? undefined : FollowLinkScript(); this.Document.waitForDoubleClickToClick = hadOnClick ? undefined : 'never'; }; @undoBatch @action followLinkOnClick = (): void => { this.Document.ignoreClick = false; - this.Document.onClick = ScriptField.MakeScript('followLink(this,altKey)', { altKey: 'boolean' }); + this.Document.onClick = FollowLinkScript(); this.Document.followLinkToggle = false; this.Document.followLinkZoom = false; this.Document.followLinkLocation = undefined; @@ -623,7 +623,7 @@ export class DocumentViewInternal extends DocComponent { diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx index 83ad5628c..b144c9318 100644 --- a/src/client/views/nodes/VideoBox.tsx +++ b/src/client/views/nodes/VideoBox.tsx @@ -34,6 +34,7 @@ import { RecordingBox } from './RecordingBox'; import { PinProps, PresBox } from './trails'; import './VideoBox.scss'; import { ScriptField } from '../../../fields/ScriptField'; +import { FollowLinkScript } from '../../util/LinkFollower'; const path = require('path'); /** @@ -325,7 +326,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent { updateDoc = action((dashDoc: Doc) => { this._dashDoc = dashDoc; - this._finalLayout = this.props.docId ? dashDoc : Doc.expandTemplateLayout(Doc.Layout(dashDoc), dashDoc, this.props.fieldKey); + this._finalLayout = this.props.docId ? dashDoc : Doc.expandTemplateLayout(Doc.Layout(dashDoc), dashDoc); if (this._finalLayout) { if (!Doc.AreProtosEqual(this._finalLayout, dashDoc)) { diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 809315963..677c4662b 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -64,6 +64,7 @@ import { schema } from './schema_rts'; import { SummaryView } from './SummaryView'; import applyDevTools = require('prosemirror-dev-tools'); import React = require('react'); +import { IsFollowLinkScript } from '../../../util/LinkFollower'; const translateGoogleApi = require('translate-google-api'); export const GoogleRef = 'googleDocId'; @@ -1933,7 +1934,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index 3a5ba4f75..662792ff0 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -906,57 +906,40 @@ export namespace Doc { saveAs(content, doc.title + '.zip'); // glr: Possibly change the name of the document to match the title? }); } - // - // Determines whether the layout needs to be expanded (as a template). - // template expansion is rquired when the layout is a template doc/field and there's a datadoc which isn't equal to the layout template - // - export function WillExpandTemplateLayout(layoutDoc: Doc, dataDoc?: Doc) { - return (layoutDoc.isTemplateForField || layoutDoc.isTemplateDoc) && dataDoc && layoutDoc !== dataDoc; - } const _pendingMap: Map = new Map(); // // Returns an expanded template layout for a target data document if there is a template relationship // between the two. If so, the layoutDoc is expanded into a new document that inherits the properties // of the original layout while allowing for individual layout properties to be overridden in the expanded layout. - // templateArgs should be equivalent to the layout key that generates the template since that's where the template parameters are stored in ()'s at the end of the key. - // NOTE: the template will have references to "@params" -- the template arguments will be assigned to the '@params' field - // so that when the @params key is accessed, it will be rewritten as the key that is stored in the 'params' field and - // the derefence will then occur on the rootDocument (the original document). - // in the future, field references could be written as @ and then arguments would be passed in the layout key as: - // layout_mytemplate(somparam=somearg). - // then any references to @someparam would be rewritten as accesses to 'somearg' on the rootDocument - export function expandTemplateLayout(templateLayoutDoc: Doc, targetDoc?: Doc, templateArgs?: string) { - const args = templateArgs?.match(/\(([a-zA-Z0-9._\-]*)\)/)?.[1].replace('()', '') || ''; - if ((!args && !WillExpandTemplateLayout(templateLayoutDoc, targetDoc)) || !targetDoc) return templateLayoutDoc; - - const templateField = StrCast(templateLayoutDoc.isTemplateForField); // the field that the template renders + export function expandTemplateLayout(templateLayoutDoc: Doc, targetDoc?: Doc) { + // nothing to do if the layout isn't a template or we don't have a target that's different than the template + if (!targetDoc || templateLayoutDoc === targetDoc || (!templateLayoutDoc.isTemplateForField && !templateLayoutDoc.isTemplateDoc)) { + return templateLayoutDoc; + } + + const templateField = StrCast(templateLayoutDoc.isTemplateForField, Doc.LayoutFieldKey(templateLayoutDoc)); // the field that the template renders // First it checks if an expanded layout already exists -- if so it will be stored on the dataDoc // using the template layout doc's id as the field key. // If it doesn't find the expanded layout, then it makes a delegate of the template layout and // saves it on the data doc indexed by the template layout's id. // - const params = args.split('=').length > 1 ? args.split('=')[0] : ''; - const layoutFielddKey = Doc.LayoutFieldKey(templateLayoutDoc); - const expandedLayoutFieldKey = (templateField || layoutFielddKey) + '-layout[' + templateLayoutDoc[Id] + (args ? `(${args})` : '') + ']'; + const expandedLayoutFieldKey = templateField + '-layout[' + templateLayoutDoc[Id] + ']'; let expandedTemplateLayout = targetDoc?.[expandedLayoutFieldKey]; if (templateLayoutDoc.resolvedDataDoc instanceof Promise) { expandedTemplateLayout = undefined; _pendingMap.set(targetDoc[Id] + expandedLayoutFieldKey, true); - } else if (expandedTemplateLayout === undefined && !_pendingMap.get(targetDoc[Id] + expandedLayoutFieldKey + args)) { + } else if (expandedTemplateLayout === undefined && !_pendingMap.get(targetDoc[Id] + expandedLayoutFieldKey)) { if (templateLayoutDoc.resolvedDataDoc === (targetDoc.rootDocument || Doc.GetProto(targetDoc))) { expandedTemplateLayout = templateLayoutDoc; // reuse an existing template layout if its for the same document with the same params } else { templateLayoutDoc.resolvedDataDoc && (templateLayoutDoc = Cast(templateLayoutDoc.proto, Doc, null) || templateLayoutDoc); // if the template has already been applied (ie, a nested template), then use the template's prototype if (!targetDoc[expandedLayoutFieldKey]) { - _pendingMap.set(targetDoc[Id] + expandedLayoutFieldKey + args, true); + _pendingMap.set(targetDoc[Id] + expandedLayoutFieldKey, true); setTimeout( action(() => { const newLayoutDoc = Doc.MakeDelegate(templateLayoutDoc, undefined, '[' + templateLayoutDoc.title + ']'); - // the template's arguments are stored in params which is derefenced to find - // the actual field key where the parameterized template data is stored. - newLayoutDoc[params] = args !== '...' ? args : ''; // ... signifies the layout has sub template(s) -- so we have to expand the layout for them so that they can get the correct 'rootDocument' field, but we don't need to reassign their params. it would be better if the 'rootDocument' field could be passed dynamically to avoid have to create instances newLayoutDoc.rootDocument = targetDoc; const dataDoc = Doc.GetProto(targetDoc); newLayoutDoc.resolvedDataDoc = dataDoc; @@ -965,7 +948,7 @@ export namespace Doc { } targetDoc[expandedLayoutFieldKey] = newLayoutDoc; - _pendingMap.delete(targetDoc[Id] + expandedLayoutFieldKey + args); + _pendingMap.delete(targetDoc[Id] + expandedLayoutFieldKey); }) ); } @@ -982,7 +965,7 @@ export namespace Doc { return { layout: childDoc, data: childDoc }; } const resolvedDataDoc = Doc.AreProtosEqual(containerDataDoc, containerDoc) || (!childDoc.isTemplateDoc && !childDoc.isTemplateForField) ? undefined : containerDataDoc; - return { layout: Doc.expandTemplateLayout(childDoc, resolvedDataDoc, '()'), data: resolvedDataDoc }; + return { layout: Doc.expandTemplateLayout(childDoc, resolvedDataDoc), data: resolvedDataDoc }; } export function Overwrite(doc: Doc, overwrite: Doc, copyProto: boolean = false): Doc { -- cgit v1.2.3-70-g09d2 From 7342eb81f241ce0b2a5a33ddfb0c865eab6a492f Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 27 Apr 2023 09:10:36 -0400 Subject: added proper scaling of multi-selections and groups. fixed pinViewport to work again. --- src/client/util/CurrentUserUtils.ts | 2 +- src/client/views/DocumentButtonBar.tsx | 4 - src/client/views/DocumentDecorations.tsx | 112 ++++++++++++--------- src/client/views/collections/TabDocView.tsx | 1 + .../collections/collectionFreeForm/MarqueeView.tsx | 5 +- src/client/views/nodes/DocumentView.tsx | 10 +- src/client/views/nodes/button/FontIconBox.tsx | 6 +- .../views/nodes/formattedText/RichTextRules.ts | 2 +- src/client/views/nodes/formattedText/marks_rts.ts | 2 +- src/client/views/nodes/trails/PresBox.tsx | 1 + 10 files changed, 80 insertions(+), 65 deletions(-) (limited to 'src/client/views/DocumentButtonBar.tsx') diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 5475873a9..479fcd011 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -621,8 +621,8 @@ export class CurrentUserUtils { } static viewTools(): Button[] { return [ - { title: "Grid", icon: "border-all", toolTip: "Show Grid", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"grid", funcs: {}, scripts: { onClick: 'showFreeform(self.toolType, _readOnly_)'}}, // Only when floating document is selected in freeform { title: "Snap\xA0Lines", icon: "th", toolTip: "Show Snap Lines", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"snap lines", funcs: {}, scripts: { onClick: 'showFreeform(self.toolType, _readOnly_)'}}, // Only when floating document is selected in freeform + { title: "Grid", icon: "border-all", toolTip: "Show Grid", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"grid", funcs: {}, scripts: { onClick: 'showFreeform(self.toolType, _readOnly_)'}}, // Only when floating document is selected in freeform { title: "View\xA0All", icon: "object-group", toolTip: "Fit all Docs to View",btnType: ButtonType.ToggleButton, expertMode: false, toolType:"viewAll", funcs: {}, scripts: { onClick: 'showFreeform(self.toolType, _readOnly_)'}}, // Only when floating document is selected in freeform { title: "Clusters", icon: "braille", toolTip: "Show Doc Clusters", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"clusters", funcs: {}, scripts: { onClick: 'showFreeform(self.toolType, _readOnly_)'}}, // Only when floating document is selected in freeform { title: "Arrange",icon: "arrow-down-short-wide",toolTip: "Toggle Auto Arrange",btnType: ButtonType.ToggleButton, expertMode: false, toolType:"arrange", funcs: {hidden: 'IsNoviceMode()'}, scripts: { onClick: 'showFreeform(self.toolType, _readOnly_)'}}, // Only when floating document is selected in freeform diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx index 8c2ced55a..30e41b06c 100644 --- a/src/client/views/DocumentButtonBar.tsx +++ b/src/client/views/DocumentButtonBar.tsx @@ -303,10 +303,6 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV onPointerEnter={action(e => (this.subEndLink = (pinLayout ? 'Layout' : '') + (pinLayout && pinContent ? ' &' : '') + (pinContent ? ' Content' : '')))} onPointerLeave={action(e => (this.subEndLink = ''))} onClick={e => { - const docs = this.props - .views() - .filter(v => v) - .map(dv => dv!.rootDoc); this.view0 && DocumentLinksButton.finishLinkClick(e.clientX, e.clientY, DocumentLinksButton.StartLink, this.view0.props.Document, true, this.view0, { pinDocLayout: pinLayout, diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 042e8f6d0..2811c96eb 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -12,7 +12,7 @@ import { InkField } from '../../fields/InkField'; import { ScriptField } from '../../fields/ScriptField'; import { Cast, NumCast, StrCast } from '../../fields/Types'; import { GetEffectiveAcl } from '../../fields/util'; -import { emptyFunction, numberValue, returnFalse, setupMoveUpEvents, Utils } from '../../Utils'; +import { aggregateBounds, emptyFunction, numberValue, returnFalse, setupMoveUpEvents, Utils } from '../../Utils'; import { Docs } from '../documents/Documents'; import { DocumentType } from '../documents/DocumentTypes'; import { DragManager } from '../util/DragManager'; @@ -34,6 +34,7 @@ import React = require('react'); import { RichTextField } from '../../fields/RichTextField'; import { LinkFollower } from '../util/LinkFollower'; import _ = require('lodash'); +import { DocumentManager } from '../util/DocumentManager'; @observer export class DocumentDecorations extends React.Component<{ PanelWidth: number; PanelHeight: number; boundsLeft: number; boundsTop: number }, { value: string }> { @@ -509,73 +510,86 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P dragRight = false, dragBotRight = false, dragTop = false; - let dX = 0, - dY = 0, - dW = 0, - dH = 0; + let dXin = 0, + dYin = 0, + dWin = 0, + dHin = 0; switch (this._resizeHdlId.split(' ')[0]) { case '': break; case 'documentDecorations-topLeftResizer': - dX = -1; - dY = -1; - dW = -move[0]; - dH = -move[1]; + dXin = -1; + dYin = -1; + dWin = -move[0]; + dHin = -move[1]; break; case 'documentDecorations-topRightResizer': - dW = move[0]; - dY = -1; - dH = -move[1]; + dWin = move[0]; + dYin = -1; + dHin = -move[1]; break; case 'documentDecorations-topResizer': - dY = -1; - dH = -move[1]; + dYin = -1; + dHin = -move[1]; dragTop = true; break; case 'documentDecorations-bottomLeftResizer': - dX = -1; - dW = -move[0]; - dH = move[1]; + dXin = -1; + dWin = -move[0]; + dHin = move[1]; break; case 'documentDecorations-bottomRightResizer': - dW = move[0]; - dH = move[1]; + dWin = move[0]; + dHin = move[1]; dragBotRight = true; break; case 'documentDecorations-bottomResizer': - dH = move[1]; + dHin = move[1]; dragBottom = true; break; case 'documentDecorations-leftResizer': - dX = -1; - dW = -move[0]; + dXin = -1; + dWin = -move[0]; break; case 'documentDecorations-rightResizer': - dW = move[0]; + dWin = move[0]; dragRight = true; break; } - SelectionManager.Views().forEach( + const isGroup = first.rootDoc._isGroup ? first.rootDoc : undefined; + const scaleViews = isGroup ? DocListCast(isGroup.data).map(doc => DocumentManager.Instance.getFirstDocumentView(doc)!) : SelectionManager.Views(); + const aggBounds = aggregateBounds(scaleViews.map(view => view.rootDoc) as any, 0, 0); + const refWidth = aggBounds.r - aggBounds.x; + const refHeight = aggBounds.b - aggBounds.y; + const scaleRefPt = first.props + .ScreenToLocalTransform() + .inverse() + .transformPoint( + NumCast(isGroup?._xPadding) + (dXin ? refWidth : 0), // + NumCast(isGroup?._yPadding) + (dYin ? refHeight : 0) + ); + scaleViews.forEach( action((docView: DocumentView) => { if (e.ctrlKey && !Doc.NativeHeight(docView.props.Document)) docView.toggleNativeDimensions(); - if (dX !== 0 || dY !== 0 || dW !== 0 || dH !== 0) { - const doc = Document(docView.rootDoc); + if (dXin !== 0 || dYin !== 0 || dWin !== 0 || dHin !== 0) { + const doc = docView.rootDoc; + const refCent = docView.props.ScreenToLocalTransform().transformPoint(scaleRefPt[0], scaleRefPt[1]); + if (doc.nativeHeightUnfrozen && !NumCast(doc.nativeHeight)) { doc._nativeHeight = (NumCast(doc._height) / NumCast(doc._width, 1)) * docView.nativeWidth; } const nwidth = docView.nativeWidth; const nheight = docView.nativeHeight; - let docheight = doc._height || 0; - let docwidth = doc._width || 0; - const width = docwidth; - let height = docheight || (nheight / nwidth) * width; - height = !height || isNaN(height) ? 20 : height; + const docwidth = NumCast(doc._width); + let docheight = (hgt => (!hgt || isNaN(hgt) ? 20 : hgt))(NumCast(doc._height) || (nheight / nwidth) * docwidth); + let dW = docwidth * (dWin / refWidth); + let dH = docheight * (dHin / refHeight); const scale = docView.props.ScreenToLocalTransform().Scale; const modifyNativeDim = (e.ctrlKey || doc.forceReflow) && doc.nativeDimModifiable && ((!dragBottom && !dragTop) || e.ctrlKey || doc.nativeHeightUnfrozen); if (nwidth && nheight) { - if (nwidth / nheight !== width / height && !dragBottom && !dragTop) { - height = (nheight / nwidth) * width; + if (nwidth / nheight !== docwidth / docheight && !dragBottom && !dragTop) { + docheight = (nheight / nwidth) * docwidth; } if (modifyNativeDim && !dragBottom && !dragTop) { // ctrl key enables modification of the nativeWidth or nativeHeight durin the interaction @@ -583,21 +597,25 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P else dW = (dH * nwidth) / nheight; } } - let actualdW = Math.max(width + dW * scale, 20); - let actualdH = Math.max(height + dH * scale, 20); + let actualdW = Math.max(docwidth + dW * scale, 20); + let actualdH = Math.max(docheight + dH * scale, 20); + let dX = !dWin ? 0 : scale * refCent[0] * (1 - (1 + dWin / refWidth)); + let dY = !dHin ? 0 : scale * refCent[1] * (1 - (1 + dHin / refHeight)); const preserveNativeDim = doc._nativeHeightUnfrozen === false && doc._nativeDimModifiable === false; const fixedAspect = nwidth && nheight && (!doc._fitWidth || preserveNativeDim || e.ctrlKey || doc.nativeHeightUnfrozen || doc.nativeDimModifiable); if (fixedAspect) { if ((Math.abs(dW) > Math.abs(dH) && ((!dragBottom && !dragTop) || !modifyNativeDim)) || dragRight) { if (dragRight && modifyNativeDim) { if (Doc.NativeWidth(doc)) { - doc._nativeWidth = (actualdW / (doc._width || 1)) * Doc.NativeWidth(doc); + doc._nativeWidth = (actualdW / (docwidth || 1)) * Doc.NativeWidth(doc); } } else { if (!doc._fitWidth || preserveNativeDim) { actualdH = (nheight / nwidth) * actualdW; doc._height = actualdH; - } else if (!modifyNativeDim || dragBotRight) doc._height = actualdH; + } else if (!modifyNativeDim || dragBotRight) { + doc._height = actualdH; + } } doc._width = actualdW; } else { @@ -605,21 +623,23 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P // frozen web pages, PDFs, and some RTFS have frozen nativewidth/height. But they are marked to allow their nativeHeight // to be explicitly modified with fitWidth and vertical resizing. (ie, with fitWidth they can't grow horizontally to match // a vertical resize so it makes more sense to change their nativeheight even if the ctrl key isn't used) - doc._nativeHeight = (actualdH / (doc._height || 1)) * Doc.NativeHeight(doc); + doc._nativeHeight = (actualdH / (docheight || 1)) * Doc.NativeHeight(doc); doc._autoHeight = false; } else { if (!doc._fitWidth || preserveNativeDim) { actualdW = (nwidth / nheight) * actualdH; doc._width = actualdW; - } else if (!modifyNativeDim || dragBotRight) doc._width = actualdW; + } else if (!modifyNativeDim || dragBotRight) { + doc._width = actualdW; + } } if (!modifyNativeDim) { - actualdH = Math.min((nheight / nwidth) * NumCast(doc._width), actualdH); - doc._height = actualdH; - } else doc._height = actualdH; + actualdH = Math.min((nheight / nwidth) * docwidth, actualdH); + } + doc._height = actualdH; } } else { - const rotCtr = [NumCast(doc._width) / 2, NumCast(doc._height) / 2]; + const rotCtr = [docwidth / 2, docheight / 2]; const tlRotated = Utils.rotPt(-rotCtr[0], -rotCtr[1], (NumCast(doc._rotation) / 180) * Math.PI); const maxHeight = doc.nativeHeightUnfrozen || !nheight ? 0 : Math.max(nheight, NumCast(doc.scrollHeight, NumCast(doc[docView.LayoutFieldKey + '-scrollHeight']))) * docView.NativeDimScaling(); @@ -632,8 +652,8 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P doc.x = NumCast(doc.x) + tlRotated.x + rotCtr[0] - (tlRotated2.x + rotCtr2[0]); // doc shifts by amount topleft moves because rotation is about center of doc doc.y = NumCast(doc.y) + tlRotated.y + rotCtr[1] - (tlRotated2.y + rotCtr2[1]); } - doc.x = (doc.x || 0) + dX * (actualdW - docwidth); - doc.y = (doc.y || 0) + (dragBottom ? 0 : dY * (actualdH - docheight)); + doc.x = NumCast(doc.x) + dX; + doc.y = NumCast(doc.y) + dY; doc._lastModified = new DateField(); } const val = this._dragHeights.get(docView.layoutDoc); @@ -726,7 +746,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P } // hide the decorations if the parent chooses to hide it or if the document itself hides it const hideDecorations = seldocview.props.hideDecorations || seldocview.rootDoc.hideDecorations; - const hideResizers = hideDecorations || seldocview.props.hideResizeHandles || seldocview.rootDoc.hideResizeHandles || seldocview.rootDoc._isGroup || this._isRounding || this._isRotating; + const hideResizers = hideDecorations || seldocview.props.hideResizeHandles || seldocview.rootDoc.hideResizeHandles || this._isRounding || this._isRotating; const hideTitle = hideDecorations || seldocview.props.hideDecorationTitle || seldocview.rootDoc.hideDecorationTitle || this._isRounding || this._isRotating; const hideDocumentButtonBar = hideDecorations || seldocview.props.hideDocumentButtonBar || seldocview.rootDoc.hideDocumentButtonBar || this._isRounding || this._isRotating; // if multiple documents have been opened at the same time, then don't show open button diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx index 4bbc3bb44..45604c1bf 100644 --- a/src/client/views/collections/TabDocView.tsx +++ b/src/client/views/collections/TabDocView.tsx @@ -266,6 +266,7 @@ export class TabDocView extends React.Component { pinDoc.treeViewHideHeaderIfTemplate = true; // this will force the document to render itself as the tree view header const duration = NumCast(doc[`${Doc.LayoutFieldKey(pinDoc)}-duration`], null); + if (pinProps.pinViewport) PresBox.pinDocView(pinDoc, pinProps, anchorDoc ?? doc); if (!pinProps?.audioRange && duration !== undefined) { pinDoc.mediaStart = 'manual'; pinDoc.mediaStop = 'manual'; diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index eaeb5f933..e5f47823c 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -425,9 +425,8 @@ export class MarqueeView extends React.Component { - const doc = this.props.Document; - TabDocView.PinDoc(doc, { pinViewport: this.Bounds }); + pinWithView = () => { + TabDocView.PinDoc(this.props.Document, { pinViewport: this.Bounds }); MarqueeOptionsMenu.Instance.fadeOut(true); this.hideMarquee(); }; diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index c957bc778..a25e5c42d 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -765,9 +765,8 @@ export class DocumentViewInternal extends DocComponent this.props.addDocTab(this.props.Document, (OpenWhere.addRight.toString() + 'KeyValue') as OpenWhere), icon: 'layer-group' }); if (!Doc.IsSystem(this.rootDoc)) { - constantItems.push({ description: 'Show Metadata', event: () => this.props.addDocTab(this.props.Document, (OpenWhere.addRight.toString() + 'KeyValue') as OpenWhere), icon: 'layer-group' }); constantItems.push({ description: 'Export as Zip file', icon: 'download', event: async () => Doc.Zip(this.props.Document) }); constantItems.push({ description: 'Import Zipped file', icon: 'upload', event: ({ x, y }) => this.importDocument() }); (this.rootDoc._viewType !== CollectionViewType.Docking || !Doc.noviceMode) && constantItems.push({ description: 'Share', event: () => SharingManager.Instance.open(this.props.DocumentView()), icon: 'users' }); @@ -775,8 +774,9 @@ export class DocumentViewInternal extends DocComponent this.props.addDocTab(Docs.Create.PdfDocument('/assets/cheat-sheet.pdf', { _width: 300, _height: 300 }), OpenWhere.addRight), icon: 'keyboard' }); @@ -819,9 +819,7 @@ export class DocumentViewInternal extends DocComponent { - window.open(documentationLink, '_blank'); - }, + event: () => window.open(documentationLink, '_blank'), icon: 'book', }); } diff --git a/src/client/views/nodes/button/FontIconBox.tsx b/src/client/views/nodes/button/FontIconBox.tsx index 1a75a7e76..4f570b5fc 100644 --- a/src/client/views/nodes/button/FontIconBox.tsx +++ b/src/client/views/nodes/button/FontIconBox.tsx @@ -610,16 +610,16 @@ ScriptingGlobals.add(function toggleOverlay(checkResult?: boolean) { selected ? selected.props.CollectionFreeFormDocumentView?.().float() : console.log('[FontIconBox.tsx] toggleOverlay failed'); }); -ScriptingGlobals.add(function showFreeform(attr: 'grid' | 'snap lines' | 'clusters' | 'arrange' | 'viewAll', checkResult?: boolean) { +ScriptingGlobals.add(function showFreeform(attr: 'grid' | 'snapline' | 'clusters' | 'arrange' | 'viewAll', checkResult?: boolean) { const selected = SelectionManager.Docs().lastElement(); // prettier-ignore - const map: Map<'grid' | 'snap lines' | 'clusters' | 'arrange'| 'viewAll', { undo: boolean, checkResult: (doc:Doc) => any; setDoc: (doc:Doc) => void;}> = new Map([ + const map: Map<'grid' | 'snapline' | 'clusters' | 'arrange'| 'viewAll', { undo: boolean, checkResult: (doc:Doc) => any; setDoc: (doc:Doc) => void;}> = new Map([ ['grid', { undo: false, checkResult: (doc:Doc) => doc._backgroundGridShow, setDoc: (doc:Doc) => doc._backgroundGridShow = !doc._backgroundGridShow, }], - ['snap lines', { + ['snapline', { undo: false, checkResult: (doc:Doc) => doc.showSnapLines, setDoc: (doc:Doc) => doc._showSnapLines = !doc._showSnapLines, diff --git a/src/client/views/nodes/formattedText/RichTextRules.ts b/src/client/views/nodes/formattedText/RichTextRules.ts index 20ce929ad..e5943f257 100644 --- a/src/client/views/nodes/formattedText/RichTextRules.ts +++ b/src/client/views/nodes/formattedText/RichTextRules.ts @@ -391,7 +391,7 @@ export class RichTextRules { const content = selected.selection.content(); const replaced = node ? selected.replaceRangeWith(start, end, schema.nodes.summary.create({ visibility: true, text: content, textslice: content.toJSON() })) : state.tr; - return replaced.setSelection(new TextSelection(replaced.doc.resolve(end + 1))).setStoredMarks([...node.marks, ...sm]); + return replaced.setSelection(new TextSelection(replaced.doc.resolve(end))).setStoredMarks([...node.marks, ...sm]); }), new InputRule(new RegExp(/%\)/), (state, match, start, end) => { diff --git a/src/client/views/nodes/formattedText/marks_rts.ts b/src/client/views/nodes/formattedText/marks_rts.ts index 3898490d3..5b47e8a70 100644 --- a/src/client/views/nodes/formattedText/marks_rts.ts +++ b/src/client/views/nodes/formattedText/marks_rts.ts @@ -349,7 +349,7 @@ export const marks: { [index: string]: MarkSpec } = { group: 'inline', toDOM(node: any) { const uid = node.attrs.userid.replace('.', '').replace('@', ''); - const min = Math.round(node.attrs.modified / 12); + const min = Math.round(node.attrs.modified / 60); const hr = Math.round(min / 60); const day = Math.round(hr / 60 / 24); const remote = node.attrs.userid !== Doc.CurrentUserEmail ? ' UM-remote' : ''; diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx index f8c47aafe..0b780f589 100644 --- a/src/client/views/nodes/trails/PresBox.tsx +++ b/src/client/views/nodes/trails/PresBox.tsx @@ -567,6 +567,7 @@ export class PresBox extends ViewBoxBaseComponent() { bestTarget._panY = viewport.panY; const dv = DocumentManager.Instance.getDocumentView(bestTarget); if (dv) { + changed = true; const computedScale = NumCast(activeItem.presZoom, 1) * Math.min(dv.props.PanelWidth() / viewport.width, dv.props.PanelHeight() / viewport.height); activeItem.presMovement === PresMovement.Zoom && (bestTarget._viewScale = computedScale); dv.ComponentView?.brushView?.(viewport); -- cgit v1.2.3-70-g09d2 From 42afc0250de658fc3e924864bfae5afb4edec335 Mon Sep 17 00:00:00 2001 From: bobzel Date: Sun, 14 May 2023 12:03:40 -0400 Subject: major overhaul of field naming conventions. --- .../apis/google_docs/GooglePhotosClientUtils.ts | 88 +++--- src/client/documents/DocumentTypes.ts | 2 +- src/client/documents/Documents.ts | 324 ++++++++++----------- src/client/documents/Gitlike.ts | 26 +- src/client/util/CaptureManager.tsx | 2 +- src/client/util/CurrentUserUtils.ts | 179 ++++++------ src/client/util/DictationManager.ts | 2 +- src/client/util/DocumentManager.ts | 22 +- src/client/util/DragManager.ts | 12 +- src/client/util/DropConverter.ts | 4 +- src/client/util/GroupManager.tsx | 8 +- src/client/util/HypothesisUtils.ts | 2 +- src/client/util/Import & Export/ImageUtils.ts | 32 +- src/client/util/InteractionUtils.tsx | 1 + src/client/util/LinkFollower.ts | 34 +-- src/client/util/LinkManager.ts | 32 +- src/client/util/ReplayMovements.ts | 4 +- src/client/util/SearchUtil.ts | 94 +++--- src/client/util/SettingsManager.tsx | 4 +- src/client/util/SharingManager.tsx | 4 +- src/client/util/SnappingManager.ts | 4 +- src/client/util/TrackMovements.ts | 2 +- src/client/views/AudioWaveform.tsx | 124 ++++---- src/client/views/DashboardView.tsx | 18 +- src/client/views/DocComponent.tsx | 21 +- src/client/views/DocumentButtonBar.tsx | 22 +- src/client/views/DocumentDecorations.tsx | 70 ++--- src/client/views/FilterPanel.tsx | 6 +- src/client/views/GestureOverlay.tsx | 14 +- src/client/views/GlobalKeyHandler.ts | 4 +- src/client/views/InkStrokeProperties.ts | 14 +- src/client/views/InkTranscription.tsx | 2 +- src/client/views/InkingStroke.tsx | 30 +- src/client/views/LightboxView.tsx | 44 +-- src/client/views/MainView.tsx | 32 +- src/client/views/MarqueeAnnotator.tsx | 12 +- src/client/views/PreviewCursor.tsx | 2 +- src/client/views/PropertiesButtons.tsx | 36 +-- .../views/PropertiesDocBacklinksSelector.tsx | 2 +- src/client/views/PropertiesDocContextSelector.tsx | 10 +- src/client/views/PropertiesView.tsx | 78 ++--- src/client/views/SidebarAnnos.tsx | 20 +- src/client/views/StyleProvider.tsx | 38 +-- src/client/views/TemplateMenu.tsx | 4 +- src/client/views/animationtimeline/Timeline.tsx | 14 +- src/client/views/animationtimeline/Track.tsx | 261 +++++++++-------- .../views/collections/CollectionCarouselView.tsx | 14 +- .../views/collections/CollectionDockingView.tsx | 22 +- .../collections/CollectionMasonryViewFieldRow.tsx | 44 +-- src/client/views/collections/CollectionMenu.tsx | 85 +++--- .../views/collections/CollectionNoteTakingView.tsx | 78 ++--- .../collections/CollectionNoteTakingViewColumn.tsx | 23 +- .../views/collections/CollectionPileView.tsx | 6 +- .../collections/CollectionStackedTimeline.tsx | 39 +-- .../views/collections/CollectionStackingView.tsx | 82 +++--- .../CollectionStackingViewFieldColumn.tsx | 30 +- src/client/views/collections/CollectionSubView.tsx | 14 +- .../views/collections/CollectionTimeView.tsx | 8 +- .../views/collections/CollectionTreeView.tsx | 28 +- src/client/views/collections/CollectionView.tsx | 16 +- src/client/views/collections/TabDocView.tsx | 34 +-- src/client/views/collections/TreeView.tsx | 64 ++-- .../CollectionFreeFormLinkView.tsx | 62 ++-- .../collectionFreeForm/CollectionFreeFormView.tsx | 186 ++++++------ .../collections/collectionFreeForm/MarqueeView.tsx | 32 +- .../collectionSchema/CollectionSchemaView.tsx | 34 +-- .../collections/collectionSchema/SchemaRowBox.tsx | 2 +- .../collectionSchema/SchemaTableCell.tsx | 4 +- src/client/views/linking/LinkMenuGroup.tsx | 21 +- src/client/views/linking/LinkMenuItem.tsx | 30 +- .../views/linking/LinkRelationshipSearch.tsx | 52 ++-- src/client/views/nodes/AudioBox.tsx | 37 +-- .../views/nodes/CollectionFreeFormDocumentView.tsx | 16 +- src/client/views/nodes/ColorBox.tsx | 4 +- src/client/views/nodes/ComparisonBox.tsx | 28 +- src/client/views/nodes/DataVizBox/DataVizBox.tsx | 18 +- .../nodes/DataVizBox/components/LineChart.tsx | 14 +- .../views/nodes/DataVizBox/components/TableBox.tsx | 12 +- src/client/views/nodes/DocumentContentsView.tsx | 12 +- src/client/views/nodes/DocumentLinksButton.tsx | 6 +- src/client/views/nodes/DocumentView.tsx | 145 ++++----- src/client/views/nodes/EquationBox.tsx | 2 +- src/client/views/nodes/FieldView.tsx | 2 +- src/client/views/nodes/FunctionPlotBox.tsx | 2 +- src/client/views/nodes/ImageBox.tsx | 90 +++--- src/client/views/nodes/KeyValueBox.tsx | 32 +- src/client/views/nodes/KeyValuePair.scss | 4 + src/client/views/nodes/KeyValuePair.tsx | 6 +- src/client/views/nodes/LabelBox.tsx | 8 +- src/client/views/nodes/LinkAnchorBox.tsx | 16 +- src/client/views/nodes/LinkBox.tsx | 4 +- src/client/views/nodes/LinkDescriptionPopup.tsx | 2 +- src/client/views/nodes/LinkDocPreview.tsx | 20 +- src/client/views/nodes/MapBox/MapBox.tsx | 42 +-- src/client/views/nodes/MapBox/MapBox2.tsx | 42 +-- src/client/views/nodes/MapBox/MapBoxInfoWindow.tsx | 6 +- src/client/views/nodes/PDFBox.tsx | 72 ++--- .../views/nodes/RecordingBox/RecordingBox.tsx | 2 +- src/client/views/nodes/ScreenshotBox.tsx | 10 +- src/client/views/nodes/ScriptingBox.tsx | 10 +- src/client/views/nodes/VideoBox.tsx | 102 +++---- src/client/views/nodes/WebBox.tsx | 123 ++++---- src/client/views/nodes/button/FontIconBox.tsx | 245 ++++++++-------- .../views/nodes/formattedText/DashDocView.tsx | 45 +-- .../views/nodes/formattedText/DashFieldView.tsx | 13 +- .../views/nodes/formattedText/FormattedTextBox.tsx | 223 +++++++------- .../views/nodes/formattedText/RichTextMenu.tsx | 14 +- .../views/nodes/formattedText/RichTextRules.ts | 28 +- src/client/views/nodes/formattedText/nodes_rts.ts | 2 +- src/client/views/nodes/trails/PresBox.tsx | 101 ++++--- src/client/views/nodes/trails/PresElementBox.tsx | 8 +- src/client/views/pdf/GPTPopup/GPTPopup.tsx | 4 +- src/client/views/pdf/PDFViewer.tsx | 56 ++-- src/client/views/search/SearchBox.tsx | 44 +-- src/fields/Doc.ts | 117 ++++---- src/fields/RichTextUtils.ts | 6 +- src/fields/Types.ts | 5 +- src/fields/documentSchemas.ts | 52 ++-- src/fields/util.ts | 4 +- src/mobile/AudioUpload.tsx | 10 +- src/server/ApiManagers/SearchManager.ts | 151 +++++----- src/server/updateProtos.ts | 24 +- src/server/websocket.ts | 4 +- 123 files changed, 2424 insertions(+), 2391 deletions(-) (limited to 'src/client/views/DocumentButtonBar.tsx') diff --git a/src/client/apis/google_docs/GooglePhotosClientUtils.ts b/src/client/apis/google_docs/GooglePhotosClientUtils.ts index ff9460b62..e8fd8fb8a 100644 --- a/src/client/apis/google_docs/GooglePhotosClientUtils.ts +++ b/src/client/apis/google_docs/GooglePhotosClientUtils.ts @@ -1,27 +1,26 @@ -import { AssertionError } from "assert"; -import { EditorState } from "prosemirror-state"; -import { Doc, DocListCastAsync, Opt } from "../../../fields/Doc"; -import { Id } from "../../../fields/FieldSymbols"; -import { RichTextField } from "../../../fields/RichTextField"; -import { RichTextUtils } from "../../../fields/RichTextUtils"; -import { Cast, StrCast } from "../../../fields/Types"; -import { ImageField } from "../../../fields/URLField"; -import { MediaItem, NewMediaItemResult } from "../../../server/apis/google/SharedTypes"; -import { Utils } from "../../../Utils"; -import { Docs, DocumentOptions, DocUtils } from "../../documents/Documents"; -import { Networking } from "../../Network"; -import { FormattedTextBox } from "../../views/nodes/formattedText/FormattedTextBox"; -import { GoogleAuthenticationManager } from "../GoogleAuthenticationManager"; +import { AssertionError } from 'assert'; +import { EditorState } from 'prosemirror-state'; +import { Doc, DocListCastAsync, Opt } from '../../../fields/Doc'; +import { Id } from '../../../fields/FieldSymbols'; +import { RichTextField } from '../../../fields/RichTextField'; +import { RichTextUtils } from '../../../fields/RichTextUtils'; +import { Cast, StrCast } from '../../../fields/Types'; +import { ImageField } from '../../../fields/URLField'; +import { MediaItem, NewMediaItemResult } from '../../../server/apis/google/SharedTypes'; +import { Utils } from '../../../Utils'; +import { Docs, DocumentOptions, DocUtils } from '../../documents/Documents'; +import { Networking } from '../../Network'; +import { FormattedTextBox } from '../../views/nodes/formattedText/FormattedTextBox'; +import { GoogleAuthenticationManager } from '../GoogleAuthenticationManager'; import Photos = require('googlephotos'); export namespace GooglePhotos { - const endpoint = async () => new Photos(await GoogleAuthenticationManager.Instance.fetchOrGenerateAccessToken()); export enum MediaType { ALL_MEDIA = 'ALL_MEDIA', PHOTO = 'PHOTO', - VIDEO = 'VIDEO' + VIDEO = 'VIDEO', } export type AlbumReference = { id: string } | { title: string }; @@ -58,11 +57,10 @@ export namespace GooglePhotos { HOUSES: 'HOUSES', GARDENS: 'GARDENS', FLOWERS: 'FLOWERS', - HOLIDAYS: 'HOLIDAYS' + HOLIDAYS: 'HOLIDAYS', }; export namespace Export { - export interface AlbumCreationResult { albumId: string; mediaItems: MediaItem[]; @@ -82,20 +80,20 @@ export namespace GooglePhotos { if (!images || !images.length) { return undefined; } - const resolved = title ? title : (StrCast(collection.title) || `Dash Collection (${collection[Id]}`); + const resolved = title ? title : StrCast(collection.title) || `Dash Collection (${collection[Id]}`; const { id, productUrl } = await Create.Album(resolved); const response = await Transactions.UploadImages(images, { id }, descriptionKey); if (response) { const { results, failed } = response; let index: Opt; while ((index = failed.pop()) !== undefined) { - Doc.RemoveDocFromList(dataDocument, "data", images.splice(index, 1)[0]); + Doc.RemoveDocFromList(dataDocument, 'data', images.splice(index, 1)[0]); } const mediaItems: MediaItem[] = results.map(item => item.mediaItem); if (mediaItems.length !== images.length) { throw new AssertionError({ actual: mediaItems.length, expected: images.length }); } - const idMapping = new Doc; + const idMapping = new Doc(); for (let i = 0; i < images.length; i++) { const image = Doc.GetProto(images[i]); const mediaItem = mediaItems[i]; @@ -117,38 +115,30 @@ export namespace GooglePhotos { return { albumId: id, mediaItems }; } }; - } export namespace Import { - export type CollectionConstructor = (data: Array, options: DocumentOptions, ...args: any) => Doc; export const CollectionFromSearch = async (constructor: CollectionConstructor, requested: Opt>): Promise => { await GoogleAuthenticationManager.Instance.fetchOrGenerateAccessToken(); const response = await Query.ContentSearch(requested); const uploads = await Transactions.WriteMediaItemsToServer(response); - const children = uploads.map((upload: Transactions.UploadInformation) => { - const document = Docs.Create.ImageDocument(Utils.fileUrl(upload.fileNames.clean)); - document.contentSize = upload.contentSize; - return document; - }); + const children = uploads.map((upload: Transactions.UploadInformation) => Docs.Create.ImageDocument(Utils.fileUrl(upload.fileNames.clean) /*, {"data_contentSize":upload.contentSize}*/)); const options = { _width: 500, _height: 500 }; return constructor(children, options); }; - } export namespace Query { - - const delimiter = ", "; - const comparator = (a: string, b: string) => (a < b) ? -1 : (a > b ? 1 : 0); + const delimiter = ', '; + const comparator = (a: string, b: string) => (a < b ? -1 : a > b ? 1 : 0); export const TagChildImages = async (collection: Doc) => { await GoogleAuthenticationManager.Instance.fetchOrGenerateAccessToken(); const idMapping = await Cast(collection.googlePhotosIdMapping, Doc); if (!idMapping) { - throw new Error("Appending image metadata requires that the targeted collection have already been mapped to an album!"); + throw new Error('Appending image metadata requires that the targeted collection have already been mapped to an album!'); } const tagMapping = new Map(); const images = (await DocListCastAsync(collection.data))!.map(Doc.GetProto); @@ -169,7 +159,7 @@ export namespace GooglePhotos { const concatenated = tagMapping.get(image[Id])!; const tags = concatenated.split(delimiter); if (tags.length > 1) { - const cleaned = concatenated.replace(ContentCategories.NONE + delimiter, ""); + const cleaned = concatenated.replace(ContentCategories.NONE + delimiter, ''); image.googlePhotosTags = cleaned.split(delimiter).sort(comparator).join(delimiter); } else { image.googlePhotosTags = ContentCategories.NONE; @@ -253,19 +243,15 @@ export namespace GooglePhotos { export const GetImage = async (mediaItemId: string): Promise => { return (await endpoint()).mediaItems.get(mediaItemId); }; - } namespace Create { - export const Album = async (title: string) => { return (await endpoint()).albums.create(title); }; - } export namespace Transactions { - export interface UploadInformation { mediaPaths: string[]; fileNames: { [key: string]: string }; @@ -295,18 +281,20 @@ export namespace GooglePhotos { }; export const WriteMediaItemsToServer = async (body: { mediaItems: any[] }): Promise => { - const uploads = await Networking.PostToServer("/googlePhotosMediaGet", body); + const uploads = await Networking.PostToServer('/googlePhotosMediaGet', body); return uploads; }; - export const UploadThenFetch = async (sources: Doc[], album?: AlbumReference, descriptionKey = "caption") => { + export const UploadThenFetch = async (sources: Doc[], album?: AlbumReference, descriptionKey = 'caption') => { const response = await UploadImages(sources, album, descriptionKey); if (!response) { return undefined; } - const baseUrls: string[] = await Promise.all(response.results.map(item => { - return new Promise(resolve => Query.GetImage(item.mediaItem.id).then(item => resolve(item.baseUrl))); - })); + const baseUrls: string[] = await Promise.all( + response.results.map(item => { + return new Promise(resolve => Query.GetImage(item.mediaItem.id).then(item => resolve(item.baseUrl))); + }) + ); return baseUrls; }; @@ -315,9 +303,9 @@ export namespace GooglePhotos { failed: number[]; } - export const UploadImages = async (sources: Doc[], album?: AlbumReference, descriptionKey = "caption"): Promise> => { + export const UploadImages = async (sources: Doc[], album?: AlbumReference, descriptionKey = 'caption'): Promise> => { await GoogleAuthenticationManager.Instance.fetchOrGenerateAccessToken(); - if (album && "title" in album) { + if (album && 'title' in album) { album = await Create.Album(album.title); } const media: MediaInput[] = []; @@ -327,13 +315,13 @@ export namespace GooglePhotos { return; } const url = data.url.href; - const target = Doc.MakeAlias(source); + const target = Doc.MakeEmbedding(source); const description = parseDescription(target, descriptionKey); await DocUtils.makeCustomViewClicked(target, Docs.Create.FreeformDocument); media.push({ url, description }); } if (media.length) { - const results = await Networking.PostToServer("/googlePhotosMediaPost", { media, album }); + const results = await Networking.PostToServer('/googlePhotosMediaPost', { media, album }); return results; } }; @@ -341,14 +329,12 @@ export namespace GooglePhotos { const parseDescription = (document: Doc, descriptionKey: string) => { let description: string = Utils.prepend(`/doc/${document[Id]}?sharing=true`); const target = document[descriptionKey]; - if (typeof target === "string") { + if (typeof target === 'string') { description = target; } else if (target instanceof RichTextField) { description = RichTextUtils.ToPlainText(EditorState.fromJSON(FormattedTextBox.Instance.config, JSON.parse(target.Data))); } return description; }; - } - -} \ No newline at end of file +} diff --git a/src/client/documents/DocumentTypes.ts b/src/client/documents/DocumentTypes.ts index d99cd2dac..2da3a24fd 100644 --- a/src/client/documents/DocumentTypes.ts +++ b/src/client/documents/DocumentTypes.ts @@ -11,7 +11,7 @@ export enum DocumentType { AUDIO = 'audio', REC = 'recording', PDF = 'pdf', - INK = 'inks', + INK = 'ink', SCREENSHOT = 'screenshot', FONTICON = 'fonticonbox', FILTER = 'filter', diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index e28e29267..849a5d6ae 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -37,7 +37,6 @@ import { FontIconBox } from '../views/nodes/button/FontIconBox'; import { ColorBox } from '../views/nodes/ColorBox'; import { ComparisonBox } from '../views/nodes/ComparisonBox'; import { DataVizBox } from '../views/nodes/DataVizBox/DataVizBox'; -import { OpenWhereMod } from '../views/nodes/DocumentView'; import { EquationBox } from '../views/nodes/EquationBox'; import { FieldViewProps } from '../views/nodes/FieldView'; import { FormattedTextBox } from '../views/nodes/formattedText/FormattedTextBox'; @@ -120,7 +119,7 @@ class PEInfo extends FInfo { } class DAInfo extends FInfo { fieldType? = 'dropActionType'; - values? = ['alias', 'copy', 'move', 'same', 'proto', 'none']; + values? = ['embed', 'copy', 'move', 'same', 'proto', 'none']; readOnly = true; } class DateInfo extends FInfo { @@ -139,7 +138,7 @@ export class DocumentOptions { x?: NUMt = new NumInfo('x coordinate of document in a freeform view'); y?: NUMt = new NumInfo('y coordinage of document in a freeform view'); z?: NUMt = new NumInfo('whether document is in overlay (1) or not (0)', false, [1, 0]); - system?: BOOLt = new BoolInfo('is this a system created/owned doc', true); + isSystem?: BOOLt = new BoolInfo('is this a system created/owned doc', true); type?: STRt = new StrInfo('type of document', true, Array.from(Object.keys(DocumentType))); title?: string; creationDate?: DATEt = new DateInfo('date the document was created', true); @@ -150,33 +149,33 @@ export class DocumentOptions { userColor?: STRt = new StrInfo('color associated with a Dash user (seen in header fields of shared documents)'); color?: STRt = new StrInfo('foreground color data doc'); backgroundColor?: STRt = new StrInfo('background color for data doc'); - _autoHeight?: BOOLt = new BoolInfo('whether document automatically resizes vertically to display contents'); + _layout_autoHeight?: BOOLt = new BoolInfo('whether document automatically resizes vertically to display contents'); _headerHeight?: NUMt = new NumInfo('height of document header used for displaying title'); _headerFontSize?: NUMt = new NumInfo('font size of header of custom notes'); _headerPointerEvents?: PEVt = new PEInfo('types of events the header of a custom text document can consume'); - _panX?: NUMt = new NumInfo('horizontal pan location of a freeform view'); - _panY?: NUMt = new NumInfo('vertical pan location of a freeform view'); + _freeform_panX?: NUMt = new NumInfo('horizontal pan location of a freeform view'); + _freeform_panY?: NUMt = new NumInfo('vertical pan location of a freeform view'); _width?: NUMt = new NumInfo('displayed width of a document'); _height?: NUMt = new NumInfo('displayed height of document'); - 'data-nativeWidth'?: NUMt = new NumInfo('native width of data field contents (e.g., the pixel width of an image)'); - 'data-nativeHeight'?: NUMt = new NumInfo('native height of data field contents (e.g., the pixel height of an image)'); + data_nativeWidth?: NUMt = new NumInfo('native width of data field contents (e.g., the pixel width of an image)'); + data_nativeHeight?: NUMt = new NumInfo('native height of data field contents (e.g., the pixel height of an image)'); _nativeWidth?: NUMt = new NumInfo('native width of document contents (e.g., the pixel width of an image)'); _nativeHeight?: NUMt = new NumInfo('native height of document contents (e.g., the pixel height of an image)'); _nativeDimModifiable?: BOOLt = new BoolInfo('native dimensions can be modified using document decoration reizers'); _nativeHeightUnfrozen?: BOOLt = new BoolInfo('native height can be changed independent of width by dragging decoration resizers'); _dimMagnitude?: NUMt = new NumInfo("magnitude of collectionMulti{row,col} element's width or height"); _dimUnit?: DIMt = new DimInfo("units of collectionMulti{row,col} element's width or height - 'px' or '*' for pixels or relative units"); - _fitWidth?: BOOLt = new BoolInfo('whether document should scale its contents to fit its rendered width or not (e.g., for PDFviews)'); - _fitContentsToBox?: BOOLt = new BoolInfo('whether a freeformview should zoom/scale to create a shrinkwrapped view of its content'); + _layout_fitWidth?: BOOLt = new BoolInfo('whether document should scale its contents to fit its rendered width or not (e.g., for PDFviews)'); + _layoutFitContentsToBox?: BOOLt = new BoolInfo('whether a freeformview should zoom/scale to create a shrinkwrapped view of its content'); _contentBounds?: List; // the (forced) bounds of the document to display. format is: [left, top, right, bottom] _lockedPosition?: boolean; // lock the x,y coordinates of the document so that it can't be dragged - _lockedTransform?: boolean; // lock the panx,pany and scale parameters of the document so that it be panned/zoomed + _lockedTransform?: boolean; // lock the freeform_panx,freeform_pany and scale parameters of the document so that it be panned/zoomed _followLinkToggle?: boolean; // whether document, when clicked, toggles display of its link target - _showTitle?: string; // field name to display in header (:hover is an optional suffix) - _showAltContentUI?: boolean; // whether to show alternate content button + _layout_showTitle?: string; // field name to display in header (:hover is an optional suffix) + _layout_altContentUI?: boolean; // whether to show alternate content button _isLightbox?: boolean; // whether a collection acts as a lightbox by opening lightbox links by hiding all other documents in collection besides link target - _showCaption?: string; // which field to display in the caption area. leave empty to have no caption - _scrollTop?: number; // scroll location for pdfs + _layout_showCaption?: string; // which field to display in the caption area. leave empty to have no caption + _layoutScrollTop?: number; // scroll location for pdfs _noAutoscroll?: boolean; // whether collections autoscroll when this item is dragged _chromeHidden?: boolean; // whether the editing chrome for a document is hidden _searchDoc?: boolean; // is this a search document (used to change UI for search results in schema view) @@ -188,15 +187,16 @@ export class DocumentOptions { _viewType?: string; // sub type of a collection viewType?: string; // sub type of a collection _gridGap?: number; // gap between items in masonry view - _viewScale?: number; // how much a freeform view has been scaled (zoomed) + _freeform_scale?: number; // how much a freeform view has been scaled (zoomed) _overflow?: string; // set overflow behavior _xMargin?: number; // gap between left edge of document and start of masonry/stacking layouts _yMargin?: number; // gap between top edge of dcoument and start of masonry/stacking layouts _xPadding?: number; _yPadding?: number; _itemIndex?: number; // which item index the carousel viewer is showing - _showSidebar?: boolean; //whether an annotationsidebar should be displayed for text docuemnts - _singleLine?: boolean; // whether text document is restricted to a single line (carriage returns make new document) + _layout_showSidebar?: boolean; //whether an annotationsidebar should be displayed for text docuemnts + _singleLine?: boolean; // whether label box is restricted to one line of text + _createDocOnCR?: boolean; // whether carriage returns and tabs create new text documents _minFontSize?: number; // minimum font size for labelBoxes _maxFontSize?: number; // maximum font size for labelBoxes _columnWidth?: number; @@ -205,24 +205,24 @@ export class DocumentOptions { _fontFamily?: string; _fontWeight?: string; _pivotField?: string; // field key used to determine headings for sections in stacking, masonry, pivot views - _curPage?: number; // current page of a PDF or other? paginated document - _currentTimecode?: number; // the current timecode of a time-based document (e.g., current time of a video) value is in seconds + _layout_curPage?: number; // current page of a PDF or other? paginated document + _layout_currentTimecode?: number; // the current timecode of a time-based document (e.g., current time of a video) value is in seconds _currentFrame?: number; // the current frame of a frame-based collection (e.g., progressive slide) _timecodeToShow?: number; // the time that a document should be displayed (e.g., when an annotation shows up as a video plays) _timecodeToHide?: number; // the time that a document should be hidden _timelineLabel?: boolean; // whether the document exists on a timeline - '_carousel-caption-xMargin'?: NUMt = new NumInfo('x margin of caption inside of a carouself collection', true); - '_carousel-caption-yMargin'?: NUMt = new NumInfo('y margin of caption inside of a carouself collection', true); - 'icon-nativeWidth'?: NUMt = new NumInfo('native width of icon view', true); - 'icon-nativeHeight'?: NUMt = new NumInfo('native height of icon view', true); - 'dragFactory-count'?: NUMt = new NumInfo('number of items created from a drag button (used for setting title with incrementing index)', true); + _caption_xMargin?: NUMt = new NumInfo('x margin of caption inside of a carousel collection', true); + _caption_yMargin?: NUMt = new NumInfo('y margin of caption inside of a carousel collection', true); + icon_nativeWidth?: NUMt = new NumInfo('native width of icon view', true); + icon_nativeHeight?: NUMt = new NumInfo('native height of icon view', true); + dragFactory_count?: NUMt = new NumInfo('number of items created from a drag button (used for setting title with incrementing index)', true); openFactoryLocation?: string; // an OpenWhere value to place the factory created document openFactoryAsDelegate?: boolean; // lat?: number; lng?: number; infoWindowOpen?: boolean; author?: string; - _layoutKey?: string; + _layout_fieldKey?: string; fieldValues?: List; // possible field values used by fieldInfos fieldType?: string; // type of afield used by fieldInfos unrendered?: boolean; // denotes an annotation that is not rendered with a DocumentView (e.g, rtf/pdf text selections and links to scroll locations in web/pdf) @@ -249,7 +249,6 @@ export class DocumentOptions { defaultDoubleClick?: 'ignore' | 'default'; // ignore double clicks, or deafult (undefined) means open document full screen waitForDoubleClickToClick?: 'always' | 'never' | 'default'; // whether a click function wait for double click to expire. 'default' undefined = wait only if there's a click handler, "never" = never wait, "always" = alway wait dontUndo?: boolean; // whether button clicks should be undoable (this is set to true for Undo/Redo/and sidebar buttons that open the siebar panel) - description?: string; // added for links layout?: string | Doc; // default layout string for a document contentPointerEvents?: string; // pointer events allowed for content of a document view. eg. set to "none" in menuSidebar for sharedDocs so that you can select a document, but not interact with its contents childLimitHeight?: number; // whether to limit the height of collection children. 0 - means height can be no bigger than width @@ -263,11 +262,11 @@ export class DocumentOptions { childContextMenuLabels?: List; childContextMenuIcons?: List; followLinkZoom?: boolean; // whether to zoom to the target of a link - hideLinkButton?: boolean; // whether the blue link counter button should be hidden + layout_hideLinkButton?: boolean; // whether the blue link counter button should be hidden disableDocBrushing?: boolean; // whether to suppress border highlighting - hideDecorationTitle?: boolean; + layout_hideDecorationTitle?: boolean; hideOpenButton?: boolean; - hideResizeHandles?: boolean; + layout_hideResizeHandles?: boolean; hideDocumentButtonBar?: boolean; hideAllLinks?: boolean; // whether all individual blue anchor dots should be hidden isTemplateForField?: string; // the field key for which the containing document is a rendering template @@ -278,8 +277,8 @@ export class DocumentOptions { caption?: RichTextField; opacity?: number; defaultBackgroundColor?: string; - _linkAutoMove?: boolean; // whether link endpoint should move around the edges of a document to make shortest path to other link endpoint - hideLinkAnchors?: boolean; // suppresses link anchor dots from being displayed + _layout_autoMoveAnchors?: boolean; // whether link endpoint should move around the edges of a document to make shortest path to other link endpoint + layout_hideLinkAnchors?: boolean; // suppresses link anchor dots from being displayed isFolder?: boolean; lastFrame?: number; // the last frame of a frame-based collection (e.g., progressive slide) activeFrame?: number; // the active frame of a document in a frame base collection @@ -294,12 +293,11 @@ export class DocumentOptions { borderRounding?: string; boxShadow?: string; // box-shadow css string OR "standard" to use dash standard box shadow data?: any; - baseProto?: boolean; // is this a base prototoype + isBaseProto?: boolean; // this Doc is base level prototype for data documents as opposed to data documents which are prototypes for layout documents. base protos are not cloned during a deep dontRegisterView?: boolean; lookupField?: ScriptField; // script that returns the value of a field. This script is passed the rootDoc, layoutDoc, field, and container of the document. see PresBox. columnHeaders?: List; // headers for stacking views schemaHeaders?: List; // headers for schema view - clipWidth?: number; // percent transition from before to after in comparisonBox dockingConfig?: string; annotationOn?: Doc; followLinkToggle?: boolean; @@ -307,7 +305,7 @@ export class DocumentOptions { _removeDropProperties?: List; // list of properties that should be removed from a document when it is dropped. e.g., a creator button may be forceActive to allow it be dragged, but the forceActive property can be removed from the dropped document noteType?: string; // BACKGROUND GRID - _backgroundGridShow?: boolean; + _freeform_backgroundGrid?: boolean; //BUTTONS buttonText?: string; @@ -318,7 +316,6 @@ export class DocumentOptions { userColorBtn?: string; canClick?: string; script?: ScriptField; - numBtnType?: string; numBtnMax?: number; numBtnMin?: number; switchToggle?: boolean; @@ -335,12 +332,14 @@ export class DocumentOptions { layout_linkView?: Doc; // view template for a link document layout_keyValue?: string; // view tempalte for key value docs - linkRelationship?: string; // type of relatinoship a link represents - linkDisplay?: boolean; // whether a link line should be dipslayed between the two link anchors - anchor1?: Doc; - anchor2?: Doc; - 'anchor1-useLinkSmallAnchor'?: boolean; // whether anchor1 of a link should use a miniature anchor dot (as when the anchor is a text selection) - 'anchor2-useLinkSmallAnchor'?: boolean; // whether anchor1 of a link should use a miniature anchor dot (as when the anchor is a text selection) + link_description?: string; // added for links + link_relationship?: string; // type of relatinoship a link represents + layout_linkDisplay?: boolean; // whether a link line should be dipslayed between the two link anchors + layout_linkDisplayArrow?: boolean; // whether to display link's directional arrowhead + link_anchor_1?: Doc; + link_anchor_2?: Doc; + link_anchor_1_useLinkSmallAnchor?: boolean; // whether link_anchor_1 of a link should use a miniature anchor dot (as when the anchor is a text selection) + link_anchor_2_useLinkSmallAnchor?: boolean; // whether link_anchor_1 of a link should use a miniature anchor dot (as when the anchor is a text selection) ignoreClick?: boolean; onClick?: ScriptField; onDoubleClick?: ScriptField; @@ -354,13 +353,13 @@ export class DocumentOptions { onDragStart?: ScriptField; //script to execute at start of drag operation -- e.g., when a "creator" button is dragged this script generates a different document to drop cloneFieldFilter?: List; // fields not to copy when the document is clonedclipboard?: Doc; filterBoolean?: string; - useCors?: boolean; + data_useCors?: boolean; icon?: string; target?: Doc; // available for use in scripts as the primary target document sourcePanel?: Doc; // panel to display in 'targetContainer' as the result of a button onClick script targetContainer?: Doc; // document whose proto will be set to 'panel' as the result of a onClick click script searchFileTypes?: List; // file types allowed in a search query - strokeWidth?: number; + stroke_width?: number; freezeChildren?: string; // whether children are now allowed to be added and or removed from a collection treeViewHideTitle?: boolean; // whether to hide the top document title of a tree view treeViewHideUnrendered?: boolean; // tells tree view not to display documents that have an 'unrendered' tag unless they also have a treeViewFieldKey tag (presBox) @@ -395,8 +394,8 @@ export class DocumentOptions { useLinkSmallAnchor?: boolean; // whether links to this document should use a miniature linkAnchorBox border?: string; //for searchbox hoverBackgroundColor?: string; // background color of a label when hovered - linkRelationshipList?: List; // for storing different link relationships (when set by user in the link editor) - linkRelationshipSizes?: List; //stores number of links contained in each relationship + link_relationshipList?: List; // for storing different link relationships (when set by user in the link editor) + link_relationshipSizes?: List; //stores number of links contained in each relationship linkColorList?: List; // colors of links corresponding to specific link relationships } export namespace Docs { @@ -427,7 +426,7 @@ export namespace Docs { _yMargin: 10, nativeDimModifiable: true, nativeHeightUnfrozen: true, - forceReflow: true, + layout_forceReflow: true, defaultDoubleClick: 'ignore', }, }, @@ -457,35 +456,35 @@ export namespace Docs { DocumentType.WEB, { layout: { view: WebBox, dataField: defaultDataKey }, - options: { _height: 300, _fitWidth: true, nativeDimModifiable: true, nativeHeightUnfrozen: true, waitForDoubleClickToClick: 'always' }, + options: { _height: 300, _layout_fitWidth: true, nativeDimModifiable: true, nativeHeightUnfrozen: true, waitForDoubleClickToClick: 'always' }, }, ], [ DocumentType.COL, { layout: { view: CollectionView, dataField: defaultDataKey }, - options: { _fitWidth: true, _panX: 0, _panY: 0, _viewScale: 1 }, + options: { _layout_fitWidth: true, _freeform_panX: 0, _freeform_panY: 0, _freeform_scale: 1 }, }, ], [ DocumentType.KVP, { layout: { view: KeyValueBox, dataField: defaultDataKey }, - options: { _fitWidth: true, _height: 150 }, + options: { _layout_fitWidth: true, _height: 150 }, }, ], [ DocumentType.VID, { layout: { view: VideoBox, dataField: defaultDataKey }, - options: { _currentTimecode: 0 }, + options: { _layout_currentTimecode: 0 }, }, ], [ DocumentType.AUDIO, { layout: { view: AudioBox, dataField: defaultDataKey }, - options: { _height: 100, fitWidth: true, forceReflow: true, nativeDimModifiable: true }, + options: { _height: 100, layout_fitWidth: true, layout_forceReflow: true, nativeDimModifiable: true }, }, ], [ @@ -499,7 +498,7 @@ export namespace Docs { DocumentType.PDF, { layout: { view: PDFBox, dataField: defaultDataKey }, - options: { _curPage: 1, _fitWidth: true, nativeDimModifiable: true, nativeHeightUnfrozen: true }, + options: { _layout_curPage: 1, _layout_fitWidth: true, nativeDimModifiable: true, nativeHeightUnfrozen: true }, }, ], [ @@ -519,14 +518,15 @@ export namespace Docs { [ DocumentType.LINK, { - layout: { view: LinkBox, dataField: defaultDataKey }, + layout: { view: LinkBox, dataField: 'link' }, options: { childDontRegisterViews: true, onClick: FollowLinkScript(), - hideLinkAnchors: true, + layout_hideLinkAnchors: true, _height: 150, - description: '', - showCaption: 'description', + link: '', + link_description: '', + layout_showCaption: 'link_description', backgroundColor: 'lightblue', // lightblue is default color for linking dot and link documents text comment area _removeDropProperties: new List(['onClick']), }, @@ -537,7 +537,7 @@ export namespace Docs { { data: new List(), layout: { view: EmptyBox, dataField: defaultDataKey }, - options: { childDropAction: 'alias', title: 'Global Link Database' }, + options: { childDropAction: 'embed', title: 'Global Link Database' }, }, ], [ @@ -545,7 +545,7 @@ export namespace Docs { { data: new List(), layout: { view: EmptyBox, dataField: defaultDataKey }, - options: { childDropAction: 'alias', title: 'Global Script Database' }, + options: { childDropAction: 'embed', title: 'Global Script Database' }, }, ], [ @@ -571,8 +571,8 @@ export namespace Docs { [ DocumentType.EQUATION, { - layout: { view: EquationBox, dataField: defaultDataKey }, - options: { nativeDimModifiable: true, fontSize: '14px', hideResizeHandles: true, hideDecorationTitle: true }, + layout: { view: EquationBox, dataField: 'text' }, + options: { nativeDimModifiable: true, fontSize: '14px', layout_hideResizeHandles: true, layout_hideDecorationTitle: true }, }, ], [ @@ -600,14 +600,14 @@ export namespace Docs { DocumentType.PRES, { layout: { view: PresBox, dataField: defaultDataKey }, - options: { defaultDoubleClick: 'ignore', hideLinkAnchors: true }, + options: { defaultDoubleClick: 'ignore', layout_hideLinkAnchors: true }, }, ], [ DocumentType.FONTICON, { layout: { view: FontIconBox, dataField: 'icon' }, - options: { defaultDoubleClick: 'ignore', waitForDoubleClickToClick: 'never', enableDragWhenActive: true, hideLinkButton: true, _width: 40, _height: 40 }, + options: { defaultDoubleClick: 'ignore', waitForDoubleClickToClick: 'never', enableDragWhenActive: true, layout_hideLinkButton: true, _width: 40, _height: 40 }, }, ], [ @@ -621,21 +621,21 @@ export namespace Docs { DocumentType.PRESELEMENT, { layout: { view: PresElementBox, dataField: defaultDataKey }, - options: { title: 'pres element template', _fitWidth: true, _xMargin: 0, isTemplateDoc: true, isTemplateForField: 'data' }, + options: { title: 'pres element template', _layout_fitWidth: true, _xMargin: 0, isTemplateDoc: true, isTemplateForField: 'data' }, }, ], [ DocumentType.MARKER, { layout: { view: CollectionView, dataField: defaultDataKey }, - options: { hideLinkButton: true, pointerEvents: 'none' }, + options: { layout_hideLinkButton: true, pointerEvents: 'none' }, }, ], [ DocumentType.INK, { // NOTE: this is unused!! ink fields are filled in directly within the InkDocument() method - layout: { view: InkingStroke, dataField: defaultDataKey }, + layout: { view: InkingStroke, dataField: 'stroke' }, options: {}, }, ], @@ -649,8 +649,9 @@ export namespace Docs { [ DocumentType.COMPARISON, { + data: '', layout: { view: ComparisonBox, dataField: defaultDataKey }, - options: { clipWidth: 50, nativeDimModifiable: true, backgroundColor: 'gray', targetDropAction: 'alias' }, + options: { nativeDimModifiable: true, backgroundColor: 'gray', targetDropAction: 'embed' }, }, ], [ @@ -658,7 +659,7 @@ export namespace Docs { { data: new List(), layout: { view: EmptyBox, dataField: defaultDataKey }, - options: { childDropAction: 'alias', title: 'Global Group Database' }, + options: { childDropAction: 'embed', title: 'Global Group Database' }, }, ], [ @@ -672,14 +673,14 @@ export namespace Docs { DocumentType.DATAVIZ, { layout: { view: DataVizBox, dataField: defaultDataKey }, - options: { _fitWidth: true, nativeDimModifiable: true }, + options: { _layout_fitWidth: true, nativeDimModifiable: true }, }, ], [ DocumentType.LOADING, { layout: { view: LoadingBox, dataField: '' }, - options: { _fitWidth: true, _fitHeight: true, nativeDimModifiable: true }, + options: { _layout_fitWidth: true, _fitHeight: true, nativeDimModifiable: true }, }, ], ]); @@ -773,11 +774,11 @@ export namespace Docs { // synthesize the default options, the type and title from computed values and // whatever options pertain to this specific prototype const options: DocumentOptions = { - system: true, - _layoutKey: 'layout', + isSystem: true, + _layout_fieldKey: 'layout', title, type, - baseProto: true, + isBaseProto: true, x: 0, y: 0, _width: 300, @@ -818,24 +819,24 @@ export namespace Docs { * main document. */ function InstanceFromProto(proto: Doc, data: Field | undefined, options: DocumentOptions, delegId?: string, fieldKey: string = 'data', protoId?: string, placeholderDoc?: Doc) { - const viewKeys = ['x', 'y', 'system']; // keys that should be addded to the view document even though they don't begin with an "_" + const viewKeys = ['x', 'y', 'isSystem']; // keys that should be addded to the view document even though they don't begin with an "_" const { omit: dataProps, extract: viewProps } = OmitKeys(options, viewKeys, '^_'); // dataProps['acl-Override'] = SharingPermissions.Unset; dataProps['acl-Public'] = options['acl-Public'] ? options['acl-Public'] : Doc.defaultAclPrivate ? SharingPermissions.None : SharingPermissions.Augment; - dataProps.system = viewProps.system; - dataProps.isPrototype = true; + dataProps.isSystem = viewProps.isSystem; + dataProps.isDataDoc = true; dataProps.author = Doc.CurrentUserEmail; dataProps.creationDate = new DateField(); if (fieldKey) { - dataProps[`${fieldKey}-lastModified`] = new DateField(); + dataProps[`${fieldKey}_modificationDate`] = new DateField(); dataProps[fieldKey] = data; // so that the list of annotations is already initialised, prevents issues in addonly. // without this, if a doc has no annotations but the user has AddOnly privileges, they won't be able to add an annotation because they would have needed to create the field's list which they don't have permissions to do. - dataProps[fieldKey + '-annotations'] = new List(); - dataProps[fieldKey + '-sidebar'] = new List(); + dataProps[fieldKey + '_annotations'] = new List(); + dataProps[fieldKey + '_sidebar'] = new List(); } // users placeholderDoc as proto if it exists @@ -901,7 +902,7 @@ export namespace Docs { } export function ComparisonDocument(options: DocumentOptions = { title: 'Comparison Box' }) { - return InstanceFromProto(Prototypes.get(DocumentType.COMPARISON), '', options); + return InstanceFromProto(Prototypes.get(DocumentType.COMPARISON), undefined, options); } export function AudioDocument(url: string, options: DocumentOptions = {}, overwriteDoc?: Doc) { @@ -954,11 +955,12 @@ export namespace Docs { Prototypes.get(DocumentType.LINK), undefined, { - anchor1: source, - anchor2: target, + link_anchor_1: source, + link_anchor_2: target, ...options, }, - id + id, + 'link' ); LinkManager.Instance.addLink(linkDoc); @@ -966,36 +968,24 @@ export namespace Docs { return linkDoc; } - export function InkDocument( - color: string, - tool: string, - strokeWidth: number, - strokeBezier: string, - fillColor: string, - arrowStart: string, - arrowEnd: string, - dash: string, - points: PointData[], - isInkMask: boolean, - options: DocumentOptions = {} - ) { + export function InkDocument(color: string, strokeWidth: number, stroke_bezier: string, fillColor: string, arrowStart: string, arrowEnd: string, dash: string, points: PointData[], isInkMask: boolean, options: DocumentOptions = {}) { const I = new Doc(); I[Initializing] = true; - I.isInkMask = isInkMask; I.type = DocumentType.INK; - I.layout = InkingStroke.LayoutString('data'); - I.color = color; - I.hideDecorationTitle = true; // don't show title when selected + I.layout = InkingStroke.LayoutString('stroke'); + I.layout_fitWidth = true; + I.layout_hideDecorationTitle = true; // don't show title when selected // I.hideOpenButton = true; // don't show open full screen button when selected + I.color = color; I.fillColor = fillColor; - I.strokeWidth = strokeWidth; - I.strokeBezier = strokeBezier; - I.strokeStartMarker = arrowStart; - I.strokeEndMarker = arrowEnd; - I.strokeDash = dash; - I.tool = tool; - I.fitWidth = true; - I['text-align'] = 'center'; + I.stroke = new InkField(points); + I.stroke_width = strokeWidth; + I.stroke_bezier = stroke_bezier; + I.stroke_startMarker = arrowStart; + I.stroke_endMarker = arrowEnd; + I.stroke_dash = dash; + I.stroke_isInkMask = isInkMask; + I.text_align = 'center'; I.title = 'ink'; I.x = options.x as number; I.y = options.y as number; @@ -1004,7 +994,6 @@ export namespace Docs { I._fontFamily = 'cursive'; I.author = Doc.CurrentUserEmail; I.rotation = 0; - I.data = new InkField(points); I.defaultDoubleClick = 'click'; I.creationDate = new DateField(); I['acl-Public'] = Doc.defaultAclPrivate ? SharingPermissions.None : SharingPermissions.Augment; @@ -1050,7 +1039,7 @@ export namespace Docs { export function FreeformDocument(documents: Array, options: DocumentOptions, id?: string) { const inst = InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _xPadding: 20, _yPadding: 20, ...options, _viewType: CollectionViewType.Freeform }, id); - documents.map(d => (d.context = inst)); + documents.map(d => (d.embedContainer = inst)); return inst; } @@ -1136,7 +1125,7 @@ export namespace Docs { } export function EquationDocument(options?: DocumentOptions) { - return InstanceFromProto(Prototypes.get(DocumentType.EQUATION), undefined, { ...(options || {}) }); + return InstanceFromProto(Prototypes.get(DocumentType.EQUATION), undefined, { ...(options || {}) }, undefined, 'text'); } export function FunctionPlotDocument(documents: Array, options?: DocumentOptions) { @@ -1263,7 +1252,7 @@ export namespace DocUtils { ? true : matches.some(value => { if (facetKey.startsWith('*')) { - // fields starting with a '*' are used to match families of related fields. ie, *lastModified will match text-lastModified, data-lastModified, etc + // fields starting with a '*' are used to match families of related fields. ie, *modificationDate will match text_modificationDate, data_modificationDate, etc const allKeys = Array.from(Object.keys(d)); allKeys.push(...Object.keys(Doc.GetProto(d))); const keys = allKeys.filter(key => key.includes(facetKey.substring(1))); @@ -1304,12 +1293,12 @@ export namespace DocUtils { broadcastEvent && runInAction(() => (DocumentManager.Instance.RecordingEvent = DocumentManager.Instance.RecordingEvent + 1)); return DocUtils.ActiveRecordings.map(audio => { const sourceDoc = getSourceDoc(); - return sourceDoc && DocUtils.MakeLink(sourceDoc, audio.getAnchor(true) || audio.props.Document, { linkDisplay: false, linkRelationship: 'recording annotation:linked recording', description: 'recording timeline' }); + return sourceDoc && DocUtils.MakeLink(sourceDoc, audio.getAnchor(true) || audio.props.Document, { layout_linkDisplay: false, link_relationship: 'recording annotation:linked recording', link_description: 'recording timeline' }); }); } - export function MakeLink(source: Doc, target: Doc, linkSettings: { linkRelationship?: string; description?: string; linkDisplay?: boolean }, id?: string, showPopup?: number[]) { - if (!linkSettings.linkRelationship) linkSettings.linkRelationship = target.type === DocumentType.RTF ? 'Commentary:Comments On' : 'link'; + export function MakeLink(source: Doc, target: Doc, linkSettings: { link_relationship?: string; link_description?: string; layout_linkDisplay?: boolean }, id?: string, showPopup?: number[]) { + if (!linkSettings.link_relationship) linkSettings.link_relationship = target.type === DocumentType.RTF ? 'Commentary:Comments On' : 'link'; const sv = DocumentManager.Instance.getDocumentView(source); if (target.doc === Doc.UserDoc()) return undefined; @@ -1350,16 +1339,16 @@ export namespace DocUtils { target, { title: ComputedField.MakeFunction('generateLinkTitle(self)') as any, - 'anchor1-useLinkSmallAnchor': source.useLinkSmallAnchor ? true : undefined, - 'anchor2-useLinkSmallAnchor': target.useLinkSmallAnchor ? true : undefined, + link_anchor_1_useLinkSmallAnchor: source.useLinkSmallAnchor ? true : undefined, + link_anchor_2_useLinkSmallAnchor: target.useLinkSmallAnchor ? true : undefined, 'acl-Public': SharingPermissions.Augment, '_acl-Public': SharingPermissions.Augment, - linkDisplay: linkSettings.linkDisplay, - _linkAutoMove: true, - linkRelationship: linkSettings.linkRelationship, - _showCaption: 'description', - _showTitle: 'linkRelationship', - description: linkSettings.description, + layout_linkDisplay: linkSettings.layout_linkDisplay, + link_relationship: linkSettings.link_relationship, + link_description: linkSettings.link_description, + _layout_autoMoveAnchors: true, + _layout_showCaption: 'link_description', + _layout_showTitle: 'link_relationship', }, id ), @@ -1443,13 +1432,13 @@ export namespace DocUtils { created = Docs.Create.AudioDocument(field.url.href, resolved); created.layout = AudioBox.LayoutString(fieldKey); } else if (field instanceof InkField) { - created = Docs.Create.InkDocument(ActiveInkColor(), Doc.ActiveTool, ActiveInkWidth(), ActiveInkBezierApprox(), ActiveFillColor(), ActiveArrowStart(), ActiveArrowEnd(), ActiveDash(), field.inkData, ActiveIsInkMask(), resolved); + created = Docs.Create.InkDocument(ActiveInkColor(), ActiveInkWidth(), ActiveInkBezierApprox(), ActiveFillColor(), ActiveArrowStart(), ActiveArrowEnd(), ActiveDash(), field.inkData, ActiveIsInkMask(), resolved); created.layout = InkingStroke.LayoutString(fieldKey); } else if (field instanceof List && field[0] instanceof Doc) { created = Docs.Create.StackingDocument(DocListCast(field), resolved); created.layout = CollectionView.LayoutString(fieldKey); } else { - created = Docs.Create.TextDocument('', { ...{ _width: 200, _height: 25, _autoHeight: true }, ...resolved }); + created = Docs.Create.TextDocument('', { ...{ _width: 200, _height: 25, _layout_autoHeight: true }, ...resolved }); created.layout = FormattedTextBox.LayoutString(fieldKey); } if (created) { @@ -1503,12 +1492,12 @@ export namespace DocUtils { const id = s[s.length - 1]; return DocServer.GetRefField(id).then(field => { if (field instanceof Doc) { - const alias = Doc.MakeAlias(field); - alias.x = (options.x as number) || 0; - alias.y = (options.y as number) || 0; - alias._width = (options._width as number) || 300; - alias._height = (options._height as number) || (options._width as number) || 300; - return alias; + const embedding = Doc.MakeEmbedding(field); + embedding.x = (options.x as number) || 0; + embedding.y = (options.y as number) || 0; + embedding._width = (options._width as number) || 300; + embedding._height = (options._height as number) || (options._width as number) || 300; + return embedding; } return undefined; }); @@ -1531,11 +1520,11 @@ export namespace DocUtils { _width: 200, x, y, - _autoHeight: note._autoHeight !== false, - title: StrCast(note.title) + '#' + (note.aliasCount = NumCast(note.aliasCount) + 1), + _layout_autoHeight: note._layout_autoHeight !== false, + title: StrCast(note.title) + '#' + (note.embeddingCount = NumCast(note.embeddingCount) + 1), }); - textDoc.layoutKey = 'layout_' + note.title; - textDoc[textDoc.layoutKey] = note; + textDoc.layout_fieldKey = 'layout_' + note.title; + textDoc[textDoc.layout_fieldKey] = note; if (pivotField) { textDoc[pivotField] = pivotValue; } @@ -1576,7 +1565,7 @@ export namespace DocUtils { export function makeCustomViewClicked(doc: Doc, creator: Opt<(documents: Array, options: DocumentOptions, id?: string) => Doc>, templateSignature: string = 'custom', docLayoutTemplate?: Doc) { const batch = UndoManager.StartBatch('makeCustomViewClicked'); runInAction(() => { - doc.layoutKey = 'layout_' + templateSignature; + doc.layout_fieldKey = 'layout_' + templateSignature; createCustomView(doc, creator, templateSignature, docLayoutTemplate); }); batch.end(); @@ -1607,7 +1596,7 @@ export namespace DocUtils { const customName = 'layout_' + templateSignature; const _width = NumCast(doc._width); const _height = NumCast(doc._height); - const options = { title: 'data', backgroundColor: StrCast(doc.backgroundColor), _autoHeight: true, _width, x: -_width / 2, y: -_height / 2, _showSidebar: false }; + const options = { title: 'data', backgroundColor: StrCast(doc.backgroundColor), _layout_autoHeight: true, _width, x: -_width / 2, y: -_height / 2, _layout_showSidebar: false }; if (docLayoutTemplate) { if (docLayoutTemplate !== doc[customName]) { @@ -1638,9 +1627,9 @@ export namespace DocUtils { } } export function iconify(doc: Doc) { - const layoutKey = Cast(doc.layoutKey, 'string', null); + const layout_fieldKey = Cast(doc.layout_fieldKey, 'string', null); DocUtils.makeCustomViewClicked(doc, Docs.Create.StackingDocument, 'icon', undefined); - if (layoutKey && layoutKey !== 'layout' && layoutKey !== 'layout_icon') doc.deiconifyLayout = layoutKey.replace('layout_', ''); + if (layout_fieldKey && layout_fieldKey !== 'layout' && layout_fieldKey !== 'layout_icon') doc.deiconifyLayout = layout_fieldKey.replace('layout_', ''); } export function pileup(docList: Doc[], x?: number, y?: number, size: number = 55, create: boolean = true) { @@ -1680,8 +1669,8 @@ export namespace DocUtils { export function LeavePushpin(doc: Doc, annotationField: string) { if (doc.followLinkToggle) return undefined; - const context = Cast(doc.context, Doc, null) ?? Cast(doc.annotationOn, Doc, null); - const hasContextAnchor = LinkManager.Links(doc).some(l => (l.anchor2 === doc && Cast(l.anchor1, Doc, null)?.annotationOn === context) || (l.anchor1 === doc && Cast(l.anchor2, Doc, null)?.annotationOn === context)); + const context = Cast(doc.embedContainer, Doc, null) ?? Cast(doc.annotationOn, Doc, null); + const hasContextAnchor = LinkManager.Links(doc).some(l => (l.link_anchor_2 === doc && Cast(l.link_anchor_1, Doc, null)?.annotationOn === context) || (l.link_anchor_1 === doc && Cast(l.link_anchor_2, Doc, null)?.annotationOn === context)); if (context && !hasContextAnchor && (context.type === DocumentType.VID || context.type === DocumentType.WEB || context.type === DocumentType.PDF || context.type === DocumentType.IMG)) { const pushpin = Docs.Create.FontIconDocument({ title: 'pushpin', @@ -1700,7 +1689,7 @@ export namespace DocUtils { _timecodeToShow: Cast(doc._timecodeToShow, 'number', null), }); Doc.AddDocToList(context, annotationField, pushpin); - const pushpinLink = DocUtils.MakeLink(pushpin, doc, { linkRelationship: 'pushpin' }, ''); + const pushpinLink = DocUtils.MakeLink(pushpin, doc, { link_relationship: 'pushpin' }, ''); doc._timecodeToShow = undefined; return pushpin; } @@ -1745,21 +1734,17 @@ export namespace DocUtils { if (doc) { const proto = Doc.GetProto(doc); proto.text = result.rawText; - proto.fileUpload = pathname - .replace(/.*\//, '') - .replace('upload_', '') - .replace(/\.[a-z0-9]*$/, ''); if (Upload.isImageInformation(result)) { const maxNativeDim = Math.min(Math.max(result.nativeHeight, result.nativeWidth), defaultNativeImageDim); const exifRotation = StrCast((result.exifData?.data as any)?.Orientation).toLowerCase(); proto['data-nativeOrientation'] = result.exifData?.data?.image?.Orientation ?? (exifRotation.includes('rotate 90') || exifRotation.includes('rotate 270') ? 5 : undefined); - proto['data-nativeWidth'] = result.nativeWidth < result.nativeHeight ? (maxNativeDim * result.nativeWidth) / result.nativeHeight : maxNativeDim; - proto['data-nativeHeight'] = result.nativeWidth < result.nativeHeight ? maxNativeDim : maxNativeDim / (result.nativeWidth / result.nativeHeight); + proto['data_nativeWidth'] = result.nativeWidth < result.nativeHeight ? (maxNativeDim * result.nativeWidth) / result.nativeHeight : maxNativeDim; + proto['data_nativeHeight'] = result.nativeWidth < result.nativeHeight ? maxNativeDim : maxNativeDim / (result.nativeWidth / result.nativeHeight); if (NumCast(proto['data-nativeOrientation']) >= 5) { - proto['data-nativeHeight'] = result.nativeWidth < result.nativeHeight ? (maxNativeDim * result.nativeWidth) / result.nativeHeight : maxNativeDim; - proto['data-nativeWidth'] = result.nativeWidth < result.nativeHeight ? maxNativeDim : maxNativeDim / (result.nativeWidth / result.nativeHeight); + proto['data_nativeHeight'] = result.nativeWidth < result.nativeHeight ? (maxNativeDim * result.nativeWidth) / result.nativeHeight : maxNativeDim; + proto['data_nativeWidth'] = result.nativeWidth < result.nativeHeight ? maxNativeDim : maxNativeDim / (result.nativeWidth / result.nativeHeight); } - proto.contentSize = result.contentSize; + proto.data_contentSize = result.contentSize; // exif gps data coordinates are stored in DMS (Degrees Minutes Seconds), the following operation converts that to decimal coordinates const latitude = result.exifData?.data?.GPSLatitude; const latitudeDirection = result.exifData?.data?.GPSLatitudeRef; @@ -1771,12 +1756,12 @@ export namespace DocUtils { } } if (Upload.isVideoInformation(result)) { - proto['data-duration'] = result.duration; + proto.data_duration = result.duration; } if (overwriteDoc) { Doc.removeCurrentlyLoading(overwriteDoc); // loading doc icons are just labels. so any icon views of loading docs need to be replaced with the proper icon view. - DocumentManager.Instance.getAllDocumentViews(overwriteDoc).forEach(dv => StrCast(dv.rootDoc.layoutKey) === 'layout_icon' && dv.iconify(() => dv.iconify())); + DocumentManager.Instance.getAllDocumentViews(overwriteDoc).forEach(dv => StrCast(dv.rootDoc.layout_fieldKey) === 'layout_icon' && dv.iconify(() => dv.iconify())); } generatedDocuments.push(doc); } @@ -1793,16 +1778,16 @@ export namespace DocUtils { _height: 35, x: x, y: y, - _fitWidth: true, - _autoHeight: true, - _showAltContentUI: BoolCast(Doc.UserDoc().defaultToFlashcards), + _layout_fitWidth: true, + _layout_autoHeight: true, + _layout_altContentUI: BoolCast(Doc.UserDoc().defaultToFlashcards), title, }); const template = Doc.UserDoc().defaultTextLayout; if (template instanceof Doc) { tbox._width = NumCast(template._width); - tbox.layoutKey = 'layout_' + StrCast(template.title); - Doc.GetProto(tbox)[StrCast(tbox.layoutKey)] = template; + tbox.layout_fieldKey = 'layout_' + StrCast(template.title); + Doc.GetProto(tbox)[StrCast(tbox.layout_fieldKey)] = template; } return tbox; } @@ -1857,9 +1842,9 @@ export namespace DocUtils { if (!dragFactory) return undefined; const ndoc = dragFactory.isTemplateDoc ? Doc.ApplyTemplate(dragFactory) : Doc.MakeCopy(dragFactory, true); ndoc && Doc.AddFileOrphan(Doc.GetProto(ndoc)); - if (ndoc && dragFactory['dragFactory-count'] !== undefined) { - dragFactory['dragFactory-count'] = NumCast(dragFactory['dragFactory-count']) + 1; - Doc.SetInPlace(ndoc, 'title', ndoc.title + ' ' + NumCast(dragFactory['dragFactory-count']).toString(), true); + if (ndoc && dragFactory['dragFactory_count'] !== undefined) { + dragFactory['dragFactory_count'] = NumCast(dragFactory['dragFactory_count']) + 1; + Doc.SetInPlace(ndoc, 'title', ndoc.title + ' ' + NumCast(dragFactory['dragFactory_count']).toString(), true); } if (ndoc && Doc.ActiveDashboard) inheritParentAcls(Doc.ActiveDashboard, ndoc); @@ -1868,9 +1853,9 @@ export namespace DocUtils { } export function delegateDragFactory(dragFactory: Doc) { const ndoc = Doc.MakeDelegateWithProto(dragFactory); - if (ndoc && dragFactory['dragFactory-count'] !== undefined) { - dragFactory['dragFactory-count'] = NumCast(dragFactory['dragFactory-count']) + 1; - Doc.GetProto(ndoc).title = ndoc.title + ' ' + NumCast(dragFactory['dragFactory-count']).toString(); + if (ndoc && dragFactory['dragFactory_count'] !== undefined) { + dragFactory['dragFactory_count'] = NumCast(dragFactory['dragFactory_count']) + 1; + Doc.GetProto(ndoc).title = ndoc.title + ' ' + NumCast(dragFactory['dragFactory_count']).toString(); } return ndoc; } @@ -1885,11 +1870,8 @@ ScriptingGlobals.add(function makeDelegate(proto: any) { return d; }); ScriptingGlobals.add(function generateLinkTitle(self: Doc) { - const anchor1title = self.anchor1 && self.anchor1 !== self ? Cast(self.anchor1, Doc, null)?.title : ''; - const anchor2title = self.anchor2 && self.anchor2 !== self ? Cast(self.anchor2, Doc, null)?.title : ''; - const relation = self.linkRelationship || 'to'; - return `${anchor1title} (${relation}) ${anchor2title}`; -}); -ScriptingGlobals.add(function openTabAlias(tab: Doc) { - CollectionDockingView.AddSplit(Doc.MakeAlias(tab), OpenWhereMod.right); + const link_anchor_1title = self.link_anchor_1 && self.link_anchor_1 !== self ? Cast(self.link_anchor_1, Doc, null)?.title : ''; + const link_anchor_2title = self.link_anchor_2 && self.link_anchor_2 !== self ? Cast(self.link_anchor_2, Doc, null)?.title : ''; + const relation = self.link_relationship || 'to'; + return `${link_anchor_1title} (${relation}) ${link_anchor_2title}`; }); diff --git a/src/client/documents/Gitlike.ts b/src/client/documents/Gitlike.ts index 5e2baf924..f35f33f65 100644 --- a/src/client/documents/Gitlike.ts +++ b/src/client/documents/Gitlike.ts @@ -9,24 +9,24 @@ // // we don't have individual timestamps for all fields -- this is a problematic design issue. // function GitlikeSynchDocs(bd: Doc, md: Doc) { // const fieldKey = Doc.LayoutFieldKey(md); -// const bdate = DateCast(bd[`${fieldKey}-lastModified`])?.date; -// const mdate = DateCast(md[`${fieldKey}-lastModified`])?.date; +// const bdate = DateCast(bd[`${fieldKey}_modificationDate`])?.date; +// const mdate = DateCast(md[`${fieldKey}_modificationDate`])?.date; // const bdproto = bd && Doc.GetProto(bd); // if (bdate !== mdate && bdate <= mdate) { // if (bdproto && md) { // bdproto[fieldKey] = Field.Copy(md[fieldKey]); -// bdproto[`${fieldKey}-lastModified`] = new DateField(); +// bdproto[`${fieldKey}_modificationDate`] = new DateField(); // } // } -// const bldate = DateCast(bd._lastModified)?.date; -// const mldate = DateCast(md._lastModified)?.date; +// const bldate = DateCast(bd._layout_modificationDate)?.date; +// const mldate = DateCast(md._layout_modificationDate)?.date; // if (bldate === mldate || bldate > mldate) return; // if (bdproto && md) { // bd.x = Field.Copy(md.x); // bd.y = Field.Copy(md.y); // bd.width = Field.Copy(md.width); // bd.height = Field.Copy(md.height); -// bdproto._lastModified = new DateField(); +// bdproto._layout_modificationDate = new DateField(); // } // } @@ -53,10 +53,10 @@ // const newlyBranchedDocs = await Promise.all(newDocsFromMaster?.map(async md => (await Doc.MakeClone(md, false, true, cloneMap)).clone) || []); // newlyBranchedDocs.forEach(nd => { // Doc.AddDocToList(branch, Doc.LayoutFieldKey(branch) + suffix, nd); -// nd.context = branch; +// nd.embedContainer = branch; // }); -// // if a branch doc's corresponding main branch doc doesn't have a context, then it was deleted. -// const remDocsFromMaster = branchMainDocs?.filter(bd => Cast(bd.branchOf, Doc, null) && !Cast(bd.branchOf, Doc, null)?.context); +// // if a branch doc's corresponding main branch doc doesn't have a embedContainer, then it was deleted. +// const remDocsFromMaster = branchMainDocs?.filter(bd => Cast(bd.branchOf, Doc, null) && !Cast(bd.branchOf, Doc, null)?.embedContainer); // // so then remove all the deleted main docs from this branch. // remDocsFromMaster?.forEach(rd => Doc.RemoveDocFromList(branch, Doc.LayoutFieldKey(branch) + suffix, rd)); // } @@ -87,14 +87,14 @@ // branchDocProto.branchOf = masterChild; // the branch child is now a branch of the master child // } // Doc.AddDocToList(master, Doc.LayoutFieldKey(master) + suffix, masterChild); // add the masterChild to master (if it's already there, this is a no-op) -// masterChild.context = master; +// masterChild.embedContainer = master; // GitlikeSynchDocs(masterChild, bd);//Doc.GetProto(masterChild), bd); // })); // const masterChildren = await DocListCastAsync(master[Doc.LayoutFieldKey(master) + suffix]); // masterChildren?.forEach(mc => { // see if any master children // if (!branchChildren?.find(bc => bc.branchOf === mc)) { // are not in the list of children for this branch. // Doc.RemoveDocFromList(master, Doc.LayoutFieldKey(master) + suffix, mc); // if so, delete the master child since the branch has deleted it. -// mc.context = undefined; // NOTE if we merge a branch that didn't do a pull, it will look like the branch deleted documents -- need edit timestamps that prevent merging if branch isn't up-to-date with last edit timestamp +// mc.embedContainer = undefined; // NOTE if we merge a branch that didn't do a pull, it will look like the branch deleted documents -- need edit timestamps that prevent merging if branch isn't up-to-date with last edit timestamp // } // }); // }); @@ -109,8 +109,8 @@ // export async function BranchTask(target: Doc, action: "pull" | "merge") { // const func = action === "pull" ? GitlikePullFromMaster : GitlikeMergeWithMaster; // await func(target, ""); -// await DocListCast(target[Doc.LayoutFieldKey(target)]).forEach(async targetChild => func(targetChild, "-annotations")); -// await DocListCast(target[Doc.LayoutFieldKey(target)]).forEach(async targetChild => func(targetChild, "-sidebar")); +// await DocListCast(target[Doc.LayoutFieldKey(target)]).forEach(async targetChild => func(targetChild, "_annotations")); +// await DocListCast(target[Doc.LayoutFieldKey(target)]).forEach(async targetChild => func(targetChild, "_sidebar")); // } // export async function BranchCreate(target: Doc) { diff --git a/src/client/util/CaptureManager.tsx b/src/client/util/CaptureManager.tsx index c9fcc84a3..d68761ba7 100644 --- a/src/client/util/CaptureManager.tsx +++ b/src/client/util/CaptureManager.tsx @@ -53,7 +53,7 @@ export class CaptureManager extends React.Component<{}> { order.push(
{i}
- {StrCast(DocCast(l.anchor1)?.title)} + {StrCast(DocCast(l.link_anchor_1)?.title)}
) ); diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index fbfe306a4..5cfd77937 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -20,7 +20,7 @@ import { TreeViewType } from "../views/collections/CollectionTreeView"; import { DashboardView } from "../views/DashboardView"; import { Colors } from "../views/global/globalEnums"; import { MainView } from "../views/MainView"; -import { ButtonType, NumButtonType } from "../views/nodes/button/FontIconBox"; +import { ButtonType } from "../views/nodes/button/FontIconBox"; import { OpenWhere } from "../views/nodes/DocumentView"; import { OverlayView } from "../views/OverlayView"; import { DragManager } from "./DragManager"; @@ -37,7 +37,6 @@ interface Button { toolTip?: string; icon?: string; btnType?: ButtonType; - numBtnType?: NumButtonType; numBtnMin?: number; numBtnMax?: number; switchToggle?: boolean; @@ -65,11 +64,11 @@ export class CurrentUserUtils { const requiredTypeNameFields:{btnOpts:DocumentOptions, templateOpts:DocumentOptions, template:(opts:DocumentOptions) => Doc}[] = [ { btnOpts: { title: "slide", icon: "address-card" }, - templateOpts: { _width: 400, _height: 300, title: "slideView", _xMargin: 3, _yMargin: 3, system: true }, + templateOpts: { _width: 400, _height: 300, title: "slideView", _xMargin: 3, _yMargin: 3, isSystem: true }, template: (opts:DocumentOptions) => Docs.Create.MultirowDocument( [ - Docs.Create.MulticolumnDocument([], { title: "data", _height: 200, system: true }), - Docs.Create.TextDocument("", { title: "text", _fitWidth:true, _height: 100, system: true, _fontFamily: StrCast(Doc.UserDoc()._fontFamily), _fontSize: StrCast(Doc.UserDoc()._fontSize) }) + Docs.Create.MulticolumnDocument([], { title: "data", _height: 200, isSystem: true }), + Docs.Create.TextDocument("", { title: "text", _layout_fitWidth:true, _height: 100, isSystem: true, _fontFamily: StrCast(Doc.UserDoc()._fontFamily), _fontSize: StrCast(Doc.UserDoc()._fontSize) }) ], opts) }, { @@ -97,9 +96,9 @@ export class CurrentUserUtils { }); const reqdOpts:DocumentOptions = { - title: "Experimental Tools", _xMargin: 0, _showTitle: "title", _chromeHidden: true, - _stayInCollection: true, _hideContextMenu: true, _forceActive: true, system: true, - _autoHeight: true, _width: 500, _height: 300, _fitWidth: true, _columnWidth: 35, ignoreClick: true, _lockedPosition: true, + title: "Experimental Tools", _xMargin: 0, _layout_showTitle: "title", _chromeHidden: true, + _stayInCollection: true, _hideContextMenu: true, _forceActive: true, isSystem: true, + _layout_autoHeight: true, _width: 500, _height: 300, _layout_fitWidth: true, _columnWidth: 35, ignoreClick: true, _lockedPosition: true, }; const reqdScripts = { dropConverter : "convertToButtons(dragData)" }; const reqdFuncs = { hidden: "IsNoviceMode()" }; @@ -109,7 +108,7 @@ export class CurrentUserUtils { /// Initializes templates for editing click funcs of a document static setupChildClickEditors(doc: Doc, field = "clickFuncs-child") { const tempClicks = DocCast(doc[field]); - const reqdClickOpts:DocumentOptions = {_width: 300, _height:200, system: true}; + const reqdClickOpts:DocumentOptions = {_width: 300, _height:200, isSystem: true}; const reqdTempOpts:{opts:DocumentOptions, script: string}[] = [ { opts: { title: "Open In Target", targetScriptKey: "onChildClick"}, script: "docCast(documentView?.props.docViewPath().lastElement()?.rootDoc.target).then((target) => target && (target.proto.data = new List([self])))"}, { opts: { title: "Open Detail On Right", targetScriptKey: "onChildDoubleClick"}, script: `openDoc(self.doubleClickView.${OpenWhere.addRight})`}]; @@ -119,14 +118,14 @@ export class CurrentUserUtils { return DocUtils.AssignOpts(clickDoc, allOpts) ?? Docs.Create.ScriptingDocument(ScriptField.MakeScript(opts.script, allOpts),allOpts); }); - const reqdOpts:DocumentOptions = { title: "child click editors", _height:75, system: true}; + const reqdOpts:DocumentOptions = { title: "child click editors", _height:75, isSystem: true}; return DocUtils.AssignOpts(tempClicks, reqdOpts, reqdClickList) ?? (doc[field] = Docs.Create.TreeDocument(reqdClickList, reqdOpts)); } /// Initializes templates for editing click funcs of a document static setupClickEditorTemplates(doc: Doc, field = "template-clickFuncs") { const tempClicks = DocCast(doc[field]); - const reqdClickOpts:DocumentOptions = { _width: 300, _height:200, system: true}; + const reqdClickOpts:DocumentOptions = { _width: 300, _height:200, isSystem: true}; const reqdTempOpts:{opts:DocumentOptions, script: string}[] = [ { opts: { title: "onClick"}, script: "console.log('click')"}, { opts: { title: "onDoubleClick"}, script: "console.log('click')"}, @@ -140,7 +139,7 @@ export class CurrentUserUtils { return DocUtils.AssignOpts(clickDoc, allOpts) ?? MakeTemplate(Docs.Create.ScriptingDocument(ScriptField.MakeScript(opts.script, {heading:Doc.name, checked:"boolean", containingTreeView:Doc.name}), allOpts), true, opts.opts.title); }); - const reqdOpts:DocumentOptions = {title: "click editor templates", _height:75, system: true}; + const reqdOpts:DocumentOptions = {title: "click editor templates", _height:75, isSystem: true}; return DocUtils.AssignOpts(tempClicks, reqdOpts, reqdClickList) ?? (doc[field] = Docs.Create.TreeDocument(reqdClickList, reqdOpts)); } @@ -152,12 +151,12 @@ export class CurrentUserUtils { { noteType: "Idea", backgroundColor: "pink", icon: "lightbulb" }, { noteType: "Topic", backgroundColor: "lightblue", icon: "book-open" }]; const reqdNoteList = reqdTempOpts.map(opts => { - const reqdOpts = {...opts, title: "text", width:200, autoHeight: true, fitWidth: true}; + const reqdOpts = {...opts, title: "text", width:200, layout_autoHeight: true, layout_fitWidth: true}; const noteType = tempNotes ? DocListCast(tempNotes.data).find(doc => doc.noteType === opts.noteType): undefined; return DocUtils.AssignOpts(noteType, reqdOpts) ?? MakeTemplate(Docs.Create.TextDocument("",reqdOpts), true, opts.noteType??"Note"); }); - const reqdOpts:DocumentOptions = { title: "Note Layouts", _height: 75, system: true }; + const reqdOpts:DocumentOptions = { title: "Note Layouts", _height: 75, isSystem: true }; return DocUtils.AssignOpts(tempNotes, reqdOpts, reqdNoteList) ?? (doc[field] = Docs.Create.TreeDocument(reqdNoteList, reqdOpts)); } @@ -169,14 +168,14 @@ export class CurrentUserUtils { CurrentUserUtils.setupClickEditorTemplates(doc) ]; CurrentUserUtils.setupChildClickEditors(doc) - const reqdOpts = { title: "template layouts", _xMargin: 0, system: true, }; + const reqdOpts = { title: "template layouts", _xMargin: 0, isSystem: true, }; const reqdScripts = { dropConverter: "convertToButtons(dragData)" }; return DocUtils.AssignDocField(doc, field, (opts,items) => Docs.Create.TreeDocument(items??[], opts), reqdOpts, templates, reqdScripts); } // setup templates for different document types when they are iconified from Document Decorations static setupDefaultIconTemplates(doc: Doc, field="template-icons") { - const reqdOpts = { title: "icon templates", _height: 75, system: true }; + const reqdOpts = { title: "icon templates", _height: 75, isSystem: true }; const templateIconsDoc = DocUtils.AssignOpts(DocCast(doc[field]), reqdOpts) ?? (doc[field] = Docs.Create.TreeDocument([], reqdOpts)); const makeIconTemplate = (type: DocumentType | undefined, templateField: string, opts:DocumentOptions) => { @@ -187,7 +186,7 @@ export class CurrentUserUtils { case DocumentType.IMG : creator = imageBox; break; case DocumentType.FONTICON: creator = fontBox; break; } - const allopts = {system: true, onClickScriptDisable: "never", ...opts}; + const allopts = {isSystem: true, onClickScriptDisable: "never", ...opts}; return DocUtils.AssignScripts( (curIcon?.iconTemplate === opts.iconTemplate ? DocUtils.AssignOpts(curIcon, allopts):undefined) ?? ((templateIconsDoc[iconFieldName] = MakeTemplate(creator(allopts), true, iconFieldName, templateField))), {onClick:"deiconifyView(documentView)", onDoubleClick: "deiconifyViewToLightbox(documentView)", }); @@ -195,14 +194,14 @@ export class CurrentUserUtils { const labelBox = (opts: DocumentOptions, data?:string) => Docs.Create.LabelDocument({ textTransform: "unset", letterSpacing: "unset", _singleLine: false, _minFontSize: 14, _maxFontSize: 24, borderRounding: "5px", _width: 150, _height: 70, _xPadding: 10, _yPadding: 10, ...opts }); - const imageBox = (opts: DocumentOptions, url?:string) => Docs.Create.ImageDocument(url ?? "http://www.cs.brown.edu/~bcz/noImage.png", { "icon-nativeWidth": 360 / 4, "icon-nativeHeight": 270 / 4, iconTemplate:DocumentType.IMG, _width: 360 / 4, _height: 270 / 4, _showTitle: "title", ...opts }); + const imageBox = (opts: DocumentOptions, url?:string) => Docs.Create.ImageDocument(url ?? "http://www.cs.brown.edu/~bcz/noImage.png", { "icon_nativeWidth": 360 / 4, "icon_nativeHeight": 270 / 4, iconTemplate:DocumentType.IMG, _width: 360 / 4, _height: 270 / 4, _layout_showTitle: "title", ...opts }); const fontBox = (opts:DocumentOptions, data?:string) => Docs.Create.FontIconDocument({ _nativeHeight: 30, _nativeWidth: 30, _width: 30, _height: 30, ...opts }); const iconTemplates = [ makeIconTemplate(undefined, "title", { iconTemplate:DocumentType.LABEL, backgroundColor: "dimgray"}), makeIconTemplate(DocumentType.AUDIO, "title", { iconTemplate:DocumentType.LABEL, backgroundColor: "lightgreen"}), makeIconTemplate(DocumentType.PDF, "title", { iconTemplate:DocumentType.LABEL, backgroundColor: "pink"}), makeIconTemplate(DocumentType.WEB, "title", { iconTemplate:DocumentType.LABEL, backgroundColor: "brown"}), - makeIconTemplate(DocumentType.RTF, "text", { iconTemplate:DocumentType.LABEL, _showTitle: "creationDate"}), + makeIconTemplate(DocumentType.RTF, "text", { iconTemplate:DocumentType.LABEL, _layout_showTitle: "creationDate"}), makeIconTemplate(DocumentType.IMG, "data", { iconTemplate:DocumentType.IMG, _height: undefined}), makeIconTemplate(DocumentType.COL, "icon", { iconTemplate:DocumentType.IMG}), makeIconTemplate(DocumentType.COL, "icon", { iconTemplate:DocumentType.IMG}), @@ -220,7 +219,7 @@ export class CurrentUserUtils { title: string, toolTip: string, icon: string, ignoreClick?: boolean, dragFactory?: Doc, backgroundColor?: string, openFactoryAsDelegate?:boolean, openFactoryLocation?:string, clickFactory?: Doc, scripts?: { onClick?: string, onDragStart?: string}, funcs?: {onDragStart?:string, hidden?: string}, }[] { - const standardOps = (key:string) => ({ title : "Untitled "+ key, _fitWidth: false, system: true, "dragFactory-count": 0, cloneFieldFilter: new List(["system"]) }); + const standardOps = (key:string) => ({ title : "Untitled "+ key, _layout_fitWidth: false, isSystem: true, "dragFactory_count": 0, cloneFieldFilter: new List(["isSystem"]) }); const json = { doc: { type: "doc", @@ -247,7 +246,7 @@ export class CurrentUserUtils { "" + ` ` + " " + - ` Metadata` + + ` Metadata` + "" }, "header"); @@ -263,27 +262,27 @@ export class CurrentUserUtils { funcs?:{[key:string]: any}, // computed fields that are rquired for the empth thing creator:(opts:DocumentOptions)=> any // how to create the empty thing if it doesn't exist }[] = [ - {key: "Note", creator: opts => Docs.Create.TextDocument("", opts), opts: { _width: 200, _autoHeight: true }}, - {key: "Flashcard", creator: opts => Docs.Create.TextDocument("", opts), opts: { _width: 200, _autoHeight: true, _showAltContentUI: true}}, - {key: "Equation", creator: opts => Docs.Create.EquationDocument(opts), opts: { _width: 300, _height: 35, _backgroundGridShow: true, }}, - {key: "Noteboard", creator: opts => Docs.Create.NoteTakingDocument([], opts), opts: { _width: 250, _height: 200, _fitWidth: true}}, - {key: "Collection", creator: opts => Docs.Create.FreeformDocument([], opts), opts: { _width: 150, _height: 100, _fitWidth: true }}, - {key: "Webpage", creator: opts => Docs.Create.WebDocument("",opts), opts: { _width: 400, _height: 512, _nativeWidth: 850, useCors: true, }}, + {key: "Note", creator: opts => Docs.Create.TextDocument("", opts), opts: { _width: 200, _layout_autoHeight: true }}, + {key: "Flashcard", creator: opts => Docs.Create.TextDocument("", opts), opts: { _width: 200, _layout_autoHeight: true, _layout_altContentUI: true}}, + {key: "Equation", creator: opts => Docs.Create.EquationDocument(opts), opts: { _width: 300, _height: 35, }}, + {key: "Noteboard", creator: opts => Docs.Create.NoteTakingDocument([], opts), opts: { _width: 250, _height: 200, _layout_fitWidth: true}}, + {key: "Collection", creator: opts => Docs.Create.FreeformDocument([], opts), opts: { _width: 150, _height: 100, _layout_fitWidth: true }}, + {key: "Webpage", creator: opts => Docs.Create.WebDocument("",opts), opts: { _width: 400, _height: 512, _nativeWidth: 850, data_useCors: true, }}, {key: "Comparison", creator: Docs.Create.ComparisonDocument, opts: { _width: 300, _height: 300 }}, {key: "Audio", creator: opts => Docs.Create.AudioDocument(nullAudio, opts),opts: { _width: 200, _height: 100, }}, - {key: "Map", creator: opts => Docs.Create.MapDocument([], opts), opts: { _width: 800, _height: 600, _fitWidth: true, _showSidebar: true, }}, + {key: "Map", creator: opts => Docs.Create.MapDocument([], opts), opts: { _width: 800, _height: 600, _layout_fitWidth: true, _layout_showSidebar: true, }}, {key: "Screengrab", creator: Docs.Create.ScreenshotDocument, opts: { _width: 400, _height: 200 }}, - {key: "WebCam", creator: opts => Docs.Create.WebCamDocument("", opts), opts: { _width: 400, _height: 200, recording:true, system: true, cloneFieldFilter: new List(["system"]) }}, + {key: "WebCam", creator: opts => Docs.Create.WebCamDocument("", opts), opts: { _width: 400, _height: 200, recording:true, isSystem: true, cloneFieldFilter: new List(["isSystem"]) }}, {key: "Button", creator: Docs.Create.ButtonDocument, opts: { _width: 150, _height: 50, _xPadding: 10, _yPadding: 10, onClick: FollowLinkScript()}}, {key: "Script", creator: opts => Docs.Create.ScriptingDocument(null, opts), opts: { _width: 200, _height: 250, }}, {key: "DataViz", creator: opts => Docs.Create.DataVizDocument("/users/rz/Downloads/addresses.csv", opts), opts: { _width: 300, _height: 300 }}, - {key: "Header", creator: headerTemplate, opts: { _width: 300, _height: 70, _headerPointerEvents: "all", _headerHeight: 12, _headerFontSize: 9, _autoHeight: true, treeViewHideUnrendered: true}}, - {key: "Trail", creator: Docs.Create.PresDocument, opts: { _width: 400, _height: 30, _viewType: CollectionViewType.Stacking, targetDropAction: "alias" as any, treeViewHideTitle: true, _fitWidth:true, _chromeHidden: true, boxShadow: "0 0" }}, - {key: "Tab", creator: opts => Docs.Create.FreeformDocument([], opts), opts: { _width: 500, _height: 800, _fitWidth: true, _backgroundGridShow: true, }}, + {key: "Header", creator: headerTemplate, opts: { _width: 300, _height: 70, _headerPointerEvents: "all", _headerHeight: 12, _headerFontSize: 9, _layout_autoHeight: true, treeViewHideUnrendered: true}}, + {key: "Trail", creator: Docs.Create.PresDocument, opts: { _width: 400, _height: 30, _viewType: CollectionViewType.Stacking, targetDropAction: "embed" as any, treeViewHideTitle: true, _layout_fitWidth:true, _chromeHidden: true, boxShadow: "0 0" }}, + {key: "Tab", creator: opts => Docs.Create.FreeformDocument([], opts), opts: { _width: 500, _height: 800, _layout_fitWidth: true, _freeform_backgroundGrid: true, }}, {key: "Slide", creator: opts => Docs.Create.TreeDocument([], opts), opts: { _width: 300, _height: 200, _viewType: CollectionViewType.Tree, - treeViewHasOverlay: true, _fontSize: "20px", _autoHeight: true, + treeViewHasOverlay: true, _fontSize: "20px", _layout_autoHeight: true, allowOverlayDrop: true, treeViewType: TreeViewType.outline, - backgroundColor: "white", _xMargin: 0, _yMargin: 0, _singleLine: true + backgroundColor: "white", _xMargin: 0, _yMargin: 0, _createDocOnCR: true }, funcs: {title: 'self.text?.Text'}}, ]; @@ -320,16 +319,16 @@ export class CurrentUserUtils { const btn = dragCreatorDoc ? DocListCast(dragCreatorDoc.data).find(doc => doc.title === reqdOpts.title): undefined; const opts:DocumentOptions = {...OmitKeys(reqdOpts, ["funcs", "scripts", "backgroundColor"]).omit, _width: 35, _height: 35, _hideContextMenu: true, _stayInCollection: true, - btnType: ButtonType.ToolButton, backgroundColor: reqdOpts.backgroundColor ?? Colors.DARK_GRAY, color: Colors.WHITE, system: true, + btnType: ButtonType.ToolButton, backgroundColor: reqdOpts.backgroundColor ?? Colors.DARK_GRAY, color: Colors.WHITE, isSystem: true, _removeDropProperties: new List(["_stayInCollection"]), }; return DocUtils.AssignScripts(DocUtils.AssignOpts(btn, opts) ?? Docs.Create.FontIconDocument(opts), reqdOpts.scripts, reqdOpts.funcs); }); const reqdOpts:DocumentOptions = { - title: "Basic Item Creators", _showTitle: "title", _xMargin: 0, _stayInCollection: true, _hideContextMenu: true, _chromeHidden: true, system: true, - _autoHeight: true, _width: 500, _height: 300, _fitWidth: true, _columnWidth: 40, ignoreClick: true, _lockedPosition: true, _forceActive: true, - childDropAction: 'alias' + title: "Basic Item Creators", _layout_showTitle: "title", _xMargin: 0, _stayInCollection: true, _hideContextMenu: true, _chromeHidden: true, isSystem: true, + _layout_autoHeight: true, _width: 500, _height: 300, _layout_fitWidth: true, _columnWidth: 40, ignoreClick: true, _lockedPosition: true, _forceActive: true, + childDropAction: 'embed' }; const reqdScripts = { dropConverter: "convertToButtons(dragData)" }; return DocUtils.AssignScripts(DocUtils.AssignOpts(dragCreatorDoc, reqdOpts, creatorBtns) ?? Docs.Create.MasonryDocument(creatorBtns, reqdOpts), reqdScripts); @@ -354,7 +353,7 @@ export class CurrentUserUtils { /// the empty panel that is filled with whichever left menu button's panel has been selected static setupLeftSidebarPanel(doc: Doc, field="myLeftSidebarPanel") { - DocUtils.AssignDocField(doc, field, (opts) => ((doc:Doc) => {doc.system = true; return doc;})(new Doc()), {system:true}); + DocUtils.AssignDocField(doc, field, (opts) => ((doc:Doc) => {doc.isSystem = true; return doc;})(new Doc()), {isSystem:true}); } /// Initializes the left sidebar menu buttons and the panels they open up @@ -364,8 +363,8 @@ export class CurrentUserUtils { const menuBtns = CurrentUserUtils.leftSidebarMenuBtnDescriptions(doc).map(({ title, target, icon, scripts, funcs }) => { const btnDoc = myLeftSidebarMenu ? DocListCast(myLeftSidebarMenu.data).find(doc => doc.title === title) : undefined; const reqdBtnOpts:DocumentOptions = { - title, icon, target, btnType: ButtonType.MenuButton, system: true, dontUndo: true, dontRegisterView: true, - _width: 60, _height: 60, _stayInCollection: true, _hideContextMenu: true, _chromeHidden: true, + title, icon, target, btnType: ButtonType.MenuButton, isSystem: true, dontUndo: true, dontRegisterView: true, + _width: 60, _height: 60, _stayInCollection: true, _hideContextMenu: true, _removeDropProperties: new List(["_stayInCollection"]), }; return DocUtils.AssignScripts(DocUtils.AssignOpts(btnDoc, reqdBtnOpts) ?? Docs.Create.FontIconDocument(reqdBtnOpts), scripts, funcs); @@ -373,14 +372,14 @@ export class CurrentUserUtils { const reqdStackOpts:DocumentOptions ={ title: "menuItemPanel", childDropAction: "same", backgroundColor: Colors.DARK_GRAY, boxShadow: "rgba(0,0,0,0)", dontRegisterView: true, ignoreClick: true, - _chromeHidden: true, _gridGap: 0, _yMargin: 0, _yPadding: 0, _xMargin: 0, _autoHeight: false, _width: 60, _columnWidth: 60, _lockedPosition: true, system: true, + _chromeHidden: true, _gridGap: 0, _yMargin: 0, _yPadding: 0, _xMargin: 0, _layout_autoHeight: false, _width: 60, _columnWidth: 60, _lockedPosition: true, isSystem: true, }; return DocUtils.AssignDocField(doc, field, (opts, items) => Docs.Create.StackingDocument(items??[], opts), reqdStackOpts, menuBtns, { dropConverter: "convertToButtons(dragData)" }); } // Sets up mobile menu if it is undefined creates a new one, otherwise returns existing menu static setupActiveMobileMenu(doc: Doc, field="activeMobileMenu") { - const reqdOpts = { _width: 980, ignoreClick: true, _lockedPosition: false, title: "home", _yMargin: 100, system: true, _chromeHidden: true,}; + const reqdOpts = { _width: 980, ignoreClick: true, _lockedPosition: false, title: "home", _yMargin: 100, isSystem: true, _chromeHidden: true,}; DocUtils.AssignDocField(doc, field, (opts, items) => Docs.Create.StackingDocument(this.setupMobileButtons(), opts), reqdOpts); } @@ -401,9 +400,9 @@ export class CurrentUserUtils { title: data.title, _lockedPosition: true, onClick: data.click ? ScriptField.MakeScript(data.click) : undefined, - backgroundColor: data.backgroundColor, system: true + backgroundColor: data.backgroundColor, isSystem: true }, - [this.createToolButton({ ignoreClick: true, icon: data.icon, backgroundColor: "rgba(0,0,0,0)", system: true, btnType: ButtonType.ClickButton, }), this.mobileTextContainer({}, [this.mobileButtonText({}, data.title), this.mobileButtonInfo({}, data.info)])]) + [this.createToolButton({ ignoreClick: true, icon: data.icon, backgroundColor: "rgba(0,0,0,0)", isSystem: true, btnType: ButtonType.ClickButton, }), this.mobileTextContainer({}, [this.mobileButtonText({}, data.title), this.mobileButtonInfo({}, data.info)])]) ); } @@ -411,51 +410,51 @@ export class CurrentUserUtils { static mobileButton = (opts: DocumentOptions, docs: Doc[]) => Docs.Create.MulticolumnDocument(docs, { ...opts, _nativeWidth: 900, _nativeHeight: 250, _width: 900, _height: 250, _yMargin: 15, - borderRounding: "5px", boxShadow: "0 0", system: true + borderRounding: "5px", boxShadow: "0 0", isSystem: true }) as any as Doc // sets up the text container for the information contained within the mobile button static mobileTextContainer = (opts: DocumentOptions, docs: Doc[]) => Docs.Create.MultirowDocument(docs, { ...opts, _nativeWidth: 450, _nativeHeight: 250, _width: 450, _height: 250, _yMargin: 25, - backgroundColor: "rgba(0,0,0,0)", borderRounding: "0", boxShadow: "0 0", ignoreClick: true, system: true + backgroundColor: "rgba(0,0,0,0)", borderRounding: "0", boxShadow: "0 0", ignoreClick: true, isSystem: true }) as any as Doc // Sets up the title of the button static mobileButtonText = (opts: DocumentOptions, buttonTitle: string) => Docs.Create.TextDocument(buttonTitle, { ...opts, - title: buttonTitle, _fontSize: "37px", _xMargin: 0, _yMargin: 0, ignoreClick: true, backgroundColor: "rgba(0,0,0,0)", system: true + title: buttonTitle, _fontSize: "37px", _xMargin: 0, _yMargin: 0, ignoreClick: true, backgroundColor: "rgba(0,0,0,0)", isSystem: true }) as any as Doc // Sets up the description of the button static mobileButtonInfo = (opts: DocumentOptions, buttonInfo: string) => Docs.Create.TextDocument(buttonInfo, { ...opts, - title: "info", _fontSize: "25px", _xMargin: 0, _yMargin: 0, ignoreClick: true, backgroundColor: "rgba(0,0,0,0)", _dimMagnitude: 2, system: true + title: "info", _fontSize: "25px", _xMargin: 0, _yMargin: 0, ignoreClick: true, backgroundColor: "rgba(0,0,0,0)", _dimMagnitude: 2, isSystem: true }) as any as Doc static setupMobileInkingDoc(userDoc: Doc) { - return Docs.Create.FreeformDocument([], { title: "Mobile Inking", backgroundColor: "white", system: true }); + return Docs.Create.FreeformDocument([], { title: "Mobile Inking", backgroundColor: "white", isSystem: true }); } static setupMobileUploadDoc(userDoc: Doc) { // const addButton = Docs.Create.FontIconDocument({ onDragStart: ScriptField.MakeScript('addWebToMobileUpload()'), title: "Add Web Doc to Upload Collection", icon: "plus", backgroundColor: "black" }) const webDoc = Docs.Create.WebDocument("https://www.britannica.com/biography/Miles-Davis", { - title: "Upload Images From the Web", _lockedPosition: true, system: true + title: "Upload Images From the Web", _lockedPosition: true, isSystem: true }); const uploadDoc = Docs.Create.StackingDocument([], { - title: "Mobile Upload Collection", backgroundColor: "white", _lockedPosition: true, system: true, _chromeHidden: true, + title: "Mobile Upload Collection", backgroundColor: "white", _lockedPosition: true, isSystem: true, _chromeHidden: true, }); return Docs.Create.StackingDocument([webDoc, uploadDoc], { - _width: screen.width, _lockedPosition: true, title: "Upload", _autoHeight: true, _yMargin: 80, backgroundColor: "lightgray", system: true, _chromeHidden: true, + _width: screen.width, _lockedPosition: true, title: "Upload", _layout_autoHeight: true, _yMargin: 80, backgroundColor: "lightgray", isSystem: true, _chromeHidden: true, }); } /// Search option on the left side button panel static setupSearcher(doc: Doc, field:string) { return DocUtils.AssignDocField(doc, field, (opts, items) => Docs.Create.SearchDocument(opts), { - dontRegisterView: true, backgroundColor: "dimgray", ignoreClick: true, title: "Search Panel", system: true, childDropAction: "alias", + dontRegisterView: true, backgroundColor: "dimgray", ignoreClick: true, title: "Search Panel", isSystem: true, childDropAction: "embed", _lockedPosition: true, _viewType: CollectionViewType.Schema, _searchDoc: true, }); } @@ -465,8 +464,8 @@ export class CurrentUserUtils { const creatorBtns = CurrentUserUtils.setupCreatorButtons(doc, DocListCast(myTools?.data)?.length ? DocListCast(myTools.data)[0]:undefined); const templateBtns = CurrentUserUtils.setupExperimentalTemplateButtons(doc,DocListCast(myTools?.data)?.length > 1 ? DocListCast(myTools.data)[1]:undefined); const reqdToolOps:DocumentOptions = { - title: "My Tools", system: true, ignoreClick: true, boxShadow: "0 0", - _showTitle: "title", _width: 500, _yMargin: 20, _lockedPosition: true, _forceActive: true, _stayInCollection: true, _hideContextMenu: true, _chromeHidden: true, + title: "My Tools", isSystem: true, ignoreClick: true, boxShadow: "0 0", + _layout_showTitle: "title", _width: 500, _yMargin: 20, _lockedPosition: true, _forceActive: true, _stayInCollection: true, _hideContextMenu: true, _chromeHidden: true, }; return DocUtils.AssignDocField(doc, field, (opts, items) => Docs.Create.StackingDocument(items??[], opts), reqdToolOps, [creatorBtns, templateBtns]); } @@ -479,7 +478,7 @@ export class CurrentUserUtils { const newDashboard = `createNewDashboard()`; const reqdBtnOpts:DocumentOptions = { _forceActive: true, _width: 30, _height: 30, _stayInCollection: true, _hideContextMenu: true, - title: "new dashboard", btnType: ButtonType.ClickButton, toolTip: "Create new dashboard", buttonText: "New trail", icon: "plus", system: true }; + title: "new dashboard", btnType: ButtonType.ClickButton, toolTip: "Create new dashboard", buttonText: "New trail", icon: "plus", isSystem: true }; const reqdBtnScript = {onClick: newDashboard,} const newDashboardButton = DocUtils.AssignScripts(DocUtils.AssignOpts(DocCast(myDashboards?.buttonMenuDoc), reqdBtnOpts) ?? Docs.Create.FontIconDocument(reqdBtnOpts), reqdBtnScript); @@ -492,9 +491,9 @@ export class CurrentUserUtils { const childContextMenuIcons = ["chalkboard", "tv", "camera", "users", "times", "trash"]; // entries must be kept in synch with childContextMenuScripts, childContextMenuLabels, and childContextMenuFilters const reqdOpts:DocumentOptions = { title: "My Dashboards", childHideLinkButton: true, freezeChildren: "remove|add", treeViewHideTitle: true, boxShadow: "0 0", childDontRegisterViews: true, - targetDropAction: "same", treeViewType: TreeViewType.fileSystem, isFolder: true, system: true, treeViewTruncateTitleWidth: 350, ignoreClick: true, - buttonMenu: true, buttonMenuDoc: newDashboardButton, childDropAction: "alias", - _showTitle: "title", _height: 400, _gridGap: 5, _forceActive: true, _lockedPosition: true, + targetDropAction: "same", treeViewType: TreeViewType.fileSystem, isFolder: true, isSystem: true, treeViewTruncateTitleWidth: 350, ignoreClick: true, + buttonMenu: true, buttonMenuDoc: newDashboardButton, childDropAction: "embed", + _layout_showTitle: "title", _height: 400, _gridGap: 5, _forceActive: true, _lockedPosition: true, contextMenuLabels:new List(contextMenuLabels), contextMenuIcons:new List(contextMenuIcons), childContextMenuLabels:new List(childContextMenuLabels), @@ -517,20 +516,20 @@ export class CurrentUserUtils { /// initializes the left sidebar File system pane static setupFilesystem(doc: Doc, field:string) { var myFilesystem = DocCast(doc[field]); - const myFileOrphans = DocUtils.AssignDocField(doc, "myFileOrphans", (opts) => Docs.Create.TreeDocument([], opts), { title: "Unfiled", _stayInCollection: true, system: true, isFolder: true }); + const myFileOrphans = DocUtils.AssignDocField(doc, "myFileOrphans", (opts) => Docs.Create.TreeDocument([], opts), { title: "Unfiled", _stayInCollection: true, isSystem: true, isFolder: true }); const newFolder = `TreeView_addNewFolder()`; const newFolderOpts: DocumentOptions = { _forceActive: true, _stayInCollection: true, _hideContextMenu: true, _width: 30, _height: 30, - title: "New folder", btnType: ButtonType.ClickButton, toolTip: "Create new folder", buttonText: "New folder", icon: "folder-plus", system: true + title: "New folder", btnType: ButtonType.ClickButton, toolTip: "Create new folder", buttonText: "New folder", icon: "folder-plus", isSystem: true }; const newFolderScript = { onClick: newFolder}; const newFolderButton = DocUtils.AssignScripts(DocUtils.AssignOpts(DocCast(myFilesystem?.buttonMenuDoc), newFolderOpts) ?? Docs.Create.FontIconDocument(newFolderOpts), newFolderScript); - const reqdOpts:DocumentOptions = { _showTitle: "title", _height: 100, _gridGap: 5, _forceActive: true, _lockedPosition: true, - title: "My Documents", buttonMenu: true, buttonMenuDoc: newFolderButton, treeViewHideTitle: true, targetDropAction: "proto", system: true, + const reqdOpts:DocumentOptions = { _layout_showTitle: "title", _height: 100, _gridGap: 5, _forceActive: true, _lockedPosition: true, + title: "My Documents", buttonMenu: true, buttonMenuDoc: newFolderButton, treeViewHideTitle: true, targetDropAction: "proto", isSystem: true, isFolder: true, treeViewType: TreeViewType.fileSystem, childHideLinkButton: true, boxShadow: "0 0", childDontRegisterViews: true, - treeViewTruncateTitleWidth: 350, ignoreClick: true, childDropAction: "alias", + treeViewTruncateTitleWidth: 350, ignoreClick: true, childDropAction: "embed", childContextMenuLabels: new List(["Create new folder"]), childContextMenuIcons: new List(["plus"]), explainer: "This is your file manager where you can create folders to keep track of documents independently of your dashboard." @@ -545,8 +544,8 @@ export class CurrentUserUtils { /// initializes the panel displaying docs that have been recently closed static setupRecentlyClosed(doc: Doc, field:string) { - const reqdOpts:DocumentOptions = { _showTitle: "title", _lockedPosition: true, _gridGap: 5, _forceActive: true, - title: "My Recently Closed", buttonMenu: true, childHideLinkButton: true, treeViewHideTitle: true, childDropAction: "alias", system: true, + const reqdOpts:DocumentOptions = { _layout_showTitle: "title", _lockedPosition: true, _gridGap: 5, _forceActive: true, + title: "My Recently Closed", buttonMenu: true, childHideLinkButton: true, treeViewHideTitle: true, childDropAction: "embed", isSystem: true, treeViewTruncateTitleWidth: 350, ignoreClick: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "same", contextMenuLabels: new List(["Empty recently closed"]), contextMenuIcons:new List(["trash"]), @@ -556,7 +555,7 @@ export class CurrentUserUtils { const clearAll = (target:string) => `getProto(${target}).data = new List([])`; const clearBtnsOpts:DocumentOptions = { _width: 30, _height: 30, _forceActive: true, _stayInCollection: true, _hideContextMenu: true, - title: "Empty", target: recentlyClosed, btnType: ButtonType.ClickButton, buttonText: "Empty", icon: "trash", system: true, + title: "Empty", target: recentlyClosed, btnType: ButtonType.ClickButton, buttonText: "Empty", icon: "trash", isSystem: true, toolTip: "Empty recently closed",}; const clearDocsButton = DocUtils.AssignDocField(recentlyClosed, "clearDocsBtn", (opts) => Docs.Create.FontIconDocument(opts), clearBtnsOpts, undefined, {onClick: clearAll("self.target")}); @@ -572,7 +571,7 @@ export class CurrentUserUtils { static setupUserDocView(doc: Doc, field:string) { const reqdOpts:DocumentOptions = { _lockedPosition: true, _gridGap: 5, _forceActive: true, title: Doc.CurrentUserEmail +"-view", - boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "same", ignoreClick: true, system: true, + boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "same", ignoreClick: true, isSystem: true, treeViewHideTitle: true, treeViewTruncateTitleWidth: 350 }; if (!doc[field]) DocUtils.AssignOpts(doc, {treeViewOpen: true, treeViewExpandedView: "fields" }); @@ -582,13 +581,13 @@ export class CurrentUserUtils { static linearButtonList = (opts: DocumentOptions, docs: Doc[]) => Docs.Create.LinearDocument(docs, { ...opts, _gridGap: 0, _xMargin: 5, _yMargin: 5, boxShadow: "0 0", _forceActive: true, dropConverter: ScriptField.MakeScript("convertToButtons(dragData)", { dragData: DragManager.DocumentDragData.name }), - _lockedPosition: true, system: true, flexDirection: "row" + _lockedPosition: true, isSystem: true, flexDirection: "row" }) static createToolButton = (opts: DocumentOptions) => Docs.Create.FontIconDocument({ btnType: ButtonType.ToolButton, _forceActive: true, _hideContextMenu: true, _removeDropProperties: new List([ "_hideContextMenu", "stayInCollection"]), - _nativeWidth: 40, _nativeHeight: 40, _width: 40, _height: 40, system: true, ...opts, + _nativeWidth: 40, _nativeHeight: 40, _width: 40, _height: 40, isSystem: true, ...opts, }) /// initializes the required buttons in the expanding button menu at the bottom of the Dash window @@ -606,7 +605,7 @@ export class CurrentUserUtils { ]; const btns = btnDescs.map(desc => dockBtn({_width: 30, _height: 30, dontUndo: true, _stayInCollection: true, ...desc.opts}, desc.scripts)); const dockBtnsReqdOpts:DocumentOptions = { - title: "docked buttons", _height: 40, flexGap: 0, boxShadow: "standard", childDropAction: 'alias', + title: "docked buttons", _height: 40, flexGap: 0, boxShadow: "standard", childDropAction: 'embed', childDontRegisterViews: true, linearViewIsExpanded: true, linearViewExpandable: true, ignoreClick: true }; reaction(() => UndoManager.redoStack.slice(), () => Doc.GetProto(btns.find(btn => btn.title === "redo")!).opacity = UndoManager.CanRedo() ? 1 : 0.4, { fireImmediately: true }); @@ -623,7 +622,7 @@ export class CurrentUserUtils { } static viewTools(): Button[] { return [ - { title: "Snap\xA0Lines", icon: "th", toolTip: "Show Snap Lines", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"snap lines", funcs: {}, scripts: { onClick: 'showFreeform(self.toolType, _readOnly_)'}}, // Only when floating document is selected in freeform + { title: "Snap\xA0Lines", icon: "th", toolTip: "Show Snap Lines", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"snaplines", funcs: {}, scripts: { onClick: 'showFreeform(self.toolType, _readOnly_)'}}, // Only when floating document is selected in freeform { title: "Grid", icon: "border-all", toolTip: "Show Grid", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"grid", funcs: {}, scripts: { onClick: 'showFreeform(self.toolType, _readOnly_)'}}, // Only when floating document is selected in freeform { title: "View\xA0All", icon: "object-group", toolTip: "Fit all Docs to View",btnType: ButtonType.ToggleButton, expertMode: false, toolType:"viewAll", funcs: {}, scripts: { onClick: 'showFreeform(self.toolType, _readOnly_)'}}, // Only when floating document is selected in freeform { title: "Clusters", icon: "braille", toolTip: "Show Doc Clusters", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"clusters", funcs: {}, scripts: { onClick: 'showFreeform(self.toolType, _readOnly_)'}}, // Only when floating document is selected in freeform @@ -635,7 +634,7 @@ export class CurrentUserUtils { return [ { title: "Font", toolTip: "Font", width: 100, btnType: ButtonType.DropdownList, toolType:"font", ignoreClick: true, scripts: {script: '{ return setFontAttr(self.toolType, value, _readOnly_);}'}, btnList: new List(["Roboto", "Roboto Mono", "Nunito", "Times New Roman", "Arial", "Georgia", "Comic Sans MS", "Tahoma", "Impact", "Crimson Text"]) }, - { title: "Size", toolTip: "Font size (%size)", btnType: ButtonType.NumberButton, width: 75, toolType:"fontSize", ignoreClick: true, scripts: {script: '{ return setFontAttr(self.toolType, value, _readOnly_);}'}, numBtnMax: 200, numBtnMin: 0, numBtnType: NumButtonType.DropdownOptions }, + { title: "Size", toolTip: "Font size (%size)", btnType: ButtonType.NumberDropdownButton, width: 75, toolType:"fontSize", ignoreClick: true, scripts: {script: '{ return setFontAttr(self.toolType, value, _readOnly_);}'}, numBtnMax: 200, numBtnMin: 0 }, { title: "Color", toolTip: "Font color (%color)", btnType: ButtonType.ColorButton, icon: "font", toolType:"fontColor",ignoreClick: true, scripts: {script: '{ return setFontAttr(self.toolType, value, _readOnly_);}'}}, { title: "Highlight",toolTip:"Font highlight", btnType: ButtonType.ColorButton, icon: "highlighter", toolType:"highlight",ignoreClick: true, scripts: {script: '{ return setFontAttr(self.toolType, value, _readOnly_);}'},funcs: {hidden: "IsNoviceMode()"} }, { title: "Bold", toolTip: "Bold (Ctrl+B)", btnType: ButtonType.ToggleButton, icon: "bold", toolType:"bold", scripts: {onClick: '{ return toggleCharStyle(self.toolType, _readOnly_);}'} }, @@ -663,7 +662,7 @@ export class CurrentUserUtils { { title: "Square", toolTip: "Square (double tap to lock mode)", btnType: ButtonType.ToggleButton, icon: "square", toolType:GestureUtils.Gestures.Rectangle, scripts: {onClick:`{ return setActiveTool(self.toolType, false, _readOnly_);}`, onDoubleClick:`{ return setActiveTool(self.toolType, true, _readOnly_);}`} }, { title: "Line", toolTip: "Line (double tap to lock mode)", btnType: ButtonType.ToggleButton, icon: "minus", toolType:GestureUtils.Gestures.Line, scripts: {onClick:`{ return setActiveTool(self.toolType, false, _readOnly_);}`, onDoubleClick:`{ return setActiveTool(self.toolType, true, _readOnly_);}`} }, { title: "Mask", toolTip: "Mask", btnType: ButtonType.ToggleButton, icon: "user-circle",toolType: "inkMask", scripts: {onClick:'{ return setInkProperty(self.toolType, value, _readOnly_);}'} }, - { title: "Width", toolTip: "Stroke width", btnType: ButtonType.NumberButton, toolType: "strokeWidth", ignoreClick: true, scripts: {script: '{ return setInkProperty(self.toolType, value, _readOnly_);}'}, numBtnType: NumButtonType.Slider, numBtnMin: 1}, + { title: "Width", toolTip: "Stroke width", btnType: ButtonType.NumberSliderButton, toolType: "strokeWidth", ignoreClick: true, scripts: {script: '{ return setInkProperty(self.toolType, value, _readOnly_);}'}, numBtnMin: 1}, { title: "Ink", toolTip: "Stroke color", btnType: ButtonType.ColorButton, icon: "pen", toolType: "strokeColor", ignoreClick: true, scripts: {script: '{ return setInkProperty(self.toolType, value, _readOnly_);}'} }, ]; } @@ -712,7 +711,7 @@ export class CurrentUserUtils { const reqdOpts:DocumentOptions = { ...OmitKeys(params, ["scripts", "funcs", "subMenu"]).omit, backgroundColor: params.backgroundColor ??"transparent", /// a bit hacky. if an onClick is specified, then assume a toggle uses onClick to get the backgroundColor (see below). Otherwise, assume a transparent background - color: Colors.WHITE, system: true, dontUndo: true, + color: Colors.WHITE, isSystem: true, dontUndo: true, _nativeWidth: params.width ?? 30, _width: params.width ?? 30, _height: 30, _nativeHeight: 30, linearBtnWidth: params.linearBtnWidth, toolType: params.toolType, expertMode: params.expertMode, @@ -728,7 +727,7 @@ export class CurrentUserUtils { /// Initializes all the default buttons for the top bar context menu static setupContextMenuButtons(doc: Doc, field="myContextMenuBtns") { - const reqdCtxtOpts:DocumentOptions = { title: "context menu buttons", flexGap: 0, childDropAction: 'alias', childDontRegisterViews: true, linearViewIsExpanded: true, ignoreClick: true, linearViewExpandable: false, _height: 35 }; + const reqdCtxtOpts:DocumentOptions = { title: "context menu buttons", flexGap: 0, childDropAction: 'embed', childDontRegisterViews: true, linearViewIsExpanded: true, ignoreClick: true, linearViewExpandable: false, _height: 35 }; const ctxtMenuBtnsDoc = DocUtils.AssignDocField(doc, field, (opts, items) => this.linearButtonList(opts, items??[]), reqdCtxtOpts, undefined); const ctxtMenuBtns = CurrentUserUtils.contextMenuTools().map(params => { const menuBtnDoc = DocListCast(ctxtMenuBtnsDoc?.data).find(doc => doc.title === params.title); @@ -750,11 +749,11 @@ export class CurrentUserUtils { /// collection of documents rendered in the overlay layer above all tabs and other UI static setupOverlays(doc: Doc, field = "myOverlayDocs") { - return DocUtils.AssignDocField(doc, field, (opts) => Docs.Create.FreeformDocument([], opts), { title: "overlay documents", backgroundColor: "#aca3a6", system: true }); + return DocUtils.AssignDocField(doc, field, (opts) => Docs.Create.FreeformDocument([], opts), { title: "overlay documents", backgroundColor: "#aca3a6", isSystem: true }); } static setupPublished(doc:Doc, field = "myPublishedDocs") { - return DocUtils.AssignDocField(doc, field, (opts) => Docs.Create.TreeDocument([], opts), { title: "published docs", backgroundColor: "#aca3a6", system: true }); + return DocUtils.AssignDocField(doc, field, (opts) => Docs.Create.TreeDocument([], opts), { title: "published docs", backgroundColor: "#aca3a6", isSystem: true }); } /// The database of all links on all documents @@ -788,9 +787,9 @@ export class CurrentUserUtils { childContextMenuLabels: new List(["Add to Dashboards",]), childContextMenuIcons: new List(["user-plus",]), "acl-Public": SharingPermissions.Augment, "_acl-Public": SharingPermissions.Augment, - childDropAction: "alias", system: true, contentPointerEvents: "all", childLimitHeight: 0, _yMargin: 0, _gridGap: 15, childDontRegisterViews:true, - // NOTE: treeViewHideTitle & _showTitle is for a TreeView's editable title, _showTitle is for DocumentViews title bar - _showTitle: "title", treeViewHideTitle: true, ignoreClick: true, _lockedPosition: true, boxShadow: "0 0", _chromeHidden: true, dontRegisterView: true, + childDropAction: "embed", isSystem: true, contentPointerEvents: "all", childLimitHeight: 0, _yMargin: 0, _gridGap: 15, childDontRegisterViews:true, + // NOTE: treeViewHideTitle & _layout_showTitle is for a TreeView's editable title, _layout_showTitle is for DocumentViews title bar + _layout_showTitle: "title", treeViewHideTitle: true, ignoreClick: true, _lockedPosition: true, boxShadow: "0 0", _chromeHidden: true, dontRegisterView: true, explainer: "This is where documents or dashboards that other users have shared with you will appear. To share a document or dashboard right click and select 'Share'" }; @@ -800,16 +799,16 @@ export class CurrentUserUtils { /// Import option on the left side button panel static setupImportSidebar(doc: Doc, field:string) { const reqdOpts:DocumentOptions = { - title: "My Imports", _forceActive: true, buttonMenu: true, ignoreClick: true, _showTitle: "title", + title: "My Imports", _forceActive: true, buttonMenu: true, ignoreClick: true, _layout_showTitle: "title", _stayInCollection: true, _hideContextMenu: true, childLimitHeight: 0, - childDropAction: "copy", _autoHeight: true, _yMargin: 50, _gridGap: 15, boxShadow: "0 0", _lockedPosition: true, system: true, _chromeHidden: true, + childDropAction: "copy", _layout_autoHeight: true, _yMargin: 50, _gridGap: 15, boxShadow: "0 0", _lockedPosition: true, isSystem: true, _chromeHidden: true, dontRegisterView: true, explainer: "This is where documents that are Imported into Dash will go." }; const myImports = DocUtils.AssignDocField(doc, field, (opts) => Docs.Create.StackingDocument([], opts), reqdOpts); const reqdBtnOpts:DocumentOptions = { _forceActive: true, toolTip: "Import from computer", _width: 30, _height: 30, _stayInCollection: true, _hideContextMenu: true, title: "Import", btnType: ButtonType.ClickButton, - buttonText: "Import", icon: "upload", system: true }; + buttonText: "Import", icon: "upload", isSystem: true }; DocUtils.AssignDocField(myImports, "buttonMenuDoc", (opts) => Docs.Create.FontIconDocument(opts), reqdBtnOpts, undefined, { onClick: "importDocument()" }); return myImports; } @@ -818,13 +817,13 @@ export class CurrentUserUtils { /// whether to revert to "default" values, or to leave them as the user/system last set them. static updateUserDocument(doc: Doc, sharingDocumentId: string, linkDatabaseId: string) { DocUtils.AssignDocField(doc, "globalGroupDatabase", () => Docs.Prototypes.MainGroupDocument(), {}); - reaction(() => DateCast(DocCast(doc.globalGroupDatabase)["data-lastModified"]), + reaction(() => DateCast(DocCast(doc.globalGroupDatabase)["data_modificationDate"]), async () => { const groups = await DocListCastAsync(DocCast(doc.globalGroupDatabase).data); const mygroups = groups?.filter(group => JSON.parse(StrCast(group.members)).includes(Doc.CurrentUserEmail)) || []; SetCachedGroups(["Public", ...mygroups?.map(g => StrCast(g.title))]); }, { fireImmediately: true }); - doc.system ?? (doc.system = true); + doc.isSystem ?? (doc.isSystem = true); doc.title ?? (doc.title = Doc.CurrentUserEmail); Doc.noviceMode ?? (Doc.noviceMode = true); doc._raiseWhenDragged ?? (doc._raiseWhenDragged = true); @@ -860,7 +859,7 @@ export class CurrentUserUtils { this.setupDocTemplates(doc); // sets up the template menu of templates this.setupFieldInfos(doc); // sets up the collection of field info descriptions for each possible DocumentOption DocUtils.AssignDocField(doc, "globalScriptDatabase", (opts) => Docs.Prototypes.MainScriptDocument(), {}); - DocUtils.AssignDocField(doc, "myHeaderBar", (opts) => Docs.Create.MulticolumnDocument([], opts), { title: "header bar", system: true }); // drop down panel at top of dashboard for stashing documents + DocUtils.AssignDocField(doc, "myHeaderBar", (opts) => Docs.Create.MulticolumnDocument([], opts), { title: "header bar", isSystem: true }); // drop down panel at top of dashboard for stashing documents Doc.AddDocToList(Doc.MyFilesystem, undefined, Doc.MySharedDocs) @@ -874,13 +873,13 @@ export class CurrentUserUtils { return doc; } static setupFieldInfos(doc:Doc, field="fieldInfos") { - const fieldInfoOpts = { title: "Field Infos", system: true}; // bcz: all possible document options have associated field infos which are stored onn the FieldInfos document **except for title and system which are used as part of the definition of the fieldInfos object + const fieldInfoOpts = { title: "Field Infos", isSystem: true}; // bcz: all possible document options have associated field infos which are stored onn the FieldInfos document **except for title and system which are used as part of the definition of the fieldInfos object const infos = DocUtils.AssignDocField(doc, field, opts => Doc.assign(new Doc(), opts as any), fieldInfoOpts); const entries = Object.entries(new DocumentOptions()); entries.forEach(pair => { if (!Array.from(Object.keys(fieldInfoOpts)).includes(pair[0])) { const options = pair[1] as FInfo; - const opts:DocumentOptions = { system: true, title: pair[0], ...OmitKeys(options, ["values"]).omit, fieldIsLayout: pair[0].startsWith("_")}; + const opts:DocumentOptions = { isSystem: true, title: pair[0], ...OmitKeys(options, ["values"]).omit, fieldIsLayout: pair[0].startsWith("_")}; switch (options.fieldType) { case "boolean": opts.fieldValues = new List(options.values as any); break; case "number": opts.fieldValues = new List(options.values as any); break; diff --git a/src/client/util/DictationManager.ts b/src/client/util/DictationManager.ts index e116ae14b..1cce21034 100644 --- a/src/client/util/DictationManager.ts +++ b/src/client/util/DictationManager.ts @@ -327,7 +327,7 @@ export namespace DictationManager { 'new outline', { action: (target: DocumentView) => { - const newBox = Docs.Create.TextDocument('', { _width: 400, _height: 200, title: 'My Outline', _autoHeight: true }); + const newBox = Docs.Create.TextDocument('', { _width: 400, _height: 200, title: 'My Outline', _layout_autoHeight: true }); const proto = newBox.proto!; const prompt = 'Press alt + r to start dictating here...'; const head = 3; diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index 695b003a6..6eed4dc86 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -69,12 +69,12 @@ export class DocumentManager { public AddView = (view: DocumentView) => { //console.log("MOUNT " + view.props.Document.title + "/" + view.props.LayoutTemplateString); if (view.props.LayoutTemplateString?.includes(LinkAnchorBox.name)) { - const viewAnchorIndex = view.props.LayoutTemplateString.includes('anchor2') ? 'anchor2' : 'anchor1'; + const viewAnchorIndex = view.props.LayoutTemplateString.includes('link_anchor_2') ? 'link_anchor_2' : 'link_anchor_1'; const link = view.rootDoc; this.LinkAnchorBoxViews?.filter(dv => Doc.AreProtosEqual(dv.rootDoc, link) && !dv.props.LayoutTemplateString?.includes(viewAnchorIndex)).forEach(otherView => this.LinkedDocumentViews.push({ - a: viewAnchorIndex === 'anchor2' ? otherView : view, - b: viewAnchorIndex === 'anchor2' ? view : otherView, + a: viewAnchorIndex === 'link_anchor_2' ? otherView : view, + b: viewAnchorIndex === 'link_anchor_2' ? view : otherView, l: link, }) ); @@ -173,7 +173,7 @@ export class DocumentManager { // heuristic to return the "best" documents first: // choose a document in the lightbox first - // choose an exact match over an alias match + // choose an exact match over an embedding match lightViews.map(view => view.rootDoc === toFind && toReturn.push(view)); lightViews.map(view => view.rootDoc !== toFind && Doc.AreProtosEqual(view.rootDoc, toFind) && toReturn.push(view)); docViews.map(view => view.rootDoc === toFind && toReturn.push(view)); @@ -184,15 +184,15 @@ export class DocumentManager { static GetContextPath(doc: Opt, includeExistingViews?: boolean) { if (!doc) return []; - const srcContext = DocCast(doc.annotationOn, DocCast(doc.context)); + const srcContext = DocCast(doc.annotationOn, DocCast(doc.embedContainer)); var containerDocContext = srcContext ? [srcContext, doc] : [doc]; while ( containerDocContext.length && - containerDocContext[0]?.context && - DocCast(containerDocContext[0].context)?.viewType !== CollectionViewType.Docking && + containerDocContext[0]?.embedContainer && + DocCast(containerDocContext[0].embedContainer)?.viewType !== CollectionViewType.Docking && (includeExistingViews || !DocumentManager.Instance.getDocumentView(containerDocContext[0])) ) { - containerDocContext = [Cast(containerDocContext[0].context, Doc, null), ...containerDocContext]; + containerDocContext = [Cast(containerDocContext[0].embedContainer, Doc, null), ...containerDocContext]; } return containerDocContext; } @@ -256,7 +256,7 @@ export class DocumentManager { if (options.openLocation === OpenWhere.lightbox) { // even if we found the document view, if the target is a lightbox, we try to open it in the lightbox to preserve lightbox semantics (eg, there's only one active doc in the lightbox) const target = DocCast(targetDoc.annotationOn, targetDoc); - const contextView = this.getDocumentView(DocCast(target.context)); + const contextView = this.getDocumentView(DocCast(target.embedContainer)); if (contextView?.docView?._componentView?.addDocTab?.(target, OpenWhere.lightbox)) { await new Promise(waitres => setTimeout(() => waitres())); } @@ -275,7 +275,7 @@ export class DocumentManager { focusViewsInPath = async (docView: DocumentView, options: DocFocusOptions, iterator: (docView: DocumentView) => Promise<{ viewSpec: Opt; childDocView: Opt }>) => { let contextView: DocumentView | undefined; // view containing context that contains target while (true) { - docView.rootDoc.layoutKey === 'layout_icon' ? await new Promise(res => docView.iconify(res)) : undefined; + docView.rootDoc.layout_fieldKey === 'layout_icon' ? await new Promise(res => docView.iconify(res)) : undefined; docView.props.focus(docView.rootDoc, options); // focus the view within its container const { childDocView, viewSpec } = await iterator(docView); if (!childDocView) return { viewSpec: options.anchorDoc ?? viewSpec ?? docView.rootDoc, docView, contextView }; @@ -315,7 +315,7 @@ export function DocFocusOrOpen(doc: Doc, options: DocFocusOptions = { willZoomCe if (dv && (!containingDoc || dv.props.docViewPath().lastElement()?.Document === containingDoc)) { DocumentManager.Instance.showDocumentView(dv, options).then(() => dv && Doc.linkFollowHighlight(dv.rootDoc)); } else { - const container = DocCast(containingDoc ?? doc.context); + const container = DocCast(containingDoc ?? doc.embedContainer); const showDoc = !Doc.IsSystem(container) ? container : doc; options.toggleTarget = undefined; DocumentManager.Instance.showDocument(showDoc, options, () => DocumentManager.Instance.showDocument(doc, { ...options, openLocation: undefined })).then(() => { diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index b6de5604d..070e0f918 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -15,7 +15,7 @@ import { SelectionManager } from './SelectionManager'; import { SnappingManager } from './SnappingManager'; import { UndoManager } from './UndoManager'; -export type dropActionType = 'alias' | 'copy' | 'move' | 'same' | 'proto' | 'none' | undefined; // undefined = move, "same" = move but don't call removeDropProperties +export type dropActionType = 'embed' | 'copy' | 'move' | 'same' | 'proto' | 'none' | undefined; // undefined = move, "same" = move but don't call removeDropProperties /** * Initialize drag @@ -131,7 +131,7 @@ export namespace DragManager { canEmbed?: boolean; userDropAction: dropActionType; // the user requested drop action -- this will be honored as specified by modifier keys defaultDropAction?: dropActionType; // an optionally specified default drop action when there is no user drop actionl - this will be honored if there is no user drop action - dropAction: dropActionType; // a drop action request by the initiating code. the actual drop action may be different -- eg, if the request is 'alias', but the document is dropped within the same collection, the drop action will be switched to 'move' + dropAction: dropActionType; // a drop action request by the initiating code. the actual drop action may be different -- eg, if the request is 'embed', but the document is dropped within the same collection, the drop action will be switched to 'move' removeDropProperties?: string[]; moveDocument?: MoveFunction; removeDocument?: RemoveFunction; @@ -193,7 +193,7 @@ export namespace DragManager { }; } - // drag a document and drop it (or make an alias/copy on drop) + // drag a document and drop it (or make an embed/copy on drop) export function StartDocumentDrag(eles: HTMLElement[], dragData: DocumentDragData, downX: number, downY: number, options?: DragOptions, dropEvent?: () => any) { const addAudioTag = (dropDoc: any) => { dropDoc && !dropDoc.creationDate && (dropDoc.creationDate = new DateField()); @@ -210,8 +210,8 @@ export namespace DragManager { dragData.draggedDocuments.map(async d => !dragData.isDocDecorationMove && !dragData.userDropAction && ScriptCast(d.onDragStart) ? addAudioTag(ScriptCast(d.onDragStart).script.run({ this: d }).result) - : docDragData.dropAction === 'alias' - ? Doc.BestAlias(d) + : docDragData.dropAction === 'embed' + ? Doc.BestEmbedding(d) : docDragData.dropAction === 'proto' ? Doc.GetProto(d) : docDragData.dropAction === 'copy' @@ -487,7 +487,7 @@ export namespace DragManager { const moveHandler = (e: PointerEvent) => { e.preventDefault(); // required or dragging text menu link item ends up dragging the link button as native drag/drop if (dragData instanceof DocumentDragData) { - dragData.userDropAction = e.ctrlKey && e.altKey ? 'copy' : e.ctrlKey ? 'alias' : dragData.defaultDropAction; + dragData.userDropAction = e.ctrlKey && e.altKey ? 'copy' : e.ctrlKey ? 'embed' : dragData.defaultDropAction; } if (((e.target as any)?.className === 'lm_tabs' || (e.target as any)?.className === 'lm_header' || e?.shiftKey) && dragData.draggedDocuments.length === 1) { if (!startWindowDragTimer) { diff --git a/src/client/util/DropConverter.ts b/src/client/util/DropConverter.ts index 2e1d6ba23..f46ea393a 100644 --- a/src/client/util/DropConverter.ts +++ b/src/client/util/DropConverter.ts @@ -58,8 +58,8 @@ export function convertDropDataToButtons(data: DragManager.DocumentDragData) { // bcz: isButtonBar is intended to allow a collection of linear buttons to be dropped and nested into another collection of buttons... it's not being used yet, and isn't very elegant if (doc.type === DocumentType.FONTICON || StrCast(Doc.Layout(doc).layout).includes('FontIconBox')) { if (data.removeDropProperties || dbox.removeDropProperties) { - //dbox = Doc.MakeAlias(doc); // don't need to do anything if dropping an icon doc onto an icon bar since there should be no layout data for an icon - dbox = Doc.MakeAlias(dbox); + //dbox = Doc.MakeEmbedding(doc); // don't need to do anything if dropping an icon doc onto an icon bar since there should be no layout data for an icon + dbox = Doc.MakeEmbedding(dbox); const dragProps = Cast(dbox.removeDropProperties, listSpec('string'), []); const remProps = (data.removeDropProperties || []).concat(Array.from(dragProps)); remProps.map(prop => (dbox[prop] = undefined)); diff --git a/src/client/util/GroupManager.tsx b/src/client/util/GroupManager.tsx index c8b784390..da947aba6 100644 --- a/src/client/util/GroupManager.tsx +++ b/src/client/util/GroupManager.tsx @@ -155,7 +155,7 @@ export class GroupManager extends React.Component<{}> { addGroup(groupDoc: Doc): boolean { if (this.GroupManagerDoc) { Doc.AddDocToList(this.GroupManagerDoc, 'data', groupDoc); - this.GroupManagerDoc['data-lastModified'] = new DateField(); + this.GroupManagerDoc['data_modificationDate'] = new DateField(); return true; } return false; @@ -176,7 +176,7 @@ export class GroupManager extends React.Component<{}> { const index = DocListCast(this.GroupManagerDoc.data).findIndex(grp => grp === group); index !== -1 && Cast(this.GroupManagerDoc.data, listSpec(Doc), [])?.splice(index, 1); } - this.GroupManagerDoc['data-lastModified'] = new DateField(); + this.GroupManagerDoc['data_modificationDate'] = new DateField(); if (group === this.currentGroup) { this.currentGroup = undefined; } @@ -197,7 +197,7 @@ export class GroupManager extends React.Component<{}> { !memberList.includes(email) && memberList.push(email); groupDoc.members = JSON.stringify(memberList); SharingManager.Instance.shareWithAddedMember(groupDoc, email); - this.GroupManagerDoc && (this.GroupManagerDoc['data-lastModified'] = new DateField()); + this.GroupManagerDoc && (this.GroupManagerDoc['data_modificationDate'] = new DateField()); } } @@ -214,7 +214,7 @@ export class GroupManager extends React.Component<{}> { const user = memberList.splice(index, 1)[0]; groupDoc.members = JSON.stringify(memberList); SharingManager.Instance.removeMember(groupDoc, email); - this.GroupManagerDoc && (this.GroupManagerDoc['data-lastModified'] = new DateField()); + this.GroupManagerDoc && (this.GroupManagerDoc['data_modificationDate'] = new DateField()); } } } diff --git a/src/client/util/HypothesisUtils.ts b/src/client/util/HypothesisUtils.ts index 297520d5d..151f18d6f 100644 --- a/src/client/util/HypothesisUtils.ts +++ b/src/client/util/HypothesisUtils.ts @@ -20,7 +20,7 @@ export namespace Hypothesis { export const getSourceWebDoc = async (uri: string) => { const result = await findWebDoc(uri); console.log(result ? 'existing doc found' : 'existing doc NOT found'); - return result || Docs.Create.WebDocument(uri, { title: uri, _nativeWidth: 850, _height: 512, _width: 400, useCors: true }); // create and return a new Web doc with given uri if no matching docs are found + return result || Docs.Create.WebDocument(uri, { title: uri, _nativeWidth: 850, _height: 512, _width: 400, data_useCors: true }); // create and return a new Web doc with given uri if no matching docs are found }; /** diff --git a/src/client/util/Import & Export/ImageUtils.ts b/src/client/util/Import & Export/ImageUtils.ts index 9bd92a316..55d37f544 100644 --- a/src/client/util/Import & Export/ImageUtils.ts +++ b/src/client/util/Import & Export/ImageUtils.ts @@ -1,12 +1,11 @@ -import { Doc } from "../../../fields/Doc"; -import { ImageField } from "../../../fields/URLField"; -import { Cast, StrCast, NumCast } from "../../../fields/Types"; -import { Networking } from "../../Network"; -import { Id } from "../../../fields/FieldSymbols"; -import { Utils } from "../../../Utils"; +import { Doc } from '../../../fields/Doc'; +import { ImageField } from '../../../fields/URLField'; +import { Cast, StrCast, NumCast } from '../../../fields/Types'; +import { Networking } from '../../Network'; +import { Id } from '../../../fields/FieldSymbols'; +import { Utils } from '../../../Utils'; export namespace ImageUtils { - export const ExtractExif = async (document: Doc): Promise => { const field = Cast(document.data, ImageField); if (!field) { @@ -17,23 +16,22 @@ export namespace ImageUtils { contentSize, nativeWidth, nativeHeight, - exifData: { error, data } - } = await Networking.PostToServer("/inspectImage", { source }); + exifData: { error, data }, + } = await Networking.PostToServer('/inspectImage', { source }); document.exif = error || Doc.Get.FromJson({ data }); const proto = Doc.GetProto(document); - nativeWidth && (document._height = NumCast(document._width) * nativeHeight / nativeWidth); - proto["data-nativeWidth"] = nativeWidth; - proto["data-nativeHeight"] = nativeHeight; - proto["data-path"] = source; - proto.contentSize = contentSize ? contentSize : undefined; + nativeWidth && (document._height = (NumCast(document._width) * nativeHeight) / nativeWidth); + proto['data_nativeWidth'] = nativeWidth; + proto['data_nativeHeight'] = nativeHeight; + proto['data-path'] = source; + proto.data_contentSize = contentSize ? contentSize : undefined; return data !== undefined; }; export const ExportHierarchyToFileSystem = async (collection: Doc): Promise => { - const a = document.createElement("a"); + const a = document.createElement('a'); a.href = Utils.prepend(`/imageHierarchyExport/${collection[Id]}`); a.download = `Dash Export [${StrCast(collection.title)}].zip`; a.click(); }; - -} \ No newline at end of file +} diff --git a/src/client/util/InteractionUtils.tsx b/src/client/util/InteractionUtils.tsx index 9591dbed3..043f0f1f3 100644 --- a/src/client/util/InteractionUtils.tsx +++ b/src/client/util/InteractionUtils.tsx @@ -161,6 +161,7 @@ export namespace InteractionUtils { diff --git a/src/client/util/LinkFollower.ts b/src/client/util/LinkFollower.ts index ba2edb65c..246f5bb8c 100644 --- a/src/client/util/LinkFollower.ts +++ b/src/client/util/LinkFollower.ts @@ -12,8 +12,8 @@ import { SelectionManager } from './SelectionManager'; import { UndoManager } from './UndoManager'; /* * link doc: - * - anchor1: doc - * - anchor2: doc + * - link_anchor_1: doc + * - link_anchor_2: doc * * group doc: * - type: string representing the group type/name/category @@ -43,10 +43,10 @@ export class LinkFollower { public static traverseLink(link: Opt, sourceDoc: Doc, finished?: () => void, traverseBacklink?: boolean) { const linkDocs = link ? [link] : LinkManager.Links(sourceDoc); - const firstDocs = linkDocs.filter(linkDoc => Doc.AreProtosEqual(linkDoc.anchor1 as Doc, sourceDoc) || Doc.AreProtosEqual((linkDoc.anchor1 as Doc).annotationOn as Doc, sourceDoc)); // link docs where 'doc' is anchor1 - const secondDocs = linkDocs.filter(linkDoc => Doc.AreProtosEqual(linkDoc.anchor2 as Doc, sourceDoc) || Doc.AreProtosEqual((linkDoc.anchor2 as Doc).annotationOn as Doc, sourceDoc)); // link docs where 'doc' is anchor2 - const fwdLinkWithoutTargetView = firstDocs.find(d => DocumentManager.Instance.getDocumentViews((d.anchor2 as Doc).type === DocumentType.MARKER ? DocCast((d.anchor2 as Doc).annotationOn) : (d.anchor2 as Doc)).length === 0); - const backLinkWithoutTargetView = secondDocs.find(d => DocumentManager.Instance.getDocumentViews((d.anchor1 as Doc).type === DocumentType.MARKER ? DocCast((d.anchor1 as Doc).annotationOn) : (d.anchor1 as Doc)).length === 0); + const firstDocs = linkDocs.filter(linkDoc => Doc.AreProtosEqual(linkDoc.link_anchor_1 as Doc, sourceDoc) || Doc.AreProtosEqual((linkDoc.link_anchor_1 as Doc).annotationOn as Doc, sourceDoc)); // link docs where 'doc' is link_anchor_1 + const secondDocs = linkDocs.filter(linkDoc => Doc.AreProtosEqual(linkDoc.link_anchor_2 as Doc, sourceDoc) || Doc.AreProtosEqual((linkDoc.link_anchor_2 as Doc).annotationOn as Doc, sourceDoc)); // link docs where 'doc' is link_anchor_2 + const fwdLinkWithoutTargetView = firstDocs.find(d => DocumentManager.Instance.getDocumentViews((d.link_anchor_2 as Doc).type === DocumentType.MARKER ? DocCast((d.link_anchor_2 as Doc).annotationOn) : (d.link_anchor_2 as Doc)).length === 0); + const backLinkWithoutTargetView = secondDocs.find(d => DocumentManager.Instance.getDocumentViews((d.link_anchor_1 as Doc).type === DocumentType.MARKER ? DocCast((d.link_anchor_1 as Doc).annotationOn) : (d.link_anchor_1 as Doc)).length === 0); const linkWithoutTargetDoc = traverseBacklink === undefined ? fwdLinkWithoutTargetView || backLinkWithoutTargetView : traverseBacklink ? backLinkWithoutTargetView : fwdLinkWithoutTargetView; const linkDocList = linkWithoutTargetDoc && !sourceDoc.followAllLinks ? [linkWithoutTargetDoc] : traverseBacklink === undefined ? firstDocs.concat(secondDocs) : traverseBacklink ? secondDocs : firstDocs; const followLinks = sourceDoc.followLinkToggle || sourceDoc.followAllLinks ? linkDocList : linkDocList.slice(0, 1); @@ -55,13 +55,13 @@ export class LinkFollower { if (!followLinks.length) finished?.(); followLinks.forEach(async linkDoc => { const target = ( - sourceDoc === linkDoc.anchor1 - ? linkDoc.anchor2 - : sourceDoc === linkDoc.anchor2 - ? linkDoc.anchor1 - : Doc.AreProtosEqual(sourceDoc, linkDoc.anchor1 as Doc) || Doc.AreProtosEqual((linkDoc.anchor1 as Doc).annotationOn as Doc, sourceDoc) - ? linkDoc.anchor2 - : linkDoc.anchor1 + sourceDoc === linkDoc.link_anchor_1 + ? linkDoc.link_anchor_2 + : sourceDoc === linkDoc.link_anchor_2 + ? linkDoc.link_anchor_1 + : Doc.AreProtosEqual(sourceDoc, linkDoc.link_anchor_1 as Doc) || Doc.AreProtosEqual((linkDoc.link_anchor_1 as Doc).annotationOn as Doc, sourceDoc) + ? linkDoc.link_anchor_2 + : linkDoc.link_anchor_1 ) as Doc; if (target) { const doFollow = (canToggle?: boolean) => { @@ -92,16 +92,16 @@ export class LinkFollower { }; let movedTarget = false; if (sourceDoc.followLinkLocation === OpenWhere.inParent) { - const sourceDocParent = DocCast(sourceDoc.context); - if (target.context instanceof Doc && target.context !== sourceDocParent) { - Doc.RemoveDocFromList(target.context, Doc.LayoutFieldKey(target.context), target); + const sourceDocParent = DocCast(sourceDoc.embedContainer); + if (target.embedContainer instanceof Doc && target.embedContainer !== sourceDocParent) { + Doc.RemoveDocFromList(target.embedContainer, Doc.LayoutFieldKey(target.embedContainer), target); movedTarget = true; } if (!DocListCast(sourceDocParent[Doc.LayoutFieldKey(sourceDocParent)]).includes(target)) { Doc.AddDocToList(sourceDocParent, Doc.LayoutFieldKey(sourceDocParent), target); movedTarget = true; } - target.context = sourceDocParent; + target.embedContainer = sourceDocParent; const moveTo = [NumCast(sourceDoc.x) + NumCast(sourceDoc.followLinkXoffset), NumCast(sourceDoc.y) + NumCast(sourceDoc.followLinkYoffset)]; if (sourceDoc.followLinkXoffset !== undefined && moveTo[0] !== target.x) { target.x = moveTo[0]; diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts index 555215417..5e6107e5f 100644 --- a/src/client/util/LinkManager.ts +++ b/src/client/util/LinkManager.ts @@ -7,8 +7,8 @@ import { Cast, DocCast, PromiseValue, StrCast } from '../../fields/Types'; import { ScriptingGlobals } from './ScriptingGlobals'; /* * link doc: - * - anchor1: doc - * - anchor2: doc + * - link_anchor_1: doc + * - link_anchor_2: doc * * group doc: * - type: string representing the group type/name/category @@ -33,7 +33,7 @@ export class LinkManager { await Promise.all( ((await DocListCastAsync(linkDb.data)) ?? []).map(link => // makes sure link anchors are loaded to avoid incremental updates to computedFns in LinkManager - [PromiseValue(link?.anchor1), PromiseValue(link?.anchor2)] + [PromiseValue(link?.link_anchor_1), PromiseValue(link?.link_anchor_2)] ) ); LinkManager.userLinkDBs.push(linkDb); @@ -42,13 +42,13 @@ export class LinkManager { static _links: Doc[] = []; constructor() { LinkManager._instance = this; - this.createLinkrelationshipLists(); + this.createlink_relationshipLists(); LinkManager.userLinkDBs = []; const addLinkToDoc = (link: Doc) => { Promise.all([link]).then(linkdoc => { const link = DocCast(linkdoc[0]); Promise.all([link.proto]).then(linkproto => { - Promise.all([link.anchor1, link.anchor2]).then(linkdata => { + Promise.all([link.link_anchor_1, link.link_anchor_2]).then(linkdata => { const a1 = DocCast(linkdata[0]); const a2 = DocCast(linkdata[1]); a1 && @@ -64,8 +64,8 @@ export class LinkManager { }); }; const remLinkFromDoc = (link: Doc) => { - const a1 = link?.anchor1; - const a2 = link?.anchor2; + const a1 = link?.link_anchor_1; + const a2 = link?.link_anchor_2; Promise.all([a1, a2]).then( action(() => { if (a1 instanceof Doc && a2 instanceof Doc && ((a1.author !== undefined && a2.author !== undefined) || link.author === Doc.CurrentUserEmail)) { @@ -130,11 +130,11 @@ export class LinkManager { LinkManager.addLinkDB(Doc.LinkDBDoc()); } - public createLinkrelationshipLists = () => { + public createlink_relationshipLists = () => { //create new lists for link relations and their associated colors if the lists don't already exist - !Doc.UserDoc().linkRelationshipList && (Doc.UserDoc().linkRelationshipList = new List()); + !Doc.UserDoc().link_relationshipList && (Doc.UserDoc().link_relationshipList = new List()); !Doc.UserDoc().linkColorList && (Doc.UserDoc().linkColorList = new List()); - !Doc.UserDoc().linkRelationshipSizes && (Doc.UserDoc().linkRelationshipSizes = new List()); + !Doc.UserDoc().link_relationshipSizes && (Doc.UserDoc().link_relationshipSizes = new List()); }; public addLink(linkDoc: Doc, checkExists = false) { @@ -162,7 +162,7 @@ export class LinkManager { return []; } const dirLinks = Doc.GetProto(anchor)[DirectLinksSym]; - const annos = DocListCast(anchor[Doc.LayoutFieldKey(anchor) + '-annotations']); + const annos = DocListCast(anchor[Doc.LayoutFieldKey(anchor) + '_annotations']); if (!annos) debugger; return annos.reduce((list, anno) => [...list, ...LinkManager.Instance.relatedLinker(anno)], Array.from(dirLinks).slice()); }, true); @@ -171,9 +171,9 @@ export class LinkManager { public getRelatedGroupedLinks(anchor: Doc): Map> { const anchorGroups = new Map>(); this.relatedLinker(anchor).forEach(link => { - if (link.linkRelationship && link.linkRelationship !== '-ungrouped-') { - const relation = StrCast(link.linkRelationship); - const anchorRelation = relation.indexOf(':') !== -1 ? relation.split(':')[Doc.AreProtosEqual(Cast(link.anchor1, Doc, null), anchor) ? 0 : 1] : relation; + if (link.link_relationship && link.link_relationship !== '-ungrouped-') { + const relation = StrCast(link.link_relationship); + const anchorRelation = relation.indexOf(':') !== -1 ? relation.split(':')[Doc.AreProtosEqual(Cast(link.link_anchor_1, Doc, null), anchor) ? 0 : 1] : relation; const group = anchorGroups.get(anchorRelation); anchorGroups.set(anchorRelation, group ? [...group, link] : [link]); } else { @@ -189,8 +189,8 @@ export class LinkManager { //TODO This should probably return undefined if there isn't an opposite anchor //TODO This should also await the return value of the anchor so we don't filter out promises public static getOppositeAnchor(linkDoc: Doc, anchor: Doc): Doc | undefined { - const a1 = Cast(linkDoc.anchor1, Doc, null); - const a2 = Cast(linkDoc.anchor2, Doc, null); + const a1 = Cast(linkDoc.link_anchor_1, Doc, null); + const a2 = Cast(linkDoc.link_anchor_2, Doc, null); if (Doc.AreProtosEqual(anchor, a1)) return a2; if (Doc.AreProtosEqual(anchor, a2)) return a1; if (Doc.AreProtosEqual(anchor, a1.annotationOn as Doc)) return a2; diff --git a/src/client/util/ReplayMovements.ts b/src/client/util/ReplayMovements.ts index 22cca4a2e..cbc465d6a 100644 --- a/src/client/util/ReplayMovements.ts +++ b/src/client/util/ReplayMovements.ts @@ -127,8 +127,8 @@ export class ReplayMovements { zoomAndPan = (movement: Movement, document: CollectionFreeFormView) => { const { panX, panY, scale } = movement; scale !== 0 && document.zoomSmoothlyAboutPt([panX, panY], scale, 0); - document.Document._panX = panX; - document.Document._panY = panY; + document.Document._freeform_panX = panX; + document.Document._freeform_panY = panY; }; getFirstMovements = (movements: Movement[]): Map => { diff --git a/src/client/util/SearchUtil.ts b/src/client/util/SearchUtil.ts index 79759a71d..d154c48a4 100644 --- a/src/client/util/SearchUtil.ts +++ b/src/client/util/SearchUtil.ts @@ -24,51 +24,57 @@ export namespace SearchUtil { export interface SearchParams { hl?: string; - "hl.fl"?: string; + 'hl.fl'?: string; start?: number; rows?: number; fq?: string; sort?: string; - allowAliases?: boolean; - onlyAliases?: boolean; - "facet"?: string; - "facet.field"?: string; + allowEmbeddings?: boolean; + onlyEmbeddings?: boolean; + facet?: string; + 'facet.field'?: string; } export function Search(query: string, returnDocs: true, options?: SearchParams): Promise; export function Search(query: string, returnDocs: false, options?: SearchParams): Promise; export async function Search(query: string, returnDocs: boolean, options: SearchParams = {}) { - query = query || "*"; //If we just have a filter query, search for * as the query - const rpquery = Utils.prepend("/dashsearch"); + query = query || '*'; //If we just have a filter query, search for * as the query + const rpquery = Utils.prepend('/dashsearch'); let replacedQuery = query.replace(/type_t:([^ )])/g, (substring, arg) => `{!join from=id to=proto_i}*:* AND ${arg}`); - if (options.onlyAliases) { - const header = query.match(/_[atnb]?:/) ? replacedQuery : "DEFAULT:" + replacedQuery; + if (options.onlyEmbeddings) { + const header = query.match(/_[atnb]?:/) ? replacedQuery : 'DEFAULT:' + replacedQuery; replacedQuery = `{!join from=id to=proto_i}* AND ${header}`; } //console.log("Q: " + replacedQuery + " fq: " + options.fq); const gotten = await rp.get(rpquery, { qs: { ...options, q: replacedQuery } }); - const result: IdSearchResult = gotten.startsWith("<") ? { ids: [], docs: [], numFound: 0, lines: [] } : JSON.parse(gotten); + const result: IdSearchResult = gotten.startsWith('<') ? { ids: [], docs: [], numFound: 0, lines: [] } : JSON.parse(gotten); if (!returnDocs) { return result; } const { ids, highlighting } = result; - const txtresult = query !== "*" && JSON.parse(await rp.get(Utils.prepend("/textsearch"), { - qs: { ...options, q: query.replace(/^[ \+\?\*\|]*/, "") }, // a leading '+' leads to a server crash since findInFiles doesn't handle regex failures - })); + const txtresult = + query !== '*' && + JSON.parse( + await rp.get(Utils.prepend('/textsearch'), { + qs: { ...options, q: query.replace(/^[ \+\?\*\|]*/, '') }, // a leading '+' leads to a server crash since findInFiles doesn't handle regex failures + }) + ); const fileids = txtresult ? txtresult.ids : []; const newIds: string[] = []; const newLines: string[][] = []; - if (fileids) { - await Promise.all(fileids.map(async (tr: string, i: number) => { - const docQuery = "fileUpload_t:" + tr.substr(0, 7); //If we just have a filter query, search for * as the query - const docResult = JSON.parse(await rp.get(Utils.prepend("/dashsearch"), { qs: { ...options, q: docQuery } })); - newIds.push(...docResult.ids); - newLines.push(...docResult.ids.map((dr: any) => txtresult.lines[i])); - })); - } - + // bcz: we stopped storing fileUpload id's, so this won't find anything + // if (fileids) { + // await Promise.all( + // fileids.map(async (tr: string, i: number) => { + // const docQuery = 'fileUpload_t:' + tr.substr(0, 7); //If we just have a filter query, search for * as the query + // const docResult = JSON.parse(await rp.get(Utils.prepend('/dashsearch'), { qs: { ...options, q: docQuery } })); + // newIds.push(...docResult.ids); + // newLines.push(...docResult.ids.map((dr: any) => txtresult.lines[i])); + // }) + // ); + // } const theDocs: Doc[] = []; const theLines: string[][] = []; @@ -86,7 +92,7 @@ export namespace SearchUtil { const docs = ids.map((id: string) => docMap[id]).map(doc => doc as Doc); for (let i = 0; i < ids.length; i++) { const testDoc = docs[i]; - if (testDoc instanceof Doc && testDoc.type !== DocumentType.KVP && (options.allowAliases || testDoc.proto === undefined || theDocs.findIndex(d => Doc.AreProtosEqual(d, testDoc)) === -1)) { + if (testDoc instanceof Doc && testDoc.type !== DocumentType.KVP && (options.allowEmbeddings || testDoc.proto === undefined || theDocs.findIndex(d => Doc.AreProtosEqual(d, testDoc)) === -1)) { theDocs.push(testDoc); theLines.push([]); } else { @@ -97,48 +103,46 @@ export namespace SearchUtil { return { docs: theDocs, numFound: Math.max(0, result.numFound), highlighting, lines: theLines }; } - export async function GetAliasesOfDocument(doc: Doc): Promise; - export async function GetAliasesOfDocument(doc: Doc, returnDocs: false): Promise; - export async function GetAliasesOfDocument(doc: Doc, returnDocs = true): Promise { + export async function GetEmbeddingsOfDocument(doc: Doc): Promise; + export async function GetEmbeddingsOfDocument(doc: Doc, returnDocs: false): Promise; + export async function GetEmbeddingsOfDocument(doc: Doc, returnDocs = true): Promise { const proto = Doc.GetProto(doc); const protoId = proto[Id]; if (returnDocs) { - return (await Search("", returnDocs, { fq: `proto_i:"${protoId}"`, allowAliases: true })).docs; + return (await Search('', returnDocs, { fq: `proto_i:"${protoId}"`, allowEmbeddings: true })).docs; } else { - return (await Search("", returnDocs, { fq: `proto_i:"${protoId}"`, allowAliases: true })).ids; + return (await Search('', returnDocs, { fq: `proto_i:"${protoId}"`, allowEmbeddings: true })).ids; } // return Search(`{!join from=id to=proto_i}id:${protoId}`, true); } export async function GetViewsOfDocument(doc: Doc): Promise { - const results = await Search("", true, { fq: `proto_i:"${doc[Id]}"` }); + const results = await Search('', true, { fq: `proto_i:"${doc[Id]}"` }); return results.docs; } - export async function GetContextsOfDocument(doc: Doc): Promise<{ contexts: Doc[], aliasContexts: Doc[] }> { - const docContexts = (await Search("", true, { fq: `data_l:"${doc[Id]}"` })).docs; - const aliases = await GetAliasesOfDocument(doc, false); - const aliasContexts = (await Promise.all(aliases.map(doc => Search("", true, { fq: `data_l:"${doc}"` })))); - const contexts = { contexts: docContexts, aliasContexts: [] as Doc[] }; - aliasContexts.forEach(result => contexts.aliasContexts.push(...result.docs)); + export async function GetContextsOfDocument(doc: Doc): Promise<{ contexts: Doc[]; embeddingContexts: Doc[] }> { + const docContexts = (await Search('', true, { fq: `data_l:"${doc[Id]}"` })).docs; + const embeddings = await GetEmbeddingsOfDocument(doc, false); + const embeddingContexts = await Promise.all(embeddings.map(doc => Search('', true, { fq: `data_l:"${doc}"` }))); + const contexts = { contexts: docContexts, embeddingContexts: [] as Doc[] }; + embeddingContexts.forEach(result => contexts.embeddingContexts.push(...result.docs)); return contexts; } - export async function GetContextIdsOfDocument(doc: Doc): Promise<{ contexts: string[], aliasContexts: string[] }> { - const docContexts = (await Search("", false, { fq: `data_l:"${doc[Id]}"` })).ids; - const aliases = await GetAliasesOfDocument(doc, false); - const aliasContexts = (await Promise.all(aliases.map(doc => Search("", false, { fq: `data_l:"${doc}"` })))); - const contexts = { contexts: docContexts, aliasContexts: [] as string[] }; - aliasContexts.forEach(result => contexts.aliasContexts.push(...result.ids)); + export async function GetContextIdsOfDocument(doc: Doc): Promise<{ contexts: string[]; embeddingContexts: string[] }> { + const docContexts = (await Search('', false, { fq: `data_l:"${doc[Id]}"` })).ids; + const embeddings = await GetEmbeddingsOfDocument(doc, false); + const embeddingContexts = await Promise.all(embeddings.map(doc => Search('', false, { fq: `data_l:"${doc}"` }))); + const contexts = { contexts: docContexts, embeddingContexts: [] as string[] }; + embeddingContexts.forEach(result => contexts.embeddingContexts.push(...result.ids)); return contexts; } export async function GetAllDocs() { - const query = "*"; + const query = '*'; const response = await rp.get(Utils.prepend('/dashsearch'), { - qs: - { start: 0, rows: 10000, q: query }, - + qs: { start: 0, rows: 10000, q: query }, }); const result: IdSearchResult = JSON.parse(response); const { ids, numFound, highlighting } = result; diff --git a/src/client/util/SettingsManager.tsx b/src/client/util/SettingsManager.tsx index 396d754b6..a3a924b75 100644 --- a/src/client/util/SettingsManager.tsx +++ b/src/client/util/SettingsManager.tsx @@ -74,7 +74,7 @@ export class SettingsManager extends React.Component<{}> { }; @undoBatch selectUserMode = action((e: React.ChangeEvent) => (Doc.noviceMode = (e.currentTarget as any)?.value === 'Novice')); - @undoBatch changeShowTitle = action((e: React.ChangeEvent) => (Doc.UserDoc().showTitle = (e.currentTarget as any).value ? 'title' : undefined)); + @undoBatch changelayout_showTitle = action((e: React.ChangeEvent) => (Doc.UserDoc().layout_showTitle = (e.currentTarget as any).value ? 'title' : undefined)); @undoBatch changeFontFamily = action((e: React.ChangeEvent) => (Doc.UserDoc().fontFamily = (e.currentTarget as any).value)); @undoBatch changeFontSize = action((e: React.ChangeEvent) => (Doc.UserDoc().fontSize = (e.currentTarget as any).value)); @undoBatch switchActiveBackgroundColor = action((color: ColorState) => (Doc.UserDoc().activeCollectionBackground = String(color.hex))); @@ -176,7 +176,7 @@ export class SettingsManager extends React.Component<{}> { return (
- (Doc.UserDoc().showTitle = Doc.UserDoc().showTitle ? undefined : 'creationDate')} checked={Doc.UserDoc().showTitle !== undefined} /> + (Doc.UserDoc().layout_showTitle = Doc.UserDoc().layout_showTitle ? undefined : 'creationDate')} checked={Doc.UserDoc().layout_showTitle !== undefined} />
Show doc header
diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx index 4937866f8..0eecb31cf 100644 --- a/src/client/util/SharingManager.tsx +++ b/src/client/util/SharingManager.tsx @@ -172,7 +172,7 @@ export class SharingManager extends React.Component<{}> { this.setDashboardBackground(doc, permission as SharingPermissions); if (permission !== SharingPermissions.None) return Doc.AddDocToList(sharingDoc, storage, doc); - else return GetEffectiveAcl(doc, user.email) === AclPrivate && Doc.RemoveDocFromList(sharingDoc, storage, (doc.aliasOf as Doc) || doc); + return GetEffectiveAcl(doc, user.email) === AclPrivate && Doc.RemoveDocFromList(sharingDoc, storage, (doc.createdFrom as Doc) || doc); }) .some(success => !success); }; @@ -215,7 +215,7 @@ export class SharingManager extends React.Component<{}> { return users .map(({ user, sharingDoc }) => { if (permission !== SharingPermissions.None) return Doc.AddDocToList(sharingDoc, storage, doc); // add the doc to the sharingDoc if it hasn't already been added - else return GetEffectiveAcl(doc, user.email) === AclPrivate && Doc.RemoveDocFromList(sharingDoc, storage, (doc.aliasOf as Doc) || doc); // remove the doc from the list if it already exists + else return GetEffectiveAcl(doc, user.email) === AclPrivate && Doc.RemoveDocFromList(sharingDoc, storage, (doc.createdFrom as Doc) || doc); // remove the doc from the list if it already exists }) .some(success => !success); } diff --git a/src/client/util/SnappingManager.ts b/src/client/util/SnappingManager.ts index 2c0a1da8b..ed9819fc0 100644 --- a/src/client/util/SnappingManager.ts +++ b/src/client/util/SnappingManager.ts @@ -40,9 +40,9 @@ export namespace SnappingManager { } export function SetShowSnapLines(show: boolean) { - runInAction(() => (Doc.UserDoc().showSnapLines = show)); + runInAction(() => (Doc.UserDoc().freeform_snapLines = show)); } export function GetShowSnapLines() { - return Doc.UserDoc().showSnapLines; + return Doc.UserDoc().freeform_snapLines; } } diff --git a/src/client/util/TrackMovements.ts b/src/client/util/TrackMovements.ts index cb8225643..a755c5dc9 100644 --- a/src/client/util/TrackMovements.ts +++ b/src/client/util/TrackMovements.ts @@ -68,7 +68,7 @@ export class TrackMovements { } const disposeFunc = reaction( - () => ({ x: NumCast(doc.panX, -1), y: NumCast(doc.panY, -1), scale: NumCast(doc.viewScale, 0) }), + () => ({ x: NumCast(doc.freeform_panX, -1), y: NumCast(doc.freeform_panY, -1), scale: NumCast(doc.freeform_scale, 0) }), res => res.x !== -1 && res.y !== -1 && this.tracking && this.trackMovement(res.x, res.y, doc, res.scale) ); this.recordingFFViews?.set(doc, disposeFunc); diff --git a/src/client/views/AudioWaveform.tsx b/src/client/views/AudioWaveform.tsx index 525c0ce5a..14c922526 100644 --- a/src/client/views/AudioWaveform.tsx +++ b/src/client/views/AudioWaveform.tsx @@ -1,27 +1,25 @@ -import React = require("react"); -import axios from "axios"; -import { action, computed, IReactionDisposer, reaction } from "mobx"; -import { observer } from "mobx-react"; -import Waveform from "react-audio-waveform"; -import { Doc } from "../../fields/Doc"; -import { List } from "../../fields/List"; -import { listSpec } from "../../fields/Schema"; -import { Cast } from "../../fields/Types"; -import { numberRange } from "../../Utils"; -import "./AudioWaveform.scss"; -import { Colors } from "./global/globalEnums"; - +import React = require('react'); +import axios from 'axios'; +import { action, computed, IReactionDisposer, reaction } from 'mobx'; +import { observer } from 'mobx-react'; +import Waveform from 'react-audio-waveform'; +import { Doc } from '../../fields/Doc'; +import { List } from '../../fields/List'; +import { listSpec } from '../../fields/Schema'; +import { Cast } from '../../fields/Types'; +import { numberRange } from '../../Utils'; +import './AudioWaveform.scss'; +import { Colors } from './global/globalEnums'; /** * AudioWaveform - * + * * Used in CollectionStackedTimeline to render a canvas with a visual of an audio waveform for AudioBox and VideoBox documents. * Uses react-audio-waveform package. * Bins the audio data into audioBuckets which are passed to package to render the lines. * Calculates new buckets each time a new zoom factor or new set of trim bounds is created and stores it in a field on the layout doc with a title indicating the bounds and zoom for that list (see audioBucketField) */ - export interface AudioWaveformProps { duration: number; // length of media clip rawDuration: number; // length of underlying media data @@ -32,6 +30,7 @@ export interface AudioWaveformProps { zoomFactor: number; PanelHeight: number; PanelWidth: number; + fieldKey: string; } @observer @@ -40,80 +39,71 @@ export class AudioWaveform extends React.Component { _disposer: IReactionDisposer | undefined; - @computed get waveHeight() { return Math.max(50, this.props.PanelHeight); } - - @computed get clipStart() { return this.props.clipStart; } - @computed get clipEnd() { return this.props.clipEnd; } - @computed get zoomFactor() { return this.props.zoomFactor; } + @computed get waveHeight() { + return Math.max(50, this.props.PanelHeight); + } - @computed get audioBuckets() { return Cast(this.props.layoutDoc[this.audioBucketField(this.clipStart, this.clipEnd, this.zoomFactor)], listSpec("number"), []); } - audioBucketField = (start: number, end: number, zoomFactor: number) => "audioBuckets/" + "/" + start.toFixed(2).replace(".", "_") + "/" + end.toFixed(2).replace(".", "_") + "/" + (zoomFactor * 10); + @computed get clipStart() { + return this.props.clipStart; + } + @computed get clipEnd() { + return this.props.clipEnd; + } + @computed get zoomFactor() { + return this.props.zoomFactor; + } + @computed get audioBuckets() { + return Cast(this.props.layoutDoc[this.audioBucketField(this.clipStart, this.clipEnd, this.zoomFactor)], listSpec('number'), []); + } + audioBucketField = (start: number, end: number, zoomFactor: number) => this.props.fieldKey + '_audioBuckets/' + '/' + start.toFixed(2).replace('.', '_') + '/' + end.toFixed(2).replace('.', '_') + '/' + zoomFactor * 10; componentWillUnmount() { this._disposer?.(); } componentDidMount() { - this._disposer = reaction(() => ({ clipStart: this.clipStart, clipEnd: this.clipEnd, fieldKey: this.audioBucketField(this.clipStart, this.clipEnd, this.zoomFactor), zoomFactor: this.props.zoomFactor }), + this._disposer = reaction( + () => ({ clipStart: this.clipStart, clipEnd: this.clipEnd, fieldKey: this.audioBucketField(this.clipStart, this.clipEnd, this.zoomFactor), zoomFactor: this.props.zoomFactor }), ({ clipStart, clipEnd, fieldKey, zoomFactor }) => { if (!this.props.layoutDoc[fieldKey]) { // setting these values here serves as a "lock" to prevent multiple attempts to create the waveform at nerly the same time. - const waveform = Cast(this.props.layoutDoc[this.audioBucketField(0, this.props.rawDuration, 1)], listSpec("number")); - this.props.layoutDoc[fieldKey] = waveform && new List(waveform.slice(clipStart / this.props.rawDuration * waveform.length, clipEnd / this.props.rawDuration * waveform.length)); + const waveform = Cast(this.props.layoutDoc[this.audioBucketField(0, this.props.rawDuration, 1)], listSpec('number')); + this.props.layoutDoc[fieldKey] = waveform && new List(waveform.slice((clipStart / this.props.rawDuration) * waveform.length, (clipEnd / this.props.rawDuration) * waveform.length)); setTimeout(() => this.createWaveformBuckets(fieldKey, clipStart, clipEnd, zoomFactor)); } - }, { fireImmediately: true }); + }, + { fireImmediately: true } + ); } // decodes the audio file into peaks for generating the waveform createWaveformBuckets = async (fieldKey: string, clipStart: number, clipEnd: number, zoomFactor: number) => { - axios({ url: this.props.mediaPath, responseType: "arraybuffer" }).then( - (response) => { - const context = new window.AudioContext(); - context.decodeAudioData( - response.data, - action((buffer) => { - const rawDecodedAudioData = buffer.getChannelData(0); - const startInd = clipStart / this.props.rawDuration; - const endInd = clipEnd / this.props.rawDuration; - const decodedAudioData = rawDecodedAudioData.slice(Math.floor(startInd * rawDecodedAudioData.length), Math.floor(endInd * rawDecodedAudioData.length)); - const numBuckets = Math.floor(AudioWaveform.NUMBER_OF_BUCKETS * zoomFactor); + axios({ url: this.props.mediaPath, responseType: 'arraybuffer' }).then(response => { + const context = new window.AudioContext(); + context.decodeAudioData( + response.data, + action(buffer => { + const rawDecodedAudioData = buffer.getChannelData(0); + const startInd = clipStart / this.props.rawDuration; + const endInd = clipEnd / this.props.rawDuration; + const decodedAudioData = rawDecodedAudioData.slice(Math.floor(startInd * rawDecodedAudioData.length), Math.floor(endInd * rawDecodedAudioData.length)); + const numBuckets = Math.floor(AudioWaveform.NUMBER_OF_BUCKETS * zoomFactor); - const bucketDataSize = Math.floor( - decodedAudioData.length / numBuckets - ); - const brange = Array.from(Array(bucketDataSize)); - const bucketList = numberRange(numBuckets).map( - (i: number) => - brange.reduce( - (p, x, j) => - Math.abs( - Math.max(p, decodedAudioData[i * bucketDataSize + j]) - ), - 0 - ) / 2 - ); - this.props.layoutDoc[fieldKey] = new List(bucketList); - }) - ); - } - ); - } + const bucketDataSize = Math.floor(decodedAudioData.length / numBuckets); + const brange = Array.from(Array(bucketDataSize)); + const bucketList = numberRange(numBuckets).map((i: number) => brange.reduce((p, x, j) => Math.abs(Math.max(p, decodedAudioData[i * bucketDataSize + j])), 0) / 2); + this.props.layoutDoc[fieldKey] = new List(bucketList); + }) + ); + }); + }; render() { return (
- +
); } -} \ No newline at end of file +} diff --git a/src/client/views/DashboardView.tsx b/src/client/views/DashboardView.tsx index dee161931..02c5085a2 100644 --- a/src/client/views/DashboardView.tsx +++ b/src/client/views/DashboardView.tsx @@ -358,15 +358,15 @@ export class DashboardView extends React.Component { y: 400, _width: 1500, _height: 1000, - _fitWidth: true, - _backgroundGridShow: true, + _layout_fitWidth: true, + _freeform_backgroundGrid: true, backgroundColor: background, title: `Untitled Tab 1`, }; const title = name ? name : `Dashboard ${dashboardCount}`; const freeformDoc = Doc.GuestTarget || Docs.Create.FreeformDocument([], freeformOptions); const dashboardDoc = Docs.Create.StandardCollectionDockingDocument([{ doc: freeformDoc, initialWidth: 600 }], { title: title }, id, 'row'); - freeformDoc.context = dashboardDoc; + freeformDoc.embedContainer = dashboardDoc; // switching the tabs from the datadoc to the regular doc const dashboardTabs = DocListCast(dashboardDoc[DataSym].data); @@ -396,7 +396,7 @@ export class DashboardView extends React.Component { btnType: ButtonType.ClickButton, buttonText: 'New trail', icon: 'plus', - system: true, + isSystem: true, }; const reqdBtnScript = { onClick: `createNewPresentation()` }; const myTrailsBtn = DocUtils.AssignScripts(Docs.Create.FontIconDocument(reqdBtnOpts), reqdBtnScript); @@ -406,13 +406,13 @@ export class DashboardView extends React.Component { // but we don't want to create the list of trails here-- but rather in createDashboard const reqdOpts: DocumentOptions = { title: 'My Trails', - _showTitle: 'title', + _layout_showTitle: 'title', _height: 100, treeViewHideTitle: true, - _fitWidth: true, + _layout_fitWidth: true, _gridGap: 5, _forceActive: true, - childDropAction: 'alias', + childDropAction: 'embed', treeViewTruncateTitleWidth: 150, ignoreClick: true, buttonMenu: true, @@ -423,7 +423,7 @@ export class DashboardView extends React.Component { boxShadow: '0 0', childDontRegisterViews: true, targetDropAction: 'same', - system: true, + isSystem: true, explainer: 'All of the trails that you have created will appear here.', }; const myTrails = DocUtils.AssignScripts(Docs.Create.TreeDocument([], reqdOpts), { treeViewChildDoubleClick: 'openPresentation(documentView.rootDoc)' }); @@ -453,7 +453,7 @@ ScriptingGlobals.add(function resetDashboard(dashboard: Doc) { DashboardView.resetDashboard(dashboard); }, 'move all dashboard tabs to single stack'); ScriptingGlobals.add(function addToDashboards(dashboard: Doc) { - DashboardView.openDashboard(Doc.MakeAlias(dashboard)); + DashboardView.openDashboard(Doc.MakeEmbedding(dashboard)); }, 'adds Dashboard to set of Dashboards'); ScriptingGlobals.add(function snapshotDashboard() { DashboardView.snapshotDashboard(); diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index eba55e30c..ffb2d92f6 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -133,7 +133,7 @@ export function ViewBoxAnnotatableComponent

() protected _multiTouchDisposer?: InteractionUtils.MultiTouchEventDisposer; @computed public get annotationKey() { - return this.fieldKey + (this._annotationKeySuffix() ? '-' + this._annotationKeySuffix() : ''); + return this.fieldKey + (this._annotationKeySuffix() ? '_' + this._annotationKeySuffix() : ''); } @action.bound @@ -152,7 +152,7 @@ export function ViewBoxAnnotatableComponent

() toRemove.forEach(doc => { leavePushpin && DocUtils.LeavePushpin(doc, annotationKey ?? this.annotationKey); Doc.RemoveDocFromList(targetDataDoc, annotationKey ?? this.annotationKey, doc); - doc.context = undefined; + doc.embedContainer = undefined; if (recent) { Doc.RemoveDocFromList(recent, 'data', doc); doc.type !== DocumentType.LOADING && Doc.AddDocToList(recent, 'data', doc, undefined, true, true); @@ -193,18 +193,19 @@ export function ViewBoxAnnotatableComponent

() } const added = docs; if (added.length) { - if (this.props.Document[AclSym] && Object.keys(this.props.Document[AclSym]).length) { + const aclKeys = Object.keys(this.props.Document[AclSym] ?? {}); + aclKeys.forEach(key => added.forEach(d => { - for (const key of Object.keys(this.props.Document[AclSym])) { - if (d.author === denormalizeEmail(key.substring(4)) && !d.aliasOf) distributeAcls(key, SharingPermissions.Admin, d); + if (d.author === denormalizeEmail(key.substring(4)) && !d.createdFrom) { + distributeAcls(key, SharingPermissions.Admin, d); } - }); - } + }) + ); if (effectiveAcl === AclAugment) { added.map(doc => { if ([AclAdmin, AclEdit].includes(GetEffectiveAcl(doc)) && Doc.ActiveDashboard) inheritParentAcls(Doc.ActiveDashboard, doc); - doc.context = this.props.Document; + doc.embedContainer = this.props.Document; if (annotationKey ?? this._annotationKeySuffix()) Doc.GetProto(doc).annotationOn = this.props.Document; Doc.AddDocToList(targetDataDoc, annotationKey ?? this.annotationKey, doc); }); @@ -215,7 +216,7 @@ export function ViewBoxAnnotatableComponent

() // only make a pushpin if we have acl's to edit the document //DocUtils.LeavePushpin(doc); doc._stayInCollection = undefined; - doc.context = this.props.Document; + doc.embedContainer = this.props.Document; if (annotationKey ?? this._annotationKeySuffix()) Doc.GetProto(doc).annotationOn = this.rootDoc; Doc.ActiveDashboard && inheritParentAcls(Doc.ActiveDashboard, doc); @@ -223,7 +224,7 @@ export function ViewBoxAnnotatableComponent

() const annoDocs = targetDataDoc[annotationKey ?? this.annotationKey] as List; if (annoDocs instanceof List) annoDocs.push(...added); else targetDataDoc[annotationKey ?? this.annotationKey] = new List(added); - targetDataDoc[(annotationKey ?? this.annotationKey) + '-lastModified'] = new DateField(new Date(Date.now())); + targetDataDoc[(annotationKey ?? this.annotationKey) + '_modificationDate'] = new DateField(new Date(Date.now())); } } return true; diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx index 30e41b06c..547d844ca 100644 --- a/src/client/views/DocumentButtonBar.tsx +++ b/src/client/views/DocumentButtonBar.tsx @@ -178,7 +178,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV e.preventDefault(); let googleDoc = await Cast(dataDoc.googleDoc, Doc); if (!googleDoc) { - const options = { _width: 600, _nativeWidth: 960, _nativeHeight: 800, useCors: false }; + const options = { _width: 600, _nativeWidth: 960, _nativeHeight: 800, data_useCors: false }; googleDoc = Docs.Create.WebDocument(googleDocUrl, options); dataDoc.googleDoc = googleDoc; } @@ -473,17 +473,17 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV ); } - @observable _aliasDown = false; + @observable _embedDown = false; onTemplateButton = action((e: React.PointerEvent): void => { this._tooltipOpen = false; - setupMoveUpEvents(this, e, this.onAliasButtonMoved, emptyFunction, emptyFunction); + setupMoveUpEvents(this, e, this.onEmbedButtonMoved, emptyFunction, emptyFunction); }); - onAliasButtonMoved = () => { + onEmbedButtonMoved = () => { if (this._dragRef.current) { const dragDocView = this.view0!; const dragData = new DragManager.DocumentDragData([dragDocView.props.Document]); const [left, top] = dragDocView.props.ScreenToLocalTransform().inverse().transformPoint(0, 0); - dragData.defaultDropAction = 'alias'; + dragData.defaultDropAction = 'embed'; dragData.canEmbed = true; DragManager.StartDocumentDrag([dragDocView.ContentDiv!], dragData, left, top, { hideSource: false }); return true; @@ -498,14 +498,14 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV const view0 = this.view0; const views = this.props.views(); return !view0 ? null : ( - Tap to Customize Layout. Drag an embeddable alias

} open={this._tooltipOpen} onClose={action(() => (this._tooltipOpen = false))} placement="bottom"> + Tap to Customize Layout. Drag an embedding
} open={this._tooltipOpen} onClose={action(() => (this._tooltipOpen = false))} placement="bottom">
!this._ref.current?.getBoundingClientRect().width && (this._tooltipOpen = true))}> (this._aliasDown = true))} - onClose={action(() => (this._aliasDown = false))} + onOpen={action(() => (this._embedDown = true))} + onClose={action(() => (this._embedDown = false))} content={ - !this._aliasDown ? null : ( + !this._embedDown ? null : (
{' '} v).map(v => v as DocumentView)} /> @@ -564,7 +564,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV const anchor = rootView.ComponentView?.getAnchor?.(false) ?? rootDoc; const trail = DocCast(anchor.presTrail) ?? Doc.MakeCopy(DocCast(Doc.UserDoc().emptyTrail), true); if (trail !== anchor.presTrail) { - DocUtils.MakeLink(anchor, trail, { linkRelationship: 'link trail' }); + DocUtils.MakeLink(anchor, trail, { link_relationship: 'link trail' }); anchor.presTrail = trail; } Doc.ActivePresentation = trail; @@ -589,7 +589,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV (link.linkDisplay = !IsFollowLinkScript(this.props.views().lastElement()?.rootDoc.onClick))} + linkCreated={link => (link.layout_linkDisplay = !IsFollowLinkScript(this.props.views().lastElement()?.rootDoc.onClick))} linkCreateAnchor={() => this.props.views().lastElement()?.ComponentView?.getAnchor?.(true)} linkFrom={() => this.props.views().lastElement()?.rootDoc} /> diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 26b64bfdd..39073d763 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -121,7 +121,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P titleFieldKey && SelectionManager.Views().forEach(d => { if (titleFieldKey === 'title') { - d.dataDoc['title-custom'] = !this._accumulatedTitle.startsWith('-'); + d.dataDoc.title_custom = !this._accumulatedTitle.startsWith('-'); if (StrCast(d.rootDoc.title).startsWith('@') && !this._accumulatedTitle.startsWith('@')) { Doc.RemoveDocFromList(Doc.MyPublishedDocs, undefined, d.rootDoc); } @@ -138,12 +138,12 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P if (curKey !== title) { if (title) { if (d.dataDoc[title] === undefined || d.dataDoc[title] instanceof RichTextField || typeof d.dataDoc[title] === 'string') { - d.rootDoc.layoutKey = `layout_${title}`; + d.rootDoc.layout_fieldKey = `layout_${title}`; d.rootDoc[`layout_${title}`] = FormattedTextBox.LayoutString(title); - d.rootDoc[`${title}-nativeWidth`] = d.rootDoc[`${title}-nativeHeight`] = 0; + d.rootDoc[`${title}_nativeWidth`] = d.rootDoc[`${title}_nativeHeight`] = 0; } } else { - d.rootDoc.layoutKey = undefined; + d.rootDoc.layout_fieldKey = undefined; } } } else { @@ -272,22 +272,22 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P const selectedDocs = SelectionManager.Views(); if (selectedDocs.length) { if (e.ctrlKey) { - // open an alias in a new tab with Ctrl Key - CollectionDockingView.AddSplit(Doc.BestAlias(selectedDocs[0].props.Document), OpenWhereMod.right); + // open an embedding in a new tab with Ctrl Key + CollectionDockingView.AddSplit(Doc.BestEmbedding(selectedDocs[0].props.Document), OpenWhereMod.right); } else if (e.shiftKey) { // open centered in a new workspace with Shift Key - const alias = Doc.MakeAlias(selectedDocs[0].props.Document); - alias.context = undefined; - alias.x = -alias[WidthSym]() / 2; - alias.y = -alias[HeightSym]() / 2; - CollectionDockingView.AddSplit(Docs.Create.FreeformDocument([alias], { title: 'Tab for ' + alias.title }), OpenWhereMod.right); + const embedding = Doc.MakeEmbedding(selectedDocs[0].props.Document); + embedding.embedContainer = undefined; + embedding.x = -embedding[WidthSym]() / 2; + embedding.y = -embedding[HeightSym]() / 2; + CollectionDockingView.AddSplit(Docs.Create.FreeformDocument([embedding], { title: 'Tab for ' + embedding.title }), OpenWhereMod.right); } else if (e.altKey) { // open same document in new tab CollectionDockingView.ToggleSplit(selectedDocs[0].props.Document, OpenWhereMod.right); } else { var openDoc = selectedDocs[0].props.Document; - if (openDoc.layoutKey === 'layout_icon') { - openDoc = DocListCast(openDoc.aliases).find(alias => !alias.context) ?? Doc.MakeAlias(openDoc); + if (openDoc.layout_fieldKey === 'layout_icon') { + openDoc = DocListCast(openDoc.proto_embeddings).find(embedding => !embedding.embedContainer) ?? Doc.MakeEmbedding(openDoc); Doc.deiconifyView(openDoc); } LightboxView.SetLightboxDoc( @@ -368,8 +368,8 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P const newloccentern = seldocview.props.ScreenToLocalTransform().transformPoint(rotCenter[0], rotCenter[1]); const newlocenter = [newloccentern[0] - NumCast(seldocview.layoutDoc._width) / 2, newloccentern[1] - NumCast(seldocview.layoutDoc._height) / 2]; const final = Utils.rotPt(newlocenter[0], newlocenter[1], -(NumCast(seldocview.rootDoc._rotation) / 180) * Math.PI); - seldocview.rootDoc.rotateCenterX = final.x / NumCast(seldocview.layoutDoc._width); - seldocview.rootDoc.rotateCenterY = final.y / NumCast(seldocview.layoutDoc._height); + seldocview.rootDoc.rotation_centerX = final.x / NumCast(seldocview.layoutDoc._width); + seldocview.rootDoc.rotation_centerY = final.y / NumCast(seldocview.layoutDoc._height); }; @action @@ -386,8 +386,8 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P action(action(() => (this._isRotating = false))), // upEvent action((e, doubleTap) => { if (doubleTap) { - seldocview.rootDoc.rotateCenterX = 0.5; - seldocview.rootDoc.rotateCenterY = 0.5; + seldocview.rootDoc.rotation_centerX = 0.5; + seldocview.rootDoc.rotation_centerY = 0.5; } }) ); @@ -586,7 +586,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P let dW = docwidth * (dWin / refWidth); let dH = docheight * (dHin / refHeight); const scale = docView.props.ScreenToLocalTransform().Scale; - const modifyNativeDim = (e.ctrlKey || doc.forceReflow) && doc.nativeDimModifiable && ((!dragBottom && !dragTop) || e.ctrlKey || doc.nativeHeightUnfrozen); + const modifyNativeDim = (e.ctrlKey || doc.layout_forceReflow) && doc.nativeDimModifiable && ((!dragBottom && !dragTop) || e.ctrlKey || doc.nativeHeightUnfrozen); if (nwidth && nheight) { if (nwidth / nheight !== docwidth / docheight && !dragBottom && !dragTop) { docheight = (nheight / nwidth) * docwidth; @@ -602,7 +602,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P let dX = !dWin ? 0 : scale * refCent[0] * (1 - (1 + dWin / refWidth)); let dY = !dHin ? 0 : scale * refCent[1] * (1 - (1 + dHin / refHeight)); const preserveNativeDim = doc._nativeHeightUnfrozen === false && doc._nativeDimModifiable === false; - const fixedAspect = nwidth && nheight && (!doc._fitWidth || preserveNativeDim || e.ctrlKey || doc.nativeHeightUnfrozen || doc.nativeDimModifiable); + const fixedAspect = nwidth && nheight && (!doc._layout_fitWidth || preserveNativeDim || e.ctrlKey || doc.nativeHeightUnfrozen || doc.nativeDimModifiable); if (fixedAspect) { if ((Math.abs(dW) > Math.abs(dH) && ((!dragBottom && !dragTop) || !modifyNativeDim)) || dragRight) { if (dragRight && modifyNativeDim) { @@ -610,7 +610,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P doc._nativeWidth = (actualdW / (docwidth || 1)) * Doc.NativeWidth(doc); } } else { - if (!doc._fitWidth || preserveNativeDim) { + if (!doc._layout_fitWidth || preserveNativeDim) { actualdH = (nheight / nwidth) * actualdW; doc._height = actualdH; } else if (!modifyNativeDim || dragBotRight) { @@ -619,14 +619,14 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P } doc._width = actualdW; } else { - if ((dragBottom || dragTop) && (modifyNativeDim || (docView.layoutDoc.nativeHeightUnfrozen && docView.layoutDoc._fitWidth))) { + if ((dragBottom || dragTop) && (modifyNativeDim || (docView.layoutDoc.nativeHeightUnfrozen && docView.layoutDoc._layout_fitWidth))) { // frozen web pages, PDFs, and some RTFS have frozen nativewidth/height. But they are marked to allow their nativeHeight // to be explicitly modified with fitWidth and vertical resizing. (ie, with fitWidth they can't grow horizontally to match // a vertical resize so it makes more sense to change their nativeheight even if the ctrl key isn't used) doc._nativeHeight = (actualdH / (docheight || 1)) * Doc.NativeHeight(doc); - doc._autoHeight = false; + doc._layout_autoHeight = false; } else { - if (!doc._fitWidth || preserveNativeDim) { + if (!doc._layout_fitWidth || preserveNativeDim) { actualdW = (nwidth / nheight) * actualdH; doc._width = actualdW; } else if (!modifyNativeDim || dragBotRight) { @@ -642,10 +642,10 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P const rotCtr = [docwidth / 2, docheight / 2]; const tlRotated = Utils.rotPt(-rotCtr[0], -rotCtr[1], (NumCast(doc._rotation) / 180) * Math.PI); - const maxHeight = doc.nativeHeightUnfrozen || !nheight ? 0 : Math.max(nheight, NumCast(doc.scrollHeight, NumCast(doc[docView.LayoutFieldKey + '-scrollHeight']))) * docView.NativeDimScaling(); + const maxHeight = doc.nativeHeightUnfrozen || !nheight ? 0 : Math.max(nheight, NumCast(doc.scrollHeight, NumCast(doc[docView.LayoutFieldKey + '_scrollHeight']))) * docView.NativeDimScaling(); dH && (doc._height = actualdH > maxHeight && maxHeight ? maxHeight : actualdH); dW && (doc._width = actualdW); - dH && (doc._autoHeight = false); + dH && (doc._layout_autoHeight = false); const rotCtr2 = [NumCast(doc._width) / 2, NumCast(doc._height) / 2]; const tlRotated2 = Utils.rotPt(-rotCtr2[0], -rotCtr2[1], (NumCast(doc._rotation) / 180) * Math.PI); @@ -654,7 +654,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P } doc.x = NumCast(doc.x) + dX; doc.y = NumCast(doc.y) + dY; - doc._lastModified = new DateField(); + doc._layout_modificationDate = new DateField(); } const val = this._dragHeights.get(docView.layoutDoc); if (val) this._dragHeights.set(docView.layoutDoc, { start: val.start, lowest: Math.min(val.lowest, NumCast(docView.layoutDoc._height)) }); @@ -670,11 +670,11 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P this._resizeUndo?.end(); SnappingManager.clearSnapLines(); - // detect autoHeight gesture and apply + // detect layout_autoHeight gesture and apply SelectionManager.Views() .map(docView => ({ doc: docView.layoutDoc, hgts: this._dragHeights.get(docView.layoutDoc) })) .filter(pair => pair.hgts && pair.hgts.lowest < pair.hgts.start && pair.hgts.lowest <= 20) - .forEach(pair => (pair.doc._autoHeight = true)); + .forEach(pair => (pair.doc._layout_autoHeight = true)); //need to change points for resize, or else rotation/control points will fail. this._inkDragDocs .map(oldbds => ({ oldbds, inkPts: Cast(oldbds.doc.data, InkField)?.inkData || [] })) @@ -713,7 +713,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P } @computed get hasIcons() { - return SelectionManager.Views().some(docView => docView.rootDoc.layoutKey === 'layout_icon'); + return SelectionManager.Views().some(docView => docView.rootDoc.layout_fieldKey === 'layout_icon'); } @observable _showRotCenter = false; @@ -722,8 +722,8 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P if (SelectionManager.Views().length) { const seldocview = SelectionManager.Views()[0]; const loccenter = Utils.rotPt( - NumCast(seldocview.rootDoc.rotateCenterX) * NumCast(seldocview.layoutDoc._width), - NumCast(seldocview.rootDoc.rotateCenterY) * NumCast(seldocview.layoutDoc._height), + NumCast(seldocview.rootDoc.rotation_centerX) * NumCast(seldocview.layoutDoc._width), + NumCast(seldocview.rootDoc.rotation_centerY) * NumCast(seldocview.layoutDoc._height), (NumCast(seldocview.rootDoc._rotation) / 180) * Math.PI ); return seldocview.props @@ -746,8 +746,8 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P } // hide the decorations if the parent chooses to hide it or if the document itself hides it const hideDecorations = seldocview.props.hideDecorations || seldocview.rootDoc.hideDecorations; - const hideResizers = hideDecorations || seldocview.props.hideResizeHandles || seldocview.rootDoc.hideResizeHandles || this._isRounding || this._isRotating; - const hideTitle = hideDecorations || seldocview.props.hideDecorationTitle || seldocview.rootDoc.hideDecorationTitle || this._isRounding || this._isRotating; + const hideResizers = hideDecorations || seldocview.props.hideResizeHandles || seldocview.rootDoc.layout_hideResizeHandles || this._isRounding || this._isRotating; + const hideTitle = hideDecorations || seldocview.props.hideDecorationTitle || seldocview.rootDoc.layout_hideDecorationTitle || this._isRounding || this._isRotating; const hideDocumentButtonBar = hideDecorations || seldocview.props.hideDocumentButtonBar || seldocview.rootDoc.hideDocumentButtonBar || this._isRounding || this._isRotating; // if multiple documents have been opened at the same time, then don't show open button const hideOpenButton = @@ -765,7 +765,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P seldocview.rootDoc.hideDeleteButton || SelectionManager.Views().some(docView => { const collectionAcl = docView.props.docViewPath()?.lastElement() ? GetEffectiveAcl(docView.props.docViewPath().lastElement().rootDoc[DataSym]) : AclEdit; - return docView.rootDoc.stayInCollection || (collectionAcl !== AclAdmin && collectionAcl !== AclEdit && GetEffectiveAcl(docView.rootDoc) !== AclAdmin); + return (docView.rootDoc.stayInCollection && !docView.rootDoc.timelineLabel) || (collectionAcl !== AclAdmin && collectionAcl !== AclEdit && GetEffectiveAcl(docView.rootDoc) !== AclAdmin); }); const topBtn = (key: string, icon: string, pointerDown: undefined | ((e: React.PointerEvent) => void), click: undefined | ((e: any) => void), title: string) => ( @@ -871,7 +871,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P {hideDeleteButton ? null : topBtn('close', 'times', undefined, e => this.onCloseClick(true), 'Close')} {hideResizers || hideDeleteButton ? null : topBtn('minimize', 'window-maximize', undefined, e => this.onCloseClick(undefined), 'Minimize')} {hideTitle ? null : titleArea} - {hideOpenButton ? null : topBtn('open', 'external-link-alt', this.onMaximizeDown, undefined, 'Open in Lightbox (ctrl: as alias, shift: in new collection)')} + {hideOpenButton ? null : topBtn('open', 'external-link-alt', this.onMaximizeDown, undefined, 'Open in Lightbox (ctrl: as new embedding, shift: in new collection)')}
{hideResizers ? null : ( <> diff --git a/src/client/views/FilterPanel.tsx b/src/client/views/FilterPanel.tsx index 84b2e1407..75e0e7c4c 100644 --- a/src/client/views/FilterPanel.tsx +++ b/src/client/views/FilterPanel.tsx @@ -46,14 +46,14 @@ export class FilterPanel extends React.Component { @computed get _allFacets() { // trace(); const noviceReqFields = ['author', 'tags', 'text', 'type']; - const noviceLayoutFields: string[] = []; //["_curPage"]; + const noviceLayoutFields: string[] = []; //["_layout_curPage"]; const noviceFields = [...noviceReqFields, ...noviceLayoutFields]; const keys = new Set(noviceFields); this.allDocs.forEach(doc => SearchBox.documentKeys(doc).filter(key => keys.add(key))); const sortedKeys = Array.from(keys.keys()) .filter(key => key[0]) - .filter(key => key.indexOf('lastModified') !== -1 || (key[0] === key[0].toUpperCase() && !key.startsWith('_')) || noviceFields.includes(key) || !Doc.noviceMode) + .filter(key => key.indexOf('modificationDate') !== -1 || (key[0] === key[0].toUpperCase() && !key.startsWith('_')) || noviceFields.includes(key) || !Doc.noviceMode) .sort(); noviceFields.forEach(key => sortedKeys.splice(sortedKeys.indexOf(key), 1)); return [...noviceFields, ...sortedKeys]; @@ -88,7 +88,7 @@ export class FilterPanel extends React.Component { (facetVal === true || facetVal == false) && valueSet.add(Field.toString(!facetVal)); const fieldKey = Doc.LayoutFieldKey(t); const annos = !Field.toString(Doc.LayoutField(t) as Field).includes('CollectionView'); - DocListCast(t[annos ? fieldKey + '-annotations' : fieldKey]).forEach(newdoc => newarray.push(newdoc)); + DocListCast(t[annos ? fieldKey + '_annotations' : fieldKey]).forEach(newdoc => newarray.push(newdoc)); }); subDocs = newarray; } diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx index b04769c1e..141e99c66 100644 --- a/src/client/views/GestureOverlay.tsx +++ b/src/client/views/GestureOverlay.tsx @@ -102,7 +102,7 @@ export class GestureOverlay extends Touchable { icon: 'clipboard', pointerUp: 'GestureOverlay.Instance.closeFloatingDoc()', pointerDown: 'GestureOverlay.Instance.openFloatingDoc(this.clipboard)', - clipboard: Docs.Create.FreeformDocument([], { _width: 300, _height: 300, system: true }), + clipboard: Docs.Create.FreeformDocument([], { _width: 300, _height: 300, isSystem: true }), backgroundColor: 'orange', }, { title: 'interpret text', icon: 'font', toolType: 'inktotext', pointerUp: "setToolglass('none')", pointerDown: 'setToolglass(self.toolType)', backgroundColor: 'orange' }, @@ -125,7 +125,7 @@ export class GestureOverlay extends Touchable { onPointerDown: data.pointerDown ? ScriptField.MakeScript(data.pointerDown) : undefined, backgroundColor: data.backgroundColor, dragFactory: data.dragFactory, - system: true, + isSystem: true, }) ); } @@ -138,19 +138,19 @@ export class GestureOverlay extends Touchable { ignoreClick: true, _lockedPosition: true, title: 'buttons', - _autoHeight: true, + _layout_autoHeight: true, _yMargin: 5, linearViewIsExpanded: true, backgroundColor: 'white', - system: true, + isSystem: true, }); thumbDoc.inkToTextDoc = Docs.Create.LinearDocument([], { _width: 300, _height: 25, - _autoHeight: true, + _layout_autoHeight: true, linearViewIsExpanded: true, flexDirection: 'column', - system: true, + isSystem: true, }); userDoc.thumbDoc = thumbDoc; } @@ -916,7 +916,7 @@ export class GestureOverlay extends Touchable { @computed get elements() { const selView = GestureOverlay.DownDocView; - const width = Number(ActiveInkWidth()) * NumCast(selView?.rootDoc._viewScale, 1); // * (selView?.props.ScreenToLocalTransform().Scale || 1); + const width = Number(ActiveInkWidth()) * NumCast(selView?.rootDoc._freeform_scale, 1); // * (selView?.props.ScreenToLocalTransform().Scale || 1); const rect = this._overlayRef.current?.getBoundingClientRect(); const B = { left: -20000, right: 20000, top: -20000, bottom: 20000, width: 40000, height: 40000 }; //this.getBounds(this._points, true); B.left = B.left - width / 2; diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts index 0f8b46dbe..b9b92dd2b 100644 --- a/src/client/views/GlobalKeyHandler.ts +++ b/src/client/views/GlobalKeyHandler.ts @@ -374,10 +374,10 @@ export class KeyManager { if (count === docids.length) { const added = await Promise.all(list.filter(d => !docList.includes(d)).map(async d => (clone ? (await Doc.MakeClone(d, true)).clone : d))); if (added.length) { - added.map(doc => (doc.context = targetDataDoc)); + added.map(doc => (doc.embedContainer = targetDataDoc)); undoBatch(() => { targetDataDoc[fieldKey] = new List([...docList, ...added]); - targetDataDoc[fieldKey + '-lastModified'] = new DateField(new Date(Date.now())); + targetDataDoc[fieldKey + '_modificationDate'] = new DateField(new Date(Date.now())); })(); } } diff --git a/src/client/views/InkStrokeProperties.ts b/src/client/views/InkStrokeProperties.ts index 156825f41..d28981e17 100644 --- a/src/client/views/InkStrokeProperties.ts +++ b/src/client/views/InkStrokeProperties.ts @@ -50,21 +50,21 @@ export class InkStrokeProperties { if (!requireCurrPoint || this._currentPoint !== -1) { const doc = inkView.rootDoc; if (doc.type === DocumentType.INK && doc.width && doc.height) { - const ink = Cast(doc.data, InkField)?.inkData; + const ink = Cast(doc.stroke, InkField)?.inkData; if (ink) { const oldXrange = (xs => ({ coord: NumCast(doc.x), min: Math.min(...xs), max: Math.max(...xs) }))(ink.map(p => p.X)); const oldYrange = (ys => ({ coord: NumCast(doc.y), min: Math.min(...ys), max: Math.max(...ys) }))(ink.map(p => p.Y)); - const ptsXscale = (NumCast(doc._width) - NumCast(doc.strokeWidth)) / (oldXrange.max - oldXrange.min || 1) || 1; - const ptsYscale = (NumCast(doc._height) - NumCast(doc.strokeWidth)) / (oldYrange.max - oldYrange.min || 1) || 1; - const newPoints = func(inkView, ink, ptsXscale, ptsYscale, NumCast(doc.strokeWidth)); + const ptsXscale = (NumCast(doc._width) - NumCast(doc.stroke_width)) / (oldXrange.max - oldXrange.min || 1) || 1; + const ptsYscale = (NumCast(doc._height) - NumCast(doc.stroke_width)) / (oldYrange.max - oldYrange.min || 1) || 1; + const newPoints = func(inkView, ink, ptsXscale, ptsYscale, NumCast(doc.stroke_width)); if (newPoints) { const newXrange = (xs => ({ min: Math.min(...xs), max: Math.max(...xs) }))(newPoints.map(p => p.X)); const newYrange = (ys => ({ min: Math.min(...ys), max: Math.max(...ys) }))(newPoints.map(p => p.Y)); - doc._width = (newXrange.max - newXrange.min) * ptsXscale + NumCast(doc.strokeWidth); - doc._height = (newYrange.max - newYrange.min) * ptsYscale + NumCast(doc.strokeWidth); + doc._width = (newXrange.max - newXrange.min) * ptsXscale + NumCast(doc.stroke_width); + doc._height = (newYrange.max - newYrange.min) * ptsYscale + NumCast(doc.stroke_width); doc.x = oldXrange.coord + (newXrange.min - oldXrange.min) * ptsXscale; doc.y = oldYrange.coord + (newYrange.min - oldYrange.min) * ptsYscale; - Doc.GetProto(doc).data = new InkField(newPoints); + Doc.GetProto(doc).stroke = new InkField(newPoints); appliedFunc = true; } } diff --git a/src/client/views/InkTranscription.tsx b/src/client/views/InkTranscription.tsx index 246b887a6..d6a6a64bf 100644 --- a/src/client/views/InkTranscription.tsx +++ b/src/client/views/InkTranscription.tsx @@ -172,7 +172,7 @@ export class InkTranscription extends React.Component { if (!selected) { return; } - const ctx = await Cast(selected[0].context, Doc); + const ctx = await Cast(selected[0].embedContainer, Doc); if (!ctx) { return; } diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx index 2fd6cc4d6..14c5dc58d 100644 --- a/src/client/views/InkingStroke.tsx +++ b/src/client/views/InkingStroke.tsx @@ -6,7 +6,7 @@ point 1, tangent pt 1, tangent pt 2, point 2, point 3, tangent pt 3, ... (Note that segment endpoints are duplicated ie Point2 = Point 3) brokenIndices - an array of indexes into the data field where the incoming and outgoing tangents are not constrained to be equal text - a text field that will be centered within a closed ink stroke - isInkMask - a flag that makes the ink stroke render as a mask over its collection where the stroke itself is mixBlendMode multiplied by + stroke_isInkMask - a flag that makes the ink stroke render as a mask over its collection where the stroke itself is mixBlendMode multiplied by the underlying collection content, and everything outside the stroke is covered by a semi-opaque dark gray mask. The coordinates of the ink data need to be mapped to the screen since ink points are not changed when the DocumentView is translated or scaled. @@ -134,7 +134,7 @@ export class InkingStroke extends ViewBoxBaseComponent() { * dimmed by a semi-opaque overlay mask. */ public static toggleMask = action((inkDoc: Doc) => { - inkDoc.isInkMask = !inkDoc.isInkMask; + inkDoc.stroke_isInkMask = !inkDoc.stroke_isInkMask; }); @observable controlUndo: UndoManager.Batch | undefined; /** @@ -241,7 +241,7 @@ export class InkingStroke extends ViewBoxBaseComponent() { */ inkScaledData = () => { const inkData = Cast(this.dataDoc[this.fieldKey], InkField)?.inkData ?? []; - const inkStrokeWidth = NumCast(this.rootDoc.strokeWidth, 1); + const inkStrokeWidth = NumCast(this.rootDoc.stroke_width, 1); const inkTop = Math.min(...inkData.map(p => p.Y)) - inkStrokeWidth / 2; const inkBottom = Math.max(...inkData.map(p => p.Y)) + inkStrokeWidth / 2; const inkLeft = Math.min(...inkData.map(p => p.X)) - inkStrokeWidth / 2; @@ -310,8 +310,8 @@ export class InkingStroke extends ViewBoxBaseComponent() { .map(p => ({ X: p[0], Y: p[1] })); const screenHdlPts = screenPts; - const startMarker = StrCast(this.layoutDoc.strokeStartMarker); - const endMarker = StrCast(this.layoutDoc.strokeEndMarker); + const startMarker = StrCast(this.layoutDoc.stroke_startMarker); + const endMarker = StrCast(this.layoutDoc.stroke_endMarker); const markerScale = NumCast(this.layoutDoc.strokeMarkerScale); return SnappingManager.GetIsDragging() ? null : !InkStrokeProperties.Instance._controlButton ? ( !this.props.isSelected() || InkingStroke.IsClosed(inkData) ? null : ( @@ -330,12 +330,12 @@ export class InkingStroke extends ViewBoxBaseComponent() { screenSpaceCenterlineStrokeWidth, StrCast(inkDoc.strokeLineJoin), StrCast(this.layoutDoc.strokeLineCap), - StrCast(inkDoc.strokeBezier), + StrCast(inkDoc.stroke_bezier), 'none', startMarker, endMarker, markerScale * Math.min(screenSpaceCenterlineStrokeWidth, screenInkWidth[0] / screenSpaceCenterlineStrokeWidth), - StrCast(inkDoc.strokeDash), + StrCast(inkDoc.stroke_dash), 1, 1, '', @@ -355,11 +355,11 @@ export class InkingStroke extends ViewBoxBaseComponent() { TraceMobx(); const { inkData, inkStrokeWidth, inkLeft, inkTop, inkScaleX, inkScaleY, inkWidth, inkHeight } = this.inkScaledData(); - const startMarker = StrCast(this.layoutDoc.strokeStartMarker); - const endMarker = StrCast(this.layoutDoc.strokeEndMarker); + const startMarker = StrCast(this.layoutDoc.stroke_startMarker); + const endMarker = StrCast(this.layoutDoc.stroke_endMarker); const markerScale = NumCast(this.layoutDoc.strokeMarkerScale, 1); const closed = InkingStroke.IsClosed(inkData); - const isInkMask = BoolCast(this.layoutDoc.isInkMask); + const isInkMask = BoolCast(this.layoutDoc.stroke_isInkMask); const fillColor = isInkMask ? DashColor(StrCast(this.layoutDoc.fillColor, 'transparent')).blacken(0).rgb().toString() : this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.FillColor) ?? 'transparent'; const strokeColor = !closed && fillColor && fillColor !== 'transparent' ? fillColor : this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.Color) ?? StrCast(this.layoutDoc.color); @@ -381,12 +381,12 @@ export class InkingStroke extends ViewBoxBaseComponent() { inkStrokeWidth, StrCast(this.layoutDoc.strokeLineJoin), StrCast(this.layoutDoc.strokeLineCap), - StrCast(this.layoutDoc.strokeBezier), + StrCast(this.layoutDoc.stroke_bezier), !closed ? 'none' : fillColor === 'transparent' ? 'none' : fillColor, startMarker, endMarker, markerScale, - StrCast(this.layoutDoc.strokeDash), + StrCast(this.layoutDoc.stroke_dash), inkScaleX, inkScaleY, '', @@ -408,7 +408,7 @@ export class InkingStroke extends ViewBoxBaseComponent() { inkStrokeWidth + (fillColor ? (closed ? 2 : (highlightIndex ?? 0) + 2) : 2), StrCast(this.layoutDoc.strokeLineJoin), StrCast(this.layoutDoc.strokeLineCap), - StrCast(this.layoutDoc.strokeBezier), + StrCast(this.layoutDoc.stroke_bezier), !closed ? 'none' : !isInkMask && (fillColor === 'transparent' || suppressFill) ? 'none' : fillColor, '', '', @@ -444,7 +444,7 @@ export class InkingStroke extends ViewBoxBaseComponent() { () { setContentView={this.setSubContentView} // this makes the inkingStroke the "dominant" component - ie, it will show the inking UI when selected (not text) yPadding={10} xPadding={10} - fieldKey={'text'} + fieldKey="text" fontSize={fsize} dontRegisterView={true} noSidebar={true} diff --git a/src/client/views/LightboxView.tsx b/src/client/views/LightboxView.tsx index c18a89481..1b309a6be 100644 --- a/src/client/views/LightboxView.tsx +++ b/src/client/views/LightboxView.tsx @@ -31,7 +31,7 @@ type LightboxSavedState = { panY: Opt; scale: Opt; scrollTop: Opt; - layoutKey: Opt; + layout_fieldKey: Opt; }; @observer export class LightboxView extends React.Component { @@ -51,11 +51,11 @@ export class LightboxView extends React.Component { static path: { doc: Opt; target: Opt; history: Opt<{ doc: Doc; target?: Doc }[]>; future: Opt; saved: Opt }[] = []; @action public static SetLightboxDoc(doc: Opt, target?: Doc, future?: Doc[], layoutTemplate?: Doc | string) { if (this.LightboxDoc && this.LightboxDoc !== doc && this._savedState) { - if (this._savedState.panX !== undefined) this.LightboxDoc._panX = this._savedState.panX; - if (this._savedState.panY !== undefined) this.LightboxDoc._panY = this._savedState.panY; - if (this._savedState.scrollTop !== undefined) this.LightboxDoc._scrollTop = this._savedState.scrollTop; - if (this._savedState.scale !== undefined) this.LightboxDoc._viewScale = this._savedState.scale; - this.LightboxDoc.layoutKey = this._savedState.layoutKey; + if (this._savedState.panX !== undefined) this.LightboxDoc._freeform_panX = this._savedState.panX; + if (this._savedState.panY !== undefined) this.LightboxDoc._freeform_panY = this._savedState.panY; + if (this._savedState.scrollTop !== undefined) this.LightboxDoc._layout_scrollTop = this._savedState.scrollTop; + if (this._savedState.scale !== undefined) this.LightboxDoc._freeform_scale = this._savedState.scale; + this.LightboxDoc.layout_fieldKey = this._savedState.layout_fieldKey; } if (!doc) { this._docFilters && (this._docFilters.length = 0); @@ -64,17 +64,17 @@ export class LightboxView extends React.Component { MainView.Instance._exploreMode = false; } else { const l = DocUtils.MakeLinkToActiveAudio(() => doc).lastElement(); - l && (Cast(l.anchor2, Doc, null).backgroundColor = 'lightgreen'); + l && (Cast(l.link_anchor_2, Doc, null).backgroundColor = 'lightgreen'); CollectionStackedTimeline.CurrentlyPlaying?.forEach(dv => dv.ComponentView?.Pause?.()); //TabDocView.PinDoc(doc, { hidePresBox: true }); this._history ? this._history.push({ doc, target }) : (this._history = [{ doc, target }]); if (doc !== LightboxView.LightboxDoc) { this._savedState = { - layoutKey: StrCast(doc.layoutKey), - panX: Cast(doc.panX, 'number', null), - panY: Cast(doc.panY, 'number', null), - scale: Cast(doc.viewScale, 'number', null), - scrollTop: Cast(doc.scrollTop, 'number', null), + layout_fieldKey: StrCast(doc.layout_fieldKey), + panX: Cast(doc.freeform_panX, 'number', null), + panY: Cast(doc.freeform_panY, 'number', null), + scale: Cast(doc.freeform_scale, 'number', null), + scrollTop: Cast(doc.layout_scrollTop, 'number', null), }; } } @@ -91,7 +91,7 @@ export class LightboxView extends React.Component { this._doc = doc; this._layoutTemplate = layoutTemplate instanceof Doc ? layoutTemplate : undefined; if (doc && (typeof layoutTemplate === 'string' ? layoutTemplate : undefined)) { - doc.layoutKey = layoutTemplate; + doc.layout_fieldKey = layoutTemplate; } this._docTarget = target || doc; @@ -142,7 +142,7 @@ export class LightboxView extends React.Component { return LightboxView.SetLightboxDoc( doc, undefined, - [...DocListCast(doc[Doc.LayoutFieldKey(doc)]), ...DocListCast(doc[Doc.LayoutFieldKey(doc) + '-annotations']).filter(anno => anno.annotationOn !== doc), ...(LightboxView._future ?? [])].sort( + [...DocListCast(doc[Doc.LayoutFieldKey(doc)]), ...DocListCast(doc[Doc.LayoutFieldKey(doc) + '_annotations']).filter(anno => anno.annotationOn !== doc), ...(LightboxView._future ?? [])].sort( (a: Doc, b: Doc) => NumCast(b._timecodeToShow) - NumCast(a._timecodeToShow) ), layoutTemplate @@ -156,17 +156,17 @@ export class LightboxView extends React.Component { const targetDocView = target && DocumentManager.Instance.getLightboxDocumentView(target); if (targetDocView && target) { const l = DocUtils.MakeLinkToActiveAudio(() => targetDocView.ComponentView?.getAnchor?.(true) || target).lastElement(); - l && (Cast(l.anchor2, Doc, null).backgroundColor = 'lightgreen'); + l && (Cast(l.link_anchor_2, Doc, null).backgroundColor = 'lightgreen'); DocumentManager.Instance.showDocument(target, { willZoomCentered: true, zoomScale: 0.9 }); if (LightboxView._history?.lastElement().target !== target) LightboxView._history?.push({ doc, target }); } else { if (!target && LightboxView.path.length) { const saved = LightboxView._savedState; if (LightboxView.LightboxDoc && saved) { - LightboxView.LightboxDoc._panX = saved.panX; - LightboxView.LightboxDoc._panY = saved.panY; - LightboxView.LightboxDoc._viewScale = saved.scale; - LightboxView.LightboxDoc._scrollTop = saved.scrollTop; + LightboxView.LightboxDoc._freeform_panX = saved.panX; + LightboxView.LightboxDoc._freeform_panY = saved.panY; + LightboxView.LightboxDoc._freeform_scale = saved.scale; + LightboxView.LightboxDoc._layout_scrollTop = saved.scrollTop; } const pop = LightboxView.path.pop(); if (pop) { @@ -210,7 +210,7 @@ export class LightboxView extends React.Component { const coll = LightboxView._docTarget; if (coll) { const fieldKey = Doc.LayoutFieldKey(coll); - const contents = [...DocListCast(coll[fieldKey]), ...DocListCast(coll[fieldKey + '-annotations'])]; + const contents = [...DocListCast(coll[fieldKey]), ...DocListCast(coll[fieldKey + '_annotations'])]; const links = LinkManager.Links(coll) .map(link => LinkManager.getOppositeAnchor(link, coll)) .filter(doc => doc) @@ -305,9 +305,9 @@ export class LightboxView extends React.Component { title="toggle fit width" onClick={e => { e.stopPropagation(); - LightboxView.LightboxDoc!._fitWidth = !LightboxView.LightboxDoc!._fitWidth; + LightboxView.LightboxDoc!._layout_fitWidth = !LightboxView.LightboxDoc!._layout_fitWidth; }}> - +
dv.rootDoc.showSnapLines) ? null : ( + return !SelectionManager.Views().some(dv => dv.rootDoc.freeform_snapLines) ? null : (
{SnappingManager.horizSnapLines().map(l => ( diff --git a/src/client/views/MarqueeAnnotator.tsx b/src/client/views/MarqueeAnnotator.tsx index 556d9b6a0..eb0fd0c7a 100644 --- a/src/client/views/MarqueeAnnotator.tsx +++ b/src/client/views/MarqueeAnnotator.tsx @@ -123,9 +123,9 @@ export class MarqueeAnnotator extends React.Component { DragManager.StartAnchorAnnoDrag([ele], new DragManager.AnchorAnnoDragData(this.props.docView, sourceAnchorCreator, targetCreator), e.pageX, e.pageY, { dragComplete: e => { if (!e.aborted && e.linkDocument) { - Doc.GetProto(e.linkDocument).linkRelationship = 'cropped image'; + Doc.GetProto(e.linkDocument).link_relationship = 'cropped image'; Doc.GetProto(e.linkDocument).title = 'crop: ' + this.props.docView.rootDoc.title; - Doc.GetProto(e.linkDocument).linkDisplay = false; + Doc.GetProto(e.linkDocument).layout_linkDisplay = false; } }, }); @@ -153,10 +153,10 @@ export class MarqueeAnnotator extends React.Component { annotationOn: this.props.rootDoc, title: 'Annotation on ' + this.props.rootDoc.title, }); - marqueeAnno.x = NumCast(this.props.docView.props.Document.panXMin) + (parseInt(anno.style.left || '0') - containerOffset[0]) / scale / NumCast(this.props.docView.props.Document._viewScale, 1); - marqueeAnno.y = NumCast(this.props.docView.props.Document.panYMin) + (parseInt(anno.style.top || '0') - containerOffset[1]) / scale / NumCast(this.props.docView.props.Document._viewScale, 1) + NumCast(this.props.scrollTop); - marqueeAnno._height = parseInt(anno.style.height || '0') / scale / NumCast(this.props.docView.props.Document._viewScale, 1); - marqueeAnno._width = parseInt(anno.style.width || '0') / scale / NumCast(this.props.docView.props.Document._viewScale, 1); + marqueeAnno.x = NumCast(this.props.docView.props.Document.freeform_panXMin) + (parseInt(anno.style.left || '0') - containerOffset[0]) / scale / NumCast(this.props.docView.props.Document._freeform_scale, 1); + marqueeAnno.y = NumCast(this.props.docView.props.Document.freeform_panYMin) + (parseInt(anno.style.top || '0') - containerOffset[1]) / scale / NumCast(this.props.docView.props.Document._freeform_scale, 1) + NumCast(this.props.scrollTop); + marqueeAnno._height = parseInt(anno.style.height || '0') / scale / NumCast(this.props.docView.props.Document._freeform_scale, 1); + marqueeAnno._width = parseInt(anno.style.width || '0') / scale / NumCast(this.props.docView.props.Document._freeform_scale, 1); anno.remove(); savedAnnoMap.clear(); return marqueeAnno; diff --git a/src/client/views/PreviewCursor.tsx b/src/client/views/PreviewCursor.tsx index c7a603897..f7fb443c0 100644 --- a/src/client/views/PreviewCursor.tsx +++ b/src/client/views/PreviewCursor.tsx @@ -57,7 +57,7 @@ export class PreviewCursor extends React.Component<{}> { title: url, _width: 500, _height: 300, - useCors: true, + data_useCors: true, x: newPoint[0], y: newPoint[1], }) diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx index cf808f801..86230ca78 100644 --- a/src/client/views/PropertiesButtons.tsx +++ b/src/client/views/PropertiesButtons.tsx @@ -74,7 +74,7 @@ export class PropertiesButtons extends React.Component<{}, {}> { @computed get maskButton() { return this.propertyToggleBtn( 'Mask', - 'isInkMask', + 'stroke_isInkMask', on => (on ? 'Make plain ink' : 'Make highlight mask'), on => 'paint-brush', (dv, doc) => InkingStroke.toggleMask(dv?.layoutDoc || doc) @@ -91,7 +91,7 @@ export class PropertiesButtons extends React.Component<{}, {}> { @computed get clustersButton() { return this.propertyToggleBtn( 'Clusters', - '_useClusters', + '_freeform_useClusters', on => `${on ? 'Hide' : 'Show'} clusters`, on => 'braille' ); @@ -115,7 +115,7 @@ export class PropertiesButtons extends React.Component<{}, {}> { @computed get fitContentButton() { return this.propertyToggleBtn( 'View All', - '_fitContentsToBox', + '_freeform_fitContentsToBox', on => `${on ? "Don't" : 'Do'} fit content to container visible area`, on => 'object-group' ); @@ -136,20 +136,20 @@ export class PropertiesButtons extends React.Component<{}, {}> { // containerDoc.noShadow = // containerDoc.disableDocBrushing = // containerDoc._forceActive = - //containerDoc._fitContentsToBox = + //containerDoc._freeform_fitContentsToBox = containerDoc._isLightbox = !containerDoc._isLightbox; //containerDoc._xPadding = containerDoc._yPadding = containerDoc._isLightbox ? 10 : undefined; const containerContents = DocListCast(dv.dataDoc[dv.props.fieldKey ?? Doc.LayoutFieldKey(containerDoc)]); //dv.rootDoc.onClick = ScriptField.MakeScript('{self.data = undefined; documentView.select(false)}', { documentView: 'any' }); - containerContents.forEach(doc => LinkManager.Links(doc).forEach(link => (link.linkDisplay = false))); + containerContents.forEach(doc => LinkManager.Links(doc).forEach(link => (link.layout_linkDisplay = false))); }); } ); } - @computed get fitWidthButton() { + @computed get layout_fitWidthButton() { return this.propertyToggleBtn( 'Fit\xA0Width', - '_fitWidth', + '_layout_fitWidth', on => `${on ? "Don't" : 'Do'} fit content to width of container`, on => 'arrows-alt-h' ); @@ -157,10 +157,10 @@ export class PropertiesButtons extends React.Component<{}, {}> { @computed get captionButton() { return this.propertyToggleBtn( 'Caption', - '_showCaption', + '_layout_showCaption', on => `${on ? 'Hide' : 'Show'} caption footer`, on => 'closed-captioning', - (dv, doc) => ((dv?.rootDoc || doc)._showCaption = (dv?.rootDoc || doc)._showCaption === undefined ? 'caption' : undefined) + (dv, doc) => ((dv?.rootDoc || doc)._layout_showCaption = (dv?.rootDoc || doc)._layout_showCaption === undefined ? 'caption' : undefined) ); } @computed get chromeButton() { @@ -175,20 +175,20 @@ export class PropertiesButtons extends React.Component<{}, {}> { @computed get titleButton() { return this.propertyToggleBtn( 'Title', - '_showTitle', + '_layout_showTitle', on => 'Switch between title styles', on => 'text-width', (dv, doc) => { const tdoc = dv?.rootDoc || doc; - const newtitle = !tdoc._showTitle ? 'title' : tdoc._showTitle === 'title' ? 'title:hover' : ''; - tdoc._showTitle = newtitle; + const newtitle = !tdoc._layout_showTitle ? 'title' : tdoc._layout_showTitle === 'title' ? 'title:hover' : ''; + tdoc._layout_showTitle = newtitle; } ); } - @computed get autoHeightButton() { + @computed get layout_autoHeightButton() { return this.propertyToggleBtn( 'Auto\xA0Size', - '_autoHeight', + '_layout_autoHeight', on => `Automatical vertical sizing to show all content`, on => 'arrows-alt-v' ); @@ -196,7 +196,7 @@ export class PropertiesButtons extends React.Component<{}, {}> { @computed get gridButton() { return this.propertyToggleBtn( 'Grid', - '_backgroundGridShow', + '_freeform_backgroundGrid', on => `Display background grid in collection`, on => 'border-all' ); @@ -236,7 +236,7 @@ export class PropertiesButtons extends React.Component<{}, {}> { @computed get snapButton() { return this.propertyToggleBtn( 'Snap\xA0Lines', - 'showSnapLines', + 'freeform_snapLines', on => `Display snapping lines when objects are dragged`, on => 'th', undefined, @@ -412,12 +412,12 @@ export class PropertiesButtons extends React.Component<{}, {}> { {toggle(this.captionButton)} {toggle(this.lockButton)} {toggle(this.onClickButton)} - {toggle(this.fitWidthButton)} + {toggle(this.layout_fitWidthButton)} {toggle(this.freezeThumb)} {toggle(this.forceActiveButton, { display: !isFreeForm && !isMap ? 'none' : '' })} {toggle(this.fitContentButton, { display: !isFreeForm && !isMap ? 'none' : '' })} {toggle(this.isLightboxButton, { display: !isFreeForm && !isMap ? 'none' : '' })} - {toggle(this.autoHeightButton, { display: !isText && !isStacking && !isTree ? 'none' : '' })} + {toggle(this.layout_autoHeightButton, { display: !isText && !isStacking && !isTree ? 'none' : '' })} {toggle(this.maskButton, { display: !isInk ? 'none' : '' })} {toggle(this.hideImageButton, { display: !isImage ? 'none' : '' })} {toggle(this.chromeButton, { display: !isCollection || isNovice ? 'none' : '' })} diff --git a/src/client/views/PropertiesDocBacklinksSelector.tsx b/src/client/views/PropertiesDocBacklinksSelector.tsx index 935d551c6..46e6fd188 100644 --- a/src/client/views/PropertiesDocBacklinksSelector.tsx +++ b/src/client/views/PropertiesDocBacklinksSelector.tsx @@ -25,7 +25,7 @@ export class PropertiesDocBacklinksSelector extends React.Component alias.context && alias.context instanceof Doc).reduce((set, alias) => set.add(Cast(alias.context, Doc, null)), new Set()); - const containerSets = Array.from(containerProtos.keys()).map(container => DocListCast(container.aliases)); + const embeddings = DocListCast(target.proto_embeddings); + const containerProtos = embeddings.filter(embedding => embedding.embedContainer && embedding.embedContainer instanceof Doc).reduce((set, embedding) => set.add(Cast(embedding.embedContainer, Doc, null)), new Set()); + const containerSets = Array.from(containerProtos.keys()).map(container => DocListCast(container.proto_embeddings)); const containers = containerSets.reduce((p, set) => { set.map(s => p.add(s)); return p; }, new Set()); - const doclayoutSets = Array.from(containers.keys()).map(dp => DocListCast(dp.aliases)); + const doclayoutSets = Array.from(containers.keys()).map(dp => DocListCast(dp.proto_embeddings)); const doclayouts = Array.from( doclayoutSets .reduce((p, set) => { @@ -48,7 +48,7 @@ export class PropertiesDocContextSelector extends React.Component { if (!this.props.DocView) return; - col = Doc.IsPrototype(col) ? Doc.MakeDelegate(col) : col; + col = Doc.IsDocDataProto(col) ? Doc.MakeDelegate(col) : col; DocFocusOrOpen(Doc.GetProto(this.props.DocView.props.Document), undefined, col); }; diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index 0b14c7b10..19c138a21 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -123,7 +123,7 @@ export class PropertiesView extends React.Component { docWidth = () => { if (this.selectedDoc) { const layoutDoc = this.selectedDoc; - const aspect = Doc.NativeAspect(layoutDoc, undefined, !layoutDoc._fitWidth); + const aspect = Doc.NativeAspect(layoutDoc, undefined, !layoutDoc._layout_fitWidth); if (aspect) return Math.min(layoutDoc[WidthSym](), Math.min(this.MAX_EMBED_HEIGHT * aspect, this.props.width - 20)); return Doc.NativeWidth(layoutDoc) ? Math.min(layoutDoc[WidthSym](), this.props.width - 20) : this.props.width - 20; } else { @@ -141,7 +141,7 @@ export class PropertiesView extends React.Component { this.MAX_EMBED_HEIGHT, Doc.NativeAspect(layoutDoc, undefined, true) ? this.docWidth() / Doc.NativeAspect(layoutDoc, undefined, true) - : layoutDoc._fitWidth + : layoutDoc._layout_fitWidth ? !Doc.NativeHeight(this.dataDoc) ? NumCast(this.props.height) : Math.min((this.docWidth() * Doc.NativeHeight(layoutDoc)) / Doc.NativeWidth(layoutDoc) || NumCast(this.props.height)) @@ -199,8 +199,8 @@ export class PropertiesView extends React.Component { } @computed get noviceFields() { - const noviceReqFields = ['author', 'creationDate', 'tags', '_curPage']; - return this.editableFields(key => key.indexOf('lastModified') !== -1 || (key[0] === key[0].toUpperCase() && !key.startsWith('acl')), noviceReqFields); + const noviceReqFields = ['author', 'creationDate', 'tags', '_layout_curPage']; + return this.editableFields(key => key.indexOf('modificationDate') !== -1 || (key[0] === key[0].toUpperCase() && !key.startsWith('acl')), noviceReqFields); } @undoBatch @@ -576,7 +576,7 @@ export class PropertiesView extends React.Component { this.selectedDoc && (this.selectedDoc.y = NumCast(this.selectedDoc?.y) + (dirs === 'up' ? 10 : -10)); break; case 'stk': - this.selectedDoc && (this.selectedDoc.strokeWidth = NumCast(this.selectedDoc?.strokeWidth) + (dirs === 'up' ? 0.1 : -0.1)); + this.selectedDoc && (this.selectedDoc.stroke_width = NumCast(this.selectedDoc?.stroke_width) + (dirs === 'up' ? 0.1 : -0.1)); break; case 'wid': const oldWidth = NumCast(this.selectedDoc?._width); @@ -813,25 +813,25 @@ export class PropertiesView extends React.Component { } @computed get solidStk() { - return this.selectedDoc?.color && (!this.selectedDoc?.strokeDash || this.selectedDoc?.strokeDash === '0') ? true : false; + return this.selectedDoc?.color && (!this.selectedDoc?.stroke_dash || this.selectedDoc?.stroke_dash === '0') ? true : false; } @computed get dashdStk() { - return this.selectedDoc?.strokeDash || ''; + return this.selectedDoc?.stroke_dash || ''; } @computed get unStrokd() { return this.selectedDoc?.color ? true : false; } @computed get widthStk() { - return this.getField('strokeWidth') || '1'; + return this.getField('stroke_width') || '1'; } @computed get markScal() { return Number(this.getField('strokeMakerScale') || '1'); } @computed get markHead() { - return this.getField('strokeStartMarker') || ''; + return this.getField('stroke_startMarker') || ''; } @computed get markTail() { - return this.getField('strokeEndMarker') || ''; + return this.getField('stroke_endMarker') || ''; } set solidStk(value) { this.dashdStk = ''; @@ -839,22 +839,22 @@ export class PropertiesView extends React.Component { } set dashdStk(value) { value && (this._lastDash = value) && (this.unStrokd = false); - this.selectedDoc && (this.selectedDoc.strokeDash = value ? this._lastDash : undefined); + this.selectedDoc && (this.selectedDoc.stroke_dash = value ? this._lastDash : undefined); } set markScal(value) { this.selectedDoc && (this.selectedDoc.strokeMarkerScale = Number(value)); } set widthStk(value) { - this.selectedDoc && (this.selectedDoc.strokeWidth = Number(value)); + this.selectedDoc && (this.selectedDoc.stroke_width = Number(value)); } set unStrokd(value) { this.colorStk = value ? '' : this._lastLine; } set markHead(value) { - this.selectedDoc && (this.selectedDoc.strokeStartMarker = value); + this.selectedDoc && (this.selectedDoc.stroke_startMarker = value); } set markTail(value) { - this.selectedDoc && (this.selectedDoc.strokeEndMarker = value); + this.selectedDoc && (this.selectedDoc.stroke_endMarker = value); } @computed get stkInput() { @@ -1151,16 +1151,16 @@ export class PropertiesView extends React.Component { } @computed get description() { - return Field.toString(LinkManager.currentLink?.description as any as Field); + return Field.toString(LinkManager.currentLink?.link_description as any as Field); } @computed get relationship() { - return StrCast(LinkManager.currentLink?.linkRelationship); + return StrCast(LinkManager.currentLink?.link_relationship); } @observable private relationshipButtonColor: string = ''; // @action - // handleDescriptionChange = (e: React.ChangeEvent) => { this.description = e.target.value; } - // handleRelationshipChange = (e: React.ChangeEvent) => { this.relationship = e.target.value; } + // handleDescriptionChange = (e: React.ChangeEvent) => { this.link_description = e.target.value; } + // handleRelationshipChange = (e: React.ChangeEvent) => { this.link_relationship = e.target.value; } @undoBatch handleDescriptionChange = action((value: string) => { @@ -1171,9 +1171,9 @@ export class PropertiesView extends React.Component { }); @undoBatch - handleLinkRelationshipChange = action((value: string) => { + handlelinkRelationshipChange = action((value: string) => { if (LinkManager.currentLink && this.selectedDoc) { - this.setLinkRelationshipValue(value); + this.setlinkRelationshipValue(value); return true; } }); @@ -1181,19 +1181,19 @@ export class PropertiesView extends React.Component { @undoBatch setDescripValue = action((value: string) => { if (LinkManager.currentLink) { - Doc.GetProto(LinkManager.currentLink).description = value; + Doc.GetProto(LinkManager.currentLink).link_description = value; return true; } }); @undoBatch - setLinkRelationshipValue = action((value: string) => { + setlinkRelationshipValue = action((value: string) => { if (LinkManager.currentLink) { - const prevRelationship = LinkManager.currentLink.linkRelationship as string; - LinkManager.currentLink.linkRelationship = value; - Doc.GetProto(LinkManager.currentLink).linkRelationship = value; - const linkRelationshipList = StrListCast(Doc.UserDoc().linkRelationshipList); - const linkRelationshipSizes = NumListCast(Doc.UserDoc().linkRelationshipSizes); + const prevRelationship = StrCast(LinkManager.currentLink.link_relationship); + LinkManager.currentLink.link_relationship = value; + Doc.GetProto(LinkManager.currentLink).link_relationship = value; + const linkRelationshipList = StrListCast(Doc.UserDoc().link_relationshipList); + const linkRelationshipSizes = NumListCast(Doc.UserDoc().link_relationshipSizes); const linkColorList = StrListCast(Doc.UserDoc().linkColorList); // if the relationship does not exist in the list, add it and a corresponding unique randomly generated color @@ -1264,13 +1264,13 @@ export class PropertiesView extends React.Component { }; onSelectOutRelationship = () => { - this.setLinkRelationshipValue(this.relationship); + this.setlinkRelationshipValue(this.relationship); document.getElementById('link_relationship_input')?.blur(); }; onRelationshipKey = (e: React.KeyboardEvent) => { if (e.key === 'Enter') { - this.setLinkRelationshipValue(this.relationship); + this.setlinkRelationshipValue(this.relationship); document.getElementById('link_relationship_input')?.blur(); } }; @@ -1283,7 +1283,7 @@ export class PropertiesView extends React.Component { const ldoc = LinkManager.currentLink; const lanch = this.selectedDocumentView?.anchorViewDoc ?? LinkManager.currentLinkAnchor; if (ldoc && lanch) return LinkManager.getOppositeAnchor(ldoc, lanch) ?? lanch; - return ldoc ? DocCast(ldoc.anchor2) : ldoc; + return ldoc ? DocCast(ldoc.link_anchor_2) : ldoc; } @computed get sourceAnchor() { @@ -1314,10 +1314,10 @@ export class PropertiesView extends React.Component {

Show link

} placement="top"> + @@ -657,7 +657,7 @@ export class CollectionViewBaseChrome extends React.Component {this.notACollection || this.props.type === CollectionViewType.Invalid ? null : this.viewModes}
- {this.aliasButton} + {this.embedButton} {/* {this.pinButton} */} {this.toggleOverlayButton}
@@ -691,7 +691,7 @@ export class CollectionFreeFormViewChrome extends React.Component key.indexOf('title') >= 0 || key.indexOf('author') >= 0 || key.indexOf('creationDate') >= 0 || key.indexOf('lastModified') >= 0 || (key[0].toUpperCase() === key[0] && key[0] !== '_')); + const keys = Object.keys(docs).filter(key => key.indexOf('title') >= 0 || key.indexOf('author') >= 0 || key.indexOf('creationDate') >= 0 || key.indexOf('modificationDate') >= 0 || (key[0].toUpperCase() === key[0] && key[0] !== '_')); return keys.filter(key => key.toLowerCase().indexOf(val) > -1); - } else { - const keys = new Set(); - docs.forEach(doc => Doc.allKeys(doc).forEach(key => keys.add(key))); - const noviceKeys = Array.from(keys).filter( - key => key.indexOf('title') >= 0 || key.indexOf('author') >= 0 || key.indexOf('creationDate') >= 0 || key.indexOf('lastModified') >= 0 || (key[0]?.toUpperCase() === key[0] && key[0] !== '_') - ); - return noviceKeys.filter(key => key.toLowerCase().indexOf(val) > -1); } + const keys = new Set(); + docs.forEach(doc => Doc.allKeys(doc).forEach(key => keys.add(key))); + const noviceKeys = Array.from(keys).filter( + key => key.indexOf('title') >= 0 || key.indexOf('author') >= 0 || key.indexOf('creationDate') >= 0 || key.indexOf('modificationDate') >= 0 || (key[0]?.toUpperCase() === key[0] && key[0] !== '_') + ); + return noviceKeys.filter(key => key.toLowerCase().indexOf(val) > -1); } if (docs instanceof Doc) { @@ -1125,13 +1124,13 @@ export class CollectionNoteTakingViewChrome extends React.Component key.indexOf('title') >= 0 || key.indexOf('author') >= 0 || key.indexOf('creationDate') >= 0 || key.indexOf('lastModified') >= 0 || (key[0].toUpperCase() === key[0] && key[0] !== '_')); + const keys = Object.keys(docs).filter(key => key.indexOf('title') >= 0 || key.indexOf('author') >= 0 || key.indexOf('creationDate') >= 0 || key.indexOf('modificationDate') >= 0 || (key[0].toUpperCase() === key[0] && key[0] !== '_')); return keys.filter(key => key.toLowerCase().indexOf(val) > -1); } else { const keys = new Set(); docs.forEach(doc => Doc.allKeys(doc).forEach(key => keys.add(key))); const noviceKeys = Array.from(keys).filter( - key => key.indexOf('title') >= 0 || key.indexOf('author') >= 0 || key.indexOf('creationDate') >= 0 || key.indexOf('lastModified') >= 0 || (key[0]?.toUpperCase() === key[0] && key[0] !== '_') + key => key.indexOf('title') >= 0 || key.indexOf('author') >= 0 || key.indexOf('creationDate') >= 0 || key.indexOf('modificationDate') >= 0 || (key[0]?.toUpperCase() === key[0] && key[0] !== '_') ); return noviceKeys.filter(key => key.toLowerCase().indexOf(val) > -1); } @@ -1235,9 +1234,9 @@ export class CollectionSchemaViewChrome extends React.Component 0; return ( diff --git a/src/client/views/collections/CollectionNoteTakingView.tsx b/src/client/views/collections/CollectionNoteTakingView.tsx index 99d4d0bee..a65e23911 100644 --- a/src/client/views/collections/CollectionNoteTakingView.tsx +++ b/src/client/views/collections/CollectionNoteTakingView.tsx @@ -49,12 +49,12 @@ export class CollectionNoteTakingView extends CollectionSubView() { return BoolCast(this.layoutDoc.chromeHidden); } // columnHeaders returns the list of SchemaHeaderFields currently being used by the layout doc to render the columns - @computed get columnHeaders() { - const columnHeaders = 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) { + @computed get colHeaderData() { + const colHeaderData = Cast(this.dataDoc[this.fieldKey + '_columnHeaders'], listSpec(SchemaHeaderField), null); + const needsUnsetCategory = this.childDocs.some(d => !d[this.notetakingCategoryField] && !colHeaderData?.find(sh => sh.heading === 'unset')); + if (needsUnsetCategory || colHeaderData === undefined || colHeaderData.length === 0) { setTimeout(() => { - const columnHeaders = Array.from(Cast(this.dataDoc.columnHeaders, listSpec(SchemaHeaderField), null) ?? []); + const columnHeaders = Array.from(Cast(this.dataDoc[this.fieldKey + '_columnHeaders'], listSpec(SchemaHeaderField), null) ?? []); const needsUnsetCategory = this.childDocs.some(d => !d[this.notetakingCategoryField] && !columnHeaders?.find(sh => sh.heading === 'unset')); if (needsUnsetCategory || columnHeaders.length === 0) { columnHeaders.push(new SchemaHeaderField('unset', undefined, undefined, 1)); @@ -62,7 +62,7 @@ export class CollectionNoteTakingView extends CollectionSubView() { } }); } - return columnHeaders ?? ([] as SchemaHeaderField[]); + return colHeaderData ?? ([] as SchemaHeaderField[]); } @computed get headerMargin() { return this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.HeaderMargin); @@ -78,7 +78,7 @@ export class CollectionNoteTakingView extends CollectionSubView() { } // numGroupColumns returns the number of columns @computed get numGroupColumns() { - return this.columnHeaders.length; + return this.colHeaderData.length; } // PanelWidth returns the size of the total available space the view occupies @computed get PanelWidth() { @@ -117,7 +117,7 @@ export class CollectionNoteTakingView extends CollectionSubView() { // (2) documentView gets unmounted as you remove it from the list @computed get Sections() { TraceMobx(); - const columnHeaders = this.columnHeaders; + const columnHeaders = this.colHeaderData; // filter out the currently dragged docs from the child docs, since we will insert them later const docs = this.childDocs.filter(d => !DragManager.docsBeingDragged.includes(d)); const sections = new Map(columnHeaders.map(sh => [sh, []] as [SchemaHeaderField, []])); @@ -149,9 +149,10 @@ export class CollectionNoteTakingView extends CollectionSubView() { componentDidMount() { super.componentDidMount?.(); document.addEventListener('pointerup', this.removeDocDragHighlight, true); - this._disposers.autoHeight = reaction( - () => this.layoutDoc._autoHeight, - autoHeight => autoHeight && this.props.setHeight?.(Math.min(NumCast(this.layoutDoc._maxHeight, Number.MAX_SAFE_INTEGER), this.headerMargin + Math.max(...this.refList.map(r => Number(getComputedStyle(r).height.replace('px', '')))))) + this._disposers.layout_autoHeight = reaction( + () => this.layoutDoc._layout_autoHeight, + layout_autoHeight => + layout_autoHeight && this.props.setHeight?.(Math.min(NumCast(this.layoutDoc._maxHeight, Number.MAX_SAFE_INTEGER), this.headerMargin + Math.max(...this.refList.map(r => Number(getComputedStyle(r).height.replace('px', '')))))) ); } @@ -230,7 +231,7 @@ export class CollectionNoteTakingView extends CollectionSubView() { PanelHeight={height} styleProvider={this.styleProvider} docViewPath={this.props.docViewPath} - fitWidth={this.props.childFitWidth} + layout_fitWidth={this.props.childLayoutFitWidth} isContentActive={emptyFunction} onKey={this.onKeyDown} //TODO: change this from a prop to a parameter passed into a function @@ -238,12 +239,12 @@ export class CollectionNoteTakingView extends CollectionSubView() { isDocumentActive={this.isContentActive} LayoutTemplate={this.props.childLayoutTemplate} LayoutTemplateString={this.props.childLayoutString} - NativeWidth={this.props.childIgnoreNativeSize ? returnZero : this.props.childFitWidth?.(doc) || (doc._fitWidth && !Doc.NativeWidth(doc)) ? width : undefined} // explicitly ignore nativeWidth/height if childIgnoreNativeSize is set- used by PresBox - NativeHeight={this.props.childIgnoreNativeSize ? returnZero : this.props.childFitWidth?.(doc) || (doc._fitWidth && !Doc.NativeHeight(doc)) ? height : undefined} + NativeWidth={this.props.childIgnoreNativeSize ? returnZero : this.props.childLayoutFitWidth?.(doc) || (doc._layout_fitWidth && !Doc.NativeWidth(doc)) ? width : undefined} // explicitly ignore nativeWidth/height if childIgnoreNativeSize is set- used by PresBox + NativeHeight={this.props.childIgnoreNativeSize ? returnZero : this.props.childLayoutFitWidth?.(doc) || (doc._layout_fitWidth && !Doc.NativeHeight(doc)) ? height : undefined} dontCenter={this.props.childIgnoreNativeSize ? 'xy' : undefined} dontRegisterView={dataDoc ? true : BoolCast(this.layoutDoc.childDontRegisterViews, this.props.dontRegisterView)} rootSelected={this.rootSelected} - showTitle={this.props.childShowTitle} + layout_showTitle={this.props.childlayout_showTitle} dropAction={StrCast(this.layoutDoc.childDropAction) as dropActionType} onClick={this.onChildClickHandler} onDoubleClick={this.onChildDoubleClickHandler} @@ -280,10 +281,10 @@ export class CollectionNoteTakingView extends CollectionSubView() { // if a note doc. Otherwise, returns the normal width (for graphs, images, etc...) getDocWidth(d: Doc) { const heading = !d[this.notetakingCategoryField] ? 'unset' : Field.toString(d[this.notetakingCategoryField] as Field); - const existingHeader = this.columnHeaders.find(sh => sh.heading === heading); + const existingHeader = this.colHeaderData.find(sh => sh.heading === heading); const existingWidth = existingHeader?.width ? existingHeader.width : 0; const maxWidth = existingWidth > 0 ? existingWidth * this.availableWidth : this.maxColWidth; - const width = d.fitWidth ? maxWidth : d[WidthSym](); + const width = d.layout_fitWidth ? maxWidth : d[WidthSym](); return Math.min(maxWidth - CollectionNoteTakingViewColumn.ColumnMargin, width < maxWidth ? width : maxWidth); } @@ -293,14 +294,14 @@ export class CollectionNoteTakingView extends CollectionSubView() { const childLayoutDoc = Doc.Layout(d, this.props.childLayoutTemplate?.()); const childDataDoc = !d.isTemplateDoc && !d.isTemplateForField ? undefined : this.props.DataDoc; const maxHeight = (lim => (lim === 0 ? this.props.PanelWidth() : lim === -1 ? 10000 : lim))(NumCast(this.layoutDoc.childLimitHeight, -1)); - const nw = Doc.NativeWidth(childLayoutDoc, childDataDoc) || (!(childLayoutDoc._fitWidth || this.props.childFitWidth?.(d)) ? d[WidthSym]() : 0); - const nh = Doc.NativeHeight(childLayoutDoc, childDataDoc) || (!(childLayoutDoc._fitWidth || this.props.childFitWidth?.(d)) ? d[HeightSym]() : 0); + const nw = Doc.NativeWidth(childLayoutDoc, childDataDoc) || (!(childLayoutDoc._layout_fitWidth || this.props.childLayoutFitWidth?.(d)) ? d[WidthSym]() : 0); + const nh = Doc.NativeHeight(childLayoutDoc, childDataDoc) || (!(childLayoutDoc._layout_fitWidth || this.props.childLayoutFitWidth?.(d)) ? d[HeightSym]() : 0); if (nw && nh) { const docWid = this.getDocWidth(d); return Math.min(maxHeight, (docWid * nh) / nw); } const childHeight = NumCast(childLayoutDoc._height); - const panelHeight = childLayoutDoc._fitWidth || this.props.childFitWidth?.(d) ? Number.MAX_SAFE_INTEGER : this.props.PanelHeight() - 2 * this.yMargin; + const panelHeight = childLayoutDoc._layout_fitWidth || this.props.childLayoutFitWidth?.(d) ? Number.MAX_SAFE_INTEGER : this.props.PanelHeight() - 2 * this.yMargin; return Math.min(childHeight, maxHeight, panelHeight); } @@ -318,7 +319,7 @@ export class CollectionNoteTakingView extends CollectionSubView() { 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( + this.dataDoc[this.fieldKey + '_columnHeaders'] = new List( headers.map(h => { h.setWidth(Math.abs(h.width) * scaleFactor); return h; @@ -352,7 +353,7 @@ export class CollectionNoteTakingView extends CollectionSubView() { }); // we alter the pivot fields of the docs in case they are moved to a new column. const colIndex = this.getColumnFromXCoord(xCoord); - const colHeader = colIndex === undefined ? 'unset' : StrCast(this.columnHeaders[colIndex].heading); + const colHeader = colIndex === undefined ? 'unset' : StrCast(this.colHeaderData[colIndex].heading); DragManager.docsBeingDragged.forEach(d => (d[this.notetakingCategoryField] = colHeader)); // used to notify sections to re-render this.docsDraggedRowCol.length = 0; @@ -365,12 +366,12 @@ export class CollectionNoteTakingView extends CollectionSubView() { // This function is used to know which document a column SHOULD be in while it is being dragged. getColumnFromXCoord = (xCoord: number): number | undefined => { let colIndex: number | undefined = undefined; - const numColumns = this.columnHeaders.length; + const numColumns = this.colHeaderData.length; const coords = []; let colStartXCoord = 0; for (let i = 0; i < numColumns; i++) { coords.push(colStartXCoord); - colStartXCoord += this.columnHeaders[i].width * this.availableWidth + this.DividerWidth; + colStartXCoord += this.colHeaderData[i].width * this.availableWidth + this.DividerWidth; } coords.push(this.PanelWidth); for (let i = 0; i < numColumns; i++) { @@ -386,7 +387,7 @@ export class CollectionNoteTakingView extends CollectionSubView() { getDocsFromXCoord = (xCoord: number): Doc[] => { const docsMatchingHeader: Doc[] = []; const colIndex = this.getColumnFromXCoord(xCoord); - const colHeader = colIndex === undefined ? 'unset' : StrCast(this.columnHeaders[colIndex].heading); + const colHeader = colIndex === undefined ? 'unset' : StrCast(this.colHeaderData[colIndex].heading); this.childDocs?.map(d => { if (d instanceof Promise) return; const sectionValue = (d[this.notetakingCategoryField] as object) ?? 'unset'; @@ -401,7 +402,7 @@ export class CollectionNoteTakingView extends CollectionSubView() { @action onKeyDown = (e: React.KeyboardEvent, fieldProps: FieldViewProps) => { const docView = fieldProps.DocumentView?.(); - if (docView && (e.ctrlKey || docView.rootDoc._singleLine) && ['Enter'].includes(e.key)) { + if (docView && (e.ctrlKey || docView.rootDoc._createDocOnCR) && ['Enter'].includes(e.key)) { e.stopPropagation?.(); const newDoc = Doc.MakeCopy(docView.rootDoc, true); Doc.GetProto(newDoc).text = undefined; @@ -436,10 +437,10 @@ export class CollectionNoteTakingView extends CollectionSubView() { } } } - } else if (de.complete.linkDragData?.dragDocument.context === this.props.Document && de.complete.linkDragData?.linkDragView?.props.CollectionFreeFormDocumentView?.()) { - const source = Docs.Create.TextDocument('', { _width: 200, _height: 75, _fitWidth: true, title: 'dropped annotation' }); + } else if (de.complete.linkDragData?.dragDocument.embedContainer === this.props.Document && de.complete.linkDragData?.linkDragView?.props.CollectionFreeFormDocumentView?.()) { + const source = Docs.Create.TextDocument('', { _width: 200, _height: 75, _layout_fitWidth: true, title: 'dropped annotation' }); this.props.addDocument?.(source); - de.complete.linkDocument = DocUtils.MakeLink(source, de.complete.linkDragData.linkSourceGetAnchor(), { linkRelationship: 'doc annotation' }); // TODODO this is where in text links get passed + de.complete.linkDocument = DocUtils.MakeLink(source, de.complete.linkDragData.linkSourceGetAnchor(), { link_relationship: 'doc annotation' }); // TODODO this is where in text links get passed e.stopPropagation(); } else if (de.complete.annoDragData?.dragDocument && super.onInternalDrop(e, de)) return this.internalAnchorAnnoDrop(e, de.complete.annoDragData); return false; @@ -468,7 +469,7 @@ export class CollectionNoteTakingView extends CollectionSubView() { this.onPointerMove(true, e.clientX, e.clientY); docus?.map((doc: Doc) => this.addDocument(doc)); const newDoc = this.childDocs.lastElement(); - const colHeader = colInd === undefined ? 'unset' : StrCast(this.columnHeaders[colInd].heading); + const colHeader = colInd === undefined ? 'unset' : StrCast(this.colHeaderData[colInd].heading); newDoc[this.notetakingCategoryField] = colHeader; const docs = this.childDocList; if (docs && targInd !== -1) { @@ -502,7 +503,7 @@ export class CollectionNoteTakingView extends CollectionSubView() { this.refList.push(ref); this.observer = new _global.ResizeObserver( action((entries: any) => { - if (this.layoutDoc._autoHeight && ref && this.refList.length && !SnappingManager.GetIsDragging()) { + if (this.layoutDoc._layout_autoHeight && ref && this.refList.length && !SnappingManager.GetIsDragging()) { const height = this.headerMargin + Math.min(NumCast(this.layoutDoc._maxHeight, Number.MAX_SAFE_INTEGER), Math.max(...this.refList.map(r => Number(getComputedStyle(r).height.replace('px', ''))))); if (!LightboxView.IsLightboxDocView(this.props.docViewPath())) { this.props.setHeight?.(height); @@ -516,7 +517,7 @@ export class CollectionNoteTakingView extends CollectionSubView() { select={this.props.select} addDocument={this.addDocument} chromeHidden={this.chromeHidden} - columnHeaders={this.columnHeaders} + colHeaderData={this.colHeaderData} Document={this.props.Document} DataDoc={this.props.DataDoc} resizeColumns={this.resizeColumns} @@ -524,6 +525,7 @@ export class CollectionNoteTakingView extends CollectionSubView() { numGroupColumns={this.numGroupColumns} gridGap={this.gridGap} pivotField={this.notetakingCategoryField} + fieldKey={this.fieldKey} dividerWidth={this.DividerWidth} maxColWidth={this.maxColWidth} availableWidth={this.availableWidth} @@ -546,15 +548,15 @@ export class CollectionNoteTakingView extends CollectionSubView() { @undoBatch @action addGroup = (value: string) => { - if (this.columnHeaders) { - for (const header of this.columnHeaders) { + if (this.colHeaderData) { + for (const header of this.colHeaderData) { if (header.heading === value) { alert('You cannot use an existing column name. Please try a new column name'); return value; } } } - const columnHeaders = Array.from(Cast(this.props.Document.columnHeaders, listSpec(SchemaHeaderField), null)); + const columnHeaders = Array.from(Cast(this.dataDoc[this.fieldKey + '_columnHeaders'], listSpec(SchemaHeaderField), null)); const newColWidth = 1 / (this.numGroupColumns + 1); columnHeaders.push(new SchemaHeaderField(value, undefined, undefined, newColWidth)); value && this.resizeColumns(columnHeaders); @@ -566,7 +568,7 @@ export class CollectionNoteTakingView extends CollectionSubView() { if (!e.isPropagationStopped()) { const subItems: ContextMenuProps[] = []; subItems.push({ description: `${this.layoutDoc._columnsFill ? 'Variable Size' : 'Autosize'} Column`, event: () => (this.layoutDoc._columnsFill = !this.layoutDoc._columnsFill), icon: 'plus' }); - subItems.push({ description: `${this.layoutDoc._autoHeight ? 'Variable Height' : 'Auto Height'}`, event: () => (this.layoutDoc._autoHeight = !this.layoutDoc._autoHeight), icon: 'plus' }); + subItems.push({ description: `${this.layoutDoc._layout_autoHeight ? 'Variable Height' : 'Auto Height'}`, event: () => (this.layoutDoc._layout_autoHeight = !this.layoutDoc._layout_autoHeight), icon: 'plus' }); subItems.push({ description: 'Clear All', event: () => (this.dataDoc.data = new List([])), icon: 'times' }); ContextMenu.Instance.addItem({ description: 'Options...', subitems: subItems, icon: 'eye' }); } @@ -576,8 +578,8 @@ export class CollectionNoteTakingView extends CollectionSubView() { @action setColumnStartXCoords = (movementXScreen: number, colIndex: number) => { const movementX = this.props.ScreenToLocalTransform().transformDirection(movementXScreen, 0)[0]; - const leftHeader = this.columnHeaders[colIndex]; - const rightHeader = this.columnHeaders[colIndex + 1]; + const leftHeader = this.colHeaderData[colIndex]; + const rightHeader = this.colHeaderData[colIndex + 1]; leftHeader.setWidth(leftHeader.width + movementX / this.availableWidth); rightHeader.setWidth(rightHeader.width - movementX / this.availableWidth); }; diff --git a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx index 28bdd0cb9..63becac1e 100644 --- a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx +++ b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx @@ -29,8 +29,9 @@ interface CSVFieldColumnProps { docList: Doc[]; heading: string; pivotField: string; + fieldKey: string | undefined; chromeHidden?: boolean; - columnHeaders: SchemaHeaderField[] | undefined; + colHeaderData: SchemaHeaderField[] | undefined; headingObject: SchemaHeaderField | undefined; yMargin: number; numGroupColumns: number; @@ -61,9 +62,9 @@ export class CollectionNoteTakingViewColumn extends React.Component { const castedValue = this.getValue(value); if (castedValue) { - if (this.props.columnHeaders?.map(i => i.heading).indexOf(castedValue.toString()) !== -1) { + if (this.props.colHeaderData?.map(i => i.heading).indexOf(castedValue.toString()) !== -1) { return false; } this.props.docList.forEach(d => (d[this.props.pivotField] = castedValue)); @@ -127,7 +128,7 @@ export class CollectionNoteTakingViewColumn extends React.Component { if (!value && !forceEmptyNote) return false; const key = this.props.pivotField; - const newDoc = Docs.Create.TextDocument(value, { _height: 18, _width: 200, _fitWidth: true, title: value, _autoHeight: true }); + const newDoc = Docs.Create.TextDocument(value, { _height: 18, _width: 200, _layout_fitWidth: true, title: value, _layout_autoHeight: true }); const colValue = this.getValue(this.props.heading); newDoc[key] = colValue; FormattedTextBox.SelectOnLoad = newDoc[Id]; @@ -141,11 +142,11 @@ export class CollectionNoteTakingViewColumn extends React.Component { - const columnHeaders = Array.from(Cast(this.props.Document.columnHeaders, listSpec(SchemaHeaderField), null)); + const colHdrData = Array.from(Cast(this.props.Document[this.props.fieldKey + '_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); + colHdrData.splice(colHdrData.indexOf(this.props.headingObject), 1); + this.props.resizeColumns(colHdrData); } }; @@ -211,7 +212,7 @@ export class CollectionNoteTakingViewColumn extends React.Component { Doc.GetProto(this.props.Document)[name] = ''; - const created = Docs.Create.TextDocument('', { title: name, _width: 250, _autoHeight: true }); + const created = Docs.Create.TextDocument('', { title: name, _width: 250, _layout_autoHeight: true }); if (created) { if (this.props.Document.isTemplateDoc) { Doc.MakeMetadataFieldTemplate(created, this.props.Document); @@ -243,7 +244,7 @@ export class CollectionNoteTakingViewColumn extends React.Component evContents} isEditingCallback={isEditing => isEditing && this.props.select(false)} SetValue={this.headingChanged} contents={evContents} oneLine={true} />
- {(this.props.columnHeaders?.length ?? 0) > 1 && ( + {(this.props.colHeaderData?.length ?? 0) > 1 && ( diff --git a/src/client/views/collections/CollectionPileView.tsx b/src/client/views/collections/CollectionPileView.tsx index 5b96a8682..ea0fbbc54 100644 --- a/src/client/views/collections/CollectionPileView.tsx +++ b/src/client/views/collections/CollectionPileView.tsx @@ -82,8 +82,8 @@ export class CollectionPileView extends CollectionSubView() { this.layoutDoc._width = NumCast(this.layoutDoc._starburstPileWidth, defaultSize); this.layoutDoc._height = NumCast(this.layoutDoc._starburstPileHeight, defaultSize); DocUtils.pileup(this.childDocs, undefined, undefined, NumCast(this.layoutDoc._width) / 2, false); - this.layoutDoc._panX = 0; - this.layoutDoc._panY = -10; + this.layoutDoc._freeform_panX = 0; + this.layoutDoc._freeform_panY = -10; this.props.Document._pileLayoutEngine = computePassLayout.name; } else { const defaultSize = NumCast(this.rootDoc._starburstDiameter, 500); @@ -91,7 +91,7 @@ export class CollectionPileView extends CollectionSubView() { this.rootDoc.y = NumCast(this.rootDoc.y) + this.layoutDoc[HeightSym]() / 2 - defaultSize / 2; this.layoutDoc._starburstPileWidth = this.layoutDoc[WidthSym](); this.layoutDoc._starburstPileHeight = this.layoutDoc[HeightSym](); - this.layoutDoc._panX = this.layoutDoc._panY = 0; + this.layoutDoc._freeform_panX = this.layoutDoc._freeform_panY = 0; this.layoutDoc._width = this.layoutDoc._height = defaultSize; this.props.Document._pileLayoutEngine = computeStarburstLayout.name; } diff --git a/src/client/views/collections/CollectionStackedTimeline.tsx b/src/client/views/collections/CollectionStackedTimeline.tsx index 22a575989..6b4c8a3e9 100644 --- a/src/client/views/collections/CollectionStackedTimeline.tsx +++ b/src/client/views/collections/CollectionStackedTimeline.tsx @@ -24,7 +24,7 @@ import { undoBatch, UndoManager } from '../../util/UndoManager'; import { AudioWaveform } from '../AudioWaveform'; import { CollectionSubView } from '../collections/CollectionSubView'; import { LightboxView } from '../LightboxView'; -import { DocFocusFunc, DocFocusOptions, DocumentView, DocumentViewProps } from '../nodes/DocumentView'; +import { DocFocusFunc, DocFocusOptions, DocumentView, DocumentViewProps, OpenWhere } from '../nodes/DocumentView'; import { LabelBox } from '../nodes/LabelBox'; import { VideoBox } from '../nodes/VideoBox'; import './CollectionStackedTimeline.scss'; @@ -41,7 +41,9 @@ export type CollectionStackedTimelineProps = { mediaPath: string; dictationKey: string; rawDuration: number; + dataFieldKey: string; fieldKey: string; + thumbnails?: () => string[]; }; // trimming state: shows full clip, current trim bounds, or not trimming @@ -80,6 +82,9 @@ export class CollectionStackedTimeline extends CollectionSubView 0 ? new ImageField(thumbnails[nearest]) : undefined; + const imgField = this.thumbnails.length > 0 ? new ImageField(this.thumbnails[nearest]) : undefined; this._thumbnail = imgField?.url?.href ? imgField.url.href.replace('.png', '_m.png') : undefined; } } @@ -401,11 +405,9 @@ export class CollectionStackedTimeline extends CollectionSubView NumCast(this.layoutDoc._currentTimecode)) { + if (seekTimeInSeconds < NumCast(this.layoutDoc._layout_currentTimecode) && endTime > NumCast(this.layoutDoc._layout_currentTimecode)) { if (!this.layoutDoc.autoPlayAnchors && this.props.playing()) { this.props.Pause(); } else { @@ -455,7 +457,7 @@ export class CollectionStackedTimeline extends CollectionSubView NumCast(this.layoutDoc._currentTimecode) - 1e-4) { + if (seekTimeInSeconds < NumCast(this.layoutDoc._layout_currentTimecode) + 1e-4 && endTime > NumCast(this.layoutDoc._layout_currentTimecode) - 1e-4) { if (this.props.playing()) this.props.Pause(); else if (this.layoutDoc.autoPlayAnchors) this.props.Play(); else if (!this.layoutDoc.autoPlayAnchors) { @@ -596,6 +598,7 @@ export class CollectionStackedTimeline extends CollectionSubView void; + addDocTab: (doc: Doc, where: OpenWhere) => boolean; rangeClickScript: () => ScriptField; rangePlayScript: () => ScriptField; left: number; @@ -709,7 +714,7 @@ class StackedTimelineAnchor extends React.Component () => this.props.currentTimecode(), time => { const dictationDoc = Cast(this.props.layoutDoc['data-dictation'], Doc, null); - const isDictation = dictationDoc && LinkManager.Links(this.props.mark).some(link => Cast(link.anchor1, Doc, null)?.annotationOn === dictationDoc); + const isDictation = dictationDoc && LinkManager.Links(this.props.mark).some(link => Cast(link.link_anchor_1, 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. @@ -808,11 +813,9 @@ class StackedTimelineAnchor extends React.Component isDocumentActive={this.props.isDocumentActive} PanelWidth={width} PanelHeight={height} - fitWidth={returnTrue} + layout_fitWidth={returnTrue} ScreenToLocalTransform={screenXf} - addDocTab={returnFalse} pinToPres={emptyFunction} - whenChildContentsActiveChanged={emptyFunction} focus={focusFunc} isContentActive={returnFalse} searchFilterDocs={returnEmptyDoclist} diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index eedf639aa..404ca5d65 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -49,7 +49,7 @@ export class CollectionStackingView extends CollectionSubView number; width: () => number; stackedDocTransform: () => Transform }[] = []; // Doesn't look like this field is being used anywhere. Obsolete? @@ -65,8 +65,8 @@ export class CollectionStackingView extends CollectionSubView(); + this.layoutDoc['_' + this.fieldKey + '_columnHeaders'] = new List(); } } @@ -154,14 +154,14 @@ export class CollectionStackingView extends CollectionSubView(); + if (!this.pivotField || this.colHeaderData instanceof Promise) return new Map(); - if (this.columnHeaders === undefined) { - setTimeout(() => (this.layoutDoc._columnHeaders = new List()), 0); + if (this.colHeaderData === undefined) { + setTimeout(() => (this.layoutDoc['_' + this.fieldKey + '_columnHeaders'] = new List()), 0); return new Map(); } - const columnHeaders = Array.from(this.columnHeaders); - const fields = new Map(columnHeaders.map(sh => [sh, []] as [SchemaHeaderField, []])); + const colHeaderData = Array.from(this.colHeaderData); + const fields = new Map(colHeaderData.map(sh => [sh, []] as [SchemaHeaderField, []])); let changed = false; this.filteredChildren.map(d => { const sectionValue = (d[this.pivotField] ? d[this.pivotField] : `NO ${this.pivotField.toUpperCase()} VALUE`) as object; @@ -170,13 +170,13 @@ export class CollectionStackingView extends CollectionSubView sh.heading === (castedSectionValue ? castedSectionValue.toString() : `NO ${this.pivotField.toUpperCase()} VALUE`)); + const existingHeader = colHeaderData.find(sh => sh.heading === (castedSectionValue ? castedSectionValue.toString() : `NO ${this.pivotField.toUpperCase()} VALUE`)); if (existingHeader) { fields.get(existingHeader)!.push(d); } else { const newSchemaHeader = new SchemaHeaderField(castedSectionValue ? castedSectionValue.toString() : `NO ${this.pivotField.toUpperCase()} VALUE`); fields.set(newSchemaHeader, [d]); - columnHeaders.push(newSchemaHeader); + colHeaderData.push(newSchemaHeader); changed = true; } }); @@ -187,13 +187,13 @@ export class CollectionStackingView extends CollectionSubView !fields.get(key)!.length) .map(header => { fields.delete(header); - columnHeaders.splice(columnHeaders.indexOf(header), 1); + colHeaderData.splice(colHeaderData.indexOf(header), 1); changed = true; }); } changed && setTimeout( - action(() => this.columnHeaders?.splice(0, this.columnHeaders.length, ...columnHeaders)), + action(() => this.colHeaderData?.splice(0, this.colHeaderData.length, ...colHeaderData)), 0 ); return fields; @@ -206,12 +206,12 @@ export class CollectionStackingView extends CollectionSubView this.pivotField, - () => (this.layoutDoc._columnHeaders = new List()) + () => (this.layoutDoc['_' + this.fieldKey + '_columnHeaders'] = new List()) ); - this._autoHeightDisposer = reaction( - () => this.layoutDoc._autoHeight, - autoHeight => - autoHeight && + this._layout_autoHeightDisposer = reaction( + () => this.layoutDoc._layout_autoHeight, + layout_autoHeight => + layout_autoHeight && this.props.setHeight?.( Math.min( NumCast(this.layoutDoc._maxHeight, Number.MAX_SAFE_INTEGER), @@ -224,7 +224,7 @@ export class CollectionStackingView extends CollectionSubView this.props.isAnyChildContentActive(); @@ -282,12 +282,12 @@ export class CollectionStackingView extends CollectionSubView([]) : undefined; - if (layoutKey !== 'layout' && docView.rootDoc[layoutKey] instanceof Doc) { - newDoc[layoutKey] = docView.rootDoc[layoutKey]; + if (layout_fieldKey !== 'layout' && docView.rootDoc[layout_fieldKey] instanceof Doc) { + newDoc[layout_fieldKey] = docView.rootDoc[layout_fieldKey]; } Doc.GetProto(newDoc).text = undefined; FormattedTextBox.SelectOnLoad = newDoc[Id]; @@ -327,19 +327,19 @@ export class CollectionStackingView extends CollectionSubView (lim === 0 ? this.props.PanelWidth() : lim === -1 ? 10000 : lim))(NumCast(this.layoutDoc.childLimitHeight, -1)); - const nw = Doc.NativeWidth(childLayoutDoc, childDataDoc) || (!(childLayoutDoc._fitWidth || this.props.childFitWidth?.(d)) ? d[WidthSym]() : 0); - const nh = Doc.NativeHeight(childLayoutDoc, childDataDoc) || (!(childLayoutDoc._fitWidth || this.props.childFitWidth?.(d)) ? d[HeightSym]() : 0); + const nw = Doc.NativeWidth(childLayoutDoc, childDataDoc) || (!(childLayoutDoc._layout_fitWidth || this.props.childLayoutFitWidth?.(d)) ? d[WidthSym]() : 0); + const nh = Doc.NativeHeight(childLayoutDoc, childDataDoc) || (!(childLayoutDoc._layout_fitWidth || this.props.childLayoutFitWidth?.(d)) ? d[HeightSym]() : 0); if (nw && nh) { const colWid = this.columnWidth / (this.isStackingView ? this.numGroupColumns : 1); const docWid = this.layoutDoc._columnsFill ? colWid : Math.min(this.getDocWidth(d), colWid); return Math.min(maxHeight, (docWid * nh) / nw); } const childHeight = NumCast(childLayoutDoc._height); - const panelHeight = childLayoutDoc._fitWidth || this.props.childFitWidth?.(d) ? Number.MAX_SAFE_INTEGER : this.props.PanelHeight() - 2 * this.yMargin; + const panelHeight = childLayoutDoc._layout_fitWidth || this.props.childLayoutFitWidth?.(d) ? Number.MAX_SAFE_INTEGER : this.props.PanelHeight() - 2 * this.yMargin; return Math.min(childHeight, maxHeight, panelHeight); } @@ -460,10 +460,10 @@ export class CollectionStackingView extends CollectionSubView { - if (this.layoutDoc._autoHeight && ref && this.refList.length && !SnappingManager.GetIsDragging()) { + if (this.layoutDoc._layout_autoHeight && ref && this.refList.length && !SnappingManager.GetIsDragging()) { const height = this.headerMargin + Math.min(NumCast(this.layoutDoc._maxHeight, Number.MAX_SAFE_INTEGER), Math.max(...this.refList.map(r => Number(getComputedStyle(r).height.replace('px', ''))))); if (!LightboxView.IsLightboxDocView(this.props.docViewPath())) { this.props.setHeight?.(height); @@ -539,7 +539,7 @@ export class CollectionStackingView extends CollectionSubView { - if (this.layoutDoc._autoHeight && ref && this.refList.length && !SnappingManager.GetIsDragging()) { + if (this.layoutDoc._layout_autoHeight && ref && this.refList.length && !SnappingManager.GetIsDragging()) { const height = this.refList.reduce((p, r) => p + Number(getComputedStyle(r).height.replace('px', '')), 0); this.props.setHeight?.(this.headerMargin + height); } @@ -608,9 +608,9 @@ export class CollectionStackingView extends CollectionSubView { - if (value && this.columnHeaders) { + if (value && this.colHeaderData) { const schemaHdrField = new SchemaHeaderField(value); - this.columnHeaders.push(schemaHdrField); + this.colHeaderData.push(schemaHdrField); return true; } return false; @@ -630,7 +630,7 @@ export class CollectionStackingView extends CollectionSubView (this.layoutDoc._columnsFill = !this.layoutDoc._columnsFill), icon: 'plus' }); - optionItems.push({ description: `${this.layoutDoc._autoHeight ? 'Variable Height' : 'Auto Height'}`, event: () => (this.layoutDoc._autoHeight = !this.layoutDoc._autoHeight), icon: 'plus' }); + optionItems.push({ description: `${this.layoutDoc._layout_autoHeight ? 'Variable Height' : 'Auto Height'}`, event: () => (this.layoutDoc._layout_autoHeight = !this.layoutDoc._layout_autoHeight), icon: 'plus' }); optionItems.push({ description: 'Clear All', event: () => (this.dataDoc[this.fieldKey ?? 'data'] = new List([])), icon: 'times' }); !options && cm.addItem({ description: 'Options...', subitems: optionItems, icon: 'compass' }); } diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx index d62c4dc62..243550c0b 100644 --- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx +++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx @@ -34,7 +34,7 @@ interface CSVFieldColumnProps { heading: string; pivotField: string; chromeHidden?: boolean; - columnHeaders: SchemaHeaderField[] | undefined; + colHeaderData: SchemaHeaderField[] | undefined; headingObject: SchemaHeaderField | undefined; yMargin: number; columnWidth: number; @@ -93,7 +93,7 @@ export class CollectionStackingViewFieldColumn extends React.Component { const drop = { docs: de.complete.docDragData?.droppedDocuments, val: this.getValue(this._heading) }; - drop.docs?.forEach(d => Doc.SetInPlace(d, this.props.pivotField, drop.val, false)); + this.props.pivotField && drop.docs?.forEach(d => Doc.SetInPlace(d, this.props.pivotField, drop.val, false)); }); getValue = (value: string): any => { const parsed = parseInt(value); @@ -107,7 +107,7 @@ export class CollectionStackingViewFieldColumn extends React.Component { const castedValue = this.getValue(value); if (castedValue) { - if (this.props.columnHeaders?.map(i => i.heading).indexOf(castedValue.toString()) !== -1) { + if (this.props.colHeaderData?.map(i => i.heading).indexOf(castedValue.toString()) !== -1) { return false; } this.props.docList.forEach(d => (d[this.props.pivotField] = castedValue)); @@ -134,7 +134,7 @@ export class CollectionStackingViewFieldColumn extends React.Component { if (!value && !forceEmptyNote) return false; const key = this.props.pivotField; - const newDoc = Docs.Create.TextDocument(value, { _height: 18, _width: 200, _fitWidth: true, title: value, _autoHeight: true }); + const newDoc = Docs.Create.TextDocument(value, { _height: 18, _width: 200, _layout_fitWidth: true, title: value, _layout_autoHeight: true }); newDoc[key] = this.getValue(this.props.heading); const maxHeading = this.props.docList.reduce((maxHeading, doc) => (NumCast(doc.heading) > maxHeading ? NumCast(doc.heading) : maxHeading), 0); const heading = maxHeading === 0 || this.props.docList.length === 0 ? 1 : maxHeading === 1 ? 2 : 3; @@ -147,9 +147,9 @@ export class CollectionStackingViewFieldColumn extends React.Component { this.props.docList.forEach(d => (d[this.props.pivotField] = undefined)); - if (this.props.columnHeaders && this.props.headingObject) { - const index = this.props.columnHeaders.indexOf(this.props.headingObject); - this.props.columnHeaders.splice(index, 1); + if (this.props.colHeaderData && this.props.headingObject) { + const index = this.props.colHeaderData.indexOf(this.props.headingObject); + this.props.colHeaderData.splice(index, 1); } }; @@ -163,15 +163,15 @@ export class CollectionStackingViewFieldColumn extends React.Component { - // is MakeAlias a way to make a copy of a doc without rendering it? - const alias = Doc.MakeAlias(this.props.Document); - alias._width = this.props.columnWidth / (this.props.columnHeaders?.length || 1); - alias._pivotField = undefined; + // is MakeEmbedding a way to make a copy of a doc without rendering it? + const embedding = Doc.MakeEmbedding(this.props.Document); + embedding._width = this.props.columnWidth / (this.props.colHeaderData?.length || 1); + embedding._pivotField = undefined; let value = this.getValue(this._heading); value = typeof value === 'string' ? `"${value}"` : value; - alias.viewSpecScript = ScriptField.MakeFunction(`doc.${this.props.pivotField} === ${value}`, { doc: Doc.name }); - if (alias.viewSpecScript) { - DragManager.StartDocumentDrag([this._headerRef.current!], new DragManager.DocumentDragData([alias]), e.clientX, e.clientY); + embedding.viewSpecScript = ScriptField.MakeFunction(`doc.${this.props.pivotField} === ${value}`, { doc: Doc.name }); + if (embedding.viewSpecScript) { + DragManager.StartDocumentDrag([this._headerRef.current!], new DragManager.DocumentDragData([embedding]), e.clientX, e.clientY); return true; } return false; @@ -266,7 +266,7 @@ export class CollectionStackingViewFieldColumn extends React.Component { Doc.GetProto(this.props.Document)[name] = ''; - const created = Docs.Create.TextDocument('', { title: name, _width: 250, _autoHeight: true }); + const created = Docs.Create.TextDocument('', { title: name, _width: 250, _layout_autoHeight: true }); if (created) { if (this.props.Document.isTemplateDoc) { Doc.MakeMetadataFieldTemplate(created, this.props.Document); diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 5b9453666..008de1944 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -129,7 +129,7 @@ export function CollectionSubView(moreProps?: X) { notFiltered = (!searchDocs.length || searchDocs.includes(d)) && DocUtils.FilterDocs([d], childDocFilters, docRangeFilters, this.props.Document).length > 0; const fieldKey = Doc.LayoutFieldKey(d); const annos = !Field.toString(Doc.LayoutField(d) as Field).includes(CollectionView.name); - const data = d[annos ? fieldKey + '-annotations' : fieldKey]; + const data = d[annos ? fieldKey + '_annotations' : fieldKey]; if (data !== undefined) { let subDocs = DocListCast(data); if (subDocs.length > 0) { @@ -141,7 +141,7 @@ export function CollectionSubView(moreProps?: X) { const fieldKey = Doc.LayoutFieldKey(t); const annos = !Field.toString(Doc.LayoutField(t) as Field).includes(CollectionView.name); notFiltered = notFiltered || ((!searchDocs.length || searchDocs.includes(t)) && ((!childDocFilters.length && !docRangeFilters.length) || DocUtils.FilterDocs([t], childDocFilters, docRangeFilters, d).length)); - DocListCast(t[annos ? fieldKey + '-annotations' : fieldKey]).forEach(newdoc => newarray.push(newdoc)); + DocListCast(t[annos ? fieldKey + '_annotations' : fieldKey]).forEach(newdoc => newarray.push(newdoc)); }); subDocs = newarray; } @@ -188,9 +188,9 @@ export function CollectionSubView(moreProps?: X) { protected onInternalPreDrop(e: Event, de: DragManager.DropEvent, targetAction: dropActionType) { if (de.complete.docDragData) { - // if targetDropAction is, say 'alias', but we're just dragging within a collection, we want to ignore the targetAction. + // if targetDropAction is, say 'embed', but we're just dragging within a collection, we want to ignore the targetAction. // otherwise, the targetAction should become the actual action (which can still be overridden by the userDropAction -eg, shift/ctrl keys) - if (targetAction && !de.complete.docDragData.draggedDocuments.some(d => d.context === this.props.Document && this.childDocs.includes(d))) { + if (targetAction && !de.complete.docDragData.draggedDocuments.some(d => d.embedContainer === this.props.Document && this.childDocs.includes(d))) { de.complete.docDragData.dropAction = targetAction; } e.stopPropagation(); @@ -282,7 +282,7 @@ export function CollectionSubView(moreProps?: X) { addDocument(Docs.Create.WebDocument(href, { ...options, title: href })); } } else if (text) { - addDocument(Docs.Create.TextDocument(text, { ...options, _showTitle: StrCast(Doc.UserDoc().showTitle), _width: 100, _height: 25 })); + addDocument(Docs.Create.TextDocument(text, { ...options, _layout_showTitle: StrCast(Doc.UserDoc().layout_showTitle), _width: 100, _height: 25 })); } return; } @@ -375,7 +375,7 @@ export function CollectionSubView(moreProps?: X) { _width: 400, _height: 512, _nativeWidth: 850, - useCors: true, + data_useCors: true, }) ); return; @@ -417,7 +417,7 @@ export function CollectionSubView(moreProps?: X) { proto._height = 20; return proto; }), - { _width: 150, _height: 600, title: 'across', backgroundColor: 'white', _singleLine: true } + { _width: 150, _height: 600, title: 'across', backgroundColor: 'white', _createDocOnCR: true } ) ); }); diff --git a/src/client/views/collections/CollectionTimeView.tsx b/src/client/views/collections/CollectionTimeView.tsx index 3cdb460a3..6135154c3 100644 --- a/src/client/views/collections/CollectionTimeView.tsx +++ b/src/client/views/collections/CollectionTimeView.tsx @@ -35,7 +35,7 @@ export class CollectionTimeView extends CollectionSubView() { 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); "; + ///const childText = "const embedding = getEmbedding(self); switchView(embedding, detailView); embedding.dropAction='embed'; useRightSplit(embedding, shiftKey); "; runInAction(() => { this._childClickedScript = ScriptField.MakeScript('openInLightbox(self)', { this: Doc.name }); this._viewDefDivClick = ScriptField.MakeScript('pivotColumnClick(this,payload)', { payload: 'any' }); @@ -55,10 +55,10 @@ export class CollectionTimeView extends CollectionSubView() { 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 - if (Cast(this.dataDoc[this.props.fieldKey + '-annotations'], listSpec(Doc), null) !== undefined) { - Cast(this.dataDoc[this.props.fieldKey + '-annotations'], listSpec(Doc), []).push(anchor); + if (Cast(this.dataDoc[this.props.fieldKey + '_annotations'], listSpec(Doc), null) !== undefined) { + Cast(this.dataDoc[this.props.fieldKey + '_annotations'], listSpec(Doc), []).push(anchor); } else { - this.dataDoc[this.props.fieldKey + '-annotations'] = new List([anchor]); + this.dataDoc[this.props.fieldKey + '_annotations'] = new List([anchor]); } } return anchor; diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index f774781ab..095e34c39 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -104,7 +104,7 @@ export class CollectionTreeView extends CollectionSubView this.rootDoc.autoHeight, + () => this.rootDoc.layout_autoHeight, auto => auto && this.computeHeight(), { fireImmediately: true } ); @@ -114,25 +114,25 @@ export class CollectionTreeView extends CollectionSubView p + Number(getComputedStyle(r).height.replace('px', '')), this.marginBot()) + 6; - this.layoutDoc._autoHeightMargins = bodyHeight; + this.layoutDoc._layout_autoHeightMargins = bodyHeight; !this.props.dontRegisterView && this.props.setHeight?.(bodyHeight + titleHeight); } }; unobserveHeight = (ref: any) => { this.refList.delete(ref); - this.rootDoc.autoHeight && this.computeHeight(); + this.rootDoc.layout_autoHeight && this.computeHeight(); }; observeHeight = (ref: any) => { if (ref) { this.refList.add(ref); this.observer = new _global.ResizeObserver( action((entries: any) => { - if (this.rootDoc.autoHeight && ref && this.refList.size && !SnappingManager.GetIsDragging()) { + if (this.rootDoc.layout_autoHeight && ref && this.refList.size && !SnappingManager.GetIsDragging()) { this.computeHeight(); } }) ); - this.rootDoc.autoHeight && this.computeHeight(); + this.rootDoc.layout_autoHeight && this.computeHeight(); this.observer.observe(ref); } }; @@ -144,7 +144,7 @@ export class CollectionTreeView extends CollectionSubView { const dragData = de.complete.docDragData; if (dragData) { - const isInTree = () => Doc.AreProtosEqual(dragData.treeViewDoc, this.props.Document) || dragData.draggedDocuments.some(d => d.context === this.doc && this.childDocs.includes(d)); + const isInTree = () => Doc.AreProtosEqual(dragData.treeViewDoc, this.props.Document) || dragData.draggedDocuments.some(d => d.embedContainer === this.doc && this.childDocs.includes(d)); dragData.dropAction = targetAction && !isInTree() ? targetAction : this.doc === dragData?.treeViewDoc ? 'same' : dragData.dropAction; } }; @@ -176,7 +176,7 @@ export class CollectionTreeView extends CollectionSubView (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => { const res = flg && Doc.AddDocToList(this.doc[DataSym], this.props.fieldKey, doc, relativeTo, before); - res && (doc.context = this.props.Document); + res && (doc.embedContainer = this.props.Document); return res; }, true); if (this.doc.resolvedDataDoc instanceof Promise) return false; @@ -234,7 +234,7 @@ export class CollectionTreeView extends CollectionSubView NumCast(this.doc._yMargin); marginBot = () => NumCast(this.doc._yMargin); documentTitleWidth = () => Math.min(this.layoutDoc?.[WidthSym](), this.panelWidth()); - documentTitleHeight = () => (this.layoutDoc?.[HeightSym]() || 0) - NumCast(this.layoutDoc.autoHeightMargins); + documentTitleHeight = () => (this.layoutDoc?.[HeightSym]() || 0) - NumCast(this.layoutDoc.layout_autoHeightMargins); truncateTitleWidth = () => this.treeViewtruncateTitleWidth; onChildClick = () => this.props.onChildClick?.() || ScriptCast(this.doc.onChildClick); panelWidth = () => Math.max(0, this.props.PanelWidth() - 2 * this.marginX() * (this.props.NativeDimScaling?.() || 1)); - addAnnotationDocument = (doc: Doc | Doc[]) => this.addDocument(doc, `${this.props.fieldKey}-annotations`) || false; - remAnnotationDocument = (doc: Doc | Doc[]) => this.removeDocument(doc, `${this.props.fieldKey}-annotations`) || false; + addAnnotationDocument = (doc: Doc | Doc[]) => this.addDocument(doc, `${this.props.fieldKey}_annotations`) || false; + remAnnotationDocument = (doc: Doc | Doc[]) => this.removeDocument(doc, `${this.props.fieldKey}_annotations`) || false; moveAnnotationDocument = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (document: Doc | Doc[], annotationKey?: string) => boolean) => - this.moveDocument(doc, targetCollection, addDocument, `${this.props.fieldKey}-annotations`) || false; + this.moveDocument(doc, targetCollection, addDocument, `${this.props.fieldKey}_annotations`) || false; @observable _headerHeight = 0; @computed get content() { @@ -430,7 +430,7 @@ export class CollectionTreeView extends CollectionSubView {!(this.doc instanceof Doc) || !this.treeChildren ? null : this.doc.treeViewHasOverlay ? ( @@ -443,7 +443,7 @@ export class CollectionTreeView extends CollectionSubView boolean | undefined; // whether child documents can be dragged if collection can be dragged (eg., in a when a Pile document is in startburst mode) childContentsActive?: () => boolean | undefined; - childFitWidth?: (child: Doc) => boolean; - childShowTitle?: () => string; + childLayoutFitWidth?: (child: Doc) => boolean; + childlayout_showTitle?: () => string; childOpacity?: () => number; childContextMenuItems?: () => { script: ScriptField; label: string }[]; childHideTitle?: () => boolean; // whether to hide the documentdecorations title for children @@ -134,8 +134,8 @@ export class CollectionView extends ViewBoxAnnotatableComponent func(CollectionViewType.Freeform), icon: 'signature' }, { description: 'Schema', event: () => func(CollectionViewType.Schema), icon: 'th-list' }, { description: 'Tree', event: () => func(CollectionViewType.Tree), icon: 'tree' }, - { description: 'Stacking', event: () => (func(CollectionViewType.Stacking)._autoHeight = true), icon: 'ellipsis-v' }, - { description: 'Notetaking', event: () => (func(CollectionViewType.NoteTaking)._autoHeight = true), icon: 'ellipsis-v' }, + { description: 'Stacking', event: () => (func(CollectionViewType.Stacking)._layout_autoHeight = true), icon: 'ellipsis-v' }, + { description: 'Notetaking', event: () => (func(CollectionViewType.NoteTaking)._layout_autoHeight = true), icon: 'ellipsis-v' }, { description: 'Multicolumn', event: () => func(CollectionViewType.Multicolumn), icon: 'columns' }, { description: 'Multirow', event: () => func(CollectionViewType.Multirow), icon: 'columns' }, { description: 'Masonry', event: () => func(CollectionViewType.Masonry), icon: 'columns' }, @@ -159,7 +159,7 @@ export class CollectionView extends ViewBoxAnnotatableComponent { - const newRendition = Doc.MakeAlias(this.rootDoc); + const newRendition = Doc.MakeEmbedding(this.rootDoc); newRendition._viewType = vtype; this.props.addDocTab(newRendition, OpenWhere.addRight); return newRendition; @@ -190,9 +190,9 @@ export class CollectionView extends ViewBoxAnnotatableComponent { - const alias = Doc.MakeAlias(this.rootDoc); - DocUtils.makeCustomViewClicked(alias, undefined, func.key); - this.props.addDocTab(alias, OpenWhere.addRight); + const embedding = Doc.MakeEmbedding(this.rootDoc); + DocUtils.makeCustomViewClicked(embedding, undefined, func.key); + this.props.addDocTab(embedding, OpenWhere.addRight); }, }) ); diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx index 45604c1bf..69963736b 100644 --- a/src/client/views/collections/TabDocView.tsx +++ b/src/client/views/collections/TabDocView.tsx @@ -252,11 +252,11 @@ export class TabDocView extends React.Component { const pinDoc = Doc.MakeDelegate(anchorDoc && anchorDoc !== doc ? anchorDoc : doc); pinDoc.presentationTargetDoc = anchorDoc ?? doc; pinDoc.title = doc.title + ' - Slide'; - pinDoc.data = new List(); // 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.data = new List(); // the children of the embedding's layout are the presentation slide children. the embedding's data field might be children of a collection, PDF data, etc -- in any case we don't want the tree view to "see" this data pinDoc.presMovement = doc.type === DocumentType.SCRIPTING || pinProps?.pinDocLayout ? PresMovement.None : PresMovement.Zoom; pinDoc.presDuration = pinDoc.presDuration ?? 1000; pinDoc.groupWithUp = false; - pinDoc.context = curPres; + pinDoc.embedContainer = curPres; // these should potentially all be props passed down by the CollectionTreeView to the TreeView elements. That way the PresBox could configure all of its children at render time pinDoc.treeViewRenderAsBulletHeader = true; // forces a tree view to render the document next to the bullet in the header area pinDoc.treeViewHeaderWidth = '100%'; // forces the header to grow to be the same size as its largest sibling. @@ -264,7 +264,7 @@ export class TabDocView extends React.Component { 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 duration = NumCast(doc[`${Doc.LayoutFieldKey(pinDoc)}-duration`], null); + const duration = NumCast(doc[`${Doc.LayoutFieldKey(pinDoc)}_duration`], null); if (pinProps.pinViewport) PresBox.pinDocView(pinDoc, pinProps, anchorDoc ?? doc); if (!pinProps?.audioRange && duration !== undefined) { @@ -283,7 +283,7 @@ export class TabDocView extends React.Component { pinDoc.title = doc.title + ' (move)'; pinDoc.presMovement = PresMovement.Pan; } - if (pinDoc.isInkMask) { + if (pinDoc.stroke_isInkMask) { pinDoc.presHideAfter = true; pinDoc.presHideBefore = true; pinDoc.presMovement = PresMovement.None; @@ -357,7 +357,7 @@ export class TabDocView extends React.Component { switch (whereFields[0]) { case undefined: case OpenWhere.lightbox: if (this.layoutDoc?._isLightbox) { - const lightboxView = !doc.annotationOn && DocCast(doc.context) ? DocumentManager.Instance.getFirstDocumentView(DocCast(doc.context)) : undefined; + const lightboxView = !doc.annotationOn && DocCast(doc.embedContainer) ? DocumentManager.Instance.getFirstDocumentView(DocCast(doc.embedContainer)) : undefined; const data = lightboxView?.dataDoc[Doc.LayoutFieldKey(lightboxView.rootDoc)]; if (lightboxView && (!data || data instanceof List)) { lightboxView.layoutDoc[Doc.LayoutFieldKey(lightboxView.rootDoc)] = new List([doc]); @@ -409,7 +409,7 @@ export class TabDocView extends React.Component { miniMapColor = () => this.tabColor; tabView = () => this._view; disableMinimap = () => !this._document || this._document.layout !== CollectionView.LayoutString(Doc.LayoutFieldKey(this._document)) || this._document?._viewType !== CollectionViewType.Freeform; - hideMinimap = () => this.disableMinimap() || BoolCast(this._document?.hideMinimap); + hideMinimap = () => this.disableMinimap() || BoolCast(this._document?.layout_hideMinimap); @computed get docView() { return !this._activated || !this._document ? null : ( @@ -449,19 +449,19 @@ export class TabDocView extends React.Component { pinToPres={TabDocView.PinDoc} /> - {this._document.hideMinimap ? 'Open minimap' : 'Close minimap'}
}> + {this._document.layout_hideMinimap ? 'Open minimap' : 'Close minimap'}
}>
e.stopPropagation()} onClick={action(e => { e.stopPropagation(); - this._document!.hideMinimap = !this._document!.hideMinimap; + this._document!.layout_hideMinimap = !this._document!.layout_hideMinimap; })}>
@@ -559,8 +559,8 @@ export class TabMinimapView extends React.Component { this, e, action((e: PointerEvent, down: number[], delta: number[]) => { - doc._panX = clamp(NumCast(doc._panX) + (delta[0] / miniSize) * renderBounds.dim, renderBounds.l, renderBounds.l + renderBounds.dim); - doc._panY = clamp(NumCast(doc._panY) + (delta[1] / miniSize) * renderBounds.dim, renderBounds.t, renderBounds.t + renderBounds.dim); + doc._freeform_panX = clamp(NumCast(doc._freeform_panX) + (delta[0] / miniSize) * renderBounds.dim, renderBounds.l, renderBounds.l + renderBounds.dim); + doc._freeform_panY = clamp(NumCast(doc._freeform_panY) + (delta[1] / miniSize) * renderBounds.dim, renderBounds.t, renderBounds.t + renderBounds.dim); return false; }), emptyFunction, @@ -569,10 +569,10 @@ export class TabMinimapView extends React.Component { }; render() { if (!this.renderBounds) return null; - const miniWidth = (this.props.PanelWidth() / NumCast(this.props.document._viewScale, 1) / this.renderBounds.dim) * 100; - const miniHeight = (this.props.PanelHeight() / NumCast(this.props.document._viewScale, 1) / this.renderBounds.dim) * 100; - const miniLeft = 50 + ((NumCast(this.props.document._panX) - this.renderBounds.cx) / this.renderBounds.dim) * 100 - miniWidth / 2; - const miniTop = 50 + ((NumCast(this.props.document._panY) - this.renderBounds.cy) / this.renderBounds.dim) * 100 - miniHeight / 2; + const miniWidth = (this.props.PanelWidth() / NumCast(this.props.document._freeform_scale, 1) / this.renderBounds.dim) * 100; + const miniHeight = (this.props.PanelHeight() / NumCast(this.props.document._freeform_scale, 1) / this.renderBounds.dim) * 100; + const miniLeft = 50 + ((NumCast(this.props.document._freeform_) - this.renderBounds.cx) / this.renderBounds.dim) * 100 - miniWidth / 2; + const miniTop = 50 + ((NumCast(this.props.document._freeform_panY) - this.renderBounds.cy) / this.renderBounds.dim) * 100 - miniHeight / 2; const miniSize = this.returnMiniSize(); return this.props.hideMinimap() ? null : (
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index 4adf86683..92b70cb5a 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -102,7 +102,7 @@ export class TreeView extends React.Component { private _treedropDisposer?: DragManager.DragDropDisposer; get treeViewOpenIsTransient() { - return this.props.treeView.doc.treeViewOpenIsTransient || Doc.IsPrototype(this.doc); + return this.props.treeView.doc.treeViewOpenIsTransient || Doc.IsDocDataProto(this.doc); } set treeViewOpen(c: boolean) { if (this.treeViewOpenIsTransient) this._transientOpenState = c; @@ -125,7 +125,7 @@ export class TreeView extends React.Component { : this.props.treeView.fileSysMode ? this.doc.isFolder ? this.fieldKey - : 'aliases' // for displaying + : 'embeddings' // for displaying : this.props.treeView.outlineMode || this.childDocs ? this.fieldKey : Doc.noviceMode @@ -160,11 +160,11 @@ export class TreeView extends React.Component { @computed get childLinks() { return this.childDocList('links'); } - @computed get childAliases() { - return this.childDocList('aliases'); + @computed get childEmbeddings() { + return this.childDocList('proto_embeddings'); } @computed get childAnnos() { - return this.childDocList(this.fieldKey + '-annotations'); + return this.childDocList(this.fieldKey + '_annotations'); } @computed get selected() { return SelectionManager.IsSelected(this._docRef); @@ -219,11 +219,13 @@ export class TreeView extends React.Component { if (this.props.document.isFolder || Doc.IsSystem(this.props.document)) { this.treeViewOpen = !this.treeViewOpen; } else { - // choose an appropriate alias or make one. --- choose the first alias that (1) user owns, (2) has no context field ... otherwise make a new alias - const bestAlias = - docView.props.Document.author === Doc.CurrentUserEmail && !Doc.IsPrototype(docView.props.Document) ? docView.props.Document : DocListCast(this.props.document.aliases).find(doc => !doc.context && doc.author === Doc.CurrentUserEmail); - const nextBestAlias = DocListCast(this.props.document.aliases).find(doc => doc.author === Doc.CurrentUserEmail); - this.props.addDocTab(bestAlias ?? nextBestAlias ?? Doc.MakeAlias(this.props.document), OpenWhere.lightbox); + // choose an appropriate embedding or make one. --- choose the first embedding that (1) user owns, (2) has no context field ... otherwise make a new embedding + const bestEmbedding = + docView.props.Document.author === Doc.CurrentUserEmail && !Doc.IsDocDataProto(docView.props.Document) + ? docView.props.Document + : DocListCast(this.props.document.proto_embeddings).find(doc => !doc.embedContainer && doc.author === Doc.CurrentUserEmail); + const nextBestEmbedding = DocListCast(this.props.document.proto_embeddings).find(doc => doc.author === Doc.CurrentUserEmail); + this.props.addDocTab(bestEmbedding ?? nextBestEmbedding ?? Doc.MakeEmbedding(this.props.document), OpenWhere.lightbox); } }; @@ -311,16 +313,16 @@ export class TreeView extends React.Component { treeViewExpandedViewLock: true, treeViewExpandedView: 'data', _viewType: CollectionViewType.Tree, - hideLinkButton: true, - _showSidebar: true, - _fitWidth: true, + layout_hideLinkButton: true, + _layout_showSidebar: true, + _layout_fitWidth: true, treeViewType: TreeViewType.outline, x: 0, y: 0, _xMargin: 0, _yMargin: 0, - _autoHeight: true, - _singleLine: true, + _layout_autoHeight: true, + _createDocOnCR: true, _width: 1000, _height: 10, }); @@ -359,7 +361,7 @@ export class TreeView extends React.Component { if (de.complete.linkDragData) { const sourceDoc = de.complete.linkDragData.linkSourceGetAnchor(); const destDoc = this.doc; - DocUtils.MakeLink(sourceDoc, destDoc, { linkRelationship: 'tree link' }); + DocUtils.MakeLink(sourceDoc, destDoc, { link_relationship: 'tree link' }); e.stopPropagation(); } const docDragData = de.complete.docDragData; @@ -378,7 +380,7 @@ export class TreeView extends React.Component { 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); + dataIsComputed && (doc.embedContainer = this.doc.embedContainer); return added; }; return (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && innerAdd(doc), true as boolean); @@ -413,7 +415,7 @@ export class TreeView extends React.Component { (() => { const aspect = Doc.NativeAspect(layoutDoc); if (aspect) return this.embeddedPanelWidth() / (aspect || 1); - return layoutDoc._fitWidth + return layoutDoc._layout_fitWidth ? !Doc.NativeHeight(layoutDoc) ? NumCast(layoutDoc._height) : Math.min((this.embeddedPanelWidth() * NumCast(layoutDoc.scrollHeight, Doc.NativeHeight(layoutDoc))) / (Doc.NativeWidth(layoutDoc) || NumCast(this.props.treeViewParent._height))) @@ -441,7 +443,7 @@ export class TreeView extends React.Component { 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); + dataIsComputed && (doc.embedContainer = this.doc.embedContainer); return added; }; return (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && innerAdd(doc), true as boolean); @@ -527,7 +529,7 @@ export class TreeView extends React.Component { TraceMobx(); const expandKey = this.treeViewExpandedView; const sortings = (this.props.styleProvider?.(this.doc, this.props.treeView.props, StyleProp.TreeViewSortings) as { [key: string]: { color: string; label: string } }) ?? {}; - if (['links', 'annotations', 'aliases', this.fieldKey].includes(expandKey)) { + if (['links', 'annotations', 'embeddings', this.fieldKey].includes(expandKey)) { const sorting = StrCast(this.doc.treeViewSortCriterion, TreeSort.None); const sortKeys = Object.keys(sortings); const curSortIndex = Math.max( @@ -549,12 +551,12 @@ export class TreeView extends React.Component { } 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); + !dataIsComputed && added && (doc.embedContainer = this.doc.embedContainer); 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); - const docs = expandKey === 'aliases' ? this.childAliases : expandKey === 'links' ? this.childLinks : expandKey === 'annotations' ? this.childAnnos : this.childDocs; + const docs = expandKey === 'embeddings' ? this.childEmbeddings : expandKey === 'links' ? this.childLinks : expandKey === 'annotations' ? this.childAnnos : this.childDocs; let downX = 0, downY = 0; if (docs?.length && this._renderCount < docs?.length) { @@ -706,13 +708,13 @@ export class TreeView extends React.Component { } @computed get validExpandViewTypes() { - const annos = () => (DocListCast(this.doc[this.fieldKey + '-annotations']).length && !this.props.treeView.dashboardMode ? 'annotations' : ''); + const annos = () => (DocListCast(this.doc[this.fieldKey + '_annotations']).length && !this.props.treeView.dashboardMode ? 'annotations' : ''); 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 embeddings = () => (this.props.treeView.dashboardMode ? '' : 'embeddings'); const fields = () => (Doc.noviceMode ? '' : 'fields'); const layout = Doc.noviceMode || this.doc.viewType === CollectionViewType.Docking ? [] : ['layout']; - return [data(), ...layout, ...(this.props.treeView.fileSysMode ? [aliases(), links(), annos()] : []), fields()].filter(m => m); + return [data(), ...layout, ...(this.props.treeView.fileSysMode ? [embeddings(), links(), annos()] : []), fields()].filter(m => m); } @action expandNextviewType = () => { @@ -759,7 +761,7 @@ export class TreeView extends React.Component { 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(`openDoc(getAlias(self), ${OpenWhere.addRight})`)!, icon: 'copy', label: 'Open Alias' }; + const openEmbedding = { script: ScriptField.MakeFunction(`openDoc(getEmbedding(self), ${OpenWhere.addRight})`)!, icon: 'copy', label: 'Open Embedding' }; 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)), @@ -768,10 +770,10 @@ export class TreeView extends React.Component { : Doc.IsSystem(this.doc) ? [] : this.props.treeView.fileSysMode && this.doc === Doc.GetProto(this.doc) - ? [openAlias, makeFolder] + ? [openEmbedding, makeFolder] : this.doc.viewType === CollectionViewType.Docking ? [] - : [deleteItem, openAlias, focusDoc]), + : [deleteItem, openEmbedding, focusDoc]), ]; }; childContextMenuItems = () => { @@ -896,7 +898,7 @@ export class TreeView extends React.Component { } })} Document={this.doc} - fitWidth={returnTrue} + layout_fitWidth={returnTrue} DataDoc={undefined} scriptContext={this} hideDecorationTitle={this.props.treeView.outlineMode} @@ -985,7 +987,7 @@ export class TreeView extends React.Component { ref={action((r: DocumentView | null) => (this._dref = r))} Document={this.doc} DataDoc={undefined} - fitWidth={this.fitWidthFilter} + layout_fitWidth={this.fitWidthFilter} PanelWidth={this.embeddedPanelWidth} PanelHeight={this.embeddedPanelHeight} LayoutTemplateString={asText ? FormattedTextBox.LayoutString('text') : undefined} @@ -1179,7 +1181,7 @@ export class TreeView extends React.Component { TreeView._editTitleOnLoad = editTitle ? { id: child[Id], parent } : undefined; Doc.AddDocToList(newParent, fieldKey, child, addAfter, false); newParent.treeViewOpen = true; - child.context = treeView.Document; + child.embedContainer = treeView.Document; } }; const indent = i === 0 ? undefined : (editTitle: boolean) => dentDoc(editTitle, docs[i - 1], undefined, treeViewRefs.get(docs[i - 1])); diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx index 0dfd119d7..68ba3d368 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx @@ -34,11 +34,11 @@ export class CollectionFreeFormLinkView extends React.Component [ this.props.A.props.ScreenToLocalTransform(), - Cast(Cast(Cast(this.props.A.rootDoc, Doc, null)?.anchor1, Doc, null)?.annotationOn, Doc, null)?.scrollTop, - Cast(Cast(Cast(this.props.A.rootDoc, Doc, null)?.anchor1, Doc, null)?.annotationOn, Doc, null)?.[CssSym], + Cast(Cast(Cast(this.props.A.rootDoc, Doc, null)?.link_anchor_1, Doc, null)?.annotationOn, Doc, null)?.layout_scrollTop, + Cast(Cast(Cast(this.props.A.rootDoc, Doc, null)?.link_anchor_1, Doc, null)?.annotationOn, Doc, null)?.[CssSym], this.props.B.props.ScreenToLocalTransform(), - Cast(Cast(Cast(this.props.A.rootDoc, Doc, null)?.anchor2, Doc, null)?.annotationOn, Doc, null)?.scrollTop, - Cast(Cast(Cast(this.props.A.rootDoc, Doc, null)?.anchor2, Doc, null)?.annotationOn, Doc, null)?.[CssSym], + Cast(Cast(Cast(this.props.A.rootDoc, Doc, null)?.link_anchor_2, Doc, null)?.annotationOn, Doc, null)?.layout_scrollTop, + Cast(Cast(Cast(this.props.A.rootDoc, Doc, null)?.link_anchor_2, Doc, null)?.annotationOn, Doc, null)?.[CssSym], ], action(() => { this._start = Date.now(); @@ -58,7 +58,7 @@ export class CollectionFreeFormLinkView extends React.Component (!LinkDocs.length || !linkDoc.linkDisplay) && (this._opacity = 0.05)), + action(() => (!LinkDocs.length || !linkDoc.layout_linkDisplay) && (this._opacity = 0.05)), 750 ); // this will unhighlight the link line. const a = A.ContentDiv.getBoundingClientRect(); @@ -72,36 +72,36 @@ export class CollectionFreeFormLinkView extends React.Component= 0 && mpx <= 1) linkDoc.anchor1_x = mpx * 100; - if (mpy >= 0 && mpy <= 1) linkDoc.anchor1_y = mpy * 100; + if (mpx >= 0 && mpx <= 1) linkDoc.link_anchor_1_x = mpx * 100; + if (mpy >= 0 && mpy <= 1) linkDoc.link_anchor_1_y = mpy * 100; if (getComputedStyle(targetAhyperlink).fontSize === '0px') linkDoc.opacity = 0; else linkDoc.opacity = 1; } if (!targetBhyperlink) { - if (linkDoc.linkAutoMove) { - linkDoc.anchor2_x = ((bpt.point.x - bleft) / bwidth) * 100; - linkDoc.anchor2_y = ((bpt.point.y - btop) / bheight) * 100; + if (linkDoc.layout_autoMoveAnchors) { + linkDoc.link_anchor_2_x = ((bpt.point.x - bleft) / bwidth) * 100; + linkDoc.link_anchor_2_y = ((bpt.point.y - btop) / bheight) * 100; } } else { const m = targetBhyperlink.getBoundingClientRect(); const mp = B.props.ScreenToLocalTransform().transformPoint(m.right, m.top + 5); const mpx = mp[0] / B.props.PanelWidth(); const mpy = mp[1] / B.props.PanelHeight(); - if (mpx >= 0 && mpx <= 1) linkDoc.anchor2_x = mpx * 100; - if (mpy >= 0 && mpy <= 1) linkDoc.anchor2_y = mpy * 100; + if (mpx >= 0 && mpx <= 1) linkDoc.link_anchor_2_x = mpx * 100; + if (mpy >= 0 && mpy <= 1) linkDoc.link_anchor_2_y = mpy * 100; if (getComputedStyle(targetBhyperlink).fontSize === '0px') linkDoc.opacity = 0; else linkDoc.opacity = 1; } @@ -112,8 +112,8 @@ export class CollectionFreeFormLinkView extends React.Component { - this.props.LinkDocs[0].linkOffsetX = NumCast(this.props.LinkDocs[0].linkOffsetX) + delta[0]; - this.props.LinkDocs[0].linkOffsetY = NumCast(this.props.LinkDocs[0].linkOffsetY) + delta[1]; + this.props.LinkDocs[0].link_relationship_OffsetX = NumCast(this.props.LinkDocs[0].link_relationship_OffsetX) + delta[0]; + this.props.LinkDocs[0].link_relationship_OffsetY = NumCast(this.props.LinkDocs[0].link_relationship_OffsetY) + delta[1]; return false; }, emptyFunction, @@ -205,8 +205,8 @@ export class CollectionFreeFormLinkView extends React.Component; + const linkRelationship = Field.toString(link?.link_relationship as any as Field); //get string representing relationship + const linkRelationshipList = Doc.UserDoc().link_relationshipList as List; const linkColorList = Doc.UserDoc().linkColorList as List; - const linkRelationshipSizes = Doc.UserDoc().linkRelationshipSizes as List; + const linkRelationshipSizes = Doc.UserDoc().link_relationshipSizes as List; const currRelationshipIndex = linkRelationshipList.indexOf(linkRelationship); - const linkDescription = Field.toString(link.description as any as Field); + const linkDescription = Field.toString(link.link_description as any as Field); const linkSize = currRelationshipIndex === -1 || currRelationshipIndex >= linkRelationshipSizes.length ? -1 : linkRelationshipSizes[currRelationshipIndex]; @@ -261,11 +261,11 @@ export class CollectionFreeFormLinkView extends React.Component @@ -294,7 +294,7 @@ export class CollectionFreeFormLinkView extends React.Component {textX === undefined || !linkDescription ? null : ( diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 08e3174d1..4d18ebeea 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -100,13 +100,13 @@ export class CollectionFreeFormView extends CollectionSubView { if (this.props.DocumentView?.().nativeWidth) return; const vals = this.fitToContentVals; - this.layoutDoc._panX = vals.bounds.cx; - this.layoutDoc._panY = vals.bounds.cy; - this.layoutDoc._viewScale = vals.scale; + this.layoutDoc._freeform_panX = vals.bounds.cx; + this.layoutDoc._freeform_panY = vals.bounds.cy; + this.layoutDoc._freeform_scale = vals.scale; }; freeformData = (force?: boolean) => (!this._firstRender && (this.fitContentsToBox || force) ? this.fitToContentVals : undefined); reverseNativeScaling = () => (this.fitContentsToBox ? true : false); - // panx, pany, zoomscale all attempt to get values first from the layout controller, then from the layout/dataDoc (or template layout doc), and finally from the resolved template data document. + // freeform_panx, freeform_pany, freeform_scale all attempt to get values first from the layout controller, then from the layout/dataDoc (or template layout doc), and finally from the resolved template data document. // this search order, for example, allows icons of cropped images to find the panx/pany/zoom on the cropped image's data doc instead of the usual layout doc because the zoom/panX/panY define the cropped image - panX = () => this.freeformData()?.bounds.cx ?? NumCast(this.Document[this.panXFieldKey], NumCast(Cast(this.Document.resolvedDataDoc, Doc, null)?.panX, 1)); - panY = () => this.freeformData()?.bounds.cy ?? NumCast(this.Document[this.panYFieldKey], NumCast(Cast(this.Document.resolvedDataDoc, Doc, null)?.panY, 1)); + panX = () => this.freeformData()?.bounds.cx ?? NumCast(this.Document[this.panXFieldKey], NumCast(Cast(this.Document.resolvedDataDoc, Doc, null)?.freeform_panX, 1)); + panY = () => this.freeformData()?.bounds.cy ?? NumCast(this.Document[this.panYFieldKey], NumCast(Cast(this.Document.resolvedDataDoc, Doc, null)?.freeform_panY, 1)); zoomScaling = () => this.freeformData()?.scale ?? NumCast(Doc.Layout(this.Document)[this.scaleFieldKey], NumCast(Cast(this.Document.resolvedDataDoc, Doc, null)?.[this.scaleFieldKey], 1)); contentTransform = () => this.props.isAnnotationOverlay && this.zoomScaling() === 1 ? `` : `translate(${this.cachedCenteringShiftX}px, ${this.cachedCenteringShiftY}px) scale(${this.zoomScaling()}) translate(${-this.panX()}px, ${-this.panY()}px)`; @@ -297,7 +297,7 @@ export class CollectionFreeFormView extends CollectionSubView= -1e-4 && curTime <= endTime); } @@ -348,7 +348,7 @@ export class CollectionFreeFormView extends CollectionSubView pair.layout) .slice() .sort((doc1, doc2) => NumCast(doc1.zIndex) - NumCast(doc2.zIndex)); - zsorted.forEach((doc, index) => (doc.zIndex = doc.isInkMask ? 5000 : index + 1)); + zsorted.forEach((doc, index) => (doc.zIndex = doc.stroke_isInkMask ? 5000 : index + 1)); const dvals = CollectionFreeFormDocumentView.getValues(refDoc, NumCast(refDoc.activeFrame, 1000)); const dropPos = this.Document._currentFrame !== undefined ? [NumCast(dvals.x), NumCast(dvals.y)] : [NumCast(refDoc.x), NumCast(refDoc.y)]; @@ -366,7 +366,7 @@ export class CollectionFreeFormView extends CollectionSubView pair.layout) .reduce((cluster, cd) => { - const grouping = this.props.Document._useClusters ? NumCast(cd.cluster, -1) : NumCast(cd.group, -1); + const grouping = this.props.Document._freeform_useClusters ? NumCast(cd.layout_cluster, -1) : NumCast(cd.group, -1); if (grouping !== -1) { const layoutDoc = Doc.Layout(cd); const cx = NumCast(cd.x) - this._clusterDistance / 2; @@ -463,10 +463,10 @@ export class CollectionFreeFormView extends CollectionSubView pair.layout).filter(cd => (this.props.Document._useClusters ? NumCast(cd.cluster) : NumCast(cd.group, -1)) === cluster); + const eles = this.childLayoutPairs.map(pair => pair.layout).filter(cd => (this.props.Document._freeform_useClusters ? NumCast(cd.layout_cluster) : NumCast(cd.group, -1)) === cluster); const clusterDocs = eles.map(ele => DocumentManager.Instance.getDocumentView(ele, this.props.DocumentView?.())!); const { left, top } = clusterDocs[0].getBounds() || { left: 0, top: 0 }; - const de = new DragManager.DocumentDragData(eles, e.ctrlKey || e.altKey ? 'alias' : undefined); + const de = new DragManager.DocumentDragData(eles, e.ctrlKey || e.altKey ? 'embed' : undefined); de.moveDocument = this.props.moveDocument; de.offset = this.getTransform().transformDirection(ptsParent.clientX - left, ptsParent.clientY - top); DragManager.StartDocumentDrag( @@ -485,8 +485,8 @@ export class CollectionFreeFormView extends CollectionSubView pair.layout).map(c => this.updateCluster(c)); } @@ -494,38 +494,43 @@ export class CollectionFreeFormView extends CollectionSubView pair.layout); - if (this.props.Document._useClusters) { + if (this.props.Document._freeform_useClusters) { const docFirst = docs[0]; docs.map(doc => this._clusterSets.map(set => Doc.IndexOf(doc, set) !== -1 && set.splice(Doc.IndexOf(doc, set), 1))); - const preferredInd = NumCast(docFirst.cluster); - docs.map(doc => (doc.cluster = -1)); + const preferredInd = NumCast(docFirst.layout_cluster); + docs.map(doc => (doc.layout_cluster = -1)); docs.map(doc => this._clusterSets.map((set, i) => set.map(member => { - if (docFirst.cluster === -1 && Doc.IndexOf(member, childLayouts) !== -1 && Doc.overlapping(doc, member, this._clusterDistance)) { - docFirst.cluster = i; + if (docFirst.layout_cluster === -1 && Doc.IndexOf(member, childLayouts) !== -1 && Doc.overlapping(doc, member, this._clusterDistance)) { + docFirst.layout_cluster = i; } }) ) ); - if (docFirst.cluster === -1 && preferredInd !== -1 && this._clusterSets.length > preferredInd && (!this._clusterSets[preferredInd] || !this._clusterSets[preferredInd].filter(member => Doc.IndexOf(member, childLayouts) !== -1).length)) { - docFirst.cluster = preferredInd; + if ( + docFirst.layout_cluster === -1 && + preferredInd !== -1 && + this._clusterSets.length > preferredInd && + (!this._clusterSets[preferredInd] || !this._clusterSets[preferredInd].filter(member => Doc.IndexOf(member, childLayouts) !== -1).length) + ) { + docFirst.layout_cluster = preferredInd; } this._clusterSets.map((set, i) => { - if (docFirst.cluster === -1 && !set.filter(member => Doc.IndexOf(member, childLayouts) !== -1).length) { - docFirst.cluster = i; + if (docFirst.layout_cluster === -1 && !set.filter(member => Doc.IndexOf(member, childLayouts) !== -1).length) { + docFirst.layout_cluster = i; } }); - if (docFirst.cluster === -1) { + if (docFirst.layout_cluster === -1) { docs.map(doc => { - doc.cluster = this._clusterSets.length; + doc.layout_cluster = this._clusterSets.length; this._clusterSets.push([doc]); }); } else if (this._clusterSets.length) { - for (let i = this._clusterSets.length; i <= NumCast(docFirst.cluster); i++) !this._clusterSets[i] && this._clusterSets.push([]); - docs.map(doc => this._clusterSets[(doc.cluster = NumCast(docFirst.cluster))].push(doc)); + for (let i = this._clusterSets.length; i <= NumCast(docFirst.layout_cluster); i++) !this._clusterSets[i] && this._clusterSets.push([]); + docs.map(doc => this._clusterSets[(doc.layout_cluster = NumCast(docFirst.layout_cluster))].push(doc)); } - childLayouts.map(child => !this._clusterSets.some((set, i) => Doc.IndexOf(child, set) !== -1 && child.cluster === i) && this.updateCluster(child)); + childLayouts.map(child => !this._clusterSets.some((set, i) => Doc.IndexOf(child, set) !== -1 && child.layout_cluster === i) && this.updateCluster(child)); } } @@ -533,31 +538,31 @@ export class CollectionFreeFormView extends CollectionSubView pair.layout); - if (this.props.Document._useClusters) { + if (this.props.Document._freeform_useClusters) { this._clusterSets.forEach(set => Doc.IndexOf(doc, set) !== -1 && set.splice(Doc.IndexOf(doc, set), 1)); - const preferredInd = NumCast(doc.cluster); - doc.cluster = -1; + const preferredInd = NumCast(doc.layout_cluster); + doc.layout_cluster = -1; this._clusterSets.forEach((set, i) => set.forEach(member => { - if (doc.cluster === -1 && Doc.IndexOf(member, childLayouts) !== -1 && Doc.overlapping(doc, member, this._clusterDistance)) { - doc.cluster = i; + if (doc.layout_cluster === -1 && Doc.IndexOf(member, childLayouts) !== -1 && Doc.overlapping(doc, member, this._clusterDistance)) { + doc.layout_cluster = i; } }) ); - if (doc.cluster === -1 && preferredInd !== -1 && this._clusterSets.length > preferredInd && (!this._clusterSets[preferredInd] || !this._clusterSets[preferredInd].filter(member => Doc.IndexOf(member, childLayouts) !== -1).length)) { - doc.cluster = preferredInd; + if (doc.layout_cluster === -1 && preferredInd !== -1 && this._clusterSets.length > preferredInd && (!this._clusterSets[preferredInd] || !this._clusterSets[preferredInd].filter(member => Doc.IndexOf(member, childLayouts) !== -1).length)) { + doc.layout_cluster = preferredInd; } this._clusterSets.forEach((set, i) => { - if (doc.cluster === -1 && !set.filter(member => Doc.IndexOf(member, childLayouts) !== -1).length) { - doc.cluster = i; + if (doc.layout_cluster === -1 && !set.filter(member => Doc.IndexOf(member, childLayouts) !== -1).length) { + doc.layout_cluster = i; } }); - if (doc.cluster === -1) { - doc.cluster = this._clusterSets.length; + if (doc.layout_cluster === -1) { + doc.layout_cluster = this._clusterSets.length; 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 ?? 0].push(doc); + for (let i = this._clusterSets.length; i <= doc.layout_cluster; i++) !this._clusterSets[i] && this._clusterSets.push([]); + this._clusterSets[doc.layout_cluster ?? 0].push(doc); } } } @@ -566,8 +571,8 @@ export class CollectionFreeFormView extends CollectionSubView doc && this.updateCluster(doc)); } else { @@ -591,7 +596,7 @@ export class CollectionFreeFormView extends CollectionSubView { if (this._hitCluster !== -1) { !addToSel && SelectionManager.DeselectAll(); - const eles = this.childLayoutPairs.map(pair => pair.layout).filter(cd => (this.props.Document._useClusters ? NumCast(cd.cluster) : NumCast(cd.group, -1)) === this._hitCluster); + const eles = this.childLayoutPairs.map(pair => pair.layout).filter(cd => (this.props.Document._freeform_useClusters ? NumCast(cd.layout_cluster) : NumCast(cd.group, -1)) === this._hitCluster); this.selectDocuments(eles); return true; } @@ -678,7 +683,6 @@ export class CollectionFreeFormView extends CollectionSubView { if (!this._deleteList.includes(intersect.inkView)) { this._deleteList.push(intersect.inkView); - SetActiveInkWidth(StrCast(intersect.inkView.rootDoc.strokeWidth?.toString()) || '1'); + SetActiveInkWidth(StrCast(intersect.inkView.rootDoc.stroke_width?.toString()) || '1'); SetActiveInkColor(StrCast(intersect.inkView.rootDoc.color?.toString()) || 'black'); // create a new curve by appending all curves of the current segment together in order to render a single new stroke. if (!e.shiftKey) { @@ -1021,19 +1025,19 @@ export class CollectionFreeFormView extends CollectionSubView 20) { deltaScale = 20 / invTransform.Scale; } - if (deltaScale < 1 && invTransform.Scale <= NumCast(this.rootDoc._viewScaleMin, 1) && this.isAnnotationOverlay) { + if (deltaScale < 1 && invTransform.Scale <= NumCast(this.rootDoc._freeform_scaleMin, 1) && this.isAnnotationOverlay) { this.setPan(0, 0); return; } - if (deltaScale * invTransform.Scale < NumCast(this.rootDoc._viewScaleMin, 1) && this.isAnnotationOverlay) { - deltaScale = NumCast(this.rootDoc._viewScaleMin, 1) / invTransform.Scale; + if (deltaScale * invTransform.Scale < NumCast(this.rootDoc._freeform_scaleMin, 1) && this.isAnnotationOverlay) { + deltaScale = NumCast(this.rootDoc._freeform_scaleMin, 1) / invTransform.Scale; } const localTransform = invTransform.scaleAbout(deltaScale, x, y); if (localTransform.Scale >= 0.05 || localTransform.Scale > this.zoomScaling()) { const safeScale = Math.min(Math.max(0.05, localTransform.Scale), 20); this.props.Document[this.scaleFieldKey] = Math.abs(safeScale); - this.setPan(-localTransform.TranslateX / safeScale, (this.props.originTopLeft ? undefined : NumCast(this.props.Document.scrollTop) * safeScale) || -localTransform.TranslateY / safeScale); + this.setPan(-localTransform.TranslateX / safeScale, (this.props.originTopLeft ? undefined : NumCast(this.props.Document.layout_scrollTop) * safeScale) || -localTransform.TranslateY / safeScale); } }; @@ -1113,26 +1117,26 @@ export class CollectionFreeFormView extends CollectionSubView (this.rootDoc.scrollTop = relTop * maxScrollTop), 10); + setTimeout(() => (this.rootDoc.layout_scrollTop = relTop * maxScrollTop), 10); newPanY = minPanY; } !this.Document._verticalScroll && (this.Document[this.panXFieldKey] = this.isAnnotationOverlay ? newPanX : panX); @@ -1143,7 +1147,7 @@ export class CollectionFreeFormView extends CollectionSubView { const collectionDoc = this.props.docViewPath().lastElement().rootDoc; - if (collectionDoc?._viewType !== CollectionViewType.Freeform || collectionDoc._panX !== undefined) { + if (collectionDoc?._viewType !== CollectionViewType.Freeform || collectionDoc._freeform_ !== undefined) { this.setPan( NumCast(this.layoutDoc[this.panXFieldKey]) + ((this.props.PanelWidth() / 2) * x) / this.zoomScaling(), // nudge x,y as a function of panel dimension and scale NumCast(this.layoutDoc[this.panYFieldKey]) + ((this.props.PanelHeight() / 2) * -y) / this.zoomScaling(), @@ -1162,7 +1166,7 @@ export class CollectionFreeFormView extends CollectionSubView NumCast(doc1.zIndex) - NumCast(doc2.zIndex)); let zfirst = docs.length ? NumCast(docs[0].zIndex) : 0; doc.zIndex = zfirst - 1; - } else if (doc.isInkMask) { + } else if (doc.stroke_isInkMask) { doc.zIndex = 5000; } else { const docs = this.childLayoutPairs.map(pair => pair.layout).slice(); @@ -1222,8 +1226,8 @@ export class CollectionFreeFormView extends CollectionSubView { const docView = fieldProps.DocumentView?.(); - if (docView && (e.metaKey || e.ctrlKey || e.altKey || docView.rootDoc._singleLine) && ['Tab', 'Enter'].includes(e.key)) { + if (docView && (e.metaKey || e.ctrlKey || e.altKey || docView.rootDoc._createDocOnCR) && ['Tab', 'Enter'].includes(e.key)) { e.stopPropagation?.(); const below = !e.altKey && e.key !== 'Tab'; - const layoutKey = StrCast(docView.LayoutFieldKey); + const layout_fieldKey = StrCast(docView.LayoutFieldKey); const newDoc = Doc.MakeCopy(docView.rootDoc, true); const dataField = docView.rootDoc[Doc.LayoutFieldKey(newDoc)]; newDoc[DataSym][Doc.LayoutFieldKey(newDoc)] = dataField === undefined || Cast(dataField, listSpec(Doc), null)?.length !== undefined ? new List([]) : undefined; if (below) newDoc.y = NumCast(docView.rootDoc.y) + NumCast(docView.rootDoc._height) + 10; else newDoc.x = NumCast(docView.rootDoc.x) + NumCast(docView.rootDoc._width) + 10; - if (layoutKey !== 'layout' && docView.rootDoc[layoutKey] instanceof Doc) { - newDoc[layoutKey] = docView.rootDoc[layoutKey]; + if (layout_fieldKey !== 'layout' && docView.rootDoc[layout_fieldKey] instanceof Doc) { + newDoc[layout_fieldKey] = docView.rootDoc[layout_fieldKey]; } Doc.GetProto(newDoc).text = undefined; FormattedTextBox.SelectOnLoad = newDoc[Id]; @@ -1315,7 +1319,7 @@ export class CollectionFreeFormView extends CollectionSubView { @@ -1521,7 +1525,7 @@ export class CollectionFreeFormView extends CollectionSubView([anchor]); + this.dataDoc[this.props.fieldKey + '_annotations'] = new List([anchor]); } } return anchor; @@ -1644,8 +1648,8 @@ export class CollectionFreeFormView extends CollectionSubView { this.dataDoc.icon = new ImageField(iconFile); - this.dataDoc['icon-nativeWidth'] = nativeWidth; - this.dataDoc['icon-nativeHeight'] = nativeHeight; + this.dataDoc['icon_nativeWidth'] = nativeWidth; + this.dataDoc['icon_nativeHeight'] = nativeHeight; } ); @@ -1762,7 +1766,7 @@ export class CollectionFreeFormView extends CollectionSubView (Doc.UserDoc().defaultToFlashcards = !Doc.UserDoc().defaultToFlashcards), icon: 'eye' }); appearanceItems.push({ description: `${this.fitContentsToBox ? 'Make Zoomable' : 'Scale to Window'}`, - event: () => (this.Document._fitContentsToBox = !this.fitContentsToBox), + event: () => (this.Document._freeform_fitContentsToBox = !this.fitContentsToBox), icon: !this.fitContentsToBox ? 'expand-arrows-alt' : 'compress-arrows-alt', }); appearanceItems.push({ description: `Pin View`, event: () => TabDocView.PinDoc(this.rootDoc, { pinViewport: MarqueeView.CurViewBounds(this.rootDoc, this.props.PanelWidth(), this.props.PanelHeight()) }), icon: 'map-pin' }); @@ -1781,7 +1785,7 @@ export class CollectionFreeFormView extends CollectionSubView SnappingManager.SetShowSnapLines(!SnappingManager.GetShowSnapLines()), icon: 'compress-arrows-alt' }) : null; - !Doc.noviceMode ? viewCtrlItems.push({ description: (this.Document._useClusters ? 'Hide' : 'Show') + ' Clusters', event: () => this.updateClusters(!this.Document._useClusters), icon: 'braille' }) : null; + !Doc.noviceMode ? viewCtrlItems.push({ description: (this.Document._freeform_useClusters ? 'Hide' : 'Show') + ' Clusters', event: () => this.updateClusters(!this.Document._freeform_useClusters), icon: 'braille' }) : null; !viewctrls && ContextMenu.Instance.addItem({ description: 'UI Controls...', subitems: viewCtrlItems, icon: 'eye' }); const options = ContextMenu.Instance.findByDescription('Options...'); @@ -1897,7 +1901,7 @@ export class CollectionFreeFormView extends CollectionSubView - {this.layoutDoc._backgroundGridShow ? ( + {this.layoutDoc._freeform_backgroundGrid ? (
this.nativeDimScaling; @@ -2310,7 +2314,7 @@ ScriptingGlobals.add(function sendToBack(doc: Doc) { }); ScriptingGlobals.add(function resetView() { SelectionManager.Docs().forEach(doc => { - doc._panX = doc._panY = 0; - doc._viewScale = 1; + doc._freeform_panX = doc._freeform_panY = 0; + doc._freeform_scale = 1; }); }); diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 11d466b0f..fdff13b54 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -52,8 +52,8 @@ export interface MarqueeViewBounds { @observer export class MarqueeView extends React.Component { public static CurViewBounds(pinDoc: Doc, panelWidth: number, panelHeight: number) { - const ps = NumCast(pinDoc._viewScale, 1); - return { left: NumCast(pinDoc._panX) - panelWidth / 2 / ps, top: NumCast(pinDoc._panY) - panelHeight / 2 / ps, width: panelWidth / ps, height: panelHeight / ps }; + const ps = NumCast(pinDoc._freeform_scale, 1); + return { left: NumCast(pinDoc._freeform_panX) - panelWidth / 2 / ps, top: NumCast(pinDoc._freeform_panY) - panelHeight / 2 / ps, width: panelWidth / ps, height: panelHeight / ps }; } private _commandExecuted = false; @@ -110,7 +110,7 @@ export class MarqueeView extends React.Component this.props.addDocTab(Docs.Create.WebDocument(`https://bing.com/search?q=${str}`, { _width: 400, x, y, _height: 512, _nativeWidth: 850, title: 'bing', useCors: true }), OpenWhere.addRight)); + cm.setDefaultItem('?', (str: string) => this.props.addDocTab(Docs.Create.WebDocument(`https://bing.com/search?q=${str}`, { _width: 400, x, y, _height: 512, _nativeWidth: 850, title: 'bing', data_useCors: true }), OpenWhere.addRight)); cm.displayMenu(this._downX, this._downY, undefined, true); e.stopPropagation(); @@ -196,7 +196,7 @@ export class MarqueeView extends React.Component 1) { @@ -204,7 +204,7 @@ export class MarqueeView extends React.Component (docDataProto[columns[i]] = values.length > i ? (values[i].indexOf(Number(values[i]).toString()) !== -1 ? Number(values[i]) : values[i]) : undefined)); if (groupAttr) { docDataProto._group = groupAttr; @@ -379,10 +379,10 @@ export class MarqueeView extends React.Component(selected); Doc.GetProto(doc).title = makeGroup ? 'grouping' : 'nested freeform'; !this.props.isAnnotationOverlay && Doc.AddFileOrphan(Doc.GetProto(doc)); - doc._panX = doc._panY = 0; + doc._freeform_panX = doc._freeform_panY = 0; return doc; })(Doc.MakeCopy(Doc.UserDoc().emptyCollection as Doc, true)); - newCollection.system = undefined; + newCollection.isSystem = undefined; newCollection._width = this.Bounds.width; newCollection._height = this.Bounds.height; newCollection._isGroup = makeGroup; @@ -390,8 +390,8 @@ export class MarqueeView extends React.Component (d.context = newCollection)); + newCollection.layout_fitWidth = true; + selected.forEach(d => (d.embedContainer = newCollection)); this.hideMarquee(); return newCollection; }); @@ -516,9 +516,19 @@ export class MarqueeView extends React.Component Doc.AreProtosEqual(DocCast(doc.context), this.rootDoc)); + return SelectionManager.Docs().filter(doc => Doc.AreProtosEqual(DocCast(doc.embedContainer), this.rootDoc)); } @computed get documentKeys() { @@ -87,7 +87,7 @@ export class CollectionSchemaView extends CollectionSubView() { } @computed get previewWidth() { - return NumCast(this.layoutDoc.schemaPreviewWidth); + return NumCast(this.layoutDoc.schema_previewWidth); } @computed get tableWidth() { @@ -95,12 +95,12 @@ export class CollectionSchemaView extends CollectionSubView() { } @computed get columnKeys() { - return Cast(this.layoutDoc.columnKeys, listSpec('string'), defaultColumnKeys); + return Cast(this.layoutDoc.schema_columnKeys, listSpec('string'), defaultColumnKeys); } @computed get storedColumnWidths() { const widths = NumListCast( - this.layoutDoc.columnWidths, + this.layoutDoc.schema_columnWidths, this.columnKeys.map(() => (this.tableWidth - CollectionSchemaView._rowMenuWidth) / this.columnKeys.length) ); @@ -243,7 +243,7 @@ export class CollectionSchemaView extends CollectionSubView() { let currKeys = [...this.columnKeys]; currKeys[index] = newKey; - this.layoutDoc.columnKeys = new List(currKeys); + this.layoutDoc.schema_columnKeys = new List(currKeys); }; @undoBatch @@ -257,11 +257,11 @@ export class CollectionSchemaView extends CollectionSubView() { const currWidths = this.storedColumnWidths.slice(); currWidths.splice(0, 0, newColWidth); const newDesiredTableWidth = currWidths.reduce((w, cw) => w + cw, 0); - this.layoutDoc.columnWidths = new List(currWidths.map(w => (w / newDesiredTableWidth) * (this.tableWidth - CollectionSchemaView._rowMenuWidth))); + this.layoutDoc.schema_columnWidths = new List(currWidths.map(w => (w / newDesiredTableWidth) * (this.tableWidth - CollectionSchemaView._rowMenuWidth))); let currKeys = this.columnKeys.slice(); currKeys.splice(0, 0, key); - this.layoutDoc.columnKeys = new List(currKeys); + this.layoutDoc.schema_columnKeys = new List(currKeys); }; @action @@ -274,11 +274,11 @@ export class CollectionSchemaView extends CollectionSubView() { const currWidths = this.storedColumnWidths.slice(); currWidths.splice(index, 1); const newDesiredTableWidth = currWidths.reduce((w, cw) => w + cw, 0); - this.layoutDoc.columnWidths = new List(currWidths.map(w => (w / newDesiredTableWidth) * (this.tableWidth - CollectionSchemaView._rowMenuWidth))); + this.layoutDoc.schema_columnWidths = new List(currWidths.map(w => (w / newDesiredTableWidth) * (this.tableWidth - CollectionSchemaView._rowMenuWidth))); let currKeys = this.columnKeys.slice(); currKeys.splice(index, 1); - this.layoutDoc.columnKeys = new List(currKeys); + this.layoutDoc.schema_columnKeys = new List(currKeys); }; @action @@ -317,7 +317,7 @@ export class CollectionSchemaView extends CollectionSubView() { @action finishResize = () => { - this.layoutDoc.columnWidths = new List(this._displayColumnWidths); + this.layoutDoc.schema_columnWidths = new List(this._displayColumnWidths); this._displayColumnWidths = undefined; }; @@ -326,11 +326,11 @@ export class CollectionSchemaView extends CollectionSubView() { moveColumn = (fromIndex: number, toIndex: number) => { let currKeys = this.columnKeys.slice(); currKeys.splice(toIndex, 0, currKeys.splice(fromIndex, 1)[0]); - this.layoutDoc.columnKeys = new List(currKeys); + this.layoutDoc.schema_columnKeys = new List(currKeys); let currWidths = this.storedColumnWidths.slice(); currWidths.splice(toIndex, 0, currWidths.splice(fromIndex, 1)[0]); - this.layoutDoc.columnWidths = new List(currWidths); + this.layoutDoc.schema_columnWidths = new List(currWidths); }; @action @@ -480,14 +480,14 @@ export class CollectionSchemaView extends CollectionSubView() { const maxWidth = 1000; const movedWidth = this.props.ScreenToLocalTransform().transformDirection(nativeWidth.right - e.clientX, 0)[0]; const width = movedWidth < minWidth ? minWidth : movedWidth > maxWidth ? maxWidth : movedWidth; - this.layoutDoc.schemaPreviewWidth = width; + this.layoutDoc.schema_previewWidth = width; return false; }; @action addNewTextDoc = (value: string, shiftDown?: boolean, forceEmptyNote?: boolean) => { if (!value && !forceEmptyNote) return false; - const newDoc = Docs.Create.TextDocument(value, { title: value, _autoHeight: true }); + const newDoc = Docs.Create.TextDocument(value, { title: value, _layout_autoHeight: true }); FormattedTextBox.SelectOnLoad = newDoc[Id]; FormattedTextBox.SelectOnLoadChar = forceEmptyNote ? '' : ' '; return this.addRow(newDoc) || false; @@ -500,7 +500,7 @@ export class CollectionSchemaView extends CollectionSubView() { ContextMenu.Instance.setDefaultItem('::', (name: string): void => { Doc.GetProto(this.props.Document)[name] = ''; - this.addRow(Docs.Create.TextDocument('', { title: name, _autoHeight: true })); + this.addRow(Docs.Create.TextDocument('', { title: name, _layout_autoHeight: true })); }); ContextMenu.Instance.displayMenu(x, y, undefined, true); }; @@ -837,7 +837,7 @@ export class CollectionSchemaView extends CollectionSubView() { }); return { docs }; } - rowHeightFunc = () => (BoolCast(this.layoutDoc._singleLine) ? CollectionSchemaView._rowSingleLineHeight : CollectionSchemaView._rowHeight); + rowHeightFunc = () => (BoolCast(this.layoutDoc._schema_singleLine) ? CollectionSchemaView._rowSingleLineHeight : CollectionSchemaView._rowHeight); sortedDocsFunc = () => this.sortedDocs; isContentActive = () => this.props.isSelected() || this.props.isContentActive(); screenToLocal = () => this.props.ScreenToLocalTransform().translate(-this.tableWidth, 0); @@ -968,7 +968,7 @@ class CollectionSchemaViewDocs extends React.Component diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx index 34631e0b7..45bfe4f77 100644 --- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx +++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx @@ -59,7 +59,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent() { onPointerMove = (e: any) => { if (!SnappingManager.GetIsDragging()) return; - const dragIsRow = DragManager.docsBeingDragged.some(doc => doc.context === this.schemaDoc); // this.schemaView?._selectedDocs.has(doc) ?? false; + const dragIsRow = DragManager.docsBeingDragged.some(doc => doc.embedContainer === this.schemaDoc); // this.schemaView?._selectedDocs.has(doc) ?? false; if (this._ref && dragIsRow) { const rect = this._ref.getBoundingClientRect(); diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx index 9f659752a..42bf32475 100644 --- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx +++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx @@ -73,7 +73,7 @@ export class SchemaTableCell extends React.Component { isSelected: returnFalse, setHeight: returnFalse, select: emptyFunction, - dropAction: 'alias' as dropActionType, + dropAction: 'embed', bringToFront: emptyFunction, renderDepth: 1, isContentActive: returnFalse, @@ -83,7 +83,7 @@ export class SchemaTableCell extends React.Component { addDocTab: SchemaTableCell.addFieldDoc, pinToPres: returnZero, Document, - fieldKey, + fieldKey: fieldKey, PanelWidth: columnWidth, PanelHeight: props.rowHeight, }; diff --git a/src/client/views/linking/LinkMenuGroup.tsx b/src/client/views/linking/LinkMenuGroup.tsx index d02a1c4eb..b9d56541a 100644 --- a/src/client/views/linking/LinkMenuGroup.tsx +++ b/src/client/views/linking/LinkMenuGroup.tsx @@ -24,12 +24,12 @@ export class LinkMenuGroup extends React.Component { private _menuRef = React.createRef(); getBackgroundColor = (): string => { - const linkRelationshipList = StrListCast(Doc.UserDoc().linkRelationshipList); + const link_relationshipList = StrListCast(Doc.UserDoc().link_relationshipList); const linkColorList = StrListCast(Doc.UserDoc().linkColorList); let color = 'white'; // if this link's relationship property is not default "link", set its color - if (linkRelationshipList) { - const relationshipIndex = linkRelationshipList.indexOf(this.props.groupType); + if (link_relationshipList) { + const relationshipIndex = link_relationshipList.indexOf(this.props.groupType); const RGBcolor: string = linkColorList[relationshipIndex]; if (RGBcolor) { //set opacity to 0.25 by modifiying the rgb string @@ -47,17 +47,18 @@ export class LinkMenuGroup extends React.Component { const sourceDoc = this.props.docView.anchorViewDoc ?? (this.props.docView.rootDoc.type === DocumentType.LINK // - ? this.props.docView.props.LayoutTemplateString?.includes('anchor1') - ? DocCast(linkDoc.anchor1) - : DocCast(linkDoc.anchor2) + ? this.props.docView.props.LayoutTemplateString?.includes('link_anchor_1') + ? DocCast(linkDoc.link_anchor_1) + : DocCast(linkDoc.link_anchor_2) : this.props.sourceDoc); const destDoc = !sourceDoc ? undefined : this.props.docView.rootDoc.type === DocumentType.LINK - ? this.props.docView.props.LayoutTemplateString?.includes('anchor1') - ? DocCast(linkDoc.anchor2) - : DocCast(linkDoc.anchor1) - : LinkManager.getOppositeAnchor(linkDoc, sourceDoc) || LinkManager.getOppositeAnchor(linkDoc, Cast(linkDoc.anchor2, Doc, null).annotationOn === sourceDoc ? Cast(linkDoc.anchor2, Doc, null) : Cast(linkDoc.anchor1, Doc, null)); + ? this.props.docView.props.LayoutTemplateString?.includes('link_anchor_1') + ? DocCast(linkDoc.link_anchor_2) + : DocCast(linkDoc.link_anchor_1) + : LinkManager.getOppositeAnchor(linkDoc, sourceDoc) || + LinkManager.getOppositeAnchor(linkDoc, Cast(linkDoc.link_anchor_2, Doc, null).annotationOn === sourceDoc ? Cast(linkDoc.link_anchor_2, Doc, null) : Cast(linkDoc.link_anchor_1, Doc, null)); return !destDoc || !sourceDoc ? null : ( void; } -// drag links and drop link targets (aliasing them if needed) +// drag links and drop link targets (embedding them if needed) export async function StartLinkTargetsDrag(dragEle: HTMLElement, docView: DocumentView, downX: number, downY: number, sourceDoc: Doc, specificLinks?: Doc[]) { const draggedDocs = (specificLinks ? specificLinks : LinkManager.Links(sourceDoc)).map(link => LinkManager.getOppositeAnchor(link, sourceDoc)).filter(l => l) as Doc[]; @@ -45,7 +43,7 @@ export async function StartLinkTargetsDrag(dragEle: HTMLElement, docView: Docume const dragData = new DragManager.DocumentDragData(moddrag.length ? moddrag : draggedDocs); dragData.canEmbed = true; - dragData.dropAction = 'alias'; + dragData.dropAction = 'embed'; DragManager.StartDocumentDrag([dragEle], dragData, downX, downY, undefined); } @@ -65,9 +63,9 @@ export class LinkMenuItem extends React.Component { @computed get sourceAnchor() { const ldoc = this.props.linkDoc; - if (this.props.sourceDoc !== ldoc.anchor1 && this.props.sourceDoc !== ldoc.anchor2) { - if (Doc.AreProtosEqual(DocCast(DocCast(ldoc.anchor1).annotationOn), this.props.sourceDoc)) return DocCast(ldoc.anchor1); - if (Doc.AreProtosEqual(DocCast(DocCast(ldoc.anchor2).annotationOn), this.props.sourceDoc)) return DocCast(ldoc.anchor2); + if (this.props.sourceDoc !== ldoc.link_anchor_1 && this.props.sourceDoc !== ldoc.link_anchor_2) { + if (Doc.AreProtosEqual(DocCast(DocCast(ldoc.link_anchor_1).annotationOn), this.props.sourceDoc)) return DocCast(ldoc.link_anchor_1); + if (Doc.AreProtosEqual(DocCast(DocCast(ldoc.link_anchor_2).annotationOn), this.props.sourceDoc)) return DocCast(ldoc.link_anchor_2); } return this.props.sourceDoc; } @@ -79,7 +77,7 @@ export class LinkMenuItem extends React.Component { this, e, e => { - const dragData = new DragManager.DocumentDragData([this.props.linkDoc], 'alias'); + const dragData = new DragManager.DocumentDragData([this.props.linkDoc], 'embed'); dragData.removeDropProperties = ['hidden']; DragManager.StartDocumentDrag([this._editRef.current!], dragData, e.x, e.y); return true; @@ -89,7 +87,7 @@ export class LinkMenuItem extends React.Component { const trail = DocCast(this.props.docView.rootDoc.presTrail); if (trail) { Doc.ActivePresentation = trail; - MainView.addDocTabFunc(trail, OpenWhere.replaceRight); + DocumentViewInternal.addDocTabFunc(trail, OpenWhere.replaceRight); } else { SelectionManager.SelectView(this.props.docView, false); if ((SettingsManager.propertiesWidth ?? 0) < 100) { @@ -118,10 +116,10 @@ export class LinkMenuItem extends React.Component { this.props.itemHandler?.(this.props.linkDoc); } else { const focusDoc = - Cast(this.props.linkDoc.anchor1, Doc, null)?.annotationOn === this.props.sourceDoc - ? Cast(this.props.linkDoc.anchor1, Doc, null) - : Cast(this.props.linkDoc.anchor2, Doc, null)?.annotationOn === this.props.sourceDoc - ? Cast(this.props.linkDoc.anchor12, Doc, null) + Cast(this.props.linkDoc.link_anchor_1, Doc, null)?.annotationOn === this.props.sourceDoc + ? Cast(this.props.linkDoc.link_anchor_1, Doc, null) + : Cast(this.props.linkDoc.link_anchor_2, Doc, null)?.annotationOn === this.props.sourceDoc + ? Cast(this.props.linkDoc.link_anchor_12, Doc, null) : undefined; if (focusDoc) this.props.docView.props.focus(focusDoc, { instant: true }); @@ -149,7 +147,7 @@ export class LinkMenuItem extends React.Component { return (
-
+
{ {this.props.linkDoc.linksToAnnotation && Cast(this.props.destinationDoc.data, WebField)?.url.href === this.props.linkDoc.annotationUri ? 'Annotation in' : ''} {StrCast(title)}

- {!this.props.linkDoc.description ? null :

{StrCast(this.props.linkDoc.description)}

} + {!this.props.linkDoc.link_description ? null :

{StrCast(this.props.linkDoc.link_description)}

}
diff --git a/src/client/views/linking/LinkRelationshipSearch.tsx b/src/client/views/linking/LinkRelationshipSearch.tsx index 53da880e4..9662b2fea 100644 --- a/src/client/views/linking/LinkRelationshipSearch.tsx +++ b/src/client/views/linking/LinkRelationshipSearch.tsx @@ -1,8 +1,8 @@ -import { observer } from "mobx-react"; +import { observer } from 'mobx-react'; import './LinkEditor.scss'; -import React = require("react"); +import React = require('react'); -interface LinkRelationshipSearchProps { +interface link_relationshipSearchProps { results: string[] | undefined; display: string; //callback fn to set rel + hide dropdown upon setting @@ -10,48 +10,48 @@ interface LinkRelationshipSearchProps { toggleSearch: () => void; } @observer -export class LinkRelationshipSearch extends React.Component { - +export class link_relationshipSearch extends React.Component { handleResultClick = (e: React.MouseEvent) => { const relationship = (e.target as HTMLParagraphElement).textContent; if (relationship) { this.props.handleRelationshipSearchChange(relationship); } - } + }; handleMouseEnter = () => { this.props.toggleSearch(); - } + }; handleMouseLeave = () => { this.props.toggleSearch(); - } + }; /** - * Render an empty div to increase the height of LinkEditor to accommodate 2+ results - */ + * Render an empty div to increase the height of LinkEditor to accommodate 2+ results + */ emptyDiv = () => { - if (this.props.results && this.props.results.length > 2 && this.props.display === "block") { - return
; + if (this.props.results && this.props.results.length > 2 && this.props.display === 'block') { + return
; } - } + }; render() { return (
-
- { // return a dropdown of relationship results if there exist results - this.props.results - ? this.props.results.map(result => { - return

- {result} -

; +
+ { + // return a dropdown of relationship results if there exist results + this.props.results ? ( + this.props.results.map(result => { + return ( +

+ {result} +

+ ); }) - :

No matching relationships

+ ) : ( +

No matching relationships

+ ) }
@@ -60,4 +60,4 @@ export class LinkRelationshipSearch extends React.Component ); } -} \ No newline at end of file +} diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx index 68fb19208..8e83cf121 100644 --- a/src/client/views/nodes/AudioBox.tsx +++ b/src/client/views/nodes/AudioBox.tsx @@ -76,7 +76,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent this.getLinkData(l)) .forEach(({ la1, la2, linkTime }) => { - if (linkTime > NumCast(this.layoutDoc._currentTimecode) && linkTime < this._ele!.currentTime) { + if (linkTime > NumCast(this.layoutDoc._layout_currentTimecode) && linkTime < this._ele!.currentTime) { Doc.linkFollowHighlight(la1); } }); - this.layoutDoc._currentTimecode = this._ele.currentTime; - this.timeline?.scrollToTime(NumCast(this.layoutDoc._currentTimecode)); + this.layoutDoc._layout_currentTimecode = this._ele.currentTime; + this.timeline?.scrollToTime(NumCast(this.layoutDoc._layout_currentTimecode)); } }; @@ -221,7 +221,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent l.anchor1 === link || l.anchor2 === link) + .filter(l => l.link_anchor_1 === link || l.link_anchor_2 === link) .forEach(l => { const { la1, la2 } = this.getLinkData(l); const startTime = this.timeline?.anchorStart(la1) || this.timeline?.anchorStart(la2); @@ -435,7 +435,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent this.props.ScreenToLocalTransform().translate(0, -AudioBox.topControlsHeight); - setPlayheadTime = (time: number) => (this._ele!.currentTime = this.layoutDoc._currentTimecode = time); + setPlayheadTime = (time: number) => (this._ele!.currentTime = this.layoutDoc._layout_currentTimecode = time); playing = () => this.mediaState === media_state.Playing; @@ -547,7 +547,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent
-
{formatTime(Math.round(NumCast(this.layoutDoc._currentTimecode)))}
+
{formatTime(Math.round(NumCast(this.layoutDoc._layout_currentTimecode)))}
) : (
@@ -623,7 +623,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent -
{this.timeline && formatTime(Math.round(NumCast(this.layoutDoc._currentTimecode) - NumCast(this.timeline.clipStart)))}
+
{this.timeline && formatTime(Math.round(NumCast(this.layoutDoc._layout_currentTimecode) - NumCast(this.timeline.clipStart)))}
{this.miniPlayer ? (
/
) : ( @@ -656,6 +656,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent (this._stackedTimeline = r))} {...this.props} CollectionFreeFormDocumentView={undefined} + dataFieldKey={this.fieldKey} fieldKey={this.annotationKey} dictationKey={this.fieldKey + '-dictation'} mediaPath={this.path} @@ -689,7 +690,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent this._ele?.duration && this._ele?.duration !== Infinity && (this.dataDoc[this.fieldKey + '-duration'] = this._ele.duration))}> + onLoadedData={action(e => this._ele?.duration && this._ele?.duration !== Infinity && (this.dataDoc[this.fieldKey + '_duration'] = this._ele.duration))}> Not supported. diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 862d0da8c..6710cee63 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -36,13 +36,13 @@ export class CollectionFreeFormDocumentView extends DocComponent (Doc.LayoutFieldKey(doc) ? [Doc.LayoutFieldKey(doc)] : []); // fields that are configured to be animatable using animation frames @@ -154,8 +154,8 @@ export class CollectionFreeFormDocumentView extends DocComponent (doc[val] = ComputedField.MakeInterpolatedString(val, 'activeFrame', doc, currTimecode))); CollectionFreeFormDocumentView.animDataFields(doc).forEach(val => (doc[val] = ComputedField.MakeInterpolatedDataField(val, 'activeFrame', doc, currTimecode))); const targetDoc = doc; // data fields, like rtf 'text' exist on the data doc, so - //doc !== targetDoc && (targetDoc.context = doc.context); // the computed fields don't see the layout doc -- need to copy the context to the data doc (HACK!!!) and set the activeFrame on the data doc (HACK!!!) - targetDoc.activeFrame = ComputedField.MakeFunction('self.context?._currentFrame||0'); + //doc !== targetDoc && (targetDoc.embedContainer = doc.embedContainer); // the computed fields don't see the layout doc -- need to copy the embedContainer to the data doc (HACK!!!) and set the activeFrame on the data doc (HACK!!!) + targetDoc.activeFrame = ComputedField.MakeFunction('self.embedContainer?._currentFrame||0'); targetDoc.dataTransition = 'inherit'; }); } @@ -202,7 +202,7 @@ export class CollectionFreeFormDocumentView extends DocComponent() { } render() { - const scaling = Math.min(this.layoutDoc.fitWidth ? 10000 : this.props.PanelHeight() / this.rootDoc[HeightSym](), this.props.PanelWidth() / this.rootDoc[WidthSym]()); + const scaling = Math.min(this.layoutDoc.layout_fitWidth ? 10000 : this.props.PanelHeight() / this.rootDoc[HeightSym](), this.props.PanelWidth() / this.rootDoc[WidthSym]()); return (
() { SetActiveInkWidth(e.target.value); SelectionManager.Views() .filter(i => StrCast(i.rootDoc.type) === DocumentType.INK) - .map(i => (i.rootDoc.strokeWidth = Number(e.target.value))); + .map(i => (i.rootDoc.stroke_width = Number(e.target.value))); }} />
diff --git a/src/client/views/nodes/ComparisonBox.tsx b/src/client/views/nodes/ComparisonBox.tsx index ace388c57..3be2d9a77 100644 --- a/src/client/views/nodes/ComparisonBox.tsx +++ b/src/client/views/nodes/ComparisonBox.tsx @@ -1,5 +1,5 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { action, observable } from 'mobx'; +import { action, computed, observable } from 'mobx'; import { observer } from 'mobx-react'; import { Doc, Opt } from '../../../fields/Doc'; import { Cast, NumCast, StrCast } from '../../../fields/Types'; @@ -26,6 +26,13 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent { // on click, animate slider movement to the targetWidth this._animating = 'all 200ms'; - this.layoutDoc._clipWidth = (targetWidth * 100) / this.props.PanelWidth(); + this.layoutDoc[this.clipWidthKey] = (targetWidth * 100) / this.props.PanelWidth(); setTimeout( action(() => (this._animating = '')), 200 @@ -71,9 +78,9 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent { - const width = movementX * this.props.ScreenToLocalTransform().Scale + (NumCast(this.layoutDoc._clipWidth) / 100) * this.props.PanelWidth(); + const width = movementX * this.props.ScreenToLocalTransform().Scale + (this.clipWidth / 100) * this.props.PanelWidth(); if (width && width > 5 && width < this.props.PanelWidth()) { - this.layoutDoc._clipWidth = (width * 100) / this.props.PanelWidth(); + this.layoutDoc[this.clipWidthKey] = (width * 100) / this.props.PanelWidth(); } return false; }; @@ -101,7 +108,6 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent { return (
{ return ( -
this.registerSliding(e, cover)} ref={ele => this.createDropTarget(ele, which, index)}> +
this.registerSliding(e, cover)} ref={ele => this.createDropTarget(ele, which, index)}> {displayDoc(which)}
); @@ -151,16 +157,16 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent - {displayBox(this.fieldKey === 'data' ? 'compareBox-after' : `${this.fieldKey}2`, 1, this.props.PanelWidth() - 3)} -
- {displayBox(this.fieldKey === 'data' ? 'compareBox-before' : `${this.fieldKey}1`, 0, 0)} + {displayBox(`${this.fieldKey}_2`, 1, this.props.PanelWidth() - 3)} +
+ {displayBox(`${this.fieldKey}_1`, 0, 0)}
(this.props.PanelWidth() - 5) / this.props.PanelWidth() ? 'w-resize' : undefined, + left: `calc(${this.clipWidth + '%'} - 0.5px)`, + cursor: this.clipWidth < 5 ? 'e-resize' : this.clipWidth / 100 > (this.props.PanelWidth() - 5) / this.props.PanelWidth() ? 'w-resize' : undefined, }} onPointerDown={e => this.registerSliding(e, this.props.PanelWidth() / 2)} /* if clicked, return slide-bar to center */ > diff --git a/src/client/views/nodes/DataVizBox/DataVizBox.tsx b/src/client/views/nodes/DataVizBox/DataVizBox.tsx index eb25d3264..5876efb01 100644 --- a/src/client/views/nodes/DataVizBox/DataVizBox.tsx +++ b/src/client/views/nodes/DataVizBox/DataVizBox.tsx @@ -3,7 +3,7 @@ import { observer } from 'mobx-react'; import * as React from 'react'; import { Doc, StrListCast } from '../../../../fields/Doc'; import { List } from '../../../../fields/List'; -import { Cast, NumCast, StrCast } from '../../../../fields/Types'; +import { Cast, CsvCast, NumCast, StrCast } from '../../../../fields/Types'; import { CsvField } from '../../../../fields/URLField'; import { Docs } from '../../../documents/Documents'; import { ViewBoxAnnotatableComponent } from '../../DocComponent'; @@ -29,7 +29,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { // @observable private pairs: { [key: string]: FieldResult }[] = []; static pairSet = new ObservableMap(); @computed.struct get pairs() { - return DataVizBox.pairSet.get(StrCast(this.rootDoc.fileUpload)); + return DataVizBox.pairSet.get(CsvCast(this.rootDoc[this.fieldKey]).url.href); } private _chartRenderer: LineChart | undefined; // // another way would be store a schema that defines the type of data we are expecting from an imported doc @@ -61,7 +61,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { @action restoreView = (data: Doc) => { const changedView = this.dataVizView !== data.presDataVizView && (this.layoutDoc._dataVizView = data.presDataVizView); - const changedAxes = this.axes.join('') !== StrListCast(data.presDataVizAxes).join('') && (this.layoutDoc._dataVizAxes = new List(StrListCast(data.presDataVizAxes))); + const changedAxes = this.axes.join('') !== StrListCast(data.presDataVizAxes).join('') && (this.layoutDoc._data_vizAxes = new List(StrListCast(data.presDataVizAxes))); const func = () => this._chartRenderer?.restoreView(data); if (changedView || changedAxes) { setTimeout(func, 100); @@ -88,14 +88,14 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { }; @computed.struct get axes() { - return StrListCast(this.layoutDoc.dataVizAxes); + return StrListCast(this.layoutDoc.data_vizAxes); } - selectAxes = (axes: string[]) => (this.layoutDoc.dataVizAxes = new List(axes)); + selectAxes = (axes: string[]) => (this.layoutDoc.data_vizAxes = new List(axes)); @computed get selectView() { const width = this.props.PanelWidth() * 0.9; const height = (this.props.PanelHeight() - 32) /* height of 'change view' button */ * 0.9; - const margin = { top: 10, right: 25, bottom: 50, left:25}; + const margin = { top: 10, right: 25, bottom: 50, left: 25 }; if (!this.pairs) return 'no data'; // prettier-ignore switch (this.dataVizView) { @@ -113,10 +113,10 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { } fetchData() { - if (DataVizBox.pairSet.has(StrCast(this.rootDoc.fileUpload))) return; - DataVizBox.pairSet.set(StrCast(this.rootDoc.fileUpload), []); + if (DataVizBox.pairSet.has(CsvCast(this.rootDoc[this.fieldKey]).url.href)) return; + DataVizBox.pairSet.set(CsvCast(this.rootDoc[this.fieldKey]).url.href, []); fetch('/csvData?uri=' + this.dataUrl?.url.href) // - .then(res => res.json().then(action(res => !res.errno && DataVizBox.pairSet.set(StrCast(this.rootDoc.fileUpload), res)))); + .then(res => res.json().then(action(res => !res.errno && DataVizBox.pairSet.set(CsvCast(this.rootDoc[this.fieldKey]).url.href, res)))); } // handle changing the view using a button diff --git a/src/client/views/nodes/DataVizBox/components/LineChart.tsx b/src/client/views/nodes/DataVizBox/components/LineChart.tsx index 777bf2f66..11f62a61f 100644 --- a/src/client/views/nodes/DataVizBox/components/LineChart.tsx +++ b/src/client/views/nodes/DataVizBox/components/LineChart.tsx @@ -56,8 +56,8 @@ export class LineChart extends React.Component { } @computed get incomingLinks() { return LinkManager.Instance.getAllRelatedLinks(this.props.rootDoc) // out of all links - .filter(link => link.anchor1 !== this.props.rootDoc) // get links where this chart doc is the target of the link - .map(link => DocCast(link.anchor1)); // then return the source of the link + .filter(link => link.link_anchor_1 !== this.props.rootDoc) // get links where this chart doc is the target of the link + .map(link => DocCast(link.link_anchor_1)); // then return the source of the link } @computed get incomingSelected() { return this.incomingLinks // all links that are pointing to this node @@ -87,7 +87,7 @@ export class LineChart extends React.Component { { fireImmediately: true } ); this._disposers.annos = reaction( - () => DocListCast(this.props.dataDoc[this.props.fieldKey + '-annotations']), + () => DocListCast(this.props.dataDoc[this.props.fieldKey + '_annotations']), annotations => { // modify how d3 renders so that anything in this annotations list would be potentially highlighted in some way // could be blue colored to make it look like anchor @@ -123,7 +123,7 @@ export class LineChart extends React.Component { element.classList.remove('selected'); } }; - // gets called whenever the "data-annotations" fields gets updated + // gets called whenever the "data_annotations" fields gets updated drawAnnotations = (dataX: number, dataY: number, selected?: boolean) => { // TODO: nda - can optimize this by having some sort of mapping of the x and y values to the individual circle elements // loop through all html elements with class .circle-d1 and find the one that has "data-x" and "data-y" attributes that match the dataX and dataY @@ -228,15 +228,15 @@ export class LineChart extends React.Component { // creating the x and y scales const xScale = scaleCreatorNumerical(xMin, xMax, 0, width); - const yScale = scaleCreatorNumerical(0, yMax,height, 0); + const yScale = scaleCreatorNumerical(0, yMax, height, 0); // adding svg const margin = this.props.margin; const svg = (this._lineChartSvg = d3 .select(this._lineChartRef.current) .append('svg') - .attr('width', `${width +margin.left + margin.right}`) - .attr('height', `${height + margin.top + margin.bottom }`) + .attr('width', `${width + margin.left + margin.right}`) + .attr('height', `${height + margin.top + margin.bottom}`) .append('g') .attr('transform', `translate(${margin.left}, ${margin.top})`)); diff --git a/src/client/views/nodes/DataVizBox/components/TableBox.tsx b/src/client/views/nodes/DataVizBox/components/TableBox.tsx index 0d69ac890..3816bddfa 100644 --- a/src/client/views/nodes/DataVizBox/components/TableBox.tsx +++ b/src/client/views/nodes/DataVizBox/components/TableBox.tsx @@ -47,17 +47,17 @@ export class TableBox extends React.Component { e => { const sourceAnchorCreator = () => this.props.docView?.()!.rootDoc!; const targetCreator = (annotationOn: Doc | undefined) => { - const alias = Doc.MakeAlias(this.props.docView?.()!.rootDoc!); - alias._dataVizView = DataVizView.LINECHART; - alias._dataVizAxes = new List([col, col]); - alias.annotationOn = annotationOn; //this.props.docView?.()!.rootDoc!; - return alias; + const embedding = Doc.MakeEmbedding(this.props.docView?.()!.rootDoc!); + embedding._dataVizView = DataVizView.LINECHART; + embedding._data_vizAxes = new List([col, col]); + embedding.annotationOn = annotationOn; //this.props.docView?.()!.rootDoc!; + return embedding; }; if (this.props.docView?.() && !Utils.isClick(e.clientX, e.clientY, downX, downY, Date.now())) { DragManager.StartAnchorAnnoDrag([header.current!], new DragManager.AnchorAnnoDragData(this.props.docView()!, sourceAnchorCreator, targetCreator), downX, downY, { dragComplete: e => { if (!e.aborted && e.annoDragData && e.annoDragData.linkSourceDoc && e.annoDragData.dropDocument && e.linkDocument) { - e.linkDocument.linkDisplay = true; + e.linkDocument.layout_linkDisplay = true; // e.annoDragData.linkSourceDoc.followLinkToggle = e.annoDragData.dropDocument.annotationOn === this.props.rootDoc; // e.annoDragData.linkSourceDoc.followLinkZoom = false; } diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index 76a5ce7b3..348ef910a 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -120,15 +120,15 @@ export class DocumentContentsView extends React.Component< select: (ctrl: boolean) => void; NativeDimScaling?: () => number; setHeight?: (height: number) => void; - layoutKey: string; + layout_fieldKey: string; } > { @computed get layout(): string { TraceMobx(); if (this.props.LayoutTemplateString) return this.props.LayoutTemplateString; if (!this.layoutDoc) return '

awaiting layout

'; - if (this.props.layoutKey === 'layout_keyValue') return StrCast(this.props.Document.layout_keyValue, KeyValueBox.LayoutString()); - const layout = Cast(this.layoutDoc[this.layoutDoc === this.props.Document && this.props.layoutKey ? this.props.layoutKey : StrCast(this.layoutDoc.layoutKey, 'layout')], 'string'); + if (this.props.layout_fieldKey === 'layout_keyValue') return StrCast(this.props.Document.layout_keyValue, KeyValueBox.LayoutString()); + const layout = Cast(this.layoutDoc[this.layoutDoc === this.props.Document && this.props.layout_fieldKey ? this.props.layout_fieldKey : StrCast(this.layoutDoc.layout_fieldKey, 'layout')], 'string'); if (layout === undefined) return this.props.Document.data ? "" : KeyValueBox.LayoutString(); if (typeof layout === 'string') return layout; return '

Loading layout

'; @@ -140,12 +140,12 @@ export class DocumentContentsView extends React.Component< } get layoutDoc() { // bcz: replaced this with below : is it correct? change was made to accommodate passing fieldKey's from a layout script - // const template: Doc = this.props.LayoutTemplate?.() || Doc.Layout(this.props.Document, this.props.layoutKey ? Cast(this.props.Document[this.props.layoutKey], Doc, null) : undefined); + // const template: Doc = this.props.LayoutTemplate?.() || Doc.Layout(this.props.Document, this.props.layout_fieldKey ? Cast(this.props.Document[this.props.layout_fieldKey], Doc, null) : undefined); const template: Doc = this.props.LayoutTemplate?.() || (this.props.LayoutTemplateString && this.props.Document) || - (this.props.layoutKey && StrCast(this.props.Document[this.props.layoutKey]) && this.props.Document) || - Doc.Layout(this.props.Document, this.props.layoutKey ? Cast(this.props.Document[this.props.layoutKey], Doc, null) : undefined); + (this.props.layout_fieldKey && StrCast(this.props.Document[this.props.layout_fieldKey]) && this.props.Document) || + Doc.Layout(this.props.Document, this.props.layout_fieldKey ? Cast(this.props.Document[this.props.layout_fieldKey], Doc, null) : undefined); return Doc.expandTemplateLayout(template, this.props.Document); } diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx index 47705d53d..d5ca30957 100644 --- a/src/client/views/nodes/DocumentLinksButton.tsx +++ b/src/client/views/nodes/DocumentLinksButton.tsx @@ -52,7 +52,7 @@ export class DocumentLinksButton extends React.Component { if (this.props.View && dropEv.linkDocument) { // dropEv.linkDocument equivalent to !dropEve.aborted since linkDocument is only assigned on a completed drop - !dropEv.linkDocument.linkRelationship && (Doc.GetProto(dropEv.linkDocument).linkRelationship = 'hyperlink'); + !dropEv.linkDocument.link_relationship && (Doc.GetProto(dropEv.linkDocument).link_relationship = 'hyperlink'); } linkDrag?.end(); }, @@ -142,7 +142,7 @@ export class DocumentLinksButton extends React.Component(this.props.View.allLinks)).forEach(link => { - if (DocUtils.FilterDocs([link], filters, []).length || DocUtils.FilterDocs([link.anchor2 as Doc], filters, []).length || DocUtils.FilterDocs([link.anchor1 as Doc], filters, []).length) { + if (DocUtils.FilterDocs([link], filters, []).length || DocUtils.FilterDocs([link.link_anchor_2 as Doc], filters, []).length || DocUtils.FilterDocs([link.link_anchor_1 as Doc], filters, []).length) { results.push(link); } }); diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index ffbde18ca..d8494e58e 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -131,7 +131,7 @@ export interface DocComponentView { setData?: (data: Field | Promise) => boolean; componentUI?: (boundsLeft: number, boundsTop: number) => JSX.Element | null; incrementalRendering?: () => void; - fitWidth?: () => boolean; // whether the component always fits width (eg, KeyValueBox) + layout_fitWidth?: () => boolean; // whether the component always fits width (eg, KeyValueBox) overridePointerEvents?: () => 'all' | 'none' | undefined; // if the conmponent overrides the pointer events for the document fieldKey?: string; annotationKey?: string; @@ -150,7 +150,7 @@ export interface DocumentViewSharedProps { Document: Doc; DataDoc?: Doc; contentBounds?: () => undefined | { x: number; y: number; r: number; b: number }; - fitContentsToBox?: () => boolean; // used by freeformview to fit its contents to its panel. corresponds to _fitContentsToBox property on a Document + fitContentsToBox?: () => boolean; // used by freeformview to fit its contents to its panel. corresponds to _freeform_fitContentsToBox property on a Document suppressSetHeight?: boolean; thumbShown?: () => boolean; setContentView?: (view: DocComponentView) => any; @@ -164,11 +164,11 @@ export interface DocumentViewSharedProps { styleProvider: Opt; setTitleFocus?: () => void; focus: DocFocusFunc; - fitWidth?: (doc: Doc) => boolean | undefined; + layout_fitWidth?: (doc: Doc) => boolean | undefined; docFilters: () => string[]; docRangeFilters: () => string[]; searchFilterDocs: () => Doc[]; - showTitle?: () => string; + layout_showTitle?: () => string; whenChildContentsActiveChanged: (isActive: boolean) => void; rootSelected: (outsideReaction?: boolean) => boolean; // whether the root of a template has been selected addDocTab: (doc: Doc, where: OpenWhere) => boolean; @@ -275,8 +275,8 @@ export class DocumentViewInternal extends DocComponent; + @computed get layout_showTitle() { + return this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.layout_showTitle) as Opt; } @computed get NativeDimScaling() { return this.props.NativeDimScaling?.() || 1; @@ -305,8 +305,8 @@ export class DocumentViewInternal extends DocComponent { - if (!StrCast(this.layoutDoc._showTitle)) this.layoutDoc._showTitle = 'title'; + if (!StrCast(this.layoutDoc._layout_showTitle)) this.layoutDoc._layout_showTitle = 'title'; setTimeout(() => this._titleRef.current?.setIsFocused(true)); // use timeout in case title wasn't shown to allow re-render so that titleref will be defined }; @@ -539,7 +539,7 @@ export class DocumentViewInternal extends DocComponent this.props.removeDocument?.(this.props.Document); @undoBatch setToggleDetail = () => (this.Document.onClick = ScriptField.MakeScript( - `toggleDetail(documentView, "${StrCast(this.Document.layoutKey) + `toggleDetail(documentView, "${StrCast(this.Document.layout_fieldKey) .replace('layout_', '') .replace(/^layout$/, 'detail')}")`, { documentView: 'any' } @@ -611,7 +611,7 @@ export class DocumentViewInternal extends DocComponent { - const portalLink = this.allLinks.find(d => d.anchor1 === this.props.Document && d.linkRelationship === 'portal to:portal from'); + const portalLink = this.allLinks.find(d => d.link_anchor_1 === this.props.Document && d.link_relationship === 'portal to:portal from'); if (!portalLink) { DocUtils.MakeLink( this.props.Document, - Docs.Create.FreeformDocument([], { _width: NumCast(this.layoutDoc._width) + 10, _height: NumCast(this.layoutDoc._height), _isLightbox: true, _fitWidth: true, title: StrCast(this.props.Document.title) + ' [Portal]' }), - { linkRelationship: 'portal to:portal from' } + Docs.Create.FreeformDocument([], { _width: NumCast(this.layoutDoc._width) + 10, _height: NumCast(this.layoutDoc._height), _isLightbox: true, _layout_fitWidth: true, title: StrCast(this.props.Document.title) + ' [Portal]' }), + { link_relationship: 'portal to:portal from' } ); } this.Document.followLinkLocation = OpenWhere.lightbox; @@ -699,7 +699,7 @@ export class DocumentViewInternal extends DocComponent item.label && cm.addItem({ description: item.label, event: () => item.script.script.run({ this: this.layoutDoc, scriptContext: this.props.scriptContext, self: this.rootDoc }), icon: item.icon as IconProp })); if (!this.props.Document.isFolder) { - const templateDoc = Cast(this.props.Document[StrCast(this.props.Document.layoutKey)], Doc, null); + const templateDoc = Cast(this.props.Document[StrCast(this.props.Document.layout_fieldKey)], Doc, null); const appearance = cm.findByDescription('UI Controls...'); const appearanceItems: ContextMenuProps[] = appearance && 'subitems' in appearance ? appearance.subitems : []; !Doc.noviceMode && templateDoc && appearanceItems.push({ description: 'Open Template ', event: () => this.props.addDocTab(templateDoc, OpenWhere.addRight), icon: 'eye' }); @@ -742,7 +742,7 @@ export class DocumentViewInternal extends DocComponent this.Document.dragFactory && (this.layoutDoc.onDragStart = ScriptField.MakeFunction('getAlias(this.dragFactory)')) }); + funcs.push({ description: 'Drag an Embedding', icon: 'edit', event: () => this.Document.dragFactory && (this.layoutDoc.onDragStart = ScriptField.MakeFunction('getEmbedding(this.dragFactory)')) }); funcs.push({ description: 'Drag a Copy', icon: 'edit', event: () => this.Document.dragFactory && (this.layoutDoc.onDragStart = ScriptField.MakeFunction('getCopy(this.dragFactory, true)')) }); funcs.push({ description: 'Drag Document', icon: 'edit', event: () => (this.layoutDoc.onDragStart = undefined) }); cm.addItem({ description: 'OnDrag...', noexpand: true, subitems: funcs, icon: 'asterisk' }); @@ -910,7 +910,7 @@ export class DocumentViewInternal extends DocComponent {this.layoutDoc.hideAllLinks ? null : this.allLinkEndpoints}
@@ -922,7 +922,7 @@ export class DocumentViewInternal extends DocComponent, props: Opt, property: string): any => { // prettier-ignore switch (property.split(':')[0]) { - case StyleProp.ShowTitle: return ''; + case StyleProp.layout_showTitle: return ''; case StyleProp.PointerEvents: return 'none'; case StyleProp.Highlighting: return undefined; } @@ -938,22 +938,22 @@ export class DocumentViewInternal extends DocComponent - Doc.AreProtosEqual(link.anchor1 as Doc, this.rootDoc) || - Doc.AreProtosEqual(link.anchor2 as Doc, this.rootDoc) || - ((link.anchor1 as Doc)?.unrendered && Doc.AreProtosEqual((link.anchor1 as Doc)?.annotationOn as Doc, this.rootDoc)) || - ((link.anchor2 as Doc)?.unrendered && Doc.AreProtosEqual((link.anchor2 as Doc)?.annotationOn as Doc, this.rootDoc)) + Doc.AreProtosEqual(link.link_anchor_1 as Doc, this.rootDoc) || + Doc.AreProtosEqual(link.link_anchor_2 as Doc, this.rootDoc) || + ((link.link_anchor_1 as Doc)?.unrendered && Doc.AreProtosEqual((link.link_anchor_1 as Doc)?.annotationOn as Doc, this.rootDoc)) || + ((link.link_anchor_2 as Doc)?.unrendered && Doc.AreProtosEqual((link.link_anchor_2 as Doc)?.annotationOn as Doc, this.rootDoc)) ); } @computed get allLinks() { TraceMobx(); return LinkManager.Instance.getAllRelatedLinks(this.rootDoc); } - hideLink = computedFn((link: Doc) => () => (link.linkDisplay = false)); + hideLink = computedFn((link: Doc) => () => (link.layout_linkDisplay = false)); @computed get allLinkEndpoints() { // the small blue dots that mark the endpoints of links TraceMobx(); - if (this.props.hideLinkAnchors || this.layoutDoc.hideLinkAnchors || this.props.dontRegisterView || this.layoutDoc.unrendered) return null; - const filtered = DocUtils.FilterDocs(this.directLinks, this.props.docFilters?.() ?? [], []).filter(d => d.linkDisplay); + if (this.props.hideLinkAnchors || this.layoutDoc.layout_hideLinkAnchors || this.props.dontRegisterView || this.layoutDoc.unrendered) return null; + const filtered = DocUtils.FilterDocs(this.directLinks, this.props.docFilters?.() ?? [], []).filter(d => d.layout_linkDisplay); return filtered.map(link => (
)); @@ -1046,9 +1046,9 @@ export class DocumentViewInternal extends DocComponent this.props.DocumentView().props.CollectionFreeFormDocumentView?.().props.ScreenToLocalTransform().Scale || 1; - const showTitle = this.ShowTitle?.split(':')[0]; - const showTitleHover = this.ShowTitle?.includes(':hover'); - const captionView = !this.showCaption ? null : ( + const layout_showTitle = this.layout_showTitle?.split(':')[0]; + const layout_showTitleHover = this.layout_showTitle?.includes(':hover'); + const captionView = !this.layout_showCaption ? null : (
); - const targetDoc = showTitle?.startsWith('_') ? this.layoutDoc : this.rootDoc; + const targetDoc = layout_showTitle?.startsWith('_') ? this.layoutDoc : this.rootDoc; const background = StrCast( SharingManager.Instance.users.find(users => users.user.email === this.dataDoc.author)?.sharingDoc.userColor, - Doc.UserDoc().showTitle && [DocumentType.RTF, DocumentType.COL].includes(this.rootDoc.type as any) ? StrCast(Doc.SharingDoc().userColor) : 'rgba(0,0,0,0.4)' + Doc.UserDoc().layout_showTitle && [DocumentType.RTF, DocumentType.COL].includes(this.rootDoc.type as any) ? StrCast(Doc.SharingDoc().userColor) : 'rgba(0,0,0,0.4)' ); - const sidebarWidthPercent = +StrCast(this.layoutDoc.sidebarWidthPercent).replace('%', ''); - const titleView = !showTitle ? null : ( + const layout_sidebarWidthPercent = +StrCast(this.layoutDoc.layout_sidebarWidthPercent).replace('%', ''); + const titleView = !layout_showTitle ? null : (
field.trim()) .map(field => targetDoc[field]?.toString()) @@ -1100,27 +1100,27 @@ export class DocumentViewInternal extends DocComponent { this.props.select(false); - return showTitle.split(';').length === 1 ? showTitle + '=' + Field.toString(targetDoc[showTitle.split(';')[0]] as any as Field) : '#' + showTitle; + return layout_showTitle.split(';').length === 1 ? layout_showTitle + '=' + Field.toString(targetDoc[layout_showTitle.split(';')[0]] as any as Field) : '#' + layout_showTitle; }} SetValue={undoBatch((input: string) => { if (input?.startsWith('#')) { - if (this.props.showTitle) { - this.rootDoc._showTitle = input?.substring(1) ? input.substring(1) : undefined; + if (this.props.layout_showTitle) { + this.rootDoc._layout_showTitle = input?.substring(1) ? input.substring(1) : undefined; } else { - Doc.UserDoc().showTitle = input?.substring(1) ? input.substring(1) : 'creationDate'; + Doc.UserDoc().layout_showTitle = input?.substring(1) ? input.substring(1) : 'creationDate'; } } else { - var value = input.replace(new RegExp(showTitle + '='), '') as string | number; - if (showTitle !== 'title' && Number(value).toString() === value) value = Number(value); - if (showTitle.includes('Date') || showTitle === 'author') return true; - Doc.SetInPlace(targetDoc, showTitle, value, true); + var value = input.replace(new RegExp(layout_showTitle + '='), '') as string | number; + if (layout_showTitle !== 'title' && Number(value).toString() === value) value = Number(value); + if (layout_showTitle.includes('Date') || layout_showTitle === 'author') return true; + Doc.SetInPlace(targetDoc, layout_showTitle, value, true); } return true; })} />
); - return this.props.hideTitle || (!showTitle && !this.showCaption) ? ( + return this.props.hideTitle || (!layout_showTitle && !this.layout_showCaption) ? ( this.contents ) : (
@@ -1319,11 +1319,11 @@ export class DocumentView extends React.Component { get LayoutFieldKey() { return this.docView?.LayoutFieldKey || 'layout'; } - @computed get fitWidth() { - return this.docView?._componentView?.fitWidth?.() ?? this.props.fitWidth?.(this.rootDoc) ?? this.layoutDoc?.fitWidth; + @computed get layout_fitWidth() { + return this.docView?._componentView?.layout_fitWidth?.() ?? this.props.layout_fitWidth?.(this.rootDoc) ?? this.layoutDoc?.layout_fitWidth; } @computed get anchorViewDoc() { - return this.props.LayoutTemplateString?.includes('anchor2') ? DocCast(this.rootDoc['anchor2']) : this.props.LayoutTemplateString?.includes('anchor1') ? DocCast(this.rootDoc['anchor1']) : undefined; + return this.props.LayoutTemplateString?.includes('link_anchor_2') ? DocCast(this.rootDoc['link_anchor_2']) : this.props.LayoutTemplateString?.includes('link_anchor_1') ? DocCast(this.rootDoc['link_anchor_1']) : undefined; } @computed get hideLinkButton() { return this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.HideLinkButton + (this.isSelected() ? ':selected' : '')); @@ -1339,13 +1339,13 @@ export class DocumentView extends React.Component { return Doc.Layout(this.Document, this.props.LayoutTemplate?.()); } @computed get nativeWidth() { - return this.docView?._componentView?.reverseNativeScaling?.() ? 0 : returnVal(this.props.NativeWidth?.(), Doc.NativeWidth(this.layoutDoc, this.props.DataDoc, !this.fitWidth)); + return this.docView?._componentView?.reverseNativeScaling?.() ? 0 : returnVal(this.props.NativeWidth?.(), Doc.NativeWidth(this.layoutDoc, this.props.DataDoc, !this.layout_fitWidth)); } @computed get nativeHeight() { - return this.docView?._componentView?.reverseNativeScaling?.() ? 0 : returnVal(this.props.NativeHeight?.(), Doc.NativeHeight(this.layoutDoc, this.props.DataDoc, !this.fitWidth)); + return this.docView?._componentView?.reverseNativeScaling?.() ? 0 : returnVal(this.props.NativeHeight?.(), Doc.NativeHeight(this.layoutDoc, this.props.DataDoc, !this.layout_fitWidth)); } @computed get shouldNotScale() { - return (this.fitWidth && !this.nativeWidth) || [CollectionViewType.Docking].includes(this.Document._viewType as any); + return (this.layout_fitWidth && !this.nativeWidth) || [CollectionViewType.Docking].includes(this.Document._viewType as any); } @computed get effectiveNativeWidth() { return this.shouldNotScale ? 0 : this.nativeWidth || NumCast(this.layoutDoc.width); @@ -1356,8 +1356,8 @@ export class DocumentView extends React.Component { @computed get nativeScaling() { if (this.shouldNotScale) return 1; const minTextScale = this.Document.type === DocumentType.RTF ? 0.1 : 0; - if (this.fitWidth || this.props.PanelHeight() / (this.effectiveNativeHeight || 1) > this.props.PanelWidth() / (this.effectiveNativeWidth || 1)) { - return Math.max(minTextScale, this.props.PanelWidth() / (this.effectiveNativeWidth || 1)); // width-limited or fitWidth + if (this.layout_fitWidth || this.props.PanelHeight() / (this.effectiveNativeHeight || 1) > this.props.PanelWidth() / (this.effectiveNativeWidth || 1)) { + return Math.max(minTextScale, this.props.PanelWidth() / (this.effectiveNativeWidth || 1)); // width-limited or layout_fitWidth } return Math.max(minTextScale, this.props.PanelHeight() / (this.effectiveNativeHeight || 1)); // height-limited or unscaled } @@ -1365,7 +1365,7 @@ export class DocumentView extends React.Component { return this.effectiveNativeWidth ? this.effectiveNativeWidth * this.nativeScaling : this.props.PanelWidth(); } @computed get panelHeight() { - if (this.effectiveNativeHeight && (!this.fitWidth || !this.layoutDoc.nativeHeightUnfrozen)) { + if (this.effectiveNativeHeight && (!this.layout_fitWidth || !this.layoutDoc.nativeHeightUnfrozen)) { return Math.min(this.props.PanelHeight(), this.effectiveNativeHeight * this.nativeScaling); } return this.props.PanelHeight(); @@ -1374,7 +1374,10 @@ export class DocumentView extends React.Component { return this.effectiveNativeWidth ? Math.max(0, (this.props.PanelWidth() - this.effectiveNativeWidth * this.nativeScaling) / 2) : 0; } @computed get Yshift() { - return this.effectiveNativeWidth && this.effectiveNativeHeight && Math.abs(this.Xshift) < 0.001 && (!this.layoutDoc.nativeHeightUnfrozen || (!this.fitWidth && this.effectiveNativeHeight * this.nativeScaling <= this.props.PanelHeight())) + return this.effectiveNativeWidth && + this.effectiveNativeHeight && + Math.abs(this.Xshift) < 0.001 && + (!this.layoutDoc.nativeHeightUnfrozen || (!this.layout_fitWidth && this.effectiveNativeHeight * this.nativeScaling <= this.props.PanelHeight())) ? Math.max(0, (this.props.PanelHeight() - this.effectiveNativeHeight * this.nativeScaling) / 2) : 0; } @@ -1410,10 +1413,10 @@ export class DocumentView extends React.Component { finished?.(); this.docView && (this.docView._animateScaleTime = animTime); }); - const layoutKey = Cast(this.Document.layoutKey, 'string', null); - if (layoutKey !== 'layout_icon') { + const layout_fieldKey = Cast(this.Document.layout_fieldKey, 'string', null); + if (layout_fieldKey !== 'layout_icon') { this.switchViews(true, 'icon', finalFinished); - if (layoutKey && layoutKey !== 'layout' && layoutKey !== 'layout_icon') this.Document.deiconifyLayout = layoutKey.replace('layout_', ''); + if (layout_fieldKey && layout_fieldKey !== 'layout' && layout_fieldKey !== 'layout_icon') this.Document.deiconifyLayout = layout_fieldKey.replace('layout_', ''); } else { const deiconifyLayout = Cast(this.Document.deiconifyLayout, 'string', null); this.switchViews(deiconifyLayout ? true : false, deiconifyLayout, finalFinished); @@ -1433,7 +1436,7 @@ export class DocumentView extends React.Component { setTimeout( action(() => { if (useExistingLayout && custom && this.rootDoc['layout_' + view]) { - this.rootDoc.layoutKey = 'layout_' + view; + this.rootDoc.layout_fieldKey = 'layout_' + view; } else { this.setCustomView(custom, view); } @@ -1520,7 +1523,7 @@ export class DocumentView extends React.Component { width: xshift ?? `${(100 * (this.props.PanelWidth() - this.Xshift * 2)) / this.props.PanelWidth()}%`, height: this.props.forceAutoHeight ? undefined - : yshift ?? (this.fitWidth ? `${this.panelHeight}px` : `${(((100 * this.effectiveNativeHeight) / this.effectiveNativeWidth) * this.props.PanelWidth()) / this.props.PanelHeight()}%`), + : yshift ?? (this.layout_fitWidth ? `${this.panelHeight}px` : `${(((100 * this.effectiveNativeHeight) / this.effectiveNativeWidth) * this.props.PanelWidth()) / this.props.PanelHeight()}%`), }}> Doc.AreProtosEqual(d, otherdoc))) { - const alias = Doc.MakeAlias(otherdoc); - alias.x = wid; - alias.y = 0; - alias._lockedPosition = false; + const embedding = Doc.MakeEmbedding(otherdoc); + embedding.x = wid; + embedding.y = 0; + embedding._lockedPosition = false; wid += otherdoc[WidthSym](); - Doc.AddDocToList(Doc.GetProto(linkCollection), 'data', alias); + Doc.AddDocToList(Doc.GetProto(linkCollection), 'data', embedding); } }); return links; diff --git a/src/client/views/nodes/EquationBox.tsx b/src/client/views/nodes/EquationBox.tsx index 163c5a9ed..f17ab06e7 100644 --- a/src/client/views/nodes/EquationBox.tsx +++ b/src/client/views/nodes/EquationBox.tsx @@ -90,7 +90,7 @@ export class EquationBox extends ViewBoxBaseComponent() { }; render() { TraceMobx(); - const scale = (this.props.NativeDimScaling?.() || 1) * NumCast(this.layoutDoc._viewScale, 1); + const scale = (this.props.NativeDimScaling?.() || 1) * NumCast(this.layoutDoc._freeform_scale, 1); return (
this.updateSize()} diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index 7eae4e938..85dd779fc 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -50,7 +50,7 @@ export class FieldView extends React.Component { @computed get field(): FieldResult { - const { Document, fieldKey } = this.props; + const { Document, fieldKey: fieldKey } = this.props; return Document[fieldKey]; } render() { diff --git a/src/client/views/nodes/FunctionPlotBox.tsx b/src/client/views/nodes/FunctionPlotBox.tsx index b43e359ff..db72209ab 100644 --- a/src/client/views/nodes/FunctionPlotBox.tsx +++ b/src/client/views/nodes/FunctionPlotBox.tsx @@ -90,7 +90,7 @@ export class FunctionPlotBox extends ViewBoxAnnotatableComponent if (ele) { this._dropDisposer = DragManager.MakeDropTarget(ele, this.drop.bind(this), this.layoutDoc); } - // if (this.autoHeight) this.tryUpdateScrollHeight(); + // if (this.layout_autoHeight) this.tryUpdateScrollHeight(); }; @computed get theGraph() { return
r && this.createGraph(r)} style={{ position: 'absolute', width: '100%', height: '100%' }} onPointerDown={e => e.stopPropagation()} />; diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index c9be10d3a..7d1d50cc7 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -79,9 +79,9 @@ export class ImageBox extends ViewBoxAnnotatableComponent ({ forceFull: this.props.renderDepth < 1 || this.layoutDoc._showFullRes, - scrSize: (this.props.ScreenToLocalTransform().inverse().transformDirection(this.nativeSize.nativeWidth, this.nativeSize.nativeHeight)[0] / this.nativeSize.nativeWidth) * NumCast(this.rootDoc._viewScale, 1), + scrSize: (this.props.ScreenToLocalTransform().inverse().transformDirection(this.nativeSize.nativeWidth, this.nativeSize.nativeHeight)[0] / this.nativeSize.nativeWidth) * NumCast(this.rootDoc._freeform_scale, 1), selected: this.props.isSelected(), }), ({ forceFull, scrSize, selected }) => (this._curSuffix = selected ? '_o' : this.fieldKey === 'icon' ? '_m' : forceFull ? '_o' : scrSize < 0.25 ? '_s' : scrSize < 0.5 ? '_m' : scrSize < 0.8 ? '_l' : '_o'), @@ -116,7 +116,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent this.layoutDoc._scrollTop, + () => this.layoutDoc.layout_scrollTop, s_top => { this._forcedScroll = true; !this._ignoreScroll && this._mainCont.current && (this._mainCont.current.scrollTop = NumCast(s_top)); @@ -144,7 +144,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent { Doc.AddDocToList(this.dataDoc, this.fieldKey + '-alternates', drop); - this.rootDoc[this.fieldKey + '-usePath'] = 'alternate:hover'; + this.rootDoc[this.fieldKey + '_usePath'] = 'alternate:hover'; e.stopPropagation(); }) ); @@ -167,28 +167,28 @@ export class ImageBox extends ViewBoxAnnotatableComponent { - const scaling = (this.props.DocumentView?.().props.ScreenToLocalTransform().Scale || 1) / NumCast(this.rootDoc._viewScale, 1); + const scaling = (this.props.DocumentView?.().props.ScreenToLocalTransform().Scale || 1) / NumCast(this.rootDoc._freeform_scale, 1); const nscale = NumCast(this.props.PanelWidth()) / scaling; - const nh = nscale / NumCast(this.dataDoc[this.fieldKey + '-nativeHeight']); - const nw = nscale / NumCast(this.dataDoc[this.fieldKey + '-nativeWidth']); - this.dataDoc[this.fieldKey + '-nativeHeight'] = NumCast(this.dataDoc[this.fieldKey + '-nativeHeight']) * nh; - this.dataDoc[this.fieldKey + '-nativeWidth'] = NumCast(this.dataDoc[this.fieldKey + '-nativeWidth']) * nh; - this.rootDoc._panX = nh * NumCast(this.rootDoc._panX); - this.rootDoc._panY = nh * NumCast(this.rootDoc._panY); - this.dataDoc._panXMax = this.dataDoc._panXMax ? nh * NumCast(this.dataDoc._panXMax) : undefined; - this.dataDoc._panXMin = this.dataDoc._panXMin ? nh * NumCast(this.dataDoc._panXMin) : undefined; - this.dataDoc._panYMax = this.dataDoc._panYMax ? nw * NumCast(this.dataDoc._panYMax) : undefined; - this.dataDoc._panYMin = this.dataDoc._panYMin ? nw * NumCast(this.dataDoc._panYMin) : undefined; + const nh = nscale / NumCast(this.dataDoc[this.fieldKey + '_nativeHeight']); + const nw = nscale / NumCast(this.dataDoc[this.fieldKey + '_nativeWidth']); + this.dataDoc[this.fieldKey + '_nativeHeight'] = NumCast(this.dataDoc[this.fieldKey + '_nativeHeight']) * nh; + this.dataDoc[this.fieldKey + '_nativeWidth'] = NumCast(this.dataDoc[this.fieldKey + '_nativeWidth']) * nh; + this.rootDoc._freeform_panX = nh * NumCast(this.rootDoc._freeform_panX); + this.rootDoc._freeform_panY = nh * NumCast(this.rootDoc._freeform_panY); + this.dataDoc._freeform_panXMax = this.dataDoc._freeform_panXMax ? nh * NumCast(this.dataDoc._freeform_panXMax) : undefined; + this.dataDoc._freeform_panXMin = this.dataDoc._freeform_panXMin ? nh * NumCast(this.dataDoc._freeform_panXMin) : undefined; + this.dataDoc._freeform_panYMax = this.dataDoc._freeform_panYMax ? nw * NumCast(this.dataDoc._freeform_panYMax) : undefined; + this.dataDoc._freeform_panYMin = this.dataDoc._freeform_panYMin ? nw * NumCast(this.dataDoc._freeform_panYMin) : undefined; }); @undoBatch rotate = action(() => { - const nw = NumCast(this.dataDoc[this.fieldKey + '-nativeWidth']); - const nh = NumCast(this.dataDoc[this.fieldKey + '-nativeHeight']); + const nw = NumCast(this.dataDoc[this.fieldKey + '_nativeWidth']); + const nh = NumCast(this.dataDoc[this.fieldKey + '_nativeHeight']); const w = this.layoutDoc._width; const h = this.layoutDoc._height; this.dataDoc[this.fieldKey + '-rotation'] = (NumCast(this.dataDoc[this.fieldKey + '-rotation']) + 90) % 360; - this.dataDoc[this.fieldKey + '-nativeWidth'] = nh; - this.dataDoc[this.fieldKey + '-nativeHeight'] = nw; + this.dataDoc[this.fieldKey + '_nativeWidth'] = nh; + this.dataDoc[this.fieldKey + '_nativeHeight'] = nw; this.layoutDoc._width = h; this.layoutDoc._height = w; }); @@ -204,7 +204,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent; }; - getScrollHeight = () => (this.props.fitWidth?.(this.rootDoc) !== false && NumCast(this.rootDoc._viewScale, 1) === NumCast(this.rootDoc._viewScaleMin, 1) ? this.nativeSize.nativeHeight : undefined); + getScrollHeight = () => (this.props.layout_fitWidth?.(this.rootDoc) !== false && NumCast(this.rootDoc._freeform_scale, 1) === NumCast(this.rootDoc._freeform_scaleMin, 1) ? this.nativeSize.nativeHeight : undefined); @computed private get considerDownloadIcon() { @@ -358,13 +358,13 @@ export class ImageBox extends ViewBoxAnnotatableComponent setupMoveUpEvents(e.target, e, returnFalse, emptyFunction, e => (this.rootDoc[`_${this.fieldKey}-usePath`] = usePath === undefined ? 'alternate' : usePath === 'alternate' ? 'alternate:hover' : undefined))} + onPointerDown={e => setupMoveUpEvents(e.target, e, returnFalse, emptyFunction, e => (this.rootDoc[`_${this.fieldKey}_usePath`] = usePath === undefined ? 'alternate' : usePath === 'alternate' ? 'alternate:hover' : undefined))} style={{ display: (SnappingManager.GetIsDragging() && DragManager.DocDragData?.canEmbed) || DocListCast(this.dataDoc[this.fieldKey + '-alternates']).length ? 'block' : 'none', width: 'min(10%, 25px)', @@ -431,7 +431,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent (this._isHovering = true))} onPointerLeave={action(() => (this._isHovering = false))} key={this.layoutDoc[Id]} ref={this.createDropTarget} onPointerDown={this.marqueeDown}> @@ -459,9 +459,9 @@ export class ImageBox extends ViewBoxAnnotatableComponent; } - screenToLocalTransform = () => this.props.ScreenToLocalTransform().translate(0, NumCast(this.layoutDoc._scrollTop) * this.props.ScreenToLocalTransform().Scale); + screenToLocalTransform = () => this.props.ScreenToLocalTransform().translate(0, NumCast(this.layoutDoc._layout_scrollTop) * this.props.ScreenToLocalTransform().Scale); marqueeDown = (e: React.PointerEvent) => { - if (!e.altKey && e.button === 0 && NumCast(this.rootDoc._viewScale, 1) <= NumCast(this.rootDoc.viewScaleMin, 1) && this.props.isContentActive(true) && ![InkTool.Highlighter, InkTool.Pen, InkTool.Write].includes(Doc.ActiveTool)) { + if (!e.altKey && e.button === 0 && NumCast(this.rootDoc._freeform_scale, 1) <= NumCast(this.rootDoc.freeform_scaleMin, 1) && this.props.isContentActive(true) && ![InkTool.Highlighter, InkTool.Pen, InkTool.Write].includes(Doc.ActiveTool)) { setupMoveUpEvents( this, e, @@ -497,9 +497,9 @@ export class ImageBox extends ViewBoxAnnotatableComponent { if (!this._forcedScroll) { - if (this.layoutDoc._scrollTop || this._mainCont.current?.scrollTop) { + if (this.layoutDoc._layout_scrollTop || this._mainCont.current?.scrollTop) { this._ignoreScroll = true; - this.layoutDoc._scrollTop = this._mainCont.current?.scrollTop; + this.layoutDoc._layout_scrollTop = this._mainCont.current?.scrollTop; this._ignoreScroll = false; } } @@ -510,7 +510,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent { } reverseNativeScaling = returnTrue; able = returnAlways; - fitWidth = returnTrue; + layout_fitWidth = returnTrue; overridePointerEvents = returnAll; onClickScriptDisable = returnAlways; @observable private rows: KeyValuePair[] = []; + @observable _splitPercentage = 50; - @computed get splitPercentage() { - return NumCast(this.props.Document.schemaSplitPercentage, 50); - } get fieldDocToLayout() { return this.props.fieldKey ? DocCast(this.props.Document[this.props.fieldKey], DocCast(this.props.Document)) : this.props.Document; } @@ -147,7 +145,9 @@ export class KeyValueBox extends React.Component { const rows: JSX.Element[] = []; let i = 0; const self = this; - for (const key of Object.keys(ids).slice().sort()) { + const keys = Object.keys(ids).slice(); + //for (const key of [...keys.filter(id => id !== 'layout' && !id.includes('_')).sort(), ...keys.filter(id => id === 'layout' || id.includes('_')).sort()]) { + for (const key of keys.sort()) { rows.push( { if (el) self.rows.push(el); }; })()} - keyWidth={100 - this.splitPercentage} + keyWidth={100 - this._splitPercentage} rowStyle={'keyValueBox-' + (i++ % 2 ? 'oddRow' : 'evenRow')} key={key} keyName={key} @@ -180,7 +180,7 @@ export class KeyValueBox extends React.Component { this._keyInput.current!.select(); e.stopPropagation(); }} - style={{ width: `${100 - this.splitPercentage}%` }}> + style={{ width: `${100 - this._splitPercentage}%` }}> { this._valInput.current!.select(); e.stopPropagation(); }} - style={{ width: `${this.splitPercentage}%` }}> + style={{ width: `${this._splitPercentage}%` }}> @@ -199,7 +199,7 @@ export class KeyValueBox extends React.Component { @action onDividerMove = (e: PointerEvent): void => { const nativeWidth = this._mainCont.current!.getBoundingClientRect(); - this.props.Document.schemaSplitPercentage = Math.max(0, 100 - Math.round(((e.clientX - nativeWidth.left) / nativeWidth.width) * 100)); + this._splitPercentage = Math.max(0, 100 - Math.round(((e.clientX - nativeWidth.left) / nativeWidth.width) * 100)); }; @action onDividerUp = (e: PointerEvent): void => { @@ -216,7 +216,7 @@ export class KeyValueBox extends React.Component { getFieldView = async () => { const rows = this.rows.filter(row => row.isChecked); if (rows.length > 1) { - const parent = Docs.Create.StackingDocument([], { _autoHeight: true, _width: 300, title: `field views for ${DocCast(this.props.Document.data).title}`, _chromeHidden: true }); + const parent = Docs.Create.StackingDocument([], { _layout_autoHeight: true, _width: 300, title: `field views for ${DocCast(this.props.Document.data).title}`, _chromeHidden: true }); for (const row of rows) { const field = this.createFieldView(DocCast(this.props.Document.data), row); field && Doc.AddDocToList(parent, 'data', field); @@ -229,9 +229,9 @@ export class KeyValueBox extends React.Component { createFieldView = (templateDoc: Doc, row: KeyValuePair) => { const metaKey = row.props.keyName; - const fieldTemplate = Doc.IsDelegateField(templateDoc, metaKey) ? Doc.MakeDelegate(templateDoc) : Doc.MakeAlias(templateDoc); + const fieldTemplate = Doc.IsDelegateField(templateDoc, metaKey) ? Doc.MakeDelegate(templateDoc) : Doc.MakeEmbedding(templateDoc); fieldTemplate.title = metaKey; - fieldTemplate.fitWidth = true; + fieldTemplate.layout_fitWidth = true; fieldTemplate._xMargin = 10; fieldTemplate._yMargin = 10; fieldTemplate._width = 100; @@ -284,8 +284,8 @@ export class KeyValueBox extends React.Component { render() { const dividerDragger = - this.splitPercentage === 0 ? null : ( -
+ this._splitPercentage === 0 ? null : ( +
); @@ -295,10 +295,10 @@ export class KeyValueBox extends React.Component { - - diff --git a/src/client/views/nodes/KeyValuePair.scss b/src/client/views/nodes/KeyValuePair.scss index 57d36932e..2b4867321 100644 --- a/src/client/views/nodes/KeyValuePair.scss +++ b/src/client/views/nodes/KeyValuePair.scss @@ -19,6 +19,7 @@ position: relative; margin: 0; } + .keyValuePair-keyFieldMod, .keyValuePair-keyField { width: 100%; margin-left: 20px; @@ -27,6 +28,9 @@ overflow: auto; display: inline; } + .keyValuePair-keyFieldMod { + margin-left: 35px; + } } } .keyValuePair-td-value { diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx index 85641124f..509bb667e 100644 --- a/src/client/views/nodes/KeyValuePair.tsx +++ b/src/client/views/nodes/KeyValuePair.tsx @@ -66,7 +66,7 @@ export class KeyValuePair extends React.Component { isSelected: returnFalse, setHeight: returnFalse, select: emptyFunction, - dropAction: 'alias', + dropAction: 'embed', bringToFront: emptyFunction, renderDepth: 1, isContentActive: returnFalse, @@ -108,8 +108,8 @@ export class KeyValuePair extends React.Component { })}> X - -
+ +
{'('.repeat(parenCount)} {props.fieldKey} {')'.repeat(parenCount)} diff --git a/src/client/views/nodes/LabelBox.tsx b/src/client/views/nodes/LabelBox.tsx index 916458dfd..32026ea9c 100644 --- a/src/client/views/nodes/LabelBox.tsx +++ b/src/client/views/nodes/LabelBox.tsx @@ -37,7 +37,7 @@ export class LabelBox extends ViewBoxBaseComponent { @@ -82,7 +82,7 @@ export class LabelBox extends ViewBoxBaseComponent { + fitTextToBox = (r: any) => { const singleLine = BoolCast(this.rootDoc._singleLine, true); const params = { rotateText: null, @@ -141,9 +141,9 @@ export class LabelBox extends ViewBoxBaseComponent - this.fitTextToBox(r))}> + this.fitTextToBox(r))}> {label.startsWith('#') ? null : label.replace(/([^a-zA-Z])/g, '$1\u200b')}
diff --git a/src/client/views/nodes/LinkAnchorBox.tsx b/src/client/views/nodes/LinkAnchorBox.tsx index 31f1775e5..f38ef634c 100644 --- a/src/client/views/nodes/LinkAnchorBox.tsx +++ b/src/client/views/nodes/LinkAnchorBox.tsx @@ -46,14 +46,14 @@ export class LinkAnchorBox extends ViewBoxBaseComponent() { const separation = Math.sqrt((pt[0] - e.clientX) * (pt[0] - e.clientX) + (pt[1] - e.clientY) * (pt[1] - e.clientY)); if (separation > 100) { const dragData = new DragManager.DocumentDragData([this.rootDoc]); - dragData.dropAction = 'alias'; - dragData.removeDropProperties = ['anchor1_x', 'anchor1_y', 'anchor2_x', 'anchor2_y', 'onClick']; + dragData.dropAction = 'embed'; + dragData.removeDropProperties = ['link_anchor_1_x', 'link_anchor_1_y', 'link_anchor_2_x', 'link_anchor_2_y', 'onClick']; DragManager.StartDocumentDrag([this._ref.current!], dragData, pt[0], pt[1]); return true; } else { this.rootDoc[this.fieldKey + '_x'] = ((pt[0] - bounds.left) / bounds.width) * 100; this.rootDoc[this.fieldKey + '_y'] = ((pt[1] - bounds.top) / bounds.height) * 100; - this.rootDoc.linkAutoMove = false; + this.rootDoc.layout_autoMoveAnchors = false; } } return false; @@ -67,10 +67,14 @@ export class LinkAnchorBox extends ViewBoxBaseComponent() { const x = NumCast(this.rootDoc[this.fieldKey + '_x'], 100); const y = NumCast(this.rootDoc[this.fieldKey + '_y'], 100); const background = this.props.styleProvider?.(this.dataDoc, this.props, StyleProp.BackgroundColor + ':anchor'); - const anchor = this.fieldKey === 'anchor1' ? 'anchor2' : 'anchor1'; - const anchorScale = !this.dataDoc[this.fieldKey + '-useLinkSmallAnchor'] && (x === 0 || x === 100 || y === 0 || y === 100) ? 1 : 0.25; + const anchor = this.fieldKey === 'link_anchor_1' ? 'link_anchor_2' : 'link_anchor_1'; + const anchorScale = !this.dataDoc[this.fieldKey + '_useLinkSmallAnchor'] && (x === 0 || x === 100 || y === 0 || y === 100) ? 1 : 0.25; const targetTitle = StrCast((this.dataDoc[anchor] as Doc)?.title); - const selView = SelectionManager.Views().lastElement()?.props.LayoutTemplateString?.includes('anchor1') ? 'anchor1' : SelectionManager.Views().lastElement()?.props.LayoutTemplateString?.includes('anchor2') ? 'anchor2' : ''; + const selView = SelectionManager.Views().lastElement()?.props.LayoutTemplateString?.includes('link_anchor_1') + ? 'link_anchor_1' + : SelectionManager.Views().lastElement()?.props.LayoutTemplateString?.includes('link_anchor_2') + ? 'link_anchor_2' + : ''; return (
() { - public static LayoutString(fieldKey: string) { + public static LayoutString(fieldKey: string = 'link') { return FieldView.LayoutString(LinkBox, fieldKey); } @@ -23,7 +23,7 @@ export class LinkBox extends ViewBoxBaseComponent() {
{ onDismiss = (add: boolean) => { LinkDescriptionPopup.descriptionPopup = false; if (add) { - LinkManager.currentLink && (Doc.GetProto(LinkManager.currentLink).description = this.description); + LinkManager.currentLink && (Doc.GetProto(LinkManager.currentLink).link_description = this.description); } }; diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx index c58b5dd8c..c6172ee01 100644 --- a/src/client/views/nodes/LinkDocPreview.tsx +++ b/src/client/views/nodes/LinkDocPreview.tsx @@ -58,13 +58,13 @@ export class LinkDocPreview extends React.Component { var linkTarget = this.props.linkDoc; this._linkSrc = this.props.linkSrc; this._linkDoc = this.props.linkDoc; - const anchor1 = this._linkDoc?.anchor1 as Doc; - const anchor2 = this._linkDoc?.anchor2 as Doc; - if (anchor1 && anchor2) { - linkTarget = Doc.AreProtosEqual(anchor1, this._linkSrc) || Doc.AreProtosEqual(anchor1?.annotationOn as Doc, this._linkSrc) ? anchor2 : anchor1; + const link_anchor_1 = this._linkDoc?.link_anchor_1 as Doc; + const link_anchor_2 = this._linkDoc?.link_anchor_2 as Doc; + if (link_anchor_1 && link_anchor_2) { + linkTarget = Doc.AreProtosEqual(link_anchor_1, this._linkSrc) || Doc.AreProtosEqual(link_anchor_1?.annotationOn as Doc, this._linkSrc) ? link_anchor_2 : link_anchor_1; } if (linkTarget?.annotationOn && linkTarget?.type !== DocumentType.RTF) { - // want to show annotation context document if annotation is not text + // want to show annotation embedContainer document if annotation is not text linkTarget && DocCastAsync(linkTarget.annotationOn).then(action(anno => (this._markerTargetDoc = this._targetDoc = anno))); } else { this._markerTargetDoc = this._targetDoc = linkTarget; @@ -111,7 +111,7 @@ export class LinkDocPreview extends React.Component { action(anchor => { if (anchor instanceof Doc && LinkManager.Links(anchor).length) { this._linkDoc = this._linkDoc ?? LinkManager.Links(anchor)[0]; - const automaticLink = this._linkDoc.linkRelationship === LinkManager.AutoKeywords; + const automaticLink = this._linkDoc.link_relationship === LinkManager.AutoKeywords; if (automaticLink) { // automatic links specify the target in the link info, not the source const linkTarget = anchor; @@ -175,7 +175,7 @@ export class LinkDocPreview extends React.Component { } else if (this.props.hrefs?.length) { const webDoc = Array.from(SearchBox.staticSearchCollection(Doc.MyFilesystem, this.props.hrefs[0]).keys()).lastElement() ?? - Docs.Create.WebDocument(this.props.hrefs[0], { title: this.props.hrefs[0], _nativeWidth: 850, _width: 200, _height: 400, useCors: true }); + Docs.Create.WebDocument(this.props.hrefs[0], { title: this.props.hrefs[0], _nativeWidth: 850, _width: 200, _height: 400, data_useCors: true }); this.props.docProps?.addDocTab(webDoc, OpenWhere.lightbox); } }; @@ -208,7 +208,7 @@ export class LinkDocPreview extends React.Component {
{StrCast(this._markerTargetDoc.title).length > 16 ? StrCast(this._markerTargetDoc.title).substr(0, 16) + '...' : StrCast(this._markerTargetDoc.title)} -

{StrCast(this._linkDoc.description)}

+

{StrCast(this._linkDoc.link_description)}

Next Link
} placement="top"> @@ -263,7 +263,7 @@ export class LinkDocPreview extends React.Component { isDocumentActive={returnFalse} isContentActive={returnFalse} addDocument={returnFalse} - showTitle={returnEmptyString} + layout_showTitle={returnEmptyString} removeDocument={returnFalse} addDocTab={returnFalse} pinToPres={returnFalse} @@ -278,7 +278,7 @@ export class LinkDocPreview extends React.Component { pointerEvents={returnNone} focus={emptyFunction} whenChildContentsActiveChanged={returnFalse} - ignoreAutoHeight={true} // need to ignore autoHeight otherwise autoHeight text boxes will expand beyond the preview panel size. + ignoreAutoHeight={true} // need to ignore layout_autoHeight otherwise layout_autoHeight text boxes will expand beyond the preview panel size. bringToFront={returnFalse} NativeWidth={Doc.NativeWidth(this._targetDoc) ? () => Doc.NativeWidth(this._targetDoc) : undefined} NativeHeight={Doc.NativeHeight(this._targetDoc) ? () => Doc.NativeHeight(this._targetDoc) : undefined} diff --git a/src/client/views/nodes/MapBox/MapBox.tsx b/src/client/views/nodes/MapBox/MapBox.tsx index 36be7d257..9b0fddce4 100644 --- a/src/client/views/nodes/MapBox/MapBox.tsx +++ b/src/client/views/nodes/MapBox/MapBox.tsx @@ -98,7 +98,7 @@ export class MapBox extends ViewBoxAnnotatableComponent void); @computed get inlineTextAnnotations() { @@ -126,7 +126,7 @@ export class MapBox extends ViewBoxAnnotatableComponent { if (this._loadPending && this._map.getBounds()) { this._loadPending = false; - this.layoutDoc.fitContentsToBox && this.fitBounds(this._map); + this.layoutDoc.freeform_fitContentsToBox && this.fitBounds(this._map); } }, 250); // listener to addmarker event @@ -282,7 +282,7 @@ export class MapBox extends ViewBoxAnnotatableComponent { if (this._loadPending && this._map.getBounds()) { this._loadPending = false; - this.layoutDoc.fitContentsToBox && this.fitBounds(this._map); + this.layoutDoc.freeform_fitContentsToBox && this.fitBounds(this._map); } this.dataDoc.mapLat = this._map.getCenter()?.lat(); this.dataDoc.mapLng = this._map.getCenter()?.lng(); @@ -292,7 +292,7 @@ export class MapBox extends ViewBoxAnnotatableComponent { if (this._loadPending && this._map.getBounds()) { this._loadPending = false; - this.layoutDoc.fitContentsToBox && this.fitBounds(this._map); + this.layoutDoc.freeform_fitContentsToBox && this.fitBounds(this._map); } this.dataDoc.mapZoom = this._map.getZoom(); }; @@ -327,7 +327,7 @@ export class MapBox extends ViewBoxAnnotatableComponent { console.log('print all sidebar Docs'); - if (!this.layoutDoc._showSidebar) this.toggleSidebar(); + if (!this.layoutDoc._layout_showSidebar) this.toggleSidebar(); const docs = doc instanceof Doc ? [doc] : doc; docs.forEach(doc => { if (doc.lat !== undefined && doc.lng !== undefined) { @@ -351,7 +351,7 @@ export class MapBox extends ViewBoxAnnotatableComponent { - if (this.layoutDoc._showSidebar) this.toggleSidebar(); + if (this.layoutDoc._layout_showSidebar) this.toggleSidebar(); const docs = doc instanceof Doc ? [doc] : doc; return this.removeDocument(doc, sidebarKey); }; @@ -375,11 +375,11 @@ export class MapBox extends ViewBoxAnnotatableComponent 0) { this._showSidebar = true; this.layoutDoc._width = fullWidth + localDelta[0]; - this.layoutDoc._sidebarWidthPercent = ((100 * (this.sidebarWidth() + localDelta[0])) / (fullWidth + localDelta[0])).toString() + '%'; + this.layoutDoc._layout_sidebarWidthPercent = ((100 * (this.sidebarWidth() + localDelta[0])) / (fullWidth + localDelta[0])).toString() + '%'; } else { this._showSidebar = false; this.layoutDoc._width = mapWidth; - this.layoutDoc._sidebarWidthPercent = '0%'; + this.layoutDoc._layout_sidebarWidthPercent = '0%'; } return false; }), @@ -388,12 +388,12 @@ export class MapBox extends ViewBoxAnnotatableComponent (Number(this.sidebarWidthPercent.substring(0, this.sidebarWidthPercent.length - 1)) / 100) * this.props.PanelWidth(); - @computed get sidebarWidthPercent() { - return StrCast(this.layoutDoc._sidebarWidthPercent, '0%'); + sidebarWidth = () => (Number(this.layout_sidebarWidthPercent.substring(0, this.layout_sidebarWidthPercent.length - 1)) / 100) * this.props.PanelWidth(); + @computed get layout_sidebarWidthPercent() { + return StrCast(this.layoutDoc._layout_sidebarWidthPercent, '0%'); } @computed get sidebarColor() { - return StrCast(this.layoutDoc.sidebarColor, StrCast(this.layoutDoc[this.props.fieldKey + '-backgroundColor'], '#e4e4e4')); + return StrCast(this.layoutDoc.sidebarColor, StrCast(this.layoutDoc[this.props.fieldKey + '_backgroundColor'], '#e4e4e4')); } /** @@ -453,7 +453,7 @@ export class MapBox extends ViewBoxAnnotatableComponent @@ -467,8 +467,8 @@ export class MapBox extends ViewBoxAnnotatableComponent { //1.2 * w * ? = .2 * w .2/1.2 const prevWidth = this.sidebarWidth(); - this.layoutDoc._showSidebar = (this.layoutDoc._sidebarWidthPercent = StrCast(this.layoutDoc._sidebarWidthPercent, '0%') === '0%' ? `${(100 * 0.2) / 1.2}%` : '0%') !== '0%'; - this.layoutDoc._width = this.layoutDoc._showSidebar ? NumCast(this.layoutDoc._width) * 1.2 : Math.max(20, NumCast(this.layoutDoc._width) - prevWidth); + this.layoutDoc._layout_showSidebar = (this.layoutDoc._layout_sidebarWidthPercent = StrCast(this.layoutDoc._layout_sidebarWidthPercent, '0%') === '0%' ? `${(100 * 0.2) / 1.2}%` : '0%') !== '0%'; + this.layoutDoc._width = this.layoutDoc._layout_showSidebar ? NumCast(this.layoutDoc._width) * 1.2 : Math.max(20, NumCast(this.layoutDoc._width) - prevWidth); }; sidebarDown = (e: React.PointerEvent) => { @@ -476,8 +476,8 @@ export class MapBox extends ViewBoxAnnotatableComponent { const bounds = this._ref.current!.getBoundingClientRect(); - this.layoutDoc._sidebarWidthPercent = '' + 100 * Math.max(0, 1 - (e.clientX - bounds.left) / bounds.width) + '%'; - this.layoutDoc._showSidebar = this.layoutDoc._sidebarWidthPercent !== '0%'; + this.layoutDoc._layout_sidebarWidthPercent = '' + 100 * Math.max(0, 1 - (e.clientX - bounds.left) / bounds.width) + '%'; + this.layoutDoc._layout_showSidebar = this.layoutDoc._layout_sidebarWidthPercent !== '0%'; e.preventDefault(); return false; }; @@ -548,7 +548,7 @@ export class MapBox extends ViewBoxAnnotatableComponent this.props.PanelWidth() / (this.props.NativeDimScaling?.() || 1) - this.sidebarWidth(); panelHeight = () => this.props.PanelHeight() / (this.props.NativeDimScaling?.() || 1); - scrollXf = () => this.props.ScreenToLocalTransform().translate(0, NumCast(this.layoutDoc._scrollTop)); + scrollXf = () => this.props.ScreenToLocalTransform().translate(0, NumCast(this.layoutDoc._layout_scrollTop)); transparentFilter = () => [...this.props.docFilters(), Utils.IsTransparentFilter()]; opaqueFilter = () => [...this.props.docFilters(), Utils.IsOpaqueFilter()]; infoWidth = () => this.props.PanelWidth() / 5; @@ -616,7 +616,7 @@ export class MapBox extends ViewBoxAnnotatableComponent + style={{ width: `calc(100% - ${this.layout_sidebarWidthPercent})`, pointerEvents: this.pointerEvents() }}>
{renderAnnotations(this.transparentFilter)}
{renderAnnotations(this.opaqueFilter)} {SnappingManager.GetIsDragging() ? null : renderAnnotations()} @@ -667,7 +667,7 @@ export class MapBox extends ViewBoxAnnotatableComponent {/* */} -
+
void); @computed get inlineTextAnnotations() { @@ -123,7 +123,7 @@ export class MapBox2 extends ViewBoxAnnotatableComponent { if (this._loadPending && this._map.getBounds()) { this._loadPending = false; - this.layoutDoc.fitContentsToBox && this.fitBounds(this._map); + this.layoutDoc.freeform_fitContentsToBox && this.fitBounds(this._map); } }, 250); // listener to addmarker event @@ -279,7 +279,7 @@ export class MapBox2 extends ViewBoxAnnotatableComponent { if (this._loadPending && this._map.getBounds()) { this._loadPending = false; - this.layoutDoc.fitContentsToBox && this.fitBounds(this._map); + this.layoutDoc.freeform_fitContentsToBox && this.fitBounds(this._map); } this.dataDoc.mapLat = this._map.getCenter()?.lat(); this.dataDoc.mapLng = this._map.getCenter()?.lng(); @@ -289,7 +289,7 @@ export class MapBox2 extends ViewBoxAnnotatableComponent { if (this._loadPending && this._map.getBounds()) { this._loadPending = false; - this.layoutDoc.fitContentsToBox && this.fitBounds(this._map); + this.layoutDoc.freeform_fitContentsToBox && this.fitBounds(this._map); } this.dataDoc.mapZoom = this._map.getZoom(); }; @@ -324,7 +324,7 @@ export class MapBox2 extends ViewBoxAnnotatableComponent { console.log('print all sidebar Docs'); - if (!this.layoutDoc._showSidebar) this.toggleSidebar(); + if (!this.layoutDoc._layout_showSidebar) this.toggleSidebar(); const docs = doc instanceof Doc ? [doc] : doc; docs.forEach(doc => { if (doc.lat !== undefined && doc.lng !== undefined) { @@ -348,7 +348,7 @@ export class MapBox2 extends ViewBoxAnnotatableComponent { - if (this.layoutDoc._showSidebar) this.toggleSidebar(); + if (this.layoutDoc._layout_showSidebar) this.toggleSidebar(); const docs = doc instanceof Doc ? [doc] : doc; return this.removeDocument(doc, sidebarKey); }; @@ -372,11 +372,11 @@ export class MapBox2 extends ViewBoxAnnotatableComponent 0) { this._showSidebar = true; this.layoutDoc._width = fullWidth + localDelta[0]; - this.layoutDoc._sidebarWidthPercent = ((100 * (this.sidebarWidth() + localDelta[0])) / (fullWidth + localDelta[0])).toString() + '%'; + this.layoutDoc._layout_sidebarWidthPercent = ((100 * (this.sidebarWidth() + localDelta[0])) / (fullWidth + localDelta[0])).toString() + '%'; } else { this._showSidebar = false; this.layoutDoc._width = mapWidth; - this.layoutDoc._sidebarWidthPercent = '0%'; + this.layoutDoc._layout_sidebarWidthPercent = '0%'; } return false; }), @@ -385,12 +385,12 @@ export class MapBox2 extends ViewBoxAnnotatableComponent (Number(this.sidebarWidthPercent.substring(0, this.sidebarWidthPercent.length - 1)) / 100) * this.props.PanelWidth(); - @computed get sidebarWidthPercent() { - return StrCast(this.layoutDoc._sidebarWidthPercent, '0%'); + sidebarWidth = () => (Number(this.layout_sidebarWidthPercent.substring(0, this.layout_sidebarWidthPercent.length - 1)) / 100) * this.props.PanelWidth(); + @computed get layout_sidebarWidthPercent() { + return StrCast(this.layoutDoc._layout_sidebarWidthPercent, '0%'); } @computed get sidebarColor() { - return StrCast(this.layoutDoc.sidebarColor, StrCast(this.layoutDoc[this.props.fieldKey + '-backgroundColor'], '#e4e4e4')); + return StrCast(this.layoutDoc.sidebarColor, StrCast(this.layoutDoc[this.props.fieldKey + '_backgroundColor'], '#e4e4e4')); } /** @@ -450,7 +450,7 @@ export class MapBox2 extends ViewBoxAnnotatableComponent @@ -464,8 +464,8 @@ export class MapBox2 extends ViewBoxAnnotatableComponent { //1.2 * w * ? = .2 * w .2/1.2 const prevWidth = this.sidebarWidth(); - this.layoutDoc._showSidebar = (this.layoutDoc._sidebarWidthPercent = StrCast(this.layoutDoc._sidebarWidthPercent, '0%') === '0%' ? `${(100 * 0.2) / 1.2}%` : '0%') !== '0%'; - this.layoutDoc._width = this.layoutDoc._showSidebar ? NumCast(this.layoutDoc._width) * 1.2 : Math.max(20, NumCast(this.layoutDoc._width) - prevWidth); + this.layoutDoc._layout_showSidebar = (this.layoutDoc._layout_sidebarWidthPercent = StrCast(this.layoutDoc._layout_sidebarWidthPercent, '0%') === '0%' ? `${(100 * 0.2) / 1.2}%` : '0%') !== '0%'; + this.layoutDoc._width = this.layoutDoc._layout_showSidebar ? NumCast(this.layoutDoc._width) * 1.2 : Math.max(20, NumCast(this.layoutDoc._width) - prevWidth); }; sidebarDown = (e: React.PointerEvent) => { @@ -473,8 +473,8 @@ export class MapBox2 extends ViewBoxAnnotatableComponent { const bounds = this._ref.current!.getBoundingClientRect(); - this.layoutDoc._sidebarWidthPercent = '' + 100 * Math.max(0, 1 - (e.clientX - bounds.left) / bounds.width) + '%'; - this.layoutDoc._showSidebar = this.layoutDoc._sidebarWidthPercent !== '0%'; + this.layoutDoc._layout_sidebarWidthPercent = '' + 100 * Math.max(0, 1 - (e.clientX - bounds.left) / bounds.width) + '%'; + this.layoutDoc._layout_showSidebar = this.layoutDoc._layout_sidebarWidthPercent !== '0%'; e.preventDefault(); return false; }; @@ -545,7 +545,7 @@ export class MapBox2 extends ViewBoxAnnotatableComponent this.props.PanelWidth() / (this.props.NativeDimScaling?.() || 1) - this.sidebarWidth(); panelHeight = () => this.props.PanelHeight() / (this.props.NativeDimScaling?.() || 1); - scrollXf = () => this.props.ScreenToLocalTransform().translate(0, NumCast(this.layoutDoc._scrollTop)); + scrollXf = () => this.props.ScreenToLocalTransform().translate(0, NumCast(this.layoutDoc._layout_scrollTop)); transparentFilter = () => [...this.props.docFilters(), Utils.IsTransparentFilter()]; opaqueFilter = () => [...this.props.docFilters(), Utils.IsOpaqueFilter()]; infoWidth = () => this.props.PanelWidth() / 5; @@ -566,7 +566,7 @@ export class MapBox2 extends ViewBoxAnnotatableComponent { e.button === 0 && !e.ctrlKey && e.stopPropagation(); }} - style={{ width: `calc(100% - ${this.sidebarWidthPercent})`, pointerEvents: this.pointerEvents() }}> + style={{ width: `calc(100% - ${this.layout_sidebarWidthPercent})`, pointerEvents: this.pointerEvents() }}>
{renderAnnotations(this.transparentFilter)}
{renderAnnotations(this.opaqueFilter)} {SnappingManager.GetIsDragging() ? null : renderAnnotations()} @@ -616,7 +616,7 @@ export class MapBox2 extends ViewBoxAnnotatableComponent {/* */} -
+
{ setupMoveUpEvents(this, e, returnFalse, emptyFunction, e => { - const newBox = Docs.Create.TextDocument('Note', { _autoHeight: true }); + const newBox = Docs.Create.TextDocument('Note', { _layout_autoHeight: true }); FormattedTextBox.SelectOnLoad = newBox[Id]; // track the new text box so we can give it a prop that tells it to focus itself when it's displayed Doc.AddDocToList(this.props.place, 'data', newBox); this._stack?.scrollToBottom(); @@ -42,7 +42,7 @@ export class MapBoxInfoWindow extends React.Component doc.type === DocumentType.RTF; + childLayoutFitWidth = (doc: Doc) => doc.type === DocumentType.RTF; addDoc = (doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).reduce((p, d) => p && Doc.AddDocToList(this.props.place, 'data', d), true as boolean); removeDoc = (doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).reduce((p, d) => p && Doc.RemoveDocFromList(this.props.place, 'data', d), true as boolean); render() { @@ -69,7 +69,7 @@ export class MapBoxInfoWindow extends React.Component (this._pdf = PDFBox.pdfcache.get(this.pdfUrl!.url.href))); else if (PDFBox.pdfpromise.get(this.pdfUrl.url.href)) PDFBox.pdfpromise.get(this.pdfUrl.url.href)?.then(action((pdf: any) => (this._pdf = pdf))); @@ -122,15 +122,15 @@ export class PDFBox extends ViewBoxAnnotatableComponent { @@ -173,15 +173,15 @@ export class PDFBox extends ViewBoxAnnotatableComponent { setTimeout(() => { this.dataDoc.icon = new ImageField(iconFile); - this.dataDoc['icon-nativeWidth'] = nativeWidth; - this.dataDoc['icon-nativeHeight'] = nativeHeight; + this.dataDoc['icon_nativeWidth'] = nativeWidth; + this.dataDoc['icon_nativeHeight'] = nativeHeight; }, 500); } ); @@ -201,13 +201,13 @@ export class PDFBox extends ViewBoxAnnotatableComponent this.rootDoc.scrollTop, + () => this.rootDoc.layout_scrollTop, () => { - if (!(ComputedField.WithoutComputed(() => FieldValue(this.props.Document[this.SidebarKey + '-panY'])) instanceof ComputedField)) { - this.props.Document[this.SidebarKey + '-panY'] = ComputedField.MakeFunction('this.scrollTop'); + if (!(ComputedField.WithoutComputed(() => FieldValue(this.props.Document[this.SidebarKey + '_panY'])) instanceof ComputedField)) { + this.props.Document[this.SidebarKey + '_panY'] = ComputedField.MakeFunction('this.layout_scrollTop'); } - this.props.Document[this.SidebarKey + '-viewScale'] = 1; - this.props.Document[this.SidebarKey + '-panX'] = 0; + this.props.Document[this.SidebarKey + '_freeform_scale'] = 1; + this.props.Document[this.SidebarKey + '_freeform_panX'] = 0; } ); } @@ -215,7 +215,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent this._pdfViewer?.brushView(view); sidebarAddDocTab = (doc: Doc, where: OpenWhere) => { - if (DocListCast(this.props.Document[this.props.fieldKey + '-sidebar']).includes(doc) && !this.SidebarShown) { + if (DocListCast(this.props.Document[this.props.fieldKey + '_sidebar']).includes(doc) && !this.SidebarShown) { this.toggleSidebar(false); return true; } @@ -239,7 +239,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent { const anchor = Docs.Create.TextanchorDocument({ - title: StrCast(this.rootDoc.title + '@' + NumCast(this.layoutDoc._scrollTop)?.toFixed(0)), + title: StrCast(this.rootDoc.title + '@' + NumCast(this.layoutDoc._layout_scrollTop)?.toFixed(0)), unrendered: true, annotationOn: this.rootDoc, }); @@ -258,11 +258,11 @@ export class PDFBox extends ViewBoxAnnotatableComponent { - this.dataDoc[this.props.fieldKey + '-numPages'] = np; + this.dataDoc[this.props.fieldKey + '_numPages'] = np; Doc.SetNativeWidth(this.dataDoc, Math.max(Doc.NativeWidth(this.dataDoc), (nw * 96) / 72)); Doc.SetNativeHeight(this.dataDoc, (nh * 96) / 72); this.layoutDoc._height = this.layoutDoc[WidthSym]() / (Doc.NativeAspect(this.dataDoc) || 1); - !this.Document._fitWidth && (this.Document._height = this.Document[WidthSym]() * (nh / nw)); + !this.Document._layout_fitWidth && (this.Document._height = this.Document[WidthSym]() * (nh / nw)); }; public search = action((searchString: string, bwd?: boolean, clear: boolean = false) => { @@ -279,14 +279,14 @@ export class PDFBox extends ViewBoxAnnotatableComponent this._pdfViewer?.prevAnnotation(); public nextAnnotation = () => this._pdfViewer?.nextAnnotation(); public backPage = () => { - this.Document._curPage = Math.max(1, (NumCast(this.Document._curPage) || 1) - 1); + this.Document._layout_curPage = Math.max(1, (NumCast(this.Document._layout_curPage) || 1) - 1); return true; }; public forwardPage = () => { - this.Document._curPage = Math.min(NumCast(this.dataDoc[this.props.fieldKey + '-numPages']), (NumCast(this.Document._curPage) || 1) + 1); + this.Document._layout_curPage = Math.min(NumCast(this.dataDoc[this.props.fieldKey + '_numPages']), (NumCast(this.Document._layout_curPage) || 1) + 1); return true; }; - public gotoPage = (p: number) => (this.Document._curPage = p); + public gotoPage = (p: number) => (this.Document._layout_curPage = p); @undoBatch onKeyDown = action((e: KeyboardEvent) => { @@ -316,9 +316,9 @@ export class PDFBox extends ViewBoxAnnotatableComponent) => (this._searchString = e.currentTarget.value); // adding external documents; to sidebar key - // if (doc.Geolocation) this.addDocument(doc, this.fieldkey+"-annotation") + // if (doc.Geolocation) this.addDocument(doc, this.fieldkey+"_annotation") sidebarAddDocument = (doc: Doc | Doc[], sidebarKey: string = this.SidebarKey) => { - if (!this.layoutDoc._showSidebar) this.toggleSidebar(); + if (!this.layoutDoc._show_sidebar) this.toggleSidebar(); return this.addDocument(doc, sidebarKey); }; sidebarBtnDown = (e: React.PointerEvent, onButton: boolean) => { @@ -332,13 +332,13 @@ export class PDFBox extends ViewBoxAnnotatableComponent= 1) { this.layoutDoc.nativeWidth = nativeWidth * ratio; onButton && (this.layoutDoc._width = this.layoutDoc[WidthSym]() + localDelta[0]); - this.layoutDoc._showSidebar = nativeWidth !== this.layoutDoc._nativeWidth; + this.layoutDoc._show_sidebar = nativeWidth !== this.layoutDoc._nativeWidth; } return false; }, @@ -352,7 +352,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent = undefined; @observable _previewWidth: Opt = undefined; toggleSidebar = action((preview: boolean = false) => { - const nativeWidth = NumCast(this.layoutDoc[this.fieldKey + '-nativeWidth']); + const nativeWidth = NumCast(this.layoutDoc[this.fieldKey + '_nativeWidth']); const sideratio = ((!this.layoutDoc.nativeWidth || this.layoutDoc.nativeWidth === nativeWidth ? PDFBox.openSidebarWidth : 0) + nativeWidth) / nativeWidth; const pdfratio = ((!this.layoutDoc.nativeWidth || this.layoutDoc.nativeWidth === nativeWidth ? PDFBox.openSidebarWidth + PDFBox.sidebarResizerWidth : 0) + nativeWidth) / nativeWidth; const curNativeWidth = NumCast(this.layoutDoc.nativeWidth, nativeWidth); @@ -363,7 +363,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent ); const searchTitle = `${!this._searching ? 'Open' : 'Close'} Search Bar`; - const curPage = NumCast(this.Document._curPage) || 1; + const curPage = NumCast(this.Document._layout_curPage) || 1; return !this.props.isContentActive() || this._pdfViewer?.isAnnotating ? null : (
99 ? 4 : 3}ch`, pointerEvents: 'all' }} - onChange={e => (this.Document._curPage = Number(e.currentTarget.value))} + onChange={e => (this.Document._layout_curPage = Number(e.currentTarget.value))} onKeyDown={e => e.stopPropagation()} onClick={action(() => (this._pageControls = !this._pageControls))} /> @@ -470,7 +470,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent this._sidebarRef.current?.anchorMenuClick; @observable _showSidebar = false; @computed get SidebarShown() { - return this._showSidebar || this.layoutDoc._showSidebar ? true : false; + return this._showSidebar || this.layoutDoc._show_sidebar ? true : false; } @computed get sidebarHandle() { return ( @@ -480,7 +480,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent this.sidebarBtnDown(e, true)}> @@ -490,10 +490,10 @@ export class PDFBox extends ViewBoxAnnotatableComponent 600 ? (NumCast(this.Document._height) * this.props.PanelWidth()) / NumCast(this.Document._width) : undefined, + height: this.props.Document._layout_scrollTop && !this.Document._layout_fitWidth && window.screen.width > 600 ? (NumCast(this.Document._height) * this.props.PanelWidth()) / NumCast(this.Document._width) : undefined, }}>
this.sidebarBtnDown(e, false)} />
{ this.result = info; this.dataDoc.type = DocumentType.VID; - this.dataDoc[this.fieldKey + '-duration'] = this.videoDuration; + this.dataDoc[this.fieldKey + '_duration'] = this.videoDuration; this.dataDoc.layout = VideoBox.LayoutString(this.fieldKey); this.dataDoc[this.props.fieldKey] = new VideoField(this.result.accessPaths.client); diff --git a/src/client/views/nodes/ScreenshotBox.tsx b/src/client/views/nodes/ScreenshotBox.tsx index 75e61bbeb..7bf765042 100644 --- a/src/client/views/nodes/ScreenshotBox.tsx +++ b/src/client/views/nodes/ScreenshotBox.tsx @@ -129,7 +129,7 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponent { - const startTime = Cast(this.layoutDoc._currentTimecode, 'number', null) || (this._videoRec ? (Date.now() - (this.recordingStart || 0)) / 1000 : undefined); + const startTime = Cast(this.layoutDoc._layout_currentTimecode, 'number', null) || (this._videoRec ? (Date.now() - (this.recordingStart || 0)) / 1000 : undefined); return CollectionStackedTimeline.createAnchor(this.rootDoc, this.dataDoc, this.annotationKey, startTime, startTime === undefined ? undefined : startTime + 3, undefined, addAsAnnotation) || this.rootDoc; }; @@ -236,13 +236,13 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponent { if (this.dataDoc[this.fieldKey + '-dictation']) return; const dictationText = DocUtils.GetNewTextDoc('dictation', NumCast(this.rootDoc.x), NumCast(this.rootDoc.y) + NumCast(this.layoutDoc._height) + 10, NumCast(this.layoutDoc._width), 2 * NumCast(this.layoutDoc._height)); - dictationText._autoHeight = false; + dictationText._layout_autoHeight = false; const dictationTextProto = Doc.GetProto(dictationText); dictationTextProto.recordingSource = this.dataDoc; dictationTextProto.recordingStart = ComputedField.MakeFunction(`self.recordingSource["${this.props.fieldKey}-recordingStart"]`); dictationTextProto.mediaState = ComputedField.MakeFunction('self.recordingSource.mediaState'); this.dataDoc[this.fieldKey + '-dictation'] = dictationText; }; - videoPanelHeight = () => (NumCast(this.dataDoc[this.fieldKey + '-nativeHeight'], this.layoutDoc[HeightSym]()) / NumCast(this.dataDoc[this.fieldKey + '-nativeWidth'], this.layoutDoc[WidthSym]())) * this.props.PanelWidth(); + videoPanelHeight = () => (NumCast(this.dataDoc[this.fieldKey + '_nativeHeight'], this.layoutDoc[HeightSym]()) / NumCast(this.dataDoc[this.fieldKey + '_nativeWidth'], this.layoutDoc[WidthSym]())) * this.props.PanelWidth(); formattedPanelHeight = () => Math.max(0, this.props.PanelHeight() - this.videoPanelHeight()); render() { TraceMobx(); diff --git a/src/client/views/nodes/ScriptingBox.tsx b/src/client/views/nodes/ScriptingBox.tsx index f09962b22..37fda14fc 100644 --- a/src/client/views/nodes/ScriptingBox.tsx +++ b/src/client/views/nodes/ScriptingBox.tsx @@ -167,7 +167,7 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent { - this.rootDoc.layoutKey = 'layout'; + this.rootDoc.layout_fieldKey = 'layout'; }; // displays error message @@ -702,7 +702,7 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent - {!StrCast(this.rootDoc.layoutKey).startsWith('layout_on') ? null : ( + {!StrCast(this.rootDoc.layout_fieldKey).startsWith('layout_on') ? null : (
+ Key + Fields