mirror of
https://github.com/status-im/react-native-mapbox-gl.git
synced 2026-08-30 20:41:08 +00:00
Add ios offline support (#312)
* Add ios offline * updates * change getpacks name, add metadat field to pack * add get bounds method
This commit is contained in:
+31
-3
@@ -4,6 +4,15 @@ var React = require('react-native');
|
||||
var { NativeModules, requireNativeComponent } = React;
|
||||
|
||||
var MapMixins = {
|
||||
addPackForRegion(mapRef, options) {
|
||||
NativeModules.MapboxGLManager.addPackForRegion(React.findNodeHandle(this.refs[mapRef]), options);
|
||||
},
|
||||
getPacks(mapRef, callback) {
|
||||
NativeModules.MapboxGLManager.getPacks(React.findNodeHandle(this.refs[mapRef]), callback);
|
||||
},
|
||||
removePack(mapRef, packName, callback) {
|
||||
NativeModules.MapboxGLManager.removePack(React.findNodeHandle(this.refs[mapRef]), packName, callback);
|
||||
},
|
||||
setDirectionAnimated(mapRef, heading) {
|
||||
NativeModules.MapboxGLManager.setDirectionAnimated(React.findNodeHandle(this.refs[mapRef]), heading);
|
||||
},
|
||||
@@ -46,9 +55,13 @@ var MapMixins = {
|
||||
getDirection(mapRef, callback) {
|
||||
NativeModules.MapboxGLManager.getDirection(React.findNodeHandle(this.refs[mapRef]), callback);
|
||||
},
|
||||
getBounds(mapRef, callback) {
|
||||
NativeModules.MapboxGLManager.getBounds(React.findNodeHandle(this.refs[mapRef]), callback);
|
||||
},
|
||||
mapStyles: NativeModules.MapboxGLManager.mapStyles,
|
||||
userTrackingMode: NativeModules.MapboxGLManager.userTrackingMode,
|
||||
userLocationVerticalAlignment: NativeModules.MapboxGLManager.userLocationVerticalAlignment
|
||||
userLocationVerticalAlignment: NativeModules.MapboxGLManager.userLocationVerticalAlignment,
|
||||
unknownResourceCount: NativeModules.MapboxGLManager.unknownResourceCount
|
||||
};
|
||||
|
||||
var MapView = React.createClass({
|
||||
@@ -85,6 +98,15 @@ var MapView = React.createClass({
|
||||
_onLocateUserFailed(event: Event) {
|
||||
if (this.props.onLocateUserFailed) this.props.onLocateUserFailed(event.nativeEvent.src);
|
||||
},
|
||||
_onOfflineProgressDidChange(event: Event) {
|
||||
if (this.props.onOfflineProgressDidChange) this.props.onOfflineProgressDidChange(event.nativeEvent.src);
|
||||
},
|
||||
_onOfflineMaxAllowedMapboxTiles(event: Event) {
|
||||
if (this.props.onOfflineMaxAllowedMapboxTiles) this.props.onOfflineMaxAllowedMapboxTiles(event.nativeEvent.src);
|
||||
},
|
||||
_onOfflineDidRecieveError(event: Event) {
|
||||
if (this.props.onOfflineDidRecieveError) this.props.onOfflineDidRecieveError(event.nativeEvent.src);
|
||||
},
|
||||
propTypes: {
|
||||
showsUserLocation: React.PropTypes.bool,
|
||||
rotateEnabled: React.PropTypes.bool,
|
||||
@@ -138,7 +160,10 @@ var MapView = React.createClass({
|
||||
onLongPress: React.PropTypes.func,
|
||||
onTap: React.PropTypes.func,
|
||||
contentInset: React.PropTypes.array,
|
||||
userLocationVerticalAlignment: React.PropTypes.number
|
||||
userLocationVerticalAlignment: React.PropTypes.number,
|
||||
onOfflineProgressDidChange: React.PropTypes.func,
|
||||
onOfflineMaxAllowedMapboxTiles: React.PropTypes.func,
|
||||
onOfflineDidRecieveError: React.PropTypes.func
|
||||
},
|
||||
getDefaultProps() {
|
||||
return {
|
||||
@@ -172,7 +197,10 @@ var MapView = React.createClass({
|
||||
onTap={this._onTap}
|
||||
onFinishLoadingMap={this._onFinishLoadingMap}
|
||||
onStartLoadingMap={this._onStartLoadingMap}
|
||||
onLocateUserFailed={this._onLocateUserFailed} />
|
||||
onLocateUserFailed={this._onLocateUserFailed}
|
||||
onOfflineProgressDidChange={this._onOfflineProgressDidChange}
|
||||
onOfflineMaxAllowedMapboxTiles={this._onOfflineMaxAllowedMapboxTiles}
|
||||
onOfflineDidRecieveError={this._onOfflineDidRecieveError} />
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
+7
-3
@@ -39,9 +39,10 @@
|
||||
| `onLocateUserFailed` | `{message: message}` | Fired when there is an error getting the users location. Do not rely on the string that is returned for determining what kind of error it is. |
|
||||
| `getCenterCoordinateZoomLevel` | `mapViewRef`, `callback` | Gets the current center location and zoom level. Returns a single callback object. |
|
||||
| `getDirection` | `mapViewRef`, `callback` | Gets the current direction. Returns a single callback object. |
|
||||
|
||||
|
||||
|
||||
| `getBounds` | `mapViewRef`, `callback` | Gets the bounds of the current view. Returns array [latitudeSW, longitudeSW, latitudeNE, longitudeNE]. |
|
||||
| `onOfflineProgressDidChange` | `{countOfResourcesCompleted: 7, countOfResourcesExpected: 1284, name: "test", countOfBytesCompleted: 306543, maximumResourcesExpected: 1284}` | Event fired when the progress of an offline pack changes while downloading. |
|
||||
| `onOfflineMaxAllowedMapboxTiles` | `{maximumCount: number}` | Event fired when the maximum number of tiles has been hit. |
|
||||
| `onOfflineDidRecieveError` | `{error: error}` | Event fired when there is an error while downloading a pack. |
|
||||
|
||||
## Methods for Modifying the Map State
|
||||
|
||||
@@ -61,6 +62,9 @@ These methods require you to use `MapboxGLMap.Mixin` to access the methods. Each
|
||||
| `removeAllAnnotations` | `mapViewRef`| Removes all annotations from the map.
|
||||
| `setVisibleCoordinateBoundsAnimated` | `mapViewRef`, `latitude1`, `longitude1`, `latitude2`, `longitude2`, `padding top`, `padding right`, `padding bottom`, `padding left` | Changes the viewport to fit the given coordinate bounds and some additional padding on each side.
|
||||
| `setUserTrackingMode` | `mapViewRef`, `userTrackingMode` | Modifies the tracking mode. Valid args: `this.userTrackingMode.none`, `this.userTrackingMode.follow`, `this.userTrackingMode.followWithCourse`, `this.userTrackingMode.followWithHeading`
|
||||
| `addPackForRegion` | `mapRef` `{name, type, bounds, minZoomLevel, maxZoomLevel, style}` | Adds an offline region for a given bounding box. `name` is a string to represent an offline pack. `type` must be of type `bbox`. `bounds` is an array. `minZoomLevel` is an number representing the minimum zoom level of the offline pack. `maxZoomLevel` is an number representing the maximum zoom level of the offline pack. `style` is a style url to download. `metadata` is an object you can use metadata about the pack.
|
||||
| `getPacks` | `mapRef` `callback` | Returns a callback with an array of all offline packs on device. If the downloaded pack was not downloaded during the current session, the size will be 0.
|
||||
| `removePack` | `mapRef` `name-of-pack` `callback` | Removes a pack from the device. The name corresponds to the `name` of the pack used when calling `addPackForRegion`
|
||||
|
||||
## Styles
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
C5AF3B8C1C5A8C3D0003BF64 /* Mapbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C5AF3B8B1C5A8C3D0003BF64 /* Mapbox.framework */; };
|
||||
C5DBB3441AF2EF2B00E611A9 /* RCTMapboxGL.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C5DBB3431AF2EF2B00E611A9 /* RCTMapboxGL.h */; };
|
||||
C5DBB3461AF2EF2B00E611A9 /* RCTMapboxGL.m in Sources */ = {isa = PBXBuildFile; fileRef = C5DBB3451AF2EF2B00E611A9 /* RCTMapboxGL.m */; };
|
||||
C5DBB34C1AF2EF2B00E611A9 /* libRCTMapboxGL.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C5DBB3401AF2EF2B00E611A9 /* libRCTMapboxGL.a */; };
|
||||
@@ -38,7 +37,6 @@
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
C5AF3B8B1C5A8C3D0003BF64 /* Mapbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Mapbox.framework; sourceTree = "<group>"; };
|
||||
C5DBB3401AF2EF2B00E611A9 /* libRCTMapboxGL.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRCTMapboxGL.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
C5DBB3431AF2EF2B00E611A9 /* RCTMapboxGL.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RCTMapboxGL.h; sourceTree = "<group>"; };
|
||||
C5DBB3451AF2EF2B00E611A9 /* RCTMapboxGL.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RCTMapboxGL.m; sourceTree = "<group>"; };
|
||||
@@ -53,7 +51,6 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
C5AF3B8C1C5A8C3D0003BF64 /* Mapbox.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -71,7 +68,6 @@
|
||||
C5DBB3371AF2EF2B00E611A9 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C5AF3B8B1C5A8C3D0003BF64 /* Mapbox.framework */,
|
||||
C5DBB3421AF2EF2B00E611A9 /* RCTMapboxGL */,
|
||||
C5DBB34F1AF2EF2B00E611A9 /* RCTMapboxGLTests */,
|
||||
C5DBB3411AF2EF2B00E611A9 /* Products */,
|
||||
|
||||
@@ -37,12 +37,14 @@
|
||||
- (void)addAnnotation:(NSObject *)annotation;
|
||||
- (void)removeAnnotation:(NSString*)selectedIdentifier;
|
||||
- (void)removeAllAnnotations;
|
||||
- (MGLCoordinateBounds)visibleCoordinateBounds;
|
||||
- (void)setVisibleCoordinateBounds:(MGLCoordinateBounds)bounds edgePadding:(UIEdgeInsets)padding animated:(BOOL)animated;
|
||||
- (void)setAttributionButtonVisibility:(BOOL)isVisible;
|
||||
- (void)setLogoVisibility:(BOOL)isVisible;
|
||||
- (void)setCompassVisibility:(BOOL)isVisible;
|
||||
- (double)zoomLevel;
|
||||
- (double)direction;
|
||||
- (void) createOfflinePack:(MGLCoordinateBounds)bounds styleURL:(NSURL*)styleURL fromZoomLevel:(double)fromZoomLevel toZoomLevel:(double)toZoomLevel name:(NSString*)name type:(NSString*)type metadata:(NSDictionary*)metadata;
|
||||
- (CLLocationCoordinate2D)centerCoordinate;
|
||||
@property (nonatomic) MGLAnnotationVerticalAlignment userLocationVerticalAlignment;
|
||||
@property (nonatomic) UIEdgeInsets contentInset;
|
||||
|
||||
@@ -12,6 +12,10 @@
|
||||
#import "UIView+React.h"
|
||||
#import "RCTLog.h"
|
||||
|
||||
@interface RCTMapboxGL ()
|
||||
@property (nonatomic) MGLOfflinePack *pack;
|
||||
@end
|
||||
|
||||
@implementation RCTMapboxGL {
|
||||
/* Required to publish events */
|
||||
RCTEventDispatcher *_eventDispatcher;
|
||||
@@ -91,6 +95,7 @@ RCT_EXPORT_MODULE();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (void)createMap
|
||||
{
|
||||
[MGLAccountManager setAccessToken:_accessToken];
|
||||
@@ -104,12 +109,35 @@ RCT_EXPORT_MODULE();
|
||||
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap:)];
|
||||
singleTap.delegate = self;
|
||||
[_map addGestureRecognizer:singleTap];
|
||||
|
||||
// Setup offline pack notification handlers.
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(offlinePackProgressDidChange:) name:MGLOfflinePackProgressChangedNotification object:nil];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(offlinePackDidReceiveError:) name:MGLOfflinePackErrorNotification object:nil];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(offlinePackDidReceiveMaximumAllowedMapboxTiles:) name:MGLOfflinePackMaximumMapboxTilesReachedNotification object:nil];
|
||||
|
||||
[self updateMap];
|
||||
[self addSubview:_map];
|
||||
[self layoutSubviews];
|
||||
}
|
||||
|
||||
-(void)createOfflinePack:(MGLCoordinateBounds)bounds styleURL:(NSURL*)styleURL fromZoomLevel:(double)fromZoomLevel toZoomLevel:(double)toZoomLevel name:(NSString*)name type:(NSString*)type metadata:(NSDictionary *)metadata
|
||||
{
|
||||
|
||||
id <MGLOfflineRegion> region = [[MGLTilePyramidOfflineRegion alloc] initWithStyleURL:styleURL bounds:bounds fromZoomLevel:fromZoomLevel toZoomLevel:toZoomLevel];
|
||||
|
||||
NSMutableDictionary *userInfo = [metadata mutableCopy];
|
||||
userInfo[@"name"] = name;
|
||||
NSData *context = [NSKeyedArchiver archivedDataWithRootObject:userInfo];
|
||||
|
||||
[[MGLOfflineStorage sharedOfflineStorage] addPackForRegion:region withContext:context completionHandler:^(MGLOfflinePack *pack, NSError *error) {
|
||||
if (error != nil) {
|
||||
RCTLogError(@"Error: %@", error.localizedFailureReason);
|
||||
} else {
|
||||
[pack resume];
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
|
||||
{
|
||||
return YES;
|
||||
@@ -256,6 +284,11 @@ RCT_EXPORT_MODULE();
|
||||
[self updateMap];
|
||||
}
|
||||
|
||||
- (MGLCoordinateBounds) visibleCoordinateBounds
|
||||
{
|
||||
return [_map visibleCoordinateBounds];
|
||||
}
|
||||
|
||||
- (void)setUserTrackingMode:(int)userTrackingMode
|
||||
{
|
||||
if (userTrackingMode > 3 || userTrackingMode < 0) {
|
||||
@@ -502,6 +535,54 @@ RCT_EXPORT_MODULE();
|
||||
[_eventDispatcher sendInputEventWithName:@"onStartLoadingMap" body:event];
|
||||
}
|
||||
|
||||
- (void)offlinePackProgressDidChange:(NSNotification *)notification {
|
||||
|
||||
MGLOfflinePack *pack = notification.object;
|
||||
NSDictionary *userInfo = [NSKeyedUnarchiver unarchiveObjectWithData:pack.context];
|
||||
MGLOfflinePackProgress progress = pack.progress;
|
||||
|
||||
NSDictionary *event = @{ @"target": self.reactTag,
|
||||
@"src": @{
|
||||
@"name": userInfo[@"name"],
|
||||
@"countOfResourcesCompleted": @(progress.countOfResourcesCompleted),
|
||||
@"countOfResourcesExpected": @(progress.countOfResourcesExpected),
|
||||
@"countOfBytesCompleted": @(progress.countOfBytesCompleted),
|
||||
@"maximumResourcesExpected": @(progress.maximumResourcesExpected)
|
||||
}
|
||||
};
|
||||
|
||||
[_eventDispatcher sendInputEventWithName:@"onOfflineProgressDidChange" body:event];
|
||||
}
|
||||
|
||||
- (void)offlinePackDidReceiveMaximumAllowedMapboxTiles:(NSNotification *)notification {
|
||||
MGLOfflinePack *pack = notification.object;
|
||||
NSDictionary *userInfo = [NSKeyedUnarchiver unarchiveObjectWithData:pack.context];
|
||||
uint64_t maximumCount = [notification.userInfo[MGLOfflinePackMaximumCountUserInfoKey] unsignedLongLongValue];
|
||||
|
||||
NSDictionary *event = @{ @"target": self.reactTag,
|
||||
@"src": @{
|
||||
@"name": userInfo[@"name"],
|
||||
@"maxTiles": @(maximumCount)
|
||||
}
|
||||
};
|
||||
[_eventDispatcher sendInputEventWithName:@"onOfflineMaxAllowedMapboxTiles" body:event];
|
||||
}
|
||||
|
||||
- (void)offlinePackDidReceiveError:(NSNotification *)notification {
|
||||
MGLOfflinePack *pack = notification.object;
|
||||
NSDictionary *userInfo = [NSKeyedUnarchiver unarchiveObjectWithData:pack.context];
|
||||
NSError *error = notification.userInfo[MGLOfflinePackErrorUserInfoKey];
|
||||
|
||||
NSDictionary *event = @{ @"target": self.reactTag,
|
||||
@"src": @{
|
||||
@"name": userInfo[@"name"],
|
||||
@"error": [error localizedDescription]
|
||||
}
|
||||
};
|
||||
[_eventDispatcher sendInputEventWithName:@"onOfflineDidRecieveError" body:event];
|
||||
}
|
||||
|
||||
|
||||
- (void)mapView:(MGLMapView *)mapView didFailToLocateUserWithError:(NSError *)error
|
||||
{
|
||||
NSDictionary *event = @{ @"target": mapView.reactTag,
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
@implementation RCTMapboxGLManager
|
||||
|
||||
|
||||
RCT_EXPORT_MODULE();
|
||||
@synthesize bridge = _bridge;
|
||||
|
||||
@@ -43,7 +44,10 @@ RCT_EXPORT_MODULE();
|
||||
@"onLongPress",
|
||||
@"onFinishLoadingMap",
|
||||
@"onStartLoadingMap",
|
||||
@"onLocateUserFailed"
|
||||
@"onLocateUserFailed",
|
||||
@"onOfflineProgressDidChange",
|
||||
@"onOfflineMaxAllowedMapboxTiles",
|
||||
@"onOfflineDidRecieveError"
|
||||
];
|
||||
}
|
||||
|
||||
@@ -68,7 +72,8 @@ RCT_EXPORT_MODULE();
|
||||
@"top": @(MGLAnnotationVerticalAlignmentTop),
|
||||
@"center": @(MGLAnnotationVerticalAlignmentCenter),
|
||||
@"bottom": @(MGLAnnotationVerticalAlignmentBottom)
|
||||
}
|
||||
},
|
||||
@"unknownResourceCount": @(UINT64_MAX)
|
||||
};
|
||||
};
|
||||
|
||||
@@ -87,7 +92,7 @@ RCT_EXPORT_VIEW_PROPERTY(zoomLevel, double);
|
||||
RCT_EXPORT_VIEW_PROPERTY(userLocationVerticalAlignment, int);
|
||||
|
||||
RCT_EXPORT_METHOD(getCenterCoordinateZoomLevel:(nonnull NSNumber *)reactTag
|
||||
findEvents:(RCTResponseSenderBlock)callback)
|
||||
callback:(RCTResponseSenderBlock)callback)
|
||||
{
|
||||
[_bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, NSDictionary<NSNumber *, RCTMapboxGL *> *viewRegistry) {
|
||||
RCTMapboxGL *mapView = viewRegistry[reactTag];
|
||||
@@ -104,8 +109,25 @@ RCT_EXPORT_METHOD(getCenterCoordinateZoomLevel:(nonnull NSNumber *)reactTag
|
||||
}];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(getBounds:(nonnull NSNumber *)reactTag
|
||||
callback:(RCTResponseSenderBlock)callback)
|
||||
{
|
||||
[_bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, NSDictionary<NSNumber *, RCTMapboxGL *> *viewRegistry) {
|
||||
RCTMapboxGL *mapView = viewRegistry[reactTag];
|
||||
MGLCoordinateBounds bounds = [mapView visibleCoordinateBounds];
|
||||
NSMutableArray *callbackArray = [[NSMutableArray alloc] init];
|
||||
|
||||
[callbackArray addObject:@(bounds.sw.latitude)];
|
||||
[callbackArray addObject:@(bounds.sw.longitude)];
|
||||
[callbackArray addObject:@(bounds.ne.latitude)];
|
||||
[callbackArray addObject:@(bounds.ne.longitude)];
|
||||
|
||||
callback(@[callbackArray]);
|
||||
}];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(getDirection:(nonnull NSNumber *)reactTag
|
||||
findEvents:(RCTResponseSenderBlock)callback)
|
||||
callback:(RCTResponseSenderBlock)callback)
|
||||
{
|
||||
[_bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, NSDictionary<NSNumber *, RCTMapboxGL *> *viewRegistry) {
|
||||
RCTMapboxGL *mapView = viewRegistry[reactTag];
|
||||
@@ -165,6 +187,111 @@ RCT_CUSTOM_VIEW_PROPERTY(compassIsHidden, BOOL, RCTMapboxGL)
|
||||
[view setCompassVisibility:value ? true : false];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(addPackForRegion:(nonnull NSNumber *)reactTag
|
||||
options:(NSDictionary*)options)
|
||||
{
|
||||
|
||||
[_bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, NSDictionary<NSNumber *, RCTMapboxGL *> *viewRegistry) {
|
||||
RCTMapboxGL *mapView = viewRegistry[reactTag];
|
||||
if ([mapView isKindOfClass:[RCTMapboxGL class]]) {
|
||||
|
||||
if ([options objectForKey:@"name"] == nil) {
|
||||
return RCTLogError(@"Name is required.");
|
||||
}
|
||||
if ([options objectForKey:@"minZoomLevel"] == nil) {
|
||||
return RCTLogError(@"minZoomLevel is required.");
|
||||
}
|
||||
if ([options objectForKey:@"maxZoomLevel"] == nil) {
|
||||
return RCTLogError(@"maxZoomLevel is required.");
|
||||
}
|
||||
if ([options objectForKey:@"bounds"] == nil) {
|
||||
return RCTLogError(@"bounds is required.");
|
||||
}
|
||||
if ([options objectForKey:@"styleURL"] == nil) {
|
||||
return RCTLogError(@"styleURL is required.");
|
||||
}
|
||||
if ([options objectForKey:@"metadata"] == nil) {
|
||||
return RCTLogError(@"metadata is required.");
|
||||
}
|
||||
if (!([[options objectForKey:@"type"] isEqualToString:@"bbox"])) {
|
||||
return RCTLogError(@"Offline type %@ not supported. Only type `bbox` supported.", [options valueForKey:@"type"]);
|
||||
}
|
||||
|
||||
NSArray *b = [options valueForKey:@"bounds"];
|
||||
MGLCoordinateBounds bounds = MGLCoordinateBoundsMake(CLLocationCoordinate2DMake([b[0] floatValue], [b[1] floatValue]), CLLocationCoordinate2DMake([b[2] floatValue], [b[3] floatValue]));
|
||||
[mapView createOfflinePack:bounds styleURL:[NSURL URLWithString:[options valueForKey:@"styleURL"]] fromZoomLevel:[[options valueForKey:@"minZoomLevel"] floatValue] toZoomLevel:[[options valueForKey:@"maxZoomLevel"] floatValue] name:[options valueForKey:@"name"] type:[options valueForKey:@"type"] metadata:[options valueForKey:@"metadata"]];
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(getPacks:(nonnull NSNumber *)reactTag
|
||||
callback:(RCTResponseSenderBlock)callback)
|
||||
{
|
||||
[_bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, NSDictionary<NSNumber *, RCTMapboxGL *> *viewRegistry) {
|
||||
RCTMapboxGL *mapView = viewRegistry[reactTag];
|
||||
if ([mapView isKindOfClass:[RCTMapboxGL class]]) {
|
||||
RCTMapboxGL *mapView = viewRegistry[reactTag];
|
||||
NSMutableArray* callbackArray = [NSMutableArray new];
|
||||
|
||||
MGLOfflinePack *packs = [MGLOfflineStorage sharedOfflineStorage].packs;
|
||||
|
||||
for (MGLOfflinePack *pack in packs) {
|
||||
NSMutableDictionary *packDict = [NSMutableDictionary new];
|
||||
NSMutableDictionary *userInfo = [[NSKeyedUnarchiver unarchiveObjectWithData:pack.context] mutableCopy];
|
||||
[packDict setObject:userInfo[@"name"] forKey:@"name"];
|
||||
[userInfo removeObjectForKey:@"name"];
|
||||
[packDict setObject:userInfo forKey:@"metadata"];
|
||||
[packDict setObject:@(pack.progress.countOfBytesCompleted) forKey:@"countOfBytesCompleted"];
|
||||
[packDict setObject:@(pack.progress.countOfResourcesCompleted) forKey:@"countOfResourcesCompleted"];
|
||||
[callbackArray addObject:packDict];
|
||||
}
|
||||
|
||||
callback(@[[NSNull null], callbackArray]);
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(removePack:(nonnull NSNumber *)reactTag
|
||||
packName:(NSString*)packName
|
||||
callback:(RCTResponseSenderBlock)callback)
|
||||
{
|
||||
[_bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, NSDictionary<NSNumber *, RCTMapboxGL *> *viewRegistry) {
|
||||
RCTMapboxGL *mapView = viewRegistry[reactTag];
|
||||
if ([mapView isKindOfClass:[RCTMapboxGL class]]) {
|
||||
RCTMapboxGL *mapView = viewRegistry[reactTag];
|
||||
|
||||
MGLOfflinePack *packs = [MGLOfflineStorage sharedOfflineStorage].packs;
|
||||
MGLOfflinePack *tempPack;
|
||||
|
||||
for (MGLOfflinePack *pack in packs) {
|
||||
NSDictionary *userInfo = [NSKeyedUnarchiver unarchiveObjectWithData:pack.context];
|
||||
if (userInfo[@"name"] == packName) {
|
||||
tempPack = pack;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (tempPack == nil) {
|
||||
return callback(@[[NSNull null]]);
|
||||
}
|
||||
|
||||
NSDictionary *userInfo = [NSKeyedUnarchiver unarchiveObjectWithData:tempPack.context];
|
||||
|
||||
[[MGLOfflineStorage sharedOfflineStorage] removePack:tempPack withCompletionHandler:^(NSError * _Nullable error) {
|
||||
if (error != nil) {
|
||||
RCTLogError(@"Error: %@", error.localizedFailureReason);
|
||||
} else {
|
||||
NSMutableDictionary *deletedObject = [NSMutableDictionary new];
|
||||
[deletedObject setObject:userInfo[@"name"] forKey:@"deleted"];
|
||||
callback(@[[NSNull null], deletedObject]);
|
||||
}
|
||||
}];
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
|
||||
|
||||
RCT_EXPORT_METHOD(setZoomLevelAnimated:(nonnull NSNumber *)reactTag
|
||||
zoomLevel:(double)zoomLevel)
|
||||
{
|
||||
@@ -331,7 +458,7 @@ RCT_EXPORT_METHOD(addAnnotations:(nonnull NSNumber *)reactTag
|
||||
}];
|
||||
}
|
||||
|
||||
NSObject *convertToMGLAnnotation (NSObject *annotationObject)
|
||||
NSObject *convertToMGLAnnotation (NSDictionary *annotationObject)
|
||||
{
|
||||
if (![annotationObject valueForKey:@"type"]) {
|
||||
RCTLogError(@"type point, polyline or polygon required");
|
||||
|
||||
+39
-7
@@ -7,7 +7,7 @@ var {
|
||||
AppRegistry,
|
||||
StyleSheet,
|
||||
Text,
|
||||
StatusBarIOS,
|
||||
StatusBar,
|
||||
View
|
||||
} = React;
|
||||
|
||||
@@ -85,8 +85,11 @@ var MapExample = React.createClass({
|
||||
onTap(location) {
|
||||
console.log('tapped', location);
|
||||
},
|
||||
render: function() {
|
||||
StatusBarIOS.setHidden(true);
|
||||
onOfflineProgressDidChange(progress) {
|
||||
console.log(progress);
|
||||
},
|
||||
render() {
|
||||
StatusBar.setHidden(true);
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Text onPress={() => this.setDirectionAnimated(mapRef, 0)}>
|
||||
@@ -145,18 +148,47 @@ var MapExample = React.createClass({
|
||||
<Text onPress={() => this.setUserTrackingMode(mapRef, this.userTrackingMode.follow)}>
|
||||
Set userTrackingMode to follow
|
||||
</Text>
|
||||
<Text onPress={() => this.getCenterCoordinateZoomLevel(mapRef, (err, location)=> {
|
||||
if (err) console.log(err);
|
||||
<Text onPress={() => this.getCenterCoordinateZoomLevel(mapRef, (location)=> {
|
||||
console.log(location);
|
||||
})}>
|
||||
Get location
|
||||
</Text>
|
||||
<Text onPress={() => this.getDirection(mapRef, (err, direction)=> {
|
||||
if (err) console.log(err);
|
||||
<Text onPress={() => this.getDirection(mapRef, (direction)=> {
|
||||
console.log(direction);
|
||||
})}>
|
||||
Get direction
|
||||
</Text>
|
||||
<Text onPress={() => this.getBounds(mapRef, (bounds)=> {
|
||||
console.log(bounds);
|
||||
})}>
|
||||
Get bounds
|
||||
</Text>
|
||||
<Text onPress={() => this.addPackForRegion(mapRef, {
|
||||
name: 'test',
|
||||
type: 'bbox',
|
||||
bounds: [0, 0, 0, 0],
|
||||
minZoomLevel: 0,
|
||||
maxZoomLevel: 0,
|
||||
styleURL: this.mapStyles.emerald
|
||||
})}>
|
||||
Create offline pack
|
||||
</Text>
|
||||
<Text onPress={() => this.getPacks(mapRef, (err, packs)=> {
|
||||
if (err) console.log(err);
|
||||
console.log(packs);
|
||||
})}>
|
||||
Get offline packs
|
||||
</Text>
|
||||
<Text onPress={() => this.removePack(mapRef, 'test', (err, info)=> {
|
||||
if (err) console.log(err);
|
||||
if (info) {
|
||||
console.log('Deleted', info.deleted);
|
||||
} else {
|
||||
console.log('No packs to delete');
|
||||
}
|
||||
})}>
|
||||
Remove pack with name 'test'
|
||||
</Text>
|
||||
<Mapbox
|
||||
style={styles.container}
|
||||
direction={0}
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@
|
||||
"url": "https://github.com/mapbox/react-native-mapbox-gl"
|
||||
},
|
||||
"scripts": {
|
||||
"preinstall": "./scripts/download-mapbox-gl-native-ios.sh 3.1.1",
|
||||
"preinstall": "./scripts/download-mapbox-gl-native-ios.sh 3.2.0",
|
||||
"test": "npm run lint",
|
||||
"lint": "eslint --no-eslintrc -c .eslintrc index.ios.js index.android.js ios/example.js android/example.js"
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user