From 3381bbb0ef5160707513f4bbbe551ca551b64b0d Mon Sep 17 00:00:00 2001 From: bobzel Date: Sat, 13 Nov 2021 10:38:53 -0500 Subject: change isContentActive to a tri-state to allow turning on/off and default - fixes issues with videobox and others so that content can be turned off reliably. added annotation overlay for treeViews for ppt like slides. lots of fixes to tree view to get layout to be more robust. --- src/Utils.ts | 2 +- src/client/documents/Documents.ts | 4 +- src/client/util/CurrentUserUtils.ts | 20 +- src/client/views/DocComponent.tsx | 18 +- src/client/views/DocumentDecorations.scss | 6 +- src/client/views/DocumentDecorations.tsx | 27 +-- src/client/views/MainView.tsx | 6 +- src/client/views/OverlayView.tsx | 2 +- src/client/views/Palette.tsx | 2 +- src/client/views/PropertiesView.tsx | 2 +- .../views/collections/CollectionStackingView.tsx | 2 +- src/client/views/collections/CollectionSubView.tsx | 7 +- .../views/collections/CollectionTreeView.scss | 9 + .../views/collections/CollectionTreeView.tsx | 252 ++++++++++++--------- src/client/views/collections/CollectionView.tsx | 12 +- src/client/views/collections/TabDocView.tsx | 3 +- src/client/views/collections/TreeView.scss | 7 +- src/client/views/collections/TreeView.tsx | 49 ++-- .../collectionFreeForm/CollectionFreeFormView.tsx | 10 +- .../CollectionMulticolumnView.tsx | 4 +- .../CollectionMultirowView.tsx | 4 +- .../collectionMulticolumn/MulticolumnResizer.tsx | 2 +- .../collectionMulticolumn/MultirowResizer.tsx | 2 +- .../collectionSchema/CollectionSchemaHeaders.tsx | 2 +- .../collections/collectionSchema/SchemaTable.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 10 +- src/client/views/nodes/FieldView.tsx | 2 +- src/client/views/nodes/FilterBox.tsx | 2 +- src/client/views/nodes/LinkBox.tsx | 2 +- src/client/views/nodes/LinkDocPreview.tsx | 2 +- src/client/views/nodes/ScreenshotBox.tsx | 2 +- src/client/views/nodes/VideoBox.scss | 10 +- src/client/views/nodes/VideoBox.tsx | 11 +- .../views/nodes/formattedText/FormattedTextBox.tsx | 18 +- src/mobile/AudioUpload.tsx | 2 +- src/mobile/MobileInterface.tsx | 2 +- 36 files changed, 298 insertions(+), 221 deletions(-) (limited to 'src') diff --git a/src/Utils.ts b/src/Utils.ts index bfb29fe8d..ca1432de2 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -448,7 +448,7 @@ export function returnEmptyDoclist() { return [] as any[]; } export let emptyPath = []; -export function emptyFunction() { } +export function emptyFunction() { return undefined; } export function unimplementedFunction() { throw new Error("This function is not implemented, but should be."); } diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index da5c8efa9..219f51a3a 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -94,6 +94,7 @@ type DROPt = DAInfo | dropActionType; export class DocumentOptions { system?: BOOLt = new BoolInfo("is this a system created/owned doc"); _dropAction?: DROPt = new DAInfo("what should happen to this document when it's dropped somewhere else"); + allowOverlayDrop?: BOOLt = new BoolInfo("can documents be dropped onto this document without using dragging title bar or holding down embed key (ctrl)?"); 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 ??? "); color?: string; // foreground color data doc @@ -289,6 +290,7 @@ export class DocumentOptions { treeViewExpandedViewLock?: boolean; // whether the expanded view can be changed treeViewChecked?: ScriptField; // script to call when a tree view checkbox is checked treeViewTruncateTitleWidth?: number; + treeViewHasOverlay?: boolean; // whether the treeview has an overlay for freeform annotations treeViewType?: string; // whether treeview is a Slide, file system, or (default) collection hierarchy sidebarColor?: string; // background color of text sidebar sidebarViewType?: string; // collection type of text sidebar @@ -821,7 +823,7 @@ export namespace Docs { } export function TreeDocument(documents: Array, options: DocumentOptions, id?: string, protoId?: string) { - return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { ...options, _viewType: CollectionViewType.Tree }, id, undefined, protoId); + return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _xMargin: 5, _yMargin: 5, ...options, _viewType: CollectionViewType.Tree }, id, undefined, protoId); } export function StackingDocument(documents: Array, options: DocumentOptions, id?: string, protoId?: string) { diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 9d06ad8a3..c9bef5924 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -339,7 +339,7 @@ export class CurrentUserUtils { const clickTemplates = CurrentUserUtils.setupClickEditorTemplates(doc); if (doc.templateDocs === undefined) { doc.templateDocs = new PrefetchProxy(Docs.Create.TreeDocument([noteTemplates, userTemplateBtns, clickTemplates], { - title: "template layouts", _xPadding: 0, system: true, + title: "template layouts", _xMargin: 0, system: true, dropConverter: ScriptField.MakeScript("convertToButtons(dragData)", { dragData: DragManager.DocumentDragData.name }) })); } @@ -421,7 +421,11 @@ export class CurrentUserUtils { ((doc.emptyPane as Doc).proto as Doc)["dragFactory-count"] = 0; } if (doc.emptySlide === undefined) { - const textDoc = Docs.Create.TreeDocument([], { title: "Slide", _viewType: CollectionViewType.Tree, _fontSize: "20px", _autoHeight: true, treeViewType: "outline", _xMargin: 0, _yMargin: 0, _width: 300, _height: 200, _singleLine: true, backgroundColor: "transparent", system: true, cloneFieldFilter: new List(["system"]) }); + const textDoc = Docs.Create.TreeDocument([], { + title: "Slide", _viewType: CollectionViewType.Tree, treeViewHasOverlay: true, _fontSize: "20px", _autoHeight: true, + allowOverlayDrop: true, treeViewType: "outline", _xMargin: 0, _yMargin: 0, _width: 300, _height: 200, _singleLine: true, + backgroundColor: "transparent", system: true, cloneFieldFilter: new List(["system"]) + }); Doc.GetProto(textDoc).title = ComputedField.MakeFunction('self.text?.Text'); FormattedTextBox.SelectOnLoad = textDoc[Id]; doc.emptySlide = textDoc; @@ -811,7 +815,7 @@ export class CurrentUserUtils { const newDashboardButton: Doc = Docs.Create.FontIconDocument({ onClick: newDashboard, _forceActive: true, toolTip: "Create new dashboard", _stayInCollection: true, _hideContextMenu: true, title: "new dashboard", btnType: ButtonType.ClickButton, _width: 30, _height: 30, buttonText: "New trail", icon: "plus", system: true }); doc.myDashboards = new PrefetchProxy(Docs.Create.TreeDocument([], { title: "My Dashboards", _showTitle: "title", _height: 400, childHideLinkButton: true, freezeChildren: "remove|add", - treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, _forceActive: true, childDropAction: "alias", + treeViewHideTitle: true, _gridGap: 5, _forceActive: true, childDropAction: "alias", treeViewTruncateTitleWidth: 150, ignoreClick: true, buttonMenu: true, buttonMenuDoc: newDashboardButton, _lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "same", treeViewType: "fileSystem", isFolder: true, system: true, explainer: "This is your collection of dashboards. A dashboard represents the tab configuration of your workspace. To manage documents as folders, go to the Files." @@ -840,7 +844,7 @@ export class CurrentUserUtils { const newTrailButton: Doc = Docs.Create.FontIconDocument({ onClick: newTrail, _forceActive: true, toolTip: "Create new trail", _stayInCollection: true, _hideContextMenu: true, title: "New trail", btnType: ButtonType.ClickButton, _width: 30, _height: 30, buttonText: "New trail", icon: "plus", system: true }); doc.myTrails = new PrefetchProxy(Docs.Create.TreeDocument([], { title: "My Trails", _showTitle: "title", _height: 100, - treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _fitWidth: true, _gridGap: 5, _forceActive: true, childDropAction: "alias", + treeViewHideTitle: true, _fitWidth: true, _gridGap: 5, _forceActive: true, childDropAction: "alias", treeViewTruncateTitleWidth: 150, ignoreClick: true, buttonMenu: true, buttonMenuDoc: newTrailButton, _lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "same", system: true, explainer: "All of the trails that you have created will appear here." @@ -865,7 +869,7 @@ export class CurrentUserUtils { }); doc.myFilesystem = new PrefetchProxy(Docs.Create.TreeDocument([doc.myFileOrphans as Doc], { title: "My Documents", _showTitle: "title", buttonMenu: true, buttonMenuDoc: newFolderButton, _height: 100, - treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, _forceActive: true, childDropAction: "alias", + treeViewHideTitle: true, _gridGap: 5, _forceActive: true, childDropAction: "alias", treeViewTruncateTitleWidth: 150, ignoreClick: true, isFolder: true, treeViewType: "fileSystem", childHideLinkButton: true, _lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "proto", system: true, @@ -884,7 +888,7 @@ export class CurrentUserUtils { const clearDocsButton: Doc = Docs.Create.FontIconDocument({ onClick: clearAll, _forceActive: true, toolTip: "Empty recently closed", _stayInCollection: true, _hideContextMenu: true, title: "Empty", btnType: ButtonType.ClickButton, _width: 30, _height: 30, buttonText: "Empty", icon: "trash", system: true }); doc.myRecentlyClosedDocs = new PrefetchProxy(Docs.Create.TreeDocument([], { title: "My Recently Closed", _showTitle: "title", buttonMenu: true, buttonMenuDoc: clearDocsButton, childHideLinkButton: true, - treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, _forceActive: true, childDropAction: "alias", + treeViewHideTitle: true, _gridGap: 5, _forceActive: true, childDropAction: "alias", treeViewTruncateTitleWidth: 150, ignoreClick: true, _lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "same", system: true, explainer: "Recently closed documents appear in this menu. They will only be deleted if you explicity empty this list." @@ -902,7 +906,7 @@ export class CurrentUserUtils { if (doc.currentFilter === undefined) { doc.currentFilter = Docs.Create.FilterDocument({ title: "Unnamed Filter", _height: 150, - treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, _forceActive: true, childDropAction: "none", + treeViewHideTitle: true, _xPadding: 5, _yPadding: 5, _gridGap: 5, _forceActive: true, childDropAction: "none", treeViewTruncateTitleWidth: 150, ignoreClick: true, _lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "same", system: true, _autoHeight: true, _fitWidth: true }); @@ -918,7 +922,7 @@ export class CurrentUserUtils { doc.treeViewOpen = true; doc.treeViewExpandedView = "fields"; doc.myUserDoc = new PrefetchProxy(Docs.Create.TreeDocument([doc], { - treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, _forceActive: true, title: "My UserDoc", _showTitle: "title", + treeViewHideTitle: true, _gridGap: 5, _forceActive: true, title: "My UserDoc", _showTitle: "title", treeViewTruncateTitleWidth: 150, ignoreClick: true, _lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "same", system: true })) as any as Doc; diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index 32c351bf5..b9772fd57 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -44,7 +44,7 @@ interface ViewBoxBaseProps { fieldKey: string; layerProvider?: (doc: Doc, assign?: boolean) => boolean; isSelected: (outsideReaction?: boolean) => boolean; - isContentActive: () => boolean; + isContentActive: () => boolean | undefined; renderDepth: number; rootSelected: (outsideReaction?: boolean) => boolean; } @@ -65,10 +65,12 @@ export function ViewBoxBaseComponent

(schemaCtor: lookupField = (field: string) => ScriptCast(this.layoutDoc.lookupField)?.script.run({ self: this.layoutDoc, data: this.rootDoc, field: field, container: this.props.ContainingCollectionDoc }).result; - isContentActive = (outsideReaction?: boolean) => (CurrentUserUtils.SelectedTool !== InkTool.None || - (this.props.isContentActive?.() || this.props.Document.forceActive || - this.props.isSelected(outsideReaction) || - this.props.rootSelected(outsideReaction)) ? true : false) + isContentActive = (outsideReaction?: boolean) => ( + this.props.isContentActive?.() === false ? false : + (CurrentUserUtils.SelectedTool !== InkTool.None || + (this.props.isContentActive?.() || this.props.Document.forceActive || + this.props.isSelected(outsideReaction) || + this.props.rootSelected(outsideReaction)) ? true : undefined)) protected _multiTouchDisposer?: InteractionUtils.MultiTouchEventDisposer; } return Component; @@ -82,7 +84,7 @@ export interface ViewBoxAnnotatableProps { fieldKey: string; filterAddDocument?: (doc: Doc[]) => boolean; // allows a document that renders a Collection view to filter or modify any documents added to the collection (see PresBox for an example) layerProvider?: (doc: Doc, assign?: boolean) => boolean; - isContentActive: () => boolean; + isContentActive: () => boolean | undefined; select: (isCtrlPressed: boolean) => void; whenChildContentsActiveChanged: (isActive: boolean) => void; isSelected: (outsideReaction?: boolean) => boolean; @@ -165,13 +167,13 @@ export function ViewBoxAnnotatableComponent

boolean, annotationKey?: string): boolean => { + moveDocument = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (doc: Doc | Doc[], annotationKey?: string) => boolean, annotationKey?: string): boolean => { if (Doc.AreProtosEqual(this.props.Document, targetCollection)) { return true; } const first = doc instanceof Doc ? doc : doc[0]; if (!first?._stayInCollection && addDocument !== returnFalse) { - return UndoManager.RunInTempBatch(() => this.removeDocument(doc, annotationKey, true) && addDocument(doc)); + return UndoManager.RunInTempBatch(() => this.removeDocument(doc, annotationKey, true) && addDocument(doc, annotationKey)); } return false; } diff --git a/src/client/views/DocumentDecorations.scss b/src/client/views/DocumentDecorations.scss index d8ad47ecb..82dca1287 100644 --- a/src/client/views/DocumentDecorations.scss +++ b/src/client/views/DocumentDecorations.scss @@ -240,8 +240,10 @@ $linkGap: 3px; text-align: center; display: flex; margin-left: 5px; - height: 22px; + height: 20px; position: absolute; + border-radius: 8px; + background: rgba(159,159,159,0.1); .documentDecorations-titleSpan, .documentDecorations-titleSpan-Dark { @@ -288,7 +290,7 @@ $linkGap: 3px; text-align: center; display: flex; margin-left: 5px; - height: 22px; + height: 20px; position: absolute; .documentDecorations-titleSpan { width: 100%; diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 522995479..1c0b1b995 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -454,17 +454,18 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number, P ); const colorScheme = StrCast(CurrentUserUtils.ActiveDashboard?.colorScheme); - const titleArea = this._edtingTitle ? - this.titleBlur()} - onChange={action(e => this._accumulatedTitle = e.target.value)} - onKeyPress={this.titleEntered} /> : -

- {`${this.selectionTitle}`} -
; + const titleArea = hideTitle ?
: + this._edtingTitle ? + this.titleBlur()} + onChange={action(e => this._accumulatedTitle = e.target.value)} + onKeyPress={this.titleEntered} /> : +
+ {`${this.selectionTitle}`} +
; let inMainMenuPanel = false; for (let node = seldoc.ContentDiv; node && !inMainMenuPanel; node = node?.parentNode as any) { @@ -498,8 +499,8 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number, P top: bounds.y - this._resizeBorderWidth / 2 - this._titleHeight, }}> {!canDelete ?
: topBtn("close", "times", undefined, this.onCloseClick, "Close")} - {hideTitle ? (null) : titleArea}{!canOpen ? (null) : topBtn("open", "external-link-alt", this.onMaximizeDown, undefined, "Open in Tab (ctrl: as alias, shift: in new collection)")} - + {titleArea} + {!canOpen ? (null) : topBtn("open", "external-link-alt", this.onMaximizeDown, undefined, "Open in Tab (ctrl: as alias, shift: in new collection)")} {hideResizers ? (null) : <> {SelectionManager.Views().length !== 1 || hideTitle ? (null) : diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 9a885fbf8..546b0e360 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -511,7 +511,7 @@ export class MainView extends React.Component { bringToFront={emptyFunction} select={emptyFunction} isAnyChildContentActive={returnFalse} - isContentActive={returnFalse} + isContentActive={emptyFunction} isSelected={returnFalse} docViewPath={returnEmptyDoclist} moveDocument={this.moveButtonDoc} @@ -592,7 +592,7 @@ export class MainView extends React.Component { pinToPres={returnFalse} ScreenToLocalTransform={Transform.Identity} bringToFront={returnFalse} - isContentActive={returnFalse} + isContentActive={emptyFunction} whenChildContentsActiveChanged={returnFalse} focus={returnFalse} docViewPath={returnEmptyDoclist} @@ -669,7 +669,7 @@ export class MainView extends React.Component { pinToPres={returnFalse} ScreenToLocalTransform={Transform.Identity} bringToFront={returnFalse} - isContentActive={returnFalse} + isContentActive={emptyFunction} whenChildContentsActiveChanged={returnFalse} focus={returnFalse} PanelWidth={() => 500} diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx index af04b967a..7cf388872 100644 --- a/src/client/views/OverlayView.tsx +++ b/src/client/views/OverlayView.tsx @@ -191,7 +191,7 @@ export class OverlayView extends React.Component { ScreenToLocalTransform={Transform.Identity} renderDepth={1} isDocumentActive={returnTrue} - isContentActive={returnFalse} + isContentActive={emptyFunction} whenChildContentsActiveChanged={emptyFunction} focus={DocUtils.DefaultFocus} styleProvider={DefaultStyleProvider} diff --git a/src/client/views/Palette.tsx b/src/client/views/Palette.tsx index 86ab881bb..529697f71 100644 --- a/src/client/views/Palette.tsx +++ b/src/client/views/Palette.tsx @@ -50,7 +50,7 @@ export default class Palette extends React.Component { PanelHeight={() => window.screen.height} renderDepth={0} isDocumentActive={returnTrue} - isContentActive={returnFalse} + isContentActive={emptyFunction} focus={emptyFunction} docViewPath={returnEmptyDoclist} styleProvider={returnEmptyString} diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index ab9022a84..1083e0075 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -295,7 +295,7 @@ export class PropertiesView extends React.Component { freezeDimensions={true} dontCenter={"y"} isDocumentActive={returnFalse} - isContentActive={returnFalse} + isContentActive={emptyFunction} NativeWidth={layoutDoc.type === DocumentType.RTF ? this.rtfWidth : undefined} NativeHeight={layoutDoc.type === DocumentType.RTF ? this.rtfHeight : undefined} PanelWidth={panelWidth} diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 648ff5087..bffaf86b1 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -226,7 +226,7 @@ export class CollectionStackingView extends CollectionSubView; - SetSubView?: (subView: any) => void; isAnyChildContentActive: () => boolean; } @@ -49,10 +48,6 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T, moreProps?: this.createDashEventsTarget(ele); } - componentDidMount() { - this.props.SetSubView?.(this); - } - componentWillUnmount() { this.gestureDisposer?.(); this._multiTouchDisposer?.(); @@ -220,7 +215,7 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T, moreProps?: const movedDocs = docDragData.droppedDocuments.filter((d, i) => docDragData.draggedDocuments[i] === d); const addedDocs = docDragData.droppedDocuments.filter((d, i) => docDragData.draggedDocuments[i] !== d); if (movedDocs.length) { - const canAdd = this.props.Document._viewType === CollectionViewType.Pile || de.embedKey || !this.props.isAnnotationOverlay || + const canAdd = this.props.Document._viewType === CollectionViewType.Pile || de.embedKey || (!this.props.isAnnotationOverlay || this.props.Document.allowOverlayDrop) || Doc.AreProtosEqual(Cast(movedDocs[0].annotationOn, Doc, null), this.props.Document); added = docDragData.moveDocument(movedDocs, this.props.Document, canAdd ? this.addDocument : returnFalse); } else { diff --git a/src/client/views/collections/CollectionTreeView.scss b/src/client/views/collections/CollectionTreeView.scss index d370d21ab..b664d9d82 100644 --- a/src/client/views/collections/CollectionTreeView.scss +++ b/src/client/views/collections/CollectionTreeView.scss @@ -71,6 +71,15 @@ display: none; } +.collectionTreeView-titleBar { + display: inline-block; + width: 100%; + height: max-content; + .contentFittingDocumentView { + display: block; // makes titleBar take up full width of the treeView (flex doesn't for some reason) + } +} + .collectionTreeView-keyHeader:hover { background: #797777; cursor: pointer; diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 3852987b9..6fb18d4c2 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -1,4 +1,3 @@ -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action, computed, IReactionDisposer, observable, reaction } from "mobx"; import { observer } from "mobx-react"; import { DataSym, Doc, DocListCast, HeightSym, Opt, StrListCast, WidthSym } from '../../../fields/Doc'; @@ -8,13 +7,14 @@ import { Document, listSpec } from '../../../fields/Schema'; import { ScriptField } from '../../../fields/ScriptField'; import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../fields/Types'; import { TraceMobx } from '../../../fields/util'; -import { returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, emptyFunction } from '../../../Utils'; +import { emptyFunction, OmitKeys, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue } from '../../../Utils'; import { DocUtils } from '../../documents/Documents'; import { CurrentUserUtils } from '../../util/CurrentUserUtils'; import { DocumentManager } from '../../util/DocumentManager'; import { DragManager, dropActionType } from "../../util/DragManager"; import { SelectionManager } from '../../util/SelectionManager'; import { SnappingManager } from '../../util/SnappingManager'; +import { Transform } from '../../util/Transform'; import { undoBatch, UndoManager } from '../../util/UndoManager'; import { ContextMenu } from '../ContextMenu'; import { ContextMenuProps } from '../ContextMenuItem'; @@ -22,11 +22,11 @@ import { EditableView } from "../EditableView"; import { DocumentView } from '../nodes/DocumentView'; import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox'; import { StyleProp } from '../StyleProvider'; +import { CollectionFreeFormView } from './collectionFreeForm'; import { CollectionSubView } from "./CollectionSubView"; import "./CollectionTreeView.scss"; import { TreeView } from "./TreeView"; import React = require("react"); -import { Transform } from '../../util/Transform'; const _global = (window /* browser */ || global /* node */) as any; export type collectionTreeViewProps = { @@ -41,10 +41,13 @@ export type collectionTreeViewProps = { @observer export class CollectionTreeView extends CollectionSubView>(Document) { - private treedropDisposer?: DragManager.DragDropDisposer; + private _treedropDisposer?: DragManager.DragDropDisposer; private _mainEle?: HTMLDivElement; + private _titleRef?: HTMLDivElement | HTMLInputElement | null; private _disposers: { [name: string]: IReactionDisposer } = {}; - MainEle = () => this._mainEle; + private _isDisposing = false; // notes that instance is in process of being disposed + private refList: Set = new Set(); // list of tree view items to monitor for height changes + private observer: any; // observer for mnonitoring tree view items. @computed get doc() { return this.props.Document; } @computed get dataDoc() { return this.props.DataDoc || this.doc; } @@ -54,6 +57,10 @@ export class CollectionTreeView extends CollectionSubView this._mainEle; + // these should stay in synch with counterparts in DocComponent.ts ViewBoxAnnotatableComponent @observable _isAnyChildContentActive = false; whenChildContentsActiveChanged = action((isActive: boolean) => this.props.whenChildContentsActiveChanged(this._isAnyChildContentActive = isActive)); @@ -62,11 +69,10 @@ export class CollectionTreeView extends CollectionSubView disposer?.()); } @@ -76,13 +82,13 @@ export class CollectionTreeView extends CollectionSubView = new Set(); - observer: any; computeHeight = () => { - if (this.isDisposing) return; - const bodyHeight = Array.from(this.refList).reduce((p, r) => p + Number(getComputedStyle(r).height.replace("px", "")), this.paddingTop() + this.paddingBot()); - this.layoutDoc._autoHeightMargins = bodyHeight; - this.props.setHeight(this.documentTitleHeight() + bodyHeight); + if (!this._isDisposing) { + const titleHeight = !this._titleRef ? this.marginTop() : Number(getComputedStyle(this._titleRef).height.replace("px", "")); + const bodyHeight = Array.from(this.refList).reduce((p, r) => p + Number(getComputedStyle(r).height.replace("px", "")), this.marginBot()); + this.layoutDoc._autoHeightMargins = bodyHeight; + this.props.setHeight(bodyHeight + titleHeight); + } } unobserveHeight = (ref: any) => { this.refList.delete(ref); @@ -101,8 +107,8 @@ export class CollectionTreeView extends CollectionSubView { - this.treedropDisposer?.(); - if (this._mainEle = ele) this.treedropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this), this.doc, this.onInternalPreDrop.bind(this)); + this._treedropDisposer?.(); + if (this._mainEle = ele) this._treedropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this), this.doc, this.onInternalPreDrop.bind(this)); } protected onInternalPreDrop = (e: Event, de: DragManager.DropEvent, targetAction: dropActionType) => { @@ -165,60 +171,54 @@ export class CollectionTreeView extends CollectionSubView { - return !this.dataDoc ? (null) : - StrCast(this.dataDoc.title)} - SetValue={undoBatch((value: string, shift: boolean, enter: boolean) => { - if (enter && this.props.Document.treeViewType === "outline") this.makeTextCollection(childDocs); - this.dataDoc.title = value; - return true; - })} />; + get editableTitle() { + return StrCast(this.dataDoc.title)} + SetValue={undoBatch((value: string, shift: boolean, enter: boolean) => { + if (enter && this.props.Document.treeViewType === "outline") this.makeTextCollection(this.treeChildren); + this.dataDoc.title = value; + return true; + })} />; } - documentTitle = (childDocs: Doc[]) => { - return
{ - e.stopPropagation(); - e.key === "Enter" && this.makeTextCollection(childDocs); - }}> - -
; + get documentTitle() { + return ; } childContextMenuItems = () => { const customScripts = Cast(this.doc.childContextMenuScripts, listSpec(ScriptField), []); @@ -263,21 +263,31 @@ export class CollectionTreeView extends CollectionSubView this._titleRef = r} + onKeyDown={e => { + if (this.outlineMode) { + e.stopPropagation(); + e.key === "Enter" && this.makeTextCollection(this.treeChildren); + } + }}> + {this.outlineMode ? this.documentTitle : this.editableTitle} +
; + } + + @computed get noviceExplainer() { + return !Doc.UserDoc().noviceMode || !this.rootDoc.explainer ? (null) : +
{this.rootDoc.explainer}
; } return35 = () => 35; @computed get buttonMenu() { - const menuDoc: Doc = Cast(this.rootDoc.buttonMenuDoc, Doc, null); + const menuDoc = Cast(this.rootDoc.buttonMenuDoc, Doc, null); // To create a multibutton menu add a CollectionLinearView - if (menuDoc) { - - const width: number = NumCast(menuDoc._width, 30); - const height: number = NumCast(menuDoc._height, 30); - console.log(menuDoc.title, width, height); - return (
+ return !menuDoc ? null : + (
); - } } - @observable _explainerHeight: number = 0; - @computed get nativeWidth() { return Doc.NativeWidth(this.Document, undefined, true); } @computed get nativeHeight() { return Doc.NativeHeight(this.Document, undefined, true); } @@ -321,47 +328,82 @@ export class CollectionTreeView extends CollectionSubView NumCast(this.doc._xPadding, 15); - paddingTop = () => NumCast(this.doc._yPadding, 20); - paddingBot = () => NumCast(this.doc._yPadding, 20); + marginX = () => NumCast(this.doc._xMargin); + marginTop = () => NumCast(this.doc._yMargin); + marginBot = () => NumCast(this.doc._yMargin); documentTitleWidth = () => Math.min(this.layoutDoc?.[WidthSym](), this.panelWidth()); documentTitleHeight = () => (this.layoutDoc?.[HeightSym]() || 0) - NumCast(this.layoutDoc.autoHeightMargins); titleTransform = () => this.props.ScreenToLocalTransform().translate(-NumCast(this.doc._xPadding, 10), -NumCast(this.doc._yPadding, 20)); truncateTitleWidth = () => this.treeViewtruncateTitleWidth; onChildClick = () => this.props.onChildClick?.() || ScriptCast(this.doc.onChildClick); - panelWidth = () => (this.props.PanelWidth() - 2 * this.paddingX()) * (this.props.scaling?.() || 1); - render() { - TraceMobx(); + panelWidth = () => (this.props.PanelWidth() - 2 * this.marginX()) * (this.props.scaling?.() || 1); + + addAnnotationDocument = (doc: Doc | Doc[]) => this.props.CollectionView?.addDocument(doc, `${this.props.fieldKey}-annotations`) || false; + remAnnotationDocument = (doc: Doc | Doc[]) => this.props.CollectionView?.removeDocument(doc, `${this.props.fieldKey}-annotations`) || false; + moveAnnotationDocument = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (document: Doc | Doc[], annotationKey?: string) => boolean) => + this.props.CollectionView?.moveDocument(doc, targetCollection, addDocument, `${this.props.fieldKey}-annotations`) || false + + contentFunc = () => { const background = () => this.props.styleProvider?.(this.doc, this.props, StyleProp.BackgroundColor); const pointerEvents = () => !this.props.isContentActive() && !SnappingManager.GetIsDragging() ? "none" : undefined; - const buttonMenu = this.rootDoc.buttonMenu; - const noviceExplainer = this.rootDoc.explainer; - - return !(this.doc instanceof Doc) || !this.treeChildren ? (null) : - <> - {this.titleBar} + const titleBar = this.props.treeViewHideTitle || this.doc.treeViewHideTitle ? (null) : this.titleBar; + return [ +
+ {titleBar}
- {buttonMenu || noviceExplainer ?
r && (this._explainerHeight = r.getBoundingClientRect().height))}> - {buttonMenu ? this.buttonMenu : null} - {Doc.UserDoc().noviceMode && noviceExplainer ? -
- {noviceExplainer} -
- : null - } -
: null} + {!this.buttonMenu && !this.noviceExplainer ? (null) : +
r && (this._explainerHeight = r.getBoundingClientRect().height))}> + {this.buttonMenu} + {this.noviceExplainer} +
+ }
e.stopPropagation()} onDrop={this.onTreeDrop} - ref={this.createTreeDropTarget}> + ref={r => !this.doc.treeViewHasOverlay && r && this.createTreeDropTarget(r)}>
    {this.treeViewElements}
- ; +
+ ]; + } + render() { + TraceMobx(); + + return !(this.doc instanceof Doc) || !this.treeChildren ? (null) : + this.doc.treeViewHasOverlay ? + + {this.contentFunc} + : + this.contentFunc(); } } \ No newline at end of file diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 38e027fb3..8e84b59de 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -63,6 +63,7 @@ export enum CollectionViewType { } export interface CollectionViewProps extends FieldViewProps { isAnnotationOverlay?: boolean; // is the collection an annotation overlay (eg an overlay on an image/video/etc) + isAnnotationOverlayScrollable?: boolean; // whether the annotation overlay can be vertically scrolled (just for tree views, currently) layoutEngine?: () => string; setPreviewCursor?: (func: (x: number, y: number, drag: boolean, hide: boolean) => void) => void; @@ -125,8 +126,9 @@ export class CollectionView extends ViewBoxAnnotatableComponent this.props.renderDepth ? this.props.ScreenToLocalTransform() : this.props.ScreenToLocalTransform().scale(this.props.PanelWidth() / this.bodyPanelWidth()); - private SubView = (type: CollectionViewType, props: SubCollectionViewProps) => { + private renderSubView = (type: CollectionViewType | undefined, props: SubCollectionViewProps) => { TraceMobx(); + if (type === undefined) return null; switch (type) { default: case CollectionViewType.Freeform: return ; @@ -246,17 +248,13 @@ export class CollectionView extends ViewBoxAnnotatableComponent this.props.childLayoutTemplate?.() || Cast(this.rootDoc.childLayoutTemplate, Doc, null); @computed get childLayoutString() { return StrCast(this.rootDoc.childLayoutString); } - - @observable _subView: any = undefined; - isContentActive = (outsideReaction?: boolean) => { - return this.props.isContentActive() ? true : false; + return this.props.isContentActive(); } render() { TraceMobx(); const props: SubCollectionViewProps = { ...this.props, - SetSubView: action((subView: any) => this._subView = subView), addDocument: this.addDocument, moveDocument: this.moveDocument, removeDocument: this.removeDocument, @@ -273,7 +271,7 @@ export class CollectionView extends ViewBoxAnnotatableComponent {this.showIsTagged()} - {this.collectionViewType !== undefined ? this.SubView(this.collectionViewType, props) : (null)} + {this.renderSubView(this.collectionViewType, props)}
); } } diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx index eb95bb913..5ba019698 100644 --- a/src/client/views/collections/TabDocView.tsx +++ b/src/client/views/collections/TabDocView.tsx @@ -476,7 +476,6 @@ export class TabMinimapView extends React.Component {
this} CollectionView={undefined} ContainingCollectionView={undefined} ContainingCollectionDoc={undefined} @@ -484,7 +483,7 @@ export class TabMinimapView extends React.Component { 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} - isContentActive={returnFalse} + isContentActive={emptyFunction} isAnyChildContentActive={returnFalse} select={emptyFunction} dropAction={undefined} diff --git a/src/client/views/collections/TreeView.scss b/src/client/views/collections/TreeView.scss index 1ebc5873e..2e33d3564 100644 --- a/src/client/views/collections/TreeView.scss +++ b/src/client/views/collections/TreeView.scss @@ -53,14 +53,11 @@ } } +.treeView-container-outline-active .treeView-container-active { z-index: 100; position: relative; - - .formattedTextbox-sidebar { - background-color: #ffff001f !important; - height: 500px !important; - } + pointer-events: all; } .treeView-openRight { diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index 7f2128230..a266c301f 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -81,7 +81,7 @@ export class TreeView extends React.Component { static _openLevelScript: Opt; private _header: React.RefObject = React.createRef(); private _tref = React.createRef(); - private _docRef: Opt; + @observable _docRef: Opt; private _selDisposer: Opt; private _editTitleScript: (() => ScriptField) | undefined; private _openScript: (() => ScriptField) | undefined; @@ -116,7 +116,8 @@ export class TreeView extends React.Component { @computed get childLinks() { return this.childDocList("links"); } @computed get childAliases() { return this.childDocList("aliases"); } @computed get childAnnos() { return this.childDocList(this.fieldKey + "-annotations"); } - @computed get selected() { return SelectionManager.Views().lastElement()?.props.Document === this.props.document; } + @computed get selected() { return SelectionManager.IsSelected(this._docRef); } + // SelectionManager.Views().lastElement()?.props.Document === this.props.document; } childDocList(field: string) { const layout = Cast(Doc.LayoutField(this.doc), Doc, null); @@ -125,7 +126,12 @@ export class TreeView extends React.Component { DocListCastOrNull(this.doc[field]); // 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); + if (this.doc !== target && addDoc !== returnFalse) { // bcz: this should all be running in a Temp undo batch instead of hackily testing for returnFalse + if (this.props.removeDoc?.(doc) === true) { + return addDoc(doc); + } + } + return false; } @undoBatch @action remove = (doc: Doc | Doc[], key: string) => { this.props.treeView.props.select(false); @@ -141,8 +147,10 @@ export class TreeView extends React.Component { this._editTitle = false; } else if (docView.isSelected()) { + const doc = docView.Document; + SelectionManager.SelectSchemaViewDoc(doc); this._editTitle = true; - this._selDisposer = reaction(() => docView.isSelected(), sel => !sel && this.setEditTitle(undefined)); + this._selDisposer = reaction(() => SelectionManager.SelectedSchemaDoc(), seldoc => seldoc !== doc && this.setEditTitle(undefined)); } else { docView.select(false); } @@ -222,7 +230,7 @@ export class TreeView extends React.Component { public static makeTextBullet() { const bullet = Docs.Create.TextDocument("-text-", { layout: CollectionView.LayoutString("data"), - title: "-title-", "sidebarColor": "transparent", "sidebarViewType": CollectionViewType.Freeform, + title: "-title-", treeViewExpandedViewLock: true, treeViewExpandedView: "data", _viewType: CollectionViewType.Tree, hideLinkButton: true, _showSidebar: true, treeViewType: "outline", x: 0, y: 0, _xMargin: 0, _yMargin: 0, _autoHeight: true, _singleLine: true, backgroundColor: "transparent", _width: 1000, _height: 10 @@ -266,23 +274,25 @@ export class TreeView extends React.Component { e.stopPropagation(); } const docDragData = de.complete.docDragData; - if (docDragData) { - e.stopPropagation(); + if (docDragData && pt[0] < rect.left + rect.width) { if (docDragData.draggedDocuments[0] === this.doc) return true; - this.dropDocuments(docDragData.droppedDocuments, before, inside, docDragData.dropAction, docDragData.moveDocument, docDragData.treeViewDoc === this.props.treeView.props.Document); + if (this.dropDocuments(docDragData.droppedDocuments, before, inside, docDragData.dropAction, docDragData.moveDocument, docDragData.treeViewDoc === this.props.treeView.props.Document)) { + e.stopPropagation(); + } } } dropDocuments(droppedDocuments: Doc[], before: boolean, inside: number | boolean, dropAction: dropActionType, moveDocument: DragManager.MoveFunction | undefined, forceAdd: boolean) { const parentAddDoc = (doc: Doc | Doc[]) => this.props.addDocument(doc, undefined, before); - const canAdd = !StrCast((inside ? this.props.document : this.props.containerCollection)?.freezeChildren).includes("add") || forceAdd; + const canAdd = (!this.props.treeView.outlineMode && !StrCast((inside ? this.props.document : this.props.containerCollection)?.freezeChildren).includes("add")) || forceAdd; const localAdd = (doc: Doc) => Doc.AddDocToList(this.dataDoc, this.fieldKey, doc) && ((doc.context = this.doc.context) || true) ? true : false; const addDoc = !inside ? parentAddDoc : (doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && localAdd(doc), true as boolean); const move = (!dropAction || dropAction === "proto" || dropAction === "move" || dropAction === "same") && moveDocument; if (canAdd) { - UndoManager.RunInTempBatch(() => droppedDocuments.reduce((added, d) => (move ? move(d, undefined, addDoc) || (dropAction === "proto" ? addDoc(d) : false) : addDoc(d)) || added, false)); + return UndoManager.RunInTempBatch(() => droppedDocuments.reduce((added, d) => (move ? move(d, undefined, addDoc) || (dropAction === "proto" ? addDoc(d) : false) : addDoc(d)) || added, false)); } + return false; } refTransform = (ref: HTMLDivElement | undefined | null) => { @@ -432,7 +442,7 @@ export class TreeView extends React.Component {
; } - return
    {this.renderEmbeddedDocument(false)}
; // "layout" + return
    { e.preventDefault(); e.stopPropagation(); }}>{this.renderEmbeddedDocument(false, returnFalse)}
