aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authoraidahosa1 <aisosa_idahosa@brown.edu>2024-07-14 14:08:59 -0400
committeraidahosa1 <aisosa_idahosa@brown.edu>2024-07-14 14:08:59 -0400
commitd320d5c879909254cea28f68abb3345dc6c58f4d (patch)
tree1038943ce813d4322cab6b0110f151ad275ae51a /src
parent3e46e59b3919458d945745f457d8c76f13094796 (diff)
parent91d305e340ab50f54ec2cd6f4c86fdf6bb5bb75f (diff)
Merge branch 'master' into aisosa-starter
Diffstat (limited to 'src')
-rw-r--r--src/ClientUtils.ts18
-rw-r--r--src/client/documents/DocFromField.ts16
-rw-r--r--src/client/documents/Documents.ts16
-rw-r--r--src/client/util/SettingsManager.tsx4
-rw-r--r--src/client/util/SnappingManager.ts3
-rw-r--r--src/client/util/request-image-size.ts1
-rw-r--r--src/client/views/GestureOverlay.tsx12
-rw-r--r--src/client/views/MainView.tsx6
-rw-r--r--src/client/views/StyleProvider.tsx2
-rw-r--r--src/client/views/collections/CollectionCarousel3DView.tsx1
-rw-r--r--src/client/views/collections/CollectionDockingView.tsx2
-rw-r--r--src/client/views/collections/CollectionMenu.tsx23
-rw-r--r--src/client/views/collections/CollectionTreeView.tsx4
-rw-r--r--src/client/views/collections/TreeView.tsx10
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx51
-rw-r--r--src/client/views/collections/collectionSchema/CollectionSchemaView.tsx1
-rw-r--r--src/client/views/global/globalScripts.ts55
-rw-r--r--src/client/views/nodes/CollectionFreeFormDocumentView.tsx11
-rw-r--r--src/client/views/nodes/DataVizBox/components/TableBox.tsx1
-rw-r--r--src/client/views/nodes/DocumentView.tsx158
-rw-r--r--src/client/views/nodes/ImageBox.tsx5
-rw-r--r--src/client/views/nodes/WebBox.tsx1
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.tsx12
-rw-r--r--src/client/views/pdf/PDFViewer.tsx2
-rw-r--r--src/fields/Doc.ts47
25 files changed, 235 insertions, 227 deletions
diff --git a/src/ClientUtils.ts b/src/ClientUtils.ts
index 8e6cd78d0..ab5c157eb 100644
--- a/src/ClientUtils.ts
+++ b/src/ClientUtils.ts
@@ -86,6 +86,7 @@ export function returnEmptyDoclist() {
return [] as any[];
}
+// eslint-disable-next-line @typescript-eslint/no-namespace
export namespace ClientUtils {
export const CLICK_TIME = 300;
export const DRAG_THRESHOLD = 4;
@@ -483,30 +484,29 @@ export function smoothScrollHorizontal(duration: number, element: HTMLElement |
animateScroll();
}
-export function addStyleSheet(styleType: string = 'text/css') {
+export function addStyleSheet() {
const style = document.createElement('style');
- style.type = styleType;
const sheets = document.head.appendChild(style);
- return (sheets as any).sheet;
+ return sheets.sheet;
}
-export function addStyleSheetRule(sheet: any, selector: any, css: any, selectorPrefix = '.') {
+export function addStyleSheetRule(sheet: CSSStyleSheet | null, selector: string, css: string | {[key:string]: string}, selectorPrefix = '.') {
const propText =
typeof css === 'string'
? css
: Object.keys(css)
.map(p => p + ':' + (p === 'content' ? "'" + css[p] + "'" : css[p]))
.join(';');
- return sheet.insertRule(selectorPrefix + selector + '{' + propText + '}', sheet.cssRules.length);
+ return sheet?.insertRule(selectorPrefix + selector + '{' + propText + '}', sheet.cssRules.length);
}
-export function removeStyleSheetRule(sheet: any, rule: number) {
- if (sheet.rules.length) {
+export function removeStyleSheetRule(sheet: CSSStyleSheet|null, rule: number) {
+ if (sheet?.rules.length) {
sheet.removeRule(rule);
return true;
}
return false;
}
-export function clearStyleSheetRules(sheet: any) {
- if (sheet.rules.length) {
+export function clearStyleSheetRules(sheet: CSSStyleSheet|null) {
+ if (sheet?.rules.length) {
numberRange(sheet.rules.length).map(() => sheet.removeRule(0));
return true;
}
diff --git a/src/client/documents/DocFromField.ts b/src/client/documents/DocFromField.ts
index b65bbbdf5..9acb9c225 100644
--- a/src/client/documents/DocFromField.ts
+++ b/src/client/documents/DocFromField.ts
@@ -1,5 +1,4 @@
import { Doc, DocListCast } from '../../fields/Doc';
-import { InkField } from '../../fields/InkField';
import { List } from '../../fields/List';
import { StrCast } from '../../fields/Types';
import { AudioField, ImageField, PdfField, VideoField } from '../../fields/URLField';
@@ -12,7 +11,17 @@ export function ResetLayoutFieldKey(doc: Doc, fieldKey: string) {
doc.layout = StrCast(doc.layout).replace(/={'.*'}/, `={'${fieldKey}'}`);
return doc;
}
-export function DocumentFromField(target: Doc, fieldKey: string, proto?: Doc, options?: DocumentOptions): Doc | undefined {
+/**
+ * Creates a new document based on the type of (and containing the) data in the specified field of an existing document.
+ * If the field contains a list, then it may be useful to specify a classProto to indicate the type of
+ * collection Doc that gets created.
+ * @param target document to retrive field from
+ * @param fieldKey field key to retrieve
+ * @param classProto optionally a class proto to set on the new document
+ * @param options metadata configuration for new document
+ * @returns
+ */
+export function DocumentFromField(target: Doc, fieldKey: string, classProto?: Doc, options?: DocumentOptions): Doc | undefined {
const field = target[fieldKey];
const resolved = options ?? {};
const nonDocFieldToDoc = () => {
@@ -20,12 +29,11 @@ export function DocumentFromField(target: Doc, fieldKey: string, proto?: Doc, op
if (field instanceof VideoField) return Docs.Create.VideoDocument(field.url.href, resolved);
if (field instanceof PdfField) return Docs.Create.PdfDocument(field.url.href, resolved);
if (field instanceof AudioField) return Docs.Create.AudioDocument(field.url.href, resolved);
- if (field instanceof InkField) return Docs.Create.InkDocument(field.inkData, resolved);
if (field instanceof List && field[0] instanceof Doc) return Docs.Create.StackingDocument(DocListCast(field), resolved);
return Docs.Create.TextDocument('', { ...{ _width: 200, _height: 25, _layout_autoHeight: true }, ...resolved });
};
const created = field instanceof Doc ? field : ResetLayoutFieldKey(nonDocFieldToDoc(), fieldKey);
created.title = fieldKey;
- proto && created.proto && (created.proto = Doc.GetProto(proto));
+ classProto && created.proto && (created.proto = classProto);
return created;
}
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index c75c10eb8..6730a9a25 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -5,7 +5,7 @@ import { reaction } from 'mobx';
import { basename } from 'path';
import { ClientUtils, OmitKeys } from '../../ClientUtils';
import { DateField } from '../../fields/DateField';
-import { ActiveArrowEnd, ActiveArrowStart, ActiveDash, ActiveFillColor, ActiveInkBezierApprox, ActiveInkColor, ActiveInkWidth, ActiveIsInkMask, CreateLinkToActiveAudio, Doc, FieldType, Opt, updateCachedAcls } from '../../fields/Doc';
+import { CreateLinkToActiveAudio, Doc, FieldType, Opt, updateCachedAcls } from '../../fields/Doc';
import { Initializing } from '../../fields/DocSymbols';
import { HtmlField } from '../../fields/HtmlField';
import { InkField } from '../../fields/InkField';
@@ -843,18 +843,7 @@ export namespace Docs {
return linkDoc;
}
- export function InkDocument(
- points: PointData[],
- options: DocumentOptions = {},
- strokeWidth = ActiveInkWidth(),
- color = ActiveInkColor(),
- strokeBezier = ActiveInkBezierApprox(),
- fillColor = ActiveFillColor(),
- arrowStart = ActiveArrowStart(),
- arrowEnd = ActiveArrowEnd(),
- dash = ActiveDash(),
- isInkMask = ActiveIsInkMask()
- ) {
+ export function InkDocument(points: PointData[], options: DocumentOptions = {}, strokeWidth: number, color: string, strokeBezier: string, fillColor: string, arrowStart: string, arrowEnd: string, dash: string, isInkMask: boolean) {
const ink = InstanceFromProto(Prototypes.get(DocumentType.INK), '', { title: 'ink', ...options });
const I = Doc.GetProto(ink);
// I.layout_hideOpenButton = true; // don't show open full screen button when selected
@@ -870,6 +859,7 @@ export namespace Docs {
I.text_align = 'center';
I.rotation = 0;
I.defaultDoubleClick = 'ignore';
+ I.keepZWhenDragged = true;
I.author_date = new DateField();
I.acl_Guest = Doc.defaultAclPrivate ? SharingPermissions.None : SharingPermissions.View;
// I.acl_Override = SharingPermissions.Unset;
diff --git a/src/client/util/SettingsManager.tsx b/src/client/util/SettingsManager.tsx
index d3c10f9f4..278931cdd 100644
--- a/src/client/util/SettingsManager.tsx
+++ b/src/client/util/SettingsManager.tsx
@@ -29,7 +29,7 @@ export enum ColorScheme {
}
@observer
-export class SettingsManager extends React.Component<{}> {
+export class SettingsManager extends React.Component<object> {
// eslint-disable-next-line no-use-before-define
public static Instance: SettingsManager;
static _settingsStyle = addStyleSheet();
@@ -123,7 +123,7 @@ export class SettingsManager extends React.Component<{}> {
'change color scheme'
);
- constructor(props: {}) {
+ constructor(props: object) {
super(props);
makeObservable(this);
SettingsManager.Instance = this;
diff --git a/src/client/util/SnappingManager.ts b/src/client/util/SnappingManager.ts
index 1337d271f..cc0366c5b 100644
--- a/src/client/util/SnappingManager.ts
+++ b/src/client/util/SnappingManager.ts
@@ -11,6 +11,7 @@ export class SnappingManager {
return SnappingManager._manager ?? new SnappingManager();
}
+ @observable _longPress = false;
@observable _shiftKey = false;
@observable _ctrlKey = false;
@observable _metaKey = false;
@@ -43,6 +44,7 @@ export class SnappingManager {
public static get HorizSnapLines() { return this.Instance._horizSnapLines; } // prettier-ignore
public static get VertSnapLines() { return this.Instance._vertSnapLines; } // prettier-ignore
+ public static get LongPress() { return this.Instance._longPress; } // prettier-ignore
public static get ShiftKey() { return this.Instance._shiftKey; } // prettier-ignore
public static get CtrlKey() { return this.Instance._ctrlKey; } // prettier-ignore
public static get MetaKey() { return this.Instance._metaKey; } // prettier-ignore
@@ -58,6 +60,7 @@ export class SnappingManager {
public static get PropertiesWidth(){ return this.Instance._propertyWid; } // prettier-ignore
public static get PrintToConsole() { return this.Instance._printToConsole; } // prettier-ignore
+ public static SetLongPress = (press: boolean) => runInAction(() => {this.Instance._longPress = press}); // prettier-ignore
public static SetShiftKey = (down: boolean) => runInAction(() => {this.Instance._shiftKey = down}); // prettier-ignore
public static SetCtrlKey = (down: boolean) => runInAction(() => {this.Instance._ctrlKey = down}); // prettier-ignore
public static SetMetaKey = (down: boolean) => runInAction(() => {this.Instance._metaKey = down}); // prettier-ignore
diff --git a/src/client/util/request-image-size.ts b/src/client/util/request-image-size.ts
index 0f98a2710..48cb6e3a5 100644
--- a/src/client/util/request-image-size.ts
+++ b/src/client/util/request-image-size.ts
@@ -54,6 +54,7 @@ module.exports = function requestImageSize(options: any) {
}
} catch (err) {
/* empty */
+ console.log("Error: ", err)
}
});
diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx
index 2f26bdaef..e3e252593 100644
--- a/src/client/views/GestureOverlay.tsx
+++ b/src/client/views/GestureOverlay.tsx
@@ -4,25 +4,23 @@ import { observer } from 'mobx-react';
import * as React from 'react';
import { returnEmptyDoclist, returnEmptyFilter, returnEmptyString, returnFalse, setupMoveUpEvents } from '../../ClientUtils';
import { emptyFunction } from '../../Utils';
+import { Doc, Opt } from '../../fields/Doc';
+import { InkData, InkField, InkTool } from '../../fields/InkField';
+import { NumCast } from '../../fields/Types';
import {
ActiveArrowEnd,
ActiveArrowScale,
ActiveArrowStart,
ActiveDash,
- ActiveFillColor,
ActiveInkBezierApprox,
ActiveInkColor,
ActiveInkWidth,
- Doc,
- Opt,
SetActiveArrowStart,
SetActiveDash,
SetActiveFillColor,
SetActiveInkColor,
SetActiveInkWidth,
-} from '../../fields/Doc';
-import { InkData, InkField, InkTool } from '../../fields/InkField';
-import { NumCast } from '../../fields/Types';
+} from './nodes/DocumentView';
// import MobileInkOverlay from '../../mobile/MobileInkOverlay';
import { Gestures } from '../../pen-gestures/GestureTypes';
import { GestureUtils } from '../../pen-gestures/GestureUtils';
@@ -32,7 +30,7 @@ import { ScriptingGlobals } from '../util/ScriptingGlobals';
import { Transform } from '../util/Transform';
import './GestureOverlay.scss';
import { ObservableReactComponent } from './ObservableReactComponent';
-import { DocumentView } from './nodes/DocumentView';
+import { ActiveFillColor, DocumentView } from './nodes/DocumentView';
export enum ToolglassTools {
InkToText = 'inktotext',
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 6c95bf4db..0d42f4099 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -559,16 +559,16 @@ export class MainView extends ObservableReactComponent<{}> {
private longPressTimer: NodeJS.Timeout | undefined;
globalPointerClick = action(() => {
this.longPressTimer && clearTimeout(this.longPressTimer);
- DocumentView.LongPress = false;
+ SnappingManager.SetLongPress(false);
});
globalPointerMove = action((e: PointerEvent) => {
if (e.movementX > 3 || e.movementY > 3) this.longPressTimer && clearTimeout(this.longPressTimer);
});
globalPointerDown = action((e: PointerEvent) => {
- DocumentView.LongPress = false;
+ SnappingManager.SetLongPress(false);
this.longPressTimer = setTimeout(
action(() => {
- DocumentView.LongPress = true;
+ SnappingManager.SetLongPress(true);
}),
1000
);
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index f4d73cd1d..40d0358d2 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -155,7 +155,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<FieldViewProps &
case StyleProp.DocContents: return undefined;
case StyleProp.WidgetColor: return isAnnotated ? Colors.LIGHT_BLUE : 'dimgrey';
case StyleProp.Opacity: return componentView?.isUnstyledView?.() ? 1 : Cast(doc?._opacity, "number", Cast(doc?.opacity, 'number', null));
- case StyleProp.FontColor: return StrCast(doc?.[fieldKey + 'fontColor'], StrCast(Doc.UserDoc().fontColor, color()));
+ case StyleProp.FontColor: return StrCast(doc?.[fieldKey + 'fontColor'], isCaption ? lightOrDark(backgroundCol()) : StrCast(Doc.UserDoc().fontColor, color()));
case StyleProp.FontSize: return StrCast(doc?.[fieldKey + 'fontSize'], StrCast(Doc.UserDoc().fontSize));
case StyleProp.FontFamily: return StrCast(doc?.[fieldKey + 'fontFamily'], StrCast(Doc.UserDoc().fontFamily));
case StyleProp.FontWeight: return StrCast(doc?.[fieldKey + 'fontWeight'], StrCast(Doc.UserDoc().fontWeight));
diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx
index 27c85533f..38f681e87 100644
--- a/src/client/views/collections/CollectionCarousel3DView.tsx
+++ b/src/client/views/collections/CollectionCarousel3DView.tsx
@@ -17,6 +17,7 @@ import { FocusViewOptions } from '../nodes/FocusViewOptions';
import './CollectionCarousel3DView.scss';
import { CollectionSubView } from './CollectionSubView';
+// eslint-disable-next-line @typescript-eslint/no-var-requires
const { CAROUSEL3D_CENTER_SCALE, CAROUSEL3D_SIDE_SCALE, CAROUSEL3D_TOP } = require('../global/globalCssVariables.module.scss');
@observer
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 73179a266..2a36e96bf 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -58,7 +58,7 @@ export class CollectionDockingView extends CollectionSubView() {
return this._goldenLayout._maximisedItem !== null;
}
private _goldenLayout: any = null;
- static _highlightStyleSheet: any = addStyleSheet();
+ static _highlightStyleSheet = addStyleSheet();
constructor(props: any) {
super(props);
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index 3eb3008c4..b2f0280a5 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -17,7 +17,7 @@ import { DocData } from '../../../fields/DocSymbols';
import { List } from '../../../fields/List';
import { ObjectField } from '../../../fields/ObjectField';
import { RichTextField } from '../../../fields/RichTextField';
-import { BoolCast, Cast, DocCast, NumCast, StrCast } from '../../../fields/Types';
+import { BoolCast, Cast, NumCast, StrCast } from '../../../fields/Types';
import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes';
import { DragManager } from '../../util/DragManager';
import { dropActionType } from '../../util/DropActionTypes';
@@ -47,7 +47,7 @@ export class CollectionMenu extends AntimodeMenu<CollectionMenuProps> {
private _docBtnRef = React.createRef<HTMLDivElement>();
- constructor(props: any) {
+ constructor(props: CollectionMenuProps) {
super(props);
makeObservable(this);
CollectionMenu.Instance = this;
@@ -279,8 +279,8 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewMenu
initialize: (button: Doc) => {
const activeDash = Doc.ActiveDashboard;
if (activeDash) {
- button.target_childFilters = (Doc.MySearcher._childFilters || activeDash._childFilters) instanceof ObjectField ? ObjectField.MakeCopy((Doc.MySearcher._childFilters || activeDash._childFilters) as any as ObjectField) : undefined;
- button.target_searchFilterDocs = activeDash._searchFilterDocs instanceof ObjectField ? ObjectField.MakeCopy(activeDash._searchFilterDocs as any as ObjectField) : undefined;
+ button.target_childFilters = (Doc.MySearcher._childFilters || activeDash._childFilters) instanceof ObjectField ? ObjectField.MakeCopy((Doc.MySearcher._childFilters || activeDash._childFilters) as ObjectField) : undefined;
+ button.target_searchFilterDocs = activeDash._searchFilterDocs instanceof ObjectField ? ObjectField.MakeCopy(activeDash._searchFilterDocs) : undefined;
}
},
};
@@ -338,15 +338,9 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewMenu
this._currentKey = this._currentKey || (this._buttonizableCommands?.length ? this._buttonizableCommands[0]?.title : '');
});
- @undoBatch
- viewChanged = (e: React.ChangeEvent) => {
- const target = this.document !== Doc.MyLeftSidebarPanel ? this.document : DocCast(this.document.proto);
- target._type_collection = (e.target as any).selectedOptions[0].value;
- };
-
- commandChanged = (e: React.ChangeEvent) => {
+ commandChanged = (e: React.ChangeEvent<HTMLSelectElement>) => {
runInAction(() => {
- this._currentKey = (e.target as any).selectedOptions[0].value;
+ this._currentKey = e.target.selectedOptions[0].value;
});
};
@@ -485,7 +479,7 @@ export class CollectionNoteTakingViewChrome extends React.Component<CollectionVi
};
@action
- onKeyChange = (e: React.ChangeEvent, { newValue }: { newValue: string }) => {
+ onKeyChange = (e: React.FormEvent<Element>, { newValue }: { newValue: string }) => {
this._currentKey = newValue;
};
@@ -538,7 +532,6 @@ export class CollectionNoteTakingViewChrome extends React.Component<CollectionVi
autosuggestProps: {
inputProps: {
value: this._currentKey,
- // @ts-ignore
onChange: this.onKeyChange,
},
getSuggestionValue: this.getSuggestionValue,
@@ -733,7 +726,7 @@ export class CollectionGridViewChrome extends React.Component<CollectionViewMenu
onChange={this.changeCompactType}
value={StrCast(this.document.gridStartCompaction, StrCast(this.document.gridCompaction))}>
{['vertical', 'horizontal', 'none'].map(type => (
- <option className="collectionGridViewChrome-viewOption" onPointerDown={stopPropagation} value={type}>
+ <option key={type} className="collectionGridViewChrome-viewOption" onPointerDown={stopPropagation} value={type}>
{this.resize ? type[0].toUpperCase() + type.substring(1) : 'Compact: ' + type}
</option>
))}
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index c39df2c76..285598600 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -52,7 +52,6 @@ export type collectionTreeViewProps = {
export class CollectionTreeView extends CollectionSubView<Partial<collectionTreeViewProps>>() {
public static AddTreeFunc = 'addTreeFolder(this.embedContainer)';
private _treedropDisposer?: DragManager.DragDropDisposer;
- private _mainEle?: HTMLDivElement;
private _titleRef?: HTMLDivElement | HTMLInputElement | null;
private _disposers: { [name: string]: IReactionDisposer } = {};
private _isDisposing = false; // notes that instance is in process of being disposed
@@ -83,8 +82,6 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
@observable _titleHeight = 0; // height of the title bar
- MainEle = () => this._mainEle;
-
// these should stay in synch with counterparts in DocComponent.ts ViewBoxAnnotatableComponent
@observable _isAnyChildContentActive = false;
whenChildContentsActiveChanged = action((isActive: boolean) => {
@@ -134,7 +131,6 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
};
protected createTreeDropTarget = (ele: HTMLDivElement) => {
this._treedropDisposer?.();
- this._mainEle = ele;
if (ele) this._treedropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this), this.Document, this.onInternalPreDrop.bind(this));
};
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index b82421e6b..f69aea2a7 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -469,14 +469,12 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
return false;
}
- refTransform = (ref: HTMLDivElement | undefined | null) => {
+ refTransform = (ref: HTMLElement | undefined | null) => {
if (!ref) return this.ScreenToLocalTransform();
- const { translateX, translateY } = ClientUtils.GetScreenTransform(ref);
- const outerXf = ClientUtils.GetScreenTransform(this.treeView.MainEle());
- const offset = this.ScreenToLocalTransform().transformDirection(outerXf.translateX - translateX, outerXf.translateY - translateY);
- return this.ScreenToLocalTransform().translate(offset[0], offset[1]);
+ const { translateX, translateY, scale } = ClientUtils.GetScreenTransform(ref);
+ return new Transform(-translateX, -translateY, 1).scale(1/scale);
};
- docTransform = () => this.refTransform(this._dref?.ContentRef?.current);
+ docTransform = () => this.refTransform(this._dref?.ContentDiv);
getTransform = () => this.refTransform(this._tref.current);
embeddedPanelWidth = () => this._props.panelWidth() / (this.treeView._props.NativeDimScaling?.() || 1);
embeddedPanelHeight = () => {
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index b6e1fca77..5b7f09be3 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -9,7 +9,8 @@ import { computedFn } from 'mobx-utils';
import * as React from 'react';
import { ClientUtils, DashColor, lightOrDark, OmitKeys, returnFalse, returnZero, setupMoveUpEvents, UpdateIcon } from '../../../../ClientUtils';
import { DateField } from '../../../../fields/DateField';
-import { ActiveEraserWidth, ActiveInkWidth, Doc, DocListCast, Field, FieldType, Opt, SetActiveInkColor, SetActiveInkWidth } from '../../../../fields/Doc';
+import { Doc, DocListCast, Field, FieldType, Opt } from '../../../../fields/Doc';
+import { ActiveArrowEnd, ActiveArrowStart, ActiveDash, ActiveEraserWidth, ActiveInkBezierApprox, ActiveInkColor, ActiveInkWidth, ActiveIsInkMask, SetActiveInkColor, SetActiveInkWidth } from '../../nodes/DocumentView';
import { DocData, Height, Width } from '../../../../fields/DocSymbols';
import { Id } from '../../../../fields/FieldSymbols';
import { InkData, InkField, InkTool, Segment } from '../../../../fields/InkField';
@@ -38,7 +39,7 @@ import { ContextMenu } from '../../ContextMenu';
import { InkingStroke } from '../../InkingStroke';
import { CollectionFreeFormDocumentView } from '../../nodes/CollectionFreeFormDocumentView';
import { SchemaCSVPopUp } from '../../nodes/DataVizBox/SchemaCSVPopUp';
-import { DocumentView } from '../../nodes/DocumentView';
+import { ActiveFillColor, DocumentView } from '../../nodes/DocumentView';
import { FieldViewProps } from '../../nodes/FieldView';
import { FocusViewOptions } from '../../nodes/FocusViewOptions';
import { FormattedTextBox } from '../../nodes/formattedText/FormattedTextBox';
@@ -87,8 +88,10 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
}
private _clusters = new CollectionFreeFormClusters(this);
- private _oldWheel: any;
- private _panZoomTransitionTimer: any;
+ private _oldWheel: HTMLDivElement | null = null;
+ private _panZoomTransitionTimer: NodeJS.Timeout | undefined = undefined;
+ private _brushtimer: NodeJS.Timeout | undefined = undefined;
+ private _brushtimer1: NodeJS.Timeout | undefined = undefined;
private _lastX: number = 0;
private _lastY: number = 0;
private _downX: number = 0;
@@ -97,8 +100,6 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
private _disposers: { [name: string]: IReactionDisposer } = {};
private _renderCutoffData = observable.map<string, boolean>();
private _batch: UndoManager.Batch | undefined = undefined;
- private _brushtimer: any;
- private _brushtimer1: any;
private _keyTimer: NodeJS.Timeout | undefined; // timer for turning off transition flag when key frame change has completed. Need to clear this if you do a second navigation before first finishes, or else first timer can go off during second naviation.
private _presEaseFunc: string = 'ease';
@@ -129,7 +130,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
@observable _eraserX: number = 0;
@observable _eraserY: number = 0;
@observable _showEraserCircle: boolean = false; // to determine whether the radius eraser should show
- constructor(props: any) {
+ constructor(props: collectionFreeformViewProps) {
super(props);
makeObservable(this);
}
@@ -550,7 +551,14 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
_width: B.width + inkWidth,
_height: B.height + inkWidth,
stroke_showLabel: BoolCast(Doc.UserDoc().activeInkHideTextLabels)}, // prettier-ignore
- inkWidth
+ inkWidth,
+ ActiveInkColor(),
+ ActiveInkBezierApprox(),
+ ActiveFillColor(),
+ ActiveArrowStart(),
+ ActiveArrowEnd(),
+ ActiveDash(),
+ ActiveIsInkMask()
);
if (Doc.ActiveTool === InkTool.Write) {
this.unprocessedDocs.push(inkDoc);
@@ -634,7 +642,14 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
_width: B.width + inkWidth,
_height: B.height + inkWidth,
stroke_showLabel: BoolCast(Doc.UserDoc().activeInkHideTextLabels)}, // prettier-ignore
- inkWidth
+ inkWidth,
+ ActiveInkColor(),
+ ActiveInkBezierApprox(),
+ ActiveFillColor(),
+ ActiveArrowStart(),
+ ActiveArrowEnd(),
+ ActiveDash(),
+ ActiveIsInkMask()
);
});
newStrokes && this.addDocument?.(newStrokes);
@@ -684,8 +699,8 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
return false;
};
- forceStrokeGesture = (e: PointerEvent, gesture: Gestures, points: InkData, text?: any) => {
- this.onGesture(e, new GestureUtils.GestureEvent(gesture, points, InkField.getBounds(points), text));
+ forceStrokeGesture = (e: PointerEvent, gesture: Gestures, points: InkData) => {
+ this.onGesture(e, new GestureUtils.GestureEvent(gesture, points, InkField.getBounds(points)));
};
onPointerMove = (e: PointerEvent) => {
@@ -1639,7 +1654,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
* since rendering a large collection of documents can be slow, at startup, docs are rendered in batches.
* each doc's render() method will call the cutoff provider which will let the doc know if it should render itself yet, or wait
*/
- renderCutoffProvider = computedFn((doc: Doc) => (this.Document.isTemplateDoc ? false : !this._renderCutoffData.get(doc[Id] + '')));
+ renderCutoffProvider = computedFn((doc: Doc) => (this.Document.isTemplateDoc || this.Document.isTemplateForField ? false : !this._renderCutoffData.get(doc[Id] + '')));
doEngineLayout(
poolData: Map<string, PoolData>,
@@ -1673,7 +1688,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
.forEach(entry =>
elements.push({
ele: this.getChildDocView(entry[1]),
- bounds: (entry[1].opacity === 0 ? { ...entry[1], width: 0, height: 0 } : { ...entry[1] }) as any,
+ bounds: (entry[1].opacity === 0 ? { payload:undefined, type:"", ...entry[1], width: 0, height: 0 } : { payload:undefined, type:"",...entry[1] }),
inkMask: BoolCast(entry[1].pair.layout.stroke_isInkMask) ? NumCast(entry[1].pair.layout.opacity, 1) : -1,
})
);
@@ -1795,10 +1810,11 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
Object.values(this._disposers).forEach(disposer => disposer?.());
}
- updateIcon = () =>
- UpdateIcon(
+ updateIcon = () => {
+ const contentDiv = this.DocumentView?.().ContentDiv;
+ contentDiv && UpdateIcon(
this.layoutDoc[Id] + '-icon' + new Date().getTime(),
- this.DocumentView?.().ContentDiv!,
+ contentDiv,
NumCast(this.layoutDoc._width),
NumCast(this.layoutDoc._height),
this._props.PanelWidth(),
@@ -1813,6 +1829,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
this.dataDoc.icon_nativeHeight = nativeHeight;
}
);
+ }
@action
onCursorMove = (e: React.PointerEvent) => {
@@ -1993,7 +2010,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
incrementalRender = action(() => {
if (!DocumentView.LightboxDoc() || DocumentView.LightboxContains(this.DocumentView?.())) {
const layoutUnrendered = this.childDocs.filter(doc => !this._renderCutoffData.get(doc[Id]));
- const loadIncrement = this.Document.isTemplateDoc ? Number.MAX_VALUE : 5;
+ const loadIncrement = this.Document.isTemplateDoc || this.Document.isTemplateForField ? Number.MAX_VALUE : 5;
for (let i = 0; i < Math.min(layoutUnrendered.length, loadIncrement); i++) {
this._renderCutoffData.set(layoutUnrendered[i][Id] + '', true);
}
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
index 7c2cfd15f..6bea53355 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
@@ -32,6 +32,7 @@ import './CollectionSchemaView.scss';
import { SchemaColumnHeader } from './SchemaColumnHeader';
import { SchemaRowBox } from './SchemaRowBox';
+// eslint-disable-next-line @typescript-eslint/no-var-requires
const { SCHEMA_NEW_NODE_HEIGHT } = require('../../global/globalCssVariables.module.scss'); // prettier-ignore
export const FInfotoColType: { [key: string]: ColumnType } = {
diff --git a/src/client/views/global/globalScripts.ts b/src/client/views/global/globalScripts.ts
index 6ea1751a9..616633bc1 100644
--- a/src/client/views/global/globalScripts.ts
+++ b/src/client/views/global/globalScripts.ts
@@ -1,25 +1,10 @@
import { Colors } from 'browndash-components';
import { action, runInAction } from 'mobx';
import { aggregateBounds } from '../../../Utils';
-import {
- ActiveFillColor,
- ActiveEraserWidth,
- ActiveInkColor,
- ActiveInkHideTextLabels,
- ActiveInkWidth,
- ActiveIsInkMask,
- Doc,
- DocListCast,
- Opt,
- SetActiveFillColor,
- SetActiveInkColor,
- SetActiveInkHideTextLabels,
- SetActiveInkWidth,
- SetActiveIsInkMask,
- SetEraserWidth,
-} from '../../../fields/Doc';
+import { Doc, DocListCast, NumListCast, Opt } from '../../../fields/Doc';
import { DocData } from '../../../fields/DocSymbols';
import { InkTool } from '../../../fields/InkField';
+import { List } from '../../../fields/List';
import { BoolCast, Cast, NumCast, StrCast } from '../../../fields/Types';
import { WebField } from '../../../fields/URLField';
import { Gestures } from '../../../pen-gestures/GestureTypes';
@@ -31,7 +16,21 @@ import { GestureOverlay } from '../GestureOverlay';
import { InkingStroke } from '../InkingStroke';
import { CollectionFreeFormView } from '../collections/collectionFreeForm';
import { CollectionFreeFormDocumentView } from '../nodes/CollectionFreeFormDocumentView';
-import { DocumentView } from '../nodes/DocumentView';
+import {
+ ActiveEraserWidth,
+ ActiveFillColor,
+ ActiveInkColor,
+ ActiveInkHideTextLabels,
+ ActiveInkWidth,
+ ActiveIsInkMask,
+ DocumentView,
+ SetActiveFillColor,
+ SetActiveInkColor,
+ SetActiveInkHideTextLabels,
+ SetActiveInkWidth,
+ SetActiveIsInkMask,
+ SetEraserWidth,
+} from '../nodes/DocumentView';
import { ImageBox } from '../nodes/ImageBox';
import { VideoBox } from '../nodes/VideoBox';
import { WebBox } from '../nodes/WebBox';
@@ -62,7 +61,7 @@ ScriptingGlobals.add(function setView(view: string, getSelected: boolean) {
// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function setBackgroundColor(color?: string, checkResult?: boolean) {
const selectedViews = DocumentView.Selected();
- if (Doc.ActiveTool !== InkTool.None) {
+ if (Doc.ActiveTool !== InkTool.None && !selectedViews.lastElement()?.Document._layout_isSvg) {
if (checkResult) {
return ActiveFillColor();
}
@@ -655,15 +654,19 @@ function setActiveTool(tool: InkTool | Gestures, keepPrim: boolean, checkResult?
GestureOverlay.Instance.InkShape = tool as Gestures;
}
} else if (tool) {
- if ([InkTool.StrokeEraser, InkTool.RadiusEraser, InkTool.SegmentEraser].includes(tool as any)) {
- Doc.UserDoc().activeEraserTool = tool;
- }
- // pen or eraser
- if (Doc.ActiveTool === tool && !GestureOverlay.Instance.InkShape && !keepPrim) {
+ if (Doc.UserDoc().ActiveTool === tool) {
Doc.ActiveTool = InkTool.None;
} else {
- Doc.ActiveTool = tool as any;
- GestureOverlay.Instance.InkShape = undefined;
+ if ([InkTool.StrokeEraser, InkTool.RadiusEraser, InkTool.SegmentEraser].includes(tool as any)) {
+ Doc.UserDoc().activeEraserTool = tool;
+ }
+ // pen or eraser
+ if (Doc.ActiveTool === tool && !GestureOverlay.Instance.InkShape && !keepPrim) {
+ Doc.ActiveTool = InkTool.None;
+ } else {
+ Doc.ActiveTool = tool as any;
+ GestureOverlay.Instance.InkShape = undefined;
+ }
}
} else {
Doc.ActiveTool = InkTool.None;
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 034a38e9c..ee67dd305 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -20,6 +20,11 @@ import { DocumentView, DocumentViewProps } from './DocumentView';
import { FieldViewProps } from './FieldView';
import { OpenWhere } from './OpenWhere';
+export enum GroupActive { // flags for whether a view is activate because of its relationship to a group
+ group = 'group', // this is a group that is activated because it's on an active canvas, but is not part of some other group
+ child = 'child', // this is a group child that is activated because its containing group is activated
+ inactive = 'inactive', // this is a group child but it is not active
+}
/// Ugh, typescript has no run-time way of iterating through the keys of an interface. so we need
/// manaully keep this list of keys in synch wih the fields of the freeFormProps interface
const freeFormPropsKeys = ['x', 'y', 'z', 'zIndex', 'rotation', 'opacity', 'backgroundColor', 'color', 'highlight', 'width', 'height', 'autoDim', 'transition'];
@@ -274,7 +279,9 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
if (this._props.isAnyChildContentActive()) return undefined;
const backColor = this.BackgroundColor;
const isGroup = this.dataDoc.isGroup && (!backColor || backColor === 'transparent');
- return isGroup ? (this._props.isDocumentActive?.() ? 'group' : this._props.isGroupActive?.() ? 'child' : 'inactive') : this._props.isGroupActive?.() ? 'child' : undefined;
+ return isGroup ? (this._props.isDocumentActive?.() ? GroupActive.group :
+ this._props.isGroupActive?.() ? GroupActive.child : GroupActive.inactive) :
+ this._props.isGroupActive?.() ? GroupActive.child : undefined; // prettier-ignore
};
localRotation = () => this._props.rotation;
render() {
@@ -313,6 +320,6 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
}
}
// eslint-disable-next-line prefer-arrow-callback
-ScriptingGlobals.add(function gotoFrame(doc: any, newFrame: any) {
+ScriptingGlobals.add(function gotoFrame(doc: Doc, newFrame: number) {
CollectionFreeFormDocumentView.gotoKeyFrame(doc, newFrame);
});
diff --git a/src/client/views/nodes/DataVizBox/components/TableBox.tsx b/src/client/views/nodes/DataVizBox/components/TableBox.tsx
index a1deb1625..d2e82284e 100644
--- a/src/client/views/nodes/DataVizBox/components/TableBox.tsx
+++ b/src/client/views/nodes/DataVizBox/components/TableBox.tsx
@@ -18,6 +18,7 @@ import { DocumentView } from '../../DocumentView';
import { DataVizView } from '../DataVizBox';
import './Chart.scss';
+// eslint-disable-next-line @typescript-eslint/no-var-requires
const { DATA_VIZ_TABLE_ROW_HEIGHT } = require('../../../global/globalCssVariables.module.scss'); // prettier-ignore
interface TableBoxProps {
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 9ff96c692..f09e0c73d 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -43,6 +43,7 @@ import { ObserverJsxParser } from '../ObservableReactComponent';
import { PinProps } from '../PinFuncs';
import { StyleProp } from '../StyleProp';
import { ViewBoxInterface } from '../ViewBoxInterface';
+import { GroupActive } from './CollectionFreeFormDocumentView';
import { DocumentContentsView } from './DocumentContentsView';
import { DocumentLinksButton } from './DocumentLinksButton';
import './DocumentView.scss';
@@ -52,7 +53,7 @@ import { OpenWhere, OpenWhereMod } from './OpenWhere';
import { FormattedTextBox } from './formattedText/FormattedTextBox';
import { PresEffect, PresEffectDirection } from './trails/PresEnums';
import SpringAnimation from './trails/SlideEffect';
-import { SpringSettings, SpringType, springMappings } from './trails/SpringUtils';
+import { SpringType, springMappings } from './trails/SpringUtils';
interface Window {
MediaRecorder: MediaRecorder;
@@ -153,7 +154,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
@computed get disableClickScriptFunc() {
const onScriptDisable = this._props.onClickScriptDisable ?? this._componentView?.onClickScriptDisable?.() ?? this.layoutDoc.onClickScriptDisable;
- return (DocumentView.LongPress ||
+ return (SnappingManager.LongPress ||
onScriptDisable === 'always' ||
(onScriptDisable !== 'never' && (this.rootSelected() || this._componentView?.isAnyChildContentActive?.()))); // prettier-ignore
}
@@ -297,17 +298,15 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
e.stopPropagation();
};
onClick = action((e: React.MouseEvent | React.PointerEvent) => {
- if (this._props.isGroupActive?.() === 'child' && !this._props.isDocumentActive?.()) return;
- const documentView = this._docView;
- if (documentView && !this.Document.ignoreClick && this._props.renderDepth >= 0 && ClientUtils.isClick(e.clientX, e.clientY, this._downX, this._downY, this._downTime)) {
+ if (this._props.isGroupActive?.() === GroupActive.child && !this._props.isDocumentActive?.()) return;
+ if (this._docView && !this.Document.ignoreClick && this._props.renderDepth >= 0 && ClientUtils.isClick(e.clientX, e.clientY, this._downX, this._downY, this._downTime)) {
let stopPropagate = true;
let preventDefault = true;
- !this.layoutDoc._keepZWhenDragged && this._props.bringToFront?.(this.Document);
const scriptProps = {
this: this.Document,
_readOnly_: false,
scriptContext: this._props.scriptContext,
- documentView,
+ documentView: this._docView,
clientX: e.clientX,
clientY: e.clientY,
shiftKey: e.shiftKey,
@@ -317,44 +316,39 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
};
if (this._doubleTap) {
const defaultDblclick = this._props.defaultDoubleClick?.() || this.Document.defaultDoubleClick;
- if (this.onDoubleClickHdlr?.script) {
- UndoManager.RunInBatch(() => this.onDoubleClickHdlr.script.run(scriptProps, console.log).result?.select && this._props.select(false), 'on double click: ' + this.Document.title);
- } else if (!Doc.IsSystem(this.Document) && defaultDblclick !== 'ignore') {
- UndoManager.RunInBatch(() => this._props.addDocTab(this.Document, OpenWhere.lightboxAlways), 'double tap');
- DocumentView.DeselectAll();
- Doc.UnBrushDoc(this.Document);
- } else {
- this._singleClickFunc?.();
- }
+ undoable(() => {
+ if (this.onDoubleClickHdlr?.script) {
+ this.onDoubleClickHdlr.script.run(scriptProps, console.log).result?.select && this._props.select(false);
+ } else if (!Doc.IsSystem(this.Document) && defaultDblclick !== 'ignore') {
+ this._props.addDocTab(this.Document, OpenWhere.lightboxAlways);
+ DocumentView.DeselectAll();
+ Doc.UnBrushDoc(this.Document);
+ } else this._singleClickFunc?.();
+ }, 'on double click: ' + this.Document.title)();
this._doubleClickTimeout && clearTimeout(this._doubleClickTimeout);
this._doubleClickTimeout = undefined;
this._singleClickFunc = undefined;
} else {
- let clickFunc: undefined | (() => any);
- if (!this.disableClickScriptFunc && this.onClickHdlr?.script) {
- clickFunc = undoable(() => {
- this.onClickHdlr?.script.run(scriptProps, console.log).result?.select && this._props.select(false);
- }, 'click ' + this.Document.title);
- } else {
- // onDragStart implies a button doc that we don't want to select when clicking. RootDocument & isTemplateForField implies we're clicking on part of a template instance and we want to select the whole template, not the part
- if (this.layoutDoc.onDragStart && !(e.ctrlKey || e.button > 0)) {
- stopPropagate = false;
- }
- preventDefault = false;
- }
- const sendToBack = e.altKey ? () => documentView._props.bringToFront?.(this.Document, true) : undefined;
+ const sendToBack = e.altKey ? () => this._props.bringToFront?.(this.Document, true) : undefined;
const selectFunc = () => {
+ !this.layoutDoc._keepZWhenDragged && this._props.bringToFront?.(this.Document);
// selecting a view that is part of a template proxies the selection back to the root of the template
const templateRoot = !(e.ctrlKey || e.button > 0) && this._props.docViewPath?.().reverse().find(dv => !dv._props.TemplateDataDocument); // prettier-ignore
(templateRoot || this._docView)?.select(e.ctrlKey || e.shiftKey, e.metaKey);
};
- this._singleClickFunc = clickFunc ?? sendToBack ?? selectFunc;
- const waitFordblclick = this._props.waitForDoubleClickToClick?.() ?? this.Document.waitForDoubleClickToClick;
- if ((clickFunc && waitFordblclick !== 'never') || waitFordblclick === 'always') {
+ const clickFunc = this.onClickFunc?.()?.script ? () => (this.onClickFunc?.()?.script.run(scriptProps, console.log).result as Opt<{ select: boolean }>)?.select && this._props.select(false) : undefined;
+ if (!clickFunc) {
+ // onDragStart implies a button doc that we don't want to select when clicking. RootDocument & isTemplateForField implies we're clicking on part of a template instance and we want to select the whole template, not the part
+ if (this.layoutDoc.onDragStart && !(e.ctrlKey || e.button > 0)) stopPropagate = false;
+ preventDefault = false;
+ }
+ this._singleClickFunc = undoable(clickFunc ?? sendToBack ?? selectFunc, 'click: ' + this.Document.title);
+ const waitForDblClick = this._props.waitForDoubleClickToClick?.() ?? this.Document.waitForDoubleClickToClick;
+ if ((clickFunc && waitForDblClick !== 'never') || waitForDblClick === 'always') {
this._doubleClickTimeout && clearTimeout(this._doubleClickTimeout);
this._doubleClickTimeout = setTimeout(this._singleClickFunc, 300);
// eslint-disable-next-line no-use-before-define
- } else if (!DocumentView.LongPress) {
+ } else if (!SnappingManager.LongPress) {
this._singleClickFunc();
this._singleClickFunc = undefined;
}
@@ -365,9 +359,9 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
});
onPointerDown = (e: React.PointerEvent): void => {
- if (this._props.isGroupActive?.() === 'child' && !this._props.isDocumentActive?.()) return;
+ if (this._props.isGroupActive?.() === GroupActive.child && !this._props.isDocumentActive?.()) return;
// eslint-disable-next-line no-use-before-define
- this._longPressSelector = setTimeout(() => DocumentView.LongPress && this._props.select(false), 1000);
+ this._longPressSelector = setTimeout(() => SnappingManager.LongPress && this._props.select(false), 1000);
if (!DocumentView.DownDocView) DocumentView.DownDocView = this._docView;
this._downX = e.clientX;
@@ -418,7 +412,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
if (!this.isContentActive()) this._lastTap = Date.now(); // don't want to process the start of a double tap if the doucment is selected
}
// eslint-disable-next-line no-use-before-define
- if (DocumentView.LongPress) e.preventDefault();
+ if (SnappingManager.LongPress) e.preventDefault();
};
toggleFollowLink = undoable((): void => {
@@ -975,8 +969,8 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
* @returns a function that will wrap a JSX animation element wrapping any JSX element
*/
public static AnimationEffect(renderDoc: JSX.Element, presEffectDoc: Opt<Doc>, root: Doc) {
- let dir = (presEffectDoc?.presentation_effectDirection ?? presEffectDoc?.followLinkAnimDirection) as PresEffectDirection;
- const transitionTime = presEffectDoc?.presentation_transition ? NumCast(presEffectDoc?.presentation_transition) : 500;
+ const dir = ((presEffectDoc?.presentation_effectDirection ?? presEffectDoc?.followLinkAnimDirection) || PresEffectDirection.Center) as PresEffectDirection;
+ const duration = Cast(presEffectDoc?.presentation_transition, 'number', Cast(presEffectDoc?.followLinkTransitionTime, 'number', null));
const effectProps = {
left: dir === PresEffectDirection.Left,
right: dir === PresEffectDirection.Right,
@@ -984,26 +978,14 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
bottom: dir === PresEffectDirection.Bottom,
opposite: true,
delay: 0,
- duration: Cast(presEffectDoc?.presentation_transition, 'number', Cast(presEffectDoc?.followLinkTransitionTime, 'number', null)),
+ duration,
};
const timing = StrCast(presEffectDoc?.presentation_effectTiming);
- let timingConfig: SpringSettings | undefined;
- if (timing) {
- timingConfig = JSON.parse(timing);
- }
-
- if (!timingConfig) {
- timingConfig = {
- type: SpringType.GENTLE,
- ...springMappings.gentle,
- };
- }
-
- if (!dir) {
- dir = PresEffectDirection.Center;
- }
-
+ const timingConfig = (timing ? JSON.parse(timing) : undefined) ?? {
+ type: SpringType.GENTLE,
+ ...springMappings.gentle,
+ };
switch (StrCast(presEffectDoc?.presentation_effect, StrCast(presEffectDoc?.followLinkAnimEffect))) {
case PresEffect.Expand: return <SpringAnimation doc={root} startOpacity={0} dir={dir} presEffect={PresEffect.Expand} springSettings={timingConfig}>{renderDoc}</SpringAnimation>
case PresEffect.Flip: return <SpringAnimation doc={root} startOpacity={0} dir={dir} presEffect={PresEffect.Flip} springSettings={timingConfig}>{renderDoc}</SpringAnimation>
@@ -1085,15 +1067,16 @@ export class DocumentView extends DocComponent<DocumentViewProps>() {
finished?: (changed: boolean) => void // func called after focusing on target with flag indicating whether anything needed to be done.
) => Promise<void>;
public static linkCommonAncestor: (link: Doc) => DocumentView | undefined;
- // pin func
+ /**
+ * Pins a Doc to the current presentation trail. (see TabDocView for implementation)
+ */
public static PinDoc: (docIn: Doc | Doc[], pinProps: PinProps) => void;
- // gesture
- public static DownDocView: DocumentView | undefined; // the first DocView that receives a pointerdown event. used by GestureOverlay to determine the doc a gesture should apply to.
- // media playing
- @observable public static CurrentlyPlaying: DocumentView[] = [];
+ /**
+ * The DocumentView below the cursor at the start of a gesture (that receives the pointerDown event). Used by GestureOverlay to determine the doc a gesture should apply to.
+ */
+ public static DownDocView: DocumentView | undefined;
public get displayName() { return 'DocumentView(' + (this.Document?.title??"") + ')'; } // prettier-ignore
- public ContentRef = React.createRef<HTMLDivElement>();
private _htmlOverlayEffect: Opt<Doc>;
private _disposers: { [name: string]: IReactionDisposer } = {};
private _viewTimer: NodeJS.Timeout | undefined;
@@ -1124,7 +1107,7 @@ export class DocumentView extends DocComponent<DocumentViewProps>() {
@observable private _htmlOverlayText: Opt<string> = undefined;
@observable private _isHovering = false;
@observable private _selected = false;
- @observable public static LongPress = false;
+ @observable public static CurrentlyPlaying: DocumentView[] = []; // audio or video media views that are currently playing
@computed private get shouldNotScale() {
return (this.layout_fitWidth && !this.nativeWidth) || this.ComponentView?.isUnstyledView?.();
@@ -1471,7 +1454,6 @@ export class DocumentView extends DocComponent<DocumentViewProps>() {
{!this.Document || !this._props.PanelWidth() ? null : (
<div
className="contentFittingDocumentView-previewDoc"
- ref={this.ContentRef}
style={{
transform: `translate(${this.centeringX}px, ${this.centeringY}px)`,
width: xshift ?? `${this._props.PanelWidth() - this.Xshift * 2}px`,
@@ -1568,6 +1550,56 @@ export class DocumentView extends DocComponent<DocumentViewProps>() {
}
}
+export function ActiveFillColor(): string {
+ const dv = DocumentView.Selected().lastElement() ?.Document._layout_isSvg ? DocumentView.Selected().lastElement() : undefined;
+ return StrCast(dv?.Document.fillColor, StrCast(ActiveInkPen()?.activeFillColor, ""));
+} // prettier-ignore
+export function ActiveInkPen(): Doc { return Doc.UserDoc(); } // prettier-ignore
+export function ActiveInkColor(): string { return StrCast(ActiveInkPen()?.activeInkColor, 'black'); } // prettier-ignore
+export function ActiveIsInkMask(): boolean { return BoolCast(ActiveInkPen()?.activeIsInkMask, false); } // prettier-ignore
+export function ActiveInkHideTextLabels(): boolean { return BoolCast(ActiveInkPen().activeInkHideTextLabels, false); } // prettier-ignore
+export function ActiveArrowStart(): string { return StrCast(ActiveInkPen()?.activeArrowStart, ''); } // prettier-ignore
+export function ActiveArrowEnd(): string { return StrCast(ActiveInkPen()?.activeArrowEnd, ''); } // prettier-ignore
+export function ActiveArrowScale(): number { return NumCast(ActiveInkPen()?.activeArrowScale, 1); } // prettier-ignore
+export function ActiveDash(): string { return StrCast(ActiveInkPen()?.activeDash, '0'); } // prettier-ignore
+export function ActiveInkWidth(): number { return Number(ActiveInkPen()?.activeInkWidth); } // prettier-ignore
+export function ActiveInkBezierApprox(): string { return StrCast(ActiveInkPen()?.activeInkBezier); } // prettier-ignore
+export function ActiveEraserWidth(): number { return Number(ActiveInkPen()?.eraserWidth); } // prettier-ignore
+
+export function SetActiveInkWidth(width: string): void {
+ !isNaN(parseInt(width)) && ActiveInkPen() && (ActiveInkPen().activeInkWidth = width);
+}
+export function SetActiveBezierApprox(bezier: string): void {
+ ActiveInkPen() && (ActiveInkPen().activeInkBezier = isNaN(parseInt(bezier)) ? '' : bezier);
+}
+export function SetActiveInkColor(value: string) {
+ ActiveInkPen() && (ActiveInkPen().activeInkColor = value);
+}
+export function SetActiveIsInkMask(value: boolean) {
+ ActiveInkPen() && (ActiveInkPen().activeIsInkMask = value);
+}
+export function SetActiveInkHideTextLabels(value: boolean) {
+ ActiveInkPen() && (ActiveInkPen().activeInkHideTextLabels = value);
+}
+export function SetActiveFillColor(value: string) {
+ ActiveInkPen() && (ActiveInkPen().activeFillColor = value);
+}
+export function SetActiveArrowStart(value: string) {
+ ActiveInkPen() && (ActiveInkPen().activeArrowStart = value);
+}
+export function SetActiveArrowEnd(value: string) {
+ ActiveInkPen() && (ActiveInkPen().activeArrowEnd = value);
+}
+export function SetActiveArrowScale(value: number) {
+ ActiveInkPen() && (ActiveInkPen().activeArrowScale = value);
+}
+export function SetActiveDash(dash: string): void {
+ !isNaN(parseInt(dash)) && ActiveInkPen() && (ActiveInkPen().activeDash = dash);
+}
+export function SetEraserWidth(width: number): void {
+ ActiveInkPen() && (ActiveInkPen().eraserWidth = width);
+}
+
// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function DocFocusOrOpen(docIn: Doc, optionsIn?: FocusViewOptions, containingDoc?: Doc) {
return DocumentView.FocusOrOpen(docIn, optionsIn, containingDoc);
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index 1c90fae9e..d940a96b9 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -454,6 +454,11 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
};
focus = (anchor: Doc, options: FocusViewOptions) => (anchor.type === DocumentType.CONFIG ? undefined : this._ffref.current?.focus(anchor, options));
+ renderedPixelDimensions = async () => {
+ const { nativeWidth: width, nativeHeight: height } = await Networking.PostToServer('/inspectImage', { source: this.paths[0] });
+ return { width, height };
+ };
+
savedAnnotations = () => this._savedAnnotations;
render() {
TraceMobx();
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index 8835ea5e7..da947face 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -45,6 +45,7 @@ import { LinkInfo } from './LinkDocPreview';
import { OpenWhere } from './OpenWhere';
import './WebBox.scss';
+// eslint-disable-next-line @typescript-eslint/no-var-requires
const { CreateImage } = require('./WebBoxRenderer');
@observer
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index 9f2a9b8e1..5b435e44a 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -87,9 +87,9 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
public static LiveTextUndo: UndoManager.Batch | undefined; // undo batch when typing a new text note into a collection
static _globalHighlightsCache: string = '';
static _globalHighlights = new ObservableSet<string>(['Audio Tags', 'Text from Others', 'Todo Items', 'Important Items', 'Disagree Items', 'Ignore Items']);
- static _highlightStyleSheet: any = addStyleSheet();
- static _bulletStyleSheet: any = addStyleSheet();
- static _userStyleSheet: any = addStyleSheet();
+ static _highlightStyleSheet = addStyleSheet();
+ static _bulletStyleSheet = addStyleSheet();
+ static _userStyleSheet = addStyleSheet();
static _hadSelection: boolean = false;
private _selectionHTML: string | undefined;
private _sidebarRef = React.createRef<SidebarAnnos>();
@@ -384,7 +384,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
}
}
} else {
- const jsonstring = Cast(dataDoc[this.fieldKey], RichTextField)?.Data!;
+ const jsonstring = Cast(dataDoc[this.fieldKey], RichTextField)?.Data;
if (jsonstring) {
const json = JSON.parse(jsonstring);
json.selection = state.toJSON().selection;
@@ -1925,11 +1925,11 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
setHeight={this.setSidebarHeight}
/>
) : (
- <div onPointerDown={e => setupMoveUpEvents(this, e, returnFalse, emptyFunction, () => DocumentView.SelectView(this.DocumentView?.()!, false), true)}>
+ <div onPointerDown={e => setupMoveUpEvents(this, e, returnFalse, emptyFunction, () => DocumentView.SelectView(this.DocumentView?.(), false), true)}>
<ComponentTag
// eslint-disable-next-line react/jsx-props-no-spreading
{...this._props}
- ref={this._sidebarTagRef as any}
+ ref={this._sidebarTagRef}
setContentView={emptyFunction}
NativeWidth={returnZero}
NativeHeight={returnZero}
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index 72448e851..709e9a23c 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -56,7 +56,7 @@ interface IViewerProps extends FieldViewProps {
*/
@observer
export class PDFViewer extends ObservableReactComponent<IViewerProps> {
- static _annotationStyle: any = addStyleSheet();
+ static _annotationStyle = addStyleSheet();
constructor(props: IViewerProps) {
super(props);
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index 4abb23404..ac2efbe5c 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -174,53 +174,6 @@ export function updateCachedAcls(doc: Doc) {
return undefined;
}
-export function ActiveInkPen(): Doc { return Doc.UserDoc(); } // prettier-ignore
-export function ActiveInkColor(): string { return StrCast(ActiveInkPen()?.activeInkColor, 'black'); } // prettier-ignore
-export function ActiveFillColor(): string { return StrCast(ActiveInkPen()?.activeFillColor, ''); } // prettier-ignore
-export function ActiveIsInkMask(): boolean { return BoolCast(ActiveInkPen()?.activeIsInkMask, false); } // prettier-ignore
-export function ActiveInkHideTextLabels(): boolean { return BoolCast(ActiveInkPen().activeInkHideTextLabels, false); } // prettier-ignore
-export function ActiveArrowStart(): string { return StrCast(ActiveInkPen()?.activeArrowStart, ''); } // prettier-ignore
-export function ActiveArrowEnd(): string { return StrCast(ActiveInkPen()?.activeArrowEnd, ''); } // prettier-ignore
-export function ActiveArrowScale(): number { return NumCast(ActiveInkPen()?.activeArrowScale, 1); } // prettier-ignore
-export function ActiveDash(): string { return StrCast(ActiveInkPen()?.activeDash, '0'); } // prettier-ignore
-export function ActiveInkWidth(): number { return Number(ActiveInkPen()?.activeInkWidth); } // prettier-ignore
-export function ActiveInkBezierApprox(): string { return StrCast(ActiveInkPen()?.activeInkBezier); } // prettier-ignore
-export function ActiveEraserWidth(): number { return Number(ActiveInkPen()?.eraserWidth); } // prettier-ignore
-
-export function SetActiveInkWidth(width: string): void {
- !isNaN(parseInt(width)) && ActiveInkPen() && (ActiveInkPen().activeInkWidth = width);
-}
-export function SetActiveBezierApprox(bezier: string): void {
- ActiveInkPen() && (ActiveInkPen().activeInkBezier = isNaN(parseInt(bezier)) ? '' : bezier);
-}
-export function SetActiveInkColor(value: string) {
- ActiveInkPen() && (ActiveInkPen().activeInkColor = value);
-}
-export function SetActiveIsInkMask(value: boolean) {
- ActiveInkPen() && (ActiveInkPen().activeIsInkMask = value);
-}
-export function SetActiveInkHideTextLabels(value: boolean) {
- ActiveInkPen() && (ActiveInkPen().activeInkHideTextLabels = value);
-}
-export function SetActiveFillColor(value: string) {
- ActiveInkPen() && (ActiveInkPen().activeFillColor = value);
-}
-export function SetActiveArrowStart(value: string) {
- ActiveInkPen() && (ActiveInkPen().activeArrowStart = value);
-}
-export function SetActiveArrowEnd(value: string) {
- ActiveInkPen() && (ActiveInkPen().activeArrowEnd = value);
-}
-export function SetActiveArrowScale(value: number) {
- ActiveInkPen() && (ActiveInkPen().activeArrowScale = value);
-}
-export function SetActiveDash(dash: string): void {
- !isNaN(parseInt(dash)) && ActiveInkPen() && (ActiveInkPen().activeDash = dash);
-}
-export function SetEraserWidth(width: number): void {
- ActiveInkPen() && (ActiveInkPen().eraserWidth = width);
-}
-
@scriptingGlobal
@Deserializable('Doc', updateCachedAcls, ['id'])
export class Doc extends RefField {