From f303131b40fac4909ab2730b369ef3bdb8e00b1d Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 21 Feb 2023 09:53:18 -0500 Subject: fixed explore mode zooming. don't show doc decorations until you move outside of the document, fixed dragging radius button over webbox to still get pointer events. fixed selection text in coments for web boxes.. fixed setting default background color for notes. fixed mode buttons to trigger click behavior before double click behavior. fixed events on nested text boxes that are linkAnchors (like text quotes in sidebar comments), --- src/client/views/DocumentDecorations.tsx | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'src/client/views/DocumentDecorations.tsx') diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 41f4a17fb..21f63ada4 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -2,7 +2,7 @@ import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Tooltip } from '@material-ui/core'; import { IconButton } from 'browndash-components'; -import { action, computed, observable, reaction } from 'mobx'; +import { action, computed, observable, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import { FaUndo } from 'react-icons/fa'; import { DateField } from '../../fields/DateField'; @@ -182,7 +182,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P dragData.removeDocument = dragDocView.props.removeDocument; dragData.isDocDecorationMove = true; dragData.canEmbed = dragTitle; - this._hidden = this.Interacting = true; + this._hidden = true; DragManager.StartDocumentDrag( SelectionManager.Views().map(dv => dv.ContentDiv!), dragData, @@ -191,7 +191,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P { dragComplete: action(e => { dragData.canEmbed && SelectionManager.DeselectAll(); - this._hidden = this.Interacting = false; + this._hidden = false; }), hideSource: true, } @@ -293,7 +293,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P */ @action onRadiusDown = (e: React.PointerEvent): void => { - this._isRounding = true; + this._isRounding = DocumentDecorations.Instance.Interacting = true; this._resizeUndo = UndoManager.StartBatch('DocDecs set radius'); // Call util move event function setupMoveUpEvents( @@ -316,10 +316,11 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P return false; }, // moveEvent action(e => { - this._isRounding = false; + DocumentDecorations.Instance.Interacting = this._isRounding = false; this._resizeUndo?.end(); }), // upEvent - e => {} // clickEvent + e => {}, // clickEvent, + true ); }; @@ -710,11 +711,14 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P return this._rotCenter; } + @observable _showNothing = true; + render() { const { b, r, x, y } = this.Bounds; const bounds = { b, r, x, y }; - const seldocview = SelectionManager.Views().slice(-1)[0]; + const seldocview = SelectionManager.Views().lastElement(); if (SnappingManager.GetIsDragging() || bounds.r - bounds.x < 1 || bounds.x === Number.MAX_VALUE || !seldocview || this._hidden || isNaN(bounds.r) || isNaN(bounds.b) || isNaN(bounds.x) || isNaN(bounds.y)) { + setTimeout(action(() => (this._showNothing = true))); return null; } // hide the decorations if the parent chooses to hide it or if the document itself hides it @@ -812,7 +816,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P ); return ( -
+
(this._showNothing = false))}>
Date: Tue, 21 Feb 2023 10:04:34 -0500 Subject: from last - fixes to showing doc decorations when pointer leaves selection box. --- src/client/views/DocumentDecorations.tsx | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'src/client/views/DocumentDecorations.tsx') diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 21f63ada4..c3ef7570b 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -66,7 +66,19 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P DocumentDecorations.Instance = this; reaction( () => SelectionManager.Views().slice(), - action(docs => (this._editingTitle = false)) + action(docs => { + docs.length > 1 && (this._showNothing = false); // show decorations if multiple docs are selected + this._editingTitle = false; + }) + ); + document.addEventListener( + // show decorations whenever pointer moves outside of selection bounds. + 'pointermove', + action(e => { + if (this.Bounds.x !== Number.MAX_VALUE && (this.Bounds.x > e.clientX || this.Bounds.r < e.clientX || this.Bounds.y > e.clientY || this.Bounds.b < e.clientY)) { + this._showNothing = false; + } + }) ); } @@ -816,7 +828,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
); return ( -
(this._showNothing = false))}> +
Date: Wed, 22 Feb 2023 21:06:34 -0500 Subject: fixed hiding doc decorations when clicking on a nested doc. finished removing old view spec code in favor of saving and restoring anchor data. --- src/client/views/DocumentDecorations.tsx | 1 + .../views/collections/CollectionTimeView.tsx | 75 +++++++++++++--------- .../collectionFreeForm/CollectionFreeFormView.tsx | 26 ++------ src/client/views/nodes/DocumentView.tsx | 9 +-- src/client/views/nodes/PDFBox.tsx | 7 +- src/client/views/nodes/WebBox.tsx | 4 +- .../views/nodes/formattedText/FormattedTextBox.tsx | 7 +- src/client/views/nodes/trails/PresBox.tsx | 25 +++++++- src/client/views/pdf/PDFViewer.tsx | 2 +- 9 files changed, 87 insertions(+), 69 deletions(-) (limited to 'src/client/views/DocumentDecorations.tsx') diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index c3ef7570b..4e51f10a8 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -67,6 +67,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P reaction( () => SelectionManager.Views().slice(), action(docs => { + this._showNothing = true; docs.length > 1 && (this._showNothing = false); // show decorations if multiple docs are selected this._editingTitle = false; }) diff --git a/src/client/views/collections/CollectionTimeView.tsx b/src/client/views/collections/CollectionTimeView.tsx index 8ec683e6d..e6f29ec37 100644 --- a/src/client/views/collections/CollectionTimeView.tsx +++ b/src/client/views/collections/CollectionTimeView.tsx @@ -7,7 +7,7 @@ import { ObjectField } from '../../../fields/ObjectField'; import { RichTextField } from '../../../fields/RichTextField'; import { listSpec } from '../../../fields/Schema'; import { ComputedField, ScriptField } from '../../../fields/ScriptField'; -import { Cast, NumCast, StrCast } from '../../../fields/Types'; +import { BoolCast, Cast, NumCast, StrCast } from '../../../fields/Types'; import { emptyFunction, returnEmptyString, returnFalse, returnTrue, setupMoveUpEvents } from '../../../Utils'; import { Docs } from '../../documents/Documents'; import { DocumentType } from '../../documents/DocumentTypes'; @@ -21,6 +21,8 @@ import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormV import { CollectionSubView } from './CollectionSubView'; import './CollectionTimeView.scss'; import React = require('react'); +import { DocFocusOptions } from '../nodes/DocumentView'; +import { PresBox } from '../nodes/trails'; @observer export class CollectionTimeView extends CollectionSubView() { @@ -31,17 +33,27 @@ export class CollectionTimeView extends CollectionSubView() { @observable _viewDefDivClick: Opt; @observable _focusPivotField: Opt; + async componentDidMount() { + this.props.setContentView?.(this); + //const detailView = (await DocCastAsync(this.props.Document.childClickedOpenTemplateView)) || DocUtils.findTemplate("detailView", StrCast(this.rootDoc.type), ""); + ///const childText = "const alias = getAlias(self); switchView(alias, detailView); alias.dropAction='alias'; useRightSplit(alias, shiftKey); "; + runInAction(() => { + this._childClickedScript = ScriptField.MakeScript('openInLightbox(self)', { this: Doc.name }); + this._viewDefDivClick = ScriptField.MakeScript('pivotColumnClick(this,payload)', { payload: 'any' }); + }); + } + + get pivotField() { + return this._focusPivotField || StrCast(this.layoutDoc._pivotField); + } + getAnchor = (addAsAnnotation: boolean) => { const anchor = Docs.Create.HTMLAnchorDocument([], { title: ComputedField.MakeFunction(`"${this.pivotField}"])`) as any, annotationOn: this.rootDoc, }); - - // save view spec information for anchor - const proto = Doc.GetProto(anchor); - proto.pivotField = this.pivotField; - proto.docFilters = ObjectField.MakeCopy(this.layoutDoc._docFilters as ObjectField) || new List([]); - proto.docRangeFilters = ObjectField.MakeCopy(this.layoutDoc._docRangeFilters as ObjectField) || new List([]); + anchor.presPinPivotField = this.pivotField; // should be captured in pinDocView below + PresBox.pinDocView(anchor, { pinData: { viewType: true, filters: true } }, this.rootDoc); if (addAsAnnotation) { // when added as an annotation, links to anchors can be found as links to the document even if the anchors are not rendered @@ -54,34 +66,33 @@ export class CollectionTimeView extends CollectionSubView() { return anchor; }; - async componentDidMount() { - this.props.setContentView?.(this); - //const detailView = (await DocCastAsync(this.props.Document.childClickedOpenTemplateView)) || DocUtils.findTemplate("detailView", StrCast(this.rootDoc.type), ""); - ///const childText = "const alias = getAlias(self); switchView(alias, detailView); alias.dropAction='alias'; useRightSplit(alias, shiftKey); "; - runInAction(() => { - this._childClickedScript = ScriptField.MakeScript('openInLightbox(self)', { this: Doc.name }); - this._viewDefDivClick = ScriptField.MakeScript('pivotColumnClick(this,payload)', { payload: 'any' }); - }); - } - - get pivotField() { - return this._focusPivotField || StrCast(this.layoutDoc._pivotField); - } @action - setViewSpec = (anchor: Doc, preview: boolean) => { - if (preview) { + scrollFocus = (anchor: Doc, options: DocFocusOptions) => { + if (options.preview) { // if in preview, then override document's fields with view spec - this._focusFilters = StrListCast(Doc.GetProto(anchor).docFilters); - this._focusRangeFilters = StrListCast(Doc.GetProto(anchor).docRangeFilters); - this._focusPivotField = StrCast(anchor.pivotField); - } else if (anchor.pivotField !== undefined) { - // otherwise set document's fields based on anchor view spec - this.layoutDoc._prevFilterIndex = 1; - this.layoutDoc._pivotField = StrCast(anchor.pivotField); - this.layoutDoc._docFilters = new List(StrListCast(anchor.docFilters)); - this.layoutDoc._docRangeFilters = new List(StrListCast(anchor.docRangeFilters)); + this._focusFilters = StrListCast(anchor.presPinDocFilters); + this._focusRangeFilters = StrListCast(anchor.presPinDocRangeFilters); + this._focusPivotField = StrCast(anchor.presPinPivotField); + return undefined; } - return 0; + const focusSpeed = options.instant ? 0 : options.zoomTime ?? 500; + + // should be part of restoreTargetDocView + this.layoutDoc._prevFilterIndex = 1; + this.layoutDoc._pivotField = anchor.presPinPivotField; + + return PresBox.restoreTargetDocView( + this.props.DocumentView?.(), // + { pinDocLayout: BoolCast(anchor.presPinLayout) }, + anchor, + focusSpeed, + { + viewType: anchor.presPinViewType ? true : false, + filters: anchor.presPinDocFilters || anchor.presPinDocRangeFilters ? true : false, + } + ) + ? focusSpeed + : undefined; }; layoutEngine = () => this._layoutEngine; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index d69e6b810..3300bc387 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -1591,25 +1591,14 @@ export class CollectionFreeFormView extends CollectionSubView { - if (preview) { - this._focusFilters = StrListCast(Doc.GetProto(anchor).docFilters); - this._focusRangeFilters = StrListCast(Doc.GetProto(anchor).docRangeFilters); - } else { - if (anchor.docFilters) { - this.layoutDoc._docFilters = new List(StrListCast(anchor.docFilters)); - } - if (anchor.docRangeFilters) { - this.layoutDoc._docRangeFilters = new List(StrListCast(anchor.docRangeFilters)); - } - } - return 0; - }; - @action scrollFocus = (anchor: Doc, options: DocFocusOptions) => { const focusSpeed = options.instant ? 0 : options.zoomTime ?? 500; + if (options.preview) { + this._focusFilters = StrListCast(anchor.presPinDocFilters); + this._focusRangeFilters = StrListCast(anchor.presPinDocRangeFilters); + return undefined; + } return PresBox.restoreTargetDocView( this.props.DocumentView?.(), // { pinDocLayout: BoolCast(anchor.presPinLayout) }, @@ -1618,6 +1607,7 @@ export class CollectionFreeFormView extends CollectionSubView([]); + PresBox.pinDocView(anchor, { pinData: { pannable: true, viewType: true, filters: true } }, this.rootDoc); if (addAsAnnotation) { if (Cast(this.dataDoc[this.props.fieldKey + '-annotations'], listSpec(Doc), null) !== undefined) { diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 94eb0b092..0a923bca9 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -107,6 +107,7 @@ export interface DocFocusOptions { afterFocus?: DocAfterFocusFunc; // function to call after focusing on a document docTransform?: Transform; // when a document can't be panned and zoomed within its own container (say a group), then we need to continue to move up the render hierarchy to find something that can pan and zoom. when this happens the docTransform must accumulate all the transforms of each level of the hierarchy instant?: boolean; // whether focus should happen instantly (as opposed to smooth zoom) + preview?: boolean; // whether changes should be previewed by the componentView or written to the document effect?: Doc; // animation effect for focus noSelect?: boolean; // whether target should be selected after focusing playAudio?: boolean; // whether to play audio annotation on focus @@ -123,7 +124,6 @@ export interface DocComponentView { getAnchor?: (addAsAnnotation: boolean) => Doc; // returns an Anchor Doc that represents the current state of the doc's componentview (e.g., the current playhead location of a an audio/video box) scrollFocus?: (doc: Doc, options: DocFocusOptions) => Opt; // returns the duration of the focus brushView?: (view: { width: number; height: number; panX: number; panY: number }) => void; - setViewSpec?: (anchor: Doc, preview: boolean) => void; // sets viewing information for a componentview, typically when following a link. 'preview' tells the view to use the values without writing to the document reverseNativeScaling?: () => boolean; // DocumentView's setup screenToLocal based on the doc having a nativeWidth/Height. However, some content views (e.g., FreeFormView w/ fitContentsToBox 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. @@ -585,10 +585,7 @@ export class DocumentViewInternal extends DocComponent this._componentView?.setViewSpec?.(anchor, LinkDocPreview.LinkInfo ? true : false)); - const focusSpeed = this._componentView?.scrollFocus?.(anchor, { ...options, instant: options?.instant || LinkDocPreview.LinkInfo ? true : false }); + const focusSpeed = this._componentView?.scrollFocus?.(anchor, { ...options, preview: LinkDocPreview.LinkInfo ? true : false }); // FOCUS: navigate through the display hierarchy making sure the target is in view const endFocus = focusSpeed === undefined ? options?.afterFocus : async (moved: boolean) => options?.afterFocus?.(true) ?? ViewAdjustment.doNothing; @@ -782,7 +779,7 @@ export class DocumentViewInternal extends DocComponent { - this._pdfViewer?.brushView(view); - }; + brushView = (view: { width: number; height: number; panX: number; panY: number }) => this._pdfViewer?.brushView(view); + scrollFocus = (doc: Doc, options: DocFocusOptions) => { let didToggle = false; if (DocListCast(this.props.Document[this.fieldKey + '-sidebar']).includes(doc) && !this.SidebarShown) { - this.toggleSidebar(!options.instant); + this.toggleSidebar(options.preview); didToggle = true; } if (this._sidebarRef?.current?.makeDocUnfiltered(doc)) return 1; diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index 5bbe521a7..4c9bead9d 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -294,9 +294,9 @@ export class WebBox extends ViewBoxAnnotatableComponent void) => (this._setBrushViewer = func); brushView = (view: { width: number; height: number; panX: number; panY: number }) => this._setBrushViewer?.(view); scrollFocus = (doc: Doc, options: DocFocusOptions) => { - if (this._url && StrCast(doc.webUrl) !== this._url) this.submitURL(StrCast(doc.webUrl), options.instant); + if (this._url && StrCast(doc.webUrl) !== this._url) this.submitURL(StrCast(doc.webUrl), options.preview); if (DocListCast(this.props.Document[this.fieldKey + '-sidebar']).includes(doc) && !this.SidebarShown) { - this.toggleSidebar(options.instant); + this.toggleSidebar(options.preview); } if (this._sidebarRef?.current?.makeDocUnfiltered(doc)) return 1; if (doc !== this.rootDoc && this._outerRef.current) { diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 0ff09a0ca..788de7af9 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -307,7 +307,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent { let didToggle = false; if (DocListCast(this.Document[this.fieldKey + '-sidebar']).includes(textAnchor) && !this.SidebarShown) { - this.toggleSidebar(options.instant); + this.toggleSidebar(options.preview); didToggle = true; } const textAnchorId = textAnchor[Id]; diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx index 32fcc0fae..4abdaeeb4 100644 --- a/src/client/views/nodes/trails/PresBox.tsx +++ b/src/client/views/nodes/trails/PresBox.tsx @@ -49,6 +49,7 @@ export interface PinProps { scrollable?: boolean | undefined; pannable?: boolean | undefined; viewType?: boolean | undefined; + filters?: boolean | undefined; temporal?: boolean | undefined; clippable?: boolean | undefined; dataview?: boolean | undefined; @@ -317,7 +318,18 @@ export class PresBox extends ViewBoxBaseComponent() { this.onHideDocument(); //Handles hide after/before } }); - static pinDataTypes(target?: Doc): { scrollable?: boolean; pannable?: boolean; viewType?: boolean; temporal?: boolean; clippable?: boolean; dataview?: boolean; textview?: boolean; poslayoutview?: boolean; dataannos?: boolean } { + static pinDataTypes(target?: Doc): { + scrollable?: boolean; + pannable?: boolean; + viewType?: boolean; + filters?: boolean; + temporal?: boolean; + clippable?: boolean; + dataview?: boolean; + textview?: boolean; + poslayoutview?: boolean; + dataannos?: boolean; + } { const targetType = target?.type as any; const scrollable = [DocumentType.PDF, DocumentType.RTF, DocumentType.WEB].includes(targetType) || target?._viewType === CollectionViewType.Stacking; const pannable = [DocumentType.IMG, DocumentType.PDF].includes(targetType) || (targetType === DocumentType.COL && target?._viewType === CollectionViewType.Freeform); @@ -327,8 +339,9 @@ export class PresBox extends ViewBoxBaseComponent() { const poslayoutview = [DocumentType.COL].includes(targetType) && target?.activeFrame === undefined; const textview = [DocumentType.RTF].includes(targetType) && target?.activeFrame === undefined; const viewType = targetType === DocumentType.COL; + const filters = true; const dataannos = false; - return { scrollable, pannable, viewType, temporal, clippable, dataview, textview, poslayoutview, dataannos }; + return { scrollable, pannable, viewType, filters, temporal, clippable, dataview, textview, poslayoutview, dataannos }; } @action @@ -375,6 +388,13 @@ export class PresBox extends ViewBoxBaseComponent() { } } + if (pinDataTypes.filters && activeItem.presPinDocFilters !== undefined) { + if (bestTarget.docFilters !== activeItem.presPinDocFilters) { + bestTarget.docFilters = ObjectField.MakeCopy(activeItem.presPinDocFilters as ObjectField) || new List([]); + changed = true; + } + } + if (pinDataTypes.scrollable) { if (bestTarget._scrollTop !== activeItem.presPinViewScroll) { bestTarget._scrollTop = activeItem.presPinViewScroll; @@ -483,6 +503,7 @@ export class PresBox extends ViewBoxBaseComponent() { if (pinProps.pinData.clippable) pinDoc.presPinClipWidth = targetDoc._clipWidth; if (pinProps.pinData.poslayoutview) pinDoc.presPinLayoutData = new List(DocListCast(targetDoc.presData).map(d => JSON.stringify({ id: d[Id], x: NumCast(d.x), y: NumCast(d.y), w: NumCast(d._width), h: NumCast(d._height) }))); if (pinProps.pinData.viewType) pinDoc.presPinViewType = targetDoc._viewType; + if (pinProps.pinData.filters) pinDoc.presPinDocFilters = ObjectField.MakeCopy(targetDoc.docFilters as ObjectField); if (pinProps.pinData.pannable) { pinDoc.presPinViewX = NumCast(targetDoc._panX); pinDoc.presPinViewY = NumCast(targetDoc._panY); diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index 9610a71ac..2db44788f 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -182,7 +182,7 @@ export class PDFViewer extends React.Component { const scrollTo = doc.unrendered ? scrollTop : Utils.scrollIntoView(scrollTop, doc[HeightSym](), NumCast(this.props.layoutDoc._scrollTop), windowHeight, 0.1 * windowHeight, this._scrollHeight); if (scrollTo !== undefined && scrollTo !== this.props.layoutDoc._scrollTop) { if (!this._pdfViewer) this._initialScroll = { loc: scrollTo, easeFunc: options.easeFunc }; - else if (!options.instant) this._scrollStopper = smoothScroll((focusSpeed = options.zoomTime ?? 500), mainCont, scrollTo, options.easeFunc, this._scrollStopper); + else if (!options.instant && !options.preview) this._scrollStopper = smoothScroll((focusSpeed = options.zoomTime ?? 500), mainCont, scrollTo, options.easeFunc, this._scrollStopper); else this._mainCont.current?.scrollTo({ top: Math.abs(scrollTo || 0) }); } } else { -- cgit v1.2.3-70-g09d2 From 9c63f3833f15cc995c2255b83923384686127f3e Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 1 Mar 2023 11:57:05 -0500 Subject: changed inPlace link following to be lightbox. allowed collections to be labeled as lightboxes. lightbox collections display link targets in an overlay that hides the rest of their content --- src/client/documents/Documents.ts | 1 + src/client/util/DocumentManager.ts | 28 ++++++---- src/client/util/LinkFollower.ts | 10 ++-- src/client/views/DocumentDecorations.tsx | 13 ++--- src/client/views/MainView.tsx | 1 - src/client/views/PropertiesButtons.tsx | 62 +++++++++++----------- src/client/views/PropertiesView.tsx | 1 - src/client/views/collections/CollectionView.tsx | 2 +- src/client/views/collections/TabDocView.tsx | 22 ++++---- .../collectionFreeForm/CollectionFreeFormView.tsx | 4 +- src/client/views/nodes/DocumentView.tsx | 17 +++--- src/client/views/nodes/MapBox/MapBox.tsx | 1 - src/fields/documentSchemas.ts | 4 +- 13 files changed, 88 insertions(+), 78 deletions(-) (limited to 'src/client/views/DocumentDecorations.tsx') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index d2ab67849..70c57e8fa 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -160,6 +160,7 @@ export class DocumentOptions { _lockedTransform?: boolean; // lock the panx,pany and scale parameters of the document so that it be panned/zoomed _followLinkToggle?: boolean; // whether document, when clicked, toggles display of its link target _showTitle?: string; // field name to display in header (:hover is an optional suffix) + _isLightbox?: boolean; // whether a collection acts as a lightbox by opening lightbox links by hiding all other documents in collection besides link target _showCaption?: string; // which field to display in the caption area. leave empty to have no caption _scrollTop?: number; // scroll location for pdfs _noAutoscroll?: boolean; // whether collections autoscroll when this item is dragged diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index d9273c2c9..0d10bed43 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -10,7 +10,7 @@ import { CollectionDockingView } from '../views/collections/CollectionDockingVie import { CollectionFreeFormView } from '../views/collections/collectionFreeForm'; import { CollectionView } from '../views/collections/CollectionView'; import { LightboxView } from '../views/LightboxView'; -import { DocFocusOptions, DocumentView, OpenWhereMod, ViewAdjustment } from '../views/nodes/DocumentView'; +import { DocFocusOptions, DocumentView, OpenWhere, OpenWhereMod, ViewAdjustment } from '../views/nodes/DocumentView'; import { LinkAnchorBox } from '../views/nodes/LinkAnchorBox'; import { ScriptingGlobals } from './ScriptingGlobals'; import { SelectionManager } from './SelectionManager'; @@ -307,16 +307,22 @@ export class DocumentManager { } //} if (options.playAudio) DocumentManager.playAudioAnno(focusView.rootDoc); - const doFocus = (forceDidFocus: boolean) => - focusView.focus(originalTarget, { - ...options, - originalTarget, - afterFocus: (didFocus: boolean) => - new Promise(res => { - focusAndFinish(forceDidFocus || didFocus); - res(ViewAdjustment.doNothing); - }), - }); + const doFocus = (forceDidFocus: boolean) => { + if (options.openInLightbox || (!options.originatingDoc?.followLinkLocation && DocCast(focusView.rootDoc.context)?._isLightbox)) { + focusView.props.addDocTab(targetDoc, OpenWhere.lightbox); + focusAndFinish(true); + } else { + focusView.focus(originalTarget, { + ...options, + originalTarget, + afterFocus: (didFocus: boolean) => + new Promise(res => { + focusAndFinish(forceDidFocus || didFocus); + res(ViewAdjustment.doNothing); + }), + }); + } + }; if (focusView.props.Document.layoutKey === 'layout_icon' && focusView.rootDoc.type !== DocumentType.SCRIPTING) { focusView.iconify(() => doFocus(true)); } else { diff --git a/src/client/util/LinkFollower.ts b/src/client/util/LinkFollower.ts index 50bc89ed2..e86e68c21 100644 --- a/src/client/util/LinkFollower.ts +++ b/src/client/util/LinkFollower.ts @@ -3,6 +3,7 @@ import { Doc, DocListCast, Opt } from '../../fields/Doc'; import { List } from '../../fields/List'; import { BoolCast, Cast, DocCast, NumCast, StrCast } from '../../fields/Types'; import { DocumentType } from '../documents/DocumentTypes'; +import { CollectionFreeFormView } from '../views/collections/collectionFreeForm'; import { DocumentDecorations } from '../views/DocumentDecorations'; import { LightboxView } from '../views/LightboxView'; import { DocFocusOptions, DocumentViewSharedProps, OpenWhere, ViewAdjustment } from '../views/nodes/DocumentView'; @@ -36,7 +37,9 @@ export class LinkFollower { const createTabForTarget = (didFocus: boolean) => new Promise(res => { const where = LightboxView.LightboxDoc ? OpenWhere.lightbox : (StrCast(sourceDoc.followLinkLocation, followLoc) as OpenWhere); - docViewProps.addDocTab(doc, where); + const lightbox = where === OpenWhere.lightbox && DocumentManager.GetContextPath(doc).find(container => container.isLightbox && DocumentManager.Instance.getDocumentView(container)); + const addDocTab = lightbox ? DocumentManager.Instance.getDocumentView(lightbox)?.ComponentView?.addDocTab : undefined; + (addDocTab ?? docViewProps.addDocTab)(doc, where); setTimeout(() => { const targDocView = DocumentManager.Instance.getFirstDocumentView(doc); // get first document view available within the lightbox if that's open, or anywhere otherwise. if (targDocView) { @@ -51,7 +54,7 @@ export class LinkFollower { }); } else { finished?.(); - res(where !== OpenWhere.inPlace || BoolCast(sourceDoc.followLinkZoom) ? ViewAdjustment.resetView : ViewAdjustment.doNothing); // for 'inPlace' resetting the initial focus&zoom would negate the zoom into the target + res(BoolCast(sourceDoc.followLinkZoom) ? ViewAdjustment.resetView : ViewAdjustment.doNothing); } }, 100); }); @@ -109,6 +112,7 @@ export class LinkFollower { zoomTime: NumCast(LinkManager.getOppositeAnchor(linkDoc, target)?.followLinkTransitionTime, 500), zoomScale: Cast(sourceDoc.followLinkZoomScale, 'number', null), easeFunc: StrCast(sourceDoc.followLinkEase, 'ease') as any, + openInLightbox: sourceDoc.followLinkLocation === OpenWhere.lightbox, effect: sourceDoc, originatingDoc: sourceDoc, zoomTextSelections: BoolCast(sourceDoc.followLinkZoomText), @@ -123,7 +127,7 @@ export class LinkFollower { } else { const containerDocContext = DocumentManager.GetContextPath(target); const targetContexts = !sourceDoc.followLinkToOuterContext && containerDocContext.length ? [containerDocContext.lastElement()] : containerDocContext; - DocumentManager.Instance.jumpToDocument(target, options, (doc, finished) => createViewFunc(doc, StrCast(linkDoc.followLinkLocation, OpenWhere.inPlace), finished), targetContexts, allFinished); + DocumentManager.Instance.jumpToDocument(target, options, (doc, finished) => createViewFunc(doc, StrCast(linkDoc.followLinkLocation, OpenWhere.lightbox), finished), targetContexts, allFinished); } }; let movedTarget = false; diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 4e51f10a8..eeef01d17 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -27,7 +27,7 @@ import { Colors } from './global/globalEnums'; import { InkingStroke } from './InkingStroke'; import { InkStrokeProperties } from './InkStrokeProperties'; import { LightboxView } from './LightboxView'; -import { DocumentView, OpenWhereMod } from './nodes/DocumentView'; +import { DocumentView, OpenWhere, OpenWhereMod } from './nodes/DocumentView'; import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox'; import { ImageBox } from './nodes/ImageBox'; import React = require('react'); @@ -283,11 +283,12 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P openDoc = DocListCast(openDoc.aliases).find(alias => !alias.context) ?? Doc.MakeAlias(openDoc); Doc.deiconifyView(openDoc); } - LightboxView.SetLightboxDoc( - openDoc, - undefined, - selectedDocs.slice(1).map(view => view.props.Document) - ); + selectedDocs[0].props.addDocTab(openDoc, OpenWhere.lightbox); + // LightboxView.SetLightboxDoc( + // openDoc, + // undefined, + // selectedDocs.slice(1).map(view => view.props.Document) + // ); } } SelectionManager.DeselectAll(); diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 1e9220e1e..95c0f3755 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -692,7 +692,6 @@ export class MainView extends React.Component { if (doc.dockingConfig) return DashboardView.openDashboard(doc); // prettier-ignore switch (whereFields[0]) { - case OpenWhere.inPlace: // fall through to lightbox case OpenWhere.lightbox: return LightboxView.AddDocTab(doc, location); case OpenWhere.dashboard: return DashboardView.openDashboard(doc); case OpenWhere.fullScreen: return CollectionDockingView.OpenFullScreen(doc); diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx index 7e33ee495..a5c01490f 100644 --- a/src/client/views/PropertiesButtons.tsx +++ b/src/client/views/PropertiesButtons.tsx @@ -7,7 +7,7 @@ import { Id } from '../../fields/FieldSymbols'; import { InkField } from '../../fields/InkField'; import { RichTextField } from '../../fields/RichTextField'; import { ScriptField } from '../../fields/ScriptField'; -import { BoolCast, StrCast } from '../../fields/Types'; +import { BoolCast, ScriptCast, StrCast } from '../../fields/Types'; import { ImageField } from '../../fields/URLField'; import { DocUtils } from '../documents/Documents'; import { CollectionViewType, DocumentType } from '../documents/DocumentTypes'; @@ -20,6 +20,7 @@ import { VideoBox } from './nodes/VideoBox'; import { pasteImageBitmap } from './nodes/WebBoxRenderer'; import './PropertiesButtons.scss'; import React = require('react'); +import { LinkManager } from '../util/LinkManager'; const higflyout = require('@hig/flyout'); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; @@ -118,14 +119,14 @@ export class PropertiesButtons extends React.Component<{}, {}> { on => 'object-group' ); } - // this implments a container pattern by marking the targetDoc (collection) as an inPlace container, - // and then making the contained collection be a "menu" such that when any of its contents are clicked, - // they will open their targets in the outer container. To get back to the "menu", you click on the main container. - @computed get inPlaceContainerButton() { + // this implments a container pattern by marking the targetDoc (collection) as a lightbox + // that always fits its contents to its container and that hides all other documents when + // a link is followed that targets a 'lightbox' destination + @computed get isLightboxButton() { return this.propertyToggleBtn( - 'In Place', - 'isInPlaceContainer', - on => `${on ? 'Make' : 'Remove'} in place container flag`, + 'Lightbox', + 'isLightbox', + on => `${on ? 'Set' : 'Remove'} lightbox flag`, on => 'window-restore', onClick => { SelectionManager.Views().forEach(dv => { @@ -134,16 +135,12 @@ export class PropertiesButtons extends React.Component<{}, {}> { // containerDoc.noShadow = // containerDoc.noHighlighting = // containerDoc._forceActive = - containerDoc._fitContentsToBox = containerDoc._isInPlaceContainer = !containerDoc._isInPlaceContainer; - containerDoc._xPadding = containerDoc._yPadding = containerDoc._isInPlaceContainer ? 10 : undefined; + containerDoc._fitContentsToBox = containerDoc._isLightbox = !containerDoc._isLightbox; + containerDoc._xPadding = containerDoc._yPadding = containerDoc._isLightbox ? 10 : undefined; const containerContents = DocListCast(dv.dataDoc[dv.props.fieldKey ?? Doc.LayoutFieldKey(containerDoc)]); dv.rootDoc.onClick = ScriptField.MakeScript('{self.data = undefined; documentView.select(false)}', { documentView: 'any' }); containerContents.forEach(doc => { - DocListCast(doc.links).forEach(link => { - doc.isLinkButton = true; - //doc.followLinkLocation = OpenWhere.inPlace; - link.linkDisplay = false; - }); + DocListCast(doc.links).forEach(link => (link.linkDisplay = false)); }); }); } @@ -290,7 +287,6 @@ export class PropertiesButtons extends React.Component<{}, {}> { @undoBatch @action handleOptionChange = (onClick: string) => { - this.selectedDoc && (this.selectedDoc.onClickBehavior = onClick); SelectionManager.Views() .filter(dv => dv.docView) .map(dv => dv.docView!) @@ -305,7 +301,7 @@ export class PropertiesButtons extends React.Component<{}, {}> { break; case 'linkInPlace': docView.toggleFollowLink(false, false); - docView.props.Document.followLinkLocation = docView.props.Document._isLinkButton ? OpenWhere.inPlace : undefined; + docView.props.Document.followLinkLocation = docView.props.Document._isLinkButton ? OpenWhere.lightbox : undefined; break; case 'linkOnRight': docView.toggleFollowLink(false, false); @@ -327,24 +323,26 @@ export class PropertiesButtons extends React.Component<{}, {}> { ['nothing', 'Select Document'], ['enterPortal', 'Enter Portal'], ['toggleDetail', 'Toggle Detail'], - ['linkInPlace', 'Open in Place'], + ['linkInPlace', 'Open Link in Lightbox'], ['linkOnRight', 'Open Link on Right'], ]; - const currentSelection = this.selectedDoc.onClickBehavior; - // Get items to place into the list - const list = buttonList.map(value => { - const click = () => { - this.handleOptionChange(value[0]); - }; + const click = () => this.handleOptionChange(value[0]); + const linkButton = BoolCast(this.selectedDoc._isLinkButton); + const followLoc = this.selectedDoc._followLinkLocation; + const linkedToLightboxView = () => DocListCast(this.selectedDoc.links).some(link => LinkManager.getOppositeAnchor(link, this.selectedDoc)?._isLightbox); + + let active = false; + // prettier-ignore + switch (value[0]) { + case 'linkInPlace': active = linkButton && followLoc === OpenWhere.lightbox && !linkedToLightboxView(); break; + case 'linkOnRight': active = linkButton && followLoc === OpenWhere.addRight; break; + case 'enterPortal': active = linkButton && this.selectedDoc._followLinkLocation === OpenWhere.lightbox && linkedToLightboxView(); break; + case 'toggleDetail':active = ScriptCast(this.selectedDoc.onClick)?.script.originalScript.includes('toggleDetail'); break; + case 'nothing': active = !linkButton && this.selectedDoc.onClick === undefined;break; + } return ( -
+
{value[1]}
); @@ -413,7 +411,7 @@ export class PropertiesButtons extends React.Component<{}, {}> { {toggle(this.freezeThumb)} {toggle(this.forceActiveButton, { display: !isFreeForm && !isMap ? 'none' : '' })} {toggle(this.fitContentButton, { display: !isFreeForm && !isMap ? 'none' : '' })} - {toggle(this.inPlaceContainerButton, { display: !isFreeForm && !isMap ? 'none' : '' })} + {toggle(this.isLightboxButton, { display: !isFreeForm && !isMap ? 'none' : '' })} {toggle(this.autoHeightButton, { display: !isText && !isStacking && !isTree ? 'none' : '' })} {toggle(this.maskButton, { display: !isInk ? 'none' : '' })} {toggle(this.hideImageButton, { display: !isImage ? 'none' : '' })} diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index e9d1433c3..0fe165783 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -1626,7 +1626,6 @@ export class PropertiesView extends React.Component { - {LinkManager.currentLink?.linksToAnnotation ? : null}
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 90406ed3c..316f1e4e9 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -191,7 +191,7 @@ export class CollectionView extends ViewBoxAnnotatableComponent this.props.addDocTab(this.rootDoc.childClickedOpenTemplateView as Doc, OpenWhere.addRight), icon: 'project-diagram' }); } - !Doc.noviceMode && optionItems.push({ description: `${this.rootDoc.isInPlaceContainer ? 'Unset' : 'Set'} inPlace Container`, event: () => (this.rootDoc.isInPlaceContainer = !this.rootDoc.isInPlaceContainer), icon: 'project-diagram' }); + !Doc.noviceMode && optionItems.push({ description: `${this.rootDoc._isLightbox ? 'Unset' : 'Set'} is Lightbox`, event: () => (this.rootDoc._isLightbox = !this.rootDoc._isLightbox), icon: 'project-diagram' }); if (!Doc.noviceMode && false) { optionItems.push({ diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx index 01872df84..042c2b71b 100644 --- a/src/client/views/collections/TabDocView.tsx +++ b/src/client/views/collections/TabDocView.tsx @@ -350,7 +350,7 @@ export class TabDocView extends React.Component { // replace[:{left,right,top,bottom,}] - e.g., "replace" will replace the current stack contents, // "replace:right" - will replace the stack on the right named "right" if it exists, or create a stack on the right with that name, // "replace:monkeys" - will replace any tab that has the label 'monkeys', or a tab with that label will be created by default on the right - // inPlace - will add the document to any collection along the path from the document to the docking view that has a field isInPlaceContainer. if none is found, inPlace adds a tab to current stack + // lightbox - will add the document to any collection along the path from the document to the docking view that has a field isLightbox. if none is found, it adds to the full screen lightbox addDocTab = (doc: Doc, location: OpenWhere) => { SelectionManager.DeselectAll(); const whereFields = doc._viewType === CollectionViewType.Docking ? [OpenWhere.dashboard] : location.split(':'); @@ -359,17 +359,15 @@ export class TabDocView extends React.Component { // prettier-ignore switch (whereFields[0]) { case undefined: - case OpenWhere.inPlace: { - if (this.layoutDoc?.isInPlaceContainer) { - const inPlaceView = !doc.annotationOn && DocCast(doc.context) ? DocumentManager.Instance.getFirstDocumentView(DocCast(doc.context)) : undefined; - const data = inPlaceView?.dataDoc[Doc.LayoutFieldKey(inPlaceView.rootDoc)]; - if (inPlaceView && (!data || data instanceof List)) { - inPlaceView.layoutDoc[Doc.LayoutFieldKey(inPlaceView.rootDoc)] = new List([doc]); - return true; - } - } - } - case OpenWhere.lightbox: return LightboxView.AddDocTab(doc, location); + case OpenWhere.lightbox: if (this.layoutDoc?._isLightbox) { + const lightboxView = !doc.annotationOn && DocCast(doc.context) ? DocumentManager.Instance.getFirstDocumentView(DocCast(doc.context)) : undefined; + const data = lightboxView?.dataDoc[Doc.LayoutFieldKey(lightboxView.rootDoc)]; + if (lightboxView && (!data || data instanceof List)) { + lightboxView.layoutDoc[Doc.LayoutFieldKey(lightboxView.rootDoc)] = new List([doc]); + return true; + } + } + return LightboxView.AddDocTab(doc, location); case OpenWhere.dashboard: return DashboardView.openDashboard(doc); case OpenWhere.fullScreen: return CollectionDockingView.OpenFullScreen(doc); case OpenWhere.close: return CollectionDockingView.CloseSplit(doc, whereMods); diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 78804b070..be8a72369 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -1414,8 +1414,8 @@ export class CollectionFreeFormView extends CollectionSubView(doc instanceof Doc ? [doc] : doc); return true; } diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index beb0f8e3a..8257c9c49 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -72,7 +72,6 @@ export enum ViewAdjustment { } export enum OpenWhere { - inPlace = 'inPlace', lightbox = 'lightbox', add = 'add', addLeft = 'add:left', @@ -109,6 +108,7 @@ export interface DocFocusOptions { effect?: Doc; // animation effect for focus noSelect?: boolean; // whether target should be selected after focusing playAudio?: boolean; // whether to play audio annotation on focus + openInLightbox?: boolean; // whether to open target in lightbox or just focus on it zoomTextSelections?: boolean; // whether to display a zoomed overlay of anchor text selections toggleTarget?: boolean; // whether to toggle target on and off originatingDoc?: Doc; // document that triggered the focus @@ -123,6 +123,7 @@ export interface DocComponentView { scrollPreview?: (docView: DocumentView, doc: Doc, options: DocFocusOptions) => Opt; // returns the duration of the focus scrollFocus?: (docView: DocumentView, doc: Doc, options: DocFocusOptions) => Opt; // returns the duration of the focus brushView?: (view: { width: number; height: number; panX: number; panY: number }) => void; + addDocTab?: (doc: Doc, where: OpenWhere) => boolean; // determines how to add a document - used in following links to open the target ina local lightbox reverseNativeScaling?: () => boolean; // DocumentView's setup screenToLocal based on the doc having a nativeWidth/Height. However, some content views (e.g., FreeFormView w/ fitContentsToBox 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. @@ -640,7 +641,8 @@ export class DocumentViewInternal extends DocComponent (func().result?.select === true ? this.props.select(false) : ''), 'on double click'); } else if (!Doc.IsSystem(this.rootDoc) && (![DocumentType.INK].includes(this.rootDoc.type as any) || Doc.UserDoc().openInkInLightbox) && !this.rootDoc.isLinkButton) { - UndoManager.RunInBatch(() => LightboxView.AddDocTab(this.rootDoc, OpenWhere.lightbox, this.props.LayoutTemplate?.()), 'double tap'); + //UndoManager.RunInBatch(() => LightboxView.AddDocTab(this.rootDoc, OpenWhere.lightbox, this.props.LayoutTemplate?.()), 'double tap'); + UndoManager.RunInBatch(() => this.props.addDocTab(this.rootDoc, OpenWhere.lightbox), 'double tap'); SelectionManager.DeselectAll(); Doc.UnBrushDoc(this.props.Document); } @@ -870,13 +872,16 @@ export class DocumentViewInternal extends DocComponent { + makeIntoPortal = () => { const portalLink = this.allLinks.find(d => d.anchor1 === this.props.Document); if (!portalLink) { - const portal = Docs.Create.FreeformDocument([], { _width: NumCast(this.layoutDoc._width) + 10, _height: NumCast(this.layoutDoc._height), _fitWidth: true, title: StrCast(this.props.Document.title) + ' [Portal]' }); - DocUtils.MakeLink({ doc: this.props.Document }, { doc: portal }, 'portal to:portal from'); + DocUtils.MakeLink( + { doc: this.props.Document }, + { doc: Docs.Create.FreeformDocument([], { _width: NumCast(this.layoutDoc._width) + 10, _height: NumCast(this.layoutDoc._height), _isLightbox: true, _fitWidth: true, title: StrCast(this.props.Document.title) + ' [Portal]' }) }, + 'portal to:portal from' + ); } - this.Document.followLinkLocation = OpenWhere.inPlace; + this.Document.followLinkLocation = OpenWhere.lightbox; this.Document.followLinkZoom = true; this.Document._isLinkButton = true; }; diff --git a/src/client/views/nodes/MapBox/MapBox.tsx b/src/client/views/nodes/MapBox/MapBox.tsx index 039f11cd1..c182dfd19 100644 --- a/src/client/views/nodes/MapBox/MapBox.tsx +++ b/src/client/views/nodes/MapBox/MapBox.tsx @@ -331,7 +331,6 @@ export class MapBox extends ViewBoxAnnotatableComponent { if (doc.lat !== undefined && doc.lng !== undefined) { const existingMarker = this.allMapMarkers.find(marker => marker.lat === doc.lat && marker.lng === doc.lng); - doc.onClickBehavior = 'enterPortal'; if (existingMarker) { Doc.AddDocToList(existingMarker, 'data', doc); } else { diff --git a/src/fields/documentSchemas.ts b/src/fields/documentSchemas.ts index 10324449f..5b489a96c 100644 --- a/src/fields/documentSchemas.ts +++ b/src/fields/documentSchemas.ts @@ -84,11 +84,11 @@ export const documentSchema = createSchema({ onPointerDown: ScriptField, // script to run when document is clicked (can be overriden by an onClick prop) onPointerUp: ScriptField, // script to run when document is clicked (can be overriden by an onClick prop) onDragStart: ScriptField, // script to run when document is dragged (without being selected). the script should return the Doc to be dropped. - followLinkLocation: 'string', // flag for where to place content when following a click interaction (e.g., add:right, inPlace, default, ) + followLinkLocation: 'string', // flag for where to place content when following a click interaction (e.g., add:right, lightbox, default, ) hideLinkButton: 'boolean', // whether the blue link counter button should be hidden hideAllLinks: 'boolean', // whether all individual blue anchor dots should be hidden linkDisplay: 'boolean', // whether a link connection should be shown between link anchor endpoints. - isInPlaceContainer: 'boolean', // whether the marked object will display addDocTab() calls that target "inPlace" destinations + isLightbox: 'boolean', // whether the marked object will display addDocTab() calls that target "lightbox" destinations isLinkButton: 'boolean', // whether document functions as a link follow button to follow the first link on the document when clicked layers: listSpec('string'), // which layers the document is part of _lockedPosition: 'boolean', // whether the document can be moved (dragged) -- cgit v1.2.3-70-g09d2 From 9c29092fc9df29c02cc83885e4ba5645b71867d4 Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 1 Mar 2023 15:45:03 -0500 Subject: fix to notetakingiview resizing when deleting a column to force an unset column --- src/client/views/DocumentDecorations.tsx | 2 +- src/client/views/collections/CollectionNoteTakingView.tsx | 12 ++++++------ .../views/collections/CollectionNoteTakingViewColumn.tsx | 7 +++---- 3 files changed, 10 insertions(+), 11 deletions(-) (limited to 'src/client/views/DocumentDecorations.tsx') diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index eeef01d17..2982f8a99 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -797,7 +797,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P const resizerScheme = colorScheme ? 'documentDecorations-resizer' + colorScheme : ''; // Radius constants - const useRounding = seldocview.ComponentView instanceof ImageBox || seldocview.ComponentView instanceof FormattedTextBox; + const useRounding = seldocview.ComponentView instanceof ImageBox || seldocview.ComponentView instanceof FormattedTextBox || seldocview.ComponentView instanceof CollectionFreeFormView; const borderRadius = numberValue(StrCast(seldocview.rootDoc.borderRounding)); const docMax = Math.min(NumCast(seldocview.rootDoc.width) / 2, NumCast(seldocview.rootDoc.height) / 2); const maxDist = Math.min((this.Bounds.r - this.Bounds.x) / 2, (this.Bounds.b - this.Bounds.y) / 2); diff --git a/src/client/views/collections/CollectionNoteTakingView.tsx b/src/client/views/collections/CollectionNoteTakingView.tsx index edd5ba96c..0e1601f35 100644 --- a/src/client/views/collections/CollectionNoteTakingView.tsx +++ b/src/client/views/collections/CollectionNoteTakingView.tsx @@ -55,11 +55,11 @@ export class CollectionNoteTakingView extends CollectionSubView() { const needsUnsetCategory = this.childDocs.some(d => !d[this.notetakingCategoryField] && !columnHeaders?.find(sh => sh.heading === 'unset')); if (needsUnsetCategory || columnHeaders === undefined || columnHeaders.length === 0) { setTimeout(() => { - const columnHeaders = Cast(this.dataDoc.columnHeaders, listSpec(SchemaHeaderField), null); + const columnHeaders = Array.from(Cast(this.dataDoc.columnHeaders, listSpec(SchemaHeaderField), null)); const needsUnsetCategory = this.childDocs.some(d => !d[this.notetakingCategoryField] && !columnHeaders?.find(sh => sh.heading === 'unset')); - if (needsUnsetCategory || columnHeaders === undefined || columnHeaders.length === 0) { - if (columnHeaders) columnHeaders.push(new SchemaHeaderField('unset', undefined, undefined, 1)); - else this.dataDoc.columnHeaders = new List(); + if (needsUnsetCategory || columnHeaders.length === 0) { + columnHeaders.push(new SchemaHeaderField('unset', undefined, undefined, 1)); + this.resizeColumns(columnHeaders); } }); } @@ -321,7 +321,7 @@ export class CollectionNoteTakingView extends CollectionSubView() { // Removing example: column widths are [0.5, 0.30, 0.20] --> user deletes the final column --> column widths are [0.625, 0.375]. // Adding example: column widths are [0.6, 0.4] --> user adds column at end --> column widths are [0.4, 0.267, 0.33] @action - resizeColumns = (isAdd: boolean, headers: SchemaHeaderField[], colIndex: number) => { + resizeColumns = (headers: SchemaHeaderField[]) => { const n = headers.length; const curWidths = headers.reduce((sum, hdr) => sum + Math.abs(hdr.width), 0); const scaleFactor = 1 / curWidths; @@ -563,7 +563,7 @@ export class CollectionNoteTakingView extends CollectionSubView() { const columnHeaders = Array.from(Cast(this.props.Document.columnHeaders, listSpec(SchemaHeaderField), null)); const newColWidth = 1 / (this.numGroupColumns + 1); columnHeaders.push(new SchemaHeaderField(value, undefined, undefined, newColWidth)); - value && this.resizeColumns(true, columnHeaders, this.columnHeaders.length - 1); + value && this.resizeColumns(columnHeaders); return true; }; diff --git a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx index ec6a2bec8..829d055e5 100644 --- a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx +++ b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx @@ -44,7 +44,7 @@ interface CSVFieldColumnProps { observeHeight: (myref: any) => void; unobserveHeight: (myref: any) => void; editableViewProps: () => any; - resizeColumns: (isAdd: boolean, headers: SchemaHeaderField[], colIndex: number) => boolean; + resizeColumns: (headers: SchemaHeaderField[]) => boolean; maxColWidth: number; dividerWidth: number; availableWidth: number; @@ -142,10 +142,9 @@ export class CollectionNoteTakingViewColumn extends React.Component { const columnHeaders = Array.from(Cast(this.props.Document.columnHeaders, listSpec(SchemaHeaderField), null)); if (this.props.headingObject) { - const index = columnHeaders.indexOf(this.props.headingObject); this.props.docList.forEach(d => (d[this.props.pivotField] = undefined)); - columnHeaders.splice(index, 1); - this.props.resizeColumns(false, columnHeaders, index); + columnHeaders.splice(columnHeaders.indexOf(this.props.headingObject), 1); + this.props.resizeColumns(columnHeaders); } }; -- cgit v1.2.3-70-g09d2