package com.hiringhall.map import android.graphics.Bitmap import android.graphics.Canvas import android.view.View import android.view.ViewGroup import com.facebook.react.bridge.Arguments import com.facebook.react.bridge.ReadableArray import com.facebook.react.bridge.ReadableMap import com.facebook.react.bridge.WritableMap import com.facebook.react.common.MapBuilder import com.facebook.react.uimanager.ThemedReactContext import com.facebook.react.uimanager.ViewGroupManager import com.facebook.react.uimanager.annotations.ReactProp import com.facebook.react.uimanager.events.RCTEventEmitter import com.google.android.gms.maps.CameraUpdateFactory import com.google.android.gms.maps.GoogleMap import com.google.android.gms.maps.MapView import com.google.android.gms.maps.OnMapReadyCallback import com.google.android.gms.maps.model.BitmapDescriptorFactory import com.google.android.gms.maps.model.CameraPosition import com.google.android.gms.maps.model.LatLng import com.google.android.gms.maps.model.MarkerOptions /** * Created by saionara1 on 7/28/17. */ class MapsViewManager : ViewGroupManager(), OnMapReadyCallback { companion object { const val REACT_NAME = "RTCMapView" const val LATITUDE = "latitude" const val LONGITUDE = "longitude" const val ZOOM = "zoom" const val JOB_RATE = "jobRate" const val URL = "url" const val PROFESSION = "profession" const val ON_MAP_MOVE = "onMapMove" const val REGISTRATION_NAME = "registrationName" const val MARKERS = "markers" const val USER_TYPE = "userType" const val DEFAULT_ZOOM = 8f const val DEFAULT_MARKER_SIZE = 100 } var googleMap: GoogleMap? = null; private lateinit var mapView: MapView override fun getName() = REACT_NAME private lateinit var drawingManager: MarkerDrawingManager; private var markers: ReadableArray? = null; private var userType: String? = null; private val viewsToAdd = ArrayList() private var initialRegion = CameraPosition(LatLng(40.7306, -73.935), DEFAULT_ZOOM, 0f, 0f) // New York by default private var shouldAnimateToInitial = false; override fun createViewInstance(reactContext: ThemedReactContext?): MapView { val map by MapDelegate(reactContext, this) mapView = map drawingManager = MarkerDrawingManager(reactContext, map) return mapView } @ReactProp(name = MARKERS) fun setMapMarkers(mapView: MapView, markersJs: ReadableArray) { markers = markersJs mapView.getMapAsync(this) } @ReactProp(name = USER_TYPE) fun setUserType(mapView: MapView, inputType: String) { userType = inputType; shouldAnimateToInitial = true getMapOrDoAction { googleMap?.animateCamera(CameraUpdateFactory.newCameraPosition(initialRegion)) } } @ReactProp(name = "initialRegion") fun setInitialRegion(mapView: MapView, inputRegion: ReadableMap) { initialRegion = CameraPosition(LatLng(inputRegion.getDouble(LATITUDE), inputRegion.getDouble(LONGITUDE)), inputRegion.getDouble("zoom").toFloat(), 0f, 0f) getMapOrDoAction { googleMap?.animateCamera(CameraUpdateFactory.newCameraPosition(initialRegion)) } } override fun onMapReady(map: GoogleMap) { googleMap = map googleMap?.clear() if (shouldAnimateToInitial) { googleMap?.animateCamera(CameraUpdateFactory.newCameraPosition(initialRegion)) shouldAnimateToInitial = false } googleMap?.setOnCameraMoveListener { sendMapMovement() } if (!viewsToAdd.isEmpty() && getChildCount(mapView) != 0) { for (view in viewsToAdd) { val marker = view as MarkerView val latLng = LatLng(marker.coordinates.latitude, marker.coordinates.longitude) googleMap?.addMarker(MarkerOptions().position(latLng) .icon(BitmapDescriptorFactory.fromBitmap(loadBitmapFromView(view)))) } } } override fun getExportedCustomDirectEventTypeConstants(): MutableMap { val map: MutableMap = MapBuilder.of( ON_MAP_MOVE, MapBuilder.of(REGISTRATION_NAME, ON_MAP_MOVE) ); return map } fun sendMapMovement() { val event = Arguments.createMap() val cameraPosition = googleMap?.cameraPosition val latLng = cameraPosition?.target event.putDouble(LATITUDE, latLng?.latitude ?: 0.0) event.putDouble(LONGITUDE, latLng?.longitude ?: 0.0) event.putDouble(ZOOM, cameraPosition?.zoom?.toDouble() ?: 0.0) val reactContext = mapView.context as ThemedReactContext; pushEvent(reactContext, mapView, ON_MAP_MOVE, event) } fun pushEvent(context: ThemedReactContext, view: View, name: String, data: WritableMap) { context.getJSModule(RCTEventEmitter::class.java) .receiveEvent(view.id, name, data) } override fun addView(parent: MapView?, child: View?, index: Int) { super.addView(parent, child, index) viewsToAdd.add(child) } fun loadBitmapFromView(v: View): Bitmap? { val width = if (v.width == 0) 100 else v.width val height = if (v.height == 0) 100 else v.height val measuredWidth = View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY) val measuredHeight = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY) val b = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888) val c = Canvas(b) v.draw(c) v.measure(measuredWidth, measuredHeight) v.layout(0, 0, width, height) v.isDrawingCacheEnabled = true; v.buildDrawingCache(); return v.drawingCache } fun addMarkers() { googleMap?.clear() var i = 0 while (i < markers?.size() ?: 0) { val marker = markers?.getMap(i) marker?.let { val latLng = LatLng(marker.getDouble(LATITUDE), marker.getDouble(LONGITUDE)) googleMap?.addMarker(MarkerOptions().position(latLng) .icon(BitmapDescriptorFactory.fromBitmap( if (userType == "Worker") drawingManager.drawJobMarker(marker.getString(URL), marker.getString(JOB_RATE), marker.getString(PROFESSION), false) else drawingManager.drawWorkerMarker(marker.getString(URL), marker.getString(JOB_RATE), marker.getString(PROFESSION), false)))) i++ } } } fun getMapOrDoAction(action: () -> Unit) { if (googleMap == null) { mapView.getMapAsync(this) } else { action.invoke() } } }