; // "layout" } get onCheckedClick() { return this.doc.type === DocumentType.COL ? undefined : this.props.onCheckedClick?.() ?? ScriptCast(this.doc.onCheckedClick); } @@ -581,6 +591,7 @@ export class TreeView extends React.Component { } titleWidth = () => Math.max(20, Math.min(this.props.treeView.truncateTitleWidth(), this.props.panelWidth() - 2 * treeBulletWidth())); + return18 = () => 18; /** * Renders the EditableView title element for placement into the tree. */ @@ -636,10 +647,10 @@ export class TreeView extends React.Component { moveDocument={this.move} removeDocument={this.props.removeDoc} ScreenToLocalTransform={this.getTransform} - NativeHeight={() => 18} + NativeHeight={this.return18} NativeWidth={this.titleWidth} PanelWidth={this.titleWidth} - PanelHeight={() => 18} + PanelHeight={this.return18} contextMenuItems={this.contextMenuItems} renderDepth={1} isContentActive={this.props.isContentActive} @@ -679,6 +690,7 @@ export class TreeView extends React.Component { renderBulletHeader = (contents: JSX.Element, editing: boolean) => { return <>
{ } - renderEmbeddedDocument = (asText: boolean) => { + renderEmbeddedDocument = (asText: boolean, isActive: () => boolean | undefined) => { const layout = StrCast(Doc.LayoutField(this.layoutDoc)); const isExpandable = layout.includes(FormattedTextBox.name) || layout.includes(SliderBox.name); const panelWidth = asText || isExpandable ? this.rtfWidth : this.expandPanelWidth; @@ -704,8 +716,8 @@ export class TreeView extends React.Component { NativeWidth={!asText && (this.layoutDoc.type === DocumentType.RTF || this.layoutDoc.type === DocumentType.SLIDER) ? this.rtfWidth : undefined} NativeHeight={!asText && (this.layoutDoc.type === DocumentType.RTF || this.layoutDoc.type === DocumentType.SLIDER) ? this.rtfHeight : undefined} LayoutTemplateString={asText ? FormattedTextBox.LayoutString("text") : undefined} - isContentActive={asText ? this.props.isContentActive : returnFalse} - isDocumentActive={asText ? this.props.isContentActive : returnFalse} + isContentActive={isActive} + isDocumentActive={isActive} styleProvider={asText ? this.titleStyleProvider : this.embeddedStyleProvider} hideTitle={asText} fitContentsToDoc={returnTrue} @@ -749,7 +761,7 @@ export class TreeView extends React.Component { @computed get renderDocumentAsHeader() { return <> {this.renderBullet} - {this.renderEmbeddedDocument(true)} + {this.renderEmbeddedDocument(true, this.props.isContentActive)} ; } @@ -776,13 +788,12 @@ export class TreeView extends React.Component { return this.props.renderedIds.indexOf(this.doc[Id]) !== -1 ? "<" + this.doc.title + ">" : // just print the title of documents we've previously rendered in this hierarchical path to avoid cycles
this.props.isContentActive(true) && SelectionManager.DeselectAll()} // bcz: this breaks entering a text filter in a filterBox since it deselects the filter's target document onKeyDown={this.onKeyDown}>
  • {hideTitle && this.doc.type !== DocumentType.RTF ? - this.renderEmbeddedDocument(false) : + this.renderEmbeddedDocument(false, returnFalse) : this.renderBulletHeader(hideTitle ? this.renderDocumentAsHeader : this.renderTitleAsHeader, this._editTitle)}
  • ; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 37caf508f..190d0e76a 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -165,7 +165,7 @@ export class CollectionFreeFormView extends CollectionSubView this.freeformData()?.bounds.cx ?? NumCast(this.Document._panX); panY = () => this.freeformData()?.bounds.cy ?? NumCast(this.Document._panY); zoomScaling = () => (this.freeformData()?.scale ?? NumCast(this.Document[this.scaleFieldKey], 1)); - contentTransform = () => `translate(${this.cachedCenteringShiftX}px, ${this.cachedCenteringShiftY}px) scale(${this.zoomScaling()}) translate(${-this.panX()}px, ${-this.panY()}px)`; + contentTransform = () => !this.cachedCenteringShiftX && !this.cachedCenteringShiftY && this.zoomScaling() === 1 ? "" : `translate(${this.cachedCenteringShiftX}px, ${this.cachedCenteringShiftY}px) scale(${this.zoomScaling()}) translate(${-this.panX()}px, ${-this.panY()}px)`; getTransform = () => this.cachedGetTransform.copy(); getLocalTransform = () => this.cachedGetLocalTransform.copy(); getContainerTransform = () => this.cachedGetContainerTransform.copy(); @@ -802,7 +802,7 @@ export class CollectionFreeFormView extends CollectionSubView boolean; + isContentActive?: () => boolean | undefined; columnUnitLength(): number | undefined; toLeft?: Doc; toRight?: Doc; diff --git a/src/client/views/collections/collectionMulticolumn/MultirowResizer.tsx b/src/client/views/collections/collectionMulticolumn/MultirowResizer.tsx index 5478bf709..006ef4df6 100644 --- a/src/client/views/collections/collectionMulticolumn/MultirowResizer.tsx +++ b/src/client/views/collections/collectionMulticolumn/MultirowResizer.tsx @@ -11,7 +11,7 @@ import { StyleProviderFunc } from "../../nodes/DocumentView"; interface ResizerProps { height: number; styleProvider?: StyleProviderFunc; - isContentActive?: () => boolean; + isContentActive?: () => boolean | undefined; columnUnitLength(): number | undefined; toTop?: Doc; toBottom?: Doc; diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaHeaders.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaHeaders.tsx index 1306b79cb..dc35b5749 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaHeaders.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaHeaders.tsx @@ -225,7 +225,7 @@ export interface KeysDropdownProps { fieldKey: string; ContainingCollectionDoc: Doc | undefined; ContainingCollectionView: Opt; - active?: (outsideReaction?: boolean) => boolean; + active?: (outsideReaction?: boolean) => boolean | undefined; openHeader: (column: any, screenx: number, screeny: number) => void; col: SchemaHeaderField; icon: IconProp; diff --git a/src/client/views/collections/collectionSchema/SchemaTable.tsx b/src/client/views/collections/collectionSchema/SchemaTable.tsx index bc5a9559f..2219345f6 100644 --- a/src/client/views/collections/collectionSchema/SchemaTable.tsx +++ b/src/client/views/collections/collectionSchema/SchemaTable.tsx @@ -68,7 +68,7 @@ export interface SchemaTableProps { addDocument?: (document: Doc | Doc[]) => boolean; moveDocument?: (document: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (document: Doc | Doc[]) => boolean) => boolean; ScreenToLocalTransform: () => Transform; - active: (outsideReaction: boolean | undefined) => boolean; + active: (outsideReaction: boolean | undefined) => boolean | undefined; onDrop: (e: React.DragEvent, options: DocumentOptions, completed?: (() => void) | undefined) => void; addDocTab: (document: Doc, where: string) => boolean; pinToPres: (document: Doc) => void; diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 6c058ff97..c8a32a911 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -138,6 +138,7 @@ export interface DocumentViewSharedProps { hideLinkButton?: boolean; hideCaptions?: boolean; ignoreAutoHeight?: boolean; + forceAutoHeight?: boolean; disableDocBrushing?: boolean; // should highlighting for this view be disabled when same document in another view is hovered over. pointerEvents?: string; scriptContext?: any; // can be assigned anything and will be passed as 'scriptContext' to any OnClick script that executes on this document @@ -224,7 +225,7 @@ export class DocumentViewInternal extends DocComponent Doc, forward?: () => boolean, back?: () => boolean }) => this._componentView = view); isContentActive = (outsideReaction?: boolean) => { - return CurrentUserUtils.SelectedTool !== InkTool.None || + return this.props.isContentActive() === false ? false : ( + CurrentUserUtils.SelectedTool !== InkTool.None || SnappingManager.GetIsDragging() || this.props.rootSelected() || this.props.Document.forceActive || this.props.isSelected(outsideReaction) || this._componentView?.isAnyChildContentActive?.() || - this.props.isContentActive() ? true : false; + this.props.isContentActive()) ? true : undefined; } @computed get contents() { TraceMobx(); @@ -1256,7 +1258,7 @@ export class DocumentView extends React.Component { position: this.props.Document.isInkMask ? "absolute" : undefined, transform: isButton ? undefined : `translate(${this.centeringX}px, ${this.centeringY}px)`, width: isButton ? "100%" : xshift() ?? `${100 * (this.props.PanelWidth() - this.Xshift * 2) / this.props.PanelWidth()}%`, - height: isButton ? undefined : yshift() ?? (this.fitWidth ? `${this.panelHeight}px` : + height: isButton || this.props.forceAutoHeight ? undefined : yshift() ?? (this.fitWidth ? `${this.panelHeight}px` : `${100 * this.effectiveNativeHeight / this.effectiveNativeWidth * this.props.PanelWidth() / this.props.PanelHeight()}%`), }}> void; - isContentActive: (outsideReaction?: boolean) => boolean; + isContentActive: (outsideReaction?: boolean) => boolean | undefined; isDocumentActive?: () => boolean; isSelected: (outsideReaction?: boolean) => boolean; scaling?: () => number; diff --git a/src/client/views/nodes/FilterBox.tsx b/src/client/views/nodes/FilterBox.tsx index 2041c7399..fb8e89da9 100644 --- a/src/client/views/nodes/FilterBox.tsx +++ b/src/client/views/nodes/FilterBox.tsx @@ -225,7 +225,7 @@ export class FilterBox extends ViewBoxBaseComponent(LinkDocument) { public static LayoutString(fieldKey: string) { return FieldView.LayoutString(LinkBox, fieldKey); } - isContentActiveFunc = () => this.isContentActive() ? true : false; + isContentActiveFunc = () => this.isContentActive(); render() { if (this.dataDoc.treeViewOpen === undefined) setTimeout(() => this.dataDoc.treeViewOpen = true); return
    { docViewPath={returnEmptyDoclist} ScreenToLocalTransform={Transform.Identity} isDocumentActive={returnFalse} - isContentActive={returnFalse} + isContentActive={emptyFunction} addDocument={returnFalse} removeDocument={returnFalse} addDocTab={returnFalse} diff --git a/src/client/views/nodes/ScreenshotBox.tsx b/src/client/views/nodes/ScreenshotBox.tsx index 7ad96bf05..0c631e5f9 100644 --- a/src/client/views/nodes/ScreenshotBox.tsx +++ b/src/client/views/nodes/ScreenshotBox.tsx @@ -313,7 +313,7 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponentLoading
    : -
    -
    +
    +