aboutsummaryrefslogtreecommitdiff
path: root/src/client
diff options
context:
space:
mode:
Diffstat (limited to 'src/client')
-rw-r--r--src/client/documents/Documents.ts14
-rw-r--r--src/client/util/CurrentUserUtils.ts6
-rw-r--r--src/client/util/RTFMarkup.tsx2
-rw-r--r--src/client/views/FilterPanel.tsx6
-rw-r--r--src/client/views/PropertiesView.tsx152
-rw-r--r--src/client/views/StyleProvider.tsx4
-rw-r--r--src/client/views/collections/CollectionDockingView.tsx1
-rw-r--r--src/client/views/collections/CollectionTimeView.tsx2
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx15
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx8
-rw-r--r--src/client/views/nodes/CollectionFreeFormDocumentView.tsx8
-rw-r--r--src/client/views/nodes/DocumentView.tsx2
-rw-r--r--src/client/views/nodes/WebBoxRenderer.js4
-rw-r--r--src/client/views/nodes/button/FontIconBox.tsx20
-rw-r--r--src/client/views/nodes/formattedText/DashDocView.tsx3
-rw-r--r--src/client/views/nodes/formattedText/DashFieldView.tsx8
-rw-r--r--src/client/views/nodes/formattedText/EquationView.tsx1
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.tsx34
-rw-r--r--src/client/views/nodes/formattedText/RichTextRules.ts16
-rw-r--r--src/client/views/nodes/formattedText/SummaryView.tsx1
20 files changed, 129 insertions, 178 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 2187f8231..5a7894c08 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -10,8 +10,8 @@ import { List } from '../../fields/List';
import { RichTextField } from '../../fields/RichTextField';
import { SchemaHeaderField } from '../../fields/SchemaHeaderField';
import { ComputedField, ScriptField } from '../../fields/ScriptField';
-import { Cast, DocCast, FieldValue, NumCast, ScriptCast, StrCast } from '../../fields/Types';
-import { AudioField, CsvField, ImageField, MapField, PdfField, RecordingField, VideoField, WebField, YoutubeField } from '../../fields/URLField';
+import { BoolCast, Cast, DocCast, FieldValue, NumCast, ScriptCast, StrCast } from '../../fields/Types';
+import { AudioField, CsvField, ImageField, PdfField, VideoField, WebField, YoutubeField } from '../../fields/URLField';
import { inheritParentAcls, SharingPermissions } from '../../fields/util';
import { Upload } from '../../server/SharedMediaTypes';
import { aggregateBounds, OmitKeys, Utils } from '../../Utils';
@@ -37,7 +37,7 @@ import { FontIconBox } from '../views/nodes/button/FontIconBox';
import { ColorBox } from '../views/nodes/ColorBox';
import { ComparisonBox } from '../views/nodes/ComparisonBox';
import { DataVizBox } from '../views/nodes/DataVizBox/DataVizBox';
-import { DocFocusOptions, OpenWhere, OpenWhereMod } from '../views/nodes/DocumentView';
+import { OpenWhereMod } from '../views/nodes/DocumentView';
import { EquationBox } from '../views/nodes/EquationBox';
import { FieldViewProps } from '../views/nodes/FieldView';
import { FormattedTextBox } from '../views/nodes/formattedText/FormattedTextBox';
@@ -173,6 +173,7 @@ export class DocumentOptions {
_lockedTransform?: boolean; // lock the panx,pany and scale parameters of the document so that it be panned/zoomed
_followLinkToggle?: boolean; // whether document, when clicked, toggles display of its link target
_showTitle?: string; // field name to display in header (:hover is an optional suffix)
+ _showAltContentUI?: boolean; // whether to show alternate content button
_isLightbox?: boolean; // whether a collection acts as a lightbox by opening lightbox links by hiding all other documents in collection besides link target
_showCaption?: string; // which field to display in the caption area. leave empty to have no caption
_scrollTop?: number; // scroll location for pdfs
@@ -1441,18 +1442,12 @@ export namespace DocUtils {
} else if (field instanceof AudioField) {
created = Docs.Create.AudioDocument(field.url.href, resolved);
created.layout = AudioBox.LayoutString(fieldKey);
- } else if (field instanceof RecordingField) {
- created = Docs.Create.RecordingDocument(field.url.href, resolved);
- created.layout = RecordingBox.LayoutString(fieldKey);
} else if (field instanceof InkField) {
created = Docs.Create.InkDocument(ActiveInkColor(), Doc.ActiveTool, ActiveInkWidth(), ActiveInkBezierApprox(), ActiveFillColor(), ActiveArrowStart(), ActiveArrowEnd(), ActiveDash(), field.inkData, ActiveIsInkMask(), resolved);
created.layout = InkingStroke.LayoutString(fieldKey);
} else if (field instanceof List && field[0] instanceof Doc) {
created = Docs.Create.StackingDocument(DocListCast(field), resolved);
created.layout = CollectionView.LayoutString(fieldKey);
- } else if (field instanceof MapField) {
- created = Docs.Create.MapDocument(DocListCast(field), resolved);
- created.layout = MapBox.LayoutString(fieldKey);
} else {
created = Docs.Create.TextDocument('', { ...{ _width: 200, _height: 25, _autoHeight: true }, ...resolved });
created.layout = FormattedTextBox.LayoutString(fieldKey);
@@ -1800,6 +1795,7 @@ export namespace DocUtils {
y: y,
_fitWidth: true,
_autoHeight: true,
+ _showAltContentUI: BoolCast(Doc.UserDoc().defaultToFlashcards),
title,
});
const template = Doc.UserDoc().defaultTextLayout;
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index d43419933..80a5f0993 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -264,9 +264,10 @@ export class CurrentUserUtils {
creator:(opts:DocumentOptions)=> any // how to create the empty thing if it doesn't exist
}[] = [
{key: "Note", creator: opts => Docs.Create.TextDocument("", opts), opts: { _width: 200, _autoHeight: true }},
+ {key: "Flashcard", creator: opts => Docs.Create.TextDocument("", opts), opts: { _width: 200, _autoHeight: true, _showAltContentUI: true}},
+ {key: "Equation", creator: opts => Docs.Create.EquationDocument(opts), opts: { _width: 300, _height: 35, _backgroundGridShow: true, }},
{key: "Noteboard", creator: opts => Docs.Create.NoteTakingDocument([], opts), opts: { _width: 250, _height: 200, _fitWidth: true}},
{key: "Collection", creator: opts => Docs.Create.FreeformDocument([], opts), opts: { _width: 150, _height: 100, _fitWidth: true }},
- {key: "Equation", creator: opts => Docs.Create.EquationDocument(opts), opts: { _width: 300, _height: 35, _backgroundGridShow: true, }},
{key: "Webpage", creator: opts => Docs.Create.WebDocument("",opts), opts: { _width: 400, _height: 512, _nativeWidth: 850, useCors: true, }},
{key: "Comparison", creator: Docs.Create.ComparisonDocument, opts: { _width: 300, _height: 300 }},
{key: "Audio", creator: opts => Docs.Create.AudioDocument(nullAudio, opts),opts: { _width: 200, _height: 100, }},
@@ -290,9 +291,10 @@ export class CurrentUserUtils {
return [
{ toolTip: "Tap or drag to create a note", title: "Note", icon: "sticky-note", dragFactory: doc.emptyNote as Doc, clickFactory: DocCast(doc.emptyNote)},
+ { toolTip: "Tap or drag to create a flashcard", title: "Flashcard", icon: "id-card", dragFactory: doc.emptyFlashcard as Doc, clickFactory: DocCast(doc.emptyFlashcard)},
+ { toolTip: "Tap or drag to create an equation", title: "Math", icon: "calculator", dragFactory: doc.emptyEquation as Doc, clickFactory: DocCast(doc.emptyEquation)},
{ toolTip: "Tap or drag to create a note board", title: "Notes", icon: "folder", dragFactory: doc.emptyNoteboard as Doc, clickFactory: DocCast(doc.emptyNoteboard)},
{ toolTip: "Tap or drag to create a collection", title: "Col", icon: "folder", dragFactory: doc.emptyCollection as Doc,clickFactory: DocCast(doc.emptyTab)},
- { toolTip: "Tap or drag to create an equation", title: "Math", icon: "calculator", dragFactory: doc.emptyEquation as Doc, clickFactory: DocCast(doc.emptyEquation)},
{ toolTip: "Tap or drag to create a webpage", title: "Web", icon: "globe-asia", dragFactory: doc.emptyWebpage as Doc, clickFactory: DocCast(doc.emptyWebpage)},
{ toolTip: "Tap or drag to create a comparison box", title: "Compare", icon: "columns", dragFactory: doc.emptyComparison as Doc,clickFactory: DocCast(doc.emptyComparison)},
{ toolTip: "Tap or drag to create an audio recorder", title: "Audio", icon: "microphone", dragFactory: doc.emptyAudio as Doc, clickFactory: DocCast(doc.emptyAudio), openFactoryLocation: OpenWhere.overlay},
diff --git a/src/client/util/RTFMarkup.tsx b/src/client/util/RTFMarkup.tsx
index 69f62fc3f..247267710 100644
--- a/src/client/util/RTFMarkup.tsx
+++ b/src/client/util/RTFMarkup.tsx
@@ -92,7 +92,7 @@ export class RTFMarkup extends React.Component<{}> {
{` creates an equation block for typeset math`}
</p>
<p>
- <b style={{ fontSize: 'larger' }}>{`%alt `}</b>
+ <b style={{ fontSize: 'larger' }}>{`%/ `}</b>
{` switch between primary and alternate text (see bottom right Button for hover options).`}
</p>
<p>
diff --git a/src/client/views/FilterPanel.tsx b/src/client/views/FilterPanel.tsx
index a237249c1..84b2e1407 100644
--- a/src/client/views/FilterPanel.tsx
+++ b/src/client/views/FilterPanel.tsx
@@ -53,7 +53,7 @@ export class FilterPanel extends React.Component<filterProps> {
this.allDocs.forEach(doc => SearchBox.documentKeys(doc).filter(key => keys.add(key)));
const sortedKeys = Array.from(keys.keys())
.filter(key => key[0])
- .filter(key => key[0] === '#' || key.indexOf('lastModified') !== -1 || (key[0] === key[0].toUpperCase() && !key.startsWith('_')) || noviceFields.includes(key) || !Doc.noviceMode)
+ .filter(key => key.indexOf('lastModified') !== -1 || (key[0] === key[0].toUpperCase() && !key.startsWith('_')) || noviceFields.includes(key) || !Doc.noviceMode)
.sort();
noviceFields.forEach(key => sortedKeys.splice(sortedKeys.indexOf(key), 1));
return [...noviceFields, ...sortedKeys];
@@ -145,8 +145,8 @@ export class FilterPanel extends React.Component<filterProps> {
const set = new Set<string>([String.fromCharCode(127) + '--undefined--']);
if (facetHeader === 'tags')
allCollectionDocs.forEach(child =>
- Field.toString(child[facetHeader] as Field)
- .split(':')
+ StrListCast(child[facetHeader])
+ .filter(h => h)
.forEach(key => set.add(key))
);
else
diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx
index 6582c3f2a..0b14c7b10 100644
--- a/src/client/views/PropertiesView.tsx
+++ b/src/client/views/PropertiesView.tsx
@@ -7,7 +7,7 @@ import { intersection } from 'lodash';
import { action, computed, Lambda, observable } from 'mobx';
import { observer } from 'mobx-react';
import { ColorState, SketchPicker } from 'react-color';
-import { AclAdmin, AclSym, DataSym, Doc, Field, HeightSym, HierarchyMapping, NumListCast, Opt, StrListCast, WidthSym } from '../../fields/Doc';
+import { AclAdmin, AclSym, DataSym, Doc, Field, FieldResult, HeightSym, HierarchyMapping, NumListCast, Opt, StrListCast, WidthSym } from '../../fields/Doc';
import { Id } from '../../fields/FieldSymbols';
import { InkField } from '../../fields/InkField';
import { List } from '../../fields/List';
@@ -152,116 +152,55 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
return 0;
};
- @computed get expandedField() {
+ editableFields = (filter: (key: string) => boolean, reqdKeys: string[]) => {
+ const rows: JSX.Element[] = [];
if (this.dataDoc && this.selectedDoc) {
- const ids: { [key: string]: string } = {};
- const docs = SelectionManager.Views().length < 2 ? [this.layoutFields ? Doc.Layout(this.selectedDoc) : this.dataDoc] : SelectionManager.Views().map(dv => (this.layoutFields ? dv.layoutDoc : dv.dataDoc));
- docs.forEach(doc => Object.keys(doc).forEach(key => !(key in ids) && doc[key] !== ComputedField.undefined && (ids[key] = key)));
- const rows: JSX.Element[] = [];
- for (const key of Object.keys(ids).slice().sort()) {
- const docvals = new Set<any>();
- docs.forEach(doc => docvals.add(doc[key]));
- const contents = Array.from(docvals.keys()).length > 1 ? '-multiple' : docs[0][key];
- if (key[0] === '#') {
- rows.push(
- <div style={{ display: 'flex', overflowY: 'visible', marginBottom: '2px' }} key={key}>
- <span style={{ fontWeight: 'bold', whiteSpace: 'nowrap' }}>{key}</span>
- &nbsp;
- </div>
- );
- } else {
- const contentElement = (
- <EditableView
- key="editableView"
- contents={contents !== undefined ? Field.toString(contents as Field) : 'null'}
- height={13}
- fontSize={10}
- GetValue={() => (contents !== undefined ? Field.toString(contents as Field) : 'null')}
- SetValue={(value: string) => {
- docs.map(doc => KeyValueBox.SetField(doc, key, value, true));
- return true;
- }}
- />
- );
- rows.push(
- <div style={{ display: 'flex', overflowY: 'visible', marginBottom: '-1px' }} key={key}>
- <span style={{ fontWeight: 'bold', whiteSpace: 'nowrap' }}>{key + ':'}</span>
- &nbsp;
- {contentElement}
- </div>
- );
- }
- }
+ const ids = new Set<string>(reqdKeys);
+ const docs: Doc[] = SelectionManager.Views().length < 2 ? [this.layoutFields ? Doc.Layout(this.selectedDoc) : this.dataDoc] : SelectionManager.Views().map(dv => (this.layoutFields ? dv.layoutDoc : dv.dataDoc));
+ docs.forEach(doc => Object.keys(doc).forEach(key => doc[key] !== ComputedField.undefined && ids.add(key)));
+
+ // prettier-ignore
+ Array.from(ids).filter(filter).sort().map(key => {
+ const multiple = Array.from(docs.reduce((set,doc) => set.add(doc[key]), new Set<FieldResult>()).keys()).length > 1;
+ const editableContents = multiple ? '-multiple-' : Field.toKeyValueString(docs[0], key);
+ const displayContents = multiple ? '-multiple-' : Field.toString(docs[0][key] as Field);
+ const contentElement = (
+ <EditableView
+ key="editableView"
+ contents={displayContents}
+ height={13}
+ fontSize={10}
+ GetValue={() => editableContents}
+ SetValue={(value: string) => {
+ value !== '-multiple-' && docs.map(doc => KeyValueBox.SetField(doc, key, value, true));
+ return true;
+ }}
+ />);
+ rows.push(
+ <div style={{ display: 'flex', overflowY: 'visible', marginBottom: '-1px' }} key={key}>
+ <span style={{ fontWeight: 'bold', whiteSpace: 'nowrap' }}>{key + ':'}</span>
+ &nbsp;
+ {contentElement}
+ </div>
+ );
+ });
+
rows.push(
- <div className="propertiesView-field" key={'newKeyValue'} style={{ marginTop: '3px' }}>
+ <div className="propertiesView-field" key="newKeyValue" style={{ marginTop: '3px' }}>
<EditableView key="editableView" oneLine contents={'add key:value or #tags'} height={13} fontSize={10} GetValue={() => ''} SetValue={this.setKeyValue} />
</div>
);
- return rows;
}
+ return rows;
+ };
+
+ @computed get expandedField() {
+ return this.editableFields(returnTrue, []);
}
@computed get noviceFields() {
- if (this.dataDoc) {
- const ids: { [key: string]: string } = {};
- const docs = SelectionManager.Views().length < 2 ? [this.dataDoc] : SelectionManager.Views().map(dv => dv.dataDoc);
- docs.forEach(doc => Object.keys(doc).forEach(key => !(key in ids) && doc[key] !== ComputedField.undefined && (ids[key] = key)));
- const rows: JSX.Element[] = [];
- const noviceReqFields = ['author', 'creationDate', 'tags'];
- const noviceLayoutFields = ['_curPage'];
- const noviceKeys = [...Array.from(Object.keys(ids)).filter(key => key[0] === '#' || key.indexOf('lastModified') !== -1 || (key[0] === key[0].toUpperCase() && !key.startsWith('acl'))), ...noviceReqFields, ...noviceLayoutFields];
- for (const key of noviceKeys.sort()) {
- const docvals = new Set<any>();
- docs.forEach(doc => docvals.add(doc[key]));
- const contents = Array.from(docvals.keys()).length > 1 ? '-multiple' : docs[0][key];
- if (key[0] === '#') {
- rows.push(
- <div className="propertiesView-uneditable-field" key={key}>
- <span style={{ fontWeight: 'bold', whiteSpace: 'nowrap' }}>{key}</span>
- &nbsp;
- </div>
- );
- } else if (contents !== undefined) {
- const value = Field.toString(contents as Field);
- if (noviceReqFields.includes(key) || key.indexOf('lastModified') !== -1) {
- rows.push(
- <div className="propertiesView-uneditable-field" key={key}>
- <span style={{ fontWeight: 'bold', whiteSpace: 'nowrap' }}>{key + ': '}</span>
- <div style={{ whiteSpace: 'nowrap', overflowX: 'hidden' }}>{value}</div>
- </div>
- );
- } else {
- const contentElement = (
- <EditableView
- key="editableView"
- contents={value}
- height={13}
- fontSize={10}
- GetValue={() => (contents !== undefined ? Field.toString(contents as Field) : 'null')}
- SetValue={(value: string) => {
- docs.map(doc => KeyValueBox.SetField(doc, key, value, true));
- return true;
- }}
- />
- );
-
- rows.push(
- <div style={{ display: 'flex', overflowY: 'visible', marginBottom: '-1px' }} key={key}>
- <span style={{ fontWeight: 'bold', whiteSpace: 'nowrap' }}>{key + ':'}</span>
- &nbsp;
- {contentElement}
- </div>
- );
- }
- }
- }
- rows.push(
- <div className="propertiesView-field" key={'newKeyValue'} style={{ marginTop: '3px' }}>
- <EditableView key="editableView" oneLine contents={'add key:value or #tags'} height={13} fontSize={10} GetValue={() => ''} SetValue={this.setKeyValue} />
- </div>
- );
- return rows;
- }
+ const noviceReqFields = ['author', 'creationDate', 'tags', '_curPage'];
+ return this.editableFields(key => key.indexOf('lastModified') !== -1 || (key[0] === key[0].toUpperCase() && !key.startsWith('acl')), noviceReqFields);
}
@undoBatch
@@ -278,11 +217,10 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
}
return true;
} else if (value[0] === '#') {
- const newVal = value + `:'${value}'`;
- doc[DataSym][value] = value;
- const tags = StrCast(doc.tags, ':');
- if (!tags.includes(`${value}:`)) {
- doc[DataSym].tags = `${tags + value + ':'}`;
+ const tags = StrListCast(doc.tags);
+ if (!tags.includes(value)) {
+ tags.push(value);
+ doc[DataSym].tags = tags.length ? new List<string>(tags) : undefined;
}
return true;
}
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index d13052f71..192a501f2 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -303,13 +303,13 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
}
}
case StyleProp.PointerEvents:
- const isInk = doc && StrCast(Doc.Layout(doc).layout).includes(InkingStroke.name);
+ const isInk = doc && StrCast(Doc.Layout(doc).layout).includes(InkingStroke.name) && !props?.LayoutTemplateString;
if (docProps?.DocumentView?.().ComponentView?.overridePointerEvents?.() !== undefined) return docProps?.DocumentView?.().ComponentView?.overridePointerEvents?.();
if (MainView.Instance._exploreMode || doc?.unrendered) return isInk ? 'visiblePainted' : 'all';
if (doc?.pointerEvents) return StrCast(doc.pointerEvents);
if (props?.contentPointerEvents) return StrCast(props.contentPointerEvents);
if (props?.pointerEvents?.() === 'none') return 'none';
- if (opacity() === 0 || doc?.isInkMask) return 'none';
+ if (opacity() === 0) return 'none';
if (props?.isDocumentActive?.()) return isInk ? 'visiblePainted' : 'all';
return undefined; // fixes problem with tree view elements getting pointer events when the tree view is not active
case StyleProp.Decorations:
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 4d000542c..bb1f788d4 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -481,7 +481,6 @@ export class CollectionDockingView extends CollectionSubView() {
Doc.RemoveDocFromList(dview, fieldKey, tab.DashDoc);
this.tabMap.delete(tab);
tab._disposers && Object.values(tab._disposers).forEach((disposer: any) => disposer?.());
- //tab.reactComponents?.forEach((ele: any) => ReactDOM.unmountComponentAtNode(ele));
this.stateChanged();
}
};
diff --git a/src/client/views/collections/CollectionTimeView.tsx b/src/client/views/collections/CollectionTimeView.tsx
index c3f77205a..3cdb460a3 100644
--- a/src/client/views/collections/CollectionTimeView.tsx
+++ b/src/client/views/collections/CollectionTimeView.tsx
@@ -202,7 +202,7 @@ export class CollectionTimeView extends CollectionSubView() {
this.childLayoutPairs.map(pair =>
this._allFacets
.filter(fieldKey => pair.layout[fieldKey] instanceof RichTextField || typeof pair.layout[fieldKey] === 'number' || typeof pair.layout[fieldKey] === 'boolean' || typeof pair.layout[fieldKey] === 'string')
- .filter(fieldKey => fieldKey[0] !== '_' && (fieldKey[0] !== '#' || fieldKey === '#') && (fieldKey === 'tags' || fieldKey[0] === toUpper(fieldKey)[0]))
+ .filter(fieldKey => fieldKey[0] !== '_' && (fieldKey === 'tags' || fieldKey[0] === toUpper(fieldKey)[0]))
.map(fieldKey => keySet.add(fieldKey))
);
Array.from(keySet).map(fieldKey => docItems.push({ description: ':' + fieldKey, event: () => (this.layoutDoc._pivotField = fieldKey), icon: 'compress-arrows-alt' }));
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx
index c1f3c5aa6..fee4705e6 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx
@@ -133,20 +133,15 @@ export function computePivotLayout(poolData: Map<string, PoolData>, pivotDoc: Do
let nonNumbers = 0;
const pivotFieldKey = toLabel(engineProps?.pivotField ?? pivotDoc._pivotField) || 'author';
childPairs.map(pair => {
- const lval =
- pivotFieldKey === '#' || pivotFieldKey === 'tags'
- ? Array.from(Object.keys(Doc.GetProto(pair.layout)))
- .filter(k => k.startsWith('#'))
- .map(k => k.substring(1))
- : Cast(pair.layout[pivotFieldKey], listSpec('string'), null);
+ const listValue = Cast(pair.layout[pivotFieldKey], listSpec('string'), null);
const num = toNumber(pair.layout[pivotFieldKey]);
if (num === undefined || Number.isNaN(num)) {
nonNumbers++;
}
const val = Field.toString(pair.layout[pivotFieldKey] as Field);
- if (lval) {
- lval.forEach((val, i) => {
+ if (listValue) {
+ listValue.forEach((val, i) => {
!pivotColumnGroups.get(val) && pivotColumnGroups.set(val, { docs: [], filters: [val], replicas: [] });
pivotColumnGroups.get(val)!.docs.push(pair.layout);
pivotColumnGroups.get(val)!.replicas.push(i.toString());
@@ -159,8 +154,8 @@ export function computePivotLayout(poolData: Map<string, PoolData>, pivotDoc: Do
docMap.set(pair.layout[Id], {
x: 0,
y: 0,
- zIndex: -99,
- width: 0,
+ zIndex: 0,
+ width: 0, // should make doc hidden in CollectionFreefromDocumentView
height: 0,
pair,
replica: '',
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 9cc732008..29bdc0e2d 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1158,7 +1158,10 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
@action
bringToFront = (doc: Doc, sendToBack?: boolean) => {
if (sendToBack) {
- doc.zIndex = 0;
+ const docs = this.childLayoutPairs.map(pair => pair.layout).slice();
+ docs.sort((doc1, doc2) => NumCast(doc1.zIndex) - NumCast(doc2.zIndex));
+ let zfirst = docs.length ? NumCast(docs[0].zIndex) : 0;
+ doc.zIndex = zfirst - 1;
} else if (doc.isInkMask) {
doc.zIndex = 5000;
} else {
@@ -1372,7 +1375,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
rotation: Cast(_rotation, 'number'),
color: Cast(color, 'string') ? StrCast(color) : this.props.styleProvider?.(childDoc, this.props, StyleProp.Color),
backgroundColor: Cast(backgroundColor, 'string') ? StrCast(backgroundColor) : this.getClusterColor(childDoc, this.props, StyleProp.BackgroundColor),
- opacity: this._keyframeEditing ? 1 : Cast(opacity, 'number') ?? this.props.styleProvider?.(childDoc, this.props, StyleProp.Opacity),
+ opacity: !_width ? 0 : this._keyframeEditing ? 1 : Cast(opacity, 'number') ?? this.props.styleProvider?.(childDoc, this.props, StyleProp.Opacity),
zIndex: Cast(zIndex, 'number'),
width: _width,
height: _height,
@@ -1756,6 +1759,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
return;
}
!Doc.noviceMode && Doc.UserDoc().defaultTextLayout && appearanceItems.push({ description: 'Reset default note style', event: () => (Doc.UserDoc().defaultTextLayout = undefined), icon: 'eye' });
+ appearanceItems.push({ description: (Doc.UserDoc().defaultToFlashcards ? 'Disable' : 'Enable') + ' Flashcard Notes', event: () => (Doc.UserDoc().defaultToFlashcards = !Doc.UserDoc().defaultToFlashcards), icon: 'eye' });
appearanceItems.push({
description: `${this.fitContentsToBox ? 'Make Zoomable' : 'Scale to Window'}`,
event: () => (this.Document._fitContentsToBox = !this.fitContentsToBox),
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 24b9f3b25..a8c8a0d2e 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -16,6 +16,8 @@ import { StyleProp } from '../StyleProvider';
import './CollectionFreeFormDocumentView.scss';
import { DocumentView, DocumentViewProps, OpenWhere } from './DocumentView';
import React = require('react');
+import { DocumentType } from '../../documents/DocumentTypes';
+import { InkingStroke } from '../InkingStroke';
export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps {
dataProvider?: (doc: Doc, replica: string) => { x: number; y: number; zIndex?: number; rotation?: number; color?: string; backgroundColor?: string; opacity?: number; highlight?: boolean; z: number; transition?: string } | undefined;
@@ -201,9 +203,10 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
PanelWidth: this.panelWidth,
PanelHeight: this.panelHeight,
};
+ const isInk = StrCast(this.layoutDoc.layout).includes(InkingStroke.name) && !this.props.LayoutTemplateString && !this.layoutDoc._isInkMask;
return (
<div
- className={'collectionFreeFormDocumentView-container'}
+ className="collectionFreeFormDocumentView-container"
style={{
width: this.panelWidth(),
height: this.panelHeight(),
@@ -211,7 +214,8 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
transformOrigin: '50% 50%',
transition: this.dataProvider?.transition ?? (this.props.dataTransition ? this.props.dataTransition : this.dataProvider ? this.dataProvider.transition : StrCast(this.layoutDoc.dataTransition)),
zIndex: this.ZInd,
- display: this.ZInd === -99 ? 'none' : undefined,
+ display: this.sizeProvider?.width ? undefined : 'none',
+ pointerEvents: isInk ? 'none' : undefined,
}}>
{this.props.renderCutoffProvider(this.props.Document) ? (
<div style={{ position: 'absolute', width: this.panelWidth(), height: this.panelHeight(), background: 'lightGreen' }} />
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 3bdd2bf6e..f1f5f7e10 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -870,7 +870,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
contentPointerEvents = () => (!this.disableClickScriptFunc && this.onClickHandler ? 'none' : this.pointerEvents);
@computed get contents() {
TraceMobx();
- const isInk = StrCast(this.layoutDoc.layout).includes(InkingStroke.name);
+ const isInk = StrCast(this.layoutDoc.layout).includes(InkingStroke.name) && !this.props.LayoutTemplateString;
return (
<div
className="documentView-contentsView"
diff --git a/src/client/views/nodes/WebBoxRenderer.js b/src/client/views/nodes/WebBoxRenderer.js
index 20554b858..eb8064780 100644
--- a/src/client/views/nodes/WebBoxRenderer.js
+++ b/src/client/views/nodes/WebBoxRenderer.js
@@ -42,6 +42,8 @@ var ForeignHtmlRenderer = function (styleSheets) {
url = CorsProxy(new URL(webUrl).origin + inurl);
} else if (!inurl.startsWith('http') && !inurl.startsWith('//')) {
url = CorsProxy(webUrl + '/' + inurl);
+ } else if (inurl.startsWith('https')) {
+ url = CorsProxy(inurl);
}
xhr.open('GET', url);
xhr.responseType = 'blob';
@@ -124,7 +126,7 @@ var ForeignHtmlRenderer = function (styleSheets) {
if (url === null) {
break;
}
- searchStartIndex = url.foundAtIndex + url.value.length;
+ searchStartIndex = url.foundAtIndex + url.value.length + 1;
if (mustEndWithQuote && url.value[url.value.length - 1] !== '"') continue;
const unquoted = removeQuotes(url.value);
if (!unquoted /* || (!unquoted.startsWith('http')&& !unquoted.startsWith("/") )*/ || unquoted === 'http://' || unquoted === 'https://') {
diff --git a/src/client/views/nodes/button/FontIconBox.tsx b/src/client/views/nodes/button/FontIconBox.tsx
index f04678d8b..26515da30 100644
--- a/src/client/views/nodes/button/FontIconBox.tsx
+++ b/src/client/views/nodes/button/FontIconBox.tsx
@@ -224,12 +224,12 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
</div>
<div
className="dropbox-background"
- onClick={e => {
+ onClick={action(e => {
e.stopPropagation();
this.rootDoc.dropDownOpen = false;
this.noTooltip = false;
Doc.UnBrushAllDocs();
- }}
+ })}
/>
</div>
) : null}
@@ -336,11 +336,11 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
style={{ backgroundColor: this.rootDoc.dropDownOpen ? Colors.MEDIUM_BLUE : backgroundColor, color: color, display: dropdown ? undefined : 'flex' }}
onClick={
dropdown
- ? () => {
+ ? action(() => {
this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen;
this.noTooltip = this.rootDoc.dropDownOpen;
Doc.UnBrushAllDocs();
- }
+ })
: undefined
}>
{dropdown ? null : <FontAwesomeIcon style={{ marginLeft: 5 }} className={`fontIconBox-icon-${this.type}`} icon={icon} color={color} />}
@@ -358,12 +358,12 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
</div>
<div
className="dropbox-background"
- onClick={e => {
+ onClick={action(e => {
e.stopPropagation();
this.rootDoc.dropDownOpen = false;
this.noTooltip = false;
Doc.UnBrushAllDocs();
- }}
+ })}
/>
</div>
) : null}
@@ -582,17 +582,19 @@ ScriptingGlobals.add(function setBackgroundColor(color?: string, checkResult?: b
} else if (selectedViews.length) {
if (checkResult) {
const selView = selectedViews.lastElement();
+ const fieldKey = selView.rootDoc.type === DocumentType.INK ? 'fillColor' : 'backgroundColor';
const layoutFrameNumber = Cast(selView.props.docViewPath().lastElement()?.rootDoc?._currentFrame, 'number'); // frame number that container is at which determines layout frame values
const contentFrameNumber = Cast(selView.rootDoc?._currentFrame, 'number', layoutFrameNumber ?? null); // frame number that content is at which determines what content is displayed
- return CollectionFreeFormDocumentView.getStringValues(selView?.rootDoc, contentFrameNumber).backgroundColor ?? 'transparent';
+ return CollectionFreeFormDocumentView.getStringValues(selView?.rootDoc, contentFrameNumber)[fieldKey] ?? 'transparent';
}
selectedViews.forEach(dv => {
+ const fieldKey = dv.rootDoc.type === DocumentType.INK ? 'fillColor' : 'backgroundColor';
const layoutFrameNumber = Cast(dv.props.docViewPath().lastElement()?.rootDoc?._currentFrame, 'number'); // frame number that container is at which determines layout frame values
const contentFrameNumber = Cast(dv.rootDoc?._currentFrame, 'number', layoutFrameNumber ?? null); // frame number that content is at which determines what content is displayed
if (contentFrameNumber !== undefined) {
- CollectionFreeFormDocumentView.setStringValues(contentFrameNumber, dv.rootDoc, { backgroundColor: color });
+ CollectionFreeFormDocumentView.setStringValues(contentFrameNumber, dv.rootDoc, { fieldKey: color });
} else {
- dv.rootDoc._backgroundColor = color;
+ dv.rootDoc['_' + fieldKey] = color;
}
});
} else {
diff --git a/src/client/views/nodes/formattedText/DashDocView.tsx b/src/client/views/nodes/formattedText/DashDocView.tsx
index 648c579d0..c05a30d1a 100644
--- a/src/client/views/nodes/formattedText/DashDocView.tsx
+++ b/src/client/views/nodes/formattedText/DashDocView.tsx
@@ -45,8 +45,7 @@ export class DashDocView {
);
}
destroy() {
- this.root.unmount();
- // ReactDOM.unmountComponentAtNode(this.dom);
+ setTimeout(this.root.unmount);
}
selectNode() {}
}
diff --git a/src/client/views/nodes/formattedText/DashFieldView.tsx b/src/client/views/nodes/formattedText/DashFieldView.tsx
index 72e8aedac..bf6fa2ec6 100644
--- a/src/client/views/nodes/formattedText/DashFieldView.tsx
+++ b/src/client/views/nodes/formattedText/DashFieldView.tsx
@@ -64,7 +64,11 @@ export class DashFieldView {
);
}
destroy() {
- this.root.unmount();
+ setTimeout(() => {
+ try {
+ this.root.unmount();
+ } catch {}
+ });
}
deselectNode() {
this.dom.classList.remove('ProseMirror-selectednode');
@@ -241,7 +245,7 @@ export class DashFieldViewInternal extends React.Component<IDashFieldViewInterna
}
list.map(c => c.heading).indexOf(this._fieldKey) === -1 && list.push(new SchemaHeaderField(this._fieldKey, '#f1efeb'));
list.map(c => c.heading).indexOf('text') === -1 && list.push(new SchemaHeaderField('text', '#f1efeb'));
- alias._pivotField = this._fieldKey.startsWith('#') ? '#' : this._fieldKey;
+ alias._pivotField = this._fieldKey.startsWith('#') ? 'tags' : this._fieldKey;
this.props.tbox.props.addDocTab(alias, OpenWhere.addRight);
}
};
diff --git a/src/client/views/nodes/formattedText/EquationView.tsx b/src/client/views/nodes/formattedText/EquationView.tsx
index 714ae458c..5e62d94c2 100644
--- a/src/client/views/nodes/formattedText/EquationView.tsx
+++ b/src/client/views/nodes/formattedText/EquationView.tsx
@@ -33,7 +33,6 @@ export class EquationView {
setEditor = (editor?: EquationEditor) => (this._editor = editor);
destroy() {
this.root.unmount();
- // ReactDOM.unmountComponentAtNode(this.dom);
}
setSelection() {
this._editor?.mathField.focus();
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index eb28ffbd7..b5aa34a29 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -12,7 +12,7 @@ import { Fragment, Mark, Node, Slice } from 'prosemirror-model';
import { EditorState, NodeSelection, Plugin, TextSelection, Transaction } from 'prosemirror-state';
import { EditorView } from 'prosemirror-view';
import { DateField } from '../../../../fields/DateField';
-import { AclAdmin, AclAugment, AclEdit, AclSelfEdit, CssSym, Doc, DocListCast, Field, ForceServerWrite, HeightSym, Opt, UpdatingFromServer, WidthSym } from '../../../../fields/Doc';
+import { AclAdmin, AclAugment, AclEdit, AclSelfEdit, CssSym, Doc, DocListCast, Field, ForceServerWrite, HeightSym, Opt, StrListCast, UpdatingFromServer, WidthSym } from '../../../../fields/Doc';
import { Id } from '../../../../fields/FieldSymbols';
import { InkTool } from '../../../../fields/InkField';
import { PrefetchProxy } from '../../../../fields/Proxy';
@@ -69,6 +69,7 @@ import { SummaryView } from './SummaryView';
import applyDevTools = require('prosemirror-dev-tools');
import React = require('react');
import { RTFMarkup } from '../../../util/RTFMarkup';
+import { List } from '../../../../fields/List';
const translateGoogleApi = require('translate-google-api');
export const GoogleRef = 'googleDocId';
type PullHandler = (exportState: Opt<GoogleApiClientUtils.Docs.ImportResult>, dataDoc: Doc) => void;
@@ -155,7 +156,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
}
@computed get config() {
this._keymap = buildKeymap(schema, this.props);
- this._rules = new RichTextRules(this.props.Document, this);
+ this._rules = new RichTextRules(this.rootDoc, this);
return {
schema,
plugins: [
@@ -313,11 +314,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
accumTags.push(node.attrs.fieldKey);
}
});
- 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 => (dataDoc[r] = undefined));
- added.forEach(a => (dataDoc[a] = a));
+ dataDoc.tags = accumTags.length ? new List<string>(Array.from(new Set<string>(accumTags))) : undefined;
let unchanged = true;
if (this._applyingChange !== this.fieldKey && removeSelection(json) !== removeSelection(curProto?.Data)) {
@@ -803,6 +800,11 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
const uicontrols: ContextMenuProps[] = [];
uicontrols.push({ description: !this.Document._noSidebar ? 'Hide Sidebar Handle' : 'Show Sidebar Handle', event: () => (this.layoutDoc._noSidebar = !this.layoutDoc._noSidebar), icon: !this.Document._noSidebar ? 'eye-slash' : 'eye' });
+ uicontrols.push({
+ description: (this.Document._showAltContentUI ? 'Hide' : 'Show') + ' Alt Content UI',
+ event: () => (this.layoutDoc._showAltContentUI = !this.layoutDoc._showAltContentUI),
+ icon: !this.Document._showAltContentUI ? 'eye-slash' : 'eye',
+ });
uicontrols.push({ description: 'Show Highlights...', noexpand: true, subitems: highlighting, icon: 'hand-point-right' });
!Doc.noviceMode &&
uicontrols.push({
@@ -858,7 +860,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
event: () => (this.layoutDoc._singleLine = !this.layoutDoc._singleLine),
icon: !this.Document._singleLine ? 'grip-lines' : 'bars',
});
- optionItems.push({ description: `${this.Document._autoHeight ? 'Lock' : 'Auto'} Height`, event: () => (this.layoutDoc._autoHeight = !this.layoutDoc._autoHeight), icon: this.Document._autoHeight ? 'lock' : 'unlock' });
+ !Doc.noviceMode && optionItems.push({ description: `${this.Document._autoHeight ? 'Lock' : 'Auto'} Height`, event: () => (this.layoutDoc._autoHeight = !this.layoutDoc._autoHeight), icon: this.Document._autoHeight ? 'lock' : 'unlock' });
optionItems.push({ description: `show markdown options`, event: RTFMarkup.Instance.open, icon: 'text' });
!options && cm.addItem({ description: 'Options...', subitems: optionItems, icon: 'eye' });
this._downX = this._downY = Number.NaN;
@@ -1934,13 +1936,19 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
</div>
);
}
+ cycleAlternateText = () => {
+ if (this.layoutDoc._showAltContentUI) {
+ const usePath = this.rootDoc[`${this.props.fieldKey}-usePath`];
+ this.rootDoc[`_${this.props.fieldKey}-usePath`] = usePath === undefined ? 'alternate' : usePath === 'alternate' ? 'alternate:hover' : undefined;
+ }
+ };
@computed get overlayAlternateIcon() {
const usePath = this.rootDoc[`${this.props.fieldKey}-usePath`];
return (
<Tooltip
title={
<div className="dash-tooltip">
- toggle between
+ toggle (%/) between
<span style={{ color: usePath === undefined ? 'black' : undefined }}>
<em> primary, </em>
</span>
@@ -1955,9 +1963,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
}>
<div
className="formattedTextBox-alternateButton"
- onPointerDown={e =>
- setupMoveUpEvents(e.target, e, returnFalse, emptyFunction, e => (this.rootDoc[`_${this.props.fieldKey}-usePath`] = usePath === undefined ? 'alternate' : usePath === 'alternate' ? 'alternate:hover' : undefined))
- }
+ onPointerDown={e => setupMoveUpEvents(e.target, e, returnFalse, emptyFunction, e => this.cycleAlternateText())}
style={{
display: this.props.isContentActive() && !SnappingManager.GetIsDragging() ? 'flex' : 'none',
background: usePath === undefined ? 'white' : usePath === 'alternate' ? 'black' : 'gray',
@@ -2023,7 +2029,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
...styleFromLayoutString,
}}>
<div
- className={`formattedTextBox-cont`}
+ className="formattedTextBox-cont"
ref={this._ref}
style={{
overflow: this.autoHeight && this.props.CollectionFreeFormDocumentView?.() ? 'hidden' : undefined, //x this breaks viewing an autoHeight doc in its own tab, or in the lightbox
@@ -2065,7 +2071,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
{this.noSidebar || this.props.dontSelectOnLoad || !this.SidebarShown || this.sidebarWidthPercent === '0%' ? null : this.sidebarCollection}
{this.noSidebar || this.Document._noSidebar || this.props.dontSelectOnLoad || this.Document._singleLine ? null : this.sidebarHandle}
{this.audioHandle}
- {this.props.dontScale ? null : this.overlayAlternateIcon}
+ {this.layoutDoc._showAltContentUI ? this.overlayAlternateIcon : null}
</div>
</div>
);
diff --git a/src/client/views/nodes/formattedText/RichTextRules.ts b/src/client/views/nodes/formattedText/RichTextRules.ts
index cc19d12bd..cad56b14b 100644
--- a/src/client/views/nodes/formattedText/RichTextRules.ts
+++ b/src/client/views/nodes/formattedText/RichTextRules.ts
@@ -1,7 +1,8 @@
import { ellipsis, emDash, InputRule, smartQuotes, textblockTypeInputRule } from 'prosemirror-inputrules';
import { NodeSelection, TextSelection } from 'prosemirror-state';
-import { DataSym, Doc } from '../../../../fields/Doc';
+import { DataSym, Doc, StrListCast } from '../../../../fields/Doc';
import { Id } from '../../../../fields/FieldSymbols';
+import { List } from '../../../../fields/List';
import { ComputedField } from '../../../../fields/ScriptField';
import { NumCast, StrCast } from '../../../../fields/Types';
import { normalizeEmail } from '../../../../fields/util';
@@ -214,8 +215,8 @@ export class RichTextRules {
}),
// stop using active style
- new InputRule(new RegExp(/%alt$/), (state, match, start, end) => {
- setTimeout(() => (this.Document[this.TextBox.props.fieldKey + '-usePath'] = this.Document[this.TextBox.props.fieldKey + '-usePath'] ? undefined : 'alternate'));
+ new InputRule(new RegExp(/%\//), (state, match, start, end) => {
+ setTimeout(this.TextBox.cycleAlternateText);
return state.tr.deleteRange(start, end);
}),
@@ -324,10 +325,11 @@ export class RichTextRules {
new InputRule(new RegExp(/#([a-zA-Z_\-]+[a-zA-Z_\-0-9]*)\s$/), (state, match, start, end) => {
const tag = match[1];
if (!tag) return state.tr;
- this.Document[DataSym]['#' + tag] = '#' + tag;
- const tags = StrCast(this.Document[DataSym].tags, ':');
- if (!tags.includes(`#${tag}:`)) {
- this.Document[DataSym].tags = `${tags + '#' + tag + ':'}`;
+ //this.Document[DataSym]['#' + tag] = '#' + tag;
+ const tags = StrListCast(this.Document[DataSym].tags);
+ if (!tags.includes(tag)) {
+ tags.push(tag);
+ this.Document[DataSym].tags = new List<string>(tags);
}
const fieldView = state.schema.nodes.dashField.create({ fieldKey: '#' + tag });
return state.tr
diff --git a/src/client/views/nodes/formattedText/SummaryView.tsx b/src/client/views/nodes/formattedText/SummaryView.tsx
index 4e75d374c..3355e4529 100644
--- a/src/client/views/nodes/formattedText/SummaryView.tsx
+++ b/src/client/views/nodes/formattedText/SummaryView.tsx
@@ -43,7 +43,6 @@ export class SummaryView {
className = (visible: boolean) => 'formattedTextBox-summarizer' + (visible ? '' : '-collapsed');
destroy() {
this.root.unmount();
- // ReactDOM.unmountComponentAtNode(this.dom);
}
selectNode() {}