diff options
author | Aubrey Li <Aubrey-Li> | 2021-10-26 17:16:10 -0400 |
---|---|---|
committer | Aubrey Li <Aubrey-Li> | 2021-10-26 17:16:10 -0400 |
commit | 3c1b393732ef9dc704a2f40b103c37b3f8370ba7 (patch) | |
tree | ef0ec8ad93e630b4309f88ecd347a4ea49abf8bf /src | |
parent | 07295bafb5fbf9651a9404aace4f3cd134685043 (diff) |
update Mapbox image rendering
Diffstat (limited to 'src')
-rw-r--r-- | src/client/views/nodes/MapBox/MapBox.tsx | 207 | ||||
-rw-r--r-- | src/client/views/nodes/formattedText/FormattedTextBox.tsx | 4 | ||||
-rw-r--r-- | src/server/DashSession/Session/agents/process_message_router.ts | 2 |
3 files changed, 162 insertions, 51 deletions
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<ViewBoxAnnotatableProps & FieldViewProps & Partial<GoogleMapProps>, MapDocument>(MapDocument) { private _dropDisposer?: DragManager.DragDropDisposer; private _disposers: { [name: string]: IReactionDisposer } = {}; + private _annotationLayer: React.RefObject<HTMLDivElement> = React.createRef(); + @observable private _overlayAnnoInfo: Opt<Doc>; + showInfo = action((anno: Opt<Doc>) => 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<HTMLInputElement>(); @observable private searchMarkers: google.maps.Marker[] = []; @observable private searchBox = new window.google.maps.places.Autocomplete(this.inputRef.current!, options); @observable private _savedAnnotations = new ObservableMap<number, HTMLDivElement[]>(); @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<HTMLDivElement> = 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<ViewBoxAnnotatableProps // iterate allMarkers to size, center, and zoom map to contain all markers private fitBounds = (map: google.maps.Map) => { 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<ViewBoxAnnotatableProps }); map.panTo(position); const mapMarker = Docs.Create.MapMarkerDocument(NumCast(position.lat()), NumCast(position.lng()), [], {}); - this.allMarkers.push(mapMarker); + this.addDocument(mapMarker, this.annotationKey); + // Doc.AddDocToList(this.dataDoc, this.annotationKey, mapMarker); } /** * A function that examines allMapMarkers docs in the map node and form MapMarkers */ - private fillMarkers = () => { - 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<ViewBoxAnnotatableProps ); } else { alert("Your geolocation is not supported by browser.") - } - this.fitBounds(map); - console.log("content in the allMapsMarker array:"); - console.log(this.allMapMarkers); - console.log("content in the sidebarDocs array:"); + }; + console.log("all sidebar docs during map loading is:") console.log(this.allSidebarDocs); - this.fillMarkers(); + this.fitBounds(map); + // this.fillMarkers(); + // listener to addmarker event this._map.addListener('click', (e) => { 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<ViewBoxAnnotatableProps } @action - private markerClickHandler = (e: MouseEvent, place: any) => { + 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<ViewBoxAnnotatableProps * @returns */ sidebarAddDocument = (doc: Doc | Doc[], sidebarKey?: string) => { + 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<ViewBoxAnnotatableProps this.addDocument(marker, this.annotationKey) } }) //add to annotation list + console.log("sidebaraddDocument"); + console.log(doc); + return this.addDocument(doc, sidebarKey); // add to sidebar list } /** - * What does this do exactly? How to operate on sidebar? + * Toggle sidebar onclick the tiny comment button on the top right corner * @param e */ sidebarBtnDown = (e: React.PointerEvent) => { @@ -397,16 +417,26 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps this.selectedPlace = undefined; } - public get SidebarKey() { return this.fieldKey + "-sidebar"; } - @computed get sidebarHandle() { + TraceMobx(); const annotated = DocListCast(this.dataDoc[this.SidebarKey]).filter(d => d?.author).length; - //&& !this.isContentActive() - return (!annotated) ? (null) : <div className="mapBox-sidebar-handle" onPointerDown={this.sidebarDown} - style={{ - left: `max(0px, calc(100% - ${this.sidebarWidthPercent} ${this.sidebarWidth() ? "- 5px" : "- 10px"}))`, - background: this.props.styleProvider?.(this.rootDoc, this.props as any, StyleProp.WidgetColor + (annotated ? ":annotated" : "")) - }} />; + 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) : + <div className="formattedTextBox-sidebar-handle" onPointerDown={this.sidebarDown} + style={{ + left: `max(0px, calc(100% - ${this.sidebarWidthPercent} - 17px))`, + backgroundColor: backgroundColor, + color: color, + opacity: annotated ? 1 : undefined + }} > + <FontAwesomeIcon icon={"comment-alt"} /> + </div>; + // return (!annotated) ? (null) : <div className="mapBox-sidebar-handle" onPointerDown={this.sidebarDown} + // style={{ + // left: `max(0px, calc(100% - ${this.sidebarWidthPercent} ${this.sidebarWidth() ? "- 5px" : "- 10px"}))`, + // background: this.props.styleProvider?.(this.rootDoc, this.props as any, StyleProp.WidgetColor + (annotated ? ":annotated" : "")) + // }} />; } @action @@ -415,6 +445,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps this.layoutDoc._showSidebar = ((this.layoutDoc._sidebarWidthPercent = StrCast(this.layoutDoc._sidebarWidthPercent, "0%") === "0%" ? "50%" : "0%")) !== "0%"; this.layoutDoc._width = this.layoutDoc._showSidebar ? NumCast(this.layoutDoc._width) * 2 : Math.max(20, NumCast(this.layoutDoc._width) - prevWidth); } + sidebarDown = (e: React.PointerEvent) => { setupMoveUpEvents(this, e, this.sidebarMove, emptyFunction, () => setTimeout(this.toggleSidebar), false); } @@ -426,7 +457,29 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps return false; } - // TODO what's the difference between savedAnnotations & allMapMarkers? + setPreviewCursor = (func?: (x: number, y: number, drag: boolean, hide: boolean) => 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<ViewBoxAnnotatableProps return anchor; } - private saveMarkerInfo = () => { - - } // create marker prop --> func that private renderMarkers = () => { - return this.allMarkers.map(place => ( + return this.allMapMarkers.map(place => ( <Marker key={place[Id]} position={{ lat: NumCast(place.lat), lng: NumCast(place.lng) }} @@ -458,7 +508,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps private renderInfoWindow = () => { return this.infoWindowOpen && this.selectedPlace && ( <InfoWindow - anchor={this.markerMap[this.selectedPlace._markerId!]} + // anchor={this.markerMap[this.selectedPlace.Id!]} onCloseClick={this.handleInfoWindowClose} > <div style={{ backgroundColor: 'white', opacity: 0.75, padding: 12 }}> @@ -485,7 +535,48 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps ) } + panelWidth = () => 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 <div className="webBox-annotationLayer" style={{ height: Doc.NativeHeight(this.Document) || undefined }} ref={this._annotationLayer}> + {this.inlineTextAnnotations.sort((a, b) => NumCast(a.y) - NumCast(b.y)).map(anno => + <Annotation {...this.props} fieldKey={this.annotationKey} showInfo={this.showInfo} dataDoc={this.dataDoc} anno={anno} key={`${anno[Id]}-annotation`} />) + } + </div>; + + } + render() { + const renderAnnotations = (docFilters?: () => string[]) => + <CollectionFreeFormView {...OmitKeys(this.props, ["NativeWidth", "NativeHeight", "setContentView"]).omit} + renderDepth={this.props.renderDepth + 1} + isAnnotationOverlay={true} + fieldKey={this.annotationKey} + CollectionView={undefined} + setPreviewCursor={this.setPreviewCursor} + PanelWidth={this.panelWidth} + PanelHeight={this.panelHeight} + ScreenToLocalTransform={this.scrollXf} + scaling={returnOne} + dropAction={"alias"} + docFilters={docFilters || this.props.docFilters} + dontRenderDocuments={docFilters ? false : true} + select={emptyFunction} + ContentScaling={returnOne} + bringToFront={emptyFunction} + whenChildContentsActiveChanged={this.whenChildContentsActiveChanged} + removeDocument={this.removeDocument} + moveDocument={this.moveDocument} + addDocument={this.sidebarAddDocument} + childPointerEvents={true} + pointerEvents={CurrentUserUtils.SelectedTool !== InkTool.None || this._isAnnotating || SnappingManager.GetIsDragging() ? "all" : "none"} />; return <div className="mapBox" ref={this._ref} // style={{ pointerEvents: this.isContentActive() ? undefined : "none" }} > @@ -497,10 +588,16 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps onWheel={e => e.stopPropagation()} onPointerDown={e => (e.button === 0 && !e.ctrlKey) && e.stopPropagation()} style={{ width: `calc(100% - ${this.sidebarWidthPercent})` }}> + + <div style={{ mixBlendMode: "multiply" }}> + {renderAnnotations(this.transparentFilter)} + </div> + {renderAnnotations(this.opaqueFilter)} + {SnappingManager.GetIsDragging() ? (null) : renderAnnotations()} + {this.annotationLayer} <GoogleMap mapContainerStyle={mapContainerStyle} zoom={this.zoom} - // center={this.center} onLoad={map => this.loadHandler(map)} options={mapOptions} > @@ -513,13 +610,24 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps {this.renderMarkers()} {this.renderInfoWindow()} </GoogleMap> + {!this._marqueeing || !this._mainCont.current || !this._annotationLayer.current ? (null) : + <MarqueeAnnotator rootDoc={this.rootDoc} + anchorMenuClick={this.anchorMenuClick} + scrollTop={0} + down={this._marqueeing} scaling={returnOne} + addDocument={this.addDocumentWrapper} + docView={this.props.docViewPath().lastElement()} + finishMarquee={this.finishMarquee} + savedAnnotations={this._savedAnnotations} + annotationLayer={this._annotationLayer.current} + mainCont={this._mainCont.current} />} </div> {/* {/* </LoadScript > */} <div className="mapBox-sidebar" style={{ width: `${this.sidebarWidthPercent}`, backgroundColor: `${this.sidebarColor}` }}> <SidebarAnnos ref={this._sidebarRef} {...this.props} - fieldKey={this.annotationKey} + fieldKey={this.fieldKey} rootDoc={this.rootDoc} layoutDoc={this.layoutDoc} dataDoc={this.dataDoc} @@ -530,7 +638,6 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps sidebarAddDocument={this.sidebarAddDocument} moveDocument={this.moveDocument} removeDocument={this.removeDocument} - //isContentActive={this.isContentActive} /> </div> <div className="mapBox-overlayButton-sidebar" key="sidebar" title="Toggle Sidebar" diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 63d2c1007..0d38bd5b8 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -120,6 +120,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp public ProseRef?: HTMLDivElement; public get EditorView() { return this._editorView; } public get SidebarKey() { return this.fieldKey + "-sidebar"; } + @computed get allSidebarDocs() { return DocListCast(this.dataDoc[this.SidebarKey]); }; @computed get sidebarWidthPercent() { return this._showSidebar ? "20%" : StrCast(this.layoutDoc._sidebarWidthPercent, "0%"); } @computed get sidebarColor() { return StrCast(this.layoutDoc.sidebarColor, StrCast(this.layoutDoc[this.props.fieldKey + "-backgroundColor"], "#e4e4e4")); } @@ -1488,6 +1489,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp sidebarContentScaling = () => (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) : <div className="formattedTextBox-sidebar-handle" onPointerDown={this.sidebarDown} style={{ diff --git a/src/server/DashSession/Session/agents/process_message_router.ts b/src/server/DashSession/Session/agents/process_message_router.ts index 6cc8aa941..0745ea455 100644 --- a/src/server/DashSession/Session/agents/process_message_router.ts +++ b/src/server/DashSession/Session/agents/process_message_router.ts @@ -33,7 +33,7 @@ export default abstract class IPCMessageReceiver { } } - /** + /** * Unregister all listeners at this message. */ public clearMessageListeners = (...names: string[]) => names.map(name => delete this.handlers[name]); |