aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2024-05-10 16:34:37 -0400
committerbobzel <zzzman@gmail.com>2024-05-10 16:34:37 -0400
commitdc20525c09943fef332f8e7dac54aab3039e8df7 (patch)
treeeda5a2fe066e1be498c7789756088a30f8d0c0e6 /src
parent4b4d77f99bd55e6de0593c3acd1cf5798ae038bf (diff)
fixed exception when text templates have no inherited data, and when text views are modified after the editor has been destroyed. random code cleanup
Diffstat (limited to 'src')
-rw-r--r--src/client/views/StyleProvider.tsx6
-rw-r--r--src/client/views/collections/TreeView.tsx2
-rw-r--r--src/client/views/nodes/DocumentView.tsx64
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.tsx7
4 files changed, 36 insertions, 43 deletions
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index 0b8201903..3842f930a 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -80,8 +80,8 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<FieldViewProps &
const isNonTransparentLevel = isNonTransparent ? Number(property.replace(/.*:nonTransparent([0-9]+).*/, '$1')) : 0; // property.includes(':nonTransparent');
const isAnnotated = property.includes(':annotated');
const layoutDoc = doc ? Doc.Layout(doc) : doc;
- const isOpen = property.includes(':open');
- const boxBackground = property.includes(':box');
+ const isOpen = property.includes(':treeOpen');
+ const boxBackground = property.includes(':docView'); // background color of docView's bounds can be different than the background of contents -- eg FontIconBox
const {
DocumentView: docView,
fieldKey: fieldKeyProp,
@@ -115,7 +115,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<FieldViewProps &
// prettier-ignore
switch (property.split(':')[0]) {
case StyleProp.TreeViewIcon: {
- const img = ImageCast(doc?.icon, ImageCast(doc?.data));
+ const img = ImageCast(doc?.icon ?? doc?.[doc ? Doc.LayoutFieldKey(doc) : ""]);
if (img) {
const ext = extname(img.url.href);
const url = doc?.icon ? img.url.href : img.url.href.replace(ext, '_s' + ext);
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index bc12d1c28..b82421e6b 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -779,7 +779,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
@computed get renderBullet() {
TraceMobx();
- const iconType = this.treeView._props.styleProvider?.(this.Document, this.treeView._props, StyleProp.TreeViewIcon + (this.treeViewOpen ? ':open' : !this.childDocs.length ? ':empty' : '')) || 'question';
+ const iconType = this.treeView._props.styleProvider?.(this.Document, this.treeView._props, StyleProp.TreeViewIcon + (this.treeViewOpen ? ':treeOpen' : !this.childDocs.length ? ':empty' : '')) || 'question';
const color = SettingsManager.userColor;
const checked = this.onCheckedClick ? this.Document.treeView_Checked ?? 'unchecked' : undefined;
return (
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 14feca0b5..804d014a1 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -123,31 +123,23 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
animateScaleTime = () => this._animateScaleTime ?? 100;
style = (doc: Doc, sprop: StyleProp | string) => this._props.styleProvider?.(doc, this._props, sprop);
- @computed get showTitle() { return this.style(this.layoutDoc, StyleProp.ShowTitle) as Opt<string>; } // prettier-ignore
- @computed get opacity() { return this.style(this.layoutDoc, StyleProp.Opacity); } // prettier-ignore
- @computed get boxShadow() { return this.style(this.layoutDoc, StyleProp.BoxShadow); } // prettier-ignore
- @computed get borderRounding() { return this.style(this.layoutDoc, StyleProp.BorderRounding); } // prettier-ignore
- @computed get widgetDecorations() { return this.style(this.layoutDoc, StyleProp.Decorations); } // prettier-ignore
- @computed get backgroundBoxColor() { return this.style(this.layoutDoc, StyleProp.BackgroundColor + ':box'); } // prettier-ignore
- @computed get headerMargin() { return this.style(this.layoutDoc, StyleProp.HeaderMargin) ?? 0; } // prettier-ignore
- @computed get showCaption() { return this.style(this.layoutDoc, StyleProp.ShowCaption) ?? 0; } // prettier-ignore
- @computed get titleHeight() { return this.style(this.layoutDoc, StyleProp.TitleHeight) ?? 0; } // prettier-ignore
- @computed get docContents() { return this.style(this.Document, StyleProp.DocContents); } // prettier-ignore
- @computed get highlighting() { return this.style(this.Document, StyleProp.Highlighting); } // prettier-ignore
- @computed get borderPath() { return this.style(this.Document, StyleProp.BorderPath); } // prettier-ignore
-
- @computed get onClickHandler() {
- return this._props.onClickScript?.() ?? ScriptCast(this.Document.onClick, ScriptCast(this.layoutDoc.onClick));
- }
- @computed get onDoubleClickHandler() {
- return this._props.onDoubleClickScript?.() ?? ScriptCast(this.layoutDoc.onDoubleClick, ScriptCast(this.Document.onDoubleClick));
- }
- @computed get onPointerDownHandler() {
- return this._props.onPointerDownScript?.() ?? ScriptCast(this.layoutDoc.onPointerDown, ScriptCast(this.Document.onPointerDown));
- }
- @computed get onPointerUpHandler() {
- return this._props.onPointerUpScript?.() ?? ScriptCast(this.layoutDoc.onPointerUp, ScriptCast(this.Document.onPointerUp));
- }
+ @computed get opacity() { return this.style(this.layoutDoc, StyleProp.Opacity); } // prettier-ignore
+ @computed get boxShadow() { return this.style(this.layoutDoc, StyleProp.BoxShadow); } // prettier-ignore
+ @computed get borderRounding() { return this.style(this.layoutDoc, StyleProp.BorderRounding); } // prettier-ignore
+ @computed get widgetDecorations() { return this.style(this.layoutDoc, StyleProp.Decorations); } // prettier-ignore
+ @computed get backgroundBoxColor(){ return this.style(this.layoutDoc, StyleProp.BackgroundColor + ':docView'); } // prettier-ignore
+ @computed get showTitle() { return this.style(this.layoutDoc, StyleProp.ShowTitle) as Opt<string>; } // prettier-ignore
+ @computed get showCaption() { return this.style(this.layoutDoc, StyleProp.ShowCaption) ?? 0; } // prettier-ignore
+ @computed get headerMargin() { return this.style(this.layoutDoc, StyleProp.HeaderMargin) ?? 0; } // prettier-ignore
+ @computed get titleHeight() { return this.style(this.layoutDoc, StyleProp.TitleHeight) ?? 0; } // prettier-ignore
+ @computed get docContents() { return this.style(this.Document, StyleProp.DocContents); } // prettier-ignore
+ @computed get highlighting() { return this.style(this.Document, StyleProp.Highlighting); } // prettier-ignore
+ @computed get borderPath() { return this.style(this.Document, StyleProp.BorderPath); } // prettier-ignore
+
+ @computed get onClickHdlr() { return this._props.onClickScript?.() ?? ScriptCast(this.layoutDoc.onClick ?? this.Document.onClick); } // prettier-ignore
+ @computed get onDoubleClickHdlr() { return this._props.onDoubleClickScript?.() ?? ScriptCast(this.layoutDoc.onDoubleClick ?? this.Document.onDoubleClick); } // prettier-ignore
+ @computed get onPointerDownHdlr() { return this._props.onPointerDownScript?.() ?? ScriptCast(this.layoutDoc.onPointerDown ?? this.Document.onPointerDown); } // prettier-ignore
+ @computed get onPointerUpHdlr() { return this._props.onPointerUpScript?.() ?? ScriptCast(this.layoutDoc.onPointerUp ?? this.Document.onPointerUp); } // prettier-ignore
@computed get disableClickScriptFunc() {
const onScriptDisable = this._props.onClickScriptDisable ?? this._componentView?.onClickScriptDisable?.() ?? this.layoutDoc.onClickScriptDisable;
@@ -163,7 +155,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
TraceMobx();
return this._props.contentPointerEvents ??
((!this.disableClickScriptFunc && //
- this.onClickHandler &&
+ this.onClickHdlr &&
!SnappingManager.ExploreMode &&
!this.layoutDoc.layout_isSvg &&
this.isContentActive() !== true) ||
@@ -315,8 +307,8 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
};
if (this._doubleTap) {
const defaultDblclick = this._props.defaultDoubleClick?.() || this.Document.defaultDoubleClick;
- if (this.onDoubleClickHandler?.script) {
- UndoManager.RunInBatch(() => this.onDoubleClickHandler.script.run(scriptProps, console.log).result?.select && this._props.select(false), 'on double click: ' + this.Document.title);
+ if (this.onDoubleClickHdlr?.script) {
+ UndoManager.RunInBatch(() => this.onDoubleClickHdlr.script.run(scriptProps, console.log).result?.select && this._props.select(false), 'on double click: ' + this.Document.title);
} else if (!Doc.IsSystem(this.Document) && defaultDblclick !== 'ignore') {
UndoManager.RunInBatch(() => this._props.addDocTab(this.Document, OpenWhere.lightboxAlways), 'double tap');
DocumentView.DeselectAll();
@@ -329,9 +321,9 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
this._singleClickFunc = undefined;
} else {
let clickFunc: undefined | (() => any);
- if (!this.disableClickScriptFunc && this.onClickHandler?.script) {
+ if (!this.disableClickScriptFunc && this.onClickHdlr?.script) {
clickFunc = undoable(() => {
- this.onClickHandler?.script.run(scriptProps, console.log).result?.select && this._props.select(false);
+ this.onClickHdlr?.script.run(scriptProps, console.log).result?.select && this._props.select(false);
}, 'click ' + this.Document.title);
} else {
// onDragStart implies a button doc that we don't want to select when clicking. RootDocument & isTemplateForField implies we're clicking on part of a template instance and we want to select the whole template, not the part
@@ -409,10 +401,10 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
this.cleanupPointerEvents();
this._longPressSelector && clearTimeout(this._longPressSelector);
- if (this.onPointerUpHandler?.script) {
- this.onPointerUpHandler.script.run({ this: this.Document }, console.log);
+ if (this.onPointerUpHdlr?.script) {
+ this.onPointerUpHdlr.script.run({ this: this.Document }, console.log);
} else if (e.button === 0 && ClientUtils.isClick(e.clientX, e.clientY, this._downX, this._downY, this._downTime)) {
- this._doubleTap = (this.onDoubleClickHandler?.script || this.Document.defaultDoubleClick !== 'ignore') && Date.now() - this._lastTap < ClientUtils.CLICK_TIME;
+ this._doubleTap = (this.onDoubleClickHdlr?.script || this.Document.defaultDoubleClick !== 'ignore') && Date.now() - this._lastTap < ClientUtils.CLICK_TIME;
if (!this.isContentActive()) this._lastTap = Date.now(); // don't want to process the start of a double tap if the doucment is selected
}
// eslint-disable-next-line no-use-before-define
@@ -585,7 +577,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
!Doc.noviceMode && onClicks.push({ description: 'Toggle Detail', event: this.setToggleDetail, icon: 'concierge-bell' });
if (!this.Document.annotationOn) {
- onClicks.push({ description: this.onClickHandler ? 'Remove Click Behavior' : 'Follow Link', event: () => this.toggleFollowLink(false, false), icon: 'link' });
+ onClicks.push({ description: this.onClickHdlr ? 'Remove Click Behavior' : 'Follow Link', event: () => this.toggleFollowLink(false, false), icon: 'link' });
!Doc.noviceMode && onClicks.push({ description: 'Edit onClick Script', event: () => UndoManager.RunInBatch(() => DocUtils.makeCustomViewClicked(this.Document, undefined, 'onClick'), 'edit onClick'), icon: 'terminal' });
!existingOnClick && cm.addItem({ description: 'OnClick...', noexpand: true, subitems: onClicks, icon: 'mouse-pointer' });
} else if (Doc.Links(this.Document).length) {
@@ -688,7 +680,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
rootSelected = () => this._rootSelected;
panelHeight = () => this._props.PanelHeight() - this.headerMargin;
screenToLocalContent = () => this._props.ScreenToLocalTransform().translate(0, -this.headerMargin);
- onClickFunc = this.disableClickScriptFunc ? undefined : () => this.onClickHandler;
+ onClickFunc = this.disableClickScriptFunc ? undefined : () => this.onClickHdlr;
setHeight = (height: number) => { !this._props.suppressSetHeight && (this.layoutDoc._height = Math.min(NumCast(this.layoutDoc._maxHeight, Number.MAX_SAFE_INTEGER), height)); } // prettier-ignore
setContentView = action((view: ViewBoxInterface<FieldViewProps>) => { this._componentView = view; }); // prettier-ignore
isContentActive = (): boolean | undefined => this._isContentActive;
@@ -793,7 +785,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
width: 100 - sidebarWidthPercent + '%',
color: background === 'transparent' ? SnappingManager.userColor : lightOrDark(background),
background,
- pointerEvents: (!this.disableClickScriptFunc && this.onClickHandler) || this.Document.ignoreClick ? 'none' : this.isContentActive() || this._props.isDocumentActive?.() ? 'all' : undefined,
+ pointerEvents: (!this.disableClickScriptFunc && this.onClickHdlr) || this.Document.ignoreClick ? 'none' : this.isContentActive() || this._props.isDocumentActive?.() ? 'all' : undefined,
}}>
{!dropdownWidth ? null : (
<div className="documntViewInternal-dropdown" style={{ width: dropdownWidth }}>
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index 624721d7c..e62a639c8 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -320,7 +320,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
return '';
};
dispatchTransaction = (tx: Transaction) => {
- if (this._editorView) {
+ if (this._editorView && !this._editorView.isDestroyed) {
const state = this._editorView.state.apply(tx);
this._editorView.updateState(state);
this.tryUpdateDoc(false);
@@ -353,6 +353,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
let unchanged = true;
const textChange = newText !== prevData?.Text; // the Text string can change even if the RichText doesn't because dashFieldViews may return new strings as the data they reference changes
+ const rtField = (layoutData !== prevData ? layoutData : undefined) ?? protoData;
if (this._applyingChange !== this.fieldKey && (force || textChange || removeSelection(newJson) !== removeSelection(prevData?.Data))) {
this._applyingChange = this.fieldKey;
textChange && (dataDoc[this.fieldKey + '_modificationDate'] = new DateField(new Date(Date.now())));
@@ -366,10 +367,10 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
this._applyingChange = ''; // turning this off here allows a Doc to retrieve data from template if noTemplate below is changed to false
unchanged = false;
}
- } else {
+ } else if (rtField) {
// if we've deleted all the text in a note driven by a template, then restore the template data
dataDoc[this.fieldKey] = undefined;
- this._editorView.updateState(EditorState.fromJSON(this.config, JSON.parse(((layoutData !== prevData ? layoutData : undefined) ?? protoData)?.Data)));
+ this._editorView.updateState(EditorState.fromJSON(this.config, JSON.parse(rtField.Data)));
ScriptCast(this.layoutDoc.onTextChanged, null)?.script.run({ this: this.layoutDoc, text: newText });
unchanged = false;
}