From 3c1b393732ef9dc704a2f40b103c37b3f8370ba7 Mon Sep 17 00:00:00 2001 From: Aubrey Li Date: Tue, 26 Oct 2021 17:16:10 -0400 Subject: update Mapbox image rendering --- src/client/views/nodes/MapBox/MapBox.tsx | 207 ++++++++++++++++----- .../views/nodes/formattedText/FormattedTextBox.tsx | 4 + .../Session/agents/process_message_router.ts | 2 +- 3 files changed, 162 insertions(+), 51 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/MapBox/MapBox.tsx b/src/client/views/nodes/MapBox/MapBox.tsx index 0cf3ae326..4c0c4c0c7 100644 --- a/src/client/views/nodes/MapBox/MapBox.tsx +++ b/src/client/views/nodes/MapBox/MapBox.tsx @@ -2,11 +2,11 @@ import { Autocomplete, GoogleMap, GoogleMapProps, InfoWindow, Marker } from '@re import { action, computed, IReactionDisposer, observable, ObservableMap } from 'mobx'; import { observer } from "mobx-react"; import * as React from "react"; -import { DataSym, Doc, DocListCast, FieldsSym, WidthSym } from '../../../../fields/Doc'; +import { DataSym, Doc, DocListCast, FieldsSym, Opt, WidthSym } from '../../../../fields/Doc'; import { documentSchema } from '../../../../fields/documentSchemas'; import { makeInterface } from '../../../../fields/Schema'; import { NumCast, StrCast } from '../../../../fields/Types'; -import { emptyFunction, setupMoveUpEvents } from '../../../../Utils'; +import { emptyFunction, OmitKeys, returnFalse, returnOne, setupMoveUpEvents, Utils } from '../../../../Utils'; import { Docs } from '../../../documents/Documents'; import { DragManager } from '../../../util/DragManager'; import { ViewBoxAnnotatableComponent, ViewBoxAnnotatableProps } from '../../DocComponent'; @@ -21,6 +21,13 @@ import { identity } from 'lodash'; import { Id } from '../../../../fields/FieldSymbols'; import { Colors } from '../../global/globalEnums'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { TraceMobx } from '../../../../fields/util'; +import { SnappingManager } from '../../../util/SnappingManager'; +import { InkTool } from '../../../../fields/InkField'; +import { CurrentUserUtils } from '../../../util/CurrentUserUtils'; +import { CollectionFreeFormView } from '../../collections/collectionFreeForm'; +import { MarqueeAnnotator } from '../../MarqueeAnnotator'; +import { Annotation } from '../../pdf/Annotation'; type MapDocument = makeInterface<[typeof documentSchema]>; const MapDocument = makeInterface(documentSchema); @@ -72,25 +79,34 @@ const options = { export class MapBox extends ViewBoxAnnotatableComponent, MapDocument>(MapDocument) { private _dropDisposer?: DragManager.DragDropDisposer; private _disposers: { [name: string]: IReactionDisposer } = {}; + private _annotationLayer: React.RefObject = React.createRef(); + @observable private _overlayAnnoInfo: Opt; + showInfo = action((anno: Opt) => this._overlayAnnoInfo = anno); public static LayoutString(fieldKey: string) { return FieldView.LayoutString(MapBox, fieldKey); } + public get SidebarKey() { return this.fieldKey + "-sidebar"; } + private _setPreviewCursor: undefined | ((x: number, y: number, drag: boolean, hide: boolean) => void); + @computed get inlineTextAnnotations() { return this.allMapMarkers.filter(a => a.textInlineAnnotations); } @observable private _map: google.maps.Map = null as unknown as google.maps.Map; - @observable private selectedPlace: MapMarker | undefined; + @observable private selectedPlace: MapMarker | Doc | undefined; @observable private markerMap: { [id: string]: google.maps.Marker } = {}; @observable private center = navigator.geolocation ? navigator.geolocation.getCurrentPosition : defaultCenter; @observable private zoom = 2.5; @observable private infoWindowOpen = false; + @observable private _marqueeing: number[] | undefined; + @observable private _isAnnotating = false; @observable private bounds = new window.google.maps.LatLngBounds(); @observable private inputRef = React.createRef(); @observable private searchMarkers: google.maps.Marker[] = []; @observable private searchBox = new window.google.maps.places.Autocomplete(this.inputRef.current!, options); @observable private _savedAnnotations = new ObservableMap(); @computed get allSidebarDocs() { return DocListCast(this.dataDoc[this.SidebarKey]); }; - @computed get allMapMarkers() { return DocListCast(this.dataDoc[this.annotationKey]); }; - @observable private allMarkers: Doc[] = []; + @computed get allMapMarkers() { return DocListCast(this.dataDoc[this.annotationKey]); }; // method to add MapMarker to allMapMarkers //TODO: change all markers to a filter function to change @observable private toggleAddMarker = false; + private _mainCont: React.RefObject = React.createRef(); + @observable _showSidebar = false; @computed get SidebarShown() { return this._showSidebar || this.layoutDoc._showSidebar ? true : false; } @@ -112,7 +128,7 @@ export class MapBox extends ViewBoxAnnotatableComponent { console.log('map bound is:' + this.bounds); - this.allMarkers.map(place => { + this.allMapMarkers.map(place => { this.bounds.extend({ lat: NumCast(place.lat), lng: NumCast(place.lng) }); return place._markerId; }); @@ -185,29 +201,28 @@ export class MapBox extends ViewBoxAnnotatableComponent { - this.allMapMarkers?.forEach(doc => { - console.log(doc); - // search for if the map marker exists, else create marker - if (doc.lat !== undefined && doc.lng !== undefined) { - console.log("image found! loading into marker document...") - const marker = Docs.Create.MapMarkerDocument(NumCast(doc.lat), NumCast(doc.lng), [doc], {}) - this.allMarkers.push(marker) - } - }) - } - - // TODO: things to ask & think about when designing - // 1. All markers are stored in allMarkers[], when adding a new marker (from a button, ideally not using drawManager), - // the new marker will be stored in allMarkers[] - // currently markerloadhandler only gets called when the map is reloaded, but we want it to be update on the GUI in real time - // TODO ** core issue --> real time updates ** + // private fillMarkers = () => { + // // console.log("allSidebarDocs:"); + // // console.log(this.allSidebarDocs); + // this.allSidebarDocs?.forEach(doc => { + // console.log(doc); + // // search for if the map marker exists, else create marker + // if (doc.lat !== undefined && doc.lng !== undefined) { + // console.log("image found! loading into marker document...") + // const marker = Docs.Create.MapMarkerDocument(NumCast(doc.lat), NumCast(doc.lng), [doc], {}) + // Doc.AddDocToList(this.dataDoc, this.annotationKey, marker) // add marker to annotation key + // } + // }); + // // console.log("allMarkers:") + // // console.log(this.allMarkers); + // } /** @@ -235,20 +250,19 @@ export class MapBox extends ViewBoxAnnotatableComponent { console.log("add marker map status:" + this.toggleAddMarker); if (this.toggleAddMarker == true) { this.placeMarker(e.latLng, map) - console.log(this.allMarkers) + console.log(this.allMapMarkers) } }) // this._map.addListener(drawingManager, 'markercomplete', this.addMarker) @@ -281,10 +295,11 @@ export class MapBox extends ViewBoxAnnotatableComponent { + private markerClickHandler = (e: MouseEvent, place: Doc) => { // set which place was clicked this.selectedPlace = place; + console.log("you have selected this location:"); console.log(this.selectedPlace); // used so clicking a second marker works @@ -303,6 +318,8 @@ export class MapBox extends ViewBoxAnnotatableComponent { + console.log("print all sidebar Docs"); + console.log(this.allSidebarDocs); if (!this.layoutDoc._showSidebar) this.toggleSidebar(); const docs = doc instanceof Doc ? [doc] : doc docs.forEach(doc => { @@ -311,11 +328,14 @@ export class MapBox extends ViewBoxAnnotatableComponent { @@ -397,16 +417,26 @@ export class MapBox extends ViewBoxAnnotatableComponent d?.author).length; - //&& !this.isContentActive() - return (!annotated) ? (null) :
; + const color = !annotated ? Colors.WHITE : Colors.BLACK; + const backgroundColor = !annotated ? this.sidebarWidth() ? Colors.MEDIUM_BLUE : Colors.BLACK : this.props.styleProvider?.(this.rootDoc, this.props as any, StyleProp.WidgetColor + (annotated ? ":annotated" : "")); + return (!annotated) ? (null) : +
+ +
; + // return (!annotated) ? (null) :
; } @action @@ -415,6 +445,7 @@ export class MapBox extends ViewBoxAnnotatableComponent { setupMoveUpEvents(this, e, this.sidebarMove, emptyFunction, () => setTimeout(this.toggleSidebar), false); } @@ -426,7 +457,29 @@ export class MapBox extends ViewBoxAnnotatableComponent void) => this._setPreviewCursor = func; + + @action + onMarqueeDown = (e: React.PointerEvent) => { + if (!e.altKey && e.button === 0 && this.props.isContentActive(true) && ![InkTool.Highlighter, InkTool.Pen].includes(CurrentUserUtils.SelectedTool)) { + setupMoveUpEvents(this, e, action(e => { + MarqueeAnnotator.clearAnnotations(this._savedAnnotations); + this._marqueeing = [e.clientX, e.clientY]; + return true; + }), returnFalse, () => MarqueeAnnotator.clearAnnotations(this._savedAnnotations), false); + } + } + @action finishMarquee = (x?: number, y?: number) => { + this._marqueeing = undefined; + this._isAnnotating = false; + x !== undefined && y !== undefined && this._setPreviewCursor?.(x, y, false, false); + } + + addDocumentWrapper = (doc: Doc | Doc[], annotationKey?: string) => { + return this.addDocument(doc, annotationKey); + } + + getAnchor = () => { const anchor = AnchorMenu.Instance?.GetAnchor(this._savedAnnotations) ?? @@ -440,12 +493,9 @@ export class MapBox extends ViewBoxAnnotatableComponent { - - } // create marker prop --> func that private renderMarkers = () => { - return this.allMarkers.map(place => ( + return this.allMapMarkers.map(place => ( { return this.infoWindowOpen && this.selectedPlace && (
@@ -485,7 +535,48 @@ export class MapBox extends ViewBoxAnnotatableComponent this.props.PanelWidth() / (this.props.scaling?.() || 1) - this.sidebarWidth(); // (this.Document.scrollHeight || Doc.NativeHeight(this.Document) || 0); + panelHeight = () => this.props.PanelHeight() / (this.props.scaling?.() || 1); // () => this._pageSizes.length && this._pageSizes[0] ? this._pageSizes[0].width : Doc.NativeWidth(this.Document); + scrollXf = () => this.props.ScreenToLocalTransform().translate(0, NumCast(this.layoutDoc._scrollTop)); + transparentFilter = () => [...this.props.docFilters(), Utils.IsTransparentFilter()]; + opaqueFilter = () => [...this.props.docFilters(), Utils.IsOpaqueFilter()]; + + anchorMenuClick = () => this._sidebarRef.current?.anchorMenuClick; + + @computed get annotationLayer() { + TraceMobx(); + return
+ {this.inlineTextAnnotations.sort((a, b) => NumCast(a.y) - NumCast(b.y)).map(anno => + ) + } +
; + + } + render() { + const renderAnnotations = (docFilters?: () => string[]) => + ; return
@@ -497,10 +588,16 @@ export class MapBox extends ViewBoxAnnotatableComponent e.stopPropagation()} onPointerDown={e => (e.button === 0 && !e.ctrlKey) && e.stopPropagation()} style={{ width: `calc(100% - ${this.sidebarWidthPercent})` }}> + +
+ {renderAnnotations(this.transparentFilter)} +
+ {renderAnnotations(this.opaqueFilter)} + {SnappingManager.GetIsDragging() ? (null) : renderAnnotations()} + {this.annotationLayer} this.loadHandler(map)} options={mapOptions} > @@ -513,13 +610,24 @@ export class MapBox extends ViewBoxAnnotatableComponent + {!this._marqueeing || !this._mainCont.current || !this._annotationLayer.current ? (null) : + }
{/* {/* */}
(this.props.scaling?.() || 1) * NumCast(this.layoutDoc._viewScale, 1); sidebarAddDocument = (doc: Doc | Doc[], sidebarKey?: string) => { if (!this.layoutDoc._showSidebar) this.toggleSidebar(); + // console.log("printting allSideBarDocs"); + // console.log(this.allSidebarDocs); return this.addDocument(doc, sidebarKey); } sidebarMoveDocument = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (doc: Doc | Doc[]) => boolean) => this.moveDocument(doc, targetCollection, addDocument, this.SidebarKey); @@ -1506,6 +1509,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp const annotated = DocListCast(this.dataDoc[this.SidebarKey]).filter(d => d?.author).length; const color = !annotated ? Colors.WHITE : Colors.BLACK; const backgroundColor = !annotated ? this.sidebarWidth() ? Colors.MEDIUM_BLUE : Colors.BLACK : this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.WidgetColor + (annotated ? ":annotated" : "")); + return (!annotated && (!this.props.isContentActive() || SnappingManager.GetIsDragging())) ? (null) :
names.map(name => delete this.handlers[name]); -- cgit v1.2.3-70-g09d2