aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/nodes')
-rw-r--r--src/client/views/nodes/DocumentLinksButton.tsx2
-rw-r--r--src/client/views/nodes/DocumentView.tsx34
-rw-r--r--src/client/views/nodes/LabelBox.tsx2
-rw-r--r--src/client/views/nodes/LinkBox.scss25
-rw-r--r--src/client/views/nodes/LinkBox.tsx69
-rw-r--r--src/client/views/nodes/LinkDescriptionPopup.tsx18
-rw-r--r--src/client/views/nodes/LinkDocPreview.tsx4
-rw-r--r--src/client/views/nodes/formattedText/DashFieldView.scss10
-rw-r--r--src/client/views/nodes/formattedText/DashFieldView.tsx27
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.tsx11
-rw-r--r--src/client/views/nodes/formattedText/RichTextRules.ts2
11 files changed, 158 insertions, 46 deletions
diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx
index d1805308d..2a68d2bf6 100644
--- a/src/client/views/nodes/DocumentLinksButton.tsx
+++ b/src/client/views/nodes/DocumentLinksButton.tsx
@@ -157,7 +157,7 @@ export class DocumentLinksButton extends ObservableReactComponent<DocumentLinksB
startLink = DocumentLinksButton.StartLinkView?.ComponentView?.getAnchor?.(true) || startLink;
const linkDoc = DocUtils.MakeLink(startLink, endLink, { link_relationship: DocumentLinksButton.AnnotationId ? 'hypothes.is annotation' : undefined });
- LinkManager.currentLink = linkDoc;
+ LinkManager.Instance.currentLink = linkDoc;
if (linkDoc) {
if (DocumentLinksButton.AnnotationId && DocumentLinksButton.AnnotationUri) {
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index b5355fb99..862dae83a 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -1,7 +1,7 @@
import { IconProp } from '@fortawesome/fontawesome-svg-core';
import { Dropdown, DropdownType, Type } from 'browndash-components';
import { Howl } from 'howler';
-import { IReactionDisposer, action, computed, makeObservable, observable, reaction, runInAction } from 'mobx';
+import { IReactionDisposer, action, computed, makeObservable, observable, reaction, runInAction, trace } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import { Bounce, Fade, Flip, JackInTheBox, Roll, Rotate, Zoom } from 'react-awesome-reveal';
@@ -20,13 +20,14 @@ import { DocServer } from '../../DocServer';
import { Networking } from '../../Network';
import { GooglePhotos } from '../../apis/google_docs/GooglePhotosClientUtils';
import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes';
-import { DocOptions, DocUtils, Docs, FInfo } from '../../documents/Documents';
+import { DocOptions, DocUtils, Docs } from '../../documents/Documents';
import { DictationManager } from '../../util/DictationManager';
import { DocumentManager } from '../../util/DocumentManager';
import { DragManager, dropActionType } from '../../util/DragManager';
import { FollowLinkScript } from '../../util/LinkFollower';
import { LinkManager } from '../../util/LinkManager';
import { ScriptingGlobals } from '../../util/ScriptingGlobals';
+import { SearchUtil } from '../../util/SearchUtil';
import { SelectionManager } from '../../util/SelectionManager';
import { SettingsManager } from '../../util/SettingsManager';
import { SharingManager } from '../../util/SharingManager';
@@ -106,6 +107,7 @@ export interface DocumentViewProps extends FieldViewSharedProps {
NativeWidth?: () => number;
NativeHeight?: () => number;
contextMenuItems?: () => { script: ScriptField; filter?: ScriptField; label: string; icon: string }[];
+ dragConfig?: (data: DragManager.DocumentDragData) => void;
dragStarting?: () => void;
dragEnding?: () => void;
}
@@ -288,7 +290,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
dragData.moveDocument = this._props.moveDocument;
dragData.draggedViews = [docView];
dragData.canEmbed = this.Document.dragAction ?? this._props.dragAction ? true : false;
- this._componentView?.dragConfig?.(dragData);
+ (this._props.dragConfig ?? this._componentView?.dragConfig)?.(dragData);
DragManager.StartDocumentDrag(
selected.map(dv => dv.ContentDiv!),
dragData,
@@ -1466,7 +1468,7 @@ ScriptingGlobals.add(function toggleDetail(dv: DocumentView, detailLayoutKeySuff
});
ScriptingGlobals.add(function updateLinkCollection(linkCollection: Doc, linkSource: Doc) {
- const collectedLinks = DocListCast(Doc.GetProto(linkCollection).data);
+ const collectedLinks = DocListCast(linkCollection[DocData].data);
let wid = NumCast(linkSource._width);
let embedding: Doc | undefined;
const links = LinkManager.Links(linkSource);
@@ -1485,3 +1487,27 @@ ScriptingGlobals.add(function updateLinkCollection(linkCollection: Doc, linkSour
embedding && DocServer.UPDATE_SERVER_CACHE(); // if a new embedding was made, update the client's server cache so that it will not come back as a promise
return links;
});
+ScriptingGlobals.add(function updateTagsCollection(collection: Doc) {
+ const tag = StrCast(collection.title).split('-->')[1];
+ const matchedTags = Array.from(SearchUtil.SearchCollection(Doc.MyFilesystem, tag, false, ['tags']).keys());
+ const collectionDocs = DocListCast(collection[DocData].data).concat(collection);
+ let wid = 100;
+ let created = false;
+ const matchedDocs = matchedTags
+ .filter(tagDoc => !Doc.AreProtosEqual(collection, tagDoc))
+ .map(tagDoc => {
+ let embedding = collectionDocs.find(doc => Doc.AreProtosEqual(tagDoc, doc));
+ if (!embedding) {
+ embedding = Doc.MakeEmbedding(tagDoc);
+ embedding.x = wid;
+ embedding.y = 0;
+ embedding._lockedPosition = false;
+ wid += NumCast(tagDoc._width);
+ created = true;
+ }
+ return embedding;
+ });
+
+ created && (collection[DocData].data = new List<Doc>(matchedDocs));
+ return true;
+});
diff --git a/src/client/views/nodes/LabelBox.tsx b/src/client/views/nodes/LabelBox.tsx
index 10eeff08d..fd3074a88 100644
--- a/src/client/views/nodes/LabelBox.tsx
+++ b/src/client/views/nodes/LabelBox.tsx
@@ -88,7 +88,7 @@ export class LabelBox extends ViewBoxBaseComponent<LabelBoxProps>() {
@observable _mouseOver = false;
@computed get hoverColor() {
- return this._mouseOver ? StrCast(this.layoutDoc._hoverBackgroundColor) : this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.BackgroundColor);
+ return this._mouseOver ? StrCast(this.layoutDoc._hoverBackgroundColor) : this._props.styleProvider?.(this.Document, this._props, StyleProp.BackgroundColor);
}
getAnchor = (addAsAnnotation: boolean, pinProps?: PinProps) => {
diff --git a/src/client/views/nodes/LinkBox.scss b/src/client/views/nodes/LinkBox.scss
index 767f0291b..484fb301e 100644
--- a/src/client/views/nodes/LinkBox.scss
+++ b/src/client/views/nodes/LinkBox.scss
@@ -5,3 +5,28 @@
.linkBox-container {
width: 100%;
}
+
+.linkBox {
+ transition: inherit;
+ pointer-events: none;
+ position: absolute;
+ width: 100%;
+ height: 100%;
+ path {
+ transition: inherit;
+ fill: transparent;
+ }
+ svg {
+ transition: inherit;
+ overflow: visible;
+ }
+ text {
+ cursor: default;
+ text-anchor: middle;
+ font-size: 12;
+ stroke: black;
+ }
+ circle {
+ cursor: default;
+ }
+}
diff --git a/src/client/views/nodes/LinkBox.tsx b/src/client/views/nodes/LinkBox.tsx
index 8b6293806..7ade846e7 100644
--- a/src/client/views/nodes/LinkBox.tsx
+++ b/src/client/views/nodes/LinkBox.tsx
@@ -4,7 +4,7 @@ import { observer } from 'mobx-react';
import * as React from 'react';
import { Id } from '../../../fields/FieldSymbols';
import { DocCast, NumCast, StrCast } from '../../../fields/Types';
-import { aggregateBounds, emptyFunction, returnAlways, returnFalse, Utils } from '../../../Utils';
+import { aggregateBounds, emptyFunction, returnAlways, returnFalse, setupMoveUpEvents, Utils } from '../../../Utils';
import { DocumentManager } from '../../util/DocumentManager';
import { Transform } from '../../util/Transform';
import { CollectionFreeFormView } from '../collections/collectionFreeForm';
@@ -13,6 +13,8 @@ import { StyleProp } from '../StyleProvider';
import { ComparisonBox } from './ComparisonBox';
import { FieldView, FieldViewProps } from './FieldView';
import './LinkBox.scss';
+import { LinkDescriptionPopup } from './LinkDescriptionPopup';
+import { LinkManager } from '../../util/LinkManager';
@observer
export class LinkBox extends ViewBoxBaseComponent<FieldViewProps>() {
@@ -97,8 +99,8 @@ export class LinkBox extends ViewBoxBaseComponent<FieldViewProps>() {
) {
this.layoutDoc.x = params?.lx;
this.layoutDoc.y = params?.ty;
- this.layoutDoc._width = params.rx - params?.lx;
- this.layoutDoc._height = params?.by - params?.ty;
+ this.layoutDoc._width = Math.max(1, params.rx - params?.lx);
+ this.layoutDoc._height = Math.max(1, params?.by - params?.ty);
}
} else {
this.layoutDoc._width = Math.max(50, NumCast(this.layoutDoc._width));
@@ -108,6 +110,22 @@ export class LinkBox extends ViewBoxBaseComponent<FieldViewProps>() {
{ fireImmediately: true }
);
}
+ descriptionDown = (e: React.PointerEvent) => {
+ setupMoveUpEvents(this, e, returnFalse, returnFalse, () => {
+ LinkManager.Instance.currentLink = this.Document;
+ LinkDescriptionPopup.Instance.popupX = e.clientX;
+ LinkDescriptionPopup.Instance.popupY = e.clientY;
+ LinkDescriptionPopup.Instance.display = true;
+
+ const rect = document.body.getBoundingClientRect();
+ if (LinkDescriptionPopup.Instance.popupX + 200 > rect.width) {
+ LinkDescriptionPopup.Instance.popupX -= 190;
+ }
+ if (LinkDescriptionPopup.Instance.popupY + 100 > rect.height) {
+ LinkDescriptionPopup.Instance.popupY -= 40;
+ }
+ });
+ };
componentWillUnmount(): void {
this.disposer?.();
}
@@ -117,19 +135,21 @@ export class LinkBox extends ViewBoxBaseComponent<FieldViewProps>() {
const highlight = this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.Highlighting);
const highlightColor = highlight?.highlightIndex ? highlight?.highlightColor : undefined;
- const bez = new Bezier(this.renderProps.pts.map(p => ({ x: p[0], y: p[1] })));
- const text = bez.get(0.5);
- const linkDesc = StrCast(this.dataDoc.link_description) || 'description';
+ const { pts, lx, ty, rx, by } = this.renderProps;
+ const bez = new Bezier(pts.map(p => ({ x: p[0] - lx, y: p[1] - ty })));
+ const { x, y } = bez.get(0.5);
+ const linkDesc = StrCast(this.dataDoc.link_description) || ' ';
const strokeWidth = NumCast(this.dataDoc.stroke_width, 4);
const dash = StrCast(this.Document.stroke_dash);
const strokeDasharray = dash && Number(dash) ? String(strokeWidth * Number(dash)) : undefined;
- const { pts, lx, ty, rx, by } = this.renderProps;
+ const pointerEvents = this._props.pointerEvents?.() === 'none' ? 'none' : 'all';
+ const stroke = highlightColor ?? 'lightblue';
return (
- <div style={{ transition: 'inherit', pointerEvents: 'none', position: 'absolute', width: '100%', height: '100%' }}>
- <svg width={Math.max(100, rx - lx)} height={Math.max(100, by - ty)} style={{ transition: 'inherit', overflow: 'visible' }}>
+ <div className="linkBox">
+ <svg width={Math.max(100, rx - lx)} height={Math.max(100, by - ty)}>
<defs>
<filter x="0" y="0" width="1" height="1" id={`${this.Document[Id] + 'background'}`}>
- <feFlood floodColor={`${StrCast(this.layoutDoc._backgroundColor, 'lightblue')}`} result="bg" />
+ <feFlood floodColor={`${highlightColor ?? StrCast(this.layoutDoc._backgroundColor, 'lightblue')}`} result="bg" />
<feMerge>
<feMergeNode in="bg" />
<feMergeNode in="SourceGraphic" />
@@ -137,26 +157,27 @@ export class LinkBox extends ViewBoxBaseComponent<FieldViewProps>() {
</filter>
</defs>
<path
- className="collectionfreeformlinkview-linkLine"
style={{
pointerEvents: this._props.pointerEvents?.() === 'none' ? 'none' : 'visibleStroke', //
- stroke: highlightColor ?? 'lightblue',
+ stroke,
strokeDasharray,
strokeWidth,
- transition: 'inherit',
}}
- d={`M ${pts[1][0] - lx} ${pts[1][1] - ty} C ${pts[1][0] + pts[1][0] - pts[0][0] - lx} ${pts[1][1] + pts[1][1] - pts[0][1] - ty},
- ${pts[2][0] + pts[2][0] - pts[3][0] - lx} ${pts[2][1] + pts[2][1] - pts[3][1] - ty}, ${pts[2][0] - lx} ${pts[2][1] - ty}`}
+ d={`M ${bez.points[0].x} ${bez.points[0].y} C ${bez.points[1].x} ${bez.points[1].y},
+ ${bez.points[2].x} ${bez.points[2].y}, ${bez.points[3].x} ${bez.points[3].y}`}
/>
- <text
- filter={`url(#${this.Document[Id] + 'background'})`}
- style={{ pointerEvents: this._props.pointerEvents?.() === 'none' ? 'none' : 'all', textAnchor: 'middle', fontSize: '12', stroke: 'black' }}
- x={text.x - lx}
- y={text.y - ty}>
- <tspan>&nbsp;</tspan>
- <tspan dy="2">{linkDesc.substring(0, 50) + (linkDesc.length > 50 ? '...' : '')}</tspan>
- <tspan dy="2">&nbsp;</tspan>
- </text>
+ {!linkDesc.trim().length ? (
+ <circle r={5} onPointerDown={this.descriptionDown} style={{ fill: stroke, pointerEvents }} cx={x} cy={y} />
+ ) : (
+ <text
+ onPointerDown={this.descriptionDown} //
+ filter={`url(#${this.Document[Id] + 'background'})`}
+ style={{ pointerEvents, background: stroke }}
+ x={x}
+ y={y}>
+ <tspan style={{ background: stroke }}>&nbsp;{linkDesc.substring(0, 50) + (linkDesc.length > 50 ? '...' : '')}&nbsp;</tspan>
+ </text>
+ )}
</svg>
</div>
);
diff --git a/src/client/views/nodes/LinkDescriptionPopup.tsx b/src/client/views/nodes/LinkDescriptionPopup.tsx
index 13f0ac4fc..1645d0813 100644
--- a/src/client/views/nodes/LinkDescriptionPopup.tsx
+++ b/src/client/views/nodes/LinkDescriptionPopup.tsx
@@ -1,10 +1,11 @@
-import { action, makeObservable, observable } from 'mobx';
+import { action, makeObservable, observable, reaction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import { DocData } from '../../../fields/DocSymbols';
import { LinkManager } from '../../util/LinkManager';
import './LinkDescriptionPopup.scss';
import { TaskCompletionBox } from './TaskCompletedBox';
+import { StrCast } from '../../../fields/Types';
@observer
export class LinkDescriptionPopup extends React.Component<{}> {
@@ -31,21 +32,26 @@ export class LinkDescriptionPopup extends React.Component<{}> {
onDismiss = (add: boolean) => {
this.display = false;
if (add) {
- LinkManager.currentLink && (LinkManager.currentLink[DocData].link_description = this.description);
+ LinkManager.Instance.currentLink && (LinkManager.Instance.currentLink[DocData].link_description = this.description);
}
+ this.description = '';
};
@action
onClick = (e: PointerEvent) => {
if (this.popupRef && !!!this.popupRef.current?.contains(e.target as any)) {
this.display = false;
+ this.description = '';
TaskCompletionBox.taskCompleted = false;
}
};
- @action
componentDidMount() {
document.addEventListener('pointerdown', this.onClick, true);
+ reaction(
+ () => this.display,
+ display => display && (this.description = StrCast(LinkManager.Instance.currentLink?.link_description))
+ );
}
componentWillUnmount() {
@@ -65,8 +71,10 @@ export class LinkDescriptionPopup extends React.Component<{}> {
className="linkDescriptionPopup-input"
onKeyDown={e => e.stopPropagation()}
onKeyPress={e => e.key === 'Enter' && this.onDismiss(true)}
- placeholder={'(Optional) Enter link description...'}
- onChange={e => this.descriptionChanged(e)}></input>
+ value={this.description}
+ placeholder={this.description || '(Optional) Enter link description...'}
+ onChange={e => this.descriptionChanged(e)}
+ />
<div className="linkDescriptionPopup-btn">
<div className="linkDescriptionPopup-btn-dismiss" onPointerDown={e => this.onDismiss(false)}>
{' '}
diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx
index 3f793b85e..ae25ff179 100644
--- a/src/client/views/nodes/LinkDocPreview.tsx
+++ b/src/client/views/nodes/LinkDocPreview.tsx
@@ -152,8 +152,8 @@ export class LinkDocPreview extends ObservableReactComponent<LinkDocPreviewProps
returnFalse,
emptyFunction,
action(() => {
- LinkManager.currentLink = this._linkDoc;
- LinkManager.currentLinkAnchor = this._linkSrc;
+ LinkManager.Instance.currentLink = this._linkDoc;
+ LinkManager.Instance.currentLinkAnchor = this._linkSrc;
this._props.DocumentView?.().select(false);
if ((SettingsManager.Instance.propertiesWidth ?? 0) < 100) {
SettingsManager.Instance.propertiesWidth = 250;
diff --git a/src/client/views/nodes/formattedText/DashFieldView.scss b/src/client/views/nodes/formattedText/DashFieldView.scss
index 3426ba1a7..7a0ff8776 100644
--- a/src/client/views/nodes/formattedText/DashFieldView.scss
+++ b/src/client/views/nodes/formattedText/DashFieldView.scss
@@ -5,6 +5,16 @@
display: inline-flex;
align-items: center;
+ select {
+ display: none;
+ }
+
+ &:hover {
+ select {
+ display: unset;
+ }
+ }
+
.dashFieldView-enumerables {
width: 10px;
height: 10px;
diff --git a/src/client/views/nodes/formattedText/DashFieldView.tsx b/src/client/views/nodes/formattedText/DashFieldView.tsx
index 18286267a..ec0b76aa8 100644
--- a/src/client/views/nodes/formattedText/DashFieldView.tsx
+++ b/src/client/views/nodes/formattedText/DashFieldView.tsx
@@ -4,21 +4,24 @@ import { action, computed, IReactionDisposer, makeObservable, observable, reacti
import { observer } from 'mobx-react';
import * as React from 'react';
import * as ReactDOM from 'react-dom/client';
-import { Doc, Field } from '../../../../fields/Doc';
+import Select from 'react-select';
+import { Doc, DocListCast, Field } from '../../../../fields/Doc';
import { List } from '../../../../fields/List';
import { listSpec } from '../../../../fields/Schema';
import { SchemaHeaderField } from '../../../../fields/SchemaHeaderField';
-import { Cast } from '../../../../fields/Types';
+import { Cast, StrCast } from '../../../../fields/Types';
import { emptyFunction, returnFalse, returnZero, setupMoveUpEvents } from '../../../../Utils';
import { DocServer } from '../../../DocServer';
import { CollectionViewType } from '../../../documents/DocumentTypes';
import { Transform } from '../../../util/Transform';
+import { undoable, undoBatch } from '../../../util/UndoManager';
import { AntimodeMenu, AntimodeMenuProps } from '../../AntimodeMenu';
import { SchemaTableCell } from '../../collections/collectionSchema/SchemaTableCell';
import { ObservableReactComponent } from '../../ObservableReactComponent';
import { OpenWhere } from '../DocumentView';
import './DashFieldView.scss';
import { FormattedTextBox } from './FormattedTextBox';
+import { FilterPanel } from '../../FilterPanel';
export class DashFieldView {
dom: HTMLDivElement; // container for label and value
@@ -97,7 +100,7 @@ export class DashFieldViewInternal extends ObservableReactComponent<IDashFieldVi
_reactionDisposer: IReactionDisposer | undefined;
_textBoxDoc: Doc;
_fieldKey: string;
- _fieldStringRef = React.createRef<HTMLSpanElement>();
+ _fieldRef = React.createRef<HTMLDivElement>();
@observable _dashDoc: Doc | undefined = undefined;
@observable _expanded = false;
@@ -180,10 +183,22 @@ export class DashFieldViewInternal extends ObservableReactComponent<IDashFieldVi
});
};
+ @undoBatch
+ selectVal = (event: React.ChangeEvent<HTMLSelectElement> | undefined) => {
+ event && this._dashDoc && (this._dashDoc[this._fieldKey] = event.target.value);
+ };
+
+ @computed get values() {
+ const vals = FilterPanel.gatherFieldValues(DocListCast(Doc.ActiveDashboard?.data), this._fieldKey, []);
+
+ return vals.strings.map(facet => ({ value: facet, label: facet }));
+ }
+
render() {
return (
<div
className="dashFieldView"
+ ref={this._fieldRef}
style={{
width: this._props.width,
height: this._props.height,
@@ -194,8 +209,12 @@ export class DashFieldViewInternal extends ObservableReactComponent<IDashFieldVi
{(this._textBoxDoc === this._dashDoc ? '' : this._dashDoc?.title + ':') + this._fieldKey}
</span>
)}
-
{this._props.fieldKey.startsWith('#') ? null : this.fieldValueContent}
+ <select onChange={this.selectVal} style={{ height: '10px', width: '15px', fontSize: '12px', background: 'transparent' }}>
+ {this.values.map(val => (
+ <option value={val.value}>{val.label}</option>
+ ))}
+ </select>
</div>
);
}
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index b82ab4219..f2c4c6c8f 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -13,7 +13,7 @@ import { EditorView } from 'prosemirror-view';
import * as React from 'react';
import { BsMarkdownFill } from 'react-icons/bs';
import { DateField } from '../../../../fields/DateField';
-import { Doc, DocListCast, Field, Opt } from '../../../../fields/Doc';
+import { Doc, DocListCast, Field, Opt, StrListCast } from '../../../../fields/Doc';
import { AclAdmin, AclAugment, AclEdit, AclSelfEdit, DocCss, DocData, ForceServerWrite, UpdatingFromServer } from '../../../../fields/DocSymbols';
import { Id } from '../../../../fields/FieldSymbols';
import { InkTool } from '../../../../fields/InkField';
@@ -67,6 +67,7 @@ import { RichTextMenu, RichTextMenuPlugin } from './RichTextMenu';
import { RichTextRules } from './RichTextRules';
import { schema } from './schema_rts';
import { SummaryView } from './SummaryView';
+import Select from 'react-select';
// import * as applyDevTools from 'prosemirror-dev-tools';
@observer
export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implements ViewBoxInterface {
@@ -360,7 +361,9 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
accumTags.push(node.attrs.fieldKey);
}
});
- dataDoc.tags = accumTags.length ? new List<string>(Array.from(new Set<string>(accumTags))) : undefined;
+ if (accumTags.some(atag => !StrListCast(dataDoc.tags).includes(atag))) {
+ dataDoc.tags = new List<string>(Array.from(new Set<string>(accumTags)));
+ }
let unchanged = true;
if (this._applyingChange !== this.fieldKey && (force || removeSelection(newJson) !== removeSelection(prevData?.Data))) {
@@ -1189,8 +1192,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
this._cachedLinks = LinkManager.Links(this.Document);
this._disposers.breakupDictation = reaction(() => Doc.RecordingEvent, this.breakupDictation);
this._disposers.layout_autoHeight = reaction(
- () => this.layout_autoHeight,
- layout_autoHeight => layout_autoHeight && this.tryUpdateScrollHeight()
+ () => ({ autoHeight: this.layout_autoHeight, fontSize: this.fontSize }),
+ (autoHeight, fontSize) => setTimeout(() => autoHeight && this.tryUpdateScrollHeight())
);
this._disposers.highlights = reaction(
() => Array.from(FormattedTextBox._globalHighlights).slice(),
diff --git a/src/client/views/nodes/formattedText/RichTextRules.ts b/src/client/views/nodes/formattedText/RichTextRules.ts
index 2fdd6374a..9bd41f42c 100644
--- a/src/client/views/nodes/formattedText/RichTextRules.ts
+++ b/src/client/views/nodes/formattedText/RichTextRules.ts
@@ -264,7 +264,7 @@ export class RichTextRules {
return null;
}),
- // stop using active style
+ // toggle alternate text UI %/
new InputRule(new RegExp(/%\//), (state, match, start, end) => {
setTimeout(this.TextBox.cycleAlternateText);
return state.tr.deleteRange(start, end);