From 205fdacf9807be2691e13e1d9d04d6b98620391a Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 15 Jan 2025 13:03:59 -0500 Subject: fixed so that users are sentt to dropbox to authorized uploads once, and then a refresh token is used afterwards. fixed up some collection views to work better with the tagsView. fixed grid view to show entire image. tweaked notetaking view to work better with tags, but it's incomplete. --- src/client/views/collections/CollectionStackingView.tsx | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'src/client/views/collections/CollectionStackingView.tsx') diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 1ac0b6d70..a57256424 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -146,7 +146,17 @@ export class CollectionStackingView extends CollectionSubView @@ -344,6 +354,7 @@ export class CollectionStackingView extends CollectionSubView Date: Thu, 27 Feb 2025 10:44:09 -0500 Subject: fixed column dragging and yMargin in masonry view. made columns always fit width of masonry --- .../views/collections/CollectionStackingView.scss | 8 ++- .../views/collections/CollectionStackingView.tsx | 68 +++++++++++++--------- 2 files changed, 48 insertions(+), 28 deletions(-) (limited to 'src/client/views/collections/CollectionStackingView.tsx') diff --git a/src/client/views/collections/CollectionStackingView.scss b/src/client/views/collections/CollectionStackingView.scss index 5237bdffb..565536623 100644 --- a/src/client/views/collections/CollectionStackingView.scss +++ b/src/client/views/collections/CollectionStackingView.scss @@ -121,11 +121,15 @@ } .collectionStackingView-columnDragger { - width: 15; - height: 15; + width: 28; + height: 28; position: absolute; margin-left: -5; z-index: 10; + > svg { + width: 100%; + height: 100%; + } } // Documents in stacking view diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index a57256424..0a25882ff 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -110,7 +110,9 @@ export class CollectionStackingView extends CollectionSubView this._props.setHeight?.(this.headerMargin + (this.isStackingView ? Math.max(...this._refList.map(DivHeight)) : 2 * this.yMargin + this._refList.reduce((p, r) => p + DivHeight(r), 0))); + observer = new ResizeObserver(this.setAutoHeight); + componentDidMount() { super.componentDidMount?.(); this._props.setContentViewBox?.(this); @@ -232,10 +237,21 @@ export class CollectionStackingView extends CollectionSubView [this._props.PanelWidth() - 2 * this.xMargin, NumCast(this.Document._layout_columnWidth, 250)], + ([pw, cw]) => { + if (!this.isStackingView) { + this.layoutDoc._layout_columnCount = Math.round(pw / cw); + } + } + ); + this._disposers.autoHeight = reaction( - () => this.layoutDoc._layout_autoHeight, - layoutAutoHeight => layoutAutoHeight && this._props.setHeight?.(this.headerMargin + (this.isStackingView ? Math.max(...this._refList.map(DivHeight)) : this._refList.reduce((p, r) => p + DivHeight(r), 0))) + () => [this.layoutDoc._layout_autoHeight, this.yMargin], + ([autoH]) => autoH && this.setAutoHeight() ); + this._disposers.refList = reaction( () => ({ refList: this._refList.slice(), autoHeight: this.layoutDoc._layout_autoHeight && !DocumentView.LightboxContains(this.DocumentView?.()) }), ({ refList, autoHeight }) => { @@ -435,8 +451,8 @@ export class CollectionStackingView extends CollectionSubView { - this.layoutDoc._columnWidth = Math.max(10, this.columnWidth + delta[0]); + onDividerMove = (e: PointerEvent) => { + this.Document._layout_columnWidth = Math.max(10, this.ScreenToLocalBoxXf().transformPoint(e.clientX, 0)[0] - this.xMargin); return false; }; @@ -446,7 +462,7 @@ export class CollectionStackingView extends CollectionSubView + style={{ cursor: this._cursor, color: SettingsManager.userColor, left: `${NumCast(this.Document._layout_columnWidth) + this.xMargin}px` }}> ); @@ -590,24 +606,26 @@ export class CollectionStackingView extends CollectionSubView (!this.isStackingView ? 1 : Math.max(1, Math.min(docList.length, Math.floor((this._props.PanelWidth() - 2 * this.xMargin) / (this.columnWidth + this.gridGap))))); return ( - +
+ +
); }; @@ -699,8 +717,6 @@ export class CollectionStackingView extends CollectionSubView this._props.setHeight?.(this.headerMargin + (this.isStackingView ? Math.max(...this._refList.map(DivHeight)) : this._refList.reduce((p, r) => p + DivHeight(r), 0)))); - onPassiveWheel = (e: WheelEvent) => e.stopPropagation(); render() { TraceMobx(); -- cgit v1.2.3-70-g09d2 From bcf3b005d55ec851374049f4c188d96ffc7a7c8b Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 27 Feb 2025 14:46:20 -0500 Subject: prevent tagsview from appeqring in spreadsheet. set default fill color only if nothing is selected. place column divider at top of stacking/card views. move card view flashcard view to top left independent of margin settings. --- .../views/collections/CollectionCardDeckView.tsx | 5 +- .../collections/CollectionMasonryViewFieldRow.tsx | 1 - .../views/collections/CollectionStackingView.scss | 194 ++++++++++----------- .../views/collections/CollectionStackingView.tsx | 45 ++--- src/client/views/global/globalScripts.ts | 2 +- src/client/views/nodes/DocumentView.tsx | 2 +- 6 files changed, 125 insertions(+), 124 deletions(-) (limited to 'src/client/views/collections/CollectionStackingView.tsx') diff --git a/src/client/views/collections/CollectionCardDeckView.tsx b/src/client/views/collections/CollectionCardDeckView.tsx index 94f85d429..756b37f99 100644 --- a/src/client/views/collections/CollectionCardDeckView.tsx +++ b/src/client/views/collections/CollectionCardDeckView.tsx @@ -540,11 +540,10 @@ export class CollectionCardView extends CollectionSubView() { height: `${100 / this.nativeScaling / fitContentScale}%`, width: `${100 / this.nativeScaling / fitContentScale}%`, transform: `scale(${this.nativeScaling * fitContentScale})`, - }}> - {this.flashCardUI(this.curDoc, this.docViewProps, this.answered)} - + }}> + {this.flashCardUI(this.curDoc, this.docViewProps, this.answered)}
- {this._props.showHandle && this._props.parent._props.isContentActive() ? this._props.parent.columnDragger : null} {showChrome ? (
svg { + width: 100%; + height: 100%; + } } -} -.collectionStackingView, -.collectionMasonryView { - height: 100%; - width: 100%; - position: absolute; - top: 0; - overflow-y: auto; - overflow-x: hidden; - flex-wrap: wrap; - transition: top 0.5s; - - > div { + // TODO:glr Turn this into a seperate class + .documentButtonMenu { position: relative; - display: block; - } - - .collectionStackingViewFieldColumn { + height: fit-content; + border-bottom: global.$standard-border; display: flex; + justify-content: center; flex-direction: column; + align-items: center; + align-content: center; + padding: 5px 0 5px 0; + + .documentExplanation { + width: 90%; + margin: 5px; + font-size: 11px; + color: global.$medium-blue; + padding: 10px; + border-radius: 5px; + border: solid 0.5px global.$medium-blue; + } } - .collectionSchemaView-previewDoc { + .collectionStackingView, + .collectionMasonryView { height: 100%; + width: 100%; position: absolute; - } + top: 0; + overflow-y: auto; + overflow-x: hidden; + flex-wrap: wrap; + transition: top 0.5s; - .collectionStackingView-docView-container { - width: 45%; - margin: 5% 2.5%; - padding-left: 2.5%; - height: auto; - } + > div { + position: relative; + display: block; + } - .collectionStackingView-flexCont { - display: flex; - flex-direction: row; - flex-wrap: wrap; - align-items: center; - } + .collectionStackingViewFieldColumn { + display: flex; + flex-direction: column; + } - .collectionStackingView-masonrySingle, - .collectionStackingView-masonryGrid { - width: 100%; - display: grid; - top: 0; - left: 0; - } + .collectionSchemaView-previewDoc { + height: 100%; + position: absolute; + } - .collectionStackingView-masonrySingle { - height: 100%; - position: absolute; - } + .collectionStackingView-docView-container { + width: 45%; + margin: 5% 2.5%; + padding-left: 2.5%; + height: auto; + } - .collectionStackingView-masonryGrid { - margin: auto; - height: max-content; - position: relative; - grid-auto-rows: 0px; - } + .collectionStackingView-flexCont { + display: flex; + flex-direction: row; + flex-wrap: wrap; + align-items: center; + } - .collectionStackingView-masonrySingle { - width: 100%; - height: 100%; - position: absolute; - display: flex; - flex-direction: column; - top: 0; - left: 0; - width: 100%; - position: absolute; - } + .collectionStackingView-masonrySingle, + .collectionStackingView-masonryGrid { + width: 100%; + display: grid; + top: 0; + left: 0; + } - .collectionStackingView-description { - font-size: 100%; - margin-bottom: 1vw; - padding: 10px; - height: 2vw; - width: 100%; - font-family: global.$sans-serif; - background: global.$dark-gray; - color: global.$white; - } + .collectionStackingView-masonrySingle { + height: 100%; + position: absolute; + } - .collectionStackingView-columnDragger { - width: 28; - height: 28; - position: absolute; - margin-left: -5; - z-index: 10; - > svg { + .collectionStackingView-masonryGrid { + margin: auto; + height: max-content; + position: relative; + grid-auto-rows: 0px; + } + + .collectionStackingView-masonrySingle { width: 100%; height: 100%; + position: absolute; + display: flex; + flex-direction: column; + top: 0; + left: 0; + width: 100%; + position: absolute; + } + + .collectionStackingView-description { + font-size: 100%; + margin-bottom: 1vw; + padding: 10px; + height: 2vw; + width: 100%; + font-family: global.$sans-serif; + background: global.$dark-gray; + color: global.$white; } } diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 0a25882ff..e8fa8b01e 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -452,7 +452,7 @@ export class CollectionStackingView extends CollectionSubView { - this.Document._layout_columnWidth = Math.max(10, this.ScreenToLocalBoxXf().transformPoint(e.clientX, 0)[0] - this.xMargin); + this.Document._layout_columnWidth = Math.max(10, (this._props.DocumentView?.().screenToViewTransform().transformPoint(e.clientX, 0)[0] ?? 0) - this.xMargin); return false; }; @@ -606,26 +606,29 @@ export class CollectionStackingView extends CollectionSubView (!this.isStackingView ? 1 : Math.max(1, Math.min(docList.length, Math.floor((this._props.PanelWidth() - 2 * this.xMargin) / (this.columnWidth + this.gridGap))))); return ( -
- -
+ <> + {this._props.isContentActive() && !this.isStackingView ? this.columnDragger : null} +
+ +
+ ); }; diff --git a/src/client/views/global/globalScripts.ts b/src/client/views/global/globalScripts.ts index b455f76e4..835c28daa 100644 --- a/src/client/views/global/globalScripts.ts +++ b/src/client/views/global/globalScripts.ts @@ -127,7 +127,7 @@ ScriptingGlobals.add(function setBackgroundColor(color?: string, checkResult?: b const contentFrameNumber = Cast(selView.Document?._currentFrame, 'number', layoutFrameNumber ?? null); // frame number that content is at which determines what content is displayed return CollectionFreeFormDocumentView.getStringValues(selView?.Document, contentFrameNumber)[fieldKey] || defaultFill(); } - setDefaultFill(color ?? 'transparent'); + !selectedViews.length && setDefaultFill(color ?? 'transparent'); selectedViews.forEach(dv => { const fieldKey = dv.Document._layout_isSvg ? 'fillColor' : 'backgroundColor'; const layoutFrameNumber = Cast(dv.containerViewPath?.().lastElement()?.Document?._currentFrame, 'number'); // frame number that container is at which determines layout frame values diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index b40ead03a..5f5dd1210 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -780,7 +780,7 @@ export class DocumentViewInternal extends DocComponent - {this._props.DocumentView?.() ? : null} + {this._props.DocumentView?.() && !this._props.docViewPath().slice(-2)[0].ComponentView?.isUnstyledView?.() ? : null}
) : ( <> -- cgit v1.2.3-70-g09d2 From 2838b8d98ab88df974fd52ba96cf5046d99298cb Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 27 Feb 2025 16:05:35 -0500 Subject: fixed passive wheel prevention on document.root. fixed key waring on masonry view. --- src/client/views/Main.tsx | 2 +- src/client/views/collections/CollectionStackingView.tsx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/client/views/collections/CollectionStackingView.tsx') diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx index 3c1da88cc..f02677d95 100644 --- a/src/client/views/Main.tsx +++ b/src/client/views/Main.tsx @@ -87,7 +87,7 @@ FieldLoader.ServerLoadStatus = { requested: 0, retrieved: 0, message: 'cache' }; await CurrentUserUtils.loadUserDocument(info); setTimeout(() => { // prevent zooming browser - document.getElementById('root')!.addEventListener('wheel', event => event.ctrlKey && event.preventDefault(), { capture: true, passive: true }); + document.getElementById('root')!.addEventListener('wheel', event => event.ctrlKey && event.preventDefault(), true); const startload = (document as unknown as { startLoad: number }).startLoad; // see index.html in deploy/ const loading = Date.now() - (startload ? Number(startload) : Date.now() - 3000); const d = new Date(); diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index e8fa8b01e..f06e0b551 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -606,7 +606,7 @@ export class CollectionStackingView extends CollectionSubView (!this.isStackingView ? 1 : Math.max(1, Math.min(docList.length, Math.floor((this._props.PanelWidth() - 2 * this.xMargin) / (this.columnWidth + this.gridGap))))); return ( - <> +
{this._props.isContentActive() && !this.isStackingView ? this.columnDragger : null}
- +
); }; -- cgit v1.2.3-70-g09d2 From 93d4c71fe523a4b1f473ee6ab5e8a9b8ca715625 Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 4 Mar 2025 11:07:40 -0500 Subject: fixed column width default / columnDragger for masonry view. --- src/client/views/collections/CollectionStackingView.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/client/views/collections/CollectionStackingView.tsx') diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index f06e0b551..96125f2c2 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -111,7 +111,7 @@ export class CollectionStackingView extends CollectionSubView [this._props.PanelWidth() - 2 * this.xMargin, NumCast(this.Document._layout_columnWidth, 250)], ([pw, cw]) => { - if (!this.isStackingView) { + if (!this.isStackingView && Math.round(pw / cw)) { this.layoutDoc._layout_columnCount = Math.round(pw / cw); } } @@ -607,7 +607,7 @@ export class CollectionStackingView extends CollectionSubView (!this.isStackingView ? 1 : Math.max(1, Math.min(docList.length, Math.floor((this._props.PanelWidth() - 2 * this.xMargin) / (this.columnWidth + this.gridGap))))); return (
- {this._props.isContentActive() && !this.isStackingView ? this.columnDragger : null} + {this._props.isContentActive() && !this.isStackingView && !this.chromeHidden ? this.columnDragger : null}
Date: Thu, 6 Mar 2025 19:46:43 -0500 Subject: a bunch of changes to improve how docs are selected automatically when created. --- src/client/documents/DocUtils.ts | 5 +- src/client/views/GlobalKeyHandler.ts | 19 +++-- src/client/views/MarqueeAnnotator.tsx | 2 +- src/client/views/SidebarAnnos.tsx | 9 +-- .../collections/CollectionMasonryViewFieldRow.tsx | 7 +- .../views/collections/CollectionNoteTakingView.tsx | 2 +- .../collections/CollectionNoteTakingViewColumn.tsx | 21 ++---- .../views/collections/CollectionStackingView.tsx | 2 +- .../CollectionStackingViewFieldColumn.tsx | 26 ++----- .../views/collections/CollectionTreeView.tsx | 2 +- src/client/views/collections/TreeView.tsx | 2 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 5 +- .../collections/collectionFreeForm/MarqueeView.tsx | 2 +- .../collectionGrid/CollectionGridView.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 6 ++ src/client/views/nodes/EquationBox.tsx | 10 +-- src/client/views/nodes/LabelBox.tsx | 5 +- src/client/views/nodes/MapBox/MapBox.tsx | 2 +- src/client/views/nodes/MapBox/MapBoxInfoWindow.tsx | 2 +- .../views/nodes/MapboxMapBox/MapboxContainer.tsx | 2 +- .../views/nodes/formattedText/DailyJournal.tsx | 25 +++---- .../views/nodes/formattedText/FormattedTextBox.tsx | 41 +++------- src/fields/Doc.ts | 4 - src/fields/RichTextField.ts | 87 +++++++++++++++++----- 24 files changed, 149 insertions(+), 141 deletions(-) (limited to 'src/client/views/collections/CollectionStackingView.tsx') diff --git a/src/client/documents/DocUtils.ts b/src/client/documents/DocUtils.ts index 7e0416447..9797a407b 100644 --- a/src/client/documents/DocUtils.ts +++ b/src/client/documents/DocUtils.ts @@ -385,7 +385,7 @@ export namespace DocUtils { newDoc.x = x; newDoc.y = y; newDoc[DocData].backgroundColor = Doc.UserDoc().textBackgroundColor; - Doc.SetSelectOnLoad(newDoc); + DocumentView.SetSelectOnLoad(newDoc); if (pivotField) { newDoc[pivotField] = pivotValue; } @@ -408,6 +408,7 @@ export namespace DocUtils { description: ':Daily Journal', event: undoable(() => { const newDoc = Docs.Create.DailyJournalDocument('', { x, y }); + DocumentView.SetSelectOnLoad(newDoc); docAdder?.(newDoc); }, 'Create Daily Journal'), icon: 'book', @@ -456,7 +457,7 @@ export namespace DocUtils { newDoc.author = ClientUtils.CurrentUserEmail(); newDoc.x = x; newDoc.y = y; - Doc.SetSelectOnLoad(newDoc); + DocumentView.SetSelectOnLoad(newDoc); if (pivotField) { newDoc[pivotField] = pivotValue; } diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts index b200aff65..2d342d1b1 100644 --- a/src/client/views/GlobalKeyHandler.ts +++ b/src/client/views/GlobalKeyHandler.ts @@ -23,7 +23,6 @@ import { CollectionFreeFormDocumentView } from './nodes/CollectionFreeFormDocume import { DocumentLinksButton } from './nodes/DocumentLinksButton'; import { DocumentView } from './nodes/DocumentView'; import { OpenWhereMod } from './nodes/OpenWhere'; -import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox'; import { AnchorMenu } from './pdf/AnchorMenu'; const modifiers = ['control', 'meta', 'shift', 'alt']; @@ -75,7 +74,6 @@ export class KeyManager { public handle = action((e: KeyboardEvent) => { // accumulate buffer of characters to insert in a new text note. once the note is created, it will stop keyboard events from reaching this function. - if (FormattedTextBox.SelectOnLoadChar) FormattedTextBox.SelectOnLoadChar += e.key === 'Enter' ? '\n' : e.key; const keyname = e.key && e.key.toLowerCase(); this.handleGreedy(/* keyname */); @@ -106,6 +104,10 @@ export class KeyManager { }; private unmodified = action((keyname: string, e: KeyboardEvent) => { + const nothing = { + stopPropagation: false, + preventDefault: false, + }; switch (keyname) { case 'u': if (document.activeElement?.tagName !== 'INPUT' && document.activeElement?.tagName !== 'TEXTAREA') { @@ -169,17 +171,14 @@ export class KeyManager { return { stopPropagation: true, preventDefault: true }; } break; - case 'arrowleft': return (e.target as any).type !== 'text' && this.nudge(-1, 0, 'nudge left') // if target is an input box, then we don't want to nudge any Docs since we're justing moving within the text itself. - case 'arrowright': return (e.target as any).type !== 'text' && this.nudge( 1, 0, 'nudge right'); - case 'arrowup': return (e.target as any).type !== 'text' && this.nudge(0, -1, 'nudge up'); - case 'arrowdown': return (e.target as any).type !== 'text' && this.nudge(0, 1, 'nudge down'); + case 'arrowleft': return (e.target as HTMLInputElement)?.type !== 'text' ? this.nudge(-1, 0, 'nudge left') : nothing; // if target is an input box, then we don't want to nudge any Docs since we're justing moving within the text itself. + case 'arrowright': return (e.target as HTMLInputElement)?.type !== 'text' ? this.nudge( 1, 0, 'nudge right') : nothing; + case 'arrowup': return (e.target as HTMLInputElement)?.type !== 'text' ? this.nudge(0, -1, 'nudge up') : nothing; + case 'arrowdown': return (e.target as HTMLInputElement | null)?.type !== 'text'? this.nudge(0, 1, 'nudge down'): nothing; default: } // prettier-ignore - return { - stopPropagation: false, - preventDefault: false, - }; + return nothing; }); private shift = action((keyname: string) => { diff --git a/src/client/views/MarqueeAnnotator.tsx b/src/client/views/MarqueeAnnotator.tsx index 02516264c..3f4200dce 100644 --- a/src/client/views/MarqueeAnnotator.tsx +++ b/src/client/views/MarqueeAnnotator.tsx @@ -199,7 +199,7 @@ export class MarqueeAnnotator extends ObservableReactComponent { const target = DocUtils.GetNewTextDoc('Note linked to ' + this.props.Document.title, 0, 0, 100, 100, annotationOn, 'yellow'); - Doc.SetSelectOnLoad(target); + DocumentView.SetSelectOnLoad(target); return target; }; DragManager.StartAnchorAnnoDrag([ele], new DragManager.AnchorAnnoDragData(this.props.docView(), sourceAnchorCreator, targetCreator), e.pageX, e.pageY, { diff --git a/src/client/views/SidebarAnnos.tsx b/src/client/views/SidebarAnnos.tsx index 87076bf65..816fc8ed3 100644 --- a/src/client/views/SidebarAnnos.tsx +++ b/src/client/views/SidebarAnnos.tsx @@ -3,23 +3,23 @@ import { observer } from 'mobx-react'; import * as React from 'react'; import { ClientUtils, returnAll, returnFalse, returnOne, returnZero } from '../../ClientUtils'; import { emptyFunction } from '../../Utils'; -import { Doc, DocListCast, Field, FieldType, FieldResult, StrListCast } from '../../fields/Doc'; +import { Doc, DocListCast, Field, FieldResult, FieldType, StrListCast } from '../../fields/Doc'; import { DocData } from '../../fields/DocSymbols'; import { Id } from '../../fields/FieldSymbols'; import { List } from '../../fields/List'; import { RichTextField } from '../../fields/RichTextField'; import { DocCast, NumCast, StrCast } from '../../fields/Types'; +import { DocUtils } from '../documents/DocUtils'; import { CollectionViewType, DocumentType } from '../documents/DocumentTypes'; import { Docs } from '../documents/Documents'; -import { DocUtils } from '../documents/DocUtils'; import { SearchUtil } from '../util/SearchUtil'; import { Transform } from '../util/Transform'; import { ObservableReactComponent } from './ObservableReactComponent'; import './SidebarAnnos.scss'; import { StyleProp } from './StyleProp'; import { CollectionStackingView } from './collections/CollectionStackingView'; +import { DocumentView } from './nodes/DocumentView'; import { FieldViewProps } from './nodes/FieldView'; -import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox'; interface ExtraProps { fieldKey: string; @@ -81,8 +81,7 @@ export class SidebarAnnos extends ObservableReactComponent this.addNewTextDoc('-typed text-', false, true), 'add text note'); - // addNewTextDoc is called when a user starts typing in a column to create a new node - @action - addNewTextDoc = (value: string, shiftDown?: boolean, forceEmptyNote?: boolean) => { - if (!value && !forceEmptyNote) return false; + addTextNote = undoable(() => { const key = this._props.pivotField; - const newDoc = Docs.Create.TextDocument(value, { _height: 18, _width: 200, _layout_fitWidth: true, title: value, _layout_autoHeight: true }); + const newDoc = Docs.Create.TextDocument('', { _height: 18, _width: 200, _layout_fitWidth: true, _layout_autoHeight: true }); const colValue = this.getValue(this._props.heading); newDoc[key] = colValue; - Doc.SetSelectOnLoad(newDoc); - FormattedTextBox.SelectOnLoadChar = forceEmptyNote ? '' : ' '; + DocumentView.SetSelectOnLoad(newDoc); return this._props.addDocument?.(newDoc) || false; - }; + }, 'add text note'); // deleteColumn is called when a user deletes a column using the 'trash' icon in the button area. // If the user deletes the first column, the documents get moved to the second column. Otherwise, @@ -177,7 +172,7 @@ export class CollectionNoteTakingViewColumn extends ObservableReactComponent { const key = this._props.pivotField; doc[key] = this.getValue(this._props.heading); - Doc.SetSelectOnLoad(doc); + DocumentView.SetSelectOnLoad(doc); return this._props.addDocument?.(doc); }, this._props.addDocument, @@ -249,7 +244,7 @@ export class CollectionNoteTakingViewColumn extends ObservableReactComponent
- +
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 96125f2c2..72e6bb8f2 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -321,7 +321,7 @@ export class CollectionStackingView extends CollectionSubView { SnappingManager.IsDragging && (this._background = '#b4b4b4'); } // prettier-ignore @action pointerLeave = () => { this._background = 'inherit'}; // prettier-ignore - @undoBatch typedNote = () => this.addNewTextDoc('-typed text-', false, true); - - @action - addNewTextDoc = (value: string, shiftDown?: boolean, forceEmptyNote?: boolean) => { - if (!value && !forceEmptyNote) return false; + @undoBatch typedNote = () => { const key = this._props.pivotField; - const newDoc = Docs.Create.TextDocument(value, { _height: 18, _width: 200, _layout_fitWidth: true, title: value, _layout_autoHeight: true }); + const newDoc = Docs.Create.TextDocument('', { _height: 18, _width: 200, _layout_fitWidth: true, _layout_autoHeight: true }); key && (newDoc[key] = this.getValue(this._props.heading)); const maxHeading = this._props.docList.reduce((prevHeading, doc) => (NumCast(doc.heading) > prevHeading ? NumCast(doc.heading) : prevHeading), 0); const heading = maxHeading === 0 || this._props.docList.length === 0 ? 1 : maxHeading === 1 ? 2 : 3; newDoc.heading = heading; - Doc.SetSelectOnLoad(newDoc); - FormattedTextBox.SelectOnLoadChar = forceEmptyNote ? '' : ' '; + DocumentView.SetSelectOnLoad(newDoc); return this._props.addDocument?.(newDoc) || false; }; @@ -240,7 +235,7 @@ export class CollectionStackingViewFieldColumn extends ObservableReactComponent< const height = this._ele ? DivHeight(this._ele) : 0; DocUtils.addDocumentCreatorMenuItems( doc => { - Doc.SetSelectOnLoad(doc); + DocumentView.SetSelectOnLoad(doc); return this._props.addDocument?.(doc); }, this._props.addDocument, @@ -394,14 +389,7 @@ export class CollectionStackingViewFieldColumn extends ObservableReactComponent< onKeyDown={e => e.stopPropagation()} className="collectionStackingView-addDocumentButton" style={{ width: 'calc(100% - 25px)', maxWidth: this._props.columnWidth / this._props.numGroupColumns - 25, marginBottom: 10 }}> - } - menuCallback={this.menuCallback} - /> + } menuCallback={this.menuCallback} />
) : null}
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index a60cd98ac..e93724dd4 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -174,7 +174,7 @@ export class CollectionTreeView extends CollectionSubView 0 && prev) { - Doc.SetSelectOnLoad(prev); + DocumentView.SetSelectOnLoad(prev); DocumentView.getDocumentView(prev, this.DocumentView?.())?.select(false); } return true; diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index ab4d8b060..6208905fe 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -1300,7 +1300,7 @@ export class TreeView extends ObservableReactComponent { const fieldKey = Doc.LayoutFieldKey(newParent); if (remove && fieldKey && Cast(newParent[fieldKey], listSpec(Doc)) !== undefined) { remove(child); - Doc.SetSelectOnLoad(child); + DocumentView.SetSelectOnLoad(child); TreeView._editTitleOnLoad = editTitle ? { id: child[Id], parent } : undefined; Doc.AddDocToList(newParent, fieldKey, child, addAfter, false); newParent.treeView_Open = true; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 43addfc29..89aa53c35 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -293,7 +293,7 @@ export class CollectionFreeFormView extends CollectionSubView this.childLayoutPairs.filter(pair => this.isCurrent(pair.layout)).map(pair => pair.layout); isAnyChildContentActive = () => this._props.isAnyChildContentActive(); addLiveTextBox = (newDoc: Doc) => { - Doc.SetSelectOnLoad(newDoc); // track the new text box so we can give it a prop that tells it to focus itself when it's displayed + DocumentView.SetSelectOnLoad(newDoc); // track the new text box so we can give it a prop that tells it to focus itself when it's displayed this.addDocument(newDoc); }; selectDocuments = (docs: Doc[]) => { @@ -1496,8 +1496,7 @@ export class CollectionFreeFormView extends CollectionSubView { const text = Docs.Create.TextDocument('', { _width: 150, _height: 50 }); - Doc.SetSelectOnLoad(text); // track the new text box so we can give it a prop that tells it to focus itself when it's displayed + DocumentView.SetSelectOnLoad(text); // track the new text box so we can give it a prop that tells it to focus itself when it's displayed Doc.AddDocToList(this.Document, this._props.fieldKey, text); this.setLayoutList(this.addLayoutItem(this.savedLayoutList, this.makeLayoutItem(text, this.screenToCell(clickEv.clientX, clickEv.clientY)))); }), diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 595abc7f8..a514ee04e 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -1110,6 +1110,12 @@ export class DocumentView extends DocComponent() { public static DeselectAll: (except?: Doc) => void | undefined; public static DeselectView: (dv: DocumentView | undefined) => void | undefined; public static SelectView: (dv: DocumentView | undefined, extendSelection: boolean) => void | undefined; + + public static SelectOnLoad: Doc | undefined; + public static SetSelectOnLoad(doc?: Doc) { + DocumentView.SelectOnLoad = doc; + doc && DocumentView.addViewRenderedCb(doc, dv => dv.select(false)); + } /** * returns a list of all currently selected DocumentViews */ diff --git a/src/client/views/nodes/EquationBox.tsx b/src/client/views/nodes/EquationBox.tsx index 576b5bbe0..dcc6e27ed 100644 --- a/src/client/views/nodes/EquationBox.tsx +++ b/src/client/views/nodes/EquationBox.tsx @@ -30,12 +30,12 @@ export class EquationBox extends ViewBoxBaseComponent() { componentDidMount() { this._props.setContentViewBox?.(this); - if (Doc.SelectOnLoad === this.Document && (!DocumentView.LightboxDoc() || DocumentView.LightboxContains(this.DocumentView?.()))) { + if (DocumentView.SelectOnLoad === this.Document && (!DocumentView.LightboxDoc() || DocumentView.LightboxContains(this.DocumentView?.()))) { this._props.select(false); - this._ref.current!.mathField.focus(); - this.dataDoc.text === 'x' && this._ref.current!.mathField.select(); - Doc.SetSelectOnLoad(undefined); + this._ref.current?.mathField.focus(); + this.dataDoc.text === 'x' && this._ref.current?.mathField.select(); + DocumentView.SetSelectOnLoad(undefined); } reaction( () => this._props.isSelected(), @@ -66,7 +66,7 @@ export class EquationBox extends ViewBoxBaseComponent() { color: StrCast(this.Document.color), fontSize: this.fontSize, }); - Doc.SetSelectOnLoad(nextEq); + DocumentView.SetSelectOnLoad(nextEq); this._props.addDocument?.(nextEq); e.stopPropagation(); } diff --git a/src/client/views/nodes/LabelBox.tsx b/src/client/views/nodes/LabelBox.tsx index dcf9e1fed..7fb83571f 100644 --- a/src/client/views/nodes/LabelBox.tsx +++ b/src/client/views/nodes/LabelBox.tsx @@ -17,6 +17,7 @@ import { FieldView, FieldViewProps } from './FieldView'; import './LabelBox.scss'; import { FormattedTextBox } from './formattedText/FormattedTextBox'; import { RichTextMenu } from './formattedText/RichTextMenu'; +import { DocumentView } from './DocumentView'; @observer export class LabelBox extends ViewBoxBaseComponent() { @@ -230,8 +231,8 @@ export class LabelBox extends ViewBoxBaseComponent() { if (this._divRef) { this._divRef.addEventListener('beforeinput', this.beforeInput); - if (Doc.SelectOnLoad === this.Document) { - Doc.SelectOnLoad = undefined; + if (DocumentView.SelectOnLoad === this.Document) { + DocumentView.SetSelectOnLoad(undefined); this._divRef.focus(); } this.fitTextToBox(this._divRef); diff --git a/src/client/views/nodes/MapBox/MapBox.tsx b/src/client/views/nodes/MapBox/MapBox.tsx index 541b41bf7..792cb6b46 100644 --- a/src/client/views/nodes/MapBox/MapBox.tsx +++ b/src/client/views/nodes/MapBox/MapBox.tsx @@ -353,7 +353,7 @@ export class MapBox extends ViewBoxAnnotatableComponent() { const targetCreator = (annotationOn: Doc | undefined) => { const target = DocUtils.GetNewTextDoc('Note linked to ' + this.Document.title, 0, 0, 100, 100, annotationOn, 'yellow'); - Doc.SetSelectOnLoad(target); + DocumentView.SetSelectOnLoad(target); return target; }; const docView = this.DocumentView?.(); diff --git a/src/client/views/nodes/MapBox/MapBoxInfoWindow.tsx b/src/client/views/nodes/MapBox/MapBoxInfoWindow.tsx index eb0431b85..a27a8bda1 100644 --- a/src/client/views/nodes/MapBox/MapBoxInfoWindow.tsx +++ b/src/client/views/nodes/MapBox/MapBoxInfoWindow.tsx @@ -32,7 +32,7 @@ // addNoteClick = (e: React.PointerEvent) => { // setupMoveUpEvents(this, e, returnFalse, emptyFunction, e => { // const newDoc = Docs.Create.TextDocument('Note', { _layout_autoHeight: true }); -// Doc.SetSelectOnLoad(newDoc); // track the new text box so we can give it a prop that tells it to focus itself when it's displayed +// DocumentView.SetSelectOnLoad(newDoc); // track the new text box so we can give it a prop that tells it to focus itself when it's displayed // Doc.AddDocToList(this.props.place, 'data', newDoc); // this._stack?.scrollToBottom(); // e.stopPropagation(); diff --git a/src/client/views/nodes/MapboxMapBox/MapboxContainer.tsx b/src/client/views/nodes/MapboxMapBox/MapboxContainer.tsx index 95f89a573..0627d382e 100644 --- a/src/client/views/nodes/MapboxMapBox/MapboxContainer.tsx +++ b/src/client/views/nodes/MapboxMapBox/MapboxContainer.tsx @@ -237,7 +237,7 @@ export class MapBoxContainer extends ViewBoxAnnotatableComponent const targetCreator = (annotationOn: Doc | undefined) => { const target = DocUtils.GetNewTextDoc('Note linked to ' + this.Document.title, 0, 0, 100, 100, annotationOn, 'yellow'); - Doc.SetSelectOnLoad(target); + DocumentView.SetSelectOnLoad(target); return target; }; const docView = this.DocumentView?.(); diff --git a/src/client/views/nodes/formattedText/DailyJournal.tsx b/src/client/views/nodes/formattedText/DailyJournal.tsx index 9decbfaf0..7999357b0 100644 --- a/src/client/views/nodes/formattedText/DailyJournal.tsx +++ b/src/client/views/nodes/formattedText/DailyJournal.tsx @@ -51,22 +51,13 @@ export class DailyJournal extends ViewBoxAnnotatableComponent() @action setDailyText() { console.log('setDailyText() called...'); - const initialText = `Journal Entry - ${this.journalDate}\n\nStart writing here...`; + const placeholderText = 'Start writing here...'; + const initialText = `Journal Entry - ${this.journalDate}\n${placeholderText}`; console.log('Checking if dataDoc has text field...'); console.log('Setting new text field with:', initialText); - this.dataDoc[this.fieldKey] = new RichTextField( - JSON.stringify({ - doc: { - type: 'doc', - content: [{ type: 'paragraph', content: [{ type: 'text', text: initialText }] }], - }, - selection: { type: 'text', anchor: 1, head: 1 }, - storedMarks: [], - }), - initialText - ); + this.dataDoc[this.fieldKey] = RichTextField.textToRtf(initialText, undefined, placeholderText.length); console.log('Current text field:', this.dataDoc[this.fieldKey]); } @@ -85,10 +76,11 @@ export class DailyJournal extends ViewBoxAnnotatableComponent() } render() { - return
- - -
; + return ( +
+ +
+ ); } } @@ -99,6 +91,7 @@ Docs.Prototypes.TemplateMap.set(DocumentType.JOURNAL, { _height: 35, _xMargin: 10, _yMargin: 10, + _layout_autoHeight: true, _layout_nativeDimEditable: true, _layout_reflowVertical: true, _layout_reflowHorizontal: true, diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index c2a2caecf..83ee619d0 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -99,7 +99,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent { [key: string]: NodeViewConstructor }) { FormattedTextBox._nodeViews = nodeViews; } // prettier-ignore public static PasteOnLoad: ClipboardEvent | undefined; - public static DontSelectInitialText = false; // whether initial text should be selected or not public static SelectOnLoadChar = ''; public static LiveTextUndo: UndoManager.Batch | undefined; // undo batch when typing a new text note into a collection @@ -286,7 +285,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent { const target = DocUtils.GetNewTextDoc('Note linked to ' + this.Document.title, 0, 0, 100, 100, annotationOn); - Doc.SetSelectOnLoad(target); + DocumentView.SetSelectOnLoad(target); return target; }; @@ -1542,44 +1541,26 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent m.type !== mark.type), mark]; + let { tr } = this.EditorView.state; if (selLoadChar) { - const $from = this.EditorView.state.selection.anchor ? this.EditorView.state.doc.resolve(this.EditorView.state.selection.anchor - 1) : undefined; - const mark = schema.marks.user_mark.create({ userid: ClientUtils.CurrentUserEmail(), modified: Math.floor(Date.now() / 1000) }); - const curMarks = this.EditorView.state.storedMarks ?? $from?.marksAcross(this.EditorView.state.selection.$head) ?? []; - const storedMarks = [...curMarks.filter(m => m.type !== mark.type), mark]; const tr1 = this.EditorView.state.tr.setStoredMarks(storedMarks); - const tr2 = selLoadChar === 'Enter' ? tr1.insert(this.EditorView.state.doc.content.size - 1, schema.nodes.paragraph.create()) : tr1.insertText(selLoadChar, this.EditorView.state.doc.content.size - 1); - const tr = tr2.setStoredMarks(storedMarks); - - this.EditorView.dispatch(tr.setSelection(new TextSelection(tr.doc.resolve(tr.doc.content.size)))); - this.tryUpdateDoc(true); // calling select() above will make isContentActive() true only after a render .. which means the selectAll() above won't write to the Document and the incomingValue will overwrite the selection with the non-updated data - } else if (!FormattedTextBox.DontSelectInitialText) { - const mark = schema.marks.user_mark.create({ userid: ClientUtils.CurrentUserEmail(), modified: Math.floor(Date.now() / 1000) }); - selectAll(this.EditorView.state, (tx: Transaction) => { - this.EditorView?.dispatch(tx.addStoredMark(mark)); - }); - this.EditorView?.dispatch(this.EditorView.state.tr.setSelection(new TextSelection(this.EditorView.state.doc.resolve(1)))); - this.tryUpdateDoc(true); // calling select() above will make isContentActive() true only after a render .. which means the selectAll() above won't write to the Document and the incomingValue will overwrite the selection with the non-updated data - } else { - const $from = this.EditorView.state.selection.anchor ? this.EditorView.state.doc.resolve(this.EditorView.state.selection.anchor - 1) : undefined; - const mark = schema.marks.user_mark.create({ userid: ClientUtils.CurrentUserEmail(), modified: Math.floor(Date.now() / 1000) }); - const curMarks = this.EditorView.state.storedMarks ?? $from?.marksAcross(this.EditorView.state.selection.$head) ?? []; - const storedMarks = [...curMarks.filter(m => m.type !== mark.type), mark]; - const { tr } = this.EditorView.state; - this.EditorView.dispatch(tr.setSelection(new TextSelection(tr.doc.resolve(tr.doc.content.size))).setStoredMarks(storedMarks)); - this.tryUpdateDoc(true); // calling select() above will make isContentActive() true only after a render .. which means the selectAll() above won't write to the Document and the incomingValue will overwrite the selection with the non-updated data + tr = selLoadChar === 'Enter' ? tr1.insert(this.EditorView.state.doc.content.size - 1, schema.nodes.paragraph.create()) : tr1.insertText(selLoadChar, this.EditorView.state.doc.content.size - 1); } + this.EditorView.dispatch(tr.setSelection(new TextSelection(tr.doc.resolve(tr.doc.content.size))).setStoredMarks(storedMarks)); + this.tryUpdateDoc(true); // calling select() above will make isContentActive() true only after a render .. which means the selectAll() above won't write to the Document and the incomingValue will overwrite the selection with the non-updated data } if (selectOnLoad) { - FormattedTextBox.DontSelectInitialText = false; this.EditorView!.focus(); } if (this._props.isContentActive()) this.prepareForTyping(); diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index bdd41b0bb..805bb4526 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -468,10 +468,6 @@ export class Doc extends RefField { } } export namespace Doc { - export let SelectOnLoad: Doc | undefined; - export function SetSelectOnLoad(doc: Doc | undefined) { - SelectOnLoad = doc; - } export let DocDragDataName: string = ''; export function SetDocDragDataName(name: string) { DocDragDataName = name; diff --git a/src/fields/RichTextField.ts b/src/fields/RichTextField.ts index dc636031a..4b1403b88 100644 --- a/src/fields/RichTextField.ts +++ b/src/fields/RichTextField.ts @@ -48,26 +48,77 @@ export class RichTextField extends ObjectField { '' ); } + static Initialize = (initial?: string) => { + const content: object[] = []; + const state = { + doc: { + type: 'doc', + content, + }, + selection: { + type: 'text', + anchor: 0, + head: 0, + }, + }; + if (initial && initial.length) { + content.push({ + type: 'paragraph', + content: { + type: 'text', + text: initial, + }, + }); + state.selection.anchor = state.selection.head = initial.length + 1; + } + return JSON.stringify(state); + }; + + private static ToProsemirrorState = (plainText: string, selectBack?: number, delimeter = '\n') => { + // Remap the text, creating blocks split on newlines + const elements = plainText.split(delimeter); + + // Google Docs adds in an extra carriage return automatically, so this counteracts it + !elements[elements.length - 1].length && elements.pop(); + + // Preserve the current state, but re-write the content to be the blocks + const parsed: Record = JSON.parse(RichTextField.Initialize()); + (parsed.doc as Record).content = elements.map(text => { + const paragraph: object = { + type: 'paragraph', + content: text.length ? [{ type: 'text', marks: [], text }] : undefined, // An empty paragraph gets treated as a line break + }; + return paragraph; + }); - public static textToRtf(text: string, imgDocId?: string) { + // If the new content is shorter than the previous content and selection is unchanged, may throw an out of bounds exception, so we reset it + parsed.selection = { type: 'text', anchor: 2 + plainText.length - (selectBack ?? 0), head: 2 + plainText.length }; + + // Export the ProseMirror-compatible state object we've just built + return JSON.stringify(parsed); + }; + + public static textToRtf(text: string, imgDocId?: string, selectBack?: number) { return new RichTextField( - JSON.stringify({ - // this is a RichText json that has the question text placed above a related image - doc: { - type: 'doc', - content: [ - { - type: 'paragraph', - attrs: { align: 'center', color: null, id: null, indent: null, inset: null, lineSpacing: null, paddingBottom: null, paddingTop: null }, - content: [ - ...(text ? [{ type: 'text', text }] : []), // - ...(imgDocId ? [{ type: 'dashDoc', attrs: { width: '200px', height: '200px', title: 'dashDoc', float: 'unset', hidden: false, docId: imgDocId } }] : []), - ], - }, - ], - }, - selection: { type: 'text', anchor: 2, head: 2 }, - }), + !imgDocId + ? this.ToProsemirrorState(text, selectBack) + : JSON.stringify({ + // this is a RichText json that has the question text placed above a related image + doc: { + type: 'doc', + content: [ + { + type: 'paragraph', + attrs: { align: 'center', color: null, id: null, indent: null, inset: null, lineSpacing: null, paddingBottom: null, paddingTop: null }, + content: [ + ...(text ? [{ type: 'text', text }] : []), // + ...(imgDocId ? [{ type: 'dashDoc', attrs: { width: '200px', height: '200px', title: 'dashDoc', float: 'unset', hidden: false, docId: imgDocId } }] : []), + ], + }, + ], + }, + selection: { type: 'text', anchor: 2 + text.length, head: 2 + text.length }, + }), text ); } -- cgit v1.2.3-70-g09d2 From d5eb3271f705b62deb20d6044a9f9e1562ab9ae4 Mon Sep 17 00:00:00 2001 From: bobzel Date: Fri, 7 Mar 2025 11:06:31 -0500 Subject: changed masonryView so that if column count is set w/o a columnWidth, then it stays fixed --- src/client/views/collections/CollectionStackingView.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/client/views/collections/CollectionStackingView.tsx') diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 72e6bb8f2..6bbd43b1b 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -239,9 +239,9 @@ export class CollectionStackingView extends CollectionSubView [this._props.PanelWidth() - 2 * this.xMargin, NumCast(this.Document._layout_columnWidth, 250)], + () => [this._props.PanelWidth() - 2 * this.xMargin, NumCast(this.Document._layout_columnWidth)], ([pw, cw]) => { - if (!this.isStackingView && Math.round(pw / cw)) { + if (cw && !this.isStackingView && Math.round(pw / cw)) { this.layoutDoc._layout_columnCount = Math.round(pw / cw); } } -- cgit v1.2.3-70-g09d2