From fd329ad25987122c8f2a31177a6c346c97f00457 Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 25 Feb 2021 18:54:45 -0500 Subject: added 'proto' drag option for dropping proto of document. auto add of non annotations to file system. auto added delegates & aliases to a docuemnt's 'alias' field. --- src/client/views/collections/CollectionSubView.tsx | 6 +----- src/client/views/collections/CollectionView.tsx | 5 ++--- src/client/views/collections/TreeView.tsx | 16 ++++++++++------ .../views/collections/collectionFreeForm/MarqueeView.tsx | 4 ++-- 4 files changed, 15 insertions(+), 16 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index a9438f8f7..d5fa81024 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -253,11 +253,7 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T, moreProps?: e.stopPropagation(); e.preventDefault(); - const addDocument = (doc: Doc | Doc[]) => { - const docs = doc instanceof Doc ? [doc] : doc; - docs.forEach(doc => Doc.AddDocToList(Cast(Doc.UserDoc().myFileOrphans, Doc, null), "data", doc)); - return this.addDocument(doc); - }; + const addDocument = (doc: Doc | Doc[]) => this.addDocument(doc); if (html) { if (FormattedTextBox.IsFragment(html)) { diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index f305174f1..a217de193 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -153,12 +153,10 @@ export class CollectionView extends Touchable { const hasContextAnchor = DocListCast(doc.links).some(l => (l.anchor2 === doc && Cast(l.anchor1, Doc, null)?.annotationOn === context) || (l.anchor1 === doc && Cast(l.anchor2, 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", label: "", + title: "pushpin", label: "", annotationOn: Cast(doc.annotationOn, Doc, null), isPushpin: true, icon: "map-pin", x: Cast(doc.x, "number", null), y: Cast(doc.y, "number", null), _backgroundColor: "#0000003d", color: "#ACCEF7", _width: 15, _height: 15, _xPadding: 0, isLinkButton: true, _timecodeToShow: Cast(doc._timecodeToShow, "number", null) }); - pushpin.isPushpin = true; - Doc.GetProto(pushpin).annotationOn = doc.annotationOn; Doc.SetInPlace(doc, "annotationOn", undefined, true); Doc.AddDocToList(context, Doc.LayoutFieldKey(context) + "-annotations", pushpin); const pushpinLink = DocUtils.MakeLink({ doc: pushpin }, { doc: doc }, "pushpin", ""); @@ -191,6 +189,7 @@ export class CollectionView extends Touchable { const ind = (targetDataDoc[this.props.fieldKey] as List).indexOf(doc); if (ind !== -1) { Doc.RemoveDocFromList(targetDataDoc, this.props.fieldKey, doc); + doc.context = undefined; recent && Doc.AddDocToList(recent, "data", doc, undefined, true, true); } }); diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index ac19a3591..0ffc2df25 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -101,13 +101,13 @@ export class TreeView extends React.Component { @observable _dref: DocumentView | undefined | null; get displayName() { return "TreeView(" + this.props.document.title + ")"; } // this makes mobx trace() statements more descriptive get treeViewLockExpandedView() { return this.doc.treeViewLockExpandedView; } - get defaultExpandedView() { return StrCast(this.doc.treeViewDefaultExpandedView, this.fileSysMode ? "data" : Doc.UserDoc().noviceMode || this.outlineMode ? "layout" : "fields"); } + get defaultExpandedView() { return StrCast(this.doc.treeViewDefaultExpandedView, this.fileSysMode ? (this.doc.isFolder ? "data" : "layout") : Doc.UserDoc().noviceMode || this.outlineMode ? "layout" : "fields"); } get treeViewDefaultExpandedView() { return this.treeViewLockExpandedView ? this.defaultExpandedView : (this.childDocs && !this.fileSysMode ? this.fieldKey : this.defaultExpandedView); } @computed get doc() { TraceMobx(); return this.props.document; } @computed get outlineMode() { return this.props.treeView.doc.treeViewType === "outline"; } @computed get fileSysMode() { return this.props.treeView.doc.treeViewType === "fileSystem"; } - @computed get treeViewOpen() { return (!this.props.treeViewPreventOpen && !this.doc.treeViewPreventOpen && BoolCast(this.doc.treeViewOpen)) || this._overrideTreeViewOpen; } + @computed get treeViewOpen() { return (!this.props.treeViewPreventOpen && !this.doc.treeViewPreventOpen && Doc.GetT(this.doc, "treeViewOpen", "boolean", true)) || this._overrideTreeViewOpen; } @computed get treeViewExpandedView() { return StrCast(this.doc.treeViewExpandedView, this.treeViewDefaultExpandedView); } @computed get MAX_EMBED_HEIGHT() { return NumCast(this.props.containingCollection.maxEmbedHeight, 200); } @computed get dataDoc() { return this.doc[DataSym]; } @@ -123,7 +123,7 @@ export class TreeView extends React.Component { const layout = Doc.LayoutField(this.doc) instanceof Doc ? Doc.LayoutField(this.doc) as Doc : undefined; return ((this.props.dataDoc ? DocListCastOrNull(this.props.dataDoc[field]) : undefined) || // if there's a data doc for an expanded template, use it's data field (layout ? DocListCastOrNull(layout[field]) : undefined) || // else if there's a layout doc, display it's fields - DocListCastOrNull(this.doc[field])); // otherwise use the document's data field + DocListCastOrNull(this.doc[field]))?.filter(doc => !this.fileSysMode || field !== "aliases" || Doc.GetT(doc, "context", Doc, true)); // otherwise use the document's data field } @undoBatch move = (doc: Doc | Doc[], target: Doc | undefined, addDoc: (doc: Doc | Doc[]) => boolean) => { return this.doc !== target && this.props.removeDoc?.(doc) === true && addDoc(doc); @@ -477,8 +477,8 @@ export class TreeView extends React.Component { { if (this.fileSysMode) { - this.doc.treeViewExpandedView = this.doc.isFolder ? this.fieldKey : this.treeViewExpandedView === "layout" ? "fields" : - this.treeViewExpandedView === "fields" ? "aliases" : "layout"; + this.doc.treeViewExpandedView = this.doc.isFolder ? this.fieldKey : this.treeViewExpandedView === "layout" ? "aliases" : + this.treeViewExpandedView === "aliases" && !Doc.UserDoc().noviceMode ? "fields" : "layout"; } else if (this.treeViewOpen) { this.doc.treeViewExpandedView = this.treeViewLockExpandedView ? this.doc.treeViewExpandedView : this.treeViewExpandedView === this.fieldKey ? (Doc.UserDoc().noviceMode || this.outlineMode ? "layout" : "fields") : @@ -495,7 +495,11 @@ export class TreeView extends React.Component { } showContextMenu = (e: React.MouseEvent) => simulateMouseClick(this._docRef?.ContentDiv, e.clientX, e.clientY + 30, e.screenX, e.screenY + 30); - contextMenuItems = () => this.doc.isFolder ? [{ script: ScriptField.MakeFunction(`scriptContext.makeFolder()`, { scriptContext: "any" })!, label: "New Folder" }] : Doc.IsSystem(this.doc) ? [] : [{ script: ScriptField.MakeFunction(`openOnRight(self)`)!, label: "Open" }, { script: ScriptField.MakeFunction(`DocFocus(self)`)!, label: "Focus" }]; + contextMenuItems = () => this.doc.isFolder ? + [{ script: ScriptField.MakeFunction(`scriptContext.makeFolder()`, { scriptContext: "any" })!, label: "New Folder" }] : Doc.IsSystem(this.doc) ? [] : + this.fileSysMode && this.doc === Doc.GetProto(this.doc) ? + [{ script: ScriptField.MakeFunction(`openOnRight(getAlias(self))`)!, label: "Open Alias" }] : + [{ script: ScriptField.MakeFunction(`DocFocusOrOpen(self)`)!, label: "Focus or Open" }]; truncateTitleWidth = () => NumCast(this.props.treeView.props.Document.treeViewTruncateTitleWidth, this.props.panelWidth()); onChildClick = () => this.props.onChildClick?.() ?? (this._editTitleScript?.() || ScriptCast(this.doc.treeChildClick)); onChildDoubleClick = () => (!this.outlineMode && this._openScript?.()) || ScriptCast(this.doc.treeChildDoubleClick); diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 9e442a8c8..34ddf6ed2 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -167,7 +167,7 @@ export class MarqueeView extends React.Component Date: Thu, 25 Feb 2021 19:16:36 -0500 Subject: prevent annotation notes on PDFS from showing up in file system view. --- src/client/util/DragManager.ts | 4 ++-- src/client/views/MarqueeAnnotator.tsx | 4 ++-- src/client/views/collections/CollectionSubView.tsx | 2 +- src/client/views/nodes/formattedText/FormattedTextBox.tsx | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 0a3928ff8..9baefd247 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -155,7 +155,7 @@ export namespace DragManager { // used by PDFs,Text,Image,Video,Web to conditionally (if the drop completes) create a text annotation when dragging the annotate button from the AnchorMenu when a text/region selection has been made. // this is pretty clunky and should be rethought out using linkDrag or DocumentDrag export class AnchorAnnoDragData { - constructor(dragDoc: Doc, annotationDocCreator: () => Doc, dropDocCreator: () => Doc) { + constructor(dragDoc: Doc, annotationDocCreator: () => Doc, dropDocCreator: (annotationOn?: Doc) => Doc) { this.dragDocument = dragDoc; this.dropDocCreator = dropDocCreator; this.annotationDocCreator = annotationDocCreator; @@ -164,7 +164,7 @@ export namespace DragManager { targetContext: Doc | undefined; dragDocument: Doc; annotationDocCreator: () => Doc; - dropDocCreator: () => Doc; + dropDocCreator: (asAnnotation?: Doc) => Doc; dropDocument?: Doc; annotationDocument?: Doc; offset: number[]; diff --git a/src/client/views/MarqueeAnnotator.tsx b/src/client/views/MarqueeAnnotator.tsx index 6e8f9a2df..1fb87f522 100644 --- a/src/client/views/MarqueeAnnotator.tsx +++ b/src/client/views/MarqueeAnnotator.tsx @@ -67,8 +67,8 @@ export class MarqueeAnnotator extends React.Component { AnchorMenu.Instance.StartDrag = action(async (e: PointerEvent, ele: HTMLElement) => { e.preventDefault(); e.stopPropagation(); - const targetCreator = () => { - const target = CurrentUserUtils.GetNewTextDoc("Note linked to " + this.props.rootDoc.title, 0, 0, 100, 100); + const targetCreator = (asAnnotation?: Doc) => { + const target = CurrentUserUtils.GetNewTextDoc("Note linked to " + this.props.rootDoc.title, 0, 0, 100, 100, undefined, asAnnotation); FormattedTextBox.SelectOnLoad = target[Id]; return target; }; diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index d5fa81024..b0c665aa8 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -227,7 +227,7 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T, moreProps?: else if (de.complete.annoDragData && (!this.props.isAnnotationOverlay || de.complete.annoDragData.dragDocument === this.props.Document)) { e.stopPropagation(); de.complete.annoDragData.annotationDocument = de.complete.annoDragData.annotationDocCreator(); - de.complete.annoDragData.dropDocument = de.complete.annoDragData.dropDocCreator(); + de.complete.annoDragData.dropDocument = de.complete.annoDragData.dropDocCreator(this.props.isAnnotationOverlay ? this.props.Document : undefined); return de.complete.annoDragData.dropDocument && this.addDocument(de.complete.annoDragData.dropDocument); } return false; diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index b4fbda9f4..f4105f313 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -231,8 +231,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp AnchorMenu.Instance.StartDrag = action(async (e: PointerEvent, ele: HTMLElement) => { e.preventDefault(); e.stopPropagation(); - const targetCreator = () => { - const target = CurrentUserUtils.GetNewTextDoc("Note linked to " + this.rootDoc.title, 0, 0, 100, 100); + const targetCreator = (annotationOn?: Doc) => { + const target = CurrentUserUtils.GetNewTextDoc("Note linked to " + this.rootDoc.title, 0, 0, 100, 100, undefined, annotationOn); FormattedTextBox.SelectOnLoad = target[Id]; return target; }; -- cgit v1.2.3-70-g09d2 From f6ed4c2eb2600282d2f9a31433c5fc24d2928fab Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 25 Feb 2021 19:19:00 -0500 Subject: add all aliases to file sys view (don't filter out those without contexts) --- src/client/views/collections/TreeView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index 0ffc2df25..513ef4015 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -123,7 +123,7 @@ export class TreeView extends React.Component { const layout = Doc.LayoutField(this.doc) instanceof Doc ? Doc.LayoutField(this.doc) as Doc : undefined; return ((this.props.dataDoc ? DocListCastOrNull(this.props.dataDoc[field]) : undefined) || // if there's a data doc for an expanded template, use it's data field (layout ? DocListCastOrNull(layout[field]) : undefined) || // else if there's a layout doc, display it's fields - DocListCastOrNull(this.doc[field]))?.filter(doc => !this.fileSysMode || field !== "aliases" || Doc.GetT(doc, "context", Doc, true)); // otherwise use the document's data field + DocListCastOrNull(this.doc[field]))?.filter(doc => !this.fileSysMode || field !== "aliases");// || Doc.GetT(doc, "context", Doc, true)); // otherwise use the document's data field } @undoBatch move = (doc: Doc | Doc[], target: Doc | undefined, addDoc: (doc: Doc | Doc[]) => boolean) => { return this.doc !== target && this.props.removeDoc?.(doc) === true && addDoc(doc); -- cgit v1.2.3-70-g09d2 From feac7f17533c4b587cadc783fbd5f47c464d40db Mon Sep 17 00:00:00 2001 From: bobzel Date: Fri, 26 Feb 2021 02:24:32 -0500 Subject: updated fieldInfos a bit more. --- src/client/documents/Documents.ts | 301 +++++++--------------------- src/client/util/CurrentUserUtils.ts | 3 +- src/client/views/LightboxView.tsx | 2 +- src/client/views/collections/TabDocView.tsx | 3 +- src/client/views/collections/TreeView.tsx | 2 +- 5 files changed, 77 insertions(+), 234 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index b5b179d3a..de08040e2 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -25,6 +25,7 @@ import { DirectoryImportBox } from "../util/Import & Export/DirectoryImportBox"; import { LinkManager } from "../util/LinkManager"; import { Scripting } from "../util/Scripting"; import { undoBatch, UndoManager } from "../util/UndoManager"; +import { DimUnit } from "../views/collections/collectionMulticolumn/CollectionMulticolumnView"; import { CollectionDockingView } from "../views/collections/CollectionDockingView"; import { CollectionView, CollectionViewType } from "../views/collections/CollectionView"; import { ContextMenu } from "../views/ContextMenu"; @@ -59,205 +60,56 @@ import { DocumentType } from "./DocumentTypes"; const path = require('path'); const defaultNativeImageDim = Number(DFLT_IMAGE_NATIVE_DIM.replace("px", "")); -interface dinfo { - description: string; - type: string; - dflt?: any; +class EmptyBox { + public static LayoutString() { + return ""; + } } -export interface DocumentOptions { - system?: boolean | dinfo; - _autoHeight?: boolean | dinfo; - _headerHeight?: number | dinfo; // height of header of custom notes - _headerFontSize?: number | dinfo; // font size of header of custom notes - _headerPointerEvents?: string | dinfo; // types of events the header of a custom text document can consume - _panX?: number | dinfo; - _panY?: number | dinfo; - _width?: number | dinfo; - _height?: number | dinfo; - _nativeWidth?: number | dinfo; - _nativeHeight?: number | dinfo; - _dimMagnitude?: number | dinfo; // magnitude of collectionMulti{row,col} view element - _dimUnit?: string | dinfo; // "px" or "*" (default = "*") - _fitWidth?: boolean | dinfo; - _fitToBox?: boolean; // whether a freeformview should zoom/scale to create a shrinkwrapped view of its contents - _freeformLOD?: boolean; // whether to use LOD to render a freeform document - _showTitle?: string; // field name to display in header (:hover is an optional suffix) - _showCaption?: string; // which field to display in the caption area. leave empty to have no caption - _scrollTop?: number; // scroll location for pdfs - _noAutoscroll?: boolean;// whether collections autoscroll when this item is dragged - _chromeStatus?: string; - _searchDoc?: boolean; // is this a search document (used to change UI for search results in schema view) - _viewType?: string; // sub type of a collection - _gridGap?: number; // gap between items in masonry view - _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) - "_carousel-caption-xMargin"?: number; - "_carousel-caption-yMargin"?: number; - x?: number; - y?: number; - z?: number; - author?: string; - _hideContextMenu?: boolean; // whether the context menu can be shown - dropAction?: dropActionType; - childDropAction?: dropActionType; - targetDropAction?: dropActionType; - layoutKey?: string; +abstract class FInfo { + description: string = ""; type?: string; - title?: string; - version?: string; // version identifier for a document - label?: string; - hidden?: boolean; - userDoc?: Doc; // the userDocument - toolTip?: string; // tooltip to display on hover - style?: string; - page?: number; - 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 - _viewScale?: number; - _overflow?: string; - forceActive?: boolean; - 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 colleciton children. 0 - means height can be no bigger than width - childLayoutTemplate?: Doc; // template for collection to use to render its children (see PresBox or Buxton layout in tree view) - childLayoutString?: string; // template string for collection to use to render its children - hideLinkButton?: boolean; // whether the blue link counter button should be hidden - hideAllLinks?: boolean; // whether all individual blue anchor dots should be hidden - _columnsHideIfEmpty?: boolean; // whether stacking view column headings should be hidden - isTemplateForField?: string; // the field key for which the containing document is a rendering template - isTemplateDoc?: boolean; - watchedDocuments?: Doc; // list of documents to "watch" in an icon doc to display a badge - targetScriptKey?: string; // where to write a template script (used by collections with click templates which need to target onClick, onDoubleClick, etc) - templates?: List; - hero?: ImageField; // primary image that best represents a compound document (e.g., for a buxton device document that has multiple images) - backgroundColor?: string | ScriptField; // background color for data doc - _backgroundColor?: string | ScriptField; // background color for each template layout doc ( overrides backgroundColor ) - color?: string; // foreground color data doc - _color?: string; // foreground color for each template layout doc (overrides color) - _clipWidth?: number; // percent transition from before to after in comparisonBox - caption?: RichTextField; - ignoreClick?: boolean; - 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 - isAnnotating?: boolean; // whether we web document is annotation mode where links can't be clicked to allow annotations to be created - opacity?: number; - defaultBackgroundColor?: string; - _layers?: List; - _raiseWhenDragged?: boolean; // whether a document is brought to front when dragged. - isLinkButton?: boolean; - isFolder?: boolean; - _columnWidth?: number; - _fontSize?: string; - _fontWeight?: number; - _fontFamily?: string; - _curPage?: number; - _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 - 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 - appearFrame?: number; // the frame in which the document appears - presTransition?: number; //the time taken for the transition TO a document - presDuration?: number; //the duration of the slide in presentation view - presProgressivize?: boolean; - borderRounding?: string; - boxShadow?: string; - dontRegisterChildViews?: boolean; - 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. - "onDoubleClick-rawScript"?: string; // onDoubleClick script in raw text form - "onChildDoubleClick-rawScript"?: string; // onChildDoubleClick script in raw text form - "onChildClick-rawScript"?: string; // on ChildClick script in raw text form - "onClick-rawScript"?: string; // onClick script in raw text form - "onCheckedClick-rawScript"?: string; // onChecked script in raw text form - "onCheckedClick-params"?: List; // parameter list for onChecked treeview functions - _pivotField?: string; // field key used to determine headings for sections in stacking, masonry, pivot views - _columnHeaders?: List; // headers for stacking views - _schemaHeaders?: List; // headers for schema view - dockingConfig?: string; - annotationOn?: Doc; - isPushpin?: boolean; - 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 - dbDoc?: Doc; - iconShape?: string; // shapes of the fonticon border - linkRelationship?: string; // type of relatinoship a link represents - ischecked?: ScriptField; // returns whether a font icon box is checked - activeInkPen?: Doc; // which pen document is currently active (used as the radio button state for the 'unhecked' pen tool scripts) - onClick?: ScriptField; - onDoubleClick?: ScriptField; - onChildClick?: ScriptField; // script given to children of a collection to execute when they are clicked - onChildDoubleClick?: ScriptField; // script given to children of a collection to execute when they are double clicked - onPointerDown?: ScriptField; - onPointerUp?: ScriptField; - dropConverter?: ScriptField; // script to run when documents are dropped on this Document. - dragFactory?: Doc; // document to create when dragging with a suitable onDragStart script - clickFactory?: Doc; // document to create when clicking on a button with a suitable onClick script - 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 - clipboard?: Doc; - 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; - cloneFieldFilter?: List; // fields not to copy when the document is cloned - _stayInCollection?: boolean;// whether the document should remain in its collection when someone tries to drag and drop it elsewhere - freezeChildren?: string; // whether children are now allowed to be added and or removed from a collection - treeViewPreventOpen?: boolean; // ignores the treeViewOpen Doc flag which allows a treeViewItem's expand/collapse state to be independent of other views of the same document in the tree view - treeViewHideTitle?: boolean; // whether to hide the top document title of a tree view - treeViewHideHeader?: boolean; // whether to hide the header for a document in a tree view - treeViewHideHeaderFields?: boolean; // whether to hide the drop down options for tree view items. - treeViewOpen?: boolean; // whether this document is expanded in a tree view - treeViewExpandedView?: string; // which field/thing is displayed when this item is opened in tree view - treeViewChecked?: ScriptField; // script to call when a tree view checkbox is checked - treeViewTruncateTitleWidth?: number; - treeViewType?: string; // whether treeview is a Slide, file system, or (default) collection hierarchy - treeViewLockExpandedView?: boolean; // whether the expanded view can be changed - treeViewDefaultExpandedView?: string; // default expanded view - sidebarColor?: string; // background color of text sidebar - sidebarViewType?: string; // collection type of text sidebar - limitHeight?: number; // maximum height for newly created (eg, from pasting) text documents - // [key: string]: Opt; - pointerHack?: boolean; // for buttons, allows onClick handler to fire onPointerDown - textTransform?: string; // is linear view expanded - letterSpacing?: string; // is linear view expanded - flexDirection?: "unset" | "row" | "column" | "row-reverse" | "column-reverse"; - selectedIndex?: number; - syntaxColor?: string; // can be applied to text for syntax highlighting all matches in the text - searchQuery?: string; // for quersyBox - linearViewIsExpanded?: boolean; // is linear view expanded - isLabel?: boolean; // whether the document is a label or not (video / audio) - useLinkSmallAnchor?: boolean; // whether links to this document should use a miniature linkAnchorBox - border?: string; //for searchbox - _hovercolor?: string; + values?: Field[]; + layoutField?: boolean; // is this field a layout (or datadoc) field + // format?: string; // format to display values (e.g, decimal places, $, etc) + // parse?: ScriptField; // parse a value from a string + constructor(d: string, l: boolean = false) { this.description = d; this.layoutField = l; } } - -let _docOptions: DocumentOptions = { - system: { type: "string", description: "is document created/owned by the system", dflt: false }, - _autoHeight: { type: "boolean", description: "whether document automatically resizes vertically to display contents", dflt: false }, - _headerHeight: { type: "number", description: "height of document header used for displaying title", dflt: 20 }, - _headerFontSize: { type: "number", description: "font size of header of custom notes", dflt: 12 }, - _headerPointerEvents: { type: "string", description: "types of events the header of a custom text document can consume" }, - _panX: { type: "number", description: "horizontal pan location of a freeform view" }, - _panY: { type: "number", description: "vertical pan location of a freeform view" }, - _width: { type: "number", description: "displayed width of a document" }, - _height: { type: "number", description: "displayed height of document" }, - _nativeWidth: { type: "number", description: "native width of document contents (e.g., the pixel width of an image)" }, - _nativeHeight: { type: "number", description: "native height of document contents (e.g., the pixel height of an image)" }, - _dimMagnitude: { type: "number", description: "magnitude of collectionMulti{row,col} element's width or height" }, - _dimUnit: { type: "string", description: "units of collectionMulti{row,col} element's width or height - 'px' or '*' for pixels or relative units" }, - _fitWidth: { type: "boolean", description: "whether document should scale its contents to fit its rendered width or not (e.g., for PDFviews)" } - -} -/*_fitToBox?: boolean; // whether a freeformview should zoom/scale to create a shrinkwrapped view of its contents +class BoolInfo extends FInfo { type?= "boolean"; values?: boolean[] = [true, false]; } +class NumInfo extends FInfo { type?= "number"; values?: number[] = []; } +class StrInfo extends FInfo { type?= "string"; values?: string[] = []; } +class DocInfo extends FInfo { type?= "Doc"; values?: Doc[] = []; } +class DimInfo extends FInfo { type?= "DimUnit"; values?= [DimUnit.Pixel, DimUnit.Ratio]; } +class PEInfo extends FInfo { type?= "pointerEvents"; values?= ["all", "none"]; } +class DAInfo extends FInfo { type?= "dropActionType"; values?= ["alias", "copy", "move", "same", "proto", "none"]; } +type BOOLt = BoolInfo | boolean; +type NUMt = NumInfo | number; +type STRt = StrInfo | string; +type DOCt = DocInfo | Doc; +type DIMt = DimInfo | typeof DimUnit.Pixel | typeof DimUnit.Ratio; +type PEVt = PEInfo | "none" | "all"; +type DROPt = DAInfo | dropActionType; +export class DocumentOptions { + system?: BOOLt = new BoolInfo("is this a system created/owned doc"); + userDoc?: DOCt = new DocInfo("the user doc"); + dropAction?: DROPt = new DAInfo("what should happen to the source document when it's dropped onto this doc "); + childDropAction?: DROPt = new DAInfo("what should happen to the source document when it's dropped onto a child of a collection "); + targetDropAction?: DROPt = new DAInfo("what should happen to the source document when ??? "); + backgroundColor?: STRt = new StrInfo("background color for data doc"); + _backgroundColor?: STRt = new StrInfo("background color for each template layout doc (overrides backgroundColor)", true); + _autoHeight?: BOOLt = new BoolInfo("whether document automatically resizes vertically to display contents", true); + _headerHeight?: NUMt = new NumInfo("height of document header used for displaying title", true); + _headerFontSize?: NUMt = new NumInfo("font size of header of custom notes", true); + _headerPointerEvents?: PEVt = new PEInfo("types of events the header of a custom text document can consume", true); + _panX?: NUMt = new NumInfo("horizontal pan location of a freeform view", true); + _panY?: NUMt = new NumInfo("vertical pan location of a freeform view", true); + _width?: NUMt = new NumInfo("displayed width of a document", true); + _height?: NUMt = new NumInfo("displayed height of document", true); + _nativeWidth?: NUMt = new NumInfo("native width of document contents (e.g., the pixel width of an image)", true); + _nativeHeight?: NUMt = new NumInfo("native height of document contents (e.g., the pixel height of an image)", true); + _dimMagnitude?: NUMt = new NumInfo("magnitude of collectionMulti{row,col} element's width or height", true); + _dimUnit?: DIMt = new DimInfo("units of collectionMulti{row,col} element's width or height - 'px' or '*' for pixels or relative units", true); + _fitWidth?: BOOLt = new BoolInfo("whether document should scale its contents to fit its rendered width or not (e.g., for PDFviews)", true); + _fitToBox?: boolean; // whether a freeformview should zoom/scale to create a shrinkwrapped view of its contents _freeformLOD?: boolean; // whether to use LOD to render a freeform document _showTitle?: string; // field name to display in header (:hover is an optional suffix) _showCaption?: string; // which field to display in the caption area. leave empty to have no caption @@ -281,16 +133,12 @@ let _docOptions: DocumentOptions = { z?: number; author?: string; _hideContextMenu?: boolean; // whether the context menu can be shown - dropAction?: dropActionType; - childDropAction?: dropActionType; - targetDropAction?: dropActionType; layoutKey?: string; type?: string; title?: string; version?: string; // version identifier for a document label?: string; hidden?: boolean; - userDoc?: Doc; // the userDocument toolTip?: string; // tooltip to display on hover style?: string; page?: number; @@ -313,8 +161,6 @@ let _docOptions: DocumentOptions = { targetScriptKey?: string; // where to write a template script (used by collections with click templates which need to target onClick, onDoubleClick, etc) templates?: List; hero?: ImageField; // primary image that best represents a compound document (e.g., for a buxton device document that has multiple images) - backgroundColor?: string | ScriptField; // background color for data doc - _backgroundColor?: string | ScriptField; // background color for each template layout doc ( overrides backgroundColor ) color?: string; // foreground color data doc _color?: string; // foreground color for each template layout doc (overrides color) _clipWidth?: number; // percent transition from before to after in comparisonBox @@ -416,37 +262,34 @@ let _docOptions: DocumentOptions = { useLinkSmallAnchor?: boolean; // whether links to this document should use a miniature linkAnchorBox border?: string; //for searchbox _hovercolor?: string; -}*/ - -class EmptyBox { - public static LayoutString() { - return ""; - } } - export namespace Docs { - export let FieldInfos: Doc | undefined; + const _docOptions = new DocumentOptions(); + export async function setupFieldInfos() { - const fieldDocs = await DocServer.GetRefField("FieldInfos"); - if (fieldDocs instanceof Doc) { - Docs.FieldInfos = fieldDocs; - } else { + return await DocServer.GetRefField("FieldInfos7") as Doc ?? runInAction(() => { - const infos = Docs.FieldInfos = new Doc("FieldInfos", true); - const keys = Object.keys(_docOptions); - for (let i = 0; i < keys.length; i++) { - const key = keys[i]; - const options = (_docOptions as any)[key] as dinfo; + const infos = new Doc("FieldInfos7", true); + const keys = Object.keys(new DocumentOptions()); + for (const key of keys) { + const options = (_docOptions as any)[key] as FInfo; const finfo = new Doc(); finfo.name = key; - finfo.default = options.dflt; + switch (options.type) { + case "boolean": finfo.options = new List(options.values as any as boolean[]); break; + case "number": finfo.options = new List(options.values as any as number[]); break; + case "Doc": finfo.options = new List(options.values as any as Doc[]); break; + default: // string, pointerEvents, dimUnit, dropActionType + finfo.options = new List(options.values as any as string[]); break; + } + finfo.layoutField = options.layoutField; finfo.description = options.description; finfo.type = options.type; infos[key] = finfo; } + return infos; }); - } } export let newAccount: boolean = false; @@ -682,7 +525,7 @@ export namespace Docs { // whatever options pertain to this specific prototype const options = { title, type, baseProto: true, ...defaultOptions, ...(template.options || {}) }; options.layout = layout.view?.LayoutString(layout.dataField); - const doc = Doc.assign(new Doc(prototypeId, true), { system: true, layoutKey: "layout", ...options }); + const doc = Doc.assign(new Doc(prototypeId, true), { system: true, layoutKey: "layout", ...options } as any); doc.data = template.data; doc.layout_keyValue = KeyValueBox.LayoutString(""); return doc; @@ -847,7 +690,7 @@ export namespace Docs { if (value !== undefined) { deleg[fieldKey] = value; } - return Doc.assign(deleg, options); + return Doc.assign(deleg, options as any); } export function ImageDocument(url: string, options: DocumentOptions = {}) { @@ -964,8 +807,8 @@ export namespace Docs { I.x = options.x; I.y = options.y; I._backgroundColor = "transparent"; - I._width = options._width; - I._height = options._height; + I._width = options._width as number; + I._height = options._height as number; I._fontFamily = "cursive"; I.author = Doc.CurrentUserEmail; I.rotation = 0; @@ -1337,7 +1180,7 @@ export namespace DocUtils { if (type.indexOf("video") !== -1) { ctor = Docs.Create.VideoDocument; if (!options._width) options._width = 600; - if (!options._height) options._height = options._width * 2 / 3; + if (!options._height) options._height = (options._width as number) * 2 / 3; } if (type.indexOf("audio") !== -1) { ctor = Docs.Create.AudioDocument; @@ -1345,7 +1188,7 @@ export namespace DocUtils { if (type.indexOf("pdf") !== -1) { ctor = Docs.Create.PdfDocument; if (!options._width) options._width = 400; - if (!options._height) options._height = options._width * 1200 / 927; + if (!options._height) options._height = (options._width as number) * 1200 / 927; } if (type.indexOf("html") !== -1) { if (path.includes(window.location.hostname)) { @@ -1356,8 +1199,8 @@ export namespace DocUtils { const alias = Doc.MakeAlias(field); alias.x = options.x || 0; alias.y = options.y || 0; - alias._width = options._width || 300; - alias._height = options._height || options._width || 300; + alias._width = (options._width as number) || 300; + alias._height = (options._height as number) || (options._width as number) || 300; return alias; } return undefined; diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index dcaf61fea..9a38c56e7 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -1050,7 +1050,7 @@ export class CurrentUserUtils { // } // }); setTimeout(() => DocServer.UPDATE_SERVER_CACHE(), 2500); - doc.fieldInfos = Docs.FieldInfos; + doc.fieldInfos = await Docs.setupFieldInfos(); return doc; } @@ -1070,7 +1070,6 @@ export class CurrentUserUtils { } public static async loadUserDocument(id: string) { - await Docs.setupFieldInfos(); this.curr_id = id; await rp.get(Utils.prepend("/getUserDocumentIds")).then(ids => { const { userDocumentId, sharingDocumentId, linkDatabaseId } = JSON.parse(ids); diff --git a/src/client/views/LightboxView.tsx b/src/client/views/LightboxView.tsx index e1fbea76e..15b98467c 100644 --- a/src/client/views/LightboxView.tsx +++ b/src/client/views/LightboxView.tsx @@ -276,6 +276,6 @@ export class LightboxTourBtn extends React.Component { this.props.stepInto(); }, StrCast(this.props.tourMap()?.lastElement()?.TourMap) - ) + ); } } \ No newline at end of file diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx index 3f8794665..68ca93f43 100644 --- a/src/client/views/collections/TabDocView.tsx +++ b/src/client/views/collections/TabDocView.tsx @@ -382,7 +382,8 @@ export class TabMinimapView extends React.Component { } } @computed get renderBounds() { - const bounds = this.props.tabView()?.ComponentView?.freeformData?.(true)?.bounds; + const compView = this.props.tabView()?.ComponentView as CollectionFreeFormView; + const bounds = compView?.freeformData?.(true)?.bounds; if (!bounds) return undefined; const xbounds = bounds.r - bounds.x; const ybounds = bounds.b - bounds.y; diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index 513ef4015..6975c24d1 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -499,7 +499,7 @@ export class TreeView extends React.Component { [{ script: ScriptField.MakeFunction(`scriptContext.makeFolder()`, { scriptContext: "any" })!, label: "New Folder" }] : Doc.IsSystem(this.doc) ? [] : this.fileSysMode && this.doc === Doc.GetProto(this.doc) ? [{ script: ScriptField.MakeFunction(`openOnRight(getAlias(self))`)!, label: "Open Alias" }] : - [{ script: ScriptField.MakeFunction(`DocFocusOrOpen(self)`)!, label: "Focus or Open" }]; + [{ script: ScriptField.MakeFunction(`DocFocusOrOpen(self)`)!, label: "Focus or Open" }] truncateTitleWidth = () => NumCast(this.props.treeView.props.Document.treeViewTruncateTitleWidth, this.props.panelWidth()); onChildClick = () => this.props.onChildClick?.() ?? (this._editTitleScript?.() || ScriptCast(this.doc.treeChildClick)); onChildDoubleClick = () => (!this.outlineMode && this._openScript?.()) || ScriptCast(this.doc.treeChildDoubleClick); -- cgit v1.2.3-70-g09d2 From daa1e3ddf585f5fe237c100504130a3eae204252 Mon Sep 17 00:00:00 2001 From: bobzel Date: Fri, 26 Feb 2021 15:12:28 -0500 Subject: fixed serialization error handling to not kill Dash - bad list items prevented tabs from being created. cleaned up document fields a little more - switched layers to _layerTags, got rid of a couple unused fields. --- src/client/documents/Documents.ts | 51 ++++++++++------------ src/client/util/CurrentUserUtils.ts | 49 ++++++++++----------- src/client/util/SerializationHelper.ts | 10 +++-- src/client/views/MainView.tsx | 6 +-- src/client/views/PropertiesButtons.tsx | 8 ++-- src/client/views/StyleProvider.tsx | 12 ++--- .../collectionFreeForm/CollectionFreeFormView.tsx | 10 ++--- .../collections/collectionFreeForm/MarqueeView.tsx | 2 +- .../collectionGrid/CollectionGridView.tsx | 2 +- src/client/views/nodes/DocumentLinksButton.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 12 ++--- src/client/views/nodes/LinkAnchorBox.tsx | 2 +- src/fields/documentSchemas.ts | 3 +- src/fields/util.ts | 1 - src/server/database.ts | 4 +- src/server/websocket.ts | 6 ++- 16 files changed, 91 insertions(+), 89 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index d8a77bfdb..7a32596b0 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -109,15 +109,26 @@ export class DocumentOptions { _dimUnit?: DIMt = new DimInfo("units of collectionMulti{row,col} element's width or height - 'px' or '*' for pixels or relative units", true); _fitWidth?: BOOLt = new BoolInfo("whether document should scale its contents to fit its rendered width or not (e.g., for PDFviews)", true); _fitToBox?: boolean; // whether a freeformview should zoom/scale to create a shrinkwrapped view of its contents + color?: string; // foreground color data doc + _color?: string; // foreground color for each template layout doc (overrides color) + _clipWidth?: number; // percent transition from before to after in comparisonBox + _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 _freeformLOD?: boolean; // whether to use LOD to render a freeform document _showTitle?: string; // field name to display in header (:hover is an optional suffix) _showCaption?: string; // which field to display in the caption area. leave empty to have no caption _scrollTop?: number; // scroll location for pdfs _noAutoscroll?: boolean;// whether collections autoscroll when this item is dragged _chromeStatus?: string; + _layerTags?: List; // layer tags a document has (used for tab filtering "layers" in document tab) _searchDoc?: boolean; // is this a search document (used to change UI for search results in schema view) + _stayInCollection?: boolean;// whether the document should remain in its collection when someone tries to drag and drop it elsewhere + _raiseWhenDragged?: boolean; // whether a document is brought to front when dragged. + _hideContextMenu?: boolean; // whether the context menu can be shown _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) + _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; @@ -125,13 +136,23 @@ export class DocumentOptions { _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) + _columnWidth?: number; + _columnsHideIfEmpty?: boolean; // whether stacking view column headings should be hidden + _fontSize?: string; + _fontWeight?: number; + _fontFamily?: string; + _curPage?: number; + _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"?: number; "_carousel-caption-yMargin"?: number; x?: number; y?: number; z?: number; author?: string; - _hideContextMenu?: boolean; // whether the context menu can be shown layoutKey?: string; type?: string; title?: string; @@ -141,8 +162,6 @@ export class DocumentOptions { toolTip?: string; // tooltip to display on hover 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 - _viewScale?: number; - _overflow?: string; forceActive?: boolean; 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 @@ -151,37 +170,19 @@ export class DocumentOptions { childLayoutString?: string; // template string for collection to use to render its children hideLinkButton?: boolean; // whether the blue link counter button should be hidden hideAllLinks?: boolean; // whether all individual blue anchor dots should be hidden - _columnsHideIfEmpty?: boolean; // whether stacking view column headings should be hidden isTemplateForField?: string; // the field key for which the containing document is a rendering template isTemplateDoc?: boolean; watchedDocuments?: Doc; // list of documents to "watch" in an icon doc to display a badge targetScriptKey?: string; // where to write a template script (used by collections with click templates which need to target onClick, onDoubleClick, etc) templates?: List; hero?: ImageField; // primary image that best represents a compound document (e.g., for a buxton device document that has multiple images) - color?: string; // foreground color data doc - _color?: string; // foreground color for each template layout doc (overrides color) - _clipWidth?: number; // percent transition from before to after in comparisonBox caption?: RichTextField; ignoreClick?: boolean; - 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 isAnnotating?: boolean; // whether we web document is annotation mode where links can't be clicked to allow annotations to be created opacity?: number; defaultBackgroundColor?: string; - _layers?: List; - _raiseWhenDragged?: boolean; // whether a document is brought to front when dragged. isLinkButton?: boolean; isFolder?: boolean; - _columnWidth?: number; - _fontSize?: string; - _fontWeight?: number; - _fontFamily?: string; - _curPage?: number; - _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 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 appearFrame?: number; // the frame in which the document appears @@ -230,7 +231,6 @@ export class DocumentOptions { searchFileTypes?: List; // file types allowed in a search query strokeWidth?: number; cloneFieldFilter?: List; // fields not to copy when the document is cloned - _stayInCollection?: boolean;// whether the document should remain in its collection when someone tries to drag and drop it elsewhere freezeChildren?: string; // whether children are now allowed to be added and or removed from a collection treeViewPreventOpen?: boolean; // ignores the treeViewOpen Doc flag which allows a treeViewItem's expand/collapse state to be independent of other views of the same document in the tree view treeViewHideTitle?: boolean; // whether to hide the top document title of a tree view @@ -246,16 +246,13 @@ export class DocumentOptions { sidebarColor?: string; // background color of text sidebar sidebarViewType?: string; // collection type of text sidebar limitHeight?: number; // maximum height for newly created (eg, from pasting) text documents - // [key: string]: Opt; - pointerHack?: boolean; // for buttons, allows onClick handler to fire onPointerDown textTransform?: string; // is linear view expanded letterSpacing?: string; // is linear view expanded flexDirection?: "unset" | "row" | "column" | "row-reverse" | "column-reverse"; - selectedIndex?: number; + selectedIndex?: number; // which item in a linear view has been selected using the "thumb doc" ui syntaxColor?: string; // can be applied to text for syntax highlighting all matches in the text searchQuery?: string; // for quersyBox linearViewIsExpanded?: boolean; // is linear view expanded - isLabel?: boolean; // whether the document is a label or not (video / audio) useLinkSmallAnchor?: boolean; // whether links to this document should use a miniature linkAnchorBox border?: string; //for searchbox _hovercolor?: string; @@ -769,7 +766,7 @@ export namespace Docs { const doc = InstanceFromProto(Prototypes.get(DocumentType.LINK), undefined, { dontRegisterChildViews: true, isLinkButton: true, treeViewHideTitle: true, backgroundColor: "lightblue", // lightblue is default color for linking dot and link documents text comment area - treeViewExpandedView: "fields", removeDropProperties: new List(["_layers", "isLinkButton"]), ...options + treeViewExpandedView: "fields", removeDropProperties: new List(["_layerTags", "isLinkButton"]), ...options }, id); const linkDocProto = Doc.GetProto(doc); linkDocProto.treeViewOpen = true;// setting this in the instance creator would set it on the view document. diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index eef2236b5..ca5d4d371 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -226,7 +226,7 @@ export class CurrentUserUtils { title: "Advanced Item Prototypes", _xMargin: 0, _showTitle: "title", hidden: ComputedField.MakeFunction("IsNoviceMode()") as any, _stayInCollection: true, _hideContextMenu: true, - _autoHeight: true, _width: 500, _columnWidth: 35, ignoreClick: true, lockedPosition: true, _chromeStatus: "disabled", + _autoHeight: true, _width: 500, _columnWidth: 35, ignoreClick: true, _lockedPosition: true, _chromeStatus: "disabled", dropConverter: ScriptField.MakeScript("convertToButtons(dragData)", { dragData: DragManager.DocumentDragData.name }), system: true })); } else { @@ -246,7 +246,7 @@ export class CurrentUserUtils { noteView.isTemplateDoc = makeTemplate(noteView, true, "Note"); doc["template-note-Note"] = new PrefetchProxy(noteView); } - if (true || doc["template-note-Idea"] === undefined) { + if (doc["template-note-Idea"] === undefined) { const noteView = Docs.Create.TextDocument("", { title: "text", backgroundColor: "pink", system: true }); noteView.isTemplateDoc = makeTemplate(noteView, true, "Idea"); doc["template-note-Idea"] = new PrefetchProxy(noteView); @@ -505,7 +505,7 @@ export class CurrentUserUtils { if (dragCreatorSet === undefined) { doc.myItemCreators = new PrefetchProxy(Docs.Create.MasonryDocument(creatorBtns, { title: "Basic Item Creators", _showTitle: "title", _xMargin: 0, _stayInCollection: true, _hideContextMenu: true, - _autoHeight: true, _width: 500, _columnWidth: 35, ignoreClick: true, lockedPosition: true, _chromeStatus: "disabled", + _autoHeight: true, _width: 500, _columnWidth: 35, ignoreClick: true, _lockedPosition: true, _chromeStatus: "disabled", dropConverter: ScriptField.MakeScript("convertToButtons(dragData)", { dragData: DragManager.DocumentDragData.name }), system: true })); } else { @@ -534,7 +534,7 @@ export class CurrentUserUtils { if (doc.mySearchPanelDoc === undefined) { doc.mySearchPanelDoc = new PrefetchProxy(Docs.Create.SearchDocument({ _width: 500, _height: 300, backgroundColor: "dimGray", ignoreClick: true, _searchDoc: true, - childDropAction: "alias", lockedPosition: true, _viewType: CollectionViewType.Schema, _chromeStatus: "disabled", title: "sidebar search stack", system: true + childDropAction: "alias", _lockedPosition: true, _viewType: CollectionViewType.Schema, _chromeStatus: "disabled", title: "sidebar search stack", system: true })) as any as Doc; } } @@ -569,7 +569,7 @@ export class CurrentUserUtils { _backgroundColor: "black", ignoreClick: true, _gridGap: 0, _yMargin: 0, - _yPadding: 0, _xMargin: 0, _autoHeight: false, _width: 60, _columnWidth: 60, lockedPosition: true, _chromeStatus: "disabled", system: true + _yPadding: 0, _xMargin: 0, _autoHeight: false, _width: 60, _columnWidth: 60, _lockedPosition: true, _chromeStatus: "disabled", system: true })); } // this resets all sidebar buttons to being deactivated @@ -602,7 +602,7 @@ export class CurrentUserUtils { // Sets up mobileMenu stacking document static setupMobileMenu() { const menu = new PrefetchProxy(Docs.Create.StackingDocument(this.setupMobileButtons(), { - _width: 980, ignoreClick: true, lockedPosition: false, _chromeStatus: "disabled", title: "home", _yMargin: 100, system: true + _width: 980, ignoreClick: true, _lockedPosition: false, _chromeStatus: "disabled", title: "home", _yMargin: 100, system: true })); return menu; } @@ -621,7 +621,7 @@ export class CurrentUserUtils { return docProtoData.filter(d => !buttons || !buttons.includes(d.title)).map(data => this.mobileButton({ title: data.title, - lockedPosition: true, + _lockedPosition: true, onClick: data.click ? ScriptField.MakeScript(data.click) : undefined, _backgroundColor: data.backgroundColor, system: true }, @@ -670,7 +670,7 @@ export class CurrentUserUtils { onDragStart: data.drag ? ScriptField.MakeFunction(data.drag) : undefined, clipboard: data.clipboard, onPointerUp: data.pointerUp ? ScriptField.MakeScript(data.pointerUp) : undefined, onPointerDown: data.pointerDown ? ScriptField.MakeScript(data.pointerDown) : undefined, - ischecked: data.ischecked ? ComputedField.MakeFunction(data.ischecked) : undefined, activeInkPen: data.activeInkPen, pointerHack: true, + ischecked: data.ischecked ? ComputedField.MakeFunction(data.ischecked) : undefined, activeInkPen: data.activeInkPen, backgroundColor: data.backgroundColor, removeDropProperties: new List(["dropAction"]), dragFactory: data.dragFactory, system: true })); } @@ -678,7 +678,7 @@ export class CurrentUserUtils { static setupThumbDoc(userDoc: Doc) { if (!userDoc.thumbDoc) { const thumbDoc = Docs.Create.LinearDocument(CurrentUserUtils.setupThumbButtons(userDoc), { - _width: 100, _height: 50, ignoreClick: true, lockedPosition: true, _chromeStatus: "disabled", title: "buttons", + _width: 100, _height: 50, ignoreClick: true, _lockedPosition: true, _chromeStatus: "disabled", title: "buttons", _autoHeight: true, _yMargin: 5, linearViewIsExpanded: true, backgroundColor: "white", system: true }); thumbDoc.inkToTextDoc = Docs.Create.LinearDocument([], { @@ -696,13 +696,13 @@ export class CurrentUserUtils { 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", _chromeStatus: "enabled", lockedPosition: true, system: true + title: "Upload Images From the Web", _chromeStatus: "enabled", _lockedPosition: true, system: true }); const uploadDoc = Docs.Create.StackingDocument([], { - title: "Mobile Upload Collection", backgroundColor: "white", lockedPosition: true, system: true + title: "Mobile Upload Collection", backgroundColor: "white", _lockedPosition: true, system: true }); return Docs.Create.StackingDocument([webDoc, uploadDoc], { - _width: screen.width, lockedPosition: true, _chromeStatus: "disabled", title: "Upload", _autoHeight: true, _yMargin: 80, backgroundColor: "lightgray", system: true + _width: screen.width, _lockedPosition: true, _chromeStatus: "disabled", title: "Upload", _autoHeight: true, _yMargin: 80, backgroundColor: "lightgray", system: true }); } @@ -722,7 +722,7 @@ export class CurrentUserUtils { if (doc.myCreators === undefined) { doc.myCreators = new PrefetchProxy(Docs.Create.StackingDocument([creatorBtns, templateBtns], { title: "all Creators", _yMargin: 0, _autoHeight: true, _xMargin: 0, - _width: 500, ignoreClick: true, lockedPosition: true, _chromeStatus: "disabled", system: true + _width: 500, ignoreClick: true, _lockedPosition: true, _chromeStatus: "disabled", system: true })); } // setup a color picker @@ -735,7 +735,7 @@ export class CurrentUserUtils { if (doc.myTools === undefined) { const toolsStack = new PrefetchProxy(Docs.Create.StackingDocument([doc.myCreators as Doc, doc.myColorPicker as Doc], { - title: "My Tools", _width: 500, _yMargin: 20, ignoreClick: true, lockedPosition: true, _chromeStatus: "disabled", forceActive: true, system: true, _stayInCollection: true, _hideContextMenu: true, + title: "My Tools", _width: 500, _yMargin: 20, ignoreClick: true, _lockedPosition: true, _chromeStatus: "disabled", forceActive: true, system: true, _stayInCollection: true, _hideContextMenu: true, })) as any as Doc; doc.myTools = toolsStack; @@ -750,7 +750,7 @@ export class CurrentUserUtils { title: "My Dashboards", _height: 400, treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, forceActive: true, childDropAction: "alias", treeViewTruncateTitleWidth: 150, treeViewPreventOpen: false, ignoreClick: true, - lockedPosition: true, boxShadow: "0 0", dontRegisterChildViews: true, targetDropAction: "same", system: true + _lockedPosition: true, boxShadow: "0 0", dontRegisterChildViews: true, targetDropAction: "same", system: true })); const newDashboard = ScriptField.MakeScript(`createNewDashboard(Doc.UserDoc())`); (doc.myDashboards as any as Doc).contextMenuScripts = new List([newDashboard!]); @@ -766,7 +766,7 @@ export class CurrentUserUtils { title: "My Presentations", _height: 100, treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, forceActive: true, childDropAction: "alias", treeViewTruncateTitleWidth: 150, treeViewPreventOpen: false, ignoreClick: true, - lockedPosition: true, boxShadow: "0 0", dontRegisterChildViews: true, targetDropAction: "same", system: true + _lockedPosition: true, boxShadow: "0 0", dontRegisterChildViews: true, targetDropAction: "same", system: true })); const newPresentations = ScriptField.MakeScript(`createNewPresentation()`); (doc.myPresentations as any as Doc).contextMenuScripts = new List([newPresentations!]); @@ -786,7 +786,7 @@ export class CurrentUserUtils { treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, forceActive: true, childDropAction: "alias", treeViewTruncateTitleWidth: 150, treeViewPreventOpen: false, ignoreClick: true, isFolder: true, treeViewType: "fileSystem", - lockedPosition: true, boxShadow: "0 0", dontRegisterChildViews: true, targetDropAction: "same", system: true + _lockedPosition: true, boxShadow: "0 0", dontRegisterChildViews: true, targetDropAction: "same", system: true })); } return doc.myFilesystem as any as Doc; @@ -794,13 +794,12 @@ export class CurrentUserUtils { static setupRecentlyClosedDocs(doc: Doc) { // setup Recently Closed library item - doc.myRecentlyClosedDocs === undefined; if (doc.myRecentlyClosedDocs === undefined) { doc.myRecentlyClosedDocs = new PrefetchProxy(Docs.Create.TreeDocument([], { title: "Recently Closed", _height: 500, treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, forceActive: true, childDropAction: "alias", treeViewTruncateTitleWidth: 150, treeViewPreventOpen: false, ignoreClick: true, - lockedPosition: true, boxShadow: "0 0", dontRegisterChildViews: true, targetDropAction: "same", system: true + _lockedPosition: true, boxShadow: "0 0", dontRegisterChildViews: true, targetDropAction: "same", system: true })); const clearAll = ScriptField.MakeScript(`getProto(self).data = new List([])`); (doc.myRecentlyClosedDocs as any as Doc).contextMenuScripts = new List([clearAll!]); @@ -815,7 +814,7 @@ export class CurrentUserUtils { title: "FilterDoc", _height: 500, treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, forceActive: true, childDropAction: "none", treeViewTruncateTitleWidth: 150, treeViewPreventOpen: false, ignoreClick: true, - lockedPosition: true, boxShadow: "0 0", dontRegisterChildViews: true, targetDropAction: "same", system: true + _lockedPosition: true, boxShadow: "0 0", dontRegisterChildViews: true, targetDropAction: "same", system: true })); } const clearAll = ScriptField.MakeScript(`getProto(self).data = new List([]); scriptContext._docFilters = scriptContext._docRangeFilters = undefined;`, { scriptContext: Doc.name }); @@ -831,7 +830,7 @@ export class CurrentUserUtils { doc.myUserDoc = new PrefetchProxy(Docs.Create.TreeDocument([doc], { treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, forceActive: true, title: "My UserDoc", treeViewTruncateTitleWidth: 150, treeViewPreventOpen: false, ignoreClick: true, - lockedPosition: true, boxShadow: "0 0", dontRegisterChildViews: true, targetDropAction: "same", system: true + _lockedPosition: true, boxShadow: "0 0", dontRegisterChildViews: true, targetDropAction: "same", system: true })) as any as Doc; } } @@ -861,7 +860,7 @@ export class CurrentUserUtils { static blist = (opts: DocumentOptions, docs: Doc[]) => new PrefetchProxy(Docs.Create.LinearDocument(docs, { ...opts, _gridGap: 5, _xMargin: 5, _yMargin: 5, _height: 42, _width: 100, boxShadow: "0 0", forceActive: true, dropConverter: ScriptField.MakeScript("convertToButtons(dragData)", { dragData: DragManager.DocumentDragData.name }), - backgroundColor: "black", treeViewPreventOpen: true, lockedPosition: true, _chromeStatus: "disabled", linearViewIsExpanded: true, system: true + backgroundColor: "black", treeViewPreventOpen: true, _lockedPosition: true, _chromeStatus: "disabled", linearViewIsExpanded: true, system: true })) as any as Doc static ficon = (opts: DocumentOptions) => new PrefetchProxy(Docs.Create.FontIconDocument({ @@ -915,7 +914,7 @@ export class CurrentUserUtils { if (!sharedDocs) { sharedDocs = Docs.Create.StackingDocument([], { title: "My SharedDocs", childDropAction: "alias", system: true, contentPointerEvents: "none", childLimitHeight: 0, _yMargin: 50, _gridGap: 15, - _showTitle: "title", ignoreClick: true, lockedPosition: true, + _showTitle: "title", ignoreClick: true, _lockedPosition: true, }, sharingDocumentId + "outer", sharingDocumentId); (sharedDocs as Doc)["acl-Public"] = Doc.GetProto(sharedDocs as Doc)["acl-Public"] = SharingPermissions.Add; } @@ -931,13 +930,13 @@ export class CurrentUserUtils { if (doc.myImportDocs === undefined) { doc.myImportDocs = new PrefetchProxy(Docs.Create.StackingDocument([], { title: "My ImportDocuments", forceActive: true, ignoreClick: true, _showTitle: "title", _stayInCollection: true, _hideContextMenu: true, childLimitHeight: 0, - childDropAction: "alias", _autoHeight: true, _yMargin: 50, _gridGap: 15, lockedPosition: true, _chromeStatus: "disabled", system: true + childDropAction: "alias", _autoHeight: true, _yMargin: 50, _gridGap: 15, _lockedPosition: true, _chromeStatus: "disabled", system: true })); } if (doc.myImportPanel === undefined) { const uploads = Cast(doc.myImportDocs, Doc, null); const newUpload = CurrentUserUtils.ficon({ onClick: ScriptField.MakeScript("importDocument()"), toolTip: "Import External document", _stayInCollection: true, _hideContextMenu: true, title: "Import", icon: "upload", system: true }); - doc.myImportPanel = new PrefetchProxy(Docs.Create.StackingDocument([newUpload, uploads], { title: "My ImportPanel", _yMargin: 20, ignoreClick: true, _stayInCollection: true, _hideContextMenu: true, lockedPosition: true, system: true })); + doc.myImportPanel = new PrefetchProxy(Docs.Create.StackingDocument([newUpload, uploads], { title: "My ImportPanel", _yMargin: 20, ignoreClick: true, _stayInCollection: true, _hideContextMenu: true, _lockedPosition: true, system: true })); } } diff --git a/src/client/util/SerializationHelper.ts b/src/client/util/SerializationHelper.ts index 00ac6e521..4c3b3f096 100644 --- a/src/client/util/SerializationHelper.ts +++ b/src/client/util/SerializationHelper.ts @@ -22,10 +22,12 @@ export namespace SerializationHelper { return obj; } - serializing++; if (!(obj.constructor.name in reverseMap)) { - throw Error(`type '${obj.constructor.name}' not registered. Make sure you register it using a @Deserializable decorator`); + // throw Error( + console.log("Error: " + `type '${obj.constructor.name}' not registered. Make sure you register it using a @Deserializable decorator`, obj); + return undefined; } + serializing++; const json = serialize(obj); json.__type = reverseMap[obj.constructor.name]; @@ -52,7 +54,9 @@ export namespace SerializationHelper { } if (!(obj.__type in serializationTypes)) { - throw Error(`type '${obj.__type}' not registered. Make sure you register it using a @Deserializable decorator`); + // throw Error( + console.log(`type '${obj.__type}' not registered. Make sure you register it using a @Deserializable decorator`); + return undefined; } const type = serializationTypes[obj.__type]; diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 314922df8..d17668ea7 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -228,7 +228,7 @@ export class MainView extends React.Component { createNewPresentation = async () => { if (!await this.userDoc.myPresentations) { this.userDoc.myPresentations = new PrefetchProxy(Docs.Create.TreeDocument([], { - title: "PRESENTATION TRAILS", _height: 100, forceActive: true, boxShadow: "0 0", lockedPosition: true, treeViewOpen: true, system: true + title: "PRESENTATION TRAILS", _height: 100, forceActive: true, boxShadow: "0 0", _lockedPosition: true, treeViewOpen: true, system: true })); } const pres = Docs.Create.PresDocument(new List(), @@ -319,8 +319,8 @@ export class MainView extends React.Component {
toggleField(e, doc, "hidden")}>
-
toggleField(e, doc, "lockedPosition")}> - +
toggleField(e, doc, "_lockedPosition")}> +
; } diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx index 8ad5f3f2b..e9963bce9 100644 --- a/src/client/views/PropertiesButtons.tsx +++ b/src/client/views/PropertiesButtons.tsx @@ -194,12 +194,12 @@ export class PropertiesButtons extends React.Component<{}, {}> { get lockButton() { const targetDoc = this.selectedDoc; return !targetDoc ? (null) : {`${this.selectedDoc?.lockedPosition ? "Unlock" : "Lock"} Position`}
} placement="top"> + title={
{`${this.selectedDoc?._lockedPosition ? "Unlock" : "Lock"} Position`}
} placement="top">
-
+
+ color={this.selectedDoc?._lockedPosition ? "black" : "white"} + icon={this.selectedDoc?._lockedPosition ? "unlock" : "lock"} />
Position
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx index 73a82d7ab..69a1e4db2 100644 --- a/src/client/views/StyleProvider.tsx +++ b/src/client/views/StyleProvider.tsx @@ -44,9 +44,9 @@ function darkScheme() { return BoolCast(CurrentUserUtils.ActiveDashboard?.darkSc function toggleBackground(doc: Doc) { UndoManager.RunInBatch(() => runInAction(() => { - const layers = StrListCast(doc.layers); + const layers = StrListCast(doc._layerTags); if (!layers.includes(StyleLayers.Background)) { - if (!layers.length) doc.layers = new List([StyleLayers.Background]); + if (!layers.length) doc._layerTags = new List([StyleLayers.Background]); else layers.push(StyleLayers.Background); } else layers.splice(layers.indexOf(StyleLayers.Background), 1); @@ -65,7 +65,7 @@ export function DefaultStyleProvider(doc: Opt, props: Opt StrListCast(doc?.layers).includes(StyleLayers.Background); + const isBackground = () => StrListCast(doc?._layerTags).includes(StyleLayers.Background); const backgroundCol = () => props?.styleProvider?.(doc, props, StyleProp.BackgroundColor); const opacity = () => props?.styleProvider?.(doc, props, StyleProp.Opacity); @@ -184,15 +184,15 @@ export function DefaultLayerProvider(thisDoc: Doc) { if (assign) { const activeLayer = StrCast(thisDoc?.activeLayer); if (activeLayer) { - const layers = Cast(doc.layers, listSpec("string"), []); + const layers = Cast(doc._layerTags, listSpec("string"), []); if (layers.length && !layers.includes(activeLayer)) layers.push(activeLayer); - else if (!layers.length) doc.layers = new List([activeLayer]); + else if (!layers.length) doc._layerTags = new List([activeLayer]); if (activeLayer === "red" || activeLayer === "green" || activeLayer === "blue") doc._backgroundColor = activeLayer; } return true; } else { if (Doc.AreProtosEqual(doc, thisDoc)) return true; - const layers = StrListCast(doc.layers); + const layers = StrListCast(doc._layerTags); if (!layers.length && !thisDoc?.activeLayer) return true; if (layers.includes(StrCast(thisDoc?.activeLayer))) return true; return false; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 4040362d8..02f148eb0 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -264,7 +264,7 @@ export class CollectionFreeFormView extends CollectionSubView s.backgroundColor); // override the cluster color with an explicitly set color on a non-background document. then override that with an explicitly set color on a background document - set?.filter(s => !StrListCast(s.layers).includes(StyleLayers.Background)).map(s => styleProp = StrCast(s.backgroundColor)); - set?.filter(s => StrListCast(s.layers).includes(StyleLayers.Background)).map(s => styleProp = StrCast(s.backgroundColor)); + set?.filter(s => !StrListCast(s._layerTags).includes(StyleLayers.Background)).map(s => styleProp = StrCast(s.backgroundColor)); + set?.filter(s => StrListCast(s._layerTags).includes(StyleLayers.Background)).map(s => styleProp = StrCast(s.backgroundColor)); } } //else if (doc && NumCast(doc.group, -1) !== -1) styleProp = "gray"; return styleProp; @@ -869,7 +869,7 @@ export class CollectionFreeFormView extends CollectionSubView { - if (sendToBack || StrListCast(doc.layers).includes(StyleLayers.Background)) { + if (sendToBack || StrListCast(doc._layerTags).includes(StyleLayers.Background)) { doc.zIndex = 0; } else if (doc.isInkMask) { doc.zIndex = 5000; @@ -1363,7 +1363,7 @@ export class CollectionFreeFormView extends CollectionSubView intersectRect(docDims(doc), rect); const otherBounds = { left: this.panX(), top: this.panY(), width: Math.abs(size[0]), height: Math.abs(size[1]) }; - let snappableDocs = activeDocs.filter(doc => !StrListCast(doc.layers).includes(StyleLayers.Background) && doc.z === undefined && isDocInView(doc, selRect)); // first see if there are any foreground docs to snap to + let snappableDocs = activeDocs.filter(doc => !StrListCast(doc._layerTags).includes(StyleLayers.Background) && doc.z === undefined && isDocInView(doc, selRect)); // first see if there are any foreground docs to snap to !snappableDocs.length && (snappableDocs = activeDocs.filter(doc => doc.z === undefined && isDocInView(doc, selRect))); // if not, see if there are background docs to snap to !snappableDocs.length && (snappableDocs = activeDocs.filter(doc => doc.z !== undefined && isDocInView(doc, otherBounds))); // if not, then why not snap to floating docs diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 34ddf6ed2..ff6c2860a 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -363,7 +363,7 @@ export class MarqueeView extends React.Component(layers); + newCollection._layerTags = new List(layers); newCollection._width = this.Bounds.width; newCollection._height = this.Bounds.height; newCollection._isGroup = makeGroup; diff --git a/src/client/views/collections/collectionGrid/CollectionGridView.tsx b/src/client/views/collections/collectionGrid/CollectionGridView.tsx index 58db080ad..e2feff5ed 100644 --- a/src/client/views/collections/collectionGrid/CollectionGridView.tsx +++ b/src/client/views/collections/collectionGrid/CollectionGridView.tsx @@ -235,7 +235,7 @@ export class CollectionGridView extends CollectionSubView(GridSchema) { i, y, h, x: x + w > this.numCols ? 0 : x, // handles wrapping around of nodes when numCols decreases w: Math.min(w, this.numCols), // reduces width if greater than numCols - static: BoolCast(this.childLayoutPairs.find(({ layout }) => layout[Id] === i)?.layout.lockedPosition, false) // checks if the lock position item has been selected in the context menu + static: BoolCast(this.childLayoutPairs.find(({ layout }) => layout[Id] === i)?.layout._lockedPosition, false) // checks if the lock position item has been selected in the context menu })) : this.savedLayoutList.map((layout, index) => { Object.assign(layout, this.unflexedPosition(index)); return layout; }); } diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx index 18cabc309..96b6bea8c 100644 --- a/src/client/views/nodes/DocumentLinksButton.tsx +++ b/src/client/views/nodes/DocumentLinksButton.tsx @@ -106,7 +106,7 @@ export class DocumentLinksButton extends React.Component 3 || Math.abs(this._downY - touch.clientY) > 3)) { if (!e.altKey && (!this.topMost || this.layoutDoc.onDragStart || this.onClickHandler)) { @@ -427,7 +427,7 @@ export class DocumentViewInternal extends DocComponent 3 || Math.abs(this._downY - e.clientY) > 3) { if (!e.altKey && (!this.topMost || this.layoutDoc.onDragStart || this.onClickHandler) && (e.buttons === 1 || InteractionUtils.IsType(e, InteractionUtils.TOUCHTYPE))) { document.removeEventListener("pointermove", this.onPointerMove); @@ -594,7 +594,7 @@ export class DocumentViewInternal extends DocComponent this.props.removeDocument?.(this.props.Document); @undoBatch toggleDetail = () => this.Document.onClick = ScriptField.MakeScript(`toggleDetail(self, "${this.Document.layoutKey}")`); - @undoBatch toggleLockPosition = () => this.Document.lockedPosition = this.Document.lockedPosition ? undefined : true; + @undoBatch toggleLockPosition = () => this.Document._lockedPosition = this.Document._lockedPosition ? undefined : true; @undoBatch @action drop = async (e: Event, de: DragManager.DropEvent) => { @@ -685,7 +685,7 @@ export class DocumentViewInternal extends DocComponent this.Document.ignoreClick = !this.Document.ignoreClick, icon: this.Document.ignoreClick ? "unlock" : "lock" }); diff --git a/src/client/views/nodes/LinkAnchorBox.tsx b/src/client/views/nodes/LinkAnchorBox.tsx index d76b61502..392565402 100644 --- a/src/client/views/nodes/LinkAnchorBox.tsx +++ b/src/client/views/nodes/LinkAnchorBox.tsx @@ -94,7 +94,7 @@ export class LinkAnchorBox extends ViewBoxBaseComponent { const alias = Doc.MakeAlias(Cast(this.layoutDoc[this.fieldKey], Doc, null)); alias.isLinkButton = undefined; - alias.layers = undefined; + alias._layerTags = undefined; alias.layoutKey = "layout"; this.props.addDocTab(alias, "add:right"); } diff --git a/src/fields/documentSchemas.ts b/src/fields/documentSchemas.ts index 6973079b0..4d8b6b55c 100644 --- a/src/fields/documentSchemas.ts +++ b/src/fields/documentSchemas.ts @@ -21,7 +21,6 @@ export const documentSchema = createSchema({ _currentTimecode: "number", // current play back time of a temporal document (video / audio) _timecodeToShow: "number", // the time that a document should be displayed (e.g., time an annotation should be displayed on a video) _timecodeToHIde: "number", // the time that a document should be hidden - isLabel: "boolean", // whether the document is a label or not (video / audio) markers: listSpec(Doc), // list of markers for audio / video x: "number", // x coordinate when in a freeform view y: "number", // y coordinate when in a freeform view @@ -96,7 +95,7 @@ export const documentSchema = createSchema({ isInPlaceContainer: "boolean",// whether the marked object will display addDocTab() calls that target "inPlace" 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) + _lockedPosition: "boolean", // whether the document can be moved (dragged) _lockedTransform: "boolean",// whether a freeformview can pan/zoom // drag drop properties diff --git a/src/fields/util.ts b/src/fields/util.ts index b9c5a13c1..b616515de 100644 --- a/src/fields/util.ts +++ b/src/fields/util.ts @@ -280,7 +280,6 @@ export function setter(target: any, in_prop: string | symbol | number, value: an let prop = in_prop; const effectiveAcl = getPropAcl(target, prop); if (effectiveAcl !== AclEdit && effectiveAcl !== AclAdmin) return true; - // if you're trying to change an acl but don't have Admin access / you're trying to change it to something that isn't an acceptable acl, you can't if (typeof prop === "string" && prop.startsWith("acl") && (effectiveAcl !== AclAdmin || ![...Object.values(SharingPermissions), undefined, "None"].includes(value))) return true; // if (typeof prop === "string" && prop.startsWith("acl") && !["Can Edit", "Can Augment", "Can View", "Not Shared", undefined].includes(value)) return true; diff --git a/src/server/database.ts b/src/server/database.ts index 41bf8b3da..8e0f99a1f 100644 --- a/src/server/database.ts +++ b/src/server/database.ts @@ -163,7 +163,7 @@ export namespace Database { } public async insert(value: any, collectionName = DocumentsCollection) { - if (this.db) { + if (this.db && value) { if ("id" in value) { value._id = value.id; delete value.id; @@ -185,7 +185,7 @@ export namespace Database { newProm = prom ? prom.then(run) : run(); this.currentWrites[id] = newProm; return newProm; - } else { + } else if (value) { this.onConnect.push(() => this.insert(value, collectionName)); } } diff --git a/src/server/websocket.ts b/src/server/websocket.ts index 7e3c4da82..4ae97913f 100644 --- a/src/server/websocket.ts +++ b/src/server/websocket.ts @@ -277,7 +277,11 @@ export namespace WebSocket { function addToListField(socket: Socket, diff: Diff, curListItems?: Transferable): void { diff.diff.$set = diff.diff.$addToSet; delete diff.diff.$addToSet;// convert add to set to a query of the current fields, and then a set of the composition of the new fields with the old ones const updatefield = Array.from(Object.keys(diff.diff.$set))[0]; - const newListItems = diff.diff.$set[updatefield].fields; + const newListItems = diff.diff.$set[updatefield]?.fields; + if (!newListItems) { + console.log("Error: addToListField - no new list items"); + return; + } const curList = (curListItems as any)?.fields?.[updatefield.replace("fields.", "")]?.fields.filter((item: any) => item !== undefined) || []; diff.diff.$set[updatefield].fields = [...curList, ...newListItems.filter((newItem: any) => newItem === null || !curList.some((curItem: any) => curItem.fieldId ? curItem.fieldId === newItem.fieldId : curItem.heading ? curItem.heading === newItem.heading : curItem === newItem))]; const sendBack = diff.diff.length !== diff.diff.$set[updatefield].fields.length; -- cgit v1.2.3-70-g09d2 From 17de222e15525ec5bda3c4e7113c1471dbfb906c Mon Sep 17 00:00:00 2001 From: bobzel Date: Fri, 26 Feb 2021 17:33:51 -0500 Subject: fixes for getting documents into myFilesystem. fixes for setting layout fields without using an _ --- src/client/util/CurrentUserUtils.ts | 2 +- src/client/views/collections/collectionFreeForm/MarqueeView.tsx | 1 + src/fields/util.ts | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index ca5d4d371..438690067 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -786,7 +786,7 @@ export class CurrentUserUtils { treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, forceActive: true, childDropAction: "alias", treeViewTruncateTitleWidth: 150, treeViewPreventOpen: false, ignoreClick: true, isFolder: true, treeViewType: "fileSystem", - _lockedPosition: true, boxShadow: "0 0", dontRegisterChildViews: true, targetDropAction: "same", system: true + _lockedPosition: true, boxShadow: "0 0", dontRegisterChildViews: true, targetDropAction: "proto", system: true })); } return doc.myFilesystem as any as Doc; diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index ff6c2860a..2a30e5fd0 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -359,6 +359,7 @@ export class MarqueeView extends React.Component { Doc.GetProto(doc).data = new List(selected); Doc.GetProto(doc).title = makeGroup ? "grouping" : "nested freeform"; + !this.props.isAnnotationOverlay && Doc.AddDocToList(Cast(Doc.UserDoc().myFileOrphans, Doc, null), "data", Doc.GetProto(doc)); doc._panX = doc._panY = 0; return doc; })(Doc.MakeCopy(Doc.UserDoc().emptyCollection as Doc, true)); diff --git a/src/fields/util.ts b/src/fields/util.ts index 26ab34ff4..7955fc9fb 100644 --- a/src/fields/util.ts +++ b/src/fields/util.ts @@ -284,7 +284,7 @@ export function setter(target: any, in_prop: string | symbol | number, value: an if (typeof prop === "string" && prop.startsWith("acl") && (effectiveAcl !== AclAdmin || ![...Object.values(SharingPermissions), undefined, "None"].includes(value))) return true; // if (typeof prop === "string" && prop.startsWith("acl") && !["Can Edit", "Can Augment", "Can View", "Not Shared", undefined].includes(value)) return true; - if (typeof prop === "string" && prop !== "__id" && prop !== "__fields" && (prop.startsWith("_") || layoutProps.includes(prop))) { + if (typeof prop === "string" && prop !== "__id" && prop !== "__fields" && prop.startsWith("_")) { // if (!prop.startsWith("_")) { // console.log(prop + " is deprecated - switch to _" + prop); // prop = "_" + prop; @@ -309,7 +309,7 @@ export function getter(target: any, in_prop: string | symbol | number, receiver: if (GetEffectiveAcl(target) === AclPrivate) return prop === HeightSym || prop === WidthSym ? returnZero : undefined; if (prop === LayoutSym) return target.__LAYOUT__; let search = false; - if (typeof prop === "string" && prop !== "__id" && prop !== "__fields" && (prop.startsWith("_") || layoutProps.includes(prop))) { + if (typeof prop === "string" && prop !== "__id" && prop !== "__fields" && prop.startsWith("_")) { // if (!prop.startsWith("_")) { // console.log(prop + " is deprecated - switch to _" + prop); // prop = "_" + prop; -- cgit v1.2.3-70-g09d2 From 7902b1021b89e45bd595e4a9588db11dccbf9831 Mon Sep 17 00:00:00 2001 From: bobzel Date: Sun, 28 Feb 2021 01:06:27 -0500 Subject: a bunch of changes to simplify how autoHeight works. extended to work for pdfs and stacking views. still some bugs. --- src/client/documents/Documents.ts | 2 +- src/client/util/CurrentUserUtils.ts | 2 +- src/client/views/DocComponent.tsx | 2 +- src/client/views/DocumentDecorations.tsx | 30 ++-- src/client/views/MainView.tsx | 4 + src/client/views/TemplateMenu.tsx | 1 + .../views/collections/CollectionSchemaView.tsx | 2 +- .../views/collections/CollectionStackingView.tsx | 17 +- src/client/views/collections/TabDocView.tsx | 1 + src/client/views/nodes/DocumentContentsView.tsx | 1 + src/client/views/nodes/DocumentView.tsx | 16 +- src/client/views/nodes/FieldView.tsx | 3 +- src/client/views/nodes/FilterBox.tsx | 1 + src/client/views/nodes/KeyValuePair.tsx | 1 + .../views/nodes/formattedText/FormattedTextBox.tsx | 180 ++++++--------------- src/client/views/pdf/PDFViewer.tsx | 6 + src/client/views/search/SearchBox.tsx | 2 +- 17 files changed, 108 insertions(+), 163 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index d725e5fc9..7f20fa990 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -240,7 +240,7 @@ export class DocumentOptions { treeViewDefaultExpandedView?: string; // default expanded view sidebarColor?: string; // background color of text sidebar sidebarViewType?: string; // collection type of text sidebar - docMaxHeight?: number; // maximum height for newly created (eg, from pasting) text documents + docMaxAutoHeight?: number; // maximum height for newly created (eg, from pasting) text documents textTransform?: string; // is linear view expanded letterSpacing?: string; // is linear view expanded flexDirection?: "unset" | "row" | "column" | "row-reverse" | "column-reverse"; diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index eab372d5d..3304de9a1 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -1198,7 +1198,7 @@ export class CurrentUserUtils { public static GetNewTextDoc(title: string, x: number, y: number, width?: number, height?: number, noMargins?: boolean, annotationOn?: Doc, maxHeight?: number) { const tbox = Docs.Create.TextDocument("", { - _xMargin: noMargins ? 0 : undefined, _yMargin: noMargins ? 0 : undefined, annotationOn, docMaxHeight: maxHeight, + _xMargin: noMargins ? 0 : undefined, _yMargin: noMargins ? 0 : undefined, annotationOn, docMaxAutoHeight: maxHeight, _width: width || 200, _height: height || 100, x: x, y: y, _autoHeight: true, _fontSize: StrCast(Doc.UserDoc().fontSize), _fontFamily: StrCast(Doc.UserDoc().fontFamily), title }); diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index ef1228976..128ba858f 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -11,7 +11,7 @@ import { GetEffectiveAcl, SharingPermissions, distributeAcls, denormalizeEmail } /// DocComponent returns a generic React base class used by views that don't have 'fieldKey' props (e.g.,CollectionFreeFormDocumentView, DocumentView) -interface DocComponentProps { +export interface DocComponentProps { Document: Doc; LayoutTemplate?: () => Opt; LayoutTemplateString?: string; diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 2391a21e6..f41238228 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -369,8 +369,7 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b let dX = 0, dY = 0, dW = 0, dH = 0; const unfreeze = () => SelectionManager.Views().forEach(action((element: DocumentView) => - ((element.rootDoc.type === DocumentType.RTF || - element.rootDoc.type === DocumentType.COMPARISON || + ((element.rootDoc.type === DocumentType.COMPARISON || (element.rootDoc.type === DocumentType.WEB && Doc.LayoutField(element.rootDoc) instanceof HtmlField)) && Doc.NativeHeight(element.layoutDoc)) && element.toggleNativeDimensions())); switch (this._resizeHdlId) { @@ -431,7 +430,7 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b if (nwidth / nheight !== width / height && !dragBottom) { height = nheight / nwidth * width; } - if (e.ctrlKey || (!dragBottom || !docView.layoutDoc._fitWidth)) { // ctrl key enables modification of the nativeWidth or nativeHeight durin the interaction + if (e.ctrlKey && !dragBottom) { // ctrl key enables modification of the nativeWidth or nativeHeight durin the interaction if (Math.abs(dW) > Math.abs(dH)) dH = dW * nheight / nwidth; else dW = dH * nwidth / nheight; } @@ -441,10 +440,6 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b doc.x = (doc.x || 0) + dX * (actualdW - width); doc.y = (doc.y || 0) + dY * (actualdH - height); const fixedAspect = (nwidth && nheight); - if (fixedAspect && (!nwidth || !nheight)) { - doc._nativeWidth = nwidth = doc._width || 0; - doc._nativeHeight = nheight = doc._height || 0; - } if (e.ctrlKey && [DocumentType.IMG, DocumentType.SCREENSHOT, DocumentType.VID].includes(doc.type as DocumentType)) { dW !== 0 && runInAction(() => { const dataDoc = doc[DataSym]; @@ -454,22 +449,24 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b Doc.SetNativeHeight(dataDoc, nh + (dW > 0 ? 10 : -10) * nh / nw); }); } - else if (nwidth > 0 && nheight > 0) { - if (Math.abs(dW) > Math.abs(dH) || dragRight) { - if (!fixedAspect || (dragRight && e.ctrlKey)) { + else if (fixedAspect) { + if ((Math.abs(dW) > Math.abs(dH) && (!dragBottom || !e.ctrlKey)) || dragRight) { + if (dragRight && e.ctrlKey) { doc._nativeWidth = actualdW / (doc._width || 1) * Doc.NativeWidth(doc); + } else { + if (!doc._fitWidth) doc._height = nheight / nwidth * actualdW; + else if (!e.ctrlKey) doc._height = actualdH; } doc._width = actualdW; - if (fixedAspect && !doc._fitWidth) doc._height = nheight / nwidth * doc._width; - else if (!fixedAspect || !e.ctrlKey) doc._height = actualdH; } else { - if (!fixedAspect || (dragBottom && (e.ctrlKey || docView.layoutDoc._fitWidth))) { + if (dragBottom && (e.ctrlKey || docView.layoutDoc._fitWidth)) { // frozen web pages and others that fitWidth can't grow horizontally to match a vertical resize so the only choice is to change the nativeheight even if the ctrl key isn't used doc._nativeHeight = actualdH / (doc._height || 1) * Doc.NativeHeight(doc); + } else { + if (!doc._fitWidth) doc._width = nwidth / nheight * actualdH; + else if (!e.ctrlKey) doc._width = actualdW; } doc._height = actualdH; - if (fixedAspect && !doc._fitWidth) doc._width = nwidth / nheight * doc._height; - else if (!fixedAspect || !e.ctrlKey) doc._width = actualdW; } } else { dW && (doc._width = actualdW); @@ -486,7 +483,8 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b SelectionManager.Views().map(dv => { if (NumCast(dv.layoutDoc._delayAutoHeight) < this._dragHeights.get(dv.layoutDoc)!) { dv.nativeWidth > 0 && Doc.toggleNativeDimensions(dv.layoutDoc, dv.ContentScale(), dv.props.PanelWidth(), dv.props.PanelHeight()); - dv.layoutDoc._autoHeight = true; + if (dv.layoutDoc._autoHeight) dv.layoutDoc._autoHeight = false; + setTimeout(() => dv.layoutDoc._autoHeight = true); } dv.layoutDoc._delayAutoHeight = undefined; }); diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 01afed5f9..b0c0af002 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -482,6 +482,7 @@ export class MainView extends React.Component { DataDoc={undefined} fieldKey={"data"} dropAction={"alias"} + setHeight={returnFalse} parentActive={returnFalse} styleProvider={DefaultStyleProvider} layerProvider={undefined} @@ -552,6 +553,7 @@ export class MainView extends React.Component { isSelected={returnTrue} active={returnTrue} select={returnTrue} + setHeight={returnFalse} addDocument={undefined} addDocTab={this.addDocTabFunc} pinToPres={emptyFunction} @@ -589,6 +591,7 @@ export class MainView extends React.Component { styleProvider={undefined} isSelected={returnFalse} select={returnFalse} + setHeight={returnFalse} rootSelected={returnFalse} renderDepth={0} parentActive={returnFalse} @@ -661,6 +664,7 @@ export class MainView extends React.Component { select={returnFalse} rootSelected={returnFalse} renderDepth={0} + setHeight={returnFalse} layerProvider={undefined} styleProvider={undefined} addDocTab={returnFalse} diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx index d2e0cb265..f39d5ee4c 100644 --- a/src/client/views/TemplateMenu.tsx +++ b/src/client/views/TemplateMenu.tsx @@ -140,6 +140,7 @@ export class TemplateMenu extends React.Component { rootSelected={returnFalse} onCheckedClick={this.scriptField} onChildClick={this.scriptField} + setHeight={returnFalse} dropAction={undefined} active={returnTrue} parentActive={returnFalse} diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 504cf32a0..a265045b8 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -553,7 +553,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
; return
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 77046f5ea..b5ce4b443 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -140,8 +140,10 @@ export class CollectionStackingView extends CollectionSubView this.pivotField, () => this.layoutDoc._columnHeaders = new List() ); - this._autoHeightDisposer = reaction(() => this.layoutDoc._autoHeight, this.forceAutoHeight); + this._autoHeightDisposer = reaction(() => this.layoutDoc._autoHeight, + () => this.props.setHeight(this.headerMargin + this.refList.reduce((p, r) => p + Number(getComputedStyle(r).height.replace("px", "")), 0))); } + componentWillUnmount() { super.componentWillUnmount(); this._pivotFieldDisposer?.(); @@ -369,11 +371,7 @@ export class CollectionStackingView extends CollectionSubView NumCast(Doc.Layout(doc)._viewScale, 1) * Number(getComputedStyle(r).height.replace("px", ""))))); - if (this.props.isAnnotationOverlay) { - doc[this.props.fieldKey + "-height"] = height; - } else { - Doc.Layout(doc)._height = height * NumCast(Doc.Layout(doc)._viewScale, 1); - } + this.props.setHeight(height * NumCast(Doc.Layout(doc)._viewScale, 1)); } })); this.observer.observe(ref); @@ -398,11 +396,6 @@ export class CollectionStackingView extends CollectionSubView { - const doc = this.props.DataDoc && this.props.DataDoc.layout === this.layoutDoc ? this.props.DataDoc : this.layoutDoc; - Doc.Layout(doc)._height = this.headerMargin + this.refList.reduce((p, r) => p + Number(getComputedStyle(r).height.replace("px", "")), 0); - } - sectionMasonry = (heading: SchemaHeaderField | undefined, docList: Doc[], first: boolean) => { const key = this.pivotField; let type: "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" | undefined = undefined; @@ -422,7 +415,7 @@ export class CollectionStackingView extends CollectionSubView { if (this.layoutDoc._autoHeight && ref && this.refList.length && !SnappingManager.GetIsDragging()) { const height = this.refList.reduce((p, r) => p + Number(getComputedStyle(r).height.replace("px", "")), 0); - Doc.Layout(doc)._height = this.headerMargin + Math.max(height, NumCast(doc[this.props.fieldKey + "-height"])); + this.props.setHeight(this.headerMargin + height); } })); this.observer.observe(ref); diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx index 68ca93f43..f7e067399 100644 --- a/src/client/views/collections/TabDocView.tsx +++ b/src/client/views/collections/TabDocView.tsx @@ -420,6 +420,7 @@ export class TabMinimapView extends React.Component { docViewPath={returnEmptyDoclist} childLayoutTemplate={this.childLayoutTemplate} // bcz: Ugh .. should probably be rendering a CollectionView or the minimap should be part of the collectionFreeFormView to avoid having to set stuff like this. noOverlay={true} // don't render overlay Docs since they won't scale + setHeight={returnFalse} active={returnTrue} select={emptyFunction} dropAction={undefined} diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index 7a8eb5628..c0af1e08a 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -109,6 +109,7 @@ export class DocumentContentsView extends React.Component boolean, select: (ctrl: boolean) => void, scaling?: () => number, + setHeight: (height: number) => void, layoutKey: string, hideOnLeave?: boolean, }> { diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index a48bc8f87..761485d61 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -1,5 +1,5 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { action, computed, observable, runInAction } from "mobx"; +import { action, computed, observable, runInAction, reaction, IReactionDisposer } from "mobx"; import { observer } from "mobx-react"; import { AclAdmin, AclEdit, AclPrivate, DataSym, Doc, DocListCast, Field, Opt, StrListCast } from "../../../fields/Doc"; import { Document } from '../../../fields/documentSchemas'; @@ -753,6 +753,7 @@ export class DocumentViewInternal extends DocComponent this.props.ScreenToLocalTransform().translate(0, -this.headerMargin); contentScaling = () => this.ContentScale; onClickFunc = () => this.onClickHandler; + setHeight = (height: number) => this.rootDoc._height = height; setContentView = (view: { getAnchor?: () => Doc, forward?: () => boolean, back?: () => boolean }) => this._componentView = view; @observable contentsActive: () => boolean = returnFalse; @action setContentsActive = (setActive: () => boolean) => this.contentsActive = setActive; @@ -778,6 +779,7 @@ export class DocumentViewInternal extends DocComponent { public static ROOT_DIV = "documentView-effectsWrapper"; public get displayName() { return "DocumentView(" + this.props.Document?.title + ")"; } // this makes mobx trace() statements more descriptive public ContentRef = React.createRef(); + private _disposers: { [name: string]: IReactionDisposer } = {}; @observable public docView: DocumentViewInternal | undefined | null; @@ -1070,9 +1073,20 @@ export class DocumentView extends React.Component { } componentDidMount() { + this._disposers.height = reaction( + () => NumCast(this.layoutDoc._height), + action(height => { + const docMax = NumCast(this.layoutDoc.docMaxAutoHeight); + if (docMax && docMax < height) this.layoutDoc.docMaxAutoHeight = height; + if (height && height <= 20 && height < NumCast(this.layoutDoc._delayAutoHeight, 20)) { + this.layoutDoc._delayAutoHeight = height; + } + }) + ); !BoolCast(this.props.Document.dontRegisterView, this.props.dontRegisterView) && DocumentManager.Instance.AddView(this); } componentWillUnmount() { + Object.values(this._disposers).forEach(disposer => disposer?.()); !this.props.dontRegisterView && DocumentManager.Instance.RemoveView(this); } diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index 1b4119210..465c18309 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -16,12 +16,13 @@ import { VideoBox } from "./VideoBox"; export interface FieldViewProps extends DocumentViewSharedProps { // FieldView specific props that are not part of DocumentView props fieldKey: string; - overflow?: boolean; // bcz: would like to think this can be avoided -- need to look at further + scrollOverflow?: boolean; // bcz: would like to think this can be avoided -- need to look at further active: (outsideReaction?: boolean) => boolean; select: (isCtrlPressed: boolean) => void; isSelected: (outsideReaction?: boolean) => boolean; scaling?: () => number; + setHeight: (height: number) => void; // properties intended to be used from within layout strings (otherwise use the function equivalents that work more efficiently with React) pointerEvents?: string; diff --git a/src/client/views/nodes/FilterBox.tsx b/src/client/views/nodes/FilterBox.tsx index f42f487cf..bdd9334f4 100644 --- a/src/client/views/nodes/FilterBox.tsx +++ b/src/client/views/nodes/FilterBox.tsx @@ -185,6 +185,7 @@ export class FilterBox extends ViewBoxBaseComponent { fieldKey: this.props.keyName, rootSelected: returnFalse, isSelected: returnFalse, + setHeight: returnFalse, select: emptyFunction, dropAction: "alias", bringToFront: emptyFunction, diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index ae778f97c..76cf6bbc8 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -680,7 +680,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp Doc.AddDocToList(Cast(Doc.UserDoc()["template-notes"], Doc, null), "data", this.rootDoc); }, icon: "eye" }); - !Doc.UserDoc().noviceMode && appearanceItems.push({ description: "Create progressivized slide...", event: this.progressivizeText, icon: "desktop" }); cm.addItem({ description: "Appearance...", subitems: appearanceItems, icon: "eye" }); const options = cm.findByDescription("Options..."); @@ -692,66 +691,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp this._downX = this._downY = Number.NaN; } - progressivizeText = () => { - const list = this.ProseRef?.getElementsByTagName("li"); - const mainBulletText: string[] = []; - const mainBulletList: Doc[] = []; - if (list) { - const newBullets: Doc[] = this.recursiveProgressivize(1, list)[0]; - mainBulletList.push.apply(mainBulletList, newBullets); - } - const title = Docs.Create.TextDocument(StrCast(this.rootDoc.title), { title: "Title", _width: 800, _height: 70, x: 20, y: -10, _fontSize: '20pt', backgroundColor: "rgba(0,0,0,0)", appearFrame: 0, _fontWeight: 700 }); - mainBulletList.push(title); - const doc = Docs.Create.FreeformDocument(mainBulletList, { - title: StrCast(this.rootDoc.title), - x: NumCast(this.props.Document.x), y: NumCast(this.props.Document.y) + NumCast(this.props.Document._height) + 10, - _width: 400, _height: 225, _fitToBox: true, - }); - this.props.addDocument?.(doc); - } - - recursiveProgressivize = (nestDepth: number, list: HTMLCollectionOf, d?: number, y?: number, before?: string): [Doc[], number] => { - const mainBulletList: Doc[] = []; - let b = d ? d : 0; - let yLoc = y ? y : 0; - let nestCount = 0; - let count: string = before ? before : ''; - const fontSize: string = (16 - (nestDepth * 2)) + 'pt'; - const xLoc: number = (nestDepth * 20); - const width: number = 390 - xLoc; - const height: number = 55 - (nestDepth * 5); - Array.from(list).forEach(listItem => { - const mainBullets: number = Number(listItem.getAttribute("data-bulletstyle")); - if (mainBullets === nestDepth) { - if (listItem.childElementCount > 1) { - b++; - nestCount++; - yLoc += height; - count = before ? count + nestCount + "." : nestCount + "."; - const text = listItem.getElementsByTagName("p")[0].innerText; - const length = text.length; - const bullet1 = Docs.Create.TextDocument(count + " " + text, { title: "Slide text", _width: width, _autoHeight: true, x: xLoc, y: (yLoc), _fontSize: fontSize, backgroundColor: "rgba(0,0,0,0)", appearFrame: d ? d : b }); - // yLoc += NumCast(bullet1._height); - mainBulletList.push(bullet1); - const newList = this.recursiveProgressivize(nestDepth + 1, listItem.getElementsByTagName("li"), b, yLoc, count); - mainBulletList.push.apply(mainBulletList, newList[0]); - yLoc += newList.length * (55 - ((nestDepth + 1) * 5)); - } else { - b++; - nestCount++; - yLoc += height; - count = before ? count + nestCount + "." : nestCount + "."; - const text = listItem.innerText; - const length = text.length; - const bullet1 = Docs.Create.TextDocument(count + " " + text, { title: "Slide text", _width: width, _autoHeight: true, x: xLoc, y: (yLoc), _fontSize: fontSize, backgroundColor: "rgba(0,0,0,0)", appearFrame: d ? d : b }); - // yLoc += NumCast(bullet1._height); - mainBulletList.push(bullet1); - } - } - }); - return [mainBulletList, yLoc]; - } - recordDictation = () => { DictationManager.Controls.listen({ interimHandler: this.setDictationContent, @@ -894,14 +833,24 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp return this.focusSpeed; } + resetNativeHeight = (scrollHeight: number) => { + const nh = this.layoutDoc.isTemplateForField ? 0 : NumCast(this.layoutDoc._nativeHeight); + this.rootDoc[this.fieldKey + "-height"] = scrollHeight * (this.props.scaling?.() || 1) + this.titleHeight; + if (nh) { + this.layoutDoc._nativeHeight = scrollHeight; + } + } + componentDidMount() { this.props.setContentView?.(this); // this tells the DocumentView that this AudioBox is the "content" of the document. this allows the DocumentView to indirectly call getAnchor() on the AudioBox when making a link. this.props.contentsActive?.(this.IsActive); this._cachedLinks = DocListCast(this.Document.links); + this._disposers.scrollHeight = reaction(() => NumCast(this.rootDoc[this.fieldKey + "-scrollHeight"]), + scrollHeight => this.layoutDoc.autoHeight && this.resetNativeHeight(scrollHeight)); this._disposers.sidebarheight = reaction( - () => ({ annoHeight: NumCast(this.rootDoc[this.annotationKey + "-height"]), textHeight: NumCast(this.rootDoc[this.fieldKey + "-height"]) }), - ({ annoHeight, textHeight }) => { - this.layoutDoc._autoHeight && (this.rootDoc._height = Math.max(annoHeight, textHeight)); + () => ({ sidebarHeight: NumCast(this.rootDoc[this.SidebarKey + "-height"]), textHeight: NumCast(this.rootDoc[this.fieldKey + "-height"]) }), + ({ sidebarHeight, textHeight }) => { + this.layoutDoc._autoHeight && this.props.setHeight(Math.max(sidebarHeight, textHeight)); }); this._disposers.links = reaction(() => DocListCast(this.Document.links), // if a link is deleted, then remove all hyperlinks that reference it from the text's marks newLinks => { @@ -958,20 +907,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp } ); this._disposers.autoHeight = reaction( - () => ({ - width: NumCast(this.layoutDoc._width), - autoHeight: this.layoutDoc?._autoHeight - }), - ({ width, autoHeight }) => width !== undefined && setTimeout(() => this.tryUpdateHeight(), 0) - ); - this._disposers.height = reaction( - () => Cast(this.layoutDoc._height, "number", null), - action(height => { - this.rootDoc[this.fieldKey + "-height"] = height; - if (height !== undefined && height <= 20 && height < NumCast(this.layoutDoc._delayAutoHeight, 20)) { - this.layoutDoc._delayAutoHeight = height; - } - }) + () => ({ width: NumCast(this.layoutDoc._width), autoHeight: this.layoutDoc?._autoHeight }), + ({ width, autoHeight }) => width && autoHeight && this.resetNativeHeight(NumCast(this.layoutDoc[this.fieldKey + "-scrollHeight"])) ); this.setupEditor(this.config, this.props.fieldKey); @@ -1599,28 +1536,14 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp get titleHeight() { return this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.HeaderMargin) || 0; } - @action tryUpdateHeight() { - let scrollHeight = Math.min(NumCast(this.layoutDoc.docMaxHeight, 10000), (this.ProseRef?.scrollHeight || 0) * NumCast(this.layoutDoc._viewScale, 1)); - if (this.props.renderDepth && this.layoutDoc._autoHeight && !this.props.ignoreAutoHeight && scrollHeight && !this.props.dontRegisterView) { // if top === 0, then the text box is growing upward (as the overlay caption) which doesn't contribute to the height computation - const nh = this.layoutDoc.isTemplateForField ? 0 : NumCast(this.layoutDoc._nativeHeight); - const dh = NumCast(this.rootDoc._height); - const newHeight = Math.max(10, (nh ? dh / nh * scrollHeight : scrollHeight) + this.titleHeight); - if (this.rootDoc !== this.layoutDoc.doc && !this.layoutDoc.resolvedDataDoc) { - // if we have a template that hasn't been resolved yet, we can't set the height or we'd be setting it on the unresolved template. So set a timeout and hope its arrived... - console.log("Delayed height adjustment..."); - setTimeout(() => { - this.rootDoc[this.fieldKey + "-height"] = this.rootDoc._height = newHeight; - this.layoutDoc._nativeHeight = nh ? scrollHeight : undefined; - }, 10); - } else { - try { - const boxHeight = Number(getComputedStyle(this._boxRef.current!).height.replace("px", "")) * NumCast(this.Document._viewScale, 1); - const outer = this.rootDoc[HeightSym]() - boxHeight - this.titleHeight; - this.rootDoc[this.fieldKey + "-height"] = newHeight + Math.max(0, outer); - } catch (e) { console.log("Error in tryUpdateHeight"); } - } - } //else this.rootDoc[this.fieldKey + "-height"] = 0; + const proseHeight = this.ProseRef?.scrollHeight || 0; + const scrollHeight = this.ProseRef && Math.min(NumCast(this.layoutDoc.docMaxAutoHeight, proseHeight), proseHeight); + if (scrollHeight && this.props.renderDepth && this.layoutDoc._autoHeight && !this.props.ignoreAutoHeight && !this.props.dontRegisterView) { // if top === 0, then the text box is growing upward (as the overlay caption) which doesn't contribute to the height computation + if (this.rootDoc === this.layoutDoc.doc || this.layoutDoc.resolvedDataDoc) { + this.rootDoc[this.fieldKey + "-scrollHeight"] = scrollHeight; + } else setTimeout(() => this.rootDoc[this.fieldKey + "-scrollHeight"] = scrollHeight, 10); // if we have a template that hasn't been resolved yet, we can't set the height or we'd be setting it on the unresolved template. So set a timeout and hope its arrived... + } } @computed get audioHandle() { @@ -1644,39 +1567,40 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp sidebarAddDocument = (doc: Doc | Doc[]) => this.addDocument(doc, this.SidebarKey); sidebarMoveDocument = (doc: Doc | Doc[], targetCollection: Doc, addDocument: (doc: Doc | Doc[]) => boolean) => this.moveDocument(doc, targetCollection, addDocument, this.SidebarKey); sidebarRemDocument = (doc: Doc | Doc[]) => this.removeDocument(doc, this.SidebarKey); + setSidebarHeight = (height: number) => this.rootDoc[this.SidebarKey + "-height"] = height; @computed get sidebarCollection() { - const collectionProps: SubCollectionViewProps & collectionFreeformViewProps = { - ...OmitKeys(this.props, ["NativeWidth", "NativeHeight"]).omit, - NativeWidth: returnZero, - NativeHeight: returnZero, - PanelHeight: this.props.PanelHeight, - PanelWidth: this.sidebarWidth, - xMargin: 0, - yMargin: 0, - chromeStatus: "enabled", - scaleField: this.SidebarKey + "-scale", - isAnnotationOverlay: false, - fieldKey: this.SidebarKey, - fitContentsToDoc: this.fitToBox, - select: emptyFunction, - active: this.annotationsActive, - scaling: this.sidebarContentScaling, - whenActiveChanged: this.whenActiveChanged, - removeDocument: this.sidebarRemDocument, - moveDocument: this.sidebarMoveDocument, - addDocument: this.sidebarAddDocument, - CollectionView: undefined, - ScreenToLocalTransform: this.sidebarScreenToLocal, - renderDepth: this.props.renderDepth + 1, - }; + const renderComponent = (tag: string) => { + const ComponentTag = tag === "freeform" ? CollectionFreeFormView : tag === "translation" ? FormattedTextBox : CollectionStackingView; + return + } return this.props.noSidebar || !this.layoutDoc._showSidebar || this.sidebarWidthPercent === "0%" ? (null) :
- {this.layoutDoc.sidebarViewType === "translation" ? - : - this.layoutDoc.sidebarViewType === CollectionViewType.Freeform ? - : - } + {renderComponent(StrCast(this.layoutDoc.sidebarViewType))}
; } diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index ca6dc87ae..720d2d92e 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -123,6 +123,12 @@ export class PDFViewer extends ViewBoxAnnotatableComponent (e.target as any).scrollLeft = 0); + this._disposers.autoHeight = reaction(() => this.layoutDoc._autoHeight, + () => { + this.layoutDoc._nativeHeight = NumCast(this.props.Document[this.fieldKey + "-nativeHeight"]); + this.props.setHeight(NumCast(this.props.Document[this.fieldKey + "-nativeHeight"]) * (this.props.scaling?.() || 1)); + }); + this._disposers.searchMatch = reaction(() => Doc.IsSearchMatch(this.rootDoc), m => { if (m) (this._lastSearch = true) && this.search(Doc.SearchQuery(), m.searchMatch > 0); diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index 553443931..c82d03fce 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -565,7 +565,7 @@ export class SearchBox extends ViewBoxBaseComponent window.innerWidth || this.children > 6 ? true : false} + scrollOverflow={length > window.innerWidth || this.children > 6 ? true : false} focus={this.selectElement} ScreenToLocalTransform={Transform.Identity} /> -- cgit v1.2.3-70-g09d2 From bed03be10f9289e36f7e1621bbcf2579b0ca3f2d Mon Sep 17 00:00:00 2001 From: bobzel Date: Mon, 1 Mar 2021 13:00:23 -0500 Subject: final cleanups for simplified drag and drop of annotations. fixed some issues rtf focus when creating notes in masonry view. fixed text sidebar. --- src/client/documents/Documents.ts | 2 +- src/client/util/CurrentUserUtils.ts | 2 +- src/client/util/DragManager.ts | 31 +++++++-------- src/client/views/DocumentDecorations.tsx | 4 +- src/client/views/MarqueeAnnotator.tsx | 30 +++++++-------- src/client/views/StyleProvider.tsx | 5 ++- .../collections/CollectionMasonryViewFieldRow.tsx | 6 ++- src/client/views/collections/CollectionSubView.tsx | 13 ++++--- src/client/views/collections/TreeView.tsx | 2 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 23 +++++++---- src/client/views/nodes/DocumentLinksButton.tsx | 8 +--- src/client/views/nodes/DocumentView.tsx | 19 +++++---- src/client/views/nodes/ImageBox.tsx | 11 ++---- src/client/views/nodes/VideoBox.tsx | 11 ++---- src/client/views/nodes/WebBox.tsx | 11 ++---- .../views/nodes/formattedText/FormattedTextBox.tsx | 45 +++++++--------------- src/client/views/pdf/AnchorMenu.tsx | 4 +- src/fields/Doc.ts | 6 +-- 18 files changed, 106 insertions(+), 127 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 3791dbc5c..3f03d39da 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -658,7 +658,7 @@ export namespace Docs { viewDoc["acl-Public"] = dataDoc["acl-Public"] = Doc.UserDoc()?.defaultAclPrivate ? SharingPermissions.None : SharingPermissions.Add; viewDoc["acl-Override"] = dataDoc["acl-Override"] = "None"; - !Doc.IsSystem(dataDoc) && proto.type !== DocumentType.PDFANNO && proto.type !== DocumentType.LINK && proto.type !== DocumentType.LINKANCHOR && + !Doc.IsSystem(dataDoc) && ![DocumentType.PDFANNO, DocumentType.LINK, DocumentType.LINKANCHOR, DocumentType.TEXTANCHOR].includes(proto.type as any) && !protoProps.annotationOn && Doc.AddDocToList(Cast(Doc.UserDoc().myFileOrphans, Doc, null), "data", dataDoc); return Doc.assign(viewDoc, delegateProps, true); diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 3304de9a1..cd9905be6 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -428,7 +428,7 @@ export class CurrentUserUtils { ((doc.emptyAudio as Doc).proto as Doc)["dragFactory-count"] = 0; } if (doc.emptyNote === undefined) { - doc.emptyNote = Docs.Create.TextDocument("", { _width: 200, title: "text note", system: true, cloneFieldFilter: new List(["system"]) }); + doc.emptyNote = Docs.Create.TextDocument("", { _width: 200, title: "text note", _autoHeight: true, system: true, cloneFieldFilter: new List(["system"]) }); ((doc.emptyNote as Doc).proto as Doc)["dragFactory-count"] = 0; } if (doc.emptyImage === undefined) { diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 9baefd247..437fea0ea 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -138,13 +138,13 @@ export namespace DragManager { isSelectionMove?: boolean; // indicates that an explicitly selected Document is being dragged. this will suppress onDragStart scripts } export class LinkDragData { - constructor(linkSourceDoc: Doc) { - this.linkSourceDocument = linkSourceDoc; + constructor(dragDoc: Doc, linkSourceGetAnchor: () => Doc) { + this.dragDocument = dragDoc; + this.linkSourceGetAnchor = linkSourceGetAnchor; } - droppedDocuments: Doc[] = []; - linkSourceDocument: Doc; - dontClearTextBox?: boolean; - linkDropCallback?: (data: { linkDocument: Doc }) => void; + dragDocument: Doc; + linkSourceGetAnchor: () => Doc; + linkSourceDoc?: Doc; } export class ColumnDragData { constructor(colKey: SchemaHeaderField) { @@ -154,23 +154,18 @@ export namespace DragManager { } // used by PDFs,Text,Image,Video,Web to conditionally (if the drop completes) create a text annotation when dragging the annotate button from the AnchorMenu when a text/region selection has been made. // this is pretty clunky and should be rethought out using linkDrag or DocumentDrag - export class AnchorAnnoDragData { - constructor(dragDoc: Doc, annotationDocCreator: () => Doc, dropDocCreator: (annotationOn?: Doc) => Doc) { - this.dragDocument = dragDoc; + export class AnchorAnnoDragData extends LinkDragData { + constructor(dragDoc: Doc, linkSourceGetAnchor: () => Doc, dropDocCreator: (annotationOn: Doc | undefined) => Doc) { + super(dragDoc, linkSourceGetAnchor); this.dropDocCreator = dropDocCreator; - this.annotationDocCreator = annotationDocCreator; this.offset = [0, 0]; } - targetContext: Doc | undefined; - dragDocument: Doc; - annotationDocCreator: () => Doc; - dropDocCreator: (asAnnotation?: Doc) => Doc; + linkSourceDoc?: Doc; + dropDocCreator: (annotationOn: Doc | undefined) => Doc; dropDocument?: Doc; - annotationDocument?: Doc; offset: number[]; dropAction: dropActionType; userDropAction: dropActionType; - linkDropCallback?: (data: { linkDocument: Doc }) => void; } export function MakeDropTarget( @@ -258,8 +253,8 @@ export namespace DragManager { } // drags a linker button and creates a link on drop - export function StartLinkDrag(ele: HTMLElement, sourceDoc: Doc, downX: number, downY: number, options?: DragOptions) { - StartDrag([ele], new DragManager.LinkDragData(sourceDoc), downX, downY, options); + export function StartLinkDrag(ele: HTMLElement, sourceDoc: Doc, sourceDocGetAnchor: undefined | (() => Doc), downX: number, downY: number, options?: DragOptions) { + StartDrag([ele], new DragManager.LinkDragData(sourceDoc, () => sourceDocGetAnchor?.() ?? sourceDoc), downX, downY, options); } // drags a column from a schema view diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 92f5b79bd..357bff36d 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -414,8 +414,8 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b if (e.ctrlKey && !Doc.NativeHeight(docView.props.Document)) docView.toggleNativeDimensions(); if (dX !== 0 || dY !== 0 || dW !== 0 || dH !== 0) { const doc = Document(docView.rootDoc); - let nwidth = docView.nativeWidth; - let nheight = docView.nativeHeight; + const nwidth = docView.nativeWidth; + const nheight = docView.nativeHeight; const width = (doc._width || 0); let height = (doc._height || (nheight / nwidth * width)); height = !height || isNaN(height) ? 20 : height; diff --git a/src/client/views/MarqueeAnnotator.tsx b/src/client/views/MarqueeAnnotator.tsx index 1fb87f522..f03e1dd9d 100644 --- a/src/client/views/MarqueeAnnotator.tsx +++ b/src/client/views/MarqueeAnnotator.tsx @@ -64,27 +64,24 @@ export class MarqueeAnnotator extends React.Component { * This function is used by the AnchorMenu to create an anchor highlight and a new linked text annotation. * It also initiates a Drag/Drop interaction to place the text annotation. */ - AnchorMenu.Instance.StartDrag = action(async (e: PointerEvent, ele: HTMLElement) => { + AnchorMenu.Instance.StartDrag = action((e: PointerEvent, ele: HTMLElement) => { e.preventDefault(); e.stopPropagation(); - const targetCreator = (asAnnotation?: Doc) => { - const target = CurrentUserUtils.GetNewTextDoc("Note linked to " + this.props.rootDoc.title, 0, 0, 100, 100, undefined, asAnnotation); - FormattedTextBox.SelectOnLoad = target[Id]; - return target; - }; - const anchorCreator = () => { - const annoDoc = this.highlight("rgba(173, 216, 230, 0.75)"); // hyperlink color - annoDoc.isLinkButton = true; // prevents link button from showing up --- maybe not a good thing? + const sourceAnchorCreator = () => { + const annoDoc = this.highlight("rgba(173, 216, 230, 0.75)", true); // hyperlink color this.props.addDocument(annoDoc); return annoDoc; }; - DragManager.StartAnchorAnnoDrag([ele], new DragManager.AnchorAnnoDragData(this.props.rootDoc, anchorCreator, targetCreator), e.pageX, e.pageY, { + const targetCreator = (annotationOn: Doc | undefined) => { + const target = CurrentUserUtils.GetNewTextDoc("Note linked to " + this.props.rootDoc.title, 0, 0, 100, 100, undefined, annotationOn); + FormattedTextBox.SelectOnLoad = target[Id]; + return target; + }; + DragManager.StartAnchorAnnoDrag([ele], new DragManager.AnchorAnnoDragData(this.props.rootDoc, sourceAnchorCreator, targetCreator), e.pageX, e.pageY, { dragComplete: e => { - if (!e.aborted && e.annoDragData && e.annoDragData.annotationDocument && e.annoDragData.dropDocument && !e.linkDocument) { - e.linkDocument = DocUtils.MakeLink({ doc: e.annoDragData.annotationDocument }, { doc: e.annoDragData.dropDocument }, "Annotation"); - e.annoDragData.annotationDocument.isPushpin = e.annoDragData?.dropDocument.annotationOn === this.props.rootDoc; + if (!e.aborted && e.annoDragData && e.annoDragData.linkSourceDoc && e.annoDragData.dropDocument && e.linkDocument) { + e.annoDragData.linkSourceDoc.isPushpin = e.annoDragData.dropDocument.annotationOn === this.props.rootDoc; } - e.linkDocument && e.annoDragData?.linkDropCallback?.(e as { linkDocument: Doc });// bcz: typescript can't figure out that this is valid even though we tested e.linkDocument } }); }); @@ -141,11 +138,12 @@ export class MarqueeAnnotator extends React.Component { } } @action - highlight = (color: string) => { + highlight = (color: string, isLinkButton: boolean) => { // creates annotation documents for current highlights const effectiveAcl = GetEffectiveAcl(this.props.rootDoc[DataSym]); const annotationDoc = [AclAddonly, AclEdit, AclAdmin].includes(effectiveAcl) && this.makeAnnotationDocument(color); annotationDoc && this.props.addDocument(annotationDoc); + annotationDoc && (annotationDoc.isLinkButton = isLinkButton); return annotationDoc as Doc ?? undefined; } @@ -197,7 +195,7 @@ export class MarqueeAnnotator extends React.Component { AnchorMenu.Instance.jumpTo(e.clientX, e.clientY); if (AnchorMenu.Instance.Highlighting) {// when highlighter has been toggled when menu is pinned, we auto-highlight immediately on mouse up - this.highlight("rgba(245, 230, 95, 0.75)"); // yellowish highlight color for highlighted text (should match AnchorMenu's highlight color) + this.highlight("rgba(245, 230, 95, 0.75)", false); // yellowish highlight color for highlighted text (should match AnchorMenu's highlight color) } } else { runInAction(() => this._width = this._height = 0); diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx index e5b2a332a..5a2fb285b 100644 --- a/src/client/views/StyleProvider.tsx +++ b/src/client/views/StyleProvider.tsx @@ -65,13 +65,14 @@ export function DefaultStyleProvider(doc: Opt, props: Opt StrListCast(doc?._layerTags).includes(StyleLayers.Background); const backgroundCol = () => props?.styleProvider?.(doc, props, StyleProp.BackgroundColor); const opacity = () => props?.styleProvider?.(doc, props, StyleProp.Opacity); switch (property.split(":")[0]) { case StyleProp.DocContents: return undefined; - case StyleProp.WidgetColor: return darkScheme() ? "lightgrey" : "dimgrey"; + case StyleProp.WidgetColor: return isAnnotated ? "lightBlue" : darkScheme() ? "lightgrey" : "dimgrey"; case StyleProp.Opacity: return Cast(doc?._opacity, "number", Cast(doc?.opacity, "number", null)); case StyleProp.HideLinkButton: return isAnchor || props?.dontRegisterView || (!selected && (doc?.isLinkButton || doc?.hideLinkButton)); case StyleProp.ShowTitle: return doc && !doc.presentationTargetDoc && StrCast(doc._showTitle, @@ -157,7 +158,7 @@ export function DefaultStyleProvider(doc: Opt, props: Opt(schemaCtor: (doc: Doc) => T, moreProps?: e.stopPropagation(); return added; } - else if (de.complete.annoDragData && (!this.props.isAnnotationOverlay || de.complete.annoDragData.dragDocument === this.props.Document)) { - e.stopPropagation(); - de.complete.annoDragData.annotationDocument = de.complete.annoDragData.annotationDocCreator(); - de.complete.annoDragData.dropDocument = de.complete.annoDragData.dropDocCreator(this.props.isAnnotationOverlay ? this.props.Document : undefined); - return de.complete.annoDragData.dropDocument && this.addDocument(de.complete.annoDragData.dropDocument); + else if (de.complete.annoDragData) { + const dropCreator = de.complete.annoDragData.dropDocCreator; + de.complete.annoDragData.dropDocCreator = () => { + const dropped = dropCreator(this.props.isAnnotationOverlay ? this.rootDoc : undefined); + this.addDocument(dropped); + return dropped; + } + return true; } return false; } diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index 6975c24d1..18d515552 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -254,7 +254,7 @@ export class TreeView extends React.Component { const before = pt[1] < rect.top + rect.height / 2; const inside = this.fileSysMode && !this.doc.isFolder ? false : pt[0] > Math.min(rect.left + 75, rect.left + rect.width * .75) || (!before && this.treeViewOpen && this.childDocList.length); if (de.complete.linkDragData) { - const sourceDoc = de.complete.linkDragData.linkSourceDocument; + const sourceDoc = de.complete.linkDragData.linkSourceGetAnchor(); const destDoc = this.doc; DocUtils.MakeLink({ doc: sourceDoc }, { doc: destDoc }, "tree link", ""); e.stopPropagation(); diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 02f148eb0..af8ccb9c5 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -275,16 +275,23 @@ export class CollectionFreeFormView extends CollectionSubView { + const dropDoc = dropCreator(annotationOn); + if (dropDoc) { + dropDoc.x = xp - annoDragData.offset[0]; + dropDoc.y = yp - annoDragData.offset[1]; + this.bringToFront(dropDoc); + } + return dropDoc || this.rootDoc; + } return true; } @undoBatch internalLinkDrop(e: Event, de: DragManager.DropEvent, linkDragData: DragManager.LinkDragData, xp: number, yp: number) { - if (linkDragData.linkSourceDocument === this.props.Document || this.props.Document.annotationOn) return false; - if (!linkDragData.linkSourceDocument.context || StrCast(Cast(linkDragData.linkSourceDocument.context, Doc, null)?.type) === DocumentType.COL) { + if (linkDragData.dragDocument === this.props.Document || this.props.Document.annotationOn) return false; + if (!linkDragData.dragDocument.context || StrCast(Cast(linkDragData.dragDocument.context, Doc, null)?.type) === DocumentType.COL) { // const source = Docs.Create.TextDocument("", { _width: 200, _height: 75, x: xp, y: yp, title: "dropped annotation" }); // this.props.addDocument(source); // linkDragData.linkDocument = DocUtils.MakeLink({ doc: source }, { doc: linkDragData.linkSourceDocument }, "doc annotation"); // TODODO this is where in text links get passed @@ -292,7 +299,7 @@ export class CollectionFreeFormView extends CollectionSubView { const [xp, yp] = this.getTransform().transformPoint(de.x, de.y); - if (this.isAnnotationOverlay !== true && de.complete.linkDragData) return this.internalLinkDrop(e, de, de.complete.linkDragData, xp, yp); if (de.complete.annoDragData?.dragDocument && super.onInternalDrop(e, de)) return this.internalAnchorAnnoDrop(e, de.complete.annoDragData, xp, yp); - if (de.complete.docDragData?.droppedDocuments.length) return this.internalDocDrop(e, de, de.complete.docDragData, xp, yp); + else if (this.isAnnotationOverlay !== true && de.complete.linkDragData) return this.internalLinkDrop(e, de, de.complete.linkDragData, xp, yp); + else if (de.complete.docDragData?.droppedDocuments.length) return this.internalDocDrop(e, de, de.complete.docDragData, xp, yp); return false; } diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx index 96b6bea8c..085ffae26 100644 --- a/src/client/views/nodes/DocumentLinksButton.tsx +++ b/src/client/views/nodes/DocumentLinksButton.tsx @@ -51,16 +51,10 @@ 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"); - - // we want to allow specific views to handle the link creation in their own way (e.g., rich text makes text hyperlinks) - // the dragged view can regiser a linkDropCallback to be notified that the link was made and to update their data structures - // however, the dropped document isn't so accessible. What we do is set the newly created link document on the documentView - // The documentView passes a function prop returning this link doc to its descendants who can react to changes to it. - dropEv.linkDragData?.linkDropCallback?.(dropEv as { linkDocument: Doc }); // bcz: typescript can't figure out that this is valid even though we tested dropEv.linkDocument above } linkDrag?.end(); }, diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 848287fcc..e5bd14809 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -605,13 +605,17 @@ export class DocumentViewInternal extends DocComponent this.props.isSelected(), - selected => { - if (!selected) { - this._savedAnnotations.values().forEach(v => v.forEach(a => a.remove())); - this._savedAnnotations.clear(); - } - }, - { fireImmediately: true }); + selected => !selected && setTimeout(() => { + this._savedAnnotations.values().forEach(v => v.forEach(a => a.remove())); + this._savedAnnotations.clear(); + })); this._disposers.path = reaction(() => ({ nativeSize: this.nativeSize, width: this.layoutDoc[WidthSym]() }), action(({ nativeSize, width }) => { if (!this.layoutDoc._height) { diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx index ac67949f9..589a6dd24 100644 --- a/src/client/views/nodes/VideoBox.tsx +++ b/src/client/views/nodes/VideoBox.tsx @@ -204,13 +204,10 @@ export class VideoBox extends ViewBoxAnnotatableComponent this.props.isSelected(), - selected => { - if (!selected) { - this._savedAnnotations.values().forEach(v => v.forEach(a => a.remove())); - this._savedAnnotations.clear(); - } - }, - { fireImmediately: true }); + selected => !selected && setTimeout(() => { + this._savedAnnotations.values().forEach(v => v.forEach(a => a.remove())); + this._savedAnnotations.clear(); + })); this._disposers.triggerVideo = reaction( () => !LinkDocPreview.LinkInfo && this.props.renderDepth !== -1 ? NumCast(this.Document._triggerVideo, null) : undefined, time => time !== undefined && setTimeout(() => { diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index 2cd6f5f33..0cf052501 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -140,13 +140,10 @@ export class WebBox extends ViewBoxAnnotatableComponent this._url = urlField?.url.toString() || ""); this._disposers.selection = reaction(() => this.props.isSelected(), - selected => { - if (!selected) { - this._savedAnnotations.values().forEach(v => v.forEach(a => a.remove())); - this._savedAnnotations.clear(); - } - }, - { fireImmediately: true }); + selected => !selected && setTimeout(() => { + this._savedAnnotations.values().forEach(v => v.forEach(a => a.remove())); + this._savedAnnotations.clear(); + })); document.addEventListener("pointerup", this.onLongPressUp); document.addEventListener("pointermove", this.onLongPressMove); diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 59147061a..288cd14c9 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -185,7 +185,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp @action setupAnchorMenu = () => { AnchorMenu.Instance.Status = "marquee"; - AnchorMenu.Instance.Highlight = action((color: string) => { + AnchorMenu.Instance.Highlight = action((color: string, isLinkButton: boolean) => { this._editorView?.state && RichTextMenu.Instance.insertHighlight(color, this._editorView.state, this._editorView?.dispatch); return undefined; }); @@ -202,16 +202,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp return target; }; - DragManager.StartAnchorAnnoDrag([ele], new DragManager.AnchorAnnoDragData(this.rootDoc, () => this.rootDoc, targetCreator), e.pageX, e.pageY, { - dragComplete: e => { - const anchor = this.makeLinkAnchor(undefined, "add:right", undefined, "a link"); - if (!e.aborted && e.annoDragData && e.annoDragData.annotationDocument && e.annoDragData.dropDocument && !e.linkDocument) { - e.linkDocument = DocUtils.MakeLink({ doc: anchor }, { doc: e.annoDragData.dropDocument }, "hyperlink", "link to note"); - e.annoDragData.annotationDocument.isPushpin = e.annoDragData?.dropDocument.annotationOn === this.rootDoc; - } - e.linkDocument && e.annoDragData?.linkDropCallback?.(e as { linkDocument: Doc });// bcz: typescript can't figure out that this is valid even though we tested e.linkDocument - } - }); + DragManager.StartAnchorAnnoDrag([ele], new DragManager.AnchorAnnoDragData(this.rootDoc, this.getAnchor, targetCreator), e.pageX, e.pageY); }); const coordsT = this._editorView!.coordsAtPos(this._editorView!.state.selection.to); const coordsB = this._editorView!.coordsAtPos(this._editorView!.state.selection.to); @@ -401,7 +392,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp @undoBatch @action - drop = async (e: Event, de: DragManager.DropEvent) => { + drop = (e: Event, de: DragManager.DropEvent) => { + if (de.complete.annoDragData) de.complete.annoDragData.dropDocCreator = this.getAnchor; const dragData = de.complete.docDragData; if (dragData) { const draggedDoc = dragData.draggedDocuments.length && dragData.draggedDocuments[0]; @@ -427,18 +419,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp e.stopPropagation(); // } } // otherwise, fall through to outer collection to handle drop - } else if (de.complete.linkDragData) { - de.complete.linkDragData.linkDropCallback = this.linkDrop; - } - else if (de.complete.annoDragData) { - de.complete.annoDragData.linkDropCallback = this.linkDrop; } } - linkDrop = (data: { linkDocument: Doc }) => { - const anchor1Title = data.linkDocument.anchor1 instanceof Doc ? StrCast(data.linkDocument.anchor1.title) : "-untitled-"; - const anchor1 = data.linkDocument.anchor1 instanceof Doc ? data.linkDocument.anchor1 : undefined; - this.makeLinkAnchor(anchor1, "add:right", undefined, anchor1Title); - } getNodeEndpoints(context: Node, node: Node): { from: number, to: number } | null { let offset = 0; @@ -875,6 +857,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp }, { fireImmediately: true } ); quickScroll = undefined; + this.tryUpdateScrollHeight(); } pushToGoogleDoc = async () => { @@ -1457,11 +1440,11 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp } @computed get sidebarHandle() { const annotated = DocListCast(this.dataDoc[this.SidebarKey]).filter(d => d?.author).length; - return this.props.noSidebar || (!this.props.isSelected() && !(annotated && !this.sidebarWidth())) ? (null) : -
; + return
; } @computed get sidebarCollection() { const renderComponent = (tag: string) => { @@ -1490,8 +1473,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp ScreenToLocalTransform={this.sidebarScreenToLocal} renderDepth={this.props.renderDepth + 1} noSidebar={true} - fieldKey={this.layoutDoc.sidebarViewType === "translation" ? `${this.fieldKey}-translation` : this.SidebarKey} /> - } + fieldKey={this.layoutDoc.sidebarViewType === "translation" ? `${this.fieldKey}-translation` : this.SidebarKey} />; + }; return
{renderComponent(StrCast(this.layoutDoc.sidebarViewType))} @@ -1557,8 +1540,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp }} />
- {this.sidebarCollection} - {this.props.noSidebar || !this.layoutDoc._showSidebar || this.sidebarWidthPercent === "0%" ? (null) : this.sidebarHandle} + {this.props.noSidebar || !this.layoutDoc._showSidebar || this.sidebarWidthPercent === "0%" ? (null) : this.sidebarCollection} + {this.sidebarHandle} {!this.layoutDoc._showAudio ? (null) : this.audioHandle}
diff --git a/src/client/views/pdf/AnchorMenu.tsx b/src/client/views/pdf/AnchorMenu.tsx index d1fdc6c44..e3d14d620 100644 --- a/src/client/views/pdf/AnchorMenu.tsx +++ b/src/client/views/pdf/AnchorMenu.tsx @@ -43,7 +43,7 @@ export class AnchorMenu extends AntimodeMenu { @observable public Status: "marquee" | "annotation" | "" = ""; public StartDrag: (e: PointerEvent, ele: HTMLElement) => void = unimplementedFunction; - public Highlight: (color: string) => Opt = (color: string) => undefined; + public Highlight: (color: string, isPushpin: boolean) => Opt = (color: string, isPushpin: boolean) => undefined; public Delete: () => void = unimplementedFunction; public AddTag: (key: string, value: string) => boolean = returnFalse; public PinToPres: () => void = unimplementedFunction; @@ -76,7 +76,7 @@ export class AnchorMenu extends AntimodeMenu { @action highlightClicked = (e: React.MouseEvent) => { - if (!this.Highlight(this.highlightColor) && this.Pinned) { + if (!this.Highlight(this.highlightColor, false) && this.Pinned) { this.Highlighting = !this.Highlighting; } } diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index bc50d70de..e24821116 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -1119,14 +1119,12 @@ export namespace Doc { export function isDocPinned(doc: Doc) { //add this new doc to props.Document const curPres = Cast(Doc.UserDoc().activePresentation, Doc) as Doc; - if (curPres) { - return DocListCast(curPres.data).findIndex((val) => Doc.AreProtosEqual(val, doc)) !== -1; - } - return false; + return !curPres ? false : DocListCast(curPres.data).findIndex((val) => Doc.AreProtosEqual(val, doc)) !== -1; } export function copyDragFactory(dragFactory: Doc) { const ndoc = dragFactory.isTemplateDoc ? Doc.ApplyTemplate(dragFactory) : Doc.MakeCopy(dragFactory, true); + ndoc && Doc.AddDocToList(Cast(Doc.UserDoc().myFileOrphans, Doc, null), "data", 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); -- cgit v1.2.3-70-g09d2 From 1b481cd441cc8bb200906b246b43e4bc5dc53b4e Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 2 Mar 2021 19:52:59 -0500 Subject: added a fitwidth toggle for lightbox. fixed _showCaption/setting _fields to undefined. updated documentView to use not having fitWidth set as a trigger for whether to treat a doc without nativeWidth/Height as if its width/height is that. --- src/client/documents/Documents.ts | 14 ++-- src/client/views/DocumentDecorations.tsx | 2 +- src/client/views/LightboxView.tsx | 5 ++ src/client/views/PropertiesButtons.tsx | 30 ++++++++- .../views/collections/CollectionStackingView.tsx | 37 ++++++----- .../CollectionMulticolumnView.tsx | 6 +- .../CollectionMultirowView.tsx | 16 ++--- src/client/views/nodes/DocumentView.tsx | 75 +++++++++++++--------- src/client/views/nodes/EquationBox.tsx | 11 ++-- src/client/views/nodes/VideoBox.tsx | 2 +- src/fields/Schema.ts | 5 +- src/fields/util.ts | 2 +- 12 files changed, 125 insertions(+), 80 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index e270d2ac8..f87c7185c 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -830,7 +830,7 @@ export namespace Docs { } export function KVPDocument(document: Doc, options: DocumentOptions = {}) { - return InstanceFromProto(Prototypes.get(DocumentType.KVP), document, { title: document.title + ".kvp", ...options }); + return InstanceFromProto(Prototypes.get(DocumentType.KVP), document, { _fitWidth: true, title: document.title + ".kvp", ...options }); } export function DocumentDocument(document?: Doc, options: DocumentOptions = {}) { @@ -860,23 +860,23 @@ export namespace Docs { } export function CarouselDocument(documents: Array, options: DocumentOptions) { - return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", ...options, _viewType: CollectionViewType.Carousel }); + return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", _fitWidth: true, ...options, _viewType: CollectionViewType.Carousel }); } export function Carousel3DDocument(documents: Array, options: DocumentOptions) { - return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", ...options, _viewType: CollectionViewType.Carousel3D }); + return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", _fitWidth: true, ...options, _viewType: CollectionViewType.Carousel3D }); } export function SchemaDocument(schemaHeaders: SchemaHeaderField[], documents: Array, options: DocumentOptions) { - return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", schemaHeaders: schemaHeaders.length ? new List(schemaHeaders) : undefined, ...options, _viewType: CollectionViewType.Schema }); + return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", _fitWidth: true, schemaHeaders: schemaHeaders.length ? new List(schemaHeaders) : undefined, ...options, _viewType: CollectionViewType.Schema }); } export function TreeDocument(documents: Array, options: DocumentOptions, id?: string) { - return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", dontRegisterChildViews: true, ...options, _viewType: CollectionViewType.Tree }, id); + return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", _fitWidth: true, dontRegisterChildViews: true, ...options, _viewType: CollectionViewType.Tree }, id); } export function StackingDocument(documents: Array, options: DocumentOptions, id?: string, protoId?: string) { - return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", ...options, _viewType: CollectionViewType.Stacking }, id, undefined, protoId); + return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", _fitWidth: true, ...options, _viewType: CollectionViewType.Stacking }, id, undefined, protoId); } export function MulticolumnDocument(documents: Array, options: DocumentOptions) { @@ -926,7 +926,7 @@ export namespace Docs { export function DockDocument(documents: Array, config: string, options: DocumentOptions, id?: string) { const inst = InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { freezeChildren: "remove|add", treeViewDefaultExpandedView: "data", ...options, _viewType: CollectionViewType.Docking, dockingConfig: config }, id); - const tabs = TreeDocument(documents, { title: "On-Screen Tabs", freezeChildren: "remove|add", treeViewLockExpandedView: true, treeViewDefaultExpandedView: "data", system: true }); + const tabs = TreeDocument(documents, { title: "On-Screen Tabs", freezeChildren: "remove|add", treeViewLockExpandedView: true, treeViewDefaultExpandedView: "data", _fitWidth: true, system: true }); const all = TreeDocument([], { title: "Off-Screen Tabs", freezeChildren: "add", treeViewLockExpandedView: true, treeViewDefaultExpandedView: "data", system: true }); Doc.GetProto(inst).data = new List([tabs, all]); return inst; diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 5b7394c42..1e3c0ba92 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -479,7 +479,7 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b SelectionManager.Views().map(dv => { const hgts = this._dragHeights.get(dv.layoutDoc); if (hgts && hgts.lowest < hgts.start && hgts.lowest <= 20) { - dv.nativeWidth > 0 && Doc.toggleNativeDimensions(dv.layoutDoc, dv.ContentScale(), dv.props.PanelWidth(), dv.props.PanelHeight()); + dv.effectiveNativeWidth > 0 && Doc.toggleNativeDimensions(dv.layoutDoc, dv.ContentScale(), dv.props.PanelWidth(), dv.props.PanelHeight()); if (dv.layoutDoc._autoHeight) dv.layoutDoc._autoHeight = false; setTimeout(() => dv.layoutDoc._autoHeight = true); } diff --git a/src/client/views/LightboxView.tsx b/src/client/views/LightboxView.tsx index 15b98467c..3fc72c45c 100644 --- a/src/client/views/LightboxView.tsx +++ b/src/client/views/LightboxView.tsx @@ -247,6 +247,7 @@ export class LightboxView extends React.Component { ContainingCollectionDoc={undefined} renderDepth={0} />
+ {this.navBtn(0, undefined, this.props.PanelHeight / 2 - 12.50, "chevron-left", () => LightboxView.LightboxDoc && LightboxView._history?.length ? "" : "none", e => { e.stopPropagation(); @@ -258,6 +259,10 @@ export class LightboxView extends React.Component { LightboxView.Next(); })} +
{ e.stopPropagation(); LightboxView.LightboxDoc!._fitWidth = !LightboxView.LightboxDoc!._fitWidth }}> + +
; } } diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx index e9963bce9..e418a6f3c 100644 --- a/src/client/views/PropertiesButtons.tsx +++ b/src/client/views/PropertiesButtons.tsx @@ -260,7 +260,10 @@ export class PropertiesButtons extends React.Component<{}, {}> { @undoBatch @action setCaption = () => { - SelectionManager.Views().forEach(dv => dv.rootDoc._showCaption = dv.rootDoc._showCaption === undefined ? "caption" : undefined); + SelectionManager.Views().forEach(dv => { + dv.rootDoc._showCaption = dv.rootDoc._showCaption === undefined ? "caption" : undefined; + console.log("caption = " + dv.rootDoc._showCaption); + }); } @computed @@ -426,6 +429,14 @@ export class PropertiesButtons extends React.Component<{}, {}> { } } + @action @undoBatch + changeFitWidth = () => { + if (this.selectedDoc) { + if (SelectionManager.Views().length) SelectionManager.Views().forEach(dv => dv.rootDoc._fitWidth = !dv.rootDoc._fitWidth); + else this.selectedDoc._fitWidth = !this.selectedDoc._fitWidth; + } + } + @action @undoBatch changeClusters = () => { if (this.selectedDoc) { @@ -448,6 +459,20 @@ export class PropertiesButtons extends React.Component<{}, {}> { ; } + @computed + get fitWidthButton() { + const targetDoc = this.selectedDoc; + return !targetDoc ? (null) :
{this.selectedDoc?._fitWidth ? "Stop Fitting Width" : "Fit Width"}
} placement="top"> +
+
+ +
+
{this.selectedDoc?._fitWidth ? "unfit" : "fit"}
+
+
; + } + @undoBatch @action private makeMask = () => { @@ -521,6 +546,9 @@ export class PropertiesButtons extends React.Component<{}, {}> {
{this.fitContentButton}
+
+ {this.fitWidthButton} +
{this.maskButton}
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index b5ce4b443..7152f4272 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -29,6 +29,7 @@ import "./CollectionStackingView.scss"; import { CollectionStackingViewFieldColumn } from "./CollectionStackingViewFieldColumn"; import { CollectionSubView } from "./CollectionSubView"; import { CollectionViewType } from "./CollectionView"; +import { LightboxView } from "../LightboxView"; const _global = (window /* browser */ || global /* node */) as any; type StackingDocument = makeInterface<[typeof collectionSchema, typeof documentSchema]>; @@ -204,10 +205,10 @@ export class CollectionStackingView extends CollectionSubView this.getDocHeight(doc); - let dref: Opt; + let dref: Opt; const stackedDocTransform = () => this.getDocTransform(doc, dref); this._docXfs.push({ stackedDocTransform, width, height }); - return dref = r?.ContentDiv ? r.ContentDiv : undefined} + return dref = r || undefined} Document={doc} DataDoc={dataDoc || (!Doc.AreProtosEqual(doc[DataSym], doc) && doc[DataSym])} renderDepth={this.props.renderDepth + 1} @@ -247,18 +248,24 @@ export class CollectionStackingView extends CollectionSubView; } + getDocTransform(doc: Doc, dref?: DocumentView) { + const y = this._scroll; // required for document decorations to update when the text box container is scrolled + const { scale, translateX, translateY } = Utils.GetScreenTransform(dref?.ContentDiv || undefined); + // the document view may center its contents and if so, will prepend that onto the screenToLocalTansform. so we have to subtract that off + return new Transform(- translateX - (dref?.centeringX || 0), - translateY - (dref?.centeringY || 0), 1).scale(this.props.ScreenToLocalTransform().Scale * (this.props.scaling?.() || 1)); + } getDocWidth(d?: Doc) { if (!d) return 0; - const layoutDoc = Doc.Layout(d, this.props.childLayoutTemplate?.()); - const nw = Doc.NativeWidth(layoutDoc); - return Math.min(nw && !this.layoutDoc._columnsFill ? d[WidthSym]() : Number.MAX_VALUE, this.columnWidth / this.numGroupColumns); + const childLayoutDoc = Doc.Layout(d, this.props.childLayoutTemplate?.()); + const nw = Doc.NativeWidth(childLayoutDoc) || (childLayoutDoc._fitWidth ? 0 : d[WidthSym]()); + return Math.min(nw && !this.layoutDoc._columnsFill ? (this.props.scaling?.() || 1) * d[WidthSym]() : Number.MAX_VALUE, this.columnWidth / this.numGroupColumns); } getDocHeight(d?: Doc) { if (!d) return 0; const childDataDoc = (!d.isTemplateDoc && !d.isTemplateForField && !d.PARAMS) ? undefined : this.props.DataDoc; const childLayoutDoc = Doc.Layout(d, this.props.childLayoutTemplate?.()); - const nw = Doc.NativeWidth(childLayoutDoc, childDataDoc); - const nh = Doc.NativeHeight(childLayoutDoc, childDataDoc); + const nw = Doc.NativeWidth(childLayoutDoc, childDataDoc) || (childLayoutDoc._fitWidth ? 0 : d[WidthSym]()); + const nh = Doc.NativeHeight(childLayoutDoc, childDataDoc) || (childLayoutDoc._fitWidth ? 0 : d[HeightSym]()); let wid = this.columnWidth / (this.isStackingView ? this.numGroupColumns : 1); if (!this.layoutDoc._columnsFill) wid = Math.min(wid, childLayoutDoc[WidthSym]()); const hllimit = NumCast(this.layoutDoc.childLimitHeight, -1); @@ -268,7 +275,7 @@ export class CollectionStackingView extends CollectionSubView this.isStackingView ? 1 : Math.max(1, Math.min(this.filteredChildren.length, Math.floor((this.props.PanelWidth() - 2 * this.xMargin) / (this.columnWidth + this.gridGap)))); return this.refList.splice(this.refList.indexOf(ref), 1)} - observeHeight={(ref) => { + unobserveHeight={ref => this.refList.splice(this.refList.indexOf(ref), 1)} + observeHeight={ref => { if (ref) { this.refList.push(ref); const doc = this.props.DataDoc && this.props.DataDoc.layout === this.layoutDoc ? this.props.DataDoc : this.layoutDoc; @@ -371,7 +378,9 @@ export class CollectionStackingView extends CollectionSubView NumCast(Doc.Layout(doc)._viewScale, 1) * Number(getComputedStyle(r).height.replace("px", ""))))); - this.props.setHeight(height * NumCast(Doc.Layout(doc)._viewScale, 1)); + if (!LightboxView.IsLightboxDocView(this.props.docViewPath())) { + this.props.setHeight(height * NumCast(Doc.Layout(doc)._viewScale, 1)); + } } })); this.observer.observe(ref); @@ -390,12 +399,6 @@ export class CollectionStackingView extends CollectionSubView; } - getDocTransform(doc: Doc, dref?: HTMLDivElement) { - const y = this._scroll; // required for document decorations to update when the text box container is scrolled - const { scale, translateX, translateY } = Utils.GetScreenTransform(dref); - return new Transform(-translateX, -translateY, 1).scale(this.props.ScreenToLocalTransform().Scale); - } - sectionMasonry = (heading: SchemaHeaderField | undefined, docList: Doc[], first: boolean) => { const key = this.pivotField; let type: "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" | undefined = undefined; diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx index e51417f64..d23f3309e 100644 --- a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx +++ b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx @@ -217,8 +217,8 @@ export class CollectionMulticolumnView extends CollectionSubView(MulticolumnDocu Document={layout} DataDoc={layout.resolvedDataDoc as Doc} styleProvider={this.props.styleProvider} - layerProvider={undefined} - docViewPath={returnEmptyDoclist} + layerProvider={this.props.layerProvider} + docViewPath={this.props.docViewPath} LayoutTemplate={this.props.childLayoutTemplate} LayoutTemplateString={this.props.childLayoutString} freezeDimensions={this.props.childFreezeDimensions} @@ -257,7 +257,7 @@ export class CollectionMulticolumnView extends CollectionSubView(MulticolumnDocu const collector: JSX.Element[] = []; for (let i = 0; i < childLayoutPairs.length; i++) { const { layout } = childLayoutPairs[i]; - const dxf = () => this.lookupIndividualTransform(layout).translate(-NumCast(Document._xMargin), -NumCast(Document._yMargin)); + const dxf = () => this.lookupIndividualTransform(layout).translate(-NumCast(Document._xMargin), -NumCast(Document._yMargin)).scale((this.props.scaling?.() || 1)); const width = () => this.lookupPixels(layout); const height = () => PanelHeight() - 2 * NumCast(Document._yMargin) - (BoolCast(Document.showWidthLabels) ? 20 : 0); collector.push( diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx index d61a2bb72..641ae6ce1 100644 --- a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx +++ b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx @@ -217,8 +217,8 @@ export class CollectionMultirowView extends CollectionSubView(MultirowDocument) Document={layout} DataDoc={layout.resolvedDataDoc as Doc} styleProvider={this.props.styleProvider} - layerProvider={undefined} - docViewPath={returnEmptyDoclist} + layerProvider={this.props.layerProvider} + docViewPath={this.props.docViewPath} LayoutTemplate={this.props.childLayoutTemplate} LayoutTemplateString={this.props.childLayoutString} freezeDimensions={this.props.childFreezeDimensions} @@ -257,19 +257,13 @@ export class CollectionMultirowView extends CollectionSubView(MultirowDocument) const collector: JSX.Element[] = []; for (let i = 0; i < childLayoutPairs.length; i++) { const { layout } = childLayoutPairs[i]; - const dxf = () => this.lookupIndividualTransform(layout).translate(-NumCast(Document._xMargin), -NumCast(Document._yMargin)); + const dxf = () => this.lookupIndividualTransform(layout).translate(-NumCast(Document._xMargin), -NumCast(Document._yMargin)).scale((this.props.scaling?.() || 1)); const height = () => this.lookupPixels(layout); const width = () => PanelWidth() - 2 * NumCast(Document._xMargin) - (BoolCast(Document.showWidthLabels) ? 20 : 0); collector.push( -
+
{this.getDisplayDoc(layout, dxf, width, height)} - +
, { @computed get docViewPath() { return this.props.docViewPath ? [...this.props.docViewPath(), this] : [this]; } @computed get layoutDoc() { 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.props.freezeDimensions)); } - @computed get nativeHeight() { return this.docView?._componentView?.reverseNativeScaling?.() ? 0 : returnVal(this.props.NativeHeight?.(), Doc.NativeHeight(this.layoutDoc, this.props.DataDoc, this.props.freezeDimensions) || 0); } + @computed get nativeWidth() { + return this.docView?._componentView?.reverseNativeScaling?.() ? 0 : + returnVal(this.props.NativeWidth?.(), Doc.NativeWidth(this.layoutDoc, this.props.DataDoc, this.props.freezeDimensions)); + } + @computed get nativeHeight() { + return this.docView?._componentView?.reverseNativeScaling?.() ? 0 : + returnVal(this.props.NativeHeight?.(), Doc.NativeHeight(this.layoutDoc, this.props.DataDoc, this.props.freezeDimensions)); + } + shouldNotScale = () => this.layoutDoc._fitWidth || [CollectionViewType.Docking, CollectionViewType.Tree].includes(this.Document._viewType as any); + @computed get effectiveNativeWidth() { return this.nativeWidth || (this.shouldNotScale() ? 0 : NumCast(this.layoutDoc.width)); } + @computed get effectiveNativeHeight() { return this.nativeHeight || (this.shouldNotScale() ? 0 : NumCast(this.layoutDoc.height)); } @computed get nativeScaling() { - if (this.nativeWidth && (this.layoutDoc?._fitWidth || this.props.PanelHeight() / this.nativeHeight > this.props.PanelWidth() / this.nativeWidth)) { - return this.props.PanelWidth() / this.nativeWidth; // width-limited or fitWidth + const minTextScale = this.Document.type === DocumentType.RTF ? 0.1 : 0; + if (this.effectiveNativeWidth && (this.layoutDoc?._fitWidth || this.props.PanelHeight() / this.effectiveNativeHeight > this.props.PanelWidth() / this.effectiveNativeWidth)) { + return Math.max(minTextScale, this.props.PanelWidth() / this.effectiveNativeWidth); // width-limited or fitWidth } - return this.nativeWidth && this.nativeHeight ? this.props.PanelHeight() / this.nativeHeight : 1; // height-limited or unscaled + return this.effectiveNativeWidth && this.effectiveNativeHeight ? Math.max(minTextScale, this.props.PanelHeight() / this.effectiveNativeHeight) : 1; // height-limited or unscaled } - @computed get panelWidth() { return this.nativeWidth ? this.nativeWidth * this.nativeScaling : this.props.PanelWidth(); } + @computed get panelWidth() { return this.effectiveNativeWidth ? this.effectiveNativeWidth * this.nativeScaling : this.props.PanelWidth(); } @computed get panelHeight() { - if (this.nativeHeight) { + if (this.effectiveNativeHeight) { return Math.min(this.props.PanelHeight(), this.props.Document._fitWidth ? - Math.max(NumCast(this.props.Document._height), NumCast(((this.props.Document.scrollHeight || 0) as number) * this.props.PanelWidth() / this.nativeWidth, this.props.PanelHeight())) : - this.nativeHeight * this.nativeScaling + Math.max(NumCast(this.props.Document._height), NumCast(((this.props.Document.scrollHeight || 0) as number) * this.props.PanelWidth() / this.effectiveNativeWidth, this.props.PanelHeight())) : + this.effectiveNativeHeight * this.nativeScaling ); } return this.props.PanelHeight(); } - @computed get Xshift() { return this.nativeWidth ? (this.props.PanelWidth() - this.nativeWidth * this.nativeScaling) / 2 : 0; } - @computed get YShift() { return this.nativeWidth && this.nativeHeight && Math.abs(this.Xshift) < 0.001 ? (this.props.PanelHeight() - this.nativeHeight * this.nativeScaling) / 2 : 0; } + @computed get Xshift() { return this.effectiveNativeWidth ? (this.props.PanelWidth() - this.effectiveNativeWidth * this.nativeScaling) / 2 : 0; } + @computed get Yshift() { return this.effectiveNativeWidth && this.effectiveNativeHeight && Math.abs(this.Xshift) < 0.001 ? (this.props.PanelHeight() - this.effectiveNativeHeight * this.nativeScaling) / 2 : 0; } @computed get centeringX() { return this.props.dontCenter?.includes("x") ? 0 : this.Xshift; } - @computed get centeringY() { return this.props.Document._fitWidth || this.props.dontCenter?.includes("y") ? 0 : this.YShift; } + @computed get centeringY() { return this.props.Document._fitWidth || this.props.dontCenter?.includes("y") ? 0 : this.Yshift; } toggleNativeDimensions = () => this.docView && Doc.toggleNativeDimensions(this.layoutDoc, this.docView.ContentScale, this.props.PanelWidth(), this.props.PanelHeight()); contentsActive = () => this.docView?.contentsActive(); @@ -1067,8 +1077,8 @@ export class DocumentView extends React.Component { docViewPathFunc = () => this.docViewPath; isSelected = (outsideReaction?: boolean) => SelectionManager.IsSelected(this, outsideReaction); select = (extendSelection: boolean) => SelectionManager.SelectView(this, !SelectionManager.Views().some(v => v.props.Document === this.props.ContainingCollectionDoc) && extendSelection); - NativeWidth = () => this.nativeWidth; - NativeHeight = () => this.nativeHeight; + NativeWidth = () => this.effectiveNativeWidth; + NativeHeight = () => this.effectiveNativeHeight; PanelWidth = () => this.panelWidth; PanelHeight = () => this.panelHeight; ContentScale = () => this.nativeScaling; @@ -1093,31 +1103,32 @@ export class DocumentView extends React.Component { render() { TraceMobx(); - const internalProps = { - ...this.props, - DocumentView: this.selfView, - viewPath: this.docViewPathFunc, - PanelWidth: this.PanelWidth, - PanelHeight: this.PanelHeight, - NativeWidth: this.NativeWidth, - NativeHeight: this.NativeHeight, - isSelected: this.isSelected, - select: this.select, - ContentScaling: this.ContentScale, - ScreenToLocalTransform: this.screenToLocalTransform, - focus: this.props.focus || emptyFunction, - bringToFront: emptyFunction, - }; + const xshift = this.props.Document.isInkMask ? InkingStroke.MaskDim : Math.abs(this.Xshift) <= 0.001 ? this.props.PanelWidth() : undefined; + const yshift = this.props.Document.isInkMask ? InkingStroke.MaskDim : Math.abs(this.Yshift) <= 0.001 ? this.props.PanelHeight() : undefined; return (
{!this.props.Document || !this.props.PanelWidth() ? (null) : (
0.001 ? `${100 * (this.props.PanelWidth() - this.Xshift * 2) / this.props.PanelWidth()}%` : this.props.PanelWidth(), - height: this.props.Document.isInkMask ? InkingStroke.MaskDim : Math.abs(this.YShift) > 0.001 ? this.props.Document._fitWidth ? `${this.panelHeight}px` : `${100 * this.nativeHeight / this.nativeWidth * this.props.PanelWidth() / this.props.PanelHeight()}%` : this.props.PanelHeight(), + width: xshift ?? `${100 * (this.props.PanelWidth() - this.Xshift * 2) / this.props.PanelWidth()}%`, + height: yshift ?? this.props.Document._fitWidth ? `${this.panelHeight}px` : + `${100 * this.effectiveNativeHeight / this.effectiveNativeWidth * this.props.PanelWidth() / this.props.PanelHeight()}%`, }}> - this.docView = r)} /> + this.docView = r)} />
)}
); } diff --git a/src/client/views/nodes/EquationBox.tsx b/src/client/views/nodes/EquationBox.tsx index 7f9fc342a..5bc73d5d9 100644 --- a/src/client/views/nodes/EquationBox.tsx +++ b/src/client/views/nodes/EquationBox.tsx @@ -56,10 +56,13 @@ export class EquationBox extends ViewBoxBaseComponent { this.dataDoc.text = str; - const _height = Number(getComputedStyle(this._ref.current!.element.current).height.replace("px", "")); - const _width = Number(getComputedStyle(this._ref.current!.element.current).width.replace("px", "")); - this.layoutDoc._width = Math.max(35, _width); - this.layoutDoc._height = Math.max(25, _height); + const style = this._ref.current && getComputedStyle(this._ref.current.element.current); + if (style) { + const _height = Number(style.height.replace("px", "")); + const _width = Number(style.width.replace("px", "")); + this.layoutDoc._width = Math.max(35, _width); + this.layoutDoc._height = Math.max(25, _height); + } } render() { TraceMobx(); diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx index 589a6dd24..6afc2258a 100644 --- a/src/client/views/nodes/VideoBox.tsx +++ b/src/client/views/nodes/VideoBox.tsx @@ -482,7 +482,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent this._playing; isActiveChild = () => this._isChildActive; - timelineWhenActiveChanged = (isActive: boolean) => this.props.whenActiveChanged(runInAction(() => this._isChildActive = isActive)); + timelineWhenActiveChanged = action((isActive: boolean) => this.props.whenActiveChanged(this._isChildActive = isActive)); timelineScreenToLocal = () => this.props.ScreenToLocalTransform().scale(this.scaling()).translate(0, -this.heightPercent / 100 * this.props.PanelHeight()); setAnchorTime = (time: number) => this.player!.currentTime = this.layoutDoc._currentTimecode = time; timelineHeight = () => this.props.PanelHeight() * (100 - this.heightPercent) / 100; diff --git a/src/fields/Schema.ts b/src/fields/Schema.ts index 4607e0fd5..78f8a6bfb 100644 --- a/src/fields/Schema.ts +++ b/src/fields/Schema.ts @@ -3,6 +3,7 @@ import { Doc, Field } from "./Doc"; import { ObjectField } from "./ObjectField"; import { RefField } from "./RefField"; import { SelfProxy } from "./FieldSymbols"; +import { List } from "./List"; type AllToInterface = { 1: ToInterface> & AllToInterface>, @@ -67,9 +68,9 @@ export function makeInterface(...schemas: T): InterfaceFu return function (doc?: Doc | Doc[]) { if (doc instanceof Doc || doc === undefined) { return fn(doc || new Doc); - } else { + } else if (doc instanceof List) { return doc.map(fn); - } + } else return {}; }; } diff --git a/src/fields/util.ts b/src/fields/util.ts index 7955fc9fb..36c765dd0 100644 --- a/src/fields/util.ts +++ b/src/fields/util.ts @@ -289,7 +289,7 @@ export function setter(target: any, in_prop: string | symbol | number, value: an // console.log(prop + " is deprecated - switch to _" + prop); // prop = "_" + prop; // } - if (!prop.startsWith("__") && value !== undefined) prop = prop.substring(1); + if (!prop.startsWith("__")) prop = prop.substring(1); if (target.__LAYOUT__) { target.__LAYOUT__[prop] = value; return true; -- cgit v1.2.3-70-g09d2