Files
smart-city-digital-twin-mar…/smart-app-city/frontend/node_modules/react-native-maps/ios/AirGoogleMaps/AIRGoogleMapManager.mm
Eric FELIXINE e30ae8ed09 feat(smart-app): implement complete mobile app MVP
- App.tsx: full navigation (Auth stack + Main tabs with 5 screens)
- Auth: LoginScreen, RegisterScreen, ForgotPasswordScreen
- HomeScreen: dashboard with IoT metrics, weather widget, alerts, quick actions, sensors
- MapScreen: interactive map with layer toggles (6 layers)
- MarketplaceScreen: categories (6), products (5), search
- ChatScreen: AI chat with quick prompts (4), bot responses
- ProfileScreen: user info, stats, menu (9 items), logout
- AlertsScreen: alert list with severity, acknowledge
- SensorsScreen: sensor list with type filters (6 types), search
- ZonesScreen: zone cards with stats
- SettingsScreen: language picker (FR/EN/ES/DE), privacy, about
- Stores: iotStore (sensors, zones, alerts), notificationStore, uiStore + i18n
- Hooks: useSensors, useAlerts, useNotifications, useLocation
- Components: Card, Button, LoadingSpinner, ErrorBoundary, Header
- Services: iotService, notificationService (with axios API client)
- Utils: formatters (temp, AQI, noise, dates), validators (email, password, IBAN)
- Theme: colors.ts with full design system (Blue Ocean palette)
- Ditto: fixed MongoDB connection, new JWT secrets, official gateway image
2026-06-01 18:00:35 -04:00

544 lines
22 KiB
Plaintext

//
// 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 "AIRGoogleMapMarker.h"
#import "AIRGoogleMapCoordinate.h"
#import "RCTConvert+GMSMapViewType.h"
#import <MapKit/MapKit.h>
#import <QuartzCore/QuartzCore.h>
#if __has_include(<ReactNativeMaps/generated/RNMapsAirModuleDelegate.h>)
#import <ReactNativeMaps/generated/RNMapsAirModuleDelegate.h>
#else
#import "RNMapsAirModuleDelegate.h"
#endif
static NSString *const RCTMapViewKey = @"MapView";
@interface AIRGoogleMapManager() <GMSMapViewDelegate>
{
BOOL didCallOnMapReady;
}
@end
@implementation AIRGoogleMapManager
RCT_EXPORT_MODULE()
- (UIView *)view
{
if (self.initialProps){
if (self.initialProps[@"googleMapId"]){
_googleMapId = self.initialProps[@"googleMapId"];
}
if (self.initialProps[@"zoomTapEnabled"]){
_zoomTapEnabled = self.initialProps[@"zoomTapEnabled"];
}
if (self.initialProps[@"loadingBackgroundColor"]){
_backgroundColor = [RCTConvert UIColor:self.initialProps[@"loadingBackgroundColor"]];
}
if (self.initialProps[@"initialCamera"]){
_camera = [RCTConvert GMSCameraPositionWithDefaults:self.initialProps[@"initialCamera"] existingCamera:nil];
}
}
AIRGoogleMap *map = [[AIRGoogleMap alloc] initWithMapId:self.googleMapId initialCamera:self.camera backgroundColor:self.backgroundColor andZoomTapEnabled:self.zoomTapEnabled];
map.bridge = self.bridge;
map.delegate = self;
map.isAccessibilityElement = NO;
map.accessibilityElementsHidden = NO;
map.settings.consumesGesturesInView = NO;
if (self.customMapStyle != nil){
map.customMapStyleString = self.customMapStyle;
}
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(googleMapId, 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, RCTDirectEventBlock)
RCT_EXPORT_VIEW_PROPERTY(onMapLoaded, RCTDirectEventBlock)
RCT_EXPORT_VIEW_PROPERTY(onKmlReady, RCTDirectEventBlock)
RCT_EXPORT_VIEW_PROPERTY(onPress, RCTBubblingEventBlock)
RCT_EXPORT_VIEW_PROPERTY(onLongPress, RCTBubblingEventBlock)
RCT_EXPORT_VIEW_PROPERTY(onPanDrag, RCTDirectEventBlock)
RCT_EXPORT_VIEW_PROPERTY(onUserLocationChange, RCTDirectEventBlock)
RCT_EXPORT_VIEW_PROPERTY(onMarkerPress, RCTDirectEventBlock)
RCT_EXPORT_VIEW_PROPERTY(onMarkerSelect, RCTDirectEventBlock)
RCT_EXPORT_VIEW_PROPERTY(onMarkerDeselect, RCTDirectEventBlock)
RCT_EXPORT_VIEW_PROPERTY(onRegionChangeStart, 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_VIEW_PROPERTY(loadingBackgroundColor, UIColor)
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 cameraProp]];
[mapView setCameraProp: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 cameraProp]];
[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;
[mapView fitToElementsWithEdgePadding:edgePadding animated:animated];
}
}];
}
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;
[mapView fitToSuppliedMarkers:markers withEdgePadding:edgePadding animated:animated];
}
}];
}
RCT_EXPORT_METHOD(fitToCoordinates:(nonnull NSNumber *)reactTag
coordinates:(nonnull NSArray<AIRGoogleMapCoordinate *> *)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;
[mapView fitToCoordinates:coordinates withEdgePadding:edgePadding animated:animated];
}
}];
}
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:(RCTPromiseResolveBlock)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 {
NSMutableDictionary* config = [NSMutableDictionary new];
[view takeSnapshotWithConfig:config success:callback error:^(NSString *code, NSString *message, NSError *error) {
callback(@[error]);
}];
[config setObject:width forKey:@"width"];
[config setObject:height forKey:@"height"];
[config setObject:format forKey:@"format"];
[config setObject:quality forKey:@"quality"];
[config setObject:result forKey:@"result"];
[config setObject:filePath forKey:@"filePath"];
// TODO: currently we are ignoring width, height, region
AIRGoogleMap* mapView = (AIRGoogleMap *) view;
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 {
id<RNMapsAirModuleDelegate> mapView = (id<RNMapsAirModuleDelegate>) view;
resolve([mapView getPointForCoordinates:coord]);
}
}];
}
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 {
id<RNMapsAirModuleDelegate> mapView = (id<RNMapsAirModuleDelegate>) view;
resolve([view getCoordinatesForPoint:pt]);
}
}];
}
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 {
resolve([view getMapBoundaries]);
}
}];
}
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;
AIRGoogleMap *googleMapView = (AIRGoogleMap *)mapView;
[googleMapView willMove: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),
},
@"numberOfTouches": @(recognizer.numberOfTouches),
});
}
@end
#endif