aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorusodhi <61431818+usodhi@users.noreply.github.com>2021-03-13 16:40:26 -0500
committerusodhi <61431818+usodhi@users.noreply.github.com>2021-03-13 16:40:26 -0500
commit74c8b78c7119e700655338a32c03f2031186b238 (patch)
tree57baf33d9230b7ea6f77addf34becae8faeb63b0
parent70a5edc6e9a203141b16fd31ee9a1a26ebae2188 (diff)
parente20a8916483734bb06d08409b6bc804c2391a289 (diff)
minor changes
-rw-r--r--src/client/apis/youtube/YoutubeBox.tsx3
-rw-r--r--src/client/documents/Documents.ts7
-rw-r--r--src/client/util/CurrentUserUtils.ts6
-rw-r--r--src/client/util/DocumentManager.ts18
-rw-r--r--src/client/views/DocComponent.tsx9
-rw-r--r--src/client/views/DocumentDecorations.tsx2
-rw-r--r--src/client/views/GestureOverlay.tsx2
-rw-r--r--src/client/views/GlobalKeyHandler.ts7
-rw-r--r--src/client/views/InkingStroke.tsx9
-rw-r--r--src/client/views/MarqueeAnnotator.tsx2
-rw-r--r--src/client/views/PropertiesView.scss4
-rw-r--r--src/client/views/PropertiesView.tsx9
-rw-r--r--src/client/views/StyleProvider.tsx2
-rw-r--r--src/client/views/collections/CollectionDockingView.tsx13
-rw-r--r--src/client/views/collections/CollectionMenu.tsx6
-rw-r--r--src/client/views/collections/CollectionSchemaHeaders.tsx10
-rw-r--r--src/client/views/collections/CollectionStackingView.tsx3
-rw-r--r--src/client/views/collections/CollectionSubView.tsx2
-rw-r--r--src/client/views/collections/CollectionTreeView.tsx5
-rw-r--r--src/client/views/collections/CollectionView.tsx18
-rw-r--r--src/client/views/collections/TabDocView.tsx12
-rw-r--r--src/client/views/collections/TreeView.tsx55
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx13
-rw-r--r--src/client/views/collections/collectionFreeForm/MarqueeView.tsx2
-rw-r--r--src/client/views/nodes/ColorBox.tsx3
-rw-r--r--src/client/views/nodes/DocumentLinksButton.tsx13
-rw-r--r--src/client/views/nodes/DocumentView.tsx17
-rw-r--r--src/client/views/nodes/FilterBox.tsx12
-rw-r--r--src/client/views/nodes/KeyValueBox.tsx9
-rw-r--r--src/client/views/nodes/PDFBox.scss20
-rw-r--r--src/client/views/nodes/PDFBox.tsx112
-rw-r--r--src/client/views/nodes/PresBox.tsx2
-rw-r--r--src/client/views/nodes/ScreenshotBox.tsx3
-rw-r--r--src/client/views/nodes/VideoBox.tsx5
-rw-r--r--src/client/views/nodes/WebBox.tsx3
-rw-r--r--src/client/views/nodes/formattedText/DashDocView.tsx4
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.tsx32
-rw-r--r--src/client/views/pdf/AnchorMenu.tsx3
-rw-r--r--src/client/views/pdf/Annotation.tsx4
-rw-r--r--src/client/views/pdf/PDFViewer.scss10
-rw-r--r--src/client/views/pdf/PDFViewer.tsx20
-rw-r--r--src/client/views/webcam/DashWebRTCVideo.tsx3
-rw-r--r--src/fields/Doc.ts37
-rw-r--r--src/mobile/MobileInterface.tsx6
44 files changed, 340 insertions, 197 deletions
diff --git a/src/client/apis/youtube/YoutubeBox.tsx b/src/client/apis/youtube/YoutubeBox.tsx
index 2a1f55710..c5ff2db68 100644
--- a/src/client/apis/youtube/YoutubeBox.tsx
+++ b/src/client/apis/youtube/YoutubeBox.tsx
@@ -11,6 +11,7 @@ import "../../views/nodes/WebBox.scss";
import "./YoutubeBox.scss";
import React = require("react");
import { InkTool } from '../../../fields/InkField';
+import { CurrentUserUtils } from '../../util/CurrentUserUtils';
interface VideoTemplate {
thumbnailUrl: string;
@@ -350,7 +351,7 @@ export class YoutubeBox extends React.Component<FieldViewProps> {
const frozen = !this.props.isSelected() || DocumentDecorations.Instance.Interacting;
- const classname = "webBox-cont" + (this.props.isSelected() && Doc.GetSelectedTool() === InkTool.None && !DocumentDecorations.Instance.Interacting ? "-interactive" : "");
+ const classname = "webBox-cont" + (this.props.isSelected() && CurrentUserUtils.SelectedTool === InkTool.None && !DocumentDecorations.Instance.Interacting ? "-interactive" : "");
return (
<>
<div className={classname} >
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index d9ada89ea..e55527f84 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -59,6 +59,7 @@ import { DocumentType } from "./DocumentTypes";
import { EquationBox } from "../views/nodes/EquationBox";
import { FunctionPlotBox } from "../views/nodes/FunctionPlotBox";
import { script } from "googleapis/build/src/apis/script";
+import { CurrentUserUtils } from "../util/CurrentUserUtils";
const path = require('path');
const defaultNativeImageDim = Number(DFLT_IMAGE_NATIVE_DIM.replace("px", ""));
@@ -663,7 +664,7 @@ export namespace Docs {
viewDoc["acl-Public"] = dataDoc["acl-Public"] = Doc.UserDoc()?.defaultAclPrivate ? SharingPermissions.None : SharingPermissions.Add;
viewDoc["acl-Override"] = dataDoc["acl-Override"] = "None";
- !Doc.IsSystem(dataDoc) && ![DocumentType.PDFANNO, DocumentType.LINK, DocumentType.LINKANCHOR, DocumentType.TEXTANCHOR].includes(proto.type as any) &&
+ !Doc.IsSystem(dataDoc) && ![DocumentType.PDFANNO, DocumentType.KVP, DocumentType.LINK, DocumentType.LINKANCHOR, DocumentType.TEXTANCHOR].includes(proto.type as any) &&
!dataDoc.isFolder && !protoProps.annotationOn && Doc.AddDocToList(Cast(Doc.UserDoc().myFileOrphans, Doc, null), "data", dataDoc);
return Doc.assign(viewDoc, delegateProps, true);
@@ -1174,7 +1175,7 @@ export namespace DocUtils {
created = Docs.Create.AudioDocument((field).url.href, resolved);
layout = AudioBox.LayoutString;
} else if (field instanceof InkField) {
- created = Docs.Create.InkDocument(ActiveInkColor(), Doc.GetSelectedTool(), ActiveInkWidth(), ActiveInkBezierApprox(), ActiveFillColor(), ActiveArrowStart(), ActiveArrowEnd(), ActiveDash(), (field).inkData, resolved);
+ created = Docs.Create.InkDocument(ActiveInkColor(), CurrentUserUtils.SelectedTool, ActiveInkWidth(), ActiveInkBezierApprox(), ActiveFillColor(), ActiveArrowStart(), ActiveArrowEnd(), ActiveDash(), (field).inkData, resolved);
layout = InkingStroke.LayoutString;
} else if (field instanceof List && field[0] instanceof Doc) {
created = Docs.Create.StackingDocument(DocListCast(field), resolved);
@@ -1436,4 +1437,4 @@ Scripting.addGlobal(function generateLinkTitle(self: Doc) {
const anchor2title = self.anchor2 && self.anchor2 !== self ? Cast(self.anchor2, Doc, null).title : "<?>";
const relation = self.linkRelationship || "to";
return `${anchor1title} (${relation}) ${anchor2title}`;
-}) \ No newline at end of file
+}); \ No newline at end of file
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 3d53ad134..aafb986be 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -1,4 +1,4 @@
-import { computed, observable, reaction } from "mobx";
+import { computed, observable, reaction, action } from "mobx";
import * as rp from 'request-promise';
import { DataSym, Doc, DocListCast, DocListCastAsync, AclReadonly } from "../../fields/Doc";
import { Id } from "../../fields/FieldSymbols";
@@ -33,6 +33,8 @@ import { SearchUtil } from "./SearchUtil";
import { SelectionManager } from "./SelectionManager";
import { UndoManager } from "./UndoManager";
import { SnappingManager } from "./SnappingManager";
+import { InkTool } from "../../fields/InkField";
+import { computedFn } from "mobx-utils";
export let resolvedPorts: { server: number, socket: number };
@@ -1214,6 +1216,8 @@ export class CurrentUserUtils {
public static get MyDashboards() { return Cast(Doc.UserDoc().myDashboards, Doc, null); }
public static get EmptyPane() { return Cast(Doc.UserDoc().emptyPane, Doc, null); }
public static get OverlayDocs() { return DocListCast((Doc.UserDoc().myOverlayDocs as Doc)?.data); }
+ public static set SelectedTool(tool: InkTool) { Doc.UserDoc().activeInkTool = tool; }
+ @computed public static get SelectedTool(): InkTool { return StrCast(Doc.UserDoc().activeInkTool, InkTool.None) as InkTool; }
}
Scripting.addGlobal(function openDragFactory(dragFactory: Doc) {
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index 969eed701..8cb80ecf9 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -9,9 +9,6 @@ import { CollectionView } from '../views/collections/CollectionView';
import { LightboxView } from '../views/LightboxView';
import { DocumentView, ViewAdjustment } from '../views/nodes/DocumentView';
import { Scripting } from './Scripting';
-import { CurrentUserUtils } from './CurrentUserUtils';
-import { TabDocView } from '../views/collections/TabDocView';
-import { UndoManager } from './UndoManager';
export class DocumentManager {
@@ -160,12 +157,15 @@ export class DocumentManager {
return false;
};
const annotatedDoc = Cast(targetDoc.annotationOn, Doc, null);
- const rtfView = annotatedDoc && getFirstDocView(annotatedDoc);
+ const annoContainerView = annotatedDoc && getFirstDocView(annotatedDoc);
const contextDocs = docContext ? await DocListCastAsync(docContext.data) : undefined;
const contextDoc = contextDocs?.find(doc => Doc.AreProtosEqual(doc, targetDoc) || Doc.AreProtosEqual(doc, annotatedDoc)) ? docContext : undefined;
const targetDocContext = contextDoc || annotatedDoc;
const targetDocContextView = targetDocContext && getFirstDocView(targetDocContext);
- const focusView = !docView && targetDoc.type === DocumentType.TEXTANCHOR && rtfView ? rtfView : docView;
+ const focusView = !docView && targetDoc.type === DocumentType.TEXTANCHOR && annoContainerView ? annoContainerView : docView;
+ if (!docView && annoContainerView && !focusView) {
+ annoContainerView.focus(targetDoc); // this allows something like a PDF view to remove its doc filters to expose the target so that it can be found in the retry code below
+ }
if (focusView) {
focusView && Doc.linkFollowHighlight(focusView.rootDoc);
focusView.focus(targetDoc, {
@@ -181,7 +181,12 @@ export class DocumentManager {
} else { // otherwise try to get a view of the context of the target
if (targetDocContextView) { // we found a context view and aren't forced to create a new one ... focus on the context first..
targetDocContext._viewTransition = "transform 500ms";
- targetDocContextView.props.focus(targetDocContextView.rootDoc, { willZoom });
+ targetDocContextView.props.focus(targetDocContextView.rootDoc, {
+ willZoom, afterFocus: async () => {
+ targetDocContext._viewTransition = undefined;
+ return ViewAdjustment.doNothing;
+ }
+ });
// now find the target document within the context
if (targetDoc._timecodeToShow) { // if the target has a timecode, it should show up once the (presumed) video context scrubs to the display timecode;
@@ -191,6 +196,7 @@ export class DocumentManager {
const findView = (delay: number) => {
const retryDocView = getFirstDocView(targetDoc); // test again for the target view snce we presumably created the context above by focusing on it
if (retryDocView) { // we found the target in the context
+ Doc.linkFollowHighlight(retryDocView.rootDoc);
retryDocView.props.focus(targetDoc, {
willZoom, afterFocus: (didFocus: boolean) =>
new Promise<ViewAdjustment>(res => {
diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx
index 6480c6507..589cfafc5 100644
--- a/src/client/views/DocComponent.tsx
+++ b/src/client/views/DocComponent.tsx
@@ -8,6 +8,7 @@ import { List } from '../../fields/List';
import { DateField } from '../../fields/DateField';
import { ScriptField } from '../../fields/ScriptField';
import { GetEffectiveAcl, SharingPermissions, distributeAcls, denormalizeEmail } from '../../fields/util';
+import { CurrentUserUtils } from '../util/CurrentUserUtils';
/// DocComponent returns a generic React base class used by views that don't have 'fieldKey' props (e.g.,CollectionFreeFormDocumentView, DocumentView)
@@ -189,7 +190,9 @@ export function ViewBoxAnnotatableComponent<P extends ViewBoxAnnotatableProps, T
}
else {
added.map(doc => doc.context = this.props.Document);
- (targetDataDoc[annotationKey ?? this.annotationKey] as List<Doc>).push(...added);
+ const annoDocs = targetDataDoc[annotationKey ?? this.annotationKey] as List<Doc>;
+ if (annoDocs) annoDocs.push(...added);
+ else targetDataDoc[annotationKey ?? this.annotationKey] = new List<Doc>(added);
targetDataDoc[(annotationKey ?? this.annotationKey) + "-lastModified"] = new DateField(new Date(Date.now()));
}
}
@@ -198,9 +201,9 @@ export function ViewBoxAnnotatableComponent<P extends ViewBoxAnnotatableProps, T
}
whenActiveChanged = action((isActive: boolean) => this.props.whenActiveChanged(this._isChildActive = isActive));
- active = (outsideReaction?: boolean) => ((Doc.GetSelectedTool() === InkTool.None && !this.props.Document._) &&
+ active = (outsideReaction?: boolean) => ((CurrentUserUtils.SelectedTool === InkTool.None && !this.props.Document._) &&
(this.props.rootSelected(outsideReaction) || this.props.isSelected(outsideReaction) || this._isChildActive || this.props.renderDepth === 0 || BoolCast((this.layoutDoc as any).forceActive)) ? true : false)
- annotationsActive = (outsideReaction?: boolean) => (Doc.GetSelectedTool() !== InkTool.None || (this.props.layerProvider?.(this.props.Document) === false && this.props.active()) ||
+ annotationsActive = (outsideReaction?: boolean) => (CurrentUserUtils.SelectedTool !== InkTool.None || (this.props.layerProvider?.(this.props.Document) === false && this.props.active()) ||
(this.props.Document.forceActive || this.props.isSelected(outsideReaction) || this._isChildActive || this.props.renderDepth === 0) ? true : false)
}
return Component;
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index c263c5cf5..6d8bd30be 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -458,7 +458,7 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b
top: bounds.y - this._resizeBorderWidth / 2 - this._titleHeight,
}}>
{!canDelete ? <div /> : topBtn("close", "times", this.onCloseClick, "Close")}
- {seldoc.props.Document.type === DocumentType.EQUATION ? (null) : titleArea}
+ {seldoc.props.hideDecorationTitle || seldoc.props.Document.type === DocumentType.EQUATION ? (null) : titleArea}
{seldoc.props.hideResizeHandles || seldoc.props.Document.type === DocumentType.EQUATION ? (null) :
<>
{SelectionManager.Views().length !== 1 || seldoc.Document.type === DocumentType.INK ? (null) :
diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx
index b4051194f..093e01a19 100644
--- a/src/client/views/GestureOverlay.tsx
+++ b/src/client/views/GestureOverlay.tsx
@@ -491,7 +491,7 @@ export class GestureOverlay extends Touchable {
@action
onPointerDown = (e: React.PointerEvent) => {
- if (InteractionUtils.IsType(e, InteractionUtils.PENTYPE) || (Doc.GetSelectedTool() === InkTool.Highlighter || Doc.GetSelectedTool() === InkTool.Pen)) {
+ if (InteractionUtils.IsType(e, InteractionUtils.PENTYPE) || [InkTool.Highlighter, InkTool.Pen].includes(CurrentUserUtils.SelectedTool)) {
this._points.push({ X: e.clientX, Y: e.clientY });
setupMoveUpEvents(this, e, this.onPointerMove, this.onPointerUp, emptyFunction);
}
diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts
index 20bba1299..bd67735a8 100644
--- a/src/client/views/GlobalKeyHandler.ts
+++ b/src/client/views/GlobalKeyHandler.ts
@@ -28,10 +28,8 @@ import { MainView } from "./MainView";
import { DocumentLinksButton } from "./nodes/DocumentLinksButton";
import { AnchorMenu } from "./pdf/AnchorMenu";
import { SearchBox } from "./search/SearchBox";
-import { random } from "lodash";
-import { DocumentView } from "./nodes/DocumentView";
+import { CurrentUserUtils } from "../util/CurrentUserUtils";
import { SettingsManager } from "../util/SettingsManager";
-import { AudioBox } from "./nodes/AudioBox";
const modifiers = ["control", "meta", "shift", "alt"];
type KeyHandler = (keycode: string, e: KeyboardEvent) => KeyControlInfo | Promise<KeyControlInfo>;
@@ -119,8 +117,7 @@ export class KeyManager {
DocumentLinksButton.StartLink = undefined;
DocumentLinksButton.StartLinkView = undefined;
InkStrokeProperties.Instance && (InkStrokeProperties.Instance._controlBtn = false);
-
- Doc.SetSelectedTool(InkTool.None);
+ CurrentUserUtils.SelectedTool = InkTool.None;
var doDeselect = true;
if (SnappingManager.GetIsDragging()) {
DragManager.AbortDrag();
diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx
index 462d78865..46586bf1b 100644
--- a/src/client/views/InkingStroke.tsx
+++ b/src/client/views/InkingStroke.tsx
@@ -17,6 +17,7 @@ import "./InkingStroke.scss";
import { FieldView, FieldViewProps } from "./nodes/FieldView";
import React = require("react");
import { InkStrokeProperties } from "./InkStrokeProperties";
+import { CurrentUserUtils } from "../util/CurrentUserUtils";
type InkDocument = makeInterface<[typeof documentSchema]>;
const InkDocument = makeInterface(documentSchema);
@@ -242,7 +243,7 @@ export function ActiveDash(): string { return StrCast(ActiveInkPen()?.activeDash
export function ActiveInkWidth(): string { return StrCast(ActiveInkPen()?.activeInkWidth, "1"); }
export function ActiveInkBezierApprox(): string { return StrCast(ActiveInkPen()?.activeInkBezier); }
Scripting.addGlobal(function activateBrush(pen: any, width: any, color: any, fill: any, arrowStart: any, arrowEnd: any, dash: any) {
- Doc.SetSelectedTool(pen ? InkTool.Highlighter : InkTool.None);
+ CurrentUserUtils.SelectedTool = pen ? InkTool.Highlighter : InkTool.None;
SetActiveInkWidth(width);
SetActiveInkColor(color);
SetActiveFillColor(fill);
@@ -250,9 +251,9 @@ Scripting.addGlobal(function activateBrush(pen: any, width: any, color: any, fil
SetActiveArrowEnd(arrowEnd);
SetActiveDash(dash);
});
-Scripting.addGlobal(function activateEraser(pen: any) { return Doc.SetSelectedTool(pen ? InkTool.Eraser : InkTool.None); });
-Scripting.addGlobal(function activateStamp(pen: any) { return Doc.SetSelectedTool(pen ? InkTool.Stamp : InkTool.None); });
-Scripting.addGlobal(function deactivateInk() { return Doc.SetSelectedTool(InkTool.None); });
+Scripting.addGlobal(function activateEraser(pen: any) { return CurrentUserUtils.SelectedTool = pen ? InkTool.Eraser : InkTool.None; });
+Scripting.addGlobal(function activateStamp(pen: any) { return CurrentUserUtils.SelectedTool = pen ? InkTool.Stamp : InkTool.None; });
+Scripting.addGlobal(function deactivateInk() { return CurrentUserUtils.SelectedTool = InkTool.None; });
Scripting.addGlobal(function setInkWidth(width: any) { return SetActiveInkWidth(width); });
Scripting.addGlobal(function setInkColor(color: any) { return SetActiveInkColor(color); });
Scripting.addGlobal(function setFillColor(fill: any) { return SetActiveFillColor(fill); });
diff --git a/src/client/views/MarqueeAnnotator.tsx b/src/client/views/MarqueeAnnotator.tsx
index 63439586c..503c284aa 100644
--- a/src/client/views/MarqueeAnnotator.tsx
+++ b/src/client/views/MarqueeAnnotator.tsx
@@ -29,6 +29,7 @@ export interface MarqueeAnnotatorProps {
addDocument: (doc: Doc) => boolean;
getPageFromScroll?: (top: number) => number;
finishMarquee: () => void;
+ anchorMenuClick?: (anchor: Doc) => void;
}
@observer
export class MarqueeAnnotator extends React.Component<MarqueeAnnotatorProps> {
@@ -59,6 +60,7 @@ export class MarqueeAnnotator extends React.Component<MarqueeAnnotatorProps> {
document.addEventListener("pointermove", this.onSelectMove);
document.addEventListener("pointerup", this.onSelectEnd);
+ AnchorMenu.Instance.OnClick = (e: PointerEvent) => this.props.anchorMenuClick?.(this.highlight("rgba(173, 216, 230, 0.75)", true));
AnchorMenu.Instance.Highlight = this.highlight;
/**
* This function is used by the AnchorMenu to create an anchor highlight and a new linked text annotation.
diff --git a/src/client/views/PropertiesView.scss b/src/client/views/PropertiesView.scss
index 134c50972..1d52136de 100644
--- a/src/client/views/PropertiesView.scss
+++ b/src/client/views/PropertiesView.scss
@@ -191,8 +191,8 @@
font-size: 10px;
padding: 10px;
margin-left: 5px;
- max-height: 40%;
- overflow-y: auto;
+ // max-height: 40%;
+ overflow-y: visible;
.propertiesView-buttonContainer {
float: right;
diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx
index 499d8ff0c..128256733 100644
--- a/src/client/views/PropertiesView.tsx
+++ b/src/client/views/PropertiesView.tsx
@@ -900,10 +900,17 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
</div>;
}
+ /**
+ * Checks if a currentFilter (FilterDoc) exists on the current collection (if the Properties Panel + Filters submenu are open).
+ * If it doesn't exist, it creates it.
+ */
checkFilterDoc() {
if (this.filterDoc.type === DocumentType.COL && !this.filterDoc.currentFilter) CurrentUserUtils.setupFilterDocs(this.filterDoc);
}
+ /**
+ * Creates a new currentFilter for this.filterDoc,
+ */
createNewFilterDoc = () => {
const temp = this.filterDoc._docFilters;
this.filterDoc._docFilters = new List<string>();
@@ -946,7 +953,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
removeDocument={returnFalse}
ScreenToLocalTransform={this.getTransform}
PanelWidth={this.docWidth}
- PanelHeight={this.docHeight}
+ PanelHeight={() => this.docHeight}
renderDepth={0}
scriptContext={this.filterDoc.currentFilter as Doc}
focus={emptyFunction}
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index 0dd0cd969..2585db046 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -78,7 +78,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<FieldViewProps |
case StyleProp.DocContents: return undefined;
case StyleProp.WidgetColor: return isAnnotated ? "lightBlue" : darkScheme() ? "lightgrey" : "dimgrey";
case StyleProp.Opacity: return Cast(doc?._opacity, "number", Cast(doc?.opacity, "number", null));
- case StyleProp.HideLinkButton: return isAnchor || props?.dontRegisterView || ((!selected || doc?.type == DocumentType.PDFANNO) && (doc?.isLinkButton || doc?.hideLinkButton));
+ case StyleProp.HideLinkButton: return isAnchor || props?.dontRegisterView || ((!selected || doc?.type === DocumentType.PDFANNO) && (doc?.isLinkButton || doc?.hideLinkButton));
case StyleProp.ShowTitle: return doc && !doc.presentationTargetDoc && StrCast(doc._showTitle,
!Doc.IsSystem(doc) && doc.type === DocumentType.RTF ?
(doc.author === Doc.CurrentUserEmail ? StrCast(Doc.UserDoc().showTitle) : "author;creationDate") : "") || "";
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 0c8e26e91..3556e74bc 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -337,7 +337,7 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) {
}
}
if (!e.nativeEvent.cancelBubble && !InteractionUtils.IsType(e, InteractionUtils.TOUCHTYPE) && !InteractionUtils.IsType(e, InteractionUtils.PENTYPE) &&
- Doc.GetSelectedTool() !== InkTool.Highlighter && Doc.GetSelectedTool() !== InkTool.Pen) {
+ ![InkTool.Highlighter, InkTool.Pen].includes(CurrentUserUtils.SelectedTool)) {
e.stopPropagation();
}
}
@@ -372,16 +372,17 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) {
this.props.Document.dockingConfig = json;
setTimeout(async () => {
- const sublists = DocListCast(this.props.Document[this.props.fieldKey]);
- const tabs = Cast(sublists[0], Doc, null);
- const other = Cast(sublists[1], Doc, null);
+ const sublists = await DocListCastAsync(this.props.Document[this.props.fieldKey]);
+ const tabs = sublists && Cast(sublists[0], Doc, null);
+ const other = sublists && Cast(sublists[1], Doc, null);
const tabdocs = await DocListCastAsync(tabs?.data);
const otherdocs = await DocListCastAsync(other?.data);
tabs && (Doc.GetProto(tabs).data = new List<Doc>(docs));
const otherSet = new Set<Doc>();
otherdocs?.filter(doc => !docs.includes(doc)).forEach(doc => otherSet.add(doc));
- tabdocs?.filter(doc => !docs.includes(doc)).forEach(doc => otherSet.add(doc));
- other && (Doc.GetProto(other).data = new List<Doc>(Array.from(otherSet.values())));
+ tabdocs?.filter(doc => !docs.includes(doc) && doc.type !== DocumentType.KVP).forEach(doc => otherSet.add(doc));
+ const vals = Array.from(otherSet.values()).filter(val => val instanceof Doc).map(d => d as Doc).filter(d => d.type !== DocumentType.KVP);
+ other && (Doc.GetProto(other).data = new List<Doc>(vals));
}, 0);
}
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index 591b4161e..51a67ea7d 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -603,7 +603,7 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionMenu
@action clearKeepPrimitiveMode() { this._selectedPrimitive = this._shapePrims.length; }
@action primCreated() {
if (!this._keepPrimitiveMode) { //get out of ink mode after each stroke=
- Doc.SetSelectedTool(InkTool.None);
+ CurrentUserUtils.SelectedTool = InkTool.None;
this._selectedPrimitive = this._shapePrims.length;
SetActiveArrowStart("none");
SetActiveArrowEnd("none");
@@ -643,7 +643,7 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionMenu
this._keepPrimitiveMode = keep;
if (this._selectedPrimitive !== i) {
this._selectedPrimitive = i;
- Doc.SetSelectedTool(InkTool.Pen);
+ CurrentUserUtils.SelectedTool = InkTool.Pen;
SetActiveArrowStart(this._head[i]);
SetActiveArrowEnd(this._end[i]);
SetActiveBezierApprox("300");
@@ -651,7 +651,7 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionMenu
GestureOverlay.Instance.InkShape = this._shapePrims[i];
} else {
this._selectedPrimitive = this._shapePrims.length;
- Doc.SetSelectedTool(InkTool.None);
+ CurrentUserUtils.SelectedTool = InkTool.None;
SetActiveArrowStart("");
SetActiveArrowEnd("");
GestureOverlay.Instance.InkShape = "";
diff --git a/src/client/views/collections/CollectionSchemaHeaders.tsx b/src/client/views/collections/CollectionSchemaHeaders.tsx
index f50da0134..3b52e6408 100644
--- a/src/client/views/collections/CollectionSchemaHeaders.tsx
+++ b/src/client/views/collections/CollectionSchemaHeaders.tsx
@@ -283,11 +283,11 @@ export class KeysDropdown extends React.Component<KeysDropdownProps> {
const colpos = this._searchTerm.indexOf(":");
const temp = this._searchTerm.slice(colpos + 1, this._searchTerm.length);
if (temp === "") {
- Doc.setDocFilter(this.props.Document, this._key, this.tempfilter, undefined);
+ Doc.setDocFilter(this.props.Document, this._key, this.tempfilter, "remove");
this.updateFilter();
}
else {
- Doc.setDocFilter(this.props.Document, this._key, this.tempfilter, undefined);
+ Doc.setDocFilter(this.props.Document, this._key, this.tempfilter, "remove");
this.tempfilter = temp;
Doc.setDocFilter(this.props.Document, this._key, temp, "check");
this.props.col.setColor("green");
@@ -295,7 +295,7 @@ export class KeysDropdown extends React.Component<KeysDropdownProps> {
}
}
else {
- Doc.setDocFilter(this.props.Document, this._key, this.tempfilter, undefined);
+ Doc.setDocFilter(this.props.Document, this._key, this.tempfilter, "remove");
this.updateFilter();
if (this.showKeys.length) {
this.onSelect(this.showKeys[0]);
@@ -421,10 +421,10 @@ export class KeysDropdown extends React.Component<KeysDropdownProps> {
onPointerDown={e => e.stopPropagation()}
onClick={e => e.stopPropagation()}
onChange={(e) => {
- e.target.checked === true ? Doc.setDocFilter(this.props.Document, this._key, key, "check") : Doc.setDocFilter(this.props.Document, this._key, key, undefined);
+ e.target.checked === true ? Doc.setDocFilter(this.props.Document, this._key, key, "check") : Doc.setDocFilter(this.props.Document, this._key, key, "remove");
e.target.checked === true ? this.closeResultsVisibility = "contents" : console.log("");
e.target.checked === true ? this.props.col.setColor("green") : this.updateFilter();
- e.target.checked === true && SearchBox.Instance.filter === true ? Doc.setDocFilter(docs[0], this._key, key, "check") : Doc.setDocFilter(docs[0], this._key, key, undefined);
+ e.target.checked === true && SearchBox.Instance.filter === true ? Doc.setDocFilter(docs[0], this._key, key, "check") : Doc.setDocFilter(docs[0], this._key, key, "remove");
}}
checked={bool}
/>
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 10494e3e2..df39ed3e1 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -233,6 +233,8 @@ export class CollectionStackingView extends CollectionSubView<StackingDocument,
ScreenToLocalTransform={stackedDocTransform}
focus={this.focusDocument}
docFilters={this.docFilters}
+ hideDecorationTitle={this.props.childHideDecorationTitle?.()}
+ hideTitle={this.props.childHideTitle?.()}
docRangeFilters={this.docRangeFilters}
searchFilterDocs={this.searchFilterDocs}
ContainingCollectionDoc={this.props.CollectionView?.props.Document}
@@ -517,6 +519,7 @@ export class CollectionStackingView extends CollectionSubView<StackingDocument,
height: `${1 / this.scaling * 100}%`,
width: `${1 / this.scaling * 100}%`,
transformOrigin: "top left",
+ background: this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor),
pointerEvents: this.backgroundEvents ? "all" : undefined
}}
onScroll={action(e => this._scroll = e.currentTarget.scrollTop)}
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index b82644128..f226cf79b 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -66,7 +66,7 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
@computed get dataField() {
// sets the dataDoc's data field to an empty list if the data field is undefined - prevents issues with addonly
// setTimeout changes it outside of the @computed section
- !this.dataDoc[this.props.fieldKey] && setTimeout(() => this.dataDoc[this.props.fieldKey] = new List<Doc>());
+ !this.dataDoc[this.props.fieldKey] && setTimeout(() => !this.dataDoc[this.props.fieldKey] && (this.dataDoc[this.props.fieldKey] = new List<Doc>()));
return this.dataDoc[this.props.fieldKey];
}
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 0a4422cbd..f5eb534aa 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -193,7 +193,10 @@ export class
/>
</div>;
}
-
+ @computed get treeViewtruncateTitleWidth() { return NumCast(this.doc.treeViewTruncateTitleWidth, this.panelWidth()); }
+ truncateTitleWidth = () => this.treeViewtruncateTitleWidth;
+ @computed get outlineMode() { return this.doc.treeViewType === "outline"; }
+ @computed get fileSysMode() { return this.doc.treeViewType === "fileSystem"; }
onChildClick = () => this.props.onChildClick?.() || ScriptCast(this.doc.onChildClick);
whenActiveChanged = (isActive: boolean) => { this.props.whenActiveChanged(this._isChildActive = isActive); };
active = (outsideReaction: boolean | undefined) => this.props.active(outsideReaction) || this._isChildActive;
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 857982782..be5a4b852 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -72,6 +72,8 @@ export interface CollectionViewProps extends FieldViewProps {
children?: never | (() => JSX.Element[]) | React.ReactNode;
childDocuments?: Doc[]; // used to override the documents shown by the sub collection to an explicit list (see LinkBox)
childOpacity?: () => number;
+ childHideTitle?: () => boolean; // whether to hide the documentdecorations title for children
+ childHideDecorationTitle?: () => boolean;
childLayoutTemplate?: () => (Doc | undefined);// specify a layout Doc template to use for children of the collection
childLayoutString?: string;
childFreezeDimensions?: boolean; // used by TimeView to coerce documents to treat their width height as their native width/height
@@ -102,13 +104,15 @@ export class CollectionView extends Touchable<CollectionViewProps> {
return viewField as any as CollectionViewType;
}
- active = (outsideReaction?: boolean) => (this.props.isSelected(outsideReaction) ||
- this.props.rootSelected(outsideReaction) ||
- (this.props.layerProvider?.(this.props.Document) !== false && (this.props.Document.forceActive || this.props.Document._isGroup)) ||
- this._isChildActive ||
- this.props.renderDepth === 0) ?
- true :
- false
+ active = (outsideReaction?: boolean) => {
+ return this.props.renderDepth === 0 ||
+ this.props.isSelected(outsideReaction) ||
+ this.props.rootSelected(outsideReaction) ||
+ (this.props.layerProvider?.(this.props.Document) !== false && (this.props.Document.forceActive || this.props.Document._isGroup)) ||
+ this._isChildActive ?
+ true :
+ false;
+ }
whenActiveChanged = (isActive: boolean) => this.props.whenActiveChanged(this._isChildActive = isActive);
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index f7e067399..2ead98aa4 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -213,7 +213,6 @@ export class TabDocView extends React.Component<TabDocViewProps> {
}
componentDidMount() {
- const selected = () => SelectionManager.Views().some(v => v.props.Document === this._document);
new _global.ResizeObserver(action((entries: any) => {
for (const entry of entries) {
this._panelWidth = entry.contentRect.width;
@@ -221,7 +220,7 @@ export class TabDocView extends React.Component<TabDocViewProps> {
}
})).observe(this.props.glContainer._element[0]);
this.props.glContainer.layoutManager.on("activeContentItemChanged", this.onActiveContentItemChanged);
- this.props.glContainer.tab?.isActive && this.onActiveContentItemChanged();
+ this.props.glContainer.tab?.isActive && this.onActiveContentItemChanged(undefined);
this._tabReaction = reaction(() => ({ selected: this.active(), title: this.tab?.titleElement[0] }),
({ selected, title }) => title && (title.style.backgroundColor = selected ? "white" : ""),
{ fireImmediately: true });
@@ -229,13 +228,15 @@ export class TabDocView extends React.Component<TabDocViewProps> {
componentWillUnmount() {
this._tabReaction?.();
+ this.tab && CollectionDockingView.Instance.tabMap.delete(this.tab);
+
this.props.glContainer.layoutManager.off("activeContentItemChanged", this.onActiveContentItemChanged);
}
@action.bound
- private onActiveContentItemChanged() {
- if (this.props.glContainer.tab && this._isActive !== this.props.glContainer.tab.isActive) {
- this._isActive = this.props.glContainer.tab.isActive;
+ private onActiveContentItemChanged(contentItem: any) {
+ if (!contentItem || (this.stack === contentItem.parent && ((contentItem?.tab === this.tab && !this._isActive) || (contentItem?.tab !== this.tab && this._isActive)))) {
+ this._activated = this._isActive = !contentItem || contentItem?.tab === this.tab;
(CollectionDockingView.Instance as any)._goldenLayout?.isInitialised && CollectionDockingView.Instance.stateChanged();
!this._isActive && this._document && Doc.UnBrushDoc(this._document); // bcz: bad -- trying to simulate a pointer leave event when a new tab is opened up on top of an existing one.
}
@@ -344,6 +345,7 @@ export class TabDocView extends React.Component<TabDocViewProps> {
}
render() {
+ this.tab && CollectionDockingView.Instance.tabMap.delete(this.tab);
return (
<div className="collectionDockingView-content" style={{ height: "100%", width: "100%" }} ref={ref => {
if (this._mainCont = ref) {
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index 67a992df2..1d14c63c7 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -32,6 +32,9 @@ import { CollectionTreeView } from './CollectionTreeView';
import { CollectionView, CollectionViewType } from './CollectionView';
import "./TreeView.scss";
import React = require("react");
+import { ContextMenu } from '../ContextMenu';
+import { ContextMenuProps } from '../ContextMenuItem';
+import { SharingManager } from '../../util/SharingManager';
export interface TreeViewProps {
document: Doc;
@@ -101,12 +104,10 @@ export class TreeView extends React.Component<TreeViewProps> {
@observable _dref: DocumentView | undefined | null;
get displayName() { return "TreeView(" + this.props.document.title + ")"; } // this makes mobx trace() statements more descriptive
get treeViewLockExpandedView() { return this.doc.treeViewLockExpandedView; }
- get defaultExpandedView() { return StrCast(this.doc.treeViewDefaultExpandedView, this.fileSysMode ? (this.doc.isFolder ? "data" : "aliases") : Doc.UserDoc().noviceMode || this.outlineMode ? "layout" : "fields"); }
- get treeViewDefaultExpandedView() { return this.treeViewLockExpandedView ? this.defaultExpandedView : (this.childDocs && !this.fileSysMode ? this.fieldKey : this.defaultExpandedView); }
+ get defaultExpandedView() { return StrCast(this.doc.treeViewDefaultExpandedView, this.props.treeView.fileSysMode ? (this.doc.isFolder ? "data" : "aliases") : Doc.UserDoc().noviceMode || this.props.treeView.outlineMode ? "layout" : "fields"); }
+ get treeViewDefaultExpandedView() { return this.treeViewLockExpandedView ? this.defaultExpandedView : (this.childDocs && !this.props.treeView.fileSysMode ? this.fieldKey : this.defaultExpandedView); }
@computed get doc() { TraceMobx(); return this.props.document; }
- @computed get outlineMode() { return this.props.treeView.doc.treeViewType === "outline"; }
- @computed get fileSysMode() { return this.props.treeView.doc.treeViewType === "fileSystem"; }
@computed get treeViewOpen() { return (!this.props.treeViewPreventOpen && !this.doc.treeViewPreventOpen && Doc.GetT(this.doc, "treeViewOpen", "boolean", true)) || this._overrideTreeViewOpen; }
@computed get treeViewExpandedView() { return StrCast(this.doc.treeViewExpandedView, this.treeViewDefaultExpandedView); }
@computed get MAX_EMBED_HEIGHT() { return NumCast(this.props.containingCollection.maxEmbedHeight, 200); }
@@ -252,7 +253,7 @@ export class TreeView extends React.Component<TreeViewProps> {
const pt = [de.x, de.y];
const rect = this._header!.current!.getBoundingClientRect();
const before = pt[1] < rect.top + rect.height / 2;
- const inside = this.fileSysMode && !this.doc.isFolder ? false : pt[0] > Math.min(rect.left + 75, rect.left + rect.width * .75) || (!before && this.treeViewOpen && this.childDocList.length);
+ const inside = this.props.treeView.fileSysMode && !this.doc.isFolder ? false : pt[0] > Math.min(rect.left + 75, rect.left + rect.width * .75) || (!before && this.treeViewOpen && this.childDocList.length);
if (de.complete.linkDragData) {
const sourceDoc = de.complete.linkDragData.linkSourceGetAnchor();
const destDoc = this.doc;
@@ -270,7 +271,7 @@ export class TreeView extends React.Component<TreeViewProps> {
(doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && localAdd(doc), true as boolean);
const move = (!docDragData.dropAction || docDragData.dropAction === "proto" || docDragData.dropAction === "move" || docDragData.dropAction === "same") && docDragData.moveDocument;
if (canAdd) {
- UndoManager.RunInTempBatch(() => docDragData.droppedDocuments.reduce((added, d) => (move ? move(d, undefined, addDoc) : addDoc(d)) || added, false));
+ UndoManager.RunInTempBatch(() => docDragData.droppedDocuments.reduce((added, d) => (move ? move(d, undefined, addDoc) || (docDragData.dropAction === "proto" ? addDoc(d) : false) : addDoc(d)) || added, false));
}
}
}
@@ -404,7 +405,7 @@ export class TreeView extends React.Component<TreeViewProps> {
onPointerDown={e => { downX = e.clientX; downY = e.clientY; e.stopPropagation(); }}
onClick={(e) => {
if (this.props.active() && Math.abs(e.clientX - downX) < 3 && Math.abs(e.clientY - downY) < 3) {
- !this.outlineMode && (this.doc[sortKey] = sortings[(curSort + 1) % sortings.length]);
+ !this.props.treeView.outlineMode && (this.doc[sortKey] = sortings[(curSort + 1) % sortings.length]);
e.stopPropagation();
}
}}>
@@ -433,7 +434,7 @@ export class TreeView extends React.Component<TreeViewProps> {
this.onCheckedClick?.script.run({
this: this.doc.isTemplateForField && this.props.dataDoc ? this.props.dataDoc : this.doc,
heading: this.props.containingCollection.title,
- checked: this.doc.treeViewChecked === "check" ? "x" : this.doc.treeViewChecked === "x" ? undefined : "check",
+ checked: this.doc.treeViewChecked === "check" ? "x" : this.doc.treeViewChecked === "x" ? "remove" : "check",
containingTreeView: this.props.treeView.props.Document,
}, console.log);
} else {
@@ -446,15 +447,14 @@ export class TreeView extends React.Component<TreeViewProps> {
TraceMobx();
const iconType = this.doc.isFolder ? (this.treeViewOpen ? "chevron-down" : "chevron-right") : Doc.toIcon(this.doc);
const checked = this.onCheckedClick ? (this.doc.treeViewChecked ?? "unchecked") : undefined;
-
- return <div className={`bullet${this.outlineMode ? "-outline" : ""}`} key={"bullet"}
+ return <div className={`bullet${this.props.treeView.outlineMode ? "-outline" : ""}`} key={"bullet"}
title={this.childDocs?.length ? `click to see ${this.childDocs?.length} items` : "view fields"}
onClick={this.bulletClick}
- style={this.outlineMode ? { opacity: this.titleStyleProvider?.(this.doc, this.props.treeView.props, StyleProp.Opacity) } : {
+ style={this.props.treeView.outlineMode ? { opacity: this.titleStyleProvider?.(this.doc, this.props.treeView.props, StyleProp.Opacity) } : {
color: StrCast(this.doc.color, checked === "unchecked" ? "white" : "inherit"),
opacity: checked === "unchecked" ? undefined : 0.4
}}>
- {this.outlineMode ?
+ {this.props.treeView.outlineMode ?
!(this.doc.text as RichTextField)?.Text ? (null) :
<FontAwesomeIcon size="sm" icon={[this.childDocs?.length && !this.treeViewOpen ? "fas" : "far", "circle"]} /> :
<div className="treeView-bulletIcons" >
@@ -476,16 +476,16 @@ export class TreeView extends React.Component<TreeViewProps> {
<FontAwesomeIcon key="bars" icon="bars" size="sm" onClick={e => { this.showContextMenu(e); e.stopPropagation(); }} />
<span className="collectionTreeView-keyHeader" key={this.treeViewExpandedView}
onPointerDown={action(() => {
- if (this.fileSysMode) {
+ if (this.props.treeView.fileSysMode) {
this.doc.treeViewExpandedView = this.doc.isFolder ? this.fieldKey : this.treeViewExpandedView === "layout" ? "aliases" :
this.treeViewExpandedView === "aliases" && !Doc.UserDoc().noviceMode ? "fields" : "layout";
} else if (this.treeViewOpen) {
this.doc.treeViewExpandedView = this.treeViewLockExpandedView ? this.doc.treeViewExpandedView :
- this.treeViewExpandedView === this.fieldKey ? (Doc.UserDoc().noviceMode || this.outlineMode ? "layout" : "fields") :
+ this.treeViewExpandedView === this.fieldKey ? (Doc.UserDoc().noviceMode || this.props.treeView.outlineMode ? "layout" : "fields") :
this.treeViewExpandedView === "fields" && this.layoutDoc ? "layout" :
this.treeViewExpandedView === "layout" && DocListCast(this.doc.links).length ? "links" :
(this.treeViewExpandedView === "links" || this.treeViewExpandedView === "layout") && DocListCast(this.doc[this.fieldKey + "-annotations"]).length ? "annotations" :
- this.childDocs ? this.fieldKey : (Doc.UserDoc().noviceMode || this.outlineMode ? "layout" : "fields");
+ this.childDocs ? this.fieldKey : (Doc.UserDoc().noviceMode || this.props.treeView.outlineMode ? "layout" : "fields");
}
this.treeViewOpen = true;
})}>
@@ -497,12 +497,11 @@ export class TreeView extends React.Component<TreeViewProps> {
showContextMenu = (e: React.MouseEvent) => simulateMouseClick(this._docRef?.ContentDiv, e.clientX, e.clientY + 30, e.screenX, e.screenY + 30);
contextMenuItems = () => this.doc.isFolder ?
[{ script: ScriptField.MakeFunction(`scriptContext.makeFolder()`, { scriptContext: "any" })!, label: "New Folder" }] : Doc.IsSystem(this.doc) ? [] :
- this.fileSysMode && this.doc === Doc.GetProto(this.doc) ?
+ this.props.treeView.fileSysMode && this.doc === Doc.GetProto(this.doc) ?
[{ script: ScriptField.MakeFunction(`openOnRight(getAlias(self))`)!, label: "Open Alias" }] :
[{ script: ScriptField.MakeFunction(`DocFocusOrOpen(self)`)!, label: "Focus or Open" }]
- truncateTitleWidth = () => NumCast(this.props.treeView.props.Document.treeViewTruncateTitleWidth, this.props.panelWidth());
onChildClick = () => this.props.onChildClick?.() ?? (this._editTitleScript?.() || ScriptCast(this.doc.treeChildClick));
- onChildDoubleClick = () => (!this.outlineMode && this._openScript?.()) || ScriptCast(this.doc.treeChildDoubleClick);
+ onChildDoubleClick = () => (!this.props.treeView.outlineMode && this._openScript?.()) || ScriptCast(this.doc.treeChildDoubleClick);
refocus = () => this.props.treeView.props.focus(this.props.treeView.props.Document);
ignoreEvent = (e: any) => {
@@ -515,7 +514,7 @@ export class TreeView extends React.Component<TreeViewProps> {
if (!doc || doc !== this.doc) return this.props?.treeView?.props.styleProvider?.(doc, props, property); // properties are inherited from the CollectionTreeView, not the hierarchical parent in the treeView
switch (property.split(":")[0]) {
- case StyleProp.Opacity: return this.outlineMode ? undefined : 1;
+ case StyleProp.Opacity: return this.props.treeView.outlineMode ? undefined : 1;
case StyleProp.BackgroundColor: return this.selected ? "#7089bb" : StrCast(doc._backgroundColor, StrCast(doc.backgroundColor));
case StyleProp.DocContents: return testDocProps(props) && !props?.treeViewDoc ? (null) :
<div className="treeView-label" style={{ // just render a title for a tree view label (identified by treeViewDoc being set in 'props')
@@ -532,7 +531,7 @@ export class TreeView extends React.Component<TreeViewProps> {
return this.props?.treeView?.props.styleProvider?.(doc, props, property); // properties are inherited from the CollectionTreeView, not the hierarchical parent in the treeView
}
onKeyDown = (e: React.KeyboardEvent) => {
- if (this.doc.treeViewHideHeader || this.outlineMode) {
+ if (this.doc.treeViewHideHeader || this.props.treeView.outlineMode) {
e.stopPropagation();
e.preventDefault();
switch (e.key) {
@@ -553,7 +552,7 @@ export class TreeView extends React.Component<TreeViewProps> {
const view = this._editTitle ? <EditableView key="_editTitle"
oneLine={true}
display={"inline-block"}
- editing={true}
+ editing={this._editTitle}
background={"#7089bb"}
contents={StrCast(this.doc.title)}
height={12}
@@ -564,11 +563,11 @@ export class TreeView extends React.Component<TreeViewProps> {
if (!shift) this.props.indentDocument?.(true);
else this.props.outdentDocument?.(true);
})}
- OnEmpty={undoBatch(() => this.outlineMode && this.props.removeDoc?.(this.doc))}
- OnFillDown={val => this.fileSysMode && this.makeFolder()}
+ OnEmpty={undoBatch(() => this.props.treeView.outlineMode && this.props.removeDoc?.(this.doc))}
+ OnFillDown={val => this.props.treeView.fileSysMode && this.makeFolder()}
SetValue={undoBatch((value: string, shiftKey: boolean, enterKey: boolean) => {
Doc.SetInPlace(this.doc, "title", value, false);
- this.outlineMode && enterKey && this.makeTextCollection();
+ this.props.treeView.outlineMode && enterKey && this.makeTextCollection();
})}
/>
: <DocumentView key="title"
@@ -598,8 +597,8 @@ export class TreeView extends React.Component<TreeViewProps> {
removeDocument={this.props.removeDoc}
ScreenToLocalTransform={this.getTransform}
NativeHeight={() => 18}
- NativeWidth={this.truncateTitleWidth}
- PanelWidth={this.truncateTitleWidth}
+ NativeWidth={this.props.treeView.truncateTitleWidth}
+ PanelWidth={this.props.treeView.truncateTitleWidth}
PanelHeight={() => 18}
contextMenuItems={this.contextMenuItems}
renderDepth={1}
@@ -705,7 +704,7 @@ export class TreeView extends React.Component<TreeViewProps> {
@computed get renderBorder() {
const sorting = this.doc[`${this.fieldKey}-sortCriteria`];
- return <div className={`treeView-border${this.outlineMode ? "outline" : ""}`}
+ return <div className={`treeView-border${this.props.treeView.outlineMode ? "outline" : ""}`}
style={{ borderColor: sorting === undefined ? undefined : sorting === "up" ? "crimson" : sorting === "down" ? "blue" : "green" }}>
{!this.treeViewOpen ? (null) : this.renderContent}
</div>;
@@ -725,7 +724,7 @@ export class TreeView extends React.Component<TreeViewProps> {
}
else this._editMaxWidth = "";
- const hideTitle = this.doc.treeViewHideHeader || this.outlineMode;
+ const hideTitle = this.doc.treeViewHideHeader || this.props.treeView.outlineMode;
return <div className={`treeView-container${this._dref?.contentsActive() ? "-active" : ""}`}
ref={this.createTreeDropTarget}
onPointerDown={e => this.props.active(true) && SelectionManager.DeselectAll()}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index ec5cb8a61..019fc9bae 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -455,7 +455,8 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
@action
onPointerDown = (e: React.PointerEvent): void => {
- if (e.nativeEvent.cancelBubble || InteractionUtils.IsType(e, InteractionUtils.TOUCHTYPE) || InteractionUtils.IsType(e, InteractionUtils.PENTYPE) || (Doc.GetSelectedTool() === InkTool.Highlighter || Doc.GetSelectedTool() === InkTool.Pen)) {
+ if (e.nativeEvent.cancelBubble || InteractionUtils.IsType(e, InteractionUtils.TOUCHTYPE) || InteractionUtils.IsType(e, InteractionUtils.PENTYPE) ||
+ ([InkTool.Pen, InkTool.Highlighter].includes(CurrentUserUtils.SelectedTool))) {
return;
}
this._hitCluster = this.pickCluster(this.getTransform().transformPoint(e.clientX, e.clientY));
@@ -465,7 +466,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
document.addEventListener("pointermove", this.onPointerMove);
document.addEventListener("pointerup", this.onPointerUp);
// if not using a pen and in no ink mode
- if (Doc.GetSelectedTool() === InkTool.None) {
+ if (CurrentUserUtils.SelectedTool === InkTool.None) {
this._downX = this._lastX = e.pageX;
this._downY = this._lastY = e.pageY;
}
@@ -489,7 +490,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
this.addMoveListeners();
this.removeEndListeners();
this.addEndListeners();
- if (Doc.GetSelectedTool() === InkTool.None) {
+ if (CurrentUserUtils.SelectedTool === InkTool.None) {
this._lastX = pt.pageX;
this._lastY = pt.pageY;
e.preventDefault();
@@ -509,7 +510,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
case GestureUtils.Gestures.Stroke:
const points = ge.points;
const B = this.getTransform().transformBounds(ge.bounds.left, ge.bounds.top, ge.bounds.width, ge.bounds.height);
- const inkDoc = Docs.Create.InkDocument(ActiveInkColor(), Doc.GetSelectedTool(), ActiveInkWidth(), ActiveInkBezierApprox(), ActiveFillColor(), ActiveArrowStart(), ActiveArrowEnd(), ActiveDash(), points,
+ const inkDoc = Docs.Create.InkDocument(ActiveInkColor(), CurrentUserUtils.SelectedTool, ActiveInkWidth(), ActiveInkBezierApprox(), ActiveFillColor(), ActiveArrowStart(), ActiveArrowEnd(), ActiveDash(), points,
{ title: "ink stroke", x: B.x - Number(ActiveInkWidth()) / 2, y: B.y - Number(ActiveInkWidth()) / 2, _width: B.width + Number(ActiveInkWidth()), _height: B.height + Number(ActiveInkWidth()) });
this.addDocument(inkDoc);
e.stopPropagation();
@@ -649,7 +650,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
if (InteractionUtils.IsType(e, InteractionUtils.TOUCHTYPE)) {
if (this.props.active(true)) e.stopPropagation();
} else if (!e.cancelBubble) {
- if (Doc.GetSelectedTool() === InkTool.None) {
+ if (CurrentUserUtils.SelectedTool === InkTool.None) {
if (this.tryDragCluster(e, this._hitCluster)) {
document.removeEventListener("pointermove", this.onPointerMove);
document.removeEventListener("pointerup", this.onPointerUp);
@@ -665,7 +666,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
if (!e.cancelBubble) {
const myTouches = InteractionUtils.GetMyTargetTouches(me, this.prevPoints, true);
if (myTouches[0]) {
- if (Doc.GetSelectedTool() === InkTool.None) {
+ if (CurrentUserUtils.SelectedTool === InkTool.None) {
if (this.tryDragCluster(e, this._hitCluster)) {
e.stopPropagation(); // doesn't actually stop propagation since all our listeners are listening to events on 'document' however it does mark the event as cancelBubble=true which we test for in the move event handlers
e.preventDefault();
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index e625b5b4b..9206d3767 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -320,7 +320,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
onClick = (e: React.MouseEvent): void => {
if (Math.abs(e.clientX - this._downX) < Utils.DRAG_THRESHOLD &&
Math.abs(e.clientY - this._downY) < Utils.DRAG_THRESHOLD) {
- if (Doc.GetSelectedTool() === InkTool.None) {
+ if (CurrentUserUtils.SelectedTool === InkTool.None) {
if (!(e.nativeEvent as any).marqueeHit) {
(e.nativeEvent as any).marqueeHit = true;
if (!this.props.trySelectCluster(e.shiftKey)) {
diff --git a/src/client/views/nodes/ColorBox.tsx b/src/client/views/nodes/ColorBox.tsx
index 715ec92f8..61cc8b3d1 100644
--- a/src/client/views/nodes/ColorBox.tsx
+++ b/src/client/views/nodes/ColorBox.tsx
@@ -16,6 +16,7 @@ import "./ColorBox.scss";
import { FieldView, FieldViewProps } from './FieldView';
import { DocumentType } from "../../documents/DocumentTypes";
import { RichTextMenu } from "./formattedText/RichTextMenu";
+import { CurrentUserUtils } from "../../util/CurrentUserUtils";
type ColorDocument = makeInterface<[typeof documentSchema]>;
const ColorDocument = makeInterface(documentSchema);
@@ -30,7 +31,7 @@ export class ColorBox extends ViewBoxBaseComponent<FieldViewProps, ColorDocument
Doc.UserDoc().backgroundColor = Utils.colorString(color);
SetActiveInkColor(color.hex);
- if (Doc.GetSelectedTool() === InkTool.None) {
+ if (CurrentUserUtils.SelectedTool === InkTool.None) {
const selected = SelectionManager.Views();
selected.map(view => {
const targetDoc = view.props.Document.dragFactory instanceof Doc ? view.props.Document.dragFactory :
diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx
index 6f102213b..3622be5fc 100644
--- a/src/client/views/nodes/DocumentLinksButton.tsx
+++ b/src/client/views/nodes/DocumentLinksButton.tsx
@@ -232,7 +232,18 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
}
@computed get filteredLinks() {
- return DocUtils.FilterDocs(Array.from(new Set<Doc>(this.props.links)), this.props.View.props.docFilters(), []);
+ const results = [] as Doc[];
+ Array.from(new Set<Doc>(this.props.links)).forEach(link => {
+ if (!DocUtils.FilterDocs([link], this.props.View.props.docFilters(), []).length) {
+ if (DocUtils.FilterDocs([link.anchor2 as Doc], this.props.View.props.docFilters(), []).length) {
+ results.push(link);
+ }
+ if (DocUtils.FilterDocs([link.anchor1 as Doc], this.props.View.props.docFilters(), []).length) {
+ results.push(link);
+ }
+ } else results.push(link);
+ });
+ return results;
}
@computed get linkButtonInner() {
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index ebc65002f..c7b2f2df6 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -127,6 +127,7 @@ export interface DocumentViewProps extends DocumentViewSharedProps {
freezeDimensions?: boolean;
hideResizeHandles?: boolean; // whether to suppress DocumentDecorations when this document is selected
hideTitle?: boolean; // forces suppression of title. e.g, treeView document labels suppress titles in case they are globally active via settings
+ hideDecorationTitle?: boolean; // forces suppression of title. e.g, treeView document labels suppress titles in case they are globally active via settings
treeViewDoc?: Doc;
contentPointerEvents?: string; // pointer events allowed for content of a document view. eg. set to "none" in menuSidebar for sharedDocs so that you can select a document, but not interact with its contents
radialMenu?: String[];
@@ -491,7 +492,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
onPointerDown = (e: React.PointerEvent): void => {
// continue if the event hasn't been canceled AND we are using a mouse or this has an onClick or onDragStart function (meaning it is a button document)
- if (!(InteractionUtils.IsType(e, InteractionUtils.MOUSETYPE) || Doc.GetSelectedTool() === InkTool.Highlighter || Doc.GetSelectedTool() === InkTool.Pen)) {
+ if (!(InteractionUtils.IsType(e, InteractionUtils.MOUSETYPE) || [InkTool.Highlighter, InkTool.Pen].includes(CurrentUserUtils.SelectedTool))) {
if (!InteractionUtils.IsType(e, InteractionUtils.PENTYPE)) {
e.stopPropagation();
if (SelectionManager.IsSelected(this.props.DocumentView(), true) && this.props.Document._viewType !== CollectionViewType.Docking) e.preventDefault(); // goldenlayout needs to be able to move its tabs, so can't preventDefault for it
@@ -503,7 +504,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
this._downY = e.clientY;
if ((!e.nativeEvent.cancelBubble || this.onClickHandler || this.layoutDoc.onDragStart) &&
// if this is part of a template, let the event go up to the tempalte root unless right/ctrl clicking
- !((this.props.Document.rootDocument) && !(e.ctrlKey || e.button > 0))) {
+ !(this.props.Document.rootDocument && !(e.ctrlKey || e.button > 0))) {
if ((this.active || this.layoutDoc.onDragStart) &&
!e.ctrlKey &&
(e.button === 0 || InteractionUtils.IsType(e, InteractionUtils.TOUCHTYPE)) &&
@@ -520,7 +521,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
}
onPointerMove = (e: PointerEvent): void => {
- if ((InteractionUtils.IsType(e, InteractionUtils.PENTYPE) || Doc.GetSelectedTool() === InkTool.Highlighter || Doc.GetSelectedTool() === InkTool.Pen)) return;
+ if ((InteractionUtils.IsType(e, InteractionUtils.PENTYPE) || [InkTool.Highlighter, InkTool.Pen].includes(CurrentUserUtils.SelectedTool))) return;
if (e.cancelBubble && this.active) {
document.removeEventListener("pointermove", this.onPointerMove); // stop listening to pointerMove if something else has stopPropagated it (e.g., the MarqueeView)
}
@@ -622,7 +623,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
makeIntoPortal = async () => {
const portalLink = this.allLinks.find(d => d.anchor1 === this.props.Document);
if (!portalLink) {
- const portal = Docs.Create.FreeformDocument([], { _width: NumCast(this.layoutDoc._width) + 10, _height: NumCast(this.layoutDoc._height), title: StrCast(this.props.Document.title) + ".portal" });
+ const portal = Docs.Create.FreeformDocument([], { _width: NumCast(this.layoutDoc._width) + 10, _height: NumCast(this.layoutDoc._height), _fitWidth: true, title: StrCast(this.props.Document.title) + ".portal" });
DocUtils.MakeLink({ doc: this.props.Document }, { doc: portal }, "portal to");
}
this.Document.followLinkLocation = "inPlace";
@@ -1009,11 +1010,11 @@ export class DocumentView extends React.Component<DocumentViewProps> {
return this.docView?._componentView?.reverseNativeScaling?.() ? 0 :
returnVal(this.props.NativeHeight?.(), Doc.NativeHeight(this.layoutDoc, this.props.DataDoc, this.props.freezeDimensions));
}
- shouldNotScale = () => (this.layoutDoc._fitWidth && !this.nativeWidth) || [CollectionViewType.Docking, CollectionViewType.Tree].includes(this.Document._viewType as any);
- @computed get effectiveNativeWidth() { return this.shouldNotScale() ? 0 : (this.nativeWidth || NumCast(this.layoutDoc.width)); }
- @computed get effectiveNativeHeight() { return this.shouldNotScale() ? 0 : (this.nativeHeight || NumCast(this.layoutDoc.height)); }
+ @computed get shouldNotScale() { return (this.layoutDoc._fitWidth && !this.nativeWidth) || [CollectionViewType.Docking, CollectionViewType.Tree].includes(this.Document._viewType as any); }
+ @computed get effectiveNativeWidth() { return this.shouldNotScale ? 0 : (this.nativeWidth || NumCast(this.layoutDoc.width)); }
+ @computed get effectiveNativeHeight() { return this.shouldNotScale ? 0 : (this.nativeHeight || NumCast(this.layoutDoc.height)); }
@computed get nativeScaling() {
- if (this.shouldNotScale()) return 1;
+ if (this.shouldNotScale) return 1;
const minTextScale = this.Document.type === DocumentType.RTF ? 0.1 : 0;
if (this.layoutDoc._fitWidth || this.props.PanelHeight() / this.effectiveNativeHeight > this.props.PanelWidth() / this.effectiveNativeWidth) {
return Math.max(minTextScale, this.props.PanelWidth() / this.effectiveNativeWidth); // width-limited or fitWidth
diff --git a/src/client/views/nodes/FilterBox.tsx b/src/client/views/nodes/FilterBox.tsx
index 65d2fe618..41e274e7a 100644
--- a/src/client/views/nodes/FilterBox.tsx
+++ b/src/client/views/nodes/FilterBox.tsx
@@ -87,6 +87,7 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps, FilterBoxDoc
const keys = new Set<string>(noviceFields);
this.allDocs.forEach(doc => SearchBox.documentKeys(doc).filter(key => keys.add(key)));
return Array.from(keys.keys()).filter(key => key[0]).filter(key => key[0] === "#" || key.indexOf("lastModified") !== -1 || (key[0] === key[0].toUpperCase() && !key.startsWith("_")) || noviceFields.includes(key) || !Doc.UserDoc().noviceMode).sort();
+ // return [];
}
@@ -231,10 +232,10 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps, FilterBoxDoc
newFacet.title = facetHeader;
newFacet.treeViewOpen = true;
newFacet.type = DocumentType.COL;
- const capturedVariables = { layoutDoc: targetDoc, system: true, _stayInCollection: true, _hideContextMenu: true, dataDoc: (targetDoc.data as any)[0][DataSym] };
- newFacet.data = ComputedField.MakeFunction(`readFacetData(layoutDoc, "${facetHeader}")`, {}, capturedVariables);
- // newFacet.target = targetDoc;
- // newFacet.data = ComputedField.MakeFunction(`readFacetData(self.target, "${facetHeader}")`);
+ // const capturedVariables = { layoutDoc: targetDoc, system: true, _stayInCollection: true, _hideContextMenu: true, dataDoc: (targetDoc.data as any)[0][DataSym] };
+ // newFacet.data = ComputedField.MakeFunction(`readFacetData(layoutDoc, "${facetHeader}")`, {}, capturedVariables);
+ newFacet.target = targetDoc;
+ newFacet.data = ComputedField.MakeFunction(`readFacetData(self.target, "${facetHeader}")`);
}
newFacet && Doc.AddDocToList(this.dataDoc, this.props.fieldKey, newFacet);
}
@@ -332,6 +333,7 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps, FilterBoxDoc
// TODO uncomment the line below when the treeview x works
// const options = this._allFacets.filter(facet => this.currentFacets.indexOf(facet) === -1).map(facet => ({ value: facet, label: facet }));
const options = this._allFacets.map(facet => ({ value: facet, label: facet }));
+ console.log(this.props.PanelHeight());
return this.props.dontRegisterView ? (null) : <div className="filterBox-treeView" style={{ width: "100%" }}>
<div className="filterBox-title">
@@ -384,7 +386,7 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps, FilterBoxDoc
ContainingCollectionDoc={this.props.ContainingCollectionDoc}
ContainingCollectionView={this.props.ContainingCollectionView}
PanelWidth={this.props.PanelWidth}
- PanelHeight={this.props.PanelHeight}
+ PanelHeight={() => 100}
rootSelected={this.props.rootSelected}
renderDepth={1}
dropAction={this.props.dropAction}
diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx
index 8acf4081c..383650e89 100644
--- a/src/client/views/nodes/KeyValueBox.tsx
+++ b/src/client/views/nodes/KeyValueBox.tsx
@@ -61,10 +61,7 @@ export class KeyValueBox extends React.Component<FieldViewProps> {
const options: ScriptOptions = { addReturn: true, params: { this: "Doc", _last_: "any" }, editable: false };
if (dubEq) options.typecheck = false;
const script = CompileScript(value, options);
- if (!script.compiled) {
- return undefined;
- }
- return { script, type: dubEq, onDelegate: eq };
+ return !script.compiled ? undefined : { script, type: dubEq, onDelegate: eq };
}
public static ApplyKVPScript(doc: Doc, key: string, kvpScript: KVPScript, forceOnDelegate?: boolean): boolean {
@@ -100,9 +97,7 @@ export class KeyValueBox extends React.Component<FieldViewProps> {
e.stopPropagation();
}
}
- onPointerWheel = (e: React.WheelEvent): void => {
- e.stopPropagation();
- }
+ onPointerWheel = (e: React.WheelEvent): void => e.stopPropagation();
rowHeight = () => 30;
diff --git a/src/client/views/nodes/PDFBox.scss b/src/client/views/nodes/PDFBox.scss
index 16cc9d27e..74b331ae1 100644
--- a/src/client/views/nodes/PDFBox.scss
+++ b/src/client/views/nodes/PDFBox.scss
@@ -176,6 +176,26 @@
}
}
+ .pdfBox-tagList {
+ display: flex;
+ flex-direction: row;
+ overflow: auto;
+ flex-flow: row;
+ flex-wrap: wrap;
+ .pdfBox-filterTag, .pdfBox-filterTag-active {
+ font-weight: bold;
+ padding-left: 6;
+ padding-right: 6;
+ box-shadow: black 1px 1px 4px;
+ border-radius: 5;
+ margin: 2;
+ height: 20;
+ background-color: lightgrey;
+ }
+ .pdfBox-filterTag-active {
+ background-color: white;
+ }
+ }
.pdfBox-title-outer {
width: 100%;
height: 100%;
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index a3b5eea0c..4e4db323c 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -3,29 +3,33 @@ import { action, computed, IReactionDisposer, observable, reaction, runInAction
import { observer } from "mobx-react";
import * as Pdfjs from "pdfjs-dist";
import "pdfjs-dist/web/pdf_viewer.css";
-import { Doc, Opt, WidthSym, HeightSym } from "../../../fields/Doc";
+import { Doc, DocListCast, Opt, StrListCast, WidthSym } from "../../../fields/Doc";
import { documentSchema } from '../../../fields/documentSchemas';
+import { Id } from '../../../fields/FieldSymbols';
import { makeInterface } from "../../../fields/Schema";
import { Cast, NumCast, StrCast } from '../../../fields/Types';
import { PdfField } from "../../../fields/URLField";
import { TraceMobx } from '../../../fields/util';
-import { Utils, returnOne, OmitKeys, emptyFunction, returnZero } from '../../../Utils';
+import { emptyFunction, OmitKeys, returnOne, returnTrue, returnZero, Utils } from '../../../Utils';
+import { Docs, DocUtils } from '../../documents/Documents';
import { KeyCodes } from '../../util/KeyCodes';
import { undoBatch } from '../../util/UndoManager';
import { panZoomSchema } from '../collections/collectionFreeForm/CollectionFreeFormView';
+import { CollectionStackingView } from '../collections/CollectionStackingView';
import { CollectionViewType } from '../collections/CollectionView';
import { ContextMenu } from '../ContextMenu';
import { ContextMenuProps } from '../ContextMenuItem';
import { ViewBoxAnnotatableComponent } from "../DocComponent";
import { PDFViewer } from "../pdf/PDFViewer";
+import { SearchBox } from '../search/SearchBox';
+import { StyleProp } from '../StyleProvider';
import { FieldView, FieldViewProps } from './FieldView';
+import { FormattedTextBox } from './formattedText/FormattedTextBox';
import { pageSchema } from "./ImageBox";
import "./PDFBox.scss";
import React = require("react");
-import { DocAfterFocusFunc } from './DocumentView';
-import { Docs } from '../../documents/Documents';
-import { CollectionStackingView } from '../collections/CollectionStackingView';
-import { StyleProp } from '../StyleProvider';
+import { DocFocusOptions } from './DocumentView';
+import { List } from '../../../fields/List';
type PdfDocument = makeInterface<[typeof documentSchema, typeof panZoomSchema, typeof pageSchema]>;
const PdfDocument = makeInterface(documentSchema, panZoomSchema, pageSchema);
@@ -85,6 +89,12 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps, PdfDocum
initialScrollTarget: Opt<Doc>;
scrollFocus = (doc: Doc, smooth: boolean) => {
+ if (DocListCast(this.rootDoc[this.sidebarKey()]).includes(doc)) {
+ if (this.layoutDoc["_" + this.sidebarKey() + "-docFilters"]) {
+ this.layoutDoc["_" + this.sidebarKey() + "-docFilters"] = new List<string>();
+ return 1;
+ }
+ }
this.initialScrollTarget = doc;
return this._pdfViewer?.scrollFocus(doc, smooth);
}
@@ -118,43 +128,64 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps, PdfDocum
!this.Document._fitWidth && (this.Document._height = this.Document[WidthSym]() * (nh / nw));
}
sidebarKey = () => this.fieldKey + "-sidebar";
+ sidebarFiltersHeight = () => 50;
sidebarTransform = () => this.props.ScreenToLocalTransform().translate(Doc.NativeWidth(this.dataDoc), 0).scale(this.props.scaling?.() || 1);
sidebarWidth = () => !this.layoutDoc._showSidebar ? 0 : (NumCast(this.layoutDoc.nativeWidth) - Doc.NativeWidth(this.dataDoc)) * this.props.PanelWidth() / NumCast(this.layoutDoc.nativeWidth);
+ sidebarHeight = () => this.props.PanelHeight() - this.sidebarFiltersHeight() - 20;
sidebarAddDocument = (doc: Doc | Doc[]) => this.addDocument(doc, this.sidebarKey());
sidebarMoveDocument = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (doc: Doc | Doc[]) => boolean) => this.moveDocument(doc, targetCollection, addDocument, this.sidebarKey());
sidebarRemDocument = (doc: Doc | Doc[]) => this.removeDocument(doc, this.sidebarKey());
+ sidebarDocFilters = () => [...StrListCast(this.layoutDoc._docFilters), ...StrListCast(this.layoutDoc[this.sidebarKey() + "-docFilters"])];
+ @computed get allTags() {
+ const keys = new Set<string>();
+ DocListCast(this.rootDoc[this.sidebarKey()]).forEach(doc => SearchBox.documentKeys(doc).forEach(key => keys.add(key)));
+ return Array.from(keys.keys()).filter(key => key[0]).filter(key => !key.startsWith("_") && (key[0] === "#" || key[0] === key[0].toUpperCase())).sort();
+ }
+ renderTag = (tag: string) => {
+ const active = StrListCast(this.rootDoc[this.sidebarKey() + "-docFilters"]).includes(`${tag}:${tag}:check`);
+ return <div className={`pdfbox-filterTag${active ? "-active" : ""}`}
+ onClick={e => Doc.setDocFilter(this.rootDoc, tag, tag, "check", true, this.sidebarKey())}>
+ {tag}
+ </div>;
+ }
@computed get sidebarOverlay() {
return !this.layoutDoc._showSidebar ? (null) :
<div style={{
position: "absolute", pointerEvents: this.active() ? "all" : undefined, top: 0, right: 0,
- background: this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor),
+ background: this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.WidgetColor),
width: `${this.sidebarWidth()}px`,
height: "100%"
}}>
- <CollectionStackingView {...OmitKeys(this.props, ["NativeWidth", "NativeHeight", "setContentView"]).omit}
- NativeWidth={returnZero}
- NativeHeight={returnZero}
- PanelHeight={this.props.PanelHeight}
- PanelWidth={this.sidebarWidth}
- xMargin={0}
- yMargin={0}
- chromeStatus={"enabled"}
- scaleField={this.sidebarKey() + "-scale"}
- isAnnotationOverlay={false}
- select={emptyFunction}
- active={this.annotationsActive}
- scaling={returnOne}
- whenActiveChanged={this.whenActiveChanged}
- childPointerEvents={true}
- removeDocument={this.sidebarRemDocument}
- moveDocument={this.sidebarMoveDocument}
- addDocument={this.sidebarAddDocument}
- CollectionView={undefined}
- ScreenToLocalTransform={this.sidebarTransform}
- renderDepth={this.props.renderDepth + 1}
- fieldKey={this.sidebarKey()}
- pointerEvents={"all"}
- />
+ <div style={{ width: "100%", height: this.sidebarHeight(), position: "relative" }}>
+ <CollectionStackingView {...OmitKeys(this.props, ["NativeWidth", "NativeHeight", "setContentView"]).omit}
+ NativeWidth={returnZero}
+ NativeHeight={returnZero}
+ PanelHeight={this.sidebarHeight}
+ PanelWidth={this.sidebarWidth}
+ xMargin={0}
+ yMargin={0}
+ docFilters={this.sidebarDocFilters}
+ chromeStatus={"enabled"}
+ scaleField={this.sidebarKey() + "-scale"}
+ isAnnotationOverlay={false}
+ select={emptyFunction}
+ active={this.annotationsActive}
+ scaling={returnOne}
+ whenActiveChanged={this.whenActiveChanged}
+ childHideDecorationTitle={returnTrue}
+ removeDocument={this.sidebarRemDocument}
+ moveDocument={this.sidebarMoveDocument}
+ addDocument={this.sidebarAddDocument}
+ CollectionView={undefined}
+ ScreenToLocalTransform={this.sidebarTransform}
+ renderDepth={this.props.renderDepth + 1}
+ fieldKey={this.sidebarKey()}
+ pointerEvents={"all"}
+ />
+ </div>
+ <div className="pdfBox-tagList" style={{ height: this.sidebarFiltersHeight(), width: this.sidebarWidth() }}>
+ {this.allTags.map(tag => this.renderTag(tag))}
+ </div>
</div>;
}
@@ -247,11 +278,26 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps, PdfDocum
const funcs: ContextMenuProps[] = [];
pdfUrl && funcs.push({ description: "Copy path", event: () => Utils.CopyText(pdfUrl.url.pathname), icon: "expand-arrows-alt" });
funcs.push({ description: "Toggle Fit Width " + (this.Document._fitWidth ? "Off" : "On"), event: () => this.Document._fitWidth = !this.Document._fitWidth, icon: "expand-arrows-alt" });
- !Doc.UserDoc().noviceMode && funcs.push({ description: "Toggle Sidebar mode ", event: () => this.Document._showSidebar = !this.Document._showSidebar, icon: "expand-arrows-alt" });
+ funcs.push({ description: "Toggle Annotation View ", event: () => this.Document._showSidebar = !this.Document._showSidebar, icon: "expand-arrows-alt" });
ContextMenu.Instance.addItem({ description: "Options...", subitems: funcs, icon: "asterisk" });
}
+ anchorMenuClick = (anchor: Doc) => {
+ this.Document._showSidebar = true;
+ const startup = StrListCast(this.rootDoc.docFilters).map(filter => filter.split(":")[0]).join(" ");
+ const target = Docs.Create.TextDocument(startup, {
+ title: "anno",
+ annotationOn: this.rootDoc, _width: 200, _height: 50, _fitWidth: true, _autoHeight: true, _fontSize: StrCast(Doc.UserDoc().fontSize),
+ _fontFamily: StrCast(Doc.UserDoc().fontFamily)
+ });
+ FormattedTextBox.SelectOnLoad = target[Id];
+ FormattedTextBox.DontSelectInitialText = true;
+ this.allTags.map(tag => target[tag] = tag);
+ DocUtils.MakeLink({ doc: anchor }, { doc: target }, "inline markup", "annotation");
+ this.sidebarAddDocument(target);
+ }
+
@computed get renderTitleBox() {
const classname = "pdfBox" + (this.active() ? "-interactive" : "");
return <div className={classname} >
@@ -260,7 +306,6 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps, PdfDocum
</div>
</div>;
}
-
isChildActive = (outsideReaction?: boolean) => this._isChildActive;
@computed get renderPdfView() {
TraceMobx();
@@ -271,6 +316,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps, PdfDocum
<PDFViewer {...this.props}
pdf={this._pdf!}
url={pdfUrl!.url.pathname}
+ anchorMenuClick={this.anchorMenuClick}
loaded={!Doc.NativeAspect(this.dataDoc) ? this.loaded : undefined}
setPdfViewer={this.setPdfViewer}
addDocument={this.addDocument}
diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx
index b9480fa74..844afe1e2 100644
--- a/src/client/views/nodes/PresBox.tsx
+++ b/src/client/views/nodes/PresBox.tsx
@@ -747,7 +747,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
removeDocument = (doc: Doc) => Doc.RemoveDocFromList(this.dataDoc, this.fieldKey, doc);
getTransform = () => this.props.ScreenToLocalTransform().translate(-5, -65);// listBox padding-left and pres-box-cont minHeight
panelHeight = () => this.props.PanelHeight() - 40;
- active = (outsideReaction?: boolean) => ((Doc.GetSelectedTool() === InkTool.None && this.props.layerProvider?.(this.layoutDoc) !== false) &&
+ active = (outsideReaction?: boolean) => ((CurrentUserUtils.SelectedTool === InkTool.None && this.props.layerProvider?.(this.layoutDoc) !== false) &&
(this.layoutDoc.forceActive || this.props.isSelected(outsideReaction) || this._isChildActive || this.props.renderDepth === 0) ? true : false)
/**
diff --git a/src/client/views/nodes/ScreenshotBox.tsx b/src/client/views/nodes/ScreenshotBox.tsx
index 4956b315d..a14d8ccae 100644
--- a/src/client/views/nodes/ScreenshotBox.tsx
+++ b/src/client/views/nodes/ScreenshotBox.tsx
@@ -17,6 +17,7 @@ import { ContextMenuProps } from "../ContextMenuItem";
import { ViewBoxBaseComponent } from "../DocComponent";
import { FieldView, FieldViewProps } from './FieldView';
import "./ScreenshotBox.scss";
+import { CurrentUserUtils } from "../../util/CurrentUserUtils";
const path = require('path');
type ScreenshotDocument = makeInterface<[typeof documentSchema]>;
@@ -129,7 +130,7 @@ export class ScreenshotBox extends ViewBoxBaseComponent<FieldViewProps, Screensh
}
@computed get content() {
- const interactive = Doc.GetSelectedTool() !== InkTool.None || !this.props.isSelected() ? "" : "-interactive";
+ const interactive = CurrentUserUtils.SelectedTool !== InkTool.None || !this.props.isSelected() ? "" : "-interactive";
const style = "videoBox-content" + interactive;
return <video className={`${style}`} key="video" autoPlay={this._screenCapture} ref={this.setVideoRef}
style={{ width: this._screenCapture ? "100%" : undefined, height: this._screenCapture ? "100%" : undefined }}
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index 6afc2258a..3e1edb927 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -27,6 +27,7 @@ import { FieldView, FieldViewProps } from './FieldView';
import { FormattedTextBoxComment } from "./formattedText/FormattedTextBoxComment";
import { LinkDocPreview } from "./LinkDocPreview";
import "./VideoBox.scss";
+import { CurrentUserUtils } from "../../util/CurrentUserUtils";
const path = require('path');
type VideoDocument = makeInterface<[typeof documentSchema]>;
@@ -293,7 +294,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps, VideoD
@computed get content() {
const field = Cast(this.dataDoc[this.fieldKey], VideoField);
- const interactive = Doc.GetSelectedTool() !== InkTool.None || !this.props.isSelected() ? "" : "-interactive";
+ const interactive = CurrentUserUtils.SelectedTool !== InkTool.None || !this.props.isSelected() ? "" : "-interactive";
const style = "videoBox-content" + (this._fullScreen ? "-fullScreen" : "") + interactive;
return !field ? <div key="loading">Loading</div> :
<div className="container" key="container" style={{ pointerEvents: this._isChildActive || this.active() ? "all" : "none" }}>
@@ -344,7 +345,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps, VideoD
this._disposers.youtubeReactionDisposer?.();
this._disposers.reactionDisposer = reaction(() => this.layoutDoc._currentTimecode, () => !this._playing && this.Seek((this.layoutDoc._currentTimecode || 0)));
this._disposers.youtubeReactionDisposer = reaction(
- () => !this.props.Document.isAnnotating && Doc.GetSelectedTool() === InkTool.None && this.props.isSelected(true) && !SnappingManager.GetIsDragging() && !DocumentDecorations.Instance.Interacting,
+ () => !this.props.Document.isAnnotating && CurrentUserUtils.SelectedTool === InkTool.None && this.props.isSelected(true) && !SnappingManager.GetIsDragging() && !DocumentDecorations.Instance.Interacting,
(interactive) => iframe.style.pointerEvents = interactive ? "all" : "none", { fireImmediately: true });
};
if (typeof (YT) === undefined) setTimeout(() => this.loadYouTube(iframe), 100);
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index 156fe64c9..b15865c1f 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -31,6 +31,7 @@ import { LinkDocPreview } from "./LinkDocPreview";
import "./WebBox.scss";
import { DocumentType } from '../../documents/DocumentTypes';
import React = require("react");
+import { CurrentUserUtils } from "../../util/CurrentUserUtils";
const htmlToText = require("html-to-text");
type WebDocument = makeInterface<[typeof documentSchema]>;
@@ -487,7 +488,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
const frozen = !this.props.isSelected() || DocumentDecorations.Instance?.Interacting;
const scale = this.props.scaling?.() || 1;
return (<>
- <div className={"webBox-cont" + (this.props.isSelected() && Doc.GetSelectedTool() === InkTool.None && !DocumentDecorations.Instance?.Interacting ? "-interactive" : "")}
+ <div className={"webBox-cont" + (this.props.isSelected() && CurrentUserUtils.SelectedTool === InkTool.None && !DocumentDecorations.Instance?.Interacting ? "-interactive" : "")}
style={{
width: NumCast(this.layoutDoc[this.fieldKey + "-contentWidth"]) || `${100 / scale}%`,
height: `${100 / scale}%`,
diff --git a/src/client/views/nodes/formattedText/DashDocView.tsx b/src/client/views/nodes/formattedText/DashDocView.tsx
index 86a9f4347..0eade44ac 100644
--- a/src/client/views/nodes/formattedText/DashDocView.tsx
+++ b/src/client/views/nodes/formattedText/DashDocView.tsx
@@ -71,7 +71,7 @@ export class DashDocViewInternal extends React.Component<IDashDocViewInternal> {
constructor(props: IDashDocViewInternal) {
super(props);
- this._textBox = this.props.tbox as FormattedTextBox;
+ this._textBox = this.props.tbox;
const updateDoc = action((dashDoc: Doc) => {
this._dashDoc = dashDoc;
@@ -101,7 +101,7 @@ export class DashDocViewInternal extends React.Component<IDashDocViewInternal> {
const aliasedDoc = Doc.MakeAlias(dashDocBase, this.props.docid + this.props.alias);
aliasedDoc.layoutKey = "layout";
this.props.fieldKey && DocUtils.makeCustomViewClicked(aliasedDoc, Docs.Create.StackingDocument, this.props.fieldKey, undefined);
- updateDoc(aliasedDoc)
+ updateDoc(aliasedDoc);
}
});
} else {
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index 9c620e729..985c5d807 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -150,6 +150,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
public static FocusedBox: FormattedTextBox | undefined;
public static PasteOnLoad: ClipboardEvent | undefined;
public static SelectOnLoad = "";
+ public static DontSelectInitialText = false; // whether initial text should be selected or not
public static SelectOnLoadChar = "";
public static IsFragment(html: string) { return html.indexOf("data-pm-slice") !== -1; }
public static GetHref(html: string): string {
@@ -1081,10 +1082,11 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
const tr = this._editorView.state.tr.setStoredMarks(storedMarks).insertText(FormattedTextBox.SelectOnLoadChar, this._editorView.state.doc.content.size - 1, this._editorView.state.doc.content.size).setStoredMarks(storedMarks);
this._editorView.dispatch(tr.setSelection(new TextSelection(tr.doc.resolve(tr.doc.content.size))));
FormattedTextBox.SelectOnLoadChar = "";
- } else if (curText?.Text) {
+ } else if (curText?.Text && !FormattedTextBox.DontSelectInitialText) {
selectAll(this._editorView!.state, this._editorView?.dispatch);
this.startUndoTypingBatch();
}
+ FormattedTextBox.DontSelectInitialText = false;
}
selectOnLoad && this._editorView!.focus();
// add user mark for any first character that was typed since the user mark that gets set in KeyPress won't have been called yet.
@@ -1153,6 +1155,9 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
if (!this._editorView?.state.selection.empty && FormattedTextBox._canAnnotate) this.setupAnchorMenu();
if (!this._downEvent) return;
this._downEvent = false;
+ if ((e.nativeEvent as any).formattedHandled) {
+ console.log("handled");
+ }
if (!(e.nativeEvent as any).formattedHandled && this.active(true)) {
const editor = this._editorView!;
const pcords = editor.posAtCoords({ left: e.clientX, top: e.clientY });
@@ -1242,7 +1247,10 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
this._editorView!.dispatch(this._editorView!.state.tr.setSelection(NodeSelection.create(this._editorView!.state.doc, pcords.pos)));
}
}
- if ((e.nativeEvent as any).formattedHandled) { e.stopPropagation(); return; }
+ if ((e.nativeEvent as any).formattedHandled) {
+ e.stopPropagation();
+ return;
+ }
this.props.isSelected(true) && ((e.nativeEvent as any).formattedHandled = true);
if (this.props.isSelected(true)) { // if text box is selected, then it consumes all click events
@@ -1295,8 +1303,12 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
const originalUpHandler = view.mouseDown.up;
view.root.removeEventListener("mouseup", originalUpHandler);
view.mouseDown.up = (e: MouseEvent) => {
- !(e as any).formattedHandled && originalUpHandler(e);
- (e as any).formattedHandled = true;
+ if (!(e as any).formattedHandled) {
+ originalUpHandler(e);
+ (e as any).formattedHandled = true;
+ } else {
+ console.log("prehandled");
+ }
};
view.root.addEventListener("mouseup", view.mouseDown.up);
}
@@ -1394,7 +1406,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
fitToBox = () => this.props.Document._fitToBox;
sidebarContentScaling = () => (this.props.scaling?.() || 1) * NumCast(this.layoutDoc._viewScale, 1);
sidebarAddDocument = (doc: Doc | Doc[]) => this.addDocument(doc, this.SidebarKey);
- sidebarMoveDocument = (doc: Doc | Doc[], targetCollection: Doc, addDocument: (doc: Doc | Doc[]) => boolean) => this.moveDocument(doc, targetCollection, addDocument, this.SidebarKey);
+ sidebarMoveDocument = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (doc: Doc | Doc[]) => boolean) => this.moveDocument(doc, targetCollection, addDocument, this.SidebarKey);
sidebarRemDocument = (doc: Doc | Doc[]) => this.removeDocument(doc, this.SidebarKey);
setSidebarHeight = (height: number) => this.rootDoc[this.SidebarKey + "-height"] = height;
sidebarWidth = () => Number(this.sidebarWidthPercent.substring(0, this.sidebarWidthPercent.length - 1)) / 100 * this.props.PanelWidth();
@@ -1417,7 +1429,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
const renderComponent = (tag: string) => {
const ComponentTag = tag === "freeform" ? CollectionFreeFormView : tag === "translation" ? FormattedTextBox : CollectionStackingView;
return <ComponentTag
- {...OmitKeys(this.props, ["NativeWidth", "NativeHeight"]).omit}
+ {...OmitKeys(this.props, ["NativeWidth", "NativeHeight", "setContentView"]).omit}
NativeWidth={returnZero}
NativeHeight={returnZero}
PanelHeight={this.props.PanelHeight}
@@ -1427,8 +1439,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
chromeStatus={"enabled"}
scaleField={this.SidebarKey + "-scale"}
isAnnotationOverlay={false}
- setHeight={this.setSidebarHeight}
- fitContentsToDoc={this.fitToBox}
select={emptyFunction}
active={this.annotationsActive}
scaling={this.sidebarContentScaling}
@@ -1439,10 +1449,12 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
CollectionView={undefined}
ScreenToLocalTransform={this.sidebarScreenToLocal}
renderDepth={this.props.renderDepth + 1}
+ setHeight={this.setSidebarHeight}
+ fitContentsToDoc={this.fitToBox}
noSidebar={true}
fieldKey={this.layoutDoc.sidebarViewType === "translation" ? `${this.fieldKey}-translation` : this.SidebarKey} />;
};
- return <div className={"formattedTextBox-sidebar" + (Doc.GetSelectedTool() !== InkTool.None ? "-inking" : "")}
+ return <div className={"formattedTextBox-sidebar" + (CurrentUserUtils.SelectedTool !== InkTool.None ? "-inking" : "")}
style={{ width: `${this.sidebarWidthPercent}`, backgroundColor: `${this.sidebarColor}` }}>
{renderComponent(StrCast(this.layoutDoc.sidebarViewType))}
</div>;
@@ -1453,7 +1465,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
const active = this.active();
const scale = this.props.hideOnLeave ? 1 : (this.props.scaling?.() || 1) * NumCast(this.layoutDoc._viewScale, 1);
const rounded = StrCast(this.layoutDoc.borderRounding) === "100%" ? "-rounded" : "";
- const interactive = (Doc.GetSelectedTool() === InkTool.None || SnappingManager.GetIsDragging()) && (this.layoutDoc.z || this.props.layerProvider?.(this.layoutDoc) !== false);
+ const interactive = (CurrentUserUtils.SelectedTool === InkTool.None || SnappingManager.GetIsDragging()) && (this.layoutDoc.z || this.props.layerProvider?.(this.layoutDoc) !== false);
if (!selected && FormattedTextBoxComment.textBox === this) setTimeout(FormattedTextBoxComment.Hide);
const minimal = this.props.ignoreAutoHeight;
const margins = NumCast(this.layoutDoc._yMargin, this.props.yMargin || 0);
diff --git a/src/client/views/pdf/AnchorMenu.tsx b/src/client/views/pdf/AnchorMenu.tsx
index e3d14d620..5a3c2103e 100644
--- a/src/client/views/pdf/AnchorMenu.tsx
+++ b/src/client/views/pdf/AnchorMenu.tsx
@@ -42,6 +42,7 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
@observable public Highlighting: boolean = false;
@observable public Status: "marquee" | "annotation" | "" = "";
+ public OnClick: (e: PointerEvent) => void = unimplementedFunction;
public StartDrag: (e: PointerEvent, ele: HTMLElement) => void = unimplementedFunction;
public Highlight: (color: string, isPushpin: boolean) => Opt<Doc> = (color: string, isPushpin: boolean) => undefined;
public Delete: () => void = unimplementedFunction;
@@ -71,7 +72,7 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
setupMoveUpEvents(this, e, (e: PointerEvent) => {
this.StartDrag(e, this._commentCont.current!);
return true;
- }, returnFalse, returnFalse);
+ }, returnFalse, e => this.OnClick?.(e));
}
@action
diff --git a/src/client/views/pdf/Annotation.tsx b/src/client/views/pdf/Annotation.tsx
index 05d81f40f..1e574b9c0 100644
--- a/src/client/views/pdf/Annotation.tsx
+++ b/src/client/views/pdf/Annotation.tsx
@@ -56,10 +56,10 @@ class RegionAnnotation extends React.Component<IRegionAnnotationProps> {
}
@undoBatch
- pinToPres = () => this.props.pinToPres(this.annoTextRegion);
+ pinToPres = () => this.props.pinToPres(this.annoTextRegion)
@undoBatch
- makePushpin = () => this.annoTextRegion.isPushpin = !this.annoTextRegion.isPushpin;
+ makePushpin = () => this.annoTextRegion.isPushpin = !this.annoTextRegion.isPushpin
isPushpin = () => BoolCast(this.annoTextRegion.isPushpin);
diff --git a/src/client/views/pdf/PDFViewer.scss b/src/client/views/pdf/PDFViewer.scss
index 3074eb4ec..390aed1e0 100644
--- a/src/client/views/pdf/PDFViewer.scss
+++ b/src/client/views/pdf/PDFViewer.scss
@@ -1,5 +1,15 @@
+
+.pdfViewer-content {
+ height: 100%;
+ width: 100%;
+ position: absolute;
+ display: inline-block;
+ top: 0;
+ left: 0;
+}
.pdfViewerDash, .pdfViewerDash-interactive {
+ position: absolute;
width: 100%;
height: 100%;
top: 0;
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index d2fa1089e..c7359f74e 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -28,6 +28,7 @@ import "./PDFViewer.scss";
const pdfjs = require('pdfjs-dist/es5/build/pdf.js');
import React = require("react");
import { SharingManager } from "../../util/SharingManager";
+import { CurrentUserUtils } from "../../util/CurrentUserUtils";
const PDFJSViewer = require("pdfjs-dist/web/pdf_viewer");
const pdfjsLib = require("pdfjs-dist");
const _global = (window /* browser */ || global /* node */) as any;
@@ -55,6 +56,7 @@ interface IViewerProps extends FieldViewProps {
setPdfViewer: (view: PDFViewer) => void;
ContentScaling?: () => number;
sidebarWidth: () => number;
+ anchorMenuClick: (anchor: Doc) => void;
}
/**
@@ -511,7 +513,7 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu
panelWidth = () => this.props.PanelWidth() / (this.props.scaling?.() || 1); // (this.Document.scrollHeight || Doc.NativeHeight(this.Document) || 0);
panelHeight = () => this.props.PanelHeight() / (this.props.scaling?.() || 1); // () => this._pageSizes.length && this._pageSizes[0] ? this._pageSizes[0].width : Doc.NativeWidth(this.Document);
@computed get overlayLayer() {
- return <div className={`pdfViewerDash-overlay${Doc.GetSelectedTool() !== InkTool.None || SnappingManager.GetIsDragging() ? "-inking" : ""}`}
+ return <div className={`pdfViewerDash-overlay${CurrentUserUtils.SelectedTool !== InkTool.None || SnappingManager.GetIsDragging() ? "-inking" : ""}`}
style={{
pointerEvents: SnappingManager.GetIsDragging() ? "all" : undefined,
mixBlendMode: this.allAnnotations.some(anno => anno.mixBlendMode) ? "hard-light" : undefined,
@@ -551,7 +553,7 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu
contentZoom = () => this._zoomed;
render() {
TraceMobx();
- return <div>
+ return <div className="pdfViewer-content">
<div className={`pdfViewerDash${this.annotationsActive() ? "-interactive" : ""}`} ref={this._mainCont}
onScroll={this.onScroll} onWheel={this.onZoomWheel} onPointerDown={this.onPointerDown} onClick={this.onClick}
style={{
@@ -563,11 +565,17 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu
{this.pdfViewerDiv}
{this.annotationLayer}
{this.overlayLayer}
+ {this.overlayInfo}
+ {this.standinViews}
+ {!this._marqueeing || !this._mainCont.current || !this._annotationLayer.current ? (null) :
+ <MarqueeAnnotator rootDoc={this.rootDoc} scrollTop={0} down={this._marqueeing}
+ anchorMenuClick={this.props.anchorMenuClick}
+ addDocument={this.addDocument}
+ finishMarquee={this.finishMarquee}
+ getPageFromScroll={this.getPageFromScroll}
+ savedAnnotations={this._savedAnnotations}
+ annotationLayer={this._annotationLayer.current} mainCont={this._mainCont.current} />}
</div>
- {this.overlayInfo}
- {this.standinViews}
- {!this._marqueeing || !this._mainCont.current || !this._annotationLayer.current ? (null) :
- <MarqueeAnnotator rootDoc={this.rootDoc} scrollTop={0} down={this._marqueeing} addDocument={this.addDocument} finishMarquee={this.finishMarquee} getPageFromScroll={this.getPageFromScroll} savedAnnotations={this._savedAnnotations} annotationLayer={this._annotationLayer.current} mainCont={this._mainCont.current} />}
</div>;
}
} \ No newline at end of file
diff --git a/src/client/views/webcam/DashWebRTCVideo.tsx b/src/client/views/webcam/DashWebRTCVideo.tsx
index 82c0e19c8..505a8da7e 100644
--- a/src/client/views/webcam/DashWebRTCVideo.tsx
+++ b/src/client/views/webcam/DashWebRTCVideo.tsx
@@ -11,6 +11,7 @@ import { FieldView, FieldViewProps } from "../nodes/FieldView";
import "./DashWebRTCVideo.scss";
import { hangup, initialize, refreshVideos } from "./WebCamLogic";
import React = require("react");
+import { CurrentUserUtils } from "../../util/CurrentUserUtils";
/**
@@ -69,7 +70,7 @@ export class DashWebRTCVideo extends React.Component<CollectionFreeFormDocumentV
</div >;
const frozen = !this.props.isSelected() || DocumentDecorations.Instance.Interacting;
- const classname = "webBox-cont" + (this.props.isSelected() && Doc.GetSelectedTool() === InkTool.None && !DocumentDecorations.Instance.Interacting ? "-interactive" : "");
+ const classname = "webBox-cont" + (this.props.isSelected() && CurrentUserUtils.SelectedTool === InkTool.None && !DocumentDecorations.Instance.Interacting ? "-interactive" : "");
return (
<>
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index 9147fc33f..2f9dc7f51 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -903,9 +903,6 @@ export namespace Doc {
export function UserDoc(): Doc { return manager._user_doc; }
export function SharingDoc(): Doc { return Cast(Doc.UserDoc().mySharedDocs, Doc, null); }
export function LinkDBDoc(): Doc { return Cast(Doc.UserDoc().myLinkDatabase, Doc, null); }
-
- export function SetSelectedTool(tool: InkTool) { Doc.UserDoc().activeInkTool = tool; }
- export function GetSelectedTool(): InkTool { return StrCast(Doc.UserDoc().activeInkTool, InkTool.None) as InkTool; }
export function SetUserDoc(doc: Doc) { return (manager._user_doc = doc); }
const isSearchMatchCache = computedFn(function IsSearchMatch(doc: Doc) {
@@ -1060,31 +1057,31 @@ export namespace Doc {
}
}
- /**
- * Filters document in a container collection:
- * all documents with the specified value for the specified key are included/excluded
- * based on the modifiers :"check", "x", undefined
- */
- export function setDocFilter(container: Opt<Doc>, key: string, value: any, modifiers?: "remove" | "match" | "check" | "x" | undefined) {
+ // filters document in a container collection:
+ // all documents with the specified value for the specified key are included/excluded
+ // based on the modifiers :"check", "x", undefined
+ export function setDocFilter(container: Opt<Doc>, key: string, value: any, modifiers: "remove" | "match" | "check" | "x", toggle?: boolean, fieldSuffix?: string) {
if (!container) return;
- const docFilters = Cast(container._docFilters, listSpec("string"), []);
+ const filterField = "_" + (fieldSuffix ? fieldSuffix + "-" : "") + "docFilters";
+ const docFilters = Cast(container[filterField], listSpec("string"), []);
runInAction(() => {
for (let i = 0; i < docFilters.length; i++) {
const fields = docFilters[i].split(":"); // split key:value:modifier
if (fields[0] === key && (fields[1] === value || modifiers === "match" || modifiers === "remove")) {
- if (fields[2] === modifiers && modifiers && fields[1] === value) return;
+ if (fields[2] === modifiers && modifiers && fields[1] === value) {
+ if (toggle) modifiers = "remove";
+ else return;
+ }
docFilters.splice(i, 1);
- container._docFilters = new List<string>(docFilters);
+ container[filterField] = new List<string>(docFilters);
break;
}
}
- if (typeof modifiers === "string") {
- if (!docFilters.length && modifiers === "match" && value === undefined) {
- container._docFilters = undefined;
- } else if (modifiers !== "remove") {
- docFilters.push(key + ":" + value + ":" + modifiers);
- container._docFilters = new List<string>(docFilters);
- }
+ if (!docFilters.length && modifiers === "match" && value === undefined) {
+ container[filterField] = undefined;
+ } else if (modifiers !== "remove") {
+ docFilters.push(key + ":" + value + ":" + modifiers);
+ container[filterField] = new List<string>(docFilters);
}
});
}
@@ -1335,5 +1332,5 @@ Scripting.addGlobal(function selectedDocs(container: Doc, excludeCollections: bo
(!excludeCollections || d.type !== DocumentType.COL || !Cast(d.data, listSpec(Doc), null)));
return docs.length ? new List(docs) : prevValue;
});
-Scripting.addGlobal(function setDocFilter(container: Doc, key: string, value: any, modifiers?: "match" | "check" | "x" | undefined) { Doc.setDocFilter(container, key, value, modifiers); });
+Scripting.addGlobal(function setDocFilter(container: Doc, key: string, value: any, modifiers: "match" | "check" | "x" | "remove") { Doc.setDocFilter(container, key, value, modifiers); });
Scripting.addGlobal(function setDocFilterRange(container: Doc, key: string, range: number[]) { Doc.setDocFilterRange(container, key, range); });
diff --git a/src/mobile/MobileInterface.tsx b/src/mobile/MobileInterface.tsx
index da3dbecbe..1001d9e19 100644
--- a/src/mobile/MobileInterface.tsx
+++ b/src/mobile/MobileInterface.tsx
@@ -76,7 +76,7 @@ export class MobileInterface extends React.Component {
componentDidMount = () => {
// if the home menu is in list view -> adjust the menu toggle appropriately
this._menuListView = this._homeDoc._viewType === "stacking" ? true : false;
- Doc.SetSelectedTool(InkTool.None); // ink should intially be set to none
+ CurrentUserUtils.SelectedTool = InkTool.None; // ink should intially be set to none
Doc.UserDoc().activeMobile = this._homeDoc; // active mobile set to home
AudioBox.Enabled = true;
@@ -419,10 +419,10 @@ export class MobileInterface extends React.Component {
button.style.color = this._ink ? "black" : "white";
if (!this._ink) {
- Doc.SetSelectedTool(InkTool.Pen);
+ CurrentUserUtils.SelectedTool = InkTool.Pen;
this._ink = true;
} else {
- Doc.SetSelectedTool(InkTool.None);
+ CurrentUserUtils.SelectedTool = InkTool.None;
this._ink = false;
}
}