From a38501569769c00dc1c25fb57d09ca88f3951c3d Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 24 Aug 2021 12:21:01 -0400 Subject: from last --- src/client/views/collections/CollectionSubView.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/client/views/collections/CollectionSubView.tsx') diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 2f07c0241..c7629acbe 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -1,6 +1,6 @@ import { action, computed, IReactionDisposer, reaction, observable, runInAction } from "mobx"; import CursorField from "../../../fields/CursorField"; -import { Doc, Opt, Field, DocListCast, AclPrivate } from "../../../fields/Doc"; +import { Doc, Opt, Field, DocListCast, AclPrivate, StrListCast } from "../../../fields/Doc"; import { Id, ToString } from "../../../fields/FieldSymbols"; import { List } from "../../../fields/List"; import { listSpec } from "../../../fields/Schema"; @@ -88,7 +88,7 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T, moreProps?: get childDocList() { return Cast(this.dataField, listSpec(Doc)); } - collectionFilters = () => this._focusFilters ?? Cast(this.props.Document._docFilters, listSpec("string"), []); + collectionFilters = () => this._focusFilters ?? StrListCast(this.props.Document._docFilters); collectionRangeDocFilters = () => this._focusRangeFilters ?? Cast(this.props.Document._docRangeFilters, listSpec("string"), []); childDocFilters = () => [...this.props.docFilters(), ...this.collectionFilters()]; childDocRangeFilters = () => [...(this.props.docRangeFilters?.() || []), ...this.collectionRangeDocFilters()]; -- cgit v1.2.3-70-g09d2 From 66dd6788fbf46cd827d80eb97810e4d2af24eb26 Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 24 Aug 2021 14:52:35 -0400 Subject: suppressed filter icon for annotations that are filtered based on transparency. fixed drawing ink on webbox's. --- src/client/views/collections/CollectionSubView.tsx | 2 +- src/client/views/nodes/WebBox.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/client/views/collections/CollectionSubView.tsx') diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index c7629acbe..55b1e4031 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -93,7 +93,7 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T, moreProps?: childDocFilters = () => [...this.props.docFilters(), ...this.collectionFilters()]; childDocRangeFilters = () => [...(this.props.docRangeFilters?.() || []), ...this.collectionRangeDocFilters()]; IsFiltered = () => this.collectionFilters().length || this.collectionRangeDocFilters().length ? "hasFilter" : - this.props.docFilters().length || this.props.docRangeFilters().length ? "inheritsFilter" : undefined + this.props.docFilters().filter(f => !f.includes("__value__")).length || this.props.docRangeFilters().length ? "inheritsFilter" : undefined searchFilterDocs = () => this.props.searchFilterDocs?.() ?? DocListCast(this.props.Document._searchFilterDocs); @computed.struct get childDocs() { TraceMobx(); diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index 94697464a..cdc79678a 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -534,7 +534,7 @@ export class WebBox extends ViewBoxAnnotatableComponent; + pointerEvents={CurrentUserUtils.SelectedTool !== InkTool.None || this._isAnnotating || SnappingManager.GetIsDragging() ? "all" : "none"} />; return (
-- cgit v1.2.3-70-g09d2 From fe818efd80e649b841009b69841b176cee4c5c8c Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 25 Aug 2021 11:53:49 -0400 Subject: cleaned up and fixed tests for nonrecursive doc filters as used in PDF/Web to separate transparent from non-transparent docs into layers. --- src/Utils.ts | 12 +++++- src/client/views/collections/CollectionSubView.tsx | 48 ++++++++++++---------- .../collectionFreeForm/CollectionFreeFormView.tsx | 4 +- src/client/views/nodes/WebBox.tsx | 14 ++++--- src/client/views/pdf/PDFViewer.tsx | 14 ++++--- src/fields/Doc.ts | 2 +- 6 files changed, 58 insertions(+), 36 deletions(-) (limited to 'src/client/views/collections/CollectionSubView.tsx') diff --git a/src/Utils.ts b/src/Utils.ts index f90296121..5d86c755a 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -115,13 +115,21 @@ export namespace Utils { return { r: r, g: g, b: b, a: a }; } + const isTransparentFunctionHack = "isTransparent(__value__)"; + const noRecursionHack = "__noRecursion"; + export function IsRecursiveFilter(val: string) { + return !val.includes(noRecursionHack); + } + export function HasTransparencyFilter(val: string) { + return val.includes(isTransparentFunctionHack); + } export function IsTransparentFilter() { // bcz: isTransparent(__value__) is a hack. it would be nice to have acual functions be parsed, but now Doc.matchFieldValue is hardwired to recognize just this one - return ["backgroundColor:isTransparent(__value__):check"]; + return `backgroundColor:${isTransparentFunctionHack},${noRecursionHack}:check`;// bcz: hack. noRecursion should probably be either another ':' delimited field, or it should be a modifier to the comparision (eg., check, x, etc) field } export function IsOpaqueFilter() { // bcz: isTransparent(__value__) is a hack. it would be nice to have acual functions be parsed, but now Doc.matchFieldValue is hardwired to recognize just this one - return ["backgroundColor:isTransparent(__value__):x"]; + return `backgroundColor:${isTransparentFunctionHack},${noRecursionHack}:x`;// bcz: hack. noRecursion should probably be either another ':' delimited field, or it should be a modifier to the comparision (eg., check, x, etc) field } diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 55b1e4031..1f4c35daa 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -90,10 +90,11 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T, moreProps?: } collectionFilters = () => this._focusFilters ?? StrListCast(this.props.Document._docFilters); collectionRangeDocFilters = () => this._focusRangeFilters ?? Cast(this.props.Document._docRangeFilters, listSpec("string"), []); - childDocFilters = () => [...this.props.docFilters(), ...this.collectionFilters()]; + childDocFilters = () => [...(this.props.docFilters?.().filter(f => Utils.IsRecursiveFilter(f)) || []), ...this.collectionFilters()]; + unrecursiveDocFilters = () => [...(this.props.docFilters?.().filter(f => !Utils.IsRecursiveFilter(f)) || [])]; childDocRangeFilters = () => [...(this.props.docRangeFilters?.() || []), ...this.collectionRangeDocFilters()]; IsFiltered = () => this.collectionFilters().length || this.collectionRangeDocFilters().length ? "hasFilter" : - this.props.docFilters().filter(f => !f.includes("__value__")).length || this.props.docRangeFilters().length ? "inheritsFilter" : undefined + this.props.docFilters?.().filter(f => Utils.IsRecursiveFilter(f)).length || this.props.docRangeFilters().length ? "inheritsFilter" : undefined searchFilterDocs = () => this.props.searchFilterDocs?.() ?? DocListCast(this.props.Document._searchFilterDocs); @computed.struct get childDocs() { TraceMobx(); @@ -113,10 +114,10 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T, moreProps?: const viewSpecScript = Cast(this.props.Document.viewSpecScript, ScriptField); const childDocs = viewSpecScript ? docs.filter(d => viewSpecScript.script.run({ doc: d }, console.log).result) : docs; - const docFilters = this.childDocFilters(); + const childDocFilters = this.childDocFilters(); const docRangeFilters = this.childDocRangeFilters(); const searchDocs = this.searchFilterDocs(); - if (this.props.Document.dontRegisterView || (!docFilters.length && !docRangeFilters.length && !searchDocs.length)) { + if (this.props.Document.dontRegisterView || (!childDocFilters.length && !this.unrecursiveDocFilters().length && !docRangeFilters.length && !searchDocs.length)) { return childDocs.filter(cd => !cd.cookies); // remove any documents that require a cookie if there are no filters to provide one } @@ -127,24 +128,27 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T, moreProps?: const docsforFilter: Doc[] = []; childDocs.forEach((d) => { // if (DocUtils.Excluded(d, docFilters)) return; - let notFiltered = d.z || Doc.IsSystem(d) || ((!searchDocs.length || searchDocs.includes(d)) && (DocUtils.FilterDocs([d], docFilters, docRangeFilters, viewSpecScript, this.props.Document).length > 0)); - const fieldKey = Doc.LayoutFieldKey(d); - const annos = !Field.toString(Doc.LayoutField(d) as Field).includes("CollectionView"); - const data = d[annos ? fieldKey + "-annotations" : fieldKey]; - if (data !== undefined) { - let subDocs = DocListCast(data); - if (subDocs.length > 0) { - let newarray: Doc[] = []; - notFiltered = notFiltered || (!searchDocs.length && DocUtils.FilterDocs(subDocs, docFilters, docRangeFilters, viewSpecScript, d).length); - while (subDocs.length > 0 && !notFiltered) { - newarray = []; - subDocs.forEach((t) => { - const fieldKey = Doc.LayoutFieldKey(t); - const annos = !Field.toString(Doc.LayoutField(t) as Field).includes("CollectionView"); - notFiltered = notFiltered || ((!searchDocs.length || searchDocs.includes(t)) && ((!docFilters.length && !docRangeFilters.length) || DocUtils.FilterDocs([t], docFilters, docRangeFilters, viewSpecScript, d).length)); - DocListCast(t[annos ? fieldKey + "-annotations" : fieldKey]).forEach((newdoc) => newarray.push(newdoc)); - }); - subDocs = newarray; + let notFiltered = d.z || Doc.IsSystem(d) || (DocUtils.FilterDocs([d], this.unrecursiveDocFilters(), docRangeFilters, viewSpecScript, this.props.Document).length > 0); + if (notFiltered) { + notFiltered = ((!searchDocs.length || searchDocs.includes(d)) && (DocUtils.FilterDocs([d], childDocFilters, docRangeFilters, viewSpecScript, this.props.Document).length > 0)); + const fieldKey = Doc.LayoutFieldKey(d); + const annos = !Field.toString(Doc.LayoutField(d) as Field).includes("CollectionView"); + const data = d[annos ? fieldKey + "-annotations" : fieldKey]; + if (data !== undefined) { + let subDocs = DocListCast(data); + if (subDocs.length > 0) { + let newarray: Doc[] = []; + notFiltered = notFiltered || (!searchDocs.length && DocUtils.FilterDocs(subDocs, childDocFilters, docRangeFilters, viewSpecScript, d).length); + while (subDocs.length > 0 && !notFiltered) { + newarray = []; + subDocs.forEach((t) => { + const fieldKey = Doc.LayoutFieldKey(t); + const annos = !Field.toString(Doc.LayoutField(t) as Field).includes("CollectionView"); + notFiltered = notFiltered || ((!searchDocs.length || searchDocs.includes(t)) && ((!childDocFilters.length && !docRangeFilters.length) || DocUtils.FilterDocs([t], childDocFilters, docRangeFilters, viewSpecScript, d).length)); + DocListCast(t[annos ? fieldKey + "-annotations" : fieldKey]).forEach((newdoc) => newarray.push(newdoc)); + }); + subDocs = newarray; + } } } } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index d09d9b9d7..b5d9ebd9f 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -74,6 +74,8 @@ export type collectionFreeformViewProps = { scaleField?: string; noOverlay?: boolean; // used to suppress docs in the overlay (z) layer (ie, for minimap since overlay doesn't scale) engineProps?: any; + dontRenderDocuments?: boolean; // used for annotation overlays which need to distribute documents into different freeformviews with different mixBlendModes depending on whether they are trnasparent or not. + // However, this screws up interactions since only the top layer gets events. so we render the freeformview a 3rd time with all documents in order to get interaction events (eg., marquee) but we don't actually want to display the documents. }; @observer @@ -1452,7 +1454,7 @@ export class CollectionFreeFormView extends CollectionSubView -
+
{this.layoutDoc["_backgroundGrid-show"] ? this.backgroundGrid : (null)} this.props.PanelHeight() / (this.props.scaling?.() || 1); // () => this._pageSizes.length && this._pageSizes[0] ? this._pageSizes[0].width : Doc.NativeWidth(this.Document); scrollXf = () => this.props.ScreenToLocalTransform().translate(0, NumCast(this.layoutDoc._scrollTop)); anchorMenuClick = () => this._sidebarRef.current?.anchorMenuClick; + transparentFilter = () => [...this.props.docFilters(), Utils.IsTransparentFilter()]; + opaqueFilter = () => [...this.props.docFilters(), Utils.IsOpaqueFilter()]; render() { const pointerEvents = this.props.layerProvider?.(this.layoutDoc) === false ? "none" : undefined; const previewScale = this._previewNativeWidth ? 1 - this.sidebarWidth() / this._previewNativeWidth : 1; const scale = previewScale * (this.props.scaling?.() || 1); - const renderAnnotations = (docFilters: () => string[]) => + const renderAnnotations = (docFilters?: () => string[]) => {this.content}
- {renderAnnotations(Utils.IsTransparentFilter)} + {renderAnnotations(this.transparentFilter)}
- {renderAnnotations(Utils.IsOpaqueFilter)} + {renderAnnotations(this.opaqueFilter)} + {renderAnnotations()} {this.annotationLayer}
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index 0261d24d9..734d9127c 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -9,7 +9,7 @@ import { createSchema } from "../../../fields/Schema"; import { Cast, NumCast, ScriptCast, StrCast } from "../../../fields/Types"; import { PdfField } from "../../../fields/URLField"; import { TraceMobx } from "../../../fields/util"; -import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, emptyFunction, OmitKeys, smoothScroll, Utils, returnFalse } from "../../../Utils"; +import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, emptyFunction, OmitKeys, smoothScroll, Utils, returnFalse, returnEmptyString, returnEmptyFilter } from "../../../Utils"; import { DocUtils } from "../../documents/Documents"; import { Networking } from "../../Network"; import { CurrentUserUtils } from "../../util/CurrentUserUtils"; @@ -506,8 +506,10 @@ export class PDFViewer extends React.Component { overlayTransform = () => this.scrollXf().scale(1 / this._zoomed); panelWidth = () => this.props.PanelWidth() / (this.props.scaling?.() || 1); // (this.Document.scrollHeight || Doc.NativeHeight(this.Document) || 0); panelHeight = () => this.props.PanelHeight() / (this.props.scaling?.() || 1); // () => this._pageSizes.length && this._pageSizes[0] ? this._pageSizes[0].width : Doc.NativeWidth(this.Document); + transparentFilter = () => [...this.props.docFilters(), Utils.IsTransparentFilter()]; + opaqueFilter = () => [...this.props.docFilters(), Utils.IsOpaqueFilter()]; @computed get overlayLayer() { - const renderAnnotations = (docFilters: () => string[]) => + const renderAnnotations = (docFilters?: () => string[]) => { select={emptyFunction} ContentScaling={this.contentZoom} bringToFront={emptyFunction} - docFilters={docFilters} + docFilters={docFilters || this.props.docFilters} + dontRenderDocuments={docFilters ? false : true} CollectionView={undefined} ScreenToLocalTransform={this.overlayTransform} renderDepth={this.props.renderDepth + 1} @@ -531,7 +534,7 @@ export class PDFViewer extends React.Component { mixBlendMode: "multiply", transform: `scale(${this._zoomed})` }}> - {renderAnnotations(Utils.IsTransparentFilter)} + {renderAnnotations(this.transparentFilter)}
{ mixBlendMode: this.allAnnotations.some(anno => anno.mixBlendMode) ? "hard-light" : undefined, transform: `scale(${this._zoomed})` }}> - {renderAnnotations(Utils.IsOpaqueFilter)} + {renderAnnotations(this.opaqueFilter)} + {renderAnnotations()}
; } diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index f6efefdf9..17f41fac8 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -1088,7 +1088,7 @@ export namespace Doc { } export function matchFieldValue(doc: Doc, key: string, value: any): boolean { - if (value === "isTransparent(__value__)") { + if (Utils.HasTransparencyFilter(value)) { const isTransparent = (color: string) => color !== "" && (Color(color).alpha() !== 1); return isTransparent(StrCast(doc[key])); } -- cgit v1.2.3-70-g09d2 From 2d8b3c6b73da1b7685903697525a277fd53340a5 Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 26 Aug 2021 00:32:47 -0400 Subject: a lot of changes to move isContentActive into DocumentView --- src/Utils.ts | 2 +- src/client/views/DocComponent.tsx | 23 ++++++++---------- src/client/views/collections/CollectionSubView.tsx | 3 +-- src/client/views/collections/CollectionView.tsx | 8 ++++++- src/client/views/collections/TabDocView.tsx | 3 ++- .../collectionFreeForm/CollectionFreeFormView.tsx | 10 ++++---- src/client/views/nodes/AudioBox.tsx | 8 +++---- .../views/nodes/CollectionFreeFormDocumentView.tsx | 6 +++-- src/client/views/nodes/ComparisonBox.tsx | 17 ++++++++++---- src/client/views/nodes/DocumentView.tsx | 15 ++++++++---- src/client/views/nodes/ImageBox.tsx | 3 +-- src/client/views/nodes/PDFBox.tsx | 11 ++++----- src/client/views/nodes/VideoBox.tsx | 27 +++++++++++----------- src/client/views/nodes/WebBox.tsx | 12 ++++------ .../views/nodes/formattedText/FormattedTextBox.tsx | 10 ++++---- src/client/views/pdf/AnchorMenu.tsx | 1 - src/client/views/pdf/PDFViewer.tsx | 3 +-- src/fields/Doc.ts | 3 +++ 18 files changed, 91 insertions(+), 74 deletions(-) (limited to 'src/client/views/collections/CollectionSubView.tsx') diff --git a/src/Utils.ts b/src/Utils.ts index 102ac520b..de3b13f63 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -116,7 +116,7 @@ export namespace Utils { } const isTransparentFunctionHack = "isTransparent(__value__)"; - const noRecursionHack = "__noRecursion"; + export const noRecursionHack = "__noRecursion"; export function IsRecursiveFilter(val: string) { return !val.includes(noRecursionHack); } diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index d9cc29bed..33dff9da5 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -1,17 +1,17 @@ -import { Doc, Opt, DataSym, AclReadonly, AclAugment, AclPrivate, AclEdit, AclSym, DocListCast, AclAdmin, AclSelfEdit } from '../../fields/Doc'; -import { Touchable } from './Touchable'; -import { computed, action, observable } from 'mobx'; -import { Cast, BoolCast, ScriptCast } from '../../fields/Types'; +import { action, computed, observable } from 'mobx'; +import { DateField } from '../../fields/DateField'; +import { AclAdmin, AclAugment, AclEdit, AclPrivate, AclReadonly, AclSym, DataSym, Doc, DocListCast, Opt } from '../../fields/Doc'; import { InkTool } from '../../fields/InkField'; -import { InteractionUtils } from '../util/InteractionUtils'; import { List } from '../../fields/List'; -import { DateField } from '../../fields/DateField'; import { ScriptField } from '../../fields/ScriptField'; -import { GetEffectiveAcl, SharingPermissions, distributeAcls, denormalizeEmail, inheritParentAcls } from '../../fields/util'; -import { CurrentUserUtils } from '../util/CurrentUserUtils'; -import { DocUtils } from '../documents/Documents'; +import { Cast, ScriptCast } from '../../fields/Types'; +import { denormalizeEmail, distributeAcls, GetEffectiveAcl, inheritParentAcls, SharingPermissions } from '../../fields/util'; import { returnFalse } from '../../Utils'; +import { DocUtils } from '../documents/Documents'; +import { CurrentUserUtils } from '../util/CurrentUserUtils'; +import { InteractionUtils } from '../util/InteractionUtils'; import { UndoManager } from '../util/UndoManager'; +import { Touchable } from './Touchable'; /// DocComponent returns a generic React base class used by views that don't have 'fieldKey' props (e.g.,CollectionFreeFormDocumentView, DocumentView) @@ -107,6 +107,7 @@ export function ViewBoxAnnotatableComponent

this._isAnyChildContentActive; lookupField = (field: string) => ScriptCast((this.layoutDoc as any).lookupField)?.script.run({ self: this.layoutDoc, data: this.rootDoc, field: field }).result; @@ -229,10 +230,6 @@ export function ViewBoxAnnotatableComponent

this.props.whenChildContentsActiveChanged(this._isAnyChildContentActive = isActive)); - isContentActive = (outsideReaction?: boolean) => (CurrentUserUtils.SelectedTool !== InkTool.None || - (this.props.isContentActive?.() || this.props.Document.forceActive || - this.props.isSelected(outsideReaction) || this._isAnyChildContentActive || - this.props.rootSelected(outsideReaction)) ? true : false) } return Component; } \ No newline at end of file diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 1f4c35daa..b70df93da 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -23,6 +23,7 @@ import ReactLoading from 'react-loading'; export interface SubCollectionViewProps extends CollectionViewProps { CollectionView: Opt; SetSubView?: (subView: any) => void; + isAnyChildContentActive: () => boolean; } export function CollectionSubView(schemaCtor: (doc: Doc) => T, moreProps?: X) { @@ -490,7 +491,5 @@ import { FormattedTextBox, GoogleRef } from "../nodes/formattedText/FormattedTex import { CollectionView, CollectionViewType, CollectionViewProps } from "./CollectionView"; import { SelectionManager } from "../../util/SelectionManager"; import { OverlayView } from "../OverlayView"; -import { Hypothesis } from "../../util/HypothesisUtils"; import { GetEffectiveAcl, TraceMobx } from "../../../fields/util"; -import { FilterBox } from "../nodes/FilterBox"; diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index a821aeeea..229e93b9e 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -37,6 +37,7 @@ import { CollectionTreeView } from "./CollectionTreeView"; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import './CollectionView.scss'; import { returnEmptyString } from '../../../Utils'; +import { InkTool } from '../../../fields/InkField'; export const COLLECTION_BORDER_WIDTH = 2; const path = require('path'); @@ -119,7 +120,7 @@ export class CollectionView extends ViewBoxAnnotatableComponent Cast(doc.data, ImageField)).map(Doc.GetProto); // const allTagged = imageProtos.length > 0 && imageProtos.every(image => image.googlePhotosTags); // return !allTagged ? (null) : ; - this.isContentActive(); + //this.isContentActive(); } screenToLocalTransform = () => this.props.renderDepth ? this.props.ScreenToLocalTransform() : this.props.ScreenToLocalTransform().scale(this.props.PanelWidth() / this.bodyPanelWidth()); @@ -253,6 +254,9 @@ export class CollectionView extends ViewBoxAnnotatableComponent { + return this.props.isContentActive() ? true : false; + } render() { TraceMobx(); const props: SubCollectionViewProps = { @@ -262,6 +266,8 @@ export class CollectionView extends ViewBoxAnnotatableComponent { 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={returnTrue} + isContentActive={returnFalse} + isAnyChildContentActive={returnFalse} select={emptyFunction} dropAction={undefined} isSelected={returnFalse} diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index b5d9ebd9f..fb949a36d 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -1,6 +1,7 @@ import { action, computed, IReactionDisposer, observable, reaction, runInAction } from "mobx"; import { observer } from "mobx-react"; import { computedFn } from "mobx-utils"; +import { DateField } from "../../../../fields/DateField"; import { Doc, HeightSym, Opt, StrListCast, WidthSym } from "../../../../fields/Doc"; import { collectionSchema, documentSchema } from "../../../../fields/documentSchemas"; import { Id } from "../../../../fields/FieldSymbols"; @@ -17,6 +18,7 @@ import { aggregateBounds, emptyFunction, intersectRect, returnFalse, setupMoveUp import { CognitiveServices } from "../../../cognitive_services/CognitiveServices"; import { DocServer } from "../../../DocServer"; import { Docs, DocUtils } from "../../../documents/Documents"; +import { DocumentType } from "../../../documents/DocumentTypes"; import { CurrentUserUtils } from "../../../util/CurrentUserUtils"; import { DocumentManager } from "../../../util/DocumentManager"; import { DragManager, dropActionType } from "../../../util/DragManager"; @@ -48,8 +50,7 @@ import { CollectionFreeFormRemoteCursors } from "./CollectionFreeFormRemoteCurso import "./CollectionFreeFormView.scss"; import { MarqueeView } from "./MarqueeView"; import React = require("react"); -import { DocumentType } from "../../../documents/DocumentTypes"; -import { DateField } from "../../../../fields/DateField"; +import Color = require("color"); export const panZoomSchema = createSchema({ _panX: "number", @@ -117,7 +118,7 @@ export class CollectionFreeFormView extends CollectionSubView ele.bounds && !ele.bounds.z).map(ele => ele.ele); } @computed get backgroundEvents() { return this.props.layerProvider?.(this.layoutDoc) === false && SnappingManager.GetIsDragging(); } - @computed get backgroundActive() { return this.props.layerProvider?.(this.layoutDoc) === false && (this.props.ContainingCollectionView?.isContentActive() || this.props.isContentActive()); } + @computed get backgroundActive() { return this.props.layerProvider?.(this.layoutDoc) === false && this.props.isContentActive(); } @computed get fitToContentVals() { return { bounds: { ...this.contentBounds, cx: (this.contentBounds.x + this.contentBounds.r) / 2, cy: (this.contentBounds.y + this.contentBounds.b) / 2 }, @@ -170,6 +171,7 @@ export class CollectionFreeFormView extends CollectionSubView this.cachedGetContainerTransform.copy(); getTransformOverlay = () => this.getContainerTransform().translate(1, 1); getActiveDocuments = () => this.childLayoutPairs.filter(pair => this.isCurrent(pair.layout)).map(pair => pair.layout); + isAnyChildContentActive = () => this.props.isAnyChildContentActive(); addLiveTextBox = (newBox: Doc) => { FormattedTextBox.SelectOnLoad = newBox[Id];// track the new text box so we can give it a prop that tells it to focus itself when it's displayed this.addDocument(newBox); @@ -1033,7 +1035,7 @@ export class CollectionFreeFormView extends CollectionSubView + return ; @@ -328,6 +328,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent} : -

+
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 092823603..9cc4b1f9a 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -17,8 +17,8 @@ import { InkingStroke } from "../InkingStroke"; import { StyleProp } from "../StyleProvider"; import "./CollectionFreeFormDocumentView.scss"; import { DocumentView, DocumentViewProps } from "./DocumentView"; -import { FieldViewProps } from "./FieldView"; import React = require("react"); +import Color = require("color"); export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps { dataProvider?: (doc: Doc, replica: string) => { x: number, y: number, zIndex?: number, opacity?: number, highlight?: boolean, z: number, transition?: string } | undefined; @@ -164,6 +164,8 @@ export class CollectionFreeFormDocumentView extends DocComponent this._contentView = r)} /> diff --git a/src/client/views/nodes/ComparisonBox.tsx b/src/client/views/nodes/ComparisonBox.tsx index 153176afc..6708a08ee 100644 --- a/src/client/views/nodes/ComparisonBox.tsx +++ b/src/client/views/nodes/ComparisonBox.tsx @@ -1,17 +1,18 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action, observable } from 'mobx'; import { observer } from "mobx-react"; -import { Doc } from '../../../fields/Doc'; +import { Doc, Opt } from '../../../fields/Doc'; import { documentSchema } from '../../../fields/documentSchemas'; import { createSchema, makeInterface } from '../../../fields/Schema'; import { Cast, NumCast, StrCast } from '../../../fields/Types'; -import { emptyFunction, OmitKeys, setupMoveUpEvents } from '../../../Utils'; +import { emptyFunction, OmitKeys, returnFalse, setupMoveUpEvents } from '../../../Utils'; import { DragManager } from '../../util/DragManager'; import { SnappingManager } from '../../util/SnappingManager'; import { undoBatch } from '../../util/UndoManager'; import { ViewBoxAnnotatableComponent, ViewBoxAnnotatableProps } from '../DocComponent'; +import { StyleProp } from '../StyleProvider'; import "./ComparisonBox.scss"; -import { DocumentView } from './DocumentView'; +import { DocumentView, DocumentViewProps } from './DocumentView'; import { FieldView, FieldViewProps } from './FieldView'; import React = require("react"); @@ -71,6 +72,11 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent, props: Opt, property: string): any => { + if (property === StyleProp.PointerEvents) return "none"; + return this.props.styleProvider?.(doc, props, property); + } + render() { const clipWidth = NumCast(this.layoutDoc._clipWidth) + "%"; const clearButton = (which: string) => { @@ -84,6 +90,9 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent @@ -102,7 +111,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent +
{displayBox("after", 1, this.props.PanelWidth() - 3)}
{displayBox("before", 0, 0)} diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index bb259da3e..11fb5cdb3 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -84,6 +84,7 @@ export interface DocComponentView { reverseNativeScaling?: () => boolean; // DocumentView's setup screenToLocal based on the doc having a nativeWidth/Height. However, some content views (e.g., FreeFormView w/ fitToBox set) may ignore the native dimensions so this flags the DocumentView to not do Nativre scaling. shrinkWrap?: () => void; // requests a document to display all of its contents with no white space. currently only implemented (needed?) for freeform views menuControls?: () => JSX.Element; // controls to display in the top menu bar when the document is selected. + isAnyChildContentActive?: () => boolean; // is any child content of the document active getKeyFrameEditing?: () => boolean; // whether the document is in keyframe editing mode (if it is, then all hidden documents that are not active at the keyframe time will still be shown) setKeyFrameEditing?: (set: boolean) => void; // whether the document is in keyframe editing mode (if it is, then all hidden documents that are not active at the keyframe time will still be shown) playFrom?: (time: number, endTime?: number) => void; @@ -182,7 +183,7 @@ export class DocumentViewInternal extends DocComponent; // needs to be accessed from DocumentView wrapper class + @observable _componentView: Opt; // needs to be accessed from DocumentView wrapper class private get topMost() { return this.props.renderDepth === 0 && !LightboxView.LightboxDoc; } public get displayName() { return "DocumentView(" + this.props.Document.title + ")"; } // this makes mobx trace() statements more descriptive @@ -778,8 +779,14 @@ export class DocumentViewInternal extends DocComponent this.ContentScale; onClickFunc = () => this.onClickHandler; setHeight = (height: number) => this.layoutDoc._height = height; - setContentView = (view: { getAnchor?: () => Doc, forward?: () => boolean, back?: () => boolean }) => this._componentView = view; - isContentActive = (outsideReaction?: boolean) => this.props.isSelected(outsideReaction) || this.props.isContentActive() ? true : false; + setContentView = action((view: { getAnchor?: () => Doc, forward?: () => boolean, back?: () => boolean }) => this._componentView = view); + isContentActive = (outsideReaction?: boolean) => { + return CurrentUserUtils.SelectedTool !== InkTool.None || + this.props.Document.forceActive || + this.props.isSelected(outsideReaction) || + this._componentView?.isAnyChildContentActive?.() || + this.props.isContentActive() ? true : false; + } @computed get contents() { TraceMobx(); const audioView = !this.layoutDoc._showAudio ? (null) : @@ -794,7 +801,7 @@ export class DocumentViewInternal extends DocComponent; return
; } marqueeDown = (e: React.PointerEvent) => { - if (!e.altKey && e.button === 0 && this.layoutDoc._viewScale === 1 && this.isContentActive(true) && ![InkTool.Highlighter, InkTool.Pen].includes(CurrentUserUtils.SelectedTool)) { + if (!e.altKey && e.button === 0 && this.layoutDoc._viewScale === 1 && this.props.isContentActive(true) && ![InkTool.Highlighter, InkTool.Pen].includes(CurrentUserUtils.SelectedTool)) { setupMoveUpEvents(this, e, action(e => { MarqueeAnnotator.clearAnnotations(this._savedAnnotations) this._marqueeing = [e.clientX, e.clientY]; @@ -368,7 +368,6 @@ export class ImageBox extends ViewBoxAnnotatableComponent; const searchTitle = `${!this._searching ? "Open" : "Close"} Search Bar`; const curPage = this.Document._curPage || 1; - return !this.isContentActive() ? (null) : + return !this.props.isContentActive() ? (null) :
[KeyCodes.BACKSPACE, KeyCodes.DELETE].includes(e.keyCode) ? e.stopPropagation() : true} - onPointerDown={e => e.stopPropagation()} style={{ display: this.isContentActive() ? "flex" : "none" }}> + onPointerDown={e => e.stopPropagation()} style={{ display: this.props.isContentActive() ? "flex" : "none" }}>
e.stopPropagation()} style={{ left: `${this._searching ? 0 : 100}%` }}> @@ -229,7 +229,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent
{this.props.Document.title} @@ -268,7 +268,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent {this.settingsPanel()}
; diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx index d4df30b48..484dec7e2 100644 --- a/src/client/views/nodes/VideoBox.tsx +++ b/src/client/views/nodes/VideoBox.tsx @@ -307,7 +307,7 @@ export class VideoBox extends ViewBoxAnnotatableComponentLoading
: -
+
} placement="bottom"> -
+ {"playback"}
} key="play" placement="bottom"> +
, - {"timecode"}
} placement="bottom"> + {"timecode"}
} key="time" placement="bottom">
{formatTime(curTime)} {" " + Math.floor((curTime - Math.trunc(curTime)) * 100).toString().padStart(2, "0")}
, - {"view full screen"}
} placement="bottom"> + {"view full screen"}
} key="full" placement="bottom">
]; return
{[...(VideoBox._nativeControls ? [] : nonNativeControls), - {"snapshot current frame"}
} placement="bottom"> + {"snapshot current frame"}
} key="snap" placement="bottom">
, - {"show annotation timeline"}
} placement="bottom"> + {"show annotation timeline"}
} key="timeline" placement="bottom">
@@ -429,7 +429,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent { this._clicking = false; - if (this.isContentActive()) { + if (this.props.isContentActive()) { const local = this.props.ScreenToLocalTransform().scale(this.props.scaling?.() || 1).transformPoint(e.clientX, e.clientY); this.layoutDoc._timelineHeightPercent = Math.max(0, Math.min(100, local[1] / this.props.PanelHeight() * 100)); } @@ -438,7 +438,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent { this.layoutDoc._timelineHeightPercent = this.heightPercent !== 100 ? 100 : VideoBox.heightPercent; setTimeout(action(() => this._clicking = false), 500); - }, this.isContentActive(), this.isContentActive()); + }, this.props.isContentActive(), this.props.isContentActive()); }); onResetDown = (e: React.PointerEvent) => { @@ -529,12 +529,12 @@ export class VideoBox extends ViewBoxAnnotatableComponent @@ -546,7 +546,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent { - if (!e.altKey && e.button === 0 && this.layoutDoc._viewScale === 1 && this.isContentActive(true) && ![InkTool.Highlighter, InkTool.Pen].includes(CurrentUserUtils.SelectedTool)) { + if (!e.altKey && e.button === 0 && this.layoutDoc._viewScale === 1 && this.props.isContentActive(true) && ![InkTool.Highlighter, InkTool.Pen].includes(CurrentUserUtils.SelectedTool)) { setupMoveUpEvents(this, e, action(e => { MarqueeAnnotator.clearAnnotations(this._savedAnnotations); this._marqueeing = [e.clientX, e.clientY]; @@ -570,7 +570,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent (this.props.scaling?.() || 1) * this.heightPercent / 100; marqueeOffset = () => [this.panelWidth() / 2 * (1 - this.heightPercent / 100) / (this.heightPercent / 100), 0]; - timelineDocFilter = () => ["_timelineLabel:true:x"]; + timelineDocFilter = () => [`_timelineLabel:true,${Utils.noRecursionHack}:x`]; render() { const borderRad = this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BorderRounding); const borderRadius = borderRad?.includes("px") ? `${Number(borderRad.split("px")[0]) / this.scaling()}px` : borderRad; @@ -592,7 +592,6 @@ export class VideoBox extends ViewBoxAnnotatableComponent { - if (!e.altKey && e.button === 0 && this.isContentActive(true) && ![InkTool.Highlighter, InkTool.Pen].includes(CurrentUserUtils.SelectedTool)) { + if (!e.altKey && e.button === 0 && this.props.isContentActive(true) && ![InkTool.Highlighter, InkTool.Pen].includes(CurrentUserUtils.SelectedTool)) { setupMoveUpEvents(this, e, action(e => { MarqueeAnnotator.clearAnnotations(this._savedAnnotations); this._marqueeing = [e.clientX, e.clientY]; @@ -484,7 +484,7 @@ export class WebBox extends ViewBoxAnnotatableComponent {this.urlContent}
; @@ -529,7 +529,6 @@ export class WebBox extends ViewBoxAnnotatableComponent; return ( -
+
{renderAnnotations(this.opaqueFilter)} - {renderAnnotations()} + {SnappingManager.GetIsDragging() ? (null) : renderAnnotations()} {this.annotationLayer}
@@ -588,10 +587,9 @@ export class WebBox extends ViewBoxAnnotatableComponent diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index d1027dfd7..4b1d76d00 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -1211,7 +1211,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp if ((e.nativeEvent as any).formattedHandled) { console.log("handled"); } - if (!(e.nativeEvent as any).formattedHandled && this.isContentActive(true)) { + if (!(e.nativeEvent as any).formattedHandled && this.props.isContentActive(true)) { const editor = this._editorView!; const pcords = editor.posAtCoords({ left: e.clientX, top: e.clientY }); !this.props.isSelected(true) && editor.dispatch(editor.state.tr.setSelection(new TextSelection(editor.state.doc.resolve(pcords?.pos || 0)))); @@ -1481,7 +1481,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp @computed get sidebarHandle() { TraceMobx(); const annotated = DocListCast(this.dataDoc[this.SidebarKey]).filter(d => d?.author).length; - return (!annotated && !this.isContentActive()) ? (null) :
: = 10 ? "-selected" : ""; return (
this.isContentActive() && e.stopPropagation()} + onWheel={e => this.props.isContentActive() && e.stopPropagation()} style={{ transform: this.props.dontScale ? undefined : `scale(${scale})`, transformOrigin: this.props.dontScale ? undefined : "top left", diff --git a/src/client/views/pdf/AnchorMenu.tsx b/src/client/views/pdf/AnchorMenu.tsx index 75e3f81fb..42bec38da 100644 --- a/src/client/views/pdf/AnchorMenu.tsx +++ b/src/client/views/pdf/AnchorMenu.tsx @@ -69,7 +69,6 @@ export class AnchorMenu extends AntimodeMenu { this._disposer = reaction(() => SelectionManager.Views(), selected => { this._showLinkPopup = false; - console.log("unmount"); AnchorMenu.Instance.fadeOut(true) }); } diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index 734d9127c..bc35d2126 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -512,7 +512,6 @@ export class PDFViewer extends React.Component { const renderAnnotations = (docFilters?: () => string[]) => { transform: `scale(${this._zoomed})` }}> {renderAnnotations(this.opaqueFilter)} - {renderAnnotations()} + {SnappingManager.GetIsDragging() ? (null) : renderAnnotations()}
; } diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index 17f41fac8..b09ff93d0 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -1092,6 +1092,9 @@ export namespace Doc { const isTransparent = (color: string) => color !== "" && (Color(color).alpha() !== 1); return isTransparent(StrCast(doc[key])); } + if (typeof value === "string") { + value = value.replace(`,${Utils.noRecursionHack}`, ""); + } const fieldVal = doc[key]; if (Cast(fieldVal, listSpec("string"), []).length) { const vals = Cast(fieldVal, listSpec("string"), []); -- cgit v1.2.3-70-g09d2 From 9d177851ecaaea1a89ac9b7de1cec16368603eaa Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 9 Sep 2021 22:49:13 -0400 Subject: added SelectionManager.Docs() to avoid having to dereference props to get at the seelcted Doc. this was causing a cycle in menu items when selected. fixed sizing of filterBox. enabled showing titles for VID,COL,and IMG in addition to RTF. --- src/client/util/CurrentUserUtils.ts | 2 +- src/client/util/HypothesisUtils.ts | 2 +- src/client/util/SelectionManager.ts | 12 ++-- src/client/views/GlobalKeyHandler.ts | 4 +- src/client/views/PropertiesView.tsx | 2 +- src/client/views/StyleProvider.tsx | 2 +- src/client/views/collections/CollectionMenu.tsx | 21 +++---- src/client/views/collections/CollectionSubView.tsx | 8 +-- .../collectionLinear/CollectionLinearView.tsx | 19 +++--- src/client/views/nodes/DocumentView.tsx | 5 +- src/client/views/nodes/FilterBox.tsx | 11 ++-- src/client/views/nodes/button/FontIconBox.tsx | 68 ++++++++++------------ .../views/nodes/formattedText/RichTextMenu.tsx | 20 +++---- 13 files changed, 81 insertions(+), 95 deletions(-) (limited to 'src/client/views/collections/CollectionSubView.tsx') diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 8435825c9..60bb375c8 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -1616,7 +1616,7 @@ Scripting.addGlobal(function dynamicOffScreenDocs(dashboard: Doc) { return []; }); Scripting.addGlobal(function selectedDocumentType(docType?: DocumentType, colType?: CollectionViewType, checkParent?: boolean) { - let selected = SelectionManager.Views().length ? SelectionManager.Views()[0].rootDoc : undefined; + let selected = SelectionManager.Docs().length ? SelectionManager.Docs()[0] : undefined; if (selected && checkParent) { const parentDoc: Doc = Cast(selected.context, Doc, null); selected = parentDoc; diff --git a/src/client/util/HypothesisUtils.ts b/src/client/util/HypothesisUtils.ts index 635673025..e910a9118 100644 --- a/src/client/util/HypothesisUtils.ts +++ b/src/client/util/HypothesisUtils.ts @@ -29,7 +29,7 @@ export namespace Hypothesis { * Search for a WebDocument whose url field matches the given uri, return undefined if not found */ export const findWebDoc = async (uri: string) => { - const currentDoc = SelectionManager.Views().length && SelectionManager.Views()[0].props.Document; + const currentDoc = SelectionManager.Docs().lastElement(); if (currentDoc && Cast(currentDoc.data, WebField)?.url.href === uri) return currentDoc; // always check first whether the currently selected doc is the annotation's source, only use Search otherwise const results: Doc[] = []; diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts index 0cfaebbf2..bac13373c 100644 --- a/src/client/util/SelectionManager.ts +++ b/src/client/util/SelectionManager.ts @@ -11,7 +11,7 @@ export namespace SelectionManager { class Manager { @observable IsDragging: boolean = false; - SelectedViews: ObservableMap = new ObservableMap(); + SelectedViews: ObservableMap = new ObservableMap(); @observable SelectedSchemaDocument: Doc | undefined; @observable SelectedSchemaCollection: CollectionSchemaView | undefined; @@ -28,19 +28,18 @@ export namespace SelectionManager { this.DeselectAll(); } - manager.SelectedViews.set(docView, true); + manager.SelectedViews.set(docView, docView.rootDoc); docView.props.whenChildContentsActiveChanged(true); } else if (!ctrlPressed && Array.from(manager.SelectedViews.entries()).length > 1) { Array.from(manager.SelectedViews.keys()).map(dv => dv !== docView && dv.props.whenChildContentsActiveChanged(false)); manager.SelectedSchemaDocument = undefined; manager.SelectedSchemaCollection = undefined; manager.SelectedViews.clear(); - manager.SelectedViews.set(docView, true); + manager.SelectedViews.set(docView, docView.rootDoc); } } @action DeselectView(docView: DocumentView): void { - if (manager.SelectedViews.get(docView)) { manager.SelectedViews.delete(docView); docView.props.whenChildContentsActiveChanged(false); @@ -92,7 +91,7 @@ export namespace SelectionManager { } export function Views(): Array { - return Array.from(manager.SelectedViews.keys()).filter(dv => dv.props.Document._viewType !== CollectionViewType.Docking); + return Array.from(manager.SelectedViews.keys()).filter(dv => manager.SelectedViews.get(dv)?._viewType !== CollectionViewType.Docking); } export function SelectedSchemaDoc(): Doc | undefined { return manager.SelectedSchemaDocument; @@ -100,4 +99,7 @@ export namespace SelectionManager { export function SelectedSchemaCollection(): CollectionSchemaView | undefined { return manager.SelectedSchemaCollection; } + export function Docs(): Doc[] { + return Array.from(manager.SelectedViews.values()).filter(doc => doc?._viewType !== CollectionViewType.Docking); + } } \ No newline at end of file diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts index 0127d3080..f66c9c788 100644 --- a/src/client/views/GlobalKeyHandler.ts +++ b/src/client/views/GlobalKeyHandler.ts @@ -229,8 +229,8 @@ export class KeyManager { } break; case "o": - const target = SelectionManager.Views()[0]; - target && CollectionDockingView.OpenFullScreen(target.props.Document); + const target = SelectionManager.Docs().lastElement(); + target && CollectionDockingView.OpenFullScreen(target); break; case "r": preventDefault = false; diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index 09e12443b..ab9022a84 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -366,7 +366,7 @@ export class PropertiesView extends React.Component { return {"Show more permissions"}
}>
{ if (this.selectedDocumentView || this.selectedDoc) { - SharingManager.Instance.open(this.selectedDocumentView?.props.Document === this.selectedDocumentView ? this.selectedDocumentView : undefined, this.selectedDoc); + SharingManager.Instance.open(this.selectedDocumentView?.props.Document === this.selectedDoc ? this.selectedDocumentView : undefined, this.selectedDoc); } }}> diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx index 3413179ed..3c88a4830 100644 --- a/src/client/views/StyleProvider.tsx +++ b/src/client/views/StyleProvider.tsx @@ -96,7 +96,7 @@ export function DefaultStyleProvider(doc: Opt, props: Opt { componentDidMount() { reaction(() => SelectionManager.Views().length && SelectionManager.Views()[0], - (doc) => doc && this.SetSelection(doc)); + view => view && this.SetSelection(view)); } @action @@ -441,10 +441,8 @@ export class CollectionViewBaseChrome extends React.Component); } - @computed get selectedDocumentView() { - return SelectionManager.Views().length ? SelectionManager.Views()[0] : undefined; - } - @computed get selectedDoc() { return this.selectedDocumentView?.rootDoc; } + @computed get selectedDocumentView() { return SelectionManager.Views().lastElement(); } + @computed get selectedDoc() { return SelectionManager.Docs().lastElement(); } @computed get notACollection() { if (this.selectedDoc) { const layoutField = Doc.LayoutField(this.selectedDoc); @@ -552,8 +550,8 @@ export class CollectionViewBaseChrome extends React.Component { const contentDiv = this.selectedDocumentView?.ContentDiv; - if (contentDiv) { - const dragData = new DragManager.DocumentDragData([this.selectedDocumentView!.props.Document]); + if (contentDiv && this.selectedDoc) { + const dragData = new DragManager.DocumentDragData([this.selectedDoc]); const offset = [e.clientX - contentDiv.getBoundingClientRect().x, e.clientY - contentDiv.getBoundingClientRect().y]; dragData.defaultDropAction = "alias"; dragData.canEmbed = true; @@ -648,11 +646,9 @@ export class CollectionFreeFormViewChrome extends React.Component; } - @observable viewType = this.selectedDoc?._viewType; render() { return !this.props.docView.layoutDoc ? (null) : diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index b70df93da..06d20f015 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -321,12 +321,8 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T, moreProps?: } }); } else { - let srcUrl: string | undefined; - let srcWeb: Doc | undefined; - if (SelectionManager.Views().length) { - srcWeb = SelectionManager.Views()[0].props.Document; - srcUrl = (srcWeb.data as WebField).url?.href?.match(/http[s]?:\/\/[^/]*/)?.[0]; - } + const srcWeb = SelectionManager.Docs().lastElement(); + const srcUrl = (srcWeb?.data as WebField).url?.href?.match(/http[s]?:\/\/[^/]*/)?.[0]; const reg = new RegExp(Utils.prepend(""), "g"); const modHtml = srcUrl ? html.replace(reg, srcUrl) : html; const htmlDoc = Docs.Create.HtmlDocument(modHtml, { ...options, title: "-web page-", _width: 300, _height: 300 }); diff --git a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx index fae92e076..7fe95fef0 100644 --- a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx +++ b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx @@ -1,24 +1,24 @@ +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Tooltip } from '@material-ui/core'; -import { action, IReactionDisposer, observable, reaction, runInAction, trace } from 'mobx'; +import { action, IReactionDisposer, observable, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; -import { Doc, HeightSym, WidthSym, Opt } from '../../../../fields/Doc'; +import { Doc, HeightSym, Opt, WidthSym } from '../../../../fields/Doc'; import { documentSchema } from '../../../../fields/documentSchemas'; import { Id } from '../../../../fields/FieldSymbols'; import { makeInterface } from '../../../../fields/Schema'; import { BoolCast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types'; -import { emptyFunction, returnEmptyDoclist, returnFalse, returnTrue, Utils } from '../../../../Utils'; +import { emptyFunction, returnEmptyDoclist, returnTrue, Utils } from '../../../../Utils'; import { DragManager } from '../../../util/DragManager'; import { Transform } from '../../../util/Transform'; +import { Colors, Shadows } from '../../global/globalEnums'; import { DocumentLinksButton } from '../../nodes/DocumentLinksButton'; import { DocumentView } from '../../nodes/DocumentView'; import { LinkDescriptionPopup } from '../../nodes/LinkDescriptionPopup'; import { StyleProp } from '../../StyleProvider'; -import "./CollectionLinearView.scss"; import { CollectionSubView } from '../CollectionSubView'; import { CollectionViewType } from '../CollectionView'; -import { Colors, Shadows } from '../../global/globalEnums'; -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import "./CollectionLinearView.scss"; type LinearDocument = makeInterface<[typeof documentSchema,]>; @@ -115,9 +115,9 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) { } - getDisplayDoc(doc: Doc) { + getDisplayDoc = (doc: Doc) => { const nested = doc._viewType === CollectionViewType.Linear; - const hidden = doc.hidden === true;; + const hidden = doc.hidden === true; let dref: Opt; const docXf = () => this.getTransform(dref); @@ -142,8 +142,7 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) { pinToPres={emptyFunction} rootSelected={this.props.isSelected} removeDocument={this.props.removeDocument} - // ScreenToLocalTransform={docXf} // bcz: Ugh -- this is what we want, but it breaks things when right-clicking on linear view item since docXf is not a constant value across invalidations - ScreenToLocalTransform={this.props.ScreenToLocalTransform} + ScreenToLocalTransform={docXf} PanelWidth={nested ? doc[WidthSym] : this.dimension} PanelHeight={nested ? doc[HeightSym] : this.dimension} renderDepth={this.props.renderDepth + 1} diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 6f97cdbd8..8b19fb204 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -649,7 +649,7 @@ export class DocumentViewInternal extends DocComponent
; const targetDoc = (showTitle?.startsWith("_") ? this.layoutDoc : this.rootDoc); - const background = StrCast(SharingManager.Instance.users.find(users => users.user.email === this.dataDoc.author)?.sharingDoc.userColor, this.rootDoc.type === DocumentType.RTF ? StrCast(Doc.SharingDoc().userColor) : "rgba(0,0,0,0.4)"); + const background = StrCast(SharingManager.Instance.users.find(users => users.user.email === this.dataDoc.author)?.sharingDoc.userColor, [DocumentType.RTF, DocumentType.COL].includes(this.rootDoc.type as any) ? StrCast(Doc.SharingDoc().userColor) : "rgba(0,0,0,0.4)"); const titleView = !showTitle ? (null) :
{ - this.layoutDoc._height = hgt + 140; // 50? need to add all the border sizes together. + this.layoutDoc._height = NumCast(this.layoutDoc._autoHeightMargins) + 150; // need to add all the border sizes together. } /** diff --git a/src/client/views/nodes/button/FontIconBox.tsx b/src/client/views/nodes/button/FontIconBox.tsx index 4475cf347..df7c54f67 100644 --- a/src/client/views/nodes/button/FontIconBox.tsx +++ b/src/client/views/nodes/button/FontIconBox.tsx @@ -248,14 +248,15 @@ export class FontIconBox extends DocComponent(Fon let noneSelected: boolean = false; if (script === 'setView') { - const selected = SelectionManager.Views().length ? SelectionManager.Views()[0] : undefined; - if (selected && StrCast(selected.Document.type) === DocumentType.COL) { - text = StrCast(selected.Document._viewType); - } else if (selected) { - dropdown = false; - text = StrCast(selected.Document.type); - if (text === DocumentType.RTF) text = "Text"; - icon = Doc.toIcon(selected.Document); + const selected = SelectionManager.Docs().lastElement(); + if (selected) { + if (StrCast(selected.type) === DocumentType.COL) { + text = StrCast(selected._viewType); + } else { + dropdown = false; + text = selected.type === DocumentType.RTF ? "Text" : StrCast(selected.type); + icon = Doc.toIcon(selected); + } } else { dropdown = false; icon = "globe-asia"; @@ -263,13 +264,8 @@ export class FontIconBox extends DocComponent(Fon } noviceList = [CollectionViewType.Freeform, CollectionViewType.Schema, CollectionViewType.Stacking]; } else if (script === 'setFont') { - const selected = SelectionManager.Views().length ? SelectionManager.Views()[0] : undefined; - if (selected && StrCast(selected.Document.type) === DocumentType.RTF) { - text = StrCast(selected.Document._fontFamily); - } else { - const fontFamily = StrCast(Doc.UserDoc()._fontFamily); - text = fontFamily; - } + const selected = SelectionManager.Docs().lastElement(); + text = StrCast((selected?.type === DocumentType.RTF ? selected : Doc.UserDoc())._fontFamily); noviceList = ["Roboto", "Times New Roman", "Arial", "Georgia", "Comic Sans MS", "Tahoma", "Impact", "Crimson Text"]; } @@ -584,13 +580,13 @@ export class FontIconBox extends DocComponent(Fon // toggle: Set overlay status of selected document Scripting.addGlobal(function setView(view: string) { - const selected = SelectionManager.Views().length ? SelectionManager.Views()[0] : undefined; - selected ? selected.Document._viewType = view : console.log("[FontIconBox.tsx] changeView failed"); + const selected = SelectionManager.Docs().lastElement(); + selected ? selected._viewType = view : console.log("[FontIconBox.tsx] changeView failed"); }); // toggle: Set overlay status of selected document Scripting.addGlobal(function setBackgroundColor(color?: string, checkResult?: boolean) { - const selected = SelectionManager.Views().length ? SelectionManager.Views()[0].rootDoc : undefined; + const selected = SelectionManager.Docs().lastElement(); if (checkResult) { if (selected) { console.log("[Background] (selected): " + StrCast(selected._backgroundColor)); @@ -635,7 +631,7 @@ Scripting.addGlobal(function toggleOverlay(checkResult?: boolean) { // toggle: Set overlay status of selected document Scripting.addGlobal(function setFont(font: string, checkResult?: boolean) { - SelectionManager.Views().map(dv => dv.props.Document._fontFamily = font); + SelectionManager.Docs().map(doc => doc._fontFamily = font); const editorView = RichTextMenu.Instance.TextView?.EditorView; editorView?.state && RichTextMenu.Instance.setFontFamily(font, editorView); Doc.UserDoc()._fontFamily = font; @@ -665,7 +661,7 @@ Scripting.addGlobal(function setAlignment(align: "left" | "right" | "center", ch if (active === align) return Colors.MEDIUM_BLUE; else return "transparent"; } - SelectionManager.Views().map(dv => dv.props.Document.textAlign = align); + SelectionManager.Docs().map(doc => doc.textAlign = align); switch (align) { case "left": editorView?.state && RichTextMenu.Instance.alignLeft(editorView, editorView.dispatch); @@ -703,13 +699,13 @@ Scripting.addGlobal(function setBulletList(mapStyle: "bullet" | "decimal", check // toggle: Set overlay status of selected document Scripting.addGlobal(function setFontColor(color?: string, checkResult?: boolean) { - const selected = SelectionManager.Views().length ? SelectionManager.Views()[0] : undefined; + const selected = SelectionManager.Docs().lastElement(); const editorView = RichTextMenu.Instance.TextView?.EditorView; if (checkResult) { if (selected) { - console.log("[Font color] (selected): " + StrCast(selected.rootDoc._fontColor)); - return selected.rootDoc._fontColor; + console.log("[Font color] (selected): " + StrCast(selected._fontColor)); + return selected._fontColor; } else { console.log("[Font color] (global): " + StrCast(Doc.UserDoc()._fontColor)); return Doc.UserDoc()._fontColor; @@ -717,7 +713,7 @@ Scripting.addGlobal(function setFontColor(color?: string, checkResult?: boolean) } if (selected) { - selected.rootDoc._fontColor = color; + selected._fontColor = color; if (color) { editorView?.state && RichTextMenu.Instance.setColor(color, editorView, editorView?.dispatch); } @@ -727,18 +723,18 @@ Scripting.addGlobal(function setFontColor(color?: string, checkResult?: boolean) // toggle: Set overlay status of selected document Scripting.addGlobal(function setFontHighlight(color?: string, checkResult?: boolean) { - const selected = SelectionManager.Views().length ? SelectionManager.Views()[0] : undefined; + const selected = SelectionManager.Docs().lastElement(); const editorView = RichTextMenu.Instance.TextView?.EditorView; if (checkResult) { if (selected) { - return selected.Document._fontHighlight; + return selected._fontHighlight; } else { return Doc.UserDoc()._fontHighlight; } } if (selected) { - selected.rootDoc._fontColor = color; + selected._fontColor = color; if (color) { editorView?.state && RichTextMenu.Instance.setHighlight(color, editorView, editorView?.dispatch); } @@ -769,7 +765,7 @@ Scripting.addGlobal(function toggleBold(checkResult?: boolean) { console.log("editorView"); editorView?.state && RichTextMenu.Instance.toggleBold(editorView, true); } - SelectionManager.Views().filter(i => StrCast(i.rootDoc.type) === DocumentType.RTF).map(dv => dv.props.Document.bold = !dv.props.Document.bold); + SelectionManager.Docs().filter(doc => StrCast(doc.type) === DocumentType.RTF).map(doc => doc.bold = !doc.bold); Doc.UserDoc().bold = !Doc.UserDoc().bold; return Doc.UserDoc().bold; }); @@ -784,7 +780,7 @@ Scripting.addGlobal(function toggleUnderline(checkResult?: boolean) { console.log("editorView"); editorView?.state && RichTextMenu.Instance.toggleUnderline(editorView, true); } - SelectionManager.Views().filter(i => StrCast(i.rootDoc.type) === DocumentType.RTF).map(dv => dv.props.Document.underline = !dv.props.Document.underline); + SelectionManager.Docs().filter(doc => StrCast(doc.type) === DocumentType.RTF).map(doc => doc.underline = !doc.underline); Doc.UserDoc().underline = !Doc.UserDoc().underline; return Doc.UserDoc().underline; }); @@ -799,7 +795,7 @@ Scripting.addGlobal(function toggleItalic(checkResult?: boolean) { console.log("editorView"); editorView?.state && RichTextMenu.Instance.toggleItalic(editorView, true); } - SelectionManager.Views().filter(i => StrCast(i.rootDoc.type) === DocumentType.RTF).map(dv => dv.props.Document.italic = !dv.props.Document.italic); + SelectionManager.Docs().filter(doc => StrCast(doc.type) === DocumentType.RTF).map(doc => doc.italic = !doc.italic); Doc.UserDoc().italic = !Doc.UserDoc().italic; return Doc.UserDoc().italic; }); @@ -841,7 +837,7 @@ Scripting.addGlobal(function setActiveInkTool(tool: string, checkResult?: boolea Scripting.addGlobal(function setStrokeWidth(width: number, checkResult?: boolean) { if (checkResult) { - const selected = SelectionManager.Views().length ? SelectionManager.Views()[0].rootDoc : undefined; + const selected = SelectionManager.Docs().lastElement(); if (selected && selected.type === DocumentType.INK) { return Number(selected.strokeWidth); } else { @@ -850,13 +846,13 @@ Scripting.addGlobal(function setStrokeWidth(width: number, checkResult?: boolean } } Doc.UserDoc().activeInkWidth = width; - SelectionManager.Views().filter(i => StrCast(i.rootDoc.type) === DocumentType.INK).map(i => i.rootDoc.strokeWidth = Number(width)); + SelectionManager.Docs().filter(doc => StrCast(doc.type) === DocumentType.INK).map(doc => doc.strokeWidth = Number(width)); }); // toggle: Set overlay status of selected document Scripting.addGlobal(function setStrokeColor(color?: string, checkResult?: boolean) { if (checkResult) { - const selected = SelectionManager.Views().length ? SelectionManager.Views()[0].rootDoc : undefined; + const selected = SelectionManager.Docs().lastElement(); if (selected && selected.type === DocumentType.INK) { return selected.color; } else { @@ -865,7 +861,7 @@ Scripting.addGlobal(function setStrokeColor(color?: string, checkResult?: boolea } } SetActiveInkColor(StrCast(color)); - SelectionManager.Views().filter(i => StrCast(i.rootDoc.type) === DocumentType.INK).map(i => i.rootDoc.color = String(color)); + SelectionManager.Docs().filter(doc => StrCast(doc.type) === DocumentType.INK).map(doc => doc.color = String(color)); }); @@ -873,7 +869,7 @@ Scripting.addGlobal(function setStrokeColor(color?: string, checkResult?: boolea * webSetURL **/ Scripting.addGlobal(function webSetURL(url: string, checkResult?: boolean) { - const selected = SelectionManager.Views().length ? SelectionManager.Views()[0].rootDoc : undefined; + const selected = SelectionManager.Docs().lastElement(); console.log("URL: ", url); if (checkResult && selected && selected.type === DocumentType.WEB) { return Cast(selected.data, WebField, null).url; @@ -888,7 +884,7 @@ Scripting.addGlobal(function webSetURL(url: string, checkResult?: boolean) { * toggleSchemaPreview **/ Scripting.addGlobal(function toggleSchemaPreview(checkResult?: boolean) { - const selected = SelectionManager.Views().length ? SelectionManager.Views()[0].rootDoc : undefined; + const selected = SelectionManager.Docs().lastElement(); console.log(selected && selected.title); if (checkResult && selected) { const result: boolean = NumCast(selected.schemaPreviewWidth) > 0; diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx index 3d9d9543d..3919fbf94 100644 --- a/src/client/views/nodes/formattedText/RichTextMenu.tsx +++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx @@ -279,33 +279,33 @@ export class RichTextMenu extends AntimodeMenu { }); } - toggleBold = (view: EditorView, forceBool?:boolean) => { - const mark = view.state.schema.mark(view.state.schema.marks.strong, {strong: forceBool}); + toggleBold = (view: EditorView, forceBool?: boolean) => { + const mark = view.state.schema.mark(view.state.schema.marks.strong, { strong: forceBool }); this.setMark(mark, view.state, view.dispatch, false); view.focus(); } - toggleUnderline = (view: EditorView, forceBool?:boolean) => { - const mark = view.state.schema.mark(view.state.schema.marks.underline, {underline: forceBool}); + toggleUnderline = (view: EditorView, forceBool?: boolean) => { + const mark = view.state.schema.mark(view.state.schema.marks.underline, { underline: forceBool }); this.setMark(mark, view.state, view.dispatch, false); view.focus(); } - toggleItalic = (view: EditorView, forceBool?:boolean) => { - const mark = view.state.schema.mark(view.state.schema.marks.em, {em: forceBool}); + toggleItalic = (view: EditorView, forceBool?: boolean) => { + const mark = view.state.schema.mark(view.state.schema.marks.em, { em: forceBool }); this.setMark(mark, view.state, view.dispatch, false); view.focus(); } - setFontSize = (size:number, view: EditorView) => { + setFontSize = (size: number, view: EditorView) => { const fmark = view.state.schema.marks.pFontSize.create({ fontSize: size }); this.setMark(fmark, view.state, (tx: any) => view.dispatch(tx.addStoredMark(fmark)), true); view.focus(); this.updateMenu(view, undefined, this.props); } - setFontFamily = (family:string, view: EditorView) => { + setFontFamily = (family: string, view: EditorView) => { const fmark = view.state.schema.marks.pFontFamily.create({ family: family }); this.setMark(fmark, view.state, (tx: any) => view.dispatch(tx.addStoredMark(fmark)), true); view.focus(); @@ -516,7 +516,7 @@ export class RichTextMenu extends AntimodeMenu { get TextView() { return (this.view as any)?.TextView as FormattedTextBox; } get TextViewFieldKey() { return this.TextView?.props.fieldKey; } - + @action setActiveHighlight(color: string) { this.activeHighlightColor = color; } @@ -566,7 +566,7 @@ export class RichTextMenu extends AntimodeMenu { if (linkDoc instanceof Doc) { const anchor1 = await Cast(linkDoc.anchor1, Doc); const anchor2 = await Cast(linkDoc.anchor2, Doc); - const currentDoc = SelectionManager.Views().length && SelectionManager.Views()[0].props.Document; + const currentDoc = SelectionManager.Docs().lastElement(); if (currentDoc && anchor1 && anchor2) { if (Doc.AreProtosEqual(currentDoc, anchor1)) { return StrCast(anchor2.title); -- cgit v1.2.3-70-g09d2 From 1ca0db9a94e8f1141f8f52446afb53e29cff0e01 Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 15 Sep 2021 09:30:15 -0400 Subject: fixed dragging document in filesystem to not create duplicates in some cases --- src/client/views/collections/CollectionSubView.tsx | 2 +- src/client/views/collections/CollectionTreeView.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/client/views/collections/CollectionSubView.tsx') diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 06d20f015..cb8b55cb2 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -216,7 +216,7 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T, moreProps?: const targetDocments = DocListCast(this.dataDoc[this.props.fieldKey]); const someMoved = !docDragData.userDropAction && docDragData.draggedDocuments.some(drag => targetDocments.includes(drag)); if (someMoved) docDragData.droppedDocuments = docDragData.droppedDocuments.map((drop, i) => targetDocments.includes(docDragData.draggedDocuments[i]) ? docDragData.draggedDocuments[i] : drop); - if ((!dropAction || dropAction === "move" || someMoved) && docDragData.moveDocument) { + if ((!dropAction || dropAction === "same" || dropAction === "move" || someMoved) && docDragData.moveDocument) { 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) { diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 624a0bf4a..3852987b9 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -108,7 +108,7 @@ export class CollectionTreeView extends CollectionSubView { const dragData = de.complete.docDragData; if (dragData) { - const isInTree = () => dragData.draggedDocuments.some(d => d.context === this.doc && this.childDocs.includes(d)); + const isInTree = () => Doc.AreProtosEqual(dragData.treeViewDoc, this.props.Document) || dragData.draggedDocuments.some(d => d.context === this.doc && this.childDocs.includes(d)); dragData.dropAction = targetAction && !isInTree() ? targetAction : this.doc === dragData?.treeViewDoc ? "same" : dragData.dropAction; } } -- cgit v1.2.3-70-g09d2