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.scss6
-rw-r--r--src/client/views/nodes/DocumentView.tsx123
-rw-r--r--src/client/views/nodes/FilterBox.tsx2
-rw-r--r--src/client/views/nodes/FunctionPlotBox.tsx76
-rw-r--r--src/client/views/nodes/LinkAnchorBox.tsx2
-rw-r--r--src/client/views/nodes/LinkDocPreview.tsx21
-rw-r--r--src/client/views/nodes/MapBox/MapBoxInfoWindow.tsx5
-rw-r--r--src/client/views/nodes/button/FontIconBox.tsx9
-rw-r--r--src/client/views/nodes/formattedText/DashFieldView.tsx14
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.tsx137
-rw-r--r--src/client/views/nodes/formattedText/RichTextMenu.tsx13
12 files changed, 243 insertions, 167 deletions
diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx
index 5939d1680..a37de7f69 100644
--- a/src/client/views/nodes/DocumentLinksButton.tsx
+++ b/src/client/views/nodes/DocumentLinksButton.tsx
@@ -307,7 +307,7 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
<div
className="documentLinksButton-wrapper"
style={{
- transform: this.props.InMenu ? undefined : `scale(${this.props.scaling})`,
+ transform: `scale(${this.props.scaling?.() || 1})`,
}}>
{(this.props.InMenu && (DocumentLinksButton.StartLink || this.props.StartLink)) || (!DocumentLinksButton.LinkEditorDocView && !this.props.InMenu) ? (
<Tooltip title={<div className="dash-tooltip">{title}</div>}>{this.linkButtonInner}</Tooltip>
diff --git a/src/client/views/nodes/DocumentView.scss b/src/client/views/nodes/DocumentView.scss
index c02692bfb..6ea697a2f 100644
--- a/src/client/views/nodes/DocumentView.scss
+++ b/src/client/views/nodes/DocumentView.scss
@@ -65,11 +65,13 @@
width: 25px;
height: 25;
position: absolute;
- top: 10px;
- left: 10px;
+ top: 0;
+ left: 50%;
border-radius: 25px;
background: white;
opacity: 0.3;
+ pointer-events: all;
+ cursor: default;
svg {
width: 90% !important;
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index edaa40bad..f87581875 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -10,7 +10,7 @@ import { List } from '../../../fields/List';
import { ObjectField } from '../../../fields/ObjectField';
import { listSpec } from '../../../fields/Schema';
import { ScriptField } from '../../../fields/ScriptField';
-import { BoolCast, Cast, ImageCast, NumCast, ScriptCast, StrCast } from '../../../fields/Types';
+import { BoolCast, Cast, DocCast, ImageCast, NumCast, ScriptCast, StrCast } from '../../../fields/Types';
import { AudioField } from '../../../fields/URLField';
import { GetEffectiveAcl, SharingPermissions, TraceMobx } from '../../../fields/util';
import { MobileInterface } from '../../../mobile/MobileInterface';
@@ -52,6 +52,8 @@ import { RadialMenu } from './RadialMenu';
import { ScriptingBox } from './ScriptingBox';
import { PresBox } from './trails/PresBox';
import React = require('react');
+import { DictationManager } from '../../util/DictationManager';
+import { Tooltip } from '@material-ui/core';
const { Howl } = require('howler');
interface Window {
@@ -156,6 +158,7 @@ export interface DocumentViewSharedProps {
scriptContext?: any; // can be assigned anything and will be passed as 'scriptContext' to any OnClick script that executes on this document
createNewFilterDoc?: () => void;
updateFilterDoc?: (doc: Doc) => void;
+ dontHideOnDrag?: boolean;
}
// these props are specific to DocuentViews
@@ -203,7 +206,6 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
public static SelectAfterContextMenu = true; // whether a document should be selected after it's contextmenu is triggered.
_animateScaleTime = 300; // milliseconds;
@observable _animateScalingTo = 0;
- @observable _mediaState = 0;
@observable _pendingDoubleClick = false;
private _disposers: { [name: string]: IReactionDisposer } = {};
private _downX: number = 0;
@@ -502,9 +504,16 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
dragData.treeViewDoc = this.props.treeViewDoc;
dragData.removeDocument = this.props.removeDocument;
dragData.moveDocument = this.props.moveDocument;
+ //dragData.dimSource :
+ // dragEffects field, set dim
+ // add kv pairs to a doc, swap properties with the node while dragging, and then swap when dropping
+ // add a dragEffects prop to DocumentView as a function that sets up. Each view has its own prop, when you start dragging:
+ // in Draganager, figure out which doc(s) you're dragging and change what opacity function returns
const ffview = this.props.CollectionFreeFormDocumentView?.().props.CollectionFreeFormView;
ffview && runInAction(() => (ffview.ChildDrag = this.props.DocumentView()));
- DragManager.StartDocumentDrag([this._mainCont.current], dragData, x, y, { hideSource: hideSource || (!dropAction && !this.layoutDoc.onDragStart) }, () => setTimeout(action(() => ffview && (ffview.ChildDrag = undefined)))); // this needs to happen after the drop event is processed.
+ DragManager.StartDocumentDrag([this._mainCont.current], dragData, x, y, { hideSource: hideSource || (!dropAction && !this.layoutDoc.onDragStart && !this.props.dontHideOnDrag) }, () =>
+ setTimeout(action(() => ffview && (ffview.ChildDrag = undefined)))
+ ); // this needs to happen after the drop event is processed.
ffview?.setupDragLines(false);
}
}
@@ -869,7 +878,6 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
!appearance && cm.addItem({ description: 'UI Controls...', subitems: appearanceItems, icon: 'compass' });
if (!Doc.IsSystem(this.rootDoc) && this.rootDoc._viewType !== CollectionViewType.Docking && this.props.ContainingCollectionDoc?._viewType !== CollectionViewType.Tree) {
- !Doc.noviceMode && appearanceItems.splice(0, 0, { description: `${!this.layoutDoc._showAudio ? 'Show' : 'Hide'} Audio Button`, event: action(() => (this.layoutDoc._showAudio = !this.layoutDoc._showAudio)), icon: 'microphone' });
const existingOnClick = cm.findByDescription('OnClick...');
const onClicks: ContextMenuProps[] = existingOnClick && 'subitems' in existingOnClick ? existingOnClick.subitems : [];
@@ -997,16 +1005,21 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
linkButtonInverseScaling = () => (this.props.NativeDimScaling?.() || 1) * this.props.DocumentView().screenToLocalTransform().Scale;
@computed get contents() {
TraceMobx();
- const audioView = !this.layoutDoc._showAudio ? null : (
- <div className="documentView-audioBackground" onPointerDown={this.recordAudioAnnotation} onPointerEnter={this.onPointerEnter}>
- <FontAwesomeIcon
- className="documentView-audioFont"
- style={{ color: [DocListCast(this.dataDoc[this.LayoutFieldKey + '-audioAnnotations']).length ? 'blue' : 'gray', 'green', 'red'][this._mediaState] }}
- icon={!DocListCast(this.dataDoc[this.LayoutFieldKey + '-audioAnnotations']).length ? 'microphone' : 'file-audio'}
- size="sm"
- />
- </div>
- );
+ const audioAnnosCount = Cast(this.dataDoc[this.LayoutFieldKey + '-audioAnnotations'], listSpec(AudioField), null)?.length;
+ const audioTextAnnos = Cast(this.dataDoc[this.LayoutFieldKey + '-audioAnnotations-text'], listSpec('string'), null);
+ const audioView =
+ (!this.props.isSelected() && !this._isHovering && this.dataDoc.audioAnnoState !== 2) || this.props.renderDepth === -1 || SnappingManager.GetIsDragging() || (!audioAnnosCount && !this.dataDoc.audioAnnoState) ? null : (
+ <Tooltip title={<div>{audioTextAnnos?.lastElement()}</div>}>
+ <div className="documentView-audioBackground" onPointerDown={this.playAnnotation}>
+ <FontAwesomeIcon
+ className="documentView-audioFont"
+ style={{ color: [audioAnnosCount ? 'blue' : 'gray', 'green', 'red'][NumCast(this.dataDoc.audioAnnoState)] }}
+ icon={!audioAnnosCount ? 'microphone' : 'file-audio'}
+ size="sm"
+ />
+ </div>
+ </Tooltip>
+ );
return (
<div
@@ -1062,7 +1075,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
<DocumentLinksButton
View={this.props.DocumentView()}
scaling={this.linkButtonInverseScaling}
- Offset={[this.topMost ? 0 : !this.props.isSelected() ? -15 : -30, undefined, undefined, this.topMost ? 10 : !this.props.isSelected() ? -15 : -30]}
+ Offset={[this.topMost ? 0 : !this.props.isSelected() ? -15 : -36, undefined, undefined, this.topMost ? 10 : !this.props.isSelected() ? -15 : -28]}
/>
)}
{audioView}
@@ -1140,58 +1153,72 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
}
@action
- onPointerEnter = () => {
+ playAnnotation = () => {
const self = this;
- const audioAnnos = DocListCast(this.dataDoc[this.LayoutFieldKey + '-audioAnnotations']);
- if (audioAnnos && audioAnnos.length && this._mediaState === 0) {
- const anno = audioAnnos[Math.floor(Math.random() * audioAnnos.length)];
- anno.data instanceof AudioField &&
- new Howl({
- src: [anno.data.url.href],
- format: ['mp3'],
- autoplay: true,
- loop: false,
- volume: 0.5,
- onend: function () {
- runInAction(() => (self._mediaState = 0));
- },
- });
- this._mediaState = 1;
+ const audioAnnos = Cast(this.dataDoc[this.LayoutFieldKey + '-audioAnnotations'], listSpec(AudioField), null);
+ const anno = audioAnnos.lastElement();
+ if (anno instanceof AudioField && this.dataDoc.audioAnnoState === 0) {
+ new Howl({
+ src: [anno.url.href],
+ format: ['mp3'],
+ autoplay: true,
+ loop: false,
+ volume: 0.5,
+ onend: function () {
+ runInAction(() => {
+ self.dataDoc.audioAnnoState = 0;
+ });
+ },
+ });
+ this.dataDoc.audioAnnoState = 1;
}
};
- recordAudioAnnotation = () => {
+
+ static recordAudioAnnotation(dataDoc: Doc, field: string, onEnd?: () => void) {
let gumStream: any;
let recorder: any;
- const self = this;
navigator.mediaDevices
.getUserMedia({
audio: true,
})
.then(function (stream) {
+ let audioTextAnnos = Cast(dataDoc[field + '-audioAnnotations-text'], listSpec('string'), null);
+ if (audioTextAnnos) audioTextAnnos.push('');
+ else audioTextAnnos = dataDoc[field + '-audioAnnotations-text'] = new List<string>(['']);
+ DictationManager.Controls.listen({
+ interimHandler: value => (audioTextAnnos[audioTextAnnos.length - 1] = value),
+ continuous: { indefinite: false },
+ }).then(results => {
+ if (results && [DictationManager.Controls.Infringed].includes(results)) {
+ DictationManager.Controls.stop();
+ }
+ onEnd?.();
+ });
+
gumStream = stream;
recorder = new MediaRecorder(stream);
recorder.ondataavailable = async (e: any) => {
const [{ result }] = await Networking.UploadFilesToServer(e.data);
if (!(result instanceof Error)) {
- const audioDoc = Docs.Create.AudioDocument(result.accessPaths.agnostic.client, { title: 'audio test', _width: 200, _height: 32 });
- audioDoc.treeViewExpandedView = 'layout';
- const audioAnnos = Cast(self.dataDoc[self.LayoutFieldKey + '-audioAnnotations'], listSpec(Doc));
+ const audioField = new AudioField(result.accessPaths.agnostic.client);
+ const audioAnnos = Cast(dataDoc[field + '-audioAnnotations'], listSpec(AudioField), null);
if (audioAnnos === undefined) {
- self.dataDoc[self.LayoutFieldKey + '-audioAnnotations'] = new List([audioDoc]);
+ dataDoc[field + '-audioAnnotations'] = new List([audioField]);
} else {
- audioAnnos.push(audioDoc);
+ audioAnnos.push(audioField);
}
}
};
- runInAction(() => (self._mediaState = 2));
+ runInAction(() => (dataDoc.audioAnnoState = 2));
recorder.start();
setTimeout(() => {
recorder.stop();
- runInAction(() => (self._mediaState = 0));
+ DictationManager.Controls.stop(false);
+ runInAction(() => (dataDoc.audioAnnoState = 0));
gumStream.getAudioTracks()[0].stop();
}, 5000);
});
- };
+ }
captionStyleProvider = (doc: Opt<Doc>, props: Opt<DocumentViewInternalProps>, property: string) => this.props?.styleProvider?.(doc, props, property + ':caption');
@computed get innards() {
@@ -1290,6 +1317,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
isHovering = () => this._isHovering;
@observable _isHovering = false;
@observable _: string = '';
+ _hoverTimeout: any = undefined;
@computed get renderDoc() {
TraceMobx();
const thumb = ImageCast(this.layoutDoc['thumb-frozen'], ImageCast(this.layoutDoc.thumb))?.url?.href.replace('.png', '_m.png');
@@ -1300,8 +1328,17 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
<div
className={`documentView-node${this.topMost ? '-topmost' : ''}`}
id={this.props.Document[Id]}
- onPointerEnter={action(() => (this._isHovering = true))}
- onPointerLeave={action(() => (this._isHovering = false))}
+ onPointerEnter={action(() => {
+ clearTimeout(this._hoverTimeout);
+ this._isHovering = true;
+ })}
+ onPointerLeave={action(() => {
+ clearTimeout(this._hoverTimeout);
+ this._hoverTimeout = setTimeout(
+ action(() => (this._isHovering = false)),
+ 500
+ );
+ })}
style={{
background: isButton || thumb ? undefined : this.backgroundColor,
opacity: this.opacity,
diff --git a/src/client/views/nodes/FilterBox.tsx b/src/client/views/nodes/FilterBox.tsx
index ff04a293c..dc3fc0396 100644
--- a/src/client/views/nodes/FilterBox.tsx
+++ b/src/client/views/nodes/FilterBox.tsx
@@ -116,7 +116,7 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps>() {
@observable _loaded = false;
componentDidMount() {
reaction(
- () => DocListCastAsync(this.layoutDoc.data),
+ () => DocListCastAsync(this.layoutDoc[this.fieldKey]),
async activeTabsAsync => {
const activeTabs = await activeTabsAsync;
activeTabs && (await SearchBox.foreachRecursiveDocAsync(activeTabs, emptyFunction));
diff --git a/src/client/views/nodes/FunctionPlotBox.tsx b/src/client/views/nodes/FunctionPlotBox.tsx
index 3ab0a3ff2..15d0f88f6 100644
--- a/src/client/views/nodes/FunctionPlotBox.tsx
+++ b/src/client/views/nodes/FunctionPlotBox.tsx
@@ -1,4 +1,4 @@
-import functionPlot from "function-plot";
+import functionPlot from 'function-plot';
import { action, computed, reaction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
@@ -12,7 +12,6 @@ import { Docs } from '../../documents/Documents';
import { ViewBoxBaseComponent } from '../DocComponent';
import { FieldView, FieldViewProps } from './FieldView';
-
const EquationSchema = createSchema({});
type EquationDocument = makeInterface<[typeof EquationSchema, typeof documentSchema]>;
@@ -20,74 +19,83 @@ const EquationDocument = makeInterface(EquationSchema, documentSchema);
@observer
export class FunctionPlotBox extends ViewBoxBaseComponent<FieldViewProps>() {
- public static LayoutString(fieldKey: string) { return FieldView.LayoutString(FunctionPlotBox, fieldKey); }
+ public static LayoutString(fieldKey: string) {
+ return FieldView.LayoutString(FunctionPlotBox, fieldKey);
+ }
public static GraphCount = 0;
_plot: any;
- _plotId = "";
+ _plotId = '';
_plotEle: any;
constructor(props: any) {
super(props);
- this._plotId = "graph" + FunctionPlotBox.GraphCount++;
+ this._plotId = 'graph' + FunctionPlotBox.GraphCount++;
}
componentDidMount() {
this.props.setContentView?.(this);
- reaction(() => [DocListCast(this.dataDoc.data).lastElement()?.text, this.layoutDoc.width, this.layoutDoc.height, this.dataDoc.xRange, this.dataDoc.yRange],
- () => this.createGraph());
+ reaction(
+ () => [DocListCast(this.dataDoc[this.fieldKey]).lastElement()?.text, this.layoutDoc.width, this.layoutDoc.height, this.dataDoc.xRange, this.dataDoc.yRange],
+ () => this.createGraph()
+ );
}
getAnchor = () => {
const anchor = Docs.Create.TextanchorDocument({ annotationOn: this.rootDoc });
anchor.xRange = new List<number>(Array.from(this._plot.options.xAxis.domain));
anchor.yRange = new List<number>(Array.from(this._plot.options.yAxis.domain));
return anchor;
- }
+ };
@action
scrollFocus = (doc: Doc, smooth: boolean) => {
- this.dataDoc.xRange = new List<number>(Array.from(Cast(doc.xRange, listSpec("number"), Cast(this.dataDoc.xRange, listSpec("number"), [-10, 10]))));
- this.dataDoc.yRange = new List<number>(Array.from(Cast(doc.yRange, listSpec("number"), Cast(this.dataDoc.xRange, listSpec("number"), [-1, 9]))));
+ this.dataDoc.xRange = new List<number>(Array.from(Cast(doc.xRange, listSpec('number'), Cast(this.dataDoc.xRange, listSpec('number'), [-10, 10]))));
+ this.dataDoc.yRange = new List<number>(Array.from(Cast(doc.yRange, listSpec('number'), Cast(this.dataDoc.xRange, listSpec('number'), [-1, 9]))));
return 0;
- }
+ };
createGraph = (ele?: HTMLDivElement) => {
this._plotEle = ele || this._plotEle;
const width = this.props.PanelWidth();
const height = this.props.PanelHeight();
- const fn = StrCast(DocListCast(this.dataDoc.data).lastElement()?.text, "x^2").replace(/\\frac\{(.*)\}\{(.*)\}/, "($1/$2)");
+ const fn = StrCast(DocListCast(this.dataDoc.data).lastElement()?.text, 'x^2').replace(/\\frac\{(.*)\}\{(.*)\}/, '($1/$2)');
try {
this._plot = functionPlot({
- target: "#" + this._plotEle.id,
+ target: '#' + this._plotEle.id,
width,
height,
- xAxis: { domain: Cast(this.dataDoc.xRange, listSpec("number"), [-10, 10]) },
- yAxis: { domain: Cast(this.dataDoc.xRange, listSpec("number"), [-1, 9]) },
+ xAxis: { domain: Cast(this.dataDoc.xRange, listSpec('number'), [-10, 10]) },
+ yAxis: { domain: Cast(this.dataDoc.xRange, listSpec('number'), [-1, 9]) },
grid: true,
data: [
{
fn,
// derivative: { fn: "2 * x", updateOnMouseMove: true }
- }
- ]
+ },
+ ],
});
} catch (e) {
console.log(e);
}
- }
+ };
@computed get theGraph() {
- return <div id={`${this._plotId}`} ref={r => r && this.createGraph(r)} style={{ position: "absolute", width: "100%", height: "100%" }}
- onPointerDown={e => e.stopPropagation()} />;
+ return <div id={`${this._plotId}`} ref={r => r && this.createGraph(r)} style={{ position: 'absolute', width: '100%', height: '100%' }} onPointerDown={e => e.stopPropagation()} />;
}
render() {
TraceMobx();
- return (<div
- style={{
- pointerEvents: !this.isContentActive() ? "all" : undefined,
- width: this.props.PanelWidth(),
- height: this.props.PanelHeight()
- }}
- >
- {this.theGraph}
- <div style={{
- display: this.props.isSelected() ? "none" : undefined, position: "absolute", width: "100%", height: "100%",
- pointerEvents: "all"
- }} />
- </div>);
+ return (
+ <div
+ style={{
+ pointerEvents: !this.isContentActive() ? 'all' : undefined,
+ width: this.props.PanelWidth(),
+ height: this.props.PanelHeight(),
+ }}>
+ {this.theGraph}
+ <div
+ style={{
+ display: this.props.isSelected() ? 'none' : undefined,
+ position: 'absolute',
+ width: '100%',
+ height: '100%',
+ pointerEvents: 'all',
+ }}
+ />
+ </div>
+ );
}
-} \ No newline at end of file
+}
diff --git a/src/client/views/nodes/LinkAnchorBox.tsx b/src/client/views/nodes/LinkAnchorBox.tsx
index 85a8622ec..5102eae51 100644
--- a/src/client/views/nodes/LinkAnchorBox.tsx
+++ b/src/client/views/nodes/LinkAnchorBox.tsx
@@ -136,7 +136,7 @@ export class LinkAnchorBox extends ViewBoxBaseComponent<FieldViewProps>() {
return (
<div
className={`linkAnchorBox-cont${small ? '-small' : ''}`}
- onPointerLeave={LinkDocPreview.Clear}
+ //onPointerLeave={} //LinkDocPreview.Clear}
onPointerEnter={e =>
LinkDocPreview.SetLinkInfo({
docProps: this.props,
diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx
index a12564839..93ca22d5d 100644
--- a/src/client/views/nodes/LinkDocPreview.tsx
+++ b/src/client/views/nodes/LinkDocPreview.tsx
@@ -5,7 +5,7 @@ import { observer } from 'mobx-react';
import wiki from 'wikijs';
import { Doc, DocCastAsync, DocListCast, HeightSym, Opt, WidthSym } from '../../../fields/Doc';
import { Cast, NumCast, StrCast } from '../../../fields/Types';
-import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnNone, setupMoveUpEvents } from '../../../Utils';
+import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnEmptyString, returnFalse, returnNone, setupMoveUpEvents } from '../../../Utils';
import { DocServer } from '../../DocServer';
import { Docs, DocUtils } from '../../documents/Documents';
import { DocumentType } from '../../documents/DocumentTypes';
@@ -17,6 +17,7 @@ import { undoBatch } from '../../util/UndoManager';
import { DocumentView, DocumentViewSharedProps } from './DocumentView';
import './LinkDocPreview.scss';
import React = require('react');
+import { LinkEditor } from '../linking/LinkEditor';
interface LinkDocPreviewProps {
linkDoc?: Doc;
@@ -118,13 +119,15 @@ export class LinkDocPreview extends React.Component<LinkDocPreviewProps> {
}
return undefined;
}
- deleteLink = (e: React.PointerEvent) => {
+ @observable _showEditor = false;
+ editLink = (e: React.PointerEvent): void => {
+ LinkManager.currentLink = this.props.linkDoc;
setupMoveUpEvents(
this,
e,
returnFalse,
emptyFunction,
- undoBatch(() => this._linkDoc && LinkManager.Instance.deleteLink(this._linkDoc))
+ action(() => (this._showEditor = !this._showEditor))
);
};
nextHref = (e: React.PointerEvent) => {
@@ -183,9 +186,9 @@ export class LinkDocPreview extends React.Component<LinkDocPreviewProps> {
</div>
</Tooltip>
- <Tooltip title={<div className="dash-tooltip">Delete Link</div>} placement="top">
- <div className="linkDocPreview-button" onPointerDown={this.deleteLink}>
- <FontAwesomeIcon className="linkDocPreview-fa-icon" icon="trash" color="white" size="sm" />
+ <Tooltip title={<div className="dash-tooltip">Edit Link</div>} placement="top">
+ <div className="linkDocPreview-button" onPointerDown={this.editLink}>
+ <FontAwesomeIcon className="linkDocPreview-fa-icon" icon="edit" color="white" size="sm" />
</div>
</Tooltip>
</div>
@@ -236,6 +239,7 @@ export class LinkDocPreview extends React.Component<LinkDocPreviewProps> {
isDocumentActive={returnFalse}
isContentActive={returnFalse}
addDocument={returnFalse}
+ showTitle={returnEmptyString}
removeDocument={returnFalse}
addDocTab={returnFalse}
pinToPres={returnFalse}
@@ -270,8 +274,9 @@ export class LinkDocPreview extends React.Component<LinkDocPreviewProps> {
className="linkDocPreview"
ref={this._linkDocRef}
onPointerDown={this.followLinkPointerDown}
- style={{ left: this.props.location[0], top: this.props.location[1], width: this.width() + borders, height: this.height() + borders + (this.props.showHeader ? 37 : 0) }}>
- {this.docPreview}
+ style={{ left: this.props.location[0], top: this.props.location[1], width: this._showEditor ? 'auto' : this.width() + borders, height: this._showEditor ? 'max-content' : this.height() + borders + (this.props.showHeader ? 37 : 0) }}>
+ {this._showEditor ? null : this.docPreview}
+ {!this._showEditor || !this._linkSrc || !this._linkDoc ? null : <LinkEditor sourceDoc={this._linkSrc} linkDoc={this._linkDoc} showLinks={action(() => (this._showEditor = !this._showEditor))} />}
</div>
);
}
diff --git a/src/client/views/nodes/MapBox/MapBoxInfoWindow.tsx b/src/client/views/nodes/MapBox/MapBoxInfoWindow.tsx
index 630ae18f5..00bedafbe 100644
--- a/src/client/views/nodes/MapBox/MapBoxInfoWindow.tsx
+++ b/src/client/views/nodes/MapBox/MapBoxInfoWindow.tsx
@@ -1,5 +1,5 @@
import { InfoWindow } from '@react-google-maps/api';
-import { action, computed } from 'mobx';
+import { action } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import { Doc } from '../../../../fields/Doc';
@@ -7,6 +7,7 @@ import { Id } from '../../../../fields/FieldSymbols';
import { emptyFunction, OmitKeys, returnAll, returnEmptyFilter, returnFalse, returnOne, returnTrue, returnZero, setupMoveUpEvents } from '../../../../Utils';
import { Docs } from '../../../documents/Documents';
import { CollectionViewType, DocumentType } from '../../../documents/DocumentTypes';
+import { CollectionNoteTakingView } from '../../collections/CollectionNoteTakingView';
import { CollectionStackingView } from '../../collections/CollectionStackingView';
import { ViewBoxAnnotatableProps } from '../../DocComponent';
import { FieldViewProps } from '../FieldView';
@@ -40,7 +41,7 @@ export class MapBoxInfoWindow extends React.Component<MapBoxInfoWindowProps & Vi
});
};
- _stack: CollectionStackingView | null | undefined;
+ _stack: CollectionStackingView | CollectionNoteTakingView | null | undefined;
childFitWidth = (doc: Doc) => doc.type === DocumentType.RTF;
addDoc = (doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).reduce((p, d) => p && Doc.AddDocToList(this.props.place, 'data', d), true as boolean);
removeDoc = (doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).reduce((p, d) => p && Doc.RemoveDocFromList(this.props.place, 'data', d), true as boolean);
diff --git a/src/client/views/nodes/button/FontIconBox.tsx b/src/client/views/nodes/button/FontIconBox.tsx
index 78ef85ec2..d3b95e25a 100644
--- a/src/client/views/nodes/button/FontIconBox.tsx
+++ b/src/client/views/nodes/button/FontIconBox.tsx
@@ -1,7 +1,7 @@
import { IconProp } from '@fortawesome/fontawesome-svg-core';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Tooltip } from '@material-ui/core';
-import { action, computed, observable } from 'mobx';
+import { action, computed, observable, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import { ColorState, SketchPicker } from 'react-color';
@@ -710,6 +710,13 @@ ScriptingGlobals.add(function toggleNoAutoLinkAnchor(checkResult?: boolean) {
}
if (editorView) RichTextMenu.Instance?.toggleNoAutoLinkAnchor();
});
+ScriptingGlobals.add(function toggleDictation(checkResult?: boolean) {
+ const textView = RichTextMenu.Instance?.TextView;
+ if (checkResult) {
+ return textView?._recording ? Colors.MEDIUM_BLUE : 'transparent';
+ }
+ if (textView) runInAction(() => (textView._recording = !textView._recording));
+});
ScriptingGlobals.add(function toggleBold(checkResult?: boolean) {
const editorView = RichTextMenu.Instance?.TextView?.EditorView;
diff --git a/src/client/views/nodes/formattedText/DashFieldView.tsx b/src/client/views/nodes/formattedText/DashFieldView.tsx
index 8c8b74560..d2f7b5677 100644
--- a/src/client/views/nodes/formattedText/DashFieldView.tsx
+++ b/src/client/views/nodes/formattedText/DashFieldView.tsx
@@ -216,7 +216,7 @@ export class DashFieldViewInternal extends React.Component<IDashFieldViewInterna
onPointerDownLabelSpan = (e: any) => {
setupMoveUpEvents(this, e, returnFalse, returnFalse, e => {
DashFieldViewMenu.createFieldView = this.createPivotForField;
- DashFieldViewMenu.Instance.show(e.clientX, e.clientY + 16);
+ DashFieldViewMenu.Instance.show(e.clientX, e.clientY + 16, this._fieldKey);
});
};
@@ -253,17 +253,21 @@ export class DashFieldViewMenu extends AntimodeMenu<AntimodeMenuProps> {
DashFieldViewMenu.Instance.fadeOut(true);
};
- public show = (x: number, y: number) => {
+ @observable _fieldKey = '';
+
+ @action
+ public show = (x: number, y: number, fieldKey: string) => {
+ this._fieldKey = fieldKey;
this.jumpTo(x, y, true);
const hideMenu = () => {
this.fadeOut(true);
- document.removeEventListener('pointerdown', hideMenu);
+ document.removeEventListener('pointerdown', hideMenu, true);
};
- document.addEventListener('pointerdown', hideMenu);
+ document.addEventListener('pointerdown', hideMenu, true);
};
render() {
const buttons = [
- <Tooltip key="trash" title={<div className="dash-tooltip">{'Remove Link Anchor'}</div>}>
+ <Tooltip key="trash" title={<div className="dash-tooltip">{`Show Pivot Viewer for '${this._fieldKey}'`}</div>}>
<button className="antimodeMenu-button" onPointerDown={this.showFields}>
<FontAwesomeIcon icon="eye" size="lg" />
</button>
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index b8ee89ef2..f61533619 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -24,7 +24,7 @@ import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, emptyFunction,
import { GoogleApiClientUtils, Pulls, Pushes } from '../../../apis/google_docs/GoogleApiClientUtils';
import { DocServer } from '../../../DocServer';
import { Docs, DocUtils } from '../../../documents/Documents';
-import { DocumentType } from '../../../documents/DocumentTypes';
+import { CollectionViewType, DocumentType } from '../../../documents/DocumentTypes';
import { DictationManager } from '../../../util/DictationManager';
import { DocumentManager } from '../../../util/DocumentManager';
import { DragManager } from '../../../util/DragManager';
@@ -63,6 +63,7 @@ import applyDevTools = require('prosemirror-dev-tools');
import React = require('react');
import { text } from 'body-parser';
import { CollectionTreeView } from '../../collections/CollectionTreeView';
+import { DocumentViewInternal } from '../DocumentView';
const translateGoogleApi = require('translate-google-api');
export interface FormattedTextBoxProps {
@@ -249,6 +250,16 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
!this.layoutDoc.showSidebar && this.toggleSidebar();
this._sidebarRef.current?.anchorMenuClick(this.getAnchor());
};
+ AnchorMenu.Instance.OnAudio = (e: PointerEvent) => {
+ !this.layoutDoc.showSidebar && this.toggleSidebar();
+ const anchor = this.getAnchor();
+ const target = this._sidebarRef.current?.anchorMenuClick(anchor);
+ if (target) {
+ anchor.followLinkAudio = true;
+ DocumentViewInternal.recordAudioAnnotation(Doc.GetProto(target), Doc.LayoutFieldKey(target));
+ target.title = ComputedField.MakeFunction(`self["text-audioAnnotations-text"].lastElement()`);
+ }
+ };
AnchorMenu.Instance.Highlight = action((color: string, isLinkButton: boolean) => {
this._editorView?.state && RichTextMenu.Instance.setHighlight(color, this._editorView, this._editorView?.dispatch);
return undefined;
@@ -382,9 +393,9 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
};
autoLink = () => {
+ const newAutoLinks = new Set<Doc>();
+ const oldAutoLinks = DocListCast(this.props.Document.links).filter(link => link.linkRelationship === LinkManager.AutoKeywords);
if (this._editorView?.state.doc.textContent) {
- const newAutoLinks = new Set<Doc>();
- const oldAutoLinks = DocListCast(this.props.Document.links).filter(link => link.linkRelationship === LinkManager.AutoKeywords);
const f = this._editorView.state.selection.from;
const t = this._editorView.state.selection.to;
var tr = this._editorView.state.tr as any;
@@ -393,8 +404,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
DocListCast(Doc.MyPublishedDocs.data).forEach(term => (tr = this.hyperlinkTerm(tr, term, newAutoLinks)));
tr = tr.setSelection(new TextSelection(tr.doc.resolve(f), tr.doc.resolve(t)));
this._editorView?.dispatch(tr);
- oldAutoLinks.filter(oldLink => !newAutoLinks.has(oldLink) && oldLink.anchor2 !== this.rootDoc).forEach(LinkManager.Instance.deleteLink);
}
+ oldAutoLinks.filter(oldLink => !newAutoLinks.has(oldLink) && oldLink.anchor2 !== this.rootDoc).forEach(LinkManager.Instance.deleteLink);
};
updateTitle = () => {
@@ -426,28 +437,26 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
const editorView = this._editorView;
if (editorView && (editorView as any).docView && !Doc.AreProtosEqual(target, this.rootDoc)) {
const autoLinkTerm = StrCast(target.title).replace(/^@/, '');
- const flattened1 = this.findInNode(editorView, editorView.state.doc, autoLinkTerm);
var alink: Doc | undefined;
- flattened1.forEach((flat, i) => {
- const flattened = this.findInNode(this._editorView!, this._editorView!.state.doc, autoLinkTerm);
- this._searchIndex = ++this._searchIndex > flattened.length - 1 ? 0 : this._searchIndex;
+ this.findInNode(editorView, editorView.state.doc, autoLinkTerm).forEach(sel => {
const splitter = editorView.state.schema.marks.splitter.create({ id: Utils.GenerateGuid() });
- const sel = flattened[i];
- tr = tr.addMark(sel.from, sel.to, splitter);
- tr.doc.nodesBetween(sel.from, sel.to, (node: any, pos: number, parent: any) => {
- if (node.firstChild === null && !node.marks.find((m: Mark) => m.type.name === schema.marks.noAutoLinkAnchor.name) && node.marks.find((m: Mark) => m.type.name === schema.marks.splitter.name)) {
- alink =
- alink ??
- (DocListCast(this.Document.links).find(link => Doc.AreProtosEqual(Cast(link.anchor1, Doc, null), this.rootDoc) && Doc.AreProtosEqual(Cast(link.anchor2, Doc, null), target)) ||
- DocUtils.MakeLink({ doc: this.props.Document }, { doc: target }, LinkManager.AutoKeywords)!);
- newAutoLinks.add(alink);
- const allAnchors = [{ href: Doc.localServerPath(target), title: 'a link', anchorId: this.props.Document[Id] }];
- allAnchors.push(...(node.marks.find((m: Mark) => m.type.name === schema.marks.autoLinkAnchor.name)?.attrs.allAnchors ?? []));
- const link = editorView.state.schema.marks.autoLinkAnchor.create({ allAnchors, title: 'auto term', location: 'add:right' });
- tr = tr.addMark(pos, pos + node.nodeSize, link);
- }
- });
- tr = tr.removeMark(sel.from, sel.to, splitter);
+ if (!sel.$anchor.pos || editorView.state.doc.textBetween(sel.$anchor.pos - 1, sel.$to.pos).trim() === autoLinkTerm) {
+ tr = tr.addMark(sel.from, sel.to, splitter);
+ tr.doc.nodesBetween(sel.from, sel.to, (node: any, pos: number, parent: any) => {
+ if (node.firstChild === null && !node.marks.find((m: Mark) => m.type.name === schema.marks.noAutoLinkAnchor.name) && node.marks.find((m: Mark) => m.type.name === schema.marks.splitter.name)) {
+ alink =
+ alink ??
+ (DocListCast(this.Document.links).find(link => Doc.AreProtosEqual(Cast(link.anchor1, Doc, null), this.rootDoc) && Doc.AreProtosEqual(Cast(link.anchor2, Doc, null), target)) ||
+ DocUtils.MakeLink({ doc: this.props.Document }, { doc: target }, LinkManager.AutoKeywords)!);
+ newAutoLinks.add(alink);
+ const allAnchors = [{ href: Doc.localServerPath(target), title: 'a link', anchorId: this.props.Document[Id] }];
+ allAnchors.push(...(node.marks.find((m: Mark) => m.type.name === schema.marks.autoLinkAnchor.name)?.attrs.allAnchors ?? []));
+ const link = editorView.state.schema.marks.autoLinkAnchor.create({ allAnchors, title: 'auto term', location: 'add:right' });
+ tr = tr.addMark(pos, pos + node.nodeSize, link);
+ }
+ });
+ tr = tr.removeMark(sel.from, sel.to, splitter);
+ }
});
}
return tr;
@@ -694,9 +703,9 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
const editor = this._editorView!;
const pcords = editor.posAtCoords({ left: e.clientX, top: e.clientY });
- let target = (e.target as any).parentElement; // hrefs are stored on the database of the <a> node that wraps the hyerlink <span>
+ let target = e.target as any; // hrefs are stored on the database of the <a> node that wraps the hyerlink <span>
while (target && !target.dataset?.targethrefs) target = target.parentElement;
- if (target) {
+ if (target && !(e.nativeEvent as any).dash) {
const hrefs = (target.dataset?.targethrefs as string)
?.trim()
.split(' ')
@@ -715,6 +724,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
AnchorMenu.Instance.jumpTo(e.clientX, e.clientY, true);
})
);
+ e.preventDefault();
e.stopPropagation();
return;
}
@@ -773,7 +783,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
const uicontrols: ContextMenuProps[] = [];
!Doc.noviceMode && uicontrols.push({ description: `${FormattedTextBox._canAnnotate ? "Don't" : ''} Show Menu on Selections`, event: () => (FormattedTextBox._canAnnotate = !FormattedTextBox._canAnnotate), icon: 'expand-arrows-alt' });
uicontrols.push({ description: !this.Document._noSidebar ? 'Hide Sidebar Handle' : 'Show Sidebar Handle', event: () => (this.layoutDoc._noSidebar = !this.layoutDoc._noSidebar), icon: 'expand-arrows-alt' });
- uicontrols.push({ description: `${this.layoutDoc._showAudio ? 'Hide' : 'Show'} Dictation Icon`, event: () => (this.layoutDoc._showAudio = !this.layoutDoc._showAudio), icon: 'expand-arrows-alt' });
uicontrols.push({ description: 'Show Highlights...', noexpand: true, subitems: highlighting, icon: 'hand-point-right' });
!Doc.noviceMode &&
uicontrols.push({
@@ -855,23 +864,28 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
setDictationContent = (value: string) => {
if (this._editorView && this._recordingStart) {
if (this._break) {
- const textanchor = Docs.Create.TextanchorDocument({ title: 'dictation anchor' });
- this.addDocument(textanchor);
- const link = DocUtils.MakeLinkToActiveAudio(() => textanchor, false).lastElement();
- link && (Doc.GetProto(link).isDictation = true);
- if (!link) return;
- const audioanchor = Cast(link.anchor2, Doc, null);
- if (!audioanchor) return;
- audioanchor.backgroundColor = 'tan';
- const audiotag = this._editorView.state.schema.nodes.audiotag.create({
- timeCode: NumCast(audioanchor._timecodeToShow),
- audioId: audioanchor[Id],
- textId: textanchor[Id],
- });
- Doc.GetProto(textanchor).title = 'dictation:' + audiotag.attrs.timeCode;
- const tr = this._editorView.state.tr.insert(this._editorView.state.doc.content.size, audiotag);
- const tr2 = tr.setSelection(TextSelection.create(tr.doc, tr.doc.content.size));
- this._editorView.dispatch(tr.setSelection(TextSelection.create(tr2.doc, tr2.doc.content.size)));
+ const textanchorFunc = () => {
+ const tanch = Docs.Create.TextanchorDocument({ title: 'dictation anchor' });
+ return this.addDocument(tanch) ? tanch : undefined;
+ };
+ const link = DocUtils.MakeLinkToActiveAudio(textanchorFunc, false).lastElement();
+ if (link) {
+ Doc.GetProto(link).isDictation = true;
+ const audioanchor = Cast(link.anchor2, Doc, null);
+ const textanchor = Cast(link.anchor1, Doc, null);
+ if (audioanchor) {
+ audioanchor.backgroundColor = 'tan';
+ const audiotag = this._editorView.state.schema.nodes.audiotag.create({
+ timeCode: NumCast(audioanchor._timecodeToShow),
+ audioId: audioanchor[Id],
+ textId: textanchor[Id],
+ });
+ Doc.GetProto(textanchor).title = 'dictation:' + audiotag.attrs.timeCode;
+ const tr = this._editorView.state.tr.insert(this._editorView.state.doc.content.size, audiotag);
+ const tr2 = tr.setSelection(TextSelection.create(tr.doc, tr.doc.content.size));
+ this._editorView.dispatch(tr.setSelection(TextSelection.create(tr2.doc, tr2.doc.content.size)));
+ }
+ }
}
const from = this._editorView.state.selection.from;
this._break = false;
@@ -1001,7 +1015,9 @@ 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));
- autoHeight && newHeight && this.props.setHeight?.(newHeight);
+ if (autoHeight && newHeight && newHeight !== this.rootDoc.height) {
+ this.props.setHeight?.(newHeight);
+ }
},
{ fireImmediately: true }
);
@@ -1459,14 +1475,14 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
document.removeEventListener('pointermove', this.onSelectMove);
};
onPointerUp = (e: React.PointerEvent): void => {
- if (!this._editorView?.state.selection.empty && FormattedTextBox._canAnnotate) this.setupAnchorMenu();
+ if (!this._editorView?.state.selection.empty && FormattedTextBox._canAnnotate && !(e.nativeEvent as any).dash) this.setupAnchorMenu();
if (!this._downEvent) return;
this._downEvent = false;
- if (this.props.isContentActive(true)) {
+ if (this.props.isContentActive(true) && !(e.nativeEvent as any).dash) {
const editor = this._editorView!;
const pcords = editor.posAtCoords({ left: e.clientX, top: e.clientY });
!this.props.isSelected(true) && editor.dispatch(editor.state.tr.setSelection(new TextSelection(editor.state.doc.resolve(pcords?.pos || 0))));
- let target = (e.target as any).parentElement; // hrefs are stored on the database of the <a> node that wraps the hyerlink <span>
+ let target = e.target as any; // hrefs are stored on the dataset of the <a> node that wraps the hyerlink <span>
while (target && !target.dataset?.targethrefs) target = target.parentElement;
FormattedTextBoxComment.update(this, editor, undefined, target?.dataset?.targethrefs, target?.dataset.linkdoc);
}
@@ -1695,7 +1711,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
if (this.props.setHeight && scrollHeight && this.props.renderDepth && !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.doc || this.layoutDoc.resolvedDataDoc) {
+ if (this.rootDoc === this.layoutDoc || this.layoutDoc.resolvedDataDoc) {
setScrollHeight();
} else {
setTimeout(setScrollHeight, 10); // if we have a template that hasn't been resolved yet, we can't set the height or we'd be setting it on the unresolved template. So set a timeout and hope its arrived...
@@ -1722,9 +1738,19 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
.scale(1 / NumCast(this.layoutDoc._viewScale, 1) / (this.props.NativeDimScaling?.() || 1));
@computed get audioHandle() {
- return (
- <div className="formattedTextBox-dictation" onClick={action(e => (this._recording = !this._recording))}>
- <FontAwesomeIcon className="formattedTextBox-audioFont" style={{ color: this._recording ? 'red' : 'blue', transitionDelay: '0.6s', opacity: this._recording ? 1 : 0.25 }} icon={'microphone'} size="sm" />
+ return !this._recording ? null : (
+ <div
+ className="formattedTextBox-dictation"
+ onPointerDown={e =>
+ setupMoveUpEvents(
+ this,
+ e,
+ returnFalse,
+ emptyFunction,
+ action(e => (this._recording = !this._recording))
+ )
+ }>
+ <FontAwesomeIcon className="formattedTextBox-audioFont" style={{ color: 'red' }} icon={'microphone'} size="sm" />
</div>
);
}
@@ -1749,7 +1775,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
}
@computed get sidebarCollection() {
const renderComponent = (tag: string) => {
- const ComponentTag = tag === 'freeform' ? CollectionFreeFormView : tag === 'tree' ? CollectionTreeView : tag === 'translation' ? FormattedTextBox : CollectionStackingView;
+ const ComponentTag = tag === CollectionViewType.Freeform ? CollectionFreeFormView : tag === CollectionViewType.Tree ? CollectionTreeView : tag === 'translation' ? FormattedTextBox : CollectionStackingView;
return ComponentTag === CollectionStackingView ? (
<SidebarAnnos
ref={this._sidebarRef}
@@ -1770,7 +1796,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
/>
) : (
<div onPointerDown={e => setupMoveUpEvents(this, e, returnFalse, emptyFunction, () => SelectionManager.SelectView(this.props.DocumentView?.()!, false), true)}>
- //@ts-ignore
<ComponentTag
{...OmitKeys(this.props, ['NativeWidth', 'NativeHeight', 'setContentView']).omit}
NativeWidth={returnZero}
@@ -1859,7 +1884,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
style={{
width: this.props.dontSelectOnLoad ? '100%' : `calc(100% - ${this.sidebarWidthPercent})`,
pointerEvents: !active && !SnappingManager.GetIsDragging() ? 'none' : undefined,
- overflow: this.layoutDoc._singleLine ? 'hidden' : undefined,
+ overflow: this.layoutDoc._singleLine ? 'hidden' : this.layoutDoc._autoHeight ? 'visible' : undefined,
}}
onScroll={this.onScroll}
onDrop={this.ondrop}>
@@ -1878,7 +1903,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
</div>
{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.layoutDoc._showAudio ? null : this.audioHandle}
+ {this.audioHandle}
</div>
</div>
);
diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx
index 21326efaa..2a77210ae 100644
--- a/src/client/views/nodes/formattedText/RichTextMenu.tsx
+++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx
@@ -60,7 +60,6 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> {
@observable private showLinkDropdown: boolean = false;
_reaction: IReactionDisposer | undefined;
- _delayHide = false;
constructor(props: Readonly<{}>) {
super(props);
runInAction(() => {
@@ -70,16 +69,6 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> {
});
}
- componentDidMount() {
- this._reaction = reaction(
- () => SelectionManager.Views(),
- () => this._delayHide && !(this._delayHide = false) && this.fadeOut(true)
- );
- }
- componentWillUnmount() {
- this._reaction?.();
- }
-
@computed get noAutoLink() {
return this._noLinkActive;
}
@@ -108,8 +97,6 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> {
return this._activeAlignment;
}
- public delayHide = () => (this._delayHide = true);
-
@action
public updateMenu(view: EditorView | undefined, lastState: EditorState | undefined, props: any) {
if (this._linkToRef.current?.getBoundingClientRect().width) {