Skip to content

Instantly share code, notes, and snippets.

@zhenguet
Last active September 26, 2023 10:32
Show Gist options
  • Save zhenguet/fcd566e31af4eda4a2e7ddb161306e2d to your computer and use it in GitHub Desktop.
Save zhenguet/fcd566e31af4eda4a2e7ddb161306e2d to your computer and use it in GitHub Desktop.
add isMarkerWithinScreen to react-native-maps@1.7.1
package com.rnmaps.maps;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Point;
import android.location.Address;
import android.location.Geocoder;
import android.net.Uri;
import android.util.Base64;
import android.util.DisplayMetrics;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.bridge.WritableNativeMap;
import com.facebook.react.module.annotations.ReactModule;
import com.facebook.react.uimanager.NativeViewHierarchyManager;
import com.facebook.react.uimanager.UIBlock;
import com.facebook.react.uimanager.UIManagerModule;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.MapsInitializer;
import com.google.android.gms.maps.OnMapsSdkInitializedCallback;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.LatLngBounds;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ReactModule(name = MapModule.NAME)
public class MapModule extends ReactContextBaseJavaModule {
public static final String NAME = "AirMapModule";
private static final String SNAPSHOT_RESULT_FILE = "file";
private static final String SNAPSHOT_RESULT_BASE64 = "base64";
private static final String SNAPSHOT_FORMAT_PNG = "png";
private static final String SNAPSHOT_FORMAT_JPG = "jpg";
public MapModule(ReactApplicationContext reactContext) {
super(reactContext);
}
@Override
public String getName() {
return NAME;
}
@Override
public Map<String, Object> getConstants() {
final Map<String, Object> constants = new HashMap<>();
constants.put(
"legalNotice",
"This license information is displayed in Settings > Google > Open Source on any device running Google Play services."
);
return constants;
}
public Activity getActivity() {
return getCurrentActivity();
}
public static void closeQuietly(Closeable closeable) {
if (closeable == null) return;
try {
closeable.close();
} catch (IOException ignored) {}
}
@ReactMethod
public void takeSnapshot(
final int tag,
final ReadableMap options,
final Promise promise
) {
// Parse and verity options
final ReactApplicationContext context = getReactApplicationContext();
final String format = options.hasKey("format")
? options.getString("format")
: "png";
final Bitmap.CompressFormat compressFormat = format.equals(
SNAPSHOT_FORMAT_PNG
)
? Bitmap.CompressFormat.PNG
: format.equals(SNAPSHOT_FORMAT_JPG) ? Bitmap.CompressFormat.JPEG : null;
final double quality = options.hasKey("quality")
? options.getDouble("quality")
: 1.0;
final DisplayMetrics displayMetrics = context
.getResources()
.getDisplayMetrics();
final Integer width = options.hasKey("width")
? (int) (displayMetrics.density * options.getDouble("width"))
: 0;
final Integer height = options.hasKey("height")
? (int) (displayMetrics.density * options.getDouble("height"))
: 0;
final String result = options.hasKey("result")
? options.getString("result")
: "file";
// Add UI-block so we can get a valid reference to the map-view
UIManagerModule uiManager = context.getNativeModule(UIManagerModule.class);
uiManager.addUIBlock(
new UIBlock() {
public void execute(NativeViewHierarchyManager nvhm) {
MapView view = (MapView) nvhm.resolveView(tag);
if (view == null) {
promise.reject("AirMapView not found");
return;
}
if (view.map == null) {
promise.reject("AirMapView.map is not valid");
return;
}
view.map.snapshot(
new GoogleMap.SnapshotReadyCallback() {
public void onSnapshotReady(@Nullable Bitmap snapshot) {
// Convert image to requested width/height if necessary
if (snapshot == null) {
promise.reject("Failed to generate bitmap, snapshot = null");
return;
}
if (
(width != 0) &&
(height != 0) &&
(
width != snapshot.getWidth() ||
height != snapshot.getHeight()
)
) {
snapshot =
Bitmap.createScaledBitmap(snapshot, width, height, true);
}
// Save the snapshot to disk
if (result.equals(SNAPSHOT_RESULT_FILE)) {
File tempFile;
FileOutputStream outputStream;
try {
tempFile =
File.createTempFile(
"AirMapSnapshot",
"." + format,
context.getCacheDir()
);
outputStream = new FileOutputStream(tempFile);
} catch (Exception e) {
promise.reject(e);
return;
}
snapshot.compress(
compressFormat,
(int) (100.0 * quality),
outputStream
);
closeQuietly(outputStream);
String uri = Uri.fromFile(tempFile).toString();
promise.resolve(uri);
} else if (result.equals(SNAPSHOT_RESULT_BASE64)) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
snapshot.compress(
compressFormat,
(int) (100.0 * quality),
outputStream
);
closeQuietly(outputStream);
byte[] bytes = outputStream.toByteArray();
String data = Base64.encodeToString(bytes, Base64.NO_WRAP);
promise.resolve(data);
}
}
}
);
}
}
);
}
@ReactMethod
public void isMarkerWithinScreen(
final int tag,
ReadableMap coordinate,
final Promise promise
) {
final ReactApplicationContext context = getReactApplicationContext();
final double lat = coordinate.getDouble("latitude");
final double lng = coordinate.getDouble("longitude");
final LatLng position = new LatLng(lat, lng);
UIManagerModule uiManager = context.getNativeModule(UIManagerModule.class);
uiManager.addUIBlock(
new UIBlock() {
@Override
public void execute(NativeViewHierarchyManager nvhm) {
MapView view = (MapView) nvhm.resolveView(tag);
if (view == null) {
promise.reject("AirMapView not found");
return;
}
if (view.map == null) {
promise.reject("AirMapView.map is not valid");
return;
}
LatLngBounds currentScreen = view.map
.getProjection()
.getVisibleRegion()
.latLngBounds;
boolean onScreen = currentScreen.contains(position);
WritableMap visibleJson = new WritableNativeMap();
visibleJson.putBoolean("visible", onScreen);
promise.resolve(visibleJson);
}
}
);
}
@ReactMethod
public void getCamera(final int tag, final Promise promise) {
final ReactApplicationContext context = getReactApplicationContext();
UIManagerModule uiManager = context.getNativeModule(UIManagerModule.class);
uiManager.addUIBlock(
new UIBlock() {
@Override
public void execute(NativeViewHierarchyManager nvhm) {
MapView view = (MapView) nvhm.resolveView(tag);
if (view == null) {
promise.reject("AirMapView not found");
return;
}
if (view.map == null) {
promise.reject("AirMapView.map is not valid");
return;
}
CameraPosition position = view.map.getCameraPosition();
WritableMap centerJson = new WritableNativeMap();
centerJson.putDouble("latitude", position.target.latitude);
centerJson.putDouble("longitude", position.target.longitude);
WritableMap cameraJson = new WritableNativeMap();
cameraJson.putMap("center", centerJson);
cameraJson.putDouble("heading", (double) position.bearing);
cameraJson.putDouble("zoom", (double) position.zoom);
cameraJson.putDouble("pitch", (double) position.tilt);
promise.resolve(cameraJson);
}
}
);
}
@ReactMethod
public void getAddressFromCoordinates(
final int tag,
final ReadableMap coordinate,
final Promise promise
) {
final ReactApplicationContext context = getReactApplicationContext();
UIManagerModule uiManager = context.getNativeModule(UIManagerModule.class);
uiManager.addUIBlock(
new UIBlock() {
@Override
public void execute(NativeViewHierarchyManager nvhm) {
MapView view = (MapView) nvhm.resolveView(tag);
if (view == null) {
promise.reject("AirMapView not found");
return;
}
if (view.map == null) {
promise.reject("AirMapView.map is not valid");
return;
}
if (
coordinate == null ||
!coordinate.hasKey("latitude") ||
!coordinate.hasKey("longitude")
) {
promise.reject("Invalid coordinate format");
return;
}
Geocoder geocoder = new Geocoder(context);
try {
List<Address> list = geocoder.getFromLocation(
coordinate.getDouble("latitude"),
coordinate.getDouble("longitude"),
1
);
if (list.isEmpty()) {
promise.reject("Can not get address location");
return;
}
Address address = list.get(0);
WritableMap addressJson = new WritableNativeMap();
addressJson.putString("name", address.getFeatureName());
addressJson.putString("locality", address.getLocality());
addressJson.putString("thoroughfare", address.getThoroughfare());
addressJson.putString(
"subThoroughfare",
address.getSubThoroughfare()
);
addressJson.putString("subLocality", address.getSubLocality());
addressJson.putString("administrativeArea", address.getAdminArea());
addressJson.putString(
"subAdministrativeArea",
address.getSubAdminArea()
);
addressJson.putString("postalCode", address.getPostalCode());
addressJson.putString("countryCode", address.getCountryCode());
addressJson.putString("country", address.getCountryName());
promise.resolve(addressJson);
} catch (IOException e) {
promise.reject("Can not get address location");
}
}
}
);
}
@ReactMethod
public void pointForCoordinate(
final int tag,
ReadableMap coordinate,
final Promise promise
) {
final ReactApplicationContext context = getReactApplicationContext();
final double density = (double) context
.getResources()
.getDisplayMetrics()
.density;
final LatLng coord = new LatLng(
coordinate.hasKey("latitude") ? coordinate.getDouble("latitude") : 0.0,
coordinate.hasKey("longitude") ? coordinate.getDouble("longitude") : 0.0
);
UIManagerModule uiManager = context.getNativeModule(UIManagerModule.class);
uiManager.addUIBlock(
new UIBlock() {
@Override
public void execute(NativeViewHierarchyManager nvhm) {
MapView view = (MapView) nvhm.resolveView(tag);
if (view == null) {
promise.reject("AirMapView not found");
return;
}
if (view.map == null) {
promise.reject("AirMapView.map is not valid");
return;
}
Point pt = view.map.getProjection().toScreenLocation(coord);
WritableMap ptJson = new WritableNativeMap();
ptJson.putDouble("x", (double) pt.x / density);
ptJson.putDouble("y", (double) pt.y / density);
promise.resolve(ptJson);
}
}
);
}
@ReactMethod
public void coordinateForPoint(
final int tag,
ReadableMap point,
final Promise promise
) {
final ReactApplicationContext context = getReactApplicationContext();
final double density = (double) context
.getResources()
.getDisplayMetrics()
.density;
final Point pt = new Point(
point.hasKey("x") ? (int) (point.getDouble("x") * density) : 0,
point.hasKey("y") ? (int) (point.getDouble("y") * density) : 0
);
UIManagerModule uiManager = context.getNativeModule(UIManagerModule.class);
uiManager.addUIBlock(
new UIBlock() {
@Override
public void execute(NativeViewHierarchyManager nvhm) {
MapView view = (MapView) nvhm.resolveView(tag);
if (view == null) {
promise.reject("AirMapView not found");
return;
}
if (view.map == null) {
promise.reject("AirMapView.map is not valid");
return;
}
LatLng coord = view.map.getProjection().fromScreenLocation(pt);
WritableMap coordJson = new WritableNativeMap();
coordJson.putDouble("latitude", coord.latitude);
coordJson.putDouble("longitude", coord.longitude);
promise.resolve(coordJson);
}
}
);
}
@ReactMethod
public void getMapBoundaries(final int tag, final Promise promise) {
final ReactApplicationContext context = getReactApplicationContext();
UIManagerModule uiManager = context.getNativeModule(UIManagerModule.class);
uiManager.addUIBlock(
new UIBlock() {
@Override
public void execute(NativeViewHierarchyManager nvhm) {
MapView view = (MapView) nvhm.resolveView(tag);
if (view == null) {
promise.reject("AirMapView not found");
return;
}
if (view.map == null) {
promise.reject("AirMapView.map is not valid");
return;
}
double[][] boundaries = view.getMapBoundaries();
WritableMap coordinates = new WritableNativeMap();
WritableMap northEastHash = new WritableNativeMap();
WritableMap southWestHash = new WritableNativeMap();
northEastHash.putDouble("longitude", boundaries[0][0]);
northEastHash.putDouble("latitude", boundaries[0][1]);
southWestHash.putDouble("longitude", boundaries[1][0]);
southWestHash.putDouble("latitude", boundaries[1][1]);
coordinates.putMap("northEast", northEastHash);
coordinates.putMap("southWest", southWestHash);
promise.resolve(coordinates);
}
}
);
}
@ReactMethod
public void enableLatestRenderer(final Promise promise) {
final ReactApplicationContext context = getReactApplicationContext();
UIManagerModule uiManager = context.getNativeModule(UIManagerModule.class);
uiManager.addUIBlock(
new UIBlock() {
@Override
public void execute(NativeViewHierarchyManager nvhm) {
MapsInitializer.initialize(
context,
MapsInitializer.Renderer.LATEST,
new OnMapsSdkInitializedCallback() {
@Override
public void onMapsSdkInitialized(
@NonNull MapsInitializer.Renderer renderer
) {
Log.d("AirMapRenderer", renderer.toString());
promise.resolve(renderer.toString());
}
}
);
}
}
);
}
}
//
// AIRGoogleMapManager.m
// AirMaps
//
// Created by Gil Birman on 9/1/16.
//
#ifdef HAVE_GOOGLE_MAPS
#import "AIRGoogleMapManager.h"
#import <React/RCTViewManager.h>
#import <React/RCTBridge.h>
#import <React/RCTUIManager.h>
#import <React/RCTConvert+CoreLocation.h>
#import <React/RCTEventDispatcher.h>
#import <React/RCTViewManager.h>
#import <React/RCTConvert.h>
#import <React/UIView+React.h>
#import "RCTConvert+GMSMapViewType.h"
#import "AIRGoogleMap.h"
#import "AIRMapMarker.h"
#import "AIRMapPolyline.h"
#import "AIRMapPolygon.h"
#import "AIRMapCircle.h"
#import "SMCalloutView.h"
#import "AIRGoogleMapMarker.h"
#import "RCTConvert+AirMap.h"
#import <MapKit/MapKit.h>
#import <QuartzCore/QuartzCore.h>
static NSString *const RCTMapViewKey = @"MapView";
@interface AIRGoogleMapManager() <GMSMapViewDelegate>
{
BOOL didCallOnMapReady;
}
@end
@implementation AIRGoogleMapManager
RCT_EXPORT_MODULE()
- (UIView *)view
{
[GMSServices setMetalRendererEnabled:YES];
AIRGoogleMap *map = [AIRGoogleMap new];
map.bridge = self.bridge;
map.delegate = self;
map.isAccessibilityElement = NO;
map.accessibilityElementsHidden = NO;
map.settings.consumesGesturesInView = NO;
UIPanGestureRecognizer *drag = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleMapDrag:)];
[drag setMinimumNumberOfTouches:1];
[drag setMaximumNumberOfTouches:1];
[map addGestureRecognizer:drag];
UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handleMapDrag:)];
[map addGestureRecognizer:pinch];
return map;
}
RCT_EXPORT_VIEW_PROPERTY(isAccessibilityElement, BOOL)
RCT_REMAP_VIEW_PROPERTY(testID, accessibilityIdentifier, NSString)
RCT_EXPORT_VIEW_PROPERTY(initialCamera, GMSCameraPosition)
RCT_REMAP_VIEW_PROPERTY(camera, cameraProp, GMSCameraPosition)
RCT_EXPORT_VIEW_PROPERTY(initialRegion, MKCoordinateRegion)
RCT_EXPORT_VIEW_PROPERTY(region, MKCoordinateRegion)
RCT_EXPORT_VIEW_PROPERTY(showsBuildings, BOOL)
RCT_EXPORT_VIEW_PROPERTY(showsCompass, BOOL)
//RCT_EXPORT_VIEW_PROPERTY(showsScale, BOOL) // Not supported by GoogleMaps
RCT_EXPORT_VIEW_PROPERTY(showsTraffic, BOOL)
RCT_EXPORT_VIEW_PROPERTY(zoomEnabled, BOOL)
RCT_EXPORT_VIEW_PROPERTY(rotateEnabled, BOOL)
RCT_EXPORT_VIEW_PROPERTY(scrollEnabled, BOOL)
RCT_EXPORT_VIEW_PROPERTY(scrollDuringRotateOrZoomEnabled, BOOL)
RCT_EXPORT_VIEW_PROPERTY(pitchEnabled, BOOL)
RCT_EXPORT_VIEW_PROPERTY(zoomTapEnabled, BOOL)
RCT_EXPORT_VIEW_PROPERTY(showsUserLocation, BOOL)
RCT_EXPORT_VIEW_PROPERTY(showsMyLocationButton, BOOL)
RCT_EXPORT_VIEW_PROPERTY(showsIndoors, BOOL)
RCT_EXPORT_VIEW_PROPERTY(showsIndoorLevelPicker, BOOL)
RCT_EXPORT_VIEW_PROPERTY(customMapStyleString, NSString)
RCT_EXPORT_VIEW_PROPERTY(mapPadding, UIEdgeInsets)
RCT_REMAP_VIEW_PROPERTY(paddingAdjustmentBehavior, paddingAdjustmentBehaviorString, NSString)
RCT_EXPORT_VIEW_PROPERTY(onMapReady, RCTBubblingEventBlock)
RCT_EXPORT_VIEW_PROPERTY(onMapLoaded, RCTBubblingEventBlock)
RCT_EXPORT_VIEW_PROPERTY(onKmlReady, RCTBubblingEventBlock)
RCT_EXPORT_VIEW_PROPERTY(onPress, RCTBubblingEventBlock)
RCT_EXPORT_VIEW_PROPERTY(onLongPress, RCTBubblingEventBlock)
RCT_EXPORT_VIEW_PROPERTY(onPanDrag, RCTBubblingEventBlock)
RCT_EXPORT_VIEW_PROPERTY(onUserLocationChange, RCTBubblingEventBlock)
RCT_EXPORT_VIEW_PROPERTY(onChange, RCTBubblingEventBlock)
RCT_EXPORT_VIEW_PROPERTY(onMarkerPress, RCTDirectEventBlock)
RCT_EXPORT_VIEW_PROPERTY(onRegionChange, RCTDirectEventBlock)
RCT_EXPORT_VIEW_PROPERTY(onRegionChangeComplete, RCTDirectEventBlock)
RCT_EXPORT_VIEW_PROPERTY(onPoiClick, RCTDirectEventBlock)
RCT_EXPORT_VIEW_PROPERTY(onIndoorLevelActivated, RCTDirectEventBlock)
RCT_EXPORT_VIEW_PROPERTY(onIndoorBuildingFocused, RCTDirectEventBlock)
RCT_EXPORT_VIEW_PROPERTY(mapType, GMSMapViewType)
RCT_EXPORT_VIEW_PROPERTY(minZoomLevel, CGFloat)
RCT_EXPORT_VIEW_PROPERTY(maxZoomLevel, CGFloat)
RCT_EXPORT_VIEW_PROPERTY(kmlSrc, NSString)
RCT_EXPORT_METHOD(isMarkerWithinScreen:(nonnull NSNumber *)reactTag
position:(CLLocationCoordinate2D)position
resolver: (RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
{
[self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
id view = viewRegistry[reactTag];
if (![view isKindOfClass:[AIRGoogleMap class]]) {
RCTLogError(@"Invalid view returned from registry, expecting AIRMap, got: %@", view);
} else {
AIRGoogleMap *mapView = (AIRGoogleMap *)view;
GMSVisibleRegion region = [mapView.projection visibleRegion];
GMSCoordinateBounds *bounds = [[GMSCoordinateBounds alloc] initWithRegion:region];
resolve(@{@"visible": @([bounds containsCoordinate:position])});
}
}];
}
RCT_EXPORT_METHOD(getCamera:(nonnull NSNumber *)reactTag
resolver: (RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
{
[self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
id view = viewRegistry[reactTag];
if (![view isKindOfClass:[AIRGoogleMap class]]) {
reject(@"Invalid argument", [NSString stringWithFormat:@"Invalid view returned from registry, expecting AIRGoogleMap, got: %@", view], NULL);
} else {
AIRGoogleMap *mapView = (AIRGoogleMap *)view;
resolve(@{
@"center": @{
@"latitude": @(mapView.camera.target.latitude),
@"longitude": @(mapView.camera.target.longitude),
},
@"pitch": @(mapView.camera.viewingAngle),
@"heading": @(mapView.camera.bearing),
@"zoom": @(mapView.camera.zoom),
});
}
}];
}
RCT_EXPORT_METHOD(setCamera:(nonnull NSNumber *)reactTag
camera:(id)json)
{
[self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
id view = viewRegistry[reactTag];
if (![view isKindOfClass:[AIRGoogleMap class]]) {
RCTLogError(@"Invalid view returned from registry, expecting AIRGoogleMap, got: %@", view);
} else {
AIRGoogleMap *mapView = (AIRGoogleMap *)view;
GMSCameraPosition *camera = [RCTConvert GMSCameraPositionWithDefaults:json existingCamera:[mapView camera]];
[mapView setCamera:camera];
}
}];
}
RCT_EXPORT_METHOD(animateCamera:(nonnull NSNumber *)reactTag
withCamera:(id)json
withDuration:(CGFloat)duration)
{
[self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
id view = viewRegistry[reactTag];
if (![view isKindOfClass:[AIRGoogleMap class]]) {
RCTLogError(@"Invalid view returned from registry, expecting AIRGoogleMap, got: %@", view);
} else {
[CATransaction begin];
[CATransaction setAnimationDuration:duration/1000];
AIRGoogleMap *mapView = (AIRGoogleMap *)view;
GMSCameraPosition *camera = [RCTConvert GMSCameraPositionWithDefaults:json existingCamera:[mapView camera]];
[mapView animateToCameraPosition:camera];
[CATransaction commit];
}
}];
}
RCT_EXPORT_METHOD(animateToRegion:(nonnull NSNumber *)reactTag
withRegion:(MKCoordinateRegion)region
withDuration:(CGFloat)duration)
{
[self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
id view = viewRegistry[reactTag];
if (![view isKindOfClass:[AIRGoogleMap class]]) {
RCTLogError(@"Invalid view returned from registry, expecting AIRGoogleMap, got: %@", view);
} else {
// Core Animation must be used to control the animation's duration
// See http://stackoverflow.com/a/15663039/171744
[CATransaction begin];
[CATransaction setAnimationDuration:duration/1000];
AIRGoogleMap *mapView = (AIRGoogleMap *)view;
GMSCameraPosition *camera = [AIRGoogleMap makeGMSCameraPositionFromMap:mapView andMKCoordinateRegion:region];
[mapView animateToCameraPosition:camera];
[CATransaction commit];
}
}];
}
RCT_EXPORT_METHOD(fitToElements:(nonnull NSNumber *)reactTag
edgePadding:(nonnull NSDictionary *)edgePadding
animated:(BOOL)animated)
{
[self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
id view = viewRegistry[reactTag];
if (![view isKindOfClass:[AIRGoogleMap class]]) {
RCTLogError(@"Invalid view returned from registry, expecting AIRGoogleMap, got: %@", view);
} else {
AIRGoogleMap *mapView = (AIRGoogleMap *)view;
CLLocationCoordinate2D myLocation = ((AIRGoogleMapMarker *)(mapView.markers.firstObject)).realMarker.position;
GMSCoordinateBounds *bounds = [[GMSCoordinateBounds alloc] initWithCoordinate:myLocation coordinate:myLocation];
for (AIRGoogleMapMarker *marker in mapView.markers)
bounds = [bounds includingCoordinate:marker.realMarker.position];
GMSCameraUpdate* cameraUpdate;
if ([edgePadding count] != 0) {
// Set Map viewport
CGFloat top = [RCTConvert CGFloat:edgePadding[@"top"]];
CGFloat right = [RCTConvert CGFloat:edgePadding[@"right"]];
CGFloat bottom = [RCTConvert CGFloat:edgePadding[@"bottom"]];
CGFloat left = [RCTConvert CGFloat:edgePadding[@"left"]];
cameraUpdate = [GMSCameraUpdate fitBounds:bounds withEdgeInsets:UIEdgeInsetsMake(top, left, bottom, right)];
} else {
cameraUpdate = [GMSCameraUpdate fitBounds:bounds withPadding:55.0f];
}
if (animated) {
[mapView animateWithCameraUpdate: cameraUpdate];
} else {
[mapView moveCamera: cameraUpdate];
}
}
}];
}
RCT_EXPORT_METHOD(fitToSuppliedMarkers:(nonnull NSNumber *)reactTag
markers:(nonnull NSArray *)markers
edgePadding:(nonnull NSDictionary *)edgePadding
animated:(BOOL)animated)
{
[self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
id view = viewRegistry[reactTag];
if (![view isKindOfClass:[AIRGoogleMap class]]) {
RCTLogError(@"Invalid view returned from registry, expecting AIRGoogleMap, got: %@", view);
} else {
AIRGoogleMap *mapView = (AIRGoogleMap *)view;
NSPredicate *filterMarkers = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
AIRGoogleMapMarker *marker = (AIRGoogleMapMarker *)evaluatedObject;
return [marker isKindOfClass:[AIRGoogleMapMarker class]] && [markers containsObject:marker.identifier];
}];
NSArray *filteredMarkers = [mapView.markers filteredArrayUsingPredicate:filterMarkers];
CLLocationCoordinate2D myLocation = ((AIRGoogleMapMarker *)(filteredMarkers.firstObject)).realMarker.position;
GMSCoordinateBounds *bounds = [[GMSCoordinateBounds alloc] initWithCoordinate:myLocation coordinate:myLocation];
for (AIRGoogleMapMarker *marker in filteredMarkers)
bounds = [bounds includingCoordinate:marker.realMarker.position];
// Set Map viewport
CGFloat top = [RCTConvert CGFloat:edgePadding[@"top"]];
CGFloat right = [RCTConvert CGFloat:edgePadding[@"right"]];
CGFloat bottom = [RCTConvert CGFloat:edgePadding[@"bottom"]];
CGFloat left = [RCTConvert CGFloat:edgePadding[@"left"]];
GMSCameraUpdate* cameraUpdate = [GMSCameraUpdate fitBounds:bounds withEdgeInsets:UIEdgeInsetsMake(top, left, bottom, right)];
if (animated) {
[mapView animateWithCameraUpdate:cameraUpdate
];
} else {
[mapView moveCamera: cameraUpdate];
}
}
}];
}
RCT_EXPORT_METHOD(fitToCoordinates:(nonnull NSNumber *)reactTag
coordinates:(nonnull NSArray<AIRMapCoordinate *> *)coordinates
edgePadding:(nonnull NSDictionary *)edgePadding
animated:(BOOL)animated)
{
[self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
id view = viewRegistry[reactTag];
if (![view isKindOfClass:[AIRGoogleMap class]]) {
RCTLogError(@"Invalid view returned from registry, expecting AIRGoogleMap, got: %@", view);
} else {
AIRGoogleMap *mapView = (AIRGoogleMap *)view;
CLLocationCoordinate2D myLocation = coordinates.firstObject.coordinate;
GMSCoordinateBounds *bounds = [[GMSCoordinateBounds alloc] initWithCoordinate:myLocation coordinate:myLocation];
for (AIRMapCoordinate *coordinate in coordinates)
bounds = [bounds includingCoordinate:coordinate.coordinate];
// Set Map viewport
CGFloat top = [RCTConvert CGFloat:edgePadding[@"top"]];
CGFloat right = [RCTConvert CGFloat:edgePadding[@"right"]];
CGFloat bottom = [RCTConvert CGFloat:edgePadding[@"bottom"]];
CGFloat left = [RCTConvert CGFloat:edgePadding[@"left"]];
GMSCameraUpdate *cameraUpdate = [GMSCameraUpdate fitBounds:bounds withEdgeInsets:UIEdgeInsetsMake(top, left, bottom, right)];
if (animated) {
[mapView animateWithCameraUpdate: cameraUpdate];
} else {
[mapView moveCamera: cameraUpdate];
}
}
}];
}
RCT_EXPORT_METHOD(takeSnapshot:(nonnull NSNumber *)reactTag
withWidth:(nonnull NSNumber *)width
withHeight:(nonnull NSNumber *)height
withRegion:(MKCoordinateRegion)region
format:(nonnull NSString *)format
quality:(nonnull NSNumber *)quality
result:(nonnull NSString *)result
withCallback:(RCTResponseSenderBlock)callback)
{
NSTimeInterval timeStamp = [[NSDate date] timeIntervalSince1970];
NSString *pathComponent = [NSString stringWithFormat:@"Documents/snapshot-%.20lf.%@", timeStamp, format];
NSString *filePath = [NSHomeDirectory() stringByAppendingPathComponent: pathComponent];
[self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
id view = viewRegistry[reactTag];
if (![view isKindOfClass:[AIRGoogleMap class]]) {
RCTLogError(@"Invalid view returned from registry, expecting AIRMap, got: %@", view);
} else {
AIRGoogleMap *mapView = (AIRGoogleMap *)view;
// TODO: currently we are ignoring width, height, region
UIGraphicsBeginImageContextWithOptions(mapView.frame.size, YES, 0.0f);
[mapView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
NSData *data;
if ([format isEqualToString:@"png"]) {
data = UIImagePNGRepresentation(image);
}
else if([format isEqualToString:@"jpg"]) {
data = UIImageJPEGRepresentation(image, quality.floatValue);
}
if ([result isEqualToString:@"file"]) {
[data writeToFile:filePath atomically:YES];
callback(@[[NSNull null], filePath]);
}
else if ([result isEqualToString:@"base64"]) {
callback(@[[NSNull null], [data base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithCarriageReturn]]);
}
}
UIGraphicsEndImageContext();
}];
}
RCT_EXPORT_METHOD(pointForCoordinate:(nonnull NSNumber *)reactTag
coordinate:(NSDictionary *)coordinate
resolver: (RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
{
CLLocationCoordinate2D coord =
CLLocationCoordinate2DMake(
[coordinate[@"latitude"] doubleValue],
[coordinate[@"longitude"] doubleValue]
);
[self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
id view = viewRegistry[reactTag];
if (![view isKindOfClass:[AIRGoogleMap class]]) {
RCTLogError(@"Invalid view returned from registry, expecting AIRMap, got: %@", view);
} else {
AIRGoogleMap *mapView = (AIRGoogleMap *)view;
CGPoint touchPoint = [mapView.projection pointForCoordinate:coord];
resolve(@{
@"x": @(touchPoint.x),
@"y": @(touchPoint.y),
});
}
}];
}
RCT_EXPORT_METHOD(coordinateForPoint:(nonnull NSNumber *)reactTag
point:(NSDictionary *)point
resolver: (RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
{
CGPoint pt = CGPointMake(
[point[@"x"] doubleValue],
[point[@"y"] doubleValue]
);
[self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
id view = viewRegistry[reactTag];
if (![view isKindOfClass:[AIRGoogleMap class]]) {
RCTLogError(@"Invalid view returned from registry, expecting AIRMap, got: %@", view);
} else {
AIRGoogleMap *mapView = (AIRGoogleMap *)view;
CLLocationCoordinate2D coordinate = [mapView.projection coordinateForPoint:pt];
resolve(@{
@"latitude": @(coordinate.latitude),
@"longitude": @(coordinate.longitude),
});
}
}];
}
RCT_EXPORT_METHOD(getMarkersFrames:(nonnull NSNumber *)reactTag
onlyVisible:(BOOL)onlyVisible
resolver: (RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
{
[self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
id view = viewRegistry[reactTag];
if (![view isKindOfClass:[AIRGoogleMap class]]) {
RCTLogError(@"Invalid view returned from registry, expecting AIRMap, got: %@", view);
} else {
AIRGoogleMap *mapView = (AIRGoogleMap *)view;
resolve([mapView getMarkersFramesWithOnlyVisible:onlyVisible]);
}
}];
}
RCT_EXPORT_METHOD(getMapBoundaries:(nonnull NSNumber *)reactTag
resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
{
[self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
id view = viewRegistry[reactTag];
if (![view isKindOfClass:[AIRGoogleMap class]]) {
RCTLogError(@"Invalid view returned from registry, expecting AIRGoogleMap, got: %@", view);
} else {
NSArray *boundingBox = [view getMapBoundaries];
resolve(@{
@"northEast" : @{
@"longitude" : boundingBox[0][0],
@"latitude" : boundingBox[0][1]
},
@"southWest" : @{
@"longitude" : boundingBox[1][0],
@"latitude" : boundingBox[1][1]
}
});
}
}];
}
RCT_EXPORT_METHOD(setMapBoundaries:(nonnull NSNumber *)reactTag
northEast:(CLLocationCoordinate2D)northEast
southWest:(CLLocationCoordinate2D)southWest)
{
[self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
id view = viewRegistry[reactTag];
if (![view isKindOfClass:[AIRGoogleMap class]]) {
RCTLogError(@"Invalid view returned from registry, expecting AIRGoogleMap, got: %@", view);
} else {
AIRGoogleMap *mapView = (AIRGoogleMap *)view;
GMSCoordinateBounds *bounds = [[GMSCoordinateBounds alloc] initWithCoordinate:northEast coordinate:southWest];
mapView.cameraTargetBounds = bounds;
}
}];
}
RCT_EXPORT_METHOD(setIndoorActiveLevelIndex:(nonnull NSNumber *)reactTag
levelIndex:(NSInteger) levelIndex)
{
[self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
id view = viewRegistry[reactTag];
if (![view isKindOfClass:[AIRGoogleMap class]]) {
RCTLogError(@"Invalid view returned from registry, expecting AIRGoogleMap, got: %@", view);
} else {
AIRGoogleMap *mapView = (AIRGoogleMap *)view;
if (!mapView.indoorDisplay) {
return;
}
if ( levelIndex < [mapView.indoorDisplay.activeBuilding.levels count]) {
mapView.indoorDisplay.activeLevel = mapView.indoorDisplay.activeBuilding.levels[levelIndex];
}
}
}];
}
+ (BOOL)requiresMainQueueSetup {
return YES;
}
- (NSDictionary *)constantsToExport {
return @{ @"legalNotice": [GMSServices openSourceLicenseInfo] };
}
- (void)mapView:(GMSMapView *)mapView willMove:(BOOL)gesture{
self.isGesture = gesture;
}
- (void)mapViewDidStartTileRendering:(GMSMapView *)mapView {
AIRGoogleMap *googleMapView = (AIRGoogleMap *)mapView;
[googleMapView didPrepareMap];
}
- (void)mapViewDidFinishTileRendering:(GMSMapView *)mapView {
AIRGoogleMap *googleMapView = (AIRGoogleMap *)mapView;
[googleMapView mapViewDidFinishTileRendering];
}
- (BOOL)mapView:(GMSMapView *)mapView didTapMarker:(GMSMarker *)marker {
AIRGoogleMap *googleMapView = (AIRGoogleMap *)mapView;
return [googleMapView didTapMarker:marker];
}
- (void)mapView:(GMSMapView *)mapView didTapOverlay:(GMSPolygon *)polygon {
AIRGoogleMap *googleMapView = (AIRGoogleMap *)mapView;
[googleMapView didTapPolygon:polygon];
}
- (void)mapView:(GMSMapView *)mapView didTapAtCoordinate:(CLLocationCoordinate2D)coordinate {
AIRGoogleMap *googleMapView = (AIRGoogleMap *)mapView;
[googleMapView didTapAtCoordinate:coordinate];
}
- (void)mapView:(GMSMapView *)mapView didLongPressAtCoordinate:(CLLocationCoordinate2D)coordinate {
AIRGoogleMap *googleMapView = (AIRGoogleMap *)mapView;
[googleMapView didLongPressAtCoordinate:coordinate];
}
- (void)mapView:(GMSMapView *)mapView didChangeCameraPosition:(GMSCameraPosition *)position {
AIRGoogleMap *googleMapView = (AIRGoogleMap *)mapView;
[googleMapView didChangeCameraPosition:position isGesture:self.isGesture];
}
- (void)mapView:(GMSMapView *)mapView idleAtCameraPosition:(GMSCameraPosition *)position {
AIRGoogleMap *googleMapView = (AIRGoogleMap *)mapView;
[googleMapView idleAtCameraPosition:position isGesture:self.isGesture];
}
- (UIView *)mapView:(GMSMapView *)mapView markerInfoWindow:(GMSMarker *)marker {
AIRGMSMarker *aMarker = (AIRGMSMarker *)marker;
return [aMarker.fakeMarker markerInfoWindow];}
- (UIView *)mapView:(GMSMapView *)mapView markerInfoContents:(GMSMarker *)marker {
AIRGMSMarker *aMarker = (AIRGMSMarker *)marker;
return [aMarker.fakeMarker markerInfoContents];
}
- (void)mapView:(GMSMapView *)mapView didTapInfoWindowOfMarker:(GMSMarker *)marker {
AIRGMSMarker *aMarker = (AIRGMSMarker *)marker;
[aMarker.fakeMarker didTapInfoWindowOfMarker:aMarker];
}
- (void)mapView:(GMSMapView *)mapView didBeginDraggingMarker:(GMSMarker *)marker {
AIRGMSMarker *aMarker = (AIRGMSMarker *)marker;
[aMarker.fakeMarker didBeginDraggingMarker:aMarker];
}
- (void)mapView:(GMSMapView *)mapView didEndDraggingMarker:(GMSMarker *)marker {
AIRGMSMarker *aMarker = (AIRGMSMarker *)marker;
[aMarker.fakeMarker didEndDraggingMarker:aMarker];
}
- (void)mapView:(GMSMapView *)mapView didDragMarker:(GMSMarker *)marker {
AIRGMSMarker *aMarker = (AIRGMSMarker *)marker;
[aMarker.fakeMarker didDragMarker:aMarker];
}
- (void)mapView:(GMSMapView *)mapView
didTapPOIWithPlaceID:(NSString *)placeID
name:(NSString *)name
location:(CLLocationCoordinate2D)location {
AIRGoogleMap *googleMapView = (AIRGoogleMap *)mapView;
[googleMapView didTapPOIWithPlaceID:placeID name:name location:location];
}
#pragma mark Gesture Recognizer Handlers
- (void)handleMapDrag:(UIPanGestureRecognizer*)recognizer {
AIRGoogleMap *map = (AIRGoogleMap *)recognizer.view;
if (!map.onPanDrag) return;
CGPoint touchPoint = [recognizer locationInView:map];
CLLocationCoordinate2D coord = [map.projection coordinateForPoint:touchPoint];
map.onPanDrag(@{
@"coordinate": @{
@"latitude": @(coord.latitude),
@"longitude": @(coord.longitude),
},
@"position": @{
@"x": @(touchPoint.x),
@"y": @(touchPoint.y),
},
});
}
@end
#endif
import * as React from "react";
import {
Animated as RNAnimated,
Animated,
NativeSyntheticEvent,
ViewProps,
} from "react-native";
import {
CalloutPressEvent,
ClickEvent,
Frame,
LatLng,
MarkerDeselectEvent,
MarkerDragEvent,
MarkerDragStartEndEvent,
MarkerPressEvent,
MarkerSelectEvent,
Point,
Provider,
Region,
} from "./sharedTypes";
import {
Address,
BoundingBox,
Camera,
ChangeEvent,
Details,
EdgePadding,
FitToOptions,
IndoorBuildingEvent,
IndoorLevelActivatedEvent,
KmlMapEvent,
LongPressEvent,
MapPressEvent,
MapStyleElement,
MapType,
MapTypes,
PanDragEvent,
PoiClickEvent,
SnapshotOptions,
UserLocationChangeEvent,
} from "./MapView.types";
import { Modify } from "./sharedTypesInternal";
import { MapViewNativeComponentType } from "./MapViewNativeComponent";
export declare const MAP_TYPES: MapTypes;
export type MapViewProps = ViewProps & {
/**
* If `true` map will be cached and displayed as an image instead of being interactable, for performance usage.
*
* @default false
* @platform iOS: Apple maps only
* @platform Android: Supported
*/
cacheEnabled?: boolean;
/**
* The camera view the map should display.
*
* Use the camera system, instead of the region system, if you need control over
* the pitch or heading. Using this will ignore the `region` property.
* @platform iOS: Supported
* @platform Android: Supported
*/
camera?: Camera;
/**
* If set, changes the position of the compass.
*
* @platform iOS: Apple Maps only
* @platform Android: Not supported
*/
compassOffset?: Point;
/**
* Adds custom styling to the map component.
* See [README](https://github.com/react-native-maps/react-native-maps#customizing-the-map-style) for more information.
*
* @platform iOS: Google Maps only
* @platform Android: Supported
*/
customMapStyle?: MapStyleElement[];
/**
* If `true` the map will focus on the user's location.
* This only works if `showsUserLocation` is true and the user has shared their location.
*
* @default false
* @platform iOS: Apple Maps only
* @platform Android: Not supported
*/
followsUserLocation?: boolean;
/**
* The initial camera view the map should use. Use this prop instead of `camera`
* only if you don't want to control the camera of the map besides the initial view.
*
* Use the camera system, instead of the region system, if you need control over
* the pitch or heading.
*
* Changing this prop after the component has mounted will not result in a camera change.
*
* This is similar to the `initialValue` prop of a text input.
*
* @platform iOS: Supported
* @platform Android: Supported
*/
initialCamera?: Camera;
/**
* The initial region to be displayed by the map. Use this prop instead of `region`
* only if you don't want to control the viewport of the map besides the initial region.
*
* Changing this prop after the component has mounted will not result in a region change.
*
* This is similar to the `initialValue` prop of a text input.
*
* @platform iOS: Supported
* @platform Android: Supported
*/
initialRegion?: Region;
/**
* The URL for KML file.
*
* @platform iOS: Google Maps only
* @platform Android: Supported
*/
kmlSrc?: string;
/**
* If set, changes the position of the "Legal" label link in Apple maps.
*
* @platform iOS: Apple Maps only
* @platform Android: Not supported
*/
legalLabelInsets?: EdgePadding;
/**
* Enables lite mode on Android
*
* @platform iOS: Not supported
* @platform Android: Supported
*/
liteMode?: boolean;
/**
* Sets loading background color.
*
* @default `#FFFFFF`
* @platform iOS: Apple Maps only
* @platform Android: Supported
*/
loadingBackgroundColor?: string;
/**
* If `true` a loading indicator will show while the map is loading.
*
* @default false
* @platform iOS: Apple Maps only
* @platform Android: Supported
*/
loadingEnabled?: boolean;
/**
* Sets loading indicator color.
*
* @default `#606060`
* @platform iOS: Apple Maps only
* @platform Android: Supported
*/
loadingIndicatorColor?: string;
/**
* Adds custom padding to each side of the map. Useful when map elements/markers are obscured.
*
* @platform iOS: Supported
* @platform Android: Supported
*/
mapPadding?: EdgePadding;
/**
* The map type to be displayed
*
* @default `standard`
* @platform iOS: hybrid | mutedStandard | sattelite | standard | terrain
* @platform Android: hybrid | none | sattelite | standard | terrain
*/
mapType?: MapType;
/**
* TODO: Add documentation
*
* @platform iOS: Apple Maps only
* @platform Android: Not supported
*/
maxDelta?: number;
/**
* Maximum zoom value for the map, must be between 0 and 20
*
* @default 20
* @platform iOS: Supported
* @platform Android: Supported
*/
maxZoomLevel?: number;
/**
* TODO: Add documentation
*
* @platform iOS: Apple Maps only
* @platform Android: Not supported
*/
minDelta?: number;
/**
* Minimum zoom value for the map, must be between 0 and 20
*
* @default 0
* @platform iOS: Supported
* @platform Android: Supported
*/
minZoomLevel?: number;
/**
* If `false` the map won't move to the marker when pressed.
*
* @default true
* @platform iOS: Not supported
* @platform Android: Supported
*/
moveOnMarkerPress?: boolean;
/**
* Callback that is called when a callout is tapped by the user.
*
* @platform iOS: Apple Maps only
* @platform Android: Supported
*/
onCalloutPress?: (event: CalloutPressEvent) => void;
/**
* Callback that is called when user double taps on the map.
*
* @platform iOS: Apple Maps only
* @platform Android: Supported
*/
onDoublePress?: (event: ClickEvent) => void;
/**
* Callback that is called when an indoor building is focused/unfocused
*
* @platform iOS: Google Maps only
* @platform Android: Supported
*/
onIndoorBuildingFocused?: (event: IndoorBuildingEvent) => void;
/**
* Callback that is called when a level on indoor building is activated
*
* @platform iOS: Google Maps only
* @platform Android: Supported
*/
onIndoorLevelActivated?: (event: IndoorLevelActivatedEvent) => void;
/**
* Callback that is called once the kml is fully loaded.
*
* @platform iOS: Google Maps only
* @platform Android: Supported
*/
onKmlReady?: (event: KmlMapEvent) => void;
/**
* Callback that is called when user makes a "long press" somewhere on the map.
*
* @platform iOS: Supported
* @platform Android: Supported
*/
onLongPress?: (event: LongPressEvent) => void;
/**
* Callback that is called when the map has finished rendering all tiles.
*
* @platform iOS: Google Maps only
* @platform Android: Supported
*/
onMapLoaded?: (event: NativeSyntheticEvent<{}>) => void;
/**
* Callback that is called once the map is ready.
*
* Event is optional, as the first onMapReady callback is intercepted
* on Android, and the event is not passed on.
*
* @platform iOS: Supported
* @platform Android: Supported
*/
onMapReady?: (event?: NativeSyntheticEvent<{}>) => void;
/**
* Callback that is called when a marker on the map becomes deselected.
* This will be called when the callout for that marker is about to be hidden.
*
* @platform iOS: Apple Maps only
* @platform Android: Not supported
*/
onMarkerDeselect?: (event: MarkerDeselectEvent) => void;
/**
* Callback called continuously as a marker is dragged
*
* @platform iOS: Apple Maps only
* @platform Android: Supported
*/
onMarkerDrag?: (event: MarkerDragEvent) => void;
/**
* Callback that is called when a drag on a marker finishes.
* This is usually the point you will want to setState on the marker's coordinate again
*
* @platform iOS: Apple Maps only
* @platform Android: Supported
*/
onMarkerDragEnd?: (event: MarkerDragStartEndEvent) => void;
/**
* Callback that is called when the user initiates a drag on a marker (if it is draggable)
*
* @platform iOS: Apple Maps only
* @platform Android: Supported
*/
onMarkerDragStart?: (event: MarkerDragStartEndEvent) => void;
/**
* Callback that is called when a marker on the map is tapped by the user.
*
* @platform iOS: Supported
* @platform Android: Supported
*/
onMarkerPress?: (event: MarkerPressEvent) => void;
/**
* Callback that is called when a marker on the map becomes selected.
* This will be called when the callout for that marker is about to be shown.
*
* @platform iOS: Apple Maps only.
* @platform Android: Not supported
*/
onMarkerSelect?: (event: MarkerSelectEvent) => void;
/**
* Callback that is called when user presses and drags the map.
* **NOTE**: for iOS `scrollEnabled` should be set to false to trigger the event
*
* @platform iOS: Supported
* @platform Android: Supported
*/
onPanDrag?: (event: PanDragEvent) => void;
/**
* Callback that is called when user click on a POI.
*
* @platform iOS: Google Maps only
* @platform Android: Supported
*/
onPoiClick?: (event: PoiClickEvent) => void;
/**
* Callback that is called when user taps on the map.
*
* @platform iOS: Supported
* @platform Android: Supported
*/
onPress?: (event: MapPressEvent) => void;
/**
* Callback that is called continuously when the region changes, such as when a user is dragging the map.
* `isGesture` property indicates if the move was from the user (true) or an animation (false).
* **Note**: `isGesture` is supported by Google Maps only.
*
* @platform iOS: Supported
* @platform Android: Supported
*/
onRegionChange?: (region: Region, details: Details) => void;
/**
* Callback that is called once when the region changes, such as when the user is done moving the map.
* `isGesture` property indicates if the move was from the user (true) or an animation (false).
* **Note**: `isGesture` is supported by Google Maps only.
*
* @platform iOS: Supported
* @platform Android: Supported
*/
onRegionChangeComplete?: (region: Region, details: Details) => void;
/**
* Callback that is called when the underlying map figures our users current location
* (coordinate also includes isFromMockProvider value for Android API 18 and above).
* Make sure **showsUserLocation** is set to *true*.
*
* @platform iOS: Supported
* @platform Android: Supported
*/
onUserLocationChange?: (event: UserLocationChangeEvent) => void;
/**
* Indicates how/when to affect padding with safe area insets
*
* @platform iOS: Google Maps only
* @platform Android: Not supported
*/
paddingAdjustmentBehavior?: "always" | "automatic" | "never";
/**
* If `false` the user won't be able to adjust the camera’s pitch angle.
*
* @default true
* @platform iOS: Google Maps only
* @platform Android: Supported
*/
pitchEnabled?: boolean;
/**
* The map framework to use.
* Either `"google"` for GoogleMaps, otherwise `undefined` to use the native map framework (`MapKit` in iOS and `GoogleMaps` in android).
*
* @platform iOS: Supported
* @platform Android: Supported
*/
provider?: Provider;
/**
* The region to be displayed by the map.
* The region is defined by the center coordinates and the span of coordinates to display.
*
* @platform iOS: Supported
* @platform Android: Supported
*/
region?: Region;
/**
* If `false` the user won't be able to adjust the camera’s pitch angle.
*
* @default true
* @platform iOS: Google Maps only
* @platform Android: Supported
*/
rotateEnabled?: boolean;
/**
* If `false` the map will stay centered while rotating or zooming.
*
* @default true
* @platform iOS: Google Maps only
* @platform Android: Supported
*/
scrollDuringRotateOrZoomEnabled?: boolean;
/**
* If `false` the user won't be able to change the map region being displayed.
*
* @default true
* @platform iOS: Supported
* @platform Android: Supported
*/
scrollEnabled?: boolean;
/**
* A Boolean indicating whether the map displays extruded building information.
*
* @default true
* @platform iOS: Not supported
* @platform Android: Supported
*/
showsBuildings?: boolean;
/**
* If `false` compass won't be displayed on the map.
*
* @default true
* @platform iOS: Supported
* @platform Android: Supported
*/
showsCompass?: boolean;
/**
* A Boolean indicating whether indoor level picker should be enabled.
*
* @default false
* @platform iOS: Google Maps only
* @platform Android: Supported
*/
showsIndoorLevelPicker?: boolean;
/**
* A Boolean indicating whether indoor maps should be enabled.
*
* @default true
* @platform iOS: Google Maps only
* @platform Android: Supported
*/
showsIndoors?: boolean;
/**
* If `false` hide the button to move map to the current user's location.
*
* @default true
* @platform iOS: Google Maps only
* @platform Android: Supported
*/
showsMyLocationButton?: boolean;
/**
* If `false` points of interest won't be displayed on the map.
* TODO: DEPRECATED? Doesn't seem to do anything
*
* @default true
* @platform iOS: Maybe Apple Maps?
* @platform Android: Not supported
*/
showsPointsOfInterest?: boolean;
/**
* A Boolean indicating whether the map shows scale information.
*
* @default true
* @platform iOS: Apple Maps only
* @platform Android: Not supported
*/
showsScale?: boolean;
/**
* A Boolean value indicating whether the map displays traffic information.
* TODO: Look into android support
*
* @default false
* @platform iOS: Supported
* @platform Android: Not supported?
*/
showsTraffic?: boolean;
/**
* If `true` the users location will be displayed on the map.
*
* This will cause iOS to ask for location permissions.
* For iOS see: [DOCS](https://github.com/react-native-maps/react-native-maps/blob/master/docs/installation.md#set-the-usage-description-property)
* @default false
* @platform iOS: Supported
* @platform Android: Supported
*/
showsUserLocation?: boolean;
/**
* Sets the tint color of the map. (Changes the color of the position indicator)
*
* @default System Blue
* @platform iOS: Apple Maps only
* @platform Android: Not supported
*/
tintColor?: string;
/**
* If `false` will hide 'Navigate' and 'Open in Maps' buttons on marker press
*
* @default true
* @platform iOS: Not supported
* @platform Android: Supported
*/
toolbarEnabled?: boolean;
/**
* Sets the map to the style selected.
*
* @default System setting
* @platform iOS: Apple Maps only (iOS >= 13.0)
* @platform Android: Not supported
*/
userInterfaceStyle?: "light" | "dark";
/**
* The title of the annotation for current user location.
*
* This only works if `showsUserLocation` is true.
*
* @default `My Location`
* @platform iOS: Apple Maps only
* @platform Android: Not supported
*/
userLocationAnnotationTitle?: string;
/**
* If `true` clicking user location will show the default callout for userLocation annotation.
*
* @default false
* @platform iOS: Apple Maps only
* @platform Android: Not supported
*/
userLocationCalloutEnabled?: boolean;
/**
* Fastest interval the application will actively acquire locations.
*
* See [Google APIs documentation](https://developers.google.com/android/reference/com/google/android/gms/location/LocationRequest.html)
*
* @default 5000
* @platform iOS: Not supported
* @platform Android: Supported
*/
userLocationFastestInterval?: number;
/**
* Set power priority of user location tracking.
*
* See [Google APIs documentation](https://developers.google.com/android/reference/com/google/android/gms/location/LocationRequest.html)
*
* @default `high`
* @platform iOS: Not supported
* @platform Android: Supported
*/
userLocationPriority?: "balanced" | "high" | "low" | "passive";
/**
* Interval of user location updates in milliseconds.
*
* See [Google APIs documentation](https://developers.google.com/android/reference/com/google/android/gms/location/LocationRequest.html)
*
* @default 5000
* @platform iOS: Not supported
* @platform Android: Supported
*/
userLocationUpdateInterval?: number;
/**
* If `false` the zoom control at the bottom right of the map won't be visible.
*
* @default true
* @platform iOS: Not supported
* @platform Android: Supported
*/
zoomControlEnabled?: boolean;
/**
* If `false` the user won't be able to pinch/zoom the map.
*
* TODO: Why is the Android reactprop defaultvalue set to false?
*
* @default true
* @platform iOS: Supported
* @platform Android: Supported
*/
zoomEnabled?: boolean;
/**
* If `false` the user won't be able to double tap to zoom the map.
* **Note:** But it will greatly decrease delay of tap gesture recognition.
*
* @default true
* @platform iOS: Google Maps only
* @platform Android: Not supported
*/
zoomTapEnabled?: boolean;
};
type ModifiedProps = Modify<
MapViewProps,
{
region?: MapViewProps["region"] | null;
initialRegion?: MapViewProps["initialRegion"] | null;
}
>;
export type NativeProps = Omit<
ModifiedProps,
"customMapStyle" | "onRegionChange" | "onRegionChangeComplete"
> & {
ref: React.RefObject<MapViewNativeComponentType>;
customMapStyleString?: string;
handlePanDrag?: boolean;
onChange?: (e: ChangeEvent) => void;
};
type State = {
isReady: boolean;
};
declare class MapView extends React.Component<MapViewProps, State> {
static Animated: Animated.AnimatedComponent<typeof MapView>;
private map;
constructor(props: MapViewProps);
/**
* @deprecated Will be removed in v2.0.0, as setNativeProps is not a thing in fabric.
* See https://reactnative.dev/docs/new-architecture-library-intro#migrating-off-setnativeprops
*/
setNativeProps(props: Partial<NativeProps>): void;
private _onMapReady;
private _onChange;
isMarkerWithinScreen(markers: string[]): void;
getCamera(): Promise<Camera>;
setCamera(camera: Partial<Camera>): void;
animateCamera(
camera: Partial<Camera>,
opts?: {
duration?: number;
},
): void;
animateToRegion(region: Region, duration?: number): void;
fitToElements(options?: FitToOptions): void;
fitToSuppliedMarkers(markers: string[], options?: FitToOptions): void;
fitToCoordinates(coordinates?: LatLng[], options?: FitToOptions): void;
/**
* Get visible boudaries
*
* @return Promise Promise with the bounding box ({ northEast: <LatLng>, southWest: <LatLng> })
*/
getMapBoundaries(): Promise<BoundingBox>;
setMapBoundaries(northEast: LatLng, southWest: LatLng): void;
setIndoorActiveLevelIndex(activeLevelIndex: number): void;
/**
* Takes a snapshot of the map and saves it to a picture
* file or returns the image as a base64 encoded string.
*
* @param args Configuration options
* @param [args.width] Width of the rendered map-view (when omitted actual view width is used).
* @param [args.height] Height of the rendered map-view (when omitted actual height is used).
* @param [args.region] Region to render (Only supported on iOS).
* @param [args.format] Encoding format ('png', 'jpg') (default: 'png').
* @param [args.quality] Compression quality (only used for jpg) (default: 1.0).
* @param [args.result] Result format ('file', 'base64') (default: 'file').
*
* @return Promise Promise with either the file-uri or base64 encoded string
*/
takeSnapshot(args: SnapshotOptions): Promise<string>;
/**
* Convert a coordinate to address by using default Geocoder
*
* @param coordinate Coordinate
* @param [coordinate.latitude] Latitude
* @param [coordinate.longitude] Longitude
*
* @return Promise with return type Address
*/
addressForCoordinate(coordinate: LatLng): Promise<Address>;
/**
* Convert a map coordinate to user-space point
*
* @param coordinate Coordinate
* @param [coordinate.latitude] Latitude
* @param [coordinate.longitude] Longitude
*
* @return Promise Promise with the point ({ x: Number, y: Number })
*/
pointForCoordinate(coordinate: LatLng): Promise<Point>;
/**
* Convert a user-space point to a map coordinate
*
* @param point Point
* @param [point.x] X
* @param [point.x] Y
*
* @return Promise Promise with the coordinate ({ latitude: Number, longitude: Number })
*/
coordinateForPoint(point: Point): Promise<LatLng>;
/**
* Get markers' centers and frames in user-space coordinates
*
* @param onlyVisible boolean true to include only visible markers, false to include all
*
* @return Promise Promise with { <identifier>: { point: Point, frame: Frame } }
*/
getMarkersFrames(onlyVisible?: boolean): Promise<{
[key: string]: {
point: Point;
frame: Frame;
};
}>;
/**
* Get bounding box from region
*
* @param region Region
*
* @return Object Object bounding box ({ northEast: <LatLng>, southWest: <LatLng> })
*/
boundingBoxForRegion(region: Region): BoundingBox;
private _mapManagerCommand;
private _getHandle;
private _runCommand;
render(): JSX.Element;
}
export declare const AnimatedMapView: RNAnimated.AnimatedComponent<
typeof MapView
>;
export declare const enableLatestRenderer: () => any;
export default MapView;
"use strict";
var __createBinding =
(this && this.__createBinding) ||
(Object.create
? function (o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (
!desc ||
("get" in desc ? !m.__esModule : desc.writable || desc.configurable)
) {
desc = {
enumerable: true,
get: function () {
return m[k];
},
};
}
Object.defineProperty(o, k2, desc);
}
: function (o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
});
var __setModuleDefault =
(this && this.__setModuleDefault) ||
(Object.create
? function (o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}
: function (o, v) {
o["default"] = v;
});
var __importStar =
(this && this.__importStar) ||
function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null)
for (var k in mod)
if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k))
__createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.enableLatestRenderer =
exports.AnimatedMapView =
exports.MAP_TYPES =
void 0;
const React = __importStar(require("react"));
const react_native_1 = require("react-native");
const decorateMapComponent_1 = require("./decorateMapComponent");
const ProviderConstants = __importStar(require("./ProviderConstants"));
const MapViewNativeComponent_1 = require("./MapViewNativeComponent");
exports.MAP_TYPES = {
STANDARD: "standard",
SATELLITE: "satellite",
HYBRID: "hybrid",
TERRAIN: "terrain",
NONE: "none",
MUTEDSTANDARD: "mutedStandard",
};
const GOOGLE_MAPS_ONLY_TYPES = [
exports.MAP_TYPES.TERRAIN,
exports.MAP_TYPES.NONE,
];
class MapView extends React.Component {
static Animated;
map;
constructor(props) {
super(props);
this.map = React.createRef();
this.state = {
isReady: react_native_1.Platform.OS === "ios",
};
this._onMapReady = this._onMapReady.bind(this);
this._onChange = this._onChange.bind(this);
}
/**
* @deprecated Will be removed in v2.0.0, as setNativeProps is not a thing in fabric.
* See https://reactnative.dev/docs/new-architecture-library-intro#migrating-off-setnativeprops
*/
setNativeProps(props) {
console.warn(
"setNativeProps is deprecated and will be removed in next major release",
);
// @ts-ignore
this.map.current?.setNativeProps(props);
}
_onMapReady() {
const { onMapReady } = this.props;
this.setState({ isReady: true }, () => {
if (onMapReady) {
onMapReady();
}
});
}
_onChange({ nativeEvent }) {
const isGesture = nativeEvent.isGesture;
const details = { isGesture };
if (nativeEvent.continuous) {
if (this.props.onRegionChange) {
this.props.onRegionChange(nativeEvent.region, details);
}
} else if (this.props.onRegionChangeComplete) {
this.props.onRegionChangeComplete(nativeEvent.region, details);
}
}
isMarkerWithinScreen(marker) {
if (react_native_1.Platform.OS === "android") {
return react_native_1.NativeModules.AirMapModule.isMarkerWithinScreen(
this._getHandle(),
marker.coordinate,
);
} else if (react_native_1.Platform.OS === "ios") {
return this._runCommand("isMarkerWithinScreen", [marker.coordinate]);
}
return Promise.reject(
"isMarkerWithinScreen not supported on this platform",
);
}
getCamera() {
if (react_native_1.Platform.OS === "android") {
return react_native_1.NativeModules.AirMapModule.getCamera(
this._getHandle(),
);
} else if (react_native_1.Platform.OS === "ios") {
return this._runCommand("getCamera", []);
}
return Promise.reject("getCamera not supported on this platform");
}
setCamera(camera) {
if (this.map.current) {
MapViewNativeComponent_1.Commands.setCamera(this.map.current, camera);
}
}
animateCamera(camera, opts) {
if (this.map.current) {
MapViewNativeComponent_1.Commands.animateCamera(
this.map.current,
camera,
opts?.duration ? opts.duration : 500,
);
}
}
animateToRegion(region, duration = 500) {
if (this.map.current) {
MapViewNativeComponent_1.Commands.animateToRegion(
this.map.current,
region,
duration,
);
}
}
fitToElements(options = {}) {
if (this.map.current) {
const {
edgePadding = { top: 0, right: 0, bottom: 0, left: 0 },
animated = true,
} = options;
MapViewNativeComponent_1.Commands.fitToElements(
this.map.current,
edgePadding,
animated,
);
}
}
fitToSuppliedMarkers(markers, options = {}) {
if (this.map.current) {
const {
edgePadding = { top: 0, right: 0, bottom: 0, left: 0 },
animated = true,
} = options;
MapViewNativeComponent_1.Commands.fitToSuppliedMarkers(
this.map.current,
markers,
edgePadding,
animated,
);
}
}
fitToCoordinates(coordinates = [], options = {}) {
if (this.map.current) {
const {
edgePadding = { top: 0, right: 0, bottom: 0, left: 0 },
animated = true,
} = options;
MapViewNativeComponent_1.Commands.fitToCoordinates(
this.map.current,
coordinates,
edgePadding,
animated,
);
}
}
/**
* Get visible boudaries
*
* @return Promise Promise with the bounding box ({ northEast: <LatLng>, southWest: <LatLng> })
*/
async getMapBoundaries() {
if (react_native_1.Platform.OS === "android") {
return await react_native_1.NativeModules.AirMapModule.getMapBoundaries(
this._getHandle(),
);
} else if (react_native_1.Platform.OS === "ios") {
return await this._runCommand("getMapBoundaries", []);
}
return Promise.reject("getMapBoundaries not supported on this platform");
}
setMapBoundaries(northEast, southWest) {
if (this.map.current) {
MapViewNativeComponent_1.Commands.setMapBoundaries(
this.map.current,
northEast,
southWest,
);
}
}
setIndoorActiveLevelIndex(activeLevelIndex) {
if (this.map.current) {
MapViewNativeComponent_1.Commands.setIndoorActiveLevelIndex(
this.map.current,
activeLevelIndex,
);
}
}
/**
* Takes a snapshot of the map and saves it to a picture
* file or returns the image as a base64 encoded string.
*
* @param args Configuration options
* @param [args.width] Width of the rendered map-view (when omitted actual view width is used).
* @param [args.height] Height of the rendered map-view (when omitted actual height is used).
* @param [args.region] Region to render (Only supported on iOS).
* @param [args.format] Encoding format ('png', 'jpg') (default: 'png').
* @param [args.quality] Compression quality (only used for jpg) (default: 1.0).
* @param [args.result] Result format ('file', 'base64') (default: 'file').
*
* @return Promise Promise with either the file-uri or base64 encoded string
*/
takeSnapshot(args) {
// Sanitize inputs
const config = {
width: args.width || 0,
height: args.height || 0,
region: args.region || {},
format: args.format || "png",
quality: args.quality || 1.0,
result: args.result || "file",
};
if (config.format !== "png" && config.format !== "jpg") {
throw new Error("Invalid format specified");
}
if (config.result !== "file" && config.result !== "base64") {
throw new Error("Invalid result specified");
}
// Call native function
if (react_native_1.Platform.OS === "android") {
return react_native_1.NativeModules.AirMapModule.takeSnapshot(
this._getHandle(),
config,
);
} else if (react_native_1.Platform.OS === "ios") {
return new Promise((resolve, reject) => {
this._runCommand("takeSnapshot", [
config.width,
config.height,
config.region,
config.format,
config.quality,
config.result,
(err, snapshot) => {
if (err) {
reject(err);
} else {
resolve(snapshot);
}
},
]);
});
}
return Promise.reject("takeSnapshot not supported on this platform");
}
/**
* Convert a coordinate to address by using default Geocoder
*
* @param coordinate Coordinate
* @param [coordinate.latitude] Latitude
* @param [coordinate.longitude] Longitude
*
* @return Promise with return type Address
*/
addressForCoordinate(coordinate) {
if (react_native_1.Platform.OS === "android") {
return react_native_1.NativeModules.AirMapModule.getAddressFromCoordinates(
this._getHandle(),
coordinate,
);
} else if (react_native_1.Platform.OS === "ios") {
return this._runCommand("getAddressFromCoordinates", [coordinate]);
}
return Promise.reject("getAddress not supported on this platform");
}
/**
* Convert a map coordinate to user-space point
*
* @param coordinate Coordinate
* @param [coordinate.latitude] Latitude
* @param [coordinate.longitude] Longitude
*
* @return Promise Promise with the point ({ x: Number, y: Number })
*/
pointForCoordinate(coordinate) {
if (react_native_1.Platform.OS === "android") {
return react_native_1.NativeModules.AirMapModule.pointForCoordinate(
this._getHandle(),
coordinate,
);
} else if (react_native_1.Platform.OS === "ios") {
return this._runCommand("pointForCoordinate", [coordinate]);
}
return Promise.reject("pointForCoordinate not supported on this platform");
}
/**
* Convert a user-space point to a map coordinate
*
* @param point Point
* @param [point.x] X
* @param [point.x] Y
*
* @return Promise Promise with the coordinate ({ latitude: Number, longitude: Number })
*/
coordinateForPoint(point) {
if (react_native_1.Platform.OS === "android") {
return react_native_1.NativeModules.AirMapModule.coordinateForPoint(
this._getHandle(),
point,
);
} else if (react_native_1.Platform.OS === "ios") {
return this._runCommand("coordinateForPoint", [point]);
}
return Promise.reject("coordinateForPoint not supported on this platform");
}
/**
* Get markers' centers and frames in user-space coordinates
*
* @param onlyVisible boolean true to include only visible markers, false to include all
*
* @return Promise Promise with { <identifier>: { point: Point, frame: Frame } }
*/
getMarkersFrames(onlyVisible = false) {
if (react_native_1.Platform.OS === "ios") {
return this._runCommand("getMarkersFrames", [onlyVisible]);
}
return Promise.reject("getMarkersFrames not supported on this platform");
}
/**
* Get bounding box from region
*
* @param region Region
*
* @return Object Object bounding box ({ northEast: <LatLng>, southWest: <LatLng> })
*/
boundingBoxForRegion(region) {
return {
northEast: {
latitude: region.latitude + region.latitudeDelta / 2,
longitude: region.longitude + region.longitudeDelta / 2,
},
southWest: {
latitude: region.latitude - region.latitudeDelta / 2,
longitude: region.longitude - region.longitudeDelta / 2,
},
};
}
_mapManagerCommand(name) {
return react_native_1.NativeModules[
`${(0, decorateMapComponent_1.getNativeMapName)(
this.props.provider,
)}Manager`
][name];
}
_getHandle() {
return (0, react_native_1.findNodeHandle)(this.map.current);
}
_runCommand(name, args) {
if (react_native_1.Platform.OS === "ios") {
return this._mapManagerCommand(name)(this._getHandle(), ...args);
} else {
return Promise.reject(
`Invalid platform was passed: ${react_native_1.Platform.OS}`,
);
}
}
render() {
let props;
if (this.state.isReady) {
props = {
region: null,
initialRegion: null,
onChange: this._onChange,
onMapReady: this._onMapReady,
ref: this.map,
customMapStyleString: this.props.customMapStyle
? JSON.stringify(this.props.customMapStyle)
: undefined,
...this.props,
};
if (
react_native_1.Platform.OS === "ios" &&
props.provider === ProviderConstants.PROVIDER_DEFAULT &&
props.mapType &&
GOOGLE_MAPS_ONLY_TYPES.includes(props.mapType)
) {
props.mapType = exports.MAP_TYPES.STANDARD;
}
if (props.onPanDrag) {
props.handlePanDrag = !!props.onPanDrag;
}
} else {
props = {
style: this.props.style,
region: null,
initialRegion: this.props.initialRegion || null,
initialCamera: this.props.initialCamera,
ref: this.map,
onChange: this._onChange,
onMapReady: this._onMapReady,
onLayout: this.props.onLayout,
customMapStyleString: this.props.customMapStyle
? JSON.stringify(this.props.customMapStyle)
: undefined,
};
}
if (react_native_1.Platform.OS === "android" && this.props.liteMode) {
return (
<decorateMapComponent_1.ProviderContext.Provider
value={this.props.provider}
>
<AIRMapLite {...props} />
</decorateMapComponent_1.ProviderContext.Provider>
);
}
const AIRMap = getNativeMapComponent(this.props.provider);
return (
<decorateMapComponent_1.ProviderContext.Provider
value={this.props.provider}
>
<AIRMap {...props} />
</decorateMapComponent_1.ProviderContext.Provider>
);
}
}
const airMaps = {
default: (0, react_native_1.requireNativeComponent)("AIRMap"),
google: () => null,
};
if (react_native_1.Platform.OS === "android") {
airMaps.google = airMaps.default;
} else {
airMaps.google = decorateMapComponent_1.googleMapIsInstalled
? (0, react_native_1.requireNativeComponent)("AIRGoogleMap")
: (0, decorateMapComponent_1.createNotSupportedComponent)(
"react-native-maps: AirGoogleMaps dir must be added to your xCode project to support GoogleMaps on iOS.",
);
}
const getNativeMapComponent = (provider) => airMaps[provider || "default"];
const AIRMapLite = react_native_1.UIManager.getViewManagerConfig("AIRMapLite")
? (0, react_native_1.requireNativeComponent)("AIRMapLite")
: () => null;
exports.AnimatedMapView =
react_native_1.Animated.createAnimatedComponent(MapView);
const enableLatestRenderer = () => {
if (react_native_1.Platform.OS !== "android") {
return;
}
return react_native_1.NativeModules.AirMapModule.enableLatestRenderer();
};
exports.enableLatestRenderer = enableLatestRenderer;
MapView.Animated = exports.AnimatedMapView;
exports.default = MapView;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment