aboutsummaryrefslogtreecommitdiff
path: root/src/client/views
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views')
-rw-r--r--src/client/views/AntimodeMenu.tsx6
-rw-r--r--src/client/views/DocumentDecorations.scss34
-rw-r--r--src/client/views/DocumentDecorations.tsx24
-rw-r--r--src/client/views/MainView.tsx18
-rw-r--r--src/client/views/collections/CollectionMenu.tsx12
-rw-r--r--src/client/views/collections/CollectionSchemaCells.tsx5
-rw-r--r--src/client/views/collections/CollectionSubView.tsx4
-rw-r--r--src/client/views/collections/CollectionTreeView.tsx1
-rw-r--r--src/client/views/collections/CollectionView.tsx9
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx1
-rw-r--r--src/client/views/collections/collectionFreeForm/FormatShapePane.tsx4
-rw-r--r--src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx4
-rw-r--r--src/client/views/nodes/AudioBox.scss16
-rw-r--r--src/client/views/nodes/AudioBox.tsx199
-rw-r--r--src/client/views/nodes/DocumentView.tsx41
-rw-r--r--src/client/views/nodes/FieldView.tsx7
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.tsx20
-rw-r--r--src/client/views/nodes/formattedText/RichTextMenu.tsx36
-rw-r--r--src/client/views/pdf/PDFMenu.tsx4
-rw-r--r--src/client/views/search/SearchBox.tsx7
20 files changed, 239 insertions, 213 deletions
diff --git a/src/client/views/AntimodeMenu.tsx b/src/client/views/AntimodeMenu.tsx
index 68ccefcb5..ccc54058d 100644
--- a/src/client/views/AntimodeMenu.tsx
+++ b/src/client/views/AntimodeMenu.tsx
@@ -1,12 +1,14 @@
import React = require("react");
import { observable, action } from "mobx";
import "./AntimodeMenu.scss";
+export interface AntimodeMenuProps {
+}
/**
* This is an abstract class that serves as the base for a PDF-style or Marquee-style
* menu. To use this class, look at PDFMenu.tsx or MarqueeOptionsMenu.tsx for an example.
*/
-export default abstract class AntimodeMenu extends React.Component {
+export default abstract class AntimodeMenu<T extends AntimodeMenuProps> extends React.Component<T, {}> {
protected _offsetY: number = 0;
protected _offsetX: number = 0;
protected _mainCont: React.RefObject<HTMLDivElement> = React.createRef();
@@ -18,7 +20,7 @@ export default abstract class AntimodeMenu extends React.Component {
@observable protected _transitionProperty: string = "opacity";
@observable protected _transitionDuration: string = "0.5s";
@observable protected _transitionDelay: string = "";
- @observable protected _canFade: boolean = true;
+ @observable protected _canFade: boolean = false;
@observable public Pinned: boolean = false;
diff --git a/src/client/views/DocumentDecorations.scss b/src/client/views/DocumentDecorations.scss
index 5401623e8..1e8cfdff4 100644
--- a/src/client/views/DocumentDecorations.scss
+++ b/src/client/views/DocumentDecorations.scss
@@ -21,14 +21,6 @@ $linkGap : 3px;
background: none;
}
-
- .documentDecorations-rotation {
- pointer-events: auto;
- cursor: alias;
- width: 10px;
- height: 10px;
- }
-
.documentDecorations-resizer {
pointer-events: auto;
background: $alt-accent;
@@ -76,11 +68,17 @@ $linkGap : 3px;
grid-column-end: 7;
}
+ #documentDecorations-rotation,
#documentDecorations-borderRadius {
- grid-column-start: 5;
- grid-column-end: 7;
+ grid-column: 5;
+ grid-row: 4;
border-radius: 100%;
background: dimgray;
+ height: 8;
+ right: -12;
+ top: 12;
+ position: relative;
+ pointer-events: all;
.borderRadiusTooltip {
width: 10px;
@@ -88,6 +86,11 @@ $linkGap : 3px;
position: absolute;
}
}
+ #documentDecorations-rotation {
+ background: transparent;
+ right: -15;
+ }
+
#documentDecorations-topLeftResizer,
#documentDecorations-bottomRightResizer {
@@ -193,11 +196,11 @@ $linkGap : 3px;
.documentDecorations-iconifyButton {
opacity: 1;
grid-column-start: 4;
- grid-column-end: 5;
+ grid-column-end: 4;
pointer-events: all;
text-align: center;
- left: -25px;
- top: -2px;
+ right: 0;
+ top: 0;
cursor: pointer;
position: absolute;
background: transparent;
@@ -206,14 +209,11 @@ $linkGap : 3px;
.documentDecorations-openInTab {
opacity: 1;
- grid-column-start: 4;
+ grid-column-start: 5;
grid-column-end: 5;
pointer-events: all;
text-align: center;
cursor: pointer;
- width: 15px;
- margin-left: -8px;
- margin-top: auto;
}
.documentDecorations-closeButton {
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index c5e3e6752..e546ca858 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -659,14 +659,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
if (bounds.y > bounds.b) {
bounds.y = bounds.b - (this._resizeBorderWidth + this._linkBoxHeight + this._titleHeight);
}
- var offset = 0;
- var rotButton = <></>;
- //make offset larger for ink to edit points
- if (seldoc.rootDoc.type === DocumentType.INK) {
- offset = 20;
- rotButton = <div id="documentDecorations-rotation" title="rotate" className="documentDecorations-rotation"
- onPointerDown={this.onRotateDown}> ⟲ </div>;
- }
+ const useRotation = seldoc.rootDoc.type === DocumentType.INK;
return (<div className="documentDecorations" style={{ background: darkScheme }} >
<div className="documentDecorations-background" style={{
@@ -680,22 +673,21 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
</div>
{bounds.r - bounds.x < 15 && bounds.b - bounds.y < 15 ? (null) : <>
<div className="documentDecorations-container" key="container" ref={this.setTextBar} style={{
- width: (bounds.r - bounds.x + this._resizeBorderWidth + offset) + "px",
- height: (bounds.b - bounds.y + this._resizeBorderWidth + this._titleHeight + offset) + "px",
- left: bounds.x - this._resizeBorderWidth / 2 - offset / 2,
- top: bounds.y - this._resizeBorderWidth / 2 - this._titleHeight - offset / 2,
+ width: (bounds.r - bounds.x + this._resizeBorderWidth) + "px",
+ height: (bounds.b - bounds.y + this._resizeBorderWidth + this._titleHeight) + "px",
+ left: bounds.x - this._resizeBorderWidth / 2,
+ top: bounds.y - this._resizeBorderWidth / 2 - this._titleHeight,
}}>
{maximizeIcon}
{titleArea}
{SelectionManager.SelectedDocuments().length !== 1 || seldoc.Document.type === DocumentType.INK ? (null) :
<Tooltip title={<><div className="dash-tooltip">{`${seldoc.finalLayoutKey.includes("icon") ? "De" : ""}Iconify Document`}</div></>} placement="top">
<div className="documentDecorations-iconifyButton" onPointerDown={this.onIconifyDown}>
- {"_"}
+ <FontAwesomeIcon icon={seldoc.finalLayoutKey.includes("icon") ? "window-restore" : "window-minimize"} className="documentView-minimizedIcon" />
</div></Tooltip>}
<Tooltip title={<><div className="dash-tooltip">Open In a New Pane</div></>} placement="top"><div className="documentDecorations-openInTab" onPointerDown={this.onMaximizeDown}>
{SelectionManager.SelectedDocuments().length === 1 ? <FontAwesomeIcon icon="external-link-alt" className="documentView-minimizedIcon" /> : "..."}
</div></Tooltip>
- {rotButton}
<div id="documentDecorations-topLeftResizer" className="documentDecorations-resizer"
onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
<div id="documentDecorations-topResizer" className="documentDecorations-resizer"
@@ -719,8 +711,8 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
onPointerDown={this.onSelectorUp} onContextMenu={e => e.preventDefault()}>
<FontAwesomeIcon className="documentdecorations-times" icon={faArrowAltCircleUp} size="lg" />
</div></Tooltip>}
- <div id="documentDecorations-borderRadius" className="documentDecorations-radius"
- onPointerDown={this.onRadiusDown} onContextMenu={(e) => e.preventDefault()}></div>
+ <div id={`documentDecorations-${useRotation ? "rotation" : "borderRadius"}`}
+ onPointerDown={useRotation ? this.onRotateDown : this.onRadiusDown} onContextMenu={(e) => e.preventDefault()}>{useRotation && "⟲"}</div>
</div >
<div className="link-button-container" key="links" style={{ left: bounds.x - this._resizeBorderWidth / 2 + 10, top: bounds.b + this._resizeBorderWidth / 2 }}>
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index db5325713..5a9d95aac 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -182,7 +182,8 @@ export class MainView extends React.Component {
fa.faIndent, fa.faEyeDropper, fa.faPaintRoller, fa.faBars, fa.faBrush, fa.faShapes, fa.faEllipsisH, fa.faHandPaper, fa.faMap, fa.faUser, faHireAHelper,
fa.faDesktop, fa.faTrashRestore, fa.faUsers, fa.faWrench, fa.faCog, fa.faMap, fa.faBellSlash, fa.faExpandAlt, fa.faArchive, fa.faBezierCurve, fa.faCircle,
fa.faLongArrowAltRight, fa.faPenFancy, fa.faAngleDoubleRight, faBuffer, fa.faExpand, fa.faUndo, fa.faSlidersH, fa.faAngleDoubleLeft, fa.faAngleUp,
- fa.faAngleDown, fa.faPlayCircle, fa.faClock, fa.faRocket, fa.faExchangeAlt, faBuffer, fa.faHashtag, fa.faAlignJustify, fa.faCheckSquare, fa.faListUl);
+ fa.faAngleDown, fa.faPlayCircle, fa.faClock, fa.faRocket, fa.faExchangeAlt, faBuffer, fa.faHashtag, fa.faAlignJustify, fa.faCheckSquare, fa.faListUl,
+ fa.faWindowMinimize, fa.faWindowRestore);
this.initEventListeners();
this.initAuthenticationRouters();
}
@@ -253,6 +254,8 @@ export class MainView extends React.Component {
@action
createNewWorkspace = async (id?: string) => {
+ const myCatalog = Doc.UserDoc().myCatalog as Doc;
+ const presentation = Doc.MakeCopy(Doc.UserDoc().emptyPresentation as Doc, true);
const workspaces = Cast(this.userDoc.myWorkspaces, Doc) as Doc;
const workspaceCount = DocListCast(workspaces.data).length + 1;
const freeformOptions: DocumentOptions = {
@@ -263,8 +266,10 @@ export class MainView extends React.Component {
title: "Untitled Collection",
};
const freeformDoc = CurrentUserUtils.GuestTarget || Docs.Create.FreeformDocument([], freeformOptions);
- const workspaceDoc = Docs.Create.StandardCollectionDockingDocument([{ doc: freeformDoc, initialWidth: 600, path: [Doc.UserDoc().myCatalog as Doc] }], { title: `Workspace ${workspaceCount}` }, id, "row");
-
+ const workspaceDoc = Docs.Create.StandardCollectionDockingDocument([{ doc: freeformDoc, initialWidth: 600, path: [myCatalog] }], { title: `Workspace ${workspaceCount}` }, id, "row");
+ Doc.AddDocToList(myCatalog, "data", freeformDoc);
+ Doc.AddDocToList(myCatalog, "data", presentation);
+ Doc.UserDoc().activePresentation = presentation;
const toggleTheme = ScriptField.MakeScript(`self.darkScheme = !self.darkScheme`);
const toggleComic = ScriptField.MakeScript(`toggleComicMode()`);
const copyWorkspace = ScriptField.MakeScript(`copyWorkspace()`);
@@ -651,7 +656,11 @@ export class MainView extends React.Component {
return !this._flyoutTranslate ? (<div className="mainView-expandFlyoutButton" title="Re-attach sidebar" onPointerDown={MainView.expandFlyout}></div>) : (null);
}
- addButtonDoc = (doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).reduce((flg: boolean, doc) => flg && Doc.AddDocToList(Doc.UserDoc().dockedBtns as Doc, "data", doc), true);
+ addButtonDoc = (doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).reduce((flg: boolean, doc) => {
+ const ret = flg && Doc.AddDocToList(Doc.UserDoc().dockedBtns as Doc, "data", doc);
+ ret && (doc._stayInCollection = undefined);
+ return ret;
+ }, true)
remButtonDoc = (doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).reduce((flg: boolean, doc) => flg && Doc.RemoveDocFromList(Doc.UserDoc().dockedBtns as Doc, "data", doc), true);
moveButtonDoc = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (document: Doc | Doc[]) => boolean) => this.remButtonDoc(doc) && addDocument(doc);
@@ -816,7 +825,6 @@ export class MainView extends React.Component {
<DocumentDecorations />
{this.search}
<CollectionMenu />
- <div style={{ display: "none" }}><RichTextMenu key="rich" /></div>
<FormatShapePane />
{LinkDescriptionPopup.descriptionPopup ? <LinkDescriptionPopup /> : null}
{DocumentLinksButton.EditLink ? <LinkMenu docView={DocumentLinksButton.EditLink} addDocTab={DocumentLinksButton.EditLink.props.addDocTab} changeFlyout={emptyFunction} /> : (null)}
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index 5119ff6c9..97d38d27e 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -21,7 +21,7 @@ import { CurrentUserUtils } from "../../util/CurrentUserUtils";
import { DragManager } from "../../util/DragManager";
import { SelectionManager } from "../../util/SelectionManager";
import { undoBatch } from "../../util/UndoManager";
-import AntimodeMenu from "../AntimodeMenu";
+import AntimodeMenu, { AntimodeMenuProps } from "../AntimodeMenu";
import { EditableView } from "../EditableView";
import GestureOverlay from "../GestureOverlay";
import { ActiveFillColor, ActiveInkColor, SetActiveArrowEnd, SetActiveArrowStart, SetActiveBezierApprox, SetActiveFillColor, SetActiveInkColor, SetActiveInkWidth } from "../InkingStroke";
@@ -32,13 +32,13 @@ import "./CollectionMenu.scss";
import { CollectionViewType, COLLECTION_BORDER_WIDTH } from "./CollectionView";
@observer
-export default class CollectionMenu extends AntimodeMenu {
+export default class CollectionMenu extends AntimodeMenu<AntimodeMenuProps> {
static Instance: CollectionMenu;
@observable SelectedCollection: DocumentView | undefined;
@observable FieldKey: string;
- constructor(props: Readonly<{}>) {
+ constructor(props: any) {
super(props);
this.FieldKey = "";
CollectionMenu.Instance = this;
@@ -429,7 +429,9 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionMenu
@computed get selectedDoc() { return this.selectedDocumentView?.rootDoc; }
@computed get isText() {
if (this.selectedDoc) {
- return this.selectedDoc[Doc.LayoutFieldKey(this.selectedDoc)] instanceof RichTextField;
+ const layoutField = Doc.LayoutField(this.selectedDoc);
+ return StrCast(layoutField).includes("FormattedText") ||
+ (layoutField instanceof Doc && StrCast(layoutField.layout).includes("FormattedText"));
}
else return false;
}
@@ -655,7 +657,7 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionMenu
</> :
(null)
}
- {this.isText ? <RichTextMenu key="rich" /> : null}
+ {this.isText ? <RichTextMenu /> : null}
</div>;
}
}
diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx
index 24088575a..81b63cbcd 100644
--- a/src/client/views/collections/CollectionSchemaCells.tsx
+++ b/src/client/views/collections/CollectionSchemaCells.tsx
@@ -82,9 +82,8 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
const doc = Doc.GetProto(this.props.rowProps.original);
const aliasdoc = await SearchUtil.GetAliasesOfDocument(doc);
if (aliasdoc.length > 0) {
- const targetContext = Cast(aliasdoc[0].context, Doc) as Doc;
- console.log(StrCast(targetContext.title));
- runInAction(() => this.contents = StrCast(targetContext.title));
+ const targetContext = Cast(aliasdoc[0].context, Doc, null);
+ targetContext && runInAction(() => this.contents = StrCast(targetContext.title));
}
}
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 3f2ad47a5..075be41fd 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -240,13 +240,13 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
Doc.AreProtosEqual(Cast(movedDocs[0].annotationOn, Doc, null), this.props.Document);
added = docDragData.moveDocument(movedDocs, this.props.Document, canAdd ? this.addDocument : returnFalse);
} else added = res;
- !added && alert("You don't have permission to perform this move");
e.stopPropagation();
} else {
ScriptCast(this.props.Document.dropConverter)?.script.run({ dragData: docDragData });
added = this.addDocument(docDragData.droppedDocuments);
}
- added && e.stopPropagation();
+ !added && alert("You cannot perform this move");
+ e.stopPropagation();
return added;
}
else if (de.complete.annoDragData) {
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index d096e7d66..f23fa8eb6 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -869,6 +869,7 @@ Scripting.addGlobal(function readFacetData(layoutDoc: Doc, dataDoc: Doc, dataKey
});
const facetValueDocSet = (nonNumbers / facetValues.length > .1 ? facetValues.sort() : facetValues.sort((n1: string, n2: string) => Number(n1) - Number(n2))).map(facetValue => {
const doc = new Doc();
+ doc.system = true;
doc.title = facetValue.toString();
doc.treeViewChecked = ComputedField.MakeFunction("determineCheckedState(layoutDoc, facetHeader, facetValue)", {}, { layoutDoc, facetHeader, facetValue });
return doc;
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 6dd21ef7f..9d305145e 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -69,7 +69,7 @@ export enum CollectionViewType {
Carousel = "carousel",
Carousel3D = "3D Carousel",
Linear = "linear",
- Staff = "staff",
+ //Staff = "staff",
Map = "map",
Grid = "grid",
Pile = "pileup"
@@ -139,6 +139,9 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
}
const docs = doc instanceof Doc ? [doc] : doc;
+
+
+ if (docs.find(doc => Doc.AreProtosEqual(doc, this.props.Document))) return false;
const targetDataDoc = this.props.Document[DataSym];
const docList = DocListCast(targetDataDoc[this.props.fieldKey]);
const added = docs.filter(d => !docList.includes(d));
@@ -177,6 +180,7 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
const pushpinLink = DocUtils.MakeLink({ doc: pushpin }, { doc: doc }, "pushpin", "");
doc.displayTimecode = undefined;
}
+ doc._stayInCollection = undefined;
doc.context = this.props.Document;
});
added.map(add => Doc.AddDocToList(Cast(Doc.UserDoc().myCatalog, Doc, null), "data", add));
@@ -253,7 +257,7 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
case CollectionViewType.Schema: return (<CollectionSchemaView key="collview" {...props} />);
case CollectionViewType.Docking: return (<CollectionDockingView key="collview" {...props} />);
case CollectionViewType.Tree: return (<CollectionTreeView key="collview" {...props} />);
- case CollectionViewType.Staff: return (<CollectionStaffView key="collview" {...props} />);
+ //case CollectionViewType.Staff: return (<CollectionStaffView key="collview" {...props} />);
case CollectionViewType.Multicolumn: return (<CollectionMulticolumnView key="collview" {...props} />);
case CollectionViewType.Multirow: return (<CollectionMultirowView key="rpwview" {...props} />);
case CollectionViewType.Linear: { return (<CollectionLinearView key="collview" {...props} />); }
@@ -480,6 +484,7 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
Doc.AddDocToList(facetCollection, this.props.fieldKey + "-filter", newFacet);
} else {
newFacet = new Doc();
+ newFacet.sytem = true;
newFacet.title = facetHeader;
newFacet.treeViewOpen = true;
newFacet.type = DocumentType.COL;
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 55c2b253b..46e30f616 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -605,6 +605,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
pan = (e: PointerEvent | React.Touch | { clientX: number, clientY: number }): void => {
// bcz: theres should be a better way of doing these than referencing these static instances directly
MarqueeOptionsMenu.Instance?.fadeOut(true);// I think it makes sense for the marquee menu to go away when panned. -syip2
+ // PDFMenu.Instance.fadeOut(true); (commented out for mobile)
const [dx, dy] = this.getTransform().transformDirection(e.clientX - this._lastX, e.clientY - this._lastY);
this.setPan((this.Document._panX || 0) - dx, (this.Document._panY || 0) - dy, undefined, true);
diff --git a/src/client/views/collections/collectionFreeForm/FormatShapePane.tsx b/src/client/views/collections/collectionFreeForm/FormatShapePane.tsx
index 1ffa2fbed..a7f44bbbf 100644
--- a/src/client/views/collections/collectionFreeForm/FormatShapePane.tsx
+++ b/src/client/views/collections/collectionFreeForm/FormatShapePane.tsx
@@ -9,13 +9,13 @@ import { InkField } from "../../../../fields/InkField";
import { BoolCast, Cast, NumCast } from "../../../../fields/Types";
import { DocumentType } from "../../../documents/DocumentTypes";
import { SelectionManager } from "../../../util/SelectionManager";
-import AntimodeMenu from "../../AntimodeMenu";
+import AntimodeMenu, { AntimodeMenuProps } from "../../AntimodeMenu";
import "./FormatShapePane.scss";
import { undoBatch } from "../../../util/UndoManager";
import { ColorState, SketchPicker } from 'react-color';
@observer
-export default class FormatShapePane extends AntimodeMenu {
+export default class FormatShapePane extends AntimodeMenu<AntimodeMenuProps> {
static Instance: FormatShapePane;
private _lastFill = "#D0021B";
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx b/src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx
index f1df7998b..2cfe0183c 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx
@@ -1,5 +1,5 @@
import React = require("react");
-import AntimodeMenu from "../../AntimodeMenu";
+import AntimodeMenu, { AntimodeMenuProps } from "../../AntimodeMenu";
import { observer } from "mobx-react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { unimplementedFunction } from "../../../../Utils";
@@ -7,7 +7,7 @@ import { undoBatch } from "../../../util/UndoManager";
import { Tooltip } from "@material-ui/core";
@observer
-export default class MarqueeOptionsMenu extends AntimodeMenu {
+export default class MarqueeOptionsMenu extends AntimodeMenu<AntimodeMenuProps> {
static Instance: MarqueeOptionsMenu;
public createCollection: (e: KeyboardEvent | React.PointerEvent | undefined) => void = unimplementedFunction;
diff --git a/src/client/views/nodes/AudioBox.scss b/src/client/views/nodes/AudioBox.scss
index c80e3af24..f16d13a4e 100644
--- a/src/client/views/nodes/AudioBox.scss
+++ b/src/client/views/nodes/AudioBox.scss
@@ -17,6 +17,22 @@
display: flex;
width: 100%;
align-items: center;
+ height: 100%;
+
+ .audiobox-dictation {
+ position: relative;
+ width: 30px;
+ height: 100%;
+ align-items: center;
+ display: inherit;
+ background: dimgray;
+ left: 0px;
+ }
+
+ .audiobox-dictation:hover {
+ color: white;
+ cursor: pointer;
+ }
}
.audiobox-handle {
diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx
index 900963eb0..5c8cb5e35 100644
--- a/src/client/views/nodes/AudioBox.tsx
+++ b/src/client/views/nodes/AudioBox.tsx
@@ -530,113 +530,112 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps, AudioD
bringToFront={emptyFunction}
scriptContext={this} />;
};
- return <div className="audiobox-container" onContextMenu={this.specificContextMenu} onClick={!this.path ? this.recordClick : undefined}>
- <div className="audiobox-inner" style={{ pointerEvents: !interactive ? "none" : undefined }}>
- {!this.path ?
- <div className="audiobox-buttons">
- <div className="audiobox-dictation" onClick={this.onFile}>
- <FontAwesomeIcon style={{ width: "30px", background: this.layoutDoc.playOnSelect ? "yellow" : "rgba(0,0,0,0)" }} icon="file-alt" size={this.props.PanelHeight() < 36 ? "1x" : "2x"} />
- </div>
- {this.audioState === "recording" ?
- <div className="recording" onClick={e => e.stopPropagation()}>
- <div className="buttons" onClick={this.recordClick}>
- <FontAwesomeIcon style={{ width: "100%" }} icon={"stop"} size={this.props.PanelHeight() < 36 ? "1x" : "2x"} />
- </div>
- <div className="buttons" onClick={this._paused ? this.recordPlay : this.recordPause}>
- <FontAwesomeIcon style={{ width: "100%" }} icon={this._paused ? "play" : "pause"} size={this.props.PanelHeight() < 36 ? "1x" : "2x"} />
- </div>
- <div className="time">{formatTime(Math.round(NumCast(this.layoutDoc.currentTimecode)))}</div>
+ return <div className="audiobox-container" onContextMenu={this.specificContextMenu} onClick={!this.path && !this._recorder ? this.recordAudioAnnotation : undefined} style={{ pointerEvents: !interactive ? "none" : undefined }}>
+ {!this.path ?
+ <div className="audiobox-buttons">
+ <div className="audiobox-dictation" onClick={this.onFile}>
+ <FontAwesomeIcon style={{ width: "30px", background: this.layoutDoc.playOnSelect ? "yellow" : "rgba(0,0,0,0)" }} icon="file-alt" size={this.props.PanelHeight() < 36 ? "1x" : "2x"} />
+ </div>
+ {this.audioState === "recording" || this.audioState === "paused" ?
+ <div className="recording" onClick={e => e.stopPropagation()}>
+ <div className="buttons" onClick={this.recordClick}>
+ <FontAwesomeIcon style={{ width: "100%" }} icon={"stop"} size={this.props.PanelHeight() < 36 ? "1x" : "2x"} />
+ </div>
+ <div className="buttons" onClick={this._paused ? this.recordPlay : this.recordPause}>
+ <FontAwesomeIcon style={{ width: "100%" }} icon={this._paused ? "play" : "pause"} size={this.props.PanelHeight() < 36 ? "1x" : "2x"} />
</div>
- :
- <button className={`audiobox-record${interactive}`} style={{ backgroundColor: "black" }}>
- RECORD
+ <div className="time">{formatTime(Math.round(NumCast(this.layoutDoc.currentTimecode)))}</div>
+ </div>
+ :
+ <button className={`audiobox-record${interactive}`} style={{ backgroundColor: "black" }}>
+ RECORD
</button>}
- </div> :
- <div className="audiobox-controls" >
- <div className="audiobox-dictation"></div>
- <div className="audiobox-player" >
- <div className="audiobox-playhead" title={this.audioState === "paused" ? "play" : "pause"} onClick={this.onPlay}> <FontAwesomeIcon style={{ width: "100%", position: "absolute", left: "0px", top: "5px", borderWidth: "thin", borderColor: "white" }} icon={this.audioState === "paused" ? "play" : "pause"} size={"1x"} /></div>
- <div className="audiobox-timeline" onClick={e => { e.stopPropagation(); e.preventDefault(); }}
- onPointerDown={e => {
- if (e.button === 0 && !e.ctrlKey) {
- const rect = (e.target as any).getBoundingClientRect();
-
- if (e.target !== this._audioRef.current) {
- const wasPaused = this.audioState === "paused";
- this._ele!.currentTime = this.layoutDoc.currentTimecode = (e.clientX - rect.x) / rect.width * this.audioDuration;
- wasPaused && this.pause();
- }
-
- this.onPointerDownTimeline(e);
- }
- }}>
- <div className="waveform">
- {this.waveform}
- </div>
- {DocListCast(this.dataDoc[this.annotationKey]).map((m, i) =>
- (!m.isLabel) ?
- (this.layoutDoc.hideMarkers) ? (null) :
- <div className={`audiobox-marker-${this.props.PanelHeight() < 32 ? "mini" : ""}container1`} key={i}
- title={`${formatTime(Math.round(NumCast(m.audioStart)))}` + " - " + `${formatTime(Math.round(NumCast(m.audioEnd)))}`}
- style={{
- left: `${NumCast(m.audioStart) / this.audioDuration * 100}%`,
- top: `${this.isOverlap(m) * 1 / (this.dataDoc.markerAmount + 1) * 100}%`,
- width: `${(NumCast(m.audioEnd) - NumCast(m.audioStart)) / this.audioDuration * 100}%`, height: `${1 / (this.dataDoc.markerAmount + 1) * 100}%`
- }}
- onClick={e => { this.playFrom(NumCast(m.audioStart), NumCast(m.audioEnd)); e.stopPropagation(); }} >
- <div className="left-resizer" onPointerDown={e => this.onPointerDown(e, m, true)}></div>
- {markerDoc(m, this.rangeScript)}
- <div className="resizer" onPointerDown={e => this.onPointerDown(e, m, false)}></div>
- </div>
- :
- (this.layoutDoc.hideLabels) ? (null) :
- <div className={`audiobox-marker-${this.props.PanelHeight() < 32 ? "mini" : ""}container`} key={i}
- style={{ left: `${NumCast(m.audioStart) / this.audioDuration * 100}%` }}>
- {markerDoc(m, this.labelScript)}
- </div>
- )}
- {DocListCast(this.dataDoc.links).map((l, i) => {
- const { la1, la2, linkTime } = this.getLinkData(l);
- let startTime = linkTime;
- if (la2.audioStart && !la2.audioEnd) {
- startTime = NumCast(la2.audioStart);
+ </div> :
+ <div className="audiobox-controls" >
+ <div className="audiobox-dictation"></div>
+ <div className="audiobox-player" >
+ <div className="audiobox-playhead" title={this.audioState === "paused" ? "play" : "pause"} onClick={this.onPlay}> <FontAwesomeIcon style={{ width: "100%", position: "absolute", left: "0px", top: "5px", borderWidth: "thin", borderColor: "white" }} icon={this.audioState === "paused" ? "play" : "pause"} size={"1x"} /></div>
+ <div className="audiobox-timeline" onClick={e => { e.stopPropagation(); e.preventDefault(); }}
+ onPointerDown={e => {
+ if (e.button === 0 && !e.ctrlKey) {
+ const rect = (e.target as any).getBoundingClientRect();
+
+ if (e.target !== this._audioRef.current) {
+ const wasPaused = this.audioState === "paused";
+ this._ele!.currentTime = this.layoutDoc.currentTimecode = (e.clientX - rect.x) / rect.width * this.audioDuration;
+ wasPaused && this.pause();
}
- return !linkTime ? (null) :
- <div className={`audiobox-marker-${this.props.PanelHeight() < 32 ? "mini" : ""}container`} key={l[Id]} style={{ left: `${startTime / this.audioDuration * 100}%` }} onClick={e => e.stopPropagation()}>
- <DocumentView {...this.props}
- Document={l}
- NativeHeight={returnZero}
- NativeWidth={returnZero}
- rootSelected={returnFalse}
- ContainingCollectionDoc={this.props.Document}
- parentActive={returnTrue}
- bringToFront={emptyFunction}
- backgroundColor={returnTransparent}
- ContentScaling={returnOne}
- forcedBackgroundColor={returnTransparent}
- pointerEvents={false}
- LayoutTemplate={undefined}
- LayoutTemplateString={LinkAnchorBox.LayoutString(`anchor${Doc.LinkEndpoint(l, la2)}`)}
- />
- <div key={i} className={`audiobox-marker`} onPointerEnter={() => Doc.linkFollowHighlight(la1)}
- onPointerDown={e => { if (e.button === 0 && !e.ctrlKey) { this.playFrom(startTime); e.stopPropagation(); e.preventDefault(); } }} />
- </div>;
- })}
- {this._visible ? this.selectionContainer : null}
-
- <div className="audiobox-current" ref={this._audioRef} onClick={e => { e.stopPropagation(); e.preventDefault(); }} style={{ left: `${NumCast(this.layoutDoc.currentTimecode) / this.audioDuration * 100}%`, pointerEvents: "none" }} />
- {this.audio}
- </div>
- <div className="current-time">
- {formatTime(Math.round(NumCast(this.layoutDoc.currentTimecode)))}
- </div>
- <div className="total-time">
- {formatTime(Math.round(this.audioDuration))}
+ this.onPointerDownTimeline(e);
+ }
+ }}>
+ <div className="waveform">
+ {this.waveform}
</div>
+ {DocListCast(this.dataDoc[this.annotationKey]).map((m, i) =>
+ (!m.isLabel) ?
+ (this.layoutDoc.hideMarkers) ? (null) :
+ <div className={`audiobox-marker-${this.props.PanelHeight() < 32 ? "mini" : ""}container1`} key={i}
+ title={`${formatTime(Math.round(NumCast(m.audioStart)))}` + " - " + `${formatTime(Math.round(NumCast(m.audioEnd)))}`}
+ style={{
+ left: `${NumCast(m.audioStart) / this.audioDuration * 100}%`,
+ top: `${this.isOverlap(m) * 1 / (this.dataDoc.markerAmount + 1) * 100}%`,
+ width: `${(NumCast(m.audioEnd) - NumCast(m.audioStart)) / this.audioDuration * 100}%`, height: `${1 / (this.dataDoc.markerAmount + 1) * 100}%`
+ }}
+ onClick={e => { this.playFrom(NumCast(m.audioStart), NumCast(m.audioEnd)); e.stopPropagation(); }} >
+ <div className="left-resizer" onPointerDown={e => this.onPointerDown(e, m, true)}></div>
+ {markerDoc(m, this.rangeScript)}
+ <div className="resizer" onPointerDown={e => this.onPointerDown(e, m, false)}></div>
+ </div>
+ :
+ (this.layoutDoc.hideLabels) ? (null) :
+ <div className={`audiobox-marker-${this.props.PanelHeight() < 32 ? "mini" : ""}container`} key={i}
+ style={{ left: `${NumCast(m.audioStart) / this.audioDuration * 100}%` }}>
+ {markerDoc(m, this.labelScript)}
+ </div>
+ )}
+ {DocListCast(this.dataDoc.links).map((l, i) => {
+ const { la1, la2, linkTime } = this.getLinkData(l);
+ let startTime = linkTime;
+ if (la2.audioStart && !la2.audioEnd) {
+ startTime = NumCast(la2.audioStart);
+ }
+
+ return !linkTime ? (null) :
+ <div className={`audiobox-marker-${this.props.PanelHeight() < 32 ? "mini" : ""}container`} key={l[Id]} style={{ left: `${startTime / this.audioDuration * 100}%` }} onClick={e => e.stopPropagation()}>
+ <DocumentView {...this.props}
+ Document={l}
+ NativeHeight={returnZero}
+ NativeWidth={returnZero}
+ rootSelected={returnFalse}
+ ContainingCollectionDoc={this.props.Document}
+ parentActive={returnTrue}
+ bringToFront={emptyFunction}
+ backgroundColor={returnTransparent}
+ ContentScaling={returnOne}
+ forcedBackgroundColor={returnTransparent}
+ pointerEvents={false}
+ LayoutTemplate={undefined}
+ LayoutTemplateString={LinkAnchorBox.LayoutString(`anchor${Doc.LinkEndpoint(l, la2)}`)}
+ />
+ <div key={i} className={`audiobox-marker`} onPointerEnter={() => Doc.linkFollowHighlight(la1)}
+ onPointerDown={e => { if (e.button === 0 && !e.ctrlKey) { this.playFrom(startTime); e.stopPropagation(); e.preventDefault(); } }} />
+ </div>;
+ })}
+ {this._visible ? this.selectionContainer : null}
+
+ <div className="audiobox-current" ref={this._audioRef} onClick={e => { e.stopPropagation(); e.preventDefault(); }} style={{ left: `${NumCast(this.layoutDoc.currentTimecode) / this.audioDuration * 100}%`, pointerEvents: "none" }} />
+ {this.audio}
+ </div>
+ <div className="current-time">
+ {formatTime(Math.round(NumCast(this.layoutDoc.currentTimecode)))}
+ </div>
+ <div className="total-time">
+ {formatTime(Math.round(this.audioDuration))}
</div>
</div>
- }</div>
+ </div>
+ }
</div>;
}
}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index d92dc0ec2..ede0d8c99 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -879,31 +879,34 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
anchorPanelWidth = () => this.props.PanelWidth() || 1;
anchorPanelHeight = () => this.props.PanelHeight() || 1;
- @computed.struct get directLinks() { return LinkManager.Instance.getAllDirectLinks(this.Document); }
+ @computed.struct get directLinks() { return LinkManager.Instance.getAllDirectLinks(this.rootDoc); }
@computed.struct get allLinks() { return DocListCast(this.Document.links); }
@computed.struct get allAnchors() {
TraceMobx();
if (this.props.LayoutTemplateString?.includes("LinkAnchorBox")) return null;
- return (this.props.treeViewDoc && this.props.LayoutTemplateString) || // render nothing for: tree view anchor dots
+ if ((this.props.treeViewDoc && this.props.LayoutTemplateString) || // render nothing for: tree view anchor dots
this.layoutDoc.presBox || // presentationbox nodes
this.rootDoc.type === DocumentType.LINK ||
- this.props.dontRegisterView ? (null) : // view that are not registered
- DocUtils.FilterDocs(this.directLinks, this.props.docFilters(), []).filter(d => !d.hidden && this.isNonTemporalLink).map((d, i) =>
- <div className="documentView-anchorCont" key={i + 1}>
- <DocumentView {...this.props}
- Document={d}
- ContainingCollectionView={this.props.ContainingCollectionView}
- ContainingCollectionDoc={this.props.Document} // bcz: hack this.props.Document is not a collection Need a better prop for passing the containing document to the LinkAnchorBox
- PanelWidth={this.anchorPanelWidth}
- PanelHeight={this.anchorPanelHeight}
- ContentScaling={returnOne}
- dontRegisterView={false}
- forcedBackgroundColor={returnTransparent}
- removeDocument={this.hideLinkAnchor}
- pointerEvents={false}
- LayoutTemplate={undefined}
- LayoutTemplateString={LinkAnchorBox.LayoutString(`anchor${Doc.LinkEndpoint(d, this.props.Document)}`)} />
- </div >);
+ this.props.dontRegisterView) {// view that are not registered
+ return (null);
+ }
+ const filtered = DocUtils.FilterDocs(this.directLinks, this.props.docFilters(), []).filter(d => !d.hidden && this.isNonTemporalLink(d));
+ return filtered.map((d, i) =>
+ <div className="documentView-anchorCont" key={i + 1}>
+ <DocumentView {...this.props}
+ Document={d}
+ ContainingCollectionView={this.props.ContainingCollectionView}
+ ContainingCollectionDoc={this.props.Document} // bcz: hack this.props.Document is not a collection Need a better prop for passing the containing document to the LinkAnchorBox
+ PanelWidth={this.anchorPanelWidth}
+ PanelHeight={this.anchorPanelHeight}
+ ContentScaling={returnOne}
+ dontRegisterView={false}
+ forcedBackgroundColor={returnTransparent}
+ removeDocument={this.hideLinkAnchor}
+ pointerEvents={false}
+ LayoutTemplate={undefined}
+ LayoutTemplateString={LinkAnchorBox.LayoutString(`anchor${Doc.LinkEndpoint(d, this.props.Document)}`)} />
+ </div >);
}
@computed get innards() {
TraceMobx();
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index 3f2a590ab..9d61ec6d1 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -102,9 +102,10 @@ export class FieldView extends React.Component<FieldViewProps> {
else if (field instanceof VideoField) {
return <VideoBox {...this.props} />;
}
- else if (field instanceof AudioField) {
- return <AudioBox {...this.props} />;
- } else if (field instanceof DateField) {
+ // else if (field instanceof AudioField) {
+ // return <AudioBox {...this.props} />;
+ //}
+ else if (field instanceof DateField) {
return <p>{field.date.toLocaleString()}</p>;
}
else if (field instanceof Doc) {
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index 8c05d3603..54d79f4b8 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -34,7 +34,7 @@ import { DictationManager } from '../../../util/DictationManager';
import { DragManager } from "../../../util/DragManager";
import { makeTemplate } from '../../../util/DropConverter';
import buildKeymap, { updateBullets } from "./ProsemirrorExampleTransfer";
-import RichTextMenu from './RichTextMenu';
+import RichTextMenu, { RichTextMenuPlugin } from './RichTextMenu';
import { RichTextRules } from "./RichTextRules";
//import { DashDocView } from "./DashDocView";
@@ -304,18 +304,19 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
// for inserting timestamps
insertTime = () => {
+ let audioState;
if (this._first) {
- this._first = false;
DocListCast(this.dataDoc.links).map((l, i) => {
let la1 = l.anchor1 as Doc;
let la2 = l.anchor2 as Doc;
this._linkTime = NumCast(l.anchor2_timecode);
+ audioState = la2.audioState;
if (Doc.AreProtosEqual(la2, this.dataDoc)) {
la1 = l.anchor2 as Doc;
la2 = l.anchor1 as Doc;
this._linkTime = NumCast(l.anchor1_timecode);
+ audioState = la1.audioState;
}
-
});
}
this._currentTime = Date.now();
@@ -336,7 +337,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
}
}
}
- if (time) {
+ if (time && audioState === "recording") {
let value = "";
this._break = false;
value = this.layoutDoc._timeStampOnEnter ? "[" + time + "] " : "\n" + "[" + time + "] ";
@@ -1306,7 +1307,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
// jump rich text menu to this textbox
const bounds = this._ref.current?.getBoundingClientRect();
- if (bounds && this.layoutDoc._chromeStatus !== "disabled") {
+ if (bounds && this.layoutDoc._chromeStatus !== "disabled" && RichTextMenu.Instance) {
const x = Math.min(Math.max(bounds.left, 0), window.innerWidth - RichTextMenu.Instance.width);
let y = Math.min(Math.max(0, bounds.top - RichTextMenu.Instance.height - 50), window.innerHeight - RichTextMenu.Instance.height);
if (coords && coords.left > x && coords.left < x + RichTextMenu.Instance.width && coords.top > y && coords.top < y + RichTextMenu.Instance.height + 50) {
@@ -1410,11 +1411,14 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
}
}
+ menuPlugin: any;
+
richTextMenuPlugin() {
+ const self = this;
return new Plugin({
view(newView) {
- RichTextMenu.Instance?.changeView(newView);
- return RichTextMenu.Instance;
+ self.props.isSelected(true) && (RichTextMenu.Instance.view = newView);
+ return self.menuPlugin = new RichTextMenuPlugin({ editorProps: this.props });
}
});
}
@@ -1524,7 +1528,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
const scale = this.props.hideOnLeave ? 1 : this.props.ContentScaling() * NumCast(this.layoutDoc._viewScale, 1);
const rounded = StrCast(this.layoutDoc.borderRounding) === "100%" ? "-rounded" : "";
const interactive = Doc.GetSelectedTool() === InkTool.None && !this.layoutDoc.isBackground;
- setTimeout(() => this._editorView && RichTextMenu.Instance.updateFromDash(this._editorView, undefined, this.props), this.props.isSelected() ? 10 : 0); // need to make sure that we update a text box that is selected after updating the one that was deselected
+ setTimeout(() => this._editorView && RichTextMenu.Instance?.updateMenu(this._editorView, undefined, this.props), this.props.isSelected() ? 10 : 0); // need to make sure that we update a text box that is selected after updating the one that was deselected
if (!this.props.isSelected() && FormattedTextBoxComment.textBox === this) {
setTimeout(() => FormattedTextBoxComment.Hide(), 0);
}
diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx
index b683fb25d..e5cc62082 100644
--- a/src/client/views/nodes/formattedText/RichTextMenu.tsx
+++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx
@@ -16,7 +16,7 @@ import { unimplementedFunction, Utils } from "../../../../Utils";
import { DocServer } from "../../../DocServer";
import { LinkManager } from "../../../util/LinkManager";
import { SelectionManager } from "../../../util/SelectionManager";
-import AntimodeMenu from "../../AntimodeMenu";
+import AntimodeMenu, { AntimodeMenuProps } from "../../AntimodeMenu";
import { FieldViewProps } from "../FieldView";
import { FormattedTextBox, FormattedTextBoxProps } from "./FormattedTextBox";
import { updateBullets } from "./ProsemirrorExampleTransfer";
@@ -31,11 +31,11 @@ library.add(faBold, faItalic, faChevronLeft, faUnderline, faStrikethrough, faSup
@observer
-export default class RichTextMenu extends AntimodeMenu {
+export default class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> {
static Instance: RichTextMenu;
public overMenu: boolean = false; // kind of hacky way to prevent selects not being selectable
- private view?: EditorView;
+ public view?: EditorView;
public editorProps: FieldViewProps & FormattedTextBoxProps | undefined;
public _brushMap: Map<string, Set<Mark>> = new Map();
@@ -156,22 +156,8 @@ export default class RichTextMenu extends AntimodeMenu {
public delayHide = () => this._delayHide = true;
@action
- changeView(view: EditorView) {
- if ((view as any)?.TextView?.props.isSelected(true)) {
- this.view = view;
- }
- }
-
- update(view: EditorView, lastState: EditorState | undefined) {
- RichTextMenu.Instance.updateFromDash(view, lastState, this.editorProps);
- }
-
- @action
- public async updateFromDash(view: EditorView, lastState: EditorState | undefined, props: any) {
- RichTextMenu.Instance.finalUpdateFromDash(view, lastState, props);
- }
- public async finalUpdateFromDash(view: EditorView, lastState: EditorState | undefined, props: any) {
- if (!view || !(view as any).TextView?.props.isSelected(true)) {
+ public updateMenu(view: EditorView, lastState: EditorState | undefined, props: any) {
+ if (!view || !(view as any).TextView?.props.isSelected(true) || !view.hasFocus()) {
return;
}
this.view = view;
@@ -199,8 +185,7 @@ export default class RichTextMenu extends AntimodeMenu {
this.activeHighlightColor = !activeHighlights.length ? "" : activeHighlights.length === 1 ? String(activeHighlights[0]) : "...";
// update link in current selection
- const targetTitle = await this.getTextLinkTargetTitle();
- this.setCurrentLink(targetTitle);
+ this.getTextLinkTargetTitle().then(targetTitle => this.setCurrentLink(targetTitle));
}
setMark = (mark: Mark, state: EditorState<any>, dispatch: any, dontToggle: boolean = false) => {
@@ -1070,4 +1055,13 @@ export class ButtonDropdown extends React.Component<ButtonDropdownProps> {
</div>
);
}
+}
+
+
+interface RichTextMenuPluginProps {
+ editorProps: any;
+}
+export class RichTextMenuPlugin extends React.Component<RichTextMenuPluginProps> {
+ render() { return null; }
+ update(view: EditorView, lastState: EditorState | undefined) { RichTextMenu.Instance?.updateMenu(view, lastState, this.props.editorProps); }
} \ No newline at end of file
diff --git a/src/client/views/pdf/PDFMenu.tsx b/src/client/views/pdf/PDFMenu.tsx
index 7bea8d01b..bee282d9b 100644
--- a/src/client/views/pdf/PDFMenu.tsx
+++ b/src/client/views/pdf/PDFMenu.tsx
@@ -4,14 +4,14 @@ import { observable, action, computed, } from "mobx";
import { observer } from "mobx-react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { unimplementedFunction, returnFalse, Utils } from "../../../Utils";
-import AntimodeMenu from "../AntimodeMenu";
+import AntimodeMenu, { AntimodeMenuProps } from "../AntimodeMenu";
import { Doc, Opt } from "../../../fields/Doc";
import { ColorState } from "react-color";
import { ButtonDropdown } from "../nodes/formattedText/RichTextMenu";
@observer
-export default class PDFMenu extends AntimodeMenu {
+export default class PDFMenu extends AntimodeMenu<AntimodeMenuProps> {
static Instance: PDFMenu;
private _commentCont = React.createRef<HTMLButtonElement>();
diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx
index 770a03cb1..084449d04 100644
--- a/src/client/views/search/SearchBox.tsx
+++ b/src/client/views/search/SearchBox.tsx
@@ -604,13 +604,12 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
}
private get filterQuery() {
- const types = ["preselement", "docholder", "search", "searchitem", "script", "fonticonbox", "button", "label"]; // this.filterTypes;
- const baseExpr = "NOT baseProto_b:true AND NOT system_b:true";
+ const types = ["preselement", "docholder", "search", "searchitem", "fonticonbox"]; // this.filterTypes;
+ const baseExpr = "NOT system_b:true";
const includeDeleted = this.getDataStatus() ? "" : " NOT deleted_b:true";
- const includeIcons = this.getDataStatus() ? "" : " NOT type_t:fonticonbox";
const typeExpr = !types ? "" : ` ${types.map(type => `NOT ({!join from=id to=proto_i}type_t:${type}) AND NOT type_t:${type}`).join(" AND ")}`;
// fq: type_t:collection OR {!join from=id to=proto_i}type_t:collection q:text_t:hello
- const query = [baseExpr, includeDeleted, includeIcons, typeExpr].join(" AND ").replace(/AND $/, "");
+ const query = [baseExpr, includeDeleted, typeExpr].join(" AND ").replace(/AND $/, "");
return query;
}