aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/formattedText/FormattedTextBox.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/nodes/formattedText/FormattedTextBox.tsx')
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.tsx86
1 files changed, 51 insertions, 35 deletions
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index 314696251..096f9a92c 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -18,7 +18,7 @@ import { PrefetchProxy } from '../../../../fields/Proxy';
import { RichTextField } from '../../../../fields/RichTextField';
import { RichTextUtils } from '../../../../fields/RichTextUtils';
import { ComputedField } from '../../../../fields/ScriptField';
-import { BoolCast, Cast, FieldValue, NumCast, ScriptCast, StrCast } from '../../../../fields/Types';
+import { BoolCast, Cast, DocCast, FieldValue, NumCast, ScriptCast, StrCast } from '../../../../fields/Types';
import { GetEffectiveAcl, TraceMobx } from '../../../../fields/util';
import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, emptyFunction, numberRange, OmitKeys, returnFalse, returnZero, setupMoveUpEvents, smoothScroll, unimplementedFunction, Utils } from '../../../../Utils';
import { GoogleApiClientUtils, Pulls, Pushes } from '../../../apis/google_docs/GoogleApiClientUtils';
@@ -124,7 +124,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
return this._showSidebar ? '20%' : StrCast(this.layoutDoc._sidebarWidthPercent, '0%');
}
@computed get sidebarColor() {
- return StrCast(this.layoutDoc.sidebarColor, StrCast(this.layoutDoc[this.props.fieldKey + '-backgroundColor'], '#e4e4e4'));
+ return StrCast(this.layoutDoc.sidebarColor, StrCast(this.layoutDoc[this.fieldKey + '-backgroundColor'], '#e4e4e4'));
}
@computed get autoHeight() {
return (this.props.forceAutoHeight || this.layoutDoc._autoHeight) && !this.props.ignoreAutoHeight;
@@ -281,12 +281,13 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
const state = this._editorView.state.apply(tx);
this._editorView.updateState(state);
+ const dataDoc = Doc.IsDelegateField(DocCast(this.layoutDoc.proto), this.fieldKey) ? DocCast(this.layoutDoc.proto) : this.dataDoc;
const curText = state.doc.textBetween(0, state.doc.content.size, ' \n');
- const curTemp = this.layoutDoc.resolvedDataDoc ? Cast(this.layoutDoc[this.props.fieldKey], RichTextField) : undefined; // the actual text in the text box
- const curProto = Cast(Cast(this.dataDoc.proto, Doc, null)?.[this.fieldKey], RichTextField, null); // the default text inherited from a prototype
+ const curTemp = this.layoutDoc.resolvedDataDoc ? Cast(this.layoutDoc[this.fieldKey], RichTextField) : undefined; // the actual text in the text box
+ const curProto = Cast(Cast(dataDoc.proto, Doc, null)?.[this.fieldKey], RichTextField, null); // the default text inherited from a prototype
const curLayout = this.rootDoc !== this.layoutDoc ? Cast(this.layoutDoc[this.fieldKey], RichTextField, null) : undefined; // the default text stored in a layout template
const json = JSON.stringify(state.toJSON());
- const effectiveAcl = GetEffectiveAcl(this.dataDoc);
+ const effectiveAcl = GetEffectiveAcl(dataDoc);
const removeSelection = (json: string | undefined) => (json?.indexOf('"storedMarks"') === -1 ? json?.replace(/"selection":.*/, '') : json?.replace(/"selection":"\"storedMarks\""/, '"storedMarks"'));
@@ -297,29 +298,34 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
accumTags.push(node.attrs.fieldKey);
}
});
- const curTags = Object.keys(this.dataDoc).filter(key => key.startsWith('#'));
+ const curTags = Object.keys(dataDoc).filter(key => key.startsWith('#'));
const added = accumTags.filter(tag => !curTags.includes(tag));
const removed = curTags.filter(tag => !accumTags.includes(tag));
- removed.forEach(r => (this.dataDoc[r] = undefined));
- added.forEach(a => (this.dataDoc[a] = a));
+ removed.forEach(r => (dataDoc[r] = undefined));
+ added.forEach(a => (dataDoc[a] = a));
let unchanged = true;
if (this._applyingChange !== this.fieldKey && removeSelection(json) !== removeSelection(curProto?.Data)) {
this._applyingChange = this.fieldKey;
- curText !== Cast(this.dataDoc[this.fieldKey], RichTextField)?.Text && (this.dataDoc[this.props.fieldKey + '-lastModified'] = new DateField(new Date(Date.now())));
+ curText !== Cast(dataDoc[this.fieldKey], RichTextField)?.Text && (dataDoc[this.fieldKey + '-lastModified'] = new DateField(new Date(Date.now())));
if ((!curTemp && !curProto) || curText || json.includes('dash')) {
// if no template, or there's text that didn't come from the layout template, write it to the document. (if this is driven by a template, then this overwrites the template text which is intended)
if (removeSelection(json) !== removeSelection(curLayout?.Data)) {
- this.dataDoc[this.props.fieldKey] = new RichTextField(json, curText);
- this.dataDoc[this.props.fieldKey + '-noTemplate'] = true; //(curTemp?.Text || "") !== curText; // mark the data field as being split from the template if it has been edited
+ const numstring = NumCast(dataDoc[this.fieldKey], null);
+ if (numstring !== undefined) {
+ dataDoc[this.fieldKey] = Number(curText);
+ } else {
+ dataDoc[this.fieldKey] = new RichTextField(json, curText);
+ }
+ dataDoc[this.fieldKey + '-noTemplate'] = true; //(curTemp?.Text || "") !== curText; // mark the data field as being split from the template if it has been edited
ScriptCast(this.layoutDoc.onTextChanged, null)?.script.run({ this: this.layoutDoc, self: this.rootDoc, text: curText });
unchanged = false;
}
} else {
// if we've deleted all the text in a note driven by a template, then restore the template data
- this.dataDoc[this.props.fieldKey] = undefined;
+ dataDoc[this.fieldKey] = undefined;
this._editorView.updateState(EditorState.fromJSON(this.config, JSON.parse((curProto || curTemp).Data)));
- this.dataDoc[this.props.fieldKey + '-noTemplate'] = undefined; // mark the data field as not being split from any template it might have
+ dataDoc[this.fieldKey + '-noTemplate'] = undefined; // mark the data field as not being split from any template it might have
ScriptCast(this.layoutDoc.onTextChanged, null)?.script.run({ this: this.layoutDoc, self: this.rootDoc, text: curText });
unchanged = false;
}
@@ -330,7 +336,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
}
}
} else {
- const jsonstring = Cast(this.dataDoc[this.fieldKey], RichTextField)?.Data!;
+ const jsonstring = Cast(dataDoc[this.fieldKey], RichTextField)?.Data!;
if (jsonstring) {
const json = JSON.parse(jsonstring);
json.selection = state.toJSON().selection;
@@ -508,7 +514,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
this._dropDisposer?.();
this.ProseRef = ele;
if (ele) {
- this.setupEditor(this.config, this.props.fieldKey);
+ this.setupEditor(this.config, this.fieldKey);
this._dropDisposer = DragManager.MakeDropTarget(ele, this.drop.bind(this), this.layoutDoc);
}
// if (this.autoHeight) this.tryUpdateScrollHeight();
@@ -524,7 +530,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
// replace text contents whend dragging with Alt
if (draggedDoc && draggedDoc.type === DocumentType.RTF && !Doc.AreProtosEqual(draggedDoc, this.props.Document) && de.altKey) {
if (draggedDoc.data instanceof RichTextField) {
- Doc.GetProto(this.dataDoc)[this.props.fieldKey] = new RichTextField(draggedDoc.data.Data, draggedDoc.data.Text);
+ Doc.GetProto(this.dataDoc)[this.fieldKey] = new RichTextField(draggedDoc.data.Data, draggedDoc.data.Text);
e.stopPropagation();
}
// embed document when dragg marked as embed
@@ -538,6 +544,9 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
docid: target[Id],
float: 'unset',
});
+ if (!['alias', 'copy'].includes((dragData.dropAction ?? '') as any)) {
+ dragData.removeDocument?.(dragData.draggedDocuments[0]);
+ }
const view = this._editorView!;
view.dispatch(view.state.tr.insert(view.posAtCoords({ left: de.x, top: de.y })!.pos, node));
e.stopPropagation();
@@ -603,20 +612,20 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
addStyleSheetRule(FormattedTextBox._userStyleSheet, 'UM-' + Doc.CurrentUserEmail.replace('.', '').replace('@', ''), { background: 'moccasin' });
}
if (highlights.indexOf('Todo Items') !== -1) {
- addStyleSheetRule(FormattedTextBox._userStyleSheet, 'UT-' + 'todo', { outline: 'black solid 1px' });
+ addStyleSheetRule(FormattedTextBox._userStyleSheet, 'UT-todo', { outline: 'black solid 1px' });
}
if (highlights.indexOf('Important Items') !== -1) {
- addStyleSheetRule(FormattedTextBox._userStyleSheet, 'UT-' + 'important', { 'font-size': 'larger' });
+ addStyleSheetRule(FormattedTextBox._userStyleSheet, 'UT-important', { 'font-size': 'larger' });
}
if (highlights.indexOf('Bold Text') !== -1) {
addStyleSheetRule(FormattedTextBox._userStyleSheet, '.formattedTextBox-inner-selected .ProseMirror strong > span', { 'font-size': 'large' }, '');
addStyleSheetRule(FormattedTextBox._userStyleSheet, '.formattedTextBox-inner-selected .ProseMirror :not(strong > span)', { 'font-size': '0px' }, '');
}
if (highlights.indexOf('Disagree Items') !== -1) {
- addStyleSheetRule(FormattedTextBox._userStyleSheet, 'UT-' + 'disagree', { 'text-decoration': 'line-through' });
+ addStyleSheetRule(FormattedTextBox._userStyleSheet, 'UT-disagree', { 'text-decoration': 'line-through' });
}
if (highlights.indexOf('Ignore Items') !== -1) {
- addStyleSheetRule(FormattedTextBox._userStyleSheet, 'UT-' + 'ignore', { 'font-size': '1' });
+ addStyleSheetRule(FormattedTextBox._userStyleSheet, 'UT-ignore', { 'font-size': '1' });
}
if (highlights.indexOf('By Recent Minute') !== -1) {
addStyleSheetRule(FormattedTextBox._userStyleSheet, 'UM-' + Doc.CurrentUserEmail.replace('.', '').replace('@', ''), { opacity: '0.1' });
@@ -675,8 +684,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
@undoBatch
deleteAnnotation = (anchor: Doc) => {
LinkManager.Instance.deleteLink(DocListCast(anchor.links)[0]);
- // const docAnnotations = DocListCast(this.props.dataDoc[this.props.fieldKey]);
- // this.props.dataDoc[this.props.fieldKey] = new List<Doc>(docAnnotations.filter(a => a !== this.annoTextRegion));
+ // const docAnnotations = DocListCast(this.props.dataDoc[this.fieldKey]);
+ // this.props.dataDoc[this.fieldKey] = new List<Doc>(docAnnotations.filter(a => a !== this.annoTextRegion));
// AnchorMenu.Instance.fadeOut(true);
this.props.select(false);
};
@@ -787,6 +796,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
const appearanceItems = appearance && 'subitems' in appearance ? appearance.subitems : [];
appearanceItems.push({ description: 'Change Perspective...', noexpand: true, subitems: changeItems, icon: 'external-link-alt' });
// this.rootDoc.isTemplateDoc && appearanceItems.push({ description: "Make Default Layout", event: async () => Doc.UserDoc().defaultTextLayout = new PrefetchProxy(this.rootDoc), icon: "eye" });
+
!Doc.noviceMode &&
appearanceItems.push({
description: 'Make Default Layout',
@@ -994,11 +1004,13 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
() => this.autoHeight,
autoHeight => autoHeight && this.tryUpdateScrollHeight()
);
+ this._disposers.width = reaction(
+ () => this.props.PanelWidth(),
+ width => this.tryUpdateScrollHeight()
+ );
this._disposers.scrollHeight = reaction(
() => ({ scrollHeight: this.scrollHeight, autoHeight: this.autoHeight, width: NumCast(this.layoutDoc._width) }),
- ({ width, scrollHeight, autoHeight }) => {
- width && autoHeight && this.resetNativeHeight(scrollHeight);
- },
+ ({ width, scrollHeight, autoHeight }) => width && autoHeight && this.resetNativeHeight(scrollHeight),
{ fireImmediately: true }
);
this._disposers.componentHeights = reaction(
@@ -1006,7 +1018,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
() => ({ sidebarHeight: this.sidebarHeight, textHeight: this.textHeight, autoHeight: this.autoHeight, marginsHeight: this.autoHeightMargins }),
({ sidebarHeight, textHeight, autoHeight, marginsHeight }) => {
const newHeight = this.contentScaling * (marginsHeight + Math.max(sidebarHeight, textHeight));
- if (autoHeight && newHeight && newHeight !== this.rootDoc.height) {
+ if (autoHeight && newHeight && newHeight !== this.rootDoc.height && !this.props.dontRegisterView) {
this.props.setHeight?.(newHeight);
}
},
@@ -1030,8 +1042,9 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
);
this._disposers.editorState = reaction(
() => {
- const whichDoc = !this.dataDoc || !this.layoutDoc ? undefined : this.dataDoc?.[this.props.fieldKey + '-noTemplate'] || !this.layoutDoc[this.props.fieldKey] ? this.dataDoc : this.layoutDoc;
- return !whichDoc ? undefined : { data: Cast(whichDoc[this.props.fieldKey], RichTextField, null), str: StrCast(whichDoc[this.props.fieldKey]) };
+ const dataDoc = Doc.IsDelegateField(DocCast(this.layoutDoc?.proto), this.fieldKey) ? DocCast(this.layoutDoc?.proto) : this?.dataDoc;
+ const whichDoc = !this.dataDoc || !this.layoutDoc ? undefined : dataDoc?.[this.fieldKey + '-noTemplate'] || !this.layoutDoc[this.fieldKey] ? dataDoc : this.layoutDoc;
+ return !whichDoc ? undefined : { data: Cast(whichDoc[this.fieldKey], RichTextField, null), str: Field.toString(whichDoc[this.fieldKey]) };
},
incomingValue => {
if (this._editorView && this._applyingChange !== this.fieldKey) {
@@ -1168,7 +1181,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
let pullSuccess = false;
if (exportState !== undefined) {
pullSuccess = true;
- dataDoc[this.props.fieldKey] = new RichTextField(JSON.stringify(exportState.state.toJSON()));
+ dataDoc[this.fieldKey] = new RichTextField(JSON.stringify(exportState.state.toJSON()));
setTimeout(() => {
if (this._editorView) {
const state = this._editorView.state;
@@ -1296,8 +1309,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
}
_didScroll = false;
setupEditor(config: any, fieldKey: string) {
- const curText = Cast(this.dataDoc[this.props.fieldKey], RichTextField, null) || StrCast(this.dataDoc[this.props.fieldKey]);
- const rtfField = Cast((!curText && this.layoutDoc[this.props.fieldKey]) || this.dataDoc[fieldKey], RichTextField);
+ const curText = Cast(this.dataDoc[this.fieldKey], RichTextField, null) || StrCast(this.dataDoc[this.fieldKey]);
+ const rtfField = Cast((!curText && this.layoutDoc[this.fieldKey]) || this.dataDoc[fieldKey], RichTextField);
if (this.ProseRef) {
const self = this;
this._editorView?.destroy();
@@ -1348,7 +1361,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
});
const { state, dispatch } = this._editorView;
if (!rtfField) {
- const startupText = Field.toString(this.dataDoc[fieldKey] as Field);
+ const dataDoc = Doc.IsDelegateField(DocCast(this.layoutDoc.proto), this.fieldKey) ? DocCast(this.layoutDoc.proto) : this.dataDoc;
+ const startupText = Field.toString(dataDoc[fieldKey] as Field);
if (startupText) {
dispatch(state.tr.insertText(startupText));
}
@@ -1697,9 +1711,11 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
const margins = 2 * NumCast(this.layoutDoc._yMargin, this.props.yPadding || 0);
const children = this.ProseRef?.children.length ? Array.from(this.ProseRef.children[0].children) : undefined;
if (children) {
- const proseHeight = !this.ProseRef ? 0 : children.reduce((p, child) => p + Number(getComputedStyle(child).height.replace('px', '')), margins);
+ const proseHeight = !this.ProseRef
+ ? 0
+ : children.reduce((p, child) => p + Number(getComputedStyle(child).height.replace('px', '')) + Number(getComputedStyle(child).marginTop.replace('px', '')) + Number(getComputedStyle(child).marginBottom.replace('px', '')), margins);
const scrollHeight = this.ProseRef && Math.min(NumCast(this.layoutDoc.docMaxAutoHeight, proseHeight), proseHeight);
- if (this.props.setHeight && scrollHeight && this.props.renderDepth && !this.props.dontRegisterView) {
+ if (this.props.setHeight && scrollHeight && !this.props.dontRegisterView) {
// if top === 0, then the text box is growing upward (as the overlay caption) which doesn't contribute to the height computation
const setScrollHeight = () => (this.rootDoc[this.fieldKey + '-scrollHeight'] = scrollHeight);
if (this.rootDoc === this.layoutDoc || this.layoutDoc.resolvedDataDoc) {
@@ -1860,7 +1876,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
className={`formattedTextBox-cont`}
ref={this._ref}
style={{
- overflow: this.autoHeight ? 'hidden' : undefined,
+ overflow: this.autoHeight && this.props.CollectionFreeFormDocumentView?.() ? 'hidden' : undefined, //x this breaks viewing an autoHeight doc in its own tab, or in the lightbox
height: this.props.height || (this.autoHeight && this.props.renderDepth && !this.props.suppressSetHeight ? 'max-content' : undefined),
pointerEvents: interactive ? undefined : 'none',
}}