Refactor offline functions with promises

This commit is contained in:
Marius Petcu
2016-07-02 00:29:56 +03:00
parent 4ae4d7295e
commit 2aa9aca898
5 changed files with 127 additions and 61 deletions
+23 -16
View File
@@ -325,6 +325,9 @@ There are 3 main methods for interacting with the offline API:
Before using them, don't forget to set an access token with `Mapbox.setAccessToken(accessToken)`
These methods return a promise, but they also accept a callback as the last
argument with the signature `(err, value) => {}`.
#### Creating a pack
```javascript
@@ -341,6 +344,10 @@ Mapbox.addOfflinePack({
minZoomLevel: 10, // required
maxZoomLevel: 13, // required
styleURL: Mapbox.mapStyles.emerald // required. Valid styleURL
}).then(() => {
// Called after the pack has been added successfully
}).catch(err => {
console.error(err); // Handle error
});
```
@@ -349,29 +356,29 @@ Mapbox.addOfflinePack({
To delete a pack, provide the `name` of the pack to delete.
```javascript
Mapbox.removeOfflinePack('test', (err, info)=> {
if (err) {
console.error(err.message);
return;
}
if (info) {
console.log('Deleted', info.deleted);
Mapbox.removeOfflinePack('test')
.then(info => {
if (info.deleted) {
console.log(`Deleted pack named ${info.deleted}`); // The pack has been deleted successfully
} else {
console.log('No packs to delete'); // There are no packs named 'test'
console.log('No packs to delete'); // There are no packs named 'test'
}
});
})
.catch(err => {
console.error(err); // Handle error
});
```
#### Querying progress
```javascript
Mapbox.getOfflinePacks((err, packs) => {
if (err) {
console.error(err.message);
return;
}
// packs is an array of progress objects
});
Mapbox.getOfflinePacks()
.then(packs => {
// packs is an array of progress objects
})
.catch(err => {
console.log(err); // Handle error
})
```
A progress object has the following shape:
@@ -13,6 +13,7 @@ import com.facebook.common.logging.FLog;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.JSApplicationIllegalArgumentException;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
@@ -108,6 +109,8 @@ public class ReactNativeMapboxGLModule extends ReactContextBaseJavaModule {
return constants;
}
// Access Token
@ReactMethod
public void setAccessToken(String accessToken) {
if (accessToken == null || accessToken.length() == 0 || accessToken.equals("your-mapbox.com-access-token")) {
@@ -123,8 +126,28 @@ public class ReactNativeMapboxGLModule extends ReactContextBaseJavaModule {
MapboxAccountManager.start(context, accessToken);
}
// Metrics
@ReactMethod
public void setMetricsEnabled(boolean value) {
MapboxEventManager.getMapboxEventManager().setTelemetryEnabled(value);
}
// Offline packs
@ReactMethod
public void getPacks(Promise promise) {
WritableArray result = Arguments.createArray();
promise.resolve(result);
}
@ReactMethod
public void addPackForRegion(ReadableMap options, Promise promise) {
promise.reject(new JSApplicationIllegalArgumentException("Mapbox.addOfflinePackForRegion not implemented on Android yet"));
}
@ReactMethod
public void removePack(String packName, Promise promise) {
promise.reject(new JSApplicationIllegalArgumentException("Mapbox.removeOfflinePack not implemented on Android yet"));
}
}
+40 -24
View File
@@ -190,8 +190,8 @@ class MapExample extends Component {
<Text onPress={() => this._map && this._map.setVisibleCoordinateBounds(40.712, -74.227, 40.774, -74.125, 100, 0, 0, 0)}>
Set visible bounds to 40.7, -74.2, 40.7, -74.1
</Text>
<Text onPress={() => this.setState({ userTrackingMode: Mapbox.userTrackingMode.follow })}>
Set userTrackingMode to follow
<Text onPress={() => this.setState({ userTrackingMode: Mapbox.userTrackingMode.followWithHeading })}>
Set userTrackingMode to followWithHeading
</Text>
<Text onPress={() => this._map && this._map.getCenterCoordinateZoomLevel((location)=> {
console.log(location);
@@ -208,31 +208,47 @@ class MapExample extends Component {
})}>
Get bounds
</Text>
<Text onPress={() => Mapbox.addOfflinePack({
name: 'test',
type: 'bbox',
bounds: [0, 0, 0, 0],
minZoomLevel: 0,
maxZoomLevel: 0,
metadata: { anyValue: 'you wish' },
styleURL: Mapbox.mapStyles.emerald
})}>
<Text onPress={() => {
Mapbox.addOfflinePack({
name: 'test',
type: 'bbox',
bounds: [0, 0, 0, 0],
minZoomLevel: 0,
maxZoomLevel: 0,
metadata: { anyValue: 'you wish' },
styleURL: Mapbox.mapStyles.emerald
}).then(() => {
console.log('Offline pack added');
}).catch(err => {
console.log(err);
});
}}>
Create offline pack
</Text>
<Text onPress={() => Mapbox.getOfflinePacks((err, packs)=> {
if (err) console.log(err);
console.log(packs);
})}>
<Text onPress={() => {
Mapbox.getOfflinePacks()
.then(packs => {
console.log(packs);
})
.catch(err => {
console.log(err);
});
}}>
Get offline packs
</Text>
<Text onPress={() => Mapbox.removeOfflinePack('test', (err, info)=> {
if (err) console.log(err);
if (info) {
console.log('Deleted', info.deleted);
} else {
console.log('No packs to delete');
}
})}>
<Text onPress={() => {
Mapbox.removeOfflinePack('test')
.then(info => {
if (info.deleted) {
console.log('Deleted', info.deleted);
} else {
console.log('No packs to delete');
}
})
.catch(err => {
console.log(err);
});
}}>
Remove pack with name 'test'
</Text>
<Text>User tracking mode is {this.state.userTrackingMode}</Text>
@@ -245,7 +261,7 @@ class MapExample extends Component {
rotateEnabled={true}
scrollEnabled={true}
zoomEnabled={true}
showsUserLocation={true}
showsUserLocation={false}
styleURL={Mapbox.mapStyles.emerald}
userTrackingMode={this.state.userTrackingMode}
annotations={this.state.annotations}
+21 -5
View File
@@ -70,16 +70,32 @@ function setAccessToken(token: string) {
}
// Offline
function addOfflinePack(options, callback = () => {}) {
MapboxGLManager.addPackForRegion(options, callback);
function bindCallbackToPromise(callback, promise) {
if (callback) {
promise.then(value => {
callback(null, value);
}).catch(err => {
callback(err);
})
}
}
function addOfflinePack(options, callback) {
const promise = MapboxGLManager.addPackForRegion(options);
bindCallbackToPromise(callback, promise);
return promise;
}
function getOfflinePacks(callback) {
MapboxGLManager.getPacks(callback);
const promise = MapboxGLManager.getPacks();
bindCallbackToPromise(callback, promise);
return promise;
}
function removeOfflinePack(packName, callback = () => {}) {
MapboxGLManager.removePack(packName, callback);
function removeOfflinePack(packName, callback) {
const promise = MapboxGLManager.removePack(packName);
bindCallbackToPromise(callback, promise);
return promise;
}
function addOfflinePackProgressListener(handler) {
+20 -16
View File
@@ -179,8 +179,8 @@ RCT_EXPORT_METHOD(setAccessToken:(nonnull NSString *)accessToken)
if ([_packRequests count]) {
NSArray * callbackArray = [self serializePacksArray:packs];
for (RCTResponseSenderBlock callback in _packRequests) {
callback(@[[NSNull null], callbackArray]);
for (RCTPromiseResolveBlock callback in _packRequests) {
callback(callbackArray);
}
[_packRequests removeAllObjects];
}
@@ -261,8 +261,10 @@ RCT_EXPORT_METHOD(setAccessToken:(nonnull NSString *)accessToken)
[_bridge.eventDispatcher sendAppEventWithName:@"MapboxOfflineError" body:event];
}
RCT_EXPORT_METHOD(addPackForRegion:(NSDictionary*)options
callback:(RCTResponseSenderBlock)callback)
RCT_REMAP_METHOD(addPackForRegion,
pack:(NSDictionary*)options
resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
{
if ([options objectForKey:@"name"] == nil) {
return RCTLogError(@"Name is required.");
@@ -302,10 +304,10 @@ RCT_EXPORT_METHOD(addPackForRegion:(NSDictionary*)options
[[MGLOfflineStorage sharedOfflineStorage] addPackForRegion:region withContext:context completionHandler:^(MGLOfflinePack *pack, NSError *error) {
if (error != nil) {
RCTLogError(@"Error: %@", error.localizedFailureReason);
reject(@"add_pack_failed", error.localizedFailureReason, error);
} else {
[pack resume];
callback(@[[NSNull null]]);
resolve([NSNull null]);
}
}];
});
@@ -328,7 +330,9 @@ RCT_EXPORT_METHOD(addPackForRegion:(NSDictionary*)options
return callbackArray;
}
RCT_EXPORT_METHOD(getPacks:(RCTResponseSenderBlock)callback)
RCT_REMAP_METHOD(getPacks,
resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
{
dispatch_async(dispatch_get_main_queue(), ^{
NSMutableArray* callbackArray = [NSMutableArray new];
@@ -336,15 +340,17 @@ RCT_EXPORT_METHOD(getPacks:(RCTResponseSenderBlock)callback)
MGLOfflinePack *packs = [MGLOfflineStorage sharedOfflineStorage].packs;
if (!packs) {
[_packRequests addObject:callback];
[_packRequests addObject:resolve];
} else {
callback(@[[NSNull null], [self serializePacksArray:packs]]);
resolve([self serializePacksArray:packs]);
}
});
}
RCT_EXPORT_METHOD(removePack:(NSString*)packName
callback:(RCTResponseSenderBlock)callback)
RCT_REMAP_METHOD(removePack,
name:(NSString*)packName
resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
{
dispatch_async(dispatch_get_main_queue(), ^{
MGLOfflinePack *packs = [MGLOfflineStorage sharedOfflineStorage].packs;
@@ -359,7 +365,7 @@ RCT_EXPORT_METHOD(removePack:(NSString*)packName
}
if (tempPack == nil) {
return callback(@[[NSNull null]]);
return resolve(@{});
}
NSDictionary *userInfo = [NSKeyedUnarchiver unarchiveObjectWithData:tempPack.context];
@@ -375,11 +381,9 @@ RCT_EXPORT_METHOD(removePack:(NSString*)packName
[_removedPacks removeObject:tempPack];
[[MGLOfflineStorage sharedOfflineStorage] removePack:tempPack withCompletionHandler:^(NSError * _Nullable error) {
if (error != nil) {
callback(@[@{ @"message": error.localizedFailureReason }]);
reject(@"remove_pack_failed", error.localizedFailureReason, error);
} else {
NSMutableDictionary *deletedObject = [NSMutableDictionary new];
[deletedObject setObject:userInfo[@"name"] forKey:@"deleted"];
callback(@[[NSNull null], deletedObject]);
resolve(@{ @"deleted": userInfo[@"name"] });
}
}];
});