From a6cc25e5d03ffed16bfaa32e48e9cc2eaff7deaf Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 7 Nov 2023 13:48:26 -0500 Subject: Changed how selection works to avoid invalidations. Fixed Cast problem with ProxyFields that caused renameEmbedding to infinite loop.. Changed brushing for the same reason. Cleaned up a few things with filter code. --- src/client/views/DocComponent.tsx | 8 ++++---- src/client/views/StyleProvider.tsx | 6 +++--- src/client/views/collections/CollectionMenu.tsx | 19 ------------------- src/client/views/collections/CollectionSubView.tsx | 2 +- src/client/views/collections/TabDocView.tsx | 4 ++-- .../CollectionFreeFormLinkView.tsx | 20 ++++++++++---------- .../collectionSchema/CollectionSchemaView.tsx | 12 +++++++++++- src/client/views/nodes/DocumentView.tsx | 18 +++++++++++++++--- src/client/views/nodes/MapBox/MapBox.tsx | 4 ++-- src/client/views/nodes/MapBox/MapBox2.tsx | 4 ++-- src/client/views/nodes/WebBox.tsx | 4 ++-- src/client/views/pdf/Annotation.tsx | 2 +- src/client/views/pdf/PDFViewer.tsx | 12 +++--------- 13 files changed, 56 insertions(+), 59 deletions(-) (limited to 'src/client/views') diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index 483b92957..57cea77c9 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -1,10 +1,10 @@ import { action, computed, observable } from 'mobx'; import { DateField } from '../../fields/DateField'; -import { Doc, DocListCast, HierarchyMapping, Opt, ReverseHierarchyMap } from '../../fields/Doc'; -import { AclAdmin, AclAugment, AclEdit, AclPrivate, AclReadonly, DocAcl, DocData } from '../../fields/DocSymbols'; +import { Doc, DocListCast, Opt } from '../../fields/Doc'; +import { AclAdmin, AclAugment, AclEdit, AclPrivate, AclReadonly, DocData } from '../../fields/DocSymbols'; import { List } from '../../fields/List'; -import { Cast, DocCast, StrCast } from '../../fields/Types'; -import { distributeAcls, GetEffectiveAcl, inheritParentAcls, SharingPermissions } from '../../fields/util'; +import { Cast } from '../../fields/Types'; +import { GetEffectiveAcl, inheritParentAcls } from '../../fields/util'; import { returnFalse } from '../../Utils'; import { DocUtils } from '../documents/Documents'; import { DocumentType } from '../documents/DocumentTypes'; diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx index c6d3efd0c..72d7cd1c5 100644 --- a/src/client/views/StyleProvider.tsx +++ b/src/client/views/StyleProvider.tsx @@ -7,13 +7,13 @@ import { extname } from 'path'; import { BsArrowDown, BsArrowDownUp, BsArrowUp } from 'react-icons/bs'; import { FaFilter } from 'react-icons/fa'; import { Doc, Opt, StrListCast } from '../../fields/Doc'; +import { DocViews } from '../../fields/DocSymbols'; import { BoolCast, Cast, DocCast, ImageCast, NumCast, StrCast } from '../../fields/Types'; import { DashColor, lightOrDark, Utils } from '../../Utils'; import { CollectionViewType, DocumentType } from '../documents/DocumentTypes'; import { DocFocusOrOpen, DocumentManager } from '../util/DocumentManager'; import { IsFollowLinkScript } from '../util/LinkFollower'; import { LinkManager } from '../util/LinkManager'; -import { SelectionManager } from '../util/SelectionManager'; import { SettingsManager } from '../util/SettingsManager'; import { undoBatch, UndoManager } from '../util/UndoManager'; import { TreeSort } from './collections/TreeSort'; @@ -116,7 +116,7 @@ export function DefaultStyleProvider(doc: Opt, props: Opt dv.rootDoc === doc); + const selected = Array.from(doc?.[DocViews]??[]).filter(dv => dv.SELECTED).length; const highlightIndex = Doc.isBrushedHighlightedDegree(doc) || (selected ? Doc.DocBrushStatus.selfBrushed : 0); const highlightColor = ['transparent', 'rgb(68, 118, 247)', selected ? "black" : 'rgb(68, 118, 247)', 'orange', 'lightBlue'][highlightIndex]; const highlightStyle = ['solid', 'dashed', 'solid', 'solid', 'solid'][highlightIndex]; @@ -282,7 +282,7 @@ export function DefaultStyleProvider(doc: Opt, props: Opt Utils.IsRecursiveFilter(f) && f !== Utils.noDragsDocFilter).length || docProps?.childFiltersByRanges().length + : docProps?.childFilters?.().filter(f => Utils.IsRecursiveFilter(f) && f !== Utils.noDragDocsFilter).length || docProps?.childFiltersByRanges().length ? 'orange' //'inheritsFilter' : undefined; return !showFilterIcon ? null : ( diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx index 52cf40635..d0eadd9aa 100644 --- a/src/client/views/collections/CollectionMenu.tsx +++ b/src/client/views/collections/CollectionMenu.tsx @@ -557,25 +557,6 @@ export class CollectionViewBaseChrome extends React.Component{Doc.isDocPinned(targetDoc) ? 'Unpin from presentation' : 'Pin to presentation'}} placement="top"> - - - ); - } @undoBatch @action diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 8a1ba0df1..e9192ebbe 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -125,7 +125,7 @@ export function CollectionSubView(moreProps?: X) { const docsforFilter: Doc[] = []; childDocs.forEach(d => { // dragging facets - const dragged = this.props.childFilters?.().some(f => f.includes(Utils.noDragsDocFilter)); + const dragged = this.props.childFilters?.().some(f => f.includes(Utils.noDragDocsFilter)); if (dragged && SnappingManager.GetCanEmbed() && DragManager.docsBeingDragged.includes(d)) return false; let notFiltered = d.z || Doc.IsSystem(d) || DocUtils.FilterDocs([d], this.unrecursiveDocFilters(), childFiltersByRanges, this.props.Document).length > 0; if (notFiltered) { diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx index 26aa5a121..41f3b2603 100644 --- a/src/client/views/collections/TabDocView.tsx +++ b/src/client/views/collections/TabDocView.tsx @@ -53,7 +53,7 @@ export class TabDocView extends React.Component { @observable _isActive: boolean = false; @observable _isAnyChildContentActive = false; @computed get _isUserActivated() { - return SelectionManager.Views().some(view => view.rootDoc === this._document) || this._isAnyChildContentActive; + return SelectionManager.IsSelected(this._document) || this._isAnyChildContentActive; } @computed get _isContentActive() { return this._isUserActivated || this._hovering; @@ -203,7 +203,7 @@ export class TabDocView extends React.Component { } }); tab._disposers.selectionDisposer = reaction( - () => SelectionManager.Views().some(view => view.rootDoc === this._document), + () => SelectionManager.IsSelected(this._document), action(selected => { if (selected) this._activated = true; const toggle = tab.element[0].children[2].children[0] as HTMLInputElement; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx index 24a758d8c..aca6df3c9 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx @@ -1,7 +1,7 @@ import { action, computed, IReactionDisposer, observable, reaction } from 'mobx'; import { observer } from 'mobx-react'; import { Doc, Field } from '../../../../fields/Doc'; -import { DocCss } from '../../../../fields/DocSymbols'; +import { Brushed, DocCss } from '../../../../fields/DocSymbols'; import { Id } from '../../../../fields/FieldSymbols'; import { List } from '../../../../fields/List'; import { Cast, NumCast, StrCast } from '../../../../fields/Types'; @@ -223,8 +223,8 @@ export class CollectionFreeFormLinkView extends React.Component - - + + diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index f73c037f4..ce63a2cf2 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -86,7 +86,17 @@ export class CollectionSchemaView extends CollectionSubView() { } @computed get _selectedDocs() { - return SelectionManager.Docs().filter(doc => Doc.AreProtosEqual(DocCast(doc.embedContainer), this.rootDoc)); + const selected = SelectionManager.Docs().filter(doc => Doc.AreProtosEqual(DocCast(doc.embedContainer), this.rootDoc)); + if (!selected.length) { + for (const sel of SelectionManager.Docs()) { + const contextPath = DocumentManager.GetContextPath(sel, true); + if (contextPath.includes(this.rootDoc)) { + const parentInd = contextPath.indexOf(this.rootDoc); + return parentInd < contextPath.length - 1 ? [contextPath[parentInd + 1]] : []; + } + } + } + return selected; } @computed get documentKeys() { diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 98b13f90f..d87efb7b1 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -5,7 +5,7 @@ import { observer } from 'mobx-react'; import { computedFn } from 'mobx-utils'; import { Bounce, Fade, Flip, LightSpeed, Roll, Rotate, Zoom } from 'react-reveal'; import { Doc, DocListCast, Field, Opt, StrListCast } from '../../../fields/Doc'; -import { AclPrivate, Animation, AudioPlay, DocData, Width } from '../../../fields/DocSymbols'; +import { AclPrivate, Animation, AudioPlay, DocData, DocViews, Width } from '../../../fields/DocSymbols'; import { Id } from '../../../fields/FieldSymbols'; import { InkTool } from '../../../fields/InkField'; import { List } from '../../../fields/List'; @@ -900,7 +900,7 @@ export class DocumentViewInternal extends DocComponent this._rootSelected; + rootSelected = () => this._rootSelected; panelHeight = () => this.props.PanelHeight() - this.headerMargin; screenToLocal = () => this.props.ScreenToLocalTransform().translate(0, -this.headerMargin); onClickFunc: any = () => (this.disableClickScriptFunc ? undefined : this.onClickHandler); @@ -1345,6 +1345,13 @@ export class DocumentViewInternal extends DocComponent { public static ROOT_DIV = 'documentView-effectsWrapper'; + @observable _selected = false; + public get SELECTED() { + return this._selected; + } + public set SELECTED(val) { + this._selected = val; + } @observable public static Interacting = false; @observable public static LongPress = false; @observable public static ExploreMode = false; @@ -1579,7 +1586,7 @@ export class DocumentView extends React.Component { scaleToScreenSpace = () => (1 / (this.props.NativeDimScaling?.() || 1)) * this.screenToLocalTransform().Scale; docViewPathFunc = () => this.docViewPath; - isSelected = (outsideReaction?: boolean) => SelectionManager.IsSelected(this, outsideReaction); + isSelected = () => SelectionManager.IsSelected(this); select = (extendSelection: boolean, focusSelection?: boolean) => { SelectionManager.SelectView(this, extendSelection); if (focusSelection) { @@ -1602,7 +1609,10 @@ export class DocumentView extends React.Component { .ScreenToLocalTransform() .translate(-this.centeringX, -this.centeringY) .scale(this.trueNativeWidth() ? 1 / this.nativeScaling : 1); + + @action componentDidMount() { + this.rootDoc[DocViews].add(this); this._disposers.updateContentsScript = reaction( () => ScriptCast(this.rootDoc.updateContentsScript)?.script?.run({ this: this.props.Document, self: Cast(this.rootDoc, Doc, null) || this.props.Document }).result, output => output @@ -1617,7 +1627,9 @@ export class DocumentView extends React.Component { ); !BoolCast(this.props.Document.dontRegisterView, this.props.dontRegisterView) && DocumentManager.Instance.AddView(this); } + @action componentWillUnmount() { + this.rootDoc[DocViews].delete(this); Object.values(this._disposers).forEach(disposer => disposer?.()); !BoolCast(this.props.Document.dontRegisterView, this.props.dontRegisterView) && DocumentManager.Instance.RemoveView(this); } diff --git a/src/client/views/nodes/MapBox/MapBox.tsx b/src/client/views/nodes/MapBox/MapBox.tsx index 50b070e7f..08dda2e1f 100644 --- a/src/client/views/nodes/MapBox/MapBox.tsx +++ b/src/client/views/nodes/MapBox/MapBox.tsx @@ -307,8 +307,8 @@ export class MapBox extends ViewBoxAnnotatableComponent this.props.PanelWidth() / (this.props.NativeDimScaling?.() || 1) - this.sidebarWidth(); panelHeight = () => this.props.PanelHeight() / (this.props.NativeDimScaling?.() || 1); scrollXf = () => this.props.ScreenToLocalTransform().translate(0, NumCast(this.layoutDoc._layout_scrollTop)); - transparentFilter = () => [...this.props.childFilters(), Utils.IsTransparentFilter()]; - opaqueFilter = () => [...this.props.childFilters(), Utils.IsOpaqueFilter()]; + transparentFilter = () => [...this.props.childFilters(), Utils.TransparentBackgroundFilter]; + opaqueFilter = () => [...this.props.childFilters(), Utils.OpaqueBackgroundFilter]; infoWidth = () => this.props.PanelWidth() / 5; infoHeight = () => this.props.PanelHeight() / 5; anchorMenuClick = () => this._sidebarRef.current?.anchorMenuClick; diff --git a/src/client/views/nodes/MapBox/MapBox2.tsx b/src/client/views/nodes/MapBox/MapBox2.tsx index 407a91dd0..d38857d90 100644 --- a/src/client/views/nodes/MapBox/MapBox2.tsx +++ b/src/client/views/nodes/MapBox/MapBox2.tsx @@ -547,8 +547,8 @@ export class MapBox2 extends ViewBoxAnnotatableComponent this.props.PanelWidth() / (this.props.NativeDimScaling?.() || 1) - this.sidebarWidth(); panelHeight = () => this.props.PanelHeight() / (this.props.NativeDimScaling?.() || 1); scrollXf = () => this.props.ScreenToLocalTransform().translate(0, NumCast(this.layoutDoc._layout_scrollTop)); - transparentFilter = () => [...this.props.childFilters(), Utils.IsTransparentFilter()]; - opaqueFilter = () => [...this.props.childFilters(), Utils.IsOpaqueFilter()]; + transparentFilter = () => [...this.props.childFilters(), Utils.TransparentBackgroundFilter]; + opaqueFilter = () => [...this.props.childFilters(), Utils.OpaqueBackgroundFilter]; infoWidth = () => this.props.PanelWidth() / 5; infoHeight = () => this.props.PanelHeight() / 5; anchorMenuClick = () => this._sidebarRef.current?.anchorMenuClick; diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index 2aca314da..5c526fe38 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -1053,8 +1053,8 @@ export class WebBox extends ViewBoxAnnotatableComponent this.props.PanelHeight() / (this.props.NativeDimScaling?.() || 1); scrollXf = () => this.props.ScreenToLocalTransform().translate(0, NumCast(this.layoutDoc._layout_scrollTop)); anchorMenuClick = () => this._sidebarRef.current?.anchorMenuClick; - transparentFilter = () => [...this.props.childFilters(), Utils.IsTransparentFilter()]; - opaqueFilter = () => [...this.props.childFilters(), Utils.noDragsDocFilter, ...(SnappingManager.GetCanEmbed() ? [] : [Utils.IsOpaqueFilter()])]; + transparentFilter = () => [...this.props.childFilters(), Utils.TransparentBackgroundFilter]; + opaqueFilter = () => [...this.props.childFilters(), Utils.noDragDocsFilter, ...(SnappingManager.GetCanEmbed() ? [] : [Utils.OpaqueBackgroundFilter])]; childStyleProvider = (doc: Doc | undefined, props: Opt, property: string): any => { if (doc instanceof Doc && property === StyleProp.PointerEvents) { if (this.inlineTextAnnotations.includes(doc)) return 'none'; diff --git a/src/client/views/pdf/Annotation.tsx b/src/client/views/pdf/Annotation.tsx index 52904b852..17a8048e9 100644 --- a/src/client/views/pdf/Annotation.tsx +++ b/src/client/views/pdf/Annotation.tsx @@ -90,7 +90,7 @@ class RegionAnnotation extends React.Component { @computed get linkHighlighted() { for (const link of LinkManager.Instance.getAllDirectLinks(this.props.document)) { const a1 = LinkManager.getOppositeAnchor(link, this.props.document); - if (a1 && Doc.IsBrushedDegreeUnmemoized(DocCast(a1.annotationOn, this.props.document))) return true; + if (a1 && Doc.IsBrushedDegree(DocCast(a1.annotationOn, this.props.document))) return true; } } diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index 43b662f0f..c1b2749fb 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -110,13 +110,7 @@ export class PDFViewer extends React.Component { this._disposers.selected = reaction( () => this.props.isSelected(), - selected => { - // if (!selected) { - // Array.from(this._savedAnnotations.values()).forEach(v => v.forEach(a => a.remove())); - // Array.from(this._savedAnnotations.keys()).forEach(k => this._savedAnnotations.set(k, [])); - // } - SelectionManager.Views().length === 1 && this.setupPdfJsViewer(); - }, + selected => SelectionManager.Views().length === 1 && this.setupPdfJsViewer(), { fireImmediately: true } ); this._disposers.curPage = reaction( @@ -509,8 +503,8 @@ export class PDFViewer extends React.Component { overlayTransform = () => this.scrollXf().scale(1 / NumCast(this.props.layoutDoc._freeform_scale, 1)); panelWidth = () => this.props.PanelWidth() / (this.props.NativeDimScaling?.() || 1); panelHeight = () => this.props.PanelHeight() / (this.props.NativeDimScaling?.() || 1); - transparentFilter = () => [...this.props.childFilters(), Utils.IsTransparentFilter()]; - opaqueFilter = () => [...this.props.childFilters(), Utils.noDragsDocFilter, ...(SnappingManager.GetCanEmbed() && this.props.isContentActive() ? [] : [Utils.IsOpaqueFilter()])]; + transparentFilter = () => [...this.props.childFilters(), Utils.TransparentBackgroundFilter]; + opaqueFilter = () => [...this.props.childFilters(), Utils.noDragDocsFilter, ...(SnappingManager.GetCanEmbed() && this.props.isContentActive() ? [] : [Utils.OpaqueBackgroundFilter])]; childStyleProvider = (doc: Doc | undefined, props: Opt, property: string): any => { if (doc instanceof Doc && property === StyleProp.PointerEvents) { if (this.inlineTextAnnotations.includes(doc) || this.props.isContentActive() === false) return 'none'; -- cgit v1.2.3-70-g09d2