diff options
32 files changed, 236 insertions, 229 deletions
diff --git a/package-lock.json b/package-lock.json index 80aef5232..c53a3219e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -82,6 +82,7 @@ "core-js": "^3.33.3", "cors": "^2.8.5", "css-loader": "^7.0.0", + "csstype": "^3.1.3", "csv-parser": "^3.0.0", "csv-stringify": "^6.4.4", "D": "^1.0.0", diff --git a/package.json b/package.json index d826c855e..0e7955d54 100644 --- a/package.json +++ b/package.json @@ -167,6 +167,7 @@ "core-js": "^3.33.3", "cors": "^2.8.5", "css-loader": "^7.0.0", + "csstype": "^3.1.3", "csv-parser": "^3.0.0", "csv-stringify": "^6.4.4", "D": "^1.0.0", diff --git a/src/client/util/SnappingManager.ts b/src/client/util/SnappingManager.ts index 3da85191f..5cd6ecfe1 100644 --- a/src/client/util/SnappingManager.ts +++ b/src/client/util/SnappingManager.ts @@ -18,6 +18,7 @@ export class SnappingManager { @observable _horizSnapLines: number[] = []; @observable _vertSnapLines: number[] = []; @observable _exploreMode = false; + @observable _userPanned = false; private constructor() { SnappingManager._manager = this; @@ -43,6 +44,7 @@ export class SnappingManager { public static get IsResizing() { return this.Instance._isResizing; } // prettier-ignore public static get CanEmbed() { return this.Instance._canEmbed; } // prettier-ignore public static get ExploreMode() { return this.Instance._exploreMode; } // prettier-ignore + public static get UserPanned() { return this.Instance._userPanned; } // 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 @@ -52,6 +54,7 @@ export class SnappingManager { public static SetIsResizing = (docid?:string) => runInAction(() => {this.Instance._isResizing = docid}); // prettier-ignore public static SetCanEmbed = (embed:boolean) => runInAction(() => {this.Instance._canEmbed = embed}); // prettier-ignore public static SetExploreMode = (state:boolean) => runInAction(() => {this.Instance._exploreMode = state}); // prettier-ignore + public static TriggerUserPanned = () => runInAction(() => {this.Instance._userPanned = !this.Instance._userPanned}); // prettier-ignore public static userColor: string | undefined; public static userVariantColor: string | undefined; diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index bbd902a96..391c2f694 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -11,43 +11,11 @@ import { GetEffectiveAcl, inheritParentAcls } from '../../fields/util'; import { DocumentType } from '../documents/DocumentTypes'; import { DragManager } from '../util/DragManager'; import { ObservableReactComponent } from './ObservableReactComponent'; +import { PinProps } from './PinFuncs'; import { DocumentView, OpenWhere } from './nodes/DocumentView'; import { FieldViewProps, FocusViewOptions } from './nodes/FieldView'; // import { DocUtils } from '../documents/Documents'; -export interface pinDataTypes { - scrollable?: boolean; - dataviz?: number[]; - pannable?: boolean; - type_collection?: boolean; - inkable?: boolean; - filters?: boolean; - pivot?: boolean; - temporal?: boolean; - clippable?: boolean; - datarange?: boolean; - dataview?: boolean; - poslayoutview?: boolean; - dataannos?: boolean; - map?: boolean; -} - -export interface MarqueeViewBounds { - left: number; - top: number; - width: number; - height: number; -} -export interface PinProps { - audioRange?: boolean; - activeFrame?: number; - currentFrame?: number; - hidePresBox?: boolean; - pinViewport?: MarqueeViewBounds; // pin a specific viewport on a freeform view (use MarqueeView.CurViewBounds to compute if no region has been selected) - pinDocLayout?: boolean; // pin layout info (width/height/x/y) - pinAudioPlay?: boolean; // pin audio annotation - pinData?: pinDataTypes; -} /** * Shared interface among all viewBox'es (ie, react classes that render the contents of a Doc) * Many of these methods only make sense for specific viewBox'es, but they should be written to diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 3083b9be0..1e6eb1aeb 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -6,10 +6,11 @@ import { observer } from 'mobx-react'; import * as React from 'react'; import { FaUndo } from 'react-icons/fa'; import { lightOrDark, returnFalse, setupMoveUpEvents } from '../../ClientUtils'; -import { Utils, numberValue, emptyFunction } from '../../Utils'; +import { Utils, emptyFunction, numberValue } from '../../Utils'; import { DateField } from '../../fields/DateField'; import { Doc, DocListCast, Field, FieldType, HierarchyMapping, ReverseHierarchyMap } from '../../fields/Doc'; import { AclAdmin, AclAugment, AclEdit, DocData } from '../../fields/DocSymbols'; +import { Id } from '../../fields/FieldSymbols'; import { InkField } from '../../fields/InkField'; import { ScriptField } from '../../fields/ScriptField'; import { BoolCast, Cast, DocCast, NumCast, StrCast } from '../../fields/Types'; @@ -31,11 +32,11 @@ import { ObservableReactComponent } from './ObservableReactComponent'; import { CollectionDockingView } from './collections/CollectionDockingView'; import { CollectionFreeFormView } from './collections/collectionFreeForm'; import { Colors } from './global/globalEnums'; +import { CollectionFreeFormDocumentView } from './nodes/CollectionFreeFormDocumentView'; import { DocumentView, OpenWhereMod } from './nodes/DocumentView'; import { ImageBox } from './nodes/ImageBox'; import { KeyValueBox } from './nodes/KeyValueBox'; import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox'; -import { Id } from '../../fields/FieldSymbols'; interface DocumentDecorationsProps { PanelWidth: number; @@ -447,7 +448,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora }; this._resizeUndo = UndoManager.StartBatch('drag resizing'); this._snapPt = { x: e.pageX, y: e.pageY }; - SelectionManager.Views.forEach(docView => docView.CollectionFreeFormView?.dragStarting(false, false)); + SelectionManager.Views.forEach(docView => CollectionFreeFormDocumentView.from(docView)?.CollectionFreeFormView?.dragStarting(false, false)); }; projectDragToAspect = (e: PointerEvent, docView: DocumentView, fixedAspect: number) => { @@ -700,7 +701,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora const bounds = this.ClippedBounds; const useLock = bounds.r - bounds.x > 135; - const useRotation = !hideResizers && seldocview.Document.type !== DocumentType.EQUATION && seldocview.CollectionFreeFormDocumentView; // when do we want an object to not rotate? + const useRotation = !hideResizers && seldocview.Document.type !== DocumentType.EQUATION && CollectionFreeFormDocumentView.from(seldocview); // when do we want an object to not rotate? const rotation = SelectionManager.Views.length === 1 ? seldocview.screenToContentsTransform().inverse().RotateDeg : 0; // Radius constants @@ -771,7 +772,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora ); const centery = hideTitle ? 0 : this._titleHeight; const transformOrigin = `${50}% calc(50% + ${centery / 2}px)`; - const freeformDoc = SelectionManager.Views.some(v => v.CollectionFreeFormDocumentView); + const freeformDoc = SelectionManager.Views.some(v => CollectionFreeFormDocumentView.from(v)); return ( <div className="documentDecorations" style={{ display: this._showNothing && !freeformDoc ? 'none' : undefined }}> <div diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx index 35067047b..cf609d8f9 100644 --- a/src/client/views/InkingStroke.tsx +++ b/src/client/views/InkingStroke.tsx @@ -34,7 +34,7 @@ import { InteractionUtils } from '../util/InteractionUtils'; import { SnappingManager } from '../util/SnappingManager'; import { UndoManager } from '../util/UndoManager'; import { ContextMenu } from './ContextMenu'; -import { PinProps, ViewBoxAnnotatableComponent, ViewBoxInterface } from './DocComponent'; +import { ViewBoxAnnotatableComponent, ViewBoxInterface } from './DocComponent'; import { Colors } from './global/globalEnums'; import { InkControlPtHandles, InkEndPtHandles } from './InkControlPtHandles'; import './InkStroke.scss'; @@ -42,7 +42,7 @@ import { InkStrokeProperties } from './InkStrokeProperties'; import { InkTangentHandles } from './InkTangentHandles'; import { FieldView, FieldViewProps } from './nodes/FieldView'; import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox'; -import { PresBox } from './nodes/trails'; +import { PinDocView, PinProps } from './PinFuncs'; import { StyleProp } from './StyleProvider'; const { INK_MASK_SIZE } = require('./global/globalCssVariables.module.scss'); // prettier-ignore @@ -92,7 +92,7 @@ export class InkingStroke extends ViewBoxAnnotatableComponent<FieldViewProps>() if (anchor) { anchor.backgroundColor = 'transparent'; addAsAnnotation && this.addDocument(anchor); - PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), inkable: true } }, this.Document); + PinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), inkable: true } }, this.Document); return anchor; } return this.Document; diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index be13b14f5..d3dd51ac6 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -76,6 +76,7 @@ import { PresBox } from './nodes/trails'; import { AnchorMenu } from './pdf/AnchorMenu'; import { GPTPopup } from './pdf/GPTPopup/GPTPopup'; import { TopBar } from './topbar/TopBar'; +import { CollectionFreeFormView } from './collections/collectionFreeForm'; const _global = (window /* browser */ || global) /* node */ as any; const { LEFT_MENU_WIDTH, TOPBAR_HEIGHT } = require('./global/globalCssVariables.module.scss'); // prettier-ignore @@ -964,7 +965,7 @@ export class MainView extends ObservableReactComponent<{}> { } @computed get snapLines() { const dragged = DragManager.docsBeingDragged.lastElement() ?? SelectionManager.Docs.lastElement(); - const dragPar = dragged ? DocumentManager.Instance.getDocumentView(dragged)?.CollectionFreeFormView : undefined; + const dragPar = dragged ? CollectionFreeFormView.from(DocumentManager.Instance.getDocumentView(dragged)) : undefined; return !dragPar?.layoutDoc.freeform_snapLines ? null : ( <div className="mainView-snapLines"> <svg style={{ width: '100%', height: '100%' }}> diff --git a/src/client/views/PinFuncs.ts b/src/client/views/PinFuncs.ts new file mode 100644 index 000000000..3d998ecaf --- /dev/null +++ b/src/client/views/PinFuncs.ts @@ -0,0 +1,139 @@ +import { Doc, DocListCast } from '../../fields/Doc'; +import { DocData } from '../../fields/DocSymbols'; +import { Copy, Id } from '../../fields/FieldSymbols'; +import { List } from '../../fields/List'; +import { ObjectField } from '../../fields/ObjectField'; +import { NumCast, StrCast } from '../../fields/Types'; +import { SerializationHelper } from '../util/SerializationHelper'; + +export interface MarqueeViewBounds { + left: number; + top: number; + width: number; + height: number; +} +export interface pinDataTypes { + scrollable?: boolean; + dataviz?: number[]; + pannable?: boolean; + type_collection?: boolean; + inkable?: boolean; + filters?: boolean; + pivot?: boolean; + temporal?: boolean; + clippable?: boolean; + datarange?: boolean; + dataview?: boolean; + poslayoutview?: boolean; + dataannos?: boolean; + map?: boolean; +} +export interface PinProps { + audioRange?: boolean; + activeFrame?: number; + currentFrame?: number; + hidePresBox?: boolean; + pinViewport?: MarqueeViewBounds; // pin a specific viewport on a freeform view (use MarqueeView.CurViewBounds to compute if no region has been selected) + pinDocLayout?: boolean; // pin layout info (width/height/x/y) + pinAudioPlay?: boolean; // pin audio annotation + pinData?: pinDataTypes; +} + +/// copies values from the targetDoc (which is the prototype of the pinDoc) to +/// reserved fields on the pinDoc so that those values can be restored to the +/// target doc when navigating to it. +export function PinDocView(pinDocIn: Doc, pinProps: PinProps, targetDoc: Doc) { + const pinDoc = pinDocIn; + pinDoc.presentation = true; + pinDoc.config = ''; + if (pinProps.pinDocLayout) { + pinDoc.config_pinLayout = true; + pinDoc.config_x = NumCast(targetDoc.x); + pinDoc.config_y = NumCast(targetDoc.y); + pinDoc.config_rotation = NumCast(targetDoc.rotation); + pinDoc.config_width = NumCast(targetDoc.width); + pinDoc.config_height = NumCast(targetDoc.height); + } + if (pinProps.pinAudioPlay) pinDoc.presPlayAudio = true; + if (pinProps.pinData) { + pinDoc.config_pinData = + pinProps.pinData.scrollable || + pinProps.pinData.temporal || + pinProps.pinData.pannable || + pinProps.pinData.type_collection || + pinProps.pinData.clippable || + pinProps.pinData.datarange || + pinProps.pinData.dataview || + pinProps.pinData.poslayoutview || + pinProps?.activeFrame !== undefined; + const fkey = Doc.LayoutFieldKey(targetDoc); + if (pinProps.pinData.dataview) { + pinDoc.config_usePath = targetDoc[fkey + '_usePath']; + pinDoc.config_data = targetDoc[fkey] instanceof ObjectField ? (targetDoc[fkey] as ObjectField)[Copy]() : targetDoc.data; + } + if (pinProps.pinData.dataannos) { + const fieldKey = Doc.LayoutFieldKey(targetDoc); + pinDoc.config_annotations = new List<Doc>(DocListCast(targetDoc[DocData][fieldKey + '_annotations']).filter(doc => !doc.layout_unrendered)); + } + if (pinProps.pinData.inkable) { + pinDoc.config_fillColor = targetDoc.fillColor; + pinDoc.config_color = targetDoc.color; + pinDoc.config_width = targetDoc._width; + pinDoc.config_height = targetDoc._height; + } + if (pinProps.pinData.scrollable) pinDoc.config_scrollTop = targetDoc._layout_scrollTop; + if (pinProps.pinData.clippable) { + const fieldKey = Doc.LayoutFieldKey(targetDoc); + pinDoc.config_clipWidth = targetDoc[fieldKey + '_clipWidth']; + } + if (pinProps.pinData.datarange) { + pinDoc.config_xRange = undefined; // targetDoc?.xrange; + pinDoc.config_yRange = undefined; // targetDoc?.yrange; + } + if (pinProps.pinData.map) { + // pinDoc.config_latitude = targetDoc?.latitude; + // pinDoc.config_longitude = targetDoc?.longitude; + pinDoc.config_map_zoom = targetDoc?.map_zoom; + pinDoc.config_map_type = targetDoc?.map_type; + // ... + } + if (pinProps.pinData.poslayoutview) + pinDoc.config_pinLayoutData = new List<string>( + DocListCast(targetDoc[fkey] as ObjectField).map(d => + JSON.stringify({ + id: d[Id], + x: NumCast(d.x), + y: NumCast(d.y), + w: NumCast(d._width), + h: NumCast(d._height), + fill: StrCast(d._fillColor), + back: StrCast(d._backgroundColor), + data: SerializationHelper.Serialize(d.data instanceof ObjectField ? d.data[Copy]() : ''), + text: SerializationHelper.Serialize(d.text instanceof ObjectField ? d.text[Copy]() : ''), + }) + ) + ); + if (pinProps.pinData.type_collection) pinDoc.config_viewType = targetDoc._type_collection; + if (pinProps.pinData.filters) pinDoc.config_docFilters = ObjectField.MakeCopy(targetDoc.childFilters as ObjectField); + if (pinProps.pinData.pivot) pinDoc.config_pivotField = targetDoc._pivotField; + if (pinProps.pinData.pannable) { + pinDoc.config_panX = NumCast(targetDoc._freeform_panX); + pinDoc.config_panY = NumCast(targetDoc._freeform_panY); + pinDoc.config_viewScale = NumCast(targetDoc._freeform_scale, 1); + } + if (pinProps.pinData.temporal) { + pinDoc.config_clipStart = targetDoc._layout_currentTimecode; + const duration = NumCast(pinDoc[`${Doc.LayoutFieldKey(pinDoc)}_duration`], NumCast(targetDoc.config_clipStart) + 0.1); + pinDoc.config_clipEnd = NumCast(pinDoc.config_clipStart) + NumCast(targetDoc.clipEnd, duration); + } + } + if (pinProps?.pinViewport) { + // If pinWithView option set then update scale and x / y props of slide + const bounds = pinProps.pinViewport; + pinDoc.config_pinView = true; + pinDoc.config_viewScale = NumCast(targetDoc._freeform_scale, 1); + pinDoc.config_panX = bounds.left + bounds.width / 2; + pinDoc.config_panY = bounds.top + bounds.height / 2; + pinDoc.config_viewBounds = new List<number>([bounds.left, bounds.top, bounds.left + bounds.width, bounds.top + bounds.height]); + } +} diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index c47fe915a..ad9960989 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -1,5 +1,6 @@ /* eslint-disable react/jsx-props-no-spreading */ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +// eslint-disable-next-line import/no-extraneous-dependencies import * as CSS from 'csstype'; import { action, computed, IReactionDisposer, makeObservable, observable, ObservableMap, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; diff --git a/src/client/views/collections/CollectionTimeView.tsx b/src/client/views/collections/CollectionTimeView.tsx index e1d2e3c40..b3760d4af 100644 --- a/src/client/views/collections/CollectionTimeView.tsx +++ b/src/client/views/collections/CollectionTimeView.tsx @@ -3,8 +3,8 @@ import { action, computed, makeObservable, observable, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; -import { emptyFunction } from '../../../Utils'; import { returnFalse, returnTrue, setupMoveUpEvents } from '../../../ClientUtils'; +import { emptyFunction } from '../../../Utils'; import { Doc, Opt, StrListCast } from '../../../fields/Doc'; import { List } from '../../../fields/List'; import { ObjectField } from '../../../fields/ObjectField'; @@ -17,8 +17,8 @@ import { ScriptingGlobals } from '../../util/ScriptingGlobals'; import { ContextMenu } from '../ContextMenu'; import { ContextMenuProps } from '../ContextMenuItem'; import { FieldsDropdown } from '../FieldsDropdown'; +import { PinDocView } from '../PinFuncs'; import { DocumentView } from '../nodes/DocumentView'; -import { PresBox } from '../nodes/trails'; import { CollectionSubView } from './CollectionSubView'; import './CollectionTimeView.scss'; import { ViewDefBounds, computePivotLayout, computeTimelineLayout } from './collectionFreeForm/CollectionFreeFormLayoutEngines'; @@ -55,7 +55,7 @@ export class CollectionTimeView extends CollectionSubView() { title: ComputedField.MakeFunction(`"${this.pivotField}"])`) as any, annotationOn: this.Document, }); - PresBox.pinDocView(anchor, { pinData: { type_collection: true, pivot: true, filters: true } }, this.Document); + PinDocView(anchor, { pinData: { type_collection: true, pivot: true, filters: true } }, this.Document); if (addAsAnnotation) { // when added as an annotation, links to anchors can be found as links to the document even if the anchors are not rendered diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx index e98e444ed..e7b8237a5 100644 --- a/src/client/views/collections/TabDocView.tsx +++ b/src/client/views/collections/TabDocView.tsx @@ -26,9 +26,9 @@ import { SnappingManager } from '../../util/SnappingManager'; import { Transform } from '../../util/Transform'; import { UndoManager, undoable } from '../../util/UndoManager'; import { DashboardView } from '../DashboardView'; -import { PinProps } from '../DocComponent'; import { LightboxView } from '../LightboxView'; import { ObservableReactComponent } from '../ObservableReactComponent'; +import { PinProps, PinDocView } from '../PinFuncs'; import { DefaultStyleProvider, StyleProp } from '../StyleProvider'; import { Colors } from '../global/globalEnums'; import { DocumentView, OpenWhere, OpenWhereMod, returnEmptyDocViewList } from '../nodes/DocumentView'; @@ -426,7 +426,7 @@ export class TabDocView extends ObservableReactComponent<TabDocViewProps> { pinDoc.treeView_HideHeaderIfTemplate = true; // this will force the document to render itself as the tree view header const duration = NumCast(doc[`${Doc.LayoutFieldKey(pinDoc)}_duration`], null); - if (pinProps.pinViewport) PresBox.pinDocView(pinDoc, pinProps, anchorDoc ?? doc); + if (pinProps.pinViewport) PinDocView(pinDoc, pinProps, anchorDoc ?? doc); if (!pinProps?.audioRange && duration !== undefined) { pinDoc.presentation_mediaStart = 'manual'; pinDoc.presentation_mediaStop = 'manual'; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 69cb52233..653a01a04 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -38,7 +38,6 @@ import { Transform } from '../../../util/Transform'; import { undoable, undoBatch, UndoManager } from '../../../util/UndoManager'; import { Timeline } from '../../animationtimeline/Timeline'; import { ContextMenu } from '../../ContextMenu'; -import { PinProps } from '../../DocComponent'; import { GestureOverlay } from '../../GestureOverlay'; import { ActiveInkWidth, InkingStroke, SetActiveInkColor, SetActiveInkWidth } from '../../InkingStroke'; import { LightboxView } from '../../LightboxView'; @@ -47,13 +46,13 @@ import { SchemaCSVPopUp } from '../../nodes/DataVizBox/SchemaCSVPopUp'; import { DocumentView, OpenWhere } from '../../nodes/DocumentView'; import { FieldViewProps, FocusViewOptions } from '../../nodes/FieldView'; import { FormattedTextBox } from '../../nodes/formattedText/FormattedTextBox'; -import { PresBox } from '../../nodes/trails/PresBox'; +import { PinDocView, PinProps } from '../../PinFuncs'; import { StyleProp } from '../../StyleProvider'; import { CollectionSubView } from '../CollectionSubView'; import { TreeViewType } from '../CollectionTreeView'; import { CollectionFreeFormBackgroundGrid } from './CollectionFreeFormBackgroundGrid'; -import { CollectionFreeFormInfoUI } from './CollectionFreeFormInfoUI'; import { CollectionFreeFormClusters } from './CollectionFreeFormClusters'; +import { CollectionFreeFormInfoUI } from './CollectionFreeFormInfoUI'; import { computePassLayout, computePivotLayout, computeStarburstLayout, computeTimelineLayout, PoolData, ViewDefBounds, ViewDefResult } from './CollectionFreeFormLayoutEngines'; import { CollectionFreeFormPannableContents } from './CollectionFreeFormPannableContents'; import { CollectionFreeFormRemoteCursors } from './CollectionFreeFormRemoteCursors'; @@ -85,6 +84,9 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection } // this makes mobx trace() statements more descriptive public unprocessedDocs: Doc[] = []; public static collectionsWithUnprocessedInk = new Set<CollectionFreeFormView>(); + public static from(dv?: DocumentView) { + return CollectionFreeFormDocumentView.from(dv)?.CollectionFreeFormView; + } _oldWheel: any; _clusters = new CollectionFreeFormClusters(this); @@ -592,7 +594,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection }; scrollPan = (e: WheelEvent | { deltaX: number; deltaY: number }): void => { - PresBox.Instance?.pauseAutoPres(); + SnappingManager.TriggerUserPanned(); this.setPan(NumCast(this.Document[this.panXFieldKey]) - e.deltaX, NumCast(this.Document[this.panYFieldKey]) - e.deltaY, 0, true); }; @@ -600,7 +602,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection pan = (e: PointerEvent): void => { const ctrlKey = e.ctrlKey && !e.shiftKey; const shiftKey = e.shiftKey && !e.ctrlKey; - PresBox.Instance?.pauseAutoPres(); + SnappingManager.TriggerUserPanned(); this.DocumentView?.().clearViewTransition(); const [dxi, dyi] = this.screenToFreeformContentsXf.transformDirection(e.clientX - this._lastX, e.clientY - this._lastY); const { x: dx, y: dy } = Utils.rotPt(dxi, dyi, this.ScreenToLocalBoxXf().Rotate); @@ -834,7 +836,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection @action onPointerWheel = (e: React.WheelEvent): void => { if (this.Document.isGroup || !this.isContentActive()) return; // group style collections neither pan nor zoom - PresBox.Instance?.pauseAutoPres(); + SnappingManager.TriggerUserPanned(); if (this.layoutDoc._Transform || this.Document.treeView_OutlineMode === TreeViewType.outline) return; e.stopPropagation(); const docHeight = NumCast(this.Document[Doc.LayoutFieldKey(this.Document) + '_nativeHeight'], this.nativeHeight); @@ -1289,7 +1291,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection presentation_transition: 500, annotationOn: this.Document, }); - PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), pannable: !this.Document.isGroup, type_collection: true, filters: true } }, this.Document); + PinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), pannable: !this.Document.isGroup, type_collection: true, filters: true } }, this.Document); if (addAsAnnotation) { if (Cast(this.dataDoc[this._props.fieldKey + '_annotations'], listSpec(Doc), null) !== undefined) { @@ -1767,11 +1769,11 @@ ScriptingGlobals.add(function pinWithView(pinContent: boolean) { }); // eslint-disable-next-line prefer-arrow-callback ScriptingGlobals.add(function bringToFront() { - SelectionManager.Views.forEach(view => view.CollectionFreeFormView?.bringToFront(view.Document)); + SelectionManager.Views.forEach(view => CollectionFreeFormView.from(view)?.bringToFront(view.Document)); }); // eslint-disable-next-line prefer-arrow-callback ScriptingGlobals.add(function sendToBack() { - SelectionManager.Views.forEach(view => view.CollectionFreeFormView?.bringToFront(view.Document, true)); + SelectionManager.Views.forEach(view => CollectionFreeFormView.from(view)?.bringToFront(view.Document, true)); }); // eslint-disable-next-line prefer-arrow-callback ScriptingGlobals.add(function datavizFromSchema() { diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx index 9251dca6d..1f618135f 100644 --- a/src/client/views/nodes/AudioBox.tsx +++ b/src/client/views/nodes/AudioBox.tsx @@ -21,11 +21,11 @@ import { undoBatch } from '../../util/UndoManager'; import { CollectionStackedTimeline, TrimScope } from '../collections/CollectionStackedTimeline'; import { ContextMenu } from '../ContextMenu'; import { ContextMenuProps } from '../ContextMenuItem'; -import { PinProps, ViewBoxAnnotatableComponent } from '../DocComponent'; +import { ViewBoxAnnotatableComponent } from '../DocComponent'; +import { PinDocView, PinProps } from '../PinFuncs'; import './AudioBox.scss'; import { OpenWhere } from './DocumentView'; import { FieldView, FieldViewProps } from './FieldView'; -import { PresBox } from './trails'; /** * AudioBox @@ -159,7 +159,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { ) || this.Document : Docs.Create.ConfigDocument({ title: '#' + timecode, _timecodeToShow: timecode, annotationOn: this.Document }); - PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), temporal: true } }, this.Document); + PinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), temporal: true } }, this.Document); return anchor; }; diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 7b1847ae4..9c4d748bd 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -38,6 +38,7 @@ interface freeFormProps { highlight?: boolean; transition?: string; } + export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps { RenderCutoffProvider: (doc: Doc) => boolean; CollectionFreeFormView: CollectionFreeFormView; @@ -63,6 +64,9 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF ]; // fields that are configured to be animatable using animation frames public static animStringFields = ['backgroundColor', 'color', 'fillColor']; // fields that are configured to be animatable using animation frames public static animDataFields = (doc: Doc) => (Doc.LayoutFieldKey(doc) ? [Doc.LayoutFieldKey(doc)] : []); // fields that are configured to be animatable using animation frames + public static from(dv?: DocumentView) { + return dv?._props.parent instanceof CollectionFreeFormDocumentView ? dv._props.parent : undefined; + } constructor(props: CollectionFreeFormDocumentViewProps & freeFormProps) { super(props); @@ -273,6 +277,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF <div style={{ position: 'absolute', width: this.PanelWidth(), height: this.PanelHeight(), background: 'lightGreen' }} /> ) : ( <DocumentView + parent={this} // eslint-disable-next-line react/jsx-props-no-spreading {...OmitKeys(this._props,this.WrapperKeys.map(val => val.lower)).omit} // prettier-ignore DataTransition={this.DataTransition} diff --git a/src/client/views/nodes/ComparisonBox.tsx b/src/client/views/nodes/ComparisonBox.tsx index e6fd447ac..bc151f6a5 100644 --- a/src/client/views/nodes/ComparisonBox.tsx +++ b/src/client/views/nodes/ComparisonBox.tsx @@ -11,14 +11,14 @@ import { DocUtils, Docs } from '../../documents/Documents'; import { DragManager } from '../../util/DragManager'; import { dropActionType } from '../../util/DropActionTypes'; import { undoBatch } from '../../util/UndoManager'; -import { PinProps, ViewBoxAnnotatableComponent, ViewBoxInterface } from '../DocComponent'; +import { ViewBoxAnnotatableComponent, ViewBoxInterface } from '../DocComponent'; +import { PinProps, PinDocView } from '../PinFuncs'; import { StyleProp } from '../StyleProvider'; import './ComparisonBox.scss'; import { DocumentView } from './DocumentView'; import { FieldView, FieldViewProps } from './FieldView'; import { KeyValueBox } from './KeyValueBox'; import { FormattedTextBox } from './formattedText/FormattedTextBox'; -import { PresBox } from './trails'; @observer export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implements ViewBoxInterface { @@ -113,7 +113,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>() if (anchor) { if (!addAsAnnotation) anchor.backgroundColor = 'transparent'; /* addAsAnnotation && */ this.addDocument(anchor); - PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), clippable: true } }, this.Document); + PinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), clippable: true } }, this.Document); return anchor; } return this.Document; diff --git a/src/client/views/nodes/DataVizBox/components/Histogram.tsx b/src/client/views/nodes/DataVizBox/components/Histogram.tsx index f0ffdbdcf..79b3e9541 100644 --- a/src/client/views/nodes/DataVizBox/components/Histogram.tsx +++ b/src/client/views/nodes/DataVizBox/components/Histogram.tsx @@ -11,9 +11,8 @@ import { listSpec } from '../../../../../fields/Schema'; import { Cast, DocCast, StrCast } from '../../../../../fields/Types'; import { Docs } from '../../../../documents/Documents'; import { undoable } from '../../../../util/UndoManager'; -import { PinProps } from '../../../DocComponent'; import { ObservableReactComponent } from '../../../ObservableReactComponent'; -import { PresBox } from '../../trails'; +import { PinProps, PinDocView } from '../../../PinFuncs'; import { scaleCreatorNumerical, yAxisCreator } from '../utils/D3Utils'; import './Chart.scss'; @@ -117,7 +116,7 @@ export class Histogram extends ObservableReactComponent<HistogramProps> { const anchor = Docs.Create.ConfigDocument({ title: 'histogram doc selection' + this._currSelected, }); - PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: pinProps?.pinData }, this._props.Document); + PinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: pinProps?.pinData }, this._props.Document); return anchor; }; diff --git a/src/client/views/nodes/DataVizBox/components/LineChart.tsx b/src/client/views/nodes/DataVizBox/components/LineChart.tsx index 8105adf1e..1c3134185 100644 --- a/src/client/views/nodes/DataVizBox/components/LineChart.tsx +++ b/src/client/views/nodes/DataVizBox/components/LineChart.tsx @@ -10,12 +10,12 @@ import { Cast, DocCast, StrCast } from '../../../../../fields/Types'; import { Docs } from '../../../../documents/Documents'; import { DocumentManager } from '../../../../util/DocumentManager'; import { undoable } from '../../../../util/UndoManager'; +import {} from '../../../DocComponent'; import { ObservableReactComponent } from '../../../ObservableReactComponent'; -import { PresBox } from '../../trails'; +import { PinProps, PinDocView } from '../../../PinFuncs'; import { DataVizBox } from '../DataVizBox'; import { createLineGenerator, drawLine, minMaxRange, scaleCreatorNumerical, xAxisCreator, xGrid, yAxisCreator, yGrid } from '../utils/D3Utils'; import './Chart.scss'; -import { PinProps } from '../../../DocComponent'; export interface DataPoint { x: number; @@ -177,7 +177,7 @@ export class LineChart extends ObservableReactComponent<LineChartProps> { // title: 'line doc selection' + (this._currSelected?.x ?? ''), }); - PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: pinProps?.pinData }, this._props.Document); + PinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: pinProps?.pinData }, this._props.Document); anchor.config_dataVizSelection = this._currSelected ? new List<number>([this._currSelected.x, this._currSelected.y]) : undefined; return anchor; }; diff --git a/src/client/views/nodes/DataVizBox/components/PieChart.tsx b/src/client/views/nodes/DataVizBox/components/PieChart.tsx index f57070f92..ffb2f528a 100644 --- a/src/client/views/nodes/DataVizBox/components/PieChart.tsx +++ b/src/client/views/nodes/DataVizBox/components/PieChart.tsx @@ -12,9 +12,8 @@ import { Cast, DocCast, StrCast } from '../../../../../fields/Types'; import { Docs } from '../../../../documents/Documents'; import { undoable } from '../../../../util/UndoManager'; import { ObservableReactComponent } from '../../../ObservableReactComponent'; -import { PresBox } from '../../trails'; +import { PinProps, PinDocView } from '../../../PinFuncs'; import './Chart.scss'; -import { PinProps } from '../../../DocComponent'; export interface PieChartProps { Document: Doc; @@ -109,7 +108,7 @@ export class PieChart extends ObservableReactComponent<PieChartProps> { // title: 'piechart doc selection' + this._currSelected, }); - PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: pinProps?.pinData }, this._props.Document); + PinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: pinProps?.pinData }, this._props.Document); return anchor; }; diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 626e3d899..a603de10b 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -22,7 +22,6 @@ import { AudioField } from '../../../fields/URLField'; import { GetEffectiveAcl, TraceMobx } from '../../../fields/util'; import { DocServer } from '../../DocServer'; import { Networking } from '../../Network'; -import { GooglePhotos } from '../../apis/google_docs/GooglePhotosClientUtils'; import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes'; import { DocUtils, Docs } from '../../documents/Documents'; import { DictationManager } from '../../util/DictationManager'; @@ -46,7 +45,6 @@ import { FieldsDropdown } from '../FieldsDropdown'; import { GestureOverlay } from '../GestureOverlay'; import { LightboxView } from '../LightboxView'; import { AudioAnnoState, StyleProp } from '../StyleProvider'; -import { CollectionFreeFormDocumentView } from './CollectionFreeFormDocumentView'; import { DocumentContentsView, ObserverJsxParser } from './DocumentContentsView'; import { DocumentLinksButton } from './DocumentLinksButton'; import './DocumentView.scss'; @@ -108,6 +106,8 @@ export interface DocumentViewProps extends FieldViewSharedProps { dragConfig?: (data: DragManager.DocumentDragData) => void; dragStarting?: () => void; dragEnding?: () => void; + + parent?: any; } @observer export class DocumentViewInternal extends DocComponent<FieldViewProps & DocumentViewProps>() { @@ -314,7 +314,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document const browseTransitionTime = 500; SelectionManager.DeselectAll(); DocumentManager.Instance.showDocument(this.Document, { zoomScale: 0.8, willZoomCentered: true }, (focused: boolean) => { - const options:FocusViewOptions = { pointFocus: {X: e.clientX, Y :e.clientY}, zoomTime: browseTransitionTime}; + const options: FocusViewOptions = { pointFocus: { X: e.clientX, Y: e.clientY }, zoomTime: browseTransitionTime }; if (!focused && this._docView) { this._docView .docViewPath() @@ -645,12 +645,6 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document if (!Doc.noviceMode) { moreItems.push({ description: 'Make View of Metadata Field', event: () => Doc.MakeMetadataFieldTemplate(this.Document, this._props.TemplateDataDocument), icon: 'concierge-bell' }); moreItems.push({ description: `${this.Document._chromeHidden ? 'Show' : 'Hide'} Chrome`, event: () => { this.Document._chromeHidden = !this.Document._chromeHidden; }, icon: 'project-diagram' }); // prettier-ignore - - if (Cast(Doc.GetProto(this.Document).data, listSpec(Doc))) { - moreItems.push({ description: 'Export to Google Photos Album', event: () => GooglePhotos.Export.CollectionToAlbum({ collection: this.Document }).then(console.log), icon: 'caret-square-right' }); - moreItems.push({ description: 'Tag Child Images via Google Photos', event: () => GooglePhotos.Query.TagChildImages(this.Document), icon: 'caret-square-right' }); - moreItems.push({ description: 'Write Back Link to Album', event: () => GooglePhotos.Transactions.AddTextEnrichment(this.Document), icon: 'caret-square-right' }); - } moreItems.push({ description: 'Copy ID', event: () => ClientUtils.CopyText(Doc.globalServerPath(this.Document)), icon: 'fingerprint' }); } } @@ -1079,7 +1073,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document } @observer -export class DocumentView extends DocComponent<DocumentViewProps & { CollectionFreeFormDocumentView?: () => CollectionFreeFormDocumentView }>() { +export class DocumentView extends DocComponent<DocumentViewProps>() { public static ROOT_DIV = 'documentView-effectsWrapper'; public get displayName() { return 'DocumentView(' + (this.Document?.title??"") + ')'; } // prettier-ignore public ContentRef = React.createRef<HTMLDivElement>(); @@ -1100,7 +1094,7 @@ export class DocumentView extends DocComponent<DocumentViewProps & { CollectionF public ViewGuid = DocumentView.UniquifyId(LightboxView.Contains(this), Utils.GenerateGuid()); // a unique id associated with the main <div>. used by LinkBox's Xanchor to find the arrowhead locations. public DocUniqueId = DocumentView.UniquifyId(LightboxView.Contains(this), this.Document[Id]); - constructor(props: DocumentViewProps & { CollectionFreeFormDocumentView?: () => CollectionFreeFormDocumentView }) { + constructor(props: DocumentViewProps) { super(props); makeObservable(this); } @@ -1227,8 +1221,6 @@ export class DocumentView extends DocComponent<DocumentViewProps & { CollectionF * path of DocumentViews hat contains this DocumentView (does not includes this DocumentView thouhg) */ public get containerViewPath() { return this._props.containerViewPath; } // prettier-ignore - public get CollectionFreeFormView() { return this.CollectionFreeFormDocumentView?.CollectionFreeFormView; } // prettier-ignore - public get CollectionFreeFormDocumentView() { return this._props.CollectionFreeFormDocumentView?.(); } // prettier-ignore public get LocalRotation() { return this._props.LocalRotation?.(); } // prettier-ignore public clearViewTransition = () => { diff --git a/src/client/views/nodes/FunctionPlotBox.tsx b/src/client/views/nodes/FunctionPlotBox.tsx index 180c651fb..31faa7ac3 100644 --- a/src/client/views/nodes/FunctionPlotBox.tsx +++ b/src/client/views/nodes/FunctionPlotBox.tsx @@ -11,9 +11,9 @@ import { DocUtils, Docs } from '../../documents/Documents'; import { DragManager } from '../../util/DragManager'; import { LinkManager } from '../../util/LinkManager'; import { undoBatch } from '../../util/UndoManager'; -import { PinProps, ViewBoxAnnotatableComponent } from '../DocComponent'; +import { ViewBoxAnnotatableComponent } from '../DocComponent'; +import { PinProps, PinDocView } from '../PinFuncs'; import { FieldView, FieldViewProps } from './FieldView'; -import { PresBox } from './trails'; @observer export class FunctionPlotBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { @@ -40,7 +40,7 @@ export class FunctionPlotBox extends ViewBoxAnnotatableComponent<FieldViewProps> } getAnchor = (addAsAnnotation: boolean, pinProps?: PinProps) => { const anchor = Docs.Create.ConfigDocument({ annotationOn: this.Document }); - PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), datarange: true } }, this.Document); + PinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), datarange: true } }, this.Document); anchor.config_xRange = new List<number>(Array.from(this._plot.options.xAxis.domain)); anchor.config_yRange = new List<number>(Array.from(this._plot.options.yAxis.domain)); if (addAsAnnotation) this.addDocument(anchor); diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 6d3d4be06..8bd5ab03d 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -21,18 +21,18 @@ import { Networking } from '../../Network'; import { DocumentManager } from '../../util/DocumentManager'; import { DragManager } from '../../util/DragManager'; import { undoBatch } from '../../util/UndoManager'; -import { ContextMenu } from '../ContextMenu'; import { CollectionFreeFormView } from '../collections/collectionFreeForm/CollectionFreeFormView'; +import { ContextMenu } from '../ContextMenu'; import { ContextMenuProps } from '../ContextMenuItem'; -import { PinProps, ViewBoxAnnotatableComponent, ViewBoxInterface } from '../DocComponent'; +import { ViewBoxAnnotatableComponent, ViewBoxInterface } from '../DocComponent'; import { MarqueeAnnotator } from '../MarqueeAnnotator'; import { OverlayView } from '../OverlayView'; import { AnchorMenu } from '../pdf/AnchorMenu'; +import { PinDocView, PinProps } from '../PinFuncs'; import { StyleProp } from '../StyleProvider'; import { OpenWhere } from './DocumentView'; import { FieldView, FieldViewProps, FocusViewOptions } from './FieldView'; import './ImageBox.scss'; -import { PresBox } from './trails'; export class ImageEditorData { // eslint-disable-next-line no-use-before-define @@ -102,7 +102,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() impl if (anchor) { if (!addAsAnnotation) anchor.backgroundColor = 'transparent'; addAsAnnotation && this.addDocument(anchor); - PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), pannable: !visibleAnchor } }, this.Document); + PinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), pannable: !visibleAnchor } }, this.Document); return anchor; } return this.Document; diff --git a/src/client/views/nodes/LabelBox.tsx b/src/client/views/nodes/LabelBox.tsx index 9df928581..89270652c 100644 --- a/src/client/views/nodes/LabelBox.tsx +++ b/src/client/views/nodes/LabelBox.tsx @@ -10,12 +10,12 @@ import { DragManager } from '../../util/DragManager'; import { undoBatch } from '../../util/UndoManager'; import { ContextMenu } from '../ContextMenu'; import { ContextMenuProps } from '../ContextMenuItem'; -import { PinProps, ViewBoxBaseComponent } from '../DocComponent'; +import { ViewBoxBaseComponent } from '../DocComponent'; +import { PinProps, PinDocView } from '../PinFuncs'; import { StyleProp } from '../StyleProvider'; import { FieldView, FieldViewProps } from './FieldView'; import BigText from './LabelBigText'; import './LabelBox.scss'; -import { PresBox } from './trails'; @observer export class LabelBox extends ViewBoxBaseComponent<FieldViewProps>() { @@ -96,7 +96,7 @@ export class LabelBox extends ViewBoxBaseComponent<FieldViewProps>() { if (anchor) { if (!addAsAnnotation) anchor.backgroundColor = 'transparent'; // addAsAnnotation && this.addDocument(anchor); - PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}) } }, this.Document); + PinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}) } }, this.Document); return anchor; } return anchor; diff --git a/src/client/views/nodes/MapBox/AnimationUtility.ts b/src/client/views/nodes/MapBox/AnimationUtility.ts index 3a2679ecf..f4bae66bb 100644 --- a/src/client/views/nodes/MapBox/AnimationUtility.ts +++ b/src/client/views/nodes/MapBox/AnimationUtility.ts @@ -1,7 +1,6 @@ import * as turf from '@turf/turf'; import { Position } from '@turf/turf'; import * as d3 from 'd3'; -// eslint-disable-next-line import/no-extraneous-dependencies import { Feature, GeoJsonProperties, Geometry } from 'geojson'; import mapboxgl, { MercatorCoordinate } from 'mapbox-gl'; import { action, computed, makeObservable, observable, runInAction } from 'mobx'; diff --git a/src/client/views/nodes/MapBox/MapBox.tsx b/src/client/views/nodes/MapBox/MapBox.tsx index 6495cf440..60dad314f 100644 --- a/src/client/views/nodes/MapBox/MapBox.tsx +++ b/src/client/views/nodes/MapBox/MapBox.tsx @@ -6,7 +6,6 @@ import { Checkbox, FormControlLabel, TextField } from '@mui/material'; import * as turf from '@turf/turf'; import { IconButton, Size, Type } from 'browndash-components'; import * as d3 from 'd3'; -// eslint-disable-next-line import/no-extraneous-dependencies import { Feature, FeatureCollection, GeoJsonProperties, Geometry, LineString, Position } from 'geojson'; import mapboxgl, { LngLatBoundsLike, MapLayerMouseEvent } from 'mapbox-gl'; import { IReactionDisposer, ObservableMap, action, autorun, computed, makeObservable, observable, runInAction } from 'mobx'; @@ -25,14 +24,14 @@ import { DocumentManager } from '../../../util/DocumentManager'; import { DragManager } from '../../../util/DragManager'; import { LinkManager } from '../../../util/LinkManager'; import { UndoManager, undoable } from '../../../util/UndoManager'; -import { PinProps, ViewBoxAnnotatableComponent, ViewBoxInterface } from '../../DocComponent'; +import { ViewBoxAnnotatableComponent, ViewBoxInterface } from '../../DocComponent'; +import { PinProps, PinDocView } from '../../PinFuncs'; import { SidebarAnnos } from '../../SidebarAnnos'; import { MarqueeOptionsMenu } from '../../collections/collectionFreeForm'; import { Colors } from '../../global/globalEnums'; import { DocumentView } from '../DocumentView'; import { FieldView, FieldViewProps, FocusViewOptions } from '../FieldView'; import { FormattedTextBox } from '../formattedText/FormattedTextBox'; -import { PresBox } from '../trails'; import { fastSpeedIcon, mediumSpeedIcon, slowSpeedIcon } from './AnimationSpeedIcons'; import { AnimationSpeed, AnimationStatus, AnimationUtility } from './AnimationUtility'; import { MapAnchorMenu } from './MapAnchorMenu'; @@ -462,7 +461,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem if (anchor) { if (!addAsAnnotation) anchor.backgroundColor = 'transparent'; addAsAnnotation && this.addDocument(anchor); - PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), map: true } }, this.Document); + PinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), map: true } }, this.Document); return anchor; } return this.Document; diff --git a/src/client/views/nodes/MapboxMapBox/MapboxContainer.tsx b/src/client/views/nodes/MapboxMapBox/MapboxContainer.tsx index c19528af6..d899fcb9a 100644 --- a/src/client/views/nodes/MapboxMapBox/MapboxContainer.tsx +++ b/src/client/views/nodes/MapboxMapBox/MapboxContainer.tsx @@ -17,7 +17,8 @@ import { DragManager } from '../../../util/DragManager'; import { LinkManager } from '../../../util/LinkManager'; import { Transform } from '../../../util/Transform'; import { UndoManager, undoable } from '../../../util/UndoManager'; -import { PinProps, ViewBoxAnnotatableComponent } from '../../DocComponent'; +import { ViewBoxAnnotatableComponent } from '../../DocComponent'; +import { PinProps, PinDocView } from '../../PinFuncs'; import { SidebarAnnos } from '../../SidebarAnnos'; import { MarqueeOptionsMenu } from '../../collections/collectionFreeForm'; import { Colors } from '../../global/globalEnums'; @@ -26,7 +27,6 @@ import { FieldView, FieldViewProps, FocusViewOptions } from '../FieldView'; import { MapAnchorMenu } from '../MapBox/MapAnchorMenu'; import '../MapBox/MapBox.scss'; import { FormattedTextBox } from '../formattedText/FormattedTextBox'; -import { PresBox } from '../trails'; /** * MapBox architecture: @@ -487,7 +487,7 @@ export class MapBoxContainer extends ViewBoxAnnotatableComponent<FieldViewProps> if (anchor) { if (!addAsAnnotation) anchor.backgroundColor = 'transparent'; addAsAnnotation && this.addDocument(anchor); - PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), map: true } }, this.Document); + PinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), map: true } }, this.Document); return anchor; } return this.Document; diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index 4d5013437..fbf5e018c 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -26,16 +26,16 @@ import { CollectionFreeFormView } from '../collections/collectionFreeForm'; import { CollectionStackingView } from '../collections/CollectionStackingView'; import { ContextMenu } from '../ContextMenu'; import { ContextMenuProps } from '../ContextMenuItem'; -import { PinProps, ViewBoxAnnotatableComponent, ViewBoxInterface } from '../DocComponent'; +import { ViewBoxAnnotatableComponent, ViewBoxInterface } from '../DocComponent'; import { Colors } from '../global/globalEnums'; -import { CreateImage } from './WebBoxRenderer'; import { PDFViewer } from '../pdf/PDFViewer'; +import { PinDocView, PinProps } from '../PinFuncs'; import { SidebarAnnos } from '../SidebarAnnos'; import { DocumentView, OpenWhere } from './DocumentView'; import { FieldView, FieldViewProps, FocusViewOptions } from './FieldView'; import { ImageBox } from './ImageBox'; import './PDFBox.scss'; -import { PresBox } from './trails'; +import { CreateImage } from './WebBoxRenderer'; @observer export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implements ViewBoxInterface { @@ -265,7 +265,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem }); const visibleAnchor = this._pdfViewer?._getAnchor?.(this._pdfViewer.savedAnnotations(), true); const anchor = visibleAnchor ?? docAnchor(); - PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), scrollable: true, pannable: true } }, this.Document); + PinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), scrollable: true, pannable: true } }, this.Document); anchor.text = ele?.textContent ?? ''; anchor.text_html = ele?.innerHTML; addAsAnnotation && this.addDocument(anchor); diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx index b8ec0081a..13ee3250e 100644 --- a/src/client/views/nodes/VideoBox.tsx +++ b/src/client/views/nodes/VideoBox.tsx @@ -25,14 +25,14 @@ import { CollectionFreeFormView } from '../collections/collectionFreeForm/Collec import { CollectionStackedTimeline, TrimScope } from '../collections/CollectionStackedTimeline'; import { ContextMenu } from '../ContextMenu'; import { ContextMenuProps } from '../ContextMenuItem'; -import { PinProps, ViewBoxAnnotatableComponent, ViewBoxInterface } from '../DocComponent'; +import { ViewBoxAnnotatableComponent, ViewBoxInterface } from '../DocComponent'; import { MarqueeAnnotator } from '../MarqueeAnnotator'; import { AnchorMenu } from '../pdf/AnchorMenu'; +import { PinDocView, PinProps } from '../PinFuncs'; import { StyleProp } from '../StyleProvider'; import { DocumentView } from './DocumentView'; import { FieldView, FieldViewProps, FocusViewOptions } from './FieldView'; import { RecordingBox } from './RecordingBox'; -import { PresBox } from './trails'; import './VideoBox.scss'; /** @@ -357,7 +357,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps>() impl addAsAnnotation && marquee ? CollectionStackedTimeline.createAnchor(this.Document, this.dataDoc, this.annotationKey, timecode || undefined, undefined, marquee, addAsAnnotation) || this.Document : Docs.Create.ConfigDocument({ title: '#' + timecode, _timecodeToShow: timecode, annotationOn: this.Document }); - PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), temporal: true, pannable: true } }, this.Document); + PinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), temporal: true, pannable: true } }, this.Document); return anchor; }; diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index 725c5bab4..dfe237a86 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -27,19 +27,19 @@ import { MarqueeOptionsMenu } from '../collections/collectionFreeForm'; import { CollectionFreeFormView } from '../collections/collectionFreeForm/CollectionFreeFormView'; import { ContextMenu } from '../ContextMenu'; import { ContextMenuProps } from '../ContextMenuItem'; -import { PinProps, ViewBoxAnnotatableComponent, ViewBoxInterface } from '../DocComponent'; +import { ViewBoxAnnotatableComponent, ViewBoxInterface } from '../DocComponent'; import { Colors } from '../global/globalEnums'; import { LightboxView } from '../LightboxView'; import { MarqueeAnnotator } from '../MarqueeAnnotator'; import { AnchorMenu } from '../pdf/AnchorMenu'; import { Annotation } from '../pdf/Annotation'; import { GPTPopup } from '../pdf/GPTPopup/GPTPopup'; +import { PinDocView, PinProps } from '../PinFuncs'; import { SidebarAnnos } from '../SidebarAnnos'; import { StyleProp } from '../StyleProvider'; import { DocumentView, OpenWhere } from './DocumentView'; import { FieldView, FieldViewProps, FocusViewOptions } from './FieldView'; import { LinkInfo } from './LinkDocPreview'; -import { PresBox } from './trails'; import './WebBox.scss'; const { CreateImage } = require('./WebBoxRenderer'); @@ -350,7 +350,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem y: NumCast(this.layoutDoc._layout_scrollTop), annotationOn: this.Document, }); - PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), scrollable: !!pinProps?.pinData, pannable: true } }, this.Document); + PinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), scrollable: !!pinProps?.pinData, pannable: true } }, this.Document); anchor.text = ele?.textContent ?? ''; anchor.text_html = ele?.innerHTML ?? this._selectionText; addAsAnnotation && this.addDocumentWrapper(anchor); diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index d659d5e3c..9bcf5027f 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -45,18 +45,18 @@ import { CollectionStackingView } from '../../collections/CollectionStackingView import { CollectionTreeView } from '../../collections/CollectionTreeView'; import { ContextMenu } from '../../ContextMenu'; import { ContextMenuProps } from '../../ContextMenuItem'; -import { PinProps, ViewBoxAnnotatableComponent, ViewBoxInterface } from '../../DocComponent'; +import { ViewBoxAnnotatableComponent, ViewBoxInterface } from '../../DocComponent'; import { Colors } from '../../global/globalEnums'; import { LightboxView } from '../../LightboxView'; import { AnchorMenu } from '../../pdf/AnchorMenu'; import { GPTPopup } from '../../pdf/GPTPopup/GPTPopup'; +import { PinDocView, PinProps } from '../../PinFuncs'; import { SidebarAnnos } from '../../SidebarAnnos'; import { styleFromLayoutString, StyleProp } from '../../StyleProvider'; import { mediaState } from '../AudioBox'; import { DocumentView, DocumentViewInternal, OpenWhere } from '../DocumentView'; import { FieldView, FieldViewProps, FocusViewOptions } from '../FieldView'; import { LinkInfo } from '../LinkDocPreview'; -import { PresBox } from '../trails'; import { DashDocCommentView } from './DashDocCommentView'; import { DashDocView } from './DashDocView'; import { DashFieldView } from './DashFieldView'; @@ -252,7 +252,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB this._finishingLink = true; this.makeLinkAnchor(anchor, OpenWhere.addRight, undefined, 'Anchored Selection', false, addAsAnnotation); this._finishingLink = false; - PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), scrollable: true } }, this.Document); + PinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), scrollable: true } }, this.Document); return anchor; }; diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx index 4fe7ec993..4cf9e99fa 100644 --- a/src/client/views/nodes/trails/PresBox.tsx +++ b/src/client/views/nodes/trails/PresBox.tsx @@ -6,9 +6,9 @@ import { action, computed, IReactionDisposer, makeObservable, observable, Observ import { observer } from 'mobx-react'; import * as React from 'react'; import { lightOrDark, returnFalse, returnOne, setupMoveUpEvents, StopEvent } from '../../../../ClientUtils'; -import { Doc, DocListCast, Field, FieldType, FieldResult, NumListCast, Opt, StrListCast } from '../../../../fields/Doc'; +import { Doc, DocListCast, Field, FieldResult, FieldType, NumListCast, Opt, StrListCast } from '../../../../fields/Doc'; import { Animation, DocData, TransitionTimer } from '../../../../fields/DocSymbols'; -import { Copy, Id } from '../../../../fields/FieldSymbols'; +import { Copy } from '../../../../fields/FieldSymbols'; import { InkField } from '../../../../fields/InkField'; import { List } from '../../../../fields/List'; import { ObjectField } from '../../../../fields/ObjectField'; @@ -24,6 +24,7 @@ import { dropActionType } from '../../../util/DropActionTypes'; import { ScriptingGlobals } from '../../../util/ScriptingGlobals'; import { SelectionManager } from '../../../util/SelectionManager'; import { SerializationHelper } from '../../../util/SerializationHelper'; +import { SettingsManager } from '../../../util/SettingsManager'; import { SnappingManager } from '../../../util/SnappingManager'; import { undoBatch, UndoManager } from '../../../util/UndoManager'; import { CollectionDockingView } from '../../collections/CollectionDockingView'; @@ -31,15 +32,15 @@ import { CollectionFreeFormView } from '../../collections/collectionFreeForm'; import { CollectionStackedTimeline } from '../../collections/CollectionStackedTimeline'; import { CollectionView } from '../../collections/CollectionView'; import { TreeView } from '../../collections/TreeView'; -import { pinDataTypes as dataTypes, PinProps, ViewBoxBaseComponent } from '../../DocComponent'; +import { ViewBoxBaseComponent } from '../../DocComponent'; import { Colors } from '../../global/globalEnums'; import { LightboxView } from '../../LightboxView'; +import { pinDataTypes as dataTypes } from '../../PinFuncs'; import { DocumentView, OpenWhere, OpenWhereMod } from '../DocumentView'; import { FieldView, FieldViewProps, FocusViewOptions } from '../FieldView'; import { ScriptingBox } from '../ScriptingBox'; import './PresBox.scss'; import { PresEffect, PresEffectDirection, PresMovement, PresStatus } from './PresEnums'; -import { SettingsManager } from '../../../util/SettingsManager'; @observer export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { @@ -144,6 +145,10 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { } componentDidMount() { + this._disposers.pause = reaction( + () => SnappingManager.UserPanned, + () => this.pauseAutoPres() + ); this._disposers.keyboard = reaction( () => this.selectedDoc, selected => { @@ -618,114 +623,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { return undefined; } - /// copies values from the targetDoc (which is the prototype of the pinDoc) to - /// reserved fields on the pinDoc so that those values can be restored to the - /// target doc when navigating to it. - @action - static pinDocView(pinDocIn: Doc, pinProps: PinProps, targetDoc: Doc) { - const pinDoc = pinDocIn; - pinDoc.presentation = true; - pinDoc.config = ''; - if (pinProps.pinDocLayout) { - pinDoc.config_pinLayout = true; - pinDoc.config_x = NumCast(targetDoc.x); - pinDoc.config_y = NumCast(targetDoc.y); - pinDoc.config_rotation = NumCast(targetDoc.rotation); - pinDoc.config_width = NumCast(targetDoc.width); - pinDoc.config_height = NumCast(targetDoc.height); - } - if (pinProps.pinAudioPlay) pinDoc.presPlayAudio = true; - if (pinProps.pinData) { - pinDoc.config_pinData = - pinProps.pinData.scrollable || - pinProps.pinData.temporal || - pinProps.pinData.pannable || - pinProps.pinData.type_collection || - pinProps.pinData.clippable || - pinProps.pinData.datarange || - pinProps.pinData.dataview || - pinProps.pinData.poslayoutview || - pinProps?.activeFrame !== undefined; - const fkey = Doc.LayoutFieldKey(targetDoc); - if (pinProps.pinData.dataview) { - pinDoc.config_usePath = targetDoc[fkey + '_usePath']; - pinDoc.config_data = targetDoc[fkey] instanceof ObjectField ? (targetDoc[fkey] as ObjectField)[Copy]() : targetDoc.data; - } - if (pinProps.pinData.dataannos) { - const fieldKey = Doc.LayoutFieldKey(targetDoc); - pinDoc.config_annotations = new List<Doc>(DocListCast(targetDoc[DocData][fieldKey + '_annotations']).filter(doc => !doc.layout_unrendered)); - } - if (pinProps.pinData.inkable) { - pinDoc.config_fillColor = targetDoc.fillColor; - pinDoc.config_color = targetDoc.color; - pinDoc.config_width = targetDoc._width; - pinDoc.config_height = targetDoc._height; - } - if (pinProps.pinData.scrollable) pinDoc.config_scrollTop = targetDoc._layout_scrollTop; - if (pinProps.pinData.clippable) { - const fieldKey = Doc.LayoutFieldKey(targetDoc); - pinDoc.config_clipWidth = targetDoc[fieldKey + '_clipWidth']; - } - if (pinProps.pinData.datarange) { - pinDoc.config_xRange = undefined; // targetDoc?.xrange; - pinDoc.config_yRange = undefined; // targetDoc?.yrange; - } - if (pinProps.pinData.map) { - // pinDoc.config_latitude = targetDoc?.latitude; - // pinDoc.config_longitude = targetDoc?.longitude; - pinDoc.config_map_zoom = targetDoc?.map_zoom; - pinDoc.config_map_type = targetDoc?.map_type; - // ... - } - if (pinProps.pinData.poslayoutview) - pinDoc.config_pinLayoutData = new List<string>( - DocListCast(targetDoc[fkey] as ObjectField).map(d => - JSON.stringify({ - id: d[Id], - x: NumCast(d.x), - y: NumCast(d.y), - w: NumCast(d._width), - h: NumCast(d._height), - fill: StrCast(d._fillColor), - back: StrCast(d._backgroundColor), - data: SerializationHelper.Serialize(d.data instanceof ObjectField ? d.data[Copy]() : ''), - text: SerializationHelper.Serialize(d.text instanceof ObjectField ? d.text[Copy]() : ''), - }) - ) - ); - if (pinProps.pinData.type_collection) pinDoc.config_viewType = targetDoc._type_collection; - if (pinProps.pinData.filters) pinDoc.config_docFilters = ObjectField.MakeCopy(targetDoc.childFilters as ObjectField); - if (pinProps.pinData.pivot) pinDoc.config_pivotField = targetDoc._pivotField; - if (pinProps.pinData.pannable) { - pinDoc.config_panX = NumCast(targetDoc._freeform_panX); - pinDoc.config_panY = NumCast(targetDoc._freeform_panY); - pinDoc.config_viewScale = NumCast(targetDoc._freeform_scale, 1); - } - if (pinProps.pinData.temporal) { - pinDoc.config_clipStart = targetDoc._layout_currentTimecode; - const duration = NumCast(pinDoc[`${Doc.LayoutFieldKey(pinDoc)}_duration`], NumCast(targetDoc.config_clipStart) + 0.1); - pinDoc.config_clipEnd = NumCast(pinDoc.config_clipStart) + NumCast(targetDoc.clipEnd, duration); - } - } - if (pinProps?.pinViewport) { - // If pinWithView option set then update scale and x / y props of slide - const bounds = pinProps.pinViewport; - pinDoc.config_pinView = true; - pinDoc.config_viewScale = NumCast(targetDoc._freeform_scale, 1); - pinDoc.config_panX = bounds.left + bounds.width / 2; - pinDoc.config_panY = bounds.top + bounds.height / 2; - pinDoc.config_viewBounds = new List<number>([bounds.left, bounds.top, bounds.left + bounds.width, bounds.top + bounds.height]); - } - } - - @action - static reversePin(pinDoc: Doc, targetDoc: Doc) { - // const fkey = Doc.LayoutFieldKey(targetDoc); - pinDoc.config_data = targetDoc.data; - - console.log(pinDoc.presData); - } - /** * This method makes sure that cursor navigates to the element that * has the option open and last in the group. diff --git a/src/client/views/nodes/trails/PresElementBox.tsx b/src/client/views/nodes/trails/PresElementBox.tsx index 5fa32ad12..cf78a45b7 100644 --- a/src/client/views/nodes/trails/PresElementBox.tsx +++ b/src/client/views/nodes/trails/PresElementBox.tsx @@ -22,6 +22,7 @@ import { TreeView } from '../../collections/TreeView'; import { ViewBoxBaseComponent } from '../../DocComponent'; import { EditableView } from '../../EditableView'; import { Colors } from '../../global/globalEnums'; +import { PinDocView } from '../../PinFuncs'; import { StyleProp } from '../../StyleProvider'; import { DocumentView } from '../DocumentView'; import { FieldView, FieldViewProps } from '../FieldView'; @@ -335,7 +336,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() { updateCapturedViewContents = undoable( action((presTargetDoc: Doc, activeItem: Doc) => { const target = DocCast(presTargetDoc.annotationOn) ?? presTargetDoc; - PresBox.pinDocView(activeItem, { pinData: PresBox.pinDataTypes(target) }, target); + PinDocView(activeItem, { pinData: PresBox.pinDataTypes(target) }, target); }), 'updated captured view contents' ); diff --git a/src/server/server_Initialization.ts b/src/server/server_Initialization.ts index 5e6c855c9..9183688c6 100644 --- a/src/server/server_Initialization.ts +++ b/src/server/server_Initialization.ts @@ -12,7 +12,6 @@ import * as passport from 'passport'; import * as request from 'request'; import * as webpack from 'webpack'; import * as wdm from 'webpack-dev-middleware'; -// eslint-disable-next-line import/no-extraneous-dependencies import * as whm from 'webpack-hot-middleware'; import * as zlib from 'zlib'; import * as config from '../../webpack.config'; |